From 39ffced97d1822c957123efbcb607254c8d01606 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 10 Mar 2022 19:45:28 +0100 Subject: [PATCH] srodowisko --- .idea/.gitignore | 8 + .idea/AI_wozek_widlowy.iml | 10 + .../inspectionProfiles/profiles_settings.xml | 6 + .idea/misc.xml | 4 + .idea/modules.xml | 8 + resources/track.png | Bin 0 -> 2684 bytes resources/truck.jpeg | Bin 0 -> 2682 bytes resources/truck.jpg | Bin 0 -> 3560 bytes run.py | 109 + venv/Include/site/python3.9/pygame/_camera.h | 26 + venv/Include/site/python3.9/pygame/_pygame.h | 326 + venv/Include/site/python3.9/pygame/_surface.h | 30 + venv/Include/site/python3.9/pygame/camera.h | 252 + venv/Include/site/python3.9/pygame/font.h | 15 + venv/Include/site/python3.9/pygame/freetype.h | 114 + .../site/python3.9/pygame/include/_pygame.h | 497 + .../site/python3.9/pygame/include/bitmask.h | 171 + .../site/python3.9/pygame/include/pgcompat.h | 108 + .../site/python3.9/pygame/include/pgimport.h | 80 + .../python3.9/pygame/include/pgplatform.h | 92 + .../site/python3.9/pygame/include/pygame.h | 34 + .../pygame/include/pygame_bufferproxy.h | 56 + .../python3.9/pygame/include/pygame_font.h | 50 + .../pygame/include/pygame_freetype.h | 42 + .../python3.9/pygame/include/pygame_mask.h | 45 + .../python3.9/pygame/include/pygame_mixer.h | 71 + .../site/python3.9/pygame/include/sse2neon.h | 6203 +++++++++ venv/Include/site/python3.9/pygame/mask.h | 7 + venv/Include/site/python3.9/pygame/mixer.h | 14 + venv/Include/site/python3.9/pygame/palette.h | 123 + .../site/python3.9/pygame/pgarrinter.h | 26 + .../site/python3.9/pygame/pgbufferproxy.h | 7 + venv/Include/site/python3.9/pygame/pgcompat.h | 57 + venv/Include/site/python3.9/pygame/pgopengl.h | 20 + .../site/python3.9/pygame/pgplatform.h | 39 + venv/Include/site/python3.9/pygame/pygame.h | 32 + venv/Include/site/python3.9/pygame/scrap.h | 147 + venv/Include/site/python3.9/pygame/surface.h | 355 + .../site-packages/_distutils_hack/__init__.py | 187 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 6890 bytes .../__pycache__/override.cpython-39.pyc | Bin 0 -> 231 bytes .../site-packages/_distutils_hack/override.py | 1 + .../site-packages/distutils-precedence.pth | 1 + .../pip-22.0.4.dist-info/INSTALLER | 1 + .../pip-22.0.4.dist-info/LICENSE.txt | 20 + .../pip-22.0.4.dist-info/METADATA | 92 + .../site-packages/pip-22.0.4.dist-info/RECORD | 1052 ++ .../site-packages/pip-22.0.4.dist-info/WHEEL | 5 + .../pip-22.0.4.dist-info/entry_points.txt | 5 + .../pip-22.0.4.dist-info/top_level.txt | 1 + venv/Lib/site-packages/pip/__init__.py | 13 + venv/Lib/site-packages/pip/__main__.py | 31 + .../pip/__pycache__/__init__.cpython-39.pyc | Bin 0 -> 624 bytes .../pip/__pycache__/__main__.cpython-39.pyc | Bin 0 -> 580 bytes .../site-packages/pip/_internal/__init__.py | 19 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 745 bytes .../__pycache__/build_env.cpython-39.pyc | Bin 0 -> 9498 bytes .../__pycache__/cache.cpython-39.pyc | Bin 0 -> 8302 bytes .../__pycache__/configuration.cpython-39.pyc | Bin 0 -> 11150 bytes .../__pycache__/exceptions.cpython-39.pyc | Bin 0 -> 23347 bytes .../_internal/__pycache__/main.cpython-39.pyc | Bin 0 -> 610 bytes .../__pycache__/pyproject.cpython-39.pyc | Bin 0 -> 3535 bytes .../self_outdated_check.cpython-39.pyc | Bin 0 -> 4575 bytes .../__pycache__/wheel_builder.cpython-39.pyc | Bin 0 -> 9154 bytes .../site-packages/pip/_internal/build_env.py | 296 + venv/Lib/site-packages/pip/_internal/cache.py | 264 + .../pip/_internal/cli/__init__.py | 4 + .../cli/__pycache__/__init__.cpython-39.pyc | Bin 0 -> 265 bytes .../__pycache__/autocompletion.cpython-39.pyc | Bin 0 -> 5248 bytes .../__pycache__/base_command.cpython-39.pyc | Bin 0 -> 6367 bytes .../cli/__pycache__/cmdoptions.cpython-39.pyc | Bin 0 -> 22691 bytes .../command_context.cpython-39.pyc | Bin 0 -> 1280 bytes .../cli/__pycache__/main.cpython-39.pyc | Bin 0 -> 1355 bytes .../__pycache__/main_parser.cpython-39.pyc | Bin 0 -> 2152 bytes .../cli/__pycache__/parser.cpython-39.pyc | Bin 0 -> 9936 bytes .../__pycache__/progress_bars.cpython-39.pyc | Bin 0 -> 9225 bytes .../__pycache__/req_command.cpython-39.pyc | Bin 0 -> 13434 bytes .../cli/__pycache__/spinners.cpython-39.pyc | Bin 0 -> 4935 bytes .../__pycache__/status_codes.cpython-39.pyc | Bin 0 -> 344 bytes .../pip/_internal/cli/autocompletion.py | 171 + .../pip/_internal/cli/base_command.py | 223 + .../pip/_internal/cli/cmdoptions.py | 1018 ++ .../pip/_internal/cli/command_context.py | 27 + .../site-packages/pip/_internal/cli/main.py | 70 + .../pip/_internal/cli/main_parser.py | 87 + .../site-packages/pip/_internal/cli/parser.py | 292 + .../pip/_internal/cli/progress_bars.py | 321 + .../pip/_internal/cli/req_command.py | 506 + .../pip/_internal/cli/spinners.py | 157 + .../pip/_internal/cli/status_codes.py | 6 + .../pip/_internal/commands/__init__.py | 127 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 3042 bytes .../commands/__pycache__/cache.cpython-39.pyc | Bin 0 -> 6169 bytes .../commands/__pycache__/check.cpython-39.pyc | Bin 0 -> 1558 bytes .../__pycache__/completion.cpython-39.pyc | Bin 0 -> 3131 bytes .../__pycache__/configuration.cpython-39.pyc | Bin 0 -> 8312 bytes .../commands/__pycache__/debug.cpython-39.pyc | Bin 0 -> 6647 bytes .../__pycache__/download.cpython-39.pyc | Bin 0 -> 3975 bytes .../__pycache__/freeze.cpython-39.pyc | Bin 0 -> 2628 bytes .../commands/__pycache__/hash.cpython-39.pyc | Bin 0 -> 2124 bytes .../commands/__pycache__/help.cpython-39.pyc | Bin 0 -> 1296 bytes .../commands/__pycache__/index.cpython-39.pyc | Bin 0 -> 4586 bytes .../__pycache__/install.cpython-39.pyc | Bin 0 -> 17687 bytes .../commands/__pycache__/list.cpython-39.pyc | Bin 0 -> 10146 bytes .../__pycache__/search.cpython-39.pyc | Bin 0 -> 5314 bytes .../commands/__pycache__/show.cpython-39.pyc | Bin 0 -> 6084 bytes .../__pycache__/uninstall.cpython-39.pyc | Bin 0 -> 3092 bytes .../commands/__pycache__/wheel.cpython-39.pyc | Bin 0 -> 4842 bytes .../pip/_internal/commands/cache.py | 223 + .../pip/_internal/commands/check.py | 53 + .../pip/_internal/commands/completion.py | 96 + .../pip/_internal/commands/configuration.py | 266 + .../pip/_internal/commands/debug.py | 202 + .../pip/_internal/commands/download.py | 140 + .../pip/_internal/commands/freeze.py | 97 + .../pip/_internal/commands/hash.py | 59 + .../pip/_internal/commands/help.py | 41 + .../pip/_internal/commands/index.py | 139 + .../pip/_internal/commands/install.py | 771 ++ .../pip/_internal/commands/list.py | 361 + .../pip/_internal/commands/search.py | 174 + .../pip/_internal/commands/show.py | 178 + .../pip/_internal/commands/uninstall.py | 105 + .../pip/_internal/commands/wheel.py | 178 + .../pip/_internal/configuration.py | 366 + .../pip/_internal/distributions/__init__.py | 21 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 788 bytes .../__pycache__/base.cpython-39.pyc | Bin 0 -> 1863 bytes .../__pycache__/installed.cpython-39.pyc | Bin 0 -> 1221 bytes .../__pycache__/sdist.cpython-39.pyc | Bin 0 -> 4544 bytes .../__pycache__/wheel.cpython-39.pyc | Bin 0 -> 1588 bytes .../pip/_internal/distributions/base.py | 36 + .../pip/_internal/distributions/installed.py | 20 + .../pip/_internal/distributions/sdist.py | 127 + .../pip/_internal/distributions/wheel.py | 31 + .../site-packages/pip/_internal/exceptions.py | 658 + .../pip/_internal/index/__init__.py | 2 + .../index/__pycache__/__init__.cpython-39.pyc | Bin 0 -> 219 bytes .../__pycache__/collector.cpython-39.pyc | Bin 0 -> 18024 bytes .../__pycache__/package_finder.cpython-39.pyc | Bin 0 -> 28074 bytes .../index/__pycache__/sources.cpython-39.pyc | Bin 0 -> 7184 bytes .../pip/_internal/index/collector.py | 610 + .../pip/_internal/index/package_finder.py | 1004 ++ .../pip/_internal/index/sources.py | 224 + .../pip/_internal/locations/__init__.py | 520 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 12507 bytes .../__pycache__/_distutils.cpython-39.pyc | Bin 0 -> 4658 bytes .../__pycache__/_sysconfig.cpython-39.pyc | Bin 0 -> 6249 bytes .../locations/__pycache__/base.cpython-39.pyc | Bin 0 -> 1527 bytes .../pip/_internal/locations/_distutils.py | 169 + .../pip/_internal/locations/_sysconfig.py | 219 + .../pip/_internal/locations/base.py | 52 + venv/Lib/site-packages/pip/_internal/main.py | 12 + .../pip/_internal/metadata/__init__.py | 62 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 2322 bytes .../metadata/__pycache__/base.cpython-39.pyc | Bin 0 -> 21114 bytes .../__pycache__/pkg_resources.cpython-39.pyc | Bin 0 -> 9920 bytes .../pip/_internal/metadata/base.py | 546 + .../pip/_internal/metadata/pkg_resources.py | 256 + .../pip/_internal/models/__init__.py | 2 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 253 bytes .../__pycache__/candidate.cpython-39.pyc | Bin 0 -> 1436 bytes .../__pycache__/direct_url.cpython-39.pyc | Bin 0 -> 7226 bytes .../__pycache__/format_control.cpython-39.pyc | Bin 0 -> 2707 bytes .../models/__pycache__/index.cpython-39.pyc | Bin 0 -> 1223 bytes .../models/__pycache__/link.cpython-39.pyc | Bin 0 -> 10247 bytes .../models/__pycache__/scheme.cpython-39.pyc | Bin 0 -> 999 bytes .../__pycache__/search_scope.cpython-39.pyc | Bin 0 -> 3468 bytes .../selection_prefs.cpython-39.pyc | Bin 0 -> 1655 bytes .../__pycache__/target_python.cpython-39.pyc | Bin 0 -> 3401 bytes .../models/__pycache__/wheel.cpython-39.pyc | Bin 0 -> 4325 bytes .../pip/_internal/models/candidate.py | 34 + .../pip/_internal/models/direct_url.py | 220 + .../pip/_internal/models/format_control.py | 80 + .../pip/_internal/models/index.py | 28 + .../pip/_internal/models/link.py | 288 + .../pip/_internal/models/scheme.py | 31 + .../pip/_internal/models/search_scope.py | 129 + .../pip/_internal/models/selection_prefs.py | 51 + .../pip/_internal/models/target_python.py | 110 + .../pip/_internal/models/wheel.py | 89 + .../pip/_internal/network/__init__.py | 2 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 241 bytes .../network/__pycache__/auth.cpython-39.pyc | Bin 0 -> 7473 bytes .../network/__pycache__/cache.cpython-39.pyc | Bin 0 -> 2913 bytes .../__pycache__/download.cpython-39.pyc | Bin 0 -> 5505 bytes .../__pycache__/lazy_wheel.cpython-39.pyc | Bin 0 -> 8373 bytes .../__pycache__/session.cpython-39.pyc | Bin 0 -> 10743 bytes .../network/__pycache__/utils.cpython-39.pyc | Bin 0 -> 1419 bytes .../network/__pycache__/xmlrpc.cpython-39.pyc | Bin 0 -> 2040 bytes .../pip/_internal/network/auth.py | 323 + .../pip/_internal/network/cache.py | 69 + .../pip/_internal/network/download.py | 185 + .../pip/_internal/network/lazy_wheel.py | 210 + .../pip/_internal/network/session.py | 454 + .../pip/_internal/network/utils.py | 96 + .../pip/_internal/network/xmlrpc.py | 60 + .../pip/_internal/operations/__init__.py | 0 .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 189 bytes .../__pycache__/check.cpython-39.pyc | Bin 0 -> 3993 bytes .../__pycache__/freeze.cpython-39.pyc | Bin 0 -> 6135 bytes .../__pycache__/prepare.cpython-39.pyc | Bin 0 -> 14751 bytes .../_internal/operations/build/__init__.py | 0 .../build/__pycache__/__init__.cpython-39.pyc | Bin 0 -> 195 bytes .../build/__pycache__/metadata.cpython-39.pyc | Bin 0 -> 1406 bytes .../metadata_editable.cpython-39.pyc | Bin 0 -> 1440 bytes .../metadata_legacy.cpython-39.pyc | Bin 0 -> 2316 bytes .../build/__pycache__/wheel.cpython-39.pyc | Bin 0 -> 1190 bytes .../__pycache__/wheel_editable.cpython-39.pyc | Bin 0 -> 1406 bytes .../__pycache__/wheel_legacy.cpython-39.pyc | Bin 0 -> 2713 bytes .../_internal/operations/build/metadata.py | 39 + .../operations/build/metadata_editable.py | 41 + .../operations/build/metadata_legacy.py | 74 + .../pip/_internal/operations/build/wheel.py | 37 + .../operations/build/wheel_editable.py | 46 + .../operations/build/wheel_legacy.py | 102 + .../pip/_internal/operations/check.py | 149 + .../pip/_internal/operations/freeze.py | 254 + .../_internal/operations/install/__init__.py | 2 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 253 bytes .../editable_legacy.cpython-39.pyc | Bin 0 -> 1474 bytes .../install/__pycache__/legacy.cpython-39.pyc | Bin 0 -> 3273 bytes .../install/__pycache__/wheel.cpython-39.pyc | Bin 0 -> 20955 bytes .../operations/install/editable_legacy.py | 47 + .../_internal/operations/install/legacy.py | 120 + .../pip/_internal/operations/install/wheel.py | 738 ++ .../pip/_internal/operations/prepare.py | 642 + .../site-packages/pip/_internal/pyproject.py | 168 + .../pip/_internal/req/__init__.py | 94 + .../req/__pycache__/__init__.cpython-39.pyc | Bin 0 -> 2548 bytes .../__pycache__/constructors.cpython-39.pyc | Bin 0 -> 12093 bytes .../req/__pycache__/req_file.cpython-39.pyc | Bin 0 -> 13366 bytes .../__pycache__/req_install.cpython-39.pyc | Bin 0 -> 22109 bytes .../req/__pycache__/req_set.cpython-39.pyc | Bin 0 -> 5886 bytes .../__pycache__/req_tracker.cpython-39.pyc | Bin 0 -> 4246 bytes .../__pycache__/req_uninstall.cpython-39.pyc | Bin 0 -> 18827 bytes .../pip/_internal/req/constructors.py | 490 + .../pip/_internal/req/req_file.py | 536 + .../pip/_internal/req/req_install.py | 858 ++ .../pip/_internal/req/req_set.py | 189 + .../pip/_internal/req/req_tracker.py | 124 + .../pip/_internal/req/req_uninstall.py | 633 + .../pip/_internal/resolution/__init__.py | 0 .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 189 bytes .../__pycache__/base.cpython-39.pyc | Bin 0 -> 1046 bytes .../pip/_internal/resolution/base.py | 20 + .../_internal/resolution/legacy/__init__.py | 0 .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 196 bytes .../__pycache__/resolver.cpython-39.pyc | Bin 0 -> 12184 bytes .../_internal/resolution/legacy/resolver.py | 467 + .../resolution/resolvelib/__init__.py | 0 .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 200 bytes .../__pycache__/base.cpython-39.pyc | Bin 0 -> 6597 bytes .../__pycache__/candidates.cpython-39.pyc | Bin 0 -> 18520 bytes .../__pycache__/factory.cpython-39.pyc | Bin 0 -> 19088 bytes .../found_candidates.cpython-39.pyc | Bin 0 -> 4831 bytes .../__pycache__/provider.cpython-39.pyc | Bin 0 -> 7626 bytes .../__pycache__/reporter.cpython-39.pyc | Bin 0 -> 3261 bytes .../__pycache__/requirements.cpython-39.pyc | Bin 0 -> 7570 bytes .../__pycache__/resolver.cpython-39.pyc | Bin 0 -> 8169 bytes .../_internal/resolution/resolvelib/base.py | 141 + .../resolution/resolvelib/candidates.py | 547 + .../resolution/resolvelib/factory.py | 739 ++ .../resolution/resolvelib/found_candidates.py | 155 + .../resolution/resolvelib/provider.py | 248 + .../resolution/resolvelib/reporter.py | 68 + .../resolution/resolvelib/requirements.py | 166 + .../resolution/resolvelib/resolver.py | 298 + .../pip/_internal/self_outdated_check.py | 189 + .../pip/_internal/utils/__init__.py | 0 .../utils/__pycache__/__init__.cpython-39.pyc | Bin 0 -> 184 bytes .../utils/__pycache__/_log.cpython-39.pyc | Bin 0 -> 1509 bytes .../utils/__pycache__/appdirs.cpython-39.pyc | Bin 0 -> 1615 bytes .../utils/__pycache__/compat.cpython-39.pyc | Bin 0 -> 1503 bytes .../compatibility_tags.cpython-39.pyc | Bin 0 -> 4055 bytes .../utils/__pycache__/datetime.cpython-39.pyc | Bin 0 -> 503 bytes .../__pycache__/deprecation.cpython-39.pyc | Bin 0 -> 3241 bytes .../direct_url_helpers.cpython-39.pyc | Bin 0 -> 2074 bytes .../__pycache__/distutils_args.cpython-39.pyc | Bin 0 -> 1089 bytes .../utils/__pycache__/egg_link.cpython-39.pyc | Bin 0 -> 2130 bytes .../utils/__pycache__/encoding.cpython-39.pyc | Bin 0 -> 1293 bytes .../__pycache__/entrypoints.cpython-39.pyc | Bin 0 -> 1294 bytes .../__pycache__/filesystem.cpython-39.pyc | Bin 0 -> 5130 bytes .../__pycache__/filetypes.cpython-39.pyc | Bin 0 -> 934 bytes .../utils/__pycache__/glibc.cpython-39.pyc | Bin 0 -> 1665 bytes .../utils/__pycache__/hashes.cpython-39.pyc | Bin 0 -> 5179 bytes .../inject_securetransport.cpython-39.pyc | Bin 0 -> 973 bytes .../utils/__pycache__/logging.cpython-39.pyc | Bin 0 -> 9585 bytes .../utils/__pycache__/misc.cpython-39.pyc | Bin 0 -> 18790 bytes .../utils/__pycache__/models.cpython-39.pyc | Bin 0 -> 2052 bytes .../__pycache__/packaging.cpython-39.pyc | Bin 0 -> 2072 bytes .../setuptools_build.cpython-39.pyc | Bin 0 -> 4560 bytes .../__pycache__/subprocess.cpython-39.pyc | Bin 0 -> 5700 bytes .../utils/__pycache__/temp_dir.cpython-39.pyc | Bin 0 -> 7251 bytes .../__pycache__/unpacking.cpython-39.pyc | Bin 0 -> 6715 bytes .../utils/__pycache__/urls.cpython-39.pyc | Bin 0 -> 1588 bytes .../__pycache__/virtualenv.cpython-39.pyc | Bin 0 -> 3278 bytes .../utils/__pycache__/wheel.cpython-39.pyc | Bin 0 -> 4468 bytes .../site-packages/pip/_internal/utils/_log.py | 38 + .../pip/_internal/utils/appdirs.py | 52 + .../pip/_internal/utils/compat.py | 63 + .../pip/_internal/utils/compatibility_tags.py | 165 + .../pip/_internal/utils/datetime.py | 11 + .../pip/_internal/utils/deprecation.py | 120 + .../pip/_internal/utils/direct_url_helpers.py | 87 + .../pip/_internal/utils/distutils_args.py | 42 + .../pip/_internal/utils/egg_link.py | 75 + .../pip/_internal/utils/encoding.py | 36 + .../pip/_internal/utils/entrypoints.py | 27 + .../pip/_internal/utils/filesystem.py | 182 + .../pip/_internal/utils/filetypes.py | 27 + .../pip/_internal/utils/glibc.py | 88 + .../pip/_internal/utils/hashes.py | 144 + .../_internal/utils/inject_securetransport.py | 35 + .../pip/_internal/utils/logging.py | 343 + .../site-packages/pip/_internal/utils/misc.py | 629 + .../pip/_internal/utils/models.py | 39 + .../pip/_internal/utils/packaging.py | 57 + .../pip/_internal/utils/setuptools_build.py | 195 + .../pip/_internal/utils/subprocess.py | 260 + .../pip/_internal/utils/temp_dir.py | 246 + .../pip/_internal/utils/unpacking.py | 258 + .../site-packages/pip/_internal/utils/urls.py | 62 + .../pip/_internal/utils/virtualenv.py | 104 + .../pip/_internal/utils/wheel.py | 136 + .../pip/_internal/vcs/__init__.py | 15 + .../vcs/__pycache__/__init__.cpython-39.pyc | Bin 0 -> 507 bytes .../vcs/__pycache__/bazaar.cpython-39.pyc | Bin 0 -> 3346 bytes .../vcs/__pycache__/git.cpython-39.pyc | Bin 0 -> 12554 bytes .../vcs/__pycache__/mercurial.cpython-39.pyc | Bin 0 -> 5051 bytes .../vcs/__pycache__/subversion.cpython-39.pyc | Bin 0 -> 8468 bytes .../__pycache__/versioncontrol.cpython-39.pyc | Bin 0 -> 21174 bytes .../site-packages/pip/_internal/vcs/bazaar.py | 101 + .../site-packages/pip/_internal/vcs/git.py | 526 + .../pip/_internal/vcs/mercurial.py | 163 + .../pip/_internal/vcs/subversion.py | 324 + .../pip/_internal/vcs/versioncontrol.py | 705 + .../pip/_internal/wheel_builder.py | 377 + .../Lib/site-packages/pip/_vendor/__init__.py | 111 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 2897 bytes .../_vendor/__pycache__/distro.cpython-39.pyc | Bin 0 -> 38359 bytes .../_vendor/__pycache__/six.cpython-39.pyc | Bin 0 -> 27501 bytes .../typing_extensions.cpython-39.pyc | Bin 0 -> 68485 bytes .../pip/_vendor/cachecontrol/__init__.py | 18 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 635 bytes .../__pycache__/_cmd.cpython-39.pyc | Bin 0 -> 1563 bytes .../__pycache__/adapter.cpython-39.pyc | Bin 0 -> 3127 bytes .../__pycache__/cache.cpython-39.pyc | Bin 0 -> 1834 bytes .../__pycache__/compat.cpython-39.pyc | Bin 0 -> 739 bytes .../__pycache__/controller.cpython-39.pyc | Bin 0 -> 8201 bytes .../__pycache__/filewrapper.cpython-39.pyc | Bin 0 -> 2779 bytes .../__pycache__/heuristics.cpython-39.pyc | Bin 0 -> 4696 bytes .../__pycache__/serialize.cpython-39.pyc | Bin 0 -> 4243 bytes .../__pycache__/wrapper.cpython-39.pyc | Bin 0 -> 666 bytes .../pip/_vendor/cachecontrol/_cmd.py | 61 + .../pip/_vendor/cachecontrol/adapter.py | 137 + .../pip/_vendor/cachecontrol/cache.py | 43 + .../_vendor/cachecontrol/caches/__init__.py | 6 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 286 bytes .../__pycache__/file_cache.cpython-39.pyc | Bin 0 -> 3316 bytes .../__pycache__/redis_cache.cpython-39.pyc | Bin 0 -> 1558 bytes .../_vendor/cachecontrol/caches/file_cache.py | 150 + .../cachecontrol/caches/redis_cache.py | 37 + .../pip/_vendor/cachecontrol/compat.py | 32 + .../pip/_vendor/cachecontrol/controller.py | 415 + .../pip/_vendor/cachecontrol/filewrapper.py | 111 + .../pip/_vendor/cachecontrol/heuristics.py | 139 + .../pip/_vendor/cachecontrol/serialize.py | 186 + .../pip/_vendor/cachecontrol/wrapper.py | 33 + .../pip/_vendor/certifi/__init__.py | 3 + .../pip/_vendor/certifi/__main__.py | 12 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 268 bytes .../__pycache__/__main__.cpython-39.pyc | Bin 0 -> 445 bytes .../certifi/__pycache__/core.cpython-39.pyc | Bin 0 -> 1536 bytes .../pip/_vendor/certifi/cacert.pem | 4362 +++++++ .../site-packages/pip/_vendor/certifi/core.py | 76 + .../pip/_vendor/chardet/__init__.py | 83 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 1892 bytes .../__pycache__/big5freq.cpython-39.pyc | Bin 0 -> 27171 bytes .../__pycache__/big5prober.cpython-39.pyc | Bin 0 -> 1126 bytes .../chardistribution.cpython-39.pyc | Bin 0 -> 6212 bytes .../charsetgroupprober.cpython-39.pyc | Bin 0 -> 2253 bytes .../__pycache__/charsetprober.cpython-39.pyc | Bin 0 -> 3475 bytes .../codingstatemachine.cpython-39.pyc | Bin 0 -> 2902 bytes .../chardet/__pycache__/compat.cpython-39.pyc | Bin 0 -> 391 bytes .../__pycache__/cp949prober.cpython-39.pyc | Bin 0 -> 1133 bytes .../chardet/__pycache__/enums.cpython-39.pyc | Bin 0 -> 2640 bytes .../__pycache__/escprober.cpython-39.pyc | Bin 0 -> 2625 bytes .../chardet/__pycache__/escsm.cpython-39.pyc | Bin 0 -> 7074 bytes .../__pycache__/eucjpprober.cpython-39.pyc | Bin 0 -> 2439 bytes .../__pycache__/euckrfreq.cpython-39.pyc | Bin 0 -> 12055 bytes .../__pycache__/euckrprober.cpython-39.pyc | Bin 0 -> 1134 bytes .../__pycache__/euctwfreq.cpython-39.pyc | Bin 0 -> 27175 bytes .../__pycache__/euctwprober.cpython-39.pyc | Bin 0 -> 1134 bytes .../__pycache__/gb2312freq.cpython-39.pyc | Bin 0 -> 19099 bytes .../__pycache__/gb2312prober.cpython-39.pyc | Bin 0 -> 1142 bytes .../__pycache__/hebrewprober.cpython-39.pyc | Bin 0 -> 3011 bytes .../__pycache__/jisfreq.cpython-39.pyc | Bin 0 -> 22127 bytes .../chardet/__pycache__/jpcntx.cpython-39.pyc | Bin 0 -> 37600 bytes .../langbulgarianmodel.cpython-39.pyc | Bin 0 -> 21802 bytes .../__pycache__/langgreekmodel.cpython-39.pyc | Bin 0 -> 20478 bytes .../langhebrewmodel.cpython-39.pyc | Bin 0 -> 20546 bytes .../langhungarianmodel.cpython-39.pyc | Bin 0 -> 21747 bytes .../langrussianmodel.cpython-39.pyc | Bin 0 -> 26350 bytes .../__pycache__/langthaimodel.cpython-39.pyc | Bin 0 -> 20722 bytes .../langturkishmodel.cpython-39.pyc | Bin 0 -> 20562 bytes .../__pycache__/latin1prober.cpython-39.pyc | Bin 0 -> 2947 bytes .../mbcharsetprober.cpython-39.pyc | Bin 0 -> 2254 bytes .../mbcsgroupprober.cpython-39.pyc | Bin 0 -> 1123 bytes .../chardet/__pycache__/mbcssm.cpython-39.pyc | Bin 0 -> 15710 bytes .../sbcharsetprober.cpython-39.pyc | Bin 0 -> 3107 bytes .../sbcsgroupprober.cpython-39.pyc | Bin 0 -> 1692 bytes .../__pycache__/sjisprober.cpython-39.pyc | Bin 0 -> 2475 bytes .../universaldetector.cpython-39.pyc | Bin 0 -> 5823 bytes .../__pycache__/utf8prober.cpython-39.pyc | Bin 0 -> 1984 bytes .../__pycache__/version.cpython-39.pyc | Bin 0 -> 431 bytes .../pip/_vendor/chardet/big5freq.py | 386 + .../pip/_vendor/chardet/big5prober.py | 47 + .../pip/_vendor/chardet/chardistribution.py | 233 + .../pip/_vendor/chardet/charsetgroupprober.py | 107 + .../pip/_vendor/chardet/charsetprober.py | 145 + .../pip/_vendor/chardet/cli/__init__.py | 1 + .../cli/__pycache__/__init__.cpython-39.pyc | Bin 0 -> 188 bytes .../cli/__pycache__/chardetect.cpython-39.pyc | Bin 0 -> 2682 bytes .../pip/_vendor/chardet/cli/chardetect.py | 84 + .../pip/_vendor/chardet/codingstatemachine.py | 88 + .../pip/_vendor/chardet/compat.py | 36 + .../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 | 4650 +++++++ .../pip/_vendor/chardet/langgreekmodel.py | 4398 +++++++ .../pip/_vendor/chardet/langhebrewmodel.py | 4383 +++++++ .../pip/_vendor/chardet/langhungarianmodel.py | 4650 +++++++ .../pip/_vendor/chardet/langrussianmodel.py | 5718 ++++++++ .../pip/_vendor/chardet/langthaimodel.py | 4383 +++++++ .../pip/_vendor/chardet/langturkishmodel.py | 4383 +++++++ .../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/metadata/__init__.py | 0 .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 193 bytes .../__pycache__/languages.cpython-39.pyc | Bin 0 -> 7924 bytes .../pip/_vendor/chardet/metadata/languages.py | 310 + .../pip/_vendor/chardet/sbcharsetprober.py | 145 + .../pip/_vendor/chardet/sbcsgroupprober.py | 83 + .../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-39.pyc | Bin 0 -> 436 bytes .../colorama/__pycache__/ansi.cpython-39.pyc | Bin 0 -> 3221 bytes .../__pycache__/ansitowin32.cpython-39.pyc | Bin 0 -> 7687 bytes .../__pycache__/initialise.cpython-39.pyc | Bin 0 -> 1703 bytes .../colorama/__pycache__/win32.cpython-39.pyc | Bin 0 -> 3935 bytes .../__pycache__/winterm.cpython-39.pyc | Bin 0 -> 4657 bytes .../pip/_vendor/colorama/ansi.py | 102 + .../pip/_vendor/colorama/ansitowin32.py | 258 + .../pip/_vendor/colorama/initialise.py | 80 + .../pip/_vendor/colorama/win32.py | 152 + .../pip/_vendor/colorama/winterm.py | 169 + .../pip/_vendor/distlib/__init__.py | 23 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 1049 bytes .../distlib/__pycache__/compat.cpython-39.pyc | Bin 0 -> 31814 bytes .../__pycache__/database.cpython-39.pyc | Bin 0 -> 42473 bytes .../distlib/__pycache__/index.cpython-39.pyc | Bin 0 -> 17282 bytes .../__pycache__/locators.cpython-39.pyc | Bin 0 -> 38246 bytes .../__pycache__/manifest.cpython-39.pyc | Bin 0 -> 10185 bytes .../__pycache__/markers.cpython-39.pyc | Bin 0 -> 4967 bytes .../__pycache__/metadata.cpython-39.pyc | Bin 0 -> 26580 bytes .../__pycache__/resources.cpython-39.pyc | Bin 0 -> 11003 bytes .../__pycache__/scripts.cpython-39.pyc | Bin 0 -> 11235 bytes .../distlib/__pycache__/util.cpython-39.pyc | Bin 0 -> 52598 bytes .../__pycache__/version.cpython-39.pyc | Bin 0 -> 20348 bytes .../distlib/__pycache__/wheel.cpython-39.pyc | Bin 0 -> 27161 bytes .../pip/_vendor/distlib/_backport/__init__.py | 6 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 476 bytes .../_backport/__pycache__/misc.cpython-39.pyc | Bin 0 -> 1096 bytes .../__pycache__/shutil.cpython-39.pyc | Bin 0 -> 21670 bytes .../__pycache__/sysconfig.cpython-39.pyc | Bin 0 -> 15960 bytes .../__pycache__/tarfile.cpython-39.pyc | Bin 0 -> 62724 bytes .../pip/_vendor/distlib/_backport/misc.py | 41 + .../pip/_vendor/distlib/_backport/shutil.py | 764 ++ .../_vendor/distlib/_backport/sysconfig.cfg | 84 + .../_vendor/distlib/_backport/sysconfig.py | 786 ++ .../pip/_vendor/distlib/_backport/tarfile.py | 2607 ++++ .../pip/_vendor/distlib/compat.py | 1122 ++ .../pip/_vendor/distlib/database.py | 1339 ++ .../pip/_vendor/distlib/index.py | 509 + .../pip/_vendor/distlib/locators.py | 1300 ++ .../pip/_vendor/distlib/manifest.py | 393 + .../pip/_vendor/distlib/markers.py | 147 + .../pip/_vendor/distlib/metadata.py | 1058 ++ .../pip/_vendor/distlib/resources.py | 358 + .../pip/_vendor/distlib/scripts.py | 429 + .../site-packages/pip/_vendor/distlib/t32.exe | Bin 0 -> 96768 bytes .../pip/_vendor/distlib/t64-arm.exe | Bin 0 -> 180736 bytes .../site-packages/pip/_vendor/distlib/t64.exe | Bin 0 -> 105984 bytes .../site-packages/pip/_vendor/distlib/util.py | 1969 +++ .../pip/_vendor/distlib/version.py | 739 ++ .../site-packages/pip/_vendor/distlib/w32.exe | Bin 0 -> 90112 bytes .../pip/_vendor/distlib/w64-arm.exe | Bin 0 -> 166400 bytes .../site-packages/pip/_vendor/distlib/w64.exe | Bin 0 -> 99840 bytes .../pip/_vendor/distlib/wheel.py | 1053 ++ venv/Lib/site-packages/pip/_vendor/distro.py | 1386 ++ .../pip/_vendor/html5lib/__init__.py | 35 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 1295 bytes .../__pycache__/_ihatexml.cpython-39.pyc | Bin 0 -> 13764 bytes .../__pycache__/_inputstream.cpython-39.pyc | Bin 0 -> 21623 bytes .../__pycache__/_tokenizer.cpython-39.pyc | Bin 0 -> 39718 bytes .../__pycache__/_utils.cpython-39.pyc | Bin 0 -> 4795 bytes .../__pycache__/constants.cpython-39.pyc | Bin 0 -> 66333 bytes .../__pycache__/html5parser.cpython-39.pyc | Bin 0 -> 91004 bytes .../__pycache__/serializer.cpython-39.pyc | Bin 0 -> 10806 bytes .../pip/_vendor/html5lib/_ihatexml.py | 289 + .../pip/_vendor/html5lib/_inputstream.py | 918 ++ .../pip/_vendor/html5lib/_tokenizer.py | 1735 +++ .../pip/_vendor/html5lib/_trie/__init__.py | 5 + .../_trie/__pycache__/__init__.cpython-39.pyc | Bin 0 -> 345 bytes .../_trie/__pycache__/_base.cpython-39.pyc | Bin 0 -> 1589 bytes .../_trie/__pycache__/py.cpython-39.pyc | Bin 0 -> 2250 bytes .../pip/_vendor/html5lib/_trie/_base.py | 40 + .../pip/_vendor/html5lib/_trie/py.py | 67 + .../pip/_vendor/html5lib/_utils.py | 159 + .../pip/_vendor/html5lib/constants.py | 2946 +++++ .../pip/_vendor/html5lib/filters/__init__.py | 0 .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 193 bytes .../alphabeticalattributes.cpython-39.pyc | Bin 0 -> 1315 bytes .../filters/__pycache__/base.cpython-39.pyc | Bin 0 -> 863 bytes .../inject_meta_charset.cpython-39.pyc | Bin 0 -> 1869 bytes .../filters/__pycache__/lint.cpython-39.pyc | Bin 0 -> 2611 bytes .../__pycache__/optionaltags.cpython-39.pyc | Bin 0 -> 2756 bytes .../__pycache__/sanitizer.cpython-39.pyc | Bin 0 -> 16879 bytes .../__pycache__/whitespace.cpython-39.pyc | Bin 0 -> 1361 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 | 916 ++ .../_vendor/html5lib/filters/whitespace.py | 38 + .../pip/_vendor/html5lib/html5parser.py | 2795 ++++ .../pip/_vendor/html5lib/serializer.py | 409 + .../_vendor/html5lib/treeadapters/__init__.py | 30 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 930 bytes .../__pycache__/genshi.cpython-39.pyc | Bin 0 -> 1538 bytes .../__pycache__/sax.cpython-39.pyc | Bin 0 -> 1457 bytes .../_vendor/html5lib/treeadapters/genshi.py | 54 + .../pip/_vendor/html5lib/treeadapters/sax.py | 50 + .../_vendor/html5lib/treebuilders/__init__.py | 88 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 3325 bytes .../__pycache__/base.cpython-39.pyc | Bin 0 -> 11309 bytes .../__pycache__/dom.cpython-39.pyc | Bin 0 -> 9446 bytes .../__pycache__/etree.cpython-39.pyc | Bin 0 -> 11814 bytes .../__pycache__/etree_lxml.cpython-39.pyc | Bin 0 -> 12997 bytes .../pip/_vendor/html5lib/treebuilders/base.py | 417 + .../pip/_vendor/html5lib/treebuilders/dom.py | 239 + .../_vendor/html5lib/treebuilders/etree.py | 343 + .../html5lib/treebuilders/etree_lxml.py | 392 + .../_vendor/html5lib/treewalkers/__init__.py | 154 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 3991 bytes .../__pycache__/base.cpython-39.pyc | Bin 0 -> 6990 bytes .../__pycache__/dom.cpython-39.pyc | Bin 0 -> 1725 bytes .../__pycache__/etree.cpython-39.pyc | Bin 0 -> 3487 bytes .../__pycache__/etree_lxml.cpython-39.pyc | Bin 0 -> 6624 bytes .../__pycache__/genshi.cpython-39.pyc | Bin 0 -> 1881 bytes .../pip/_vendor/html5lib/treewalkers/base.py | 252 + .../pip/_vendor/html5lib/treewalkers/dom.py | 43 + .../pip/_vendor/html5lib/treewalkers/etree.py | 131 + .../html5lib/treewalkers/etree_lxml.py | 215 + .../_vendor/html5lib/treewalkers/genshi.py | 69 + .../pip/_vendor/idna/__init__.py | 44 + .../idna/__pycache__/__init__.cpython-39.pyc | Bin 0 -> 840 bytes .../idna/__pycache__/codec.cpython-39.pyc | Bin 0 -> 3077 bytes .../idna/__pycache__/compat.cpython-39.pyc | Bin 0 -> 759 bytes .../idna/__pycache__/core.cpython-39.pyc | Bin 0 -> 9755 bytes .../idna/__pycache__/idnadata.cpython-39.pyc | Bin 0 -> 23036 bytes .../idna/__pycache__/intranges.cpython-39.pyc | Bin 0 -> 1990 bytes .../__pycache__/package_data.cpython-39.pyc | Bin 0 -> 204 bytes .../idna/__pycache__/uts46data.cpython-39.pyc | Bin 0 -> 151737 bytes .../site-packages/pip/_vendor/idna/codec.py | 112 + .../site-packages/pip/_vendor/idna/compat.py | 13 + .../site-packages/pip/_vendor/idna/core.py | 397 + .../pip/_vendor/idna/idnadata.py | 2137 +++ .../pip/_vendor/idna/intranges.py | 54 + .../pip/_vendor/idna/package_data.py | 2 + .../pip/_vendor/idna/uts46data.py | 8512 ++++++++++++ .../pip/_vendor/msgpack/__init__.py | 54 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 1407 bytes .../__pycache__/_version.cpython-39.pyc | Bin 0 -> 211 bytes .../__pycache__/exceptions.cpython-39.pyc | Bin 0 -> 1845 bytes .../msgpack/__pycache__/ext.cpython-39.pyc | Bin 0 -> 6273 bytes .../__pycache__/fallback.cpython-39.pyc | Bin 0 -> 25612 bytes .../pip/_vendor/msgpack/_version.py | 1 + .../pip/_vendor/msgpack/exceptions.py | 48 + .../site-packages/pip/_vendor/msgpack/ext.py | 193 + .../pip/_vendor/msgpack/fallback.py | 1012 ++ .../pip/_vendor/packaging/__about__.py | 26 + .../pip/_vendor/packaging/__init__.py | 25 + .../__pycache__/__about__.cpython-39.pyc | Bin 0 -> 583 bytes .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 439 bytes .../__pycache__/_manylinux.cpython-39.pyc | Bin 0 -> 7287 bytes .../__pycache__/_musllinux.cpython-39.pyc | Bin 0 -> 4602 bytes .../__pycache__/_structures.cpython-39.pyc | Bin 0 -> 2796 bytes .../__pycache__/markers.cpython-39.pyc | Bin 0 -> 9446 bytes .../__pycache__/requirements.cpython-39.pyc | Bin 0 -> 3967 bytes .../__pycache__/specifiers.cpython-39.pyc | Bin 0 -> 21514 bytes .../packaging/__pycache__/tags.cpython-39.pyc | Bin 0 -> 12245 bytes .../__pycache__/utils.cpython-39.pyc | Bin 0 -> 3604 bytes .../__pycache__/version.cpython-39.pyc | Bin 0 -> 13145 bytes .../pip/_vendor/packaging/_manylinux.py | 301 + .../pip/_vendor/packaging/_musllinux.py | 136 + .../pip/_vendor/packaging/_structures.py | 61 + .../pip/_vendor/packaging/markers.py | 304 + .../pip/_vendor/packaging/requirements.py | 146 + .../pip/_vendor/packaging/specifiers.py | 802 ++ .../pip/_vendor/packaging/tags.py | 487 + .../pip/_vendor/packaging/utils.py | 136 + .../pip/_vendor/packaging/version.py | 504 + .../pip/_vendor/pep517/__init__.py | 6 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 306 bytes .../pep517/__pycache__/build.cpython-39.pyc | Bin 0 -> 3554 bytes .../pep517/__pycache__/check.cpython-39.pyc | Bin 0 -> 5101 bytes .../__pycache__/colorlog.cpython-39.pyc | Bin 0 -> 2931 bytes .../pep517/__pycache__/compat.cpython-39.pyc | Bin 0 -> 1522 bytes .../__pycache__/dirtools.cpython-39.pyc | Bin 0 -> 1340 bytes .../__pycache__/envbuild.cpython-39.pyc | Bin 0 -> 4500 bytes .../pep517/__pycache__/meta.cpython-39.pyc | Bin 0 -> 2913 bytes .../__pycache__/wrappers.cpython-39.pyc | Bin 0 -> 12486 bytes .../site-packages/pip/_vendor/pep517/build.py | 127 + .../site-packages/pip/_vendor/pep517/check.py | 207 + .../pip/_vendor/pep517/colorlog.py | 115 + .../pip/_vendor/pep517/compat.py | 51 + .../pip/_vendor/pep517/dirtools.py | 44 + .../pip/_vendor/pep517/envbuild.py | 171 + .../pip/_vendor/pep517/in_process/__init__.py | 17 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 908 bytes .../__pycache__/_in_process.cpython-39.pyc | Bin 0 -> 10262 bytes .../_vendor/pep517/in_process/_in_process.py | 363 + .../site-packages/pip/_vendor/pep517/meta.py | 92 + .../pip/_vendor/pep517/wrappers.py | 375 + .../pip/_vendor/pkg_resources/__init__.py | 3296 +++++ .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 100329 bytes .../__pycache__/py31compat.cpython-39.pyc | Bin 0 -> 643 bytes .../pip/_vendor/pkg_resources/py31compat.py | 23 + .../pip/_vendor/platformdirs/__init__.py | 331 + .../pip/_vendor/platformdirs/__main__.py | 46 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 10644 bytes .../__pycache__/__main__.cpython-39.pyc | Bin 0 -> 1215 bytes .../__pycache__/android.cpython-39.pyc | Bin 0 -> 4364 bytes .../__pycache__/api.cpython-39.pyc | Bin 0 -> 5277 bytes .../__pycache__/macos.cpython-39.pyc | Bin 0 -> 3299 bytes .../__pycache__/unix.cpython-39.pyc | Bin 0 -> 7047 bytes .../__pycache__/version.cpython-39.pyc | Bin 0 -> 288 bytes .../__pycache__/windows.cpython-39.pyc | Bin 0 -> 6443 bytes .../pip/_vendor/platformdirs/android.py | 119 + .../pip/_vendor/platformdirs/api.py | 156 + .../pip/_vendor/platformdirs/macos.py | 64 + .../pip/_vendor/platformdirs/unix.py | 181 + .../pip/_vendor/platformdirs/version.py | 4 + .../pip/_vendor/platformdirs/windows.py | 182 + .../pip/_vendor/progress/__init__.py | 189 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 5675 bytes .../progress/__pycache__/bar.cpython-39.pyc | Bin 0 -> 2720 bytes .../__pycache__/colors.cpython-39.pyc | Bin 0 -> 1493 bytes .../__pycache__/counter.cpython-39.pyc | Bin 0 -> 1618 bytes .../__pycache__/spinner.cpython-39.pyc | Bin 0 -> 1444 bytes .../site-packages/pip/_vendor/progress/bar.py | 93 + .../pip/_vendor/progress/colors.py | 79 + .../pip/_vendor/progress/counter.py | 47 + .../pip/_vendor/progress/spinner.py | 45 + .../pip/_vendor/pygments/__init__.py | 83 + .../pip/_vendor/pygments/__main__.py | 17 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 3018 bytes .../__pycache__/__main__.cpython-39.pyc | Bin 0 -> 579 bytes .../__pycache__/cmdline.cpython-39.pyc | Bin 0 -> 15371 bytes .../__pycache__/console.cpython-39.pyc | Bin 0 -> 1876 bytes .../__pycache__/filter.cpython-39.pyc | Bin 0 -> 2637 bytes .../__pycache__/formatter.cpython-39.pyc | Bin 0 -> 3001 bytes .../pygments/__pycache__/lexer.cpython-39.pyc | Bin 0 -> 24431 bytes .../__pycache__/modeline.cpython-39.pyc | Bin 0 -> 1179 bytes .../__pycache__/plugin.cpython-39.pyc | Bin 0 -> 2099 bytes .../__pycache__/regexopt.cpython-39.pyc | Bin 0 -> 2933 bytes .../__pycache__/scanner.cpython-39.pyc | Bin 0 -> 3546 bytes .../__pycache__/sphinxext.cpython-39.pyc | Bin 0 -> 4551 bytes .../pygments/__pycache__/style.cpython-39.pyc | Bin 0 -> 4488 bytes .../pygments/__pycache__/token.cpython-39.pyc | Bin 0 -> 4350 bytes .../__pycache__/unistring.cpython-39.pyc | Bin 0 -> 31208 bytes .../pygments/__pycache__/util.cpython-39.pyc | Bin 0 -> 9165 bytes .../pip/_vendor/pygments/cmdline.py | 663 + .../pip/_vendor/pygments/console.py | 70 + .../pip/_vendor/pygments/filter.py | 71 + .../pip/_vendor/pygments/filters/__init__.py | 937 ++ .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 23386 bytes .../pip/_vendor/pygments/formatter.py | 94 + .../_vendor/pygments/formatters/__init__.py | 153 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 4654 bytes .../__pycache__/_mapping.cpython-39.pyc | Bin 0 -> 5410 bytes .../__pycache__/bbcode.cpython-39.pyc | Bin 0 -> 3058 bytes .../__pycache__/groff.cpython-39.pyc | Bin 0 -> 4331 bytes .../__pycache__/html.cpython-39.pyc | Bin 0 -> 29043 bytes .../formatters/__pycache__/img.cpython-39.pyc | Bin 0 -> 17485 bytes .../formatters/__pycache__/irc.cpython-39.pyc | Bin 0 -> 4397 bytes .../__pycache__/latex.cpython-39.pyc | Bin 0 -> 13479 bytes .../__pycache__/other.cpython-39.pyc | Bin 0 -> 4781 bytes .../__pycache__/pangomarkup.cpython-39.pyc | Bin 0 -> 2083 bytes .../formatters/__pycache__/rtf.cpython-39.pyc | Bin 0 -> 4117 bytes .../formatters/__pycache__/svg.cpython-39.pyc | Bin 0 -> 6329 bytes .../__pycache__/terminal.cpython-39.pyc | Bin 0 -> 3898 bytes .../__pycache__/terminal256.cpython-39.pyc | Bin 0 -> 9208 bytes .../_vendor/pygments/formatters/_mapping.py | 84 + .../pip/_vendor/pygments/formatters/bbcode.py | 108 + .../pip/_vendor/pygments/formatters/groff.py | 168 + .../pip/_vendor/pygments/formatters/html.py | 983 ++ .../pip/_vendor/pygments/formatters/img.py | 641 + .../pip/_vendor/pygments/formatters/irc.py | 179 + .../pip/_vendor/pygments/formatters/latex.py | 511 + .../pip/_vendor/pygments/formatters/other.py | 161 + .../pygments/formatters/pangomarkup.py | 83 + .../pip/_vendor/pygments/formatters/rtf.py | 146 + .../pip/_vendor/pygments/formatters/svg.py | 188 + .../_vendor/pygments/formatters/terminal.py | 127 + .../pygments/formatters/terminal256.py | 338 + .../pip/_vendor/pygments/lexer.py | 879 ++ .../pip/_vendor/pygments/lexers/__init__.py | 341 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 9131 bytes .../__pycache__/_mapping.cpython-39.pyc | Bin 0 -> 50814 bytes .../lexers/__pycache__/python.cpython-39.pyc | Bin 0 -> 28959 bytes .../pip/_vendor/pygments/lexers/_mapping.py | 580 + .../pip/_vendor/pygments/lexers/python.py | 1188 ++ .../pip/_vendor/pygments/modeline.py | 43 + .../pip/_vendor/pygments/plugin.py | 69 + .../pip/_vendor/pygments/regexopt.py | 91 + .../pip/_vendor/pygments/scanner.py | 104 + .../pip/_vendor/pygments/sphinxext.py | 155 + .../pip/_vendor/pygments/style.py | 197 + .../pip/_vendor/pygments/styles/__init__.py | 93 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 2999 bytes .../pip/_vendor/pygments/token.py | 212 + .../pip/_vendor/pygments/unistring.py | 153 + .../pip/_vendor/pygments/util.py | 308 + .../pip/_vendor/pyparsing/__init__.py | 328 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 7110 bytes .../__pycache__/actions.cpython-39.pyc | Bin 0 -> 7161 bytes .../__pycache__/common.cpython-39.pyc | Bin 0 -> 10052 bytes .../pyparsing/__pycache__/core.cpython-39.pyc | Bin 0 -> 176662 bytes .../__pycache__/exceptions.cpython-39.pyc | Bin 0 -> 9149 bytes .../__pycache__/helpers.cpython-39.pyc | Bin 0 -> 34697 bytes .../__pycache__/results.cpython-39.pyc | Bin 0 -> 24773 bytes .../__pycache__/testing.cpython-39.pyc | Bin 0 -> 12102 bytes .../__pycache__/unicode.cpython-39.pyc | Bin 0 -> 10243 bytes .../pyparsing/__pycache__/util.cpython-39.pyc | Bin 0 -> 8612 bytes .../pip/_vendor/pyparsing/actions.py | 207 + .../pip/_vendor/pyparsing/common.py | 424 + .../pip/_vendor/pyparsing/core.py | 5789 ++++++++ .../pip/_vendor/pyparsing/diagram/__init__.py | 593 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 15580 bytes .../pip/_vendor/pyparsing/exceptions.py | 267 + .../pip/_vendor/pyparsing/helpers.py | 1069 ++ .../pip/_vendor/pyparsing/results.py | 760 ++ .../pip/_vendor/pyparsing/testing.py | 331 + .../pip/_vendor/pyparsing/unicode.py | 332 + .../pip/_vendor/pyparsing/util.py | 235 + .../pip/_vendor/requests/__init__.py | 154 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 4021 bytes .../__pycache__/__version__.cpython-39.pyc | Bin 0 -> 548 bytes .../_internal_utils.cpython-39.pyc | Bin 0 -> 1295 bytes .../__pycache__/adapters.cpython-39.pyc | Bin 0 -> 17105 bytes .../requests/__pycache__/api.cpython-39.pyc | Bin 0 -> 6712 bytes .../requests/__pycache__/auth.cpython-39.pyc | Bin 0 -> 8324 bytes .../requests/__pycache__/certs.cpython-39.pyc | Bin 0 -> 626 bytes .../__pycache__/compat.cpython-39.pyc | Bin 0 -> 1661 bytes .../__pycache__/cookies.cpython-39.pyc | Bin 0 -> 18815 bytes .../__pycache__/exceptions.cpython-39.pyc | Bin 0 -> 5651 bytes .../requests/__pycache__/help.cpython-39.pyc | Bin 0 -> 2886 bytes .../requests/__pycache__/hooks.cpython-39.pyc | Bin 0 -> 983 bytes .../__pycache__/models.cpython-39.pyc | Bin 0 -> 24364 bytes .../__pycache__/packages.cpython-39.pyc | Bin 0 -> 495 bytes .../__pycache__/sessions.cpython-39.pyc | Bin 0 -> 19699 bytes .../__pycache__/status_codes.cpython-39.pyc | Bin 0 -> 4232 bytes .../__pycache__/structures.cpython-39.pyc | Bin 0 -> 4453 bytes .../requests/__pycache__/utils.cpython-39.pyc | Bin 0 -> 24280 bytes .../pip/_vendor/requests/__version__.py | 14 + .../pip/_vendor/requests/_internal_utils.py | 42 + .../pip/_vendor/requests/adapters.py | 538 + .../site-packages/pip/_vendor/requests/api.py | 159 + .../pip/_vendor/requests/auth.py | 305 + .../pip/_vendor/requests/certs.py | 18 + .../pip/_vendor/requests/compat.py | 77 + .../pip/_vendor/requests/cookies.py | 549 + .../pip/_vendor/requests/exceptions.py | 133 + .../pip/_vendor/requests/help.py | 132 + .../pip/_vendor/requests/hooks.py | 34 + .../pip/_vendor/requests/models.py | 973 ++ .../pip/_vendor/requests/packages.py | 16 + .../pip/_vendor/requests/sessions.py | 771 ++ .../pip/_vendor/requests/status_codes.py | 123 + .../pip/_vendor/requests/structures.py | 105 + .../pip/_vendor/requests/utils.py | 1060 ++ .../pip/_vendor/resolvelib/__init__.py | 26 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 599 bytes .../__pycache__/providers.cpython-39.pyc | Bin 0 -> 6698 bytes .../__pycache__/reporters.cpython-39.pyc | Bin 0 -> 2610 bytes .../__pycache__/resolvers.cpython-39.pyc | Bin 0 -> 15301 bytes .../__pycache__/structs.cpython-39.pyc | Bin 0 -> 7272 bytes .../pip/_vendor/resolvelib/compat/__init__.py | 0 .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 194 bytes .../collections_abc.cpython-39.pyc | Bin 0 -> 368 bytes .../resolvelib/compat/collections_abc.py | 6 + .../pip/_vendor/resolvelib/providers.py | 133 + .../pip/_vendor/resolvelib/reporters.py | 43 + .../pip/_vendor/resolvelib/resolvers.py | 482 + .../pip/_vendor/resolvelib/structs.py | 165 + .../pip/_vendor/rich/__init__.py | 172 + .../pip/_vendor/rich/__main__.py | 280 + .../rich/__pycache__/__init__.cpython-39.pyc | Bin 0 -> 5792 bytes .../rich/__pycache__/__main__.cpython-39.pyc | Bin 0 -> 7284 bytes .../__pycache__/_cell_widths.cpython-39.pyc | Bin 0 -> 7807 bytes .../__pycache__/_emoji_codes.cpython-39.pyc | Bin 0 -> 132694 bytes .../__pycache__/_emoji_replace.cpython-39.pyc | Bin 0 -> 1179 bytes .../__pycache__/_extension.cpython-39.pyc | Bin 0 -> 488 bytes .../rich/__pycache__/_inspect.cpython-39.pyc | Bin 0 -> 6633 bytes .../__pycache__/_log_render.cpython-39.pyc | Bin 0 -> 2571 bytes .../rich/__pycache__/_loop.cpython-39.pyc | Bin 0 -> 1261 bytes .../__pycache__/_lru_cache.cpython-39.pyc | Bin 0 -> 1577 bytes .../rich/__pycache__/_palettes.cpython-39.pyc | Bin 0 -> 5090 bytes .../rich/__pycache__/_pick.cpython-39.pyc | Bin 0 -> 631 bytes .../rich/__pycache__/_ratio.cpython-39.pyc | Bin 0 -> 5115 bytes .../rich/__pycache__/_spinners.cpython-39.pyc | Bin 0 -> 13910 bytes .../rich/__pycache__/_stack.cpython-39.pyc | Bin 0 -> 836 bytes .../rich/__pycache__/_timer.cpython-39.pyc | Bin 0 -> 683 bytes .../rich/__pycache__/_windows.cpython-39.pyc | Bin 0 -> 1859 bytes .../rich/__pycache__/_wrap.cpython-39.pyc | Bin 0 -> 1489 bytes .../rich/__pycache__/abc.cpython-39.pyc | Bin 0 -> 1297 bytes .../rich/__pycache__/align.cpython-39.pyc | Bin 0 -> 7865 bytes .../rich/__pycache__/ansi.cpython-39.pyc | Bin 0 -> 5667 bytes .../rich/__pycache__/bar.cpython-39.pyc | Bin 0 -> 2935 bytes .../rich/__pycache__/box.cpython-39.pyc | Bin 0 -> 7849 bytes .../rich/__pycache__/cells.cpython-39.pyc | Bin 0 -> 3484 bytes .../rich/__pycache__/color.cpython-39.pyc | Bin 0 -> 14743 bytes .../__pycache__/color_triplet.cpython-39.pyc | Bin 0 -> 1418 bytes .../rich/__pycache__/columns.cpython-39.pyc | Bin 0 -> 6122 bytes .../rich/__pycache__/console.cpython-39.pyc | Bin 0 -> 69744 bytes .../rich/__pycache__/constrain.cpython-39.pyc | Bin 0 -> 1656 bytes .../__pycache__/containers.cpython-39.pyc | Bin 0 -> 6417 bytes .../rich/__pycache__/control.cpython-39.pyc | Bin 0 -> 6842 bytes .../__pycache__/default_styles.cpython-39.pyc | Bin 0 -> 5109 bytes .../rich/__pycache__/diagnose.cpython-39.pyc | Bin 0 -> 342 bytes .../rich/__pycache__/emoji.cpython-39.pyc | Bin 0 -> 3195 bytes .../rich/__pycache__/errors.cpython-39.pyc | Bin 0 -> 1662 bytes .../__pycache__/file_proxy.cpython-39.pyc | Bin 0 -> 2236 bytes .../rich/__pycache__/filesize.cpython-39.pyc | Bin 0 -> 2605 bytes .../__pycache__/highlighter.cpython-39.pyc | Bin 0 -> 5310 bytes .../rich/__pycache__/json.cpython-39.pyc | Bin 0 -> 4696 bytes .../rich/__pycache__/jupyter.cpython-39.pyc | Bin 0 -> 3836 bytes .../rich/__pycache__/layout.cpython-39.pyc | Bin 0 -> 14678 bytes .../rich/__pycache__/live.cpython-39.pyc | Bin 0 -> 11278 bytes .../__pycache__/live_render.cpython-39.pyc | Bin 0 -> 3383 bytes .../rich/__pycache__/logging.cpython-39.pyc | Bin 0 -> 9222 bytes .../rich/__pycache__/markup.cpython-39.pyc | Bin 0 -> 5889 bytes .../rich/__pycache__/measure.cpython-39.pyc | Bin 0 -> 4970 bytes .../rich/__pycache__/padding.cpython-39.pyc | Bin 0 -> 4399 bytes .../rich/__pycache__/pager.cpython-39.pyc | Bin 0 -> 1465 bytes .../rich/__pycache__/palette.cpython-39.pyc | Bin 0 -> 3681 bytes .../rich/__pycache__/panel.cpython-39.pyc | Bin 0 -> 6386 bytes .../rich/__pycache__/pretty.cpython-39.pyc | Bin 0 -> 24911 bytes .../rich/__pycache__/progress.cpython-39.pyc | Bin 0 -> 32945 bytes .../__pycache__/progress_bar.cpython-39.pyc | Bin 0 -> 6610 bytes .../rich/__pycache__/prompt.cpython-39.pyc | Bin 0 -> 11350 bytes .../rich/__pycache__/protocol.cpython-39.pyc | Bin 0 -> 1351 bytes .../rich/__pycache__/region.cpython-39.pyc | Bin 0 -> 518 bytes .../rich/__pycache__/repr.cpython-39.pyc | Bin 0 -> 4030 bytes .../rich/__pycache__/rule.cpython-39.pyc | Bin 0 -> 3694 bytes .../rich/__pycache__/scope.cpython-39.pyc | Bin 0 -> 2956 bytes .../rich/__pycache__/screen.cpython-39.pyc | Bin 0 -> 1815 bytes .../rich/__pycache__/segment.cpython-39.pyc | Bin 0 -> 20296 bytes .../rich/__pycache__/spinner.cpython-39.pyc | Bin 0 -> 4336 bytes .../rich/__pycache__/status.cpython-39.pyc | Bin 0 -> 4568 bytes .../rich/__pycache__/style.cpython-39.pyc | Bin 0 -> 20596 bytes .../rich/__pycache__/styled.cpython-39.pyc | Bin 0 -> 1681 bytes .../rich/__pycache__/syntax.cpython-39.pyc | Bin 0 -> 18797 bytes .../rich/__pycache__/table.cpython-39.pyc | Bin 0 -> 26663 bytes .../rich/__pycache__/tabulate.cpython-39.pyc | Bin 0 -> 1723 bytes .../__pycache__/terminal_theme.cpython-39.pyc | Bin 0 -> 1693 bytes .../rich/__pycache__/text.cpython-39.pyc | Bin 0 -> 39443 bytes .../rich/__pycache__/theme.cpython-39.pyc | Bin 0 -> 4673 bytes .../rich/__pycache__/themes.cpython-39.pyc | Bin 0 -> 286 bytes .../rich/__pycache__/traceback.cpython-39.pyc | Bin 0 -> 19353 bytes .../rich/__pycache__/tree.cpython-39.pyc | Bin 0 -> 7203 bytes .../pip/_vendor/rich/_cell_widths.py | 451 + .../pip/_vendor/rich/_emoji_codes.py | 3610 +++++ .../pip/_vendor/rich/_emoji_replace.py | 32 + .../pip/_vendor/rich/_extension.py | 10 + .../pip/_vendor/rich/_inspect.py | 210 + .../pip/_vendor/rich/_log_render.py | 94 + .../site-packages/pip/_vendor/rich/_loop.py | 43 + .../pip/_vendor/rich/_lru_cache.py | 34 + .../pip/_vendor/rich/_palettes.py | 309 + .../site-packages/pip/_vendor/rich/_pick.py | 17 + .../site-packages/pip/_vendor/rich/_ratio.py | 160 + .../pip/_vendor/rich/_spinners.py | 848 ++ .../site-packages/pip/_vendor/rich/_stack.py | 16 + .../site-packages/pip/_vendor/rich/_timer.py | 19 + .../pip/_vendor/rich/_windows.py | 72 + .../site-packages/pip/_vendor/rich/_wrap.py | 55 + .../Lib/site-packages/pip/_vendor/rich/abc.py | 33 + .../site-packages/pip/_vendor/rich/align.py | 312 + .../site-packages/pip/_vendor/rich/ansi.py | 228 + .../Lib/site-packages/pip/_vendor/rich/bar.py | 94 + .../Lib/site-packages/pip/_vendor/rich/box.py | 483 + .../site-packages/pip/_vendor/rich/cells.py | 147 + .../site-packages/pip/_vendor/rich/color.py | 581 + .../pip/_vendor/rich/color_triplet.py | 38 + .../site-packages/pip/_vendor/rich/columns.py | 187 + .../site-packages/pip/_vendor/rich/console.py | 2211 ++++ .../pip/_vendor/rich/constrain.py | 37 + .../pip/_vendor/rich/containers.py | 167 + .../site-packages/pip/_vendor/rich/control.py | 175 + .../pip/_vendor/rich/default_styles.py | 183 + .../pip/_vendor/rich/diagnose.py | 6 + .../site-packages/pip/_vendor/rich/emoji.py | 96 + .../site-packages/pip/_vendor/rich/errors.py | 34 + .../pip/_vendor/rich/file_proxy.py | 54 + .../pip/_vendor/rich/filesize.py | 89 + .../pip/_vendor/rich/highlighter.py | 147 + .../site-packages/pip/_vendor/rich/json.py | 140 + .../site-packages/pip/_vendor/rich/jupyter.py | 92 + .../site-packages/pip/_vendor/rich/layout.py | 444 + .../site-packages/pip/_vendor/rich/live.py | 365 + .../pip/_vendor/rich/live_render.py | 113 + .../site-packages/pip/_vendor/rich/logging.py | 268 + .../site-packages/pip/_vendor/rich/markup.py | 244 + .../site-packages/pip/_vendor/rich/measure.py | 149 + .../site-packages/pip/_vendor/rich/padding.py | 141 + .../site-packages/pip/_vendor/rich/pager.py | 34 + .../site-packages/pip/_vendor/rich/palette.py | 100 + .../site-packages/pip/_vendor/rich/panel.py | 250 + .../site-packages/pip/_vendor/rich/pretty.py | 903 ++ .../pip/_vendor/rich/progress.py | 1036 ++ .../pip/_vendor/rich/progress_bar.py | 216 + .../site-packages/pip/_vendor/rich/prompt.py | 376 + .../pip/_vendor/rich/protocol.py | 42 + .../site-packages/pip/_vendor/rich/region.py | 10 + .../site-packages/pip/_vendor/rich/repr.py | 151 + .../site-packages/pip/_vendor/rich/rule.py | 115 + .../site-packages/pip/_vendor/rich/scope.py | 86 + .../site-packages/pip/_vendor/rich/screen.py | 54 + .../site-packages/pip/_vendor/rich/segment.py | 720 + .../site-packages/pip/_vendor/rich/spinner.py | 134 + .../site-packages/pip/_vendor/rich/status.py | 132 + .../site-packages/pip/_vendor/rich/style.py | 785 ++ .../site-packages/pip/_vendor/rich/styled.py | 42 + .../site-packages/pip/_vendor/rich/syntax.py | 735 ++ .../site-packages/pip/_vendor/rich/table.py | 968 ++ .../pip/_vendor/rich/tabulate.py | 51 + .../pip/_vendor/rich/terminal_theme.py | 55 + .../site-packages/pip/_vendor/rich/text.py | 1282 ++ .../site-packages/pip/_vendor/rich/theme.py | 112 + .../site-packages/pip/_vendor/rich/themes.py | 5 + .../pip/_vendor/rich/traceback.py | 678 + .../site-packages/pip/_vendor/rich/tree.py | 249 + venv/Lib/site-packages/pip/_vendor/six.py | 998 ++ .../pip/_vendor/tenacity/__init__.py | 517 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 16272 bytes .../__pycache__/_asyncio.cpython-39.pyc | Bin 0 -> 2587 bytes .../__pycache__/_utils.cpython-39.pyc | Bin 0 -> 1224 bytes .../tenacity/__pycache__/after.cpython-39.pyc | Bin 0 -> 1203 bytes .../__pycache__/before.cpython-39.pyc | Bin 0 -> 1091 bytes .../__pycache__/before_sleep.cpython-39.pyc | Bin 0 -> 1383 bytes .../tenacity/__pycache__/nap.cpython-39.pyc | Bin 0 -> 1185 bytes .../tenacity/__pycache__/retry.cpython-39.pyc | Bin 0 -> 8773 bytes .../tenacity/__pycache__/stop.cpython-39.pyc | Bin 0 -> 4237 bytes .../__pycache__/tornadoweb.cpython-39.pyc | Bin 0 -> 1737 bytes .../tenacity/__pycache__/wait.cpython-39.pyc | Bin 0 -> 7949 bytes .../pip/_vendor/tenacity/_asyncio.py | 92 + .../pip/_vendor/tenacity/_utils.py | 68 + .../pip/_vendor/tenacity/after.py | 46 + .../pip/_vendor/tenacity/before.py | 41 + .../pip/_vendor/tenacity/before_sleep.py | 58 + .../site-packages/pip/_vendor/tenacity/nap.py | 43 + .../pip/_vendor/tenacity/retry.py | 213 + .../pip/_vendor/tenacity/stop.py | 96 + .../pip/_vendor/tenacity/tornadoweb.py | 59 + .../pip/_vendor/tenacity/wait.py | 191 + .../pip/_vendor/tomli/__init__.py | 6 + .../tomli/__pycache__/__init__.cpython-39.pyc | Bin 0 -> 372 bytes .../tomli/__pycache__/_parser.cpython-39.pyc | Bin 0 -> 16347 bytes .../tomli/__pycache__/_re.cpython-39.pyc | Bin 0 -> 2422 bytes .../pip/_vendor/tomli/_parser.py | 703 + .../site-packages/pip/_vendor/tomli/_re.py | 83 + .../pip/_vendor/typing_extensions.py | 2296 ++++ .../pip/_vendor/urllib3/__init__.py | 85 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 2182 bytes .../__pycache__/_collections.cpython-39.pyc | Bin 0 -> 10777 bytes .../__pycache__/_version.cpython-39.pyc | Bin 0 -> 206 bytes .../__pycache__/connection.cpython-39.pyc | Bin 0 -> 13671 bytes .../__pycache__/connectionpool.cpython-39.pyc | Bin 0 -> 25355 bytes .../__pycache__/exceptions.cpython-39.pyc | Bin 0 -> 11639 bytes .../urllib3/__pycache__/fields.cpython-39.pyc | Bin 0 -> 8154 bytes .../__pycache__/filepost.cpython-39.pyc | Bin 0 -> 2755 bytes .../__pycache__/poolmanager.cpython-39.pyc | Bin 0 -> 15157 bytes .../__pycache__/request.cpython-39.pyc | Bin 0 -> 5618 bytes .../__pycache__/response.cpython-39.pyc | Bin 0 -> 20829 bytes .../pip/_vendor/urllib3/_collections.py | 337 + .../pip/_vendor/urllib3/_version.py | 2 + .../pip/_vendor/urllib3/connection.py | 569 + .../pip/_vendor/urllib3/connectionpool.py | 1108 ++ .../pip/_vendor/urllib3/contrib/__init__.py | 0 .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 192 bytes .../_appengine_environ.cpython-39.pyc | Bin 0 -> 1412 bytes .../__pycache__/appengine.cpython-39.pyc | Bin 0 -> 8265 bytes .../__pycache__/ntlmpool.cpython-39.pyc | Bin 0 -> 3619 bytes .../__pycache__/pyopenssl.cpython-39.pyc | Bin 0 -> 15596 bytes .../securetransport.cpython-39.pyc | Bin 0 -> 21918 bytes .../contrib/__pycache__/socks.cpython-39.pyc | Bin 0 -> 5628 bytes .../urllib3/contrib/_appengine_environ.py | 36 + .../contrib/_securetransport/__init__.py | 0 .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 209 bytes .../__pycache__/bindings.cpython-39.pyc | Bin 0 -> 10701 bytes .../__pycache__/low_level.cpython-39.pyc | Bin 0 -> 9169 bytes .../contrib/_securetransport/bindings.py | 519 + .../contrib/_securetransport/low_level.py | 397 + .../pip/_vendor/urllib3/contrib/appengine.py | 314 + .../pip/_vendor/urllib3/contrib/ntlmpool.py | 130 + .../pip/_vendor/urllib3/contrib/pyopenssl.py | 511 + .../urllib3/contrib/securetransport.py | 922 ++ .../pip/_vendor/urllib3/contrib/socks.py | 216 + .../pip/_vendor/urllib3/exceptions.py | 323 + .../pip/_vendor/urllib3/fields.py | 274 + .../pip/_vendor/urllib3/filepost.py | 98 + .../pip/_vendor/urllib3/packages/__init__.py | 0 .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 193 bytes .../packages/__pycache__/six.cpython-39.pyc | Bin 0 -> 27576 bytes .../urllib3/packages/backports/__init__.py | 0 .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 203 bytes .../__pycache__/makefile.cpython-39.pyc | Bin 0 -> 1301 bytes .../urllib3/packages/backports/makefile.py | 51 + .../pip/_vendor/urllib3/packages/six.py | 1077 ++ .../pip/_vendor/urllib3/poolmanager.py | 536 + .../pip/_vendor/urllib3/request.py | 170 + .../pip/_vendor/urllib3/response.py | 821 ++ .../pip/_vendor/urllib3/util/__init__.py | 49 + .../util/__pycache__/__init__.cpython-39.pyc | Bin 0 -> 1102 bytes .../__pycache__/connection.cpython-39.pyc | Bin 0 -> 3434 bytes .../util/__pycache__/proxy.cpython-39.pyc | Bin 0 -> 1338 bytes .../util/__pycache__/queue.cpython-39.pyc | Bin 0 -> 1057 bytes .../util/__pycache__/request.cpython-39.pyc | Bin 0 -> 3445 bytes .../util/__pycache__/response.cpython-39.pyc | Bin 0 -> 2342 bytes .../util/__pycache__/retry.cpython-39.pyc | Bin 0 -> 16249 bytes .../util/__pycache__/ssl_.cpython-39.pyc | Bin 0 -> 11326 bytes .../ssl_match_hostname.cpython-39.pyc | Bin 0 -> 3276 bytes .../__pycache__/ssltransport.cpython-39.pyc | Bin 0 -> 7472 bytes .../util/__pycache__/timeout.cpython-39.pyc | Bin 0 -> 8940 bytes .../util/__pycache__/url.cpython-39.pyc | Bin 0 -> 10665 bytes .../util/__pycache__/wait.cpython-39.pyc | Bin 0 -> 3125 bytes .../pip/_vendor/urllib3/util/connection.py | 149 + .../pip/_vendor/urllib3/util/proxy.py | 57 + .../pip/_vendor/urllib3/util/queue.py | 22 + .../pip/_vendor/urllib3/util/request.py | 143 + .../pip/_vendor/urllib3/util/response.py | 107 + .../pip/_vendor/urllib3/util/retry.py | 620 + .../pip/_vendor/urllib3/util/ssl_.py | 495 + .../urllib3/util/ssl_match_hostname.py | 161 + .../pip/_vendor/urllib3/util/ssltransport.py | 221 + .../pip/_vendor/urllib3/util/timeout.py | 268 + .../pip/_vendor/urllib3/util/url.py | 432 + .../pip/_vendor/urllib3/util/wait.py | 153 + venv/Lib/site-packages/pip/_vendor/vendor.txt | 25 + .../pip/_vendor/webencodings/__init__.py | 342 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 9716 bytes .../__pycache__/labels.cpython-39.pyc | Bin 0 -> 3830 bytes .../__pycache__/mklabels.cpython-39.pyc | Bin 0 -> 1900 bytes .../__pycache__/tests.cpython-39.pyc | Bin 0 -> 5064 bytes .../__pycache__/x_user_defined.cpython-39.pyc | Bin 0 -> 2660 bytes .../pip/_vendor/webencodings/labels.py | 231 + .../pip/_vendor/webencodings/mklabels.py | 59 + .../pip/_vendor/webencodings/tests.py | 153 + .../_vendor/webencodings/x_user_defined.py | 325 + venv/Lib/site-packages/pip/py.typed | 4 + .../site-packages/pkg_resources/__init__.py | 3283 +++++ .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 100702 bytes .../pkg_resources/_vendor/__init__.py | 0 .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 186 bytes .../__pycache__/appdirs.cpython-39.pyc | Bin 0 -> 20503 bytes .../__pycache__/pyparsing.cpython-39.pyc | Bin 0 -> 201339 bytes .../_vendor/__pycache__/zipp.cpython-39.pyc | Bin 0 -> 10336 bytes .../pkg_resources/_vendor/appdirs.py | 608 + .../_vendor/importlib_resources/__init__.py | 36 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 641 bytes .../__pycache__/_adapters.cpython-39.pyc | Bin 0 -> 7489 bytes .../__pycache__/_common.cpython-39.pyc | Bin 0 -> 2631 bytes .../__pycache__/_compat.cpython-39.pyc | Bin 0 -> 3483 bytes .../__pycache__/_itertools.cpython-39.pyc | Bin 0 -> 864 bytes .../__pycache__/_legacy.cpython-39.pyc | Bin 0 -> 4201 bytes .../__pycache__/abc.cpython-39.pyc | Bin 0 -> 5439 bytes .../__pycache__/readers.cpython-39.pyc | Bin 0 -> 5555 bytes .../__pycache__/simple.cpython-39.pyc | Bin 0 -> 4751 bytes .../_vendor/importlib_resources/_adapters.py | 170 + .../_vendor/importlib_resources/_common.py | 104 + .../_vendor/importlib_resources/_compat.py | 98 + .../_vendor/importlib_resources/_itertools.py | 35 + .../_vendor/importlib_resources/_legacy.py | 121 + .../_vendor/importlib_resources/abc.py | 137 + .../_vendor/importlib_resources/readers.py | 122 + .../_vendor/importlib_resources/simple.py | 116 + .../pkg_resources/_vendor/jaraco/__init__.py | 0 .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 193 bytes .../jaraco/__pycache__/context.cpython-39.pyc | Bin 0 -> 6278 bytes .../__pycache__/functools.cpython-39.pyc | Bin 0 -> 15655 bytes .../pkg_resources/_vendor/jaraco/context.py | 213 + .../pkg_resources/_vendor/jaraco/functools.py | 525 + .../_vendor/jaraco/text/__init__.py | 599 + .../text/__pycache__/__init__.cpython-39.pyc | Bin 0 -> 19684 bytes .../_vendor/more_itertools/__init__.py | 4 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 268 bytes .../__pycache__/more.cpython-39.pyc | Bin 0 -> 123089 bytes .../__pycache__/recipes.cpython-39.pyc | Bin 0 -> 20274 bytes .../_vendor/more_itertools/more.py | 4316 ++++++ .../_vendor/more_itertools/recipes.py | 698 + .../_vendor/packaging/__about__.py | 26 + .../_vendor/packaging/__init__.py | 25 + .../__pycache__/__about__.cpython-39.pyc | Bin 0 -> 593 bytes .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 449 bytes .../__pycache__/_manylinux.cpython-39.pyc | Bin 0 -> 7297 bytes .../__pycache__/_musllinux.cpython-39.pyc | Bin 0 -> 4612 bytes .../__pycache__/_structures.cpython-39.pyc | Bin 0 -> 2806 bytes .../__pycache__/markers.cpython-39.pyc | Bin 0 -> 9465 bytes .../__pycache__/requirements.cpython-39.pyc | Bin 0 -> 3986 bytes .../__pycache__/specifiers.cpython-39.pyc | Bin 0 -> 21524 bytes .../packaging/__pycache__/tags.cpython-39.pyc | Bin 0 -> 12255 bytes .../__pycache__/utils.cpython-39.pyc | Bin 0 -> 3614 bytes .../__pycache__/version.cpython-39.pyc | Bin 0 -> 13155 bytes .../_vendor/packaging/_manylinux.py | 301 + .../_vendor/packaging/_musllinux.py | 136 + .../_vendor/packaging/_structures.py | 61 + .../_vendor/packaging/markers.py | 304 + .../_vendor/packaging/requirements.py | 146 + .../_vendor/packaging/specifiers.py | 802 ++ .../pkg_resources/_vendor/packaging/tags.py | 487 + .../pkg_resources/_vendor/packaging/utils.py | 136 + .../_vendor/packaging/version.py | 504 + .../pkg_resources/_vendor/pyparsing.py | 5742 ++++++++ .../pkg_resources/_vendor/zipp.py | 329 + .../pkg_resources/extern/__init__.py | 76 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 2920 bytes .../pygame-2.1.2.dist-info/INSTALLER | 1 + .../pygame-2.1.2.dist-info/METADATA | 228 + .../pygame-2.1.2.dist-info/RECORD | 747 ++ .../pygame-2.1.2.dist-info/REQUESTED | 0 .../pygame-2.1.2.dist-info/WHEEL | 5 + .../pygame-2.1.2.dist-info/entry_points.txt | 3 + .../pygame-2.1.2.dist-info/top_level.txt | 1 + venv/Lib/site-packages/pygame/SDL2.dll | Bin 0 -> 2227712 bytes venv/Lib/site-packages/pygame/SDL2_image.dll | Bin 0 -> 125440 bytes venv/Lib/site-packages/pygame/SDL2_mixer.dll | Bin 0 -> 123904 bytes venv/Lib/site-packages/pygame/SDL2_ttf.dll | Bin 0 -> 33792 bytes venv/Lib/site-packages/pygame/__init__.py | 371 + venv/Lib/site-packages/pygame/__init__.pyi | 74 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 8069 bytes .../__pycache__/_camera_opencv.cpython-39.pyc | Bin 0 -> 4415 bytes .../_camera_vidcapture.cpython-39.pyc | Bin 0 -> 4034 bytes .../pygame/__pycache__/camera.cpython-39.pyc | Bin 0 -> 4450 bytes .../__pycache__/colordict.cpython-39.pyc | Bin 0 -> 21569 bytes .../pygame/__pycache__/cursors.cpython-39.pyc | Bin 0 -> 11807 bytes .../pygame/__pycache__/draw_py.cpython-39.pyc | Bin 0 -> 12476 bytes .../__pycache__/fastevent.cpython-39.pyc | Bin 0 -> 2380 bytes .../__pycache__/freetype.cpython-39.pyc | Bin 0 -> 2274 bytes .../pygame/__pycache__/ftfont.cpython-39.pyc | Bin 0 -> 6451 bytes .../pygame/__pycache__/locals.cpython-39.pyc | Bin 0 -> 7662 bytes .../pygame/__pycache__/macosx.cpython-39.pyc | Bin 0 -> 662 bytes .../pygame/__pycache__/midi.cpython-39.pyc | Bin 0 -> 22986 bytes .../pygame/__pycache__/pkgdata.cpython-39.pyc | Bin 0 -> 2537 bytes .../__pycache__/sndarray.cpython-39.pyc | Bin 0 -> 3257 bytes .../pygame/__pycache__/sprite.cpython-39.pyc | Bin 0 -> 50688 bytes .../__pycache__/surfarray.cpython-39.pyc | Bin 0 -> 13044 bytes .../pygame/__pycache__/sysfont.cpython-39.pyc | Bin 0 -> 10383 bytes .../pygame/__pycache__/version.cpython-39.pyc | Bin 0 -> 2513 bytes .../pygame/__pyinstaller/__init__.py | 5 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 361 bytes .../__pycache__/hook-pygame.cpython-39.pyc | Bin 0 -> 1156 bytes .../pygame/__pyinstaller/hook-pygame.py | 44 + .../pygame/_camera.cp39-win_amd64.pyd | Bin 0 -> 31232 bytes .../site-packages/pygame/_camera_opencv.py | 174 + .../pygame/_camera_vidcapture.py | 117 + venv/Lib/site-packages/pygame/_common.pyi | 34 + .../pygame/_freetype.cp39-win_amd64.pyd | Bin 0 -> 78336 bytes .../site-packages/pygame/_sdl2/__init__.py | 3 + .../site-packages/pygame/_sdl2/__init__.pyi | 1 + .../_sdl2/__pycache__/__init__.cpython-39.pyc | Bin 0 -> 249 bytes .../pygame/_sdl2/audio.cp39-win_amd64.pyd | Bin 0 -> 139776 bytes .../_sdl2/controller.cp39-win_amd64.pyd | Bin 0 -> 71680 bytes .../site-packages/pygame/_sdl2/controller.pyi | 30 + .../pygame/_sdl2/mixer.cp39-win_amd64.pyd | Bin 0 -> 121344 bytes .../pygame/_sdl2/sdl2.cp39-win_amd64.pyd | Bin 0 -> 36864 bytes .../pygame/_sdl2/touch.cp39-win_amd64.pyd | Bin 0 -> 13824 bytes venv/Lib/site-packages/pygame/_sdl2/touch.pyi | 6 + .../pygame/_sdl2/video.cp39-win_amd64.pyd | Bin 0 -> 184320 bytes venv/Lib/site-packages/pygame/_sdl2/video.pyi | 154 + .../pygame/_sprite.cp39-win_amd64.pyd | Bin 0 -> 251904 bytes .../pygame/base.cp39-win_amd64.pyd | Bin 0 -> 30720 bytes .../pygame/bufferproxy.cp39-win_amd64.pyd | Bin 0 -> 18432 bytes venv/Lib/site-packages/pygame/bufferproxy.pyi | 10 + venv/Lib/site-packages/pygame/camera.py | 194 + venv/Lib/site-packages/pygame/camera.pyi | 29 + .../pygame/color.cp39-win_amd64.pyd | Bin 0 -> 35328 bytes venv/Lib/site-packages/pygame/color.pyi | 40 + venv/Lib/site-packages/pygame/colordict.py | 692 + .../pygame/constants.cp39-win_amd64.pyd | Bin 0 -> 49152 bytes venv/Lib/site-packages/pygame/constants.pyi | 557 + venv/Lib/site-packages/pygame/cursors.py | 840 ++ venv/Lib/site-packages/pygame/cursors.pyi | 86 + .../pygame/display.cp39-win_amd64.pyd | Bin 0 -> 44032 bytes venv/Lib/site-packages/pygame/display.pyi | 68 + .../Lib/site-packages/pygame/docs/__main__.py | 38 + .../docs/__pycache__/__main__.cpython-39.pyc | Bin 0 -> 1184 bytes .../_images/AdvancedInputOutput1.gif | Bin 0 -> 5649 bytes .../_images/AdvancedInputOutput11.gif | Bin 0 -> 5649 bytes .../_images/AdvancedInputOutput2.gif | Bin 0 -> 72233 bytes .../_images/AdvancedInputOutput21.gif | Bin 0 -> 72233 bytes .../_images/AdvancedInputOutput3.gif | Bin 0 -> 6294 bytes .../_images/AdvancedInputOutput31.gif | Bin 0 -> 6294 bytes .../_images/AdvancedInputOutput4.gif | Bin 0 -> 29185 bytes .../_images/AdvancedInputOutput41.gif | Bin 0 -> 29185 bytes .../_images/AdvancedInputOutput5.gif | Bin 0 -> 37349 bytes .../_images/AdvancedInputOutput51.gif | Bin 0 -> 37349 bytes .../_images/AdvancedOutputAlpha1.gif | Bin 0 -> 14915 bytes .../_images/AdvancedOutputAlpha11.gif | Bin 0 -> 14915 bytes .../_images/AdvancedOutputAlpha2.gif | Bin 0 -> 71819 bytes .../_images/AdvancedOutputAlpha21.gif | Bin 0 -> 71819 bytes .../_images/AdvancedOutputAlpha3.gif | Bin 0 -> 30380 bytes .../_images/AdvancedOutputAlpha31.gif | Bin 0 -> 30380 bytes .../_images/AdvancedOutputProcess1.gif | Bin 0 -> 15951 bytes .../_images/AdvancedOutputProcess11.gif | Bin 0 -> 15951 bytes .../_images/AdvancedOutputProcess2.gif | Bin 0 -> 1868 bytes .../_images/AdvancedOutputProcess21.gif | Bin 0 -> 1868 bytes .../_images/AdvancedOutputProcess3.gif | Bin 0 -> 1912 bytes .../_images/AdvancedOutputProcess31.gif | Bin 0 -> 1912 bytes .../_images/AdvancedOutputProcess4.gif | Bin 0 -> 14500 bytes .../_images/AdvancedOutputProcess41.gif | Bin 0 -> 14500 bytes .../_images/AdvancedOutputProcess5.gif | Bin 0 -> 16896 bytes .../_images/AdvancedOutputProcess51.gif | Bin 0 -> 16896 bytes .../_images/AdvancedOutputProcess6.gif | Bin 0 -> 34058 bytes .../_images/AdvancedOutputProcess61.gif | Bin 0 -> 34058 bytes .../_images/Bagic-INPUT-resultscreen.png | Bin 0 -> 5973 bytes .../_images/Bagic-INPUT-resultscreen1.png | Bin 0 -> 5973 bytes .../_images/Bagic-INPUT-sourcecode.png | Bin 0 -> 77061 bytes .../_images/Bagic-INPUT-sourcecode1.png | Bin 0 -> 77061 bytes .../_images/Bagic-PROCESS-resultscreen.png | Bin 0 -> 5348 bytes .../_images/Bagic-PROCESS-resultscreen1.png | Bin 0 -> 5348 bytes .../_images/Bagic-PROCESS-sourcecode.png | Bin 0 -> 66070 bytes .../_images/Bagic-PROCESS-sourcecode1.png | Bin 0 -> 66070 bytes .../_images/Bagic-ouput-result-screen.png | Bin 0 -> 4819 bytes .../_images/Bagic-ouput-result-screen1.png | Bin 0 -> 4819 bytes .../_images/Basic-ouput-sourcecode.png | Bin 0 -> 57466 bytes .../_images/Basic-ouput-sourcecode1.png | Bin 0 -> 57466 bytes .../docs/generated/_images/camera_average.jpg | Bin 0 -> 20881 bytes .../generated/_images/camera_background.jpg | Bin 0 -> 7493 bytes .../docs/generated/_images/camera_green.jpg | Bin 0 -> 10219 bytes .../docs/generated/_images/camera_hsv.jpg | Bin 0 -> 36673 bytes .../docs/generated/_images/camera_mask.jpg | Bin 0 -> 18779 bytes .../docs/generated/_images/camera_rgb.jpg | Bin 0 -> 32488 bytes .../docs/generated/_images/camera_thresh.jpg | Bin 0 -> 4346 bytes .../generated/_images/camera_thresholded.jpg | Bin 0 -> 23678 bytes .../docs/generated/_images/camera_yuv.jpg | Bin 0 -> 20105 bytes .../docs/generated/_images/chimpshot.gif | Bin 0 -> 46010 bytes .../generated/_images/draw_module_example.png | Bin 0 -> 7727 bytes .../docs/generated/_images/intro_ball.gif | Bin 0 -> 5015 bytes .../docs/generated/_images/intro_blade.jpg | Bin 0 -> 2631 bytes .../docs/generated/_images/intro_freedom.jpg | Bin 0 -> 7050 bytes .../_images/introduction-Battleship.png | Bin 0 -> 165586 bytes .../_images/introduction-Battleship1.png | Bin 0 -> 165586 bytes .../_images/introduction-PuyoPuyo.png | Bin 0 -> 31388 bytes .../_images/introduction-PuyoPuyo1.png | Bin 0 -> 31388 bytes .../generated/_images/introduction-TPS.png | Bin 0 -> 136031 bytes .../generated/_images/introduction-TPS1.png | Bin 0 -> 136031 bytes .../docs/generated/_images/joystick_calls.png | Bin 0 -> 23524 bytes .../generated/_images/surfarray_allblack.png | Bin 0 -> 125 bytes .../generated/_images/surfarray_flipped.png | Bin 0 -> 50835 bytes .../generated/_images/surfarray_redimg.png | Bin 0 -> 23443 bytes .../generated/_images/surfarray_rgbarray.png | Bin 0 -> 50897 bytes .../generated/_images/surfarray_scaledown.png | Bin 0 -> 15109 bytes .../generated/_images/surfarray_scaleup.png | Bin 0 -> 67759 bytes .../generated/_images/surfarray_soften.png | Bin 0 -> 47540 bytes .../generated/_images/surfarray_striped.png | Bin 0 -> 392 bytes .../generated/_images/surfarray_xfade.png | Bin 0 -> 41834 bytes .../docs/generated/_images/tom_basic.png | Bin 0 -> 5139 bytes .../generated/_images/tom_event-flowchart.png | Bin 0 -> 5528 bytes .../docs/generated/_images/tom_formulae.png | Bin 0 -> 6763 bytes .../docs/generated/_images/tom_radians.png | Bin 0 -> 17409 bytes .../docs/generated/_sources/c_api.rst.txt | 26 + .../docs/generated/_sources/filepaths.rst.txt | 17 + .../docs/generated/_sources/index.rst.txt | 190 + .../_sources/ref/bufferproxy.rst.txt | 113 + .../generated/_sources/ref/camera.rst.txt | 247 + .../docs/generated/_sources/ref/cdrom.rst.txt | 310 + .../docs/generated/_sources/ref/color.rst.txt | 266 + .../generated/_sources/ref/color_list.rst.txt | 2014 +++ .../generated/_sources/ref/cursors.rst.txt | 250 + .../generated/_sources/ref/display.rst.txt | 716 + .../docs/generated/_sources/ref/draw.rst.txt | 559 + .../docs/generated/_sources/ref/event.rst.txt | 476 + .../generated/_sources/ref/examples.rst.txt | 451 + .../generated/_sources/ref/fastevent.rst.txt | 109 + .../docs/generated/_sources/ref/font.rst.txt | 405 + .../generated/_sources/ref/freetype.rst.txt | 766 ++ .../generated/_sources/ref/gfxdraw.rst.txt | 628 + .../docs/generated/_sources/ref/image.rst.txt | 284 + .../generated/_sources/ref/joystick.rst.txt | 545 + .../docs/generated/_sources/ref/key.rst.txt | 430 + .../generated/_sources/ref/locals.rst.txt | 27 + .../docs/generated/_sources/ref/mask.rst.txt | 642 + .../docs/generated/_sources/ref/math.rst.txt | 880 ++ .../docs/generated/_sources/ref/midi.rst.txt | 484 + .../docs/generated/_sources/ref/mixer.rst.txt | 604 + .../docs/generated/_sources/ref/mouse.rst.txt | 219 + .../docs/generated/_sources/ref/music.rst.txt | 274 + .../generated/_sources/ref/overlay.rst.txt | 79 + .../generated/_sources/ref/pixelarray.rst.txt | 295 + .../generated/_sources/ref/pixelcopy.rst.txt | 104 + .../generated/_sources/ref/pygame.rst.txt | 488 + .../docs/generated/_sources/ref/rect.rst.txt | 391 + .../docs/generated/_sources/ref/scrap.rst.txt | 240 + .../_sources/ref/sdl2_controller.rst.txt | 287 + .../generated/_sources/ref/sdl2_video.rst.txt | 334 + .../generated/_sources/ref/sndarray.rst.txt | 95 + .../generated/_sources/ref/sprite.rst.txt | 879 ++ .../generated/_sources/ref/surface.rst.txt | 902 ++ .../generated/_sources/ref/surfarray.rst.txt | 337 + .../docs/generated/_sources/ref/tests.rst.txt | 108 + .../docs/generated/_sources/ref/time.rst.txt | 165 + .../docs/generated/_sources/ref/touch.rst.txt | 66 + .../generated/_sources/ref/transform.rst.txt | 271 + .../pygame/docs/generated/_static/basic.css | 905 ++ .../pygame/docs/generated/_static/doctools.js | 323 + .../_static/documentation_options.js | 12 + .../pygame/docs/generated/_static/file.png | Bin 0 -> 286 bytes .../docs/generated/_static/jquery-3.5.1.js | 10872 ++++++++++++++++ .../pygame/docs/generated/_static/jquery.js | 2 + .../docs/generated/_static/language_data.js | 297 + .../pygame/docs/generated/_static/minus.png | Bin 0 -> 90 bytes .../pygame/docs/generated/_static/plus.png | Bin 0 -> 90 bytes .../pygame/docs/generated/_static/pygame.css | 680 + .../pygame/docs/generated/_static/pygame.ico | Bin 0 -> 1078 bytes .../docs/generated/_static/pygame_tiny.png | Bin 0 -> 15310 bytes .../docs/generated/_static/pygments.css | 74 + .../pygame/docs/generated/_static/reset.css | 49 + .../docs/generated/_static/searchtools.js | 529 + .../pygame/docs/generated/_static/tooltip.css | 44 + .../generated/_static/underscore-1.13.1.js | 2042 +++ .../docs/generated/_static/underscore.js | 6 + .../pygame/docs/generated/c_api.html | 157 + .../pygame/docs/generated/c_api/base.html | 365 + .../docs/generated/c_api/bufferproxy.html | 183 + .../pygame/docs/generated/c_api/cdrom.html | 178 + .../pygame/docs/generated/c_api/color.html | 172 + .../pygame/docs/generated/c_api/display.html | 177 + .../pygame/docs/generated/c_api/event.html | 192 + .../pygame/docs/generated/c_api/freetype.html | 180 + .../pygame/docs/generated/c_api/mixer.html | 213 + .../pygame/docs/generated/c_api/rect.html | 202 + .../pygame/docs/generated/c_api/rwobject.html | 207 + .../pygame/docs/generated/c_api/slots.html | 157 + .../pygame/docs/generated/c_api/surface.html | 194 + .../pygame/docs/generated/c_api/surflock.html | 231 + .../pygame/docs/generated/c_api/version.html | 173 + .../pygame/docs/generated/filepaths.html | 145 + .../pygame/docs/generated/genindex.html | 2604 ++++ .../pygame/docs/generated/index.html | 258 + .../pygame/docs/generated/py-modindex.html | 251 + .../docs/generated/ref/bufferproxy.html | 283 + .../pygame/docs/generated/ref/camera.html | 472 + .../pygame/docs/generated/ref/cdrom.html | 592 + .../pygame/docs/generated/ref/color.html | 508 + .../pygame/docs/generated/ref/color_list.html | 2813 ++++ .../pygame/docs/generated/ref/cursors.html | 452 + .../pygame/docs/generated/ref/display.html | 990 ++ .../pygame/docs/generated/ref/draw.html | 971 ++ .../pygame/docs/generated/ref/event.html | 715 + .../pygame/docs/generated/ref/examples.html | 712 + .../pygame/docs/generated/ref/fastevent.html | 286 + .../pygame/docs/generated/ref/font.html | 698 + .../pygame/docs/generated/ref/freetype.html | 1270 ++ .../pygame/docs/generated/ref/gfxdraw.html | 1058 ++ .../pygame/docs/generated/ref/image.html | 459 + .../pygame/docs/generated/ref/joystick.html | 984 ++ .../pygame/docs/generated/ref/key.html | 628 + .../pygame/docs/generated/ref/locals.html | 161 + .../pygame/docs/generated/ref/mask.html | 1123 ++ .../pygame/docs/generated/ref/math.html | 1509 +++ .../pygame/docs/generated/ref/midi.html | 845 ++ .../pygame/docs/generated/ref/mixer.html | 995 ++ .../pygame/docs/generated/ref/mouse.html | 406 + .../pygame/docs/generated/ref/music.html | 502 + .../pygame/docs/generated/ref/overlay.html | 231 + .../pygame/docs/generated/ref/pixelarray.html | 486 + .../pygame/docs/generated/ref/pixelcopy.html | 262 + .../pygame/docs/generated/ref/pygame.html | 693 + .../pygame/docs/generated/ref/rect.html | 672 + .../pygame/docs/generated/ref/scrap.html | 458 + .../docs/generated/ref/sdl2_controller.html | 569 + .../pygame/docs/generated/ref/sdl2_video.html | 1091 ++ .../pygame/docs/generated/ref/sndarray.html | 274 + .../pygame/docs/generated/ref/sprite.html | 1381 ++ .../pygame/docs/generated/ref/surface.html | 1290 ++ .../pygame/docs/generated/ref/surfarray.html | 571 + .../pygame/docs/generated/ref/tests.html | 241 + .../pygame/docs/generated/ref/time.html | 370 + .../pygame/docs/generated/ref/touch.html | 240 + .../pygame/docs/generated/ref/transform.html | 535 + .../pygame/docs/generated/search.html | 96 + .../pygame/docs/generated/searchindex.js | 1 + .../docs/generated/tut/CameraIntro.html | 378 + .../docs/generated/tut/ChimpLineByLine.html | 597 + .../docs/generated/tut/DisplayModes.html | 314 + .../pygame/docs/generated/tut/ImportInit.html | 197 + .../pygame/docs/generated/tut/MakeGames.html | 237 + .../pygame/docs/generated/tut/MoveIt.html | 539 + .../docs/generated/tut/PygameIntro.html | 418 + .../docs/generated/tut/SpriteIntro.html | 498 + .../docs/generated/tut/SurfarrayIntro.html | 661 + .../pygame/docs/generated/tut/chimp.py.html | 342 + .../docs/generated/tut/newbieguide.html | 475 + .../pygame/docs/generated/tut/tom_games2.html | 240 + .../pygame/docs/generated/tut/tom_games3.html | 220 + .../pygame/docs/generated/tut/tom_games4.html | 249 + .../pygame/docs/generated/tut/tom_games5.html | 238 + .../pygame/docs/generated/tut/tom_games6.html | 436 + .../pygame/draw.cp39-win_amd64.pyd | Bin 0 -> 48128 bytes venv/Lib/site-packages/pygame/draw.pyi | 74 + venv/Lib/site-packages/pygame/draw_py.py | 564 + .../pygame/event.cp39-win_amd64.pyd | Bin 0 -> 40448 bytes venv/Lib/site-packages/pygame/event.pyi | 32 + .../site-packages/pygame/examples/README.rst | 142 + .../site-packages/pygame/examples/__init__.py | 0 .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 197 bytes .../__pycache__/aacircle.cpython-39.pyc | Bin 0 -> 1097 bytes .../__pycache__/aliens.cpython-39.pyc | Bin 0 -> 9945 bytes .../__pycache__/arraydemo.cpython-39.pyc | Bin 0 -> 2747 bytes .../__pycache__/audiocapture.cpython-39.pyc | Bin 0 -> 1675 bytes .../__pycache__/blend_fill.cpython-39.pyc | Bin 0 -> 2630 bytes .../__pycache__/blit_blends.cpython-39.pyc | Bin 0 -> 3900 bytes .../__pycache__/camera.cpython-39.pyc | Bin 0 -> 2385 bytes .../examples/__pycache__/chimp.cpython-39.pyc | Bin 0 -> 5806 bytes .../__pycache__/cursors.cpython-39.pyc | Bin 0 -> 2504 bytes .../__pycache__/dropevent.cpython-39.pyc | Bin 0 -> 1638 bytes .../__pycache__/eventlist.cpython-39.pyc | Bin 0 -> 4876 bytes .../__pycache__/font_viewer.cpython-39.pyc | Bin 0 -> 7593 bytes .../examples/__pycache__/fonty.cpython-39.pyc | Bin 0 -> 1494 bytes .../__pycache__/freetype_misc.cpython-39.pyc | Bin 0 -> 2982 bytes .../__pycache__/glcube.cpython-39.pyc | Bin 0 -> 12720 bytes .../headless_no_windows_needed.cpython-39.pyc | Bin 0 -> 1443 bytes .../__pycache__/joystick.cpython-39.pyc | Bin 0 -> 3214 bytes .../__pycache__/liquid.cpython-39.pyc | Bin 0 -> 1850 bytes .../examples/__pycache__/mask.cpython-39.pyc | Bin 0 -> 5661 bytes .../examples/__pycache__/midi.cpython-39.pyc | Bin 0 -> 19586 bytes .../__pycache__/moveit.cpython-39.pyc | Bin 0 -> 2034 bytes .../music_drop_fade.cpython-39.pyc | Bin 0 -> 6579 bytes .../__pycache__/pixelarray.cpython-39.pyc | Bin 0 -> 2506 bytes .../__pycache__/playmus.cpython-39.pyc | Bin 0 -> 4294 bytes .../prevent_display_stretching.cpython-39.pyc | Bin 0 -> 2068 bytes .../__pycache__/resizing_new.cpython-39.pyc | Bin 0 -> 1048 bytes .../__pycache__/scaletest.cpython-39.pyc | Bin 0 -> 3314 bytes .../scrap_clipboard.cpython-39.pyc | Bin 0 -> 2599 bytes .../__pycache__/scroll.cpython-39.pyc | Bin 0 -> 4512 bytes .../__pycache__/setmodescale.cpython-39.pyc | Bin 0 -> 1838 bytes .../examples/__pycache__/sound.cpython-39.pyc | Bin 0 -> 1269 bytes .../sound_array_demos.cpython-39.pyc | Bin 0 -> 3755 bytes .../__pycache__/sprite_texture.cpython-39.pyc | Bin 0 -> 2690 bytes .../examples/__pycache__/stars.cpython-39.pyc | Bin 0 -> 2756 bytes .../__pycache__/testsprite.cpython-39.pyc | Bin 0 -> 4906 bytes .../__pycache__/textinput.cpython-39.pyc | Bin 0 -> 3097 bytes .../__pycache__/vgrade.cpython-39.pyc | Bin 0 -> 3298 bytes .../examples/__pycache__/video.cpython-39.pyc | Bin 0 -> 3406 bytes .../site-packages/pygame/examples/aacircle.py | 41 + .../site-packages/pygame/examples/aliens.py | 401 + .../pygame/examples/arraydemo.py | 129 + .../pygame/examples/audiocapture.py | 78 + .../pygame/examples/blend_fill.py | 115 + .../pygame/examples/blit_blends.py | 198 + .../site-packages/pygame/examples/camera.py | 105 + .../site-packages/pygame/examples/chimp.py | 203 + .../site-packages/pygame/examples/cursors.py | 105 + .../pygame/examples/data/BGR.png | Bin 0 -> 244 bytes .../pygame/examples/data/alien1.gif | Bin 0 -> 3826 bytes .../pygame/examples/data/alien1.jpg | Bin 0 -> 3103 bytes .../pygame/examples/data/alien1.png | Bin 0 -> 3522 bytes .../pygame/examples/data/alien2.gif | Bin 0 -> 3834 bytes .../pygame/examples/data/alien2.png | Bin 0 -> 3526 bytes .../pygame/examples/data/alien3.gif | Bin 0 -> 3829 bytes .../pygame/examples/data/alien3.png | Bin 0 -> 3518 bytes .../pygame/examples/data/arraydemo.bmp | Bin 0 -> 76854 bytes .../pygame/examples/data/asprite.bmp | Bin 0 -> 578 bytes .../pygame/examples/data/background.gif | Bin 0 -> 9133 bytes .../pygame/examples/data/black.ppm | 3076 +++++ .../pygame/examples/data/blue.gif | Bin 0 -> 84 bytes .../pygame/examples/data/blue.mpg | Bin 0 -> 6144 bytes .../pygame/examples/data/bomb.gif | Bin 0 -> 1170 bytes .../pygame/examples/data/boom.wav | Bin 0 -> 12562 bytes .../pygame/examples/data/brick.png | Bin 0 -> 170 bytes .../pygame/examples/data/car_door.wav | Bin 0 -> 3910 bytes .../pygame/examples/data/chimp.png | Bin 0 -> 826 bytes .../pygame/examples/data/city.png | Bin 0 -> 143 bytes .../pygame/examples/data/crimson.pnm | 5 + .../pygame/examples/data/danger.gif | Bin 0 -> 2761 bytes .../pygame/examples/data/explosion1.gif | Bin 0 -> 6513 bytes .../pygame/examples/data/fist.png | Bin 0 -> 86196 bytes .../pygame/examples/data/green.pcx | Bin 0 -> 320 bytes .../pygame/examples/data/grey.pgm | 1028 ++ .../pygame/examples/data/house_lo.mp3 | Bin 0 -> 116320 bytes .../pygame/examples/data/house_lo.ogg | Bin 0 -> 31334 bytes .../pygame/examples/data/house_lo.wav | Bin 0 -> 78464 bytes .../pygame/examples/data/laplacian.png | Bin 0 -> 253 bytes .../pygame/examples/data/liquid.bmp | Bin 0 -> 11734 bytes .../pygame/examples/data/midikeys.png | Bin 0 -> 19666 bytes .../pygame/examples/data/player1.gif | Bin 0 -> 3470 bytes .../pygame/examples/data/punch.wav | Bin 0 -> 4176 bytes .../pygame/examples/data/purple.xpm | 36 + .../pygame/examples/data/red.jpg | Bin 0 -> 1251 bytes .../pygame/examples/data/sans.ttf | Bin 0 -> 133088 bytes .../pygame/examples/data/scarlet.webp | Bin 0 -> 82 bytes .../pygame/examples/data/secosmic_lo.wav | Bin 0 -> 18700 bytes .../pygame/examples/data/shot.gif | Bin 0 -> 129 bytes .../pygame/examples/data/static.png | Bin 0 -> 1202 bytes .../pygame/examples/data/teal.svg | 9 + .../pygame/examples/data/turquoise.tif | Bin 0 -> 1186 bytes .../pygame/examples/data/whiff.wav | Bin 0 -> 5850 bytes .../pygame/examples/data/yellow.tga | Bin 0 -> 3116 bytes .../pygame/examples/dropevent.py | 76 + .../pygame/examples/eventlist.py | 196 + .../pygame/examples/font_viewer.py | 279 + .../site-packages/pygame/examples/fonty.py | 80 + .../pygame/examples/freetype_misc.py | 157 + .../site-packages/pygame/examples/glcube.py | 591 + .../examples/headless_no_windows_needed.py | 50 + .../site-packages/pygame/examples/joystick.py | 149 + .../site-packages/pygame/examples/liquid.py | 89 + .../Lib/site-packages/pygame/examples/mask.py | 212 + .../Lib/site-packages/pygame/examples/midi.py | 877 ++ .../site-packages/pygame/examples/moveit.py | 72 + .../pygame/examples/music_drop_fade.py | 249 + .../pygame/examples/pixelarray.py | 142 + .../site-packages/pygame/examples/playmus.py | 165 + .../examples/prevent_display_stretching.py | 93 + .../pygame/examples/resizing_new.py | 44 + .../pygame/examples/scaletest.py | 158 + .../pygame/examples/scrap_clipboard.py | 94 + .../site-packages/pygame/examples/scroll.py | 192 + .../pygame/examples/setmodescale.py | 67 + .../site-packages/pygame/examples/sound.py | 45 + .../pygame/examples/sound_array_demos.py | 217 + .../pygame/examples/sprite_texture.py | 104 + .../site-packages/pygame/examples/stars.py | 103 + .../pygame/examples/testsprite.py | 261 + .../pygame/examples/textinput.py | 174 + .../site-packages/pygame/examples/vgrade.py | 102 + .../site-packages/pygame/examples/video.py | 162 + venv/Lib/site-packages/pygame/fastevent.py | 88 + venv/Lib/site-packages/pygame/fastevent.pyi | 11 + .../pygame/font.cp39-win_amd64.pyd | Bin 0 -> 24064 bytes venv/Lib/site-packages/pygame/font.pyi | 50 + .../Lib/site-packages/pygame/freesansbold.ttf | Bin 0 -> 98600 bytes venv/Lib/site-packages/pygame/freetype.py | 78 + venv/Lib/site-packages/pygame/freetype.pyi | 122 + venv/Lib/site-packages/pygame/ftfont.py | 203 + .../pygame/gfxdraw.cp39-win_amd64.pyd | Bin 0 -> 57856 bytes venv/Lib/site-packages/pygame/gfxdraw.pyi | 91 + .../pygame/image.cp39-win_amd64.pyd | Bin 0 -> 28160 bytes venv/Lib/site-packages/pygame/image.pyi | 35 + .../pygame/imageext.cp39-win_amd64.pyd | Bin 0 -> 19456 bytes .../pygame/joystick.cp39-win_amd64.pyd | Bin 0 -> 20480 bytes venv/Lib/site-packages/pygame/joystick.pyi | 29 + .../pygame/key.cp39-win_amd64.pyd | Bin 0 -> 26624 bytes venv/Lib/site-packages/pygame/key.pyi | 15 + venv/Lib/site-packages/pygame/libFLAC-8.dll | Bin 0 -> 441344 bytes .../site-packages/pygame/libfreetype-6.dll | Bin 0 -> 586240 bytes venv/Lib/site-packages/pygame/libjpeg-9.dll | Bin 0 -> 244224 bytes .../Lib/site-packages/pygame/libmodplug-1.dll | Bin 0 -> 252928 bytes venv/Lib/site-packages/pygame/libmpg123-0.dll | Bin 0 -> 337408 bytes venv/Lib/site-packages/pygame/libogg-0.dll | Bin 0 -> 52224 bytes venv/Lib/site-packages/pygame/libopus-0.dll | Bin 0 -> 124928 bytes .../site-packages/pygame/libopusfile-0.dll | Bin 0 -> 46592 bytes venv/Lib/site-packages/pygame/libpng16-16.dll | Bin 0 -> 210944 bytes venv/Lib/site-packages/pygame/libtiff-5.dll | Bin 0 -> 432640 bytes venv/Lib/site-packages/pygame/libvorbis-0.dll | Bin 0 -> 251904 bytes .../site-packages/pygame/libvorbisfile-3.dll | Bin 0 -> 69632 bytes venv/Lib/site-packages/pygame/libwebp-7.dll | Bin 0 -> 447488 bytes venv/Lib/site-packages/pygame/locals.py | 576 + venv/Lib/site-packages/pygame/macosx.py | 15 + .../pygame/mask.cp39-win_amd64.pyd | Bin 0 -> 56832 bytes venv/Lib/site-packages/pygame/mask.pyi | 58 + .../pygame/math.cp39-win_amd64.pyd | Bin 0 -> 67584 bytes venv/Lib/site-packages/pygame/math.pyi | 281 + venv/Lib/site-packages/pygame/midi.py | 718 + venv/Lib/site-packages/pygame/midi.pyi | 49 + .../pygame/mixer.cp39-win_amd64.pyd | Bin 0 -> 37376 bytes venv/Lib/site-packages/pygame/mixer.pyi | 86 + .../pygame/mixer_music.cp39-win_amd64.pyd | Bin 0 -> 20992 bytes .../pygame/mouse.cp39-win_amd64.pyd | Bin 0 -> 19456 bytes venv/Lib/site-packages/pygame/mouse.pyi | 34 + venv/Lib/site-packages/pygame/music.pyi | 20 + .../pygame/newbuffer.cp39-win_amd64.pyd | Bin 0 -> 22016 bytes .../pygame/pixelarray.cp39-win_amd64.pyd | Bin 0 -> 44544 bytes venv/Lib/site-packages/pygame/pixelarray.pyi | 35 + .../pygame/pixelcopy.cp39-win_amd64.pyd | Bin 0 -> 26112 bytes venv/Lib/site-packages/pygame/pixelcopy.pyi | 19 + venv/Lib/site-packages/pygame/pkgdata.py | 79 + venv/Lib/site-packages/pygame/portmidi.dll | Bin 0 -> 41984 bytes venv/Lib/site-packages/pygame/py.typed | 0 venv/Lib/site-packages/pygame/pygame.ico | Bin 0 -> 145516 bytes venv/Lib/site-packages/pygame/pygame_icon.bmp | Bin 0 -> 630 bytes .../Lib/site-packages/pygame/pygame_icon.icns | Bin 0 -> 264148 bytes .../site-packages/pygame/pygame_icon_mac.bmp | Bin 0 -> 262282 bytes .../pygame/pypm.cp39-win_amd64.pyd | Bin 0 -> 71680 bytes .../pygame/rect.cp39-win_amd64.pyd | Bin 0 -> 36864 bytes venv/Lib/site-packages/pygame/rect.pyi | 229 + .../pygame/rwobject.cp39-win_amd64.pyd | Bin 0 -> 19456 bytes .../pygame/scrap.cp39-win_amd64.pyd | Bin 0 -> 18944 bytes venv/Lib/site-packages/pygame/scrap.pyi | 10 + venv/Lib/site-packages/pygame/sndarray.py | 139 + venv/Lib/site-packages/pygame/sndarray.pyi | 12 + venv/Lib/site-packages/pygame/sprite.py | 1782 +++ venv/Lib/site-packages/pygame/sprite.pyi | 152 + .../pygame/surface.cp39-win_amd64.pyd | Bin 0 -> 220672 bytes venv/Lib/site-packages/pygame/surface.pyi | 121 + venv/Lib/site-packages/pygame/surfarray.py | 447 + venv/Lib/site-packages/pygame/surfarray.pyi | 25 + .../pygame/surflock.cp39-win_amd64.pyd | Bin 0 -> 13824 bytes venv/Lib/site-packages/pygame/sysfont.py | 529 + .../site-packages/pygame/tests/__init__.py | 40 + .../site-packages/pygame/tests/__main__.py | 144 + .../tests/__pycache__/__init__.cpython-39.pyc | Bin 0 -> 1372 bytes .../tests/__pycache__/__main__.cpython-39.pyc | Bin 0 -> 2830 bytes .../__pycache__/base_test.cpython-39.pyc | Bin 0 -> 16434 bytes .../__pycache__/blit_test.cpython-39.pyc | Bin 0 -> 4074 bytes .../bufferproxy_test.cpython-39.pyc | Bin 0 -> 12852 bytes .../__pycache__/camera_test.cpython-39.pyc | Bin 0 -> 394 bytes .../__pycache__/color_test.cpython-39.pyc | Bin 0 -> 40386 bytes .../__pycache__/constants_test.cpython-39.pyc | Bin 0 -> 7842 bytes .../controller_test.cpython-39.pyc | Bin 0 -> 10079 bytes .../__pycache__/cursors_test.cpython-39.pyc | Bin 0 -> 3667 bytes .../__pycache__/display_test.cpython-39.pyc | Bin 0 -> 22466 bytes .../__pycache__/docs_test.cpython-39.pyc | Bin 0 -> 1365 bytes .../__pycache__/draw_test.cpython-39.pyc | Bin 0 -> 142718 bytes .../__pycache__/event_test.cpython-39.pyc | Bin 0 -> 23295 bytes .../__pycache__/font_test.cpython-39.pyc | Bin 0 -> 19021 bytes .../__pycache__/freetype_tags.cpython-39.pyc | Bin 0 -> 386 bytes .../__pycache__/freetype_test.cpython-39.pyc | Bin 0 -> 38449 bytes .../__pycache__/ftfont_tags.cpython-39.pyc | Bin 0 -> 382 bytes .../__pycache__/ftfont_test.cpython-39.pyc | Bin 0 -> 592 bytes .../__pycache__/gfxdraw_test.cpython-39.pyc | Bin 0 -> 21759 bytes ...image__save_gl_surface_test.cpython-39.pyc | Bin 0 -> 1361 bytes .../__pycache__/image_tags.cpython-39.pyc | Bin 0 -> 329 bytes .../__pycache__/image_test.cpython-39.pyc | Bin 0 -> 25278 bytes .../__pycache__/imageext_tags.cpython-39.pyc | Bin 0 -> 335 bytes .../__pycache__/imageext_test.cpython-39.pyc | Bin 0 -> 3947 bytes .../__pycache__/joystick_test.cpython-39.pyc | Bin 0 -> 3851 bytes .../tests/__pycache__/key_test.cpython-39.pyc | Bin 0 -> 3557 bytes .../__pycache__/mask_test.cpython-39.pyc | Bin 0 -> 163209 bytes .../__pycache__/math_test.cpython-39.pyc | Bin 0 -> 71813 bytes .../__pycache__/midi_test.cpython-39.pyc | Bin 0 -> 15062 bytes .../mixer_music_tags.cpython-39.pyc | Bin 0 -> 341 bytes .../mixer_music_test.cpython-39.pyc | Bin 0 -> 10790 bytes .../__pycache__/mixer_tags.cpython-39.pyc | Bin 0 -> 329 bytes .../__pycache__/mixer_test.cpython-39.pyc | Bin 0 -> 30281 bytes .../__pycache__/mouse_test.cpython-39.pyc | Bin 0 -> 9369 bytes .../pixelarray_test.cpython-39.pyc | Bin 0 -> 38682 bytes .../__pycache__/pixelcopy_test.cpython-39.pyc | Bin 0 -> 18170 bytes .../__pycache__/rect_test.cpython-39.pyc | Bin 0 -> 66131 bytes .../__pycache__/rwobject_test.cpython-39.pyc | Bin 0 -> 5185 bytes .../__pycache__/scrap_tags.cpython-39.pyc | Bin 0 -> 238 bytes .../__pycache__/scrap_test.cpython-39.pyc | Bin 0 -> 9669 bytes .../__pycache__/sndarray_tags.cpython-39.pyc | Bin 0 -> 392 bytes .../__pycache__/sndarray_test.cpython-39.pyc | Bin 0 -> 5569 bytes .../__pycache__/sprite_test.cpython-39.pyc | Bin 0 -> 36482 bytes .../__pycache__/surface_test.cpython-39.pyc | Bin 0 -> 98920 bytes .../__pycache__/surfarray_tags.cpython-39.pyc | Bin 0 -> 431 bytes .../__pycache__/surfarray_test.cpython-39.pyc | Bin 0 -> 18845 bytes .../__pycache__/surflock_test.cpython-39.pyc | Bin 0 -> 2852 bytes .../__pycache__/sysfont_test.cpython-39.pyc | Bin 0 -> 2040 bytes .../__pycache__/test_test_.cpython-39.pyc | Bin 0 -> 200 bytes .../__pycache__/threads_test.cpython-39.pyc | Bin 0 -> 7008 bytes .../__pycache__/time_test.cpython-39.pyc | Bin 0 -> 7840 bytes .../__pycache__/touch_test.cpython-39.pyc | Bin 0 -> 3458 bytes .../__pycache__/transform_test.cpython-39.pyc | Bin 0 -> 27223 bytes .../__pycache__/version_test.cpython-39.pyc | Bin 0 -> 1642 bytes .../__pycache__/video_test.cpython-39.pyc | Bin 0 -> 1098 bytes .../site-packages/pygame/tests/base_test.py | 635 + .../site-packages/pygame/tests/blit_test.py | 155 + .../pygame/tests/bufferproxy_test.py | 507 + .../site-packages/pygame/tests/camera_test.py | 5 + .../site-packages/pygame/tests/color_test.py | 1302 ++ .../pygame/tests/constants_test.py | 437 + .../pygame/tests/controller_test.py | 357 + .../pygame/tests/cursors_test.py | 291 + .../pygame/tests/display_test.py | 811 ++ .../site-packages/pygame/tests/docs_test.py | 35 + .../site-packages/pygame/tests/draw_test.py | 6563 ++++++++++ .../site-packages/pygame/tests/event_test.py | 840 ++ .../tests/fixtures/fonts/A_PyGameMono-8.png | Bin 0 -> 92 bytes .../fixtures/fonts/PyGameMono-18-100dpi.bdf | 165 + .../fixtures/fonts/PyGameMono-18-75dpi.bdf | 143 + .../tests/fixtures/fonts/PyGameMono-8.bdf | 103 + .../tests/fixtures/fonts/PyGameMono.otf | Bin 0 -> 3128 bytes .../tests/fixtures/fonts/test_fixed.otf | Bin 0 -> 58464 bytes .../pygame/tests/fixtures/fonts/test_sans.ttf | Bin 0 -> 133088 bytes .../fixtures/fonts/u13079_PyGameMono-8.png | Bin 0 -> 89 bytes .../fixtures/xbm_cursors/white_sizing.xbm | 8 + .../xbm_cursors/white_sizing_mask.xbm | 8 + .../site-packages/pygame/tests/font_test.py | 633 + .../pygame/tests/freetype_tags.py | 11 + .../pygame/tests/freetype_test.py | 1799 +++ .../site-packages/pygame/tests/ftfont_tags.py | 11 + .../site-packages/pygame/tests/ftfont_test.py | 19 + .../pygame/tests/gfxdraw_test.py | 877 ++ .../tests/image__save_gl_surface_test.py | 46 + .../site-packages/pygame/tests/image_tags.py | 7 + .../site-packages/pygame/tests/image_test.py | 1115 ++ .../pygame/tests/imageext_tags.py | 7 + .../pygame/tests/imageext_test.py | 94 + .../pygame/tests/joystick_test.py | 172 + .../site-packages/pygame/tests/key_test.py | 110 + .../site-packages/pygame/tests/mask_test.py | 6440 +++++++++ .../site-packages/pygame/tests/math_test.py | 2326 ++++ .../site-packages/pygame/tests/midi_test.py | 472 + .../pygame/tests/mixer_music_tags.py | 7 + .../pygame/tests/mixer_music_test.py | 415 + .../site-packages/pygame/tests/mixer_tags.py | 7 + .../site-packages/pygame/tests/mixer_test.py | 1193 ++ .../site-packages/pygame/tests/mouse_test.py | 350 + .../pygame/tests/pixelarray_test.py | 1660 +++ .../pygame/tests/pixelcopy_test.py | 712 + .../site-packages/pygame/tests/rect_test.py | 2152 +++ .../pygame/tests/run_tests__tests/__init__.py | 1 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 211 bytes .../run_tests__test.cpython-39.pyc | Bin 0 -> 3391 bytes .../tests/run_tests__tests/all_ok/__init__.py | 1 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 218 bytes .../__pycache__/fake_2_test.cpython-39.pyc | Bin 0 -> 1651 bytes .../__pycache__/fake_3_test.cpython-39.pyc | Bin 0 -> 1651 bytes .../__pycache__/fake_4_test.cpython-39.pyc | Bin 0 -> 1651 bytes .../__pycache__/fake_5_test.cpython-39.pyc | Bin 0 -> 1651 bytes .../__pycache__/fake_6_test.cpython-39.pyc | Bin 0 -> 1651 bytes ...rtions__ret_code_of_1__test.cpython-39.pyc | Bin 0 -> 1604 bytes .../zero_tests_test.cpython-39.pyc | Bin 0 -> 774 bytes .../run_tests__tests/all_ok/fake_2_test.py | 39 + .../run_tests__tests/all_ok/fake_3_test.py | 39 + .../run_tests__tests/all_ok/fake_4_test.py | 39 + .../run_tests__tests/all_ok/fake_5_test.py | 39 + .../run_tests__tests/all_ok/fake_6_test.py | 39 + .../no_assertions__ret_code_of_1__test.py | 39 + .../all_ok/zero_tests_test.py | 23 + .../run_tests__tests/everything/__init__.py | 1 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 222 bytes .../__pycache__/fake_2_test.cpython-39.pyc | Bin 0 -> 1655 bytes .../incomplete_todo_test.cpython-39.pyc | Bin 0 -> 1684 bytes .../__pycache__/magic_tag_test.cpython-39.pyc | Bin 0 -> 1535 bytes .../__pycache__/sleep_test.cpython-39.pyc | Bin 0 -> 1027 bytes .../everything/fake_2_test.py | 39 + .../everything/incomplete_todo_test.py | 39 + .../everything/magic_tag_test.py | 38 + .../run_tests__tests/everything/sleep_test.py | 29 + .../run_tests__tests/exclude/__init__.py | 1 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 219 bytes .../__pycache__/fake_2_test.cpython-39.pyc | Bin 0 -> 1652 bytes .../invisible_tag_test.cpython-39.pyc | Bin 0 -> 1688 bytes .../__pycache__/magic_tag_test.cpython-39.pyc | Bin 0 -> 1532 bytes .../run_tests__tests/exclude/fake_2_test.py | 39 + .../exclude/invisible_tag_test.py | 41 + .../exclude/magic_tag_test.py | 38 + .../run_tests__tests/failures1/__init__.py | 1 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 221 bytes .../__pycache__/fake_2_test.cpython-39.pyc | Bin 0 -> 1654 bytes .../__pycache__/fake_3_test.cpython-39.pyc | Bin 0 -> 1654 bytes .../__pycache__/fake_4_test.cpython-39.pyc | Bin 0 -> 1668 bytes .../run_tests__tests/failures1/fake_2_test.py | 39 + .../run_tests__tests/failures1/fake_3_test.py | 39 + .../run_tests__tests/failures1/fake_4_test.py | 41 + .../run_tests__tests/incomplete/__init__.py | 1 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 222 bytes .../__pycache__/fake_2_test.cpython-39.pyc | Bin 0 -> 1672 bytes .../__pycache__/fake_3_test.cpython-39.pyc | Bin 0 -> 1655 bytes .../incomplete/fake_2_test.py | 39 + .../incomplete/fake_3_test.py | 39 + .../incomplete_todo/__init__.py | 1 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 227 bytes .../__pycache__/fake_2_test.cpython-39.pyc | Bin 0 -> 1680 bytes .../__pycache__/fake_3_test.cpython-39.pyc | Bin 0 -> 1660 bytes .../incomplete_todo/fake_2_test.py | 39 + .../incomplete_todo/fake_3_test.py | 39 + .../infinite_loop/__init__.py | 1 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 225 bytes .../__pycache__/fake_1_test.cpython-39.pyc | Bin 0 -> 1648 bytes .../__pycache__/fake_2_test.cpython-39.pyc | Bin 0 -> 1658 bytes .../infinite_loop/fake_1_test.py | 40 + .../infinite_loop/fake_2_test.py | 39 + .../run_tests__tests/print_stderr/__init__.py | 1 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 224 bytes .../__pycache__/fake_2_test.cpython-39.pyc | Bin 0 -> 1657 bytes .../__pycache__/fake_3_test.cpython-39.pyc | Bin 0 -> 1721 bytes .../__pycache__/fake_4_test.cpython-39.pyc | Bin 0 -> 1671 bytes .../print_stderr/fake_2_test.py | 39 + .../print_stderr/fake_3_test.py | 41 + .../print_stderr/fake_4_test.py | 41 + .../run_tests__tests/print_stdout/__init__.py | 1 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 224 bytes .../__pycache__/fake_2_test.cpython-39.pyc | Bin 0 -> 1657 bytes .../__pycache__/fake_3_test.cpython-39.pyc | Bin 0 -> 1764 bytes .../__pycache__/fake_4_test.cpython-39.pyc | Bin 0 -> 1671 bytes .../print_stdout/fake_2_test.py | 39 + .../print_stdout/fake_3_test.py | 42 + .../print_stdout/fake_4_test.py | 41 + .../tests/run_tests__tests/run_tests__test.py | 145 + .../run_tests__tests/timeout/__init__.py | 1 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 219 bytes .../__pycache__/fake_2_test.cpython-39.pyc | Bin 0 -> 1652 bytes .../__pycache__/sleep_test.cpython-39.pyc | Bin 0 -> 1024 bytes .../run_tests__tests/timeout/fake_2_test.py | 39 + .../run_tests__tests/timeout/sleep_test.py | 30 + .../pygame/tests/rwobject_test.py | 139 + .../site-packages/pygame/tests/scrap_tags.py | 26 + .../site-packages/pygame/tests/scrap_test.py | 301 + .../pygame/tests/sndarray_tags.py | 12 + .../pygame/tests/sndarray_test.py | 155 + .../site-packages/pygame/tests/sprite_test.py | 1403 ++ .../pygame/tests/surface_test.py | 4015 ++++++ .../pygame/tests/surfarray_tags.py | 16 + .../pygame/tests/surfarray_test.py | 754 ++ .../pygame/tests/surflock_test.py | 144 + .../pygame/tests/sysfont_test.py | 51 + .../site-packages/pygame/tests/test_test_.py | 2 + .../pygame/tests/test_utils/__init__.py | 227 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 6644 bytes .../__pycache__/arrinter.cpython-39.pyc | Bin 0 -> 13041 bytes .../__pycache__/async_sub.cpython-39.pyc | Bin 0 -> 7152 bytes .../__pycache__/buftools.cpython-39.pyc | Bin 0 -> 17204 bytes .../__pycache__/endian.cpython-39.pyc | Bin 0 -> 681 bytes .../test_utils/__pycache__/png.cpython-39.pyc | Bin 0 -> 122895 bytes .../__pycache__/run_tests.cpython-39.pyc | Bin 0 -> 8810 bytes .../__pycache__/test_machinery.cpython-39.pyc | Bin 0 -> 2833 bytes .../__pycache__/test_runner.cpython-39.pyc | Bin 0 -> 6962 bytes .../pygame/tests/test_utils/arrinter.py | 441 + .../pygame/tests/test_utils/async_sub.py | 301 + .../pygame/tests/test_utils/buftools.py | 613 + .../pygame/tests/test_utils/endian.py | 20 + .../pygame/tests/test_utils/png.py | 4001 ++++++ .../pygame/tests/test_utils/run_tests.py | 350 + .../pygame/tests/test_utils/test_machinery.py | 89 + .../pygame/tests/test_utils/test_runner.py | 330 + .../pygame/tests/threads_test.py | 240 + .../site-packages/pygame/tests/time_test.py | 392 + .../site-packages/pygame/tests/touch_test.py | 98 + .../pygame/tests/transform_test.py | 1316 ++ .../pygame/tests/version_test.py | 48 + .../site-packages/pygame/tests/video_test.py | 26 + .../site-packages/pygame/threads/__init__.py | 272 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 6542 bytes .../pygame/time.cp39-win_amd64.pyd | Bin 0 -> 18944 bytes venv/Lib/site-packages/pygame/time.pyi | 15 + .../pygame/transform.cp39-win_amd64.pyd | Bin 0 -> 52224 bytes venv/Lib/site-packages/pygame/transform.pyi | 41 + venv/Lib/site-packages/pygame/version.py | 72 + venv/Lib/site-packages/pygame/version.pyi | 17 + venv/Lib/site-packages/pygame/zlib1.dll | Bin 0 -> 108544 bytes .../setuptools-60.9.3.dist-info/INSTALLER | 1 + .../setuptools-60.9.3.dist-info/LICENSE | 19 + .../setuptools-60.9.3.dist-info/METADATA | 142 + .../setuptools-60.9.3.dist-info/RECORD | 389 + .../setuptools-60.9.3.dist-info/WHEEL | 5 + .../entry_points.txt | 55 + .../setuptools-60.9.3.dist-info/top_level.txt | 3 + venv/Lib/site-packages/setuptools/__init__.py | 244 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 8622 bytes .../_deprecation_warning.cpython-39.pyc | Bin 0 -> 545 bytes .../__pycache__/_entry_points.cpython-39.pyc | Bin 0 -> 2984 bytes .../__pycache__/_imp.cpython-39.pyc | Bin 0 -> 2080 bytes .../__pycache__/_importlib.cpython-39.pyc | Bin 0 -> 1082 bytes .../__pycache__/_itertools.cpython-39.pyc | Bin 0 -> 903 bytes .../__pycache__/_path.cpython-39.pyc | Bin 0 -> 423 bytes .../__pycache__/_reqs.cpython-39.pyc | Bin 0 -> 826 bytes .../__pycache__/archive_util.cpython-39.pyc | Bin 0 -> 5806 bytes .../__pycache__/build_meta.cpython-39.pyc | Bin 0 -> 9826 bytes .../__pycache__/config.cpython-39.pyc | Bin 0 -> 20848 bytes .../__pycache__/dep_util.cpython-39.pyc | Bin 0 -> 852 bytes .../__pycache__/depends.cpython-39.pyc | Bin 0 -> 5270 bytes .../__pycache__/dist.cpython-39.pyc | Bin 0 -> 38025 bytes .../__pycache__/errors.cpython-39.pyc | Bin 0 -> 1497 bytes .../__pycache__/extension.cpython-39.pyc | Bin 0 -> 1971 bytes .../__pycache__/glob.cpython-39.pyc | Bin 0 -> 3689 bytes .../__pycache__/installer.cpython-39.pyc | Bin 0 -> 2994 bytes .../__pycache__/launch.cpython-39.pyc | Bin 0 -> 896 bytes .../__pycache__/logging.cpython-39.pyc | Bin 0 -> 1206 bytes .../__pycache__/monkey.cpython-39.pyc | Bin 0 -> 4608 bytes .../__pycache__/msvc.cpython-39.pyc | Bin 0 -> 42834 bytes .../__pycache__/namespaces.cpython-39.pyc | Bin 0 -> 3595 bytes .../__pycache__/package_index.cpython-39.pyc | Bin 0 -> 32862 bytes .../__pycache__/py34compat.cpython-39.pyc | Bin 0 -> 475 bytes .../__pycache__/sandbox.cpython-39.pyc | Bin 0 -> 15751 bytes .../__pycache__/unicode_utils.cpython-39.pyc | Bin 0 -> 1109 bytes .../__pycache__/version.cpython-39.pyc | Bin 0 -> 319 bytes .../__pycache__/wheel.cpython-39.pyc | Bin 0 -> 7260 bytes .../windows_support.cpython-39.pyc | Bin 0 -> 1018 bytes .../setuptools/_deprecation_warning.py | 7 + .../setuptools/_distutils/__init__.py | 24 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 553 bytes .../__pycache__/_collections.cpython-39.pyc | Bin 0 -> 2052 bytes .../__pycache__/_msvccompiler.cpython-39.pyc | Bin 0 -> 13819 bytes .../__pycache__/archive_util.cpython-39.pyc | Bin 0 -> 6640 bytes .../__pycache__/bcppcompiler.cpython-39.pyc | Bin 0 -> 6584 bytes .../__pycache__/ccompiler.cpython-39.pyc | Bin 0 -> 33457 bytes .../_distutils/__pycache__/cmd.cpython-39.pyc | Bin 0 -> 13979 bytes .../__pycache__/config.cpython-39.pyc | Bin 0 -> 3582 bytes .../__pycache__/core.cpython-39.pyc | Bin 0 -> 7135 bytes .../cygwinccompiler.cpython-39.pyc | Bin 0 -> 7780 bytes .../__pycache__/debug.cpython-39.pyc | Bin 0 -> 249 bytes .../__pycache__/dep_util.cpython-39.pyc | Bin 0 -> 2769 bytes .../__pycache__/dir_util.cpython-39.pyc | Bin 0 -> 5870 bytes .../__pycache__/dist.cpython-39.pyc | Bin 0 -> 34440 bytes .../__pycache__/errors.cpython-39.pyc | Bin 0 -> 5305 bytes .../__pycache__/extension.cpython-39.pyc | Bin 0 -> 6970 bytes .../__pycache__/fancy_getopt.cpython-39.pyc | Bin 0 -> 10678 bytes .../__pycache__/file_util.cpython-39.pyc | Bin 0 -> 6036 bytes .../__pycache__/filelist.cpython-39.pyc | Bin 0 -> 10828 bytes .../_distutils/__pycache__/log.cpython-39.pyc | Bin 0 -> 2368 bytes .../__pycache__/msvc9compiler.cpython-39.pyc | Bin 0 -> 17602 bytes .../__pycache__/msvccompiler.cpython-39.pyc | Bin 0 -> 14793 bytes .../__pycache__/py35compat.cpython-39.pyc | Bin 0 -> 625 bytes .../__pycache__/py38compat.cpython-39.pyc | Bin 0 -> 420 bytes .../__pycache__/spawn.cpython-39.pyc | Bin 0 -> 2863 bytes .../__pycache__/sysconfig.cpython-39.pyc | Bin 0 -> 12260 bytes .../__pycache__/text_file.cpython-39.pyc | Bin 0 -> 8494 bytes .../__pycache__/unixccompiler.cpython-39.pyc | Bin 0 -> 6842 bytes .../__pycache__/util.cpython-39.pyc | Bin 0 -> 13498 bytes .../__pycache__/version.cpython-39.pyc | Bin 0 -> 7846 bytes .../versionpredicate.cpython-39.pyc | Bin 0 -> 5313 bytes .../setuptools/_distutils/_collections.py | 56 + .../setuptools/_distutils/_msvccompiler.py | 561 + .../setuptools/_distutils/archive_util.py | 256 + .../setuptools/_distutils/bcppcompiler.py | 393 + .../setuptools/_distutils/ccompiler.py | 1123 ++ .../setuptools/_distutils/cmd.py | 403 + .../setuptools/_distutils/command/__init__.py | 31 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 528 bytes .../command/__pycache__/bdist.cpython-39.pyc | Bin 0 -> 3658 bytes .../__pycache__/bdist_dumb.cpython-39.pyc | Bin 0 -> 3641 bytes .../__pycache__/bdist_msi.cpython-39.pyc | Bin 0 -> 19829 bytes .../__pycache__/bdist_rpm.cpython-39.pyc | Bin 0 -> 12278 bytes .../__pycache__/bdist_wininst.cpython-39.pyc | Bin 0 -> 8598 bytes .../command/__pycache__/build.cpython-39.pyc | Bin 0 -> 3930 bytes .../__pycache__/build_clib.cpython-39.pyc | Bin 0 -> 4853 bytes .../__pycache__/build_ext.cpython-39.pyc | Bin 0 -> 16218 bytes .../__pycache__/build_py.cpython-39.pyc | Bin 0 -> 9848 bytes .../__pycache__/build_scripts.cpython-39.pyc | Bin 0 -> 4013 bytes .../command/__pycache__/check.cpython-39.pyc | Bin 0 -> 4995 bytes .../command/__pycache__/clean.cpython-39.pyc | Bin 0 -> 2135 bytes .../command/__pycache__/config.cpython-39.pyc | Bin 0 -> 10265 bytes .../__pycache__/install.cpython-39.pyc | Bin 0 -> 17118 bytes .../__pycache__/install_data.cpython-39.pyc | Bin 0 -> 2338 bytes .../install_egg_info.cpython-39.pyc | Bin 0 -> 3297 bytes .../install_headers.cpython-39.pyc | Bin 0 -> 1763 bytes .../__pycache__/install_lib.cpython-39.pyc | Bin 0 -> 5135 bytes .../install_scripts.cpython-39.pyc | Bin 0 -> 2186 bytes .../__pycache__/py37compat.cpython-39.pyc | Bin 0 -> 1029 bytes .../__pycache__/register.cpython-39.pyc | Bin 0 -> 8506 bytes .../command/__pycache__/sdist.cpython-39.pyc | Bin 0 -> 14533 bytes .../command/__pycache__/upload.cpython-39.pyc | Bin 0 -> 5256 bytes .../setuptools/_distutils/command/bdist.py | 143 + .../_distutils/command/bdist_dumb.py | 123 + .../_distutils/command/bdist_msi.py | 749 ++ .../_distutils/command/bdist_rpm.py | 579 + .../_distutils/command/bdist_wininst.py | 377 + .../setuptools/_distutils/command/build.py | 157 + .../_distutils/command/build_clib.py | 209 + .../_distutils/command/build_ext.py | 755 ++ .../setuptools/_distutils/command/build_py.py | 392 + .../_distutils/command/build_scripts.py | 152 + .../setuptools/_distutils/command/check.py | 148 + .../setuptools/_distutils/command/clean.py | 76 + .../setuptools/_distutils/command/config.py | 344 + .../setuptools/_distutils/command/install.py | 781 ++ .../_distutils/command/install_data.py | 79 + .../_distutils/command/install_egg_info.py | 84 + .../_distutils/command/install_headers.py | 47 + .../_distutils/command/install_lib.py | 217 + .../_distutils/command/install_scripts.py | 60 + .../_distutils/command/py37compat.py | 30 + .../setuptools/_distutils/command/register.py | 304 + .../setuptools/_distutils/command/sdist.py | 494 + .../setuptools/_distutils/command/upload.py | 214 + .../setuptools/_distutils/config.py | 130 + .../setuptools/_distutils/core.py | 249 + .../setuptools/_distutils/cygwinccompiler.py | 362 + .../setuptools/_distutils/debug.py | 5 + .../setuptools/_distutils/dep_util.py | 92 + .../setuptools/_distutils/dir_util.py | 210 + .../setuptools/_distutils/dist.py | 1257 ++ .../setuptools/_distutils/errors.py | 97 + .../setuptools/_distutils/extension.py | 240 + .../setuptools/_distutils/fancy_getopt.py | 457 + .../setuptools/_distutils/file_util.py | 238 + .../setuptools/_distutils/filelist.py | 355 + .../setuptools/_distutils/log.py | 81 + .../setuptools/_distutils/msvc9compiler.py | 788 ++ .../setuptools/_distutils/msvccompiler.py | 643 + .../setuptools/_distutils/py35compat.py | 19 + .../setuptools/_distutils/py38compat.py | 7 + .../setuptools/_distutils/spawn.py | 106 + .../setuptools/_distutils/sysconfig.py | 567 + .../setuptools/_distutils/text_file.py | 286 + .../setuptools/_distutils/unixccompiler.py | 325 + .../setuptools/_distutils/util.py | 496 + .../setuptools/_distutils/version.py | 363 + .../setuptools/_distutils/versionpredicate.py | 169 + .../site-packages/setuptools/_entry_points.py | 86 + venv/Lib/site-packages/setuptools/_imp.py | 82 + .../site-packages/setuptools/_importlib.py | 36 + .../site-packages/setuptools/_itertools.py | 23 + venv/Lib/site-packages/setuptools/_path.py | 7 + venv/Lib/site-packages/setuptools/_reqs.py | 19 + .../setuptools/_vendor/__init__.py | 0 .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 183 bytes .../__pycache__/ordered_set.cpython-39.pyc | Bin 0 -> 16377 bytes .../__pycache__/pyparsing.cpython-39.pyc | Bin 0 -> 201336 bytes .../typing_extensions.cpython-39.pyc | Bin 0 -> 68492 bytes .../_vendor/__pycache__/zipp.cpython-39.pyc | Bin 0 -> 10333 bytes .../_vendor/importlib_metadata/__init__.py | 1047 ++ .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 37471 bytes .../__pycache__/_adapters.cpython-39.pyc | Bin 0 -> 2397 bytes .../__pycache__/_collections.cpython-39.pyc | Bin 0 -> 1572 bytes .../__pycache__/_compat.cpython-39.pyc | Bin 0 -> 2061 bytes .../__pycache__/_functools.cpython-39.pyc | Bin 0 -> 3162 bytes .../__pycache__/_itertools.cpython-39.pyc | Bin 0 -> 2039 bytes .../__pycache__/_meta.cpython-39.pyc | Bin 0 -> 2416 bytes .../__pycache__/_text.cpython-39.pyc | Bin 0 -> 3105 bytes .../_vendor/importlib_metadata/_adapters.py | 68 + .../importlib_metadata/_collections.py | 30 + .../_vendor/importlib_metadata/_compat.py | 71 + .../_vendor/importlib_metadata/_functools.py | 104 + .../_vendor/importlib_metadata/_itertools.py | 73 + .../_vendor/importlib_metadata/_meta.py | 48 + .../_vendor/importlib_metadata/_text.py | 99 + .../_vendor/importlib_resources/__init__.py | 36 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 638 bytes .../__pycache__/_adapters.cpython-39.pyc | Bin 0 -> 7486 bytes .../__pycache__/_common.cpython-39.pyc | Bin 0 -> 2628 bytes .../__pycache__/_compat.cpython-39.pyc | Bin 0 -> 3480 bytes .../__pycache__/_itertools.cpython-39.pyc | Bin 0 -> 861 bytes .../__pycache__/_legacy.cpython-39.pyc | Bin 0 -> 4198 bytes .../__pycache__/abc.cpython-39.pyc | Bin 0 -> 5436 bytes .../__pycache__/readers.cpython-39.pyc | Bin 0 -> 5552 bytes .../__pycache__/simple.cpython-39.pyc | Bin 0 -> 4748 bytes .../_vendor/importlib_resources/_adapters.py | 170 + .../_vendor/importlib_resources/_common.py | 104 + .../_vendor/importlib_resources/_compat.py | 98 + .../_vendor/importlib_resources/_itertools.py | 35 + .../_vendor/importlib_resources/_legacy.py | 121 + .../_vendor/importlib_resources/abc.py | 137 + .../_vendor/importlib_resources/readers.py | 122 + .../_vendor/importlib_resources/simple.py | 116 + .../setuptools/_vendor/jaraco/__init__.py | 0 .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 190 bytes .../jaraco/__pycache__/context.cpython-39.pyc | Bin 0 -> 6275 bytes .../__pycache__/functools.cpython-39.pyc | Bin 0 -> 15646 bytes .../setuptools/_vendor/jaraco/context.py | 213 + .../setuptools/_vendor/jaraco/functools.py | 525 + .../_vendor/jaraco/text/__init__.py | 599 + .../text/__pycache__/__init__.cpython-39.pyc | Bin 0 -> 19672 bytes .../_vendor/more_itertools/__init__.py | 4 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 264 bytes .../__pycache__/more.cpython-39.pyc | Bin 0 -> 110012 bytes .../__pycache__/recipes.cpython-39.pyc | Bin 0 -> 17929 bytes .../setuptools/_vendor/more_itertools/more.py | 3824 ++++++ .../_vendor/more_itertools/recipes.py | 620 + .../setuptools/_vendor/ordered_set.py | 488 + .../setuptools/_vendor/packaging/__about__.py | 26 + .../setuptools/_vendor/packaging/__init__.py | 25 + .../__pycache__/__about__.cpython-39.pyc | Bin 0 -> 590 bytes .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 446 bytes .../__pycache__/_manylinux.cpython-39.pyc | Bin 0 -> 7294 bytes .../__pycache__/_musllinux.cpython-39.pyc | Bin 0 -> 4609 bytes .../__pycache__/_structures.cpython-39.pyc | Bin 0 -> 2803 bytes .../__pycache__/markers.cpython-39.pyc | Bin 0 -> 9459 bytes .../__pycache__/requirements.cpython-39.pyc | Bin 0 -> 3980 bytes .../__pycache__/specifiers.cpython-39.pyc | Bin 0 -> 21521 bytes .../packaging/__pycache__/tags.cpython-39.pyc | Bin 0 -> 12252 bytes .../__pycache__/utils.cpython-39.pyc | Bin 0 -> 3611 bytes .../__pycache__/version.cpython-39.pyc | Bin 0 -> 13152 bytes .../_vendor/packaging/_manylinux.py | 301 + .../_vendor/packaging/_musllinux.py | 136 + .../_vendor/packaging/_structures.py | 61 + .../setuptools/_vendor/packaging/markers.py | 304 + .../_vendor/packaging/requirements.py | 146 + .../_vendor/packaging/specifiers.py | 802 ++ .../setuptools/_vendor/packaging/tags.py | 487 + .../setuptools/_vendor/packaging/utils.py | 136 + .../setuptools/_vendor/packaging/version.py | 504 + .../setuptools/_vendor/pyparsing.py | 5742 ++++++++ .../setuptools/_vendor/typing_extensions.py | 2296 ++++ .../site-packages/setuptools/_vendor/zipp.py | 329 + .../site-packages/setuptools/archive_util.py | 205 + .../site-packages/setuptools/build_meta.py | 304 + venv/Lib/site-packages/setuptools/cli-32.exe | Bin 0 -> 65536 bytes venv/Lib/site-packages/setuptools/cli-64.exe | Bin 0 -> 74752 bytes .../site-packages/setuptools/cli-arm64.exe | Bin 0 -> 137216 bytes venv/Lib/site-packages/setuptools/cli.exe | Bin 0 -> 65536 bytes .../setuptools/command/__init__.py | 8 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 372 bytes .../command/__pycache__/alias.cpython-39.pyc | Bin 0 -> 2366 bytes .../__pycache__/bdist_egg.cpython-39.pyc | Bin 0 -> 13056 bytes .../__pycache__/bdist_rpm.cpython-39.pyc | Bin 0 -> 1579 bytes .../__pycache__/build_clib.cpython-39.pyc | Bin 0 -> 2463 bytes .../__pycache__/build_ext.cpython-39.pyc | Bin 0 -> 9822 bytes .../__pycache__/build_py.cpython-39.pyc | Bin 0 -> 8209 bytes .../__pycache__/develop.cpython-39.pyc | Bin 0 -> 6132 bytes .../__pycache__/dist_info.cpython-39.pyc | Bin 0 -> 1390 bytes .../__pycache__/easy_install.cpython-39.pyc | Bin 0 -> 64328 bytes .../__pycache__/egg_info.cpython-39.pyc | Bin 0 -> 22519 bytes .../__pycache__/install.cpython-39.pyc | Bin 0 -> 4180 bytes .../install_egg_info.cpython-39.pyc | Bin 0 -> 2453 bytes .../__pycache__/install_lib.cpython-39.pyc | Bin 0 -> 4129 bytes .../install_scripts.cpython-39.pyc | Bin 0 -> 2441 bytes .../__pycache__/py36compat.cpython-39.pyc | Bin 0 -> 4584 bytes .../__pycache__/register.cpython-39.pyc | Bin 0 -> 840 bytes .../command/__pycache__/rotate.cpython-39.pyc | Bin 0 -> 2499 bytes .../__pycache__/saveopts.cpython-39.pyc | Bin 0 -> 918 bytes .../command/__pycache__/sdist.cpython-39.pyc | Bin 0 -> 6916 bytes .../command/__pycache__/setopt.cpython-39.pyc | Bin 0 -> 4669 bytes .../command/__pycache__/test.cpython-39.pyc | Bin 0 -> 8122 bytes .../command/__pycache__/upload.cpython-39.pyc | Bin 0 -> 813 bytes .../__pycache__/upload_docs.cpython-39.pyc | Bin 0 -> 6167 bytes .../site-packages/setuptools/command/alias.py | 78 + .../setuptools/command/bdist_egg.py | 457 + .../setuptools/command/bdist_rpm.py | 40 + .../setuptools/command/build_clib.py | 101 + .../setuptools/command/build_ext.py | 328 + .../setuptools/command/build_py.py | 242 + .../setuptools/command/develop.py | 193 + .../setuptools/command/dist_info.py | 36 + .../setuptools/command/easy_install.py | 2320 ++++ .../setuptools/command/egg_info.py | 743 ++ .../setuptools/command/install.py | 132 + .../setuptools/command/install_egg_info.py | 63 + .../setuptools/command/install_lib.py | 122 + .../setuptools/command/install_scripts.py | 70 + .../setuptools/command/launcher manifest.xml | 15 + .../setuptools/command/py36compat.py | 134 + .../setuptools/command/register.py | 18 + .../setuptools/command/rotate.py | 64 + .../setuptools/command/saveopts.py | 22 + .../site-packages/setuptools/command/sdist.py | 196 + .../setuptools/command/setopt.py | 149 + .../site-packages/setuptools/command/test.py | 251 + .../setuptools/command/upload.py | 17 + .../setuptools/command/upload_docs.py | 204 + venv/Lib/site-packages/setuptools/config.py | 751 ++ venv/Lib/site-packages/setuptools/dep_util.py | 25 + venv/Lib/site-packages/setuptools/depends.py | 176 + venv/Lib/site-packages/setuptools/dist.py | 1192 ++ venv/Lib/site-packages/setuptools/errors.py | 40 + .../Lib/site-packages/setuptools/extension.py | 55 + .../setuptools/extern/__init__.py | 76 + .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 2988 bytes venv/Lib/site-packages/setuptools/glob.py | 167 + venv/Lib/site-packages/setuptools/gui-32.exe | Bin 0 -> 65536 bytes venv/Lib/site-packages/setuptools/gui-64.exe | Bin 0 -> 75264 bytes .../site-packages/setuptools/gui-arm64.exe | Bin 0 -> 137728 bytes venv/Lib/site-packages/setuptools/gui.exe | Bin 0 -> 65536 bytes .../Lib/site-packages/setuptools/installer.py | 104 + venv/Lib/site-packages/setuptools/launch.py | 36 + venv/Lib/site-packages/setuptools/logging.py | 36 + venv/Lib/site-packages/setuptools/monkey.py | 177 + venv/Lib/site-packages/setuptools/msvc.py | 1805 +++ .../site-packages/setuptools/namespaces.py | 107 + .../site-packages/setuptools/package_index.py | 1127 ++ .../site-packages/setuptools/py34compat.py | 13 + venv/Lib/site-packages/setuptools/sandbox.py | 530 + .../setuptools/script (dev).tmpl | 6 + venv/Lib/site-packages/setuptools/script.tmpl | 3 + .../site-packages/setuptools/unicode_utils.py | 42 + venv/Lib/site-packages/setuptools/version.py | 6 + venv/Lib/site-packages/setuptools/wheel.py | 213 + .../setuptools/windows_support.py | 29 + venv/Scripts/Activate.ps1 | 398 + venv/Scripts/activate | 66 + venv/Scripts/activate.bat | 33 + venv/Scripts/deactivate.bat | 21 + venv/Scripts/pip.exe | Bin 0 -> 106390 bytes venv/Scripts/pip3.9.exe | Bin 0 -> 106390 bytes venv/Scripts/pip3.exe | Bin 0 -> 106390 bytes venv/Scripts/python.exe | Bin 0 -> 539312 bytes venv/Scripts/pythonw.exe | Bin 0 -> 537776 bytes venv/pyvenv.cfg | 3 + 2204 files changed, 421244 insertions(+) create mode 100644 .idea/.gitignore create mode 100644 .idea/AI_wozek_widlowy.iml create mode 100644 .idea/inspectionProfiles/profiles_settings.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 resources/track.png create mode 100644 resources/truck.jpeg create mode 100644 resources/truck.jpg create mode 100644 run.py create mode 100644 venv/Include/site/python3.9/pygame/_camera.h create mode 100644 venv/Include/site/python3.9/pygame/_pygame.h create mode 100644 venv/Include/site/python3.9/pygame/_surface.h create mode 100644 venv/Include/site/python3.9/pygame/camera.h create mode 100644 venv/Include/site/python3.9/pygame/font.h create mode 100644 venv/Include/site/python3.9/pygame/freetype.h create mode 100644 venv/Include/site/python3.9/pygame/include/_pygame.h create mode 100644 venv/Include/site/python3.9/pygame/include/bitmask.h create mode 100644 venv/Include/site/python3.9/pygame/include/pgcompat.h create mode 100644 venv/Include/site/python3.9/pygame/include/pgimport.h create mode 100644 venv/Include/site/python3.9/pygame/include/pgplatform.h create mode 100644 venv/Include/site/python3.9/pygame/include/pygame.h create mode 100644 venv/Include/site/python3.9/pygame/include/pygame_bufferproxy.h create mode 100644 venv/Include/site/python3.9/pygame/include/pygame_font.h create mode 100644 venv/Include/site/python3.9/pygame/include/pygame_freetype.h create mode 100644 venv/Include/site/python3.9/pygame/include/pygame_mask.h create mode 100644 venv/Include/site/python3.9/pygame/include/pygame_mixer.h create mode 100644 venv/Include/site/python3.9/pygame/include/sse2neon.h create mode 100644 venv/Include/site/python3.9/pygame/mask.h create mode 100644 venv/Include/site/python3.9/pygame/mixer.h create mode 100644 venv/Include/site/python3.9/pygame/palette.h create mode 100644 venv/Include/site/python3.9/pygame/pgarrinter.h create mode 100644 venv/Include/site/python3.9/pygame/pgbufferproxy.h create mode 100644 venv/Include/site/python3.9/pygame/pgcompat.h create mode 100644 venv/Include/site/python3.9/pygame/pgopengl.h create mode 100644 venv/Include/site/python3.9/pygame/pgplatform.h create mode 100644 venv/Include/site/python3.9/pygame/pygame.h create mode 100644 venv/Include/site/python3.9/pygame/scrap.h create mode 100644 venv/Include/site/python3.9/pygame/surface.h create mode 100644 venv/Lib/site-packages/_distutils_hack/__init__.py create mode 100644 venv/Lib/site-packages/_distutils_hack/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/_distutils_hack/__pycache__/override.cpython-39.pyc create mode 100644 venv/Lib/site-packages/_distutils_hack/override.py create mode 100644 venv/Lib/site-packages/distutils-precedence.pth create mode 100644 venv/Lib/site-packages/pip-22.0.4.dist-info/INSTALLER create mode 100644 venv/Lib/site-packages/pip-22.0.4.dist-info/LICENSE.txt create mode 100644 venv/Lib/site-packages/pip-22.0.4.dist-info/METADATA create mode 100644 venv/Lib/site-packages/pip-22.0.4.dist-info/RECORD create mode 100644 venv/Lib/site-packages/pip-22.0.4.dist-info/WHEEL create mode 100644 venv/Lib/site-packages/pip-22.0.4.dist-info/entry_points.txt create mode 100644 venv/Lib/site-packages/pip-22.0.4.dist-info/top_level.txt create mode 100644 venv/Lib/site-packages/pip/__init__.py create mode 100644 venv/Lib/site-packages/pip/__main__.py create mode 100644 venv/Lib/site-packages/pip/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/__pycache__/__main__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/__init__.py create mode 100644 venv/Lib/site-packages/pip/_internal/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/__pycache__/build_env.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/__pycache__/cache.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/__pycache__/configuration.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/__pycache__/exceptions.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/__pycache__/main.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/__pycache__/pyproject.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/__pycache__/self_outdated_check.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/__pycache__/wheel_builder.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/build_env.py create mode 100644 venv/Lib/site-packages/pip/_internal/cache.py create mode 100644 venv/Lib/site-packages/pip/_internal/cli/__init__.py create mode 100644 venv/Lib/site-packages/pip/_internal/cli/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/cli/__pycache__/autocompletion.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/cli/__pycache__/base_command.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/cli/__pycache__/cmdoptions.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/cli/__pycache__/command_context.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/cli/__pycache__/main.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/cli/__pycache__/main_parser.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/cli/__pycache__/parser.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/cli/__pycache__/progress_bars.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/cli/__pycache__/req_command.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/cli/__pycache__/spinners.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/cli/__pycache__/status_codes.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/cli/autocompletion.py create mode 100644 venv/Lib/site-packages/pip/_internal/cli/base_command.py create mode 100644 venv/Lib/site-packages/pip/_internal/cli/cmdoptions.py create mode 100644 venv/Lib/site-packages/pip/_internal/cli/command_context.py create mode 100644 venv/Lib/site-packages/pip/_internal/cli/main.py create mode 100644 venv/Lib/site-packages/pip/_internal/cli/main_parser.py create mode 100644 venv/Lib/site-packages/pip/_internal/cli/parser.py create mode 100644 venv/Lib/site-packages/pip/_internal/cli/progress_bars.py create mode 100644 venv/Lib/site-packages/pip/_internal/cli/req_command.py create mode 100644 venv/Lib/site-packages/pip/_internal/cli/spinners.py create mode 100644 venv/Lib/site-packages/pip/_internal/cli/status_codes.py create mode 100644 venv/Lib/site-packages/pip/_internal/commands/__init__.py create mode 100644 venv/Lib/site-packages/pip/_internal/commands/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/commands/__pycache__/cache.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/commands/__pycache__/check.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/commands/__pycache__/completion.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/commands/__pycache__/configuration.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/commands/__pycache__/debug.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/commands/__pycache__/download.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/commands/__pycache__/freeze.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/commands/__pycache__/hash.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/commands/__pycache__/help.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/commands/__pycache__/index.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/commands/__pycache__/install.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/commands/__pycache__/list.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/commands/__pycache__/search.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/commands/__pycache__/show.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/commands/__pycache__/uninstall.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/commands/__pycache__/wheel.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/commands/cache.py create mode 100644 venv/Lib/site-packages/pip/_internal/commands/check.py create mode 100644 venv/Lib/site-packages/pip/_internal/commands/completion.py create mode 100644 venv/Lib/site-packages/pip/_internal/commands/configuration.py create mode 100644 venv/Lib/site-packages/pip/_internal/commands/debug.py create mode 100644 venv/Lib/site-packages/pip/_internal/commands/download.py create mode 100644 venv/Lib/site-packages/pip/_internal/commands/freeze.py create mode 100644 venv/Lib/site-packages/pip/_internal/commands/hash.py create mode 100644 venv/Lib/site-packages/pip/_internal/commands/help.py create mode 100644 venv/Lib/site-packages/pip/_internal/commands/index.py create mode 100644 venv/Lib/site-packages/pip/_internal/commands/install.py create mode 100644 venv/Lib/site-packages/pip/_internal/commands/list.py create mode 100644 venv/Lib/site-packages/pip/_internal/commands/search.py create mode 100644 venv/Lib/site-packages/pip/_internal/commands/show.py create mode 100644 venv/Lib/site-packages/pip/_internal/commands/uninstall.py create mode 100644 venv/Lib/site-packages/pip/_internal/commands/wheel.py create mode 100644 venv/Lib/site-packages/pip/_internal/configuration.py create mode 100644 venv/Lib/site-packages/pip/_internal/distributions/__init__.py create mode 100644 venv/Lib/site-packages/pip/_internal/distributions/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/distributions/__pycache__/base.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/distributions/__pycache__/installed.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/distributions/__pycache__/sdist.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/distributions/__pycache__/wheel.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/distributions/base.py create mode 100644 venv/Lib/site-packages/pip/_internal/distributions/installed.py create mode 100644 venv/Lib/site-packages/pip/_internal/distributions/sdist.py create mode 100644 venv/Lib/site-packages/pip/_internal/distributions/wheel.py create mode 100644 venv/Lib/site-packages/pip/_internal/exceptions.py create mode 100644 venv/Lib/site-packages/pip/_internal/index/__init__.py create mode 100644 venv/Lib/site-packages/pip/_internal/index/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/index/__pycache__/collector.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/index/__pycache__/package_finder.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/index/__pycache__/sources.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/index/collector.py create mode 100644 venv/Lib/site-packages/pip/_internal/index/package_finder.py create mode 100644 venv/Lib/site-packages/pip/_internal/index/sources.py create mode 100644 venv/Lib/site-packages/pip/_internal/locations/__init__.py create mode 100644 venv/Lib/site-packages/pip/_internal/locations/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/locations/__pycache__/_distutils.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/locations/__pycache__/_sysconfig.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/locations/__pycache__/base.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/locations/_distutils.py create mode 100644 venv/Lib/site-packages/pip/_internal/locations/_sysconfig.py create mode 100644 venv/Lib/site-packages/pip/_internal/locations/base.py create mode 100644 venv/Lib/site-packages/pip/_internal/main.py create mode 100644 venv/Lib/site-packages/pip/_internal/metadata/__init__.py create mode 100644 venv/Lib/site-packages/pip/_internal/metadata/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/metadata/__pycache__/base.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/metadata/__pycache__/pkg_resources.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/metadata/base.py create mode 100644 venv/Lib/site-packages/pip/_internal/metadata/pkg_resources.py create mode 100644 venv/Lib/site-packages/pip/_internal/models/__init__.py create mode 100644 venv/Lib/site-packages/pip/_internal/models/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/models/__pycache__/candidate.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/models/__pycache__/direct_url.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/models/__pycache__/format_control.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/models/__pycache__/index.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/models/__pycache__/link.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/models/__pycache__/scheme.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/models/__pycache__/search_scope.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/models/__pycache__/selection_prefs.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/models/__pycache__/target_python.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/models/__pycache__/wheel.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/models/candidate.py create mode 100644 venv/Lib/site-packages/pip/_internal/models/direct_url.py create mode 100644 venv/Lib/site-packages/pip/_internal/models/format_control.py create mode 100644 venv/Lib/site-packages/pip/_internal/models/index.py create mode 100644 venv/Lib/site-packages/pip/_internal/models/link.py create mode 100644 venv/Lib/site-packages/pip/_internal/models/scheme.py create mode 100644 venv/Lib/site-packages/pip/_internal/models/search_scope.py create mode 100644 venv/Lib/site-packages/pip/_internal/models/selection_prefs.py create mode 100644 venv/Lib/site-packages/pip/_internal/models/target_python.py create mode 100644 venv/Lib/site-packages/pip/_internal/models/wheel.py create mode 100644 venv/Lib/site-packages/pip/_internal/network/__init__.py create mode 100644 venv/Lib/site-packages/pip/_internal/network/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/network/__pycache__/auth.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/network/__pycache__/cache.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/network/__pycache__/download.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/network/__pycache__/lazy_wheel.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/network/__pycache__/session.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/network/__pycache__/utils.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/network/__pycache__/xmlrpc.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/network/auth.py create mode 100644 venv/Lib/site-packages/pip/_internal/network/cache.py create mode 100644 venv/Lib/site-packages/pip/_internal/network/download.py create mode 100644 venv/Lib/site-packages/pip/_internal/network/lazy_wheel.py create mode 100644 venv/Lib/site-packages/pip/_internal/network/session.py create mode 100644 venv/Lib/site-packages/pip/_internal/network/utils.py create mode 100644 venv/Lib/site-packages/pip/_internal/network/xmlrpc.py create mode 100644 venv/Lib/site-packages/pip/_internal/operations/__init__.py create mode 100644 venv/Lib/site-packages/pip/_internal/operations/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/operations/__pycache__/check.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/operations/__pycache__/freeze.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/operations/__pycache__/prepare.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/operations/build/__init__.py create mode 100644 venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/metadata.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/metadata_editable.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/metadata_legacy.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/wheel.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/wheel_editable.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/wheel_legacy.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/operations/build/metadata.py create mode 100644 venv/Lib/site-packages/pip/_internal/operations/build/metadata_editable.py create mode 100644 venv/Lib/site-packages/pip/_internal/operations/build/metadata_legacy.py create mode 100644 venv/Lib/site-packages/pip/_internal/operations/build/wheel.py create mode 100644 venv/Lib/site-packages/pip/_internal/operations/build/wheel_editable.py create mode 100644 venv/Lib/site-packages/pip/_internal/operations/build/wheel_legacy.py create mode 100644 venv/Lib/site-packages/pip/_internal/operations/check.py create mode 100644 venv/Lib/site-packages/pip/_internal/operations/freeze.py create mode 100644 venv/Lib/site-packages/pip/_internal/operations/install/__init__.py create mode 100644 venv/Lib/site-packages/pip/_internal/operations/install/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/operations/install/__pycache__/editable_legacy.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/operations/install/__pycache__/legacy.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/operations/install/__pycache__/wheel.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/operations/install/editable_legacy.py create mode 100644 venv/Lib/site-packages/pip/_internal/operations/install/legacy.py create mode 100644 venv/Lib/site-packages/pip/_internal/operations/install/wheel.py create mode 100644 venv/Lib/site-packages/pip/_internal/operations/prepare.py create mode 100644 venv/Lib/site-packages/pip/_internal/pyproject.py create mode 100644 venv/Lib/site-packages/pip/_internal/req/__init__.py create mode 100644 venv/Lib/site-packages/pip/_internal/req/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/req/__pycache__/constructors.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/req/__pycache__/req_file.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/req/__pycache__/req_install.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/req/__pycache__/req_set.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/req/__pycache__/req_tracker.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/req/__pycache__/req_uninstall.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/req/constructors.py create mode 100644 venv/Lib/site-packages/pip/_internal/req/req_file.py create mode 100644 venv/Lib/site-packages/pip/_internal/req/req_install.py create mode 100644 venv/Lib/site-packages/pip/_internal/req/req_set.py create mode 100644 venv/Lib/site-packages/pip/_internal/req/req_tracker.py create mode 100644 venv/Lib/site-packages/pip/_internal/req/req_uninstall.py create mode 100644 venv/Lib/site-packages/pip/_internal/resolution/__init__.py create mode 100644 venv/Lib/site-packages/pip/_internal/resolution/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/resolution/__pycache__/base.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/resolution/base.py create mode 100644 venv/Lib/site-packages/pip/_internal/resolution/legacy/__init__.py create mode 100644 venv/Lib/site-packages/pip/_internal/resolution/legacy/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/resolution/legacy/__pycache__/resolver.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/resolution/legacy/resolver.py create mode 100644 venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__init__.py create mode 100644 venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/base.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/candidates.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/factory.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/found_candidates.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/provider.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/reporter.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/requirements.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/resolver.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/resolution/resolvelib/base.py create mode 100644 venv/Lib/site-packages/pip/_internal/resolution/resolvelib/candidates.py create mode 100644 venv/Lib/site-packages/pip/_internal/resolution/resolvelib/factory.py create mode 100644 venv/Lib/site-packages/pip/_internal/resolution/resolvelib/found_candidates.py create mode 100644 venv/Lib/site-packages/pip/_internal/resolution/resolvelib/provider.py create mode 100644 venv/Lib/site-packages/pip/_internal/resolution/resolvelib/reporter.py create mode 100644 venv/Lib/site-packages/pip/_internal/resolution/resolvelib/requirements.py create mode 100644 venv/Lib/site-packages/pip/_internal/resolution/resolvelib/resolver.py create mode 100644 venv/Lib/site-packages/pip/_internal/self_outdated_check.py create mode 100644 venv/Lib/site-packages/pip/_internal/utils/__init__.py create mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/_log.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/appdirs.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/compat.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/compatibility_tags.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/datetime.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/deprecation.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/direct_url_helpers.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/distutils_args.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/egg_link.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/encoding.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/entrypoints.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/filesystem.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/filetypes.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/glibc.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/hashes.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/inject_securetransport.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/logging.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/misc.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/models.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/packaging.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/setuptools_build.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/subprocess.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/temp_dir.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/unpacking.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/urls.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/virtualenv.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/wheel.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/utils/_log.py create mode 100644 venv/Lib/site-packages/pip/_internal/utils/appdirs.py create mode 100644 venv/Lib/site-packages/pip/_internal/utils/compat.py create mode 100644 venv/Lib/site-packages/pip/_internal/utils/compatibility_tags.py create mode 100644 venv/Lib/site-packages/pip/_internal/utils/datetime.py create mode 100644 venv/Lib/site-packages/pip/_internal/utils/deprecation.py create mode 100644 venv/Lib/site-packages/pip/_internal/utils/direct_url_helpers.py create mode 100644 venv/Lib/site-packages/pip/_internal/utils/distutils_args.py create mode 100644 venv/Lib/site-packages/pip/_internal/utils/egg_link.py create mode 100644 venv/Lib/site-packages/pip/_internal/utils/encoding.py create mode 100644 venv/Lib/site-packages/pip/_internal/utils/entrypoints.py create mode 100644 venv/Lib/site-packages/pip/_internal/utils/filesystem.py create mode 100644 venv/Lib/site-packages/pip/_internal/utils/filetypes.py create mode 100644 venv/Lib/site-packages/pip/_internal/utils/glibc.py create mode 100644 venv/Lib/site-packages/pip/_internal/utils/hashes.py create mode 100644 venv/Lib/site-packages/pip/_internal/utils/inject_securetransport.py create mode 100644 venv/Lib/site-packages/pip/_internal/utils/logging.py create mode 100644 venv/Lib/site-packages/pip/_internal/utils/misc.py create mode 100644 venv/Lib/site-packages/pip/_internal/utils/models.py create mode 100644 venv/Lib/site-packages/pip/_internal/utils/packaging.py create mode 100644 venv/Lib/site-packages/pip/_internal/utils/setuptools_build.py create mode 100644 venv/Lib/site-packages/pip/_internal/utils/subprocess.py create mode 100644 venv/Lib/site-packages/pip/_internal/utils/temp_dir.py create mode 100644 venv/Lib/site-packages/pip/_internal/utils/unpacking.py create mode 100644 venv/Lib/site-packages/pip/_internal/utils/urls.py create mode 100644 venv/Lib/site-packages/pip/_internal/utils/virtualenv.py create mode 100644 venv/Lib/site-packages/pip/_internal/utils/wheel.py create mode 100644 venv/Lib/site-packages/pip/_internal/vcs/__init__.py create mode 100644 venv/Lib/site-packages/pip/_internal/vcs/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/vcs/__pycache__/bazaar.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/vcs/__pycache__/git.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/vcs/__pycache__/mercurial.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/vcs/__pycache__/subversion.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/vcs/__pycache__/versioncontrol.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_internal/vcs/bazaar.py create mode 100644 venv/Lib/site-packages/pip/_internal/vcs/git.py create mode 100644 venv/Lib/site-packages/pip/_internal/vcs/mercurial.py create mode 100644 venv/Lib/site-packages/pip/_internal/vcs/subversion.py create mode 100644 venv/Lib/site-packages/pip/_internal/vcs/versioncontrol.py create mode 100644 venv/Lib/site-packages/pip/_internal/wheel_builder.py create mode 100644 venv/Lib/site-packages/pip/_vendor/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/__pycache__/distro.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/__pycache__/six.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/__pycache__/typing_extensions.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/_cmd.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/adapter.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/cache.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/compat.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/controller.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/filewrapper.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/heuristics.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/serialize.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/wrapper.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/_cmd.py create mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/adapter.py create mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/cache.py create mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/__pycache__/file_cache.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/__pycache__/redis_cache.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/file_cache.py create mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/redis_cache.py create mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/compat.py create mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/controller.py create mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/filewrapper.py create mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/heuristics.py create mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/serialize.py create mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/wrapper.py create mode 100644 venv/Lib/site-packages/pip/_vendor/certifi/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/certifi/__main__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/certifi/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/certifi/__pycache__/__main__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/certifi/__pycache__/core.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/certifi/cacert.pem create mode 100644 venv/Lib/site-packages/pip/_vendor/certifi/core.py create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/big5freq.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/big5prober.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/chardistribution.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/charsetgroupprober.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/charsetprober.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/codingstatemachine.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/compat.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/cp949prober.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/enums.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/escprober.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/escsm.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/eucjpprober.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/euckrfreq.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/euckrprober.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/euctwfreq.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/euctwprober.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/gb2312freq.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/gb2312prober.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/hebrewprober.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/jisfreq.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/jpcntx.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/langbulgarianmodel.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/langgreekmodel.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/langhebrewmodel.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/langhungarianmodel.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/langrussianmodel.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/langthaimodel.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/langturkishmodel.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/latin1prober.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/mbcharsetprober.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/mbcsgroupprober.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/mbcssm.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/sbcharsetprober.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/sbcsgroupprober.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/sjisprober.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/universaldetector.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/utf8prober.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/version.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/big5freq.py create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/big5prober.py create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/chardistribution.py create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/charsetgroupprober.py create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/charsetprober.py create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/cli/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/cli/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/cli/__pycache__/chardetect.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/cli/chardetect.py create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/codingstatemachine.py create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/compat.py create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/cp949prober.py create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/enums.py create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/escprober.py create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/escsm.py create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/eucjpprober.py create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/euckrfreq.py create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/euckrprober.py create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/euctwfreq.py create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/euctwprober.py create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/gb2312freq.py create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/gb2312prober.py create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/hebrewprober.py create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/jisfreq.py create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/jpcntx.py create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/langbulgarianmodel.py create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/langgreekmodel.py create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/langhebrewmodel.py create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/langhungarianmodel.py create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/langrussianmodel.py create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/langthaimodel.py create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/langturkishmodel.py create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/latin1prober.py create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/mbcharsetprober.py create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/mbcsgroupprober.py create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/mbcssm.py create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/metadata/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/metadata/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/metadata/__pycache__/languages.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/metadata/languages.py create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/sbcharsetprober.py create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/sbcsgroupprober.py create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/sjisprober.py create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/universaldetector.py create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/utf8prober.py create mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/version.py create mode 100644 venv/Lib/site-packages/pip/_vendor/colorama/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/colorama/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/colorama/__pycache__/ansi.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/colorama/__pycache__/ansitowin32.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/colorama/__pycache__/initialise.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/colorama/__pycache__/win32.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/colorama/__pycache__/winterm.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/colorama/ansi.py create mode 100644 venv/Lib/site-packages/pip/_vendor/colorama/ansitowin32.py create mode 100644 venv/Lib/site-packages/pip/_vendor/colorama/initialise.py create mode 100644 venv/Lib/site-packages/pip/_vendor/colorama/win32.py create mode 100644 venv/Lib/site-packages/pip/_vendor/colorama/winterm.py create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/compat.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/database.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/index.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/locators.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/manifest.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/markers.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/metadata.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/resources.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/scripts.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/util.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/version.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/wheel.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/_backport/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/_backport/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/_backport/__pycache__/misc.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/_backport/__pycache__/shutil.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/_backport/__pycache__/sysconfig.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/_backport/__pycache__/tarfile.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/_backport/misc.py create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/_backport/shutil.py create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/_backport/sysconfig.cfg create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/_backport/sysconfig.py create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/_backport/tarfile.py create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/compat.py create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/database.py create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/index.py create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/locators.py create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/manifest.py create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/markers.py create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/metadata.py create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/resources.py create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/scripts.py create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/t32.exe create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/t64-arm.exe create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/t64.exe create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/util.py create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/version.py create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/w32.exe create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/w64-arm.exe create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/w64.exe create mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/wheel.py create mode 100644 venv/Lib/site-packages/pip/_vendor/distro.py create mode 100644 venv/Lib/site-packages/pip/_vendor/html5lib/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/html5lib/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/html5lib/__pycache__/_ihatexml.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/html5lib/__pycache__/_inputstream.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/html5lib/__pycache__/_tokenizer.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/html5lib/__pycache__/_utils.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/html5lib/__pycache__/constants.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/html5lib/__pycache__/html5parser.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/html5lib/__pycache__/serializer.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/html5lib/_ihatexml.py create mode 100644 venv/Lib/site-packages/pip/_vendor/html5lib/_inputstream.py create mode 100644 venv/Lib/site-packages/pip/_vendor/html5lib/_tokenizer.py create mode 100644 venv/Lib/site-packages/pip/_vendor/html5lib/_trie/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/html5lib/_trie/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/html5lib/_trie/__pycache__/_base.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/html5lib/_trie/__pycache__/py.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/html5lib/_trie/_base.py create mode 100644 venv/Lib/site-packages/pip/_vendor/html5lib/_trie/py.py create mode 100644 venv/Lib/site-packages/pip/_vendor/html5lib/_utils.py create mode 100644 venv/Lib/site-packages/pip/_vendor/html5lib/constants.py create mode 100644 venv/Lib/site-packages/pip/_vendor/html5lib/filters/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/html5lib/filters/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/html5lib/filters/__pycache__/alphabeticalattributes.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/html5lib/filters/__pycache__/base.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/html5lib/filters/__pycache__/inject_meta_charset.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/html5lib/filters/__pycache__/lint.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/html5lib/filters/__pycache__/optionaltags.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/html5lib/filters/__pycache__/sanitizer.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/html5lib/filters/__pycache__/whitespace.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/html5lib/filters/alphabeticalattributes.py create mode 100644 venv/Lib/site-packages/pip/_vendor/html5lib/filters/base.py create mode 100644 venv/Lib/site-packages/pip/_vendor/html5lib/filters/inject_meta_charset.py create mode 100644 venv/Lib/site-packages/pip/_vendor/html5lib/filters/lint.py create mode 100644 venv/Lib/site-packages/pip/_vendor/html5lib/filters/optionaltags.py create mode 100644 venv/Lib/site-packages/pip/_vendor/html5lib/filters/sanitizer.py create mode 100644 venv/Lib/site-packages/pip/_vendor/html5lib/filters/whitespace.py create mode 100644 venv/Lib/site-packages/pip/_vendor/html5lib/html5parser.py create mode 100644 venv/Lib/site-packages/pip/_vendor/html5lib/serializer.py create mode 100644 venv/Lib/site-packages/pip/_vendor/html5lib/treeadapters/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/html5lib/treeadapters/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/html5lib/treeadapters/__pycache__/genshi.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/html5lib/treeadapters/__pycache__/sax.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/html5lib/treeadapters/genshi.py create mode 100644 venv/Lib/site-packages/pip/_vendor/html5lib/treeadapters/sax.py create mode 100644 venv/Lib/site-packages/pip/_vendor/html5lib/treebuilders/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/html5lib/treebuilders/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/html5lib/treebuilders/__pycache__/base.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/html5lib/treebuilders/__pycache__/dom.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/html5lib/treebuilders/__pycache__/etree.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/html5lib/treebuilders/__pycache__/etree_lxml.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/html5lib/treebuilders/base.py create mode 100644 venv/Lib/site-packages/pip/_vendor/html5lib/treebuilders/dom.py create mode 100644 venv/Lib/site-packages/pip/_vendor/html5lib/treebuilders/etree.py create mode 100644 venv/Lib/site-packages/pip/_vendor/html5lib/treebuilders/etree_lxml.py create mode 100644 venv/Lib/site-packages/pip/_vendor/html5lib/treewalkers/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/html5lib/treewalkers/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/html5lib/treewalkers/__pycache__/base.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/html5lib/treewalkers/__pycache__/dom.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/html5lib/treewalkers/__pycache__/etree.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/html5lib/treewalkers/__pycache__/etree_lxml.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/html5lib/treewalkers/__pycache__/genshi.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/html5lib/treewalkers/base.py create mode 100644 venv/Lib/site-packages/pip/_vendor/html5lib/treewalkers/dom.py create mode 100644 venv/Lib/site-packages/pip/_vendor/html5lib/treewalkers/etree.py create mode 100644 venv/Lib/site-packages/pip/_vendor/html5lib/treewalkers/etree_lxml.py create mode 100644 venv/Lib/site-packages/pip/_vendor/html5lib/treewalkers/genshi.py create mode 100644 venv/Lib/site-packages/pip/_vendor/idna/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/idna/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/idna/__pycache__/codec.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/idna/__pycache__/compat.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/idna/__pycache__/core.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/idna/__pycache__/idnadata.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/idna/__pycache__/intranges.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/idna/__pycache__/package_data.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/idna/__pycache__/uts46data.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/idna/codec.py create mode 100644 venv/Lib/site-packages/pip/_vendor/idna/compat.py create mode 100644 venv/Lib/site-packages/pip/_vendor/idna/core.py create mode 100644 venv/Lib/site-packages/pip/_vendor/idna/idnadata.py create mode 100644 venv/Lib/site-packages/pip/_vendor/idna/intranges.py create mode 100644 venv/Lib/site-packages/pip/_vendor/idna/package_data.py create mode 100644 venv/Lib/site-packages/pip/_vendor/idna/uts46data.py create mode 100644 venv/Lib/site-packages/pip/_vendor/msgpack/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/msgpack/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/msgpack/__pycache__/_version.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/msgpack/__pycache__/exceptions.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/msgpack/__pycache__/ext.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/msgpack/__pycache__/fallback.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/msgpack/_version.py create mode 100644 venv/Lib/site-packages/pip/_vendor/msgpack/exceptions.py create mode 100644 venv/Lib/site-packages/pip/_vendor/msgpack/ext.py create mode 100644 venv/Lib/site-packages/pip/_vendor/msgpack/fallback.py create mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/__about__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/__about__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/_manylinux.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/_musllinux.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/_structures.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/markers.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/requirements.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/specifiers.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/tags.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/utils.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/version.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/_manylinux.py create mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/_musllinux.py create mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/_structures.py create mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/markers.py create mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/requirements.py create mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/specifiers.py create mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/tags.py create mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/utils.py create mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/version.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pep517/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pep517/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pep517/__pycache__/build.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pep517/__pycache__/check.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pep517/__pycache__/colorlog.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pep517/__pycache__/compat.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pep517/__pycache__/dirtools.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pep517/__pycache__/envbuild.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pep517/__pycache__/meta.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pep517/__pycache__/wrappers.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pep517/build.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pep517/check.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pep517/colorlog.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pep517/compat.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pep517/dirtools.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pep517/envbuild.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pep517/in_process/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pep517/in_process/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pep517/in_process/__pycache__/_in_process.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pep517/in_process/_in_process.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pep517/meta.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pep517/wrappers.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pkg_resources/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pkg_resources/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pkg_resources/__pycache__/py31compat.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pkg_resources/py31compat.py create mode 100644 venv/Lib/site-packages/pip/_vendor/platformdirs/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/platformdirs/__main__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/__main__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/android.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/api.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/macos.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/unix.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/version.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/windows.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/platformdirs/android.py create mode 100644 venv/Lib/site-packages/pip/_vendor/platformdirs/api.py create mode 100644 venv/Lib/site-packages/pip/_vendor/platformdirs/macos.py create mode 100644 venv/Lib/site-packages/pip/_vendor/platformdirs/unix.py create mode 100644 venv/Lib/site-packages/pip/_vendor/platformdirs/version.py create mode 100644 venv/Lib/site-packages/pip/_vendor/platformdirs/windows.py create mode 100644 venv/Lib/site-packages/pip/_vendor/progress/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/progress/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/progress/__pycache__/bar.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/progress/__pycache__/colors.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/progress/__pycache__/counter.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/progress/__pycache__/spinner.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/progress/bar.py create mode 100644 venv/Lib/site-packages/pip/_vendor/progress/colors.py create mode 100644 venv/Lib/site-packages/pip/_vendor/progress/counter.py create mode 100644 venv/Lib/site-packages/pip/_vendor/progress/spinner.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/__main__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/__main__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/cmdline.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/console.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/filter.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/formatter.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/lexer.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/modeline.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/plugin.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/regexopt.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/scanner.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/sphinxext.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/style.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/token.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/unistring.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/util.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/cmdline.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/console.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/filter.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/filters/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/filters/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatter.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/_mapping.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/bbcode.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/groff.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/html.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/img.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/irc.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/latex.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/other.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/pangomarkup.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/rtf.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/svg.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/terminal.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/terminal256.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/_mapping.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/bbcode.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/groff.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/html.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/img.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/irc.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/latex.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/other.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/pangomarkup.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/rtf.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/svg.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/terminal.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/terminal256.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/lexer.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/lexers/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/lexers/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/lexers/__pycache__/_mapping.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/lexers/__pycache__/python.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/lexers/_mapping.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/lexers/python.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/modeline.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/plugin.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/regexopt.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/scanner.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/sphinxext.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/style.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/styles/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/styles/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/token.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/unistring.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/util.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pyparsing/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pyparsing/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pyparsing/__pycache__/actions.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pyparsing/__pycache__/common.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pyparsing/__pycache__/core.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pyparsing/__pycache__/exceptions.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pyparsing/__pycache__/helpers.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pyparsing/__pycache__/results.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pyparsing/__pycache__/testing.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pyparsing/__pycache__/unicode.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pyparsing/__pycache__/util.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pyparsing/actions.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pyparsing/common.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pyparsing/core.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pyparsing/diagram/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pyparsing/diagram/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/pyparsing/exceptions.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pyparsing/helpers.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pyparsing/results.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pyparsing/testing.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pyparsing/unicode.py create mode 100644 venv/Lib/site-packages/pip/_vendor/pyparsing/util.py create mode 100644 venv/Lib/site-packages/pip/_vendor/requests/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/requests/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/requests/__pycache__/__version__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/requests/__pycache__/_internal_utils.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/requests/__pycache__/adapters.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/requests/__pycache__/api.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/requests/__pycache__/auth.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/requests/__pycache__/certs.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/requests/__pycache__/compat.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/requests/__pycache__/cookies.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/requests/__pycache__/exceptions.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/requests/__pycache__/help.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/requests/__pycache__/hooks.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/requests/__pycache__/models.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/requests/__pycache__/packages.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/requests/__pycache__/sessions.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/requests/__pycache__/status_codes.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/requests/__pycache__/structures.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/requests/__pycache__/utils.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/requests/__version__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/requests/_internal_utils.py create mode 100644 venv/Lib/site-packages/pip/_vendor/requests/adapters.py create mode 100644 venv/Lib/site-packages/pip/_vendor/requests/api.py create mode 100644 venv/Lib/site-packages/pip/_vendor/requests/auth.py create mode 100644 venv/Lib/site-packages/pip/_vendor/requests/certs.py create mode 100644 venv/Lib/site-packages/pip/_vendor/requests/compat.py create mode 100644 venv/Lib/site-packages/pip/_vendor/requests/cookies.py create mode 100644 venv/Lib/site-packages/pip/_vendor/requests/exceptions.py create mode 100644 venv/Lib/site-packages/pip/_vendor/requests/help.py create mode 100644 venv/Lib/site-packages/pip/_vendor/requests/hooks.py create mode 100644 venv/Lib/site-packages/pip/_vendor/requests/models.py create mode 100644 venv/Lib/site-packages/pip/_vendor/requests/packages.py create mode 100644 venv/Lib/site-packages/pip/_vendor/requests/sessions.py create mode 100644 venv/Lib/site-packages/pip/_vendor/requests/status_codes.py create mode 100644 venv/Lib/site-packages/pip/_vendor/requests/structures.py create mode 100644 venv/Lib/site-packages/pip/_vendor/requests/utils.py create mode 100644 venv/Lib/site-packages/pip/_vendor/resolvelib/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/resolvelib/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/resolvelib/__pycache__/providers.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/resolvelib/__pycache__/reporters.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/resolvelib/__pycache__/resolvers.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/resolvelib/__pycache__/structs.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/resolvelib/compat/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/resolvelib/compat/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/resolvelib/compat/__pycache__/collections_abc.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/resolvelib/compat/collections_abc.py create mode 100644 venv/Lib/site-packages/pip/_vendor/resolvelib/providers.py create mode 100644 venv/Lib/site-packages/pip/_vendor/resolvelib/reporters.py create mode 100644 venv/Lib/site-packages/pip/_vendor/resolvelib/resolvers.py create mode 100644 venv/Lib/site-packages/pip/_vendor/resolvelib/structs.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__main__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/__main__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_cell_widths.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_emoji_codes.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_emoji_replace.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_extension.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_inspect.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_log_render.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_loop.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_lru_cache.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_palettes.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_pick.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_ratio.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_spinners.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_stack.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_timer.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_windows.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_wrap.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/abc.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/align.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/ansi.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/bar.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/box.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/cells.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/color.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/color_triplet.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/columns.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/console.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/constrain.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/containers.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/control.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/default_styles.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/diagnose.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/emoji.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/errors.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/file_proxy.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/filesize.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/highlighter.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/json.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/jupyter.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/layout.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/live.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/live_render.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/logging.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/markup.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/measure.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/padding.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/pager.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/palette.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/panel.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/pretty.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/progress.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/progress_bar.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/prompt.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/protocol.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/region.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/repr.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/rule.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/scope.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/screen.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/segment.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/spinner.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/status.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/style.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/styled.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/syntax.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/table.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/tabulate.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/terminal_theme.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/text.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/theme.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/themes.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/traceback.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/tree.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/_cell_widths.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/_emoji_codes.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/_emoji_replace.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/_extension.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/_inspect.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/_log_render.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/_loop.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/_lru_cache.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/_palettes.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/_pick.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/_ratio.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/_spinners.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/_stack.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/_timer.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/_windows.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/_wrap.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/abc.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/align.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/ansi.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/bar.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/box.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/cells.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/color.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/color_triplet.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/columns.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/console.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/constrain.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/containers.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/control.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/default_styles.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/diagnose.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/emoji.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/errors.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/file_proxy.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/filesize.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/highlighter.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/json.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/jupyter.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/layout.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/live.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/live_render.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/logging.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/markup.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/measure.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/padding.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/pager.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/palette.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/panel.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/pretty.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/progress.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/progress_bar.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/prompt.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/protocol.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/region.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/repr.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/rule.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/scope.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/screen.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/segment.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/spinner.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/status.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/style.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/styled.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/syntax.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/table.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/tabulate.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/terminal_theme.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/text.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/theme.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/themes.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/traceback.py create mode 100644 venv/Lib/site-packages/pip/_vendor/rich/tree.py create mode 100644 venv/Lib/site-packages/pip/_vendor/six.py create mode 100644 venv/Lib/site-packages/pip/_vendor/tenacity/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/tenacity/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/tenacity/__pycache__/_asyncio.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/tenacity/__pycache__/_utils.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/tenacity/__pycache__/after.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/tenacity/__pycache__/before.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/tenacity/__pycache__/before_sleep.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/tenacity/__pycache__/nap.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/tenacity/__pycache__/retry.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/tenacity/__pycache__/stop.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/tenacity/__pycache__/tornadoweb.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/tenacity/__pycache__/wait.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/tenacity/_asyncio.py create mode 100644 venv/Lib/site-packages/pip/_vendor/tenacity/_utils.py create mode 100644 venv/Lib/site-packages/pip/_vendor/tenacity/after.py create mode 100644 venv/Lib/site-packages/pip/_vendor/tenacity/before.py create mode 100644 venv/Lib/site-packages/pip/_vendor/tenacity/before_sleep.py create mode 100644 venv/Lib/site-packages/pip/_vendor/tenacity/nap.py create mode 100644 venv/Lib/site-packages/pip/_vendor/tenacity/retry.py create mode 100644 venv/Lib/site-packages/pip/_vendor/tenacity/stop.py create mode 100644 venv/Lib/site-packages/pip/_vendor/tenacity/tornadoweb.py create mode 100644 venv/Lib/site-packages/pip/_vendor/tenacity/wait.py create mode 100644 venv/Lib/site-packages/pip/_vendor/tomli/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/tomli/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/tomli/__pycache__/_parser.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/tomli/__pycache__/_re.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/tomli/_parser.py create mode 100644 venv/Lib/site-packages/pip/_vendor/tomli/_re.py create mode 100644 venv/Lib/site-packages/pip/_vendor/typing_extensions.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/_collections.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/_version.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/connection.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/connectionpool.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/exceptions.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/fields.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/filepost.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/poolmanager.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/request.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/response.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/_collections.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/_version.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/connection.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/connectionpool.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/_appengine_environ.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/appengine.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/ntlmpool.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/pyopenssl.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/securetransport.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/socks.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/contrib/_appengine_environ.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__pycache__/bindings.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__pycache__/low_level.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/bindings.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/low_level.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/contrib/appengine.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/contrib/ntlmpool.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/contrib/pyopenssl.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/contrib/securetransport.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/contrib/socks.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/exceptions.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/fields.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/filepost.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/packages/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/packages/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/packages/__pycache__/six.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/packages/backports/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/packages/backports/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/packages/backports/__pycache__/makefile.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/packages/backports/makefile.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/packages/six.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/poolmanager.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/request.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/response.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/connection.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/proxy.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/queue.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/request.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/response.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/retry.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/ssl_.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/ssl_match_hostname.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/ssltransport.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/timeout.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/url.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/wait.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/connection.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/proxy.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/queue.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/request.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/response.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/retry.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/ssl_.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/ssl_match_hostname.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/ssltransport.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/timeout.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/url.py create mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/wait.py create mode 100644 venv/Lib/site-packages/pip/_vendor/vendor.txt create mode 100644 venv/Lib/site-packages/pip/_vendor/webencodings/__init__.py create mode 100644 venv/Lib/site-packages/pip/_vendor/webencodings/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/webencodings/__pycache__/labels.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/webencodings/__pycache__/mklabels.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/webencodings/__pycache__/tests.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/webencodings/__pycache__/x_user_defined.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pip/_vendor/webencodings/labels.py create mode 100644 venv/Lib/site-packages/pip/_vendor/webencodings/mklabels.py create mode 100644 venv/Lib/site-packages/pip/_vendor/webencodings/tests.py create mode 100644 venv/Lib/site-packages/pip/_vendor/webencodings/x_user_defined.py create mode 100644 venv/Lib/site-packages/pip/py.typed create mode 100644 venv/Lib/site-packages/pkg_resources/__init__.py create mode 100644 venv/Lib/site-packages/pkg_resources/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/__init__.py create mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/__pycache__/appdirs.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/__pycache__/pyparsing.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/__pycache__/zipp.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/appdirs.py create mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/importlib_resources/__init__.py create mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/importlib_resources/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/importlib_resources/__pycache__/_adapters.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/importlib_resources/__pycache__/_common.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/importlib_resources/__pycache__/_compat.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/importlib_resources/__pycache__/_itertools.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/importlib_resources/__pycache__/_legacy.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/importlib_resources/__pycache__/abc.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/importlib_resources/__pycache__/readers.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/importlib_resources/__pycache__/simple.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/importlib_resources/_adapters.py create mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/importlib_resources/_common.py create mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/importlib_resources/_compat.py create mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/importlib_resources/_itertools.py create mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/importlib_resources/_legacy.py create mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/importlib_resources/abc.py create mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/importlib_resources/readers.py create mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/importlib_resources/simple.py create mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/jaraco/__init__.py create mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/jaraco/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/jaraco/__pycache__/context.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/jaraco/__pycache__/functools.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/jaraco/context.py create mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/jaraco/functools.py create mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/jaraco/text/__init__.py create mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/jaraco/text/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/more_itertools/__init__.py create mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/more_itertools/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/more_itertools/__pycache__/more.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/more_itertools/__pycache__/recipes.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/more_itertools/more.py create mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/more_itertools/recipes.py create mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/packaging/__about__.py create mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/packaging/__init__.py create mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/packaging/__pycache__/__about__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/packaging/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/packaging/__pycache__/_manylinux.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/packaging/__pycache__/_musllinux.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/packaging/__pycache__/_structures.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/packaging/__pycache__/markers.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/packaging/__pycache__/requirements.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/packaging/__pycache__/specifiers.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/packaging/__pycache__/tags.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/packaging/__pycache__/utils.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/packaging/__pycache__/version.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/packaging/_manylinux.py create mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/packaging/_musllinux.py create mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/packaging/_structures.py create mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/packaging/markers.py create mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/packaging/requirements.py create mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/packaging/specifiers.py create mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/packaging/tags.py create mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/packaging/utils.py create mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/packaging/version.py create mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/pyparsing.py create mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/zipp.py create mode 100644 venv/Lib/site-packages/pkg_resources/extern/__init__.py create mode 100644 venv/Lib/site-packages/pkg_resources/extern/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame-2.1.2.dist-info/INSTALLER create mode 100644 venv/Lib/site-packages/pygame-2.1.2.dist-info/METADATA create mode 100644 venv/Lib/site-packages/pygame-2.1.2.dist-info/RECORD create mode 100644 venv/Lib/site-packages/pygame-2.1.2.dist-info/REQUESTED create mode 100644 venv/Lib/site-packages/pygame-2.1.2.dist-info/WHEEL create mode 100644 venv/Lib/site-packages/pygame-2.1.2.dist-info/entry_points.txt create mode 100644 venv/Lib/site-packages/pygame-2.1.2.dist-info/top_level.txt create mode 100644 venv/Lib/site-packages/pygame/SDL2.dll create mode 100644 venv/Lib/site-packages/pygame/SDL2_image.dll create mode 100644 venv/Lib/site-packages/pygame/SDL2_mixer.dll create mode 100644 venv/Lib/site-packages/pygame/SDL2_ttf.dll create mode 100644 venv/Lib/site-packages/pygame/__init__.py create mode 100644 venv/Lib/site-packages/pygame/__init__.pyi create mode 100644 venv/Lib/site-packages/pygame/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/__pycache__/_camera_opencv.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/__pycache__/_camera_vidcapture.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/__pycache__/camera.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/__pycache__/colordict.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/__pycache__/cursors.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/__pycache__/draw_py.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/__pycache__/fastevent.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/__pycache__/freetype.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/__pycache__/ftfont.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/__pycache__/locals.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/__pycache__/macosx.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/__pycache__/midi.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/__pycache__/pkgdata.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/__pycache__/sndarray.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/__pycache__/sprite.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/__pycache__/surfarray.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/__pycache__/sysfont.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/__pycache__/version.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/__pyinstaller/__init__.py create mode 100644 venv/Lib/site-packages/pygame/__pyinstaller/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/__pyinstaller/__pycache__/hook-pygame.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/__pyinstaller/hook-pygame.py create mode 100644 venv/Lib/site-packages/pygame/_camera.cp39-win_amd64.pyd create mode 100644 venv/Lib/site-packages/pygame/_camera_opencv.py create mode 100644 venv/Lib/site-packages/pygame/_camera_vidcapture.py create mode 100644 venv/Lib/site-packages/pygame/_common.pyi create mode 100644 venv/Lib/site-packages/pygame/_freetype.cp39-win_amd64.pyd create mode 100644 venv/Lib/site-packages/pygame/_sdl2/__init__.py create mode 100644 venv/Lib/site-packages/pygame/_sdl2/__init__.pyi create mode 100644 venv/Lib/site-packages/pygame/_sdl2/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/_sdl2/audio.cp39-win_amd64.pyd create mode 100644 venv/Lib/site-packages/pygame/_sdl2/controller.cp39-win_amd64.pyd create mode 100644 venv/Lib/site-packages/pygame/_sdl2/controller.pyi create mode 100644 venv/Lib/site-packages/pygame/_sdl2/mixer.cp39-win_amd64.pyd create mode 100644 venv/Lib/site-packages/pygame/_sdl2/sdl2.cp39-win_amd64.pyd create mode 100644 venv/Lib/site-packages/pygame/_sdl2/touch.cp39-win_amd64.pyd create mode 100644 venv/Lib/site-packages/pygame/_sdl2/touch.pyi create mode 100644 venv/Lib/site-packages/pygame/_sdl2/video.cp39-win_amd64.pyd create mode 100644 venv/Lib/site-packages/pygame/_sdl2/video.pyi create mode 100644 venv/Lib/site-packages/pygame/_sprite.cp39-win_amd64.pyd create mode 100644 venv/Lib/site-packages/pygame/base.cp39-win_amd64.pyd create mode 100644 venv/Lib/site-packages/pygame/bufferproxy.cp39-win_amd64.pyd create mode 100644 venv/Lib/site-packages/pygame/bufferproxy.pyi create mode 100644 venv/Lib/site-packages/pygame/camera.py create mode 100644 venv/Lib/site-packages/pygame/camera.pyi create mode 100644 venv/Lib/site-packages/pygame/color.cp39-win_amd64.pyd create mode 100644 venv/Lib/site-packages/pygame/color.pyi create mode 100644 venv/Lib/site-packages/pygame/colordict.py create mode 100644 venv/Lib/site-packages/pygame/constants.cp39-win_amd64.pyd create mode 100644 venv/Lib/site-packages/pygame/constants.pyi create mode 100644 venv/Lib/site-packages/pygame/cursors.py create mode 100644 venv/Lib/site-packages/pygame/cursors.pyi create mode 100644 venv/Lib/site-packages/pygame/display.cp39-win_amd64.pyd create mode 100644 venv/Lib/site-packages/pygame/display.pyi create mode 100644 venv/Lib/site-packages/pygame/docs/__main__.py create mode 100644 venv/Lib/site-packages/pygame/docs/__pycache__/__main__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_images/AdvancedInputOutput1.gif create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_images/AdvancedInputOutput11.gif create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_images/AdvancedInputOutput2.gif create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_images/AdvancedInputOutput21.gif create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_images/AdvancedInputOutput3.gif create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_images/AdvancedInputOutput31.gif create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_images/AdvancedInputOutput4.gif create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_images/AdvancedInputOutput41.gif create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_images/AdvancedInputOutput5.gif create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_images/AdvancedInputOutput51.gif create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_images/AdvancedOutputAlpha1.gif create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_images/AdvancedOutputAlpha11.gif create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_images/AdvancedOutputAlpha2.gif create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_images/AdvancedOutputAlpha21.gif create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_images/AdvancedOutputAlpha3.gif create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_images/AdvancedOutputAlpha31.gif create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_images/AdvancedOutputProcess1.gif create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_images/AdvancedOutputProcess11.gif create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_images/AdvancedOutputProcess2.gif create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_images/AdvancedOutputProcess21.gif create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_images/AdvancedOutputProcess3.gif create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_images/AdvancedOutputProcess31.gif create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_images/AdvancedOutputProcess4.gif create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_images/AdvancedOutputProcess41.gif create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_images/AdvancedOutputProcess5.gif create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_images/AdvancedOutputProcess51.gif create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_images/AdvancedOutputProcess6.gif create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_images/AdvancedOutputProcess61.gif create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_images/Bagic-INPUT-resultscreen.png create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_images/Bagic-INPUT-resultscreen1.png create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_images/Bagic-INPUT-sourcecode.png create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_images/Bagic-INPUT-sourcecode1.png create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_images/Bagic-PROCESS-resultscreen.png create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_images/Bagic-PROCESS-resultscreen1.png create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_images/Bagic-PROCESS-sourcecode.png create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_images/Bagic-PROCESS-sourcecode1.png create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_images/Bagic-ouput-result-screen.png create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_images/Bagic-ouput-result-screen1.png create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_images/Basic-ouput-sourcecode.png create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_images/Basic-ouput-sourcecode1.png create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_images/camera_average.jpg create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_images/camera_background.jpg create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_images/camera_green.jpg create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_images/camera_hsv.jpg create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_images/camera_mask.jpg create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_images/camera_rgb.jpg create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_images/camera_thresh.jpg create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_images/camera_thresholded.jpg create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_images/camera_yuv.jpg create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_images/chimpshot.gif create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_images/draw_module_example.png create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_images/intro_ball.gif create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_images/intro_blade.jpg create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_images/intro_freedom.jpg create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_images/introduction-Battleship.png create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_images/introduction-Battleship1.png create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_images/introduction-PuyoPuyo.png create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_images/introduction-PuyoPuyo1.png create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_images/introduction-TPS.png create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_images/introduction-TPS1.png create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_images/joystick_calls.png create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_images/surfarray_allblack.png create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_images/surfarray_flipped.png create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_images/surfarray_redimg.png create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_images/surfarray_rgbarray.png create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_images/surfarray_scaledown.png create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_images/surfarray_scaleup.png create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_images/surfarray_soften.png create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_images/surfarray_striped.png create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_images/surfarray_xfade.png create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_images/tom_basic.png create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_images/tom_event-flowchart.png create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_images/tom_formulae.png create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_images/tom_radians.png create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_sources/c_api.rst.txt create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_sources/filepaths.rst.txt create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_sources/index.rst.txt create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_sources/ref/bufferproxy.rst.txt create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_sources/ref/camera.rst.txt create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_sources/ref/cdrom.rst.txt create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_sources/ref/color.rst.txt create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_sources/ref/color_list.rst.txt create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_sources/ref/cursors.rst.txt create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_sources/ref/display.rst.txt create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_sources/ref/draw.rst.txt create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_sources/ref/event.rst.txt create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_sources/ref/examples.rst.txt create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_sources/ref/fastevent.rst.txt create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_sources/ref/font.rst.txt create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_sources/ref/freetype.rst.txt create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_sources/ref/gfxdraw.rst.txt create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_sources/ref/image.rst.txt create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_sources/ref/joystick.rst.txt create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_sources/ref/key.rst.txt create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_sources/ref/locals.rst.txt create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_sources/ref/mask.rst.txt create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_sources/ref/math.rst.txt create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_sources/ref/midi.rst.txt create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_sources/ref/mixer.rst.txt create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_sources/ref/mouse.rst.txt create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_sources/ref/music.rst.txt create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_sources/ref/overlay.rst.txt create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_sources/ref/pixelarray.rst.txt create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_sources/ref/pixelcopy.rst.txt create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_sources/ref/pygame.rst.txt create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_sources/ref/rect.rst.txt create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_sources/ref/scrap.rst.txt create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_sources/ref/sdl2_controller.rst.txt create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_sources/ref/sdl2_video.rst.txt create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_sources/ref/sndarray.rst.txt create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_sources/ref/sprite.rst.txt create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_sources/ref/surface.rst.txt create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_sources/ref/surfarray.rst.txt create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_sources/ref/tests.rst.txt create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_sources/ref/time.rst.txt create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_sources/ref/touch.rst.txt create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_sources/ref/transform.rst.txt create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_static/basic.css create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_static/doctools.js create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_static/documentation_options.js create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_static/file.png create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_static/jquery-3.5.1.js create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_static/jquery.js create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_static/language_data.js create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_static/minus.png create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_static/plus.png create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_static/pygame.css create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_static/pygame.ico create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_static/pygame_tiny.png create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_static/pygments.css create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_static/reset.css create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_static/searchtools.js create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_static/tooltip.css create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_static/underscore-1.13.1.js create mode 100644 venv/Lib/site-packages/pygame/docs/generated/_static/underscore.js create mode 100644 venv/Lib/site-packages/pygame/docs/generated/c_api.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/c_api/base.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/c_api/bufferproxy.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/c_api/cdrom.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/c_api/color.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/c_api/display.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/c_api/event.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/c_api/freetype.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/c_api/mixer.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/c_api/rect.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/c_api/rwobject.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/c_api/slots.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/c_api/surface.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/c_api/surflock.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/c_api/version.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/filepaths.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/genindex.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/index.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/py-modindex.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/ref/bufferproxy.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/ref/camera.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/ref/cdrom.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/ref/color.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/ref/color_list.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/ref/cursors.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/ref/display.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/ref/draw.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/ref/event.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/ref/examples.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/ref/fastevent.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/ref/font.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/ref/freetype.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/ref/gfxdraw.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/ref/image.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/ref/joystick.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/ref/key.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/ref/locals.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/ref/mask.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/ref/math.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/ref/midi.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/ref/mixer.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/ref/mouse.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/ref/music.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/ref/overlay.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/ref/pixelarray.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/ref/pixelcopy.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/ref/pygame.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/ref/rect.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/ref/scrap.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/ref/sdl2_controller.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/ref/sdl2_video.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/ref/sndarray.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/ref/sprite.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/ref/surface.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/ref/surfarray.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/ref/tests.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/ref/time.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/ref/touch.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/ref/transform.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/search.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/searchindex.js create mode 100644 venv/Lib/site-packages/pygame/docs/generated/tut/CameraIntro.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/tut/ChimpLineByLine.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/tut/DisplayModes.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/tut/ImportInit.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/tut/MakeGames.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/tut/MoveIt.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/tut/PygameIntro.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/tut/SpriteIntro.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/tut/SurfarrayIntro.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/tut/chimp.py.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/tut/newbieguide.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/tut/tom_games2.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/tut/tom_games3.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/tut/tom_games4.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/tut/tom_games5.html create mode 100644 venv/Lib/site-packages/pygame/docs/generated/tut/tom_games6.html create mode 100644 venv/Lib/site-packages/pygame/draw.cp39-win_amd64.pyd create mode 100644 venv/Lib/site-packages/pygame/draw.pyi create mode 100644 venv/Lib/site-packages/pygame/draw_py.py create mode 100644 venv/Lib/site-packages/pygame/event.cp39-win_amd64.pyd create mode 100644 venv/Lib/site-packages/pygame/event.pyi create mode 100644 venv/Lib/site-packages/pygame/examples/README.rst create mode 100644 venv/Lib/site-packages/pygame/examples/__init__.py create mode 100644 venv/Lib/site-packages/pygame/examples/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/examples/__pycache__/aacircle.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/examples/__pycache__/aliens.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/examples/__pycache__/arraydemo.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/examples/__pycache__/audiocapture.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/examples/__pycache__/blend_fill.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/examples/__pycache__/blit_blends.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/examples/__pycache__/camera.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/examples/__pycache__/chimp.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/examples/__pycache__/cursors.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/examples/__pycache__/dropevent.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/examples/__pycache__/eventlist.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/examples/__pycache__/font_viewer.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/examples/__pycache__/fonty.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/examples/__pycache__/freetype_misc.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/examples/__pycache__/glcube.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/examples/__pycache__/headless_no_windows_needed.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/examples/__pycache__/joystick.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/examples/__pycache__/liquid.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/examples/__pycache__/mask.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/examples/__pycache__/midi.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/examples/__pycache__/moveit.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/examples/__pycache__/music_drop_fade.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/examples/__pycache__/pixelarray.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/examples/__pycache__/playmus.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/examples/__pycache__/prevent_display_stretching.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/examples/__pycache__/resizing_new.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/examples/__pycache__/scaletest.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/examples/__pycache__/scrap_clipboard.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/examples/__pycache__/scroll.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/examples/__pycache__/setmodescale.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/examples/__pycache__/sound.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/examples/__pycache__/sound_array_demos.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/examples/__pycache__/sprite_texture.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/examples/__pycache__/stars.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/examples/__pycache__/testsprite.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/examples/__pycache__/textinput.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/examples/__pycache__/vgrade.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/examples/__pycache__/video.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/examples/aacircle.py create mode 100644 venv/Lib/site-packages/pygame/examples/aliens.py create mode 100644 venv/Lib/site-packages/pygame/examples/arraydemo.py create mode 100644 venv/Lib/site-packages/pygame/examples/audiocapture.py create mode 100644 venv/Lib/site-packages/pygame/examples/blend_fill.py create mode 100644 venv/Lib/site-packages/pygame/examples/blit_blends.py create mode 100644 venv/Lib/site-packages/pygame/examples/camera.py create mode 100644 venv/Lib/site-packages/pygame/examples/chimp.py create mode 100644 venv/Lib/site-packages/pygame/examples/cursors.py create mode 100644 venv/Lib/site-packages/pygame/examples/data/BGR.png create mode 100644 venv/Lib/site-packages/pygame/examples/data/alien1.gif create mode 100644 venv/Lib/site-packages/pygame/examples/data/alien1.jpg create mode 100644 venv/Lib/site-packages/pygame/examples/data/alien1.png create mode 100644 venv/Lib/site-packages/pygame/examples/data/alien2.gif create mode 100644 venv/Lib/site-packages/pygame/examples/data/alien2.png create mode 100644 venv/Lib/site-packages/pygame/examples/data/alien3.gif create mode 100644 venv/Lib/site-packages/pygame/examples/data/alien3.png create mode 100644 venv/Lib/site-packages/pygame/examples/data/arraydemo.bmp create mode 100644 venv/Lib/site-packages/pygame/examples/data/asprite.bmp create mode 100644 venv/Lib/site-packages/pygame/examples/data/background.gif create mode 100644 venv/Lib/site-packages/pygame/examples/data/black.ppm create mode 100644 venv/Lib/site-packages/pygame/examples/data/blue.gif create mode 100644 venv/Lib/site-packages/pygame/examples/data/blue.mpg create mode 100644 venv/Lib/site-packages/pygame/examples/data/bomb.gif create mode 100644 venv/Lib/site-packages/pygame/examples/data/boom.wav create mode 100644 venv/Lib/site-packages/pygame/examples/data/brick.png create mode 100644 venv/Lib/site-packages/pygame/examples/data/car_door.wav create mode 100644 venv/Lib/site-packages/pygame/examples/data/chimp.png create mode 100644 venv/Lib/site-packages/pygame/examples/data/city.png create mode 100644 venv/Lib/site-packages/pygame/examples/data/crimson.pnm create mode 100644 venv/Lib/site-packages/pygame/examples/data/danger.gif create mode 100644 venv/Lib/site-packages/pygame/examples/data/explosion1.gif create mode 100644 venv/Lib/site-packages/pygame/examples/data/fist.png create mode 100644 venv/Lib/site-packages/pygame/examples/data/green.pcx create mode 100644 venv/Lib/site-packages/pygame/examples/data/grey.pgm create mode 100644 venv/Lib/site-packages/pygame/examples/data/house_lo.mp3 create mode 100644 venv/Lib/site-packages/pygame/examples/data/house_lo.ogg create mode 100644 venv/Lib/site-packages/pygame/examples/data/house_lo.wav create mode 100644 venv/Lib/site-packages/pygame/examples/data/laplacian.png create mode 100644 venv/Lib/site-packages/pygame/examples/data/liquid.bmp create mode 100644 venv/Lib/site-packages/pygame/examples/data/midikeys.png create mode 100644 venv/Lib/site-packages/pygame/examples/data/player1.gif create mode 100644 venv/Lib/site-packages/pygame/examples/data/punch.wav create mode 100644 venv/Lib/site-packages/pygame/examples/data/purple.xpm create mode 100644 venv/Lib/site-packages/pygame/examples/data/red.jpg create mode 100644 venv/Lib/site-packages/pygame/examples/data/sans.ttf create mode 100644 venv/Lib/site-packages/pygame/examples/data/scarlet.webp create mode 100644 venv/Lib/site-packages/pygame/examples/data/secosmic_lo.wav create mode 100644 venv/Lib/site-packages/pygame/examples/data/shot.gif create mode 100644 venv/Lib/site-packages/pygame/examples/data/static.png create mode 100644 venv/Lib/site-packages/pygame/examples/data/teal.svg create mode 100644 venv/Lib/site-packages/pygame/examples/data/turquoise.tif create mode 100644 venv/Lib/site-packages/pygame/examples/data/whiff.wav create mode 100644 venv/Lib/site-packages/pygame/examples/data/yellow.tga create mode 100644 venv/Lib/site-packages/pygame/examples/dropevent.py create mode 100644 venv/Lib/site-packages/pygame/examples/eventlist.py create mode 100644 venv/Lib/site-packages/pygame/examples/font_viewer.py create mode 100644 venv/Lib/site-packages/pygame/examples/fonty.py create mode 100644 venv/Lib/site-packages/pygame/examples/freetype_misc.py create mode 100644 venv/Lib/site-packages/pygame/examples/glcube.py create mode 100644 venv/Lib/site-packages/pygame/examples/headless_no_windows_needed.py create mode 100644 venv/Lib/site-packages/pygame/examples/joystick.py create mode 100644 venv/Lib/site-packages/pygame/examples/liquid.py create mode 100644 venv/Lib/site-packages/pygame/examples/mask.py create mode 100644 venv/Lib/site-packages/pygame/examples/midi.py create mode 100644 venv/Lib/site-packages/pygame/examples/moveit.py create mode 100644 venv/Lib/site-packages/pygame/examples/music_drop_fade.py create mode 100644 venv/Lib/site-packages/pygame/examples/pixelarray.py create mode 100644 venv/Lib/site-packages/pygame/examples/playmus.py create mode 100644 venv/Lib/site-packages/pygame/examples/prevent_display_stretching.py create mode 100644 venv/Lib/site-packages/pygame/examples/resizing_new.py create mode 100644 venv/Lib/site-packages/pygame/examples/scaletest.py create mode 100644 venv/Lib/site-packages/pygame/examples/scrap_clipboard.py create mode 100644 venv/Lib/site-packages/pygame/examples/scroll.py create mode 100644 venv/Lib/site-packages/pygame/examples/setmodescale.py create mode 100644 venv/Lib/site-packages/pygame/examples/sound.py create mode 100644 venv/Lib/site-packages/pygame/examples/sound_array_demos.py create mode 100644 venv/Lib/site-packages/pygame/examples/sprite_texture.py create mode 100644 venv/Lib/site-packages/pygame/examples/stars.py create mode 100644 venv/Lib/site-packages/pygame/examples/testsprite.py create mode 100644 venv/Lib/site-packages/pygame/examples/textinput.py create mode 100644 venv/Lib/site-packages/pygame/examples/vgrade.py create mode 100644 venv/Lib/site-packages/pygame/examples/video.py create mode 100644 venv/Lib/site-packages/pygame/fastevent.py create mode 100644 venv/Lib/site-packages/pygame/fastevent.pyi create mode 100644 venv/Lib/site-packages/pygame/font.cp39-win_amd64.pyd create mode 100644 venv/Lib/site-packages/pygame/font.pyi create mode 100644 venv/Lib/site-packages/pygame/freesansbold.ttf create mode 100644 venv/Lib/site-packages/pygame/freetype.py create mode 100644 venv/Lib/site-packages/pygame/freetype.pyi create mode 100644 venv/Lib/site-packages/pygame/ftfont.py create mode 100644 venv/Lib/site-packages/pygame/gfxdraw.cp39-win_amd64.pyd create mode 100644 venv/Lib/site-packages/pygame/gfxdraw.pyi create mode 100644 venv/Lib/site-packages/pygame/image.cp39-win_amd64.pyd create mode 100644 venv/Lib/site-packages/pygame/image.pyi create mode 100644 venv/Lib/site-packages/pygame/imageext.cp39-win_amd64.pyd create mode 100644 venv/Lib/site-packages/pygame/joystick.cp39-win_amd64.pyd create mode 100644 venv/Lib/site-packages/pygame/joystick.pyi create mode 100644 venv/Lib/site-packages/pygame/key.cp39-win_amd64.pyd create mode 100644 venv/Lib/site-packages/pygame/key.pyi create mode 100644 venv/Lib/site-packages/pygame/libFLAC-8.dll create mode 100644 venv/Lib/site-packages/pygame/libfreetype-6.dll create mode 100644 venv/Lib/site-packages/pygame/libjpeg-9.dll create mode 100644 venv/Lib/site-packages/pygame/libmodplug-1.dll create mode 100644 venv/Lib/site-packages/pygame/libmpg123-0.dll create mode 100644 venv/Lib/site-packages/pygame/libogg-0.dll create mode 100644 venv/Lib/site-packages/pygame/libopus-0.dll create mode 100644 venv/Lib/site-packages/pygame/libopusfile-0.dll create mode 100644 venv/Lib/site-packages/pygame/libpng16-16.dll create mode 100644 venv/Lib/site-packages/pygame/libtiff-5.dll create mode 100644 venv/Lib/site-packages/pygame/libvorbis-0.dll create mode 100644 venv/Lib/site-packages/pygame/libvorbisfile-3.dll create mode 100644 venv/Lib/site-packages/pygame/libwebp-7.dll create mode 100644 venv/Lib/site-packages/pygame/locals.py create mode 100644 venv/Lib/site-packages/pygame/macosx.py create mode 100644 venv/Lib/site-packages/pygame/mask.cp39-win_amd64.pyd create mode 100644 venv/Lib/site-packages/pygame/mask.pyi create mode 100644 venv/Lib/site-packages/pygame/math.cp39-win_amd64.pyd create mode 100644 venv/Lib/site-packages/pygame/math.pyi create mode 100644 venv/Lib/site-packages/pygame/midi.py create mode 100644 venv/Lib/site-packages/pygame/midi.pyi create mode 100644 venv/Lib/site-packages/pygame/mixer.cp39-win_amd64.pyd create mode 100644 venv/Lib/site-packages/pygame/mixer.pyi create mode 100644 venv/Lib/site-packages/pygame/mixer_music.cp39-win_amd64.pyd create mode 100644 venv/Lib/site-packages/pygame/mouse.cp39-win_amd64.pyd create mode 100644 venv/Lib/site-packages/pygame/mouse.pyi create mode 100644 venv/Lib/site-packages/pygame/music.pyi create mode 100644 venv/Lib/site-packages/pygame/newbuffer.cp39-win_amd64.pyd create mode 100644 venv/Lib/site-packages/pygame/pixelarray.cp39-win_amd64.pyd create mode 100644 venv/Lib/site-packages/pygame/pixelarray.pyi create mode 100644 venv/Lib/site-packages/pygame/pixelcopy.cp39-win_amd64.pyd create mode 100644 venv/Lib/site-packages/pygame/pixelcopy.pyi create mode 100644 venv/Lib/site-packages/pygame/pkgdata.py create mode 100644 venv/Lib/site-packages/pygame/portmidi.dll create mode 100644 venv/Lib/site-packages/pygame/py.typed create mode 100644 venv/Lib/site-packages/pygame/pygame.ico create mode 100644 venv/Lib/site-packages/pygame/pygame_icon.bmp create mode 100644 venv/Lib/site-packages/pygame/pygame_icon.icns create mode 100644 venv/Lib/site-packages/pygame/pygame_icon_mac.bmp create mode 100644 venv/Lib/site-packages/pygame/pypm.cp39-win_amd64.pyd create mode 100644 venv/Lib/site-packages/pygame/rect.cp39-win_amd64.pyd create mode 100644 venv/Lib/site-packages/pygame/rect.pyi create mode 100644 venv/Lib/site-packages/pygame/rwobject.cp39-win_amd64.pyd create mode 100644 venv/Lib/site-packages/pygame/scrap.cp39-win_amd64.pyd create mode 100644 venv/Lib/site-packages/pygame/scrap.pyi create mode 100644 venv/Lib/site-packages/pygame/sndarray.py create mode 100644 venv/Lib/site-packages/pygame/sndarray.pyi create mode 100644 venv/Lib/site-packages/pygame/sprite.py create mode 100644 venv/Lib/site-packages/pygame/sprite.pyi create mode 100644 venv/Lib/site-packages/pygame/surface.cp39-win_amd64.pyd create mode 100644 venv/Lib/site-packages/pygame/surface.pyi create mode 100644 venv/Lib/site-packages/pygame/surfarray.py create mode 100644 venv/Lib/site-packages/pygame/surfarray.pyi create mode 100644 venv/Lib/site-packages/pygame/surflock.cp39-win_amd64.pyd create mode 100644 venv/Lib/site-packages/pygame/sysfont.py create mode 100644 venv/Lib/site-packages/pygame/tests/__init__.py create mode 100644 venv/Lib/site-packages/pygame/tests/__main__.py create mode 100644 venv/Lib/site-packages/pygame/tests/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/__pycache__/__main__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/__pycache__/base_test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/__pycache__/blit_test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/__pycache__/bufferproxy_test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/__pycache__/camera_test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/__pycache__/color_test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/__pycache__/constants_test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/__pycache__/controller_test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/__pycache__/cursors_test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/__pycache__/display_test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/__pycache__/docs_test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/__pycache__/draw_test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/__pycache__/event_test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/__pycache__/font_test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/__pycache__/freetype_tags.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/__pycache__/freetype_test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/__pycache__/ftfont_tags.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/__pycache__/ftfont_test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/__pycache__/gfxdraw_test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/__pycache__/image__save_gl_surface_test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/__pycache__/image_tags.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/__pycache__/image_test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/__pycache__/imageext_tags.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/__pycache__/imageext_test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/__pycache__/joystick_test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/__pycache__/key_test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/__pycache__/mask_test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/__pycache__/math_test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/__pycache__/midi_test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/__pycache__/mixer_music_tags.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/__pycache__/mixer_music_test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/__pycache__/mixer_tags.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/__pycache__/mixer_test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/__pycache__/mouse_test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/__pycache__/pixelarray_test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/__pycache__/pixelcopy_test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/__pycache__/rect_test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/__pycache__/rwobject_test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/__pycache__/scrap_tags.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/__pycache__/scrap_test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/__pycache__/sndarray_tags.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/__pycache__/sndarray_test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/__pycache__/sprite_test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/__pycache__/surface_test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/__pycache__/surfarray_tags.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/__pycache__/surfarray_test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/__pycache__/surflock_test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/__pycache__/sysfont_test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/__pycache__/test_test_.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/__pycache__/threads_test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/__pycache__/time_test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/__pycache__/touch_test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/__pycache__/transform_test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/__pycache__/version_test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/__pycache__/video_test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/base_test.py create mode 100644 venv/Lib/site-packages/pygame/tests/blit_test.py create mode 100644 venv/Lib/site-packages/pygame/tests/bufferproxy_test.py create mode 100644 venv/Lib/site-packages/pygame/tests/camera_test.py create mode 100644 venv/Lib/site-packages/pygame/tests/color_test.py create mode 100644 venv/Lib/site-packages/pygame/tests/constants_test.py create mode 100644 venv/Lib/site-packages/pygame/tests/controller_test.py create mode 100644 venv/Lib/site-packages/pygame/tests/cursors_test.py create mode 100644 venv/Lib/site-packages/pygame/tests/display_test.py create mode 100644 venv/Lib/site-packages/pygame/tests/docs_test.py create mode 100644 venv/Lib/site-packages/pygame/tests/draw_test.py create mode 100644 venv/Lib/site-packages/pygame/tests/event_test.py create mode 100644 venv/Lib/site-packages/pygame/tests/fixtures/fonts/A_PyGameMono-8.png create mode 100644 venv/Lib/site-packages/pygame/tests/fixtures/fonts/PyGameMono-18-100dpi.bdf create mode 100644 venv/Lib/site-packages/pygame/tests/fixtures/fonts/PyGameMono-18-75dpi.bdf create mode 100644 venv/Lib/site-packages/pygame/tests/fixtures/fonts/PyGameMono-8.bdf create mode 100644 venv/Lib/site-packages/pygame/tests/fixtures/fonts/PyGameMono.otf create mode 100644 venv/Lib/site-packages/pygame/tests/fixtures/fonts/test_fixed.otf create mode 100644 venv/Lib/site-packages/pygame/tests/fixtures/fonts/test_sans.ttf create mode 100644 venv/Lib/site-packages/pygame/tests/fixtures/fonts/u13079_PyGameMono-8.png create mode 100644 venv/Lib/site-packages/pygame/tests/fixtures/xbm_cursors/white_sizing.xbm create mode 100644 venv/Lib/site-packages/pygame/tests/fixtures/xbm_cursors/white_sizing_mask.xbm create mode 100644 venv/Lib/site-packages/pygame/tests/font_test.py create mode 100644 venv/Lib/site-packages/pygame/tests/freetype_tags.py create mode 100644 venv/Lib/site-packages/pygame/tests/freetype_test.py create mode 100644 venv/Lib/site-packages/pygame/tests/ftfont_tags.py create mode 100644 venv/Lib/site-packages/pygame/tests/ftfont_test.py create mode 100644 venv/Lib/site-packages/pygame/tests/gfxdraw_test.py create mode 100644 venv/Lib/site-packages/pygame/tests/image__save_gl_surface_test.py create mode 100644 venv/Lib/site-packages/pygame/tests/image_tags.py create mode 100644 venv/Lib/site-packages/pygame/tests/image_test.py create mode 100644 venv/Lib/site-packages/pygame/tests/imageext_tags.py create mode 100644 venv/Lib/site-packages/pygame/tests/imageext_test.py create mode 100644 venv/Lib/site-packages/pygame/tests/joystick_test.py create mode 100644 venv/Lib/site-packages/pygame/tests/key_test.py create mode 100644 venv/Lib/site-packages/pygame/tests/mask_test.py create mode 100644 venv/Lib/site-packages/pygame/tests/math_test.py create mode 100644 venv/Lib/site-packages/pygame/tests/midi_test.py create mode 100644 venv/Lib/site-packages/pygame/tests/mixer_music_tags.py create mode 100644 venv/Lib/site-packages/pygame/tests/mixer_music_test.py create mode 100644 venv/Lib/site-packages/pygame/tests/mixer_tags.py create mode 100644 venv/Lib/site-packages/pygame/tests/mixer_test.py create mode 100644 venv/Lib/site-packages/pygame/tests/mouse_test.py create mode 100644 venv/Lib/site-packages/pygame/tests/pixelarray_test.py create mode 100644 venv/Lib/site-packages/pygame/tests/pixelcopy_test.py create mode 100644 venv/Lib/site-packages/pygame/tests/rect_test.py create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/__init__.py create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/__pycache__/run_tests__test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/all_ok/__init__.py create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/all_ok/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/all_ok/__pycache__/fake_2_test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/all_ok/__pycache__/fake_3_test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/all_ok/__pycache__/fake_4_test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/all_ok/__pycache__/fake_5_test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/all_ok/__pycache__/fake_6_test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/all_ok/__pycache__/no_assertions__ret_code_of_1__test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/all_ok/__pycache__/zero_tests_test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/all_ok/fake_2_test.py create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/all_ok/fake_3_test.py create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/all_ok/fake_4_test.py create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/all_ok/fake_5_test.py create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/all_ok/fake_6_test.py create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/all_ok/no_assertions__ret_code_of_1__test.py create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/all_ok/zero_tests_test.py create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/everything/__init__.py create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/everything/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/everything/__pycache__/fake_2_test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/everything/__pycache__/incomplete_todo_test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/everything/__pycache__/magic_tag_test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/everything/__pycache__/sleep_test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/everything/fake_2_test.py create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/everything/incomplete_todo_test.py create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/everything/magic_tag_test.py create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/everything/sleep_test.py create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/exclude/__init__.py create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/exclude/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/exclude/__pycache__/fake_2_test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/exclude/__pycache__/invisible_tag_test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/exclude/__pycache__/magic_tag_test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/exclude/fake_2_test.py create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/exclude/invisible_tag_test.py create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/exclude/magic_tag_test.py create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/failures1/__init__.py create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/failures1/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/failures1/__pycache__/fake_2_test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/failures1/__pycache__/fake_3_test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/failures1/__pycache__/fake_4_test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/failures1/fake_2_test.py create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/failures1/fake_3_test.py create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/failures1/fake_4_test.py create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/incomplete/__init__.py create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/incomplete/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/incomplete/__pycache__/fake_2_test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/incomplete/__pycache__/fake_3_test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/incomplete/fake_2_test.py create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/incomplete/fake_3_test.py create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/incomplete_todo/__init__.py create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/incomplete_todo/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/incomplete_todo/__pycache__/fake_2_test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/incomplete_todo/__pycache__/fake_3_test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/incomplete_todo/fake_2_test.py create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/incomplete_todo/fake_3_test.py create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/infinite_loop/__init__.py create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/infinite_loop/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/infinite_loop/__pycache__/fake_1_test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/infinite_loop/__pycache__/fake_2_test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/infinite_loop/fake_1_test.py create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/infinite_loop/fake_2_test.py create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/print_stderr/__init__.py create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/print_stderr/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/print_stderr/__pycache__/fake_2_test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/print_stderr/__pycache__/fake_3_test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/print_stderr/__pycache__/fake_4_test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/print_stderr/fake_2_test.py create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/print_stderr/fake_3_test.py create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/print_stderr/fake_4_test.py create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/print_stdout/__init__.py create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/print_stdout/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/print_stdout/__pycache__/fake_2_test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/print_stdout/__pycache__/fake_3_test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/print_stdout/__pycache__/fake_4_test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/print_stdout/fake_2_test.py create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/print_stdout/fake_3_test.py create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/print_stdout/fake_4_test.py create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/run_tests__test.py create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/timeout/__init__.py create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/timeout/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/timeout/__pycache__/fake_2_test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/timeout/__pycache__/sleep_test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/timeout/fake_2_test.py create mode 100644 venv/Lib/site-packages/pygame/tests/run_tests__tests/timeout/sleep_test.py create mode 100644 venv/Lib/site-packages/pygame/tests/rwobject_test.py create mode 100644 venv/Lib/site-packages/pygame/tests/scrap_tags.py create mode 100644 venv/Lib/site-packages/pygame/tests/scrap_test.py create mode 100644 venv/Lib/site-packages/pygame/tests/sndarray_tags.py create mode 100644 venv/Lib/site-packages/pygame/tests/sndarray_test.py create mode 100644 venv/Lib/site-packages/pygame/tests/sprite_test.py create mode 100644 venv/Lib/site-packages/pygame/tests/surface_test.py create mode 100644 venv/Lib/site-packages/pygame/tests/surfarray_tags.py create mode 100644 venv/Lib/site-packages/pygame/tests/surfarray_test.py create mode 100644 venv/Lib/site-packages/pygame/tests/surflock_test.py create mode 100644 venv/Lib/site-packages/pygame/tests/sysfont_test.py create mode 100644 venv/Lib/site-packages/pygame/tests/test_test_.py create mode 100644 venv/Lib/site-packages/pygame/tests/test_utils/__init__.py create mode 100644 venv/Lib/site-packages/pygame/tests/test_utils/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/test_utils/__pycache__/arrinter.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/test_utils/__pycache__/async_sub.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/test_utils/__pycache__/buftools.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/test_utils/__pycache__/endian.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/test_utils/__pycache__/png.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/test_utils/__pycache__/run_tests.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/test_utils/__pycache__/test_machinery.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/test_utils/__pycache__/test_runner.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/tests/test_utils/arrinter.py create mode 100644 venv/Lib/site-packages/pygame/tests/test_utils/async_sub.py create mode 100644 venv/Lib/site-packages/pygame/tests/test_utils/buftools.py create mode 100644 venv/Lib/site-packages/pygame/tests/test_utils/endian.py create mode 100644 venv/Lib/site-packages/pygame/tests/test_utils/png.py create mode 100644 venv/Lib/site-packages/pygame/tests/test_utils/run_tests.py create mode 100644 venv/Lib/site-packages/pygame/tests/test_utils/test_machinery.py create mode 100644 venv/Lib/site-packages/pygame/tests/test_utils/test_runner.py create mode 100644 venv/Lib/site-packages/pygame/tests/threads_test.py create mode 100644 venv/Lib/site-packages/pygame/tests/time_test.py create mode 100644 venv/Lib/site-packages/pygame/tests/touch_test.py create mode 100644 venv/Lib/site-packages/pygame/tests/transform_test.py create mode 100644 venv/Lib/site-packages/pygame/tests/version_test.py create mode 100644 venv/Lib/site-packages/pygame/tests/video_test.py create mode 100644 venv/Lib/site-packages/pygame/threads/__init__.py create mode 100644 venv/Lib/site-packages/pygame/threads/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/pygame/time.cp39-win_amd64.pyd create mode 100644 venv/Lib/site-packages/pygame/time.pyi create mode 100644 venv/Lib/site-packages/pygame/transform.cp39-win_amd64.pyd create mode 100644 venv/Lib/site-packages/pygame/transform.pyi create mode 100644 venv/Lib/site-packages/pygame/version.py create mode 100644 venv/Lib/site-packages/pygame/version.pyi create mode 100644 venv/Lib/site-packages/pygame/zlib1.dll create mode 100644 venv/Lib/site-packages/setuptools-60.9.3.dist-info/INSTALLER create mode 100644 venv/Lib/site-packages/setuptools-60.9.3.dist-info/LICENSE create mode 100644 venv/Lib/site-packages/setuptools-60.9.3.dist-info/METADATA create mode 100644 venv/Lib/site-packages/setuptools-60.9.3.dist-info/RECORD create mode 100644 venv/Lib/site-packages/setuptools-60.9.3.dist-info/WHEEL create mode 100644 venv/Lib/site-packages/setuptools-60.9.3.dist-info/entry_points.txt create mode 100644 venv/Lib/site-packages/setuptools-60.9.3.dist-info/top_level.txt create mode 100644 venv/Lib/site-packages/setuptools/__init__.py create mode 100644 venv/Lib/site-packages/setuptools/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/__pycache__/_deprecation_warning.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/__pycache__/_entry_points.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/__pycache__/_imp.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/__pycache__/_importlib.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/__pycache__/_itertools.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/__pycache__/_path.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/__pycache__/_reqs.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/__pycache__/archive_util.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/__pycache__/build_meta.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/__pycache__/config.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/__pycache__/dep_util.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/__pycache__/depends.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/__pycache__/dist.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/__pycache__/errors.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/__pycache__/extension.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/__pycache__/glob.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/__pycache__/installer.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/__pycache__/launch.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/__pycache__/logging.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/__pycache__/monkey.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/__pycache__/msvc.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/__pycache__/namespaces.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/__pycache__/package_index.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/__pycache__/py34compat.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/__pycache__/sandbox.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/__pycache__/unicode_utils.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/__pycache__/version.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/__pycache__/wheel.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/__pycache__/windows_support.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_deprecation_warning.py create mode 100644 venv/Lib/site-packages/setuptools/_distutils/__init__.py create mode 100644 venv/Lib/site-packages/setuptools/_distutils/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_distutils/__pycache__/_collections.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_distutils/__pycache__/_msvccompiler.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_distutils/__pycache__/archive_util.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_distutils/__pycache__/bcppcompiler.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_distutils/__pycache__/ccompiler.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_distutils/__pycache__/cmd.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_distutils/__pycache__/config.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_distutils/__pycache__/core.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_distutils/__pycache__/cygwinccompiler.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_distutils/__pycache__/debug.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_distutils/__pycache__/dep_util.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_distutils/__pycache__/dir_util.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_distutils/__pycache__/dist.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_distutils/__pycache__/errors.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_distutils/__pycache__/extension.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_distutils/__pycache__/fancy_getopt.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_distutils/__pycache__/file_util.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_distutils/__pycache__/filelist.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_distutils/__pycache__/log.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_distutils/__pycache__/msvc9compiler.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_distutils/__pycache__/msvccompiler.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_distutils/__pycache__/py35compat.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_distutils/__pycache__/py38compat.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_distutils/__pycache__/spawn.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_distutils/__pycache__/sysconfig.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_distutils/__pycache__/text_file.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_distutils/__pycache__/unixccompiler.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_distutils/__pycache__/util.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_distutils/__pycache__/version.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_distutils/__pycache__/versionpredicate.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_distutils/_collections.py create mode 100644 venv/Lib/site-packages/setuptools/_distutils/_msvccompiler.py create mode 100644 venv/Lib/site-packages/setuptools/_distutils/archive_util.py create mode 100644 venv/Lib/site-packages/setuptools/_distutils/bcppcompiler.py create mode 100644 venv/Lib/site-packages/setuptools/_distutils/ccompiler.py create mode 100644 venv/Lib/site-packages/setuptools/_distutils/cmd.py create mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/__init__.py create mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/bdist.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/bdist_dumb.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/bdist_msi.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/bdist_rpm.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/bdist_wininst.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/build.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/build_clib.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/build_ext.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/build_py.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/build_scripts.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/check.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/clean.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/config.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/install.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/install_data.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/install_egg_info.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/install_headers.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/install_lib.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/install_scripts.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/py37compat.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/register.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/sdist.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/upload.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/bdist.py create mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/bdist_dumb.py create mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/bdist_msi.py create mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/bdist_rpm.py create mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/bdist_wininst.py create mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/build.py create mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/build_clib.py create mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/build_ext.py create mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/build_py.py create mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/build_scripts.py create mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/check.py create mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/clean.py create mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/config.py create mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/install.py create mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/install_data.py create mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/install_egg_info.py create mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/install_headers.py create mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/install_lib.py create mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/install_scripts.py create mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/py37compat.py create mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/register.py create mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/sdist.py create mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/upload.py create mode 100644 venv/Lib/site-packages/setuptools/_distutils/config.py create mode 100644 venv/Lib/site-packages/setuptools/_distutils/core.py create mode 100644 venv/Lib/site-packages/setuptools/_distutils/cygwinccompiler.py create mode 100644 venv/Lib/site-packages/setuptools/_distutils/debug.py create mode 100644 venv/Lib/site-packages/setuptools/_distutils/dep_util.py create mode 100644 venv/Lib/site-packages/setuptools/_distutils/dir_util.py create mode 100644 venv/Lib/site-packages/setuptools/_distutils/dist.py create mode 100644 venv/Lib/site-packages/setuptools/_distutils/errors.py create mode 100644 venv/Lib/site-packages/setuptools/_distutils/extension.py create mode 100644 venv/Lib/site-packages/setuptools/_distutils/fancy_getopt.py create mode 100644 venv/Lib/site-packages/setuptools/_distutils/file_util.py create mode 100644 venv/Lib/site-packages/setuptools/_distutils/filelist.py create mode 100644 venv/Lib/site-packages/setuptools/_distutils/log.py create mode 100644 venv/Lib/site-packages/setuptools/_distutils/msvc9compiler.py create mode 100644 venv/Lib/site-packages/setuptools/_distutils/msvccompiler.py create mode 100644 venv/Lib/site-packages/setuptools/_distutils/py35compat.py create mode 100644 venv/Lib/site-packages/setuptools/_distutils/py38compat.py create mode 100644 venv/Lib/site-packages/setuptools/_distutils/spawn.py create mode 100644 venv/Lib/site-packages/setuptools/_distutils/sysconfig.py create mode 100644 venv/Lib/site-packages/setuptools/_distutils/text_file.py create mode 100644 venv/Lib/site-packages/setuptools/_distutils/unixccompiler.py create mode 100644 venv/Lib/site-packages/setuptools/_distutils/util.py create mode 100644 venv/Lib/site-packages/setuptools/_distutils/version.py create mode 100644 venv/Lib/site-packages/setuptools/_distutils/versionpredicate.py create mode 100644 venv/Lib/site-packages/setuptools/_entry_points.py create mode 100644 venv/Lib/site-packages/setuptools/_imp.py create mode 100644 venv/Lib/site-packages/setuptools/_importlib.py create mode 100644 venv/Lib/site-packages/setuptools/_itertools.py create mode 100644 venv/Lib/site-packages/setuptools/_path.py create mode 100644 venv/Lib/site-packages/setuptools/_reqs.py create mode 100644 venv/Lib/site-packages/setuptools/_vendor/__init__.py create mode 100644 venv/Lib/site-packages/setuptools/_vendor/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_vendor/__pycache__/ordered_set.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_vendor/__pycache__/pyparsing.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_vendor/__pycache__/typing_extensions.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_vendor/__pycache__/zipp.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/__init__.py create mode 100644 venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/__pycache__/_adapters.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/__pycache__/_collections.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/__pycache__/_compat.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/__pycache__/_functools.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/__pycache__/_itertools.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/__pycache__/_meta.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/__pycache__/_text.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/_adapters.py create mode 100644 venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/_collections.py create mode 100644 venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/_compat.py create mode 100644 venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/_functools.py create mode 100644 venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/_itertools.py create mode 100644 venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/_meta.py create mode 100644 venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/_text.py create mode 100644 venv/Lib/site-packages/setuptools/_vendor/importlib_resources/__init__.py create mode 100644 venv/Lib/site-packages/setuptools/_vendor/importlib_resources/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_vendor/importlib_resources/__pycache__/_adapters.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_vendor/importlib_resources/__pycache__/_common.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_vendor/importlib_resources/__pycache__/_compat.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_vendor/importlib_resources/__pycache__/_itertools.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_vendor/importlib_resources/__pycache__/_legacy.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_vendor/importlib_resources/__pycache__/abc.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_vendor/importlib_resources/__pycache__/readers.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_vendor/importlib_resources/__pycache__/simple.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_vendor/importlib_resources/_adapters.py create mode 100644 venv/Lib/site-packages/setuptools/_vendor/importlib_resources/_common.py create mode 100644 venv/Lib/site-packages/setuptools/_vendor/importlib_resources/_compat.py create mode 100644 venv/Lib/site-packages/setuptools/_vendor/importlib_resources/_itertools.py create mode 100644 venv/Lib/site-packages/setuptools/_vendor/importlib_resources/_legacy.py create mode 100644 venv/Lib/site-packages/setuptools/_vendor/importlib_resources/abc.py create mode 100644 venv/Lib/site-packages/setuptools/_vendor/importlib_resources/readers.py create mode 100644 venv/Lib/site-packages/setuptools/_vendor/importlib_resources/simple.py create mode 100644 venv/Lib/site-packages/setuptools/_vendor/jaraco/__init__.py create mode 100644 venv/Lib/site-packages/setuptools/_vendor/jaraco/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_vendor/jaraco/__pycache__/context.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_vendor/jaraco/__pycache__/functools.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_vendor/jaraco/context.py create mode 100644 venv/Lib/site-packages/setuptools/_vendor/jaraco/functools.py create mode 100644 venv/Lib/site-packages/setuptools/_vendor/jaraco/text/__init__.py create mode 100644 venv/Lib/site-packages/setuptools/_vendor/jaraco/text/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_vendor/more_itertools/__init__.py create mode 100644 venv/Lib/site-packages/setuptools/_vendor/more_itertools/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_vendor/more_itertools/__pycache__/more.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_vendor/more_itertools/__pycache__/recipes.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_vendor/more_itertools/more.py create mode 100644 venv/Lib/site-packages/setuptools/_vendor/more_itertools/recipes.py create mode 100644 venv/Lib/site-packages/setuptools/_vendor/ordered_set.py create mode 100644 venv/Lib/site-packages/setuptools/_vendor/packaging/__about__.py create mode 100644 venv/Lib/site-packages/setuptools/_vendor/packaging/__init__.py create mode 100644 venv/Lib/site-packages/setuptools/_vendor/packaging/__pycache__/__about__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_vendor/packaging/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_vendor/packaging/__pycache__/_manylinux.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_vendor/packaging/__pycache__/_musllinux.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_vendor/packaging/__pycache__/_structures.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_vendor/packaging/__pycache__/markers.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_vendor/packaging/__pycache__/requirements.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_vendor/packaging/__pycache__/specifiers.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_vendor/packaging/__pycache__/tags.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_vendor/packaging/__pycache__/utils.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_vendor/packaging/__pycache__/version.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/_vendor/packaging/_manylinux.py create mode 100644 venv/Lib/site-packages/setuptools/_vendor/packaging/_musllinux.py create mode 100644 venv/Lib/site-packages/setuptools/_vendor/packaging/_structures.py create mode 100644 venv/Lib/site-packages/setuptools/_vendor/packaging/markers.py create mode 100644 venv/Lib/site-packages/setuptools/_vendor/packaging/requirements.py create mode 100644 venv/Lib/site-packages/setuptools/_vendor/packaging/specifiers.py create mode 100644 venv/Lib/site-packages/setuptools/_vendor/packaging/tags.py create mode 100644 venv/Lib/site-packages/setuptools/_vendor/packaging/utils.py create mode 100644 venv/Lib/site-packages/setuptools/_vendor/packaging/version.py create mode 100644 venv/Lib/site-packages/setuptools/_vendor/pyparsing.py create mode 100644 venv/Lib/site-packages/setuptools/_vendor/typing_extensions.py create mode 100644 venv/Lib/site-packages/setuptools/_vendor/zipp.py create mode 100644 venv/Lib/site-packages/setuptools/archive_util.py create mode 100644 venv/Lib/site-packages/setuptools/build_meta.py create mode 100644 venv/Lib/site-packages/setuptools/cli-32.exe create mode 100644 venv/Lib/site-packages/setuptools/cli-64.exe create mode 100644 venv/Lib/site-packages/setuptools/cli-arm64.exe create mode 100644 venv/Lib/site-packages/setuptools/cli.exe create mode 100644 venv/Lib/site-packages/setuptools/command/__init__.py create mode 100644 venv/Lib/site-packages/setuptools/command/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/command/__pycache__/alias.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/command/__pycache__/bdist_egg.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/command/__pycache__/bdist_rpm.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/command/__pycache__/build_clib.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/command/__pycache__/build_ext.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/command/__pycache__/build_py.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/command/__pycache__/develop.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/command/__pycache__/dist_info.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/command/__pycache__/easy_install.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/command/__pycache__/egg_info.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/command/__pycache__/install.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/command/__pycache__/install_egg_info.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/command/__pycache__/install_lib.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/command/__pycache__/install_scripts.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/command/__pycache__/py36compat.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/command/__pycache__/register.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/command/__pycache__/rotate.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/command/__pycache__/saveopts.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/command/__pycache__/sdist.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/command/__pycache__/setopt.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/command/__pycache__/test.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/command/__pycache__/upload.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/command/__pycache__/upload_docs.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/command/alias.py create mode 100644 venv/Lib/site-packages/setuptools/command/bdist_egg.py create mode 100644 venv/Lib/site-packages/setuptools/command/bdist_rpm.py create mode 100644 venv/Lib/site-packages/setuptools/command/build_clib.py create mode 100644 venv/Lib/site-packages/setuptools/command/build_ext.py create mode 100644 venv/Lib/site-packages/setuptools/command/build_py.py create mode 100644 venv/Lib/site-packages/setuptools/command/develop.py create mode 100644 venv/Lib/site-packages/setuptools/command/dist_info.py create mode 100644 venv/Lib/site-packages/setuptools/command/easy_install.py create mode 100644 venv/Lib/site-packages/setuptools/command/egg_info.py create mode 100644 venv/Lib/site-packages/setuptools/command/install.py create mode 100644 venv/Lib/site-packages/setuptools/command/install_egg_info.py create mode 100644 venv/Lib/site-packages/setuptools/command/install_lib.py create mode 100644 venv/Lib/site-packages/setuptools/command/install_scripts.py create mode 100644 venv/Lib/site-packages/setuptools/command/launcher manifest.xml create mode 100644 venv/Lib/site-packages/setuptools/command/py36compat.py create mode 100644 venv/Lib/site-packages/setuptools/command/register.py create mode 100644 venv/Lib/site-packages/setuptools/command/rotate.py create mode 100644 venv/Lib/site-packages/setuptools/command/saveopts.py create mode 100644 venv/Lib/site-packages/setuptools/command/sdist.py create mode 100644 venv/Lib/site-packages/setuptools/command/setopt.py create mode 100644 venv/Lib/site-packages/setuptools/command/test.py create mode 100644 venv/Lib/site-packages/setuptools/command/upload.py create mode 100644 venv/Lib/site-packages/setuptools/command/upload_docs.py create mode 100644 venv/Lib/site-packages/setuptools/config.py create mode 100644 venv/Lib/site-packages/setuptools/dep_util.py create mode 100644 venv/Lib/site-packages/setuptools/depends.py create mode 100644 venv/Lib/site-packages/setuptools/dist.py create mode 100644 venv/Lib/site-packages/setuptools/errors.py create mode 100644 venv/Lib/site-packages/setuptools/extension.py create mode 100644 venv/Lib/site-packages/setuptools/extern/__init__.py create mode 100644 venv/Lib/site-packages/setuptools/extern/__pycache__/__init__.cpython-39.pyc create mode 100644 venv/Lib/site-packages/setuptools/glob.py create mode 100644 venv/Lib/site-packages/setuptools/gui-32.exe create mode 100644 venv/Lib/site-packages/setuptools/gui-64.exe create mode 100644 venv/Lib/site-packages/setuptools/gui-arm64.exe create mode 100644 venv/Lib/site-packages/setuptools/gui.exe create mode 100644 venv/Lib/site-packages/setuptools/installer.py create mode 100644 venv/Lib/site-packages/setuptools/launch.py create mode 100644 venv/Lib/site-packages/setuptools/logging.py create mode 100644 venv/Lib/site-packages/setuptools/monkey.py create mode 100644 venv/Lib/site-packages/setuptools/msvc.py create mode 100644 venv/Lib/site-packages/setuptools/namespaces.py create mode 100644 venv/Lib/site-packages/setuptools/package_index.py create mode 100644 venv/Lib/site-packages/setuptools/py34compat.py create mode 100644 venv/Lib/site-packages/setuptools/sandbox.py create mode 100644 venv/Lib/site-packages/setuptools/script (dev).tmpl create mode 100644 venv/Lib/site-packages/setuptools/script.tmpl create mode 100644 venv/Lib/site-packages/setuptools/unicode_utils.py create mode 100644 venv/Lib/site-packages/setuptools/version.py create mode 100644 venv/Lib/site-packages/setuptools/wheel.py create mode 100644 venv/Lib/site-packages/setuptools/windows_support.py create mode 100644 venv/Scripts/Activate.ps1 create mode 100644 venv/Scripts/activate create mode 100644 venv/Scripts/activate.bat create mode 100644 venv/Scripts/deactivate.bat create mode 100644 venv/Scripts/pip.exe create mode 100644 venv/Scripts/pip3.9.exe create mode 100644 venv/Scripts/pip3.exe create mode 100644 venv/Scripts/python.exe create mode 100644 venv/Scripts/pythonw.exe create mode 100644 venv/pyvenv.cfg diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..73f69e0 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml +# Editor-based HTTP Client requests +/httpRequests/ diff --git a/.idea/AI_wozek_widlowy.iml b/.idea/AI_wozek_widlowy.iml new file mode 100644 index 0000000..74d515a --- /dev/null +++ b/.idea/AI_wozek_widlowy.iml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000..105ce2d --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..5eee172 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..5984f79 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/resources/track.png b/resources/track.png new file mode 100644 index 0000000000000000000000000000000000000000..24b7c969c59526f9433d3f4820f57cff100a4efe GIT binary patch literal 2684 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 + +/* Ensure PyPy-specific code is not in use when running on GraalPython (PR + * #2580) */ +#if defined(GRAALVM_PYTHON) && defined(PYPY_VERSION) +#undef PYPY_VERSION +#endif + +#include + +/* SDL 1.2 constants removed from SDL 2 */ +typedef enum { + SDL_HWSURFACE = 0, + SDL_RESIZABLE = SDL_WINDOW_RESIZABLE, + SDL_ASYNCBLIT = 0, + SDL_OPENGL = SDL_WINDOW_OPENGL, + SDL_OPENGLBLIT = 0, + SDL_ANYFORMAT = 0, + SDL_HWPALETTE = 0, + SDL_DOUBLEBUF = 0, + SDL_FULLSCREEN = SDL_WINDOW_FULLSCREEN, + SDL_HWACCEL = 0, + SDL_SRCCOLORKEY = 0, + SDL_RLEACCELOK = 0, + SDL_SRCALPHA = 0, + SDL_NOFRAME = SDL_WINDOW_BORDERLESS, + SDL_GL_SWAP_CONTROL = 0, + TIMER_RESOLUTION = 0 +} PygameVideoFlags; + +/* the wheel button constants were removed from SDL 2 */ +typedef enum { + PGM_BUTTON_LEFT = SDL_BUTTON_LEFT, + PGM_BUTTON_RIGHT = SDL_BUTTON_RIGHT, + PGM_BUTTON_MIDDLE = SDL_BUTTON_MIDDLE, + PGM_BUTTON_WHEELUP = 4, + PGM_BUTTON_WHEELDOWN = 5, + PGM_BUTTON_X1 = SDL_BUTTON_X1 + 2, + PGM_BUTTON_X2 = SDL_BUTTON_X2 + 2, + PGM_BUTTON_KEEP = 0x80 +} PygameMouseFlags; + +typedef enum { + /* Any SDL_* events here are for backward compatibility. */ + SDL_NOEVENT = 0, + + SDL_ACTIVEEVENT = SDL_USEREVENT, + SDL_VIDEORESIZE, + SDL_VIDEOEXPOSE, + + PGE_MIDIIN, + PGE_MIDIOUT, + PGE_KEYREPEAT, /* Special internal pygame event, for managing key-presses + */ + + /* DO NOT CHANGE THE ORDER OF EVENTS HERE */ + PGE_WINDOWSHOWN, + PGE_WINDOWHIDDEN, + PGE_WINDOWEXPOSED, + PGE_WINDOWMOVED, + PGE_WINDOWRESIZED, + PGE_WINDOWSIZECHANGED, + PGE_WINDOWMINIMIZED, + PGE_WINDOWMAXIMIZED, + PGE_WINDOWRESTORED, + PGE_WINDOWENTER, + PGE_WINDOWLEAVE, + PGE_WINDOWFOCUSGAINED, + PGE_WINDOWFOCUSLOST, + PGE_WINDOWCLOSE, + PGE_WINDOWTAKEFOCUS, + PGE_WINDOWHITTEST, + + /* Here we define PGPOST_* events, events that act as a one-to-one + * proxy for SDL events (and some extra events too!), the proxy is used + * internally when pygame users use event.post() + * + * At a first glance, these may look redundant, but they are really + * important, especially with event blocking. If proxy events are + * not there, blocked events dont make it to our event filter, and + * that can break a lot of stuff. + * + * IMPORTANT NOTE: Do not post events directly with these proxy types, + * use the appropriate functions from event.c, that handle these proxy + * events for you. + * Proxy events are for internal use only */ + PGPOST_EVENTBEGIN, /* mark start of proxy-events */ + PGPOST_ACTIVEEVENT = PGPOST_EVENTBEGIN, + PGPOST_AUDIODEVICEADDED, + PGPOST_AUDIODEVICEREMOVED, + PGPOST_CONTROLLERAXISMOTION, + PGPOST_CONTROLLERBUTTONDOWN, + PGPOST_CONTROLLERBUTTONUP, + PGPOST_CONTROLLERDEVICEADDED, + PGPOST_CONTROLLERDEVICEREMOVED, + PGPOST_CONTROLLERDEVICEREMAPPED, + PGPOST_CONTROLLERTOUCHPADDOWN, + PGPOST_CONTROLLERTOUCHPADMOTION, + PGPOST_CONTROLLERTOUCHPADUP, + PGPOST_DOLLARGESTURE, + PGPOST_DOLLARRECORD, + PGPOST_DROPFILE, + PGPOST_DROPTEXT, + PGPOST_DROPBEGIN, + PGPOST_DROPCOMPLETE, + PGPOST_FINGERMOTION, + PGPOST_FINGERDOWN, + PGPOST_FINGERUP, + PGPOST_KEYDOWN, + PGPOST_KEYUP, + PGPOST_JOYAXISMOTION, + PGPOST_JOYBALLMOTION, + PGPOST_JOYHATMOTION, + PGPOST_JOYBUTTONDOWN, + PGPOST_JOYBUTTONUP, + PGPOST_JOYDEVICEADDED, + PGPOST_JOYDEVICEREMOVED, + PGPOST_MIDIIN, + PGPOST_MIDIOUT, + PGPOST_MOUSEMOTION, + PGPOST_MOUSEBUTTONDOWN, + PGPOST_MOUSEBUTTONUP, + PGPOST_MOUSEWHEEL, + PGPOST_MULTIGESTURE, + PGPOST_NOEVENT, + PGPOST_QUIT, + PGPOST_SYSWMEVENT, + PGPOST_TEXTEDITING, + PGPOST_TEXTINPUT, + PGPOST_VIDEORESIZE, + PGPOST_VIDEOEXPOSE, + PGPOST_WINDOWSHOWN, + PGPOST_WINDOWHIDDEN, + PGPOST_WINDOWEXPOSED, + PGPOST_WINDOWMOVED, + PGPOST_WINDOWRESIZED, + PGPOST_WINDOWSIZECHANGED, + PGPOST_WINDOWMINIMIZED, + PGPOST_WINDOWMAXIMIZED, + PGPOST_WINDOWRESTORED, + PGPOST_WINDOWENTER, + PGPOST_WINDOWLEAVE, + PGPOST_WINDOWFOCUSGAINED, + PGPOST_WINDOWFOCUSLOST, + PGPOST_WINDOWCLOSE, + PGPOST_WINDOWTAKEFOCUS, + PGPOST_WINDOWHITTEST, + + PGE_USEREVENT, /* this event must stay in this position only */ + + PG_NUMEVENTS = + SDL_LASTEVENT /* Not an event. Indicates end of user events. */ +} PygameEventCode; + +typedef enum { + SDL_APPFOCUSMOUSE, + SDL_APPINPUTFOCUS, + SDL_APPACTIVE +} PygameAppCode; + +/* Surface flags: based on SDL 1.2 flags */ +typedef enum { + PGS_SWSURFACE = 0x00000000, + PGS_HWSURFACE = 0x00000001, + PGS_ASYNCBLIT = 0x00000004, + + PGS_ANYFORMAT = 0x10000000, + PGS_HWPALETTE = 0x20000000, + PGS_DOUBLEBUF = 0x40000000, + PGS_FULLSCREEN = 0x80000000, + PGS_SCALED = 0x00000200, + + PGS_OPENGL = 0x00000002, + PGS_OPENGLBLIT = 0x0000000A, + PGS_RESIZABLE = 0x00000010, + PGS_NOFRAME = 0x00000020, + PGS_SHOWN = 0x00000040, /* Added from SDL 2 */ + PGS_HIDDEN = 0x00000080, /* Added from SDL 2 */ + + PGS_HWACCEL = 0x00000100, + PGS_SRCCOLORKEY = 0x00001000, + PGS_RLEACCELOK = 0x00002000, + PGS_RLEACCEL = 0x00004000, + PGS_SRCALPHA = 0x00010000, + PGS_PREALLOC = 0x01000000 +} PygameSurfaceFlags; + +// TODO Implement check below in a way that does not break CI +/* New buffer protocol (PEP 3118) implemented on all supported Py versions. +#if !defined(Py_TPFLAGS_HAVE_NEWBUFFER) +#error No support for PEP 3118/Py_TPFLAGS_HAVE_NEWBUFFER. Please use a +supported Python version. #endif */ + +#define RAISE(x, y) (PyErr_SetString((x), (y)), (PyObject *)NULL) +#define DEL_ATTR_NOT_SUPPORTED_CHECK(name, value) \ + do { \ + if (!value) { \ + if (name) { \ + PyErr_Format(PyExc_AttributeError, \ + "Cannot delete attribute %s", name); \ + } \ + else { \ + PyErr_SetString(PyExc_AttributeError, \ + "Cannot delete attribute"); \ + } \ + return -1; \ + } \ + } while (0) + +/* + * Initialization checks + */ + +#define VIDEO_INIT_CHECK() \ + if (!SDL_WasInit(SDL_INIT_VIDEO)) \ + return RAISE(pgExc_SDLError, "video system not initialized") + +#define CDROM_INIT_CHECK() \ + if (!SDL_WasInit(SDL_INIT_CDROM)) \ + return RAISE(pgExc_SDLError, "cdrom system not initialized") + +#define JOYSTICK_INIT_CHECK() \ + if (!SDL_WasInit(SDL_INIT_JOYSTICK)) \ + return RAISE(pgExc_SDLError, "joystick system not initialized") + +/* thread check */ +#ifdef WITH_THREAD +#define PG_CHECK_THREADS() (1) +#else /* ~WITH_THREAD */ +#define PG_CHECK_THREADS() \ + (RAISE(PyExc_NotImplementedError, "Python built without thread support")) +#endif /* ~WITH_THREAD */ + +#define PyType_Init(x) (((x).ob_type) = &PyType_Type) + +/* + * event module internals + */ +struct pgEventObject { + PyObject_HEAD int type; + PyObject *dict; +}; + +/* + * surflock module internals + */ +typedef struct { + PyObject_HEAD PyObject *surface; + PyObject *lockobj; + PyObject *weakrefs; +} pgLifetimeLockObject; + +/* + * surface module internals + */ +struct pgSubSurface_Data { + PyObject *owner; + int pixeloffset; + int offsetx, offsety; +}; + +/* + * color module internals + */ +struct pgColorObject { + PyObject_HEAD Uint8 data[4]; + Uint8 len; +}; + +/* + * include public API + */ +#include "include/_pygame.h" + +/* Slot counts. + * Remember to keep these constants up to date. + */ + +#define PYGAMEAPI_RECT_NUMSLOTS 5 +#define PYGAMEAPI_JOYSTICK_NUMSLOTS 2 +#define PYGAMEAPI_DISPLAY_NUMSLOTS 2 +#define PYGAMEAPI_SURFACE_NUMSLOTS 4 +#define PYGAMEAPI_SURFLOCK_NUMSLOTS 8 +#define PYGAMEAPI_RWOBJECT_NUMSLOTS 7 +#define PYGAMEAPI_PIXELARRAY_NUMSLOTS 2 +#define PYGAMEAPI_COLOR_NUMSLOTS 5 +#define PYGAMEAPI_MATH_NUMSLOTS 2 +#define PYGAMEAPI_CDROM_NUMSLOTS 2 +#define PYGAMEAPI_BASE_NUMSLOTS 24 +#define PYGAMEAPI_EVENT_NUMSLOTS 6 + +#endif /* _PYGAME_INTERNAL_H */ diff --git a/venv/Include/site/python3.9/pygame/_surface.h b/venv/Include/site/python3.9/pygame/_surface.h new file mode 100644 index 0000000..b2b4644 --- /dev/null +++ b/venv/Include/site/python3.9/pygame/_surface.h @@ -0,0 +1,30 @@ +/* + pygame - Python Game Library + Copyright (C) 2000-2001 Pete Shinners + Copyright (C) 2007 Marcus von Appen + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Pete Shinners + pete@shinners.org +*/ + +#ifndef _SURFACE_H +#define _SURFACE_H + +#include "_pygame.h" +#include "surface.h" + +#endif diff --git a/venv/Include/site/python3.9/pygame/camera.h b/venv/Include/site/python3.9/pygame/camera.h new file mode 100644 index 0000000..6806dfe --- /dev/null +++ b/venv/Include/site/python3.9/pygame/camera.h @@ -0,0 +1,252 @@ +#ifndef CAMERA_H +#define CAMERA_H +/* + pygame - Python Game Library + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#include "pygame.h" +#include "pgcompat.h" +#include "doc/camera_doc.h" + +#if defined(__unix__) +#include +#include +#include +#include +#include + +#include /* low-level i/o */ +#include +#include +#include +#include +#include +#include +#include + +/* on freebsd there is no asm/types */ +#ifdef linux +#include /* for videodev2.h */ +#endif + +#include +#endif + +#if defined(__WIN32__) +#define PYGAME_WINDOWS_CAMERA 1 + +#include +#include +#include +#include +#include +#include +#endif + +/* some constants used which are not defined on non-v4l machines. */ +#ifndef V4L2_PIX_FMT_RGB24 +#define V4L2_PIX_FMT_RGB24 'RGB3' +#endif +#ifndef V4L2_PIX_FMT_RGB444 +#define V4L2_PIX_FMT_RGB444 'R444' +#endif +#ifndef V4L2_PIX_FMT_YUYV +#define V4L2_PIX_FMT_YUYV 'YUYV' +#endif +#ifndef V4L2_PIX_FMT_XBGR32 +#define V4L2_PIX_FMT_XBGR32 'XR24' +#endif + +#define CLEAR(x) memset(&(x), 0, sizeof(x)) +#define SAT(c) \ + if (c & (~255)) { \ + if (c < 0) \ + c = 0; \ + else \ + c = 255; \ + } +#define SAT2(c) ((c) & (~255) ? ((c) < 0 ? 0 : 255) : (c)) +#define DEFAULT_WIDTH 640 +#define DEFAULT_HEIGHT 480 +#define RGB_OUT 1 +#define YUV_OUT 2 +#define HSV_OUT 4 +#define CAM_V4L \ + 1 /* deprecated. the incomplete support in pygame was removed */ +#define CAM_V4L2 2 + +struct buffer { + void *start; + size_t length; +}; + +#if defined(__unix__) +typedef struct pgCameraObject { + PyObject_HEAD char *device_name; + int camera_type; + unsigned long pixelformat; + unsigned int color_out; + struct buffer *buffers; + unsigned int n_buffers; + int width; + int height; + int size; + int hflip; + int vflip; + int brightness; + int fd; +} pgCameraObject; +#elif defined(PYGAME_WINDOWS_CAMERA) +typedef struct pgCameraObject { + PyObject_HEAD WCHAR *device_name; + IMFSourceReader *reader; + IMFTransform *transform; + IMFVideoProcessorControl *control; + IMFMediaBuffer *buf; + IMFMediaBuffer *raw_buf; + int buffer_ready; + short open; /* used to signal the update_function to exit */ + HANDLE t_handle; + HRESULT t_error; + int t_error_line; + int width; + int height; + int hflip; + int vflip; + int last_vflip; + int color_out; + unsigned long pixelformat; +} pgCameraObject; + +#else +/* generic definition. + */ + +typedef struct pgCameraObject { + PyObject_HEAD char *device_name; + int camera_type; + unsigned long pixelformat; + unsigned int color_out; + struct buffer *buffers; + unsigned int n_buffers; + int width; + int height; + int size; + int hflip; + int vflip; + int brightness; + int fd; +} pgCameraObject; +#endif + +/* internal functions for colorspace conversion */ +void +colorspace(SDL_Surface *src, SDL_Surface *dst, int cspace); +void +rgb24_to_rgb(const void *src, void *dst, int length, SDL_PixelFormat *format); +void +bgr32_to_rgb(const void *src, void *dst, int length, SDL_PixelFormat *format); +void +rgb444_to_rgb(const void *src, void *dst, int length, SDL_PixelFormat *format); +void +rgb_to_yuv(const void *src, void *dst, int length, unsigned long source, + SDL_PixelFormat *format); +void +rgb_to_hsv(const void *src, void *dst, int length, unsigned long source, + SDL_PixelFormat *format); +void +yuyv_to_rgb(const void *src, void *dst, int length, SDL_PixelFormat *format); +void +yuyv_to_yuv(const void *src, void *dst, int length, SDL_PixelFormat *format); +void +uyvy_to_rgb(const void *src, void *dst, int length, SDL_PixelFormat *format); +void +uyvy_to_yuv(const void *src, void *dst, int length, SDL_PixelFormat *format); +void +sbggr8_to_rgb(const void *src, void *dst, int width, int height, + SDL_PixelFormat *format); +void +yuv420_to_rgb(const void *src, void *dst, int width, int height, + SDL_PixelFormat *format); +void +yuv420_to_yuv(const void *src, void *dst, int width, int height, + SDL_PixelFormat *format); + +#if defined(__unix__) +/* internal functions specific to v4l2 */ +char ** +v4l2_list_cameras(int *num_devices); +int +v4l2_get_control(int fd, int id, int *value); +int +v4l2_set_control(int fd, int id, int value); +PyObject * +v4l2_read_raw(pgCameraObject *self); +int +v4l2_xioctl(int fd, int request, void *arg); +int +v4l2_process_image(pgCameraObject *self, const void *image, + unsigned int buffer_size, SDL_Surface *surf); +int +v4l2_query_buffer(pgCameraObject *self); +int +v4l2_read_frame(pgCameraObject *self, SDL_Surface *surf); +int +v4l2_stop_capturing(pgCameraObject *self); +int +v4l2_start_capturing(pgCameraObject *self); +int +v4l2_uninit_device(pgCameraObject *self); +int +v4l2_init_mmap(pgCameraObject *self); +int +v4l2_init_device(pgCameraObject *self); +int +v4l2_close_device(pgCameraObject *self); +int +v4l2_open_device(pgCameraObject *self); + +#elif defined(PYGAME_WINDOWS_CAMERA) +/* internal functions specific to WINDOWS */ +WCHAR ** +windows_list_cameras(int *num_devices); +int +windows_init_device(pgCameraObject *self); +int +windows_open_device(pgCameraObject *self); +IMFActivate * +windows_device_from_name(WCHAR *device_name); +int +windows_close_device(pgCameraObject *self); +int +windows_read_frame(pgCameraObject *self, SDL_Surface *surf); +int +windows_frame_ready(pgCameraObject *self, int *result); +PyObject * +windows_read_raw(pgCameraObject *self); +int +windows_process_image(pgCameraObject *self, BYTE *data, DWORD buffer_size, + SDL_Surface *surf); +void +windows_dealloc_device(pgCameraObject *self); +int +windows_init_device(pgCameraObject *self); + +#endif + +#endif /* !CAMERA_H */ diff --git a/venv/Include/site/python3.9/pygame/font.h b/venv/Include/site/python3.9/pygame/font.h new file mode 100644 index 0000000..f5eedb2 --- /dev/null +++ b/venv/Include/site/python3.9/pygame/font.h @@ -0,0 +1,15 @@ +#ifndef PGFONT_INTERNAL_H +#define PGFONT_INTERNAL_H + +#include + +/* test font initialization */ +#define FONT_INIT_CHECK() \ + if (!(*(int *)PyFONT_C_API[2])) \ + return RAISE(pgExc_SDLError, "font system not initialized") + +#include "include/pygame_font.h" + +#define PYGAMEAPI_FONT_NUMSLOTS 3 + +#endif /* ~PGFONT_INTERNAL_H */ diff --git a/venv/Include/site/python3.9/pygame/freetype.h b/venv/Include/site/python3.9/pygame/freetype.h new file mode 100644 index 0000000..fd86bc2 --- /dev/null +++ b/venv/Include/site/python3.9/pygame/freetype.h @@ -0,0 +1,114 @@ +/* + pygame - Python Game Library + Copyright (C) 2009 Vicent Marti + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ +#ifndef _PYGAME_FREETYPE_INTERNAL_H_ +#define _PYGAME_FREETYPE_INTERNAL_H_ + +#include "pgcompat.h" +#include "pgplatform.h" + +#include +#include FT_FREETYPE_H +#include FT_CACHE_H +#include FT_XFREE86_H +#include FT_TRIGONOMETRY_H + +/********************************************************** + * Global module constants + **********************************************************/ + +/* Render styles */ +#define FT_STYLE_NORMAL 0x00 +#define FT_STYLE_STRONG 0x01 +#define FT_STYLE_OBLIQUE 0x02 +#define FT_STYLE_UNDERLINE 0x04 +#define FT_STYLE_WIDE 0x08 +#define FT_STYLE_DEFAULT 0xFF + +/* Bounding box modes */ +#define FT_BBOX_EXACT FT_GLYPH_BBOX_SUBPIXELS +#define FT_BBOX_EXACT_GRIDFIT FT_GLYPH_BBOX_GRIDFIT +#define FT_BBOX_PIXEL FT_GLYPH_BBOX_TRUNCATE +#define FT_BBOX_PIXEL_GRIDFIT FT_GLYPH_BBOX_PIXELS + +/* Rendering flags */ +#define FT_RFLAG_NONE (0) +#define FT_RFLAG_ANTIALIAS (1 << 0) +#define FT_RFLAG_AUTOHINT (1 << 1) +#define FT_RFLAG_VERTICAL (1 << 2) +#define FT_RFLAG_HINTED (1 << 3) +#define FT_RFLAG_KERNING (1 << 4) +#define FT_RFLAG_TRANSFORM (1 << 5) +#define FT_RFLAG_PAD (1 << 6) +#define FT_RFLAG_ORIGIN (1 << 7) +#define FT_RFLAG_UCS4 (1 << 8) +#define FT_RFLAG_USE_BITMAP_STRIKES (1 << 9) +#define FT_RFLAG_DEFAULTS \ + (FT_RFLAG_HINTED | FT_RFLAG_USE_BITMAP_STRIKES | FT_RFLAG_ANTIALIAS) + +#define FT_RENDER_NEWBYTEARRAY 0x0 +#define FT_RENDER_NEWSURFACE 0x1 +#define FT_RENDER_EXISTINGSURFACE 0x2 + +/********************************************************** + * Global module types + **********************************************************/ + +typedef struct _scale_s { + FT_UInt x, y; +} Scale_t; +typedef FT_Angle Angle_t; + +struct fontinternals_; +struct freetypeinstance_; + +typedef struct { + FT_Long font_index; + FT_Open_Args open_args; +} pgFontId; + +typedef struct { + PyObject_HEAD pgFontId id; + PyObject *path; + int is_scalable; + int is_bg_col_set; + + Scale_t face_size; + FT_Int16 style; + FT_Int16 render_flags; + double strength; + double underline_adjustment; + FT_UInt resolution; + Angle_t rotation; + FT_Matrix transform; + FT_Byte fgcolor[4]; + FT_Byte bgcolor[4]; + + struct freetypeinstance_ *freetype; /* Personal reference */ + struct fontinternals_ *_internals; +} pgFontObject; + +#define pgFont_IS_ALIVE(o) (((pgFontObject *)(o))->_internals != 0) + +/* import public API */ +#include "include/pygame_freetype.h" + +#define PYGAMEAPI_FREETYPE_NUMSLOTS 2 + +#endif /* ~_PYGAME_FREETYPE_INTERNAL_H_ */ diff --git a/venv/Include/site/python3.9/pygame/include/_pygame.h b/venv/Include/site/python3.9/pygame/include/_pygame.h new file mode 100644 index 0000000..9817f96 --- /dev/null +++ b/venv/Include/site/python3.9/pygame/include/_pygame.h @@ -0,0 +1,497 @@ +/* + pygame - Python Game Library + Copyright (C) 2000-2001 Pete Shinners + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Pete Shinners + pete@shinners.org +*/ + +#ifndef _PYGAME_H +#define _PYGAME_H + +/** This header file includes all the definitions for the + ** base pygame extensions. This header only requires + ** Python includes (and SDL.h for functions that use SDL types). + ** The reason for functions prototyped with #define's is + ** to allow for maximum Python portability. It also uses + ** Python as the runtime linker, which allows for late binding. + '' For more information on this style of development, read + ** the Python docs on this subject. + ** http://www.python.org/doc/current/ext/using-cobjects.html + ** + ** If using this to build your own derived extensions, + ** you'll see that the functions available here are mainly + ** used to help convert between python objects and SDL objects. + ** Since this library doesn't add a lot of functionality to + ** the SDL library, it doesn't need to offer a lot either. + ** + ** When initializing your extension module, you must manually + ** import the modules you want to use. (this is the part about + ** using python as the runtime linker). Each module has its + ** own import_xxx() routine. You need to perform this import + ** after you have initialized your own module, and before + ** you call any routines from that module. Since every module + ** in pygame does this, there are plenty of examples. + ** + ** The base module does include some useful conversion routines + ** that you are free to use in your own extension. + **/ + +#include "pgplatform.h" +#include + +/* version macros (defined since version 1.9.5) */ +#define PG_MAJOR_VERSION 2 +#define PG_MINOR_VERSION 1 +#define PG_PATCH_VERSION 2 +#define PG_VERSIONNUM(MAJOR, MINOR, PATCH) \ + (1000 * (MAJOR) + 100 * (MINOR) + (PATCH)) +#define PG_VERSION_ATLEAST(MAJOR, MINOR, PATCH) \ + (PG_VERSIONNUM(PG_MAJOR_VERSION, PG_MINOR_VERSION, PG_PATCH_VERSION) >= \ + PG_VERSIONNUM(MAJOR, MINOR, PATCH)) + +#include "pgcompat.h" + +/* Flag indicating a pg_buffer; used for assertions within callbacks */ +#ifndef NDEBUG +#define PyBUF_PYGAME 0x4000 +#endif +#define PyBUF_HAS_FLAG(f, F) (((f) & (F)) == (F)) + +/* Array information exchange struct C type; inherits from Py_buffer + * + * Pygame uses its own Py_buffer derived C struct as an internal representation + * of an imported array buffer. The extended Py_buffer allows for a + * per-instance release callback, + */ +typedef void (*pybuffer_releaseproc)(Py_buffer *); + +typedef struct pg_bufferinfo_s { + Py_buffer view; + PyObject *consumer; /* Input: Borrowed reference */ + pybuffer_releaseproc release_buffer; +} pg_buffer; + +#include "pgimport.h" + +/* + * BASE module + */ +#ifndef PYGAMEAPI_BASE_INTERNAL +#define pgExc_SDLError ((PyObject *)PYGAMEAPI_GET_SLOT(base, 0)) + +#define pg_RegisterQuit \ + (*(void (*)(void (*)(void)))PYGAMEAPI_GET_SLOT(base, 1)) + +#define pg_IntFromObj \ + (*(int (*)(PyObject *, int *))PYGAMEAPI_GET_SLOT(base, 2)) + +#define pg_IntFromObjIndex \ + (*(int (*)(PyObject *, int, int *))PYGAMEAPI_GET_SLOT(base, 3)) + +#define pg_TwoIntsFromObj \ + (*(int (*)(PyObject *, int *, int *))PYGAMEAPI_GET_SLOT(base, 4)) + +#define pg_FloatFromObj \ + (*(int (*)(PyObject *, float *))PYGAMEAPI_GET_SLOT(base, 5)) + +#define pg_FloatFromObjIndex \ + (*(int (*)(PyObject *, int, float *))PYGAMEAPI_GET_SLOT(base, 6)) + +#define pg_TwoFloatsFromObj \ + (*(int (*)(PyObject *, float *, float *))PYGAMEAPI_GET_SLOT(base, 7)) + +#define pg_UintFromObj \ + (*(int (*)(PyObject *, Uint32 *))PYGAMEAPI_GET_SLOT(base, 8)) + +#define pg_UintFromObjIndex \ + (*(int (*)(PyObject *, int, Uint32 *))PYGAMEAPI_GET_SLOT(base, 9)) + +#define pg_mod_autoinit (*(int (*)(const char *))PYGAMEAPI_GET_SLOT(base, 10)) + +#define pg_mod_autoquit (*(void (*)(const char *))PYGAMEAPI_GET_SLOT(base, 11)) + +#define pg_RGBAFromObj \ + (*(int (*)(PyObject *, Uint8 *))PYGAMEAPI_GET_SLOT(base, 12)) + +#define pgBuffer_AsArrayInterface \ + (*(PyObject * (*)(Py_buffer *)) PYGAMEAPI_GET_SLOT(base, 13)) + +#define pgBuffer_AsArrayStruct \ + (*(PyObject * (*)(Py_buffer *)) PYGAMEAPI_GET_SLOT(base, 14)) + +#define pgObject_GetBuffer \ + (*(int (*)(PyObject *, pg_buffer *, int))PYGAMEAPI_GET_SLOT(base, 15)) + +#define pgBuffer_Release (*(void (*)(pg_buffer *))PYGAMEAPI_GET_SLOT(base, 16)) + +#define pgDict_AsBuffer \ + (*(int (*)(pg_buffer *, PyObject *, int))PYGAMEAPI_GET_SLOT(base, 17)) + +#define pgExc_BufferError ((PyObject *)PYGAMEAPI_GET_SLOT(base, 18)) + +#define pg_GetDefaultWindow \ + (*(SDL_Window * (*)(void)) PYGAMEAPI_GET_SLOT(base, 19)) + +#define pg_SetDefaultWindow \ + (*(void (*)(SDL_Window *))PYGAMEAPI_GET_SLOT(base, 20)) + +#define pg_GetDefaultWindowSurface \ + (*(pgSurfaceObject * (*)(void)) PYGAMEAPI_GET_SLOT(base, 21)) + +#define pg_SetDefaultWindowSurface \ + (*(void (*)(pgSurfaceObject *))PYGAMEAPI_GET_SLOT(base, 22)) + +#define pg_EnvShouldBlendAlphaSDL2 \ + (*(char *(*)(void))PYGAMEAPI_GET_SLOT(base, 23)) + +#define import_pygame_base() IMPORT_PYGAME_MODULE(base) +#endif /* ~PYGAMEAPI_BASE_INTERNAL */ + +typedef struct { + PyObject_HEAD SDL_Rect r; + PyObject *weakreflist; +} pgRectObject; + +#define pgRect_AsRect(x) (((pgRectObject *)x)->r) +#ifndef PYGAMEAPI_RECT_INTERNAL +#define pgRect_Type (*(PyTypeObject *)PYGAMEAPI_GET_SLOT(rect, 0)) + +#define pgRect_Check(x) ((x)->ob_type == &pgRect_Type) +#define pgRect_New (*(PyObject * (*)(SDL_Rect *)) PYGAMEAPI_GET_SLOT(rect, 1)) + +#define pgRect_New4 \ + (*(PyObject * (*)(int, int, int, int)) PYGAMEAPI_GET_SLOT(rect, 2)) + +#define pgRect_FromObject \ + (*(SDL_Rect * (*)(PyObject *, SDL_Rect *)) PYGAMEAPI_GET_SLOT(rect, 3)) + +#define pgRect_Normalize (*(void (*)(SDL_Rect *))PYGAMEAPI_GET_SLOT(rect, 4)) + +#define import_pygame_rect() IMPORT_PYGAME_MODULE(rect) +#endif /* ~PYGAMEAPI_RECT_INTERNAL */ + +/* + * CDROM module + */ + +typedef struct { + PyObject_HEAD int id; +} pgCDObject; + +#define pgCD_AsID(x) (((pgCDObject *)x)->id) +#ifndef PYGAMEAPI_CDROM_INTERNAL +#define pgCD_Type (*(PyTypeObject *)PYGAMEAPI_GET_SLOT(cdrom, 0)) + +#define pgCD_Check(x) ((x)->ob_type == &pgCD_Type) +#define pgCD_New (*(PyObject * (*)(int)) PYGAMEAPI_GET_SLOT(cdrom, 1)) + +#define import_pygame_cd() IMPORT_PYGAME_MODULE(cdrom) +#endif + +/* + * JOYSTICK module + */ +typedef struct pgJoystickObject { + PyObject_HEAD int id; + SDL_Joystick *joy; + + /* Joysticks form an intrusive linked list. + * + * Note that we don't maintain refcounts for these so they are weakrefs + * from the Python side. + */ + struct pgJoystickObject *next; + struct pgJoystickObject *prev; +} pgJoystickObject; + +#define pgJoystick_AsID(x) (((pgJoystickObject *)x)->id) +#define pgJoystick_AsSDL(x) (((pgJoystickObject *)x)->joy) + +#ifndef PYGAMEAPI_JOYSTICK_INTERNAL +#define pgJoystick_Type (*(PyTypeObject *)PYGAMEAPI_GET_SLOT(joystick, 0)) + +#define pgJoystick_Check(x) ((x)->ob_type == &pgJoystick_Type) +#define pgJoystick_New (*(PyObject * (*)(int)) PYGAMEAPI_GET_SLOT(joystick, 1)) + +#define import_pygame_joystick() IMPORT_PYGAME_MODULE(joystick) +#endif + +/* + * DISPLAY module + */ + +typedef struct { + Uint32 hw_available : 1; + Uint32 wm_available : 1; + Uint32 blit_hw : 1; + Uint32 blit_hw_CC : 1; + Uint32 blit_hw_A : 1; + Uint32 blit_sw : 1; + Uint32 blit_sw_CC : 1; + Uint32 blit_sw_A : 1; + Uint32 blit_fill : 1; + Uint32 video_mem; + SDL_PixelFormat *vfmt; + SDL_PixelFormat vfmt_data; + int current_w; + int current_h; +} pg_VideoInfo; + +typedef struct { + PyObject_HEAD pg_VideoInfo info; +} pgVidInfoObject; + +#define pgVidInfo_AsVidInfo(x) (((pgVidInfoObject *)x)->info) + +#ifndef PYGAMEAPI_DISPLAY_INTERNAL +#define pgVidInfo_Type (*(PyTypeObject *)PYGAMEAPI_GET_SLOT(display, 0)) + +#define pgVidInfo_Check(x) ((x)->ob_type == &pgVidInfo_Type) +#define pgVidInfo_New \ + (*(PyObject * (*)(pg_VideoInfo *)) PYGAMEAPI_GET_SLOT(display, 1)) + +#define import_pygame_display() IMPORT_PYGAME_MODULE(display) +#endif /* ~PYGAMEAPI_DISPLAY_INTERNAL */ + +/* + * SURFACE module + */ +struct pgSubSurface_Data; +struct SDL_Surface; + +typedef struct { + PyObject_HEAD struct SDL_Surface *surf; + int owner; + struct pgSubSurface_Data *subsurface; /* ptr to subsurface data (if a + * subsurface)*/ + PyObject *weakreflist; + PyObject *locklist; + PyObject *dependency; +} pgSurfaceObject; +#define pgSurface_AsSurface(x) (((pgSurfaceObject *)x)->surf) + +#ifndef PYGAMEAPI_SURFACE_INTERNAL +#define pgSurface_Type (*(PyTypeObject *)PYGAMEAPI_GET_SLOT(surface, 0)) + +#define pgSurface_Check(x) \ + (PyObject_IsInstance((x), (PyObject *)&pgSurface_Type)) +#define pgSurface_New2 \ + (*(pgSurfaceObject * (*)(SDL_Surface *, int)) \ + PYGAMEAPI_GET_SLOT(surface, 1)) + +#define pgSurface_SetSurface \ + (*(int (*)(pgSurfaceObject *, SDL_Surface *, int))PYGAMEAPI_GET_SLOT( \ + surface, 3)) + +#define pgSurface_Blit \ + (*(int (*)(pgSurfaceObject *, pgSurfaceObject *, SDL_Rect *, SDL_Rect *, \ + int))PYGAMEAPI_GET_SLOT(surface, 2)) + +#define import_pygame_surface() \ + do { \ + IMPORT_PYGAME_MODULE(surface); \ + if (PyErr_Occurred() != NULL) \ + break; \ + IMPORT_PYGAME_MODULE(surflock); \ + } while (0) + +#define pgSurface_New(surface) pgSurface_New2((surface), 1) +#define pgSurface_NewNoOwn(surface) pgSurface_New2((surface), 0) + +#endif /* ~PYGAMEAPI_SURFACE_INTERNAL */ + +/* + * SURFLOCK module + * auto imported/initialized by surface + */ +#ifndef PYGAMEAPI_SURFLOCK_INTERNAL +#define pgLifetimeLock_Type (*(PyTypeObject *)PYGAMEAPI_GET_SLOT(surflock, 0)) + +#define pgLifetimeLock_Check(x) ((x)->ob_type == &pgLifetimeLock_Type) + +#define pgSurface_Prep(x) \ + if ((x)->subsurface) \ + (*(*(void (*)(pgSurfaceObject *))PYGAMEAPI_GET_SLOT(surflock, 1)))(x) + +#define pgSurface_Unprep(x) \ + if ((x)->subsurface) \ + (*(*(void (*)(pgSurfaceObject *))PYGAMEAPI_GET_SLOT(surflock, 2)))(x) + +#define pgSurface_Lock \ + (*(int (*)(pgSurfaceObject *))PYGAMEAPI_GET_SLOT(surflock, 3)) + +#define pgSurface_Unlock \ + (*(int (*)(pgSurfaceObject *))PYGAMEAPI_GET_SLOT(surflock, 4)) + +#define pgSurface_LockBy \ + (*(int (*)(pgSurfaceObject *, PyObject *))PYGAMEAPI_GET_SLOT(surflock, 5)) + +#define pgSurface_UnlockBy \ + (*(int (*)(pgSurfaceObject *, PyObject *))PYGAMEAPI_GET_SLOT(surflock, 6)) + +#define pgSurface_LockLifetime \ + (*(PyObject * (*)(PyObject *, PyObject *)) PYGAMEAPI_GET_SLOT(surflock, 7)) +#endif + +/* + * EVENT module + */ +typedef struct pgEventObject pgEventObject; + +#ifndef PYGAMEAPI_EVENT_INTERNAL +#define pgEvent_Type (*(PyTypeObject *)PYGAMEAPI_GET_SLOT(event, 0)) + +#define pgEvent_Check(x) ((x)->ob_type == &pgEvent_Type) + +#define pgEvent_New \ + (*(PyObject * (*)(SDL_Event *)) PYGAMEAPI_GET_SLOT(event, 1)) + +#define pgEvent_New2 \ + (*(PyObject * (*)(int, PyObject *)) PYGAMEAPI_GET_SLOT(event, 2)) + +#define pgEvent_FillUserEvent \ + (*(int (*)(pgEventObject *, SDL_Event *))PYGAMEAPI_GET_SLOT(event, 3)) + +#define pg_EnableKeyRepeat (*(int (*)(int, int))PYGAMEAPI_GET_SLOT(event, 4)) + +#define pg_GetKeyRepeat (*(void (*)(int *, int *))PYGAMEAPI_GET_SLOT(event, 5)) + +#define import_pygame_event() IMPORT_PYGAME_MODULE(event) +#endif + +/* + * RWOBJECT module + * the rwobject are only needed for C side work, not accessable from python. + */ +#ifndef PYGAMEAPI_RWOBJECT_INTERNAL +#define pgRWops_FromObject \ + (*(SDL_RWops * (*)(PyObject *)) PYGAMEAPI_GET_SLOT(rwobject, 0)) + +#define pgRWops_IsFileObject \ + (*(int (*)(SDL_RWops *))PYGAMEAPI_GET_SLOT(rwobject, 1)) + +#define pg_EncodeFilePath \ + (*(PyObject * (*)(PyObject *, PyObject *)) PYGAMEAPI_GET_SLOT(rwobject, 2)) + +#define pg_EncodeString \ + (*(PyObject * (*)(PyObject *, const char *, const char *, PyObject *)) \ + PYGAMEAPI_GET_SLOT(rwobject, 3)) + +#define pgRWops_FromFileObject \ + (*(SDL_RWops * (*)(PyObject *)) PYGAMEAPI_GET_SLOT(rwobject, 4)) + +#define pgRWops_ReleaseObject \ + (*(int (*)(SDL_RWops *))PYGAMEAPI_GET_SLOT(rwobject, 5)) + +#define pgRWops_GetFileExtension \ + (*(char *(*)(SDL_RWops *))PYGAMEAPI_GET_SLOT(rwobject, 6)) + +#define import_pygame_rwobject() IMPORT_PYGAME_MODULE(rwobject) + +#endif + +/* + * PixelArray module + */ +#ifndef PYGAMEAPI_PIXELARRAY_INTERNAL +#define PyPixelArray_Type ((PyTypeObject *)PYGAMEAPI_GET_SLOT(pixelarray, 0)) + +#define PyPixelArray_Check(x) ((x)->ob_type == &PyPixelArray_Type) +#define PyPixelArray_New (*(PyObject * (*)) PYGAMEAPI_GET_SLOT(pixelarray, 1)) + +#define import_pygame_pixelarray() IMPORT_PYGAME_MODULE(pixelarray) +#endif /* PYGAMEAPI_PIXELARRAY_INTERNAL */ + +/* + * Color module + */ +typedef struct pgColorObject pgColorObject; + +#ifndef PYGAMEAPI_COLOR_INTERNAL +#define pgColor_Type (*(PyObject *)PYGAMEAPI_GET_SLOT(color, 0)) + +#define pgColor_Check(x) ((x)->ob_type == &pgColor_Type) +#define pgColor_New (*(PyObject * (*)(Uint8 *)) PYGAMEAPI_GET_SLOT(color, 1)) + +#define pgColor_NewLength \ + (*(PyObject * (*)(Uint8 *, Uint8)) PYGAMEAPI_GET_SLOT(color, 3)) + +#define pg_RGBAFromColorObj \ + (*(int (*)(PyObject *, Uint8 *))PYGAMEAPI_GET_SLOT(color, 2)) + +#define pg_RGBAFromFuzzyColorObj \ + (*(int (*)(PyObject *, Uint8 *))PYGAMEAPI_GET_SLOT(color, 4)) + +#define pgColor_AsArray(x) (((pgColorObject *)x)->data) +#define pgColor_NumComponents(x) (((pgColorObject *)x)->len) + +#define import_pygame_color() IMPORT_PYGAME_MODULE(color) +#endif /* PYGAMEAPI_COLOR_INTERNAL */ + +/* + * Math module + */ +#ifndef PYGAMEAPI_MATH_INTERNAL +#define pgVector2_Check(x) \ + ((x)->ob_type == (PyTypeObject *)PYGAMEAPI_GET_SLOT(math, 0)) + +#define pgVector3_Check(x) \ + ((x)->ob_type == (PyTypeObject *)PYGAMEAPI_GET_SLOT(math, 1)) +/* +#define pgVector2_New \ + (*(PyObject*(*)) \ + PYGAMEAPI_GET_SLOT(PyGAME_C_API, 1)) +*/ +#define import_pygame_math() IMPORT_PYGAME_MODULE(math) +#endif /* PYGAMEAPI_MATH_INTERNAL */ + +#define IMPORT_PYGAME_MODULE _IMPORT_PYGAME_MODULE + +/* + * base pygame API slots + * disable slots with NO_PYGAME_C_API + */ +#ifdef PYGAME_H +PYGAMEAPI_DEFINE_SLOTS(base); +PYGAMEAPI_DEFINE_SLOTS(rect); +PYGAMEAPI_DEFINE_SLOTS(cdrom); +PYGAMEAPI_DEFINE_SLOTS(joystick); +PYGAMEAPI_DEFINE_SLOTS(display); +PYGAMEAPI_DEFINE_SLOTS(surface); +PYGAMEAPI_DEFINE_SLOTS(surflock); +PYGAMEAPI_DEFINE_SLOTS(event); +PYGAMEAPI_DEFINE_SLOTS(rwobject); +PYGAMEAPI_DEFINE_SLOTS(pixelarray); +PYGAMEAPI_DEFINE_SLOTS(color); +PYGAMEAPI_DEFINE_SLOTS(math); +#else /* ~PYGAME_H */ +PYGAMEAPI_EXTERN_SLOTS(base); +PYGAMEAPI_EXTERN_SLOTS(rect); +PYGAMEAPI_EXTERN_SLOTS(cdrom); +PYGAMEAPI_EXTERN_SLOTS(joystick); +PYGAMEAPI_EXTERN_SLOTS(display); +PYGAMEAPI_EXTERN_SLOTS(surface); +PYGAMEAPI_EXTERN_SLOTS(surflock); +PYGAMEAPI_EXTERN_SLOTS(event); +PYGAMEAPI_EXTERN_SLOTS(rwobject); +PYGAMEAPI_EXTERN_SLOTS(pixelarray); +PYGAMEAPI_EXTERN_SLOTS(color); +PYGAMEAPI_EXTERN_SLOTS(math); +#endif /* ~PYGAME_H */ + +#endif /* PYGAME_H */ diff --git a/venv/Include/site/python3.9/pygame/include/bitmask.h b/venv/Include/site/python3.9/pygame/include/bitmask.h new file mode 100644 index 0000000..eee09b7 --- /dev/null +++ b/venv/Include/site/python3.9/pygame/include/bitmask.h @@ -0,0 +1,171 @@ +/* + Bitmask 1.7 - A pixel-perfect collision detection library. + + Copyright (C) 2002-2005 Ulf Ekstrom except for the bitcount + function which is copyright (C) Donald W. Gillies, 1992. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef BITMASK_H +#define BITMASK_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +/* Define INLINE for different compilers. If your compiler does not + support inlining then there might be a performance hit in + bitmask_overlap_area(). +*/ +#ifndef INLINE +#ifdef __GNUC__ +#define INLINE inline +#else +#ifdef _MSC_VER +#define INLINE __inline +#else +#define INLINE +#endif +#endif +#endif + +#define BITMASK_W unsigned long int +#define BITMASK_W_LEN (sizeof(BITMASK_W) * CHAR_BIT) +#define BITMASK_W_MASK (BITMASK_W_LEN - 1) +#define BITMASK_N(n) ((BITMASK_W)1 << (n)) + +typedef struct bitmask { + int w, h; + BITMASK_W bits[1]; +} bitmask_t; + +/* Creates a bitmask of width w and height h, where + w and h must both be greater than or equal to 0. + The mask is automatically cleared when created. + */ +bitmask_t * +bitmask_create(int w, int h); + +/* Frees all the memory allocated by bitmask_create for m. */ +void +bitmask_free(bitmask_t *m); + +/* Create a copy of the given bitmask. */ +bitmask_t * +bitmask_copy(bitmask_t *m); + +/* Clears all bits in the mask */ +void +bitmask_clear(bitmask_t *m); + +/* Sets all bits in the mask */ +void +bitmask_fill(bitmask_t *m); + +/* Flips all bits in the mask */ +void +bitmask_invert(bitmask_t *m); + +/* Counts the bits in the mask */ +unsigned int +bitmask_count(bitmask_t *m); + +/* Returns nonzero if the bit at (x,y) is set. Coordinates start at + (0,0) */ +static INLINE int +bitmask_getbit(const bitmask_t *m, int x, int y) +{ + return (m->bits[x / BITMASK_W_LEN * m->h + y] & + BITMASK_N(x & BITMASK_W_MASK)) != 0; +} + +/* Sets the bit at (x,y) */ +static INLINE void +bitmask_setbit(bitmask_t *m, int x, int y) +{ + m->bits[x / BITMASK_W_LEN * m->h + y] |= BITMASK_N(x & BITMASK_W_MASK); +} + +/* Clears the bit at (x,y) */ +static INLINE void +bitmask_clearbit(bitmask_t *m, int x, int y) +{ + m->bits[x / BITMASK_W_LEN * m->h + y] &= ~BITMASK_N(x & BITMASK_W_MASK); +} + +/* Returns nonzero if the masks overlap with the given offset. + The overlap tests uses the following offsets (which may be negative): + + +----+----------.. + |A | yoffset + | +-+----------.. + +--|B + |xoffset + | | + : : +*/ +int +bitmask_overlap(const bitmask_t *a, const bitmask_t *b, int xoffset, + int yoffset); + +/* Like bitmask_overlap(), but will also give a point of intersection. + x and y are given in the coordinates of mask a, and are untouched + if there is no overlap. */ +int +bitmask_overlap_pos(const bitmask_t *a, const bitmask_t *b, int xoffset, + int yoffset, int *x, int *y); + +/* Returns the number of overlapping 'pixels' */ +int +bitmask_overlap_area(const bitmask_t *a, const bitmask_t *b, int xoffset, + int yoffset); + +/* Fills a mask with the overlap of two other masks. A bitwise AND. */ +void +bitmask_overlap_mask(const bitmask_t *a, const bitmask_t *b, bitmask_t *c, + int xoffset, int yoffset); + +/* Draws mask b onto mask a (bitwise OR). Can be used to compose large + (game background?) mask from several submasks, which may speed up + the testing. */ + +void +bitmask_draw(bitmask_t *a, const bitmask_t *b, int xoffset, int yoffset); + +void +bitmask_erase(bitmask_t *a, const bitmask_t *b, int xoffset, int yoffset); + +/* Return a new scaled bitmask, with dimensions w*h. The quality of the + scaling may not be perfect for all circumstances, but it should + be reasonable. If either w or h is 0 a clear 1x1 mask is returned. */ +bitmask_t * +bitmask_scale(const bitmask_t *m, int w, int h); + +/* Convolve b into a, drawing the output into o, shifted by offset. If offset + * is 0, then the (x,y) bit will be set if and only if + * bitmask_overlap(a, b, x - b->w - 1, y - b->h - 1) returns true. + * + * Modifies bits o[xoffset ... xoffset + a->w + b->w - 1) + * [yoffset ... yoffset + a->h + b->h - 1). */ +void +bitmask_convolve(const bitmask_t *a, const bitmask_t *b, bitmask_t *o, + int xoffset, int yoffset); + +#ifdef __cplusplus +} /* End of extern "C" { */ +#endif + +#endif diff --git a/venv/Include/site/python3.9/pygame/include/pgcompat.h b/venv/Include/site/python3.9/pygame/include/pgcompat.h new file mode 100644 index 0000000..4a11ca0 --- /dev/null +++ b/venv/Include/site/python3.9/pygame/include/pgcompat.h @@ -0,0 +1,108 @@ +/* Python 2.x/3.x and SDL compatibility tools + */ + +#if !defined(PGCOMPAT_H) +#define PGCOMPAT_H + +#include + +/* define common types where SDL is not included */ +#ifndef SDL_VERSION_ATLEAST +#ifdef _MSC_VER +typedef unsigned __int8 uint8_t; +typedef unsigned __int32 uint32_t; +#else +#include +#endif +typedef uint32_t Uint32; +typedef uint8_t Uint8; +#endif /* no SDL */ + +#if defined(SDL_VERSION_ATLEAST) + +#ifndef SDL_WINDOW_VULKAN +#define SDL_WINDOW_VULKAN 0 +#endif + +#ifndef SDL_WINDOW_ALWAYS_ON_TOP +#define SDL_WINDOW_ALWAYS_ON_TOP 0 +#endif + +#ifndef SDL_WINDOW_SKIP_TASKBAR +#define SDL_WINDOW_SKIP_TASKBAR 0 +#endif + +#ifndef SDL_WINDOW_UTILITY +#define SDL_WINDOW_UTILITY 0 +#endif + +#ifndef SDL_WINDOW_TOOLTIP +#define SDL_WINDOW_TOOLTIP 0 +#endif + +#ifndef SDL_WINDOW_POPUP_MENU +#define SDL_WINDOW_POPUP_MENU 0 +#endif + +#ifndef SDL_WINDOW_INPUT_GRABBED +#define SDL_WINDOW_INPUT_GRABBED 0 +#endif + +#ifndef SDL_WINDOW_INPUT_FOCUS +#define SDL_WINDOW_INPUT_FOCUS 0 +#endif + +#ifndef SDL_WINDOW_MOUSE_FOCUS +#define SDL_WINDOW_MOUSE_FOCUS 0 +#endif + +#ifndef SDL_WINDOW_FOREIGN +#define SDL_WINDOW_FOREIGN 0 +#endif + +#ifndef SDL_WINDOW_ALLOW_HIGHDPI +#define SDL_WINDOW_ALLOW_HIGHDPI 0 +#endif + +#ifndef SDL_WINDOW_MOUSE_CAPTURE +#define SDL_WINDOW_MOUSE_CAPTURE 0 +#endif + +#ifndef SDL_WINDOW_ALWAYS_ON_TOP +#define SDL_WINDOW_ALWAYS_ON_TOP 0 +#endif + +#ifndef SDL_WINDOW_SKIP_TASKBAR +#define SDL_WINDOW_SKIP_TASKBAR 0 +#endif + +#ifndef SDL_WINDOW_UTILITY +#define SDL_WINDOW_UTILITY 0 +#endif + +#ifndef SDL_WINDOW_TOOLTIP +#define SDL_WINDOW_TOOLTIP 0 +#endif + +#ifndef SDL_WINDOW_POPUP_MENU +#define SDL_WINDOW_POPUP_MENU 0 +#endif + +#if SDL_VERSION_ATLEAST(2, 0, 4) +/* To control the use of: + * SDL_AUDIODEVICEADDED + * SDL_AUDIODEVICEREMOVED + * + * Ref: https://wiki.libsdl.org/SDL_EventType + * Ref: https://wiki.libsdl.org/SDL_AudioDeviceEvent + */ +#define SDL2_AUDIODEVICE_SUPPORTED +#endif + +#ifndef SDL_MOUSEWHEEL_FLIPPED +#define NO_SDL_MOUSEWHEEL_FLIPPED +#endif + +#endif /* defined(SDL_VERSION_ATLEAST) */ + +#endif /* ~defined(PGCOMPAT_H) */ diff --git a/venv/Include/site/python3.9/pygame/include/pgimport.h b/venv/Include/site/python3.9/pygame/include/pgimport.h new file mode 100644 index 0000000..16a36db --- /dev/null +++ b/venv/Include/site/python3.9/pygame/include/pgimport.h @@ -0,0 +1,80 @@ +#ifndef PGIMPORT_H +#define PGIMPORT_H + +/* Prefix when initializing module */ +#define MODPREFIX "" +/* Prefix when importing module */ +#define IMPPREFIX "pygame." + +#ifdef __SYMBIAN32__ + +/* On Symbian there is no pygame package. The extensions are built-in or in + * sys\bin. */ +#undef MODPREFIX +#undef IMPPREFIX +#define MODPREFIX "pygame_" +#define IMPPREFIX "pygame_" + +#endif /* __SYMBIAN32__ */ + +#include "pgcompat.h" + +#define PYGAMEAPI_LOCAL_ENTRY "_PYGAME_C_API" +#define PG_CAPSULE_NAME(m) (IMPPREFIX m "." PYGAMEAPI_LOCAL_ENTRY) + +/* + * fill API slots defined by PYGAMEAPI_DEFINE_SLOTS/PYGAMEAPI_EXTERN_SLOTS + */ +#define _IMPORT_PYGAME_MODULE(module) \ + { \ + PyObject *_mod_##module = PyImport_ImportModule(IMPPREFIX #module); \ + \ + if (_mod_##module != NULL) { \ + PyObject *_c_api = \ + PyObject_GetAttrString(_mod_##module, PYGAMEAPI_LOCAL_ENTRY); \ + \ + Py_DECREF(_mod_##module); \ + if (_c_api != NULL && PyCapsule_CheckExact(_c_api)) { \ + void **localptr = (void **)PyCapsule_GetPointer( \ + _c_api, PG_CAPSULE_NAME(#module)); \ + _PGSLOTS_##module = localptr; \ + } \ + Py_XDECREF(_c_api); \ + } \ + } + +#define PYGAMEAPI_IS_IMPORTED(module) (_PGSLOTS_##module != NULL) + +/* + * source file must include one of these in order to use _IMPORT_PYGAME_MODULE. + * this is set by import_pygame_*() functions. + * disable with NO_PYGAME_C_API + */ +#define PYGAMEAPI_DEFINE_SLOTS(module) void **_PGSLOTS_##module = NULL +#define PYGAMEAPI_EXTERN_SLOTS(module) extern void **_PGSLOTS_##module +#define PYGAMEAPI_GET_SLOT(module, index) _PGSLOTS_##module[(index)] + +/* + * disabled API with NO_PYGAME_C_API; do nothing instead + */ +#ifdef NO_PYGAME_C_API + +#undef PYGAMEAPI_DEFINE_SLOTS +#undef PYGAMEAPI_EXTERN_SLOTS + +#define PYGAMEAPI_DEFINE_SLOTS(module) +#define PYGAMEAPI_EXTERN_SLOTS(module) + +/* intentionally leave this defined to cause a compiler error * +#define PYGAMEAPI_GET_SLOT(api_root, index) +#undef PYGAMEAPI_GET_SLOT*/ + +#undef _IMPORT_PYGAME_MODULE +#define _IMPORT_PYGAME_MODULE(module) + +#endif /* NO_PYGAME_C_API */ + +#define encapsulate_api(ptr, module) \ + PyCapsule_New(ptr, PG_CAPSULE_NAME(module), NULL) + +#endif /* ~PGIMPORT_H */ diff --git a/venv/Include/site/python3.9/pygame/include/pgplatform.h b/venv/Include/site/python3.9/pygame/include/pgplatform.h new file mode 100644 index 0000000..c73cc24 --- /dev/null +++ b/venv/Include/site/python3.9/pygame/include/pgplatform.h @@ -0,0 +1,92 @@ +/* platform/compiler adjustments */ +#ifndef PG_PLATFORM_H +#define PG_PLATFORM_H + +#if defined(HAVE_SNPRINTF) /* defined in python.h (pyerrors.h) and SDL.h \ + (SDL_config.h) */ +#undef HAVE_SNPRINTF /* remove GCC redefine warning */ +#endif /* HAVE_SNPRINTF */ + +#ifndef PG_INLINE +#if defined(__clang__) +#define PG_INLINE __inline__ __attribute__((__unused__)) +#elif defined(__GNUC__) +#define PG_INLINE __inline__ +#elif defined(_MSC_VER) +#define PG_INLINE __inline +#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L +#define PG_INLINE inline +#else +#define PG_INLINE +#endif +#endif /* ~PG_INLINE */ + +// Worth trying this on MSVC/win32 builds to see if provides any speed up +#ifndef PG_FORCEINLINE +#if defined(__clang__) +#define PG_FORCEINLINE __inline__ __attribute__((__unused__)) +#elif defined(__GNUC__) +#define PG_FORCEINLINE __inline__ +#elif defined(_MSC_VER) +#define PG_FORCEINLINE __forceinline +#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L +#define PG_FORCEINLINE inline +#else +#define PG_FORCEINLINE +#endif +#endif /* ~PG_FORCEINLINE */ + +/* This is unconditionally defined in Python.h */ +#if defined(_POSIX_C_SOURCE) +#undef _POSIX_C_SOURCE +#endif + +/* No signal() */ +#if defined(__SYMBIAN32__) && defined(HAVE_SIGNAL_H) +#undef HAVE_SIGNAL_H +#endif + +#if defined(HAVE_SNPRINTF) +#undef HAVE_SNPRINTF +#endif + +/* SDL needs WIN32 */ +#if !defined(WIN32) && \ + (defined(MS_WIN32) || defined(_WIN32) || defined(__WIN32) || \ + defined(__WIN32__) || defined(_WINDOWS)) +#define WIN32 +#endif + +/* Commenting out SSE4_2 stuff because it does not do runtime detection. +#ifndef PG_TARGET_SSE4_2 +#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ == 4 && +__GNUC_MINOR__ >= 9) || __GNUC__ >= 5 )) +//The old gcc 4.8 on centos used by manylinux1 does not seem to get sse4.2 +intrinsics #define PG_FUNCTION_TARGET_SSE4_2 __attribute__((target("sse4.2"))) +// No else; we define the fallback later +#endif +#endif +*/ +/* ~PG_TARGET_SSE4_2 */ + +/* +#ifdef PG_FUNCTION_TARGET_SSE4_2 +#if !defined(__SSE4_2__) && !defined(PG_COMPILE_SSE4_2) +#if defined(__x86_64__) || defined(__i386__) +#define PG_COMPILE_SSE4_2 1 +#endif +#endif +#endif +*/ +/* ~PG_TARGET_SSE4_2 */ + +/* Fallback definition of target attribute */ +#ifndef PG_FUNCTION_TARGET_SSE4_2 +#define PG_FUNCTION_TARGET_SSE4_2 +#endif + +#ifndef PG_COMPILE_SSE4_2 +#define PG_COMPILE_SSE4_2 0 +#endif + +#endif /* ~PG_PLATFORM_H */ diff --git a/venv/Include/site/python3.9/pygame/include/pygame.h b/venv/Include/site/python3.9/pygame/include/pygame.h new file mode 100644 index 0000000..3772ae6 --- /dev/null +++ b/venv/Include/site/python3.9/pygame/include/pygame.h @@ -0,0 +1,34 @@ +/* + pygame - Python Game Library + Copyright (C) 2000-2001 Pete Shinners + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Pete Shinners + pete@shinners.org +*/ + +/* To allow the Pygame C api to be globally shared by all code within an + * extension module built from multiple C files, only include the pygame.h + * header within the top level C file, the one which calls the + * 'import_pygame_*' macros. All other C source files of the module should + * include _pygame.h instead. + */ +#ifndef PYGAME_H +#define PYGAME_H + +#include "_pygame.h" + +#endif diff --git a/venv/Include/site/python3.9/pygame/include/pygame_bufferproxy.h b/venv/Include/site/python3.9/pygame/include/pygame_bufferproxy.h new file mode 100644 index 0000000..9284ff2 --- /dev/null +++ b/venv/Include/site/python3.9/pygame/include/pygame_bufferproxy.h @@ -0,0 +1,56 @@ +/* + pygame - Python Game Library + Copyright (C) 2000-2001 Pete Shinners + Copyright (C) 2007 Rene Dudfield, Richard Goedeken + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Pete Shinners + pete@shinners.org +*/ + +/* Bufferproxy module C api. */ +#if !defined(PG_BUFPROXY_HEADER) +#define PG_BUFPROXY_HEADER + +#include + +typedef PyObject *(*_pgbufproxy_new_t)(PyObject *, getbufferproc); +typedef PyObject *(*_pgbufproxy_get_obj_t)(PyObject *); +typedef int (*_pgbufproxy_trip_t)(PyObject *); + +#ifndef PYGAMEAPI_BUFPROXY_INTERNAL + +#include "pgimport.h" + +PYGAMEAPI_DEFINE_SLOTS(bufferproxy); + +#define pgBufproxy_Type (*(PyTypeObject *)PYGAMEAPI_GET_SLOT(bufferproxy, 0)) + +#define pgBufproxy_Check(x) ((x)->ob_type == &pgBufproxy_Type) + +#define pgBufproxy_New (*(_pgbufproxy_new_t)PYGAMEAPI_GET_SLOT(bufferproxy, 1)) + +#define pgBufproxy_GetParent \ + (*(_pgbufproxy_get_obj_t)PYGAMEAPI_GET_SLOT(bufferproxy, 2)) + +#define pgBufproxy_Trip \ + (*(_pgbufproxy_trip_t)PYGAMEAPI_GET_SLOT(bufferproxy, 3)) + +#define import_pygame_bufferproxy() _IMPORT_PYGAME_MODULE(bufferproxy) + +#endif /* ~PYGAMEAPI_BUFPROXY_INTERNAL */ + +#endif /* ~defined(PG_BUFPROXY_HEADER) */ diff --git a/venv/Include/site/python3.9/pygame/include/pygame_font.h b/venv/Include/site/python3.9/pygame/include/pygame_font.h new file mode 100644 index 0000000..aae41bf --- /dev/null +++ b/venv/Include/site/python3.9/pygame/include/pygame_font.h @@ -0,0 +1,50 @@ +/* + pygame - Python Game Library + Copyright (C) 2000-2001 Pete Shinners + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Pete Shinners + pete@shinners.org +*/ + +#include +#include "pgplatform.h" + +struct TTF_Font; + +typedef struct { + PyObject_HEAD TTF_Font *font; + PyObject *weakreflist; + unsigned int ttf_init_generation; +} PyFontObject; +#define PyFont_AsFont(x) (((PyFontObject *)x)->font) + +#ifndef PYGAMEAPI_FONT_INTERNAL + +#include "pgimport.h" + +PYGAMEAPI_DEFINE_SLOTS(font); + +#define PyFont_Type (*(PyTypeObject *)PYGAMEAPI_GET_SLOT(font, 0)) +#define PyFont_Check(x) ((x)->ob_type == &PyFont_Type) + +#define PyFont_New (*(PyObject * (*)(TTF_Font *)) PYGAMEAPI_GET_SLOT(font, 1)) + +/*slot 2 taken by FONT_INIT_CHECK*/ + +#define import_pygame_font() _IMPORT_PYGAME_MODULE(font) + +#endif diff --git a/venv/Include/site/python3.9/pygame/include/pygame_freetype.h b/venv/Include/site/python3.9/pygame/include/pygame_freetype.h new file mode 100644 index 0000000..90172cc --- /dev/null +++ b/venv/Include/site/python3.9/pygame/include/pygame_freetype.h @@ -0,0 +1,42 @@ +/* + pygame - Python Game Library + Copyright (C) 2009 Vicent Marti + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ +#ifndef PYGAME_FREETYPE_H_ +#define PYGAME_FREETYPE_H_ + +#include "pgplatform.h" +#include "pgimport.h" +#include "pgcompat.h" + +#ifndef PYGAME_FREETYPE_INTERNAL + +PYGAMEAPI_DEFINE_SLOTS(_freetype); + +#define pgFont_Type (*(PyTypeObject *)PYGAMEAPI_GET_SLOT(_freetype, 0)) + +#define pgFont_Check(x) ((x)->ob_type == &pgFont_Type) + +#define pgFont_New \ + (*(PyObject * (*)(const char *, long)) PYGAMEAPI_GET_SLOT(_freetype, 1)) + +#define import_pygame_freetype() _IMPORT_PYGAME_MODULE(_freetype) + +#endif /* PYGAME_FREETYPE_INTERNAL */ + +#endif /* PYGAME_FREETYPE_H_ */ diff --git a/venv/Include/site/python3.9/pygame/include/pygame_mask.h b/venv/Include/site/python3.9/pygame/include/pygame_mask.h new file mode 100644 index 0000000..8dd8f17 --- /dev/null +++ b/venv/Include/site/python3.9/pygame/include/pygame_mask.h @@ -0,0 +1,45 @@ +/* + pygame - Python Game Library + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef PGMASK_H +#define PGMASK_H + +#include +#include "bitmask.h" + +typedef struct { + PyObject_HEAD bitmask_t *mask; + void *bufdata; +} pgMaskObject; + +#define pgMask_AsBitmap(x) (((pgMaskObject *)x)->mask) + +#ifndef PYGAMEAPI_MASK_INTERNAL + +#include "pgimport.h" + +PYGAMEAPI_DEFINE_SLOTS(mask); + +#define pgMask_Type (*(PyTypeObject *)PYGAMEAPI_GET_SLOT(mask, 0)) +#define pgMask_Check(x) ((x)->ob_type == &pgMask_Type) + +#define import_pygame_mask() _IMPORT_PYGAME_MODULE(mask) + +#endif /* ~PYGAMEAPI_MASK_INTERNAL */ + +#endif /* ~PGMASK_H */ diff --git a/venv/Include/site/python3.9/pygame/include/pygame_mixer.h b/venv/Include/site/python3.9/pygame/include/pygame_mixer.h new file mode 100644 index 0000000..e19d273 --- /dev/null +++ b/venv/Include/site/python3.9/pygame/include/pygame_mixer.h @@ -0,0 +1,71 @@ +/* + pygame - Python Game Library + Copyright (C) 2000-2001 Pete Shinners + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Pete Shinners + pete@shinners.org +*/ + +#ifndef PGMIXER_H +#define PGMIXER_H + +#include +#include + +#include "pgcompat.h" + +struct Mix_Chunk; + +typedef struct { + PyObject_HEAD Mix_Chunk *chunk; + Uint8 *mem; + PyObject *weakreflist; +} pgSoundObject; + +typedef struct { + PyObject_HEAD int chan; +} pgChannelObject; + +#define pgSound_AsChunk(x) (((pgSoundObject *)x)->chunk) +#define pgChannel_AsInt(x) (((pgChannelObject *)x)->chan) + +#include "pgimport.h" + +#ifndef PYGAMEAPI_MIXER_INTERNAL + +PYGAMEAPI_DEFINE_SLOTS(mixer); + +#define pgSound_Type (*(PyTypeObject *)PYGAMEAPI_GET_SLOT(mixer, 0)) + +#define pgSound_Check(x) ((x)->ob_type == &pgSound_Type) + +#define pgSound_New \ + (*(PyObject * (*)(Mix_Chunk *)) PYGAMEAPI_GET_SLOT(mixer, 1)) + +#define pgSound_Play \ + (*(PyObject * (*)(PyObject *, PyObject *)) PYGAMEAPI_GET_SLOT(mixer, 2)) + +#define pgChannel_Type (*(PyTypeObject *)PYGAMEAPI_GET_SLOT(mixer, 3)) +#define pgChannel_Check(x) ((x)->ob_type == &pgChannel_Type) + +#define pgChannel_New (*(PyObject * (*)(int)) PYGAMEAPI_GET_SLOT(mixer, 4)) + +#define import_pygame_mixer() _IMPORT_PYGAME_MODULE(mixer) + +#endif /* PYGAMEAPI_MIXER_INTERNAL */ + +#endif /* ~PGMIXER_H */ diff --git a/venv/Include/site/python3.9/pygame/include/sse2neon.h b/venv/Include/site/python3.9/pygame/include/sse2neon.h new file mode 100644 index 0000000..a3e3ac0 --- /dev/null +++ b/venv/Include/site/python3.9/pygame/include/sse2neon.h @@ -0,0 +1,6203 @@ +#ifndef SSE2NEON_H +#define SSE2NEON_H + +// This header file provides a simple API translation layer +// between SSE intrinsics to their corresponding Arm/Aarch64 NEON versions +// +// This header file does not yet translate all of the SSE intrinsics. +// +// Contributors to this work are: +// John W. Ratcliff +// Brandon Rowlett +// Ken Fast +// Eric van Beurden +// Alexander Potylitsin +// Hasindu Gamaarachchi +// Jim Huang +// Mark Cheng +// Malcolm James MacLeod +// Devin Hussey (easyaspi314) +// Sebastian Pop +// Developer Ecosystem Engineering +// Danila Kutenin +// François Turban (JishinMaster) +// Pei-Hsuan Hung +// Yang-Hao Yuan + +/* + * sse2neon is freely redistributable under 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. + */ + +/* Tunable configurations */ + +/* Enable precise implementation of _mm_min_ps and _mm_max_ps + * This would slow down the computation a bit, but gives consistent result with + * x86 SSE2. (e.g. would solve a hole or NaN pixel in the rendering result) + */ +#ifndef SSE2NEON_PRECISE_MINMAX +#define SSE2NEON_PRECISE_MINMAX (0) +#endif + +#if defined(__GNUC__) || defined(__clang__) +#pragma push_macro("FORCE_INLINE") +#pragma push_macro("ALIGN_STRUCT") +#define FORCE_INLINE static inline __attribute__((always_inline)) +#define ALIGN_STRUCT(x) __attribute__((aligned(x))) +#else +#error "Macro name collisions may happen with unsupported compiler." +#ifdef FORCE_INLINE +#undef FORCE_INLINE +#endif +#define FORCE_INLINE static inline +#ifndef ALIGN_STRUCT +#define ALIGN_STRUCT(x) __declspec(align(x)) +#endif +#endif + +#include +#include + +// These cause the build to fail on raspberry pi with 'unsupported target' +// and don't seem to do anything particularly useful +///* Architecture-specific build options */ +///* FIXME: #pragma GCC push_options is only available on GCC */ +//#if defined(__GNUC__) +//#if defined(__arm__) && __ARM_ARCH == 7 +///* According to ARM C Language Extensions Architecture specification, +// * __ARM_NEON is defined to a value indicating the Advanced SIMD (NEON) +// * architecture supported. +// */ +//#if !defined(__ARM_NEON) || !defined(__ARM_NEON__) +//#error "You must enable NEON instructions (e.g. -mfpu=neon) to use SSE2NEON." +//#endif +//#pragma GCC push_options +//#pragma GCC target("fpu=neon") +//#elif defined(__aarch64__) +//#pragma GCC push_options +//#pragma GCC target("+simd") +//#else +//#error "Unsupported target. Must be either ARMv7-A+NEON or ARMv8-A." +//#endif +//#endif + +#include + +/* Rounding functions require either Aarch64 instructions or libm failback */ +#if !defined(__aarch64__) +#include +#endif + +/* "__has_builtin" can be used to query support for built-in functions + * provided by gcc/clang and other compilers that support it. + */ +#ifndef __has_builtin /* GCC prior to 10 or non-clang compilers */ +/* Compatibility with gcc <= 9 */ +#if __GNUC__ <= 9 +#define __has_builtin(x) HAS##x +#define HAS__builtin_popcount 1 +#define HAS__builtin_popcountll 1 +#else +#define __has_builtin(x) 0 +#endif +#endif + +/** + * MACRO for shuffle parameter for _mm_shuffle_ps(). + * Argument fp3 is a digit[0123] that represents the fp from argument "b" + * of mm_shuffle_ps that will be placed in fp3 of result. fp2 is the same + * for fp2 in result. fp1 is a digit[0123] that represents the fp from + * argument "a" of mm_shuffle_ps that will be places in fp1 of result. + * fp0 is the same for fp0 of result. + */ +#define _MM_SHUFFLE(fp3, fp2, fp1, fp0) \ + (((fp3) << 6) | ((fp2) << 4) | ((fp1) << 2) | ((fp0))) + +/* Rounding mode macros. */ +#define _MM_FROUND_TO_NEAREST_INT 0x00 +#define _MM_FROUND_TO_NEG_INF 0x01 +#define _MM_FROUND_TO_POS_INF 0x02 +#define _MM_FROUND_TO_ZERO 0x03 +#define _MM_FROUND_CUR_DIRECTION 0x04 +#define _MM_FROUND_NO_EXC 0x08 + +/* indicate immediate constant argument in a given range */ +#define __constrange(a, b) const + +/* A few intrinsics accept traditional data types like ints or floats, but + * most operate on data types that are specific to SSE. + * If a vector type ends in d, it contains doubles, and if it does not have + * a suffix, it contains floats. An integer vector type can contain any type + * of integer, from chars to shorts to unsigned long longs. + */ +typedef int64x1_t __m64; +typedef float32x4_t __m128; /* 128-bit vector containing 4 floats */ +// On ARM 32-bit architecture, the float64x2_t is not supported. +// The data type __m128d should be represented in a different way for related +// intrinsic conversion. +#if defined(__aarch64__) +typedef float64x2_t __m128d; /* 128-bit vector containing 2 doubles */ +#else +typedef float32x4_t __m128d; +#endif +typedef int64x2_t __m128i; /* 128-bit vector containing integers */ + +/* type-safe casting between types */ + +#define vreinterpretq_m128_f16(x) vreinterpretq_f32_f16(x) +#define vreinterpretq_m128_f32(x) (x) +#define vreinterpretq_m128_f64(x) vreinterpretq_f32_f64(x) + +#define vreinterpretq_m128_u8(x) vreinterpretq_f32_u8(x) +#define vreinterpretq_m128_u16(x) vreinterpretq_f32_u16(x) +#define vreinterpretq_m128_u32(x) vreinterpretq_f32_u32(x) +#define vreinterpretq_m128_u64(x) vreinterpretq_f32_u64(x) + +#define vreinterpretq_m128_s8(x) vreinterpretq_f32_s8(x) +#define vreinterpretq_m128_s16(x) vreinterpretq_f32_s16(x) +#define vreinterpretq_m128_s32(x) vreinterpretq_f32_s32(x) +#define vreinterpretq_m128_s64(x) vreinterpretq_f32_s64(x) + +#define vreinterpretq_f16_m128(x) vreinterpretq_f16_f32(x) +#define vreinterpretq_f32_m128(x) (x) +#define vreinterpretq_f64_m128(x) vreinterpretq_f64_f32(x) + +#define vreinterpretq_u8_m128(x) vreinterpretq_u8_f32(x) +#define vreinterpretq_u16_m128(x) vreinterpretq_u16_f32(x) +#define vreinterpretq_u32_m128(x) vreinterpretq_u32_f32(x) +#define vreinterpretq_u64_m128(x) vreinterpretq_u64_f32(x) + +#define vreinterpretq_s8_m128(x) vreinterpretq_s8_f32(x) +#define vreinterpretq_s16_m128(x) vreinterpretq_s16_f32(x) +#define vreinterpretq_s32_m128(x) vreinterpretq_s32_f32(x) +#define vreinterpretq_s64_m128(x) vreinterpretq_s64_f32(x) + +#define vreinterpretq_m128i_s8(x) vreinterpretq_s64_s8(x) +#define vreinterpretq_m128i_s16(x) vreinterpretq_s64_s16(x) +#define vreinterpretq_m128i_s32(x) vreinterpretq_s64_s32(x) +#define vreinterpretq_m128i_s64(x) (x) + +#define vreinterpretq_m128i_u8(x) vreinterpretq_s64_u8(x) +#define vreinterpretq_m128i_u16(x) vreinterpretq_s64_u16(x) +#define vreinterpretq_m128i_u32(x) vreinterpretq_s64_u32(x) +#define vreinterpretq_m128i_u64(x) vreinterpretq_s64_u64(x) + +#define vreinterpretq_s8_m128i(x) vreinterpretq_s8_s64(x) +#define vreinterpretq_s16_m128i(x) vreinterpretq_s16_s64(x) +#define vreinterpretq_s32_m128i(x) vreinterpretq_s32_s64(x) +#define vreinterpretq_s64_m128i(x) (x) + +#define vreinterpretq_u8_m128i(x) vreinterpretq_u8_s64(x) +#define vreinterpretq_u16_m128i(x) vreinterpretq_u16_s64(x) +#define vreinterpretq_u32_m128i(x) vreinterpretq_u32_s64(x) +#define vreinterpretq_u64_m128i(x) vreinterpretq_u64_s64(x) + +#define vreinterpret_m64_s8(x) vreinterpret_s64_s8(x) +#define vreinterpret_m64_s16(x) vreinterpret_s64_s16(x) +#define vreinterpret_m64_s32(x) vreinterpret_s64_s32(x) +#define vreinterpret_m64_s64(x) (x) + +#define vreinterpret_m64_u8(x) vreinterpret_s64_u8(x) +#define vreinterpret_m64_u16(x) vreinterpret_s64_u16(x) +#define vreinterpret_m64_u32(x) vreinterpret_s64_u32(x) +#define vreinterpret_m64_u64(x) vreinterpret_s64_u64(x) + +#define vreinterpret_m64_f16(x) vreinterpret_s64_f16(x) +#define vreinterpret_m64_f32(x) vreinterpret_s64_f32(x) +#define vreinterpret_m64_f64(x) vreinterpret_s64_f64(x) + +#define vreinterpret_u8_m64(x) vreinterpret_u8_s64(x) +#define vreinterpret_u16_m64(x) vreinterpret_u16_s64(x) +#define vreinterpret_u32_m64(x) vreinterpret_u32_s64(x) +#define vreinterpret_u64_m64(x) vreinterpret_u64_s64(x) + +#define vreinterpret_s8_m64(x) vreinterpret_s8_s64(x) +#define vreinterpret_s16_m64(x) vreinterpret_s16_s64(x) +#define vreinterpret_s32_m64(x) vreinterpret_s32_s64(x) +#define vreinterpret_s64_m64(x) (x) + +#define vreinterpret_f32_m64(x) vreinterpret_f32_s64(x) + +#if defined(__aarch64__) +#define vreinterpretq_m128d_s32(x) vreinterpretq_f64_s32(x) +#define vreinterpretq_m128d_s64(x) vreinterpretq_f64_s64(x) + +#define vreinterpretq_m128d_f64(x) (x) + +#define vreinterpretq_s64_m128d(x) vreinterpretq_s64_f64(x) + +#define vreinterpretq_f64_m128d(x) (x) +#else +#define vreinterpretq_m128d_s32(x) vreinterpretq_f32_s32(x) +#define vreinterpretq_m128d_s64(x) vreinterpretq_f32_s64(x) + +#define vreinterpretq_m128d_f32(x) (x) + +#define vreinterpretq_s64_m128d(x) vreinterpretq_s64_f32(x) + +#define vreinterpretq_f32_m128d(x) (x) +#endif + +// A struct is defined in this header file called 'SIMDVec' which can be used +// by applications which attempt to access the contents of an _m128 struct +// directly. It is important to note that accessing the __m128 struct directly +// is bad coding practice by Microsoft: @see: +// https://msdn.microsoft.com/en-us/library/ayeb3ayc.aspx +// +// However, some legacy source code may try to access the contents of an __m128 +// struct directly so the developer can use the SIMDVec as an alias for it. Any +// casting must be done manually by the developer, as you cannot cast or +// otherwise alias the base NEON data type for intrinsic operations. +// +// union intended to allow direct access to an __m128 variable using the names +// that the MSVC compiler provides. This union should really only be used when +// trying to access the members of the vector as integer values. GCC/clang +// allow native access to the float members through a simple array access +// operator (in C since 4.6, in C++ since 4.8). +// +// Ideally direct accesses to SIMD vectors should not be used since it can cause +// a performance hit. If it really is needed however, the original __m128 +// variable can be aliased with a pointer to this union and used to access +// individual components. The use of this union should be hidden behind a macro +// that is used throughout the codebase to access the members instead of always +// declaring this type of variable. +typedef union ALIGN_STRUCT(16) SIMDVec { + float m128_f32[4]; // as floats - DON'T USE. Added for convenience. + int8_t m128_i8[16]; // as signed 8-bit integers. + int16_t m128_i16[8]; // as signed 16-bit integers. + int32_t m128_i32[4]; // as signed 32-bit integers. + int64_t m128_i64[2]; // as signed 64-bit integers. + uint8_t m128_u8[16]; // as unsigned 8-bit integers. + uint16_t m128_u16[8]; // as unsigned 16-bit integers. + uint32_t m128_u32[4]; // as unsigned 32-bit integers. + uint64_t m128_u64[2]; // as unsigned 64-bit integers. +} SIMDVec; + +// casting using SIMDVec +#define vreinterpretq_nth_u64_m128i(x, n) (((SIMDVec *) &x)->m128_u64[n]) +#define vreinterpretq_nth_u32_m128i(x, n) (((SIMDVec *) &x)->m128_u32[n]) +#define vreinterpretq_nth_u8_m128i(x, n) (((SIMDVec *) &x)->m128_u8[n]) + +/* Backwards compatibility for compilers with lack of specific type support */ + +// Older gcc does not define vld1q_u8_x4 type +#if defined(__GNUC__) && !defined(__clang__) +#if __GNUC__ <= 9 +FORCE_INLINE uint8x16x4_t vld1q_u8_x4(const uint8_t *p) +{ + uint8x16x4_t ret; + ret.val[0] = vld1q_u8(p + 0); + ret.val[1] = vld1q_u8(p + 16); + ret.val[2] = vld1q_u8(p + 32); + ret.val[3] = vld1q_u8(p + 48); + return ret; +} +#endif +#endif + +/* Function Naming Conventions + * The naming convention of SSE intrinsics is straightforward. A generic SSE + * intrinsic function is given as follows: + * _mm__ + * + * The parts of this format are given as follows: + * 1. describes the operation performed by the intrinsic + * 2. identifies the data type of the function's primary arguments + * + * This last part, , is a little complicated. It identifies the + * content of the input values, and can be set to any of the following values: + * + ps - vectors contain floats (ps stands for packed single-precision) + * + pd - vectors cantain doubles (pd stands for packed double-precision) + * + epi8/epi16/epi32/epi64 - vectors contain 8-bit/16-bit/32-bit/64-bit + * signed integers + * + epu8/epu16/epu32/epu64 - vectors contain 8-bit/16-bit/32-bit/64-bit + * unsigned integers + * + si128 - unspecified 128-bit vector or 256-bit vector + * + m128/m128i/m128d - identifies input vector types when they are different + * than the type of the returned vector + * + * For example, _mm_setzero_ps. The _mm implies that the function returns + * a 128-bit vector. The _ps at the end implies that the argument vectors + * contain floats. + * + * A complete example: Byte Shuffle - pshufb (_mm_shuffle_epi8) + * // Set packed 16-bit integers. 128 bits, 8 short, per 16 bits + * __m128i v_in = _mm_setr_epi16(1, 2, 3, 4, 5, 6, 7, 8); + * // Set packed 8-bit integers + * // 128 bits, 16 chars, per 8 bits + * __m128i v_perm = _mm_setr_epi8(1, 0, 2, 3, 8, 9, 10, 11, + * 4, 5, 12, 13, 6, 7, 14, 15); + * // Shuffle packed 8-bit integers + * __m128i v_out = _mm_shuffle_epi8(v_in, v_perm); // pshufb + * + * Data (Number, Binary, Byte Index): + +------+------+-------------+------+------+-------------+ + | 1 | 2 | 3 | 4 | Number + +------+------+------+------+------+------+------+------+ + | 0000 | 0001 | 0000 | 0010 | 0000 | 0011 | 0000 | 0100 | Binary + +------+------+------+------+------+------+------+------+ + | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | Index + +------+------+------+------+------+------+------+------+ + + +------+------+------+------+------+------+------+------+ + | 5 | 6 | 7 | 8 | Number + +------+------+------+------+------+------+------+------+ + | 0000 | 0101 | 0000 | 0110 | 0000 | 0111 | 0000 | 1000 | Binary + +------+------+------+------+------+------+------+------+ + | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | Index + +------+------+------+------+------+------+------+------+ + * Index (Byte Index): + +------+------+------+------+------+------+------+------+ + | 1 | 0 | 2 | 3 | 8 | 9 | 10 | 11 | + +------+------+------+------+------+------+------+------+ + + +------+------+------+------+------+------+------+------+ + | 4 | 5 | 12 | 13 | 6 | 7 | 14 | 15 | + +------+------+------+------+------+------+------+------+ + * Result: + +------+------+------+------+------+------+------+------+ + | 1 | 0 | 2 | 3 | 8 | 9 | 10 | 11 | Index + +------+------+------+------+------+------+------+------+ + | 0001 | 0000 | 0000 | 0010 | 0000 | 0101 | 0000 | 0110 | Binary + +------+------+------+------+------+------+------+------+ + | 256 | 2 | 5 | 6 | Number + +------+------+------+------+------+------+------+------+ + + +------+------+------+------+------+------+------+------+ + | 4 | 5 | 12 | 13 | 6 | 7 | 14 | 15 | Index + +------+------+------+------+------+------+------+------+ + | 0000 | 0011 | 0000 | 0111 | 0000 | 0100 | 0000 | 1000 | Binary + +------+------+------+------+------+------+------+------+ + | 3 | 7 | 4 | 8 | Number + +------+------+------+------+------+------+-------------+ + */ + +/* Set/get methods */ + +/* Constants for use with _mm_prefetch. */ +enum _mm_hint { + _MM_HINT_NTA = 0, /* load data to L1 and L2 cache, mark it as NTA */ + _MM_HINT_T0 = 1, /* load data to L1 and L2 cache */ + _MM_HINT_T1 = 2, /* load data to L2 cache only */ + _MM_HINT_T2 = 3, /* load data to L2 cache only, mark it as NTA */ + _MM_HINT_ENTA = 4, /* exclusive version of _MM_HINT_NTA */ + _MM_HINT_ET0 = 5, /* exclusive version of _MM_HINT_T0 */ + _MM_HINT_ET1 = 6, /* exclusive version of _MM_HINT_T1 */ + _MM_HINT_ET2 = 7 /* exclusive version of _MM_HINT_T2 */ +}; + +// Loads one cache line of data from address p to a location closer to the +// processor. https://msdn.microsoft.com/en-us/library/84szxsww(v=vs.100).aspx +FORCE_INLINE void _mm_prefetch(const void *p, int i) +{ + (void) i; + __builtin_prefetch(p); +} + +// Copy the lower single-precision (32-bit) floating-point element of a to dst. +// +// dst[31:0] := a[31:0] +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtss_f32 +FORCE_INLINE float _mm_cvtss_f32(__m128 a) +{ + return vgetq_lane_f32(vreinterpretq_f32_m128(a), 0); +} + +// Convert the lower single-precision (32-bit) floating-point element in a to a +// 32-bit integer, and store the result in dst. +// +// dst[31:0] := Convert_FP32_To_Int32(a[31:0]) +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtss_si32 +#define _mm_cvtss_si32(a) _mm_cvt_ss2si(a) + +// Convert the lower single-precision (32-bit) floating-point element in a to a +// 64-bit integer, and store the result in dst. +// +// dst[63:0] := Convert_FP32_To_Int64(a[31:0]) +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtss_si64 +FORCE_INLINE int _mm_cvtss_si64(__m128 a) +{ +#if defined(__aarch64__) + return vgetq_lane_s64( + vreinterpretq_s64_s32(vcvtnq_s32_f32(vreinterpretq_f32_m128(a))), 0); +#else + float32_t data = vgetq_lane_f32(vreinterpretq_f32_m128(a), 0); + float32_t diff = data - floor(data); + if (diff > 0.5) + return (int64_t) ceil(data); + if (diff == 0.5) { + int64_t f = (int64_t) floor(data); + int64_t c = (int64_t) ceil(data); + return c & 1 ? f : c; + } + return (int64_t) floor(data); +#endif +} + +// Convert packed single-precision (32-bit) floating-point elements in a to +// packed 32-bit integers with truncation, and store the results in dst. +// +// FOR j := 0 to 1 +// i := 32*j +// dst[i+31:i] := Convert_FP32_To_Int32_Truncate(a[i+31:i]) +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtt_ps2pi +FORCE_INLINE __m64 _mm_cvtt_ps2pi(__m128 a) +{ + return vreinterpret_m64_s32( + vget_low_s32(vcvtq_s32_f32(vreinterpretq_f32_m128(a)))); +} + +// Convert the lower single-precision (32-bit) floating-point element in a to a +// 32-bit integer with truncation, and store the result in dst. +// +// dst[31:0] := Convert_FP32_To_Int32_Truncate(a[31:0]) +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtt_ss2si +FORCE_INLINE int _mm_cvtt_ss2si(__m128 a) +{ + return vgetq_lane_s32(vcvtq_s32_f32(vreinterpretq_f32_m128(a)), 0); +} + +// Convert packed single-precision (32-bit) floating-point elements in a to +// packed 32-bit integers with truncation, and store the results in dst. +// +// FOR j := 0 to 1 +// i := 32*j +// dst[i+31:i] := Convert_FP32_To_Int32_Truncate(a[i+31:i]) +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvttps_pi32 +#define _mm_cvttps_pi32(a) _mm_cvtt_ps2pi(a) + +// Convert the lower single-precision (32-bit) floating-point element in a to a +// 32-bit integer with truncation, and store the result in dst. +// +// dst[31:0] := Convert_FP32_To_Int32_Truncate(a[31:0]) +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvttss_si32 +#define _mm_cvttss_si32(a) _mm_cvtt_ss2si(a) + +// Convert the lower single-precision (32-bit) floating-point element in a to a +// 64-bit integer with truncation, and store the result in dst. +// +// dst[63:0] := Convert_FP32_To_Int64_Truncate(a[31:0]) +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvttss_si64 +FORCE_INLINE int64_t _mm_cvttss_si64(__m128 a) +{ + return vgetq_lane_s64( + vmovl_s32(vget_low_s32(vcvtq_s32_f32(vreinterpretq_f32_m128(a)))), 0); +} + +// Sets the 128-bit value to zero +// https://msdn.microsoft.com/en-us/library/vstudio/ys7dw0kh(v=vs.100).aspx +FORCE_INLINE __m128i _mm_setzero_si128(void) +{ + return vreinterpretq_m128i_s32(vdupq_n_s32(0)); +} + +// Clears the four single-precision, floating-point values. +// https://msdn.microsoft.com/en-us/library/vstudio/tk1t2tbz(v=vs.100).aspx +FORCE_INLINE __m128 _mm_setzero_ps(void) +{ + return vreinterpretq_m128_f32(vdupq_n_f32(0)); +} + +// Return vector of type __m128d with all elements set to zero. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_setzero_pd +FORCE_INLINE __m128d _mm_setzero_pd(void) +{ +#if defined(__aarch64__) + return vreinterpretq_m128d_f64(vdupq_n_f64(0)); +#else + return vreinterpretq_m128d_f32(vdupq_n_f32(0)); +#endif +} + +// Sets the four single-precision, floating-point values to w. +// +// r0 := r1 := r2 := r3 := w +// +// https://msdn.microsoft.com/en-us/library/vstudio/2x1se8ha(v=vs.100).aspx +FORCE_INLINE __m128 _mm_set1_ps(float _w) +{ + return vreinterpretq_m128_f32(vdupq_n_f32(_w)); +} + +// Sets the four single-precision, floating-point values to w. +// https://msdn.microsoft.com/en-us/library/vstudio/2x1se8ha(v=vs.100).aspx +FORCE_INLINE __m128 _mm_set_ps1(float _w) +{ + return vreinterpretq_m128_f32(vdupq_n_f32(_w)); +} + +// Sets the four single-precision, floating-point values to the four inputs. +// https://msdn.microsoft.com/en-us/library/vstudio/afh0zf75(v=vs.100).aspx +FORCE_INLINE __m128 _mm_set_ps(float w, float z, float y, float x) +{ + float ALIGN_STRUCT(16) data[4] = {x, y, z, w}; + return vreinterpretq_m128_f32(vld1q_f32(data)); +} + +// Copy single-precision (32-bit) floating-point element a to the lower element +// of dst, and zero the upper 3 elements. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_set_ss +FORCE_INLINE __m128 _mm_set_ss(float a) +{ + float ALIGN_STRUCT(16) data[4] = {a, 0, 0, 0}; + return vreinterpretq_m128_f32(vld1q_f32(data)); +} + +// Sets the four single-precision, floating-point values to the four inputs in +// reverse order. +// https://msdn.microsoft.com/en-us/library/vstudio/d2172ct3(v=vs.100).aspx +FORCE_INLINE __m128 _mm_setr_ps(float w, float z, float y, float x) +{ + float ALIGN_STRUCT(16) data[4] = {w, z, y, x}; + return vreinterpretq_m128_f32(vld1q_f32(data)); +} + +// Sets the 8 signed 16-bit integer values in reverse order. +// +// Return Value +// r0 := w0 +// r1 := w1 +// ... +// r7 := w7 +FORCE_INLINE __m128i _mm_setr_epi16(short w0, + short w1, + short w2, + short w3, + short w4, + short w5, + short w6, + short w7) +{ + int16_t ALIGN_STRUCT(16) data[8] = {w0, w1, w2, w3, w4, w5, w6, w7}; + return vreinterpretq_m128i_s16(vld1q_s16((int16_t *) data)); +} + +// Sets the 4 signed 32-bit integer values in reverse order +// https://technet.microsoft.com/en-us/library/security/27yb3ee5(v=vs.90).aspx +FORCE_INLINE __m128i _mm_setr_epi32(int i3, int i2, int i1, int i0) +{ + int32_t ALIGN_STRUCT(16) data[4] = {i3, i2, i1, i0}; + return vreinterpretq_m128i_s32(vld1q_s32(data)); +} + +// Set packed 64-bit integers in dst with the supplied values in reverse order. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_setr_epi64 +FORCE_INLINE __m128i _mm_setr_epi64(__m64 e1, __m64 e0) +{ + return vreinterpretq_m128i_s64(vcombine_s64(e1, e0)); +} + +// Sets the 16 signed 8-bit integer values to b. +// +// r0 := b +// r1 := b +// ... +// r15 := b +// +// https://msdn.microsoft.com/en-us/library/6e14xhyf(v=vs.100).aspx +FORCE_INLINE __m128i _mm_set1_epi8(signed char w) +{ + return vreinterpretq_m128i_s8(vdupq_n_s8(w)); +} + +// Sets the 8 signed 16-bit integer values to w. +// +// r0 := w +// r1 := w +// ... +// r7 := w +// +// https://msdn.microsoft.com/en-us/library/k0ya3x0e(v=vs.90).aspx +FORCE_INLINE __m128i _mm_set1_epi16(short w) +{ + return vreinterpretq_m128i_s16(vdupq_n_s16(w)); +} + +// Sets the 16 signed 8-bit integer values. +// https://msdn.microsoft.com/en-us/library/x0cx8zd3(v=vs.90).aspx +FORCE_INLINE __m128i _mm_set_epi8(signed char b15, + signed char b14, + signed char b13, + signed char b12, + signed char b11, + signed char b10, + signed char b9, + signed char b8, + signed char b7, + signed char b6, + signed char b5, + signed char b4, + signed char b3, + signed char b2, + signed char b1, + signed char b0) +{ + int8_t ALIGN_STRUCT(16) + data[16] = {(int8_t) b0, (int8_t) b1, (int8_t) b2, (int8_t) b3, + (int8_t) b4, (int8_t) b5, (int8_t) b6, (int8_t) b7, + (int8_t) b8, (int8_t) b9, (int8_t) b10, (int8_t) b11, + (int8_t) b12, (int8_t) b13, (int8_t) b14, (int8_t) b15}; + return (__m128i) vld1q_s8(data); +} + +// Sets the 8 signed 16-bit integer values. +// https://msdn.microsoft.com/en-au/library/3e0fek84(v=vs.90).aspx +FORCE_INLINE __m128i _mm_set_epi16(short i7, + short i6, + short i5, + short i4, + short i3, + short i2, + short i1, + short i0) +{ + int16_t ALIGN_STRUCT(16) data[8] = {i0, i1, i2, i3, i4, i5, i6, i7}; + return vreinterpretq_m128i_s16(vld1q_s16(data)); +} + +// Sets the 16 signed 8-bit integer values in reverse order. +// https://msdn.microsoft.com/en-us/library/2khb9c7k(v=vs.90).aspx +FORCE_INLINE __m128i _mm_setr_epi8(signed char b0, + signed char b1, + signed char b2, + signed char b3, + signed char b4, + signed char b5, + signed char b6, + signed char b7, + signed char b8, + signed char b9, + signed char b10, + signed char b11, + signed char b12, + signed char b13, + signed char b14, + signed char b15) +{ + int8_t ALIGN_STRUCT(16) + data[16] = {(int8_t) b0, (int8_t) b1, (int8_t) b2, (int8_t) b3, + (int8_t) b4, (int8_t) b5, (int8_t) b6, (int8_t) b7, + (int8_t) b8, (int8_t) b9, (int8_t) b10, (int8_t) b11, + (int8_t) b12, (int8_t) b13, (int8_t) b14, (int8_t) b15}; + return (__m128i) vld1q_s8(data); +} + +// Sets the 4 signed 32-bit integer values to i. +// +// r0 := i +// r1 := i +// r2 := i +// r3 := I +// +// https://msdn.microsoft.com/en-us/library/vstudio/h4xscxat(v=vs.100).aspx +FORCE_INLINE __m128i _mm_set1_epi32(int _i) +{ + return vreinterpretq_m128i_s32(vdupq_n_s32(_i)); +} + +// Sets the 2 signed 64-bit integer values to i. +// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/whtfzhzk(v=vs.100) +FORCE_INLINE __m128i _mm_set1_epi64(__m64 _i) +{ + return vreinterpretq_m128i_s64(vdupq_n_s64((int64_t) _i)); +} + +// Sets the 2 signed 64-bit integer values to i. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_set1_epi64x +FORCE_INLINE __m128i _mm_set1_epi64x(int64_t _i) +{ + return vreinterpretq_m128i_s64(vdupq_n_s64(_i)); +} + +// Sets the 4 signed 32-bit integer values. +// https://msdn.microsoft.com/en-us/library/vstudio/019beekt(v=vs.100).aspx +FORCE_INLINE __m128i _mm_set_epi32(int i3, int i2, int i1, int i0) +{ + int32_t ALIGN_STRUCT(16) data[4] = {i0, i1, i2, i3}; + return vreinterpretq_m128i_s32(vld1q_s32(data)); +} + +// Returns the __m128i structure with its two 64-bit integer values +// initialized to the values of the two 64-bit integers passed in. +// https://msdn.microsoft.com/en-us/library/dk2sdw0h(v=vs.120).aspx +FORCE_INLINE __m128i _mm_set_epi64x(int64_t i1, int64_t i2) +{ + int64_t ALIGN_STRUCT(16) data[2] = {i2, i1}; + return vreinterpretq_m128i_s64(vld1q_s64(data)); +} + +// Returns the __m128i structure with its two 64-bit integer values +// initialized to the values of the two 64-bit integers passed in. +// https://msdn.microsoft.com/en-us/library/dk2sdw0h(v=vs.120).aspx +FORCE_INLINE __m128i _mm_set_epi64(__m64 i1, __m64 i2) +{ + return _mm_set_epi64x((int64_t) i1, (int64_t) i2); +} + +// Set packed double-precision (64-bit) floating-point elements in dst with the +// supplied values. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_set_pd +FORCE_INLINE __m128d _mm_set_pd(double e1, double e0) +{ + double ALIGN_STRUCT(16) data[2] = {e0, e1}; +#if defined(__aarch64__) + return vreinterpretq_m128d_f64(vld1q_f64((float64_t *) data)); +#else + return vreinterpretq_m128d_f32(vld1q_f32((float32_t *) data)); +#endif +} + +// Stores four single-precision, floating-point values. +// https://msdn.microsoft.com/en-us/library/vstudio/s3h4ay6y(v=vs.100).aspx +FORCE_INLINE void _mm_store_ps(float *p, __m128 a) +{ + vst1q_f32(p, vreinterpretq_f32_m128(a)); +} + +// Stores four single-precision, floating-point values. +// https://msdn.microsoft.com/en-us/library/44e30x22(v=vs.100).aspx +FORCE_INLINE void _mm_storeu_ps(float *p, __m128 a) +{ + vst1q_f32(p, vreinterpretq_f32_m128(a)); +} + +// Stores four 32-bit integer values as (as a __m128i value) at the address p. +// https://msdn.microsoft.com/en-us/library/vstudio/edk11s13(v=vs.100).aspx +FORCE_INLINE void _mm_store_si128(__m128i *p, __m128i a) +{ + vst1q_s32((int32_t *) p, vreinterpretq_s32_m128i(a)); +} + +// Stores four 32-bit integer values as (as a __m128i value) at the address p. +// https://msdn.microsoft.com/en-us/library/vstudio/edk11s13(v=vs.100).aspx +FORCE_INLINE void _mm_storeu_si128(__m128i *p, __m128i a) +{ + vst1q_s32((int32_t *) p, vreinterpretq_s32_m128i(a)); +} + +// Stores the lower single - precision, floating - point value. +// https://msdn.microsoft.com/en-us/library/tzz10fbx(v=vs.100).aspx +FORCE_INLINE void _mm_store_ss(float *p, __m128 a) +{ + vst1q_lane_f32(p, vreinterpretq_f32_m128(a), 0); +} + +// Store 128-bits (composed of 2 packed double-precision (64-bit) floating-point +// elements) from a into memory. mem_addr must be aligned on a 16-byte boundary +// or a general-protection exception may be generated. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_store_pd +FORCE_INLINE void _mm_store_pd(double *mem_addr, __m128d a) +{ +#if defined(__aarch64__) + vst1q_f64((float64_t *) mem_addr, vreinterpretq_f64_m128d(a)); +#else + vst1q_f32((float32_t *) mem_addr, vreinterpretq_f32_m128d(a)); +#endif +} + +// Store 128-bits (composed of 2 packed double-precision (64-bit) floating-point +// elements) from a into memory. mem_addr does not need to be aligned on any +// particular boundary. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_storeu_pd +FORCE_INLINE void _mm_storeu_pd(double *mem_addr, __m128d a) +{ + _mm_store_pd(mem_addr, a); +} + +// Reads the lower 64 bits of b and stores them into the lower 64 bits of a. +// https://msdn.microsoft.com/en-us/library/hhwf428f%28v=vs.90%29.aspx +FORCE_INLINE void _mm_storel_epi64(__m128i *a, __m128i b) +{ + uint64x1_t hi = vget_high_u64(vreinterpretq_u64_m128i(*a)); + uint64x1_t lo = vget_low_u64(vreinterpretq_u64_m128i(b)); + *a = vreinterpretq_m128i_u64(vcombine_u64(lo, hi)); +} + +// Stores the lower two single-precision floating point values of a to the +// address p. +// +// *p0 := a0 +// *p1 := a1 +// +// https://msdn.microsoft.com/en-us/library/h54t98ks(v=vs.90).aspx +FORCE_INLINE void _mm_storel_pi(__m64 *p, __m128 a) +{ + *p = vreinterpret_m64_f32(vget_low_f32(a)); +} + +// Stores the upper two single-precision, floating-point values of a to the +// address p. +// +// *p0 := a2 +// *p1 := a3 +// +// https://msdn.microsoft.com/en-us/library/a7525fs8(v%3dvs.90).aspx +FORCE_INLINE void _mm_storeh_pi(__m64 *p, __m128 a) +{ + *p = vreinterpret_m64_f32(vget_high_f32(a)); +} + +// Loads a single single-precision, floating-point value, copying it into all +// four words +// https://msdn.microsoft.com/en-us/library/vstudio/5cdkf716(v=vs.100).aspx +FORCE_INLINE __m128 _mm_load1_ps(const float *p) +{ + return vreinterpretq_m128_f32(vld1q_dup_f32(p)); +} + +// Load a single-precision (32-bit) floating-point element from memory into all +// elements of dst. +// +// dst[31:0] := MEM[mem_addr+31:mem_addr] +// dst[63:32] := MEM[mem_addr+31:mem_addr] +// dst[95:64] := MEM[mem_addr+31:mem_addr] +// dst[127:96] := MEM[mem_addr+31:mem_addr] +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_load_ps1 +#define _mm_load_ps1 _mm_load1_ps + +// Sets the lower two single-precision, floating-point values with 64 +// bits of data loaded from the address p; the upper two values are passed +// through from a. +// +// Return Value +// r0 := *p0 +// r1 := *p1 +// r2 := a2 +// r3 := a3 +// +// https://msdn.microsoft.com/en-us/library/s57cyak2(v=vs.100).aspx +FORCE_INLINE __m128 _mm_loadl_pi(__m128 a, __m64 const *p) +{ + return vreinterpretq_m128_f32( + vcombine_f32(vld1_f32((const float32_t *) p), vget_high_f32(a))); +} + +// Load 4 single-precision (32-bit) floating-point elements from memory into dst +// in reverse order. mem_addr must be aligned on a 16-byte boundary or a +// general-protection exception may be generated. +// +// dst[31:0] := MEM[mem_addr+127:mem_addr+96] +// dst[63:32] := MEM[mem_addr+95:mem_addr+64] +// dst[95:64] := MEM[mem_addr+63:mem_addr+32] +// dst[127:96] := MEM[mem_addr+31:mem_addr] +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_loadr_ps +FORCE_INLINE __m128 _mm_loadr_ps(const float *p) +{ + float32x4_t v = vrev64q_f32(vld1q_f32(p)); + return vreinterpretq_m128_f32(vextq_f32(v, v, 2)); +} + +// Sets the upper two single-precision, floating-point values with 64 +// bits of data loaded from the address p; the lower two values are passed +// through from a. +// +// r0 := a0 +// r1 := a1 +// r2 := *p0 +// r3 := *p1 +// +// https://msdn.microsoft.com/en-us/library/w92wta0x(v%3dvs.100).aspx +FORCE_INLINE __m128 _mm_loadh_pi(__m128 a, __m64 const *p) +{ + return vreinterpretq_m128_f32( + vcombine_f32(vget_low_f32(a), vld1_f32((const float32_t *) p))); +} + +// Loads four single-precision, floating-point values. +// https://msdn.microsoft.com/en-us/library/vstudio/zzd50xxt(v=vs.100).aspx +FORCE_INLINE __m128 _mm_load_ps(const float *p) +{ + return vreinterpretq_m128_f32(vld1q_f32(p)); +} + +// Loads four single-precision, floating-point values. +// https://msdn.microsoft.com/en-us/library/x1b16s7z%28v=vs.90%29.aspx +FORCE_INLINE __m128 _mm_loadu_ps(const float *p) +{ + // for neon, alignment doesn't matter, so _mm_load_ps and _mm_loadu_ps are + // equivalent for neon + return vreinterpretq_m128_f32(vld1q_f32(p)); +} + +// Load unaligned 16-bit integer from memory into the first element of dst. +// +// dst[15:0] := MEM[mem_addr+15:mem_addr] +// dst[MAX:16] := 0 +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_loadu_si16 +FORCE_INLINE __m128i _mm_loadu_si16(const void *p) +{ + return vreinterpretq_m128i_s16( + vsetq_lane_s16(*(const int16_t *) p, vdupq_n_s16(0), 0)); +} + +// Load unaligned 64-bit integer from memory into the first element of dst. +// +// dst[63:0] := MEM[mem_addr+63:mem_addr] +// dst[MAX:64] := 0 +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_loadu_si64 +FORCE_INLINE __m128i _mm_loadu_si64(const void *p) +{ + return vreinterpretq_m128i_s64( + vcombine_s64(vld1_s64((const int64_t *) p), vdup_n_s64(0))); +} + +// Load a double-precision (64-bit) floating-point element from memory into the +// lower of dst, and zero the upper element. mem_addr does not need to be +// aligned on any particular boundary. +// +// dst[63:0] := MEM[mem_addr+63:mem_addr] +// dst[127:64] := 0 +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_load_sd +FORCE_INLINE __m128d _mm_load_sd(const double *p) +{ +#if defined(__aarch64__) + return vreinterpretq_m128d_f64(vsetq_lane_f64(*p, vdupq_n_f64(0), 0)); +#else + const float *fp = (const float *) p; + float ALIGN_STRUCT(16) data[4] = {fp[0], fp[1], 0, 0}; + return vreinterpretq_m128d_f32(vld1q_f32(data)); +#endif +} + +// Loads two double-precision from 16-byte aligned memory, floating-point +// values. +// +// dst[127:0] := MEM[mem_addr+127:mem_addr] +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_load_pd +FORCE_INLINE __m128d _mm_load_pd(const double *p) +{ +#if defined(__aarch64__) + return vreinterpretq_m128d_f64(vld1q_f64(p)); +#else + const float *fp = (const float *) p; + float ALIGN_STRUCT(16) data[4] = {fp[0], fp[1], fp[2], fp[3]}; + return vreinterpretq_m128d_f32(vld1q_f32(data)); +#endif +} + +// Loads two double-precision from unaligned memory, floating-point values. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_loadu_pd +FORCE_INLINE __m128d _mm_loadu_pd(const double *p) +{ + return _mm_load_pd(p); +} + +// Loads an single - precision, floating - point value into the low word and +// clears the upper three words. +// https://msdn.microsoft.com/en-us/library/548bb9h4%28v=vs.90%29.aspx +FORCE_INLINE __m128 _mm_load_ss(const float *p) +{ + return vreinterpretq_m128_f32(vsetq_lane_f32(*p, vdupq_n_f32(0), 0)); +} + +FORCE_INLINE __m128i _mm_loadl_epi64(__m128i const *p) +{ + /* Load the lower 64 bits of the value pointed to by p into the + * lower 64 bits of the result, zeroing the upper 64 bits of the result. + */ + return vreinterpretq_m128i_s32( + vcombine_s32(vld1_s32((int32_t const *) p), vcreate_s32(0))); +} + +// Load a double-precision (64-bit) floating-point element from memory into the +// lower element of dst, and copy the upper element from a to dst. mem_addr does +// not need to be aligned on any particular boundary. +// +// dst[63:0] := MEM[mem_addr+63:mem_addr] +// dst[127:64] := a[127:64] +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_loadl_pd +FORCE_INLINE __m128d _mm_loadl_pd(__m128d a, const double *p) +{ +#if defined(__aarch64__) + return vreinterpretq_m128d_f64( + vcombine_f64(vld1_f64(p), vget_high_f64(vreinterpretq_f64_m128d(a)))); +#else + return vreinterpretq_m128d_f32( + vcombine_f32(vld1_f32((const float *) p), + vget_high_f32(vreinterpretq_f32_m128d(a)))); +#endif +} + +// Load 2 double-precision (64-bit) floating-point elements from memory into dst +// in reverse order. mem_addr must be aligned on a 16-byte boundary or a +// general-protection exception may be generated. +// +// dst[63:0] := MEM[mem_addr+127:mem_addr+64] +// dst[127:64] := MEM[mem_addr+63:mem_addr] +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_loadr_pd +FORCE_INLINE __m128d _mm_loadr_pd(const double *p) +{ +#if defined(__aarch64__) + float64x2_t v = vld1q_f64(p); + return vreinterpretq_m128d_f64(vextq_f64(v, v, 1)); +#else + int64x2_t v = vld1q_s64((const int64_t *) p); + return vreinterpretq_m128d_s64(vextq_s64(v, v, 1)); +#endif +} + +// Sets the low word to the single-precision, floating-point value of b +// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/35hdzazd(v=vs.100) +FORCE_INLINE __m128 _mm_move_ss(__m128 a, __m128 b) +{ + return vreinterpretq_m128_f32( + vsetq_lane_f32(vgetq_lane_f32(vreinterpretq_f32_m128(b), 0), + vreinterpretq_f32_m128(a), 0)); +} + +// Copy the lower 64-bit integer in a to the lower element of dst, and zero the +// upper element. +// +// dst[63:0] := a[63:0] +// dst[127:64] := 0 +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_move_epi64 +FORCE_INLINE __m128i _mm_move_epi64(__m128i a) +{ + return vreinterpretq_m128i_s64( + vsetq_lane_s64(0, vreinterpretq_s64_m128i(a), 1)); +} + +// Return vector of type __m128 with undefined elements. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_undefined_ps +FORCE_INLINE __m128 _mm_undefined_ps(void) +{ + __m128 a; + return a; +} + +/* Logic/Binary operations */ + +// Computes the bitwise AND-NOT of the four single-precision, floating-point +// values of a and b. +// +// r0 := ~a0 & b0 +// r1 := ~a1 & b1 +// r2 := ~a2 & b2 +// r3 := ~a3 & b3 +// +// https://msdn.microsoft.com/en-us/library/vstudio/68h7wd02(v=vs.100).aspx +FORCE_INLINE __m128 _mm_andnot_ps(__m128 a, __m128 b) +{ + return vreinterpretq_m128_s32( + vbicq_s32(vreinterpretq_s32_m128(b), + vreinterpretq_s32_m128(a))); // *NOTE* argument swap +} + +// Compute the bitwise NOT of packed double-precision (64-bit) floating-point +// elements in a and then AND with b, and store the results in dst. +// +// FOR j := 0 to 1 +// i := j*64 +// dst[i+63:i] := ((NOT a[i+63:i]) AND b[i+63:i]) +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_andnot_pd +FORCE_INLINE __m128d _mm_andnot_pd(__m128d a, __m128d b) +{ + // *NOTE* argument swap + return vreinterpretq_m128d_s64( + vbicq_s64(vreinterpretq_s64_m128d(b), vreinterpretq_s64_m128d(a))); +} + +// Computes the bitwise AND of the 128-bit value in b and the bitwise NOT of the +// 128-bit value in a. +// +// r := (~a) & b +// +// https://msdn.microsoft.com/en-us/library/vstudio/1beaceh8(v=vs.100).aspx +FORCE_INLINE __m128i _mm_andnot_si128(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_s32( + vbicq_s32(vreinterpretq_s32_m128i(b), + vreinterpretq_s32_m128i(a))); // *NOTE* argument swap +} + +// Computes the bitwise AND of the 128-bit value in a and the 128-bit value in +// b. +// +// r := a & b +// +// https://msdn.microsoft.com/en-us/library/vstudio/6d1txsa8(v=vs.100).aspx +FORCE_INLINE __m128i _mm_and_si128(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_s32( + vandq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b))); +} + +// Computes the bitwise AND of the four single-precision, floating-point values +// of a and b. +// +// r0 := a0 & b0 +// r1 := a1 & b1 +// r2 := a2 & b2 +// r3 := a3 & b3 +// +// https://msdn.microsoft.com/en-us/library/vstudio/73ck1xc5(v=vs.100).aspx +FORCE_INLINE __m128 _mm_and_ps(__m128 a, __m128 b) +{ + return vreinterpretq_m128_s32( + vandq_s32(vreinterpretq_s32_m128(a), vreinterpretq_s32_m128(b))); +} + +// Compute the bitwise AND of packed double-precision (64-bit) floating-point +// elements in a and b, and store the results in dst. +// +// FOR j := 0 to 1 +// i := j*64 +// dst[i+63:i] := a[i+63:i] AND b[i+63:i] +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_and_pd +FORCE_INLINE __m128d _mm_and_pd(__m128d a, __m128d b) +{ + return vreinterpretq_m128d_s64( + vandq_s64(vreinterpretq_s64_m128d(a), vreinterpretq_s64_m128d(b))); +} + +// Computes the bitwise OR of the four single-precision, floating-point values +// of a and b. +// https://msdn.microsoft.com/en-us/library/vstudio/7ctdsyy0(v=vs.100).aspx +FORCE_INLINE __m128 _mm_or_ps(__m128 a, __m128 b) +{ + return vreinterpretq_m128_s32( + vorrq_s32(vreinterpretq_s32_m128(a), vreinterpretq_s32_m128(b))); +} + +// Computes bitwise EXOR (exclusive-or) of the four single-precision, +// floating-point values of a and b. +// https://msdn.microsoft.com/en-us/library/ss6k3wk8(v=vs.100).aspx +FORCE_INLINE __m128 _mm_xor_ps(__m128 a, __m128 b) +{ + return vreinterpretq_m128_s32( + veorq_s32(vreinterpretq_s32_m128(a), vreinterpretq_s32_m128(b))); +} + +// Compute the bitwise XOR of packed double-precision (64-bit) floating-point +// elements in a and b, and store the results in dst. +// +// FOR j := 0 to 1 +// i := j*64 +// dst[i+63:i] := a[i+63:i] XOR b[i+63:i] +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_xor_pd +FORCE_INLINE __m128d _mm_xor_pd(__m128d a, __m128d b) +{ + return vreinterpretq_m128d_s64( + veorq_s64(vreinterpretq_s64_m128d(a), vreinterpretq_s64_m128d(b))); +} + +// Computes the bitwise OR of the 128-bit value in a and the 128-bit value in b. +// +// r := a | b +// +// https://msdn.microsoft.com/en-us/library/vstudio/ew8ty0db(v=vs.100).aspx +FORCE_INLINE __m128i _mm_or_si128(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_s32( + vorrq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b))); +} + +// Computes the bitwise XOR of the 128-bit value in a and the 128-bit value in +// b. https://msdn.microsoft.com/en-us/library/fzt08www(v=vs.100).aspx +FORCE_INLINE __m128i _mm_xor_si128(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_s32( + veorq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b))); +} + +// Duplicate odd-indexed single-precision (32-bit) floating-point elements +// from a, and store the results in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_movehdup_ps +FORCE_INLINE __m128 _mm_movehdup_ps(__m128 a) +{ +#if __has_builtin(__builtin_shufflevector) + return vreinterpretq_m128_f32(__builtin_shufflevector( + vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(a), 1, 1, 3, 3)); +#else + float32_t a1 = vgetq_lane_f32(vreinterpretq_f32_m128(a), 1); + float32_t a3 = vgetq_lane_f32(vreinterpretq_f32_m128(a), 3); + float ALIGN_STRUCT(16) data[4] = {a1, a1, a3, a3}; + return vreinterpretq_m128_f32(vld1q_f32(data)); +#endif +} + +// Duplicate even-indexed single-precision (32-bit) floating-point elements +// from a, and store the results in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_moveldup_ps +FORCE_INLINE __m128 _mm_moveldup_ps(__m128 a) +{ +#if __has_builtin(__builtin_shufflevector) + return vreinterpretq_m128_f32(__builtin_shufflevector( + vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(a), 0, 0, 2, 2)); +#else + float32_t a0 = vgetq_lane_f32(vreinterpretq_f32_m128(a), 0); + float32_t a2 = vgetq_lane_f32(vreinterpretq_f32_m128(a), 2); + float ALIGN_STRUCT(16) data[4] = {a0, a0, a2, a2}; + return vreinterpretq_m128_f32(vld1q_f32(data)); +#endif +} + +// Moves the upper two values of B into the lower two values of A. +// +// r3 := a3 +// r2 := a2 +// r1 := b3 +// r0 := b2 +FORCE_INLINE __m128 _mm_movehl_ps(__m128 __A, __m128 __B) +{ + float32x2_t a32 = vget_high_f32(vreinterpretq_f32_m128(__A)); + float32x2_t b32 = vget_high_f32(vreinterpretq_f32_m128(__B)); + return vreinterpretq_m128_f32(vcombine_f32(b32, a32)); +} + +// Moves the lower two values of B into the upper two values of A. +// +// r3 := b1 +// r2 := b0 +// r1 := a1 +// r0 := a0 +FORCE_INLINE __m128 _mm_movelh_ps(__m128 __A, __m128 __B) +{ + float32x2_t a10 = vget_low_f32(vreinterpretq_f32_m128(__A)); + float32x2_t b10 = vget_low_f32(vreinterpretq_f32_m128(__B)); + return vreinterpretq_m128_f32(vcombine_f32(a10, b10)); +} + +// Compute the absolute value of packed signed 32-bit integers in a, and store +// the unsigned results in dst. +// +// FOR j := 0 to 3 +// i := j*32 +// dst[i+31:i] := ABS(a[i+31:i]) +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_abs_epi32 +FORCE_INLINE __m128i _mm_abs_epi32(__m128i a) +{ + return vreinterpretq_m128i_s32(vabsq_s32(vreinterpretq_s32_m128i(a))); +} + +// Compute the absolute value of packed signed 16-bit integers in a, and store +// the unsigned results in dst. +// +// FOR j := 0 to 7 +// i := j*16 +// dst[i+15:i] := ABS(a[i+15:i]) +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_abs_epi16 +FORCE_INLINE __m128i _mm_abs_epi16(__m128i a) +{ + return vreinterpretq_m128i_s16(vabsq_s16(vreinterpretq_s16_m128i(a))); +} + +// Compute the absolute value of packed signed 8-bit integers in a, and store +// the unsigned results in dst. +// +// FOR j := 0 to 15 +// i := j*8 +// dst[i+7:i] := ABS(a[i+7:i]) +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_abs_epi8 +FORCE_INLINE __m128i _mm_abs_epi8(__m128i a) +{ + return vreinterpretq_m128i_s8(vabsq_s8(vreinterpretq_s8_m128i(a))); +} + +// Compute the absolute value of packed signed 32-bit integers in a, and store +// the unsigned results in dst. +// +// FOR j := 0 to 1 +// i := j*32 +// dst[i+31:i] := ABS(a[i+31:i]) +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_abs_pi32 +FORCE_INLINE __m64 _mm_abs_pi32(__m64 a) +{ + return vreinterpret_m64_s32(vabs_s32(vreinterpret_s32_m64(a))); +} + +// Compute the absolute value of packed signed 16-bit integers in a, and store +// the unsigned results in dst. +// +// FOR j := 0 to 3 +// i := j*16 +// dst[i+15:i] := ABS(a[i+15:i]) +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_abs_pi16 +FORCE_INLINE __m64 _mm_abs_pi16(__m64 a) +{ + return vreinterpret_m64_s16(vabs_s16(vreinterpret_s16_m64(a))); +} + +// Compute the absolute value of packed signed 8-bit integers in a, and store +// the unsigned results in dst. +// +// FOR j := 0 to 7 +// i := j*8 +// dst[i+7:i] := ABS(a[i+7:i]) +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_abs_pi8 +FORCE_INLINE __m64 _mm_abs_pi8(__m64 a) +{ + return vreinterpret_m64_s8(vabs_s8(vreinterpret_s8_m64(a))); +} + +// Takes the upper 64 bits of a and places it in the low end of the result +// Takes the lower 64 bits of b and places it into the high end of the result. +FORCE_INLINE __m128 _mm_shuffle_ps_1032(__m128 a, __m128 b) +{ + float32x2_t a32 = vget_high_f32(vreinterpretq_f32_m128(a)); + float32x2_t b10 = vget_low_f32(vreinterpretq_f32_m128(b)); + return vreinterpretq_m128_f32(vcombine_f32(a32, b10)); +} + +// takes the lower two 32-bit values from a and swaps them and places in high +// end of result takes the higher two 32 bit values from b and swaps them and +// places in low end of result. +FORCE_INLINE __m128 _mm_shuffle_ps_2301(__m128 a, __m128 b) +{ + float32x2_t a01 = vrev64_f32(vget_low_f32(vreinterpretq_f32_m128(a))); + float32x2_t b23 = vrev64_f32(vget_high_f32(vreinterpretq_f32_m128(b))); + return vreinterpretq_m128_f32(vcombine_f32(a01, b23)); +} + +FORCE_INLINE __m128 _mm_shuffle_ps_0321(__m128 a, __m128 b) +{ + float32x2_t a21 = vget_high_f32( + vextq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(a), 3)); + float32x2_t b03 = vget_low_f32( + vextq_f32(vreinterpretq_f32_m128(b), vreinterpretq_f32_m128(b), 3)); + return vreinterpretq_m128_f32(vcombine_f32(a21, b03)); +} + +FORCE_INLINE __m128 _mm_shuffle_ps_2103(__m128 a, __m128 b) +{ + float32x2_t a03 = vget_low_f32( + vextq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(a), 3)); + float32x2_t b21 = vget_high_f32( + vextq_f32(vreinterpretq_f32_m128(b), vreinterpretq_f32_m128(b), 3)); + return vreinterpretq_m128_f32(vcombine_f32(a03, b21)); +} + +FORCE_INLINE __m128 _mm_shuffle_ps_1010(__m128 a, __m128 b) +{ + float32x2_t a10 = vget_low_f32(vreinterpretq_f32_m128(a)); + float32x2_t b10 = vget_low_f32(vreinterpretq_f32_m128(b)); + return vreinterpretq_m128_f32(vcombine_f32(a10, b10)); +} + +FORCE_INLINE __m128 _mm_shuffle_ps_1001(__m128 a, __m128 b) +{ + float32x2_t a01 = vrev64_f32(vget_low_f32(vreinterpretq_f32_m128(a))); + float32x2_t b10 = vget_low_f32(vreinterpretq_f32_m128(b)); + return vreinterpretq_m128_f32(vcombine_f32(a01, b10)); +} + +FORCE_INLINE __m128 _mm_shuffle_ps_0101(__m128 a, __m128 b) +{ + float32x2_t a01 = vrev64_f32(vget_low_f32(vreinterpretq_f32_m128(a))); + float32x2_t b01 = vrev64_f32(vget_low_f32(vreinterpretq_f32_m128(b))); + return vreinterpretq_m128_f32(vcombine_f32(a01, b01)); +} + +// keeps the low 64 bits of b in the low and puts the high 64 bits of a in the +// high +FORCE_INLINE __m128 _mm_shuffle_ps_3210(__m128 a, __m128 b) +{ + float32x2_t a10 = vget_low_f32(vreinterpretq_f32_m128(a)); + float32x2_t b32 = vget_high_f32(vreinterpretq_f32_m128(b)); + return vreinterpretq_m128_f32(vcombine_f32(a10, b32)); +} + +FORCE_INLINE __m128 _mm_shuffle_ps_0011(__m128 a, __m128 b) +{ + float32x2_t a11 = vdup_lane_f32(vget_low_f32(vreinterpretq_f32_m128(a)), 1); + float32x2_t b00 = vdup_lane_f32(vget_low_f32(vreinterpretq_f32_m128(b)), 0); + return vreinterpretq_m128_f32(vcombine_f32(a11, b00)); +} + +FORCE_INLINE __m128 _mm_shuffle_ps_0022(__m128 a, __m128 b) +{ + float32x2_t a22 = + vdup_lane_f32(vget_high_f32(vreinterpretq_f32_m128(a)), 0); + float32x2_t b00 = vdup_lane_f32(vget_low_f32(vreinterpretq_f32_m128(b)), 0); + return vreinterpretq_m128_f32(vcombine_f32(a22, b00)); +} + +FORCE_INLINE __m128 _mm_shuffle_ps_2200(__m128 a, __m128 b) +{ + float32x2_t a00 = vdup_lane_f32(vget_low_f32(vreinterpretq_f32_m128(a)), 0); + float32x2_t b22 = + vdup_lane_f32(vget_high_f32(vreinterpretq_f32_m128(b)), 0); + return vreinterpretq_m128_f32(vcombine_f32(a00, b22)); +} + +FORCE_INLINE __m128 _mm_shuffle_ps_3202(__m128 a, __m128 b) +{ + float32_t a0 = vgetq_lane_f32(vreinterpretq_f32_m128(a), 0); + float32x2_t a22 = + vdup_lane_f32(vget_high_f32(vreinterpretq_f32_m128(a)), 0); + float32x2_t a02 = vset_lane_f32(a0, a22, 1); /* TODO: use vzip ?*/ + float32x2_t b32 = vget_high_f32(vreinterpretq_f32_m128(b)); + return vreinterpretq_m128_f32(vcombine_f32(a02, b32)); +} + +FORCE_INLINE __m128 _mm_shuffle_ps_1133(__m128 a, __m128 b) +{ + float32x2_t a33 = + vdup_lane_f32(vget_high_f32(vreinterpretq_f32_m128(a)), 1); + float32x2_t b11 = vdup_lane_f32(vget_low_f32(vreinterpretq_f32_m128(b)), 1); + return vreinterpretq_m128_f32(vcombine_f32(a33, b11)); +} + +FORCE_INLINE __m128 _mm_shuffle_ps_2010(__m128 a, __m128 b) +{ + float32x2_t a10 = vget_low_f32(vreinterpretq_f32_m128(a)); + float32_t b2 = vgetq_lane_f32(vreinterpretq_f32_m128(b), 2); + float32x2_t b00 = vdup_lane_f32(vget_low_f32(vreinterpretq_f32_m128(b)), 0); + float32x2_t b20 = vset_lane_f32(b2, b00, 1); + return vreinterpretq_m128_f32(vcombine_f32(a10, b20)); +} + +FORCE_INLINE __m128 _mm_shuffle_ps_2001(__m128 a, __m128 b) +{ + float32x2_t a01 = vrev64_f32(vget_low_f32(vreinterpretq_f32_m128(a))); + float32_t b2 = vgetq_lane_f32(b, 2); + float32x2_t b00 = vdup_lane_f32(vget_low_f32(vreinterpretq_f32_m128(b)), 0); + float32x2_t b20 = vset_lane_f32(b2, b00, 1); + return vreinterpretq_m128_f32(vcombine_f32(a01, b20)); +} + +FORCE_INLINE __m128 _mm_shuffle_ps_2032(__m128 a, __m128 b) +{ + float32x2_t a32 = vget_high_f32(vreinterpretq_f32_m128(a)); + float32_t b2 = vgetq_lane_f32(b, 2); + float32x2_t b00 = vdup_lane_f32(vget_low_f32(vreinterpretq_f32_m128(b)), 0); + float32x2_t b20 = vset_lane_f32(b2, b00, 1); + return vreinterpretq_m128_f32(vcombine_f32(a32, b20)); +} + +// NEON does not support a general purpose permute intrinsic +// Selects four specific single-precision, floating-point values from a and b, +// based on the mask i. +// +// C equivalent: +// __m128 _mm_shuffle_ps_default(__m128 a, __m128 b, +// __constrange(0, 255) int imm) { +// __m128 ret; +// ret[0] = a[imm & 0x3]; ret[1] = a[(imm >> 2) & 0x3]; +// ret[2] = b[(imm >> 4) & 0x03]; ret[3] = b[(imm >> 6) & 0x03]; +// return ret; +// } +// +// https://msdn.microsoft.com/en-us/library/vstudio/5f0858x0(v=vs.100).aspx +#define _mm_shuffle_ps_default(a, b, imm) \ + __extension__({ \ + float32x4_t ret; \ + ret = vmovq_n_f32( \ + vgetq_lane_f32(vreinterpretq_f32_m128(a), (imm) & (0x3))); \ + ret = vsetq_lane_f32( \ + vgetq_lane_f32(vreinterpretq_f32_m128(a), ((imm) >> 2) & 0x3), \ + ret, 1); \ + ret = vsetq_lane_f32( \ + vgetq_lane_f32(vreinterpretq_f32_m128(b), ((imm) >> 4) & 0x3), \ + ret, 2); \ + ret = vsetq_lane_f32( \ + vgetq_lane_f32(vreinterpretq_f32_m128(b), ((imm) >> 6) & 0x3), \ + ret, 3); \ + vreinterpretq_m128_f32(ret); \ + }) + +// FORCE_INLINE __m128 _mm_shuffle_ps(__m128 a, __m128 b, __constrange(0,255) +// int imm) +#if __has_builtin(__builtin_shufflevector) +#define _mm_shuffle_ps(a, b, imm) \ + __extension__({ \ + float32x4_t _input1 = vreinterpretq_f32_m128(a); \ + float32x4_t _input2 = vreinterpretq_f32_m128(b); \ + float32x4_t _shuf = __builtin_shufflevector( \ + _input1, _input2, (imm) & (0x3), ((imm) >> 2) & 0x3, \ + (((imm) >> 4) & 0x3) + 4, (((imm) >> 6) & 0x3) + 4); \ + vreinterpretq_m128_f32(_shuf); \ + }) +#else // generic +#define _mm_shuffle_ps(a, b, imm) \ + __extension__({ \ + __m128 ret; \ + switch (imm) { \ + case _MM_SHUFFLE(1, 0, 3, 2): \ + ret = _mm_shuffle_ps_1032((a), (b)); \ + break; \ + case _MM_SHUFFLE(2, 3, 0, 1): \ + ret = _mm_shuffle_ps_2301((a), (b)); \ + break; \ + case _MM_SHUFFLE(0, 3, 2, 1): \ + ret = _mm_shuffle_ps_0321((a), (b)); \ + break; \ + case _MM_SHUFFLE(2, 1, 0, 3): \ + ret = _mm_shuffle_ps_2103((a), (b)); \ + break; \ + case _MM_SHUFFLE(1, 0, 1, 0): \ + ret = _mm_movelh_ps((a), (b)); \ + break; \ + case _MM_SHUFFLE(1, 0, 0, 1): \ + ret = _mm_shuffle_ps_1001((a), (b)); \ + break; \ + case _MM_SHUFFLE(0, 1, 0, 1): \ + ret = _mm_shuffle_ps_0101((a), (b)); \ + break; \ + case _MM_SHUFFLE(3, 2, 1, 0): \ + ret = _mm_shuffle_ps_3210((a), (b)); \ + break; \ + case _MM_SHUFFLE(0, 0, 1, 1): \ + ret = _mm_shuffle_ps_0011((a), (b)); \ + break; \ + case _MM_SHUFFLE(0, 0, 2, 2): \ + ret = _mm_shuffle_ps_0022((a), (b)); \ + break; \ + case _MM_SHUFFLE(2, 2, 0, 0): \ + ret = _mm_shuffle_ps_2200((a), (b)); \ + break; \ + case _MM_SHUFFLE(3, 2, 0, 2): \ + ret = _mm_shuffle_ps_3202((a), (b)); \ + break; \ + case _MM_SHUFFLE(3, 2, 3, 2): \ + ret = _mm_movehl_ps((b), (a)); \ + break; \ + case _MM_SHUFFLE(1, 1, 3, 3): \ + ret = _mm_shuffle_ps_1133((a), (b)); \ + break; \ + case _MM_SHUFFLE(2, 0, 1, 0): \ + ret = _mm_shuffle_ps_2010((a), (b)); \ + break; \ + case _MM_SHUFFLE(2, 0, 0, 1): \ + ret = _mm_shuffle_ps_2001((a), (b)); \ + break; \ + case _MM_SHUFFLE(2, 0, 3, 2): \ + ret = _mm_shuffle_ps_2032((a), (b)); \ + break; \ + default: \ + ret = _mm_shuffle_ps_default((a), (b), (imm)); \ + break; \ + } \ + ret; \ + }) +#endif + +// Takes the upper 64 bits of a and places it in the low end of the result +// Takes the lower 64 bits of a and places it into the high end of the result. +FORCE_INLINE __m128i _mm_shuffle_epi_1032(__m128i a) +{ + int32x2_t a32 = vget_high_s32(vreinterpretq_s32_m128i(a)); + int32x2_t a10 = vget_low_s32(vreinterpretq_s32_m128i(a)); + return vreinterpretq_m128i_s32(vcombine_s32(a32, a10)); +} + +// takes the lower two 32-bit values from a and swaps them and places in low end +// of result takes the higher two 32 bit values from a and swaps them and places +// in high end of result. +FORCE_INLINE __m128i _mm_shuffle_epi_2301(__m128i a) +{ + int32x2_t a01 = vrev64_s32(vget_low_s32(vreinterpretq_s32_m128i(a))); + int32x2_t a23 = vrev64_s32(vget_high_s32(vreinterpretq_s32_m128i(a))); + return vreinterpretq_m128i_s32(vcombine_s32(a01, a23)); +} + +// rotates the least significant 32 bits into the most signficant 32 bits, and +// shifts the rest down +FORCE_INLINE __m128i _mm_shuffle_epi_0321(__m128i a) +{ + return vreinterpretq_m128i_s32( + vextq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(a), 1)); +} + +// rotates the most significant 32 bits into the least signficant 32 bits, and +// shifts the rest up +FORCE_INLINE __m128i _mm_shuffle_epi_2103(__m128i a) +{ + return vreinterpretq_m128i_s32( + vextq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(a), 3)); +} + +// gets the lower 64 bits of a, and places it in the upper 64 bits +// gets the lower 64 bits of a and places it in the lower 64 bits +FORCE_INLINE __m128i _mm_shuffle_epi_1010(__m128i a) +{ + int32x2_t a10 = vget_low_s32(vreinterpretq_s32_m128i(a)); + return vreinterpretq_m128i_s32(vcombine_s32(a10, a10)); +} + +// gets the lower 64 bits of a, swaps the 0 and 1 elements, and places it in the +// lower 64 bits gets the lower 64 bits of a, and places it in the upper 64 bits +FORCE_INLINE __m128i _mm_shuffle_epi_1001(__m128i a) +{ + int32x2_t a01 = vrev64_s32(vget_low_s32(vreinterpretq_s32_m128i(a))); + int32x2_t a10 = vget_low_s32(vreinterpretq_s32_m128i(a)); + return vreinterpretq_m128i_s32(vcombine_s32(a01, a10)); +} + +// gets the lower 64 bits of a, swaps the 0 and 1 elements and places it in the +// upper 64 bits gets the lower 64 bits of a, swaps the 0 and 1 elements, and +// places it in the lower 64 bits +FORCE_INLINE __m128i _mm_shuffle_epi_0101(__m128i a) +{ + int32x2_t a01 = vrev64_s32(vget_low_s32(vreinterpretq_s32_m128i(a))); + return vreinterpretq_m128i_s32(vcombine_s32(a01, a01)); +} + +FORCE_INLINE __m128i _mm_shuffle_epi_2211(__m128i a) +{ + int32x2_t a11 = vdup_lane_s32(vget_low_s32(vreinterpretq_s32_m128i(a)), 1); + int32x2_t a22 = vdup_lane_s32(vget_high_s32(vreinterpretq_s32_m128i(a)), 0); + return vreinterpretq_m128i_s32(vcombine_s32(a11, a22)); +} + +FORCE_INLINE __m128i _mm_shuffle_epi_0122(__m128i a) +{ + int32x2_t a22 = vdup_lane_s32(vget_high_s32(vreinterpretq_s32_m128i(a)), 0); + int32x2_t a01 = vrev64_s32(vget_low_s32(vreinterpretq_s32_m128i(a))); + return vreinterpretq_m128i_s32(vcombine_s32(a22, a01)); +} + +FORCE_INLINE __m128i _mm_shuffle_epi_3332(__m128i a) +{ + int32x2_t a32 = vget_high_s32(vreinterpretq_s32_m128i(a)); + int32x2_t a33 = vdup_lane_s32(vget_high_s32(vreinterpretq_s32_m128i(a)), 1); + return vreinterpretq_m128i_s32(vcombine_s32(a32, a33)); +} + +// Shuffle packed 8-bit integers in a according to shuffle control mask in the +// corresponding 8-bit element of b, and store the results in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_shuffle_epi8 +FORCE_INLINE __m128i _mm_shuffle_epi8(__m128i a, __m128i b) +{ + int8x16_t tbl = vreinterpretq_s8_m128i(a); // input a + uint8x16_t idx = vreinterpretq_u8_m128i(b); // input b + uint8x16_t idx_masked = + vandq_u8(idx, vdupq_n_u8(0x8F)); // avoid using meaningless bits +#if defined(__aarch64__) + return vreinterpretq_m128i_s8(vqtbl1q_s8(tbl, idx_masked)); +#elif defined(__GNUC__) + int8x16_t ret; + // %e and %f represent the even and odd D registers + // respectively. + __asm__ __volatile__( + "vtbl.8 %e[ret], {%e[tbl], %f[tbl]}, %e[idx]\n" + "vtbl.8 %f[ret], {%e[tbl], %f[tbl]}, %f[idx]\n" + : [ret] "=&w"(ret) + : [tbl] "w"(tbl), [idx] "w"(idx_masked)); + return vreinterpretq_m128i_s8(ret); +#else + // use this line if testing on aarch64 + int8x8x2_t a_split = {vget_low_s8(tbl), vget_high_s8(tbl)}; + return vreinterpretq_m128i_s8( + vcombine_s8(vtbl2_s8(a_split, vget_low_u8(idx_masked)), + vtbl2_s8(a_split, vget_high_u8(idx_masked)))); +#endif +} + +// C equivalent: +// __m128i _mm_shuffle_epi32_default(__m128i a, +// __constrange(0, 255) int imm) { +// __m128i ret; +// ret[0] = a[imm & 0x3]; ret[1] = a[(imm >> 2) & 0x3]; +// ret[2] = a[(imm >> 4) & 0x03]; ret[3] = a[(imm >> 6) & 0x03]; +// return ret; +// } +#define _mm_shuffle_epi32_default(a, imm) \ + __extension__({ \ + int32x4_t ret; \ + ret = vmovq_n_s32( \ + vgetq_lane_s32(vreinterpretq_s32_m128i(a), (imm) & (0x3))); \ + ret = vsetq_lane_s32( \ + vgetq_lane_s32(vreinterpretq_s32_m128i(a), ((imm) >> 2) & 0x3), \ + ret, 1); \ + ret = vsetq_lane_s32( \ + vgetq_lane_s32(vreinterpretq_s32_m128i(a), ((imm) >> 4) & 0x3), \ + ret, 2); \ + ret = vsetq_lane_s32( \ + vgetq_lane_s32(vreinterpretq_s32_m128i(a), ((imm) >> 6) & 0x3), \ + ret, 3); \ + vreinterpretq_m128i_s32(ret); \ + }) + +// FORCE_INLINE __m128i _mm_shuffle_epi32_splat(__m128i a, __constrange(0,255) +// int imm) +#if defined(__aarch64__) +#define _mm_shuffle_epi32_splat(a, imm) \ + __extension__({ \ + vreinterpretq_m128i_s32( \ + vdupq_laneq_s32(vreinterpretq_s32_m128i(a), (imm))); \ + }) +#else +#define _mm_shuffle_epi32_splat(a, imm) \ + __extension__({ \ + vreinterpretq_m128i_s32( \ + vdupq_n_s32(vgetq_lane_s32(vreinterpretq_s32_m128i(a), (imm)))); \ + }) +#endif + +// Shuffles the 4 signed or unsigned 32-bit integers in a as specified by imm. +// https://msdn.microsoft.com/en-us/library/56f67xbk%28v=vs.90%29.aspx +// FORCE_INLINE __m128i _mm_shuffle_epi32(__m128i a, +// __constrange(0,255) int imm) +#if __has_builtin(__builtin_shufflevector) +#define _mm_shuffle_epi32(a, imm) \ + __extension__({ \ + int32x4_t _input = vreinterpretq_s32_m128i(a); \ + int32x4_t _shuf = __builtin_shufflevector( \ + _input, _input, (imm) & (0x3), ((imm) >> 2) & 0x3, \ + ((imm) >> 4) & 0x3, ((imm) >> 6) & 0x3); \ + vreinterpretq_m128i_s32(_shuf); \ + }) +#else // generic +#define _mm_shuffle_epi32(a, imm) \ + __extension__({ \ + __m128i ret; \ + switch (imm) { \ + case _MM_SHUFFLE(1, 0, 3, 2): \ + ret = _mm_shuffle_epi_1032((a)); \ + break; \ + case _MM_SHUFFLE(2, 3, 0, 1): \ + ret = _mm_shuffle_epi_2301((a)); \ + break; \ + case _MM_SHUFFLE(0, 3, 2, 1): \ + ret = _mm_shuffle_epi_0321((a)); \ + break; \ + case _MM_SHUFFLE(2, 1, 0, 3): \ + ret = _mm_shuffle_epi_2103((a)); \ + break; \ + case _MM_SHUFFLE(1, 0, 1, 0): \ + ret = _mm_shuffle_epi_1010((a)); \ + break; \ + case _MM_SHUFFLE(1, 0, 0, 1): \ + ret = _mm_shuffle_epi_1001((a)); \ + break; \ + case _MM_SHUFFLE(0, 1, 0, 1): \ + ret = _mm_shuffle_epi_0101((a)); \ + break; \ + case _MM_SHUFFLE(2, 2, 1, 1): \ + ret = _mm_shuffle_epi_2211((a)); \ + break; \ + case _MM_SHUFFLE(0, 1, 2, 2): \ + ret = _mm_shuffle_epi_0122((a)); \ + break; \ + case _MM_SHUFFLE(3, 3, 3, 2): \ + ret = _mm_shuffle_epi_3332((a)); \ + break; \ + case _MM_SHUFFLE(0, 0, 0, 0): \ + ret = _mm_shuffle_epi32_splat((a), 0); \ + break; \ + case _MM_SHUFFLE(1, 1, 1, 1): \ + ret = _mm_shuffle_epi32_splat((a), 1); \ + break; \ + case _MM_SHUFFLE(2, 2, 2, 2): \ + ret = _mm_shuffle_epi32_splat((a), 2); \ + break; \ + case _MM_SHUFFLE(3, 3, 3, 3): \ + ret = _mm_shuffle_epi32_splat((a), 3); \ + break; \ + default: \ + ret = _mm_shuffle_epi32_default((a), (imm)); \ + break; \ + } \ + ret; \ + }) +#endif + +// Shuffles the lower 4 signed or unsigned 16-bit integers in a as specified +// by imm. +// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/y41dkk37(v=vs.100) +// FORCE_INLINE __m128i _mm_shufflelo_epi16_function(__m128i a, +// __constrange(0,255) int +// imm) +#define _mm_shufflelo_epi16_function(a, imm) \ + __extension__({ \ + int16x8_t ret = vreinterpretq_s16_m128i(a); \ + int16x4_t lowBits = vget_low_s16(ret); \ + ret = vsetq_lane_s16(vget_lane_s16(lowBits, (imm) & (0x3)), ret, 0); \ + ret = vsetq_lane_s16(vget_lane_s16(lowBits, ((imm) >> 2) & 0x3), ret, \ + 1); \ + ret = vsetq_lane_s16(vget_lane_s16(lowBits, ((imm) >> 4) & 0x3), ret, \ + 2); \ + ret = vsetq_lane_s16(vget_lane_s16(lowBits, ((imm) >> 6) & 0x3), ret, \ + 3); \ + vreinterpretq_m128i_s16(ret); \ + }) + +// FORCE_INLINE __m128i _mm_shufflelo_epi16(__m128i a, +// __constrange(0,255) int imm) +#if __has_builtin(__builtin_shufflevector) +#define _mm_shufflelo_epi16(a, imm) \ + __extension__({ \ + int16x8_t _input = vreinterpretq_s16_m128i(a); \ + int16x8_t _shuf = __builtin_shufflevector( \ + _input, _input, ((imm) & (0x3)), (((imm) >> 2) & 0x3), \ + (((imm) >> 4) & 0x3), (((imm) >> 6) & 0x3), 4, 5, 6, 7); \ + vreinterpretq_m128i_s16(_shuf); \ + }) +#else // generic +#define _mm_shufflelo_epi16(a, imm) _mm_shufflelo_epi16_function((a), (imm)) +#endif + +// Shuffles the upper 4 signed or unsigned 16-bit integers in a as specified +// by imm. +// https://msdn.microsoft.com/en-us/library/13ywktbs(v=vs.100).aspx +// FORCE_INLINE __m128i _mm_shufflehi_epi16_function(__m128i a, +// __constrange(0,255) int +// imm) +#define _mm_shufflehi_epi16_function(a, imm) \ + __extension__({ \ + int16x8_t ret = vreinterpretq_s16_m128i(a); \ + int16x4_t highBits = vget_high_s16(ret); \ + ret = vsetq_lane_s16(vget_lane_s16(highBits, (imm) & (0x3)), ret, 4); \ + ret = vsetq_lane_s16(vget_lane_s16(highBits, ((imm) >> 2) & 0x3), ret, \ + 5); \ + ret = vsetq_lane_s16(vget_lane_s16(highBits, ((imm) >> 4) & 0x3), ret, \ + 6); \ + ret = vsetq_lane_s16(vget_lane_s16(highBits, ((imm) >> 6) & 0x3), ret, \ + 7); \ + vreinterpretq_m128i_s16(ret); \ + }) + +// FORCE_INLINE __m128i _mm_shufflehi_epi16(__m128i a, +// __constrange(0,255) int imm) +#if __has_builtin(__builtin_shufflevector) +#define _mm_shufflehi_epi16(a, imm) \ + __extension__({ \ + int16x8_t _input = vreinterpretq_s16_m128i(a); \ + int16x8_t _shuf = __builtin_shufflevector( \ + _input, _input, 0, 1, 2, 3, ((imm) & (0x3)) + 4, \ + (((imm) >> 2) & 0x3) + 4, (((imm) >> 4) & 0x3) + 4, \ + (((imm) >> 6) & 0x3) + 4); \ + vreinterpretq_m128i_s16(_shuf); \ + }) +#else // generic +#define _mm_shufflehi_epi16(a, imm) _mm_shufflehi_epi16_function((a), (imm)) +#endif + +// Blend packed 16-bit integers from a and b using control mask imm8, and store +// the results in dst. +// +// FOR j := 0 to 7 +// i := j*16 +// IF imm8[j] +// dst[i+15:i] := b[i+15:i] +// ELSE +// dst[i+15:i] := a[i+15:i] +// FI +// ENDFOR +// FORCE_INLINE __m128i _mm_blend_epi16(__m128i a, __m128i b, +// __constrange(0,255) int imm) +#define _mm_blend_epi16(a, b, imm) \ + __extension__({ \ + const uint16_t _mask[8] = {((imm) & (1 << 0)) ? 0xFFFF : 0x0000, \ + ((imm) & (1 << 1)) ? 0xFFFF : 0x0000, \ + ((imm) & (1 << 2)) ? 0xFFFF : 0x0000, \ + ((imm) & (1 << 3)) ? 0xFFFF : 0x0000, \ + ((imm) & (1 << 4)) ? 0xFFFF : 0x0000, \ + ((imm) & (1 << 5)) ? 0xFFFF : 0x0000, \ + ((imm) & (1 << 6)) ? 0xFFFF : 0x0000, \ + ((imm) & (1 << 7)) ? 0xFFFF : 0x0000}; \ + uint16x8_t _mask_vec = vld1q_u16(_mask); \ + uint16x8_t _a = vreinterpretq_u16_m128i(a); \ + uint16x8_t _b = vreinterpretq_u16_m128i(b); \ + vreinterpretq_m128i_u16(vbslq_u16(_mask_vec, _b, _a)); \ + }) + +// Blend packed 8-bit integers from a and b using mask, and store the results in +// dst. +// +// FOR j := 0 to 15 +// i := j*8 +// IF mask[i+7] +// dst[i+7:i] := b[i+7:i] +// ELSE +// dst[i+7:i] := a[i+7:i] +// FI +// ENDFOR +FORCE_INLINE __m128i _mm_blendv_epi8(__m128i _a, __m128i _b, __m128i _mask) +{ + // Use a signed shift right to create a mask with the sign bit + uint8x16_t mask = + vreinterpretq_u8_s8(vshrq_n_s8(vreinterpretq_s8_m128i(_mask), 7)); + uint8x16_t a = vreinterpretq_u8_m128i(_a); + uint8x16_t b = vreinterpretq_u8_m128i(_b); + return vreinterpretq_m128i_u8(vbslq_u8(mask, b, a)); +} + +/* Shifts */ + + +// Shift packed 16-bit integers in a right by imm while shifting in sign +// bits, and store the results in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_srai_epi16 +FORCE_INLINE __m128i _mm_srai_epi16(__m128i a, int imm) +{ + const int count = (imm & ~15) ? 15 : imm; + return (__m128i) vshlq_s16((int16x8_t) a, vdupq_n_s16(-count)); +} + +// Shifts the 8 signed or unsigned 16-bit integers in a left by count bits while +// shifting in zeros. +// +// r0 := a0 << count +// r1 := a1 << count +// ... +// r7 := a7 << count +// +// https://msdn.microsoft.com/en-us/library/es73bcsy(v=vs.90).aspx +#define _mm_slli_epi16(a, imm) \ + __extension__({ \ + __m128i ret; \ + if ((imm) <= 0) { \ + ret = a; \ + } else if ((imm) > 15) { \ + ret = _mm_setzero_si128(); \ + } else { \ + ret = vreinterpretq_m128i_s16( \ + vshlq_n_s16(vreinterpretq_s16_m128i(a), (imm))); \ + } \ + ret; \ + }) + +// Shifts the 4 signed or unsigned 32-bit integers in a left by count bits while +// shifting in zeros. : +// https://msdn.microsoft.com/en-us/library/z2k3bbtb%28v=vs.90%29.aspx +// FORCE_INLINE __m128i _mm_slli_epi32(__m128i a, __constrange(0,255) int imm) +FORCE_INLINE __m128i _mm_slli_epi32(__m128i a, int imm) +{ + if (imm <= 0) /* TODO: add constant range macro: [0, 255] */ + return a; + if (imm > 31) /* TODO: add unlikely macro */ + return _mm_setzero_si128(); + return vreinterpretq_m128i_s32( + vshlq_s32(vreinterpretq_s32_m128i(a), vdupq_n_s32(imm))); +} + +// Shift packed 64-bit integers in a left by imm8 while shifting in zeros, and +// store the results in dst. +FORCE_INLINE __m128i _mm_slli_epi64(__m128i a, int imm) +{ + if (imm <= 0) /* TODO: add constant range macro: [0, 255] */ + return a; + if (imm > 63) /* TODO: add unlikely macro */ + return _mm_setzero_si128(); + return vreinterpretq_m128i_s64( + vshlq_s64(vreinterpretq_s64_m128i(a), vdupq_n_s64(imm))); +} + +// Shift packed 16-bit integers in a right by imm8 while shifting in zeros, and +// store the results in dst. +// +// FOR j := 0 to 7 +// i := j*16 +// IF imm8[7:0] > 15 +// dst[i+15:i] := 0 +// ELSE +// dst[i+15:i] := ZeroExtend16(a[i+15:i] >> imm8[7:0]) +// FI +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_srli_epi16 +#define _mm_srli_epi16(a, imm) \ + __extension__({ \ + __m128i ret; \ + if ((imm) == 0) { \ + ret = a; \ + } else if (0 < (imm) && (imm) < 16) { \ + ret = vreinterpretq_m128i_u16( \ + vshlq_u16(vreinterpretq_u16_m128i(a), vdupq_n_s16(-imm))); \ + } else { \ + ret = _mm_setzero_si128(); \ + } \ + ret; \ + }) + +// Shift packed 32-bit integers in a right by imm8 while shifting in zeros, and +// store the results in dst. +// +// FOR j := 0 to 3 +// i := j*32 +// IF imm8[7:0] > 31 +// dst[i+31:i] := 0 +// ELSE +// dst[i+31:i] := ZeroExtend32(a[i+31:i] >> imm8[7:0]) +// FI +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_srli_epi32 +// FORCE_INLINE __m128i _mm_srli_epi32(__m128i a, __constrange(0,255) int imm) +#define _mm_srli_epi32(a, imm) \ + __extension__({ \ + __m128i ret; \ + if ((imm) == 0) { \ + ret = a; \ + } else if (0 < (imm) && (imm) < 32) { \ + ret = vreinterpretq_m128i_u32( \ + vshlq_u32(vreinterpretq_u32_m128i(a), vdupq_n_s32(-imm))); \ + } else { \ + ret = _mm_setzero_si128(); \ + } \ + ret; \ + }) + +// Shift packed 64-bit integers in a right by imm8 while shifting in zeros, and +// store the results in dst. +// +// FOR j := 0 to 1 +// i := j*64 +// IF imm8[7:0] > 63 +// dst[i+63:i] := 0 +// ELSE +// dst[i+63:i] := ZeroExtend64(a[i+63:i] >> imm8[7:0]) +// FI +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_srli_epi64 +#define _mm_srli_epi64(a, imm) \ + __extension__({ \ + __m128i ret; \ + if ((imm) == 0) { \ + ret = a; \ + } else if (0 < (imm) && (imm) < 64) { \ + ret = vreinterpretq_m128i_u64( \ + vshlq_u64(vreinterpretq_u64_m128i(a), vdupq_n_s64(-imm))); \ + } else { \ + ret = _mm_setzero_si128(); \ + } \ + ret; \ + }) + +// Shift packed 32-bit integers in a right by imm8 while shifting in sign bits, +// and store the results in dst. +// +// FOR j := 0 to 3 +// i := j*32 +// IF imm8[7:0] > 31 +// dst[i+31:i] := (a[i+31] ? 0xFFFFFFFF : 0x0) +// ELSE +// dst[i+31:i] := SignExtend32(a[i+31:i] >> imm8[7:0]) +// FI +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_srai_epi32 +// FORCE_INLINE __m128i _mm_srai_epi32(__m128i a, __constrange(0,255) int imm) +#define _mm_srai_epi32(a, imm) \ + __extension__({ \ + __m128i ret; \ + if ((imm) == 0) { \ + ret = a; \ + } else if (0 < (imm) && (imm) < 32) { \ + ret = vreinterpretq_m128i_s32( \ + vshlq_s32(vreinterpretq_s32_m128i(a), vdupq_n_s32(-imm))); \ + } else { \ + ret = vreinterpretq_m128i_s32( \ + vshrq_n_s32(vreinterpretq_s32_m128i(a), 31)); \ + } \ + ret; \ + }) + +// Shifts the 128 - bit value in a right by imm bytes while shifting in +// zeros.imm must be an immediate. +// +// r := srl(a, imm*8) +// +// https://msdn.microsoft.com/en-us/library/305w28yz(v=vs.100).aspx +// FORCE_INLINE _mm_srli_si128(__m128i a, __constrange(0,255) int imm) +#define _mm_srli_si128(a, imm) \ + __extension__({ \ + __m128i ret; \ + if ((imm) <= 0) { \ + ret = a; \ + } else if ((imm) > 15) { \ + ret = _mm_setzero_si128(); \ + } else { \ + ret = vreinterpretq_m128i_s8( \ + vextq_s8(vreinterpretq_s8_m128i(a), vdupq_n_s8(0), (imm))); \ + } \ + ret; \ + }) + +// Shifts the 128-bit value in a left by imm bytes while shifting in zeros. imm +// must be an immediate. +// +// r := a << (imm * 8) +// +// https://msdn.microsoft.com/en-us/library/34d3k2kt(v=vs.100).aspx +// FORCE_INLINE __m128i _mm_slli_si128(__m128i a, __constrange(0,255) int imm) +#define _mm_slli_si128(a, imm) \ + __extension__({ \ + __m128i ret; \ + if ((imm) <= 0) { \ + ret = a; \ + } else if ((imm) > 15) { \ + ret = _mm_setzero_si128(); \ + } else { \ + ret = vreinterpretq_m128i_s8(vextq_s8( \ + vdupq_n_s8(0), vreinterpretq_s8_m128i(a), 16 - (imm))); \ + } \ + ret; \ + }) + +// Shifts the 8 signed or unsigned 16-bit integers in a left by count bits while +// shifting in zeros. +// +// r0 := a0 << count +// r1 := a1 << count +// ... +// r7 := a7 << count +// +// https://msdn.microsoft.com/en-us/library/c79w388h(v%3dvs.90).aspx +FORCE_INLINE __m128i _mm_sll_epi16(__m128i a, __m128i count) +{ + uint64_t c = vreinterpretq_nth_u64_m128i(count, 0); + if (c > 15) + return _mm_setzero_si128(); + + int16x8_t vc = vdupq_n_s16((int16_t) c); + return vreinterpretq_m128i_s16(vshlq_s16(vreinterpretq_s16_m128i(a), vc)); +} + +// Shifts the 4 signed or unsigned 32-bit integers in a left by count bits while +// shifting in zeros. +// +// r0 := a0 << count +// r1 := a1 << count +// r2 := a2 << count +// r3 := a3 << count +// +// https://msdn.microsoft.com/en-us/library/6fe5a6s9(v%3dvs.90).aspx +FORCE_INLINE __m128i _mm_sll_epi32(__m128i a, __m128i count) +{ + uint64_t c = vreinterpretq_nth_u64_m128i(count, 0); + if (c > 31) + return _mm_setzero_si128(); + + int32x4_t vc = vdupq_n_s32((int32_t) c); + return vreinterpretq_m128i_s32(vshlq_s32(vreinterpretq_s32_m128i(a), vc)); +} + +// Shifts the 2 signed or unsigned 64-bit integers in a left by count bits while +// shifting in zeros. +// +// r0 := a0 << count +// r1 := a1 << count +// +// https://msdn.microsoft.com/en-us/library/6ta9dffd(v%3dvs.90).aspx +FORCE_INLINE __m128i _mm_sll_epi64(__m128i a, __m128i count) +{ + uint64_t c = vreinterpretq_nth_u64_m128i(count, 0); + if (c > 63) + return _mm_setzero_si128(); + + int64x2_t vc = vdupq_n_s64((int64_t) c); + return vreinterpretq_m128i_s64(vshlq_s64(vreinterpretq_s64_m128i(a), vc)); +} + +// Shifts the 8 signed or unsigned 16-bit integers in a right by count bits +// while shifting in zeros. +// +// r0 := srl(a0, count) +// r1 := srl(a1, count) +// ... +// r7 := srl(a7, count) +// +// https://msdn.microsoft.com/en-us/library/wd5ax830(v%3dvs.90).aspx +FORCE_INLINE __m128i _mm_srl_epi16(__m128i a, __m128i count) +{ + uint64_t c = vreinterpretq_nth_u64_m128i(count, 0); + if (c > 15) + return _mm_setzero_si128(); + + int16x8_t vc = vdupq_n_s16(-(int16_t) c); + return vreinterpretq_m128i_u16(vshlq_u16(vreinterpretq_u16_m128i(a), vc)); +} + +// Shifts the 4 signed or unsigned 32-bit integers in a right by count bits +// while shifting in zeros. +// +// r0 := srl(a0, count) +// r1 := srl(a1, count) +// r2 := srl(a2, count) +// r3 := srl(a3, count) +// +// https://msdn.microsoft.com/en-us/library/a9cbttf4(v%3dvs.90).aspx +FORCE_INLINE __m128i _mm_srl_epi32(__m128i a, __m128i count) +{ + uint64_t c = vreinterpretq_nth_u64_m128i(count, 0); + if (c > 31) + return _mm_setzero_si128(); + + int32x4_t vc = vdupq_n_s32(-(int32_t) c); + return vreinterpretq_m128i_u32(vshlq_u32(vreinterpretq_u32_m128i(a), vc)); +} + +// Shifts the 2 signed or unsigned 64-bit integers in a right by count bits +// while shifting in zeros. +// +// r0 := srl(a0, count) +// r1 := srl(a1, count) +// +// https://msdn.microsoft.com/en-us/library/yf6cf9k8(v%3dvs.90).aspx +FORCE_INLINE __m128i _mm_srl_epi64(__m128i a, __m128i count) +{ + uint64_t c = vreinterpretq_nth_u64_m128i(count, 0); + if (c > 63) + return _mm_setzero_si128(); + + int64x2_t vc = vdupq_n_s64(-(int64_t) c); + return vreinterpretq_m128i_u64(vshlq_u64(vreinterpretq_u64_m128i(a), vc)); +} + +// NEON does not provide a version of this function. +// Creates a 16-bit mask from the most significant bits of the 16 signed or +// unsigned 8-bit integers in a and zero extends the upper bits. +// https://msdn.microsoft.com/en-us/library/vstudio/s090c8fk(v=vs.100).aspx +FORCE_INLINE int _mm_movemask_epi8(__m128i a) +{ +#if defined(__aarch64__) + uint8x16_t input = vreinterpretq_u8_m128i(a); + const int8_t ALIGN_STRUCT(16) + xr[16] = {-7, -6, -5, -4, -3, -2, -1, 0, -7, -6, -5, -4, -3, -2, -1, 0}; + const uint8x16_t mask_and = vdupq_n_u8(0x80); + const int8x16_t mask_shift = vld1q_s8(xr); + const uint8x16_t mask_result = + vshlq_u8(vandq_u8(input, mask_and), mask_shift); + uint8x8_t lo = vget_low_u8(mask_result); + uint8x8_t hi = vget_high_u8(mask_result); + + return vaddv_u8(lo) + (vaddv_u8(hi) << 8); +#else + // Use increasingly wide shifts+adds to collect the sign bits + // together. + // Since the widening shifts would be rather confusing to follow in little + // endian, everything will be illustrated in big endian order instead. This + // has a different result - the bits would actually be reversed on a big + // endian machine. + + // Starting input (only half the elements are shown): + // 89 ff 1d c0 00 10 99 33 + uint8x16_t input = vreinterpretq_u8_m128i(a); + + // Shift out everything but the sign bits with an unsigned shift right. + // + // Bytes of the vector:: + // 89 ff 1d c0 00 10 99 33 + // \ \ \ \ \ \ \ \ high_bits = (uint16x4_t)(input >> 7) + // | | | | | | | | + // 01 01 00 01 00 00 01 00 + // + // Bits of first important lane(s): + // 10001001 (89) + // \______ + // | + // 00000001 (01) + uint16x8_t high_bits = vreinterpretq_u16_u8(vshrq_n_u8(input, 7)); + + // Merge the even lanes together with a 16-bit unsigned shift right + add. + // 'xx' represents garbage data which will be ignored in the final result. + // In the important bytes, the add functions like a binary OR. + // + // 01 01 00 01 00 00 01 00 + // \_ | \_ | \_ | \_ | paired16 = (uint32x4_t)(input + (input >> 7)) + // \| \| \| \| + // xx 03 xx 01 xx 00 xx 02 + // + // 00000001 00000001 (01 01) + // \_______ | + // \| + // xxxxxxxx xxxxxx11 (xx 03) + uint32x4_t paired16 = + vreinterpretq_u32_u16(vsraq_n_u16(high_bits, high_bits, 7)); + + // Repeat with a wider 32-bit shift + add. + // xx 03 xx 01 xx 00 xx 02 + // \____ | \____ | paired32 = (uint64x1_t)(paired16 + (paired16 >> + // 14)) + // \| \| + // xx xx xx 0d xx xx xx 02 + // + // 00000011 00000001 (03 01) + // \\_____ || + // '----.\|| + // xxxxxxxx xxxx1101 (xx 0d) + uint64x2_t paired32 = + vreinterpretq_u64_u32(vsraq_n_u32(paired16, paired16, 14)); + + // Last, an even wider 64-bit shift + add to get our result in the low 8 bit + // lanes. xx xx xx 0d xx xx xx 02 + // \_________ | paired64 = (uint8x8_t)(paired32 + (paired32 >> + // 28)) + // \| + // xx xx xx xx xx xx xx d2 + // + // 00001101 00000010 (0d 02) + // \ \___ | | + // '---. \| | + // xxxxxxxx 11010010 (xx d2) + uint8x16_t paired64 = + vreinterpretq_u8_u64(vsraq_n_u64(paired32, paired32, 28)); + + // Extract the low 8 bits from each 64-bit lane with 2 8-bit extracts. + // xx xx xx xx xx xx xx d2 + // || return paired64[0] + // d2 + // Note: Little endian would return the correct value 4b (01001011) instead. + return vgetq_lane_u8(paired64, 0) | ((int) vgetq_lane_u8(paired64, 8) << 8); +#endif +} + +// Copy the lower 64-bit integer in a to dst. +// +// dst[63:0] := a[63:0] +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_movepi64_pi64 +FORCE_INLINE __m64 _mm_movepi64_pi64(__m128i a) +{ + return vreinterpret_m64_s64(vget_low_s64(vreinterpretq_s64_m128i(a))); +} + +// Copy the 64-bit integer a to the lower element of dst, and zero the upper +// element. +// +// dst[63:0] := a[63:0] +// dst[127:64] := 0 +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_movpi64_epi64 +FORCE_INLINE __m128i _mm_movpi64_epi64(__m64 a) +{ + return vreinterpretq_m128i_s64( + vcombine_s64(vreinterpret_s64_m64(a), vdup_n_s64(0))); +} + +// NEON does not provide this method +// Creates a 4-bit mask from the most significant bits of the four +// single-precision, floating-point values. +// https://msdn.microsoft.com/en-us/library/vstudio/4490ys29(v=vs.100).aspx +FORCE_INLINE int _mm_movemask_ps(__m128 a) +{ + uint32x4_t input = vreinterpretq_u32_m128(a); +#if defined(__aarch64__) + static const int32x4_t shift = {0, 1, 2, 3}; + uint32x4_t tmp = vshrq_n_u32(input, 31); + return vaddvq_u32(vshlq_u32(tmp, shift)); +#else + // Uses the exact same method as _mm_movemask_epi8, see that for details. + // Shift out everything but the sign bits with a 32-bit unsigned shift + // right. + uint64x2_t high_bits = vreinterpretq_u64_u32(vshrq_n_u32(input, 31)); + // Merge the two pairs together with a 64-bit unsigned shift right + add. + uint8x16_t paired = + vreinterpretq_u8_u64(vsraq_n_u64(high_bits, high_bits, 31)); + // Extract the result. + return vgetq_lane_u8(paired, 0) | (vgetq_lane_u8(paired, 8) << 2); +#endif +} + +// Compute the bitwise NOT of a and then AND with a 128-bit vector containing +// all 1's, and return 1 if the result is zero, otherwise return 0. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_test_all_ones +FORCE_INLINE int _mm_test_all_ones(__m128i a) +{ + return (uint64_t)(vgetq_lane_s64(a, 0) & vgetq_lane_s64(a, 1)) == + ~(uint64_t) 0; +} + +// Compute the bitwise AND of 128 bits (representing integer data) in a and +// mask, and return 1 if the result is zero, otherwise return 0. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_test_all_zeros +FORCE_INLINE int _mm_test_all_zeros(__m128i a, __m128i mask) +{ + int64x2_t a_and_mask = + vandq_s64(vreinterpretq_s64_m128i(a), vreinterpretq_s64_m128i(mask)); + return (vgetq_lane_s64(a_and_mask, 0) | vgetq_lane_s64(a_and_mask, 1)) ? 0 + : 1; +} + +/* Math operations */ + +// Subtracts the four single-precision, floating-point values of a and b. +// +// r0 := a0 - b0 +// r1 := a1 - b1 +// r2 := a2 - b2 +// r3 := a3 - b3 +// +// https://msdn.microsoft.com/en-us/library/vstudio/1zad2k61(v=vs.100).aspx +FORCE_INLINE __m128 _mm_sub_ps(__m128 a, __m128 b) +{ + return vreinterpretq_m128_f32( + vsubq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b))); +} + +// Subtract the lower single-precision (32-bit) floating-point element in b from +// the lower single-precision (32-bit) floating-point element in a, store the +// result in the lower element of dst, and copy the upper 3 packed elements from +// a to the upper elements of dst. +// +// dst[31:0] := a[31:0] - b[31:0] +// dst[127:32] := a[127:32] +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_sub_ss +FORCE_INLINE __m128 _mm_sub_ss(__m128 a, __m128 b) +{ + return _mm_move_ss(a, _mm_sub_ps(a, b)); +} + +// Subtract 2 packed 64-bit integers in b from 2 packed 64-bit integers in a, +// and store the results in dst. +// r0 := a0 - b0 +// r1 := a1 - b1 +FORCE_INLINE __m128i _mm_sub_epi64(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_s64( + vsubq_s64(vreinterpretq_s64_m128i(a), vreinterpretq_s64_m128i(b))); +} + +// Subtracts the 4 signed or unsigned 32-bit integers of b from the 4 signed or +// unsigned 32-bit integers of a. +// +// r0 := a0 - b0 +// r1 := a1 - b1 +// r2 := a2 - b2 +// r3 := a3 - b3 +// +// https://msdn.microsoft.com/en-us/library/vstudio/fhh866h0(v=vs.100).aspx +FORCE_INLINE __m128i _mm_sub_epi32(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_s32( + vsubq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b))); +} + +FORCE_INLINE __m128i _mm_sub_epi16(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_s16( + vsubq_s16(vreinterpretq_s16_m128i(a), vreinterpretq_s16_m128i(b))); +} + +FORCE_INLINE __m128i _mm_sub_epi8(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_s8( + vsubq_s8(vreinterpretq_s8_m128i(a), vreinterpretq_s8_m128i(b))); +} + +// Subtract 64-bit integer b from 64-bit integer a, and store the result in dst. +// +// dst[63:0] := a[63:0] - b[63:0] +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_sub_si64 +FORCE_INLINE __m64 _mm_sub_si64(__m64 a, __m64 b) +{ + return vreinterpret_m64_s64( + vsub_s64(vreinterpret_s64_m64(a), vreinterpret_s64_m64(b))); +} + +// Subtracts the 8 unsigned 16-bit integers of bfrom the 8 unsigned 16-bit +// integers of a and saturates.. +// https://technet.microsoft.com/en-us/subscriptions/index/f44y0s19(v=vs.90).aspx +FORCE_INLINE __m128i _mm_subs_epu16(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_u16( + vqsubq_u16(vreinterpretq_u16_m128i(a), vreinterpretq_u16_m128i(b))); +} + +// Subtracts the 16 unsigned 8-bit integers of b from the 16 unsigned 8-bit +// integers of a and saturates. +// +// r0 := UnsignedSaturate(a0 - b0) +// r1 := UnsignedSaturate(a1 - b1) +// ... +// r15 := UnsignedSaturate(a15 - b15) +// +// https://technet.microsoft.com/en-us/subscriptions/yadkxc18(v=vs.90) +FORCE_INLINE __m128i _mm_subs_epu8(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_u8( + vqsubq_u8(vreinterpretq_u8_m128i(a), vreinterpretq_u8_m128i(b))); +} + +// Subtracts the 16 signed 8-bit integers of b from the 16 signed 8-bit integers +// of a and saturates. +// +// r0 := SignedSaturate(a0 - b0) +// r1 := SignedSaturate(a1 - b1) +// ... +// r15 := SignedSaturate(a15 - b15) +// +// https://technet.microsoft.com/en-us/subscriptions/by7kzks1(v=vs.90) +FORCE_INLINE __m128i _mm_subs_epi8(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_s8( + vqsubq_s8(vreinterpretq_s8_m128i(a), vreinterpretq_s8_m128i(b))); +} + +// Subtracts the 8 signed 16-bit integers of b from the 8 signed 16-bit integers +// of a and saturates. +// +// r0 := SignedSaturate(a0 - b0) +// r1 := SignedSaturate(a1 - b1) +// ... +// r7 := SignedSaturate(a7 - b7) +// +// https://technet.microsoft.com/en-us/subscriptions/3247z5b8(v=vs.90) +FORCE_INLINE __m128i _mm_subs_epi16(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_s16( + vqsubq_s16(vreinterpretq_s16_m128i(a), vreinterpretq_s16_m128i(b))); +} + +FORCE_INLINE __m128i _mm_adds_epu16(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_u16( + vqaddq_u16(vreinterpretq_u16_m128i(a), vreinterpretq_u16_m128i(b))); +} + +// Negate packed 8-bit integers in a when the corresponding signed +// 8-bit integer in b is negative, and store the results in dst. +// Element in dst are zeroed out when the corresponding element +// in b is zero. +// +// for i in 0..15 +// if b[i] < 0 +// r[i] := -a[i] +// else if b[i] == 0 +// r[i] := 0 +// else +// r[i] := a[i] +// fi +// done +FORCE_INLINE __m128i _mm_sign_epi8(__m128i _a, __m128i _b) +{ + int8x16_t a = vreinterpretq_s8_m128i(_a); + int8x16_t b = vreinterpretq_s8_m128i(_b); + + // signed shift right: faster than vclt + // (b < 0) ? 0xFF : 0 + uint8x16_t ltMask = vreinterpretq_u8_s8(vshrq_n_s8(b, 7)); + + // (b == 0) ? 0xFF : 0 +#if defined(__aarch64__) + int8x16_t zeroMask = vreinterpretq_s8_u8(vceqzq_s8(b)); +#else + int8x16_t zeroMask = vreinterpretq_s8_u8(vceqq_s8(b, vdupq_n_s8(0))); +#endif + + // bitwise select either a or nagative 'a' (vnegq_s8(a) return nagative 'a') + // based on ltMask + int8x16_t masked = vbslq_s8(ltMask, vnegq_s8(a), a); + // res = masked & (~zeroMask) + int8x16_t res = vbicq_s8(masked, zeroMask); + + return vreinterpretq_m128i_s8(res); +} + +// Negate packed 16-bit integers in a when the corresponding signed +// 16-bit integer in b is negative, and store the results in dst. +// Element in dst are zeroed out when the corresponding element +// in b is zero. +// +// for i in 0..7 +// if b[i] < 0 +// r[i] := -a[i] +// else if b[i] == 0 +// r[i] := 0 +// else +// r[i] := a[i] +// fi +// done +FORCE_INLINE __m128i _mm_sign_epi16(__m128i _a, __m128i _b) +{ + int16x8_t a = vreinterpretq_s16_m128i(_a); + int16x8_t b = vreinterpretq_s16_m128i(_b); + + // signed shift right: faster than vclt + // (b < 0) ? 0xFFFF : 0 + uint16x8_t ltMask = vreinterpretq_u16_s16(vshrq_n_s16(b, 15)); + // (b == 0) ? 0xFFFF : 0 +#if defined(__aarch64__) + int16x8_t zeroMask = vreinterpretq_s16_u16(vceqzq_s16(b)); +#else + int16x8_t zeroMask = vreinterpretq_s16_u16(vceqq_s16(b, vdupq_n_s16(0))); +#endif + + // bitwise select either a or negative 'a' (vnegq_s16(a) equals to negative + // 'a') based on ltMask + int16x8_t masked = vbslq_s16(ltMask, vnegq_s16(a), a); + // res = masked & (~zeroMask) + int16x8_t res = vbicq_s16(masked, zeroMask); + return vreinterpretq_m128i_s16(res); +} + +// Negate packed 32-bit integers in a when the corresponding signed +// 32-bit integer in b is negative, and store the results in dst. +// Element in dst are zeroed out when the corresponding element +// in b is zero. +// +// for i in 0..3 +// if b[i] < 0 +// r[i] := -a[i] +// else if b[i] == 0 +// r[i] := 0 +// else +// r[i] := a[i] +// fi +// done +FORCE_INLINE __m128i _mm_sign_epi32(__m128i _a, __m128i _b) +{ + int32x4_t a = vreinterpretq_s32_m128i(_a); + int32x4_t b = vreinterpretq_s32_m128i(_b); + + // signed shift right: faster than vclt + // (b < 0) ? 0xFFFFFFFF : 0 + uint32x4_t ltMask = vreinterpretq_u32_s32(vshrq_n_s32(b, 31)); + + // (b == 0) ? 0xFFFFFFFF : 0 +#if defined(__aarch64__) + int32x4_t zeroMask = vreinterpretq_s32_u32(vceqzq_s32(b)); +#else + int32x4_t zeroMask = vreinterpretq_s32_u32(vceqq_s32(b, vdupq_n_s32(0))); +#endif + + // bitwise select either a or negative 'a' (vnegq_s32(a) equals to negative + // 'a') based on ltMask + int32x4_t masked = vbslq_s32(ltMask, vnegq_s32(a), a); + // res = masked & (~zeroMask) + int32x4_t res = vbicq_s32(masked, zeroMask); + return vreinterpretq_m128i_s32(res); +} + +// Negate packed 16-bit integers in a when the corresponding signed 16-bit +// integer in b is negative, and store the results in dst. Element in dst are +// zeroed out when the corresponding element in b is zero. +// +// FOR j := 0 to 3 +// i := j*16 +// IF b[i+15:i] < 0 +// dst[i+15:i] := -(a[i+15:i]) +// ELSE IF b[i+15:i] == 0 +// dst[i+15:i] := 0 +// ELSE +// dst[i+15:i] := a[i+15:i] +// FI +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_sign_pi16 +FORCE_INLINE __m64 _mm_sign_pi16(__m64 _a, __m64 _b) +{ + int16x4_t a = vreinterpret_s16_m64(_a); + int16x4_t b = vreinterpret_s16_m64(_b); + + // signed shift right: faster than vclt + // (b < 0) ? 0xFFFF : 0 + uint16x4_t ltMask = vreinterpret_u16_s16(vshr_n_s16(b, 15)); + + // (b == 0) ? 0xFFFF : 0 +#if defined(__aarch64__) + int16x4_t zeroMask = vreinterpret_s16_u16(vceqz_s16(b)); +#else + int16x4_t zeroMask = vreinterpret_s16_u16(vceq_s16(b, vdup_n_s16(0))); +#endif + + // bitwise select either a or nagative 'a' (vneg_s16(a) return nagative 'a') + // based on ltMask + int16x4_t masked = vbsl_s16(ltMask, vneg_s16(a), a); + // res = masked & (~zeroMask) + int16x4_t res = vbic_s16(masked, zeroMask); + + return vreinterpret_m64_s16(res); +} + +// Negate packed 32-bit integers in a when the corresponding signed 32-bit +// integer in b is negative, and store the results in dst. Element in dst are +// zeroed out when the corresponding element in b is zero. +// +// FOR j := 0 to 1 +// i := j*32 +// IF b[i+31:i] < 0 +// dst[i+31:i] := -(a[i+31:i]) +// ELSE IF b[i+31:i] == 0 +// dst[i+31:i] := 0 +// ELSE +// dst[i+31:i] := a[i+31:i] +// FI +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_sign_pi32 +FORCE_INLINE __m64 _mm_sign_pi32(__m64 _a, __m64 _b) +{ + int32x2_t a = vreinterpret_s32_m64(_a); + int32x2_t b = vreinterpret_s32_m64(_b); + + // signed shift right: faster than vclt + // (b < 0) ? 0xFFFFFFFF : 0 + uint32x2_t ltMask = vreinterpret_u32_s32(vshr_n_s32(b, 31)); + + // (b == 0) ? 0xFFFFFFFF : 0 +#if defined(__aarch64__) + int32x2_t zeroMask = vreinterpret_s32_u32(vceqz_s32(b)); +#else + int32x2_t zeroMask = vreinterpret_s32_u32(vceq_s32(b, vdup_n_s32(0))); +#endif + + // bitwise select either a or nagative 'a' (vneg_s32(a) return nagative 'a') + // based on ltMask + int32x2_t masked = vbsl_s32(ltMask, vneg_s32(a), a); + // res = masked & (~zeroMask) + int32x2_t res = vbic_s32(masked, zeroMask); + + return vreinterpret_m64_s32(res); +} + +// Negate packed 8-bit integers in a when the corresponding signed 8-bit integer +// in b is negative, and store the results in dst. Element in dst are zeroed out +// when the corresponding element in b is zero. +// +// FOR j := 0 to 7 +// i := j*8 +// IF b[i+7:i] < 0 +// dst[i+7:i] := -(a[i+7:i]) +// ELSE IF b[i+7:i] == 0 +// dst[i+7:i] := 0 +// ELSE +// dst[i+7:i] := a[i+7:i] +// FI +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_sign_pi8 +FORCE_INLINE __m64 _mm_sign_pi8(__m64 _a, __m64 _b) +{ + int8x8_t a = vreinterpret_s8_m64(_a); + int8x8_t b = vreinterpret_s8_m64(_b); + + // signed shift right: faster than vclt + // (b < 0) ? 0xFF : 0 + uint8x8_t ltMask = vreinterpret_u8_s8(vshr_n_s8(b, 7)); + + // (b == 0) ? 0xFF : 0 +#if defined(__aarch64__) + int8x8_t zeroMask = vreinterpret_s8_u8(vceqz_s8(b)); +#else + int8x8_t zeroMask = vreinterpret_s8_u8(vceq_s8(b, vdup_n_s8(0))); +#endif + + // bitwise select either a or nagative 'a' (vneg_s8(a) return nagative 'a') + // based on ltMask + int8x8_t masked = vbsl_s8(ltMask, vneg_s8(a), a); + // res = masked & (~zeroMask) + int8x8_t res = vbic_s8(masked, zeroMask); + + return vreinterpret_m64_s8(res); +} + +// Average packed unsigned 16-bit integers in a and b, and store the results in +// dst. +// +// FOR j := 0 to 3 +// i := j*16 +// dst[i+15:i] := (a[i+15:i] + b[i+15:i] + 1) >> 1 +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_avg_pu16 +FORCE_INLINE __m64 _mm_avg_pu16(__m64 a, __m64 b) +{ + return vreinterpret_m64_u16( + vrhadd_u16(vreinterpret_u16_m64(a), vreinterpret_u16_m64(b))); +} + +// Average packed unsigned 8-bit integers in a and b, and store the results in +// dst. +// +// FOR j := 0 to 7 +// i := j*8 +// dst[i+7:i] := (a[i+7:i] + b[i+7:i] + 1) >> 1 +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_avg_pu8 +FORCE_INLINE __m64 _mm_avg_pu8(__m64 a, __m64 b) +{ + return vreinterpret_m64_u8( + vrhadd_u8(vreinterpret_u8_m64(a), vreinterpret_u8_m64(b))); +} + +// Average packed unsigned 8-bit integers in a and b, and store the results in +// dst. +// +// FOR j := 0 to 7 +// i := j*8 +// dst[i+7:i] := (a[i+7:i] + b[i+7:i] + 1) >> 1 +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_m_pavgb +#define _m_pavgb(a, b) _mm_avg_pu8(a, b) + +// Average packed unsigned 16-bit integers in a and b, and store the results in +// dst. +// +// FOR j := 0 to 3 +// i := j*16 +// dst[i+15:i] := (a[i+15:i] + b[i+15:i] + 1) >> 1 +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_m_pavgw +#define _m_pavgw(a, b) _mm_avg_pu16(a, b) + +// Computes the average of the 16 unsigned 8-bit integers in a and the 16 +// unsigned 8-bit integers in b and rounds. +// +// r0 := (a0 + b0) / 2 +// r1 := (a1 + b1) / 2 +// ... +// r15 := (a15 + b15) / 2 +// +// https://msdn.microsoft.com/en-us/library/vstudio/8zwh554a(v%3dvs.90).aspx +FORCE_INLINE __m128i _mm_avg_epu8(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_u8( + vrhaddq_u8(vreinterpretq_u8_m128i(a), vreinterpretq_u8_m128i(b))); +} + +// Computes the average of the 8 unsigned 16-bit integers in a and the 8 +// unsigned 16-bit integers in b and rounds. +// +// r0 := (a0 + b0) / 2 +// r1 := (a1 + b1) / 2 +// ... +// r7 := (a7 + b7) / 2 +// +// https://msdn.microsoft.com/en-us/library/vstudio/y13ca3c8(v=vs.90).aspx +FORCE_INLINE __m128i _mm_avg_epu16(__m128i a, __m128i b) +{ + return (__m128i) vrhaddq_u16(vreinterpretq_u16_m128i(a), + vreinterpretq_u16_m128i(b)); +} + +// Adds the four single-precision, floating-point values of a and b. +// +// r0 := a0 + b0 +// r1 := a1 + b1 +// r2 := a2 + b2 +// r3 := a3 + b3 +// +// https://msdn.microsoft.com/en-us/library/vstudio/c9848chc(v=vs.100).aspx +FORCE_INLINE __m128 _mm_add_ps(__m128 a, __m128 b) +{ + return vreinterpretq_m128_f32( + vaddq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b))); +} + +// Add packed double-precision (64-bit) floating-point elements in a and b, and +// store the results in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_add_pd +FORCE_INLINE __m128d _mm_add_pd(__m128d a, __m128d b) +{ +#if defined(__aarch64__) + return vreinterpretq_m128d_f64( + vaddq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b))); +#else + double *da = (double *) &a; + double *db = (double *) &b; + double c[2]; + c[0] = da[0] + db[0]; + c[1] = da[1] + db[1]; + return vld1q_f32((float32_t *) c); +#endif +} + +// Add 64-bit integers a and b, and store the result in dst. +// +// dst[63:0] := a[63:0] + b[63:0] +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_add_si64 +FORCE_INLINE __m64 _mm_add_si64(__m64 a, __m64 b) +{ + return vreinterpret_m64_s64( + vadd_s64(vreinterpret_s64_m64(a), vreinterpret_s64_m64(b))); +} + +// adds the scalar single-precision floating point values of a and b. +// https://msdn.microsoft.com/en-us/library/be94x2y6(v=vs.100).aspx +FORCE_INLINE __m128 _mm_add_ss(__m128 a, __m128 b) +{ + float32_t b0 = vgetq_lane_f32(vreinterpretq_f32_m128(b), 0); + float32x4_t value = vsetq_lane_f32(b0, vdupq_n_f32(0), 0); + // the upper values in the result must be the remnants of . + return vreinterpretq_m128_f32(vaddq_f32(a, value)); +} + +// Adds the 4 signed or unsigned 64-bit integers in a to the 4 signed or +// unsigned 32-bit integers in b. +// https://msdn.microsoft.com/en-us/library/vstudio/09xs4fkk(v=vs.100).aspx +FORCE_INLINE __m128i _mm_add_epi64(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_s64( + vaddq_s64(vreinterpretq_s64_m128i(a), vreinterpretq_s64_m128i(b))); +} + +// Adds the 4 signed or unsigned 32-bit integers in a to the 4 signed or +// unsigned 32-bit integers in b. +// +// r0 := a0 + b0 +// r1 := a1 + b1 +// r2 := a2 + b2 +// r3 := a3 + b3 +// +// https://msdn.microsoft.com/en-us/library/vstudio/09xs4fkk(v=vs.100).aspx +FORCE_INLINE __m128i _mm_add_epi32(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_s32( + vaddq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b))); +} + +// Adds the 8 signed or unsigned 16-bit integers in a to the 8 signed or +// unsigned 16-bit integers in b. +// https://msdn.microsoft.com/en-us/library/fceha5k4(v=vs.100).aspx +FORCE_INLINE __m128i _mm_add_epi16(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_s16( + vaddq_s16(vreinterpretq_s16_m128i(a), vreinterpretq_s16_m128i(b))); +} + +// Adds the 16 signed or unsigned 8-bit integers in a to the 16 signed or +// unsigned 8-bit integers in b. +// https://technet.microsoft.com/en-us/subscriptions/yc7tcyzs(v=vs.90) +FORCE_INLINE __m128i _mm_add_epi8(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_s8( + vaddq_s8(vreinterpretq_s8_m128i(a), vreinterpretq_s8_m128i(b))); +} + +// Adds the 8 signed 16-bit integers in a to the 8 signed 16-bit integers in b +// and saturates. +// +// r0 := SignedSaturate(a0 + b0) +// r1 := SignedSaturate(a1 + b1) +// ... +// r7 := SignedSaturate(a7 + b7) +// +// https://msdn.microsoft.com/en-us/library/1a306ef8(v=vs.100).aspx +FORCE_INLINE __m128i _mm_adds_epi16(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_s16( + vqaddq_s16(vreinterpretq_s16_m128i(a), vreinterpretq_s16_m128i(b))); +} + +// Add packed signed 8-bit integers in a and b using saturation, and store the +// results in dst. +// +// FOR j := 0 to 15 +// i := j*8 +// dst[i+7:i] := Saturate8( a[i+7:i] + b[i+7:i] ) +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_adds_epi8 +FORCE_INLINE __m128i _mm_adds_epi8(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_s8( + vqaddq_s8(vreinterpretq_s8_m128i(a), vreinterpretq_s8_m128i(b))); +} + +// Adds the 16 unsigned 8-bit integers in a to the 16 unsigned 8-bit integers in +// b and saturates.. +// https://msdn.microsoft.com/en-us/library/9hahyddy(v=vs.100).aspx +FORCE_INLINE __m128i _mm_adds_epu8(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_u8( + vqaddq_u8(vreinterpretq_u8_m128i(a), vreinterpretq_u8_m128i(b))); +} + +// Multiplies the 8 signed or unsigned 16-bit integers from a by the 8 signed or +// unsigned 16-bit integers from b. +// +// r0 := (a0 * b0)[15:0] +// r1 := (a1 * b1)[15:0] +// ... +// r7 := (a7 * b7)[15:0] +// +// https://msdn.microsoft.com/en-us/library/vstudio/9ks1472s(v=vs.100).aspx +FORCE_INLINE __m128i _mm_mullo_epi16(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_s16( + vmulq_s16(vreinterpretq_s16_m128i(a), vreinterpretq_s16_m128i(b))); +} + +// Multiplies the 4 signed or unsigned 32-bit integers from a by the 4 signed or +// unsigned 32-bit integers from b. +// https://msdn.microsoft.com/en-us/library/vstudio/bb531409(v=vs.100).aspx +FORCE_INLINE __m128i _mm_mullo_epi32(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_s32( + vmulq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b))); +} + +// Multiply the packed unsigned 16-bit integers in a and b, producing +// intermediate 32-bit integers, and store the high 16 bits of the intermediate +// integers in dst. +// +// FOR j := 0 to 3 +// i := j*16 +// tmp[31:0] := a[i+15:i] * b[i+15:i] +// dst[i+15:i] := tmp[31:16] +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_m_pmulhuw +#define _m_pmulhuw(a, b) _mm_mulhi_pu16(a, b) + +// Multiplies the four single-precision, floating-point values of a and b. +// +// r0 := a0 * b0 +// r1 := a1 * b1 +// r2 := a2 * b2 +// r3 := a3 * b3 +// +// https://msdn.microsoft.com/en-us/library/vstudio/22kbk6t9(v=vs.100).aspx +FORCE_INLINE __m128 _mm_mul_ps(__m128 a, __m128 b) +{ + return vreinterpretq_m128_f32( + vmulq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b))); +} + +// Multiply packed double-precision (64-bit) floating-point elements in a and b, +// and store the results in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mul_pd +FORCE_INLINE __m128d _mm_mul_pd(__m128d a, __m128d b) +{ +#if defined(__aarch64__) + return vreinterpretq_m128d_f64( + vmulq_f64(vreinterpretq_f64_m128d(a), vreinterpretq_f64_m128d(b))); +#else + double *da = (double *) &a; + double *db = (double *) &b; + double c[2]; + c[0] = da[0] * db[0]; + c[1] = da[1] * db[1]; + return vld1q_f32((float32_t *) c); +#endif +} + +// Multiply the lower single-precision (32-bit) floating-point element in a and +// b, store the result in the lower element of dst, and copy the upper 3 packed +// elements from a to the upper elements of dst. +// +// dst[31:0] := a[31:0] * b[31:0] +// dst[127:32] := a[127:32] +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mul_ss +FORCE_INLINE __m128 _mm_mul_ss(__m128 a, __m128 b) +{ + return _mm_move_ss(a, _mm_mul_ps(a, b)); +} + +// Multiply the low unsigned 32-bit integers from each packed 64-bit element in +// a and b, and store the unsigned 64-bit results in dst. +// +// r0 := (a0 & 0xFFFFFFFF) * (b0 & 0xFFFFFFFF) +// r1 := (a2 & 0xFFFFFFFF) * (b2 & 0xFFFFFFFF) +FORCE_INLINE __m128i _mm_mul_epu32(__m128i a, __m128i b) +{ + // vmull_u32 upcasts instead of masking, so we downcast. + uint32x2_t a_lo = vmovn_u64(vreinterpretq_u64_m128i(a)); + uint32x2_t b_lo = vmovn_u64(vreinterpretq_u64_m128i(b)); + return vreinterpretq_m128i_u64(vmull_u32(a_lo, b_lo)); +} + +// Multiply the low unsigned 32-bit integers from a and b, and store the +// unsigned 64-bit result in dst. +// +// dst[63:0] := a[31:0] * b[31:0] +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mul_su32 +FORCE_INLINE __m64 _mm_mul_su32(__m64 a, __m64 b) +{ + return vreinterpret_m64_u64(vget_low_u64( + vmull_u32(vreinterpret_u32_m64(a), vreinterpret_u32_m64(b)))); +} + +// Multiply the low signed 32-bit integers from each packed 64-bit element in +// a and b, and store the signed 64-bit results in dst. +// +// r0 := (int64_t)(int32_t)a0 * (int64_t)(int32_t)b0 +// r1 := (int64_t)(int32_t)a2 * (int64_t)(int32_t)b2 +FORCE_INLINE __m128i _mm_mul_epi32(__m128i a, __m128i b) +{ + // vmull_s32 upcasts instead of masking, so we downcast. + int32x2_t a_lo = vmovn_s64(vreinterpretq_s64_m128i(a)); + int32x2_t b_lo = vmovn_s64(vreinterpretq_s64_m128i(b)); + return vreinterpretq_m128i_s64(vmull_s32(a_lo, b_lo)); +} + +// Multiplies the 8 signed 16-bit integers from a by the 8 signed 16-bit +// integers from b. +// +// r0 := (a0 * b0) + (a1 * b1) +// r1 := (a2 * b2) + (a3 * b3) +// r2 := (a4 * b4) + (a5 * b5) +// r3 := (a6 * b6) + (a7 * b7) +// https://msdn.microsoft.com/en-us/library/yht36sa6(v=vs.90).aspx +FORCE_INLINE __m128i _mm_madd_epi16(__m128i a, __m128i b) +{ + int32x4_t low = vmull_s16(vget_low_s16(vreinterpretq_s16_m128i(a)), + vget_low_s16(vreinterpretq_s16_m128i(b))); + int32x4_t high = vmull_s16(vget_high_s16(vreinterpretq_s16_m128i(a)), + vget_high_s16(vreinterpretq_s16_m128i(b))); + + int32x2_t low_sum = vpadd_s32(vget_low_s32(low), vget_high_s32(low)); + int32x2_t high_sum = vpadd_s32(vget_low_s32(high), vget_high_s32(high)); + + return vreinterpretq_m128i_s32(vcombine_s32(low_sum, high_sum)); +} + +// Multiply packed signed 16-bit integers in a and b, producing intermediate +// signed 32-bit integers. Shift right by 15 bits while rounding up, and store +// the packed 16-bit integers in dst. +// +// r0 := Round(((int32_t)a0 * (int32_t)b0) >> 15) +// r1 := Round(((int32_t)a1 * (int32_t)b1) >> 15) +// r2 := Round(((int32_t)a2 * (int32_t)b2) >> 15) +// ... +// r7 := Round(((int32_t)a7 * (int32_t)b7) >> 15) +FORCE_INLINE __m128i _mm_mulhrs_epi16(__m128i a, __m128i b) +{ + // Has issues due to saturation + // return vreinterpretq_m128i_s16(vqrdmulhq_s16(a, b)); + + // Multiply + int32x4_t mul_lo = vmull_s16(vget_low_s16(vreinterpretq_s16_m128i(a)), + vget_low_s16(vreinterpretq_s16_m128i(b))); + int32x4_t mul_hi = vmull_s16(vget_high_s16(vreinterpretq_s16_m128i(a)), + vget_high_s16(vreinterpretq_s16_m128i(b))); + + // Rounding narrowing shift right + // narrow = (int16_t)((mul + 16384) >> 15); + int16x4_t narrow_lo = vrshrn_n_s32(mul_lo, 15); + int16x4_t narrow_hi = vrshrn_n_s32(mul_hi, 15); + + // Join together + return vreinterpretq_m128i_s16(vcombine_s16(narrow_lo, narrow_hi)); +} + +// Vertically multiply each unsigned 8-bit integer from a with the corresponding +// signed 8-bit integer from b, producing intermediate signed 16-bit integers. +// Horizontally add adjacent pairs of intermediate signed 16-bit integers, +// and pack the saturated results in dst. +// +// FOR j := 0 to 7 +// i := j*16 +// dst[i+15:i] := Saturate_To_Int16( a[i+15:i+8]*b[i+15:i+8] + +// a[i+7:i]*b[i+7:i] ) +// ENDFOR +FORCE_INLINE __m128i _mm_maddubs_epi16(__m128i _a, __m128i _b) +{ +#if defined(__aarch64__) + uint8x16_t a = vreinterpretq_u8_m128i(_a); + int8x16_t b = vreinterpretq_s8_m128i(_b); + int16x8_t tl = vmulq_s16(vreinterpretq_s16_u16(vmovl_u8(vget_low_u8(a))), + vmovl_s8(vget_low_s8(b))); + int16x8_t th = vmulq_s16(vreinterpretq_s16_u16(vmovl_u8(vget_high_u8(a))), + vmovl_s8(vget_high_s8(b))); + return vreinterpretq_m128i_s16( + vqaddq_s16(vuzp1q_s16(tl, th), vuzp2q_s16(tl, th))); +#else + // This would be much simpler if x86 would choose to zero extend OR sign + // extend, not both. This could probably be optimized better. + uint16x8_t a = vreinterpretq_u16_m128i(_a); + int16x8_t b = vreinterpretq_s16_m128i(_b); + + // Zero extend a + int16x8_t a_odd = vreinterpretq_s16_u16(vshrq_n_u16(a, 8)); + int16x8_t a_even = vreinterpretq_s16_u16(vbicq_u16(a, vdupq_n_u16(0xff00))); + + // Sign extend by shifting left then shifting right. + int16x8_t b_even = vshrq_n_s16(vshlq_n_s16(b, 8), 8); + int16x8_t b_odd = vshrq_n_s16(b, 8); + + // multiply + int16x8_t prod1 = vmulq_s16(a_even, b_even); + int16x8_t prod2 = vmulq_s16(a_odd, b_odd); + + // saturated add + return vreinterpretq_m128i_s16(vqaddq_s16(prod1, prod2)); +#endif +} + +// Computes the fused multiple add product of 32-bit floating point numbers. +// +// Return Value +// Multiplies A and B, and adds C to the temporary result before returning it. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_fmadd +FORCE_INLINE __m128 _mm_fmadd_ps(__m128 a, __m128 b, __m128 c) +{ +#if defined(__aarch64__) + return vreinterpretq_m128_f32(vfmaq_f32(vreinterpretq_f32_m128(c), + vreinterpretq_f32_m128(b), + vreinterpretq_f32_m128(a))); +#else + return _mm_add_ps(_mm_mul_ps(a, b), c); +#endif +} + +// Alternatively add and subtract packed single-precision (32-bit) +// floating-point elements in a to/from packed elements in b, and store the +// results in dst. +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=addsub_ps +FORCE_INLINE __m128 _mm_addsub_ps(__m128 a, __m128 b) +{ + __m128 mask = {-1.0f, 1.0f, -1.0f, 1.0f}; + return _mm_fmadd_ps(b, mask, a); +} + +// Compute the absolute differences of packed unsigned 8-bit integers in a and +// b, then horizontally sum each consecutive 8 differences to produce two +// unsigned 16-bit integers, and pack these unsigned 16-bit integers in the low +// 16 bits of 64-bit elements in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_sad_epu8 +FORCE_INLINE __m128i _mm_sad_epu8(__m128i a, __m128i b) +{ + uint16x8_t t = vpaddlq_u8(vabdq_u8((uint8x16_t) a, (uint8x16_t) b)); + uint16_t r0 = t[0] + t[1] + t[2] + t[3]; + uint16_t r4 = t[4] + t[5] + t[6] + t[7]; + uint16x8_t r = vsetq_lane_u16(r0, vdupq_n_u16(0), 0); + return (__m128i) vsetq_lane_u16(r4, r, 4); +} + +// Compute the absolute differences of packed unsigned 8-bit integers in a and +// b, then horizontally sum each consecutive 8 differences to produce four +// unsigned 16-bit integers, and pack these unsigned 16-bit integers in the low +// 16 bits of dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_sad_pu8 +FORCE_INLINE __m64 _mm_sad_pu8(__m64 a, __m64 b) +{ + uint16x4_t t = + vpaddl_u8(vabd_u8(vreinterpret_u8_m64(a), vreinterpret_u8_m64(b))); + uint16_t r0 = t[0] + t[1] + t[2] + t[3]; + return vreinterpret_m64_u16(vset_lane_u16(r0, vdup_n_u16(0), 0)); +} + +// Compute the absolute differences of packed unsigned 8-bit integers in a and +// b, then horizontally sum each consecutive 8 differences to produce four +// unsigned 16-bit integers, and pack these unsigned 16-bit integers in the low +// 16 bits of dst. +// +// FOR j := 0 to 7 +// i := j*8 +// tmp[i+7:i] := ABS(a[i+7:i] - b[i+7:i]) +// ENDFOR +// dst[15:0] := tmp[7:0] + tmp[15:8] + tmp[23:16] + tmp[31:24] + tmp[39:32] + +// tmp[47:40] + tmp[55:48] + tmp[63:56] dst[63:16] := 0 +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_m_psadbw +#define _m_psadbw(a, b) _mm_sad_pu8(a, b) + +// Divides the four single-precision, floating-point values of a and b. +// +// r0 := a0 / b0 +// r1 := a1 / b1 +// r2 := a2 / b2 +// r3 := a3 / b3 +// +// https://msdn.microsoft.com/en-us/library/edaw8147(v=vs.100).aspx +FORCE_INLINE __m128 _mm_div_ps(__m128 a, __m128 b) +{ +#if defined(__aarch64__) + return vreinterpretq_m128_f32( + vdivq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b))); +#else + float32x4_t recip0 = vrecpeq_f32(vreinterpretq_f32_m128(b)); + float32x4_t recip1 = + vmulq_f32(recip0, vrecpsq_f32(recip0, vreinterpretq_f32_m128(b))); + return vreinterpretq_m128_f32(vmulq_f32(vreinterpretq_f32_m128(a), recip1)); +#endif +} + +// Divides the scalar single-precision floating point value of a by b. +// https://msdn.microsoft.com/en-us/library/4y73xa49(v=vs.100).aspx +FORCE_INLINE __m128 _mm_div_ss(__m128 a, __m128 b) +{ + float32_t value = + vgetq_lane_f32(vreinterpretq_f32_m128(_mm_div_ps(a, b)), 0); + return vreinterpretq_m128_f32( + vsetq_lane_f32(value, vreinterpretq_f32_m128(a), 0)); +} + +// Compute the approximate reciprocal of packed single-precision (32-bit) +// floating-point elements in a, and store the results in dst. The maximum +// relative error for this approximation is less than 1.5*2^-12. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_rcp_ps +FORCE_INLINE __m128 _mm_rcp_ps(__m128 in) +{ +#if defined(__aarch64__) + return vreinterpretq_m128_f32( + vdivq_f32(vdupq_n_f32(1.0f), vreinterpretq_f32_m128(in))); +#else + float32x4_t recip = vrecpeq_f32(vreinterpretq_f32_m128(in)); + recip = vmulq_f32(recip, vrecpsq_f32(recip, vreinterpretq_f32_m128(in))); + return vreinterpretq_m128_f32(recip); +#endif +} + +// Compute the approximate reciprocal of the lower single-precision (32-bit) +// floating-point element in a, store the result in the lower element of dst, +// and copy the upper 3 packed elements from a to the upper elements of dst. The +// maximum relative error for this approximation is less than 1.5*2^-12. +// +// dst[31:0] := (1.0 / a[31:0]) +// dst[127:32] := a[127:32] +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_rcp_ss +FORCE_INLINE __m128 _mm_rcp_ss(__m128 a) +{ + return _mm_move_ss(a, _mm_rcp_ps(a)); +} + +// Computes the approximations of square roots of the four single-precision, +// floating-point values of a. First computes reciprocal square roots and then +// reciprocals of the four values. +// +// r0 := sqrt(a0) +// r1 := sqrt(a1) +// r2 := sqrt(a2) +// r3 := sqrt(a3) +// +// https://msdn.microsoft.com/en-us/library/vstudio/8z67bwwk(v=vs.100).aspx +FORCE_INLINE __m128 _mm_sqrt_ps(__m128 in) +{ +#if defined(__aarch64__) + return vreinterpretq_m128_f32(vsqrtq_f32(vreinterpretq_f32_m128(in))); +#else + float32x4_t recipsq = vrsqrteq_f32(vreinterpretq_f32_m128(in)); + float32x4_t sq = vrecpeq_f32(recipsq); + // ??? use step versions of both sqrt and recip for better accuracy? + return vreinterpretq_m128_f32(sq); +#endif +} + +// Computes the approximation of the square root of the scalar single-precision +// floating point value of in. +// https://msdn.microsoft.com/en-us/library/ahfsc22d(v=vs.100).aspx +FORCE_INLINE __m128 _mm_sqrt_ss(__m128 in) +{ + float32_t value = + vgetq_lane_f32(vreinterpretq_f32_m128(_mm_sqrt_ps(in)), 0); + return vreinterpretq_m128_f32( + vsetq_lane_f32(value, vreinterpretq_f32_m128(in), 0)); +} + +// Computes the approximations of the reciprocal square roots of the four +// single-precision floating point values of in. +// https://msdn.microsoft.com/en-us/library/22hfsh53(v=vs.100).aspx +FORCE_INLINE __m128 _mm_rsqrt_ps(__m128 in) +{ + return vreinterpretq_m128_f32(vrsqrteq_f32(vreinterpretq_f32_m128(in))); +} + +// Compute the approximate reciprocal square root of the lower single-precision +// (32-bit) floating-point element in a, store the result in the lower element +// of dst, and copy the upper 3 packed elements from a to the upper elements of +// dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_rsqrt_ss +FORCE_INLINE __m128 _mm_rsqrt_ss(__m128 in) +{ + return vsetq_lane_f32(vgetq_lane_f32(_mm_rsqrt_ps(in), 0), in, 0); +} + +// Compare packed signed 16-bit integers in a and b, and store packed maximum +// values in dst. +// +// FOR j := 0 to 3 +// i := j*16 +// dst[i+15:i] := MAX(a[i+15:i], b[i+15:i]) +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_max_pi16 +FORCE_INLINE __m64 _mm_max_pi16(__m64 a, __m64 b) +{ + return vreinterpret_m64_s16( + vmax_s16(vreinterpret_s16_m64(a), vreinterpret_s16_m64(b))); +} + +// Compare packed signed 16-bit integers in a and b, and store packed maximum +// values in dst. +// +// FOR j := 0 to 3 +// i := j*16 +// dst[i+15:i] := MAX(a[i+15:i], b[i+15:i]) +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_max_pi16 +#define _m_pmaxsw(a, b) _mm_max_pi16(a, b) + +// Computes the maximums of the four single-precision, floating-point values of +// a and b. +// https://msdn.microsoft.com/en-us/library/vstudio/ff5d607a(v=vs.100).aspx +FORCE_INLINE __m128 _mm_max_ps(__m128 a, __m128 b) +{ +#if SSE2NEON_PRECISE_MINMAX + float32x4_t _a = vreinterpretq_f32_m128(a); + float32x4_t _b = vreinterpretq_f32_m128(b); + return vbslq_f32(vcltq_f32(_b, _a), _a, _b); +#else + return vreinterpretq_m128_f32( + vmaxq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b))); +#endif +} + +// Compare packed unsigned 8-bit integers in a and b, and store packed maximum +// values in dst. +// +// FOR j := 0 to 7 +// i := j*8 +// dst[i+7:i] := MAX(a[i+7:i], b[i+7:i]) +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_max_pu8 +FORCE_INLINE __m64 _mm_max_pu8(__m64 a, __m64 b) +{ + return vreinterpret_m64_u8( + vmax_u8(vreinterpret_u8_m64(a), vreinterpret_u8_m64(b))); +} + +// Compare packed unsigned 8-bit integers in a and b, and store packed maximum +// values in dst. +// +// FOR j := 0 to 7 +// i := j*8 +// dst[i+7:i] := MAX(a[i+7:i], b[i+7:i]) +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_max_pu8 +#define _m_pmaxub(a, b) _mm_max_pu8(a, b) + +// Compare packed signed 16-bit integers in a and b, and store packed minimum +// values in dst. +// +// FOR j := 0 to 3 +// i := j*16 +// dst[i+15:i] := MIN(a[i+15:i], b[i+15:i]) +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_min_pi16 +FORCE_INLINE __m64 _mm_min_pi16(__m64 a, __m64 b) +{ + return vreinterpret_m64_s16( + vmin_s16(vreinterpret_s16_m64(a), vreinterpret_s16_m64(b))); +} + +// Compare packed signed 16-bit integers in a and b, and store packed minimum +// values in dst. +// +// FOR j := 0 to 3 +// i := j*16 +// dst[i+15:i] := MIN(a[i+15:i], b[i+15:i]) +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_min_pi16 +#define _m_pminsw(a, b) _mm_min_pi16(a, b) + +// Computes the minima of the four single-precision, floating-point values of a +// and b. +// https://msdn.microsoft.com/en-us/library/vstudio/wh13kadz(v=vs.100).aspx +FORCE_INLINE __m128 _mm_min_ps(__m128 a, __m128 b) +{ +#if SSE2NEON_PRECISE_MINMAX + float32x4_t _a = vreinterpretq_f32_m128(a); + float32x4_t _b = vreinterpretq_f32_m128(b); + return vbslq_f32(vcltq_f32(_a, _b), _a, _b); +#else + return vreinterpretq_m128_f32( + vminq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b))); +#endif +} + +// Compare packed unsigned 8-bit integers in a and b, and store packed minimum +// values in dst. +// +// FOR j := 0 to 7 +// i := j*8 +// dst[i+7:i] := MIN(a[i+7:i], b[i+7:i]) +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_min_pu8 +FORCE_INLINE __m64 _mm_min_pu8(__m64 a, __m64 b) +{ + return vreinterpret_m64_u8( + vmin_u8(vreinterpret_u8_m64(a), vreinterpret_u8_m64(b))); +} + +// Compare packed unsigned 8-bit integers in a and b, and store packed minimum +// values in dst. +// +// FOR j := 0 to 7 +// i := j*8 +// dst[i+7:i] := MIN(a[i+7:i], b[i+7:i]) +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_min_pu8 +#define _m_pminub(a, b) _mm_min_pu8(a, b) + +// Computes the maximum of the two lower scalar single-precision floating point +// values of a and b. +// https://msdn.microsoft.com/en-us/library/s6db5esz(v=vs.100).aspx +FORCE_INLINE __m128 _mm_max_ss(__m128 a, __m128 b) +{ + float32_t value = vgetq_lane_f32(_mm_max_ps(a, b), 0); + return vreinterpretq_m128_f32( + vsetq_lane_f32(value, vreinterpretq_f32_m128(a), 0)); +} + +// Computes the minimum of the two lower scalar single-precision floating point +// values of a and b. +// https://msdn.microsoft.com/en-us/library/0a9y7xaa(v=vs.100).aspx +FORCE_INLINE __m128 _mm_min_ss(__m128 a, __m128 b) +{ + float32_t value = vgetq_lane_f32(_mm_min_ps(a, b), 0); + return vreinterpretq_m128_f32( + vsetq_lane_f32(value, vreinterpretq_f32_m128(a), 0)); +} + +// Computes the pairwise maxima of the 16 unsigned 8-bit integers from a and the +// 16 unsigned 8-bit integers from b. +// https://msdn.microsoft.com/en-us/library/st6634za(v=vs.100).aspx +FORCE_INLINE __m128i _mm_max_epu8(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_u8( + vmaxq_u8(vreinterpretq_u8_m128i(a), vreinterpretq_u8_m128i(b))); +} + +// Computes the pairwise minima of the 16 unsigned 8-bit integers from a and the +// 16 unsigned 8-bit integers from b. +// https://msdn.microsoft.com/ko-kr/library/17k8cf58(v=vs.100).aspxx +FORCE_INLINE __m128i _mm_min_epu8(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_u8( + vminq_u8(vreinterpretq_u8_m128i(a), vreinterpretq_u8_m128i(b))); +} + +// Computes the pairwise minima of the 8 signed 16-bit integers from a and the 8 +// signed 16-bit integers from b. +// https://msdn.microsoft.com/en-us/library/vstudio/6te997ew(v=vs.100).aspx +FORCE_INLINE __m128i _mm_min_epi16(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_s16( + vminq_s16(vreinterpretq_s16_m128i(a), vreinterpretq_s16_m128i(b))); +} + +// Compare packed signed 8-bit integers in a and b, and store packed maximum +// values in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_max_epi8 +FORCE_INLINE __m128i _mm_max_epi8(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_s8( + vmaxq_s8(vreinterpretq_s8_m128i(a), vreinterpretq_s8_m128i(b))); +} + +// Compare packed unsigned 16-bit integers in a and b, and store packed maximum +// values in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_max_epu16 +FORCE_INLINE __m128i _mm_max_epu16(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_u16( + vmaxq_u16(vreinterpretq_u16_m128i(a), vreinterpretq_u16_m128i(b))); +} + +// Compare packed signed 8-bit integers in a and b, and store packed minimum +// values in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_min_epi8 +FORCE_INLINE __m128i _mm_min_epi8(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_s8( + vminq_s8(vreinterpretq_s8_m128i(a), vreinterpretq_s8_m128i(b))); +} + +// Compare packed unsigned 16-bit integers in a and b, and store packed minimum +// values in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_min_epu16 +FORCE_INLINE __m128i _mm_min_epu16(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_u16( + vminq_u16(vreinterpretq_u16_m128i(a), vreinterpretq_u16_m128i(b))); +} + +// Computes the pairwise maxima of the 8 signed 16-bit integers from a and the 8 +// signed 16-bit integers from b. +// https://msdn.microsoft.com/en-us/LIBRary/3x060h7c(v=vs.100).aspx +FORCE_INLINE __m128i _mm_max_epi16(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_s16( + vmaxq_s16(vreinterpretq_s16_m128i(a), vreinterpretq_s16_m128i(b))); +} + +// epi versions of min/max +// Computes the pariwise maximums of the four signed 32-bit integer values of a +// and b. +// +// A 128-bit parameter that can be defined with the following equations: +// r0 := (a0 > b0) ? a0 : b0 +// r1 := (a1 > b1) ? a1 : b1 +// r2 := (a2 > b2) ? a2 : b2 +// r3 := (a3 > b3) ? a3 : b3 +// +// https://msdn.microsoft.com/en-us/library/vstudio/bb514055(v=vs.100).aspx +FORCE_INLINE __m128i _mm_max_epi32(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_s32( + vmaxq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b))); +} + +// Computes the pariwise minima of the four signed 32-bit integer values of a +// and b. +// +// A 128-bit parameter that can be defined with the following equations: +// r0 := (a0 < b0) ? a0 : b0 +// r1 := (a1 < b1) ? a1 : b1 +// r2 := (a2 < b2) ? a2 : b2 +// r3 := (a3 < b3) ? a3 : b3 +// +// https://msdn.microsoft.com/en-us/library/vstudio/bb531476(v=vs.100).aspx +FORCE_INLINE __m128i _mm_min_epi32(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_s32( + vminq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b))); +} + +// Compare packed unsigned 32-bit integers in a and b, and store packed maximum +// values in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_max_epu32 +FORCE_INLINE __m128i _mm_max_epu32(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_u32( + vmaxq_u32(vreinterpretq_u32_m128i(a), vreinterpretq_u32_m128i(b))); +} + +// Compare packed unsigned 32-bit integers in a and b, and store packed minimum +// values in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_max_epu32 +FORCE_INLINE __m128i _mm_min_epu32(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_u32( + vminq_u32(vreinterpretq_u32_m128i(a), vreinterpretq_u32_m128i(b))); +} + +// Multiply the packed unsigned 16-bit integers in a and b, producing +// intermediate 32-bit integers, and store the high 16 bits of the intermediate +// integers in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mulhi_pu16 +FORCE_INLINE __m64 _mm_mulhi_pu16(__m64 a, __m64 b) +{ + return vreinterpret_m64_u16(vshrn_n_u32( + vmull_u16(vreinterpret_u16_m64(a), vreinterpret_u16_m64(b)), 16)); +} + +// Multiplies the 8 signed 16-bit integers from a by the 8 signed 16-bit +// integers from b. +// +// r0 := (a0 * b0)[31:16] +// r1 := (a1 * b1)[31:16] +// ... +// r7 := (a7 * b7)[31:16] +// +// https://msdn.microsoft.com/en-us/library/vstudio/59hddw1d(v=vs.100).aspx +FORCE_INLINE __m128i _mm_mulhi_epi16(__m128i a, __m128i b) +{ + /* FIXME: issue with large values because of result saturation */ + // int16x8_t ret = vqdmulhq_s16(vreinterpretq_s16_m128i(a), + // vreinterpretq_s16_m128i(b)); /* =2*a*b */ return + // vreinterpretq_m128i_s16(vshrq_n_s16(ret, 1)); + int16x4_t a3210 = vget_low_s16(vreinterpretq_s16_m128i(a)); + int16x4_t b3210 = vget_low_s16(vreinterpretq_s16_m128i(b)); + int32x4_t ab3210 = vmull_s16(a3210, b3210); /* 3333222211110000 */ + int16x4_t a7654 = vget_high_s16(vreinterpretq_s16_m128i(a)); + int16x4_t b7654 = vget_high_s16(vreinterpretq_s16_m128i(b)); + int32x4_t ab7654 = vmull_s16(a7654, b7654); /* 7777666655554444 */ + uint16x8x2_t r = + vuzpq_u16(vreinterpretq_u16_s32(ab3210), vreinterpretq_u16_s32(ab7654)); + return vreinterpretq_m128i_u16(r.val[1]); +} + +// Multiply the packed unsigned 16-bit integers in a and b, producing +// intermediate 32-bit integers, and store the high 16 bits of the intermediate +// integers in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_mulhi_epu16 +FORCE_INLINE __m128i _mm_mulhi_epu16(__m128i a, __m128i b) +{ + uint16x4_t a3210 = vget_low_u16(vreinterpretq_u16_m128i(a)); + uint16x4_t b3210 = vget_low_u16(vreinterpretq_u16_m128i(b)); + uint32x4_t ab3210 = vmull_u16(a3210, b3210); +#if defined(__aarch64__) + uint32x4_t ab7654 = + vmull_high_u16(vreinterpretq_u16_m128i(a), vreinterpretq_u16_m128i(b)); + uint16x8_t r = vuzp2q_u16(vreinterpretq_u16_u32(ab3210), + vreinterpretq_u16_u32(ab7654)); + return vreinterpretq_m128i_u16(r); +#else + uint16x4_t a7654 = vget_high_u16(vreinterpretq_u16_m128i(a)); + uint16x4_t b7654 = vget_high_u16(vreinterpretq_u16_m128i(b)); + uint32x4_t ab7654 = vmull_u16(a7654, b7654); + uint16x8x2_t r = + vuzpq_u16(vreinterpretq_u16_u32(ab3210), vreinterpretq_u16_u32(ab7654)); + return vreinterpretq_m128i_u16(r.val[1]); +#endif +} + +// Computes pairwise add of each argument as single-precision, floating-point +// values a and b. +// https://msdn.microsoft.com/en-us/library/yd9wecaa.aspx +FORCE_INLINE __m128 _mm_hadd_ps(__m128 a, __m128 b) +{ +#if defined(__aarch64__) + return vreinterpretq_m128_f32( + vpaddq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b))); +#else + float32x2_t a10 = vget_low_f32(vreinterpretq_f32_m128(a)); + float32x2_t a32 = vget_high_f32(vreinterpretq_f32_m128(a)); + float32x2_t b10 = vget_low_f32(vreinterpretq_f32_m128(b)); + float32x2_t b32 = vget_high_f32(vreinterpretq_f32_m128(b)); + return vreinterpretq_m128_f32( + vcombine_f32(vpadd_f32(a10, a32), vpadd_f32(b10, b32))); +#endif +} + +// Computes pairwise add of each argument as a 16-bit signed or unsigned integer +// values a and b. +FORCE_INLINE __m128i _mm_hadd_epi16(__m128i _a, __m128i _b) +{ + int16x8_t a = vreinterpretq_s16_m128i(_a); + int16x8_t b = vreinterpretq_s16_m128i(_b); +#if defined(__aarch64__) + return vreinterpretq_m128i_s16(vpaddq_s16(a, b)); +#else + return vreinterpretq_m128i_s16( + vcombine_s16(vpadd_s16(vget_low_s16(a), vget_high_s16(a)), + vpadd_s16(vget_low_s16(b), vget_high_s16(b)))); +#endif +} + +// Horizontally substract adjacent pairs of single-precision (32-bit) +// floating-point elements in a and b, and pack the results in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_hsub_ps +FORCE_INLINE __m128 _mm_hsub_ps(__m128 _a, __m128 _b) +{ +#if defined(__aarch64__) + return vreinterpretq_m128_f32(vsubq_f32( + vuzp1q_f32(vreinterpretq_f32_m128(_a), vreinterpretq_f32_m128(_b)), + vuzp2q_f32(vreinterpretq_f32_m128(_a), vreinterpretq_f32_m128(_b)))); +#else + float32x4x2_t c = + vuzpq_f32(vreinterpretq_f32_m128(_a), vreinterpretq_f32_m128(_b)); + return vreinterpretq_m128_f32(vsubq_f32(c.val[0], c.val[1])); +#endif +} + +// Horizontally add adjacent pairs of 16-bit integers in a and b, and pack the +// signed 16-bit results in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_hadd_pi16 +FORCE_INLINE __m64 _mm_hadd_pi16(__m64 a, __m64 b) +{ + return vreinterpret_m64_s16( + vpadd_s16(vreinterpret_s16_m64(a), vreinterpret_s16_m64(b))); +} + +// Horizontally add adjacent pairs of 32-bit integers in a and b, and pack the +// signed 32-bit results in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_hadd_pi32 +FORCE_INLINE __m64 _mm_hadd_pi32(__m64 a, __m64 b) +{ + return vreinterpret_m64_s32( + vpadd_s32(vreinterpret_s32_m64(a), vreinterpret_s32_m64(b))); +} + +// Computes pairwise difference of each argument as a 16-bit signed or unsigned +// integer values a and b. +FORCE_INLINE __m128i _mm_hsub_epi16(__m128i _a, __m128i _b) +{ + int32x4_t a = vreinterpretq_s32_m128i(_a); + int32x4_t b = vreinterpretq_s32_m128i(_b); + // Interleave using vshrn/vmovn + // [a0|a2|a4|a6|b0|b2|b4|b6] + // [a1|a3|a5|a7|b1|b3|b5|b7] + int16x8_t ab0246 = vcombine_s16(vmovn_s32(a), vmovn_s32(b)); + int16x8_t ab1357 = vcombine_s16(vshrn_n_s32(a, 16), vshrn_n_s32(b, 16)); + // Subtract + return vreinterpretq_m128i_s16(vsubq_s16(ab0246, ab1357)); +} + +// Computes saturated pairwise sub of each argument as a 16-bit signed +// integer values a and b. +FORCE_INLINE __m128i _mm_hadds_epi16(__m128i _a, __m128i _b) +{ +#if defined(__aarch64__) + int16x8_t a = vreinterpretq_s16_m128i(_a); + int16x8_t b = vreinterpretq_s16_m128i(_b); + return vreinterpretq_s64_s16( + vqaddq_s16(vuzp1q_s16(a, b), vuzp2q_s16(a, b))); +#else + int32x4_t a = vreinterpretq_s32_m128i(_a); + int32x4_t b = vreinterpretq_s32_m128i(_b); + // Interleave using vshrn/vmovn + // [a0|a2|a4|a6|b0|b2|b4|b6] + // [a1|a3|a5|a7|b1|b3|b5|b7] + int16x8_t ab0246 = vcombine_s16(vmovn_s32(a), vmovn_s32(b)); + int16x8_t ab1357 = vcombine_s16(vshrn_n_s32(a, 16), vshrn_n_s32(b, 16)); + // Saturated add + return vreinterpretq_m128i_s16(vqaddq_s16(ab0246, ab1357)); +#endif +} + +// Computes saturated pairwise difference of each argument as a 16-bit signed +// integer values a and b. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_hsubs_epi16 +FORCE_INLINE __m128i _mm_hsubs_epi16(__m128i _a, __m128i _b) +{ +#if defined(__aarch64__) + int16x8_t a = vreinterpretq_s16_m128i(_a); + int16x8_t b = vreinterpretq_s16_m128i(_b); + return vreinterpretq_s64_s16( + vqsubq_s16(vuzp1q_s16(a, b), vuzp2q_s16(a, b))); +#else + int32x4_t a = vreinterpretq_s32_m128i(_a); + int32x4_t b = vreinterpretq_s32_m128i(_b); + // Interleave using vshrn/vmovn + // [a0|a2|a4|a6|b0|b2|b4|b6] + // [a1|a3|a5|a7|b1|b3|b5|b7] + int16x8_t ab0246 = vcombine_s16(vmovn_s32(a), vmovn_s32(b)); + int16x8_t ab1357 = vcombine_s16(vshrn_n_s32(a, 16), vshrn_n_s32(b, 16)); + // Saturated subtract + return vreinterpretq_m128i_s16(vqsubq_s16(ab0246, ab1357)); +#endif +} + +// Computes pairwise add of each argument as a 32-bit signed or unsigned integer +// values a and b. +FORCE_INLINE __m128i _mm_hadd_epi32(__m128i _a, __m128i _b) +{ + int32x4_t a = vreinterpretq_s32_m128i(_a); + int32x4_t b = vreinterpretq_s32_m128i(_b); + return vreinterpretq_m128i_s32( + vcombine_s32(vpadd_s32(vget_low_s32(a), vget_high_s32(a)), + vpadd_s32(vget_low_s32(b), vget_high_s32(b)))); +} + +// Computes pairwise difference of each argument as a 32-bit signed or unsigned +// integer values a and b. +FORCE_INLINE __m128i _mm_hsub_epi32(__m128i _a, __m128i _b) +{ + int64x2_t a = vreinterpretq_s64_m128i(_a); + int64x2_t b = vreinterpretq_s64_m128i(_b); + // Interleave using vshrn/vmovn + // [a0|a2|b0|b2] + // [a1|a2|b1|b3] + int32x4_t ab02 = vcombine_s32(vmovn_s64(a), vmovn_s64(b)); + int32x4_t ab13 = vcombine_s32(vshrn_n_s64(a, 32), vshrn_n_s64(b, 32)); + // Subtract + return vreinterpretq_m128i_s32(vsubq_s32(ab02, ab13)); +} + +// Kahan summation for accurate summation of floating-point numbers. +// http://blog.zachbjornson.com/2019/08/11/fast-float-summation.html +FORCE_INLINE void sse2neon_kadd_f32(float *sum, float *c, float y) +{ + y -= *c; + float t = *sum + y; + *c = (t - *sum) - y; + *sum = t; +} + +// Conditionally multiply the packed single-precision (32-bit) floating-point +// elements in a and b using the high 4 bits in imm8, sum the four products, +// and conditionally store the sum in dst using the low 4 bits of imm. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_dp_ps +FORCE_INLINE __m128 _mm_dp_ps(__m128 a, __m128 b, const int imm) +{ +#if defined(__aarch64__) + /* shortcuts */ + if (imm == 0xFF) { + return _mm_set1_ps(vaddvq_f32(_mm_mul_ps(a, b))); + } + if (imm == 0x7F) { + float32x4_t m = _mm_mul_ps(a, b); + m[3] = 0; + return _mm_set1_ps(vaddvq_f32(m)); + } +#endif + + float s = 0, c = 0; + float32x4_t f32a = vreinterpretq_f32_m128(a); + float32x4_t f32b = vreinterpretq_f32_m128(b); + + /* To improve the accuracy of floating-point summation, Kahan algorithm + * is used for each operation. + */ + if (imm & (1 << 4)) + sse2neon_kadd_f32(&s, &c, f32a[0] * f32b[0]); + if (imm & (1 << 5)) + sse2neon_kadd_f32(&s, &c, f32a[1] * f32b[1]); + if (imm & (1 << 6)) + sse2neon_kadd_f32(&s, &c, f32a[2] * f32b[2]); + if (imm & (1 << 7)) + sse2neon_kadd_f32(&s, &c, f32a[3] * f32b[3]); + s += c; + + float32x4_t res = { + (imm & 0x1) ? s : 0, + (imm & 0x2) ? s : 0, + (imm & 0x4) ? s : 0, + (imm & 0x8) ? s : 0, + }; + return vreinterpretq_m128_f32(res); +} + +/* Compare operations */ + +// Compares for less than +// https://msdn.microsoft.com/en-us/library/vstudio/f330yhc8(v=vs.100).aspx +FORCE_INLINE __m128 _mm_cmplt_ps(__m128 a, __m128 b) +{ + return vreinterpretq_m128_u32( + vcltq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b))); +} + +// Compares for less than +// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/fy94wye7(v=vs.100) +FORCE_INLINE __m128 _mm_cmplt_ss(__m128 a, __m128 b) +{ + return _mm_move_ss(a, _mm_cmplt_ps(a, b)); +} + +// Compares for greater than. +// +// r0 := (a0 > b0) ? 0xffffffff : 0x0 +// r1 := (a1 > b1) ? 0xffffffff : 0x0 +// r2 := (a2 > b2) ? 0xffffffff : 0x0 +// r3 := (a3 > b3) ? 0xffffffff : 0x0 +// +// https://msdn.microsoft.com/en-us/library/vstudio/11dy102s(v=vs.100).aspx +FORCE_INLINE __m128 _mm_cmpgt_ps(__m128 a, __m128 b) +{ + return vreinterpretq_m128_u32( + vcgtq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b))); +} + +// Compares for greater than. +// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/1xyyyy9e(v=vs.100) +FORCE_INLINE __m128 _mm_cmpgt_ss(__m128 a, __m128 b) +{ + return _mm_move_ss(a, _mm_cmpgt_ps(a, b)); +} + +// Compares for greater than or equal. +// https://msdn.microsoft.com/en-us/library/vstudio/fs813y2t(v=vs.100).aspx +FORCE_INLINE __m128 _mm_cmpge_ps(__m128 a, __m128 b) +{ + return vreinterpretq_m128_u32( + vcgeq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b))); +} + +// Compares for greater than or equal. +// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/kesh3ddc(v=vs.100) +FORCE_INLINE __m128 _mm_cmpge_ss(__m128 a, __m128 b) +{ + return _mm_move_ss(a, _mm_cmpge_ps(a, b)); +} + +// Compares for less than or equal. +// +// r0 := (a0 <= b0) ? 0xffffffff : 0x0 +// r1 := (a1 <= b1) ? 0xffffffff : 0x0 +// r2 := (a2 <= b2) ? 0xffffffff : 0x0 +// r3 := (a3 <= b3) ? 0xffffffff : 0x0 +// +// https://msdn.microsoft.com/en-us/library/vstudio/1s75w83z(v=vs.100).aspx +FORCE_INLINE __m128 _mm_cmple_ps(__m128 a, __m128 b) +{ + return vreinterpretq_m128_u32( + vcleq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b))); +} + +// Compares for less than or equal. +// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/a7x0hbhw(v=vs.100) +FORCE_INLINE __m128 _mm_cmple_ss(__m128 a, __m128 b) +{ + return _mm_move_ss(a, _mm_cmple_ps(a, b)); +} + +// Compares for equality. +// https://msdn.microsoft.com/en-us/library/vstudio/36aectz5(v=vs.100).aspx +FORCE_INLINE __m128 _mm_cmpeq_ps(__m128 a, __m128 b) +{ + return vreinterpretq_m128_u32( + vceqq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b))); +} + +// Compares for equality. +// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/k423z28e(v=vs.100) +FORCE_INLINE __m128 _mm_cmpeq_ss(__m128 a, __m128 b) +{ + return _mm_move_ss(a, _mm_cmpeq_ps(a, b)); +} + +// Compares for inequality. +// https://msdn.microsoft.com/en-us/library/sf44thbx(v=vs.100).aspx +FORCE_INLINE __m128 _mm_cmpneq_ps(__m128 a, __m128 b) +{ + return vreinterpretq_m128_u32(vmvnq_u32( + vceqq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b)))); +} + +// Compares for inequality. +// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/ekya8fh4(v=vs.100) +FORCE_INLINE __m128 _mm_cmpneq_ss(__m128 a, __m128 b) +{ + return _mm_move_ss(a, _mm_cmpneq_ps(a, b)); +} + +// Compares for not greater than or equal. +// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/wsexys62(v=vs.100) +FORCE_INLINE __m128 _mm_cmpnge_ps(__m128 a, __m128 b) +{ + return _mm_cmplt_ps(a, b); +} + +// Compares for not greater than or equal. +// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/fk2y80s8(v=vs.100) +FORCE_INLINE __m128 _mm_cmpnge_ss(__m128 a, __m128 b) +{ + return _mm_cmplt_ss(a, b); +} + +// Compares for not greater than. +// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/d0xh7w0s(v=vs.100) +FORCE_INLINE __m128 _mm_cmpngt_ps(__m128 a, __m128 b) +{ + return _mm_cmple_ps(a, b); +} + +// Compares for not greater than. +// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/z7x9ydwh(v=vs.100) +FORCE_INLINE __m128 _mm_cmpngt_ss(__m128 a, __m128 b) +{ + return _mm_cmple_ss(a, b); +} + +// Compares for not less than or equal. +// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/6a330kxw(v=vs.100) +FORCE_INLINE __m128 _mm_cmpnle_ps(__m128 a, __m128 b) +{ + return _mm_cmpgt_ps(a, b); +} + +// Compares for not less than or equal. +// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/z7x9ydwh(v=vs.100) +FORCE_INLINE __m128 _mm_cmpnle_ss(__m128 a, __m128 b) +{ + return _mm_cmpgt_ss(a, b); +} + +// Compares for not less than. +// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/4686bbdw(v=vs.100) +FORCE_INLINE __m128 _mm_cmpnlt_ps(__m128 a, __m128 b) +{ + return _mm_cmpge_ps(a, b); +} + +// Compares for not less than. +// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/56b9z2wf(v=vs.100) +FORCE_INLINE __m128 _mm_cmpnlt_ss(__m128 a, __m128 b) +{ + return _mm_cmpge_ss(a, b); +} + +// Compares the 16 signed or unsigned 8-bit integers in a and the 16 signed or +// unsigned 8-bit integers in b for equality. +// https://msdn.microsoft.com/en-us/library/windows/desktop/bz5xk21a(v=vs.90).aspx +FORCE_INLINE __m128i _mm_cmpeq_epi8(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_u8( + vceqq_s8(vreinterpretq_s8_m128i(a), vreinterpretq_s8_m128i(b))); +} + +// Compares the 8 signed or unsigned 16-bit integers in a and the 8 signed or +// unsigned 16-bit integers in b for equality. +// https://msdn.microsoft.com/en-us/library/2ay060te(v=vs.100).aspx +FORCE_INLINE __m128i _mm_cmpeq_epi16(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_u16( + vceqq_s16(vreinterpretq_s16_m128i(a), vreinterpretq_s16_m128i(b))); +} + +// Compare packed 32-bit integers in a and b for equality, and store the results +// in dst +FORCE_INLINE __m128i _mm_cmpeq_epi32(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_u32( + vceqq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b))); +} + +// Compare packed 64-bit integers in a and b for equality, and store the results +// in dst +FORCE_INLINE __m128i _mm_cmpeq_epi64(__m128i a, __m128i b) +{ +#if defined(__aarch64__) + return vreinterpretq_m128i_u64( + vceqq_u64(vreinterpretq_u64_m128i(a), vreinterpretq_u64_m128i(b))); +#else + // ARMv7 lacks vceqq_u64 + // (a == b) -> (a_lo == b_lo) && (a_hi == b_hi) + uint32x4_t cmp = + vceqq_u32(vreinterpretq_u32_m128i(a), vreinterpretq_u32_m128i(b)); + uint32x4_t swapped = vrev64q_u32(cmp); + return vreinterpretq_m128i_u32(vandq_u32(cmp, swapped)); +#endif +} + +// Compares the 16 signed 8-bit integers in a and the 16 signed 8-bit integers +// in b for lesser than. +// https://msdn.microsoft.com/en-us/library/windows/desktop/9s46csht(v=vs.90).aspx +FORCE_INLINE __m128i _mm_cmplt_epi8(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_u8( + vcltq_s8(vreinterpretq_s8_m128i(a), vreinterpretq_s8_m128i(b))); +} + +// Compares the 16 signed 8-bit integers in a and the 16 signed 8-bit integers +// in b for greater than. +// +// r0 := (a0 > b0) ? 0xff : 0x0 +// r1 := (a1 > b1) ? 0xff : 0x0 +// ... +// r15 := (a15 > b15) ? 0xff : 0x0 +// +// https://msdn.microsoft.com/zh-tw/library/wf45zt2b(v=vs.100).aspx +FORCE_INLINE __m128i _mm_cmpgt_epi8(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_u8( + vcgtq_s8(vreinterpretq_s8_m128i(a), vreinterpretq_s8_m128i(b))); +} + +// Compares the 8 signed 16-bit integers in a and the 8 signed 16-bit integers +// in b for less than. +// +// r0 := (a0 < b0) ? 0xffff : 0x0 +// r1 := (a1 < b1) ? 0xffff : 0x0 +// ... +// r7 := (a7 < b7) ? 0xffff : 0x0 +// +// https://technet.microsoft.com/en-us/library/t863edb2(v=vs.100).aspx +FORCE_INLINE __m128i _mm_cmplt_epi16(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_u16( + vcltq_s16(vreinterpretq_s16_m128i(a), vreinterpretq_s16_m128i(b))); +} + +// Compares the 8 signed 16-bit integers in a and the 8 signed 16-bit integers +// in b for greater than. +// +// r0 := (a0 > b0) ? 0xffff : 0x0 +// r1 := (a1 > b1) ? 0xffff : 0x0 +// ... +// r7 := (a7 > b7) ? 0xffff : 0x0 +// +// https://technet.microsoft.com/en-us/library/xd43yfsa(v=vs.100).aspx +FORCE_INLINE __m128i _mm_cmpgt_epi16(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_u16( + vcgtq_s16(vreinterpretq_s16_m128i(a), vreinterpretq_s16_m128i(b))); +} + + +// Compares the 4 signed 32-bit integers in a and the 4 signed 32-bit integers +// in b for less than. +// https://msdn.microsoft.com/en-us/library/vstudio/4ak0bf5d(v=vs.100).aspx +FORCE_INLINE __m128i _mm_cmplt_epi32(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_u32( + vcltq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b))); +} + +// Compares the 4 signed 32-bit integers in a and the 4 signed 32-bit integers +// in b for greater than. +// https://msdn.microsoft.com/en-us/library/vstudio/1s9f2z0y(v=vs.100).aspx +FORCE_INLINE __m128i _mm_cmpgt_epi32(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_u32( + vcgtq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b))); +} + +// Compares the 2 signed 64-bit integers in a and the 2 signed 64-bit integers +// in b for greater than. +FORCE_INLINE __m128i _mm_cmpgt_epi64(__m128i a, __m128i b) +{ +#if defined(__aarch64__) + return vreinterpretq_m128i_u64( + vcgtq_s64(vreinterpretq_s64_m128i(a), vreinterpretq_s64_m128i(b))); +#else + // ARMv7 lacks vcgtq_s64. + // This is based off of Clang's SSE2 polyfill: + // (a > b) -> ((a_hi > b_hi) || (a_lo > b_lo && a_hi == b_hi)) + + // Mask the sign bit out since we need a signed AND an unsigned comparison + // and it is ugly to try and split them. + int32x4_t mask = vreinterpretq_s32_s64(vdupq_n_s64(0x80000000ull)); + int32x4_t a_mask = veorq_s32(vreinterpretq_s32_m128i(a), mask); + int32x4_t b_mask = veorq_s32(vreinterpretq_s32_m128i(b), mask); + // Check if a > b + int64x2_t greater = vreinterpretq_s64_u32(vcgtq_s32(a_mask, b_mask)); + // Copy upper mask to lower mask + // a_hi > b_hi + int64x2_t gt_hi = vshrq_n_s64(greater, 63); + // Copy lower mask to upper mask + // a_lo > b_lo + int64x2_t gt_lo = vsliq_n_s64(greater, greater, 32); + // Compare for equality + int64x2_t equal = vreinterpretq_s64_u32(vceqq_s32(a_mask, b_mask)); + // Copy upper mask to lower mask + // a_hi == b_hi + int64x2_t eq_hi = vshrq_n_s64(equal, 63); + // a_hi > b_hi || (a_lo > b_lo && a_hi == b_hi) + int64x2_t ret = vorrq_s64(gt_hi, vandq_s64(gt_lo, eq_hi)); + return vreinterpretq_m128i_s64(ret); +#endif +} + +// Compares the four 32-bit floats in a and b to check if any values are NaN. +// Ordered compare between each value returns true for "orderable" and false for +// "not orderable" (NaN). +// https://msdn.microsoft.com/en-us/library/vstudio/0h9w00fx(v=vs.100).aspx see +// also: +// http://stackoverflow.com/questions/8627331/what-does-ordered-unordered-comparison-mean +// http://stackoverflow.com/questions/29349621/neon-isnanval-intrinsics +FORCE_INLINE __m128 _mm_cmpord_ps(__m128 a, __m128 b) +{ + // Note: NEON does not have ordered compare builtin + // Need to compare a eq a and b eq b to check for NaN + // Do AND of results to get final + uint32x4_t ceqaa = + vceqq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(a)); + uint32x4_t ceqbb = + vceqq_f32(vreinterpretq_f32_m128(b), vreinterpretq_f32_m128(b)); + return vreinterpretq_m128_u32(vandq_u32(ceqaa, ceqbb)); +} + +// Compares for ordered. +// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/343t62da(v=vs.100) +FORCE_INLINE __m128 _mm_cmpord_ss(__m128 a, __m128 b) +{ + return _mm_move_ss(a, _mm_cmpord_ps(a, b)); +} + +// Compares for unordered. +// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/khy6fk1t(v=vs.100) +FORCE_INLINE __m128 _mm_cmpunord_ps(__m128 a, __m128 b) +{ + uint32x4_t f32a = + vceqq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(a)); + uint32x4_t f32b = + vceqq_f32(vreinterpretq_f32_m128(b), vreinterpretq_f32_m128(b)); + return vreinterpretq_m128_u32(vmvnq_u32(vandq_u32(f32a, f32b))); +} + +// Compares for unordered. +// https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/2as2387b(v=vs.100) +FORCE_INLINE __m128 _mm_cmpunord_ss(__m128 a, __m128 b) +{ + return _mm_move_ss(a, _mm_cmpunord_ps(a, b)); +} + +// Compares the lower single-precision floating point scalar values of a and b +// using a less than operation. : +// https://msdn.microsoft.com/en-us/library/2kwe606b(v=vs.90).aspx Important +// note!! The documentation on MSDN is incorrect! If either of the values is a +// NAN the docs say you will get a one, but in fact, it will return a zero!! +FORCE_INLINE int _mm_comilt_ss(__m128 a, __m128 b) +{ + uint32x4_t a_not_nan = + vceqq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(a)); + uint32x4_t b_not_nan = + vceqq_f32(vreinterpretq_f32_m128(b), vreinterpretq_f32_m128(b)); + uint32x4_t a_and_b_not_nan = vandq_u32(a_not_nan, b_not_nan); + uint32x4_t a_lt_b = + vcltq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b)); + return (vgetq_lane_u32(vandq_u32(a_and_b_not_nan, a_lt_b), 0) != 0) ? 1 : 0; +} + +// Compares the lower single-precision floating point scalar values of a and b +// using a greater than operation. : +// https://msdn.microsoft.com/en-us/library/b0738e0t(v=vs.100).aspx +FORCE_INLINE int _mm_comigt_ss(__m128 a, __m128 b) +{ + // return vgetq_lane_u32(vcgtq_f32(vreinterpretq_f32_m128(a), + // vreinterpretq_f32_m128(b)), 0); + uint32x4_t a_not_nan = + vceqq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(a)); + uint32x4_t b_not_nan = + vceqq_f32(vreinterpretq_f32_m128(b), vreinterpretq_f32_m128(b)); + uint32x4_t a_and_b_not_nan = vandq_u32(a_not_nan, b_not_nan); + uint32x4_t a_gt_b = + vcgtq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b)); + return (vgetq_lane_u32(vandq_u32(a_and_b_not_nan, a_gt_b), 0) != 0) ? 1 : 0; +} + +// Compares the lower single-precision floating point scalar values of a and b +// using a less than or equal operation. : +// https://msdn.microsoft.com/en-us/library/1w4t7c57(v=vs.90).aspx +FORCE_INLINE int _mm_comile_ss(__m128 a, __m128 b) +{ + // return vgetq_lane_u32(vcleq_f32(vreinterpretq_f32_m128(a), + // vreinterpretq_f32_m128(b)), 0); + uint32x4_t a_not_nan = + vceqq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(a)); + uint32x4_t b_not_nan = + vceqq_f32(vreinterpretq_f32_m128(b), vreinterpretq_f32_m128(b)); + uint32x4_t a_and_b_not_nan = vandq_u32(a_not_nan, b_not_nan); + uint32x4_t a_le_b = + vcleq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b)); + return (vgetq_lane_u32(vandq_u32(a_and_b_not_nan, a_le_b), 0) != 0) ? 1 : 0; +} + +// Compares the lower single-precision floating point scalar values of a and b +// using a greater than or equal operation. : +// https://msdn.microsoft.com/en-us/library/8t80des6(v=vs.100).aspx +FORCE_INLINE int _mm_comige_ss(__m128 a, __m128 b) +{ + // return vgetq_lane_u32(vcgeq_f32(vreinterpretq_f32_m128(a), + // vreinterpretq_f32_m128(b)), 0); + uint32x4_t a_not_nan = + vceqq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(a)); + uint32x4_t b_not_nan = + vceqq_f32(vreinterpretq_f32_m128(b), vreinterpretq_f32_m128(b)); + uint32x4_t a_and_b_not_nan = vandq_u32(a_not_nan, b_not_nan); + uint32x4_t a_ge_b = + vcgeq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b)); + return (vgetq_lane_u32(vandq_u32(a_and_b_not_nan, a_ge_b), 0) != 0) ? 1 : 0; +} + +// Compares the lower single-precision floating point scalar values of a and b +// using an equality operation. : +// https://msdn.microsoft.com/en-us/library/93yx2h2b(v=vs.100).aspx +FORCE_INLINE int _mm_comieq_ss(__m128 a, __m128 b) +{ + // return vgetq_lane_u32(vceqq_f32(vreinterpretq_f32_m128(a), + // vreinterpretq_f32_m128(b)), 0); + uint32x4_t a_not_nan = + vceqq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(a)); + uint32x4_t b_not_nan = + vceqq_f32(vreinterpretq_f32_m128(b), vreinterpretq_f32_m128(b)); + uint32x4_t a_and_b_not_nan = vandq_u32(a_not_nan, b_not_nan); + uint32x4_t a_eq_b = + vceqq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b)); + return (vgetq_lane_u32(vandq_u32(a_and_b_not_nan, a_eq_b), 0) != 0) ? 1 : 0; +} + +// Compares the lower single-precision floating point scalar values of a and b +// using an inequality operation. : +// https://msdn.microsoft.com/en-us/library/bafh5e0a(v=vs.90).aspx +FORCE_INLINE int _mm_comineq_ss(__m128 a, __m128 b) +{ + // return !vgetq_lane_u32(vceqq_f32(vreinterpretq_f32_m128(a), + // vreinterpretq_f32_m128(b)), 0); + uint32x4_t a_not_nan = + vceqq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(a)); + uint32x4_t b_not_nan = + vceqq_f32(vreinterpretq_f32_m128(b), vreinterpretq_f32_m128(b)); + uint32x4_t a_or_b_nan = vmvnq_u32(vandq_u32(a_not_nan, b_not_nan)); + uint32x4_t a_neq_b = vmvnq_u32( + vceqq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b))); + return (vgetq_lane_u32(vorrq_u32(a_or_b_nan, a_neq_b), 0) != 0) ? 1 : 0; +} + +// according to the documentation, these intrinsics behave the same as the +// non-'u' versions. We'll just alias them here. +#define _mm_ucomilt_ss _mm_comilt_ss +#define _mm_ucomile_ss _mm_comile_ss +#define _mm_ucomigt_ss _mm_comigt_ss +#define _mm_ucomige_ss _mm_comige_ss +#define _mm_ucomieq_ss _mm_comieq_ss +#define _mm_ucomineq_ss _mm_comineq_ss + +/* Conversions */ + +// Convert packed signed 32-bit integers in b to packed single-precision +// (32-bit) floating-point elements, store the results in the lower 2 elements +// of dst, and copy the upper 2 packed elements from a to the upper elements of +// dst. +// +// dst[31:0] := Convert_Int32_To_FP32(b[31:0]) +// dst[63:32] := Convert_Int32_To_FP32(b[63:32]) +// dst[95:64] := a[95:64] +// dst[127:96] := a[127:96] +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvt_pi2ps +FORCE_INLINE __m128 _mm_cvt_pi2ps(__m128 a, __m64 b) +{ + return vreinterpretq_m128_f32( + vcombine_f32(vcvt_f32_s32(vreinterpret_s32_m64(b)), + vget_high_f32(vreinterpretq_f32_m128(a)))); +} + +// Convert the signed 32-bit integer b to a single-precision (32-bit) +// floating-point element, store the result in the lower element of dst, and +// copy the upper 3 packed elements from a to the upper elements of dst. +// +// dst[31:0] := Convert_Int32_To_FP32(b[31:0]) +// dst[127:32] := a[127:32] +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvt_si2ss +FORCE_INLINE __m128 _mm_cvt_si2ss(__m128 a, int b) +{ + return vreinterpretq_m128_f32( + vsetq_lane_f32((float) b, vreinterpretq_f32_m128(a), 0)); +} + +// Convert the signed 32-bit integer b to a single-precision (32-bit) +// floating-point element, store the result in the lower element of dst, and +// copy the upper 3 packed elements from a to the upper elements of dst. +// +// dst[31:0] := Convert_Int32_To_FP32(b[31:0]) +// dst[127:32] := a[127:32] +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtsi32_ss +#define _mm_cvtsi32_ss(a, b) _mm_cvt_si2ss(a, b) + +// Convert the signed 64-bit integer b to a single-precision (32-bit) +// floating-point element, store the result in the lower element of dst, and +// copy the upper 3 packed elements from a to the upper elements of dst. +// +// dst[31:0] := Convert_Int64_To_FP32(b[63:0]) +// dst[127:32] := a[127:32] +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtsi64_ss +FORCE_INLINE __m128 _mm_cvtsi64_ss(__m128 a, int64_t b) +{ + return vreinterpretq_m128_f32( + vsetq_lane_f32((float) b, vreinterpretq_f32_m128(a), 0)); +} + +// Convert the lower single-precision (32-bit) floating-point element in a to a +// 32-bit integer, and store the result in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvt_ss2si +FORCE_INLINE int _mm_cvt_ss2si(__m128 a) +{ +#if defined(__aarch64__) + return vgetq_lane_s32(vcvtnq_s32_f32(vreinterpretq_f32_m128(a)), 0); +#else + float32_t data = vgetq_lane_f32(vreinterpretq_f32_m128(a), 0); + float32_t diff = data - floor(data); + if (diff > 0.5) + return (int32_t) ceil(data); + if (diff == 0.5) { + int32_t f = (int32_t) floor(data); + int32_t c = (int32_t) ceil(data); + return c & 1 ? f : c; + } + return (int32_t) floor(data); +#endif +} + +// Convert packed 16-bit integers in a to packed single-precision (32-bit) +// floating-point elements, and store the results in dst. +// +// FOR j := 0 to 3 +// i := j*16 +// m := j*32 +// dst[m+31:m] := Convert_Int16_To_FP32(a[i+15:i]) +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtpi16_ps +FORCE_INLINE __m128 _mm_cvtpi16_ps(__m64 a) +{ + return vreinterpretq_m128_f32( + vcvtq_f32_s32(vmovl_s16(vreinterpret_s16_m64(a)))); +} + +// Convert packed 32-bit integers in b to packed single-precision (32-bit) +// floating-point elements, store the results in the lower 2 elements of dst, +// and copy the upper 2 packed elements from a to the upper elements of dst. +// +// dst[31:0] := Convert_Int32_To_FP32(b[31:0]) +// dst[63:32] := Convert_Int32_To_FP32(b[63:32]) +// dst[95:64] := a[95:64] +// dst[127:96] := a[127:96] +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtpi32_ps +FORCE_INLINE __m128 _mm_cvtpi32_ps(__m128 a, __m64 b) +{ + return vreinterpretq_m128_f32( + vcombine_f32(vcvt_f32_s32(vreinterpret_s32_m64(b)), + vget_high_f32(vreinterpretq_f32_m128(a)))); +} + +// Convert packed signed 32-bit integers in a to packed single-precision +// (32-bit) floating-point elements, store the results in the lower 2 elements +// of dst, then covert the packed signed 32-bit integers in b to +// single-precision (32-bit) floating-point element, and store the results in +// the upper 2 elements of dst. +// +// dst[31:0] := Convert_Int32_To_FP32(a[31:0]) +// dst[63:32] := Convert_Int32_To_FP32(a[63:32]) +// dst[95:64] := Convert_Int32_To_FP32(b[31:0]) +// dst[127:96] := Convert_Int32_To_FP32(b[63:32]) +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtpi32x2_ps +FORCE_INLINE __m128 _mm_cvtpi32x2_ps(__m64 a, __m64 b) +{ + return vreinterpretq_m128_f32(vcvtq_f32_s32( + vcombine_s32(vreinterpret_s32_m64(a), vreinterpret_s32_m64(b)))); +} + +// Convert the lower packed 8-bit integers in a to packed single-precision +// (32-bit) floating-point elements, and store the results in dst. +// +// FOR j := 0 to 3 +// i := j*8 +// m := j*32 +// dst[m+31:m] := Convert_Int8_To_FP32(a[i+7:i]) +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtpi8_ps +FORCE_INLINE __m128 _mm_cvtpi8_ps(__m64 a) +{ + return vreinterpretq_m128_f32(vcvtq_f32_s32( + vmovl_s16(vget_low_s16(vmovl_s8(vreinterpret_s8_m64(a)))))); +} + +// Convert packed unsigned 16-bit integers in a to packed single-precision +// (32-bit) floating-point elements, and store the results in dst. +// +// FOR j := 0 to 3 +// i := j*16 +// m := j*32 +// dst[m+31:m] := Convert_UInt16_To_FP32(a[i+15:i]) +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtpu16_ps +FORCE_INLINE __m128 _mm_cvtpu16_ps(__m64 a) +{ + return vreinterpretq_m128_f32( + vcvtq_f32_u32(vmovl_u16(vreinterpret_u16_m64(a)))); +} + +// Convert the lower packed unsigned 8-bit integers in a to packed +// single-precision (32-bit) floating-point elements, and store the results in +// dst. +// +// FOR j := 0 to 3 +// i := j*8 +// m := j*32 +// dst[m+31:m] := Convert_UInt8_To_FP32(a[i+7:i]) +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtpu8_ps +FORCE_INLINE __m128 _mm_cvtpu8_ps(__m64 a) +{ + return vreinterpretq_m128_f32(vcvtq_f32_u32( + vmovl_u16(vget_low_u16(vmovl_u8(vreinterpret_u8_m64(a)))))); +} + +// Converts the four single-precision, floating-point values of a to signed +// 32-bit integer values using truncate. +// https://msdn.microsoft.com/en-us/library/vstudio/1h005y6x(v=vs.100).aspx +FORCE_INLINE __m128i _mm_cvttps_epi32(__m128 a) +{ + return vreinterpretq_m128i_s32(vcvtq_s32_f32(vreinterpretq_f32_m128(a))); +} + +// Convert the lower double-precision (64-bit) floating-point element in a to a +// 64-bit integer with truncation, and store the result in dst. +// +// dst[63:0] := Convert_FP64_To_Int64_Truncate(a[63:0]) +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvttsd_si64 +FORCE_INLINE int64_t _mm_cvttsd_si64(__m128d a) +{ +#if defined(__aarch64__) + return vgetq_lane_s64(vcvtq_s64_f64(vreinterpretq_f64_m128d(a)), 0); +#else + double ret = *((double *) &a); + return (int64_t) ret; +#endif +} + +// Convert the lower double-precision (64-bit) floating-point element in a to a +// 64-bit integer with truncation, and store the result in dst. +// +// dst[63:0] := Convert_FP64_To_Int64_Truncate(a[63:0]) +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvttsd_si64x +#define _mm_cvttsd_si64x(a) _mm_cvttsd_si64(a) + +// Converts the four signed 32-bit integer values of a to single-precision, +// floating-point values +// https://msdn.microsoft.com/en-us/library/vstudio/36bwxcx5(v=vs.100).aspx +FORCE_INLINE __m128 _mm_cvtepi32_ps(__m128i a) +{ + return vreinterpretq_m128_f32(vcvtq_f32_s32(vreinterpretq_s32_m128i(a))); +} + +// Converts the four unsigned 8-bit integers in the lower 16 bits to four +// unsigned 32-bit integers. +FORCE_INLINE __m128i _mm_cvtepu8_epi16(__m128i a) +{ + uint8x16_t u8x16 = vreinterpretq_u8_m128i(a); /* xxxx xxxx xxxx DCBA */ + uint16x8_t u16x8 = vmovl_u8(vget_low_u8(u8x16)); /* 0x0x 0x0x 0D0C 0B0A */ + return vreinterpretq_m128i_u16(u16x8); +} + +// Converts the four unsigned 8-bit integers in the lower 32 bits to four +// unsigned 32-bit integers. +// https://msdn.microsoft.com/en-us/library/bb531467%28v=vs.100%29.aspx +FORCE_INLINE __m128i _mm_cvtepu8_epi32(__m128i a) +{ + uint8x16_t u8x16 = vreinterpretq_u8_m128i(a); /* xxxx xxxx xxxx DCBA */ + uint16x8_t u16x8 = vmovl_u8(vget_low_u8(u8x16)); /* 0x0x 0x0x 0D0C 0B0A */ + uint32x4_t u32x4 = vmovl_u16(vget_low_u16(u16x8)); /* 000D 000C 000B 000A */ + return vreinterpretq_m128i_u32(u32x4); +} + +// Converts the two unsigned 8-bit integers in the lower 16 bits to two +// unsigned 64-bit integers. +FORCE_INLINE __m128i _mm_cvtepu8_epi64(__m128i a) +{ + uint8x16_t u8x16 = vreinterpretq_u8_m128i(a); /* xxxx xxxx xxxx xxBA */ + uint16x8_t u16x8 = vmovl_u8(vget_low_u8(u8x16)); /* 0x0x 0x0x 0x0x 0B0A */ + uint32x4_t u32x4 = vmovl_u16(vget_low_u16(u16x8)); /* 000x 000x 000B 000A */ + uint64x2_t u64x2 = vmovl_u32(vget_low_u32(u32x4)); /* 0000 000B 0000 000A */ + return vreinterpretq_m128i_u64(u64x2); +} + +// Converts the four unsigned 8-bit integers in the lower 16 bits to four +// unsigned 32-bit integers. +FORCE_INLINE __m128i _mm_cvtepi8_epi16(__m128i a) +{ + int8x16_t s8x16 = vreinterpretq_s8_m128i(a); /* xxxx xxxx xxxx DCBA */ + int16x8_t s16x8 = vmovl_s8(vget_low_s8(s8x16)); /* 0x0x 0x0x 0D0C 0B0A */ + return vreinterpretq_m128i_s16(s16x8); +} + +// Converts the four unsigned 8-bit integers in the lower 32 bits to four +// unsigned 32-bit integers. +FORCE_INLINE __m128i _mm_cvtepi8_epi32(__m128i a) +{ + int8x16_t s8x16 = vreinterpretq_s8_m128i(a); /* xxxx xxxx xxxx DCBA */ + int16x8_t s16x8 = vmovl_s8(vget_low_s8(s8x16)); /* 0x0x 0x0x 0D0C 0B0A */ + int32x4_t s32x4 = vmovl_s16(vget_low_s16(s16x8)); /* 000D 000C 000B 000A */ + return vreinterpretq_m128i_s32(s32x4); +} + +// Converts the two signed 8-bit integers in the lower 32 bits to four +// signed 64-bit integers. +FORCE_INLINE __m128i _mm_cvtepi8_epi64(__m128i a) +{ + int8x16_t s8x16 = vreinterpretq_s8_m128i(a); /* xxxx xxxx xxxx xxBA */ + int16x8_t s16x8 = vmovl_s8(vget_low_s8(s8x16)); /* 0x0x 0x0x 0x0x 0B0A */ + int32x4_t s32x4 = vmovl_s16(vget_low_s16(s16x8)); /* 000x 000x 000B 000A */ + int64x2_t s64x2 = vmovl_s32(vget_low_s32(s32x4)); /* 0000 000B 0000 000A */ + return vreinterpretq_m128i_s64(s64x2); +} + +// Converts the four signed 16-bit integers in the lower 64 bits to four signed +// 32-bit integers. +FORCE_INLINE __m128i _mm_cvtepi16_epi32(__m128i a) +{ + return vreinterpretq_m128i_s32( + vmovl_s16(vget_low_s16(vreinterpretq_s16_m128i(a)))); +} + +// Converts the two signed 16-bit integers in the lower 32 bits two signed +// 32-bit integers. +FORCE_INLINE __m128i _mm_cvtepi16_epi64(__m128i a) +{ + int16x8_t s16x8 = vreinterpretq_s16_m128i(a); /* xxxx xxxx xxxx 0B0A */ + int32x4_t s32x4 = vmovl_s16(vget_low_s16(s16x8)); /* 000x 000x 000B 000A */ + int64x2_t s64x2 = vmovl_s32(vget_low_s32(s32x4)); /* 0000 000B 0000 000A */ + return vreinterpretq_m128i_s64(s64x2); +} + +// Converts the four unsigned 16-bit integers in the lower 64 bits to four +// unsigned 32-bit integers. +FORCE_INLINE __m128i _mm_cvtepu16_epi32(__m128i a) +{ + return vreinterpretq_m128i_u32( + vmovl_u16(vget_low_u16(vreinterpretq_u16_m128i(a)))); +} + +// Converts the two unsigned 16-bit integers in the lower 32 bits to two +// unsigned 64-bit integers. +FORCE_INLINE __m128i _mm_cvtepu16_epi64(__m128i a) +{ + uint16x8_t u16x8 = vreinterpretq_u16_m128i(a); /* xxxx xxxx xxxx 0B0A */ + uint32x4_t u32x4 = vmovl_u16(vget_low_u16(u16x8)); /* 000x 000x 000B 000A */ + uint64x2_t u64x2 = vmovl_u32(vget_low_u32(u32x4)); /* 0000 000B 0000 000A */ + return vreinterpretq_m128i_u64(u64x2); +} + +// Converts the two unsigned 32-bit integers in the lower 64 bits to two +// unsigned 64-bit integers. +FORCE_INLINE __m128i _mm_cvtepu32_epi64(__m128i a) +{ + return vreinterpretq_m128i_u64( + vmovl_u32(vget_low_u32(vreinterpretq_u32_m128i(a)))); +} + +// Converts the two signed 32-bit integers in the lower 64 bits to two signed +// 64-bit integers. +FORCE_INLINE __m128i _mm_cvtepi32_epi64(__m128i a) +{ + return vreinterpretq_m128i_s64( + vmovl_s32(vget_low_s32(vreinterpretq_s32_m128i(a)))); +} + +// Converts the four single-precision, floating-point values of a to signed +// 32-bit integer values. +// +// r0 := (int) a0 +// r1 := (int) a1 +// r2 := (int) a2 +// r3 := (int) a3 +// +// https://msdn.microsoft.com/en-us/library/vstudio/xdc42k5e(v=vs.100).aspx +// *NOTE*. The default rounding mode on SSE is 'round to even', which ARMv7-A +// does not support! It is supported on ARMv8-A however. +FORCE_INLINE __m128i _mm_cvtps_epi32(__m128 a) +{ +#if defined(__aarch64__) + return vreinterpretq_m128i_s32(vcvtnq_s32_f32(a)); +#else + uint32x4_t signmask = vdupq_n_u32(0x80000000); + float32x4_t half = vbslq_f32(signmask, vreinterpretq_f32_m128(a), + vdupq_n_f32(0.5f)); /* +/- 0.5 */ + int32x4_t r_normal = vcvtq_s32_f32(vaddq_f32( + vreinterpretq_f32_m128(a), half)); /* round to integer: [a + 0.5]*/ + int32x4_t r_trunc = + vcvtq_s32_f32(vreinterpretq_f32_m128(a)); /* truncate to integer: [a] */ + int32x4_t plusone = vreinterpretq_s32_u32(vshrq_n_u32( + vreinterpretq_u32_s32(vnegq_s32(r_trunc)), 31)); /* 1 or 0 */ + int32x4_t r_even = vbicq_s32(vaddq_s32(r_trunc, plusone), + vdupq_n_s32(1)); /* ([a] + {0,1}) & ~1 */ + float32x4_t delta = vsubq_f32( + vreinterpretq_f32_m128(a), + vcvtq_f32_s32(r_trunc)); /* compute delta: delta = (a - [a]) */ + uint32x4_t is_delta_half = vceqq_f32(delta, half); /* delta == +/- 0.5 */ + return vreinterpretq_m128i_s32(vbslq_s32(is_delta_half, r_even, r_normal)); +#endif +} + +// Copy the lower 32-bit integer in a to dst. +// +// dst[31:0] := a[31:0] +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtsi128_si32 +FORCE_INLINE int _mm_cvtsi128_si32(__m128i a) +{ + return vgetq_lane_s32(vreinterpretq_s32_m128i(a), 0); +} + +// Copy the lower 64-bit integer in a to dst. +// +// dst[63:0] := a[63:0] +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtsi128_si64 +FORCE_INLINE int64_t _mm_cvtsi128_si64(__m128i a) +{ + return vgetq_lane_s64(vreinterpretq_s64_m128i(a), 0); +} + +// Copy the lower 64-bit integer in a to dst. +// +// dst[63:0] := a[63:0] +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtsi128_si64x +#define _mm_cvtsi128_si64x(a) _mm_cvtsi128_si64(a) + +// Moves 32-bit integer a to the least significant 32 bits of an __m128 object, +// zero extending the upper bits. +// +// r0 := a +// r1 := 0x0 +// r2 := 0x0 +// r3 := 0x0 +// +// https://msdn.microsoft.com/en-us/library/ct3539ha%28v=vs.90%29.aspx +FORCE_INLINE __m128i _mm_cvtsi32_si128(int a) +{ + return vreinterpretq_m128i_s32(vsetq_lane_s32(a, vdupq_n_s32(0), 0)); +} + +// Moves 64-bit integer a to the least significant 64 bits of an __m128 object, +// zero extending the upper bits. +// +// r0 := a +// r1 := 0x0 +FORCE_INLINE __m128i _mm_cvtsi64_si128(int64_t a) +{ + return vreinterpretq_m128i_s64(vsetq_lane_s64(a, vdupq_n_s64(0), 0)); +} + +// Cast vector of type __m128 to type __m128d. This intrinsic is only used for +// compilation and does not generate any instructions, thus it has zero latency. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_castps_pd +FORCE_INLINE __m128d _mm_castps_pd(__m128 a) +{ + return vreinterpretq_m128d_s32(vreinterpretq_s32_m128(a)); +} + +// Applies a type cast to reinterpret four 32-bit floating point values passed +// in as a 128-bit parameter as packed 32-bit integers. +// https://msdn.microsoft.com/en-us/library/bb514099.aspx +FORCE_INLINE __m128i _mm_castps_si128(__m128 a) +{ + return vreinterpretq_m128i_s32(vreinterpretq_s32_m128(a)); +} + +// Applies a type cast to reinterpret four 32-bit integers passed in as a +// 128-bit parameter as packed 32-bit floating point values. +// https://msdn.microsoft.com/en-us/library/bb514029.aspx +FORCE_INLINE __m128 _mm_castsi128_ps(__m128i a) +{ + return vreinterpretq_m128_s32(vreinterpretq_s32_m128i(a)); +} + +// Loads 128-bit value. : +// https://msdn.microsoft.com/en-us/library/atzzad1h(v=vs.80).aspx +FORCE_INLINE __m128i _mm_load_si128(const __m128i *p) +{ + return vreinterpretq_m128i_s32(vld1q_s32((const int32_t *) p)); +} + +// Load a double-precision (64-bit) floating-point element from memory into both +// elements of dst. +// +// dst[63:0] := MEM[mem_addr+63:mem_addr] +// dst[127:64] := MEM[mem_addr+63:mem_addr] +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_load1_pd +FORCE_INLINE __m128d _mm_load1_pd(const double *p) +{ +#if defined(__aarch64__) + return vreinterpretq_m128d_f64(vld1q_dup_f64(p)); +#else + return vreinterpretq_m128d_s64(vdupq_n_s64(*(const int64_t *) p)); +#endif +} + +// Load a double-precision (64-bit) floating-point element from memory into the +// upper element of dst, and copy the lower element from a to dst. mem_addr does +// not need to be aligned on any particular boundary. +// +// dst[63:0] := a[63:0] +// dst[127:64] := MEM[mem_addr+63:mem_addr] +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_loadh_pd +FORCE_INLINE __m128d _mm_loadh_pd(__m128d a, const double *p) +{ +#if defined(__aarch64__) + return vreinterpretq_m128d_f64( + vcombine_f64(vget_low_f64(vreinterpretq_f64_m128d(a)), vld1_f64(p))); +#else + return vreinterpretq_m128d_f32(vcombine_f32( + vget_low_f32(vreinterpretq_f32_m128d(a)), vld1_f32((const float *) p))); +#endif +} + +// Load a double-precision (64-bit) floating-point element from memory into both +// elements of dst. +// +// dst[63:0] := MEM[mem_addr+63:mem_addr] +// dst[127:64] := MEM[mem_addr+63:mem_addr] +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_load_pd1 +#define _mm_load_pd1 _mm_load1_pd + +// Load a double-precision (64-bit) floating-point element from memory into both +// elements of dst. +// +// dst[63:0] := MEM[mem_addr+63:mem_addr] +// dst[127:64] := MEM[mem_addr+63:mem_addr] +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_loaddup_pd +#define _mm_loaddup_pd _mm_load1_pd + +// Loads 128-bit value. : +// https://msdn.microsoft.com/zh-cn/library/f4k12ae8(v=vs.90).aspx +FORCE_INLINE __m128i _mm_loadu_si128(const __m128i *p) +{ + return vreinterpretq_m128i_s32(vld1q_s32((const int32_t *) p)); +} + +// Load unaligned 32-bit integer from memory into the first element of dst. +// +// dst[31:0] := MEM[mem_addr+31:mem_addr] +// dst[MAX:32] := 0 +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_loadu_si32 +FORCE_INLINE __m128i _mm_loadu_si32(const void *p) +{ + return vreinterpretq_m128i_s32( + vsetq_lane_s32(*(const int32_t *) p, vdupq_n_s32(0), 0)); +} + +// Convert packed double-precision (64-bit) floating-point elements in a to +// packed single-precision (32-bit) floating-point elements, and store the +// results in dst. +// +// FOR j := 0 to 1 +// i := 32*j +// k := 64*j +// dst[i+31:i] := Convert_FP64_To_FP32(a[k+64:k]) +// ENDFOR +// dst[127:64] := 0 +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtpd_ps +FORCE_INLINE __m128 _mm_cvtpd_ps(__m128d a) +{ +#if defined(__aarch64__) + float32x2_t tmp = vcvt_f32_f64(vreinterpretq_f64_m128d(a)); + return vreinterpretq_m128_f32(vcombine_f32(tmp, vdup_n_f32(0))); +#else + float a0 = (float) ((double *) &a)[0]; + float a1 = (float) ((double *) &a)[1]; + return _mm_set_ps(0, 0, a1, a0); +#endif +} + +// Copy the lower double-precision (64-bit) floating-point element of a to dst. +// +// dst[63:0] := a[63:0] +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtsd_f64 +FORCE_INLINE double _mm_cvtsd_f64(__m128d a) +{ +#if defined(__aarch64__) + return (double) vgetq_lane_f64(vreinterpretq_f64_m128d(a), 0); +#else + return ((double *) &a)[0]; +#endif +} + +// Convert packed single-precision (32-bit) floating-point elements in a to +// packed double-precision (64-bit) floating-point elements, and store the +// results in dst. +// +// FOR j := 0 to 1 +// i := 64*j +// k := 32*j +// dst[i+63:i] := Convert_FP32_To_FP64(a[k+31:k]) +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvtps_pd +FORCE_INLINE __m128d _mm_cvtps_pd(__m128 a) +{ +#if defined(__aarch64__) + return vreinterpretq_m128d_f64( + vcvt_f64_f32(vget_low_f32(vreinterpretq_f32_m128(a)))); +#else + double a0 = (double) vgetq_lane_f32(vreinterpretq_f32_m128(a), 0); + double a1 = (double) vgetq_lane_f32(vreinterpretq_f32_m128(a), 1); + return _mm_set_pd(a1, a0); +#endif +} + +// Cast vector of type __m128d to type __m128i. This intrinsic is only used for +// compilation and does not generate any instructions, thus it has zero latency. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_castpd_si128 +FORCE_INLINE __m128i _mm_castpd_si128(__m128d a) +{ + return vreinterpretq_m128i_s64(vreinterpretq_s64_m128d(a)); +} + +// Blend packed single-precision (32-bit) floating-point elements from a and b +// using mask, and store the results in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_blendv_ps +FORCE_INLINE __m128 _mm_blendv_ps(__m128 a, __m128 b, __m128 mask) +{ + return vreinterpretq_m128_f32(vbslq_f32(vreinterpretq_u32_m128(mask), + vreinterpretq_f32_m128(b), + vreinterpretq_f32_m128(a))); +} + +// Round the packed single-precision (32-bit) floating-point elements in a using +// the rounding parameter, and store the results as packed single-precision +// floating-point elements in dst. +// software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_round_ps +FORCE_INLINE __m128 _mm_round_ps(__m128 a, int rounding) +{ +#if defined(__aarch64__) + switch (rounding) { + case (_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC): + return vreinterpretq_m128_f32(vrndnq_f32(vreinterpretq_f32_m128(a))); + case (_MM_FROUND_TO_NEG_INF | _MM_FROUND_NO_EXC): + return vreinterpretq_m128_f32(vrndmq_f32(vreinterpretq_f32_m128(a))); + case (_MM_FROUND_TO_POS_INF | _MM_FROUND_NO_EXC): + return vreinterpretq_m128_f32(vrndpq_f32(vreinterpretq_f32_m128(a))); + case (_MM_FROUND_TO_ZERO | _MM_FROUND_NO_EXC): + return vreinterpretq_m128_f32(vrndq_f32(vreinterpretq_f32_m128(a))); + default: //_MM_FROUND_CUR_DIRECTION + return vreinterpretq_m128_f32(vrndiq_f32(vreinterpretq_f32_m128(a))); + } +#else + float *v_float = (float *) &a; + __m128 zero, neg_inf, pos_inf; + + switch (rounding) { + case (_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC): + return _mm_cvtepi32_ps(_mm_cvtps_epi32(a)); + case (_MM_FROUND_TO_NEG_INF | _MM_FROUND_NO_EXC): + return (__m128){floorf(v_float[0]), floorf(v_float[1]), + floorf(v_float[2]), floorf(v_float[3])}; + case (_MM_FROUND_TO_POS_INF | _MM_FROUND_NO_EXC): + return (__m128){ceilf(v_float[0]), ceilf(v_float[1]), ceilf(v_float[2]), + ceilf(v_float[3])}; + case (_MM_FROUND_TO_ZERO | _MM_FROUND_NO_EXC): + zero = _mm_set_ps(0.0f, 0.0f, 0.0f, 0.0f); + neg_inf = _mm_set_ps(floorf(v_float[0]), floorf(v_float[1]), + floorf(v_float[2]), floorf(v_float[3])); + pos_inf = _mm_set_ps(ceilf(v_float[0]), ceilf(v_float[1]), + ceilf(v_float[2]), ceilf(v_float[3])); + return _mm_blendv_ps(pos_inf, neg_inf, _mm_cmple_ps(a, zero)); + default: //_MM_FROUND_CUR_DIRECTION + return (__m128){roundf(v_float[0]), roundf(v_float[1]), + roundf(v_float[2]), roundf(v_float[3])}; + } +#endif +} + +// Convert packed single-precision (32-bit) floating-point elements in a to +// packed 32-bit integers, and store the results in dst. +// +// FOR j := 0 to 1 +// i := 32*j +// dst[i+31:i] := Convert_FP32_To_Int32(a[i+31:i]) +// ENDFOR +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_cvt_ps2pi +FORCE_INLINE __m64 _mm_cvt_ps2pi(__m128 a) +{ +#if defined(__aarch64__) + return vreinterpret_m64_s32( + vget_low_s32(vcvtnq_s32_f32(vreinterpretq_f32_m128(a)))); +#else + return vreinterpret_m64_s32( + vcvt_s32_f32(vget_low_f32(vreinterpretq_f32_m128( + _mm_round_ps(a, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC))))); +#endif +} + +// Round the packed single-precision (32-bit) floating-point elements in a up to +// an integer value, and store the results as packed single-precision +// floating-point elements in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_ceil_ps +FORCE_INLINE __m128 _mm_ceil_ps(__m128 a) +{ + return _mm_round_ps(a, _MM_FROUND_TO_POS_INF | _MM_FROUND_NO_EXC); +} + +// Round the packed single-precision (32-bit) floating-point elements in a down +// to an integer value, and store the results as packed single-precision +// floating-point elements in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_floor_ps +FORCE_INLINE __m128 _mm_floor_ps(__m128 a) +{ + return _mm_round_ps(a, _MM_FROUND_TO_NEG_INF | _MM_FROUND_NO_EXC); +} + + +// Load 128-bits of integer data from unaligned memory into dst. This intrinsic +// may perform better than _mm_loadu_si128 when the data crosses a cache line +// boundary. +// +// dst[127:0] := MEM[mem_addr+127:mem_addr] +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_lddqu_si128 +#define _mm_lddqu_si128 _mm_loadu_si128 + +/* Miscellaneous Operations */ + +// Shifts the 8 signed 16-bit integers in a right by count bits while shifting +// in the sign bit. +// +// r0 := a0 >> count +// r1 := a1 >> count +// ... +// r7 := a7 >> count +// +// https://msdn.microsoft.com/en-us/library/3c9997dk(v%3dvs.90).aspx +FORCE_INLINE __m128i _mm_sra_epi16(__m128i a, __m128i count) +{ + int64_t c = (int64_t) vget_low_s64((int64x2_t) count); + if (c > 15) + return _mm_cmplt_epi16(a, _mm_setzero_si128()); + return vreinterpretq_m128i_s16(vshlq_s16((int16x8_t) a, vdupq_n_s16(-c))); +} + +// Shifts the 4 signed 32-bit integers in a right by count bits while shifting +// in the sign bit. +// +// r0 := a0 >> count +// r1 := a1 >> count +// r2 := a2 >> count +// r3 := a3 >> count +// +// https://msdn.microsoft.com/en-us/library/ce40009e(v%3dvs.100).aspx +FORCE_INLINE __m128i _mm_sra_epi32(__m128i a, __m128i count) +{ + int64_t c = (int64_t) vget_low_s64((int64x2_t) count); + if (c > 31) + return _mm_cmplt_epi32(a, _mm_setzero_si128()); + return vreinterpretq_m128i_s32(vshlq_s32((int32x4_t) a, vdupq_n_s32(-c))); +} + +// Packs the 16 signed 16-bit integers from a and b into 8-bit integers and +// saturates. +// https://msdn.microsoft.com/en-us/library/k4y4f7w5%28v=vs.90%29.aspx +FORCE_INLINE __m128i _mm_packs_epi16(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_s8( + vcombine_s8(vqmovn_s16(vreinterpretq_s16_m128i(a)), + vqmovn_s16(vreinterpretq_s16_m128i(b)))); +} + +// Packs the 16 signed 16 - bit integers from a and b into 8 - bit unsigned +// integers and saturates. +// +// r0 := UnsignedSaturate(a0) +// r1 := UnsignedSaturate(a1) +// ... +// r7 := UnsignedSaturate(a7) +// r8 := UnsignedSaturate(b0) +// r9 := UnsignedSaturate(b1) +// ... +// r15 := UnsignedSaturate(b7) +// +// https://msdn.microsoft.com/en-us/library/07ad1wx4(v=vs.100).aspx +FORCE_INLINE __m128i _mm_packus_epi16(const __m128i a, const __m128i b) +{ + return vreinterpretq_m128i_u8( + vcombine_u8(vqmovun_s16(vreinterpretq_s16_m128i(a)), + vqmovun_s16(vreinterpretq_s16_m128i(b)))); +} + +// Packs the 8 signed 32-bit integers from a and b into signed 16-bit integers +// and saturates. +// +// r0 := SignedSaturate(a0) +// r1 := SignedSaturate(a1) +// r2 := SignedSaturate(a2) +// r3 := SignedSaturate(a3) +// r4 := SignedSaturate(b0) +// r5 := SignedSaturate(b1) +// r6 := SignedSaturate(b2) +// r7 := SignedSaturate(b3) +// +// https://msdn.microsoft.com/en-us/library/393t56f9%28v=vs.90%29.aspx +FORCE_INLINE __m128i _mm_packs_epi32(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_s16( + vcombine_s16(vqmovn_s32(vreinterpretq_s32_m128i(a)), + vqmovn_s32(vreinterpretq_s32_m128i(b)))); +} + +// Packs the 8 unsigned 32-bit integers from a and b into unsigned 16-bit +// integers and saturates. +// +// r0 := UnsignedSaturate(a0) +// r1 := UnsignedSaturate(a1) +// r2 := UnsignedSaturate(a2) +// r3 := UnsignedSaturate(a3) +// r4 := UnsignedSaturate(b0) +// r5 := UnsignedSaturate(b1) +// r6 := UnsignedSaturate(b2) +// r7 := UnsignedSaturate(b3) +FORCE_INLINE __m128i _mm_packus_epi32(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_u16( + vcombine_u16(vqmovun_s32(vreinterpretq_s32_m128i(a)), + vqmovun_s32(vreinterpretq_s32_m128i(b)))); +} + +// Interleaves the lower 8 signed or unsigned 8-bit integers in a with the lower +// 8 signed or unsigned 8-bit integers in b. +// +// r0 := a0 +// r1 := b0 +// r2 := a1 +// r3 := b1 +// ... +// r14 := a7 +// r15 := b7 +// +// https://msdn.microsoft.com/en-us/library/xf7k860c%28v=vs.90%29.aspx +FORCE_INLINE __m128i _mm_unpacklo_epi8(__m128i a, __m128i b) +{ +#if defined(__aarch64__) + return vreinterpretq_m128i_s8( + vzip1q_s8(vreinterpretq_s8_m128i(a), vreinterpretq_s8_m128i(b))); +#else + int8x8_t a1 = vreinterpret_s8_s16(vget_low_s16(vreinterpretq_s16_m128i(a))); + int8x8_t b1 = vreinterpret_s8_s16(vget_low_s16(vreinterpretq_s16_m128i(b))); + int8x8x2_t result = vzip_s8(a1, b1); + return vreinterpretq_m128i_s8(vcombine_s8(result.val[0], result.val[1])); +#endif +} + +// Interleaves the lower 4 signed or unsigned 16-bit integers in a with the +// lower 4 signed or unsigned 16-bit integers in b. +// +// r0 := a0 +// r1 := b0 +// r2 := a1 +// r3 := b1 +// r4 := a2 +// r5 := b2 +// r6 := a3 +// r7 := b3 +// +// https://msdn.microsoft.com/en-us/library/btxb17bw%28v=vs.90%29.aspx +FORCE_INLINE __m128i _mm_unpacklo_epi16(__m128i a, __m128i b) +{ +#if defined(__aarch64__) + return vreinterpretq_m128i_s16( + vzip1q_s16(vreinterpretq_s16_m128i(a), vreinterpretq_s16_m128i(b))); +#else + int16x4_t a1 = vget_low_s16(vreinterpretq_s16_m128i(a)); + int16x4_t b1 = vget_low_s16(vreinterpretq_s16_m128i(b)); + int16x4x2_t result = vzip_s16(a1, b1); + return vreinterpretq_m128i_s16(vcombine_s16(result.val[0], result.val[1])); +#endif +} + +// Interleaves the lower 2 signed or unsigned 32 - bit integers in a with the +// lower 2 signed or unsigned 32 - bit integers in b. +// +// r0 := a0 +// r1 := b0 +// r2 := a1 +// r3 := b1 +// +// https://msdn.microsoft.com/en-us/library/x8atst9d(v=vs.100).aspx +FORCE_INLINE __m128i _mm_unpacklo_epi32(__m128i a, __m128i b) +{ +#if defined(__aarch64__) + return vreinterpretq_m128i_s32( + vzip1q_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b))); +#else + int32x2_t a1 = vget_low_s32(vreinterpretq_s32_m128i(a)); + int32x2_t b1 = vget_low_s32(vreinterpretq_s32_m128i(b)); + int32x2x2_t result = vzip_s32(a1, b1); + return vreinterpretq_m128i_s32(vcombine_s32(result.val[0], result.val[1])); +#endif +} + +FORCE_INLINE __m128i _mm_unpacklo_epi64(__m128i a, __m128i b) +{ + int64x1_t a_l = vget_low_s64(vreinterpretq_s64_m128i(a)); + int64x1_t b_l = vget_low_s64(vreinterpretq_s64_m128i(b)); + return vreinterpretq_m128i_s64(vcombine_s64(a_l, b_l)); +} + +// Selects and interleaves the lower two single-precision, floating-point values +// from a and b. +// +// r0 := a0 +// r1 := b0 +// r2 := a1 +// r3 := b1 +// +// https://msdn.microsoft.com/en-us/library/25st103b%28v=vs.90%29.aspx +FORCE_INLINE __m128 _mm_unpacklo_ps(__m128 a, __m128 b) +{ +#if defined(__aarch64__) + return vreinterpretq_m128_f32( + vzip1q_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b))); +#else + float32x2_t a1 = vget_low_f32(vreinterpretq_f32_m128(a)); + float32x2_t b1 = vget_low_f32(vreinterpretq_f32_m128(b)); + float32x2x2_t result = vzip_f32(a1, b1); + return vreinterpretq_m128_f32(vcombine_f32(result.val[0], result.val[1])); +#endif +} + +// Selects and interleaves the upper two single-precision, floating-point values +// from a and b. +// +// r0 := a2 +// r1 := b2 +// r2 := a3 +// r3 := b3 +// +// https://msdn.microsoft.com/en-us/library/skccxx7d%28v=vs.90%29.aspx +FORCE_INLINE __m128 _mm_unpackhi_ps(__m128 a, __m128 b) +{ +#if defined(__aarch64__) + return vreinterpretq_m128_f32( + vzip2q_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b))); +#else + float32x2_t a1 = vget_high_f32(vreinterpretq_f32_m128(a)); + float32x2_t b1 = vget_high_f32(vreinterpretq_f32_m128(b)); + float32x2x2_t result = vzip_f32(a1, b1); + return vreinterpretq_m128_f32(vcombine_f32(result.val[0], result.val[1])); +#endif +} + +// Interleaves the upper 8 signed or unsigned 8-bit integers in a with the upper +// 8 signed or unsigned 8-bit integers in b. +// +// r0 := a8 +// r1 := b8 +// r2 := a9 +// r3 := b9 +// ... +// r14 := a15 +// r15 := b15 +// +// https://msdn.microsoft.com/en-us/library/t5h7783k(v=vs.100).aspx +FORCE_INLINE __m128i _mm_unpackhi_epi8(__m128i a, __m128i b) +{ +#if defined(__aarch64__) + return vreinterpretq_m128i_s8( + vzip2q_s8(vreinterpretq_s8_m128i(a), vreinterpretq_s8_m128i(b))); +#else + int8x8_t a1 = + vreinterpret_s8_s16(vget_high_s16(vreinterpretq_s16_m128i(a))); + int8x8_t b1 = + vreinterpret_s8_s16(vget_high_s16(vreinterpretq_s16_m128i(b))); + int8x8x2_t result = vzip_s8(a1, b1); + return vreinterpretq_m128i_s8(vcombine_s8(result.val[0], result.val[1])); +#endif +} + +// Interleaves the upper 4 signed or unsigned 16-bit integers in a with the +// upper 4 signed or unsigned 16-bit integers in b. +// +// r0 := a4 +// r1 := b4 +// r2 := a5 +// r3 := b5 +// r4 := a6 +// r5 := b6 +// r6 := a7 +// r7 := b7 +// +// https://msdn.microsoft.com/en-us/library/03196cz7(v=vs.100).aspx +FORCE_INLINE __m128i _mm_unpackhi_epi16(__m128i a, __m128i b) +{ +#if defined(__aarch64__) + return vreinterpretq_m128i_s16( + vzip2q_s16(vreinterpretq_s16_m128i(a), vreinterpretq_s16_m128i(b))); +#else + int16x4_t a1 = vget_high_s16(vreinterpretq_s16_m128i(a)); + int16x4_t b1 = vget_high_s16(vreinterpretq_s16_m128i(b)); + int16x4x2_t result = vzip_s16(a1, b1); + return vreinterpretq_m128i_s16(vcombine_s16(result.val[0], result.val[1])); +#endif +} + +// Interleaves the upper 2 signed or unsigned 32-bit integers in a with the +// upper 2 signed or unsigned 32-bit integers in b. +// https://msdn.microsoft.com/en-us/library/65sa7cbs(v=vs.100).aspx +FORCE_INLINE __m128i _mm_unpackhi_epi32(__m128i a, __m128i b) +{ +#if defined(__aarch64__) + return vreinterpretq_m128i_s32( + vzip2q_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b))); +#else + int32x2_t a1 = vget_high_s32(vreinterpretq_s32_m128i(a)); + int32x2_t b1 = vget_high_s32(vreinterpretq_s32_m128i(b)); + int32x2x2_t result = vzip_s32(a1, b1); + return vreinterpretq_m128i_s32(vcombine_s32(result.val[0], result.val[1])); +#endif +} + +// Interleaves the upper signed or unsigned 64-bit integer in a with the +// upper signed or unsigned 64-bit integer in b. +// +// r0 := a1 +// r1 := b1 +FORCE_INLINE __m128i _mm_unpackhi_epi64(__m128i a, __m128i b) +{ + int64x1_t a_h = vget_high_s64(vreinterpretq_s64_m128i(a)); + int64x1_t b_h = vget_high_s64(vreinterpretq_s64_m128i(b)); + return vreinterpretq_m128i_s64(vcombine_s64(a_h, b_h)); +} + +// Horizontally compute the minimum amongst the packed unsigned 16-bit integers +// in a, store the minimum and index in dst, and zero the remaining bits in dst. +// +// index[2:0] := 0 +// min[15:0] := a[15:0] +// FOR j := 0 to 7 +// i := j*16 +// IF a[i+15:i] < min[15:0] +// index[2:0] := j +// min[15:0] := a[i+15:i] +// FI +// ENDFOR +// dst[15:0] := min[15:0] +// dst[18:16] := index[2:0] +// dst[127:19] := 0 +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_minpos_epu16 +FORCE_INLINE __m128i _mm_minpos_epu16(__m128i a) +{ + __m128i dst; + uint16_t min, idx = 0; + // Find the minimum value +#if defined(__aarch64__) + min = vminvq_u16(vreinterpretq_u16_m128i(a)); +#else + __m64 tmp; + tmp = vreinterpret_m64_u16( + vmin_u16(vget_low_u16(vreinterpretq_u16_m128i(a)), + vget_high_u16(vreinterpretq_u16_m128i(a)))); + tmp = vreinterpret_m64_u16( + vpmin_u16(vreinterpret_u16_m64(tmp), vreinterpret_u16_m64(tmp))); + tmp = vreinterpret_m64_u16( + vpmin_u16(vreinterpret_u16_m64(tmp), vreinterpret_u16_m64(tmp))); + min = vget_lane_u16(vreinterpret_u16_m64(tmp), 0); +#endif + // Get the index of the minimum value + int i; + for (i = 0; i < 8; i++) { + if (min == vgetq_lane_u16(vreinterpretq_u16_m128i(a), 0)) { + idx = (uint16_t) i; + break; + } + a = _mm_srli_si128(a, 2); + } + // Generate result + dst = _mm_setzero_si128(); + dst = vreinterpretq_m128i_u16( + vsetq_lane_u16(min, vreinterpretq_u16_m128i(dst), 0)); + dst = vreinterpretq_m128i_u16( + vsetq_lane_u16(idx, vreinterpretq_u16_m128i(dst), 1)); + return dst; +} + +// shift to right +// https://msdn.microsoft.com/en-us/library/bb514041(v=vs.120).aspx +// http://blog.csdn.net/hemmingway/article/details/44828303 +// Clang requires a macro here, as it is extremely picky about c being a +// literal. +#define _mm_alignr_epi8(a, b, c) \ + ((__m128i) vextq_s8((int8x16_t)(b), (int8x16_t)(a), (c))) + +// Compute the bitwise AND of 128 bits (representing integer data) in a and b, +// and set ZF to 1 if the result is zero, otherwise set ZF to 0. Compute the +// bitwise NOT of a and then AND with b, and set CF to 1 if the result is zero, +// otherwise set CF to 0. Return the CF value. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_testc_si128 +FORCE_INLINE int _mm_testc_si128(__m128i a, __m128i b) +{ + int64x2_t s64 = + vandq_s64(vreinterpretq_s64_s32(vmvnq_s32(vreinterpretq_s32_m128i(a))), + vreinterpretq_s64_m128i(b)); + return !(vgetq_lane_s64(s64, 0) | vgetq_lane_s64(s64, 1)); +} + +// Compute the bitwise AND of 128 bits (representing integer data) in a and b, +// and set ZF to 1 if the result is zero, otherwise set ZF to 0. Compute the +// bitwise NOT of a and then AND with b, and set CF to 1 if the result is zero, +// otherwise set CF to 0. Return the ZF value. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_testz_si128 +FORCE_INLINE int _mm_testz_si128(__m128i a, __m128i b) +{ + int64x2_t s64 = + vandq_s64(vreinterpretq_s64_m128i(a), vreinterpretq_s64_m128i(b)); + return !(vgetq_lane_s64(s64, 0) | vgetq_lane_s64(s64, 1)); +} + +// Extracts the selected signed or unsigned 8-bit integer from a and zero +// extends. +// FORCE_INLINE int _mm_extract_epi8(__m128i a, __constrange(0,16) int imm) +#define _mm_extract_epi8(a, imm) vgetq_lane_u8(vreinterpretq_u8_m128i(a), (imm)) + +// Inserts the least significant 8 bits of b into the selected 8-bit integer +// of a. +// FORCE_INLINE __m128i _mm_insert_epi8(__m128i a, int b, +// __constrange(0,16) int imm) +#define _mm_insert_epi8(a, b, imm) \ + __extension__({ \ + vreinterpretq_m128i_s8( \ + vsetq_lane_s8((b), vreinterpretq_s8_m128i(a), (imm))); \ + }) + +// Extracts the selected signed or unsigned 16-bit integer from a and zero +// extends. +// https://msdn.microsoft.com/en-us/library/6dceta0c(v=vs.100).aspx +// FORCE_INLINE int _mm_extract_epi16(__m128i a, __constrange(0,8) int imm) +#define _mm_extract_epi16(a, imm) \ + vgetq_lane_u16(vreinterpretq_u16_m128i(a), (imm)) + +// Inserts the least significant 16 bits of b into the selected 16-bit integer +// of a. +// https://msdn.microsoft.com/en-us/library/kaze8hz1%28v=vs.100%29.aspx +// FORCE_INLINE __m128i _mm_insert_epi16(__m128i a, int b, +// __constrange(0,8) int imm) +#define _mm_insert_epi16(a, b, imm) \ + __extension__({ \ + vreinterpretq_m128i_s16( \ + vsetq_lane_s16((b), vreinterpretq_s16_m128i(a), (imm))); \ + }) + +// Extracts the selected signed or unsigned 32-bit integer from a and zero +// extends. +// FORCE_INLINE int _mm_extract_epi32(__m128i a, __constrange(0,4) int imm) +#define _mm_extract_epi32(a, imm) \ + vgetq_lane_s32(vreinterpretq_s32_m128i(a), (imm)) + +// Extracts the selected single-precision (32-bit) floating-point from a. +// FORCE_INLINE int _mm_extract_ps(__m128 a, __constrange(0,4) int imm) +#define _mm_extract_ps(a, imm) vgetq_lane_s32(vreinterpretq_s32_m128(a), (imm)) + +// Inserts the least significant 32 bits of b into the selected 32-bit integer +// of a. +// FORCE_INLINE __m128i _mm_insert_epi32(__m128i a, int b, +// __constrange(0,4) int imm) +#define _mm_insert_epi32(a, b, imm) \ + __extension__({ \ + vreinterpretq_m128i_s32( \ + vsetq_lane_s32((b), vreinterpretq_s32_m128i(a), (imm))); \ + }) + +// Extracts the selected signed or unsigned 64-bit integer from a and zero +// extends. +// FORCE_INLINE __int64 _mm_extract_epi64(__m128i a, __constrange(0,2) int imm) +#define _mm_extract_epi64(a, imm) \ + vgetq_lane_s64(vreinterpretq_s64_m128i(a), (imm)) + +// Inserts the least significant 64 bits of b into the selected 64-bit integer +// of a. +// FORCE_INLINE __m128i _mm_insert_epi64(__m128i a, __int64 b, +// __constrange(0,2) int imm) +#define _mm_insert_epi64(a, b, imm) \ + __extension__({ \ + vreinterpretq_m128i_s64( \ + vsetq_lane_s64((b), vreinterpretq_s64_m128i(a), (imm))); \ + }) + +// Count the number of bits set to 1 in unsigned 32-bit integer a, and +// return that count in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_popcnt_u32 +FORCE_INLINE int _mm_popcnt_u32(unsigned int a) +{ +#if defined(__aarch64__) +#if __has_builtin(__builtin_popcount) + return __builtin_popcount(a); +#else + return (int) vaddlv_u8(vcnt_u8(vcreate_u8((uint64_t) a))); +#endif +#else + uint32_t count = 0; + uint8x8_t input_val, count8x8_val; + uint16x4_t count16x4_val; + uint32x2_t count32x2_val; + + input_val = vld1_u8((uint8_t *) &a); + count8x8_val = vcnt_u8(input_val); + count16x4_val = vpaddl_u8(count8x8_val); + count32x2_val = vpaddl_u16(count16x4_val); + + vst1_u32(&count, count32x2_val); + return count; +#endif +} + +// Count the number of bits set to 1 in unsigned 64-bit integer a, and +// return that count in dst. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_popcnt_u64 +FORCE_INLINE int64_t _mm_popcnt_u64(uint64_t a) +{ +#if defined(__aarch64__) +#if __has_builtin(__builtin_popcountll) + return __builtin_popcountll(a); +#else + return (int64_t) vaddlv_u8(vcnt_u8(vcreate_u8(a))); +#endif +#else + uint64_t count = 0; + uint8x8_t input_val, count8x8_val; + uint16x4_t count16x4_val; + uint32x2_t count32x2_val; + uint64x1_t count64x1_val; + + input_val = vld1_u8((uint8_t *) &a); + count8x8_val = vcnt_u8(input_val); + count16x4_val = vpaddl_u8(count8x8_val); + count32x2_val = vpaddl_u16(count16x4_val); + count64x1_val = vpaddl_u32(count32x2_val); + vst1_u64(&count, count64x1_val); + return count; +#endif +} + +// Macro: Transpose the 4x4 matrix formed by the 4 rows of single-precision +// (32-bit) floating-point elements in row0, row1, row2, and row3, and store the +// transposed matrix in these vectors (row0 now contains column 0, etc.). +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=MM_TRANSPOSE4_PS +#define _MM_TRANSPOSE4_PS(row0, row1, row2, row3) \ + do { \ + float32x4x2_t ROW01 = vtrnq_f32(row0, row1); \ + float32x4x2_t ROW23 = vtrnq_f32(row2, row3); \ + row0 = vcombine_f32(vget_low_f32(ROW01.val[0]), \ + vget_low_f32(ROW23.val[0])); \ + row1 = vcombine_f32(vget_low_f32(ROW01.val[1]), \ + vget_low_f32(ROW23.val[1])); \ + row2 = vcombine_f32(vget_high_f32(ROW01.val[0]), \ + vget_high_f32(ROW23.val[0])); \ + row3 = vcombine_f32(vget_high_f32(ROW01.val[1]), \ + vget_high_f32(ROW23.val[1])); \ + } while (0) + +/* Crypto Extensions */ + +#if defined(__ARM_FEATURE_CRYPTO) +// Wraps vmull_p64 +FORCE_INLINE uint64x2_t _sse2neon_vmull_p64(uint64x1_t _a, uint64x1_t _b) +{ + poly64_t a = vget_lane_p64(vreinterpret_p64_u64(_a), 0); + poly64_t b = vget_lane_p64(vreinterpret_p64_u64(_b), 0); + return vreinterpretq_u64_p128(vmull_p64(a, b)); +} +#else // ARMv7 polyfill +// ARMv7/some A64 lacks vmull_p64, but it has vmull_p8. +// +// vmull_p8 calculates 8 8-bit->16-bit polynomial multiplies, but we need a +// 64-bit->128-bit polynomial multiply. +// +// It needs some work and is somewhat slow, but it is still faster than all +// known scalar methods. +// +// Algorithm adapted to C from +// https://www.workofard.com/2017/07/ghash-for-low-end-cores/, which is adapted +// from "Fast Software Polynomial Multiplication on ARM Processors Using the +// NEON Engine" by Danilo Camara, Conrado Gouvea, Julio Lopez and Ricardo Dahab +// (https://hal.inria.fr/hal-01506572) +static uint64x2_t _sse2neon_vmull_p64(uint64x1_t _a, uint64x1_t _b) +{ + poly8x8_t a = vreinterpret_p8_u64(_a); + poly8x8_t b = vreinterpret_p8_u64(_b); + + // Masks + uint8x16_t k48_32 = vcombine_u8(vcreate_u8(0x0000ffffffffffff), + vcreate_u8(0x00000000ffffffff)); + uint8x16_t k16_00 = vcombine_u8(vcreate_u8(0x000000000000ffff), + vcreate_u8(0x0000000000000000)); + + // Do the multiplies, rotating with vext to get all combinations + uint8x16_t d = vreinterpretq_u8_p16(vmull_p8(a, b)); // D = A0 * B0 + uint8x16_t e = + vreinterpretq_u8_p16(vmull_p8(a, vext_p8(b, b, 1))); // E = A0 * B1 + uint8x16_t f = + vreinterpretq_u8_p16(vmull_p8(vext_p8(a, a, 1), b)); // F = A1 * B0 + uint8x16_t g = + vreinterpretq_u8_p16(vmull_p8(a, vext_p8(b, b, 2))); // G = A0 * B2 + uint8x16_t h = + vreinterpretq_u8_p16(vmull_p8(vext_p8(a, a, 2), b)); // H = A2 * B0 + uint8x16_t i = + vreinterpretq_u8_p16(vmull_p8(a, vext_p8(b, b, 3))); // I = A0 * B3 + uint8x16_t j = + vreinterpretq_u8_p16(vmull_p8(vext_p8(a, a, 3), b)); // J = A3 * B0 + uint8x16_t k = + vreinterpretq_u8_p16(vmull_p8(a, vext_p8(b, b, 4))); // L = A0 * B4 + + // Add cross products + uint8x16_t l = veorq_u8(e, f); // L = E + F + uint8x16_t m = veorq_u8(g, h); // M = G + H + uint8x16_t n = veorq_u8(i, j); // N = I + J + + // Interleave. Using vzip1 and vzip2 prevents Clang from emitting TBL + // instructions. +#if defined(__aarch64__) + uint8x16_t lm_p0 = vreinterpretq_u8_u64( + vzip1q_u64(vreinterpretq_u64_u8(l), vreinterpretq_u64_u8(m))); + uint8x16_t lm_p1 = vreinterpretq_u8_u64( + vzip2q_u64(vreinterpretq_u64_u8(l), vreinterpretq_u64_u8(m))); + uint8x16_t nk_p0 = vreinterpretq_u8_u64( + vzip1q_u64(vreinterpretq_u64_u8(n), vreinterpretq_u64_u8(k))); + uint8x16_t nk_p1 = vreinterpretq_u8_u64( + vzip2q_u64(vreinterpretq_u64_u8(n), vreinterpretq_u64_u8(k))); +#else + uint8x16_t lm_p0 = vcombine_u8(vget_low_u8(l), vget_low_u8(m)); + uint8x16_t lm_p1 = vcombine_u8(vget_high_u8(l), vget_high_u8(m)); + uint8x16_t nk_p0 = vcombine_u8(vget_low_u8(n), vget_low_u8(k)); + uint8x16_t nk_p1 = vcombine_u8(vget_high_u8(n), vget_high_u8(k)); +#endif + // t0 = (L) (P0 + P1) << 8 + // t1 = (M) (P2 + P3) << 16 + uint8x16_t t0t1_tmp = veorq_u8(lm_p0, lm_p1); + uint8x16_t t0t1_h = vandq_u8(lm_p1, k48_32); + uint8x16_t t0t1_l = veorq_u8(t0t1_tmp, t0t1_h); + + // t2 = (N) (P4 + P5) << 24 + // t3 = (K) (P6 + P7) << 32 + uint8x16_t t2t3_tmp = veorq_u8(nk_p0, nk_p1); + uint8x16_t t2t3_h = vandq_u8(nk_p1, k16_00); + uint8x16_t t2t3_l = veorq_u8(t2t3_tmp, t2t3_h); + + // De-interleave +#if defined(__aarch64__) + uint8x16_t t0 = vreinterpretq_u8_u64( + vuzp1q_u64(vreinterpretq_u64_u8(t0t1_l), vreinterpretq_u64_u8(t0t1_h))); + uint8x16_t t1 = vreinterpretq_u8_u64( + vuzp2q_u64(vreinterpretq_u64_u8(t0t1_l), vreinterpretq_u64_u8(t0t1_h))); + uint8x16_t t2 = vreinterpretq_u8_u64( + vuzp1q_u64(vreinterpretq_u64_u8(t2t3_l), vreinterpretq_u64_u8(t2t3_h))); + uint8x16_t t3 = vreinterpretq_u8_u64( + vuzp2q_u64(vreinterpretq_u64_u8(t2t3_l), vreinterpretq_u64_u8(t2t3_h))); +#else + uint8x16_t t1 = vcombine_u8(vget_high_u8(t0t1_l), vget_high_u8(t0t1_h)); + uint8x16_t t0 = vcombine_u8(vget_low_u8(t0t1_l), vget_low_u8(t0t1_h)); + uint8x16_t t3 = vcombine_u8(vget_high_u8(t2t3_l), vget_high_u8(t2t3_h)); + uint8x16_t t2 = vcombine_u8(vget_low_u8(t2t3_l), vget_low_u8(t2t3_h)); +#endif + // Shift the cross products + uint8x16_t t0_shift = vextq_u8(t0, t0, 15); // t0 << 8 + uint8x16_t t1_shift = vextq_u8(t1, t1, 14); // t1 << 16 + uint8x16_t t2_shift = vextq_u8(t2, t2, 13); // t2 << 24 + uint8x16_t t3_shift = vextq_u8(t3, t3, 12); // t3 << 32 + + // Accumulate the products + uint8x16_t cross1 = veorq_u8(t0_shift, t1_shift); + uint8x16_t cross2 = veorq_u8(t2_shift, t3_shift); + uint8x16_t mix = veorq_u8(d, cross1); + uint8x16_t r = veorq_u8(mix, cross2); + return vreinterpretq_u64_u8(r); +} +#endif // ARMv7 polyfill + +FORCE_INLINE __m128i _mm_clmulepi64_si128(__m128i _a, __m128i _b, const int imm) +{ + uint64x2_t a = vreinterpretq_u64_m128i(_a); + uint64x2_t b = vreinterpretq_u64_m128i(_b); + switch (imm & 0x11) { + case 0x00: + return vreinterpretq_m128i_u64( + _sse2neon_vmull_p64(vget_low_u64(a), vget_low_u64(b))); + case 0x01: + return vreinterpretq_m128i_u64( + _sse2neon_vmull_p64(vget_high_u64(a), vget_low_u64(b))); + case 0x10: + return vreinterpretq_m128i_u64( + _sse2neon_vmull_p64(vget_low_u64(a), vget_high_u64(b))); + case 0x11: + return vreinterpretq_m128i_u64( + _sse2neon_vmull_p64(vget_high_u64(a), vget_high_u64(b))); + default: + abort(); + } +} + +#if !defined(__ARM_FEATURE_CRYPTO) +/* clang-format off */ +#define SSE2NEON_AES_DATA(w) \ + { \ + w(0x63), w(0x7c), w(0x77), w(0x7b), w(0xf2), w(0x6b), w(0x6f), \ + w(0xc5), w(0x30), w(0x01), w(0x67), w(0x2b), w(0xfe), w(0xd7), \ + w(0xab), w(0x76), w(0xca), w(0x82), w(0xc9), w(0x7d), w(0xfa), \ + w(0x59), w(0x47), w(0xf0), w(0xad), w(0xd4), w(0xa2), w(0xaf), \ + w(0x9c), w(0xa4), w(0x72), w(0xc0), w(0xb7), w(0xfd), w(0x93), \ + w(0x26), w(0x36), w(0x3f), w(0xf7), w(0xcc), w(0x34), w(0xa5), \ + w(0xe5), w(0xf1), w(0x71), w(0xd8), w(0x31), w(0x15), w(0x04), \ + w(0xc7), w(0x23), w(0xc3), w(0x18), w(0x96), w(0x05), w(0x9a), \ + w(0x07), w(0x12), w(0x80), w(0xe2), w(0xeb), w(0x27), w(0xb2), \ + w(0x75), w(0x09), w(0x83), w(0x2c), w(0x1a), w(0x1b), w(0x6e), \ + w(0x5a), w(0xa0), w(0x52), w(0x3b), w(0xd6), w(0xb3), w(0x29), \ + w(0xe3), w(0x2f), w(0x84), w(0x53), w(0xd1), w(0x00), w(0xed), \ + w(0x20), w(0xfc), w(0xb1), w(0x5b), w(0x6a), w(0xcb), w(0xbe), \ + w(0x39), w(0x4a), w(0x4c), w(0x58), w(0xcf), w(0xd0), w(0xef), \ + w(0xaa), w(0xfb), w(0x43), w(0x4d), w(0x33), w(0x85), w(0x45), \ + w(0xf9), w(0x02), w(0x7f), w(0x50), w(0x3c), w(0x9f), w(0xa8), \ + w(0x51), w(0xa3), w(0x40), w(0x8f), w(0x92), w(0x9d), w(0x38), \ + w(0xf5), w(0xbc), w(0xb6), w(0xda), w(0x21), w(0x10), w(0xff), \ + w(0xf3), w(0xd2), w(0xcd), w(0x0c), w(0x13), w(0xec), w(0x5f), \ + w(0x97), w(0x44), w(0x17), w(0xc4), w(0xa7), w(0x7e), w(0x3d), \ + w(0x64), w(0x5d), w(0x19), w(0x73), w(0x60), w(0x81), w(0x4f), \ + w(0xdc), w(0x22), w(0x2a), w(0x90), w(0x88), w(0x46), w(0xee), \ + w(0xb8), w(0x14), w(0xde), w(0x5e), w(0x0b), w(0xdb), w(0xe0), \ + w(0x32), w(0x3a), w(0x0a), w(0x49), w(0x06), w(0x24), w(0x5c), \ + w(0xc2), w(0xd3), w(0xac), w(0x62), w(0x91), w(0x95), w(0xe4), \ + w(0x79), w(0xe7), w(0xc8), w(0x37), w(0x6d), w(0x8d), w(0xd5), \ + w(0x4e), w(0xa9), w(0x6c), w(0x56), w(0xf4), w(0xea), w(0x65), \ + w(0x7a), w(0xae), w(0x08), w(0xba), w(0x78), w(0x25), w(0x2e), \ + w(0x1c), w(0xa6), w(0xb4), w(0xc6), w(0xe8), w(0xdd), w(0x74), \ + w(0x1f), w(0x4b), w(0xbd), w(0x8b), w(0x8a), w(0x70), w(0x3e), \ + w(0xb5), w(0x66), w(0x48), w(0x03), w(0xf6), w(0x0e), w(0x61), \ + w(0x35), w(0x57), w(0xb9), w(0x86), w(0xc1), w(0x1d), w(0x9e), \ + w(0xe1), w(0xf8), w(0x98), w(0x11), w(0x69), w(0xd9), w(0x8e), \ + w(0x94), w(0x9b), w(0x1e), w(0x87), w(0xe9), w(0xce), w(0x55), \ + w(0x28), w(0xdf), w(0x8c), w(0xa1), w(0x89), w(0x0d), w(0xbf), \ + w(0xe6), w(0x42), w(0x68), w(0x41), w(0x99), w(0x2d), w(0x0f), \ + w(0xb0), w(0x54), w(0xbb), w(0x16) \ + } +/* clang-format on */ + +/* X Macro trick. See https://en.wikipedia.org/wiki/X_Macro */ +#define SSE2NEON_AES_H0(x) (x) +static const uint8_t SSE2NEON_sbox[256] = SSE2NEON_AES_DATA(SSE2NEON_AES_H0); +#undef SSE2NEON_AES_H0 + +// In the absence of crypto extensions, implement aesenc using regular neon +// intrinsics instead. See: +// https://www.workofard.com/2017/01/accelerated-aes-for-the-arm64-linux-kernel/ +// https://www.workofard.com/2017/07/ghash-for-low-end-cores/ and +// https://github.com/ColinIanKing/linux-next-mirror/blob/b5f466091e130caaf0735976648f72bd5e09aa84/crypto/aegis128-neon-inner.c#L52 +// for more information Reproduced with permission of the author. +FORCE_INLINE __m128i _mm_aesenc_si128(__m128i EncBlock, __m128i RoundKey) +{ +#if defined(__aarch64__) + static const uint8_t shift_rows[] = {0x0, 0x5, 0xa, 0xf, 0x4, 0x9, + 0xe, 0x3, 0x8, 0xd, 0x2, 0x7, + 0xc, 0x1, 0x6, 0xb}; + static const uint8_t ror32by8[] = {0x1, 0x2, 0x3, 0x0, 0x5, 0x6, 0x7, 0x4, + 0x9, 0xa, 0xb, 0x8, 0xd, 0xe, 0xf, 0xc}; + + uint8x16_t v; + uint8x16_t w = vreinterpretq_u8_m128i(EncBlock); + + // shift rows + w = vqtbl1q_u8(w, vld1q_u8(shift_rows)); + + // sub bytes + v = vqtbl4q_u8(vld1q_u8_x4(SSE2NEON_sbox), w); + v = vqtbx4q_u8(v, vld1q_u8_x4(SSE2NEON_sbox + 0x40), w - 0x40); + v = vqtbx4q_u8(v, vld1q_u8_x4(SSE2NEON_sbox + 0x80), w - 0x80); + v = vqtbx4q_u8(v, vld1q_u8_x4(SSE2NEON_sbox + 0xc0), w - 0xc0); + + // mix columns + w = (v << 1) ^ (uint8x16_t)(((int8x16_t) v >> 7) & 0x1b); + w ^= (uint8x16_t) vrev32q_u16((uint16x8_t) v); + w ^= vqtbl1q_u8(v ^ w, vld1q_u8(ror32by8)); + + // add round key + return vreinterpretq_m128i_u8(w) ^ RoundKey; + +#else /* ARMv7-A NEON implementation */ +#define SSE2NEON_AES_B2W(b0, b1, b2, b3) \ + (((uint32_t)(b3) << 24) | ((uint32_t)(b2) << 16) | ((uint32_t)(b1) << 8) | \ + (b0)) +#define SSE2NEON_AES_F2(x) ((x << 1) ^ (((x >> 7) & 1) * 0x011b /* WPOLY */)) +#define SSE2NEON_AES_F3(x) (SSE2NEON_AES_F2(x) ^ x) +#define SSE2NEON_AES_U0(p) \ + SSE2NEON_AES_B2W(SSE2NEON_AES_F2(p), p, p, SSE2NEON_AES_F3(p)) +#define SSE2NEON_AES_U1(p) \ + SSE2NEON_AES_B2W(SSE2NEON_AES_F3(p), SSE2NEON_AES_F2(p), p, p) +#define SSE2NEON_AES_U2(p) \ + SSE2NEON_AES_B2W(p, SSE2NEON_AES_F3(p), SSE2NEON_AES_F2(p), p) +#define SSE2NEON_AES_U3(p) \ + SSE2NEON_AES_B2W(p, p, SSE2NEON_AES_F3(p), SSE2NEON_AES_F2(p)) + static const uint32_t ALIGN_STRUCT(16) aes_table[4][256] = { + SSE2NEON_AES_DATA(SSE2NEON_AES_U0), + SSE2NEON_AES_DATA(SSE2NEON_AES_U1), + SSE2NEON_AES_DATA(SSE2NEON_AES_U2), + SSE2NEON_AES_DATA(SSE2NEON_AES_U3), + }; +#undef SSE2NEON_AES_B2W +#undef SSE2NEON_AES_F2 +#undef SSE2NEON_AES_F3 +#undef SSE2NEON_AES_U0 +#undef SSE2NEON_AES_U1 +#undef SSE2NEON_AES_U2 +#undef SSE2NEON_AES_U3 + + uint32_t x0 = _mm_cvtsi128_si32(EncBlock); + uint32_t x1 = _mm_cvtsi128_si32(_mm_shuffle_epi32(EncBlock, 0x55)); + uint32_t x2 = _mm_cvtsi128_si32(_mm_shuffle_epi32(EncBlock, 0xAA)); + uint32_t x3 = _mm_cvtsi128_si32(_mm_shuffle_epi32(EncBlock, 0xFF)); + + __m128i out = _mm_set_epi32( + (aes_table[0][x3 & 0xff] ^ aes_table[1][(x0 >> 8) & 0xff] ^ + aes_table[2][(x1 >> 16) & 0xff] ^ aes_table[3][x2 >> 24]), + (aes_table[0][x2 & 0xff] ^ aes_table[1][(x3 >> 8) & 0xff] ^ + aes_table[2][(x0 >> 16) & 0xff] ^ aes_table[3][x1 >> 24]), + (aes_table[0][x1 & 0xff] ^ aes_table[1][(x2 >> 8) & 0xff] ^ + aes_table[2][(x3 >> 16) & 0xff] ^ aes_table[3][x0 >> 24]), + (aes_table[0][x0 & 0xff] ^ aes_table[1][(x1 >> 8) & 0xff] ^ + aes_table[2][(x2 >> 16) & 0xff] ^ aes_table[3][x3 >> 24])); + + return _mm_xor_si128(out, RoundKey); +#endif +} + +FORCE_INLINE __m128i _mm_aesenclast_si128(__m128i a, __m128i RoundKey) +{ + /* FIXME: optimized for NEON */ + uint8_t v[4][4] = { + [0] = {SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 0)], + SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 5)], + SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 10)], + SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 15)]}, + [1] = {SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 4)], + SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 9)], + SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 14)], + SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 3)]}, + [2] = {SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 8)], + SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 13)], + SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 2)], + SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 7)]}, + [3] = {SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 12)], + SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 1)], + SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 6)], + SSE2NEON_sbox[vreinterpretq_nth_u8_m128i(a, 11)]}, + }; + for (int i = 0; i < 16; i++) + vreinterpretq_nth_u8_m128i(a, i) = + v[i / 4][i % 4] ^ vreinterpretq_nth_u8_m128i(RoundKey, i); + return a; +} + +// Emits the Advanced Encryption Standard (AES) instruction aeskeygenassist. +// This instruction generates a round key for AES encryption. See +// https://kazakov.life/2017/11/01/cryptocurrency-mining-on-ios-devices/ +// for details. +// +// https://msdn.microsoft.com/en-us/library/cc714138(v=vs.120).aspx +FORCE_INLINE __m128i _mm_aeskeygenassist_si128(__m128i key, const int rcon) +{ + uint32_t X1 = _mm_cvtsi128_si32(_mm_shuffle_epi32(key, 0x55)); + uint32_t X3 = _mm_cvtsi128_si32(_mm_shuffle_epi32(key, 0xFF)); + for (int i = 0; i < 4; ++i) { + ((uint8_t *) &X1)[i] = SSE2NEON_sbox[((uint8_t *) &X1)[i]]; + ((uint8_t *) &X3)[i] = SSE2NEON_sbox[((uint8_t *) &X3)[i]]; + } + return _mm_set_epi32(((X3 >> 8) | (X3 << 24)) ^ rcon, X3, + ((X1 >> 8) | (X1 << 24)) ^ rcon, X1); +} +#undef SSE2NEON_AES_DATA + +#else /* __ARM_FEATURE_CRYPTO */ +// Implements equivalent of 'aesenc' by combining AESE (with an empty key) and +// AESMC and then manually applying the real key as an xor operation. This +// unfortunately means an additional xor op; the compiler should be able to +// optimize this away for repeated calls however. See +// https://blog.michaelbrase.com/2018/05/08/emulating-x86-aes-intrinsics-on-armv8-a +// for more details. +FORCE_INLINE __m128i _mm_aesenc_si128(__m128i a, __m128i b) +{ + return vreinterpretq_m128i_u8( + vaesmcq_u8(vaeseq_u8(vreinterpretq_u8_m128i(a), vdupq_n_u8(0))) ^ + vreinterpretq_u8_m128i(b)); +} + +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_aesenclast_si128 +FORCE_INLINE __m128i _mm_aesenclast_si128(__m128i a, __m128i RoundKey) +{ + return _mm_xor_si128(vreinterpretq_m128i_u8(vaeseq_u8( + vreinterpretq_u8_m128i(a), vdupq_n_u8(0))), + RoundKey); +} + +FORCE_INLINE __m128i _mm_aeskeygenassist_si128(__m128i a, const int rcon) +{ + // AESE does ShiftRows and SubBytes on A + uint8x16_t u8 = vaeseq_u8(vreinterpretq_u8_m128i(a), vdupq_n_u8(0)); + + uint8x16_t dest = { + // Undo ShiftRows step from AESE and extract X1 and X3 + u8[0x4], u8[0x1], u8[0xE], u8[0xB], // SubBytes(X1) + u8[0x1], u8[0xE], u8[0xB], u8[0x4], // ROT(SubBytes(X1)) + u8[0xC], u8[0x9], u8[0x6], u8[0x3], // SubBytes(X3) + u8[0x9], u8[0x6], u8[0x3], u8[0xC], // ROT(SubBytes(X3)) + }; + uint32x4_t r = {0, (unsigned) rcon, 0, (unsigned) rcon}; + return vreinterpretq_m128i_u8(dest) ^ vreinterpretq_m128i_u32(r); +} +#endif + +/* Streaming Extensions */ + +// Guarantees that every preceding store is globally visible before any +// subsequent store. +// https://msdn.microsoft.com/en-us/library/5h2w73d1%28v=vs.90%29.aspx +FORCE_INLINE void _mm_sfence(void) +{ + __sync_synchronize(); +} + +// Store 128-bits (composed of 4 packed single-precision (32-bit) floating- +// point elements) from a into memory using a non-temporal memory hint. +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_stream_ps +FORCE_INLINE void _mm_stream_ps(float *p, __m128 a) +{ +#if __has_builtin(__builtin_nontemporal_store) + __builtin_nontemporal_store(a, (float32x4_t *) p); +#else + vst1q_f32(p, vreinterpretq_f32_m128(a)); +#endif +} + +// Stores the data in a to the address p without polluting the caches. If the +// cache line containing address p is already in the cache, the cache will be +// updated. +// https://msdn.microsoft.com/en-us/library/ba08y07y%28v=vs.90%29.aspx +FORCE_INLINE void _mm_stream_si128(__m128i *p, __m128i a) +{ +#if __has_builtin(__builtin_nontemporal_store) + __builtin_nontemporal_store(a, p); +#else + vst1q_s64((int64_t *) p, vreinterpretq_s64_m128i(a)); +#endif +} + +// Load 128-bits of integer data from memory into dst using a non-temporal +// memory hint. mem_addr must be aligned on a 16-byte boundary or a +// general-protection exception may be generated. +// +// dst[127:0] := MEM[mem_addr+127:mem_addr] +// +// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_stream_load_si128 +FORCE_INLINE __m128i _mm_stream_load_si128(__m128i *p) +{ +#if __has_builtin(__builtin_nontemporal_store) + return __builtin_nontemporal_load(p); +#else + return vreinterpretq_m128i_s64(vld1q_s64((int64_t *) p)); +#endif +} + +// Cache line containing p is flushed and invalidated from all caches in the +// coherency domain. : +// https://msdn.microsoft.com/en-us/library/ba08y07y(v=vs.100).aspx +FORCE_INLINE void _mm_clflush(void const *p) +{ + (void) p; + // no corollary for Neon? +} + +// Allocate aligned blocks of memory. +// https://software.intel.com/en-us/ +// cpp-compiler-developer-guide-and-reference-allocating-and-freeing-aligned-memory-blocks +FORCE_INLINE void *_mm_malloc(size_t size, size_t align) +{ + void *ptr; + if (align == 1) + return malloc(size); + if (align == 2 || (sizeof(void *) == 8 && align == 4)) + align = sizeof(void *); + if (!posix_memalign(&ptr, align, size)) + return ptr; + return NULL; +} + +FORCE_INLINE void _mm_free(void *addr) +{ + free(addr); +} + +// Starting with the initial value in crc, accumulates a CRC32 value for +// unsigned 8-bit integer v. +// https://msdn.microsoft.com/en-us/library/bb514036(v=vs.100) +FORCE_INLINE uint32_t _mm_crc32_u8(uint32_t crc, uint8_t v) +{ +#if defined(__aarch64__) && defined(__ARM_FEATURE_CRC32) + __asm__ __volatile__("crc32cb %w[c], %w[c], %w[v]\n\t" + : [c] "+r"(crc) + : [v] "r"(v)); +#else + crc ^= v; + for (int bit = 0; bit < 8; bit++) { + if (crc & 1) + crc = (crc >> 1) ^ UINT32_C(0x82f63b78); + else + crc = (crc >> 1); + } +#endif + return crc; +} + +// Starting with the initial value in crc, accumulates a CRC32 value for +// unsigned 16-bit integer v. +// https://msdn.microsoft.com/en-us/library/bb531411(v=vs.100) +FORCE_INLINE uint32_t _mm_crc32_u16(uint32_t crc, uint16_t v) +{ +#if defined(__aarch64__) && defined(__ARM_FEATURE_CRC32) + __asm__ __volatile__("crc32ch %w[c], %w[c], %w[v]\n\t" + : [c] "+r"(crc) + : [v] "r"(v)); +#else + crc = _mm_crc32_u8(crc, v & 0xff); + crc = _mm_crc32_u8(crc, (v >> 8) & 0xff); +#endif + return crc; +} + +// Starting with the initial value in crc, accumulates a CRC32 value for +// unsigned 32-bit integer v. +// https://msdn.microsoft.com/en-us/library/bb531394(v=vs.100) +FORCE_INLINE uint32_t _mm_crc32_u32(uint32_t crc, uint32_t v) +{ +#if defined(__aarch64__) && defined(__ARM_FEATURE_CRC32) + __asm__ __volatile__("crc32cw %w[c], %w[c], %w[v]\n\t" + : [c] "+r"(crc) + : [v] "r"(v)); +#else + crc = _mm_crc32_u16(crc, v & 0xffff); + crc = _mm_crc32_u16(crc, (v >> 16) & 0xffff); +#endif + return crc; +} + +// Starting with the initial value in crc, accumulates a CRC32 value for +// unsigned 64-bit integer v. +// https://msdn.microsoft.com/en-us/library/bb514033(v=vs.100) +FORCE_INLINE uint64_t _mm_crc32_u64(uint64_t crc, uint64_t v) +{ +#if defined(__aarch64__) && defined(__ARM_FEATURE_CRC32) + __asm__ __volatile__("crc32cx %w[c], %w[c], %x[v]\n\t" + : [c] "+r"(crc) + : [v] "r"(v)); +#else + crc = _mm_crc32_u32((uint32_t)(crc), v & 0xffffffff); + crc = _mm_crc32_u32((uint32_t)(crc), (v >> 32) & 0xffffffff); +#endif + return crc; +} + +#if defined(__GNUC__) || defined(__clang__) +#pragma pop_macro("ALIGN_STRUCT") +#pragma pop_macro("FORCE_INLINE") +#endif + +#if defined(__GNUC__) +#pragma GCC pop_options +#endif + +#endif diff --git a/venv/Include/site/python3.9/pygame/mask.h b/venv/Include/site/python3.9/pygame/mask.h new file mode 100644 index 0000000..45ad8c5 --- /dev/null +++ b/venv/Include/site/python3.9/pygame/mask.h @@ -0,0 +1,7 @@ +#ifndef PGMASK_INTERNAL_H +#define PGMASK_INTERNAL_H + +#include "include/pygame_mask.h" +#define PYGAMEAPI_MASK_NUMSLOTS 1 + +#endif /* ~PGMASK_INTERNAL_H */ diff --git a/venv/Include/site/python3.9/pygame/mixer.h b/venv/Include/site/python3.9/pygame/mixer.h new file mode 100644 index 0000000..97f5a0f --- /dev/null +++ b/venv/Include/site/python3.9/pygame/mixer.h @@ -0,0 +1,14 @@ +#ifndef MIXER_INTERNAL_H +#define MIXER_INTERNAL_H + +#include + +/* test mixer initializations */ +#define MIXER_INIT_CHECK() \ + if (!SDL_WasInit(SDL_INIT_AUDIO)) \ + return RAISE(pgExc_SDLError, "mixer not initialized") + +#define PYGAMEAPI_MIXER_NUMSLOTS 5 +#include "include/pygame_mixer.h" + +#endif /* ~MIXER_INTERNAL_H */ diff --git a/venv/Include/site/python3.9/pygame/palette.h b/venv/Include/site/python3.9/pygame/palette.h new file mode 100644 index 0000000..1ae4cf6 --- /dev/null +++ b/venv/Include/site/python3.9/pygame/palette.h @@ -0,0 +1,123 @@ +/* + pygame - Python Game Library + Copyright (C) 2000-2001 Pete Shinners + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Pete Shinners + pete@shinners.org +*/ + +#ifndef PALETTE_H +#define PALETTE_H + +#include + +/* SDL 2 does not assign a default palette color scheme to a new 8 bit + * surface. Instead, the palette is set all white. This defines the SDL 1.2 + * default palette. + */ +static const SDL_Color default_palette_colors[] = { + {0, 0, 0, 255}, {0, 0, 85, 255}, {0, 0, 170, 255}, + {0, 0, 255, 255}, {0, 36, 0, 255}, {0, 36, 85, 255}, + {0, 36, 170, 255}, {0, 36, 255, 255}, {0, 73, 0, 255}, + {0, 73, 85, 255}, {0, 73, 170, 255}, {0, 73, 255, 255}, + {0, 109, 0, 255}, {0, 109, 85, 255}, {0, 109, 170, 255}, + {0, 109, 255, 255}, {0, 146, 0, 255}, {0, 146, 85, 255}, + {0, 146, 170, 255}, {0, 146, 255, 255}, {0, 182, 0, 255}, + {0, 182, 85, 255}, {0, 182, 170, 255}, {0, 182, 255, 255}, + {0, 219, 0, 255}, {0, 219, 85, 255}, {0, 219, 170, 255}, + {0, 219, 255, 255}, {0, 255, 0, 255}, {0, 255, 85, 255}, + {0, 255, 170, 255}, {0, 255, 255, 255}, {85, 0, 0, 255}, + {85, 0, 85, 255}, {85, 0, 170, 255}, {85, 0, 255, 255}, + {85, 36, 0, 255}, {85, 36, 85, 255}, {85, 36, 170, 255}, + {85, 36, 255, 255}, {85, 73, 0, 255}, {85, 73, 85, 255}, + {85, 73, 170, 255}, {85, 73, 255, 255}, {85, 109, 0, 255}, + {85, 109, 85, 255}, {85, 109, 170, 255}, {85, 109, 255, 255}, + {85, 146, 0, 255}, {85, 146, 85, 255}, {85, 146, 170, 255}, + {85, 146, 255, 255}, {85, 182, 0, 255}, {85, 182, 85, 255}, + {85, 182, 170, 255}, {85, 182, 255, 255}, {85, 219, 0, 255}, + {85, 219, 85, 255}, {85, 219, 170, 255}, {85, 219, 255, 255}, + {85, 255, 0, 255}, {85, 255, 85, 255}, {85, 255, 170, 255}, + {85, 255, 255, 255}, {170, 0, 0, 255}, {170, 0, 85, 255}, + {170, 0, 170, 255}, {170, 0, 255, 255}, {170, 36, 0, 255}, + {170, 36, 85, 255}, {170, 36, 170, 255}, {170, 36, 255, 255}, + {170, 73, 0, 255}, {170, 73, 85, 255}, {170, 73, 170, 255}, + {170, 73, 255, 255}, {170, 109, 0, 255}, {170, 109, 85, 255}, + {170, 109, 170, 255}, {170, 109, 255, 255}, {170, 146, 0, 255}, + {170, 146, 85, 255}, {170, 146, 170, 255}, {170, 146, 255, 255}, + {170, 182, 0, 255}, {170, 182, 85, 255}, {170, 182, 170, 255}, + {170, 182, 255, 255}, {170, 219, 0, 255}, {170, 219, 85, 255}, + {170, 219, 170, 255}, {170, 219, 255, 255}, {170, 255, 0, 255}, + {170, 255, 85, 255}, {170, 255, 170, 255}, {170, 255, 255, 255}, + {255, 0, 0, 255}, {255, 0, 85, 255}, {255, 0, 170, 255}, + {255, 0, 255, 255}, {255, 36, 0, 255}, {255, 36, 85, 255}, + {255, 36, 170, 255}, {255, 36, 255, 255}, {255, 73, 0, 255}, + {255, 73, 85, 255}, {255, 73, 170, 255}, {255, 73, 255, 255}, + {255, 109, 0, 255}, {255, 109, 85, 255}, {255, 109, 170, 255}, + {255, 109, 255, 255}, {255, 146, 0, 255}, {255, 146, 85, 255}, + {255, 146, 170, 255}, {255, 146, 255, 255}, {255, 182, 0, 255}, + {255, 182, 85, 255}, {255, 182, 170, 255}, {255, 182, 255, 255}, + {255, 219, 0, 255}, {255, 219, 85, 255}, {255, 219, 170, 255}, + {255, 219, 255, 255}, {255, 255, 0, 255}, {255, 255, 85, 255}, + {255, 255, 170, 255}, {255, 255, 255, 255}, {0, 0, 0, 255}, + {0, 0, 85, 255}, {0, 0, 170, 255}, {0, 0, 255, 255}, + {0, 36, 0, 255}, {0, 36, 85, 255}, {0, 36, 170, 255}, + {0, 36, 255, 255}, {0, 73, 0, 255}, {0, 73, 85, 255}, + {0, 73, 170, 255}, {0, 73, 255, 255}, {0, 109, 0, 255}, + {0, 109, 85, 255}, {0, 109, 170, 255}, {0, 109, 255, 255}, + {0, 146, 0, 255}, {0, 146, 85, 255}, {0, 146, 170, 255}, + {0, 146, 255, 255}, {0, 182, 0, 255}, {0, 182, 85, 255}, + {0, 182, 170, 255}, {0, 182, 255, 255}, {0, 219, 0, 255}, + {0, 219, 85, 255}, {0, 219, 170, 255}, {0, 219, 255, 255}, + {0, 255, 0, 255}, {0, 255, 85, 255}, {0, 255, 170, 255}, + {0, 255, 255, 255}, {85, 0, 0, 255}, {85, 0, 85, 255}, + {85, 0, 170, 255}, {85, 0, 255, 255}, {85, 36, 0, 255}, + {85, 36, 85, 255}, {85, 36, 170, 255}, {85, 36, 255, 255}, + {85, 73, 0, 255}, {85, 73, 85, 255}, {85, 73, 170, 255}, + {85, 73, 255, 255}, {85, 109, 0, 255}, {85, 109, 85, 255}, + {85, 109, 170, 255}, {85, 109, 255, 255}, {85, 146, 0, 255}, + {85, 146, 85, 255}, {85, 146, 170, 255}, {85, 146, 255, 255}, + {85, 182, 0, 255}, {85, 182, 85, 255}, {85, 182, 170, 255}, + {85, 182, 255, 255}, {85, 219, 0, 255}, {85, 219, 85, 255}, + {85, 219, 170, 255}, {85, 219, 255, 255}, {85, 255, 0, 255}, + {85, 255, 85, 255}, {85, 255, 170, 255}, {85, 255, 255, 255}, + {170, 0, 0, 255}, {170, 0, 85, 255}, {170, 0, 170, 255}, + {170, 0, 255, 255}, {170, 36, 0, 255}, {170, 36, 85, 255}, + {170, 36, 170, 255}, {170, 36, 255, 255}, {170, 73, 0, 255}, + {170, 73, 85, 255}, {170, 73, 170, 255}, {170, 73, 255, 255}, + {170, 109, 0, 255}, {170, 109, 85, 255}, {170, 109, 170, 255}, + {170, 109, 255, 255}, {170, 146, 0, 255}, {170, 146, 85, 255}, + {170, 146, 170, 255}, {170, 146, 255, 255}, {170, 182, 0, 255}, + {170, 182, 85, 255}, {170, 182, 170, 255}, {170, 182, 255, 255}, + {170, 219, 0, 255}, {170, 219, 85, 255}, {170, 219, 170, 255}, + {170, 219, 255, 255}, {170, 255, 0, 255}, {170, 255, 85, 255}, + {170, 255, 170, 255}, {170, 255, 255, 255}, {255, 0, 0, 255}, + {255, 0, 85, 255}, {255, 0, 170, 255}, {255, 0, 255, 255}, + {255, 36, 0, 255}, {255, 36, 85, 255}, {255, 36, 170, 255}, + {255, 36, 255, 255}, {255, 73, 0, 255}, {255, 73, 85, 255}, + {255, 73, 170, 255}, {255, 73, 255, 255}, {255, 109, 0, 255}, + {255, 109, 85, 255}, {255, 109, 170, 255}, {255, 109, 255, 255}, + {255, 146, 0, 255}, {255, 146, 85, 255}, {255, 146, 170, 255}, + {255, 146, 255, 255}, {255, 182, 0, 255}, {255, 182, 85, 255}, + {255, 182, 170, 255}, {255, 182, 255, 255}, {255, 219, 0, 255}, + {255, 219, 85, 255}, {255, 219, 170, 255}, {255, 219, 255, 255}, + {255, 255, 0, 255}, {255, 255, 85, 255}, {255, 255, 170, 255}, + {255, 255, 255, 255}}; + +static const int default_palette_size = + (int)(sizeof(default_palette_colors) / sizeof(SDL_Color)); + +#endif diff --git a/venv/Include/site/python3.9/pygame/pgarrinter.h b/venv/Include/site/python3.9/pygame/pgarrinter.h new file mode 100644 index 0000000..5ba096b --- /dev/null +++ b/venv/Include/site/python3.9/pygame/pgarrinter.h @@ -0,0 +1,26 @@ +/* array structure interface version 3 declarations */ + +#if !defined(PG_ARRAYINTER_HEADER) +#define PG_ARRAYINTER_HEADER + +static const int PAI_CONTIGUOUS = 0x01; +static const int PAI_FORTRAN = 0x02; +static const int PAI_ALIGNED = 0x100; +static const int PAI_NOTSWAPPED = 0x200; +static const int PAI_WRITEABLE = 0x400; +static const int PAI_ARR_HAS_DESCR = 0x800; + +typedef struct { + int two; /* contains the integer 2 -- simple sanity check */ + int nd; /* number of dimensions */ + char typekind; /* kind in array -- character code of typestr */ + int itemsize; /* size of each element */ + int flags; /* flags indicating how the data should be */ + /* interpreted */ + Py_intptr_t *shape; /* A length-nd array of shape information */ + Py_intptr_t *strides; /* A length-nd array of stride information */ + void *data; /* A pointer to the first element of the array */ + PyObject *descr; /* NULL or a data-description */ +} PyArrayInterface; + +#endif diff --git a/venv/Include/site/python3.9/pygame/pgbufferproxy.h b/venv/Include/site/python3.9/pygame/pgbufferproxy.h new file mode 100644 index 0000000..1507608 --- /dev/null +++ b/venv/Include/site/python3.9/pygame/pgbufferproxy.h @@ -0,0 +1,7 @@ +#ifndef PG_BUFPROXY_INTERNAL_H +#define PG_BUFPROXY_INTERNAL_H + +#include "include/pygame_bufferproxy.h" +#define PYGAMEAPI_BUFPROXY_NUMSLOTS 4 + +#endif /* ~PG_BUFPROXY_INTERNAL_H */ diff --git a/venv/Include/site/python3.9/pygame/pgcompat.h b/venv/Include/site/python3.9/pygame/pgcompat.h new file mode 100644 index 0000000..602043d --- /dev/null +++ b/venv/Include/site/python3.9/pygame/pgcompat.h @@ -0,0 +1,57 @@ +/* Python 2.x/3.x compatibility tools (internal) + */ +#ifndef PGCOMPAT_INTERNAL_H +#define PGCOMPAT_INTERNAL_H + +#include "include/pgcompat.h" + +/* Module init function returns new module instance. */ +#define MODINIT_DEFINE(mod_name) PyMODINIT_FUNC PyInit_##mod_name(void) + +/* Defaults for unicode file path encoding */ +#if defined(MS_WIN32) +#define UNICODE_DEF_FS_ERROR "replace" +#else +#define UNICODE_DEF_FS_ERROR "surrogateescape" +#endif + +#define RELATIVE_MODULE(m) ("." m) + +#ifndef Py_TPFLAGS_HAVE_NEWBUFFER +#define Py_TPFLAGS_HAVE_NEWBUFFER 0 +#endif + +#ifndef Py_TPFLAGS_HAVE_CLASS +#define Py_TPFLAGS_HAVE_CLASS 0 +#endif + +#ifndef Py_TPFLAGS_CHECKTYPES +#define Py_TPFLAGS_CHECKTYPES 0 +#endif + +#define Slice_GET_INDICES_EX(slice, length, start, stop, step, slicelength) \ + PySlice_GetIndicesEx(slice, length, start, stop, step, slicelength) + +#if defined(SDL_VERSION_ATLEAST) +#if !(SDL_VERSION_ATLEAST(2, 0, 5)) +/* These functions require SDL 2.0.5 or greater. + + https://wiki.libsdl.org/SDL_SetWindowResizable +*/ +void +SDL_SetWindowResizable(SDL_Window *window, SDL_bool resizable); +int +SDL_GetWindowOpacity(SDL_Window *window, float *opacity); +int +SDL_SetWindowOpacity(SDL_Window *window, float opacity); +int +SDL_SetWindowModalFor(SDL_Window *modal_window, SDL_Window *parent_window); +int +SDL_SetWindowInputFocus(SDL_Window *window); +SDL_Surface * +SDL_CreateRGBSurfaceWithFormat(Uint32 flags, int width, int height, int depth, + Uint32 format); +#endif /* !(SDL_VERSION_ATLEAST(2, 0, 5)) */ +#endif /* defined(SDL_VERSION_ATLEAST) */ + +#endif /* ~PGCOMPAT_INTERNAL_H */ diff --git a/venv/Include/site/python3.9/pygame/pgopengl.h b/venv/Include/site/python3.9/pygame/pgopengl.h new file mode 100644 index 0000000..a845cbf --- /dev/null +++ b/venv/Include/site/python3.9/pygame/pgopengl.h @@ -0,0 +1,20 @@ +#if !defined(PGOPENGL_H) +#define PGOPENGL_H + +/** This header includes definitions of Opengl functions as pointer types for + ** use with the SDL function SDL_GL_GetProcAddress. + **/ + +#if defined(_WIN32) +#define GL_APIENTRY __stdcall +#else +#define GL_APIENTRY +#endif + +typedef void(GL_APIENTRY *GL_glReadPixels_Func)(int, int, int, int, + unsigned int, unsigned int, + void *); + +typedef void(GL_APIENTRY *GL_glViewport_Func)(int, int, unsigned int, + unsigned int); +#endif diff --git a/venv/Include/site/python3.9/pygame/pgplatform.h b/venv/Include/site/python3.9/pygame/pgplatform.h new file mode 100644 index 0000000..1c6c285 --- /dev/null +++ b/venv/Include/site/python3.9/pygame/pgplatform.h @@ -0,0 +1,39 @@ +/* platform/compiler adjustments (internal) */ +#ifndef PG_PLATFORM_INTERNAL_H +#define PG_PLATFORM_INTERNAL_H + +/* This must be before all else */ +#if defined(__SYMBIAN32__) && defined(OPENC) +#include +#if defined(__WINS__) +void * +_alloca(size_t size); +#define alloca _alloca +#endif /* __WINS__ */ +#endif /* defined(__SYMBIAN32__) && defined(OPENC) */ + +#include "include/pgplatform.h" + +#ifndef MIN +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#endif +#ifndef MAX +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#endif +#ifndef ABS +#define ABS(a) (((a) < 0) ? -(a) : (a)) +#endif + +#if defined(macintosh) && defined(__MWERKS__) || defined(__SYMBIAN32__) +#define PYGAME_EXPORT __declspec(export) +#else +#define PYGAME_EXPORT +#endif + +/* warnings */ +#define PG_STRINGIZE_HELPER(x) #x +#define PG_STRINGIZE(x) PG_STRINGIZE_HELPER(x) +#define PG_WARN(desc) \ + message(__FILE__ "(" PG_STRINGIZE(__LINE__) "): WARNING: " #desc) + +#endif /* ~PG_PLATFORM_INTERNAL_H */ diff --git a/venv/Include/site/python3.9/pygame/pygame.h b/venv/Include/site/python3.9/pygame/pygame.h new file mode 100644 index 0000000..d7eaf73 --- /dev/null +++ b/venv/Include/site/python3.9/pygame/pygame.h @@ -0,0 +1,32 @@ +/* + pygame - Python Game Library + Copyright (C) 2000-2001 Pete Shinners + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Pete Shinners + pete@shinners.org +*/ + +/* This will use PYGAMEAPI_DEFINE_SLOTS instead + * of PYGAMEAPI_EXTERN_SLOTS for base modules. + */ +#ifndef PYGAME_INTERNAL_H +#define PYGAME_INTERNAL_H + +#define PYGAME_H +#include "_pygame.h" + +#endif /* ~PYGAME_INTERNAL_H */ diff --git a/venv/Include/site/python3.9/pygame/scrap.h b/venv/Include/site/python3.9/pygame/scrap.h new file mode 100644 index 0000000..b3265a3 --- /dev/null +++ b/venv/Include/site/python3.9/pygame/scrap.h @@ -0,0 +1,147 @@ +/* + pygame - Python Game Library + Copyright (C) 2006, 2007 Rene Dudfield, Marcus von Appen + + Originally put in the public domain by Sam Lantinga. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef SCRAP_H +#define SCRAP_H + +/* This is unconditionally defined in Python.h */ +#if defined(_POSIX_C_SOURCE) +#undef _POSIX_C_SOURCE +#endif + +#include + +/* Handle clipboard text and data in arbitrary formats */ + +/** + * Predefined supported pygame scrap types. + */ +#define PYGAME_SCRAP_TEXT "text/plain" +#define PYGAME_SCRAP_BMP "image/bmp" +#define PYGAME_SCRAP_PPM "image/ppm" +#define PYGAME_SCRAP_PBM "image/pbm" + +/** + * The supported scrap clipboard types. + * + * This is only relevant in a X11 environment, which supports mouse + * selections as well. For Win32 and MacOS environments the default + * clipboard is used, no matter what value is passed. + */ +typedef enum { + SCRAP_CLIPBOARD, + SCRAP_SELECTION /* only supported in X11 environments. */ +} ScrapClipType; + +/** + * Macro for initialization checks. + */ +#define PYGAME_SCRAP_INIT_CHECK() \ + if (!pygame_scrap_initialized()) \ + return (PyErr_SetString(pgExc_SDLError, "scrap system not initialized."), \ + NULL) + +/** + * \brief Checks, whether the pygame scrap module was initialized. + * + * \return 1 if the modules was initialized, 0 otherwise. + */ +extern int +pygame_scrap_initialized(void); + +/** + * \brief Initializes the pygame scrap module internals. Call this before any + * other method. + * + * \return 1 on successful initialization, 0 otherwise. + */ +extern int +pygame_scrap_init(void); + +/** + * \brief Checks, whether the pygame window lost the clipboard focus or not. + * + * \return 1 if the window lost the focus, 0 otherwise. + */ +extern int +pygame_scrap_lost(void); + +/** + * \brief Places content of a specific type into the clipboard. + * + * \note For X11 the following notes are important: The following types + * are reserved for internal usage and thus will throw an error on + * setting them: "TIMESTAMP", "TARGETS", "SDL_SELECTION". + * Setting PYGAME_SCRAP_TEXT ("text/plain") will also automatically + * set the X11 types "STRING" (XA_STRING), "TEXT" and "UTF8_STRING". + * + * For Win32 the following notes are important: Setting + * PYGAME_SCRAP_TEXT ("text/plain") will also automatically set + * the Win32 type "TEXT" (CF_TEXT). + * + * For QNX the following notes are important: Setting + * PYGAME_SCRAP_TEXT ("text/plain") will also automatically set + * the QNX type "TEXT" (Ph_CL_TEXT). + * + * \param type The type of the content. + * \param srclen The length of the content. + * \param src The NULL terminated content. + * \return 1, if the content could be successfully pasted into the clipboard, + * 0 otherwise. + */ +extern int +pygame_scrap_put(char *type, int srclen, char *src); + +/** + * \brief Gets the current content from the clipboard. + * + * \note The received content does not need to be the content previously + * placed in the clipboard using pygame_put_scrap(). See the + * pygame_put_scrap() notes for more details. + * + * \param type The type of the content to receive. + * \param count The size of the returned content. + * \return The content or NULL in case of an error or if no content of the + * specified type was available. + */ +extern char * +pygame_scrap_get(char *type, unsigned long *count); + +/** + * \brief Gets the currently available content types from the clipboard. + * + * \return The different available content types or NULL in case of an + * error or if no content type is available. + */ +extern char ** +pygame_scrap_get_types(void); + +/** + * \brief Checks whether content for the specified scrap type is currently + * available in the clipboard. + * + * \param type The type to check for. + * \return 1, if there is content and 0 otherwise. + */ +extern int +pygame_scrap_contains(char *type); + +#endif /* SCRAP_H */ diff --git a/venv/Include/site/python3.9/pygame/surface.h b/venv/Include/site/python3.9/pygame/surface.h new file mode 100644 index 0000000..eb9bbed --- /dev/null +++ b/venv/Include/site/python3.9/pygame/surface.h @@ -0,0 +1,355 @@ +/* + pygame - Python Game Library + Copyright (C) 2000-2001 Pete Shinners + Copyright (C) 2007 Marcus von Appen + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Pete Shinners + pete@shinners.org +*/ + +#ifndef SURFACE_H +#define SURFACE_H + +/* This is defined in SDL.h */ +#if defined(_POSIX_C_SOURCE) +#undef _POSIX_C_SOURCE +#endif + +#include +#include "pygame.h" + +/* Blend modes */ +#define PYGAME_BLEND_ADD 0x1 +#define PYGAME_BLEND_SUB 0x2 +#define PYGAME_BLEND_MULT 0x3 +#define PYGAME_BLEND_MIN 0x4 +#define PYGAME_BLEND_MAX 0x5 + +#define PYGAME_BLEND_RGB_ADD 0x1 +#define PYGAME_BLEND_RGB_SUB 0x2 +#define PYGAME_BLEND_RGB_MULT 0x3 +#define PYGAME_BLEND_RGB_MIN 0x4 +#define PYGAME_BLEND_RGB_MAX 0x5 + +#define PYGAME_BLEND_RGBA_ADD 0x6 +#define PYGAME_BLEND_RGBA_SUB 0x7 +#define PYGAME_BLEND_RGBA_MULT 0x8 +#define PYGAME_BLEND_RGBA_MIN 0x9 +#define PYGAME_BLEND_RGBA_MAX 0x10 +#define PYGAME_BLEND_PREMULTIPLIED 0x11 +#define PYGAME_BLEND_ALPHA_SDL2 0x12 + +#if SDL_BYTEORDER == SDL_LIL_ENDIAN +#define GET_PIXEL_24(b) (b[0] + (b[1] << 8) + (b[2] << 16)) +#else +#define GET_PIXEL_24(b) (b[2] + (b[1] << 8) + (b[0] << 16)) +#endif + +#define GET_PIXEL(pxl, bpp, source) \ + switch (bpp) { \ + case 2: \ + pxl = *((Uint16 *)(source)); \ + break; \ + case 4: \ + pxl = *((Uint32 *)(source)); \ + break; \ + default: { \ + Uint8 *b = (Uint8 *)source; \ + pxl = GET_PIXEL_24(b); \ + } break; \ + } + +#define GET_PIXELVALS(_sR, _sG, _sB, _sA, px, fmt, ppa) \ + SDL_GetRGBA(px, fmt, &(_sR), &(_sG), &(_sB), &(_sA)); \ + if (!ppa) { \ + _sA = 255; \ + } + +#define GET_PIXELVALS_1(sr, sg, sb, sa, _src, _fmt) \ + sr = _fmt->palette->colors[*((Uint8 *)(_src))].r; \ + sg = _fmt->palette->colors[*((Uint8 *)(_src))].g; \ + sb = _fmt->palette->colors[*((Uint8 *)(_src))].b; \ + sa = 255; + +/* For 1 byte palette pixels */ +#define SET_PIXELVAL(px, fmt, _dR, _dG, _dB, _dA) \ + *(px) = (Uint8)SDL_MapRGBA(fmt, _dR, _dG, _dB, _dA) + +#if SDL_BYTEORDER == SDL_LIL_ENDIAN +#define SET_OFFSETS_24(or, og, ob, fmt) \ + { \ + or = (fmt->Rshift == 0 ? 0 : fmt->Rshift == 8 ? 1 : 2); \ + og = (fmt->Gshift == 0 ? 0 : fmt->Gshift == 8 ? 1 : 2); \ + ob = (fmt->Bshift == 0 ? 0 : fmt->Bshift == 8 ? 1 : 2); \ + } + +#define SET_OFFSETS_32(or, og, ob, fmt) \ + { \ + or = (fmt->Rshift == 0 ? 0 \ + : fmt->Rshift == 8 ? 1 \ + : fmt->Rshift == 16 ? 2 \ + : 3); \ + og = (fmt->Gshift == 0 ? 0 \ + : fmt->Gshift == 8 ? 1 \ + : fmt->Gshift == 16 ? 2 \ + : 3); \ + ob = (fmt->Bshift == 0 ? 0 \ + : fmt->Bshift == 8 ? 1 \ + : fmt->Bshift == 16 ? 2 \ + : 3); \ + } +#else +#define SET_OFFSETS_24(or, og, ob, fmt) \ + { \ + or = (fmt->Rshift == 0 ? 2 : fmt->Rshift == 8 ? 1 : 0); \ + og = (fmt->Gshift == 0 ? 2 : fmt->Gshift == 8 ? 1 : 0); \ + ob = (fmt->Bshift == 0 ? 2 : fmt->Bshift == 8 ? 1 : 0); \ + } + +#define SET_OFFSETS_32(or, og, ob, fmt) \ + { \ + or = (fmt->Rshift == 0 ? 3 \ + : fmt->Rshift == 8 ? 2 \ + : fmt->Rshift == 16 ? 1 \ + : 0); \ + og = (fmt->Gshift == 0 ? 3 \ + : fmt->Gshift == 8 ? 2 \ + : fmt->Gshift == 16 ? 1 \ + : 0); \ + ob = (fmt->Bshift == 0 ? 3 \ + : fmt->Bshift == 8 ? 2 \ + : fmt->Bshift == 16 ? 1 \ + : 0); \ + } +#endif + +#define CREATE_PIXEL(buf, r, g, b, a, bp, ft) \ + switch (bp) { \ + case 2: \ + *((Uint16 *)(buf)) = ((r >> ft->Rloss) << ft->Rshift) | \ + ((g >> ft->Gloss) << ft->Gshift) | \ + ((b >> ft->Bloss) << ft->Bshift) | \ + ((a >> ft->Aloss) << ft->Ashift); \ + break; \ + case 4: \ + *((Uint32 *)(buf)) = ((r >> ft->Rloss) << ft->Rshift) | \ + ((g >> ft->Gloss) << ft->Gshift) | \ + ((b >> ft->Bloss) << ft->Bshift) | \ + ((a >> ft->Aloss) << ft->Ashift); \ + break; \ + } + +/* Pretty good idea from Tom Duff :-). */ +#define LOOP_UNROLLED4(code, n, width) \ + n = (width + 3) / 4; \ + switch (width & 3) { \ + case 0: \ + do { \ + code; \ + case 3: \ + code; \ + case 2: \ + code; \ + case 1: \ + code; \ + } while (--n > 0); \ + } + +/* Used in the srcbpp == dstbpp == 1 blend functions */ +#define REPEAT_3(code) \ + code; \ + code; \ + code; + +#define REPEAT_4(code) \ + code; \ + code; \ + code; \ + code; + +#define BLEND_ADD(tmp, sR, sG, sB, sA, dR, dG, dB, dA) \ + tmp = dR + sR; \ + dR = (tmp <= 255 ? tmp : 255); \ + tmp = dG + sG; \ + dG = (tmp <= 255 ? tmp : 255); \ + tmp = dB + sB; \ + dB = (tmp <= 255 ? tmp : 255); + +#define BLEND_SUB(tmp, sR, sG, sB, sA, dR, dG, dB, dA) \ + tmp = dR - sR; \ + dR = (tmp >= 0 ? tmp : 0); \ + tmp = dG - sG; \ + dG = (tmp >= 0 ? tmp : 0); \ + tmp = dB - sB; \ + dB = (tmp >= 0 ? tmp : 0); + +#define BLEND_MULT(sR, sG, sB, sA, dR, dG, dB, dA) \ + dR = (dR && sR) ? (dR * sR) >> 8 : 0; \ + dG = (dG && sG) ? (dG * sG) >> 8 : 0; \ + dB = (dB && sB) ? (dB * sB) >> 8 : 0; + +#define BLEND_MIN(sR, sG, sB, sA, dR, dG, dB, dA) \ + if (sR < dR) { \ + dR = sR; \ + } \ + if (sG < dG) { \ + dG = sG; \ + } \ + if (sB < dB) { \ + dB = sB; \ + } + +#define BLEND_MAX(sR, sG, sB, sA, dR, dG, dB, dA) \ + if (sR > dR) { \ + dR = sR; \ + } \ + if (sG > dG) { \ + dG = sG; \ + } \ + if (sB > dB) { \ + dB = sB; \ + } + +#define BLEND_RGBA_ADD(tmp, sR, sG, sB, sA, dR, dG, dB, dA) \ + tmp = dR + sR; \ + dR = (tmp <= 255 ? tmp : 255); \ + tmp = dG + sG; \ + dG = (tmp <= 255 ? tmp : 255); \ + tmp = dB + sB; \ + dB = (tmp <= 255 ? tmp : 255); \ + tmp = dA + sA; \ + dA = (tmp <= 255 ? tmp : 255); + +#define BLEND_RGBA_SUB(tmp, sR, sG, sB, sA, dR, dG, dB, dA) \ + tmp = dR - sR; \ + dR = (tmp >= 0 ? tmp : 0); \ + tmp = dG - sG; \ + dG = (tmp >= 0 ? tmp : 0); \ + tmp = dB - sB; \ + dB = (tmp >= 0 ? tmp : 0); \ + tmp = dA - sA; \ + dA = (tmp >= 0 ? tmp : 0); + +#define BLEND_RGBA_MULT(sR, sG, sB, sA, dR, dG, dB, dA) \ + dR = (dR && sR) ? (dR * sR) >> 8 : 0; \ + dG = (dG && sG) ? (dG * sG) >> 8 : 0; \ + dB = (dB && sB) ? (dB * sB) >> 8 : 0; \ + dA = (dA && sA) ? (dA * sA) >> 8 : 0; + +#define BLEND_RGBA_MIN(sR, sG, sB, sA, dR, dG, dB, dA) \ + if (sR < dR) { \ + dR = sR; \ + } \ + if (sG < dG) { \ + dG = sG; \ + } \ + if (sB < dB) { \ + dB = sB; \ + } \ + if (sA < dA) { \ + dA = sA; \ + } + +#define BLEND_RGBA_MAX(sR, sG, sB, sA, dR, dG, dB, dA) \ + if (sR > dR) { \ + dR = sR; \ + } \ + if (sG > dG) { \ + dG = sG; \ + } \ + if (sB > dB) { \ + dB = sB; \ + } \ + if (sA > dA) { \ + dA = sA; \ + } + +#if 1 +/* Choose an alpha blend equation. If the sign is preserved on a right shift + * then use a specialized, faster, equation. Otherwise a more general form, + * where all additions are done before the shift, is needed. + */ +#if (-1 >> 1) < 0 +#define ALPHA_BLEND_COMP(sC, dC, sA) ((((sC - dC) * sA + sC) >> 8) + dC) +#else +#define ALPHA_BLEND_COMP(sC, dC, sA) (((dC << 8) + (sC - dC) * sA + sC) >> 8) +#endif + +#define ALPHA_BLEND(sR, sG, sB, sA, dR, dG, dB, dA) \ + do { \ + if (dA) { \ + dR = ALPHA_BLEND_COMP(sR, dR, sA); \ + dG = ALPHA_BLEND_COMP(sG, dG, sA); \ + dB = ALPHA_BLEND_COMP(sB, dB, sA); \ + dA = sA + dA - ((sA * dA) / 255); \ + } \ + else { \ + dR = sR; \ + dG = sG; \ + dB = sB; \ + dA = sA; \ + } \ + } while (0) + +#define ALPHA_BLEND_PREMULTIPLIED_COMP(sC, dC, sA) \ + (sC + dC - ((dC + 1) * sA >> 8)) + +#define ALPHA_BLEND_PREMULTIPLIED(tmp, sR, sG, sB, sA, dR, dG, dB, dA) \ + do { \ + dR = ALPHA_BLEND_PREMULTIPLIED_COMP(sR, dR, sA); \ + dG = ALPHA_BLEND_PREMULTIPLIED_COMP(sG, dG, sA); \ + dB = ALPHA_BLEND_PREMULTIPLIED_COMP(sB, dB, sA); \ + dA = ALPHA_BLEND_PREMULTIPLIED_COMP(sA, dA, sA); \ + } while (0) +#elif 0 + +#define ALPHA_BLEND(sR, sG, sB, sA, dR, dG, dB, dA) \ + do { \ + if (sA) { \ + if (dA && sA < 255) { \ + int dContrib = dA * (255 - sA) / 255; \ + dA = sA + dA - ((sA * dA) / 255); \ + dR = (dR * dContrib + sR * sA) / dA; \ + dG = (dG * dContrib + sG * sA) / dA; \ + dB = (dB * dContrib + sB * sA) / dA; \ + } \ + else { \ + dR = sR; \ + dG = sG; \ + dB = sB; \ + dA = sA; \ + } \ + } \ + } while (0) +#endif + +int +surface_fill_blend(SDL_Surface *surface, SDL_Rect *rect, Uint32 color, + int blendargs); + +void +surface_respect_clip_rect(SDL_Surface *surface, SDL_Rect *rect); + +int +pygame_AlphaBlit(SDL_Surface *src, SDL_Rect *srcrect, SDL_Surface *dst, + SDL_Rect *dstrect, int the_args); + +int +pygame_Blit(SDL_Surface *src, SDL_Rect *srcrect, SDL_Surface *dst, + SDL_Rect *dstrect, int the_args); + +#endif /* SURFACE_H */ diff --git a/venv/Lib/site-packages/_distutils_hack/__init__.py b/venv/Lib/site-packages/_distutils_hack/__init__.py new file mode 100644 index 0000000..605a6ed --- /dev/null +++ b/venv/Lib/site-packages/_distutils_hack/__init__.py @@ -0,0 +1,187 @@ +# don't import any costly modules +import sys +import os + + +is_pypy = '__pypy__' in sys.builtin_module_names + + +def warn_distutils_present(): + if 'distutils' not in sys.modules: + return + if is_pypy and sys.version_info < (3, 7): + # PyPy for 3.6 unconditionally imports distutils, so bypass the warning + # https://foss.heptapod.net/pypy/pypy/-/blob/be829135bc0d758997b3566062999ee8b23872b4/lib-python/3/site.py#L250 + return + import warnings + warnings.warn( + "Distutils was imported before Setuptools, but importing Setuptools " + "also replaces the `distutils` module in `sys.modules`. This may lead " + "to undesirable behaviors or errors. To avoid these issues, avoid " + "using distutils directly, ensure that setuptools is installed in the " + "traditional way (e.g. not an editable install), and/or make sure " + "that setuptools is always imported before distutils.") + + +def clear_distutils(): + if 'distutils' not in sys.modules: + return + import warnings + warnings.warn("Setuptools is replacing distutils.") + mods = [ + name for name in sys.modules + if name == "distutils" or name.startswith("distutils.") + ] + for name in mods: + del sys.modules[name] + + +def enabled(): + """ + Allow selection of distutils by environment variable. + """ + which = os.environ.get('SETUPTOOLS_USE_DISTUTILS', 'local') + return which == 'local' + + +def ensure_local_distutils(): + import importlib + clear_distutils() + + # With the DistutilsMetaFinder in place, + # perform an import to cause distutils to be + # loaded from setuptools._distutils. Ref #2906. + with shim(): + importlib.import_module('distutils') + + # check that submodules load as expected + core = importlib.import_module('distutils.core') + assert '_distutils' in core.__file__, core.__file__ + assert 'setuptools._distutils.log' not in sys.modules + + +def do_override(): + """ + Ensure that the local copy of distutils is preferred over stdlib. + + See https://github.com/pypa/setuptools/issues/417#issuecomment-392298401 + for more motivation. + """ + if enabled(): + warn_distutils_present() + ensure_local_distutils() + + +class _TrivialRe: + def __init__(self, *patterns): + self._patterns = patterns + + def match(self, string): + return all(pat in string for pat in self._patterns) + + +class DistutilsMetaFinder: + def find_spec(self, fullname, path, target=None): + if path is not None: + return + + method_name = 'spec_for_{fullname}'.format(**locals()) + method = getattr(self, method_name, lambda: None) + return method() + + def spec_for_distutils(self): + if self.is_cpython(): + return + + import importlib + import importlib.abc + import importlib.util + + try: + mod = importlib.import_module('setuptools._distutils') + except Exception: + # There are a couple of cases where setuptools._distutils + # may not be present: + # - An older Setuptools without a local distutils is + # taking precedence. Ref #2957. + # - Path manipulation during sitecustomize removes + # setuptools from the path but only after the hook + # has been loaded. Ref #2980. + # In either case, fall back to stdlib behavior. + return + + class DistutilsLoader(importlib.abc.Loader): + + def create_module(self, spec): + mod.__name__ = 'distutils' + return mod + + def exec_module(self, module): + pass + + return importlib.util.spec_from_loader( + 'distutils', DistutilsLoader(), origin=mod.__file__ + ) + + @staticmethod + def is_cpython(): + """ + Suppress supplying distutils for CPython (build and tests). + Ref #2965 and #3007. + """ + return os.path.isfile('pybuilddir.txt') + + def spec_for_pip(self): + """ + Ensure stdlib distutils when running under pip. + See pypa/pip#8761 for rationale. + """ + if self.pip_imported_during_build(): + return + clear_distutils() + self.spec_for_distutils = lambda: None + + @classmethod + def pip_imported_during_build(cls): + """ + Detect if pip is being imported in a build script. Ref #2355. + """ + import traceback + return any( + cls.frame_file_is_setup(frame) + for frame, line in traceback.walk_stack(None) + ) + + @staticmethod + def frame_file_is_setup(frame): + """ + Return True if the indicated frame suggests a setup.py file. + """ + # some frames may not have __file__ (#2940) + return frame.f_globals.get('__file__', '').endswith('setup.py') + + +DISTUTILS_FINDER = DistutilsMetaFinder() + + +def add_shim(): + DISTUTILS_FINDER in sys.meta_path or insert_shim() + + +class shim: + def __enter__(self): + insert_shim() + + def __exit__(self, exc, value, tb): + remove_shim() + + +def insert_shim(): + sys.meta_path.insert(0, DISTUTILS_FINDER) + + +def remove_shim(): + try: + sys.meta_path.remove(DISTUTILS_FINDER) + except ValueError: + pass diff --git a/venv/Lib/site-packages/_distutils_hack/__pycache__/__init__.cpython-39.pyc b/venv/Lib/site-packages/_distutils_hack/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..eb021d6f744bc35366fce61fa9995af51b29b418 GIT binary patch literal 6890 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/_distutils_hack/__pycache__/override.cpython-39.pyc b/venv/Lib/site-packages/_distutils_hack/__pycache__/override.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d091cd4c180d01344069e6bda97a90de796f0a76 GIT binary patch literal 231 zcmYe~<>g`kf)07LBpo3A7{oyaOhAqU5ElyoiByIZhGxbEj0+hU8B!R788n%q_~TPD zi%UvNGINUKGZK@t{WO_wamB}H<`(1^mBhzKai`?R=a;1x6=kNRu4E_z83!hQMLJu> zgche36~`pzhWESX_<`n=wpMjVG01?YVJpcdz literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/_distutils_hack/override.py b/venv/Lib/site-packages/_distutils_hack/override.py new file mode 100644 index 0000000..2cc433a --- /dev/null +++ b/venv/Lib/site-packages/_distutils_hack/override.py @@ -0,0 +1 @@ +__import__('_distutils_hack').do_override() diff --git a/venv/Lib/site-packages/distutils-precedence.pth b/venv/Lib/site-packages/distutils-precedence.pth new file mode 100644 index 0000000..7f009fe --- /dev/null +++ b/venv/Lib/site-packages/distutils-precedence.pth @@ -0,0 +1 @@ +import os; var = 'SETUPTOOLS_USE_DISTUTILS'; enabled = os.environ.get(var, 'local') == 'local'; enabled and __import__('_distutils_hack').add_shim(); diff --git a/venv/Lib/site-packages/pip-22.0.4.dist-info/INSTALLER b/venv/Lib/site-packages/pip-22.0.4.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/venv/Lib/site-packages/pip-22.0.4.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/venv/Lib/site-packages/pip-22.0.4.dist-info/LICENSE.txt b/venv/Lib/site-packages/pip-22.0.4.dist-info/LICENSE.txt new file mode 100644 index 0000000..8e7b65e --- /dev/null +++ b/venv/Lib/site-packages/pip-22.0.4.dist-info/LICENSE.txt @@ -0,0 +1,20 @@ +Copyright (c) 2008-present The pip developers (see AUTHORS.txt file) + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/venv/Lib/site-packages/pip-22.0.4.dist-info/METADATA b/venv/Lib/site-packages/pip-22.0.4.dist-info/METADATA new file mode 100644 index 0000000..4e68399 --- /dev/null +++ b/venv/Lib/site-packages/pip-22.0.4.dist-info/METADATA @@ -0,0 +1,92 @@ +Metadata-Version: 2.1 +Name: pip +Version: 22.0.4 +Summary: The PyPA recommended tool for installing Python packages. +Home-page: https://pip.pypa.io/ +Author: The pip developers +Author-email: distutils-sig@python.org +License: MIT +Project-URL: Documentation, https://pip.pypa.io +Project-URL: Source, https://github.com/pypa/pip +Project-URL: Changelog, https://pip.pypa.io/en/stable/news/ +Platform: UNKNOWN +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: MIT License +Classifier: Topic :: Software Development :: Build Tools +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3 :: Only +Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: 3.10 +Classifier: Programming Language :: Python :: Implementation :: CPython +Classifier: Programming Language :: Python :: Implementation :: PyPy +Requires-Python: >=3.7 +License-File: LICENSE.txt + +pip - The Python Package Installer +================================== + +.. image:: https://img.shields.io/pypi/v/pip.svg + :target: https://pypi.org/project/pip/ + +.. image:: https://readthedocs.org/projects/pip/badge/?version=latest + :target: https://pip.pypa.io/en/latest + +pip is the `package installer`_ for Python. You can use pip to install packages from the `Python Package Index`_ and other indexes. + +Please take a look at our documentation for how to install and use pip: + +* `Installation`_ +* `Usage`_ + +We release updates regularly, with a new version every 3 months. Find more details in our documentation: + +* `Release notes`_ +* `Release process`_ + +In pip 20.3, we've `made a big improvement to the heart of pip`_; `learn more`_. We want your input, so `sign up for our user experience research studies`_ to help us do it right. + +**Note**: pip 21.0, in January 2021, removed Python 2 support, per pip's `Python 2 support policy`_. Please migrate to Python 3. + +If you find bugs, need help, or want to talk to the developers, please use our mailing lists or chat rooms: + +* `Issue tracking`_ +* `Discourse channel`_ +* `User IRC`_ + +If you want to get involved head over to GitHub to get the source code, look at our development documentation and feel free to jump on the developer mailing lists and chat rooms: + +* `GitHub page`_ +* `Development documentation`_ +* `Development mailing list`_ +* `Development IRC`_ + +Code of Conduct +--------------- + +Everyone interacting in the pip project's codebases, issue trackers, chat +rooms, and mailing lists is expected to follow the `PSF Code of Conduct`_. + +.. _package installer: https://packaging.python.org/guides/tool-recommendations/ +.. _Python Package Index: https://pypi.org +.. _Installation: https://pip.pypa.io/en/stable/installation/ +.. _Usage: https://pip.pypa.io/en/stable/ +.. _Release notes: https://pip.pypa.io/en/stable/news.html +.. _Release process: https://pip.pypa.io/en/latest/development/release-process/ +.. _GitHub page: https://github.com/pypa/pip +.. _Development documentation: https://pip.pypa.io/en/latest/development +.. _made a big improvement to the heart of pip: https://pyfound.blogspot.com/2020/11/pip-20-3-new-resolver.html +.. _learn more: https://pip.pypa.io/en/latest/user_guide/#changes-to-the-pip-dependency-resolver-in-20-3-2020 +.. _sign up for our user experience research studies: https://pyfound.blogspot.com/2020/03/new-pip-resolver-to-roll-out-this-year.html +.. _Python 2 support policy: https://pip.pypa.io/en/latest/development/release-process/#python-2-support +.. _Issue tracking: https://github.com/pypa/pip/issues +.. _Discourse channel: https://discuss.python.org/c/packaging +.. _Development mailing list: https://mail.python.org/mailman3/lists/distutils-sig.python.org/ +.. _User IRC: https://kiwiirc.com/nextclient/#ircs://irc.libera.chat:+6697/pypa +.. _Development IRC: https://kiwiirc.com/nextclient/#ircs://irc.libera.chat:+6697/pypa-dev +.. _PSF Code of Conduct: https://github.com/pypa/.github/blob/main/CODE_OF_CONDUCT.md + + diff --git a/venv/Lib/site-packages/pip-22.0.4.dist-info/RECORD b/venv/Lib/site-packages/pip-22.0.4.dist-info/RECORD new file mode 100644 index 0000000..2ff22f8 --- /dev/null +++ b/venv/Lib/site-packages/pip-22.0.4.dist-info/RECORD @@ -0,0 +1,1052 @@ +../../Scripts/pip.exe,sha256=RfYKY3iY1pSe2G1PbhvZHVZTyzHMesphk6tWC32M2-0,106390 +../../Scripts/pip3.9.exe,sha256=RfYKY3iY1pSe2G1PbhvZHVZTyzHMesphk6tWC32M2-0,106390 +../../Scripts/pip3.exe,sha256=RfYKY3iY1pSe2G1PbhvZHVZTyzHMesphk6tWC32M2-0,106390 +pip-22.0.4.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +pip-22.0.4.dist-info/LICENSE.txt,sha256=Y0MApmnUmurmWxLGxIySTFGkzfPR_whtw0VtyLyqIQQ,1093 +pip-22.0.4.dist-info/METADATA,sha256=bGtDzdgW1AF93Nx32ySc78yQHtHkOrRD146Dvsz85CM,4166 +pip-22.0.4.dist-info/RECORD,, +pip-22.0.4.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92 +pip-22.0.4.dist-info/entry_points.txt,sha256=5ExSa1s54zSPNA_1epJn5SX06786S8k5YHwskMvVYzw,125 +pip-22.0.4.dist-info/top_level.txt,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +pip/__init__.py,sha256=b_avKym1xgWv1_1CobpKDp59sdjm_9nwB7sencJQUEY,357 +pip/__main__.py,sha256=mXwWDftNLMKfwVqKFWGE_uuBZvGSIiUELhLkeysIuZc,1198 +pip/__pycache__/__init__.cpython-39.pyc,, +pip/__pycache__/__main__.cpython-39.pyc,, +pip/_internal/__init__.py,sha256=nnFCuxrPMgALrIDxSoy-H6Zj4W4UY60D-uL1aJyq0pc,573 +pip/_internal/__pycache__/__init__.cpython-39.pyc,, +pip/_internal/__pycache__/build_env.cpython-39.pyc,, +pip/_internal/__pycache__/cache.cpython-39.pyc,, +pip/_internal/__pycache__/configuration.cpython-39.pyc,, +pip/_internal/__pycache__/exceptions.cpython-39.pyc,, +pip/_internal/__pycache__/main.cpython-39.pyc,, +pip/_internal/__pycache__/pyproject.cpython-39.pyc,, +pip/_internal/__pycache__/self_outdated_check.cpython-39.pyc,, +pip/_internal/__pycache__/wheel_builder.cpython-39.pyc,, +pip/_internal/build_env.py,sha256=QAsnxJFvj74jS2cZUcxk7zXLvrtAYiRL0EkSPkpSJTo,9739 +pip/_internal/cache.py,sha256=71eaYwrls34HJ6gzbmmYiotiKhPNFTM_tqYJXD5nf3s,9441 +pip/_internal/cli/__init__.py,sha256=FkHBgpxxb-_gd6r1FjnNhfMOzAUYyXoXKJ6abijfcFU,132 +pip/_internal/cli/__pycache__/__init__.cpython-39.pyc,, +pip/_internal/cli/__pycache__/autocompletion.cpython-39.pyc,, +pip/_internal/cli/__pycache__/base_command.cpython-39.pyc,, +pip/_internal/cli/__pycache__/cmdoptions.cpython-39.pyc,, +pip/_internal/cli/__pycache__/command_context.cpython-39.pyc,, +pip/_internal/cli/__pycache__/main.cpython-39.pyc,, +pip/_internal/cli/__pycache__/main_parser.cpython-39.pyc,, +pip/_internal/cli/__pycache__/parser.cpython-39.pyc,, +pip/_internal/cli/__pycache__/progress_bars.cpython-39.pyc,, +pip/_internal/cli/__pycache__/req_command.cpython-39.pyc,, +pip/_internal/cli/__pycache__/spinners.cpython-39.pyc,, +pip/_internal/cli/__pycache__/status_codes.cpython-39.pyc,, +pip/_internal/cli/autocompletion.py,sha256=wY2JPZY2Eji1vhR7bVo-yCBPJ9LCy6P80iOAhZD1Vi8,6676 +pip/_internal/cli/base_command.py,sha256=zYHdQssEkCvWHYf3dtIApaVaxOwAh3maA61nVxaZF2M,8152 +pip/_internal/cli/cmdoptions.py,sha256=TTYO0nxK9YyLwrXk1NHrn7X3dbGoqdV02Yb8kdVoVhc,28526 +pip/_internal/cli/command_context.py,sha256=a1pBBvvGLDiZ1Kw64_4tT6HmRTwYDoYy8JFgG5Czn7s,760 +pip/_internal/cli/main.py,sha256=ioJ8IVlb2K1qLOxR-tXkee9lURhYV89CDM71MKag7YY,2472 +pip/_internal/cli/main_parser.py,sha256=Q9TnytfuC5Z2JSjBFWVGtEdYLFy7rukNIb04movHdAo,2614 +pip/_internal/cli/parser.py,sha256=CDXTuFr2UD8ozOlZYf1KDziQdo9-X_IaYOiUcyJQwrA,10788 +pip/_internal/cli/progress_bars.py,sha256=_52w11WoZrvDSR3oItLWvLrEZFUKAfLf4Y6I6WtOnIU,10339 +pip/_internal/cli/req_command.py,sha256=VwqonOy18QwZsRsVjHhp-6w15fG9x3Ltwoa8yJqQno8,18669 +pip/_internal/cli/spinners.py,sha256=TFhjxtOnLeNJ5YmRvQm4eKPgPbJNkZiqO8jOXuxRaYU,5076 +pip/_internal/cli/status_codes.py,sha256=sEFHUaUJbqv8iArL3HAtcztWZmGOFX01hTesSytDEh0,116 +pip/_internal/commands/__init__.py,sha256=Vc1HjsLEtyCh7506OozPHPKXe2Hk-z9cFkFF3BMj1lM,3736 +pip/_internal/commands/__pycache__/__init__.cpython-39.pyc,, +pip/_internal/commands/__pycache__/cache.cpython-39.pyc,, +pip/_internal/commands/__pycache__/check.cpython-39.pyc,, +pip/_internal/commands/__pycache__/completion.cpython-39.pyc,, +pip/_internal/commands/__pycache__/configuration.cpython-39.pyc,, +pip/_internal/commands/__pycache__/debug.cpython-39.pyc,, +pip/_internal/commands/__pycache__/download.cpython-39.pyc,, +pip/_internal/commands/__pycache__/freeze.cpython-39.pyc,, +pip/_internal/commands/__pycache__/hash.cpython-39.pyc,, +pip/_internal/commands/__pycache__/help.cpython-39.pyc,, +pip/_internal/commands/__pycache__/index.cpython-39.pyc,, +pip/_internal/commands/__pycache__/install.cpython-39.pyc,, +pip/_internal/commands/__pycache__/list.cpython-39.pyc,, +pip/_internal/commands/__pycache__/search.cpython-39.pyc,, +pip/_internal/commands/__pycache__/show.cpython-39.pyc,, +pip/_internal/commands/__pycache__/uninstall.cpython-39.pyc,, +pip/_internal/commands/__pycache__/wheel.cpython-39.pyc,, +pip/_internal/commands/cache.py,sha256=p9gvc6W_xgxE2zO0o8NXqO1gGJEinEK42qEC-a7Cnuk,7524 +pip/_internal/commands/check.py,sha256=0gjXR7j36xJT5cs2heYU_dfOfpnFfzX8OoPNNoKhqdM,1685 +pip/_internal/commands/completion.py,sha256=kTG_I1VR3N5kGC4Ma9pQTSoY9Q1URCrNyseHSQ-rCL4,2958 +pip/_internal/commands/configuration.py,sha256=arE8vLstjBg-Ar1krXF-bBmT1qBtnL7Fpk-NVh38a0U,8944 +pip/_internal/commands/debug.py,sha256=krET-y45CnQzXwKR1qA3M_tJE4LE2vnQtm3yfGyDSnE,6629 +pip/_internal/commands/download.py,sha256=gVIAEOcpWolhRj9hl89Qzn52G2b_pcZ8naXhxaXobdo,4942 +pip/_internal/commands/freeze.py,sha256=gCjoD6foBZPBAAYx5t8zZLkJhsF_ZRtnb3dPuD7beO8,2951 +pip/_internal/commands/hash.py,sha256=EVVOuvGtoPEdFi8SNnmdqlCQrhCxV-kJsdwtdcCnXGQ,1703 +pip/_internal/commands/help.py,sha256=gcc6QDkcgHMOuAn5UxaZwAStsRBrnGSn_yxjS57JIoM,1132 +pip/_internal/commands/index.py,sha256=8pYkICUJlccjm3E83b7UuZ5DtOfLh1N7ZHXAgkajjHo,4849 +pip/_internal/commands/install.py,sha256=YVygBF6vfrNi0jmdNBCM6bcoWb7vaALEGG1--8Mmf88,27893 +pip/_internal/commands/list.py,sha256=tTjZ7u0VIh3uhnX231Q9pwt6ObT_zrDfixRQvgpJAvM,12221 +pip/_internal/commands/search.py,sha256=sbBZiARRc050QquOKcCvOr2K3XLsoYebLKZGRi__iUI,5697 +pip/_internal/commands/show.py,sha256=2VicM3jF0YWgn4O1jG_QF5oxOT0ln57VDu1NE6hqWcM,5859 +pip/_internal/commands/uninstall.py,sha256=DNTYAGJNljMO_YYBxrpcwj0FEl7lo_P55_98O6g2TNk,3526 +pip/_internal/commands/wheel.py,sha256=7HAjLclZxIzBrX6JmhmGBVxH5xrjaBYCtSdpQi1pWCE,6206 +pip/_internal/configuration.py,sha256=qmCX3uuVM73PQeAuWQHic22bhops8s31B8k02nFAoiQ,13171 +pip/_internal/distributions/__init__.py,sha256=Hq6kt6gXBgjNit5hTTWLAzeCNOKoB-N0pGYSqehrli8,858 +pip/_internal/distributions/__pycache__/__init__.cpython-39.pyc,, +pip/_internal/distributions/__pycache__/base.cpython-39.pyc,, +pip/_internal/distributions/__pycache__/installed.cpython-39.pyc,, +pip/_internal/distributions/__pycache__/sdist.cpython-39.pyc,, +pip/_internal/distributions/__pycache__/wheel.cpython-39.pyc,, +pip/_internal/distributions/base.py,sha256=3FUYD8Gb4YuSu3pggC_FRctZBDbpm5ZK89tPksIUjoE,1172 +pip/_internal/distributions/installed.py,sha256=HzfNRu3smoOm54m8H2iK6LHzBx6_DEnka4OPEsizbXg,680 +pip/_internal/distributions/sdist.py,sha256=0nJvU1RhZtbwaeYtLbzSwYrbGRcY6IgNsWdEhAHROK8,5499 +pip/_internal/distributions/wheel.py,sha256=-NgzdIs-w_hcer_U81yzgpVTljJRg5m79xufqvbjv0s,1115 +pip/_internal/exceptions.py,sha256=U-dV1ixkSz6NAU6Aw9dosKi2EzZ5D3BA7ilYZuTLKeU,20912 +pip/_internal/index/__init__.py,sha256=vpt-JeTZefh8a-FC22ZeBSXFVbuBcXSGiILhQZJaNpQ,30 +pip/_internal/index/__pycache__/__init__.cpython-39.pyc,, +pip/_internal/index/__pycache__/collector.cpython-39.pyc,, +pip/_internal/index/__pycache__/package_finder.cpython-39.pyc,, +pip/_internal/index/__pycache__/sources.cpython-39.pyc,, +pip/_internal/index/collector.py,sha256=E4yZHzlzPtaXg2BxaugrNg1Jwtwgs4gC-Q_0bzYrBU4,19671 +pip/_internal/index/package_finder.py,sha256=9UVg-7582nYNEWa0cIIl8otzPm4mlfyrQVuozAcssLo,36783 +pip/_internal/index/sources.py,sha256=SVyPitv08-Qalh2_Bk5diAJ9GAA_d-a93koouQodAG0,6557 +pip/_internal/locations/__init__.py,sha256=ergvPwlfNTmQYFmaRYbj--ZwTN5izgTL9KE5d0FB7-8,17362 +pip/_internal/locations/__pycache__/__init__.cpython-39.pyc,, +pip/_internal/locations/__pycache__/_distutils.cpython-39.pyc,, +pip/_internal/locations/__pycache__/_sysconfig.cpython-39.pyc,, +pip/_internal/locations/__pycache__/base.cpython-39.pyc,, +pip/_internal/locations/_distutils.py,sha256=Sk7tw8ZP1DWMYJ8MibABsa8IME2Ejv1PKeGlYQCBTZc,5871 +pip/_internal/locations/_sysconfig.py,sha256=LQNKTJKyjVqxXaPntlBwdUqTG1xwYf6GVCKMbyRJx5M,7918 +pip/_internal/locations/base.py,sha256=x5D1ONktmPJd8nnUTh-ELsAJ7fiXA-k-0a_vhfi2_Us,1579 +pip/_internal/main.py,sha256=r-UnUe8HLo5XFJz8inTcOOTiu_sxNhgHb6VwlGUllOI,340 +pip/_internal/metadata/__init__.py,sha256=iGoDbe_iTXQTIAEVy9f7dm-VQfZANO8kkwFr1CpqxqI,2036 +pip/_internal/metadata/__pycache__/__init__.cpython-39.pyc,, +pip/_internal/metadata/__pycache__/base.cpython-39.pyc,, +pip/_internal/metadata/__pycache__/pkg_resources.cpython-39.pyc,, +pip/_internal/metadata/base.py,sha256=SCRPtShrtPy0lfFxuaFTgJJHsRXToGFToQUAZoBBbeA,19429 +pip/_internal/metadata/pkg_resources.py,sha256=wAnEtrcgH9YtV996MfoBjR2hGLHvi3uxk0vUOHbqBak,9456 +pip/_internal/models/__init__.py,sha256=3DHUd_qxpPozfzouoqa9g9ts1Czr5qaHfFxbnxriepM,63 +pip/_internal/models/__pycache__/__init__.cpython-39.pyc,, +pip/_internal/models/__pycache__/candidate.cpython-39.pyc,, +pip/_internal/models/__pycache__/direct_url.cpython-39.pyc,, +pip/_internal/models/__pycache__/format_control.cpython-39.pyc,, +pip/_internal/models/__pycache__/index.cpython-39.pyc,, +pip/_internal/models/__pycache__/link.cpython-39.pyc,, +pip/_internal/models/__pycache__/scheme.cpython-39.pyc,, +pip/_internal/models/__pycache__/search_scope.cpython-39.pyc,, +pip/_internal/models/__pycache__/selection_prefs.cpython-39.pyc,, +pip/_internal/models/__pycache__/target_python.cpython-39.pyc,, +pip/_internal/models/__pycache__/wheel.cpython-39.pyc,, +pip/_internal/models/candidate.py,sha256=6pcABsaR7CfIHlbJbr2_kMkVJFL_yrYjTx6SVWUnCPQ,990 +pip/_internal/models/direct_url.py,sha256=7XtGQSLLDQb5ZywI2EMnnLcddtf5CJLx44lMtTHPxFw,6350 +pip/_internal/models/format_control.py,sha256=DJpMYjxeYKKQdwNcML2_F0vtAh-qnKTYe-CpTxQe-4g,2520 +pip/_internal/models/index.py,sha256=tYnL8oxGi4aSNWur0mG8DAP7rC6yuha_MwJO8xw0crI,1030 +pip/_internal/models/link.py,sha256=hoT_qsOBAgLBm9GKqpBrNF_mrEXeGXQE-aH_RX2cGgg,9817 +pip/_internal/models/scheme.py,sha256=3EFQp_ICu_shH1-TBqhl0QAusKCPDFOlgHFeN4XowWs,738 +pip/_internal/models/search_scope.py,sha256=LwloG0PJAmtI1hFXIypsD95kWE9xfR5hf_a2v1Vw7sk,4520 +pip/_internal/models/selection_prefs.py,sha256=KZdi66gsR-_RUXUr9uejssk3rmTHrQVJWeNA2sV-VSY,1907 +pip/_internal/models/target_python.py,sha256=qKpZox7J8NAaPmDs5C_aniwfPDxzvpkrCKqfwndG87k,3858 +pip/_internal/models/wheel.py,sha256=hN9Ub-m-cAJCajCcQHyQNsqpcDCbPPDlEzBDwaBMc14,3500 +pip/_internal/network/__init__.py,sha256=jf6Tt5nV_7zkARBrKojIXItgejvoegVJVKUbhAa5Ioc,50 +pip/_internal/network/__pycache__/__init__.cpython-39.pyc,, +pip/_internal/network/__pycache__/auth.cpython-39.pyc,, +pip/_internal/network/__pycache__/cache.cpython-39.pyc,, +pip/_internal/network/__pycache__/download.cpython-39.pyc,, +pip/_internal/network/__pycache__/lazy_wheel.cpython-39.pyc,, +pip/_internal/network/__pycache__/session.cpython-39.pyc,, +pip/_internal/network/__pycache__/utils.cpython-39.pyc,, +pip/_internal/network/__pycache__/xmlrpc.cpython-39.pyc,, +pip/_internal/network/auth.py,sha256=a3C7Xaa8kTJjXkdi_wrUjqaySc8Z9Yz7U6QIbXfzMyc,12190 +pip/_internal/network/cache.py,sha256=FJ3uTUo3wgf2KHmeZ3ltN9x3tQoy_0X6qNsRtNXsuL0,2131 +pip/_internal/network/download.py,sha256=12Ef_L7MlhNUN_0-n_3DggozWJER8c9J0us16cbvkKA,6062 +pip/_internal/network/lazy_wheel.py,sha256=1b8ZJ1w4bSBzpGzGwJR_CL2yQ6AFIwWQkS1vbPPw2XU,7627 +pip/_internal/network/session.py,sha256=38IKGKC64MTVUIH5XOR1hr2pOCzp39RccykdmGAvqRU,16729 +pip/_internal/network/utils.py,sha256=igLlTu_-q0LmL8FdJKq-Uj7AT_owrQ-T9FfyarkhK5U,4059 +pip/_internal/network/xmlrpc.py,sha256=AzQgG4GgS152_cqmGr_Oz2MIXsCal-xfsis7fA7nmU0,1791 +pip/_internal/operations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/_internal/operations/__pycache__/__init__.cpython-39.pyc,, +pip/_internal/operations/__pycache__/check.cpython-39.pyc,, +pip/_internal/operations/__pycache__/freeze.cpython-39.pyc,, +pip/_internal/operations/__pycache__/prepare.cpython-39.pyc,, +pip/_internal/operations/build/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/_internal/operations/build/__pycache__/__init__.cpython-39.pyc,, +pip/_internal/operations/build/__pycache__/metadata.cpython-39.pyc,, +pip/_internal/operations/build/__pycache__/metadata_editable.cpython-39.pyc,, +pip/_internal/operations/build/__pycache__/metadata_legacy.cpython-39.pyc,, +pip/_internal/operations/build/__pycache__/wheel.cpython-39.pyc,, +pip/_internal/operations/build/__pycache__/wheel_editable.cpython-39.pyc,, +pip/_internal/operations/build/__pycache__/wheel_legacy.cpython-39.pyc,, +pip/_internal/operations/build/metadata.py,sha256=ES_uRmAvhrNm_nDTpZxshBfUsvnXtkj-g_4rZrH9Rww,1404 +pip/_internal/operations/build/metadata_editable.py,sha256=_Rai0VZjxoeJUkjkuICrq45LtjwFoDOveosMYH43rKc,1456 +pip/_internal/operations/build/metadata_legacy.py,sha256=o-eU21As175hDC7dluM1fJJ_FqokTIShyWpjKaIpHZw,2198 +pip/_internal/operations/build/wheel.py,sha256=AO9XnTGhTgHtZmU8Dkbfo1OGr41rBuSDjIgAa4zUKgE,1063 +pip/_internal/operations/build/wheel_editable.py,sha256=TVETY-L_M_dSEKBhTIcQOP75zKVXw8tuq1U354Mm30A,1405 +pip/_internal/operations/build/wheel_legacy.py,sha256=C9j6rukgQI1n_JeQLoZGuDdfUwzCXShyIdPTp6edbMQ,3064 +pip/_internal/operations/check.py,sha256=ca4O9CkPt9Em9sLCf3H0iVt1GIcW7M8C0U5XooaBuT4,5109 +pip/_internal/operations/freeze.py,sha256=ZiYw5GlUpLVx4VJHz4S1AP2JFNyvH0iq5kpcYj2ovyw,9770 +pip/_internal/operations/install/__init__.py,sha256=mX7hyD2GNBO2mFGokDQ30r_GXv7Y_PLdtxcUv144e-s,51 +pip/_internal/operations/install/__pycache__/__init__.cpython-39.pyc,, +pip/_internal/operations/install/__pycache__/editable_legacy.cpython-39.pyc,, +pip/_internal/operations/install/__pycache__/legacy.cpython-39.pyc,, +pip/_internal/operations/install/__pycache__/wheel.cpython-39.pyc,, +pip/_internal/operations/install/editable_legacy.py,sha256=ee4kfJHNuzTdKItbfAsNOSEwq_vD7DRPGkBdK48yBhU,1354 +pip/_internal/operations/install/legacy.py,sha256=x7BG8kBm0K3JO6AR4sBl0zh2LOrfUaz7EdNt-keHBv4,4091 +pip/_internal/operations/install/wheel.py,sha256=QuQyCZE-XjuJjDYRixo40oUt2ucFhNmSrCbcXY7A9aE,27412 +pip/_internal/operations/prepare.py,sha256=LJP97jsuiCAaTGVIRrcINvxc1ntVsB45MoRbyMIukg4,24145 +pip/_internal/pyproject.py,sha256=Wm2ljdT6spC-tSdf1LBRaMYSJaXr1xUxV3OwdHCW9jc,6722 +pip/_internal/req/__init__.py,sha256=A7mUvT1KAcCYP3H7gUOTx2GRMlgoDur3H68Q0OJqM5A,2793 +pip/_internal/req/__pycache__/__init__.cpython-39.pyc,, +pip/_internal/req/__pycache__/constructors.cpython-39.pyc,, +pip/_internal/req/__pycache__/req_file.cpython-39.pyc,, +pip/_internal/req/__pycache__/req_install.cpython-39.pyc,, +pip/_internal/req/__pycache__/req_set.cpython-39.pyc,, +pip/_internal/req/__pycache__/req_tracker.cpython-39.pyc,, +pip/_internal/req/__pycache__/req_uninstall.cpython-39.pyc,, +pip/_internal/req/constructors.py,sha256=fXmtNI_J77JFP_HRvYcQW-1nKw3AiUu6Q3b1Nm8aMm0,16094 +pip/_internal/req/req_file.py,sha256=5N8OTouPCof-305StC2YK9HBxQMw-xO46skRoBPbkZo,17421 +pip/_internal/req/req_install.py,sha256=jU1HQBT_DnXZean7jY8wPNMhb6_CzdKHcilHFY_o-Fc,32524 +pip/_internal/req/req_set.py,sha256=kHYiLvkKRx21WaLTwOI-54Ng0SSzZZ9SE7FD0PsfvYA,7584 +pip/_internal/req/req_tracker.py,sha256=jK7JDu-Wt73X-gqozrFtgJVlUlnQo0P4IQ4x4_gPlfM,4117 +pip/_internal/req/req_uninstall.py,sha256=K2BHYRRJAfkSpFqcPzc9XfX2EvbhaRtQIPRFmMtUdfo,23814 +pip/_internal/resolution/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/_internal/resolution/__pycache__/__init__.cpython-39.pyc,, +pip/_internal/resolution/__pycache__/base.cpython-39.pyc,, +pip/_internal/resolution/base.py,sha256=qlmh325SBVfvG6Me9gc5Nsh5sdwHBwzHBq6aEXtKsLA,583 +pip/_internal/resolution/legacy/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/_internal/resolution/legacy/__pycache__/__init__.cpython-39.pyc,, +pip/_internal/resolution/legacy/__pycache__/resolver.cpython-39.pyc,, +pip/_internal/resolution/legacy/resolver.py,sha256=b7bf5qL1ROg73sl8dhTvLdD1w5XF8xybBAF6eF_kz7c,18288 +pip/_internal/resolution/resolvelib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/_internal/resolution/resolvelib/__pycache__/__init__.cpython-39.pyc,, +pip/_internal/resolution/resolvelib/__pycache__/base.cpython-39.pyc,, +pip/_internal/resolution/resolvelib/__pycache__/candidates.cpython-39.pyc,, +pip/_internal/resolution/resolvelib/__pycache__/factory.cpython-39.pyc,, +pip/_internal/resolution/resolvelib/__pycache__/found_candidates.cpython-39.pyc,, +pip/_internal/resolution/resolvelib/__pycache__/provider.cpython-39.pyc,, +pip/_internal/resolution/resolvelib/__pycache__/reporter.cpython-39.pyc,, +pip/_internal/resolution/resolvelib/__pycache__/requirements.cpython-39.pyc,, +pip/_internal/resolution/resolvelib/__pycache__/resolver.cpython-39.pyc,, +pip/_internal/resolution/resolvelib/base.py,sha256=u1O4fkvCO4mhmu5i32xrDv9AX5NgUci_eYVyBDQhTIM,5220 +pip/_internal/resolution/resolvelib/candidates.py,sha256=KR5jxZRSahByOABXbwrX-zNoawa7Gm9Iss-HrvrcvNw,18357 +pip/_internal/resolution/resolvelib/factory.py,sha256=0bbxnUSSjaeTmtIEgeeKtEqhEFfNhv3xpq7j9IaMq2c,28298 +pip/_internal/resolution/resolvelib/found_candidates.py,sha256=hvL3Hoa9VaYo-qEOZkBi2Iqw251UDxPz-uMHVaWmLpE,5705 +pip/_internal/resolution/resolvelib/provider.py,sha256=LzQQyzMVaZYAwLgKInbq-it6mbQL1gX0hGohz5Cr5wg,9915 +pip/_internal/resolution/resolvelib/reporter.py,sha256=3ZVVYrs5PqvLFJkGLcuXoMK5mTInFzl31xjUpDBpZZk,2526 +pip/_internal/resolution/resolvelib/requirements.py,sha256=B1ndvKPSuyyyTEXt9sKhbwminViSWnBrJa7qO2ln4Z0,5455 +pip/_internal/resolution/resolvelib/resolver.py,sha256=UsWuwuTu9aYHIfEBnEb7e1r3tXGgJbSA5LVgQqdVZ2w,11633 +pip/_internal/self_outdated_check.py,sha256=GKSatNlt2cz_CMGxu72FbUzuPaXpWOnIVKOOYIk0gvY,6849 +pip/_internal/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/_internal/utils/__pycache__/__init__.cpython-39.pyc,, +pip/_internal/utils/__pycache__/_log.cpython-39.pyc,, +pip/_internal/utils/__pycache__/appdirs.cpython-39.pyc,, +pip/_internal/utils/__pycache__/compat.cpython-39.pyc,, +pip/_internal/utils/__pycache__/compatibility_tags.cpython-39.pyc,, +pip/_internal/utils/__pycache__/datetime.cpython-39.pyc,, +pip/_internal/utils/__pycache__/deprecation.cpython-39.pyc,, +pip/_internal/utils/__pycache__/direct_url_helpers.cpython-39.pyc,, +pip/_internal/utils/__pycache__/distutils_args.cpython-39.pyc,, +pip/_internal/utils/__pycache__/egg_link.cpython-39.pyc,, +pip/_internal/utils/__pycache__/encoding.cpython-39.pyc,, +pip/_internal/utils/__pycache__/entrypoints.cpython-39.pyc,, +pip/_internal/utils/__pycache__/filesystem.cpython-39.pyc,, +pip/_internal/utils/__pycache__/filetypes.cpython-39.pyc,, +pip/_internal/utils/__pycache__/glibc.cpython-39.pyc,, +pip/_internal/utils/__pycache__/hashes.cpython-39.pyc,, +pip/_internal/utils/__pycache__/inject_securetransport.cpython-39.pyc,, +pip/_internal/utils/__pycache__/logging.cpython-39.pyc,, +pip/_internal/utils/__pycache__/misc.cpython-39.pyc,, +pip/_internal/utils/__pycache__/models.cpython-39.pyc,, +pip/_internal/utils/__pycache__/packaging.cpython-39.pyc,, +pip/_internal/utils/__pycache__/setuptools_build.cpython-39.pyc,, +pip/_internal/utils/__pycache__/subprocess.cpython-39.pyc,, +pip/_internal/utils/__pycache__/temp_dir.cpython-39.pyc,, +pip/_internal/utils/__pycache__/unpacking.cpython-39.pyc,, +pip/_internal/utils/__pycache__/urls.cpython-39.pyc,, +pip/_internal/utils/__pycache__/virtualenv.cpython-39.pyc,, +pip/_internal/utils/__pycache__/wheel.cpython-39.pyc,, +pip/_internal/utils/_log.py,sha256=-jHLOE_THaZz5BFcCnoSL9EYAtJ0nXem49s9of4jvKw,1015 +pip/_internal/utils/appdirs.py,sha256=swgcTKOm3daLeXTW6v5BUS2Ti2RvEnGRQYH_yDXklAo,1665 +pip/_internal/utils/compat.py,sha256=ACyBfLgj3_XG-iA5omEDrXqDM0cQKzi8h8HRBInzG6Q,1884 +pip/_internal/utils/compatibility_tags.py,sha256=ydin8QG8BHqYRsPY4OL6cmb44CbqXl1T0xxS97VhHkk,5377 +pip/_internal/utils/datetime.py,sha256=m21Y3wAtQc-ji6Veb6k_M5g6A0ZyFI4egchTdnwh-pQ,242 +pip/_internal/utils/deprecation.py,sha256=NKo8VqLioJ4nnXXGmW4KdasxF90EFHkZaHeX1fT08C8,3627 +pip/_internal/utils/direct_url_helpers.py,sha256=6F1tc2rcKaCZmgfVwsE6ObIe_Pux23mUVYA-2D9wCFc,3206 +pip/_internal/utils/distutils_args.py,sha256=mcAscyp80vTt3xAGTipnpgc83V-_wCvydNELVXLq7JI,1249 +pip/_internal/utils/egg_link.py,sha256=5MVlpz5LirT4iLQq86OYzjXaYF0D4Qk1dprEI7ThST4,2203 +pip/_internal/utils/encoding.py,sha256=bdZ3YgUpaOEBI5MP4-DEXiQarCW3V0rxw1kRz-TaU1Q,1169 +pip/_internal/utils/entrypoints.py,sha256=aPvCnQVi9Hdk35Kloww_D5ibjUpqxgqcJP8O9VuMZek,1055 +pip/_internal/utils/filesystem.py,sha256=rrl-rY1w8TYyKYndUyZlE9ffkQyA4-jI9x_59zXkn5s,5893 +pip/_internal/utils/filetypes.py,sha256=i8XAQ0eFCog26Fw9yV0Yb1ygAqKYB1w9Cz9n0fj8gZU,716 +pip/_internal/utils/glibc.py,sha256=tDfwVYnJCOC0BNVpItpy8CGLP9BjkxFHdl0mTS0J7fc,3110 +pip/_internal/utils/hashes.py,sha256=anpZfFGIT6HcIj2td9NHtE8AWg6GeAIhwpP8GPvZE0E,4811 +pip/_internal/utils/inject_securetransport.py,sha256=o-QRVMGiENrTJxw3fAhA7uxpdEdw6M41TjHYtSVRrcg,795 +pip/_internal/utils/logging.py,sha256=Rvght-fDXL70VWib1cpgZ3iU-kXODV98bNeLUlbqVto,11522 +pip/_internal/utils/misc.py,sha256=yLQuNWaRGtSGQqK7GT-Kj2mO7oXnPcJZkr5-9Q7AGwE,18392 +pip/_internal/utils/models.py,sha256=5GoYU586SrxURMvDn_jBMJInitviJg4O5-iOU-6I0WY,1193 +pip/_internal/utils/packaging.py,sha256=5Wm6_x7lKrlqVjPI5MBN_RurcRHwVYoQ7Ksrs84de7s,2108 +pip/_internal/utils/setuptools_build.py,sha256=vNH9hQB9wT6d-h1hVQhBKw91jNeT42meHpVeii-urOI,5652 +pip/_internal/utils/subprocess.py,sha256=vIWGpet5ARBmZ2Qn4NEHNgzCOduqbPIuByZmhhmr6mM,9182 +pip/_internal/utils/temp_dir.py,sha256=zob3PYMVevONkheOMUp_4jDofrEY3HIu5DHK78cSspI,7662 +pip/_internal/utils/unpacking.py,sha256=HUFlMEyCa9dPwdLh6sWeh95DeKytV8rsOyKShEw9y6g,8906 +pip/_internal/utils/urls.py,sha256=AhaesUGl-9it6uvG6fsFPOr9ynFpGaTMk4t5XTX7Z_Q,1759 +pip/_internal/utils/virtualenv.py,sha256=4_48qMzCwB_F5jIK5BC_ua7uiAMVifmQWU9NdaGUoVA,3459 +pip/_internal/utils/wheel.py,sha256=lXOgZyTlOm5HmK8tw5iw0A3_5A6wRzsXHOaQkIvvloU,4549 +pip/_internal/vcs/__init__.py,sha256=UAqvzpbi0VbZo3Ub6skEeZAw-ooIZR-zX_WpCbxyCoU,596 +pip/_internal/vcs/__pycache__/__init__.cpython-39.pyc,, +pip/_internal/vcs/__pycache__/bazaar.cpython-39.pyc,, +pip/_internal/vcs/__pycache__/git.cpython-39.pyc,, +pip/_internal/vcs/__pycache__/mercurial.cpython-39.pyc,, +pip/_internal/vcs/__pycache__/subversion.cpython-39.pyc,, +pip/_internal/vcs/__pycache__/versioncontrol.cpython-39.pyc,, +pip/_internal/vcs/bazaar.py,sha256=IGb5ca1xSZfgegRD2_JeyoZPrQQHs7lEYEIgpVsKpoU,3047 +pip/_internal/vcs/git.py,sha256=mjhwudCx9WlLNkxZ6_kOKmueF0rLoU2i1xeASKF6yiQ,18116 +pip/_internal/vcs/mercurial.py,sha256=Bzbd518Jsx-EJI0IhIobiQqiRsUv5TWYnrmRIFWE0Gw,5238 +pip/_internal/vcs/subversion.py,sha256=TEMRdwECvMcXakZX0pTNUep79kmBYkWDkWFkrYmcmac,11718 +pip/_internal/vcs/versioncontrol.py,sha256=KUOc-hN51em9jrqxKwUR3JnkgSE-xSOqMiiJcSaL6B8,22811 +pip/_internal/wheel_builder.py,sha256=65rOA8FSYt3c3HyqEw17uujjlCgqmoKEIv6rv9xN2NM,12307 +pip/_vendor/__init__.py,sha256=xjcBX0EP50pkaMdCssrsBXoZgo2hTtYxlcH1CIyA3T4,4708 +pip/_vendor/__pycache__/__init__.cpython-39.pyc,, +pip/_vendor/__pycache__/distro.cpython-39.pyc,, +pip/_vendor/__pycache__/six.cpython-39.pyc,, +pip/_vendor/__pycache__/typing_extensions.cpython-39.pyc,, +pip/_vendor/cachecontrol/__init__.py,sha256=1j_YQfjmiix6YyouLrftC6NzksAm8e8xGSjMKMRPIkM,465 +pip/_vendor/cachecontrol/__pycache__/__init__.cpython-39.pyc,, +pip/_vendor/cachecontrol/__pycache__/_cmd.cpython-39.pyc,, +pip/_vendor/cachecontrol/__pycache__/adapter.cpython-39.pyc,, +pip/_vendor/cachecontrol/__pycache__/cache.cpython-39.pyc,, +pip/_vendor/cachecontrol/__pycache__/compat.cpython-39.pyc,, +pip/_vendor/cachecontrol/__pycache__/controller.cpython-39.pyc,, +pip/_vendor/cachecontrol/__pycache__/filewrapper.cpython-39.pyc,, +pip/_vendor/cachecontrol/__pycache__/heuristics.cpython-39.pyc,, +pip/_vendor/cachecontrol/__pycache__/serialize.cpython-39.pyc,, +pip/_vendor/cachecontrol/__pycache__/wrapper.cpython-39.pyc,, +pip/_vendor/cachecontrol/_cmd.py,sha256=lxUXqfNTVx84zf6tcWbkLZHA6WVBRtJRpfeA9ZqhaAY,1379 +pip/_vendor/cachecontrol/adapter.py,sha256=ew9OYEQHEOjvGl06ZsuX8W3DAvHWsQKHwWAxISyGug8,5033 +pip/_vendor/cachecontrol/cache.py,sha256=eMS9Bn9JWQkHiIYA5GPRBqKVU95uS-yXkxrzpoafRig,917 +pip/_vendor/cachecontrol/caches/__init__.py,sha256=gGFOtIH8QDRvkP4YAfGIh-u9YYcGZVxwLM1-6e1mPNI,170 +pip/_vendor/cachecontrol/caches/__pycache__/__init__.cpython-39.pyc,, +pip/_vendor/cachecontrol/caches/__pycache__/file_cache.cpython-39.pyc,, +pip/_vendor/cachecontrol/caches/__pycache__/redis_cache.cpython-39.pyc,, +pip/_vendor/cachecontrol/caches/file_cache.py,sha256=P2KHcNXiqxEW7fCq5KC-NYHGSk0nNR9NIKuN-vBTn-E,4251 +pip/_vendor/cachecontrol/caches/redis_cache.py,sha256=tu_YBV7EV8vdBRGazUErkoRqYYjSBmNcB8dZ7BNomqk,940 +pip/_vendor/cachecontrol/compat.py,sha256=LNx7vqBndYdHU8YuJt53ab_8rzMGTXVrvMb7CZJkxG0,778 +pip/_vendor/cachecontrol/controller.py,sha256=9DSEiV58Gx7Ce69fLCrRcpN-_sHzXTY4ol9bEviatR0,15625 +pip/_vendor/cachecontrol/filewrapper.py,sha256=X4BAQOO26GNOR7nH_fhTzAfeuct2rBQcx_15MyFBpcs,3946 +pip/_vendor/cachecontrol/heuristics.py,sha256=8kAyuZLSCyEIgQr6vbUwfhpqg9ows4mM0IV6DWazevI,4154 +pip/_vendor/cachecontrol/serialize.py,sha256=dlySaeA5U7Q5eHvjiObgo1M8j8_huVjfWjid7Aq-r8c,6783 +pip/_vendor/cachecontrol/wrapper.py,sha256=X3-KMZ20Ho3VtqyVaXclpeQpFzokR5NE8tZSfvKVaB8,774 +pip/_vendor/certifi/__init__.py,sha256=xWdRgntT3j1V95zkRipGOg_A1UfEju2FcpujhysZLRI,62 +pip/_vendor/certifi/__main__.py,sha256=1k3Cr95vCxxGRGDljrW3wMdpZdL3Nhf0u1n-k2qdsCY,255 +pip/_vendor/certifi/__pycache__/__init__.cpython-39.pyc,, +pip/_vendor/certifi/__pycache__/__main__.cpython-39.pyc,, +pip/_vendor/certifi/__pycache__/core.cpython-39.pyc,, +pip/_vendor/certifi/cacert.pem,sha256=-og4Keu4zSpgL5shwfhd4kz0eUnVILzrGCi0zRy2kGw,265969 +pip/_vendor/certifi/core.py,sha256=gOFd0zHYlx4krrLEn982esOtmz3djiG0BFSDhgjlvcI,2840 +pip/_vendor/chardet/__init__.py,sha256=mWZaWmvZkhwfBEAT9O1Y6nRTfKzhT7FHhQTTAujbqUA,3271 +pip/_vendor/chardet/__pycache__/__init__.cpython-39.pyc,, +pip/_vendor/chardet/__pycache__/big5freq.cpython-39.pyc,, +pip/_vendor/chardet/__pycache__/big5prober.cpython-39.pyc,, +pip/_vendor/chardet/__pycache__/chardistribution.cpython-39.pyc,, +pip/_vendor/chardet/__pycache__/charsetgroupprober.cpython-39.pyc,, +pip/_vendor/chardet/__pycache__/charsetprober.cpython-39.pyc,, +pip/_vendor/chardet/__pycache__/codingstatemachine.cpython-39.pyc,, +pip/_vendor/chardet/__pycache__/compat.cpython-39.pyc,, +pip/_vendor/chardet/__pycache__/cp949prober.cpython-39.pyc,, +pip/_vendor/chardet/__pycache__/enums.cpython-39.pyc,, +pip/_vendor/chardet/__pycache__/escprober.cpython-39.pyc,, +pip/_vendor/chardet/__pycache__/escsm.cpython-39.pyc,, +pip/_vendor/chardet/__pycache__/eucjpprober.cpython-39.pyc,, +pip/_vendor/chardet/__pycache__/euckrfreq.cpython-39.pyc,, +pip/_vendor/chardet/__pycache__/euckrprober.cpython-39.pyc,, +pip/_vendor/chardet/__pycache__/euctwfreq.cpython-39.pyc,, +pip/_vendor/chardet/__pycache__/euctwprober.cpython-39.pyc,, +pip/_vendor/chardet/__pycache__/gb2312freq.cpython-39.pyc,, +pip/_vendor/chardet/__pycache__/gb2312prober.cpython-39.pyc,, +pip/_vendor/chardet/__pycache__/hebrewprober.cpython-39.pyc,, +pip/_vendor/chardet/__pycache__/jisfreq.cpython-39.pyc,, +pip/_vendor/chardet/__pycache__/jpcntx.cpython-39.pyc,, +pip/_vendor/chardet/__pycache__/langbulgarianmodel.cpython-39.pyc,, +pip/_vendor/chardet/__pycache__/langgreekmodel.cpython-39.pyc,, +pip/_vendor/chardet/__pycache__/langhebrewmodel.cpython-39.pyc,, +pip/_vendor/chardet/__pycache__/langhungarianmodel.cpython-39.pyc,, +pip/_vendor/chardet/__pycache__/langrussianmodel.cpython-39.pyc,, +pip/_vendor/chardet/__pycache__/langthaimodel.cpython-39.pyc,, +pip/_vendor/chardet/__pycache__/langturkishmodel.cpython-39.pyc,, +pip/_vendor/chardet/__pycache__/latin1prober.cpython-39.pyc,, +pip/_vendor/chardet/__pycache__/mbcharsetprober.cpython-39.pyc,, +pip/_vendor/chardet/__pycache__/mbcsgroupprober.cpython-39.pyc,, +pip/_vendor/chardet/__pycache__/mbcssm.cpython-39.pyc,, +pip/_vendor/chardet/__pycache__/sbcharsetprober.cpython-39.pyc,, +pip/_vendor/chardet/__pycache__/sbcsgroupprober.cpython-39.pyc,, +pip/_vendor/chardet/__pycache__/sjisprober.cpython-39.pyc,, +pip/_vendor/chardet/__pycache__/universaldetector.cpython-39.pyc,, +pip/_vendor/chardet/__pycache__/utf8prober.cpython-39.pyc,, +pip/_vendor/chardet/__pycache__/version.cpython-39.pyc,, +pip/_vendor/chardet/big5freq.py,sha256=D_zK5GyzoVsRes0HkLJziltFQX0bKCLOrFe9_xDvO_8,31254 +pip/_vendor/chardet/big5prober.py,sha256=kBxHbdetBpPe7xrlb-e990iot64g_eGSLd32lB7_h3M,1757 +pip/_vendor/chardet/chardistribution.py,sha256=3woWS62KrGooKyqz4zQSnjFbJpa6V7g02daAibTwcl8,9411 +pip/_vendor/chardet/charsetgroupprober.py,sha256=GZLReHP6FRRn43hvSOoGCxYamErKzyp6RgOQxVeC3kg,3839 +pip/_vendor/chardet/charsetprober.py,sha256=KSmwJErjypyj0bRZmC5F5eM7c8YQgLYIjZXintZNstg,5110 +pip/_vendor/chardet/cli/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1 +pip/_vendor/chardet/cli/__pycache__/__init__.cpython-39.pyc,, +pip/_vendor/chardet/cli/__pycache__/chardetect.cpython-39.pyc,, +pip/_vendor/chardet/cli/chardetect.py,sha256=XK5zqjUG2a4-y6eLHZ8ThYcp6WWUrdlmELxNypcc2SE,2747 +pip/_vendor/chardet/codingstatemachine.py,sha256=VYp_6cyyki5sHgXDSZnXW4q1oelHc3cu9AyQTX7uug8,3590 +pip/_vendor/chardet/compat.py,sha256=40zr6wICZwknxyuLGGcIOPyve8DTebBCbbvttvnmp5Q,1200 +pip/_vendor/chardet/cp949prober.py,sha256=TZ434QX8zzBsnUvL_8wm4AQVTZ2ZkqEEQL_lNw9f9ow,1855 +pip/_vendor/chardet/enums.py,sha256=Aimwdb9as1dJKZaFNUH2OhWIVBVd6ZkJJ_WK5sNY8cU,1661 +pip/_vendor/chardet/escprober.py,sha256=kkyqVg1Yw3DIOAMJ2bdlyQgUFQhuHAW8dUGskToNWSc,3950 +pip/_vendor/chardet/escsm.py,sha256=RuXlgNvTIDarndvllNCk5WZBIpdCxQ0kcd9EAuxUh84,10510 +pip/_vendor/chardet/eucjpprober.py,sha256=iD8Jdp0ISRjgjiVN7f0e8xGeQJ5GM2oeZ1dA8nbSeUw,3749 +pip/_vendor/chardet/euckrfreq.py,sha256=-7GdmvgWez4-eO4SuXpa7tBiDi5vRXQ8WvdFAzVaSfo,13546 +pip/_vendor/chardet/euckrprober.py,sha256=MqFMTQXxW4HbzIpZ9lKDHB3GN8SP4yiHenTmf8g_PxY,1748 +pip/_vendor/chardet/euctwfreq.py,sha256=No1WyduFOgB5VITUA7PLyC5oJRNzRyMbBxaKI1l16MA,31621 +pip/_vendor/chardet/euctwprober.py,sha256=13p6EP4yRaxqnP4iHtxHOJ6R2zxHq1_m8hTRjzVZ95c,1747 +pip/_vendor/chardet/gb2312freq.py,sha256=JX8lsweKLmnCwmk8UHEQsLgkr_rP_kEbvivC4qPOrlc,20715 +pip/_vendor/chardet/gb2312prober.py,sha256=gGvIWi9WhDjE-xQXHvNIyrnLvEbMAYgyUSZ65HUfylw,1754 +pip/_vendor/chardet/hebrewprober.py,sha256=c3SZ-K7hvyzGY6JRAZxJgwJ_sUS9k0WYkvMY00YBYFo,13838 +pip/_vendor/chardet/jisfreq.py,sha256=vpmJv2Bu0J8gnMVRPHMFefTRvo_ha1mryLig8CBwgOg,25777 +pip/_vendor/chardet/jpcntx.py,sha256=PYlNqRUQT8LM3cT5FmHGP0iiscFlTWED92MALvBungo,19643 +pip/_vendor/chardet/langbulgarianmodel.py,sha256=rk9CJpuxO0bObboJcv6gNgWuosYZmd8qEEds5y7DS_Y,105697 +pip/_vendor/chardet/langgreekmodel.py,sha256=S-uNQ1ihC75yhBvSux24gLFZv3QyctMwC6OxLJdX-bw,99571 +pip/_vendor/chardet/langhebrewmodel.py,sha256=DzPP6TPGG_-PV7tqspu_d8duueqm7uN-5eQ0aHUw1Gg,98776 +pip/_vendor/chardet/langhungarianmodel.py,sha256=RtJH7DZdsmaHqyK46Kkmnk5wQHiJwJPPJSqqIlpeZRc,102498 +pip/_vendor/chardet/langrussianmodel.py,sha256=THqJOhSxiTQcHboDNSc5yofc2koXXQFHFyjtyuntUfM,131180 +pip/_vendor/chardet/langthaimodel.py,sha256=R1wXHnUMtejpw0JnH_JO8XdYasME6wjVqp1zP7TKLgg,103312 +pip/_vendor/chardet/langturkishmodel.py,sha256=rfwanTptTwSycE4-P-QasPmzd-XVYgevytzjlEzBBu8,95946 +pip/_vendor/chardet/latin1prober.py,sha256=S2IoORhFk39FEFOlSFWtgVybRiP6h7BlLldHVclNkU8,5370 +pip/_vendor/chardet/mbcharsetprober.py,sha256=AR95eFH9vuqSfvLQZN-L5ijea25NOBCoXqw8s5O9xLQ,3413 +pip/_vendor/chardet/mbcsgroupprober.py,sha256=h6TRnnYq2OxG1WdD5JOyxcdVpn7dG0q-vB8nWr5mbh4,2012 +pip/_vendor/chardet/mbcssm.py,sha256=SY32wVIF3HzcjY3BaEspy9metbNSKxIIB0RKPn7tjpI,25481 +pip/_vendor/chardet/metadata/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/_vendor/chardet/metadata/__pycache__/__init__.cpython-39.pyc,, +pip/_vendor/chardet/metadata/__pycache__/languages.cpython-39.pyc,, +pip/_vendor/chardet/metadata/languages.py,sha256=41tLq3eLSrBEbEVVQpVGFq9K7o1ln9b1HpY1l0hCUQo,19474 +pip/_vendor/chardet/sbcharsetprober.py,sha256=nmyMyuxzG87DN6K3Rk2MUzJLMLR69MrWpdnHzOwVUwQ,6136 +pip/_vendor/chardet/sbcsgroupprober.py,sha256=hqefQuXmiFyDBArOjujH6hd6WFXlOD1kWCsxDhjx5Vc,4309 +pip/_vendor/chardet/sjisprober.py,sha256=IIt-lZj0WJqK4rmUZzKZP4GJlE8KUEtFYVuY96ek5MQ,3774 +pip/_vendor/chardet/universaldetector.py,sha256=DpZTXCX0nUHXxkQ9sr4GZxGB_hveZ6hWt3uM94cgWKs,12503 +pip/_vendor/chardet/utf8prober.py,sha256=IdD8v3zWOsB8OLiyPi-y_fqwipRFxV9Nc1eKBLSuIEw,2766 +pip/_vendor/chardet/version.py,sha256=A4CILFAd8MRVG1HoXPp45iK9RLlWyV73a1EtwE8Tvn8,242 +pip/_vendor/colorama/__init__.py,sha256=pCdErryzLSzDW5P-rRPBlPLqbBtIRNJB6cMgoeJns5k,239 +pip/_vendor/colorama/__pycache__/__init__.cpython-39.pyc,, +pip/_vendor/colorama/__pycache__/ansi.cpython-39.pyc,, +pip/_vendor/colorama/__pycache__/ansitowin32.cpython-39.pyc,, +pip/_vendor/colorama/__pycache__/initialise.cpython-39.pyc,, +pip/_vendor/colorama/__pycache__/win32.cpython-39.pyc,, +pip/_vendor/colorama/__pycache__/winterm.cpython-39.pyc,, +pip/_vendor/colorama/ansi.py,sha256=Top4EeEuaQdBWdteKMEcGOTeKeF19Q-Wo_6_Cj5kOzQ,2522 +pip/_vendor/colorama/ansitowin32.py,sha256=yV7CEmCb19MjnJKODZEEvMH_fnbJhwnpzo4sxZuGXmA,10517 +pip/_vendor/colorama/initialise.py,sha256=PprovDNxMTrvoNHFcL2NZjpH2XzDc8BLxLxiErfUl4k,1915 +pip/_vendor/colorama/win32.py,sha256=bJ8Il9jwaBN5BJ8bmN6FoYZ1QYuMKv2j8fGrXh7TJjw,5404 +pip/_vendor/colorama/winterm.py,sha256=2y_2b7Zsv34feAsP67mLOVc-Bgq51mdYGo571VprlrM,6438 +pip/_vendor/distlib/__init__.py,sha256=HTGLP7dnTRTQCbEZNGUxBq-0sobr0KQUMn3yd6uEObA,581 +pip/_vendor/distlib/__pycache__/__init__.cpython-39.pyc,, +pip/_vendor/distlib/__pycache__/compat.cpython-39.pyc,, +pip/_vendor/distlib/__pycache__/database.cpython-39.pyc,, +pip/_vendor/distlib/__pycache__/index.cpython-39.pyc,, +pip/_vendor/distlib/__pycache__/locators.cpython-39.pyc,, +pip/_vendor/distlib/__pycache__/manifest.cpython-39.pyc,, +pip/_vendor/distlib/__pycache__/markers.cpython-39.pyc,, +pip/_vendor/distlib/__pycache__/metadata.cpython-39.pyc,, +pip/_vendor/distlib/__pycache__/resources.cpython-39.pyc,, +pip/_vendor/distlib/__pycache__/scripts.cpython-39.pyc,, +pip/_vendor/distlib/__pycache__/util.cpython-39.pyc,, +pip/_vendor/distlib/__pycache__/version.cpython-39.pyc,, +pip/_vendor/distlib/__pycache__/wheel.cpython-39.pyc,, +pip/_vendor/distlib/_backport/__init__.py,sha256=bqS_dTOH6uW9iGgd0uzfpPjo6vZ4xpPZ7kyfZJ2vNaw,274 +pip/_vendor/distlib/_backport/__pycache__/__init__.cpython-39.pyc,, +pip/_vendor/distlib/_backport/__pycache__/misc.cpython-39.pyc,, +pip/_vendor/distlib/_backport/__pycache__/shutil.cpython-39.pyc,, +pip/_vendor/distlib/_backport/__pycache__/sysconfig.cpython-39.pyc,, +pip/_vendor/distlib/_backport/__pycache__/tarfile.cpython-39.pyc,, +pip/_vendor/distlib/_backport/misc.py,sha256=KWecINdbFNOxSOP1fGF680CJnaC6S4fBRgEtaYTw0ig,971 +pip/_vendor/distlib/_backport/shutil.py,sha256=IX_G2NPqwecJibkIDje04bqu0xpHkfSQ2GaGdEVqM5Y,25707 +pip/_vendor/distlib/_backport/sysconfig.cfg,sha256=swZKxq9RY5e9r3PXCrlvQPMsvOdiWZBTHLEbqS8LJLU,2617 +pip/_vendor/distlib/_backport/sysconfig.py,sha256=BQHFlb6pubCl_dvT1NjtzIthylofjKisox239stDg0U,26854 +pip/_vendor/distlib/_backport/tarfile.py,sha256=Ihp7rXRcjbIKw8COm9wSePV9ARGXbSF9gGXAMn2Q-KU,92628 +pip/_vendor/distlib/compat.py,sha256=fbsxc5PfJ2wBx1K4k6mQ2goAYs-GZW0tcOPIlE_vf0I,41495 +pip/_vendor/distlib/database.py,sha256=Kl0YvPQKc4OcpVi7k5cFziydM1xOK8iqdxLGXgbZHV4,51059 +pip/_vendor/distlib/index.py,sha256=UfcimNW19AB7IKWam4VaJbXuCBvArKfSxhV16EwavzE,20739 +pip/_vendor/distlib/locators.py,sha256=AKlB3oZvfOTg4E0CtfwOzujFL19X5V4XUA4eHdKOu44,51965 +pip/_vendor/distlib/manifest.py,sha256=nQEhYmgoreaBZzyFzwYsXxJARu3fo4EkunU163U16iE,14811 +pip/_vendor/distlib/markers.py,sha256=9c70ISEKwBjmUOHuIdOygVnRVESOKdNYp9a2TVn4qrI,4989 +pip/_vendor/distlib/metadata.py,sha256=vatoxFdmBr6ie-sTVXVNPOPG3uwMDWJTnEECnm7xDCw,39109 +pip/_vendor/distlib/resources.py,sha256=LwbPksc0A1JMbi6XnuPdMBUn83X7BPuFNWqPGEKI698,10820 +pip/_vendor/distlib/scripts.py,sha256=tjSwENINeV91ROZxec5zTSMRg2jEeKc4enyCHDzNvEE,17720 +pip/_vendor/distlib/t32.exe,sha256=NS3xBCVAld35JVFNmb-1QRyVtThukMrwZVeXn4LhaEQ,96768 +pip/_vendor/distlib/t64-arm.exe,sha256=8WGDh6aI8WJAjngRNQpyJpB21Sv20PCYYFSNW1fWd6w,180736 +pip/_vendor/distlib/t64.exe,sha256=oAqHes78rUWVM0OtVqIhUvequl_PKhAhXYQWnUf7zR0,105984 +pip/_vendor/distlib/util.py,sha256=0Uq_qa63FCLtdyNdWvMnmPbiSvVa-ykHM2E8HT7LSIU,67766 +pip/_vendor/distlib/version.py,sha256=WG__LyAa2GwmA6qSoEJtvJE8REA1LZpbSizy8WvhJLk,23513 +pip/_vendor/distlib/w32.exe,sha256=lJtnZdeUxTZWya_EW5DZos_K5rswRECGspIl8ZJCIXs,90112 +pip/_vendor/distlib/w64-arm.exe,sha256=Q_HdzVu9zxYdaBa3m0iJ5_ddLOEqtPe8x30WADoXza8,166400 +pip/_vendor/distlib/w64.exe,sha256=0aRzoN2BO9NWW4ENy4_4vHkHR4qZTFZNVSAJJYlODTI,99840 +pip/_vendor/distlib/wheel.py,sha256=pj5VVCjqZMcHvgizORWwAFPS7hOk61CZ59dxP8laQ4E,42943 +pip/_vendor/distro.py,sha256=O1EeHMq1-xAO373JI2_6pYEtd09yEkxtmrYkdY-9S-w,48414 +pip/_vendor/html5lib/__init__.py,sha256=BYzcKCqeEii52xDrqBFruhnmtmkiuHXFyFh-cglQ8mk,1160 +pip/_vendor/html5lib/__pycache__/__init__.cpython-39.pyc,, +pip/_vendor/html5lib/__pycache__/_ihatexml.cpython-39.pyc,, +pip/_vendor/html5lib/__pycache__/_inputstream.cpython-39.pyc,, +pip/_vendor/html5lib/__pycache__/_tokenizer.cpython-39.pyc,, +pip/_vendor/html5lib/__pycache__/_utils.cpython-39.pyc,, +pip/_vendor/html5lib/__pycache__/constants.cpython-39.pyc,, +pip/_vendor/html5lib/__pycache__/html5parser.cpython-39.pyc,, +pip/_vendor/html5lib/__pycache__/serializer.cpython-39.pyc,, +pip/_vendor/html5lib/_ihatexml.py,sha256=ifOwF7pXqmyThIXc3boWc96s4MDezqRrRVp7FwDYUFs,16728 +pip/_vendor/html5lib/_inputstream.py,sha256=jErNASMlkgs7MpOM9Ve_VdLDJyFFweAjLuhVutZz33U,32353 +pip/_vendor/html5lib/_tokenizer.py,sha256=04mgA2sNTniutl2fxFv-ei5bns4iRaPxVXXHh_HrV_4,77040 +pip/_vendor/html5lib/_trie/__init__.py,sha256=nqfgO910329BEVJ5T4psVwQtjd2iJyEXQ2-X8c1YxwU,109 +pip/_vendor/html5lib/_trie/__pycache__/__init__.cpython-39.pyc,, +pip/_vendor/html5lib/_trie/__pycache__/_base.cpython-39.pyc,, +pip/_vendor/html5lib/_trie/__pycache__/py.cpython-39.pyc,, +pip/_vendor/html5lib/_trie/_base.py,sha256=CaybYyMro8uERQYjby2tTeSUatnWDfWroUN9N7ety5w,1013 +pip/_vendor/html5lib/_trie/py.py,sha256=wXmQLrZRf4MyWNyg0m3h81m9InhLR7GJ002mIIZh-8o,1775 +pip/_vendor/html5lib/_utils.py,sha256=Dx9AKntksRjFT1veBj7I362pf5OgIaT0zglwq43RnfU,4931 +pip/_vendor/html5lib/constants.py,sha256=Ll-yzLU_jcjyAI_h57zkqZ7aQWE5t5xA4y_jQgoUUhw,83464 +pip/_vendor/html5lib/filters/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/_vendor/html5lib/filters/__pycache__/__init__.cpython-39.pyc,, +pip/_vendor/html5lib/filters/__pycache__/alphabeticalattributes.cpython-39.pyc,, +pip/_vendor/html5lib/filters/__pycache__/base.cpython-39.pyc,, +pip/_vendor/html5lib/filters/__pycache__/inject_meta_charset.cpython-39.pyc,, +pip/_vendor/html5lib/filters/__pycache__/lint.cpython-39.pyc,, +pip/_vendor/html5lib/filters/__pycache__/optionaltags.cpython-39.pyc,, +pip/_vendor/html5lib/filters/__pycache__/sanitizer.cpython-39.pyc,, +pip/_vendor/html5lib/filters/__pycache__/whitespace.cpython-39.pyc,, +pip/_vendor/html5lib/filters/alphabeticalattributes.py,sha256=lViZc2JMCclXi_5gduvmdzrRxtO5Xo9ONnbHBVCsykU,919 +pip/_vendor/html5lib/filters/base.py,sha256=z-IU9ZAYjpsVsqmVt7kuWC63jR11hDMr6CVrvuao8W0,286 +pip/_vendor/html5lib/filters/inject_meta_charset.py,sha256=egDXUEHXmAG9504xz0K6ALDgYkvUrC2q15YUVeNlVQg,2945 +pip/_vendor/html5lib/filters/lint.py,sha256=jk6q56xY0ojiYfvpdP-OZSm9eTqcAdRqhCoPItemPYA,3643 +pip/_vendor/html5lib/filters/optionaltags.py,sha256=8lWT75J0aBOHmPgfmqTHSfPpPMp01T84NKu0CRedxcE,10588 +pip/_vendor/html5lib/filters/sanitizer.py,sha256=m6oGmkBhkGAnn2nV6D4hE78SCZ6WEnK9rKdZB3uXBIc,26897 +pip/_vendor/html5lib/filters/whitespace.py,sha256=8eWqZxd4UC4zlFGW6iyY6f-2uuT8pOCSALc3IZt7_t4,1214 +pip/_vendor/html5lib/html5parser.py,sha256=anr-aXre_ImfrkQ35c_rftKXxC80vJCREKe06Tq15HA,117186 +pip/_vendor/html5lib/serializer.py,sha256=_PpvcZF07cwE7xr9uKkZqh5f4UEaI8ltCU2xPJzaTpk,15759 +pip/_vendor/html5lib/treeadapters/__init__.py,sha256=A0rY5gXIe4bJOiSGRO_j_tFhngRBO8QZPzPtPw5dFzo,679 +pip/_vendor/html5lib/treeadapters/__pycache__/__init__.cpython-39.pyc,, +pip/_vendor/html5lib/treeadapters/__pycache__/genshi.cpython-39.pyc,, +pip/_vendor/html5lib/treeadapters/__pycache__/sax.cpython-39.pyc,, +pip/_vendor/html5lib/treeadapters/genshi.py,sha256=CH27pAsDKmu4ZGkAUrwty7u0KauGLCZRLPMzaO3M5vo,1715 +pip/_vendor/html5lib/treeadapters/sax.py,sha256=BKS8woQTnKiqeffHsxChUqL4q2ZR_wb5fc9MJ3zQC8s,1776 +pip/_vendor/html5lib/treebuilders/__init__.py,sha256=AysSJyvPfikCMMsTVvaxwkgDieELD5dfR8FJIAuq7hY,3592 +pip/_vendor/html5lib/treebuilders/__pycache__/__init__.cpython-39.pyc,, +pip/_vendor/html5lib/treebuilders/__pycache__/base.cpython-39.pyc,, +pip/_vendor/html5lib/treebuilders/__pycache__/dom.cpython-39.pyc,, +pip/_vendor/html5lib/treebuilders/__pycache__/etree.cpython-39.pyc,, +pip/_vendor/html5lib/treebuilders/__pycache__/etree_lxml.cpython-39.pyc,, +pip/_vendor/html5lib/treebuilders/base.py,sha256=z-o51vt9r_l2IDG5IioTOKGzZne4Fy3_Fc-7ztrOh4I,14565 +pip/_vendor/html5lib/treebuilders/dom.py,sha256=22whb0C71zXIsai5mamg6qzBEiigcBIvaDy4Asw3at0,8925 +pip/_vendor/html5lib/treebuilders/etree.py,sha256=w5ZFpKk6bAxnrwD2_BrF5EVC7vzz0L3LMi9Sxrbc_8w,12836 +pip/_vendor/html5lib/treebuilders/etree_lxml.py,sha256=9gqDjs-IxsPhBYa5cpvv2FZ1KZlG83Giusy2lFmvIkE,14766 +pip/_vendor/html5lib/treewalkers/__init__.py,sha256=OBPtc1TU5mGyy18QDMxKEyYEz0wxFUUNj5v0-XgmYhY,5719 +pip/_vendor/html5lib/treewalkers/__pycache__/__init__.cpython-39.pyc,, +pip/_vendor/html5lib/treewalkers/__pycache__/base.cpython-39.pyc,, +pip/_vendor/html5lib/treewalkers/__pycache__/dom.cpython-39.pyc,, +pip/_vendor/html5lib/treewalkers/__pycache__/etree.cpython-39.pyc,, +pip/_vendor/html5lib/treewalkers/__pycache__/etree_lxml.cpython-39.pyc,, +pip/_vendor/html5lib/treewalkers/__pycache__/genshi.cpython-39.pyc,, +pip/_vendor/html5lib/treewalkers/base.py,sha256=ouiOsuSzvI0KgzdWP8PlxIaSNs9falhbiinAEc_UIJY,7476 +pip/_vendor/html5lib/treewalkers/dom.py,sha256=EHyFR8D8lYNnyDU9lx_IKigVJRyecUGua0mOi7HBukc,1413 +pip/_vendor/html5lib/treewalkers/etree.py,sha256=xo1L5m9VtkfpFJK0pFmkLVajhqYYVisVZn3k9kYpPkI,4551 +pip/_vendor/html5lib/treewalkers/etree_lxml.py,sha256=_b0LAVWLcVu9WaU_-w3D8f0IRSpCbjf667V-3NRdhTw,6357 +pip/_vendor/html5lib/treewalkers/genshi.py,sha256=4D2PECZ5n3ZN3qu3jMl9yY7B81jnQApBQSVlfaIuYbA,2309 +pip/_vendor/idna/__init__.py,sha256=KJQN1eQBr8iIK5SKrJ47lXvxG0BJ7Lm38W4zT0v_8lk,849 +pip/_vendor/idna/__pycache__/__init__.cpython-39.pyc,, +pip/_vendor/idna/__pycache__/codec.cpython-39.pyc,, +pip/_vendor/idna/__pycache__/compat.cpython-39.pyc,, +pip/_vendor/idna/__pycache__/core.cpython-39.pyc,, +pip/_vendor/idna/__pycache__/idnadata.cpython-39.pyc,, +pip/_vendor/idna/__pycache__/intranges.cpython-39.pyc,, +pip/_vendor/idna/__pycache__/package_data.cpython-39.pyc,, +pip/_vendor/idna/__pycache__/uts46data.cpython-39.pyc,, +pip/_vendor/idna/codec.py,sha256=6ly5odKfqrytKT9_7UrlGklHnf1DSK2r9C6cSM4sa28,3374 +pip/_vendor/idna/compat.py,sha256=0_sOEUMT4CVw9doD3vyRhX80X19PwqFoUBs7gWsFME4,321 +pip/_vendor/idna/core.py,sha256=RFIkY-HhFZaDoBEFjGwyGd_vWI04uOAQjnzueMWqwOU,12795 +pip/_vendor/idna/idnadata.py,sha256=fzMzkCea2xieVxcrjngJ-2pLsKQNejPCZFlBajIuQdw,44025 +pip/_vendor/idna/intranges.py,sha256=YBr4fRYuWH7kTKS2tXlFjM24ZF1Pdvcir-aywniInqg,1881 +pip/_vendor/idna/package_data.py,sha256=szxQhV0ZD0nKJ84Kuobw3l8q4_KeCyXjFRdpwIpKZmw,21 +pip/_vendor/idna/uts46data.py,sha256=o-D7V-a0fOLZNd7tvxof6MYfUd0TBZzE2bLR5XO67xU,204400 +pip/_vendor/msgpack/__init__.py,sha256=2gJwcsTIaAtCM0GMi2rU-_Y6kILeeQuqRkrQ22jSANc,1118 +pip/_vendor/msgpack/__pycache__/__init__.cpython-39.pyc,, +pip/_vendor/msgpack/__pycache__/_version.cpython-39.pyc,, +pip/_vendor/msgpack/__pycache__/exceptions.cpython-39.pyc,, +pip/_vendor/msgpack/__pycache__/ext.cpython-39.pyc,, +pip/_vendor/msgpack/__pycache__/fallback.cpython-39.pyc,, +pip/_vendor/msgpack/_version.py,sha256=JpTcnRd3YUioA24NDtDZbLW0Nhl2yA-N1Rq2lLDBB-g,20 +pip/_vendor/msgpack/exceptions.py,sha256=dCTWei8dpkrMsQDcjQk74ATl9HsIBH0ybt8zOPNqMYc,1081 +pip/_vendor/msgpack/ext.py,sha256=4l356Y4sVEcvCla2dh_cL57vh4GMhZfa3kuWHFHYz6A,6088 +pip/_vendor/msgpack/fallback.py,sha256=L5jriXysURbf6rPbbHbvXgvoFrKZiryIBmujMTcrf3A,34475 +pip/_vendor/packaging/__about__.py,sha256=ugASIO2w1oUyH8_COqQ2X_s0rDhjbhQC3yJocD03h2c,661 +pip/_vendor/packaging/__init__.py,sha256=b9Kk5MF7KxhhLgcDmiUWukN-LatWFxPdNug0joPhHSk,497 +pip/_vendor/packaging/__pycache__/__about__.cpython-39.pyc,, +pip/_vendor/packaging/__pycache__/__init__.cpython-39.pyc,, +pip/_vendor/packaging/__pycache__/_manylinux.cpython-39.pyc,, +pip/_vendor/packaging/__pycache__/_musllinux.cpython-39.pyc,, +pip/_vendor/packaging/__pycache__/_structures.cpython-39.pyc,, +pip/_vendor/packaging/__pycache__/markers.cpython-39.pyc,, +pip/_vendor/packaging/__pycache__/requirements.cpython-39.pyc,, +pip/_vendor/packaging/__pycache__/specifiers.cpython-39.pyc,, +pip/_vendor/packaging/__pycache__/tags.cpython-39.pyc,, +pip/_vendor/packaging/__pycache__/utils.cpython-39.pyc,, +pip/_vendor/packaging/__pycache__/version.cpython-39.pyc,, +pip/_vendor/packaging/_manylinux.py,sha256=XcbiXB-qcjv3bcohp6N98TMpOP4_j3m-iOA8ptK2GWY,11488 +pip/_vendor/packaging/_musllinux.py,sha256=_KGgY_qc7vhMGpoqss25n2hiLCNKRtvz9mCrS7gkqyc,4378 +pip/_vendor/packaging/_structures.py,sha256=q3eVNmbWJGG_S0Dit_S3Ao8qQqz_5PYTXFAKBZe5yr4,1431 +pip/_vendor/packaging/markers.py,sha256=AJBOcY8Oq0kYc570KuuPTkvuqjAlhufaE2c9sCUbm64,8487 +pip/_vendor/packaging/requirements.py,sha256=NtDlPBtojpn1IUC85iMjPNsUmufjpSlwnNA-Xb4m5NA,4676 +pip/_vendor/packaging/specifiers.py,sha256=LRQ0kFsHrl5qfcFNEEJrIFYsnIHQUJXY9fIsakTrrqE,30110 +pip/_vendor/packaging/tags.py,sha256=lmsnGNiJ8C4D_Pf9PbM0qgbZvD9kmB9lpZBQUZa3R_Y,15699 +pip/_vendor/packaging/utils.py,sha256=dJjeat3BS-TYn1RrUFVwufUMasbtzLfYRoy_HXENeFQ,4200 +pip/_vendor/packaging/version.py,sha256=_fLRNrFrxYcHVfyo8vk9j8s6JM8N_xsSxVFr6RJyco8,14665 +pip/_vendor/pep517/__init__.py,sha256=Y1bATL2qbFNN6M_DQa4yyrwqjpIiL-j9T6kBmR0DS14,130 +pip/_vendor/pep517/__pycache__/__init__.cpython-39.pyc,, +pip/_vendor/pep517/__pycache__/build.cpython-39.pyc,, +pip/_vendor/pep517/__pycache__/check.cpython-39.pyc,, +pip/_vendor/pep517/__pycache__/colorlog.cpython-39.pyc,, +pip/_vendor/pep517/__pycache__/compat.cpython-39.pyc,, +pip/_vendor/pep517/__pycache__/dirtools.cpython-39.pyc,, +pip/_vendor/pep517/__pycache__/envbuild.cpython-39.pyc,, +pip/_vendor/pep517/__pycache__/meta.cpython-39.pyc,, +pip/_vendor/pep517/__pycache__/wrappers.cpython-39.pyc,, +pip/_vendor/pep517/build.py,sha256=2bar6EdjwIz2Dlfy94qdxn3oA9mVnnny40mfoT5f-qI,3457 +pip/_vendor/pep517/check.py,sha256=bCORq1WrHjhpTONa-zpAqG0EB9rHNuhO1ORu6DsDuL8,6084 +pip/_vendor/pep517/colorlog.py,sha256=Tk9AuYm_cLF3BKTBoSTJt9bRryn0aFojIQOwbfVUTxQ,4098 +pip/_vendor/pep517/compat.py,sha256=NmLImE5oiDT3gbEhJ4w7xeoMFcpAPrGu_NltBytSJUY,1253 +pip/_vendor/pep517/dirtools.py,sha256=2mkAkAL0mRz_elYFjRKuekTJVipH1zTn4tbf1EDev84,1129 +pip/_vendor/pep517/envbuild.py,sha256=zFde--rmzjXMLXcm7SA_3hDtgk5VCTA8hjpk88RbF6E,6100 +pip/_vendor/pep517/in_process/__init__.py,sha256=MyWoAi8JHdcBv7yXuWpUSVADbx6LSB9rZh7kTIgdA8Y,563 +pip/_vendor/pep517/in_process/__pycache__/__init__.cpython-39.pyc,, +pip/_vendor/pep517/in_process/__pycache__/_in_process.cpython-39.pyc,, +pip/_vendor/pep517/in_process/_in_process.py,sha256=D3waguyNSGcwosociD5USfcycYr2RCzCjYtxX5UHQmQ,11201 +pip/_vendor/pep517/meta.py,sha256=8mnM5lDnT4zXQpBTliJbRGfesH7iioHwozbDxALPS9Y,2463 +pip/_vendor/pep517/wrappers.py,sha256=impq7Cz_LL1iDF1iiOzYWB4MaEu6O6Gps7TJ5qsJz1Q,13429 +pip/_vendor/pkg_resources/__init__.py,sha256=NnpQ3g6BCHzpMgOR_OLBmYtniY4oOzdKpwqghfq_6ug,108287 +pip/_vendor/pkg_resources/__pycache__/__init__.cpython-39.pyc,, +pip/_vendor/pkg_resources/__pycache__/py31compat.cpython-39.pyc,, +pip/_vendor/pkg_resources/py31compat.py,sha256=CRk8fkiPRDLsbi5pZcKsHI__Pbmh_94L8mr9Qy9Ab2U,562 +pip/_vendor/platformdirs/__init__.py,sha256=Aizpxewwd4nY63Gqw-Od1Rso9Ah4bSoc6rkx-GBRu2Y,12676 +pip/_vendor/platformdirs/__main__.py,sha256=ZmsnTxEOxtTvwa-Y_Vfab_JN3X4XCVeN8X0yyy9-qnc,1176 +pip/_vendor/platformdirs/__pycache__/__init__.cpython-39.pyc,, +pip/_vendor/platformdirs/__pycache__/__main__.cpython-39.pyc,, +pip/_vendor/platformdirs/__pycache__/android.cpython-39.pyc,, +pip/_vendor/platformdirs/__pycache__/api.cpython-39.pyc,, +pip/_vendor/platformdirs/__pycache__/macos.cpython-39.pyc,, +pip/_vendor/platformdirs/__pycache__/unix.cpython-39.pyc,, +pip/_vendor/platformdirs/__pycache__/version.cpython-39.pyc,, +pip/_vendor/platformdirs/__pycache__/windows.cpython-39.pyc,, +pip/_vendor/platformdirs/android.py,sha256=xhlD4NmrKCARe5lgnpBGYo4lOYxEOBOByNDNYy91gEE,4012 +pip/_vendor/platformdirs/api.py,sha256=MXKHXOL3eh_-trSok-JUTjAR_zjmmKF3rjREVABjP8s,4910 +pip/_vendor/platformdirs/macos.py,sha256=-3UXQewbT0yMhMdkzRXfXGAntmLIH7Qt4a9Hlf8I5_Y,2655 +pip/_vendor/platformdirs/unix.py,sha256=b4aVYTz0qZ50HntwOXo8r6tp82jAa3qTjxw-WlnC2yc,6910 +pip/_vendor/platformdirs/version.py,sha256=bXzLJCe23FNQRQrf7ZRWKejxWnct_wft7dxdkMGT33E,80 +pip/_vendor/platformdirs/windows.py,sha256=ISruopR5UGBePC0BxCxXevkZYfjJsIZc49YWU5iYfQ4,6439 +pip/_vendor/progress/__init__.py,sha256=1HejNZtv2ouUNQeStUDAtZrtwkz_3FmYKQ476hJ7zOs,5294 +pip/_vendor/progress/__pycache__/__init__.cpython-39.pyc,, +pip/_vendor/progress/__pycache__/bar.cpython-39.pyc,, +pip/_vendor/progress/__pycache__/colors.cpython-39.pyc,, +pip/_vendor/progress/__pycache__/counter.cpython-39.pyc,, +pip/_vendor/progress/__pycache__/spinner.cpython-39.pyc,, +pip/_vendor/progress/bar.py,sha256=GbedY0oZ-Q1duXjmvVLO0tSf-uTSH7hJ3zzyI91Esws,2942 +pip/_vendor/progress/colors.py,sha256=cCYXQnYFYVmQKKmYEbQ_lj6SPSFzdw4FN98F2x2kR-U,2655 +pip/_vendor/progress/counter.py,sha256=zYt9DWH0_05s8Q9TrJwHVud-WwsyyaR3PwYtk5hxwwQ,1613 +pip/_vendor/progress/spinner.py,sha256=u5ElzW94XEiLGH-aAlr54VJtKfeK745xr6UfGvvflzU,1461 +pip/_vendor/pygments/__init__.py,sha256=CAmA9UthykwxvtutUcH0IxqtiyQcSg6CmYdM-jKlcRY,3002 +pip/_vendor/pygments/__main__.py,sha256=X7rGLMUC54EXgO14FZ9goKXZDmhPzKXTsUglmb_McIU,353 +pip/_vendor/pygments/__pycache__/__init__.cpython-39.pyc,, +pip/_vendor/pygments/__pycache__/__main__.cpython-39.pyc,, +pip/_vendor/pygments/__pycache__/cmdline.cpython-39.pyc,, +pip/_vendor/pygments/__pycache__/console.cpython-39.pyc,, +pip/_vendor/pygments/__pycache__/filter.cpython-39.pyc,, +pip/_vendor/pygments/__pycache__/formatter.cpython-39.pyc,, +pip/_vendor/pygments/__pycache__/lexer.cpython-39.pyc,, +pip/_vendor/pygments/__pycache__/modeline.cpython-39.pyc,, +pip/_vendor/pygments/__pycache__/plugin.cpython-39.pyc,, +pip/_vendor/pygments/__pycache__/regexopt.cpython-39.pyc,, +pip/_vendor/pygments/__pycache__/scanner.cpython-39.pyc,, +pip/_vendor/pygments/__pycache__/sphinxext.cpython-39.pyc,, +pip/_vendor/pygments/__pycache__/style.cpython-39.pyc,, +pip/_vendor/pygments/__pycache__/token.cpython-39.pyc,, +pip/_vendor/pygments/__pycache__/unistring.cpython-39.pyc,, +pip/_vendor/pygments/__pycache__/util.cpython-39.pyc,, +pip/_vendor/pygments/cmdline.py,sha256=XpsyWgErcSqHC7rXiYKLF3Y61Uy8SR2DNQDDhZGuezg,23408 +pip/_vendor/pygments/console.py,sha256=QZXBUAkyl4dPLQ1e6XHjQu3mmXBWvuGQwsQT2q1mtCY,1697 +pip/_vendor/pygments/filter.py,sha256=35iMZiB1rcuogxokm92kViB2DPXPp_wWoxWuMmwvvzY,1938 +pip/_vendor/pygments/filters/__init__.py,sha256=-veOimzCyYGEARru2Dfo6ofSYcZ8tGsIVuMprtaZQ24,40292 +pip/_vendor/pygments/filters/__pycache__/__init__.cpython-39.pyc,, +pip/_vendor/pygments/formatter.py,sha256=zSBbX2U_OOriy7SJvSTK6OAxjuXtROWxQlNpJEJZjBA,2917 +pip/_vendor/pygments/formatters/__init__.py,sha256=fjkYDy5-F998XczKi0ymHFayr5ObIRLHF8cgp9k8kpA,5119 +pip/_vendor/pygments/formatters/__pycache__/__init__.cpython-39.pyc,, +pip/_vendor/pygments/formatters/__pycache__/_mapping.cpython-39.pyc,, +pip/_vendor/pygments/formatters/__pycache__/bbcode.cpython-39.pyc,, +pip/_vendor/pygments/formatters/__pycache__/groff.cpython-39.pyc,, +pip/_vendor/pygments/formatters/__pycache__/html.cpython-39.pyc,, +pip/_vendor/pygments/formatters/__pycache__/img.cpython-39.pyc,, +pip/_vendor/pygments/formatters/__pycache__/irc.cpython-39.pyc,, +pip/_vendor/pygments/formatters/__pycache__/latex.cpython-39.pyc,, +pip/_vendor/pygments/formatters/__pycache__/other.cpython-39.pyc,, +pip/_vendor/pygments/formatters/__pycache__/pangomarkup.cpython-39.pyc,, +pip/_vendor/pygments/formatters/__pycache__/rtf.cpython-39.pyc,, +pip/_vendor/pygments/formatters/__pycache__/svg.cpython-39.pyc,, +pip/_vendor/pygments/formatters/__pycache__/terminal.cpython-39.pyc,, +pip/_vendor/pygments/formatters/__pycache__/terminal256.cpython-39.pyc,, +pip/_vendor/pygments/formatters/_mapping.py,sha256=3A1rYSjYN9MLduCFWy2_mYhllPVpwlw55anRYnPXX8w,6516 +pip/_vendor/pygments/formatters/bbcode.py,sha256=cSKMOioUnE4TzvCCsK4IbJ6G78W07ZwHtkz4V1Wte0U,3314 +pip/_vendor/pygments/formatters/groff.py,sha256=ULgMKvGeLswX0KZn3IBp0p0U3rruiSHBtpl6O5qbqLs,5005 +pip/_vendor/pygments/formatters/html.py,sha256=0jM7Jc4xA4tsjmPq35uklm_En_OVdcNb0__SEXp2pDQ,35330 +pip/_vendor/pygments/formatters/img.py,sha256=r4iag_jCfyv_LhIt-1fRDeVEEoAfVJzkD9nZChIwiS8,21819 +pip/_vendor/pygments/formatters/irc.py,sha256=gi_IeIZeNaTfTMtvseLigZdS6lNicN7r7O7rnI6myo0,5871 +pip/_vendor/pygments/formatters/latex.py,sha256=qZUerrHt2Nn2aB4gJcdqj99qBkIxl_1v1ukYsf230Gk,18930 +pip/_vendor/pygments/formatters/other.py,sha256=Q01LtkqPZ8m_EYdgMVzXPUGjHoL00lXI3By97wzytYU,5073 +pip/_vendor/pygments/formatters/pangomarkup.py,sha256=ZpjALTSuGFwviJd5kOYwr-1NgqxCX3XRJrjXC7x1UbQ,2212 +pip/_vendor/pygments/formatters/rtf.py,sha256=qh7-z_wbUsTY6z7fZUGrYECYBlWB0wEdBwIZVEVybL0,5014 +pip/_vendor/pygments/formatters/svg.py,sha256=T7Jj004I3JUPOr48aAhQ368K2qWCciUyMQ2tdU-LB-4,7335 +pip/_vendor/pygments/formatters/terminal.py,sha256=cRD5hitINOkYlGZo9ma252vpJYPSGNgLivrsm6zGyec,4674 +pip/_vendor/pygments/formatters/terminal256.py,sha256=Bvz9zZL3UWc94TDm1GhKMI4x0BTit0XplhyRL0zmtkw,11753 +pip/_vendor/pygments/lexer.py,sha256=ECXWlEsbRnKs_njozZns6BGQ4riTMzct_BzAr3zV6dY,31937 +pip/_vendor/pygments/lexers/__init__.py,sha256=6Ds0GVBP3jrIU02wmjRdpoL4eFGhwT2IVD1zf3cV5_Y,11307 +pip/_vendor/pygments/lexers/__pycache__/__init__.cpython-39.pyc,, +pip/_vendor/pygments/lexers/__pycache__/_mapping.cpython-39.pyc,, +pip/_vendor/pygments/lexers/__pycache__/python.cpython-39.pyc,, +pip/_vendor/pygments/lexers/_mapping.py,sha256=jAxmvh5wvNkD-p3Fh6E7hY_B0sGbcxWRfseT6iq7ex4,70032 +pip/_vendor/pygments/lexers/python.py,sha256=LXnk43Lcngqn9xj6eRqdk2f73oF4kHZWiwgHMM_RlVM,52776 +pip/_vendor/pygments/modeline.py,sha256=37fen3cf1moCz4vMVJqX41eAQCmj8pzUchikgPcHp-U,986 +pip/_vendor/pygments/plugin.py,sha256=zGSig3S7QX-3o6RDxd4_Uvice_t25l_BN9aQQ9k8vmU,1727 +pip/_vendor/pygments/regexopt.py,sha256=mj8Fgu3sT0d5PZwRwDLexEvVOQbuHeosubQnqVwgiqs,3072 +pip/_vendor/pygments/scanner.py,sha256=nGoHy-Npk2ylUd4bws_CJN1hK785Xqo8e0teRmNX2jo,3091 +pip/_vendor/pygments/sphinxext.py,sha256=FZ2puvLe2Bztqtj6UJvQd7D8TvtOZ1GsfRJObvH59tE,4630 +pip/_vendor/pygments/style.py,sha256=lGyan5bU42q1kGMfFqafwL3g1j5EurTvfkv8vdP7NzQ,6257 +pip/_vendor/pygments/styles/__init__.py,sha256=Qx2zq6ufbDNE2cTp51M-s9zW-sDE-KLIqFw31qr3Bhg,3252 +pip/_vendor/pygments/styles/__pycache__/__init__.cpython-39.pyc,, +pip/_vendor/pygments/token.py,sha256=lNPgeaQTzu2DEUi6n_lxAIU7uy4DVj8LMI3nSVnTjks,6143 +pip/_vendor/pygments/unistring.py,sha256=Xs0FzOzE0l0iWRoTlcgi-Q_kAMdF5Gt5FL_goGKJc98,63188 +pip/_vendor/pygments/util.py,sha256=s9n8BQXIxG3lIwCPWv5-ci8yhaqq5JbEVK9v8Z-8_3I,9123 +pip/_vendor/pyparsing/__init__.py,sha256=jXheGTFT1b6r_4WxuOE0uVUqiouLJ3WHzOScpLieRgQ,9107 +pip/_vendor/pyparsing/__pycache__/__init__.cpython-39.pyc,, +pip/_vendor/pyparsing/__pycache__/actions.cpython-39.pyc,, +pip/_vendor/pyparsing/__pycache__/common.cpython-39.pyc,, +pip/_vendor/pyparsing/__pycache__/core.cpython-39.pyc,, +pip/_vendor/pyparsing/__pycache__/exceptions.cpython-39.pyc,, +pip/_vendor/pyparsing/__pycache__/helpers.cpython-39.pyc,, +pip/_vendor/pyparsing/__pycache__/results.cpython-39.pyc,, +pip/_vendor/pyparsing/__pycache__/testing.cpython-39.pyc,, +pip/_vendor/pyparsing/__pycache__/unicode.cpython-39.pyc,, +pip/_vendor/pyparsing/__pycache__/util.cpython-39.pyc,, +pip/_vendor/pyparsing/actions.py,sha256=60v7mETOBzc01YPH_qQD5isavgcSJpAfIKpzgjM3vaU,6429 +pip/_vendor/pyparsing/common.py,sha256=lFL97ooIeR75CmW5hjURZqwDCTgruqltcTCZ-ulLO2Q,12936 +pip/_vendor/pyparsing/core.py,sha256=GtQsD06HlwKPc7M8K8hyOuOW-cRnd87AxAHq-ad5lEk,212248 +pip/_vendor/pyparsing/diagram/__init__.py,sha256=h0gsUwmo5N3shgvfXVQTtqvTpUAv-ZdQjSQ6IUJmsxY,22165 +pip/_vendor/pyparsing/diagram/__pycache__/__init__.cpython-39.pyc,, +pip/_vendor/pyparsing/exceptions.py,sha256=H4D9gqMavqmAFSsdrU_J6bO-jA-T-A7yvtXWZpooIUA,9030 +pip/_vendor/pyparsing/helpers.py,sha256=kqpIZFG-y0fQ3g_TmloYllo9we6YCYiewZMXIK0y5wc,38299 +pip/_vendor/pyparsing/results.py,sha256=4D-oURF1cLeL7k0d3zMqUuWH_gTjop_OrZwik9O0HXU,25339 +pip/_vendor/pyparsing/testing.py,sha256=szs8AKZREZMhL0y0vsMfaTVAnpqPHetg6VKJBNmc4QY,13388 +pip/_vendor/pyparsing/unicode.py,sha256=IR-ioeGY29cZ49tG8Ts7ITPWWNP5G2DcZs58oa8zn44,10381 +pip/_vendor/pyparsing/util.py,sha256=kq772O5YSeXOSdP-M31EWpbH_ayj7BMHImBYo9xPD5M,6805 +pip/_vendor/requests/__init__.py,sha256=6IUFQM6K9V2NIu4fe4LtUsN21-TFbw_w3EfPpdUN-qc,5130 +pip/_vendor/requests/__pycache__/__init__.cpython-39.pyc,, +pip/_vendor/requests/__pycache__/__version__.cpython-39.pyc,, +pip/_vendor/requests/__pycache__/_internal_utils.cpython-39.pyc,, +pip/_vendor/requests/__pycache__/adapters.cpython-39.pyc,, +pip/_vendor/requests/__pycache__/api.cpython-39.pyc,, +pip/_vendor/requests/__pycache__/auth.cpython-39.pyc,, +pip/_vendor/requests/__pycache__/certs.cpython-39.pyc,, +pip/_vendor/requests/__pycache__/compat.cpython-39.pyc,, +pip/_vendor/requests/__pycache__/cookies.cpython-39.pyc,, +pip/_vendor/requests/__pycache__/exceptions.cpython-39.pyc,, +pip/_vendor/requests/__pycache__/help.cpython-39.pyc,, +pip/_vendor/requests/__pycache__/hooks.cpython-39.pyc,, +pip/_vendor/requests/__pycache__/models.cpython-39.pyc,, +pip/_vendor/requests/__pycache__/packages.cpython-39.pyc,, +pip/_vendor/requests/__pycache__/sessions.cpython-39.pyc,, +pip/_vendor/requests/__pycache__/status_codes.cpython-39.pyc,, +pip/_vendor/requests/__pycache__/structures.cpython-39.pyc,, +pip/_vendor/requests/__pycache__/utils.cpython-39.pyc,, +pip/_vendor/requests/__version__.py,sha256=q8miOQaomOv3S74lK4eQs1zZ5jwcnOusyEU-M2idhts,441 +pip/_vendor/requests/_internal_utils.py,sha256=Zx3PnEUccyfsB-ie11nZVAW8qClJy0gx1qNME7rgT18,1096 +pip/_vendor/requests/adapters.py,sha256=WazYJQ_b2LHhNDb_y0hscNlWVsSe5ca5I3pymPrer5w,21861 +pip/_vendor/requests/api.py,sha256=hjuoP79IAEmX6Dysrw8t032cLfwLHxbI_wM4gC5G9t0,6402 +pip/_vendor/requests/auth.py,sha256=OMoJIVKyRLy9THr91y8rxysZuclwPB-K1Xg1zBomUhQ,10207 +pip/_vendor/requests/certs.py,sha256=nXRVq9DtGmv_1AYbwjTu9UrgAcdJv05ZvkNeaoLOZxY,465 +pip/_vendor/requests/compat.py,sha256=N1281mkcTluMjKqCSLf88LR6HNOygEhS1TbR9LLsoVY,2114 +pip/_vendor/requests/cookies.py,sha256=Y-bKX6TvW3FnYlE6Au0SXtVVWcaNdFvuAwQxw-G0iTI,18430 +pip/_vendor/requests/exceptions.py,sha256=VcpBXOL-9JYhNbK8OZxCIImBgpQSXJlUelDPf1f-pmM,3446 +pip/_vendor/requests/help.py,sha256=dyhe3lcmHXnFCzDiZVjcGmVvvO_jtsfAm-AC542ndw8,3972 +pip/_vendor/requests/hooks.py,sha256=QReGyy0bRcr5rkwCuObNakbYsc7EkiKeBwG4qHekr2Q,757 +pip/_vendor/requests/models.py,sha256=7pzscX_47qxx7-zEaBWGxMoB33Vdf6HLoUKZh1ktEvM,35116 +pip/_vendor/requests/packages.py,sha256=njJmVifY4aSctuW3PP5EFRCxjEwMRDO6J_feG2dKWsI,695 +pip/_vendor/requests/sessions.py,sha256=Zu-Y9YPlwTIsyFx1hvIrc3ziyeFpuFPqcOuSuz8BNWs,29835 +pip/_vendor/requests/status_codes.py,sha256=gT79Pbs_cQjBgp-fvrUgg1dn2DQO32bDj4TInjnMPSc,4188 +pip/_vendor/requests/structures.py,sha256=msAtr9mq1JxHd-JRyiILfdFlpbJwvvFuP3rfUQT_QxE,3005 +pip/_vendor/requests/utils.py,sha256=siud-FQ6xgKFbL49DRvAb3PMQMMHoeCL_TCmuHh9AUU,33301 +pip/_vendor/resolvelib/__init__.py,sha256=UL-B2BDI0_TRIqkfGwLHKLxY-LjBlomz7941wDqzB1I,537 +pip/_vendor/resolvelib/__pycache__/__init__.cpython-39.pyc,, +pip/_vendor/resolvelib/__pycache__/providers.cpython-39.pyc,, +pip/_vendor/resolvelib/__pycache__/reporters.cpython-39.pyc,, +pip/_vendor/resolvelib/__pycache__/resolvers.cpython-39.pyc,, +pip/_vendor/resolvelib/__pycache__/structs.cpython-39.pyc,, +pip/_vendor/resolvelib/compat/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/_vendor/resolvelib/compat/__pycache__/__init__.cpython-39.pyc,, +pip/_vendor/resolvelib/compat/__pycache__/collections_abc.cpython-39.pyc,, +pip/_vendor/resolvelib/compat/collections_abc.py,sha256=uy8xUZ-NDEw916tugUXm8HgwCGiMO0f-RcdnpkfXfOs,156 +pip/_vendor/resolvelib/providers.py,sha256=roVmFBItQJ0TkhNua65h8LdNny7rmeqVEXZu90QiP4o,5872 +pip/_vendor/resolvelib/reporters.py,sha256=fW91NKf-lK8XN7i6Yd_rczL5QeOT3sc6AKhpaTEnP3E,1583 +pip/_vendor/resolvelib/resolvers.py,sha256=2wYzVGBGerbmcIpH8cFmgSKgLSETz8jmwBMGjCBMHG4,17592 +pip/_vendor/resolvelib/structs.py,sha256=IVIYof6sA_N4ZEiE1C1UhzTX495brCNnyCdgq6CYq28,4794 +pip/_vendor/rich/__init__.py,sha256=wF1th4JGBCVC02xfaw8j6P2MrFcJaQJL72scKtEmDYQ,5804 +pip/_vendor/rich/__main__.py,sha256=vd1PP-o7_1un-ThdgMU9LHV-D8z56yz_-fryczn38eE,8810 +pip/_vendor/rich/__pycache__/__init__.cpython-39.pyc,, +pip/_vendor/rich/__pycache__/__main__.cpython-39.pyc,, +pip/_vendor/rich/__pycache__/_cell_widths.cpython-39.pyc,, +pip/_vendor/rich/__pycache__/_emoji_codes.cpython-39.pyc,, +pip/_vendor/rich/__pycache__/_emoji_replace.cpython-39.pyc,, +pip/_vendor/rich/__pycache__/_extension.cpython-39.pyc,, +pip/_vendor/rich/__pycache__/_inspect.cpython-39.pyc,, +pip/_vendor/rich/__pycache__/_log_render.cpython-39.pyc,, +pip/_vendor/rich/__pycache__/_loop.cpython-39.pyc,, +pip/_vendor/rich/__pycache__/_lru_cache.cpython-39.pyc,, +pip/_vendor/rich/__pycache__/_palettes.cpython-39.pyc,, +pip/_vendor/rich/__pycache__/_pick.cpython-39.pyc,, +pip/_vendor/rich/__pycache__/_ratio.cpython-39.pyc,, +pip/_vendor/rich/__pycache__/_spinners.cpython-39.pyc,, +pip/_vendor/rich/__pycache__/_stack.cpython-39.pyc,, +pip/_vendor/rich/__pycache__/_timer.cpython-39.pyc,, +pip/_vendor/rich/__pycache__/_windows.cpython-39.pyc,, +pip/_vendor/rich/__pycache__/_wrap.cpython-39.pyc,, +pip/_vendor/rich/__pycache__/abc.cpython-39.pyc,, +pip/_vendor/rich/__pycache__/align.cpython-39.pyc,, +pip/_vendor/rich/__pycache__/ansi.cpython-39.pyc,, +pip/_vendor/rich/__pycache__/bar.cpython-39.pyc,, +pip/_vendor/rich/__pycache__/box.cpython-39.pyc,, +pip/_vendor/rich/__pycache__/cells.cpython-39.pyc,, +pip/_vendor/rich/__pycache__/color.cpython-39.pyc,, +pip/_vendor/rich/__pycache__/color_triplet.cpython-39.pyc,, +pip/_vendor/rich/__pycache__/columns.cpython-39.pyc,, +pip/_vendor/rich/__pycache__/console.cpython-39.pyc,, +pip/_vendor/rich/__pycache__/constrain.cpython-39.pyc,, +pip/_vendor/rich/__pycache__/containers.cpython-39.pyc,, +pip/_vendor/rich/__pycache__/control.cpython-39.pyc,, +pip/_vendor/rich/__pycache__/default_styles.cpython-39.pyc,, +pip/_vendor/rich/__pycache__/diagnose.cpython-39.pyc,, +pip/_vendor/rich/__pycache__/emoji.cpython-39.pyc,, +pip/_vendor/rich/__pycache__/errors.cpython-39.pyc,, +pip/_vendor/rich/__pycache__/file_proxy.cpython-39.pyc,, +pip/_vendor/rich/__pycache__/filesize.cpython-39.pyc,, +pip/_vendor/rich/__pycache__/highlighter.cpython-39.pyc,, +pip/_vendor/rich/__pycache__/json.cpython-39.pyc,, +pip/_vendor/rich/__pycache__/jupyter.cpython-39.pyc,, +pip/_vendor/rich/__pycache__/layout.cpython-39.pyc,, +pip/_vendor/rich/__pycache__/live.cpython-39.pyc,, +pip/_vendor/rich/__pycache__/live_render.cpython-39.pyc,, +pip/_vendor/rich/__pycache__/logging.cpython-39.pyc,, +pip/_vendor/rich/__pycache__/markup.cpython-39.pyc,, +pip/_vendor/rich/__pycache__/measure.cpython-39.pyc,, +pip/_vendor/rich/__pycache__/padding.cpython-39.pyc,, +pip/_vendor/rich/__pycache__/pager.cpython-39.pyc,, +pip/_vendor/rich/__pycache__/palette.cpython-39.pyc,, +pip/_vendor/rich/__pycache__/panel.cpython-39.pyc,, +pip/_vendor/rich/__pycache__/pretty.cpython-39.pyc,, +pip/_vendor/rich/__pycache__/progress.cpython-39.pyc,, +pip/_vendor/rich/__pycache__/progress_bar.cpython-39.pyc,, +pip/_vendor/rich/__pycache__/prompt.cpython-39.pyc,, +pip/_vendor/rich/__pycache__/protocol.cpython-39.pyc,, +pip/_vendor/rich/__pycache__/region.cpython-39.pyc,, +pip/_vendor/rich/__pycache__/repr.cpython-39.pyc,, +pip/_vendor/rich/__pycache__/rule.cpython-39.pyc,, +pip/_vendor/rich/__pycache__/scope.cpython-39.pyc,, +pip/_vendor/rich/__pycache__/screen.cpython-39.pyc,, +pip/_vendor/rich/__pycache__/segment.cpython-39.pyc,, +pip/_vendor/rich/__pycache__/spinner.cpython-39.pyc,, +pip/_vendor/rich/__pycache__/status.cpython-39.pyc,, +pip/_vendor/rich/__pycache__/style.cpython-39.pyc,, +pip/_vendor/rich/__pycache__/styled.cpython-39.pyc,, +pip/_vendor/rich/__pycache__/syntax.cpython-39.pyc,, +pip/_vendor/rich/__pycache__/table.cpython-39.pyc,, +pip/_vendor/rich/__pycache__/tabulate.cpython-39.pyc,, +pip/_vendor/rich/__pycache__/terminal_theme.cpython-39.pyc,, +pip/_vendor/rich/__pycache__/text.cpython-39.pyc,, +pip/_vendor/rich/__pycache__/theme.cpython-39.pyc,, +pip/_vendor/rich/__pycache__/themes.cpython-39.pyc,, +pip/_vendor/rich/__pycache__/traceback.cpython-39.pyc,, +pip/_vendor/rich/__pycache__/tree.cpython-39.pyc,, +pip/_vendor/rich/_cell_widths.py,sha256=2n4EiJi3X9sqIq0O16kUZ_zy6UYMd3xFfChlKfnW1Hc,10096 +pip/_vendor/rich/_emoji_codes.py,sha256=hu1VL9nbVdppJrVoijVshRlcRRe_v3dju3Mmd2sKZdY,140235 +pip/_vendor/rich/_emoji_replace.py,sha256=n-kcetsEUx2ZUmhQrfeMNc-teeGhpuSQ5F8VPBsyvDo,1064 +pip/_vendor/rich/_extension.py,sha256=Xt47QacCKwYruzjDi-gOBq724JReDj9Cm9xUi5fr-34,265 +pip/_vendor/rich/_inspect.py,sha256=vq6BjewwEvddjcBTr_lCcjYQBsKi92aTNpcXyaA5ERA,7444 +pip/_vendor/rich/_log_render.py,sha256=1ByI0PA1ZpxZY3CGJOK54hjlq4X-Bz_boIjIqCd8Kns,3225 +pip/_vendor/rich/_loop.py,sha256=hV_6CLdoPm0va22Wpw4zKqM0RYsz3TZxXj0PoS-9eDQ,1236 +pip/_vendor/rich/_lru_cache.py,sha256=M7H1ZQF32o6SxrpOur9zTIhEHlNXT9XnrcdhruUmG5I,1246 +pip/_vendor/rich/_palettes.py,sha256=cdev1JQKZ0JvlguV9ipHgznTdnvlIzUFDBb0It2PzjI,7063 +pip/_vendor/rich/_pick.py,sha256=evDt8QN4lF5CiwrUIXlOJCntitBCOsI3ZLPEIAVRLJU,423 +pip/_vendor/rich/_ratio.py,sha256=2lLSliL025Y-YMfdfGbutkQDevhcyDqc-DtUYW9mU70,5472 +pip/_vendor/rich/_spinners.py,sha256=huT1biTlwyp9Lm8S7bLfVzg1psUaIH5xHDwTaWEHVh0,26521 +pip/_vendor/rich/_stack.py,sha256=-C8OK7rxn3sIUdVwxZBBpeHhIzX0eI-VM3MemYfaXm0,351 +pip/_vendor/rich/_timer.py,sha256=zelxbT6oPFZnNrwWPpc1ktUeAT-Vc4fuFcRZLQGLtMI,417 +pip/_vendor/rich/_windows.py,sha256=nBO71icHMIHlzT7hg6fkoIdh1mT-5MvDdPDwunkshyw,2065 +pip/_vendor/rich/_wrap.py,sha256=OtnSxnERkuNlSM1d_MYtNg8KIYTcTBk3peg16dCZH_U,1804 +pip/_vendor/rich/abc.py,sha256=ON-E-ZqSSheZ88VrKX2M3PXpFbGEUUZPMa_Af0l-4f0,890 +pip/_vendor/rich/align.py,sha256=2zRHV8SzR5eP-vQkSDgjmgsBLBluCBwykgejAW6oRD0,10425 +pip/_vendor/rich/ansi.py,sha256=QaVVkfvVL6C3OsuWI9iQ-iJFkMsMohjYlxgMLnVTEPo,6676 +pip/_vendor/rich/bar.py,sha256=a7UD303BccRCrEhGjfMElpv5RFYIinaAhAuqYqhUvmw,3264 +pip/_vendor/rich/box.py,sha256=o0ywz1iW0WjGLPrRVDAZPh1CVPEgAOaWsn8Bf3sf43g,9069 +pip/_vendor/rich/cells.py,sha256=NadN20gFxE8Aj-2S3Drn7qgn-ZpsRZcNnTNtweRL7rA,4285 +pip/_vendor/rich/color.py,sha256=SD3yTf3t8japb-jOv8GYCMCDqyzpipzXS_0rAXhSlU4,17285 +pip/_vendor/rich/color_triplet.py,sha256=3lhQkdJbvWPoLDO-AnYImAWmJvV5dlgYNCVZ97ORaN4,1054 +pip/_vendor/rich/columns.py,sha256=HUX0KcMm9dsKNi11fTbiM_h2iDtl8ySCaVcxlalEzq8,7131 +pip/_vendor/rich/console.py,sha256=bioCy8012eZ8PIOBxMyyqxYPltKk2pGEG9jmwylNCQk,81236 +pip/_vendor/rich/constrain.py,sha256=1VIPuC8AgtKWrcncQrjBdYqA3JVWysu6jZo1rrh7c7Q,1288 +pip/_vendor/rich/containers.py,sha256=aKgm5UDHn5Nmui6IJaKdsZhbHClh_X7D-_Wg8Ehrr7s,5497 +pip/_vendor/rich/control.py,sha256=qxg6Yjd78XuF0VxthlT8O4dpvpACYwKkBfm2S4-IvHA,5298 +pip/_vendor/rich/default_styles.py,sha256=At42PcWzmnYWcx5fUOKyOUpI8HK5m4ItZqxkgHToaMs,7614 +pip/_vendor/rich/diagnose.py,sha256=4L8SZfbqjIRotzJ39QzD9-d4I80FyV1mNKHryg1eArE,183 +pip/_vendor/rich/emoji.py,sha256=omTF9asaAnsM4yLY94eR_9dgRRSm1lHUszX20D1yYCQ,2501 +pip/_vendor/rich/errors.py,sha256=5pP3Kc5d4QJ_c0KFsxrfyhjiPVe7J1zOqSFbFAzcV-Y,642 +pip/_vendor/rich/file_proxy.py,sha256=fHeReSO3VJ7IbH_9ri-OrPYbFC3UYOzeTNjngiiWOcY,1613 +pip/_vendor/rich/filesize.py,sha256=oQJnM5_7ygkpzt3GtNq5l3F6gmB7YahBA5vpdQVKLwI,2511 +pip/_vendor/rich/highlighter.py,sha256=AdhjC0meTYswZ_xKgka0cRYdNjLABLUzHAbyF3QpPWo,4894 +pip/_vendor/rich/json.py,sha256=RCm4lXBXrjvXHpqrWPH8wdGP0jEo4IohLmkddlhRY18,5051 +pip/_vendor/rich/jupyter.py,sha256=4sxNAwJs4g3dYfWy_enPw9fp0Tdn-82tV4T9uh9vAOM,3025 +pip/_vendor/rich/layout.py,sha256=b64KMDP2EPiC103P-v-_VZKGY13oWiiGS418P_KRRlc,14048 +pip/_vendor/rich/live.py,sha256=OKxMaFU5sFfuR--cJftGYjSvg1VPQri1U_DNZUjCsvI,13711 +pip/_vendor/rich/live_render.py,sha256=zElm3PrfSIvjOce28zETHMIUf9pFYSUA5o0AflgUP64,3667 +pip/_vendor/rich/logging.py,sha256=YNcCSK6pCo2Wg6JKqScAe6VgFqebHBnS5nDnBO4gXAA,10868 +pip/_vendor/rich/markup.py,sha256=hsVW_k1TIvj5OPPQ12ihAii9HSVa8N1TStvA5B2GGpo,8058 +pip/_vendor/rich/measure.py,sha256=Z74XvzIgLZm0xH-QIo1uX5d4oahavHe8D8MKyxLNqPQ,5258 +pip/_vendor/rich/padding.py,sha256=kTFGsdGe0os7tXLnHKpwTI90CXEvrceeZGCshmJy5zw,4970 +pip/_vendor/rich/pager.py,sha256=VK_2EfH0JduZWdyV-KZma06bvi_V5PWmHG6W7BoiaTg,838 +pip/_vendor/rich/palette.py,sha256=lInvR1ODDT2f3UZMfL1grq7dY_pDdKHw4bdUgOGaM4Y,3396 +pip/_vendor/rich/panel.py,sha256=O6ORyIhDcOLSEasTjpcDvmhvIcppPGCeQoXpoycIUT8,8637 +pip/_vendor/rich/pretty.py,sha256=HAB68BpYysaL1EXeV4X5Tt-U2hDlcLpbFz06fkojWWE,32572 +pip/_vendor/rich/progress.py,sha256=jcgi7aMnQ_YjSpAmQkalwtNsgVn9i56SeZGprr7tuOk,35926 +pip/_vendor/rich/progress_bar.py,sha256=ELiBaxJOgsRYKpNIrot7BC0bFXvmf8cTd6nxI02BbK0,7762 +pip/_vendor/rich/prompt.py,sha256=gKVd13YWv6jedzwcRPZGUINBjC-xcJhJ_xz_NvMW80c,11307 +pip/_vendor/rich/protocol.py,sha256=Vx6n4fEoSDhzSup8t3KH0iK2RWyssIOks5E0S1qw1GA,1401 +pip/_vendor/rich/region.py,sha256=rNT9xZrVZTYIXZC0NYn41CJQwYNbR-KecPOxTgQvB8Y,166 +pip/_vendor/rich/repr.py,sha256=1A0U0_ibG_bZbw71pUBIctO9Az-CQUuyOTbiKcJOwyw,4309 +pip/_vendor/rich/rule.py,sha256=cPK6NYo4kzh-vM_8a-rXajXplsbaHa6ahErYvGSsrJ0,4197 +pip/_vendor/rich/scope.py,sha256=HX13XsJfqzQHpPfw4Jn9JmJjCsRj9uhHxXQEqjkwyLA,2842 +pip/_vendor/rich/screen.py,sha256=YoeReESUhx74grqb0mSSb9lghhysWmFHYhsbMVQjXO8,1591 +pip/_vendor/rich/segment.py,sha256=MBBAWaHyqCQFCfiNbrTW4BGaFR1uU31XktJ1S3Taqb4,23916 +pip/_vendor/rich/spinner.py,sha256=V6dW0jIk5IO0_2MyxyftQf5VjCHI0T2cRhJ4F31hPIQ,4312 +pip/_vendor/rich/status.py,sha256=gJsIXIZeSo3urOyxRUjs6VrhX5CZrA0NxIQ-dxhCnwo,4425 +pip/_vendor/rich/style.py,sha256=AD1I7atfclsFCtGeL8ronH1Jj-02WLp9ZQ2VYqmpBjM,26469 +pip/_vendor/rich/styled.py,sha256=eZNnzGrI4ki_54pgY3Oj0T-x3lxdXTYh4_ryDB24wBU,1258 +pip/_vendor/rich/syntax.py,sha256=pJAD08ywowg5xVwTGCqUOMpDYskjoMoDYEV-hryEX5s,26994 +pip/_vendor/rich/table.py,sha256=oQAEBaV4zMUPyg_tSA93_GrCirdIf-osolxf9wb3pEo,36757 +pip/_vendor/rich/tabulate.py,sha256=nl0oeNbiXectEgTHyj3K7eN4NZMISpaogpOdZyEOGbs,1700 +pip/_vendor/rich/terminal_theme.py,sha256=E0nI_ycFpvflamt-KVCY4J52LmUjRi1Y6ICB-Ef3gMo,1459 +pip/_vendor/rich/text.py,sha256=auX3LpY-I6PBiNyxB3o3LyMEx7lna2cx9IbNQJDwtw8,44424 +pip/_vendor/rich/theme.py,sha256=GKNtQhDBZKAzDaY0vQVQQFzbc0uWfFe6CJXA-syT7zQ,3627 +pip/_vendor/rich/themes.py,sha256=0xgTLozfabebYtcJtDdC5QkX5IVUEaviqDUJJh4YVFk,102 +pip/_vendor/rich/traceback.py,sha256=hAU3IR295eFuup_px2NU4aCEWu7KQs1qpZbnqoHCtR0,25935 +pip/_vendor/rich/tree.py,sha256=JxyWbc27ZuwoLQnd7I-rSsRsqI9lzaVKlfTLJXla9U0,9122 +pip/_vendor/six.py,sha256=TOOfQi7nFGfMrIvtdr6wX4wyHH8M7aknmuLfo2cBBrM,34549 +pip/_vendor/tenacity/__init__.py,sha256=GLLsTFD4Bd5VDgTR6mU_FxyOsrxc48qONorVaRebeD4,18257 +pip/_vendor/tenacity/__pycache__/__init__.cpython-39.pyc,, +pip/_vendor/tenacity/__pycache__/_asyncio.cpython-39.pyc,, +pip/_vendor/tenacity/__pycache__/_utils.cpython-39.pyc,, +pip/_vendor/tenacity/__pycache__/after.cpython-39.pyc,, +pip/_vendor/tenacity/__pycache__/before.cpython-39.pyc,, +pip/_vendor/tenacity/__pycache__/before_sleep.cpython-39.pyc,, +pip/_vendor/tenacity/__pycache__/nap.cpython-39.pyc,, +pip/_vendor/tenacity/__pycache__/retry.cpython-39.pyc,, +pip/_vendor/tenacity/__pycache__/stop.cpython-39.pyc,, +pip/_vendor/tenacity/__pycache__/tornadoweb.cpython-39.pyc,, +pip/_vendor/tenacity/__pycache__/wait.cpython-39.pyc,, +pip/_vendor/tenacity/_asyncio.py,sha256=HEb0BVJEeBJE9P-m9XBxh1KcaF96BwoeqkJCL5sbVcQ,3314 +pip/_vendor/tenacity/_utils.py,sha256=-y68scDcyoqvTJuJJ0GTfjdSCljEYlbCYvgk7nM4NdM,1944 +pip/_vendor/tenacity/after.py,sha256=dlmyxxFy2uqpLXDr838DiEd7jgv2AGthsWHGYcGYsaI,1496 +pip/_vendor/tenacity/before.py,sha256=7XtvRmO0dRWUp8SVn24OvIiGFj8-4OP5muQRUiWgLh0,1376 +pip/_vendor/tenacity/before_sleep.py,sha256=ThyDvqKU5yle_IvYQz_b6Tp6UjUS0PhVp6zgqYl9U6Y,1908 +pip/_vendor/tenacity/nap.py,sha256=fRWvnz1aIzbIq9Ap3gAkAZgDH6oo5zxMrU6ZOVByq0I,1383 +pip/_vendor/tenacity/retry.py,sha256=62R71W59bQjuNyFKsDM7hE2aEkEPtwNBRA0tnsEvgSk,6645 +pip/_vendor/tenacity/stop.py,sha256=sKHmHaoSaW6sKu3dTxUVKr1-stVkY7lw4Y9yjZU30zQ,2790 +pip/_vendor/tenacity/tornadoweb.py,sha256=E8lWO2nwe6dJgoB-N2HhQprYLDLB_UdSgFnv-EN6wKE,2145 +pip/_vendor/tenacity/wait.py,sha256=e_Saa6I2tsNLpCL1t9897wN2fGb0XQMQlE4bU2t9V2w,6691 +pip/_vendor/tomli/__init__.py,sha256=z1Elt0nLAqU5Y0DOn9p__8QnLWavlEOpRyQikdYgKro,230 +pip/_vendor/tomli/__pycache__/__init__.cpython-39.pyc,, +pip/_vendor/tomli/__pycache__/_parser.cpython-39.pyc,, +pip/_vendor/tomli/__pycache__/_re.cpython-39.pyc,, +pip/_vendor/tomli/_parser.py,sha256=50BD4o9YbzFAGAYyZLqZC8F81DQ7iWWyJnrHNwBKa6A,22415 +pip/_vendor/tomli/_re.py,sha256=5GPfgXKteg7wRFCF-DzlkAPI2ilHbkMK2-JC49F-AJQ,2681 +pip/_vendor/typing_extensions.py,sha256=1uqi_RSlI7gos4eJB_NEV3d5wQwzTUQHd3_jrkbTo8Q,87149 +pip/_vendor/urllib3/__init__.py,sha256=j3yzHIbmW7CS-IKQJ9-PPQf_YKO8EOAey_rMW0UR7us,2763 +pip/_vendor/urllib3/__pycache__/__init__.cpython-39.pyc,, +pip/_vendor/urllib3/__pycache__/_collections.cpython-39.pyc,, +pip/_vendor/urllib3/__pycache__/_version.cpython-39.pyc,, +pip/_vendor/urllib3/__pycache__/connection.cpython-39.pyc,, +pip/_vendor/urllib3/__pycache__/connectionpool.cpython-39.pyc,, +pip/_vendor/urllib3/__pycache__/exceptions.cpython-39.pyc,, +pip/_vendor/urllib3/__pycache__/fields.cpython-39.pyc,, +pip/_vendor/urllib3/__pycache__/filepost.cpython-39.pyc,, +pip/_vendor/urllib3/__pycache__/poolmanager.cpython-39.pyc,, +pip/_vendor/urllib3/__pycache__/request.cpython-39.pyc,, +pip/_vendor/urllib3/__pycache__/response.cpython-39.pyc,, +pip/_vendor/urllib3/_collections.py,sha256=Rp1mVyBgc_UlAcp6M3at1skJBXR5J43NawRTvW2g_XY,10811 +pip/_vendor/urllib3/_version.py,sha256=_NdMUQaeBvFHAX2z3zAIX2Wum58A6rVtY1f7ByHsQ4g,63 +pip/_vendor/urllib3/connection.py,sha256=6zokyboYYKm9VkyrQvVVLgxMyCZK7n9Vmg_2ZK6pbhc,20076 +pip/_vendor/urllib3/connectionpool.py,sha256=qz-ICrW6g4TZVCbDQ8fRe68BMpXkskkR9vAVY9zUWtA,39013 +pip/_vendor/urllib3/contrib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/_vendor/urllib3/contrib/__pycache__/__init__.cpython-39.pyc,, +pip/_vendor/urllib3/contrib/__pycache__/_appengine_environ.cpython-39.pyc,, +pip/_vendor/urllib3/contrib/__pycache__/appengine.cpython-39.pyc,, +pip/_vendor/urllib3/contrib/__pycache__/ntlmpool.cpython-39.pyc,, +pip/_vendor/urllib3/contrib/__pycache__/pyopenssl.cpython-39.pyc,, +pip/_vendor/urllib3/contrib/__pycache__/securetransport.cpython-39.pyc,, +pip/_vendor/urllib3/contrib/__pycache__/socks.cpython-39.pyc,, +pip/_vendor/urllib3/contrib/_appengine_environ.py,sha256=bDbyOEhW2CKLJcQqAKAyrEHN-aklsyHFKq6vF8ZFsmk,957 +pip/_vendor/urllib3/contrib/_securetransport/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/_vendor/urllib3/contrib/_securetransport/__pycache__/__init__.cpython-39.pyc,, +pip/_vendor/urllib3/contrib/_securetransport/__pycache__/bindings.cpython-39.pyc,, +pip/_vendor/urllib3/contrib/_securetransport/__pycache__/low_level.cpython-39.pyc,, +pip/_vendor/urllib3/contrib/_securetransport/bindings.py,sha256=4Xk64qIkPBt09A5q-RIFUuDhNc9mXilVapm7WnYnzRw,17632 +pip/_vendor/urllib3/contrib/_securetransport/low_level.py,sha256=B2JBB2_NRP02xK6DCa1Pa9IuxrPwxzDzZbixQkb7U9M,13922 +pip/_vendor/urllib3/contrib/appengine.py,sha256=lfzpHFmJiO82shClLEm3QB62SYgHWnjpZOH_2JhU5Tc,11034 +pip/_vendor/urllib3/contrib/ntlmpool.py,sha256=ej9gGvfAb2Gt00lafFp45SIoRz-QwrQ4WChm6gQmAlM,4538 +pip/_vendor/urllib3/contrib/pyopenssl.py,sha256=DD4pInv_3OEEGffEFynBoirc8ldR789sLmGSKukzA0E,16900 +pip/_vendor/urllib3/contrib/securetransport.py,sha256=4qUKo7PUV-vVIqXmr2BD-sH7qplB918jiD5eNsRI9vU,34449 +pip/_vendor/urllib3/contrib/socks.py,sha256=aRi9eWXo9ZEb95XUxef4Z21CFlnnjbEiAo9HOseoMt4,7097 +pip/_vendor/urllib3/exceptions.py,sha256=0Mnno3KHTNfXRfY7638NufOPkUb6mXOm-Lqj-4x2w8A,8217 +pip/_vendor/urllib3/fields.py,sha256=kvLDCg_JmH1lLjUUEY_FLS8UhY7hBvDPuVETbY8mdrM,8579 +pip/_vendor/urllib3/filepost.py,sha256=5b_qqgRHVlL7uLtdAYBzBh-GHmU5AfJVt_2N0XS3PeY,2440 +pip/_vendor/urllib3/packages/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/_vendor/urllib3/packages/__pycache__/__init__.cpython-39.pyc,, +pip/_vendor/urllib3/packages/__pycache__/six.cpython-39.pyc,, +pip/_vendor/urllib3/packages/backports/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pip/_vendor/urllib3/packages/backports/__pycache__/__init__.cpython-39.pyc,, +pip/_vendor/urllib3/packages/backports/__pycache__/makefile.cpython-39.pyc,, +pip/_vendor/urllib3/packages/backports/makefile.py,sha256=nbzt3i0agPVP07jqqgjhaYjMmuAi_W5E0EywZivVO8E,1417 +pip/_vendor/urllib3/packages/six.py,sha256=1LVW7ljqRirFlfExjwl-v1B7vSAUNTmzGMs-qays2zg,34666 +pip/_vendor/urllib3/poolmanager.py,sha256=whzlX6UTEgODMOCy0ZDMUONRBCz5wyIM8Z9opXAY-Lk,19763 +pip/_vendor/urllib3/request.py,sha256=ZFSIqX0C6WizixecChZ3_okyu7BEv0lZu1VT0s6h4SM,5985 +pip/_vendor/urllib3/response.py,sha256=hGhGBh7TkEkh_IQg5C1W_xuPNrgIKv5BUXPyE-q0LuE,28203 +pip/_vendor/urllib3/util/__init__.py,sha256=JEmSmmqqLyaw8P51gUImZh8Gwg9i1zSe-DoqAitn2nc,1155 +pip/_vendor/urllib3/util/__pycache__/__init__.cpython-39.pyc,, +pip/_vendor/urllib3/util/__pycache__/connection.cpython-39.pyc,, +pip/_vendor/urllib3/util/__pycache__/proxy.cpython-39.pyc,, +pip/_vendor/urllib3/util/__pycache__/queue.cpython-39.pyc,, +pip/_vendor/urllib3/util/__pycache__/request.cpython-39.pyc,, +pip/_vendor/urllib3/util/__pycache__/response.cpython-39.pyc,, +pip/_vendor/urllib3/util/__pycache__/retry.cpython-39.pyc,, +pip/_vendor/urllib3/util/__pycache__/ssl_.cpython-39.pyc,, +pip/_vendor/urllib3/util/__pycache__/ssl_match_hostname.cpython-39.pyc,, +pip/_vendor/urllib3/util/__pycache__/ssltransport.cpython-39.pyc,, +pip/_vendor/urllib3/util/__pycache__/timeout.cpython-39.pyc,, +pip/_vendor/urllib3/util/__pycache__/url.cpython-39.pyc,, +pip/_vendor/urllib3/util/__pycache__/wait.cpython-39.pyc,, +pip/_vendor/urllib3/util/connection.py,sha256=5Lx2B1PW29KxBn2T0xkN1CBgRBa3gGVJBKoQoRogEVk,4901 +pip/_vendor/urllib3/util/proxy.py,sha256=zUvPPCJrp6dOF0N4GAVbOcl6o-4uXKSrGiTkkr5vUS4,1605 +pip/_vendor/urllib3/util/queue.py,sha256=nRgX8_eX-_VkvxoX096QWoz8Ps0QHUAExILCY_7PncM,498 +pip/_vendor/urllib3/util/request.py,sha256=NnzaEKQ1Pauw5MFMV6HmgEMHITf0Aua9fQuzi2uZzGc,4123 +pip/_vendor/urllib3/util/response.py,sha256=GJpg3Egi9qaJXRwBh5wv-MNuRWan5BIu40oReoxWP28,3510 +pip/_vendor/urllib3/util/retry.py,sha256=iESg2PvViNdXBRY4MpL4h0kqwOOkHkxmLn1kkhFHPU8,22001 +pip/_vendor/urllib3/util/ssl_.py,sha256=X4-AqW91aYPhPx6-xbf66yHFQKbqqfC_5Zt4WkLX1Hc,17177 +pip/_vendor/urllib3/util/ssl_match_hostname.py,sha256=w01jCYuwvQ038p9mhc1P1gF8IiTN1qHakThpoukOlbw,5751 +pip/_vendor/urllib3/util/ssltransport.py,sha256=NA-u5rMTrDFDFC8QzRKUEKMG0561hOD4qBTr3Z4pv6E,6895 +pip/_vendor/urllib3/util/timeout.py,sha256=QSbBUNOB9yh6AnDn61SrLQ0hg5oz0I9-uXEG91AJuIg,10003 +pip/_vendor/urllib3/util/url.py,sha256=QVEzcbHipbXyCWwH6R4K4TR-N8T4LM55WEMwNUTBmLE,14047 +pip/_vendor/urllib3/util/wait.py,sha256=3MUKRSAUJDB2tgco7qRUskW0zXGAWYvRRE4Q1_6xlLs,5404 +pip/_vendor/vendor.txt,sha256=SpijkWP2aapE1DEgOKL1wxuOz1ztM7E2Xs2PZ-V1PKA,496 +pip/_vendor/webencodings/__init__.py,sha256=qOBJIuPy_4ByYH6W_bNgJF-qYQ2DoU-dKsDu5yRWCXg,10579 +pip/_vendor/webencodings/__pycache__/__init__.cpython-39.pyc,, +pip/_vendor/webencodings/__pycache__/labels.cpython-39.pyc,, +pip/_vendor/webencodings/__pycache__/mklabels.cpython-39.pyc,, +pip/_vendor/webencodings/__pycache__/tests.cpython-39.pyc,, +pip/_vendor/webencodings/__pycache__/x_user_defined.cpython-39.pyc,, +pip/_vendor/webencodings/labels.py,sha256=4AO_KxTddqGtrL9ns7kAPjb0CcN6xsCIxbK37HY9r3E,8979 +pip/_vendor/webencodings/mklabels.py,sha256=GYIeywnpaLnP0GSic8LFWgd0UVvO_l1Nc6YoF-87R_4,1305 +pip/_vendor/webencodings/tests.py,sha256=OtGLyjhNY1fvkW1GvLJ_FV9ZoqC9Anyjr7q3kxTbzNs,6563 +pip/_vendor/webencodings/x_user_defined.py,sha256=yOqWSdmpytGfUgh_Z6JYgDNhoc-BAHyyeeT15Fr42tM,4307 +pip/py.typed,sha256=EBVvvPRTn_eIpz5e5QztSCdrMX7Qwd7VP93RSoIlZ2I,286 diff --git a/venv/Lib/site-packages/pip-22.0.4.dist-info/WHEEL b/venv/Lib/site-packages/pip-22.0.4.dist-info/WHEEL new file mode 100644 index 0000000..becc9a6 --- /dev/null +++ b/venv/Lib/site-packages/pip-22.0.4.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.37.1) +Root-Is-Purelib: true +Tag: py3-none-any + diff --git a/venv/Lib/site-packages/pip-22.0.4.dist-info/entry_points.txt b/venv/Lib/site-packages/pip-22.0.4.dist-info/entry_points.txt new file mode 100644 index 0000000..9609f72 --- /dev/null +++ b/venv/Lib/site-packages/pip-22.0.4.dist-info/entry_points.txt @@ -0,0 +1,5 @@ +[console_scripts] +pip = pip._internal.cli.main:main +pip3 = pip._internal.cli.main:main +pip3.9 = pip._internal.cli.main:main + diff --git a/venv/Lib/site-packages/pip-22.0.4.dist-info/top_level.txt b/venv/Lib/site-packages/pip-22.0.4.dist-info/top_level.txt new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/venv/Lib/site-packages/pip-22.0.4.dist-info/top_level.txt @@ -0,0 +1 @@ +pip diff --git a/venv/Lib/site-packages/pip/__init__.py b/venv/Lib/site-packages/pip/__init__.py new file mode 100644 index 0000000..3a0d263 --- /dev/null +++ b/venv/Lib/site-packages/pip/__init__.py @@ -0,0 +1,13 @@ +from typing import List, Optional + +__version__ = "22.0.4" + + +def main(args: Optional[List[str]] = None) -> int: + """This is an internal API only meant for use by pip's own console scripts. + + For additional details, see https://github.com/pypa/pip/issues/7498. + """ + from pip._internal.utils.entrypoints import _wrapper + + return _wrapper(args) diff --git a/venv/Lib/site-packages/pip/__main__.py b/venv/Lib/site-packages/pip/__main__.py new file mode 100644 index 0000000..fe34a7b --- /dev/null +++ b/venv/Lib/site-packages/pip/__main__.py @@ -0,0 +1,31 @@ +import os +import sys +import warnings + +# Remove '' and current working directory from the first entry +# of sys.path, if present to avoid using current directory +# in pip commands check, freeze, install, list and show, +# when invoked as python -m pip +if sys.path[0] in ("", os.getcwd()): + sys.path.pop(0) + +# If we are running from a wheel, add the wheel to sys.path +# This allows the usage python pip-*.whl/pip install pip-*.whl +if __package__ == "": + # __file__ is pip-*.whl/pip/__main__.py + # first dirname call strips of '/__main__.py', second strips off '/pip' + # Resulting path is the name of the wheel itself + # Add that to sys.path so we can import pip + path = os.path.dirname(os.path.dirname(__file__)) + sys.path.insert(0, path) + +if __name__ == "__main__": + # Work around the error reported in #9540, pending a proper fix. + # Note: It is essential the warning filter is set *before* importing + # pip, as the deprecation happens at import time, not runtime. + warnings.filterwarnings( + "ignore", category=DeprecationWarning, module=".*packaging\\.version" + ) + from pip._internal.cli.main import main as _main + + sys.exit(_main()) diff --git a/venv/Lib/site-packages/pip/__pycache__/__init__.cpython-39.pyc b/venv/Lib/site-packages/pip/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0e25b14114b9d8114f669d1750bf029bd1cff553 GIT binary patch literal 624 zcmYjP&2H2%5Vn(Sx-3-Uz@?}91X_tEXjMU}5TYtVLMjD`a#=-+yz#JWnmCrnVU<-m z!Id)?UVvB1l@qVPiSZ&(N1oBx^YeWkTkh^o7|GZDy9?lq{S2GylF;TEDbC0!rg+U7 zKIcs|k2q7&JXSjp0f%Id?J*dsD*ZB=rz(ESrsH2!$EMMcoN4sK__g)AHL~8M zvsv~aJ3J2|>6SR84t(cKMJ)bHL|)KSQoKV(aTNsypEze%{EB_%gb{DPU92<;TG9w@ zJUBuSCvRSg*3`XdKpHRJw@!2jV$ln$?L8Fj+K8$(*w!Gha@u;#CKEyOf>NbY`Y%K0kmHo5Js%&BLt5j(*A(c$BxY}?3%%S`z&F4s<43yyBP zPnlWyk7d?*YMp`cuD30nqDwVtll`6t*2F7uvfkpsE5EHl#zkj0jZ-f#?V~TQ1u_Obf1QN;4nUz2goBWCCKnI#fBkzVJ5Dg5O zdon`iXJD&+$zdvEnOsLSXil10JI@c0L$^2K;L|u+(l=z0{y=x+wI@C;%T_2|mOfFn z?krp#W)F?1&PA int: + """This is preserved for old console scripts that may still be referencing + it. + + For additional details, see https://github.com/pypa/pip/issues/7498. + """ + from pip._internal.utils.entrypoints import _wrapper + + return _wrapper(args) diff --git a/venv/Lib/site-packages/pip/_internal/__pycache__/__init__.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a835e8fc05e54f30804a39f6f2670106c75b4e03 GIT binary patch literal 745 zcmZuv!EV$*44p}`X}aA?NO0+?b3$4~vlj%V0t71JfU0t!2q}sb&1T%)DU)P0o=|O7 zPH^Q95P~DWlq)BGffJqup&n|*9y=b}&mPO|?J*QP5`{Ah`FS#A)Y5XOyVB7CQq1Yp1P8;g`~jMy>>UZH$;|sDfM38T3NpXwRgS*Fnjm+&otI}5q#zU zvSmf8_EnYJ)sQq&w_8*K!!odR61iYa`SEmXNd3yvfLwSD7n2z7T-ShZ&!F}dLfzAI zI@zM_oF8JkTim=Rz=cx9WDSCrVL>H^7`+=}n!&pKy6Gz-tnrXNYC6>$coGJS8HpQF J#wSS@{{bQJ%-#S1 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/__pycache__/build_env.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/__pycache__/build_env.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bd1643e290c680c00656d882e72c1df3e7a5432d GIT binary patch literal 9498 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/__pycache__/cache.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/__pycache__/cache.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..edd0f1ed7977ae4f1474c01ea1bc66b3b64aa0fe GIT binary patch literal 8302 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/__pycache__/configuration.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/__pycache__/configuration.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..41138753e8631db2fa31ed70677c7e84242ec314 GIT binary patch literal 11150 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 Z;yE@P%HaRMvbjav$vgA;BZZ~I{{!2QE|CBL literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/__pycache__/exceptions.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/__pycache__/exceptions.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c5efd65562c3819c63f59f3aed175f489d15b392 GIT binary patch literal 23347 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 grGuw?#{6n{_SI$B8oe{7*)IRF3v literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/__pycache__/main.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/__pycache__/main.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b16c3c6aa8b0b7291c52d68483e5d16d9f15ce0b GIT binary patch literal 610 zcmYjPKX2496t|OHdYq`lz|yInkWS)~1wpA00u?b;W$3Y-B2~Wl_0Etu)_V@sRqX^T z-vF`mm9jGN6_|JqQq?EFpMJLAe_QYG&jic&!zb&d6ykT>+?R|uZ&;~dFv7@2v~nfe zWR*x^a!5czdLRx2WG4NQn9NMRO;!_=oQwJ1ANCRRWXMh}g<<-^2irN_oW&!J8ya$i z(4(t4^PMEjqMoqQV+JEl60_b)DQ@JA_$oPedi`^`wWN4?1Oog5MqPHOy2hxwbJR7U zs7C7psj$^SwR)#0*rriyPzaZR;A-nOGsR*)|0`7ng0>AkRRo~6A$U42 z%Z&}&eqGdETl$^XrMJGcL_JXX;@QiiVhn__r@0)a7gwmg2jr#?*|NB>E&%cvik_>X z0$jkI@A#B3k3I>;p^yBRz$x>;=O@S2M{bfT?VP6St@rPA(A8;I>!w;l>njeu=$+T~ zXE2MaEkLt)e)P#wP1o_Rx=UNN+PcE;hAfhpiXw>oVS@25%;niUAM&vCJRFQKfhog~ fQoteQGDoYiu6ytxnoM7{o#`8R9ebzf`Y8PegN~r% literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/__pycache__/pyproject.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/__pycache__/pyproject.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9d4ccbf33916c43786847ff877dd8be49778a463 GIT binary patch literal 3535 zcmb7H&2JmW6`$E1u9nLW$&y-Fshw=xG!hGoaDaZeg6lSpQq+N~3b9+agaTs48A@yK zmuH5u$u4_{ay9Bh4*}u?a!&1k66BC`vDX3xdg-ON0CoD_EJ;y@QJ^dAaAx*>{@$B6 zPeG&M5qKWI_U8VLR|xq#F6JKx7C(nq{RIY2IE_dLf31kdR>z_^w<9}d9TrzQmDuSx zW{*V+vDHs2(>ujkwuq#*3XrN(2*2eBr6ZU0(f&bDfTG?k%>i@yq$3X_AEe+I2~x__^5q|gJI z^e9?Bd2nvS`wqP70t}kuL<0!vE860eTOYxCn;g?)blToI!)yUPLq>eh!;q5?mc|rB zP!#c7LdgS*6JVq}V1yTfjo?|*6NRm`ge|LmrC^~J@n4Bt1_59H?wzf@-zXu~UXUb# z+Iu_8wgVmP-Aa2ww0B3u*w4n!gzW%BwGDEc?NWOS(;s%`|a>ZbiJSk%52p&oU;JtJ<}vI(RGL$bn# zu(YVG!;Z1H99EEE@da6nu&EFsLM37Y-mXo}?y7Vkd!oxB1A01@L)id|GuUEa5L*)% zv_O-4^u)^Hd_1!NQEO+^JoOK=3o^$_Rl%}A9~SIh8YW=r8gRa7=}H{j7u^|i7a7on zskIkjUM!moyFFA8oNb|lFj6g6xUx)JRV?gd01{qQdWWKSzo<{vMp~;#q(1FfDTU|#IFXg0pM={#{>ZSjE>o4Zo#~gGu6&3s;%wZ z{siFp)HD95LD<@9woGd&ez_oCfaK-@PW1Es>=`Eu6uRyxu z-|ykg7fxJW0XjEfoQ++O_8I8-4B%%2DnHJN`dHiCK}~#NOp4Vt zfhD+4pHQ`m)Vv8AVI?=Tm)m^tF?#Ou<{BASbuF(RBjqo29lk;FdThbh>NfdcXY7sY zx{-Uwl#;t7*ihSHQvt z@8vF_q8#; zPz`#*6w06ZJ82?jLQv4`iA9jii8%~ZvaWro98uT{bu{!Q$EUhvE@0%NB4t|8u5Bnh3SBL2!;usL)aU>3c-q7!* z9P~kjx$LJ9UHLGC?}2Zw%bDJd*$ge1vsd|jnZ_?*cKHnT)YEB@Cw1s7(HW7awwluA z2Y`sVn4$=hCFnzf`2aGyeMS@7Hpq-~`*{8OA~_0Wnjo-e2xn#8I1ag#`eBSfmb_)* zEIr$pn7fG(wayw{Vu5YI5kQ*G=aDbdRG+3_%cvjS^?53kpQPFkvP=XLx%Lt6-Jw2& zWSm@wTYe%!42HixO{R6=g5@la&DmS``{^Lz?NMc*`=oMsI0Kv(ussP5#OT6JjozD(_}D_A3D9W(P^t}_-v@eZ%mS4rqc?!KmnLx8LIDbr zDQ5ErV#^2M%LFP@W=TR%P2_isoKRu4lvP}?G!u!$=DMgvP+Orh05!a@4}>lpIQ4O$ zC0?+mJCWF$y{HIv(|GmwL#9I}S>$(S+;!7#*N~#wb(Rh($r0ZxU$`(aU3IZns^~}vEmG+rS`(i z3?-8wivaRVAB^}tE|D>zob#RUoQY;< zs|J3LUwU=pZ|4o;pVT=1bI^Dff9aTp!3<_5MlgMwfvMY8VClCV*!t}Rj((Q{SHH_a z8E-4`(n?TCt3lPI^>#9o)`D4GcanNK7tHB;DQTqh!Mv`!$wGQ6IHl|5WHCJ*oYr+O zIg>60OS)c3&Zg&rbLsiue0m|cp!=%H#q?5e3H6!aGPfr$aevTYesYF-=v?r zO{=hPWP`%F8Mjr_EK0pdNRGHu>#1W1KpcHn|EJ??nAX zg*@AdMV_TRBPok(oYuv8c2DpQ7d&foiT>)nxVOfo#6Z(7<|EdP+E@{)v=?^bgcptW z7H@Bdy-00^`EJHVQ5L+HU>2?Bnd}Q5vRDikmLIGvrz^|s{_=a*mp{C|ycW<=w)voN z1y_BMwPER_pN$&*SMiqsh%quI#=bE&l{v9S=Dsy%+aZ`dJT(J5rhAsIm`^pgHU`aT^`x+o0OGwY@}hgzGO$A3o-@oV&QgPb6+ zxDB9K0FTWa0L9@Y^pu{O%w^?A&Yl^#+~(zO8M8dVsluw5ou%{S2%Zz3aMHvcv$MI&dOUro~O|eXPeF0qNKH5)SoMz&{|kI%&%)sH;*%| z^(j7_yvMV`>B<~sl1Hp4f3$W>h+Gua-$hBEPwUU+ZryM_&U4=C#>}by*S)~cYq6uTDvbm z5+H&&<j>OD87- z*#c1382tHr_$u8!WQ}SPNi}t3(ZZ4LH?3#pwP)sa@*9~86+%(6s7ek-jzGb(IWJzq zL@`5!PX!siD8s$T?Zqs0X-4v-5*<=yv9NaQ&h6FrZmoV0-n?=DR(Siv`{ET^Rbu_L zCk1(6QQ8$TXl9<)*Qg*YiC0lH-KmLbgW@MtTt-niia%6^**Rf)z&6_9Z(@e@Q5cqM zI`)F;I142QRAl|f^%_>qyk=SGty#lUCy+s_n-#(}ohJ;7Y8a+D>x0+Aq85gq_oL)s z#KsB5kMWJd>k0UmP=kY`6G3Vey^Yah8zf2=gf#8pUo;a+AEd6fxbPv?-;JanXYgkP zRpxIDd{BI~>f?8RE5?xY`w|0Lu6&jIES3m-10T!%es5DmjQc5KCqghu&1f~Pi8H?w zwUw6hf^@j5;;B#3h1R4|hL^bJ%YJ*y$5vR@@$<~T%~>v@mR^4s=Z|}UXc=cL8alwo zP<6b~r(j-G4nH88mLO#m4z{U|saZ4AB2Ef!Iyfm}V+g4aFkMpEG2EId-oqO-P?pnd zpeW}(`hxs^prFWc^%S8r_kF2gWhAWSqC+6^svSA4a;lUi2RH<8< zxCrhpbKs=q9YYKm+F<1>Vs-x*0?8dXB z*(atvdmw44d-f}X&Hl+6*VVbnc~-}2XH?%u&Wpfz1(bB*i8=UeN=oWn_aYL z_Z}EJ1QK@VhyT#n^*g!nqYT(1m(nd*u{8zkoj8qwQb4mK_~(6u$AO=Bd>u9=p*Kgy z=ff}kUCy^#{u%`_LaPLm0pmQ@UJ+*+b|eQ7j(50^EKMg*19TSNeE(w~{0K>Tr=#agW0Dq!jnFFc57`!RPr(P&))e95Cg5}zp^Jj6c#R4o zxA=?e6{2AATQrJ!+3!J~lwpS5vG+F{vWf#b%#;U6F5eLoUl z0Ez5FAL$@w`pfc{{#L%r(Z1$C?<6HhJ5iiO8wqb!X}#Ra`w8>gaIYAt`vIGfyq!4G zs=B&-#7zFm$|2ie16Q#s1#__0@QwT6F;EYf1E}DXzfA2-f=J&9&LGv%R$v7P(8<%o zHniBuo0l}Nh+CxN^1+rh@lLHlsc7N$RXfXfr-6n78F&G~?dLQ$t8$QMC^?S8q$uh6 zZNc$jK@=eoEIMsnY!wqaSY~xrlVY{fm*cR`SEQ%k+tiBFC z&r>#FGUl!}TL--a}EibQT!mGiuZYPjhv&x#CPh*Nj6+VJyQu z!Q`S$^4lpp$=PS99{}wfEz!>0hHROjFv>O4F&&EOmV@YBwHA?QR=;!XhFP^e^jY+L z<9ho2t&5nCn&ti1#Y&In+BM6wtF*>)zp={5RjVY^LZ*u6ndjB1Wm?|~j_);_f&d{F zsL(k}nKVlp^$;wyVGuTCi=2C!4{2Mt3YlfLDJW(O3fjdb9Ib_8We9YbP2ms|T899n zm?S7V9ZWpDbG5YRw~qXGinl9T*oip@F&1}NZ4eDZQfLdfpI+cvDOVA|7EMFzD<=kV z)l6jT1V3m@pWIZ&)ow1fF;`!sMTItg`9*OE){sUQ!f6hm)4XZkNcmlH_Ww;!aqXPu zklNQO2>y38lEtq`LF-h!O9kC0wbvHTMxH0y4GLG^WTdv-F=!oSU4{4dG?jaYZWr=L cC_JFz`Gd?5x#8in2!uIy)o!@;Uo@)!19?N#nE(I) literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/__pycache__/wheel_builder.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/__pycache__/wheel_builder.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fde4d8402514f19e99ace04fcff70103765779e4 GIT binary patch literal 9154 zcmbtZTW{Rfb|yI-&PAh(Wm&$&c4#NQjBQP9$FUtB+b8iYaq1|B?IaD4Qi2+8jYc9l z4$u^kilRXJEBbI=`v-{gP@pfTMbVc&)y<{fTI7sIii!s4 z47j;3Yi};@y)NHc^hQU^8h+1SK0d$utfu`7HHLphG~U9czBDw=*Bs5)eIw8vo$rQ| z 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 E53$T&p8x;= literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/build_env.py b/venv/Lib/site-packages/pip/_internal/build_env.py new file mode 100644 index 0000000..daeb7fb --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/build_env.py @@ -0,0 +1,296 @@ +"""Build Environment used for isolation during sdist building +""" + +import contextlib +import logging +import os +import pathlib +import sys +import textwrap +import zipfile +from collections import OrderedDict +from sysconfig import get_paths +from types import TracebackType +from typing import TYPE_CHECKING, Iterable, Iterator, List, Optional, Set, Tuple, Type + +from pip._vendor.certifi import where +from pip._vendor.packaging.requirements import Requirement +from pip._vendor.packaging.version import Version + +from pip import __file__ as pip_location +from pip._internal.cli.spinners import open_spinner +from pip._internal.locations import get_platlib, get_prefixed_libs, get_purelib +from pip._internal.metadata import get_environment +from pip._internal.utils.subprocess import call_subprocess +from pip._internal.utils.temp_dir import TempDirectory, tempdir_kinds + +if TYPE_CHECKING: + from pip._internal.index.package_finder import PackageFinder + +logger = logging.getLogger(__name__) + + +class _Prefix: + def __init__(self, path: str) -> None: + self.path = path + self.setup = False + self.bin_dir = get_paths( + "nt" if os.name == "nt" else "posix_prefix", + vars={"base": path, "platbase": path}, + )["scripts"] + self.lib_dirs = get_prefixed_libs(path) + + +@contextlib.contextmanager +def _create_standalone_pip() -> Iterator[str]: + """Create a "standalone pip" zip file. + + The zip file's content is identical to the currently-running pip. + It will be used to install requirements into the build environment. + """ + source = pathlib.Path(pip_location).resolve().parent + + # Return the current instance if `source` is not a directory. We can't build + # a zip from this, and it likely means the instance is already standalone. + if not source.is_dir(): + yield str(source) + return + + with TempDirectory(kind="standalone-pip") as tmp_dir: + pip_zip = os.path.join(tmp_dir.path, "__env_pip__.zip") + kwargs = {} + if sys.version_info >= (3, 8): + kwargs["strict_timestamps"] = False + with zipfile.ZipFile(pip_zip, "w", **kwargs) as zf: + for child in source.rglob("*"): + zf.write(child, child.relative_to(source.parent).as_posix()) + yield os.path.join(pip_zip, "pip") + + +class BuildEnvironment: + """Creates and manages an isolated environment to install build deps""" + + def __init__(self) -> None: + temp_dir = TempDirectory(kind=tempdir_kinds.BUILD_ENV, globally_managed=True) + + self._prefixes = OrderedDict( + (name, _Prefix(os.path.join(temp_dir.path, name))) + for name in ("normal", "overlay") + ) + + self._bin_dirs: List[str] = [] + self._lib_dirs: List[str] = [] + for prefix in reversed(list(self._prefixes.values())): + self._bin_dirs.append(prefix.bin_dir) + self._lib_dirs.extend(prefix.lib_dirs) + + # Customize site to: + # - ensure .pth files are honored + # - prevent access to system site packages + system_sites = { + os.path.normcase(site) for site in (get_purelib(), get_platlib()) + } + self._site_dir = os.path.join(temp_dir.path, "site") + if not os.path.exists(self._site_dir): + os.mkdir(self._site_dir) + with open( + os.path.join(self._site_dir, "sitecustomize.py"), "w", encoding="utf-8" + ) as fp: + fp.write( + textwrap.dedent( + """ + import os, site, sys + + # First, drop system-sites related paths. + original_sys_path = sys.path[:] + known_paths = set() + for path in {system_sites!r}: + site.addsitedir(path, known_paths=known_paths) + system_paths = set( + os.path.normcase(path) + for path in sys.path[len(original_sys_path):] + ) + original_sys_path = [ + path for path in original_sys_path + if os.path.normcase(path) not in system_paths + ] + sys.path = original_sys_path + + # Second, add lib directories. + # ensuring .pth file are processed. + for path in {lib_dirs!r}: + assert not path in sys.path + site.addsitedir(path) + """ + ).format(system_sites=system_sites, lib_dirs=self._lib_dirs) + ) + + def __enter__(self) -> None: + self._save_env = { + name: os.environ.get(name, None) + for name in ("PATH", "PYTHONNOUSERSITE", "PYTHONPATH") + } + + path = self._bin_dirs[:] + old_path = self._save_env["PATH"] + if old_path: + path.extend(old_path.split(os.pathsep)) + + pythonpath = [self._site_dir] + + os.environ.update( + { + "PATH": os.pathsep.join(path), + "PYTHONNOUSERSITE": "1", + "PYTHONPATH": os.pathsep.join(pythonpath), + } + ) + + def __exit__( + self, + exc_type: Optional[Type[BaseException]], + exc_val: Optional[BaseException], + exc_tb: Optional[TracebackType], + ) -> None: + for varname, old_value in self._save_env.items(): + if old_value is None: + os.environ.pop(varname, None) + else: + os.environ[varname] = old_value + + def check_requirements( + self, reqs: Iterable[str] + ) -> Tuple[Set[Tuple[str, str]], Set[str]]: + """Return 2 sets: + - conflicting requirements: set of (installed, wanted) reqs tuples + - missing requirements: set of reqs + """ + missing = set() + conflicting = set() + if reqs: + env = get_environment(self._lib_dirs) + for req_str in reqs: + req = Requirement(req_str) + dist = env.get_distribution(req.name) + if not dist: + missing.add(req_str) + continue + if isinstance(dist.version, Version): + installed_req_str = f"{req.name}=={dist.version}" + else: + installed_req_str = f"{req.name}==={dist.version}" + if dist.version not in req.specifier: + conflicting.add((installed_req_str, req_str)) + # FIXME: Consider direct URL? + return conflicting, missing + + def install_requirements( + self, + finder: "PackageFinder", + requirements: Iterable[str], + prefix_as_string: str, + *, + kind: str, + ) -> None: + prefix = self._prefixes[prefix_as_string] + assert not prefix.setup + prefix.setup = True + if not requirements: + return + with contextlib.ExitStack() as ctx: + pip_runnable = ctx.enter_context(_create_standalone_pip()) + self._install_requirements( + pip_runnable, + finder, + requirements, + prefix, + kind=kind, + ) + + @staticmethod + def _install_requirements( + pip_runnable: str, + finder: "PackageFinder", + requirements: Iterable[str], + prefix: _Prefix, + *, + kind: str, + ) -> None: + args: List[str] = [ + sys.executable, + pip_runnable, + "install", + "--ignore-installed", + "--no-user", + "--prefix", + prefix.path, + "--no-warn-script-location", + ] + if logger.getEffectiveLevel() <= logging.DEBUG: + args.append("-v") + for format_control in ("no_binary", "only_binary"): + formats = getattr(finder.format_control, format_control) + args.extend( + ( + "--" + format_control.replace("_", "-"), + ",".join(sorted(formats or {":none:"})), + ) + ) + + index_urls = finder.index_urls + if index_urls: + args.extend(["-i", index_urls[0]]) + for extra_index in index_urls[1:]: + args.extend(["--extra-index-url", extra_index]) + else: + args.append("--no-index") + for link in finder.find_links: + args.extend(["--find-links", link]) + + for host in finder.trusted_hosts: + args.extend(["--trusted-host", host]) + if finder.allow_all_prereleases: + args.append("--pre") + if finder.prefer_binary: + args.append("--prefer-binary") + args.append("--") + args.extend(requirements) + extra_environ = {"_PIP_STANDALONE_CERT": where()} + with open_spinner(f"Installing {kind}") as spinner: + call_subprocess( + args, + command_desc=f"pip subprocess to install {kind}", + spinner=spinner, + extra_environ=extra_environ, + ) + + +class NoOpBuildEnvironment(BuildEnvironment): + """A no-op drop-in replacement for BuildEnvironment""" + + def __init__(self) -> None: + pass + + def __enter__(self) -> None: + pass + + def __exit__( + self, + exc_type: Optional[Type[BaseException]], + exc_val: Optional[BaseException], + exc_tb: Optional[TracebackType], + ) -> None: + pass + + def cleanup(self) -> None: + pass + + def install_requirements( + self, + finder: "PackageFinder", + requirements: Iterable[str], + prefix_as_string: str, + *, + kind: str, + ) -> None: + raise NotImplementedError() diff --git a/venv/Lib/site-packages/pip/_internal/cache.py b/venv/Lib/site-packages/pip/_internal/cache.py new file mode 100644 index 0000000..1d6df22 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/cache.py @@ -0,0 +1,264 @@ +"""Cache Management +""" + +import hashlib +import json +import logging +import os +from typing import Any, Dict, List, Optional, Set + +from pip._vendor.packaging.tags import Tag, interpreter_name, interpreter_version +from pip._vendor.packaging.utils import canonicalize_name + +from pip._internal.exceptions import InvalidWheelFilename +from pip._internal.models.format_control import FormatControl +from pip._internal.models.link import Link +from pip._internal.models.wheel import Wheel +from pip._internal.utils.temp_dir import TempDirectory, tempdir_kinds +from pip._internal.utils.urls import path_to_url + +logger = logging.getLogger(__name__) + + +def _hash_dict(d: Dict[str, str]) -> str: + """Return a stable sha224 of a dictionary.""" + s = json.dumps(d, sort_keys=True, separators=(",", ":"), ensure_ascii=True) + return hashlib.sha224(s.encode("ascii")).hexdigest() + + +class Cache: + """An abstract class - provides cache directories for data from links + + + :param cache_dir: The root of the cache. + :param format_control: An object of FormatControl class to limit + binaries being read from the cache. + :param allowed_formats: which formats of files the cache should store. + ('binary' and 'source' are the only allowed values) + """ + + def __init__( + self, cache_dir: str, format_control: FormatControl, allowed_formats: Set[str] + ) -> None: + super().__init__() + assert not cache_dir or os.path.isabs(cache_dir) + self.cache_dir = cache_dir or None + self.format_control = format_control + self.allowed_formats = allowed_formats + + _valid_formats = {"source", "binary"} + assert self.allowed_formats.union(_valid_formats) == _valid_formats + + def _get_cache_path_parts(self, link: Link) -> List[str]: + """Get parts of part that must be os.path.joined with cache_dir""" + + # We want to generate an url to use as our cache key, we don't want to + # just re-use the URL because it might have other items in the fragment + # and we don't care about those. + key_parts = {"url": link.url_without_fragment} + if link.hash_name is not None and link.hash is not None: + key_parts[link.hash_name] = link.hash + if link.subdirectory_fragment: + key_parts["subdirectory"] = link.subdirectory_fragment + + # Include interpreter name, major and minor version in cache key + # to cope with ill-behaved sdists that build a different wheel + # depending on the python version their setup.py is being run on, + # and don't encode the difference in compatibility tags. + # https://github.com/pypa/pip/issues/7296 + key_parts["interpreter_name"] = interpreter_name() + key_parts["interpreter_version"] = interpreter_version() + + # Encode our key url with sha224, we'll use this because it has similar + # security properties to sha256, but with a shorter total output (and + # thus less secure). However the differences don't make a lot of + # difference for our use case here. + hashed = _hash_dict(key_parts) + + # We want to nest the directories some to prevent having a ton of top + # level directories where we might run out of sub directories on some + # FS. + parts = [hashed[:2], hashed[2:4], hashed[4:6], hashed[6:]] + + return parts + + def _get_candidates(self, link: Link, canonical_package_name: str) -> List[Any]: + can_not_cache = not self.cache_dir or not canonical_package_name or not link + if can_not_cache: + return [] + + formats = self.format_control.get_allowed_formats(canonical_package_name) + if not self.allowed_formats.intersection(formats): + return [] + + candidates = [] + path = self.get_path_for_link(link) + if os.path.isdir(path): + for candidate in os.listdir(path): + candidates.append((candidate, path)) + return candidates + + def get_path_for_link(self, link: Link) -> str: + """Return a directory to store cached items in for link.""" + raise NotImplementedError() + + def get( + self, + link: Link, + package_name: Optional[str], + supported_tags: List[Tag], + ) -> Link: + """Returns a link to a cached item if it exists, otherwise returns the + passed link. + """ + raise NotImplementedError() + + +class SimpleWheelCache(Cache): + """A cache of wheels for future installs.""" + + def __init__(self, cache_dir: str, format_control: FormatControl) -> None: + super().__init__(cache_dir, format_control, {"binary"}) + + def get_path_for_link(self, link: Link) -> str: + """Return a directory to store cached wheels for link + + Because there are M wheels for any one sdist, we provide a directory + to cache them in, and then consult that directory when looking up + cache hits. + + We only insert things into the cache if they have plausible version + numbers, so that we don't contaminate the cache with things that were + not unique. E.g. ./package might have dozens of installs done for it + and build a version of 0.0...and if we built and cached a wheel, we'd + end up using the same wheel even if the source has been edited. + + :param link: The link of the sdist for which this will cache wheels. + """ + parts = self._get_cache_path_parts(link) + assert self.cache_dir + # Store wheels within the root cache_dir + return os.path.join(self.cache_dir, "wheels", *parts) + + def get( + self, + link: Link, + package_name: Optional[str], + supported_tags: List[Tag], + ) -> Link: + candidates = [] + + if not package_name: + return link + + canonical_package_name = canonicalize_name(package_name) + for wheel_name, wheel_dir in self._get_candidates(link, canonical_package_name): + try: + wheel = Wheel(wheel_name) + except InvalidWheelFilename: + continue + if canonicalize_name(wheel.name) != canonical_package_name: + logger.debug( + "Ignoring cached wheel %s for %s as it " + "does not match the expected distribution name %s.", + wheel_name, + link, + package_name, + ) + continue + if not wheel.supported(supported_tags): + # Built for a different python/arch/etc + continue + candidates.append( + ( + wheel.support_index_min(supported_tags), + wheel_name, + wheel_dir, + ) + ) + + if not candidates: + return link + + _, wheel_name, wheel_dir = min(candidates) + return Link(path_to_url(os.path.join(wheel_dir, wheel_name))) + + +class EphemWheelCache(SimpleWheelCache): + """A SimpleWheelCache that creates it's own temporary cache directory""" + + def __init__(self, format_control: FormatControl) -> None: + self._temp_dir = TempDirectory( + kind=tempdir_kinds.EPHEM_WHEEL_CACHE, + globally_managed=True, + ) + + super().__init__(self._temp_dir.path, format_control) + + +class CacheEntry: + def __init__( + self, + link: Link, + persistent: bool, + ): + self.link = link + self.persistent = persistent + + +class WheelCache(Cache): + """Wraps EphemWheelCache and SimpleWheelCache into a single Cache + + This Cache allows for gracefully degradation, using the ephem wheel cache + when a certain link is not found in the simple wheel cache first. + """ + + def __init__(self, cache_dir: str, format_control: FormatControl) -> None: + super().__init__(cache_dir, format_control, {"binary"}) + self._wheel_cache = SimpleWheelCache(cache_dir, format_control) + self._ephem_cache = EphemWheelCache(format_control) + + def get_path_for_link(self, link: Link) -> str: + return self._wheel_cache.get_path_for_link(link) + + def get_ephem_path_for_link(self, link: Link) -> str: + return self._ephem_cache.get_path_for_link(link) + + def get( + self, + link: Link, + package_name: Optional[str], + supported_tags: List[Tag], + ) -> Link: + cache_entry = self.get_cache_entry(link, package_name, supported_tags) + if cache_entry is None: + return link + return cache_entry.link + + def get_cache_entry( + self, + link: Link, + package_name: Optional[str], + supported_tags: List[Tag], + ) -> Optional[CacheEntry]: + """Returns a CacheEntry with a link to a cached item if it exists or + None. The cache entry indicates if the item was found in the persistent + or ephemeral cache. + """ + retval = self._wheel_cache.get( + link=link, + package_name=package_name, + supported_tags=supported_tags, + ) + if retval is not link: + return CacheEntry(retval, persistent=True) + + retval = self._ephem_cache.get( + link=link, + package_name=package_name, + supported_tags=supported_tags, + ) + if retval is not link: + return CacheEntry(retval, persistent=False) + + return None diff --git a/venv/Lib/site-packages/pip/_internal/cli/__init__.py b/venv/Lib/site-packages/pip/_internal/cli/__init__.py new file mode 100644 index 0000000..e589bb9 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/cli/__init__.py @@ -0,0 +1,4 @@ +"""Subpackage containing all of pip's command line interface related code +""" + +# This file intentionally does not import submodules diff --git a/venv/Lib/site-packages/pip/_internal/cli/__pycache__/__init__.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/cli/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..da146723680601dba028ac0909db5ece1789ea34 GIT binary patch literal 265 zcmYjMv1$TA5Z$wh2!4ZGDHfMff=EbEunB2Qnz*oxyQA5-H@n>K5n`P-ACh0P%_rDd zWzNch_l7rb;LSk4-xFLvgW=|z`(G=rt6=fKNL?l?-h?eyV%#|_SIs7Z*~1Q{36#N+ zqn!lrW!TE-;wbUFs(`HYj!-(vSZ~3gtkFY8%eKYd^SC(PXl;Yh`d8E)PPx!|J)f%A zgmqFt1W7%{xPT1mDH!nT1*@nyrEI9Z0&V&Ej_AwD-G@si9a>N6OD6HU@lI)$E^B=o RzmDBm6>Q`2zJ2e+5dW_CPXPb` literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/cli/__pycache__/autocompletion.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/cli/__pycache__/autocompletion.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..426e1747a1f0eddcbd6cba0c2cb801cc4f925104 GIT binary patch literal 5248 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 YYX)qmzY?1O2Z3MovR`KASEY&n0y=Rx4*&oF literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/cli/__pycache__/base_command.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/cli/__pycache__/base_command.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7de135641786aeee57284915769f706083b87800 GIT binary patch literal 6367 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 K03Hi=X#XGba;%2{ literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/cli/__pycache__/cmdoptions.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/cli/__pycache__/cmdoptions.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2943eab1624d7a5ad7c806fa04c6a432326d6d7f GIT binary patch literal 22691 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 SUVdLpyt46zW}WXOUirW7z&aoR literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/cli/__pycache__/command_context.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/cli/__pycache__/command_context.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..865e9e500b8ed84f3ca200438f7f09b5f0ff24d8 GIT binary patch literal 1280 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 KctL8GUH%7bJ5^o) literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/cli/__pycache__/parser.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/cli/__pycache__/parser.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d064cba50ac3a86acd64068d3dd8ef0b5e5e8087 GIT binary patch literal 9936 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 JcFmfa`ERf%0?hyb literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/cli/__pycache__/progress_bars.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/cli/__pycache__/progress_bars.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..32fa35335fc4a1656992d8900e98b60479e4c6f9 GIT binary patch literal 9225 zcmbVRO^h2ycJ5!Yhw~$9G#brFvfP&SM_Z!)Z24zpuVhJ6rit=yN7=J7@E}+CrQfWl&V|Uk(mAhg9XJ63!b6Kiv6uRiPhK zokO>jP&=h?i%;+)i^__c{WrBm#W~8S>BlA?>1>KkKQNqQ{21TCr~8^y;YI!mn>nvs zRoD(zexR^2u&<)Elg*+vi(a~O9PM3f4(&O<1ML%N?`HF8&!cx0tvzf3tp&7BqP58O zqP3TwnOZ=@xg&$?dz?lkr1)O<1;~U<+mDSj*j|_I4oxr>AFqKswsbk-r#CNCI=?4Yp zJX4pH%9$@o{%RFHEi7HTdaZUN-Nks*ZTm^x3zPb)8#14Zv=DnMq3c)7RKFN@QtOiI z`|h&OQ|ns7g_}eowLWYmUW87md86I(Ifm5Vb49xIeb4v3aOILG8a|H+HFGU&2p;e- zaecHaYFb=sd11&!rIbzpb1CxML72{5j_!qiuaWKiFE!wdKo-)+S_A9oj_uJge4LLxMqeAf-(hH;aNr54Y75~Vk<)h>T{ za|zWQE1bB*XdSe4peCD<2;8I|gGe;3M&w7r4O}o|q9r&+6P%@16YN`d8+X!z;7MDA z4XFF@F;F8za0w;83y>&1WlhCaDt&!j>uK?P4_ilArZK&*%bG#86>VMb>4_#W<_h}v z)i;!Ny*tPB$9VHZeQfl!Cu**ciP`Zph3u&X<(9IfoWiI}FeVUr>_A*scL;e?9t8UEWN+B(R6K;|S`GTj0@5M=KtVLd!7UU2-o&7lUFc!Z;Bl0Uk zM51Dd{aBuOfxwFZX{oX53bz4~ik~XtRiM85^wQh6KaPR8?S`Qn-@e#tU3L@q_HRTD z*S~!OWZiCgtrP9A1%7gN;@&Ff{)uyMu6c1I?$W#4B*|PrGH*A0?{;e-GxcRx#MM?O zov+8-=Z&O3eADpVI6j2g;{^akoiPm6FiUFb8^f40HFZv%QcIdRfp@7@e-BK6%r>a& z_(S_hPkb4GD`dW5x>ZN#1~+Ku9_gPeO_dqUd@$vhz!V;-5>sRrFa{qIlGUi4 z*gkjfLQd=i8v=g7-@C)@RgXba>_%I}k%%i8Xcf9MKAmK{jd^1)@O)RU zBw6KlzAv`#Ez{6PW1HWHgwcFU-U?VE86oFdl{`3ZFM}pGwxgzf7qSE8v`<&h9M3qC z^|2wmXmh(6(K2Z;Oa!h5@!J^>PFL+~iDVW?>cmw{njEWC z@ulsw8&Lprm~g+7eR@`YN(|$%?O{8>-eG4iv|GO0;5NStX1Pu5w(W*?8-{7H@nCwk zo5v*~*!O#@USkzI;rkfoE=Om6zXgFtPsV+>gMZ#^0)gq8a>;Edl${7~Wd+Q^`1wff zP~ZdlaI0Y0aTGwLU@3F5h8uGNd;rxQ@Gu`Kml?@r*B9JnogpXKaWGwA6J6p=#+BMr zJvCgh5~qbb_vl|7fZ8-v(xAbkS#73RQoH*g^P9{-HK*mNx|MUpMVgmNycd8t_gH-bPi(|7^2%UjwC*p5 z{JG9!9PQ6%Q6{6ANJ0Px3Qe4nHYA35@EI7|YC)g{UxB{B4Unn{TMgzz633N%AWH)w z=kbu3kd9X0?;OW&Wp->#C&u^36lbx-w2;v>+8c2WXt3u^{E4>+jQD&WO^y;vt4%y! z+=j>5hz(+6{!pF1xr8E*i=OgWA;#h#qKVU18#4AUhif7KX_IAM<`6bc8Vept+Xid< z9NFB==-k{47#@XwCo|Rqg90nzXFEBxr#Y*=5tDKFdUppZnMu1Qh&PgV6qUOL;fp4P28!=!U%yjBKzs;`%(VB-9e>Hvh7z|+p>#wlGhrd$oir%JW z{@0)W{BQEgU+0y-g6Z5uI7F%4Y85@Zx0*w(Y_`z>6QDWP7Q>LBmfF zcFXdl98y;XkS~wx96N~p%$zXV(<#T`CND4(dt6|}2S#6YibIUWCM3ohVoGdMVkTsa zsyHR-s7-=RGwJR;boprDZb}!WCQcE7#P9skQ6U25p+;M_^-yDKqV?hH?@{I`643Vm z)^+Kl>oxH`eDftq3Z#PUUZxj|sHMdKhStRy{|4bVSv*poFHkZy)n?W1fo*9X9xU5S zH_d#BhM~*`#T{#EAIFGzAI*v;=&(sm3X<-N?Zmy5I|`gVq)})%MeEwzlQQbOfrrFT z;-jR)Mg>&hFuS9P8Kx~M2~?Ia`;Gy}vrHvc{*m&>SO6`eqSv|x zqAXjygg!(j8i=kEx1O+VDJ?;r62xri@(X;DQK=OWyF81%qYpL&q{LdXxD6WR6@Z?4 zS@~pvLeU>&2OU`4)A}j}mY*3o_%u2INkB6(fVTseG)Z+BN@=n4gGBR^RJ}i@-=qMk z;la826PipqJ*uS^^s?IByFF{Eb7g9iT^XGasfFVXHY(|)dYlMx9pj3R3H%m;PY7Hl zFfyE@1EYo)pQFTO085=m>{r%N3Mi(ax5SeT&(PQ$0s8sIMw$yVv#K|tB8avAPgdeK zMott_{sICb%1r%2sY?s7rf+bCvBJcl^4LVr!V~IOkntsA&j%La>WD361e&)kX;sYH z`&-sUBDxDDo&vzPn47kFxW(cy@M-a$AV-g-1usTIpp$WRr1)}wt@FMcEHn4rU*ePh zMp3#)$Jal!IMwq$Mfvf&sAOOK|Hu+9(PlRNcD%YBMKX5(Tl5ihLR2OMh5hLyB353{ z;?*(Bx=+5l7{=a>2vnavBUdh#>2pqCWNhWSY01(i{{<@X41i*lAknjig~USH=k*T|Yvca|C`kH}rUd1`DIYp*JDvfjxr8YKe9gcl* z4WD;U9X!w3Mkb{a*DBVgH9;ji2>9ZJA%~Fh@goc^zE5DJkg_KE zxQZ9QLXpPIf-%FHPq=3C2oZGAnQRpTTw?gR}x(6}7(= z2|M$-hpt^s_!wl{*#f-y2b6p^YJaQQCiB^(llshgLX7)QWAjk^Tg|hW&$A`v`<&H9 znB||xW~KJGnst9Z>(DdJeXi#(w}pxRWo%+P zdOm7Nol(07pRvyB=#$z8$A?^sB8prKou%aX^ptsJ9V?*Z1RM-y4Fwpu>d0Rso))h# zE!5x~X+2$>8`Sj`^NG4nj)&1R$O*}PV{(TN&;vSiOZ}Xd0j_Uu(ZMN?X0@!M^7)TuEHO7-KP< zN6j??bd+XP)~P0mzDl(bAtP!&!;61K$pRq*CQ+L)1!3v7CTccQEecc9jT@eq7BYLB znw%my+)7NrJCau@lnzhzz`dVkkI1m)57mc4M||obmEDF@gnx3fZ4$yoc&Upr9|wm! zYpaXYQ-7$gK@8=V7&Sqsk5~ezsN#3%Ps5GR#q0GOw?4YEB;7GY4HVePw___N`=8F$ zDLc~WjB@oL+r*dyAH1xVHSuE_)<`W9@a&Qbo$5)ag_{YwnAw;gqt%h0Nu_}j|06)Q zvbg*`tg5g67~&Sco8X4EudeF|C!kn~25m=__z)S#zLFRyW?yNV>qdB}hijNYuLAJJ z!F!ci_|8JF!n%=6^bAVyd&pa^n>}+4(PT1-FmFnRc{-bZsI3=z=1g(8h0X4<-_FIP%6Qxmp1kV&q(LBaDs z-^C4>DWfFu1GJr4g!j0uTdl(#$DKXhfOJfYWgFkepH>vnfp`ok+L>Bn@0h;EpFS zm5^KQA)Ghhb>I&rs3$OtJsc6xL7Bqo{^%;l9zPNfsq}QR^b3$#O8F4b|hN_7q8Q{P!3nuBP6GZ}KDZ~Uox`6A&Y8^K< zEE3hBion_knodj-n4*sRx9u2bm)>F;U7W@7E+ksR0mtN93O>oVm?a>UL8^t+11bHa z7U^C&n9PskR-@WZJU_0|MHJLX1~>b*>)=N#xU^W28Z%hirXd1ccx5@A$uV+;jEN?$ z+;4Dc7*cb&lknJC*z6KqmtuvRixWgWX-c}IUdP2Qbe?X|V3J|Ivd@F{^+ z0(S_I11v%U5rGx~I`G8r5}-4a%vK@~f=qsByT_zvczUMR`7GD`E@UK25YlmO;fi;^ zM%TQjrl$a>aJZLsy7ZmbXZOwOGjEp7vNdDRyf9asHS!<6{IzkQ0F9QvuL~th)xMdU TF5qiTEqpz77>)tP*1q{)FyWw? literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/cli/__pycache__/req_command.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/cli/__pycache__/req_command.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..686bf700b5e9eb51af5ca10c1e2b6b064e6a6241 GIT binary patch literal 13434 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 b#-N=3cV&UzGSyE`9b*0bV?9?nTs`=|#+|X- literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/cli/__pycache__/spinners.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/cli/__pycache__/spinners.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3d9999348313c35685c85b8dace8942b2fd84a19 GIT binary patch literal 4935 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/cli/__pycache__/status_codes.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/cli/__pycache__/status_codes.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..77b9909dfcb2645f0b52ef82c02cf2b72c75e47f GIT binary patch literal 344 zcmYk2&q~BF5XSp=SA>EGK@WmAVGs2vA|lqdi^ZBs+f*ol5SxJ2ZZ|Y7qVM2?_)5Kc z>MM9MaTT0le#6InA?w zk{mA+2!e6{E)9z)ff>GnQ5@hPN`L)3Ai=j@?q7%5#`~dlj{NEeU)VoGP_RxQ(zZk( zkMn@^1jXx$G$>~)j(E-8q2;7{X4HLoWUO&dPM>N~i8nPvxNdvawbEWSH4;7P2Z5_K YW#X8>j$7xeH60pup;i{^jF$eF-% None: + """Entry Point for completion of main and subcommand options.""" + # Don't complete if user hasn't sourced bash_completion file. + if "PIP_AUTO_COMPLETE" not in os.environ: + return + cwords = os.environ["COMP_WORDS"].split()[1:] + cword = int(os.environ["COMP_CWORD"]) + try: + current = cwords[cword - 1] + except IndexError: + current = "" + + parser = create_main_parser() + subcommands = list(commands_dict) + options = [] + + # subcommand + subcommand_name: Optional[str] = None + for word in cwords: + if word in subcommands: + subcommand_name = word + break + # subcommand options + if subcommand_name is not None: + # special case: 'help' subcommand has no options + if subcommand_name == "help": + sys.exit(1) + # special case: list locally installed dists for show and uninstall + should_list_installed = not current.startswith("-") and subcommand_name in [ + "show", + "uninstall", + ] + if should_list_installed: + env = get_default_environment() + lc = current.lower() + installed = [ + dist.canonical_name + for dist in env.iter_installed_distributions(local_only=True) + if dist.canonical_name.startswith(lc) + and dist.canonical_name not in cwords[1:] + ] + # if there are no dists installed, fall back to option completion + if installed: + for dist in installed: + print(dist) + sys.exit(1) + + should_list_installables = ( + not current.startswith("-") and subcommand_name == "install" + ) + if should_list_installables: + for path in auto_complete_paths(current, "path"): + print(path) + sys.exit(1) + + subcommand = create_command(subcommand_name) + + for opt in subcommand.parser.option_list_all: + if opt.help != optparse.SUPPRESS_HELP: + for opt_str in opt._long_opts + opt._short_opts: + options.append((opt_str, opt.nargs)) + + # filter out previously specified options from available options + prev_opts = [x.split("=")[0] for x in cwords[1 : cword - 1]] + options = [(x, v) for (x, v) in options if x not in prev_opts] + # filter options by current input + options = [(k, v) for k, v in options if k.startswith(current)] + # get completion type given cwords and available subcommand options + completion_type = get_path_completion_type( + cwords, + cword, + subcommand.parser.option_list_all, + ) + # get completion files and directories if ``completion_type`` is + # ````, ``

`` or ```` + if completion_type: + paths = auto_complete_paths(current, completion_type) + options = [(path, 0) for path in paths] + for option in options: + opt_label = option[0] + # append '=' to options which require args + if option[1] and option[0][:2] == "--": + opt_label += "=" + print(opt_label) + else: + # show main parser options only when necessary + + opts = [i.option_list for i in parser.option_groups] + opts.append(parser.option_list) + flattened_opts = chain.from_iterable(opts) + if current.startswith("-"): + for opt in flattened_opts: + if opt.help != optparse.SUPPRESS_HELP: + subcommands += opt._long_opts + opt._short_opts + else: + # get completion type given cwords and all available options + completion_type = get_path_completion_type(cwords, cword, flattened_opts) + if completion_type: + subcommands = list(auto_complete_paths(current, completion_type)) + + print(" ".join([x for x in subcommands if x.startswith(current)])) + sys.exit(1) + + +def get_path_completion_type( + cwords: List[str], cword: int, opts: Iterable[Any] +) -> Optional[str]: + """Get the type of path completion (``file``, ``dir``, ``path`` or None) + + :param cwords: same as the environmental variable ``COMP_WORDS`` + :param cword: same as the environmental variable ``COMP_CWORD`` + :param opts: The available options to check + :return: path completion type (``file``, ``dir``, ``path`` or None) + """ + if cword < 2 or not cwords[cword - 2].startswith("-"): + return None + for opt in opts: + if opt.help == optparse.SUPPRESS_HELP: + continue + for o in str(opt).split("/"): + if cwords[cword - 2].split("=")[0] == o: + if not opt.metavar or any( + x in ("path", "file", "dir") for x in opt.metavar.split("/") + ): + return opt.metavar + return None + + +def auto_complete_paths(current: str, completion_type: str) -> Iterable[str]: + """If ``completion_type`` is ``file`` or ``path``, list all regular files + and directories starting with ``current``; otherwise only list directories + starting with ``current``. + + :param current: The word to be completed + :param completion_type: path completion type(``file``, ``path`` or ``dir``) + :return: A generator of regular files and/or directories + """ + directory, filename = os.path.split(current) + current_path = os.path.abspath(directory) + # Don't complete paths if they can't be accessed + if not os.access(current_path, os.R_OK): + return + filename = os.path.normcase(filename) + # list all files that start with ``filename`` + file_list = ( + x for x in os.listdir(current_path) if os.path.normcase(x).startswith(filename) + ) + for f in file_list: + opt = os.path.join(current_path, f) + comp_file = os.path.normcase(os.path.join(directory, f)) + # complete regular files when there is not ```` after option + # complete directories when there is ````, ```` or + # ````after option + if completion_type != "dir" and os.path.isfile(opt): + yield comp_file + elif os.path.isdir(opt): + yield os.path.join(comp_file, "") diff --git a/venv/Lib/site-packages/pip/_internal/cli/base_command.py b/venv/Lib/site-packages/pip/_internal/cli/base_command.py new file mode 100644 index 0000000..78b96bb --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/cli/base_command.py @@ -0,0 +1,223 @@ +"""Base Command class, and related routines""" + +import functools +import logging +import logging.config +import optparse +import os +import sys +import traceback +from optparse import Values +from typing import Any, Callable, List, Optional, Tuple + +from pip._vendor.rich import traceback as rich_traceback + +from pip._internal.cli import cmdoptions +from pip._internal.cli.command_context import CommandContextMixIn +from pip._internal.cli.parser import ConfigOptionParser, UpdatingDefaultsHelpFormatter +from pip._internal.cli.status_codes import ( + ERROR, + PREVIOUS_BUILD_DIR_ERROR, + UNKNOWN_ERROR, + VIRTUALENV_NOT_FOUND, +) +from pip._internal.exceptions import ( + BadCommand, + CommandError, + DiagnosticPipError, + InstallationError, + NetworkConnectionError, + PreviousBuildDirError, + UninstallationError, +) +from pip._internal.utils.filesystem import check_path_owner +from pip._internal.utils.logging import BrokenStdoutLoggingError, setup_logging +from pip._internal.utils.misc import get_prog, normalize_path +from pip._internal.utils.temp_dir import TempDirectoryTypeRegistry as TempDirRegistry +from pip._internal.utils.temp_dir import global_tempdir_manager, tempdir_registry +from pip._internal.utils.virtualenv import running_under_virtualenv + +__all__ = ["Command"] + +logger = logging.getLogger(__name__) + + +class Command(CommandContextMixIn): + usage: str = "" + ignore_require_venv: bool = False + + def __init__(self, name: str, summary: str, isolated: bool = False) -> None: + super().__init__() + + self.name = name + self.summary = summary + self.parser = ConfigOptionParser( + usage=self.usage, + prog=f"{get_prog()} {name}", + formatter=UpdatingDefaultsHelpFormatter(), + add_help_option=False, + name=name, + description=self.__doc__, + isolated=isolated, + ) + + self.tempdir_registry: Optional[TempDirRegistry] = None + + # Commands should add options to this option group + optgroup_name = f"{self.name.capitalize()} Options" + self.cmd_opts = optparse.OptionGroup(self.parser, optgroup_name) + + # Add the general options + gen_opts = cmdoptions.make_option_group( + cmdoptions.general_group, + self.parser, + ) + self.parser.add_option_group(gen_opts) + + self.add_options() + + def add_options(self) -> None: + pass + + def handle_pip_version_check(self, options: Values) -> None: + """ + This is a no-op so that commands by default do not do the pip version + check. + """ + # Make sure we do the pip version check if the index_group options + # are present. + assert not hasattr(options, "no_index") + + def run(self, options: Values, args: List[str]) -> int: + raise NotImplementedError + + def parse_args(self, args: List[str]) -> Tuple[Values, List[str]]: + # factored out for testability + return self.parser.parse_args(args) + + def main(self, args: List[str]) -> int: + try: + with self.main_context(): + return self._main(args) + finally: + logging.shutdown() + + def _main(self, args: List[str]) -> int: + # We must initialize this before the tempdir manager, otherwise the + # configuration would not be accessible by the time we clean up the + # tempdir manager. + self.tempdir_registry = self.enter_context(tempdir_registry()) + # Intentionally set as early as possible so globally-managed temporary + # directories are available to the rest of the code. + self.enter_context(global_tempdir_manager()) + + options, args = self.parse_args(args) + + # Set verbosity so that it can be used elsewhere. + self.verbosity = options.verbose - options.quiet + + level_number = setup_logging( + verbosity=self.verbosity, + no_color=options.no_color, + user_log_file=options.log, + ) + + # TODO: Try to get these passing down from the command? + # without resorting to os.environ to hold these. + # This also affects isolated builds and it should. + + if options.no_input: + os.environ["PIP_NO_INPUT"] = "1" + + if options.exists_action: + os.environ["PIP_EXISTS_ACTION"] = " ".join(options.exists_action) + + if options.require_venv and not self.ignore_require_venv: + # If a venv is required check if it can really be found + if not running_under_virtualenv(): + logger.critical("Could not find an activated virtualenv (required).") + sys.exit(VIRTUALENV_NOT_FOUND) + + if options.cache_dir: + options.cache_dir = normalize_path(options.cache_dir) + if not check_path_owner(options.cache_dir): + logger.warning( + "The directory '%s' or its parent directory is not owned " + "or is not writable by the current user. The cache " + "has been disabled. Check the permissions and owner of " + "that directory. If executing pip with sudo, you should " + "use sudo's -H flag.", + options.cache_dir, + ) + options.cache_dir = None + + if "2020-resolver" in options.features_enabled: + logger.warning( + "--use-feature=2020-resolver no longer has any effect, " + "since it is now the default dependency resolver in pip. " + "This will become an error in pip 21.0." + ) + + def intercepts_unhandled_exc( + run_func: Callable[..., int] + ) -> Callable[..., int]: + @functools.wraps(run_func) + def exc_logging_wrapper(*args: Any) -> int: + try: + status = run_func(*args) + assert isinstance(status, int) + return status + except DiagnosticPipError as exc: + logger.error("[present-diagnostic] %s", exc) + logger.debug("Exception information:", exc_info=True) + + return ERROR + except PreviousBuildDirError as exc: + logger.critical(str(exc)) + logger.debug("Exception information:", exc_info=True) + + return PREVIOUS_BUILD_DIR_ERROR + except ( + InstallationError, + UninstallationError, + BadCommand, + NetworkConnectionError, + ) as exc: + logger.critical(str(exc)) + logger.debug("Exception information:", exc_info=True) + + return ERROR + except CommandError as exc: + logger.critical("%s", exc) + logger.debug("Exception information:", exc_info=True) + + return ERROR + except BrokenStdoutLoggingError: + # Bypass our logger and write any remaining messages to + # stderr because stdout no longer works. + print("ERROR: Pipe to stdout was broken", file=sys.stderr) + if level_number <= logging.DEBUG: + traceback.print_exc(file=sys.stderr) + + return ERROR + except KeyboardInterrupt: + logger.critical("Operation cancelled by user") + logger.debug("Exception information:", exc_info=True) + + return ERROR + except BaseException: + logger.critical("Exception:", exc_info=True) + + return UNKNOWN_ERROR + + return exc_logging_wrapper + + try: + if not options.debug_mode: + run = intercepts_unhandled_exc(self.run) + else: + run = self.run + rich_traceback.install(show_locals=True) + return run(options, args) + finally: + self.handle_pip_version_check(options) diff --git a/venv/Lib/site-packages/pip/_internal/cli/cmdoptions.py b/venv/Lib/site-packages/pip/_internal/cli/cmdoptions.py new file mode 100644 index 0000000..71b1d19 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/cli/cmdoptions.py @@ -0,0 +1,1018 @@ +""" +shared options and groups + +The principle here is to define options once, but *not* instantiate them +globally. One reason being that options with action='append' can carry state +between parses. pip parses general options twice internally, and shouldn't +pass on state. To be consistent, all options will follow this design. +""" + +# The following comment should be removed at some point in the future. +# mypy: strict-optional=False + +import logging +import os +import textwrap +from functools import partial +from optparse import SUPPRESS_HELP, Option, OptionGroup, OptionParser, Values +from textwrap import dedent +from typing import Any, Callable, Dict, Optional, Tuple + +from pip._vendor.packaging.utils import canonicalize_name + +from pip._internal.cli.parser import ConfigOptionParser +from pip._internal.cli.progress_bars import BAR_TYPES +from pip._internal.exceptions import CommandError +from pip._internal.locations import USER_CACHE_DIR, get_src_prefix +from pip._internal.models.format_control import FormatControl +from pip._internal.models.index import PyPI +from pip._internal.models.target_python import TargetPython +from pip._internal.utils.hashes import STRONG_HASHES +from pip._internal.utils.misc import strtobool + +logger = logging.getLogger(__name__) + + +def raise_option_error(parser: OptionParser, option: Option, msg: str) -> None: + """ + Raise an option parsing error using parser.error(). + + Args: + parser: an OptionParser instance. + option: an Option instance. + msg: the error text. + """ + msg = f"{option} error: {msg}" + msg = textwrap.fill(" ".join(msg.split())) + parser.error(msg) + + +def make_option_group(group: Dict[str, Any], parser: ConfigOptionParser) -> OptionGroup: + """ + Return an OptionGroup object + group -- assumed to be dict with 'name' and 'options' keys + parser -- an optparse Parser + """ + option_group = OptionGroup(parser, group["name"]) + for option in group["options"]: + option_group.add_option(option()) + return option_group + + +def check_install_build_global( + options: Values, check_options: Optional[Values] = None +) -> None: + """Disable wheels if per-setup.py call options are set. + + :param options: The OptionParser options to update. + :param check_options: The options to check, if not supplied defaults to + options. + """ + if check_options is None: + check_options = options + + def getname(n: str) -> Optional[Any]: + return getattr(check_options, n, None) + + names = ["build_options", "global_options", "install_options"] + if any(map(getname, names)): + control = options.format_control + control.disallow_binaries() + logger.warning( + "Disabling all use of wheels due to the use of --build-option " + "/ --global-option / --install-option.", + ) + + +def check_dist_restriction(options: Values, check_target: bool = False) -> None: + """Function for determining if custom platform options are allowed. + + :param options: The OptionParser options. + :param check_target: Whether or not to check if --target is being used. + """ + dist_restriction_set = any( + [ + options.python_version, + options.platforms, + options.abis, + options.implementation, + ] + ) + + binary_only = FormatControl(set(), {":all:"}) + sdist_dependencies_allowed = ( + options.format_control != binary_only and not options.ignore_dependencies + ) + + # Installations or downloads using dist restrictions must not combine + # source distributions and dist-specific wheels, as they are not + # guaranteed to be locally compatible. + if dist_restriction_set and sdist_dependencies_allowed: + raise CommandError( + "When restricting platform and interpreter constraints using " + "--python-version, --platform, --abi, or --implementation, " + "either --no-deps must be set, or --only-binary=:all: must be " + "set and --no-binary must not be set (or must be set to " + ":none:)." + ) + + if check_target: + if dist_restriction_set and not options.target_dir: + raise CommandError( + "Can not use any platform or abi specific options unless " + "installing via '--target'" + ) + + +def _path_option_check(option: Option, opt: str, value: str) -> str: + return os.path.expanduser(value) + + +def _package_name_option_check(option: Option, opt: str, value: str) -> str: + return canonicalize_name(value) + + +class PipOption(Option): + TYPES = Option.TYPES + ("path", "package_name") + TYPE_CHECKER = Option.TYPE_CHECKER.copy() + TYPE_CHECKER["package_name"] = _package_name_option_check + TYPE_CHECKER["path"] = _path_option_check + + +########### +# options # +########### + +help_: Callable[..., Option] = partial( + Option, + "-h", + "--help", + dest="help", + action="help", + help="Show help.", +) + +debug_mode: Callable[..., Option] = partial( + Option, + "--debug", + dest="debug_mode", + action="store_true", + default=False, + help=( + "Let unhandled exceptions propagate outside the main subroutine, " + "instead of logging them to stderr." + ), +) + +isolated_mode: Callable[..., Option] = partial( + Option, + "--isolated", + dest="isolated_mode", + action="store_true", + default=False, + help=( + "Run pip in an isolated mode, ignoring environment variables and user " + "configuration." + ), +) + +require_virtualenv: Callable[..., Option] = partial( + Option, + "--require-virtualenv", + "--require-venv", + dest="require_venv", + action="store_true", + default=False, + help=( + "Allow pip to only run in a virtual environment; " + "exit with an error otherwise." + ), +) + +verbose: Callable[..., Option] = partial( + Option, + "-v", + "--verbose", + dest="verbose", + action="count", + default=0, + help="Give more output. Option is additive, and can be used up to 3 times.", +) + +no_color: Callable[..., Option] = partial( + Option, + "--no-color", + dest="no_color", + action="store_true", + default=False, + help="Suppress colored output.", +) + +version: Callable[..., Option] = partial( + Option, + "-V", + "--version", + dest="version", + action="store_true", + help="Show version and exit.", +) + +quiet: Callable[..., Option] = partial( + Option, + "-q", + "--quiet", + dest="quiet", + action="count", + default=0, + help=( + "Give less output. Option is additive, and can be used up to 3" + " times (corresponding to WARNING, ERROR, and CRITICAL logging" + " levels)." + ), +) + +progress_bar: Callable[..., Option] = partial( + Option, + "--progress-bar", + dest="progress_bar", + type="choice", + choices=list(BAR_TYPES.keys()), + default="on", + help=( + "Specify type of progress to be displayed [" + + "|".join(BAR_TYPES.keys()) + + "] (default: %default)" + ), +) + +log: Callable[..., Option] = partial( + PipOption, + "--log", + "--log-file", + "--local-log", + dest="log", + metavar="path", + type="path", + help="Path to a verbose appending log.", +) + +no_input: Callable[..., Option] = partial( + Option, + # Don't ask for input + "--no-input", + dest="no_input", + action="store_true", + default=False, + help="Disable prompting for input.", +) + +proxy: Callable[..., Option] = partial( + Option, + "--proxy", + dest="proxy", + type="str", + default="", + help="Specify a proxy in the form [user:passwd@]proxy.server:port.", +) + +retries: Callable[..., Option] = partial( + Option, + "--retries", + dest="retries", + type="int", + default=5, + help="Maximum number of retries each connection should attempt " + "(default %default times).", +) + +timeout: Callable[..., Option] = partial( + Option, + "--timeout", + "--default-timeout", + metavar="sec", + dest="timeout", + type="float", + default=15, + help="Set the socket timeout (default %default seconds).", +) + + +def exists_action() -> Option: + return Option( + # Option when path already exist + "--exists-action", + dest="exists_action", + type="choice", + choices=["s", "i", "w", "b", "a"], + default=[], + action="append", + metavar="action", + help="Default action when a path already exists: " + "(s)witch, (i)gnore, (w)ipe, (b)ackup, (a)bort.", + ) + + +cert: Callable[..., Option] = partial( + PipOption, + "--cert", + dest="cert", + type="path", + metavar="path", + help=( + "Path to PEM-encoded CA certificate bundle. " + "If provided, overrides the default. " + "See 'SSL Certificate Verification' in pip documentation " + "for more information." + ), +) + +client_cert: Callable[..., Option] = partial( + PipOption, + "--client-cert", + dest="client_cert", + type="path", + default=None, + metavar="path", + help="Path to SSL client certificate, a single file containing the " + "private key and the certificate in PEM format.", +) + +index_url: Callable[..., Option] = partial( + Option, + "-i", + "--index-url", + "--pypi-url", + dest="index_url", + metavar="URL", + default=PyPI.simple_url, + help="Base URL of the Python Package Index (default %default). " + "This should point to a repository compliant with PEP 503 " + "(the simple repository API) or a local directory laid out " + "in the same format.", +) + + +def extra_index_url() -> Option: + return Option( + "--extra-index-url", + dest="extra_index_urls", + metavar="URL", + action="append", + default=[], + help="Extra URLs of package indexes to use in addition to " + "--index-url. Should follow the same rules as " + "--index-url.", + ) + + +no_index: Callable[..., Option] = partial( + Option, + "--no-index", + dest="no_index", + action="store_true", + default=False, + help="Ignore package index (only looking at --find-links URLs instead).", +) + + +def find_links() -> Option: + return Option( + "-f", + "--find-links", + dest="find_links", + action="append", + default=[], + metavar="url", + help="If a URL or path to an html file, then parse for links to " + "archives such as sdist (.tar.gz) or wheel (.whl) files. " + "If a local path or file:// URL that's a directory, " + "then look for archives in the directory listing. " + "Links to VCS project URLs are not supported.", + ) + + +def trusted_host() -> Option: + return Option( + "--trusted-host", + dest="trusted_hosts", + action="append", + metavar="HOSTNAME", + default=[], + help="Mark this host or host:port pair as trusted, even though it " + "does not have valid or any HTTPS.", + ) + + +def constraints() -> Option: + return Option( + "-c", + "--constraint", + dest="constraints", + action="append", + default=[], + metavar="file", + help="Constrain versions using the given constraints file. " + "This option can be used multiple times.", + ) + + +def requirements() -> Option: + return Option( + "-r", + "--requirement", + dest="requirements", + action="append", + default=[], + metavar="file", + help="Install from the given requirements file. " + "This option can be used multiple times.", + ) + + +def editable() -> Option: + return Option( + "-e", + "--editable", + dest="editables", + action="append", + default=[], + metavar="path/url", + help=( + "Install a project in editable mode (i.e. setuptools " + '"develop mode") from a local project path or a VCS url.' + ), + ) + + +def _handle_src(option: Option, opt_str: str, value: str, parser: OptionParser) -> None: + value = os.path.abspath(value) + setattr(parser.values, option.dest, value) + + +src: Callable[..., Option] = partial( + PipOption, + "--src", + "--source", + "--source-dir", + "--source-directory", + dest="src_dir", + type="path", + metavar="dir", + default=get_src_prefix(), + action="callback", + callback=_handle_src, + help="Directory to check out editable projects into. " + 'The default in a virtualenv is "/src". ' + 'The default for global installs is "/src".', +) + + +def _get_format_control(values: Values, option: Option) -> Any: + """Get a format_control object.""" + return getattr(values, option.dest) + + +def _handle_no_binary( + option: Option, opt_str: str, value: str, parser: OptionParser +) -> None: + existing = _get_format_control(parser.values, option) + FormatControl.handle_mutual_excludes( + value, + existing.no_binary, + existing.only_binary, + ) + + +def _handle_only_binary( + option: Option, opt_str: str, value: str, parser: OptionParser +) -> None: + existing = _get_format_control(parser.values, option) + FormatControl.handle_mutual_excludes( + value, + existing.only_binary, + existing.no_binary, + ) + + +def no_binary() -> Option: + format_control = FormatControl(set(), set()) + return Option( + "--no-binary", + dest="format_control", + action="callback", + callback=_handle_no_binary, + type="str", + default=format_control, + help="Do not use binary packages. Can be supplied multiple times, and " + 'each time adds to the existing value. Accepts either ":all:" to ' + 'disable all binary packages, ":none:" to empty the set (notice ' + "the colons), or one or more package names with commas between " + "them (no colons). Note that some packages are tricky to compile " + "and may fail to install when this option is used on them.", + ) + + +def only_binary() -> Option: + format_control = FormatControl(set(), set()) + return Option( + "--only-binary", + dest="format_control", + action="callback", + callback=_handle_only_binary, + type="str", + default=format_control, + help="Do not use source packages. Can be supplied multiple times, and " + 'each time adds to the existing value. Accepts either ":all:" to ' + 'disable all source packages, ":none:" to empty the set, or one ' + "or more package names with commas between them. Packages " + "without binary distributions will fail to install when this " + "option is used on them.", + ) + + +platforms: Callable[..., Option] = partial( + Option, + "--platform", + dest="platforms", + metavar="platform", + action="append", + default=None, + help=( + "Only use wheels compatible with . Defaults to the " + "platform of the running system. Use this option multiple times to " + "specify multiple platforms supported by the target interpreter." + ), +) + + +# This was made a separate function for unit-testing purposes. +def _convert_python_version(value: str) -> Tuple[Tuple[int, ...], Optional[str]]: + """ + Convert a version string like "3", "37", or "3.7.3" into a tuple of ints. + + :return: A 2-tuple (version_info, error_msg), where `error_msg` is + non-None if and only if there was a parsing error. + """ + if not value: + # The empty string is the same as not providing a value. + return (None, None) + + parts = value.split(".") + if len(parts) > 3: + return ((), "at most three version parts are allowed") + + if len(parts) == 1: + # Then we are in the case of "3" or "37". + value = parts[0] + if len(value) > 1: + parts = [value[0], value[1:]] + + try: + version_info = tuple(int(part) for part in parts) + except ValueError: + return ((), "each version part must be an integer") + + return (version_info, None) + + +def _handle_python_version( + option: Option, opt_str: str, value: str, parser: OptionParser +) -> None: + """ + Handle a provided --python-version value. + """ + version_info, error_msg = _convert_python_version(value) + if error_msg is not None: + msg = "invalid --python-version value: {!r}: {}".format( + value, + error_msg, + ) + raise_option_error(parser, option=option, msg=msg) + + parser.values.python_version = version_info + + +python_version: Callable[..., Option] = partial( + Option, + "--python-version", + dest="python_version", + metavar="python_version", + action="callback", + callback=_handle_python_version, + type="str", + default=None, + help=dedent( + """\ + The Python interpreter version to use for wheel and "Requires-Python" + compatibility checks. Defaults to a version derived from the running + interpreter. The version can be specified using up to three dot-separated + integers (e.g. "3" for 3.0.0, "3.7" for 3.7.0, or "3.7.3"). A major-minor + version can also be given as a string without dots (e.g. "37" for 3.7.0). + """ + ), +) + + +implementation: Callable[..., Option] = partial( + Option, + "--implementation", + dest="implementation", + metavar="implementation", + default=None, + help=( + "Only use wheels compatible with Python " + "implementation , e.g. 'pp', 'jy', 'cp', " + " or 'ip'. If not specified, then the current " + "interpreter implementation is used. Use 'py' to force " + "implementation-agnostic wheels." + ), +) + + +abis: Callable[..., Option] = partial( + Option, + "--abi", + dest="abis", + metavar="abi", + action="append", + default=None, + help=( + "Only use wheels compatible with Python abi , e.g. 'pypy_41'. " + "If not specified, then the current interpreter abi tag is used. " + "Use this option multiple times to specify multiple abis supported " + "by the target interpreter. Generally you will need to specify " + "--implementation, --platform, and --python-version when using this " + "option." + ), +) + + +def add_target_python_options(cmd_opts: OptionGroup) -> None: + cmd_opts.add_option(platforms()) + cmd_opts.add_option(python_version()) + cmd_opts.add_option(implementation()) + cmd_opts.add_option(abis()) + + +def make_target_python(options: Values) -> TargetPython: + target_python = TargetPython( + platforms=options.platforms, + py_version_info=options.python_version, + abis=options.abis, + implementation=options.implementation, + ) + + return target_python + + +def prefer_binary() -> Option: + return Option( + "--prefer-binary", + dest="prefer_binary", + action="store_true", + default=False, + help="Prefer older binary packages over newer source packages.", + ) + + +cache_dir: Callable[..., Option] = partial( + PipOption, + "--cache-dir", + dest="cache_dir", + default=USER_CACHE_DIR, + metavar="dir", + type="path", + help="Store the cache data in .", +) + + +def _handle_no_cache_dir( + option: Option, opt: str, value: str, parser: OptionParser +) -> None: + """ + Process a value provided for the --no-cache-dir option. + + This is an optparse.Option callback for the --no-cache-dir option. + """ + # The value argument will be None if --no-cache-dir is passed via the + # command-line, since the option doesn't accept arguments. However, + # the value can be non-None if the option is triggered e.g. by an + # environment variable, like PIP_NO_CACHE_DIR=true. + if value is not None: + # Then parse the string value to get argument error-checking. + try: + strtobool(value) + except ValueError as exc: + raise_option_error(parser, option=option, msg=str(exc)) + + # Originally, setting PIP_NO_CACHE_DIR to a value that strtobool() + # converted to 0 (like "false" or "no") caused cache_dir to be disabled + # rather than enabled (logic would say the latter). Thus, we disable + # the cache directory not just on values that parse to True, but (for + # backwards compatibility reasons) also on values that parse to False. + # In other words, always set it to False if the option is provided in + # some (valid) form. + parser.values.cache_dir = False + + +no_cache: Callable[..., Option] = partial( + Option, + "--no-cache-dir", + dest="cache_dir", + action="callback", + callback=_handle_no_cache_dir, + help="Disable the cache.", +) + +no_deps: Callable[..., Option] = partial( + Option, + "--no-deps", + "--no-dependencies", + dest="ignore_dependencies", + action="store_true", + default=False, + help="Don't install package dependencies.", +) + +ignore_requires_python: Callable[..., Option] = partial( + Option, + "--ignore-requires-python", + dest="ignore_requires_python", + action="store_true", + help="Ignore the Requires-Python information.", +) + +no_build_isolation: Callable[..., Option] = partial( + Option, + "--no-build-isolation", + dest="build_isolation", + action="store_false", + default=True, + help="Disable isolation when building a modern source distribution. " + "Build dependencies specified by PEP 518 must be already installed " + "if this option is used.", +) + + +def _handle_no_use_pep517( + option: Option, opt: str, value: str, parser: OptionParser +) -> None: + """ + Process a value provided for the --no-use-pep517 option. + + This is an optparse.Option callback for the no_use_pep517 option. + """ + # Since --no-use-pep517 doesn't accept arguments, the value argument + # will be None if --no-use-pep517 is passed via the command-line. + # However, the value can be non-None if the option is triggered e.g. + # by an environment variable, for example "PIP_NO_USE_PEP517=true". + if value is not None: + msg = """A value was passed for --no-use-pep517, + probably using either the PIP_NO_USE_PEP517 environment variable + or the "no-use-pep517" config file option. Use an appropriate value + of the PIP_USE_PEP517 environment variable or the "use-pep517" + config file option instead. + """ + raise_option_error(parser, option=option, msg=msg) + + # Otherwise, --no-use-pep517 was passed via the command-line. + parser.values.use_pep517 = False + + +use_pep517: Any = partial( + Option, + "--use-pep517", + dest="use_pep517", + action="store_true", + default=None, + help="Use PEP 517 for building source distributions " + "(use --no-use-pep517 to force legacy behaviour).", +) + +no_use_pep517: Any = partial( + Option, + "--no-use-pep517", + dest="use_pep517", + action="callback", + callback=_handle_no_use_pep517, + default=None, + help=SUPPRESS_HELP, +) + +install_options: Callable[..., Option] = partial( + Option, + "--install-option", + dest="install_options", + action="append", + metavar="options", + help="Extra arguments to be supplied to the setup.py install " + 'command (use like --install-option="--install-scripts=/usr/local/' + 'bin"). Use multiple --install-option options to pass multiple ' + "options to setup.py install. If you are using an option with a " + "directory path, be sure to use absolute path.", +) + +build_options: Callable[..., Option] = partial( + Option, + "--build-option", + dest="build_options", + metavar="options", + action="append", + help="Extra arguments to be supplied to 'setup.py bdist_wheel'.", +) + +global_options: Callable[..., Option] = partial( + Option, + "--global-option", + dest="global_options", + action="append", + metavar="options", + help="Extra global options to be supplied to the setup.py " + "call before the install or bdist_wheel command.", +) + +no_clean: Callable[..., Option] = partial( + Option, + "--no-clean", + action="store_true", + default=False, + help="Don't clean up build directories.", +) + +pre: Callable[..., Option] = partial( + Option, + "--pre", + action="store_true", + default=False, + help="Include pre-release and development versions. By default, " + "pip only finds stable versions.", +) + +disable_pip_version_check: Callable[..., Option] = partial( + Option, + "--disable-pip-version-check", + dest="disable_pip_version_check", + action="store_true", + default=False, + help="Don't periodically check PyPI to determine whether a new version " + "of pip is available for download. Implied with --no-index.", +) + + +def _handle_merge_hash( + option: Option, opt_str: str, value: str, parser: OptionParser +) -> None: + """Given a value spelled "algo:digest", append the digest to a list + pointed to in a dict by the algo name.""" + if not parser.values.hashes: + parser.values.hashes = {} + try: + algo, digest = value.split(":", 1) + except ValueError: + parser.error( + "Arguments to {} must be a hash name " # noqa + "followed by a value, like --hash=sha256:" + "abcde...".format(opt_str) + ) + if algo not in STRONG_HASHES: + parser.error( + "Allowed hash algorithms for {} are {}.".format( # noqa + opt_str, ", ".join(STRONG_HASHES) + ) + ) + parser.values.hashes.setdefault(algo, []).append(digest) + + +hash: Callable[..., Option] = partial( + Option, + "--hash", + # Hash values eventually end up in InstallRequirement.hashes due to + # __dict__ copying in process_line(). + dest="hashes", + action="callback", + callback=_handle_merge_hash, + type="string", + help="Verify that the package's archive matches this " + "hash before installing. Example: --hash=sha256:abcdef...", +) + + +require_hashes: Callable[..., Option] = partial( + Option, + "--require-hashes", + dest="require_hashes", + action="store_true", + default=False, + help="Require a hash to check each requirement against, for " + "repeatable installs. This option is implied when any package in a " + "requirements file has a --hash option.", +) + + +list_path: Callable[..., Option] = partial( + PipOption, + "--path", + dest="path", + type="path", + action="append", + help="Restrict to the specified installation path for listing " + "packages (can be used multiple times).", +) + + +def check_list_path_option(options: Values) -> None: + if options.path and (options.user or options.local): + raise CommandError("Cannot combine '--path' with '--user' or '--local'") + + +list_exclude: Callable[..., Option] = partial( + PipOption, + "--exclude", + dest="excludes", + action="append", + metavar="package", + type="package_name", + help="Exclude specified package from the output", +) + + +no_python_version_warning: Callable[..., Option] = partial( + Option, + "--no-python-version-warning", + dest="no_python_version_warning", + action="store_true", + default=False, + help="Silence deprecation warnings for upcoming unsupported Pythons.", +) + + +use_new_feature: Callable[..., Option] = partial( + Option, + "--use-feature", + dest="features_enabled", + metavar="feature", + action="append", + default=[], + choices=["2020-resolver", "fast-deps", "in-tree-build"], + help="Enable new functionality, that may be backward incompatible.", +) + +use_deprecated_feature: Callable[..., Option] = partial( + Option, + "--use-deprecated", + dest="deprecated_features_enabled", + metavar="feature", + action="append", + default=[], + choices=[ + "legacy-resolver", + "out-of-tree-build", + "backtrack-on-build-failures", + "html5lib", + ], + help=("Enable deprecated functionality, that will be removed in the future."), +) + + +########## +# groups # +########## + +general_group: Dict[str, Any] = { + "name": "General Options", + "options": [ + help_, + debug_mode, + isolated_mode, + require_virtualenv, + verbose, + version, + quiet, + log, + no_input, + proxy, + retries, + timeout, + exists_action, + trusted_host, + cert, + client_cert, + cache_dir, + no_cache, + disable_pip_version_check, + no_color, + no_python_version_warning, + use_new_feature, + use_deprecated_feature, + ], +} + +index_group: Dict[str, Any] = { + "name": "Package Index Options", + "options": [ + index_url, + extra_index_url, + no_index, + find_links, + ], +} diff --git a/venv/Lib/site-packages/pip/_internal/cli/command_context.py b/venv/Lib/site-packages/pip/_internal/cli/command_context.py new file mode 100644 index 0000000..ed68322 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/cli/command_context.py @@ -0,0 +1,27 @@ +from contextlib import ExitStack, contextmanager +from typing import ContextManager, Iterator, TypeVar + +_T = TypeVar("_T", covariant=True) + + +class CommandContextMixIn: + def __init__(self) -> None: + super().__init__() + self._in_main_context = False + self._main_context = ExitStack() + + @contextmanager + def main_context(self) -> Iterator[None]: + assert not self._in_main_context + + self._in_main_context = True + try: + with self._main_context: + yield + finally: + self._in_main_context = False + + def enter_context(self, context_provider: ContextManager[_T]) -> _T: + assert self._in_main_context + + return self._main_context.enter_context(context_provider) diff --git a/venv/Lib/site-packages/pip/_internal/cli/main.py b/venv/Lib/site-packages/pip/_internal/cli/main.py new file mode 100644 index 0000000..0e31221 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/cli/main.py @@ -0,0 +1,70 @@ +"""Primary application entrypoint. +""" +import locale +import logging +import os +import sys +from typing import List, Optional + +from pip._internal.cli.autocompletion import autocomplete +from pip._internal.cli.main_parser import parse_command +from pip._internal.commands import create_command +from pip._internal.exceptions import PipError +from pip._internal.utils import deprecation + +logger = logging.getLogger(__name__) + + +# Do not import and use main() directly! Using it directly is actively +# discouraged by pip's maintainers. The name, location and behavior of +# this function is subject to change, so calling it directly is not +# portable across different pip versions. + +# In addition, running pip in-process is unsupported and unsafe. This is +# elaborated in detail at +# https://pip.pypa.io/en/stable/user_guide/#using-pip-from-your-program. +# That document also provides suggestions that should work for nearly +# all users that are considering importing and using main() directly. + +# However, we know that certain users will still want to invoke pip +# in-process. If you understand and accept the implications of using pip +# in an unsupported manner, the best approach is to use runpy to avoid +# depending on the exact location of this entry point. + +# The following example shows how to use runpy to invoke pip in that +# case: +# +# sys.argv = ["pip", your, args, here] +# runpy.run_module("pip", run_name="__main__") +# +# Note that this will exit the process after running, unlike a direct +# call to main. As it is not safe to do any processing after calling +# main, this should not be an issue in practice. + + +def main(args: Optional[List[str]] = None) -> int: + if args is None: + args = sys.argv[1:] + + # Configure our deprecation warnings to be sent through loggers + deprecation.install_warning_logger() + + autocomplete() + + try: + cmd_name, cmd_args = parse_command(args) + except PipError as exc: + sys.stderr.write(f"ERROR: {exc}") + sys.stderr.write(os.linesep) + sys.exit(1) + + # Needed for locale.getpreferredencoding(False) to work + # in pip._internal.utils.encoding.auto_decode + try: + locale.setlocale(locale.LC_ALL, "") + except locale.Error as e: + # setlocale can apparently crash if locale are uninitialized + logger.debug("Ignoring error %s when setting locale", e) + command = create_command(cmd_name, isolated=("--isolated" in cmd_args)) + + return command.main(cmd_args) diff --git a/venv/Lib/site-packages/pip/_internal/cli/main_parser.py b/venv/Lib/site-packages/pip/_internal/cli/main_parser.py new file mode 100644 index 0000000..3666ab0 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/cli/main_parser.py @@ -0,0 +1,87 @@ +"""A single place for constructing and exposing the main parser +""" + +import os +import sys +from typing import List, Tuple + +from pip._internal.cli import cmdoptions +from pip._internal.cli.parser import ConfigOptionParser, UpdatingDefaultsHelpFormatter +from pip._internal.commands import commands_dict, get_similar_commands +from pip._internal.exceptions import CommandError +from pip._internal.utils.misc import get_pip_version, get_prog + +__all__ = ["create_main_parser", "parse_command"] + + +def create_main_parser() -> ConfigOptionParser: + """Creates and returns the main parser for pip's CLI""" + + parser = ConfigOptionParser( + usage="\n%prog [options]", + add_help_option=False, + formatter=UpdatingDefaultsHelpFormatter(), + name="global", + prog=get_prog(), + ) + parser.disable_interspersed_args() + + parser.version = get_pip_version() + + # add the general options + gen_opts = cmdoptions.make_option_group(cmdoptions.general_group, parser) + parser.add_option_group(gen_opts) + + # so the help formatter knows + parser.main = True # type: ignore + + # create command listing for description + description = [""] + [ + f"{name:27} {command_info.summary}" + for name, command_info in commands_dict.items() + ] + parser.description = "\n".join(description) + + return parser + + +def parse_command(args: List[str]) -> Tuple[str, List[str]]: + parser = create_main_parser() + + # Note: parser calls disable_interspersed_args(), so the result of this + # call is to split the initial args into the general options before the + # subcommand and everything else. + # For example: + # args: ['--timeout=5', 'install', '--user', 'INITools'] + # general_options: ['--timeout==5'] + # args_else: ['install', '--user', 'INITools'] + general_options, args_else = parser.parse_args(args) + + # --version + if general_options.version: + sys.stdout.write(parser.version) + sys.stdout.write(os.linesep) + sys.exit() + + # pip || pip help -> print_help() + if not args_else or (args_else[0] == "help" and len(args_else) == 1): + parser.print_help() + sys.exit() + + # the subcommand name + cmd_name = args_else[0] + + if cmd_name not in commands_dict: + guess = get_similar_commands(cmd_name) + + msg = [f'unknown command "{cmd_name}"'] + if guess: + msg.append(f'maybe you meant "{guess}"') + + raise CommandError(" - ".join(msg)) + + # all the args without the subcommand + cmd_args = args[:] + cmd_args.remove(cmd_name) + + return cmd_name, cmd_args diff --git a/venv/Lib/site-packages/pip/_internal/cli/parser.py b/venv/Lib/site-packages/pip/_internal/cli/parser.py new file mode 100644 index 0000000..a1c99a8 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/cli/parser.py @@ -0,0 +1,292 @@ +"""Base option parser setup""" + +import logging +import optparse +import shutil +import sys +import textwrap +from contextlib import suppress +from typing import Any, Dict, Iterator, List, Tuple + +from pip._internal.cli.status_codes import UNKNOWN_ERROR +from pip._internal.configuration import Configuration, ConfigurationError +from pip._internal.utils.misc import redact_auth_from_url, strtobool + +logger = logging.getLogger(__name__) + + +class PrettyHelpFormatter(optparse.IndentedHelpFormatter): + """A prettier/less verbose help formatter for optparse.""" + + def __init__(self, *args: Any, **kwargs: Any) -> None: + # help position must be aligned with __init__.parseopts.description + kwargs["max_help_position"] = 30 + kwargs["indent_increment"] = 1 + kwargs["width"] = shutil.get_terminal_size()[0] - 2 + super().__init__(*args, **kwargs) + + def format_option_strings(self, option: optparse.Option) -> str: + return self._format_option_strings(option) + + def _format_option_strings( + self, option: optparse.Option, mvarfmt: str = " <{}>", optsep: str = ", " + ) -> str: + """ + Return a comma-separated list of option strings and metavars. + + :param option: tuple of (short opt, long opt), e.g: ('-f', '--format') + :param mvarfmt: metavar format string + :param optsep: separator + """ + opts = [] + + if option._short_opts: + opts.append(option._short_opts[0]) + if option._long_opts: + opts.append(option._long_opts[0]) + if len(opts) > 1: + opts.insert(1, optsep) + + if option.takes_value(): + assert option.dest is not None + metavar = option.metavar or option.dest.lower() + opts.append(mvarfmt.format(metavar.lower())) + + return "".join(opts) + + def format_heading(self, heading: str) -> str: + if heading == "Options": + return "" + return heading + ":\n" + + def format_usage(self, usage: str) -> str: + """ + Ensure there is only one newline between usage and the first heading + if there is no description. + """ + msg = "\nUsage: {}\n".format(self.indent_lines(textwrap.dedent(usage), " ")) + return msg + + def format_description(self, description: str) -> str: + # leave full control over description to us + if description: + if hasattr(self.parser, "main"): + label = "Commands" + else: + label = "Description" + # some doc strings have initial newlines, some don't + description = description.lstrip("\n") + # some doc strings have final newlines and spaces, some don't + description = description.rstrip() + # dedent, then reindent + description = self.indent_lines(textwrap.dedent(description), " ") + description = f"{label}:\n{description}\n" + return description + else: + return "" + + def format_epilog(self, epilog: str) -> str: + # leave full control over epilog to us + if epilog: + return epilog + else: + return "" + + def indent_lines(self, text: str, indent: str) -> str: + new_lines = [indent + line for line in text.split("\n")] + return "\n".join(new_lines) + + +class UpdatingDefaultsHelpFormatter(PrettyHelpFormatter): + """Custom help formatter for use in ConfigOptionParser. + + This is updates the defaults before expanding them, allowing + them to show up correctly in the help listing. + + Also redact auth from url type options + """ + + def expand_default(self, option: optparse.Option) -> str: + default_values = None + if self.parser is not None: + assert isinstance(self.parser, ConfigOptionParser) + self.parser._update_defaults(self.parser.defaults) + assert option.dest is not None + default_values = self.parser.defaults.get(option.dest) + help_text = super().expand_default(option) + + if default_values and option.metavar == "URL": + if isinstance(default_values, str): + default_values = [default_values] + + # If its not a list, we should abort and just return the help text + if not isinstance(default_values, list): + default_values = [] + + for val in default_values: + help_text = help_text.replace(val, redact_auth_from_url(val)) + + return help_text + + +class CustomOptionParser(optparse.OptionParser): + def insert_option_group( + self, idx: int, *args: Any, **kwargs: Any + ) -> optparse.OptionGroup: + """Insert an OptionGroup at a given position.""" + group = self.add_option_group(*args, **kwargs) + + self.option_groups.pop() + self.option_groups.insert(idx, group) + + return group + + @property + def option_list_all(self) -> List[optparse.Option]: + """Get a list of all options, including those in option groups.""" + res = self.option_list[:] + for i in self.option_groups: + res.extend(i.option_list) + + return res + + +class ConfigOptionParser(CustomOptionParser): + """Custom option parser which updates its defaults by checking the + configuration files and environmental variables""" + + def __init__( + self, + *args: Any, + name: str, + isolated: bool = False, + **kwargs: Any, + ) -> None: + self.name = name + self.config = Configuration(isolated) + + assert self.name + super().__init__(*args, **kwargs) + + def check_default(self, option: optparse.Option, key: str, val: Any) -> Any: + try: + return option.check_value(key, val) + except optparse.OptionValueError as exc: + print(f"An error occurred during configuration: {exc}") + sys.exit(3) + + def _get_ordered_configuration_items(self) -> Iterator[Tuple[str, Any]]: + # Configuration gives keys in an unordered manner. Order them. + override_order = ["global", self.name, ":env:"] + + # Pool the options into different groups + section_items: Dict[str, List[Tuple[str, Any]]] = { + name: [] for name in override_order + } + for section_key, val in self.config.items(): + # ignore empty values + if not val: + logger.debug( + "Ignoring configuration key '%s' as it's value is empty.", + section_key, + ) + continue + + section, key = section_key.split(".", 1) + if section in override_order: + section_items[section].append((key, val)) + + # Yield each group in their override order + for section in override_order: + for key, val in section_items[section]: + yield key, val + + def _update_defaults(self, defaults: Dict[str, Any]) -> Dict[str, Any]: + """Updates the given defaults with values from the config files and + the environ. Does a little special handling for certain types of + options (lists).""" + + # Accumulate complex default state. + self.values = optparse.Values(self.defaults) + late_eval = set() + # Then set the options with those values + for key, val in self._get_ordered_configuration_items(): + # '--' because configuration supports only long names + option = self.get_option("--" + key) + + # Ignore options not present in this parser. E.g. non-globals put + # in [global] by users that want them to apply to all applicable + # commands. + if option is None: + continue + + assert option.dest is not None + + if option.action in ("store_true", "store_false"): + try: + val = strtobool(val) + except ValueError: + self.error( + "{} is not a valid value for {} option, " # noqa + "please specify a boolean value like yes/no, " + "true/false or 1/0 instead.".format(val, key) + ) + elif option.action == "count": + with suppress(ValueError): + val = strtobool(val) + with suppress(ValueError): + val = int(val) + if not isinstance(val, int) or val < 0: + self.error( + "{} is not a valid value for {} option, " # noqa + "please instead specify either a non-negative integer " + "or a boolean value like yes/no or false/true " + "which is equivalent to 1/0.".format(val, key) + ) + elif option.action == "append": + val = val.split() + val = [self.check_default(option, key, v) for v in val] + elif option.action == "callback": + assert option.callback is not None + late_eval.add(option.dest) + opt_str = option.get_opt_string() + val = option.convert_value(opt_str, val) + # From take_action + args = option.callback_args or () + kwargs = option.callback_kwargs or {} + option.callback(option, opt_str, val, self, *args, **kwargs) + else: + val = self.check_default(option, key, val) + + defaults[option.dest] = val + + for key in late_eval: + defaults[key] = getattr(self.values, key) + self.values = None + return defaults + + def get_default_values(self) -> optparse.Values: + """Overriding to make updating the defaults after instantiation of + the option parser possible, _update_defaults() does the dirty work.""" + if not self.process_default_values: + # Old, pre-Optik 1.5 behaviour. + return optparse.Values(self.defaults) + + # Load the configuration, or error out in case of an error + try: + self.config.load() + except ConfigurationError as err: + self.exit(UNKNOWN_ERROR, str(err)) + + defaults = self._update_defaults(self.defaults.copy()) # ours + for option in self._get_all_options(): + assert option.dest is not None + default = defaults.get(option.dest) + if isinstance(default, str): + opt_str = option.get_opt_string() + defaults[option.dest] = option.check_value(opt_str, default) + return optparse.Values(defaults) + + def error(self, msg: str) -> None: + self.print_usage(sys.stderr) + self.exit(UNKNOWN_ERROR, f"{msg}\n") diff --git a/venv/Lib/site-packages/pip/_internal/cli/progress_bars.py b/venv/Lib/site-packages/pip/_internal/cli/progress_bars.py new file mode 100644 index 0000000..ffa1964 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/cli/progress_bars.py @@ -0,0 +1,321 @@ +import functools +import itertools +import sys +from signal import SIGINT, default_int_handler, signal +from typing import Any, Callable, Iterator, Optional, Tuple + +from pip._vendor.progress.bar import Bar, FillingCirclesBar, IncrementalBar +from pip._vendor.progress.spinner import Spinner +from pip._vendor.rich.progress import ( + BarColumn, + DownloadColumn, + FileSizeColumn, + Progress, + ProgressColumn, + SpinnerColumn, + TextColumn, + TimeElapsedColumn, + TimeRemainingColumn, + TransferSpeedColumn, +) + +from pip._internal.utils.compat import WINDOWS +from pip._internal.utils.logging import get_indentation +from pip._internal.utils.misc import format_size + +try: + from pip._vendor import colorama +# Lots of different errors can come from this, including SystemError and +# ImportError. +except Exception: + colorama = None + +DownloadProgressRenderer = Callable[[Iterator[bytes]], Iterator[bytes]] + + +def _select_progress_class(preferred: Bar, fallback: Bar) -> Bar: + encoding = getattr(preferred.file, "encoding", None) + + # If we don't know what encoding this file is in, then we'll just assume + # that it doesn't support unicode and use the ASCII bar. + if not encoding: + return fallback + + # Collect all of the possible characters we want to use with the preferred + # bar. + characters = [ + getattr(preferred, "empty_fill", ""), + getattr(preferred, "fill", ""), + ] + characters += list(getattr(preferred, "phases", [])) + + # Try to decode the characters we're using for the bar using the encoding + # of the given file, if this works then we'll assume that we can use the + # fancier bar and if not we'll fall back to the plaintext bar. + try: + "".join(characters).encode(encoding) + except UnicodeEncodeError: + return fallback + else: + return preferred + + +_BaseBar: Any = _select_progress_class(IncrementalBar, Bar) + + +class InterruptibleMixin: + """ + Helper to ensure that self.finish() gets called on keyboard interrupt. + + This allows downloads to be interrupted without leaving temporary state + (like hidden cursors) behind. + + This class is similar to the progress library's existing SigIntMixin + helper, but as of version 1.2, that helper has the following problems: + + 1. It calls sys.exit(). + 2. It discards the existing SIGINT handler completely. + 3. It leaves its own handler in place even after an uninterrupted finish, + which will have unexpected delayed effects if the user triggers an + unrelated keyboard interrupt some time after a progress-displaying + download has already completed, for example. + """ + + def __init__(self, *args: Any, **kwargs: Any) -> None: + """ + Save the original SIGINT handler for later. + """ + # https://github.com/python/mypy/issues/5887 + super().__init__(*args, **kwargs) # type: ignore + + self.original_handler = signal(SIGINT, self.handle_sigint) + + # If signal() returns None, the previous handler was not installed from + # Python, and we cannot restore it. This probably should not happen, + # but if it does, we must restore something sensible instead, at least. + # The least bad option should be Python's default SIGINT handler, which + # just raises KeyboardInterrupt. + if self.original_handler is None: + self.original_handler = default_int_handler + + def finish(self) -> None: + """ + Restore the original SIGINT handler after finishing. + + This should happen regardless of whether the progress display finishes + normally, or gets interrupted. + """ + super().finish() # type: ignore + signal(SIGINT, self.original_handler) + + def handle_sigint(self, signum, frame): # type: ignore + """ + Call self.finish() before delegating to the original SIGINT handler. + + This handler should only be in place while the progress display is + active. + """ + self.finish() + self.original_handler(signum, frame) + + +class SilentBar(Bar): + def update(self) -> None: + pass + + +class BlueEmojiBar(IncrementalBar): + + suffix = "%(percent)d%%" + bar_prefix = " " + bar_suffix = " " + phases = ("\U0001F539", "\U0001F537", "\U0001F535") + + +class DownloadProgressMixin: + def __init__(self, *args: Any, **kwargs: Any) -> None: + # https://github.com/python/mypy/issues/5887 + super().__init__(*args, **kwargs) # type: ignore + self.message: str = (" " * (get_indentation() + 2)) + self.message + + @property + def downloaded(self) -> str: + return format_size(self.index) # type: ignore + + @property + def download_speed(self) -> str: + # Avoid zero division errors... + if self.avg == 0.0: # type: ignore + return "..." + return format_size(1 / self.avg) + "/s" # type: ignore + + @property + def pretty_eta(self) -> str: + if self.eta: # type: ignore + return f"eta {self.eta_td}" # type: ignore + return "" + + def iter(self, it): # type: ignore + for x in it: + yield x + # B305 is incorrectly raised here + # https://github.com/PyCQA/flake8-bugbear/issues/59 + self.next(len(x)) # noqa: B305 + self.finish() + + +class WindowsMixin: + def __init__(self, *args: Any, **kwargs: Any) -> None: + # The Windows terminal does not support the hide/show cursor ANSI codes + # even with colorama. So we'll ensure that hide_cursor is False on + # Windows. + # This call needs to go before the super() call, so that hide_cursor + # is set in time. The base progress bar class writes the "hide cursor" + # code to the terminal in its init, so if we don't set this soon + # enough, we get a "hide" with no corresponding "show"... + if WINDOWS and self.hide_cursor: # type: ignore + self.hide_cursor = False + + # https://github.com/python/mypy/issues/5887 + super().__init__(*args, **kwargs) # type: ignore + + # Check if we are running on Windows and we have the colorama module, + # if we do then wrap our file with it. + if WINDOWS and colorama: + self.file = colorama.AnsiToWin32(self.file) # type: ignore + # The progress code expects to be able to call self.file.isatty() + # but the colorama.AnsiToWin32() object doesn't have that, so we'll + # add it. + self.file.isatty = lambda: self.file.wrapped.isatty() + # The progress code expects to be able to call self.file.flush() + # but the colorama.AnsiToWin32() object doesn't have that, so we'll + # add it. + self.file.flush = lambda: self.file.wrapped.flush() + + +class BaseDownloadProgressBar(WindowsMixin, InterruptibleMixin, DownloadProgressMixin): + + file = sys.stdout + message = "%(percent)d%%" + suffix = "%(downloaded)s %(download_speed)s %(pretty_eta)s" + + +class DefaultDownloadProgressBar(BaseDownloadProgressBar, _BaseBar): + pass + + +class DownloadSilentBar(BaseDownloadProgressBar, SilentBar): + pass + + +class DownloadBar(BaseDownloadProgressBar, Bar): + pass + + +class DownloadFillingCirclesBar(BaseDownloadProgressBar, FillingCirclesBar): + pass + + +class DownloadBlueEmojiProgressBar(BaseDownloadProgressBar, BlueEmojiBar): + pass + + +class DownloadProgressSpinner( + WindowsMixin, InterruptibleMixin, DownloadProgressMixin, Spinner +): + + file = sys.stdout + suffix = "%(downloaded)s %(download_speed)s" + + def next_phase(self) -> str: + if not hasattr(self, "_phaser"): + self._phaser = itertools.cycle(self.phases) + return next(self._phaser) + + def update(self) -> None: + message = self.message % self + phase = self.next_phase() + suffix = self.suffix % self + line = "".join( + [ + message, + " " if message else "", + phase, + " " if suffix else "", + suffix, + ] + ) + + self.writeln(line) + + +BAR_TYPES = { + "off": (DownloadSilentBar, DownloadSilentBar), + "on": (DefaultDownloadProgressBar, DownloadProgressSpinner), + "ascii": (DownloadBar, DownloadProgressSpinner), + "pretty": (DownloadFillingCirclesBar, DownloadProgressSpinner), + "emoji": (DownloadBlueEmojiProgressBar, DownloadProgressSpinner), +} + + +def _legacy_progress_bar( + progress_bar: str, max: Optional[int] +) -> DownloadProgressRenderer: + if max is None or max == 0: + return BAR_TYPES[progress_bar][1]().iter # type: ignore + else: + return BAR_TYPES[progress_bar][0](max=max).iter + + +# +# Modern replacement, for our legacy progress bars. +# +def _rich_progress_bar( + iterable: Iterator[bytes], + *, + bar_type: str, + size: int, +) -> Iterator[bytes]: + assert bar_type == "on", "This should only be used in the default mode." + + if not size: + total = float("inf") + columns: Tuple[ProgressColumn, ...] = ( + TextColumn("[progress.description]{task.description}"), + SpinnerColumn("line", speed=1.5), + FileSizeColumn(), + TransferSpeedColumn(), + TimeElapsedColumn(), + ) + else: + total = size + columns = ( + TextColumn("[progress.description]{task.description}"), + BarColumn(), + DownloadColumn(), + TransferSpeedColumn(), + TextColumn("eta"), + TimeRemainingColumn(), + ) + + progress = Progress(*columns, refresh_per_second=30) + task_id = progress.add_task(" " * (get_indentation() + 2), total=total) + with progress: + for chunk in iterable: + yield chunk + progress.update(task_id, advance=len(chunk)) + + +def get_download_progress_renderer( + *, bar_type: str, size: Optional[int] = None +) -> DownloadProgressRenderer: + """Get an object that can be used to render the download progress. + + Returns a callable, that takes an iterable to "wrap". + """ + if bar_type == "on": + return functools.partial(_rich_progress_bar, bar_type=bar_type, size=size) + elif bar_type == "off": + return iter # no-op, when passed an iterator + else: + return _legacy_progress_bar(bar_type, size) diff --git a/venv/Lib/site-packages/pip/_internal/cli/req_command.py b/venv/Lib/site-packages/pip/_internal/cli/req_command.py new file mode 100644 index 0000000..5d4d1f0 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/cli/req_command.py @@ -0,0 +1,506 @@ +"""Contains the Command base classes that depend on PipSession. + +The classes in this module are in a separate module so the commands not +needing download / PackageFinder capability don't unnecessarily import the +PackageFinder machinery and all its vendored dependencies, etc. +""" + +import logging +import os +import sys +from functools import partial +from optparse import Values +from typing import Any, List, Optional, Tuple + +from pip._internal.cache import WheelCache +from pip._internal.cli import cmdoptions +from pip._internal.cli.base_command import Command +from pip._internal.cli.command_context import CommandContextMixIn +from pip._internal.exceptions import CommandError, PreviousBuildDirError +from pip._internal.index.collector import LinkCollector +from pip._internal.index.package_finder import PackageFinder +from pip._internal.models.selection_prefs import SelectionPreferences +from pip._internal.models.target_python import TargetPython +from pip._internal.network.session import PipSession +from pip._internal.operations.prepare import RequirementPreparer +from pip._internal.req.constructors import ( + install_req_from_editable, + install_req_from_line, + install_req_from_parsed_requirement, + install_req_from_req_string, +) +from pip._internal.req.req_file import parse_requirements +from pip._internal.req.req_install import InstallRequirement +from pip._internal.req.req_tracker import RequirementTracker +from pip._internal.resolution.base import BaseResolver +from pip._internal.self_outdated_check import pip_self_version_check +from pip._internal.utils.deprecation import deprecated +from pip._internal.utils.temp_dir import ( + TempDirectory, + TempDirectoryTypeRegistry, + tempdir_kinds, +) +from pip._internal.utils.virtualenv import running_under_virtualenv + +logger = logging.getLogger(__name__) + + +class SessionCommandMixin(CommandContextMixIn): + + """ + A class mixin for command classes needing _build_session(). + """ + + def __init__(self) -> None: + super().__init__() + self._session: Optional[PipSession] = None + + @classmethod + def _get_index_urls(cls, options: Values) -> Optional[List[str]]: + """Return a list of index urls from user-provided options.""" + index_urls = [] + if not getattr(options, "no_index", False): + url = getattr(options, "index_url", None) + if url: + index_urls.append(url) + urls = getattr(options, "extra_index_urls", None) + if urls: + index_urls.extend(urls) + # Return None rather than an empty list + return index_urls or None + + def get_default_session(self, options: Values) -> PipSession: + """Get a default-managed session.""" + if self._session is None: + self._session = self.enter_context(self._build_session(options)) + # there's no type annotation on requests.Session, so it's + # automatically ContextManager[Any] and self._session becomes Any, + # then https://github.com/python/mypy/issues/7696 kicks in + assert self._session is not None + return self._session + + def _build_session( + self, + options: Values, + retries: Optional[int] = None, + timeout: Optional[int] = None, + ) -> PipSession: + assert not options.cache_dir or os.path.isabs(options.cache_dir) + session = PipSession( + cache=( + os.path.join(options.cache_dir, "http") if options.cache_dir else None + ), + retries=retries if retries is not None else options.retries, + trusted_hosts=options.trusted_hosts, + index_urls=self._get_index_urls(options), + ) + + # Handle custom ca-bundles from the user + if options.cert: + session.verify = options.cert + + # Handle SSL client certificate + if options.client_cert: + session.cert = options.client_cert + + # Handle timeouts + if options.timeout or timeout: + session.timeout = timeout if timeout is not None else options.timeout + + # Handle configured proxies + if options.proxy: + session.proxies = { + "http": options.proxy, + "https": options.proxy, + } + + # Determine if we can prompt the user for authentication or not + session.auth.prompting = not options.no_input + + return session + + +class IndexGroupCommand(Command, SessionCommandMixin): + + """ + Abstract base class for commands with the index_group options. + + This also corresponds to the commands that permit the pip version check. + """ + + def handle_pip_version_check(self, options: Values) -> None: + """ + Do the pip version check if not disabled. + + This overrides the default behavior of not doing the check. + """ + # Make sure the index_group options are present. + assert hasattr(options, "no_index") + + if options.disable_pip_version_check or options.no_index: + return + + # Otherwise, check if we're using the latest version of pip available. + session = self._build_session( + options, retries=0, timeout=min(5, options.timeout) + ) + with session: + pip_self_version_check(session, options) + + +KEEPABLE_TEMPDIR_TYPES = [ + tempdir_kinds.BUILD_ENV, + tempdir_kinds.EPHEM_WHEEL_CACHE, + tempdir_kinds.REQ_BUILD, +] + + +def warn_if_run_as_root() -> None: + """Output a warning for sudo users on Unix. + + In a virtual environment, sudo pip still writes to virtualenv. + On Windows, users may run pip as Administrator without issues. + This warning only applies to Unix root users outside of virtualenv. + """ + if running_under_virtualenv(): + return + if not hasattr(os, "getuid"): + return + # On Windows, there are no "system managed" Python packages. Installing as + # Administrator via pip is the correct way of updating system environments. + # + # We choose sys.platform over utils.compat.WINDOWS here to enable Mypy platform + # checks: https://mypy.readthedocs.io/en/stable/common_issues.html + if sys.platform == "win32" or sys.platform == "cygwin": + return + + if os.getuid() != 0: + return + + logger.warning( + "Running pip as the 'root' user can result in broken permissions and " + "conflicting behaviour with the system package manager. " + "It is recommended to use a virtual environment instead: " + "https://pip.pypa.io/warnings/venv" + ) + + +def with_cleanup(func: Any) -> Any: + """Decorator for common logic related to managing temporary + directories. + """ + + def configure_tempdir_registry(registry: TempDirectoryTypeRegistry) -> None: + for t in KEEPABLE_TEMPDIR_TYPES: + registry.set_delete(t, False) + + def wrapper( + self: RequirementCommand, options: Values, args: List[Any] + ) -> Optional[int]: + assert self.tempdir_registry is not None + if options.no_clean: + configure_tempdir_registry(self.tempdir_registry) + + try: + return func(self, options, args) + except PreviousBuildDirError: + # This kind of conflict can occur when the user passes an explicit + # build directory with a pre-existing folder. In that case we do + # not want to accidentally remove it. + configure_tempdir_registry(self.tempdir_registry) + raise + + return wrapper + + +class RequirementCommand(IndexGroupCommand): + def __init__(self, *args: Any, **kw: Any) -> None: + super().__init__(*args, **kw) + + self.cmd_opts.add_option(cmdoptions.no_clean()) + + @staticmethod + def determine_resolver_variant(options: Values) -> str: + """Determines which resolver should be used, based on the given options.""" + if "legacy-resolver" in options.deprecated_features_enabled: + return "legacy" + + return "2020-resolver" + + @staticmethod + def determine_build_failure_suppression(options: Values) -> bool: + """Determines whether build failures should be suppressed and backtracked on.""" + if "backtrack-on-build-failures" not in options.deprecated_features_enabled: + return False + + if "legacy-resolver" in options.deprecated_features_enabled: + raise CommandError("Cannot backtrack with legacy resolver.") + + deprecated( + reason=( + "Backtracking on build failures can mask issues related to how " + "a package generates metadata or builds a wheel. This flag will " + "be removed in pip 22.2." + ), + gone_in=None, + replacement=( + "avoiding known-bad versions by explicitly telling pip to ignore them " + "(either directly as requirements, or via a constraints file)" + ), + feature_flag=None, + issue=10655, + ) + return True + + @classmethod + def make_requirement_preparer( + cls, + temp_build_dir: TempDirectory, + options: Values, + req_tracker: RequirementTracker, + session: PipSession, + finder: PackageFinder, + use_user_site: bool, + download_dir: Optional[str] = None, + verbosity: int = 0, + ) -> RequirementPreparer: + """ + Create a RequirementPreparer instance for the given parameters. + """ + temp_build_dir_path = temp_build_dir.path + assert temp_build_dir_path is not None + + resolver_variant = cls.determine_resolver_variant(options) + if resolver_variant == "2020-resolver": + lazy_wheel = "fast-deps" in options.features_enabled + if lazy_wheel: + logger.warning( + "pip is using lazily downloaded wheels using HTTP " + "range requests to obtain dependency information. " + "This experimental feature is enabled through " + "--use-feature=fast-deps and it is not ready for " + "production." + ) + else: + lazy_wheel = False + if "fast-deps" in options.features_enabled: + logger.warning( + "fast-deps has no effect when used with the legacy resolver." + ) + + in_tree_build = "out-of-tree-build" not in options.deprecated_features_enabled + if "in-tree-build" in options.features_enabled: + deprecated( + reason="In-tree builds are now the default.", + replacement="to remove the --use-feature=in-tree-build flag", + gone_in="22.1", + ) + if "out-of-tree-build" in options.deprecated_features_enabled: + deprecated( + reason="Out-of-tree builds are deprecated.", + replacement=None, + gone_in="22.1", + ) + + if options.progress_bar not in {"on", "off"}: + deprecated( + reason="Custom progress bar styles are deprecated", + replacement="to use the default progress bar style.", + gone_in="22.1", + ) + + return RequirementPreparer( + build_dir=temp_build_dir_path, + src_dir=options.src_dir, + download_dir=download_dir, + build_isolation=options.build_isolation, + req_tracker=req_tracker, + session=session, + progress_bar=options.progress_bar, + finder=finder, + require_hashes=options.require_hashes, + use_user_site=use_user_site, + lazy_wheel=lazy_wheel, + verbosity=verbosity, + in_tree_build=in_tree_build, + ) + + @classmethod + def make_resolver( + cls, + preparer: RequirementPreparer, + finder: PackageFinder, + options: Values, + wheel_cache: Optional[WheelCache] = None, + use_user_site: bool = False, + ignore_installed: bool = True, + ignore_requires_python: bool = False, + force_reinstall: bool = False, + upgrade_strategy: str = "to-satisfy-only", + use_pep517: Optional[bool] = None, + py_version_info: Optional[Tuple[int, ...]] = None, + ) -> BaseResolver: + """ + Create a Resolver instance for the given parameters. + """ + make_install_req = partial( + install_req_from_req_string, + isolated=options.isolated_mode, + use_pep517=use_pep517, + ) + suppress_build_failures = cls.determine_build_failure_suppression(options) + resolver_variant = cls.determine_resolver_variant(options) + # The long import name and duplicated invocation is needed to convince + # Mypy into correctly typechecking. Otherwise it would complain the + # "Resolver" class being redefined. + if resolver_variant == "2020-resolver": + import pip._internal.resolution.resolvelib.resolver + + return pip._internal.resolution.resolvelib.resolver.Resolver( + preparer=preparer, + finder=finder, + wheel_cache=wheel_cache, + make_install_req=make_install_req, + use_user_site=use_user_site, + ignore_dependencies=options.ignore_dependencies, + ignore_installed=ignore_installed, + ignore_requires_python=ignore_requires_python, + force_reinstall=force_reinstall, + upgrade_strategy=upgrade_strategy, + py_version_info=py_version_info, + suppress_build_failures=suppress_build_failures, + ) + import pip._internal.resolution.legacy.resolver + + return pip._internal.resolution.legacy.resolver.Resolver( + preparer=preparer, + finder=finder, + wheel_cache=wheel_cache, + make_install_req=make_install_req, + use_user_site=use_user_site, + ignore_dependencies=options.ignore_dependencies, + ignore_installed=ignore_installed, + ignore_requires_python=ignore_requires_python, + force_reinstall=force_reinstall, + upgrade_strategy=upgrade_strategy, + py_version_info=py_version_info, + ) + + def get_requirements( + self, + args: List[str], + options: Values, + finder: PackageFinder, + session: PipSession, + ) -> List[InstallRequirement]: + """ + Parse command-line arguments into the corresponding requirements. + """ + requirements: List[InstallRequirement] = [] + for filename in options.constraints: + for parsed_req in parse_requirements( + filename, + constraint=True, + finder=finder, + options=options, + session=session, + ): + req_to_add = install_req_from_parsed_requirement( + parsed_req, + isolated=options.isolated_mode, + user_supplied=False, + ) + requirements.append(req_to_add) + + for req in args: + req_to_add = install_req_from_line( + req, + None, + isolated=options.isolated_mode, + use_pep517=options.use_pep517, + user_supplied=True, + ) + requirements.append(req_to_add) + + for req in options.editables: + req_to_add = install_req_from_editable( + req, + user_supplied=True, + isolated=options.isolated_mode, + use_pep517=options.use_pep517, + ) + requirements.append(req_to_add) + + # NOTE: options.require_hashes may be set if --require-hashes is True + for filename in options.requirements: + for parsed_req in parse_requirements( + filename, finder=finder, options=options, session=session + ): + req_to_add = install_req_from_parsed_requirement( + parsed_req, + isolated=options.isolated_mode, + use_pep517=options.use_pep517, + user_supplied=True, + ) + requirements.append(req_to_add) + + # If any requirement has hash options, enable hash checking. + if any(req.has_hash_options for req in requirements): + options.require_hashes = True + + if not (args or options.editables or options.requirements): + opts = {"name": self.name} + if options.find_links: + raise CommandError( + "You must give at least one requirement to {name} " + '(maybe you meant "pip {name} {links}"?)'.format( + **dict(opts, links=" ".join(options.find_links)) + ) + ) + else: + raise CommandError( + "You must give at least one requirement to {name} " + '(see "pip help {name}")'.format(**opts) + ) + + return requirements + + @staticmethod + def trace_basic_info(finder: PackageFinder) -> None: + """ + Trace basic information about the provided objects. + """ + # Display where finder is looking for packages + search_scope = finder.search_scope + locations = search_scope.get_formatted_locations() + if locations: + logger.info(locations) + + def _build_package_finder( + self, + options: Values, + session: PipSession, + target_python: Optional[TargetPython] = None, + ignore_requires_python: Optional[bool] = None, + ) -> PackageFinder: + """ + Create a package finder appropriate to this requirement command. + + :param ignore_requires_python: Whether to ignore incompatible + "Requires-Python" values in links. Defaults to False. + """ + link_collector = LinkCollector.create(session, options=options) + selection_prefs = SelectionPreferences( + allow_yanked=True, + format_control=options.format_control, + allow_all_prereleases=options.pre, + prefer_binary=options.prefer_binary, + ignore_requires_python=ignore_requires_python, + ) + + return PackageFinder.create( + link_collector=link_collector, + selection_prefs=selection_prefs, + target_python=target_python, + use_deprecated_html5lib="html5lib" in options.deprecated_features_enabled, + ) diff --git a/venv/Lib/site-packages/pip/_internal/cli/spinners.py b/venv/Lib/site-packages/pip/_internal/cli/spinners.py new file mode 100644 index 0000000..1e313e1 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/cli/spinners.py @@ -0,0 +1,157 @@ +import contextlib +import itertools +import logging +import sys +import time +from typing import IO, Iterator + +from pip._vendor.progress import HIDE_CURSOR, SHOW_CURSOR + +from pip._internal.utils.compat import WINDOWS +from pip._internal.utils.logging import get_indentation + +logger = logging.getLogger(__name__) + + +class SpinnerInterface: + def spin(self) -> None: + raise NotImplementedError() + + def finish(self, final_status: str) -> None: + raise NotImplementedError() + + +class InteractiveSpinner(SpinnerInterface): + def __init__( + self, + message: str, + file: IO[str] = None, + spin_chars: str = "-\\|/", + # Empirically, 8 updates/second looks nice + min_update_interval_seconds: float = 0.125, + ): + self._message = message + if file is None: + file = sys.stdout + self._file = file + self._rate_limiter = RateLimiter(min_update_interval_seconds) + self._finished = False + + self._spin_cycle = itertools.cycle(spin_chars) + + self._file.write(" " * get_indentation() + self._message + " ... ") + self._width = 0 + + def _write(self, status: str) -> None: + assert not self._finished + # Erase what we wrote before by backspacing to the beginning, writing + # spaces to overwrite the old text, and then backspacing again + backup = "\b" * self._width + self._file.write(backup + " " * self._width + backup) + # Now we have a blank slate to add our status + self._file.write(status) + self._width = len(status) + self._file.flush() + self._rate_limiter.reset() + + def spin(self) -> None: + if self._finished: + return + if not self._rate_limiter.ready(): + return + self._write(next(self._spin_cycle)) + + def finish(self, final_status: str) -> None: + if self._finished: + return + self._write(final_status) + self._file.write("\n") + self._file.flush() + self._finished = True + + +# Used for dumb terminals, non-interactive installs (no tty), etc. +# We still print updates occasionally (once every 60 seconds by default) to +# act as a keep-alive for systems like Travis-CI that take lack-of-output as +# an indication that a task has frozen. +class NonInteractiveSpinner(SpinnerInterface): + def __init__(self, message: str, min_update_interval_seconds: float = 60.0) -> None: + self._message = message + self._finished = False + self._rate_limiter = RateLimiter(min_update_interval_seconds) + self._update("started") + + def _update(self, status: str) -> None: + assert not self._finished + self._rate_limiter.reset() + logger.info("%s: %s", self._message, status) + + def spin(self) -> None: + if self._finished: + return + if not self._rate_limiter.ready(): + return + self._update("still running...") + + def finish(self, final_status: str) -> None: + if self._finished: + return + self._update(f"finished with status '{final_status}'") + self._finished = True + + +class RateLimiter: + def __init__(self, min_update_interval_seconds: float) -> None: + self._min_update_interval_seconds = min_update_interval_seconds + self._last_update: float = 0 + + def ready(self) -> bool: + now = time.time() + delta = now - self._last_update + return delta >= self._min_update_interval_seconds + + def reset(self) -> None: + self._last_update = time.time() + + +@contextlib.contextmanager +def open_spinner(message: str) -> Iterator[SpinnerInterface]: + # Interactive spinner goes directly to sys.stdout rather than being routed + # through the logging system, but it acts like it has level INFO, + # i.e. it's only displayed if we're at level INFO or better. + # Non-interactive spinner goes through the logging system, so it is always + # in sync with logging configuration. + if sys.stdout.isatty() and logger.getEffectiveLevel() <= logging.INFO: + spinner: SpinnerInterface = InteractiveSpinner(message) + else: + spinner = NonInteractiveSpinner(message) + try: + with hidden_cursor(sys.stdout): + yield spinner + except KeyboardInterrupt: + spinner.finish("canceled") + raise + except Exception: + spinner.finish("error") + raise + else: + spinner.finish("done") + + +@contextlib.contextmanager +def hidden_cursor(file: IO[str]) -> Iterator[None]: + # The Windows terminal does not support the hide/show cursor ANSI codes, + # even via colorama. So don't even try. + if WINDOWS: + yield + # We don't want to clutter the output with control characters if we're + # writing to a file, or if the user is running with --quiet. + # See https://github.com/pypa/pip/issues/3418 + elif not file.isatty() or logger.getEffectiveLevel() > logging.INFO: + yield + else: + file.write(HIDE_CURSOR) + try: + yield + finally: + file.write(SHOW_CURSOR) diff --git a/venv/Lib/site-packages/pip/_internal/cli/status_codes.py b/venv/Lib/site-packages/pip/_internal/cli/status_codes.py new file mode 100644 index 0000000..5e29502 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/cli/status_codes.py @@ -0,0 +1,6 @@ +SUCCESS = 0 +ERROR = 1 +UNKNOWN_ERROR = 2 +VIRTUALENV_NOT_FOUND = 3 +PREVIOUS_BUILD_DIR_ERROR = 4 +NO_MATCHES_FOUND = 23 diff --git a/venv/Lib/site-packages/pip/_internal/commands/__init__.py b/venv/Lib/site-packages/pip/_internal/commands/__init__.py new file mode 100644 index 0000000..c72f24f --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/commands/__init__.py @@ -0,0 +1,127 @@ +""" +Package containing all pip commands +""" + +import importlib +from collections import namedtuple +from typing import Any, Dict, Optional + +from pip._internal.cli.base_command import Command + +CommandInfo = namedtuple("CommandInfo", "module_path, class_name, summary") + +# This dictionary does a bunch of heavy lifting for help output: +# - Enables avoiding additional (costly) imports for presenting `--help`. +# - The ordering matters for help display. +# +# Even though the module path starts with the same "pip._internal.commands" +# prefix, the full path makes testing easier (specifically when modifying +# `commands_dict` in test setup / teardown). +commands_dict: Dict[str, CommandInfo] = { + "install": CommandInfo( + "pip._internal.commands.install", + "InstallCommand", + "Install packages.", + ), + "download": CommandInfo( + "pip._internal.commands.download", + "DownloadCommand", + "Download packages.", + ), + "uninstall": CommandInfo( + "pip._internal.commands.uninstall", + "UninstallCommand", + "Uninstall packages.", + ), + "freeze": CommandInfo( + "pip._internal.commands.freeze", + "FreezeCommand", + "Output installed packages in requirements format.", + ), + "list": CommandInfo( + "pip._internal.commands.list", + "ListCommand", + "List installed packages.", + ), + "show": CommandInfo( + "pip._internal.commands.show", + "ShowCommand", + "Show information about installed packages.", + ), + "check": CommandInfo( + "pip._internal.commands.check", + "CheckCommand", + "Verify installed packages have compatible dependencies.", + ), + "config": CommandInfo( + "pip._internal.commands.configuration", + "ConfigurationCommand", + "Manage local and global configuration.", + ), + "search": CommandInfo( + "pip._internal.commands.search", + "SearchCommand", + "Search PyPI for packages.", + ), + "cache": CommandInfo( + "pip._internal.commands.cache", + "CacheCommand", + "Inspect and manage pip's wheel cache.", + ), + "index": CommandInfo( + "pip._internal.commands.index", + "IndexCommand", + "Inspect information available from package indexes.", + ), + "wheel": CommandInfo( + "pip._internal.commands.wheel", + "WheelCommand", + "Build wheels from your requirements.", + ), + "hash": CommandInfo( + "pip._internal.commands.hash", + "HashCommand", + "Compute hashes of package archives.", + ), + "completion": CommandInfo( + "pip._internal.commands.completion", + "CompletionCommand", + "A helper command used for command completion.", + ), + "debug": CommandInfo( + "pip._internal.commands.debug", + "DebugCommand", + "Show information useful for debugging.", + ), + "help": CommandInfo( + "pip._internal.commands.help", + "HelpCommand", + "Show help for commands.", + ), +} + + +def create_command(name: str, **kwargs: Any) -> Command: + """ + Create an instance of the Command class with the given name. + """ + module_path, class_name, summary = commands_dict[name] + module = importlib.import_module(module_path) + command_class = getattr(module, class_name) + command = command_class(name=name, summary=summary, **kwargs) + + return command + + +def get_similar_commands(name: str) -> Optional[str]: + """Command name auto-correct.""" + from difflib import get_close_matches + + name = name.lower() + + close_commands = get_close_matches(name, commands_dict.keys()) + + if close_commands: + return close_commands[0] + else: + return None diff --git a/venv/Lib/site-packages/pip/_internal/commands/__pycache__/__init__.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/commands/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..72ad052655f8a2c403679fa351bea9afd06f86d8 GIT binary patch literal 3042 zcmd5;NpBoQ6z**n&lWo|Nu0Gq94C|510gHHK!U9Zi;zTe0@7%trrfV)rg3jnb;rzT z=47sL=HNpjapA^+UsG33`~@T=UR6&!4tR2AMqTx)y6US}-}~xSlX|_P;qS-uOItrT zH0=-BIQTn;jr;iUMP1XLYoN6?(82KawvM&w8-dw2b=hb6R#0dcf?~TEl-ecLSMbZh zOnXMxs0l?V?HcV0tw0%Opt5VCRfQVVmDPYFFsrONI10yxm*I-Cns61aDQg*4prx$$;C;BRtPkJ@+*H;rxD9u9 zO}M)^+pf|gtz66qLBDFsI->N6V-{a5q6`Y9Ym1&)QL&bU$$MJaPCO7Wt*qC3>ys3;hHVS z3lqu^sFknY@^^xRr5T`Vye*&FKw}yL4PB37xEH4_5`|r_mol6b zg<^i~U^8EI=}Qty-TRSCd>dtM_xxxJO*{y%C%1;vV#q0BZeP?lRh^?QWKH|&;OT~p z(tZfv!U#c5kP%tsFqcr;F?AE=7oI`sDDL$#w|DxKqK|U$bVv^=`o3M;kW~(OBZqt= zelLjU6G?2BMM3T?1_CEaf~Q4Mc_C_FOK0*07C%cpA2J6~p%QNprR)viPFGu>@V=;i zj%AK_5e+;J6g9y6l-p5v-#^K`_d+^&VX6WG%uy=*a}p=BbLf=^cAxq&WqFFTQ;x?? z#>>rem(pA|X*vr)x6+=dt;;HhUi!}&LFjJkD{wWThbi_gJfL651C}}B356*AJ?J2B zHD^UB&qw9`1UK_KNfjq)#!}h9;_^HfP&at~ikZkoaiZda5|k*Yz>7i_UQ5NKf{f%; z7P1{%(iu^oP{kd<8vw5ZOQv&C+}CRBxRwCck%wOj8*}kFYw{_ut>C#wxD&) zu`xEsR-(T&M#d|BTu97OVPx(avyh}z z67|eVf-BR9@e2?3#RAoJ`G0bJPG)nsE55#%|)UzrI-G?Z5!g%uU3mD_i}^|;H2@?B^D0`27S z={VTuC63dI2cqFBzMRR+KCa5uXO-2^EBK!`*lp~akixE_{YD5)?6B}z!-va}>Jv)~ z^s%mEpk5lUw6QkQM_OXOv|ec#LJTQujSSEiv`r1n>}guVQ+a%3C~T4@(TW=}hFP!0 zq-gL=Q{I{|$?xRn}`5(V9`I7`poZZ4~~O*6+uk9j*NXAVkGp literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/commands/__pycache__/cache.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/commands/__pycache__/cache.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..785ed5ef356044a371fee1c87b4fe87b183efada GIT binary patch literal 6169 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/commands/__pycache__/check.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/commands/__pycache__/check.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..02c436b325ebade2b8044399819694752935fcc3 GIT binary patch literal 1558 zcmZuxOK;mo5MI71igKM4Fyi#Z9uh!7P2>=yMNt$jl%N;G1*|3qRt7JLjF|3 z?l4jK3MaopLJ8G!5~;7AYlR-^n&OSzD9p(0cr&*OJF+|8%ALZE+@crtI@!*>q964O zKk_@-$p^(=w5JguzrF+eziH8(ZwPg1?-ijvu-8U(muh1&^!~!wzbL zGcNG!jH;qYN;=e~_5Aeo+f(U`UyMf2$79soN#~GW#&wcjCNqdR2>Ef!AQ7;ui_ckA z#97HjlIK8iQ~#P}Xj3(!ZbYhr?~W}bk5CIF(kO{^sznCXBNHsJ!8s)0QsWncn$&t_ zMm=idF&ycSR6d)Gm!G}_mYv@O+sMHtQ69{bD+to6s1uP*a|kHZP*Nz<40yOa@PckU zs97}&zOQPLRV6~lm%U!v=;xdwQ-v4Ct;2WTA6E2Bf=VEfgyI*$@0+y9^jwB zqRAL2{*&N(o~833<3U-8H#mk&!*eZy)~SF}bbixD1UFT4i*sidEW$QUrU43gU=;>z{8Bh6A ztxd2S1h5j#u?SUr@k!T8VSR(4n(_eS@Fz%!?rFa6YDhJG^RxeU9i_Ru)pRSb-JY+R zXuI6sZG#ZEI~jV?jk{yTvGn4&sA!V|@_rmInj}|Ppyb3ctx{yHhGRoB9TQ-xxTV1b zlLltZ?kk#oP0BU)$IAO<(tn Fe*gvfsQ3T? literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/commands/__pycache__/completion.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/commands/__pycache__/completion.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ef68477fd6abcdd5dfb13de31b2ac6f01d6da4ce GIT binary patch literal 3131 zcmai0-EZVX68HCbW|Ayl2g~tseIa*>IeC_Vgb>=SF3jf8>XuEE$$~JmvK)6Oaq!sQ z?sk@SGEdppMdE!Ql1Kife&q@AcyGKwm1iDcYE)0PVASh@4r3!V24-OD$TL%GU1dW=uQ+Ln| znl=B15a1Zmr+_W z0hDz=5fb`FHy;e5j3U{4*zKT_+oQwee?d;tIK3*xgLgJ zZEW4`tu8Jd9pUU~_|5x|hQmeDzp(h++PJT!ySRFFX-fb3n$3Hg;o8IPjSv^yU*BF| zT_H;=hu+2xk!`{#rbmzBCbMSF9+~r&l0d>j#Lh1$YYQ>eBM^ zNUy&_JnuSmuf%m^X64aEc&|k_mMQW7`=^MOS0ftkCSw0Q{uly0gAO5r!BM5(%|shn zhU3H>Ns|mu)FX?F*DtAKj4WTV_dz80QCB9TBoo9>i0}VFxAe#;I_og^0L6dqfmzB1xarX4xTx&Wx>ZRvt~2W6qxE&oq>GBeJ+0UWU(GBz`;_ z%buyMok;8}vx3G#yko3Dv(Ka=ega&kVHFGvss|=D0*ji|dZAOBI?t@YW)5pG_f3s8 zY2$^7)eg8VYC>gesh7Kxf&>(vQuWaqfm&5Cj>QT&MCN3Nky0>9cJnEFyfvt0o$b0h zawbcj#Sk}>2Wc0+E_|X7&9Qc%9q3f226~A;(#CT~Kj&jDHlZ5Zw0(gORT=mTz`rr! z8>c3H3H6;BSk+-aFF&Xp-$(2!!{1SDA#=_kRx=@a1B@%XF2mJ3>jOB-ssBJyR__hh zdX{pcx_&6TUaKt1gj5#7QrW%_#{&8*jvK4qzE&5CfjfA9Aim3+D1NQs3;U3S+0{=;ZrMo|B{0-3Y>rVI6{zH%w{V2;K z(O)ZyyOE6g_p#{px7ncRL+bivRz&f)jQUUZ8B6_-KRHN5EGnGqhe;+G&p><}2m*=m z@2gWhRqd&7;$tu>K7>Zo9o?9|zdG*!88@qUx)ZfPVaRo6G($QxMmrVCiuj)3a7EB! z6K#zj2YNi;I?5^_q;{&GX+sm^?3pHwWAjA6tDWdW>sUW9kIh4k2huvVLC!%AHP4KL zhICIfYCYG_^r0=AvUSinw(D8@xpAWFnr!zpId?FBxOQkigZQVtXuDE1srRoMlCscw9>)>}Wn zNPt>yiRI6F4>4BABoHaq0;EcND;cnL*A3 zNVb3_5J$~$^;h(kZt1W8W|^<)mf`3NKvjRa5=yVF+%U|d0SiOb3d2E8%M|IkFnnA_ z>3F6QhBS|X{c5t8VU6PKahX65VR6XcM1L?8I0iZFQgUSi3j7xGrry>RI?3_+yaJ!V zlH`Juma*`5&Gl~Zf1$)bpiwU5(Wr)?cIC*Y1^n4YR^Ek_?@Us@6Q@ZBiXm3dIwLuT zrMf~0uCcNdAO}4(nrZbyuI$ S=M4CuwQQqlw2fb!_kIU;$~@ix literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/commands/__pycache__/configuration.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/commands/__pycache__/configuration.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0260dea1a8b8fec9dc99dce20cf94cf13d978021 GIT binary patch literal 8312 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 AjsO4v literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/commands/__pycache__/download.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/commands/__pycache__/download.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..742d93fa8e18eef30f4f9f470876c31880a97f8c GIT binary patch literal 3975 zcmbVPUvJ~a5$8Wq6h+CheP^HVatRUOu2oT~N!p}E;9jrrwMCP|A*ho)Fg`FecWqI} zf458eB13wq@6|v*KpyOu0{u#hy!ENyAV|}qGfPUAjbzi?Om2C%WS<@1PPV)) zRiVnoHobGHdOLqmNSipX72?qLneN>s>b}zN`~&u?JnO5%{5*(D%7HSTM!bNp9VR5p zizrL6cOwa2P`?P+F)jRjQjD^+uZfL6(U)b!XhPFsFH4djCBk_X6(c{4X^@sV%xvy| zwzv1Y{e2*}aWcD_;ukCkUr^T9g-uglGU}6viEf&)B#5I^>gPc*0*x#xsGpTZUgFL= zpVB0M0?UR)#wH<}u>3TDc?>V#g@!8Vd`}~)rxVRHh)#^JRnj2lYr|_$lQyYETRRH1 zN%L!+SfusZI8(hg(ZM~oSbLJaO5-dbwROQ$RZ(mgp1Huy!Gz$La`%X3$%nQS4%|;B zpZwANG5EvHiV3H zgLokUS4j^c&Pa;C4svvb~z$fmjVB!{_P?|Dv0~ngc)TQZ3#Ih8_1I34Q zu@WVfvBAB$LtXa)Xg+qosDtjgySucBD=$5Azo=b4kWL*e#t(;;&YPMB?3%L5qW?$H z?n%fO2LMO&$o=1o?#9=S3q$z_hu5csC;qd=V40hY79~qV@YLebfI>XlgO_7aPL;88 zp%&VOeyLol>J@LS@QoGTT;ZE5ytTr&R(N}bZ?Evq3g21byDR+K3g27d*RS}oN>rj@ zN@GG78{3a2z(g5Lb0Eu_HeWR;FBjL<*NkW;9WAER@iYSG2*ahLEVc!r2t|FQV zErOGPi6)^(K^Ygq7|}Rqc7oUKL$HWVL_164$(-rrj2=-oXLZg(p+leO)_VO>z(*9;!E9xe zbN>+byn*Vr>;MIuIc<{lm#t{$sDasCf zI0VYlAU+7I3y~kpBVw3?udmLIKfv6542`1pe(0x}s6df{A2I)p6qt zWsSnDXiT7sCdy}eVNKODb!I?^c5ciXFsfZRXONIHv*sGp#cAiwWhqFX?))folJP%Y4g6r9&g?0wW~ z9$^qO)5g7K$|r`n6XX)^*}`?UT9$@N4^}i#t$efbjr^ z1^udEEmYURNfv;QEJ(rE*DFvib|jQ6VWz+E)NgQZroW&zpnvLSq`!}|qN7z6ABY~-n8!7Ex2F7;hxfLWY9#$Ic_E3vk0E2o99=aC8L zrGrpHVb#2gQ*~CR9|OU^ghtU#-PCN&QEg}~fS?MRjPK2+qiL#ys(+bg58&wvw2(Fc zwB~&PT>msJTkFE8u4>n>srIzf%~dFa)%%XHd>?)0`@;79BqL>vwB!3P%OI{LP2VS3 z2;Gg6LmsjBV7sh|4OUAG5l`q4b3zAWvoFpMLa1l}7r`iEElwW=_`e{%?& z41~7)kHt(-FD(;q-W&+ISCkyaLRBH-MyzN9O+(aH|ND}OBJNyQR2C8Z??~WYlNnhh zsEo&z-B$x8S|Lu!d}~3LJq0fT+B}zDL6-r8p8anw7uIfdq>r%H;dh|1R7-VK2ja|u Ms}b8Fw{5^i&^rz{~l&76~MWl z6+*&0%1cr=vZyO94L0hs#1+x(=G~2rTbrA}`a7J`jsiCnlCWYsYwpj)2l{d<5>&R0 ztZOFHh=5IAY`2msrzslceZNa7%k}BY&mt-}KuWC?5i7L`N*!XSE^$(ixWs#gh);s2 zZtBy3hIDYzq7ez7Ib=X0kPe9pHyf()ZR6YA@9t3)!}CQen^wj}B_w8ylDNV7eLSNA zL@}oi+Je)PR#L<}H7~K8MrPYW3v(JXxC`ur4LHuRpb1!`l_+HKkjA3sda>q&@~PR| zoj0#IzTEJ77JoC3>9-U6&sF+JUcY)(?29Rck8;k(aBq_i4#DG9j+UaM`2ma#7~&To z2iBgohX^7zafmy!h^GT{7@(7tP=|yJ$%u@}${~PfzT*s8HPSVZdcE`rN&Cn-wvN$4 zYn_}0t#d~%dFjZL{xLd6%K z8LcSCvZ!WpZPGuDzuqlG+$RE3SjF2kZUv;RY?&+?uq2C;is{5tE}=q#Q@Jh#6%e|E zK}Q88mG~j%%H5@`fm^XIND@}(m?^J+MMBn`W|Ft`c6axaogOd`3ocvCX!Q_of@Qpm zMLc8mHfAx-b1KA@nACAq%ek-fMYgX|_5x<76PK?84)|G3&S`QUNarUB+y;Epw7c>} z#r99EEr5J#4PvVG5&$rrc3zS|VW_At>=6cTSUssQ{(lATDp%eQ(-d?GnHC*I+8d6GP?>tGV85c*RF zITR|w#Bh)yZd%VkmuS{txeFc2)Uk5+>Y`HN&0F`fFF*ZwGaVU~xeLl~FxL?~t4on>=CEnHPtY<<);H?hQ9pXuapeND?|3p!lV zRys(OB&O3P*WTYNL@qkLwv`o?q`U%kjZ{Fb*y`gwZT8jh^fuxm94Nj5Vj&;dr$5{N z-5)PWZ2J#?xHSLE4^~fh*e(kHvH$W1i}k;Kf7R|TKGz?oOQ%j870kPoaxtF?z5*WP zj`m~zc<^5Iq6Q|?lIRI~>>QvyTfBVW968c8y#(!f{9QeV6;Df~e-s=*F99wD*#Jfa zV+dmeV|<`BR|q-`Zd%`-d+f?Hd#gul2QINMnC|r8o?M4s;@p`8YPi%oRAlNds{!t6 zpdsC}p2mStVIgXUp*KS|0m%Fna9W{ga#lI;q2eJ-`6Vs$+lGK1e;p=iI7f)+fptFL zrTP7A0k1hwc%XNm(d2?AI&I1|_#2-bo0TJp3gSy zo{UtOWfd-ImZ>Py{Eo#0JWErV*5PPkF52YHidX~Y*oZ?dOx8ZDVYofsc zk(69H0B(L=%T8T3oc5cKfM_%c{r4zDuJ78ez4D%sPuBP~kg5>C*B7KVt$exPK=U?7 zq-#(=(?$JEb5``3dG$Z?={9_uvw4AW4OsO*O3+hfD?knUyh%d(+Vhs`#(X^BU(mF# xQIl+S>3OYI7EDaxFi3ijB@G{QtN#mw3UBn`{y;Y~p__P!Mvy%i{m%}ae*v}$=js3e literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/commands/__pycache__/hash.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/commands/__pycache__/hash.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..49117a4178bbe94327ee6d5114f16dd4fe0080ce GIT binary patch literal 2124 zcmZuyOK%iM5T2g*J~5DhLlPJijIt5CB9RhB7C|A#36YSIY(tdEqEUOgy*p-J?(V^1 zvp$(C${*mcK1KOUea$I9A-RyMS!0%n9!*VkclD#bud0T2I!y!Gi!0Z6{%{TBFYGKf z8#>>@D_??O1|z8v&c7rib>9q4_?oGe*`ZBv&Ptuk4c%I|Q!n#Fzt)|!ku}3+)(Ts7 z-%Z^;&GKfk-B{#62+sUQe~xLJaMs| zqIC;Kxq%1)IwZ818QRPW9cDA|PUQg&#xNHYyP%~-Ow*vG@e?|N84-_@r+m?Y_3|W#<$~{5iQpN}l?-;1ln1H^SOMcDr;6^Ryxu9vrJ`vn2X$|9X{8j!DEOr) zRZ`^gac~Ql-VO$X!FJ7n;HnaNOcuaFy$$agymA%9)Yvoj2qVm7mNJ>GEauE?=FS{t z9+P9jycZrpD|hBGAFYo~j1xeou`x0GbkgegX*w!^k#VLQZ&XLBLh#8o@PCff=@fbg zK&%Eu&Jn-g4kzY~pyz0tajCQykBcPcQoA%p&$P$*F0E3f?J-YFfj;zn?Z+95z;~&e zl+_y83Lhqg2SU5Mg~%u@+AES=yCoHp3w<6yFpox}s7j1c$%Hf@|ybCl8?<32@ZJw3GGAa92j)Zg8KNxeK_P_diFOjjF;M_1ua>Yds z=J7n}HMzJDfP;mVJxhBh#A}<1krYU4 zY~fxf&4Dk%QFDD8l&L8%AcHfa%suOv5JN$fPsyHhXid$##^dEfTe*x(?Wv_alt<@@^lU$;sD9!Hgg_}7+v2INV_xDWzwAv!3q#_3Lk zI7G#6guyDH+8I4ZAP(X(iYqA4T-zm87U_y`9rQRSb4BF}*^h)uf0HeKQablq33 zH94~g7ufdN+K-}~W;}{?Gm5f;RVnK2DB7=RdNSih5i4RCcIF-L1>y|65?%L+?b&eKZnqxqS>hVn)X>!2;nuI) zTik8KsDd11c0_==?jf)>v!^z)x_|j6_!roQZ5&y|$d^7h zQa?X~1WV@_GuWD3-K=Xwpk5~_OGc1`^Qwjn4YVnCHhQkMi;_bsB714Fqph4D zhz49tyH&}k;<_>Bzs^?!p{K5C@1z<+^1@Q>)Fu4?Kz#xmeF<+3lwr0>leEcaMBsRD zS=_{PytEjNl6)ktV$X-*pQkj!rd{={#JQT8%aDPC(+nKMX)@TMl1C@0DDVfN-(dvR zRaFwqpbX997Q<6tdV9M{B~XIV8L+}iQ`a25{4T2uDngCYJopgYw7xb3Lq%V literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/commands/__pycache__/help.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/commands/__pycache__/help.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c77cfb40c6604f72bfab98a7d03bd2801fbf3503 GIT binary patch literal 1296 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 TF%K7OATw;heW+GFM&0~3-xb^6 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/commands/__pycache__/install.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/commands/__pycache__/install.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..cd32b674bb59fc9bc663b0e740b11468566d1695 GIT binary patch literal 17687 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 N50#>!&hJ(h{~NBOSC{|* literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/commands/__pycache__/search.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/commands/__pycache__/search.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..687c3e7dce9df4704e8c10a62b306729a1d72489 GIT binary patch literal 5314 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/commands/__pycache__/show.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/commands/__pycache__/show.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..12c34f78978afeb5832da789e0aec205e09c7bc1 GIT binary patch literal 6084 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/commands/__pycache__/uninstall.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/commands/__pycache__/uninstall.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d24a2e36bdffc523251900f4c209eaeb44e6f552 GIT binary patch literal 3092 zcmZuzUvJ~a5$BQ=Nl}vj-sLV$n`|$+Bq}036hRWWhajylD1u%O0UQ@7>wu=UD~Ue- z^X}4$1^K0ySAT-0fc=(!i9Gg0>}#L;*2kg^dYxIxvd#%@j%J5D!`YeN%rNP6LJO{o zH{L$_d&jc=fs56v0gF%Imfr$l79*Jz;jf*M+>UI5ypuV(8@YyevqtVkp5Ysrp9fK3 zcrR<_VHD=AsAblE*3LUo$M8Y6maj+ahHqvY`DV0f_%Pebx1;U+PISktTiM zaqIFPzkfxdSAT1nhN{%)D)Nx{0d-rnOShH3Ec7{Al!-wvm%?3 z$YFNmGKaa}5Y}Mc*KX9{9`||hs>Pek|HfefYl1Xn4#YOp8~eq=)kTbw-w?|RDO}4Z zv`Plgk`b5v&^!QVX)0-QlyRy`T3=hBc_|fLnB(k5jsC7ECk5qS4S0nI16{#)=Ei#T z^ICAqAfdHNGr81SF*Hflm>wQhXKGv)RB}~U{p##`!{On3bTUo{W8)m98Bb0*J>p{s z9W6?lbCs|}CFm>Tii;dF1R9B=!!+ZPPB=KQbh~fN^yuC|q?Mu*kyI5I@@4})I{Oi4 z7(eA%SsfnE^{4v_ZyrL5NAyqS{NP{GM~h&7O#A)$R!VR0=?VI16=%jzqhQKFKmbHB zfIKZPKigiYYB>ZovE}!%%wSCvD?rt<5GbK0|b@!86PIFNBfxZ(?n=@%(DuP za5io9dS_f}2T3SZDR`_z&8NS7To&&rn#gB#SPD8Qi(x8qQ+>1?u0Wgdj2r0oyN=j~ z0E;_F?jgb8cU>I}au$Q%@P>pL4!!bB;S0SD0OLa81}yE7DC-J3fGc@6{F^1-02}{F zc6Sc;VV68eiXxE*zpkps0NjHoC3LuhFL+)ZK<)MF0x`r{Z!+dQ>wWOiaViILiq8(> zv;c$`uzfJ^g7RQlpHMTpb>o_R3*IRo0I`Ti?3+K^{Q(g0Db2#P$-LE@2`#LUxePtQz=v@b_ zW67+u<};Ut;B#}<6yMF7mm60Wc=w&!d=9^A3yP_QwHu_egt5Zebnmm`6vh@?ErA{S zP|$Q#06ZD(nKD@>53p&b8g$VLCWfRq?OxJ`lCTA)Q~Pp0_NKr1V_8GpKv%|cqtNl7 zIl`)h2Dnms*cqoA^j*n0eSqB^>xNG42VL#J68!F%xpbBmBOFz8#M`=^)T)dZMWg*w zE{;mcyW4tu#8tc~$9Un4XrXJJ>j1=Hk!u%EA#j*!FDpkQF0_y18D1ndKq?S7qKyRG zn}E+6*a?Ay?*QFg21ndSd2{YSs?M~B(Mpx@Q7Hh@4aMuoV|>J$NFD--HX#Z!hC|$# zdJp8<0l5yarJ;j5yqVt7=5lLXC29=Q$Q19K(7AG5{0bQPIS`A4wo3w2UGD!p*CQLS zwjKL>&kI57y$Btop5u`%0#8Ut+!x*pw_&7i8)Tplnl4!K$n?(s^}M~VMEH*Bwsa7i z51=^KVT{48GY)(^j!)_&!&AV@k7HI2fN9hc2D6SgYERN@xcT;-`hzU(A0_bVwWt7r-?92&im z`u@w-ZoX6u?4r$=AH$0bFmKxic^|3)qF4`L#z+HsgWlUOFsJS3(6{H1ZbHF4G58lB rqUSv%80(ezn{-f+>EO{kzaQh|k%;|(v`O2BKeB-w{B5{xJ9PdJCJm2! literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/commands/__pycache__/wheel.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/commands/__pycache__/wheel.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..13710794cb3680b0fa20b3325122346b8da337e2 GIT binary patch literal 4842 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 can be a glob expression or a package name. + """ + + ignore_require_venv = True + usage = """ + %prog dir + %prog info + %prog list [] [--format=[human, abspath]] + %prog remove + %prog purge + """ + + def add_options(self) -> None: + + self.cmd_opts.add_option( + "--format", + action="store", + dest="list_format", + default="human", + choices=("human", "abspath"), + help="Select the output format among: human (default) or abspath", + ) + + self.parser.insert_option_group(0, self.cmd_opts) + + def run(self, options: Values, args: List[str]) -> int: + handlers = { + "dir": self.get_cache_dir, + "info": self.get_cache_info, + "list": self.list_cache_items, + "remove": self.remove_cache_items, + "purge": self.purge_cache, + } + + if not options.cache_dir: + logger.error("pip cache commands can not function since cache is disabled.") + return ERROR + + # Determine action + if not args or args[0] not in handlers: + logger.error( + "Need an action (%s) to perform.", + ", ".join(sorted(handlers)), + ) + return ERROR + + action = args[0] + + # Error handling happens here, not in the action-handlers. + try: + handlers[action](options, args[1:]) + except PipError as e: + logger.error(e.args[0]) + return ERROR + + return SUCCESS + + def get_cache_dir(self, options: Values, args: List[Any]) -> None: + if args: + raise CommandError("Too many arguments") + + logger.info(options.cache_dir) + + def get_cache_info(self, options: Values, args: List[Any]) -> None: + if args: + raise CommandError("Too many arguments") + + num_http_files = len(self._find_http_files(options)) + num_packages = len(self._find_wheels(options, "*")) + + http_cache_location = self._cache_dir(options, "http") + wheels_cache_location = self._cache_dir(options, "wheels") + http_cache_size = filesystem.format_directory_size(http_cache_location) + wheels_cache_size = filesystem.format_directory_size(wheels_cache_location) + + message = ( + textwrap.dedent( + """ + Package index page cache location: {http_cache_location} + Package index page cache size: {http_cache_size} + Number of HTTP files: {num_http_files} + Wheels location: {wheels_cache_location} + Wheels size: {wheels_cache_size} + Number of wheels: {package_count} + """ + ) + .format( + http_cache_location=http_cache_location, + http_cache_size=http_cache_size, + num_http_files=num_http_files, + wheels_cache_location=wheels_cache_location, + package_count=num_packages, + wheels_cache_size=wheels_cache_size, + ) + .strip() + ) + + logger.info(message) + + def list_cache_items(self, options: Values, args: List[Any]) -> None: + if len(args) > 1: + raise CommandError("Too many arguments") + + if args: + pattern = args[0] + else: + pattern = "*" + + files = self._find_wheels(options, pattern) + if options.list_format == "human": + self.format_for_human(files) + else: + self.format_for_abspath(files) + + def format_for_human(self, files: List[str]) -> None: + if not files: + logger.info("Nothing cached.") + return + + results = [] + for filename in files: + wheel = os.path.basename(filename) + size = filesystem.format_file_size(filename) + results.append(f" - {wheel} ({size})") + logger.info("Cache contents:\n") + logger.info("\n".join(sorted(results))) + + def format_for_abspath(self, files: List[str]) -> None: + if not files: + return + + results = [] + for filename in files: + results.append(filename) + + logger.info("\n".join(sorted(results))) + + def remove_cache_items(self, options: Values, args: List[Any]) -> None: + if len(args) > 1: + raise CommandError("Too many arguments") + + if not args: + raise CommandError("Please provide a pattern") + + files = self._find_wheels(options, args[0]) + + no_matching_msg = "No matching packages" + if args[0] == "*": + # Only fetch http files if no specific pattern given + files += self._find_http_files(options) + else: + # Add the pattern to the log message + no_matching_msg += ' for pattern "{}"'.format(args[0]) + + if not files: + logger.warning(no_matching_msg) + + for filename in files: + os.unlink(filename) + logger.verbose("Removed %s", filename) + logger.info("Files removed: %s", len(files)) + + def purge_cache(self, options: Values, args: List[Any]) -> None: + if args: + raise CommandError("Too many arguments") + + return self.remove_cache_items(options, ["*"]) + + def _cache_dir(self, options: Values, subdir: str) -> str: + return os.path.join(options.cache_dir, subdir) + + def _find_http_files(self, options: Values) -> List[str]: + http_dir = self._cache_dir(options, "http") + return filesystem.find_files(http_dir, "*") + + def _find_wheels(self, options: Values, pattern: str) -> List[str]: + wheel_dir = self._cache_dir(options, "wheels") + + # The wheel filename format, as specified in PEP 427, is: + # {distribution}-{version}(-{build})?-{python}-{abi}-{platform}.whl + # + # Additionally, non-alphanumeric values in the distribution are + # normalized to underscores (_), meaning hyphens can never occur + # before `-{version}`. + # + # Given that information: + # - If the pattern we're given contains a hyphen (-), the user is + # providing at least the version. Thus, we can just append `*.whl` + # to match the rest of it. + # - If the pattern we're given doesn't contain a hyphen (-), the + # user is only providing the name. Thus, we append `-*.whl` to + # match the hyphen before the version, followed by anything else. + # + # PEP 427: https://www.python.org/dev/peps/pep-0427/ + pattern = pattern + ("*.whl" if "-" in pattern else "-*.whl") + + return filesystem.find_files(wheel_dir, pattern) diff --git a/venv/Lib/site-packages/pip/_internal/commands/check.py b/venv/Lib/site-packages/pip/_internal/commands/check.py new file mode 100644 index 0000000..3864220 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/commands/check.py @@ -0,0 +1,53 @@ +import logging +from optparse import Values +from typing import List + +from pip._internal.cli.base_command import Command +from pip._internal.cli.status_codes import ERROR, SUCCESS +from pip._internal.operations.check import ( + check_package_set, + create_package_set_from_installed, +) +from pip._internal.utils.misc import write_output + +logger = logging.getLogger(__name__) + + +class CheckCommand(Command): + """Verify installed packages have compatible dependencies.""" + + usage = """ + %prog [options]""" + + def run(self, options: Values, args: List[str]) -> int: + + package_set, parsing_probs = create_package_set_from_installed() + missing, conflicting = check_package_set(package_set) + + for project_name in missing: + version = package_set[project_name].version + for dependency in missing[project_name]: + write_output( + "%s %s requires %s, which is not installed.", + project_name, + version, + dependency[0], + ) + + for project_name in conflicting: + version = package_set[project_name].version + for dep_name, dep_version, req in conflicting[project_name]: + write_output( + "%s %s has requirement %s, but you have %s %s.", + project_name, + version, + req, + dep_name, + dep_version, + ) + + if missing or conflicting or parsing_probs: + return ERROR + else: + write_output("No broken requirements found.") + return SUCCESS diff --git a/venv/Lib/site-packages/pip/_internal/commands/completion.py b/venv/Lib/site-packages/pip/_internal/commands/completion.py new file mode 100644 index 0000000..c0fb4ca --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/commands/completion.py @@ -0,0 +1,96 @@ +import sys +import textwrap +from optparse import Values +from typing import List + +from pip._internal.cli.base_command import Command +from pip._internal.cli.status_codes import SUCCESS +from pip._internal.utils.misc import get_prog + +BASE_COMPLETION = """ +# pip {shell} completion start{script}# pip {shell} completion end +""" + +COMPLETION_SCRIPTS = { + "bash": """ + _pip_completion() + {{ + COMPREPLY=( $( COMP_WORDS="${{COMP_WORDS[*]}}" \\ + COMP_CWORD=$COMP_CWORD \\ + PIP_AUTO_COMPLETE=1 $1 2>/dev/null ) ) + }} + complete -o default -F _pip_completion {prog} + """, + "zsh": """ + function _pip_completion {{ + local words cword + read -Ac words + read -cn cword + reply=( $( COMP_WORDS="$words[*]" \\ + COMP_CWORD=$(( cword-1 )) \\ + PIP_AUTO_COMPLETE=1 $words[1] 2>/dev/null )) + }} + compctl -K _pip_completion {prog} + """, + "fish": """ + function __fish_complete_pip + set -lx COMP_WORDS (commandline -o) "" + set -lx COMP_CWORD ( \\ + math (contains -i -- (commandline -t) $COMP_WORDS)-1 \\ + ) + set -lx PIP_AUTO_COMPLETE 1 + string split \\ -- (eval $COMP_WORDS[1]) + end + complete -fa "(__fish_complete_pip)" -c {prog} + """, +} + + +class CompletionCommand(Command): + """A helper command to be used for command completion.""" + + ignore_require_venv = True + + def add_options(self) -> None: + self.cmd_opts.add_option( + "--bash", + "-b", + action="store_const", + const="bash", + dest="shell", + help="Emit completion code for bash", + ) + self.cmd_opts.add_option( + "--zsh", + "-z", + action="store_const", + const="zsh", + dest="shell", + help="Emit completion code for zsh", + ) + self.cmd_opts.add_option( + "--fish", + "-f", + action="store_const", + const="fish", + dest="shell", + help="Emit completion code for fish", + ) + + self.parser.insert_option_group(0, self.cmd_opts) + + def run(self, options: Values, args: List[str]) -> int: + """Prints the completion code of the given shell""" + shells = COMPLETION_SCRIPTS.keys() + shell_options = ["--" + shell for shell in sorted(shells)] + if options.shell in shells: + script = textwrap.dedent( + COMPLETION_SCRIPTS.get(options.shell, "").format(prog=get_prog()) + ) + print(BASE_COMPLETION.format(script=script, shell=options.shell)) + return SUCCESS + else: + sys.stderr.write( + "ERROR: You must pass {}\n".format(" or ".join(shell_options)) + ) + return SUCCESS diff --git a/venv/Lib/site-packages/pip/_internal/commands/configuration.py b/venv/Lib/site-packages/pip/_internal/commands/configuration.py new file mode 100644 index 0000000..c6c74ed --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/commands/configuration.py @@ -0,0 +1,266 @@ +import logging +import os +import subprocess +from optparse import Values +from typing import Any, List, Optional + +from pip._internal.cli.base_command import Command +from pip._internal.cli.status_codes import ERROR, SUCCESS +from pip._internal.configuration import ( + Configuration, + Kind, + get_configuration_files, + kinds, +) +from pip._internal.exceptions import PipError +from pip._internal.utils.logging import indent_log +from pip._internal.utils.misc import get_prog, write_output + +logger = logging.getLogger(__name__) + + +class ConfigurationCommand(Command): + """ + Manage local and global configuration. + + Subcommands: + + - list: List the active configuration (or from the file specified) + - edit: Edit the configuration file in an editor + - get: Get the value associated with name + - set: Set the name=value + - unset: Unset the value associated with name + - debug: List the configuration files and values defined under them + + If none of --user, --global and --site are passed, a virtual + environment configuration file is used if one is active and the file + exists. Otherwise, all modifications happen to the user file by + default. + """ + + ignore_require_venv = True + usage = """ + %prog [] list + %prog [] [--editor ] edit + + %prog [] get name + %prog [] set name value + %prog [] unset name + %prog [] debug + """ + + def add_options(self) -> None: + self.cmd_opts.add_option( + "--editor", + dest="editor", + action="store", + default=None, + help=( + "Editor to use to edit the file. Uses VISUAL or EDITOR " + "environment variables if not provided." + ), + ) + + self.cmd_opts.add_option( + "--global", + dest="global_file", + action="store_true", + default=False, + help="Use the system-wide configuration file only", + ) + + self.cmd_opts.add_option( + "--user", + dest="user_file", + action="store_true", + default=False, + help="Use the user configuration file only", + ) + + self.cmd_opts.add_option( + "--site", + dest="site_file", + action="store_true", + default=False, + help="Use the current environment configuration file only", + ) + + self.parser.insert_option_group(0, self.cmd_opts) + + def run(self, options: Values, args: List[str]) -> int: + handlers = { + "list": self.list_values, + "edit": self.open_in_editor, + "get": self.get_name, + "set": self.set_name_value, + "unset": self.unset_name, + "debug": self.list_config_values, + } + + # Determine action + if not args or args[0] not in handlers: + logger.error( + "Need an action (%s) to perform.", + ", ".join(sorted(handlers)), + ) + return ERROR + + action = args[0] + + # Determine which configuration files are to be loaded + # Depends on whether the command is modifying. + try: + load_only = self._determine_file( + options, need_value=(action in ["get", "set", "unset", "edit"]) + ) + except PipError as e: + logger.error(e.args[0]) + return ERROR + + # Load a new configuration + self.configuration = Configuration( + isolated=options.isolated_mode, load_only=load_only + ) + self.configuration.load() + + # Error handling happens here, not in the action-handlers. + try: + handlers[action](options, args[1:]) + except PipError as e: + logger.error(e.args[0]) + return ERROR + + return SUCCESS + + def _determine_file(self, options: Values, need_value: bool) -> Optional[Kind]: + file_options = [ + key + for key, value in ( + (kinds.USER, options.user_file), + (kinds.GLOBAL, options.global_file), + (kinds.SITE, options.site_file), + ) + if value + ] + + if not file_options: + if not need_value: + return None + # Default to user, unless there's a site file. + elif any( + os.path.exists(site_config_file) + for site_config_file in get_configuration_files()[kinds.SITE] + ): + return kinds.SITE + else: + return kinds.USER + elif len(file_options) == 1: + return file_options[0] + + raise PipError( + "Need exactly one file to operate upon " + "(--user, --site, --global) to perform." + ) + + def list_values(self, options: Values, args: List[str]) -> None: + self._get_n_args(args, "list", n=0) + + for key, value in sorted(self.configuration.items()): + write_output("%s=%r", key, value) + + def get_name(self, options: Values, args: List[str]) -> None: + key = self._get_n_args(args, "get [name]", n=1) + value = self.configuration.get_value(key) + + write_output("%s", value) + + def set_name_value(self, options: Values, args: List[str]) -> None: + key, value = self._get_n_args(args, "set [name] [value]", n=2) + self.configuration.set_value(key, value) + + self._save_configuration() + + def unset_name(self, options: Values, args: List[str]) -> None: + key = self._get_n_args(args, "unset [name]", n=1) + self.configuration.unset_value(key) + + self._save_configuration() + + def list_config_values(self, options: Values, args: List[str]) -> None: + """List config key-value pairs across different config files""" + self._get_n_args(args, "debug", n=0) + + self.print_env_var_values() + # Iterate over config files and print if they exist, and the + # key-value pairs present in them if they do + for variant, files in sorted(self.configuration.iter_config_files()): + write_output("%s:", variant) + for fname in files: + with indent_log(): + file_exists = os.path.exists(fname) + write_output("%s, exists: %r", fname, file_exists) + if file_exists: + self.print_config_file_values(variant) + + def print_config_file_values(self, variant: Kind) -> None: + """Get key-value pairs from the file of a variant""" + for name, value in self.configuration.get_values_in_config(variant).items(): + with indent_log(): + write_output("%s: %s", name, value) + + def print_env_var_values(self) -> None: + """Get key-values pairs present as environment variables""" + write_output("%s:", "env_var") + with indent_log(): + for key, value in sorted(self.configuration.get_environ_vars()): + env_var = f"PIP_{key.upper()}" + write_output("%s=%r", env_var, value) + + def open_in_editor(self, options: Values, args: List[str]) -> None: + editor = self._determine_editor(options) + + fname = self.configuration.get_file_to_edit() + if fname is None: + raise PipError("Could not determine appropriate file.") + + try: + subprocess.check_call([editor, fname]) + except subprocess.CalledProcessError as e: + raise PipError( + "Editor Subprocess exited with exit code {}".format(e.returncode) + ) + + def _get_n_args(self, args: List[str], example: str, n: int) -> Any: + """Helper to make sure the command got the right number of arguments""" + if len(args) != n: + msg = ( + "Got unexpected number of arguments, expected {}. " + '(example: "{} config {}")' + ).format(n, get_prog(), example) + raise PipError(msg) + + if n == 1: + return args[0] + else: + return args + + def _save_configuration(self) -> None: + # We successfully ran a modifying command. Need to save the + # configuration. + try: + self.configuration.save() + except Exception: + logger.exception( + "Unable to save configuration. Please report this as a bug." + ) + raise PipError("Internal Error.") + + def _determine_editor(self, options: Values) -> str: + if options.editor is not None: + return options.editor + elif "VISUAL" in os.environ: + return os.environ["VISUAL"] + elif "EDITOR" in os.environ: + return os.environ["EDITOR"] + else: + raise PipError("Could not determine editor to use.") diff --git a/venv/Lib/site-packages/pip/_internal/commands/debug.py b/venv/Lib/site-packages/pip/_internal/commands/debug.py new file mode 100644 index 0000000..d3f1f28 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/commands/debug.py @@ -0,0 +1,202 @@ +import locale +import logging +import os +import sys +from optparse import Values +from types import ModuleType +from typing import Any, Dict, List, Optional + +import pip._vendor +from pip._vendor.certifi import where +from pip._vendor.packaging.version import parse as parse_version + +from pip import __file__ as pip_location +from pip._internal.cli import cmdoptions +from pip._internal.cli.base_command import Command +from pip._internal.cli.cmdoptions import make_target_python +from pip._internal.cli.status_codes import SUCCESS +from pip._internal.configuration import Configuration +from pip._internal.metadata import get_environment +from pip._internal.utils.logging import indent_log +from pip._internal.utils.misc import get_pip_version + +logger = logging.getLogger(__name__) + + +def show_value(name: str, value: Any) -> None: + logger.info("%s: %s", name, value) + + +def show_sys_implementation() -> None: + logger.info("sys.implementation:") + implementation_name = sys.implementation.name + with indent_log(): + show_value("name", implementation_name) + + +def create_vendor_txt_map() -> Dict[str, str]: + vendor_txt_path = os.path.join( + os.path.dirname(pip_location), "_vendor", "vendor.txt" + ) + + with open(vendor_txt_path) as f: + # Purge non version specifying lines. + # Also, remove any space prefix or suffixes (including comments). + lines = [ + line.strip().split(" ", 1)[0] for line in f.readlines() if "==" in line + ] + + # Transform into "module" -> version dict. + return dict(line.split("==", 1) for line in lines) # type: ignore + + +def get_module_from_module_name(module_name: str) -> ModuleType: + # Module name can be uppercase in vendor.txt for some reason... + module_name = module_name.lower() + # PATCH: setuptools is actually only pkg_resources. + if module_name == "setuptools": + module_name = "pkg_resources" + + __import__(f"pip._vendor.{module_name}", globals(), locals(), level=0) + return getattr(pip._vendor, module_name) + + +def get_vendor_version_from_module(module_name: str) -> Optional[str]: + module = get_module_from_module_name(module_name) + version = getattr(module, "__version__", None) + + if not version: + # Try to find version in debundled module info. + env = get_environment([os.path.dirname(module.__file__)]) + dist = env.get_distribution(module_name) + if dist: + version = str(dist.version) + + return version + + +def show_actual_vendor_versions(vendor_txt_versions: Dict[str, str]) -> None: + """Log the actual version and print extra info if there is + a conflict or if the actual version could not be imported. + """ + for module_name, expected_version in vendor_txt_versions.items(): + extra_message = "" + actual_version = get_vendor_version_from_module(module_name) + if not actual_version: + extra_message = ( + " (Unable to locate actual module version, using" + " vendor.txt specified version)" + ) + actual_version = expected_version + elif parse_version(actual_version) != parse_version(expected_version): + extra_message = ( + " (CONFLICT: vendor.txt suggests version should" + " be {})".format(expected_version) + ) + logger.info("%s==%s%s", module_name, actual_version, extra_message) + + +def show_vendor_versions() -> None: + logger.info("vendored library versions:") + + vendor_txt_versions = create_vendor_txt_map() + with indent_log(): + show_actual_vendor_versions(vendor_txt_versions) + + +def show_tags(options: Values) -> None: + tag_limit = 10 + + target_python = make_target_python(options) + tags = target_python.get_tags() + + # Display the target options that were explicitly provided. + formatted_target = target_python.format_given() + suffix = "" + if formatted_target: + suffix = f" (target: {formatted_target})" + + msg = "Compatible tags: {}{}".format(len(tags), suffix) + logger.info(msg) + + if options.verbose < 1 and len(tags) > tag_limit: + tags_limited = True + tags = tags[:tag_limit] + else: + tags_limited = False + + with indent_log(): + for tag in tags: + logger.info(str(tag)) + + if tags_limited: + msg = ( + "...\n[First {tag_limit} tags shown. Pass --verbose to show all.]" + ).format(tag_limit=tag_limit) + logger.info(msg) + + +def ca_bundle_info(config: Configuration) -> str: + levels = set() + for key, _ in config.items(): + levels.add(key.split(".")[0]) + + if not levels: + return "Not specified" + + levels_that_override_global = ["install", "wheel", "download"] + global_overriding_level = [ + level for level in levels if level in levels_that_override_global + ] + if not global_overriding_level: + return "global" + + if "global" in levels: + levels.remove("global") + return ", ".join(levels) + + +class DebugCommand(Command): + """ + Display debug information. + """ + + usage = """ + %prog """ + ignore_require_venv = True + + def add_options(self) -> None: + cmdoptions.add_target_python_options(self.cmd_opts) + self.parser.insert_option_group(0, self.cmd_opts) + self.parser.config.load() + + def run(self, options: Values, args: List[str]) -> int: + logger.warning( + "This command is only meant for debugging. " + "Do not use this with automation for parsing and getting these " + "details, since the output and options of this command may " + "change without notice." + ) + show_value("pip version", get_pip_version()) + show_value("sys.version", sys.version) + show_value("sys.executable", sys.executable) + show_value("sys.getdefaultencoding", sys.getdefaultencoding()) + show_value("sys.getfilesystemencoding", sys.getfilesystemencoding()) + show_value( + "locale.getpreferredencoding", + locale.getpreferredencoding(), + ) + show_value("sys.platform", sys.platform) + show_sys_implementation() + + show_value("'cert' config value", ca_bundle_info(self.parser.config)) + show_value("REQUESTS_CA_BUNDLE", os.environ.get("REQUESTS_CA_BUNDLE")) + show_value("CURL_CA_BUNDLE", os.environ.get("CURL_CA_BUNDLE")) + show_value("pip._vendor.certifi.where()", where()) + show_value("pip._vendor.DEBUNDLED", pip._vendor.DEBUNDLED) + + show_vendor_versions() + + show_tags(options) + + return SUCCESS diff --git a/venv/Lib/site-packages/pip/_internal/commands/download.py b/venv/Lib/site-packages/pip/_internal/commands/download.py new file mode 100644 index 0000000..233b7e9 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/commands/download.py @@ -0,0 +1,140 @@ +import logging +import os +from optparse import Values +from typing import List + +from pip._internal.cli import cmdoptions +from pip._internal.cli.cmdoptions import make_target_python +from pip._internal.cli.req_command import RequirementCommand, with_cleanup +from pip._internal.cli.status_codes import SUCCESS +from pip._internal.req.req_tracker import get_requirement_tracker +from pip._internal.utils.misc import ensure_dir, normalize_path, write_output +from pip._internal.utils.temp_dir import TempDirectory + +logger = logging.getLogger(__name__) + + +class DownloadCommand(RequirementCommand): + """ + Download packages from: + + - PyPI (and other indexes) using requirement specifiers. + - VCS project urls. + - Local project directories. + - Local or remote source archives. + + pip also supports downloading from "requirements files", which provide + an easy way to specify a whole environment to be downloaded. + """ + + usage = """ + %prog [options] [package-index-options] ... + %prog [options] -r [package-index-options] ... + %prog [options] ... + %prog [options] ... + %prog [options] ...""" + + def add_options(self) -> None: + self.cmd_opts.add_option(cmdoptions.constraints()) + self.cmd_opts.add_option(cmdoptions.requirements()) + self.cmd_opts.add_option(cmdoptions.no_deps()) + self.cmd_opts.add_option(cmdoptions.global_options()) + self.cmd_opts.add_option(cmdoptions.no_binary()) + self.cmd_opts.add_option(cmdoptions.only_binary()) + self.cmd_opts.add_option(cmdoptions.prefer_binary()) + self.cmd_opts.add_option(cmdoptions.src()) + self.cmd_opts.add_option(cmdoptions.pre()) + self.cmd_opts.add_option(cmdoptions.require_hashes()) + self.cmd_opts.add_option(cmdoptions.progress_bar()) + self.cmd_opts.add_option(cmdoptions.no_build_isolation()) + self.cmd_opts.add_option(cmdoptions.use_pep517()) + self.cmd_opts.add_option(cmdoptions.no_use_pep517()) + self.cmd_opts.add_option(cmdoptions.ignore_requires_python()) + + self.cmd_opts.add_option( + "-d", + "--dest", + "--destination-dir", + "--destination-directory", + dest="download_dir", + metavar="dir", + default=os.curdir, + help="Download packages into .", + ) + + cmdoptions.add_target_python_options(self.cmd_opts) + + index_opts = cmdoptions.make_option_group( + cmdoptions.index_group, + self.parser, + ) + + self.parser.insert_option_group(0, index_opts) + self.parser.insert_option_group(0, self.cmd_opts) + + @with_cleanup + def run(self, options: Values, args: List[str]) -> int: + + options.ignore_installed = True + # editable doesn't really make sense for `pip download`, but the bowels + # of the RequirementSet code require that property. + options.editables = [] + + cmdoptions.check_dist_restriction(options) + + options.download_dir = normalize_path(options.download_dir) + ensure_dir(options.download_dir) + + session = self.get_default_session(options) + + target_python = make_target_python(options) + finder = self._build_package_finder( + options=options, + session=session, + target_python=target_python, + ignore_requires_python=options.ignore_requires_python, + ) + + req_tracker = self.enter_context(get_requirement_tracker()) + + directory = TempDirectory( + delete=not options.no_clean, + kind="download", + globally_managed=True, + ) + + reqs = self.get_requirements(args, options, finder, session) + + preparer = self.make_requirement_preparer( + temp_build_dir=directory, + options=options, + req_tracker=req_tracker, + session=session, + finder=finder, + download_dir=options.download_dir, + use_user_site=False, + verbosity=self.verbosity, + ) + + resolver = self.make_resolver( + preparer=preparer, + finder=finder, + options=options, + ignore_requires_python=options.ignore_requires_python, + py_version_info=options.python_version, + ) + + self.trace_basic_info(finder) + + requirement_set = resolver.resolve(reqs, check_supported_wheels=True) + + downloaded: List[str] = [] + for req in requirement_set.requirements.values(): + if req.satisfied_by is None: + assert req.name is not None + preparer.save_linked_requirement(req) + downloaded.append(req.name) + if downloaded: + write_output("Successfully downloaded %s", " ".join(downloaded)) + + return SUCCESS diff --git a/venv/Lib/site-packages/pip/_internal/commands/freeze.py b/venv/Lib/site-packages/pip/_internal/commands/freeze.py new file mode 100644 index 0000000..5fa6d39 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/commands/freeze.py @@ -0,0 +1,97 @@ +import sys +from optparse import Values +from typing import List + +from pip._internal.cli import cmdoptions +from pip._internal.cli.base_command import Command +from pip._internal.cli.status_codes import SUCCESS +from pip._internal.operations.freeze import freeze +from pip._internal.utils.compat import stdlib_pkgs + +DEV_PKGS = {"pip", "setuptools", "distribute", "wheel"} + + +class FreezeCommand(Command): + """ + Output installed packages in requirements format. + + packages are listed in a case-insensitive sorted order. + """ + + usage = """ + %prog [options]""" + log_streams = ("ext://sys.stderr", "ext://sys.stderr") + + def add_options(self) -> None: + self.cmd_opts.add_option( + "-r", + "--requirement", + dest="requirements", + action="append", + default=[], + metavar="file", + help=( + "Use the order in the given requirements file and its " + "comments when generating output. This option can be " + "used multiple times." + ), + ) + self.cmd_opts.add_option( + "-l", + "--local", + dest="local", + action="store_true", + default=False, + help=( + "If in a virtualenv that has global access, do not output " + "globally-installed packages." + ), + ) + self.cmd_opts.add_option( + "--user", + dest="user", + action="store_true", + default=False, + help="Only output packages installed in user-site.", + ) + self.cmd_opts.add_option(cmdoptions.list_path()) + self.cmd_opts.add_option( + "--all", + dest="freeze_all", + action="store_true", + help=( + "Do not skip these packages in the output:" + " {}".format(", ".join(DEV_PKGS)) + ), + ) + self.cmd_opts.add_option( + "--exclude-editable", + dest="exclude_editable", + action="store_true", + help="Exclude editable package from output.", + ) + self.cmd_opts.add_option(cmdoptions.list_exclude()) + + self.parser.insert_option_group(0, self.cmd_opts) + + def run(self, options: Values, args: List[str]) -> int: + skip = set(stdlib_pkgs) + if not options.freeze_all: + skip.update(DEV_PKGS) + + if options.excludes: + skip.update(options.excludes) + + cmdoptions.check_list_path_option(options) + + for line in freeze( + requirement=options.requirements, + local_only=options.local, + user_only=options.user, + paths=options.path, + isolated=options.isolated_mode, + skip=skip, + exclude_editable=options.exclude_editable, + ): + sys.stdout.write(line + "\n") + return SUCCESS diff --git a/venv/Lib/site-packages/pip/_internal/commands/hash.py b/venv/Lib/site-packages/pip/_internal/commands/hash.py new file mode 100644 index 0000000..042dac8 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/commands/hash.py @@ -0,0 +1,59 @@ +import hashlib +import logging +import sys +from optparse import Values +from typing import List + +from pip._internal.cli.base_command import Command +from pip._internal.cli.status_codes import ERROR, SUCCESS +from pip._internal.utils.hashes import FAVORITE_HASH, STRONG_HASHES +from pip._internal.utils.misc import read_chunks, write_output + +logger = logging.getLogger(__name__) + + +class HashCommand(Command): + """ + Compute a hash of a local package archive. + + These can be used with --hash in a requirements file to do repeatable + installs. + """ + + usage = "%prog [options] ..." + ignore_require_venv = True + + def add_options(self) -> None: + self.cmd_opts.add_option( + "-a", + "--algorithm", + dest="algorithm", + choices=STRONG_HASHES, + action="store", + default=FAVORITE_HASH, + help="The hash algorithm to use: one of {}".format( + ", ".join(STRONG_HASHES) + ), + ) + self.parser.insert_option_group(0, self.cmd_opts) + + def run(self, options: Values, args: List[str]) -> int: + if not args: + self.parser.print_usage(sys.stderr) + return ERROR + + algorithm = options.algorithm + for path in args: + write_output( + "%s:\n--hash=%s:%s", path, algorithm, _hash_of_file(path, algorithm) + ) + return SUCCESS + + +def _hash_of_file(path: str, algorithm: str) -> str: + """Return the hash digest of a file.""" + with open(path, "rb") as archive: + hash = hashlib.new(algorithm) + for chunk in read_chunks(archive): + hash.update(chunk) + return hash.hexdigest() diff --git a/venv/Lib/site-packages/pip/_internal/commands/help.py b/venv/Lib/site-packages/pip/_internal/commands/help.py new file mode 100644 index 0000000..6206631 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/commands/help.py @@ -0,0 +1,41 @@ +from optparse import Values +from typing import List + +from pip._internal.cli.base_command import Command +from pip._internal.cli.status_codes import SUCCESS +from pip._internal.exceptions import CommandError + + +class HelpCommand(Command): + """Show help for commands""" + + usage = """ + %prog """ + ignore_require_venv = True + + def run(self, options: Values, args: List[str]) -> int: + from pip._internal.commands import ( + commands_dict, + create_command, + get_similar_commands, + ) + + try: + # 'pip help' with no args is handled by pip.__init__.parseopt() + cmd_name = args[0] # the command we need help for + except IndexError: + return SUCCESS + + if cmd_name not in commands_dict: + guess = get_similar_commands(cmd_name) + + msg = [f'unknown command "{cmd_name}"'] + if guess: + msg.append(f'maybe you meant "{guess}"') + + raise CommandError(" - ".join(msg)) + + command = create_command(cmd_name) + command.parser.print_help() + + return SUCCESS diff --git a/venv/Lib/site-packages/pip/_internal/commands/index.py b/venv/Lib/site-packages/pip/_internal/commands/index.py new file mode 100644 index 0000000..9d8aae3 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/commands/index.py @@ -0,0 +1,139 @@ +import logging +from optparse import Values +from typing import Any, Iterable, List, Optional, Union + +from pip._vendor.packaging.version import LegacyVersion, Version + +from pip._internal.cli import cmdoptions +from pip._internal.cli.req_command import IndexGroupCommand +from pip._internal.cli.status_codes import ERROR, SUCCESS +from pip._internal.commands.search import print_dist_installation_info +from pip._internal.exceptions import CommandError, DistributionNotFound, PipError +from pip._internal.index.collector import LinkCollector +from pip._internal.index.package_finder import PackageFinder +from pip._internal.models.selection_prefs import SelectionPreferences +from pip._internal.models.target_python import TargetPython +from pip._internal.network.session import PipSession +from pip._internal.utils.misc import write_output + +logger = logging.getLogger(__name__) + + +class IndexCommand(IndexGroupCommand): + """ + Inspect information available from package indexes. + """ + + usage = """ + %prog versions + """ + + def add_options(self) -> None: + cmdoptions.add_target_python_options(self.cmd_opts) + + self.cmd_opts.add_option(cmdoptions.ignore_requires_python()) + self.cmd_opts.add_option(cmdoptions.pre()) + self.cmd_opts.add_option(cmdoptions.no_binary()) + self.cmd_opts.add_option(cmdoptions.only_binary()) + + index_opts = cmdoptions.make_option_group( + cmdoptions.index_group, + self.parser, + ) + + self.parser.insert_option_group(0, index_opts) + self.parser.insert_option_group(0, self.cmd_opts) + + def run(self, options: Values, args: List[str]) -> int: + handlers = { + "versions": self.get_available_package_versions, + } + + logger.warning( + "pip index is currently an experimental command. " + "It may be removed/changed in a future release " + "without prior warning." + ) + + # Determine action + if not args or args[0] not in handlers: + logger.error( + "Need an action (%s) to perform.", + ", ".join(sorted(handlers)), + ) + return ERROR + + action = args[0] + + # Error handling happens here, not in the action-handlers. + try: + handlers[action](options, args[1:]) + except PipError as e: + logger.error(e.args[0]) + return ERROR + + return SUCCESS + + def _build_package_finder( + self, + options: Values, + session: PipSession, + target_python: Optional[TargetPython] = None, + ignore_requires_python: Optional[bool] = None, + ) -> PackageFinder: + """ + Create a package finder appropriate to the index command. + """ + link_collector = LinkCollector.create(session, options=options) + + # Pass allow_yanked=False to ignore yanked versions. + selection_prefs = SelectionPreferences( + allow_yanked=False, + allow_all_prereleases=options.pre, + ignore_requires_python=ignore_requires_python, + ) + + return PackageFinder.create( + link_collector=link_collector, + selection_prefs=selection_prefs, + target_python=target_python, + use_deprecated_html5lib="html5lib" in options.deprecated_features_enabled, + ) + + def get_available_package_versions(self, options: Values, args: List[Any]) -> None: + if len(args) != 1: + raise CommandError("You need to specify exactly one argument") + + target_python = cmdoptions.make_target_python(options) + query = args[0] + + with self._build_session(options) as session: + finder = self._build_package_finder( + options=options, + session=session, + target_python=target_python, + ignore_requires_python=options.ignore_requires_python, + ) + + versions: Iterable[Union[LegacyVersion, Version]] = ( + candidate.version for candidate in finder.find_all_candidates(query) + ) + + if not options.pre: + # Remove prereleases + versions = ( + version for version in versions if not version.is_prerelease + ) + versions = set(versions) + + if not versions: + raise DistributionNotFound( + "No matching distribution found for {}".format(query) + ) + + formatted_versions = [str(ver) for ver in sorted(versions, reverse=True)] + latest = formatted_versions[0] + + write_output("{} ({})".format(query, latest)) + write_output("Available versions: {}".format(", ".join(formatted_versions))) + print_dist_installation_info(query, latest) diff --git a/venv/Lib/site-packages/pip/_internal/commands/install.py b/venv/Lib/site-packages/pip/_internal/commands/install.py new file mode 100644 index 0000000..34e4c2f --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/commands/install.py @@ -0,0 +1,771 @@ +import errno +import operator +import os +import shutil +import site +from optparse import SUPPRESS_HELP, Values +from typing import Iterable, List, Optional + +from pip._vendor.packaging.utils import canonicalize_name + +from pip._internal.cache import WheelCache +from pip._internal.cli import cmdoptions +from pip._internal.cli.cmdoptions import make_target_python +from pip._internal.cli.req_command import ( + RequirementCommand, + warn_if_run_as_root, + with_cleanup, +) +from pip._internal.cli.status_codes import ERROR, SUCCESS +from pip._internal.exceptions import CommandError, InstallationError +from pip._internal.locations import get_scheme +from pip._internal.metadata import get_environment +from pip._internal.models.format_control import FormatControl +from pip._internal.operations.check import ConflictDetails, check_install_conflicts +from pip._internal.req import install_given_reqs +from pip._internal.req.req_install import InstallRequirement +from pip._internal.req.req_tracker import get_requirement_tracker +from pip._internal.utils.compat import WINDOWS +from pip._internal.utils.distutils_args import parse_distutils_args +from pip._internal.utils.filesystem import test_writable_dir +from pip._internal.utils.logging import getLogger +from pip._internal.utils.misc import ( + ensure_dir, + get_pip_version, + protect_pip_from_modification_on_windows, + write_output, +) +from pip._internal.utils.temp_dir import TempDirectory +from pip._internal.utils.virtualenv import ( + running_under_virtualenv, + virtualenv_no_global, +) +from pip._internal.wheel_builder import ( + BinaryAllowedPredicate, + build, + should_build_for_install_command, +) + +logger = getLogger(__name__) + + +def get_check_binary_allowed(format_control: FormatControl) -> BinaryAllowedPredicate: + def check_binary_allowed(req: InstallRequirement) -> bool: + canonical_name = canonicalize_name(req.name or "") + allowed_formats = format_control.get_allowed_formats(canonical_name) + return "binary" in allowed_formats + + return check_binary_allowed + + +class InstallCommand(RequirementCommand): + """ + Install packages from: + + - PyPI (and other indexes) using requirement specifiers. + - VCS project urls. + - Local project directories. + - Local or remote source archives. + + pip also supports installing from "requirements files", which provide + an easy way to specify a whole environment to be installed. + """ + + usage = """ + %prog [options] [package-index-options] ... + %prog [options] -r [package-index-options] ... + %prog [options] [-e] ... + %prog [options] [-e] ... + %prog [options] ...""" + + def add_options(self) -> None: + self.cmd_opts.add_option(cmdoptions.requirements()) + self.cmd_opts.add_option(cmdoptions.constraints()) + self.cmd_opts.add_option(cmdoptions.no_deps()) + self.cmd_opts.add_option(cmdoptions.pre()) + + self.cmd_opts.add_option(cmdoptions.editable()) + self.cmd_opts.add_option( + "-t", + "--target", + dest="target_dir", + metavar="dir", + default=None, + help=( + "Install packages into . " + "By default this will not replace existing files/folders in " + ". Use --upgrade to replace existing packages in " + "with new versions." + ), + ) + cmdoptions.add_target_python_options(self.cmd_opts) + + self.cmd_opts.add_option( + "--user", + dest="use_user_site", + action="store_true", + help=( + "Install to the Python user install directory for your " + "platform. Typically ~/.local/, or %APPDATA%\\Python on " + "Windows. (See the Python documentation for site.USER_BASE " + "for full details.)" + ), + ) + self.cmd_opts.add_option( + "--no-user", + dest="use_user_site", + action="store_false", + help=SUPPRESS_HELP, + ) + self.cmd_opts.add_option( + "--root", + dest="root_path", + metavar="dir", + default=None, + help="Install everything relative to this alternate root directory.", + ) + self.cmd_opts.add_option( + "--prefix", + dest="prefix_path", + metavar="dir", + default=None, + help=( + "Installation prefix where lib, bin and other top-level " + "folders are placed" + ), + ) + + self.cmd_opts.add_option(cmdoptions.src()) + + self.cmd_opts.add_option( + "-U", + "--upgrade", + dest="upgrade", + action="store_true", + help=( + "Upgrade all specified packages to the newest available " + "version. The handling of dependencies depends on the " + "upgrade-strategy used." + ), + ) + + self.cmd_opts.add_option( + "--upgrade-strategy", + dest="upgrade_strategy", + default="only-if-needed", + choices=["only-if-needed", "eager"], + help=( + "Determines how dependency upgrading should be handled " + "[default: %default]. " + '"eager" - dependencies are upgraded regardless of ' + "whether the currently installed version satisfies the " + "requirements of the upgraded package(s). " + '"only-if-needed" - are upgraded only when they do not ' + "satisfy the requirements of the upgraded package(s)." + ), + ) + + self.cmd_opts.add_option( + "--force-reinstall", + dest="force_reinstall", + action="store_true", + help="Reinstall all packages even if they are already up-to-date.", + ) + + self.cmd_opts.add_option( + "-I", + "--ignore-installed", + dest="ignore_installed", + action="store_true", + help=( + "Ignore the installed packages, overwriting them. " + "This can break your system if the existing package " + "is of a different version or was installed " + "with a different package manager!" + ), + ) + + self.cmd_opts.add_option(cmdoptions.ignore_requires_python()) + self.cmd_opts.add_option(cmdoptions.no_build_isolation()) + self.cmd_opts.add_option(cmdoptions.use_pep517()) + self.cmd_opts.add_option(cmdoptions.no_use_pep517()) + + self.cmd_opts.add_option(cmdoptions.install_options()) + self.cmd_opts.add_option(cmdoptions.global_options()) + + self.cmd_opts.add_option( + "--compile", + action="store_true", + dest="compile", + default=True, + help="Compile Python source files to bytecode", + ) + + self.cmd_opts.add_option( + "--no-compile", + action="store_false", + dest="compile", + help="Do not compile Python source files to bytecode", + ) + + self.cmd_opts.add_option( + "--no-warn-script-location", + action="store_false", + dest="warn_script_location", + default=True, + help="Do not warn when installing scripts outside PATH", + ) + self.cmd_opts.add_option( + "--no-warn-conflicts", + action="store_false", + dest="warn_about_conflicts", + default=True, + help="Do not warn about broken dependencies", + ) + + self.cmd_opts.add_option(cmdoptions.no_binary()) + self.cmd_opts.add_option(cmdoptions.only_binary()) + self.cmd_opts.add_option(cmdoptions.prefer_binary()) + self.cmd_opts.add_option(cmdoptions.require_hashes()) + self.cmd_opts.add_option(cmdoptions.progress_bar()) + + index_opts = cmdoptions.make_option_group( + cmdoptions.index_group, + self.parser, + ) + + self.parser.insert_option_group(0, index_opts) + self.parser.insert_option_group(0, self.cmd_opts) + + @with_cleanup + def run(self, options: Values, args: List[str]) -> int: + if options.use_user_site and options.target_dir is not None: + raise CommandError("Can not combine '--user' and '--target'") + + cmdoptions.check_install_build_global(options) + upgrade_strategy = "to-satisfy-only" + if options.upgrade: + upgrade_strategy = options.upgrade_strategy + + cmdoptions.check_dist_restriction(options, check_target=True) + + install_options = options.install_options or [] + + logger.verbose("Using %s", get_pip_version()) + options.use_user_site = decide_user_install( + options.use_user_site, + prefix_path=options.prefix_path, + target_dir=options.target_dir, + root_path=options.root_path, + isolated_mode=options.isolated_mode, + ) + + target_temp_dir: Optional[TempDirectory] = None + target_temp_dir_path: Optional[str] = None + if options.target_dir: + options.ignore_installed = True + options.target_dir = os.path.abspath(options.target_dir) + if ( + # fmt: off + os.path.exists(options.target_dir) and + not os.path.isdir(options.target_dir) + # fmt: on + ): + raise CommandError( + "Target path exists but is not a directory, will not continue." + ) + + # Create a target directory for using with the target option + target_temp_dir = TempDirectory(kind="target") + target_temp_dir_path = target_temp_dir.path + self.enter_context(target_temp_dir) + + global_options = options.global_options or [] + + session = self.get_default_session(options) + + target_python = make_target_python(options) + finder = self._build_package_finder( + options=options, + session=session, + target_python=target_python, + ignore_requires_python=options.ignore_requires_python, + ) + wheel_cache = WheelCache(options.cache_dir, options.format_control) + + req_tracker = self.enter_context(get_requirement_tracker()) + + directory = TempDirectory( + delete=not options.no_clean, + kind="install", + globally_managed=True, + ) + + try: + reqs = self.get_requirements(args, options, finder, session) + + # Only when installing is it permitted to use PEP 660. + # In other circumstances (pip wheel, pip download) we generate + # regular (i.e. non editable) metadata and wheels. + for req in reqs: + req.permit_editable_wheels = True + + reject_location_related_install_options(reqs, options.install_options) + + preparer = self.make_requirement_preparer( + temp_build_dir=directory, + options=options, + req_tracker=req_tracker, + session=session, + finder=finder, + use_user_site=options.use_user_site, + verbosity=self.verbosity, + ) + resolver = self.make_resolver( + preparer=preparer, + finder=finder, + options=options, + wheel_cache=wheel_cache, + use_user_site=options.use_user_site, + ignore_installed=options.ignore_installed, + ignore_requires_python=options.ignore_requires_python, + force_reinstall=options.force_reinstall, + upgrade_strategy=upgrade_strategy, + use_pep517=options.use_pep517, + ) + + self.trace_basic_info(finder) + + requirement_set = resolver.resolve( + reqs, check_supported_wheels=not options.target_dir + ) + + try: + pip_req = requirement_set.get_requirement("pip") + except KeyError: + modifying_pip = False + else: + # If we're not replacing an already installed pip, + # we're not modifying it. + modifying_pip = pip_req.satisfied_by is None + protect_pip_from_modification_on_windows(modifying_pip=modifying_pip) + + check_binary_allowed = get_check_binary_allowed(finder.format_control) + + reqs_to_build = [ + r + for r in requirement_set.requirements.values() + if should_build_for_install_command(r, check_binary_allowed) + ] + + _, build_failures = build( + reqs_to_build, + wheel_cache=wheel_cache, + verify=True, + build_options=[], + global_options=[], + ) + + # If we're using PEP 517, we cannot do a legacy setup.py install + # so we fail here. + pep517_build_failure_names: List[str] = [ + r.name for r in build_failures if r.use_pep517 # type: ignore + ] + if pep517_build_failure_names: + raise InstallationError( + "Could not build wheels for {}, which is required to " + "install pyproject.toml-based projects".format( + ", ".join(pep517_build_failure_names) + ) + ) + + # For now, we just warn about failures building legacy + # requirements, as we'll fall through to a setup.py install for + # those. + for r in build_failures: + if not r.use_pep517: + r.legacy_install_reason = 8368 + + to_install = resolver.get_installation_order(requirement_set) + + # Check for conflicts in the package set we're installing. + conflicts: Optional[ConflictDetails] = None + should_warn_about_conflicts = ( + not options.ignore_dependencies and options.warn_about_conflicts + ) + if should_warn_about_conflicts: + conflicts = self._determine_conflicts(to_install) + + # Don't warn about script install locations if + # --target or --prefix has been specified + warn_script_location = options.warn_script_location + if options.target_dir or options.prefix_path: + warn_script_location = False + + installed = install_given_reqs( + to_install, + install_options, + global_options, + root=options.root_path, + home=target_temp_dir_path, + prefix=options.prefix_path, + warn_script_location=warn_script_location, + use_user_site=options.use_user_site, + pycompile=options.compile, + ) + + lib_locations = get_lib_location_guesses( + user=options.use_user_site, + home=target_temp_dir_path, + root=options.root_path, + prefix=options.prefix_path, + isolated=options.isolated_mode, + ) + env = get_environment(lib_locations) + + installed.sort(key=operator.attrgetter("name")) + items = [] + for result in installed: + item = result.name + try: + installed_dist = env.get_distribution(item) + if installed_dist is not None: + item = f"{item}-{installed_dist.version}" + except Exception: + pass + items.append(item) + + if conflicts is not None: + self._warn_about_conflicts( + conflicts, + resolver_variant=self.determine_resolver_variant(options), + ) + + installed_desc = " ".join(items) + if installed_desc: + write_output( + "Successfully installed %s", + installed_desc, + ) + except OSError as error: + show_traceback = self.verbosity >= 1 + + message = create_os_error_message( + error, + show_traceback, + options.use_user_site, + ) + logger.error(message, exc_info=show_traceback) # noqa + + return ERROR + + if options.target_dir: + assert target_temp_dir + self._handle_target_dir( + options.target_dir, target_temp_dir, options.upgrade + ) + + warn_if_run_as_root() + return SUCCESS + + def _handle_target_dir( + self, target_dir: str, target_temp_dir: TempDirectory, upgrade: bool + ) -> None: + ensure_dir(target_dir) + + # Checking both purelib and platlib directories for installed + # packages to be moved to target directory + lib_dir_list = [] + + # Checking both purelib and platlib directories for installed + # packages to be moved to target directory + scheme = get_scheme("", home=target_temp_dir.path) + purelib_dir = scheme.purelib + platlib_dir = scheme.platlib + data_dir = scheme.data + + if os.path.exists(purelib_dir): + lib_dir_list.append(purelib_dir) + if os.path.exists(platlib_dir) and platlib_dir != purelib_dir: + lib_dir_list.append(platlib_dir) + if os.path.exists(data_dir): + lib_dir_list.append(data_dir) + + for lib_dir in lib_dir_list: + for item in os.listdir(lib_dir): + if lib_dir == data_dir: + ddir = os.path.join(data_dir, item) + if any(s.startswith(ddir) for s in lib_dir_list[:-1]): + continue + target_item_dir = os.path.join(target_dir, item) + if os.path.exists(target_item_dir): + if not upgrade: + logger.warning( + "Target directory %s already exists. Specify " + "--upgrade to force replacement.", + target_item_dir, + ) + continue + if os.path.islink(target_item_dir): + logger.warning( + "Target directory %s already exists and is " + "a link. pip will not automatically replace " + "links, please remove if replacement is " + "desired.", + target_item_dir, + ) + continue + if os.path.isdir(target_item_dir): + shutil.rmtree(target_item_dir) + else: + os.remove(target_item_dir) + + shutil.move(os.path.join(lib_dir, item), target_item_dir) + + def _determine_conflicts( + self, to_install: List[InstallRequirement] + ) -> Optional[ConflictDetails]: + try: + return check_install_conflicts(to_install) + except Exception: + logger.exception( + "Error while checking for conflicts. Please file an issue on " + "pip's issue tracker: https://github.com/pypa/pip/issues/new" + ) + return None + + def _warn_about_conflicts( + self, conflict_details: ConflictDetails, resolver_variant: str + ) -> None: + package_set, (missing, conflicting) = conflict_details + if not missing and not conflicting: + return + + parts: List[str] = [] + if resolver_variant == "legacy": + parts.append( + "pip's legacy dependency resolver does not consider dependency " + "conflicts when selecting packages. This behaviour is the " + "source of the following dependency conflicts." + ) + else: + assert resolver_variant == "2020-resolver" + parts.append( + "pip's dependency resolver does not currently take into account " + "all the packages that are installed. This behaviour is the " + "source of the following dependency conflicts." + ) + + # NOTE: There is some duplication here, with commands/check.py + for project_name in missing: + version = package_set[project_name][0] + for dependency in missing[project_name]: + message = ( + "{name} {version} requires {requirement}, " + "which is not installed." + ).format( + name=project_name, + version=version, + requirement=dependency[1], + ) + parts.append(message) + + for project_name in conflicting: + version = package_set[project_name][0] + for dep_name, dep_version, req in conflicting[project_name]: + message = ( + "{name} {version} requires {requirement}, but {you} have " + "{dep_name} {dep_version} which is incompatible." + ).format( + name=project_name, + version=version, + requirement=req, + dep_name=dep_name, + dep_version=dep_version, + you=("you" if resolver_variant == "2020-resolver" else "you'll"), + ) + parts.append(message) + + logger.critical("\n".join(parts)) + + +def get_lib_location_guesses( + user: bool = False, + home: Optional[str] = None, + root: Optional[str] = None, + isolated: bool = False, + prefix: Optional[str] = None, +) -> List[str]: + scheme = get_scheme( + "", + user=user, + home=home, + root=root, + isolated=isolated, + prefix=prefix, + ) + return [scheme.purelib, scheme.platlib] + + +def site_packages_writable(root: Optional[str], isolated: bool) -> bool: + return all( + test_writable_dir(d) + for d in set(get_lib_location_guesses(root=root, isolated=isolated)) + ) + + +def decide_user_install( + use_user_site: Optional[bool], + prefix_path: Optional[str] = None, + target_dir: Optional[str] = None, + root_path: Optional[str] = None, + isolated_mode: bool = False, +) -> bool: + """Determine whether to do a user install based on the input options. + + If use_user_site is False, no additional checks are done. + If use_user_site is True, it is checked for compatibility with other + options. + If use_user_site is None, the default behaviour depends on the environment, + which is provided by the other arguments. + """ + # In some cases (config from tox), use_user_site can be set to an integer + # rather than a bool, which 'use_user_site is False' wouldn't catch. + if (use_user_site is not None) and (not use_user_site): + logger.debug("Non-user install by explicit request") + return False + + if use_user_site: + if prefix_path: + raise CommandError( + "Can not combine '--user' and '--prefix' as they imply " + "different installation locations" + ) + if virtualenv_no_global(): + raise InstallationError( + "Can not perform a '--user' install. User site-packages " + "are not visible in this virtualenv." + ) + logger.debug("User install by explicit request") + return True + + # If we are here, user installs have not been explicitly requested/avoided + assert use_user_site is None + + # user install incompatible with --prefix/--target + if prefix_path or target_dir: + logger.debug("Non-user install due to --prefix or --target option") + return False + + # If user installs are not enabled, choose a non-user install + if not site.ENABLE_USER_SITE: + logger.debug("Non-user install because user site-packages disabled") + return False + + # If we have permission for a non-user install, do that, + # otherwise do a user install. + if site_packages_writable(root=root_path, isolated=isolated_mode): + logger.debug("Non-user install because site-packages writeable") + return False + + logger.info( + "Defaulting to user installation because normal site-packages " + "is not writeable" + ) + return True + + +def reject_location_related_install_options( + requirements: List[InstallRequirement], options: Optional[List[str]] +) -> None: + """If any location-changing --install-option arguments were passed for + requirements or on the command-line, then show a deprecation warning. + """ + + def format_options(option_names: Iterable[str]) -> List[str]: + return ["--{}".format(name.replace("_", "-")) for name in option_names] + + offenders = [] + + for requirement in requirements: + install_options = requirement.install_options + location_options = parse_distutils_args(install_options) + if location_options: + offenders.append( + "{!r} from {}".format( + format_options(location_options.keys()), requirement + ) + ) + + if options: + location_options = parse_distutils_args(options) + if location_options: + offenders.append( + "{!r} from command line".format(format_options(location_options.keys())) + ) + + if not offenders: + return + + raise CommandError( + "Location-changing options found in --install-option: {}." + " This is unsupported, use pip-level options like --user," + " --prefix, --root, and --target instead.".format("; ".join(offenders)) + ) + + +def create_os_error_message( + error: OSError, show_traceback: bool, using_user_site: bool +) -> str: + """Format an error message for an OSError + + It may occur anytime during the execution of the install command. + """ + parts = [] + + # Mention the error if we are not going to show a traceback + parts.append("Could not install packages due to an OSError") + if not show_traceback: + parts.append(": ") + parts.append(str(error)) + else: + parts.append(".") + + # Spilt the error indication from a helper message (if any) + parts[-1] += "\n" + + # Suggest useful actions to the user: + # (1) using user site-packages or (2) verifying the permissions + if error.errno == errno.EACCES: + user_option_part = "Consider using the `--user` option" + permissions_part = "Check the permissions" + + if not running_under_virtualenv() and not using_user_site: + parts.extend( + [ + user_option_part, + " or ", + permissions_part.lower(), + ] + ) + else: + parts.append(permissions_part) + parts.append(".\n") + + # Suggest the user to enable Long Paths if path length is + # more than 260 + if ( + WINDOWS + and error.errno == errno.ENOENT + and error.filename + and len(error.filename) > 260 + ): + parts.append( + "HINT: This error might have occurred since " + "this system does not have Windows Long Path " + "support enabled. You can find information on " + "how to enable this at " + "https://pip.pypa.io/warnings/enable-long-paths\n" + ) + + return "".join(parts).strip() + "\n" diff --git a/venv/Lib/site-packages/pip/_internal/commands/list.py b/venv/Lib/site-packages/pip/_internal/commands/list.py new file mode 100644 index 0000000..57f05e0 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/commands/list.py @@ -0,0 +1,361 @@ +import json +import logging +from optparse import Values +from typing import TYPE_CHECKING, Iterator, List, Optional, Sequence, Tuple, cast + +from pip._vendor.packaging.utils import canonicalize_name + +from pip._internal.cli import cmdoptions +from pip._internal.cli.req_command import IndexGroupCommand +from pip._internal.cli.status_codes import SUCCESS +from pip._internal.exceptions import CommandError +from pip._internal.index.collector import LinkCollector +from pip._internal.index.package_finder import PackageFinder +from pip._internal.metadata import BaseDistribution, get_environment +from pip._internal.models.selection_prefs import SelectionPreferences +from pip._internal.network.session import PipSession +from pip._internal.utils.compat import stdlib_pkgs +from pip._internal.utils.misc import tabulate, write_output + +if TYPE_CHECKING: + from pip._internal.metadata.base import DistributionVersion + + class _DistWithLatestInfo(BaseDistribution): + """Give the distribution object a couple of extra fields. + + These will be populated during ``get_outdated()``. This is dirty but + makes the rest of the code much cleaner. + """ + + latest_version: DistributionVersion + latest_filetype: str + + _ProcessedDists = Sequence[_DistWithLatestInfo] + + +logger = logging.getLogger(__name__) + + +class ListCommand(IndexGroupCommand): + """ + List installed packages, including editables. + + Packages are listed in a case-insensitive sorted order. + """ + + ignore_require_venv = True + usage = """ + %prog [options]""" + + def add_options(self) -> None: + self.cmd_opts.add_option( + "-o", + "--outdated", + action="store_true", + default=False, + help="List outdated packages", + ) + self.cmd_opts.add_option( + "-u", + "--uptodate", + action="store_true", + default=False, + help="List uptodate packages", + ) + self.cmd_opts.add_option( + "-e", + "--editable", + action="store_true", + default=False, + help="List editable projects.", + ) + self.cmd_opts.add_option( + "-l", + "--local", + action="store_true", + default=False, + help=( + "If in a virtualenv that has global access, do not list " + "globally-installed packages." + ), + ) + self.cmd_opts.add_option( + "--user", + dest="user", + action="store_true", + default=False, + help="Only output packages installed in user-site.", + ) + self.cmd_opts.add_option(cmdoptions.list_path()) + self.cmd_opts.add_option( + "--pre", + action="store_true", + default=False, + help=( + "Include pre-release and development versions. By default, " + "pip only finds stable versions." + ), + ) + + self.cmd_opts.add_option( + "--format", + action="store", + dest="list_format", + default="columns", + choices=("columns", "freeze", "json"), + help="Select the output format among: columns (default), freeze, or json", + ) + + self.cmd_opts.add_option( + "--not-required", + action="store_true", + dest="not_required", + help="List packages that are not dependencies of installed packages.", + ) + + self.cmd_opts.add_option( + "--exclude-editable", + action="store_false", + dest="include_editable", + help="Exclude editable package from output.", + ) + self.cmd_opts.add_option( + "--include-editable", + action="store_true", + dest="include_editable", + help="Include editable package from output.", + default=True, + ) + self.cmd_opts.add_option(cmdoptions.list_exclude()) + index_opts = cmdoptions.make_option_group(cmdoptions.index_group, self.parser) + + self.parser.insert_option_group(0, index_opts) + self.parser.insert_option_group(0, self.cmd_opts) + + def _build_package_finder( + self, options: Values, session: PipSession + ) -> PackageFinder: + """ + Create a package finder appropriate to this list command. + """ + link_collector = LinkCollector.create(session, options=options) + + # Pass allow_yanked=False to ignore yanked versions. + selection_prefs = SelectionPreferences( + allow_yanked=False, + allow_all_prereleases=options.pre, + ) + + return PackageFinder.create( + link_collector=link_collector, + selection_prefs=selection_prefs, + use_deprecated_html5lib="html5lib" in options.deprecated_features_enabled, + ) + + def run(self, options: Values, args: List[str]) -> int: + if options.outdated and options.uptodate: + raise CommandError("Options --outdated and --uptodate cannot be combined.") + + cmdoptions.check_list_path_option(options) + + skip = set(stdlib_pkgs) + if options.excludes: + skip.update(canonicalize_name(n) for n in options.excludes) + + packages: "_ProcessedDists" = [ + cast("_DistWithLatestInfo", d) + for d in get_environment(options.path).iter_installed_distributions( + local_only=options.local, + user_only=options.user, + editables_only=options.editable, + include_editables=options.include_editable, + skip=skip, + ) + ] + + # get_not_required must be called firstly in order to find and + # filter out all dependencies correctly. Otherwise a package + # can't be identified as requirement because some parent packages + # could be filtered out before. + if options.not_required: + packages = self.get_not_required(packages, options) + + if options.outdated: + packages = self.get_outdated(packages, options) + elif options.uptodate: + packages = self.get_uptodate(packages, options) + + self.output_package_listing(packages, options) + return SUCCESS + + def get_outdated( + self, packages: "_ProcessedDists", options: Values + ) -> "_ProcessedDists": + return [ + dist + for dist in self.iter_packages_latest_infos(packages, options) + if dist.latest_version > dist.version + ] + + def get_uptodate( + self, packages: "_ProcessedDists", options: Values + ) -> "_ProcessedDists": + return [ + dist + for dist in self.iter_packages_latest_infos(packages, options) + if dist.latest_version == dist.version + ] + + def get_not_required( + self, packages: "_ProcessedDists", options: Values + ) -> "_ProcessedDists": + dep_keys = { + canonicalize_name(dep.name) + for dist in packages + for dep in (dist.iter_dependencies() or ()) + } + + # Create a set to remove duplicate packages, and cast it to a list + # to keep the return type consistent with get_outdated and + # get_uptodate + return list({pkg for pkg in packages if pkg.canonical_name not in dep_keys}) + + def iter_packages_latest_infos( + self, packages: "_ProcessedDists", options: Values + ) -> Iterator["_DistWithLatestInfo"]: + with self._build_session(options) as session: + finder = self._build_package_finder(options, session) + + def latest_info( + dist: "_DistWithLatestInfo", + ) -> Optional["_DistWithLatestInfo"]: + all_candidates = finder.find_all_candidates(dist.canonical_name) + if not options.pre: + # Remove prereleases + all_candidates = [ + candidate + for candidate in all_candidates + if not candidate.version.is_prerelease + ] + + evaluator = finder.make_candidate_evaluator( + project_name=dist.canonical_name, + ) + best_candidate = evaluator.sort_best_candidate(all_candidates) + if best_candidate is None: + return None + + remote_version = best_candidate.version + if best_candidate.link.is_wheel: + typ = "wheel" + else: + typ = "sdist" + dist.latest_version = remote_version + dist.latest_filetype = typ + return dist + + for dist in map(latest_info, packages): + if dist is not None: + yield dist + + def output_package_listing( + self, packages: "_ProcessedDists", options: Values + ) -> None: + packages = sorted( + packages, + key=lambda dist: dist.canonical_name, + ) + if options.list_format == "columns" and packages: + data, header = format_for_columns(packages, options) + self.output_package_listing_columns(data, header) + elif options.list_format == "freeze": + for dist in packages: + if options.verbose >= 1: + write_output( + "%s==%s (%s)", dist.raw_name, dist.version, dist.location + ) + else: + write_output("%s==%s", dist.raw_name, dist.version) + elif options.list_format == "json": + write_output(format_for_json(packages, options)) + + def output_package_listing_columns( + self, data: List[List[str]], header: List[str] + ) -> None: + # insert the header first: we need to know the size of column names + if len(data) > 0: + data.insert(0, header) + + pkg_strings, sizes = tabulate(data) + + # Create and add a separator. + if len(data) > 0: + pkg_strings.insert(1, " ".join(map(lambda x: "-" * x, sizes))) + + for val in pkg_strings: + write_output(val) + + +def format_for_columns( + pkgs: "_ProcessedDists", options: Values +) -> Tuple[List[List[str]], List[str]]: + """ + Convert the package data into something usable + by output_package_listing_columns. + """ + header = ["Package", "Version"] + + running_outdated = options.outdated + if running_outdated: + header.extend(["Latest", "Type"]) + + has_editables = any(x.editable for x in pkgs) + if has_editables: + header.append("Editable project location") + + if options.verbose >= 1: + header.append("Location") + if options.verbose >= 1: + header.append("Installer") + + data = [] + for proj in pkgs: + # if we're working on the 'outdated' list, separate out the + # latest_version and type + row = [proj.raw_name, str(proj.version)] + + if running_outdated: + row.append(str(proj.latest_version)) + row.append(proj.latest_filetype) + + if has_editables: + row.append(proj.editable_project_location or "") + + if options.verbose >= 1: + row.append(proj.location or "") + if options.verbose >= 1: + row.append(proj.installer) + + data.append(row) + + return data, header + + +def format_for_json(packages: "_ProcessedDists", options: Values) -> str: + data = [] + for dist in packages: + info = { + "name": dist.raw_name, + "version": str(dist.version), + } + if options.verbose >= 1: + info["location"] = dist.location or "" + info["installer"] = dist.installer + if options.outdated: + info["latest_version"] = str(dist.latest_version) + info["latest_filetype"] = dist.latest_filetype + editable_project_location = dist.editable_project_location + if editable_project_location: + info["editable_project_location"] = editable_project_location + data.append(info) + return json.dumps(data) diff --git a/venv/Lib/site-packages/pip/_internal/commands/search.py b/venv/Lib/site-packages/pip/_internal/commands/search.py new file mode 100644 index 0000000..03ed925 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/commands/search.py @@ -0,0 +1,174 @@ +import logging +import shutil +import sys +import textwrap +import xmlrpc.client +from collections import OrderedDict +from optparse import Values +from typing import TYPE_CHECKING, Dict, List, Optional + +from pip._vendor.packaging.version import parse as parse_version + +from pip._internal.cli.base_command import Command +from pip._internal.cli.req_command import SessionCommandMixin +from pip._internal.cli.status_codes import NO_MATCHES_FOUND, SUCCESS +from pip._internal.exceptions import CommandError +from pip._internal.metadata import get_default_environment +from pip._internal.models.index import PyPI +from pip._internal.network.xmlrpc import PipXmlrpcTransport +from pip._internal.utils.logging import indent_log +from pip._internal.utils.misc import write_output + +if TYPE_CHECKING: + from typing import TypedDict + + class TransformedHit(TypedDict): + name: str + summary: str + versions: List[str] + + +logger = logging.getLogger(__name__) + + +class SearchCommand(Command, SessionCommandMixin): + """Search for PyPI packages whose name or summary contains .""" + + usage = """ + %prog [options] """ + ignore_require_venv = True + + def add_options(self) -> None: + self.cmd_opts.add_option( + "-i", + "--index", + dest="index", + metavar="URL", + default=PyPI.pypi_url, + help="Base URL of Python Package Index (default %default)", + ) + + self.parser.insert_option_group(0, self.cmd_opts) + + def run(self, options: Values, args: List[str]) -> int: + if not args: + raise CommandError("Missing required argument (search query).") + query = args + pypi_hits = self.search(query, options) + hits = transform_hits(pypi_hits) + + terminal_width = None + if sys.stdout.isatty(): + terminal_width = shutil.get_terminal_size()[0] + + print_results(hits, terminal_width=terminal_width) + if pypi_hits: + return SUCCESS + return NO_MATCHES_FOUND + + def search(self, query: List[str], options: Values) -> List[Dict[str, str]]: + index_url = options.index + + session = self.get_default_session(options) + + transport = PipXmlrpcTransport(index_url, session) + pypi = xmlrpc.client.ServerProxy(index_url, transport) + try: + hits = pypi.search({"name": query, "summary": query}, "or") + except xmlrpc.client.Fault as fault: + message = "XMLRPC request failed [code: {code}]\n{string}".format( + code=fault.faultCode, + string=fault.faultString, + ) + raise CommandError(message) + assert isinstance(hits, list) + return hits + + +def transform_hits(hits: List[Dict[str, str]]) -> List["TransformedHit"]: + """ + The list from pypi is really a list of versions. We want a list of + packages with the list of versions stored inline. This converts the + list from pypi into one we can use. + """ + packages: Dict[str, "TransformedHit"] = OrderedDict() + for hit in hits: + name = hit["name"] + summary = hit["summary"] + version = hit["version"] + + if name not in packages.keys(): + packages[name] = { + "name": name, + "summary": summary, + "versions": [version], + } + else: + packages[name]["versions"].append(version) + + # if this is the highest version, replace summary and score + if version == highest_version(packages[name]["versions"]): + packages[name]["summary"] = summary + + return list(packages.values()) + + +def print_dist_installation_info(name: str, latest: str) -> None: + env = get_default_environment() + dist = env.get_distribution(name) + if dist is not None: + with indent_log(): + if dist.version == latest: + write_output("INSTALLED: %s (latest)", dist.version) + else: + write_output("INSTALLED: %s", dist.version) + if parse_version(latest).pre: + write_output( + "LATEST: %s (pre-release; install" + " with `pip install --pre`)", + latest, + ) + else: + write_output("LATEST: %s", latest) + + +def print_results( + hits: List["TransformedHit"], + name_column_width: Optional[int] = None, + terminal_width: Optional[int] = None, +) -> None: + if not hits: + return + if name_column_width is None: + name_column_width = ( + max( + [ + len(hit["name"]) + len(highest_version(hit.get("versions", ["-"]))) + for hit in hits + ] + ) + + 4 + ) + + for hit in hits: + name = hit["name"] + summary = hit["summary"] or "" + latest = highest_version(hit.get("versions", ["-"])) + if terminal_width is not None: + target_width = terminal_width - name_column_width - 5 + if target_width > 10: + # wrap and indent summary to fit terminal + summary_lines = textwrap.wrap(summary, target_width) + summary = ("\n" + " " * (name_column_width + 3)).join(summary_lines) + + name_latest = f"{name} ({latest})" + line = f"{name_latest:{name_column_width}} - {summary}" + try: + write_output(line) + print_dist_installation_info(name, latest) + except UnicodeEncodeError: + pass + + +def highest_version(versions: List[str]) -> str: + return max(versions, key=parse_version) diff --git a/venv/Lib/site-packages/pip/_internal/commands/show.py b/venv/Lib/site-packages/pip/_internal/commands/show.py new file mode 100644 index 0000000..d5540d6 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/commands/show.py @@ -0,0 +1,178 @@ +import logging +from optparse import Values +from typing import Iterator, List, NamedTuple, Optional + +from pip._vendor.packaging.utils import canonicalize_name + +from pip._internal.cli.base_command import Command +from pip._internal.cli.status_codes import ERROR, SUCCESS +from pip._internal.metadata import BaseDistribution, get_default_environment +from pip._internal.utils.misc import write_output + +logger = logging.getLogger(__name__) + + +class ShowCommand(Command): + """ + Show information about one or more installed packages. + + The output is in RFC-compliant mail header format. + """ + + usage = """ + %prog [options] ...""" + ignore_require_venv = True + + def add_options(self) -> None: + self.cmd_opts.add_option( + "-f", + "--files", + dest="files", + action="store_true", + default=False, + help="Show the full list of installed files for each package.", + ) + + self.parser.insert_option_group(0, self.cmd_opts) + + def run(self, options: Values, args: List[str]) -> int: + if not args: + logger.warning("ERROR: Please provide a package name or names.") + return ERROR + query = args + + results = search_packages_info(query) + if not print_results( + results, list_files=options.files, verbose=options.verbose + ): + return ERROR + return SUCCESS + + +class _PackageInfo(NamedTuple): + name: str + version: str + location: str + requires: List[str] + required_by: List[str] + installer: str + metadata_version: str + classifiers: List[str] + summary: str + homepage: str + author: str + author_email: str + license: str + entry_points: List[str] + files: Optional[List[str]] + + +def search_packages_info(query: List[str]) -> Iterator[_PackageInfo]: + """ + Gather details from installed distributions. Print distribution name, + version, location, and installed files. Installed files requires a + pip generated 'installed-files.txt' in the distributions '.egg-info' + directory. + """ + env = get_default_environment() + + installed = {dist.canonical_name: dist for dist in env.iter_distributions()} + query_names = [canonicalize_name(name) for name in query] + missing = sorted( + [name for name, pkg in zip(query, query_names) if pkg not in installed] + ) + if missing: + logger.warning("Package(s) not found: %s", ", ".join(missing)) + + def _get_requiring_packages(current_dist: BaseDistribution) -> Iterator[str]: + return ( + dist.metadata["Name"] or "UNKNOWN" + for dist in installed.values() + if current_dist.canonical_name + in {canonicalize_name(d.name) for d in dist.iter_dependencies()} + ) + + for query_name in query_names: + try: + dist = installed[query_name] + except KeyError: + continue + + requires = sorted((req.name for req in dist.iter_dependencies()), key=str.lower) + required_by = sorted(_get_requiring_packages(dist), key=str.lower) + + try: + entry_points_text = dist.read_text("entry_points.txt") + entry_points = entry_points_text.splitlines(keepends=False) + except FileNotFoundError: + entry_points = [] + + files_iter = dist.iter_declared_entries() + if files_iter is None: + files: Optional[List[str]] = None + else: + files = sorted(files_iter) + + metadata = dist.metadata + + yield _PackageInfo( + name=dist.raw_name, + version=str(dist.version), + location=dist.location or "", + requires=requires, + required_by=required_by, + installer=dist.installer, + metadata_version=dist.metadata_version or "", + classifiers=metadata.get_all("Classifier", []), + summary=metadata.get("Summary", ""), + homepage=metadata.get("Home-page", ""), + author=metadata.get("Author", ""), + author_email=metadata.get("Author-email", ""), + license=metadata.get("License", ""), + entry_points=entry_points, + files=files, + ) + + +def print_results( + distributions: Iterator[_PackageInfo], + list_files: bool, + verbose: bool, +) -> bool: + """ + Print the information from installed distributions found. + """ + results_printed = False + for i, dist in enumerate(distributions): + results_printed = True + if i > 0: + write_output("---") + + write_output("Name: %s", dist.name) + write_output("Version: %s", dist.version) + write_output("Summary: %s", dist.summary) + write_output("Home-page: %s", dist.homepage) + write_output("Author: %s", dist.author) + write_output("Author-email: %s", dist.author_email) + write_output("License: %s", dist.license) + write_output("Location: %s", dist.location) + write_output("Requires: %s", ", ".join(dist.requires)) + write_output("Required-by: %s", ", ".join(dist.required_by)) + + if verbose: + write_output("Metadata-Version: %s", dist.metadata_version) + write_output("Installer: %s", dist.installer) + write_output("Classifiers:") + for classifier in dist.classifiers: + write_output(" %s", classifier) + write_output("Entry-points:") + for entry in dist.entry_points: + write_output(" %s", entry.strip()) + if list_files: + write_output("Files:") + if dist.files is None: + write_output("Cannot locate RECORD or installed-files.txt") + else: + for line in dist.files: + write_output(" %s", line.strip()) + return results_printed diff --git a/venv/Lib/site-packages/pip/_internal/commands/uninstall.py b/venv/Lib/site-packages/pip/_internal/commands/uninstall.py new file mode 100644 index 0000000..bb9e8e6 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/commands/uninstall.py @@ -0,0 +1,105 @@ +import logging +from optparse import Values +from typing import List + +from pip._vendor.packaging.utils import canonicalize_name + +from pip._internal.cli.base_command import Command +from pip._internal.cli.req_command import SessionCommandMixin, warn_if_run_as_root +from pip._internal.cli.status_codes import SUCCESS +from pip._internal.exceptions import InstallationError +from pip._internal.req import parse_requirements +from pip._internal.req.constructors import ( + install_req_from_line, + install_req_from_parsed_requirement, +) +from pip._internal.utils.misc import protect_pip_from_modification_on_windows + +logger = logging.getLogger(__name__) + + +class UninstallCommand(Command, SessionCommandMixin): + """ + Uninstall packages. + + pip is able to uninstall most installed packages. Known exceptions are: + + - Pure distutils packages installed with ``python setup.py install``, which + leave behind no metadata to determine what files were installed. + - Script wrappers installed by ``python setup.py develop``. + """ + + usage = """ + %prog [options] ... + %prog [options] -r ...""" + + def add_options(self) -> None: + self.cmd_opts.add_option( + "-r", + "--requirement", + dest="requirements", + action="append", + default=[], + metavar="file", + help=( + "Uninstall all the packages listed in the given requirements " + "file. This option can be used multiple times." + ), + ) + self.cmd_opts.add_option( + "-y", + "--yes", + dest="yes", + action="store_true", + help="Don't ask for confirmation of uninstall deletions.", + ) + + self.parser.insert_option_group(0, self.cmd_opts) + + def run(self, options: Values, args: List[str]) -> int: + session = self.get_default_session(options) + + reqs_to_uninstall = {} + for name in args: + req = install_req_from_line( + name, + isolated=options.isolated_mode, + ) + if req.name: + reqs_to_uninstall[canonicalize_name(req.name)] = req + else: + logger.warning( + "Invalid requirement: %r ignored -" + " the uninstall command expects named" + " requirements.", + name, + ) + for filename in options.requirements: + for parsed_req in parse_requirements( + filename, options=options, session=session + ): + req = install_req_from_parsed_requirement( + parsed_req, isolated=options.isolated_mode + ) + if req.name: + reqs_to_uninstall[canonicalize_name(req.name)] = req + if not reqs_to_uninstall: + raise InstallationError( + f"You must give at least one requirement to {self.name} (see " + f'"pip help {self.name}")' + ) + + protect_pip_from_modification_on_windows( + modifying_pip="pip" in reqs_to_uninstall + ) + + for req in reqs_to_uninstall.values(): + uninstall_pathset = req.uninstall( + auto_confirm=options.yes, + verbose=self.verbosity > 0, + ) + if uninstall_pathset: + uninstall_pathset.commit() + + warn_if_run_as_root() + return SUCCESS diff --git a/venv/Lib/site-packages/pip/_internal/commands/wheel.py b/venv/Lib/site-packages/pip/_internal/commands/wheel.py new file mode 100644 index 0000000..d5b20dc --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/commands/wheel.py @@ -0,0 +1,178 @@ +import logging +import os +import shutil +from optparse import Values +from typing import List + +from pip._internal.cache import WheelCache +from pip._internal.cli import cmdoptions +from pip._internal.cli.req_command import RequirementCommand, with_cleanup +from pip._internal.cli.status_codes import SUCCESS +from pip._internal.exceptions import CommandError +from pip._internal.req.req_install import InstallRequirement +from pip._internal.req.req_tracker import get_requirement_tracker +from pip._internal.utils.misc import ensure_dir, normalize_path +from pip._internal.utils.temp_dir import TempDirectory +from pip._internal.wheel_builder import build, should_build_for_wheel_command + +logger = logging.getLogger(__name__) + + +class WheelCommand(RequirementCommand): + """ + Build Wheel archives for your requirements and dependencies. + + Wheel is a built-package format, and offers the advantage of not + recompiling your software during every install. For more details, see the + wheel docs: https://wheel.readthedocs.io/en/latest/ + + Requirements: setuptools>=0.8, and wheel. + + 'pip wheel' uses the bdist_wheel setuptools extension from the wheel + package to build individual wheels. + + """ + + usage = """ + %prog [options] ... + %prog [options] -r ... + %prog [options] [-e] ... + %prog [options] [-e] ... + %prog [options] ...""" + + def add_options(self) -> None: + + self.cmd_opts.add_option( + "-w", + "--wheel-dir", + dest="wheel_dir", + metavar="dir", + default=os.curdir, + help=( + "Build wheels into , where the default is the " + "current working directory." + ), + ) + self.cmd_opts.add_option(cmdoptions.no_binary()) + self.cmd_opts.add_option(cmdoptions.only_binary()) + self.cmd_opts.add_option(cmdoptions.prefer_binary()) + self.cmd_opts.add_option(cmdoptions.no_build_isolation()) + self.cmd_opts.add_option(cmdoptions.use_pep517()) + self.cmd_opts.add_option(cmdoptions.no_use_pep517()) + self.cmd_opts.add_option(cmdoptions.constraints()) + self.cmd_opts.add_option(cmdoptions.editable()) + self.cmd_opts.add_option(cmdoptions.requirements()) + self.cmd_opts.add_option(cmdoptions.src()) + self.cmd_opts.add_option(cmdoptions.ignore_requires_python()) + self.cmd_opts.add_option(cmdoptions.no_deps()) + self.cmd_opts.add_option(cmdoptions.progress_bar()) + + self.cmd_opts.add_option( + "--no-verify", + dest="no_verify", + action="store_true", + default=False, + help="Don't verify if built wheel is valid.", + ) + + self.cmd_opts.add_option(cmdoptions.build_options()) + self.cmd_opts.add_option(cmdoptions.global_options()) + + self.cmd_opts.add_option( + "--pre", + action="store_true", + default=False, + help=( + "Include pre-release and development versions. By default, " + "pip only finds stable versions." + ), + ) + + self.cmd_opts.add_option(cmdoptions.require_hashes()) + + index_opts = cmdoptions.make_option_group( + cmdoptions.index_group, + self.parser, + ) + + self.parser.insert_option_group(0, index_opts) + self.parser.insert_option_group(0, self.cmd_opts) + + @with_cleanup + def run(self, options: Values, args: List[str]) -> int: + cmdoptions.check_install_build_global(options) + + session = self.get_default_session(options) + + finder = self._build_package_finder(options, session) + wheel_cache = WheelCache(options.cache_dir, options.format_control) + + options.wheel_dir = normalize_path(options.wheel_dir) + ensure_dir(options.wheel_dir) + + req_tracker = self.enter_context(get_requirement_tracker()) + + directory = TempDirectory( + delete=not options.no_clean, + kind="wheel", + globally_managed=True, + ) + + reqs = self.get_requirements(args, options, finder, session) + + preparer = self.make_requirement_preparer( + temp_build_dir=directory, + options=options, + req_tracker=req_tracker, + session=session, + finder=finder, + download_dir=options.wheel_dir, + use_user_site=False, + verbosity=self.verbosity, + ) + + resolver = self.make_resolver( + preparer=preparer, + finder=finder, + options=options, + wheel_cache=wheel_cache, + ignore_requires_python=options.ignore_requires_python, + use_pep517=options.use_pep517, + ) + + self.trace_basic_info(finder) + + requirement_set = resolver.resolve(reqs, check_supported_wheels=True) + + reqs_to_build: List[InstallRequirement] = [] + for req in requirement_set.requirements.values(): + if req.is_wheel: + preparer.save_linked_requirement(req) + elif should_build_for_wheel_command(req): + reqs_to_build.append(req) + + # build wheels + build_successes, build_failures = build( + reqs_to_build, + wheel_cache=wheel_cache, + verify=(not options.no_verify), + build_options=options.build_options or [], + global_options=options.global_options or [], + ) + for req in build_successes: + assert req.link and req.link.is_wheel + assert req.local_file_path + # copy from cache to target directory + try: + shutil.copy(req.local_file_path, options.wheel_dir) + except OSError as e: + logger.warning( + "Building wheel for %s failed: %s", + req.name, + e, + ) + build_failures.append(req) + if len(build_failures) != 0: + raise CommandError("Failed to build one or more wheels") + + return SUCCESS diff --git a/venv/Lib/site-packages/pip/_internal/configuration.py b/venv/Lib/site-packages/pip/_internal/configuration.py new file mode 100644 index 0000000..a8092d1 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/configuration.py @@ -0,0 +1,366 @@ +"""Configuration management setup + +Some terminology: +- name + As written in config files. +- value + Value associated with a name +- key + Name combined with it's section (section.name) +- variant + A single word describing where the configuration key-value pair came from +""" + +import configparser +import locale +import os +import sys +from typing import Any, Dict, Iterable, List, NewType, Optional, Tuple + +from pip._internal.exceptions import ( + ConfigurationError, + ConfigurationFileCouldNotBeLoaded, +) +from pip._internal.utils import appdirs +from pip._internal.utils.compat import WINDOWS +from pip._internal.utils.logging import getLogger +from pip._internal.utils.misc import ensure_dir, enum + +RawConfigParser = configparser.RawConfigParser # Shorthand +Kind = NewType("Kind", str) + +CONFIG_BASENAME = "pip.ini" if WINDOWS else "pip.conf" +ENV_NAMES_IGNORED = "version", "help" + +# The kinds of configurations there are. +kinds = enum( + USER="user", # User Specific + GLOBAL="global", # System Wide + SITE="site", # [Virtual] Environment Specific + ENV="env", # from PIP_CONFIG_FILE + ENV_VAR="env-var", # from Environment Variables +) +OVERRIDE_ORDER = kinds.GLOBAL, kinds.USER, kinds.SITE, kinds.ENV, kinds.ENV_VAR +VALID_LOAD_ONLY = kinds.USER, kinds.GLOBAL, kinds.SITE + +logger = getLogger(__name__) + + +# NOTE: Maybe use the optionx attribute to normalize keynames. +def _normalize_name(name: str) -> str: + """Make a name consistent regardless of source (environment or file)""" + name = name.lower().replace("_", "-") + if name.startswith("--"): + name = name[2:] # only prefer long opts + return name + + +def _disassemble_key(name: str) -> List[str]: + if "." not in name: + error_message = ( + "Key does not contain dot separated section and key. " + "Perhaps you wanted to use 'global.{}' instead?" + ).format(name) + raise ConfigurationError(error_message) + return name.split(".", 1) + + +def get_configuration_files() -> Dict[Kind, List[str]]: + global_config_files = [ + os.path.join(path, CONFIG_BASENAME) for path in appdirs.site_config_dirs("pip") + ] + + site_config_file = os.path.join(sys.prefix, CONFIG_BASENAME) + legacy_config_file = os.path.join( + os.path.expanduser("~"), + "pip" if WINDOWS else ".pip", + CONFIG_BASENAME, + ) + new_config_file = os.path.join(appdirs.user_config_dir("pip"), CONFIG_BASENAME) + return { + kinds.GLOBAL: global_config_files, + kinds.SITE: [site_config_file], + kinds.USER: [legacy_config_file, new_config_file], + } + + +class Configuration: + """Handles management of configuration. + + Provides an interface to accessing and managing configuration files. + + This class converts provides an API that takes "section.key-name" style + keys and stores the value associated with it as "key-name" under the + section "section". + + This allows for a clean interface wherein the both the section and the + key-name are preserved in an easy to manage form in the configuration files + and the data stored is also nice. + """ + + def __init__(self, isolated: bool, load_only: Optional[Kind] = None) -> None: + super().__init__() + + if load_only is not None and load_only not in VALID_LOAD_ONLY: + raise ConfigurationError( + "Got invalid value for load_only - should be one of {}".format( + ", ".join(map(repr, VALID_LOAD_ONLY)) + ) + ) + self.isolated = isolated + self.load_only = load_only + + # Because we keep track of where we got the data from + self._parsers: Dict[Kind, List[Tuple[str, RawConfigParser]]] = { + variant: [] for variant in OVERRIDE_ORDER + } + self._config: Dict[Kind, Dict[str, Any]] = { + variant: {} for variant in OVERRIDE_ORDER + } + self._modified_parsers: List[Tuple[str, RawConfigParser]] = [] + + def load(self) -> None: + """Loads configuration from configuration files and environment""" + self._load_config_files() + if not self.isolated: + self._load_environment_vars() + + def get_file_to_edit(self) -> Optional[str]: + """Returns the file with highest priority in configuration""" + assert self.load_only is not None, "Need to be specified a file to be editing" + + try: + return self._get_parser_to_modify()[0] + except IndexError: + return None + + def items(self) -> Iterable[Tuple[str, Any]]: + """Returns key-value pairs like dict.items() representing the loaded + configuration + """ + return self._dictionary.items() + + def get_value(self, key: str) -> Any: + """Get a value from the configuration.""" + try: + return self._dictionary[key] + except KeyError: + raise ConfigurationError(f"No such key - {key}") + + def set_value(self, key: str, value: Any) -> None: + """Modify a value in the configuration.""" + self._ensure_have_load_only() + + assert self.load_only + fname, parser = self._get_parser_to_modify() + + if parser is not None: + section, name = _disassemble_key(key) + + # Modify the parser and the configuration + if not parser.has_section(section): + parser.add_section(section) + parser.set(section, name, value) + + self._config[self.load_only][key] = value + self._mark_as_modified(fname, parser) + + def unset_value(self, key: str) -> None: + """Unset a value in the configuration.""" + self._ensure_have_load_only() + + assert self.load_only + if key not in self._config[self.load_only]: + raise ConfigurationError(f"No such key - {key}") + + fname, parser = self._get_parser_to_modify() + + if parser is not None: + section, name = _disassemble_key(key) + if not ( + parser.has_section(section) and parser.remove_option(section, name) + ): + # The option was not removed. + raise ConfigurationError( + "Fatal Internal error [id=1]. Please report as a bug." + ) + + # The section may be empty after the option was removed. + if not parser.items(section): + parser.remove_section(section) + self._mark_as_modified(fname, parser) + + del self._config[self.load_only][key] + + def save(self) -> None: + """Save the current in-memory state.""" + self._ensure_have_load_only() + + for fname, parser in self._modified_parsers: + logger.info("Writing to %s", fname) + + # Ensure directory exists. + ensure_dir(os.path.dirname(fname)) + + with open(fname, "w") as f: + parser.write(f) + + # + # Private routines + # + + def _ensure_have_load_only(self) -> None: + if self.load_only is None: + raise ConfigurationError("Needed a specific file to be modifying.") + logger.debug("Will be working with %s variant only", self.load_only) + + @property + def _dictionary(self) -> Dict[str, Any]: + """A dictionary representing the loaded configuration.""" + # NOTE: Dictionaries are not populated if not loaded. So, conditionals + # are not needed here. + retval = {} + + for variant in OVERRIDE_ORDER: + retval.update(self._config[variant]) + + return retval + + def _load_config_files(self) -> None: + """Loads configuration from configuration files""" + config_files = dict(self.iter_config_files()) + if config_files[kinds.ENV][0:1] == [os.devnull]: + logger.debug( + "Skipping loading configuration files due to " + "environment's PIP_CONFIG_FILE being os.devnull" + ) + return + + for variant, files in config_files.items(): + for fname in files: + # If there's specific variant set in `load_only`, load only + # that variant, not the others. + if self.load_only is not None and variant != self.load_only: + logger.debug("Skipping file '%s' (variant: %s)", fname, variant) + continue + + parser = self._load_file(variant, fname) + + # Keeping track of the parsers used + self._parsers[variant].append((fname, parser)) + + def _load_file(self, variant: Kind, fname: str) -> RawConfigParser: + logger.verbose("For variant '%s', will try loading '%s'", variant, fname) + parser = self._construct_parser(fname) + + for section in parser.sections(): + items = parser.items(section) + self._config[variant].update(self._normalized_keys(section, items)) + + return parser + + def _construct_parser(self, fname: str) -> RawConfigParser: + parser = configparser.RawConfigParser() + # If there is no such file, don't bother reading it but create the + # parser anyway, to hold the data. + # Doing this is useful when modifying and saving files, where we don't + # need to construct a parser. + if os.path.exists(fname): + locale_encoding = locale.getpreferredencoding(False) + try: + parser.read(fname, encoding=locale_encoding) + except UnicodeDecodeError: + # See https://github.com/pypa/pip/issues/4963 + raise ConfigurationFileCouldNotBeLoaded( + reason=f"contains invalid {locale_encoding} characters", + fname=fname, + ) + except configparser.Error as error: + # See https://github.com/pypa/pip/issues/4893 + raise ConfigurationFileCouldNotBeLoaded(error=error) + return parser + + def _load_environment_vars(self) -> None: + """Loads configuration from environment variables""" + self._config[kinds.ENV_VAR].update( + self._normalized_keys(":env:", self.get_environ_vars()) + ) + + def _normalized_keys( + self, section: str, items: Iterable[Tuple[str, Any]] + ) -> Dict[str, Any]: + """Normalizes items to construct a dictionary with normalized keys. + + This routine is where the names become keys and are made the same + regardless of source - configuration files or environment. + """ + normalized = {} + for name, val in items: + key = section + "." + _normalize_name(name) + normalized[key] = val + return normalized + + def get_environ_vars(self) -> Iterable[Tuple[str, str]]: + """Returns a generator with all environmental vars with prefix PIP_""" + for key, val in os.environ.items(): + if key.startswith("PIP_"): + name = key[4:].lower() + if name not in ENV_NAMES_IGNORED: + yield name, val + + # XXX: This is patched in the tests. + def iter_config_files(self) -> Iterable[Tuple[Kind, List[str]]]: + """Yields variant and configuration files associated with it. + + This should be treated like items of a dictionary. + """ + # SMELL: Move the conditions out of this function + + # environment variables have the lowest priority + config_file = os.environ.get("PIP_CONFIG_FILE", None) + if config_file is not None: + yield kinds.ENV, [config_file] + else: + yield kinds.ENV, [] + + config_files = get_configuration_files() + + # at the base we have any global configuration + yield kinds.GLOBAL, config_files[kinds.GLOBAL] + + # per-user configuration next + should_load_user_config = not self.isolated and not ( + config_file and os.path.exists(config_file) + ) + if should_load_user_config: + # The legacy config file is overridden by the new config file + yield kinds.USER, config_files[kinds.USER] + + # finally virtualenv configuration first trumping others + yield kinds.SITE, config_files[kinds.SITE] + + def get_values_in_config(self, variant: Kind) -> Dict[str, Any]: + """Get values present in a config file""" + return self._config[variant] + + def _get_parser_to_modify(self) -> Tuple[str, RawConfigParser]: + # Determine which parser to modify + assert self.load_only + parsers = self._parsers[self.load_only] + if not parsers: + # This should not happen if everything works correctly. + raise ConfigurationError( + "Fatal Internal error [id=2]. Please report as a bug." + ) + + # Use the highest priority parser. + return parsers[-1] + + # XXX: This is patched in the tests. + def _mark_as_modified(self, fname: str, parser: RawConfigParser) -> None: + file_parser_tuple = (fname, parser) + if file_parser_tuple not in self._modified_parsers: + self._modified_parsers.append(file_parser_tuple) + + def __repr__(self) -> str: + return f"{self.__class__.__name__}({self._dictionary!r})" diff --git a/venv/Lib/site-packages/pip/_internal/distributions/__init__.py b/venv/Lib/site-packages/pip/_internal/distributions/__init__.py new file mode 100644 index 0000000..9a89a83 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/distributions/__init__.py @@ -0,0 +1,21 @@ +from pip._internal.distributions.base import AbstractDistribution +from pip._internal.distributions.sdist import SourceDistribution +from pip._internal.distributions.wheel import WheelDistribution +from pip._internal.req.req_install import InstallRequirement + + +def make_distribution_for_install_requirement( + install_req: InstallRequirement, +) -> AbstractDistribution: + """Returns a Distribution for the given InstallRequirement""" + # Editable requirements will always be source distributions. They use the + # legacy logic until we create a modern standard for them. + if install_req.editable: + return SourceDistribution(install_req) + + # If it's a wheel, it's a WheelDistribution + if install_req.is_wheel: + return WheelDistribution(install_req) + + # Otherwise, a SourceDistribution + return SourceDistribution(install_req) diff --git a/venv/Lib/site-packages/pip/_internal/distributions/__pycache__/__init__.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/distributions/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..79958374b2b0b1a4e0835581f053ff3e467ae130 GIT binary patch literal 788 zcmaJ#iL>b5psC%s8U2)`YwWa=u?Cc2%GF^x7}>g-HpZ4n_m3~ z{sI3|uAcl09>m$LPh*j8n9a<$lbLV6EZg3`L2!M(_pmNPLcY0Rx)39KXl98UC!9*s z(t=Xw2Qp~GBJ_SJqjpxzydTN9O^SpPNPzO$mw?AS`4kl?Pgf-0_>PrGPRHB(wXvEt zb}8^J>cNUmA-=Qf2Hn6F^wygr0C@%6d9I9QQXazTAT+d~Y#xl8;u5VioQ|;uJ80EV z*Y)>uet>p>W**>nL5_*OY3T*|NLMZj^c@>sMr$;u=Z_D4Et9cqN+f&R>C7HM_D;M9 zmHmfPG^W6XWwiwD6dhAxsxvo`jxfxrj`8)CX!kRIz`<_$+JH7CQ;L~#zwejKvhqdO zFj>BWwl90p&j;1B<^=fM7n(nMax6?^&fQsA31vYmOy?7EO&2Jnv6t`z)KeE|vLK`H$Dl87AE3tdvfKY`HX#%JcM2LjTXeG-tcCr(^$;V zu{v6?_zFI^50fO4Y7*mrpy@1#1B!B}!&wwZwH)cztR1&0`Ig9*Y+n-DR^+rJJFmjH zE9oH_cK-rT0`_;~F0=Pu#SMiBKK*%mj05(gtaE=`t%cdfiI?GR3 z)<74DR!mr*9fP?W_j(M*(Nr<}np0yb@^e4^uO(RHxz^^)J!;I^h@B}mE1hQv9ODh% zFsZzZRv3p+;Hm`%k(gf~ z2g(a6ycpNp2g9HWA+J^2LRf5`LV+v?%J_xwxgD51c|m@se-KKZ)8~W-k{pt2dN2&D zmMaTot1jnRo_Wq~8`QyfP(KjmiClSvZi4kaF3v5sigyq@ zbP7Ufk6zrr=~avupoi3UKryALJ|8IKw+Ej?hZuuj;l&;j+l3|2x_4mwlUbqb$FAhp z)*9#zb`wtRo#nIzQuXeM@_dm2zKZ$-ICgdLgNyNvDF4?K!rwlwds4NPl$n-1b4Cj+ zz=jXzZ!u85jgQ?1g<;sBzX!6##J|boeqmK1tXiY6B*ws^;SybZdLx%x&4+iej<5r8 zUiCPi8ChzS`5g`S^uIF}}cQp4=lxvoNyq}3fU?|cyFsgV{L+q*bnc&jKeM%%Yh z9L(!6Ra%3e*SYGWHYUtstHv}t3`>_rTRTxix5FriXz)*c3O#=VGg?>naKpX_iq%I@ zp5tYCjxjmU#`7M)n_Sgs;`i4T7o{=A60VWQZ>?*LM;f2!Go}eMnRAwBGwi~kwvs#LSUF=-gZ;-uQLg{iznNI z7r#M2fPST1J^2+ph;Nd1n?iM#ynT7|X6E;2!bhV4!SU_(-SE3X$WQ&!9TvVk#Yb&n z5Jb>~q|~QW=SE_rrf)X6nOLdq+myT@!V>l|5jM~x(|3gPj*NT1a5WjzdVM=orQ}h$ z8{>Z*R%M)LSRcLN(FeW{&*Myh#KP5QTtT-f(mQm=64`yM0`aLJz9Fb@f+dU-DokM= zTfPkr^n@*(6I1j=A1i%fBchf1`pZm}JV`)wk6CB1PkYQrlla6{vc9ci{I0oN5OjqQUyHAxC*w5VwaaZc%4T) z3HBf@f+8+9t4xanV)Nq+AlZDlbr7paE%aQ#;;aOjVY}#9u7ahoUNNt4>_f>?D7nDh zS+{YdX=ENc3skc5II@j_x(&{q> zK?&)k(PC`M6)Z^&NUrLj6>7s3%<5aM_izFJlGHV9QQ9|RE*@OY;=k+h!uA=@6FHGDbLL9?o@FwYaYrr*zDH<`vRZ46otrAvKkIjgos zjXzC&GVawbI_WK)^tuKqFT^iZYHIbJi)~u>Pu}Tw!&(~}IR3`P#xv(z)EdlXDC_>? Pmh}^DlG1pG6o2MlkcCpz literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/distributions/__pycache__/sdist.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/distributions/__pycache__/sdist.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5a83f7a50f28a65f530bf7e22e7e936f1e053aee GIT binary patch literal 4544 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 RF?5%j>BTb%Cn%kx;omfU#moQz literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/distributions/base.py b/venv/Lib/site-packages/pip/_internal/distributions/base.py new file mode 100644 index 0000000..149fff5 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/distributions/base.py @@ -0,0 +1,36 @@ +import abc + +from pip._internal.index.package_finder import PackageFinder +from pip._internal.metadata.base import BaseDistribution +from pip._internal.req import InstallRequirement + + +class AbstractDistribution(metaclass=abc.ABCMeta): + """A base class for handling installable artifacts. + + The requirements for anything installable are as follows: + + - we must be able to determine the requirement name + (or we can't correctly handle the non-upgrade case). + + - for packages with setup requirements, we must also be able + to determine their requirements without installing additional + packages (for the same reason as run-time dependencies) + + - we must be able to create a Distribution object exposing the + above metadata. + """ + + def __init__(self, req: InstallRequirement) -> None: + super().__init__() + self.req = req + + @abc.abstractmethod + def get_metadata_distribution(self) -> BaseDistribution: + raise NotImplementedError() + + @abc.abstractmethod + def prepare_distribution_metadata( + self, finder: PackageFinder, build_isolation: bool + ) -> None: + raise NotImplementedError() diff --git a/venv/Lib/site-packages/pip/_internal/distributions/installed.py b/venv/Lib/site-packages/pip/_internal/distributions/installed.py new file mode 100644 index 0000000..be5962f --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/distributions/installed.py @@ -0,0 +1,20 @@ +from pip._internal.distributions.base import AbstractDistribution +from pip._internal.index.package_finder import PackageFinder +from pip._internal.metadata import BaseDistribution + + +class InstalledDistribution(AbstractDistribution): + """Represents an installed package. + + This does not need any preparation as the required information has already + been computed. + """ + + def get_metadata_distribution(self) -> BaseDistribution: + assert self.req.satisfied_by is not None, "not actually installed" + return self.req.satisfied_by + + def prepare_distribution_metadata( + self, finder: PackageFinder, build_isolation: bool + ) -> None: + pass diff --git a/venv/Lib/site-packages/pip/_internal/distributions/sdist.py b/venv/Lib/site-packages/pip/_internal/distributions/sdist.py new file mode 100644 index 0000000..bdaf403 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/distributions/sdist.py @@ -0,0 +1,127 @@ +import logging +from typing import Iterable, Set, Tuple + +from pip._internal.build_env import BuildEnvironment +from pip._internal.distributions.base import AbstractDistribution +from pip._internal.exceptions import InstallationError +from pip._internal.index.package_finder import PackageFinder +from pip._internal.metadata import BaseDistribution +from pip._internal.utils.subprocess import runner_with_spinner_message + +logger = logging.getLogger(__name__) + + +class SourceDistribution(AbstractDistribution): + """Represents a source distribution. + + The preparation step for these needs metadata for the packages to be + generated, either using PEP 517 or using the legacy `setup.py egg_info`. + """ + + def get_metadata_distribution(self) -> BaseDistribution: + return self.req.get_dist() + + def prepare_distribution_metadata( + self, finder: PackageFinder, build_isolation: bool + ) -> None: + # Load pyproject.toml, to determine whether PEP 517 is to be used + self.req.load_pyproject_toml() + + # Set up the build isolation, if this requirement should be isolated + should_isolate = self.req.use_pep517 and build_isolation + if should_isolate: + # Setup an isolated environment and install the build backend static + # requirements in it. + self._prepare_build_backend(finder) + # Check that if the requirement is editable, it either supports PEP 660 or + # has a setup.py or a setup.cfg. This cannot be done earlier because we need + # to setup the build backend to verify it supports build_editable, nor can + # it be done later, because we want to avoid installing build requirements + # needlessly. Doing it here also works around setuptools generating + # UNKNOWN.egg-info when running get_requires_for_build_wheel on a directory + # without setup.py nor setup.cfg. + self.req.isolated_editable_sanity_check() + # Install the dynamic build requirements. + self._install_build_reqs(finder) + + self.req.prepare_metadata() + + def _prepare_build_backend(self, finder: PackageFinder) -> None: + # Isolate in a BuildEnvironment and install the build-time + # requirements. + pyproject_requires = self.req.pyproject_requires + assert pyproject_requires is not None + + self.req.build_env = BuildEnvironment() + self.req.build_env.install_requirements( + finder, pyproject_requires, "overlay", kind="build dependencies" + ) + conflicting, missing = self.req.build_env.check_requirements( + self.req.requirements_to_check + ) + if conflicting: + self._raise_conflicts("PEP 517/518 supported requirements", conflicting) + if missing: + logger.warning( + "Missing build requirements in pyproject.toml for %s.", + self.req, + ) + logger.warning( + "The project does not specify a build backend, and " + "pip cannot fall back to setuptools without %s.", + " and ".join(map(repr, sorted(missing))), + ) + + def _get_build_requires_wheel(self) -> Iterable[str]: + with self.req.build_env: + runner = runner_with_spinner_message("Getting requirements to build wheel") + backend = self.req.pep517_backend + assert backend is not None + with backend.subprocess_runner(runner): + return backend.get_requires_for_build_wheel() + + def _get_build_requires_editable(self) -> Iterable[str]: + with self.req.build_env: + runner = runner_with_spinner_message( + "Getting requirements to build editable" + ) + backend = self.req.pep517_backend + assert backend is not None + with backend.subprocess_runner(runner): + return backend.get_requires_for_build_editable() + + def _install_build_reqs(self, finder: PackageFinder) -> None: + # Install any extra build dependencies that the backend requests. + # This must be done in a second pass, as the pyproject.toml + # dependencies must be installed before we can call the backend. + if ( + self.req.editable + and self.req.permit_editable_wheels + and self.req.supports_pyproject_editable() + ): + build_reqs = self._get_build_requires_editable() + else: + build_reqs = self._get_build_requires_wheel() + conflicting, missing = self.req.build_env.check_requirements(build_reqs) + if conflicting: + self._raise_conflicts("the backend dependencies", conflicting) + self.req.build_env.install_requirements( + finder, missing, "normal", kind="backend dependencies" + ) + + def _raise_conflicts( + self, conflicting_with: str, conflicting_reqs: Set[Tuple[str, str]] + ) -> None: + format_string = ( + "Some build dependencies for {requirement} " + "conflict with {conflicting_with}: {description}." + ) + error_message = format_string.format( + requirement=self.req, + conflicting_with=conflicting_with, + description=", ".join( + f"{installed} is incompatible with {wanted}" + for installed, wanted in sorted(conflicting_reqs) + ), + ) + raise InstallationError(error_message) diff --git a/venv/Lib/site-packages/pip/_internal/distributions/wheel.py b/venv/Lib/site-packages/pip/_internal/distributions/wheel.py new file mode 100644 index 0000000..340b0f3 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/distributions/wheel.py @@ -0,0 +1,31 @@ +from pip._vendor.packaging.utils import canonicalize_name + +from pip._internal.distributions.base import AbstractDistribution +from pip._internal.index.package_finder import PackageFinder +from pip._internal.metadata import ( + BaseDistribution, + FilesystemWheel, + get_wheel_distribution, +) + + +class WheelDistribution(AbstractDistribution): + """Represents a wheel distribution. + + This does not need any preparation as wheels can be directly unpacked. + """ + + def get_metadata_distribution(self) -> BaseDistribution: + """Loads the metadata from the wheel file into memory and returns a + Distribution that uses it, not relying on the wheel file or + requirement. + """ + assert self.req.local_file_path, "Set as part of preparation during download" + assert self.req.name, "Wheels are never unnamed" + wheel = FilesystemWheel(self.req.local_file_path) + return get_wheel_distribution(wheel, canonicalize_name(self.req.name)) + + def prepare_distribution_metadata( + self, finder: PackageFinder, build_isolation: bool + ) -> None: + pass diff --git a/venv/Lib/site-packages/pip/_internal/exceptions.py b/venv/Lib/site-packages/pip/_internal/exceptions.py new file mode 100644 index 0000000..97b9612 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/exceptions.py @@ -0,0 +1,658 @@ +"""Exceptions used throughout package. + +This module MUST NOT try to import from anything within `pip._internal` to +operate. This is expected to be importable from any/all files within the +subpackage and, thus, should not depend on them. +""" + +import configparser +import re +from itertools import chain, groupby, repeat +from typing import TYPE_CHECKING, Dict, List, Optional, Union + +from pip._vendor.requests.models import Request, Response +from pip._vendor.rich.console import Console, ConsoleOptions, RenderResult +from pip._vendor.rich.markup import escape +from pip._vendor.rich.text import Text + +if TYPE_CHECKING: + from hashlib import _Hash + from typing import Literal + + from pip._internal.metadata import BaseDistribution + from pip._internal.req.req_install import InstallRequirement + + +# +# Scaffolding +# +def _is_kebab_case(s: str) -> bool: + return re.match(r"^[a-z]+(-[a-z]+)*$", s) is not None + + +def _prefix_with_indent( + s: Union[Text, str], + console: Console, + *, + prefix: str, + indent: str, +) -> Text: + if isinstance(s, Text): + text = s + else: + text = console.render_str(s) + + return console.render_str(prefix, overflow="ignore") + console.render_str( + f"\n{indent}", overflow="ignore" + ).join(text.split(allow_blank=True)) + + +class PipError(Exception): + """The base pip error.""" + + +class DiagnosticPipError(PipError): + """An error, that presents diagnostic information to the user. + + This contains a bunch of logic, to enable pretty presentation of our error + messages. Each error gets a unique reference. Each error can also include + additional context, a hint and/or a note -- which are presented with the + main error message in a consistent style. + + This is adapted from the error output styling in `sphinx-theme-builder`. + """ + + reference: str + + def __init__( + self, + *, + kind: 'Literal["error", "warning"]' = "error", + reference: Optional[str] = None, + message: Union[str, Text], + context: Optional[Union[str, Text]], + hint_stmt: Optional[Union[str, Text]], + note_stmt: Optional[Union[str, Text]] = None, + link: Optional[str] = None, + ) -> None: + # Ensure a proper reference is provided. + if reference is None: + assert hasattr(self, "reference"), "error reference not provided!" + reference = self.reference + assert _is_kebab_case(reference), "error reference must be kebab-case!" + + self.kind = kind + self.reference = reference + + self.message = message + self.context = context + + self.note_stmt = note_stmt + self.hint_stmt = hint_stmt + + self.link = link + + super().__init__(f"<{self.__class__.__name__}: {self.reference}>") + + def __repr__(self) -> str: + return ( + f"<{self.__class__.__name__}(" + f"reference={self.reference!r}, " + f"message={self.message!r}, " + f"context={self.context!r}, " + f"note_stmt={self.note_stmt!r}, " + f"hint_stmt={self.hint_stmt!r}" + ")>" + ) + + def __rich_console__( + self, + console: Console, + options: ConsoleOptions, + ) -> RenderResult: + colour = "red" if self.kind == "error" else "yellow" + + yield f"[{colour} bold]{self.kind}[/]: [bold]{self.reference}[/]" + yield "" + + if not options.ascii_only: + # Present the main message, with relevant context indented. + if self.context is not None: + yield _prefix_with_indent( + self.message, + console, + prefix=f"[{colour}]×[/] ", + indent=f"[{colour}]│[/] ", + ) + yield _prefix_with_indent( + self.context, + console, + prefix=f"[{colour}]╰─>[/] ", + indent=f"[{colour}] [/] ", + ) + else: + yield _prefix_with_indent( + self.message, + console, + prefix="[red]×[/] ", + indent=" ", + ) + else: + yield self.message + if self.context is not None: + yield "" + yield self.context + + if self.note_stmt is not None or self.hint_stmt is not None: + yield "" + + if self.note_stmt is not None: + yield _prefix_with_indent( + self.note_stmt, + console, + prefix="[magenta bold]note[/]: ", + indent=" ", + ) + if self.hint_stmt is not None: + yield _prefix_with_indent( + self.hint_stmt, + console, + prefix="[cyan bold]hint[/]: ", + indent=" ", + ) + + if self.link is not None: + yield "" + yield f"Link: {self.link}" + + +# +# Actual Errors +# +class ConfigurationError(PipError): + """General exception in configuration""" + + +class InstallationError(PipError): + """General exception during installation""" + + +class UninstallationError(PipError): + """General exception during uninstallation""" + + +class MissingPyProjectBuildRequires(DiagnosticPipError): + """Raised when pyproject.toml has `build-system`, but no `build-system.requires`.""" + + reference = "missing-pyproject-build-system-requires" + + def __init__(self, *, package: str) -> None: + super().__init__( + message=f"Can not process {escape(package)}", + context=Text( + "This package has an invalid pyproject.toml file.\n" + "The [build-system] table is missing the mandatory `requires` key." + ), + note_stmt="This is an issue with the package mentioned above, not pip.", + hint_stmt=Text("See PEP 518 for the detailed specification."), + ) + + +class InvalidPyProjectBuildRequires(DiagnosticPipError): + """Raised when pyproject.toml an invalid `build-system.requires`.""" + + reference = "invalid-pyproject-build-system-requires" + + def __init__(self, *, package: str, reason: str) -> None: + super().__init__( + message=f"Can not process {escape(package)}", + context=Text( + "This package has an invalid `build-system.requires` key in " + f"pyproject.toml.\n{reason}" + ), + note_stmt="This is an issue with the package mentioned above, not pip.", + hint_stmt=Text("See PEP 518 for the detailed specification."), + ) + + +class NoneMetadataError(PipError): + """Raised when accessing a Distribution's "METADATA" or "PKG-INFO". + + This signifies an inconsistency, when the Distribution claims to have + the metadata file (if not, raise ``FileNotFoundError`` instead), but is + not actually able to produce its content. This may be due to permission + errors. + """ + + def __init__( + self, + dist: "BaseDistribution", + metadata_name: str, + ) -> None: + """ + :param dist: A Distribution object. + :param metadata_name: The name of the metadata being accessed + (can be "METADATA" or "PKG-INFO"). + """ + self.dist = dist + self.metadata_name = metadata_name + + def __str__(self) -> str: + # Use `dist` in the error message because its stringification + # includes more information, like the version and location. + return "None {} metadata found for distribution: {}".format( + self.metadata_name, + self.dist, + ) + + +class UserInstallationInvalid(InstallationError): + """A --user install is requested on an environment without user site.""" + + def __str__(self) -> str: + return "User base directory is not specified" + + +class InvalidSchemeCombination(InstallationError): + def __str__(self) -> str: + before = ", ".join(str(a) for a in self.args[:-1]) + return f"Cannot set {before} and {self.args[-1]} together" + + +class DistributionNotFound(InstallationError): + """Raised when a distribution cannot be found to satisfy a requirement""" + + +class RequirementsFileParseError(InstallationError): + """Raised when a general error occurs parsing a requirements file line.""" + + +class BestVersionAlreadyInstalled(PipError): + """Raised when the most up-to-date version of a package is already + installed.""" + + +class BadCommand(PipError): + """Raised when virtualenv or a command is not found""" + + +class CommandError(PipError): + """Raised when there is an error in command-line arguments""" + + +class PreviousBuildDirError(PipError): + """Raised when there's a previous conflicting build directory""" + + +class NetworkConnectionError(PipError): + """HTTP connection error""" + + def __init__( + self, error_msg: str, response: Response = None, request: Request = None + ) -> None: + """ + Initialize NetworkConnectionError with `request` and `response` + objects. + """ + self.response = response + self.request = request + self.error_msg = error_msg + if ( + self.response is not None + and not self.request + and hasattr(response, "request") + ): + self.request = self.response.request + super().__init__(error_msg, response, request) + + def __str__(self) -> str: + return str(self.error_msg) + + +class InvalidWheelFilename(InstallationError): + """Invalid wheel filename.""" + + +class UnsupportedWheel(InstallationError): + """Unsupported wheel.""" + + +class InvalidWheel(InstallationError): + """Invalid (e.g. corrupt) wheel.""" + + def __init__(self, location: str, name: str): + self.location = location + self.name = name + + def __str__(self) -> str: + return f"Wheel '{self.name}' located at {self.location} is invalid." + + +class MetadataInconsistent(InstallationError): + """Built metadata contains inconsistent information. + + This is raised when the metadata contains values (e.g. name and version) + that do not match the information previously obtained from sdist filename + or user-supplied ``#egg=`` value. + """ + + def __init__( + self, ireq: "InstallRequirement", field: str, f_val: str, m_val: str + ) -> None: + self.ireq = ireq + self.field = field + self.f_val = f_val + self.m_val = m_val + + def __str__(self) -> str: + template = ( + "Requested {} has inconsistent {}: " + "filename has {!r}, but metadata has {!r}" + ) + return template.format(self.ireq, self.field, self.f_val, self.m_val) + + +class LegacyInstallFailure(DiagnosticPipError): + """Error occurred while executing `setup.py install`""" + + reference = "legacy-install-failure" + + def __init__(self, package_details: str) -> None: + super().__init__( + message="Encountered error while trying to install package.", + context=package_details, + hint_stmt="See above for output from the failure.", + note_stmt="This is an issue with the package mentioned above, not pip.", + ) + + +class InstallationSubprocessError(DiagnosticPipError, InstallationError): + """A subprocess call failed.""" + + reference = "subprocess-exited-with-error" + + def __init__( + self, + *, + command_description: str, + exit_code: int, + output_lines: Optional[List[str]], + ) -> None: + if output_lines is None: + output_prompt = Text("See above for output.") + else: + output_prompt = ( + Text.from_markup(f"[red][{len(output_lines)} lines of output][/]\n") + + Text("".join(output_lines)) + + Text.from_markup(R"[red]\[end of output][/]") + ) + + super().__init__( + message=( + f"[green]{escape(command_description)}[/] did not run successfully.\n" + f"exit code: {exit_code}" + ), + context=output_prompt, + hint_stmt=None, + note_stmt=( + "This error originates from a subprocess, and is likely not a " + "problem with pip." + ), + ) + + self.command_description = command_description + self.exit_code = exit_code + + def __str__(self) -> str: + return f"{self.command_description} exited with {self.exit_code}" + + +class MetadataGenerationFailed(InstallationSubprocessError, InstallationError): + reference = "metadata-generation-failed" + + def __init__( + self, + *, + package_details: str, + ) -> None: + super(InstallationSubprocessError, self).__init__( + message="Encountered error while generating package metadata.", + context=escape(package_details), + hint_stmt="See above for details.", + note_stmt="This is an issue with the package mentioned above, not pip.", + ) + + def __str__(self) -> str: + return "metadata generation failed" + + +class HashErrors(InstallationError): + """Multiple HashError instances rolled into one for reporting""" + + def __init__(self) -> None: + self.errors: List["HashError"] = [] + + def append(self, error: "HashError") -> None: + self.errors.append(error) + + def __str__(self) -> str: + lines = [] + self.errors.sort(key=lambda e: e.order) + for cls, errors_of_cls in groupby(self.errors, lambda e: e.__class__): + lines.append(cls.head) + lines.extend(e.body() for e in errors_of_cls) + if lines: + return "\n".join(lines) + return "" + + def __bool__(self) -> bool: + return bool(self.errors) + + +class HashError(InstallationError): + """ + A failure to verify a package against known-good hashes + + :cvar order: An int sorting hash exception classes by difficulty of + recovery (lower being harder), so the user doesn't bother fretting + about unpinned packages when he has deeper issues, like VCS + dependencies, to deal with. Also keeps error reports in a + deterministic order. + :cvar head: A section heading for display above potentially many + exceptions of this kind + :ivar req: The InstallRequirement that triggered this error. This is + pasted on after the exception is instantiated, because it's not + typically available earlier. + + """ + + req: Optional["InstallRequirement"] = None + head = "" + order: int = -1 + + def body(self) -> str: + """Return a summary of me for display under the heading. + + This default implementation simply prints a description of the + triggering requirement. + + :param req: The InstallRequirement that provoked this error, with + its link already populated by the resolver's _populate_link(). + + """ + return f" {self._requirement_name()}" + + def __str__(self) -> str: + return f"{self.head}\n{self.body()}" + + def _requirement_name(self) -> str: + """Return a description of the requirement that triggered me. + + This default implementation returns long description of the req, with + line numbers + + """ + return str(self.req) if self.req else "unknown package" + + +class VcsHashUnsupported(HashError): + """A hash was provided for a version-control-system-based requirement, but + we don't have a method for hashing those.""" + + order = 0 + head = ( + "Can't verify hashes for these requirements because we don't " + "have a way to hash version control repositories:" + ) + + +class DirectoryUrlHashUnsupported(HashError): + """A hash was provided for a version-control-system-based requirement, but + we don't have a method for hashing those.""" + + order = 1 + head = ( + "Can't verify hashes for these file:// requirements because they " + "point to directories:" + ) + + +class HashMissing(HashError): + """A hash was needed for a requirement but is absent.""" + + order = 2 + head = ( + "Hashes are required in --require-hashes mode, but they are " + "missing from some requirements. Here is a list of those " + "requirements along with the hashes their downloaded archives " + "actually had. Add lines like these to your requirements files to " + "prevent tampering. (If you did not enable --require-hashes " + "manually, note that it turns on automatically when any package " + "has a hash.)" + ) + + def __init__(self, gotten_hash: str) -> None: + """ + :param gotten_hash: The hash of the (possibly malicious) archive we + just downloaded + """ + self.gotten_hash = gotten_hash + + def body(self) -> str: + # Dodge circular import. + from pip._internal.utils.hashes import FAVORITE_HASH + + package = None + if self.req: + # In the case of URL-based requirements, display the original URL + # seen in the requirements file rather than the package name, + # so the output can be directly copied into the requirements file. + package = ( + self.req.original_link + if self.req.original_link + # In case someone feeds something downright stupid + # to InstallRequirement's constructor. + else getattr(self.req, "req", None) + ) + return " {} --hash={}:{}".format( + package or "unknown package", FAVORITE_HASH, self.gotten_hash + ) + + +class HashUnpinned(HashError): + """A requirement had a hash specified but was not pinned to a specific + version.""" + + order = 3 + head = ( + "In --require-hashes mode, all requirements must have their " + "versions pinned with ==. These do not:" + ) + + +class HashMismatch(HashError): + """ + Distribution file hash values don't match. + + :ivar package_name: The name of the package that triggered the hash + mismatch. Feel free to write to this after the exception is raise to + improve its error message. + + """ + + order = 4 + head = ( + "THESE PACKAGES DO NOT MATCH THE HASHES FROM THE REQUIREMENTS " + "FILE. If you have updated the package versions, please update " + "the hashes. Otherwise, examine the package contents carefully; " + "someone may have tampered with them." + ) + + def __init__(self, allowed: Dict[str, List[str]], gots: Dict[str, "_Hash"]) -> None: + """ + :param allowed: A dict of algorithm names pointing to lists of allowed + hex digests + :param gots: A dict of algorithm names pointing to hashes we + actually got from the files under suspicion + """ + self.allowed = allowed + self.gots = gots + + def body(self) -> str: + return " {}:\n{}".format(self._requirement_name(), self._hash_comparison()) + + def _hash_comparison(self) -> str: + """ + Return a comparison of actual and expected hash values. + + Example:: + + Expected sha256 abcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcde + or 123451234512345123451234512345123451234512345 + Got bcdefbcdefbcdefbcdefbcdefbcdefbcdefbcdefbcdef + + """ + + def hash_then_or(hash_name: str) -> "chain[str]": + # For now, all the decent hashes have 6-char names, so we can get + # away with hard-coding space literals. + return chain([hash_name], repeat(" or")) + + lines: List[str] = [] + for hash_name, expecteds in self.allowed.items(): + prefix = hash_then_or(hash_name) + lines.extend( + (" Expected {} {}".format(next(prefix), e)) for e in expecteds + ) + lines.append( + " Got {}\n".format(self.gots[hash_name].hexdigest()) + ) + return "\n".join(lines) + + +class UnsupportedPythonVersion(InstallationError): + """Unsupported python version according to Requires-Python package + metadata.""" + + +class ConfigurationFileCouldNotBeLoaded(ConfigurationError): + """When there are errors while loading a configuration file""" + + def __init__( + self, + reason: str = "could not be loaded", + fname: Optional[str] = None, + error: Optional[configparser.Error] = None, + ) -> None: + super().__init__(error) + self.reason = reason + self.fname = fname + self.error = error + + def __str__(self) -> str: + if self.fname is not None: + message_part = f" in {self.fname}." + else: + assert self.error is not None + message_part = f".\n{self.error}\n" + return f"Configuration file {self.reason}{message_part}" diff --git a/venv/Lib/site-packages/pip/_internal/index/__init__.py b/venv/Lib/site-packages/pip/_internal/index/__init__.py new file mode 100644 index 0000000..7a17b7b --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/index/__init__.py @@ -0,0 +1,2 @@ +"""Index interaction code +""" diff --git a/venv/Lib/site-packages/pip/_internal/index/__pycache__/__init__.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/index/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..21230850ad5078aea0c8f883c1a41d9a1e1150c5 GIT binary patch literal 219 zcmYe~<>g`kf?j#GBsn1c7{oyaj6jY95EpX*i4=w?h7`tN22G|aanHPz)Cz^nypq(S z#N?99{5*x^{FGEKKTXD4?D6p_`N{F|D;bKIfV#lMuUKcRn9$%Dz*QOg-BG literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/index/__pycache__/collector.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/index/__pycache__/collector.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7268ff3c8ecfc4d3ca17a9cafe8a444d4eaf717d GIT binary patch literal 18024 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 W{m*jQiDBc%791a`hq+hs$^Q#zGrfQS literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/index/__pycache__/package_finder.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/index/__pycache__/package_finder.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..cbd4f60e18eddaee17c723386dacbc9d4dec7cc3 GIT binary patch literal 28074 zcmdsgd5j#{d0$oaIXyiGhr|2WS{}>kT~05_J+z`IF3(v}T8)?`cNMj{YBsxSW_sAi z?5mz7r`2Og%e8FTqNPZQl1OW1C?rTW31Y)YfBF5xW2@fRqG~<39q& zu%-1L`Tf3ERbAcFT-!o`0PbPGe)a0z?|a|<9xG#GIRl@&4?J|^7e8+p-{(X8lflCo ze7$+gFdU;~IHqIO&5|j_jzL@6P^$x;%(iF&G$E~OipQl^nDWg8=@4kU z>?-YQ>@MwY>?!S$^jv*!V_#`sV}EJCJdf5NXxJrN;`#c6jRU0v5+AD{Y#b^blK6Q2 zaO0uULlU2;A8E{#W+XmYFEk!5JuLAp^+y^RiAAXOGSxqtv}j0Ryro}>H6`; ziP8y)Z>vAnc)awu#JAU+fxxES;42uKN2Lr%IuvkTTPgWu9Qc|L=*X?MgugZJka(nvq=oNy0? z?-mkBzu;bQ_Pv&L_B#)}nkrp<#&B%s!B-9E!8=xI&ds_u@;vUI)iLJ)avpRJy_zgN zgPez*hmi9j~(HC@kEZoSfW9lPDKFRxv`bkwdj9rw2D z{eZwYU�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 NiXwIbx?lX;zX3 Optional[str]: + """Look for VCS schemes in the URL. + + Returns the matched VCS scheme, or None if there's no match. + """ + for scheme in vcs.schemes: + if url.lower().startswith(scheme) and url[len(scheme)] in "+:": + return scheme + return None + + +class _NotHTML(Exception): + def __init__(self, content_type: str, request_desc: str) -> None: + super().__init__(content_type, request_desc) + self.content_type = content_type + self.request_desc = request_desc + + +def _ensure_html_header(response: Response) -> None: + """Check the Content-Type header to ensure the response contains HTML. + + Raises `_NotHTML` if the content type is not text/html. + """ + content_type = response.headers.get("Content-Type", "") + if not content_type.lower().startswith("text/html"): + raise _NotHTML(content_type, response.request.method) + + +class _NotHTTP(Exception): + pass + + +def _ensure_html_response(url: str, session: PipSession) -> None: + """Send a HEAD request to the URL, and ensure the response contains HTML. + + Raises `_NotHTTP` if the URL is not available for a HEAD request, or + `_NotHTML` if the content type is not text/html. + """ + scheme, netloc, path, query, fragment = urllib.parse.urlsplit(url) + if scheme not in {"http", "https"}: + raise _NotHTTP() + + resp = session.head(url, allow_redirects=True) + raise_for_status(resp) + + _ensure_html_header(resp) + + +def _get_html_response(url: str, session: PipSession) -> Response: + """Access an HTML page with GET, and return the response. + + This consists of three parts: + + 1. If the URL looks suspiciously like an archive, send a HEAD first to + check the Content-Type is HTML, to avoid downloading a large file. + Raise `_NotHTTP` if the content type cannot be determined, or + `_NotHTML` if it is not HTML. + 2. Actually perform the request. Raise HTTP exceptions on network failures. + 3. Check the Content-Type header to make sure we got HTML, and raise + `_NotHTML` otherwise. + """ + if is_archive_file(Link(url).filename): + _ensure_html_response(url, session=session) + + logger.debug("Getting page %s", redact_auth_from_url(url)) + + resp = session.get( + url, + headers={ + "Accept": "text/html", + # We don't want to blindly returned cached data for + # /simple/, because authors generally expecting that + # twine upload && pip install will function, but if + # they've done a pip install in the last ~10 minutes + # it won't. Thus by setting this to zero we will not + # blindly use any cached data, however the benefit of + # using max-age=0 instead of no-cache, is that we will + # still support conditional requests, so we will still + # minimize traffic sent in cases where the page hasn't + # changed at all, we will just always incur the round + # trip for the conditional GET now instead of only + # once per 10 minutes. + # For more information, please see pypa/pip#5670. + "Cache-Control": "max-age=0", + }, + ) + raise_for_status(resp) + + # The check for archives above only works if the url ends with + # something that looks like an archive. However that is not a + # requirement of an url. Unless we issue a HEAD request on every + # url we cannot know ahead of time for sure if something is HTML + # or not. However we can check after we've downloaded it. + _ensure_html_header(resp) + + return resp + + +def _get_encoding_from_headers(headers: ResponseHeaders) -> Optional[str]: + """Determine if we have any encoding information in our headers.""" + if headers and "Content-Type" in headers: + content_type, params = cgi.parse_header(headers["Content-Type"]) + if "charset" in params: + return params["charset"] + return None + + +def _determine_base_url(document: HTMLElement, page_url: str) -> str: + """Determine the HTML document's base URL. + + This looks for a ```` tag in the HTML document. If present, its href + attribute denotes the base URL of anchor tags in the document. If there is + no such tag (or if it does not have a valid href attribute), the HTML + file's URL is used as the base URL. + + :param document: An HTML document representation. The current + implementation expects the result of ``html5lib.parse()``. + :param page_url: The URL of the HTML document. + + TODO: Remove when `html5lib` is dropped. + """ + for base in document.findall(".//base"): + href = base.get("href") + if href is not None: + return href + return page_url + + +def _clean_url_path_part(part: str) -> str: + """ + Clean a "part" of a URL path (i.e. after splitting on "@" characters). + """ + # We unquote prior to quoting to make sure nothing is double quoted. + return urllib.parse.quote(urllib.parse.unquote(part)) + + +def _clean_file_url_path(part: str) -> str: + """ + Clean the first part of a URL path that corresponds to a local + filesystem path (i.e. the first part after splitting on "@" characters). + """ + # We unquote prior to quoting to make sure nothing is double quoted. + # Also, on Windows the path part might contain a drive letter which + # should not be quoted. On Linux where drive letters do not + # exist, the colon should be quoted. We rely on urllib.request + # to do the right thing here. + return urllib.request.pathname2url(urllib.request.url2pathname(part)) + + +# percent-encoded: / +_reserved_chars_re = re.compile("(@|%2F)", re.IGNORECASE) + + +def _clean_url_path(path: str, is_local_path: bool) -> str: + """ + Clean the path portion of a URL. + """ + if is_local_path: + clean_func = _clean_file_url_path + else: + clean_func = _clean_url_path_part + + # Split on the reserved characters prior to cleaning so that + # revision strings in VCS URLs are properly preserved. + parts = _reserved_chars_re.split(path) + + cleaned_parts = [] + for to_clean, reserved in pairwise(itertools.chain(parts, [""])): + cleaned_parts.append(clean_func(to_clean)) + # Normalize %xx escapes (e.g. %2f -> %2F) + cleaned_parts.append(reserved.upper()) + + return "".join(cleaned_parts) + + +def _clean_link(url: str) -> str: + """ + Make sure a link is fully quoted. + For example, if ' ' occurs in the URL, it will be replaced with "%20", + and without double-quoting other characters. + """ + # Split the URL into parts according to the general structure + # `scheme://netloc/path;parameters?query#fragment`. + result = urllib.parse.urlparse(url) + # If the netloc is empty, then the URL refers to a local filesystem path. + is_local_path = not result.netloc + path = _clean_url_path(result.path, is_local_path=is_local_path) + return urllib.parse.urlunparse(result._replace(path=path)) + + +def _create_link_from_element( + element_attribs: Dict[str, Optional[str]], + page_url: str, + base_url: str, +) -> Optional[Link]: + """ + Convert an anchor element's attributes in a simple repository page to a Link. + """ + href = element_attribs.get("href") + if not href: + return None + + url = _clean_link(urllib.parse.urljoin(base_url, href)) + pyrequire = element_attribs.get("data-requires-python") + yanked_reason = element_attribs.get("data-yanked") + + link = Link( + url, + comes_from=page_url, + requires_python=pyrequire, + yanked_reason=yanked_reason, + ) + + return link + + +class CacheablePageContent: + def __init__(self, page: "HTMLPage") -> None: + assert page.cache_link_parsing + self.page = page + + def __eq__(self, other: object) -> bool: + return isinstance(other, type(self)) and self.page.url == other.page.url + + def __hash__(self) -> int: + return hash(self.page.url) + + +class ParseLinks(Protocol): + def __call__( + self, page: "HTMLPage", use_deprecated_html5lib: bool + ) -> Iterable[Link]: + ... + + +def with_cached_html_pages(fn: ParseLinks) -> ParseLinks: + """ + Given a function that parses an Iterable[Link] from an HTMLPage, cache the + function's result (keyed by CacheablePageContent), unless the HTMLPage + `page` has `page.cache_link_parsing == False`. + """ + + @functools.lru_cache(maxsize=None) + def wrapper( + cacheable_page: CacheablePageContent, use_deprecated_html5lib: bool + ) -> List[Link]: + return list(fn(cacheable_page.page, use_deprecated_html5lib)) + + @functools.wraps(fn) + def wrapper_wrapper(page: "HTMLPage", use_deprecated_html5lib: bool) -> List[Link]: + if page.cache_link_parsing: + return wrapper(CacheablePageContent(page), use_deprecated_html5lib) + return list(fn(page, use_deprecated_html5lib)) + + return wrapper_wrapper + + +def _parse_links_html5lib(page: "HTMLPage") -> Iterable[Link]: + """ + Parse an HTML document, and yield its anchor elements as Link objects. + + TODO: Remove when `html5lib` is dropped. + """ + document = html5lib.parse( + page.content, + transport_encoding=page.encoding, + namespaceHTMLElements=False, + ) + + url = page.url + base_url = _determine_base_url(document, url) + for anchor in document.findall(".//a"): + link = _create_link_from_element( + anchor.attrib, + page_url=url, + base_url=base_url, + ) + if link is None: + continue + yield link + + +@with_cached_html_pages +def parse_links(page: "HTMLPage", use_deprecated_html5lib: bool) -> Iterable[Link]: + """ + Parse an HTML document, and yield its anchor elements as Link objects. + """ + + if use_deprecated_html5lib: + yield from _parse_links_html5lib(page) + return + + parser = HTMLLinkParser(page.url) + encoding = page.encoding or "utf-8" + parser.feed(page.content.decode(encoding)) + + url = page.url + base_url = parser.base_url or url + for anchor in parser.anchors: + link = _create_link_from_element( + anchor, + page_url=url, + base_url=base_url, + ) + if link is None: + continue + yield link + + +class HTMLPage: + """Represents one page, along with its URL""" + + def __init__( + self, + content: bytes, + encoding: Optional[str], + url: str, + cache_link_parsing: bool = True, + ) -> None: + """ + :param encoding: the encoding to decode the given content. + :param url: the URL from which the HTML was downloaded. + :param cache_link_parsing: whether links parsed from this page's url + should be cached. PyPI index urls should + have this set to False, for example. + """ + self.content = content + self.encoding = encoding + self.url = url + self.cache_link_parsing = cache_link_parsing + + def __str__(self) -> str: + return redact_auth_from_url(self.url) + + +class HTMLLinkParser(HTMLParser): + """ + HTMLParser that keeps the first base HREF and a list of all anchor + elements' attributes. + """ + + def __init__(self, url: str) -> None: + super().__init__(convert_charrefs=True) + + self.url: str = url + self.base_url: Optional[str] = None + self.anchors: List[Dict[str, Optional[str]]] = [] + + def handle_starttag(self, tag: str, attrs: List[Tuple[str, Optional[str]]]) -> None: + if tag == "base" and self.base_url is None: + href = self.get_href(attrs) + if href is not None: + self.base_url = href + elif tag == "a": + self.anchors.append(dict(attrs)) + + def get_href(self, attrs: List[Tuple[str, Optional[str]]]) -> Optional[str]: + for name, value in attrs: + if name == "href": + return value + return None + + +def _handle_get_page_fail( + link: Link, + reason: Union[str, Exception], + meth: Optional[Callable[..., None]] = None, +) -> None: + if meth is None: + meth = logger.debug + meth("Could not fetch URL %s: %s - skipping", link, reason) + + +def _make_html_page(response: Response, cache_link_parsing: bool = True) -> HTMLPage: + encoding = _get_encoding_from_headers(response.headers) + return HTMLPage( + response.content, + encoding=encoding, + url=response.url, + cache_link_parsing=cache_link_parsing, + ) + + +def _get_html_page( + link: Link, session: Optional[PipSession] = None +) -> Optional["HTMLPage"]: + if session is None: + raise TypeError( + "_get_html_page() missing 1 required keyword argument: 'session'" + ) + + url = link.url.split("#", 1)[0] + + # Check for VCS schemes that do not support lookup as web pages. + vcs_scheme = _match_vcs_scheme(url) + if vcs_scheme: + logger.warning( + "Cannot look at %s URL %s because it does not support lookup as web pages.", + vcs_scheme, + link, + ) + return None + + # Tack index.html onto file:// URLs that point to directories + scheme, _, path, _, _, _ = urllib.parse.urlparse(url) + if scheme == "file" and os.path.isdir(urllib.request.url2pathname(path)): + # add trailing slash if not present so urljoin doesn't trim + # final segment + if not url.endswith("/"): + url += "/" + url = urllib.parse.urljoin(url, "index.html") + logger.debug(" file: URL is directory, getting %s", url) + + try: + resp = _get_html_response(url, session=session) + except _NotHTTP: + logger.warning( + "Skipping page %s because it looks like an archive, and cannot " + "be checked by a HTTP HEAD request.", + link, + ) + except _NotHTML as exc: + logger.warning( + "Skipping page %s because the %s request got Content-Type: %s." + "The only supported Content-Type is text/html", + link, + exc.request_desc, + exc.content_type, + ) + except NetworkConnectionError as exc: + _handle_get_page_fail(link, exc) + except RetryError as exc: + _handle_get_page_fail(link, exc) + except SSLError as exc: + reason = "There was a problem confirming the ssl certificate: " + reason += str(exc) + _handle_get_page_fail(link, reason, meth=logger.info) + except requests.ConnectionError as exc: + _handle_get_page_fail(link, f"connection error: {exc}") + except requests.Timeout: + _handle_get_page_fail(link, "timed out") + else: + return _make_html_page(resp, cache_link_parsing=link.cache_link_parsing) + return None + + +class CollectedSources(NamedTuple): + find_links: Sequence[Optional[LinkSource]] + index_urls: Sequence[Optional[LinkSource]] + + +class LinkCollector: + + """ + Responsible for collecting Link objects from all configured locations, + making network requests as needed. + + The class's main method is its collect_sources() method. + """ + + def __init__( + self, + session: PipSession, + search_scope: SearchScope, + ) -> None: + self.search_scope = search_scope + self.session = session + + @classmethod + def create( + cls, + session: PipSession, + options: Values, + suppress_no_index: bool = False, + ) -> "LinkCollector": + """ + :param session: The Session to use to make requests. + :param suppress_no_index: Whether to ignore the --no-index option + when constructing the SearchScope object. + """ + index_urls = [options.index_url] + options.extra_index_urls + if options.no_index and not suppress_no_index: + logger.debug( + "Ignoring indexes: %s", + ",".join(redact_auth_from_url(url) for url in index_urls), + ) + index_urls = [] + + # Make sure find_links is a list before passing to create(). + find_links = options.find_links or [] + + search_scope = SearchScope.create( + find_links=find_links, + index_urls=index_urls, + ) + link_collector = LinkCollector( + session=session, + search_scope=search_scope, + ) + return link_collector + + @property + def find_links(self) -> List[str]: + return self.search_scope.find_links + + def fetch_page(self, location: Link) -> Optional[HTMLPage]: + """ + Fetch an HTML page containing package links. + """ + return _get_html_page(location, session=self.session) + + def collect_sources( + self, + project_name: str, + candidates_from_page: CandidatesFromPage, + ) -> CollectedSources: + # The OrderedDict calls deduplicate sources by URL. + index_url_sources = collections.OrderedDict( + build_source( + loc, + candidates_from_page=candidates_from_page, + page_validator=self.session.is_secure_origin, + expand_dir=False, + cache_link_parsing=False, + ) + for loc in self.search_scope.get_index_urls_locations(project_name) + ).values() + find_links_sources = collections.OrderedDict( + build_source( + loc, + candidates_from_page=candidates_from_page, + page_validator=self.session.is_secure_origin, + expand_dir=True, + cache_link_parsing=True, + ) + for loc in self.find_links + ).values() + + if logger.isEnabledFor(logging.DEBUG): + lines = [ + f"* {s.link}" + for s in itertools.chain(find_links_sources, index_url_sources) + if s is not None and s.link is not None + ] + lines = [ + f"{len(lines)} location(s) to search " + f"for versions of {project_name}:" + ] + lines + logger.debug("\n".join(lines)) + + return CollectedSources( + find_links=list(find_links_sources), + index_urls=list(index_url_sources), + ) diff --git a/venv/Lib/site-packages/pip/_internal/index/package_finder.py b/venv/Lib/site-packages/pip/_internal/index/package_finder.py new file mode 100644 index 0000000..223d06d --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/index/package_finder.py @@ -0,0 +1,1004 @@ +"""Routines related to PyPI, indexes""" + +# The following comment should be removed at some point in the future. +# mypy: strict-optional=False + +import functools +import itertools +import logging +import re +from typing import FrozenSet, Iterable, List, Optional, Set, Tuple, Union + +from pip._vendor.packaging import specifiers +from pip._vendor.packaging.tags import Tag +from pip._vendor.packaging.utils import canonicalize_name +from pip._vendor.packaging.version import _BaseVersion +from pip._vendor.packaging.version import parse as parse_version + +from pip._internal.exceptions import ( + BestVersionAlreadyInstalled, + DistributionNotFound, + InvalidWheelFilename, + UnsupportedWheel, +) +from pip._internal.index.collector import LinkCollector, parse_links +from pip._internal.models.candidate import InstallationCandidate +from pip._internal.models.format_control import FormatControl +from pip._internal.models.link import Link +from pip._internal.models.search_scope import SearchScope +from pip._internal.models.selection_prefs import SelectionPreferences +from pip._internal.models.target_python import TargetPython +from pip._internal.models.wheel import Wheel +from pip._internal.req import InstallRequirement +from pip._internal.utils._log import getLogger +from pip._internal.utils.filetypes import WHEEL_EXTENSION +from pip._internal.utils.hashes import Hashes +from pip._internal.utils.logging import indent_log +from pip._internal.utils.misc import build_netloc +from pip._internal.utils.packaging import check_requires_python +from pip._internal.utils.unpacking import SUPPORTED_EXTENSIONS + +__all__ = ["FormatControl", "BestCandidateResult", "PackageFinder"] + + +logger = getLogger(__name__) + +BuildTag = Union[Tuple[()], Tuple[int, str]] +CandidateSortingKey = Tuple[int, int, int, _BaseVersion, Optional[int], BuildTag] + + +def _check_link_requires_python( + link: Link, + version_info: Tuple[int, int, int], + ignore_requires_python: bool = False, +) -> bool: + """ + Return whether the given Python version is compatible with a link's + "Requires-Python" value. + + :param version_info: A 3-tuple of ints representing the Python + major-minor-micro version to check. + :param ignore_requires_python: Whether to ignore the "Requires-Python" + value if the given Python version isn't compatible. + """ + try: + is_compatible = check_requires_python( + link.requires_python, + version_info=version_info, + ) + except specifiers.InvalidSpecifier: + logger.debug( + "Ignoring invalid Requires-Python (%r) for link: %s", + link.requires_python, + link, + ) + else: + if not is_compatible: + version = ".".join(map(str, version_info)) + if not ignore_requires_python: + logger.verbose( + "Link requires a different Python (%s not in: %r): %s", + version, + link.requires_python, + link, + ) + return False + + logger.debug( + "Ignoring failed Requires-Python check (%s not in: %r) for link: %s", + version, + link.requires_python, + link, + ) + + return True + + +class LinkEvaluator: + + """ + Responsible for evaluating links for a particular project. + """ + + _py_version_re = re.compile(r"-py([123]\.?[0-9]?)$") + + # Don't include an allow_yanked default value to make sure each call + # site considers whether yanked releases are allowed. This also causes + # that decision to be made explicit in the calling code, which helps + # people when reading the code. + def __init__( + self, + project_name: str, + canonical_name: str, + formats: FrozenSet[str], + target_python: TargetPython, + allow_yanked: bool, + ignore_requires_python: Optional[bool] = None, + ) -> None: + """ + :param project_name: The user supplied package name. + :param canonical_name: The canonical package name. + :param formats: The formats allowed for this package. Should be a set + with 'binary' or 'source' or both in it. + :param target_python: The target Python interpreter to use when + evaluating link compatibility. This is used, for example, to + check wheel compatibility, as well as when checking the Python + version, e.g. the Python version embedded in a link filename + (or egg fragment) and against an HTML link's optional PEP 503 + "data-requires-python" attribute. + :param allow_yanked: Whether files marked as yanked (in the sense + of PEP 592) are permitted to be candidates for install. + :param ignore_requires_python: Whether to ignore incompatible + PEP 503 "data-requires-python" values in HTML links. Defaults + to False. + """ + if ignore_requires_python is None: + ignore_requires_python = False + + self._allow_yanked = allow_yanked + self._canonical_name = canonical_name + self._ignore_requires_python = ignore_requires_python + self._formats = formats + self._target_python = target_python + + self.project_name = project_name + + def evaluate_link(self, link: Link) -> Tuple[bool, Optional[str]]: + """ + Determine whether a link is a candidate for installation. + + :return: A tuple (is_candidate, result), where `result` is (1) a + version string if `is_candidate` is True, and (2) if + `is_candidate` is False, an optional string to log the reason + the link fails to qualify. + """ + version = None + if link.is_yanked and not self._allow_yanked: + reason = link.yanked_reason or "" + return (False, f"yanked for reason: {reason}") + + if link.egg_fragment: + egg_info = link.egg_fragment + ext = link.ext + else: + egg_info, ext = link.splitext() + if not ext: + return (False, "not a file") + if ext not in SUPPORTED_EXTENSIONS: + return (False, f"unsupported archive format: {ext}") + if "binary" not in self._formats and ext == WHEEL_EXTENSION: + reason = "No binaries permitted for {}".format(self.project_name) + return (False, reason) + if "macosx10" in link.path and ext == ".zip": + return (False, "macosx10 one") + if ext == WHEEL_EXTENSION: + try: + wheel = Wheel(link.filename) + except InvalidWheelFilename: + return (False, "invalid wheel filename") + if canonicalize_name(wheel.name) != self._canonical_name: + reason = "wrong project name (not {})".format(self.project_name) + return (False, reason) + + supported_tags = self._target_python.get_tags() + if not wheel.supported(supported_tags): + # Include the wheel's tags in the reason string to + # simplify troubleshooting compatibility issues. + file_tags = wheel.get_formatted_file_tags() + reason = ( + "none of the wheel's tags ({}) are compatible " + "(run pip debug --verbose to show compatible tags)".format( + ", ".join(file_tags) + ) + ) + return (False, reason) + + version = wheel.version + + # This should be up by the self.ok_binary check, but see issue 2700. + if "source" not in self._formats and ext != WHEEL_EXTENSION: + reason = f"No sources permitted for {self.project_name}" + return (False, reason) + + if not version: + version = _extract_version_from_fragment( + egg_info, + self._canonical_name, + ) + if not version: + reason = f"Missing project version for {self.project_name}" + return (False, reason) + + match = self._py_version_re.search(version) + if match: + version = version[: match.start()] + py_version = match.group(1) + if py_version != self._target_python.py_version: + return (False, "Python version is incorrect") + + supports_python = _check_link_requires_python( + link, + version_info=self._target_python.py_version_info, + ignore_requires_python=self._ignore_requires_python, + ) + if not supports_python: + # Return None for the reason text to suppress calling + # _log_skipped_link(). + return (False, None) + + logger.debug("Found link %s, version: %s", link, version) + + return (True, version) + + +def filter_unallowed_hashes( + candidates: List[InstallationCandidate], + hashes: Hashes, + project_name: str, +) -> List[InstallationCandidate]: + """ + Filter out candidates whose hashes aren't allowed, and return a new + list of candidates. + + If at least one candidate has an allowed hash, then all candidates with + either an allowed hash or no hash specified are returned. Otherwise, + the given candidates are returned. + + Including the candidates with no hash specified when there is a match + allows a warning to be logged if there is a more preferred candidate + with no hash specified. Returning all candidates in the case of no + matches lets pip report the hash of the candidate that would otherwise + have been installed (e.g. permitting the user to more easily update + their requirements file with the desired hash). + """ + if not hashes: + logger.debug( + "Given no hashes to check %s links for project %r: " + "discarding no candidates", + len(candidates), + project_name, + ) + # Make sure we're not returning back the given value. + return list(candidates) + + matches_or_no_digest = [] + # Collect the non-matches for logging purposes. + non_matches = [] + match_count = 0 + for candidate in candidates: + link = candidate.link + if not link.has_hash: + pass + elif link.is_hash_allowed(hashes=hashes): + match_count += 1 + else: + non_matches.append(candidate) + continue + + matches_or_no_digest.append(candidate) + + if match_count: + filtered = matches_or_no_digest + else: + # Make sure we're not returning back the given value. + filtered = list(candidates) + + if len(filtered) == len(candidates): + discard_message = "discarding no candidates" + else: + discard_message = "discarding {} non-matches:\n {}".format( + len(non_matches), + "\n ".join(str(candidate.link) for candidate in non_matches), + ) + + logger.debug( + "Checked %s links for project %r against %s hashes " + "(%s matches, %s no digest): %s", + len(candidates), + project_name, + hashes.digest_count, + match_count, + len(matches_or_no_digest) - match_count, + discard_message, + ) + + return filtered + + +class CandidatePreferences: + + """ + Encapsulates some of the preferences for filtering and sorting + InstallationCandidate objects. + """ + + def __init__( + self, + prefer_binary: bool = False, + allow_all_prereleases: bool = False, + ) -> None: + """ + :param allow_all_prereleases: Whether to allow all pre-releases. + """ + self.allow_all_prereleases = allow_all_prereleases + self.prefer_binary = prefer_binary + + +class BestCandidateResult: + """A collection of candidates, returned by `PackageFinder.find_best_candidate`. + + This class is only intended to be instantiated by CandidateEvaluator's + `compute_best_candidate()` method. + """ + + def __init__( + self, + candidates: List[InstallationCandidate], + applicable_candidates: List[InstallationCandidate], + best_candidate: Optional[InstallationCandidate], + ) -> None: + """ + :param candidates: A sequence of all available candidates found. + :param applicable_candidates: The applicable candidates. + :param best_candidate: The most preferred candidate found, or None + if no applicable candidates were found. + """ + assert set(applicable_candidates) <= set(candidates) + + if best_candidate is None: + assert not applicable_candidates + else: + assert best_candidate in applicable_candidates + + self._applicable_candidates = applicable_candidates + self._candidates = candidates + + self.best_candidate = best_candidate + + def iter_all(self) -> Iterable[InstallationCandidate]: + """Iterate through all candidates.""" + return iter(self._candidates) + + def iter_applicable(self) -> Iterable[InstallationCandidate]: + """Iterate through the applicable candidates.""" + return iter(self._applicable_candidates) + + +class CandidateEvaluator: + + """ + Responsible for filtering and sorting candidates for installation based + on what tags are valid. + """ + + @classmethod + def create( + cls, + project_name: str, + target_python: Optional[TargetPython] = None, + prefer_binary: bool = False, + allow_all_prereleases: bool = False, + specifier: Optional[specifiers.BaseSpecifier] = None, + hashes: Optional[Hashes] = None, + ) -> "CandidateEvaluator": + """Create a CandidateEvaluator object. + + :param target_python: The target Python interpreter to use when + checking compatibility. If None (the default), a TargetPython + object will be constructed from the running Python. + :param specifier: An optional object implementing `filter` + (e.g. `packaging.specifiers.SpecifierSet`) to filter applicable + versions. + :param hashes: An optional collection of allowed hashes. + """ + if target_python is None: + target_python = TargetPython() + if specifier is None: + specifier = specifiers.SpecifierSet() + + supported_tags = target_python.get_tags() + + return cls( + project_name=project_name, + supported_tags=supported_tags, + specifier=specifier, + prefer_binary=prefer_binary, + allow_all_prereleases=allow_all_prereleases, + hashes=hashes, + ) + + def __init__( + self, + project_name: str, + supported_tags: List[Tag], + specifier: specifiers.BaseSpecifier, + prefer_binary: bool = False, + allow_all_prereleases: bool = False, + hashes: Optional[Hashes] = None, + ) -> None: + """ + :param supported_tags: The PEP 425 tags supported by the target + Python in order of preference (most preferred first). + """ + self._allow_all_prereleases = allow_all_prereleases + self._hashes = hashes + self._prefer_binary = prefer_binary + self._project_name = project_name + self._specifier = specifier + self._supported_tags = supported_tags + # Since the index of the tag in the _supported_tags list is used + # as a priority, precompute a map from tag to index/priority to be + # used in wheel.find_most_preferred_tag. + self._wheel_tag_preferences = { + tag: idx for idx, tag in enumerate(supported_tags) + } + + def get_applicable_candidates( + self, + candidates: List[InstallationCandidate], + ) -> List[InstallationCandidate]: + """ + Return the applicable candidates from a list of candidates. + """ + # Using None infers from the specifier instead. + allow_prereleases = self._allow_all_prereleases or None + specifier = self._specifier + versions = { + str(v) + for v in specifier.filter( + # We turn the version object into a str here because otherwise + # when we're debundled but setuptools isn't, Python will see + # packaging.version.Version and + # pkg_resources._vendor.packaging.version.Version as different + # types. This way we'll use a str as a common data interchange + # format. If we stop using the pkg_resources provided specifier + # and start using our own, we can drop the cast to str(). + (str(c.version) for c in candidates), + prereleases=allow_prereleases, + ) + } + + # Again, converting version to str to deal with debundling. + applicable_candidates = [c for c in candidates if str(c.version) in versions] + + filtered_applicable_candidates = filter_unallowed_hashes( + candidates=applicable_candidates, + hashes=self._hashes, + project_name=self._project_name, + ) + + return sorted(filtered_applicable_candidates, key=self._sort_key) + + def _sort_key(self, candidate: InstallationCandidate) -> CandidateSortingKey: + """ + Function to pass as the `key` argument to a call to sorted() to sort + InstallationCandidates by preference. + + Returns a tuple such that tuples sorting as greater using Python's + default comparison operator are more preferred. + + The preference is as follows: + + First and foremost, candidates with allowed (matching) hashes are + always preferred over candidates without matching hashes. This is + because e.g. if the only candidate with an allowed hash is yanked, + we still want to use that candidate. + + Second, excepting hash considerations, candidates that have been + yanked (in the sense of PEP 592) are always less preferred than + candidates that haven't been yanked. Then: + + If not finding wheels, they are sorted by version only. + If finding wheels, then the sort order is by version, then: + 1. existing installs + 2. wheels ordered via Wheel.support_index_min(self._supported_tags) + 3. source archives + If prefer_binary was set, then all wheels are sorted above sources. + + Note: it was considered to embed this logic into the Link + comparison operators, but then different sdist links + with the same version, would have to be considered equal + """ + valid_tags = self._supported_tags + support_num = len(valid_tags) + build_tag: BuildTag = () + binary_preference = 0 + link = candidate.link + if link.is_wheel: + # can raise InvalidWheelFilename + wheel = Wheel(link.filename) + try: + pri = -( + wheel.find_most_preferred_tag( + valid_tags, self._wheel_tag_preferences + ) + ) + except ValueError: + raise UnsupportedWheel( + "{} is not a supported wheel for this platform. It " + "can't be sorted.".format(wheel.filename) + ) + if self._prefer_binary: + binary_preference = 1 + if wheel.build_tag is not None: + match = re.match(r"^(\d+)(.*)$", wheel.build_tag) + build_tag_groups = match.groups() + build_tag = (int(build_tag_groups[0]), build_tag_groups[1]) + else: # sdist + pri = -(support_num) + has_allowed_hash = int(link.is_hash_allowed(self._hashes)) + yank_value = -1 * int(link.is_yanked) # -1 for yanked. + return ( + has_allowed_hash, + yank_value, + binary_preference, + candidate.version, + pri, + build_tag, + ) + + def sort_best_candidate( + self, + candidates: List[InstallationCandidate], + ) -> Optional[InstallationCandidate]: + """ + Return the best candidate per the instance's sort order, or None if + no candidate is acceptable. + """ + if not candidates: + return None + best_candidate = max(candidates, key=self._sort_key) + return best_candidate + + def compute_best_candidate( + self, + candidates: List[InstallationCandidate], + ) -> BestCandidateResult: + """ + Compute and return a `BestCandidateResult` instance. + """ + applicable_candidates = self.get_applicable_candidates(candidates) + + best_candidate = self.sort_best_candidate(applicable_candidates) + + return BestCandidateResult( + candidates, + applicable_candidates=applicable_candidates, + best_candidate=best_candidate, + ) + + +class PackageFinder: + """This finds packages. + + This is meant to match easy_install's technique for looking for + packages, by reading pages and looking for appropriate links. + """ + + def __init__( + self, + link_collector: LinkCollector, + target_python: TargetPython, + allow_yanked: bool, + use_deprecated_html5lib: bool, + format_control: Optional[FormatControl] = None, + candidate_prefs: Optional[CandidatePreferences] = None, + ignore_requires_python: Optional[bool] = None, + ) -> None: + """ + This constructor is primarily meant to be used by the create() class + method and from tests. + + :param format_control: A FormatControl object, used to control + the selection of source packages / binary packages when consulting + the index and links. + :param candidate_prefs: Options to use when creating a + CandidateEvaluator object. + """ + if candidate_prefs is None: + candidate_prefs = CandidatePreferences() + + format_control = format_control or FormatControl(set(), set()) + + self._allow_yanked = allow_yanked + self._candidate_prefs = candidate_prefs + self._ignore_requires_python = ignore_requires_python + self._link_collector = link_collector + self._target_python = target_python + self._use_deprecated_html5lib = use_deprecated_html5lib + + self.format_control = format_control + + # These are boring links that have already been logged somehow. + self._logged_links: Set[Link] = set() + + # Don't include an allow_yanked default value to make sure each call + # site considers whether yanked releases are allowed. This also causes + # that decision to be made explicit in the calling code, which helps + # people when reading the code. + @classmethod + def create( + cls, + link_collector: LinkCollector, + selection_prefs: SelectionPreferences, + target_python: Optional[TargetPython] = None, + *, + use_deprecated_html5lib: bool, + ) -> "PackageFinder": + """Create a PackageFinder. + + :param selection_prefs: The candidate selection preferences, as a + SelectionPreferences object. + :param target_python: The target Python interpreter to use when + checking compatibility. If None (the default), a TargetPython + object will be constructed from the running Python. + """ + if target_python is None: + target_python = TargetPython() + + candidate_prefs = CandidatePreferences( + prefer_binary=selection_prefs.prefer_binary, + allow_all_prereleases=selection_prefs.allow_all_prereleases, + ) + + return cls( + candidate_prefs=candidate_prefs, + link_collector=link_collector, + target_python=target_python, + allow_yanked=selection_prefs.allow_yanked, + format_control=selection_prefs.format_control, + ignore_requires_python=selection_prefs.ignore_requires_python, + use_deprecated_html5lib=use_deprecated_html5lib, + ) + + @property + def target_python(self) -> TargetPython: + return self._target_python + + @property + def search_scope(self) -> SearchScope: + return self._link_collector.search_scope + + @search_scope.setter + def search_scope(self, search_scope: SearchScope) -> None: + self._link_collector.search_scope = search_scope + + @property + def find_links(self) -> List[str]: + return self._link_collector.find_links + + @property + def index_urls(self) -> List[str]: + return self.search_scope.index_urls + + @property + def trusted_hosts(self) -> Iterable[str]: + for host_port in self._link_collector.session.pip_trusted_origins: + yield build_netloc(*host_port) + + @property + def allow_all_prereleases(self) -> bool: + return self._candidate_prefs.allow_all_prereleases + + def set_allow_all_prereleases(self) -> None: + self._candidate_prefs.allow_all_prereleases = True + + @property + def prefer_binary(self) -> bool: + return self._candidate_prefs.prefer_binary + + def set_prefer_binary(self) -> None: + self._candidate_prefs.prefer_binary = True + + def make_link_evaluator(self, project_name: str) -> LinkEvaluator: + canonical_name = canonicalize_name(project_name) + formats = self.format_control.get_allowed_formats(canonical_name) + + return LinkEvaluator( + project_name=project_name, + canonical_name=canonical_name, + formats=formats, + target_python=self._target_python, + allow_yanked=self._allow_yanked, + ignore_requires_python=self._ignore_requires_python, + ) + + def _sort_links(self, links: Iterable[Link]) -> List[Link]: + """ + Returns elements of links in order, non-egg links first, egg links + second, while eliminating duplicates + """ + eggs, no_eggs = [], [] + seen: Set[Link] = set() + for link in links: + if link not in seen: + seen.add(link) + if link.egg_fragment: + eggs.append(link) + else: + no_eggs.append(link) + return no_eggs + eggs + + def _log_skipped_link(self, link: Link, reason: str) -> None: + if link not in self._logged_links: + # Put the link at the end so the reason is more visible and because + # the link string is usually very long. + logger.debug("Skipping link: %s: %s", reason, link) + self._logged_links.add(link) + + def get_install_candidate( + self, link_evaluator: LinkEvaluator, link: Link + ) -> Optional[InstallationCandidate]: + """ + If the link is a candidate for install, convert it to an + InstallationCandidate and return it. Otherwise, return None. + """ + is_candidate, result = link_evaluator.evaluate_link(link) + if not is_candidate: + if result: + self._log_skipped_link(link, reason=result) + return None + + return InstallationCandidate( + name=link_evaluator.project_name, + link=link, + version=result, + ) + + def evaluate_links( + self, link_evaluator: LinkEvaluator, links: Iterable[Link] + ) -> List[InstallationCandidate]: + """ + Convert links that are candidates to InstallationCandidate objects. + """ + candidates = [] + for link in self._sort_links(links): + candidate = self.get_install_candidate(link_evaluator, link) + if candidate is not None: + candidates.append(candidate) + + return candidates + + def process_project_url( + self, project_url: Link, link_evaluator: LinkEvaluator + ) -> List[InstallationCandidate]: + logger.debug( + "Fetching project page and analyzing links: %s", + project_url, + ) + html_page = self._link_collector.fetch_page(project_url) + if html_page is None: + return [] + + page_links = list(parse_links(html_page, self._use_deprecated_html5lib)) + + with indent_log(): + package_links = self.evaluate_links( + link_evaluator, + links=page_links, + ) + + return package_links + + @functools.lru_cache(maxsize=None) + def find_all_candidates(self, project_name: str) -> List[InstallationCandidate]: + """Find all available InstallationCandidate for project_name + + This checks index_urls and find_links. + All versions found are returned as an InstallationCandidate list. + + See LinkEvaluator.evaluate_link() for details on which files + are accepted. + """ + link_evaluator = self.make_link_evaluator(project_name) + + collected_sources = self._link_collector.collect_sources( + project_name=project_name, + candidates_from_page=functools.partial( + self.process_project_url, + link_evaluator=link_evaluator, + ), + ) + + page_candidates_it = itertools.chain.from_iterable( + source.page_candidates() + for sources in collected_sources + for source in sources + if source is not None + ) + page_candidates = list(page_candidates_it) + + file_links_it = itertools.chain.from_iterable( + source.file_links() + for sources in collected_sources + for source in sources + if source is not None + ) + file_candidates = self.evaluate_links( + link_evaluator, + sorted(file_links_it, reverse=True), + ) + + if logger.isEnabledFor(logging.DEBUG) and file_candidates: + paths = [] + for candidate in file_candidates: + assert candidate.link.url # we need to have a URL + try: + paths.append(candidate.link.file_path) + except Exception: + paths.append(candidate.link.url) # it's not a local file + + logger.debug("Local files found: %s", ", ".join(paths)) + + # This is an intentional priority ordering + return file_candidates + page_candidates + + def make_candidate_evaluator( + self, + project_name: str, + specifier: Optional[specifiers.BaseSpecifier] = None, + hashes: Optional[Hashes] = None, + ) -> CandidateEvaluator: + """Create a CandidateEvaluator object to use.""" + candidate_prefs = self._candidate_prefs + return CandidateEvaluator.create( + project_name=project_name, + target_python=self._target_python, + prefer_binary=candidate_prefs.prefer_binary, + allow_all_prereleases=candidate_prefs.allow_all_prereleases, + specifier=specifier, + hashes=hashes, + ) + + @functools.lru_cache(maxsize=None) + def find_best_candidate( + self, + project_name: str, + specifier: Optional[specifiers.BaseSpecifier] = None, + hashes: Optional[Hashes] = None, + ) -> BestCandidateResult: + """Find matches for the given project and specifier. + + :param specifier: An optional object implementing `filter` + (e.g. `packaging.specifiers.SpecifierSet`) to filter applicable + versions. + + :return: A `BestCandidateResult` instance. + """ + candidates = self.find_all_candidates(project_name) + candidate_evaluator = self.make_candidate_evaluator( + project_name=project_name, + specifier=specifier, + hashes=hashes, + ) + return candidate_evaluator.compute_best_candidate(candidates) + + def find_requirement( + self, req: InstallRequirement, upgrade: bool + ) -> Optional[InstallationCandidate]: + """Try to find a Link matching req + + Expects req, an InstallRequirement and upgrade, a boolean + Returns a InstallationCandidate if found, + Raises DistributionNotFound or BestVersionAlreadyInstalled otherwise + """ + hashes = req.hashes(trust_internet=False) + best_candidate_result = self.find_best_candidate( + req.name, + specifier=req.specifier, + hashes=hashes, + ) + best_candidate = best_candidate_result.best_candidate + + installed_version: Optional[_BaseVersion] = None + if req.satisfied_by is not None: + installed_version = req.satisfied_by.version + + def _format_versions(cand_iter: Iterable[InstallationCandidate]) -> str: + # This repeated parse_version and str() conversion is needed to + # handle different vendoring sources from pip and pkg_resources. + # If we stop using the pkg_resources provided specifier and start + # using our own, we can drop the cast to str(). + return ( + ", ".join( + sorted( + {str(c.version) for c in cand_iter}, + key=parse_version, + ) + ) + or "none" + ) + + if installed_version is None and best_candidate is None: + logger.critical( + "Could not find a version that satisfies the requirement %s " + "(from versions: %s)", + req, + _format_versions(best_candidate_result.iter_all()), + ) + + raise DistributionNotFound( + "No matching distribution found for {}".format(req) + ) + + best_installed = False + if installed_version and ( + best_candidate is None or best_candidate.version <= installed_version + ): + best_installed = True + + if not upgrade and installed_version is not None: + if best_installed: + logger.debug( + "Existing installed version (%s) is most up-to-date and " + "satisfies requirement", + installed_version, + ) + else: + logger.debug( + "Existing installed version (%s) satisfies requirement " + "(most up-to-date version is %s)", + installed_version, + best_candidate.version, + ) + return None + + if best_installed: + # We have an existing version, and its the best version + logger.debug( + "Installed version (%s) is most up-to-date (past versions: %s)", + installed_version, + _format_versions(best_candidate_result.iter_applicable()), + ) + raise BestVersionAlreadyInstalled + + logger.debug( + "Using version %s (newest of versions: %s)", + best_candidate.version, + _format_versions(best_candidate_result.iter_applicable()), + ) + return best_candidate + + +def _find_name_version_sep(fragment: str, canonical_name: str) -> int: + """Find the separator's index based on the package's canonical name. + + :param fragment: A + filename "fragment" (stem) or + egg fragment. + :param canonical_name: The package's canonical name. + + This function is needed since the canonicalized name does not necessarily + have the same length as the egg info's name part. An example:: + + >>> fragment = 'foo__bar-1.0' + >>> canonical_name = 'foo-bar' + >>> _find_name_version_sep(fragment, canonical_name) + 8 + """ + # Project name and version must be separated by one single dash. Find all + # occurrences of dashes; if the string in front of it matches the canonical + # name, this is the one separating the name and version parts. + for i, c in enumerate(fragment): + if c != "-": + continue + if canonicalize_name(fragment[:i]) == canonical_name: + return i + raise ValueError(f"{fragment} does not match {canonical_name}") + + +def _extract_version_from_fragment(fragment: str, canonical_name: str) -> Optional[str]: + """Parse the version string from a + filename + "fragment" (stem) or egg fragment. + + :param fragment: The string to parse. E.g. foo-2.1 + :param canonical_name: The canonicalized name of the package this + belongs to. + """ + try: + version_start = _find_name_version_sep(fragment, canonical_name) + 1 + except ValueError: + return None + version = fragment[version_start:] + if not version: + return None + return version diff --git a/venv/Lib/site-packages/pip/_internal/index/sources.py b/venv/Lib/site-packages/pip/_internal/index/sources.py new file mode 100644 index 0000000..eec3f12 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/index/sources.py @@ -0,0 +1,224 @@ +import logging +import mimetypes +import os +import pathlib +from typing import Callable, Iterable, Optional, Tuple + +from pip._internal.models.candidate import InstallationCandidate +from pip._internal.models.link import Link +from pip._internal.utils.urls import path_to_url, url_to_path +from pip._internal.vcs import is_url + +logger = logging.getLogger(__name__) + +FoundCandidates = Iterable[InstallationCandidate] +FoundLinks = Iterable[Link] +CandidatesFromPage = Callable[[Link], Iterable[InstallationCandidate]] +PageValidator = Callable[[Link], bool] + + +class LinkSource: + @property + def link(self) -> Optional[Link]: + """Returns the underlying link, if there's one.""" + raise NotImplementedError() + + def page_candidates(self) -> FoundCandidates: + """Candidates found by parsing an archive listing HTML file.""" + raise NotImplementedError() + + def file_links(self) -> FoundLinks: + """Links found by specifying archives directly.""" + raise NotImplementedError() + + +def _is_html_file(file_url: str) -> bool: + return mimetypes.guess_type(file_url, strict=False)[0] == "text/html" + + +class _FlatDirectorySource(LinkSource): + """Link source specified by ``--find-links=``. + + This looks the content of the directory, and returns: + + * ``page_candidates``: Links listed on each HTML file in the directory. + * ``file_candidates``: Archives in the directory. + """ + + def __init__( + self, + candidates_from_page: CandidatesFromPage, + path: str, + ) -> None: + self._candidates_from_page = candidates_from_page + self._path = pathlib.Path(os.path.realpath(path)) + + @property + def link(self) -> Optional[Link]: + return None + + def page_candidates(self) -> FoundCandidates: + for path in self._path.iterdir(): + url = path_to_url(str(path)) + if not _is_html_file(url): + continue + yield from self._candidates_from_page(Link(url)) + + def file_links(self) -> FoundLinks: + for path in self._path.iterdir(): + url = path_to_url(str(path)) + if _is_html_file(url): + continue + yield Link(url) + + +class _LocalFileSource(LinkSource): + """``--find-links=`` or ``--[extra-]index-url=``. + + If a URL is supplied, it must be a ``file:`` URL. If a path is supplied to + the option, it is converted to a URL first. This returns: + + * ``page_candidates``: Links listed on an HTML file. + * ``file_candidates``: The non-HTML file. + """ + + def __init__( + self, + candidates_from_page: CandidatesFromPage, + link: Link, + ) -> None: + self._candidates_from_page = candidates_from_page + self._link = link + + @property + def link(self) -> Optional[Link]: + return self._link + + def page_candidates(self) -> FoundCandidates: + if not _is_html_file(self._link.url): + return + yield from self._candidates_from_page(self._link) + + def file_links(self) -> FoundLinks: + if _is_html_file(self._link.url): + return + yield self._link + + +class _RemoteFileSource(LinkSource): + """``--find-links=`` or ``--[extra-]index-url=``. + + This returns: + + * ``page_candidates``: Links listed on an HTML file. + * ``file_candidates``: The non-HTML file. + """ + + def __init__( + self, + candidates_from_page: CandidatesFromPage, + page_validator: PageValidator, + link: Link, + ) -> None: + self._candidates_from_page = candidates_from_page + self._page_validator = page_validator + self._link = link + + @property + def link(self) -> Optional[Link]: + return self._link + + def page_candidates(self) -> FoundCandidates: + if not self._page_validator(self._link): + return + yield from self._candidates_from_page(self._link) + + def file_links(self) -> FoundLinks: + yield self._link + + +class _IndexDirectorySource(LinkSource): + """``--[extra-]index-url=``. + + This is treated like a remote URL; ``candidates_from_page`` contains logic + for this by appending ``index.html`` to the link. + """ + + def __init__( + self, + candidates_from_page: CandidatesFromPage, + link: Link, + ) -> None: + self._candidates_from_page = candidates_from_page + self._link = link + + @property + def link(self) -> Optional[Link]: + return self._link + + def page_candidates(self) -> FoundCandidates: + yield from self._candidates_from_page(self._link) + + def file_links(self) -> FoundLinks: + return () + + +def build_source( + location: str, + *, + candidates_from_page: CandidatesFromPage, + page_validator: PageValidator, + expand_dir: bool, + cache_link_parsing: bool, +) -> Tuple[Optional[str], Optional[LinkSource]]: + + path: Optional[str] = None + url: Optional[str] = None + if os.path.exists(location): # Is a local path. + url = path_to_url(location) + path = location + elif location.startswith("file:"): # A file: URL. + url = location + path = url_to_path(location) + elif is_url(location): + url = location + + if url is None: + msg = ( + "Location '%s' is ignored: " + "it is either a non-existing path or lacks a specific scheme." + ) + logger.warning(msg, location) + return (None, None) + + if path is None: + source: LinkSource = _RemoteFileSource( + candidates_from_page=candidates_from_page, + page_validator=page_validator, + link=Link(url, cache_link_parsing=cache_link_parsing), + ) + return (url, source) + + if os.path.isdir(path): + if expand_dir: + source = _FlatDirectorySource( + candidates_from_page=candidates_from_page, + path=path, + ) + else: + source = _IndexDirectorySource( + candidates_from_page=candidates_from_page, + link=Link(url, cache_link_parsing=cache_link_parsing), + ) + return (url, source) + elif os.path.isfile(path): + source = _LocalFileSource( + candidates_from_page=candidates_from_page, + link=Link(url, cache_link_parsing=cache_link_parsing), + ) + return (url, source) + logger.warning( + "Location '%s' is ignored: it is neither a file nor a directory.", + location, + ) + return (url, None) diff --git a/venv/Lib/site-packages/pip/_internal/locations/__init__.py b/venv/Lib/site-packages/pip/_internal/locations/__init__.py new file mode 100644 index 0000000..ac0c166 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/locations/__init__.py @@ -0,0 +1,520 @@ +import functools +import logging +import os +import pathlib +import sys +import sysconfig +from typing import Any, Dict, Iterator, List, Optional, Tuple + +from pip._internal.models.scheme import SCHEME_KEYS, Scheme +from pip._internal.utils.compat import WINDOWS +from pip._internal.utils.deprecation import deprecated +from pip._internal.utils.virtualenv import running_under_virtualenv + +from . import _distutils, _sysconfig +from .base import ( + USER_CACHE_DIR, + get_major_minor_version, + get_src_prefix, + is_osx_framework, + site_packages, + user_site, +) + +__all__ = [ + "USER_CACHE_DIR", + "get_bin_prefix", + "get_bin_user", + "get_major_minor_version", + "get_platlib", + "get_prefixed_libs", + "get_purelib", + "get_scheme", + "get_src_prefix", + "site_packages", + "user_site", +] + + +logger = logging.getLogger(__name__) + + +_PLATLIBDIR: str = getattr(sys, "platlibdir", "lib") + +_USE_SYSCONFIG_DEFAULT = sys.version_info >= (3, 10) + + +def _should_use_sysconfig() -> bool: + """This function determines the value of _USE_SYSCONFIG. + + By default, pip uses sysconfig on Python 3.10+. + But Python distributors can override this decision by setting: + sysconfig._PIP_USE_SYSCONFIG = True / False + Rationale in https://github.com/pypa/pip/issues/10647 + + This is a function for testability, but should be constant during any one + run. + """ + return bool(getattr(sysconfig, "_PIP_USE_SYSCONFIG", _USE_SYSCONFIG_DEFAULT)) + + +_USE_SYSCONFIG = _should_use_sysconfig() + +# Be noisy about incompatibilities if this platforms "should" be using +# sysconfig, but is explicitly opting out and using distutils instead. +if _USE_SYSCONFIG_DEFAULT and not _USE_SYSCONFIG: + _MISMATCH_LEVEL = logging.WARNING +else: + _MISMATCH_LEVEL = logging.DEBUG + + +def _looks_like_bpo_44860() -> bool: + """The resolution to bpo-44860 will change this incorrect platlib. + + See . + """ + from distutils.command.install import INSTALL_SCHEMES # type: ignore + + try: + unix_user_platlib = INSTALL_SCHEMES["unix_user"]["platlib"] + except KeyError: + return False + return unix_user_platlib == "$usersite" + + +def _looks_like_red_hat_patched_platlib_purelib(scheme: Dict[str, str]) -> bool: + platlib = scheme["platlib"] + if "/$platlibdir/" in platlib: + platlib = platlib.replace("/$platlibdir/", f"/{_PLATLIBDIR}/") + if "/lib64/" not in platlib: + return False + unpatched = platlib.replace("/lib64/", "/lib/") + return unpatched.replace("$platbase/", "$base/") == scheme["purelib"] + + +@functools.lru_cache(maxsize=None) +def _looks_like_red_hat_lib() -> bool: + """Red Hat patches platlib in unix_prefix and unix_home, but not purelib. + + This is the only way I can see to tell a Red Hat-patched Python. + """ + from distutils.command.install import INSTALL_SCHEMES # type: ignore + + return all( + k in INSTALL_SCHEMES + and _looks_like_red_hat_patched_platlib_purelib(INSTALL_SCHEMES[k]) + for k in ("unix_prefix", "unix_home") + ) + + +@functools.lru_cache(maxsize=None) +def _looks_like_debian_scheme() -> bool: + """Debian adds two additional schemes.""" + from distutils.command.install import INSTALL_SCHEMES # type: ignore + + return "deb_system" in INSTALL_SCHEMES and "unix_local" in INSTALL_SCHEMES + + +@functools.lru_cache(maxsize=None) +def _looks_like_red_hat_scheme() -> bool: + """Red Hat patches ``sys.prefix`` and ``sys.exec_prefix``. + + Red Hat's ``00251-change-user-install-location.patch`` changes the install + command's ``prefix`` and ``exec_prefix`` to append ``"/local"``. This is + (fortunately?) done quite unconditionally, so we create a default command + object without any configuration to detect this. + """ + from distutils.command.install import install + from distutils.dist import Distribution + + cmd: Any = install(Distribution()) + cmd.finalize_options() + return ( + cmd.exec_prefix == f"{os.path.normpath(sys.exec_prefix)}/local" + and cmd.prefix == f"{os.path.normpath(sys.prefix)}/local" + ) + + +@functools.lru_cache(maxsize=None) +def _looks_like_slackware_scheme() -> bool: + """Slackware patches sysconfig but fails to patch distutils and site. + + Slackware changes sysconfig's user scheme to use ``"lib64"`` for the lib + path, but does not do the same to the site module. + """ + if user_site is None: # User-site not available. + return False + try: + paths = sysconfig.get_paths(scheme="posix_user", expand=False) + except KeyError: # User-site not available. + return False + return "/lib64/" in paths["purelib"] and "/lib64/" not in user_site + + +@functools.lru_cache(maxsize=None) +def _looks_like_msys2_mingw_scheme() -> bool: + """MSYS2 patches distutils and sysconfig to use a UNIX-like scheme. + + However, MSYS2 incorrectly patches sysconfig ``nt`` scheme. The fix is + likely going to be included in their 3.10 release, so we ignore the warning. + See msys2/MINGW-packages#9319. + + MSYS2 MINGW's patch uses lowercase ``"lib"`` instead of the usual uppercase, + and is missing the final ``"site-packages"``. + """ + paths = sysconfig.get_paths("nt", expand=False) + return all( + "Lib" not in p and "lib" in p and not p.endswith("site-packages") + for p in (paths[key] for key in ("platlib", "purelib")) + ) + + +def _fix_abiflags(parts: Tuple[str]) -> Iterator[str]: + ldversion = sysconfig.get_config_var("LDVERSION") + abiflags: str = getattr(sys, "abiflags", None) + + # LDVERSION does not end with sys.abiflags. Just return the path unchanged. + if not ldversion or not abiflags or not ldversion.endswith(abiflags): + yield from parts + return + + # Strip sys.abiflags from LDVERSION-based path components. + for part in parts: + if part.endswith(ldversion): + part = part[: (0 - len(abiflags))] + yield part + + +@functools.lru_cache(maxsize=None) +def _warn_mismatched(old: pathlib.Path, new: pathlib.Path, *, key: str) -> None: + issue_url = "https://github.com/pypa/pip/issues/10151" + message = ( + "Value for %s does not match. Please report this to <%s>" + "\ndistutils: %s" + "\nsysconfig: %s" + ) + logger.log(_MISMATCH_LEVEL, message, key, issue_url, old, new) + + +def _warn_if_mismatch(old: pathlib.Path, new: pathlib.Path, *, key: str) -> bool: + if old == new: + return False + _warn_mismatched(old, new, key=key) + return True + + +@functools.lru_cache(maxsize=None) +def _log_context( + *, + user: bool = False, + home: Optional[str] = None, + root: Optional[str] = None, + prefix: Optional[str] = None, +) -> None: + parts = [ + "Additional context:", + "user = %r", + "home = %r", + "root = %r", + "prefix = %r", + ] + + logger.log(_MISMATCH_LEVEL, "\n".join(parts), user, home, root, prefix) + + +def get_scheme( + dist_name: str, + user: bool = False, + home: Optional[str] = None, + root: Optional[str] = None, + isolated: bool = False, + prefix: Optional[str] = None, +) -> Scheme: + new = _sysconfig.get_scheme( + dist_name, + user=user, + home=home, + root=root, + isolated=isolated, + prefix=prefix, + ) + if _USE_SYSCONFIG: + return new + + old = _distutils.get_scheme( + dist_name, + user=user, + home=home, + root=root, + isolated=isolated, + prefix=prefix, + ) + + warning_contexts = [] + for k in SCHEME_KEYS: + old_v = pathlib.Path(getattr(old, k)) + new_v = pathlib.Path(getattr(new, k)) + + if old_v == new_v: + continue + + # distutils incorrectly put PyPy packages under ``site-packages/python`` + # in the ``posix_home`` scheme, but PyPy devs said they expect the + # directory name to be ``pypy`` instead. So we treat this as a bug fix + # and not warn about it. See bpo-43307 and python/cpython#24628. + skip_pypy_special_case = ( + sys.implementation.name == "pypy" + and home is not None + and k in ("platlib", "purelib") + and old_v.parent == new_v.parent + and old_v.name.startswith("python") + and new_v.name.startswith("pypy") + ) + if skip_pypy_special_case: + continue + + # sysconfig's ``osx_framework_user`` does not include ``pythonX.Y`` in + # the ``include`` value, but distutils's ``headers`` does. We'll let + # CPython decide whether this is a bug or feature. See bpo-43948. + skip_osx_framework_user_special_case = ( + user + and is_osx_framework() + and k == "headers" + and old_v.parent.parent == new_v.parent + and old_v.parent.name.startswith("python") + ) + if skip_osx_framework_user_special_case: + continue + + # On Red Hat and derived Linux distributions, distutils is patched to + # use "lib64" instead of "lib" for platlib. + if k == "platlib" and _looks_like_red_hat_lib(): + continue + + # On Python 3.9+, sysconfig's posix_user scheme sets platlib against + # sys.platlibdir, but distutils's unix_user incorrectly coninutes + # using the same $usersite for both platlib and purelib. This creates a + # mismatch when sys.platlibdir is not "lib". + skip_bpo_44860 = ( + user + and k == "platlib" + and not WINDOWS + and sys.version_info >= (3, 9) + and _PLATLIBDIR != "lib" + and _looks_like_bpo_44860() + ) + if skip_bpo_44860: + continue + + # Slackware incorrectly patches posix_user to use lib64 instead of lib, + # but not usersite to match the location. + skip_slackware_user_scheme = ( + user + and k in ("platlib", "purelib") + and not WINDOWS + and _looks_like_slackware_scheme() + ) + if skip_slackware_user_scheme: + continue + + # Both Debian and Red Hat patch Python to place the system site under + # /usr/local instead of /usr. Debian also places lib in dist-packages + # instead of site-packages, but the /usr/local check should cover it. + skip_linux_system_special_case = ( + not (user or home or prefix or running_under_virtualenv()) + and old_v.parts[1:3] == ("usr", "local") + and len(new_v.parts) > 1 + and new_v.parts[1] == "usr" + and (len(new_v.parts) < 3 or new_v.parts[2] != "local") + and (_looks_like_red_hat_scheme() or _looks_like_debian_scheme()) + ) + if skip_linux_system_special_case: + continue + + # On Python 3.7 and earlier, sysconfig does not include sys.abiflags in + # the "pythonX.Y" part of the path, but distutils does. + skip_sysconfig_abiflag_bug = ( + sys.version_info < (3, 8) + and not WINDOWS + and k in ("headers", "platlib", "purelib") + and tuple(_fix_abiflags(old_v.parts)) == new_v.parts + ) + if skip_sysconfig_abiflag_bug: + continue + + # MSYS2 MINGW's sysconfig patch does not include the "site-packages" + # part of the path. This is incorrect and will be fixed in MSYS. + skip_msys2_mingw_bug = ( + WINDOWS and k in ("platlib", "purelib") and _looks_like_msys2_mingw_scheme() + ) + if skip_msys2_mingw_bug: + continue + + # CPython's POSIX install script invokes pip (via ensurepip) against the + # interpreter located in the source tree, not the install site. This + # triggers special logic in sysconfig that's not present in distutils. + # https://github.com/python/cpython/blob/8c21941ddaf/Lib/sysconfig.py#L178-L194 + skip_cpython_build = ( + sysconfig.is_python_build(check_home=True) + and not WINDOWS + and k in ("headers", "include", "platinclude") + ) + if skip_cpython_build: + continue + + warning_contexts.append((old_v, new_v, f"scheme.{k}")) + + if not warning_contexts: + return old + + # Check if this path mismatch is caused by distutils config files. Those + # files will no longer work once we switch to sysconfig, so this raises a + # deprecation message for them. + default_old = _distutils.distutils_scheme( + dist_name, + user, + home, + root, + isolated, + prefix, + ignore_config_files=True, + ) + if any(default_old[k] != getattr(old, k) for k in SCHEME_KEYS): + deprecated( + reason=( + "Configuring installation scheme with distutils config files " + "is deprecated and will no longer work in the near future. If you " + "are using a Homebrew or Linuxbrew Python, please see discussion " + "at https://github.com/Homebrew/homebrew-core/issues/76621" + ), + replacement=None, + gone_in=None, + ) + return old + + # Post warnings about this mismatch so user can report them back. + for old_v, new_v, key in warning_contexts: + _warn_mismatched(old_v, new_v, key=key) + _log_context(user=user, home=home, root=root, prefix=prefix) + + return old + + +def get_bin_prefix() -> str: + new = _sysconfig.get_bin_prefix() + if _USE_SYSCONFIG: + return new + + old = _distutils.get_bin_prefix() + if _warn_if_mismatch(pathlib.Path(old), pathlib.Path(new), key="bin_prefix"): + _log_context() + return old + + +def get_bin_user() -> str: + return _sysconfig.get_scheme("", user=True).scripts + + +def _looks_like_deb_system_dist_packages(value: str) -> bool: + """Check if the value is Debian's APT-controlled dist-packages. + + Debian's ``distutils.sysconfig.get_python_lib()`` implementation returns the + default package path controlled by APT, but does not patch ``sysconfig`` to + do the same. This is similar to the bug worked around in ``get_scheme()``, + but here the default is ``deb_system`` instead of ``unix_local``. Ultimately + we can't do anything about this Debian bug, and this detection allows us to + skip the warning when needed. + """ + if not _looks_like_debian_scheme(): + return False + if value == "/usr/lib/python3/dist-packages": + return True + return False + + +def get_purelib() -> str: + """Return the default pure-Python lib location.""" + new = _sysconfig.get_purelib() + if _USE_SYSCONFIG: + return new + + old = _distutils.get_purelib() + if _looks_like_deb_system_dist_packages(old): + return old + if _warn_if_mismatch(pathlib.Path(old), pathlib.Path(new), key="purelib"): + _log_context() + return old + + +def get_platlib() -> str: + """Return the default platform-shared lib location.""" + new = _sysconfig.get_platlib() + if _USE_SYSCONFIG: + return new + + old = _distutils.get_platlib() + if _looks_like_deb_system_dist_packages(old): + return old + if _warn_if_mismatch(pathlib.Path(old), pathlib.Path(new), key="platlib"): + _log_context() + return old + + +def _deduplicated(v1: str, v2: str) -> List[str]: + """Deduplicate values from a list.""" + if v1 == v2: + return [v1] + return [v1, v2] + + +def _looks_like_apple_library(path: str) -> bool: + """Apple patches sysconfig to *always* look under */Library/Python*.""" + if sys.platform[:6] != "darwin": + return False + return path == f"/Library/Python/{get_major_minor_version()}/site-packages" + + +def get_prefixed_libs(prefix: str) -> List[str]: + """Return the lib locations under ``prefix``.""" + new_pure, new_plat = _sysconfig.get_prefixed_libs(prefix) + if _USE_SYSCONFIG: + return _deduplicated(new_pure, new_plat) + + old_pure, old_plat = _distutils.get_prefixed_libs(prefix) + old_lib_paths = _deduplicated(old_pure, old_plat) + + # Apple's Python (shipped with Xcode and Command Line Tools) hard-code + # platlib and purelib to '/Library/Python/X.Y/site-packages'. This will + # cause serious build isolation bugs when Apple starts shipping 3.10 because + # pip will install build backends to the wrong location. This tells users + # who is at fault so Apple may notice it and fix the issue in time. + if all(_looks_like_apple_library(p) for p in old_lib_paths): + deprecated( + reason=( + "Python distributed by Apple's Command Line Tools incorrectly " + "patches sysconfig to always point to '/Library/Python'. This " + "will cause build isolation to operate incorrectly on Python " + "3.10 or later. Please help report this to Apple so they can " + "fix this. https://developer.apple.com/bug-reporting/" + ), + replacement=None, + gone_in=None, + ) + return old_lib_paths + + warned = [ + _warn_if_mismatch( + pathlib.Path(old_pure), + pathlib.Path(new_pure), + key="prefixed-purelib", + ), + _warn_if_mismatch( + pathlib.Path(old_plat), + pathlib.Path(new_plat), + key="prefixed-platlib", + ), + ] + if any(warned): + _log_context(prefix=prefix) + + return old_lib_paths diff --git a/venv/Lib/site-packages/pip/_internal/locations/__pycache__/__init__.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/locations/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e28b0b6ab31970d4bcfcc740dadea6659ec10e32 GIT binary patch literal 12507 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 Ow}!Uo@wYoQl=@!{D8R!2 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/locations/__pycache__/_distutils.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/locations/__pycache__/_distutils.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6ebf97a2ad5e3f50690482733949909931409219 GIT binary patch literal 4658 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 Ht7iQd;3?)m literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/locations/__pycache__/_sysconfig.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/locations/__pycache__/_sysconfig.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f7ec380bce8796336424a18b4868fbf9bfafcab1 GIT binary patch literal 6249 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 f%xAMjGnY2Z}CkMR-OTK)&l zhYq%|u8=H?6Cq*P5jkTC8-+QGsR+*!p>mQ^cBb7d$#f;l1x=HIZpuW_FeA|mGNQ(@ zEU3x_i%iVh%>iW(e%SyK<1tcr?EH>ke`iMPKD3^7^wlZ#CuGdU_9S6k_-9negfpKH z?NpQtL7DQOPSq(`iS&stm4H+~_Gx$2wV^gY>wdZEgEI_1dAL~^XQh{y-IteJt}YL` zm=L91IhDF`y+N3;A^#JJCCJZ;e}CQkx_=^J`#xce$o_7YJtB(qf8r5I`^R*W^#P0R zoSEa(c>Da6(scWauf~atWt78s*~DAuF)8(J7zxCelbh-Tj$LqUc-1seEMp8G^lpI*=?SAe+>hxCVn zPyC25pK(9sYy=Aj#s#R;-Kq;0veXWj+RKPK)!vvVOw^3AoC!KiE_4}?h|XhOIXv1I zf(z}@i$nn(2hz9ztLl(RSggJ&kT6uzEd%4t^aj{u3k1Styy7}|4L6)+Pjt-MS`Ot5 z4P_16C*(pVGx`?3#?gb{;%mYvAnM!!{P2}Q#W@JtPoEz@K0NroxBK({v%}txKqzm( zd8%tbr--v*GAfcP#^D(ew{o`hvWYJzGUW0i911d_=Ulw_6t*i0?}+;_-rCT$Va_52 z!KG+}MSCW93!b=V^s<^}P=;U?>d^h4Y+a}gco+`p`|p_P-dyLRIxUM!M50p~!ULdN zCrA6eaBp|-@qYN|Nl#Y|#-vgTcNkjM7J#pUqlsEfslalMx@lQj5hq5v=Y^c$}y7TXQSqCWtz& XzWJO6Zn$-~%JVuZ5Z^ literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/locations/_distutils.py b/venv/Lib/site-packages/pip/_internal/locations/_distutils.py new file mode 100644 index 0000000..2ec79e6 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/locations/_distutils.py @@ -0,0 +1,169 @@ +"""Locations where we look for configs, install stuff, etc""" + +# The following comment should be removed at some point in the future. +# mypy: strict-optional=False + +import logging +import os +import sys +from distutils.cmd import Command as DistutilsCommand +from distutils.command.install import SCHEME_KEYS +from distutils.command.install import install as distutils_install_command +from distutils.sysconfig import get_python_lib +from typing import Dict, List, Optional, Tuple, Union, cast + +from pip._internal.models.scheme import Scheme +from pip._internal.utils.compat import WINDOWS +from pip._internal.utils.virtualenv import running_under_virtualenv + +from .base import get_major_minor_version + +logger = logging.getLogger(__name__) + + +def distutils_scheme( + dist_name: str, + user: bool = False, + home: str = None, + root: str = None, + isolated: bool = False, + prefix: str = None, + *, + ignore_config_files: bool = False, +) -> Dict[str, str]: + """ + Return a distutils install scheme + """ + from distutils.dist import Distribution + + dist_args: Dict[str, Union[str, List[str]]] = {"name": dist_name} + if isolated: + dist_args["script_args"] = ["--no-user-cfg"] + + d = Distribution(dist_args) + if not ignore_config_files: + try: + d.parse_config_files() + except UnicodeDecodeError: + # Typeshed does not include find_config_files() for some reason. + paths = d.find_config_files() # type: ignore + logger.warning( + "Ignore distutils configs in %s due to encoding errors.", + ", ".join(os.path.basename(p) for p in paths), + ) + obj: Optional[DistutilsCommand] = None + obj = d.get_command_obj("install", create=True) + assert obj is not None + i = cast(distutils_install_command, obj) + # NOTE: setting user or home has the side-effect of creating the home dir + # or user base for installations during finalize_options() + # ideally, we'd prefer a scheme class that has no side-effects. + assert not (user and prefix), f"user={user} prefix={prefix}" + assert not (home and prefix), f"home={home} prefix={prefix}" + i.user = user or i.user + if user or home: + i.prefix = "" + i.prefix = prefix or i.prefix + i.home = home or i.home + i.root = root or i.root + i.finalize_options() + + scheme = {} + for key in SCHEME_KEYS: + scheme[key] = getattr(i, "install_" + key) + + # install_lib specified in setup.cfg should install *everything* + # into there (i.e. it takes precedence over both purelib and + # platlib). Note, i.install_lib is *always* set after + # finalize_options(); we only want to override here if the user + # has explicitly requested it hence going back to the config + if "install_lib" in d.get_option_dict("install"): + scheme.update(dict(purelib=i.install_lib, platlib=i.install_lib)) + + if running_under_virtualenv(): + if home: + prefix = home + elif user: + prefix = i.install_userbase # type: ignore + else: + prefix = i.prefix + scheme["headers"] = os.path.join( + prefix, + "include", + "site", + f"python{get_major_minor_version()}", + dist_name, + ) + + if root is not None: + path_no_drive = os.path.splitdrive(os.path.abspath(scheme["headers"]))[1] + scheme["headers"] = os.path.join(root, path_no_drive[1:]) + + return scheme + + +def get_scheme( + dist_name: str, + user: bool = False, + home: Optional[str] = None, + root: Optional[str] = None, + isolated: bool = False, + prefix: Optional[str] = None, +) -> Scheme: + """ + Get the "scheme" corresponding to the input parameters. The distutils + documentation provides the context for the available schemes: + https://docs.python.org/3/install/index.html#alternate-installation + + :param dist_name: the name of the package to retrieve the scheme for, used + in the headers scheme path + :param user: indicates to use the "user" scheme + :param home: indicates to use the "home" scheme and provides the base + directory for the same + :param root: root under which other directories are re-based + :param isolated: equivalent to --no-user-cfg, i.e. do not consider + ~/.pydistutils.cfg (posix) or ~/pydistutils.cfg (non-posix) for + scheme paths + :param prefix: indicates to use the "prefix" scheme and provides the + base directory for the same + """ + scheme = distutils_scheme(dist_name, user, home, root, isolated, prefix) + return Scheme( + platlib=scheme["platlib"], + purelib=scheme["purelib"], + headers=scheme["headers"], + scripts=scheme["scripts"], + data=scheme["data"], + ) + + +def get_bin_prefix() -> str: + # XXX: In old virtualenv versions, sys.prefix can contain '..' components, + # so we need to call normpath to eliminate them. + prefix = os.path.normpath(sys.prefix) + if WINDOWS: + bin_py = os.path.join(prefix, "Scripts") + # buildout uses 'bin' on Windows too? + if not os.path.exists(bin_py): + bin_py = os.path.join(prefix, "bin") + return bin_py + # Forcing to use /usr/local/bin for standard macOS framework installs + # Also log to ~/Library/Logs/ for use with the Console.app log viewer + if sys.platform[:6] == "darwin" and prefix[:16] == "/System/Library/": + return "/usr/local/bin" + return os.path.join(prefix, "bin") + + +def get_purelib() -> str: + return get_python_lib(plat_specific=False) + + +def get_platlib() -> str: + return get_python_lib(plat_specific=True) + + +def get_prefixed_libs(prefix: str) -> Tuple[str, str]: + return ( + get_python_lib(plat_specific=False, prefix=prefix), + get_python_lib(plat_specific=True, prefix=prefix), + ) diff --git a/venv/Lib/site-packages/pip/_internal/locations/_sysconfig.py b/venv/Lib/site-packages/pip/_internal/locations/_sysconfig.py new file mode 100644 index 0000000..5e141aa --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/locations/_sysconfig.py @@ -0,0 +1,219 @@ +import distutils.util # FIXME: For change_root. +import logging +import os +import sys +import sysconfig +import typing + +from pip._internal.exceptions import InvalidSchemeCombination, UserInstallationInvalid +from pip._internal.models.scheme import SCHEME_KEYS, Scheme +from pip._internal.utils.virtualenv import running_under_virtualenv + +from .base import get_major_minor_version, is_osx_framework + +logger = logging.getLogger(__name__) + + +# Notes on _infer_* functions. +# Unfortunately ``get_default_scheme()`` didn't exist before 3.10, so there's no +# way to ask things like "what is the '_prefix' scheme on this platform". These +# functions try to answer that with some heuristics while accounting for ad-hoc +# platforms not covered by CPython's default sysconfig implementation. If the +# ad-hoc implementation does not fully implement sysconfig, we'll fall back to +# a POSIX scheme. + +_AVAILABLE_SCHEMES = set(sysconfig.get_scheme_names()) + +_PREFERRED_SCHEME_API = getattr(sysconfig, "get_preferred_scheme", None) + + +def _should_use_osx_framework_prefix() -> bool: + """Check for Apple's ``osx_framework_library`` scheme. + + Python distributed by Apple's Command Line Tools has this special scheme + that's used when: + + * This is a framework build. + * We are installing into the system prefix. + + This does not account for ``pip install --prefix`` (also means we're not + installing to the system prefix), which should use ``posix_prefix``, but + logic here means ``_infer_prefix()`` outputs ``osx_framework_library``. But + since ``prefix`` is not available for ``sysconfig.get_default_scheme()``, + which is the stdlib replacement for ``_infer_prefix()``, presumably Apple + wouldn't be able to magically switch between ``osx_framework_library`` and + ``posix_prefix``. ``_infer_prefix()`` returning ``osx_framework_library`` + means its behavior is consistent whether we use the stdlib implementation + or our own, and we deal with this special case in ``get_scheme()`` instead. + """ + return ( + "osx_framework_library" in _AVAILABLE_SCHEMES + and not running_under_virtualenv() + and is_osx_framework() + ) + + +def _infer_prefix() -> str: + """Try to find a prefix scheme for the current platform. + + This tries: + + * A special ``osx_framework_library`` for Python distributed by Apple's + Command Line Tools, when not running in a virtual environment. + * Implementation + OS, used by PyPy on Windows (``pypy_nt``). + * Implementation without OS, used by PyPy on POSIX (``pypy``). + * OS + "prefix", used by CPython on POSIX (``posix_prefix``). + * Just the OS name, used by CPython on Windows (``nt``). + + If none of the above works, fall back to ``posix_prefix``. + """ + if _PREFERRED_SCHEME_API: + return _PREFERRED_SCHEME_API("prefix") + if _should_use_osx_framework_prefix(): + return "osx_framework_library" + implementation_suffixed = f"{sys.implementation.name}_{os.name}" + if implementation_suffixed in _AVAILABLE_SCHEMES: + return implementation_suffixed + if sys.implementation.name in _AVAILABLE_SCHEMES: + return sys.implementation.name + suffixed = f"{os.name}_prefix" + if suffixed in _AVAILABLE_SCHEMES: + return suffixed + if os.name in _AVAILABLE_SCHEMES: # On Windows, prefx is just called "nt". + return os.name + return "posix_prefix" + + +def _infer_user() -> str: + """Try to find a user scheme for the current platform.""" + if _PREFERRED_SCHEME_API: + return _PREFERRED_SCHEME_API("user") + if is_osx_framework() and not running_under_virtualenv(): + suffixed = "osx_framework_user" + else: + suffixed = f"{os.name}_user" + if suffixed in _AVAILABLE_SCHEMES: + return suffixed + if "posix_user" not in _AVAILABLE_SCHEMES: # User scheme unavailable. + raise UserInstallationInvalid() + return "posix_user" + + +def _infer_home() -> str: + """Try to find a home for the current platform.""" + if _PREFERRED_SCHEME_API: + return _PREFERRED_SCHEME_API("home") + suffixed = f"{os.name}_home" + if suffixed in _AVAILABLE_SCHEMES: + return suffixed + return "posix_home" + + +# Update these keys if the user sets a custom home. +_HOME_KEYS = [ + "installed_base", + "base", + "installed_platbase", + "platbase", + "prefix", + "exec_prefix", +] +if sysconfig.get_config_var("userbase") is not None: + _HOME_KEYS.append("userbase") + + +def get_scheme( + dist_name: str, + user: bool = False, + home: typing.Optional[str] = None, + root: typing.Optional[str] = None, + isolated: bool = False, + prefix: typing.Optional[str] = None, +) -> Scheme: + """ + Get the "scheme" corresponding to the input parameters. + + :param dist_name: the name of the package to retrieve the scheme for, used + in the headers scheme path + :param user: indicates to use the "user" scheme + :param home: indicates to use the "home" scheme + :param root: root under which other directories are re-based + :param isolated: ignored, but kept for distutils compatibility (where + this controls whether the user-site pydistutils.cfg is honored) + :param prefix: indicates to use the "prefix" scheme and provides the + base directory for the same + """ + if user and prefix: + raise InvalidSchemeCombination("--user", "--prefix") + if home and prefix: + raise InvalidSchemeCombination("--home", "--prefix") + + if home is not None: + scheme_name = _infer_home() + elif user: + scheme_name = _infer_user() + else: + scheme_name = _infer_prefix() + + # Special case: When installing into a custom prefix, use posix_prefix + # instead of osx_framework_library. See _should_use_osx_framework_prefix() + # docstring for details. + if prefix is not None and scheme_name == "osx_framework_library": + scheme_name = "posix_prefix" + + if home is not None: + variables = {k: home for k in _HOME_KEYS} + elif prefix is not None: + variables = {k: prefix for k in _HOME_KEYS} + else: + variables = {} + + paths = sysconfig.get_paths(scheme=scheme_name, vars=variables) + + # Logic here is very arbitrary, we're doing it for compatibility, don't ask. + # 1. Pip historically uses a special header path in virtual environments. + # 2. If the distribution name is not known, distutils uses 'UNKNOWN'. We + # only do the same when not running in a virtual environment because + # pip's historical header path logic (see point 1) did not do this. + if running_under_virtualenv(): + if user: + base = variables.get("userbase", sys.prefix) + else: + base = variables.get("base", sys.prefix) + python_xy = f"python{get_major_minor_version()}" + paths["include"] = os.path.join(base, "include", "site", python_xy) + elif not dist_name: + dist_name = "UNKNOWN" + + scheme = Scheme( + platlib=paths["platlib"], + purelib=paths["purelib"], + headers=os.path.join(paths["include"], dist_name), + scripts=paths["scripts"], + data=paths["data"], + ) + if root is not None: + for key in SCHEME_KEYS: + value = distutils.util.change_root(root, getattr(scheme, key)) + setattr(scheme, key, value) + return scheme + + +def get_bin_prefix() -> str: + # Forcing to use /usr/local/bin for standard macOS framework installs. + if sys.platform[:6] == "darwin" and sys.prefix[:16] == "/System/Library/": + return "/usr/local/bin" + return sysconfig.get_paths()["scripts"] + + +def get_purelib() -> str: + return sysconfig.get_paths()["purelib"] + + +def get_platlib() -> str: + return sysconfig.get_paths()["platlib"] + + +def get_prefixed_libs(prefix: str) -> typing.Tuple[str, str]: + paths = sysconfig.get_paths(vars={"base": prefix, "platbase": prefix}) + return (paths["purelib"], paths["platlib"]) diff --git a/venv/Lib/site-packages/pip/_internal/locations/base.py b/venv/Lib/site-packages/pip/_internal/locations/base.py new file mode 100644 index 0000000..86dad4a --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/locations/base.py @@ -0,0 +1,52 @@ +import functools +import os +import site +import sys +import sysconfig +import typing + +from pip._internal.utils import appdirs +from pip._internal.utils.virtualenv import running_under_virtualenv + +# Application Directories +USER_CACHE_DIR = appdirs.user_cache_dir("pip") + +# FIXME doesn't account for venv linked to global site-packages +site_packages: typing.Optional[str] = sysconfig.get_path("purelib") + + +def get_major_minor_version() -> str: + """ + Return the major-minor version of the current Python as a string, e.g. + "3.7" or "3.10". + """ + return "{}.{}".format(*sys.version_info) + + +def get_src_prefix() -> str: + if running_under_virtualenv(): + src_prefix = os.path.join(sys.prefix, "src") + else: + # FIXME: keep src in cwd for now (it is not a temporary folder) + try: + src_prefix = os.path.join(os.getcwd(), "src") + except OSError: + # In case the current working directory has been renamed or deleted + sys.exit("The folder you are executing pip from can no longer be found.") + + # under macOS + virtualenv sys.prefix is not properly resolved + # it is something like /path/to/python/bin/.. + return os.path.abspath(src_prefix) + + +try: + # Use getusersitepackages if this is present, as it ensures that the + # value is initialised properly. + user_site: typing.Optional[str] = site.getusersitepackages() +except AttributeError: + user_site = site.USER_SITE + + +@functools.lru_cache(maxsize=None) +def is_osx_framework() -> bool: + return bool(sysconfig.get_config_var("PYTHONFRAMEWORK")) diff --git a/venv/Lib/site-packages/pip/_internal/main.py b/venv/Lib/site-packages/pip/_internal/main.py new file mode 100644 index 0000000..33c6d24 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/main.py @@ -0,0 +1,12 @@ +from typing import List, Optional + + +def main(args: Optional[List[str]] = None) -> int: + """This is preserved for old console scripts that may still be referencing + it. + + For additional details, see https://github.com/pypa/pip/issues/7498. + """ + from pip._internal.utils.entrypoints import _wrapper + + return _wrapper(args) diff --git a/venv/Lib/site-packages/pip/_internal/metadata/__init__.py b/venv/Lib/site-packages/pip/_internal/metadata/__init__.py new file mode 100644 index 0000000..cc037c1 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/metadata/__init__.py @@ -0,0 +1,62 @@ +from typing import List, Optional + +from .base import BaseDistribution, BaseEnvironment, FilesystemWheel, MemoryWheel, Wheel + +__all__ = [ + "BaseDistribution", + "BaseEnvironment", + "FilesystemWheel", + "MemoryWheel", + "Wheel", + "get_default_environment", + "get_environment", + "get_wheel_distribution", +] + + +def get_default_environment() -> BaseEnvironment: + """Get the default representation for the current environment. + + This returns an Environment instance from the chosen backend. The default + Environment instance should be built from ``sys.path`` and may use caching + to share instance state accorss calls. + """ + from .pkg_resources import Environment + + return Environment.default() + + +def get_environment(paths: Optional[List[str]]) -> BaseEnvironment: + """Get a representation of the environment specified by ``paths``. + + This returns an Environment instance from the chosen backend based on the + given import paths. The backend must build a fresh instance representing + the state of installed distributions when this function is called. + """ + from .pkg_resources import Environment + + return Environment.from_paths(paths) + + +def get_directory_distribution(directory: str) -> BaseDistribution: + """Get the distribution metadata representation in the specified directory. + + This returns a Distribution instance from the chosen backend based on + the given on-disk ``.dist-info`` directory. + """ + from .pkg_resources import Distribution + + return Distribution.from_directory(directory) + + +def get_wheel_distribution(wheel: Wheel, canonical_name: str) -> BaseDistribution: + """Get the representation of the specified wheel's distribution metadata. + + This returns a Distribution instance from the chosen backend based on + the given wheel's ``.dist-info`` directory. + + :param canonical_name: Normalized project name of the given wheel. + """ + from .pkg_resources import Distribution + + return Distribution.from_wheel(wheel, canonical_name) diff --git a/venv/Lib/site-packages/pip/_internal/metadata/__pycache__/__init__.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/metadata/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8df578ea28ee3700f2ffbce18fbb320df857cbd6 GIT binary patch literal 2322 zcmcIl%WfP+6z%SLdR}${Byj|yRz$P#tWXqL2muMO31LAHQfs81a#xL~;(n>BJ7_E; zv0%#|coDPXPxyx3vdW$nE6%N+X}2wV1(Z}ZQ@0-X);;Ik=Hv0eLHqT?kBHmJs1>*UcHHqhao6w0J--+C{l4oQJEHxY>+i^p z=$yNvD|)}Q{ekqPD~J2ez5{#z+!H%u0Q*P|Wm^m}ABi#MW7)Ts$$3lcial5+;?8%@ z^zK_k;Y_`<{al&6?0=i(DouFw)+KYN-1~wX`3y^19Tl`x?vmxpMjk)ilh59>|iMGAIm%ta>N-35r{@eQ@8ADnHM?ku`#v4F(MD|^<&yC*OtmrC8%1Vjw`!v2?`}D4gfMNDY$|)3 zWa$YVar9mM{JnU3IRD;AZRR{lxS4;RWzTrd=g(6(nZJ~AHqTUcP$U_>T^v|64<0{x zrA%l}X>A^;B$pZ-oX0Zff=&mpsXPc~*;c0 zU>yi)F*#PRK^7Hfsm_^oR54~l9~KuTx111+gB8-OE`hFzTyp_btI)@zEHk4B?wWcs z45*NMPB z0fsw5X&L6I9{&Qz(?4oCH>w2Nvgtaw%4WI&XdT0iXtHKCyiD{h+OE;8goxxl zQhoyF%qaB-Dp{sbaKklKm8}{_O`qF@-$%;)iA{KY3`u_vW=(6?l3qTf>RIo+T0ybB z!lDa3J-`f_?^tb?laMEAq5yu7@K{#3kfyecv_)F9`l7S7zVJai^GIK3?uBO+Hfhw_ znwnLO-DvDmSJwR_bA_5Ui2oxrTfetMW3fEUxaKiL(ag>vdy(pxN9q)s%5?e)WM-5$ zws~HKzID+Q5|yPZxK={4`(WS4vVKUz4Z!LV7CuI=5bOg%vb>n?mfd`vLHL^B(u7ml zrs{J0x40Js5P1;Tnp(E-*|%D?l(4rpNJaHtlbp-`Cvhr@NPbFX*O2o)?|rX7nv5Qd H_J;oeJRFMY literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/metadata/__pycache__/base.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/metadata/__pycache__/base.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ec2df9fae3927c0f2917147d0c28390296f89917 GIT binary patch literal 21114 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 V0FyC8Z^JH?&3e9ew*CvP{6A$`RU`la literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/metadata/base.py b/venv/Lib/site-packages/pip/_internal/metadata/base.py new file mode 100644 index 0000000..1a5a781 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/metadata/base.py @@ -0,0 +1,546 @@ +import csv +import email.message +import json +import logging +import pathlib +import re +import zipfile +from typing import ( + IO, + TYPE_CHECKING, + Collection, + Container, + Iterable, + Iterator, + List, + Optional, + Tuple, + Union, +) + +from pip._vendor.packaging.requirements import Requirement +from pip._vendor.packaging.specifiers import InvalidSpecifier, SpecifierSet +from pip._vendor.packaging.utils import NormalizedName +from pip._vendor.packaging.version import LegacyVersion, Version + +from pip._internal.exceptions import NoneMetadataError +from pip._internal.locations import site_packages, user_site +from pip._internal.models.direct_url import ( + DIRECT_URL_METADATA_NAME, + DirectUrl, + DirectUrlValidationError, +) +from pip._internal.utils.compat import stdlib_pkgs # TODO: Move definition here. +from pip._internal.utils.egg_link import ( + egg_link_path_from_location, + egg_link_path_from_sys_path, +) +from pip._internal.utils.misc import is_local, normalize_path +from pip._internal.utils.urls import url_to_path + +if TYPE_CHECKING: + from typing import Protocol +else: + Protocol = object + +DistributionVersion = Union[LegacyVersion, Version] + +InfoPath = Union[str, pathlib.PurePosixPath] + +logger = logging.getLogger(__name__) + + +class BaseEntryPoint(Protocol): + @property + def name(self) -> str: + raise NotImplementedError() + + @property + def value(self) -> str: + raise NotImplementedError() + + @property + def group(self) -> str: + raise NotImplementedError() + + +def _convert_installed_files_path( + entry: Tuple[str, ...], + info: Tuple[str, ...], +) -> str: + """Convert a legacy installed-files.txt path into modern RECORD path. + + The legacy format stores paths relative to the info directory, while the + modern format stores paths relative to the package root, e.g. the + site-packages directory. + + :param entry: Path parts of the installed-files.txt entry. + :param info: Path parts of the egg-info directory relative to package root. + :returns: The converted entry. + + For best compatibility with symlinks, this does not use ``abspath()`` or + ``Path.resolve()``, but tries to work with path parts: + + 1. While ``entry`` starts with ``..``, remove the equal amounts of parts + from ``info``; if ``info`` is empty, start appending ``..`` instead. + 2. Join the two directly. + """ + while entry and entry[0] == "..": + if not info or info[-1] == "..": + info += ("..",) + else: + info = info[:-1] + entry = entry[1:] + return str(pathlib.Path(*info, *entry)) + + +class BaseDistribution(Protocol): + def __repr__(self) -> str: + return f"{self.raw_name} {self.version} ({self.location})" + + def __str__(self) -> str: + return f"{self.raw_name} {self.version}" + + @property + def location(self) -> Optional[str]: + """Where the distribution is loaded from. + + A string value is not necessarily a filesystem path, since distributions + can be loaded from other sources, e.g. arbitrary zip archives. ``None`` + means the distribution is created in-memory. + + Do not canonicalize this value with e.g. ``pathlib.Path.resolve()``. If + this is a symbolic link, we want to preserve the relative path between + it and files in the distribution. + """ + raise NotImplementedError() + + @property + def editable_project_location(self) -> Optional[str]: + """The project location for editable distributions. + + This is the directory where pyproject.toml or setup.py is located. + None if the distribution is not installed in editable mode. + """ + # TODO: this property is relatively costly to compute, memoize it ? + direct_url = self.direct_url + if direct_url: + if direct_url.is_local_editable(): + return url_to_path(direct_url.url) + else: + # Search for an .egg-link file by walking sys.path, as it was + # done before by dist_is_editable(). + egg_link_path = egg_link_path_from_sys_path(self.raw_name) + if egg_link_path: + # TODO: get project location from second line of egg_link file + # (https://github.com/pypa/pip/issues/10243) + return self.location + return None + + @property + def installed_location(self) -> Optional[str]: + """The distribution's "installed" location. + + This should generally be a ``site-packages`` directory. This is + usually ``dist.location``, except for legacy develop-installed packages, + where ``dist.location`` is the source code location, and this is where + the ``.egg-link`` file is. + + The returned location is normalized (in particular, with symlinks removed). + """ + egg_link = egg_link_path_from_location(self.raw_name) + if egg_link: + location = egg_link + elif self.location: + location = self.location + else: + return None + return normalize_path(location) + + @property + def info_location(self) -> Optional[str]: + """Location of the .[egg|dist]-info directory or file. + + Similarly to ``location``, a string value is not necessarily a + filesystem path. ``None`` means the distribution is created in-memory. + + For a modern .dist-info installation on disk, this should be something + like ``{location}/{raw_name}-{version}.dist-info``. + + Do not canonicalize this value with e.g. ``pathlib.Path.resolve()``. If + this is a symbolic link, we want to preserve the relative path between + it and other files in the distribution. + """ + raise NotImplementedError() + + @property + def installed_by_distutils(self) -> bool: + """Whether this distribution is installed with legacy distutils format. + + A distribution installed with "raw" distutils not patched by setuptools + uses one single file at ``info_location`` to store metadata. We need to + treat this specially on uninstallation. + """ + info_location = self.info_location + if not info_location: + return False + return pathlib.Path(info_location).is_file() + + @property + def installed_as_egg(self) -> bool: + """Whether this distribution is installed as an egg. + + This usually indicates the distribution was installed by (older versions + of) easy_install. + """ + location = self.location + if not location: + return False + return location.endswith(".egg") + + @property + def installed_with_setuptools_egg_info(self) -> bool: + """Whether this distribution is installed with the ``.egg-info`` format. + + This usually indicates the distribution was installed with setuptools + with an old pip version or with ``single-version-externally-managed``. + + Note that this ensure the metadata store is a directory. distutils can + also installs an ``.egg-info``, but as a file, not a directory. This + property is *False* for that case. Also see ``installed_by_distutils``. + """ + info_location = self.info_location + if not info_location: + return False + if not info_location.endswith(".egg-info"): + return False + return pathlib.Path(info_location).is_dir() + + @property + def installed_with_dist_info(self) -> bool: + """Whether this distribution is installed with the "modern format". + + This indicates a "modern" installation, e.g. storing metadata in the + ``.dist-info`` directory. This applies to installations made by + setuptools (but through pip, not directly), or anything using the + standardized build backend interface (PEP 517). + """ + info_location = self.info_location + if not info_location: + return False + if not info_location.endswith(".dist-info"): + return False + return pathlib.Path(info_location).is_dir() + + @property + def canonical_name(self) -> NormalizedName: + raise NotImplementedError() + + @property + def version(self) -> DistributionVersion: + raise NotImplementedError() + + @property + def setuptools_filename(self) -> str: + """Convert a project name to its setuptools-compatible filename. + + This is a copy of ``pkg_resources.to_filename()`` for compatibility. + """ + return self.raw_name.replace("-", "_") + + @property + def direct_url(self) -> Optional[DirectUrl]: + """Obtain a DirectUrl from this distribution. + + Returns None if the distribution has no `direct_url.json` metadata, + or if `direct_url.json` is invalid. + """ + try: + content = self.read_text(DIRECT_URL_METADATA_NAME) + except FileNotFoundError: + return None + try: + return DirectUrl.from_json(content) + except ( + UnicodeDecodeError, + json.JSONDecodeError, + DirectUrlValidationError, + ) as e: + logger.warning( + "Error parsing %s for %s: %s", + DIRECT_URL_METADATA_NAME, + self.canonical_name, + e, + ) + return None + + @property + def installer(self) -> str: + try: + installer_text = self.read_text("INSTALLER") + except (OSError, ValueError, NoneMetadataError): + return "" # Fail silently if the installer file cannot be read. + for line in installer_text.splitlines(): + cleaned_line = line.strip() + if cleaned_line: + return cleaned_line + return "" + + @property + def editable(self) -> bool: + return bool(self.editable_project_location) + + @property + def local(self) -> bool: + """If distribution is installed in the current virtual environment. + + Always True if we're not in a virtualenv. + """ + if self.installed_location is None: + return False + return is_local(self.installed_location) + + @property + def in_usersite(self) -> bool: + if self.installed_location is None or user_site is None: + return False + return self.installed_location.startswith(normalize_path(user_site)) + + @property + def in_site_packages(self) -> bool: + if self.installed_location is None or site_packages is None: + return False + return self.installed_location.startswith(normalize_path(site_packages)) + + def is_file(self, path: InfoPath) -> bool: + """Check whether an entry in the info directory is a file.""" + raise NotImplementedError() + + def iterdir(self, path: InfoPath) -> Iterator[pathlib.PurePosixPath]: + """Iterate through a directory in the info directory. + + Each item yielded would be a path relative to the info directory. + + :raise FileNotFoundError: If ``name`` does not exist in the directory. + :raise NotADirectoryError: If ``name`` does not point to a directory. + """ + raise NotImplementedError() + + def read_text(self, path: InfoPath) -> str: + """Read a file in the info directory. + + :raise FileNotFoundError: If ``name`` does not exist in the directory. + :raise NoneMetadataError: If ``name`` exists in the info directory, but + cannot be read. + """ + raise NotImplementedError() + + def iter_entry_points(self) -> Iterable[BaseEntryPoint]: + raise NotImplementedError() + + @property + def metadata(self) -> email.message.Message: + """Metadata of distribution parsed from e.g. METADATA or PKG-INFO. + + This should return an empty message if the metadata file is unavailable. + + :raises NoneMetadataError: If the metadata file is available, but does + not contain valid metadata. + """ + raise NotImplementedError() + + @property + def metadata_version(self) -> Optional[str]: + """Value of "Metadata-Version:" in distribution metadata, if available.""" + return self.metadata.get("Metadata-Version") + + @property + def raw_name(self) -> str: + """Value of "Name:" in distribution metadata.""" + # The metadata should NEVER be missing the Name: key, but if it somehow + # does, fall back to the known canonical name. + return self.metadata.get("Name", self.canonical_name) + + @property + def requires_python(self) -> SpecifierSet: + """Value of "Requires-Python:" in distribution metadata. + + If the key does not exist or contains an invalid value, an empty + SpecifierSet should be returned. + """ + value = self.metadata.get("Requires-Python") + if value is None: + return SpecifierSet() + try: + # Convert to str to satisfy the type checker; this can be a Header object. + spec = SpecifierSet(str(value)) + except InvalidSpecifier as e: + message = "Package %r has an invalid Requires-Python: %s" + logger.warning(message, self.raw_name, e) + return SpecifierSet() + return spec + + def iter_dependencies(self, extras: Collection[str] = ()) -> Iterable[Requirement]: + """Dependencies of this distribution. + + For modern .dist-info distributions, this is the collection of + "Requires-Dist:" entries in distribution metadata. + """ + raise NotImplementedError() + + def iter_provided_extras(self) -> Iterable[str]: + """Extras provided by this distribution. + + For modern .dist-info distributions, this is the collection of + "Provides-Extra:" entries in distribution metadata. + """ + raise NotImplementedError() + + def _iter_declared_entries_from_record(self) -> Optional[Iterator[str]]: + try: + text = self.read_text("RECORD") + except FileNotFoundError: + return None + # This extra Path-str cast normalizes entries. + return (str(pathlib.Path(row[0])) for row in csv.reader(text.splitlines())) + + def _iter_declared_entries_from_legacy(self) -> Optional[Iterator[str]]: + try: + text = self.read_text("installed-files.txt") + except FileNotFoundError: + return None + paths = (p for p in text.splitlines(keepends=False) if p) + root = self.location + info = self.info_location + if root is None or info is None: + return paths + try: + info_rel = pathlib.Path(info).relative_to(root) + except ValueError: # info is not relative to root. + return paths + if not info_rel.parts: # info *is* root. + return paths + return ( + _convert_installed_files_path(pathlib.Path(p).parts, info_rel.parts) + for p in paths + ) + + def iter_declared_entries(self) -> Optional[Iterator[str]]: + """Iterate through file entires declared in this distribution. + + For modern .dist-info distributions, this is the files listed in the + ``RECORD`` metadata file. For legacy setuptools distributions, this + comes from ``installed-files.txt``, with entries normalized to be + compatible with the format used by ``RECORD``. + + :return: An iterator for listed entries, or None if the distribution + contains neither ``RECORD`` nor ``installed-files.txt``. + """ + return ( + self._iter_declared_entries_from_record() + or self._iter_declared_entries_from_legacy() + ) + + +class BaseEnvironment: + """An environment containing distributions to introspect.""" + + @classmethod + def default(cls) -> "BaseEnvironment": + raise NotImplementedError() + + @classmethod + def from_paths(cls, paths: Optional[List[str]]) -> "BaseEnvironment": + raise NotImplementedError() + + def get_distribution(self, name: str) -> Optional["BaseDistribution"]: + """Given a requirement name, return the installed distributions. + + The name may not be normalized. The implementation must canonicalize + it for lookup. + """ + raise NotImplementedError() + + def _iter_distributions(self) -> Iterator["BaseDistribution"]: + """Iterate through installed distributions. + + This function should be implemented by subclass, but never called + directly. Use the public ``iter_distribution()`` instead, which + implements additional logic to make sure the distributions are valid. + """ + raise NotImplementedError() + + def iter_distributions(self) -> Iterator["BaseDistribution"]: + """Iterate through installed distributions.""" + for dist in self._iter_distributions(): + # Make sure the distribution actually comes from a valid Python + # packaging distribution. Pip's AdjacentTempDirectory leaves folders + # e.g. ``~atplotlib.dist-info`` if cleanup was interrupted. The + # valid project name pattern is taken from PEP 508. + project_name_valid = re.match( + r"^([A-Z0-9]|[A-Z0-9][A-Z0-9._-]*[A-Z0-9])$", + dist.canonical_name, + flags=re.IGNORECASE, + ) + if not project_name_valid: + logger.warning( + "Ignoring invalid distribution %s (%s)", + dist.canonical_name, + dist.location, + ) + continue + yield dist + + def iter_installed_distributions( + self, + local_only: bool = True, + skip: Container[str] = stdlib_pkgs, + include_editables: bool = True, + editables_only: bool = False, + user_only: bool = False, + ) -> Iterator[BaseDistribution]: + """Return a list of installed distributions. + + :param local_only: If True (default), only return installations + local to the current virtualenv, if in a virtualenv. + :param skip: An iterable of canonicalized project names to ignore; + defaults to ``stdlib_pkgs``. + :param include_editables: If False, don't report editables. + :param editables_only: If True, only report editables. + :param user_only: If True, only report installations in the user + site directory. + """ + it = self.iter_distributions() + if local_only: + it = (d for d in it if d.local) + if not include_editables: + it = (d for d in it if not d.editable) + if editables_only: + it = (d for d in it if d.editable) + if user_only: + it = (d for d in it if d.in_usersite) + return (d for d in it if d.canonical_name not in skip) + + +class Wheel(Protocol): + location: str + + def as_zipfile(self) -> zipfile.ZipFile: + raise NotImplementedError() + + +class FilesystemWheel(Wheel): + def __init__(self, location: str) -> None: + self.location = location + + def as_zipfile(self) -> zipfile.ZipFile: + return zipfile.ZipFile(self.location, allowZip64=True) + + +class MemoryWheel(Wheel): + def __init__(self, location: str, stream: IO[bytes]) -> None: + self.location = location + self.stream = stream + + def as_zipfile(self) -> zipfile.ZipFile: + return zipfile.ZipFile(self.stream, allowZip64=True) diff --git a/venv/Lib/site-packages/pip/_internal/metadata/pkg_resources.py b/venv/Lib/site-packages/pip/_internal/metadata/pkg_resources.py new file mode 100644 index 0000000..d39f0ba --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/metadata/pkg_resources.py @@ -0,0 +1,256 @@ +import email.message +import email.parser +import logging +import os +import pathlib +import zipfile +from typing import Collection, Iterable, Iterator, List, Mapping, NamedTuple, Optional + +from pip._vendor import pkg_resources +from pip._vendor.packaging.requirements import Requirement +from pip._vendor.packaging.utils import NormalizedName, canonicalize_name +from pip._vendor.packaging.version import parse as parse_version + +from pip._internal.exceptions import InvalidWheel, NoneMetadataError, UnsupportedWheel +from pip._internal.utils.misc import display_path +from pip._internal.utils.wheel import parse_wheel, read_wheel_metadata_file + +from .base import ( + BaseDistribution, + BaseEntryPoint, + BaseEnvironment, + DistributionVersion, + InfoPath, + Wheel, +) + +logger = logging.getLogger(__name__) + + +class EntryPoint(NamedTuple): + name: str + value: str + group: str + + +class WheelMetadata: + """IMetadataProvider that reads metadata files from a dictionary. + + This also maps metadata decoding exceptions to our internal exception type. + """ + + def __init__(self, metadata: Mapping[str, bytes], wheel_name: str) -> None: + self._metadata = metadata + self._wheel_name = wheel_name + + def has_metadata(self, name: str) -> bool: + return name in self._metadata + + def get_metadata(self, name: str) -> str: + try: + return self._metadata[name].decode() + except UnicodeDecodeError as e: + # Augment the default error with the origin of the file. + raise UnsupportedWheel( + f"Error decoding metadata for {self._wheel_name}: {e} in {name} file" + ) + + def get_metadata_lines(self, name: str) -> Iterable[str]: + return pkg_resources.yield_lines(self.get_metadata(name)) + + def metadata_isdir(self, name: str) -> bool: + return False + + def metadata_listdir(self, name: str) -> List[str]: + return [] + + def run_script(self, script_name: str, namespace: str) -> None: + pass + + +class Distribution(BaseDistribution): + def __init__(self, dist: pkg_resources.Distribution) -> None: + self._dist = dist + + @classmethod + def from_directory(cls, directory: str) -> "Distribution": + dist_dir = directory.rstrip(os.sep) + + # Build a PathMetadata object, from path to metadata. :wink: + base_dir, dist_dir_name = os.path.split(dist_dir) + metadata = pkg_resources.PathMetadata(base_dir, dist_dir) + + # Determine the correct Distribution object type. + if dist_dir.endswith(".egg-info"): + dist_cls = pkg_resources.Distribution + dist_name = os.path.splitext(dist_dir_name)[0] + else: + assert dist_dir.endswith(".dist-info") + dist_cls = pkg_resources.DistInfoDistribution + dist_name = os.path.splitext(dist_dir_name)[0].split("-")[0] + + dist = dist_cls(base_dir, project_name=dist_name, metadata=metadata) + return cls(dist) + + @classmethod + def from_wheel(cls, wheel: Wheel, name: str) -> "Distribution": + """Load the distribution from a given wheel. + + :raises InvalidWheel: Whenever loading of the wheel causes a + :py:exc:`zipfile.BadZipFile` exception to be thrown. + :raises UnsupportedWheel: If the wheel is a valid zip, but malformed + internally. + """ + try: + with wheel.as_zipfile() as zf: + info_dir, _ = parse_wheel(zf, name) + metadata_text = { + path.split("/", 1)[-1]: read_wheel_metadata_file(zf, path) + for path in zf.namelist() + if path.startswith(f"{info_dir}/") + } + except zipfile.BadZipFile as e: + raise InvalidWheel(wheel.location, name) from e + except UnsupportedWheel as e: + raise UnsupportedWheel(f"{name} has an invalid wheel, {e}") + dist = pkg_resources.DistInfoDistribution( + location=wheel.location, + metadata=WheelMetadata(metadata_text, wheel.location), + project_name=name, + ) + return cls(dist) + + @property + def location(self) -> Optional[str]: + return self._dist.location + + @property + def info_location(self) -> Optional[str]: + return self._dist.egg_info + + @property + def installed_by_distutils(self) -> bool: + # A distutils-installed distribution is provided by FileMetadata. This + # provider has a "path" attribute not present anywhere else. Not the + # best introspection logic, but pip has been doing this for a long time. + try: + return bool(self._dist._provider.path) + except AttributeError: + return False + + @property + def canonical_name(self) -> NormalizedName: + return canonicalize_name(self._dist.project_name) + + @property + def version(self) -> DistributionVersion: + return parse_version(self._dist.version) + + def is_file(self, path: InfoPath) -> bool: + return self._dist.has_metadata(str(path)) + + def iterdir(self, path: InfoPath) -> Iterator[pathlib.PurePosixPath]: + name = str(path) + if not self._dist.has_metadata(name): + raise FileNotFoundError(name) + if not self._dist.isdir(name): + raise NotADirectoryError(name) + for child in self._dist.metadata_listdir(name): + yield pathlib.PurePosixPath(path, child) + + def read_text(self, path: InfoPath) -> str: + name = str(path) + if not self._dist.has_metadata(name): + raise FileNotFoundError(name) + content = self._dist.get_metadata(name) + if content is None: + raise NoneMetadataError(self, name) + return content + + def iter_entry_points(self) -> Iterable[BaseEntryPoint]: + for group, entries in self._dist.get_entry_map().items(): + for name, entry_point in entries.items(): + name, _, value = str(entry_point).partition("=") + yield EntryPoint(name=name.strip(), value=value.strip(), group=group) + + @property + def metadata(self) -> email.message.Message: + """ + :raises NoneMetadataError: if the distribution reports `has_metadata()` + True but `get_metadata()` returns None. + """ + if isinstance(self._dist, pkg_resources.DistInfoDistribution): + metadata_name = "METADATA" + else: + metadata_name = "PKG-INFO" + try: + metadata = self.read_text(metadata_name) + except FileNotFoundError: + if self.location: + displaying_path = display_path(self.location) + else: + displaying_path = repr(self.location) + logger.warning("No metadata found in %s", displaying_path) + metadata = "" + feed_parser = email.parser.FeedParser() + feed_parser.feed(metadata) + return feed_parser.close() + + def iter_dependencies(self, extras: Collection[str] = ()) -> Iterable[Requirement]: + if extras: # pkg_resources raises on invalid extras, so we sanitize. + extras = frozenset(extras).intersection(self._dist.extras) + return self._dist.requires(extras) + + def iter_provided_extras(self) -> Iterable[str]: + return self._dist.extras + + +class Environment(BaseEnvironment): + def __init__(self, ws: pkg_resources.WorkingSet) -> None: + self._ws = ws + + @classmethod + def default(cls) -> BaseEnvironment: + return cls(pkg_resources.working_set) + + @classmethod + def from_paths(cls, paths: Optional[List[str]]) -> BaseEnvironment: + return cls(pkg_resources.WorkingSet(paths)) + + def _search_distribution(self, name: str) -> Optional[BaseDistribution]: + """Find a distribution matching the ``name`` in the environment. + + This searches from *all* distributions available in the environment, to + match the behavior of ``pkg_resources.get_distribution()``. + """ + canonical_name = canonicalize_name(name) + for dist in self.iter_distributions(): + if dist.canonical_name == canonical_name: + return dist + return None + + def get_distribution(self, name: str) -> Optional[BaseDistribution]: + # Search the distribution by looking through the working set. + dist = self._search_distribution(name) + if dist: + return dist + + # If distribution could not be found, call working_set.require to + # update the working set, and try to find the distribution again. + # This might happen for e.g. when you install a package twice, once + # using setup.py develop and again using setup.py install. Now when + # running pip uninstall twice, the package gets removed from the + # working set in the first uninstall, so we have to populate the + # working set again so that pip knows about it and the packages gets + # picked up and is successfully uninstalled the second time too. + try: + # We didn't pass in any version specifiers, so this can never + # raise pkg_resources.VersionConflict. + self._ws.require(name) + except pkg_resources.DistributionNotFound: + return None + return self._search_distribution(name) + + def _iter_distributions(self) -> Iterator[BaseDistribution]: + for dist in self._ws: + yield Distribution(dist) diff --git a/venv/Lib/site-packages/pip/_internal/models/__init__.py b/venv/Lib/site-packages/pip/_internal/models/__init__.py new file mode 100644 index 0000000..7855226 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/models/__init__.py @@ -0,0 +1,2 @@ +"""A package that contains models that represent entities. +""" diff --git a/venv/Lib/site-packages/pip/_internal/models/__pycache__/__init__.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/models/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f98b68beb9f5232c032ccf2b901c0fd06c6381a9 GIT binary patch literal 253 zcmYjMy=nqM5Z<%Nao{s#E5YI{MI=sWlzzS6aMgmhM! zi%mZGX867t<_G%yLNG3mgUt))?@s(j#$v{#oP!k~!e%Qm?42ib8Nlq}3uW3ulBV$q zoF`c~7Av}&5ko{mpCr>Ihcqgd!>oPK+BQb(tB5@w`xkDXuT%9-7)gQmKx!Vs8zfMR z#z3XkSO*ncC=b5di?%#&5vy`M**P+F?rKUqpD=oEzh9v=J1%KG3a2)IV)IbpbNA8@ GQ~UzBq)M~^ literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/models/__pycache__/candidate.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/models/__pycache__/candidate.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b94d81857c3dbcd0d10a2a9a2ad19a8658086935 GIT binary patch literal 1436 zcmbVML2uhO6ecA~a$Gwd)~@RYWK(h|B4F`pD2k#e)@8sjGz*4xy9fpdR-{uUw4{=B zx1{bV0eb2`=waI}e~E`(dg@;&uwn1XcH(B)Wfb`IQRE}P_whZ6e!okgz54vt<3B?} z-r!)lF&KOW-QEEsiKLp0X&z9-feyzkXDtqOG>-F_l5dG*GCCnLQt@$^Co+CSvg9pz zlZ^VP5ymP2Y^SUa;C=m}I{aE#CAaG_%&G6oU(2e%)yplK59|*B6v?S1c_3*X?g5KG zXwFmwPb@>pUbB~EL}eu7lU|;vNG7kT?8uc9mUrf(uDk-Hm6wE(ybJ7l{-f_I>x9Ud*DrZxXHnjs(3Y~5gizOTBs5WW2*cC5kQCSq9vjX>lL3(c(X%7xZW^{0D2KX_Ei| literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/models/__pycache__/direct_url.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/models/__pycache__/direct_url.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2dbd8b2829b3c8a99b778b7bef94a5c737aa7a28 GIT binary patch literal 7226 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/models/__pycache__/link.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/models/__pycache__/link.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..68cd56741bd34448eb278d4192bf677471507e36 GIT binary patch literal 10247 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/models/__pycache__/scheme.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/models/__pycache__/scheme.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..918de24786f5386719cf88ab67d149a3166ef9be GIT binary patch literal 999 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/models/candidate.py b/venv/Lib/site-packages/pip/_internal/models/candidate.py new file mode 100644 index 0000000..a4963ae --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/models/candidate.py @@ -0,0 +1,34 @@ +from pip._vendor.packaging.version import parse as parse_version + +from pip._internal.models.link import Link +from pip._internal.utils.models import KeyBasedCompareMixin + + +class InstallationCandidate(KeyBasedCompareMixin): + """Represents a potential "candidate" for installation.""" + + __slots__ = ["name", "version", "link"] + + def __init__(self, name: str, version: str, link: Link) -> None: + self.name = name + self.version = parse_version(version) + self.link = link + + super().__init__( + key=(self.name, self.version, self.link), + defining_class=InstallationCandidate, + ) + + def __repr__(self) -> str: + return "".format( + self.name, + self.version, + self.link, + ) + + def __str__(self) -> str: + return "{!r} candidate (version {} at {})".format( + self.name, + self.version, + self.link, + ) diff --git a/venv/Lib/site-packages/pip/_internal/models/direct_url.py b/venv/Lib/site-packages/pip/_internal/models/direct_url.py new file mode 100644 index 0000000..92060d4 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/models/direct_url.py @@ -0,0 +1,220 @@ +""" PEP 610 """ +import json +import re +import urllib.parse +from typing import Any, Dict, Iterable, Optional, Type, TypeVar, Union + +__all__ = [ + "DirectUrl", + "DirectUrlValidationError", + "DirInfo", + "ArchiveInfo", + "VcsInfo", +] + +T = TypeVar("T") + +DIRECT_URL_METADATA_NAME = "direct_url.json" +ENV_VAR_RE = re.compile(r"^\$\{[A-Za-z0-9-_]+\}(:\$\{[A-Za-z0-9-_]+\})?$") + + +class DirectUrlValidationError(Exception): + pass + + +def _get( + d: Dict[str, Any], expected_type: Type[T], key: str, default: Optional[T] = None +) -> Optional[T]: + """Get value from dictionary and verify expected type.""" + if key not in d: + return default + value = d[key] + if not isinstance(value, expected_type): + raise DirectUrlValidationError( + "{!r} has unexpected type for {} (expected {})".format( + value, key, expected_type + ) + ) + return value + + +def _get_required( + d: Dict[str, Any], expected_type: Type[T], key: str, default: Optional[T] = None +) -> T: + value = _get(d, expected_type, key, default) + if value is None: + raise DirectUrlValidationError(f"{key} must have a value") + return value + + +def _exactly_one_of(infos: Iterable[Optional["InfoType"]]) -> "InfoType": + infos = [info for info in infos if info is not None] + if not infos: + raise DirectUrlValidationError( + "missing one of archive_info, dir_info, vcs_info" + ) + if len(infos) > 1: + raise DirectUrlValidationError( + "more than one of archive_info, dir_info, vcs_info" + ) + assert infos[0] is not None + return infos[0] + + +def _filter_none(**kwargs: Any) -> Dict[str, Any]: + """Make dict excluding None values.""" + return {k: v for k, v in kwargs.items() if v is not None} + + +class VcsInfo: + name = "vcs_info" + + def __init__( + self, + vcs: str, + commit_id: str, + requested_revision: Optional[str] = None, + resolved_revision: Optional[str] = None, + resolved_revision_type: Optional[str] = None, + ) -> None: + self.vcs = vcs + self.requested_revision = requested_revision + self.commit_id = commit_id + self.resolved_revision = resolved_revision + self.resolved_revision_type = resolved_revision_type + + @classmethod + def _from_dict(cls, d: Optional[Dict[str, Any]]) -> Optional["VcsInfo"]: + if d is None: + return None + return cls( + vcs=_get_required(d, str, "vcs"), + commit_id=_get_required(d, str, "commit_id"), + requested_revision=_get(d, str, "requested_revision"), + resolved_revision=_get(d, str, "resolved_revision"), + resolved_revision_type=_get(d, str, "resolved_revision_type"), + ) + + def _to_dict(self) -> Dict[str, Any]: + return _filter_none( + vcs=self.vcs, + requested_revision=self.requested_revision, + commit_id=self.commit_id, + resolved_revision=self.resolved_revision, + resolved_revision_type=self.resolved_revision_type, + ) + + +class ArchiveInfo: + name = "archive_info" + + def __init__( + self, + hash: Optional[str] = None, + ) -> None: + self.hash = hash + + @classmethod + def _from_dict(cls, d: Optional[Dict[str, Any]]) -> Optional["ArchiveInfo"]: + if d is None: + return None + return cls(hash=_get(d, str, "hash")) + + def _to_dict(self) -> Dict[str, Any]: + return _filter_none(hash=self.hash) + + +class DirInfo: + name = "dir_info" + + def __init__( + self, + editable: bool = False, + ) -> None: + self.editable = editable + + @classmethod + def _from_dict(cls, d: Optional[Dict[str, Any]]) -> Optional["DirInfo"]: + if d is None: + return None + return cls(editable=_get_required(d, bool, "editable", default=False)) + + def _to_dict(self) -> Dict[str, Any]: + return _filter_none(editable=self.editable or None) + + +InfoType = Union[ArchiveInfo, DirInfo, VcsInfo] + + +class DirectUrl: + def __init__( + self, + url: str, + info: InfoType, + subdirectory: Optional[str] = None, + ) -> None: + self.url = url + self.info = info + self.subdirectory = subdirectory + + def _remove_auth_from_netloc(self, netloc: str) -> str: + if "@" not in netloc: + return netloc + user_pass, netloc_no_user_pass = netloc.split("@", 1) + if ( + isinstance(self.info, VcsInfo) + and self.info.vcs == "git" + and user_pass == "git" + ): + return netloc + if ENV_VAR_RE.match(user_pass): + return netloc + return netloc_no_user_pass + + @property + def redacted_url(self) -> str: + """url with user:password part removed unless it is formed with + environment variables as specified in PEP 610, or it is ``git`` + in the case of a git URL. + """ + purl = urllib.parse.urlsplit(self.url) + netloc = self._remove_auth_from_netloc(purl.netloc) + surl = urllib.parse.urlunsplit( + (purl.scheme, netloc, purl.path, purl.query, purl.fragment) + ) + return surl + + def validate(self) -> None: + self.from_dict(self.to_dict()) + + @classmethod + def from_dict(cls, d: Dict[str, Any]) -> "DirectUrl": + return DirectUrl( + url=_get_required(d, str, "url"), + subdirectory=_get(d, str, "subdirectory"), + info=_exactly_one_of( + [ + ArchiveInfo._from_dict(_get(d, dict, "archive_info")), + DirInfo._from_dict(_get(d, dict, "dir_info")), + VcsInfo._from_dict(_get(d, dict, "vcs_info")), + ] + ), + ) + + def to_dict(self) -> Dict[str, Any]: + res = _filter_none( + url=self.redacted_url, + subdirectory=self.subdirectory, + ) + res[self.info.name] = self.info._to_dict() + return res + + @classmethod + def from_json(cls, s: str) -> "DirectUrl": + return cls.from_dict(json.loads(s)) + + def to_json(self) -> str: + return json.dumps(self.to_dict(), sort_keys=True) + + def is_local_editable(self) -> bool: + return isinstance(self.info, DirInfo) and self.info.editable diff --git a/venv/Lib/site-packages/pip/_internal/models/format_control.py b/venv/Lib/site-packages/pip/_internal/models/format_control.py new file mode 100644 index 0000000..db3995e --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/models/format_control.py @@ -0,0 +1,80 @@ +from typing import FrozenSet, Optional, Set + +from pip._vendor.packaging.utils import canonicalize_name + +from pip._internal.exceptions import CommandError + + +class FormatControl: + """Helper for managing formats from which a package can be installed.""" + + __slots__ = ["no_binary", "only_binary"] + + def __init__( + self, + no_binary: Optional[Set[str]] = None, + only_binary: Optional[Set[str]] = None, + ) -> None: + if no_binary is None: + no_binary = set() + if only_binary is None: + only_binary = set() + + self.no_binary = no_binary + self.only_binary = only_binary + + def __eq__(self, other: object) -> bool: + if not isinstance(other, self.__class__): + return NotImplemented + + if self.__slots__ != other.__slots__: + return False + + return all(getattr(self, k) == getattr(other, k) for k in self.__slots__) + + def __repr__(self) -> str: + return "{}({}, {})".format( + self.__class__.__name__, self.no_binary, self.only_binary + ) + + @staticmethod + def handle_mutual_excludes(value: str, target: Set[str], other: Set[str]) -> None: + if value.startswith("-"): + raise CommandError( + "--no-binary / --only-binary option requires 1 argument." + ) + new = value.split(",") + while ":all:" in new: + other.clear() + target.clear() + target.add(":all:") + del new[: new.index(":all:") + 1] + # Without a none, we want to discard everything as :all: covers it + if ":none:" not in new: + return + for name in new: + if name == ":none:": + target.clear() + continue + name = canonicalize_name(name) + other.discard(name) + target.add(name) + + def get_allowed_formats(self, canonical_name: str) -> FrozenSet[str]: + result = {"binary", "source"} + if canonical_name in self.only_binary: + result.discard("source") + elif canonical_name in self.no_binary: + result.discard("binary") + elif ":all:" in self.only_binary: + result.discard("source") + elif ":all:" in self.no_binary: + result.discard("binary") + return frozenset(result) + + def disallow_binaries(self) -> None: + self.handle_mutual_excludes( + ":all:", + self.no_binary, + self.only_binary, + ) diff --git a/venv/Lib/site-packages/pip/_internal/models/index.py b/venv/Lib/site-packages/pip/_internal/models/index.py new file mode 100644 index 0000000..b94c325 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/models/index.py @@ -0,0 +1,28 @@ +import urllib.parse + + +class PackageIndex: + """Represents a Package Index and provides easier access to endpoints""" + + __slots__ = ["url", "netloc", "simple_url", "pypi_url", "file_storage_domain"] + + def __init__(self, url: str, file_storage_domain: str) -> None: + super().__init__() + self.url = url + self.netloc = urllib.parse.urlsplit(url).netloc + self.simple_url = self._url_for_path("simple") + self.pypi_url = self._url_for_path("pypi") + + # This is part of a temporary hack used to block installs of PyPI + # packages which depend on external urls only necessary until PyPI can + # block such packages themselves + self.file_storage_domain = file_storage_domain + + def _url_for_path(self, path: str) -> str: + return urllib.parse.urljoin(self.url, path) + + +PyPI = PackageIndex("https://pypi.org/", file_storage_domain="files.pythonhosted.org") +TestPyPI = PackageIndex( + "https://test.pypi.org/", file_storage_domain="test-files.pythonhosted.org" +) diff --git a/venv/Lib/site-packages/pip/_internal/models/link.py b/venv/Lib/site-packages/pip/_internal/models/link.py new file mode 100644 index 0000000..6069b27 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/models/link.py @@ -0,0 +1,288 @@ +import functools +import logging +import os +import posixpath +import re +import urllib.parse +from typing import TYPE_CHECKING, Dict, List, NamedTuple, Optional, Tuple, Union + +from pip._internal.utils.filetypes import WHEEL_EXTENSION +from pip._internal.utils.hashes import Hashes +from pip._internal.utils.misc import ( + redact_auth_from_url, + split_auth_from_netloc, + splitext, +) +from pip._internal.utils.models import KeyBasedCompareMixin +from pip._internal.utils.urls import path_to_url, url_to_path + +if TYPE_CHECKING: + from pip._internal.index.collector import HTMLPage + +logger = logging.getLogger(__name__) + + +_SUPPORTED_HASHES = ("sha1", "sha224", "sha384", "sha256", "sha512", "md5") + + +class Link(KeyBasedCompareMixin): + """Represents a parsed link from a Package Index's simple URL""" + + __slots__ = [ + "_parsed_url", + "_url", + "comes_from", + "requires_python", + "yanked_reason", + "cache_link_parsing", + ] + + def __init__( + self, + url: str, + comes_from: Optional[Union[str, "HTMLPage"]] = None, + requires_python: Optional[str] = None, + yanked_reason: Optional[str] = None, + cache_link_parsing: bool = True, + ) -> None: + """ + :param url: url of the resource pointed to (href of the link) + :param comes_from: instance of HTMLPage where the link was found, + or string. + :param requires_python: String containing the `Requires-Python` + metadata field, specified in PEP 345. This may be specified by + a data-requires-python attribute in the HTML link tag, as + described in PEP 503. + :param yanked_reason: the reason the file has been yanked, if the + file has been yanked, or None if the file hasn't been yanked. + This is the value of the "data-yanked" attribute, if present, in + a simple repository HTML link. If the file has been yanked but + no reason was provided, this should be the empty string. See + PEP 592 for more information and the specification. + :param cache_link_parsing: A flag that is used elsewhere to determine + whether resources retrieved from this link + should be cached. PyPI index urls should + generally have this set to False, for + example. + """ + + # url can be a UNC windows share + if url.startswith("\\\\"): + url = path_to_url(url) + + self._parsed_url = urllib.parse.urlsplit(url) + # Store the url as a private attribute to prevent accidentally + # trying to set a new value. + self._url = url + + self.comes_from = comes_from + self.requires_python = requires_python if requires_python else None + self.yanked_reason = yanked_reason + + super().__init__(key=url, defining_class=Link) + + self.cache_link_parsing = cache_link_parsing + + def __str__(self) -> str: + if self.requires_python: + rp = f" (requires-python:{self.requires_python})" + else: + rp = "" + if self.comes_from: + return "{} (from {}){}".format( + redact_auth_from_url(self._url), self.comes_from, rp + ) + else: + return redact_auth_from_url(str(self._url)) + + def __repr__(self) -> str: + return f"" + + @property + def url(self) -> str: + return self._url + + @property + def filename(self) -> str: + path = self.path.rstrip("/") + name = posixpath.basename(path) + if not name: + # Make sure we don't leak auth information if the netloc + # includes a username and password. + netloc, user_pass = split_auth_from_netloc(self.netloc) + return netloc + + name = urllib.parse.unquote(name) + assert name, f"URL {self._url!r} produced no filename" + return name + + @property + def file_path(self) -> str: + return url_to_path(self.url) + + @property + def scheme(self) -> str: + return self._parsed_url.scheme + + @property + def netloc(self) -> str: + """ + This can contain auth information. + """ + return self._parsed_url.netloc + + @property + def path(self) -> str: + return urllib.parse.unquote(self._parsed_url.path) + + def splitext(self) -> Tuple[str, str]: + return splitext(posixpath.basename(self.path.rstrip("/"))) + + @property + def ext(self) -> str: + return self.splitext()[1] + + @property + def url_without_fragment(self) -> str: + scheme, netloc, path, query, fragment = self._parsed_url + return urllib.parse.urlunsplit((scheme, netloc, path, query, "")) + + _egg_fragment_re = re.compile(r"[#&]egg=([^&]*)") + + @property + def egg_fragment(self) -> Optional[str]: + match = self._egg_fragment_re.search(self._url) + if not match: + return None + return match.group(1) + + _subdirectory_fragment_re = re.compile(r"[#&]subdirectory=([^&]*)") + + @property + def subdirectory_fragment(self) -> Optional[str]: + match = self._subdirectory_fragment_re.search(self._url) + if not match: + return None + return match.group(1) + + _hash_re = re.compile( + r"({choices})=([a-f0-9]+)".format(choices="|".join(_SUPPORTED_HASHES)) + ) + + @property + def hash(self) -> Optional[str]: + match = self._hash_re.search(self._url) + if match: + return match.group(2) + return None + + @property + def hash_name(self) -> Optional[str]: + match = self._hash_re.search(self._url) + if match: + return match.group(1) + return None + + @property + def show_url(self) -> str: + return posixpath.basename(self._url.split("#", 1)[0].split("?", 1)[0]) + + @property + def is_file(self) -> bool: + return self.scheme == "file" + + def is_existing_dir(self) -> bool: + return self.is_file and os.path.isdir(self.file_path) + + @property + def is_wheel(self) -> bool: + return self.ext == WHEEL_EXTENSION + + @property + def is_vcs(self) -> bool: + from pip._internal.vcs import vcs + + return self.scheme in vcs.all_schemes + + @property + def is_yanked(self) -> bool: + return self.yanked_reason is not None + + @property + def has_hash(self) -> bool: + return self.hash_name is not None + + def is_hash_allowed(self, hashes: Optional[Hashes]) -> bool: + """ + Return True if the link has a hash and it is allowed. + """ + if hashes is None or not self.has_hash: + return False + # Assert non-None so mypy knows self.hash_name and self.hash are str. + assert self.hash_name is not None + assert self.hash is not None + + return hashes.is_hash_allowed(self.hash_name, hex_digest=self.hash) + + +class _CleanResult(NamedTuple): + """Convert link for equivalency check. + + This is used in the resolver to check whether two URL-specified requirements + likely point to the same distribution and can be considered equivalent. This + equivalency logic avoids comparing URLs literally, which can be too strict + (e.g. "a=1&b=2" vs "b=2&a=1") and produce conflicts unexpecting to users. + + Currently this does three things: + + 1. Drop the basic auth part. This is technically wrong since a server can + serve different content based on auth, but if it does that, it is even + impossible to guarantee two URLs without auth are equivalent, since + the user can input different auth information when prompted. So the + practical solution is to assume the auth doesn't affect the response. + 2. Parse the query to avoid the ordering issue. Note that ordering under the + same key in the query are NOT cleaned; i.e. "a=1&a=2" and "a=2&a=1" are + still considered different. + 3. Explicitly drop most of the fragment part, except ``subdirectory=`` and + hash values, since it should have no impact the downloaded content. Note + that this drops the "egg=" part historically used to denote the requested + project (and extras), which is wrong in the strictest sense, but too many + people are supplying it inconsistently to cause superfluous resolution + conflicts, so we choose to also ignore them. + """ + + parsed: urllib.parse.SplitResult + query: Dict[str, List[str]] + subdirectory: str + hashes: Dict[str, str] + + +def _clean_link(link: Link) -> _CleanResult: + parsed = link._parsed_url + netloc = parsed.netloc.rsplit("@", 1)[-1] + # According to RFC 8089, an empty host in file: means localhost. + if parsed.scheme == "file" and not netloc: + netloc = "localhost" + fragment = urllib.parse.parse_qs(parsed.fragment) + if "egg" in fragment: + logger.debug("Ignoring egg= fragment in %s", link) + try: + # If there are multiple subdirectory values, use the first one. + # This matches the behavior of Link.subdirectory_fragment. + subdirectory = fragment["subdirectory"][0] + except (IndexError, KeyError): + subdirectory = "" + # If there are multiple hash values under the same algorithm, use the + # first one. This matches the behavior of Link.hash_value. + hashes = {k: fragment[k][0] for k in _SUPPORTED_HASHES if k in fragment} + return _CleanResult( + parsed=parsed._replace(netloc=netloc, query="", fragment=""), + query=urllib.parse.parse_qs(parsed.query), + subdirectory=subdirectory, + hashes=hashes, + ) + + +@functools.lru_cache(maxsize=None) +def links_equivalent(link1: Link, link2: Link) -> bool: + return _clean_link(link1) == _clean_link(link2) diff --git a/venv/Lib/site-packages/pip/_internal/models/scheme.py b/venv/Lib/site-packages/pip/_internal/models/scheme.py new file mode 100644 index 0000000..f51190a --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/models/scheme.py @@ -0,0 +1,31 @@ +""" +For types associated with installation schemes. + +For a general overview of available schemes and their context, see +https://docs.python.org/3/install/index.html#alternate-installation. +""" + + +SCHEME_KEYS = ["platlib", "purelib", "headers", "scripts", "data"] + + +class Scheme: + """A Scheme holds paths which are used as the base directories for + artifacts associated with a Python package. + """ + + __slots__ = SCHEME_KEYS + + def __init__( + self, + platlib: str, + purelib: str, + headers: str, + scripts: str, + data: str, + ) -> None: + self.platlib = platlib + self.purelib = purelib + self.headers = headers + self.scripts = scripts + self.data = data diff --git a/venv/Lib/site-packages/pip/_internal/models/search_scope.py b/venv/Lib/site-packages/pip/_internal/models/search_scope.py new file mode 100644 index 0000000..e4e54c2 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/models/search_scope.py @@ -0,0 +1,129 @@ +import itertools +import logging +import os +import posixpath +import urllib.parse +from typing import List + +from pip._vendor.packaging.utils import canonicalize_name + +from pip._internal.models.index import PyPI +from pip._internal.utils.compat import has_tls +from pip._internal.utils.misc import normalize_path, redact_auth_from_url + +logger = logging.getLogger(__name__) + + +class SearchScope: + + """ + Encapsulates the locations that pip is configured to search. + """ + + __slots__ = ["find_links", "index_urls"] + + @classmethod + def create( + cls, + find_links: List[str], + index_urls: List[str], + ) -> "SearchScope": + """ + Create a SearchScope object after normalizing the `find_links`. + """ + # Build find_links. If an argument starts with ~, it may be + # a local file relative to a home directory. So try normalizing + # it and if it exists, use the normalized version. + # This is deliberately conservative - it might be fine just to + # blindly normalize anything starting with a ~... + built_find_links: List[str] = [] + for link in find_links: + if link.startswith("~"): + new_link = normalize_path(link) + if os.path.exists(new_link): + link = new_link + built_find_links.append(link) + + # If we don't have TLS enabled, then WARN if anyplace we're looking + # relies on TLS. + if not has_tls(): + for link in itertools.chain(index_urls, built_find_links): + parsed = urllib.parse.urlparse(link) + if parsed.scheme == "https": + logger.warning( + "pip is configured with locations that require " + "TLS/SSL, however the ssl module in Python is not " + "available." + ) + break + + return cls( + find_links=built_find_links, + index_urls=index_urls, + ) + + def __init__( + self, + find_links: List[str], + index_urls: List[str], + ) -> None: + self.find_links = find_links + self.index_urls = index_urls + + def get_formatted_locations(self) -> str: + lines = [] + redacted_index_urls = [] + if self.index_urls and self.index_urls != [PyPI.simple_url]: + for url in self.index_urls: + + redacted_index_url = redact_auth_from_url(url) + + # Parse the URL + purl = urllib.parse.urlsplit(redacted_index_url) + + # URL is generally invalid if scheme and netloc is missing + # there are issues with Python and URL parsing, so this test + # is a bit crude. See bpo-20271, bpo-23505. Python doesn't + # always parse invalid URLs correctly - it should raise + # exceptions for malformed URLs + if not purl.scheme and not purl.netloc: + logger.warning( + 'The index url "%s" seems invalid, please provide a scheme.', + redacted_index_url, + ) + + redacted_index_urls.append(redacted_index_url) + + lines.append( + "Looking in indexes: {}".format(", ".join(redacted_index_urls)) + ) + + if self.find_links: + lines.append( + "Looking in links: {}".format( + ", ".join(redact_auth_from_url(url) for url in self.find_links) + ) + ) + return "\n".join(lines) + + def get_index_urls_locations(self, project_name: str) -> List[str]: + """Returns the locations found via self.index_urls + + Checks the url_name on the main (first in the list) index and + use this url_name to produce all locations + """ + + def mkurl_pypi_url(url: str) -> str: + loc = posixpath.join( + url, urllib.parse.quote(canonicalize_name(project_name)) + ) + # For maximum compatibility with easy_install, ensure the path + # ends in a trailing slash. Although this isn't in the spec + # (and PyPI can handle it without the slash) some other index + # implementations might break if they relied on easy_install's + # behavior. + if not loc.endswith("/"): + loc = loc + "/" + return loc + + return [mkurl_pypi_url(url) for url in self.index_urls] diff --git a/venv/Lib/site-packages/pip/_internal/models/selection_prefs.py b/venv/Lib/site-packages/pip/_internal/models/selection_prefs.py new file mode 100644 index 0000000..977bc4c --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/models/selection_prefs.py @@ -0,0 +1,51 @@ +from typing import Optional + +from pip._internal.models.format_control import FormatControl + + +class SelectionPreferences: + """ + Encapsulates the candidate selection preferences for downloading + and installing files. + """ + + __slots__ = [ + "allow_yanked", + "allow_all_prereleases", + "format_control", + "prefer_binary", + "ignore_requires_python", + ] + + # Don't include an allow_yanked default value to make sure each call + # site considers whether yanked releases are allowed. This also causes + # that decision to be made explicit in the calling code, which helps + # people when reading the code. + def __init__( + self, + allow_yanked: bool, + allow_all_prereleases: bool = False, + format_control: Optional[FormatControl] = None, + prefer_binary: bool = False, + ignore_requires_python: Optional[bool] = None, + ) -> None: + """Create a SelectionPreferences object. + + :param allow_yanked: Whether files marked as yanked (in the sense + of PEP 592) are permitted to be candidates for install. + :param format_control: A FormatControl object or None. Used to control + the selection of source packages / binary packages when consulting + the index and links. + :param prefer_binary: Whether to prefer an old, but valid, binary + dist over a new source dist. + :param ignore_requires_python: Whether to ignore incompatible + "Requires-Python" values in links. Defaults to False. + """ + if ignore_requires_python is None: + ignore_requires_python = False + + self.allow_yanked = allow_yanked + self.allow_all_prereleases = allow_all_prereleases + self.format_control = format_control + self.prefer_binary = prefer_binary + self.ignore_requires_python = ignore_requires_python diff --git a/venv/Lib/site-packages/pip/_internal/models/target_python.py b/venv/Lib/site-packages/pip/_internal/models/target_python.py new file mode 100644 index 0000000..744bd7e --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/models/target_python.py @@ -0,0 +1,110 @@ +import sys +from typing import List, Optional, Tuple + +from pip._vendor.packaging.tags import Tag + +from pip._internal.utils.compatibility_tags import get_supported, version_info_to_nodot +from pip._internal.utils.misc import normalize_version_info + + +class TargetPython: + + """ + Encapsulates the properties of a Python interpreter one is targeting + for a package install, download, etc. + """ + + __slots__ = [ + "_given_py_version_info", + "abis", + "implementation", + "platforms", + "py_version", + "py_version_info", + "_valid_tags", + ] + + def __init__( + self, + platforms: Optional[List[str]] = None, + py_version_info: Optional[Tuple[int, ...]] = None, + abis: Optional[List[str]] = None, + implementation: Optional[str] = None, + ) -> None: + """ + :param platforms: A list of strings or None. If None, searches for + packages that are supported by the current system. Otherwise, will + find packages that can be built on the platforms passed in. These + packages will only be downloaded for distribution: they will + not be built locally. + :param py_version_info: An optional tuple of ints representing the + Python version information to use (e.g. `sys.version_info[:3]`). + This can have length 1, 2, or 3 when provided. + :param abis: A list of strings or None. This is passed to + compatibility_tags.py's get_supported() function as is. + :param implementation: A string or None. This is passed to + compatibility_tags.py's get_supported() function as is. + """ + # Store the given py_version_info for when we call get_supported(). + self._given_py_version_info = py_version_info + + if py_version_info is None: + py_version_info = sys.version_info[:3] + else: + py_version_info = normalize_version_info(py_version_info) + + py_version = ".".join(map(str, py_version_info[:2])) + + self.abis = abis + self.implementation = implementation + self.platforms = platforms + self.py_version = py_version + self.py_version_info = py_version_info + + # This is used to cache the return value of get_tags(). + self._valid_tags: Optional[List[Tag]] = None + + def format_given(self) -> str: + """ + Format the given, non-None attributes for display. + """ + display_version = None + if self._given_py_version_info is not None: + display_version = ".".join( + str(part) for part in self._given_py_version_info + ) + + key_values = [ + ("platforms", self.platforms), + ("version_info", display_version), + ("abis", self.abis), + ("implementation", self.implementation), + ] + return " ".join( + f"{key}={value!r}" for key, value in key_values if value is not None + ) + + def get_tags(self) -> List[Tag]: + """ + Return the supported PEP 425 tags to check wheel candidates against. + + The tags are returned in order of preference (most preferred first). + """ + if self._valid_tags is None: + # Pass versions=None if no py_version_info was given since + # versions=None uses special default logic. + py_version_info = self._given_py_version_info + if py_version_info is None: + version = None + else: + version = version_info_to_nodot(py_version_info) + + tags = get_supported( + version=version, + platforms=self.platforms, + abis=self.abis, + impl=self.implementation, + ) + self._valid_tags = tags + + return self._valid_tags diff --git a/venv/Lib/site-packages/pip/_internal/models/wheel.py b/venv/Lib/site-packages/pip/_internal/models/wheel.py new file mode 100644 index 0000000..e091612 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/models/wheel.py @@ -0,0 +1,89 @@ +"""Represents a wheel file and provides access to the various parts of the +name that have meaning. +""" +import re +from typing import Dict, Iterable, List + +from pip._vendor.packaging.tags import Tag + +from pip._internal.exceptions import InvalidWheelFilename + + +class Wheel: + """A wheel file""" + + wheel_file_re = re.compile( + r"""^(?P(?P.+?)-(?P.*?)) + ((-(?P\d[^-]*?))?-(?P.+?)-(?P.+?)-(?P.+?) + \.whl|\.dist-info)$""", + re.VERBOSE, + ) + + def __init__(self, filename: str) -> None: + """ + :raises InvalidWheelFilename: when the filename is invalid for a wheel + """ + wheel_info = self.wheel_file_re.match(filename) + if not wheel_info: + raise InvalidWheelFilename(f"{filename} is not a valid wheel filename.") + self.filename = filename + self.name = wheel_info.group("name").replace("_", "-") + # we'll assume "_" means "-" due to wheel naming scheme + # (https://github.com/pypa/pip/issues/1150) + self.version = wheel_info.group("ver").replace("_", "-") + self.build_tag = wheel_info.group("build") + self.pyversions = wheel_info.group("pyver").split(".") + self.abis = wheel_info.group("abi").split(".") + self.plats = wheel_info.group("plat").split(".") + + # All the tag combinations from this file + self.file_tags = { + Tag(x, y, z) for x in self.pyversions for y in self.abis for z in self.plats + } + + def get_formatted_file_tags(self) -> List[str]: + """Return the wheel's tags as a sorted list of strings.""" + return sorted(str(tag) for tag in self.file_tags) + + def support_index_min(self, tags: List[Tag]) -> int: + """Return the lowest index that one of the wheel's file_tag combinations + achieves in the given list of supported tags. + + For example, if there are 8 supported tags and one of the file tags + is first in the list, then return 0. + + :param tags: the PEP 425 tags to check the wheel against, in order + with most preferred first. + + :raises ValueError: If none of the wheel's file tags match one of + the supported tags. + """ + return min(tags.index(tag) for tag in self.file_tags if tag in tags) + + def find_most_preferred_tag( + self, tags: List[Tag], tag_to_priority: Dict[Tag, int] + ) -> int: + """Return the priority of the most preferred tag that one of the wheel's file + tag combinations achieves in the given list of supported tags using the given + tag_to_priority mapping, where lower priorities are more-preferred. + + This is used in place of support_index_min in some cases in order to avoid + an expensive linear scan of a large list of tags. + + :param tags: the PEP 425 tags to check the wheel against. + :param tag_to_priority: a mapping from tag to priority of that tag, where + lower is more preferred. + + :raises ValueError: If none of the wheel's file tags match one of + the supported tags. + """ + return min( + tag_to_priority[tag] for tag in self.file_tags if tag in tag_to_priority + ) + + def supported(self, tags: Iterable[Tag]) -> bool: + """Return whether the wheel is compatible with one of the given tags. + + :param tags: the PEP 425 tags to check the wheel against. + """ + return not self.file_tags.isdisjoint(tags) diff --git a/venv/Lib/site-packages/pip/_internal/network/__init__.py b/venv/Lib/site-packages/pip/_internal/network/__init__.py new file mode 100644 index 0000000..b51bde9 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/network/__init__.py @@ -0,0 +1,2 @@ +"""Contains purely network-related utilities. +""" diff --git a/venv/Lib/site-packages/pip/_internal/network/__pycache__/__init__.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/network/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b04da04b08350ae9cc373968d2f9e14efdbd03e4 GIT binary patch literal 241 zcmYjMv5EpQ5Y5`02!4ZG339B(6(VwoqUB+uHWC=d&4AIEgd~gTKlma3lC7U`-Br#W z7Cv}ycr%Y-2HWkHU|c)h?HAWaZQhZwnJ{CMMTw12*;4cxm(Q8A3AK&6uL7BKZYiBy zI23F!k;<#2jZT_kzqROP_YVN&N`RXP4c_!Ge=r-#b)*m_T8mLmy`N)3`Qu77az#fk zz4k?AJ(dSj#c4-miotNNV;L{?OoFzFg5~(@014dE383%K_vZJ}smjo}e&d%Zo`GUU A<^TWy literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/network/__pycache__/auth.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/network/__pycache__/auth.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6841778899ca354ff26e8f5f7ff1c6a37e974f2c GIT binary patch literal 7473 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 ak!8PJshOVHz;#lVoigsz9J}@6OaBMm_qt91 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/network/__pycache__/cache.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/network/__pycache__/cache.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e2e627d3084ffd5d977218c3ae85c62049a486b0 GIT binary patch literal 2913 zcmaJ@OLH4V5T4nGB(Eh~PMkN8g@S;9r~-#nilR~^hLEHvClv=Mwp47bc1HF(`^wD7 zj#bJfGL;kL59DCymcKMtPWcO*=pM;zV|t$FnHPJjJ%&qR%eN8tJM;-&6djgY^w zGy6Eu`3_$B3IrnoVU$@Z4JiEEsg>D*O>xXgoy-l~tP)gA-%YDoEvT7xC7sK>z%%V? zI-k{px@p(aMz#CdIjY$;fxgxC2A=DoDoJge_I!AWj&ms#fsYrLdvfi3Pj zBN{CKNLZ6C?Gm=cYa=^2#jG{bIx)C#`{Bd;ejLRc+)uJH>_UdvCxAvf840 zAue*opQtR#qjfG?mag4VTtuo6x^}Nb?I;Dkxto#XD`*Qlw~}<)sXgGbEONe>M#xv-m30t`3=QNX z8=SLOwbv6x78>tvf$i!#2j7%vQ85qNuZdWMzkfO_-*kSKT*yw8=aKB(D9i676?J|p z;wbGr5yp61IXHk8x!70d|=|`4Kb*9;3eyN`58z2?w0qd5=PmlHW*fT>*!| zS!=L$r{`~T2xb1M@}oHBQu+#_YBqwcd@}8C_NDUWqog!*Nxtq!IrB?V;2O_|NASme zE|v5n=_kFZ+IA$-IM1VQ%30f}B0sA4)_xG85C+Z}fzIkPvR{@EM#JzA&YB(&cGqJkRm$Sn|@Kq`^IVl=S1!z^aMw4Re5BouRZ>w(K17_C4mR9OvD zp#uFXuR$uz!I;P9VQdZ(z~MC*_h8&&^_LE7u!UVWm^T(tbCEScv;G{&6*MqSbYm^* z@hPDP+s5@9K9bk(0_oWV=IxCn-tZIYOVIaK;rAu?`4(c20l;{uNB|9e;5UyUfp+{X z+A-$xLit@j30(pR`-SkgMWPVx1F$VUH(fbqjvGay0gBfj%)*XO{LDRc@NL$U`EG_KPTd2yc-0|6abFD^Z`hxVSm z57okgGsuD82u_`&y*2U`k+-jyDuQ(c=MQ!BCd~F`XD2+-mgu$|fy^@5s-2?bxpoAP z7>pZ~FwVjUp=s|pJU00IHB6239#~L=ydNwb1qF1#7MjuSR+RSPc;HV;NEbN<203u> zU<9YYJcG^@7)K#6zaucngFScX>_ZAbzcPda@x}S4?$F(<4y}C{d&~K|v(Bs9(A}Ja zRn|K+)vPAM^qQ`=yhDft-WbG16g~)Dg&Z^d#?q%<%x^Bx1w*e^Wd_7AaP&(QK8h9! zlT*{g(zfL48jPFMj~GCkmPbFcj)Mw%@oc5Q3V}N?jJghuDR7nn?mPmwXa5I0SB^U^ zE`y0#W*Cq0(9Vi2-m+)B@s8x_V=uJ}!unv@8n#$fp}!tFg0i#79@~%yE_UPg$b%{IK9Oc+!vBlHzp-4=4pCR z#th`=P{kB9JiIWb2KO3u+-0{}Tdth<1kSWh3#?CL47|zZDNVWpBcLm4r-VaSUz&MNv;bY9!lJj1m+gE+xt!Kwn&1 z5d(T*b=kDLPTTQ9T6)vzblG)(L6>*B>r7|z7d+|XI~Sy0b{|u4aB%O%eV%i^?;J23 zAFpV*zB>Er%I}V8+Fz-%|FTiJf;(H%H7(M7Ez%<+)_q+)4c|~t(>K-A@+~~g*zP#K z(<%9-j_bQRjj`f#r{Y&SWB!<`+i|rs?vJao6W2Nu{)8%*;>pgGKc&iUJl&b`XH>Zy z&vuUZM^w2IAMG6TkE!xle7rN~&vj1tCpstnld7#6pX!|UPj}AvXF6y7v%1ENZI8XQ zqxCvE1HU?(f%#8osVYFZ#FuD`fF52 z%h4xhbSyfKmU=NVnnTNp=pO_!m)oDLRMR zIn*vi#-dh#xnIAQZX|IUMqaBOv&`FQi#4yy(^by0%xfo6yBUgML`s(fZrR(!c!POgg=06D*Z~E7z`zg!1X_B$JF3+qo z5k$i^gV90(XGz33yU*k-XHnP`LD&;(#S%RpOE>GrZNa_}IHyH3NQX1g<4F_#xqDHW{Q4^H>@q}u zQfRrh4zHclw)A`2qGoBr5T>wN=H>-mqu)>9-;3I1CF{m~zt&6>!4h#PX345ptJ~6S zCqkCiSO`63vT`?!drT=tx}UJkqEuem>=uo6ozGzDry4(j$Ftz-_m}Tv7`PlJNti9a z-|b!tMYwz`ZHDpk66QlHlODU|D$+MTpw7*bYuyzgADFqmt_x$`yl?PRC|d(7aqzSUmT+{Q?BC-Zfa$z{?v8tWQ&Ftrq zjrQr>j2!g(t*Tk{R!roYnA|c3rQFGWpO+RjF_jzWSNh5rxVf8`wsauRo$r^v9C)vN zIjHw1?quy`)l*&^dFQi!Z3IecKA(NK)V}frS~GkX8VUrAEG^P*eOjqgIxtC`HaV$E z&Jd8{=qV3Z8KBk)+X-BEE!_yniDw}KLV4N~aP4rl12^MSG}0*`z$a1RW2z-iS63OA zRy%2>atb!S-f9sjAF^BQA&X^+I$)R5x;g*hZ9YLG$ymGuQ7RTStn+cm1XYdD5$ zSo);l>NTTk)O1I8aa+aHu#5`cTIk8Yjgi2$OWI4q4l5k-FtEunl_OSB5CHYIk!w3- zP`&?g#ly82CT#)Rcw&ut=SH)g^BxjlJ)$cw^uTQj-PhW{N{0Sv;uX+ts7b&_Mw&^h z8;Ugvqi1SM05$Q+VJ*yM!zF_uX#}HHZ=iQ(Kxh_!6B5(TjQT`-OUucKwZdKue>iY> zHIhc-BBSme{vs+u+t%sm%f`R}7R_x$;~jlq~Zn2@0)C6RusT z$mZY0>G)d^(k`&(pljI4Uab6LnipvGHfG3Ff@9b8if);%&fi5_-Q0%?#de4F?4Xx& zvd1WZ(X;`aj9g7=7`o;jG;HPuSjG?*p2&;lG}3*xAna{t*xQV(9b;&d1#pn{HqB&Z zk1%HmeMMBsnBs|4nT|RW>F><}gC(h;l;a_0j|xlmM{as)pPPP7VC+|is=lOX zP^(u8vmC`c{yh?;V?GTb%bj+IQ8xtq)gJPK0I{1TlpgTcsn;7Mz5`LW_t`{YjGRE4 z=zkb(CtnchMzHw|gE9(mn&p5~ESR0-EN)jtKYH>H@Sf6>tjJUfdVJ0iEcDt9dks{` z5w=z8yJJKq%uP;Vc!f4L?GyP@$0}SM(x23wlNk`Jj1ZQCf zCngn0Tjex`=EkXW4Fd6*{7>ynRz%1txPz<hk81<)dZk(Bz zsEPZ)MaR2>J9`I$X~^p}-(V)AJl;SSi-RGHwUHfL$eb-^wczEEjW3_!9X3WizylN*rHjZNQUrK@yA*?WQ^`N0GD;;ROudno8uQQ2D57EXRer&6C!sYL0x)R|(dBFmuQ&I#Fa#Az!2N?WBpdyT|khgk@IhKP#&0 zA9lWkQXLC2t{*kK{xKFf@Nw~934wotA^a8z3h4U| ztIkRK_zmtos2@MH=svtln?hg4l|LxLr{zZ%DVYFI>dF2Fk?VliUk2tb=mEWfwF~;s z0eV}3-X4Pft$m{7sG64M%aexB&BJ{(T zNZcVo_~v&Z>eT{wYt*3htPn`x9Wz!!w^cgubbW-qY+5Nj1qrsWX{MuIHPTO<^$3@ZH(*jh!uU*pawRPSP|?CMAV z!RcMSAxi;baWe?`+o4ulz=UJT6LkgR=)nm_*h9 zBd|CtzUe40m1kAA(Vqd0X54O!KG*_;$V`3t$>Rrmu`ilT{Z*6|%zNVC>tc}x{%vAk z6d$p3FYG|@Q5urPW_Ncn{7a(Iq(6d+PuJ52XBhPuC0&Zr{>>~s(Z-Q?vmy0Wd-z1E zPosnXM~ctoDbnLKDX5H0=$86yF6>RQg&!e7nW3_`v{yC-%Ze!SCbg=h^#dvq2P&FW zw%q5DyW}d}cMG0=j}p6#zEmuH-xj}FV-lI?-fvc)H7e$;s~A{!zNucAEKS#@k4%?p GXa5BcMpcvm literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/network/__pycache__/lazy_wheel.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/network/__pycache__/lazy_wheel.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5006b163217f97f9deb008ac0aa648d2f75f751f GIT binary patch literal 8373 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 Yi)*AEMou3ZGP1dJ&dndqXY!f<27A#k;{X5v literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/network/__pycache__/utils.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/network/__pycache__/utils.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..06277c49b4aa7ba9d0880345a3f1dae5b1e1d794 GIT binary patch literal 1419 zcmZ8h&5s*36t_Je`Pgg{MRdDeR5~Z5NKI5gpzW$cU6R07R6*L0mPUcm?AY6NlXzxr zXO~3D1$tcxacz;xkqdtU2mTCmw`au0QvBWtuxc_3~d3 z8P$n#+dS4L|3EVt=|sX#t@TCsu+u#ZTYE>{&%=WUy^hK6GnFPnu{t&zU8XM*IcOz9 zuvqg%bfiq=w6Yt=EY*#Uh!e`iQfonxSV{lkbT9WLmY~uN+E#!gKN%o$a|uyOWPGvd>cISltuQ-9f^) zdviivm^~LcXn^I{)Egi<6D~$#%kIBG)SnTMIav8G(2w36i}$H_#pef_2cKUupUtID z;r~7}EPvIx8J;0pyd>XZilEMGU4y3HSf4bur$w%k#`gAycN_2V?;&yiH;8E^Xbm~k zDafk06HJT2Ng{)>9PR}COOja}FnP}8$^tOR+ahLoQj|HZD#X8#X@Le#TX-rdHPv zxd6fmFc%9l^~ahIRWqHKs*Jc|A=DsTobV>ZRPTU5*u^D};3_WRw}?-+$i{2ewUW3l zme;`oj$eYw6ywve7=(&XnY67KLml6Y70+VWQTrgK0bmMDnPG}4xg>4$RdG&c4NOIs`)8ETV7xWxIl@7?$%x7$mqiON&~nfQ{L5D^5d~)3ml=J zBD&05ZbCN3%l?*OwGbP2x3Z#4xCnOFW^XmfCB(<%I{CA>Rl+5w1Z5^z-U3a%VthSG zp_!#EptP0iy$t|1L&%LLvbjpGIRbhOm2|C{z23}bX12n)$-c3d16&p= H`2YR~)QNTh literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/network/__pycache__/xmlrpc.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/network/__pycache__/xmlrpc.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..712712d2c639f95666f38affe55c64149d4cf979 GIT binary patch literal 2040 zcmZuyTW=gS6t?F+likhsexqfj3dB}qTL}qO2q94Dg;Ju3E-D=@a%aa*GTXV;_BP3C z(uby^PyGjdNM4XC@r(S*6Mvyx%JIx5El}_JjE{ZnIp;gy@kH%*fS^5p|HJWX2ch4z z@^-U8`4YPL83aWkqL>;f4src7LbHBap$$(nbuu?}GcWY8wzE<{3&Nlt+v!5q3S0Hq zN!wW`>|n%PPQlJit!yz|%(`J0=J4JTc61+y$8I3%QU58TKC>ssCnt8z@FX?vpnfpB zxRs^6jMHR181g6=Wx-`H$;y;vESHf?iahuo97ZdBL$!zZRtl6tg~`o=KUgmEoW*+2HO>nTE5T|~-eE$(6lh%@C4!N)f)fE}PX(OmlbeN*!|jr( zHu)~%Vk1h^Xq>WGzxD0r&J}SB1`GjkC^RSr;9AULHgl*+trylaw1%loou}>4rETiM zn#UaGQ|}A_@WQ46U3hAT!82r`Z~;K*sH5QJk2Ma57|gz3<;A0fvR>4?{|=1q{|BVr zqa@O%Z{ocl^q>{v2_Q14$JbZ-mhzLFvMn;@sd7bwjA~5*6>rKtJVfL^(|XpcZEjr%XsPF6g#$A2B{I!2LE@$2tiIO+%pjGIa4P2#G2z@vb2{ zx6l(@p@~u9%Aio`6sajth3q#I2mltXxgs=hluVy~^8# zv{n|R(67*5P6|3*OVSAAwLN+lu)at=8hKo^$6c=z$_W27%lTJ__VA zfL;#B`uC^fXsrXk09!BzD}Pz`?Cd+}H$SkCuj_wH7h)b|3<@zIBrE7N)#DZ+52sN& zUvUYcMNA042o7+~K4p!IBCT1k?D4i_g6ms>U)F2wdELbU^t$%??`|9YVHoqcu=A?6?4RPFfSqzR;*eyxr|LUn&}2~ORki1}2wxB&Q|L6R za^!XiJGcQhwTtRBl=9%Plm`GhEA^K`H2FRM@8x-=59T*d6a2Y%+e~GWiiSkGw(H7P zJ`nSEO%#4bPxiI5PUEHW53l(;&bOd?LjmveCM#cH*eNupEYpMRd$?=pYo=vbFbd3n E0Qv+kjsO4v literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/network/auth.py b/venv/Lib/site-packages/pip/_internal/network/auth.py new file mode 100644 index 0000000..ca42798 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/network/auth.py @@ -0,0 +1,323 @@ +"""Network Authentication Helpers + +Contains interface (MultiDomainBasicAuth) and associated glue code for +providing credentials in the context of network requests. +""" + +import urllib.parse +from typing import Any, Dict, List, Optional, Tuple + +from pip._vendor.requests.auth import AuthBase, HTTPBasicAuth +from pip._vendor.requests.models import Request, Response +from pip._vendor.requests.utils import get_netrc_auth + +from pip._internal.utils.logging import getLogger +from pip._internal.utils.misc import ( + ask, + ask_input, + ask_password, + remove_auth_from_url, + split_auth_netloc_from_url, +) +from pip._internal.vcs.versioncontrol import AuthInfo + +logger = getLogger(__name__) + +Credentials = Tuple[str, str, str] + +try: + import keyring +except ImportError: + keyring = None # type: ignore[assignment] +except Exception as exc: + logger.warning( + "Keyring is skipped due to an exception: %s", + str(exc), + ) + keyring = None # type: ignore[assignment] + + +def get_keyring_auth(url: Optional[str], username: Optional[str]) -> Optional[AuthInfo]: + """Return the tuple auth for a given url from keyring.""" + global keyring + if not url or not keyring: + return None + + try: + try: + get_credential = keyring.get_credential + except AttributeError: + pass + else: + logger.debug("Getting credentials from keyring for %s", url) + cred = get_credential(url, username) + if cred is not None: + return cred.username, cred.password + return None + + if username: + logger.debug("Getting password from keyring for %s", url) + password = keyring.get_password(url, username) + if password: + return username, password + + except Exception as exc: + logger.warning( + "Keyring is skipped due to an exception: %s", + str(exc), + ) + keyring = None # type: ignore[assignment] + return None + + +class MultiDomainBasicAuth(AuthBase): + def __init__( + self, prompting: bool = True, index_urls: Optional[List[str]] = None + ) -> None: + self.prompting = prompting + self.index_urls = index_urls + self.passwords: Dict[str, AuthInfo] = {} + # When the user is prompted to enter credentials and keyring is + # available, we will offer to save them. If the user accepts, + # this value is set to the credentials they entered. After the + # request authenticates, the caller should call + # ``save_credentials`` to save these. + self._credentials_to_save: Optional[Credentials] = None + + def _get_index_url(self, url: str) -> Optional[str]: + """Return the original index URL matching the requested URL. + + Cached or dynamically generated credentials may work against + the original index URL rather than just the netloc. + + The provided url should have had its username and password + removed already. If the original index url had credentials then + they will be included in the return value. + + Returns None if no matching index was found, or if --no-index + was specified by the user. + """ + if not url or not self.index_urls: + return None + + for u in self.index_urls: + prefix = remove_auth_from_url(u).rstrip("/") + "/" + if url.startswith(prefix): + return u + return None + + def _get_new_credentials( + self, + original_url: str, + allow_netrc: bool = True, + allow_keyring: bool = False, + ) -> AuthInfo: + """Find and return credentials for the specified URL.""" + # Split the credentials and netloc from the url. + url, netloc, url_user_password = split_auth_netloc_from_url( + original_url, + ) + + # Start with the credentials embedded in the url + username, password = url_user_password + if username is not None and password is not None: + logger.debug("Found credentials in url for %s", netloc) + return url_user_password + + # Find a matching index url for this request + index_url = self._get_index_url(url) + if index_url: + # Split the credentials from the url. + index_info = split_auth_netloc_from_url(index_url) + if index_info: + index_url, _, index_url_user_password = index_info + logger.debug("Found index url %s", index_url) + + # If an index URL was found, try its embedded credentials + if index_url and index_url_user_password[0] is not None: + username, password = index_url_user_password + if username is not None and password is not None: + logger.debug("Found credentials in index url for %s", netloc) + return index_url_user_password + + # Get creds from netrc if we still don't have them + if allow_netrc: + netrc_auth = get_netrc_auth(original_url) + if netrc_auth: + logger.debug("Found credentials in netrc for %s", netloc) + return netrc_auth + + # If we don't have a password and keyring is available, use it. + if allow_keyring: + # The index url is more specific than the netloc, so try it first + # fmt: off + kr_auth = ( + get_keyring_auth(index_url, username) or + get_keyring_auth(netloc, username) + ) + # fmt: on + if kr_auth: + logger.debug("Found credentials in keyring for %s", netloc) + return kr_auth + + return username, password + + def _get_url_and_credentials( + self, original_url: str + ) -> Tuple[str, Optional[str], Optional[str]]: + """Return the credentials to use for the provided URL. + + If allowed, netrc and keyring may be used to obtain the + correct credentials. + + Returns (url_without_credentials, username, password). Note + that even if the original URL contains credentials, this + function may return a different username and password. + """ + url, netloc, _ = split_auth_netloc_from_url(original_url) + + # Try to get credentials from original url + username, password = self._get_new_credentials(original_url) + + # If credentials not found, use any stored credentials for this netloc. + # Do this if either the username or the password is missing. + # This accounts for the situation in which the user has specified + # the username in the index url, but the password comes from keyring. + if (username is None or password is None) and netloc in self.passwords: + un, pw = self.passwords[netloc] + # It is possible that the cached credentials are for a different username, + # in which case the cache should be ignored. + if username is None or username == un: + username, password = un, pw + + if username is not None or password is not None: + # Convert the username and password if they're None, so that + # this netloc will show up as "cached" in the conditional above. + # Further, HTTPBasicAuth doesn't accept None, so it makes sense to + # cache the value that is going to be used. + username = username or "" + password = password or "" + + # Store any acquired credentials. + self.passwords[netloc] = (username, password) + + assert ( + # Credentials were found + (username is not None and password is not None) + # Credentials were not found + or (username is None and password is None) + ), f"Could not load credentials from url: {original_url}" + + return url, username, password + + def __call__(self, req: Request) -> Request: + # Get credentials for this request + url, username, password = self._get_url_and_credentials(req.url) + + # Set the url of the request to the url without any credentials + req.url = url + + if username is not None and password is not None: + # Send the basic auth with this request + req = HTTPBasicAuth(username, password)(req) + + # Attach a hook to handle 401 responses + req.register_hook("response", self.handle_401) + + return req + + # Factored out to allow for easy patching in tests + def _prompt_for_password( + self, netloc: str + ) -> Tuple[Optional[str], Optional[str], bool]: + username = ask_input(f"User for {netloc}: ") + if not username: + return None, None, False + auth = get_keyring_auth(netloc, username) + if auth and auth[0] is not None and auth[1] is not None: + return auth[0], auth[1], False + password = ask_password("Password: ") + return username, password, True + + # Factored out to allow for easy patching in tests + def _should_save_password_to_keyring(self) -> bool: + if not keyring: + return False + return ask("Save credentials to keyring [y/N]: ", ["y", "n"]) == "y" + + def handle_401(self, resp: Response, **kwargs: Any) -> Response: + # We only care about 401 responses, anything else we want to just + # pass through the actual response + if resp.status_code != 401: + return resp + + # We are not able to prompt the user so simply return the response + if not self.prompting: + return resp + + parsed = urllib.parse.urlparse(resp.url) + + # Query the keyring for credentials: + username, password = self._get_new_credentials( + resp.url, + allow_netrc=False, + allow_keyring=True, + ) + + # Prompt the user for a new username and password + save = False + if not username and not password: + username, password, save = self._prompt_for_password(parsed.netloc) + + # Store the new username and password to use for future requests + self._credentials_to_save = None + if username is not None and password is not None: + self.passwords[parsed.netloc] = (username, password) + + # Prompt to save the password to keyring + if save and self._should_save_password_to_keyring(): + self._credentials_to_save = (parsed.netloc, username, password) + + # Consume content and release the original connection to allow our new + # request to reuse the same one. + resp.content + resp.raw.release_conn() + + # Add our new username and password to the request + req = HTTPBasicAuth(username or "", password or "")(resp.request) + req.register_hook("response", self.warn_on_401) + + # On successful request, save the credentials that were used to + # keyring. (Note that if the user responded "no" above, this member + # is not set and nothing will be saved.) + if self._credentials_to_save: + req.register_hook("response", self.save_credentials) + + # Send our new request + new_resp = resp.connection.send(req, **kwargs) + new_resp.history.append(resp) + + return new_resp + + def warn_on_401(self, resp: Response, **kwargs: Any) -> None: + """Response callback to warn about incorrect credentials.""" + if resp.status_code == 401: + logger.warning( + "401 Error, Credentials not correct for %s", + resp.request.url, + ) + + def save_credentials(self, resp: Response, **kwargs: Any) -> None: + """Response callback to save credentials on success.""" + assert keyring is not None, "should never reach here without keyring" + if not keyring: + return + + creds = self._credentials_to_save + self._credentials_to_save = None + if creds and resp.status_code < 400: + try: + logger.info("Saving credentials to keyring") + keyring.set_password(*creds) + except Exception: + logger.exception("Failed to save credentials") diff --git a/venv/Lib/site-packages/pip/_internal/network/cache.py b/venv/Lib/site-packages/pip/_internal/network/cache.py new file mode 100644 index 0000000..9dba7ed --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/network/cache.py @@ -0,0 +1,69 @@ +"""HTTP cache implementation. +""" + +import os +from contextlib import contextmanager +from typing import Iterator, Optional + +from pip._vendor.cachecontrol.cache import BaseCache +from pip._vendor.cachecontrol.caches import FileCache +from pip._vendor.requests.models import Response + +from pip._internal.utils.filesystem import adjacent_tmp_file, replace +from pip._internal.utils.misc import ensure_dir + + +def is_from_cache(response: Response) -> bool: + return getattr(response, "from_cache", False) + + +@contextmanager +def suppressed_cache_errors() -> Iterator[None]: + """If we can't access the cache then we can just skip caching and process + requests as if caching wasn't enabled. + """ + try: + yield + except OSError: + pass + + +class SafeFileCache(BaseCache): + """ + A file based cache which is safe to use even when the target directory may + not be accessible or writable. + """ + + def __init__(self, directory: str) -> None: + assert directory is not None, "Cache directory must not be None." + super().__init__() + self.directory = directory + + def _get_cache_path(self, name: str) -> str: + # From cachecontrol.caches.file_cache.FileCache._fn, brought into our + # class for backwards-compatibility and to avoid using a non-public + # method. + hashed = FileCache.encode(name) + parts = list(hashed[:5]) + [hashed] + return os.path.join(self.directory, *parts) + + def get(self, key: str) -> Optional[bytes]: + path = self._get_cache_path(key) + with suppressed_cache_errors(): + with open(path, "rb") as f: + return f.read() + + def set(self, key: str, value: bytes, expires: Optional[int] = None) -> None: + path = self._get_cache_path(key) + with suppressed_cache_errors(): + ensure_dir(os.path.dirname(path)) + + with adjacent_tmp_file(path) as f: + f.write(value) + + replace(f.name, path) + + def delete(self, key: str) -> None: + path = self._get_cache_path(key) + with suppressed_cache_errors(): + os.remove(path) diff --git a/venv/Lib/site-packages/pip/_internal/network/download.py b/venv/Lib/site-packages/pip/_internal/network/download.py new file mode 100644 index 0000000..35bc970 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/network/download.py @@ -0,0 +1,185 @@ +"""Download files with progress indicators. +""" +import cgi +import logging +import mimetypes +import os +from typing import Iterable, Optional, Tuple + +from pip._vendor.requests.models import CONTENT_CHUNK_SIZE, Response + +from pip._internal.cli.progress_bars import get_download_progress_renderer +from pip._internal.exceptions import NetworkConnectionError +from pip._internal.models.index import PyPI +from pip._internal.models.link import Link +from pip._internal.network.cache import is_from_cache +from pip._internal.network.session import PipSession +from pip._internal.network.utils import HEADERS, raise_for_status, response_chunks +from pip._internal.utils.misc import format_size, redact_auth_from_url, splitext + +logger = logging.getLogger(__name__) + + +def _get_http_response_size(resp: Response) -> Optional[int]: + try: + return int(resp.headers["content-length"]) + except (ValueError, KeyError, TypeError): + return None + + +def _prepare_download( + resp: Response, + link: Link, + progress_bar: str, +) -> Iterable[bytes]: + total_length = _get_http_response_size(resp) + + if link.netloc == PyPI.file_storage_domain: + url = link.show_url + else: + url = link.url_without_fragment + + logged_url = redact_auth_from_url(url) + + if total_length: + logged_url = "{} ({})".format(logged_url, format_size(total_length)) + + if is_from_cache(resp): + logger.info("Using cached %s", logged_url) + else: + logger.info("Downloading %s", logged_url) + + if logger.getEffectiveLevel() > logging.INFO: + show_progress = False + elif is_from_cache(resp): + show_progress = False + elif not total_length: + show_progress = True + elif total_length > (40 * 1000): + show_progress = True + else: + show_progress = False + + chunks = response_chunks(resp, CONTENT_CHUNK_SIZE) + + if not show_progress: + return chunks + + renderer = get_download_progress_renderer(bar_type=progress_bar, size=total_length) + return renderer(chunks) + + +def sanitize_content_filename(filename: str) -> str: + """ + Sanitize the "filename" value from a Content-Disposition header. + """ + return os.path.basename(filename) + + +def parse_content_disposition(content_disposition: str, default_filename: str) -> str: + """ + Parse the "filename" value from a Content-Disposition header, and + return the default filename if the result is empty. + """ + _type, params = cgi.parse_header(content_disposition) + filename = params.get("filename") + if filename: + # We need to sanitize the filename to prevent directory traversal + # in case the filename contains ".." path parts. + filename = sanitize_content_filename(filename) + return filename or default_filename + + +def _get_http_response_filename(resp: Response, link: Link) -> str: + """Get an ideal filename from the given HTTP response, falling back to + the link filename if not provided. + """ + filename = link.filename # fallback + # Have a look at the Content-Disposition header for a better guess + content_disposition = resp.headers.get("content-disposition") + if content_disposition: + filename = parse_content_disposition(content_disposition, filename) + ext: Optional[str] = splitext(filename)[1] + if not ext: + ext = mimetypes.guess_extension(resp.headers.get("content-type", "")) + if ext: + filename += ext + if not ext and link.url != resp.url: + ext = os.path.splitext(resp.url)[1] + if ext: + filename += ext + return filename + + +def _http_get_download(session: PipSession, link: Link) -> Response: + target_url = link.url.split("#", 1)[0] + resp = session.get(target_url, headers=HEADERS, stream=True) + raise_for_status(resp) + return resp + + +class Downloader: + def __init__( + self, + session: PipSession, + progress_bar: str, + ) -> None: + self._session = session + self._progress_bar = progress_bar + + def __call__(self, link: Link, location: str) -> Tuple[str, str]: + """Download the file given by link into location.""" + try: + resp = _http_get_download(self._session, link) + except NetworkConnectionError as e: + assert e.response is not None + logger.critical( + "HTTP error %s while getting %s", e.response.status_code, link + ) + raise + + filename = _get_http_response_filename(resp, link) + filepath = os.path.join(location, filename) + + chunks = _prepare_download(resp, link, self._progress_bar) + with open(filepath, "wb") as content_file: + for chunk in chunks: + content_file.write(chunk) + content_type = resp.headers.get("Content-Type", "") + return filepath, content_type + + +class BatchDownloader: + def __init__( + self, + session: PipSession, + progress_bar: str, + ) -> None: + self._session = session + self._progress_bar = progress_bar + + def __call__( + self, links: Iterable[Link], location: str + ) -> Iterable[Tuple[Link, Tuple[str, str]]]: + """Download the files given by links into location.""" + for link in links: + try: + resp = _http_get_download(self._session, link) + except NetworkConnectionError as e: + assert e.response is not None + logger.critical( + "HTTP error %s while getting %s", + e.response.status_code, + link, + ) + raise + + filename = _get_http_response_filename(resp, link) + filepath = os.path.join(location, filename) + + chunks = _prepare_download(resp, link, self._progress_bar) + with open(filepath, "wb") as content_file: + for chunk in chunks: + content_file.write(chunk) + content_type = resp.headers.get("Content-Type", "") + yield link, (filepath, content_type) diff --git a/venv/Lib/site-packages/pip/_internal/network/lazy_wheel.py b/venv/Lib/site-packages/pip/_internal/network/lazy_wheel.py new file mode 100644 index 0000000..c9e44d5 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/network/lazy_wheel.py @@ -0,0 +1,210 @@ +"""Lazy ZIP over HTTP""" + +__all__ = ["HTTPRangeRequestUnsupported", "dist_from_wheel_url"] + +from bisect import bisect_left, bisect_right +from contextlib import contextmanager +from tempfile import NamedTemporaryFile +from typing import Any, Dict, Iterator, List, Optional, Tuple +from zipfile import BadZipfile, ZipFile + +from pip._vendor.packaging.utils import canonicalize_name +from pip._vendor.requests.models import CONTENT_CHUNK_SIZE, Response + +from pip._internal.metadata import BaseDistribution, MemoryWheel, get_wheel_distribution +from pip._internal.network.session import PipSession +from pip._internal.network.utils import HEADERS, raise_for_status, response_chunks + + +class HTTPRangeRequestUnsupported(Exception): + pass + + +def dist_from_wheel_url(name: str, url: str, session: PipSession) -> BaseDistribution: + """Return a distribution object from the given wheel URL. + + This uses HTTP range requests to only fetch the potion of the wheel + containing metadata, just enough for the object to be constructed. + If such requests are not supported, HTTPRangeRequestUnsupported + is raised. + """ + with LazyZipOverHTTP(url, session) as zf: + # For read-only ZIP files, ZipFile only needs methods read, + # seek, seekable and tell, not the whole IO protocol. + wheel = MemoryWheel(zf.name, zf) # type: ignore + # After context manager exit, wheel.name + # is an invalid file by intention. + return get_wheel_distribution(wheel, canonicalize_name(name)) + + +class LazyZipOverHTTP: + """File-like object mapped to a ZIP file over HTTP. + + This uses HTTP range requests to lazily fetch the file's content, + which is supposed to be fed to ZipFile. If such requests are not + supported by the server, raise HTTPRangeRequestUnsupported + during initialization. + """ + + def __init__( + self, url: str, session: PipSession, chunk_size: int = CONTENT_CHUNK_SIZE + ) -> None: + head = session.head(url, headers=HEADERS) + raise_for_status(head) + assert head.status_code == 200 + self._session, self._url, self._chunk_size = session, url, chunk_size + self._length = int(head.headers["Content-Length"]) + self._file = NamedTemporaryFile() + self.truncate(self._length) + self._left: List[int] = [] + self._right: List[int] = [] + if "bytes" not in head.headers.get("Accept-Ranges", "none"): + raise HTTPRangeRequestUnsupported("range request is not supported") + self._check_zip() + + @property + def mode(self) -> str: + """Opening mode, which is always rb.""" + return "rb" + + @property + def name(self) -> str: + """Path to the underlying file.""" + return self._file.name + + def seekable(self) -> bool: + """Return whether random access is supported, which is True.""" + return True + + def close(self) -> None: + """Close the file.""" + self._file.close() + + @property + def closed(self) -> bool: + """Whether the file is closed.""" + return self._file.closed + + def read(self, size: int = -1) -> bytes: + """Read up to size bytes from the object and return them. + + As a convenience, if size is unspecified or -1, + all bytes until EOF are returned. Fewer than + size bytes may be returned if EOF is reached. + """ + download_size = max(size, self._chunk_size) + start, length = self.tell(), self._length + stop = length if size < 0 else min(start + download_size, length) + start = max(0, stop - download_size) + self._download(start, stop - 1) + return self._file.read(size) + + def readable(self) -> bool: + """Return whether the file is readable, which is True.""" + return True + + def seek(self, offset: int, whence: int = 0) -> int: + """Change stream position and return the new absolute position. + + Seek to offset relative position indicated by whence: + * 0: Start of stream (the default). pos should be >= 0; + * 1: Current position - pos may be negative; + * 2: End of stream - pos usually negative. + """ + return self._file.seek(offset, whence) + + def tell(self) -> int: + """Return the current position.""" + return self._file.tell() + + def truncate(self, size: Optional[int] = None) -> int: + """Resize the stream to the given size in bytes. + + If size is unspecified resize to the current position. + The current stream position isn't changed. + + Return the new file size. + """ + return self._file.truncate(size) + + def writable(self) -> bool: + """Return False.""" + return False + + def __enter__(self) -> "LazyZipOverHTTP": + self._file.__enter__() + return self + + def __exit__(self, *exc: Any) -> Optional[bool]: + return self._file.__exit__(*exc) + + @contextmanager + def _stay(self) -> Iterator[None]: + """Return a context manager keeping the position. + + At the end of the block, seek back to original position. + """ + pos = self.tell() + try: + yield + finally: + self.seek(pos) + + def _check_zip(self) -> None: + """Check and download until the file is a valid ZIP.""" + end = self._length - 1 + for start in reversed(range(0, end, self._chunk_size)): + self._download(start, end) + with self._stay(): + try: + # For read-only ZIP files, ZipFile only needs + # methods read, seek, seekable and tell. + ZipFile(self) # type: ignore + except BadZipfile: + pass + else: + break + + def _stream_response( + self, start: int, end: int, base_headers: Dict[str, str] = HEADERS + ) -> Response: + """Return HTTP response to a range request from start to end.""" + headers = base_headers.copy() + headers["Range"] = f"bytes={start}-{end}" + # TODO: Get range requests to be correctly cached + headers["Cache-Control"] = "no-cache" + return self._session.get(self._url, headers=headers, stream=True) + + def _merge( + self, start: int, end: int, left: int, right: int + ) -> Iterator[Tuple[int, int]]: + """Return an iterator of intervals to be fetched. + + Args: + start (int): Start of needed interval + end (int): End of needed interval + left (int): Index of first overlapping downloaded data + right (int): Index after last overlapping downloaded data + """ + lslice, rslice = self._left[left:right], self._right[left:right] + i = start = min([start] + lslice[:1]) + end = max([end] + rslice[-1:]) + for j, k in zip(lslice, rslice): + if j > i: + yield i, j - 1 + i = k + 1 + if i <= end: + yield i, end + self._left[left:right], self._right[left:right] = [start], [end] + + def _download(self, start: int, end: int) -> None: + """Download bytes from start to end inclusively.""" + with self._stay(): + left = bisect_left(self._right, start) + right = bisect_right(self._left, end) + for start, end in self._merge(start, end, left, right): + response = self._stream_response(start, end) + response.raise_for_status() + self.seek(start) + for chunk in response_chunks(response, self._chunk_size): + self._file.write(chunk) diff --git a/venv/Lib/site-packages/pip/_internal/network/session.py b/venv/Lib/site-packages/pip/_internal/network/session.py new file mode 100644 index 0000000..cbe743b --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/network/session.py @@ -0,0 +1,454 @@ +"""PipSession and supporting code, containing all pip-specific +network request configuration and behavior. +""" + +import email.utils +import io +import ipaddress +import json +import logging +import mimetypes +import os +import platform +import shutil +import subprocess +import sys +import urllib.parse +import warnings +from typing import Any, Dict, Iterator, List, Mapping, Optional, Sequence, Tuple, Union + +from pip._vendor import requests, urllib3 +from pip._vendor.cachecontrol import CacheControlAdapter +from pip._vendor.requests.adapters import BaseAdapter, HTTPAdapter +from pip._vendor.requests.models import PreparedRequest, Response +from pip._vendor.requests.structures import CaseInsensitiveDict +from pip._vendor.urllib3.connectionpool import ConnectionPool +from pip._vendor.urllib3.exceptions import InsecureRequestWarning + +from pip import __version__ +from pip._internal.metadata import get_default_environment +from pip._internal.models.link import Link +from pip._internal.network.auth import MultiDomainBasicAuth +from pip._internal.network.cache import SafeFileCache + +# Import ssl from compat so the initial import occurs in only one place. +from pip._internal.utils.compat import has_tls +from pip._internal.utils.glibc import libc_ver +from pip._internal.utils.misc import build_url_from_netloc, parse_netloc +from pip._internal.utils.urls import url_to_path + +logger = logging.getLogger(__name__) + +SecureOrigin = Tuple[str, str, Optional[Union[int, str]]] + + +# Ignore warning raised when using --trusted-host. +warnings.filterwarnings("ignore", category=InsecureRequestWarning) + + +SECURE_ORIGINS: List[SecureOrigin] = [ + # protocol, hostname, port + # Taken from Chrome's list of secure origins (See: http://bit.ly/1qrySKC) + ("https", "*", "*"), + ("*", "localhost", "*"), + ("*", "127.0.0.0/8", "*"), + ("*", "::1/128", "*"), + ("file", "*", None), + # ssh is always secure. + ("ssh", "*", "*"), +] + + +# These are environment variables present when running under various +# CI systems. For each variable, some CI systems that use the variable +# are indicated. The collection was chosen so that for each of a number +# of popular systems, at least one of the environment variables is used. +# This list is used to provide some indication of and lower bound for +# CI traffic to PyPI. Thus, it is okay if the list is not comprehensive. +# For more background, see: https://github.com/pypa/pip/issues/5499 +CI_ENVIRONMENT_VARIABLES = ( + # Azure Pipelines + "BUILD_BUILDID", + # Jenkins + "BUILD_ID", + # AppVeyor, CircleCI, Codeship, Gitlab CI, Shippable, Travis CI + "CI", + # Explicit environment variable. + "PIP_IS_CI", +) + + +def looks_like_ci() -> bool: + """ + Return whether it looks like pip is running under CI. + """ + # We don't use the method of checking for a tty (e.g. using isatty()) + # because some CI systems mimic a tty (e.g. Travis CI). Thus that + # method doesn't provide definitive information in either direction. + return any(name in os.environ for name in CI_ENVIRONMENT_VARIABLES) + + +def user_agent() -> str: + """ + Return a string representing the user agent. + """ + data: Dict[str, Any] = { + "installer": {"name": "pip", "version": __version__}, + "python": platform.python_version(), + "implementation": { + "name": platform.python_implementation(), + }, + } + + if data["implementation"]["name"] == "CPython": + data["implementation"]["version"] = platform.python_version() + elif data["implementation"]["name"] == "PyPy": + pypy_version_info = sys.pypy_version_info # type: ignore + if pypy_version_info.releaselevel == "final": + pypy_version_info = pypy_version_info[:3] + data["implementation"]["version"] = ".".join( + [str(x) for x in pypy_version_info] + ) + elif data["implementation"]["name"] == "Jython": + # Complete Guess + data["implementation"]["version"] = platform.python_version() + elif data["implementation"]["name"] == "IronPython": + # Complete Guess + data["implementation"]["version"] = platform.python_version() + + if sys.platform.startswith("linux"): + from pip._vendor import distro + + linux_distribution = distro.name(), distro.version(), distro.codename() + distro_infos: Dict[str, Any] = dict( + filter( + lambda x: x[1], + zip(["name", "version", "id"], linux_distribution), + ) + ) + libc = dict( + filter( + lambda x: x[1], + zip(["lib", "version"], libc_ver()), + ) + ) + if libc: + distro_infos["libc"] = libc + if distro_infos: + data["distro"] = distro_infos + + if sys.platform.startswith("darwin") and platform.mac_ver()[0]: + data["distro"] = {"name": "macOS", "version": platform.mac_ver()[0]} + + if platform.system(): + data.setdefault("system", {})["name"] = platform.system() + + if platform.release(): + data.setdefault("system", {})["release"] = platform.release() + + if platform.machine(): + data["cpu"] = platform.machine() + + if has_tls(): + import _ssl as ssl + + data["openssl_version"] = ssl.OPENSSL_VERSION + + setuptools_dist = get_default_environment().get_distribution("setuptools") + if setuptools_dist is not None: + data["setuptools_version"] = str(setuptools_dist.version) + + if shutil.which("rustc") is not None: + # If for any reason `rustc --version` fails, silently ignore it + try: + rustc_output = subprocess.check_output( + ["rustc", "--version"], stderr=subprocess.STDOUT, timeout=0.5 + ) + except Exception: + pass + else: + if rustc_output.startswith(b"rustc "): + # The format of `rustc --version` is: + # `b'rustc 1.52.1 (9bc8c42bb 2021-05-09)\n'` + # We extract just the middle (1.52.1) part + data["rustc_version"] = rustc_output.split(b" ")[1].decode() + + # Use None rather than False so as not to give the impression that + # pip knows it is not being run under CI. Rather, it is a null or + # inconclusive result. Also, we include some value rather than no + # value to make it easier to know that the check has been run. + data["ci"] = True if looks_like_ci() else None + + user_data = os.environ.get("PIP_USER_AGENT_USER_DATA") + if user_data is not None: + data["user_data"] = user_data + + return "{data[installer][name]}/{data[installer][version]} {json}".format( + data=data, + json=json.dumps(data, separators=(",", ":"), sort_keys=True), + ) + + +class LocalFSAdapter(BaseAdapter): + def send( + self, + request: PreparedRequest, + stream: bool = False, + timeout: Optional[Union[float, Tuple[float, float]]] = None, + verify: Union[bool, str] = True, + cert: Optional[Union[str, Tuple[str, str]]] = None, + proxies: Optional[Mapping[str, str]] = None, + ) -> Response: + pathname = url_to_path(request.url) + + resp = Response() + resp.status_code = 200 + resp.url = request.url + + try: + stats = os.stat(pathname) + except OSError as exc: + # format the exception raised as a io.BytesIO object, + # to return a better error message: + resp.status_code = 404 + resp.reason = type(exc).__name__ + resp.raw = io.BytesIO(f"{resp.reason}: {exc}".encode("utf8")) + else: + modified = email.utils.formatdate(stats.st_mtime, usegmt=True) + content_type = mimetypes.guess_type(pathname)[0] or "text/plain" + resp.headers = CaseInsensitiveDict( + { + "Content-Type": content_type, + "Content-Length": stats.st_size, + "Last-Modified": modified, + } + ) + + resp.raw = open(pathname, "rb") + resp.close = resp.raw.close + + return resp + + def close(self) -> None: + pass + + +class InsecureHTTPAdapter(HTTPAdapter): + def cert_verify( + self, + conn: ConnectionPool, + url: str, + verify: Union[bool, str], + cert: Optional[Union[str, Tuple[str, str]]], + ) -> None: + super().cert_verify(conn=conn, url=url, verify=False, cert=cert) + + +class InsecureCacheControlAdapter(CacheControlAdapter): + def cert_verify( + self, + conn: ConnectionPool, + url: str, + verify: Union[bool, str], + cert: Optional[Union[str, Tuple[str, str]]], + ) -> None: + super().cert_verify(conn=conn, url=url, verify=False, cert=cert) + + +class PipSession(requests.Session): + + timeout: Optional[int] = None + + def __init__( + self, + *args: Any, + retries: int = 0, + cache: Optional[str] = None, + trusted_hosts: Sequence[str] = (), + index_urls: Optional[List[str]] = None, + **kwargs: Any, + ) -> None: + """ + :param trusted_hosts: Domains not to emit warnings for when not using + HTTPS. + """ + super().__init__(*args, **kwargs) + + # Namespace the attribute with "pip_" just in case to prevent + # possible conflicts with the base class. + self.pip_trusted_origins: List[Tuple[str, Optional[int]]] = [] + + # Attach our User Agent to the request + self.headers["User-Agent"] = user_agent() + + # Attach our Authentication handler to the session + self.auth = MultiDomainBasicAuth(index_urls=index_urls) + + # Create our urllib3.Retry instance which will allow us to customize + # how we handle retries. + retries = urllib3.Retry( + # Set the total number of retries that a particular request can + # have. + total=retries, + # A 503 error from PyPI typically means that the Fastly -> Origin + # connection got interrupted in some way. A 503 error in general + # is typically considered a transient error so we'll go ahead and + # retry it. + # A 500 may indicate transient error in Amazon S3 + # A 520 or 527 - may indicate transient error in CloudFlare + status_forcelist=[500, 503, 520, 527], + # Add a small amount of back off between failed requests in + # order to prevent hammering the service. + backoff_factor=0.25, + ) # type: ignore + + # Our Insecure HTTPAdapter disables HTTPS validation. It does not + # support caching so we'll use it for all http:// URLs. + # If caching is disabled, we will also use it for + # https:// hosts that we've marked as ignoring + # TLS errors for (trusted-hosts). + insecure_adapter = InsecureHTTPAdapter(max_retries=retries) + + # We want to _only_ cache responses on securely fetched origins or when + # the host is specified as trusted. We do this because + # we can't validate the response of an insecurely/untrusted fetched + # origin, and we don't want someone to be able to poison the cache and + # require manual eviction from the cache to fix it. + if cache: + secure_adapter = CacheControlAdapter( + cache=SafeFileCache(cache), + max_retries=retries, + ) + self._trusted_host_adapter = InsecureCacheControlAdapter( + cache=SafeFileCache(cache), + max_retries=retries, + ) + else: + secure_adapter = HTTPAdapter(max_retries=retries) + self._trusted_host_adapter = insecure_adapter + + self.mount("https://", secure_adapter) + self.mount("http://", insecure_adapter) + + # Enable file:// urls + self.mount("file://", LocalFSAdapter()) + + for host in trusted_hosts: + self.add_trusted_host(host, suppress_logging=True) + + def update_index_urls(self, new_index_urls: List[str]) -> None: + """ + :param new_index_urls: New index urls to update the authentication + handler with. + """ + self.auth.index_urls = new_index_urls + + def add_trusted_host( + self, host: str, source: Optional[str] = None, suppress_logging: bool = False + ) -> None: + """ + :param host: It is okay to provide a host that has previously been + added. + :param source: An optional source string, for logging where the host + string came from. + """ + if not suppress_logging: + msg = f"adding trusted host: {host!r}" + if source is not None: + msg += f" (from {source})" + logger.info(msg) + + host_port = parse_netloc(host) + if host_port not in self.pip_trusted_origins: + self.pip_trusted_origins.append(host_port) + + self.mount( + build_url_from_netloc(host, scheme="http") + "/", self._trusted_host_adapter + ) + self.mount(build_url_from_netloc(host) + "/", self._trusted_host_adapter) + if not host_port[1]: + self.mount( + build_url_from_netloc(host, scheme="http") + ":", + self._trusted_host_adapter, + ) + # Mount wildcard ports for the same host. + self.mount(build_url_from_netloc(host) + ":", self._trusted_host_adapter) + + def iter_secure_origins(self) -> Iterator[SecureOrigin]: + yield from SECURE_ORIGINS + for host, port in self.pip_trusted_origins: + yield ("*", host, "*" if port is None else port) + + def is_secure_origin(self, location: Link) -> bool: + # Determine if this url used a secure transport mechanism + parsed = urllib.parse.urlparse(str(location)) + origin_protocol, origin_host, origin_port = ( + parsed.scheme, + parsed.hostname, + parsed.port, + ) + + # The protocol to use to see if the protocol matches. + # Don't count the repository type as part of the protocol: in + # cases such as "git+ssh", only use "ssh". (I.e., Only verify against + # the last scheme.) + origin_protocol = origin_protocol.rsplit("+", 1)[-1] + + # Determine if our origin is a secure origin by looking through our + # hardcoded list of secure origins, as well as any additional ones + # configured on this PackageFinder instance. + for secure_origin in self.iter_secure_origins(): + secure_protocol, secure_host, secure_port = secure_origin + if origin_protocol != secure_protocol and secure_protocol != "*": + continue + + try: + addr = ipaddress.ip_address(origin_host) + network = ipaddress.ip_network(secure_host) + except ValueError: + # We don't have both a valid address or a valid network, so + # we'll check this origin against hostnames. + if ( + origin_host + and origin_host.lower() != secure_host.lower() + and secure_host != "*" + ): + continue + else: + # We have a valid address and network, so see if the address + # is contained within the network. + if addr not in network: + continue + + # Check to see if the port matches. + if ( + origin_port != secure_port + and secure_port != "*" + and secure_port is not None + ): + continue + + # If we've gotten here, then this origin matches the current + # secure origin and we should return True + return True + + # If we've gotten to this point, then the origin isn't secure and we + # will not accept it as a valid location to search. We will however + # log a warning that we are ignoring it. + logger.warning( + "The repository located at %s is not a trusted or secure host and " + "is being ignored. If this repository is available via HTTPS we " + "recommend you use HTTPS instead, otherwise you may silence " + "this warning and allow it anyway with '--trusted-host %s'.", + origin_host, + origin_host, + ) + + return False + + def request(self, method: str, url: str, *args: Any, **kwargs: Any) -> Response: + # Allow setting a default timeout on a session + kwargs.setdefault("timeout", self.timeout) + + # Dispatch the actual request + return super().request(method, url, *args, **kwargs) diff --git a/venv/Lib/site-packages/pip/_internal/network/utils.py b/venv/Lib/site-packages/pip/_internal/network/utils.py new file mode 100644 index 0000000..094cf1b --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/network/utils.py @@ -0,0 +1,96 @@ +from typing import Dict, Iterator + +from pip._vendor.requests.models import CONTENT_CHUNK_SIZE, Response + +from pip._internal.exceptions import NetworkConnectionError + +# The following comments and HTTP headers were originally added by +# Donald Stufft in git commit 22c562429a61bb77172039e480873fb239dd8c03. +# +# We use Accept-Encoding: identity here because requests defaults to +# accepting compressed responses. This breaks in a variety of ways +# depending on how the server is configured. +# - Some servers will notice that the file isn't a compressible file +# and will leave the file alone and with an empty Content-Encoding +# - Some servers will notice that the file is already compressed and +# will leave the file alone, adding a Content-Encoding: gzip header +# - Some servers won't notice anything at all and will take a file +# that's already been compressed and compress it again, and set +# the Content-Encoding: gzip header +# By setting this to request only the identity encoding we're hoping +# to eliminate the third case. Hopefully there does not exist a server +# which when given a file will notice it is already compressed and that +# you're not asking for a compressed file and will then decompress it +# before sending because if that's the case I don't think it'll ever be +# possible to make this work. +HEADERS: Dict[str, str] = {"Accept-Encoding": "identity"} + + +def raise_for_status(resp: Response) -> None: + http_error_msg = "" + if isinstance(resp.reason, bytes): + # We attempt to decode utf-8 first because some servers + # choose to localize their reason strings. If the string + # isn't utf-8, we fall back to iso-8859-1 for all other + # encodings. + try: + reason = resp.reason.decode("utf-8") + except UnicodeDecodeError: + reason = resp.reason.decode("iso-8859-1") + else: + reason = resp.reason + + if 400 <= resp.status_code < 500: + http_error_msg = ( + f"{resp.status_code} Client Error: {reason} for url: {resp.url}" + ) + + elif 500 <= resp.status_code < 600: + http_error_msg = ( + f"{resp.status_code} Server Error: {reason} for url: {resp.url}" + ) + + if http_error_msg: + raise NetworkConnectionError(http_error_msg, response=resp) + + +def response_chunks( + response: Response, chunk_size: int = CONTENT_CHUNK_SIZE +) -> Iterator[bytes]: + """Given a requests Response, provide the data chunks.""" + try: + # Special case for urllib3. + for chunk in response.raw.stream( + chunk_size, + # We use decode_content=False here because we don't + # want urllib3 to mess with the raw bytes we get + # from the server. If we decompress inside of + # urllib3 then we cannot verify the checksum + # because the checksum will be of the compressed + # file. This breakage will only occur if the + # server adds a Content-Encoding header, which + # depends on how the server was configured: + # - Some servers will notice that the file isn't a + # compressible file and will leave the file alone + # and with an empty Content-Encoding + # - Some servers will notice that the file is + # already compressed and will leave the file + # alone and will add a Content-Encoding: gzip + # header + # - Some servers won't notice anything at all and + # will take a file that's already been compressed + # and compress it again and set the + # Content-Encoding: gzip header + # + # By setting this not to decode automatically we + # hope to eliminate problems with the second case. + decode_content=False, + ): + yield chunk + except AttributeError: + # Standard file-like object. + while True: + chunk = response.raw.read(chunk_size) + if not chunk: + break + yield chunk diff --git a/venv/Lib/site-packages/pip/_internal/network/xmlrpc.py b/venv/Lib/site-packages/pip/_internal/network/xmlrpc.py new file mode 100644 index 0000000..4a7d55d --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/network/xmlrpc.py @@ -0,0 +1,60 @@ +"""xmlrpclib.Transport implementation +""" + +import logging +import urllib.parse +import xmlrpc.client +from typing import TYPE_CHECKING, Tuple + +from pip._internal.exceptions import NetworkConnectionError +from pip._internal.network.session import PipSession +from pip._internal.network.utils import raise_for_status + +if TYPE_CHECKING: + from xmlrpc.client import _HostType, _Marshallable + +logger = logging.getLogger(__name__) + + +class PipXmlrpcTransport(xmlrpc.client.Transport): + """Provide a `xmlrpclib.Transport` implementation via a `PipSession` + object. + """ + + def __init__( + self, index_url: str, session: PipSession, use_datetime: bool = False + ) -> None: + super().__init__(use_datetime) + index_parts = urllib.parse.urlparse(index_url) + self._scheme = index_parts.scheme + self._session = session + + def request( + self, + host: "_HostType", + handler: str, + request_body: bytes, + verbose: bool = False, + ) -> Tuple["_Marshallable", ...]: + assert isinstance(host, str) + parts = (self._scheme, host, handler, None, None, None) + url = urllib.parse.urlunparse(parts) + try: + headers = {"Content-Type": "text/xml"} + response = self._session.post( + url, + data=request_body, + headers=headers, + stream=True, + ) + raise_for_status(response) + self.verbose = verbose + return self.parse_response(response.raw) + except NetworkConnectionError as exc: + assert exc.response + logger.critical( + "HTTP error %s while getting %s", + exc.response.status_code, + url, + ) + raise diff --git a/venv/Lib/site-packages/pip/_internal/operations/__init__.py b/venv/Lib/site-packages/pip/_internal/operations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/venv/Lib/site-packages/pip/_internal/operations/__pycache__/__init__.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/operations/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..022909c018701babfb0164ce08fbd1e78a195351 GIT binary patch literal 189 zcmYe~<>g`kf?j#GBoO@=L?8o3AjbiSi&=m~3PUi1CZpdY!wq)oLW>I zlbDy6SRCV6P~ehSk{IKYpPZNz6Ox)+5L1v@pj(<(keHmEnxb2tk(!#LYi5y^S)5#4 z1(J)2&&(@HEy@Eb&o4+VN-W9D&nu3J2a0Bv#K-FuRNmsS$<0qG%}KQb+5H)a835rp BGSC13 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/operations/__pycache__/check.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/operations/__pycache__/check.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..28502f525641c9a84ac312a23c3c577b1c51d746 GIT binary patch literal 3993 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 KeY<6~KKVa$Lsy3Y literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/operations/__pycache__/prepare.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/operations/__pycache__/prepare.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f691f03737c58436388aed45f5fa81389a1e2b12 GIT binary patch literal 14751 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 IGY~TX057>ULI3~& literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/metadata.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/metadata.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..dc74bcc2f283216cc893699cb2de87e876ce6a93 GIT binary patch literal 1406 zcmZuxTaV*36t)vLX}jrMR!9sCf=Eb+K1?(#!GaJ%!0d35U{$e;MjKT`Y3yy?N$kjW zXK0low9D&g{{TWekNg3COkR27FYtgkPA@wvaFk=8i|upHcaGCuuZv(@z4gwhY9aKe zWo{0Tp-S+{bp@MFJd$L)sq@=no>yUp6q zZxultV8mL?Wj)rT?OzG)(C#lJ-l5I|)W5ZO?^|Y4nwm5mGr?49xD;V7$2*GBQt%xZPi{R{j<_xrfs8?f^IJ0E-{<@rgP=S*4I=QEzuQ*ptS6a^Ee@6?B1 z3vIxlIsU3P zqP)iy%Zya>KB+q+dwIgdMeUE$?3@W&`xHXtxvo9M%uI>QweGJ+8|DE16ZrKXKunW$ z>RvfZw{oX=Nh#p665Eya?smH=N{F@&wgSs}>)Qg`3S2yviIujP zt>E90I)Eeoo}7F%{9ZGqhp7;$9)4Dq_n@(iu0Va`|BMWz%jS4h0xrBiO%zS0Z;;olC+&}+8fQ8C1OumU U10inP37i1$kpKt8!_Ghd0(&K%lK=n! literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/metadata_editable.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/metadata_editable.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f0379478b17ec50c17c5876395242117a94a1f5a GIT binary patch literal 1440 zcmZuxTaVjB6rQoic9J@~Xa{n9zd8v0 zZj{{tHuNF9ih`ghLKIUg!x4tr&aB*yY;0^KBe@ef_1ekY+>5-t5jASv&6;^DYSn8m zyOH~mj}dd2&DyL@8$S`+q^%!Gv`4K6sC#4n_Lod2G|@>gVuHy;^Fjn!G2&_PxR8M= zrZQy#S8!aZ!20Bt2(>Rvv{b@=R5(WO^z^Y8&|L(SX^9_XJ+`8wg!z zo!VE{(q7mTyd(?s>VUO3nISs$bM9%y7iuJO`6L!w8Jc4iZdmLB*H zw7amVbA=b)6YC5;LeyP)-+Q99ntP~+&cH?xK~I5K(Yb@v4?TqI=Ml*Ncz@pYYHxy{ zHx^{!UK=L8dA3d;3-S%6Q^myy)O4H(u5uMnrc&UM(SVDff7%a@k9%RO6~Oqa&W#H6 zm~Bb{!nRw{O_IYpdcL0*lu2>433v!BlXDK~?u@cx2wczNJP|+>oxjzWtW2cA!YJ3t zFx$cSW;ugum;i&JF7m9~#nFBV%)yuOnz;Mjru2ZCij;{SOV=!Ks%;g;s~U-3FY9Ai zyulPh1;^`xSf48id@N0)RaT)YGAX#|Hl(Qn*)+m*XtlrHLFXmhyz;jOqq(aCE8nyQ z7mthBSRH1n`4=Q_!xn#jd-C4kYsI7*Btj%=@KIUbgDx9A51wx<`4afL`;`~Rv`FJvc0jKV0Y(^KKob=*EbCSeFJ)2!93?Fi zal4M#01da@Cryu42QPZrcPT6DU&sy(uf7-qznDyg|B}06`<4F-(vU=x`BiP$@Q12z mQRjb0m}^&!_n}^=8T$Z(rfz{CcEj>5A9sk4ed1#4uYUmVcB>Nr literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/metadata_legacy.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/metadata_legacy.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ef4df2a851776074c74fb5c70a6072feebc39a03 GIT binary patch literal 2316 zcmaJ?&5zqe6rZsj$MI&fY1z`HpH^v0BeBuK0ijY=g?=EUwnE!N)hOUPo=Mib_Snog zEiq0H-CkD}65;?w+C6gRZ{V+(E2o~hRUmjX`Cu0+Z25Wo-t)|x_kQm;!Q!He;MzHT zzW2R@&~NHv|5b&LEAWUPKoHbH1QR319jxC*$AGsPn~Bx2u(DZkC9ylU9#`UO;&hy( z)~O|K$JIJJUP$Vlx*k{K#iY?`=&=(oCCyF~BZ_wq(ZhSV^BP^I%cS<)ATC*WYITlK zOKIrqT3>%|lSR@1{ZV4vL9M0YgIhEYNRS8KfHKO1JW81tr-LZ;`YHEfItap%C(lR; z;X3Cjm&f<3?hJbwPeUri#JDmG?BjV{H-adp1m-@O1Y6V>G#_Spn#RJXgMlBhe(DE& zAi!ZMgq3_TpAuAycWIJci#QGQl#g15tdZG=v^h-0S%}q!rk4Tl3OrZg5$hmS>7Jq- z?cx&c;cI9ck8z2``P?98iGD;s8Qb^?&dm~ULqWGJeg!O*T}ydu3)-yg+9fJ6vEM*@ zD*e@>eIsJT3z*l2Ev%|7co6kGGB0A@gZbBk_A4X2qar*8Vt`8Y#bFiIE`V+ibF0MP z8edtk5-w`<6(AW7WkfuR@(sv?(O#3d|1;uCFvZLC>c#G7f^yLf7z;%A!z{Z7=;+=| zA*EfF!)_L3t3#Fr;T9#Uk2WZcSKoVoGZLXFl&uSu$SG&w4iK0iN_2Y)A>CvOHh+Sv zb~cjkr5I2Zrb%}BCtg5wOUT%R-nlWY4hMq`*Tv}O>Z%Au1jabXz ziVI||58z}$LWNG`L^PG9ad0z7Kqr&|8Ow%+8%7-)*!jz{_;Jv+Y+2K}@+o^L7d6KH zY~+Qck*6CYw!Se-TBLE^hLg!O$NB%va*c<%L@gYasu^cfbxbSVgpa73sAM%3j`$|q5S~b9lS!QeWqSO3RT?y?;bfcJ$X`%lYm7Lz=i?%M&!iw4uXLRsT{_?L#H*ZgU}FUtT_#x@(ER44dXDcaCh~oLL2b)~Q(MC rK=D4;OyyikQZkI`WyONx3<%3~umcQL$IBHZ>xOGKo6{nw#J~I-+`N+~ literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/wheel.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/wheel.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d8788db8c1d35222392a5b2de666688d60ae260d GIT binary patch literal 1190 zcmY*Z-H+Tf5V!NSxm-@V7C}`N9eycvrC!uN@S&=zfNK$;>UwHHZC8<^?0Rl5+r$aB z(_>fL7uweoFT4TL-6Q{!UwPtR00|g7P!3z3&Di6a-~490<cF(VaCY*%sJE)^(G#OC>YXkFap^hQxiYvbk&No#_#O|=-$8i;pc7pY_F_qkhph6 z_CkOxjw^jssIGEK14@;17>6bhWdmk3EoaX_aC5N%UGh?w1+OH`bSsx8)X;R?L=to_ z#S9aFJ#4};u034p2NY|M)1IpIOY$9EJ<;Tpa&PUQd6a06`)l$e;la=TOZp;M(^G#P zoYC)hC|T1*u=eq8c;dYXA0u%A3CK$%N^IXG>d6g4-F%AjF%c{vI$XXQ_Ao}oqcyQH zp5o0%X&a$r`OrKJBZTvsM86LMV;gJcMt0%&-BWS+6QFXZi@(!My{9 z1hT0!?_@heqOv4mI3Bw673)fU#B|G!j{s^`9WvF=tl42-*GqR(XY2ublgE{U>ujJ+ zv3-o5IZykm%XdNPN|d&8>^0N3*j2T9!$Gxxh5(1HWUCA8TDL?v3oJ>d+om3msT?8S ztG7QZs~Y%#`2V-As&QhXx}DEKnvlb^pG#Xjb3ygfe{w5^?l7A!-;Nhu)M3f-ClII5&5q3u=~MBi%QMZ%AVy#B{WEE^t|mrI_gyJ zVCT*{>z3x?xipH-J%$v+s~r?1NvTIu&!fp-fuGUo^#9Q_>zTLFEui*|wP1&s&ai^Z0Nr1Vy8U67$?GaGJ literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/wheel_editable.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/wheel_editable.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d9867eb60c71c7f3fa42ccd5b42c2829176b3726 GIT binary patch literal 1406 zcmZWpTW=gS6t?HKmu#Z6stQ#l>X#rEkx}~4fGUKbX;DETjapFD)kwqa`eb*ubHnyD z>}r<>$`ew=4*;aiBmae8VDZKie*qA1>`8hNwrtO_kI(tecYG#UU+)rZr#IdlE`36N zH^R#;K;c6i@=KgJ;WQ(IW~Bp)vXeQvJ8-Glb2BgZ2Ywz50xNr2D{l|llmJ#xYedi6?LW{9Ip|Z}eo(2jERwA6=(YQ0`Q)=y%Cs2k z%|obe-F(+iQux!NJr_QyD*4~9NkvtOG% z>!GzE2CK3D2ra1gw6p3WF8|Ci8JM5msnd+JvHN$YLf(}CcqBw z9kSis9X7P;l_*C@c-ZYSY!5Asl2wVCFjcaX2|&iuV;S!o*3!ZJ+Fg(;EfVt_*z=6tW?OQ8)j~CZfTt=MX26b1!RD9PTh$B^O)MNz7A(9dseNj8L0QcJL*H6fk97sgAF%v_ozPn&a8pWyqO-}pF5 zGvJN2|H0Uj{WTqA<#-H2`y7V#SYU|}eM#2CbH3u{t~Y{#oqZj=qo}WQ0^C zGWw{h?qV@S`{gLfqR+7oqAIPn>!LFC!nduF?cMjLsT|3us1X+;{%=g8Q_Gy-mgI zc%#3eTZUC6Tx_DO12w~%9}C9_*AZYCKgB{XMOfK?MR+2T3V}*Xt1!i_->_;IafG!> zGa0_fOOvS17}S1~zjkbSjALQ`1=^KLSTL5;m!{XuY5V=WWVK+b^3PT_S18b281+*Xpd2v}K5&=aR!)SK8*PdiNV|BN) zSu;L`0|z30073E|xpLsl@8~Nh{sDwUP}O7aZXzNvmV5e9{i^z^YLca;kic{ArPsFp zY!dQ2HV!`lG(LjA{1pmD7|ltye$%c6Z7a8jPS+W_U6*3NoqI#S>zlfh2g63UVd`!k z4x8QPu+?o*!pUrjFYnRr5$^DnGi&&1bqTmAB z(J;BiW69Ncq{=dv@fL$A@y>wrJWfPk!YW77B+p|x-WrKA;V-|2LXnExrBjR1%K8zs{gXYlD=JS_ zHnZO)Q@eOi(V4YJlzr2=<%kXFcT9g&(V5GvJt{XV$}H%kFy>bDNAeT4?8*ksc#|_% z%+aIy;i9al?*jUXpcdt2zn>NT&SdpseYpsfFdp(k$&E?5c>27DVtB*ZFhv0IYs}>wYu0cWEfVM1$hIE;RR!9T7Y>8vg-}bayBttHB zpx{U`%Y=5Yz%1=nOd8qf@tXl~vi5a~D}~l|6GR zcaMUnTGxqkkvV1qPg~5v85P;Ho<2u;H~m>q(TXtlI7k|T*IXl#`T9);XWjl`?2U!xQV7%>{z4VfaY4K<`HYW;YITk55 zP%ZcKax2N>(u75+m+IXXO&86?YSa*~#e+9SPcx|f1{FXJf=mS{F?!FLdJMpUpk+hQ z@)fQ8yYz?erh&3%5TpP%i;~Hjaw-qPl2rxFgE@^Gq&V*Yg1Z$Z_^X1M$9zN+=0SQu z6e;d8tvxf`wQs828o6D1HS34q|c+V;Q=8&Ra@oMoX&X~=!9VePYu4@r+!ZSb|l9s zW{d4{p4Y&uPIL{H6FZsYZ$))FkS2b1%t~!roCdXu*PzfxAdIQ3Fp&nWHd!@CMMUcz z&^0E_=yhXfh&%1c@k<9&4t#4PIxQzJj&{`mLi|EFI+W&M+oQOno$fI0&r_pzxe%q8 zoVb#Jld$^ck8gfjUTwQiMZDb<7?%X5xY}7<#<#|Ofk^4bhtMJ5O0O%yzd zgMJPv7_MCN+^T)&6&!vQi+vr5GbkO_@fUNoZsF-;2%!=TDBi$fug+8EoC{g>h$p@8 znZqtu+xvZ(FE^kdEsM^74?VvHp&J};(L=3=p=bK&8ieyh{eOGDcn4;;*Tgcsv|q}O z+1lLFQ@e23zQFGRVdMA str: + """Generate metadata using mechanisms described in PEP 517. + + Returns the generated metadata directory. + """ + metadata_tmpdir = TempDirectory(kind="modern-metadata", globally_managed=True) + + metadata_dir = metadata_tmpdir.path + + with build_env: + # Note that Pep517HookCaller implements a fallback for + # prepare_metadata_for_build_wheel, so we don't have to + # consider the possibility that this hook doesn't exist. + runner = runner_with_spinner_message("Preparing metadata (pyproject.toml)") + with backend.subprocess_runner(runner): + try: + distinfo_dir = backend.prepare_metadata_for_build_wheel(metadata_dir) + except InstallationSubprocessError as error: + raise MetadataGenerationFailed(package_details=details) from error + + return os.path.join(metadata_dir, distinfo_dir) diff --git a/venv/Lib/site-packages/pip/_internal/operations/build/metadata_editable.py b/venv/Lib/site-packages/pip/_internal/operations/build/metadata_editable.py new file mode 100644 index 0000000..4c3f48b --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/operations/build/metadata_editable.py @@ -0,0 +1,41 @@ +"""Metadata generation logic for source distributions. +""" + +import os + +from pip._vendor.pep517.wrappers import Pep517HookCaller + +from pip._internal.build_env import BuildEnvironment +from pip._internal.exceptions import ( + InstallationSubprocessError, + MetadataGenerationFailed, +) +from pip._internal.utils.subprocess import runner_with_spinner_message +from pip._internal.utils.temp_dir import TempDirectory + + +def generate_editable_metadata( + build_env: BuildEnvironment, backend: Pep517HookCaller, details: str +) -> str: + """Generate metadata using mechanisms described in PEP 660. + + Returns the generated metadata directory. + """ + metadata_tmpdir = TempDirectory(kind="modern-metadata", globally_managed=True) + + metadata_dir = metadata_tmpdir.path + + with build_env: + # Note that Pep517HookCaller implements a fallback for + # prepare_metadata_for_build_wheel/editable, so we don't have to + # consider the possibility that this hook doesn't exist. + runner = runner_with_spinner_message( + "Preparing editable metadata (pyproject.toml)" + ) + with backend.subprocess_runner(runner): + try: + distinfo_dir = backend.prepare_metadata_for_build_editable(metadata_dir) + except InstallationSubprocessError as error: + raise MetadataGenerationFailed(package_details=details) from error + + return os.path.join(metadata_dir, distinfo_dir) diff --git a/venv/Lib/site-packages/pip/_internal/operations/build/metadata_legacy.py b/venv/Lib/site-packages/pip/_internal/operations/build/metadata_legacy.py new file mode 100644 index 0000000..e60988d --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/operations/build/metadata_legacy.py @@ -0,0 +1,74 @@ +"""Metadata generation logic for legacy source distributions. +""" + +import logging +import os + +from pip._internal.build_env import BuildEnvironment +from pip._internal.cli.spinners import open_spinner +from pip._internal.exceptions import ( + InstallationError, + InstallationSubprocessError, + MetadataGenerationFailed, +) +from pip._internal.utils.setuptools_build import make_setuptools_egg_info_args +from pip._internal.utils.subprocess import call_subprocess +from pip._internal.utils.temp_dir import TempDirectory + +logger = logging.getLogger(__name__) + + +def _find_egg_info(directory: str) -> str: + """Find an .egg-info subdirectory in `directory`.""" + filenames = [f for f in os.listdir(directory) if f.endswith(".egg-info")] + + if not filenames: + raise InstallationError(f"No .egg-info directory found in {directory}") + + if len(filenames) > 1: + raise InstallationError( + "More than one .egg-info directory found in {}".format(directory) + ) + + return os.path.join(directory, filenames[0]) + + +def generate_metadata( + build_env: BuildEnvironment, + setup_py_path: str, + source_dir: str, + isolated: bool, + details: str, +) -> str: + """Generate metadata using setup.py-based defacto mechanisms. + + Returns the generated metadata directory. + """ + logger.debug( + "Running setup.py (path:%s) egg_info for package %s", + setup_py_path, + details, + ) + + egg_info_dir = TempDirectory(kind="pip-egg-info", globally_managed=True).path + + args = make_setuptools_egg_info_args( + setup_py_path, + egg_info_dir=egg_info_dir, + no_user_config=isolated, + ) + + with build_env: + with open_spinner("Preparing metadata (setup.py)") as spinner: + try: + call_subprocess( + args, + cwd=source_dir, + command_desc="python setup.py egg_info", + spinner=spinner, + ) + except InstallationSubprocessError as error: + raise MetadataGenerationFailed(package_details=details) from error + + # Return the .egg-info directory. + return _find_egg_info(egg_info_dir) diff --git a/venv/Lib/site-packages/pip/_internal/operations/build/wheel.py b/venv/Lib/site-packages/pip/_internal/operations/build/wheel.py new file mode 100644 index 0000000..b0d2fc9 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/operations/build/wheel.py @@ -0,0 +1,37 @@ +import logging +import os +from typing import Optional + +from pip._vendor.pep517.wrappers import Pep517HookCaller + +from pip._internal.utils.subprocess import runner_with_spinner_message + +logger = logging.getLogger(__name__) + + +def build_wheel_pep517( + name: str, + backend: Pep517HookCaller, + metadata_directory: str, + tempd: str, +) -> Optional[str]: + """Build one InstallRequirement using the PEP 517 build process. + + Returns path to wheel if successfully built. Otherwise, returns None. + """ + assert metadata_directory is not None + try: + logger.debug("Destination directory: %s", tempd) + + runner = runner_with_spinner_message( + f"Building wheel for {name} (pyproject.toml)" + ) + with backend.subprocess_runner(runner): + wheel_name = backend.build_wheel( + tempd, + metadata_directory=metadata_directory, + ) + except Exception: + logger.error("Failed building wheel for %s", name) + return None + return os.path.join(tempd, wheel_name) diff --git a/venv/Lib/site-packages/pip/_internal/operations/build/wheel_editable.py b/venv/Lib/site-packages/pip/_internal/operations/build/wheel_editable.py new file mode 100644 index 0000000..cf7b01a --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/operations/build/wheel_editable.py @@ -0,0 +1,46 @@ +import logging +import os +from typing import Optional + +from pip._vendor.pep517.wrappers import HookMissing, Pep517HookCaller + +from pip._internal.utils.subprocess import runner_with_spinner_message + +logger = logging.getLogger(__name__) + + +def build_wheel_editable( + name: str, + backend: Pep517HookCaller, + metadata_directory: str, + tempd: str, +) -> Optional[str]: + """Build one InstallRequirement using the PEP 660 build process. + + Returns path to wheel if successfully built. Otherwise, returns None. + """ + assert metadata_directory is not None + try: + logger.debug("Destination directory: %s", tempd) + + runner = runner_with_spinner_message( + f"Building editable for {name} (pyproject.toml)" + ) + with backend.subprocess_runner(runner): + try: + wheel_name = backend.build_editable( + tempd, + metadata_directory=metadata_directory, + ) + except HookMissing as e: + logger.error( + "Cannot build editable %s because the build " + "backend does not have the %s hook", + name, + e, + ) + return None + except Exception: + logger.error("Failed building editable for %s", name) + return None + return os.path.join(tempd, wheel_name) diff --git a/venv/Lib/site-packages/pip/_internal/operations/build/wheel_legacy.py b/venv/Lib/site-packages/pip/_internal/operations/build/wheel_legacy.py new file mode 100644 index 0000000..c5f0492 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/operations/build/wheel_legacy.py @@ -0,0 +1,102 @@ +import logging +import os.path +from typing import List, Optional + +from pip._internal.cli.spinners import open_spinner +from pip._internal.utils.setuptools_build import make_setuptools_bdist_wheel_args +from pip._internal.utils.subprocess import call_subprocess, format_command_args + +logger = logging.getLogger(__name__) + + +def format_command_result( + command_args: List[str], + command_output: str, +) -> str: + """Format command information for logging.""" + command_desc = format_command_args(command_args) + text = f"Command arguments: {command_desc}\n" + + if not command_output: + text += "Command output: None" + elif logger.getEffectiveLevel() > logging.DEBUG: + text += "Command output: [use --verbose to show]" + else: + if not command_output.endswith("\n"): + command_output += "\n" + text += f"Command output:\n{command_output}" + + return text + + +def get_legacy_build_wheel_path( + names: List[str], + temp_dir: str, + name: str, + command_args: List[str], + command_output: str, +) -> Optional[str]: + """Return the path to the wheel in the temporary build directory.""" + # Sort for determinism. + names = sorted(names) + if not names: + msg = ("Legacy build of wheel for {!r} created no files.\n").format(name) + msg += format_command_result(command_args, command_output) + logger.warning(msg) + return None + + if len(names) > 1: + msg = ( + "Legacy build of wheel for {!r} created more than one file.\n" + "Filenames (choosing first): {}\n" + ).format(name, names) + msg += format_command_result(command_args, command_output) + logger.warning(msg) + + return os.path.join(temp_dir, names[0]) + + +def build_wheel_legacy( + name: str, + setup_py_path: str, + source_dir: str, + global_options: List[str], + build_options: List[str], + tempd: str, +) -> Optional[str]: + """Build one unpacked package using the "legacy" build process. + + Returns path to wheel if successfully built. Otherwise, returns None. + """ + wheel_args = make_setuptools_bdist_wheel_args( + setup_py_path, + global_options=global_options, + build_options=build_options, + destination_dir=tempd, + ) + + spin_message = f"Building wheel for {name} (setup.py)" + with open_spinner(spin_message) as spinner: + logger.debug("Destination directory: %s", tempd) + + try: + output = call_subprocess( + wheel_args, + command_desc="python setup.py bdist_wheel", + cwd=source_dir, + spinner=spinner, + ) + except Exception: + spinner.finish("error") + logger.error("Failed building wheel for %s", name) + return None + + names = os.listdir(tempd) + wheel_path = get_legacy_build_wheel_path( + names=names, + temp_dir=tempd, + name=name, + command_args=wheel_args, + command_output=output, + ) + return wheel_path diff --git a/venv/Lib/site-packages/pip/_internal/operations/check.py b/venv/Lib/site-packages/pip/_internal/operations/check.py new file mode 100644 index 0000000..fb3ac8b --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/operations/check.py @@ -0,0 +1,149 @@ +"""Validation of dependencies of packages +""" + +import logging +from typing import Callable, Dict, List, NamedTuple, Optional, Set, Tuple + +from pip._vendor.packaging.requirements import Requirement +from pip._vendor.packaging.utils import NormalizedName, canonicalize_name + +from pip._internal.distributions import make_distribution_for_install_requirement +from pip._internal.metadata import get_default_environment +from pip._internal.metadata.base import DistributionVersion +from pip._internal.req.req_install import InstallRequirement + +logger = logging.getLogger(__name__) + + +class PackageDetails(NamedTuple): + version: DistributionVersion + dependencies: List[Requirement] + + +# Shorthands +PackageSet = Dict[NormalizedName, PackageDetails] +Missing = Tuple[NormalizedName, Requirement] +Conflicting = Tuple[NormalizedName, DistributionVersion, Requirement] + +MissingDict = Dict[NormalizedName, List[Missing]] +ConflictingDict = Dict[NormalizedName, List[Conflicting]] +CheckResult = Tuple[MissingDict, ConflictingDict] +ConflictDetails = Tuple[PackageSet, CheckResult] + + +def create_package_set_from_installed() -> Tuple[PackageSet, bool]: + """Converts a list of distributions into a PackageSet.""" + package_set = {} + problems = False + env = get_default_environment() + for dist in env.iter_installed_distributions(local_only=False, skip=()): + name = dist.canonical_name + try: + dependencies = list(dist.iter_dependencies()) + package_set[name] = PackageDetails(dist.version, dependencies) + except (OSError, ValueError) as e: + # Don't crash on unreadable or broken metadata. + logger.warning("Error parsing requirements for %s: %s", name, e) + problems = True + return package_set, problems + + +def check_package_set( + package_set: PackageSet, should_ignore: Optional[Callable[[str], bool]] = None +) -> CheckResult: + """Check if a package set is consistent + + If should_ignore is passed, it should be a callable that takes a + package name and returns a boolean. + """ + + missing = {} + conflicting = {} + + for package_name, package_detail in package_set.items(): + # Info about dependencies of package_name + missing_deps: Set[Missing] = set() + conflicting_deps: Set[Conflicting] = set() + + if should_ignore and should_ignore(package_name): + continue + + for req in package_detail.dependencies: + name = canonicalize_name(req.name) + + # Check if it's missing + if name not in package_set: + missed = True + if req.marker is not None: + missed = req.marker.evaluate() + if missed: + missing_deps.add((name, req)) + continue + + # Check if there's a conflict + version = package_set[name].version + if not req.specifier.contains(version, prereleases=True): + conflicting_deps.add((name, version, req)) + + if missing_deps: + missing[package_name] = sorted(missing_deps, key=str) + if conflicting_deps: + conflicting[package_name] = sorted(conflicting_deps, key=str) + + return missing, conflicting + + +def check_install_conflicts(to_install: List[InstallRequirement]) -> ConflictDetails: + """For checking if the dependency graph would be consistent after \ + installing given requirements + """ + # Start from the current state + package_set, _ = create_package_set_from_installed() + # Install packages + would_be_installed = _simulate_installation_of(to_install, package_set) + + # Only warn about directly-dependent packages; create a whitelist of them + whitelist = _create_whitelist(would_be_installed, package_set) + + return ( + package_set, + check_package_set( + package_set, should_ignore=lambda name: name not in whitelist + ), + ) + + +def _simulate_installation_of( + to_install: List[InstallRequirement], package_set: PackageSet +) -> Set[NormalizedName]: + """Computes the version of packages after installing to_install.""" + # Keep track of packages that were installed + installed = set() + + # Modify it as installing requirement_set would (assuming no errors) + for inst_req in to_install: + abstract_dist = make_distribution_for_install_requirement(inst_req) + dist = abstract_dist.get_metadata_distribution() + name = dist.canonical_name + package_set[name] = PackageDetails(dist.version, list(dist.iter_dependencies())) + + installed.add(name) + + return installed + + +def _create_whitelist( + would_be_installed: Set[NormalizedName], package_set: PackageSet +) -> Set[NormalizedName]: + packages_affected = set(would_be_installed) + + for package_name in package_set: + if package_name in packages_affected: + continue + + for req in package_set[package_name].dependencies: + if canonicalize_name(req.name) in packages_affected: + packages_affected.add(package_name) + break + + return packages_affected diff --git a/venv/Lib/site-packages/pip/_internal/operations/freeze.py b/venv/Lib/site-packages/pip/_internal/operations/freeze.py new file mode 100644 index 0000000..4565540 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/operations/freeze.py @@ -0,0 +1,254 @@ +import collections +import logging +import os +from typing import Container, Dict, Iterable, Iterator, List, NamedTuple, Optional, Set + +from pip._vendor.packaging.utils import canonicalize_name +from pip._vendor.packaging.version import Version + +from pip._internal.exceptions import BadCommand, InstallationError +from pip._internal.metadata import BaseDistribution, get_environment +from pip._internal.req.constructors import ( + install_req_from_editable, + install_req_from_line, +) +from pip._internal.req.req_file import COMMENT_RE +from pip._internal.utils.direct_url_helpers import direct_url_as_pep440_direct_reference + +logger = logging.getLogger(__name__) + + +class _EditableInfo(NamedTuple): + requirement: str + comments: List[str] + + +def freeze( + requirement: Optional[List[str]] = None, + local_only: bool = False, + user_only: bool = False, + paths: Optional[List[str]] = None, + isolated: bool = False, + exclude_editable: bool = False, + skip: Container[str] = (), +) -> Iterator[str]: + installations: Dict[str, FrozenRequirement] = {} + + dists = get_environment(paths).iter_installed_distributions( + local_only=local_only, + skip=(), + user_only=user_only, + ) + for dist in dists: + req = FrozenRequirement.from_dist(dist) + if exclude_editable and req.editable: + continue + installations[req.canonical_name] = req + + if requirement: + # the options that don't get turned into an InstallRequirement + # should only be emitted once, even if the same option is in multiple + # requirements files, so we need to keep track of what has been emitted + # so that we don't emit it again if it's seen again + emitted_options: Set[str] = set() + # keep track of which files a requirement is in so that we can + # give an accurate warning if a requirement appears multiple times. + req_files: Dict[str, List[str]] = collections.defaultdict(list) + for req_file_path in requirement: + with open(req_file_path) as req_file: + for line in req_file: + if ( + not line.strip() + or line.strip().startswith("#") + or line.startswith( + ( + "-r", + "--requirement", + "-f", + "--find-links", + "-i", + "--index-url", + "--pre", + "--trusted-host", + "--process-dependency-links", + "--extra-index-url", + "--use-feature", + ) + ) + ): + line = line.rstrip() + if line not in emitted_options: + emitted_options.add(line) + yield line + continue + + if line.startswith("-e") or line.startswith("--editable"): + if line.startswith("-e"): + line = line[2:].strip() + else: + line = line[len("--editable") :].strip().lstrip("=") + line_req = install_req_from_editable( + line, + isolated=isolated, + ) + else: + line_req = install_req_from_line( + COMMENT_RE.sub("", line).strip(), + isolated=isolated, + ) + + if not line_req.name: + logger.info( + "Skipping line in requirement file [%s] because " + "it's not clear what it would install: %s", + req_file_path, + line.strip(), + ) + logger.info( + " (add #egg=PackageName to the URL to avoid" + " this warning)" + ) + else: + line_req_canonical_name = canonicalize_name(line_req.name) + if line_req_canonical_name not in installations: + # either it's not installed, or it is installed + # but has been processed already + if not req_files[line_req.name]: + logger.warning( + "Requirement file [%s] contains %s, but " + "package %r is not installed", + req_file_path, + COMMENT_RE.sub("", line).strip(), + line_req.name, + ) + else: + req_files[line_req.name].append(req_file_path) + else: + yield str(installations[line_req_canonical_name]).rstrip() + del installations[line_req_canonical_name] + req_files[line_req.name].append(req_file_path) + + # Warn about requirements that were included multiple times (in a + # single requirements file or in different requirements files). + for name, files in req_files.items(): + if len(files) > 1: + logger.warning( + "Requirement %s included multiple times [%s]", + name, + ", ".join(sorted(set(files))), + ) + + yield ("## The following requirements were added by pip freeze:") + for installation in sorted(installations.values(), key=lambda x: x.name.lower()): + if installation.canonical_name not in skip: + yield str(installation).rstrip() + + +def _format_as_name_version(dist: BaseDistribution) -> str: + if isinstance(dist.version, Version): + return f"{dist.raw_name}=={dist.version}" + return f"{dist.raw_name}==={dist.version}" + + +def _get_editable_info(dist: BaseDistribution) -> _EditableInfo: + """ + Compute and return values (req, comments) for use in + FrozenRequirement.from_dist(). + """ + editable_project_location = dist.editable_project_location + assert editable_project_location + location = os.path.normcase(os.path.abspath(editable_project_location)) + + from pip._internal.vcs import RemoteNotFoundError, RemoteNotValidError, vcs + + vcs_backend = vcs.get_backend_for_dir(location) + + if vcs_backend is None: + display = _format_as_name_version(dist) + logger.debug( + 'No VCS found for editable requirement "%s" in: %r', + display, + location, + ) + return _EditableInfo( + requirement=location, + comments=[f"# Editable install with no version control ({display})"], + ) + + vcs_name = type(vcs_backend).__name__ + + try: + req = vcs_backend.get_src_requirement(location, dist.raw_name) + except RemoteNotFoundError: + display = _format_as_name_version(dist) + return _EditableInfo( + requirement=location, + comments=[f"# Editable {vcs_name} install with no remote ({display})"], + ) + except RemoteNotValidError as ex: + display = _format_as_name_version(dist) + return _EditableInfo( + requirement=location, + comments=[ + f"# Editable {vcs_name} install ({display}) with either a deleted " + f"local remote or invalid URI:", + f"# '{ex.url}'", + ], + ) + except BadCommand: + logger.warning( + "cannot determine version of editable source in %s " + "(%s command not found in path)", + location, + vcs_backend.name, + ) + return _EditableInfo(requirement=location, comments=[]) + except InstallationError as exc: + logger.warning("Error when trying to get requirement for VCS system %s", exc) + else: + return _EditableInfo(requirement=req, comments=[]) + + logger.warning("Could not determine repository location of %s", location) + + return _EditableInfo( + requirement=location, + comments=["## !! Could not determine repository location"], + ) + + +class FrozenRequirement: + def __init__( + self, + name: str, + req: str, + editable: bool, + comments: Iterable[str] = (), + ) -> None: + self.name = name + self.canonical_name = canonicalize_name(name) + self.req = req + self.editable = editable + self.comments = comments + + @classmethod + def from_dist(cls, dist: BaseDistribution) -> "FrozenRequirement": + editable = dist.editable + if editable: + req, comments = _get_editable_info(dist) + else: + comments = [] + direct_url = dist.direct_url + if direct_url: + # if PEP 610 metadata is present, use it + req = direct_url_as_pep440_direct_reference(direct_url, dist.raw_name) + else: + # name==version requirement + req = _format_as_name_version(dist) + + return cls(dist.raw_name, req, editable, comments=comments) + + def __str__(self) -> str: + req = self.req + if self.editable: + req = f"-e {req}" + return "\n".join(list(self.comments) + [str(req)]) + "\n" diff --git a/venv/Lib/site-packages/pip/_internal/operations/install/__init__.py b/venv/Lib/site-packages/pip/_internal/operations/install/__init__.py new file mode 100644 index 0000000..24d6a5d --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/operations/install/__init__.py @@ -0,0 +1,2 @@ +"""For modules related to installing packages. +""" diff --git a/venv/Lib/site-packages/pip/_internal/operations/install/__pycache__/__init__.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/operations/install/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..051397858e20c7de44904ec3afb9b2be4481c5f0 GIT binary patch literal 253 zcmYjM!D>P=5X|$U2!2Cz5`;c41t~?OqV!aHX?rOPVf(UZY)nEnQtChWA^wurenM|O zbzj?q12fAo%dm@sL0<_D7sJ;pnV+pWMKbEXW6V+Ij#T~1_hxYe&rF#CLqLXkN=qyV_pw0_ zPqa;tT&j1W?IK&huZes;x!yQ#c;9AVTqu--tj9zdi;IEb{|YdYx?;>YeVlsJzjJ5p IOJ73u1Gn8vL;wH) literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/operations/install/__pycache__/editable_legacy.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/operations/install/__pycache__/editable_legacy.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a352d8f5be049c96d19fe985756589d72e65ef5a GIT binary patch literal 1474 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 VEzfqa@#VMmTe?-eSNQ&K{{>>Fipu~1 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/operations/install/__pycache__/wheel.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/operations/install/__pycache__/wheel.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..43ad2cddb244ecf032b310e6d3cc1b35027aafe0 GIT binary patch literal 20955 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 P`zdY6(g%BfRIUF9-AG?Z literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/operations/install/editable_legacy.py b/venv/Lib/site-packages/pip/_internal/operations/install/editable_legacy.py new file mode 100644 index 0000000..bb548cd --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/operations/install/editable_legacy.py @@ -0,0 +1,47 @@ +"""Legacy editable installation process, i.e. `setup.py develop`. +""" +import logging +from typing import List, Optional, Sequence + +from pip._internal.build_env import BuildEnvironment +from pip._internal.utils.logging import indent_log +from pip._internal.utils.setuptools_build import make_setuptools_develop_args +from pip._internal.utils.subprocess import call_subprocess + +logger = logging.getLogger(__name__) + + +def install_editable( + install_options: List[str], + global_options: Sequence[str], + prefix: Optional[str], + home: Optional[str], + use_user_site: bool, + name: str, + setup_py_path: str, + isolated: bool, + build_env: BuildEnvironment, + unpacked_source_directory: str, +) -> None: + """Install a package in editable mode. Most arguments are pass-through + to setuptools. + """ + logger.info("Running setup.py develop for %s", name) + + args = make_setuptools_develop_args( + setup_py_path, + global_options=global_options, + install_options=install_options, + no_user_config=isolated, + prefix=prefix, + home=home, + use_user_site=use_user_site, + ) + + with indent_log(): + with build_env: + call_subprocess( + args, + command_desc="python setup.py develop", + cwd=unpacked_source_directory, + ) diff --git a/venv/Lib/site-packages/pip/_internal/operations/install/legacy.py b/venv/Lib/site-packages/pip/_internal/operations/install/legacy.py new file mode 100644 index 0000000..5b7ef90 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/operations/install/legacy.py @@ -0,0 +1,120 @@ +"""Legacy installation process, i.e. `setup.py install`. +""" + +import logging +import os +from distutils.util import change_root +from typing import List, Optional, Sequence + +from pip._internal.build_env import BuildEnvironment +from pip._internal.exceptions import InstallationError, LegacyInstallFailure +from pip._internal.models.scheme import Scheme +from pip._internal.utils.misc import ensure_dir +from pip._internal.utils.setuptools_build import make_setuptools_install_args +from pip._internal.utils.subprocess import runner_with_spinner_message +from pip._internal.utils.temp_dir import TempDirectory + +logger = logging.getLogger(__name__) + + +def write_installed_files_from_setuptools_record( + record_lines: List[str], + root: Optional[str], + req_description: str, +) -> None: + def prepend_root(path: str) -> str: + if root is None or not os.path.isabs(path): + return path + else: + return change_root(root, path) + + for line in record_lines: + directory = os.path.dirname(line) + if directory.endswith(".egg-info"): + egg_info_dir = prepend_root(directory) + break + else: + message = ( + "{} did not indicate that it installed an " + ".egg-info directory. Only setup.py projects " + "generating .egg-info directories are supported." + ).format(req_description) + raise InstallationError(message) + + new_lines = [] + for line in record_lines: + filename = line.strip() + if os.path.isdir(filename): + filename += os.path.sep + new_lines.append(os.path.relpath(prepend_root(filename), egg_info_dir)) + new_lines.sort() + ensure_dir(egg_info_dir) + inst_files_path = os.path.join(egg_info_dir, "installed-files.txt") + with open(inst_files_path, "w") as f: + f.write("\n".join(new_lines) + "\n") + + +def install( + install_options: List[str], + global_options: Sequence[str], + root: Optional[str], + home: Optional[str], + prefix: Optional[str], + use_user_site: bool, + pycompile: bool, + scheme: Scheme, + setup_py_path: str, + isolated: bool, + req_name: str, + build_env: BuildEnvironment, + unpacked_source_directory: str, + req_description: str, +) -> bool: + + header_dir = scheme.headers + + with TempDirectory(kind="record") as temp_dir: + try: + record_filename = os.path.join(temp_dir.path, "install-record.txt") + install_args = make_setuptools_install_args( + setup_py_path, + global_options=global_options, + install_options=install_options, + record_filename=record_filename, + root=root, + prefix=prefix, + header_dir=header_dir, + home=home, + use_user_site=use_user_site, + no_user_config=isolated, + pycompile=pycompile, + ) + + runner = runner_with_spinner_message( + f"Running setup.py install for {req_name}" + ) + with build_env: + runner( + cmd=install_args, + cwd=unpacked_source_directory, + ) + + if not os.path.exists(record_filename): + logger.debug("Record file %s not found", record_filename) + # Signal to the caller that we didn't install the new package + return False + + except Exception as e: + # Signal to the caller that we didn't install the new package + raise LegacyInstallFailure(package_details=req_name) from e + + # At this point, we have successfully installed the requirement. + + # We intentionally do not use any encoding to read the file because + # setuptools writes the file using distutils.file_util.write_file, + # which does not specify an encoding. + with open(record_filename) as f: + record_lines = f.read().splitlines() + + write_installed_files_from_setuptools_record(record_lines, root, req_description) + return True diff --git a/venv/Lib/site-packages/pip/_internal/operations/install/wheel.py b/venv/Lib/site-packages/pip/_internal/operations/install/wheel.py new file mode 100644 index 0000000..e191b13 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/operations/install/wheel.py @@ -0,0 +1,738 @@ +"""Support for installing and building the "wheel" binary package format. +""" + +import collections +import compileall +import contextlib +import csv +import importlib +import logging +import os.path +import re +import shutil +import sys +import warnings +from base64 import urlsafe_b64encode +from email.message import Message +from itertools import chain, filterfalse, starmap +from typing import ( + IO, + TYPE_CHECKING, + Any, + BinaryIO, + Callable, + Dict, + Iterable, + Iterator, + List, + NewType, + Optional, + Sequence, + Set, + Tuple, + Union, + cast, +) +from zipfile import ZipFile, ZipInfo + +from pip._vendor.distlib.scripts import ScriptMaker +from pip._vendor.distlib.util import get_export_entry +from pip._vendor.packaging.utils import canonicalize_name + +from pip._internal.exceptions import InstallationError +from pip._internal.locations import get_major_minor_version +from pip._internal.metadata import ( + BaseDistribution, + FilesystemWheel, + get_wheel_distribution, +) +from pip._internal.models.direct_url import DIRECT_URL_METADATA_NAME, DirectUrl +from pip._internal.models.scheme import SCHEME_KEYS, Scheme +from pip._internal.utils.filesystem import adjacent_tmp_file, replace +from pip._internal.utils.misc import captured_stdout, ensure_dir, hash_file, partition +from pip._internal.utils.unpacking import ( + current_umask, + is_within_directory, + set_extracted_file_to_default_mode_plus_executable, + zip_item_is_executable, +) +from pip._internal.utils.wheel import parse_wheel + +if TYPE_CHECKING: + from typing import Protocol + + class File(Protocol): + src_record_path: "RecordPath" + dest_path: str + changed: bool + + def save(self) -> None: + pass + + +logger = logging.getLogger(__name__) + +RecordPath = NewType("RecordPath", str) +InstalledCSVRow = Tuple[RecordPath, str, Union[int, str]] + + +def rehash(path: str, blocksize: int = 1 << 20) -> Tuple[str, str]: + """Return (encoded_digest, length) for path using hashlib.sha256()""" + h, length = hash_file(path, blocksize) + digest = "sha256=" + urlsafe_b64encode(h.digest()).decode("latin1").rstrip("=") + return (digest, str(length)) + + +def csv_io_kwargs(mode: str) -> Dict[str, Any]: + """Return keyword arguments to properly open a CSV file + in the given mode. + """ + return {"mode": mode, "newline": "", "encoding": "utf-8"} + + +def fix_script(path: str) -> bool: + """Replace #!python with #!/path/to/python + Return True if file was changed. + """ + # XXX RECORD hashes will need to be updated + assert os.path.isfile(path) + + with open(path, "rb") as script: + firstline = script.readline() + if not firstline.startswith(b"#!python"): + return False + exename = sys.executable.encode(sys.getfilesystemencoding()) + firstline = b"#!" + exename + os.linesep.encode("ascii") + rest = script.read() + with open(path, "wb") as script: + script.write(firstline) + script.write(rest) + return True + + +def wheel_root_is_purelib(metadata: Message) -> bool: + return metadata.get("Root-Is-Purelib", "").lower() == "true" + + +def get_entrypoints(dist: BaseDistribution) -> Tuple[Dict[str, str], Dict[str, str]]: + console_scripts = {} + gui_scripts = {} + for entry_point in dist.iter_entry_points(): + if entry_point.group == "console_scripts": + console_scripts[entry_point.name] = entry_point.value + elif entry_point.group == "gui_scripts": + gui_scripts[entry_point.name] = entry_point.value + return console_scripts, gui_scripts + + +def message_about_scripts_not_on_PATH(scripts: Sequence[str]) -> Optional[str]: + """Determine if any scripts are not on PATH and format a warning. + Returns a warning message if one or more scripts are not on PATH, + otherwise None. + """ + if not scripts: + return None + + # Group scripts by the path they were installed in + grouped_by_dir: Dict[str, Set[str]] = collections.defaultdict(set) + for destfile in scripts: + parent_dir = os.path.dirname(destfile) + script_name = os.path.basename(destfile) + grouped_by_dir[parent_dir].add(script_name) + + # We don't want to warn for directories that are on PATH. + not_warn_dirs = [ + os.path.normcase(i).rstrip(os.sep) + for i in os.environ.get("PATH", "").split(os.pathsep) + ] + # If an executable sits with sys.executable, we don't warn for it. + # This covers the case of venv invocations without activating the venv. + not_warn_dirs.append(os.path.normcase(os.path.dirname(sys.executable))) + warn_for: Dict[str, Set[str]] = { + parent_dir: scripts + for parent_dir, scripts in grouped_by_dir.items() + if os.path.normcase(parent_dir) not in not_warn_dirs + } + if not warn_for: + return None + + # Format a message + msg_lines = [] + for parent_dir, dir_scripts in warn_for.items(): + sorted_scripts: List[str] = sorted(dir_scripts) + if len(sorted_scripts) == 1: + start_text = "script {} is".format(sorted_scripts[0]) + else: + start_text = "scripts {} are".format( + ", ".join(sorted_scripts[:-1]) + " and " + sorted_scripts[-1] + ) + + msg_lines.append( + "The {} installed in '{}' which is not on PATH.".format( + start_text, parent_dir + ) + ) + + last_line_fmt = ( + "Consider adding {} to PATH or, if you prefer " + "to suppress this warning, use --no-warn-script-location." + ) + if len(msg_lines) == 1: + msg_lines.append(last_line_fmt.format("this directory")) + else: + msg_lines.append(last_line_fmt.format("these directories")) + + # Add a note if any directory starts with ~ + warn_for_tilde = any( + i[0] == "~" for i in os.environ.get("PATH", "").split(os.pathsep) if i + ) + if warn_for_tilde: + tilde_warning_msg = ( + "NOTE: The current PATH contains path(s) starting with `~`, " + "which may not be expanded by all applications." + ) + msg_lines.append(tilde_warning_msg) + + # Returns the formatted multiline message + return "\n".join(msg_lines) + + +def _normalized_outrows( + outrows: Iterable[InstalledCSVRow], +) -> List[Tuple[str, str, str]]: + """Normalize the given rows of a RECORD file. + + Items in each row are converted into str. Rows are then sorted to make + the value more predictable for tests. + + Each row is a 3-tuple (path, hash, size) and corresponds to a record of + a RECORD file (see PEP 376 and PEP 427 for details). For the rows + passed to this function, the size can be an integer as an int or string, + or the empty string. + """ + # Normally, there should only be one row per path, in which case the + # second and third elements don't come into play when sorting. + # However, in cases in the wild where a path might happen to occur twice, + # we don't want the sort operation to trigger an error (but still want + # determinism). Since the third element can be an int or string, we + # coerce each element to a string to avoid a TypeError in this case. + # For additional background, see-- + # https://github.com/pypa/pip/issues/5868 + return sorted( + (record_path, hash_, str(size)) for record_path, hash_, size in outrows + ) + + +def _record_to_fs_path(record_path: RecordPath) -> str: + return record_path + + +def _fs_to_record_path(path: str, relative_to: Optional[str] = None) -> RecordPath: + if relative_to is not None: + # On Windows, do not handle relative paths if they belong to different + # logical disks + if ( + os.path.splitdrive(path)[0].lower() + == os.path.splitdrive(relative_to)[0].lower() + ): + path = os.path.relpath(path, relative_to) + path = path.replace(os.path.sep, "/") + return cast("RecordPath", path) + + +def get_csv_rows_for_installed( + old_csv_rows: List[List[str]], + installed: Dict[RecordPath, RecordPath], + changed: Set[RecordPath], + generated: List[str], + lib_dir: str, +) -> List[InstalledCSVRow]: + """ + :param installed: A map from archive RECORD path to installation RECORD + path. + """ + installed_rows: List[InstalledCSVRow] = [] + for row in old_csv_rows: + if len(row) > 3: + logger.warning("RECORD line has more than three elements: %s", row) + old_record_path = cast("RecordPath", row[0]) + new_record_path = installed.pop(old_record_path, old_record_path) + if new_record_path in changed: + digest, length = rehash(_record_to_fs_path(new_record_path)) + else: + digest = row[1] if len(row) > 1 else "" + length = row[2] if len(row) > 2 else "" + installed_rows.append((new_record_path, digest, length)) + for f in generated: + path = _fs_to_record_path(f, lib_dir) + digest, length = rehash(f) + installed_rows.append((path, digest, length)) + for installed_record_path in installed.values(): + installed_rows.append((installed_record_path, "", "")) + return installed_rows + + +def get_console_script_specs(console: Dict[str, str]) -> List[str]: + """ + Given the mapping from entrypoint name to callable, return the relevant + console script specs. + """ + # Don't mutate caller's version + console = console.copy() + + scripts_to_generate = [] + + # Special case pip and setuptools to generate versioned wrappers + # + # The issue is that some projects (specifically, pip and setuptools) use + # code in setup.py to create "versioned" entry points - pip2.7 on Python + # 2.7, pip3.3 on Python 3.3, etc. But these entry points are baked into + # the wheel metadata at build time, and so if the wheel is installed with + # a *different* version of Python the entry points will be wrong. The + # correct fix for this is to enhance the metadata to be able to describe + # such versioned entry points, but that won't happen till Metadata 2.0 is + # available. + # In the meantime, projects using versioned entry points will either have + # incorrect versioned entry points, or they will not be able to distribute + # "universal" wheels (i.e., they will need a wheel per Python version). + # + # Because setuptools and pip are bundled with _ensurepip and virtualenv, + # we need to use universal wheels. So, as a stopgap until Metadata 2.0, we + # override the versioned entry points in the wheel and generate the + # correct ones. This code is purely a short-term measure until Metadata 2.0 + # is available. + # + # To add the level of hack in this section of code, in order to support + # ensurepip this code will look for an ``ENSUREPIP_OPTIONS`` environment + # variable which will control which version scripts get installed. + # + # ENSUREPIP_OPTIONS=altinstall + # - Only pipX.Y and easy_install-X.Y will be generated and installed + # ENSUREPIP_OPTIONS=install + # - pipX.Y, pipX, easy_install-X.Y will be generated and installed. Note + # that this option is technically if ENSUREPIP_OPTIONS is set and is + # not altinstall + # DEFAULT + # - The default behavior is to install pip, pipX, pipX.Y, easy_install + # and easy_install-X.Y. + pip_script = console.pop("pip", None) + if pip_script: + if "ENSUREPIP_OPTIONS" not in os.environ: + scripts_to_generate.append("pip = " + pip_script) + + if os.environ.get("ENSUREPIP_OPTIONS", "") != "altinstall": + scripts_to_generate.append( + "pip{} = {}".format(sys.version_info[0], pip_script) + ) + + scripts_to_generate.append(f"pip{get_major_minor_version()} = {pip_script}") + # Delete any other versioned pip entry points + pip_ep = [k for k in console if re.match(r"pip(\d(\.\d)?)?$", k)] + for k in pip_ep: + del console[k] + easy_install_script = console.pop("easy_install", None) + if easy_install_script: + if "ENSUREPIP_OPTIONS" not in os.environ: + scripts_to_generate.append("easy_install = " + easy_install_script) + + scripts_to_generate.append( + "easy_install-{} = {}".format( + get_major_minor_version(), easy_install_script + ) + ) + # Delete any other versioned easy_install entry points + easy_install_ep = [ + k for k in console if re.match(r"easy_install(-\d\.\d)?$", k) + ] + for k in easy_install_ep: + del console[k] + + # Generate the console entry points specified in the wheel + scripts_to_generate.extend(starmap("{} = {}".format, console.items())) + + return scripts_to_generate + + +class ZipBackedFile: + def __init__( + self, src_record_path: RecordPath, dest_path: str, zip_file: ZipFile + ) -> None: + self.src_record_path = src_record_path + self.dest_path = dest_path + self._zip_file = zip_file + self.changed = False + + def _getinfo(self) -> ZipInfo: + return self._zip_file.getinfo(self.src_record_path) + + def save(self) -> None: + # directory creation is lazy and after file filtering + # to ensure we don't install empty dirs; empty dirs can't be + # uninstalled. + parent_dir = os.path.dirname(self.dest_path) + ensure_dir(parent_dir) + + # When we open the output file below, any existing file is truncated + # before we start writing the new contents. This is fine in most + # cases, but can cause a segfault if pip has loaded a shared + # object (e.g. from pyopenssl through its vendored urllib3) + # Since the shared object is mmap'd an attempt to call a + # symbol in it will then cause a segfault. Unlinking the file + # allows writing of new contents while allowing the process to + # continue to use the old copy. + if os.path.exists(self.dest_path): + os.unlink(self.dest_path) + + zipinfo = self._getinfo() + + with self._zip_file.open(zipinfo) as f: + with open(self.dest_path, "wb") as dest: + shutil.copyfileobj(f, dest) + + if zip_item_is_executable(zipinfo): + set_extracted_file_to_default_mode_plus_executable(self.dest_path) + + +class ScriptFile: + def __init__(self, file: "File") -> None: + self._file = file + self.src_record_path = self._file.src_record_path + self.dest_path = self._file.dest_path + self.changed = False + + def save(self) -> None: + self._file.save() + self.changed = fix_script(self.dest_path) + + +class MissingCallableSuffix(InstallationError): + def __init__(self, entry_point: str) -> None: + super().__init__( + "Invalid script entry point: {} - A callable " + "suffix is required. Cf https://packaging.python.org/" + "specifications/entry-points/#use-for-scripts for more " + "information.".format(entry_point) + ) + + +def _raise_for_invalid_entrypoint(specification: str) -> None: + entry = get_export_entry(specification) + if entry is not None and entry.suffix is None: + raise MissingCallableSuffix(str(entry)) + + +class PipScriptMaker(ScriptMaker): + def make(self, specification: str, options: Dict[str, Any] = None) -> List[str]: + _raise_for_invalid_entrypoint(specification) + return super().make(specification, options) + + +def _install_wheel( + name: str, + wheel_zip: ZipFile, + wheel_path: str, + scheme: Scheme, + pycompile: bool = True, + warn_script_location: bool = True, + direct_url: Optional[DirectUrl] = None, + requested: bool = False, +) -> None: + """Install a wheel. + + :param name: Name of the project to install + :param wheel_zip: open ZipFile for wheel being installed + :param scheme: Distutils scheme dictating the install directories + :param req_description: String used in place of the requirement, for + logging + :param pycompile: Whether to byte-compile installed Python files + :param warn_script_location: Whether to check that scripts are installed + into a directory on PATH + :raises UnsupportedWheel: + * when the directory holds an unpacked wheel with incompatible + Wheel-Version + * when the .dist-info dir does not match the wheel + """ + info_dir, metadata = parse_wheel(wheel_zip, name) + + if wheel_root_is_purelib(metadata): + lib_dir = scheme.purelib + else: + lib_dir = scheme.platlib + + # Record details of the files moved + # installed = files copied from the wheel to the destination + # changed = files changed while installing (scripts #! line typically) + # generated = files newly generated during the install (script wrappers) + installed: Dict[RecordPath, RecordPath] = {} + changed: Set[RecordPath] = set() + generated: List[str] = [] + + def record_installed( + srcfile: RecordPath, destfile: str, modified: bool = False + ) -> None: + """Map archive RECORD paths to installation RECORD paths.""" + newpath = _fs_to_record_path(destfile, lib_dir) + installed[srcfile] = newpath + if modified: + changed.add(_fs_to_record_path(destfile)) + + def is_dir_path(path: RecordPath) -> bool: + return path.endswith("/") + + def assert_no_path_traversal(dest_dir_path: str, target_path: str) -> None: + if not is_within_directory(dest_dir_path, target_path): + message = ( + "The wheel {!r} has a file {!r} trying to install" + " outside the target directory {!r}" + ) + raise InstallationError( + message.format(wheel_path, target_path, dest_dir_path) + ) + + def root_scheme_file_maker( + zip_file: ZipFile, dest: str + ) -> Callable[[RecordPath], "File"]: + def make_root_scheme_file(record_path: RecordPath) -> "File": + normed_path = os.path.normpath(record_path) + dest_path = os.path.join(dest, normed_path) + assert_no_path_traversal(dest, dest_path) + return ZipBackedFile(record_path, dest_path, zip_file) + + return make_root_scheme_file + + def data_scheme_file_maker( + zip_file: ZipFile, scheme: Scheme + ) -> Callable[[RecordPath], "File"]: + scheme_paths = {key: getattr(scheme, key) for key in SCHEME_KEYS} + + def make_data_scheme_file(record_path: RecordPath) -> "File": + normed_path = os.path.normpath(record_path) + try: + _, scheme_key, dest_subpath = normed_path.split(os.path.sep, 2) + except ValueError: + message = ( + "Unexpected file in {}: {!r}. .data directory contents" + " should be named like: '/'." + ).format(wheel_path, record_path) + raise InstallationError(message) + + try: + scheme_path = scheme_paths[scheme_key] + except KeyError: + valid_scheme_keys = ", ".join(sorted(scheme_paths)) + message = ( + "Unknown scheme key used in {}: {} (for file {!r}). .data" + " directory contents should be in subdirectories named" + " with a valid scheme key ({})" + ).format(wheel_path, scheme_key, record_path, valid_scheme_keys) + raise InstallationError(message) + + dest_path = os.path.join(scheme_path, dest_subpath) + assert_no_path_traversal(scheme_path, dest_path) + return ZipBackedFile(record_path, dest_path, zip_file) + + return make_data_scheme_file + + def is_data_scheme_path(path: RecordPath) -> bool: + return path.split("/", 1)[0].endswith(".data") + + paths = cast(List[RecordPath], wheel_zip.namelist()) + file_paths = filterfalse(is_dir_path, paths) + root_scheme_paths, data_scheme_paths = partition(is_data_scheme_path, file_paths) + + make_root_scheme_file = root_scheme_file_maker(wheel_zip, lib_dir) + files: Iterator[File] = map(make_root_scheme_file, root_scheme_paths) + + def is_script_scheme_path(path: RecordPath) -> bool: + parts = path.split("/", 2) + return len(parts) > 2 and parts[0].endswith(".data") and parts[1] == "scripts" + + other_scheme_paths, script_scheme_paths = partition( + is_script_scheme_path, data_scheme_paths + ) + + make_data_scheme_file = data_scheme_file_maker(wheel_zip, scheme) + other_scheme_files = map(make_data_scheme_file, other_scheme_paths) + files = chain(files, other_scheme_files) + + # Get the defined entry points + distribution = get_wheel_distribution( + FilesystemWheel(wheel_path), + canonicalize_name(name), + ) + console, gui = get_entrypoints(distribution) + + def is_entrypoint_wrapper(file: "File") -> bool: + # EP, EP.exe and EP-script.py are scripts generated for + # entry point EP by setuptools + path = file.dest_path + name = os.path.basename(path) + if name.lower().endswith(".exe"): + matchname = name[:-4] + elif name.lower().endswith("-script.py"): + matchname = name[:-10] + elif name.lower().endswith(".pya"): + matchname = name[:-4] + else: + matchname = name + # Ignore setuptools-generated scripts + return matchname in console or matchname in gui + + script_scheme_files: Iterator[File] = map( + make_data_scheme_file, script_scheme_paths + ) + script_scheme_files = filterfalse(is_entrypoint_wrapper, script_scheme_files) + script_scheme_files = map(ScriptFile, script_scheme_files) + files = chain(files, script_scheme_files) + + for file in files: + file.save() + record_installed(file.src_record_path, file.dest_path, file.changed) + + def pyc_source_file_paths() -> Iterator[str]: + # We de-duplicate installation paths, since there can be overlap (e.g. + # file in .data maps to same location as file in wheel root). + # Sorting installation paths makes it easier to reproduce and debug + # issues related to permissions on existing files. + for installed_path in sorted(set(installed.values())): + full_installed_path = os.path.join(lib_dir, installed_path) + if not os.path.isfile(full_installed_path): + continue + if not full_installed_path.endswith(".py"): + continue + yield full_installed_path + + def pyc_output_path(path: str) -> str: + """Return the path the pyc file would have been written to.""" + return importlib.util.cache_from_source(path) + + # Compile all of the pyc files for the installed files + if pycompile: + with captured_stdout() as stdout: + with warnings.catch_warnings(): + warnings.filterwarnings("ignore") + for path in pyc_source_file_paths(): + success = compileall.compile_file(path, force=True, quiet=True) + if success: + pyc_path = pyc_output_path(path) + assert os.path.exists(pyc_path) + pyc_record_path = cast( + "RecordPath", pyc_path.replace(os.path.sep, "/") + ) + record_installed(pyc_record_path, pyc_path) + logger.debug(stdout.getvalue()) + + maker = PipScriptMaker(None, scheme.scripts) + + # Ensure old scripts are overwritten. + # See https://github.com/pypa/pip/issues/1800 + maker.clobber = True + + # Ensure we don't generate any variants for scripts because this is almost + # never what somebody wants. + # See https://bitbucket.org/pypa/distlib/issue/35/ + maker.variants = {""} + + # This is required because otherwise distlib creates scripts that are not + # executable. + # See https://bitbucket.org/pypa/distlib/issue/32/ + maker.set_mode = True + + # Generate the console and GUI entry points specified in the wheel + scripts_to_generate = get_console_script_specs(console) + + gui_scripts_to_generate = list(starmap("{} = {}".format, gui.items())) + + generated_console_scripts = maker.make_multiple(scripts_to_generate) + generated.extend(generated_console_scripts) + + generated.extend(maker.make_multiple(gui_scripts_to_generate, {"gui": True})) + + if warn_script_location: + msg = message_about_scripts_not_on_PATH(generated_console_scripts) + if msg is not None: + logger.warning(msg) + + generated_file_mode = 0o666 & ~current_umask() + + @contextlib.contextmanager + def _generate_file(path: str, **kwargs: Any) -> Iterator[BinaryIO]: + with adjacent_tmp_file(path, **kwargs) as f: + yield f + os.chmod(f.name, generated_file_mode) + replace(f.name, path) + + dest_info_dir = os.path.join(lib_dir, info_dir) + + # Record pip as the installer + installer_path = os.path.join(dest_info_dir, "INSTALLER") + with _generate_file(installer_path) as installer_file: + installer_file.write(b"pip\n") + generated.append(installer_path) + + # Record the PEP 610 direct URL reference + if direct_url is not None: + direct_url_path = os.path.join(dest_info_dir, DIRECT_URL_METADATA_NAME) + with _generate_file(direct_url_path) as direct_url_file: + direct_url_file.write(direct_url.to_json().encode("utf-8")) + generated.append(direct_url_path) + + # Record the REQUESTED file + if requested: + requested_path = os.path.join(dest_info_dir, "REQUESTED") + with open(requested_path, "wb"): + pass + generated.append(requested_path) + + record_text = distribution.read_text("RECORD") + record_rows = list(csv.reader(record_text.splitlines())) + + rows = get_csv_rows_for_installed( + record_rows, + installed=installed, + changed=changed, + generated=generated, + lib_dir=lib_dir, + ) + + # Record details of all files installed + record_path = os.path.join(dest_info_dir, "RECORD") + + with _generate_file(record_path, **csv_io_kwargs("w")) as record_file: + # Explicitly cast to typing.IO[str] as a workaround for the mypy error: + # "writer" has incompatible type "BinaryIO"; expected "_Writer" + writer = csv.writer(cast("IO[str]", record_file)) + writer.writerows(_normalized_outrows(rows)) + + +@contextlib.contextmanager +def req_error_context(req_description: str) -> Iterator[None]: + try: + yield + except InstallationError as e: + message = "For req: {}. {}".format(req_description, e.args[0]) + raise InstallationError(message) from e + + +def install_wheel( + name: str, + wheel_path: str, + scheme: Scheme, + req_description: str, + pycompile: bool = True, + warn_script_location: bool = True, + direct_url: Optional[DirectUrl] = None, + requested: bool = False, +) -> None: + with ZipFile(wheel_path, allowZip64=True) as z: + with req_error_context(req_description): + _install_wheel( + name=name, + wheel_zip=z, + wheel_path=wheel_path, + scheme=scheme, + pycompile=pycompile, + warn_script_location=warn_script_location, + direct_url=direct_url, + requested=requested, + ) diff --git a/venv/Lib/site-packages/pip/_internal/operations/prepare.py b/venv/Lib/site-packages/pip/_internal/operations/prepare.py new file mode 100644 index 0000000..a726f03 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/operations/prepare.py @@ -0,0 +1,642 @@ +"""Prepares a distribution for installation +""" + +# The following comment should be removed at some point in the future. +# mypy: strict-optional=False + +import logging +import mimetypes +import os +import shutil +from typing import Dict, Iterable, List, Optional + +from pip._vendor.packaging.utils import canonicalize_name + +from pip._internal.distributions import make_distribution_for_install_requirement +from pip._internal.distributions.installed import InstalledDistribution +from pip._internal.exceptions import ( + DirectoryUrlHashUnsupported, + HashMismatch, + HashUnpinned, + InstallationError, + NetworkConnectionError, + PreviousBuildDirError, + VcsHashUnsupported, +) +from pip._internal.index.package_finder import PackageFinder +from pip._internal.metadata import BaseDistribution +from pip._internal.models.link import Link +from pip._internal.models.wheel import Wheel +from pip._internal.network.download import BatchDownloader, Downloader +from pip._internal.network.lazy_wheel import ( + HTTPRangeRequestUnsupported, + dist_from_wheel_url, +) +from pip._internal.network.session import PipSession +from pip._internal.req.req_install import InstallRequirement +from pip._internal.req.req_tracker import RequirementTracker +from pip._internal.utils.filesystem import copy2_fixed +from pip._internal.utils.hashes import Hashes, MissingHashes +from pip._internal.utils.logging import indent_log +from pip._internal.utils.misc import display_path, hide_url, is_installable_dir, rmtree +from pip._internal.utils.temp_dir import TempDirectory +from pip._internal.utils.unpacking import unpack_file +from pip._internal.vcs import vcs + +logger = logging.getLogger(__name__) + + +def _get_prepared_distribution( + req: InstallRequirement, + req_tracker: RequirementTracker, + finder: PackageFinder, + build_isolation: bool, +) -> BaseDistribution: + """Prepare a distribution for installation.""" + abstract_dist = make_distribution_for_install_requirement(req) + with req_tracker.track(req): + abstract_dist.prepare_distribution_metadata(finder, build_isolation) + return abstract_dist.get_metadata_distribution() + + +def unpack_vcs_link(link: Link, location: str, verbosity: int) -> None: + vcs_backend = vcs.get_backend_for_scheme(link.scheme) + assert vcs_backend is not None + vcs_backend.unpack(location, url=hide_url(link.url), verbosity=verbosity) + + +class File: + def __init__(self, path: str, content_type: Optional[str]) -> None: + self.path = path + if content_type is None: + self.content_type = mimetypes.guess_type(path)[0] + else: + self.content_type = content_type + + +def get_http_url( + link: Link, + download: Downloader, + download_dir: Optional[str] = None, + hashes: Optional[Hashes] = None, +) -> File: + temp_dir = TempDirectory(kind="unpack", globally_managed=True) + # If a download dir is specified, is the file already downloaded there? + already_downloaded_path = None + if download_dir: + already_downloaded_path = _check_download_dir(link, download_dir, hashes) + + if already_downloaded_path: + from_path = already_downloaded_path + content_type = None + else: + # let's download to a tmp dir + from_path, content_type = download(link, temp_dir.path) + if hashes: + hashes.check_against_path(from_path) + + return File(from_path, content_type) + + +def _copy2_ignoring_special_files(src: str, dest: str) -> None: + """Copying special files is not supported, but as a convenience to users + we skip errors copying them. This supports tools that may create e.g. + socket files in the project source directory. + """ + try: + copy2_fixed(src, dest) + except shutil.SpecialFileError as e: + # SpecialFileError may be raised due to either the source or + # destination. If the destination was the cause then we would actually + # care, but since the destination directory is deleted prior to + # copy we ignore all of them assuming it is caused by the source. + logger.warning( + "Ignoring special file error '%s' encountered copying %s to %s.", + str(e), + src, + dest, + ) + + +def _copy_source_tree(source: str, target: str) -> None: + target_abspath = os.path.abspath(target) + target_basename = os.path.basename(target_abspath) + target_dirname = os.path.dirname(target_abspath) + + def ignore(d: str, names: List[str]) -> List[str]: + skipped: List[str] = [] + if d == source: + # Pulling in those directories can potentially be very slow, + # exclude the following directories if they appear in the top + # level dir (and only it). + # See discussion at https://github.com/pypa/pip/pull/6770 + skipped += [".tox", ".nox"] + if os.path.abspath(d) == target_dirname: + # Prevent an infinite recursion if the target is in source. + # This can happen when TMPDIR is set to ${PWD}/... + # and we copy PWD to TMPDIR. + skipped += [target_basename] + return skipped + + shutil.copytree( + source, + target, + ignore=ignore, + symlinks=True, + copy_function=_copy2_ignoring_special_files, + ) + + +def get_file_url( + link: Link, download_dir: Optional[str] = None, hashes: Optional[Hashes] = None +) -> File: + """Get file and optionally check its hash.""" + # If a download dir is specified, is the file already there and valid? + already_downloaded_path = None + if download_dir: + already_downloaded_path = _check_download_dir(link, download_dir, hashes) + + if already_downloaded_path: + from_path = already_downloaded_path + else: + from_path = link.file_path + + # If --require-hashes is off, `hashes` is either empty, the + # link's embedded hash, or MissingHashes; it is required to + # match. If --require-hashes is on, we are satisfied by any + # hash in `hashes` matching: a URL-based or an option-based + # one; no internet-sourced hash will be in `hashes`. + if hashes: + hashes.check_against_path(from_path) + return File(from_path, None) + + +def unpack_url( + link: Link, + location: str, + download: Downloader, + verbosity: int, + download_dir: Optional[str] = None, + hashes: Optional[Hashes] = None, +) -> Optional[File]: + """Unpack link into location, downloading if required. + + :param hashes: A Hashes object, one of whose embedded hashes must match, + or HashMismatch will be raised. If the Hashes is empty, no matches are + required, and unhashable types of requirements (like VCS ones, which + would ordinarily raise HashUnsupported) are allowed. + """ + # non-editable vcs urls + if link.is_vcs: + unpack_vcs_link(link, location, verbosity=verbosity) + return None + + # Once out-of-tree-builds are no longer supported, could potentially + # replace the below condition with `assert not link.is_existing_dir` + # - unpack_url does not need to be called for in-tree-builds. + # + # As further cleanup, _copy_source_tree and accompanying tests can + # be removed. + # + # TODO when use-deprecated=out-of-tree-build is removed + if link.is_existing_dir(): + if os.path.isdir(location): + rmtree(location) + _copy_source_tree(link.file_path, location) + return None + + # file urls + if link.is_file: + file = get_file_url(link, download_dir, hashes=hashes) + + # http urls + else: + file = get_http_url( + link, + download, + download_dir, + hashes=hashes, + ) + + # unpack the archive to the build dir location. even when only downloading + # archives, they have to be unpacked to parse dependencies, except wheels + if not link.is_wheel: + unpack_file(file.path, location, file.content_type) + + return file + + +def _check_download_dir( + link: Link, download_dir: str, hashes: Optional[Hashes] +) -> Optional[str]: + """Check download_dir for previously downloaded file with correct hash + If a correct file is found return its path else None + """ + download_path = os.path.join(download_dir, link.filename) + + if not os.path.exists(download_path): + return None + + # If already downloaded, does its hash match? + logger.info("File was already downloaded %s", download_path) + if hashes: + try: + hashes.check_against_path(download_path) + except HashMismatch: + logger.warning( + "Previously-downloaded file %s has bad hash. Re-downloading.", + download_path, + ) + os.unlink(download_path) + return None + return download_path + + +class RequirementPreparer: + """Prepares a Requirement""" + + def __init__( + self, + build_dir: str, + download_dir: Optional[str], + src_dir: str, + build_isolation: bool, + req_tracker: RequirementTracker, + session: PipSession, + progress_bar: str, + finder: PackageFinder, + require_hashes: bool, + use_user_site: bool, + lazy_wheel: bool, + verbosity: int, + in_tree_build: bool, + ) -> None: + super().__init__() + + self.src_dir = src_dir + self.build_dir = build_dir + self.req_tracker = req_tracker + self._session = session + self._download = Downloader(session, progress_bar) + self._batch_download = BatchDownloader(session, progress_bar) + self.finder = finder + + # Where still-packed archives should be written to. If None, they are + # not saved, and are deleted immediately after unpacking. + self.download_dir = download_dir + + # Is build isolation allowed? + self.build_isolation = build_isolation + + # Should hash-checking be required? + self.require_hashes = require_hashes + + # Should install in user site-packages? + self.use_user_site = use_user_site + + # Should wheels be downloaded lazily? + self.use_lazy_wheel = lazy_wheel + + # How verbose should underlying tooling be? + self.verbosity = verbosity + + # Should in-tree builds be used for local paths? + self.in_tree_build = in_tree_build + + # Memoized downloaded files, as mapping of url: path. + self._downloaded: Dict[str, str] = {} + + # Previous "header" printed for a link-based InstallRequirement + self._previous_requirement_header = ("", "") + + def _log_preparing_link(self, req: InstallRequirement) -> None: + """Provide context for the requirement being prepared.""" + if req.link.is_file and not req.original_link_is_in_wheel_cache: + message = "Processing %s" + information = str(display_path(req.link.file_path)) + else: + message = "Collecting %s" + information = str(req.req or req) + + if (message, information) != self._previous_requirement_header: + self._previous_requirement_header = (message, information) + logger.info(message, information) + + if req.original_link_is_in_wheel_cache: + with indent_log(): + logger.info("Using cached %s", req.link.filename) + + def _ensure_link_req_src_dir( + self, req: InstallRequirement, parallel_builds: bool + ) -> None: + """Ensure source_dir of a linked InstallRequirement.""" + # Since source_dir is only set for editable requirements. + if req.link.is_wheel: + # We don't need to unpack wheels, so no need for a source + # directory. + return + assert req.source_dir is None + if req.link.is_existing_dir() and self.in_tree_build: + # build local directories in-tree + req.source_dir = req.link.file_path + return + + # We always delete unpacked sdists after pip runs. + req.ensure_has_source_dir( + self.build_dir, + autodelete=True, + parallel_builds=parallel_builds, + ) + + # If a checkout exists, it's unwise to keep going. version + # inconsistencies are logged later, but do not fail the + # installation. + # FIXME: this won't upgrade when there's an existing + # package unpacked in `req.source_dir` + # TODO: this check is now probably dead code + if is_installable_dir(req.source_dir): + raise PreviousBuildDirError( + "pip can't proceed with requirements '{}' due to a" + "pre-existing build directory ({}). This is likely " + "due to a previous installation that failed . pip is " + "being responsible and not assuming it can delete this. " + "Please delete it and try again.".format(req, req.source_dir) + ) + + def _get_linked_req_hashes(self, req: InstallRequirement) -> Hashes: + # By the time this is called, the requirement's link should have + # been checked so we can tell what kind of requirements req is + # and raise some more informative errors than otherwise. + # (For example, we can raise VcsHashUnsupported for a VCS URL + # rather than HashMissing.) + if not self.require_hashes: + return req.hashes(trust_internet=True) + + # We could check these first 2 conditions inside unpack_url + # and save repetition of conditions, but then we would + # report less-useful error messages for unhashable + # requirements, complaining that there's no hash provided. + if req.link.is_vcs: + raise VcsHashUnsupported() + if req.link.is_existing_dir(): + raise DirectoryUrlHashUnsupported() + + # Unpinned packages are asking for trouble when a new version + # is uploaded. This isn't a security check, but it saves users + # a surprising hash mismatch in the future. + # file:/// URLs aren't pinnable, so don't complain about them + # not being pinned. + if req.original_link is None and not req.is_pinned: + raise HashUnpinned() + + # If known-good hashes are missing for this requirement, + # shim it with a facade object that will provoke hash + # computation and then raise a HashMissing exception + # showing the user what the hash should be. + return req.hashes(trust_internet=False) or MissingHashes() + + def _fetch_metadata_using_lazy_wheel( + self, + link: Link, + ) -> Optional[BaseDistribution]: + """Fetch metadata using lazy wheel, if possible.""" + if not self.use_lazy_wheel: + return None + if self.require_hashes: + logger.debug("Lazy wheel is not used as hash checking is required") + return None + if link.is_file or not link.is_wheel: + logger.debug( + "Lazy wheel is not used as %r does not points to a remote wheel", + link, + ) + return None + + wheel = Wheel(link.filename) + name = canonicalize_name(wheel.name) + logger.info( + "Obtaining dependency information from %s %s", + name, + wheel.version, + ) + url = link.url.split("#", 1)[0] + try: + return dist_from_wheel_url(name, url, self._session) + except HTTPRangeRequestUnsupported: + logger.debug("%s does not support range requests", url) + return None + + def _complete_partial_requirements( + self, + partially_downloaded_reqs: Iterable[InstallRequirement], + parallel_builds: bool = False, + ) -> None: + """Download any requirements which were only fetched by metadata.""" + # Download to a temporary directory. These will be copied over as + # needed for downstream 'download', 'wheel', and 'install' commands. + temp_dir = TempDirectory(kind="unpack", globally_managed=True).path + + # Map each link to the requirement that owns it. This allows us to set + # `req.local_file_path` on the appropriate requirement after passing + # all the links at once into BatchDownloader. + links_to_fully_download: Dict[Link, InstallRequirement] = {} + for req in partially_downloaded_reqs: + assert req.link + links_to_fully_download[req.link] = req + + batch_download = self._batch_download( + links_to_fully_download.keys(), + temp_dir, + ) + for link, (filepath, _) in batch_download: + logger.debug("Downloading link %s to %s", link, filepath) + req = links_to_fully_download[link] + req.local_file_path = filepath + + # This step is necessary to ensure all lazy wheels are processed + # successfully by the 'download', 'wheel', and 'install' commands. + for req in partially_downloaded_reqs: + self._prepare_linked_requirement(req, parallel_builds) + + def prepare_linked_requirement( + self, req: InstallRequirement, parallel_builds: bool = False + ) -> BaseDistribution: + """Prepare a requirement to be obtained from req.link.""" + assert req.link + link = req.link + self._log_preparing_link(req) + with indent_log(): + # Check if the relevant file is already available + # in the download directory + file_path = None + if self.download_dir is not None and link.is_wheel: + hashes = self._get_linked_req_hashes(req) + file_path = _check_download_dir(req.link, self.download_dir, hashes) + + if file_path is not None: + # The file is already available, so mark it as downloaded + self._downloaded[req.link.url] = file_path + else: + # The file is not available, attempt to fetch only metadata + wheel_dist = self._fetch_metadata_using_lazy_wheel(link) + if wheel_dist is not None: + req.needs_more_preparation = True + return wheel_dist + + # None of the optimizations worked, fully prepare the requirement + return self._prepare_linked_requirement(req, parallel_builds) + + def prepare_linked_requirements_more( + self, reqs: Iterable[InstallRequirement], parallel_builds: bool = False + ) -> None: + """Prepare linked requirements more, if needed.""" + reqs = [req for req in reqs if req.needs_more_preparation] + for req in reqs: + # Determine if any of these requirements were already downloaded. + if self.download_dir is not None and req.link.is_wheel: + hashes = self._get_linked_req_hashes(req) + file_path = _check_download_dir(req.link, self.download_dir, hashes) + if file_path is not None: + self._downloaded[req.link.url] = file_path + req.needs_more_preparation = False + + # Prepare requirements we found were already downloaded for some + # reason. The other downloads will be completed separately. + partially_downloaded_reqs: List[InstallRequirement] = [] + for req in reqs: + if req.needs_more_preparation: + partially_downloaded_reqs.append(req) + else: + self._prepare_linked_requirement(req, parallel_builds) + + # TODO: separate this part out from RequirementPreparer when the v1 + # resolver can be removed! + self._complete_partial_requirements( + partially_downloaded_reqs, + parallel_builds=parallel_builds, + ) + + def _prepare_linked_requirement( + self, req: InstallRequirement, parallel_builds: bool + ) -> BaseDistribution: + assert req.link + link = req.link + + self._ensure_link_req_src_dir(req, parallel_builds) + hashes = self._get_linked_req_hashes(req) + + if link.is_existing_dir() and self.in_tree_build: + local_file = None + elif link.url not in self._downloaded: + try: + local_file = unpack_url( + link, + req.source_dir, + self._download, + self.verbosity, + self.download_dir, + hashes, + ) + except NetworkConnectionError as exc: + raise InstallationError( + "Could not install requirement {} because of HTTP " + "error {} for URL {}".format(req, exc, link) + ) + else: + file_path = self._downloaded[link.url] + if hashes: + hashes.check_against_path(file_path) + local_file = File(file_path, content_type=None) + + # For use in later processing, + # preserve the file path on the requirement. + if local_file: + req.local_file_path = local_file.path + + dist = _get_prepared_distribution( + req, + self.req_tracker, + self.finder, + self.build_isolation, + ) + return dist + + def save_linked_requirement(self, req: InstallRequirement) -> None: + assert self.download_dir is not None + assert req.link is not None + link = req.link + if link.is_vcs or (link.is_existing_dir() and req.editable): + # Make a .zip of the source_dir we already created. + req.archive(self.download_dir) + return + + if link.is_existing_dir(): + logger.debug( + "Not copying link to destination directory " + "since it is a directory: %s", + link, + ) + return + if req.local_file_path is None: + # No distribution was downloaded for this requirement. + return + + download_location = os.path.join(self.download_dir, link.filename) + if not os.path.exists(download_location): + shutil.copy(req.local_file_path, download_location) + download_path = display_path(download_location) + logger.info("Saved %s", download_path) + + def prepare_editable_requirement( + self, + req: InstallRequirement, + ) -> BaseDistribution: + """Prepare an editable requirement.""" + assert req.editable, "cannot prepare a non-editable req as editable" + + logger.info("Obtaining %s", req) + + with indent_log(): + if self.require_hashes: + raise InstallationError( + "The editable requirement {} cannot be installed when " + "requiring hashes, because there is no single file to " + "hash.".format(req) + ) + req.ensure_has_source_dir(self.src_dir) + req.update_editable() + + dist = _get_prepared_distribution( + req, + self.req_tracker, + self.finder, + self.build_isolation, + ) + + req.check_if_exists(self.use_user_site) + + return dist + + def prepare_installed_requirement( + self, + req: InstallRequirement, + skip_reason: str, + ) -> BaseDistribution: + """Prepare an already-installed requirement.""" + assert req.satisfied_by, "req should have been satisfied but isn't" + assert skip_reason is not None, ( + "did not get skip reason skipped but req.satisfied_by " + "is set to {}".format(req.satisfied_by) + ) + logger.info( + "Requirement %s: %s (%s)", skip_reason, req, req.satisfied_by.version + ) + with indent_log(): + if self.require_hashes: + logger.debug( + "Since it is already installed, we are trusting this " + "package without checking its hash. To ensure a " + "completely repeatable environment, install into an " + "empty virtualenv." + ) + return InstalledDistribution(req).get_metadata_distribution() diff --git a/venv/Lib/site-packages/pip/_internal/pyproject.py b/venv/Lib/site-packages/pip/_internal/pyproject.py new file mode 100644 index 0000000..e183eaf --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/pyproject.py @@ -0,0 +1,168 @@ +import os +from collections import namedtuple +from typing import Any, List, Optional + +from pip._vendor import tomli +from pip._vendor.packaging.requirements import InvalidRequirement, Requirement + +from pip._internal.exceptions import ( + InstallationError, + InvalidPyProjectBuildRequires, + MissingPyProjectBuildRequires, +) + + +def _is_list_of_str(obj: Any) -> bool: + return isinstance(obj, list) and all(isinstance(item, str) for item in obj) + + +def make_pyproject_path(unpacked_source_directory: str) -> str: + return os.path.join(unpacked_source_directory, "pyproject.toml") + + +BuildSystemDetails = namedtuple( + "BuildSystemDetails", ["requires", "backend", "check", "backend_path"] +) + + +def load_pyproject_toml( + use_pep517: Optional[bool], pyproject_toml: str, setup_py: str, req_name: str +) -> Optional[BuildSystemDetails]: + """Load the pyproject.toml file. + + Parameters: + use_pep517 - Has the user requested PEP 517 processing? None + means the user hasn't explicitly specified. + pyproject_toml - Location of the project's pyproject.toml file + setup_py - Location of the project's setup.py file + req_name - The name of the requirement we're processing (for + error reporting) + + Returns: + None if we should use the legacy code path, otherwise a tuple + ( + requirements from pyproject.toml, + name of PEP 517 backend, + requirements we should check are installed after setting + up the build environment + directory paths to import the backend from (backend-path), + relative to the project root. + ) + """ + has_pyproject = os.path.isfile(pyproject_toml) + has_setup = os.path.isfile(setup_py) + + if not has_pyproject and not has_setup: + raise InstallationError( + f"{req_name} does not appear to be a Python project: " + f"neither 'setup.py' nor 'pyproject.toml' found." + ) + + if has_pyproject: + with open(pyproject_toml, encoding="utf-8") as f: + pp_toml = tomli.loads(f.read()) + build_system = pp_toml.get("build-system") + else: + build_system = None + + # The following cases must use PEP 517 + # We check for use_pep517 being non-None and falsey because that means + # the user explicitly requested --no-use-pep517. The value 0 as + # opposed to False can occur when the value is provided via an + # environment variable or config file option (due to the quirk of + # strtobool() returning an integer in pip's configuration code). + if has_pyproject and not has_setup: + if use_pep517 is not None and not use_pep517: + raise InstallationError( + "Disabling PEP 517 processing is invalid: " + "project does not have a setup.py" + ) + use_pep517 = True + elif build_system and "build-backend" in build_system: + if use_pep517 is not None and not use_pep517: + raise InstallationError( + "Disabling PEP 517 processing is invalid: " + "project specifies a build backend of {} " + "in pyproject.toml".format(build_system["build-backend"]) + ) + use_pep517 = True + + # If we haven't worked out whether to use PEP 517 yet, + # and the user hasn't explicitly stated a preference, + # we do so if the project has a pyproject.toml file. + elif use_pep517 is None: + use_pep517 = has_pyproject + + # At this point, we know whether we're going to use PEP 517. + assert use_pep517 is not None + + # If we're using the legacy code path, there is nothing further + # for us to do here. + if not use_pep517: + return None + + if build_system is None: + # Either the user has a pyproject.toml with no build-system + # section, or the user has no pyproject.toml, but has opted in + # explicitly via --use-pep517. + # In the absence of any explicit backend specification, we + # assume the setuptools backend that most closely emulates the + # traditional direct setup.py execution, and require wheel and + # a version of setuptools that supports that backend. + + build_system = { + "requires": ["setuptools>=40.8.0", "wheel"], + "build-backend": "setuptools.build_meta:__legacy__", + } + + # If we're using PEP 517, we have build system information (either + # from pyproject.toml, or defaulted by the code above). + # Note that at this point, we do not know if the user has actually + # specified a backend, though. + assert build_system is not None + + # Ensure that the build-system section in pyproject.toml conforms + # to PEP 518. + + # Specifying the build-system table but not the requires key is invalid + if "requires" not in build_system: + raise MissingPyProjectBuildRequires(package=req_name) + + # Error out if requires is not a list of strings + requires = build_system["requires"] + if not _is_list_of_str(requires): + raise InvalidPyProjectBuildRequires( + package=req_name, + reason="It is not a list of strings.", + ) + + # Each requirement must be valid as per PEP 508 + for requirement in requires: + try: + Requirement(requirement) + except InvalidRequirement as error: + raise InvalidPyProjectBuildRequires( + package=req_name, + reason=f"It contains an invalid requirement: {requirement!r}", + ) from error + + backend = build_system.get("build-backend") + backend_path = build_system.get("backend-path", []) + check: List[str] = [] + if backend is None: + # If the user didn't specify a backend, we assume they want to use + # the setuptools backend. But we can't be sure they have included + # a version of setuptools which supplies the backend, or wheel + # (which is needed by the backend) in their requirements. So we + # make a note to check that those requirements are present once + # we have set up the environment. + # This is quite a lot of work to check for a very specific case. But + # the problem is, that case is potentially quite common - projects that + # adopted PEP 518 early for the ability to specify requirements to + # execute setup.py, but never considered needing to mention the build + # tools themselves. The original PEP 518 code had a similar check (but + # implemented in a different way). + backend = "setuptools.build_meta:__legacy__" + check = ["setuptools>=40.8.0", "wheel"] + + return BuildSystemDetails(requires, backend, check, backend_path) diff --git a/venv/Lib/site-packages/pip/_internal/req/__init__.py b/venv/Lib/site-packages/pip/_internal/req/__init__.py new file mode 100644 index 0000000..70dea27 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/req/__init__.py @@ -0,0 +1,94 @@ +import collections +import logging +from typing import Iterator, List, Optional, Sequence, Tuple + +from pip._internal.utils.logging import indent_log + +from .req_file import parse_requirements +from .req_install import InstallRequirement +from .req_set import RequirementSet + +__all__ = [ + "RequirementSet", + "InstallRequirement", + "parse_requirements", + "install_given_reqs", +] + +logger = logging.getLogger(__name__) + + +class InstallationResult: + def __init__(self, name: str) -> None: + self.name = name + + def __repr__(self) -> str: + return f"InstallationResult(name={self.name!r})" + + +def _validate_requirements( + requirements: List[InstallRequirement], +) -> Iterator[Tuple[str, InstallRequirement]]: + for req in requirements: + assert req.name, f"invalid to-be-installed requirement: {req}" + yield req.name, req + + +def install_given_reqs( + requirements: List[InstallRequirement], + install_options: List[str], + global_options: Sequence[str], + root: Optional[str], + home: Optional[str], + prefix: Optional[str], + warn_script_location: bool, + use_user_site: bool, + pycompile: bool, +) -> List[InstallationResult]: + """ + Install everything in the given list. + + (to be called after having downloaded and unpacked the packages) + """ + to_install = collections.OrderedDict(_validate_requirements(requirements)) + + if to_install: + logger.info( + "Installing collected packages: %s", + ", ".join(to_install.keys()), + ) + + installed = [] + + with indent_log(): + for req_name, requirement in to_install.items(): + if requirement.should_reinstall: + logger.info("Attempting uninstall: %s", req_name) + with indent_log(): + uninstalled_pathset = requirement.uninstall(auto_confirm=True) + else: + uninstalled_pathset = None + + try: + requirement.install( + install_options, + global_options, + root=root, + home=home, + prefix=prefix, + warn_script_location=warn_script_location, + use_user_site=use_user_site, + pycompile=pycompile, + ) + except Exception: + # if install did not succeed, rollback previous uninstall + if uninstalled_pathset and not requirement.install_succeeded: + uninstalled_pathset.rollback() + raise + else: + if uninstalled_pathset and requirement.install_succeeded: + uninstalled_pathset.commit() + + installed.append(InstallationResult(req_name)) + + return installed diff --git a/venv/Lib/site-packages/pip/_internal/req/__pycache__/__init__.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/req/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..86b16eb70e4b5a9a7329a46a3c1670087ee078b2 GIT binary patch literal 2548 zcmaJCO^+Nk)^=4_S65f}d}Ik#U#tvQDA_06|1TY`3VOOG*3anh+}nhAc<=?`!3i5~ z2v_triEu<)oEN=4wn;V#?>=BWi_){~+Kid=+>v za(asl)*ga|WM|Ma{ySR8L|4+dH#4P;|8A|bs!Vd@-x7DmqD+Np-5%Gu7*G>rB^RZR z^J@Pg1pz=>uM??6Ea7Y>MFG1Csqd6ZCwczfuVkS1m(W{64_t{Jmlzb;0btg%DO9&ZEIvL^crr4lsoJ)y?A z-Wf3CmPsLuCxsr%GG!ojK5&imO_&O`Y-mGbh&FhT?tD#UA805+iG0r@UlX|ww4XkH z^ZMw0C8Qc9Wtpha8+Cmn(aGp$l_vSd@NAVj|P@?Q@#m8uEu zjpD3?$Uq=Q;D%8QXr|+MyFN1h9JzpcS%vB3(#+#a#%<5f4X9j!qbY`LK5&h$w6>ug z9BexzUoy_Va=<=kXL9jTkyp`Iul_^_aurxW?i&28$y0C+P}EO~TE_7vV1KUP^xVKh z9uytNCWzyr;^Q3GVI1EXC;4p0QCi9kybujvx)oh6@oL!va2}>|0r+&)u@neV2u@ri z=%e01Cn8IVyxRa8a)W&G>@jWVAyJqAj^3ePlCRha{oK+Ty2m~sl-zM`Hn5$^m8`s* zF?*&Zj#4y+?7?OjeAgGp4U?BWuKXidx?ALLTXZtlW>XGSUYkvJEfFp#yIR_UKhzMY|$`c9BC4C40~d zqJ!ivvheC&nO6x%ddZ`C6R~ozpCtQ24XlvKQ?nb9Ev-OQs)1{M=z4TTP1uXkCpY+TOL33qQp*AA1huHv*R_cB@R3_KY@)a6qMo<{Htf@cw20WerM-PujhWtHi^ zE4h$@-^fyJv(|X&@DX7OQcZ3IX0Rz66tZ!6U|lG%hl2yriy0$){bRZ_7tMfvP`=AVTm* zhM54ou()@&u$PECws)ECQl*=73vC6D>qH+Yp?_EF63YjDrv3(itoE5pUCL-AA=xd0qpw-*)?Y64L0TTAk4JU%MefF>7yF{5?h>f5MZN| zEd_E=}R+MaPwL*j#B@g8;o`%0sob5GdE+q98_2I6~e+Hnk73+=nJ zFZ4|tZ21^oH$Z?bT0V{ddzf)|t17peFL`It(2f7f^f7o1-z(dh!Crcqg)9W$gv@UT TPQT;P{?8%6U%#oBydQo6UmlDj literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/req/__pycache__/constructors.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/req/__pycache__/constructors.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1fc065ebaf100086a620eb25d06c5494b2d1bc2a GIT binary patch literal 12093 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 S?B2gCZKt0~A4w0V5B?8r;ZQRG literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/req/__pycache__/req_install.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/req/__pycache__/req_install.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1fd8cf0a38b8a568d16ddbf6b0d419d25b853182 GIT binary patch literal 22109 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 X*}>nkX&X+*ww9Lw{eN|?=+gZ+!we{m literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/provider.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/provider.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..04542b99dea7d31ba8c999c151fe20c82ba6176b GIT binary patch literal 7626 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 H&GY{U-p|2P literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/reporter.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/reporter.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..774e886695965770c693791a5af62fa062790536 GIT binary patch literal 3261 zcmb7GOK%iM5T4gQyt_6A%u5iZf$-P>>qLq|f=C20N`!gul^UERU_e9OZ3;^Xt{f6Q6d zpCrtF9)uhCsT_n`+>Wip?%Ou;PV6LZ-!;4&dr7TdOX~f)k-fN)H2Y2PHC~VBl2*T! zwEJz_60Ybxv-|TuSiHfT&n?~*&1Y_Z0rDJgL2eoO0B_&7x}CS!)#}E9iN~Wz zibSM3q&;Ro7s3tv)TbcA>f7AvJKW~ZOPjmgd+zmJ;X$swbaEBL8XAllOQGke?eX%Fne-Ip#Tms_yut&V@sqnt&G#aZ?! zN(U^^EI}xuJQnPUkSfYj#j*|dYaWD;f`RbUAQ4ZQ&KMW)K8aGnHiuC-oNAM?FiY}4 zN9(Y$8R;R*^iW79ccP+t?7`3|j$+Pq@JO(L%*3KM{>#i@62pWj&Qhd;>0ywvks1YY zkNupDSP~6}nx#Tuea3Q`J&Cx0mH@C^q+F!o7PeGb3^z&`N=qaVQV6HC45CzHmke5b z6bdFssg4rSWA}w%L#=alZFw2t>E&B_(2KI=%|NC=q?Xqa3#<!3dd8L#(~M z!M1>IGe|X=4%Sg5Km~VT{xWb1rPzv=F}uW8dRlWCHq9g(K^`j3?M>9 z(}#AXeV^P==G@yY&#B?>@A1;zozm@172n{{gwsPKJ6INy@6(UUxQ?GG<$GYZt%ugO z{m`yiC(tUcTCR1y8arVS2Zu3P~BFeHF#IX)hc#BO!!$zN$t4hT)xd)pt!RvAM@< zXi=W1L9U}^QQP(Ubx{)yjLf}sd5gC((ll}h8uNSs@|aEH)T-(z{T@0GiTL7c2SLmLv&CLW5&g%H^bmyMZfz*IoQ-<;}xj!9*T-5!6mpFfpV+$^;S-RzgW2ZYvFy`HMHM7h0F-oSZs4^CgA zI{C$OvMbMFQP(Le_X7Ccco(L4%Qas>Ws3Ujdr_DA=x$`SsKE^Sh&kaD*6Bz5e>%V_ z2hh|J<_i90X3S2!aA&;e!tQQYI3toU)kcJj#XTMBgA%Y)D5cFkf!_~p zz0|!ngY)EjaCY6IJ#)Jj^*oR$@%+x=r&d|qXRDY8yo~wI)eZcY zSyeofuwRBLd4s^qF#ze~`Z_+$Y?Hj;}V)uYNO?J)@ISW!W ze4l5b@5}Qvbb!c3B6JERJxJvxB6CE{_0c1a5&4YBPIe7vE|O0$L28OxP!sppg1hJ* zn*1cqu67rTc9_Mn2^R5($-PpXGRZ`DoQVlfB794v!A7 zWt&%$UI&G@j>mWj*1$F%n>I{0oY{Xr*hTYtd3SzGPi93;zGHXnMW^E|I!$-+%)j`^ BEP((3 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/requirements.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/requirements.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3b2bd622e090042c91fd71d176ac4f918a2f3c21 GIT binary patch literal 7570 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/resolver.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/resolver.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..931c24574140252091ffcda9b555c3268f0493d3 GIT binary patch literal 8169 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 str: + if not extras: + return project + canonical_extras = sorted(canonicalize_name(e) for e in extras) + return "{}[{}]".format(project, ",".join(canonical_extras)) + + +class Constraint: + def __init__( + self, specifier: SpecifierSet, hashes: Hashes, links: FrozenSet[Link] + ) -> None: + self.specifier = specifier + self.hashes = hashes + self.links = links + + @classmethod + def empty(cls) -> "Constraint": + return Constraint(SpecifierSet(), Hashes(), frozenset()) + + @classmethod + def from_ireq(cls, ireq: InstallRequirement) -> "Constraint": + links = frozenset([ireq.link]) if ireq.link else frozenset() + return Constraint(ireq.specifier, ireq.hashes(trust_internet=False), links) + + def __bool__(self) -> bool: + return bool(self.specifier) or bool(self.hashes) or bool(self.links) + + def __and__(self, other: InstallRequirement) -> "Constraint": + if not isinstance(other, InstallRequirement): + return NotImplemented + specifier = self.specifier & other.specifier + hashes = self.hashes & other.hashes(trust_internet=False) + links = self.links + if other.link: + links = links.union([other.link]) + return Constraint(specifier, hashes, links) + + def is_satisfied_by(self, candidate: "Candidate") -> bool: + # Reject if there are any mismatched URL constraints on this package. + if self.links and not all(_match_link(link, candidate) for link in self.links): + return False + # We can safely always allow prereleases here since PackageFinder + # already implements the prerelease logic, and would have filtered out + # prerelease candidates if the user does not expect them. + return self.specifier.contains(candidate.version, prereleases=True) + + +class Requirement: + @property + def project_name(self) -> NormalizedName: + """The "project name" of a requirement. + + This is different from ``name`` if this requirement contains extras, + in which case ``name`` would contain the ``[...]`` part, while this + refers to the name of the project. + """ + raise NotImplementedError("Subclass should override") + + @property + def name(self) -> str: + """The name identifying this requirement in the resolver. + + This is different from ``project_name`` if this requirement contains + extras, where ``project_name`` would not contain the ``[...]`` part. + """ + raise NotImplementedError("Subclass should override") + + def is_satisfied_by(self, candidate: "Candidate") -> bool: + return False + + def get_candidate_lookup(self) -> CandidateLookup: + raise NotImplementedError("Subclass should override") + + def format_for_error(self) -> str: + raise NotImplementedError("Subclass should override") + + +def _match_link(link: Link, candidate: "Candidate") -> bool: + if candidate.source_link: + return links_equivalent(link, candidate.source_link) + return False + + +class Candidate: + @property + def project_name(self) -> NormalizedName: + """The "project name" of the candidate. + + This is different from ``name`` if this candidate contains extras, + in which case ``name`` would contain the ``[...]`` part, while this + refers to the name of the project. + """ + raise NotImplementedError("Override in subclass") + + @property + def name(self) -> str: + """The name identifying this candidate in the resolver. + + This is different from ``project_name`` if this candidate contains + extras, where ``project_name`` would not contain the ``[...]`` part. + """ + raise NotImplementedError("Override in subclass") + + @property + def version(self) -> CandidateVersion: + raise NotImplementedError("Override in subclass") + + @property + def is_installed(self) -> bool: + raise NotImplementedError("Override in subclass") + + @property + def is_editable(self) -> bool: + raise NotImplementedError("Override in subclass") + + @property + def source_link(self) -> Optional[Link]: + raise NotImplementedError("Override in subclass") + + def iter_dependencies(self, with_requires: bool) -> Iterable[Optional[Requirement]]: + raise NotImplementedError("Override in subclass") + + def get_install_requirement(self) -> Optional[InstallRequirement]: + raise NotImplementedError("Override in subclass") + + def format_for_error(self) -> str: + raise NotImplementedError("Subclass should override") diff --git a/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/candidates.py b/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/candidates.py new file mode 100644 index 0000000..9b8450e --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/candidates.py @@ -0,0 +1,547 @@ +import logging +import sys +from typing import TYPE_CHECKING, Any, FrozenSet, Iterable, Optional, Tuple, Union, cast + +from pip._vendor.packaging.utils import NormalizedName, canonicalize_name +from pip._vendor.packaging.version import Version + +from pip._internal.exceptions import ( + HashError, + InstallationSubprocessError, + MetadataInconsistent, +) +from pip._internal.metadata import BaseDistribution +from pip._internal.models.link import Link, links_equivalent +from pip._internal.models.wheel import Wheel +from pip._internal.req.constructors import ( + install_req_from_editable, + install_req_from_line, +) +from pip._internal.req.req_install import InstallRequirement +from pip._internal.utils.misc import normalize_version_info + +from .base import Candidate, CandidateVersion, Requirement, format_name + +if TYPE_CHECKING: + from .factory import Factory + +logger = logging.getLogger(__name__) + +BaseCandidate = Union[ + "AlreadyInstalledCandidate", + "EditableCandidate", + "LinkCandidate", +] + +# Avoid conflicting with the PyPI package "Python". +REQUIRES_PYTHON_IDENTIFIER = cast(NormalizedName, "") + + +def as_base_candidate(candidate: Candidate) -> Optional[BaseCandidate]: + """The runtime version of BaseCandidate.""" + base_candidate_classes = ( + AlreadyInstalledCandidate, + EditableCandidate, + LinkCandidate, + ) + if isinstance(candidate, base_candidate_classes): + return candidate + return None + + +def make_install_req_from_link( + link: Link, template: InstallRequirement +) -> InstallRequirement: + assert not template.editable, "template is editable" + if template.req: + line = str(template.req) + else: + line = link.url + ireq = install_req_from_line( + line, + user_supplied=template.user_supplied, + comes_from=template.comes_from, + use_pep517=template.use_pep517, + isolated=template.isolated, + constraint=template.constraint, + options=dict( + install_options=template.install_options, + global_options=template.global_options, + hashes=template.hash_options, + ), + ) + ireq.original_link = template.original_link + ireq.link = link + return ireq + + +def make_install_req_from_editable( + link: Link, template: InstallRequirement +) -> InstallRequirement: + assert template.editable, "template not editable" + return install_req_from_editable( + link.url, + user_supplied=template.user_supplied, + comes_from=template.comes_from, + use_pep517=template.use_pep517, + isolated=template.isolated, + constraint=template.constraint, + permit_editable_wheels=template.permit_editable_wheels, + options=dict( + install_options=template.install_options, + global_options=template.global_options, + hashes=template.hash_options, + ), + ) + + +def _make_install_req_from_dist( + dist: BaseDistribution, template: InstallRequirement +) -> InstallRequirement: + if template.req: + line = str(template.req) + elif template.link: + line = f"{dist.canonical_name} @ {template.link.url}" + else: + line = f"{dist.canonical_name}=={dist.version}" + ireq = install_req_from_line( + line, + user_supplied=template.user_supplied, + comes_from=template.comes_from, + use_pep517=template.use_pep517, + isolated=template.isolated, + constraint=template.constraint, + options=dict( + install_options=template.install_options, + global_options=template.global_options, + hashes=template.hash_options, + ), + ) + ireq.satisfied_by = dist + return ireq + + +class _InstallRequirementBackedCandidate(Candidate): + """A candidate backed by an ``InstallRequirement``. + + This represents a package request with the target not being already + in the environment, and needs to be fetched and installed. The backing + ``InstallRequirement`` is responsible for most of the leg work; this + class exposes appropriate information to the resolver. + + :param link: The link passed to the ``InstallRequirement``. The backing + ``InstallRequirement`` will use this link to fetch the distribution. + :param source_link: The link this candidate "originates" from. This is + different from ``link`` when the link is found in the wheel cache. + ``link`` would point to the wheel cache, while this points to the + found remote link (e.g. from pypi.org). + """ + + dist: BaseDistribution + is_installed = False + + def __init__( + self, + link: Link, + source_link: Link, + ireq: InstallRequirement, + factory: "Factory", + name: Optional[NormalizedName] = None, + version: Optional[CandidateVersion] = None, + ) -> None: + self._link = link + self._source_link = source_link + self._factory = factory + self._ireq = ireq + self._name = name + self._version = version + self.dist = self._prepare() + + def __str__(self) -> str: + return f"{self.name} {self.version}" + + def __repr__(self) -> str: + return "{class_name}({link!r})".format( + class_name=self.__class__.__name__, + link=str(self._link), + ) + + def __hash__(self) -> int: + return hash((self.__class__, self._link)) + + def __eq__(self, other: Any) -> bool: + if isinstance(other, self.__class__): + return links_equivalent(self._link, other._link) + return False + + @property + def source_link(self) -> Optional[Link]: + return self._source_link + + @property + def project_name(self) -> NormalizedName: + """The normalised name of the project the candidate refers to""" + if self._name is None: + self._name = self.dist.canonical_name + return self._name + + @property + def name(self) -> str: + return self.project_name + + @property + def version(self) -> CandidateVersion: + if self._version is None: + self._version = self.dist.version + return self._version + + def format_for_error(self) -> str: + return "{} {} (from {})".format( + self.name, + self.version, + self._link.file_path if self._link.is_file else self._link, + ) + + def _prepare_distribution(self) -> BaseDistribution: + raise NotImplementedError("Override in subclass") + + def _check_metadata_consistency(self, dist: BaseDistribution) -> None: + """Check for consistency of project name and version of dist.""" + if self._name is not None and self._name != dist.canonical_name: + raise MetadataInconsistent( + self._ireq, + "name", + self._name, + dist.canonical_name, + ) + if self._version is not None and self._version != dist.version: + raise MetadataInconsistent( + self._ireq, + "version", + str(self._version), + str(dist.version), + ) + + def _prepare(self) -> BaseDistribution: + try: + dist = self._prepare_distribution() + except HashError as e: + # Provide HashError the underlying ireq that caused it. This + # provides context for the resulting error message to show the + # offending line to the user. + e.req = self._ireq + raise + except InstallationSubprocessError as exc: + # The output has been presented already, so don't duplicate it. + exc.context = "See above for output." + raise + + self._check_metadata_consistency(dist) + return dist + + def iter_dependencies(self, with_requires: bool) -> Iterable[Optional[Requirement]]: + requires = self.dist.iter_dependencies() if with_requires else () + for r in requires: + yield self._factory.make_requirement_from_spec(str(r), self._ireq) + yield self._factory.make_requires_python_requirement(self.dist.requires_python) + + def get_install_requirement(self) -> Optional[InstallRequirement]: + return self._ireq + + +class LinkCandidate(_InstallRequirementBackedCandidate): + is_editable = False + + def __init__( + self, + link: Link, + template: InstallRequirement, + factory: "Factory", + name: Optional[NormalizedName] = None, + version: Optional[CandidateVersion] = None, + ) -> None: + source_link = link + cache_entry = factory.get_wheel_cache_entry(link, name) + if cache_entry is not None: + logger.debug("Using cached wheel link: %s", cache_entry.link) + link = cache_entry.link + ireq = make_install_req_from_link(link, template) + assert ireq.link == link + if ireq.link.is_wheel and not ireq.link.is_file: + wheel = Wheel(ireq.link.filename) + wheel_name = canonicalize_name(wheel.name) + assert name == wheel_name, f"{name!r} != {wheel_name!r} for wheel" + # Version may not be present for PEP 508 direct URLs + if version is not None: + wheel_version = Version(wheel.version) + assert version == wheel_version, "{!r} != {!r} for wheel {}".format( + version, wheel_version, name + ) + + if ( + cache_entry is not None + and cache_entry.persistent + and template.link is template.original_link + ): + ireq.original_link_is_in_wheel_cache = True + + super().__init__( + link=link, + source_link=source_link, + ireq=ireq, + factory=factory, + name=name, + version=version, + ) + + def _prepare_distribution(self) -> BaseDistribution: + preparer = self._factory.preparer + return preparer.prepare_linked_requirement(self._ireq, parallel_builds=True) + + +class EditableCandidate(_InstallRequirementBackedCandidate): + is_editable = True + + def __init__( + self, + link: Link, + template: InstallRequirement, + factory: "Factory", + name: Optional[NormalizedName] = None, + version: Optional[CandidateVersion] = None, + ) -> None: + super().__init__( + link=link, + source_link=link, + ireq=make_install_req_from_editable(link, template), + factory=factory, + name=name, + version=version, + ) + + def _prepare_distribution(self) -> BaseDistribution: + return self._factory.preparer.prepare_editable_requirement(self._ireq) + + +class AlreadyInstalledCandidate(Candidate): + is_installed = True + source_link = None + + def __init__( + self, + dist: BaseDistribution, + template: InstallRequirement, + factory: "Factory", + ) -> None: + self.dist = dist + self._ireq = _make_install_req_from_dist(dist, template) + self._factory = factory + + # This is just logging some messages, so we can do it eagerly. + # The returned dist would be exactly the same as self.dist because we + # set satisfied_by in _make_install_req_from_dist. + # TODO: Supply reason based on force_reinstall and upgrade_strategy. + skip_reason = "already satisfied" + factory.preparer.prepare_installed_requirement(self._ireq, skip_reason) + + def __str__(self) -> str: + return str(self.dist) + + def __repr__(self) -> str: + return "{class_name}({distribution!r})".format( + class_name=self.__class__.__name__, + distribution=self.dist, + ) + + def __hash__(self) -> int: + return hash((self.__class__, self.name, self.version)) + + def __eq__(self, other: Any) -> bool: + if isinstance(other, self.__class__): + return self.name == other.name and self.version == other.version + return False + + @property + def project_name(self) -> NormalizedName: + return self.dist.canonical_name + + @property + def name(self) -> str: + return self.project_name + + @property + def version(self) -> CandidateVersion: + return self.dist.version + + @property + def is_editable(self) -> bool: + return self.dist.editable + + def format_for_error(self) -> str: + return f"{self.name} {self.version} (Installed)" + + def iter_dependencies(self, with_requires: bool) -> Iterable[Optional[Requirement]]: + if not with_requires: + return + for r in self.dist.iter_dependencies(): + yield self._factory.make_requirement_from_spec(str(r), self._ireq) + + def get_install_requirement(self) -> Optional[InstallRequirement]: + return None + + +class ExtrasCandidate(Candidate): + """A candidate that has 'extras', indicating additional dependencies. + + Requirements can be for a project with dependencies, something like + foo[extra]. The extras don't affect the project/version being installed + directly, but indicate that we need additional dependencies. We model that + by having an artificial ExtrasCandidate that wraps the "base" candidate. + + The ExtrasCandidate differs from the base in the following ways: + + 1. It has a unique name, of the form foo[extra]. This causes the resolver + to treat it as a separate node in the dependency graph. + 2. When we're getting the candidate's dependencies, + a) We specify that we want the extra dependencies as well. + b) We add a dependency on the base candidate. + See below for why this is needed. + 3. We return None for the underlying InstallRequirement, as the base + candidate will provide it, and we don't want to end up with duplicates. + + The dependency on the base candidate is needed so that the resolver can't + decide that it should recommend foo[extra1] version 1.0 and foo[extra2] + version 2.0. Having those candidates depend on foo=1.0 and foo=2.0 + respectively forces the resolver to recognise that this is a conflict. + """ + + def __init__( + self, + base: BaseCandidate, + extras: FrozenSet[str], + ) -> None: + self.base = base + self.extras = extras + + def __str__(self) -> str: + name, rest = str(self.base).split(" ", 1) + return "{}[{}] {}".format(name, ",".join(self.extras), rest) + + def __repr__(self) -> str: + return "{class_name}(base={base!r}, extras={extras!r})".format( + class_name=self.__class__.__name__, + base=self.base, + extras=self.extras, + ) + + def __hash__(self) -> int: + return hash((self.base, self.extras)) + + def __eq__(self, other: Any) -> bool: + if isinstance(other, self.__class__): + return self.base == other.base and self.extras == other.extras + return False + + @property + def project_name(self) -> NormalizedName: + return self.base.project_name + + @property + def name(self) -> str: + """The normalised name of the project the candidate refers to""" + return format_name(self.base.project_name, self.extras) + + @property + def version(self) -> CandidateVersion: + return self.base.version + + def format_for_error(self) -> str: + return "{} [{}]".format( + self.base.format_for_error(), ", ".join(sorted(self.extras)) + ) + + @property + def is_installed(self) -> bool: + return self.base.is_installed + + @property + def is_editable(self) -> bool: + return self.base.is_editable + + @property + def source_link(self) -> Optional[Link]: + return self.base.source_link + + def iter_dependencies(self, with_requires: bool) -> Iterable[Optional[Requirement]]: + factory = self.base._factory + + # Add a dependency on the exact base + # (See note 2b in the class docstring) + yield factory.make_requirement_from_candidate(self.base) + if not with_requires: + return + + # The user may have specified extras that the candidate doesn't + # support. We ignore any unsupported extras here. + valid_extras = self.extras.intersection(self.base.dist.iter_provided_extras()) + invalid_extras = self.extras.difference(self.base.dist.iter_provided_extras()) + for extra in sorted(invalid_extras): + logger.warning( + "%s %s does not provide the extra '%s'", + self.base.name, + self.version, + extra, + ) + + for r in self.base.dist.iter_dependencies(valid_extras): + requirement = factory.make_requirement_from_spec( + str(r), self.base._ireq, valid_extras + ) + if requirement: + yield requirement + + def get_install_requirement(self) -> Optional[InstallRequirement]: + # We don't return anything here, because we always + # depend on the base candidate, and we'll get the + # install requirement from that. + return None + + +class RequiresPythonCandidate(Candidate): + is_installed = False + source_link = None + + def __init__(self, py_version_info: Optional[Tuple[int, ...]]) -> None: + if py_version_info is not None: + version_info = normalize_version_info(py_version_info) + else: + version_info = sys.version_info[:3] + self._version = Version(".".join(str(c) for c in version_info)) + + # We don't need to implement __eq__() and __ne__() since there is always + # only one RequiresPythonCandidate in a resolution, i.e. the host Python. + # The built-in object.__eq__() and object.__ne__() do exactly what we want. + + def __str__(self) -> str: + return f"Python {self._version}" + + @property + def project_name(self) -> NormalizedName: + return REQUIRES_PYTHON_IDENTIFIER + + @property + def name(self) -> str: + return REQUIRES_PYTHON_IDENTIFIER + + @property + def version(self) -> CandidateVersion: + return self._version + + def format_for_error(self) -> str: + return f"Python {self.version}" + + def iter_dependencies(self, with_requires: bool) -> Iterable[Optional[Requirement]]: + return () + + def get_install_requirement(self) -> Optional[InstallRequirement]: + return None diff --git a/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/factory.py b/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/factory.py new file mode 100644 index 0000000..261d8d5 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/factory.py @@ -0,0 +1,739 @@ +import contextlib +import functools +import logging +from typing import ( + TYPE_CHECKING, + Dict, + FrozenSet, + Iterable, + Iterator, + List, + Mapping, + NamedTuple, + Optional, + Sequence, + Set, + Tuple, + TypeVar, + cast, +) + +from pip._vendor.packaging.requirements import InvalidRequirement +from pip._vendor.packaging.specifiers import SpecifierSet +from pip._vendor.packaging.utils import NormalizedName, canonicalize_name +from pip._vendor.resolvelib import ResolutionImpossible + +from pip._internal.cache import CacheEntry, WheelCache +from pip._internal.exceptions import ( + DistributionNotFound, + InstallationError, + InstallationSubprocessError, + MetadataInconsistent, + UnsupportedPythonVersion, + UnsupportedWheel, +) +from pip._internal.index.package_finder import PackageFinder +from pip._internal.metadata import BaseDistribution, get_default_environment +from pip._internal.models.link import Link +from pip._internal.models.wheel import Wheel +from pip._internal.operations.prepare import RequirementPreparer +from pip._internal.req.constructors import install_req_from_link_and_ireq +from pip._internal.req.req_install import ( + InstallRequirement, + check_invalid_constraint_type, +) +from pip._internal.resolution.base import InstallRequirementProvider +from pip._internal.utils.compatibility_tags import get_supported +from pip._internal.utils.hashes import Hashes +from pip._internal.utils.packaging import get_requirement +from pip._internal.utils.virtualenv import running_under_virtualenv + +from .base import Candidate, CandidateVersion, Constraint, Requirement +from .candidates import ( + AlreadyInstalledCandidate, + BaseCandidate, + EditableCandidate, + ExtrasCandidate, + LinkCandidate, + RequiresPythonCandidate, + as_base_candidate, +) +from .found_candidates import FoundCandidates, IndexCandidateInfo +from .requirements import ( + ExplicitRequirement, + RequiresPythonRequirement, + SpecifierRequirement, + UnsatisfiableRequirement, +) + +if TYPE_CHECKING: + from typing import Protocol + + class ConflictCause(Protocol): + requirement: RequiresPythonRequirement + parent: Candidate + + +logger = logging.getLogger(__name__) + +C = TypeVar("C") +Cache = Dict[Link, C] + + +class CollectedRootRequirements(NamedTuple): + requirements: List[Requirement] + constraints: Dict[str, Constraint] + user_requested: Dict[str, int] + + +class Factory: + def __init__( + self, + finder: PackageFinder, + preparer: RequirementPreparer, + make_install_req: InstallRequirementProvider, + wheel_cache: Optional[WheelCache], + use_user_site: bool, + force_reinstall: bool, + ignore_installed: bool, + ignore_requires_python: bool, + suppress_build_failures: bool, + py_version_info: Optional[Tuple[int, ...]] = None, + ) -> None: + self._finder = finder + self.preparer = preparer + self._wheel_cache = wheel_cache + self._python_candidate = RequiresPythonCandidate(py_version_info) + self._make_install_req_from_spec = make_install_req + self._use_user_site = use_user_site + self._force_reinstall = force_reinstall + self._ignore_requires_python = ignore_requires_python + self._suppress_build_failures = suppress_build_failures + + self._build_failures: Cache[InstallationError] = {} + self._link_candidate_cache: Cache[LinkCandidate] = {} + self._editable_candidate_cache: Cache[EditableCandidate] = {} + self._installed_candidate_cache: Dict[str, AlreadyInstalledCandidate] = {} + self._extras_candidate_cache: Dict[ + Tuple[int, FrozenSet[str]], ExtrasCandidate + ] = {} + + if not ignore_installed: + env = get_default_environment() + self._installed_dists = { + dist.canonical_name: dist + for dist in env.iter_installed_distributions(local_only=False) + } + else: + self._installed_dists = {} + + @property + def force_reinstall(self) -> bool: + return self._force_reinstall + + def _fail_if_link_is_unsupported_wheel(self, link: Link) -> None: + if not link.is_wheel: + return + wheel = Wheel(link.filename) + if wheel.supported(self._finder.target_python.get_tags()): + return + msg = f"{link.filename} is not a supported wheel on this platform." + raise UnsupportedWheel(msg) + + def _make_extras_candidate( + self, base: BaseCandidate, extras: FrozenSet[str] + ) -> ExtrasCandidate: + cache_key = (id(base), extras) + try: + candidate = self._extras_candidate_cache[cache_key] + except KeyError: + candidate = ExtrasCandidate(base, extras) + self._extras_candidate_cache[cache_key] = candidate + return candidate + + def _make_candidate_from_dist( + self, + dist: BaseDistribution, + extras: FrozenSet[str], + template: InstallRequirement, + ) -> Candidate: + try: + base = self._installed_candidate_cache[dist.canonical_name] + except KeyError: + base = AlreadyInstalledCandidate(dist, template, factory=self) + self._installed_candidate_cache[dist.canonical_name] = base + if not extras: + return base + return self._make_extras_candidate(base, extras) + + def _make_candidate_from_link( + self, + link: Link, + extras: FrozenSet[str], + template: InstallRequirement, + name: Optional[NormalizedName], + version: Optional[CandidateVersion], + ) -> Optional[Candidate]: + # TODO: Check already installed candidate, and use it if the link and + # editable flag match. + + if link in self._build_failures: + # We already tried this candidate before, and it does not build. + # Don't bother trying again. + return None + + if template.editable: + if link not in self._editable_candidate_cache: + try: + self._editable_candidate_cache[link] = EditableCandidate( + link, + template, + factory=self, + name=name, + version=version, + ) + except MetadataInconsistent as e: + logger.info( + "Discarding [blue underline]%s[/]: [yellow]%s[reset]", + link, + e, + extra={"markup": True}, + ) + self._build_failures[link] = e + return None + except InstallationSubprocessError as e: + if not self._suppress_build_failures: + raise + logger.warning("Discarding %s due to build failure: %s", link, e) + self._build_failures[link] = e + return None + + base: BaseCandidate = self._editable_candidate_cache[link] + else: + if link not in self._link_candidate_cache: + try: + self._link_candidate_cache[link] = LinkCandidate( + link, + template, + factory=self, + name=name, + version=version, + ) + except MetadataInconsistent as e: + logger.info( + "Discarding [blue underline]%s[/]: [yellow]%s[reset]", + link, + e, + extra={"markup": True}, + ) + self._build_failures[link] = e + return None + except InstallationSubprocessError as e: + if not self._suppress_build_failures: + raise + logger.warning("Discarding %s due to build failure: %s", link, e) + self._build_failures[link] = e + return None + base = self._link_candidate_cache[link] + + if not extras: + return base + return self._make_extras_candidate(base, extras) + + def _iter_found_candidates( + self, + ireqs: Sequence[InstallRequirement], + specifier: SpecifierSet, + hashes: Hashes, + prefers_installed: bool, + incompatible_ids: Set[int], + ) -> Iterable[Candidate]: + if not ireqs: + return () + + # The InstallRequirement implementation requires us to give it a + # "template". Here we just choose the first requirement to represent + # all of them. + # Hopefully the Project model can correct this mismatch in the future. + template = ireqs[0] + assert template.req, "Candidates found on index must be PEP 508" + name = canonicalize_name(template.req.name) + + extras: FrozenSet[str] = frozenset() + for ireq in ireqs: + assert ireq.req, "Candidates found on index must be PEP 508" + specifier &= ireq.req.specifier + hashes &= ireq.hashes(trust_internet=False) + extras |= frozenset(ireq.extras) + + def _get_installed_candidate() -> Optional[Candidate]: + """Get the candidate for the currently-installed version.""" + # If --force-reinstall is set, we want the version from the index + # instead, so we "pretend" there is nothing installed. + if self._force_reinstall: + return None + try: + installed_dist = self._installed_dists[name] + except KeyError: + return None + # Don't use the installed distribution if its version does not fit + # the current dependency graph. + if not specifier.contains(installed_dist.version, prereleases=True): + return None + candidate = self._make_candidate_from_dist( + dist=installed_dist, + extras=extras, + template=template, + ) + # The candidate is a known incompatibility. Don't use it. + if id(candidate) in incompatible_ids: + return None + return candidate + + def iter_index_candidate_infos() -> Iterator[IndexCandidateInfo]: + result = self._finder.find_best_candidate( + project_name=name, + specifier=specifier, + hashes=hashes, + ) + icans = list(result.iter_applicable()) + + # PEP 592: Yanked releases are ignored unless the specifier + # explicitly pins a version (via '==' or '===') that can be + # solely satisfied by a yanked release. + all_yanked = all(ican.link.is_yanked for ican in icans) + + def is_pinned(specifier: SpecifierSet) -> bool: + for sp in specifier: + if sp.operator == "===": + return True + if sp.operator != "==": + continue + if sp.version.endswith(".*"): + continue + return True + return False + + pinned = is_pinned(specifier) + + # PackageFinder returns earlier versions first, so we reverse. + for ican in reversed(icans): + if not (all_yanked and pinned) and ican.link.is_yanked: + continue + func = functools.partial( + self._make_candidate_from_link, + link=ican.link, + extras=extras, + template=template, + name=name, + version=ican.version, + ) + yield ican.version, func + + return FoundCandidates( + iter_index_candidate_infos, + _get_installed_candidate(), + prefers_installed, + incompatible_ids, + ) + + def _iter_explicit_candidates_from_base( + self, + base_requirements: Iterable[Requirement], + extras: FrozenSet[str], + ) -> Iterator[Candidate]: + """Produce explicit candidates from the base given an extra-ed package. + + :param base_requirements: Requirements known to the resolver. The + requirements are guaranteed to not have extras. + :param extras: The extras to inject into the explicit requirements' + candidates. + """ + for req in base_requirements: + lookup_cand, _ = req.get_candidate_lookup() + if lookup_cand is None: # Not explicit. + continue + # We've stripped extras from the identifier, and should always + # get a BaseCandidate here, unless there's a bug elsewhere. + base_cand = as_base_candidate(lookup_cand) + assert base_cand is not None, "no extras here" + yield self._make_extras_candidate(base_cand, extras) + + def _iter_candidates_from_constraints( + self, + identifier: str, + constraint: Constraint, + template: InstallRequirement, + ) -> Iterator[Candidate]: + """Produce explicit candidates from constraints. + + This creates "fake" InstallRequirement objects that are basically clones + of what "should" be the template, but with original_link set to link. + """ + for link in constraint.links: + self._fail_if_link_is_unsupported_wheel(link) + candidate = self._make_candidate_from_link( + link, + extras=frozenset(), + template=install_req_from_link_and_ireq(link, template), + name=canonicalize_name(identifier), + version=None, + ) + if candidate: + yield candidate + + def find_candidates( + self, + identifier: str, + requirements: Mapping[str, Iterable[Requirement]], + incompatibilities: Mapping[str, Iterator[Candidate]], + constraint: Constraint, + prefers_installed: bool, + ) -> Iterable[Candidate]: + # Collect basic lookup information from the requirements. + explicit_candidates: Set[Candidate] = set() + ireqs: List[InstallRequirement] = [] + for req in requirements[identifier]: + cand, ireq = req.get_candidate_lookup() + if cand is not None: + explicit_candidates.add(cand) + if ireq is not None: + ireqs.append(ireq) + + # If the current identifier contains extras, add explicit candidates + # from entries from extra-less identifier. + with contextlib.suppress(InvalidRequirement): + parsed_requirement = get_requirement(identifier) + explicit_candidates.update( + self._iter_explicit_candidates_from_base( + requirements.get(parsed_requirement.name, ()), + frozenset(parsed_requirement.extras), + ), + ) + + # Add explicit candidates from constraints. We only do this if there are + # known ireqs, which represent requirements not already explicit. If + # there are no ireqs, we're constraining already-explicit requirements, + # which is handled later when we return the explicit candidates. + if ireqs: + try: + explicit_candidates.update( + self._iter_candidates_from_constraints( + identifier, + constraint, + template=ireqs[0], + ), + ) + except UnsupportedWheel: + # If we're constrained to install a wheel incompatible with the + # target architecture, no candidates will ever be valid. + return () + + # Since we cache all the candidates, incompatibility identification + # can be made quicker by comparing only the id() values. + incompat_ids = {id(c) for c in incompatibilities.get(identifier, ())} + + # If none of the requirements want an explicit candidate, we can ask + # the finder for candidates. + if not explicit_candidates: + return self._iter_found_candidates( + ireqs, + constraint.specifier, + constraint.hashes, + prefers_installed, + incompat_ids, + ) + + return ( + c + for c in explicit_candidates + if id(c) not in incompat_ids + and constraint.is_satisfied_by(c) + and all(req.is_satisfied_by(c) for req in requirements[identifier]) + ) + + def _make_requirement_from_install_req( + self, ireq: InstallRequirement, requested_extras: Iterable[str] + ) -> Optional[Requirement]: + if not ireq.match_markers(requested_extras): + logger.info( + "Ignoring %s: markers '%s' don't match your environment", + ireq.name, + ireq.markers, + ) + return None + if not ireq.link: + return SpecifierRequirement(ireq) + self._fail_if_link_is_unsupported_wheel(ireq.link) + cand = self._make_candidate_from_link( + ireq.link, + extras=frozenset(ireq.extras), + template=ireq, + name=canonicalize_name(ireq.name) if ireq.name else None, + version=None, + ) + if cand is None: + # There's no way we can satisfy a URL requirement if the underlying + # candidate fails to build. An unnamed URL must be user-supplied, so + # we fail eagerly. If the URL is named, an unsatisfiable requirement + # can make the resolver do the right thing, either backtrack (and + # maybe find some other requirement that's buildable) or raise a + # ResolutionImpossible eventually. + if not ireq.name: + raise self._build_failures[ireq.link] + return UnsatisfiableRequirement(canonicalize_name(ireq.name)) + return self.make_requirement_from_candidate(cand) + + def collect_root_requirements( + self, root_ireqs: List[InstallRequirement] + ) -> CollectedRootRequirements: + collected = CollectedRootRequirements([], {}, {}) + for i, ireq in enumerate(root_ireqs): + if ireq.constraint: + # Ensure we only accept valid constraints + problem = check_invalid_constraint_type(ireq) + if problem: + raise InstallationError(problem) + if not ireq.match_markers(): + continue + assert ireq.name, "Constraint must be named" + name = canonicalize_name(ireq.name) + if name in collected.constraints: + collected.constraints[name] &= ireq + else: + collected.constraints[name] = Constraint.from_ireq(ireq) + else: + req = self._make_requirement_from_install_req( + ireq, + requested_extras=(), + ) + if req is None: + continue + if ireq.user_supplied and req.name not in collected.user_requested: + collected.user_requested[req.name] = i + collected.requirements.append(req) + return collected + + def make_requirement_from_candidate( + self, candidate: Candidate + ) -> ExplicitRequirement: + return ExplicitRequirement(candidate) + + def make_requirement_from_spec( + self, + specifier: str, + comes_from: Optional[InstallRequirement], + requested_extras: Iterable[str] = (), + ) -> Optional[Requirement]: + ireq = self._make_install_req_from_spec(specifier, comes_from) + return self._make_requirement_from_install_req(ireq, requested_extras) + + def make_requires_python_requirement( + self, + specifier: SpecifierSet, + ) -> Optional[Requirement]: + if self._ignore_requires_python: + return None + # Don't bother creating a dependency for an empty Requires-Python. + if not str(specifier): + return None + return RequiresPythonRequirement(specifier, self._python_candidate) + + def get_wheel_cache_entry( + self, link: Link, name: Optional[str] + ) -> Optional[CacheEntry]: + """Look up the link in the wheel cache. + + If ``preparer.require_hashes`` is True, don't use the wheel cache, + because cached wheels, always built locally, have different hashes + than the files downloaded from the index server and thus throw false + hash mismatches. Furthermore, cached wheels at present have + nondeterministic contents due to file modification times. + """ + if self._wheel_cache is None or self.preparer.require_hashes: + return None + return self._wheel_cache.get_cache_entry( + link=link, + package_name=name, + supported_tags=get_supported(), + ) + + def get_dist_to_uninstall(self, candidate: Candidate) -> Optional[BaseDistribution]: + # TODO: Are there more cases this needs to return True? Editable? + dist = self._installed_dists.get(candidate.project_name) + if dist is None: # Not installed, no uninstallation required. + return None + + # We're installing into global site. The current installation must + # be uninstalled, no matter it's in global or user site, because the + # user site installation has precedence over global. + if not self._use_user_site: + return dist + + # We're installing into user site. Remove the user site installation. + if dist.in_usersite: + return dist + + # We're installing into user site, but the installed incompatible + # package is in global site. We can't uninstall that, and would let + # the new user installation to "shadow" it. But shadowing won't work + # in virtual environments, so we error out. + if running_under_virtualenv() and dist.in_site_packages: + message = ( + f"Will not install to the user site because it will lack " + f"sys.path precedence to {dist.raw_name} in {dist.location}" + ) + raise InstallationError(message) + return None + + def _report_requires_python_error( + self, causes: Sequence["ConflictCause"] + ) -> UnsupportedPythonVersion: + assert causes, "Requires-Python error reported with no cause" + + version = self._python_candidate.version + + if len(causes) == 1: + specifier = str(causes[0].requirement.specifier) + message = ( + f"Package {causes[0].parent.name!r} requires a different " + f"Python: {version} not in {specifier!r}" + ) + return UnsupportedPythonVersion(message) + + message = f"Packages require a different Python. {version} not in:" + for cause in causes: + package = cause.parent.format_for_error() + specifier = str(cause.requirement.specifier) + message += f"\n{specifier!r} (required by {package})" + return UnsupportedPythonVersion(message) + + def _report_single_requirement_conflict( + self, req: Requirement, parent: Optional[Candidate] + ) -> DistributionNotFound: + if parent is None: + req_disp = str(req) + else: + req_disp = f"{req} (from {parent.name})" + + cands = self._finder.find_all_candidates(req.project_name) + versions = [str(v) for v in sorted({c.version for c in cands})] + + logger.critical( + "Could not find a version that satisfies the requirement %s " + "(from versions: %s)", + req_disp, + ", ".join(versions) or "none", + ) + if str(req) == "requirements.txt": + logger.info( + "HINT: You are attempting to install a package literally " + 'named "requirements.txt" (which cannot exist). Consider ' + "using the '-r' flag to install the packages listed in " + "requirements.txt" + ) + + return DistributionNotFound(f"No matching distribution found for {req}") + + def get_installation_error( + self, + e: "ResolutionImpossible[Requirement, Candidate]", + constraints: Dict[str, Constraint], + ) -> InstallationError: + + assert e.causes, "Installation error reported with no cause" + + # If one of the things we can't solve is "we need Python X.Y", + # that is what we report. + requires_python_causes = [ + cause + for cause in e.causes + if isinstance(cause.requirement, RequiresPythonRequirement) + and not cause.requirement.is_satisfied_by(self._python_candidate) + ] + if requires_python_causes: + # The comprehension above makes sure all Requirement instances are + # RequiresPythonRequirement, so let's cast for convenience. + return self._report_requires_python_error( + cast("Sequence[ConflictCause]", requires_python_causes), + ) + + # Otherwise, we have a set of causes which can't all be satisfied + # at once. + + # The simplest case is when we have *one* cause that can't be + # satisfied. We just report that case. + if len(e.causes) == 1: + req, parent = e.causes[0] + if req.name not in constraints: + return self._report_single_requirement_conflict(req, parent) + + # OK, we now have a list of requirements that can't all be + # satisfied at once. + + # A couple of formatting helpers + def text_join(parts: List[str]) -> str: + if len(parts) == 1: + return parts[0] + + return ", ".join(parts[:-1]) + " and " + parts[-1] + + def describe_trigger(parent: Candidate) -> str: + ireq = parent.get_install_requirement() + if not ireq or not ireq.comes_from: + return f"{parent.name}=={parent.version}" + if isinstance(ireq.comes_from, InstallRequirement): + return str(ireq.comes_from.name) + return str(ireq.comes_from) + + triggers = set() + for req, parent in e.causes: + if parent is None: + # This is a root requirement, so we can report it directly + trigger = req.format_for_error() + else: + trigger = describe_trigger(parent) + triggers.add(trigger) + + if triggers: + info = text_join(sorted(triggers)) + else: + info = "the requested packages" + + msg = ( + "Cannot install {} because these package versions " + "have conflicting dependencies.".format(info) + ) + logger.critical(msg) + msg = "\nThe conflict is caused by:" + + relevant_constraints = set() + for req, parent in e.causes: + if req.name in constraints: + relevant_constraints.add(req.name) + msg = msg + "\n " + if parent: + msg = msg + f"{parent.name} {parent.version} depends on " + else: + msg = msg + "The user requested " + msg = msg + req.format_for_error() + for key in relevant_constraints: + spec = constraints[key].specifier + msg += f"\n The user requested (constraint) {key}{spec}" + + msg = ( + msg + + "\n\n" + + "To fix this you could try to:\n" + + "1. loosen the range of package versions you've specified\n" + + "2. remove package versions to allow pip attempt to solve " + + "the dependency conflict\n" + ) + + logger.info(msg) + + return DistributionNotFound( + "ResolutionImpossible: for help visit " + "https://pip.pypa.io/en/latest/topics/dependency-resolution/" + "#dealing-with-dependency-conflicts" + ) diff --git a/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/found_candidates.py b/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/found_candidates.py new file mode 100644 index 0000000..8663097 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/found_candidates.py @@ -0,0 +1,155 @@ +"""Utilities to lazily create and visit candidates found. + +Creating and visiting a candidate is a *very* costly operation. It involves +fetching, extracting, potentially building modules from source, and verifying +distribution metadata. It is therefore crucial for performance to keep +everything here lazy all the way down, so we only touch candidates that we +absolutely need, and not "download the world" when we only need one version of +something. +""" + +import functools +from collections.abc import Sequence +from typing import TYPE_CHECKING, Any, Callable, Iterator, Optional, Set, Tuple + +from pip._vendor.packaging.version import _BaseVersion + +from .base import Candidate + +IndexCandidateInfo = Tuple[_BaseVersion, Callable[[], Optional[Candidate]]] + +if TYPE_CHECKING: + SequenceCandidate = Sequence[Candidate] +else: + # For compatibility: Python before 3.9 does not support using [] on the + # Sequence class. + # + # >>> from collections.abc import Sequence + # >>> Sequence[str] + # Traceback (most recent call last): + # File "", line 1, in + # TypeError: 'ABCMeta' object is not subscriptable + # + # TODO: Remove this block after dropping Python 3.8 support. + SequenceCandidate = Sequence + + +def _iter_built(infos: Iterator[IndexCandidateInfo]) -> Iterator[Candidate]: + """Iterator for ``FoundCandidates``. + + This iterator is used when the package is not already installed. Candidates + from index come later in their normal ordering. + """ + versions_found: Set[_BaseVersion] = set() + for version, func in infos: + if version in versions_found: + continue + candidate = func() + if candidate is None: + continue + yield candidate + versions_found.add(version) + + +def _iter_built_with_prepended( + installed: Candidate, infos: Iterator[IndexCandidateInfo] +) -> Iterator[Candidate]: + """Iterator for ``FoundCandidates``. + + This iterator is used when the resolver prefers the already-installed + candidate and NOT to upgrade. The installed candidate is therefore + always yielded first, and candidates from index come later in their + normal ordering, except skipped when the version is already installed. + """ + yield installed + versions_found: Set[_BaseVersion] = {installed.version} + for version, func in infos: + if version in versions_found: + continue + candidate = func() + if candidate is None: + continue + yield candidate + versions_found.add(version) + + +def _iter_built_with_inserted( + installed: Candidate, infos: Iterator[IndexCandidateInfo] +) -> Iterator[Candidate]: + """Iterator for ``FoundCandidates``. + + This iterator is used when the resolver prefers to upgrade an + already-installed package. Candidates from index are returned in their + normal ordering, except replaced when the version is already installed. + + The implementation iterates through and yields other candidates, inserting + the installed candidate exactly once before we start yielding older or + equivalent candidates, or after all other candidates if they are all newer. + """ + versions_found: Set[_BaseVersion] = set() + for version, func in infos: + if version in versions_found: + continue + # If the installed candidate is better, yield it first. + if installed.version >= version: + yield installed + versions_found.add(installed.version) + candidate = func() + if candidate is None: + continue + yield candidate + versions_found.add(version) + + # If the installed candidate is older than all other candidates. + if installed.version not in versions_found: + yield installed + + +class FoundCandidates(SequenceCandidate): + """A lazy sequence to provide candidates to the resolver. + + The intended usage is to return this from `find_matches()` so the resolver + can iterate through the sequence multiple times, but only access the index + page when remote packages are actually needed. This improve performances + when suitable candidates are already installed on disk. + """ + + def __init__( + self, + get_infos: Callable[[], Iterator[IndexCandidateInfo]], + installed: Optional[Candidate], + prefers_installed: bool, + incompatible_ids: Set[int], + ): + self._get_infos = get_infos + self._installed = installed + self._prefers_installed = prefers_installed + self._incompatible_ids = incompatible_ids + + def __getitem__(self, index: Any) -> Any: + # Implemented to satisfy the ABC check. This is not needed by the + # resolver, and should not be used by the provider either (for + # performance reasons). + raise NotImplementedError("don't do this") + + def __iter__(self) -> Iterator[Candidate]: + infos = self._get_infos() + if not self._installed: + iterator = _iter_built(infos) + elif self._prefers_installed: + iterator = _iter_built_with_prepended(self._installed, infos) + else: + iterator = _iter_built_with_inserted(self._installed, infos) + return (c for c in iterator if id(c) not in self._incompatible_ids) + + def __len__(self) -> int: + # Implemented to satisfy the ABC check. This is not needed by the + # resolver, and should not be used by the provider either (for + # performance reasons). + raise NotImplementedError("don't do this") + + @functools.lru_cache(maxsize=1) + def __bool__(self) -> bool: + if self._prefers_installed and self._installed: + return True + return any(self) diff --git a/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/provider.py b/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/provider.py new file mode 100644 index 0000000..e6ec959 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/provider.py @@ -0,0 +1,248 @@ +import collections +import math +from typing import ( + TYPE_CHECKING, + Dict, + Iterable, + Iterator, + Mapping, + Sequence, + TypeVar, + Union, +) + +from pip._vendor.resolvelib.providers import AbstractProvider + +from .base import Candidate, Constraint, Requirement +from .candidates import REQUIRES_PYTHON_IDENTIFIER +from .factory import Factory + +if TYPE_CHECKING: + from pip._vendor.resolvelib.providers import Preference + from pip._vendor.resolvelib.resolvers import RequirementInformation + + PreferenceInformation = RequirementInformation[Requirement, Candidate] + + _ProviderBase = AbstractProvider[Requirement, Candidate, str] +else: + _ProviderBase = AbstractProvider + +# Notes on the relationship between the provider, the factory, and the +# candidate and requirement classes. +# +# The provider is a direct implementation of the resolvelib class. Its role +# is to deliver the API that resolvelib expects. +# +# Rather than work with completely abstract "requirement" and "candidate" +# concepts as resolvelib does, pip has concrete classes implementing these two +# ideas. The API of Requirement and Candidate objects are defined in the base +# classes, but essentially map fairly directly to the equivalent provider +# methods. In particular, `find_matches` and `is_satisfied_by` are +# requirement methods, and `get_dependencies` is a candidate method. +# +# The factory is the interface to pip's internal mechanisms. It is stateless, +# and is created by the resolver and held as a property of the provider. It is +# responsible for creating Requirement and Candidate objects, and provides +# services to those objects (access to pip's finder and preparer). + + +D = TypeVar("D") +V = TypeVar("V") + + +def _get_with_identifier( + mapping: Mapping[str, V], + identifier: str, + default: D, +) -> Union[D, V]: + """Get item from a package name lookup mapping with a resolver identifier. + + This extra logic is needed when the target mapping is keyed by package + name, which cannot be directly looked up with an identifier (which may + contain requested extras). Additional logic is added to also look up a value + by "cleaning up" the extras from the identifier. + """ + if identifier in mapping: + return mapping[identifier] + # HACK: Theoretically we should check whether this identifier is a valid + # "NAME[EXTRAS]" format, and parse out the name part with packaging or + # some regular expression. But since pip's resolver only spits out three + # kinds of identifiers: normalized PEP 503 names, normalized names plus + # extras, and Requires-Python, we can cheat a bit here. + name, open_bracket, _ = identifier.partition("[") + if open_bracket and name in mapping: + return mapping[name] + return default + + +class PipProvider(_ProviderBase): + """Pip's provider implementation for resolvelib. + + :params constraints: A mapping of constraints specified by the user. Keys + are canonicalized project names. + :params ignore_dependencies: Whether the user specified ``--no-deps``. + :params upgrade_strategy: The user-specified upgrade strategy. + :params user_requested: A set of canonicalized package names that the user + supplied for pip to install/upgrade. + """ + + def __init__( + self, + factory: Factory, + constraints: Dict[str, Constraint], + ignore_dependencies: bool, + upgrade_strategy: str, + user_requested: Dict[str, int], + ) -> None: + self._factory = factory + self._constraints = constraints + self._ignore_dependencies = ignore_dependencies + self._upgrade_strategy = upgrade_strategy + self._user_requested = user_requested + self._known_depths: Dict[str, float] = collections.defaultdict(lambda: math.inf) + + def identify(self, requirement_or_candidate: Union[Requirement, Candidate]) -> str: + return requirement_or_candidate.name + + def get_preference( # type: ignore + self, + identifier: str, + resolutions: Mapping[str, Candidate], + candidates: Mapping[str, Iterator[Candidate]], + information: Mapping[str, Iterable["PreferenceInformation"]], + backtrack_causes: Sequence["PreferenceInformation"], + ) -> "Preference": + """Produce a sort key for given requirement based on preference. + + The lower the return value is, the more preferred this group of + arguments is. + + Currently pip considers the followings in order: + + * Prefer if any of the known requirements is "direct", e.g. points to an + explicit URL. + * If equal, prefer if any requirement is "pinned", i.e. contains + operator ``===`` or ``==``. + * If equal, calculate an approximate "depth" and resolve requirements + closer to the user-specified requirements first. + * Order user-specified requirements by the order they are specified. + * If equal, prefers "non-free" requirements, i.e. contains at least one + operator, such as ``>=`` or ``<``. + * If equal, order alphabetically for consistency (helps debuggability). + """ + lookups = (r.get_candidate_lookup() for r, _ in information[identifier]) + candidate, ireqs = zip(*lookups) + operators = [ + specifier.operator + for specifier_set in (ireq.specifier for ireq in ireqs if ireq) + for specifier in specifier_set + ] + + direct = candidate is not None + pinned = any(op[:2] == "==" for op in operators) + unfree = bool(operators) + + try: + requested_order: Union[int, float] = self._user_requested[identifier] + except KeyError: + requested_order = math.inf + parent_depths = ( + self._known_depths[parent.name] if parent is not None else 0.0 + for _, parent in information[identifier] + ) + inferred_depth = min(d for d in parent_depths) + 1.0 + else: + inferred_depth = 1.0 + self._known_depths[identifier] = inferred_depth + + requested_order = self._user_requested.get(identifier, math.inf) + + # Requires-Python has only one candidate and the check is basically + # free, so we always do it first to avoid needless work if it fails. + requires_python = identifier == REQUIRES_PYTHON_IDENTIFIER + + # HACK: Setuptools have a very long and solid backward compatibility + # track record, and extremely few projects would request a narrow, + # non-recent version range of it since that would break a lot things. + # (Most projects specify it only to request for an installer feature, + # which does not work, but that's another topic.) Intentionally + # delaying Setuptools helps reduce branches the resolver has to check. + # This serves as a temporary fix for issues like "apache-airflow[all]" + # while we work on "proper" branch pruning techniques. + delay_this = identifier == "setuptools" + + # Prefer the causes of backtracking on the assumption that the problem + # resolving the dependency tree is related to the failures that caused + # the backtracking + backtrack_cause = self.is_backtrack_cause(identifier, backtrack_causes) + + return ( + not requires_python, + delay_this, + not direct, + not pinned, + not backtrack_cause, + inferred_depth, + requested_order, + not unfree, + identifier, + ) + + def find_matches( + self, + identifier: str, + requirements: Mapping[str, Iterator[Requirement]], + incompatibilities: Mapping[str, Iterator[Candidate]], + ) -> Iterable[Candidate]: + def _eligible_for_upgrade(identifier: str) -> bool: + """Are upgrades allowed for this project? + + This checks the upgrade strategy, and whether the project was one + that the user specified in the command line, in order to decide + whether we should upgrade if there's a newer version available. + + (Note that we don't need access to the `--upgrade` flag, because + an upgrade strategy of "to-satisfy-only" means that `--upgrade` + was not specified). + """ + if self._upgrade_strategy == "eager": + return True + elif self._upgrade_strategy == "only-if-needed": + user_order = _get_with_identifier( + self._user_requested, + identifier, + default=None, + ) + return user_order is not None + return False + + constraint = _get_with_identifier( + self._constraints, + identifier, + default=Constraint.empty(), + ) + return self._factory.find_candidates( + identifier=identifier, + requirements=requirements, + constraint=constraint, + prefers_installed=(not _eligible_for_upgrade(identifier)), + incompatibilities=incompatibilities, + ) + + def is_satisfied_by(self, requirement: Requirement, candidate: Candidate) -> bool: + return requirement.is_satisfied_by(candidate) + + def get_dependencies(self, candidate: Candidate) -> Sequence[Requirement]: + with_requires = not self._ignore_dependencies + return [r for r in candidate.iter_dependencies(with_requires) if r is not None] + + @staticmethod + def is_backtrack_cause( + identifier: str, backtrack_causes: Sequence["PreferenceInformation"] + ) -> bool: + for backtrack_cause in backtrack_causes: + if identifier == backtrack_cause.requirement.name: + return True + if backtrack_cause.parent and identifier == backtrack_cause.parent.name: + return True + return False diff --git a/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/reporter.py b/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/reporter.py new file mode 100644 index 0000000..6ced532 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/reporter.py @@ -0,0 +1,68 @@ +from collections import defaultdict +from logging import getLogger +from typing import Any, DefaultDict + +from pip._vendor.resolvelib.reporters import BaseReporter + +from .base import Candidate, Requirement + +logger = getLogger(__name__) + + +class PipReporter(BaseReporter): + def __init__(self) -> None: + self.backtracks_by_package: DefaultDict[str, int] = defaultdict(int) + + self._messages_at_backtrack = { + 1: ( + "pip is looking at multiple versions of {package_name} to " + "determine which version is compatible with other " + "requirements. This could take a while." + ), + 8: ( + "pip is looking at multiple versions of {package_name} to " + "determine which version is compatible with other " + "requirements. This could take a while." + ), + 13: ( + "This is taking longer than usual. You might need to provide " + "the dependency resolver with stricter constraints to reduce " + "runtime. See https://pip.pypa.io/warnings/backtracking for " + "guidance. If you want to abort this run, press Ctrl + C." + ), + } + + def backtracking(self, candidate: Candidate) -> None: + self.backtracks_by_package[candidate.name] += 1 + + count = self.backtracks_by_package[candidate.name] + if count not in self._messages_at_backtrack: + return + + message = self._messages_at_backtrack[count] + logger.info("INFO: %s", message.format(package_name=candidate.name)) + + +class PipDebuggingReporter(BaseReporter): + """A reporter that does an info log for every event it sees.""" + + def starting(self) -> None: + logger.info("Reporter.starting()") + + def starting_round(self, index: int) -> None: + logger.info("Reporter.starting_round(%r)", index) + + def ending_round(self, index: int, state: Any) -> None: + logger.info("Reporter.ending_round(%r, state)", index) + + def ending(self, state: Any) -> None: + logger.info("Reporter.ending(%r)", state) + + def adding_requirement(self, requirement: Requirement, parent: Candidate) -> None: + logger.info("Reporter.adding_requirement(%r, %r)", requirement, parent) + + def backtracking(self, candidate: Candidate) -> None: + logger.info("Reporter.backtracking(%r)", candidate) + + def pinning(self, candidate: Candidate) -> None: + logger.info("Reporter.pinning(%r)", candidate) diff --git a/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/requirements.py b/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/requirements.py new file mode 100644 index 0000000..f561f1f --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/requirements.py @@ -0,0 +1,166 @@ +from pip._vendor.packaging.specifiers import SpecifierSet +from pip._vendor.packaging.utils import NormalizedName, canonicalize_name + +from pip._internal.req.req_install import InstallRequirement + +from .base import Candidate, CandidateLookup, Requirement, format_name + + +class ExplicitRequirement(Requirement): + def __init__(self, candidate: Candidate) -> None: + self.candidate = candidate + + def __str__(self) -> str: + return str(self.candidate) + + def __repr__(self) -> str: + return "{class_name}({candidate!r})".format( + class_name=self.__class__.__name__, + candidate=self.candidate, + ) + + @property + def project_name(self) -> NormalizedName: + # No need to canonicalize - the candidate did this + return self.candidate.project_name + + @property + def name(self) -> str: + # No need to canonicalize - the candidate did this + return self.candidate.name + + def format_for_error(self) -> str: + return self.candidate.format_for_error() + + def get_candidate_lookup(self) -> CandidateLookup: + return self.candidate, None + + def is_satisfied_by(self, candidate: Candidate) -> bool: + return candidate == self.candidate + + +class SpecifierRequirement(Requirement): + def __init__(self, ireq: InstallRequirement) -> None: + assert ireq.link is None, "This is a link, not a specifier" + self._ireq = ireq + self._extras = frozenset(ireq.extras) + + def __str__(self) -> str: + return str(self._ireq.req) + + def __repr__(self) -> str: + return "{class_name}({requirement!r})".format( + class_name=self.__class__.__name__, + requirement=str(self._ireq.req), + ) + + @property + def project_name(self) -> NormalizedName: + assert self._ireq.req, "Specifier-backed ireq is always PEP 508" + return canonicalize_name(self._ireq.req.name) + + @property + def name(self) -> str: + return format_name(self.project_name, self._extras) + + def format_for_error(self) -> str: + + # Convert comma-separated specifiers into "A, B, ..., F and G" + # This makes the specifier a bit more "human readable", without + # risking a change in meaning. (Hopefully! Not all edge cases have + # been checked) + parts = [s.strip() for s in str(self).split(",")] + if len(parts) == 0: + return "" + elif len(parts) == 1: + return parts[0] + + return ", ".join(parts[:-1]) + " and " + parts[-1] + + def get_candidate_lookup(self) -> CandidateLookup: + return None, self._ireq + + def is_satisfied_by(self, candidate: Candidate) -> bool: + assert candidate.name == self.name, ( + f"Internal issue: Candidate is not for this requirement " + f"{candidate.name} vs {self.name}" + ) + # We can safely always allow prereleases here since PackageFinder + # already implements the prerelease logic, and would have filtered out + # prerelease candidates if the user does not expect them. + assert self._ireq.req, "Specifier-backed ireq is always PEP 508" + spec = self._ireq.req.specifier + return spec.contains(candidate.version, prereleases=True) + + +class RequiresPythonRequirement(Requirement): + """A requirement representing Requires-Python metadata.""" + + def __init__(self, specifier: SpecifierSet, match: Candidate) -> None: + self.specifier = specifier + self._candidate = match + + def __str__(self) -> str: + return f"Python {self.specifier}" + + def __repr__(self) -> str: + return "{class_name}({specifier!r})".format( + class_name=self.__class__.__name__, + specifier=str(self.specifier), + ) + + @property + def project_name(self) -> NormalizedName: + return self._candidate.project_name + + @property + def name(self) -> str: + return self._candidate.name + + def format_for_error(self) -> str: + return str(self) + + def get_candidate_lookup(self) -> CandidateLookup: + if self.specifier.contains(self._candidate.version, prereleases=True): + return self._candidate, None + return None, None + + def is_satisfied_by(self, candidate: Candidate) -> bool: + assert candidate.name == self._candidate.name, "Not Python candidate" + # We can safely always allow prereleases here since PackageFinder + # already implements the prerelease logic, and would have filtered out + # prerelease candidates if the user does not expect them. + return self.specifier.contains(candidate.version, prereleases=True) + + +class UnsatisfiableRequirement(Requirement): + """A requirement that cannot be satisfied.""" + + def __init__(self, name: NormalizedName) -> None: + self._name = name + + def __str__(self) -> str: + return f"{self._name} (unavailable)" + + def __repr__(self) -> str: + return "{class_name}({name!r})".format( + class_name=self.__class__.__name__, + name=str(self._name), + ) + + @property + def project_name(self) -> NormalizedName: + return self._name + + @property + def name(self) -> str: + return self._name + + def format_for_error(self) -> str: + return str(self) + + def get_candidate_lookup(self) -> CandidateLookup: + return None, None + + def is_satisfied_by(self, candidate: Candidate) -> bool: + return False diff --git a/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/resolver.py b/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/resolver.py new file mode 100644 index 0000000..32ef789 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/resolver.py @@ -0,0 +1,298 @@ +import functools +import logging +import os +from typing import TYPE_CHECKING, Dict, List, Optional, Set, Tuple, cast + +from pip._vendor.packaging.utils import canonicalize_name +from pip._vendor.resolvelib import BaseReporter, ResolutionImpossible +from pip._vendor.resolvelib import Resolver as RLResolver +from pip._vendor.resolvelib.structs import DirectedGraph + +from pip._internal.cache import WheelCache +from pip._internal.index.package_finder import PackageFinder +from pip._internal.operations.prepare import RequirementPreparer +from pip._internal.req.req_install import InstallRequirement +from pip._internal.req.req_set import RequirementSet +from pip._internal.resolution.base import BaseResolver, InstallRequirementProvider +from pip._internal.resolution.resolvelib.provider import PipProvider +from pip._internal.resolution.resolvelib.reporter import ( + PipDebuggingReporter, + PipReporter, +) + +from .base import Candidate, Requirement +from .factory import Factory + +if TYPE_CHECKING: + from pip._vendor.resolvelib.resolvers import Result as RLResult + + Result = RLResult[Requirement, Candidate, str] + + +logger = logging.getLogger(__name__) + + +class Resolver(BaseResolver): + _allowed_strategies = {"eager", "only-if-needed", "to-satisfy-only"} + + def __init__( + self, + preparer: RequirementPreparer, + finder: PackageFinder, + wheel_cache: Optional[WheelCache], + make_install_req: InstallRequirementProvider, + use_user_site: bool, + ignore_dependencies: bool, + ignore_installed: bool, + ignore_requires_python: bool, + force_reinstall: bool, + upgrade_strategy: str, + suppress_build_failures: bool, + py_version_info: Optional[Tuple[int, ...]] = None, + ): + super().__init__() + assert upgrade_strategy in self._allowed_strategies + + self.factory = Factory( + finder=finder, + preparer=preparer, + make_install_req=make_install_req, + wheel_cache=wheel_cache, + use_user_site=use_user_site, + force_reinstall=force_reinstall, + ignore_installed=ignore_installed, + ignore_requires_python=ignore_requires_python, + suppress_build_failures=suppress_build_failures, + py_version_info=py_version_info, + ) + self.ignore_dependencies = ignore_dependencies + self.upgrade_strategy = upgrade_strategy + self._result: Optional[Result] = None + + def resolve( + self, root_reqs: List[InstallRequirement], check_supported_wheels: bool + ) -> RequirementSet: + collected = self.factory.collect_root_requirements(root_reqs) + provider = PipProvider( + factory=self.factory, + constraints=collected.constraints, + ignore_dependencies=self.ignore_dependencies, + upgrade_strategy=self.upgrade_strategy, + user_requested=collected.user_requested, + ) + if "PIP_RESOLVER_DEBUG" in os.environ: + reporter: BaseReporter = PipDebuggingReporter() + else: + reporter = PipReporter() + resolver: RLResolver[Requirement, Candidate, str] = RLResolver( + provider, + reporter, + ) + + try: + try_to_avoid_resolution_too_deep = 2000000 + result = self._result = resolver.resolve( + collected.requirements, max_rounds=try_to_avoid_resolution_too_deep + ) + + except ResolutionImpossible as e: + error = self.factory.get_installation_error( + cast("ResolutionImpossible[Requirement, Candidate]", e), + collected.constraints, + ) + raise error from e + + req_set = RequirementSet(check_supported_wheels=check_supported_wheels) + for candidate in result.mapping.values(): + ireq = candidate.get_install_requirement() + if ireq is None: + continue + + # Check if there is already an installation under the same name, + # and set a flag for later stages to uninstall it, if needed. + installed_dist = self.factory.get_dist_to_uninstall(candidate) + if installed_dist is None: + # There is no existing installation -- nothing to uninstall. + ireq.should_reinstall = False + elif self.factory.force_reinstall: + # The --force-reinstall flag is set -- reinstall. + ireq.should_reinstall = True + elif installed_dist.version != candidate.version: + # The installation is different in version -- reinstall. + ireq.should_reinstall = True + elif candidate.is_editable or installed_dist.editable: + # The incoming distribution is editable, or different in + # editable-ness to installation -- reinstall. + ireq.should_reinstall = True + elif candidate.source_link and candidate.source_link.is_file: + # The incoming distribution is under file:// + if candidate.source_link.is_wheel: + # is a local wheel -- do nothing. + logger.info( + "%s is already installed with the same version as the " + "provided wheel. Use --force-reinstall to force an " + "installation of the wheel.", + ireq.name, + ) + continue + + # is a local sdist or path -- reinstall + ireq.should_reinstall = True + else: + continue + + link = candidate.source_link + if link and link.is_yanked: + # The reason can contain non-ASCII characters, Unicode + # is required for Python 2. + msg = ( + "The candidate selected for download or install is a " + "yanked version: {name!r} candidate (version {version} " + "at {link})\nReason for being yanked: {reason}" + ).format( + name=candidate.name, + version=candidate.version, + link=link, + reason=link.yanked_reason or "", + ) + logger.warning(msg) + + req_set.add_named_requirement(ireq) + + reqs = req_set.all_requirements + self.factory.preparer.prepare_linked_requirements_more(reqs) + return req_set + + def get_installation_order( + self, req_set: RequirementSet + ) -> List[InstallRequirement]: + """Get order for installation of requirements in RequirementSet. + + The returned list contains a requirement before another that depends on + it. This helps ensure that the environment is kept consistent as they + get installed one-by-one. + + The current implementation creates a topological ordering of the + dependency graph, giving more weight to packages with less + or no dependencies, while breaking any cycles in the graph at + arbitrary points. We make no guarantees about where the cycle + would be broken, other than it *would* be broken. + """ + assert self._result is not None, "must call resolve() first" + + if not req_set.requirements: + # Nothing is left to install, so we do not need an order. + return [] + + graph = self._result.graph + weights = get_topological_weights(graph, set(req_set.requirements.keys())) + + sorted_items = sorted( + req_set.requirements.items(), + key=functools.partial(_req_set_item_sorter, weights=weights), + reverse=True, + ) + return [ireq for _, ireq in sorted_items] + + +def get_topological_weights( + graph: "DirectedGraph[Optional[str]]", requirement_keys: Set[str] +) -> Dict[Optional[str], int]: + """Assign weights to each node based on how "deep" they are. + + This implementation may change at any point in the future without prior + notice. + + We first simplify the dependency graph by pruning any leaves and giving them + the highest weight: a package without any dependencies should be installed + first. This is done again and again in the same way, giving ever less weight + to the newly found leaves. The loop stops when no leaves are left: all + remaining packages have at least one dependency left in the graph. + + Then we continue with the remaining graph, by taking the length for the + longest path to any node from root, ignoring any paths that contain a single + node twice (i.e. cycles). This is done through a depth-first search through + the graph, while keeping track of the path to the node. + + Cycles in the graph result would result in node being revisited while also + being on its own path. In this case, take no action. This helps ensure we + don't get stuck in a cycle. + + When assigning weight, the longer path (i.e. larger length) is preferred. + + We are only interested in the weights of packages that are in the + requirement_keys. + """ + path: Set[Optional[str]] = set() + weights: Dict[Optional[str], int] = {} + + def visit(node: Optional[str]) -> None: + if node in path: + # We hit a cycle, so we'll break it here. + return + + # Time to visit the children! + path.add(node) + for child in graph.iter_children(node): + visit(child) + path.remove(node) + + if node not in requirement_keys: + return + + last_known_parent_count = weights.get(node, 0) + weights[node] = max(last_known_parent_count, len(path)) + + # Simplify the graph, pruning leaves that have no dependencies. + # This is needed for large graphs (say over 200 packages) because the + # `visit` function is exponentially slower then, taking minutes. + # See https://github.com/pypa/pip/issues/10557 + # We will loop until we explicitly break the loop. + while True: + leaves = set() + for key in graph: + if key is None: + continue + for _child in graph.iter_children(key): + # This means we have at least one child + break + else: + # No child. + leaves.add(key) + if not leaves: + # We are done simplifying. + break + # Calculate the weight for the leaves. + weight = len(graph) - 1 + for leaf in leaves: + if leaf not in requirement_keys: + continue + weights[leaf] = weight + # Remove the leaves from the graph, making it simpler. + for leaf in leaves: + graph.remove(leaf) + + # Visit the remaining graph. + # `None` is guaranteed to be the root node by resolvelib. + visit(None) + + # Sanity check: all requirement keys should be in the weights, + # and no other keys should be in the weights. + difference = set(weights.keys()).difference(requirement_keys) + assert not difference, difference + + return weights + + +def _req_set_item_sorter( + item: Tuple[str, InstallRequirement], + weights: Dict[Optional[str], int], +) -> Tuple[int, str]: + """Key function used to sort install requirements for installation. + + Based on the "weight" mapping calculated in ``get_installation_order()``. + The canonical package name is returned as the second member as a tie- + breaker to ensure the result is predictable, which is useful in tests. + """ + name = canonicalize_name(item[0]) + return weights[name], name diff --git a/venv/Lib/site-packages/pip/_internal/self_outdated_check.py b/venv/Lib/site-packages/pip/_internal/self_outdated_check.py new file mode 100644 index 0000000..7300e0e --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/self_outdated_check.py @@ -0,0 +1,189 @@ +import datetime +import hashlib +import json +import logging +import optparse +import os.path +import sys +from typing import Any, Dict + +from pip._vendor.packaging.version import parse as parse_version + +from pip._internal.index.collector import LinkCollector +from pip._internal.index.package_finder import PackageFinder +from pip._internal.metadata import get_default_environment +from pip._internal.models.selection_prefs import SelectionPreferences +from pip._internal.network.session import PipSession +from pip._internal.utils.filesystem import adjacent_tmp_file, check_path_owner, replace +from pip._internal.utils.misc import ensure_dir + +SELFCHECK_DATE_FMT = "%Y-%m-%dT%H:%M:%SZ" + + +logger = logging.getLogger(__name__) + + +def _get_statefile_name(key: str) -> str: + key_bytes = key.encode() + name = hashlib.sha224(key_bytes).hexdigest() + return name + + +class SelfCheckState: + def __init__(self, cache_dir: str) -> None: + self.state: Dict[str, Any] = {} + self.statefile_path = None + + # Try to load the existing state + if cache_dir: + self.statefile_path = os.path.join( + cache_dir, "selfcheck", _get_statefile_name(self.key) + ) + try: + with open(self.statefile_path, encoding="utf-8") as statefile: + self.state = json.load(statefile) + except (OSError, ValueError, KeyError): + # Explicitly suppressing exceptions, since we don't want to + # error out if the cache file is invalid. + pass + + @property + def key(self) -> str: + return sys.prefix + + def save(self, pypi_version: str, current_time: datetime.datetime) -> None: + # If we do not have a path to cache in, don't bother saving. + if not self.statefile_path: + return + + # Check to make sure that we own the directory + if not check_path_owner(os.path.dirname(self.statefile_path)): + return + + # Now that we've ensured the directory is owned by this user, we'll go + # ahead and make sure that all our directories are created. + ensure_dir(os.path.dirname(self.statefile_path)) + + state = { + # Include the key so it's easy to tell which pip wrote the + # file. + "key": self.key, + "last_check": current_time.strftime(SELFCHECK_DATE_FMT), + "pypi_version": pypi_version, + } + + text = json.dumps(state, sort_keys=True, separators=(",", ":")) + + with adjacent_tmp_file(self.statefile_path) as f: + f.write(text.encode()) + + try: + # Since we have a prefix-specific state file, we can just + # overwrite whatever is there, no need to check. + replace(f.name, self.statefile_path) + except OSError: + # Best effort. + pass + + +def was_installed_by_pip(pkg: str) -> bool: + """Checks whether pkg was installed by pip + + This is used not to display the upgrade message when pip is in fact + installed by system package manager, such as dnf on Fedora. + """ + dist = get_default_environment().get_distribution(pkg) + return dist is not None and "pip" == dist.installer + + +def pip_self_version_check(session: PipSession, options: optparse.Values) -> None: + """Check for an update for pip. + + Limit the frequency of checks to once per week. State is stored either in + the active virtualenv or in the user's USER_CACHE_DIR keyed off the prefix + of the pip script path. + """ + installed_dist = get_default_environment().get_distribution("pip") + if not installed_dist: + return + + pip_version = installed_dist.version + pypi_version = None + + try: + state = SelfCheckState(cache_dir=options.cache_dir) + + current_time = datetime.datetime.utcnow() + # Determine if we need to refresh the state + if "last_check" in state.state and "pypi_version" in state.state: + last_check = datetime.datetime.strptime( + state.state["last_check"], SELFCHECK_DATE_FMT + ) + if (current_time - last_check).total_seconds() < 7 * 24 * 60 * 60: + pypi_version = state.state["pypi_version"] + + # Refresh the version if we need to or just see if we need to warn + if pypi_version is None: + # Lets use PackageFinder to see what the latest pip version is + link_collector = LinkCollector.create( + session, + options=options, + suppress_no_index=True, + ) + + # Pass allow_yanked=False so we don't suggest upgrading to a + # yanked version. + selection_prefs = SelectionPreferences( + allow_yanked=False, + allow_all_prereleases=False, # Explicitly set to False + ) + + finder = PackageFinder.create( + link_collector=link_collector, + selection_prefs=selection_prefs, + use_deprecated_html5lib=( + "html5lib" in options.deprecated_features_enabled + ), + ) + best_candidate = finder.find_best_candidate("pip").best_candidate + if best_candidate is None: + return + pypi_version = str(best_candidate.version) + + # save that we've performed a check + state.save(pypi_version, current_time) + + remote_version = parse_version(pypi_version) + + local_version_is_older = ( + pip_version < remote_version + and pip_version.base_version != remote_version.base_version + and was_installed_by_pip("pip") + ) + + # Determine if our pypi_version is older + if not local_version_is_older: + return + + # We cannot tell how the current pip is available in the current + # command context, so be pragmatic here and suggest the command + # that's always available. This does not accommodate spaces in + # `sys.executable` on purpose as it is not possible to do it + # correctly without knowing the user's shell. Thus, + # it won't be done until possible through the standard library. + # Do not be tempted to use the undocumented subprocess.list2cmdline. + # It is considered an internal implementation detail for a reason. + pip_cmd = f"{sys.executable} -m pip" + logger.warning( + "You are using pip version %s; however, version %s is " + "available.\nYou should consider upgrading via the " + "'%s install --upgrade pip' command.", + pip_version, + pypi_version, + pip_cmd, + ) + except Exception: + logger.debug( + "There was an error checking the latest version of pip", + exc_info=True, + ) diff --git a/venv/Lib/site-packages/pip/_internal/utils/__init__.py b/venv/Lib/site-packages/pip/_internal/utils/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/__init__.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..32e73e263a76a57899b39d81d4c144b6f8a5cc79 GIT binary patch literal 184 zcmYe~<>g`kf?j#GBoO@=L?8o3AjbiSi&=m~3PUi1CZpdI zlbDy6SRCV6P~ehSk{IKYpPZNz6Ox)+5L1v@pj(<(keHmEnxb2tk(!#LYi5y^S)5#4 w1(J)2&&(@HEy@EbFD=Q;DUOK;3S^eV$LkeT-r}&y%}*)KNwou6`x%HC0MwB%xBvhE literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/_log.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/_log.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..427de8dce374cdd01e31527149840f33e7abcb23 GIT binary patch literal 1509 zcmZuxOK;pZ5GEx`TFbkM(Kap6OL!;>3$S%8ilQhIKN=J;)_|P^?P38%7U^9%dTdE5 zh8KHFt}Xfle29x)+MlFrPx%D}dg=_d>#hM4;E1G#^Z4c)rh`F9VEpp<%d>x6LjK0h z`e3km0#iQ+A;^dbDx89jD16<*DczAj2uBnu4K}a9^l|!Gr@!hIQSL^za6~n66u`Hf9zo4-FAlygap9hDPLxc5$+c9 zjV!{D!+3dkvUhxX$a4+pnM)}v{=@M5V@Oi)gTuWS&tj`Kj9BZIdeX8~O?2zOzU;nA znnqQb0}-zVmLKOaO#L~C1-T%GF6hKrIKR^ql9Pq|2mO^oA*sa$LTZC$AmE2-S)3~$ zZmIx955%8D4dCW)F{9Kl^@hqS1Hq|W6UQ4li zIhC^5{p#zBTxWWY|HesP8L28zZ%kh3G1fbtUA4gyp-;h&wh7VsqdV}fSQ7;xk-!VpCCy@ox!oIjZ$b)Vcl&aYvKW(VePkIYDBI_nP*RcGz^WY z4LHpxh}FO~-r0w#@uC5Ujq~1JkQ@3IdxXySATjKW|H-(+&ltBl&>IKd3Czcx|8^oLxrW-^6FJg#MP&$+TZThJBgIdrbyHyX-qXj}+0ef= zzfEa7+OfCtSjIfBI8Y|OrA(Z_5}t^}s;Er}c^G*LDbqgCtDfJ-C#S=#p9*n=-8RHB zqW&6I7BvK{?XN#PkKx4ffcPO*2url7KE|uok8iGKP}Po5wmN9G^^fd(W8JDxP#aOV c*Y9=N`?jO)cSt4O2f>0K-D1rBDBSY?17eAPpa1{> literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/appdirs.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/appdirs.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..356a9256736d5979297f349bd4b0f3eca167662f GIT binary patch literal 1615 zcmZ8hPix#p6xaOOU9G&{byGK?P{>e9K_s@Jg-}W;ZBu*-zI1z87Q|RH-ql(wi8rG- zHgcgf*Zl@L#K(LkU3=P>fev-3dhe;~tHC=y8>$`TM93Sy zXDU)#?|QQ>^~oLHNNpo;gdDEJ&jYVJRuk0SR`k~(esu9qG+ky!q@~j03}j`5U25@0 z7perUgsdu+ff4Ic)wve76sGhNpluC>cq8*#8zDhQX}PYX&5lv*qy#UN)&RP&qROhy z!?84aKSGyUWQE0}tSkh&N4ucUAhTNB=+s6o(DDMLs%4&^KNqK3S6Q*}maR6{h)Nps zJd%YH8Y8w|PADiVltHWV#A*-WZBUnnjE4DS=(g^XfI5z(QL=H z(U7DvUFrm##RQzGj{yvE`*;58`}uDuVCJ$Yq?!LzRli6p=da6D=JTmuS91h(uP!Q? zo@%vsw$wV`d-2^WGpV_7XY<6N3k8bTHp|gaSH}J7971%lgVRu40^;du%zOmx07|(= zjKQ^N>Lr{M4i}(f`h0)JpPPIe?A;B!q?WGO2j0*t0-`|#6uV?i053eh*WmvZy=0#1 zH|&ZaM*QgTBL%!60c_!N5&eF!pO(c*wm66fFhEwj?U7QLz5}YIrD-{K*|P0r#xeM+ z%!)SBZ!7EqCmVC0i8lxnG%=gxSy8`D^6XS6PSu0lE$*7OkCU}bOOtdp@$Q|kT|D!J z4d@OT5zaW_WK7{x&JPS4cQy6gj1^YiScSS#{(?LSFuB2zhwpHTk-9kA z;kwRk))fv@{`Q*-exPj{hwvF5!(+E}^)~nhB)9dRc(UsW-vB*R<(UO{;o5<-XLNN9 z2jZClzDE!1yYs+?d4|fyVea60gw>5mpTSe4V={H$xE&;kD$^wKj(m)5-=4eI2OM_o z7GARbqCc^HzAjOd8% J@ZIt5@INf*lKTJv literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/compat.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/compat.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..418b8d7a211c7e1c2cf0ba916dc6ddb277cf234e GIT binary patch literal 1503 zcmY*ZL2n~96t+E+WSSNZ3gIb$c8*0D#n zXG5y?!gA#out+VO_)ETW;xBOGdD5cABYU3x{GQ+Y{5`XFyNRIv^8SaDaRZ^h!sN{s z!Q?CG_D2{v8X=B3k$8lwKN*qgAC00J;?eJT6bpP^6ZIQBYKVl#uQ9Lj`p@xbLo~%E zZ@eZv;Tte-%@J?@fk$l-opr9?;+r?PFhS<6bE1tPXIs2|PDXEYGDO|Z#dkwjPN&q( znWH?PPKB{FSGS^2jvlYvTr2t#6uDNGGR0{jnVV{}X!6`TlTS()RK33;6?D{%d}}6L zS}-?H%bfd7>$uD(X>mTYzHxGJv_Ci*cCoJ;;Yy>jV0G6B2nqBj(CsHMTyy{kB+(T* zK_TQAIlQ76h3^z8vJ-%dBw0jP7^6!JNySG7gXMELqIED#k5323PmhMf!*1;3)LQ8` z4;F*T3wVr~ zQp}DY7sWnvY<#FQCdbdkq8NkE?NSviI~RO=ITu21Km6=0x0$^Nx^bE-Cyava;UqiG z^a9}O6)WGEGn+bTJ8)7pAWU#V>bQmLq(w}t3d+X;T~mWe7IM97fmLC#f^PzX1GqST zMa)BougN9M&LZgX*XV{^VOXnO;v0Nczak(vf{c;+2zDgb8<*$?+hbU71}W@O9k+Rj zeuazpjl9A?;mg3Gh;<=^CWZE_x=Z=7VpXs{fYmQbDf^%AKKKCGmX$WpFf|W$cRt45E0TY_E(1H)rQ}oqCtS&-T+x}P zY{^!)+3XpXTktU$Rt(ysCv%~yq$!-w?y{rW(2S}3j!pzMf&myIQ{Nn#P0wl zTTzR2q7JUKj{^IAy{NGC2{W^T87q8aX=k|+Qy(pJ<)cjIo+#J7=NoCtb(W^SA@yvQ ztC3v4w!edN6>Mc%rqeY67ePlL+dnip5m1BzF&$ zZ$iSx*(K1+$H9q-;ixxq43%v{qCWX@p?N9Aqfl7(9t?4mVE9N9HKR^@ize~Ep5vpm literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/compatibility_tags.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/compatibility_tags.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f1c392038292ac312cfaf9ded9e884ee1e5e6e63 GIT binary patch literal 4055 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/deprecation.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/deprecation.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4576bed3a560fcddcdbdcaa97dc1e47a42ca072a GIT binary patch literal 3241 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 Kam(^IeETm%A1fmO literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/egg_link.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/egg_link.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..66ca1001d0e7e9fda5c975d631fd0f052c31db6c GIT binary patch literal 2130 zcmbVNPj4GV6yMohum99>LkYA9R7R@Q;!<0*kx+>cqD_kgs)E#}7vr#+c*o8->zQR{ zHo=yA3I{HH0yrc`J`k6^a^frWfOv1#abna1Vx@UI@6Gt_d%yR7&une2;lcCEhqw2C zt$E&`s9b&mP`-p^eg=_v2}!+P`6fN$bie1r+fRc@*b51s1!-jx^`c3&S9N-r)+Y5{ zebVSPK(8dx$nRa@P2NnZzxhcmss9xA)<6$=^F7bm8c79gtrgpqBm&#jguL+D&A%WT zZ>LR)+P9e%O0u-=7i&gX9%pQD$VS{0_1thBqYch(=v+!6M{zC_upS9*bCz;>RBT-A zW2xd%s`go0yw69YI2G~`{MmzesMRDkQ{%KZ9;Rx*FcSDyO|#=zvI#FD&26sbfMB?b z2lo|N+px?v5Y{^-2}%69cNQeUbr13jXMZ#(JljehacwE1JK&B^xMc~mj2^Kx=hP}V z=t7_!43y#*@6r7!Wm%R^Ay?#$0px5R@fYaq|DIla1?89RIUfy+%a%z$X(QQ zn9Bj)>N*EI%JMCG%;|thsVoIlajT>luvE+zzuD&lh9|<(18~l0B8Ee*xwJG@BQYp_ z&061m|ESYro!KXy&$@dbzb2hoeVGA3=WAXB5NVs}IzaQgr(5uPy|=y9e+ktzeTadX z{-Z2=0yy-a0qALemrt^OCbCX0vG_dc93OC=c0PSL7G_{(c-D`Fv|K}@^Z|j?^v~Nk)y{PXoOAn#E6#B7? z-MOe!yNnj_o0=lTgThy^8!I7;NEme34jrz=+DgJj-8DHdWm446PaN{4xC&|NDu|n~ zOcR6`)<}c2NE74=JP6Gao*5`351{c*JbiagPKou;2=Q!i;+e-b)Q_DlM4P+;`ojzT z((Q@^7~pj91~wX3PiymF?gPA`)9Q2Zp?But0^XexUUnU-=n#JHcu0{9n5x4Sm1XZy z2e%kv1M?q+vF09Ca6=yp1FYInl6M=<)h-x0@MV*l0hde*WwzYG{We8@2w)ezm?`cE zsBHBV2|E-r!7DhHx-VZmeICE~diUu)jI1;+=a>88gLdgps!lnW{+s7jCz}f=Q*QpB zmrLPY#C)FEM~RYmkmb2B;vE9mfAT zT^br2wTNI`a+&A=6dj>JiaX-#w{eFvT5q7h!O*Uh460xSjeZwQMTq;N3Zdd4{x@;p zZ`HdC%X|RByB3lNNYfxqKg73RBeeyQ+Uw;9kzo2Q5JhCC88BVrFe{o(7q!nPD#=s+1%Ak2 W+8B5Z(pV?!kx%@;!)U#}(fkMU0z^>& literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/encoding.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/encoding.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2e1d0d8c3321985f14621e2e12b2e477ba870055 GIT binary patch literal 1293 zcmZuv&2Jk;6rb5I+iRyWX)q|l ztb#4)0_B3lfjbBL$b|!c&RjX=%n2^=W}R3*FspgL_cin0{^kX1Yc9d{^9LXGf3XPp zQyZ(RjK=4<#SFzMVT93`bQegww6Kk?QJ~p15slay*yf~HC7oI=cVo)u)%?Ks1J;X9UtYgaZ ztisB3n*A=_S#?h4n%c_br~M&>7hd4?#}b4mBu5^+LCVpE?07Qu!jy9eWjyv6NK`yI z1P_u0Wv=VtItb#pAK*Qh9;aat!}dAIjKcu%EW1tK!aM;DFODw2OEXBe8eW=s-;Cuj zOaDJ~;9RAvl`au{Gkplp%FkyO>r z(f-T!mq%apzU?SSK)}PHa?W|0XF@rP7S-ne^{7lS7HR`S3A!8TaYC zh&8%F>(rw4fBE|uYurVE}F{V!0&0rk>dkWre5UQd<6bd*Ig@H+NU lv|X^dA|4eDJ{zShkKr>t9zwfZS}wl2xxgFw_XF28{{upQV=Vvx literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/entrypoints.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/entrypoints.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c105a0532a17b22bed0362217c92f048eba401b4 GIT binary patch literal 1294 zcmZ8hO^YN&5Ur2yp0=F@4 zF?V{#gG^+qlTCbPI&HE|*5sQ!jo-PRG}FzL-_J0|3}+9MhY6m^$IBjFa3fvwreIQRwHNyP&KQdYSf1n z(qA%}{+gyq$iGj1h%qwpCvUt)6THxH@WMItP+1Q`Yp_~ET+ zTUDH9q}xGI4Km0HYq-ZS(rfIVxsPez*;o_YD-n=`C<4bCjPaefdnFkL8Z2vJ6g5K; z55k+sV+_ko2a-~GWcEBia19J>fGh8<^8>omqQn89M(tK`Krr@jtmUXoHKyD8|BD1H z#!*KaAUFn;t@o@7ScAn__jg(Ludlwi`RwM?%dtoVJB*x^+1uABVb?`k(E?O@<-)(H z1>D8t4~h*^38nb}=UuhzKm@KRu`E$#c1E$d)hJkWLWDX5N0;mMy$W@^D@xm}UFXD_ z_pL`qte-r2`gAm(+$*jC16AtVW1*lm620yQj?qEIB1*EiN*?9#cBfhU&bCl8^)Zp7 zd6;jg;qgTic|GPe3dojap1w7MM$yTmGP)}k%SoTJ6Z;tjj_UjA!7FxMyyMH%Pxl$Mx|U zfA~Dkyu|Dli|&He*R%&WvlU{_&=c;5A*b`>^%Pm DNlT5s literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/filesystem.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/filesystem.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b4bf69d6c7af1c031f2d86bdbb243fa4f4696296 GIT binary patch literal 5130 zcmbVQ&65+y6`!6NjkMY?0Shb(h5;LlVvyJ17{{R;o3Aplvp6gStXh{m(zI5yJDSmU zw^*b|hp?1mADpC|L#h%xwOf@#sLCOi{2w{@H7CxwIjKs1uSdJEKrUI;^mM=eocDh3 z{a$Y{Ia##u_tmje_1r!299v=BMv#ihxS!`9aH>)z!wnuNL>X^1$b%nIJ=Hy?KNs(9 z@2l=>&s1mH`>Xqn%!?1S4^|JFdOn_QAF3W=7N6sX!@@UqI2INky453S&xI@;|HcU? z!bwP8+8HqwPNRL47a*D7Q+)D}6_zk=Pq_D?yTPi*_`Yx-p9yC+7~dc6-(cZ^ubisS zea=>nqyPBMN(aMPtaM_heJGqm`(?D}_%xrxx`(muk?o;`ay5b^GsnG66kyJW&JBiXnyNy7qvZHf? zE78*>snSj@Xku(F@fwjSg_8lvkaV<60ius*zh3VyOK4WL(xj4#<<}!AyZrox3-j|8GvPb-S%2~~Kazeh+H;|t(_VH+ zoinEthoCJz7Rg$6DqVW^BxP5ez!>o|4P;F{wKEpp8*_u6tng{XxLG!H?6VNa11K!d zW+h`)V_V0At!HfU8hUnlGkF3rhOr}|o2;npO^5tw#oa>0dc^1>T&V)33yZbui;Fid ze<)}Zor{e$FIBCbhWrsTpnv9o;#Ca2f=3zvG1K1m4{von5X&+H*wbN#05*NY6x%GI zKDLE<%t~foET6}W&~+`>+Hf$c^oAuL%$qPofe19_0)n~VBo2JjL`c}1OmjAlR=JKKS9JN5ru;h&Th4M)(7A;1P_2fU-Cv*@VMs(Nl1X=i9|c3 znRV{3i%2P+P%Dh&ssW#g^}fPdBVO^b6heUXBSrJKQJrbrUytILmg)pjX6qtsbm%K8 z&$AG1M5~H4Hha-7>p{=#M$-&kW#6#9Zrb4qc@p{BwZ2<{0?MxTz(t6{+CiMu9)ctI z2oBP1;=NEV3I~=p*vgP}1WjG22a;1z6=T#(aMihH+?6f7WG`uGkB*(Ba2$%-;v5xa z8U_NB-B>+?NWCWrSAqslR1K#xPW1ssOCN<*beYYH_}TwTd zpu!Vtrw2r0G!CHccLUr*JWl#o$I7Bx?e6lu@EsN zwiL!tt})UaK297)p%2s)$fLG>iW&yiK*eP{<3_I&2-x5`<2*Mh!eWvr$nr9tvYBTW z*_17=LAFcH9t4CE!jb$dijWNvAijj!LT7`4fxaHv0~WfQ?3Y%Pg}KmsSU_K%`Zm}W zJ7^6ZWv@7f%bYEH==P5y9=Zb;(i|S|5_oMTf5}2$4h(h*3|8nNrJ&y@)>_GAEuU|< z5iAOnw_uIpAV)z5webNWD~$-pkh_%BL|EJa$AuQmIliDzX9hBQ$o!?vfl}FO!Zt`4 zYK<=9t_W-Tm7v}Td2_iHt*plFB<-vTsk-;p@AvxiZ=5^-=J(&a@b(WL(}h9r*3&i| z&y${JQ4Fk4OG8G{{|i8pg65h{=MiVniGif4yaP{ux zkM#64fc~n<^Rmot`eQEIpm^+=3381%g^PRLB#x3*L*!*I3pp2XV6i|2IkjKF4MTHh%rd5_K3F5+gnX&H-=9=pLx+jEVj05&BGgMg&JlYDJ9}ax{gK zSmgG?^}A=K>ct$n90w&W$7!9`qOYy&@@>K_1%HEC3OK;*3}Kc6=@-Z_x9n$e>pU^P zxQ!VIJwL(AkOPqGiZp!+wc@Af`} zBeFkXPm*Rboe;T*65TpY+Yk&9#)7#3fh{SC8^z*C5~j@^iLQX+4eB!f{FGDEsm%>> zi#8(ESvG-I#Hju66VXLMA@w4{BFY-Y6fp(4nfk)rN~0U;&Zd9H@a-J3{p^N$2^=4_;a0c39hJ_b-?yNof{zJA-@K z6moeX(EdMlOjBQ|}p8j0cE2pwvFjAL8^Po(og)Ta1pnqZp_~$ uzm;#Iz}5SyA0;`yJp}>EF6K&mOGgeAXY(a@cI?0Iv--CH literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/filetypes.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/filetypes.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b3c1c73c8db10c4b7c81b34347fde81344b099d8 GIT binary patch literal 934 zcmY*X%Wl&^6rCA6v6JRSRrMhu;T2LA^`Z*|s6v#Is+FpOniML_!kuI$jlnO?IDJ@U z1zUaqv4AE2!WYbzReymMciae)k?zr*bKiG{Hk)+>=gWhK!(RlU-}*9t47fZ8kzWB$ z5JMhfn2`v_#3NYiMr6dMXM%2e6;|=8oN$X($7BO>n_1h4*xH)!^iBu8qyE9G zqkgwiSf$HVp*`*}DrO`owbB|DF;&e|Z!Qwti!f6y@8IoRy z>koy=Gib7eE=Dm<(Wv?25r#QQNk&IBvqlz1oO1hJ6w^O&Y{mAk*2r12IB^Rstu>1q z?|{YS7Pq-QCd)`K-UaJUjEAV({u@q3gD%nTX{nMTXQ{T&sxswWtR2BsCGyC)tUnkg zeP|N?2Pt%eN>AY%1l!@+moMuW>0hMDdF21Xg@j#wsYH@rJn;+R4~m@o$=J^e4ce9x=s& zlOkeiaK^JTD3kKA%1ahq@%Zq1!g+f5`4^XojO5I$1!0maE&z?7Qb{U<`siLc)%V_X zi5&w5fesO2#v6zkyGel>u_G8LbcthpMZ|tghG=$Qky{$mJA7;1p@1yV0{?{a2NqJc za#U+fr%y35@6V77L-Yxn8{(|lvmZs0F){U%4Cu;uu9zXvFUAd^TQDxME@W?sXHVPL zN&eZV1O0Y?7=Ax^6`mY_+YevAcsV>i9duny$kNlA{;=(NY0pXM%*hQ} zP}Q1K<=zmP&*|-sp=Uwov_d75U<@Rj3!KkrEUo>&Cc3OpqQj$dBlM_s23;ZQ4#a5 zCEhV12c;+?E@harj7vy;E*=>B?pnERv*UonBWUs=bchn%hSvp_2=;KBy41xE@vujP z@!a6b{H96$nydF=V1#0U=AdvD5*?GuF`c8a`8Emt`xzv&D*Tv3>17G1gqrY89q~LL zo|VKfUm2w`8Q(~S^gjZqo~%@->t9cjXaXCKS(PfYH`KnGuDt8blH8A&Y|cuH;;JhB zF@uut)vHDsk@x_vukE_>yST1!P{+LuCD=kvyDQEH5Gzg6BFDilwutx;#$8XCgcn9Z zwFCTt4hjR8pr$i;)#ubTP=i~Ct({WKo!M8rUuQ*JrTnQWk6M#mIOr|fu{#HykN*Xk C=dN@B literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/hashes.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/hashes.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..300d2685248bf6d469f67bc1ebe186eb6c34bc5b GIT binary patch literal 5179 zcmbVQOLH5?5uVvyJO~01Mbfk=%ko-w?7)#|`B@I5D3T>vWMV^(DBC5NuGJDV1eRQ2 z!I=dqqQFB;RY^YBuAJjkkvXJF|04JNgT3aIb8bG^`Fa*40ZOV$Wm!Aendy0Tf8G5J z{ZgsG@O=ByYb*bpWb9v58Gam8uHe<*p%6^)kk#nd3VF+_SuML}x15^O%G5HgY%R;F z&kl2~d@bJ^tBth^wSsAL!tqwIR^&`t>Kl)RJMF|?5o!uz#?GBQg&%wH!3ZL>Bd& z$Uksuc{wHvV(bSl3S#_$v&(Da7@LtrQT)LcB~gYiP6FNia!Ph)0U?L~1Gwddpv>a?4egp2y~gT1^g z&Y^ZnSg_HnNtRS4bmo3+C_yG)4aPh3SqpkLZMidEm(+|5+7ff@tVkOyhnk1`?S?U(ld+?CX3D4K? z>UU8DY{%+z!Mj|&(dT+|kaR{(BqwCeg{BT_-!Y`JZ}CAHg$f_4maxpCx%fS^u=!e~p1!`W!Yro4|y z8WJLh?NtCa6U4Hm0jEgCQY3i~2&KUQzoTWis!rlONp8@Z*w{egtjlfvn5om~`ti$a z^UI%Usr0hnZu@%qYNvDEkNxG3qq-k1-;u4(awq6q=(an4eO-zRTTLm$3-5oh7U;U} zQQxwMGf35jcsCA0y_~9guCtBppf89$?Li6|L|=lO(H=Dias0Ok&4V5Lk1n<|BX z!$vGb)}hy?X;x6gtj}Y^;X=?)Q+V}R6b;sAU(M|B zKF74|5u0V3OgVl2XKTY*N|jsT>N!Z_VAkBlgl|5!)G5@}3>Bn(^#Y2daEVM`k6N9} zzd`*!cv}|H&zrjxl0o!kd>jbF#)SZ}31JDIp(bdqay5zFBL?eIy|Eqmf9Zq)N<)1UoHY~xG*kfKrw6#Oo zu2_n!lH>+nk{;_w$zzuqvMuj-)a5G>Q|D0hUK<=B9pcraZaW@Q^uYkQnXS96RF|(| zAWnK@!lNaM!}DB*oF>pPt2gzObuj5z6QRwcK#&yR-(EUARU)1J;Gu7V-Zi|Me1oFS z8ruW(8f@R%gdQrq_hy=KTsSB>5k*J05p2r#Q0#C6jSyr4#2gex;7sg>MCMBmbP)~e zEh@~Zj*fOB(4N`tVDyKOIXK( zc_-7)?B)B;J_l}=H$FwrnCWp%OwabSdxd?1BpK1(!ir}1NyB%ytnm7Se%KIr2ldPv`Ta{dj4oZ!Q(}-fN2q;O$oGNi>F~BH_ zkE3SVBx-M6R72R?*&qX)N@Z8uf{P{6;U9Z zQoMW;UgUPtNUJ$_cDZ%ib|7ZgIIdxY;X3d_8=*Exzq9E=99-K1LW}d3aD2@e9+b$qM;;Xt&- zCS)}kgaK;LI1h>@fCI0}J=>RKH6sCSU zhq;bh0d$E3JTFA&L3ll)Non5*F&aTS;g*yUyV4KW8AZC>L_tWg} zRDa~>M`j^I(R!NRH&B28oI|+g0FOmr#=$EDu84tK^dfgJj?o#&l4|j)bRKLdOnSLPq_T*7<~rX(~vy zCZ?)q7(1P-3o%Xcfgu=z9b5UIvOilt5Aowvt^%$zOO%=zgXbj$&uc}Z8`5{t^ESGE zIOqX|6H(ps6e$thC02^gqRvq9I<@6H3cjS`?ZgIoS8r0s0u}F2L1ZJztZc_pr{RM_ zpt7kTqpF)!ETTxVX>3xzrDw!0-?SIEKXDA!MOE=l^Xk{jJX z8K#{E=f&717T<;54E^%!F^rN90SO>RHZ;auWle$whd4<6v^T>MJ!9%q8v92oZd0*Dg>fN*q`E@|O_h`e=dQ~Tv3qE>WfCz< z-o@9S@S2zc56Des6}45S)O+|zvhj8YHdYkRQ%5svkRuw`O-|vWJ$HD~o;yT`PC1M@ zH4(bwg62j(2l&zjFZXR<>r3@5z)3l literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/inject_securetransport.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/inject_securetransport.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..aa550fc69cb64b8543a1cd1210bad681cda7faa5 GIT binary patch literal 973 zcmZuw&u`N(6t4E8I<`P^Ni3BguTuj)ePvhl z&o~f;_DsPzK(d+!>X-EAG#P|D(1gn>DN;Fu@`H@aFgzrw0iLR*U>e{%0dnvr!^80O zQSdlu{eibdeIFNf&26q_QpT6d0cQ>NK5S#bSTw~9&s@F9P>9agK?x+B3-lhzTOP9R zBEX;pMjt@05Isbn(bQw^tfqG>d@3FD?%^NJpQWl$#jo{? zI-~k5l^WDVX}g0uK)7uxDea|{{#xOhg(;eupmwbE96}?C8wZuTJ*|~4wgzu|eR!1k zUGFG781&=*@taq@qhdQtvmid@k|`bJT8MP?BuJFBIvr^bnih>gxGZsV`Sx)tt%_Gr z-_Z>KRmfjRZ-D=Iw*NdjHe8#CN=Z$$mu0W1rO}~EsECGqo<-2Ko6C$QAXgXU4<2dhdG<4#^QEQKZh6B}y7uq~!Q!w6YFTHa9Zmkg~PzrO_Bp70IT0y2sT$ zk~kRdCQEJBPNGfLxqyTLq+nkZM6=dBCi}gOQuU_&>^?t9vKHv@12fe|1*(=xg zdHd=^-jJMUhx_XXyaV-v-og5?H(WpD9g_V{I8q<=MrA!09vjGJX$~I9h3D! zc)WhXJ0a`E(5;{JPRe>;_(J`ZcdCBcJ1yI#aIAjDJ0t7;;o15*@0_d;gq8Yv@4T*Y z=gEstHSYpH%?3AgZ~SeImD#>W8r#PwHcam#AL5rrHGYY|#D+Fawx1n%WO={Fwbhr| zi~JQn!1Pg#4R0Fk5F2@9V~1DyD{ORAXNTDl%zO>|9c9O`-!X2izK$K=;Cb{NXD85i zV#C0SH_>+4NwiP$BbYIX_6zJ3+NZGQ*H&~R=BVai1%pBXc^GxJ)s zmgR5I*auaSA7t~hXsYWc6&D=a+uJec{ z+w8!BK(_8WKvRZ$4W_IfK-FYk< zo|=AdZu-WxJ2SUu{decz_R+dI^8<_&d6YB-_gNrX>AmPjnmRvOv-@xU# z8`o-0k+@5-aMKm;CUOTn1h3ZJ2P;9y-4Gv!{U+p2vp|2|_oHf^`+ipR{d&xrA=OL1 z|8cV#c1Ci(&*GZzKhwksoLPb|7H&)~yq|E9EL5YYnk-yvG^W5E3%BB0HC(vE>x~7V zV!RnOsQ510}fx(AH9|sfiLXbE+o?2+yg})>CuCh$q_m zs+C%+Hj1-k+}DT(vv+P*a@pW6{E9=^EGq^{5G83fs_`rbej)bBY%W9;XU_D@><8Cw zW%l%YGw)4T3_+hDULdfAIN{PR2mK)N7bT&6po06@AQopalt}ff=XJ}rbjuLu(f2uh z6L{2&nssps^%^lz_eb>t3UOL81(0eR_)yx^@?1s{aky zAC-5uFF~gR2}bL_WRh!cEe4q$rf$6&RUs9`NwpRCK@f&+t=deuWH!*w1-~|$shh^` zB6kBwE!Hu~j@4*QZbq}}5DV;+xV#>uGy&)g7#5^mt~9ej$RN0bcBqox0CQrg545K| z>)SR^(ZvOP@ow}M)f8Iv3SmX!G?&*0bVJV@g1F+Dt}uz}j-Q2=WStT!DR9MfW^9;} zEyP9i3Bori44ko=rb0|mXOF(J=29Qbr`k%gr!Lz>q#Zw}(@H#4cB%trZtC3PHn*6? z>`m)u+LF#3mU}edIXuVnJje2|Dg{=At}gK6Y9D&~HVrwi#QGn>hW<>mG_N10AIOGg zBtjwnH)B!9(Ya{t8~bp4tUf-*?u@-NIri@4*!)c>wEik%ej0#MX|>)UHDOi7av}(q znRD-fZ0z7e!UySAm5woV47 zs-|wd$k!6dUp<1JtL)~;iQ?8ylZ~o?vfFX~N$kHE$04y~Py;_jTdW!e5g0L9iJKuK zrfmqm6g=c?Yd<>OgCJd@GX%mFycP>~7DwtLNAWC8o2{4%L3Yw?aF{?J92}&+Pv}c{ zxFko#t3Zr+4d5B2#If$HHId{)RaSDnxBZ+w6aSOQ$+oUf*FM9AQ6bsR$(nD*ewF-By z&CSltzCG!-a?^8jx929^ij8kowk*qahO?qPO+xe%Bltw;)xVV z2tc~}iQd+q>g&+dPar2SNaj;x-E5m}4X@Tg%_Wsj)h3O@Y{-Q8iw2v3Bc z{V2%+fMtC5N2PWB6R_tY?H9(!*8DcwK?NHVmokgq4Owy&H}wQ5D_#!ade-84-WvVZ^H&DM z5iAj;dBrh+Y(L{mRd~u$mHVA9p!hAbNFPc~lbP@jGZUVe`nI=dxNs|8o>Lr5=gImz zdaB05u&b-249Ua0m?B;VcpF6$j+__cE6XroZt?eJd2pyKXVfrb$B*cJ6-7E~UF-M0 z#!c8f{jw%)pMj^ecd&=xZDy0TV-EN^*R^S!ZHp3$;J$9e;3)ou>zIQZBjb!*EJKmx zc^yfDNe7}+CZvL)6-o5;wm|}!8c!gU5LByeO=%yUTenjPCyC|(2pPFnZF?Hw>^rDo z1i=~geSDNDpHke!j+tJB>VkTp6ADr@f(Y&PNsjR)%LwuWDvsitAJUWsfGnS=P$tQ2 zHSHZ5+NH|MAP>AVzw@!a|6@!_$d%E|0qC$i_^7D2PAM+hjy717ohxT6#a#>~NF!#0 zz7LN-R*qSMRqvx$&?`hg0W$xhN}zW(S#zoH2LLS;>5>(Vyq*J->e)KwswBa*>e+GIzavu3mC2vrA zOJ#6YUv_{3NyJw3GJNVplv(~ara!!Udv0nT);@DoXqDxo7zhtz@jOeJIDHOKN{O#UGl(U|qvru+ilZ_nPr3#=u?Y+?z^yh0K$rTzm^ZQQKbg17=* zEAay<+g?#trIPJ*H>&B1*SE4QHnyZDlR~ekMe%3XHgeSEiC(WmgS{`V%A*&Wv7ns)6#b;DY;TqqwMLR7q zn>mkRYNO#!e?R&^Lw`>7w?-h(1FM5=i{)7XBq~0(C}fI`T3T9O`v)Bo4LR4I?4x(; z+J{bbb3}z#Er~OWcFexGwaE6W`;acp5z$qOvX}5kTgQlhIj)?$8`M~ zWwhR+iPs5`krh`75HDqRL%;-Nh3SViF4be!w<41$GQRC9BWc9QYw^mx4^*M6)MZ(& zW81cgzDwI%6zlyNYRPE;O}ESusG$KE2dgR(j@sFyhnC6gc1vh9w-Npz^ZfwZtaaip2QLP>@JH1mLCd}A2K*M?d8%CPeP zXE=`0a`(jCc5?39t=Jhh6C|F35($EYRNNu3NPwbeF;9TBfsjn}0o4)$bR=qvyh)e@%<{9b+E)!eFFlW+F%0bDFphNK3mC& zQOwGWILR#1s96p1EVXKBDc%4IUvQA)}35gj>fxe~+S~I(@V>lkVVLWU!l)bqoYgS1O@q&WRH&Fj5q>t*6c82Cqe6OkM~n<;yq zqv4jsoX4~-4Jnn(k$g@brh@9X#Cccdt$7#d22uK~)Bg9?m>rtbp!+wH+e?w8! zFf2<@4|GofHhM8mf^<##PFX*)p+aUV@pAsWH%JUfUe^uU>_^Z>ZE}5VQKnSPx*1KO zP0r8p6h*qrXMGGg!%btozy{bLE2CCi#!c2=!KD(v zVnfS%WGrjQNc7=7`6mVV)40z<-DC%$ABM@vVuw&0*{Y3hnsBXfm$hlgC+@Nk!5!Z; z+E%;BPK=T&C@>fL{Um!~*UXX9R-1+Qa=cfNn}eW2I+X+6 zC=>^YMUoA5+r9g-EZ-HGo2~QT_2QkXwqkr?oU2H?(HiJ}jZ#-Q$j=D@78&N&#qZj4 z53PZq3rLo#&PSR%0#%c27~GMHpoT~A~!P?Pe5Hi?wtGXj4|fab#&|1lm29q6uA#cYK6ET{)cU~hGWO-6&((TFfs1`F|C9@e1t7~#G zTvzGh{vK`g`vfRr#P`XA=9T9ul2)H2#(m^I5GvCc5;!@i(1dPyMp%%LW9{>Y$iCqX zq(>n>i9BT1$+W@KOT?dJX=aHyPE`^ZeU*Nt(m$cMA0%*oQAzoCBVO0?3NE8c3Bg$oBQ<**S#x1KRCnfJ#YhP+g+$k=#%EJwC4H7QyH8 zlgmM*Sg6a~*?wfW19bzwWgoI4eS$BSXG01toXKI;*9QzBA5GV{NjBI)qq;HR3JcrJ zl}l&ohyH3dzUa@9P}TE>V-zi9>hR|v!)RG$3%R%Xlr zxsz4=Tk9KZM*Iy<3y)9+QrEL0s6%&;VX!DKM|llW7a!r|v$ATt9ppwHAWlq* zMTis`N!MC>bSmT}4%{YJC#dNHWckbL|0AxzaZ?xV9ZBj)6{RoE86%ELWR#2&a;>s1 dvz%pTxZl!81_rF5mkqrQ_h!5{|`>gWG(;z literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/misc.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/misc.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ac6c827daeed12731772771fa80d46426dd4c21a GIT binary patch literal 18790 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

7wj7G8$E|iLHm$1N)(I!T4YVhytphTZY#x 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/models.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/models.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ff6d910b4c11d5d20870ac17e00202d19b4665ff GIT binary patch literal 2052 zcmb_dO>Y}T7@pZ(f5fpJCr#6as%0xABp=cP2S5lRN{|o&BBZpJ#nNcJGl|#TugAiql@s%T>c(y{IQ3A^lQ=$7u&bY8X(WgN?KtV{3NJl7#jUN4|n)A=18 z%|L?%j^cr<9Oa%mfu|d~sn~u+kXSl`3h_tbsNZYvKm?3cUW==m4Y zYIT?;xitE_=;tUs`{;X<{TL}|6IR2K%~C&-gZqkEf9h?HSFDM3ffVq*y+K+t^XC(WYip?V)`r)TawoFF^Je>{q-(!Kcn|2%?&mi$ky8yliK=HnPY} z*%Ts%CYMf4a|fGma5Z-^wu`!?`CyG=WGDRZw9FkklMblJXd%oVjnFf_R?OT3r24Nc zVBoD;oZ>2PWN{x1-nj(}GVt~+)@iX11`lt;;{VV>zg(jQ>EPdj1sNE+hFq&`Cc2np zs&?U<{9 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/packaging.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/packaging.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..498360c4f22f545b157a555193ff29234681299d GIT binary patch literal 2072 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 rXXG|g!p3xz(7!3>nNw!foOBAr^=G#Yx8Ft&j7g literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/unpacking.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/unpacking.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..406d6435e8f13f215a3d68eac6e001b3574ddd9e GIT binary patch literal 6715 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 lAOJ9^n literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/urls.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/urls.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b70a82f727e0cd20cc64fc79040d5346a76d834c GIT binary patch literal 1588 zcmZ8h&2Aev5GJ`lTCIL!v}p_n1#4N~R{ubpoO2?dsHaUrI9oFwn!1 zoJc%QLwyLL5%nPgm_g)zm70-4{X20pP@vMqy$usX#&p4)^lEZO&*+>Oe;h1AL1Anx zBBy0@T4UPTY!q{N_R8W|D#KHb=WtWP>_wK#UHh2W#~SUO*?rlpZ$wY*A|(c4bF44lJW)3Q>l4&2p7MX4ruplyIFHwhsVd3I<6 z*r}y$034TDVH--mno4bK8T<7Wpa1?z*f#WwwWXQM(~*OceT>~ky&)VP6nWV?6vdo3Gl zgPc0apdH@BUGIai5ndGASK$^Lf0yP{`ISnqHY4TmN6(JFWk0&~9&M|0==T5q^OT!TdSC#9I?@-zJZX>5@QemVHIS=+lA HuEqZXL41{x literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/virtualenv.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/virtualenv.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7f51618f7c69644f5e496c9c3a9e6b635f478027 GIT binary patch literal 3278 zcmaJ@&2r<$5uO1+kfJ1N|E#i;bv&_Ck?E4SO68}vT=piiR%^SmkyR_XY_phPN1P!E zEeIep18K!bCnZNGFOY+D%q!%cm%!C0zk&~myJtv|(kdnkKRp;=y1)MV>*0%wbppSy z-}?Ff*&-p|pfUUN!T22<`rmL8M9_q^-IcbfwY|1yuYTLN*PtE1)k`YFupJJo?J6ab zoY&;s1#Q=*cRnwCxLc5mBKRj26%qb5Xg9`IRn)**8e4Os4%RJMm7%=-26=^7q)Nhde3dBclp=(&LGi%_c2FB~78yE`EFV zR{>)a4t)JdKcL~&}Q0+c(2i4)x!y9eI2^5gPuq>40+(|%N>LaOKx z#v6#52PaZd^KgCzS|p@}7I|xkp@N=y7SQ2UK$Yal1W>?COLG&1Hvz`F@UD@99mQtA z^5dMZ=n1mu`WVld1%Ou70oMqj3c;@_itY}5Eq{6~TqXNO!Xa#zGx+i{Omo493W0bf zcnX6y_yxEzTA+*3=}J;!v`;IN(#;0Ej9+%x_`An1j6N=A=N%jFNg4@B)u09Q#;du$bR}DKSrjty1l-wG*`n=h(<#t0b!wL7}qQTonToHuBp_n z`W(cXZD*-mMUZ0yuM~-3X=WG@LOkHzuGE?VrmPny(vf9UpRPHo6sEWK5Y(e4({3h! z|J%*E(#v!i%sl&%pTPne$wVr*sOLB6I$faZM_^y!o(}^795#bHaD&`CC6F^( z5Ov=`HidUVDG{J;C*(2t<9nyn_~*e1y`ZPwi3jtjVkh2tMFbb1`Y$}i-0VLy5kjV_ zyba{G70jOhpKLv6y-cAnf=sh3G7a9C-)Vb`&y%?m@47g#SQ0dL@b0`%| zp)T?~(@^>*WBbw;`eCf&{RFb9vLU;ypIL=nWzVPSea?mj@CJ#*ZQ`(X*|Ox4tYZwnvtgzRHRmy4xI9f-92%FNy(aUoD9=i(CjZ9q5-ZQ=<}-`H{j5sisfN@ z*MA)IA&qaR*_!j|>Q1C(UYfU=d5*YLOhMqZ=xgY<4^Ua#N4dAFda4M@JhHb%6 zmQ}v5o$BGTWi7J$6-DYUP77VUpl}QLI2vXmf;Y?i)5O{F$#%`Yd_B$YMAO-Bqw#9z zMNM-$7%tP0der-G5U5ocy^?CMq2-Kq@IKt24ypy$gN+CGuNxoxvE6feqfaIcgR}iC zOC(QMFA<-1W`^y^Z8p;EMty2MX$Gz}Bl}!`M(1Wiwfi=!^!KLeo<{yBn62?K2|^lr zc&Ih7n#*MsD-O6|(^Gm%sug%(8&DaV;~XC$$CVGKat_+aQ&*ypEX*M!>rH%8#ce1w zABCHNGQfamwiCE3fK4ZCkg&VhDzf-mFK&#Z_5q~3NaQ0#Tr)V;p#I$dmRF~)G8?tV NT%)qQ)OfSe_#WEkl<)um literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/utils/__pycache__/wheel.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/utils/__pycache__/wheel.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6ea7a1449c3916c0e915e876c09a62cc4f807377 GIT binary patch literal 4468 zcma)9Npl;=6`l&B3%hwP)66WLeJ2A|89gI&X;b zx3)MTDqlPG)7&#FCebn_PNL-ux11HzXgMWj&~lDjY%z?2yp3+uOoBMl-bSpvtysMdqD^lr zNLt=jOUlsO2tuiAJ29vVl zuz>zkO+SjGpy`J}DjSjCrs>l!BAxF-id9;xYW-kh6-BSAolWot8fnnU9Ga53N+w+u zH7(l9@aN)7X1<3U#6-zL$xf`Ey=(TJRU^9T7>T|82h-@oq!?`r zbKvyMq|htuntRr+`OaK5zBGi@FT5>8<@~#7EEqBu=bI!9n7+rA)N9?(3jg_VCk*9|>OxD4Xj~ z`LLSh(DA)^gUdA$=wyMG^F*LzGl|umumfhqR4wbNgz7PHx0-z2_4;u{d3P34UvQQ2f(ekkvc)6OZ&1*`%;TTd6_A{H`F-{`>}p+Y3&8PORxD+AGRyd@m{aDbR@qYL(FQkkb=*}=$(vUdw2k>+ktX6{|9gi5 zfymeJz=5%6+&AEJmav6`7K>|k&(`yaDd21G%-k!5``S?t(N-MTq6A;G_sl($`g^vR zIB)bF_@)C%1$@!ocYB3_+jI9!{T8#z0~>zn=APSg;FTxRzx^-gX~t3F2N7K4LvA$k zJU`G~kcd*%QzEfAvu;Q3eUPjpuMNAsGRz^EKG07be3 zmje`8wZ+WruruYaIgH9CZfTj2bKYJ+_1}1m^h)m2V~$_D6_TUr+qL}($972s!n?eH z!Y1u%Lm#9@RejFG(l|DQXgSzX6mEcEZ+(dhP=;f7@<78(yKqc z&;1$c<%8u8VZ^?rSYK(i-3^lfu>B!d2w;D<>XNt9Ppx^6)tlbNWBCPuKK)htbz z9MzdlvZ;NB;rbDMs!2?_f=B-xFQYhPO<9gvvMQ!!PQ7=Wl2tNGh<(d+Oy|Az-f?+G z)#jaK4xp@cJoasf+UK4psH7E&`yQfq6^;R(L4+svhQ0keunl+vY~u*{@i*|`p7o9O z9in>3Ht2tAfo=FpY$G6{YOkaxn{hW3tXU;};iW~UAcyaClz?9--NM0uo^$+3tz zuAeb(-oQkh9P#@dF*9*AGc$B%56nHF+>o2CF>Yo(3A+7KC@d2J1a9xMkg zg7*rmYpA)z5Xh*&Q6^i@O3#w7Cr-~A6a?(Bi%e=51@87s)1W`hDX`yjmi46(S@3hp zqug};i{OonjwCKnJtsk9sSRa{3orBhBe%i-YpTiB!*f^C%eiX=+G__eJ&ZOsATw*} zxlyJx)`Q?H=2%vMwUD0{63TxwyX|)}8(D`U-pa}^{ji%`86op4YN`wqod#R(44RI_ zqB@DTCZ0SeaR`@yPO#ot*pGW5iziYxbv)>ZK8X+6a8FUl4F}c3d`L8ENExhw1vA!Ta?lT24m;X=r%F{eeV87Rt9&Gsv_XtE1h%=V$WcI6 zoNo9n0!Re-7KR|j#;8LJ^KL$owN39vZPB~!U9VlQe#VJ2?VB?6C{J4Qb;%ukZ)h$r zj>2ttNrVMQP5Ejp@OtgWP~h-D!!b*caASde1D@PbQX_bC!DDLhK6ylEnfD&i3RT_) zapsao@BBn`7sKk5?c(-D3d&(ge$|v6zIFKPaW~2D4olppk73plAM>Ye;vpV3DHwSh zIq%=y=|h=E_Po=t(pX9>j;c9np<|>d7z74ZH{pxvrwPx# literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/utils/_log.py b/venv/Lib/site-packages/pip/_internal/utils/_log.py new file mode 100644 index 0000000..92c4c6a --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/utils/_log.py @@ -0,0 +1,38 @@ +"""Customize logging + +Defines custom logger class for the `logger.verbose(...)` method. + +init_logging() must be called before any other modules that call logging.getLogger. +""" + +import logging +from typing import Any, cast + +# custom log level for `--verbose` output +# between DEBUG and INFO +VERBOSE = 15 + + +class VerboseLogger(logging.Logger): + """Custom Logger, defining a verbose log-level + + VERBOSE is between INFO and DEBUG. + """ + + def verbose(self, msg: str, *args: Any, **kwargs: Any) -> None: + return self.log(VERBOSE, msg, *args, **kwargs) + + +def getLogger(name: str) -> VerboseLogger: + """logging.getLogger, but ensures our VerboseLogger class is returned""" + return cast(VerboseLogger, logging.getLogger(name)) + + +def init_logging() -> None: + """Register our VerboseLogger and VERBOSE log level. + + Should be called before any calls to getLogger(), + i.e. in pip._internal.__init__ + """ + logging.setLoggerClass(VerboseLogger) + logging.addLevelName(VERBOSE, "VERBOSE") diff --git a/venv/Lib/site-packages/pip/_internal/utils/appdirs.py b/venv/Lib/site-packages/pip/_internal/utils/appdirs.py new file mode 100644 index 0000000..16933bf --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/utils/appdirs.py @@ -0,0 +1,52 @@ +""" +This code wraps the vendored appdirs module to so the return values are +compatible for the current pip code base. + +The intention is to rewrite current usages gradually, keeping the tests pass, +and eventually drop this after all usages are changed. +""" + +import os +import sys +from typing import List + +from pip._vendor import platformdirs as _appdirs + + +def user_cache_dir(appname: str) -> str: + return _appdirs.user_cache_dir(appname, appauthor=False) + + +def _macos_user_config_dir(appname: str, roaming: bool = True) -> str: + # Use ~/Application Support/pip, if the directory exists. + path = _appdirs.user_data_dir(appname, appauthor=False, roaming=roaming) + if os.path.isdir(path): + return path + + # Use a Linux-like ~/.config/pip, by default. + linux_like_path = "~/.config/" + if appname: + linux_like_path = os.path.join(linux_like_path, appname) + + return os.path.expanduser(linux_like_path) + + +def user_config_dir(appname: str, roaming: bool = True) -> str: + if sys.platform == "darwin": + return _macos_user_config_dir(appname, roaming) + + return _appdirs.user_config_dir(appname, appauthor=False, roaming=roaming) + + +# for the discussion regarding site_config_dir locations +# see +def site_config_dirs(appname: str) -> List[str]: + if sys.platform == "darwin": + return [_appdirs.site_data_dir(appname, appauthor=False, multipath=True)] + + dirval = _appdirs.site_config_dir(appname, appauthor=False, multipath=True) + if sys.platform == "win32": + return [dirval] + + # Unix-y system. Look in /etc as well. + return dirval.split(os.pathsep) + ["/etc"] diff --git a/venv/Lib/site-packages/pip/_internal/utils/compat.py b/venv/Lib/site-packages/pip/_internal/utils/compat.py new file mode 100644 index 0000000..3f4d300 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/utils/compat.py @@ -0,0 +1,63 @@ +"""Stuff that differs in different Python versions and platform +distributions.""" + +import logging +import os +import sys + +__all__ = ["get_path_uid", "stdlib_pkgs", "WINDOWS"] + + +logger = logging.getLogger(__name__) + + +def has_tls() -> bool: + try: + import _ssl # noqa: F401 # ignore unused + + return True + except ImportError: + pass + + from pip._vendor.urllib3.util import IS_PYOPENSSL + + return IS_PYOPENSSL + + +def get_path_uid(path: str) -> int: + """ + Return path's uid. + + Does not follow symlinks: + https://github.com/pypa/pip/pull/935#discussion_r5307003 + + Placed this function in compat due to differences on AIX and + Jython, that should eventually go away. + + :raises OSError: When path is a symlink or can't be read. + """ + if hasattr(os, "O_NOFOLLOW"): + fd = os.open(path, os.O_RDONLY | os.O_NOFOLLOW) + file_uid = os.fstat(fd).st_uid + os.close(fd) + else: # AIX and Jython + # WARNING: time of check vulnerability, but best we can do w/o NOFOLLOW + if not os.path.islink(path): + # older versions of Jython don't have `os.fstat` + file_uid = os.stat(path).st_uid + else: + # raise OSError for parity with os.O_NOFOLLOW above + raise OSError(f"{path} is a symlink; Will not return uid for symlinks") + return file_uid + + +# packages in the stdlib that may have installation metadata, but should not be +# considered 'installed'. this theoretically could be determined based on +# dist.location (py27:`sysconfig.get_paths()['stdlib']`, +# py26:sysconfig.get_config_vars('LIBDEST')), but fear platform variation may +# make this ineffective, so hard-coding +stdlib_pkgs = {"python", "wsgiref", "argparse"} + + +# windows detection, covers cpython and ironpython +WINDOWS = sys.platform.startswith("win") or (sys.platform == "cli" and os.name == "nt") diff --git a/venv/Lib/site-packages/pip/_internal/utils/compatibility_tags.py b/venv/Lib/site-packages/pip/_internal/utils/compatibility_tags.py new file mode 100644 index 0000000..b6ed9a7 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/utils/compatibility_tags.py @@ -0,0 +1,165 @@ +"""Generate and work with PEP 425 Compatibility Tags. +""" + +import re +from typing import List, Optional, Tuple + +from pip._vendor.packaging.tags import ( + PythonVersion, + Tag, + compatible_tags, + cpython_tags, + generic_tags, + interpreter_name, + interpreter_version, + mac_platforms, +) + +_osx_arch_pat = re.compile(r"(.+)_(\d+)_(\d+)_(.+)") + + +def version_info_to_nodot(version_info: Tuple[int, ...]) -> str: + # Only use up to the first two numbers. + return "".join(map(str, version_info[:2])) + + +def _mac_platforms(arch: str) -> List[str]: + match = _osx_arch_pat.match(arch) + if match: + name, major, minor, actual_arch = match.groups() + mac_version = (int(major), int(minor)) + arches = [ + # Since we have always only checked that the platform starts + # with "macosx", for backwards-compatibility we extract the + # actual prefix provided by the user in case they provided + # something like "macosxcustom_". It may be good to remove + # this as undocumented or deprecate it in the future. + "{}_{}".format(name, arch[len("macosx_") :]) + for arch in mac_platforms(mac_version, actual_arch) + ] + else: + # arch pattern didn't match (?!) + arches = [arch] + return arches + + +def _custom_manylinux_platforms(arch: str) -> List[str]: + arches = [arch] + arch_prefix, arch_sep, arch_suffix = arch.partition("_") + if arch_prefix == "manylinux2014": + # manylinux1/manylinux2010 wheels run on most manylinux2014 systems + # with the exception of wheels depending on ncurses. PEP 599 states + # manylinux1/manylinux2010 wheels should be considered + # manylinux2014 wheels: + # https://www.python.org/dev/peps/pep-0599/#backwards-compatibility-with-manylinux2010-wheels + if arch_suffix in {"i686", "x86_64"}: + arches.append("manylinux2010" + arch_sep + arch_suffix) + arches.append("manylinux1" + arch_sep + arch_suffix) + elif arch_prefix == "manylinux2010": + # manylinux1 wheels run on most manylinux2010 systems with the + # exception of wheels depending on ncurses. PEP 571 states + # manylinux1 wheels should be considered manylinux2010 wheels: + # https://www.python.org/dev/peps/pep-0571/#backwards-compatibility-with-manylinux1-wheels + arches.append("manylinux1" + arch_sep + arch_suffix) + return arches + + +def _get_custom_platforms(arch: str) -> List[str]: + arch_prefix, arch_sep, arch_suffix = arch.partition("_") + if arch.startswith("macosx"): + arches = _mac_platforms(arch) + elif arch_prefix in ["manylinux2014", "manylinux2010"]: + arches = _custom_manylinux_platforms(arch) + else: + arches = [arch] + return arches + + +def _expand_allowed_platforms(platforms: Optional[List[str]]) -> Optional[List[str]]: + if not platforms: + return None + + seen = set() + result = [] + + for p in platforms: + if p in seen: + continue + additions = [c for c in _get_custom_platforms(p) if c not in seen] + seen.update(additions) + result.extend(additions) + + return result + + +def _get_python_version(version: str) -> PythonVersion: + if len(version) > 1: + return int(version[0]), int(version[1:]) + else: + return (int(version[0]),) + + +def _get_custom_interpreter( + implementation: Optional[str] = None, version: Optional[str] = None +) -> str: + if implementation is None: + implementation = interpreter_name() + if version is None: + version = interpreter_version() + return f"{implementation}{version}" + + +def get_supported( + version: Optional[str] = None, + platforms: Optional[List[str]] = None, + impl: Optional[str] = None, + abis: Optional[List[str]] = None, +) -> List[Tag]: + """Return a list of supported tags for each version specified in + `versions`. + + :param version: a string version, of the form "33" or "32", + or None. The version will be assumed to support our ABI. + :param platform: specify a list of platforms you want valid + tags for, or None. If None, use the local system platform. + :param impl: specify the exact implementation you want valid + tags for, or None. If None, use the local interpreter impl. + :param abis: specify a list of abis you want valid + tags for, or None. If None, use the local interpreter abi. + """ + supported: List[Tag] = [] + + python_version: Optional[PythonVersion] = None + if version is not None: + python_version = _get_python_version(version) + + interpreter = _get_custom_interpreter(impl, version) + + platforms = _expand_allowed_platforms(platforms) + + is_cpython = (impl or interpreter_name()) == "cp" + if is_cpython: + supported.extend( + cpython_tags( + python_version=python_version, + abis=abis, + platforms=platforms, + ) + ) + else: + supported.extend( + generic_tags( + interpreter=interpreter, + abis=abis, + platforms=platforms, + ) + ) + supported.extend( + compatible_tags( + python_version=python_version, + interpreter=interpreter, + platforms=platforms, + ) + ) + + return supported diff --git a/venv/Lib/site-packages/pip/_internal/utils/datetime.py b/venv/Lib/site-packages/pip/_internal/utils/datetime.py new file mode 100644 index 0000000..8668b3b --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/utils/datetime.py @@ -0,0 +1,11 @@ +"""For when pip wants to check the date or time. +""" + +import datetime + + +def today_is_later_than(year: int, month: int, day: int) -> bool: + today = datetime.date.today() + given = datetime.date(year, month, day) + + return today > given diff --git a/venv/Lib/site-packages/pip/_internal/utils/deprecation.py b/venv/Lib/site-packages/pip/_internal/utils/deprecation.py new file mode 100644 index 0000000..72bd6f2 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/utils/deprecation.py @@ -0,0 +1,120 @@ +""" +A module that implements tooling to enable easy warnings about deprecations. +""" + +import logging +import warnings +from typing import Any, Optional, TextIO, Type, Union + +from pip._vendor.packaging.version import parse + +from pip import __version__ as current_version # NOTE: tests patch this name. + +DEPRECATION_MSG_PREFIX = "DEPRECATION: " + + +class PipDeprecationWarning(Warning): + pass + + +_original_showwarning: Any = None + + +# Warnings <-> Logging Integration +def _showwarning( + message: Union[Warning, str], + category: Type[Warning], + filename: str, + lineno: int, + file: Optional[TextIO] = None, + line: Optional[str] = None, +) -> None: + if file is not None: + if _original_showwarning is not None: + _original_showwarning(message, category, filename, lineno, file, line) + elif issubclass(category, PipDeprecationWarning): + # We use a specially named logger which will handle all of the + # deprecation messages for pip. + logger = logging.getLogger("pip._internal.deprecations") + logger.warning(message) + else: + _original_showwarning(message, category, filename, lineno, file, line) + + +def install_warning_logger() -> None: + # Enable our Deprecation Warnings + warnings.simplefilter("default", PipDeprecationWarning, append=True) + + global _original_showwarning + + if _original_showwarning is None: + _original_showwarning = warnings.showwarning + warnings.showwarning = _showwarning + + +def deprecated( + *, + reason: str, + replacement: Optional[str], + gone_in: Optional[str], + feature_flag: Optional[str] = None, + issue: Optional[int] = None, +) -> None: + """Helper to deprecate existing functionality. + + reason: + Textual reason shown to the user about why this functionality has + been deprecated. Should be a complete sentence. + replacement: + Textual suggestion shown to the user about what alternative + functionality they can use. + gone_in: + The version of pip does this functionality should get removed in. + Raises an error if pip's current version is greater than or equal to + this. + feature_flag: + Command-line flag of the form --use-feature={feature_flag} for testing + upcoming functionality. + issue: + Issue number on the tracker that would serve as a useful place for + users to find related discussion and provide feedback. + """ + + # Determine whether or not the feature is already gone in this version. + is_gone = gone_in is not None and parse(current_version) >= parse(gone_in) + + message_parts = [ + (reason, f"{DEPRECATION_MSG_PREFIX}{{}}"), + ( + gone_in, + "pip {} will enforce this behaviour change." + if not is_gone + else "Since pip {}, this is no longer supported.", + ), + ( + replacement, + "A possible replacement is {}.", + ), + ( + feature_flag, + "You can use the flag --use-feature={} to test the upcoming behaviour." + if not is_gone + else None, + ), + ( + issue, + "Discussion can be found at https://github.com/pypa/pip/issues/{}", + ), + ] + + message = " ".join( + format_str.format(value) + for value, format_str in message_parts + if format_str is not None and value is not None + ) + + # Raise as an error if this behaviour is deprecated. + if is_gone: + raise PipDeprecationWarning(message) + + warnings.warn(message, category=PipDeprecationWarning, stacklevel=2) diff --git a/venv/Lib/site-packages/pip/_internal/utils/direct_url_helpers.py b/venv/Lib/site-packages/pip/_internal/utils/direct_url_helpers.py new file mode 100644 index 0000000..0e8e5e1 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/utils/direct_url_helpers.py @@ -0,0 +1,87 @@ +from typing import Optional + +from pip._internal.models.direct_url import ArchiveInfo, DirectUrl, DirInfo, VcsInfo +from pip._internal.models.link import Link +from pip._internal.utils.urls import path_to_url +from pip._internal.vcs import vcs + + +def direct_url_as_pep440_direct_reference(direct_url: DirectUrl, name: str) -> str: + """Convert a DirectUrl to a pip requirement string.""" + direct_url.validate() # if invalid, this is a pip bug + requirement = name + " @ " + fragments = [] + if isinstance(direct_url.info, VcsInfo): + requirement += "{}+{}@{}".format( + direct_url.info.vcs, direct_url.url, direct_url.info.commit_id + ) + elif isinstance(direct_url.info, ArchiveInfo): + requirement += direct_url.url + if direct_url.info.hash: + fragments.append(direct_url.info.hash) + else: + assert isinstance(direct_url.info, DirInfo) + requirement += direct_url.url + if direct_url.subdirectory: + fragments.append("subdirectory=" + direct_url.subdirectory) + if fragments: + requirement += "#" + "&".join(fragments) + return requirement + + +def direct_url_for_editable(source_dir: str) -> DirectUrl: + return DirectUrl( + url=path_to_url(source_dir), + info=DirInfo(editable=True), + ) + + +def direct_url_from_link( + link: Link, source_dir: Optional[str] = None, link_is_in_wheel_cache: bool = False +) -> DirectUrl: + if link.is_vcs: + vcs_backend = vcs.get_backend_for_scheme(link.scheme) + assert vcs_backend + url, requested_revision, _ = vcs_backend.get_url_rev_and_auth( + link.url_without_fragment + ) + # For VCS links, we need to find out and add commit_id. + if link_is_in_wheel_cache: + # If the requested VCS link corresponds to a cached + # wheel, it means the requested revision was an + # immutable commit hash, otherwise it would not have + # been cached. In that case we don't have a source_dir + # with the VCS checkout. + assert requested_revision + commit_id = requested_revision + else: + # If the wheel was not in cache, it means we have + # had to checkout from VCS to build and we have a source_dir + # which we can inspect to find out the commit id. + assert source_dir + commit_id = vcs_backend.get_revision(source_dir) + return DirectUrl( + url=url, + info=VcsInfo( + vcs=vcs_backend.name, + commit_id=commit_id, + requested_revision=requested_revision, + ), + subdirectory=link.subdirectory_fragment, + ) + elif link.is_existing_dir(): + return DirectUrl( + url=link.url_without_fragment, + info=DirInfo(), + subdirectory=link.subdirectory_fragment, + ) + else: + hash = None + hash_name = link.hash_name + if hash_name: + hash = f"{hash_name}={link.hash}" + return DirectUrl( + url=link.url_without_fragment, + info=ArchiveInfo(hash=hash), + subdirectory=link.subdirectory_fragment, + ) diff --git a/venv/Lib/site-packages/pip/_internal/utils/distutils_args.py b/venv/Lib/site-packages/pip/_internal/utils/distutils_args.py new file mode 100644 index 0000000..e4aa5b8 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/utils/distutils_args.py @@ -0,0 +1,42 @@ +from distutils.errors import DistutilsArgError +from distutils.fancy_getopt import FancyGetopt +from typing import Dict, List + +_options = [ + ("exec-prefix=", None, ""), + ("home=", None, ""), + ("install-base=", None, ""), + ("install-data=", None, ""), + ("install-headers=", None, ""), + ("install-lib=", None, ""), + ("install-platlib=", None, ""), + ("install-purelib=", None, ""), + ("install-scripts=", None, ""), + ("prefix=", None, ""), + ("root=", None, ""), + ("user", None, ""), +] + + +# typeshed doesn't permit Tuple[str, None, str], see python/typeshed#3469. +_distutils_getopt = FancyGetopt(_options) # type: ignore + + +def parse_distutils_args(args: List[str]) -> Dict[str, str]: + """Parse provided arguments, returning an object that has the + matched arguments. + + Any unknown arguments are ignored. + """ + result = {} + for arg in args: + try: + _, match = _distutils_getopt.getopt(args=[arg]) + except DistutilsArgError: + # We don't care about any other options, which here may be + # considered unrecognized since our option list is not + # exhaustive. + pass + else: + result.update(match.__dict__) + return result diff --git a/venv/Lib/site-packages/pip/_internal/utils/egg_link.py b/venv/Lib/site-packages/pip/_internal/utils/egg_link.py new file mode 100644 index 0000000..9e0da8d --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/utils/egg_link.py @@ -0,0 +1,75 @@ +# The following comment should be removed at some point in the future. +# mypy: strict-optional=False + +import os +import re +import sys +from typing import Optional + +from pip._internal.locations import site_packages, user_site +from pip._internal.utils.virtualenv import ( + running_under_virtualenv, + virtualenv_no_global, +) + +__all__ = [ + "egg_link_path_from_sys_path", + "egg_link_path_from_location", +] + + +def _egg_link_name(raw_name: str) -> str: + """ + Convert a Name metadata value to a .egg-link name, by applying + the same substitution as pkg_resources's safe_name function. + Note: we cannot use canonicalize_name because it has a different logic. + """ + return re.sub("[^A-Za-z0-9.]+", "-", raw_name) + ".egg-link" + + +def egg_link_path_from_sys_path(raw_name: str) -> Optional[str]: + """ + Look for a .egg-link file for project name, by walking sys.path. + """ + egg_link_name = _egg_link_name(raw_name) + for path_item in sys.path: + egg_link = os.path.join(path_item, egg_link_name) + if os.path.isfile(egg_link): + return egg_link + return None + + +def egg_link_path_from_location(raw_name: str) -> Optional[str]: + """ + Return the path for the .egg-link file if it exists, otherwise, None. + + There's 3 scenarios: + 1) not in a virtualenv + try to find in site.USER_SITE, then site_packages + 2) in a no-global virtualenv + try to find in site_packages + 3) in a yes-global virtualenv + try to find in site_packages, then site.USER_SITE + (don't look in global location) + + For #1 and #3, there could be odd cases, where there's an egg-link in 2 + locations. + + This method will just return the first one found. + """ + sites = [] + if running_under_virtualenv(): + sites.append(site_packages) + if not virtualenv_no_global() and user_site: + sites.append(user_site) + else: + if user_site: + sites.append(user_site) + sites.append(site_packages) + + egg_link_name = _egg_link_name(raw_name) + for site in sites: + egglink = os.path.join(site, egg_link_name) + if os.path.isfile(egglink): + return egglink + return None diff --git a/venv/Lib/site-packages/pip/_internal/utils/encoding.py b/venv/Lib/site-packages/pip/_internal/utils/encoding.py new file mode 100644 index 0000000..1c73f6c --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/utils/encoding.py @@ -0,0 +1,36 @@ +import codecs +import locale +import re +import sys +from typing import List, Tuple + +BOMS: List[Tuple[bytes, str]] = [ + (codecs.BOM_UTF8, "utf-8"), + (codecs.BOM_UTF16, "utf-16"), + (codecs.BOM_UTF16_BE, "utf-16-be"), + (codecs.BOM_UTF16_LE, "utf-16-le"), + (codecs.BOM_UTF32, "utf-32"), + (codecs.BOM_UTF32_BE, "utf-32-be"), + (codecs.BOM_UTF32_LE, "utf-32-le"), +] + +ENCODING_RE = re.compile(br"coding[:=]\s*([-\w.]+)") + + +def auto_decode(data: bytes) -> str: + """Check a bytes string for a BOM to correctly detect the encoding + + Fallback to locale.getpreferredencoding(False) like open() on Python3""" + for bom, encoding in BOMS: + if data.startswith(bom): + return data[len(bom) :].decode(encoding) + # Lets check the first two lines as in PEP263 + for line in data.split(b"\n")[:2]: + if line[0:1] == b"#" and ENCODING_RE.search(line): + result = ENCODING_RE.search(line) + assert result is not None + encoding = result.groups()[0].decode("ascii") + return data.decode(encoding) + return data.decode( + locale.getpreferredencoding(False) or sys.getdefaultencoding(), + ) diff --git a/venv/Lib/site-packages/pip/_internal/utils/entrypoints.py b/venv/Lib/site-packages/pip/_internal/utils/entrypoints.py new file mode 100644 index 0000000..1504a12 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/utils/entrypoints.py @@ -0,0 +1,27 @@ +import sys +from typing import List, Optional + +from pip._internal.cli.main import main + + +def _wrapper(args: Optional[List[str]] = None) -> int: + """Central wrapper for all old entrypoints. + + Historically pip has had several entrypoints defined. Because of issues + arising from PATH, sys.path, multiple Pythons, their interactions, and most + of them having a pip installed, users suffer every time an entrypoint gets + moved. + + To alleviate this pain, and provide a mechanism for warning users and + directing them to an appropriate place for help, we now define all of + our old entrypoints as wrappers for the current one. + """ + sys.stderr.write( + "WARNING: pip is being invoked by an old script wrapper. This will " + "fail in a future version of pip.\n" + "Please see https://github.com/pypa/pip/issues/5599 for advice on " + "fixing the underlying issue.\n" + "To avoid this problem you can invoke Python with '-m pip' instead of " + "running pip directly.\n" + ) + return main(args) diff --git a/venv/Lib/site-packages/pip/_internal/utils/filesystem.py b/venv/Lib/site-packages/pip/_internal/utils/filesystem.py new file mode 100644 index 0000000..b7e6191 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/utils/filesystem.py @@ -0,0 +1,182 @@ +import fnmatch +import os +import os.path +import random +import shutil +import stat +import sys +from contextlib import contextmanager +from tempfile import NamedTemporaryFile +from typing import Any, BinaryIO, Iterator, List, Union, cast + +from pip._vendor.tenacity import retry, stop_after_delay, wait_fixed + +from pip._internal.utils.compat import get_path_uid +from pip._internal.utils.misc import format_size + + +def check_path_owner(path: str) -> bool: + # If we don't have a way to check the effective uid of this process, then + # we'll just assume that we own the directory. + if sys.platform == "win32" or not hasattr(os, "geteuid"): + return True + + assert os.path.isabs(path) + + previous = None + while path != previous: + if os.path.lexists(path): + # Check if path is writable by current user. + if os.geteuid() == 0: + # Special handling for root user in order to handle properly + # cases where users use sudo without -H flag. + try: + path_uid = get_path_uid(path) + except OSError: + return False + return path_uid == 0 + else: + return os.access(path, os.W_OK) + else: + previous, path = path, os.path.dirname(path) + return False # assume we don't own the path + + +def copy2_fixed(src: str, dest: str) -> None: + """Wrap shutil.copy2() but map errors copying socket files to + SpecialFileError as expected. + + See also https://bugs.python.org/issue37700. + """ + try: + shutil.copy2(src, dest) + except OSError: + for f in [src, dest]: + try: + is_socket_file = is_socket(f) + except OSError: + # An error has already occurred. Another error here is not + # a problem and we can ignore it. + pass + else: + if is_socket_file: + raise shutil.SpecialFileError(f"`{f}` is a socket") + + raise + + +def is_socket(path: str) -> bool: + return stat.S_ISSOCK(os.lstat(path).st_mode) + + +@contextmanager +def adjacent_tmp_file(path: str, **kwargs: Any) -> Iterator[BinaryIO]: + """Return a file-like object pointing to a tmp file next to path. + + The file is created securely and is ensured to be written to disk + after the context reaches its end. + + kwargs will be passed to tempfile.NamedTemporaryFile to control + the way the temporary file will be opened. + """ + with NamedTemporaryFile( + delete=False, + dir=os.path.dirname(path), + prefix=os.path.basename(path), + suffix=".tmp", + **kwargs, + ) as f: + result = cast(BinaryIO, f) + try: + yield result + finally: + result.flush() + os.fsync(result.fileno()) + + +# Tenacity raises RetryError by default, explicitly raise the original exception +_replace_retry = retry(reraise=True, stop=stop_after_delay(1), wait=wait_fixed(0.25)) + +replace = _replace_retry(os.replace) + + +# test_writable_dir and _test_writable_dir_win are copied from Flit, +# with the author's agreement to also place them under pip's license. +def test_writable_dir(path: str) -> bool: + """Check if a directory is writable. + + Uses os.access() on POSIX, tries creating files on Windows. + """ + # If the directory doesn't exist, find the closest parent that does. + while not os.path.isdir(path): + parent = os.path.dirname(path) + if parent == path: + break # Should never get here, but infinite loops are bad + path = parent + + if os.name == "posix": + return os.access(path, os.W_OK) + + return _test_writable_dir_win(path) + + +def _test_writable_dir_win(path: str) -> bool: + # os.access doesn't work on Windows: http://bugs.python.org/issue2528 + # and we can't use tempfile: http://bugs.python.org/issue22107 + basename = "accesstest_deleteme_fishfingers_custard_" + alphabet = "abcdefghijklmnopqrstuvwxyz0123456789" + for _ in range(10): + name = basename + "".join(random.choice(alphabet) for _ in range(6)) + file = os.path.join(path, name) + try: + fd = os.open(file, os.O_RDWR | os.O_CREAT | os.O_EXCL) + except FileExistsError: + pass + except PermissionError: + # This could be because there's a directory with the same name. + # But it's highly unlikely there's a directory called that, + # so we'll assume it's because the parent dir is not writable. + # This could as well be because the parent dir is not readable, + # due to non-privileged user access. + return False + else: + os.close(fd) + os.unlink(file) + return True + + # This should never be reached + raise OSError("Unexpected condition testing for writable directory") + + +def find_files(path: str, pattern: str) -> List[str]: + """Returns a list of absolute paths of files beneath path, recursively, + with filenames which match the UNIX-style shell glob pattern.""" + result: List[str] = [] + for root, _, files in os.walk(path): + matches = fnmatch.filter(files, pattern) + result.extend(os.path.join(root, f) for f in matches) + return result + + +def file_size(path: str) -> Union[int, float]: + # If it's a symlink, return 0. + if os.path.islink(path): + return 0 + return os.path.getsize(path) + + +def format_file_size(path: str) -> str: + return format_size(file_size(path)) + + +def directory_size(path: str) -> Union[int, float]: + size = 0.0 + for root, _dirs, files in os.walk(path): + for filename in files: + file_path = os.path.join(root, filename) + size += file_size(file_path) + return size + + +def format_directory_size(path: str) -> str: + return format_size(directory_size(path)) diff --git a/venv/Lib/site-packages/pip/_internal/utils/filetypes.py b/venv/Lib/site-packages/pip/_internal/utils/filetypes.py new file mode 100644 index 0000000..5948570 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/utils/filetypes.py @@ -0,0 +1,27 @@ +"""Filetype information. +""" + +from typing import Tuple + +from pip._internal.utils.misc import splitext + +WHEEL_EXTENSION = ".whl" +BZ2_EXTENSIONS: Tuple[str, ...] = (".tar.bz2", ".tbz") +XZ_EXTENSIONS: Tuple[str, ...] = ( + ".tar.xz", + ".txz", + ".tlz", + ".tar.lz", + ".tar.lzma", +) +ZIP_EXTENSIONS: Tuple[str, ...] = (".zip", WHEEL_EXTENSION) +TAR_EXTENSIONS: Tuple[str, ...] = (".tar.gz", ".tgz", ".tar") +ARCHIVE_EXTENSIONS = ZIP_EXTENSIONS + BZ2_EXTENSIONS + TAR_EXTENSIONS + XZ_EXTENSIONS + + +def is_archive_file(name: str) -> bool: + """Return True if `name` is a considered as an archive file.""" + ext = splitext(name)[1].lower() + if ext in ARCHIVE_EXTENSIONS: + return True + return False diff --git a/venv/Lib/site-packages/pip/_internal/utils/glibc.py b/venv/Lib/site-packages/pip/_internal/utils/glibc.py new file mode 100644 index 0000000..7bd3c20 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/utils/glibc.py @@ -0,0 +1,88 @@ +# The following comment should be removed at some point in the future. +# mypy: strict-optional=False + +import os +import sys +from typing import Optional, Tuple + + +def glibc_version_string() -> Optional[str]: + "Returns glibc version string, or None if not using glibc." + return glibc_version_string_confstr() or glibc_version_string_ctypes() + + +def glibc_version_string_confstr() -> Optional[str]: + "Primary implementation of glibc_version_string using os.confstr." + # os.confstr is quite a bit faster than ctypes.DLL. It's also less likely + # to be broken or missing. This strategy is used in the standard library + # platform module: + # https://github.com/python/cpython/blob/fcf1d003bf4f0100c9d0921ff3d70e1127ca1b71/Lib/platform.py#L175-L183 + if sys.platform == "win32": + return None + try: + # os.confstr("CS_GNU_LIBC_VERSION") returns a string like "glibc 2.17": + _, version = os.confstr("CS_GNU_LIBC_VERSION").split() + except (AttributeError, OSError, ValueError): + # os.confstr() or CS_GNU_LIBC_VERSION not available (or a bad value)... + return None + return version + + +def glibc_version_string_ctypes() -> Optional[str]: + "Fallback implementation of glibc_version_string using ctypes." + + try: + import ctypes + except ImportError: + return None + + # ctypes.CDLL(None) internally calls dlopen(NULL), and as the dlopen + # manpage says, "If filename is NULL, then the returned handle is for the + # main program". This way we can let the linker do the work to figure out + # which libc our process is actually using. + process_namespace = ctypes.CDLL(None) + try: + gnu_get_libc_version = process_namespace.gnu_get_libc_version + except AttributeError: + # Symbol doesn't exist -> therefore, we are not linked to + # glibc. + return None + + # Call gnu_get_libc_version, which returns a string like "2.5" + gnu_get_libc_version.restype = ctypes.c_char_p + version_str = gnu_get_libc_version() + # py2 / py3 compatibility: + if not isinstance(version_str, str): + version_str = version_str.decode("ascii") + + return version_str + + +# platform.libc_ver regularly returns completely nonsensical glibc +# versions. E.g. on my computer, platform says: +# +# ~$ python2.7 -c 'import platform; print(platform.libc_ver())' +# ('glibc', '2.7') +# ~$ python3.5 -c 'import platform; print(platform.libc_ver())' +# ('glibc', '2.9') +# +# But the truth is: +# +# ~$ ldd --version +# ldd (Debian GLIBC 2.22-11) 2.22 +# +# This is unfortunate, because it means that the linehaul data on libc +# versions that was generated by pip 8.1.2 and earlier is useless and +# misleading. Solution: instead of using platform, use our code that actually +# works. +def libc_ver() -> Tuple[str, str]: + """Try to determine the glibc version + + Returns a tuple of strings (lib, version) which default to empty strings + in case the lookup fails. + """ + glibc_version = glibc_version_string() + if glibc_version is None: + return ("", "") + else: + return ("glibc", glibc_version) diff --git a/venv/Lib/site-packages/pip/_internal/utils/hashes.py b/venv/Lib/site-packages/pip/_internal/utils/hashes.py new file mode 100644 index 0000000..82eb035 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/utils/hashes.py @@ -0,0 +1,144 @@ +import hashlib +from typing import TYPE_CHECKING, BinaryIO, Dict, Iterator, List + +from pip._internal.exceptions import HashMismatch, HashMissing, InstallationError +from pip._internal.utils.misc import read_chunks + +if TYPE_CHECKING: + from hashlib import _Hash + + # NoReturn introduced in 3.6.2; imported only for type checking to maintain + # pip compatibility with older patch versions of Python 3.6 + from typing import NoReturn + + +# The recommended hash algo of the moment. Change this whenever the state of +# the art changes; it won't hurt backward compatibility. +FAVORITE_HASH = "sha256" + + +# Names of hashlib algorithms allowed by the --hash option and ``pip hash`` +# Currently, those are the ones at least as collision-resistant as sha256. +STRONG_HASHES = ["sha256", "sha384", "sha512"] + + +class Hashes: + """A wrapper that builds multiple hashes at once and checks them against + known-good values + + """ + + def __init__(self, hashes: Dict[str, List[str]] = None) -> None: + """ + :param hashes: A dict of algorithm names pointing to lists of allowed + hex digests + """ + allowed = {} + if hashes is not None: + for alg, keys in hashes.items(): + # Make sure values are always sorted (to ease equality checks) + allowed[alg] = sorted(keys) + self._allowed = allowed + + def __and__(self, other: "Hashes") -> "Hashes": + if not isinstance(other, Hashes): + return NotImplemented + + # If either of the Hashes object is entirely empty (i.e. no hash + # specified at all), all hashes from the other object are allowed. + if not other: + return self + if not self: + return other + + # Otherwise only hashes that present in both objects are allowed. + new = {} + for alg, values in other._allowed.items(): + if alg not in self._allowed: + continue + new[alg] = [v for v in values if v in self._allowed[alg]] + return Hashes(new) + + @property + def digest_count(self) -> int: + return sum(len(digests) for digests in self._allowed.values()) + + def is_hash_allowed(self, hash_name: str, hex_digest: str) -> bool: + """Return whether the given hex digest is allowed.""" + return hex_digest in self._allowed.get(hash_name, []) + + def check_against_chunks(self, chunks: Iterator[bytes]) -> None: + """Check good hashes against ones built from iterable of chunks of + data. + + Raise HashMismatch if none match. + + """ + gots = {} + for hash_name in self._allowed.keys(): + try: + gots[hash_name] = hashlib.new(hash_name) + except (ValueError, TypeError): + raise InstallationError(f"Unknown hash name: {hash_name}") + + for chunk in chunks: + for hash in gots.values(): + hash.update(chunk) + + for hash_name, got in gots.items(): + if got.hexdigest() in self._allowed[hash_name]: + return + self._raise(gots) + + def _raise(self, gots: Dict[str, "_Hash"]) -> "NoReturn": + raise HashMismatch(self._allowed, gots) + + def check_against_file(self, file: BinaryIO) -> None: + """Check good hashes against a file-like object + + Raise HashMismatch if none match. + + """ + return self.check_against_chunks(read_chunks(file)) + + def check_against_path(self, path: str) -> None: + with open(path, "rb") as file: + return self.check_against_file(file) + + def __bool__(self) -> bool: + """Return whether I know any known-good hashes.""" + return bool(self._allowed) + + def __eq__(self, other: object) -> bool: + if not isinstance(other, Hashes): + return NotImplemented + return self._allowed == other._allowed + + def __hash__(self) -> int: + return hash( + ",".join( + sorted( + ":".join((alg, digest)) + for alg, digest_list in self._allowed.items() + for digest in digest_list + ) + ) + ) + + +class MissingHashes(Hashes): + """A workalike for Hashes used when we're missing a hash for a requirement + + It computes the actual hash of the requirement and raises a HashMissing + exception showing it to the user. + + """ + + def __init__(self) -> None: + """Don't offer the ``hashes`` kwarg.""" + # Pass our favorite hash in to generate a "gotten hash". With the + # empty list, it will never match, so an error will always raise. + super().__init__(hashes={FAVORITE_HASH: []}) + + def _raise(self, gots: Dict[str, "_Hash"]) -> "NoReturn": + raise HashMissing(gots[FAVORITE_HASH].hexdigest()) diff --git a/venv/Lib/site-packages/pip/_internal/utils/inject_securetransport.py b/venv/Lib/site-packages/pip/_internal/utils/inject_securetransport.py new file mode 100644 index 0000000..276aa79 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/utils/inject_securetransport.py @@ -0,0 +1,35 @@ +"""A helper module that injects SecureTransport, on import. + +The import should be done as early as possible, to ensure all requests and +sessions (or whatever) are created after injecting SecureTransport. + +Note that we only do the injection on macOS, when the linked OpenSSL is too +old to handle TLSv1.2. +""" + +import sys + + +def inject_securetransport() -> None: + # Only relevant on macOS + if sys.platform != "darwin": + return + + try: + import ssl + except ImportError: + return + + # Checks for OpenSSL 1.0.1 + if ssl.OPENSSL_VERSION_NUMBER >= 0x1000100F: + return + + try: + from pip._vendor.urllib3.contrib import securetransport + except (ImportError, OSError): + return + + securetransport.inject_into_urllib3() + + +inject_securetransport() diff --git a/venv/Lib/site-packages/pip/_internal/utils/logging.py b/venv/Lib/site-packages/pip/_internal/utils/logging.py new file mode 100644 index 0000000..6e001c5 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/utils/logging.py @@ -0,0 +1,343 @@ +import contextlib +import errno +import logging +import logging.handlers +import os +import sys +import threading +from dataclasses import dataclass +from logging import Filter +from typing import IO, Any, ClassVar, Iterator, List, Optional, TextIO, Type + +from pip._vendor.rich.console import ( + Console, + ConsoleOptions, + ConsoleRenderable, + RenderResult, +) +from pip._vendor.rich.highlighter import NullHighlighter +from pip._vendor.rich.logging import RichHandler +from pip._vendor.rich.segment import Segment +from pip._vendor.rich.style import Style + +from pip._internal.exceptions import DiagnosticPipError +from pip._internal.utils._log import VERBOSE, getLogger +from pip._internal.utils.compat import WINDOWS +from pip._internal.utils.deprecation import DEPRECATION_MSG_PREFIX +from pip._internal.utils.misc import ensure_dir + +_log_state = threading.local() +subprocess_logger = getLogger("pip.subprocessor") + + +class BrokenStdoutLoggingError(Exception): + """ + Raised if BrokenPipeError occurs for the stdout stream while logging. + """ + + +def _is_broken_pipe_error(exc_class: Type[BaseException], exc: BaseException) -> bool: + if exc_class is BrokenPipeError: + return True + + # On Windows, a broken pipe can show up as EINVAL rather than EPIPE: + # https://bugs.python.org/issue19612 + # https://bugs.python.org/issue30418 + if not WINDOWS: + return False + + return isinstance(exc, OSError) and exc.errno in (errno.EINVAL, errno.EPIPE) + + +@contextlib.contextmanager +def indent_log(num: int = 2) -> Iterator[None]: + """ + A context manager which will cause the log output to be indented for any + log messages emitted inside it. + """ + # For thread-safety + _log_state.indentation = get_indentation() + _log_state.indentation += num + try: + yield + finally: + _log_state.indentation -= num + + +def get_indentation() -> int: + return getattr(_log_state, "indentation", 0) + + +class IndentingFormatter(logging.Formatter): + default_time_format = "%Y-%m-%dT%H:%M:%S" + + def __init__( + self, + *args: Any, + add_timestamp: bool = False, + **kwargs: Any, + ) -> None: + """ + A logging.Formatter that obeys the indent_log() context manager. + + :param add_timestamp: A bool indicating output lines should be prefixed + with their record's timestamp. + """ + self.add_timestamp = add_timestamp + super().__init__(*args, **kwargs) + + def get_message_start(self, formatted: str, levelno: int) -> str: + """ + Return the start of the formatted log message (not counting the + prefix to add to each line). + """ + if levelno < logging.WARNING: + return "" + if formatted.startswith(DEPRECATION_MSG_PREFIX): + # Then the message already has a prefix. We don't want it to + # look like "WARNING: DEPRECATION: ...." + return "" + if levelno < logging.ERROR: + return "WARNING: " + + return "ERROR: " + + def format(self, record: logging.LogRecord) -> str: + """ + Calls the standard formatter, but will indent all of the log message + lines by our current indentation level. + """ + formatted = super().format(record) + message_start = self.get_message_start(formatted, record.levelno) + formatted = message_start + formatted + + prefix = "" + if self.add_timestamp: + prefix = f"{self.formatTime(record)} " + prefix += " " * get_indentation() + formatted = "".join([prefix + line for line in formatted.splitlines(True)]) + return formatted + + +@dataclass +class IndentedRenderable: + renderable: ConsoleRenderable + indent: int + + def __rich_console__( + self, console: Console, options: ConsoleOptions + ) -> RenderResult: + segments = console.render(self.renderable, options) + lines = Segment.split_lines(segments) + for line in lines: + yield Segment(" " * self.indent) + yield from line + yield Segment("\n") + + +class RichPipStreamHandler(RichHandler): + KEYWORDS: ClassVar[Optional[List[str]]] = [] + + def __init__(self, stream: Optional[TextIO], no_color: bool) -> None: + super().__init__( + console=Console(file=stream, no_color=no_color, soft_wrap=True), + show_time=False, + show_level=False, + show_path=False, + highlighter=NullHighlighter(), + ) + + # Our custom override on Rich's logger, to make things work as we need them to. + def emit(self, record: logging.LogRecord) -> None: + style: Optional[Style] = None + + # If we are given a diagnostic error to present, present it with indentation. + if record.msg == "[present-diagnostic] %s" and len(record.args) == 1: + diagnostic_error: DiagnosticPipError = record.args[0] # type: ignore[index] + assert isinstance(diagnostic_error, DiagnosticPipError) + + renderable: ConsoleRenderable = IndentedRenderable( + diagnostic_error, indent=get_indentation() + ) + else: + message = self.format(record) + renderable = self.render_message(record, message) + if record.levelno is not None: + if record.levelno >= logging.ERROR: + style = Style(color="red") + elif record.levelno >= logging.WARNING: + style = Style(color="yellow") + + try: + self.console.print(renderable, overflow="ignore", crop=False, style=style) + except Exception: + self.handleError(record) + + def handleError(self, record: logging.LogRecord) -> None: + """Called when logging is unable to log some output.""" + + exc_class, exc = sys.exc_info()[:2] + # If a broken pipe occurred while calling write() or flush() on the + # stdout stream in logging's Handler.emit(), then raise our special + # exception so we can handle it in main() instead of logging the + # broken pipe error and continuing. + if ( + exc_class + and exc + and self.console.file is sys.stdout + and _is_broken_pipe_error(exc_class, exc) + ): + raise BrokenStdoutLoggingError() + + return super().handleError(record) + + +class BetterRotatingFileHandler(logging.handlers.RotatingFileHandler): + def _open(self) -> IO[Any]: + ensure_dir(os.path.dirname(self.baseFilename)) + return super()._open() + + +class MaxLevelFilter(Filter): + def __init__(self, level: int) -> None: + self.level = level + + def filter(self, record: logging.LogRecord) -> bool: + return record.levelno < self.level + + +class ExcludeLoggerFilter(Filter): + + """ + A logging Filter that excludes records from a logger (or its children). + """ + + def filter(self, record: logging.LogRecord) -> bool: + # The base Filter class allows only records from a logger (or its + # children). + return not super().filter(record) + + +def setup_logging(verbosity: int, no_color: bool, user_log_file: Optional[str]) -> int: + """Configures and sets up all of the logging + + Returns the requested logging level, as its integer value. + """ + + # Determine the level to be logging at. + if verbosity >= 2: + level_number = logging.DEBUG + elif verbosity == 1: + level_number = VERBOSE + elif verbosity == -1: + level_number = logging.WARNING + elif verbosity == -2: + level_number = logging.ERROR + elif verbosity <= -3: + level_number = logging.CRITICAL + else: + level_number = logging.INFO + + level = logging.getLevelName(level_number) + + # The "root" logger should match the "console" level *unless* we also need + # to log to a user log file. + include_user_log = user_log_file is not None + if include_user_log: + additional_log_file = user_log_file + root_level = "DEBUG" + else: + additional_log_file = "/dev/null" + root_level = level + + # Disable any logging besides WARNING unless we have DEBUG level logging + # enabled for vendored libraries. + vendored_log_level = "WARNING" if level in ["INFO", "ERROR"] else "DEBUG" + + # Shorthands for clarity + log_streams = { + "stdout": "ext://sys.stdout", + "stderr": "ext://sys.stderr", + } + handler_classes = { + "stream": "pip._internal.utils.logging.RichPipStreamHandler", + "file": "pip._internal.utils.logging.BetterRotatingFileHandler", + } + handlers = ["console", "console_errors", "console_subprocess"] + ( + ["user_log"] if include_user_log else [] + ) + + logging.config.dictConfig( + { + "version": 1, + "disable_existing_loggers": False, + "filters": { + "exclude_warnings": { + "()": "pip._internal.utils.logging.MaxLevelFilter", + "level": logging.WARNING, + }, + "restrict_to_subprocess": { + "()": "logging.Filter", + "name": subprocess_logger.name, + }, + "exclude_subprocess": { + "()": "pip._internal.utils.logging.ExcludeLoggerFilter", + "name": subprocess_logger.name, + }, + }, + "formatters": { + "indent": { + "()": IndentingFormatter, + "format": "%(message)s", + }, + "indent_with_timestamp": { + "()": IndentingFormatter, + "format": "%(message)s", + "add_timestamp": True, + }, + }, + "handlers": { + "console": { + "level": level, + "class": handler_classes["stream"], + "no_color": no_color, + "stream": log_streams["stdout"], + "filters": ["exclude_subprocess", "exclude_warnings"], + "formatter": "indent", + }, + "console_errors": { + "level": "WARNING", + "class": handler_classes["stream"], + "no_color": no_color, + "stream": log_streams["stderr"], + "filters": ["exclude_subprocess"], + "formatter": "indent", + }, + # A handler responsible for logging to the console messages + # from the "subprocessor" logger. + "console_subprocess": { + "level": level, + "class": handler_classes["stream"], + "stream": log_streams["stderr"], + "no_color": no_color, + "filters": ["restrict_to_subprocess"], + "formatter": "indent", + }, + "user_log": { + "level": "DEBUG", + "class": handler_classes["file"], + "filename": additional_log_file, + "encoding": "utf-8", + "delay": True, + "formatter": "indent_with_timestamp", + }, + }, + "root": { + "level": root_level, + "handlers": handlers, + }, + "loggers": {"pip._vendor": {"level": vendored_log_level}}, + } + ) + + return level_number diff --git a/venv/Lib/site-packages/pip/_internal/utils/misc.py b/venv/Lib/site-packages/pip/_internal/utils/misc.py new file mode 100644 index 0000000..b07e56f --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/utils/misc.py @@ -0,0 +1,629 @@ +# The following comment should be removed at some point in the future. +# mypy: strict-optional=False + +import contextlib +import errno +import getpass +import hashlib +import io +import logging +import os +import posixpath +import shutil +import stat +import sys +import urllib.parse +from io import StringIO +from itertools import filterfalse, tee, zip_longest +from types import TracebackType +from typing import ( + Any, + BinaryIO, + Callable, + ContextManager, + Iterable, + Iterator, + List, + Optional, + TextIO, + Tuple, + Type, + TypeVar, + cast, +) + +from pip._vendor.tenacity import retry, stop_after_delay, wait_fixed + +from pip import __version__ +from pip._internal.exceptions import CommandError +from pip._internal.locations import get_major_minor_version +from pip._internal.utils.compat import WINDOWS +from pip._internal.utils.virtualenv import running_under_virtualenv + +__all__ = [ + "rmtree", + "display_path", + "backup_dir", + "ask", + "splitext", + "format_size", + "is_installable_dir", + "normalize_path", + "renames", + "get_prog", + "captured_stdout", + "ensure_dir", + "remove_auth_from_url", +] + + +logger = logging.getLogger(__name__) + +T = TypeVar("T") +ExcInfo = Tuple[Type[BaseException], BaseException, TracebackType] +VersionInfo = Tuple[int, int, int] +NetlocTuple = Tuple[str, Tuple[Optional[str], Optional[str]]] + + +def get_pip_version() -> str: + pip_pkg_dir = os.path.join(os.path.dirname(__file__), "..", "..") + pip_pkg_dir = os.path.abspath(pip_pkg_dir) + + return "pip {} from {} (python {})".format( + __version__, + pip_pkg_dir, + get_major_minor_version(), + ) + + +def normalize_version_info(py_version_info: Tuple[int, ...]) -> Tuple[int, int, int]: + """ + Convert a tuple of ints representing a Python version to one of length + three. + + :param py_version_info: a tuple of ints representing a Python version, + or None to specify no version. The tuple can have any length. + + :return: a tuple of length three if `py_version_info` is non-None. + Otherwise, return `py_version_info` unchanged (i.e. None). + """ + if len(py_version_info) < 3: + py_version_info += (3 - len(py_version_info)) * (0,) + elif len(py_version_info) > 3: + py_version_info = py_version_info[:3] + + return cast("VersionInfo", py_version_info) + + +def ensure_dir(path: str) -> None: + """os.path.makedirs without EEXIST.""" + try: + os.makedirs(path) + except OSError as e: + # Windows can raise spurious ENOTEMPTY errors. See #6426. + if e.errno != errno.EEXIST and e.errno != errno.ENOTEMPTY: + raise + + +def get_prog() -> str: + try: + prog = os.path.basename(sys.argv[0]) + if prog in ("__main__.py", "-c"): + return f"{sys.executable} -m pip" + else: + return prog + except (AttributeError, TypeError, IndexError): + pass + return "pip" + + +# Retry every half second for up to 3 seconds +# Tenacity raises RetryError by default, explicitly raise the original exception +@retry(reraise=True, stop=stop_after_delay(3), wait=wait_fixed(0.5)) +def rmtree(dir: str, ignore_errors: bool = False) -> None: + shutil.rmtree(dir, ignore_errors=ignore_errors, onerror=rmtree_errorhandler) + + +def rmtree_errorhandler(func: Callable[..., Any], path: str, exc_info: ExcInfo) -> None: + """On Windows, the files in .svn are read-only, so when rmtree() tries to + remove them, an exception is thrown. We catch that here, remove the + read-only attribute, and hopefully continue without problems.""" + try: + has_attr_readonly = not (os.stat(path).st_mode & stat.S_IWRITE) + except OSError: + # it's equivalent to os.path.exists + return + + if has_attr_readonly: + # convert to read/write + os.chmod(path, stat.S_IWRITE) + # use the original function to repeat the operation + func(path) + return + else: + raise + + +def display_path(path: str) -> str: + """Gives the display value for a given path, making it relative to cwd + if possible.""" + path = os.path.normcase(os.path.abspath(path)) + if path.startswith(os.getcwd() + os.path.sep): + path = "." + path[len(os.getcwd()) :] + return path + + +def backup_dir(dir: str, ext: str = ".bak") -> str: + """Figure out the name of a directory to back up the given dir to + (adding .bak, .bak2, etc)""" + n = 1 + extension = ext + while os.path.exists(dir + extension): + n += 1 + extension = ext + str(n) + return dir + extension + + +def ask_path_exists(message: str, options: Iterable[str]) -> str: + for action in os.environ.get("PIP_EXISTS_ACTION", "").split(): + if action in options: + return action + return ask(message, options) + + +def _check_no_input(message: str) -> None: + """Raise an error if no input is allowed.""" + if os.environ.get("PIP_NO_INPUT"): + raise Exception( + f"No input was expected ($PIP_NO_INPUT set); question: {message}" + ) + + +def ask(message: str, options: Iterable[str]) -> str: + """Ask the message interactively, with the given possible responses""" + while 1: + _check_no_input(message) + response = input(message) + response = response.strip().lower() + if response not in options: + print( + "Your response ({!r}) was not one of the expected responses: " + "{}".format(response, ", ".join(options)) + ) + else: + return response + + +def ask_input(message: str) -> str: + """Ask for input interactively.""" + _check_no_input(message) + return input(message) + + +def ask_password(message: str) -> str: + """Ask for a password interactively.""" + _check_no_input(message) + return getpass.getpass(message) + + +def strtobool(val: str) -> int: + """Convert a string representation of truth to true (1) or false (0). + + True values are 'y', 'yes', 't', 'true', 'on', and '1'; false values + are 'n', 'no', 'f', 'false', 'off', and '0'. Raises ValueError if + 'val' is anything else. + """ + val = val.lower() + if val in ("y", "yes", "t", "true", "on", "1"): + return 1 + elif val in ("n", "no", "f", "false", "off", "0"): + return 0 + else: + raise ValueError(f"invalid truth value {val!r}") + + +def format_size(bytes: float) -> str: + if bytes > 1000 * 1000: + return "{:.1f} MB".format(bytes / 1000.0 / 1000) + elif bytes > 10 * 1000: + return "{} kB".format(int(bytes / 1000)) + elif bytes > 1000: + return "{:.1f} kB".format(bytes / 1000.0) + else: + return "{} bytes".format(int(bytes)) + + +def tabulate(rows: Iterable[Iterable[Any]]) -> Tuple[List[str], List[int]]: + """Return a list of formatted rows and a list of column sizes. + + For example:: + + >>> tabulate([['foobar', 2000], [0xdeadbeef]]) + (['foobar 2000', '3735928559'], [10, 4]) + """ + rows = [tuple(map(str, row)) for row in rows] + sizes = [max(map(len, col)) for col in zip_longest(*rows, fillvalue="")] + table = [" ".join(map(str.ljust, row, sizes)).rstrip() for row in rows] + return table, sizes + + +def is_installable_dir(path: str) -> bool: + """Is path is a directory containing pyproject.toml or setup.py? + + If pyproject.toml exists, this is a PEP 517 project. Otherwise we look for + a legacy setuptools layout by identifying setup.py. We don't check for the + setup.cfg because using it without setup.py is only available for PEP 517 + projects, which are already covered by the pyproject.toml check. + """ + if not os.path.isdir(path): + return False + if os.path.isfile(os.path.join(path, "pyproject.toml")): + return True + if os.path.isfile(os.path.join(path, "setup.py")): + return True + return False + + +def read_chunks(file: BinaryIO, size: int = io.DEFAULT_BUFFER_SIZE) -> Iterator[bytes]: + """Yield pieces of data from a file-like object until EOF.""" + while True: + chunk = file.read(size) + if not chunk: + break + yield chunk + + +def normalize_path(path: str, resolve_symlinks: bool = True) -> str: + """ + Convert a path to its canonical, case-normalized, absolute version. + + """ + path = os.path.expanduser(path) + if resolve_symlinks: + path = os.path.realpath(path) + else: + path = os.path.abspath(path) + return os.path.normcase(path) + + +def splitext(path: str) -> Tuple[str, str]: + """Like os.path.splitext, but take off .tar too""" + base, ext = posixpath.splitext(path) + if base.lower().endswith(".tar"): + ext = base[-4:] + ext + base = base[:-4] + return base, ext + + +def renames(old: str, new: str) -> None: + """Like os.renames(), but handles renaming across devices.""" + # Implementation borrowed from os.renames(). + head, tail = os.path.split(new) + if head and tail and not os.path.exists(head): + os.makedirs(head) + + shutil.move(old, new) + + head, tail = os.path.split(old) + if head and tail: + try: + os.removedirs(head) + except OSError: + pass + + +def is_local(path: str) -> bool: + """ + Return True if path is within sys.prefix, if we're running in a virtualenv. + + If we're not in a virtualenv, all paths are considered "local." + + Caution: this function assumes the head of path has been normalized + with normalize_path. + """ + if not running_under_virtualenv(): + return True + return path.startswith(normalize_path(sys.prefix)) + + +def write_output(msg: Any, *args: Any) -> None: + logger.info(msg, *args) + + +class StreamWrapper(StringIO): + orig_stream: TextIO = None + + @classmethod + def from_stream(cls, orig_stream: TextIO) -> "StreamWrapper": + cls.orig_stream = orig_stream + return cls() + + # compileall.compile_dir() needs stdout.encoding to print to stdout + # https://github.com/python/mypy/issues/4125 + @property + def encoding(self): # type: ignore + return self.orig_stream.encoding + + +@contextlib.contextmanager +def captured_output(stream_name: str) -> Iterator[StreamWrapper]: + """Return a context manager used by captured_stdout/stdin/stderr + that temporarily replaces the sys stream *stream_name* with a StringIO. + + Taken from Lib/support/__init__.py in the CPython repo. + """ + orig_stdout = getattr(sys, stream_name) + setattr(sys, stream_name, StreamWrapper.from_stream(orig_stdout)) + try: + yield getattr(sys, stream_name) + finally: + setattr(sys, stream_name, orig_stdout) + + +def captured_stdout() -> ContextManager[StreamWrapper]: + """Capture the output of sys.stdout: + + with captured_stdout() as stdout: + print('hello') + self.assertEqual(stdout.getvalue(), 'hello\n') + + Taken from Lib/support/__init__.py in the CPython repo. + """ + return captured_output("stdout") + + +def captured_stderr() -> ContextManager[StreamWrapper]: + """ + See captured_stdout(). + """ + return captured_output("stderr") + + +# Simulates an enum +def enum(*sequential: Any, **named: Any) -> Type[Any]: + enums = dict(zip(sequential, range(len(sequential))), **named) + reverse = {value: key for key, value in enums.items()} + enums["reverse_mapping"] = reverse + return type("Enum", (), enums) + + +def build_netloc(host: str, port: Optional[int]) -> str: + """ + Build a netloc from a host-port pair + """ + if port is None: + return host + if ":" in host: + # Only wrap host with square brackets when it is IPv6 + host = f"[{host}]" + return f"{host}:{port}" + + +def build_url_from_netloc(netloc: str, scheme: str = "https") -> str: + """ + Build a full URL from a netloc. + """ + if netloc.count(":") >= 2 and "@" not in netloc and "[" not in netloc: + # It must be a bare IPv6 address, so wrap it with brackets. + netloc = f"[{netloc}]" + return f"{scheme}://{netloc}" + + +def parse_netloc(netloc: str) -> Tuple[str, Optional[int]]: + """ + Return the host-port pair from a netloc. + """ + url = build_url_from_netloc(netloc) + parsed = urllib.parse.urlparse(url) + return parsed.hostname, parsed.port + + +def split_auth_from_netloc(netloc: str) -> NetlocTuple: + """ + Parse out and remove the auth information from a netloc. + + Returns: (netloc, (username, password)). + """ + if "@" not in netloc: + return netloc, (None, None) + + # Split from the right because that's how urllib.parse.urlsplit() + # behaves if more than one @ is present (which can be checked using + # the password attribute of urlsplit()'s return value). + auth, netloc = netloc.rsplit("@", 1) + pw: Optional[str] = None + if ":" in auth: + # Split from the left because that's how urllib.parse.urlsplit() + # behaves if more than one : is present (which again can be checked + # using the password attribute of the return value) + user, pw = auth.split(":", 1) + else: + user, pw = auth, None + + user = urllib.parse.unquote(user) + if pw is not None: + pw = urllib.parse.unquote(pw) + + return netloc, (user, pw) + + +def redact_netloc(netloc: str) -> str: + """ + Replace the sensitive data in a netloc with "****", if it exists. + + For example: + - "user:pass@example.com" returns "user:****@example.com" + - "accesstoken@example.com" returns "****@example.com" + """ + netloc, (user, password) = split_auth_from_netloc(netloc) + if user is None: + return netloc + if password is None: + user = "****" + password = "" + else: + user = urllib.parse.quote(user) + password = ":****" + return "{user}{password}@{netloc}".format( + user=user, password=password, netloc=netloc + ) + + +def _transform_url( + url: str, transform_netloc: Callable[[str], Tuple[Any, ...]] +) -> Tuple[str, NetlocTuple]: + """Transform and replace netloc in a url. + + transform_netloc is a function taking the netloc and returning a + tuple. The first element of this tuple is the new netloc. The + entire tuple is returned. + + Returns a tuple containing the transformed url as item 0 and the + original tuple returned by transform_netloc as item 1. + """ + purl = urllib.parse.urlsplit(url) + netloc_tuple = transform_netloc(purl.netloc) + # stripped url + url_pieces = (purl.scheme, netloc_tuple[0], purl.path, purl.query, purl.fragment) + surl = urllib.parse.urlunsplit(url_pieces) + return surl, cast("NetlocTuple", netloc_tuple) + + +def _get_netloc(netloc: str) -> NetlocTuple: + return split_auth_from_netloc(netloc) + + +def _redact_netloc(netloc: str) -> Tuple[str]: + return (redact_netloc(netloc),) + + +def split_auth_netloc_from_url(url: str) -> Tuple[str, str, Tuple[str, str]]: + """ + Parse a url into separate netloc, auth, and url with no auth. + + Returns: (url_without_auth, netloc, (username, password)) + """ + url_without_auth, (netloc, auth) = _transform_url(url, _get_netloc) + return url_without_auth, netloc, auth + + +def remove_auth_from_url(url: str) -> str: + """Return a copy of url with 'username:password@' removed.""" + # username/pass params are passed to subversion through flags + # and are not recognized in the url. + return _transform_url(url, _get_netloc)[0] + + +def redact_auth_from_url(url: str) -> str: + """Replace the password in a given url with ****.""" + return _transform_url(url, _redact_netloc)[0] + + +class HiddenText: + def __init__(self, secret: str, redacted: str) -> None: + self.secret = secret + self.redacted = redacted + + def __repr__(self) -> str: + return "".format(str(self)) + + def __str__(self) -> str: + return self.redacted + + # This is useful for testing. + def __eq__(self, other: Any) -> bool: + if type(self) != type(other): + return False + + # The string being used for redaction doesn't also have to match, + # just the raw, original string. + return self.secret == other.secret + + +def hide_value(value: str) -> HiddenText: + return HiddenText(value, redacted="****") + + +def hide_url(url: str) -> HiddenText: + redacted = redact_auth_from_url(url) + return HiddenText(url, redacted=redacted) + + +def protect_pip_from_modification_on_windows(modifying_pip: bool) -> None: + """Protection of pip.exe from modification on Windows + + On Windows, any operation modifying pip should be run as: + python -m pip ... + """ + pip_names = [ + "pip.exe", + "pip{}.exe".format(sys.version_info[0]), + "pip{}.{}.exe".format(*sys.version_info[:2]), + ] + + # See https://github.com/pypa/pip/issues/1299 for more discussion + should_show_use_python_msg = ( + modifying_pip and WINDOWS and os.path.basename(sys.argv[0]) in pip_names + ) + + if should_show_use_python_msg: + new_command = [sys.executable, "-m", "pip"] + sys.argv[1:] + raise CommandError( + "To modify pip, please run the following command:\n{}".format( + " ".join(new_command) + ) + ) + + +def is_console_interactive() -> bool: + """Is this console interactive?""" + return sys.stdin is not None and sys.stdin.isatty() + + +def hash_file(path: str, blocksize: int = 1 << 20) -> Tuple[Any, int]: + """Return (hash, length) for path using hashlib.sha256()""" + + h = hashlib.sha256() + length = 0 + with open(path, "rb") as f: + for block in read_chunks(f, size=blocksize): + length += len(block) + h.update(block) + return h, length + + +def is_wheel_installed() -> bool: + """ + Return whether the wheel package is installed. + """ + try: + import wheel # noqa: F401 + except ImportError: + return False + + return True + + +def pairwise(iterable: Iterable[Any]) -> Iterator[Tuple[Any, Any]]: + """ + Return paired elements. + + For example: + s -> (s0, s1), (s2, s3), (s4, s5), ... + """ + iterable = iter(iterable) + return zip_longest(iterable, iterable) + + +def partition( + pred: Callable[[T], bool], + iterable: Iterable[T], +) -> Tuple[Iterable[T], Iterable[T]]: + """ + Use a predicate to partition entries into false entries and true entries, + like + + partition(is_odd, range(10)) --> 0 2 4 6 8 and 1 3 5 7 9 + """ + t1, t2 = tee(iterable) + return filterfalse(pred, t1), filter(pred, t2) diff --git a/venv/Lib/site-packages/pip/_internal/utils/models.py b/venv/Lib/site-packages/pip/_internal/utils/models.py new file mode 100644 index 0000000..b6bb21a --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/utils/models.py @@ -0,0 +1,39 @@ +"""Utilities for defining models +""" + +import operator +from typing import Any, Callable, Type + + +class KeyBasedCompareMixin: + """Provides comparison capabilities that is based on a key""" + + __slots__ = ["_compare_key", "_defining_class"] + + def __init__(self, key: Any, defining_class: Type["KeyBasedCompareMixin"]) -> None: + self._compare_key = key + self._defining_class = defining_class + + def __hash__(self) -> int: + return hash(self._compare_key) + + def __lt__(self, other: Any) -> bool: + return self._compare(other, operator.__lt__) + + def __le__(self, other: Any) -> bool: + return self._compare(other, operator.__le__) + + def __gt__(self, other: Any) -> bool: + return self._compare(other, operator.__gt__) + + def __ge__(self, other: Any) -> bool: + return self._compare(other, operator.__ge__) + + def __eq__(self, other: Any) -> bool: + return self._compare(other, operator.__eq__) + + def _compare(self, other: Any, method: Callable[[Any, Any], bool]) -> bool: + if not isinstance(other, self._defining_class): + return NotImplemented + + return method(self._compare_key, other._compare_key) diff --git a/venv/Lib/site-packages/pip/_internal/utils/packaging.py b/venv/Lib/site-packages/pip/_internal/utils/packaging.py new file mode 100644 index 0000000..b9f6af4 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/utils/packaging.py @@ -0,0 +1,57 @@ +import functools +import logging +import re +from typing import NewType, Optional, Tuple, cast + +from pip._vendor.packaging import specifiers, version +from pip._vendor.packaging.requirements import Requirement + +NormalizedExtra = NewType("NormalizedExtra", str) + +logger = logging.getLogger(__name__) + + +def check_requires_python( + requires_python: Optional[str], version_info: Tuple[int, ...] +) -> bool: + """ + Check if the given Python version matches a "Requires-Python" specifier. + + :param version_info: A 3-tuple of ints representing a Python + major-minor-micro version to check (e.g. `sys.version_info[:3]`). + + :return: `True` if the given Python version satisfies the requirement. + Otherwise, return `False`. + + :raises InvalidSpecifier: If `requires_python` has an invalid format. + """ + if requires_python is None: + # The package provides no information + return True + requires_python_specifier = specifiers.SpecifierSet(requires_python) + + python_version = version.parse(".".join(map(str, version_info))) + return python_version in requires_python_specifier + + +@functools.lru_cache(maxsize=512) +def get_requirement(req_string: str) -> Requirement: + """Construct a packaging.Requirement object with caching""" + # Parsing requirement strings is expensive, and is also expected to happen + # with a low diversity of different arguments (at least relative the number + # constructed). This method adds a cache to requirement object creation to + # minimize repeated parsing of the same string to construct equivalent + # Requirement objects. + return Requirement(req_string) + + +def safe_extra(extra: str) -> NormalizedExtra: + """Convert an arbitrary string to a standard 'extra' name + + Any runs of non-alphanumeric characters are replaced with a single '_', + and the result is always lowercased. + + This function is duplicated from ``pkg_resources``. Note that this is not + the same to either ``canonicalize_name`` or ``_egg_link_name``. + """ + return cast(NormalizedExtra, re.sub("[^A-Za-z0-9.-]+", "_", extra).lower()) diff --git a/venv/Lib/site-packages/pip/_internal/utils/setuptools_build.py b/venv/Lib/site-packages/pip/_internal/utils/setuptools_build.py new file mode 100644 index 0000000..f460c40 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/utils/setuptools_build.py @@ -0,0 +1,195 @@ +import sys +import textwrap +from typing import List, Optional, Sequence + +# Shim to wrap setup.py invocation with setuptools +# Note that __file__ is handled via two {!r} *and* %r, to ensure that paths on +# Windows are correctly handled (it should be "C:\\Users" not "C:\Users"). +_SETUPTOOLS_SHIM = textwrap.dedent( + """ + exec(compile(''' + # This is -- a caller that pip uses to run setup.py + # + # - It imports setuptools before invoking setup.py, to enable projects that directly + # import from `distutils.core` to work with newer packaging standards. + # - It provides a clear error message when setuptools is not installed. + # - It sets `sys.argv[0]` to the underlying `setup.py`, when invoking `setup.py` so + # setuptools doesn't think the script is `-c`. This avoids the following warning: + # manifest_maker: standard file '-c' not found". + # - It generates a shim setup.py, for handling setup.cfg-only projects. + import os, sys, tokenize + + try: + import setuptools + except ImportError as error: + print( + "ERROR: Can not execute `setup.py` since setuptools is not available in " + "the build environment.", + file=sys.stderr, + ) + sys.exit(1) + + __file__ = %r + sys.argv[0] = __file__ + + if os.path.exists(__file__): + filename = __file__ + with tokenize.open(__file__) as f: + setup_py_code = f.read() + else: + filename = "" + setup_py_code = "from setuptools import setup; setup()" + + exec(compile(setup_py_code, filename, "exec")) + ''' % ({!r},), "", "exec")) + """ +).rstrip() + + +def make_setuptools_shim_args( + setup_py_path: str, + global_options: Sequence[str] = None, + no_user_config: bool = False, + unbuffered_output: bool = False, +) -> List[str]: + """ + Get setuptools command arguments with shim wrapped setup file invocation. + + :param setup_py_path: The path to setup.py to be wrapped. + :param global_options: Additional global options. + :param no_user_config: If True, disables personal user configuration. + :param unbuffered_output: If True, adds the unbuffered switch to the + argument list. + """ + args = [sys.executable] + if unbuffered_output: + args += ["-u"] + args += ["-c", _SETUPTOOLS_SHIM.format(setup_py_path)] + if global_options: + args += global_options + if no_user_config: + args += ["--no-user-cfg"] + return args + + +def make_setuptools_bdist_wheel_args( + setup_py_path: str, + global_options: Sequence[str], + build_options: Sequence[str], + destination_dir: str, +) -> List[str]: + # NOTE: Eventually, we'd want to also -S to the flags here, when we're + # isolating. Currently, it breaks Python in virtualenvs, because it + # relies on site.py to find parts of the standard library outside the + # virtualenv. + args = make_setuptools_shim_args( + setup_py_path, global_options=global_options, unbuffered_output=True + ) + args += ["bdist_wheel", "-d", destination_dir] + args += build_options + return args + + +def make_setuptools_clean_args( + setup_py_path: str, + global_options: Sequence[str], +) -> List[str]: + args = make_setuptools_shim_args( + setup_py_path, global_options=global_options, unbuffered_output=True + ) + args += ["clean", "--all"] + return args + + +def make_setuptools_develop_args( + setup_py_path: str, + global_options: Sequence[str], + install_options: Sequence[str], + no_user_config: bool, + prefix: Optional[str], + home: Optional[str], + use_user_site: bool, +) -> List[str]: + assert not (use_user_site and prefix) + + args = make_setuptools_shim_args( + setup_py_path, + global_options=global_options, + no_user_config=no_user_config, + ) + + args += ["develop", "--no-deps"] + + args += install_options + + if prefix: + args += ["--prefix", prefix] + if home is not None: + args += ["--install-dir", home] + + if use_user_site: + args += ["--user", "--prefix="] + + return args + + +def make_setuptools_egg_info_args( + setup_py_path: str, + egg_info_dir: Optional[str], + no_user_config: bool, +) -> List[str]: + args = make_setuptools_shim_args(setup_py_path, no_user_config=no_user_config) + + args += ["egg_info"] + + if egg_info_dir: + args += ["--egg-base", egg_info_dir] + + return args + + +def make_setuptools_install_args( + setup_py_path: str, + global_options: Sequence[str], + install_options: Sequence[str], + record_filename: str, + root: Optional[str], + prefix: Optional[str], + header_dir: Optional[str], + home: Optional[str], + use_user_site: bool, + no_user_config: bool, + pycompile: bool, +) -> List[str]: + assert not (use_user_site and prefix) + assert not (use_user_site and root) + + args = make_setuptools_shim_args( + setup_py_path, + global_options=global_options, + no_user_config=no_user_config, + unbuffered_output=True, + ) + args += ["install", "--record", record_filename] + args += ["--single-version-externally-managed"] + + if root is not None: + args += ["--root", root] + if prefix is not None: + args += ["--prefix", prefix] + if home is not None: + args += ["--home", home] + if use_user_site: + args += ["--user", "--prefix="] + + if pycompile: + args += ["--compile"] + else: + args += ["--no-compile"] + + if header_dir: + args += ["--install-headers", header_dir] + + args += install_options + + return args diff --git a/venv/Lib/site-packages/pip/_internal/utils/subprocess.py b/venv/Lib/site-packages/pip/_internal/utils/subprocess.py new file mode 100644 index 0000000..b5b7624 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/utils/subprocess.py @@ -0,0 +1,260 @@ +import logging +import os +import shlex +import subprocess +from typing import ( + TYPE_CHECKING, + Any, + Callable, + Iterable, + List, + Mapping, + Optional, + Union, +) + +from pip._vendor.rich.markup import escape + +from pip._internal.cli.spinners import SpinnerInterface, open_spinner +from pip._internal.exceptions import InstallationSubprocessError +from pip._internal.utils.logging import VERBOSE, subprocess_logger +from pip._internal.utils.misc import HiddenText + +if TYPE_CHECKING: + # Literal was introduced in Python 3.8. + # + # TODO: Remove `if TYPE_CHECKING` when dropping support for Python 3.7. + from typing import Literal + +CommandArgs = List[Union[str, HiddenText]] + + +def make_command(*args: Union[str, HiddenText, CommandArgs]) -> CommandArgs: + """ + Create a CommandArgs object. + """ + command_args: CommandArgs = [] + for arg in args: + # Check for list instead of CommandArgs since CommandArgs is + # only known during type-checking. + if isinstance(arg, list): + command_args.extend(arg) + else: + # Otherwise, arg is str or HiddenText. + command_args.append(arg) + + return command_args + + +def format_command_args(args: Union[List[str], CommandArgs]) -> str: + """ + Format command arguments for display. + """ + # For HiddenText arguments, display the redacted form by calling str(). + # Also, we don't apply str() to arguments that aren't HiddenText since + # this can trigger a UnicodeDecodeError in Python 2 if the argument + # has type unicode and includes a non-ascii character. (The type + # checker doesn't ensure the annotations are correct in all cases.) + return " ".join( + shlex.quote(str(arg)) if isinstance(arg, HiddenText) else shlex.quote(arg) + for arg in args + ) + + +def reveal_command_args(args: Union[List[str], CommandArgs]) -> List[str]: + """ + Return the arguments in their raw, unredacted form. + """ + return [arg.secret if isinstance(arg, HiddenText) else arg for arg in args] + + +def call_subprocess( + cmd: Union[List[str], CommandArgs], + show_stdout: bool = False, + cwd: Optional[str] = None, + on_returncode: 'Literal["raise", "warn", "ignore"]' = "raise", + extra_ok_returncodes: Optional[Iterable[int]] = None, + extra_environ: Optional[Mapping[str, Any]] = None, + unset_environ: Optional[Iterable[str]] = None, + spinner: Optional[SpinnerInterface] = None, + log_failed_cmd: Optional[bool] = True, + stdout_only: Optional[bool] = False, + *, + command_desc: str, +) -> str: + """ + Args: + show_stdout: if true, use INFO to log the subprocess's stderr and + stdout streams. Otherwise, use DEBUG. Defaults to False. + extra_ok_returncodes: an iterable of integer return codes that are + acceptable, in addition to 0. Defaults to None, which means []. + unset_environ: an iterable of environment variable names to unset + prior to calling subprocess.Popen(). + log_failed_cmd: if false, failed commands are not logged, only raised. + stdout_only: if true, return only stdout, else return both. When true, + logging of both stdout and stderr occurs when the subprocess has + terminated, else logging occurs as subprocess output is produced. + """ + if extra_ok_returncodes is None: + extra_ok_returncodes = [] + if unset_environ is None: + unset_environ = [] + # Most places in pip use show_stdout=False. What this means is-- + # + # - We connect the child's output (combined stderr and stdout) to a + # single pipe, which we read. + # - We log this output to stderr at DEBUG level as it is received. + # - If DEBUG logging isn't enabled (e.g. if --verbose logging wasn't + # requested), then we show a spinner so the user can still see the + # subprocess is in progress. + # - If the subprocess exits with an error, we log the output to stderr + # at ERROR level if it hasn't already been displayed to the console + # (e.g. if --verbose logging wasn't enabled). This way we don't log + # the output to the console twice. + # + # If show_stdout=True, then the above is still done, but with DEBUG + # replaced by INFO. + if show_stdout: + # Then log the subprocess output at INFO level. + log_subprocess = subprocess_logger.info + used_level = logging.INFO + else: + # Then log the subprocess output using VERBOSE. This also ensures + # it will be logged to the log file (aka user_log), if enabled. + log_subprocess = subprocess_logger.verbose + used_level = VERBOSE + + # Whether the subprocess will be visible in the console. + showing_subprocess = subprocess_logger.getEffectiveLevel() <= used_level + + # Only use the spinner if we're not showing the subprocess output + # and we have a spinner. + use_spinner = not showing_subprocess and spinner is not None + + log_subprocess("Running command %s", command_desc) + env = os.environ.copy() + if extra_environ: + env.update(extra_environ) + for name in unset_environ: + env.pop(name, None) + try: + proc = subprocess.Popen( + # Convert HiddenText objects to the underlying str. + reveal_command_args(cmd), + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT if not stdout_only else subprocess.PIPE, + cwd=cwd, + env=env, + errors="backslashreplace", + ) + except Exception as exc: + if log_failed_cmd: + subprocess_logger.critical( + "Error %s while executing command %s", + exc, + command_desc, + ) + raise + all_output = [] + if not stdout_only: + assert proc.stdout + assert proc.stdin + proc.stdin.close() + # In this mode, stdout and stderr are in the same pipe. + while True: + line: str = proc.stdout.readline() + if not line: + break + line = line.rstrip() + all_output.append(line + "\n") + + # Show the line immediately. + log_subprocess(line) + # Update the spinner. + if use_spinner: + assert spinner + spinner.spin() + try: + proc.wait() + finally: + if proc.stdout: + proc.stdout.close() + output = "".join(all_output) + else: + # In this mode, stdout and stderr are in different pipes. + # We must use communicate() which is the only safe way to read both. + out, err = proc.communicate() + # log line by line to preserve pip log indenting + for out_line in out.splitlines(): + log_subprocess(out_line) + all_output.append(out) + for err_line in err.splitlines(): + log_subprocess(err_line) + all_output.append(err) + output = out + + proc_had_error = proc.returncode and proc.returncode not in extra_ok_returncodes + if use_spinner: + assert spinner + if proc_had_error: + spinner.finish("error") + else: + spinner.finish("done") + if proc_had_error: + if on_returncode == "raise": + error = InstallationSubprocessError( + command_description=command_desc, + exit_code=proc.returncode, + output_lines=all_output if not showing_subprocess else None, + ) + if log_failed_cmd: + subprocess_logger.error("[present-diagnostic] %s", error) + subprocess_logger.verbose( + "[bold magenta]full command[/]: [blue]%s[/]", + escape(format_command_args(cmd)), + extra={"markup": True}, + ) + subprocess_logger.verbose( + "[bold magenta]cwd[/]: %s", + escape(cwd or "[inherit]"), + extra={"markup": True}, + ) + + raise error + elif on_returncode == "warn": + subprocess_logger.warning( + 'Command "%s" had error code %s in %s', + command_desc, + proc.returncode, + cwd, + ) + elif on_returncode == "ignore": + pass + else: + raise ValueError(f"Invalid value: on_returncode={on_returncode!r}") + return output + + +def runner_with_spinner_message(message: str) -> Callable[..., None]: + """Provide a subprocess_runner that shows a spinner message. + + Intended for use with for pep517's Pep517HookCaller. Thus, the runner has + an API that matches what's expected by Pep517HookCaller.subprocess_runner. + """ + + def runner( + cmd: List[str], + cwd: Optional[str] = None, + extra_environ: Optional[Mapping[str, Any]] = None, + ) -> None: + with open_spinner(message) as spinner: + call_subprocess( + cmd, + command_desc=message, + cwd=cwd, + extra_environ=extra_environ, + spinner=spinner, + ) + + return runner diff --git a/venv/Lib/site-packages/pip/_internal/utils/temp_dir.py b/venv/Lib/site-packages/pip/_internal/utils/temp_dir.py new file mode 100644 index 0000000..442679a --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/utils/temp_dir.py @@ -0,0 +1,246 @@ +import errno +import itertools +import logging +import os.path +import tempfile +from contextlib import ExitStack, contextmanager +from typing import Any, Dict, Iterator, Optional, TypeVar, Union + +from pip._internal.utils.misc import enum, rmtree + +logger = logging.getLogger(__name__) + +_T = TypeVar("_T", bound="TempDirectory") + + +# Kinds of temporary directories. Only needed for ones that are +# globally-managed. +tempdir_kinds = enum( + BUILD_ENV="build-env", + EPHEM_WHEEL_CACHE="ephem-wheel-cache", + REQ_BUILD="req-build", +) + + +_tempdir_manager: Optional[ExitStack] = None + + +@contextmanager +def global_tempdir_manager() -> Iterator[None]: + global _tempdir_manager + with ExitStack() as stack: + old_tempdir_manager, _tempdir_manager = _tempdir_manager, stack + try: + yield + finally: + _tempdir_manager = old_tempdir_manager + + +class TempDirectoryTypeRegistry: + """Manages temp directory behavior""" + + def __init__(self) -> None: + self._should_delete: Dict[str, bool] = {} + + def set_delete(self, kind: str, value: bool) -> None: + """Indicate whether a TempDirectory of the given kind should be + auto-deleted. + """ + self._should_delete[kind] = value + + def get_delete(self, kind: str) -> bool: + """Get configured auto-delete flag for a given TempDirectory type, + default True. + """ + return self._should_delete.get(kind, True) + + +_tempdir_registry: Optional[TempDirectoryTypeRegistry] = None + + +@contextmanager +def tempdir_registry() -> Iterator[TempDirectoryTypeRegistry]: + """Provides a scoped global tempdir registry that can be used to dictate + whether directories should be deleted. + """ + global _tempdir_registry + old_tempdir_registry = _tempdir_registry + _tempdir_registry = TempDirectoryTypeRegistry() + try: + yield _tempdir_registry + finally: + _tempdir_registry = old_tempdir_registry + + +class _Default: + pass + + +_default = _Default() + + +class TempDirectory: + """Helper class that owns and cleans up a temporary directory. + + This class can be used as a context manager or as an OO representation of a + temporary directory. + + Attributes: + path + Location to the created temporary directory + delete + Whether the directory should be deleted when exiting + (when used as a contextmanager) + + Methods: + cleanup() + Deletes the temporary directory + + When used as a context manager, if the delete attribute is True, on + exiting the context the temporary directory is deleted. + """ + + def __init__( + self, + path: Optional[str] = None, + delete: Union[bool, None, _Default] = _default, + kind: str = "temp", + globally_managed: bool = False, + ): + super().__init__() + + if delete is _default: + if path is not None: + # If we were given an explicit directory, resolve delete option + # now. + delete = False + else: + # Otherwise, we wait until cleanup and see what + # tempdir_registry says. + delete = None + + # The only time we specify path is in for editables where it + # is the value of the --src option. + if path is None: + path = self._create(kind) + + self._path = path + self._deleted = False + self.delete = delete + self.kind = kind + + if globally_managed: + assert _tempdir_manager is not None + _tempdir_manager.enter_context(self) + + @property + def path(self) -> str: + assert not self._deleted, f"Attempted to access deleted path: {self._path}" + return self._path + + def __repr__(self) -> str: + return f"<{self.__class__.__name__} {self.path!r}>" + + def __enter__(self: _T) -> _T: + return self + + def __exit__(self, exc: Any, value: Any, tb: Any) -> None: + if self.delete is not None: + delete = self.delete + elif _tempdir_registry: + delete = _tempdir_registry.get_delete(self.kind) + else: + delete = True + + if delete: + self.cleanup() + + def _create(self, kind: str) -> str: + """Create a temporary directory and store its path in self.path""" + # We realpath here because some systems have their default tmpdir + # symlinked to another directory. This tends to confuse build + # scripts, so we canonicalize the path by traversing potential + # symlinks here. + path = os.path.realpath(tempfile.mkdtemp(prefix=f"pip-{kind}-")) + logger.debug("Created temporary directory: %s", path) + return path + + def cleanup(self) -> None: + """Remove the temporary directory created and reset state""" + self._deleted = True + if not os.path.exists(self._path): + return + rmtree(self._path) + + +class AdjacentTempDirectory(TempDirectory): + """Helper class that creates a temporary directory adjacent to a real one. + + Attributes: + original + The original directory to create a temp directory for. + path + After calling create() or entering, contains the full + path to the temporary directory. + delete + Whether the directory should be deleted when exiting + (when used as a contextmanager) + + """ + + # The characters that may be used to name the temp directory + # We always prepend a ~ and then rotate through these until + # a usable name is found. + # pkg_resources raises a different error for .dist-info folder + # with leading '-' and invalid metadata + LEADING_CHARS = "-~.=%0123456789" + + def __init__(self, original: str, delete: Optional[bool] = None) -> None: + self.original = original.rstrip("/\\") + super().__init__(delete=delete) + + @classmethod + def _generate_names(cls, name: str) -> Iterator[str]: + """Generates a series of temporary names. + + The algorithm replaces the leading characters in the name + with ones that are valid filesystem characters, but are not + valid package names (for both Python and pip definitions of + package). + """ + for i in range(1, len(name)): + for candidate in itertools.combinations_with_replacement( + cls.LEADING_CHARS, i - 1 + ): + new_name = "~" + "".join(candidate) + name[i:] + if new_name != name: + yield new_name + + # If we make it this far, we will have to make a longer name + for i in range(len(cls.LEADING_CHARS)): + for candidate in itertools.combinations_with_replacement( + cls.LEADING_CHARS, i + ): + new_name = "~" + "".join(candidate) + name + if new_name != name: + yield new_name + + def _create(self, kind: str) -> str: + root, name = os.path.split(self.original) + for candidate in self._generate_names(name): + path = os.path.join(root, candidate) + try: + os.mkdir(path) + except OSError as ex: + # Continue if the name exists already + if ex.errno != errno.EEXIST: + raise + else: + path = os.path.realpath(path) + break + else: + # Final fallback on the default behavior. + path = os.path.realpath(tempfile.mkdtemp(prefix=f"pip-{kind}-")) + + logger.debug("Created temporary directory: %s", path) + return path diff --git a/venv/Lib/site-packages/pip/_internal/utils/unpacking.py b/venv/Lib/site-packages/pip/_internal/utils/unpacking.py new file mode 100644 index 0000000..5f63f97 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/utils/unpacking.py @@ -0,0 +1,258 @@ +"""Utilities related archives. +""" + +import logging +import os +import shutil +import stat +import tarfile +import zipfile +from typing import Iterable, List, Optional +from zipfile import ZipInfo + +from pip._internal.exceptions import InstallationError +from pip._internal.utils.filetypes import ( + BZ2_EXTENSIONS, + TAR_EXTENSIONS, + XZ_EXTENSIONS, + ZIP_EXTENSIONS, +) +from pip._internal.utils.misc import ensure_dir + +logger = logging.getLogger(__name__) + + +SUPPORTED_EXTENSIONS = ZIP_EXTENSIONS + TAR_EXTENSIONS + +try: + import bz2 # noqa + + SUPPORTED_EXTENSIONS += BZ2_EXTENSIONS +except ImportError: + logger.debug("bz2 module is not available") + +try: + # Only for Python 3.3+ + import lzma # noqa + + SUPPORTED_EXTENSIONS += XZ_EXTENSIONS +except ImportError: + logger.debug("lzma module is not available") + + +def current_umask() -> int: + """Get the current umask which involves having to set it temporarily.""" + mask = os.umask(0) + os.umask(mask) + return mask + + +def split_leading_dir(path: str) -> List[str]: + path = path.lstrip("/").lstrip("\\") + if "/" in path and ( + ("\\" in path and path.find("/") < path.find("\\")) or "\\" not in path + ): + return path.split("/", 1) + elif "\\" in path: + return path.split("\\", 1) + else: + return [path, ""] + + +def has_leading_dir(paths: Iterable[str]) -> bool: + """Returns true if all the paths have the same leading path name + (i.e., everything is in one subdirectory in an archive)""" + common_prefix = None + for path in paths: + prefix, rest = split_leading_dir(path) + if not prefix: + return False + elif common_prefix is None: + common_prefix = prefix + elif prefix != common_prefix: + return False + return True + + +def is_within_directory(directory: str, target: str) -> bool: + """ + Return true if the absolute path of target is within the directory + """ + abs_directory = os.path.abspath(directory) + abs_target = os.path.abspath(target) + + prefix = os.path.commonprefix([abs_directory, abs_target]) + return prefix == abs_directory + + +def set_extracted_file_to_default_mode_plus_executable(path: str) -> None: + """ + Make file present at path have execute for user/group/world + (chmod +x) is no-op on windows per python docs + """ + os.chmod(path, (0o777 & ~current_umask() | 0o111)) + + +def zip_item_is_executable(info: ZipInfo) -> bool: + mode = info.external_attr >> 16 + # if mode and regular file and any execute permissions for + # user/group/world? + return bool(mode and stat.S_ISREG(mode) and mode & 0o111) + + +def unzip_file(filename: str, location: str, flatten: bool = True) -> None: + """ + Unzip the file (with path `filename`) to the destination `location`. All + files are written based on system defaults and umask (i.e. permissions are + not preserved), except that regular file members with any execute + permissions (user, group, or world) have "chmod +x" applied after being + written. Note that for windows, any execute changes using os.chmod are + no-ops per the python docs. + """ + ensure_dir(location) + zipfp = open(filename, "rb") + try: + zip = zipfile.ZipFile(zipfp, allowZip64=True) + leading = has_leading_dir(zip.namelist()) and flatten + for info in zip.infolist(): + name = info.filename + fn = name + if leading: + fn = split_leading_dir(name)[1] + fn = os.path.join(location, fn) + dir = os.path.dirname(fn) + if not is_within_directory(location, fn): + message = ( + "The zip file ({}) has a file ({}) trying to install " + "outside target directory ({})" + ) + raise InstallationError(message.format(filename, fn, location)) + if fn.endswith("/") or fn.endswith("\\"): + # A directory + ensure_dir(fn) + else: + ensure_dir(dir) + # Don't use read() to avoid allocating an arbitrarily large + # chunk of memory for the file's content + fp = zip.open(name) + try: + with open(fn, "wb") as destfp: + shutil.copyfileobj(fp, destfp) + finally: + fp.close() + if zip_item_is_executable(info): + set_extracted_file_to_default_mode_plus_executable(fn) + finally: + zipfp.close() + + +def untar_file(filename: str, location: str) -> None: + """ + Untar the file (with path `filename`) to the destination `location`. + All files are written based on system defaults and umask (i.e. permissions + are not preserved), except that regular file members with any execute + permissions (user, group, or world) have "chmod +x" applied after being + written. Note that for windows, any execute changes using os.chmod are + no-ops per the python docs. + """ + ensure_dir(location) + if filename.lower().endswith(".gz") or filename.lower().endswith(".tgz"): + mode = "r:gz" + elif filename.lower().endswith(BZ2_EXTENSIONS): + mode = "r:bz2" + elif filename.lower().endswith(XZ_EXTENSIONS): + mode = "r:xz" + elif filename.lower().endswith(".tar"): + mode = "r" + else: + logger.warning( + "Cannot determine compression type for file %s", + filename, + ) + mode = "r:*" + tar = tarfile.open(filename, mode, encoding="utf-8") + try: + leading = has_leading_dir([member.name for member in tar.getmembers()]) + for member in tar.getmembers(): + fn = member.name + if leading: + fn = split_leading_dir(fn)[1] + path = os.path.join(location, fn) + if not is_within_directory(location, path): + message = ( + "The tar file ({}) has a file ({}) trying to install " + "outside target directory ({})" + ) + raise InstallationError(message.format(filename, path, location)) + if member.isdir(): + ensure_dir(path) + elif member.issym(): + try: + # https://github.com/python/typeshed/issues/2673 + tar._extract_member(member, path) # type: ignore + except Exception as exc: + # Some corrupt tar files seem to produce this + # (specifically bad symlinks) + logger.warning( + "In the tar file %s the member %s is invalid: %s", + filename, + member.name, + exc, + ) + continue + else: + try: + fp = tar.extractfile(member) + except (KeyError, AttributeError) as exc: + # Some corrupt tar files seem to produce this + # (specifically bad symlinks) + logger.warning( + "In the tar file %s the member %s is invalid: %s", + filename, + member.name, + exc, + ) + continue + ensure_dir(os.path.dirname(path)) + assert fp is not None + with open(path, "wb") as destfp: + shutil.copyfileobj(fp, destfp) + fp.close() + # Update the timestamp (useful for cython compiled files) + tar.utime(member, path) + # member have any execute permissions for user/group/world? + if member.mode & 0o111: + set_extracted_file_to_default_mode_plus_executable(path) + finally: + tar.close() + + +def unpack_file( + filename: str, + location: str, + content_type: Optional[str] = None, +) -> None: + filename = os.path.realpath(filename) + if ( + content_type == "application/zip" + or filename.lower().endswith(ZIP_EXTENSIONS) + or zipfile.is_zipfile(filename) + ): + unzip_file(filename, location, flatten=not filename.endswith(".whl")) + elif ( + content_type == "application/x-gzip" + or tarfile.is_tarfile(filename) + or filename.lower().endswith(TAR_EXTENSIONS + BZ2_EXTENSIONS + XZ_EXTENSIONS) + ): + untar_file(filename, location) + else: + # FIXME: handle? + # FIXME: magic signatures? + logger.critical( + "Cannot unpack file %s (downloaded from %s, content-type: %s); " + "cannot detect archive format", + filename, + location, + content_type, + ) + raise InstallationError(f"Cannot determine archive format of {location}") diff --git a/venv/Lib/site-packages/pip/_internal/utils/urls.py b/venv/Lib/site-packages/pip/_internal/utils/urls.py new file mode 100644 index 0000000..6ba2e04 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/utils/urls.py @@ -0,0 +1,62 @@ +import os +import string +import urllib.parse +import urllib.request +from typing import Optional + +from .compat import WINDOWS + + +def get_url_scheme(url: str) -> Optional[str]: + if ":" not in url: + return None + return url.split(":", 1)[0].lower() + + +def path_to_url(path: str) -> str: + """ + Convert a path to a file: URL. The path will be made absolute and have + quoted path parts. + """ + path = os.path.normpath(os.path.abspath(path)) + url = urllib.parse.urljoin("file:", urllib.request.pathname2url(path)) + return url + + +def url_to_path(url: str) -> str: + """ + Convert a file: URL to a path. + """ + assert url.startswith( + "file:" + ), f"You can only turn file: urls into filenames (not {url!r})" + + _, netloc, path, _, _ = urllib.parse.urlsplit(url) + + if not netloc or netloc == "localhost": + # According to RFC 8089, same as empty authority. + netloc = "" + elif WINDOWS: + # If we have a UNC path, prepend UNC share notation. + netloc = "\\\\" + netloc + else: + raise ValueError( + f"non-local file URIs are not supported on this platform: {url!r}" + ) + + path = urllib.request.url2pathname(netloc + path) + + # On Windows, urlsplit parses the path as something like "/C:/Users/foo". + # This creates issues for path-related functions like io.open(), so we try + # to detect and strip the leading slash. + if ( + WINDOWS + and not netloc # Not UNC. + and len(path) >= 3 + and path[0] == "/" # Leading slash to strip. + and path[1] in string.ascii_letters # Drive letter. + and path[2:4] in (":", ":/") # Colon + end of string, or colon + absolute path. + ): + path = path[1:] + + return path diff --git a/venv/Lib/site-packages/pip/_internal/utils/virtualenv.py b/venv/Lib/site-packages/pip/_internal/utils/virtualenv.py new file mode 100644 index 0000000..c926db4 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/utils/virtualenv.py @@ -0,0 +1,104 @@ +import logging +import os +import re +import site +import sys +from typing import List, Optional + +logger = logging.getLogger(__name__) +_INCLUDE_SYSTEM_SITE_PACKAGES_REGEX = re.compile( + r"include-system-site-packages\s*=\s*(?Ptrue|false)" +) + + +def _running_under_venv() -> bool: + """Checks if sys.base_prefix and sys.prefix match. + + This handles PEP 405 compliant virtual environments. + """ + return sys.prefix != getattr(sys, "base_prefix", sys.prefix) + + +def _running_under_regular_virtualenv() -> bool: + """Checks if sys.real_prefix is set. + + This handles virtual environments created with pypa's virtualenv. + """ + # pypa/virtualenv case + return hasattr(sys, "real_prefix") + + +def running_under_virtualenv() -> bool: + """Return True if we're running inside a virtualenv, False otherwise.""" + return _running_under_venv() or _running_under_regular_virtualenv() + + +def _get_pyvenv_cfg_lines() -> Optional[List[str]]: + """Reads {sys.prefix}/pyvenv.cfg and returns its contents as list of lines + + Returns None, if it could not read/access the file. + """ + pyvenv_cfg_file = os.path.join(sys.prefix, "pyvenv.cfg") + try: + # Although PEP 405 does not specify, the built-in venv module always + # writes with UTF-8. (pypa/pip#8717) + with open(pyvenv_cfg_file, encoding="utf-8") as f: + return f.read().splitlines() # avoids trailing newlines + except OSError: + return None + + +def _no_global_under_venv() -> bool: + """Check `{sys.prefix}/pyvenv.cfg` for system site-packages inclusion + + PEP 405 specifies that when system site-packages are not supposed to be + visible from a virtual environment, `pyvenv.cfg` must contain the following + line: + + include-system-site-packages = false + + Additionally, log a warning if accessing the file fails. + """ + cfg_lines = _get_pyvenv_cfg_lines() + if cfg_lines is None: + # We're not in a "sane" venv, so assume there is no system + # site-packages access (since that's PEP 405's default state). + logger.warning( + "Could not access 'pyvenv.cfg' despite a virtual environment " + "being active. Assuming global site-packages is not accessible " + "in this environment." + ) + return True + + for line in cfg_lines: + match = _INCLUDE_SYSTEM_SITE_PACKAGES_REGEX.match(line) + if match is not None and match.group("value") == "false": + return True + return False + + +def _no_global_under_regular_virtualenv() -> bool: + """Check if "no-global-site-packages.txt" exists beside site.py + + This mirrors logic in pypa/virtualenv for determining whether system + site-packages are visible in the virtual environment. + """ + site_mod_dir = os.path.dirname(os.path.abspath(site.__file__)) + no_global_site_packages_file = os.path.join( + site_mod_dir, + "no-global-site-packages.txt", + ) + return os.path.exists(no_global_site_packages_file) + + +def virtualenv_no_global() -> bool: + """Returns a boolean, whether running in venv with no system site-packages.""" + # PEP 405 compliance needs to be checked first since virtualenv >=20 would + # return True for both checks, but is only able to use the PEP 405 config. + if _running_under_venv(): + return _no_global_under_venv() + + if _running_under_regular_virtualenv(): + return _no_global_under_regular_virtualenv() + + return False diff --git a/venv/Lib/site-packages/pip/_internal/utils/wheel.py b/venv/Lib/site-packages/pip/_internal/utils/wheel.py new file mode 100644 index 0000000..e5e3f34 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/utils/wheel.py @@ -0,0 +1,136 @@ +"""Support functions for working with wheel files. +""" + +import logging +from email.message import Message +from email.parser import Parser +from typing import Tuple +from zipfile import BadZipFile, ZipFile + +from pip._vendor.packaging.utils import canonicalize_name + +from pip._internal.exceptions import UnsupportedWheel + +VERSION_COMPATIBLE = (1, 0) + + +logger = logging.getLogger(__name__) + + +def parse_wheel(wheel_zip: ZipFile, name: str) -> Tuple[str, Message]: + """Extract information from the provided wheel, ensuring it meets basic + standards. + + Returns the name of the .dist-info directory and the parsed WHEEL metadata. + """ + try: + info_dir = wheel_dist_info_dir(wheel_zip, name) + metadata = wheel_metadata(wheel_zip, info_dir) + version = wheel_version(metadata) + except UnsupportedWheel as e: + raise UnsupportedWheel("{} has an invalid wheel, {}".format(name, str(e))) + + check_compatibility(version, name) + + return info_dir, metadata + + +def wheel_dist_info_dir(source: ZipFile, name: str) -> str: + """Returns the name of the contained .dist-info directory. + + Raises AssertionError or UnsupportedWheel if not found, >1 found, or + it doesn't match the provided name. + """ + # Zip file path separators must be / + subdirs = {p.split("/", 1)[0] for p in source.namelist()} + + info_dirs = [s for s in subdirs if s.endswith(".dist-info")] + + if not info_dirs: + raise UnsupportedWheel(".dist-info directory not found") + + if len(info_dirs) > 1: + raise UnsupportedWheel( + "multiple .dist-info directories found: {}".format(", ".join(info_dirs)) + ) + + info_dir = info_dirs[0] + + info_dir_name = canonicalize_name(info_dir) + canonical_name = canonicalize_name(name) + if not info_dir_name.startswith(canonical_name): + raise UnsupportedWheel( + ".dist-info directory {!r} does not start with {!r}".format( + info_dir, canonical_name + ) + ) + + return info_dir + + +def read_wheel_metadata_file(source: ZipFile, path: str) -> bytes: + try: + return source.read(path) + # BadZipFile for general corruption, KeyError for missing entry, + # and RuntimeError for password-protected files + except (BadZipFile, KeyError, RuntimeError) as e: + raise UnsupportedWheel(f"could not read {path!r} file: {e!r}") + + +def wheel_metadata(source: ZipFile, dist_info_dir: str) -> Message: + """Return the WHEEL metadata of an extracted wheel, if possible. + Otherwise, raise UnsupportedWheel. + """ + path = f"{dist_info_dir}/WHEEL" + # Zip file path separators must be / + wheel_contents = read_wheel_metadata_file(source, path) + + try: + wheel_text = wheel_contents.decode() + except UnicodeDecodeError as e: + raise UnsupportedWheel(f"error decoding {path!r}: {e!r}") + + # FeedParser (used by Parser) does not raise any exceptions. The returned + # message may have .defects populated, but for backwards-compatibility we + # currently ignore them. + return Parser().parsestr(wheel_text) + + +def wheel_version(wheel_data: Message) -> Tuple[int, ...]: + """Given WHEEL metadata, return the parsed Wheel-Version. + Otherwise, raise UnsupportedWheel. + """ + version_text = wheel_data["Wheel-Version"] + if version_text is None: + raise UnsupportedWheel("WHEEL is missing Wheel-Version") + + version = version_text.strip() + + try: + return tuple(map(int, version.split("."))) + except ValueError: + raise UnsupportedWheel(f"invalid Wheel-Version: {version!r}") + + +def check_compatibility(version: Tuple[int, ...], name: str) -> None: + """Raises errors or warns if called with an incompatible Wheel-Version. + + pip should refuse to install a Wheel-Version that's a major series + ahead of what it's compatible with (e.g 2.0 > 1.1); and warn when + installing a version only minor version ahead (e.g 1.2 > 1.1). + + version: a 2-tuple representing a Wheel-Version (Major, Minor) + name: name of wheel or package to raise exception about + + :raises UnsupportedWheel: when an incompatible Wheel-Version is given + """ + if version[0] > VERSION_COMPATIBLE[0]: + raise UnsupportedWheel( + "{}'s Wheel-Version ({}) is not compatible with this version " + "of pip".format(name, ".".join(map(str, version))) + ) + elif version > VERSION_COMPATIBLE: + logger.warning( + "Installing from a newer Wheel-Version (%s)", + ".".join(map(str, version)), + ) diff --git a/venv/Lib/site-packages/pip/_internal/vcs/__init__.py b/venv/Lib/site-packages/pip/_internal/vcs/__init__.py new file mode 100644 index 0000000..b6beddb --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/vcs/__init__.py @@ -0,0 +1,15 @@ +# Expose a limited set of classes and functions so callers outside of +# the vcs package don't need to import deeper than `pip._internal.vcs`. +# (The test directory may still need to import from a vcs sub-package.) +# Import all vcs modules to register each VCS in the VcsSupport object. +import pip._internal.vcs.bazaar +import pip._internal.vcs.git +import pip._internal.vcs.mercurial +import pip._internal.vcs.subversion # noqa: F401 +from pip._internal.vcs.versioncontrol import ( # noqa: F401 + RemoteNotFoundError, + RemoteNotValidError, + is_url, + make_vcs_requirement_url, + vcs, +) diff --git a/venv/Lib/site-packages/pip/_internal/vcs/__pycache__/__init__.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/vcs/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..633dd37b678f5564a8bc2ba047977d9dabd72539 GIT binary patch literal 507 zcmZWlO-lnY5Y2Ym?Y7dB2n7W_2|aX=A|j$xJxLE*J*k9Cr**#F=U@h|1- z$-m&qq%Km}33)H`9y7y)3b8 z$SYuk+r6f#tND_GW=h(FrdwONk_Hq9|9cR6XnW{*h#Y((82Gn`pU24wzSpiNCQ=fO zFUs7MgAAINj8ei=vmnDAGE1)D|#QAW;f*pkgo@aFfeP!*6K{g?RAmp&B!3qjEI9FA^QTrS8tJiMLDcMiGH%uLII^6I^Z zyZ>oh*1xfHyHM!-4yyb+G|XZowF3OwDaq`>&YZx>Xg~?_oYc*{z{?sz!}MwDXU(8# zXg6(T?VxRFFYRPA!A#Z-y4h?noArWTHW$nhi(BXOeBpuw{oh-x!TgsN^Lg*o2^RU> z`4V5eAh4c%ZVj7nKpJan=xF*PkxKi2DpgYCQL5eTNtyDYty_Oc7~}ai|4Qi&OJtcw z$6*<%@sQ|F7VYyeF0w4j8T8x84^h2mR<+AJnH`&5WR z=+jH1~E#55a0k6mB zfIAO$0e9y8kpuhBo!MVoBf{p{!pjbv0oH{XKI_A|i)_i9yL5}U%vKC<+3@O}R@my9 z!|t*BW@Pnii(0`w@XVU_K8dO*6583VL`65C)!wd%@_0OKR6cZnI##Nznpc#p8c0ex zu1DnvMhy!I569B79vUUawT|G2+7nz&L>`k{mPXo!`V6Y{pyx~U;(gB6kH(y* z>%aQw%S6Vq!m*t&$rTrXz8&!X&aP2^qdeAgdt8OPk>nu=97bYK4&Ydc5?Xe(Qrl_c zdy}>Rf|PN9wF7w6ZCqR!d`sOtbZuuJUXUY7+GZa_8KkAavv=hlUF;wo|u zaGTmwS2T z^hwpbblvr`A-yYu@eU@>tAaFE;~f-pYJF)bf_^y#t1|nQjmZ(L>1=6F9wi{rYoeX_ zhz)J=BUoT80Vn+!={qW4KY<}> z1S7p0f$K3afbp&|stF&Mj0NXAmsM^6p{!HuoJ`3D*>O(DiG2cqNAO<|@c@(}%hm~u z0*sxJV@zFnka(Uveq2#ZG;pD~a#8{S`xurGes$>PfE&0IbW5s8D74~uNWnL$tOdiI zqMH*)BXGq?34UvaVVnXPhPA$kGl3F*4AtZ&%b6!Fz*KerRwB52B3xvC3YiFRw>si) ztB>)4)%dOg0x`wN9{7)e;*7qcC-&4vPd>N)x(&u~&TYsD4s)UZ3Ha7Iccv7K^9U%4 z6!TUgV?cbnQy2KV%A2~U#I^_|Rs!gpx;ON}qk}co_#0ejV9Lgp7=Q$u+pitnmgC|m zl!`$v2-@{GEb{bNd&w?D#Q6V^$LTFa)S^_}N*z;izMuM4$@h+Vwp#hZ2UZFeD3uiZ6(&i{88b63%* z-j;SD{pZEzw)iD1c=H{Ut8{v`3} zTME>3VS7w8n&wf)Yy6=SR|RRz=mvini{^1=R}Y`2N71ny0RAT#AE+@Oz`cc%$pI_! z57Z!wAiZrGIj>YO8SOc2a##9!@GQR75)~#a zbt??Bf=yDSJ7I{s)FT4V)D4!v4W4n`L^PO1x*-9k8Q`r0VXu-n<7!+m?Ev}&`c*7q zgUM6C)7jDvyaU7s*v0%S9wD!7vOv93pos(;O*FB=bRd3<4H{6>-J(dvr%29RW{;Ss z=~V_XY4hhe+vF1TAm&5)5E{Iz%&%pWCF&FVznz7?)2B9h(6GsT7i!Zc0@n|Mj!XE~${4v&LcIcynvLs6&BjC}socomy;JLo5Y|6<*Bm+7EkzM?DeGJNof~2B znZVS8xA%a@)5axC;`%vVn+fCB7+7?Wn!)3nfan+IsUR>k#e3MGdK!XY5B?HxaSKMq fbmpe_e^Z0tV}z~52Z&Glc8_%6x8}E;-sk@VC;vFw literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/vcs/__pycache__/git.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/vcs/__pycache__/git.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..808c250572e0f9741d79d1a646847921e1598124 GIT binary patch literal 12554 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 Vr`d{==Xpey_?pw77@rsy{~NjHfYJZ} literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/vcs/__pycache__/versioncontrol.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/vcs/__pycache__/versioncontrol.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9f966562bd8aa3b9c3e6fb9c17bdc13f57017604 GIT binary patch literal 21174 zcmch935+Dyd0tm_^)Wp?$L`MF2WyAdG&wWNLn5WsiXyek)zTtI)b5gw+N<=|bk)rC zY+w7TdY04bNnkD$0Wm0BPHaRGnas*?B1TCZz)65O7ip=BD>tOYu!M?5Lq1Ie=POfv!!>uFLBdw#=qjH~b9%~)1 z9&eqfo@kw{o@||}o@$-0o^G9~o@w1zy{~0gZE06%o^8!n=Uewz?{7U&eW3MV^+BmG zHXmv|Tz%Ncct!PXj5UGzEmRlqth8=aE1t3Yi1+9{qq^wLdNbbA@r*9l%;TBrvbW@& zb0^<2-LgCNhE;vcJ%bwl>6T0G^jkT1#+`j5SABd~?;dz7>mGCu;f*IglX2(V!*68V z!`_p3v(=B_{)l@N_ebUaqqslj9>@LhyJqz%+?{Yw;_f8wp7x%;o2h;bb*J3Zs5_0i zkGtlzOy$0Q<%-jGo1Skw&8Ge8#cTG$mZ$tir)}3e?Lc*!72EH1yB!sLha0<6nGC0{ zf8pilYZtFPfAO;~tb8WSKG)t3txJu15EfquJmsu5z33|FsL*<`;Rj*iC8yhMwAaJp z=ehxUcbZ}DdasL?*7fbK7v^4Rqqbs%v)9n9?Wq^q=xWWWdlfS*ecEv^c3LgWG(7M^ z+Yc~ThrK+nR7X{cVd+Z4b-ng=@3kPDar|4gt`lt3yw@1<1bu(;81y;@H-!;)NWInACI9&GrvMl=YPBJbr@D^Q+SvBJq{BG0LHKb)y!CN;me z+Etyp=lkKIwT@~zL9MQ5TXWc|+;VPtaTS(0z3v4ZwdU71yq1TW!ix<8t{G;x>i#=s zXtkY|7v_~0^i;bJ(n&rhuCn-E#MgfaMUWX}?ixGB03_ARs5x%yz*x_?*>4zuv1uO7 zY-O;~R{zP8jn7r-(hgM5vm0x6u;JMp%Wif$w|u+VxaHZ7{mRuBm!fY!!x=X!w7u)5zOLsOruetQp$2J>&-S6|+4Qva*1l+j+ zFx`moG(ywm?sk~R&H=6;$8dfTMaC)`MZ+@GBe<^Q!lLrJ9og@!^0vY|C zY$H%aokiQa#kZqR9{+Rr3doQ3Mi>X7E3Ia zQG~O2t(G1(#3tMp+|WgZt&Rz;V0&vRXmHB}`XX#fWn&JTI&G?t;*Cl+EH;5cWC!7d z07-Q^f!;<^OZ?%M@+%#^ii<&J$JEs0KZWZosbx1i$lNn_@NAI1WhyJMc5|*VFz=aQ z^PsHTmbA(b474-V71l{j0dE-h$WpWYe=j?BxzToIt4L!nZwDJ-snPNu_HEA5Ufs5R z&r$UaFh;xAmDZ#$f7=hdmc6DrE$QlJyuh2w2?3*1GC4cw#J%c1l}FaNrmLu@wqdgPJsU z*bn;lLZBMJOG=rpqk!Ue{J7!ym6b|S9l@T2W(Pcm3kwT)t_ic*Szq^5Sh(Y;wulfP z9835RP_D_w6-$vY)zj=^s-qg~wHRdKRMYW;VBDRL|jQolVjoa_?vH^~)%{3{;;C)gEAq86LVS zWW3S|E)%#S&Q^%gHQ`CMT3D*pS{=6sF;ol7wc72T(jz4)mvAcTzwSYf zr(yaM8_Q^yakYhS3{&3kfhlFgvuyM_iWsJ@0loH+XSrGEf;lfQW#Kp&iEF)Oxj8ov zZLjF%-NIXjTXZL&zx-PwbKfVTXntrB1*y%v^(X9O0`!=6BUSl+-aW#F#tkCA1bedvk$=4YY^Kg zfsBHNEYX5g*ndZsMeQgpZ+Rb2;5^|qGCe58tFk~neKw|u-qNyER4Rdkw;yQJ?+h2k zL7LE52|%eGLRfci+bdvn*ReP)Td(0NoLp5-yS^d(0#9G$Q$Em5q_OaaA(J5D{|S7B zA!W)?kj%WnzdqPej57)Kyklr!r6b4I zd$s%d^90Bz-!-0r{wVXb@xDwJBgyPXr%MI_Cah|;uc4t3VP<@$`uT{S%qb@Lz$tQq zZUz`}5Lb}&(2`MeEu&t*L(E0A6@loC>#aGxWl^U9(naaHj2F6rdj^z8!Pw2Lz7l-B zkl<^q%|jU&A?L{aurY%k)kzR(8ijrc;|lP@12jce9pB?ZHE9uL01s|OXrTjNgJx`3 z3Xqn3_)}=65y`TELPcZND2+lPYB&M~?hYX#P>6TOFOePvfkdf(J4@lS5@!0-&>lKN zLVDMz09Rzg_S>2gMvTn7pW*CecQ7~0>>p0;&al-xrta)4TJMo($z~nIQ=-hK-Vkio zn^gDA{!b*ZeF=7+?Z9yEZfh>++4Y_hWk;AM*yEzT+6y9{3SIpUR~2zk?$C27g`f9$ z`XL;Jrh`~;=%=$vQ)al&fKarPg4DC3S96miwymF?`wH!#J&Ng$GzGKCQi z5kIe(D=U?maT!~v)!a@Uv^$9x)dY*rvEXit>{aj=Wx^u#PpARGwi2ZLqkOu`VvWUc zN^&Lg`15!$z}KhYSv0Lu#>jlvj98fY`{lXmtZB^Ur_0lM#kO^PM?Tz9e*E7>5zFdV zGL1|%>scPueR^ylRm}?^PMXoxf(vOKX-AOO(2k1UgqMRPM{OjzOWvecc8#bmmfTaU zOHD#&2caDtl2%7hcho(Gy1At8IO^#2 zv8soYI=)MPbr189fF9gE1?@!e)eoR=jWzFIl63ab`}z1xWYu1 z?U{5UA!t~VxOa_v$plTciCR%m;dKBe@55{qHN#)#z(OEBr{q;Csw@_#j%gE_MF`1zhWBuk&goA73uZwLS`$t)__ zm5~?Nn3EM80tL#nW4G-SXhV#Pm!_6&e8=g4l=6y z%&(*M@8Fy1Kb+dH$nx`-FVKo>`p@7Zegi{nqy7HSh+q6Qw9q>;3XS;r$l|!Lgv;Bw ziAD0I%ok@NmJL`i<|c%(k-1$O4EIRSBftx)ha!@ha;?6^+9CH6#`O^D{w2PC5ko+lXzwNQVY#VCa6pCb?Q)W60q!(fn}t$rKYZWNJ_VWKK3(kI$*pYsX{#79K}7 zXUXUvPHo(<4Z3=Yz3kB?sDHE_oX!oVa|F&iDYD<~qDf?ZkVtJybdRXD)fzyjBC=rCmR^TMe-txBL>mg@Vub~JJQ3D-LL3}M5hklrCY_`d^oY%r^(`&<&myIHb!}1oq zgfV{$CsTKkA5h##a}rH}69rBn4kNyv@lBRVL|xUORnh1F+ZaQf7?~WLjle@Vdqlgn z3@Z){9*L47ZI|k2?1#WXzq5xt zljYBG`NnSMo;HGL^Z@^X!-o1%JffGV*}3B>%|No4lDfOkTqjd=Ex@+WL<;Bs2zO02 zsvH|rS2c9VS4B$=XKFQJg5p-D_lX={s~;p{5&LR`R|OU#k^UI3xS?9*eVtctu$W-+ z6&63n;!m@9nZ*#~Lw8dH5B>qZqDPhB=`NZF^9QNY#^3y0an_nUIya%%wvO+}hdRZx z`1=12TyUt~iZjY!fVG-)&1&8&cttlWs_ujfrh>ZCNL>zfdAOd+UJ>f>gj=|f@us|@ zH|-XoQck!faZSxgowON-H=)eVN_`PwO;f^}bYmURbr?4ZYohj`cL=@CaTIqBtq;3L zr02t^9&F;8 z7%!>@bQfY;7CH^5dTk$4#cOXhR0jr270;oQmUPgJ(WJd>nJPn~R~^HR=1b81=+Ax8hz)gYC+TP?0T~?9!9C2=M$c^u zQ5SAm+rg7mh>#8fe%>|CgTH?ja}G<0jjOw0DKZ%Dac0+wMJg!}{HO!_) z;fdi80O7<>k%tl>nS6g?)bF|cfiEfg6!)-t^rR&nVH^2dznZK%<-dx9S)-9M2}>p_B%(G%cY%Fc4)(9^2Q2t;w7VWQB4dZ5Z4Eu`-veKuhLt(RxR)47=*t{O zl4H7If_2GDi^=+Pu-!&{44Vh}*Afw>`&6rW7>^(z0 z5L2VX*0b^iR*dM(nO#e+aseXm1B?2wYrbjiMD2$!X zop!V1=vb~qXOm7M=U#K$9#M^lw4BzGleflweCe3@_X@=)om>|xV0wrx?g1O-7x)9y zPi()@YBU{iqmJPFTBivm3TSd(ClzR>VcTCC&Xcsi^DHVfTJ1=P|4ZqK?Ia_=Ydi|| zj3Iq^iX@dK#a8K~*CyYe=hfF)e3VTKnzV-7|0rrn6?#PJPkn^V#|TeUb6?egc*!o8zE(cyj z6bL7{cCkyy+d;?(kuRP7^Z(-4b%s4++oBNLvTaAUIKpRR8a;xehY&Y@p@keOy7)aE zmQ@Z`Fa|?)19hJz%!H>G`(v>zq1TZh00{L8-U%(&14W$0wR8M{+O}X&R=@JI*$RrBK0T_=(_M zk8+w|aoTPNrYAELqWraC$Wb<^5hUYqLS7umBzatC{IUg^-f@TB$c&=_6#V@7ihIiL zwe`Xn+^lan?e)|WFl$+wvj)ppFB&UGY!ymEqZ@|@z(GjAZOwM-L@@2!cTyhx%d)N5 z8Zm*nKkBDhj1kOnrmw}pRkG`vOdO-WlAyrk9v;TGi<%onFq_D(M#w2QyG#Y1)nEz-1#MzfnlJ{*LI+fVe_YqK4F6In&#y|m9 zD&l{*+)>CX4~ zyAMF1nRE_UjQ)@~=(Kswc2@mPvxiJD>Q6r87t}u;Uh4SEtXuZI?qUKSh=C`cu;CjR zY3eE_3@u3ZU;X?I2n^R#mEg59D>YAmwTySmO_`$?^ou zMO@HRx+YOOr-}#33SVXbB2f+_XBd+6po{APK(NSiidYTV5<_?T5ydQ&g`}@^)?W6)NO_;uWf7pihgUfF=nnG3Nnz%a@IrJ zBsCRbcI0#c5SwJyr!z&bmqQOKEHw0-Ip;M)$Cm@GZDROXE_X$(5V z7G7}et%f60SXu(GB(Y0Cy0p|qde5DXf+W!SB&puu3WnY#c@(PCTSu}R*1+Uc+rA7R zR|mH$NyGq33j%)z5{C8<)|_OuT~c(!R~#iI<>CC$40^Y%iF z4h!)r7D0J>0hJ`V(zY2BjoGy@mA?k;(^xvnRJ8w7_X?MjTjSJTOPI`|eRZ0#=Fs1- zuzTUoBI0q!&jh~Iss;c594^RGw2$pZj%;Sf+R5!8*M49kLa-QQT~q7Oca7Ik$J9p` zu>|HX(O12jrw96;2^N*zK}>X~h#Xf7uFC$v+AScT32pHV^@F0{4~lMn*qe+z0iB$h zdCo1Y<)E|Ew_O|*)+i~8QI-63ZRALcDlS*w0aj#I)Z?7OHoIr` zu*^Yp|F(@3>R>y8gT0`2j%O=yA~b;im_|w)^4w+ng?7E!bD6Rb1J91$Vdf{*dWeN* zB@Z+V#y0Z%TL#ei}Zl zOlZL&So|?S&M((X7T)e+L7ozsq6_GE<3ef*$>E z5hTJW3jI@Kf_9|gh&zX_39dkvLUmBv=bKbovYML=EYQDjl%2u=d&Gh8x)W=UxXEJffE#ApPM@qTD=)eh-A+8Z|?^h;yUR$1)?a1rNwU=E-4N`;tY7q z1e6^Sd7J=~0^f>O1M}+VuqvEe@amBC>M(B9-(x|=Pcc>jyib&GXhPCX+=-$y{%tnn z7KAg=qXaKxPYAPc5~LPSVSJaw){XHu5{G|-d&L-iCU;Qsj(Ma3;n4l9-LaSV7`j>X zBm2i7ek2W$@V<*wNbxtB{YC=)6{;=GMxXqF;HP51puM9SK62TSyxwcy?sWn>pdfR( zJHj$}kCO;VKSARb{}mAGSFuau_>k|(hNH+~!uROFHw zu6PVxcve$SwAOHIGS~l|fN%o238Sd9xAh2N384y1(}YF6C$Xab4SJ7dg1Bn*fiQ_d z_>YNR1Ir0E4kYTEmOeBF>nMi|haBF+!7)TJegjtpiB;rrRU9CTXLAC_$^KSQ+MPsJ zR%WxjJ9RG;Oe1Ftz1>4UXg33E$=aN~XZqhny92HjJxA+7E^2d-zPEwJY@v2ZTEWiJ zv%uXU7vpWtvH$4Z{Jk8W7Iq5lWAeO+_oEi<(Vf^SNPS6aP4*icb|-g_3<_@fI5Y?R zpE{noOPvnE{#)jc;jm?JboZD$!*NkJD|M^V%K<$qGtPqJTpQN~O>i&7ita&q@0-C1 zwu6qy*&m8#Jt6ZrxqAw40&XAD%bfJ`ZM=QJJ)BxMVnbXxpn7@;F*!MN#5sp8PDn+L zwcyMe1q@g_qsmML$h*P;x69f z(HY7&46n^OaH}XxFr3^_AVr-)=h@R2bvf}9lJU_~0vb#^hGG(oy4Z?!g%1&b&|gS9 zEB(rYINZ}_;+H;rtxa{>r*+uO5YeJZE+AvDKP&8*b3p3{eIyt@aP3w@4vE8YRCi!q z#e5o|UkW-)gus0EuFTtNIrx`j1|RaKQ=L zHZAeg?osAo$P~K-EM|U?-ZivxJD)qA!QzKeL^*im>R}G*aMM$V`0Sstpt%%U;x7EByuZN0W^sVU&!T`| zc^gMTF_AzWWhE^Z*k&8OpwSF1x+c^=K~-#$4b=+a;y=&UVrxZ5LBet@>}fcJdAMTW zE@1@H?{<(b5*8`BxUfB>nqJ@L$Ht>ik3LLwebx z7U@|+o=N(`70gpBo@a5jM_J0D@*=+C7#Vs6)m#8cHo})F$H4W4H)i|4nQ*gZXhQu4 zAu5>oA8-XYi>f~c>@oEuuYb+pRrp%;F{C0+4KsCkR4vi1Mw~75&H&-|)#iUP0b$B_ zL?DA@y42|R0`aQTU?T3-y~mB?i0P2HhY`;W2mU_?d&l1zNCxFd_|b*6#(EFg5krxq zRW?OG^B4&UlUOAXxU5XEe|ii6I$?yPkT}0@KzApWH88r|8 z9yPRlf1bP}_V7ceg~t!NU2!lmD8bJ+`GatLS~v-`-8F#O&;WV<0PzT%73CQP{?EOQ zG|tzJFJ#&epk-nE$CH-STiK%Ub~b8ZKBm*jiv4dTn0d9w967q+c{*1^C3zT!xsV;x zWyX$uN8u-F5I}MeTLLE<`zaUbZlEOO#%bFJohCg+J&OUO6Mvms?R#5tz`A@6Jf z-aO-+yvpA>_%8sb`mZeh8;k$W;wM=A4;KHE#s5OlpNn!oxKG-hsu8Wx$9Rx)jz%hqn=w*!i-3&4WVILC;tsB7%rRga2dMNb%s0#UPr2 z90&X`OV?R$bk2G0b8_}PIEN%d?E>R-{LX^s^}TcVBk>Tb$QMo5D@3*?X|t0&6q3o0k%HCTbD2i~PGUCb&4}1#pH|IzpNZ zT+?};77MY?H{_Q6(-(;o)F`#qPyZ*BPAd4z%iOp`AC!Y(dJ9KoYG`f3=@jQ6%A!Z5 zsQOn}<+liGvC4CEM*pEPz#vF%*D~0I_WQ&eamAqQp0a)w{-Gb4^X*MBMDn% zupUgM1xtxcj26ni+WtaCeiXu6X8b)F$a~GnJ$?4>Y>nrL%;jI;Xu3xTvWc>7p zjb|D`zs;*2ixP{^vG_AAghN+(#i)8XDL?+8Q^eF?X7$%te4T})K7NC(%3#bvqaHP* z6G?LM)L-P)F&3X^;j#FuEPe(>SbPpS0533Ygz+fF;E#?&{Q|Fki3JU=Fbj=Yn`ktI zlvq+?UQt0+|B=Nm3o0(E%z|paDzYFYC`x$sJ1j_IiV#k*JE6h~>#m|WNb_eG7X&>1 z%sF!oIhUq!uwWWT@I9Ev8I_~Bo;Wy#lS}V|!x`p#(`7s1YxHP|s-V>XUH+bl-`X*0N`af^aWIQl`1{@I zr*(fa+X{YS=Db?Rbi)FFJ_sC2tMdOARdT#AEJM@8>0=~GA@@hZP+=bD-q;dY7D0#{ zM?;NRrw{uG{D=e^MW`wXbi)&rcFAv)E!Ufk List[str]: + return ["-r", rev] + + def fetch_new( + self, dest: str, url: HiddenText, rev_options: RevOptions, verbosity: int + ) -> None: + rev_display = rev_options.to_display() + logger.info( + "Checking out %s%s to %s", + url, + rev_display, + display_path(dest), + ) + if verbosity <= 0: + flag = "--quiet" + elif verbosity == 1: + flag = "" + else: + flag = f"-{'v'*verbosity}" + cmd_args = make_command("branch", flag, rev_options.to_args(), url, dest) + self.run_command(cmd_args) + + def switch(self, dest: str, url: HiddenText, rev_options: RevOptions) -> None: + self.run_command(make_command("switch", url), cwd=dest) + + def update(self, dest: str, url: HiddenText, rev_options: RevOptions) -> None: + cmd_args = make_command("pull", "-q", rev_options.to_args()) + self.run_command(cmd_args, cwd=dest) + + @classmethod + def get_url_rev_and_auth(cls, url: str) -> Tuple[str, Optional[str], AuthInfo]: + # hotfix the URL scheme after removing bzr+ from bzr+ssh:// readd it + url, rev, user_pass = super().get_url_rev_and_auth(url) + if url.startswith("ssh://"): + url = "bzr+" + url + return url, rev, user_pass + + @classmethod + def get_remote_url(cls, location: str) -> str: + urls = cls.run_command( + ["info"], show_stdout=False, stdout_only=True, cwd=location + ) + for line in urls.splitlines(): + line = line.strip() + for x in ("checkout of branch: ", "parent branch: "): + if line.startswith(x): + repo = line.split(x)[1] + if cls._is_local_repository(repo): + return path_to_url(repo) + return repo + raise RemoteNotFoundError + + @classmethod + def get_revision(cls, location: str) -> str: + revision = cls.run_command( + ["revno"], + show_stdout=False, + stdout_only=True, + cwd=location, + ) + return revision.splitlines()[-1] + + @classmethod + def is_commit_id_equal(cls, dest: str, name: Optional[str]) -> bool: + """Always assume the versions don't match""" + return False + + +vcs.register(Bazaar) diff --git a/venv/Lib/site-packages/pip/_internal/vcs/git.py b/venv/Lib/site-packages/pip/_internal/vcs/git.py new file mode 100644 index 0000000..8d1d499 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/vcs/git.py @@ -0,0 +1,526 @@ +import logging +import os.path +import pathlib +import re +import urllib.parse +import urllib.request +from typing import List, Optional, Tuple + +from pip._internal.exceptions import BadCommand, InstallationError +from pip._internal.utils.misc import HiddenText, display_path, hide_url +from pip._internal.utils.subprocess import make_command +from pip._internal.vcs.versioncontrol import ( + AuthInfo, + RemoteNotFoundError, + RemoteNotValidError, + RevOptions, + VersionControl, + find_path_to_project_root_from_repo_root, + vcs, +) + +urlsplit = urllib.parse.urlsplit +urlunsplit = urllib.parse.urlunsplit + + +logger = logging.getLogger(__name__) + + +GIT_VERSION_REGEX = re.compile( + r"^git version " # Prefix. + r"(\d+)" # Major. + r"\.(\d+)" # Dot, minor. + r"(?:\.(\d+))?" # Optional dot, patch. + r".*$" # Suffix, including any pre- and post-release segments we don't care about. +) + +HASH_REGEX = re.compile("^[a-fA-F0-9]{40}$") + +# SCP (Secure copy protocol) shorthand. e.g. 'git@example.com:foo/bar.git' +SCP_REGEX = re.compile( + r"""^ + # Optional user, e.g. 'git@' + (\w+@)? + # Server, e.g. 'github.com'. + ([^/:]+): + # The server-side path. e.g. 'user/project.git'. Must start with an + # alphanumeric character so as not to be confusable with a Windows paths + # like 'C:/foo/bar' or 'C:\foo\bar'. + (\w[^:]*) + $""", + re.VERBOSE, +) + + +def looks_like_hash(sha: str) -> bool: + return bool(HASH_REGEX.match(sha)) + + +class Git(VersionControl): + name = "git" + dirname = ".git" + repo_name = "clone" + schemes = ( + "git+http", + "git+https", + "git+ssh", + "git+git", + "git+file", + ) + # Prevent the user's environment variables from interfering with pip: + # https://github.com/pypa/pip/issues/1130 + unset_environ = ("GIT_DIR", "GIT_WORK_TREE") + default_arg_rev = "HEAD" + + @staticmethod + def get_base_rev_args(rev: str) -> List[str]: + return [rev] + + def is_immutable_rev_checkout(self, url: str, dest: str) -> bool: + _, rev_options = self.get_url_rev_options(hide_url(url)) + if not rev_options.rev: + return False + if not self.is_commit_id_equal(dest, rev_options.rev): + # the current commit is different from rev, + # which means rev was something else than a commit hash + return False + # return False in the rare case rev is both a commit hash + # and a tag or a branch; we don't want to cache in that case + # because that branch/tag could point to something else in the future + is_tag_or_branch = bool(self.get_revision_sha(dest, rev_options.rev)[0]) + return not is_tag_or_branch + + def get_git_version(self) -> Tuple[int, ...]: + version = self.run_command( + ["version"], + command_desc="git version", + show_stdout=False, + stdout_only=True, + ) + match = GIT_VERSION_REGEX.match(version) + if not match: + logger.warning("Can't parse git version: %s", version) + return () + return tuple(int(c) for c in match.groups()) + + @classmethod + def get_current_branch(cls, location: str) -> Optional[str]: + """ + Return the current branch, or None if HEAD isn't at a branch + (e.g. detached HEAD). + """ + # git-symbolic-ref exits with empty stdout if "HEAD" is a detached + # HEAD rather than a symbolic ref. In addition, the -q causes the + # command to exit with status code 1 instead of 128 in this case + # and to suppress the message to stderr. + args = ["symbolic-ref", "-q", "HEAD"] + output = cls.run_command( + args, + extra_ok_returncodes=(1,), + show_stdout=False, + stdout_only=True, + cwd=location, + ) + ref = output.strip() + + if ref.startswith("refs/heads/"): + return ref[len("refs/heads/") :] + + return None + + @classmethod + def get_revision_sha(cls, dest: str, rev: str) -> Tuple[Optional[str], bool]: + """ + Return (sha_or_none, is_branch), where sha_or_none is a commit hash + if the revision names a remote branch or tag, otherwise None. + + Args: + dest: the repository directory. + rev: the revision name. + """ + # Pass rev to pre-filter the list. + output = cls.run_command( + ["show-ref", rev], + cwd=dest, + show_stdout=False, + stdout_only=True, + on_returncode="ignore", + ) + refs = {} + # NOTE: We do not use splitlines here since that would split on other + # unicode separators, which can be maliciously used to install a + # different revision. + for line in output.strip().split("\n"): + line = line.rstrip("\r") + if not line: + continue + try: + ref_sha, ref_name = line.split(" ", maxsplit=2) + except ValueError: + # Include the offending line to simplify troubleshooting if + # this error ever occurs. + raise ValueError(f"unexpected show-ref line: {line!r}") + + refs[ref_name] = ref_sha + + branch_ref = f"refs/remotes/origin/{rev}" + tag_ref = f"refs/tags/{rev}" + + sha = refs.get(branch_ref) + if sha is not None: + return (sha, True) + + sha = refs.get(tag_ref) + + return (sha, False) + + @classmethod + def _should_fetch(cls, dest: str, rev: str) -> bool: + """ + Return true if rev is a ref or is a commit that we don't have locally. + + Branches and tags are not considered in this method because they are + assumed to be always available locally (which is a normal outcome of + ``git clone`` and ``git fetch --tags``). + """ + if rev.startswith("refs/"): + # Always fetch remote refs. + return True + + if not looks_like_hash(rev): + # Git fetch would fail with abbreviated commits. + return False + + if cls.has_commit(dest, rev): + # Don't fetch if we have the commit locally. + return False + + return True + + @classmethod + def resolve_revision( + cls, dest: str, url: HiddenText, rev_options: RevOptions + ) -> RevOptions: + """ + Resolve a revision to a new RevOptions object with the SHA1 of the + branch, tag, or ref if found. + + Args: + rev_options: a RevOptions object. + """ + rev = rev_options.arg_rev + # The arg_rev property's implementation for Git ensures that the + # rev return value is always non-None. + assert rev is not None + + sha, is_branch = cls.get_revision_sha(dest, rev) + + if sha is not None: + rev_options = rev_options.make_new(sha) + rev_options.branch_name = rev if is_branch else None + + return rev_options + + # Do not show a warning for the common case of something that has + # the form of a Git commit hash. + if not looks_like_hash(rev): + logger.warning( + "Did not find branch or tag '%s', assuming revision or ref.", + rev, + ) + + if not cls._should_fetch(dest, rev): + return rev_options + + # fetch the requested revision + cls.run_command( + make_command("fetch", "-q", url, rev_options.to_args()), + cwd=dest, + ) + # Change the revision to the SHA of the ref we fetched + sha = cls.get_revision(dest, rev="FETCH_HEAD") + rev_options = rev_options.make_new(sha) + + return rev_options + + @classmethod + def is_commit_id_equal(cls, dest: str, name: Optional[str]) -> bool: + """ + Return whether the current commit hash equals the given name. + + Args: + dest: the repository directory. + name: a string name. + """ + if not name: + # Then avoid an unnecessary subprocess call. + return False + + return cls.get_revision(dest) == name + + def fetch_new( + self, dest: str, url: HiddenText, rev_options: RevOptions, verbosity: int + ) -> None: + rev_display = rev_options.to_display() + logger.info("Cloning %s%s to %s", url, rev_display, display_path(dest)) + if verbosity <= 0: + flags: Tuple[str, ...] = ("--quiet",) + elif verbosity == 1: + flags = () + else: + flags = ("--verbose", "--progress") + if self.get_git_version() >= (2, 17): + # Git added support for partial clone in 2.17 + # https://git-scm.com/docs/partial-clone + # Speeds up cloning by functioning without a complete copy of repository + self.run_command( + make_command( + "clone", + "--filter=blob:none", + *flags, + url, + dest, + ) + ) + else: + self.run_command(make_command("clone", *flags, url, dest)) + + if rev_options.rev: + # Then a specific revision was requested. + rev_options = self.resolve_revision(dest, url, rev_options) + branch_name = getattr(rev_options, "branch_name", None) + logger.debug("Rev options %s, branch_name %s", rev_options, branch_name) + if branch_name is None: + # Only do a checkout if the current commit id doesn't match + # the requested revision. + if not self.is_commit_id_equal(dest, rev_options.rev): + cmd_args = make_command( + "checkout", + "-q", + rev_options.to_args(), + ) + self.run_command(cmd_args, cwd=dest) + elif self.get_current_branch(dest) != branch_name: + # Then a specific branch was requested, and that branch + # is not yet checked out. + track_branch = f"origin/{branch_name}" + cmd_args = [ + "checkout", + "-b", + branch_name, + "--track", + track_branch, + ] + self.run_command(cmd_args, cwd=dest) + else: + sha = self.get_revision(dest) + rev_options = rev_options.make_new(sha) + + logger.info("Resolved %s to commit %s", url, rev_options.rev) + + #: repo may contain submodules + self.update_submodules(dest) + + def switch(self, dest: str, url: HiddenText, rev_options: RevOptions) -> None: + self.run_command( + make_command("config", "remote.origin.url", url), + cwd=dest, + ) + cmd_args = make_command("checkout", "-q", rev_options.to_args()) + self.run_command(cmd_args, cwd=dest) + + self.update_submodules(dest) + + def update(self, dest: str, url: HiddenText, rev_options: RevOptions) -> None: + # First fetch changes from the default remote + if self.get_git_version() >= (1, 9): + # fetch tags in addition to everything else + self.run_command(["fetch", "-q", "--tags"], cwd=dest) + else: + self.run_command(["fetch", "-q"], cwd=dest) + # Then reset to wanted revision (maybe even origin/master) + rev_options = self.resolve_revision(dest, url, rev_options) + cmd_args = make_command("reset", "--hard", "-q", rev_options.to_args()) + self.run_command(cmd_args, cwd=dest) + #: update submodules + self.update_submodules(dest) + + @classmethod + def get_remote_url(cls, location: str) -> str: + """ + Return URL of the first remote encountered. + + Raises RemoteNotFoundError if the repository does not have a remote + url configured. + """ + # We need to pass 1 for extra_ok_returncodes since the command + # exits with return code 1 if there are no matching lines. + stdout = cls.run_command( + ["config", "--get-regexp", r"remote\..*\.url"], + extra_ok_returncodes=(1,), + show_stdout=False, + stdout_only=True, + cwd=location, + ) + remotes = stdout.splitlines() + try: + found_remote = remotes[0] + except IndexError: + raise RemoteNotFoundError + + for remote in remotes: + if remote.startswith("remote.origin.url "): + found_remote = remote + break + url = found_remote.split(" ")[1] + return cls._git_remote_to_pip_url(url.strip()) + + @staticmethod + def _git_remote_to_pip_url(url: str) -> str: + """ + Convert a remote url from what git uses to what pip accepts. + + There are 3 legal forms **url** may take: + + 1. A fully qualified url: ssh://git@example.com/foo/bar.git + 2. A local project.git folder: /path/to/bare/repository.git + 3. SCP shorthand for form 1: git@example.com:foo/bar.git + + Form 1 is output as-is. Form 2 must be converted to URI and form 3 must + be converted to form 1. + + See the corresponding test test_git_remote_url_to_pip() for examples of + sample inputs/outputs. + """ + if re.match(r"\w+://", url): + # This is already valid. Pass it though as-is. + return url + if os.path.exists(url): + # A local bare remote (git clone --mirror). + # Needs a file:// prefix. + return pathlib.PurePath(url).as_uri() + scp_match = SCP_REGEX.match(url) + if scp_match: + # Add an ssh:// prefix and replace the ':' with a '/'. + return scp_match.expand(r"ssh://\1\2/\3") + # Otherwise, bail out. + raise RemoteNotValidError(url) + + @classmethod + def has_commit(cls, location: str, rev: str) -> bool: + """ + Check if rev is a commit that is available in the local repository. + """ + try: + cls.run_command( + ["rev-parse", "-q", "--verify", "sha^" + rev], + cwd=location, + log_failed_cmd=False, + ) + except InstallationError: + return False + else: + return True + + @classmethod + def get_revision(cls, location: str, rev: Optional[str] = None) -> str: + if rev is None: + rev = "HEAD" + current_rev = cls.run_command( + ["rev-parse", rev], + show_stdout=False, + stdout_only=True, + cwd=location, + ) + return current_rev.strip() + + @classmethod + def get_subdirectory(cls, location: str) -> Optional[str]: + """ + Return the path to Python project root, relative to the repo root. + Return None if the project root is in the repo root. + """ + # find the repo root + git_dir = cls.run_command( + ["rev-parse", "--git-dir"], + show_stdout=False, + stdout_only=True, + cwd=location, + ).strip() + if not os.path.isabs(git_dir): + git_dir = os.path.join(location, git_dir) + repo_root = os.path.abspath(os.path.join(git_dir, "..")) + return find_path_to_project_root_from_repo_root(location, repo_root) + + @classmethod + def get_url_rev_and_auth(cls, url: str) -> Tuple[str, Optional[str], AuthInfo]: + """ + Prefixes stub URLs like 'user@hostname:user/repo.git' with 'ssh://'. + That's required because although they use SSH they sometimes don't + work with a ssh:// scheme (e.g. GitHub). But we need a scheme for + parsing. Hence we remove it again afterwards and return it as a stub. + """ + # Works around an apparent Git bug + # (see https://article.gmane.org/gmane.comp.version-control.git/146500) + scheme, netloc, path, query, fragment = urlsplit(url) + if scheme.endswith("file"): + initial_slashes = path[: -len(path.lstrip("/"))] + newpath = initial_slashes + urllib.request.url2pathname(path).replace( + "\\", "/" + ).lstrip("/") + after_plus = scheme.find("+") + 1 + url = scheme[:after_plus] + urlunsplit( + (scheme[after_plus:], netloc, newpath, query, fragment), + ) + + if "://" not in url: + assert "file:" not in url + url = url.replace("git+", "git+ssh://") + url, rev, user_pass = super().get_url_rev_and_auth(url) + url = url.replace("ssh://", "") + else: + url, rev, user_pass = super().get_url_rev_and_auth(url) + + return url, rev, user_pass + + @classmethod + def update_submodules(cls, location: str) -> None: + if not os.path.exists(os.path.join(location, ".gitmodules")): + return + cls.run_command( + ["submodule", "update", "--init", "--recursive", "-q"], + cwd=location, + ) + + @classmethod + def get_repository_root(cls, location: str) -> Optional[str]: + loc = super().get_repository_root(location) + if loc: + return loc + try: + r = cls.run_command( + ["rev-parse", "--show-toplevel"], + cwd=location, + show_stdout=False, + stdout_only=True, + on_returncode="raise", + log_failed_cmd=False, + ) + except BadCommand: + logger.debug( + "could not determine if %s is under git control " + "because git is not available", + location, + ) + return None + except InstallationError: + return None + return os.path.normpath(r.rstrip("\r\n")) + + @staticmethod + def should_add_vcs_url_prefix(repo_url: str) -> bool: + """In either https or ssh form, requirements must be prefixed with git+.""" + return True + + +vcs.register(Git) diff --git a/venv/Lib/site-packages/pip/_internal/vcs/mercurial.py b/venv/Lib/site-packages/pip/_internal/vcs/mercurial.py new file mode 100644 index 0000000..2a005e0 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/vcs/mercurial.py @@ -0,0 +1,163 @@ +import configparser +import logging +import os +from typing import List, Optional, Tuple + +from pip._internal.exceptions import BadCommand, InstallationError +from pip._internal.utils.misc import HiddenText, display_path +from pip._internal.utils.subprocess import make_command +from pip._internal.utils.urls import path_to_url +from pip._internal.vcs.versioncontrol import ( + RevOptions, + VersionControl, + find_path_to_project_root_from_repo_root, + vcs, +) + +logger = logging.getLogger(__name__) + + +class Mercurial(VersionControl): + name = "hg" + dirname = ".hg" + repo_name = "clone" + schemes = ( + "hg+file", + "hg+http", + "hg+https", + "hg+ssh", + "hg+static-http", + ) + + @staticmethod + def get_base_rev_args(rev: str) -> List[str]: + return [rev] + + def fetch_new( + self, dest: str, url: HiddenText, rev_options: RevOptions, verbosity: int + ) -> None: + rev_display = rev_options.to_display() + logger.info( + "Cloning hg %s%s to %s", + url, + rev_display, + display_path(dest), + ) + if verbosity <= 0: + flags: Tuple[str, ...] = ("--quiet",) + elif verbosity == 1: + flags = () + elif verbosity == 2: + flags = ("--verbose",) + else: + flags = ("--verbose", "--debug") + self.run_command(make_command("clone", "--noupdate", *flags, url, dest)) + self.run_command( + make_command("update", *flags, rev_options.to_args()), + cwd=dest, + ) + + def switch(self, dest: str, url: HiddenText, rev_options: RevOptions) -> None: + repo_config = os.path.join(dest, self.dirname, "hgrc") + config = configparser.RawConfigParser() + try: + config.read(repo_config) + config.set("paths", "default", url.secret) + with open(repo_config, "w") as config_file: + config.write(config_file) + except (OSError, configparser.NoSectionError) as exc: + logger.warning("Could not switch Mercurial repository to %s: %s", url, exc) + else: + cmd_args = make_command("update", "-q", rev_options.to_args()) + self.run_command(cmd_args, cwd=dest) + + def update(self, dest: str, url: HiddenText, rev_options: RevOptions) -> None: + self.run_command(["pull", "-q"], cwd=dest) + cmd_args = make_command("update", "-q", rev_options.to_args()) + self.run_command(cmd_args, cwd=dest) + + @classmethod + def get_remote_url(cls, location: str) -> str: + url = cls.run_command( + ["showconfig", "paths.default"], + show_stdout=False, + stdout_only=True, + cwd=location, + ).strip() + if cls._is_local_repository(url): + url = path_to_url(url) + return url.strip() + + @classmethod + def get_revision(cls, location: str) -> str: + """ + Return the repository-local changeset revision number, as an integer. + """ + current_revision = cls.run_command( + ["parents", "--template={rev}"], + show_stdout=False, + stdout_only=True, + cwd=location, + ).strip() + return current_revision + + @classmethod + def get_requirement_revision(cls, location: str) -> str: + """ + Return the changeset identification hash, as a 40-character + hexadecimal string + """ + current_rev_hash = cls.run_command( + ["parents", "--template={node}"], + show_stdout=False, + stdout_only=True, + cwd=location, + ).strip() + return current_rev_hash + + @classmethod + def is_commit_id_equal(cls, dest: str, name: Optional[str]) -> bool: + """Always assume the versions don't match""" + return False + + @classmethod + def get_subdirectory(cls, location: str) -> Optional[str]: + """ + Return the path to Python project root, relative to the repo root. + Return None if the project root is in the repo root. + """ + # find the repo root + repo_root = cls.run_command( + ["root"], show_stdout=False, stdout_only=True, cwd=location + ).strip() + if not os.path.isabs(repo_root): + repo_root = os.path.abspath(os.path.join(location, repo_root)) + return find_path_to_project_root_from_repo_root(location, repo_root) + + @classmethod + def get_repository_root(cls, location: str) -> Optional[str]: + loc = super().get_repository_root(location) + if loc: + return loc + try: + r = cls.run_command( + ["root"], + cwd=location, + show_stdout=False, + stdout_only=True, + on_returncode="raise", + log_failed_cmd=False, + ) + except BadCommand: + logger.debug( + "could not determine if %s is under hg control " + "because hg is not available", + location, + ) + return None + except InstallationError: + return None + return os.path.normpath(r.rstrip("\r\n")) + + +vcs.register(Mercurial) diff --git a/venv/Lib/site-packages/pip/_internal/vcs/subversion.py b/venv/Lib/site-packages/pip/_internal/vcs/subversion.py new file mode 100644 index 0000000..89c8754 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/vcs/subversion.py @@ -0,0 +1,324 @@ +import logging +import os +import re +from typing import List, Optional, Tuple + +from pip._internal.utils.misc import ( + HiddenText, + display_path, + is_console_interactive, + is_installable_dir, + split_auth_from_netloc, +) +from pip._internal.utils.subprocess import CommandArgs, make_command +from pip._internal.vcs.versioncontrol import ( + AuthInfo, + RemoteNotFoundError, + RevOptions, + VersionControl, + vcs, +) + +logger = logging.getLogger(__name__) + +_svn_xml_url_re = re.compile('url="([^"]+)"') +_svn_rev_re = re.compile(r'committed-rev="(\d+)"') +_svn_info_xml_rev_re = re.compile(r'\s*revision="(\d+)"') +_svn_info_xml_url_re = re.compile(r"(.*)") + + +class Subversion(VersionControl): + name = "svn" + dirname = ".svn" + repo_name = "checkout" + schemes = ("svn+ssh", "svn+http", "svn+https", "svn+svn", "svn+file") + + @classmethod + def should_add_vcs_url_prefix(cls, remote_url: str) -> bool: + return True + + @staticmethod + def get_base_rev_args(rev: str) -> List[str]: + return ["-r", rev] + + @classmethod + def get_revision(cls, location: str) -> str: + """ + Return the maximum revision for all files under a given location + """ + # Note: taken from setuptools.command.egg_info + revision = 0 + + for base, dirs, _ in os.walk(location): + if cls.dirname not in dirs: + dirs[:] = [] + continue # no sense walking uncontrolled subdirs + dirs.remove(cls.dirname) + entries_fn = os.path.join(base, cls.dirname, "entries") + if not os.path.exists(entries_fn): + # FIXME: should we warn? + continue + + dirurl, localrev = cls._get_svn_url_rev(base) + + if base == location: + assert dirurl is not None + base = dirurl + "/" # save the root url + elif not dirurl or not dirurl.startswith(base): + dirs[:] = [] + continue # not part of the same svn tree, skip it + revision = max(revision, localrev) + return str(revision) + + @classmethod + def get_netloc_and_auth( + cls, netloc: str, scheme: str + ) -> Tuple[str, Tuple[Optional[str], Optional[str]]]: + """ + This override allows the auth information to be passed to svn via the + --username and --password options instead of via the URL. + """ + if scheme == "ssh": + # The --username and --password options can't be used for + # svn+ssh URLs, so keep the auth information in the URL. + return super().get_netloc_and_auth(netloc, scheme) + + return split_auth_from_netloc(netloc) + + @classmethod + def get_url_rev_and_auth(cls, url: str) -> Tuple[str, Optional[str], AuthInfo]: + # hotfix the URL scheme after removing svn+ from svn+ssh:// readd it + url, rev, user_pass = super().get_url_rev_and_auth(url) + if url.startswith("ssh://"): + url = "svn+" + url + return url, rev, user_pass + + @staticmethod + def make_rev_args( + username: Optional[str], password: Optional[HiddenText] + ) -> CommandArgs: + extra_args: CommandArgs = [] + if username: + extra_args += ["--username", username] + if password: + extra_args += ["--password", password] + + return extra_args + + @classmethod + def get_remote_url(cls, location: str) -> str: + # In cases where the source is in a subdirectory, we have to look up in + # the location until we find a valid project root. + orig_location = location + while not is_installable_dir(location): + last_location = location + location = os.path.dirname(location) + if location == last_location: + # We've traversed up to the root of the filesystem without + # finding a Python project. + logger.warning( + "Could not find Python project for directory %s (tried all " + "parent directories)", + orig_location, + ) + raise RemoteNotFoundError + + url, _rev = cls._get_svn_url_rev(location) + if url is None: + raise RemoteNotFoundError + + return url + + @classmethod + def _get_svn_url_rev(cls, location: str) -> Tuple[Optional[str], int]: + from pip._internal.exceptions import InstallationError + + entries_path = os.path.join(location, cls.dirname, "entries") + if os.path.exists(entries_path): + with open(entries_path) as f: + data = f.read() + else: # subversion >= 1.7 does not have the 'entries' file + data = "" + + url = None + if data.startswith("8") or data.startswith("9") or data.startswith("10"): + entries = list(map(str.splitlines, data.split("\n\x0c\n"))) + del entries[0][0] # get rid of the '8' + url = entries[0][3] + revs = [int(d[9]) for d in entries if len(d) > 9 and d[9]] + [0] + elif data.startswith("= 1.7 + # Note that using get_remote_call_options is not necessary here + # because `svn info` is being run against a local directory. + # We don't need to worry about making sure interactive mode + # is being used to prompt for passwords, because passwords + # are only potentially needed for remote server requests. + xml = cls.run_command( + ["info", "--xml", location], + show_stdout=False, + stdout_only=True, + ) + match = _svn_info_xml_url_re.search(xml) + assert match is not None + url = match.group(1) + revs = [int(m.group(1)) for m in _svn_info_xml_rev_re.finditer(xml)] + except InstallationError: + url, revs = None, [] + + if revs: + rev = max(revs) + else: + rev = 0 + + return url, rev + + @classmethod + def is_commit_id_equal(cls, dest: str, name: Optional[str]) -> bool: + """Always assume the versions don't match""" + return False + + def __init__(self, use_interactive: bool = None) -> None: + if use_interactive is None: + use_interactive = is_console_interactive() + self.use_interactive = use_interactive + + # This member is used to cache the fetched version of the current + # ``svn`` client. + # Special value definitions: + # None: Not evaluated yet. + # Empty tuple: Could not parse version. + self._vcs_version: Optional[Tuple[int, ...]] = None + + super().__init__() + + def call_vcs_version(self) -> Tuple[int, ...]: + """Query the version of the currently installed Subversion client. + + :return: A tuple containing the parts of the version information or + ``()`` if the version returned from ``svn`` could not be parsed. + :raises: BadCommand: If ``svn`` is not installed. + """ + # Example versions: + # svn, version 1.10.3 (r1842928) + # compiled Feb 25 2019, 14:20:39 on x86_64-apple-darwin17.0.0 + # svn, version 1.7.14 (r1542130) + # compiled Mar 28 2018, 08:49:13 on x86_64-pc-linux-gnu + # svn, version 1.12.0-SlikSvn (SlikSvn/1.12.0) + # compiled May 28 2019, 13:44:56 on x86_64-microsoft-windows6.2 + version_prefix = "svn, version " + version = self.run_command(["--version"], show_stdout=False, stdout_only=True) + if not version.startswith(version_prefix): + return () + + version = version[len(version_prefix) :].split()[0] + version_list = version.partition("-")[0].split(".") + try: + parsed_version = tuple(map(int, version_list)) + except ValueError: + return () + + return parsed_version + + def get_vcs_version(self) -> Tuple[int, ...]: + """Return the version of the currently installed Subversion client. + + If the version of the Subversion client has already been queried, + a cached value will be used. + + :return: A tuple containing the parts of the version information or + ``()`` if the version returned from ``svn`` could not be parsed. + :raises: BadCommand: If ``svn`` is not installed. + """ + if self._vcs_version is not None: + # Use cached version, if available. + # If parsing the version failed previously (empty tuple), + # do not attempt to parse it again. + return self._vcs_version + + vcs_version = self.call_vcs_version() + self._vcs_version = vcs_version + return vcs_version + + def get_remote_call_options(self) -> CommandArgs: + """Return options to be used on calls to Subversion that contact the server. + + These options are applicable for the following ``svn`` subcommands used + in this class. + + - checkout + - switch + - update + + :return: A list of command line arguments to pass to ``svn``. + """ + if not self.use_interactive: + # --non-interactive switch is available since Subversion 0.14.4. + # Subversion < 1.8 runs in interactive mode by default. + return ["--non-interactive"] + + svn_version = self.get_vcs_version() + # By default, Subversion >= 1.8 runs in non-interactive mode if + # stdin is not a TTY. Since that is how pip invokes SVN, in + # call_subprocess(), pip must pass --force-interactive to ensure + # the user can be prompted for a password, if required. + # SVN added the --force-interactive option in SVN 1.8. Since + # e.g. RHEL/CentOS 7, which is supported until 2024, ships with + # SVN 1.7, pip should continue to support SVN 1.7. Therefore, pip + # can't safely add the option if the SVN version is < 1.8 (or unknown). + if svn_version >= (1, 8): + return ["--force-interactive"] + + return [] + + def fetch_new( + self, dest: str, url: HiddenText, rev_options: RevOptions, verbosity: int + ) -> None: + rev_display = rev_options.to_display() + logger.info( + "Checking out %s%s to %s", + url, + rev_display, + display_path(dest), + ) + if verbosity <= 0: + flag = "--quiet" + else: + flag = "" + cmd_args = make_command( + "checkout", + flag, + self.get_remote_call_options(), + rev_options.to_args(), + url, + dest, + ) + self.run_command(cmd_args) + + def switch(self, dest: str, url: HiddenText, rev_options: RevOptions) -> None: + cmd_args = make_command( + "switch", + self.get_remote_call_options(), + rev_options.to_args(), + url, + dest, + ) + self.run_command(cmd_args) + + def update(self, dest: str, url: HiddenText, rev_options: RevOptions) -> None: + cmd_args = make_command( + "update", + self.get_remote_call_options(), + rev_options.to_args(), + dest, + ) + self.run_command(cmd_args) + + +vcs.register(Subversion) diff --git a/venv/Lib/site-packages/pip/_internal/vcs/versioncontrol.py b/venv/Lib/site-packages/pip/_internal/vcs/versioncontrol.py new file mode 100644 index 0000000..02bbf68 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/vcs/versioncontrol.py @@ -0,0 +1,705 @@ +"""Handles all VCS (version control) support""" + +import logging +import os +import shutil +import sys +import urllib.parse +from typing import ( + TYPE_CHECKING, + Any, + Dict, + Iterable, + Iterator, + List, + Mapping, + Optional, + Tuple, + Type, + Union, +) + +from pip._internal.cli.spinners import SpinnerInterface +from pip._internal.exceptions import BadCommand, InstallationError +from pip._internal.utils.misc import ( + HiddenText, + ask_path_exists, + backup_dir, + display_path, + hide_url, + hide_value, + is_installable_dir, + rmtree, +) +from pip._internal.utils.subprocess import ( + CommandArgs, + call_subprocess, + format_command_args, + make_command, +) +from pip._internal.utils.urls import get_url_scheme + +if TYPE_CHECKING: + # Literal was introduced in Python 3.8. + # + # TODO: Remove `if TYPE_CHECKING` when dropping support for Python 3.7. + from typing import Literal + + +__all__ = ["vcs"] + + +logger = logging.getLogger(__name__) + +AuthInfo = Tuple[Optional[str], Optional[str]] + + +def is_url(name: str) -> bool: + """ + Return true if the name looks like a URL. + """ + scheme = get_url_scheme(name) + if scheme is None: + return False + return scheme in ["http", "https", "file", "ftp"] + vcs.all_schemes + + +def make_vcs_requirement_url( + repo_url: str, rev: str, project_name: str, subdir: Optional[str] = None +) -> str: + """ + Return the URL for a VCS requirement. + + Args: + repo_url: the remote VCS url, with any needed VCS prefix (e.g. "git+"). + project_name: the (unescaped) project name. + """ + egg_project_name = project_name.replace("-", "_") + req = f"{repo_url}@{rev}#egg={egg_project_name}" + if subdir: + req += f"&subdirectory={subdir}" + + return req + + +def find_path_to_project_root_from_repo_root( + location: str, repo_root: str +) -> Optional[str]: + """ + Find the the Python project's root by searching up the filesystem from + `location`. Return the path to project root relative to `repo_root`. + Return None if the project root is `repo_root`, or cannot be found. + """ + # find project root. + orig_location = location + while not is_installable_dir(location): + last_location = location + location = os.path.dirname(location) + if location == last_location: + # We've traversed up to the root of the filesystem without + # finding a Python project. + logger.warning( + "Could not find a Python project for directory %s (tried all " + "parent directories)", + orig_location, + ) + return None + + if os.path.samefile(repo_root, location): + return None + + return os.path.relpath(location, repo_root) + + +class RemoteNotFoundError(Exception): + pass + + +class RemoteNotValidError(Exception): + def __init__(self, url: str): + super().__init__(url) + self.url = url + + +class RevOptions: + + """ + Encapsulates a VCS-specific revision to install, along with any VCS + install options. + + Instances of this class should be treated as if immutable. + """ + + def __init__( + self, + vc_class: Type["VersionControl"], + rev: Optional[str] = None, + extra_args: Optional[CommandArgs] = None, + ) -> None: + """ + Args: + vc_class: a VersionControl subclass. + rev: the name of the revision to install. + extra_args: a list of extra options. + """ + if extra_args is None: + extra_args = [] + + self.extra_args = extra_args + self.rev = rev + self.vc_class = vc_class + self.branch_name: Optional[str] = None + + def __repr__(self) -> str: + return f"" + + @property + def arg_rev(self) -> Optional[str]: + if self.rev is None: + return self.vc_class.default_arg_rev + + return self.rev + + def to_args(self) -> CommandArgs: + """ + Return the VCS-specific command arguments. + """ + args: CommandArgs = [] + rev = self.arg_rev + if rev is not None: + args += self.vc_class.get_base_rev_args(rev) + args += self.extra_args + + return args + + def to_display(self) -> str: + if not self.rev: + return "" + + return f" (to revision {self.rev})" + + def make_new(self, rev: str) -> "RevOptions": + """ + Make a copy of the current instance, but with a new rev. + + Args: + rev: the name of the revision for the new object. + """ + return self.vc_class.make_rev_options(rev, extra_args=self.extra_args) + + +class VcsSupport: + _registry: Dict[str, "VersionControl"] = {} + schemes = ["ssh", "git", "hg", "bzr", "sftp", "svn"] + + def __init__(self) -> None: + # Register more schemes with urlparse for various version control + # systems + urllib.parse.uses_netloc.extend(self.schemes) + super().__init__() + + def __iter__(self) -> Iterator[str]: + return self._registry.__iter__() + + @property + def backends(self) -> List["VersionControl"]: + return list(self._registry.values()) + + @property + def dirnames(self) -> List[str]: + return [backend.dirname for backend in self.backends] + + @property + def all_schemes(self) -> List[str]: + schemes: List[str] = [] + for backend in self.backends: + schemes.extend(backend.schemes) + return schemes + + def register(self, cls: Type["VersionControl"]) -> None: + if not hasattr(cls, "name"): + logger.warning("Cannot register VCS %s", cls.__name__) + return + if cls.name not in self._registry: + self._registry[cls.name] = cls() + logger.debug("Registered VCS backend: %s", cls.name) + + def unregister(self, name: str) -> None: + if name in self._registry: + del self._registry[name] + + def get_backend_for_dir(self, location: str) -> Optional["VersionControl"]: + """ + Return a VersionControl object if a repository of that type is found + at the given directory. + """ + vcs_backends = {} + for vcs_backend in self._registry.values(): + repo_path = vcs_backend.get_repository_root(location) + if not repo_path: + continue + logger.debug("Determine that %s uses VCS: %s", location, vcs_backend.name) + vcs_backends[repo_path] = vcs_backend + + if not vcs_backends: + return None + + # Choose the VCS in the inner-most directory. Since all repository + # roots found here would be either `location` or one of its + # parents, the longest path should have the most path components, + # i.e. the backend representing the inner-most repository. + inner_most_repo_path = max(vcs_backends, key=len) + return vcs_backends[inner_most_repo_path] + + def get_backend_for_scheme(self, scheme: str) -> Optional["VersionControl"]: + """ + Return a VersionControl object or None. + """ + for vcs_backend in self._registry.values(): + if scheme in vcs_backend.schemes: + return vcs_backend + return None + + def get_backend(self, name: str) -> Optional["VersionControl"]: + """ + Return a VersionControl object or None. + """ + name = name.lower() + return self._registry.get(name) + + +vcs = VcsSupport() + + +class VersionControl: + name = "" + dirname = "" + repo_name = "" + # List of supported schemes for this Version Control + schemes: Tuple[str, ...] = () + # Iterable of environment variable names to pass to call_subprocess(). + unset_environ: Tuple[str, ...] = () + default_arg_rev: Optional[str] = None + + @classmethod + def should_add_vcs_url_prefix(cls, remote_url: str) -> bool: + """ + Return whether the vcs prefix (e.g. "git+") should be added to a + repository's remote url when used in a requirement. + """ + return not remote_url.lower().startswith(f"{cls.name}:") + + @classmethod + def get_subdirectory(cls, location: str) -> Optional[str]: + """ + Return the path to Python project root, relative to the repo root. + Return None if the project root is in the repo root. + """ + return None + + @classmethod + def get_requirement_revision(cls, repo_dir: str) -> str: + """ + Return the revision string that should be used in a requirement. + """ + return cls.get_revision(repo_dir) + + @classmethod + def get_src_requirement(cls, repo_dir: str, project_name: str) -> str: + """ + Return the requirement string to use to redownload the files + currently at the given repository directory. + + Args: + project_name: the (unescaped) project name. + + The return value has a form similar to the following: + + {repository_url}@{revision}#egg={project_name} + """ + repo_url = cls.get_remote_url(repo_dir) + + if cls.should_add_vcs_url_prefix(repo_url): + repo_url = f"{cls.name}+{repo_url}" + + revision = cls.get_requirement_revision(repo_dir) + subdir = cls.get_subdirectory(repo_dir) + req = make_vcs_requirement_url(repo_url, revision, project_name, subdir=subdir) + + return req + + @staticmethod + def get_base_rev_args(rev: str) -> List[str]: + """ + Return the base revision arguments for a vcs command. + + Args: + rev: the name of a revision to install. Cannot be None. + """ + raise NotImplementedError + + def is_immutable_rev_checkout(self, url: str, dest: str) -> bool: + """ + Return true if the commit hash checked out at dest matches + the revision in url. + + Always return False, if the VCS does not support immutable commit + hashes. + + This method does not check if there are local uncommitted changes + in dest after checkout, as pip currently has no use case for that. + """ + return False + + @classmethod + def make_rev_options( + cls, rev: Optional[str] = None, extra_args: Optional[CommandArgs] = None + ) -> RevOptions: + """ + Return a RevOptions object. + + Args: + rev: the name of a revision to install. + extra_args: a list of extra options. + """ + return RevOptions(cls, rev, extra_args=extra_args) + + @classmethod + def _is_local_repository(cls, repo: str) -> bool: + """ + posix absolute paths start with os.path.sep, + win32 ones start with drive (like c:\\folder) + """ + drive, tail = os.path.splitdrive(repo) + return repo.startswith(os.path.sep) or bool(drive) + + @classmethod + def get_netloc_and_auth( + cls, netloc: str, scheme: str + ) -> Tuple[str, Tuple[Optional[str], Optional[str]]]: + """ + Parse the repository URL's netloc, and return the new netloc to use + along with auth information. + + Args: + netloc: the original repository URL netloc. + scheme: the repository URL's scheme without the vcs prefix. + + This is mainly for the Subversion class to override, so that auth + information can be provided via the --username and --password options + instead of through the URL. For other subclasses like Git without + such an option, auth information must stay in the URL. + + Returns: (netloc, (username, password)). + """ + return netloc, (None, None) + + @classmethod + def get_url_rev_and_auth(cls, url: str) -> Tuple[str, Optional[str], AuthInfo]: + """ + Parse the repository URL to use, and return the URL, revision, + and auth info to use. + + Returns: (url, rev, (username, password)). + """ + scheme, netloc, path, query, frag = urllib.parse.urlsplit(url) + if "+" not in scheme: + raise ValueError( + "Sorry, {!r} is a malformed VCS url. " + "The format is +://, " + "e.g. svn+http://myrepo/svn/MyApp#egg=MyApp".format(url) + ) + # Remove the vcs prefix. + scheme = scheme.split("+", 1)[1] + netloc, user_pass = cls.get_netloc_and_auth(netloc, scheme) + rev = None + if "@" in path: + path, rev = path.rsplit("@", 1) + if not rev: + raise InstallationError( + "The URL {!r} has an empty revision (after @) " + "which is not supported. Include a revision after @ " + "or remove @ from the URL.".format(url) + ) + url = urllib.parse.urlunsplit((scheme, netloc, path, query, "")) + return url, rev, user_pass + + @staticmethod + def make_rev_args( + username: Optional[str], password: Optional[HiddenText] + ) -> CommandArgs: + """ + Return the RevOptions "extra arguments" to use in obtain(). + """ + return [] + + def get_url_rev_options(self, url: HiddenText) -> Tuple[HiddenText, RevOptions]: + """ + Return the URL and RevOptions object to use in obtain(), + as a tuple (url, rev_options). + """ + secret_url, rev, user_pass = self.get_url_rev_and_auth(url.secret) + username, secret_password = user_pass + password: Optional[HiddenText] = None + if secret_password is not None: + password = hide_value(secret_password) + extra_args = self.make_rev_args(username, password) + rev_options = self.make_rev_options(rev, extra_args=extra_args) + + return hide_url(secret_url), rev_options + + @staticmethod + def normalize_url(url: str) -> str: + """ + Normalize a URL for comparison by unquoting it and removing any + trailing slash. + """ + return urllib.parse.unquote(url).rstrip("/") + + @classmethod + def compare_urls(cls, url1: str, url2: str) -> bool: + """ + Compare two repo URLs for identity, ignoring incidental differences. + """ + return cls.normalize_url(url1) == cls.normalize_url(url2) + + def fetch_new( + self, dest: str, url: HiddenText, rev_options: RevOptions, verbosity: int + ) -> None: + """ + Fetch a revision from a repository, in the case that this is the + first fetch from the repository. + + Args: + dest: the directory to fetch the repository to. + rev_options: a RevOptions object. + verbosity: verbosity level. + """ + raise NotImplementedError + + def switch(self, dest: str, url: HiddenText, rev_options: RevOptions) -> None: + """ + Switch the repo at ``dest`` to point to ``URL``. + + Args: + rev_options: a RevOptions object. + """ + raise NotImplementedError + + def update(self, dest: str, url: HiddenText, rev_options: RevOptions) -> None: + """ + Update an already-existing repo to the given ``rev_options``. + + Args: + rev_options: a RevOptions object. + """ + raise NotImplementedError + + @classmethod + def is_commit_id_equal(cls, dest: str, name: Optional[str]) -> bool: + """ + Return whether the id of the current commit equals the given name. + + Args: + dest: the repository directory. + name: a string name. + """ + raise NotImplementedError + + def obtain(self, dest: str, url: HiddenText, verbosity: int) -> None: + """ + Install or update in editable mode the package represented by this + VersionControl object. + + :param dest: the repository directory in which to install or update. + :param url: the repository URL starting with a vcs prefix. + :param verbosity: verbosity level. + """ + url, rev_options = self.get_url_rev_options(url) + + if not os.path.exists(dest): + self.fetch_new(dest, url, rev_options, verbosity=verbosity) + return + + rev_display = rev_options.to_display() + if self.is_repository_directory(dest): + existing_url = self.get_remote_url(dest) + if self.compare_urls(existing_url, url.secret): + logger.debug( + "%s in %s exists, and has correct URL (%s)", + self.repo_name.title(), + display_path(dest), + url, + ) + if not self.is_commit_id_equal(dest, rev_options.rev): + logger.info( + "Updating %s %s%s", + display_path(dest), + self.repo_name, + rev_display, + ) + self.update(dest, url, rev_options) + else: + logger.info("Skipping because already up-to-date.") + return + + logger.warning( + "%s %s in %s exists with URL %s", + self.name, + self.repo_name, + display_path(dest), + existing_url, + ) + prompt = ("(s)witch, (i)gnore, (w)ipe, (b)ackup ", ("s", "i", "w", "b")) + else: + logger.warning( + "Directory %s already exists, and is not a %s %s.", + dest, + self.name, + self.repo_name, + ) + # https://github.com/python/mypy/issues/1174 + prompt = ("(i)gnore, (w)ipe, (b)ackup ", ("i", "w", "b")) # type: ignore + + logger.warning( + "The plan is to install the %s repository %s", + self.name, + url, + ) + response = ask_path_exists("What to do? {}".format(prompt[0]), prompt[1]) + + if response == "a": + sys.exit(-1) + + if response == "w": + logger.warning("Deleting %s", display_path(dest)) + rmtree(dest) + self.fetch_new(dest, url, rev_options, verbosity=verbosity) + return + + if response == "b": + dest_dir = backup_dir(dest) + logger.warning("Backing up %s to %s", display_path(dest), dest_dir) + shutil.move(dest, dest_dir) + self.fetch_new(dest, url, rev_options, verbosity=verbosity) + return + + # Do nothing if the response is "i". + if response == "s": + logger.info( + "Switching %s %s to %s%s", + self.repo_name, + display_path(dest), + url, + rev_display, + ) + self.switch(dest, url, rev_options) + + def unpack(self, location: str, url: HiddenText, verbosity: int) -> None: + """ + Clean up current location and download the url repository + (and vcs infos) into location + + :param url: the repository URL starting with a vcs prefix. + :param verbosity: verbosity level. + """ + if os.path.exists(location): + rmtree(location) + self.obtain(location, url=url, verbosity=verbosity) + + @classmethod + def get_remote_url(cls, location: str) -> str: + """ + Return the url used at location + + Raises RemoteNotFoundError if the repository does not have a remote + url configured. + """ + raise NotImplementedError + + @classmethod + def get_revision(cls, location: str) -> str: + """ + Return the current commit id of the files at the given location. + """ + raise NotImplementedError + + @classmethod + def run_command( + cls, + cmd: Union[List[str], CommandArgs], + show_stdout: bool = True, + cwd: Optional[str] = None, + on_returncode: 'Literal["raise", "warn", "ignore"]' = "raise", + extra_ok_returncodes: Optional[Iterable[int]] = None, + command_desc: Optional[str] = None, + extra_environ: Optional[Mapping[str, Any]] = None, + spinner: Optional[SpinnerInterface] = None, + log_failed_cmd: bool = True, + stdout_only: bool = False, + ) -> str: + """ + Run a VCS subcommand + This is simply a wrapper around call_subprocess that adds the VCS + command name, and checks that the VCS is available + """ + cmd = make_command(cls.name, *cmd) + if command_desc is None: + command_desc = format_command_args(cmd) + try: + return call_subprocess( + cmd, + show_stdout, + cwd, + on_returncode=on_returncode, + extra_ok_returncodes=extra_ok_returncodes, + command_desc=command_desc, + extra_environ=extra_environ, + unset_environ=cls.unset_environ, + spinner=spinner, + log_failed_cmd=log_failed_cmd, + stdout_only=stdout_only, + ) + except FileNotFoundError: + # errno.ENOENT = no such file or directory + # In other words, the VCS executable isn't available + raise BadCommand( + f"Cannot find command {cls.name!r} - do you have " + f"{cls.name!r} installed and in your PATH?" + ) + except PermissionError: + # errno.EACCES = Permission denied + # This error occurs, for instance, when the command is installed + # only for another user. So, the current user don't have + # permission to call the other user command. + raise BadCommand( + f"No permission to execute {cls.name!r} - install it " + f"locally, globally (ask admin), or check your PATH. " + f"See possible solutions at " + f"https://pip.pypa.io/en/latest/reference/pip_freeze/" + f"#fixing-permission-denied." + ) + + @classmethod + def is_repository_directory(cls, path: str) -> bool: + """ + Return whether a directory path is a repository directory. + """ + logger.debug("Checking in %s for %s (%s)...", path, cls.dirname, cls.name) + return os.path.exists(os.path.join(path, cls.dirname)) + + @classmethod + def get_repository_root(cls, location: str) -> Optional[str]: + """ + Return the "root" (top-level) directory controlled by the vcs, + or `None` if the directory is not in any. + + It is meant to be overridden to implement smarter detection + mechanisms for specific vcs. + + This can do more than is_repository_directory() alone. For + example, the Git override checks that Git is actually available. + """ + if cls.is_repository_directory(location): + return location + return None diff --git a/venv/Lib/site-packages/pip/_internal/wheel_builder.py b/venv/Lib/site-packages/pip/_internal/wheel_builder.py new file mode 100644 index 0000000..d066344 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/wheel_builder.py @@ -0,0 +1,377 @@ +"""Orchestrator for building wheels from InstallRequirements. +""" + +import logging +import os.path +import re +import shutil +from typing import Any, Callable, Iterable, List, Optional, Tuple + +from pip._vendor.packaging.utils import canonicalize_name, canonicalize_version +from pip._vendor.packaging.version import InvalidVersion, Version + +from pip._internal.cache import WheelCache +from pip._internal.exceptions import InvalidWheelFilename, UnsupportedWheel +from pip._internal.metadata import FilesystemWheel, get_wheel_distribution +from pip._internal.models.link import Link +from pip._internal.models.wheel import Wheel +from pip._internal.operations.build.wheel import build_wheel_pep517 +from pip._internal.operations.build.wheel_editable import build_wheel_editable +from pip._internal.operations.build.wheel_legacy import build_wheel_legacy +from pip._internal.req.req_install import InstallRequirement +from pip._internal.utils.logging import indent_log +from pip._internal.utils.misc import ensure_dir, hash_file, is_wheel_installed +from pip._internal.utils.setuptools_build import make_setuptools_clean_args +from pip._internal.utils.subprocess import call_subprocess +from pip._internal.utils.temp_dir import TempDirectory +from pip._internal.utils.urls import path_to_url +from pip._internal.vcs import vcs + +logger = logging.getLogger(__name__) + +_egg_info_re = re.compile(r"([a-z0-9_.]+)-([a-z0-9_.!+-]+)", re.IGNORECASE) + +BinaryAllowedPredicate = Callable[[InstallRequirement], bool] +BuildResult = Tuple[List[InstallRequirement], List[InstallRequirement]] + + +def _contains_egg_info(s: str) -> bool: + """Determine whether the string looks like an egg_info. + + :param s: The string to parse. E.g. foo-2.1 + """ + return bool(_egg_info_re.search(s)) + + +def _should_build( + req: InstallRequirement, + need_wheel: bool, + check_binary_allowed: BinaryAllowedPredicate, +) -> bool: + """Return whether an InstallRequirement should be built into a wheel.""" + if req.constraint: + # never build requirements that are merely constraints + return False + if req.is_wheel: + if need_wheel: + logger.info( + "Skipping %s, due to already being wheel.", + req.name, + ) + return False + + if need_wheel: + # i.e. pip wheel, not pip install + return True + + # From this point, this concerns the pip install command only + # (need_wheel=False). + + if not req.source_dir: + return False + + if req.editable: + # we only build PEP 660 editable requirements + return req.supports_pyproject_editable() + + if req.use_pep517: + return True + + if not check_binary_allowed(req): + logger.info( + "Skipping wheel build for %s, due to binaries being disabled for it.", + req.name, + ) + return False + + if not is_wheel_installed(): + # we don't build legacy requirements if wheel is not installed + logger.info( + "Using legacy 'setup.py install' for %s, " + "since package 'wheel' is not installed.", + req.name, + ) + return False + + return True + + +def should_build_for_wheel_command( + req: InstallRequirement, +) -> bool: + return _should_build(req, need_wheel=True, check_binary_allowed=_always_true) + + +def should_build_for_install_command( + req: InstallRequirement, + check_binary_allowed: BinaryAllowedPredicate, +) -> bool: + return _should_build( + req, need_wheel=False, check_binary_allowed=check_binary_allowed + ) + + +def _should_cache( + req: InstallRequirement, +) -> Optional[bool]: + """ + Return whether a built InstallRequirement can be stored in the persistent + wheel cache, assuming the wheel cache is available, and _should_build() + has determined a wheel needs to be built. + """ + if req.editable or not req.source_dir: + # never cache editable requirements + return False + + if req.link and req.link.is_vcs: + # VCS checkout. Do not cache + # unless it points to an immutable commit hash. + assert not req.editable + assert req.source_dir + vcs_backend = vcs.get_backend_for_scheme(req.link.scheme) + assert vcs_backend + if vcs_backend.is_immutable_rev_checkout(req.link.url, req.source_dir): + return True + return False + + assert req.link + base, ext = req.link.splitext() + if _contains_egg_info(base): + return True + + # Otherwise, do not cache. + return False + + +def _get_cache_dir( + req: InstallRequirement, + wheel_cache: WheelCache, +) -> str: + """Return the persistent or temporary cache directory where the built + wheel need to be stored. + """ + cache_available = bool(wheel_cache.cache_dir) + assert req.link + if cache_available and _should_cache(req): + cache_dir = wheel_cache.get_path_for_link(req.link) + else: + cache_dir = wheel_cache.get_ephem_path_for_link(req.link) + return cache_dir + + +def _always_true(_: Any) -> bool: + return True + + +def _verify_one(req: InstallRequirement, wheel_path: str) -> None: + canonical_name = canonicalize_name(req.name or "") + w = Wheel(os.path.basename(wheel_path)) + if canonicalize_name(w.name) != canonical_name: + raise InvalidWheelFilename( + "Wheel has unexpected file name: expected {!r}, " + "got {!r}".format(canonical_name, w.name), + ) + dist = get_wheel_distribution(FilesystemWheel(wheel_path), canonical_name) + dist_verstr = str(dist.version) + if canonicalize_version(dist_verstr) != canonicalize_version(w.version): + raise InvalidWheelFilename( + "Wheel has unexpected file name: expected {!r}, " + "got {!r}".format(dist_verstr, w.version), + ) + metadata_version_value = dist.metadata_version + if metadata_version_value is None: + raise UnsupportedWheel("Missing Metadata-Version") + try: + metadata_version = Version(metadata_version_value) + except InvalidVersion: + msg = f"Invalid Metadata-Version: {metadata_version_value}" + raise UnsupportedWheel(msg) + if metadata_version >= Version("1.2") and not isinstance(dist.version, Version): + raise UnsupportedWheel( + "Metadata 1.2 mandates PEP 440 version, " + "but {!r} is not".format(dist_verstr) + ) + + +def _build_one( + req: InstallRequirement, + output_dir: str, + verify: bool, + build_options: List[str], + global_options: List[str], + editable: bool, +) -> Optional[str]: + """Build one wheel. + + :return: The filename of the built wheel, or None if the build failed. + """ + artifact = "editable" if editable else "wheel" + try: + ensure_dir(output_dir) + except OSError as e: + logger.warning( + "Building %s for %s failed: %s", + artifact, + req.name, + e, + ) + return None + + # Install build deps into temporary directory (PEP 518) + with req.build_env: + wheel_path = _build_one_inside_env( + req, output_dir, build_options, global_options, editable + ) + if wheel_path and verify: + try: + _verify_one(req, wheel_path) + except (InvalidWheelFilename, UnsupportedWheel) as e: + logger.warning("Built %s for %s is invalid: %s", artifact, req.name, e) + return None + return wheel_path + + +def _build_one_inside_env( + req: InstallRequirement, + output_dir: str, + build_options: List[str], + global_options: List[str], + editable: bool, +) -> Optional[str]: + with TempDirectory(kind="wheel") as temp_dir: + assert req.name + if req.use_pep517: + assert req.metadata_directory + assert req.pep517_backend + if global_options: + logger.warning( + "Ignoring --global-option when building %s using PEP 517", req.name + ) + if build_options: + logger.warning( + "Ignoring --build-option when building %s using PEP 517", req.name + ) + if editable: + wheel_path = build_wheel_editable( + name=req.name, + backend=req.pep517_backend, + metadata_directory=req.metadata_directory, + tempd=temp_dir.path, + ) + else: + wheel_path = build_wheel_pep517( + name=req.name, + backend=req.pep517_backend, + metadata_directory=req.metadata_directory, + tempd=temp_dir.path, + ) + else: + wheel_path = build_wheel_legacy( + name=req.name, + setup_py_path=req.setup_py_path, + source_dir=req.unpacked_source_directory, + global_options=global_options, + build_options=build_options, + tempd=temp_dir.path, + ) + + if wheel_path is not None: + wheel_name = os.path.basename(wheel_path) + dest_path = os.path.join(output_dir, wheel_name) + try: + wheel_hash, length = hash_file(wheel_path) + shutil.move(wheel_path, dest_path) + logger.info( + "Created wheel for %s: filename=%s size=%d sha256=%s", + req.name, + wheel_name, + length, + wheel_hash.hexdigest(), + ) + logger.info("Stored in directory: %s", output_dir) + return dest_path + except Exception as e: + logger.warning( + "Building wheel for %s failed: %s", + req.name, + e, + ) + # Ignore return, we can't do anything else useful. + if not req.use_pep517: + _clean_one_legacy(req, global_options) + return None + + +def _clean_one_legacy(req: InstallRequirement, global_options: List[str]) -> bool: + clean_args = make_setuptools_clean_args( + req.setup_py_path, + global_options=global_options, + ) + + logger.info("Running setup.py clean for %s", req.name) + try: + call_subprocess( + clean_args, command_desc="python setup.py clean", cwd=req.source_dir + ) + return True + except Exception: + logger.error("Failed cleaning build dir for %s", req.name) + return False + + +def build( + requirements: Iterable[InstallRequirement], + wheel_cache: WheelCache, + verify: bool, + build_options: List[str], + global_options: List[str], +) -> BuildResult: + """Build wheels. + + :return: The list of InstallRequirement that succeeded to build and + the list of InstallRequirement that failed to build. + """ + if not requirements: + return [], [] + + # Build the wheels. + logger.info( + "Building wheels for collected packages: %s", + ", ".join(req.name for req in requirements), # type: ignore + ) + + with indent_log(): + build_successes, build_failures = [], [] + for req in requirements: + assert req.name + cache_dir = _get_cache_dir(req, wheel_cache) + wheel_file = _build_one( + req, + cache_dir, + verify, + build_options, + global_options, + req.editable and req.permit_editable_wheels, + ) + if wheel_file: + # Update the link for this. + req.link = Link(path_to_url(wheel_file)) + req.local_file_path = req.link.file_path + assert req.link.is_wheel + build_successes.append(req) + else: + build_failures.append(req) + + # notify success/failure + if build_successes: + logger.info( + "Successfully built %s", + " ".join([req.name for req in build_successes]), # type: ignore + ) + if build_failures: + logger.info( + "Failed to build %s", + " ".join([req.name for req in build_failures]), # type: ignore + ) + # Return a list of requirements that failed to build + return build_successes, build_failures diff --git a/venv/Lib/site-packages/pip/_vendor/__init__.py b/venv/Lib/site-packages/pip/_vendor/__init__.py new file mode 100644 index 0000000..3843cb0 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/__init__.py @@ -0,0 +1,111 @@ +""" +pip._vendor is for vendoring dependencies of pip to prevent needing pip to +depend on something external. + +Files inside of pip._vendor should be considered immutable and should only be +updated to versions from upstream. +""" +from __future__ import absolute_import + +import glob +import os.path +import sys + +# Downstream redistributors which have debundled our dependencies should also +# patch this value to be true. This will trigger the additional patching +# to cause things like "six" to be available as pip. +DEBUNDLED = False + +# By default, look in this directory for a bunch of .whl files which we will +# add to the beginning of sys.path before attempting to import anything. This +# is done to support downstream re-distributors like Debian and Fedora who +# wish to create their own Wheels for our dependencies to aid in debundling. +WHEEL_DIR = os.path.abspath(os.path.dirname(__file__)) + + +# Define a small helper function to alias our vendored modules to the real ones +# if the vendored ones do not exist. This idea of this was taken from +# https://github.com/kennethreitz/requests/pull/2567. +def vendored(modulename): + vendored_name = "{0}.{1}".format(__name__, modulename) + + try: + __import__(modulename, globals(), locals(), level=0) + except ImportError: + # We can just silently allow import failures to pass here. If we + # got to this point it means that ``import pip._vendor.whatever`` + # failed and so did ``import whatever``. Since we're importing this + # upfront in an attempt to alias imports, not erroring here will + # just mean we get a regular import error whenever pip *actually* + # tries to import one of these modules to use it, which actually + # gives us a better error message than we would have otherwise + # gotten. + pass + else: + sys.modules[vendored_name] = sys.modules[modulename] + base, head = vendored_name.rsplit(".", 1) + setattr(sys.modules[base], head, sys.modules[modulename]) + + +# If we're operating in a debundled setup, then we want to go ahead and trigger +# the aliasing of our vendored libraries as well as looking for wheels to add +# to our sys.path. This will cause all of this code to be a no-op typically +# however downstream redistributors can enable it in a consistent way across +# all platforms. +if DEBUNDLED: + # Actually look inside of WHEEL_DIR to find .whl files and add them to the + # front of our sys.path. + sys.path[:] = glob.glob(os.path.join(WHEEL_DIR, "*.whl")) + sys.path + + # Actually alias all of our vendored dependencies. + vendored("cachecontrol") + vendored("certifi") + vendored("colorama") + vendored("distlib") + vendored("distro") + vendored("html5lib") + vendored("six") + vendored("six.moves") + vendored("six.moves.urllib") + vendored("six.moves.urllib.parse") + vendored("packaging") + vendored("packaging.version") + vendored("packaging.specifiers") + vendored("pep517") + vendored("pkg_resources") + vendored("platformdirs") + vendored("progress") + vendored("requests") + vendored("requests.exceptions") + vendored("requests.packages") + vendored("requests.packages.urllib3") + vendored("requests.packages.urllib3._collections") + vendored("requests.packages.urllib3.connection") + vendored("requests.packages.urllib3.connectionpool") + vendored("requests.packages.urllib3.contrib") + vendored("requests.packages.urllib3.contrib.ntlmpool") + vendored("requests.packages.urllib3.contrib.pyopenssl") + vendored("requests.packages.urllib3.exceptions") + vendored("requests.packages.urllib3.fields") + vendored("requests.packages.urllib3.filepost") + vendored("requests.packages.urllib3.packages") + vendored("requests.packages.urllib3.packages.ordered_dict") + vendored("requests.packages.urllib3.packages.six") + vendored("requests.packages.urllib3.packages.ssl_match_hostname") + vendored("requests.packages.urllib3.packages.ssl_match_hostname." + "_implementation") + vendored("requests.packages.urllib3.poolmanager") + vendored("requests.packages.urllib3.request") + vendored("requests.packages.urllib3.response") + vendored("requests.packages.urllib3.util") + vendored("requests.packages.urllib3.util.connection") + vendored("requests.packages.urllib3.util.request") + vendored("requests.packages.urllib3.util.response") + vendored("requests.packages.urllib3.util.retry") + vendored("requests.packages.urllib3.util.ssl_") + vendored("requests.packages.urllib3.util.timeout") + vendored("requests.packages.urllib3.util.url") + vendored("resolvelib") + vendored("tenacity") + vendored("tomli") + vendored("urllib3") diff --git a/venv/Lib/site-packages/pip/_vendor/__pycache__/__init__.cpython-39.pyc b/venv/Lib/site-packages/pip/_vendor/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6a8337a411d6a5a2e7d6a3a57e64958aa1a64010 GIT binary patch literal 2897 zcmbuBTW{1x6vxMxwRe|Y2oNrz1~Q1Z4v5fCClrXWF5vHcV;%Q zCV5Kxh}4geJoYP%`qn4DLZ5oZo@}F5*`U_e&Tl;P_nFH%p0jbc+eUD`KYw+Ak0JDj ze%O0?@bESKgl8j!Q4e7Y+tkYJo^9#6L!F*e(d{)VdOZ)jJ)bnzn%k|aY?DJf){fQd z;0E@7M!hcaf3>+yoNcG-KTJB<-?4Wr;;l7LAzfkzJHObE5b5IPmSt(S4BLi>3_FHh z!^4J03}+0F8Xhw|Za8ar!tkWwDZ|r-bB1ROKQa8&@T}oE!}ErL;RVBshL;R48(uNI zYIx1?y5YRx4a1v;pBXL~hK9EcZyVk*{M_)a;TMLBhW8Bb8$K}nQWHDhqxpyB@9iQj z!f2i3nDHPL!3v;$O7qnKlLC53o}@$sY$X73AX!jw0vZ|QgkUYJo7=TIV0j=|M&wX; zk++iYJf>m0{WPUuCCx>Oi7_@ASq#~T;$T36gjE7gaFAx%NX7$7f;h*4k+7VOLDwD? zIF=xS>8ukjQg|&`;VcVAg^--YS=j!d5 zpO8>sYa2;x1MS$GR(V?58%R1^NV;1H+t_*UTIdzZkGV)T#`i3w?;lbA@HUd(n!kbO zYFdxbhPBwU zS>cDOp{+ddP8LhmjG{cwNEE4dWYz?Af0eR9Ooj3&OEeEXtCqXWIpfL^W1;+v;SqR2 zd0Z4UmC6@H#!~WmSGDUtZCG{d5Fof3N4bMo5akX@jDJIX7H0S7%O?-}F9mFTKhE=5 z^uH;JrC7%O=X&V=4$GRQUU(M8?ji1cmQf+Eb=IuYf}q#BMm1x0!CpDke#bJ&QMUQ@gZ z;awh`R6`Sm0q96&(2X;w$1t}Kq+*jS=^=ib4U?ZLo(d!g6mfEX01yQr$Y!y18 z#>r13BBUsf@76-{HX()7fnFY+G}eQ`^ymK7WR`Kayt;2!7{N|alGIi&@2`U`&TCnD z{bN)GW3;?5RVg`a@r?r|VJ<0zF_^n~u(lX8IIx7E<&?GT*~egili)UrMR{?Wf|7y> zIZZQh&#nFK>}o>BF@bY0!f7I>Ic@TSj^M?QFbo?K!MTwPqan;!f8piwe|jy{rwt_; z9R9J6nexgMGvKo<&f`_Wr$vG>Fl`gzizp!KNqKJn(MB?*<^1&ia8DFZ`6jffaCchQ z4lp^H+mwJa1|=VtmkuzeJvGhsl_{BKgpH=gU8RF#Ottk{Lm`c%gI-gTJWf(M?lmOK zXsZ1Bpu0PNMEOyKSyE?|m605A$SxfIDI(?Sw4!__;PjJ2Wi!D$y1liu{P^XIrRU2_ z%B^~QNV9bX4zntaK%QEGqz_hGufAPgejY77`>r~_mAl5$yvihdiWAyw^HH6LzS22Q htV7}Y9lL44-Eh5GuX)CEE<4q;Zu>uXZFL_De*w6Lj5+`S literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_vendor/__pycache__/distro.cpython-39.pyc b/venv/Lib/site-packages/pip/_vendor/__pycache__/distro.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1bb20036218db0c4088301e6231a41259c3cfd95 GIT binary patch literal 38359 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 B|K$Jx literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_vendor/__pycache__/six.cpython-39.pyc b/venv/Lib/site-packages/pip/_vendor/__pycache__/six.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..282f7baab89c902c1f2a15151645f845f81266f2 GIT binary patch literal 27501 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_vendor/__pycache__/typing_extensions.cpython-39.pyc b/venv/Lib/site-packages/pip/_vendor/__pycache__/typing_extensions.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..cd8328dacb9f394b9d8a02a4359d0eabeb3ed13a GIT binary patch literal 68485 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

#&6kN4kVcK@1bC+AC<@5}E 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/cache.cpython-39.pyc b/venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/cache.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d156566a7c93b9e79aad0ca21d1a5e1c8932fe06 GIT binary patch literal 1834 zcma)7&x_ke6rRzHWm&sU+@!x~X{$mBHFQl{N+}_fq?=L##T1fKY7AmlGn>_}EU7c{ zCTo1k?zQC9dvf%@G}oT`FZ9&+Mr%uC9ojMTc1G`M-uK>o-%9lRA%XG7C$|p%WQ6>M zoA%(axd+pH4Mvg)kyLsaop}?Fk{^j=l3x(X6+34W4*QPuVecyr`;P2BBEw*D5I#Oq zQ6dts#lf*ks_6dD52M3EN9nB0)J)}7nm?%{%qYTWsSd?FtD@9IBC3wG5;8R6P(^9J zH&e4hpG7iFsvr zXPn?AuLrK*P?koY?tocw9pJhL#&%9cHdnT*o|UOq#?@4t9dt9Js<&XVB{_KhZ%dop zx{H~yajhi2RGF&O+pRorI(h7v5W)1dkrly1>`cbdszv>OBZpS986| z;(S9o9(HXI$GMoPIJRLN&k8xuaJ?JHzt2Thd-N`xq6cWOJNgEiCY@Vh|1^>pV-0pZ z@B$XHfVrn{=J{<1-S9k=o@BspkSg$;0MB5`V$Qe1hP_6?cFP|Gt=qU92ZJoH>MZ7wqh`FxcTjf-lK2c?qZ_dF5SRCnSF#JaxObP{%nw#k6a2G)X}mSG0k*;PTzM z%=aRqn3ulvmUQW*^cAJ#SD+Jz-#McsAACv77q@|J`1=iJyI0612hjTS5}KuSAD=Wt za2!CId(!qP__EZD^y_brla7mSb$N5R4er)@{SN=nxiUE4WrOSg0w9}Q5&!@I literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/compat.cpython-39.pyc b/venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/compat.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..348d1962065a3f806481f1f1a7eaad842da807b2 GIT binary patch literal 739 zcmZ{h--^^Q6vmVO+3C)9b_Xv+MD%W9geig`A|fj)D9Ezts2B=kHa)uCO_OYrsxuGZ zoe$y*_$Xc!@4WIAyz+E9jzut~r#bn4`A$yCN24LZ@%h^R@h~LhN1OCVg2@5C?mLF% zxF7|Uq@s*c@`|Xd5rJTlQPMsuE$p<{Ltl zY|!)lv|&S;bXt#(7vDM#_SmS?i{Lq##6Ph^ zGNH|&w(?Y$>JaDYV_sT~xPag!n|%j3*&>%azR(Cj>^jJE!f zwc0ib>MN}oh@(=RNocmr>dP`ynr!|aRH1EV;k*Xt9U6%<{tjH$8Q(;uD{k@c5O$@% z>0g9h@2mf}tbHkM)SmTHf5RWUR>n(ErO*X5+a5mpxnCHZ9`XvhzC!2i7h?C&WEFnB zd2lCxfmh&it`v9qePbSS&-15RaGB4bGC9_o)~am~is^?F06D#N`?PezEn6*L-$gFC wI02!Rw_4^xSBCq{ESltQrHfj^y%>wSeGCB|)0AEa1B@x%jn;YacRj)N-#@R&JOBUy literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/controller.cpython-39.pyc b/venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/controller.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ff3f2297d72e78e278608faeec26fef69c027cb1 GIT binary patch literal 8201 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/wrapper.cpython-39.pyc b/venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/wrapper.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b9b6778b6e0872793ebb08d563bc5ee9da051e26 GIT binary patch literal 666 zcmYjOJ#Q2-5VgIZm%D=y8bm`EX^SHrLQ#Z>HWfnGa5SftPL6GH3*KGJ_7ZXORnX=? zK*?WnOT|AxsTl7i(vIb)Hy=CuW=!YvBLsH);`BO=5c(6Gv1Q=Ag=j-$p6Q2IS>zGF$P?7(|P+VaDw4`h+%C5D#lb4(-D>Q^BS2eRkYPn)Lls?!5 zNbpOz<{f~;9Q8;)vgkW%iNkyBQuWN@ed!vrIE3^AWyG#&4ycoUXkP5_{1g7E14`wwn}q&ffq literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_vendor/cachecontrol/_cmd.py b/venv/Lib/site-packages/pip/_vendor/cachecontrol/_cmd.py new file mode 100644 index 0000000..4266b5e --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/cachecontrol/_cmd.py @@ -0,0 +1,61 @@ +# SPDX-FileCopyrightText: 2015 Eric Larson +# +# SPDX-License-Identifier: Apache-2.0 + +import logging + +from pip._vendor import requests + +from pip._vendor.cachecontrol.adapter import CacheControlAdapter +from pip._vendor.cachecontrol.cache import DictCache +from pip._vendor.cachecontrol.controller import logger + +from argparse import ArgumentParser + + +def setup_logging(): + logger.setLevel(logging.DEBUG) + handler = logging.StreamHandler() + logger.addHandler(handler) + + +def get_session(): + adapter = CacheControlAdapter( + DictCache(), cache_etags=True, serializer=None, heuristic=None + ) + sess = requests.Session() + sess.mount("http://", adapter) + sess.mount("https://", adapter) + + sess.cache_controller = adapter.controller + return sess + + +def get_args(): + parser = ArgumentParser() + parser.add_argument("url", help="The URL to try and cache") + return parser.parse_args() + + +def main(args=None): + args = get_args() + sess = get_session() + + # Make a request to get a response + resp = sess.get(args.url) + + # Turn on logging + setup_logging() + + # try setting the cache + sess.cache_controller.cache_response(resp.request, resp.raw) + + # Now try to get it + if sess.cache_controller.cached_request(resp.request): + print("Cached!") + else: + print("Not cached :(") + + +if __name__ == "__main__": + main() diff --git a/venv/Lib/site-packages/pip/_vendor/cachecontrol/adapter.py b/venv/Lib/site-packages/pip/_vendor/cachecontrol/adapter.py new file mode 100644 index 0000000..94c75e1 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/cachecontrol/adapter.py @@ -0,0 +1,137 @@ +# SPDX-FileCopyrightText: 2015 Eric Larson +# +# SPDX-License-Identifier: Apache-2.0 + +import types +import functools +import zlib + +from pip._vendor.requests.adapters import HTTPAdapter + +from .controller import CacheController, PERMANENT_REDIRECT_STATUSES +from .cache import DictCache +from .filewrapper import CallbackFileWrapper + + +class CacheControlAdapter(HTTPAdapter): + invalidating_methods = {"PUT", "PATCH", "DELETE"} + + def __init__( + self, + cache=None, + cache_etags=True, + controller_class=None, + serializer=None, + heuristic=None, + cacheable_methods=None, + *args, + **kw + ): + super(CacheControlAdapter, self).__init__(*args, **kw) + self.cache = DictCache() if cache is None else cache + self.heuristic = heuristic + self.cacheable_methods = cacheable_methods or ("GET",) + + controller_factory = controller_class or CacheController + self.controller = controller_factory( + self.cache, cache_etags=cache_etags, serializer=serializer + ) + + def send(self, request, cacheable_methods=None, **kw): + """ + Send a request. Use the request information to see if it + exists in the cache and cache the response if we need to and can. + """ + cacheable = cacheable_methods or self.cacheable_methods + if request.method in cacheable: + try: + cached_response = self.controller.cached_request(request) + except zlib.error: + cached_response = None + if cached_response: + return self.build_response(request, cached_response, from_cache=True) + + # check for etags and add headers if appropriate + request.headers.update(self.controller.conditional_headers(request)) + + resp = super(CacheControlAdapter, self).send(request, **kw) + + return resp + + def build_response( + self, request, response, from_cache=False, cacheable_methods=None + ): + """ + Build a response by making a request or using the cache. + + This will end up calling send and returning a potentially + cached response + """ + cacheable = cacheable_methods or self.cacheable_methods + if not from_cache and request.method in cacheable: + # Check for any heuristics that might update headers + # before trying to cache. + if self.heuristic: + response = self.heuristic.apply(response) + + # apply any expiration heuristics + if response.status == 304: + # We must have sent an ETag request. This could mean + # that we've been expired already or that we simply + # have an etag. In either case, we want to try and + # update the cache if that is the case. + cached_response = self.controller.update_cached_response( + request, response + ) + + if cached_response is not response: + from_cache = True + + # We are done with the server response, read a + # possible response body (compliant servers will + # not return one, but we cannot be 100% sure) and + # release the connection back to the pool. + response.read(decode_content=False) + response.release_conn() + + response = cached_response + + # We always cache the 301 responses + elif int(response.status) in PERMANENT_REDIRECT_STATUSES: + self.controller.cache_response(request, response) + else: + # Wrap the response file with a wrapper that will cache the + # response when the stream has been consumed. + response._fp = CallbackFileWrapper( + response._fp, + functools.partial( + self.controller.cache_response, request, response + ), + ) + if response.chunked: + super_update_chunk_length = response._update_chunk_length + + def _update_chunk_length(self): + super_update_chunk_length() + if self.chunk_left == 0: + self._fp._close() + + response._update_chunk_length = types.MethodType( + _update_chunk_length, response + ) + + resp = super(CacheControlAdapter, self).build_response(request, response) + + # See if we should invalidate the cache. + if request.method in self.invalidating_methods and resp.ok: + cache_url = self.controller.cache_url(request.url) + self.cache.delete(cache_url) + + # Give the request a from_cache attr to let people use it + resp.from_cache = from_cache + + return resp + + def close(self): + self.cache.close() + super(CacheControlAdapter, self).close() diff --git a/venv/Lib/site-packages/pip/_vendor/cachecontrol/cache.py b/venv/Lib/site-packages/pip/_vendor/cachecontrol/cache.py new file mode 100644 index 0000000..44e4309 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/cachecontrol/cache.py @@ -0,0 +1,43 @@ +# SPDX-FileCopyrightText: 2015 Eric Larson +# +# SPDX-License-Identifier: Apache-2.0 + +""" +The cache object API for implementing caches. The default is a thread +safe in-memory dictionary. +""" +from threading import Lock + + +class BaseCache(object): + + def get(self, key): + raise NotImplementedError() + + def set(self, key, value, expires=None): + raise NotImplementedError() + + def delete(self, key): + raise NotImplementedError() + + def close(self): + pass + + +class DictCache(BaseCache): + + def __init__(self, init_dict=None): + self.lock = Lock() + self.data = init_dict or {} + + def get(self, key): + return self.data.get(key, None) + + def set(self, key, value, expires=None): + with self.lock: + self.data.update({key: value}) + + def delete(self, key): + with self.lock: + if key in self.data: + self.data.pop(key) diff --git a/venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/__init__.py b/venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/__init__.py new file mode 100644 index 0000000..44becd6 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/__init__.py @@ -0,0 +1,6 @@ +# SPDX-FileCopyrightText: 2015 Eric Larson +# +# SPDX-License-Identifier: Apache-2.0 + +from .file_cache import FileCache # noqa +from .redis_cache import RedisCache # noqa diff --git a/venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/__pycache__/__init__.cpython-39.pyc b/venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ea12121ee9f5441621335567139e183be7fc6f9f GIT binary patch literal 286 zcmYk0%}N6?5XY01h*I%XJXF1ufe@3CMzcvswu-((A4DH%ubzAb zPfk`34$Q}I{=>}3$)sXrn}fsq56Yhz{#!wCPM-EDXr{SkEnjk;>%taoxh$zJZ&*G0 z;xtn8etcyt&ZJr)LA5|_(m>bssIMMK6Do@_ukLqa*8e&sb>3OrrZj|aGdqF1gfW41 zPA0er;Zk-I=3Yq)x7Y>mrs1{UIc>dOTRhvM>nZ=X$A171*G|*` literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/__pycache__/file_cache.cpython-39.pyc b/venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/__pycache__/file_cache.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e11bf21b72b300623904ed58802f69a8fa099647 GIT binary patch literal 3316 zcmZWrUvC@75#QbW!{dpPX(ezSHEpg%o0LVYsz&PuLh9O9ti*sy7P1mm1cAfpb}5oN z-m$w!St5==5xMA7n>_TbKq2KV{S^Hi``Racg!ZMK*)u81zQfM#pV_&Y*_q#Lw7l#S zc>eO<`-gw86Y_5yEIu9#9zjzD5KcHvNW1*fHia=u*wAWQlyHmNi9K}Mj_EszJFK)T zluSI~QL<0cHJga)*%y@HD}1rkWo_?(q-=w5msehrcI{KbJzjlDcvU#(R(qNIdA{UhT58 z!_vsoINIUBc)lF ze@o!8B=+;aLca=LHZ?~yvrH45;|m4$R_C9i8ZvRWlsGNLe81xRPJ); zoKCB`Q&i7kCj`>n4Uj7j3vcSCH6xkGw5Uwof)*sKKv0s-pQ^r91SV>fDm;Suyxl}C{6d_6b- z?l?+kQ$aruPWn**QMP$wZ-7&Cu9>78ERCA>zlf5tC^N*HG0E?PmHN(XxIRP!XCwI@ zE-pPAjxw2>jS>+^SAj>wc_z%@=fNh`( z0rUl=&uPK1i2aGZ0~uYgBl;aOwQ@GF1`z%O=ZF^8H*}Z$6%&9puMiv>uKB;VlfKF& zmJe-@qP(Z=LDo;r=`?KFF!Kf}U9?hg?TjLstJiGNR@hDZz^o9J2|(2yI$6H92Ug!O zW{wjb*l}&lTJV%4mBAI%+HB>u<@$Q9KaVU@!NnJ)(kZc zfd4sx8eE#JnLGq@HsMe5HV|z~5pjJRHEd@2b~aAA3G127*0DH~zd}yd?Y&_v;KB&j zR1FBBKEzm!e#mM!Oa`79&ujJ|OwOzHH!zr+Y){s5dI6_6urBPvzJwqfIG1c*ecikQ z)pv8T`odlhIluaB>g3hJ835P~eB&~=a4(h$R#xw8r=@jp*~v|py|((d#Z`2iya#GF zYNgvuh+O=#3Z?;M1BTS3dMuREk@TMyIode^&4IXz8isN0sB1AZe|U5 zjH>%^b72?O%wOp$1d)BVvFPh-PdKF~3}~S{-wi#PqHvleoiO9vDfp;D? zF4k~}oW;a1*&5Ead>3VZ4@eU(hfRP@06O$_7-~NZ0anLwg9vpk4F52Wl5$0U2>iMR zWdo3M2*oSoCd*5`AECrgk$i^a+Qp`aewN<_@-Z}pQ=aoG!6^BU{{aK9dlj$huNba3 zyo{bUQ291=N~lC^Dj>4ayMR1&(%BXHSf&A%!Y-D$7_UYF;!bb~*IgcD<>KeNJL|qF zTYJ5}3V0?|fF)a`3a&}l`^71sm->O>gfl>3(^Vrh9LvO*-LSL;eO<*Lnk5r~3+9^$ zs{>D%XCZQhsLE+@ye<7n$SqPm{GV*Kx)m;zn=|&?H zA-dXx!z)YYb)uLYL8qG^Ea)^p6779lp7ldCPTc|GQIFODZE8^Cu(x7)jr!jI0ifLU AvH$=8 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/__pycache__/redis_cache.cpython-39.pyc b/venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/__pycache__/redis_cache.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..77d06410b26a5c3a954438853deef3a299901a38 GIT binary patch literal 1558 zcmZ`(PmkO*6u09flbz0N7Zss`1Q>xTMPlcODpVEPtprGD4lGXTb{SDS6rF|mH zv(lDz{R0bDh!6cI*tfAbOu^e4c z@R!IvIEm$0-hy=`CvpmFA|t?YyC46iWN8Oa!Hyf0aUQ|67?O^5BnOtq)`u+sYK7+Xp z?MFMI9n1;}>g~Y%Vt{>cIS7N}HF-k*Ja_};3mFbD!<4)nOUQE?tbX}f=|&lTQX5`q zB}`d8<3elhP8El2TV7UNa0&JM6gqOop|JUR=}yOdGYZi<=-;pADH}2oqM1SLA0pL9 z-p%Krw!SjhK3yH`5cBH)@IsC_JukG`VE@5e@zyHKu^Cl?KzLKv8d!YGtD09zN$zT( zRs(M2bbWC)_wi2YPz>0**JX_`!Q^W=9HJlG013(z-hn;rze+4sp7-NCU)HkKC{ObI zWh?ZcF}LvF*eC|eX^72Tls?7JwP!E+u8Kf`Ru-+2AYlm`kKh{{)XdWuy`8kKHQ>!) r=6&%mzJS+bws}2f#m?(7Yz&6a|KdYl`{cnu;2}D(*r*ez_6hqJvvgEG literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/file_cache.py b/venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/file_cache.py new file mode 100644 index 0000000..6cd1106 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/file_cache.py @@ -0,0 +1,150 @@ +# SPDX-FileCopyrightText: 2015 Eric Larson +# +# SPDX-License-Identifier: Apache-2.0 + +import hashlib +import os +from textwrap import dedent + +from ..cache import BaseCache +from ..controller import CacheController + +try: + FileNotFoundError +except NameError: + # py2.X + FileNotFoundError = (IOError, OSError) + + +def _secure_open_write(filename, fmode): + # We only want to write to this file, so open it in write only mode + flags = os.O_WRONLY + + # os.O_CREAT | os.O_EXCL will fail if the file already exists, so we only + # will open *new* files. + # We specify this because we want to ensure that the mode we pass is the + # mode of the file. + flags |= os.O_CREAT | os.O_EXCL + + # Do not follow symlinks to prevent someone from making a symlink that + # we follow and insecurely open a cache file. + if hasattr(os, "O_NOFOLLOW"): + flags |= os.O_NOFOLLOW + + # On Windows we'll mark this file as binary + if hasattr(os, "O_BINARY"): + flags |= os.O_BINARY + + # Before we open our file, we want to delete any existing file that is + # there + try: + os.remove(filename) + except (IOError, OSError): + # The file must not exist already, so we can just skip ahead to opening + pass + + # Open our file, the use of os.O_CREAT | os.O_EXCL will ensure that if a + # race condition happens between the os.remove and this line, that an + # error will be raised. Because we utilize a lockfile this should only + # happen if someone is attempting to attack us. + fd = os.open(filename, flags, fmode) + try: + return os.fdopen(fd, "wb") + + except: + # An error occurred wrapping our FD in a file object + os.close(fd) + raise + + +class FileCache(BaseCache): + + def __init__( + self, + directory, + forever=False, + filemode=0o0600, + dirmode=0o0700, + use_dir_lock=None, + lock_class=None, + ): + + if use_dir_lock is not None and lock_class is not None: + raise ValueError("Cannot use use_dir_lock and lock_class together") + + try: + from lockfile import LockFile + from lockfile.mkdirlockfile import MkdirLockFile + except ImportError: + notice = dedent( + """ + NOTE: In order to use the FileCache you must have + lockfile installed. You can install it via pip: + pip install lockfile + """ + ) + raise ImportError(notice) + + else: + if use_dir_lock: + lock_class = MkdirLockFile + + elif lock_class is None: + lock_class = LockFile + + self.directory = directory + self.forever = forever + self.filemode = filemode + self.dirmode = dirmode + self.lock_class = lock_class + + @staticmethod + def encode(x): + return hashlib.sha224(x.encode()).hexdigest() + + def _fn(self, name): + # NOTE: This method should not change as some may depend on it. + # See: https://github.com/ionrock/cachecontrol/issues/63 + hashed = self.encode(name) + parts = list(hashed[:5]) + [hashed] + return os.path.join(self.directory, *parts) + + def get(self, key): + name = self._fn(key) + try: + with open(name, "rb") as fh: + return fh.read() + + except FileNotFoundError: + return None + + def set(self, key, value, expires=None): + name = self._fn(key) + + # Make sure the directory exists + try: + os.makedirs(os.path.dirname(name), self.dirmode) + except (IOError, OSError): + pass + + with self.lock_class(name) as lock: + # Write our actual file + with _secure_open_write(lock.path, self.filemode) as fh: + fh.write(value) + + def delete(self, key): + name = self._fn(key) + if not self.forever: + try: + os.remove(name) + except FileNotFoundError: + pass + + +def url_to_file_path(url, filecache): + """Return the file cache path based on the URL. + + This does not ensure the file exists! + """ + key = CacheController.cache_url(url) + return filecache._fn(key) diff --git a/venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/redis_cache.py b/venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/redis_cache.py new file mode 100644 index 0000000..720b507 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/redis_cache.py @@ -0,0 +1,37 @@ +# SPDX-FileCopyrightText: 2015 Eric Larson +# +# SPDX-License-Identifier: Apache-2.0 + +from __future__ import division + +from datetime import datetime +from pip._vendor.cachecontrol.cache import BaseCache + + +class RedisCache(BaseCache): + + def __init__(self, conn): + self.conn = conn + + def get(self, key): + return self.conn.get(key) + + def set(self, key, value, expires=None): + if not expires: + self.conn.set(key, value) + else: + expires = expires - datetime.utcnow() + self.conn.setex(key, int(expires.total_seconds()), value) + + def delete(self, key): + self.conn.delete(key) + + def clear(self): + """Helper for clearing all the keys in a database. Use with + caution!""" + for key in self.conn.keys(): + self.conn.delete(key) + + def close(self): + """Redis uses connection pooling, no need to close the connection.""" + pass diff --git a/venv/Lib/site-packages/pip/_vendor/cachecontrol/compat.py b/venv/Lib/site-packages/pip/_vendor/cachecontrol/compat.py new file mode 100644 index 0000000..ccec937 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/cachecontrol/compat.py @@ -0,0 +1,32 @@ +# SPDX-FileCopyrightText: 2015 Eric Larson +# +# SPDX-License-Identifier: Apache-2.0 + +try: + from urllib.parse import urljoin +except ImportError: + from urlparse import urljoin + + +try: + import cPickle as pickle +except ImportError: + import pickle + +# Handle the case where the requests module has been patched to not have +# urllib3 bundled as part of its source. +try: + from pip._vendor.requests.packages.urllib3.response import HTTPResponse +except ImportError: + from pip._vendor.urllib3.response import HTTPResponse + +try: + from pip._vendor.requests.packages.urllib3.util import is_fp_closed +except ImportError: + from pip._vendor.urllib3.util import is_fp_closed + +# Replicate some six behaviour +try: + text_type = unicode +except NameError: + text_type = str diff --git a/venv/Lib/site-packages/pip/_vendor/cachecontrol/controller.py b/venv/Lib/site-packages/pip/_vendor/cachecontrol/controller.py new file mode 100644 index 0000000..d7e7380 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/cachecontrol/controller.py @@ -0,0 +1,415 @@ +# SPDX-FileCopyrightText: 2015 Eric Larson +# +# SPDX-License-Identifier: Apache-2.0 + +""" +The httplib2 algorithms ported for use with requests. +""" +import logging +import re +import calendar +import time +from email.utils import parsedate_tz + +from pip._vendor.requests.structures import CaseInsensitiveDict + +from .cache import DictCache +from .serialize import Serializer + + +logger = logging.getLogger(__name__) + +URI = re.compile(r"^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?") + +PERMANENT_REDIRECT_STATUSES = (301, 308) + + +def parse_uri(uri): + """Parses a URI using the regex given in Appendix B of RFC 3986. + + (scheme, authority, path, query, fragment) = parse_uri(uri) + """ + groups = URI.match(uri).groups() + return (groups[1], groups[3], groups[4], groups[6], groups[8]) + + +class CacheController(object): + """An interface to see if request should cached or not. + """ + + def __init__( + self, cache=None, cache_etags=True, serializer=None, status_codes=None + ): + self.cache = DictCache() if cache is None else cache + self.cache_etags = cache_etags + self.serializer = serializer or Serializer() + self.cacheable_status_codes = status_codes or (200, 203, 300, 301, 308) + + @classmethod + def _urlnorm(cls, uri): + """Normalize the URL to create a safe key for the cache""" + (scheme, authority, path, query, fragment) = parse_uri(uri) + if not scheme or not authority: + raise Exception("Only absolute URIs are allowed. uri = %s" % uri) + + scheme = scheme.lower() + authority = authority.lower() + + if not path: + path = "/" + + # Could do syntax based normalization of the URI before + # computing the digest. See Section 6.2.2 of Std 66. + request_uri = query and "?".join([path, query]) or path + defrag_uri = scheme + "://" + authority + request_uri + + return defrag_uri + + @classmethod + def cache_url(cls, uri): + return cls._urlnorm(uri) + + def parse_cache_control(self, headers): + known_directives = { + # https://tools.ietf.org/html/rfc7234#section-5.2 + "max-age": (int, True), + "max-stale": (int, False), + "min-fresh": (int, True), + "no-cache": (None, False), + "no-store": (None, False), + "no-transform": (None, False), + "only-if-cached": (None, False), + "must-revalidate": (None, False), + "public": (None, False), + "private": (None, False), + "proxy-revalidate": (None, False), + "s-maxage": (int, True), + } + + cc_headers = headers.get("cache-control", headers.get("Cache-Control", "")) + + retval = {} + + for cc_directive in cc_headers.split(","): + if not cc_directive.strip(): + continue + + parts = cc_directive.split("=", 1) + directive = parts[0].strip() + + try: + typ, required = known_directives[directive] + except KeyError: + logger.debug("Ignoring unknown cache-control directive: %s", directive) + continue + + if not typ or not required: + retval[directive] = None + if typ: + try: + retval[directive] = typ(parts[1].strip()) + except IndexError: + if required: + logger.debug( + "Missing value for cache-control " "directive: %s", + directive, + ) + except ValueError: + logger.debug( + "Invalid value for cache-control directive " "%s, must be %s", + directive, + typ.__name__, + ) + + return retval + + def cached_request(self, request): + """ + Return a cached response if it exists in the cache, otherwise + return False. + """ + cache_url = self.cache_url(request.url) + logger.debug('Looking up "%s" in the cache', cache_url) + cc = self.parse_cache_control(request.headers) + + # Bail out if the request insists on fresh data + if "no-cache" in cc: + logger.debug('Request header has "no-cache", cache bypassed') + return False + + if "max-age" in cc and cc["max-age"] == 0: + logger.debug('Request header has "max_age" as 0, cache bypassed') + return False + + # Request allows serving from the cache, let's see if we find something + cache_data = self.cache.get(cache_url) + if cache_data is None: + logger.debug("No cache entry available") + return False + + # Check whether it can be deserialized + resp = self.serializer.loads(request, cache_data) + if not resp: + logger.warning("Cache entry deserialization failed, entry ignored") + return False + + # If we have a cached permanent redirect, return it immediately. We + # don't need to test our response for other headers b/c it is + # intrinsically "cacheable" as it is Permanent. + # + # See: + # https://tools.ietf.org/html/rfc7231#section-6.4.2 + # + # Client can try to refresh the value by repeating the request + # with cache busting headers as usual (ie no-cache). + if int(resp.status) in PERMANENT_REDIRECT_STATUSES: + msg = ( + "Returning cached permanent redirect response " + "(ignoring date and etag information)" + ) + logger.debug(msg) + return resp + + headers = CaseInsensitiveDict(resp.headers) + if not headers or "date" not in headers: + if "etag" not in headers: + # Without date or etag, the cached response can never be used + # and should be deleted. + logger.debug("Purging cached response: no date or etag") + self.cache.delete(cache_url) + logger.debug("Ignoring cached response: no date") + return False + + now = time.time() + date = calendar.timegm(parsedate_tz(headers["date"])) + current_age = max(0, now - date) + logger.debug("Current age based on date: %i", current_age) + + # TODO: There is an assumption that the result will be a + # urllib3 response object. This may not be best since we + # could probably avoid instantiating or constructing the + # response until we know we need it. + resp_cc = self.parse_cache_control(headers) + + # determine freshness + freshness_lifetime = 0 + + # Check the max-age pragma in the cache control header + if "max-age" in resp_cc: + freshness_lifetime = resp_cc["max-age"] + logger.debug("Freshness lifetime from max-age: %i", freshness_lifetime) + + # If there isn't a max-age, check for an expires header + elif "expires" in headers: + expires = parsedate_tz(headers["expires"]) + if expires is not None: + expire_time = calendar.timegm(expires) - date + freshness_lifetime = max(0, expire_time) + logger.debug("Freshness lifetime from expires: %i", freshness_lifetime) + + # Determine if we are setting freshness limit in the + # request. Note, this overrides what was in the response. + if "max-age" in cc: + freshness_lifetime = cc["max-age"] + logger.debug( + "Freshness lifetime from request max-age: %i", freshness_lifetime + ) + + if "min-fresh" in cc: + min_fresh = cc["min-fresh"] + # adjust our current age by our min fresh + current_age += min_fresh + logger.debug("Adjusted current age from min-fresh: %i", current_age) + + # Return entry if it is fresh enough + if freshness_lifetime > current_age: + logger.debug('The response is "fresh", returning cached response') + logger.debug("%i > %i", freshness_lifetime, current_age) + return resp + + # we're not fresh. If we don't have an Etag, clear it out + if "etag" not in headers: + logger.debug('The cached response is "stale" with no etag, purging') + self.cache.delete(cache_url) + + # return the original handler + return False + + def conditional_headers(self, request): + cache_url = self.cache_url(request.url) + resp = self.serializer.loads(request, self.cache.get(cache_url)) + new_headers = {} + + if resp: + headers = CaseInsensitiveDict(resp.headers) + + if "etag" in headers: + new_headers["If-None-Match"] = headers["ETag"] + + if "last-modified" in headers: + new_headers["If-Modified-Since"] = headers["Last-Modified"] + + return new_headers + + def cache_response(self, request, response, body=None, status_codes=None): + """ + Algorithm for caching requests. + + This assumes a requests Response object. + """ + # From httplib2: Don't cache 206's since we aren't going to + # handle byte range requests + cacheable_status_codes = status_codes or self.cacheable_status_codes + if response.status not in cacheable_status_codes: + logger.debug( + "Status code %s not in %s", response.status, cacheable_status_codes + ) + return + + response_headers = CaseInsensitiveDict(response.headers) + + if "date" in response_headers: + date = calendar.timegm(parsedate_tz(response_headers["date"])) + else: + date = 0 + + # If we've been given a body, our response has a Content-Length, that + # Content-Length is valid then we can check to see if the body we've + # been given matches the expected size, and if it doesn't we'll just + # skip trying to cache it. + if ( + body is not None + and "content-length" in response_headers + and response_headers["content-length"].isdigit() + and int(response_headers["content-length"]) != len(body) + ): + return + + cc_req = self.parse_cache_control(request.headers) + cc = self.parse_cache_control(response_headers) + + cache_url = self.cache_url(request.url) + logger.debug('Updating cache with response from "%s"', cache_url) + + # Delete it from the cache if we happen to have it stored there + no_store = False + if "no-store" in cc: + no_store = True + logger.debug('Response header has "no-store"') + if "no-store" in cc_req: + no_store = True + logger.debug('Request header has "no-store"') + if no_store and self.cache.get(cache_url): + logger.debug('Purging existing cache entry to honor "no-store"') + self.cache.delete(cache_url) + if no_store: + return + + # https://tools.ietf.org/html/rfc7234#section-4.1: + # A Vary header field-value of "*" always fails to match. + # Storing such a response leads to a deserialization warning + # during cache lookup and is not allowed to ever be served, + # so storing it can be avoided. + if "*" in response_headers.get("vary", ""): + logger.debug('Response header has "Vary: *"') + return + + # If we've been given an etag, then keep the response + if self.cache_etags and "etag" in response_headers: + expires_time = 0 + if response_headers.get("expires"): + expires = parsedate_tz(response_headers["expires"]) + if expires is not None: + expires_time = calendar.timegm(expires) - date + + expires_time = max(expires_time, 14 * 86400) + + logger.debug("etag object cached for {0} seconds".format(expires_time)) + logger.debug("Caching due to etag") + self.cache.set( + cache_url, + self.serializer.dumps(request, response, body), + expires=expires_time, + ) + + # Add to the cache any permanent redirects. We do this before looking + # that the Date headers. + elif int(response.status) in PERMANENT_REDIRECT_STATUSES: + logger.debug("Caching permanent redirect") + self.cache.set(cache_url, self.serializer.dumps(request, response, b"")) + + # Add to the cache if the response headers demand it. If there + # is no date header then we can't do anything about expiring + # the cache. + elif "date" in response_headers: + date = calendar.timegm(parsedate_tz(response_headers["date"])) + # cache when there is a max-age > 0 + if "max-age" in cc and cc["max-age"] > 0: + logger.debug("Caching b/c date exists and max-age > 0") + expires_time = cc["max-age"] + self.cache.set( + cache_url, + self.serializer.dumps(request, response, body), + expires=expires_time, + ) + + # If the request can expire, it means we should cache it + # in the meantime. + elif "expires" in response_headers: + if response_headers["expires"]: + expires = parsedate_tz(response_headers["expires"]) + if expires is not None: + expires_time = calendar.timegm(expires) - date + else: + expires_time = None + + logger.debug( + "Caching b/c of expires header. expires in {0} seconds".format( + expires_time + ) + ) + self.cache.set( + cache_url, + self.serializer.dumps(request, response, body=body), + expires=expires_time, + ) + + def update_cached_response(self, request, response): + """On a 304 we will get a new set of headers that we want to + update our cached value with, assuming we have one. + + This should only ever be called when we've sent an ETag and + gotten a 304 as the response. + """ + cache_url = self.cache_url(request.url) + + cached_response = self.serializer.loads(request, self.cache.get(cache_url)) + + if not cached_response: + # we didn't have a cached response + return response + + # Lets update our headers with the headers from the new request: + # http://tools.ietf.org/html/draft-ietf-httpbis-p4-conditional-26#section-4.1 + # + # The server isn't supposed to send headers that would make + # the cached body invalid. But... just in case, we'll be sure + # to strip out ones we know that might be problmatic due to + # typical assumptions. + excluded_headers = ["content-length"] + + cached_response.headers.update( + dict( + (k, v) + for k, v in response.headers.items() + if k.lower() not in excluded_headers + ) + ) + + # we want a 200 b/c we have content via the cache + cached_response.status = 200 + + # update our cache + self.cache.set(cache_url, self.serializer.dumps(request, cached_response)) + + return cached_response diff --git a/venv/Lib/site-packages/pip/_vendor/cachecontrol/filewrapper.py b/venv/Lib/site-packages/pip/_vendor/cachecontrol/filewrapper.py new file mode 100644 index 0000000..f5ed5f6 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/cachecontrol/filewrapper.py @@ -0,0 +1,111 @@ +# SPDX-FileCopyrightText: 2015 Eric Larson +# +# SPDX-License-Identifier: Apache-2.0 + +from tempfile import NamedTemporaryFile +import mmap + + +class CallbackFileWrapper(object): + """ + Small wrapper around a fp object which will tee everything read into a + buffer, and when that file is closed it will execute a callback with the + contents of that buffer. + + All attributes are proxied to the underlying file object. + + This class uses members with a double underscore (__) leading prefix so as + not to accidentally shadow an attribute. + + The data is stored in a temporary file until it is all available. As long + as the temporary files directory is disk-based (sometimes it's a + memory-backed-``tmpfs`` on Linux), data will be unloaded to disk if memory + pressure is high. For small files the disk usually won't be used at all, + it'll all be in the filesystem memory cache, so there should be no + performance impact. + """ + + def __init__(self, fp, callback): + self.__buf = NamedTemporaryFile("rb+", delete=True) + self.__fp = fp + self.__callback = callback + + def __getattr__(self, name): + # The vaguaries of garbage collection means that self.__fp is + # not always set. By using __getattribute__ and the private + # name[0] allows looking up the attribute value and raising an + # AttributeError when it doesn't exist. This stop thigns from + # infinitely recursing calls to getattr in the case where + # self.__fp hasn't been set. + # + # [0] https://docs.python.org/2/reference/expressions.html#atom-identifiers + fp = self.__getattribute__("_CallbackFileWrapper__fp") + return getattr(fp, name) + + def __is_fp_closed(self): + try: + return self.__fp.fp is None + + except AttributeError: + pass + + try: + return self.__fp.closed + + except AttributeError: + pass + + # We just don't cache it then. + # TODO: Add some logging here... + return False + + def _close(self): + if self.__callback: + if self.__buf.tell() == 0: + # Empty file: + result = b"" + else: + # Return the data without actually loading it into memory, + # relying on Python's buffer API and mmap(). mmap() just gives + # a view directly into the filesystem's memory cache, so it + # doesn't result in duplicate memory use. + self.__buf.seek(0, 0) + result = memoryview( + mmap.mmap(self.__buf.fileno(), 0, access=mmap.ACCESS_READ) + ) + self.__callback(result) + + # We assign this to None here, because otherwise we can get into + # really tricky problems where the CPython interpreter dead locks + # because the callback is holding a reference to something which + # has a __del__ method. Setting this to None breaks the cycle + # and allows the garbage collector to do it's thing normally. + self.__callback = None + + # Closing the temporary file releases memory and frees disk space. + # Important when caching big files. + self.__buf.close() + + def read(self, amt=None): + data = self.__fp.read(amt) + if data: + # We may be dealing with b'', a sign that things are over: + # it's passed e.g. after we've already closed self.__buf. + self.__buf.write(data) + if self.__is_fp_closed(): + self._close() + + return data + + def _safe_read(self, amt): + data = self.__fp._safe_read(amt) + if amt == 2 and data == b"\r\n": + # urllib executes this read to toss the CRLF at the end + # of the chunk. + return data + + self.__buf.write(data) + if self.__is_fp_closed(): + self._close() + + return data diff --git a/venv/Lib/site-packages/pip/_vendor/cachecontrol/heuristics.py b/venv/Lib/site-packages/pip/_vendor/cachecontrol/heuristics.py new file mode 100644 index 0000000..ebe4a96 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/cachecontrol/heuristics.py @@ -0,0 +1,139 @@ +# SPDX-FileCopyrightText: 2015 Eric Larson +# +# SPDX-License-Identifier: Apache-2.0 + +import calendar +import time + +from email.utils import formatdate, parsedate, parsedate_tz + +from datetime import datetime, timedelta + +TIME_FMT = "%a, %d %b %Y %H:%M:%S GMT" + + +def expire_after(delta, date=None): + date = date or datetime.utcnow() + return date + delta + + +def datetime_to_header(dt): + return formatdate(calendar.timegm(dt.timetuple())) + + +class BaseHeuristic(object): + + def warning(self, response): + """ + Return a valid 1xx warning header value describing the cache + adjustments. + + The response is provided too allow warnings like 113 + http://tools.ietf.org/html/rfc7234#section-5.5.4 where we need + to explicitly say response is over 24 hours old. + """ + return '110 - "Response is Stale"' + + def update_headers(self, response): + """Update the response headers with any new headers. + + NOTE: This SHOULD always include some Warning header to + signify that the response was cached by the client, not + by way of the provided headers. + """ + return {} + + def apply(self, response): + updated_headers = self.update_headers(response) + + if updated_headers: + response.headers.update(updated_headers) + warning_header_value = self.warning(response) + if warning_header_value is not None: + response.headers.update({"Warning": warning_header_value}) + + return response + + +class OneDayCache(BaseHeuristic): + """ + Cache the response by providing an expires 1 day in the + future. + """ + + def update_headers(self, response): + headers = {} + + if "expires" not in response.headers: + date = parsedate(response.headers["date"]) + expires = expire_after(timedelta(days=1), date=datetime(*date[:6])) + headers["expires"] = datetime_to_header(expires) + headers["cache-control"] = "public" + return headers + + +class ExpiresAfter(BaseHeuristic): + """ + Cache **all** requests for a defined time period. + """ + + def __init__(self, **kw): + self.delta = timedelta(**kw) + + def update_headers(self, response): + expires = expire_after(self.delta) + return {"expires": datetime_to_header(expires), "cache-control": "public"} + + def warning(self, response): + tmpl = "110 - Automatically cached for %s. Response might be stale" + return tmpl % self.delta + + +class LastModified(BaseHeuristic): + """ + If there is no Expires header already, fall back on Last-Modified + using the heuristic from + http://tools.ietf.org/html/rfc7234#section-4.2.2 + to calculate a reasonable value. + + Firefox also does something like this per + https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching_FAQ + http://lxr.mozilla.org/mozilla-release/source/netwerk/protocol/http/nsHttpResponseHead.cpp#397 + Unlike mozilla we limit this to 24-hr. + """ + cacheable_by_default_statuses = { + 200, 203, 204, 206, 300, 301, 404, 405, 410, 414, 501 + } + + def update_headers(self, resp): + headers = resp.headers + + if "expires" in headers: + return {} + + if "cache-control" in headers and headers["cache-control"] != "public": + return {} + + if resp.status not in self.cacheable_by_default_statuses: + return {} + + if "date" not in headers or "last-modified" not in headers: + return {} + + date = calendar.timegm(parsedate_tz(headers["date"])) + last_modified = parsedate(headers["last-modified"]) + if date is None or last_modified is None: + return {} + + now = time.time() + current_age = max(0, now - date) + delta = date - calendar.timegm(last_modified) + freshness_lifetime = max(0, min(delta / 10, 24 * 3600)) + if freshness_lifetime <= current_age: + return {} + + expires = date + freshness_lifetime + return {"expires": time.strftime(TIME_FMT, time.gmtime(expires))} + + def warning(self, resp): + return None diff --git a/venv/Lib/site-packages/pip/_vendor/cachecontrol/serialize.py b/venv/Lib/site-packages/pip/_vendor/cachecontrol/serialize.py new file mode 100644 index 0000000..b075df1 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/cachecontrol/serialize.py @@ -0,0 +1,186 @@ +# SPDX-FileCopyrightText: 2015 Eric Larson +# +# SPDX-License-Identifier: Apache-2.0 + +import base64 +import io +import json +import zlib + +from pip._vendor import msgpack +from pip._vendor.requests.structures import CaseInsensitiveDict + +from .compat import HTTPResponse, pickle, text_type + + +def _b64_decode_bytes(b): + return base64.b64decode(b.encode("ascii")) + + +def _b64_decode_str(s): + return _b64_decode_bytes(s).decode("utf8") + + +_default_body_read = object() + + +class Serializer(object): + def dumps(self, request, response, body=None): + response_headers = CaseInsensitiveDict(response.headers) + + if body is None: + # When a body isn't passed in, we'll read the response. We + # also update the response with a new file handler to be + # sure it acts as though it was never read. + body = response.read(decode_content=False) + response._fp = io.BytesIO(body) + + # NOTE: This is all a bit weird, but it's really important that on + # Python 2.x these objects are unicode and not str, even when + # they contain only ascii. The problem here is that msgpack + # understands the difference between unicode and bytes and we + # have it set to differentiate between them, however Python 2 + # doesn't know the difference. Forcing these to unicode will be + # enough to have msgpack know the difference. + data = { + u"response": { + u"body": body, + u"headers": dict( + (text_type(k), text_type(v)) for k, v in response.headers.items() + ), + u"status": response.status, + u"version": response.version, + u"reason": text_type(response.reason), + u"strict": response.strict, + u"decode_content": response.decode_content, + } + } + + # Construct our vary headers + data[u"vary"] = {} + if u"vary" in response_headers: + varied_headers = response_headers[u"vary"].split(",") + for header in varied_headers: + header = text_type(header).strip() + header_value = request.headers.get(header, None) + if header_value is not None: + header_value = text_type(header_value) + data[u"vary"][header] = header_value + + return b",".join([b"cc=4", msgpack.dumps(data, use_bin_type=True)]) + + def loads(self, request, data): + # Short circuit if we've been given an empty set of data + if not data: + return + + # Determine what version of the serializer the data was serialized + # with + try: + ver, data = data.split(b",", 1) + except ValueError: + ver = b"cc=0" + + # Make sure that our "ver" is actually a version and isn't a false + # positive from a , being in the data stream. + if ver[:3] != b"cc=": + data = ver + data + ver = b"cc=0" + + # Get the version number out of the cc=N + ver = ver.split(b"=", 1)[-1].decode("ascii") + + # Dispatch to the actual load method for the given version + try: + return getattr(self, "_loads_v{}".format(ver))(request, data) + + except AttributeError: + # This is a version we don't have a loads function for, so we'll + # just treat it as a miss and return None + return + + def prepare_response(self, request, cached): + """Verify our vary headers match and construct a real urllib3 + HTTPResponse object. + """ + # Special case the '*' Vary value as it means we cannot actually + # determine if the cached response is suitable for this request. + # This case is also handled in the controller code when creating + # a cache entry, but is left here for backwards compatibility. + if "*" in cached.get("vary", {}): + return + + # Ensure that the Vary headers for the cached response match our + # request + for header, value in cached.get("vary", {}).items(): + if request.headers.get(header, None) != value: + return + + body_raw = cached["response"].pop("body") + + headers = CaseInsensitiveDict(data=cached["response"]["headers"]) + if headers.get("transfer-encoding", "") == "chunked": + headers.pop("transfer-encoding") + + cached["response"]["headers"] = headers + + try: + body = io.BytesIO(body_raw) + except TypeError: + # This can happen if cachecontrol serialized to v1 format (pickle) + # using Python 2. A Python 2 str(byte string) will be unpickled as + # a Python 3 str (unicode string), which will cause the above to + # fail with: + # + # TypeError: 'str' does not support the buffer interface + body = io.BytesIO(body_raw.encode("utf8")) + + return HTTPResponse(body=body, preload_content=False, **cached["response"]) + + def _loads_v0(self, request, data): + # The original legacy cache data. This doesn't contain enough + # information to construct everything we need, so we'll treat this as + # a miss. + return + + def _loads_v1(self, request, data): + try: + cached = pickle.loads(data) + except ValueError: + return + + return self.prepare_response(request, cached) + + def _loads_v2(self, request, data): + try: + cached = json.loads(zlib.decompress(data).decode("utf8")) + except (ValueError, zlib.error): + return + + # We need to decode the items that we've base64 encoded + cached["response"]["body"] = _b64_decode_bytes(cached["response"]["body"]) + cached["response"]["headers"] = dict( + (_b64_decode_str(k), _b64_decode_str(v)) + for k, v in cached["response"]["headers"].items() + ) + cached["response"]["reason"] = _b64_decode_str(cached["response"]["reason"]) + cached["vary"] = dict( + (_b64_decode_str(k), _b64_decode_str(v) if v is not None else v) + for k, v in cached["vary"].items() + ) + + return self.prepare_response(request, cached) + + def _loads_v3(self, request, data): + # Due to Python 2 encoding issues, it's impossible to know for sure + # exactly how to load v3 entries, thus we'll treat these as a miss so + # that they get rewritten out as v4 entries. + return + + def _loads_v4(self, request, data): + try: + cached = msgpack.loads(data, raw=False) + except ValueError: + return + + return self.prepare_response(request, cached) diff --git a/venv/Lib/site-packages/pip/_vendor/cachecontrol/wrapper.py b/venv/Lib/site-packages/pip/_vendor/cachecontrol/wrapper.py new file mode 100644 index 0000000..b6ee7f2 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/cachecontrol/wrapper.py @@ -0,0 +1,33 @@ +# SPDX-FileCopyrightText: 2015 Eric Larson +# +# SPDX-License-Identifier: Apache-2.0 + +from .adapter import CacheControlAdapter +from .cache import DictCache + + +def CacheControl( + sess, + cache=None, + cache_etags=True, + serializer=None, + heuristic=None, + controller_class=None, + adapter_class=None, + cacheable_methods=None, +): + + cache = DictCache() if cache is None else cache + adapter_class = adapter_class or CacheControlAdapter + adapter = adapter_class( + cache, + cache_etags=cache_etags, + serializer=serializer, + heuristic=heuristic, + controller_class=controller_class, + cacheable_methods=cacheable_methods, + ) + sess.mount("http://", adapter) + sess.mount("https://", adapter) + + return sess diff --git a/venv/Lib/site-packages/pip/_vendor/certifi/__init__.py b/venv/Lib/site-packages/pip/_vendor/certifi/__init__.py new file mode 100644 index 0000000..8db1a0e --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/certifi/__init__.py @@ -0,0 +1,3 @@ +from .core import contents, where + +__version__ = "2021.10.08" diff --git a/venv/Lib/site-packages/pip/_vendor/certifi/__main__.py b/venv/Lib/site-packages/pip/_vendor/certifi/__main__.py new file mode 100644 index 0000000..0037634 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/certifi/__main__.py @@ -0,0 +1,12 @@ +import argparse + +from pip._vendor.certifi import contents, where + +parser = argparse.ArgumentParser() +parser.add_argument("-c", "--contents", action="store_true") +args = parser.parse_args() + +if args.contents: + print(contents()) +else: + print(where()) diff --git a/venv/Lib/site-packages/pip/_vendor/certifi/__pycache__/__init__.cpython-39.pyc b/venv/Lib/site-packages/pip/_vendor/certifi/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e6a799455d1393790f5104f34cb83b6822fb4e84 GIT binary patch literal 268 zcmYk0u}TCn5QdZND#yuzrJbFy#V&hS$RTnlTFNzg%@PSQ88Nz>gk(?g-oXd)mC{=I z3RX_K8<>Ci`QV>l&Sq1B^L2Xmw8Hz7&HgYnSGe&6MH5YXGSH3=tYegD))l(ACsp}N z5mzitl(Qq)F{Xo$7YMMMF51PsnYT^5Tvuf(l?xDZXedz9kr3|?qH$J;ZxRkO$ny7i zbHO(e5tr7=$gjP>m80Z$PRX7>z~H$zzTR3d)f?yK0FJDbmahDm#WUF1^3c_ff b4Hv>#GYZl8&osFloZj}Z%DrRmbIkq$Cuv83 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_vendor/certifi/__pycache__/__main__.cpython-39.pyc b/venv/Lib/site-packages/pip/_vendor/certifi/__pycache__/__main__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4e4e35370199e593b11a6c1f8b8a6977d9959c97 GIT binary patch literal 445 zcmYjM!Ait15KYo;x0c;y!4L2z^w2$uh=_}xL_|%Xi^t(Aa7>gB=1ewa2O#QtDW8ZZ<{|{^FMss9NVLBEpWtfiBgwIi7S$l%1b?r z0Ihp(DD}ag2i)U5?(<;fcz@lud+EaW762El7J$w4*6 zL!pS(SDpnknyOh_S&K_|TbZDHrObeFo>`G@W}=RDy*9lLeW?o3ydyPoQVzcEP7dge z)zFj)!8DypdCD3_&+D9(^cpHj?Jh|xB+H+GC-z5BCVTtyLg#wnW^}VB-Rw!TtYU@8 evWa{(;bB$twuB>W&9rk2$(V$Aj6)LO0r>&j3xQ?; literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_vendor/certifi/__pycache__/core.cpython-39.pyc b/venv/Lib/site-packages/pip/_vendor/certifi/__pycache__/core.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..714192390ac07bca966c8f1e4421e546a9d7b3a6 GIT binary patch literal 1536 zcmZux-*4MC5GE9E0rac zq}wJ)_b}%*7_h&DaVj$x}65Ey4SzkIseAmlG} zE)E}@yD-fP7D*;VQpplJp+6AmNq$NsS8VA`yyNc`J>;v3tgPvzs;YWlR%Pv!Olrzo zlHV!p^Amqwp9J&9q(O;fVH0Lc*2}0zB)!dv@{V#!@OeVgFTmeA`m^-qj%>*0DV;QA ztK0z*>=uz*avQR2OZJd-J~~!Gq_m9>;%lO@l_z*-H`5XNWTj{9C4=t_3rnOm>BiOKRW-JvZ4Ue zIDg+CKX#t6+SP>s87M8pWyA^^HvySJ>csaO0c|o@2~8Bo5n?|dSSXAsxa@;riKR>E zuoEWPnfJ%;8}Gzhu{C)_7_j8 zFf2KwD>#8QeN)=}1o*76H`!35vY^r|Ga7FlSCg?uePah4#0ho)Kg{B^LmfT%FC0|I z0Okfxll=<`d>|E=1(Gc=Ko_6~yra%M$X*$`+UDE~82Spt=xeZmMv>`-bVa8X8uiax z{wIhym+5EaCj3EX2kI$g7J(E#0pHaJuOpS?T~fAAO{Fhmou$qLJ(azHJlxfIo@d%7 z@zbtWCR^x8l{L|by#%z4RtuvW_lxL()|u9r{&KMU<=yeE2N4E)gI9fThcn)!ocgTF Sb{MCeHFv>h%}P++s{RAUsZf&u literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_vendor/certifi/cacert.pem b/venv/Lib/site-packages/pip/_vendor/certifi/cacert.pem new file mode 100644 index 0000000..6d0ccc0 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/certifi/cacert.pem @@ -0,0 +1,4362 @@ + +# Issuer: CN=GlobalSign Root CA O=GlobalSign nv-sa OU=Root CA +# Subject: CN=GlobalSign Root CA O=GlobalSign nv-sa OU=Root CA +# Label: "GlobalSign Root CA" +# Serial: 4835703278459707669005204 +# MD5 Fingerprint: 3e:45:52:15:09:51:92:e1:b7:5d:37:9f:b1:87:29:8a +# SHA1 Fingerprint: b1:bc:96:8b:d4:f4:9d:62:2a:a8:9a:81:f2:15:01:52:a4:1d:82:9c +# SHA256 Fingerprint: eb:d4:10:40:e4:bb:3e:c7:42:c9:e3:81:d3:1e:f2:a4:1a:48:b6:68:5c:96:e7:ce:f3:c1:df:6c:d4:33:1c:99 +-----BEGIN CERTIFICATE----- +MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG +A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv +b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw +MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i +YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT +aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ +jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp +xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp +1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG +snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ +U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8 +9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E +BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B +AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz +yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE +38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP +AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad +DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME +HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A== +-----END CERTIFICATE----- + +# Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R2 +# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R2 +# Label: "GlobalSign Root CA - R2" +# Serial: 4835703278459682885658125 +# MD5 Fingerprint: 94:14:77:7e:3e:5e:fd:8f:30:bd:41:b0:cf:e7:d0:30 +# SHA1 Fingerprint: 75:e0:ab:b6:13:85:12:27:1c:04:f8:5f:dd:de:38:e4:b7:24:2e:fe +# SHA256 Fingerprint: ca:42:dd:41:74:5f:d0:b8:1e:b9:02:36:2c:f9:d8:bf:71:9d:a1:bd:1b:1e:fc:94:6f:5b:4c:99:f4:2c:1b:9e +-----BEGIN CERTIFICATE----- +MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4G +A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNp +Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1 +MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMjETMBEG +A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6ErPL +v4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8 +eoLrvozps6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklq +tTleiDTsvHgMCJiEbKjNS7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzd +C9XZzPnqJworc5HGnRusyMvo4KD0L5CLTfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pa +zq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6CygPCm48CAwEAAaOBnDCB +mTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUm+IH +V2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5n +bG9iYWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG +3lm0mi3f3BmGLjANBgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4Gs +J0/WwbgcQ3izDJr86iw8bmEbTUsp9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO +291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu01yiPqFbQfXf5WRDLenVOavS +ot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG79G+dwfCMNYxd +AfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7 +TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg== +-----END CERTIFICATE----- + +# Issuer: CN=Entrust.net Certification Authority (2048) O=Entrust.net OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.)/(c) 1999 Entrust.net Limited +# Subject: CN=Entrust.net Certification Authority (2048) O=Entrust.net OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.)/(c) 1999 Entrust.net Limited +# Label: "Entrust.net Premium 2048 Secure Server CA" +# Serial: 946069240 +# MD5 Fingerprint: ee:29:31:bc:32:7e:9a:e6:e8:b5:f7:51:b4:34:71:90 +# SHA1 Fingerprint: 50:30:06:09:1d:97:d4:f5:ae:39:f7:cb:e7:92:7d:7d:65:2d:34:31 +# SHA256 Fingerprint: 6d:c4:71:72:e0:1c:bc:b0:bf:62:58:0d:89:5f:e2:b8:ac:9a:d4:f8:73:80:1e:0c:10:b9:c8:37:d2:1e:b1:77 +-----BEGIN CERTIFICATE----- +MIIEKjCCAxKgAwIBAgIEOGPe+DANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChML +RW50cnVzdC5uZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBp +bmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5 +IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNVBAMTKkVudHJ1c3QubmV0IENlcnRp +ZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQxNzUwNTFaFw0yOTA3 +MjQxNDE1MTJaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3d3d3 +LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxp +YWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEG +A1UEAxMqRW50cnVzdC5uZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgp +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArU1LqRKGsuqjIAcVFmQq +K0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOLGp18EzoOH1u3Hs/lJBQe +sYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSrhRSGlVuX +MlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVT +XTzWnLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/ +HoZdenoVve8AjhUiVBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH +4QIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV +HQ4EFgQUVeSB0RGAvtiJuQijMfmhJAkWuXAwDQYJKoZIhvcNAQEFBQADggEBADub +j1abMOdTmXx6eadNl9cZlZD7Bh/KM3xGY4+WZiT6QBshJ8rmcnPyT/4xmf3IDExo +U8aAghOY+rat2l098c5u9hURlIIM7j+VrxGrD9cv3h8Dj1csHsm7mhpElesYT6Yf +zX1XEC+bBAlahLVu2B064dae0Wx5XnkcFMXj0EyTO2U87d89vqbllRrDtRnDvV5b +u/8j72gZyxKTJ1wDLW8w0B62GqzeWvfRqqgnpv55gcR5mTNXuhKwqeBCbJPKVt7+ +bYQLCIt+jerXmCHG8+c8eS9enNFMFY3h7CI3zJpDC5fcgJCNs2ebb0gIFVbPv/Er +fF6adulZkMV8gzURZVE= +-----END CERTIFICATE----- + +# Issuer: CN=Baltimore CyberTrust Root O=Baltimore OU=CyberTrust +# Subject: CN=Baltimore CyberTrust Root O=Baltimore OU=CyberTrust +# Label: "Baltimore CyberTrust Root" +# Serial: 33554617 +# MD5 Fingerprint: ac:b6:94:a5:9c:17:e0:d7:91:52:9b:b1:97:06:a6:e4 +# SHA1 Fingerprint: d4:de:20:d0:5e:66:fc:53:fe:1a:50:88:2c:78:db:28:52:ca:e4:74 +# SHA256 Fingerprint: 16:af:57:a9:f6:76:b0:ab:12:60:95:aa:5e:ba:de:f2:2a:b3:11:19:d6:44:ac:95:cd:4b:93:db:f3:f2:6a:eb +-----BEGIN CERTIFICATE----- +MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ +RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD +VQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoX +DTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9y +ZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVy +VHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKr +mD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjr +IZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeK +mpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSu +XmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZy +dc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/ye +jl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1 +BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3 +DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT92 +9hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3Wgx +jkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0 +Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67G7fyUIhz +ksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS +R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp +-----END CERTIFICATE----- + +# Issuer: CN=Entrust Root Certification Authority O=Entrust, Inc. OU=www.entrust.net/CPS is incorporated by reference/(c) 2006 Entrust, Inc. +# Subject: CN=Entrust Root Certification Authority O=Entrust, Inc. OU=www.entrust.net/CPS is incorporated by reference/(c) 2006 Entrust, Inc. +# Label: "Entrust Root Certification Authority" +# Serial: 1164660820 +# MD5 Fingerprint: d6:a5:c3:ed:5d:dd:3e:00:c1:3d:87:92:1f:1d:3f:e4 +# SHA1 Fingerprint: b3:1e:b1:b7:40:e3:6c:84:02:da:dc:37:d4:4d:f5:d4:67:49:52:f9 +# SHA256 Fingerprint: 73:c1:76:43:4f:1b:c6:d5:ad:f4:5b:0e:76:e7:27:28:7c:8d:e5:76:16:c1:e6:e6:14:1a:2b:2c:bc:7d:8e:4c +-----BEGIN CERTIFICATE----- +MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMC +VVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0 +Lm5ldC9DUFMgaXMgaW5jb3Jwb3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMW +KGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsGA1UEAxMkRW50cnVzdCBSb290IENl +cnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0MloXDTI2MTEyNzIw +NTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMTkw +NwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSBy +ZWZlcmVuY2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNV +BAMTJEVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJ +KoZIhvcNAQEBBQADggEPADCCAQoCggEBALaVtkNC+sZtKm9I35RMOVcF7sN5EUFo +Nu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYszA9u3g3s+IIRe7bJWKKf4 +4LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOwwCj0Yzfv9 +KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGI +rb68j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi +94DkZfs0Nw4pgHBNrziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOB +sDCBrTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAi +gA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1MzQyWjAfBgNVHSMEGDAWgBRo +kORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DHhmak8fdLQ/uE +vW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA +A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9t +O1KzKtvn1ISMY/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6Zua +AGAT/3B+XxFNSRuzFVJ7yVTav52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP +9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTSW3iDVuycNsMm4hH2Z0kdkquM++v/ +eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0tHuu2guQOHXvgR1m +0vdXcDazv/wor3ElhVsT/h5/WrQ8 +-----END CERTIFICATE----- + +# Issuer: CN=AAA Certificate Services O=Comodo CA Limited +# Subject: CN=AAA Certificate Services O=Comodo CA Limited +# Label: "Comodo AAA Services root" +# Serial: 1 +# MD5 Fingerprint: 49:79:04:b0:eb:87:19:ac:47:b0:bc:11:51:9b:74:d0 +# SHA1 Fingerprint: d1:eb:23:a4:6d:17:d6:8f:d9:25:64:c2:f1:f1:60:17:64:d8:e3:49 +# SHA256 Fingerprint: d7:a7:a0:fb:5d:7e:27:31:d7:71:e9:48:4e:bc:de:f7:1d:5f:0c:3e:0a:29:48:78:2b:c8:3e:e0:ea:69:9e:f4 +-----BEGIN CERTIFICATE----- +MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEb +MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow +GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmlj +YXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAwMFoXDTI4MTIzMTIzNTk1OVowezEL +MAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE +BwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNVBAMM +GEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEP +ADCCAQoCggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQua +BtDFcCLNSS1UY8y2bmhGC1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe +3M/vg4aijJRPn2jymJBGhCfHdr/jzDUsi14HZGWCwEiwqJH5YZ92IFCokcdmtet4 +YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszWY19zjNoFmag4qMsXeDZR +rOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjHYpy+g8cm +ez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQU +oBEKIz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF +MAMBAf8wewYDVR0fBHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20v +QUFBQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29t +b2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2VzLmNybDANBgkqhkiG9w0BAQUF +AAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm7l3sAg9g1o1Q +GE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz +Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2 +G9w84FoVxp7Z8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsi +l2D4kF501KKaU73yqWjgom7C12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3 +smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg== +-----END CERTIFICATE----- + +# Issuer: CN=QuoVadis Root CA 2 O=QuoVadis Limited +# Subject: CN=QuoVadis Root CA 2 O=QuoVadis Limited +# Label: "QuoVadis Root CA 2" +# Serial: 1289 +# MD5 Fingerprint: 5e:39:7b:dd:f8:ba:ec:82:e9:ac:62:ba:0c:54:00:2b +# SHA1 Fingerprint: ca:3a:fb:cf:12:40:36:4b:44:b2:16:20:88:80:48:39:19:93:7c:f7 +# SHA256 Fingerprint: 85:a0:dd:7d:d7:20:ad:b7:ff:05:f8:3d:54:2b:20:9d:c7:ff:45:28:f7:d6:77:b1:83:89:fe:a5:e5:c4:9e:86 +-----BEGIN CERTIFICATE----- +MIIFtzCCA5+gAwIBAgICBQkwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0x +GTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJv +b3QgQ0EgMjAeFw0wNjExMjQxODI3MDBaFw0zMTExMjQxODIzMzNaMEUxCzAJBgNV +BAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9W +YWRpcyBSb290IENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCa +GMpLlA0ALa8DKYrwD4HIrkwZhR0In6spRIXzL4GtMh6QRr+jhiYaHv5+HBg6XJxg +Fyo6dIMzMH1hVBHL7avg5tKifvVrbxi3Cgst/ek+7wrGsxDp3MJGF/hd/aTa/55J +WpzmM+Yklvc/ulsrHHo1wtZn/qtmUIttKGAr79dgw8eTvI02kfN/+NsRE8Scd3bB +rrcCaoF6qUWD4gXmuVbBlDePSHFjIuwXZQeVikvfj8ZaCuWw419eaxGrDPmF60Tp ++ARz8un+XJiM9XOva7R+zdRcAitMOeGylZUtQofX1bOQQ7dsE/He3fbE+Ik/0XX1 +ksOR1YqI0JDs3G3eicJlcZaLDQP9nL9bFqyS2+r+eXyt66/3FsvbzSUr5R/7mp/i +Ucw6UwxI5g69ybR2BlLmEROFcmMDBOAENisgGQLodKcftslWZvB1JdxnwQ5hYIiz +PtGo/KPaHbDRsSNU30R2be1B2MGyIrZTHN81Hdyhdyox5C315eXbyOD/5YDXC2Og +/zOhD7osFRXql7PSorW+8oyWHhqPHWykYTe5hnMz15eWniN9gqRMgeKh0bpnX5UH +oycR7hYQe7xFSkyyBNKr79X9DFHOUGoIMfmR2gyPZFwDwzqLID9ujWc9Otb+fVuI +yV77zGHcizN300QyNQliBJIWENieJ0f7OyHj+OsdWwIDAQABo4GwMIGtMA8GA1Ud +EwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1UdDgQWBBQahGK8SEwzJQTU7tD2 +A8QZRtGUazBuBgNVHSMEZzBlgBQahGK8SEwzJQTU7tD2A8QZRtGUa6FJpEcwRTEL +MAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMT +ElF1b1ZhZGlzIFJvb3QgQ0EgMoICBQkwDQYJKoZIhvcNAQEFBQADggIBAD4KFk2f +BluornFdLwUvZ+YTRYPENvbzwCYMDbVHZF34tHLJRqUDGCdViXh9duqWNIAXINzn +g/iN/Ae42l9NLmeyhP3ZRPx3UIHmfLTJDQtyU/h2BwdBR5YM++CCJpNVjP4iH2Bl +fF/nJrP3MpCYUNQ3cVX2kiF495V5+vgtJodmVjB3pjd4M1IQWK4/YY7yarHvGH5K +WWPKjaJW1acvvFYfzznB4vsKqBUsfU16Y8Zsl0Q80m/DShcK+JDSV6IZUaUtl0Ha +B0+pUNqQjZRG4T7wlP0QADj1O+hA4bRuVhogzG9Yje0uRY/W6ZM/57Es3zrWIozc +hLsib9D45MY56QSIPMO661V6bYCZJPVsAfv4l7CUW+v90m/xd2gNNWQjrLhVoQPR +TUIZ3Ph1WVaj+ahJefivDrkRoHy3au000LYmYjgahwz46P0u05B/B5EqHdZ+XIWD +mbA4CD/pXvk1B+TJYm5Xf6dQlfe6yJvmjqIBxdZmv3lh8zwc4bmCXF2gw+nYSL0Z +ohEUGW6yhhtoPkg3Goi3XZZenMfvJ2II4pEZXNLxId26F0KCl3GBUzGpn/Z9Yr9y +4aOTHcyKJloJONDO1w2AFrR4pTqHTI2KpdVGl/IsELm8VCLAAVBpQ570su9t+Oza +8eOx79+Rj1QqCyXBJhnEUhAFZdWCEOrCMc0u +-----END CERTIFICATE----- + +# Issuer: CN=QuoVadis Root CA 3 O=QuoVadis Limited +# Subject: CN=QuoVadis Root CA 3 O=QuoVadis Limited +# Label: "QuoVadis Root CA 3" +# Serial: 1478 +# MD5 Fingerprint: 31:85:3c:62:94:97:63:b9:aa:fd:89:4e:af:6f:e0:cf +# SHA1 Fingerprint: 1f:49:14:f7:d8:74:95:1d:dd:ae:02:c0:be:fd:3a:2d:82:75:51:85 +# SHA256 Fingerprint: 18:f1:fc:7f:20:5d:f8:ad:dd:eb:7f:e0:07:dd:57:e3:af:37:5a:9c:4d:8d:73:54:6b:f4:f1:fe:d1:e1:8d:35 +-----BEGIN CERTIFICATE----- +MIIGnTCCBIWgAwIBAgICBcYwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0x +GTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJv +b3QgQ0EgMzAeFw0wNjExMjQxOTExMjNaFw0zMTExMjQxOTA2NDRaMEUxCzAJBgNV +BAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9W +YWRpcyBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDM +V0IWVJzmmNPTTe7+7cefQzlKZbPoFog02w1ZkXTPkrgEQK0CSzGrvI2RaNggDhoB +4hp7Thdd4oq3P5kazethq8Jlph+3t723j/z9cI8LoGe+AaJZz3HmDyl2/7FWeUUr +H556VOijKTVopAFPD6QuN+8bv+OPEKhyq1hX51SGyMnzW9os2l2ObjyjPtr7guXd +8lyyBTNvijbO0BNO/79KDDRMpsMhvVAEVeuxu537RR5kFd5VAYwCdrXLoT9Cabwv +vWhDFlaJKjdhkf2mrk7AyxRllDdLkgbvBNDInIjbC3uBr7E9KsRlOni27tyAsdLT +mZw67mtaa7ONt9XOnMK+pUsvFrGeaDsGb659n/je7Mwpp5ijJUMv7/FfJuGITfhe +btfZFG4ZM2mnO4SJk8RTVROhUXhA+LjJou57ulJCg54U7QVSWllWp5f8nT8KKdjc +T5EOE7zelaTfi5m+rJsziO+1ga8bxiJTyPbH7pcUsMV8eFLI8M5ud2CEpukqdiDt +WAEXMJPpGovgc2PZapKUSU60rUqFxKMiMPwJ7Wgic6aIDFUhWMXhOp8q3crhkODZ +c6tsgLjoC2SToJyMGf+z0gzskSaHirOi4XCPLArlzW1oUevaPwV/izLmE1xr/l9A +4iLItLRkT9a6fUg+qGkM17uGcclzuD87nSVL2v9A6wIDAQABo4IBlTCCAZEwDwYD +VR0TAQH/BAUwAwEB/zCB4QYDVR0gBIHZMIHWMIHTBgkrBgEEAb5YAAMwgcUwgZMG +CCsGAQUFBwICMIGGGoGDQW55IHVzZSBvZiB0aGlzIENlcnRpZmljYXRlIGNvbnN0 +aXR1dGVzIGFjY2VwdGFuY2Ugb2YgdGhlIFF1b1ZhZGlzIFJvb3QgQ0EgMyBDZXJ0 +aWZpY2F0ZSBQb2xpY3kgLyBDZXJ0aWZpY2F0aW9uIFByYWN0aWNlIFN0YXRlbWVu +dC4wLQYIKwYBBQUHAgEWIWh0dHA6Ly93d3cucXVvdmFkaXNnbG9iYWwuY29tL2Nw +czALBgNVHQ8EBAMCAQYwHQYDVR0OBBYEFPLAE+CCQz777i9nMpY1XNu4ywLQMG4G +A1UdIwRnMGWAFPLAE+CCQz777i9nMpY1XNu4ywLQoUmkRzBFMQswCQYDVQQGEwJC +TTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDEbMBkGA1UEAxMSUXVvVmFkaXMg +Um9vdCBDQSAzggIFxjANBgkqhkiG9w0BAQUFAAOCAgEAT62gLEz6wPJv92ZVqyM0 +7ucp2sNbtrCD2dDQ4iH782CnO11gUyeim/YIIirnv6By5ZwkajGxkHon24QRiSem +d1o417+shvzuXYO8BsbRd2sPbSQvS3pspweWyuOEn62Iix2rFo1bZhfZFvSLgNLd ++LJ2w/w4E6oM3kJpK27zPOuAJ9v1pkQNn1pVWQvVDVJIxa6f8i+AxeoyUDUSly7B +4f/xI4hROJ/yZlZ25w9Rl6VSDE1JUZU2Pb+iSwwQHYaZTKrzchGT5Or2m9qoXadN +t54CrnMAyNojA+j56hl0YgCUyyIgvpSnWbWCar6ZeXqp8kokUvd0/bpO5qgdAm6x +DYBEwa7TIzdfu4V8K5Iu6H6li92Z4b8nby1dqnuH/grdS/yO9SbkbnBCbjPsMZ57 +k8HkyWkaPcBrTiJt7qtYTcbQQcEr6k8Sh17rRdhs9ZgC06DYVYoGmRmioHfRMJ6s +zHXug/WwYjnPbFfiTNKRCw51KBuav/0aQ/HKd/s7j2G4aSgWQgRecCocIdiP4b0j +Wy10QJLZYxkNc91pvGJHvOB0K7Lrfb5BG7XARsWhIstfTsEokt4YutUqKLsRixeT +mJlglFwjz1onl14LBQaTNx47aTbrqZ5hHY8y2o4M1nQ+ewkk2gF3R8Q7zTSMmfXK +4SVhM7JZG+Ju1zdXtg2pEto= +-----END CERTIFICATE----- + +# Issuer: O=SECOM Trust.net OU=Security Communication RootCA1 +# Subject: O=SECOM Trust.net OU=Security Communication RootCA1 +# Label: "Security Communication Root CA" +# Serial: 0 +# MD5 Fingerprint: f1:bc:63:6a:54:e0:b5:27:f5:cd:e7:1a:e3:4d:6e:4a +# SHA1 Fingerprint: 36:b1:2b:49:f9:81:9e:d7:4c:9e:bc:38:0f:c6:56:8f:5d:ac:b2:f7 +# SHA256 Fingerprint: e7:5e:72:ed:9f:56:0e:ec:6e:b4:80:00:73:a4:3f:c3:ad:19:19:5a:39:22:82:01:78:95:97:4a:99:02:6b:6c +-----BEGIN CERTIFICATE----- +MIIDWjCCAkKgAwIBAgIBADANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJKUDEY +MBYGA1UEChMPU0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21t +dW5pY2F0aW9uIFJvb3RDQTEwHhcNMDMwOTMwMDQyMDQ5WhcNMjMwOTMwMDQyMDQ5 +WjBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMPU0VDT00gVHJ1c3QubmV0MScwJQYD +VQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEwggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQCzs/5/022x7xZ8V6UMbXaKL0u/ZPtM7orw8yl8 +9f/uKuDp6bpbZCKamm8sOiZpUQWZJtzVHGpxxpp9Hp3dfGzGjGdnSj74cbAZJ6kJ +DKaVv0uMDPpVmDvY6CKhS3E4eayXkmmziX7qIWgGmBSWh9JhNrxtJ1aeV+7AwFb9 +Ms+k2Y7CI9eNqPPYJayX5HA49LY6tJ07lyZDo6G8SVlyTCMwhwFY9k6+HGhWZq/N +QV3Is00qVUarH9oe4kA92819uZKAnDfdDJZkndwi92SL32HeFZRSFaB9UslLqCHJ +xrHty8OVYNEP8Ktw+N/LTX7s1vqr2b1/VPKl6Xn62dZ2JChzAgMBAAGjPzA9MB0G +A1UdDgQWBBSgc0mZaNyFW2XjmygvV5+9M7wHSDALBgNVHQ8EBAMCAQYwDwYDVR0T +AQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAaECpqLvkT115swW1F7NgE+vG +kl3g0dNq/vu+m22/xwVtWSDEHPC32oRYAmP6SBbvT6UL90qY8j+eG61Ha2POCEfr +Uj94nK9NrvjVT8+amCoQQTlSxN3Zmw7vkwGusi7KaEIkQmywszo+zenaSMQVy+n5 +Bw+SUEmK3TGXX8npN6o7WWWXlDLJs58+OmJYxUmtYg5xpTKqL8aJdkNAExNnPaJU +JRDL8Try2frbSVa7pv6nQTXD4IhhyYjH3zYQIphZ6rBK+1YWc26sTfcioU+tHXot +RSflMMFe8toTyyVCUZVHA4xsIcx0Qu1T/zOLjw9XARYvz6buyXAiFL39vmwLAw== +-----END CERTIFICATE----- + +# Issuer: CN=XRamp Global Certification Authority O=XRamp Security Services Inc OU=www.xrampsecurity.com +# Subject: CN=XRamp Global Certification Authority O=XRamp Security Services Inc OU=www.xrampsecurity.com +# Label: "XRamp Global CA Root" +# Serial: 107108908803651509692980124233745014957 +# MD5 Fingerprint: a1:0b:44:b3:ca:10:d8:00:6e:9d:0f:d8:0f:92:0a:d1 +# SHA1 Fingerprint: b8:01:86:d1:eb:9c:86:a5:41:04:cf:30:54:f3:4c:52:b7:e5:58:c6 +# SHA256 Fingerprint: ce:cd:dc:90:50:99:d8:da:df:c5:b1:d2:09:b7:37:cb:e2:c1:8c:fb:2c:10:c0:ff:0b:cf:0d:32:86:fc:1a:a2 +-----BEGIN CERTIFICATE----- +MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCB +gjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEk +MCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRY +UmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQxMTAxMTcx +NDA0WhcNMzUwMTAxMDUzNzE5WjCBgjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3 +dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2Vy +dmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBB +dXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCYJB69FbS6 +38eMpSe2OAtp87ZOqCwuIR1cRN8hXX4jdP5efrRKt6atH67gBhbim1vZZ3RrXYCP +KZ2GG9mcDZhtdhAoWORlsH9KmHmf4MMxfoArtYzAQDsRhtDLooY2YKTVMIJt2W7Q +DxIEM5dfT2Fa8OT5kavnHTu86M/0ay00fOJIYRyO82FEzG+gSqmUsE3a56k0enI4 +qEHMPJQRfevIpoy3hsvKMzvZPTeL+3o+hiznc9cKV6xkmxnr9A8ECIqsAxcZZPRa +JSKNNCyy9mgdEm3Tih4U2sSPpuIjhdV6Db1q4Ons7Be7QhtnqiXtRYMh/MHJfNVi +PvryxS3T/dRlAgMBAAGjgZ8wgZwwEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0P +BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFMZPoj0GY4QJnM5i5ASs +jVy16bYbMDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly9jcmwueHJhbXBzZWN1cml0 +eS5jb20vWEdDQS5jcmwwEAYJKwYBBAGCNxUBBAMCAQEwDQYJKoZIhvcNAQEFBQAD +ggEBAJEVOQMBG2f7Shz5CmBbodpNl2L5JFMn14JkTpAuw0kbK5rc/Kh4ZzXxHfAR +vbdI4xD2Dd8/0sm2qlWkSLoC295ZLhVbO50WfUfXN+pfTXYSNrsf16GBBEYgoyxt +qZ4Bfj8pzgCT3/3JknOJiWSe5yvkHJEs0rnOfc5vMZnT5r7SHpDwCRR5XCOrTdLa +IR9NmXmd4c8nnxCbHIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSy +i6mx5O+aGtA9aZnuqCij4Tyz8LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQ +O+7ETPTsJ3xCwnR8gooJybQDJbw= +-----END CERTIFICATE----- + +# Issuer: O=The Go Daddy Group, Inc. OU=Go Daddy Class 2 Certification Authority +# Subject: O=The Go Daddy Group, Inc. OU=Go Daddy Class 2 Certification Authority +# Label: "Go Daddy Class 2 CA" +# Serial: 0 +# MD5 Fingerprint: 91:de:06:25:ab:da:fd:32:17:0c:bb:25:17:2a:84:67 +# SHA1 Fingerprint: 27:96:ba:e6:3f:18:01:e2:77:26:1b:a0:d7:77:70:02:8f:20:ee:e4 +# SHA256 Fingerprint: c3:84:6b:f2:4b:9e:93:ca:64:27:4c:0e:c6:7c:1e:cc:5e:02:4f:fc:ac:d2:d7:40:19:35:0e:81:fe:54:6a:e4 +-----BEGIN CERTIFICATE----- +MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEh +MB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBE +YWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3 +MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkGA1UEBhMCVVMxITAfBgNVBAoTGFRo +ZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28gRGFkZHkgQ2xhc3Mg +MiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQADggEN +ADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCA +PVYYYwhv2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6w +wdhFJ2+qN1j3hybX2C32qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXi +EqITLdiOr18SPaAIBQi2XKVlOARFmR6jYGB0xUGlcmIbYsUfb18aQr4CUWWoriMY +avx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmYvLEHZ6IVDd2gWMZEewo+ +YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0OBBYEFNLE +sNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h +/t2oatTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5 +IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmlj +YXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD +ggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wimPQoZ+YeAEW5p5JYXMP80kWNy +OO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKtI3lpjbi2Tc7P +TMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ +HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mER +dEr/VxqHD3VILs9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5Cuf +ReYNnyicsbkqWletNw+vHX/bvZ8= +-----END CERTIFICATE----- + +# Issuer: O=Starfield Technologies, Inc. OU=Starfield Class 2 Certification Authority +# Subject: O=Starfield Technologies, Inc. OU=Starfield Class 2 Certification Authority +# Label: "Starfield Class 2 CA" +# Serial: 0 +# MD5 Fingerprint: 32:4a:4b:bb:c8:63:69:9b:be:74:9a:c6:dd:1d:46:24 +# SHA1 Fingerprint: ad:7e:1c:28:b0:64:ef:8f:60:03:40:20:14:c3:d0:e3:37:0e:b5:8a +# SHA256 Fingerprint: 14:65:fa:20:53:97:b8:76:fa:a6:f0:a9:95:8e:55:90:e4:0f:cc:7f:aa:4f:b7:c2:c8:67:75:21:fb:5f:b6:58 +-----BEGIN CERTIFICATE----- +MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzEl +MCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMp +U3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQw +NjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBoMQswCQYDVQQGEwJVUzElMCMGA1UE +ChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZp +ZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqGSIb3 +DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf +8MOh2tTYbitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN ++lq2cwQlZut3f+dZxkqZJRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0 +X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVmepsZGD3/cVE8MC5fvj13c7JdBmzDI1aa +K4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSNF4Azbl5KXZnJHoe0nRrA +1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HFMIHCMB0G +A1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fR +zt0fhvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0 +YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBD +bGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8w +DQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGsafPzWdqbAYcaT1epoXkJKtv3 +L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLMPUxA2IGvd56D +eruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl +xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynp +VSJYACPq4xJDKVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEY +WQPJIrSPnNVeKtelttQKbfi3QBFGmh95DmK/D5fs4C8fF5Q= +-----END CERTIFICATE----- + +# Issuer: CN=DigiCert Assured ID Root CA O=DigiCert Inc OU=www.digicert.com +# Subject: CN=DigiCert Assured ID Root CA O=DigiCert Inc OU=www.digicert.com +# Label: "DigiCert Assured ID Root CA" +# Serial: 17154717934120587862167794914071425081 +# MD5 Fingerprint: 87:ce:0b:7b:2a:0e:49:00:e1:58:71:9b:37:a8:93:72 +# SHA1 Fingerprint: 05:63:b8:63:0d:62:d7:5a:bb:c8:ab:1e:4b:df:b5:a8:99:b2:4d:43 +# SHA256 Fingerprint: 3e:90:99:b5:01:5e:8f:48:6c:00:bc:ea:9d:11:1e:e7:21:fa:ba:35:5a:89:bc:f1:df:69:56:1e:3d:c6:32:5c +-----BEGIN CERTIFICATE----- +MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBl +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv +b3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzExMTEwMDAwMDAwWjBlMQswCQYDVQQG +EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl +cnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7c +JpSIqvTO9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYP +mDI2dsze3Tyoou9q+yHyUmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+ +wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW/lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4 +VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpyoeb6pNnVFzF1roV9Iq4/ +AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whfGHdPAgMB +AAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW +BBRF66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYun +pyGd823IDzANBgkqhkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRC +dWKuh+vy1dneVrOfzM4UKLkNl2BcEkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTf +fwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38FnSbNd67IJKusm7Xi+fT8r87cm +NW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i8b5QZ7dsvfPx +H2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe ++o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g== +-----END CERTIFICATE----- + +# Issuer: CN=DigiCert Global Root CA O=DigiCert Inc OU=www.digicert.com +# Subject: CN=DigiCert Global Root CA O=DigiCert Inc OU=www.digicert.com +# Label: "DigiCert Global Root CA" +# Serial: 10944719598952040374951832963794454346 +# MD5 Fingerprint: 79:e4:a9:84:0d:7d:3a:96:d7:c0:4f:e2:43:4c:89:2e +# SHA1 Fingerprint: a8:98:5d:3a:65:e5:e5:c4:b2:d7:d6:6d:40:c6:dd:2f:b1:9c:54:36 +# SHA256 Fingerprint: 43:48:a0:e9:44:4c:78:cb:26:5e:05:8d:5e:89:44:b4:d8:4f:96:62:bd:26:db:25:7f:89:34:a4:43:c7:01:61 +-----BEGIN CERTIFICATE----- +MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD +QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT +MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j +b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB +CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97 +nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt +43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P +T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4 +gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO +BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR +TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw +DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr +hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg +06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF +PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls +YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk +CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4= +-----END CERTIFICATE----- + +# Issuer: CN=DigiCert High Assurance EV Root CA O=DigiCert Inc OU=www.digicert.com +# Subject: CN=DigiCert High Assurance EV Root CA O=DigiCert Inc OU=www.digicert.com +# Label: "DigiCert High Assurance EV Root CA" +# Serial: 3553400076410547919724730734378100087 +# MD5 Fingerprint: d4:74:de:57:5c:39:b2:d3:9c:85:83:c5:c0:65:49:8a +# SHA1 Fingerprint: 5f:b7:ee:06:33:e2:59:db:ad:0c:4c:9a:e6:d3:8f:1a:61:c7:dc:25 +# SHA256 Fingerprint: 74:31:e5:f4:c3:c1:ce:46:90:77:4f:0b:61:e0:54:40:88:3b:a9:a0:1e:d0:0b:a6:ab:d7:80:6e:d3:b1:18:cf +-----BEGIN CERTIFICATE----- +MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j +ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL +MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3 +LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug +RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm ++9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW +PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM +xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB +Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3 +hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg +EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF +MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA +FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec +nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z +eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF +hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2 +Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe +vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep ++OkuE6N36B9K +-----END CERTIFICATE----- + +# Issuer: CN=DST Root CA X3 O=Digital Signature Trust Co. +# Subject: CN=DST Root CA X3 O=Digital Signature Trust Co. +# Label: "DST Root CA X3" +# Serial: 91299735575339953335919266965803778155 +# MD5 Fingerprint: 41:03:52:dc:0f:f7:50:1b:16:f0:02:8e:ba:6f:45:c5 +# SHA1 Fingerprint: da:c9:02:4f:54:d8:f6:df:94:93:5f:b1:73:26:38:ca:6a:d7:7c:13 +# SHA256 Fingerprint: 06:87:26:03:31:a7:24:03:d9:09:f1:05:e6:9b:cf:0d:32:e1:bd:24:93:ff:c6:d9:20:6d:11:bc:d6:77:07:39 +-----BEGIN CERTIFICATE----- +MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/ +MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT +DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow +PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD +Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O +rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq +OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b +xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw +7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD +aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV +HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG +SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69 +ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr +AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz +R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5 +JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo +Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ +-----END CERTIFICATE----- + +# Issuer: CN=SwissSign Gold CA - G2 O=SwissSign AG +# Subject: CN=SwissSign Gold CA - G2 O=SwissSign AG +# Label: "SwissSign Gold CA - G2" +# Serial: 13492815561806991280 +# MD5 Fingerprint: 24:77:d9:a8:91:d1:3b:fa:88:2d:c2:ff:f8:cd:33:93 +# SHA1 Fingerprint: d8:c5:38:8a:b7:30:1b:1b:6e:d4:7a:e6:45:25:3a:6f:9f:1a:27:61 +# SHA256 Fingerprint: 62:dd:0b:e9:b9:f5:0a:16:3e:a0:f8:e7:5c:05:3b:1e:ca:57:ea:55:c8:68:8f:64:7c:68:81:f2:c8:35:7b:95 +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- + +# Issuer: CN=SwissSign Silver CA - G2 O=SwissSign AG +# Subject: CN=SwissSign Silver CA - G2 O=SwissSign AG +# Label: "SwissSign Silver CA - G2" +# Serial: 5700383053117599563 +# MD5 Fingerprint: e0:06:a1:c9:7d:cf:c9:fc:0d:c0:56:75:96:d8:62:13 +# SHA1 Fingerprint: 9b:aa:e5:9f:56:ee:21:cb:43:5a:be:25:93:df:a7:f0:40:d1:1d:cb +# SHA256 Fingerprint: be:6c:4d:a2:bb:b9:ba:59:b6:f3:93:97:68:37:42:46:c3:c0:05:99:3f:a9:8f:02:0d:1d:ed:be:d4:8a:81:d5 +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- + +# Issuer: CN=SecureTrust CA O=SecureTrust Corporation +# Subject: CN=SecureTrust CA O=SecureTrust Corporation +# Label: "SecureTrust CA" +# Serial: 17199774589125277788362757014266862032 +# MD5 Fingerprint: dc:32:c3:a7:6d:25:57:c7:68:09:9d:ea:2d:a9:a2:d1 +# SHA1 Fingerprint: 87:82:c6:c3:04:35:3b:cf:d2:96:92:d2:59:3e:7d:44:d9:34:ff:11 +# SHA256 Fingerprint: f1:c1:b5:0a:e5:a2:0d:d8:03:0e:c9:f6:bc:24:82:3d:d3:67:b5:25:57:59:b4:e7:1b:61:fc:e9:f7:37:5d:73 +-----BEGIN CERTIFICATE----- +MIIDuDCCAqCgAwIBAgIQDPCOXAgWpa1Cf/DrJxhZ0DANBgkqhkiG9w0BAQUFADBI +MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24x +FzAVBgNVBAMTDlNlY3VyZVRydXN0IENBMB4XDTA2MTEwNzE5MzExOFoXDTI5MTIz +MTE5NDA1NVowSDELMAkGA1UEBhMCVVMxIDAeBgNVBAoTF1NlY3VyZVRydXN0IENv +cnBvcmF0aW9uMRcwFQYDVQQDEw5TZWN1cmVUcnVzdCBDQTCCASIwDQYJKoZIhvcN +AQEBBQADggEPADCCAQoCggEBAKukgeWVzfX2FI7CT8rU4niVWJxB4Q2ZQCQXOZEz +Zum+4YOvYlyJ0fwkW2Gz4BERQRwdbvC4u/jep4G6pkjGnx29vo6pQT64lO0pGtSO +0gMdA+9tDWccV9cGrcrI9f4Or2YlSASWC12juhbDCE/RRvgUXPLIXgGZbf2IzIao +wW8xQmxSPmjL8xk037uHGFaAJsTQ3MBv396gwpEWoGQRS0S8Hvbn+mPeZqx2pHGj +7DaUaHp3pLHnDi+BeuK1cobvomuL8A/b01k/unK8RCSc43Oz969XL0Imnal0ugBS +8kvNU3xHCzaFDmapCJcWNFfBZveA4+1wVMeT4C4oFVmHursCAwEAAaOBnTCBmjAT +BgkrBgEEAYI3FAIEBh4EAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB +/zAdBgNVHQ4EFgQUQjK2FvoE/f5dS3rD/fdMQB1aQ68wNAYDVR0fBC0wKzApoCeg +JYYjaHR0cDovL2NybC5zZWN1cmV0cnVzdC5jb20vU1RDQS5jcmwwEAYJKwYBBAGC +NxUBBAMCAQAwDQYJKoZIhvcNAQEFBQADggEBADDtT0rhWDpSclu1pqNlGKa7UTt3 +6Z3q059c4EVlew3KW+JwULKUBRSuSceNQQcSc5R+DCMh/bwQf2AQWnL1mA6s7Ll/ +3XpvXdMc9P+IBWlCqQVxyLesJugutIxq/3HcuLHfmbx8IVQr5Fiiu1cprp6poxkm +D5kuCLDv/WnPmRoJjeOnnyvJNjR7JLN4TJUXpAYmHrZkUjZfYGfZnMUFdAvnZyPS +CPyI6a6Lf+Ew9Dd+/cYy2i2eRDAwbO4H3tI0/NL/QPZL9GZGBlSm8jIKYyYwa5vR +3ItHuuG51WLQoqD0ZwV4KWMabwTW+MZMo5qxN7SN5ShLHZ4swrhovO0C7jE= +-----END CERTIFICATE----- + +# Issuer: CN=Secure Global CA O=SecureTrust Corporation +# Subject: CN=Secure Global CA O=SecureTrust Corporation +# Label: "Secure Global CA" +# Serial: 9751836167731051554232119481456978597 +# MD5 Fingerprint: cf:f4:27:0d:d4:ed:dc:65:16:49:6d:3d:da:bf:6e:de +# SHA1 Fingerprint: 3a:44:73:5a:e5:81:90:1f:24:86:61:46:1e:3b:9c:c4:5f:f5:3a:1b +# SHA256 Fingerprint: 42:00:f5:04:3a:c8:59:0e:bb:52:7d:20:9e:d1:50:30:29:fb:cb:d4:1c:a1:b5:06:ec:27:f1:5a:de:7d:ac:69 +-----BEGIN CERTIFICATE----- +MIIDvDCCAqSgAwIBAgIQB1YipOjUiolN9BPI8PjqpTANBgkqhkiG9w0BAQUFADBK +MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24x +GTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwgQ0EwHhcNMDYxMTA3MTk0MjI4WhcNMjkx +MjMxMTk1MjA2WjBKMQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3Qg +Q29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwgQ0EwggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvNS7YrGxVaQZx5RNoJLNP2MwhR/jxYDiJ +iQPpvepeRlMJ3Fz1Wuj3RSoC6zFh1ykzTM7HfAo3fg+6MpjhHZevj8fcyTiW89sa +/FHtaMbQbqR8JNGuQsiWUGMu4P51/pinX0kuleM5M2SOHqRfkNJnPLLZ/kG5VacJ +jnIFHovdRIWCQtBJwB1g8NEXLJXr9qXBkqPFwqcIYA1gBBCWeZ4WNOaptvolRTnI +HmX5k/Wq8VLcmZg9pYYaDDUz+kulBAYVHDGA76oYa8J719rO+TMg1fW9ajMtgQT7 +sFzUnKPiXB3jqUJ1XnvUd+85VLrJChgbEplJL4hL/VBi0XPnj3pDAgMBAAGjgZ0w +gZowEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1UdEwEB/wQF +MAMBAf8wHQYDVR0OBBYEFK9EBMJBfkiD2045AuzshHrmzsmkMDQGA1UdHwQtMCsw +KaAnoCWGI2h0dHA6Ly9jcmwuc2VjdXJldHJ1c3QuY29tL1NHQ0EuY3JsMBAGCSsG +AQQBgjcVAQQDAgEAMA0GCSqGSIb3DQEBBQUAA4IBAQBjGghAfaReUw132HquHw0L +URYD7xh8yOOvaliTFGCRsoTciE6+OYo68+aCiV0BN7OrJKQVDpI1WkpEXk5X+nXO +H0jOZvQ8QCaSmGwb7iRGDBezUqXbpZGRzzfTb+cnCDpOGR86p1hcF895P4vkp9Mm +I50mD1hp/Ed+stCNi5O/KU9DaXR2Z0vPB4zmAve14bRDtUstFJ/53CYNv6ZHdAbY +iNE6KTCEztI5gGIbqMdXSbxqVVFnFUq+NQfk1XWYN3kwFNspnWzFacxHVaIw98xc +f8LDmBxrThaA63p4ZUWiABqvDA1VZDRIuJK58bRQKfJPIx/abKwfROHdI3hRW8cW +-----END CERTIFICATE----- + +# Issuer: CN=COMODO Certification Authority O=COMODO CA Limited +# Subject: CN=COMODO Certification Authority O=COMODO CA Limited +# Label: "COMODO Certification Authority" +# Serial: 104350513648249232941998508985834464573 +# MD5 Fingerprint: 5c:48:dc:f7:42:72:ec:56:94:6d:1c:cc:71:35:80:75 +# SHA1 Fingerprint: 66:31:bf:9e:f7:4f:9e:b6:c9:d5:a6:0c:ba:6a:be:d1:f7:bd:ef:7b +# SHA256 Fingerprint: 0c:2c:d6:3d:f7:80:6f:a3:99:ed:e8:09:11:6b:57:5b:f8:79:89:f0:65:18:f9:80:8c:86:05:03:17:8b:af:66 +-----BEGIN CERTIFICATE----- +MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCB +gTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G +A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNV +BAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEyMDEwMDAw +MDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3Jl +YXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01P +RE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0 +aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3 +UcEbVASY06m/weaKXTuH+7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI +2GqGd0S7WWaXUF601CxwRM/aN5VCaTwwxHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8 +Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV4EajcNxo2f8ESIl33rXp ++2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA1KGzqSX+ +DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5O +nKVIrLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW +/zAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6g +PKA6hjhodHRwOi8vY3JsLmNvbW9kb2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9u +QXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOCAQEAPpiem/Yb6dc5t3iuHXIY +SdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CPOGEIqB6BCsAv +IC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/ +RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4 +zJVSk/BwJVmcIGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5dd +BA6+C4OmF4O5MBKgxTMVBbkN+8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IB +ZQ== +-----END CERTIFICATE----- + +# Issuer: CN=Network Solutions Certificate Authority O=Network Solutions L.L.C. +# Subject: CN=Network Solutions Certificate Authority O=Network Solutions L.L.C. +# Label: "Network Solutions Certificate Authority" +# Serial: 116697915152937497490437556386812487904 +# MD5 Fingerprint: d3:f3:a6:16:c0:fa:6b:1d:59:b1:2d:96:4d:0e:11:2e +# SHA1 Fingerprint: 74:f8:a3:c3:ef:e7:b3:90:06:4b:83:90:3c:21:64:60:20:e5:df:ce +# SHA256 Fingerprint: 15:f0:ba:00:a3:ac:7a:f3:ac:88:4c:07:2b:10:11:a0:77:bd:77:c0:97:f4:01:64:b2:f8:59:8a:bd:83:86:0c +-----BEGIN CERTIFICATE----- +MIID5jCCAs6gAwIBAgIQV8szb8JcFuZHFhfjkDFo4DANBgkqhkiG9w0BAQUFADBi +MQswCQYDVQQGEwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMu +MTAwLgYDVQQDEydOZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3Jp +dHkwHhcNMDYxMjAxMDAwMDAwWhcNMjkxMjMxMjM1OTU5WjBiMQswCQYDVQQGEwJV +UzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMuMTAwLgYDVQQDEydO +ZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDkvH6SMG3G2I4rC7xGzuAnlt7e+foS0zwz +c7MEL7xxjOWftiJgPl9dzgn/ggwbmlFQGiaJ3dVhXRncEg8tCqJDXRfQNJIg6nPP +OCwGJgl6cvf6UDL4wpPTaaIjzkGxzOTVHzbRijr4jGPiFFlp7Q3Tf2vouAPlT2rl +mGNpSAW+Lv8ztumXWWn4Zxmuk2GWRBXTcrA/vGp97Eh/jcOrqnErU2lBUzS1sLnF +BgrEsEX1QV1uiUV7PTsmjHTC5dLRfbIR1PtYMiKagMnc/Qzpf14Dl847ABSHJ3A4 +qY5usyd2mFHgBeMhqxrVhSI8KbWaFsWAqPS7azCPL0YCorEMIuDTAgMBAAGjgZcw +gZQwHQYDVR0OBBYEFCEwyfsA106Y2oeqKtCnLrFAMadMMA4GA1UdDwEB/wQEAwIB +BjAPBgNVHRMBAf8EBTADAQH/MFIGA1UdHwRLMEkwR6BFoEOGQWh0dHA6Ly9jcmwu +bmV0c29sc3NsLmNvbS9OZXR3b3JrU29sdXRpb25zQ2VydGlmaWNhdGVBdXRob3Jp +dHkuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQC7rkvnt1frf6ott3NHhWrB5KUd5Oc8 +6fRZZXe1eltajSU24HqXLjjAV2CDmAaDn7l2em5Q4LqILPxFzBiwmZVRDuwduIj/ +h1AcgsLj4DKAv6ALR8jDMe+ZZzKATxcheQxpXN5eNK4CtSbqUN9/GGUsyfJj4akH +/nxxH2szJGoeBfcFaMBqEssuXmHLrijTfsK0ZpEmXzwuJF/LWA/rKOyvEZbz3Htv +wKeI8lN3s2Berq4o2jUsbzRF0ybh3uxbTydrFny9RAQYgrOJeRcQcT16ohZO9QHN +pGxlaKFJdlxDydi8NmdspZS11My5vWo1ViHe2MPr+8ukYEywVaCge1ey +-----END CERTIFICATE----- + +# Issuer: CN=COMODO ECC Certification Authority O=COMODO CA Limited +# Subject: CN=COMODO ECC Certification Authority O=COMODO CA Limited +# Label: "COMODO ECC Certification Authority" +# Serial: 41578283867086692638256921589707938090 +# MD5 Fingerprint: 7c:62:ff:74:9d:31:53:5e:68:4a:d5:78:aa:1e:bf:23 +# SHA1 Fingerprint: 9f:74:4e:9f:2b:4d:ba:ec:0f:31:2c:50:b6:56:3b:8e:2d:93:c3:11 +# SHA256 Fingerprint: 17:93:92:7a:06:14:54:97:89:ad:ce:2f:8f:34:f7:f0:b6:6d:0f:3a:e3:a3:b8:4d:21:ec:15:db:ba:4f:ad:c7 +-----BEGIN CERTIFICATE----- +MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTEL +MAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE +BxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMT +IkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwMzA2MDAw +MDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdy +ZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09N +T0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlv +biBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQDR3svdcmCFYX7deSR +FtSrYpn1PlILBs5BAH+X4QokPB0BBO490o0JlwzgdeT6+3eKKvUDYEs2ixYjFq0J +cfRK9ChQtP6IHG4/bC8vCVlbpVsLM5niwz2J+Wos77LTBumjQjBAMB0GA1UdDgQW +BBR1cacZSBm8nZ3qQUfflMRId5nTeTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/ +BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VGFAkK+qDm +fQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdv +GDeAU/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY= +-----END CERTIFICATE----- + +# Issuer: CN=Certigna O=Dhimyotis +# Subject: CN=Certigna O=Dhimyotis +# Label: "Certigna" +# Serial: 18364802974209362175 +# MD5 Fingerprint: ab:57:a6:5b:7d:42:82:19:b5:d8:58:26:28:5e:fd:ff +# SHA1 Fingerprint: b1:2e:13:63:45:86:a4:6f:1a:b2:60:68:37:58:2d:c4:ac:fd:94:97 +# SHA256 Fingerprint: e3:b6:a2:db:2e:d7:ce:48:84:2f:7a:c5:32:41:c7:b7:1d:54:14:4b:fb:40:c1:1f:3f:1d:0b:42:f5:ee:a1:2d +-----BEGIN CERTIFICATE----- +MIIDqDCCApCgAwIBAgIJAP7c4wEPyUj/MA0GCSqGSIb3DQEBBQUAMDQxCzAJBgNV +BAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hMB4X +DTA3MDYyOTE1MTMwNVoXDTI3MDYyOTE1MTMwNVowNDELMAkGA1UEBhMCRlIxEjAQ +BgNVBAoMCURoaW15b3RpczERMA8GA1UEAwwIQ2VydGlnbmEwggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQDIaPHJ1tazNHUmgh7stL7qXOEm7RFHYeGifBZ4 +QCHkYJ5ayGPhxLGWkv8YbWkj4Sti993iNi+RB7lIzw7sebYs5zRLcAglozyHGxny +gQcPOJAZ0xH+hrTy0V4eHpbNgGzOOzGTtvKg0KmVEn2lmsxryIRWijOp5yIVUxbw +zBfsV1/pogqYCd7jX5xv3EjjhQsVWqa6n6xI4wmy9/Qy3l40vhx4XUJbzg4ij02Q +130yGLMLLGq/jj8UEYkgDncUtT2UCIf3JR7VsmAA7G8qKCVuKj4YYxclPz5EIBb2 +JsglrgVKtOdjLPOMFlN+XPsRGgjBRmKfIrjxwo1p3Po6WAbfAgMBAAGjgbwwgbkw +DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUGu3+QTmQtCRZvgHyUtVF9lo53BEw +ZAYDVR0jBF0wW4AUGu3+QTmQtCRZvgHyUtVF9lo53BGhOKQ2MDQxCzAJBgNVBAYT +AkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hggkA/tzj +AQ/JSP8wDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG +9w0BAQUFAAOCAQEAhQMeknH2Qq/ho2Ge6/PAD/Kl1NqV5ta+aDY9fm4fTIrv0Q8h +bV6lUmPOEvjvKtpv6zf+EwLHyzs+ImvaYS5/1HI93TDhHkxAGYwP15zRgzB7mFnc +fca5DClMoTOi62c6ZYTTluLtdkVwj7Ur3vkj1kluPBS1xp81HlDQwY9qcEQCYsuu +HWhBp6pX6FOqB9IG9tUUBguRA3UsbHK1YZWaDYu5Def131TN3ubY1gkIl2PlwS6w +t0QmwCbAr1UwnjvVNioZBPRcHv/PLLf/0P2HQBHVESO7SMAhqaQoLf0V+LBOK/Qw +WyH8EZE0vkHve52Xdf+XlcCWWC/qu0bXu+TZLg== +-----END CERTIFICATE----- + +# Issuer: CN=Cybertrust Global Root O=Cybertrust, Inc +# Subject: CN=Cybertrust Global Root O=Cybertrust, Inc +# Label: "Cybertrust Global Root" +# Serial: 4835703278459682877484360 +# MD5 Fingerprint: 72:e4:4a:87:e3:69:40:80:77:ea:bc:e3:f4:ff:f0:e1 +# SHA1 Fingerprint: 5f:43:e5:b1:bf:f8:78:8c:ac:1c:c7:ca:4a:9a:c6:22:2b:cc:34:c6 +# SHA256 Fingerprint: 96:0a:df:00:63:e9:63:56:75:0c:29:65:dd:0a:08:67:da:0b:9c:bd:6e:77:71:4a:ea:fb:23:49:ab:39:3d:a3 +-----BEGIN CERTIFICATE----- +MIIDoTCCAomgAwIBAgILBAAAAAABD4WqLUgwDQYJKoZIhvcNAQEFBQAwOzEYMBYG +A1UEChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2Jh +bCBSb290MB4XDTA2MTIxNTA4MDAwMFoXDTIxMTIxNTA4MDAwMFowOzEYMBYGA1UE +ChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2JhbCBS +b290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA+Mi8vRRQZhP/8NN5 +7CPytxrHjoXxEnOmGaoQ25yiZXRadz5RfVb23CO21O1fWLE3TdVJDm71aofW0ozS +J8bi/zafmGWgE07GKmSb1ZASzxQG9Dvj1Ci+6A74q05IlG2OlTEQXO2iLb3VOm2y +HLtgwEZLAfVJrn5GitB0jaEMAs7u/OePuGtm839EAL9mJRQr3RAwHQeWP032a7iP +t3sMpTjr3kfb1V05/Iin89cqdPHoWqI7n1C6poxFNcJQZZXcY4Lv3b93TZxiyWNz +FtApD0mpSPCzqrdsxacwOUBdrsTiXSZT8M4cIwhhqJQZugRiQOwfOHB3EgZxpzAY +XSUnpQIDAQABo4GlMIGiMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/ +MB0GA1UdDgQWBBS2CHsNesysIEyGVjJez6tuhS1wVzA/BgNVHR8EODA2MDSgMqAw +hi5odHRwOi8vd3d3Mi5wdWJsaWMtdHJ1c3QuY29tL2NybC9jdC9jdHJvb3QuY3Js +MB8GA1UdIwQYMBaAFLYIew16zKwgTIZWMl7Pq26FLXBXMA0GCSqGSIb3DQEBBQUA +A4IBAQBW7wojoFROlZfJ+InaRcHUowAl9B8Tq7ejhVhpwjCt2BWKLePJzYFa+HMj +Wqd8BfP9IjsO0QbE2zZMcwSO5bAi5MXzLqXZI+O4Tkogp24CJJ8iYGd7ix1yCcUx +XOl5n4BHPa2hCwcUPUf/A2kaDAtE52Mlp3+yybh2hO0j9n0Hq0V+09+zv+mKts2o +omcrUtW3ZfA5TGOgkXmTUg9U3YO7n9GPp1Nzw8v/MOx8BLjYRB+TX3EJIrduPuoc +A06dGiBh+4E37F78CkWr1+cXVdCg6mCbpvbjjFspwgZgFJ0tl0ypkxWdYcQBX0jW +WL1WMRJOEcgh4LMRkWXbtKaIOM5V +-----END CERTIFICATE----- + +# Issuer: O=Chunghwa Telecom Co., Ltd. OU=ePKI Root Certification Authority +# Subject: O=Chunghwa Telecom Co., Ltd. OU=ePKI Root Certification Authority +# Label: "ePKI Root Certification Authority" +# Serial: 28956088682735189655030529057352760477 +# MD5 Fingerprint: 1b:2e:00:ca:26:06:90:3d:ad:fe:6f:15:68:d3:6b:b3 +# SHA1 Fingerprint: 67:65:0d:f1:7e:8e:7e:5b:82:40:a4:f4:56:4b:cf:e2:3d:69:c6:f0 +# SHA256 Fingerprint: c0:a6:f4:dc:63:a2:4b:fd:cf:54:ef:2a:6a:08:2a:0a:72:de:35:80:3e:2f:f5:ff:52:7a:e5:d8:72:06:df:d5 +-----BEGIN CERTIFICATE----- +MIIFsDCCA5igAwIBAgIQFci9ZUdcr7iXAF7kBtK8nTANBgkqhkiG9w0BAQUFADBe +MQswCQYDVQQGEwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0 +ZC4xKjAoBgNVBAsMIWVQS0kgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAe +Fw0wNDEyMjAwMjMxMjdaFw0zNDEyMjAwMjMxMjdaMF4xCzAJBgNVBAYTAlRXMSMw +IQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEqMCgGA1UECwwhZVBL +SSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0BAQEF +AAOCAg8AMIICCgKCAgEA4SUP7o3biDN1Z82tH306Tm2d0y8U82N0ywEhajfqhFAH +SyZbCUNsIZ5qyNUD9WBpj8zwIuQf5/dqIjG3LBXy4P4AakP/h2XGtRrBp0xtInAh +ijHyl3SJCRImHJ7K2RKilTza6We/CKBk49ZCt0Xvl/T29de1ShUCWH2YWEtgvM3X +DZoTM1PRYfl61dd4s5oz9wCGzh1NlDivqOx4UXCKXBCDUSH3ET00hl7lSM2XgYI1 +TBnsZfZrxQWh7kcT1rMhJ5QQCtkkO7q+RBNGMD+XPNjX12ruOzjjK9SXDrkb5wdJ +fzcq+Xd4z1TtW0ado4AOkUPB1ltfFLqfpo0kR0BZv3I4sjZsN/+Z0V0OWQqraffA +sgRFelQArr5T9rXn4fg8ozHSqf4hUmTFpmfwdQcGlBSBVcYn5AGPF8Fqcde+S/uU +WH1+ETOxQvdibBjWzwloPn9s9h6PYq2lY9sJpx8iQkEeb5mKPtf5P0B6ebClAZLS +nT0IFaUQAS2zMnaolQ2zepr7BxB4EW/hj8e6DyUadCrlHJhBmd8hh+iVBmoKs2pH +dmX2Os+PYhcZewoozRrSgx4hxyy/vv9haLdnG7t4TY3OZ+XkwY63I2binZB1NJip +NiuKmpS5nezMirH4JYlcWrYvjB9teSSnUmjDhDXiZo1jDiVN1Rmy5nk3pyKdVDEC +AwEAAaNqMGgwHQYDVR0OBBYEFB4M97Zn8uGSJglFwFU5Lnc/QkqiMAwGA1UdEwQF +MAMBAf8wOQYEZyoHAAQxMC8wLQIBADAJBgUrDgMCGgUAMAcGBWcqAwAABBRFsMLH +ClZ87lt4DJX5GFPBphzYEDANBgkqhkiG9w0BAQUFAAOCAgEACbODU1kBPpVJufGB +uvl2ICO1J2B01GqZNF5sAFPZn/KmsSQHRGoqxqWOeBLoR9lYGxMqXnmbnwoqZ6Yl +PwZpVnPDimZI+ymBV3QGypzqKOg4ZyYr8dW1P2WT+DZdjo2NQCCHGervJ8A9tDkP +JXtoUHRVnAxZfVo9QZQlUgjgRywVMRnVvwdVxrsStZf0X4OFunHB2WyBEXYKCrC/ +gpf36j36+uwtqSiUO1bd0lEursC9CBWMd1I0ltabrNMdjmEPNXubrjlpC2JgQCA2 +j6/7Nu4tCEoduL+bXPjqpRugc6bY+G7gMwRfaKonh+3ZwZCc7b3jajWvY9+rGNm6 +5ulK6lCKD2GTHuItGeIwlDWSXQ62B68ZgI9HkFFLLk3dheLSClIKF5r8GrBQAuUB +o2M3IUxExJtRmREOc5wGj1QupyheRDmHVi03vYVElOEMSyycw5KFNGHLD7ibSkNS +/jQ6fbjpKdx2qcgw+BRxgMYeNkh0IkFch4LoGHGLQYlE535YW6i4jRPpp2zDR+2z +Gp1iro2C6pSe3VkQw63d4k3jMdXH7OjysP6SHhYKGvzZ8/gntsm+HbRsZJB/9OTE +W9c3rkIO3aQab3yIVMUWbuF6aC74Or8NpDyJO3inTmODBCEIZ43ygknQW/2xzQ+D +hNQ+IIX3Sj0rnP0qCglN6oH4EZw= +-----END CERTIFICATE----- + +# Issuer: O=certSIGN OU=certSIGN ROOT CA +# Subject: O=certSIGN OU=certSIGN ROOT CA +# Label: "certSIGN ROOT CA" +# Serial: 35210227249154 +# MD5 Fingerprint: 18:98:c0:d6:e9:3a:fc:f9:b0:f5:0c:f7:4b:01:44:17 +# SHA1 Fingerprint: fa:b7:ee:36:97:26:62:fb:2d:b0:2a:f6:bf:03:fd:e8:7c:4b:2f:9b +# SHA256 Fingerprint: ea:a9:62:c4:fa:4a:6b:af:eb:e4:15:19:6d:35:1c:cd:88:8d:4f:53:f3:fa:8a:e6:d7:c4:66:a9:4e:60:42:bb +-----BEGIN CERTIFICATE----- +MIIDODCCAiCgAwIBAgIGIAYFFnACMA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNVBAYT +AlJPMREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBD +QTAeFw0wNjA3MDQxNzIwMDRaFw0zMTA3MDQxNzIwMDRaMDsxCzAJBgNVBAYTAlJP +MREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBDQTCC +ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALczuX7IJUqOtdu0KBuqV5Do +0SLTZLrTk+jUrIZhQGpgV2hUhE28alQCBf/fm5oqrl0Hj0rDKH/v+yv6efHHrfAQ +UySQi2bJqIirr1qjAOm+ukbuW3N7LBeCgV5iLKECZbO9xSsAfsT8AzNXDe3i+s5d +RdY4zTW2ssHQnIFKquSyAVwdj1+ZxLGt24gh65AIgoDzMKND5pCCrlUoSe1b16kQ +OA7+j0xbm0bqQfWwCHTD0IgztnzXdN/chNFDDnU5oSVAKOp4yw4sLjmdjItuFhwv +JoIQ4uNllAoEwF73XVv4EOLQunpL+943AAAaWyjj0pxzPjKHmKHJUS/X3qwzs08C +AwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAcYwHQYDVR0O +BBYEFOCMm9slSbPxfIbWskKHC9BroNnkMA0GCSqGSIb3DQEBBQUAA4IBAQA+0hyJ +LjX8+HXd5n9liPRyTMks1zJO890ZeUe9jjtbkw9QSSQTaxQGcu8J06Gh40CEyecY +MnQ8SG4Pn0vU9x7Tk4ZkVJdjclDVVc/6IJMCopvDI5NOFlV2oHB5bc0hH88vLbwZ +44gx+FkagQnIl6Z0x2DEW8xXjrJ1/RsCCdtZb3KTafcxQdaIOL+Hsr0Wefmq5L6I +Jd1hJyMctTEHBDa0GpC9oHRxUIltvBTjD4au8as+x6AJzKNI0eDbZOeStc+vckNw +i/nDhDwTqn6Sm1dTk/pwwpEOMfmbZ13pljheX7NzTogVZ96edhBiIL5VaZVDADlN +9u6wWk5JRFRYX0KD +-----END CERTIFICATE----- + +# Issuer: CN=NetLock Arany (Class Gold) F\u0151tan\xfas\xedtv\xe1ny O=NetLock Kft. OU=Tan\xfas\xedtv\xe1nykiad\xf3k (Certification Services) +# Subject: CN=NetLock Arany (Class Gold) F\u0151tan\xfas\xedtv\xe1ny O=NetLock Kft. OU=Tan\xfas\xedtv\xe1nykiad\xf3k (Certification Services) +# Label: "NetLock Arany (Class Gold) F\u0151tan\xfas\xedtv\xe1ny" +# Serial: 80544274841616 +# MD5 Fingerprint: c5:a1:b7:ff:73:dd:d6:d7:34:32:18:df:fc:3c:ad:88 +# SHA1 Fingerprint: 06:08:3f:59:3f:15:a1:04:a0:69:a4:6b:a9:03:d0:06:b7:97:09:91 +# SHA256 Fingerprint: 6c:61:da:c3:a2:de:f0:31:50:6b:e0:36:d2:a6:fe:40:19:94:fb:d1:3d:f9:c8:d4:66:59:92:74:c4:46:ec:98 +-----BEGIN CERTIFICATE----- +MIIEFTCCAv2gAwIBAgIGSUEs5AAQMA0GCSqGSIb3DQEBCwUAMIGnMQswCQYDVQQG +EwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3 +MDUGA1UECwwuVGFuw7pzw610dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNl +cnZpY2VzKTE1MDMGA1UEAwwsTmV0TG9jayBBcmFueSAoQ2xhc3MgR29sZCkgRsWR +dGFuw7pzw610dsOhbnkwHhcNMDgxMjExMTUwODIxWhcNMjgxMjA2MTUwODIxWjCB +pzELMAkGA1UEBhMCSFUxETAPBgNVBAcMCEJ1ZGFwZXN0MRUwEwYDVQQKDAxOZXRM +b2NrIEtmdC4xNzA1BgNVBAsMLlRhbsO6c8OtdHbDoW55a2lhZMOzayAoQ2VydGlm +aWNhdGlvbiBTZXJ2aWNlcykxNTAzBgNVBAMMLE5ldExvY2sgQXJhbnkgKENsYXNz +IEdvbGQpIEbFkXRhbsO6c8OtdHbDoW55MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEAxCRec75LbRTDofTjl5Bu0jBFHjzuZ9lk4BqKf8owyoPjIMHj9DrT +lF8afFttvzBPhCf2nx9JvMaZCpDyD/V/Q4Q3Y1GLeqVw/HpYzY6b7cNGbIRwXdrz +AZAj/E4wqX7hJ2Pn7WQ8oLjJM2P+FpD/sLj916jAwJRDC7bVWaaeVtAkH3B5r9s5 +VA1lddkVQZQBr17s9o3x/61k/iCa11zr/qYfCGSji3ZVrR47KGAuhyXoqq8fxmRG +ILdwfzzeSNuWU7c5d+Qa4scWhHaXWy+7GRWF+GmF9ZmnqfI0p6m2pgP8b4Y9VHx2 +BJtr+UBdADTHLpl1neWIA6pN+APSQnbAGwIDAKiLo0UwQzASBgNVHRMBAf8ECDAG +AQH/AgEEMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUzPpnk/C2uNClwB7zU/2M +U9+D15YwDQYJKoZIhvcNAQELBQADggEBAKt/7hwWqZw8UQCgwBEIBaeZ5m8BiFRh +bvG5GK1Krf6BQCOUL/t1fC8oS2IkgYIL9WHxHG64YTjrgfpioTtaYtOUZcTh5m2C ++C8lcLIhJsFyUR+MLMOEkMNaj7rP9KdlpeuY0fsFskZ1FSNqb4VjMIDw1Z4fKRzC +bLBQWV2QWzuoDTDPv31/zvGdg73JRm4gpvlhUbohL3u+pRVjodSVh/GeufOJ8z2F +uLjbvrW5KfnaNwUASZQDhETnv0Mxz3WLJdH0pmT1kvarBes96aULNmLazAZfNou2 +XjG4Kvte9nHfRCaexOYNkbQudZWAUWpLMKawYqGT8ZvYzsRjdT9ZR7E= +-----END CERTIFICATE----- + +# Issuer: CN=Hongkong Post Root CA 1 O=Hongkong Post +# Subject: CN=Hongkong Post Root CA 1 O=Hongkong Post +# Label: "Hongkong Post Root CA 1" +# Serial: 1000 +# MD5 Fingerprint: a8:0d:6f:39:78:b9:43:6d:77:42:6d:98:5a:cc:23:ca +# SHA1 Fingerprint: d6:da:a8:20:8d:09:d2:15:4d:24:b5:2f:cb:34:6e:b2:58:b2:8a:58 +# SHA256 Fingerprint: f9:e6:7d:33:6c:51:00:2a:c0:54:c6:32:02:2d:66:dd:a2:e7:e3:ff:f1:0a:d0:61:ed:31:d8:bb:b4:10:cf:b2 +-----BEGIN CERTIFICATE----- +MIIDMDCCAhigAwIBAgICA+gwDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCSEsx +FjAUBgNVBAoTDUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3Qg +Um9vdCBDQSAxMB4XDTAzMDUxNTA1MTMxNFoXDTIzMDUxNTA0NTIyOVowRzELMAkG +A1UEBhMCSEsxFjAUBgNVBAoTDUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdr +b25nIFBvc3QgUm9vdCBDQSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC +AQEArP84tulmAknjorThkPlAj3n54r15/gK97iSSHSL22oVyaf7XPwnU3ZG1ApzQ +jVrhVcNQhrkpJsLj2aDxaQMoIIBFIi1WpztUlVYiWR8o3x8gPW2iNr4joLFutbEn +PzlTCeqrauh0ssJlXI6/fMN4hM2eFvz1Lk8gKgifd/PFHsSaUmYeSF7jEAaPIpjh +ZY4bXSNmO7ilMlHIhqqhqZ5/dpTCpmy3QfDVyAY45tQM4vM7TG1QjMSDJ8EThFk9 +nnV0ttgCXjqQesBCNnLsak3c78QA3xMYV18meMjWCnl3v/evt3a5pQuEF10Q6m/h +q5URX208o1xNg1vysxmKgIsLhwIDAQABoyYwJDASBgNVHRMBAf8ECDAGAQH/AgED +MA4GA1UdDwEB/wQEAwIBxjANBgkqhkiG9w0BAQUFAAOCAQEADkbVPK7ih9legYsC +mEEIjEy82tvuJxuC52pF7BaLT4Wg87JwvVqWuspube5Gi27nKi6Wsxkz67SfqLI3 +7piol7Yutmcn1KZJ/RyTZXaeQi/cImyaT/JaFTmxcdcrUehtHJjA2Sr0oYJ71clB +oiMBdDhViw+5LmeiIAQ32pwL0xch4I+XeTRvhEgCIDMb5jREn5Fw9IBehEPCKdJs +EhTkYY2sEJCehFC78JZvRZ+K88psT/oROhUVRsPNH4NbLUES7VBnQRM9IauUiqpO +fMGx+6fWtScvl6tu4B3i0RwsH0Ti/L6RoZz71ilTc4afU9hDDl3WY4JxHYB0yvbi +AmvZWg== +-----END CERTIFICATE----- + +# Issuer: CN=SecureSign RootCA11 O=Japan Certification Services, Inc. +# Subject: CN=SecureSign RootCA11 O=Japan Certification Services, Inc. +# Label: "SecureSign RootCA11" +# Serial: 1 +# MD5 Fingerprint: b7:52:74:e2:92:b4:80:93:f2:75:e4:cc:d7:f2:ea:26 +# SHA1 Fingerprint: 3b:c4:9f:48:f8:f3:73:a0:9c:1e:bd:f8:5b:b1:c3:65:c7:d8:11:b3 +# SHA256 Fingerprint: bf:0f:ee:fb:9e:3a:58:1a:d5:f9:e9:db:75:89:98:57:43:d2:61:08:5c:4d:31:4f:6f:5d:72:59:aa:42:16:12 +-----BEGIN CERTIFICATE----- +MIIDbTCCAlWgAwIBAgIBATANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQGEwJKUDEr +MCkGA1UEChMiSmFwYW4gQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcywgSW5jLjEcMBoG +A1UEAxMTU2VjdXJlU2lnbiBSb290Q0ExMTAeFw0wOTA0MDgwNDU2NDdaFw0yOTA0 +MDgwNDU2NDdaMFgxCzAJBgNVBAYTAkpQMSswKQYDVQQKEyJKYXBhbiBDZXJ0aWZp +Y2F0aW9uIFNlcnZpY2VzLCBJbmMuMRwwGgYDVQQDExNTZWN1cmVTaWduIFJvb3RD +QTExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA/XeqpRyQBTvLTJsz +i1oURaTnkBbR31fSIRCkF/3frNYfp+TbfPfs37gD2pRY/V1yfIw/XwFndBWW4wI8 +h9uuywGOwvNmxoVF9ALGOrVisq/6nL+k5tSAMJjzDbaTj6nU2DbysPyKyiyhFTOV +MdrAG/LuYpmGYz+/3ZMqg6h2uRMft85OQoWPIucuGvKVCbIFtUROd6EgvanyTgp9 +UK31BQ1FT0Zx/Sg+U/sE2C3XZR1KG/rPO7AxmjVuyIsG0wCR8pQIZUyxNAYAeoni +8McDWc/V1uinMrPmmECGxc0nEovMe863ETxiYAcjPitAbpSACW22s293bzUIUPsC +h8U+iQIDAQABo0IwQDAdBgNVHQ4EFgQUW/hNT7KlhtQ60vFjmqC+CfZXt94wDgYD +VR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEB +AKChOBZmLqdWHyGcBvod7bkixTgm2E5P7KN/ed5GIaGHd48HCJqypMWvDzKYC3xm +KbabfSVSSUOrTC4rbnpwrxYO4wJs+0LmGJ1F2FXI6Dvd5+H0LgscNFxsWEr7jIhQ +X5Ucv+2rIrVls4W6ng+4reV6G4pQOh29Dbx7VFALuUKvVaAYga1lme++5Jy/xIWr +QbJUb9wlze144o4MjQlJ3WN7WmmWAiGovVJZ6X01y8hSyn+B/tlr0/cR7SXf+Of5 +pPpyl4RTDaXQMhhRdlkUbA/r7F+AjHVDg8OFmP9Mni0N5HeDk061lgeLKBObjBmN +QSdJQO7e5iNEOdyhIta6A/I= +-----END CERTIFICATE----- + +# Issuer: CN=Microsec e-Szigno Root CA 2009 O=Microsec Ltd. +# Subject: CN=Microsec e-Szigno Root CA 2009 O=Microsec Ltd. +# Label: "Microsec e-Szigno Root CA 2009" +# Serial: 14014712776195784473 +# MD5 Fingerprint: f8:49:f4:03:bc:44:2d:83:be:48:69:7d:29:64:fc:b1 +# SHA1 Fingerprint: 89:df:74:fe:5c:f4:0f:4a:80:f9:e3:37:7d:54:da:91:e1:01:31:8e +# SHA256 Fingerprint: 3c:5f:81:fe:a5:fa:b8:2c:64:bf:a2:ea:ec:af:cd:e8:e0:77:fc:86:20:a7:ca:e5:37:16:3d:f3:6e:db:f3:78 +-----BEGIN CERTIFICATE----- +MIIECjCCAvKgAwIBAgIJAMJ+QwRORz8ZMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYD +VQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0 +ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0G +CSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5odTAeFw0wOTA2MTYxMTMwMThaFw0y +OTEyMzAxMTMwMThaMIGCMQswCQYDVQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3Qx +FjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUtU3pp +Z25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5o +dTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOn4j/NjrdqG2KfgQvvP +kd6mJviZpWNwrZuuyjNAfW2WbqEORO7hE52UQlKavXWFdCyoDh2Tthi3jCyoz/tc +cbna7P7ofo/kLx2yqHWH2Leh5TvPmUpG0IMZfcChEhyVbUr02MelTTMuhTlAdX4U +fIASmFDHQWe4oIBhVKZsTh/gnQ4H6cm6M+f+wFUoLAKApxn1ntxVUwOXewdI/5n7 +N4okxFnMUBBjjqqpGrCEGob5X7uxUG6k0QrM1XF+H6cbfPVTbiJfyyvm1HxdrtbC +xkzlBQHZ7Vf8wSN5/PrIJIOV87VqUQHQd9bpEqH5GoP7ghu5sJf0dgYzQ0mg/wu1 ++rUCAwEAAaOBgDB+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G +A1UdDgQWBBTLD8bfQkPMPcu1SCOhGnqmKrs0aDAfBgNVHSMEGDAWgBTLD8bfQkPM +Pcu1SCOhGnqmKrs0aDAbBgNVHREEFDASgRBpbmZvQGUtc3ppZ25vLmh1MA0GCSqG +SIb3DQEBCwUAA4IBAQDJ0Q5eLtXMs3w+y/w9/w0olZMEyL/azXm4Q5DwpL7v8u8h +mLzU1F0G9u5C7DBsoKqpyvGvivo/C3NqPuouQH4frlRheesuCDfXI/OMn74dseGk +ddug4lQUsbocKaQY9hK6ohQU4zE1yED/t+AFdlfBHFny+L/k7SViXITwfn4fs775 +tyERzAMBVnCnEJIeGzSBHq2cGsMEPO0CYdYeBvNfOofyK/FFh+U9rNHHV4S9a67c +2Pm2G2JwCz02yULyMtd6YebS2z3PyKnJm9zbWETXbzivf3jTo60adbocwTZ8jx5t +HMN1Rq41Bab2XD0h7lbwyYIiLXpUq3DDfSJlgnCW +-----END CERTIFICATE----- + +# Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R3 +# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R3 +# Label: "GlobalSign Root CA - R3" +# Serial: 4835703278459759426209954 +# MD5 Fingerprint: c5:df:b8:49:ca:05:13:55:ee:2d:ba:1a:c3:3e:b0:28 +# SHA1 Fingerprint: d6:9b:56:11:48:f0:1c:77:c5:45:78:c1:09:26:df:5b:85:69:76:ad +# SHA256 Fingerprint: cb:b5:22:d7:b7:f1:27:ad:6a:01:13:86:5b:df:1c:d4:10:2e:7d:07:59:af:63:5a:7c:f4:72:0d:c9:63:c5:3b +-----BEGIN CERTIFICATE----- +MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4G +A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNp +Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4 +MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEG +A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWtiHL8 +RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsT +gHeMCOFJ0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmm +KPZpO/bLyCiR5Z2KYVc3rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zd +QQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjlOCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZ +XriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2xmmFghcCAwEAAaNCMEAw +DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI/wS3+o +LkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZU +RUm7lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMp +jjM5RcOO5LlXbKr8EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK +6fBdRoyV3XpYKBovHd7NADdBj+1EbddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQX +mcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18YIvDQVETI53O9zJrlAGomecs +Mx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpH +WD9f +-----END CERTIFICATE----- + +# Issuer: CN=Autoridad de Certificacion Firmaprofesional CIF A62634068 +# Subject: CN=Autoridad de Certificacion Firmaprofesional CIF A62634068 +# Label: "Autoridad de Certificacion Firmaprofesional CIF A62634068" +# Serial: 6047274297262753887 +# MD5 Fingerprint: 73:3a:74:7a:ec:bb:a3:96:a6:c2:e4:e2:c8:9b:c0:c3 +# SHA1 Fingerprint: ae:c5:fb:3f:c8:e1:bf:c4:e5:4f:03:07:5a:9a:e8:00:b7:f7:b6:fa +# SHA256 Fingerprint: 04:04:80:28:bf:1f:28:64:d4:8f:9a:d4:d8:32:94:36:6a:82:88:56:55:3f:3b:14:30:3f:90:14:7f:5d:40:ef +-----BEGIN CERTIFICATE----- +MIIGFDCCA/ygAwIBAgIIU+w77vuySF8wDQYJKoZIhvcNAQEFBQAwUTELMAkGA1UE +BhMCRVMxQjBABgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1h +cHJvZmVzaW9uYWwgQ0lGIEE2MjYzNDA2ODAeFw0wOTA1MjAwODM4MTVaFw0zMDEy +MzEwODM4MTVaMFExCzAJBgNVBAYTAkVTMUIwQAYDVQQDDDlBdXRvcmlkYWQgZGUg +Q2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBBNjI2MzQwNjgwggIi +MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDDUtd9 +thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQM +cas9UX4PB99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9qFD0sefG +L9ItWY16Ck6WaVICqjaY7Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15i +NA9wBj4gGFrO93IbJWyTdBSTo3OxDqqHECNZXyAFGUftaI6SEspd/NYrspI8IM/h +X68gvqB2f3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyIplD9amML9ZMWGxmPsu2b +m8mQ9QEM3xk9Dz44I8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctXMbScyJCy +Z/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirja +EbsXLZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/T +KI8xWVvTyQKmtFLKbpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF +6NkBiDkal4ZkQdU7hwxu+g/GvUgUvzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVh +OSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMBIGA1UdEwEB/wQIMAYBAf8CAQEwDgYD +VR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRlzeurNR4APn7VdMActHNHDhpkLzCBpgYD +VR0gBIGeMIGbMIGYBgRVHSAAMIGPMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmZp +cm1hcHJvZmVzaW9uYWwuY29tL2NwczBcBggrBgEFBQcCAjBQHk4AUABhAHMAZQBv +ACAAZABlACAAbABhACAAQgBvAG4AYQBuAG8AdgBhACAANAA3ACAAQgBhAHIAYwBl +AGwAbwBuAGEAIAAwADgAMAAxADcwDQYJKoZIhvcNAQEFBQADggIBABd9oPm03cXF +661LJLWhAqvdpYhKsg9VSytXjDvlMd3+xDLx51tkljYyGOylMnfX40S2wBEqgLk9 +am58m9Ot/MPWo+ZkKXzR4Tgegiv/J2Wv+xYVxC5xhOW1//qkR71kMrv2JYSiJ0L1 +ILDCExARzRAVukKQKtJE4ZYm6zFIEv0q2skGz3QeqUvVhyj5eTSSPi5E6PaPT481 +PyWzOdxjKpBrIF/EUhJOlywqrJ2X3kjyo2bbwtKDlaZmp54lD+kLM5FlClrD2VQS +3a/DTg4fJl4N3LON7NWBcN7STyQF82xO9UxJZo3R/9ILJUFI/lGExkKvgATP0H5k +SeTy36LssUzAKh3ntLFlosS88Zj0qnAHY7S42jtM+kAiMFsRpvAFDsYCA0irhpuF +3dvd6qJ2gHN99ZwExEWN57kci57q13XRcrHedUTnQn3iV2t93Jm8PYMo6oCTjcVM +ZcFwgbg4/EMxsvYDNEeyrPsiBsse3RdHHF9mudMaotoRsaS8I8nkvof/uZS2+F0g +StRf571oe2XyFR7SOqkt6dhrJKyXWERHrVkY8SFlcN7ONGCoQPHzPKTDKCOM/icz +Q0CgFzzr6juwcqajuUpLXhZI9LK8yIySxZ2frHI2vDSANGupi5LAuBft7HZT9SQB +jLMi6Et8Vcad+qMUu2WFbm5PEn4KPJ2V +-----END CERTIFICATE----- + +# Issuer: CN=Izenpe.com O=IZENPE S.A. +# Subject: CN=Izenpe.com O=IZENPE S.A. +# Label: "Izenpe.com" +# Serial: 917563065490389241595536686991402621 +# MD5 Fingerprint: a6:b0:cd:85:80:da:5c:50:34:a3:39:90:2f:55:67:73 +# SHA1 Fingerprint: 2f:78:3d:25:52:18:a7:4a:65:39:71:b5:2c:a2:9c:45:15:6f:e9:19 +# SHA256 Fingerprint: 25:30:cc:8e:98:32:15:02:ba:d9:6f:9b:1f:ba:1b:09:9e:2d:29:9e:0f:45:48:bb:91:4f:36:3b:c0:d4:53:1f +-----BEGIN CERTIFICATE----- +MIIF8TCCA9mgAwIBAgIQALC3WhZIX7/hy/WL1xnmfTANBgkqhkiG9w0BAQsFADA4 +MQswCQYDVQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6 +ZW5wZS5jb20wHhcNMDcxMjEzMTMwODI4WhcNMzcxMjEzMDgyNzI1WjA4MQswCQYD +VQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6ZW5wZS5j +b20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDJ03rKDx6sp4boFmVq +scIbRTJxldn+EFvMr+eleQGPicPK8lVx93e+d5TzcqQsRNiekpsUOqHnJJAKClaO +xdgmlOHZSOEtPtoKct2jmRXagaKH9HtuJneJWK3W6wyyQXpzbm3benhB6QiIEn6H +LmYRY2xU+zydcsC8Lv/Ct90NduM61/e0aL6i9eOBbsFGb12N4E3GVFWJGjMxCrFX +uaOKmMPsOzTFlUFpfnXCPCDFYbpRR6AgkJOhkEvzTnyFRVSa0QUmQbC1TR0zvsQD +yCV8wXDbO/QJLVQnSKwv4cSsPsjLkkxTOTcj7NMB+eAJRE1NZMDhDVqHIrytG6P+ +JrUV86f8hBnp7KGItERphIPzidF0BqnMC9bC3ieFUCbKF7jJeodWLBoBHmy+E60Q +rLUk9TiRodZL2vG70t5HtfG8gfZZa88ZU+mNFctKy6lvROUbQc/hhqfK0GqfvEyN +BjNaooXlkDWgYlwWTvDjovoDGrQscbNYLN57C9saD+veIR8GdwYDsMnvmfzAuU8L +hij+0rnq49qlw0dpEuDb8PYZi+17cNcC1u2HGCgsBCRMd+RIihrGO5rUD8r6ddIB +QFqNeb+Lz0vPqhbBleStTIo+F5HUsWLlguWABKQDfo2/2n+iD5dPDNMN+9fR5XJ+ +HMh3/1uaD7euBUbl8agW7EekFwIDAQABo4H2MIHzMIGwBgNVHREEgagwgaWBD2lu +Zm9AaXplbnBlLmNvbaSBkTCBjjFHMEUGA1UECgw+SVpFTlBFIFMuQS4gLSBDSUYg +QTAxMzM3MjYwLVJNZXJjLlZpdG9yaWEtR2FzdGVpeiBUMTA1NSBGNjIgUzgxQzBB +BgNVBAkMOkF2ZGEgZGVsIE1lZGl0ZXJyYW5lbyBFdG9yYmlkZWEgMTQgLSAwMTAx +MCBWaXRvcmlhLUdhc3RlaXowDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +AQYwHQYDVR0OBBYEFB0cZQ6o8iV7tJHP5LGx5r1VdGwFMA0GCSqGSIb3DQEBCwUA +A4ICAQB4pgwWSp9MiDrAyw6lFn2fuUhfGI8NYjb2zRlrrKvV9pF9rnHzP7MOeIWb +laQnIUdCSnxIOvVFfLMMjlF4rJUT3sb9fbgakEyrkgPH7UIBzg/YsfqikuFgba56 +awmqxinuaElnMIAkejEWOVt+8Rwu3WwJrfIxwYJOubv5vr8qhT/AQKM6WfxZSzwo +JNu0FXWuDYi6LnPAvViH5ULy617uHjAimcs30cQhbIHsvm0m5hzkQiCeR7Csg1lw +LDXWrzY0tM07+DKo7+N4ifuNRSzanLh+QBxh5z6ikixL8s36mLYp//Pye6kfLqCT +VyvehQP5aTfLnnhqBbTFMXiJ7HqnheG5ezzevh55hM6fcA5ZwjUukCox2eRFekGk +LhObNA5me0mrZJfQRsN5nXJQY6aYWwa9SG3YOYNw6DXwBdGqvOPbyALqfP2C2sJb +UjWumDqtujWTI6cfSN01RpiyEGjkpTHCClguGYEQyVB1/OpaFs4R1+7vUIgtYf8/ +QnMFlEPVjjxOAToZpR9GTnfQXeWBIiGH/pR9hNiTrdZoQ0iy2+tzJOeRf1SktoA+ +naM8THLCV8Sg1Mw4J87VBp6iSNnpn86CcDaTmjvfliHjWbcM2pE38P1ZWrOZyGls +QyYBNWNgVYkDOnXYukrZVP/u3oDYLdE41V4tC5h9Pmzb/CaIxw== +-----END CERTIFICATE----- + +# Issuer: CN=Go Daddy Root Certificate Authority - G2 O=GoDaddy.com, Inc. +# Subject: CN=Go Daddy Root Certificate Authority - G2 O=GoDaddy.com, Inc. +# Label: "Go Daddy Root Certificate Authority - G2" +# Serial: 0 +# MD5 Fingerprint: 80:3a:bc:22:c1:e6:fb:8d:9b:3b:27:4a:32:1b:9a:01 +# SHA1 Fingerprint: 47:be:ab:c9:22:ea:e8:0e:78:78:34:62:a7:9f:45:c2:54:fd:e6:8b +# SHA256 Fingerprint: 45:14:0b:32:47:eb:9c:c8:c5:b4:f0:d7:b5:30:91:f7:32:92:08:9e:6e:5a:63:e2:74:9d:d3:ac:a9:19:8e:da +-----BEGIN CERTIFICATE----- +MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMx +EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoT +EUdvRGFkZHkuY29tLCBJbmMuMTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRp +ZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIz +NTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQH +EwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8GA1UE +AxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIw +DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKD +E6bFIEMBO4Tx5oVJnyfq9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH +/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD+qK+ihVqf94Lw7YZFAXK6sOoBJQ7Rnwy +DfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutdfMh8+7ArU6SSYmlRJQVh +GkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMlNAJWJwGR +tDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEA +AaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE +FDqahQcQZyi27/a9BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmX +WWcDYfF+OwYxdS2hII5PZYe096acvNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu +9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r5N9ss4UXnT3ZJE95kTXWXwTr +gIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYVN8Gb5DKj7Tjo +2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO +LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI +4uJEvlz36hz1 +-----END CERTIFICATE----- + +# Issuer: CN=Starfield Root Certificate Authority - G2 O=Starfield Technologies, Inc. +# Subject: CN=Starfield Root Certificate Authority - G2 O=Starfield Technologies, Inc. +# Label: "Starfield Root Certificate Authority - G2" +# Serial: 0 +# MD5 Fingerprint: d6:39:81:c6:52:7e:96:69:fc:fc:ca:66:ed:05:f2:96 +# SHA1 Fingerprint: b5:1c:06:7c:ee:2b:0c:3d:f8:55:ab:2d:92:f4:fe:39:d4:e7:0f:0e +# SHA256 Fingerprint: 2c:e1:cb:0b:f9:d2:f9:e1:02:99:3f:be:21:51:52:c3:b2:dd:0c:ab:de:1c:68:e5:31:9b:83:91:54:db:b7:f5 +-----BEGIN CERTIFICATE----- +MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMx +EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT +HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVs +ZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAw +MFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6 +b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQgVGVj +aG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZp +Y2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBAL3twQP89o/8ArFvW59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMg +nLRJdzIpVv257IzdIvpy3Cdhl+72WoTsbhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1 +HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNkN3mSwOxGXn/hbVNMYq/N +Hwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7NfZTD4p7dN +dloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0 +HZbUJtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAO +BgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0G +CSqGSIb3DQEBCwUAA4IBAQARWfolTwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjU +sHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx4mcujJUDJi5DnUox9g61DLu3 +4jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUwF5okxBDgBPfg +8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K +pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1 +mMpYjn0q7pBZc2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0 +-----END CERTIFICATE----- + +# Issuer: CN=Starfield Services Root Certificate Authority - G2 O=Starfield Technologies, Inc. +# Subject: CN=Starfield Services Root Certificate Authority - G2 O=Starfield Technologies, Inc. +# Label: "Starfield Services Root Certificate Authority - G2" +# Serial: 0 +# MD5 Fingerprint: 17:35:74:af:7b:61:1c:eb:f4:f9:3c:e2:ee:40:f9:a2 +# SHA1 Fingerprint: 92:5a:8f:8d:2c:6d:04:e0:66:5f:59:6a:ff:22:d8:63:e8:25:6f:3f +# SHA256 Fingerprint: 56:8d:69:05:a2:c8:87:08:a4:b3:02:51:90:ed:cf:ed:b1:97:4a:60:6a:13:c6:e5:29:0f:cb:2a:e6:3e:da:b5 +-----BEGIN CERTIFICATE----- +MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMx +EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT +HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVs +ZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5 +MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNVBAYTAlVTMRAwDgYD +VQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFy +ZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2Vy +dmljZXMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20p +OsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm2 +8xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4PahHQUw2eeBGg6345AWh1K +Ts9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLPLJGmpufe +hRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk +6mFBrMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAw +DwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+q +AdcwKziIorhtSpzyEZGDMA0GCSqGSIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMI +bw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPPE95Dz+I0swSdHynVv/heyNXB +ve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTyxQGjhdByPq1z +qwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkd +iEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn +0q23KXB56jzaYyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCN +sSi6 +-----END CERTIFICATE----- + +# Issuer: CN=AffirmTrust Commercial O=AffirmTrust +# Subject: CN=AffirmTrust Commercial O=AffirmTrust +# Label: "AffirmTrust Commercial" +# Serial: 8608355977964138876 +# MD5 Fingerprint: 82:92:ba:5b:ef:cd:8a:6f:a6:3d:55:f9:84:f6:d6:b7 +# SHA1 Fingerprint: f9:b5:b6:32:45:5f:9c:be:ec:57:5f:80:dc:e9:6e:2c:c7:b2:78:b7 +# SHA256 Fingerprint: 03:76:ab:1d:54:c5:f9:80:3c:e4:b2:e2:01:a0:ee:7e:ef:7b:57:b6:36:e8:a9:3c:9b:8d:48:60:c9:6f:5f:a7 +-----BEGIN CERTIFICATE----- +MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UE +BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz +dCBDb21tZXJjaWFsMB4XDTEwMDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDEL +MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp +cm1UcnVzdCBDb21tZXJjaWFsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC +AQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTWzsO3qyxPxkEylFf6EqdbDuKP +Hx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U6Mje+SJIZMblq8Yr +ba0F8PrVC8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNAFxHUdPAL +MeIrJmqbTFeurCA+ukV6BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1 +yHp52UKqK39c/s4mT6NmgTWvRLpUHhwwMmWd5jyTXlBOeuM61G7MGvv50jeuJCqr +VwMiKA1JdX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNVHQ4EFgQUnZPGU4teyq8/ +nx4P5ZmVvCT2lI8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ +KoZIhvcNAQELBQADggEBAFis9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYG +XUPGhi4+c7ImfU+TqbbEKpqrIZcUsd6M06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNj +vbz4YYCanrHOQnDiqX0GJX0nof5v7LMeJNrjS1UaADs1tDvZ110w/YETifLCBivt +Z8SOyUOyXGsViQK8YvxO8rUzqrJv0wqiUOP2O+guRMLbZjipM1ZI8W0bM40NjD9g +N53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0khsUlHRUe072o0EclNmsxZt9YC +nlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8= +-----END CERTIFICATE----- + +# Issuer: CN=AffirmTrust Networking O=AffirmTrust +# Subject: CN=AffirmTrust Networking O=AffirmTrust +# Label: "AffirmTrust Networking" +# Serial: 8957382827206547757 +# MD5 Fingerprint: 42:65:ca:be:01:9a:9a:4c:a9:8c:41:49:cd:c0:d5:7f +# SHA1 Fingerprint: 29:36:21:02:8b:20:ed:02:f5:66:c5:32:d1:d6:ed:90:9f:45:00:2f +# SHA256 Fingerprint: 0a:81:ec:5a:92:97:77:f1:45:90:4a:f3:8d:5d:50:9f:66:b5:e2:c5:8f:cd:b5:31:05:8b:0e:17:f3:f0:b4:1b +-----BEGIN CERTIFICATE----- +MIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UE +BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz +dCBOZXR3b3JraW5nMB4XDTEwMDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDEL +MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp +cm1UcnVzdCBOZXR3b3JraW5nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC +AQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWREZY9nZOIG41w3SfYvm4SEHi3y +YJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ/Ls6rnla1fTWcbua +kCNrmreIdIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXLviRmVSRL +QESxG9fhwoXA3hA/Pe24/PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp +6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gbh+0t+nvujArjqWaJGctB+d1ENmHP4ndG +yH329JKBNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNVHQ4EFgQUBx/S55zawm6i +QLSwelAQUHTEyL0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ +KoZIhvcNAQEFBQADggEBAIlXshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfO +tDIuUFUaNU52Q3Eg75N3ThVwLofDwR1t3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzu +QY0x2+c06lkh1QF612S4ZDnNye2v7UsDSKegmQGA3GWjNq5lWUhPgkvIZfFXHeVZ +Lgo/bNjR9eUJtGxUAArgFU2HdW23WJZa3W3SAKD0m0i+wzekujbgfIeFlxoVot4u +olu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9/ZFvgrG+CJPbFEfxojfHRZ48 +x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s= +-----END CERTIFICATE----- + +# Issuer: CN=AffirmTrust Premium O=AffirmTrust +# Subject: CN=AffirmTrust Premium O=AffirmTrust +# Label: "AffirmTrust Premium" +# Serial: 7893706540734352110 +# MD5 Fingerprint: c4:5d:0e:48:b6:ac:28:30:4e:0a:bc:f9:38:16:87:57 +# SHA1 Fingerprint: d8:a6:33:2c:e0:03:6f:b1:85:f6:63:4f:7d:6a:06:65:26:32:28:27 +# SHA256 Fingerprint: 70:a7:3f:7f:37:6b:60:07:42:48:90:45:34:b1:14:82:d5:bf:0e:69:8e:cc:49:8d:f5:25:77:eb:f2:e9:3b:9a +-----BEGIN CERTIFICATE----- +MIIFRjCCAy6gAwIBAgIIbYwURrGmCu4wDQYJKoZIhvcNAQEMBQAwQTELMAkGA1UE +BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVz +dCBQcmVtaXVtMB4XDTEwMDEyOTE0MTAzNloXDTQwMTIzMTE0MTAzNlowQTELMAkG +A1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1U +cnVzdCBQcmVtaXVtMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxBLf +qV/+Qd3d9Z+K4/as4Tx4mrzY8H96oDMq3I0gW64tb+eT2TZwamjPjlGjhVtnBKAQ +JG9dKILBl1fYSCkTtuG+kU3fhQxTGJoeJKJPj/CihQvL9Cl/0qRY7iZNyaqoe5rZ ++jjeRFcV5fiMyNlI4g0WJx0eyIOFJbe6qlVBzAMiSy2RjYvmia9mx+n/K+k8rNrS +s8PhaJyJ+HoAVt70VZVs+7pk3WKL3wt3MutizCaam7uqYoNMtAZ6MMgpv+0GTZe5 +HMQxK9VfvFMSF5yZVylmd2EhMQcuJUmdGPLu8ytxjLW6OQdJd/zvLpKQBY0tL3d7 +70O/Nbua2Plzpyzy0FfuKE4mX4+QaAkvuPjcBukumj5Rp9EixAqnOEhss/n/fauG +V+O61oV4d7pD6kh/9ti+I20ev9E2bFhc8e6kGVQa9QPSdubhjL08s9NIS+LI+H+S +qHZGnEJlPqQewQcDWkYtuJfzt9WyVSHvutxMAJf7FJUnM7/oQ0dG0giZFmA7mn7S +5u046uwBHjxIVkkJx0w3AJ6IDsBz4W9m6XJHMD4Q5QsDyZpCAGzFlH5hxIrff4Ia +C1nEWTJ3s7xgaVY5/bQGeyzWZDbZvUjthB9+pSKPKrhC9IK31FOQeE4tGv2Bb0TX +OwF0lkLgAOIua+rF7nKsu7/+6qqo+Nz2snmKtmcCAwEAAaNCMEAwHQYDVR0OBBYE +FJ3AZ6YMItkm9UWrpmVSESfYRaxjMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/ +BAQDAgEGMA0GCSqGSIb3DQEBDAUAA4ICAQCzV00QYk465KzquByvMiPIs0laUZx2 +KI15qldGF9X1Uva3ROgIRL8YhNILgM3FEv0AVQVhh0HctSSePMTYyPtwni94loMg +Nt58D2kTiKV1NpgIpsbfrM7jWNa3Pt668+s0QNiigfV4Py/VpfzZotReBA4Xrf5B +8OWycvpEgjNC6C1Y91aMYj+6QrCcDFx+LmUmXFNPALJ4fqENmS2NuB2OosSw/WDQ +MKSOyARiqcTtNd56l+0OOF6SL5Nwpamcb6d9Ex1+xghIsV5n61EIJenmJWtSKZGc +0jlzCFfemQa0W50QBuHCAKi4HEoCChTQwUHK+4w1IX2COPKpVJEZNZOUbWo6xbLQ +u4mGk+ibyQ86p3q4ofB4Rvr8Ny/lioTz3/4E2aFooC8k4gmVBtWVyuEklut89pMF +u+1z6S3RdTnX5yTb2E5fQ4+e0BQ5v1VwSJlXMbSc7kqYA5YwH2AG7hsj/oFgIxpH +YoWlzBk0gG+zrBrjn/B7SK3VAdlntqlyk+otZrWyuOQ9PLLvTIzq6we/qzWaVYa8 +GKa1qF60g2xraUDTn9zxw2lrueFtCfTxqlB2Cnp9ehehVZZCmTEJ3WARjQUwfuaO +RtGdFNrHF+QFlozEJLUbzxQHskD4o55BhrwE0GuWyCqANP2/7waj3VjFhT0+j/6e +KeC2uAloGRwYQw== +-----END CERTIFICATE----- + +# Issuer: CN=AffirmTrust Premium ECC O=AffirmTrust +# Subject: CN=AffirmTrust Premium ECC O=AffirmTrust +# Label: "AffirmTrust Premium ECC" +# Serial: 8401224907861490260 +# MD5 Fingerprint: 64:b0:09:55:cf:b1:d5:99:e2:be:13:ab:a6:5d:ea:4d +# SHA1 Fingerprint: b8:23:6b:00:2f:1d:16:86:53:01:55:6c:11:a4:37:ca:eb:ff:c3:bb +# SHA256 Fingerprint: bd:71:fd:f6:da:97:e4:cf:62:d1:64:7a:dd:25:81:b0:7d:79:ad:f8:39:7e:b4:ec:ba:9c:5e:84:88:82:14:23 +-----BEGIN CERTIFICATE----- +MIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMC +VVMxFDASBgNVBAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQ +cmVtaXVtIEVDQzAeFw0xMDAxMjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJ +BgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1UcnVzdDEgMB4GA1UEAwwXQWZmaXJt +VHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQNMF4bFZ0D +0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQUX+iOGasvLkjmrBhDeKzQN8O9 +ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR4ptlKymjQjBAMB0G +A1UdDgQWBBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTADAQH/MA4G +A1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/Vs +aobgxCd05DhT1wV/GzTjxi+zygk8N53X57hG8f2h4nECMEJZh0PUUd+60wkyWs6I +flc9nF9Ca/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKMeQ== +-----END CERTIFICATE----- + +# Issuer: CN=Certum Trusted Network CA O=Unizeto Technologies S.A. OU=Certum Certification Authority +# Subject: CN=Certum Trusted Network CA O=Unizeto Technologies S.A. OU=Certum Certification Authority +# Label: "Certum Trusted Network CA" +# Serial: 279744 +# MD5 Fingerprint: d5:e9:81:40:c5:18:69:fc:46:2c:89:75:62:0f:aa:78 +# SHA1 Fingerprint: 07:e0:32:e0:20:b7:2c:3f:19:2f:06:28:a2:59:3a:19:a7:0f:06:9e +# SHA256 Fingerprint: 5c:58:46:8d:55:f5:8e:49:7e:74:39:82:d2:b5:00:10:b6:d1:65:37:4a:cf:83:a7:d4:a3:2d:b7:68:c4:40:8e +-----BEGIN CERTIFICATE----- +MIIDuzCCAqOgAwIBAgIDBETAMA0GCSqGSIb3DQEBBQUAMH4xCzAJBgNVBAYTAlBM +MSIwIAYDVQQKExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5D +ZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBU +cnVzdGVkIE5ldHdvcmsgQ0EwHhcNMDgxMDIyMTIwNzM3WhcNMjkxMjMxMTIwNzM3 +WjB+MQswCQYDVQQGEwJQTDEiMCAGA1UEChMZVW5pemV0byBUZWNobm9sb2dpZXMg +Uy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MSIw +IAYDVQQDExlDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENBMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEA4/t9o3K6wvDJFIf1awFO4W5AB7ptJ11/91sts1rH +UV+rpDKmYYe2bg+G0jACl/jXaVehGDldamR5xgFZrDwxSjh80gTSSyjoIF87B6LM +TXPb865Px1bVWqeWifrzq2jUI4ZZJ88JJ7ysbnKDHDBy3+Ci6dLhdHUZvSqeexVU +BBvXQzmtVSjF4hq79MDkrjhJM8x2hZ85RdKknvISjFH4fOQtf/WsX+sWn7Et0brM +kUJ3TCXJkDhv2/DM+44el1k+1WBO5gUo7Ul5E0u6SNsv+XLTOcr+H9g0cvW0QM8x +AcPs3hEtF10fuFDRXhmnad4HMyjKUJX5p1TLVIZQRan5SQIDAQABo0IwQDAPBgNV +HRMBAf8EBTADAQH/MB0GA1UdDgQWBBQIds3LB/8k9sXN7buQvOKEN0Z19zAOBgNV +HQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQEFBQADggEBAKaorSLOAT2mo/9i0Eidi15y +sHhE49wcrwn9I0j6vSrEuVUEtRCjjSfeC4Jj0O7eDDd5QVsisrCaQVymcODU0HfL +I9MA4GxWL+FpDQ3Zqr8hgVDZBqWo/5U30Kr+4rP1mS1FhIrlQgnXdAIv94nYmem8 +J9RHjboNRhx3zxSkHLmkMcScKHQDNP8zGSal6Q10tz6XxnboJ5ajZt3hrvJBW8qY +VoNzcOSGGtIxQbovvi0TWnZvTuhOgQ4/WwMioBK+ZlgRSssDxLQqKi2WF+A5VLxI +03YnnZotBqbJ7DnSq9ufmgsnAjUpsUCV5/nonFWIGUbWtzT1fs45mtk48VH3Tyw= +-----END CERTIFICATE----- + +# Issuer: CN=TWCA Root Certification Authority O=TAIWAN-CA OU=Root CA +# Subject: CN=TWCA Root Certification Authority O=TAIWAN-CA OU=Root CA +# Label: "TWCA Root Certification Authority" +# Serial: 1 +# MD5 Fingerprint: aa:08:8f:f6:f9:7b:b7:f2:b1:a7:1e:9b:ea:ea:bd:79 +# SHA1 Fingerprint: cf:9e:87:6d:d3:eb:fc:42:26:97:a3:b5:a3:7a:a0:76:a9:06:23:48 +# SHA256 Fingerprint: bf:d8:8f:e1:10:1c:41:ae:3e:80:1b:f8:be:56:35:0e:e9:ba:d1:a6:b9:bd:51:5e:dc:5c:6d:5b:87:11:ac:44 +-----BEGIN CERTIFICATE----- +MIIDezCCAmOgAwIBAgIBATANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJUVzES +MBAGA1UECgwJVEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFU +V0NBIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwODI4MDcyNDMz +WhcNMzAxMjMxMTU1OTU5WjBfMQswCQYDVQQGEwJUVzESMBAGA1UECgwJVEFJV0FO +LUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NBIFJvb3QgQ2VydGlm +aWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB +AQCwfnK4pAOU5qfeCTiRShFAh6d8WWQUe7UREN3+v9XAu1bihSX0NXIP+FPQQeFE +AcK0HMMxQhZHhTMidrIKbw/lJVBPhYa+v5guEGcevhEFhgWQxFnQfHgQsIBct+HH +K3XLfJ+utdGdIzdjp9xCoi2SBBtQwXu4PhvJVgSLL1KbralW6cH/ralYhzC2gfeX +RfwZVzsrb+RH9JlF/h3x+JejiB03HFyP4HYlmlD4oFT/RJB2I9IyxsOrBr/8+7/z +rX2SYgJbKdM1o5OaQ2RgXbL6Mv87BK9NQGr5x+PvI/1ry+UPizgN7gr8/g+YnzAx +3WxSZfmLgb4i4RxYA7qRG4kHAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV +HRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqOFsmjd6LWvJPelSDGRjjCDWmujANBgkq +hkiG9w0BAQUFAAOCAQEAPNV3PdrfibqHDAhUaiBQkr6wQT25JmSDCi/oQMCXKCeC +MErJk/9q56YAf4lCmtYR5VPOL8zy2gXE/uJQxDqGfczafhAJO5I1KlOy/usrBdls +XebQ79NqZp4VKIV66IIArB6nCWlWQtNoURi+VJq/REG6Sb4gumlc7rh3zc5sH62D +lhh9DrUUOYTxKOkto557HnpyWoOzeW/vtPzQCqVYT0bf+215WfKEIlKuD8z7fDvn +aspHYcN6+NOSBB+4IIThNlQWx0DeO4pz3N/GCUzf7Nr/1FNCocnyYh0igzyXxfkZ +YiesZSLX0zzG5Y6yU8xJzrww/nsOM5D77dIUkR8Hrw== +-----END CERTIFICATE----- + +# Issuer: O=SECOM Trust Systems CO.,LTD. OU=Security Communication RootCA2 +# Subject: O=SECOM Trust Systems CO.,LTD. OU=Security Communication RootCA2 +# Label: "Security Communication RootCA2" +# Serial: 0 +# MD5 Fingerprint: 6c:39:7d:a4:0e:55:59:b2:3f:d6:41:b1:12:50:de:43 +# SHA1 Fingerprint: 5f:3b:8c:f2:f8:10:b3:7d:78:b4:ce:ec:19:19:c3:73:34:b9:c7:74 +# SHA256 Fingerprint: 51:3b:2c:ec:b8:10:d4:cd:e5:dd:85:39:1a:df:c6:c2:dd:60:d8:7b:b7:36:d2:b5:21:48:4a:a4:7a:0e:be:f6 +-----BEGIN CERTIFICATE----- +MIIDdzCCAl+gAwIBAgIBADANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJKUDEl +MCMGA1UEChMcU0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UECxMe +U2VjdXJpdHkgQ29tbXVuaWNhdGlvbiBSb290Q0EyMB4XDTA5MDUyOTA1MDAzOVoX +DTI5MDUyOTA1MDAzOVowXTELMAkGA1UEBhMCSlAxJTAjBgNVBAoTHFNFQ09NIFRy +dXN0IFN5c3RlbXMgQ08uLExURC4xJzAlBgNVBAsTHlNlY3VyaXR5IENvbW11bmlj +YXRpb24gUm9vdENBMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANAV +OVKxUrO6xVmCxF1SrjpDZYBLx/KWvNs2l9amZIyoXvDjChz335c9S672XewhtUGr +zbl+dp+++T42NKA7wfYxEUV0kz1XgMX5iZnK5atq1LXaQZAQwdbWQonCv/Q4EpVM +VAX3NuRFg3sUZdbcDE3R3n4MqzvEFb46VqZab3ZpUql6ucjrappdUtAtCms1FgkQ +hNBqyjoGADdH5H5XTz+L62e4iKrFvlNVspHEfbmwhRkGeC7bYRr6hfVKkaHnFtWO +ojnflLhwHyg/i/xAXmODPIMqGplrz95Zajv8bxbXH/1KEOtOghY6rCcMU/Gt1SSw +awNQwS08Ft1ENCcadfsCAwEAAaNCMEAwHQYDVR0OBBYEFAqFqXdlBZh8QIH4D5cs +OPEK7DzPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3 +DQEBCwUAA4IBAQBMOqNErLlFsceTfsgLCkLfZOoc7llsCLqJX2rKSpWeeo8HxdpF +coJxDjrSzG+ntKEju/Ykn8sX/oymzsLS28yN/HH8AynBbF0zX2S2ZTuJbxh2ePXc +okgfGT+Ok+vx+hfuzU7jBBJV1uXk3fs+BXziHV7Gp7yXT2g69ekuCkO2r1dcYmh8 +t/2jioSgrGK+KwmHNPBqAbubKVY8/gA3zyNs8U6qtnRGEmyR7jTV7JqR50S+kDFy +1UkC9gLl9B/rfNmWVan/7Ir5mUf/NVoCqgTLiluHcSmRvaS0eg29mvVXIwAHIRc/ +SjnRBUkLp7Y3gaVdjKozXoEofKd9J+sAro03 +-----END CERTIFICATE----- + +# Issuer: CN=EC-ACC O=Agencia Catalana de Certificacio (NIF Q-0801176-I) OU=Serveis Publics de Certificacio/Vegeu https://www.catcert.net/verarrel (c)03/Jerarquia Entitats de Certificacio Catalanes +# Subject: CN=EC-ACC O=Agencia Catalana de Certificacio (NIF Q-0801176-I) OU=Serveis Publics de Certificacio/Vegeu https://www.catcert.net/verarrel (c)03/Jerarquia Entitats de Certificacio Catalanes +# Label: "EC-ACC" +# Serial: -23701579247955709139626555126524820479 +# MD5 Fingerprint: eb:f5:9d:29:0d:61:f9:42:1f:7c:c2:ba:6d:e3:15:09 +# SHA1 Fingerprint: 28:90:3a:63:5b:52:80:fa:e6:77:4c:0b:6d:a7:d6:ba:a6:4a:f2:e8 +# SHA256 Fingerprint: 88:49:7f:01:60:2f:31:54:24:6a:e2:8c:4d:5a:ef:10:f1:d8:7e:bb:76:62:6f:4a:e0:b7:f9:5b:a7:96:87:99 +-----BEGIN CERTIFICATE----- +MIIFVjCCBD6gAwIBAgIQ7is969Qh3hSoYqwE893EATANBgkqhkiG9w0BAQUFADCB +8zELMAkGA1UEBhMCRVMxOzA5BgNVBAoTMkFnZW5jaWEgQ2F0YWxhbmEgZGUgQ2Vy +dGlmaWNhY2lvIChOSUYgUS0wODAxMTc2LUkpMSgwJgYDVQQLEx9TZXJ2ZWlzIFB1 +YmxpY3MgZGUgQ2VydGlmaWNhY2lvMTUwMwYDVQQLEyxWZWdldSBodHRwczovL3d3 +dy5jYXRjZXJ0Lm5ldC92ZXJhcnJlbCAoYykwMzE1MDMGA1UECxMsSmVyYXJxdWlh +IEVudGl0YXRzIGRlIENlcnRpZmljYWNpbyBDYXRhbGFuZXMxDzANBgNVBAMTBkVD +LUFDQzAeFw0wMzAxMDcyMzAwMDBaFw0zMTAxMDcyMjU5NTlaMIHzMQswCQYDVQQG +EwJFUzE7MDkGA1UEChMyQWdlbmNpYSBDYXRhbGFuYSBkZSBDZXJ0aWZpY2FjaW8g +KE5JRiBRLTA4MDExNzYtSSkxKDAmBgNVBAsTH1NlcnZlaXMgUHVibGljcyBkZSBD +ZXJ0aWZpY2FjaW8xNTAzBgNVBAsTLFZlZ2V1IGh0dHBzOi8vd3d3LmNhdGNlcnQu +bmV0L3ZlcmFycmVsIChjKTAzMTUwMwYDVQQLEyxKZXJhcnF1aWEgRW50aXRhdHMg +ZGUgQ2VydGlmaWNhY2lvIENhdGFsYW5lczEPMA0GA1UEAxMGRUMtQUNDMIIBIjAN +BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsyLHT+KXQpWIR4NA9h0X84NzJB5R +85iKw5K4/0CQBXCHYMkAqbWUZRkiFRfCQ2xmRJoNBD45b6VLeqpjt4pEndljkYRm +4CgPukLjbo73FCeTae6RDqNfDrHrZqJyTxIThmV6PttPB/SnCWDaOkKZx7J/sxaV +HMf5NLWUhdWZXqBIoH7nF2W4onW4HvPlQn2v7fOKSGRdghST2MDk/7NQcvJ29rNd +QlB50JQ+awwAvthrDk4q7D7SzIKiGGUzE3eeml0aE9jD2z3Il3rucO2n5nzbcc8t +lGLfbdb1OL4/pYUKGbio2Al1QnDE6u/LDsg0qBIimAy4E5S2S+zw0JDnJwIDAQAB +o4HjMIHgMB0GA1UdEQQWMBSBEmVjX2FjY0BjYXRjZXJ0Lm5ldDAPBgNVHRMBAf8E +BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUoMOLRKo3pUW/l4Ba0fF4 +opvpXY0wfwYDVR0gBHgwdjB0BgsrBgEEAfV4AQMBCjBlMCwGCCsGAQUFBwIBFiBo +dHRwczovL3d3dy5jYXRjZXJ0Lm5ldC92ZXJhcnJlbDA1BggrBgEFBQcCAjApGidW +ZWdldSBodHRwczovL3d3dy5jYXRjZXJ0Lm5ldC92ZXJhcnJlbCAwDQYJKoZIhvcN +AQEFBQADggEBAKBIW4IB9k1IuDlVNZyAelOZ1Vr/sXE7zDkJlF7W2u++AVtd0x7Y +/X1PzaBB4DSTv8vihpw3kpBWHNzrKQXlxJ7HNd+KDM3FIUPpqojlNcAZQmNaAl6k +SBg6hW/cnbw/nZzBh7h6YQjpdwt/cKt63dmXLGQehb+8dJahw3oS7AwaboMMPOhy +Rp/7SNVel+axofjk70YllJyJ22k4vuxcDlbHZVHlUIiIv0LVKz3l+bqeLrPK9HOS +Agu+TGbrIP65y7WZf+a2E/rKS03Z7lNGBjvGTq2TWoF+bCpLagVFjPIhpDGQh2xl +nJ2lYJU6Un/10asIbvPuW/mIPX64b24D5EI= +-----END CERTIFICATE----- + +# Issuer: CN=Hellenic Academic and Research Institutions RootCA 2011 O=Hellenic Academic and Research Institutions Cert. Authority +# Subject: CN=Hellenic Academic and Research Institutions RootCA 2011 O=Hellenic Academic and Research Institutions Cert. Authority +# Label: "Hellenic Academic and Research Institutions RootCA 2011" +# Serial: 0 +# MD5 Fingerprint: 73:9f:4c:4b:73:5b:79:e9:fa:ba:1c:ef:6e:cb:d5:c9 +# SHA1 Fingerprint: fe:45:65:9b:79:03:5b:98:a1:61:b5:51:2e:ac:da:58:09:48:22:4d +# SHA256 Fingerprint: bc:10:4f:15:a4:8b:e7:09:dc:a5:42:a7:e1:d4:b9:df:6f:05:45:27:e8:02:ea:a9:2d:59:54:44:25:8a:fe:71 +-----BEGIN CERTIFICATE----- +MIIEMTCCAxmgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBlTELMAkGA1UEBhMCR1Ix +RDBCBgNVBAoTO0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1 +dGlvbnMgQ2VydC4gQXV0aG9yaXR5MUAwPgYDVQQDEzdIZWxsZW5pYyBBY2FkZW1p +YyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIFJvb3RDQSAyMDExMB4XDTExMTIw +NjEzNDk1MloXDTMxMTIwMTEzNDk1MlowgZUxCzAJBgNVBAYTAkdSMUQwQgYDVQQK +EztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIENl +cnQuIEF1dGhvcml0eTFAMD4GA1UEAxM3SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJl +c2VhcmNoIEluc3RpdHV0aW9ucyBSb290Q0EgMjAxMTCCASIwDQYJKoZIhvcNAQEB +BQADggEPADCCAQoCggEBAKlTAOMupvaO+mDYLZU++CwqVE7NuYRhlFhPjz2L5EPz +dYmNUeTDN9KKiE15HrcS3UN4SoqS5tdI1Q+kOilENbgH9mgdVc04UfCMJDGFr4PJ +fel3r+0ae50X+bOdOFAPplp5kYCvN66m0zH7tSYJnTxa71HFK9+WXesyHgLacEns +bgzImjeN9/E2YEsmLIKe0HjzDQ9jpFEw4fkrJxIH2Oq9GGKYsFk3fb7u8yBRQlqD +75O6aRXxYp2fmTmCobd0LovUxQt7L/DICto9eQqakxylKHJzkUOap9FNhYS5qXSP +FEDH3N6sQWRstBmbAmNtJGSPRLIl6s5ddAxjMlyNh+UCAwEAAaOBiTCBhjAPBgNV +HRMBAf8EBTADAQH/MAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQUppFC/RNhSiOeCKQp +5dgTBCPuQSUwRwYDVR0eBEAwPqA8MAWCAy5ncjAFggMuZXUwBoIELmVkdTAGggQu +b3JnMAWBAy5ncjAFgQMuZXUwBoEELmVkdTAGgQQub3JnMA0GCSqGSIb3DQEBBQUA +A4IBAQAf73lB4XtuP7KMhjdCSk4cNx6NZrokgclPEg8hwAOXhiVtXdMiKahsog2p +6z0GW5k6x8zDmjR/qw7IThzh+uTczQ2+vyT+bOdrwg3IBp5OjWEopmr95fZi6hg8 +TqBTnbI6nOulnJEWtk2C4AwFSKls9cz4y51JtPACpf1wA+2KIaWuE4ZJwzNzvoc7 +dIsXRSZMFpGD/md9zU1jZ/rzAxKWeAaNsWftjj++n08C9bMJL/NMh98qy5V8Acys +Nnq/onN694/BtZqhFLKPM58N7yLcZnuEvUUXBj08yrl3NI/K6s8/MT7jiOOASSXI +l7WdmplNsDz4SgCbZN2fOUvRJ9e4 +-----END CERTIFICATE----- + +# Issuer: CN=Actalis Authentication Root CA O=Actalis S.p.A./03358520967 +# Subject: CN=Actalis Authentication Root CA O=Actalis S.p.A./03358520967 +# Label: "Actalis Authentication Root CA" +# Serial: 6271844772424770508 +# MD5 Fingerprint: 69:c1:0d:4f:07:a3:1b:c3:fe:56:3d:04:bc:11:f6:a6 +# SHA1 Fingerprint: f3:73:b3:87:06:5a:28:84:8a:f2:f3:4a:ce:19:2b:dd:c7:8e:9c:ac +# SHA256 Fingerprint: 55:92:60:84:ec:96:3a:64:b9:6e:2a:be:01:ce:0b:a8:6a:64:fb:fe:bc:c7:aa:b5:af:c1:55:b3:7f:d7:60:66 +-----BEGIN CERTIFICATE----- +MIIFuzCCA6OgAwIBAgIIVwoRl0LE48wwDQYJKoZIhvcNAQELBQAwazELMAkGA1UE +BhMCSVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8w +MzM1ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290 +IENBMB4XDTExMDkyMjExMjIwMloXDTMwMDkyMjExMjIwMlowazELMAkGA1UEBhMC +SVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8wMzM1 +ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290IENB +MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAp8bEpSmkLO/lGMWwUKNv +UTufClrJwkg4CsIcoBh/kbWHuUA/3R1oHwiD1S0eiKD4j1aPbZkCkpAW1V8IbInX +4ay8IMKx4INRimlNAJZaby/ARH6jDuSRzVju3PvHHkVH3Se5CAGfpiEd9UEtL0z9 +KK3giq0itFZljoZUj5NDKd45RnijMCO6zfB9E1fAXdKDa0hMxKufgFpbOr3JpyI/ +gCczWw63igxdBzcIy2zSekciRDXFzMwujt0q7bd9Zg1fYVEiVRvjRuPjPdA1Yprb +rxTIW6HMiRvhMCb8oJsfgadHHwTrozmSBp+Z07/T6k9QnBn+locePGX2oxgkg4YQ +51Q+qDp2JE+BIcXjDwL4k5RHILv+1A7TaLndxHqEguNTVHnd25zS8gebLra8Pu2F +be8lEfKXGkJh90qX6IuxEAf6ZYGyojnP9zz/GPvG8VqLWeICrHuS0E4UT1lF9gxe +KF+w6D9Fz8+vm2/7hNN3WpVvrJSEnu68wEqPSpP4RCHiMUVhUE4Q2OM1fEwZtN4F +v6MGn8i1zeQf1xcGDXqVdFUNaBr8EBtiZJ1t4JWgw5QHVw0U5r0F+7if5t+L4sbn +fpb2U8WANFAoWPASUHEXMLrmeGO89LKtmyuy/uE5jF66CyCU3nuDuP/jVo23Eek7 +jPKxwV2dpAtMK9myGPW1n0sCAwEAAaNjMGEwHQYDVR0OBBYEFFLYiDrIn3hm7Ynz +ezhwlMkCAjbQMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUUtiIOsifeGbt +ifN7OHCUyQICNtAwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQAL +e3KHwGCmSUyIWOYdiPcUZEim2FgKDk8TNd81HdTtBjHIgT5q1d07GjLukD0R0i70 +jsNjLiNmsGe+b7bAEzlgqqI0JZN1Ut6nna0Oh4lScWoWPBkdg/iaKWW+9D+a2fDz +WochcYBNy+A4mz+7+uAwTc+G02UQGRjRlwKxK3JCaKygvU5a2hi/a5iB0P2avl4V +SM0RFbnAKVy06Ij3Pjaut2L9HmLecHgQHEhb2rykOLpn7VU+Xlff1ANATIGk0k9j +pwlCCRT8AKnCgHNPLsBA2RF7SOp6AsDT6ygBJlh0wcBzIm2Tlf05fbsq4/aC4yyX +X04fkZT6/iyj2HYauE2yOE+b+h1IYHkm4vP9qdCa6HCPSXrW5b0KDtst842/6+Ok +fcvHlXHo2qN8xcL4dJIEG4aspCJTQLas/kx2z/uUMsA1n3Y/buWQbqCmJqK4LL7R +K4X9p2jIugErsWx0Hbhzlefut8cl8ABMALJ+tguLHPPAUJ4lueAI3jZm/zel0btU +ZCzJJ7VLkn5l/9Mt4blOvH+kQSGQQXemOR/qnuOf0GZvBeyqdn6/axag67XH/JJU +LysRJyU3eExRarDzzFhdFPFqSBX/wge2sY0PjlxQRrM9vwGYT7JZVEc+NHt4bVaT +LnPqZih4zR0Uv6CPLy64Lo7yFIrM6bV8+2ydDKXhlg== +-----END CERTIFICATE----- + +# Issuer: CN=Buypass Class 2 Root CA O=Buypass AS-983163327 +# Subject: CN=Buypass Class 2 Root CA O=Buypass AS-983163327 +# Label: "Buypass Class 2 Root CA" +# Serial: 2 +# MD5 Fingerprint: 46:a7:d2:fe:45:fb:64:5a:a8:59:90:9b:78:44:9b:29 +# SHA1 Fingerprint: 49:0a:75:74:de:87:0a:47:fe:58:ee:f6:c7:6b:eb:c6:0b:12:40:99 +# SHA256 Fingerprint: 9a:11:40:25:19:7c:5b:b9:5d:94:e6:3d:55:cd:43:79:08:47:b6:46:b2:3c:df:11:ad:a4:a0:0e:ff:15:fb:48 +-----BEGIN CERTIFICATE----- +MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEd +MBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3Mg +Q2xhc3MgMiBSb290IENBMB4XDTEwMTAyNjA4MzgwM1oXDTQwMTAyNjA4MzgwM1ow +TjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBhc3MgQVMtOTgzMTYzMzI3MSAw +HgYDVQQDDBdCdXlwYXNzIENsYXNzIDIgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEB +BQADggIPADCCAgoCggIBANfHXvfBB9R3+0Mh9PT1aeTuMgHbo4Yf5FkNuud1g1Lr +6hxhFUi7HQfKjK6w3Jad6sNgkoaCKHOcVgb/S2TwDCo3SbXlzwx87vFKu3MwZfPV +L4O2fuPn9Z6rYPnT8Z2SdIrkHJasW4DptfQxh6NR/Md+oW+OU3fUl8FVM5I+GC91 +1K2GScuVr1QGbNgGE41b/+EmGVnAJLqBcXmQRFBoJJRfuLMR8SlBYaNByyM21cHx +MlAQTn/0hpPshNOOvEu/XAFOBz3cFIqUCqTqc/sLUegTBxj6DvEr0VQVfTzh97QZ +QmdiXnfgolXsttlpF9U6r0TtSsWe5HonfOV116rLJeffawrbD02TTqigzXsu8lkB +arcNuAeBfos4GzjmCleZPe4h6KP1DBbdi+w0jpwqHAAVF41og9JwnxgIzRFo1clr +Us3ERo/ctfPYV3Me6ZQ5BL/T3jjetFPsaRyifsSP5BtwrfKi+fv3FmRmaZ9JUaLi +FRhnBkp/1Wy1TbMz4GHrXb7pmA8y1x1LPC5aAVKRCfLf6o3YBkBjqhHk/sM3nhRS +P/TizPJhk9H9Z2vXUq6/aKtAQ6BXNVN48FP4YUIHZMbXb5tMOA1jrGKvNouicwoN +9SG9dKpN6nIDSdvHXx1iY8f93ZHsM+71bbRuMGjeyNYmsHVee7QHIJihdjK4TWxP +AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFMmAd+BikoL1Rpzz +uvdMw964o605MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAU18h +9bqwOlI5LJKwbADJ784g7wbylp7ppHR/ehb8t/W2+xUbP6umwHJdELFx7rxP462s +A20ucS6vxOOto70MEae0/0qyexAQH6dXQbLArvQsWdZHEIjzIVEpMMpghq9Gqx3t +OluwlN5E40EIosHsHdb9T7bWR9AUC8rmyrV7d35BH16Dx7aMOZawP5aBQW9gkOLo ++fsicdl9sz1Gv7SEr5AcD48Saq/v7h56rgJKihcrdv6sVIkkLE8/trKnToyokZf7 +KcZ7XC25y2a2t6hbElGFtQl+Ynhw/qlqYLYdDnkM/crqJIByw5c/8nerQyIKx+u2 +DISCLIBrQYoIwOula9+ZEsuK1V6ADJHgJgg2SMX6OBE1/yWDLfJ6v9r9jv6ly0Us +H8SIU653DtmadsWOLB2jutXsMq7Aqqz30XpN69QH4kj3Io6wpJ9qzo6ysmD0oyLQ +I+uUWnpp3Q+/QFesa1lQ2aOZ4W7+jQF5JyMV3pKdewlNWudLSDBaGOYKbeaP4NK7 +5t98biGCwWg5TbSYWGZizEqQXsP6JwSxeRV0mcy+rSDeJmAc61ZRpqPq5KM/p/9h +3PFaTWwyI0PurKju7koSCTxdccK+efrCh2gdC/1cacwG0Jp9VJkqyTkaGa9LKkPz +Y11aWOIv4x3kqdbQCtCev9eBCfHJxyYNrJgWVqA= +-----END CERTIFICATE----- + +# Issuer: CN=Buypass Class 3 Root CA O=Buypass AS-983163327 +# Subject: CN=Buypass Class 3 Root CA O=Buypass AS-983163327 +# Label: "Buypass Class 3 Root CA" +# Serial: 2 +# MD5 Fingerprint: 3d:3b:18:9e:2c:64:5a:e8:d5:88:ce:0e:f9:37:c2:ec +# SHA1 Fingerprint: da:fa:f7:fa:66:84:ec:06:8f:14:50:bd:c7:c2:81:a5:bc:a9:64:57 +# SHA256 Fingerprint: ed:f7:eb:bc:a2:7a:2a:38:4d:38:7b:7d:40:10:c6:66:e2:ed:b4:84:3e:4c:29:b4:ae:1d:5b:93:32:e6:b2:4d +-----BEGIN CERTIFICATE----- +MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEd +MBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3Mg +Q2xhc3MgMyBSb290IENBMB4XDTEwMTAyNjA4Mjg1OFoXDTQwMTAyNjA4Mjg1OFow +TjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBhc3MgQVMtOTgzMTYzMzI3MSAw +HgYDVQQDDBdCdXlwYXNzIENsYXNzIDMgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEB +BQADggIPADCCAgoCggIBAKXaCpUWUOOV8l6ddjEGMnqb8RB2uACatVI2zSRHsJ8Y +ZLya9vrVediQYkwiL944PdbgqOkcLNt4EemOaFEVcsfzM4fkoF0LXOBXByow9c3E +N3coTRiR5r/VUv1xLXA+58bEiuPwKAv0dpihi4dVsjoT/Lc+JzeOIuOoTyrvYLs9 +tznDDgFHmV0ST9tD+leh7fmdvhFHJlsTmKtdFoqwNxxXnUX/iJY2v7vKB3tvh2PX +0DJq1l1sDPGzbjniazEuOQAnFN44wOwZZoYS6J1yFhNkUsepNxz9gjDthBgd9K5c +/3ATAOux9TN6S9ZV+AWNS2mw9bMoNlwUxFFzTWsL8TQH2xc519woe2v1n/MuwU8X +KhDzzMro6/1rqy6any2CbgTUUgGTLT2G/H783+9CHaZr77kgxve9oKeV/afmiSTY +zIw0bOIjL9kSGiG5VZFvC5F5GQytQIgLcOJ60g7YaEi7ghM5EFjp2CoHxhLbWNvS +O1UQRwUVZ2J+GGOmRj8JDlQyXr8NYnon74Do29lLBlo3WiXQCBJ31G8JUJc9yB3D +34xFMFbG02SrZvPAXpacw8Tvw3xrizp5f7NJzz3iiZ+gMEuFuZyUJHmPfWupRWgP +K9Dx2hzLabjKSWJtyNBjYt1gD1iqj6G8BaVmos8bdrKEZLFMOVLAMLrwjEsCsLa3 +AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFEe4zf/lb+74suwv +Tg75JbCOPGvDMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAACAj +QTUEkMJAYmDv4jVM1z+s4jSQuKFvdvoWFqRINyzpkMLyPPgKn9iB5btb2iUspKdV +cSQy9sgL8rxq+JOssgfCX5/bzMiKqr5qb+FJEMwx14C7u8jYog5kV+qi9cKpMRXS +IGrs/CIBKM+GuIAeqcwRpTzyFrNHnfzSgCHEy9BHcEGhyoMZCCxt8l13nIoUE9Q2 +HJLw5QY33KbmkJs4j1xrG0aGQ0JfPgEHU1RdZX33inOhmlRaHylDFCfChQ+1iHsa +O5S3HWCntZznKWlXWpuTekMwGwPXYshApqr8ZORK15FTAaggiG6cX0S5y2CBNOxv +033aSF/rtJC8LakcC6wc1aJoIIAE1vyxjy+7SjENSoYc6+I2KSb12tjE8nVhz36u +dmNKekBlk4f4HoCMhuWG1o8O/FMsYOgWYRqiPkN7zTlgVGr18okmAWiDSKIz6MkE +kbIRNBE+6tBDGR8Dk5AM/1E9V/RBbuHLoL7ryWPNbczk+DaqaJ3tvV2XcEQNtg41 +3OEMXbugUZTLfhbrES+jkkXITHHZvMmZUldGL1DPvTVp9D0VzgalLA8+9oG6lLvD +u79leNKGef9JOxqDDPDeeOzI8k1MGt6CKfjBWtrt7uYnXuhF0J0cUahoq0Tj0Itq +4/g7u9xN12TyUb7mqqta6THuBrxzvxNiCp/HuZc= +-----END CERTIFICATE----- + +# Issuer: CN=T-TeleSec GlobalRoot Class 3 O=T-Systems Enterprise Services GmbH OU=T-Systems Trust Center +# Subject: CN=T-TeleSec GlobalRoot Class 3 O=T-Systems Enterprise Services GmbH OU=T-Systems Trust Center +# Label: "T-TeleSec GlobalRoot Class 3" +# Serial: 1 +# MD5 Fingerprint: ca:fb:40:a8:4e:39:92:8a:1d:fe:8e:2f:c4:27:ea:ef +# SHA1 Fingerprint: 55:a6:72:3e:cb:f2:ec:cd:c3:23:74:70:19:9d:2a:be:11:e3:81:d1 +# SHA256 Fingerprint: fd:73:da:d3:1c:64:4f:f1:b4:3b:ef:0c:cd:da:96:71:0b:9c:d9:87:5e:ca:7e:31:70:7a:f3:e9:6d:52:2b:bd +-----BEGIN CERTIFICATE----- +MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUx +KzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAd +BgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNl +YyBHbG9iYWxSb290IENsYXNzIDMwHhcNMDgxMDAxMTAyOTU2WhcNMzMxMDAxMjM1 +OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnBy +aXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50 +ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwggEiMA0G +CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC9dZPwYiJvJK7genasfb3ZJNW4t/zN +8ELg63iIVl6bmlQdTQyK9tPPcPRStdiTBONGhnFBSivwKixVA9ZIw+A5OO3yXDw/ +RLyTPWGrTs0NvvAgJ1gORH8EGoel15YUNpDQSXuhdfsaa3Ox+M6pCSzyU9XDFES4 +hqX2iys52qMzVNn6chr3IhUciJFrf2blw2qAsCTz34ZFiP0Zf3WHHx+xGwpzJFu5 +ZeAsVMhg02YXP+HMVDNzkQI6pn97djmiH5a2OK61yJN0HZ65tOVgnS9W0eDrXltM +EnAMbEQgqxHY9Bn20pxSN+f6tsIxO0rUFJmtxxr1XV/6B7h8DR/Wgx6zAgMBAAGj +QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS1 +A/d2O2GCahKqGFPrAyGUv/7OyjANBgkqhkiG9w0BAQsFAAOCAQEAVj3vlNW92nOy +WL6ukK2YJ5f+AbGwUgC4TeQbIXQbfsDuXmkqJa9c1h3a0nnJ85cp4IaH3gRZD/FZ +1GSFS5mvJQQeyUapl96Cshtwn5z2r3Ex3XsFpSzTucpH9sry9uetuUg/vBa3wW30 +6gmv7PO15wWeph6KU1HWk4HMdJP2udqmJQV0eVp+QD6CSyYRMG7hP0HHRwA11fXT +91Q+gT3aSWqas+8QPebrb9HIIkfLzM8BMZLZGOMivgkeGj5asuRrDFR6fUNOuIml +e9eiPZaGzPImNC1qkp2aGtAw4l1OBLBfiyB+d8E9lYLRRpo7PHi4b6HQDWSieB4p +TpPDpFQUWw== +-----END CERTIFICATE----- + +# Issuer: CN=D-TRUST Root Class 3 CA 2 2009 O=D-Trust GmbH +# Subject: CN=D-TRUST Root Class 3 CA 2 2009 O=D-Trust GmbH +# Label: "D-TRUST Root Class 3 CA 2 2009" +# Serial: 623603 +# MD5 Fingerprint: cd:e0:25:69:8d:47:ac:9c:89:35:90:f7:fd:51:3d:2f +# SHA1 Fingerprint: 58:e8:ab:b0:36:15:33:fb:80:f7:9b:1b:6d:29:d3:ff:8d:5f:00:f0 +# SHA256 Fingerprint: 49:e7:a4:42:ac:f0:ea:62:87:05:00:54:b5:25:64:b6:50:e4:f4:9e:42:e3:48:d6:aa:38:e0:39:e9:57:b1:c1 +-----BEGIN CERTIFICATE----- +MIIEMzCCAxugAwIBAgIDCYPzMA0GCSqGSIb3DQEBCwUAME0xCzAJBgNVBAYTAkRF +MRUwEwYDVQQKDAxELVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBD +bGFzcyAzIENBIDIgMjAwOTAeFw0wOTExMDUwODM1NThaFw0yOTExMDUwODM1NTha +ME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxELVRydXN0IEdtYkgxJzAlBgNVBAMM +HkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTCCASIwDQYJKoZIhvcNAQEB +BQADggEPADCCAQoCggEBANOySs96R+91myP6Oi/WUEWJNTrGa9v+2wBoqOADER03 +UAifTUpolDWzU9GUY6cgVq/eUXjsKj3zSEhQPgrfRlWLJ23DEE0NkVJD2IfgXU42 +tSHKXzlABF9bfsyjxiupQB7ZNoTWSPOSHjRGICTBpFGOShrvUD9pXRl/RcPHAY9R +ySPocq60vFYJfxLLHLGvKZAKyVXMD9O0Gu1HNVpK7ZxzBCHQqr0ME7UAyiZsxGsM +lFqVlNpQmvH/pStmMaTJOKDfHR+4CS7zp+hnUquVH+BGPtikw8paxTGA6Eian5Rp +/hnd2HN8gcqW3o7tszIFZYQ05ub9VxC1X3a/L7AQDcUCAwEAAaOCARowggEWMA8G +A1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFP3aFMSfMN4hvR5COfyrYyNJ4PGEMA4G +A1UdDwEB/wQEAwIBBjCB0wYDVR0fBIHLMIHIMIGAoH6gfIZ6bGRhcDovL2RpcmVj +dG9yeS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwUm9vdCUyMENsYXNzJTIwMyUy +MENBJTIwMiUyMDIwMDksTz1ELVRydXN0JTIwR21iSCxDPURFP2NlcnRpZmljYXRl +cmV2b2NhdGlvbmxpc3QwQ6BBoD+GPWh0dHA6Ly93d3cuZC10cnVzdC5uZXQvY3Js +L2QtdHJ1c3Rfcm9vdF9jbGFzc18zX2NhXzJfMjAwOS5jcmwwDQYJKoZIhvcNAQEL +BQADggEBAH+X2zDI36ScfSF6gHDOFBJpiBSVYEQBrLLpME+bUMJm2H6NMLVwMeni +acfzcNsgFYbQDfC+rAF1hM5+n02/t2A7nPPKHeJeaNijnZflQGDSNiH+0LS4F9p0 +o3/U37CYAqxva2ssJSRyoWXuJVrl5jLn8t+rSfrzkGkj2wTZ51xY/GXUl77M/C4K +zCUqNQT4YJEVdT1B/yMfGchs64JTBKbkTCJNjYy6zltz7GRUUG3RnFX7acM2w4y8 +PIWmawomDeCTmGCufsYkl4phX5GOZpIJhzbNi5stPvZR1FDUWSi9g/LMKHtThm3Y +Johw1+qRzT65ysCQblrGXnRl11z+o+I= +-----END CERTIFICATE----- + +# Issuer: CN=D-TRUST Root Class 3 CA 2 EV 2009 O=D-Trust GmbH +# Subject: CN=D-TRUST Root Class 3 CA 2 EV 2009 O=D-Trust GmbH +# Label: "D-TRUST Root Class 3 CA 2 EV 2009" +# Serial: 623604 +# MD5 Fingerprint: aa:c6:43:2c:5e:2d:cd:c4:34:c0:50:4f:11:02:4f:b6 +# SHA1 Fingerprint: 96:c9:1b:0b:95:b4:10:98:42:fa:d0:d8:22:79:fe:60:fa:b9:16:83 +# SHA256 Fingerprint: ee:c5:49:6b:98:8c:e9:86:25:b9:34:09:2e:ec:29:08:be:d0:b0:f3:16:c2:d4:73:0c:84:ea:f1:f3:d3:48:81 +-----BEGIN CERTIFICATE----- +MIIEQzCCAyugAwIBAgIDCYP0MA0GCSqGSIb3DQEBCwUAMFAxCzAJBgNVBAYTAkRF +MRUwEwYDVQQKDAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBD +bGFzcyAzIENBIDIgRVYgMjAwOTAeFw0wOTExMDUwODUwNDZaFw0yOTExMDUwODUw +NDZaMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxELVRydXN0IEdtYkgxKjAoBgNV +BAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAwOTCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAJnxhDRwui+3MKCOvXwEz75ivJn9gpfSegpn +ljgJ9hBOlSJzmY3aFS3nBfwZcyK3jpgAvDw9rKFs+9Z5JUut8Mxk2og+KbgPCdM0 +3TP1YtHhzRnp7hhPTFiu4h7WDFsVWtg6uMQYZB7jM7K1iXdODL/ZlGsTl28So/6Z +qQTMFexgaDbtCHu39b+T7WYxg4zGcTSHThfqr4uRjRxWQa4iN1438h3Z0S0NL2lR +p75mpoo6Kr3HGrHhFPC+Oh25z1uxav60sUYgovseO3Dvk5h9jHOW8sXvhXCtKSb8 +HgQ+HKDYD8tSg2J87otTlZCpV6LqYQXY+U3EJ/pure3511H3a6UCAwEAAaOCASQw +ggEgMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNOUikxiEyoZLsyvcop9Ntea +HNxnMA4GA1UdDwEB/wQEAwIBBjCB3QYDVR0fBIHVMIHSMIGHoIGEoIGBhn9sZGFw +Oi8vZGlyZWN0b3J5LmQtdHJ1c3QubmV0L0NOPUQtVFJVU1QlMjBSb290JTIwQ2xh +c3MlMjAzJTIwQ0ElMjAyJTIwRVYlMjAyMDA5LE89RC1UcnVzdCUyMEdtYkgsQz1E +RT9jZXJ0aWZpY2F0ZXJldm9jYXRpb25saXN0MEagRKBChkBodHRwOi8vd3d3LmQt +dHJ1c3QubmV0L2NybC9kLXRydXN0X3Jvb3RfY2xhc3NfM19jYV8yX2V2XzIwMDku +Y3JsMA0GCSqGSIb3DQEBCwUAA4IBAQA07XtaPKSUiO8aEXUHL7P+PPoeUSbrh/Yp +3uDx1MYkCenBz1UbtDDZzhr+BlGmFaQt77JLvyAoJUnRpjZ3NOhk31KxEcdzes05 +nsKtjHEh8lprr988TlWvsoRlFIm5d8sqMb7Po23Pb0iUMkZv53GMoKaEGTcH8gNF +CSuGdXzfX2lXANtu2KZyIktQ1HWYVt+3GP9DQ1CuekR78HlR10M9p9OB0/DJT7na +xpeG0ILD5EJt/rDiZE4OJudANCa1CInXCGNjOCd1HjPqbqjdn5lPdE2BiYBL3ZqX +KVwvvoFBuYz/6n1gBp7N1z3TLqMVvKjmJuVvw9y4AyHqnxbxLFS1 +-----END CERTIFICATE----- + +# Issuer: CN=CA Disig Root R2 O=Disig a.s. +# Subject: CN=CA Disig Root R2 O=Disig a.s. +# Label: "CA Disig Root R2" +# Serial: 10572350602393338211 +# MD5 Fingerprint: 26:01:fb:d8:27:a7:17:9a:45:54:38:1a:43:01:3b:03 +# SHA1 Fingerprint: b5:61:eb:ea:a4:de:e4:25:4b:69:1a:98:a5:57:47:c2:34:c7:d9:71 +# SHA256 Fingerprint: e2:3d:4a:03:6d:7b:70:e9:f5:95:b1:42:20:79:d2:b9:1e:df:bb:1f:b6:51:a0:63:3e:aa:8a:9d:c5:f8:07:03 +-----BEGIN CERTIFICATE----- +MIIFaTCCA1GgAwIBAgIJAJK4iNuwisFjMA0GCSqGSIb3DQEBCwUAMFIxCzAJBgNV +BAYTAlNLMRMwEQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMu +MRkwFwYDVQQDExBDQSBEaXNpZyBSb290IFIyMB4XDTEyMDcxOTA5MTUzMFoXDTQy +MDcxOTA5MTUzMFowUjELMAkGA1UEBhMCU0sxEzARBgNVBAcTCkJyYXRpc2xhdmEx +EzARBgNVBAoTCkRpc2lnIGEucy4xGTAXBgNVBAMTEENBIERpc2lnIFJvb3QgUjIw +ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCio8QACdaFXS1tFPbCw3Oe +NcJxVX6B+6tGUODBfEl45qt5WDza/3wcn9iXAng+a0EE6UG9vgMsRfYvZNSrXaNH +PWSb6WiaxswbP7q+sos0Ai6YVRn8jG+qX9pMzk0DIaPY0jSTVpbLTAwAFjxfGs3I +x2ymrdMxp7zo5eFm1tL7A7RBZckQrg4FY8aAamkw/dLukO8NJ9+flXP04SXabBbe +QTg06ov80egEFGEtQX6sx3dOy1FU+16SGBsEWmjGycT6txOgmLcRK7fWV8x8nhfR +yyX+hk4kLlYMeE2eARKmK6cBZW58Yh2EhN/qwGu1pSqVg8NTEQxzHQuyRpDRQjrO +QG6Vrf/GlK1ul4SOfW+eioANSW1z4nuSHsPzwfPrLgVv2RvPN3YEyLRa5Beny912 +H9AZdugsBbPWnDTYltxhh5EF5EQIM8HauQhl1K6yNg3ruji6DOWbnuuNZt2Zz9aJ +QfYEkoopKW1rOhzndX0CcQ7zwOe9yxndnWCywmZgtrEE7snmhrmaZkCo5xHtgUUD +i/ZnWejBBhG93c+AAk9lQHhcR1DIm+YfgXvkRKhbhZri3lrVx/k6RGZL5DJUfORs +nLMOPReisjQS1n6yqEm70XooQL6iFh/f5DcfEXP7kAplQ6INfPgGAVUzfbANuPT1 +rqVCV3w2EYx7XsQDnYx5nQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1Ud +DwEB/wQEAwIBBjAdBgNVHQ4EFgQUtZn4r7CU9eMg1gqtzk5WpC5uQu0wDQYJKoZI +hvcNAQELBQADggIBACYGXnDnZTPIgm7ZnBc6G3pmsgH2eDtpXi/q/075KMOYKmFM +tCQSin1tERT3nLXK5ryeJ45MGcipvXrA1zYObYVybqjGom32+nNjf7xueQgcnYqf +GopTpti72TVVsRHFqQOzVju5hJMiXn7B9hJSi+osZ7z+Nkz1uM/Rs0mSO9MpDpkb +lvdhuDvEK7Z4bLQjb/D907JedR+Zlais9trhxTF7+9FGs9K8Z7RiVLoJ92Owk6Ka ++elSLotgEqv89WBW7xBci8QaQtyDW2QOy7W81k/BfDxujRNt+3vrMNDcTa/F1bal +TFtxyegxvug4BkihGuLq0t4SOVga/4AOgnXmt8kHbA7v/zjxmHHEt38OFdAlab0i +nSvtBfZGR6ztwPDUO+Ls7pZbkBNOHlY667DvlruWIxG68kOGdGSVyCh13x01utI3 +gzhTODY7z2zp+WsO0PsE6E9312UBeIYMej4hYvF/Y3EMyZ9E26gnonW+boE+18Dr +G5gPcFw0sorMwIUY6256s/daoQe/qUKS82Ail+QUoQebTnbAjn39pCXHR+3/H3Os +zMOl6W8KjptlwlCFtaOgUxLMVYdh84GuEEZhvUQhuMI9dM9+JDX6HAcOmz0iyu8x +L4ysEr3vQCj8KWefshNPZiTEUxnpHikV7+ZtsH8tZ/3zbBt1RqPlShfppNcL +-----END CERTIFICATE----- + +# Issuer: CN=ACCVRAIZ1 O=ACCV OU=PKIACCV +# Subject: CN=ACCVRAIZ1 O=ACCV OU=PKIACCV +# Label: "ACCVRAIZ1" +# Serial: 6828503384748696800 +# MD5 Fingerprint: d0:a0:5a:ee:05:b6:09:94:21:a1:7d:f1:b2:29:82:02 +# SHA1 Fingerprint: 93:05:7a:88:15:c6:4f:ce:88:2f:fa:91:16:52:28:78:bc:53:64:17 +# SHA256 Fingerprint: 9a:6e:c0:12:e1:a7:da:9d:be:34:19:4d:47:8a:d7:c0:db:18:22:fb:07:1d:f1:29:81:49:6e:d1:04:38:41:13 +-----BEGIN CERTIFICATE----- +MIIH0zCCBbugAwIBAgIIXsO3pkN/pOAwDQYJKoZIhvcNAQEFBQAwQjESMBAGA1UE +AwwJQUNDVlJBSVoxMRAwDgYDVQQLDAdQS0lBQ0NWMQ0wCwYDVQQKDARBQ0NWMQsw +CQYDVQQGEwJFUzAeFw0xMTA1MDUwOTM3MzdaFw0zMDEyMzEwOTM3MzdaMEIxEjAQ +BgNVBAMMCUFDQ1ZSQUlaMTEQMA4GA1UECwwHUEtJQUNDVjENMAsGA1UECgwEQUND +VjELMAkGA1UEBhMCRVMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCb +qau/YUqXry+XZpp0X9DZlv3P4uRm7x8fRzPCRKPfmt4ftVTdFXxpNRFvu8gMjmoY +HtiP2Ra8EEg2XPBjs5BaXCQ316PWywlxufEBcoSwfdtNgM3802/J+Nq2DoLSRYWo +G2ioPej0RGy9ocLLA76MPhMAhN9KSMDjIgro6TenGEyxCQ0jVn8ETdkXhBilyNpA +lHPrzg5XPAOBOp0KoVdDaaxXbXmQeOW1tDvYvEyNKKGno6e6Ak4l0Squ7a4DIrhr +IA8wKFSVf+DuzgpmndFALW4ir50awQUZ0m/A8p/4e7MCQvtQqR0tkw8jq8bBD5L/ +0KIV9VMJcRz/RROE5iZe+OCIHAr8Fraocwa48GOEAqDGWuzndN9wrqODJerWx5eH +k6fGioozl2A3ED6XPm4pFdahD9GILBKfb6qkxkLrQaLjlUPTAYVtjrs78yM2x/47 +4KElB0iryYl0/wiPgL/AlmXz7uxLaL2diMMxs0Dx6M/2OLuc5NF/1OVYm3z61PMO +m3WR5LpSLhl+0fXNWhn8ugb2+1KoS5kE3fj5tItQo05iifCHJPqDQsGH+tUtKSpa +cXpkatcnYGMN285J9Y0fkIkyF/hzQ7jSWpOGYdbhdQrqeWZ2iE9x6wQl1gpaepPl +uUsXQA+xtrn13k/c4LOsOxFwYIRKQ26ZIMApcQrAZQIDAQABo4ICyzCCAscwfQYI +KwYBBQUHAQEEcTBvMEwGCCsGAQUFBzAChkBodHRwOi8vd3d3LmFjY3YuZXMvZmls +ZWFkbWluL0FyY2hpdm9zL2NlcnRpZmljYWRvcy9yYWl6YWNjdjEuY3J0MB8GCCsG +AQUFBzABhhNodHRwOi8vb2NzcC5hY2N2LmVzMB0GA1UdDgQWBBTSh7Tj3zcnk1X2 +VuqB5TbMjB4/vTAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFNKHtOPfNyeT +VfZW6oHlNsyMHj+9MIIBcwYDVR0gBIIBajCCAWYwggFiBgRVHSAAMIIBWDCCASIG +CCsGAQUFBwICMIIBFB6CARAAQQB1AHQAbwByAGkAZABhAGQAIABkAGUAIABDAGUA +cgB0AGkAZgBpAGMAYQBjAGkA8wBuACAAUgBhAO0AegAgAGQAZQAgAGwAYQAgAEEA +QwBDAFYAIAAoAEEAZwBlAG4AYwBpAGEAIABkAGUAIABUAGUAYwBuAG8AbABvAGcA +7QBhACAAeQAgAEMAZQByAHQAaQBmAGkAYwBhAGMAaQDzAG4AIABFAGwAZQBjAHQA +cgDzAG4AaQBjAGEALAAgAEMASQBGACAAUQA0ADYAMAAxADEANQA2AEUAKQAuACAA +QwBQAFMAIABlAG4AIABoAHQAdABwADoALwAvAHcAdwB3AC4AYQBjAGMAdgAuAGUA +czAwBggrBgEFBQcCARYkaHR0cDovL3d3dy5hY2N2LmVzL2xlZ2lzbGFjaW9uX2Mu +aHRtMFUGA1UdHwROMEwwSqBIoEaGRGh0dHA6Ly93d3cuYWNjdi5lcy9maWxlYWRt +aW4vQXJjaGl2b3MvY2VydGlmaWNhZG9zL3JhaXphY2N2MV9kZXIuY3JsMA4GA1Ud +DwEB/wQEAwIBBjAXBgNVHREEEDAOgQxhY2N2QGFjY3YuZXMwDQYJKoZIhvcNAQEF +BQADggIBAJcxAp/n/UNnSEQU5CmH7UwoZtCPNdpNYbdKl02125DgBS4OxnnQ8pdp +D70ER9m+27Up2pvZrqmZ1dM8MJP1jaGo/AaNRPTKFpV8M9xii6g3+CfYCS0b78gU +JyCpZET/LtZ1qmxNYEAZSUNUY9rizLpm5U9EelvZaoErQNV/+QEnWCzI7UiRfD+m +AM/EKXMRNt6GGT6d7hmKG9Ww7Y49nCrADdg9ZuM8Db3VlFzi4qc1GwQA9j9ajepD +vV+JHanBsMyZ4k0ACtrJJ1vnE5Bc5PUzolVt3OAJTS+xJlsndQAJxGJ3KQhfnlms +tn6tn1QwIgPBHnFk/vk4CpYY3QIUrCPLBhwepH2NDd4nQeit2hW3sCPdK6jT2iWH +7ehVRE2I9DZ+hJp4rPcOVkkO1jMl1oRQQmwgEh0q1b688nCBpHBgvgW1m54ERL5h +I6zppSSMEYCUWqKiuUnSwdzRp+0xESyeGabu4VXhwOrPDYTkF7eifKXeVSUG7szA +h1xA2syVP1XgNce4hL60Xc16gwFy7ofmXx2utYXGJt/mwZrpHgJHnyqobalbz+xF +d3+YJ5oyXSrjhO7FmGYvliAd3djDJ9ew+f7Zfc3Qn48LFFhRny+Lwzgt3uiP1o2H +pPVWQxaZLPSkVrQ0uGE3ycJYgBugl6H8WY3pEfbRD0tVNEYqi4Y7 +-----END CERTIFICATE----- + +# Issuer: CN=TWCA Global Root CA O=TAIWAN-CA OU=Root CA +# Subject: CN=TWCA Global Root CA O=TAIWAN-CA OU=Root CA +# Label: "TWCA Global Root CA" +# Serial: 3262 +# MD5 Fingerprint: f9:03:7e:cf:e6:9e:3c:73:7a:2a:90:07:69:ff:2b:96 +# SHA1 Fingerprint: 9c:bb:48:53:f6:a4:f6:d3:52:a4:e8:32:52:55:60:13:f5:ad:af:65 +# SHA256 Fingerprint: 59:76:90:07:f7:68:5d:0f:cd:50:87:2f:9f:95:d5:75:5a:5b:2b:45:7d:81:f3:69:2b:61:0a:98:67:2f:0e:1b +-----BEGIN CERTIFICATE----- +MIIFQTCCAymgAwIBAgICDL4wDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCVFcx +EjAQBgNVBAoTCVRBSVdBTi1DQTEQMA4GA1UECxMHUm9vdCBDQTEcMBoGA1UEAxMT +VFdDQSBHbG9iYWwgUm9vdCBDQTAeFw0xMjA2MjcwNjI4MzNaFw0zMDEyMzExNTU5 +NTlaMFExCzAJBgNVBAYTAlRXMRIwEAYDVQQKEwlUQUlXQU4tQ0ExEDAOBgNVBAsT +B1Jvb3QgQ0ExHDAaBgNVBAMTE1RXQ0EgR2xvYmFsIFJvb3QgQ0EwggIiMA0GCSqG +SIb3DQEBAQUAA4ICDwAwggIKAoICAQCwBdvI64zEbooh745NnHEKH1Jw7W2CnJfF +10xORUnLQEK1EjRsGcJ0pDFfhQKX7EMzClPSnIyOt7h52yvVavKOZsTuKwEHktSz +0ALfUPZVr2YOy+BHYC8rMjk1Ujoog/h7FsYYuGLWRyWRzvAZEk2tY/XTP3VfKfCh +MBwqoJimFb3u/Rk28OKRQ4/6ytYQJ0lM793B8YVwm8rqqFpD/G2Gb3PpN0Wp8DbH +zIh1HrtsBv+baz4X7GGqcXzGHaL3SekVtTzWoWH1EfcFbx39Eb7QMAfCKbAJTibc +46KokWofwpFFiFzlmLhxpRUZyXx1EcxwdE8tmx2RRP1WKKD+u4ZqyPpcC1jcxkt2 +yKsi2XMPpfRaAok/T54igu6idFMqPVMnaR1sjjIsZAAmY2E2TqNGtz99sy2sbZCi +laLOz9qC5wc0GZbpuCGqKX6mOL6OKUohZnkfs8O1CWfe1tQHRvMq2uYiN2DLgbYP +oA/pyJV/v1WRBXrPPRXAb94JlAGD1zQbzECl8LibZ9WYkTunhHiVJqRaCPgrdLQA +BDzfuBSO6N+pjWxnkjMdwLfS7JLIvgm/LCkFbwJrnu+8vyq8W8BQj0FwcYeyTbcE +qYSjMq+u7msXi7Kx/mzhkIyIqJdIzshNy/MGz19qCkKxHh53L46g5pIOBvwFItIm +4TFRfTLcDwIDAQABoyMwITAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB +/zANBgkqhkiG9w0BAQsFAAOCAgEAXzSBdu+WHdXltdkCY4QWwa6gcFGn90xHNcgL +1yg9iXHZqjNB6hQbbCEAwGxCGX6faVsgQt+i0trEfJdLjbDorMjupWkEmQqSpqsn +LhpNgb+E1HAerUf+/UqdM+DyucRFCCEK2mlpc3INvjT+lIutwx4116KD7+U4x6WF +H6vPNOw/KP4M8VeGTslV9xzU2KV9Bnpv1d8Q34FOIWWxtuEXeZVFBs5fzNxGiWNo +RI2T9GRwoD2dKAXDOXC4Ynsg/eTb6QihuJ49CcdP+yz4k3ZB3lLg4VfSnQO8d57+ +nile98FRYB/e2guyLXW3Q0iT5/Z5xoRdgFlglPx4mI88k1HtQJAH32RjJMtOcQWh +15QaiDLxInQirqWm2BJpTGCjAu4r7NRjkgtevi92a6O2JryPA9gK8kxkRr05YuWW +6zRjESjMlfGt7+/cgFhI6Uu46mWs6fyAtbXIRfmswZ/ZuepiiI7E8UuDEq3mi4TW +nsLrgxifarsbJGAzcMzs9zLzXNl5fe+epP7JI8Mk7hWSsT2RTyaGvWZzJBPqpK5j +wa19hAM8EHiGG3njxPPyBJUgriOCxLM6AGK/5jYk4Ve6xx6QddVfP5VhK8E7zeWz +aGHQRiapIVJpLesux+t3zqY6tQMzT3bR51xUAV3LePTJDL/PEo4XLSNolOer/qmy +KwbQBM0= +-----END CERTIFICATE----- + +# Issuer: CN=TeliaSonera Root CA v1 O=TeliaSonera +# Subject: CN=TeliaSonera Root CA v1 O=TeliaSonera +# Label: "TeliaSonera Root CA v1" +# Serial: 199041966741090107964904287217786801558 +# MD5 Fingerprint: 37:41:49:1b:18:56:9a:26:f5:ad:c2:66:fb:40:a5:4c +# SHA1 Fingerprint: 43:13:bb:96:f1:d5:86:9b:c1:4e:6a:92:f6:cf:f6:34:69:87:82:37 +# SHA256 Fingerprint: dd:69:36:fe:21:f8:f0:77:c1:23:a1:a5:21:c1:22:24:f7:22:55:b7:3e:03:a7:26:06:93:e8:a2:4b:0f:a3:89 +-----BEGIN CERTIFICATE----- +MIIFODCCAyCgAwIBAgIRAJW+FqD3LkbxezmCcvqLzZYwDQYJKoZIhvcNAQEFBQAw +NzEUMBIGA1UECgwLVGVsaWFTb25lcmExHzAdBgNVBAMMFlRlbGlhU29uZXJhIFJv +b3QgQ0EgdjEwHhcNMDcxMDE4MTIwMDUwWhcNMzIxMDE4MTIwMDUwWjA3MRQwEgYD +VQQKDAtUZWxpYVNvbmVyYTEfMB0GA1UEAwwWVGVsaWFTb25lcmEgUm9vdCBDQSB2 +MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMK+6yfwIaPzaSZVfp3F +VRaRXP3vIb9TgHot0pGMYzHw7CTww6XScnwQbfQ3t+XmfHnqjLWCi65ItqwA3GV1 +7CpNX8GH9SBlK4GoRz6JI5UwFpB/6FcHSOcZrr9FZ7E3GwYq/t75rH2D+1665I+X +Z75Ljo1kB1c4VWk0Nj0TSO9P4tNmHqTPGrdeNjPUtAa9GAH9d4RQAEX1jF3oI7x+ +/jXh7VB7qTCNGdMJjmhnXb88lxhTuylixcpecsHHltTbLaC0H2kD7OriUPEMPPCs +81Mt8Bz17Ww5OXOAFshSsCPN4D7c3TxHoLs1iuKYaIu+5b9y7tL6pe0S7fyYGKkm +dtwoSxAgHNN/Fnct7W+A90m7UwW7XWjH1Mh1Fj+JWov3F0fUTPHSiXk+TT2YqGHe +Oh7S+F4D4MHJHIzTjU3TlTazN19jY5szFPAtJmtTfImMMsJu7D0hADnJoWjiUIMu +sDor8zagrC/kb2HCUQk5PotTubtn2txTuXZZNp1D5SDgPTJghSJRt8czu90VL6R4 +pgd7gUY2BIbdeTXHlSw7sKMXNeVzH7RcWe/a6hBle3rQf5+ztCo3O3CLm1u5K7fs +slESl1MpWtTwEhDcTwK7EpIvYtQ/aUN8Ddb8WHUBiJ1YFkveupD/RwGJBmr2X7KQ +arMCpgKIv7NHfirZ1fpoeDVNAgMBAAGjPzA9MA8GA1UdEwEB/wQFMAMBAf8wCwYD +VR0PBAQDAgEGMB0GA1UdDgQWBBTwj1k4ALP1j5qWDNXr+nuqF+gTEjANBgkqhkiG +9w0BAQUFAAOCAgEAvuRcYk4k9AwI//DTDGjkk0kiP0Qnb7tt3oNmzqjMDfz1mgbl +dxSR651Be5kqhOX//CHBXfDkH1e3damhXwIm/9fH907eT/j3HEbAek9ALCI18Bmx +0GtnLLCo4MBANzX2hFxc469CeP6nyQ1Q6g2EdvZR74NTxnr/DlZJLo961gzmJ1Tj +TQpgcmLNkQfWpb/ImWvtxBnmq0wROMVvMeJuScg/doAmAyYp4Db29iBT4xdwNBed +Y2gea+zDTYa4EzAvXUYNR0PVG6pZDrlcjQZIrXSHX8f8MVRBE+LHIQ6e4B4N4cB7 +Q4WQxYpYxmUKeFfyxiMPAdkgS94P+5KFdSpcc41teyWRyu5FrgZLAMzTsVlQ2jqI +OylDRl6XK1TOU2+NSueW+r9xDkKLfP0ooNBIytrEgUy7onOTJsjrDNYmiLbAJM+7 +vVvrdX3pCI6GMyx5dwlppYn8s3CQh3aP0yK7Qs69cwsgJirQmz1wHiRszYd2qReW +t88NkvuOGKmYSdGe/mBEciG5Ge3C9THxOUiIkCR1VBatzvT4aRRkOfujuLpwQMcn +HL/EVlP6Y2XQ8xwOFvVrhlhNGNTkDY6lnVuR3HYkUD/GKvvZt5y11ubQ2egZixVx +SK236thZiNSQvxaz2emsWWFUyBy6ysHK4bkgTI86k4mloMy/0/Z1pHWWbVY= +-----END CERTIFICATE----- + +# Issuer: CN=E-Tugra Certification Authority O=E-Tu\u011fra EBG Bili\u015fim Teknolojileri ve Hizmetleri A.\u015e. OU=E-Tugra Sertifikasyon Merkezi +# Subject: CN=E-Tugra Certification Authority O=E-Tu\u011fra EBG Bili\u015fim Teknolojileri ve Hizmetleri A.\u015e. OU=E-Tugra Sertifikasyon Merkezi +# Label: "E-Tugra Certification Authority" +# Serial: 7667447206703254355 +# MD5 Fingerprint: b8:a1:03:63:b0:bd:21:71:70:8a:6f:13:3a:bb:79:49 +# SHA1 Fingerprint: 51:c6:e7:08:49:06:6e:f3:92:d4:5c:a0:0d:6d:a3:62:8f:c3:52:39 +# SHA256 Fingerprint: b0:bf:d5:2b:b0:d7:d9:bd:92:bf:5d:4d:c1:3d:a2:55:c0:2c:54:2f:37:83:65:ea:89:39:11:f5:5e:55:f2:3c +-----BEGIN CERTIFICATE----- +MIIGSzCCBDOgAwIBAgIIamg+nFGby1MwDQYJKoZIhvcNAQELBQAwgbIxCzAJBgNV +BAYTAlRSMQ8wDQYDVQQHDAZBbmthcmExQDA+BgNVBAoMN0UtVHXEn3JhIEVCRyBC +aWxpxZ9pbSBUZWtub2xvamlsZXJpIHZlIEhpem1ldGxlcmkgQS7Fni4xJjAkBgNV +BAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBNZXJrZXppMSgwJgYDVQQDDB9FLVR1 +Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTEzMDMwNTEyMDk0OFoXDTIz +MDMwMzEyMDk0OFowgbIxCzAJBgNVBAYTAlRSMQ8wDQYDVQQHDAZBbmthcmExQDA+ +BgNVBAoMN0UtVHXEn3JhIEVCRyBCaWxpxZ9pbSBUZWtub2xvamlsZXJpIHZlIEhp +em1ldGxlcmkgQS7Fni4xJjAkBgNVBAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBN +ZXJrZXppMSgwJgYDVQQDDB9FLVR1Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5 +MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA4vU/kwVRHoViVF56C/UY +B4Oufq9899SKa6VjQzm5S/fDxmSJPZQuVIBSOTkHS0vdhQd2h8y/L5VMzH2nPbxH +D5hw+IyFHnSOkm0bQNGZDbt1bsipa5rAhDGvykPL6ys06I+XawGb1Q5KCKpbknSF +Q9OArqGIW66z6l7LFpp3RMih9lRozt6Plyu6W0ACDGQXwLWTzeHxE2bODHnv0ZEo +q1+gElIwcxmOj+GMB6LDu0rw6h8VqO4lzKRG+Bsi77MOQ7osJLjFLFzUHPhdZL3D +k14opz8n8Y4e0ypQBaNV2cvnOVPAmJ6MVGKLJrD3fY185MaeZkJVgkfnsliNZvcH +fC425lAcP9tDJMW/hkd5s3kc91r0E+xs+D/iWR+V7kI+ua2oMoVJl0b+SzGPWsut +dEcf6ZG33ygEIqDUD13ieU/qbIWGvaimzuT6w+Gzrt48Ue7LE3wBf4QOXVGUnhMM +ti6lTPk5cDZvlsouDERVxcr6XQKj39ZkjFqzAQqptQpHF//vkUAqjqFGOjGY5RH8 +zLtJVor8udBhmm9lbObDyz51Sf6Pp+KJxWfXnUYTTjF2OySznhFlhqt/7x3U+Lzn +rFpct1pHXFXOVbQicVtbC/DP3KBhZOqp12gKY6fgDT+gr9Oq0n7vUaDmUStVkhUX +U8u3Zg5mTPj5dUyQ5xJwx0UCAwEAAaNjMGEwHQYDVR0OBBYEFC7j27JJ0JxUeVz6 +Jyr+zE7S6E5UMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAULuPbsknQnFR5 +XPonKv7MTtLoTlQwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQAF +Nzr0TbdF4kV1JI+2d1LoHNgQk2Xz8lkGpD4eKexd0dCrfOAKkEh47U6YA5n+KGCR +HTAduGN8qOY1tfrTYXbm1gdLymmasoR6d5NFFxWfJNCYExL/u6Au/U5Mh/jOXKqY +GwXgAEZKgoClM4so3O0409/lPun++1ndYYRP0lSWE2ETPo+Aab6TR7U1Q9Jauz1c +77NCR807VRMGsAnb/WP2OogKmW9+4c4bU2pEZiNRCHu8W1Ki/QY3OEBhj0qWuJA3 ++GbHeJAAFS6LrVE1Uweoa2iu+U48BybNCAVwzDk/dr2l02cmAYamU9JgO3xDf1WK +vJUawSg5TB9D0pH0clmKuVb8P7Sd2nCcdlqMQ1DujjByTd//SffGqWfZbawCEeI6 +FiWnWAjLb1NBnEg4R2gz0dfHj9R0IdTDBZB6/86WiLEVKV0jq9BgoRJP3vQXzTLl +yb/IQ639Lo7xr+L0mPoSHyDYwKcMhcWQ9DstliaxLL5Mq+ux0orJ23gTDx4JnW2P +AJ8C2sH6H3p6CcRK5ogql5+Ji/03X186zjhZhkuvcQu02PJwT58yE+Owp1fl2tpD +y4Q08ijE6m30Ku/Ba3ba+367hTzSU8JNvnHhRdH9I2cNE3X7z2VnIp2usAnRCf8d +NL/+I5c30jn6PQ0GC7TbO6Orb1wdtn7os4I07QZcJA== +-----END CERTIFICATE----- + +# Issuer: CN=T-TeleSec GlobalRoot Class 2 O=T-Systems Enterprise Services GmbH OU=T-Systems Trust Center +# Subject: CN=T-TeleSec GlobalRoot Class 2 O=T-Systems Enterprise Services GmbH OU=T-Systems Trust Center +# Label: "T-TeleSec GlobalRoot Class 2" +# Serial: 1 +# MD5 Fingerprint: 2b:9b:9e:e4:7b:6c:1f:00:72:1a:cc:c1:77:79:df:6a +# SHA1 Fingerprint: 59:0d:2d:7d:88:4f:40:2e:61:7e:a5:62:32:17:65:cf:17:d8:94:e9 +# SHA256 Fingerprint: 91:e2:f5:78:8d:58:10:eb:a7:ba:58:73:7d:e1:54:8a:8e:ca:cd:01:45:98:bc:0b:14:3e:04:1b:17:05:25:52 +-----BEGIN CERTIFICATE----- +MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUx +KzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAd +BgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNl +YyBHbG9iYWxSb290IENsYXNzIDIwHhcNMDgxMDAxMTA0MDE0WhcNMzMxMDAxMjM1 +OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnBy +aXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50 +ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwggEiMA0G +CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCqX9obX+hzkeXaXPSi5kfl82hVYAUd +AqSzm1nzHoqvNK38DcLZSBnuaY/JIPwhqgcZ7bBcrGXHX+0CfHt8LRvWurmAwhiC +FoT6ZrAIxlQjgeTNuUk/9k9uN0goOA/FvudocP05l03Sx5iRUKrERLMjfTlH6VJi +1hKTXrcxlkIF+3anHqP1wvzpesVsqXFP6st4vGCvx9702cu+fjOlbpSD8DT6Iavq +jnKgP6TeMFvvhk1qlVtDRKgQFRzlAVfFmPHmBiiRqiDFt1MmUUOyCxGVWOHAD3bZ +wI18gfNycJ5v/hqO2V81xrJvNHy+SE/iWjnX2J14np+GPgNeGYtEotXHAgMBAAGj +QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS/ +WSA2AHmgoCJrjNXyYdK4LMuCSjANBgkqhkiG9w0BAQsFAAOCAQEAMQOiYQsfdOhy +NsZt+U2e+iKo4YFWz827n+qrkRk4r6p8FU3ztqONpfSO9kSpp+ghla0+AGIWiPAC +uvxhI+YzmzB6azZie60EI4RYZeLbK4rnJVM3YlNfvNoBYimipidx5joifsFvHZVw +IEoHNN/q/xWA5brXethbdXwFeilHfkCoMRN3zUA7tFFHei4R40cR3p1m0IvVVGb6 +g1XqfMIpiRvpb7PO4gWEyS8+eIVibslfwXhjdFjASBgMmTnrpMwatXlajRWc2BQN +9noHV8cigwUtPJslJj0Ys6lDfMjIq2SPDqO/nBudMNva0Bkuqjzx+zOAduTNrRlP +BSeOE6Fuwg== +-----END CERTIFICATE----- + +# Issuer: CN=Atos TrustedRoot 2011 O=Atos +# Subject: CN=Atos TrustedRoot 2011 O=Atos +# Label: "Atos TrustedRoot 2011" +# Serial: 6643877497813316402 +# MD5 Fingerprint: ae:b9:c4:32:4b:ac:7f:5d:66:cc:77:94:bb:2a:77:56 +# SHA1 Fingerprint: 2b:b1:f5:3e:55:0c:1d:c5:f1:d4:e6:b7:6a:46:4b:55:06:02:ac:21 +# SHA256 Fingerprint: f3:56:be:a2:44:b7:a9:1e:b3:5d:53:ca:9a:d7:86:4a:ce:01:8e:2d:35:d5:f8:f9:6d:df:68:a6:f4:1a:a4:74 +-----BEGIN CERTIFICATE----- +MIIDdzCCAl+gAwIBAgIIXDPLYixfszIwDQYJKoZIhvcNAQELBQAwPDEeMBwGA1UE +AwwVQXRvcyBUcnVzdGVkUm9vdCAyMDExMQ0wCwYDVQQKDARBdG9zMQswCQYDVQQG +EwJERTAeFw0xMTA3MDcxNDU4MzBaFw0zMDEyMzEyMzU5NTlaMDwxHjAcBgNVBAMM +FUF0b3MgVHJ1c3RlZFJvb3QgMjAxMTENMAsGA1UECgwEQXRvczELMAkGA1UEBhMC +REUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCVhTuXbyo7LjvPpvMp +Nb7PGKw+qtn4TaA+Gke5vJrf8v7MPkfoepbCJI419KkM/IL9bcFyYie96mvr54rM +VD6QUM+A1JX76LWC1BTFtqlVJVfbsVD2sGBkWXppzwO3bw2+yj5vdHLqqjAqc2K+ +SZFhyBH+DgMq92og3AIVDV4VavzjgsG1xZ1kCWyjWZgHJ8cblithdHFsQ/H3NYkQ +4J7sVaE3IqKHBAUsR320HLliKWYoyrfhk/WklAOZuXCFteZI6o1Q/NnezG8HDt0L +cp2AMBYHlT8oDv3FdU9T1nSatCQujgKRz3bFmx5VdJx4IbHwLfELn8LVlhgf8FQi +eowHAgMBAAGjfTB7MB0GA1UdDgQWBBSnpQaxLKYJYO7Rl+lwrrw7GWzbITAPBgNV +HRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKelBrEspglg7tGX6XCuvDsZbNshMBgG +A1UdIAQRMA8wDQYLKwYBBAGwLQMEAQEwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3 +DQEBCwUAA4IBAQAmdzTblEiGKkGdLD4GkGDEjKwLVLgfuXvTBznk+j57sj1O7Z8j +vZfza1zv7v1Apt+hk6EKhqzvINB5Ab149xnYJDE0BAGmuhWawyfc2E8PzBhj/5kP +DpFrdRbhIfzYJsdHt6bPWHJxfrrhTZVHO8mvbaG0weyJ9rQPOLXiZNwlz6bb65pc +maHFCN795trV1lpFDMS3wrUU77QR/w4VtfX128a961qn8FYiqTxlVMYVqL2Gns2D +lmh6cYGJ4Qvh6hEbaAjMaZ7snkGeRDImeuKHCnE96+RapNLbxc3G3mB/ufNPRJLv +KrcYPqcZ2Qt9sTdBQrC6YB3y/gkRsPCHe6ed +-----END CERTIFICATE----- + +# Issuer: CN=QuoVadis Root CA 1 G3 O=QuoVadis Limited +# Subject: CN=QuoVadis Root CA 1 G3 O=QuoVadis Limited +# Label: "QuoVadis Root CA 1 G3" +# Serial: 687049649626669250736271037606554624078720034195 +# MD5 Fingerprint: a4:bc:5b:3f:fe:37:9a:fa:64:f0:e2:fa:05:3d:0b:ab +# SHA1 Fingerprint: 1b:8e:ea:57:96:29:1a:c9:39:ea:b8:0a:81:1a:73:73:c0:93:79:67 +# SHA256 Fingerprint: 8a:86:6f:d1:b2:76:b5:7e:57:8e:92:1c:65:82:8a:2b:ed:58:e9:f2:f2:88:05:41:34:b7:f1:f4:bf:c9:cc:74 +-----BEGIN CERTIFICATE----- +MIIFYDCCA0igAwIBAgIUeFhfLq0sGUvjNwc1NBMotZbUZZMwDQYJKoZIhvcNAQEL +BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc +BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMSBHMzAeFw0xMjAxMTIxNzI3NDRaFw00 +MjAxMTIxNzI3NDRaMEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM +aW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDEgRzMwggIiMA0GCSqG +SIb3DQEBAQUAA4ICDwAwggIKAoICAQCgvlAQjunybEC0BJyFuTHK3C3kEakEPBtV +wedYMB0ktMPvhd6MLOHBPd+C5k+tR4ds7FtJwUrVu4/sh6x/gpqG7D0DmVIB0jWe +rNrwU8lmPNSsAgHaJNM7qAJGr6Qc4/hzWHa39g6QDbXwz8z6+cZM5cOGMAqNF341 +68Xfuw6cwI2H44g4hWf6Pser4BOcBRiYz5P1sZK0/CPTz9XEJ0ngnjybCKOLXSoh +4Pw5qlPafX7PGglTvF0FBM+hSo+LdoINofjSxxR3W5A2B4GbPgb6Ul5jxaYA/qXp +UhtStZI5cgMJYr2wYBZupt0lwgNm3fME0UDiTouG9G/lg6AnhF4EwfWQvTA9xO+o +abw4m6SkltFi2mnAAZauy8RRNOoMqv8hjlmPSlzkYZqn0ukqeI1RPToV7qJZjqlc +3sX5kCLliEVx3ZGZbHqfPT2YfF72vhZooF6uCyP8Wg+qInYtyaEQHeTTRCOQiJ/G +KubX9ZqzWB4vMIkIG1SitZgj7Ah3HJVdYdHLiZxfokqRmu8hqkkWCKi9YSgxyXSt +hfbZxbGL0eUQMk1fiyA6PEkfM4VZDdvLCXVDaXP7a3F98N/ETH3Goy7IlXnLc6KO +Tk0k+17kBL5yG6YnLUlamXrXXAkgt3+UuU/xDRxeiEIbEbfnkduebPRq34wGmAOt +zCjvpUfzUwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB +BjAdBgNVHQ4EFgQUo5fW816iEOGrRZ88F2Q87gFwnMwwDQYJKoZIhvcNAQELBQAD +ggIBABj6W3X8PnrHX3fHyt/PX8MSxEBd1DKquGrX1RUVRpgjpeaQWxiZTOOtQqOC +MTaIzen7xASWSIsBx40Bz1szBpZGZnQdT+3Btrm0DWHMY37XLneMlhwqI2hrhVd2 +cDMT/uFPpiN3GPoajOi9ZcnPP/TJF9zrx7zABC4tRi9pZsMbj/7sPtPKlL92CiUN +qXsCHKnQO18LwIE6PWThv6ctTr1NxNgpxiIY0MWscgKCP6o6ojoilzHdCGPDdRS5 +YCgtW2jgFqlmgiNR9etT2DGbe+m3nUvriBbP+V04ikkwj+3x6xn0dxoxGE1nVGwv +b2X52z3sIexe9PSLymBlVNFxZPT5pqOBMzYzcfCkeF9OrYMh3jRJjehZrJ3ydlo2 +8hP0r+AJx2EqbPfgna67hkooby7utHnNkDPDs3b69fBsnQGQ+p6Q9pxyz0fawx/k +NSBT8lTR32GDpgLiJTjehTItXnOQUl1CxM49S+H5GYQd1aJQzEH7QRTDvdbJWqNj +ZgKAvQU6O0ec7AAmTPWIUb+oI38YB7AL7YsmoWTTYUrrXJ/es69nA7Mf3W1daWhp +q1467HxpvMc7hU6eFbm0FU/DlXpY18ls6Wy58yljXrQs8C097Vpl4KlbQMJImYFt +nh8GKjwStIsPm6Ik8KaN1nrgS7ZklmOVhMJKzRwuJIczYOXD +-----END CERTIFICATE----- + +# Issuer: CN=QuoVadis Root CA 2 G3 O=QuoVadis Limited +# Subject: CN=QuoVadis Root CA 2 G3 O=QuoVadis Limited +# Label: "QuoVadis Root CA 2 G3" +# Serial: 390156079458959257446133169266079962026824725800 +# MD5 Fingerprint: af:0c:86:6e:bf:40:2d:7f:0b:3e:12:50:ba:12:3d:06 +# SHA1 Fingerprint: 09:3c:61:f3:8b:8b:dc:7d:55:df:75:38:02:05:00:e1:25:f5:c8:36 +# SHA256 Fingerprint: 8f:e4:fb:0a:f9:3a:4d:0d:67:db:0b:eb:b2:3e:37:c7:1b:f3:25:dc:bc:dd:24:0e:a0:4d:af:58:b4:7e:18:40 +-----BEGIN CERTIFICATE----- +MIIFYDCCA0igAwIBAgIURFc0JFuBiZs18s64KztbpybwdSgwDQYJKoZIhvcNAQEL +BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc +BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMiBHMzAeFw0xMjAxMTIxODU5MzJaFw00 +MjAxMTIxODU5MzJaMEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM +aW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDIgRzMwggIiMA0GCSqG +SIb3DQEBAQUAA4ICDwAwggIKAoICAQChriWyARjcV4g/Ruv5r+LrI3HimtFhZiFf +qq8nUeVuGxbULX1QsFN3vXg6YOJkApt8hpvWGo6t/x8Vf9WVHhLL5hSEBMHfNrMW +n4rjyduYNM7YMxcoRvynyfDStNVNCXJJ+fKH46nafaF9a7I6JaltUkSs+L5u+9ym +c5GQYaYDFCDy54ejiK2toIz/pgslUiXnFgHVy7g1gQyjO/Dh4fxaXc6AcW34Sas+ +O7q414AB+6XrW7PFXmAqMaCvN+ggOp+oMiwMzAkd056OXbxMmO7FGmh77FOm6RQ1 +o9/NgJ8MSPsc9PG/Srj61YxxSscfrf5BmrODXfKEVu+lV0POKa2Mq1W/xPtbAd0j +IaFYAI7D0GoT7RPjEiuA3GfmlbLNHiJuKvhB1PLKFAeNilUSxmn1uIZoL1NesNKq +IcGY5jDjZ1XHm26sGahVpkUG0CM62+tlXSoREfA7T8pt9DTEceT/AFr2XK4jYIVz +8eQQsSWu1ZK7E8EM4DnatDlXtas1qnIhO4M15zHfeiFuuDIIfR0ykRVKYnLP43eh +vNURG3YBZwjgQQvD6xVu+KQZ2aKrr+InUlYrAoosFCT5v0ICvybIxo/gbjh9Uy3l +7ZizlWNof/k19N+IxWA1ksB8aRxhlRbQ694Lrz4EEEVlWFA4r0jyWbYW8jwNkALG +cC4BrTwV1wIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB +BjAdBgNVHQ4EFgQU7edvdlq/YOxJW8ald7tyFnGbxD0wDQYJKoZIhvcNAQELBQAD +ggIBAJHfgD9DCX5xwvfrs4iP4VGyvD11+ShdyLyZm3tdquXK4Qr36LLTn91nMX66 +AarHakE7kNQIXLJgapDwyM4DYvmL7ftuKtwGTTwpD4kWilhMSA/ohGHqPHKmd+RC +roijQ1h5fq7KpVMNqT1wvSAZYaRsOPxDMuHBR//47PERIjKWnML2W2mWeyAMQ0Ga +W/ZZGYjeVYg3UQt4XAoeo0L9x52ID8DyeAIkVJOviYeIyUqAHerQbj5hLja7NQ4n +lv1mNDthcnPxFlxHBlRJAHpYErAK74X9sbgzdWqTHBLmYF5vHX/JHyPLhGGfHoJE ++V+tYlUkmlKY7VHnoX6XOuYvHxHaU4AshZ6rNRDbIl9qxV6XU/IyAgkwo1jwDQHV +csaxfGl7w/U2Rcxhbl5MlMVerugOXou/983g7aEOGzPuVBj+D77vfoRrQ+NwmNtd +dbINWQeFFSM51vHfqSYP1kjHs6Yi9TM3WpVHn3u6GBVv/9YUZINJ0gpnIdsPNWNg +KCLjsZWDzYWm3S8P52dSbrsvhXz1SnPnxT7AvSESBT/8twNJAlvIJebiVDj1eYeM +HVOyToV7BjjHLPj4sHKNJeV3UvQDHEimUF+IIDBu8oJDqz2XhOdT+yHBTw8imoa4 +WSr2Rz0ZiC3oheGe7IUIarFsNMkd7EgrO3jtZsSOeWmD3n+M +-----END CERTIFICATE----- + +# Issuer: CN=QuoVadis Root CA 3 G3 O=QuoVadis Limited +# Subject: CN=QuoVadis Root CA 3 G3 O=QuoVadis Limited +# Label: "QuoVadis Root CA 3 G3" +# Serial: 268090761170461462463995952157327242137089239581 +# MD5 Fingerprint: df:7d:b9:ad:54:6f:68:a1:df:89:57:03:97:43:b0:d7 +# SHA1 Fingerprint: 48:12:bd:92:3c:a8:c4:39:06:e7:30:6d:27:96:e6:a4:cf:22:2e:7d +# SHA256 Fingerprint: 88:ef:81:de:20:2e:b0:18:45:2e:43:f8:64:72:5c:ea:5f:bd:1f:c2:d9:d2:05:73:07:09:c5:d8:b8:69:0f:46 +-----BEGIN CERTIFICATE----- +MIIFYDCCA0igAwIBAgIULvWbAiin23r/1aOp7r0DoM8Sah0wDQYJKoZIhvcNAQEL +BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc +BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMyBHMzAeFw0xMjAxMTIyMDI2MzJaFw00 +MjAxMTIyMDI2MzJaMEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM +aW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDMgRzMwggIiMA0GCSqG +SIb3DQEBAQUAA4ICDwAwggIKAoICAQCzyw4QZ47qFJenMioKVjZ/aEzHs286IxSR +/xl/pcqs7rN2nXrpixurazHb+gtTTK/FpRp5PIpM/6zfJd5O2YIyC0TeytuMrKNu +FoM7pmRLMon7FhY4futD4tN0SsJiCnMK3UmzV9KwCoWdcTzeo8vAMvMBOSBDGzXR +U7Ox7sWTaYI+FrUoRqHe6okJ7UO4BUaKhvVZR74bbwEhELn9qdIoyhA5CcoTNs+c +ra1AdHkrAj80//ogaX3T7mH1urPnMNA3I4ZyYUUpSFlob3emLoG+B01vr87ERROR +FHAGjx+f+IdpsQ7vw4kZ6+ocYfx6bIrc1gMLnia6Et3UVDmrJqMz6nWB2i3ND0/k +A9HvFZcba5DFApCTZgIhsUfei5pKgLlVj7WiL8DWM2fafsSntARE60f75li59wzw +eyuxwHApw0BiLTtIadwjPEjrewl5qW3aqDCYz4ByA4imW0aucnl8CAMhZa634Ryl +sSqiMd5mBPfAdOhx3v89WcyWJhKLhZVXGqtrdQtEPREoPHtht+KPZ0/l7DxMYIBp +VzgeAVuNVejH38DMdyM0SXV89pgR6y3e7UEuFAUCf+D+IOs15xGsIs5XPd7JMG0Q +A4XN8f+MFrXBsj6IbGB/kE+V9/YtrQE5BwT6dYB9v0lQ7e/JxHwc64B+27bQ3RP+ +ydOc17KXqQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB +BjAdBgNVHQ4EFgQUxhfQvKjqAkPyGwaZXSuQILnXnOQwDQYJKoZIhvcNAQELBQAD +ggIBADRh2Va1EodVTd2jNTFGu6QHcrxfYWLopfsLN7E8trP6KZ1/AvWkyaiTt3px +KGmPc+FSkNrVvjrlt3ZqVoAh313m6Tqe5T72omnHKgqwGEfcIHB9UqM+WXzBusnI +FUBhynLWcKzSt/Ac5IYp8M7vaGPQtSCKFWGafoaYtMnCdvvMujAWzKNhxnQT5Wvv +oxXqA/4Ti2Tk08HS6IT7SdEQTXlm66r99I0xHnAUrdzeZxNMgRVhvLfZkXdxGYFg +u/BYpbWcC/ePIlUnwEsBbTuZDdQdm2NnL9DuDcpmvJRPpq3t/O5jrFc/ZSXPsoaP +0Aj/uHYUbt7lJ+yreLVTubY/6CD50qi+YUbKh4yE8/nxoGibIh6BJpsQBJFxwAYf +3KDTuVan45gtf4Od34wrnDKOMpTwATwiKp9Dwi7DmDkHOHv8XgBCH/MyJnmDhPbl +8MFREsALHgQjDFSlTC9JxUrRtm5gDWv8a4uFJGS3iQ6rJUdbPM9+Sb3H6QrG2vd+ +DhcI00iX0HGS8A85PjRqHH3Y8iKuu2n0M7SmSFXRDw4m6Oy2Cy2nhTXN/VnIn9HN +PlopNLk9hM6xZdRZkZFWdSHBd575euFgndOtBBj0fOtek49TSiIp+EgrPk2GrFt/ +ywaZWWDYWGWVjUTR939+J399roD1B0y2PpxxVJkES/1Y+Zj0 +-----END CERTIFICATE----- + +# Issuer: CN=DigiCert Assured ID Root G2 O=DigiCert Inc OU=www.digicert.com +# Subject: CN=DigiCert Assured ID Root G2 O=DigiCert Inc OU=www.digicert.com +# Label: "DigiCert Assured ID Root G2" +# Serial: 15385348160840213938643033620894905419 +# MD5 Fingerprint: 92:38:b9:f8:63:24:82:65:2c:57:33:e6:fe:81:8f:9d +# SHA1 Fingerprint: a1:4b:48:d9:43:ee:0a:0e:40:90:4f:3c:e0:a4:c0:91:93:51:5d:3f +# SHA256 Fingerprint: 7d:05:eb:b6:82:33:9f:8c:94:51:ee:09:4e:eb:fe:fa:79:53:a1:14:ed:b2:f4:49:49:45:2f:ab:7d:2f:c1:85 +-----BEGIN CERTIFICATE----- +MIIDljCCAn6gAwIBAgIQC5McOtY5Z+pnI7/Dr5r0SzANBgkqhkiG9w0BAQsFADBl +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv +b3QgRzIwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBlMQswCQYDVQQG +EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl +cnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIwggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZ5ygvUj82ckmIkzTz+GoeMVSA +n61UQbVH35ao1K+ALbkKz3X9iaV9JPrjIgwrvJUXCzO/GU1BBpAAvQxNEP4Htecc +biJVMWWXvdMX0h5i89vqbFCMP4QMls+3ywPgym2hFEwbid3tALBSfK+RbLE4E9Hp +EgjAALAcKxHad3A2m67OeYfcgnDmCXRwVWmvo2ifv922ebPynXApVfSr/5Vh88lA +bx3RvpO704gqu52/clpWcTs/1PPRCv4o76Pu2ZmvA9OPYLfykqGxvYmJHzDNw6Yu +YjOuFgJ3RFrngQo8p0Quebg/BLxcoIfhG69Rjs3sLPr4/m3wOnyqi+RnlTGNAgMB +AAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQW +BBTOw0q5mVXyuNtgv6l+vVa1lzan1jANBgkqhkiG9w0BAQsFAAOCAQEAyqVVjOPI +QW5pJ6d1Ee88hjZv0p3GeDgdaZaikmkuOGybfQTUiaWxMTeKySHMq2zNixya1r9I +0jJmwYrA8y8678Dj1JGG0VDjA9tzd29KOVPt3ibHtX2vK0LRdWLjSisCx1BL4Gni +lmwORGYQRI+tBev4eaymG+g3NJ1TyWGqolKvSnAWhsI6yLETcDbYz+70CjTVW0z9 +B5yiutkBclzzTcHdDrEcDcRjvq30FPuJ7KJBDkzMyFdA0G4Dqs0MjomZmWzwPDCv +ON9vvKO+KSAnq3T/EyJ43pdSVR6DtVQgA+6uwE9W3jfMw3+qBCe703e4YtsXfJwo +IhNzbM8m9Yop5w== +-----END CERTIFICATE----- + +# Issuer: CN=DigiCert Assured ID Root G3 O=DigiCert Inc OU=www.digicert.com +# Subject: CN=DigiCert Assured ID Root G3 O=DigiCert Inc OU=www.digicert.com +# Label: "DigiCert Assured ID Root G3" +# Serial: 15459312981008553731928384953135426796 +# MD5 Fingerprint: 7c:7f:65:31:0c:81:df:8d:ba:3e:99:e2:5c:ad:6e:fb +# SHA1 Fingerprint: f5:17:a2:4f:9a:48:c6:c9:f8:a2:00:26:9f:dc:0f:48:2c:ab:30:89 +# SHA256 Fingerprint: 7e:37:cb:8b:4c:47:09:0c:ab:36:55:1b:a6:f4:5d:b8:40:68:0f:ba:16:6a:95:2d:b1:00:71:7f:43:05:3f:c2 +-----BEGIN CERTIFICATE----- +MIICRjCCAc2gAwIBAgIQC6Fa+h3foLVJRK/NJKBs7DAKBggqhkjOPQQDAzBlMQsw +CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu +ZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3Qg +RzMwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBlMQswCQYDVQQGEwJV +UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQu +Y29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwdjAQBgcq +hkjOPQIBBgUrgQQAIgNiAAQZ57ysRGXtzbg/WPuNsVepRC0FFfLvC/8QdJ+1YlJf +Zn4f5dwbRXkLzMZTCp2NXQLZqVneAlr2lSoOjThKiknGvMYDOAdfVdp+CW7if17Q +RSAPWXYQ1qAk8C3eNvJsKTmjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/ +BAQDAgGGMB0GA1UdDgQWBBTL0L2p4ZgFUaFNN6KDec6NHSrkhDAKBggqhkjOPQQD +AwNnADBkAjAlpIFFAmsSS3V0T8gj43DydXLefInwz5FyYZ5eEJJZVrmDxxDnOOlY +JjZ91eQ0hjkCMHw2U/Aw5WJjOpnitqM7mzT6HtoQknFekROn3aRukswy1vUhZscv +6pZjamVFkpUBtA== +-----END CERTIFICATE----- + +# Issuer: CN=DigiCert Global Root G2 O=DigiCert Inc OU=www.digicert.com +# Subject: CN=DigiCert Global Root G2 O=DigiCert Inc OU=www.digicert.com +# Label: "DigiCert Global Root G2" +# Serial: 4293743540046975378534879503202253541 +# MD5 Fingerprint: e4:a6:8a:c8:54:ac:52:42:46:0a:fd:72:48:1b:2a:44 +# SHA1 Fingerprint: df:3c:24:f9:bf:d6:66:76:1b:26:80:73:fe:06:d1:cc:8d:4f:82:a4 +# SHA256 Fingerprint: cb:3c:cb:b7:60:31:e5:e0:13:8f:8d:d3:9a:23:f9:de:47:ff:c3:5e:43:c1:14:4c:ea:27:d4:6a:5a:b1:cb:5f +-----BEGIN CERTIFICATE----- +MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBh +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH +MjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVT +MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j +b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI +2/Ou8jqJkTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx +1x7e/dfgy5SDN67sH0NO3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQ +q2EGnI/yuum06ZIya7XzV+hdG82MHauVBJVJ8zUtluNJbd134/tJS7SsVQepj5Wz +tCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyMUNGPHgm+F6HmIcr9g+UQ +vIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQABo0IwQDAP +BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV +5uNu5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY +1Yl9PMWLSn/pvtsrF9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4 +NeF22d+mQrvHRAiGfzZ0JFrabA0UWTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NG +Fdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBHQRFXGU7Aj64GxJUTFy8bJZ91 +8rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/iyK5S9kJRaTe +pLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl +MrY= +-----END CERTIFICATE----- + +# Issuer: CN=DigiCert Global Root G3 O=DigiCert Inc OU=www.digicert.com +# Subject: CN=DigiCert Global Root G3 O=DigiCert Inc OU=www.digicert.com +# Label: "DigiCert Global Root G3" +# Serial: 7089244469030293291760083333884364146 +# MD5 Fingerprint: f5:5d:a4:50:a5:fb:28:7e:1e:0f:0d:cc:96:57:56:ca +# SHA1 Fingerprint: 7e:04:de:89:6a:3e:66:6d:00:e6:87:d3:3f:fa:d9:3b:e8:3d:34:9e +# SHA256 Fingerprint: 31:ad:66:48:f8:10:41:38:c7:38:f3:9e:a4:32:01:33:39:3e:3a:18:cc:02:29:6e:f9:7c:2a:c9:ef:67:31:d0 +-----BEGIN CERTIFICATE----- +MIICPzCCAcWgAwIBAgIQBVVWvPJepDU1w6QP1atFcjAKBggqhkjOPQQDAzBhMQsw +CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu +ZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMzAe +Fw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVTMRUw +EwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20x +IDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEczMHYwEAYHKoZIzj0CAQYF +K4EEACIDYgAE3afZu4q4C/sLfyHS8L6+c/MzXRq8NOrexpu80JX28MzQC7phW1FG +fp4tn+6OYwwX7Adw9c+ELkCDnOg/QW07rdOkFFk2eJ0DQ+4QE2xy3q6Ip6FrtUPO +Z9wj/wMco+I+o0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAd +BgNVHQ4EFgQUs9tIpPmhxdiuNkHMEWNpYim8S8YwCgYIKoZIzj0EAwMDaAAwZQIx +AK288mw/EkrRLTnDCgmXc/SINoyIJ7vmiI1Qhadj+Z4y3maTD/HMsQmP3Wyr+mt/ +oAIwOWZbwmSNuJ5Q3KjVSaLtx9zRSX8XAbjIho9OjIgrqJqpisXRAL34VOKa5Vt8 +sycX +-----END CERTIFICATE----- + +# Issuer: CN=DigiCert Trusted Root G4 O=DigiCert Inc OU=www.digicert.com +# Subject: CN=DigiCert Trusted Root G4 O=DigiCert Inc OU=www.digicert.com +# Label: "DigiCert Trusted Root G4" +# Serial: 7451500558977370777930084869016614236 +# MD5 Fingerprint: 78:f2:fc:aa:60:1f:2f:b4:eb:c9:37:ba:53:2e:75:49 +# SHA1 Fingerprint: dd:fb:16:cd:49:31:c9:73:a2:03:7d:3f:c8:3a:4d:7d:77:5d:05:e4 +# SHA256 Fingerprint: 55:2f:7b:dc:f1:a7:af:9e:6c:e6:72:01:7f:4f:12:ab:f7:72:40:c7:8e:76:1a:c2:03:d1:d9:d2:0a:c8:99:88 +-----BEGIN CERTIFICATE----- +MIIFkDCCA3igAwIBAgIQBZsbV56OITLiOQe9p3d1XDANBgkqhkiG9w0BAQwFADBi +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3Qg +RzQwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBiMQswCQYDVQQGEwJV +UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQu +Y29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwggIiMA0GCSqG +SIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1KPDAiMGkz7MKnJS7JIT3y +ithZwuEppz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2rsnnyyhHS5F/WBTxSD1If +xp4VpX6+n6lXFllVcq9ok3DCsrp1mWpzMpTREEQQLt+C8weE5nQ7bXHiLQwb7iDV +ySAdYyktzuxeTsiT+CFhmzTrBcZe7FsavOvJz82sNEBfsXpm7nfISKhmV1efVFiO +DCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGYQJB5w3jHtrHEtWoYOAMQ +jdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8rhsDdV14Ztk6MUSaM0C/ +CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaYdj1ZXUJ2h4mXaXpI8OCi +EhtmmnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+wJS00mFt6zPZxd9LBADM +fRyVw4/3IbKyEbe7f/LVjHAsQWCqsWMYRJUadmJ+9oCw++hkpjPRiQfhvbfmQ6QY +uKZ3AeEPlAwhHbJUKSWJbOUOUlFHdL4mrLZBdd56rF+NP8m800ERElvlEFDrMcXK +chYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8oR7FwI+isX4KJpn15GkvmB0t +9dmpsh3lGwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB +hjAdBgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wDQYJKoZIhvcNAQEMBQAD +ggIBALth2X2pbL4XxJEbw6GiAI3jZGgPVs93rnD5/ZpKmbnJeFwMDF/k5hQpVgs2 +SV1EY+CtnJYYZhsjDT156W1r1lT40jzBQ0CuHVD1UvyQO7uYmWlrx8GnqGikJ9yd ++SeuMIW59mdNOj6PWTkiU0TryF0Dyu1Qen1iIQqAyHNm0aAFYF/opbSnr6j3bTWc +fFqK1qI4mfN4i/RN0iAL3gTujJtHgXINwBQy7zBZLq7gcfJW5GqXb5JQbZaNaHqa +sjYUegbyJLkJEVDXCLG4iXqEI2FCKeWjzaIgQdfRnGTZ6iahixTXTBmyUEFxPT9N +cCOGDErcgdLMMpSEDQgJlxxPwO5rIHQw0uA5NBCFIRUBCOhVMt5xSdkoF1BN5r5N +0XWs0Mr7QbhDparTwwVETyw2m+L64kW4I1NsBm9nVX9GtUw/bihaeSbSpKhil9Ie +4u1Ki7wb/UdKDd9nZn6yW0HQO+T0O/QEY+nvwlQAUaCKKsnOeMzV6ocEGLPOr0mI +r/OSmbaz5mEP0oUA51Aa5BuVnRmhuZyxm7EAHu/QD09CbMkKvO5D+jpxpchNJqU1 +/YldvIViHTLSoCtU7ZpXwdv6EM8Zt4tKG48BtieVU+i2iW1bvGjUI+iLUaJW+fCm +gKDWHrO8Dw9TdSmq6hN35N6MgSGtBxBHEa2HPQfRdbzP82Z+ +-----END CERTIFICATE----- + +# Issuer: CN=COMODO RSA Certification Authority O=COMODO CA Limited +# Subject: CN=COMODO RSA Certification Authority O=COMODO CA Limited +# Label: "COMODO RSA Certification Authority" +# Serial: 101909084537582093308941363524873193117 +# MD5 Fingerprint: 1b:31:b0:71:40:36:cc:14:36:91:ad:c4:3e:fd:ec:18 +# SHA1 Fingerprint: af:e5:d2:44:a8:d1:19:42:30:ff:47:9f:e2:f8:97:bb:cd:7a:8c:b4 +# SHA256 Fingerprint: 52:f0:e1:c4:e5:8e:c6:29:29:1b:60:31:7f:07:46:71:b8:5d:7e:a8:0d:5b:07:27:34:63:53:4b:32:b4:02:34 +-----BEGIN CERTIFICATE----- +MIIF2DCCA8CgAwIBAgIQTKr5yttjb+Af907YWwOGnTANBgkqhkiG9w0BAQwFADCB +hTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G +A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNV +BAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAwMTE5 +MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgT +EkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR +Q09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNh +dGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCR +6FSS0gpWsawNJN3Fz0RndJkrN6N9I3AAcbxT38T6KhKPS38QVr2fcHK3YX/JSw8X +pz3jsARh7v8Rl8f0hj4K+j5c+ZPmNHrZFGvnnLOFoIJ6dq9xkNfs/Q36nGz637CC +9BR++b7Epi9Pf5l/tfxnQ3K9DADWietrLNPtj5gcFKt+5eNu/Nio5JIk2kNrYrhV +/erBvGy2i/MOjZrkm2xpmfh4SDBF1a3hDTxFYPwyllEnvGfDyi62a+pGx8cgoLEf +Zd5ICLqkTqnyg0Y3hOvozIFIQ2dOciqbXL1MGyiKXCJ7tKuY2e7gUYPDCUZObT6Z ++pUX2nwzV0E8jVHtC7ZcryxjGt9XyD+86V3Em69FmeKjWiS0uqlWPc9vqv9JWL7w +qP/0uK3pN/u6uPQLOvnoQ0IeidiEyxPx2bvhiWC4jChWrBQdnArncevPDt09qZah +SL0896+1DSJMwBGB7FY79tOi4lu3sgQiUpWAk2nojkxl8ZEDLXB0AuqLZxUpaVIC +u9ffUGpVRr+goyhhf3DQw6KqLCGqR84onAZFdr+CGCe01a60y1Dma/RMhnEw6abf +Fobg2P9A3fvQQoh/ozM6LlweQRGBY84YcWsr7KaKtzFcOmpH4MN5WdYgGq/yapiq +crxXStJLnbsQ/LBMQeXtHT1eKJ2czL+zUdqnR+WEUwIDAQABo0IwQDAdBgNVHQ4E +FgQUu69+Aj36pvE8hI6t7jiY7NkyMtQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB +/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAArx1UaEt65Ru2yyTUEUAJNMnMvl +wFTPoCWOAvn9sKIN9SCYPBMtrFaisNZ+EZLpLrqeLppysb0ZRGxhNaKatBYSaVqM +4dc+pBroLwP0rmEdEBsqpIt6xf4FpuHA1sj+nq6PK7o9mfjYcwlYRm6mnPTXJ9OV +2jeDchzTc+CiR5kDOF3VSXkAKRzH7JsgHAckaVd4sjn8OoSgtZx8jb8uk2Intzna +FxiuvTwJaP+EmzzV1gsD41eeFPfR60/IvYcjt7ZJQ3mFXLrrkguhxuhoqEwWsRqZ +CuhTLJK7oQkYdQxlqHvLI7cawiiFwxv/0Cti76R7CZGYZ4wUAc1oBmpjIXUDgIiK +boHGhfKppC3n9KUkEEeDys30jXlYsQab5xoq2Z0B15R97QNKyvDb6KkBPvVWmcke +jkk9u+UJueBPSZI9FoJAzMxZxuY67RIuaTxslbH9qh17f4a+Hg4yRvv7E491f0yL +S0Zj/gA0QHDBw7mh3aZw4gSzQbzpgJHqZJx64SIDqZxubw5lT2yHh17zbqD5daWb +QOhTsiedSrnAdyGN/4fy3ryM7xfft0kL0fJuMAsaDk527RH89elWsn2/x20Kk4yl +0MC2Hb46TpSi125sC8KKfPog88Tk5c0NqMuRkrF8hey1FGlmDoLnzc7ILaZRfyHB +NVOFBkpdn627G190 +-----END CERTIFICATE----- + +# Issuer: CN=USERTrust RSA Certification Authority O=The USERTRUST Network +# Subject: CN=USERTrust RSA Certification Authority O=The USERTRUST Network +# Label: "USERTrust RSA Certification Authority" +# Serial: 2645093764781058787591871645665788717 +# MD5 Fingerprint: 1b:fe:69:d1:91:b7:19:33:a3:72:a8:0f:e1:55:e5:b5 +# SHA1 Fingerprint: 2b:8f:1b:57:33:0d:bb:a2:d0:7a:6c:51:f7:0e:e9:0d:da:b9:ad:8e +# SHA256 Fingerprint: e7:93:c9:b0:2f:d8:aa:13:e2:1c:31:22:8a:cc:b0:81:19:64:3b:74:9c:89:89:64:b1:74:6d:46:c3:d4:cb:d2 +-----BEGIN CERTIFICATE----- +MIIF3jCCA8agAwIBAgIQAf1tMPyjylGoG7xkDjUDLTANBgkqhkiG9w0BAQwFADCB +iDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0pl +cnNleSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNV +BAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAw +MjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMCVVMxEzARBgNV +BAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU +aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2Vy +dGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK +AoICAQCAEmUXNg7D2wiz0KxXDXbtzSfTTK1Qg2HiqiBNCS1kCdzOiZ/MPans9s/B +3PHTsdZ7NygRK0faOca8Ohm0X6a9fZ2jY0K2dvKpOyuR+OJv0OwWIJAJPuLodMkY +tJHUYmTbf6MG8YgYapAiPLz+E/CHFHv25B+O1ORRxhFnRghRy4YUVD+8M/5+bJz/ +Fp0YvVGONaanZshyZ9shZrHUm3gDwFA66Mzw3LyeTP6vBZY1H1dat//O+T23LLb2 +VN3I5xI6Ta5MirdcmrS3ID3KfyI0rn47aGYBROcBTkZTmzNg95S+UzeQc0PzMsNT +79uq/nROacdrjGCT3sTHDN/hMq7MkztReJVni+49Vv4M0GkPGw/zJSZrM233bkf6 +c0Plfg6lZrEpfDKEY1WJxA3Bk1QwGROs0303p+tdOmw1XNtB1xLaqUkL39iAigmT +Yo61Zs8liM2EuLE/pDkP2QKe6xJMlXzzawWpXhaDzLhn4ugTncxbgtNMs+1b/97l +c6wjOy0AvzVVdAlJ2ElYGn+SNuZRkg7zJn0cTRe8yexDJtC/QV9AqURE9JnnV4ee +UB9XVKg+/XRjL7FQZQnmWEIuQxpMtPAlR1n6BB6T1CZGSlCBst6+eLf8ZxXhyVeE +Hg9j1uliutZfVS7qXMYoCAQlObgOK6nyTJccBz8NUvXt7y+CDwIDAQABo0IwQDAd +BgNVHQ4EFgQUU3m/WqorSs9UgOHYm8Cd8rIDZsswDgYDVR0PAQH/BAQDAgEGMA8G +A1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAFzUfA3P9wF9QZllDHPF +Up/L+M+ZBn8b2kMVn54CVVeWFPFSPCeHlCjtHzoBN6J2/FNQwISbxmtOuowhT6KO +VWKR82kV2LyI48SqC/3vqOlLVSoGIG1VeCkZ7l8wXEskEVX/JJpuXior7gtNn3/3 +ATiUFJVDBwn7YKnuHKsSjKCaXqeYalltiz8I+8jRRa8YFWSQEg9zKC7F4iRO/Fjs +8PRF/iKz6y+O0tlFYQXBl2+odnKPi4w2r78NBc5xjeambx9spnFixdjQg3IM8WcR +iQycE0xyNN+81XHfqnHd4blsjDwSXWXavVcStkNr/+XeTWYRUc+ZruwXtuhxkYze +Sf7dNXGiFSeUHM9h4ya7b6NnJSFd5t0dCy5oGzuCr+yDZ4XUmFF0sbmZgIn/f3gZ +XHlKYC6SQK5MNyosycdiyA5d9zZbyuAlJQG03RoHnHcAP9Dc1ew91Pq7P8yF1m9/ +qS3fuQL39ZeatTXaw2ewh0qpKJ4jjv9cJ2vhsE/zB+4ALtRZh8tSQZXq9EfX7mRB +VXyNWQKV3WKdwrnuWih0hKWbt5DHDAff9Yk2dDLWKMGwsAvgnEzDHNb842m1R0aB +L6KCq9NjRHDEjf8tM7qtj3u1cIiuPhnPQCjY/MiQu12ZIvVS5ljFH4gxQ+6IHdfG +jjxDah2nGN59PRbxYvnKkKj9 +-----END CERTIFICATE----- + +# Issuer: CN=USERTrust ECC Certification Authority O=The USERTRUST Network +# Subject: CN=USERTrust ECC Certification Authority O=The USERTRUST Network +# Label: "USERTrust ECC Certification Authority" +# Serial: 123013823720199481456569720443997572134 +# MD5 Fingerprint: fa:68:bc:d9:b5:7f:ad:fd:c9:1d:06:83:28:cc:24:c1 +# SHA1 Fingerprint: d1:cb:ca:5d:b2:d5:2a:7f:69:3b:67:4d:e5:f0:5a:1d:0c:95:7d:f0 +# SHA256 Fingerprint: 4f:f4:60:d5:4b:9c:86:da:bf:bc:fc:57:12:e0:40:0d:2b:ed:3f:bc:4d:4f:bd:aa:86:e0:6a:dc:d2:a9:ad:7a +-----BEGIN CERTIFICATE----- +MIICjzCCAhWgAwIBAgIQXIuZxVqUxdJxVt7NiYDMJjAKBggqhkjOPQQDAzCBiDEL +MAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNl +eSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMT +JVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAwMjAx +MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgT +Ck5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVUaGUg +VVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlm +aWNhdGlvbiBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQarFRaqflo +I+d61SRvU8Za2EurxtW20eZzca7dnNYMYf3boIkDuAUU7FfO7l0/4iGzzvfUinng +o4N+LZfQYcTxmdwlkWOrfzCjtHDix6EznPO/LlxTsV+zfTJ/ijTjeXmjQjBAMB0G +A1UdDgQWBBQ64QmG1M8ZwpZ2dEl23OA1xmNjmjAOBgNVHQ8BAf8EBAMCAQYwDwYD +VR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjA2Z6EWCNzklwBBHU6+4WMB +zzuqQhFkoJ2UOQIReVx7Hfpkue4WQrO/isIJxOzksU0CMQDpKmFHjFJKS04YcPbW +RNZu9YO6bVi9JNlWSOrvxKJGgYhqOkbRqZtNyWHa0V1Xahg= +-----END CERTIFICATE----- + +# Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign ECC Root CA - R4 +# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign ECC Root CA - R4 +# Label: "GlobalSign ECC Root CA - R4" +# Serial: 14367148294922964480859022125800977897474 +# MD5 Fingerprint: 20:f0:27:68:d1:7e:a0:9d:0e:e6:2a:ca:df:5c:89:8e +# SHA1 Fingerprint: 69:69:56:2e:40:80:f4:24:a1:e7:19:9f:14:ba:f3:ee:58:ab:6a:bb +# SHA256 Fingerprint: be:c9:49:11:c2:95:56:76:db:6c:0a:55:09:86:d7:6e:3b:a0:05:66:7c:44:2c:97:62:b4:fb:b7:73:de:22:8c +-----BEGIN CERTIFICATE----- +MIIB4TCCAYegAwIBAgIRKjikHJYKBN5CsiilC+g0mAIwCgYIKoZIzj0EAwIwUDEk +MCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI0MRMwEQYDVQQKEwpH +bG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoX +DTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBD +QSAtIFI0MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu +MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEuMZ5049sJQ6fLjkZHAOkrprlOQcJ +FspjsbmG+IpXwVfOQvpzofdlQv8ewQCybnMO/8ch5RikqtlxP6jUuc6MHaNCMEAw +DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFFSwe61F +uOJAf/sKbvu+M8k8o4TVMAoGCCqGSM49BAMCA0gAMEUCIQDckqGgE6bPA7DmxCGX +kPoUVy0D7O48027KqGx2vKLeuwIgJ6iFJzWbVsaj8kfSt24bAgAXqmemFZHe+pTs +ewv4n4Q= +-----END CERTIFICATE----- + +# Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign ECC Root CA - R5 +# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign ECC Root CA - R5 +# Label: "GlobalSign ECC Root CA - R5" +# Serial: 32785792099990507226680698011560947931244 +# MD5 Fingerprint: 9f:ad:3b:1c:02:1e:8a:ba:17:74:38:81:0c:a2:bc:08 +# SHA1 Fingerprint: 1f:24:c6:30:cd:a4:18:ef:20:69:ff:ad:4f:dd:5f:46:3a:1b:69:aa +# SHA256 Fingerprint: 17:9f:bc:14:8a:3d:d0:0f:d2:4e:a1:34:58:cc:43:bf:a7:f5:9c:81:82:d7:83:a5:13:f6:eb:ec:10:0c:89:24 +-----BEGIN CERTIFICATE----- +MIICHjCCAaSgAwIBAgIRYFlJ4CYuu1X5CneKcflK2GwwCgYIKoZIzj0EAwMwUDEk +MCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpH +bG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoX +DTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBD +QSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu +MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAER0UOlvt9Xb/pOdEh+J8LttV7HpI6SFkc +8GIxLcB6KP4ap1yztsyX50XUWPrRd21DosCHZTQKH3rd6zwzocWdTaRvQZU4f8ke +hOvRnkmSh5SHDDqFSmafnVmTTZdhBoZKo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYD +VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUPeYpSJvqB8ohREom3m7e0oPQn1kwCgYI +KoZIzj0EAwMDaAAwZQIxAOVpEslu28YxuglB4Zf4+/2a4n0Sye18ZNPLBSWLVtmg +515dTguDnFt2KaAJJiFqYgIwcdK1j1zqO+F4CYWodZI7yFz9SO8NdCKoCOJuxUnO +xwy8p2Fp8fc74SrL+SvzZpA3 +-----END CERTIFICATE----- + +# Issuer: CN=Staat der Nederlanden EV Root CA O=Staat der Nederlanden +# Subject: CN=Staat der Nederlanden EV Root CA O=Staat der Nederlanden +# Label: "Staat der Nederlanden EV Root CA" +# Serial: 10000013 +# MD5 Fingerprint: fc:06:af:7b:e8:1a:f1:9a:b4:e8:d2:70:1f:c0:f5:ba +# SHA1 Fingerprint: 76:e2:7e:c1:4f:db:82:c1:c0:a6:75:b5:05:be:3d:29:b4:ed:db:bb +# SHA256 Fingerprint: 4d:24:91:41:4c:fe:95:67:46:ec:4c:ef:a6:cf:6f:72:e2:8a:13:29:43:2f:9d:8a:90:7a:c4:cb:5d:ad:c1:5a +-----BEGIN CERTIFICATE----- +MIIFcDCCA1igAwIBAgIEAJiWjTANBgkqhkiG9w0BAQsFADBYMQswCQYDVQQGEwJO +TDEeMBwGA1UECgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSkwJwYDVQQDDCBTdGFh +dCBkZXIgTmVkZXJsYW5kZW4gRVYgUm9vdCBDQTAeFw0xMDEyMDgxMTE5MjlaFw0y +MjEyMDgxMTEwMjhaMFgxCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIg +TmVkZXJsYW5kZW4xKTAnBgNVBAMMIFN0YWF0IGRlciBOZWRlcmxhbmRlbiBFViBS +b290IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA48d+ifkkSzrS +M4M1LGns3Amk41GoJSt5uAg94JG6hIXGhaTK5skuU6TJJB79VWZxXSzFYGgEt9nC +UiY4iKTWO0Cmws0/zZiTs1QUWJZV1VD+hq2kY39ch/aO5ieSZxeSAgMs3NZmdO3d +Z//BYY1jTw+bbRcwJu+r0h8QoPnFfxZpgQNH7R5ojXKhTbImxrpsX23Wr9GxE46p +rfNeaXUmGD5BKyF/7otdBwadQ8QpCiv8Kj6GyzyDOvnJDdrFmeK8eEEzduG/L13l +pJhQDBXd4Pqcfzho0LKmeqfRMb1+ilgnQ7O6M5HTp5gVXJrm0w912fxBmJc+qiXb +j5IusHsMX/FjqTf5m3VpTCgmJdrV8hJwRVXj33NeN/UhbJCONVrJ0yPr08C+eKxC +KFhmpUZtcALXEPlLVPxdhkqHz3/KRawRWrUgUY0viEeXOcDPusBCAUCZSCELa6fS +/ZbV0b5GnUngC6agIk440ME8MLxwjyx1zNDFjFE7PZQIZCZhfbnDZY8UnCHQqv0X +cgOPvZuM5l5Tnrmd74K74bzickFbIZTTRTeU0d8JOV3nI6qaHcptqAqGhYqCvkIH +1vI4gnPah1vlPNOePqc7nvQDs/nxfRN0Av+7oeX6AHkcpmZBiFxgV6YuCcS6/ZrP +px9Aw7vMWgpVSzs4dlG4Y4uElBbmVvMCAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB +/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFP6rAJCYniT8qcwaivsnuL8wbqg7 +MA0GCSqGSIb3DQEBCwUAA4ICAQDPdyxuVr5Os7aEAJSrR8kN0nbHhp8dB9O2tLsI +eK9p0gtJ3jPFrK3CiAJ9Brc1AsFgyb/E6JTe1NOpEyVa/m6irn0F3H3zbPB+po3u +2dfOWBfoqSmuc0iH55vKbimhZF8ZE/euBhD/UcabTVUlT5OZEAFTdfETzsemQUHS +v4ilf0X8rLiltTMMgsT7B/Zq5SWEXwbKwYY5EdtYzXc7LMJMD16a4/CrPmEbUCTC +wPTxGfARKbalGAKb12NMcIxHowNDXLldRqANb/9Zjr7dn3LDWyvfjFvO5QxGbJKy +CqNMVEIYFRIYvdr8unRu/8G2oGTYqV9Vrp9canaW2HNnh/tNf1zuacpzEPuKqf2e +vTY4SUmH9A4U8OmHuD+nT3pajnnUk+S7aFKErGzp85hwVXIy+TSrK0m1zSBi5Dp6 +Z2Orltxtrpfs/J92VoguZs9btsmksNcFuuEnL5O7Jiqik7Ab846+HUCjuTaPPoIa +Gl6I6lD4WeKDRikL40Rc4ZW2aZCaFG+XroHPaO+Zmr615+F/+PoTRxZMzG0IQOeL +eG9QgkRQP2YGiqtDhFZKDyAthg710tvSeopLzaXoTvFeJiUBWSOgftL2fiFX1ye8 +FVdMpEbB4IMeDExNH08GGeL5qPQ6gqGyeUN51q1veieQA6TqJIc/2b3Z6fJfUEkc +7uzXLg== +-----END CERTIFICATE----- + +# Issuer: CN=IdenTrust Commercial Root CA 1 O=IdenTrust +# Subject: CN=IdenTrust Commercial Root CA 1 O=IdenTrust +# Label: "IdenTrust Commercial Root CA 1" +# Serial: 13298821034946342390520003877796839426 +# MD5 Fingerprint: b3:3e:77:73:75:ee:a0:d3:e3:7e:49:63:49:59:bb:c7 +# SHA1 Fingerprint: df:71:7e:aa:4a:d9:4e:c9:55:84:99:60:2d:48:de:5f:bc:f0:3a:25 +# SHA256 Fingerprint: 5d:56:49:9b:e4:d2:e0:8b:cf:ca:d0:8a:3e:38:72:3d:50:50:3b:de:70:69:48:e4:2f:55:60:30:19:e5:28:ae +-----BEGIN CERTIFICATE----- +MIIFYDCCA0igAwIBAgIQCgFCgAAAAUUjyES1AAAAAjANBgkqhkiG9w0BAQsFADBK +MQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVu +VHJ1c3QgQ29tbWVyY2lhbCBSb290IENBIDEwHhcNMTQwMTE2MTgxMjIzWhcNMzQw +MTE2MTgxMjIzWjBKMQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0MScw +JQYDVQQDEx5JZGVuVHJ1c3QgQ29tbWVyY2lhbCBSb290IENBIDEwggIiMA0GCSqG +SIb3DQEBAQUAA4ICDwAwggIKAoICAQCnUBneP5k91DNG8W9RYYKyqU+PZ4ldhNlT +3Qwo2dfw/66VQ3KZ+bVdfIrBQuExUHTRgQ18zZshq0PirK1ehm7zCYofWjK9ouuU ++ehcCuz/mNKvcbO0U59Oh++SvL3sTzIwiEsXXlfEU8L2ApeN2WIrvyQfYo3fw7gp +S0l4PJNgiCL8mdo2yMKi1CxUAGc1bnO/AljwpN3lsKImesrgNqUZFvX9t++uP0D1 +bVoE/c40yiTcdCMbXTMTEl3EASX2MN0CXZ/g1Ue9tOsbobtJSdifWwLziuQkkORi +T0/Br4sOdBeo0XKIanoBScy0RnnGF7HamB4HWfp1IYVl3ZBWzvurpWCdxJ35UrCL +vYf5jysjCiN2O/cz4ckA82n5S6LgTrx+kzmEB/dEcH7+B1rlsazRGMzyNeVJSQjK +Vsk9+w8YfYs7wRPCTY/JTw436R+hDmrfYi7LNQZReSzIJTj0+kuniVyc0uMNOYZK +dHzVWYfCP04MXFL0PfdSgvHqo6z9STQaKPNBiDoT7uje/5kdX7rL6B7yuVBgwDHT +c+XvvqDtMwt0viAgxGds8AgDelWAf0ZOlqf0Hj7h9tgJ4TNkK2PXMl6f+cB7D3hv +l7yTmvmcEpB4eoCHFddydJxVdHixuuFucAS6T6C6aMN7/zHwcz09lCqxC0EOoP5N +iGVreTO01wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB +/zAdBgNVHQ4EFgQU7UQZwNPwBovupHu+QucmVMiONnYwDQYJKoZIhvcNAQELBQAD +ggIBAA2ukDL2pkt8RHYZYR4nKM1eVO8lvOMIkPkp165oCOGUAFjvLi5+U1KMtlwH +6oi6mYtQlNeCgN9hCQCTrQ0U5s7B8jeUeLBfnLOic7iPBZM4zY0+sLj7wM+x8uwt +LRvM7Kqas6pgghstO8OEPVeKlh6cdbjTMM1gCIOQ045U8U1mwF10A0Cj7oV+wh93 +nAbowacYXVKV7cndJZ5t+qntozo00Fl72u1Q8zW/7esUTTHHYPTa8Yec4kjixsU3 ++wYQ+nVZZjFHKdp2mhzpgq7vmrlR94gjmmmVYjzlVYA211QC//G5Xc7UI2/YRYRK +W2XviQzdFKcgyxilJbQN+QHwotL0AMh0jqEqSI5l2xPE4iUXfeu+h1sXIFRRk0pT +AwvsXcoz7WL9RccvW9xYoIA55vrX/hMUpu09lEpCdNTDd1lzzY9GvlU47/rokTLq +l1gEIt44w8y8bckzOmoKaT+gyOpyj4xjhiO9bTyWnpXgSUyqorkqG5w2gXjtw+hG +4iZZRHUe2XWJUc0QhJ1hYMtd+ZciTY6Y5uN/9lu7rs3KSoFrXgvzUeF0K+l+J6fZ +mUlO+KWA2yUPHGNiiskzZ2s8EIPGrd6ozRaOjfAHN3Gf8qv8QfXBi+wAN10J5U6A +7/qxXDgGpRtK4dw4LTzcqx+QGtVKnO7RcGzM7vRX+Bi6hG6H +-----END CERTIFICATE----- + +# Issuer: CN=IdenTrust Public Sector Root CA 1 O=IdenTrust +# Subject: CN=IdenTrust Public Sector Root CA 1 O=IdenTrust +# Label: "IdenTrust Public Sector Root CA 1" +# Serial: 13298821034946342390521976156843933698 +# MD5 Fingerprint: 37:06:a5:b0:fc:89:9d:ba:f4:6b:8c:1a:64:cd:d5:ba +# SHA1 Fingerprint: ba:29:41:60:77:98:3f:f4:f3:ef:f2:31:05:3b:2e:ea:6d:4d:45:fd +# SHA256 Fingerprint: 30:d0:89:5a:9a:44:8a:26:20:91:63:55:22:d1:f5:20:10:b5:86:7a:ca:e1:2c:78:ef:95:8f:d4:f4:38:9f:2f +-----BEGIN CERTIFICATE----- +MIIFZjCCA06gAwIBAgIQCgFCgAAAAUUjz0Z8AAAAAjANBgkqhkiG9w0BAQsFADBN +MQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVu +VHJ1c3QgUHVibGljIFNlY3RvciBSb290IENBIDEwHhcNMTQwMTE2MTc1MzMyWhcN +MzQwMTE2MTc1MzMyWjBNMQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0 +MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3RvciBSb290IENBIDEwggIi +MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2IpT8pEiv6EdrCvsnduTyP4o7 +ekosMSqMjbCpwzFrqHd2hCa2rIFCDQjrVVi7evi8ZX3yoG2LqEfpYnYeEe4IFNGy +RBb06tD6Hi9e28tzQa68ALBKK0CyrOE7S8ItneShm+waOh7wCLPQ5CQ1B5+ctMlS +bdsHyo+1W/CD80/HLaXIrcuVIKQxKFdYWuSNG5qrng0M8gozOSI5Cpcu81N3uURF +/YTLNiCBWS2ab21ISGHKTN9T0a9SvESfqy9rg3LvdYDaBjMbXcjaY8ZNzaxmMc3R +3j6HEDbhuaR672BQssvKplbgN6+rNBM5Jeg5ZuSYeqoSmJxZZoY+rfGwyj4GD3vw +EUs3oERte8uojHH01bWRNszwFcYr3lEXsZdMUD2xlVl8BX0tIdUAvwFnol57plzy +9yLxkA2T26pEUWbMfXYD62qoKjgZl3YNa4ph+bz27nb9cCvdKTz4Ch5bQhyLVi9V +GxyhLrXHFub4qjySjmm2AcG1hp2JDws4lFTo6tyePSW8Uybt1as5qsVATFSrsrTZ +2fjXctscvG29ZV/viDUqZi/u9rNl8DONfJhBaUYPQxxp+pu10GFqzcpL2UyQRqsV +WaFHVCkugyhfHMKiq3IXAAaOReyL4jM9f9oZRORicsPfIsbyVtTdX5Vy7W1f90gD +W/3FKqD2cyOEEBsB5wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/ +BAUwAwEB/zAdBgNVHQ4EFgQU43HgntinQtnbcZFrlJPrw6PRFKMwDQYJKoZIhvcN +AQELBQADggIBAEf63QqwEZE4rU1d9+UOl1QZgkiHVIyqZJnYWv6IAcVYpZmxI1Qj +t2odIFflAWJBF9MJ23XLblSQdf4an4EKwt3X9wnQW3IV5B4Jaj0z8yGa5hV+rVHV +DRDtfULAj+7AmgjVQdZcDiFpboBhDhXAuM/FSRJSzL46zNQuOAXeNf0fb7iAaJg9 +TaDKQGXSc3z1i9kKlT/YPyNtGtEqJBnZhbMX73huqVjRI9PHE+1yJX9dsXNw0H8G +lwmEKYBhHfpe/3OsoOOJuBxxFcbeMX8S3OFtm6/n6J91eEyrRjuazr8FGF1NFTwW +mhlQBJqymm9li1JfPFgEKCXAZmExfrngdbkaqIHWchezxQMxNRF4eKLg6TCMf4Df +WN88uieW4oA0beOY02QnrEh+KHdcxiVhJfiFDGX6xDIvpZgF5PgLZxYWxoK4Mhn5 ++bl53B/N66+rDt0b20XkeucC4pVd/GnwU2lhlXV5C15V5jgclKlZM57IcXR5f1GJ +tshquDDIajjDbp7hNxbqBWJMWxJH7ae0s1hWx0nzfxJoCTFx8G34Tkf71oXuxVhA +GaQdp/lLQzfcaFpPz+vCZHTetBXZ9FRUGi8c15dxVJCO2SCdUyt/q4/i6jC8UDfv +8Ue1fXwsBOxonbRJRBD0ckscZOf85muQ3Wl9af0AVqW3rLatt8o+Ae+c +-----END CERTIFICATE----- + +# Issuer: CN=Entrust Root Certification Authority - G2 O=Entrust, Inc. OU=See www.entrust.net/legal-terms/(c) 2009 Entrust, Inc. - for authorized use only +# Subject: CN=Entrust Root Certification Authority - G2 O=Entrust, Inc. OU=See www.entrust.net/legal-terms/(c) 2009 Entrust, Inc. - for authorized use only +# Label: "Entrust Root Certification Authority - G2" +# Serial: 1246989352 +# MD5 Fingerprint: 4b:e2:c9:91:96:65:0c:f4:0e:5a:93:92:a0:0a:fe:b2 +# SHA1 Fingerprint: 8c:f4:27:fd:79:0c:3a:d1:66:06:8d:e8:1e:57:ef:bb:93:22:72:d4 +# SHA256 Fingerprint: 43:df:57:74:b0:3e:7f:ef:5f:e4:0d:93:1a:7b:ed:f1:bb:2e:6b:42:73:8c:4e:6d:38:41:10:3d:3a:a7:f3:39 +-----BEGIN CERTIFICATE----- +MIIEPjCCAyagAwIBAgIESlOMKDANBgkqhkiG9w0BAQsFADCBvjELMAkGA1UEBhMC +VVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50 +cnVzdC5uZXQvbGVnYWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3Qs +IEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25seTEyMDAGA1UEAxMpRW50cnVz +dCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIwHhcNMDkwNzA3MTcy +NTU0WhcNMzAxMjA3MTc1NTU0WjCBvjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUVu +dHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwt +dGVybXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0 +aG9yaXplZCB1c2Ugb25seTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmlj +YXRpb24gQXV0aG9yaXR5IC0gRzIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK +AoIBAQC6hLZy254Ma+KZ6TABp3bqMriVQRrJ2mFOWHLP/vaCeb9zYQYKpSfYs1/T +RU4cctZOMvJyig/3gxnQaoCAAEUesMfnmr8SVycco2gvCoe9amsOXmXzHHfV1IWN +cCG0szLni6LVhjkCsbjSR87kyUnEO6fe+1R9V77w6G7CebI6C1XiUJgWMhNcL3hW +wcKUs/Ja5CeanyTXxuzQmyWC48zCxEXFjJd6BmsqEZ+pCm5IO2/b1BEZQvePB7/1 +U1+cPvQXLOZprE4yTGJ36rfo5bs0vBmLrpxR57d+tVOxMyLlbc9wPBr64ptntoP0 +jaWvYkxN4FisZDQSA/i2jZRjJKRxAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAP +BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqciZ60B7vfec7aVHUbI2fkBJmqzAN +BgkqhkiG9w0BAQsFAAOCAQEAeZ8dlsa2eT8ijYfThwMEYGprmi5ZiXMRrEPR9RP/ +jTkrwPK9T3CMqS/qF8QLVJ7UG5aYMzyorWKiAHarWWluBh1+xLlEjZivEtRh2woZ +Rkfz6/djwUAFQKXSt/S1mja/qYh2iARVBCuch38aNzx+LaUa2NSJXsq9rD1s2G2v +1fN2D807iDginWyTmsQ9v4IbZT+mD12q/OWyFcq1rca8PdCE6OoGcrBNOTJ4vz4R +nAuknZoh8/CbCzB428Hch0P+vGOaysXCHMnHjf87ElgI5rY97HosTvuDls4MPGmH +VHOkc8KT/1EQrBVUAdj8BbGJoX90g5pJ19xOe4pIb4tF9g== +-----END CERTIFICATE----- + +# Issuer: CN=Entrust Root Certification Authority - EC1 O=Entrust, Inc. OU=See www.entrust.net/legal-terms/(c) 2012 Entrust, Inc. - for authorized use only +# Subject: CN=Entrust Root Certification Authority - EC1 O=Entrust, Inc. OU=See www.entrust.net/legal-terms/(c) 2012 Entrust, Inc. - for authorized use only +# Label: "Entrust Root Certification Authority - EC1" +# Serial: 51543124481930649114116133369 +# MD5 Fingerprint: b6:7e:1d:f0:58:c5:49:6c:24:3b:3d:ed:98:18:ed:bc +# SHA1 Fingerprint: 20:d8:06:40:df:9b:25:f5:12:25:3a:11:ea:f7:59:8a:eb:14:b5:47 +# SHA256 Fingerprint: 02:ed:0e:b2:8c:14:da:45:16:5c:56:67:91:70:0d:64:51:d7:fb:56:f0:b2:ab:1d:3b:8e:b0:70:e5:6e:df:f5 +-----BEGIN CERTIFICATE----- +MIIC+TCCAoCgAwIBAgINAKaLeSkAAAAAUNCR+TAKBggqhkjOPQQDAzCBvzELMAkG +A1UEBhMCVVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3 +d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDEyIEVu +dHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25seTEzMDEGA1UEAxMq +RW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRUMxMB4XDTEy +MTIxODE1MjUzNloXDTM3MTIxODE1NTUzNlowgb8xCzAJBgNVBAYTAlVTMRYwFAYD +VQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3QubmV0 +L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxMiBFbnRydXN0LCBJbmMuIC0g +Zm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxMzAxBgNVBAMTKkVudHJ1c3QgUm9vdCBD +ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEVDMTB2MBAGByqGSM49AgEGBSuBBAAi +A2IABIQTydC6bUF74mzQ61VfZgIaJPRbiWlH47jCffHyAsWfoPZb1YsGGYZPUxBt +ByQnoaD41UcZYUx9ypMn6nQM72+WCf5j7HBdNq1nd67JnXxVRDqiY1Ef9eNi1KlH +Bz7MIKNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0O +BBYEFLdj5xrdjekIplWDpOBqUEFlEUJJMAoGCCqGSM49BAMDA2cAMGQCMGF52OVC +R98crlOZF7ZvHH3hvxGU0QOIdeSNiaSKd0bebWHvAvX7td/M/k7//qnmpwIwW5nX +hTcGtXsI/esni0qU+eH6p44mCOh8kmhtc9hvJqwhAriZtyZBWyVgrtBIGu4G +-----END CERTIFICATE----- + +# Issuer: CN=CFCA EV ROOT O=China Financial Certification Authority +# Subject: CN=CFCA EV ROOT O=China Financial Certification Authority +# Label: "CFCA EV ROOT" +# Serial: 407555286 +# MD5 Fingerprint: 74:e1:b6:ed:26:7a:7a:44:30:33:94:ab:7b:27:81:30 +# SHA1 Fingerprint: e2:b8:29:4b:55:84:ab:6b:58:c2:90:46:6c:ac:3f:b8:39:8f:84:83 +# SHA256 Fingerprint: 5c:c3:d7:8e:4e:1d:5e:45:54:7a:04:e6:87:3e:64:f9:0c:f9:53:6d:1c:cc:2e:f8:00:f3:55:c4:c5:fd:70:fd +-----BEGIN CERTIFICATE----- +MIIFjTCCA3WgAwIBAgIEGErM1jANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJD +TjEwMC4GA1UECgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9y +aXR5MRUwEwYDVQQDDAxDRkNBIEVWIFJPT1QwHhcNMTIwODA4MDMwNzAxWhcNMjkx +MjMxMDMwNzAxWjBWMQswCQYDVQQGEwJDTjEwMC4GA1UECgwnQ2hpbmEgRmluYW5j +aWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQDDAxDRkNBIEVWIFJP +T1QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDXXWvNED8fBVnVBU03 +sQ7smCuOFR36k0sXgiFxEFLXUWRwFsJVaU2OFW2fvwwbwuCjZ9YMrM8irq93VCpL +TIpTUnrD7i7es3ElweldPe6hL6P3KjzJIx1qqx2hp/Hz7KDVRM8Vz3IvHWOX6Jn5 +/ZOkVIBMUtRSqy5J35DNuF++P96hyk0g1CXohClTt7GIH//62pCfCqktQT+x8Rgp +7hZZLDRJGqgG16iI0gNyejLi6mhNbiyWZXvKWfry4t3uMCz7zEasxGPrb382KzRz +EpR/38wmnvFyXVBlWY9ps4deMm/DGIq1lY+wejfeWkU7xzbh72fROdOXW3NiGUgt +hxwG+3SYIElz8AXSG7Ggo7cbcNOIabla1jj0Ytwli3i/+Oh+uFzJlU9fpy25IGvP +a931DfSCt/SyZi4QKPaXWnuWFo8BGS1sbn85WAZkgwGDg8NNkt0yxoekN+kWzqot +aK8KgWU6cMGbrU1tVMoqLUuFG7OA5nBFDWteNfB/O7ic5ARwiRIlk9oKmSJgamNg +TnYGmE69g60dWIolhdLHZR4tjsbftsbhf4oEIRUpdPA+nJCdDC7xij5aqgwJHsfV +PKPtl8MeNPo4+QgO48BdK4PRVmrJtqhUUy54Mmc9gn900PvhtgVguXDbjgv5E1hv +cWAQUhC5wUEJ73IfZzF4/5YFjQIDAQABo2MwYTAfBgNVHSMEGDAWgBTj/i39KNAL +tbq2osS/BqoFjJP7LzAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAd +BgNVHQ4EFgQU4/4t/SjQC7W6tqLEvwaqBYyT+y8wDQYJKoZIhvcNAQELBQADggIB +ACXGumvrh8vegjmWPfBEp2uEcwPenStPuiB/vHiyz5ewG5zz13ku9Ui20vsXiObT +ej/tUxPQ4i9qecsAIyjmHjdXNYmEwnZPNDatZ8POQQaIxffu2Bq41gt/UP+TqhdL +jOztUmCypAbqTuv0axn96/Ua4CUqmtzHQTb3yHQFhDmVOdYLO6Qn+gjYXB74BGBS +ESgoA//vU2YApUo0FmZ8/Qmkrp5nGm9BC2sGE5uPhnEFtC+NiWYzKXZUmhH4J/qy +P5Hgzg0b8zAarb8iXRvTvyUFTeGSGn+ZnzxEk8rUQElsgIfXBDrDMlI1Dlb4pd19 +xIsNER9Tyx6yF7Zod1rg1MvIB671Oi6ON7fQAUtDKXeMOZePglr4UeWJoBjnaH9d +Ci77o0cOPaYjesYBx4/IXr9tgFa+iiS6M+qf4TIRnvHST4D2G0CvOJ4RUHlzEhLN +5mydLIhyPDCBBpEi6lmt2hkuIsKNuYyH4Ga8cyNfIWRjgEj1oDwYPZTISEEdQLpe +/v5WOaHIz16eGWRGENoXkbcFgKyLmZJ956LYBws2J+dIeWCKw9cTXPhyQN9Ky8+Z +AAoACxGV2lZFA4gKn2fQ1XmxqI1AbQ3CekD6819kR5LLU7m7Wc5P/dAVUwHY3+vZ +5nbv0CO7O6l5s9UCKc2Jo5YPSjXnTkLAdc0Hz+Ys63su +-----END CERTIFICATE----- + +# Issuer: CN=OISTE WISeKey Global Root GB CA O=WISeKey OU=OISTE Foundation Endorsed +# Subject: CN=OISTE WISeKey Global Root GB CA O=WISeKey OU=OISTE Foundation Endorsed +# Label: "OISTE WISeKey Global Root GB CA" +# Serial: 157768595616588414422159278966750757568 +# MD5 Fingerprint: a4:eb:b9:61:28:2e:b7:2f:98:b0:35:26:90:99:51:1d +# SHA1 Fingerprint: 0f:f9:40:76:18:d3:d7:6a:4b:98:f0:a8:35:9e:0c:fd:27:ac:cc:ed +# SHA256 Fingerprint: 6b:9c:08:e8:6e:b0:f7:67:cf:ad:65:cd:98:b6:21:49:e5:49:4a:67:f5:84:5e:7b:d1:ed:01:9f:27:b8:6b:d6 +-----BEGIN CERTIFICATE----- +MIIDtTCCAp2gAwIBAgIQdrEgUnTwhYdGs/gjGvbCwDANBgkqhkiG9w0BAQsFADBt +MQswCQYDVQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUg +Rm91bmRhdGlvbiBFbmRvcnNlZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9i +YWwgUm9vdCBHQiBDQTAeFw0xNDEyMDExNTAwMzJaFw0zOTEyMDExNTEwMzFaMG0x +CzAJBgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYDVQQLExlPSVNURSBG +b3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEdsb2Jh +bCBSb290IEdCIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2Be3 +HEokKtaXscriHvt9OO+Y9bI5mE4nuBFde9IllIiCFSZqGzG7qFshISvYD06fWvGx +WuR51jIjK+FTzJlFXHtPrby/h0oLS5daqPZI7H17Dc0hBt+eFf1Biki3IPShehtX +1F1Q/7pn2COZH8g/497/b1t3sWtuuMlk9+HKQUYOKXHQuSP8yYFfTvdv37+ErXNk +u7dCjmn21HYdfp2nuFeKUWdy19SouJVUQHMD9ur06/4oQnc/nSMbsrY9gBQHTC5P +99UKFg29ZkM3fiNDecNAhvVMKdqOmq0NpQSHiB6F4+lT1ZvIiwNjeOvgGUpuuy9r +M2RYk61pv48b74JIxwIDAQABo1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUw +AwEB/zAdBgNVHQ4EFgQUNQ/INmNe4qPs+TtmFc5RUuORmj0wEAYJKwYBBAGCNxUB +BAMCAQAwDQYJKoZIhvcNAQELBQADggEBAEBM+4eymYGQfp3FsLAmzYh7KzKNbrgh +cViXfa43FK8+5/ea4n32cZiZBKpDdHij40lhPnOMTZTg+XHEthYOU3gf1qKHLwI5 +gSk8rxWYITD+KJAAjNHhy/peyP34EEY7onhCkRd0VQreUGdNZtGn//3ZwLWoo4rO +ZvUPQ82nK1d7Y0Zqqi5S2PTt4W2tKZB4SLrhI6qjiey1q5bAtEuiHZeeevJuQHHf +aPFlTc58Bd9TZaml8LGXBHAVRgOY1NK/VLSgWH1Sb9pWJmLU2NuJMW8c8CLC02Ic +Nc1MaRVUGpCY3useX8p3x8uOPUNpnJpY0CQ73xtAln41rYHHTnG6iBM= +-----END CERTIFICATE----- + +# Issuer: CN=SZAFIR ROOT CA2 O=Krajowa Izba Rozliczeniowa S.A. +# Subject: CN=SZAFIR ROOT CA2 O=Krajowa Izba Rozliczeniowa S.A. +# Label: "SZAFIR ROOT CA2" +# Serial: 357043034767186914217277344587386743377558296292 +# MD5 Fingerprint: 11:64:c1:89:b0:24:b1:8c:b1:07:7e:89:9e:51:9e:99 +# SHA1 Fingerprint: e2:52:fa:95:3f:ed:db:24:60:bd:6e:28:f3:9c:cc:cf:5e:b3:3f:de +# SHA256 Fingerprint: a1:33:9d:33:28:1a:0b:56:e5:57:d3:d3:2b:1c:e7:f9:36:7e:b0:94:bd:5f:a7:2a:7e:50:04:c8:de:d7:ca:fe +-----BEGIN CERTIFICATE----- +MIIDcjCCAlqgAwIBAgIUPopdB+xV0jLVt+O2XwHrLdzk1uQwDQYJKoZIhvcNAQEL +BQAwUTELMAkGA1UEBhMCUEwxKDAmBgNVBAoMH0tyYWpvd2EgSXpiYSBSb3psaWN6 +ZW5pb3dhIFMuQS4xGDAWBgNVBAMMD1NaQUZJUiBST09UIENBMjAeFw0xNTEwMTkw +NzQzMzBaFw0zNTEwMTkwNzQzMzBaMFExCzAJBgNVBAYTAlBMMSgwJgYDVQQKDB9L +cmFqb3dhIEl6YmEgUm96bGljemVuaW93YSBTLkEuMRgwFgYDVQQDDA9TWkFGSVIg +Uk9PVCBDQTIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC3vD5QqEvN +QLXOYeeWyrSh2gwisPq1e3YAd4wLz32ohswmUeQgPYUM1ljj5/QqGJ3a0a4m7utT +3PSQ1hNKDJA8w/Ta0o4NkjrcsbH/ON7Dui1fgLkCvUqdGw+0w8LBZwPd3BucPbOw +3gAeqDRHu5rr/gsUvTaE2g0gv/pby6kWIK05YO4vdbbnl5z5Pv1+TW9NL++IDWr6 +3fE9biCloBK0TXC5ztdyO4mTp4CEHCdJckm1/zuVnsHMyAHs6A6KCpbns6aH5db5 +BSsNl0BwPLqsdVqc1U2dAgrSS5tmS0YHF2Wtn2yIANwiieDhZNRnvDF5YTy7ykHN +XGoAyDw4jlivAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD +AgEGMB0GA1UdDgQWBBQuFqlKGLXLzPVvUPMjX/hd56zwyDANBgkqhkiG9w0BAQsF +AAOCAQEAtXP4A9xZWx126aMqe5Aosk3AM0+qmrHUuOQn/6mWmc5G4G18TKI4pAZw +8PRBEew/R40/cof5O/2kbytTAOD/OblqBw7rHRz2onKQy4I9EYKL0rufKq8h5mOG +nXkZ7/e7DDWQw4rtTw/1zBLZpD67oPwglV9PJi8RI4NOdQcPv5vRtB3pEAT+ymCP +oky4rc/hkA/NrgrHXXu3UNLUYfrVFdvXn4dRVOul4+vJhaAlIDf7js4MNIThPIGy +d05DpYhfhmehPea0XGG2Ptv+tyjFogeutcrKjSoS75ftwjCkySp6+/NNIxuZMzSg +LvWpCz/UXeHPhJ/iGcJfitYgHuNztw== +-----END CERTIFICATE----- + +# Issuer: CN=Certum Trusted Network CA 2 O=Unizeto Technologies S.A. OU=Certum Certification Authority +# Subject: CN=Certum Trusted Network CA 2 O=Unizeto Technologies S.A. OU=Certum Certification Authority +# Label: "Certum Trusted Network CA 2" +# Serial: 44979900017204383099463764357512596969 +# MD5 Fingerprint: 6d:46:9e:d9:25:6d:08:23:5b:5e:74:7d:1e:27:db:f2 +# SHA1 Fingerprint: d3:dd:48:3e:2b:bf:4c:05:e8:af:10:f5:fa:76:26:cf:d3:dc:30:92 +# SHA256 Fingerprint: b6:76:f2:ed:da:e8:77:5c:d3:6c:b0:f6:3c:d1:d4:60:39:61:f4:9e:62:65:ba:01:3a:2f:03:07:b6:d0:b8:04 +-----BEGIN CERTIFICATE----- +MIIF0jCCA7qgAwIBAgIQIdbQSk8lD8kyN/yqXhKN6TANBgkqhkiG9w0BAQ0FADCB +gDELMAkGA1UEBhMCUEwxIjAgBgNVBAoTGVVuaXpldG8gVGVjaG5vbG9naWVzIFMu +QS4xJzAlBgNVBAsTHkNlcnR1bSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEkMCIG +A1UEAxMbQ2VydHVtIFRydXN0ZWQgTmV0d29yayBDQSAyMCIYDzIwMTExMDA2MDgz +OTU2WhgPMjA0NjEwMDYwODM5NTZaMIGAMQswCQYDVQQGEwJQTDEiMCAGA1UEChMZ +VW5pemV0byBUZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRp +ZmljYXRpb24gQXV0aG9yaXR5MSQwIgYDVQQDExtDZXJ0dW0gVHJ1c3RlZCBOZXR3 +b3JrIENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC9+Xj45tWA +DGSdhhuWZGc/IjoedQF97/tcZ4zJzFxrqZHmuULlIEub2pt7uZld2ZuAS9eEQCsn +0+i6MLs+CRqnSZXvK0AkwpfHp+6bJe+oCgCXhVqqndwpyeI1B+twTUrWwbNWuKFB +OJvR+zF/j+Bf4bE/D44WSWDXBo0Y+aomEKsq09DRZ40bRr5HMNUuctHFY9rnY3lE +fktjJImGLjQ/KUxSiyqnwOKRKIm5wFv5HdnnJ63/mgKXwcZQkpsCLL2puTRZCr+E +Sv/f/rOf69me4Jgj7KZrdxYq28ytOxykh9xGc14ZYmhFV+SQgkK7QtbwYeDBoz1m +o130GO6IyY0XRSmZMnUCMe4pJshrAua1YkV/NxVaI2iJ1D7eTiew8EAMvE0Xy02i +sx7QBlrd9pPPV3WZ9fqGGmd4s7+W/jTcvedSVuWz5XV710GRBdxdaeOVDUO5/IOW +OZV7bIBaTxNyxtd9KXpEulKkKtVBRgkg/iKgtlswjbyJDNXXcPiHUv3a76xRLgez +Tv7QCdpw75j6VuZt27VXS9zlLCUVyJ4ueE742pyehizKV/Ma5ciSixqClnrDvFAS +adgOWkaLOusm+iPJtrCBvkIApPjW/jAux9JG9uWOdf3yzLnQh1vMBhBgu4M1t15n +3kfsmUjxpKEV/q2MYo45VU85FrmxY53/twIDAQABo0IwQDAPBgNVHRMBAf8EBTAD +AQH/MB0GA1UdDgQWBBS2oVQ5AsOgP46KvPrU+Bym0ToO/TAOBgNVHQ8BAf8EBAMC +AQYwDQYJKoZIhvcNAQENBQADggIBAHGlDs7k6b8/ONWJWsQCYftMxRQXLYtPU2sQ +F/xlhMcQSZDe28cmk4gmb3DWAl45oPePq5a1pRNcgRRtDoGCERuKTsZPpd1iHkTf +CVn0W3cLN+mLIMb4Ck4uWBzrM9DPhmDJ2vuAL55MYIR4PSFk1vtBHxgP58l1cb29 +XN40hz5BsA72udY/CROWFC/emh1auVbONTqwX3BNXuMp8SMoclm2q8KMZiYcdywm +djWLKKdpoPk79SPdhRB0yZADVpHnr7pH1BKXESLjokmUbOe3lEu6LaTaM4tMpkT/ +WjzGHWTYtTHkpjx6qFcL2+1hGsvxznN3Y6SHb0xRONbkX8eftoEq5IVIeVheO/jb +AoJnwTnbw3RLPTYe+SmTiGhbqEQZIfCn6IENLOiTNrQ3ssqwGyZ6miUfmpqAnksq +P/ujmv5zMnHCnsZy4YpoJ/HkD7TETKVhk/iXEAcqMCWpuchxuO9ozC1+9eB+D4Ko +b7a6bINDd82Kkhehnlt4Fj1F4jNy3eFmypnTycUm/Q1oBEauttmbjL4ZvrHG8hnj +XALKLNhvSgfZyTXaQHXyxKcZb55CEJh15pWLYLztxRLXis7VmFxWlgPF7ncGNf/P +5O4/E2Hu29othfDNrp2yGAlFw5Khchf8R7agCyzxxN5DaAhqXzvwdmP7zAYspsbi +DrW5viSP +-----END CERTIFICATE----- + +# Issuer: CN=Hellenic Academic and Research Institutions RootCA 2015 O=Hellenic Academic and Research Institutions Cert. Authority +# Subject: CN=Hellenic Academic and Research Institutions RootCA 2015 O=Hellenic Academic and Research Institutions Cert. Authority +# Label: "Hellenic Academic and Research Institutions RootCA 2015" +# Serial: 0 +# MD5 Fingerprint: ca:ff:e2:db:03:d9:cb:4b:e9:0f:ad:84:fd:7b:18:ce +# SHA1 Fingerprint: 01:0c:06:95:a6:98:19:14:ff:bf:5f:c6:b0:b6:95:ea:29:e9:12:a6 +# SHA256 Fingerprint: a0:40:92:9a:02:ce:53:b4:ac:f4:f2:ff:c6:98:1c:e4:49:6f:75:5e:6d:45:fe:0b:2a:69:2b:cd:52:52:3f:36 +-----BEGIN CERTIFICATE----- +MIIGCzCCA/OgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBpjELMAkGA1UEBhMCR1Ix +DzANBgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5k +IFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMT +N0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9v +dENBIDIwMTUwHhcNMTUwNzA3MTAxMTIxWhcNNDAwNjMwMTAxMTIxWjCBpjELMAkG +A1UEBhMCR1IxDzANBgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNh +ZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkx +QDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1 +dGlvbnMgUm9vdENBIDIwMTUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC +AQDC+Kk/G4n8PDwEXT2QNrCROnk8ZlrvbTkBSRq0t89/TSNTt5AA4xMqKKYx8ZEA +4yjsriFBzh/a/X0SWwGDD7mwX5nh8hKDgE0GPt+sr+ehiGsxr/CL0BgzuNtFajT0 +AoAkKAoCFZVedioNmToUW/bLy1O8E00BiDeUJRtCvCLYjqOWXjrZMts+6PAQZe10 +4S+nfK8nNLspfZu2zwnI5dMK/IhlZXQK3HMcXM1AsRzUtoSMTFDPaI6oWa7CJ06C +ojXdFPQf/7J31Ycvqm59JCfnxssm5uX+Zwdj2EUN3TpZZTlYepKZcj2chF6IIbjV +9Cz82XBST3i4vTwri5WY9bPRaM8gFH5MXF/ni+X1NYEZN9cRCLdmvtNKzoNXADrD +gfgXy5I2XdGj2HUb4Ysn6npIQf1FGQatJ5lOwXBH3bWfgVMS5bGMSF0xQxfjjMZ6 +Y5ZLKTBOhE5iGV48zpeQpX8B653g+IuJ3SWYPZK2fu/Z8VFRfS0myGlZYeCsargq +NhEEelC9MoS+L9xy1dcdFkfkR2YgP/SWxa+OAXqlD3pk9Q0Yh9muiNX6hME6wGko +LfINaFGq46V3xqSQDqE3izEjR8EJCOtu93ib14L8hCCZSRm2Ekax+0VVFqmjZayc +Bw/qa9wfLgZy7IaIEuQt218FL+TwA9MmM+eAws1CoRc0CwIDAQABo0IwQDAPBgNV +HRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUcRVnyMjJvXVd +ctA4GGqd83EkVAswDQYJKoZIhvcNAQELBQADggIBAHW7bVRLqhBYRjTyYtcWNl0I +XtVsyIe9tC5G8jH4fOpCtZMWVdyhDBKg2mF+D1hYc2Ryx+hFjtyp8iY/xnmMsVMI +M4GwVhO+5lFc2JsKT0ucVlMC6U/2DWDqTUJV6HwbISHTGzrMd/K4kPFox/la/vot +9L/J9UUbzjgQKjeKeaO04wlshYaT/4mWJ3iBj2fjRnRUjtkNaeJK9E10A/+yd+2V +Z5fkscWrv2oj6NSU4kQoYsRL4vDY4ilrGnB+JGGTe08DMiUNRSQrlrRGar9KC/ea +j8GsGsVn82800vpzY4zvFrCopEYq+OsS7HK07/grfoxSwIuEVPkvPuNVqNxmsdnh +X9izjFk0WaSrT2y7HxjbdavYy5LNlDhhDgcGH0tGEPEVvo2FXDtKK4F5D7Rpn0lQ +l033DlZdwJVqwjbDG2jJ9SrcR5q+ss7FJej6A7na+RZukYT1HCjI/CbM1xyQVqdf +bzoEvM14iQuODy+jqk+iGxI9FghAD/FGTNeqewjBCvVtJ94Cj8rDtSvK6evIIVM4 +pcw72Hc3MKJP2W/R8kCtQXoXxdZKNYm3QdV8hn9VTYNKpXMgwDqvkPGaJI7ZjnHK +e7iG2rKPmT4dEw0SEe7Uq/DpFXYC5ODfqiAeW2GFZECpkJcNrVPSWh2HagCXZWK0 +vm9qp/UsQu0yrbYhnr68 +-----END CERTIFICATE----- + +# Issuer: CN=Hellenic Academic and Research Institutions ECC RootCA 2015 O=Hellenic Academic and Research Institutions Cert. Authority +# Subject: CN=Hellenic Academic and Research Institutions ECC RootCA 2015 O=Hellenic Academic and Research Institutions Cert. Authority +# Label: "Hellenic Academic and Research Institutions ECC RootCA 2015" +# Serial: 0 +# MD5 Fingerprint: 81:e5:b4:17:eb:c2:f5:e1:4b:0d:41:7b:49:92:fe:ef +# SHA1 Fingerprint: 9f:f1:71:8d:92:d5:9a:f3:7d:74:97:b4:bc:6f:84:68:0b:ba:b6:66 +# SHA256 Fingerprint: 44:b5:45:aa:8a:25:e6:5a:73:ca:15:dc:27:fc:36:d2:4c:1c:b9:95:3a:06:65:39:b1:15:82:dc:48:7b:48:33 +-----BEGIN CERTIFICATE----- +MIICwzCCAkqgAwIBAgIBADAKBggqhkjOPQQDAjCBqjELMAkGA1UEBhMCR1IxDzAN +BgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJl +c2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxRDBCBgNVBAMTO0hl +bGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgRUNDIFJv +b3RDQSAyMDE1MB4XDTE1MDcwNzEwMzcxMloXDTQwMDYzMDEwMzcxMlowgaoxCzAJ +BgNVBAYTAkdSMQ8wDQYDVQQHEwZBdGhlbnMxRDBCBgNVBAoTO0hlbGxlbmljIEFj +YWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9yaXR5 +MUQwQgYDVQQDEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0 +dXRpb25zIEVDQyBSb290Q0EgMjAxNTB2MBAGByqGSM49AgEGBSuBBAAiA2IABJKg +QehLgoRc4vgxEZmGZE4JJS+dQS8KrjVPdJWyUWRrjWvmP3CV8AVER6ZyOFB2lQJa +jq4onvktTpnvLEhvTCUp6NFxW98dwXU3tNf6e3pCnGoKVlp8aQuqgAkkbH7BRqNC +MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFLQi +C4KZJAEOnLvkDv2/+5cgk5kqMAoGCCqGSM49BAMCA2cAMGQCMGfOFmI4oqxiRaep +lSTAGiecMjvAwNW6qef4BENThe5SId6d9SWDPp5YSy/XZxMOIQIwBeF1Ad5o7Sof +TUwJCA3sS61kFyjndc5FZXIhF8siQQ6ME5g4mlRtm8rifOoCWCKR +-----END CERTIFICATE----- + +# Issuer: CN=ISRG Root X1 O=Internet Security Research Group +# Subject: CN=ISRG Root X1 O=Internet Security Research Group +# Label: "ISRG Root X1" +# Serial: 172886928669790476064670243504169061120 +# MD5 Fingerprint: 0c:d2:f9:e0:da:17:73:e9:ed:86:4d:a5:e3:70:e7:4e +# SHA1 Fingerprint: ca:bd:2a:79:a1:07:6a:31:f2:1d:25:36:35:cb:03:9d:43:29:a5:e8 +# SHA256 Fingerprint: 96:bc:ec:06:26:49:76:f3:74:60:77:9a:cf:28:c5:a7:cf:e8:a3:c0:aa:e1:1a:8f:fc:ee:05:c0:bd:df:08:c6 +-----BEGIN CERTIFICATE----- +MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw +TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh +cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4 +WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu +ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY +MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc +h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+ +0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U +A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW +T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH +B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC +B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv +KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn +OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn +jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw +qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI +rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV +HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq +hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL +ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ +3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK +NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5 +ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur +TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC +jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc +oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq +4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA +mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d +emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc= +-----END CERTIFICATE----- + +# Issuer: O=FNMT-RCM OU=AC RAIZ FNMT-RCM +# Subject: O=FNMT-RCM OU=AC RAIZ FNMT-RCM +# Label: "AC RAIZ FNMT-RCM" +# Serial: 485876308206448804701554682760554759 +# MD5 Fingerprint: e2:09:04:b4:d3:bd:d1:a0:14:fd:1a:d2:47:c4:57:1d +# SHA1 Fingerprint: ec:50:35:07:b2:15:c4:95:62:19:e2:a8:9a:5b:42:99:2c:4c:2c:20 +# SHA256 Fingerprint: eb:c5:57:0c:29:01:8c:4d:67:b1:aa:12:7b:af:12:f7:03:b4:61:1e:bc:17:b7:da:b5:57:38:94:17:9b:93:fa +-----BEGIN CERTIFICATE----- +MIIFgzCCA2ugAwIBAgIPXZONMGc2yAYdGsdUhGkHMA0GCSqGSIb3DQEBCwUAMDsx +CzAJBgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJ +WiBGTk1ULVJDTTAeFw0wODEwMjkxNTU5NTZaFw0zMDAxMDEwMDAwMDBaMDsxCzAJ +BgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJWiBG +Tk1ULVJDTTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALpxgHpMhm5/ +yBNtwMZ9HACXjywMI7sQmkCpGreHiPibVmr75nuOi5KOpyVdWRHbNi63URcfqQgf +BBckWKo3Shjf5TnUV/3XwSyRAZHiItQDwFj8d0fsjz50Q7qsNI1NOHZnjrDIbzAz +WHFctPVrbtQBULgTfmxKo0nRIBnuvMApGGWn3v7v3QqQIecaZ5JCEJhfTzC8PhxF +tBDXaEAUwED653cXeuYLj2VbPNmaUtu1vZ5Gzz3rkQUCwJaydkxNEJY7kvqcfw+Z +374jNUUeAlz+taibmSXaXvMiwzn15Cou08YfxGyqxRxqAQVKL9LFwag0Jl1mpdIC +IfkYtwb1TplvqKtMUejPUBjFd8g5CSxJkjKZqLsXF3mwWsXmo8RZZUc1g16p6DUL +mbvkzSDGm0oGObVo/CK67lWMK07q87Hj/LaZmtVC+nFNCM+HHmpxffnTtOmlcYF7 +wk5HlqX2doWjKI/pgG6BU6VtX7hI+cL5NqYuSf+4lsKMB7ObiFj86xsc3i1w4peS +MKGJ47xVqCfWS+2QrYv6YyVZLag13cqXM7zlzced0ezvXg5KkAYmY6252TUtB7p2 +ZSysV4999AeU14ECll2jB0nVetBX+RvnU0Z1qrB5QstocQjpYL05ac70r8NWQMet +UqIJ5G+GR4of6ygnXYMgrwTJbFaai0b1AgMBAAGjgYMwgYAwDwYDVR0TAQH/BAUw +AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFPd9xf3E6Jobd2Sn9R2gzL+H +YJptMD4GA1UdIAQ3MDUwMwYEVR0gADArMCkGCCsGAQUFBwIBFh1odHRwOi8vd3d3 +LmNlcnQuZm5tdC5lcy9kcGNzLzANBgkqhkiG9w0BAQsFAAOCAgEAB5BK3/MjTvDD +nFFlm5wioooMhfNzKWtN/gHiqQxjAb8EZ6WdmF/9ARP67Jpi6Yb+tmLSbkyU+8B1 +RXxlDPiyN8+sD8+Nb/kZ94/sHvJwnvDKuO+3/3Y3dlv2bojzr2IyIpMNOmqOFGYM +LVN0V2Ue1bLdI4E7pWYjJ2cJj+F3qkPNZVEI7VFY/uY5+ctHhKQV8Xa7pO6kO8Rf +77IzlhEYt8llvhjho6Tc+hj507wTmzl6NLrTQfv6MooqtyuGC2mDOL7Nii4LcK2N +JpLuHvUBKwrZ1pebbuCoGRw6IYsMHkCtA+fdZn71uSANA+iW+YJF1DngoABd15jm +fZ5nc8OaKveri6E6FO80vFIOiZiaBECEHX5FaZNXzuvO+FB8TxxuBEOb+dY7Ixjp +6o7RTUaN8Tvkasq6+yO3m/qZASlaWFot4/nUbQ4mrcFuNLwy+AwF+mWj2zs3gyLp +1txyM/1d8iC9djwj2ij3+RvrWWTV3F9yfiD8zYm1kGdNYno/Tq0dwzn+evQoFt9B +9kiABdcPUXmsEKvU7ANm5mqwujGSQkBqvjrTcuFqN1W8rB2Vt2lh8kORdOag0wok +RqEIr9baRRmW1FMdW4R58MD3R++Lj8UGrp1MYp3/RgT408m2ECVAdf4WqslKYIYv +uu8wd+RU4riEmViAqhOLUTpPSPaLtrM= +-----END CERTIFICATE----- + +# Issuer: CN=Amazon Root CA 1 O=Amazon +# Subject: CN=Amazon Root CA 1 O=Amazon +# Label: "Amazon Root CA 1" +# Serial: 143266978916655856878034712317230054538369994 +# MD5 Fingerprint: 43:c6:bf:ae:ec:fe:ad:2f:18:c6:88:68:30:fc:c8:e6 +# SHA1 Fingerprint: 8d:a7:f9:65:ec:5e:fc:37:91:0f:1c:6e:59:fd:c1:cc:6a:6e:de:16 +# SHA256 Fingerprint: 8e:cd:e6:88:4f:3d:87:b1:12:5b:a3:1a:c3:fc:b1:3d:70:16:de:7f:57:cc:90:4f:e1:cb:97:c6:ae:98:19:6e +-----BEGIN CERTIFICATE----- +MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF +ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6 +b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL +MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv +b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj +ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM +9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw +IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6 +VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L +93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm +jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA +A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI +U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs +N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv +o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU +5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy +rqXRfboQnoZsG4q5WTP468SQvvG5 +-----END CERTIFICATE----- + +# Issuer: CN=Amazon Root CA 2 O=Amazon +# Subject: CN=Amazon Root CA 2 O=Amazon +# Label: "Amazon Root CA 2" +# Serial: 143266982885963551818349160658925006970653239 +# MD5 Fingerprint: c8:e5:8d:ce:a8:42:e2:7a:c0:2a:5c:7c:9e:26:bf:66 +# SHA1 Fingerprint: 5a:8c:ef:45:d7:a6:98:59:76:7a:8c:8b:44:96:b5:78:cf:47:4b:1a +# SHA256 Fingerprint: 1b:a5:b2:aa:8c:65:40:1a:82:96:01:18:f8:0b:ec:4f:62:30:4d:83:ce:c4:71:3a:19:c3:9c:01:1e:a4:6d:b4 +-----BEGIN CERTIFICATE----- +MIIFQTCCAymgAwIBAgITBmyf0pY1hp8KD+WGePhbJruKNzANBgkqhkiG9w0BAQwF +ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6 +b24gUm9vdCBDQSAyMB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTEL +MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv +b3QgQ0EgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK2Wny2cSkxK +gXlRmeyKy2tgURO8TW0G/LAIjd0ZEGrHJgw12MBvIITplLGbhQPDW9tK6Mj4kHbZ +W0/jTOgGNk3Mmqw9DJArktQGGWCsN0R5hYGCrVo34A3MnaZMUnbqQ523BNFQ9lXg +1dKmSYXpN+nKfq5clU1Imj+uIFptiJXZNLhSGkOQsL9sBbm2eLfq0OQ6PBJTYv9K +8nu+NQWpEjTj82R0Yiw9AElaKP4yRLuH3WUnAnE72kr3H9rN9yFVkE8P7K6C4Z9r +2UXTu/Bfh+08LDmG2j/e7HJV63mjrdvdfLC6HM783k81ds8P+HgfajZRRidhW+me +z/CiVX18JYpvL7TFz4QuK/0NURBs+18bvBt+xa47mAExkv8LV/SasrlX6avvDXbR +8O70zoan4G7ptGmh32n2M8ZpLpcTnqWHsFcQgTfJU7O7f/aS0ZzQGPSSbtqDT6Zj +mUyl+17vIWR6IF9sZIUVyzfpYgwLKhbcAS4y2j5L9Z469hdAlO+ekQiG+r5jqFoz +7Mt0Q5X5bGlSNscpb/xVA1wf+5+9R+vnSUeVC06JIglJ4PVhHvG/LopyboBZ/1c6 ++XUyo05f7O0oYtlNc/LMgRdg7c3r3NunysV+Ar3yVAhU/bQtCSwXVEqY0VThUWcI +0u1ufm8/0i2BWSlmy5A5lREedCf+3euvAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMB +Af8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSwDPBMMPQFWAJI/TPlUq9LhONm +UjANBgkqhkiG9w0BAQwFAAOCAgEAqqiAjw54o+Ci1M3m9Zh6O+oAA7CXDpO8Wqj2 +LIxyh6mx/H9z/WNxeKWHWc8w4Q0QshNabYL1auaAn6AFC2jkR2vHat+2/XcycuUY ++gn0oJMsXdKMdYV2ZZAMA3m3MSNjrXiDCYZohMr/+c8mmpJ5581LxedhpxfL86kS +k5Nrp+gvU5LEYFiwzAJRGFuFjWJZY7attN6a+yb3ACfAXVU3dJnJUH/jWS5E4ywl +7uxMMne0nxrpS10gxdr9HIcWxkPo1LsmmkVwXqkLN1PiRnsn/eBG8om3zEK2yygm +btmlyTrIQRNg91CMFa6ybRoVGld45pIq2WWQgj9sAq+uEjonljYE1x2igGOpm/Hl +urR8FLBOybEfdF849lHqm/osohHUqS0nGkWxr7JOcQ3AWEbWaQbLU8uz/mtBzUF+ +fUwPfHJ5elnNXkoOrJupmHN5fLT0zLm4BwyydFy4x2+IoZCn9Kr5v2c69BoVYh63 +n749sSmvZ6ES8lgQGVMDMBu4Gon2nL2XA46jCfMdiyHxtN/kHNGfZQIG6lzWE7OE +76KlXIx3KadowGuuQNKotOrN8I1LOJwZmhsoVLiJkO/KdYE+HvJkJMcYr07/R54H +9jVlpNMKVv/1F2Rs76giJUmTtt8AF9pYfl3uxRuw0dFfIRDH+fO6AgonB8Xx1sfT +4PsJYGw= +-----END CERTIFICATE----- + +# Issuer: CN=Amazon Root CA 3 O=Amazon +# Subject: CN=Amazon Root CA 3 O=Amazon +# Label: "Amazon Root CA 3" +# Serial: 143266986699090766294700635381230934788665930 +# MD5 Fingerprint: a0:d4:ef:0b:f7:b5:d8:49:95:2a:ec:f5:c4:fc:81:87 +# SHA1 Fingerprint: 0d:44:dd:8c:3c:8c:1a:1a:58:75:64:81:e9:0f:2e:2a:ff:b3:d2:6e +# SHA256 Fingerprint: 18:ce:6c:fe:7b:f1:4e:60:b2:e3:47:b8:df:e8:68:cb:31:d0:2e:bb:3a:da:27:15:69:f5:03:43:b4:6d:b3:a4 +-----BEGIN CERTIFICATE----- +MIIBtjCCAVugAwIBAgITBmyf1XSXNmY/Owua2eiedgPySjAKBggqhkjOPQQDAjA5 +MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g +Um9vdCBDQSAzMB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG +A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg +Q0EgMzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCmXp8ZBf8ANm+gBG1bG8lKl +ui2yEujSLtf6ycXYqm0fc4E7O5hrOXwzpcVOho6AF2hiRVd9RFgdszflZwjrZt6j +QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSr +ttvXBp43rDCGB5Fwx5zEGbF4wDAKBggqhkjOPQQDAgNJADBGAiEA4IWSoxe3jfkr +BqWTrBqYaGFy+uGh0PsceGCmQ5nFuMQCIQCcAu/xlJyzlvnrxir4tiz+OpAUFteM +YyRIHN8wfdVoOw== +-----END CERTIFICATE----- + +# Issuer: CN=Amazon Root CA 4 O=Amazon +# Subject: CN=Amazon Root CA 4 O=Amazon +# Label: "Amazon Root CA 4" +# Serial: 143266989758080763974105200630763877849284878 +# MD5 Fingerprint: 89:bc:27:d5:eb:17:8d:06:6a:69:d5:fd:89:47:b4:cd +# SHA1 Fingerprint: f6:10:84:07:d6:f8:bb:67:98:0c:c2:e2:44:c2:eb:ae:1c:ef:63:be +# SHA256 Fingerprint: e3:5d:28:41:9e:d0:20:25:cf:a6:90:38:cd:62:39:62:45:8d:a5:c6:95:fb:de:a3:c2:2b:0b:fb:25:89:70:92 +-----BEGIN CERTIFICATE----- +MIIB8jCCAXigAwIBAgITBmyf18G7EEwpQ+Vxe3ssyBrBDjAKBggqhkjOPQQDAzA5 +MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g +Um9vdCBDQSA0MB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG +A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg +Q0EgNDB2MBAGByqGSM49AgEGBSuBBAAiA2IABNKrijdPo1MN/sGKe0uoe0ZLY7Bi +9i0b2whxIdIA6GO9mif78DluXeo9pcmBqqNbIJhFXRbb/egQbeOc4OO9X4Ri83Bk +M6DLJC9wuoihKqB1+IGuYgbEgds5bimwHvouXKNCMEAwDwYDVR0TAQH/BAUwAwEB +/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFNPsxzplbszh2naaVvuc84ZtV+WB +MAoGCCqGSM49BAMDA2gAMGUCMDqLIfG9fhGt0O9Yli/W651+kI0rz2ZVwyzjKKlw +CkcO8DdZEv8tmZQoTipPNU0zWgIxAOp1AE47xDqUEpHJWEadIRNyp4iciuRMStuW +1KyLa2tJElMzrdfkviT8tQp21KW8EA== +-----END CERTIFICATE----- + +# Issuer: CN=TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1 O=Turkiye Bilimsel ve Teknolojik Arastirma Kurumu - TUBITAK OU=Kamu Sertifikasyon Merkezi - Kamu SM +# Subject: CN=TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1 O=Turkiye Bilimsel ve Teknolojik Arastirma Kurumu - TUBITAK OU=Kamu Sertifikasyon Merkezi - Kamu SM +# Label: "TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1" +# Serial: 1 +# MD5 Fingerprint: dc:00:81:dc:69:2f:3e:2f:b0:3b:f6:3d:5a:91:8e:49 +# SHA1 Fingerprint: 31:43:64:9b:ec:ce:27:ec:ed:3a:3f:0b:8f:0d:e4:e8:91:dd:ee:ca +# SHA256 Fingerprint: 46:ed:c3:68:90:46:d5:3a:45:3f:b3:10:4a:b8:0d:ca:ec:65:8b:26:60:ea:16:29:dd:7e:86:79:90:64:87:16 +-----BEGIN CERTIFICATE----- +MIIEYzCCA0ugAwIBAgIBATANBgkqhkiG9w0BAQsFADCB0jELMAkGA1UEBhMCVFIx +GDAWBgNVBAcTD0dlYnplIC0gS29jYWVsaTFCMEAGA1UEChM5VHVya2l5ZSBCaWxp +bXNlbCB2ZSBUZWtub2xvamlrIEFyYXN0aXJtYSBLdXJ1bXUgLSBUVUJJVEFLMS0w +KwYDVQQLEyRLYW11IFNlcnRpZmlrYXN5b24gTWVya2V6aSAtIEthbXUgU00xNjA0 +BgNVBAMTLVRVQklUQUsgS2FtdSBTTSBTU0wgS29rIFNlcnRpZmlrYXNpIC0gU3Vy +dW0gMTAeFw0xMzExMjUwODI1NTVaFw00MzEwMjUwODI1NTVaMIHSMQswCQYDVQQG +EwJUUjEYMBYGA1UEBxMPR2ViemUgLSBLb2NhZWxpMUIwQAYDVQQKEzlUdXJraXll +IEJpbGltc2VsIHZlIFRla25vbG9qaWsgQXJhc3Rpcm1hIEt1cnVtdSAtIFRVQklU +QUsxLTArBgNVBAsTJEthbXUgU2VydGlmaWthc3lvbiBNZXJrZXppIC0gS2FtdSBT +TTE2MDQGA1UEAxMtVFVCSVRBSyBLYW11IFNNIFNTTCBLb2sgU2VydGlmaWthc2kg +LSBTdXJ1bSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr3UwM6q7 +a9OZLBI3hNmNe5eA027n/5tQlT6QlVZC1xl8JoSNkvoBHToP4mQ4t4y86Ij5iySr +LqP1N+RAjhgleYN1Hzv/bKjFxlb4tO2KRKOrbEz8HdDc72i9z+SqzvBV96I01INr +N3wcwv61A+xXzry0tcXtAA9TNypN9E8Mg/uGz8v+jE69h/mniyFXnHrfA2eJLJ2X +YacQuFWQfw4tJzh03+f92k4S400VIgLI4OD8D62K18lUUMw7D8oWgITQUVbDjlZ/ +iSIzL+aFCr2lqBs23tPcLG07xxO9WSMs5uWk99gL7eqQQESolbuT1dCANLZGeA4f +AJNG4e7p+exPFwIDAQABo0IwQDAdBgNVHQ4EFgQUZT/HiobGPN08VFw1+DrtUgxH +V8gwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL +BQADggEBACo/4fEyjq7hmFxLXs9rHmoJ0iKpEsdeV31zVmSAhHqT5Am5EM2fKifh +AHe+SMg1qIGf5LgsyX8OsNJLN13qudULXjS99HMpw+0mFZx+CFOKWI3QSyjfwbPf +IPP54+M638yclNhOT8NrF7f3cuitZjO1JVOr4PhMqZ398g26rrnZqsZr+ZO7rqu4 +lzwDGrpDxpa5RXI4s6ehlj2Re37AIVNMh+3yC1SVUZPVIqUNivGTDj5UDrDYyU7c +8jEyVupk+eq1nRZmQnLzf9OxMUP8pI4X8W0jq5Rm+K37DwhuJi1/FwcJsoz7UMCf +lo3Ptv0AnVoUmr8CRPXBwp8iXqIPoeM= +-----END CERTIFICATE----- + +# Issuer: CN=GDCA TrustAUTH R5 ROOT O=GUANG DONG CERTIFICATE AUTHORITY CO.,LTD. +# Subject: CN=GDCA TrustAUTH R5 ROOT O=GUANG DONG CERTIFICATE AUTHORITY CO.,LTD. +# Label: "GDCA TrustAUTH R5 ROOT" +# Serial: 9009899650740120186 +# MD5 Fingerprint: 63:cc:d9:3d:34:35:5c:6f:53:a3:e2:08:70:48:1f:b4 +# SHA1 Fingerprint: 0f:36:38:5b:81:1a:25:c3:9b:31:4e:83:ca:e9:34:66:70:cc:74:b4 +# SHA256 Fingerprint: bf:ff:8f:d0:44:33:48:7d:6a:8a:a6:0c:1a:29:76:7a:9f:c2:bb:b0:5e:42:0f:71:3a:13:b9:92:89:1d:38:93 +-----BEGIN CERTIFICATE----- +MIIFiDCCA3CgAwIBAgIIfQmX/vBH6nowDQYJKoZIhvcNAQELBQAwYjELMAkGA1UE +BhMCQ04xMjAwBgNVBAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZ +IENPLixMVEQuMR8wHQYDVQQDDBZHRENBIFRydXN0QVVUSCBSNSBST09UMB4XDTE0 +MTEyNjA1MTMxNVoXDTQwMTIzMTE1NTk1OVowYjELMAkGA1UEBhMCQ04xMjAwBgNV +BAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZIENPLixMVEQuMR8w +HQYDVQQDDBZHRENBIFRydXN0QVVUSCBSNSBST09UMIICIjANBgkqhkiG9w0BAQEF +AAOCAg8AMIICCgKCAgEA2aMW8Mh0dHeb7zMNOwZ+Vfy1YI92hhJCfVZmPoiC7XJj +Dp6L3TQsAlFRwxn9WVSEyfFrs0yw6ehGXTjGoqcuEVe6ghWinI9tsJlKCvLriXBj +TnnEt1u9ol2x8kECK62pOqPseQrsXzrj/e+APK00mxqriCZ7VqKChh/rNYmDf1+u +KU49tm7srsHwJ5uu4/Ts765/94Y9cnrrpftZTqfrlYwiOXnhLQiPzLyRuEH3FMEj +qcOtmkVEs7LXLM3GKeJQEK5cy4KOFxg2fZfmiJqwTTQJ9Cy5WmYqsBebnh52nUpm +MUHfP/vFBu8btn4aRjb3ZGM74zkYI+dndRTVdVeSN72+ahsmUPI2JgaQxXABZG12 +ZuGR224HwGGALrIuL4xwp9E7PLOR5G62xDtw8mySlwnNR30YwPO7ng/Wi64HtloP +zgsMR6flPri9fcebNaBhlzpBdRfMK5Z3KpIhHtmVdiBnaM8Nvd/WHwlqmuLMc3Gk +L30SgLdTMEZeS1SZD2fJpcjyIMGC7J0R38IC+xo70e0gmu9lZJIQDSri3nDxGGeC +jGHeuLzRL5z7D9Ar7Rt2ueQ5Vfj4oR24qoAATILnsn8JuLwwoC8N9VKejveSswoA +HQBUlwbgsQfZxw9cZX08bVlX5O2ljelAU58VS6Bx9hoh49pwBiFYFIeFd3mqgnkC +AwEAAaNCMEAwHQYDVR0OBBYEFOLJQJ9NzuiaoXzPDj9lxSmIahlRMA8GA1UdEwEB +/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQDRSVfg +p8xoWLoBDysZzY2wYUWsEe1jUGn4H3++Fo/9nesLqjJHdtJnJO29fDMylyrHBYZm +DRd9FBUb1Ov9H5r2XpdptxolpAqzkT9fNqyL7FeoPueBihhXOYV0GkLH6VsTX4/5 +COmSdI31R9KrO9b7eGZONn356ZLpBN79SWP8bfsUcZNnL0dKt7n/HipzcEYwv1ry +L3ml4Y0M2fmyYzeMN2WFcGpcWwlyua1jPLHd+PwyvzeG5LuOmCd+uh8W4XAR8gPf +JWIyJyYYMoSf/wA6E7qaTfRPuBRwIrHKK5DOKcFw9C+df/KQHtZa37dG/OaG+svg +IHZ6uqbL9XzeYqWxi+7egmaKTjowHz+Ay60nugxe19CxVsp3cbK1daFQqUBDF8Io +2c9Si1vIY9RCPqAzekYu9wogRlR+ak8x8YF+QnQ4ZXMn7sZ8uI7XpTrXmKGcjBBV +09tL7ECQ8s1uV9JiDnxXk7Gnbc2dg7sq5+W2O3FYrf3RRbxake5TFW/TRQl1brqQ +XR4EzzffHqhmsYzmIGrv/EhOdJhCrylvLmrH+33RZjEizIYAfmaDDEL0vTSSwxrq +T8p+ck0LcIymSLumoRT2+1hEmRSuqguTaaApJUqlyyvdimYHFngVV3Eb7PVHhPOe +MTd61X8kreS8/f3MboPoDKi3QWwH3b08hpcv0g== +-----END CERTIFICATE----- + +# Issuer: CN=TrustCor RootCert CA-1 O=TrustCor Systems S. de R.L. OU=TrustCor Certificate Authority +# Subject: CN=TrustCor RootCert CA-1 O=TrustCor Systems S. de R.L. OU=TrustCor Certificate Authority +# Label: "TrustCor RootCert CA-1" +# Serial: 15752444095811006489 +# MD5 Fingerprint: 6e:85:f1:dc:1a:00:d3:22:d5:b2:b2:ac:6b:37:05:45 +# SHA1 Fingerprint: ff:bd:cd:e7:82:c8:43:5e:3c:6f:26:86:5c:ca:a8:3a:45:5b:c3:0a +# SHA256 Fingerprint: d4:0e:9c:86:cd:8f:e4:68:c1:77:69:59:f4:9e:a7:74:fa:54:86:84:b6:c4:06:f3:90:92:61:f4:dc:e2:57:5c +-----BEGIN CERTIFICATE----- +MIIEMDCCAxigAwIBAgIJANqb7HHzA7AZMA0GCSqGSIb3DQEBCwUAMIGkMQswCQYD +VQQGEwJQQTEPMA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEgQ2l0eTEk +MCIGA1UECgwbVHJ1c3RDb3IgU3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5U +cnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxHzAdBgNVBAMMFlRydXN0Q29y +IFJvb3RDZXJ0IENBLTEwHhcNMTYwMjA0MTIzMjE2WhcNMjkxMjMxMTcyMzE2WjCB +pDELMAkGA1UEBhMCUEExDzANBgNVBAgMBlBhbmFtYTEUMBIGA1UEBwwLUGFuYW1h +IENpdHkxJDAiBgNVBAoMG1RydXN0Q29yIFN5c3RlbXMgUy4gZGUgUi5MLjEnMCUG +A1UECwweVHJ1c3RDb3IgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MR8wHQYDVQQDDBZU +cnVzdENvciBSb290Q2VydCBDQS0xMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEAv463leLCJhJrMxnHQFgKq1mqjQCj/IDHUHuO1CAmujIS2CNUSSUQIpid +RtLByZ5OGy4sDjjzGiVoHKZaBeYei0i/mJZ0PmnK6bV4pQa81QBeCQryJ3pS/C3V +seq0iWEk8xoT26nPUu0MJLq5nux+AHT6k61sKZKuUbS701e/s/OojZz0JEsq1pme +9J7+wH5COucLlVPat2gOkEz7cD+PSiyU8ybdY2mplNgQTsVHCJCZGxdNuWxu72CV +EY4hgLW9oHPY0LJ3xEXqWib7ZnZ2+AYfYW0PVcWDtxBWcgYHpfOxGgMFZA6dWorW +hnAbJN7+KIor0Gqw/Hqi3LJ5DotlDwIDAQABo2MwYTAdBgNVHQ4EFgQU7mtJPHo/ +DeOxCbeKyKsZn3MzUOcwHwYDVR0jBBgwFoAU7mtJPHo/DeOxCbeKyKsZn3MzUOcw +DwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQELBQAD +ggEBACUY1JGPE+6PHh0RU9otRCkZoB5rMZ5NDp6tPVxBb5UrJKF5mDo4Nvu7Zp5I +/5CQ7z3UuJu0h3U/IJvOcs+hVcFNZKIZBqEHMwwLKeXx6quj7LUKdJDHfXLy11yf +ke+Ri7fc7Waiz45mO7yfOgLgJ90WmMCV1Aqk5IGadZQ1nJBfiDcGrVmVCrDRZ9MZ +yonnMlo2HD6CqFqTvsbQZJG2z9m2GM/bftJlo6bEjhcxwft+dtvTheNYsnd6djts +L1Ac59v2Z3kf9YKVmgenFK+P3CghZwnS1k1aHBkcjndcw5QkPTJrS37UeJSDvjdN +zl/HHk484IkzlQsPpTLWPFp5LBk= +-----END CERTIFICATE----- + +# Issuer: CN=TrustCor RootCert CA-2 O=TrustCor Systems S. de R.L. OU=TrustCor Certificate Authority +# Subject: CN=TrustCor RootCert CA-2 O=TrustCor Systems S. de R.L. OU=TrustCor Certificate Authority +# Label: "TrustCor RootCert CA-2" +# Serial: 2711694510199101698 +# MD5 Fingerprint: a2:e1:f8:18:0b:ba:45:d5:c7:41:2a:bb:37:52:45:64 +# SHA1 Fingerprint: b8:be:6d:cb:56:f1:55:b9:63:d4:12:ca:4e:06:34:c7:94:b2:1c:c0 +# SHA256 Fingerprint: 07:53:e9:40:37:8c:1b:d5:e3:83:6e:39:5d:ae:a5:cb:83:9e:50:46:f1:bd:0e:ae:19:51:cf:10:fe:c7:c9:65 +-----BEGIN CERTIFICATE----- +MIIGLzCCBBegAwIBAgIIJaHfyjPLWQIwDQYJKoZIhvcNAQELBQAwgaQxCzAJBgNV +BAYTAlBBMQ8wDQYDVQQIDAZQYW5hbWExFDASBgNVBAcMC1BhbmFtYSBDaXR5MSQw +IgYDVQQKDBtUcnVzdENvciBTeXN0ZW1zIFMuIGRlIFIuTC4xJzAlBgNVBAsMHlRy +dXN0Q29yIENlcnRpZmljYXRlIEF1dGhvcml0eTEfMB0GA1UEAwwWVHJ1c3RDb3Ig +Um9vdENlcnQgQ0EtMjAeFw0xNjAyMDQxMjMyMjNaFw0zNDEyMzExNzI2MzlaMIGk +MQswCQYDVQQGEwJQQTEPMA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEg +Q2l0eTEkMCIGA1UECgwbVHJ1c3RDb3IgU3lzdGVtcyBTLiBkZSBSLkwuMScwJQYD +VQQLDB5UcnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxHzAdBgNVBAMMFlRy +dXN0Q29yIFJvb3RDZXJ0IENBLTIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK +AoICAQCnIG7CKqJiJJWQdsg4foDSq8GbZQWU9MEKENUCrO2fk8eHyLAnK0IMPQo+ +QVqedd2NyuCb7GgypGmSaIwLgQ5WoD4a3SwlFIIvl9NkRvRUqdw6VC0xK5mC8tkq +1+9xALgxpL56JAfDQiDyitSSBBtlVkxs1Pu2YVpHI7TYabS3OtB0PAx1oYxOdqHp +2yqlO/rOsP9+aij9JxzIsekp8VduZLTQwRVtDr4uDkbIXvRR/u8OYzo7cbrPb1nK +DOObXUm4TOJXsZiKQlecdu/vvdFoqNL0Cbt3Nb4lggjEFixEIFapRBF37120Hape +az6LMvYHL1cEksr1/p3C6eizjkxLAjHZ5DxIgif3GIJ2SDpxsROhOdUuxTTCHWKF +3wP+TfSvPd9cW436cOGlfifHhi5qjxLGhF5DUVCcGZt45vz27Ud+ez1m7xMTiF88 +oWP7+ayHNZ/zgp6kPwqcMWmLmaSISo5uZk3vFsQPeSghYA2FFn3XVDjxklb9tTNM +g9zXEJ9L/cb4Qr26fHMC4P99zVvh1Kxhe1fVSntb1IVYJ12/+CtgrKAmrhQhJ8Z3 +mjOAPF5GP/fDsaOGM8boXg25NSyqRsGFAnWAoOsk+xWq5Gd/bnc/9ASKL3x74xdh +8N0JqSDIvgmk0H5Ew7IwSjiqqewYmgeCK9u4nBit2uBGF6zPXQIDAQABo2MwYTAd +BgNVHQ4EFgQU2f4hQG6UnrybPZx9mCAZ5YwwYrIwHwYDVR0jBBgwFoAU2f4hQG6U +nrybPZx9mCAZ5YwwYrIwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYw +DQYJKoZIhvcNAQELBQADggIBAJ5Fngw7tu/hOsh80QA9z+LqBrWyOrsGS2h60COX +dKcs8AjYeVrXWoSK2BKaG9l9XE1wxaX5q+WjiYndAfrs3fnpkpfbsEZC89NiqpX+ +MWcUaViQCqoL7jcjx1BRtPV+nuN79+TMQjItSQzL/0kMmx40/W5ulop5A7Zv2wnL +/V9lFDfhOPXzYRZY5LVtDQsEGz9QLX+zx3oaFoBg+Iof6Rsqxvm6ARppv9JYx1RX +CI/hOWB3S6xZhBqI8d3LT3jX5+EzLfzuQfogsL7L9ziUwOHQhQ+77Sxzq+3+knYa +ZH9bDTMJBzN7Bj8RpFxwPIXAz+OQqIN3+tvmxYxoZxBnpVIt8MSZj3+/0WvitUfW +2dCFmU2Umw9Lje4AWkcdEQOsQRivh7dvDDqPys/cA8GiCcjl/YBeyGBCARsaU1q7 +N6a3vLqE6R5sGtRk2tRD/pOLS/IseRYQ1JMLiI+h2IYURpFHmygk71dSTlxCnKr3 +Sewn6EAes6aJInKc9Q0ztFijMDvd1GpUk74aTfOTlPf8hAs/hCBcNANExdqtvArB +As8e5ZTZ845b2EzwnexhF7sUMlQMAimTHpKG9n/v55IFDlndmQguLvqcAFLTxWYp +5KeXRKQOKIETNcX2b2TmQcTVL8w0RSXPQQCWPUouwpaYT05KnJe32x+SMsj/D1Fu +1uwJ +-----END CERTIFICATE----- + +# Issuer: CN=TrustCor ECA-1 O=TrustCor Systems S. de R.L. OU=TrustCor Certificate Authority +# Subject: CN=TrustCor ECA-1 O=TrustCor Systems S. de R.L. OU=TrustCor Certificate Authority +# Label: "TrustCor ECA-1" +# Serial: 9548242946988625984 +# MD5 Fingerprint: 27:92:23:1d:0a:f5:40:7c:e9:e6:6b:9d:d8:f5:e7:6c +# SHA1 Fingerprint: 58:d1:df:95:95:67:6b:63:c0:f0:5b:1c:17:4d:8b:84:0b:c8:78:bd +# SHA256 Fingerprint: 5a:88:5d:b1:9c:01:d9:12:c5:75:93:88:93:8c:af:bb:df:03:1a:b2:d4:8e:91:ee:15:58:9b:42:97:1d:03:9c +-----BEGIN CERTIFICATE----- +MIIEIDCCAwigAwIBAgIJAISCLF8cYtBAMA0GCSqGSIb3DQEBCwUAMIGcMQswCQYD +VQQGEwJQQTEPMA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEgQ2l0eTEk +MCIGA1UECgwbVHJ1c3RDb3IgU3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5U +cnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxFzAVBgNVBAMMDlRydXN0Q29y +IEVDQS0xMB4XDTE2MDIwNDEyMzIzM1oXDTI5MTIzMTE3MjgwN1owgZwxCzAJBgNV +BAYTAlBBMQ8wDQYDVQQIDAZQYW5hbWExFDASBgNVBAcMC1BhbmFtYSBDaXR5MSQw +IgYDVQQKDBtUcnVzdENvciBTeXN0ZW1zIFMuIGRlIFIuTC4xJzAlBgNVBAsMHlRy +dXN0Q29yIENlcnRpZmljYXRlIEF1dGhvcml0eTEXMBUGA1UEAwwOVHJ1c3RDb3Ig +RUNBLTEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDPj+ARtZ+odnbb +3w9U73NjKYKtR8aja+3+XzP4Q1HpGjORMRegdMTUpwHmspI+ap3tDvl0mEDTPwOA +BoJA6LHip1GnHYMma6ve+heRK9jGrB6xnhkB1Zem6g23xFUfJ3zSCNV2HykVh0A5 +3ThFEXXQmqc04L/NyFIduUd+Dbi7xgz2c1cWWn5DkR9VOsZtRASqnKmcp0yJF4Ou +owReUoCLHhIlERnXDH19MURB6tuvsBzvgdAsxZohmz3tQjtQJvLsznFhBmIhVE5/ +wZ0+fyCMgMsq2JdiyIMzkX2woloPV+g7zPIlstR8L+xNxqE6FXrntl019fZISjZF +ZtS6mFjBAgMBAAGjYzBhMB0GA1UdDgQWBBREnkj1zG1I1KBLf/5ZJC+Dl5mahjAf +BgNVHSMEGDAWgBREnkj1zG1I1KBLf/5ZJC+Dl5mahjAPBgNVHRMBAf8EBTADAQH/ +MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAQEABT41XBVwm8nHc2Fv +civUwo/yQ10CzsSUuZQRg2dd4mdsdXa/uwyqNsatR5Nj3B5+1t4u/ukZMjgDfxT2 +AHMsWbEhBuH7rBiVDKP/mZb3Kyeb1STMHd3BOuCYRLDE5D53sXOpZCz2HAF8P11F +hcCF5yWPldwX8zyfGm6wyuMdKulMY/okYWLW2n62HGz1Ah3UKt1VkOsqEUc8Ll50 +soIipX1TH0XsJ5F95yIW6MBoNtjG8U+ARDL54dHRHareqKucBK+tIA5kmE2la8BI +WJZpTdwHjFGTot+fDz2LYLSCjaoITmJF4PkL0uDgPFveXHEnJcLmA4GLEFPjx1Wi +tJ/X5g== +-----END CERTIFICATE----- + +# Issuer: CN=SSL.com Root Certification Authority RSA O=SSL Corporation +# Subject: CN=SSL.com Root Certification Authority RSA O=SSL Corporation +# Label: "SSL.com Root Certification Authority RSA" +# Serial: 8875640296558310041 +# MD5 Fingerprint: 86:69:12:c0:70:f1:ec:ac:ac:c2:d5:bc:a5:5b:a1:29 +# SHA1 Fingerprint: b7:ab:33:08:d1:ea:44:77:ba:14:80:12:5a:6f:bd:a9:36:49:0c:bb +# SHA256 Fingerprint: 85:66:6a:56:2e:e0:be:5c:e9:25:c1:d8:89:0a:6f:76:a8:7e:c1:6d:4d:7d:5f:29:ea:74:19:cf:20:12:3b:69 +-----BEGIN CERTIFICATE----- +MIIF3TCCA8WgAwIBAgIIeyyb0xaAMpkwDQYJKoZIhvcNAQELBQAwfDELMAkGA1UE +BhMCVVMxDjAMBgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQK +DA9TU0wgQ29ycG9yYXRpb24xMTAvBgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZp +Y2F0aW9uIEF1dGhvcml0eSBSU0EwHhcNMTYwMjEyMTczOTM5WhcNNDEwMjEyMTcz +OTM5WjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hv +dXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NMLmNv +bSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFJTQTCCAiIwDQYJKoZIhvcN +AQEBBQADggIPADCCAgoCggIBAPkP3aMrfcvQKv7sZ4Wm5y4bunfh4/WvpOz6Sl2R +xFdHaxh3a3by/ZPkPQ/CFp4LZsNWlJ4Xg4XOVu/yFv0AYvUiCVToZRdOQbngT0aX +qhvIuG5iXmmxX9sqAn78bMrzQdjt0Oj8P2FI7bADFB0QDksZ4LtO7IZl/zbzXmcC +C52GVWH9ejjt/uIZALdvoVBidXQ8oPrIJZK0bnoix/geoeOy3ZExqysdBP+lSgQ3 +6YWkMyv94tZVNHwZpEpox7Ko07fKoZOI68GXvIz5HdkihCR0xwQ9aqkpk8zruFvh +/l8lqjRYyMEjVJ0bmBHDOJx+PYZspQ9AhnwC9FwCTyjLrnGfDzrIM/4RJTXq/LrF +YD3ZfBjVsqnTdXgDciLKOsMf7yzlLqn6niy2UUb9rwPW6mBo6oUWNmuF6R7As93E +JNyAKoFBbZQ+yODJgUEAnl6/f8UImKIYLEJAs/lvOCdLToD0PYFH4Ih86hzOtXVc +US4cK38acijnALXRdMbX5J+tB5O2UzU1/Dfkw/ZdFr4hc96SCvigY2q8lpJqPvi8 +ZVWb3vUNiSYE/CUapiVpy8JtynziWV+XrOvvLsi81xtZPCvM8hnIk2snYxnP/Okm ++Mpxm3+T/jRnhE6Z6/yzeAkzcLpmpnbtG3PrGqUNxCITIJRWCk4sbE6x/c+cCbqi +M+2HAgMBAAGjYzBhMB0GA1UdDgQWBBTdBAkHovV6fVJTEpKV7jiAJQ2mWTAPBgNV +HRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFN0ECQei9Xp9UlMSkpXuOIAlDaZZMA4G +A1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAIBgRlCn7Jp0cHh5wYfGV +cpNxJK1ok1iOMq8bs3AD/CUrdIWQPXhq9LmLpZc7tRiRux6n+UBbkflVma8eEdBc +Hadm47GUBwwyOabqG7B52B2ccETjit3E+ZUfijhDPwGFpUenPUayvOUiaPd7nNgs +PgohyC0zrL/FgZkxdMF1ccW+sfAjRfSda/wZY52jvATGGAslu1OJD7OAUN5F7kR/ +q5R4ZJjT9ijdh9hwZXT7DrkT66cPYakylszeu+1jTBi7qUD3oFRuIIhxdRjqerQ0 +cuAjJ3dctpDqhiVAq+8zD8ufgr6iIPv2tS0a5sKFsXQP+8hlAqRSAUfdSSLBv9jr +a6x+3uxjMxW3IwiPxg+NQVrdjsW5j+VFP3jbutIbQLH+cU0/4IGiul607BXgk90I +H37hVZkLId6Tngr75qNJvTYw/ud3sqB1l7UtgYgXZSD32pAAn8lSzDLKNXz1PQ/Y +K9f1JmzJBjSWFupwWRoyeXkLtoh/D1JIPb9s2KJELtFOt3JY04kTlf5Eq/jXixtu +nLwsoFvVagCvXzfh1foQC5ichucmj87w7G6KVwuA406ywKBjYZC6VWg3dGq2ktuf +oYYitmUnDuy2n0Jg5GfCtdpBC8TTi2EbvPofkSvXRAdeuims2cXp71NIWuuA8ShY +Ic2wBlX7Jz9TkHCpBB5XJ7k= +-----END CERTIFICATE----- + +# Issuer: CN=SSL.com Root Certification Authority ECC O=SSL Corporation +# Subject: CN=SSL.com Root Certification Authority ECC O=SSL Corporation +# Label: "SSL.com Root Certification Authority ECC" +# Serial: 8495723813297216424 +# MD5 Fingerprint: 2e:da:e4:39:7f:9c:8f:37:d1:70:9f:26:17:51:3a:8e +# SHA1 Fingerprint: c3:19:7c:39:24:e6:54:af:1b:c4:ab:20:95:7a:e2:c3:0e:13:02:6a +# SHA256 Fingerprint: 34:17:bb:06:cc:60:07:da:1b:96:1c:92:0b:8a:b4:ce:3f:ad:82:0e:4a:a3:0b:9a:cb:c4:a7:4e:bd:ce:bc:65 +-----BEGIN CERTIFICATE----- +MIICjTCCAhSgAwIBAgIIdebfy8FoW6gwCgYIKoZIzj0EAwIwfDELMAkGA1UEBhMC +VVMxDjAMBgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9T +U0wgQ29ycG9yYXRpb24xMTAvBgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZpY2F0 +aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYwMjEyMTgxNDAzWhcNNDEwMjEyMTgxNDAz +WjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hvdXN0 +b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NMLmNvbSBS +b290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49AgEGBSuB +BAAiA2IABEVuqVDEpiM2nl8ojRfLliJkP9x6jh3MCLOicSS6jkm5BBtHllirLZXI +7Z4INcgn64mMU1jrYor+8FsPazFSY0E7ic3s7LaNGdM0B9y7xgZ/wkWV7Mt/qCPg +CemB+vNH06NjMGEwHQYDVR0OBBYEFILRhXMw5zUE044CkvvlpNHEIejNMA8GA1Ud +EwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUgtGFczDnNQTTjgKS++Wk0cQh6M0wDgYD +VR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2cAMGQCMG/n61kRpGDPYbCWe+0F+S8T +kdzt5fxQaxFGRrMcIQBiu77D5+jNB5n5DQtdcj7EqgIwH7y6C+IwJPt8bYBVCpk+ +gA0z5Wajs6O7pdWLjwkspl1+4vAHCGht0nxpbl/f5Wpl +-----END CERTIFICATE----- + +# Issuer: CN=SSL.com EV Root Certification Authority RSA R2 O=SSL Corporation +# Subject: CN=SSL.com EV Root Certification Authority RSA R2 O=SSL Corporation +# Label: "SSL.com EV Root Certification Authority RSA R2" +# Serial: 6248227494352943350 +# MD5 Fingerprint: e1:1e:31:58:1a:ae:54:53:02:f6:17:6a:11:7b:4d:95 +# SHA1 Fingerprint: 74:3a:f0:52:9b:d0:32:a0:f4:4a:83:cd:d4:ba:a9:7b:7c:2e:c4:9a +# SHA256 Fingerprint: 2e:7b:f1:6c:c2:24:85:a7:bb:e2:aa:86:96:75:07:61:b0:ae:39:be:3b:2f:e9:d0:cc:6d:4e:f7:34:91:42:5c +-----BEGIN CERTIFICATE----- +MIIF6zCCA9OgAwIBAgIIVrYpzTS8ePYwDQYJKoZIhvcNAQELBQAwgYIxCzAJBgNV +BAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UE +CgwPU1NMIENvcnBvcmF0aW9uMTcwNQYDVQQDDC5TU0wuY29tIEVWIFJvb3QgQ2Vy +dGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIyMB4XDTE3MDUzMTE4MTQzN1oXDTQy +MDUzMDE4MTQzN1owgYIxCzAJBgNVBAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEQMA4G +A1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMTcwNQYDVQQD +DC5TU0wuY29tIEVWIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIy +MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAjzZlQOHWTcDXtOlG2mvq +M0fNTPl9fb69LT3w23jhhqXZuglXaO1XPqDQCEGD5yhBJB/jchXQARr7XnAjssuf +OePPxU7Gkm0mxnu7s9onnQqG6YE3Bf7wcXHswxzpY6IXFJ3vG2fThVUCAtZJycxa +4bH3bzKfydQ7iEGonL3Lq9ttewkfokxykNorCPzPPFTOZw+oz12WGQvE43LrrdF9 +HSfvkusQv1vrO6/PgN3B0pYEW3p+pKk8OHakYo6gOV7qd89dAFmPZiw+B6KjBSYR +aZfqhbcPlgtLyEDhULouisv3D5oi53+aNxPN8k0TayHRwMwi8qFG9kRpnMphNQcA +b9ZhCBHqurj26bNg5U257J8UZslXWNvNh2n4ioYSA0e/ZhN2rHd9NCSFg83XqpyQ +Gp8hLH94t2S42Oim9HizVcuE0jLEeK6jj2HdzghTreyI/BXkmg3mnxp3zkyPuBQV +PWKchjgGAGYS5Fl2WlPAApiiECtoRHuOec4zSnaqW4EWG7WK2NAAe15itAnWhmMO +pgWVSbooi4iTsjQc2KRVbrcc0N6ZVTsj9CLg+SlmJuwgUHfbSguPvuUCYHBBXtSu +UDkiFCbLsjtzdFVHB3mBOagwE0TlBIqulhMlQg+5U8Sb/M3kHN48+qvWBkofZ6aY +MBzdLNvcGJVXZsb/XItW9XcCAwEAAaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAfBgNV +HSMEGDAWgBT5YLvU49U09rj1BoAlp3PbRmmonjAdBgNVHQ4EFgQU+WC71OPVNPa4 +9QaAJadz20ZpqJ4wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQBW +s47LCp1Jjr+kxJG7ZhcFUZh1++VQLHqe8RT6q9OKPv+RKY9ji9i0qVQBDb6Thi/5 +Sm3HXvVX+cpVHBK+Rw82xd9qt9t1wkclf7nxY/hoLVUE0fKNsKTPvDxeH3jnpaAg +cLAExbf3cqfeIg29MyVGjGSSJuM+LmOW2puMPfgYCdcDzH2GguDKBAdRUNf/ktUM +79qGn5nX67evaOI5JpS6aLe/g9Pqemc9YmeuJeVy6OLk7K4S9ksrPJ/psEDzOFSz +/bdoyNrGj1E8svuR3Bznm53htw1yj+KkxKl4+esUrMZDBcJlOSgYAsOCsp0FvmXt +ll9ldDz7CTUue5wT/RsPXcdtgTpWD8w74a8CLyKsRspGPKAcTNZEtF4uXBVmCeEm +Kf7GUmG6sXP/wwyc5WxqlD8UykAWlYTzWamsX0xhk23RO8yilQwipmdnRC652dKK +QbNmC1r7fSOl8hqw/96bg5Qu0T/fkreRrwU7ZcegbLHNYhLDkBvjJc40vG93drEQ +w/cFGsDWr3RiSBd3kmmQYRzelYB0VI8YHMPzA9C/pEN1hlMYegouCRw2n5H9gooi +S9EOUCXdywMMF8mDAAhONU2Ki+3wApRmLER/y5UnlhetCTCstnEXbosX9hwJ1C07 +mKVx01QT2WDz9UtmT/rx7iASjbSsV7FFY6GsdqnC+w== +-----END CERTIFICATE----- + +# Issuer: CN=SSL.com EV Root Certification Authority ECC O=SSL Corporation +# Subject: CN=SSL.com EV Root Certification Authority ECC O=SSL Corporation +# Label: "SSL.com EV Root Certification Authority ECC" +# Serial: 3182246526754555285 +# MD5 Fingerprint: 59:53:22:65:83:42:01:54:c0:ce:42:b9:5a:7c:f2:90 +# SHA1 Fingerprint: 4c:dd:51:a3:d1:f5:20:32:14:b0:c6:c5:32:23:03:91:c7:46:42:6d +# SHA256 Fingerprint: 22:a2:c1:f7:bd:ed:70:4c:c1:e7:01:b5:f4:08:c3:10:88:0f:e9:56:b5:de:2a:4a:44:f9:9c:87:3a:25:a7:c8 +-----BEGIN CERTIFICATE----- +MIIClDCCAhqgAwIBAgIILCmcWxbtBZUwCgYIKoZIzj0EAwIwfzELMAkGA1UEBhMC +VVMxDjAMBgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9T +U0wgQ29ycG9yYXRpb24xNDAyBgNVBAMMK1NTTC5jb20gRVYgUm9vdCBDZXJ0aWZp +Y2F0aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYwMjEyMTgxNTIzWhcNNDEwMjEyMTgx +NTIzWjB/MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hv +dXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjE0MDIGA1UEAwwrU1NMLmNv +bSBFViBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49 +AgEGBSuBBAAiA2IABKoSR5CYG/vvw0AHgyBO8TCCogbR8pKGYfL2IWjKAMTH6kMA +VIbc/R/fALhBYlzccBYy3h+Z1MzFB8gIH2EWB1E9fVwHU+M1OIzfzZ/ZLg1Kthku +WnBaBu2+8KGwytAJKaNjMGEwHQYDVR0OBBYEFFvKXuXe0oGqzagtZFG22XKbl+ZP +MA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUW8pe5d7SgarNqC1kUbbZcpuX +5k8wDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2gAMGUCMQCK5kCJN+vp1RPZ +ytRrJPOwPYdGWBrssd9v+1a6cGvHOMzosYxPD/fxZ3YOg9AeUY8CMD32IygmTMZg +h5Mmm7I1HrrW9zzRHM76JTymGoEVW/MSD2zuZYrJh6j5B+BimoxcSg== +-----END CERTIFICATE----- + +# Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R6 +# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R6 +# Label: "GlobalSign Root CA - R6" +# Serial: 1417766617973444989252670301619537 +# MD5 Fingerprint: 4f:dd:07:e4:d4:22:64:39:1e:0c:37:42:ea:d1:c6:ae +# SHA1 Fingerprint: 80:94:64:0e:b5:a7:a1:ca:11:9c:1f:dd:d5:9f:81:02:63:a7:fb:d1 +# SHA256 Fingerprint: 2c:ab:ea:fe:37:d0:6c:a2:2a:ba:73:91:c0:03:3d:25:98:29:52:c4:53:64:73:49:76:3a:3a:b5:ad:6c:cf:69 +-----BEGIN CERTIFICATE----- +MIIFgzCCA2ugAwIBAgIORea7A4Mzw4VlSOb/RVEwDQYJKoZIhvcNAQEMBQAwTDEg +MB4GA1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjYxEzARBgNVBAoTCkdsb2Jh +bFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMTQxMjEwMDAwMDAwWhcNMzQx +MjEwMDAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSNjET +MBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCAiIwDQYJ +KoZIhvcNAQEBBQADggIPADCCAgoCggIBAJUH6HPKZvnsFMp7PPcNCPG0RQssgrRI +xutbPK6DuEGSMxSkb3/pKszGsIhrxbaJ0cay/xTOURQh7ErdG1rG1ofuTToVBu1k +ZguSgMpE3nOUTvOniX9PeGMIyBJQbUJmL025eShNUhqKGoC3GYEOfsSKvGRMIRxD +aNc9PIrFsmbVkJq3MQbFvuJtMgamHvm566qjuL++gmNQ0PAYid/kD3n16qIfKtJw +LnvnvJO7bVPiSHyMEAc4/2ayd2F+4OqMPKq0pPbzlUoSB239jLKJz9CgYXfIWHSw +1CM69106yqLbnQneXUQtkPGBzVeS+n68UARjNN9rkxi+azayOeSsJDa38O+2HBNX +k7besvjihbdzorg1qkXy4J02oW9UivFyVm4uiMVRQkQVlO6jxTiWm05OWgtH8wY2 +SXcwvHE35absIQh1/OZhFj931dmRl4QKbNQCTXTAFO39OfuD8l4UoQSwC+n+7o/h +bguyCLNhZglqsQY6ZZZZwPA1/cnaKI0aEYdwgQqomnUdnjqGBQCe24DWJfncBZ4n +WUx2OVvq+aWh2IMP0f/fMBH5hc8zSPXKbWQULHpYT9NLCEnFlWQaYw55PfWzjMpY +rZxCRXluDocZXFSxZba/jJvcE+kNb7gu3GduyYsRtYQUigAZcIN5kZeR1Bonvzce +MgfYFGM8KEyvAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTAD +AQH/MB0GA1UdDgQWBBSubAWjkxPioufi1xzWx/B/yGdToDAfBgNVHSMEGDAWgBSu +bAWjkxPioufi1xzWx/B/yGdToDANBgkqhkiG9w0BAQwFAAOCAgEAgyXt6NH9lVLN +nsAEoJFp5lzQhN7craJP6Ed41mWYqVuoPId8AorRbrcWc+ZfwFSY1XS+wc3iEZGt +Ixg93eFyRJa0lV7Ae46ZeBZDE1ZXs6KzO7V33EByrKPrmzU+sQghoefEQzd5Mr61 +55wsTLxDKZmOMNOsIeDjHfrYBzN2VAAiKrlNIC5waNrlU/yDXNOd8v9EDERm8tLj +vUYAGm0CuiVdjaExUd1URhxN25mW7xocBFymFe944Hn+Xds+qkxV/ZoVqW/hpvvf +cDDpw+5CRu3CkwWJ+n1jez/QcYF8AOiYrg54NMMl+68KnyBr3TsTjxKM4kEaSHpz +oHdpx7Zcf4LIHv5YGygrqGytXm3ABdJ7t+uA/iU3/gKbaKxCXcPu9czc8FB10jZp +nOZ7BN9uBmm23goJSFmH63sUYHpkqmlD75HHTOwY3WzvUy2MmeFe8nI+z1TIvWfs +pA9MRf/TuTAjB0yPEL+GltmZWrSZVxykzLsViVO6LAUP5MSeGbEYNNVMnbrt9x+v +JJUEeKgDu+6B5dpffItKoZB0JaezPkvILFa9x8jvOOJckvB595yEunQtYQEgfn7R +8k8HWV+LLUNS60YMlOH1Zkd5d9VUWx+tJDfLRVpOoERIyNiwmcUVhAn21klJwGW4 +5hpxbqCo8YLoRT5s1gLXCmeDBVrJpBA= +-----END CERTIFICATE----- + +# Issuer: CN=OISTE WISeKey Global Root GC CA O=WISeKey OU=OISTE Foundation Endorsed +# Subject: CN=OISTE WISeKey Global Root GC CA O=WISeKey OU=OISTE Foundation Endorsed +# Label: "OISTE WISeKey Global Root GC CA" +# Serial: 44084345621038548146064804565436152554 +# MD5 Fingerprint: a9:d6:b9:2d:2f:93:64:f8:a5:69:ca:91:e9:68:07:23 +# SHA1 Fingerprint: e0:11:84:5e:34:de:be:88:81:b9:9c:f6:16:26:d1:96:1f:c3:b9:31 +# SHA256 Fingerprint: 85:60:f9:1c:36:24:da:ba:95:70:b5:fe:a0:db:e3:6f:f1:1a:83:23:be:94:86:85:4f:b3:f3:4a:55:71:19:8d +-----BEGIN CERTIFICATE----- +MIICaTCCAe+gAwIBAgIQISpWDK7aDKtARb8roi066jAKBggqhkjOPQQDAzBtMQsw +CQYDVQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUgRm91 +bmRhdGlvbiBFbmRvcnNlZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwg +Um9vdCBHQyBDQTAeFw0xNzA1MDkwOTQ4MzRaFw00MjA1MDkwOTU4MzNaMG0xCzAJ +BgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYDVQQLExlPSVNURSBGb3Vu +ZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEdsb2JhbCBS +b290IEdDIENBMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAETOlQwMYPchi82PG6s4ni +eUqjFqdrVCTbUf/q9Akkwwsin8tqJ4KBDdLArzHkdIJuyiXZjHWd8dvQmqJLIX4W +p2OQ0jnUsYd4XxiWD1AbNTcPasbc2RNNpI6QN+a9WzGRo1QwUjAOBgNVHQ8BAf8E +BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUSIcUrOPDnpBgOtfKie7T +rYy0UGYwEAYJKwYBBAGCNxUBBAMCAQAwCgYIKoZIzj0EAwMDaAAwZQIwJsdpW9zV +57LnyAyMjMPdeYwbY9XJUpROTYJKcx6ygISpJcBMWm1JKWB4E+J+SOtkAjEA2zQg +Mgj/mkkCtojeFK9dbJlxjRo/i9fgojaGHAeCOnZT/cKi7e97sIBPWA9LUzm9 +-----END CERTIFICATE----- + +# Issuer: CN=GTS Root R1 O=Google Trust Services LLC +# Subject: CN=GTS Root R1 O=Google Trust Services LLC +# Label: "GTS Root R1" +# Serial: 146587175971765017618439757810265552097 +# MD5 Fingerprint: 82:1a:ef:d4:d2:4a:f2:9f:e2:3d:97:06:14:70:72:85 +# SHA1 Fingerprint: e1:c9:50:e6:ef:22:f8:4c:56:45:72:8b:92:20:60:d7:d5:a7:a3:e8 +# SHA256 Fingerprint: 2a:57:54:71:e3:13:40:bc:21:58:1c:bd:2c:f1:3e:15:84:63:20:3e:ce:94:bc:f9:d3:cc:19:6b:f0:9a:54:72 +-----BEGIN CERTIFICATE----- +MIIFWjCCA0KgAwIBAgIQbkepxUtHDA3sM9CJuRz04TANBgkqhkiG9w0BAQwFADBH +MQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExM +QzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIy +MDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNl +cnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwggIiMA0GCSqGSIb3DQEB +AQUAA4ICDwAwggIKAoICAQC2EQKLHuOhd5s73L+UPreVp0A8of2C+X0yBoJx9vaM +f/vo27xqLpeXo4xL+Sv2sfnOhB2x+cWX3u+58qPpvBKJXqeqUqv4IyfLpLGcY9vX +mX7wCl7raKb0xlpHDU0QM+NOsROjyBhsS+z8CZDfnWQpJSMHobTSPS5g4M/SCYe7 +zUjwTcLCeoiKu7rPWRnWr4+wB7CeMfGCwcDfLqZtbBkOtdh+JhpFAz2weaSUKK0P +fyblqAj+lug8aJRT7oM6iCsVlgmy4HqMLnXWnOunVmSPlk9orj2XwoSPwLxAwAtc +vfaHszVsrBhQf4TgTM2S0yDpM7xSma8ytSmzJSq0SPly4cpk9+aCEI3oncKKiPo4 +Zor8Y/kB+Xj9e1x3+naH+uzfsQ55lVe0vSbv1gHR6xYKu44LtcXFilWr06zqkUsp +zBmkMiVOKvFlRNACzqrOSbTqn3yDsEB750Orp2yjj32JgfpMpf/VjsPOS+C12LOO +Rc92wO1AK/1TD7Cn1TsNsYqiA94xrcx36m97PtbfkSIS5r762DL8EGMUUXLeXdYW +k70paDPvOmbsB4om3xPXV2V4J95eSRQAogB/mqghtqmxlbCluQ0WEdrHbEg8QOB+ +DVrNVjzRlwW5y0vtOUucxD/SVRNuJLDWcfr0wbrM7Rv1/oFB2ACYPTrIrnqYNxgF +lQIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV +HQ4EFgQU5K8rJnEaK0gnhS9SZizv8IkTcT4wDQYJKoZIhvcNAQEMBQADggIBADiW +Cu49tJYeX++dnAsznyvgyv3SjgofQXSlfKqE1OXyHuY3UjKcC9FhHb8owbZEKTV1 +d5iyfNm9dKyKaOOpMQkpAWBz40d8U6iQSifvS9efk+eCNs6aaAyC58/UEBZvXw6Z +XPYfcX3v73svfuo21pdwCxXu11xWajOl40k4DLh9+42FpLFZXvRq4d2h9mREruZR +gyFmxhE+885H7pwoHyXa/6xmld01D1zvICxi/ZG6qcz8WpyTgYMpl0p8WnK0OdC3 +d8t5/Wk6kjftbjhlRn7pYL15iJdfOBL07q9bgsiG1eGZbYwE8na6SfZu6W0eX6Dv +J4J2QPim01hcDyxC2kLGe4g0x8HYRZvBPsVhHdljUEn2NIVq4BjFbkerQUIpm/Zg +DdIx02OYI5NaAIFItO/Nis3Jz5nu2Z6qNuFoS3FJFDYoOj0dzpqPJeaAcWErtXvM ++SUWgeExX6GjfhaknBZqlxi9dnKlC54dNuYvoS++cJEPqOba+MSSQGwlfnuzCdyy +F62ARPBopY+Udf90WuioAnwMCeKpSwughQtiue+hMZL77/ZRBIls6Kl0obsXs7X9 +SQ98POyDGCBDTtWTurQ0sR8WNh8M5mQ5Fkzc4P4dyKliPUDqysU0ArSuiYgzNdws +E3PYJ/HQcu51OyLemGhmW/HGY0dVHLqlCFF1pkgl +-----END CERTIFICATE----- + +# Issuer: CN=GTS Root R2 O=Google Trust Services LLC +# Subject: CN=GTS Root R2 O=Google Trust Services LLC +# Label: "GTS Root R2" +# Serial: 146587176055767053814479386953112547951 +# MD5 Fingerprint: 44:ed:9a:0e:a4:09:3b:00:f2:ae:4c:a3:c6:61:b0:8b +# SHA1 Fingerprint: d2:73:96:2a:2a:5e:39:9f:73:3f:e1:c7:1e:64:3f:03:38:34:fc:4d +# SHA256 Fingerprint: c4:5d:7b:b0:8e:6d:67:e6:2e:42:35:11:0b:56:4e:5f:78:fd:92:ef:05:8c:84:0a:ea:4e:64:55:d7:58:5c:60 +-----BEGIN CERTIFICATE----- +MIIFWjCCA0KgAwIBAgIQbkepxlqz5yDFMJo/aFLybzANBgkqhkiG9w0BAQwFADBH +MQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExM +QzEUMBIGA1UEAxMLR1RTIFJvb3QgUjIwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIy +MDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNl +cnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjIwggIiMA0GCSqGSIb3DQEB +AQUAA4ICDwAwggIKAoICAQDO3v2m++zsFDQ8BwZabFn3GTXd98GdVarTzTukk3Lv +CvptnfbwhYBboUhSnznFt+4orO/LdmgUud+tAWyZH8QiHZ/+cnfgLFuv5AS/T3Kg +GjSY6Dlo7JUle3ah5mm5hRm9iYz+re026nO8/4Piy33B0s5Ks40FnotJk9/BW9Bu +XvAuMC6C/Pq8tBcKSOWIm8Wba96wyrQD8Nr0kLhlZPdcTK3ofmZemde4wj7I0BOd +re7kRXuJVfeKH2JShBKzwkCX44ofR5GmdFrS+LFjKBC4swm4VndAoiaYecb+3yXu +PuWgf9RhD1FLPD+M2uFwdNjCaKH5wQzpoeJ/u1U8dgbuak7MkogwTZq9TwtImoS1 +mKPV+3PBV2HdKFZ1E66HjucMUQkQdYhMvI35ezzUIkgfKtzra7tEscszcTJGr61K +8YzodDqs5xoic4DSMPclQsciOzsSrZYuxsN2B6ogtzVJV+mSSeh2FnIxZyuWfoqj +x5RWIr9qS34BIbIjMt/kmkRtWVtd9QCgHJvGeJeNkP+byKq0rxFROV7Z+2et1VsR +nTKaG73VululycslaVNVJ1zgyjbLiGH7HrfQy+4W+9OmTN6SpdTi3/UGVN4unUu0 +kzCqgc7dGtxRcw1PcOnlthYhGXmy5okLdWTK1au8CcEYof/UVKGFPP0UJAOyh9Ok +twIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV +HQ4EFgQUu//KjiOfT5nK2+JopqUVJxce2Q4wDQYJKoZIhvcNAQEMBQADggIBALZp +8KZ3/p7uC4Gt4cCpx/k1HUCCq+YEtN/L9x0Pg/B+E02NjO7jMyLDOfxA325BS0JT +vhaI8dI4XsRomRyYUpOM52jtG2pzegVATX9lO9ZY8c6DR2Dj/5epnGB3GFW1fgiT +z9D2PGcDFWEJ+YF59exTpJ/JjwGLc8R3dtyDovUMSRqodt6Sm2T4syzFJ9MHwAiA +pJiS4wGWAqoC7o87xdFtCjMwc3i5T1QWvwsHoaRc5svJXISPD+AVdyx+Jn7axEvb +pxZ3B7DNdehyQtaVhJ2Gg/LkkM0JR9SLA3DaWsYDQvTtN6LwG1BUSw7YhN4ZKJmB +R64JGz9I0cNv4rBgF/XuIwKl2gBbbZCr7qLpGzvpx0QnRY5rn/WkhLx3+WuXrD5R +RaIRpsyF7gpo8j5QOHokYh4XIDdtak23CZvJ/KRY9bb7nE4Yu5UC56GtmwfuNmsk +0jmGwZODUNKBRqhfYlcsu2xkiAhu7xNUX90txGdj08+JN7+dIPT7eoOboB6BAFDC +5AwiWVIQ7UNWhwD4FFKnHYuTjKJNRn8nxnGbJN7k2oaLDX5rIMHAnuFl2GqjpuiF +izoHCBy69Y9Vmhh1fuXsgWbRIXOhNUQLgD1bnF5vKheW0YMjiGZt5obicDIvUiLn +yOd/xCxgXS/Dr55FBcOEArf9LAhST4Ldo/DUhgkC +-----END CERTIFICATE----- + +# Issuer: CN=GTS Root R3 O=Google Trust Services LLC +# Subject: CN=GTS Root R3 O=Google Trust Services LLC +# Label: "GTS Root R3" +# Serial: 146587176140553309517047991083707763997 +# MD5 Fingerprint: 1a:79:5b:6b:04:52:9c:5d:c7:74:33:1b:25:9a:f9:25 +# SHA1 Fingerprint: 30:d4:24:6f:07:ff:db:91:89:8a:0b:e9:49:66:11:eb:8c:5e:46:e5 +# SHA256 Fingerprint: 15:d5:b8:77:46:19:ea:7d:54:ce:1c:a6:d0:b0:c4:03:e0:37:a9:17:f1:31:e8:a0:4e:1e:6b:7a:71:ba:bc:e5 +-----BEGIN CERTIFICATE----- +MIICDDCCAZGgAwIBAgIQbkepx2ypcyRAiQ8DVd2NHTAKBggqhkjOPQQDAzBHMQsw +CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU +MBIGA1UEAxMLR1RTIFJvb3QgUjMwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw +MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp +Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjMwdjAQBgcqhkjOPQIBBgUrgQQA +IgNiAAQfTzOHMymKoYTey8chWEGJ6ladK0uFxh1MJ7x/JlFyb+Kf1qPKzEUURout +736GjOyxfi//qXGdGIRFBEFVbivqJn+7kAHjSxm65FSWRQmx1WyRRK2EE46ajA2A +DDL24CejQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud +DgQWBBTB8Sa6oC2uhYHP0/EqEr24Cmf9vDAKBggqhkjOPQQDAwNpADBmAjEAgFuk +fCPAlaUs3L6JbyO5o91lAFJekazInXJ0glMLfalAvWhgxeG4VDvBNhcl2MG9AjEA +njWSdIUlUfUk7GRSJFClH9voy8l27OyCbvWFGFPouOOaKaqW04MjyaR7YbPMAuhd +-----END CERTIFICATE----- + +# Issuer: CN=GTS Root R4 O=Google Trust Services LLC +# Subject: CN=GTS Root R4 O=Google Trust Services LLC +# Label: "GTS Root R4" +# Serial: 146587176229350439916519468929765261721 +# MD5 Fingerprint: 5d:b6:6a:c4:60:17:24:6a:1a:99:a8:4b:ee:5e:b4:26 +# SHA1 Fingerprint: 2a:1d:60:27:d9:4a:b1:0a:1c:4d:91:5c:cd:33:a0:cb:3e:2d:54:cb +# SHA256 Fingerprint: 71:cc:a5:39:1f:9e:79:4b:04:80:25:30:b3:63:e1:21:da:8a:30:43:bb:26:66:2f:ea:4d:ca:7f:c9:51:a4:bd +-----BEGIN CERTIFICATE----- +MIICCjCCAZGgAwIBAgIQbkepyIuUtui7OyrYorLBmTAKBggqhkjOPQQDAzBHMQsw +CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU +MBIGA1UEAxMLR1RTIFJvb3QgUjQwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw +MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp +Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjQwdjAQBgcqhkjOPQIBBgUrgQQA +IgNiAATzdHOnaItgrkO4NcWBMHtLSZ37wWHO5t5GvWvVYRg1rkDdc/eJkTBa6zzu +hXyiQHY7qca4R9gq55KRanPpsXI5nymfopjTX15YhmUPoYRlBtHci8nHc8iMai/l +xKvRHYqjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud +DgQWBBSATNbrdP9JNqPV2Py1PsVq8JQdjDAKBggqhkjOPQQDAwNnADBkAjBqUFJ0 +CMRw3J5QdCHojXohw0+WbhXRIjVhLfoIN+4Zba3bssx9BzT1YBkstTTZbyACMANx +sbqjYAuG7ZoIapVon+Kz4ZNkfF6Tpt95LY2F45TPI11xzPKwTdb+mciUqXWi4w== +-----END CERTIFICATE----- + +# Issuer: CN=UCA Global G2 Root O=UniTrust +# Subject: CN=UCA Global G2 Root O=UniTrust +# Label: "UCA Global G2 Root" +# Serial: 124779693093741543919145257850076631279 +# MD5 Fingerprint: 80:fe:f0:c4:4a:f0:5c:62:32:9f:1c:ba:78:a9:50:f8 +# SHA1 Fingerprint: 28:f9:78:16:19:7a:ff:18:25:18:aa:44:fe:c1:a0:ce:5c:b6:4c:8a +# SHA256 Fingerprint: 9b:ea:11:c9:76:fe:01:47:64:c1:be:56:a6:f9:14:b5:a5:60:31:7a:bd:99:88:39:33:82:e5:16:1a:a0:49:3c +-----BEGIN CERTIFICATE----- +MIIFRjCCAy6gAwIBAgIQXd+x2lqj7V2+WmUgZQOQ7zANBgkqhkiG9w0BAQsFADA9 +MQswCQYDVQQGEwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxGzAZBgNVBAMMElVDQSBH +bG9iYWwgRzIgUm9vdDAeFw0xNjAzMTEwMDAwMDBaFw00MDEyMzEwMDAwMDBaMD0x +CzAJBgNVBAYTAkNOMREwDwYDVQQKDAhVbmlUcnVzdDEbMBkGA1UEAwwSVUNBIEds +b2JhbCBHMiBSb290MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxeYr +b3zvJgUno4Ek2m/LAfmZmqkywiKHYUGRO8vDaBsGxUypK8FnFyIdK+35KYmToni9 +kmugow2ifsqTs6bRjDXVdfkX9s9FxeV67HeToI8jrg4aA3++1NDtLnurRiNb/yzm +VHqUwCoV8MmNsHo7JOHXaOIxPAYzRrZUEaalLyJUKlgNAQLx+hVRZ2zA+te2G3/R +VogvGjqNO7uCEeBHANBSh6v7hn4PJGtAnTRnvI3HLYZveT6OqTwXS3+wmeOwcWDc +C/Vkw85DvG1xudLeJ1uK6NjGruFZfc8oLTW4lVYa8bJYS7cSN8h8s+1LgOGN+jIj +tm+3SJUIsUROhYw6AlQgL9+/V087OpAh18EmNVQg7Mc/R+zvWr9LesGtOxdQXGLY +D0tK3Cv6brxzks3sx1DoQZbXqX5t2Okdj4q1uViSukqSKwxW/YDrCPBeKW4bHAyv +j5OJrdu9o54hyokZ7N+1wxrrFv54NkzWbtA+FxyQF2smuvt6L78RHBgOLXMDj6Dl +NaBa4kx1HXHhOThTeEDMg5PXCp6dW4+K5OXgSORIskfNTip1KnvyIvbJvgmRlld6 +iIis7nCs+dwp4wwcOxJORNanTrAmyPPZGpeRaOrvjUYG0lZFWJo8DA+DuAUlwznP +O6Q0ibd5Ei9Hxeepl2n8pndntd978XplFeRhVmUCAwEAAaNCMEAwDgYDVR0PAQH/ +BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFIHEjMz15DD/pQwIX4wV +ZyF0Ad/fMA0GCSqGSIb3DQEBCwUAA4ICAQATZSL1jiutROTL/7lo5sOASD0Ee/oj +L3rtNtqyzm325p7lX1iPyzcyochltq44PTUbPrw7tgTQvPlJ9Zv3hcU2tsu8+Mg5 +1eRfB70VVJd0ysrtT7q6ZHafgbiERUlMjW+i67HM0cOU2kTC5uLqGOiiHycFutfl +1qnN3e92mI0ADs0b+gO3joBYDic/UvuUospeZcnWhNq5NXHzJsBPd+aBJ9J3O5oU +b3n09tDh05S60FdRvScFDcH9yBIw7m+NESsIndTUv4BFFJqIRNow6rSn4+7vW4LV +PtateJLbXDzz2K36uGt/xDYotgIVilQsnLAXc47QN6MUPJiVAAwpBVueSUmxX8fj +y88nZY41F7dXyDDZQVu5FLbowg+UMaeUmMxq67XhJ/UQqAHojhJi6IjMtX9Gl8Cb +EGY4GjZGXyJoPd/JxhMnq1MGrKI8hgZlb7F+sSlEmqO6SWkoaY/X5V+tBIZkbxqg +DMUIYs6Ao9Dz7GjevjPHF1t/gMRMTLGmhIrDO7gJzRSBuhjjVFc2/tsvfEehOjPI ++Vg7RE+xygKJBJYoaMVLuCaJu9YzL1DV/pqJuhgyklTGW+Cd+V7lDSKb9triyCGy +YiGqhkCyLmTTX8jjfhFnRR8F/uOi77Oos/N9j/gMHyIfLXC0uAE0djAA5SN4p1bX +UB+K+wb1whnw0A== +-----END CERTIFICATE----- + +# Issuer: CN=UCA Extended Validation Root O=UniTrust +# Subject: CN=UCA Extended Validation Root O=UniTrust +# Label: "UCA Extended Validation Root" +# Serial: 106100277556486529736699587978573607008 +# MD5 Fingerprint: a1:f3:5f:43:c6:34:9b:da:bf:8c:7e:05:53:ad:96:e2 +# SHA1 Fingerprint: a3:a1:b0:6f:24:61:23:4a:e3:36:a5:c2:37:fc:a6:ff:dd:f0:d7:3a +# SHA256 Fingerprint: d4:3a:f9:b3:54:73:75:5c:96:84:fc:06:d7:d8:cb:70:ee:5c:28:e7:73:fb:29:4e:b4:1e:e7:17:22:92:4d:24 +-----BEGIN CERTIFICATE----- +MIIFWjCCA0KgAwIBAgIQT9Irj/VkyDOeTzRYZiNwYDANBgkqhkiG9w0BAQsFADBH +MQswCQYDVQQGEwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxJTAjBgNVBAMMHFVDQSBF +eHRlbmRlZCBWYWxpZGF0aW9uIFJvb3QwHhcNMTUwMzEzMDAwMDAwWhcNMzgxMjMx +MDAwMDAwWjBHMQswCQYDVQQGEwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxJTAjBgNV +BAMMHFVDQSBFeHRlbmRlZCBWYWxpZGF0aW9uIFJvb3QwggIiMA0GCSqGSIb3DQEB +AQUAA4ICDwAwggIKAoICAQCpCQcoEwKwmeBkqh5DFnpzsZGgdT6o+uM4AHrsiWog +D4vFsJszA1qGxliG1cGFu0/GnEBNyr7uaZa4rYEwmnySBesFK5pI0Lh2PpbIILvS +sPGP2KxFRv+qZ2C0d35qHzwaUnoEPQc8hQ2E0B92CvdqFN9y4zR8V05WAT558aop +O2z6+I9tTcg1367r3CTueUWnhbYFiN6IXSV8l2RnCdm/WhUFhvMJHuxYMjMR83dk +sHYf5BA1FxvyDrFspCqjc/wJHx4yGVMR59mzLC52LqGj3n5qiAno8geK+LLNEOfi +c0CTuwjRP+H8C5SzJe98ptfRr5//lpr1kXuYC3fUfugH0mK1lTnj8/FtDw5lhIpj +VMWAtuCeS31HJqcBCF3RiJ7XwzJE+oJKCmhUfzhTA8ykADNkUVkLo4KRel7sFsLz +KuZi2irbWWIQJUoqgQtHB0MGcIfS+pMRKXpITeuUx3BNr2fVUbGAIAEBtHoIppB/ +TuDvB0GHr2qlXov7z1CymlSvw4m6WC31MJixNnI5fkkE/SmnTHnkBVfblLkWU41G +sx2VYVdWf6/wFlthWG82UBEL2KwrlRYaDh8IzTY0ZRBiZtWAXxQgXy0MoHgKaNYs +1+lvK9JKBZP8nm9rZ/+I8U6laUpSNwXqxhaN0sSZ0YIrO7o1dfdRUVjzyAfd5LQD +fwIDAQABo0IwQDAdBgNVHQ4EFgQU2XQ65DA9DfcS3H5aBZ8eNJr34RQwDwYDVR0T +AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQELBQADggIBADaN +l8xCFWQpN5smLNb7rhVpLGsaGvdftvkHTFnq88nIua7Mui563MD1sC3AO6+fcAUR +ap8lTwEpcOPlDOHqWnzcSbvBHiqB9RZLcpHIojG5qtr8nR/zXUACE/xOHAbKsxSQ +VBcZEhrxH9cMaVr2cXj0lH2RC47skFSOvG+hTKv8dGT9cZr4QQehzZHkPJrgmzI5 +c6sq1WnIeJEmMX3ixzDx/BR4dxIOE/TdFpS/S2d7cFOFyrC78zhNLJA5wA3CXWvp +4uXViI3WLL+rG761KIcSF3Ru/H38j9CHJrAb+7lsq+KePRXBOy5nAliRn+/4Qh8s +t2j1da3Ptfb/EX3C8CSlrdP6oDyp+l3cpaDvRKS+1ujl5BOWF3sGPjLtx7dCvHaj +2GU4Kzg1USEODm8uNBNA4StnDG1KQTAYI1oyVZnJF+A83vbsea0rWBmirSwiGpWO +vpaQXUJXxPkUAzUrHC1RVwinOt4/5Mi0A3PCwSaAuwtCH60NryZy2sy+s6ODWA2C +xR9GUeOcGMyNm43sSet1UNWMKFnKdDTajAshqx7qG+XH/RU+wBeq+yNuJkbL+vmx +cmtpzyKEC2IPrNkZAJSidjzULZrtBJ4tBmIQN1IchXIbJ+XMxjHsN+xjWZsLHXbM +fjKaiJUINlK73nZfdklJrX+9ZSCyycErdhh2n1ax +-----END CERTIFICATE----- + +# Issuer: CN=Certigna Root CA O=Dhimyotis OU=0002 48146308100036 +# Subject: CN=Certigna Root CA O=Dhimyotis OU=0002 48146308100036 +# Label: "Certigna Root CA" +# Serial: 269714418870597844693661054334862075617 +# MD5 Fingerprint: 0e:5c:30:62:27:eb:5b:bc:d7:ae:62:ba:e9:d5:df:77 +# SHA1 Fingerprint: 2d:0d:52:14:ff:9e:ad:99:24:01:74:20:47:6e:6c:85:27:27:f5:43 +# SHA256 Fingerprint: d4:8d:3d:23:ee:db:50:a4:59:e5:51:97:60:1c:27:77:4b:9d:7b:18:c9:4d:5a:05:95:11:a1:02:50:b9:31:68 +-----BEGIN CERTIFICATE----- +MIIGWzCCBEOgAwIBAgIRAMrpG4nxVQMNo+ZBbcTjpuEwDQYJKoZIhvcNAQELBQAw +WjELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCURoaW15b3RpczEcMBoGA1UECwwTMDAw +MiA0ODE0NjMwODEwMDAzNjEZMBcGA1UEAwwQQ2VydGlnbmEgUm9vdCBDQTAeFw0x +MzEwMDEwODMyMjdaFw0zMzEwMDEwODMyMjdaMFoxCzAJBgNVBAYTAkZSMRIwEAYD +VQQKDAlEaGlteW90aXMxHDAaBgNVBAsMEzAwMDIgNDgxNDYzMDgxMDAwMzYxGTAX +BgNVBAMMEENlcnRpZ25hIFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw +ggIKAoICAQDNGDllGlmx6mQWDoyUJJV8g9PFOSbcDO8WV43X2KyjQn+Cyu3NW9sO +ty3tRQgXstmzy9YXUnIo245Onoq2C/mehJpNdt4iKVzSs9IGPjA5qXSjklYcoW9M +CiBtnyN6tMbaLOQdLNyzKNAT8kxOAkmhVECe5uUFoC2EyP+YbNDrihqECB63aCPu +I9Vwzm1RaRDuoXrC0SIxwoKF0vJVdlB8JXrJhFwLrN1CTivngqIkicuQstDuI7pm +TLtipPlTWmR7fJj6o0ieD5Wupxj0auwuA0Wv8HT4Ks16XdG+RCYyKfHx9WzMfgIh +C59vpD++nVPiz32pLHxYGpfhPTc3GGYo0kDFUYqMwy3OU4gkWGQwFsWq4NYKpkDf +ePb1BHxpE4S80dGnBs8B92jAqFe7OmGtBIyT46388NtEbVncSVmurJqZNjBBe3Yz +IoejwpKGbvlw7q6Hh5UbxHq9MfPU0uWZ/75I7HX1eBYdpnDBfzwboZL7z8g81sWT +Co/1VTp2lc5ZmIoJlXcymoO6LAQ6l73UL77XbJuiyn1tJslV1c/DeVIICZkHJC1k +JWumIWmbat10TWuXekG9qxf5kBdIjzb5LdXF2+6qhUVB+s06RbFo5jZMm5BX7CO5 +hwjCxAnxl4YqKE3idMDaxIzb3+KhF1nOJFl0Mdp//TBt2dzhauH8XwIDAQABo4IB +GjCCARYwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE +FBiHVuBud+4kNTxOc5of1uHieX4rMB8GA1UdIwQYMBaAFBiHVuBud+4kNTxOc5of +1uHieX4rMEQGA1UdIAQ9MDswOQYEVR0gADAxMC8GCCsGAQUFBwIBFiNodHRwczov +L3d3d3cuY2VydGlnbmEuZnIvYXV0b3JpdGVzLzBtBgNVHR8EZjBkMC+gLaArhilo +dHRwOi8vY3JsLmNlcnRpZ25hLmZyL2NlcnRpZ25hcm9vdGNhLmNybDAxoC+gLYYr +aHR0cDovL2NybC5kaGlteW90aXMuY29tL2NlcnRpZ25hcm9vdGNhLmNybDANBgkq +hkiG9w0BAQsFAAOCAgEAlLieT/DjlQgi581oQfccVdV8AOItOoldaDgvUSILSo3L +6btdPrtcPbEo/uRTVRPPoZAbAh1fZkYJMyjhDSSXcNMQH+pkV5a7XdrnxIxPTGRG +HVyH41neQtGbqH6mid2PHMkwgu07nM3A6RngatgCdTer9zQoKJHyBApPNeNgJgH6 +0BGM+RFq7q89w1DTj18zeTyGqHNFkIwgtnJzFyO+B2XleJINugHA64wcZr+shncB +lA2c5uk5jR+mUYyZDDl34bSb+hxnV29qao6pK0xXeXpXIs/NX2NGjVxZOob4Mkdi +o2cNGJHc+6Zr9UhhcyNZjgKnvETq9Emd8VRY+WCv2hikLyhF3HqgiIZd8zvn/yk1 +gPxkQ5Tm4xxvvq0OKmOZK8l+hfZx6AYDlf7ej0gcWtSS6Cvu5zHbugRqh5jnxV/v +faci9wHYTfmJ0A6aBVmknpjZbyvKcL5kwlWj9Omvw5Ip3IgWJJk8jSaYtlu3zM63 +Nwf9JtmYhST/WSMDmu2dnajkXjjO11INb9I/bbEFa0nOipFGc/T2L/Coc3cOZayh +jWZSaX5LaAzHHjcng6WMxwLkFM1JAbBzs/3GkDpv0mztO+7skb6iQ12LAEpmJURw +3kAP+HwV96LOPNdeE4yBFxgX0b3xdxA61GU5wSesVywlVP+i2k+KYTlerj1KjL0= +-----END CERTIFICATE----- + +# Issuer: CN=emSign Root CA - G1 O=eMudhra Technologies Limited OU=emSign PKI +# Subject: CN=emSign Root CA - G1 O=eMudhra Technologies Limited OU=emSign PKI +# Label: "emSign Root CA - G1" +# Serial: 235931866688319308814040 +# MD5 Fingerprint: 9c:42:84:57:dd:cb:0b:a7:2e:95:ad:b6:f3:da:bc:ac +# SHA1 Fingerprint: 8a:c7:ad:8f:73:ac:4e:c1:b5:75:4d:a5:40:f4:fc:cf:7c:b5:8e:8c +# SHA256 Fingerprint: 40:f6:af:03:46:a9:9a:a1:cd:1d:55:5a:4e:9c:ce:62:c7:f9:63:46:03:ee:40:66:15:83:3d:c8:c8:d0:03:67 +-----BEGIN CERTIFICATE----- +MIIDlDCCAnygAwIBAgIKMfXkYgxsWO3W2DANBgkqhkiG9w0BAQsFADBnMQswCQYD +VQQGEwJJTjETMBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBU +ZWNobm9sb2dpZXMgTGltaXRlZDEcMBoGA1UEAxMTZW1TaWduIFJvb3QgQ0EgLSBH +MTAeFw0xODAyMTgxODMwMDBaFw00MzAyMTgxODMwMDBaMGcxCzAJBgNVBAYTAklO +MRMwEQYDVQQLEwplbVNpZ24gUEtJMSUwIwYDVQQKExxlTXVkaHJhIFRlY2hub2xv +Z2llcyBMaW1pdGVkMRwwGgYDVQQDExNlbVNpZ24gUm9vdCBDQSAtIEcxMIIBIjAN +BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAk0u76WaK7p1b1TST0Bsew+eeuGQz +f2N4aLTNLnF115sgxk0pvLZoYIr3IZpWNVrzdr3YzZr/k1ZLpVkGoZM0Kd0WNHVO +8oG0x5ZOrRkVUkr+PHB1cM2vK6sVmjM8qrOLqs1D/fXqcP/tzxE7lM5OMhbTI0Aq +d7OvPAEsbO2ZLIvZTmmYsvePQbAyeGHWDV/D+qJAkh1cF+ZwPjXnorfCYuKrpDhM +tTk1b+oDafo6VGiFbdbyL0NVHpENDtjVaqSW0RM8LHhQ6DqS0hdW5TUaQBw+jSzt +Od9C4INBdN+jzcKGYEho42kLVACL5HZpIQ15TjQIXhTCzLG3rdd8cIrHhQIDAQAB +o0IwQDAdBgNVHQ4EFgQU++8Nhp6w492pufEhF38+/PB3KxowDgYDVR0PAQH/BAQD +AgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAFn/8oz1h31x +PaOfG1vR2vjTnGs2vZupYeveFix0PZ7mddrXuqe8QhfnPZHr5X3dPpzxz5KsbEjM +wiI/aTvFthUvozXGaCocV685743QNcMYDHsAVhzNixl03r4PEuDQqqE/AjSxcM6d +GNYIAwlG7mDgfrbESQRRfXBgvKqy/3lyeqYdPV8q+Mri/Tm3R7nrft8EI6/6nAYH +6ftjk4BAtcZsCjEozgyfz7MjNYBBjWzEN3uBL4ChQEKF6dk4jeihU80Bv2noWgby +RQuQ+q7hv53yrlc8pa6yVvSLZUDp/TGBLPQ5Cdjua6e0ph0VpZj3AYHYhX3zUVxx +iN66zB+Afko= +-----END CERTIFICATE----- + +# Issuer: CN=emSign ECC Root CA - G3 O=eMudhra Technologies Limited OU=emSign PKI +# Subject: CN=emSign ECC Root CA - G3 O=eMudhra Technologies Limited OU=emSign PKI +# Label: "emSign ECC Root CA - G3" +# Serial: 287880440101571086945156 +# MD5 Fingerprint: ce:0b:72:d1:9f:88:8e:d0:50:03:e8:e3:b8:8b:67:40 +# SHA1 Fingerprint: 30:43:fa:4f:f2:57:dc:a0:c3:80:ee:2e:58:ea:78:b2:3f:e6:bb:c1 +# SHA256 Fingerprint: 86:a1:ec:ba:08:9c:4a:8d:3b:be:27:34:c6:12:ba:34:1d:81:3e:04:3c:f9:e8:a8:62:cd:5c:57:a3:6b:be:6b +-----BEGIN CERTIFICATE----- +MIICTjCCAdOgAwIBAgIKPPYHqWhwDtqLhDAKBggqhkjOPQQDAzBrMQswCQYDVQQG +EwJJTjETMBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBUZWNo +bm9sb2dpZXMgTGltaXRlZDEgMB4GA1UEAxMXZW1TaWduIEVDQyBSb290IENBIC0g +RzMwHhcNMTgwMjE4MTgzMDAwWhcNNDMwMjE4MTgzMDAwWjBrMQswCQYDVQQGEwJJ +TjETMBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBUZWNobm9s +b2dpZXMgTGltaXRlZDEgMB4GA1UEAxMXZW1TaWduIEVDQyBSb290IENBIC0gRzMw +djAQBgcqhkjOPQIBBgUrgQQAIgNiAAQjpQy4LRL1KPOxst3iAhKAnjlfSU2fySU0 +WXTsuwYc58Byr+iuL+FBVIcUqEqy6HyC5ltqtdyzdc6LBtCGI79G1Y4PPwT01xyS +fvalY8L1X44uT6EYGQIrMgqCZH0Wk9GjQjBAMB0GA1UdDgQWBBR8XQKEE9TMipuB +zhccLikenEhjQjAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggq +hkjOPQQDAwNpADBmAjEAvvNhzwIQHWSVB7gYboiFBS+DCBeQyh+KTOgNG3qxrdWB +CUfvO6wIBHxcmbHtRwfSAjEAnbpV/KlK6O3t5nYBQnvI+GDZjVGLVTv7jHvrZQnD ++JbNR6iC8hZVdyR+EhCVBCyj +-----END CERTIFICATE----- + +# Issuer: CN=emSign Root CA - C1 O=eMudhra Inc OU=emSign PKI +# Subject: CN=emSign Root CA - C1 O=eMudhra Inc OU=emSign PKI +# Label: "emSign Root CA - C1" +# Serial: 825510296613316004955058 +# MD5 Fingerprint: d8:e3:5d:01:21:fa:78:5a:b0:df:ba:d2:ee:2a:5f:68 +# SHA1 Fingerprint: e7:2e:f1:df:fc:b2:09:28:cf:5d:d4:d5:67:37:b1:51:cb:86:4f:01 +# SHA256 Fingerprint: 12:56:09:aa:30:1d:a0:a2:49:b9:7a:82:39:cb:6a:34:21:6f:44:dc:ac:9f:39:54:b1:42:92:f2:e8:c8:60:8f +-----BEGIN CERTIFICATE----- +MIIDczCCAlugAwIBAgILAK7PALrEzzL4Q7IwDQYJKoZIhvcNAQELBQAwVjELMAkG +A1UEBhMCVVMxEzARBgNVBAsTCmVtU2lnbiBQS0kxFDASBgNVBAoTC2VNdWRocmEg +SW5jMRwwGgYDVQQDExNlbVNpZ24gUm9vdCBDQSAtIEMxMB4XDTE4MDIxODE4MzAw +MFoXDTQzMDIxODE4MzAwMFowVjELMAkGA1UEBhMCVVMxEzARBgNVBAsTCmVtU2ln +biBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMRwwGgYDVQQDExNlbVNpZ24gUm9v +dCBDQSAtIEMxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz+upufGZ +BczYKCFK83M0UYRWEPWgTywS4/oTmifQz/l5GnRfHXk5/Fv4cI7gklL35CX5VIPZ +HdPIWoU/Xse2B+4+wM6ar6xWQio5JXDWv7V7Nq2s9nPczdcdioOl+yuQFTdrHCZH +3DspVpNqs8FqOp099cGXOFgFixwR4+S0uF2FHYP+eF8LRWgYSKVGczQ7/g/IdrvH +GPMF0Ybzhe3nudkyrVWIzqa2kbBPrH4VI5b2P/AgNBbeCsbEBEV5f6f9vtKppa+c +xSMq9zwhbL2vj07FOrLzNBL834AaSaTUqZX3noleoomslMuoaJuvimUnzYnu3Yy1 +aylwQ6BpC+S5DwIDAQABo0IwQDAdBgNVHQ4EFgQU/qHgcB4qAzlSWkK+XJGFehiq +TbUwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL +BQADggEBAMJKVvoVIXsoounlHfv4LcQ5lkFMOycsxGwYFYDGrK9HWS8mC+M2sO87 +/kOXSTKZEhVb3xEp/6tT+LvBeA+snFOvV71ojD1pM/CjoCNjO2RnIkSt1XHLVip4 +kqNPEjE2NuLe/gDEo2APJ62gsIq1NnpSob0n9CAnYuhNlCQT5AoE6TyrLshDCUrG +YQTlSTR+08TI9Q/Aqum6VF7zYytPT1DU/rl7mYw9wC68AivTxEDkigcxHpvOJpkT ++xHqmiIMERnHXhuBUDDIlhJu58tBf5E7oke3VIAb3ADMmpDqw8NQBmIMMMAVSKeo +WXzhriKi4gp6D/piq1JM4fHfyr6DDUI= +-----END CERTIFICATE----- + +# Issuer: CN=emSign ECC Root CA - C3 O=eMudhra Inc OU=emSign PKI +# Subject: CN=emSign ECC Root CA - C3 O=eMudhra Inc OU=emSign PKI +# Label: "emSign ECC Root CA - C3" +# Serial: 582948710642506000014504 +# MD5 Fingerprint: 3e:53:b3:a3:81:ee:d7:10:f8:d3:b0:1d:17:92:f5:d5 +# SHA1 Fingerprint: b6:af:43:c2:9b:81:53:7d:f6:ef:6b:c3:1f:1f:60:15:0c:ee:48:66 +# SHA256 Fingerprint: bc:4d:80:9b:15:18:9d:78:db:3e:1d:8c:f4:f9:72:6a:79:5d:a1:64:3c:a5:f1:35:8e:1d:db:0e:dc:0d:7e:b3 +-----BEGIN CERTIFICATE----- +MIICKzCCAbGgAwIBAgIKe3G2gla4EnycqDAKBggqhkjOPQQDAzBaMQswCQYDVQQG +EwJVUzETMBEGA1UECxMKZW1TaWduIFBLSTEUMBIGA1UEChMLZU11ZGhyYSBJbmMx +IDAeBgNVBAMTF2VtU2lnbiBFQ0MgUm9vdCBDQSAtIEMzMB4XDTE4MDIxODE4MzAw +MFoXDTQzMDIxODE4MzAwMFowWjELMAkGA1UEBhMCVVMxEzARBgNVBAsTCmVtU2ln +biBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMSAwHgYDVQQDExdlbVNpZ24gRUND +IFJvb3QgQ0EgLSBDMzB2MBAGByqGSM49AgEGBSuBBAAiA2IABP2lYa57JhAd6bci +MK4G9IGzsUJxlTm801Ljr6/58pc1kjZGDoeVjbk5Wum739D+yAdBPLtVb4Ojavti +sIGJAnB9SMVK4+kiVCJNk7tCDK93nCOmfddhEc5lx/h//vXyqaNCMEAwHQYDVR0O +BBYEFPtaSNCAIEDyqOkAB2kZd6fmw/TPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMB +Af8EBTADAQH/MAoGCCqGSM49BAMDA2gAMGUCMQC02C8Cif22TGK6Q04ThHK1rt0c +3ta13FaPWEBaLd4gTCKDypOofu4SQMfWh0/434UCMBwUZOR8loMRnLDRWmFLpg9J +0wD8ofzkpf9/rdcw0Md3f76BB1UwUCAU9Vc4CqgxUQ== +-----END CERTIFICATE----- + +# Issuer: CN=Hongkong Post Root CA 3 O=Hongkong Post +# Subject: CN=Hongkong Post Root CA 3 O=Hongkong Post +# Label: "Hongkong Post Root CA 3" +# Serial: 46170865288971385588281144162979347873371282084 +# MD5 Fingerprint: 11:fc:9f:bd:73:30:02:8a:fd:3f:f3:58:b9:cb:20:f0 +# SHA1 Fingerprint: 58:a2:d0:ec:20:52:81:5b:c1:f3:f8:64:02:24:4e:c2:8e:02:4b:02 +# SHA256 Fingerprint: 5a:2f:c0:3f:0c:83:b0:90:bb:fa:40:60:4b:09:88:44:6c:76:36:18:3d:f9:84:6e:17:10:1a:44:7f:b8:ef:d6 +-----BEGIN CERTIFICATE----- +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 +mpv0 +-----END CERTIFICATE----- + +# Issuer: CN=Entrust Root Certification Authority - G4 O=Entrust, Inc. OU=See www.entrust.net/legal-terms/(c) 2015 Entrust, Inc. - for authorized use only +# Subject: CN=Entrust Root Certification Authority - G4 O=Entrust, Inc. OU=See www.entrust.net/legal-terms/(c) 2015 Entrust, Inc. - for authorized use only +# Label: "Entrust Root Certification Authority - G4" +# Serial: 289383649854506086828220374796556676440 +# MD5 Fingerprint: 89:53:f1:83:23:b7:7c:8e:05:f1:8c:71:38:4e:1f:88 +# SHA1 Fingerprint: 14:88:4e:86:26:37:b0:26:af:59:62:5c:40:77:ec:35:29:ba:96:01 +# SHA256 Fingerprint: db:35:17:d1:f6:73:2a:2d:5a:b9:7c:53:3e:c7:07:79:ee:32:70:a6:2f:b4:ac:42:38:37:24:60:e6:f0:1e:88 +-----BEGIN CERTIFICATE----- +MIIGSzCCBDOgAwIBAgIRANm1Q3+vqTkPAAAAAFVlrVgwDQYJKoZIhvcNAQELBQAw +gb4xCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQL +Ex9TZWUgd3d3LmVudHJ1c3QubmV0L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykg +MjAxNSBFbnRydXN0LCBJbmMuIC0gZm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxMjAw +BgNVBAMTKUVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEc0 +MB4XDTE1MDUyNzExMTExNloXDTM3MTIyNzExNDExNlowgb4xCzAJBgNVBAYTAlVT +MRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1 +c3QubmV0L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxNSBFbnRydXN0LCBJ +bmMuIC0gZm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxMjAwBgNVBAMTKUVudHJ1c3Qg +Um9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEc0MIICIjANBgkqhkiG9w0B +AQEFAAOCAg8AMIICCgKCAgEAsewsQu7i0TD/pZJH4i3DumSXbcr3DbVZwbPLqGgZ +2K+EbTBwXX7zLtJTmeH+H17ZSK9dE43b/2MzTdMAArzE+NEGCJR5WIoV3imz/f3E +T+iq4qA7ec2/a0My3dl0ELn39GjUu9CH1apLiipvKgS1sqbHoHrmSKvS0VnM1n4j +5pds8ELl3FFLFUHtSUrJ3hCX1nbB76W1NhSXNdh4IjVS70O92yfbYVaCNNzLiGAM +C1rlLAHGVK/XqsEQe9IFWrhAnoanw5CGAlZSCXqc0ieCU0plUmr1POeo8pyvi73T +DtTUXm6Hnmo9RR3RXRv06QqsYJn7ibT/mCzPfB3pAqoEmh643IhuJbNsZvc8kPNX +wbMv9W3y+8qh+CmdRouzavbmZwe+LGcKKh9asj5XxNMhIWNlUpEbsZmOeX7m640A +2Vqq6nPopIICR5b+W45UYaPrL0swsIsjdXJ8ITzI9vF01Bx7owVV7rtNOzK+mndm +nqxpkCIHH2E6lr7lmk/MBTwoWdPBDFSoWWG9yHJM6Nyfh3+9nEg2XpWjDrk4JFX8 +dWbrAuMINClKxuMrLzOg2qOGpRKX/YAr2hRC45K9PvJdXmd0LhyIRyk0X+IyqJwl +N4y6mACXi0mWHv0liqzc2thddG5msP9E36EYxr5ILzeUePiVSj9/E15dWf10hkNj +c0kCAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD +VR0OBBYEFJ84xFYjwznooHFs6FRM5Og6sb9nMA0GCSqGSIb3DQEBCwUAA4ICAQAS +5UKme4sPDORGpbZgQIeMJX6tuGguW8ZAdjwD+MlZ9POrYs4QjbRaZIxowLByQzTS +Gwv2LFPSypBLhmb8qoMi9IsabyZIrHZ3CL/FmFz0Jomee8O5ZDIBf9PD3Vht7LGr +hFV0d4QEJ1JrhkzO3bll/9bGXp+aEJlLdWr+aumXIOTkdnrG0CSqkM0gkLpHZPt/ +B7NTeLUKYvJzQ85BK4FqLoUWlFPUa19yIqtRLULVAJyZv967lDtX/Zr1hstWO1uI +AeV8KEsD+UmDfLJ/fOPtjqF/YFOOVZ1QNBIPt5d7bIdKROf1beyAN/BYGW5KaHbw +H5Lk6rWS02FREAutp9lfx1/cH6NcjKF+m7ee01ZvZl4HliDtC3T7Zk6LERXpgUl+ +b7DUUH8i119lAg2m9IUe2K4GS0qn0jFmwvjO5QimpAKWRGhXxNUzzxkvFMSUHHuk +2fCfDrGA4tGeEWSpiBE6doLlYsKA2KSD7ZPvfC+QsDJMlhVoSFLUmQjAJOgc47Ol +IQ6SwJAfzyBfyjs4x7dtOvPmRLgOMWuIjnDrnBdSqEGULoe256YSxXXfW8AKbnuk +5F6G+TaU33fD6Q3AOfF5u0aOq0NZJ7cguyPpVkAh7DE9ZapD8j3fcEThuk0mEDuY +n/PIjhs4ViFqUZPTkcpG2om3PVODLAgfi49T3f+sHw== +-----END CERTIFICATE----- + +# Issuer: CN=Microsoft ECC Root Certificate Authority 2017 O=Microsoft Corporation +# Subject: CN=Microsoft ECC Root Certificate Authority 2017 O=Microsoft Corporation +# Label: "Microsoft ECC Root Certificate Authority 2017" +# Serial: 136839042543790627607696632466672567020 +# MD5 Fingerprint: dd:a1:03:e6:4a:93:10:d1:bf:f0:19:42:cb:fe:ed:67 +# SHA1 Fingerprint: 99:9a:64:c3:7f:f4:7d:9f:ab:95:f1:47:69:89:14:60:ee:c4:c3:c5 +# SHA256 Fingerprint: 35:8d:f3:9d:76:4a:f9:e1:b7:66:e9:c9:72:df:35:2e:e1:5c:fa:c2:27:af:6a:d1:d7:0e:8e:4a:6e:dc:ba:02 +-----BEGIN CERTIFICATE----- +MIICWTCCAd+gAwIBAgIQZvI9r4fei7FK6gxXMQHC7DAKBggqhkjOPQQDAzBlMQsw +CQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYwNAYD +VQQDEy1NaWNyb3NvZnQgRUNDIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIw +MTcwHhcNMTkxMjE4MjMwNjQ1WhcNNDIwNzE4MjMxNjA0WjBlMQswCQYDVQQGEwJV +UzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYwNAYDVQQDEy1NaWNy +b3NvZnQgRUNDIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcwdjAQBgcq +hkjOPQIBBgUrgQQAIgNiAATUvD0CQnVBEyPNgASGAlEvaqiBYgtlzPbKnR5vSmZR +ogPZnZH6thaxjG7efM3beaYvzrvOcS/lpaso7GMEZpn4+vKTEAXhgShC48Zo9OYb +hGBKia/teQ87zvH2RPUBeMCjVDBSMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8E +BTADAQH/MB0GA1UdDgQWBBTIy5lycFIM+Oa+sgRXKSrPQhDtNTAQBgkrBgEEAYI3 +FQEEAwIBADAKBggqhkjOPQQDAwNoADBlAjBY8k3qDPlfXu5gKcs68tvWMoQZP3zV +L8KxzJOuULsJMsbG7X7JNpQS5GiFBqIb0C8CMQCZ6Ra0DvpWSNSkMBaReNtUjGUB +iudQZsIxtzm6uBoiB078a1QWIP8rtedMDE2mT3M= +-----END CERTIFICATE----- + +# Issuer: CN=Microsoft RSA Root Certificate Authority 2017 O=Microsoft Corporation +# Subject: CN=Microsoft RSA Root Certificate Authority 2017 O=Microsoft Corporation +# Label: "Microsoft RSA Root Certificate Authority 2017" +# Serial: 40975477897264996090493496164228220339 +# MD5 Fingerprint: 10:ff:00:ff:cf:c9:f8:c7:7a:c0:ee:35:8e:c9:0f:47 +# SHA1 Fingerprint: 73:a5:e6:4a:3b:ff:83:16:ff:0e:dc:cc:61:8a:90:6e:4e:ae:4d:74 +# SHA256 Fingerprint: c7:41:f7:0f:4b:2a:8d:88:bf:2e:71:c1:41:22:ef:53:ef:10:eb:a0:cf:a5:e6:4c:fa:20:f4:18:85:30:73:e0 +-----BEGIN CERTIFICATE----- +MIIFqDCCA5CgAwIBAgIQHtOXCV/YtLNHcB6qvn9FszANBgkqhkiG9w0BAQwFADBl +MQswCQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYw +NAYDVQQDEy1NaWNyb3NvZnQgUlNBIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5 +IDIwMTcwHhcNMTkxMjE4MjI1MTIyWhcNNDIwNzE4MjMwMDIzWjBlMQswCQYDVQQG +EwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYwNAYDVQQDEy1N +aWNyb3NvZnQgUlNBIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcwggIi +MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKW76UM4wplZEWCpW9R2LBifOZ +Nt9GkMml7Xhqb0eRaPgnZ1AzHaGm++DlQ6OEAlcBXZxIQIJTELy/xztokLaCLeX0 +ZdDMbRnMlfl7rEqUrQ7eS0MdhweSE5CAg2Q1OQT85elss7YfUJQ4ZVBcF0a5toW1 +HLUX6NZFndiyJrDKxHBKrmCk3bPZ7Pw71VdyvD/IybLeS2v4I2wDwAW9lcfNcztm +gGTjGqwu+UcF8ga2m3P1eDNbx6H7JyqhtJqRjJHTOoI+dkC0zVJhUXAoP8XFWvLJ +jEm7FFtNyP9nTUwSlq31/niol4fX/V4ggNyhSyL71Imtus5Hl0dVe49FyGcohJUc +aDDv70ngNXtk55iwlNpNhTs+VcQor1fznhPbRiefHqJeRIOkpcrVE7NLP8TjwuaG +YaRSMLl6IE9vDzhTyzMMEyuP1pq9KsgtsRx9S1HKR9FIJ3Jdh+vVReZIZZ2vUpC6 +W6IYZVcSn2i51BVrlMRpIpj0M+Dt+VGOQVDJNE92kKz8OMHY4Xu54+OU4UZpyw4K +UGsTuqwPN1q3ErWQgR5WrlcihtnJ0tHXUeOrO8ZV/R4O03QK0dqq6mm4lyiPSMQH ++FJDOvTKVTUssKZqwJz58oHhEmrARdlns87/I6KJClTUFLkqqNfs+avNJVgyeY+Q +W5g5xAgGwax/Dj0ApQIDAQABo1QwUjAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/ +BAUwAwEB/zAdBgNVHQ4EFgQUCctZf4aycI8awznjwNnpv7tNsiMwEAYJKwYBBAGC +NxUBBAMCAQAwDQYJKoZIhvcNAQEMBQADggIBAKyvPl3CEZaJjqPnktaXFbgToqZC +LgLNFgVZJ8og6Lq46BrsTaiXVq5lQ7GPAJtSzVXNUzltYkyLDVt8LkS/gxCP81OC +gMNPOsduET/m4xaRhPtthH80dK2Jp86519efhGSSvpWhrQlTM93uCupKUY5vVau6 +tZRGrox/2KJQJWVggEbbMwSubLWYdFQl3JPk+ONVFT24bcMKpBLBaYVu32TxU5nh +SnUgnZUP5NbcA/FZGOhHibJXWpS2qdgXKxdJ5XbLwVaZOjex/2kskZGT4d9Mozd2 +TaGf+G0eHdP67Pv0RR0Tbc/3WeUiJ3IrhvNXuzDtJE3cfVa7o7P4NHmJweDyAmH3 +pvwPuxwXC65B2Xy9J6P9LjrRk5Sxcx0ki69bIImtt2dmefU6xqaWM/5TkshGsRGR +xpl/j8nWZjEgQRCHLQzWwa80mMpkg/sTV9HB8Dx6jKXB/ZUhoHHBk2dxEuqPiApp +GWSZI1b7rCoucL5mxAyE7+WL85MB+GqQk2dLsmijtWKP6T+MejteD+eMuMZ87zf9 +dOLITzNy4ZQ5bb0Sr74MTnB8G2+NszKTc0QWbej09+CVgI+WXTik9KveCjCHk9hN +AHFiRSdLOkKEW39lt2c0Ui2cFmuqqNh7o0JMcccMyj6D5KbvtwEwXlGjefVwaaZB +RA+GsCyRxj3qrg+E +-----END CERTIFICATE----- + +# Issuer: CN=e-Szigno Root CA 2017 O=Microsec Ltd. +# Subject: CN=e-Szigno Root CA 2017 O=Microsec Ltd. +# Label: "e-Szigno Root CA 2017" +# Serial: 411379200276854331539784714 +# MD5 Fingerprint: de:1f:f6:9e:84:ae:a7:b4:21:ce:1e:58:7d:d1:84:98 +# SHA1 Fingerprint: 89:d4:83:03:4f:9e:9a:48:80:5f:72:37:d4:a9:a6:ef:cb:7c:1f:d1 +# SHA256 Fingerprint: be:b0:0b:30:83:9b:9b:c3:2c:32:e4:44:79:05:95:06:41:f2:64:21:b1:5e:d0:89:19:8b:51:8a:e2:ea:1b:99 +-----BEGIN CERTIFICATE----- +MIICQDCCAeWgAwIBAgIMAVRI7yH9l1kN9QQKMAoGCCqGSM49BAMCMHExCzAJBgNV +BAYTAkhVMREwDwYDVQQHDAhCdWRhcGVzdDEWMBQGA1UECgwNTWljcm9zZWMgTHRk +LjEXMBUGA1UEYQwOVkFUSFUtMjM1ODQ0OTcxHjAcBgNVBAMMFWUtU3ppZ25vIFJv +b3QgQ0EgMjAxNzAeFw0xNzA4MjIxMjA3MDZaFw00MjA4MjIxMjA3MDZaMHExCzAJ +BgNVBAYTAkhVMREwDwYDVQQHDAhCdWRhcGVzdDEWMBQGA1UECgwNTWljcm9zZWMg +THRkLjEXMBUGA1UEYQwOVkFUSFUtMjM1ODQ0OTcxHjAcBgNVBAMMFWUtU3ppZ25v +IFJvb3QgQ0EgMjAxNzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABJbcPYrYsHtv +xie+RJCxs1YVe45DJH0ahFnuY2iyxl6H0BVIHqiQrb1TotreOpCmYF9oMrWGQd+H +Wyx7xf58etqjYzBhMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G +A1UdDgQWBBSHERUI0arBeAyxr87GyZDvvzAEwDAfBgNVHSMEGDAWgBSHERUI0arB +eAyxr87GyZDvvzAEwDAKBggqhkjOPQQDAgNJADBGAiEAtVfd14pVCzbhhkT61Nlo +jbjcI4qKDdQvfepz7L9NbKgCIQDLpbQS+ue16M9+k/zzNY9vTlp8tLxOsvxyqltZ ++efcMQ== +-----END CERTIFICATE----- + +# Issuer: O=CERTSIGN SA OU=certSIGN ROOT CA G2 +# Subject: O=CERTSIGN SA OU=certSIGN ROOT CA G2 +# Label: "certSIGN Root CA G2" +# Serial: 313609486401300475190 +# MD5 Fingerprint: 8c:f1:75:8a:c6:19:cf:94:b7:f7:65:20:87:c3:97:c7 +# SHA1 Fingerprint: 26:f9:93:b4:ed:3d:28:27:b0:b9:4b:a7:e9:15:1d:a3:8d:92:e5:32 +# SHA256 Fingerprint: 65:7c:fe:2f:a7:3f:aa:38:46:25:71:f3:32:a2:36:3a:46:fc:e7:02:09:51:71:07:02:cd:fb:b6:ee:da:33:05 +-----BEGIN CERTIFICATE----- +MIIFRzCCAy+gAwIBAgIJEQA0tk7GNi02MA0GCSqGSIb3DQEBCwUAMEExCzAJBgNV +BAYTAlJPMRQwEgYDVQQKEwtDRVJUU0lHTiBTQTEcMBoGA1UECxMTY2VydFNJR04g +Uk9PVCBDQSBHMjAeFw0xNzAyMDYwOTI3MzVaFw00MjAyMDYwOTI3MzVaMEExCzAJ +BgNVBAYTAlJPMRQwEgYDVQQKEwtDRVJUU0lHTiBTQTEcMBoGA1UECxMTY2VydFNJ +R04gUk9PVCBDQSBHMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMDF +dRmRfUR0dIf+DjuW3NgBFszuY5HnC2/OOwppGnzC46+CjobXXo9X69MhWf05N0Iw +vlDqtg+piNguLWkh59E3GE59kdUWX2tbAMI5Qw02hVK5U2UPHULlj88F0+7cDBrZ +uIt4ImfkabBoxTzkbFpG583H+u/E7Eu9aqSs/cwoUe+StCmrqzWaTOTECMYmzPhp +n+Sc8CnTXPnGFiWeI8MgwT0PPzhAsP6CRDiqWhqKa2NYOLQV07YRaXseVO6MGiKs +cpc/I1mbySKEwQdPzH/iV8oScLumZfNpdWO9lfsbl83kqK/20U6o2YpxJM02PbyW +xPFsqa7lzw1uKA2wDrXKUXt4FMMgL3/7FFXhEZn91QqhngLjYl/rNUssuHLoPj1P +rCy7Lobio3aP5ZMqz6WryFyNSwb/EkaseMsUBzXgqd+L6a8VTxaJW732jcZZroiF +DsGJ6x9nxUWO/203Nit4ZoORUSs9/1F3dmKh7Gc+PoGD4FapUB8fepmrY7+EF3fx +DTvf95xhszWYijqy7DwaNz9+j5LP2RIUZNoQAhVB/0/E6xyjyfqZ90bp4RjZsbgy +LcsUDFDYg2WD7rlcz8sFWkz6GZdr1l0T08JcVLwyc6B49fFtHsufpaafItzRUZ6C +eWRgKRM+o/1Pcmqr4tTluCRVLERLiohEnMqE0yo7AgMBAAGjQjBAMA8GA1UdEwEB +/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSCIS1mxteg4BXrzkwJ +d8RgnlRuAzANBgkqhkiG9w0BAQsFAAOCAgEAYN4auOfyYILVAzOBywaK8SJJ6ejq +kX/GM15oGQOGO0MBzwdw5AgeZYWR5hEit/UCI46uuR59H35s5r0l1ZUa8gWmr4UC +b6741jH/JclKyMeKqdmfS0mbEVeZkkMR3rYzpMzXjWR91M08KCy0mpbqTfXERMQl +qiCA2ClV9+BB/AYm/7k29UMUA2Z44RGx2iBfRgB4ACGlHgAoYXhvqAEBj500mv/0 +OJD7uNGzcgbJceaBxXntC6Z58hMLnPddDnskk7RI24Zf3lCGeOdA5jGokHZwYa+c +NywRtYK3qq4kNFtyDGkNzVmf9nGvnAvRCjj5BiKDUyUM/FHE5r7iOZULJK2v0ZXk +ltd0ZGtxTgI8qoXzIKNDOXZbbFD+mpwUHmUUihW9o4JFWklWatKcsWMy5WHgUyIO +pwpJ6st+H6jiYoD2EEVSmAYY3qXNL3+q1Ok+CHLsIwMCPKaq2LxndD0UF/tUSxfj +03k9bWtJySgOLnRQvwzZRjoQhsmnP+mg7H/rpXdYaXHmgwo38oZJar55CJD2AhZk +PuXaTH4MNMn5X7azKFGnpyuqSfqNZSlO42sTp5SjLVFteAxEy9/eCG/Oo2Sr05WE +1LlSVHJ7liXMvGnjSG4N0MedJ5qq+BOS3R7fY581qRY27Iy4g/Q9iY/NtBde17MX +QRBdJ3NghVdJIgc= +-----END CERTIFICATE----- + +# Issuer: CN=Trustwave Global Certification Authority O=Trustwave Holdings, Inc. +# Subject: CN=Trustwave Global Certification Authority O=Trustwave Holdings, Inc. +# Label: "Trustwave Global Certification Authority" +# Serial: 1846098327275375458322922162 +# MD5 Fingerprint: f8:1c:18:2d:2f:ba:5f:6d:a1:6c:bc:c7:ab:91:c7:0e +# SHA1 Fingerprint: 2f:8f:36:4f:e1:58:97:44:21:59:87:a5:2a:9a:d0:69:95:26:7f:b5 +# SHA256 Fingerprint: 97:55:20:15:f5:dd:fc:3c:87:88:c0:06:94:45:55:40:88:94:45:00:84:f1:00:86:70:86:bc:1a:2b:b5:8d:c8 +-----BEGIN CERTIFICATE----- +MIIF2jCCA8KgAwIBAgIMBfcOhtpJ80Y1LrqyMA0GCSqGSIb3DQEBCwUAMIGIMQsw +CQYDVQQGEwJVUzERMA8GA1UECAwISWxsaW5vaXMxEDAOBgNVBAcMB0NoaWNhZ28x +ITAfBgNVBAoMGFRydXN0d2F2ZSBIb2xkaW5ncywgSW5jLjExMC8GA1UEAwwoVHJ1 +c3R3YXZlIEdsb2JhbCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0xNzA4MjMx +OTM0MTJaFw00MjA4MjMxOTM0MTJaMIGIMQswCQYDVQQGEwJVUzERMA8GA1UECAwI +SWxsaW5vaXMxEDAOBgNVBAcMB0NoaWNhZ28xITAfBgNVBAoMGFRydXN0d2F2ZSBI +b2xkaW5ncywgSW5jLjExMC8GA1UEAwwoVHJ1c3R3YXZlIEdsb2JhbCBDZXJ0aWZp +Y2F0aW9uIEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB +ALldUShLPDeS0YLOvR29zd24q88KPuFd5dyqCblXAj7mY2Hf8g+CY66j96xz0Xzn +swuvCAAJWX/NKSqIk4cXGIDtiLK0thAfLdZfVaITXdHG6wZWiYj+rDKd/VzDBcdu +7oaJuogDnXIhhpCujwOl3J+IKMujkkkP7NAP4m1ET4BqstTnoApTAbqOl5F2brz8 +1Ws25kCI1nsvXwXoLG0R8+eyvpJETNKXpP7ScoFDB5zpET71ixpZfR9oWN0EACyW +80OzfpgZdNmcc9kYvkHHNHnZ9GLCQ7mzJ7Aiy/k9UscwR7PJPrhq4ufogXBeQotP +JqX+OsIgbrv4Fo7NDKm0G2x2EOFYeUY+VM6AqFcJNykbmROPDMjWLBz7BegIlT1l +RtzuzWniTY+HKE40Cz7PFNm73bZQmq131BnW2hqIyE4bJ3XYsgjxroMwuREOzYfw +hI0Vcnyh78zyiGG69Gm7DIwLdVcEuE4qFC49DxweMqZiNu5m4iK4BUBjECLzMx10 +coos9TkpoNPnG4CELcU9402x/RpvumUHO1jsQkUm+9jaJXLE9gCxInm943xZYkqc +BW89zubWR2OZxiRvchLIrH+QtAuRcOi35hYQcRfO3gZPSEF9NUqjifLJS3tBEW1n +twiYTOURGa5CgNz7kAXU+FDKvuStx8KU1xad5hePrzb7AgMBAAGjQjBAMA8GA1Ud +EwEB/wQFMAMBAf8wHQYDVR0OBBYEFJngGWcNYtt2s9o9uFvo/ULSMQ6HMA4GA1Ud +DwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAmHNw4rDT7TnsTGDZqRKGFx6W +0OhUKDtkLSGm+J1WE2pIPU/HPinbbViDVD2HfSMF1OQc3Og4ZYbFdada2zUFvXfe +uyk3QAUHw5RSn8pk3fEbK9xGChACMf1KaA0HZJDmHvUqoai7PF35owgLEQzxPy0Q +lG/+4jSHg9bP5Rs1bdID4bANqKCqRieCNqcVtgimQlRXtpla4gt5kNdXElE1GYhB +aCXUNxeEFfsBctyV3lImIJgm4nb1J2/6ADtKYdkNy1GTKv0WBpanI5ojSP5RvbbE +sLFUzt5sQa0WZ37b/TjNuThOssFgy50X31ieemKyJo90lZvkWx3SD92YHJtZuSPT +MaCm/zjdzyBP6VhWOmfD0faZmZ26NraAL4hHT4a/RDqA5Dccprrql5gR0IRiR2Qe +qu5AvzSxnI9O4fKSTx+O856X3vOmeWqJcU9LJxdI/uz0UA9PSX3MReO9ekDFQdxh +VicGaeVyQYHTtgGJoC86cnn+OjC/QezHYj6RS8fZMXZC+fc8Y+wmjHMMfRod6qh8 +h6jCJ3zhM0EPz8/8AKAigJ5Kp28AsEFFtyLKaEjFQqKu3R3y4G5OBVixwJAWKqQ9 +EEC+j2Jjg6mcgn0tAumDMHzLJ8n9HmYAsC7TIS+OMxZsmO0QqAfWzJPP29FpHOTK +yeC2nOnOcXHebD8WpHk= +-----END CERTIFICATE----- + +# Issuer: CN=Trustwave Global ECC P256 Certification Authority O=Trustwave Holdings, Inc. +# Subject: CN=Trustwave Global ECC P256 Certification Authority O=Trustwave Holdings, Inc. +# Label: "Trustwave Global ECC P256 Certification Authority" +# Serial: 4151900041497450638097112925 +# MD5 Fingerprint: 5b:44:e3:8d:5d:36:86:26:e8:0d:05:d2:59:a7:83:54 +# SHA1 Fingerprint: b4:90:82:dd:45:0c:be:8b:5b:b1:66:d3:e2:a4:08:26:cd:ed:42:cf +# SHA256 Fingerprint: 94:5b:bc:82:5e:a5:54:f4:89:d1:fd:51:a7:3d:df:2e:a6:24:ac:70:19:a0:52:05:22:5c:22:a7:8c:cf:a8:b4 +-----BEGIN CERTIFICATE----- +MIICYDCCAgegAwIBAgIMDWpfCD8oXD5Rld9dMAoGCCqGSM49BAMCMIGRMQswCQYD +VQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAf +BgNVBAoTGFRydXN0d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3 +YXZlIEdsb2JhbCBFQ0MgUDI1NiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0x +NzA4MjMxOTM1MTBaFw00MjA4MjMxOTM1MTBaMIGRMQswCQYDVQQGEwJVUzERMA8G +A1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRydXN0 +d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBF +Q0MgUDI1NiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTBZMBMGByqGSM49AgEGCCqG +SM49AwEHA0IABH77bOYj43MyCMpg5lOcunSNGLB4kFKA3TjASh3RqMyTpJcGOMoN +FWLGjgEqZZ2q3zSRLoHB5DOSMcT9CTqmP62jQzBBMA8GA1UdEwEB/wQFMAMBAf8w +DwYDVR0PAQH/BAUDAwcGADAdBgNVHQ4EFgQUo0EGrJBt0UrrdaVKEJmzsaGLSvcw +CgYIKoZIzj0EAwIDRwAwRAIgB+ZU2g6gWrKuEZ+Hxbb/ad4lvvigtwjzRM4q3wgh +DDcCIC0mA6AFvWvR9lz4ZcyGbbOcNEhjhAnFjXca4syc4XR7 +-----END CERTIFICATE----- + +# Issuer: CN=Trustwave Global ECC P384 Certification Authority O=Trustwave Holdings, Inc. +# Subject: CN=Trustwave Global ECC P384 Certification Authority O=Trustwave Holdings, Inc. +# Label: "Trustwave Global ECC P384 Certification Authority" +# Serial: 2704997926503831671788816187 +# MD5 Fingerprint: ea:cf:60:c4:3b:b9:15:29:40:a1:97:ed:78:27:93:d6 +# SHA1 Fingerprint: e7:f3:a3:c8:cf:6f:c3:04:2e:6d:0e:67:32:c5:9e:68:95:0d:5e:d2 +# SHA256 Fingerprint: 55:90:38:59:c8:c0:c3:eb:b8:75:9e:ce:4e:25:57:22:5f:f5:75:8b:bd:38:eb:d4:82:76:60:1e:1b:d5:80:97 +-----BEGIN CERTIFICATE----- +MIICnTCCAiSgAwIBAgIMCL2Fl2yZJ6SAaEc7MAoGCCqGSM49BAMDMIGRMQswCQYD +VQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAf +BgNVBAoTGFRydXN0d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3 +YXZlIEdsb2JhbCBFQ0MgUDM4NCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0x +NzA4MjMxOTM2NDNaFw00MjA4MjMxOTM2NDNaMIGRMQswCQYDVQQGEwJVUzERMA8G +A1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRydXN0 +d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBF +Q0MgUDM4NCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTB2MBAGByqGSM49AgEGBSuB +BAAiA2IABGvaDXU1CDFHBa5FmVXxERMuSvgQMSOjfoPTfygIOiYaOs+Xgh+AtycJ +j9GOMMQKmw6sWASr9zZ9lCOkmwqKi6vr/TklZvFe/oyujUF5nQlgziip04pt89ZF +1PKYhDhloKNDMEEwDwYDVR0TAQH/BAUwAwEB/zAPBgNVHQ8BAf8EBQMDBwYAMB0G +A1UdDgQWBBRVqYSJ0sEyvRjLbKYHTsjnnb6CkDAKBggqhkjOPQQDAwNnADBkAjA3 +AZKXRRJ+oPM+rRk6ct30UJMDEr5E0k9BpIycnR+j9sKS50gU/k6bpZFXrsY3crsC +MGclCrEMXu6pY5Jv5ZAL/mYiykf9ijH3g/56vxC+GCsej/YpHpRZ744hN8tRmKVu +Sw== +-----END CERTIFICATE----- + +# Issuer: CN=NAVER Global Root Certification Authority O=NAVER BUSINESS PLATFORM Corp. +# Subject: CN=NAVER Global Root Certification Authority O=NAVER BUSINESS PLATFORM Corp. +# Label: "NAVER Global Root Certification Authority" +# Serial: 9013692873798656336226253319739695165984492813 +# MD5 Fingerprint: c8:7e:41:f6:25:3b:f5:09:b3:17:e8:46:3d:bf:d0:9b +# SHA1 Fingerprint: 8f:6b:f2:a9:27:4a:da:14:a0:c4:f4:8e:61:27:f9:c0:1e:78:5d:d1 +# SHA256 Fingerprint: 88:f4:38:dc:f8:ff:d1:fa:8f:42:91:15:ff:e5:f8:2a:e1:e0:6e:0c:70:c3:75:fa:ad:71:7b:34:a4:9e:72:65 +-----BEGIN CERTIFICATE----- +MIIFojCCA4qgAwIBAgIUAZQwHqIL3fXFMyqxQ0Rx+NZQTQ0wDQYJKoZIhvcNAQEM +BQAwaTELMAkGA1UEBhMCS1IxJjAkBgNVBAoMHU5BVkVSIEJVU0lORVNTIFBMQVRG +T1JNIENvcnAuMTIwMAYDVQQDDClOQVZFUiBHbG9iYWwgUm9vdCBDZXJ0aWZpY2F0 +aW9uIEF1dGhvcml0eTAeFw0xNzA4MTgwODU4NDJaFw0zNzA4MTgyMzU5NTlaMGkx +CzAJBgNVBAYTAktSMSYwJAYDVQQKDB1OQVZFUiBCVVNJTkVTUyBQTEFURk9STSBD +b3JwLjEyMDAGA1UEAwwpTkFWRVIgR2xvYmFsIFJvb3QgQ2VydGlmaWNhdGlvbiBB +dXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC21PGTXLVA +iQqrDZBbUGOukJR0F0Vy1ntlWilLp1agS7gvQnXp2XskWjFlqxcX0TM62RHcQDaH +38dq6SZeWYp34+hInDEW+j6RscrJo+KfziFTowI2MMtSAuXaMl3Dxeb57hHHi8lE +HoSTGEq0n+USZGnQJoViAbbJAh2+g1G7XNr4rRVqmfeSVPc0W+m/6imBEtRTkZaz +kVrd/pBzKPswRrXKCAfHcXLJZtM0l/aM9BhK4dA9WkW2aacp+yPOiNgSnABIqKYP +szuSjXEOdMWLyEz59JuOuDxp7W87UC9Y7cSw0BwbagzivESq2M0UXZR4Yb8Obtoq +vC8MC3GmsxY/nOb5zJ9TNeIDoKAYv7vxvvTWjIcNQvcGufFt7QSUqP620wbGQGHf +nZ3zVHbOUzoBppJB7ASjjw2i1QnK1sua8e9DXcCrpUHPXFNwcMmIpi3Ua2FzUCaG +YQ5fG8Ir4ozVu53BA0K6lNpfqbDKzE0K70dpAy8i+/Eozr9dUGWokG2zdLAIx6yo +0es+nPxdGoMuK8u180SdOqcXYZaicdNwlhVNt0xz7hlcxVs+Qf6sdWA7G2POAN3a +CJBitOUt7kinaxeZVL6HSuOpXgRM6xBtVNbv8ejyYhbLgGvtPe31HzClrkvJE+2K +AQHJuFFYwGY6sWZLxNUxAmLpdIQM201GLQIDAQABo0IwQDAdBgNVHQ4EFgQU0p+I +36HNLL3s9TsBAZMzJ7LrYEswDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMB +Af8wDQYJKoZIhvcNAQEMBQADggIBADLKgLOdPVQG3dLSLvCkASELZ0jKbY7gyKoN +qo0hV4/GPnrK21HUUrPUloSlWGB/5QuOH/XcChWB5Tu2tyIvCZwTFrFsDDUIbatj +cu3cvuzHV+YwIHHW1xDBE1UBjCpD5EHxzzp6U5LOogMFDTjfArsQLtk70pt6wKGm ++LUx5vR1yblTmXVHIloUFcd4G7ad6Qz4G3bxhYTeodoS76TiEJd6eN4MUZeoIUCL +hr0N8F5OSza7OyAfikJW4Qsav3vQIkMsRIz75Sq0bBwcupTgE34h5prCy8VCZLQe +lHsIJchxzIdFV4XTnyliIoNRlwAYl3dqmJLJfGBs32x9SuRwTMKeuB330DTHD8z7 +p/8Dvq1wkNoL3chtl1+afwkyQf3NosxabUzyqkn+Zvjp2DXrDige7kgvOtB5CTh8 +piKCk5XQA76+AqAF3SAi428diDRgxuYKuQl1C/AH6GmWNcf7I4GOODm4RStDeKLR +LBT/DShycpWbXgnbiUSYqqFJu3FS8r/2/yehNq+4tneI3TqkbZs0kNwUXTC/t+sX +5Ie3cdCh13cV1ELX8vMxmV2b3RZtP+oGI/hGoiLtk/bdmuYqh7GYVPEi92tF4+KO +dh2ajcQGjTa3FPOdVGm3jjzVpG2Tgbet9r1ke8LJaDmgkpzNNIaRkPpkUZ3+/uul +9XXeifdy +-----END CERTIFICATE----- + +# Issuer: CN=AC RAIZ FNMT-RCM SERVIDORES SEGUROS O=FNMT-RCM OU=Ceres +# Subject: CN=AC RAIZ FNMT-RCM SERVIDORES SEGUROS O=FNMT-RCM OU=Ceres +# Label: "AC RAIZ FNMT-RCM SERVIDORES SEGUROS" +# Serial: 131542671362353147877283741781055151509 +# MD5 Fingerprint: 19:36:9c:52:03:2f:d2:d1:bb:23:cc:dd:1e:12:55:bb +# SHA1 Fingerprint: 62:ff:d9:9e:c0:65:0d:03:ce:75:93:d2:ed:3f:2d:32:c9:e3:e5:4a +# SHA256 Fingerprint: 55:41:53:b1:3d:2c:f9:dd:b7:53:bf:be:1a:4e:0a:e0:8d:0a:a4:18:70:58:fe:60:a2:b8:62:b2:e4:b8:7b:cb +-----BEGIN CERTIFICATE----- +MIICbjCCAfOgAwIBAgIQYvYybOXE42hcG2LdnC6dlTAKBggqhkjOPQQDAzB4MQsw +CQYDVQQGEwJFUzERMA8GA1UECgwIRk5NVC1SQ00xDjAMBgNVBAsMBUNlcmVzMRgw +FgYDVQRhDA9WQVRFUy1RMjgyNjAwNEoxLDAqBgNVBAMMI0FDIFJBSVogRk5NVC1S +Q00gU0VSVklET1JFUyBTRUdVUk9TMB4XDTE4MTIyMDA5MzczM1oXDTQzMTIyMDA5 +MzczM1oweDELMAkGA1UEBhMCRVMxETAPBgNVBAoMCEZOTVQtUkNNMQ4wDAYDVQQL +DAVDZXJlczEYMBYGA1UEYQwPVkFURVMtUTI4MjYwMDRKMSwwKgYDVQQDDCNBQyBS +QUlaIEZOTVQtUkNNIFNFUlZJRE9SRVMgU0VHVVJPUzB2MBAGByqGSM49AgEGBSuB +BAAiA2IABPa6V1PIyqvfNkpSIeSX0oNnnvBlUdBeh8dHsVnyV0ebAAKTRBdp20LH +sbI6GA60XYyzZl2hNPk2LEnb80b8s0RpRBNm/dfF/a82Tc4DTQdxz69qBdKiQ1oK +Um8BA06Oi6NCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD +VR0OBBYEFAG5L++/EYZg8k/QQW6rcx/n0m5JMAoGCCqGSM49BAMDA2kAMGYCMQCu +SuMrQMN0EfKVrRYj3k4MGuZdpSRea0R7/DjiT8ucRRcRTBQnJlU5dUoDzBOQn5IC +MQD6SmxgiHPz7riYYqnOK8LZiqZwMR2vsJRM60/G49HzYqc8/5MuB1xJAWdpEgJy +v+c= +-----END CERTIFICATE----- + +# Issuer: CN=GlobalSign Root R46 O=GlobalSign nv-sa +# Subject: CN=GlobalSign Root R46 O=GlobalSign nv-sa +# Label: "GlobalSign Root R46" +# Serial: 1552617688466950547958867513931858518042577 +# MD5 Fingerprint: c4:14:30:e4:fa:66:43:94:2a:6a:1b:24:5f:19:d0:ef +# SHA1 Fingerprint: 53:a2:b0:4b:ca:6b:d6:45:e6:39:8a:8e:c4:0d:d2:bf:77:c3:a2:90 +# SHA256 Fingerprint: 4f:a3:12:6d:8d:3a:11:d1:c4:85:5a:4f:80:7c:ba:d6:cf:91:9d:3a:5a:88:b0:3b:ea:2c:63:72:d9:3c:40:c9 +-----BEGIN CERTIFICATE----- +MIIFWjCCA0KgAwIBAgISEdK7udcjGJ5AXwqdLdDfJWfRMA0GCSqGSIb3DQEBDAUA +MEYxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRwwGgYD +VQQDExNHbG9iYWxTaWduIFJvb3QgUjQ2MB4XDTE5MDMyMDAwMDAwMFoXDTQ2MDMy +MDAwMDAwMFowRjELMAkGA1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYt +c2ExHDAaBgNVBAMTE0dsb2JhbFNpZ24gUm9vdCBSNDYwggIiMA0GCSqGSIb3DQEB +AQUAA4ICDwAwggIKAoICAQCsrHQy6LNl5brtQyYdpokNRbopiLKkHWPd08EsCVeJ +OaFV6Wc0dwxu5FUdUiXSE2te4R2pt32JMl8Nnp8semNgQB+msLZ4j5lUlghYruQG +vGIFAha/r6gjA7aUD7xubMLL1aa7DOn2wQL7Id5m3RerdELv8HQvJfTqa1VbkNud +316HCkD7rRlr+/fKYIje2sGP1q7Vf9Q8g+7XFkyDRTNrJ9CG0Bwta/OrffGFqfUo +0q3v84RLHIf8E6M6cqJaESvWJ3En7YEtbWaBkoe0G1h6zD8K+kZPTXhc+CtI4wSE +y132tGqzZfxCnlEmIyDLPRT5ge1lFgBPGmSXZgjPjHvjK8Cd+RTyG/FWaha/LIWF +zXg4mutCagI0GIMXTpRW+LaCtfOW3T3zvn8gdz57GSNrLNRyc0NXfeD412lPFzYE ++cCQYDdF3uYM2HSNrpyibXRdQr4G9dlkbgIQrImwTDsHTUB+JMWKmIJ5jqSngiCN +I/onccnfxkF0oE32kRbcRoxfKWMxWXEM2G/CtjJ9++ZdU6Z+Ffy7dXxd7Pj2Fxzs +x2sZy/N78CsHpdlseVR2bJ0cpm4O6XkMqCNqo98bMDGfsVR7/mrLZqrcZdCinkqa +ByFrgY/bxFn63iLABJzjqls2k+g9vXqhnQt2sQvHnf3PmKgGwvgqo6GDoLclcqUC +4wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV +HQ4EFgQUA1yrc4GHqMywptWU4jaWSf8FmSwwDQYJKoZIhvcNAQEMBQADggIBAHx4 +7PYCLLtbfpIrXTncvtgdokIzTfnvpCo7RGkerNlFo048p9gkUbJUHJNOxO97k4Vg +JuoJSOD1u8fpaNK7ajFxzHmuEajwmf3lH7wvqMxX63bEIaZHU1VNaL8FpO7XJqti +2kM3S+LGteWygxk6x9PbTZ4IevPuzz5i+6zoYMzRx6Fcg0XERczzF2sUyQQCPtIk +pnnpHs6i58FZFZ8d4kuaPp92CC1r2LpXFNqD6v6MVenQTqnMdzGxRBF6XLE+0xRF +FRhiJBPSy03OXIPBNvIQtQ6IbbjhVp+J3pZmOUdkLG5NrmJ7v2B0GbhWrJKsFjLt +rWhV/pi60zTe9Mlhww6G9kuEYO4Ne7UyWHmRVSyBQ7N0H3qqJZ4d16GLuc1CLgSk +ZoNNiTW2bKg2SnkheCLQQrzRQDGQob4Ez8pn7fXwgNNgyYMqIgXQBztSvwyeqiv5 +u+YfjyW6hY0XHgL+XVAEV8/+LbzvXMAaq7afJMbfc2hIkCwU9D9SGuTSyxTDYWnP +4vkYxboznxSjBF25cfe1lNj2M8FawTSLfJvdkzrnE6JwYZ+vj+vYxXX4M2bUdGc6 +N3ec592kD3ZDZopD8p/7DEJ4Y9HiD2971KE9dJeFt0g5QdYg/NA6s/rob8SKunE3 +vouXsXgxT7PntgMTzlSdriVZzH81Xwj3QEUxeCp6 +-----END CERTIFICATE----- + +# Issuer: CN=GlobalSign Root E46 O=GlobalSign nv-sa +# Subject: CN=GlobalSign Root E46 O=GlobalSign nv-sa +# Label: "GlobalSign Root E46" +# Serial: 1552617690338932563915843282459653771421763 +# MD5 Fingerprint: b5:b8:66:ed:de:08:83:e3:c9:e2:01:34:06:ac:51:6f +# SHA1 Fingerprint: 39:b4:6c:d5:fe:80:06:eb:e2:2f:4a:bb:08:33:a0:af:db:b9:dd:84 +# SHA256 Fingerprint: cb:b9:c4:4d:84:b8:04:3e:10:50:ea:31:a6:9f:51:49:55:d7:bf:d2:e2:c6:b4:93:01:01:9a:d6:1d:9f:50:58 +-----BEGIN CERTIFICATE----- +MIICCzCCAZGgAwIBAgISEdK7ujNu1LzmJGjFDYQdmOhDMAoGCCqGSM49BAMDMEYx +CzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRwwGgYDVQQD +ExNHbG9iYWxTaWduIFJvb3QgRTQ2MB4XDTE5MDMyMDAwMDAwMFoXDTQ2MDMyMDAw +MDAwMFowRjELMAkGA1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2Ex +HDAaBgNVBAMTE0dsb2JhbFNpZ24gUm9vdCBFNDYwdjAQBgcqhkjOPQIBBgUrgQQA +IgNiAAScDrHPt+ieUnd1NPqlRqetMhkytAepJ8qUuwzSChDH2omwlwxwEwkBjtjq +R+q+soArzfwoDdusvKSGN+1wCAB16pMLey5SnCNoIwZD7JIvU4Tb+0cUB+hflGdd +yXqBPCCjQjBAMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud +DgQWBBQxCpCPtsad0kRLgLWi5h+xEk8blTAKBggqhkjOPQQDAwNoADBlAjEA31SQ +7Zvvi5QCkxeCmb6zniz2C5GMn0oUsfZkvLtoURMMA/cVi4RguYv/Uo7njLwcAjA8 ++RHUjE7AwWHCFUyqqx0LMV87HOIAl0Qx5v5zli/altP+CAezNIm8BZ/3Hobui3A= +-----END CERTIFICATE----- + +# Issuer: CN=GLOBALTRUST 2020 O=e-commerce monitoring GmbH +# Subject: CN=GLOBALTRUST 2020 O=e-commerce monitoring GmbH +# Label: "GLOBALTRUST 2020" +# Serial: 109160994242082918454945253 +# MD5 Fingerprint: 8a:c7:6f:cb:6d:e3:cc:a2:f1:7c:83:fa:0e:78:d7:e8 +# SHA1 Fingerprint: d0:67:c1:13:51:01:0c:aa:d0:c7:6a:65:37:31:16:26:4f:53:71:a2 +# SHA256 Fingerprint: 9a:29:6a:51:82:d1:d4:51:a2:e3:7f:43:9b:74:da:af:a2:67:52:33:29:f9:0f:9a:0d:20:07:c3:34:e2:3c:9a +-----BEGIN CERTIFICATE----- +MIIFgjCCA2qgAwIBAgILWku9WvtPilv6ZeUwDQYJKoZIhvcNAQELBQAwTTELMAkG +A1UEBhMCQVQxIzAhBgNVBAoTGmUtY29tbWVyY2UgbW9uaXRvcmluZyBHbWJIMRkw +FwYDVQQDExBHTE9CQUxUUlVTVCAyMDIwMB4XDTIwMDIxMDAwMDAwMFoXDTQwMDYx +MDAwMDAwMFowTTELMAkGA1UEBhMCQVQxIzAhBgNVBAoTGmUtY29tbWVyY2UgbW9u +aXRvcmluZyBHbWJIMRkwFwYDVQQDExBHTE9CQUxUUlVTVCAyMDIwMIICIjANBgkq +hkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAri5WrRsc7/aVj6B3GyvTY4+ETUWiD59b +RatZe1E0+eyLinjF3WuvvcTfk0Uev5E4C64OFudBc/jbu9G4UeDLgztzOG53ig9Z +YybNpyrOVPu44sB8R85gfD+yc/LAGbaKkoc1DZAoouQVBGM+uq/ufF7MpotQsjj3 +QWPKzv9pj2gOlTblzLmMCcpL3TGQlsjMH/1WljTbjhzqLL6FLmPdqqmV0/0plRPw +yJiT2S0WR5ARg6I6IqIoV6Lr/sCMKKCmfecqQjuCgGOlYx8ZzHyyZqjC0203b+J+ +BlHZRYQfEs4kUmSFC0iAToexIiIwquuuvuAC4EDosEKAA1GqtH6qRNdDYfOiaxaJ +SaSjpCuKAsR49GiKweR6NrFvG5Ybd0mN1MkGco/PU+PcF4UgStyYJ9ORJitHHmkH +r96i5OTUawuzXnzUJIBHKWk7buis/UDr2O1xcSvy6Fgd60GXIsUf1DnQJ4+H4xj0 +4KlGDfV0OoIu0G4skaMxXDtG6nsEEFZegB31pWXogvziB4xiRfUg3kZwhqG8k9Me +dKZssCz3AwyIDMvUclOGvGBG85hqwvG/Q/lwIHfKN0F5VVJjjVsSn8VoxIidrPIw +q7ejMZdnrY8XD2zHc+0klGvIg5rQmjdJBKuxFshsSUktq6HQjJLyQUp5ISXbY9e2 +nKd+Qmn7OmMCAwEAAaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +AQYwHQYDVR0OBBYEFNwuH9FhN3nkq9XVsxJxaD1qaJwiMB8GA1UdIwQYMBaAFNwu +H9FhN3nkq9XVsxJxaD1qaJwiMA0GCSqGSIb3DQEBCwUAA4ICAQCR8EICaEDuw2jA +VC/f7GLDw56KoDEoqoOOpFaWEhCGVrqXctJUMHytGdUdaG/7FELYjQ7ztdGl4wJC +XtzoRlgHNQIw4Lx0SsFDKv/bGtCwr2zD/cuz9X9tAy5ZVp0tLTWMstZDFyySCstd +6IwPS3BD0IL/qMy/pJTAvoe9iuOTe8aPmxadJ2W8esVCgmxcB9CpwYhgROmYhRZf ++I/KARDOJcP5YBugxZfD0yyIMaK9MOzQ0MAS8cE54+X1+NZK3TTN+2/BT+MAi1bi +kvcoskJ3ciNnxz8RFbLEAwW+uxF7Cr+obuf/WEPPm2eggAe2HcqtbepBEX4tdJP7 +wry+UUTF72glJ4DjyKDUEuzZpTcdN3y0kcra1LGWge9oXHYQSa9+pTeAsRxSvTOB +TI/53WXZFM2KJVj04sWDpQmQ1GwUY7VA3+vA/MRYfg0UFodUJ25W5HCEuGwyEn6C +MUO+1918oa2u1qsgEu8KwxCMSZY13At1XrFP1U80DhEgB3VDRemjEdqso5nCtnkn +4rnvyOL2NSl6dPrFf4IFYqYK6miyeUcGbvJXqBUzxvd4Sj1Ce2t+/vdG6tHrju+I +aFvowdlxfv1k7/9nR4hYJS8+hge9+6jlgqispdNpQ80xiEmEU5LAsTkbOYMBMMTy +qfrQA71yN2BWHzZ8vTmR9W0Nv3vXkg== +-----END CERTIFICATE----- + +# Issuer: CN=ANF Secure Server Root CA O=ANF Autoridad de Certificacion OU=ANF CA Raiz +# Subject: CN=ANF Secure Server Root CA O=ANF Autoridad de Certificacion OU=ANF CA Raiz +# Label: "ANF Secure Server Root CA" +# Serial: 996390341000653745 +# MD5 Fingerprint: 26:a6:44:5a:d9:af:4e:2f:b2:1d:b6:65:b0:4e:e8:96 +# SHA1 Fingerprint: 5b:6e:68:d0:cc:15:b6:a0:5f:1e:c1:5f:ae:02:fc:6b:2f:5d:6f:74 +# SHA256 Fingerprint: fb:8f:ec:75:91:69:b9:10:6b:1e:51:16:44:c6:18:c5:13:04:37:3f:6c:06:43:08:8d:8b:ef:fd:1b:99:75:99 +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- + +# Issuer: CN=Certum EC-384 CA O=Asseco Data Systems S.A. OU=Certum Certification Authority +# Subject: CN=Certum EC-384 CA O=Asseco Data Systems S.A. OU=Certum Certification Authority +# Label: "Certum EC-384 CA" +# Serial: 160250656287871593594747141429395092468 +# MD5 Fingerprint: b6:65:b3:96:60:97:12:a1:ec:4e:e1:3d:a3:c6:c9:f1 +# SHA1 Fingerprint: f3:3e:78:3c:ac:df:f4:a2:cc:ac:67:55:69:56:d7:e5:16:3c:e1:ed +# SHA256 Fingerprint: 6b:32:80:85:62:53:18:aa:50:d1:73:c9:8d:8b:da:09:d5:7e:27:41:3d:11:4c:f7:87:a0:f5:d0:6c:03:0c:f6 +-----BEGIN CERTIFICATE----- +MIICZTCCAeugAwIBAgIQeI8nXIESUiClBNAt3bpz9DAKBggqhkjOPQQDAzB0MQsw +CQYDVQQGEwJQTDEhMB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBTLkEuMScw +JQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxGTAXBgNVBAMT +EENlcnR1bSBFQy0zODQgQ0EwHhcNMTgwMzI2MDcyNDU0WhcNNDMwMzI2MDcyNDU0 +WjB0MQswCQYDVQQGEwJQTDEhMB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBT +LkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxGTAX +BgNVBAMTEENlcnR1bSBFQy0zODQgQ0EwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAATE +KI6rGFtqvm5kN2PkzeyrOvfMobgOgknXhimfoZTy42B4mIF4Bk3y7JoOV2CDn7Tm +Fy8as10CW4kjPMIRBSqniBMY81CE1700LCeJVf/OTOffph8oxPBUw7l8t1Ot68Kj +QjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI0GZnQkdjrzife81r1HfS+8 +EF9LMA4GA1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNoADBlAjADVS2m5hjEfO/J +UG7BJw+ch69u1RsIGL2SKcHvlJF40jocVYli5RsJHrpka/F2tNQCMQC0QoSZ/6vn +nvuRlydd3LBbMHHOXjgaatkl5+r3YZJW+OraNsKHZZYuciUvf9/DE8k= +-----END CERTIFICATE----- + +# Issuer: CN=Certum Trusted Root CA O=Asseco Data Systems S.A. OU=Certum Certification Authority +# Subject: CN=Certum Trusted Root CA O=Asseco Data Systems S.A. OU=Certum Certification Authority +# Label: "Certum Trusted Root CA" +# Serial: 40870380103424195783807378461123655149 +# MD5 Fingerprint: 51:e1:c2:e7:fe:4c:84:af:59:0e:2f:f4:54:6f:ea:29 +# SHA1 Fingerprint: c8:83:44:c0:18:ae:9f:cc:f1:87:b7:8f:22:d1:c5:d7:45:84:ba:e5 +# SHA256 Fingerprint: fe:76:96:57:38:55:77:3e:37:a9:5e:7a:d4:d9:cc:96:c3:01:57:c1:5d:31:76:5b:a9:b1:57:04:e1:ae:78:fd +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- + +# Issuer: CN=TunTrust Root CA O=Agence Nationale de Certification Electronique +# Subject: CN=TunTrust Root CA O=Agence Nationale de Certification Electronique +# Label: "TunTrust Root CA" +# Serial: 108534058042236574382096126452369648152337120275 +# MD5 Fingerprint: 85:13:b9:90:5b:36:5c:b6:5e:b8:5a:f8:e0:31:57:b4 +# SHA1 Fingerprint: cf:e9:70:84:0f:e0:73:0f:9d:f6:0c:7f:2c:4b:ee:20:46:34:9c:bb +# SHA256 Fingerprint: 2e:44:10:2a:b5:8c:b8:54:19:45:1c:8e:19:d9:ac:f3:66:2c:af:bc:61:4b:6a:53:96:0a:30:f7:d0:e2:eb:41 +-----BEGIN CERTIFICATE----- +MIIFszCCA5ugAwIBAgIUEwLV4kBMkkaGFmddtLu7sms+/BMwDQYJKoZIhvcNAQEL +BQAwYTELMAkGA1UEBhMCVE4xNzA1BgNVBAoMLkFnZW5jZSBOYXRpb25hbGUgZGUg +Q2VydGlmaWNhdGlvbiBFbGVjdHJvbmlxdWUxGTAXBgNVBAMMEFR1blRydXN0IFJv +b3QgQ0EwHhcNMTkwNDI2MDg1NzU2WhcNNDQwNDI2MDg1NzU2WjBhMQswCQYDVQQG +EwJUTjE3MDUGA1UECgwuQWdlbmNlIE5hdGlvbmFsZSBkZSBDZXJ0aWZpY2F0aW9u +IEVsZWN0cm9uaXF1ZTEZMBcGA1UEAwwQVHVuVHJ1c3QgUm9vdCBDQTCCAiIwDQYJ +KoZIhvcNAQEBBQADggIPADCCAgoCggIBAMPN0/y9BFPdDCA61YguBUtB9YOCfvdZ +n56eY+hz2vYGqU8ftPkLHzmMmiDQfgbU7DTZhrx1W4eI8NLZ1KMKsmwb60ksPqxd +2JQDoOw05TDENX37Jk0bbjBU2PWARZw5rZzJJQRNmpA+TkBuimvNKWfGzC3gdOgF +VwpIUPp6Q9p+7FuaDmJ2/uqdHYVy7BG7NegfJ7/Boce7SBbdVtfMTqDhuazb1YMZ +GoXRlJfXyqNlC/M4+QKu3fZnz8k/9YosRxqZbwUN/dAdgjH8KcwAWJeRTIAAHDOF +li/LQcKLEITDCSSJH7UP2dl3RxiSlGBcx5kDPP73lad9UKGAwqmDrViWVSHbhlnU +r8a83YFuB9tgYv7sEG7aaAH0gxupPqJbI9dkxt/con3YS7qC0lH4Zr8GRuR5KiY2 +eY8fTpkdso8MDhz/yV3A/ZAQprE38806JG60hZC/gLkMjNWb1sjxVj8agIl6qeIb +MlEsPvLfe/ZdeikZjuXIvTZxi11Mwh0/rViizz1wTaZQmCXcI/m4WEEIcb9PuISg +jwBUFfyRbVinljvrS5YnzWuioYasDXxU5mZMZl+QviGaAkYt5IPCgLnPSz7ofzwB +7I9ezX/SKEIBlYrilz0QIX32nRzFNKHsLA4KUiwSVXAkPcvCFDVDXSdOvsC9qnyW +5/yeYa1E0wCXAgMBAAGjYzBhMB0GA1UdDgQWBBQGmpsfU33x9aTI04Y+oXNZtPdE +ITAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFAaamx9TffH1pMjThj6hc1m0 +90QhMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAqgVutt0Vyb+z +xiD2BkewhpMl0425yAA/l/VSJ4hxyXT968pk21vvHl26v9Hr7lxpuhbI87mP0zYu +QEkHDVneixCwSQXi/5E/S7fdAo74gShczNxtr18UnH1YeA32gAm56Q6XKRm4t+v4 +FstVEuTGfbvE7Pi1HE4+Z7/FXxttbUcoqgRYYdZ2vyJ/0Adqp2RT8JeNnYA/u8EH +22Wv5psymsNUk8QcCMNE+3tjEUPRahphanltkE8pjkcFwRJpadbGNjHh/PqAulxP +xOu3Mqz4dWEX1xAZufHSCe96Qp1bWgvUxpVOKs7/B9dPfhgGiPEZtdmYu65xxBzn +dFlY7wyJz4sfdZMaBBSSSFCp61cpABbjNhzI+L/wM9VBD8TMPN3pM0MBkRArHtG5 +Xc0yGYuPjCB31yLEQtyEFpslbei0VXF/sHyz03FJuc9SpAQ/3D2gu68zngowYI7b +nV2UqL1g52KAdoGDDIzMMEZJ4gzSqK/rYXHv5yJiqfdcZGyfFoxnNidF9Ql7v/YQ +CvGwjVRDjAS6oz/v4jXH+XTgbzRB0L9zZVcg+ZtnemZoJE6AZb0QmQZZ8mWvuMZH +u/2QeItBcy6vVR/cO5JyboTT0GFMDcx2V+IthSIVNg3rAZ3r2OvEhJn7wAzMMujj +d9qDRIueVSjAi1jTkD5OGwDxFa2DK5o= +-----END CERTIFICATE----- + +# Issuer: CN=HARICA TLS RSA Root CA 2021 O=Hellenic Academic and Research Institutions CA +# Subject: CN=HARICA TLS RSA Root CA 2021 O=Hellenic Academic and Research Institutions CA +# Label: "HARICA TLS RSA Root CA 2021" +# Serial: 76817823531813593706434026085292783742 +# MD5 Fingerprint: 65:47:9b:58:86:dd:2c:f0:fc:a2:84:1f:1e:96:c4:91 +# SHA1 Fingerprint: 02:2d:05:82:fa:88:ce:14:0c:06:79:de:7f:14:10:e9:45:d7:a5:6d +# SHA256 Fingerprint: d9:5d:0e:8e:da:79:52:5b:f9:be:b1:1b:14:d2:10:0d:32:94:98:5f:0c:62:d9:fa:bd:9c:d9:99:ec:cb:7b:1d +-----BEGIN CERTIFICATE----- +MIIFpDCCA4ygAwIBAgIQOcqTHO9D88aOk8f0ZIk4fjANBgkqhkiG9w0BAQsFADBs +MQswCQYDVQQGEwJHUjE3MDUGA1UECgwuSGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJl +c2VhcmNoIEluc3RpdHV0aW9ucyBDQTEkMCIGA1UEAwwbSEFSSUNBIFRMUyBSU0Eg +Um9vdCBDQSAyMDIxMB4XDTIxMDIxOTEwNTUzOFoXDTQ1MDIxMzEwNTUzN1owbDEL +MAkGA1UEBhMCR1IxNzA1BgNVBAoMLkhlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNl +YXJjaCBJbnN0aXR1dGlvbnMgQ0ExJDAiBgNVBAMMG0hBUklDQSBUTFMgUlNBIFJv +b3QgQ0EgMjAyMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAIvC569l +mwVnlskNJLnQDmT8zuIkGCyEf3dRywQRNrhe7Wlxp57kJQmXZ8FHws+RFjZiPTgE +4VGC/6zStGndLuwRo0Xua2s7TL+MjaQenRG56Tj5eg4MmOIjHdFOY9TnuEFE+2uv +a9of08WRiFukiZLRgeaMOVig1mlDqa2YUlhu2wr7a89o+uOkXjpFc5gH6l8Cct4M +pbOfrqkdtx2z/IpZ525yZa31MJQjB/OCFks1mJxTuy/K5FrZx40d/JiZ+yykgmvw +Kh+OC19xXFyuQnspiYHLA6OZyoieC0AJQTPb5lh6/a6ZcMBaD9YThnEvdmn8kN3b +LW7R8pv1GmuebxWMevBLKKAiOIAkbDakO/IwkfN4E8/BPzWr8R0RI7VDIp4BkrcY +AuUR0YLbFQDMYTfBKnya4dC6s1BG7oKsnTH4+yPiAwBIcKMJJnkVU2DzOFytOOqB +AGMUuTNe3QvboEUHGjMJ+E20pwKmafTCWQWIZYVWrkvL4N48fS0ayOn7H6NhStYq +E613TBoYm5EPWNgGVMWX+Ko/IIqmhaZ39qb8HOLubpQzKoNQhArlT4b4UEV4AIHr +W2jjJo3Me1xR9BQsQL4aYB16cmEdH2MtiKrOokWQCPxrvrNQKlr9qEgYRtaQQJKQ +CoReaDH46+0N0x3GfZkYVVYnZS6NRcUk7M7jAgMBAAGjQjBAMA8GA1UdEwEB/wQF +MAMBAf8wHQYDVR0OBBYEFApII6ZgpJIKM+qTW8VX6iVNvRLuMA4GA1UdDwEB/wQE +AwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAPpBIqm5iFSVmewzVjIuJndftTgfvnNAU +X15QvWiWkKQUEapobQk1OUAJ2vQJLDSle1mESSmXdMgHHkdt8s4cUCbjnj1AUz/3 +f5Z2EMVGpdAgS1D0NTsY9FVqQRtHBmg8uwkIYtlfVUKqrFOFrJVWNlar5AWMxaja +H6NpvVMPxP/cyuN+8kyIhkdGGvMA9YCRotxDQpSbIPDRzbLrLFPCU3hKTwSUQZqP +JzLB5UkZv/HywouoCjkxKLR9YjYsTewfM7Z+d21+UPCfDtcRj88YxeMn/ibvBZ3P +zzfF0HvaO7AWhAw6k9a+F9sPPg4ZeAnHqQJyIkv3N3a6dcSFA1pj1bF1BcK5vZSt +jBWZp5N99sXzqnTPBIWUmAD04vnKJGW/4GKvyMX6ssmeVkjaef2WdhW+o45WxLM0 +/L5H9MG0qPzVMIho7suuyWPEdr6sOBjhXlzPrjoiUevRi7PzKzMHVIf6tLITe7pT +BGIBnfHAT+7hOtSLIBD6Alfm78ELt5BGnBkpjNxvoEppaZS3JGWg/6w/zgH7IS79 +aPib8qXPMThcFarmlwDB31qlpzmq6YR/PFGoOtmUW4y/Twhx5duoXNTSpv4Ao8YW +xw/ogM4cKGR0GQjTQuPOAF1/sdwTsOEFy9EgqoZ0njnnkf3/W9b3raYvAwtt41dU +63ZTGI0RmLo= +-----END CERTIFICATE----- + +# Issuer: CN=HARICA TLS ECC Root CA 2021 O=Hellenic Academic and Research Institutions CA +# Subject: CN=HARICA TLS ECC Root CA 2021 O=Hellenic Academic and Research Institutions CA +# Label: "HARICA TLS ECC Root CA 2021" +# Serial: 137515985548005187474074462014555733966 +# MD5 Fingerprint: ae:f7:4c:e5:66:35:d1:b7:9b:8c:22:93:74:d3:4b:b0 +# SHA1 Fingerprint: bc:b0:c1:9d:e9:98:92:70:19:38:57:e9:8d:a7:b4:5d:6e:ee:01:48 +# SHA256 Fingerprint: 3f:99:cc:47:4a:cf:ce:4d:fe:d5:87:94:66:5e:47:8d:15:47:73:9f:2e:78:0f:1b:b4:ca:9b:13:30:97:d4:01 +-----BEGIN CERTIFICATE----- +MIICVDCCAdugAwIBAgIQZ3SdjXfYO2rbIvT/WeK/zjAKBggqhkjOPQQDAzBsMQsw +CQYDVQQGEwJHUjE3MDUGA1UECgwuSGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2Vh +cmNoIEluc3RpdHV0aW9ucyBDQTEkMCIGA1UEAwwbSEFSSUNBIFRMUyBFQ0MgUm9v +dCBDQSAyMDIxMB4XDTIxMDIxOTExMDExMFoXDTQ1MDIxMzExMDEwOVowbDELMAkG +A1UEBhMCR1IxNzA1BgNVBAoMLkhlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJj +aCBJbnN0aXR1dGlvbnMgQ0ExJDAiBgNVBAMMG0hBUklDQSBUTFMgRUNDIFJvb3Qg +Q0EgMjAyMTB2MBAGByqGSM49AgEGBSuBBAAiA2IABDgI/rGgltJ6rK9JOtDA4MM7 +KKrxcm1lAEeIhPyaJmuqS7psBAqIXhfyVYf8MLA04jRYVxqEU+kw2anylnTDUR9Y +STHMmE5gEYd103KUkE+bECUqqHgtvpBBWJAVcqeht6NCMEAwDwYDVR0TAQH/BAUw +AwEB/zAdBgNVHQ4EFgQUyRtTgRL+BNUW0aq8mm+3oJUZbsowDgYDVR0PAQH/BAQD +AgGGMAoGCCqGSM49BAMDA2cAMGQCMBHervjcToiwqfAircJRQO9gcS3ujwLEXQNw +SaSS6sUUiHCm0w2wqsosQJz76YJumgIwK0eaB8bRwoF8yguWGEEbo/QwCZ61IygN +nxS2PFOiTAZpffpskcYqSUXm7LcT4Tps +-----END CERTIFICATE----- diff --git a/venv/Lib/site-packages/pip/_vendor/certifi/core.py b/venv/Lib/site-packages/pip/_vendor/certifi/core.py new file mode 100644 index 0000000..b8140cf --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/certifi/core.py @@ -0,0 +1,76 @@ +# -*- coding: utf-8 -*- + +""" +certifi.py +~~~~~~~~~~ + +This module returns the installation location of cacert.pem or its contents. +""" +import os + + +class _PipPatchedCertificate(Exception): + pass + + +try: + # Return a certificate file on disk for a standalone pip zipapp running in + # an isolated build environment to use. Passing --cert to the standalone + # pip does not work since requests calls where() unconditionally on import. + _PIP_STANDALONE_CERT = os.environ.get("_PIP_STANDALONE_CERT") + if _PIP_STANDALONE_CERT: + def where(): + return _PIP_STANDALONE_CERT + raise _PipPatchedCertificate() + + from importlib.resources import path as get_path, read_text + + _CACERT_CTX = None + _CACERT_PATH = None + + def where(): + # This is slightly terrible, but we want to delay extracting the file + # in cases where we're inside of a zipimport situation until someone + # actually calls where(), but we don't want to re-extract the file + # on every call of where(), so we'll do it once then store it in a + # global variable. + global _CACERT_CTX + global _CACERT_PATH + if _CACERT_PATH is None: + # This is slightly janky, the importlib.resources API wants you to + # manage the cleanup of this file, so it doesn't actually return a + # path, it returns a context manager that will give you the path + # when you enter it and will do any cleanup when you leave it. In + # the common case of not needing a temporary file, it will just + # return the file system location and the __exit__() is a no-op. + # + # We also have to hold onto the actual context manager, because + # it will do the cleanup whenever it gets garbage collected, so + # we will also store that at the global level as well. + _CACERT_CTX = get_path("pip._vendor.certifi", "cacert.pem") + _CACERT_PATH = str(_CACERT_CTX.__enter__()) + + return _CACERT_PATH + +except _PipPatchedCertificate: + pass + +except ImportError: + # This fallback will work for Python versions prior to 3.7 that lack the + # importlib.resources module but relies on the existing `where` function + # so won't address issues with environments like PyOxidizer that don't set + # __file__ on modules. + def read_text(_module, _path, encoding="ascii"): + with open(where(), "r", encoding=encoding) as data: + return data.read() + + # If we don't have importlib.resources, then we will just do the old logic + # of assuming we're on the filesystem and munge the path directly. + def where(): + f = os.path.dirname(__file__) + + return os.path.join(f, "cacert.pem") + + +def contents(): + return read_text("certifi", "cacert.pem", encoding="ascii") diff --git a/venv/Lib/site-packages/pip/_vendor/chardet/__init__.py b/venv/Lib/site-packages/pip/_vendor/chardet/__init__.py new file mode 100644 index 0000000..80ad254 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/chardet/__init__.py @@ -0,0 +1,83 @@ +######################## BEGIN LICENSE BLOCK ######################## +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + + +from .universaldetector import UniversalDetector +from .enums import InputState +from .version import __version__, VERSION + + +__all__ = ['UniversalDetector', 'detect', 'detect_all', '__version__', 'VERSION'] + + +def detect(byte_str): + """ + Detect the encoding of the given byte string. + + :param byte_str: The byte sequence to examine. + :type byte_str: ``bytes`` or ``bytearray`` + """ + if not isinstance(byte_str, bytearray): + if not isinstance(byte_str, bytes): + raise TypeError('Expected object of type bytes or bytearray, got: ' + '{}'.format(type(byte_str))) + else: + byte_str = bytearray(byte_str) + detector = UniversalDetector() + detector.feed(byte_str) + return detector.close() + + +def detect_all(byte_str): + """ + Detect all the possible encodings of the given byte string. + + :param byte_str: The byte sequence to examine. + :type byte_str: ``bytes`` or ``bytearray`` + """ + if not isinstance(byte_str, bytearray): + if not isinstance(byte_str, bytes): + raise TypeError('Expected object of type bytes or bytearray, got: ' + '{}'.format(type(byte_str))) + else: + byte_str = bytearray(byte_str) + + detector = UniversalDetector() + detector.feed(byte_str) + detector.close() + + if detector._input_state == InputState.HIGH_BYTE: + results = [] + for prober in detector._charset_probers: + if prober.get_confidence() > detector.MINIMUM_THRESHOLD: + charset_name = prober.charset_name + lower_charset_name = prober.charset_name.lower() + # Use Windows encoding name instead of ISO-8859 if we saw any + # extra Windows-specific bytes + if lower_charset_name.startswith('iso-8859'): + if detector._has_win_bytes: + charset_name = detector.ISO_WIN_MAP.get(lower_charset_name, + charset_name) + results.append({ + 'encoding': charset_name, + 'confidence': prober.get_confidence(), + 'language': prober.language, + }) + if len(results) > 0: + return sorted(results, key=lambda result: -result['confidence']) + + return [detector.result] diff --git a/venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/__init__.cpython-39.pyc b/venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8a34cdbdc65d2cb8bcd1d906844e0c4aa69c3761 GIT binary patch literal 1892 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/codingstatemachine.cpython-39.pyc b/venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/codingstatemachine.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..00d8478e7b2b204f40335a942a3d89933c5c7ffd GIT binary patch literal 2902 zcmb7GO>Y}T7@pnr$Hs9?=!a+pg@Hp=i^i&iL{WvHr7c|AfRez$vb37)jO|U=yY9?5 zX`=MhUb%8^kNrz~<$hYF=07MdJPi z+^#S%oM$x5r&{eN`OM6Bii}*EW5dzPYlp5C7bstyVgWjX{Y9(pNVG5?V%jRLj3r71 zmdV;r3LPt{1Ii^@1C((>fFmGnT0 z;QJy?B!^0hPjmRwbs~Zq4WgCiV`2ENQlLYs%qGJ`$zJK%)5n!tbH6f~#E27e54;mk zizh!tfZc__Iq#kWz&XuS#V{EYKZHka8D%L(Fe{ZwMj6C%Vdta~_97G*rqx-_b6{v3 z)0hNdauS^UV4NT*V<-^knH3Pt64B)1dAKUnNpUQ3kqYNhB@h`-#AGs2GNF8dp@d=; z(wYMphMVW%=unm5b6Ov7ZT-AeFk&6dI+c+MhSY7t_>He43u8r&)HCi&zZ2?JnMxq7hAy2x-xY z;+fVF1waH9t3HKal&Y*)E$3Z$7tJ&ujc|DuDWoj&XvqY>!w4&)e*sx7iIe2~yPE-K9gc-+3Bu%kseP)cQl} zuA%xK#W+E|qiaiCaJ(%jPVd+g#mDFzvpwj29m-#4FMaep>+c26e0@iv7uDQ+fO#K< zMRi)?#%kBu6^wqwUIwmT$2_e=}1k zI2Mamre4^{P5ppDLwGFccx`CA?sq)@@0!2vb-be+OXxk_dqHE;*=bC^5kK2ZUq-X* zIY;$Xw9or;89CsR122n+h(Wsif_0U`H-7)PbdOj2B{KjcUk<8;L(wE2}rI@}!)u&W_j;aW!I-e?S51r{V5}w4A zrW~WShK53~b~OycAnc$7zUOAUb-hAhb(PH~rp)+8zPpF-IXAxywg|s1o&N37HO@K7M?e{#j zwe`I<7%M9^k!n_XdjE9P&@r0M_|8hnyb|DhsHA$CxLSktse?Dy?miMScRrO445G9? zp4JYZ#I5=yX19rK=;!(Rj6GURV_Ye2*_GBe+;KLla$c}8l$vR&2P>s{z63FNodXnu zlhcK?xqWXuHd%ubm0|gu8v%~xRjIif>e?sgWhGVxTgn!#F$Run_ literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/cp949prober.cpython-39.pyc b/venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/cp949prober.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c60730494b55ac8a2578cc1dd0856d1917204c52 GIT binary patch literal 1133 zcma)5&rcLF6mI9&4!9tq7)?w}G%?vIcp*lNQE``efJNfUWim_2j?c$@jVth8Pn&Y3F;dKi=#2zVf-bSpx0*{YU-R4MKjRQEwg?Z=mZA z41x%nk(@@9B6cz-cO%zgH}i5o@-6nVAa6tsO5PFSi{O}uK>8Cm3PqzwTH!AWN402m zcVoA``Jt0)qtgD+q=RC;;Mqv08YUOp1CbU7J;ROc^5ifrBzSLkhnY#=j*M&{a@CV& zM-BQ?!OVPnXKi(j^}4M4zO%8FK!_{NJ-75K07)V$NaUQ5eJZGMj>E{6o^XYCOeQq) z0o%L*2PecM5$4^fuGtvVkO^Mmq9Mir*!2?_3^DYGOq^5a2cg8c#+!i6d=pFv{2NE) zG{hM};9$DlnyGv}ETvKbY_3Aa(jqmCDLhd5=$lC_A57=UL3>Hmcw-!i8%tIBN@{7& zXys{{?ZbbDu_WVKGj>LP@3mjVyILw8^P=E7UN6fIH$2`NBs_~h%Djxrv|Jt*B~Ly} zvHa~&%53@B^G~Tx^cd%2_Ei>QpyCAh7t+K@3AC5C3M=JEg^=4r=o$f`^K{k?>G)QS zxRr~`{ly@%*v7r6IYEILXS?$4Rv7i-VMKM3ds#(VJff#0pn~Z%K@@zU|sjEVu z5_Dij>LwhkmSCvn&P$lcECWqk5-^WTkOeE72LLoa=8!f+2Z(p5^`p8LY`JQRnTlv} zDk_bSET29yE4k`=-an^oT3UrAsRHn75FiTD9$m}jvLfNj=>=ci!-P-=O=>^)57K83 AJpcdz literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/enums.cpython-39.pyc b/venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/enums.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3b6470ca3975eb3a6aaaa38e67a3bce026db847a GIT binary patch literal 2640 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 W>3|04vFneN^w(MfjSDF{Ed2+%SCCf# literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/eucjpprober.cpython-39.pyc b/venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/eucjpprober.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..265e315d6338eac0c80f154ce02b6f8fd8b7328d GIT binary patch literal 2439 zcma)8OK%%D5GJ_~t>m?=IB{YJMe6`f0ReT8LlFc;P&Ad@JP^xdWKJ<`le-4lBDYu?`NoTlnET;(2l{uW@Ylg#_ZyYQxmI!>me)h$| z?`1;%LSg>1LHHJ0`W%QLf<`2!EgG{HqbRe;itUzdcq?*Zx8)k%jta5Y@(k}p#kkZe z8QzT+V!!26@`#9n@J@;Fq&=}(i=x;d)zVuEYN|~8yQ+WCO*)M%$fWkSgYc-ENF!CL zzP>$-vhH^$nXDZJsv$F6Efvfx*ZSgo+iVkzu5Intp6+gT(@b>_hFQ0tJWPVsbhfUHYt|6;!ZOuVoqD5;pL* zbc7?^Q!=3~7kG1X;0vNCN~fgdi3Q<9Uwln$(kg)`7WIPBpWiG*x14{-qjGHNS3ok7 z(J`5@DLW&SWL9QRK;};7P6+gc%rkv)Or|AVAxML~q4ny5cGBTMDpiC-w8wcj>1LcO z2SnxJSTQv241(}jijAL-q>MK1-S2hN zFdgAsoBt#e(O2ydqCm*3Er(%mFfg%jXKH-mB6+dIsKrCqXRl;&ujvu+i$g#`#76OR@Hz z27@4h*ZsI^FA9>*Fz85(&~vqyJb%6*G&Z4K@L}v>IGMZNgIgQV(+T`G$&Y`&V&Ho= zwZ?SJ*2o!sWsM=+d(JUab(nFd1p%So^Pm;S>@|k{Qbf=s~2JQA&i$l z7+->M-<)4LBd_c+6AVWF7(+gKSTZJGN0izYmP8Ky*0u(XHF* zI{fANuzu9d)*)5kxDy49t=C`1|GDA1Rqno^_?c)-qLQqQ@c-^4V1m_clPU>{7F+g zjpoC>roP&N;0%XK$pm@`R#2=<96%x$O%`eUP)eboJb`*+iY{($HMeTbC-p~qsngH6 zO!~vl5f=a;x@^wuCx=}jlThmA#^as6W^KR8n~(RlKzO!Ub<{GR=Ak3NMx|*Nl4S;V zrsjBP4M#s*&M8%ejrXCY4}cI_VHJZbrFS;-sB3tnh&5$eq04NQGMGc^T4h$IKJ{@e z8&&3$5U+SC`Ow?gOeTB^47@CvQix29aAr7`nM|0l3luW2vjNLZlbXLNJk+{-?OQUc`zL56d9J|6eQFhbtv{KYVc@)-lj z2L7}MQ3;hNJDH0dbgV+fdT~}KLK#I+k1ig-AgKXSELopJOA$>y>KA;Q(UOJDyJb+g zUM*`!Cc`*2F_}m2QhYE&yF4uvVz6G$U*3dPod2s~iXhZ9tSoaiFE4{`ZxANg%e?Nn iaAXPv5({Py{}=XNAhGu#_sKU{O;W5(6%2&@XZ;IIl1|P5 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/euckrfreq.cpython-39.pyc b/venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/euckrfreq.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0a8cb7c41ba793b890ea19ea76c82948700fc44e GIT binary patch literal 12055 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/euckrprober.cpython-39.pyc b/venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/euckrprober.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9914cda83673e11a05a717a4ed6dfc604c49d95b GIT binary patch literal 1134 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 F{{U4C&@BJ} literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/euctwprober.cpython-39.pyc b/venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/euctwprober.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8f8e50834f83bf623c84ccd53d46868372028941 GIT binary patch literal 1134 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 Vy8n@aG(QRt@iwwjx2jF;?Ekpdt@;1} literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/jisfreq.cpython-39.pyc b/venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/jisfreq.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..cc3b7610fbf3138ad85f6ad8e4ca1eb0bb93c383 GIT binary patch literal 22127 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

)>so;j<1fpL=&y-BoJIrAs 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/langbulgarianmodel.cpython-39.pyc b/venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/langbulgarianmodel.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0174e18647099272b44db6d51c84f3e99d23e757 GIT binary patch literal 21802 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 G8UF?q$--m+ literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/langhebrewmodel.cpython-39.pyc b/venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/langhebrewmodel.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d2f8f5b35f2e784ea0b988c83f31a0f510ad66d2 GIT binary patch literal 20546 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 Y|KB@O`?7Bop!*VC>7nXQaYa7(FKF?vod5s; literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/langhungarianmodel.cpython-39.pyc b/venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/langhungarianmodel.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..33277bac8801433a35495e9ff31c99c1170f2fab GIT binary patch literal 21747 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 HkCpMid#&iO literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/langthaimodel.cpython-39.pyc b/venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/langthaimodel.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..cb30d6eb38c184cf3533766b49bb496b258e6c80 GIT binary patch literal 20722 zcmeI2cbHUFnun{Q5zLA+>Y!tsQBgrf#VlDt2@06n*0SI$p{40=Pd7L?LCg_FF^f6p zthb!txH;$8o6hcRs@*r=Uq03CV^?PqbR`&bNPz}yd?s? z6TSl8yRY^8YgjMGqUTGjkue z#sfd&eK}lf~Gh=sOS}`DjKY{_UdJ^=*J} zd^qiI#yY8=8nWP3aJ_D~`1ZX#tE}kJp5`uxPwpAknaQ^3`_do}@Y8o)x4#vk|LoOF zS=SopavSV0QM!~-)N9Gn`AD3>LA zG#`1aLwDU*tv6H{L=Q|ul;<5gf!W9=vlIwN1mOdhqOSAJMk6_E5D>G3M) zELNn=?JILybv-Vn?2=XY01w>)>&grCv#K&D-3}fw_79eQFZV)g&GPIvyv901lz4(= zRv5`buG>e=`v6a+8x1<^{`gy2l~kkG>TBfON^#`p{iOPURprO`^S9^PGwD0TN$t?? z+B|lhfvUOckw?NwKchZCYwoY_$(F1z_I$Xk^vg5%OETC-N;>_W%g8s)a=KIA z+sv@;5g|#whUd|H$R&#wybqL9Rajo28=X9|$w=B2wRYIUvihW`d&^@#iG)1xjzvq} zrR*ci8a5ayMpp7Z(7GhqAD&0_sGDG;XLz7fL-$+~Tgt5LvaSzQ6(oyojT&tz68B)} zUfu`9piC;qF3GybOC-v-ZjbkYvOt#PtDnu^x%aHO9>!h;^eVFalt#*p_Oa-Z=k>=M ztu|J$s7WXDZ041c2gv4Y#gp=@am8m_%DC@u`K^3w9}kL>!?orsWVtBYSS{@|N))Aw z;BGnat~DHyb3Oh2l`MC-5TxbZcq_1=v}F%m&OMM;-9Pz> zR(c=1SY_r}8tQ>Om%MA%+dV*oe;Ot5T^9X~q%3NrnZ`&rp4UtsxMWcR4~p~8a;(@! z(gQNmp7p_J8F$f^Dn<^{Psb?RrpYrlTN9h@7uUww$3NTJ@Tc*_cDB9kU_07QwzKVG zyV`i$%|2(Jx7}?I+ta>a6KpTr+rDV~*uJ)(?QaLzfekjlWM8&}>|i^@CfcEPm>q7D zY_c6;N7_*~#g4XP>{y#>$Jz0Af}Ln5*~xZF;ryvK&8FK7n`yIbw#~8A>~x!J^Xv>e z)8^X(TWE{yEIZp4+Y(!9=h(S+o}F(OSchF`opzC3Y-PK|Dz?m)n_1N^wH3C~y6iGr zW!<*gdaT#_>~ag%Zv(c*)~5Bp!oFhb>`MEpea*gZ->|FFyS(16wrlKKyUwn+8|+5A z$!@k=>{h$YHl#gsyWL?M?M}PPHrd^FkKJqc+5Pr_J!lWvW_#Eku}AGOd)%I|C+#VF z+Mcmz?KykiUa%MKC41Rku~+Rid)?l!H|;HZ+upHvElDdg&T1RmHkUd^SKI78`(|}? zb(DR}zHQ&J_cx5~Xt(b!DNX#K&R>&EY#ZEtNmtK`?&{2S1Jzk8D`81>U_q}{yX&LU z?Rxr0CZ+ml1gF);#TX z5i%RQGW`NL7@P|B1yjK!ur1gnMZmfGDPU)?12_~+2IIl!K|7cRb_e`%O~}^1#B>j^ zBRB-?1@;36g6+ZHU?TV;*dI&*Uk2NNvEU$ZJU9uQ41Ngy7yJ+SZ}1Md46FhM-USJ$ zfhxEdya&Dsy1{DD1A4)?z_-D7zy+WT`oQJjeehlI0r&|p9n1yuKmcceelP$o1!sew z2WvnFSOFG-#o!X~3*bVq2rLCFK^LfiWuO!MBKURi8{jv=Z-L(i=Y!t?zYBg3{5}{2 ze*pdvtOb7r{uulTh+sK52P^@93jPdy5Bxd!3-FiVufSh}I`|v#x8Uzm1WFsS(te-O zI5z$soXK=supQVQ(0?Ioq$?Qh1Zd2VH7lJR#siu^a18?88R*GC6NWtj%^xO!y};gp zt_%BseZhW!CJfxXK%a)JmH&YeJsIf4a4IHc5;o=88s@!3~K_Dz!|LiPQT zLn`S02xlqDBFfU4r6em4c~;u98fDqdDwx%hJS(SJCg~TIG3$~nomqym2yY9S1pxwUDhR+u=Xl=96S$R0k47A!JD80xaYyZ!{9OS0$2?Kcmu2iJ>YiG4>o`& zz+2!da6VWCE(c!$FM@^O0?-TAf-AsnU>;ZiR)B6W0M-DSCd>tAgT-J8SPDA8g@Esp zPz9HQ%fOA`krZ`&sjmZ9g0F(FfvraBGz|-Iv z@GN)^Q2jauty6{iOW$^K zm6fg)wY^`R{)4B!Kkc+NW7LUTA3A|_A9`=F?k~;tf{Q14(`f&d7!u48>|}2t1EpSJNagLHNP(p?mn=tuWNawyWH2? z-!;&+wptFAfv(<;@vExUzH+61c~@7tyE-sX4gG`TD&2i6E6b__3nz~0IIyp)Z*qBU zHT`djFc~{m9hls|>?2S5LhrI_2&2*xcI>=#?u>cm`7;)tUS6`r_MF8X;~Vxe`RCK$UeaP`_;A^*6Fbl8Prd1^^z>BvJ7@Iu&8`eo zI_LMML3A#yuI}qh9h;8>g23q&8b^k`L`&vK$TKBJY|62EN OrE&DonD$~uKKwsiayGXB literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/langturkishmodel.cpython-39.pyc b/venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/langturkishmodel.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5a62e0314af5acaba2074d4bb496316f1de6e45f GIT binary patch literal 20562 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/latin1prober.cpython-39.pyc b/venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/latin1prober.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6586bda6708e84e330a25ebfd1a3d74810cca2e7 GIT binary patch literal 2947 zcmc&$&2Jk;6rY*>@Ora$(-PW-7FvWlr&v*K22X zOjYAtNTi++{0Z%`7ybzTj6H!kp!@+`dMWSCCbc(&suc%jw9jwedo%Oq_db%SQt=6l zAJ3e-`*eE1!RyZrF z4N^O@3&}=mG^^CtBh`@lmg?V?3IqXi-K5jdk(RqQSna|`b|ELpu7$)w;vy*_@qpA8 z6-r;4;70XgV$OT9iP0Wrhi_AcOb+;0JA6rQY`DYhCZ|leiQVL)$-NWVi|wAD*8(pJ z1EI!|E(4Jyq)_qfA!$=V1>5mLOIX6*A)zfD;Rtt!Y}3#Mz9c-umqc0kp!dX#2;jH; zkk};jA@-FlSdMfzxtPbig}&|&Je%cllxp6BJmW23)2zbVN^bI2f0$^gGDpc&>L)a_QyI76 zx6E@x&YzH{QT>zV?Nq9?86`=SHkSs2tC5bH%l%dqH`iou&>VCJ3&Ug(weCr=aDQFO zc;UlK8{M>(j!@U+-^oPuRTEthQa5As`hmxfx$3Jyp3U`%B~tJH-#dVLzC3;WMG z6sw-|KTbI*SLyREvRv4o?>q{ znF2M3e9cj>p^10*ftH|F8Es`ghGVbfY^=Bgd6e00DTRi8=}91j`qYEzQ})bd$l3H5 z_1NfWA;!3;5L@&OKZAD@7(fM@#s&i%XEDn(ptWId8~g!XqRtDp#gfw~71li3!@o3u zt}{nYLZnWSEjDI?f#of<1m2x9GQhgD()oVwmm9y2cCKIvn34Y_!R+1>y}#IL{`Bi# z=bL|C0c73*g+dS2+dwia9rg@%H7f_r(S04o09QY0cZEz^@*q&v4y67>{R14c2U$RE zhOoKpIKXBDY_{dm(WwGt#oe_TY>rq+&>VfvdwnsCkq{V~x7flPw9GMJzX%5~zY|gCPSFbC~mdsje)R8oR)W1fuic91gtLiM6sJD=uL4qDk nxn}wqx|VsD^XGs1CahA-o`43-W;P^WVOq2FKh59VckRmGp~zI( literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/mbcharsetprober.cpython-39.pyc b/venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/mbcharsetprober.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ec65a1756222a00468a323b7e5cac77e3ebbb36c GIT binary patch literal 2254 zcma)7UvC>l5Z~SVle2Sn)1+xq0j&YG$cR)t00I;cB?)b$)*%(zE|0{RCT6(i( zIoYAcZYi)0?+EwM3moZ+Dd8QG0~$;LUlL`*dtzGnha@P8im1YW`8lykFb$s0=$lUl zNfCd$U&sr-4r}Eaw9A!7)rgpJZ$gl_PI~?kFa;^-h#ask8&N@Dn9z*~w*&!d3no~H z0p|z;ZdeTn)^rl49ljGMg;cL_*Sf2ne9)IlIUs3|^EizQ&h@;A^FqbjgCfpS9;RWk zKa@(BqD(++dEV1yo`iY9BM3i4-OgpQqg>eJCDkR)BT(j?za)Q)l`q>{xm0;OOw%xL zKj`;Y!y;@y&Z01Bw`8y1?#KP5LD~e~D#nTkxc(Uy=! zySI&8E{ndo^!xpNRRYT&K+ioOgw9eIzTutAgM0tN zK$f8AIET8-8)$bP$z>jRn7D(mBfmIj{i@qN zoqGX2nBRCICKe2$Vs4inz_&_%{NouQrOS@25goBxWK5q~Bdf5x&QqoupmC3;1YoV} zK`)Ki7|K#n?oI=`d`kBI-1E)s3e4Vt@#=rZufe!)_MaJ(XZ8q?2_wG)YQYwaUl-Og z{?8uGp)|6`;2`Wd83B)kwMdXIkl%2{sh$e^WIZ$MZ-DK2*!i_td2>vVJ6agy-iuFd z_4?E|kZ(Xua2msR@8&i5O@LI}jf)!8f=t!IqP7hM3v?!p6{gXvV`%kT+EH*BQd@~k zO)l$lDt{?>js;g?N!8BU=H|wxc9X2rfvVvMxjpEp1yHF)BnUI@Ha1%P$(nX2E491c zYNG6Yx3Se&PnPb)LZ*?_v&}~vo2`|t7H>V;Tm#|pYTYql)E*ul{8F06 zkp3q{&sgvG19qmM=!E zP8)R}9|^1j@JN(7?`2|;An$X&Hwcpx%@pS%i#RuR+0-)aL5{&gQ|zD10}Pq*MORLq zj7TO4Ec-XKrYxF@hzNcUea6!0QQNM%zQ<_U!tT9eN^Aojw919YL1CP&x0*SFCWX0uOctbYJm6e9Nk literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/mbcsgroupprober.cpython-39.pyc b/venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/mbcsgroupprober.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..393abde593fa557fc04734f0e5c85221974d20a8 GIT binary patch literal 1123 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 D!KSa& literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/sbcharsetprober.cpython-39.pyc b/venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/sbcharsetprober.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6f5fc0d71ea1dee47c8242b1b82ef131fc5a8103 GIT binary patch literal 3107 zcmb^zO>Z2xm7K4g{j@AAc4XP@qOgN35F1Vl)NPPdaiq1RR9+d{b%6{vAVx!Kzh-CF zoLLJ}XHOOo^iZJ3wkIh!UGgLPGk7a{@}=#uC{VcXaU@Ghs#`hWn@7G!^6`DruU1P0 z+V6k-!Op*K5%M=2Tx=E$K8K#P0C2)-NXFEolyHNap)oc+Q{z@>jcv~!JDxKxcm+xX z<#vy7=Ue*P@Z2@R3*0><+!f|)(<|~~n>0#qU{BJZsucNS!PDs^6mMugRbA=(vMti* zGTsrgVXEsm;RmUZD}E|^vD{Y`Bo3lpJB1lF-xe>YA_~OjU?jppKaRP&*#>ebzSvL2 z>3+{*F2Y7ZRRY*95h=r?l^gm|Z|e7ix{mWKjae+YkZkNvRPBt&#<*DBO!p^)zz^9Z zP6p}Vm0;3O2eFzT2{B=Q5)1|`6e&oWDAx}seSb%!0bccDL&aiCb^r+CQBFLAQ_tjv zXK~ZBx#c0Lue_!tX`A^tRmY=qQGeLm~d5C%1lP>{DNlG*F z+Bh|{C-QqIBF%4KX2 z4N}IGbE^3wlj0SqRd7|&hGP@$9;(bjKS^_&sVYmvOBTe_NSmMx)=a@#Fqr^jK0qt0 z65Ex?iMTBVctgWdRwBY(W#^`L-!NI`l;XDjKNE~9WkDCCxgj@X*BVJk>C&Z`a*;ce*TN$APJHKq;=UV5%E}dQ5G)J zZnA?INR(gj;bdPffKGk}Jwb%f8g&f#==pb0zrw%|&lDM8aGf>8-`VmL7+kg`*S6$F zkEYgJC67l|w)cn`sc2((n^q9OIy&=Us$0l{43;NDe2otjpA z@c%_NOyO6{hSY877iGKBRnBrIIq%t{MG_t==(nGINRM5LENRvDH!eM}6(N|_Do$}s;I zJzqJUufS~e5~X%ZLCalBzQuGitS*wwUL-Ros=*krd~W8ze=c)uvIqt2F?ju_zy~f| zefbC|WO#j6fWMi}4{wZ&KTx>}BiwgkWaXoy_m0WT&0Ltfsps&nw~pS25GZ8sF_b`9 zy9hhpjy}{}OCxf+4|18v1uK@0EzJq5*=-nuwi;GTViX?SyPwp9INBX>tYP)f>i3h6 z>U*Nz_g{&+U*8)Oyk?27g0_LP2%QTp#^|TM}-|xpEhs_#ya}TM( zVe0noAcW)y`4wP<)hmJwxd$~bffS78RF;8HVxTD#f>zpy6<@Sgn@=}d%~e%c*=lvR zw>EXqs&f0uv*(*l*52@%I)d|<*HL{FH_}0_LkRsy6<3>`=1OOywFXt`3)XCHy;xgk z+s#eZS>JB9*S9uTRSk2+xkl8|^R4zqXX7_;%KFxJXXQob0<#mwy`F$H&c)8Or`)Go zAS&DFKIip7BA#u1cssTp@y7ksFN*Xh$ zL9PE-79^HCS0xra?ovX*AV%-ffx8I^$4~{A=f=pA>)@D>^ipGJF6#U~Buf}F*3e!e z7}9_{nD>W;e9X;}4XZ4qf$Q3>-ftJaTl?$5;j+&BJvac`KbLzrx$xaTmK$!K*|qs~ z1#r)-n0sRt_;ZKBu9S{Qsp2H zLlI!CCK3&+s+Zmf5+7&E7EoRj9j+2XP1jxNBBl%SdEI(fyp;QCe*a%#fz`#eVpQmY K39kCqD*YF<w1 z^UKl7kNTH?Xb4b%ISMhs7-WlEp-pTf+uR8gBoQV_(&!FPg=vxwGbCg51YZiXBx~d( zcf%aXg?W+>3#1ShNikd|%VCL>j6cO6gk@4Ta+fq8?o~&i2nQJ-Yp*y1nSFSZeil@3-`@d2nz%+qX8i@0)p#K7W1A zSEWY>d(DH(cv~f@%8k9#TD3}>7oK-lhOzGKELhiW5C32M@p+?0n+x&lr@Qs~&&|fk zNu$2t+L)_p`@RqQ*lKum=gHT!b+p@%qIul#j&6Mqy}_`@+1{&&&1Mj{ zyQ>FtZ`m_VKGFh11P6#%@6dA`;J|vDCiXkzAmZq$+N$8~)xEh{c45q)7SOYxe@G~Q z*ASryPtmn?W4%WhMfNp%gCi$O1bC{c^2Rc&RRjnwa`scJvZ4}lGG;=Qbg3#$>0mgB zC>2n?SO!RgV_C9@hNFOSIyU^3A`ea%APbNKfR`&W07-xp05n7-0H7^GKWU^=vm`1Z zn9f{rlp`5`u5x|zBxYx*6+Y?>x<04(&E*#ZIa#!Rz$!y&m-|vu`T_kL)W2(ANG4?4 z9}a!l-W`wk{m5^hjC8_wi-qI%crf0a499-=iUpf5`;76;o!T!0*_E%s*QPJnFc^t; zSHIqXMQz#X${sx7xcaT}D^b?B`AYw?rUBtRPGSc;A05Y_mBiLZCzaIJg)afR1>Zl( zmDg(vgxdNvhDriPGW0`6sam2ife8oMrSwC^v3=d|$%}RpS1z*O~C1F9!b5P~vXHDi7YCVC*XP z+|oc5z!Rs7UBD|+1gn@xd7I0y$MDF|$`H(O3;3pT5FhpZL7W2^rA&@!BCZCqADa!w v3VK}ewPxiTHbV>MdSki-y;14!^%Ss)YQ5 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 Q>-RArga=sYm>&PyN>|vi0Uq z8>BJzI>GuQoMg;EE=j>D&}U|>0V((jtOUby#o25Hnp(~1f{8iUjKYFy!=wOFWWIhy`45EH-Cw zNU(^KKRTG_nDHo;c_&;qkD^}GEB$EH3CdO+6Pd +# +# 128 --> 0.42261 +# 256 --> 0.57851 +# 512 --> 0.74851 +# 1024 --> 0.89384 +# 2048 --> 0.97583 +# +# Ideal Distribution Ratio = 0.74851/(1-0.74851) =2.98 +# Random Distribution Ration = 512/(5401-512)=0.105 +# +# Typical Distribution Ratio about 25% of Ideal one, still much higher than RDR + +BIG5_TYPICAL_DISTRIBUTION_RATIO = 0.75 + +#Char to FreqOrder table +BIG5_TABLE_SIZE = 5376 + +BIG5_CHAR_TO_FREQ_ORDER = ( + 1,1801,1506, 255,1431, 198, 9, 82, 6,5008, 177, 202,3681,1256,2821, 110, # 16 +3814, 33,3274, 261, 76, 44,2114, 16,2946,2187,1176, 659,3971, 26,3451,2653, # 32 +1198,3972,3350,4202, 410,2215, 302, 590, 361,1964, 8, 204, 58,4510,5009,1932, # 48 + 63,5010,5011, 317,1614, 75, 222, 159,4203,2417,1480,5012,3555,3091, 224,2822, # 64 +3682, 3, 10,3973,1471, 29,2787,1135,2866,1940, 873, 130,3275,1123, 312,5013, # 80 +4511,2052, 507, 252, 682,5014, 142,1915, 124, 206,2947, 34,3556,3204, 64, 604, # 96 +5015,2501,1977,1978, 155,1991, 645, 641,1606,5016,3452, 337, 72, 406,5017, 80, # 112 + 630, 238,3205,1509, 263, 939,1092,2654, 756,1440,1094,3453, 449, 69,2987, 591, # 128 + 179,2096, 471, 115,2035,1844, 60, 50,2988, 134, 806,1869, 734,2036,3454, 180, # 144 + 995,1607, 156, 537,2907, 688,5018, 319,1305, 779,2145, 514,2379, 298,4512, 359, # 160 +2502, 90,2716,1338, 663, 11, 906,1099,2553, 20,2441, 182, 532,1716,5019, 732, # 176 +1376,4204,1311,1420,3206, 25,2317,1056, 113, 399, 382,1950, 242,3455,2474, 529, # 192 +3276, 475,1447,3683,5020, 117, 21, 656, 810,1297,2300,2334,3557,5021, 126,4205, # 208 + 706, 456, 150, 613,4513, 71,1118,2037,4206, 145,3092, 85, 835, 486,2115,1246, # 224 +1426, 428, 727,1285,1015, 800, 106, 623, 303,1281,5022,2128,2359, 347,3815, 221, # 240 +3558,3135,5023,1956,1153,4207, 83, 296,1199,3093, 192, 624, 93,5024, 822,1898, # 256 +2823,3136, 795,2065, 991,1554,1542,1592, 27, 43,2867, 859, 139,1456, 860,4514, # 272 + 437, 712,3974, 164,2397,3137, 695, 211,3037,2097, 195,3975,1608,3559,3560,3684, # 288 +3976, 234, 811,2989,2098,3977,2233,1441,3561,1615,2380, 668,2077,1638, 305, 228, # 304 +1664,4515, 467, 415,5025, 262,2099,1593, 239, 108, 300, 200,1033, 512,1247,2078, # 320 +5026,5027,2176,3207,3685,2682, 593, 845,1062,3277, 88,1723,2038,3978,1951, 212, # 336 + 266, 152, 149, 468,1899,4208,4516, 77, 187,5028,3038, 37, 5,2990,5029,3979, # 352 +5030,5031, 39,2524,4517,2908,3208,2079, 55, 148, 74,4518, 545, 483,1474,1029, # 368 +1665, 217,1870,1531,3138,1104,2655,4209, 24, 172,3562, 900,3980,3563,3564,4519, # 384 + 32,1408,2824,1312, 329, 487,2360,2251,2717, 784,2683, 4,3039,3351,1427,1789, # 400 + 188, 109, 499,5032,3686,1717,1790, 888,1217,3040,4520,5033,3565,5034,3352,1520, # 416 +3687,3981, 196,1034, 775,5035,5036, 929,1816, 249, 439, 38,5037,1063,5038, 794, # 432 +3982,1435,2301, 46, 178,3278,2066,5039,2381,5040, 214,1709,4521, 804, 35, 707, # 448 + 324,3688,1601,2554, 140, 459,4210,5041,5042,1365, 839, 272, 978,2262,2580,3456, # 464 +2129,1363,3689,1423, 697, 100,3094, 48, 70,1231, 495,3139,2196,5043,1294,5044, # 480 +2080, 462, 586,1042,3279, 853, 256, 988, 185,2382,3457,1698, 434,1084,5045,3458, # 496 + 314,2625,2788,4522,2335,2336, 569,2285, 637,1817,2525, 757,1162,1879,1616,3459, # 512 + 287,1577,2116, 768,4523,1671,2868,3566,2526,1321,3816, 909,2418,5046,4211, 933, # 528 +3817,4212,2053,2361,1222,4524, 765,2419,1322, 786,4525,5047,1920,1462,1677,2909, # 544 +1699,5048,4526,1424,2442,3140,3690,2600,3353,1775,1941,3460,3983,4213, 309,1369, # 560 +1130,2825, 364,2234,1653,1299,3984,3567,3985,3986,2656, 525,1085,3041, 902,2001, # 576 +1475, 964,4527, 421,1845,1415,1057,2286, 940,1364,3141, 376,4528,4529,1381, 7, # 592 +2527, 983,2383, 336,1710,2684,1846, 321,3461, 559,1131,3042,2752,1809,1132,1313, # 608 + 265,1481,1858,5049, 352,1203,2826,3280, 167,1089, 420,2827, 776, 792,1724,3568, # 624 +4214,2443,3281,5050,4215,5051, 446, 229, 333,2753, 901,3818,1200,1557,4530,2657, # 640 +1921, 395,2754,2685,3819,4216,1836, 125, 916,3209,2626,4531,5052,5053,3820,5054, # 656 +5055,5056,4532,3142,3691,1133,2555,1757,3462,1510,2318,1409,3569,5057,2146, 438, # 672 +2601,2910,2384,3354,1068, 958,3043, 461, 311,2869,2686,4217,1916,3210,4218,1979, # 688 + 383, 750,2755,2627,4219, 274, 539, 385,1278,1442,5058,1154,1965, 384, 561, 210, # 704 + 98,1295,2556,3570,5059,1711,2420,1482,3463,3987,2911,1257, 129,5060,3821, 642, # 720 + 523,2789,2790,2658,5061, 141,2235,1333, 68, 176, 441, 876, 907,4220, 603,2602, # 736 + 710, 171,3464, 404, 549, 18,3143,2398,1410,3692,1666,5062,3571,4533,2912,4534, # 752 +5063,2991, 368,5064, 146, 366, 99, 871,3693,1543, 748, 807,1586,1185, 22,2263, # 768 + 379,3822,3211,5065,3212, 505,1942,2628,1992,1382,2319,5066, 380,2362, 218, 702, # 784 +1818,1248,3465,3044,3572,3355,3282,5067,2992,3694, 930,3283,3823,5068, 59,5069, # 800 + 585, 601,4221, 497,3466,1112,1314,4535,1802,5070,1223,1472,2177,5071, 749,1837, # 816 + 690,1900,3824,1773,3988,1476, 429,1043,1791,2236,2117, 917,4222, 447,1086,1629, # 832 +5072, 556,5073,5074,2021,1654, 844,1090, 105, 550, 966,1758,2828,1008,1783, 686, # 848 +1095,5075,2287, 793,1602,5076,3573,2603,4536,4223,2948,2302,4537,3825, 980,2503, # 864 + 544, 353, 527,4538, 908,2687,2913,5077, 381,2629,1943,1348,5078,1341,1252, 560, # 880 +3095,5079,3467,2870,5080,2054, 973, 886,2081, 143,4539,5081,5082, 157,3989, 496, # 896 +4224, 57, 840, 540,2039,4540,4541,3468,2118,1445, 970,2264,1748,1966,2082,4225, # 912 +3144,1234,1776,3284,2829,3695, 773,1206,2130,1066,2040,1326,3990,1738,1725,4226, # 928 + 279,3145, 51,1544,2604, 423,1578,2131,2067, 173,4542,1880,5083,5084,1583, 264, # 944 + 610,3696,4543,2444, 280, 154,5085,5086,5087,1739, 338,1282,3096, 693,2871,1411, # 960 +1074,3826,2445,5088,4544,5089,5090,1240, 952,2399,5091,2914,1538,2688, 685,1483, # 976 +4227,2475,1436, 953,4228,2055,4545, 671,2400, 79,4229,2446,3285, 608, 567,2689, # 992 +3469,4230,4231,1691, 393,1261,1792,2401,5092,4546,5093,5094,5095,5096,1383,1672, # 1008 +3827,3213,1464, 522,1119, 661,1150, 216, 675,4547,3991,1432,3574, 609,4548,2690, # 1024 +2402,5097,5098,5099,4232,3045, 0,5100,2476, 315, 231,2447, 301,3356,4549,2385, # 1040 +5101, 233,4233,3697,1819,4550,4551,5102, 96,1777,1315,2083,5103, 257,5104,1810, # 1056 +3698,2718,1139,1820,4234,2022,1124,2164,2791,1778,2659,5105,3097, 363,1655,3214, # 1072 +5106,2993,5107,5108,5109,3992,1567,3993, 718, 103,3215, 849,1443, 341,3357,2949, # 1088 +1484,5110,1712, 127, 67, 339,4235,2403, 679,1412, 821,5111,5112, 834, 738, 351, # 1104 +2994,2147, 846, 235,1497,1881, 418,1993,3828,2719, 186,1100,2148,2756,3575,1545, # 1120 +1355,2950,2872,1377, 583,3994,4236,2581,2995,5113,1298,3699,1078,2557,3700,2363, # 1136 + 78,3829,3830, 267,1289,2100,2002,1594,4237, 348, 369,1274,2197,2178,1838,4552, # 1152 +1821,2830,3701,2757,2288,2003,4553,2951,2758, 144,3358, 882,4554,3995,2759,3470, # 1168 +4555,2915,5114,4238,1726, 320,5115,3996,3046, 788,2996,5116,2831,1774,1327,2873, # 1184 +3997,2832,5117,1306,4556,2004,1700,3831,3576,2364,2660, 787,2023, 506, 824,3702, # 1200 + 534, 323,4557,1044,3359,2024,1901, 946,3471,5118,1779,1500,1678,5119,1882,4558, # 1216 + 165, 243,4559,3703,2528, 123, 683,4239, 764,4560, 36,3998,1793, 589,2916, 816, # 1232 + 626,1667,3047,2237,1639,1555,1622,3832,3999,5120,4000,2874,1370,1228,1933, 891, # 1248 +2084,2917, 304,4240,5121, 292,2997,2720,3577, 691,2101,4241,1115,4561, 118, 662, # 1264 +5122, 611,1156, 854,2386,1316,2875, 2, 386, 515,2918,5123,5124,3286, 868,2238, # 1280 +1486, 855,2661, 785,2216,3048,5125,1040,3216,3578,5126,3146, 448,5127,1525,5128, # 1296 +2165,4562,5129,3833,5130,4242,2833,3579,3147, 503, 818,4001,3148,1568, 814, 676, # 1312 +1444, 306,1749,5131,3834,1416,1030, 197,1428, 805,2834,1501,4563,5132,5133,5134, # 1328 +1994,5135,4564,5136,5137,2198, 13,2792,3704,2998,3149,1229,1917,5138,3835,2132, # 1344 +5139,4243,4565,2404,3580,5140,2217,1511,1727,1120,5141,5142, 646,3836,2448, 307, # 1360 +5143,5144,1595,3217,5145,5146,5147,3705,1113,1356,4002,1465,2529,2530,5148, 519, # 1376 +5149, 128,2133, 92,2289,1980,5150,4003,1512, 342,3150,2199,5151,2793,2218,1981, # 1392 +3360,4244, 290,1656,1317, 789, 827,2365,5152,3837,4566, 562, 581,4004,5153, 401, # 1408 +4567,2252, 94,4568,5154,1399,2794,5155,1463,2025,4569,3218,1944,5156, 828,1105, # 1424 +4245,1262,1394,5157,4246, 605,4570,5158,1784,2876,5159,2835, 819,2102, 578,2200, # 1440 +2952,5160,1502, 436,3287,4247,3288,2836,4005,2919,3472,3473,5161,2721,2320,5162, # 1456 +5163,2337,2068, 23,4571, 193, 826,3838,2103, 699,1630,4248,3098, 390,1794,1064, # 1472 +3581,5164,1579,3099,3100,1400,5165,4249,1839,1640,2877,5166,4572,4573, 137,4250, # 1488 + 598,3101,1967, 780, 104, 974,2953,5167, 278, 899, 253, 402, 572, 504, 493,1339, # 1504 +5168,4006,1275,4574,2582,2558,5169,3706,3049,3102,2253, 565,1334,2722, 863, 41, # 1520 +5170,5171,4575,5172,1657,2338, 19, 463,2760,4251, 606,5173,2999,3289,1087,2085, # 1536 +1323,2662,3000,5174,1631,1623,1750,4252,2691,5175,2878, 791,2723,2663,2339, 232, # 1552 +2421,5176,3001,1498,5177,2664,2630, 755,1366,3707,3290,3151,2026,1609, 119,1918, # 1568 +3474, 862,1026,4253,5178,4007,3839,4576,4008,4577,2265,1952,2477,5179,1125, 817, # 1584 +4254,4255,4009,1513,1766,2041,1487,4256,3050,3291,2837,3840,3152,5180,5181,1507, # 1600 +5182,2692, 733, 40,1632,1106,2879, 345,4257, 841,2531, 230,4578,3002,1847,3292, # 1616 +3475,5183,1263, 986,3476,5184, 735, 879, 254,1137, 857, 622,1300,1180,1388,1562, # 1632 +4010,4011,2954, 967,2761,2665,1349, 592,2134,1692,3361,3003,1995,4258,1679,4012, # 1648 +1902,2188,5185, 739,3708,2724,1296,1290,5186,4259,2201,2202,1922,1563,2605,2559, # 1664 +1871,2762,3004,5187, 435,5188, 343,1108, 596, 17,1751,4579,2239,3477,3709,5189, # 1680 +4580, 294,3582,2955,1693, 477, 979, 281,2042,3583, 643,2043,3710,2631,2795,2266, # 1696 +1031,2340,2135,2303,3584,4581, 367,1249,2560,5190,3585,5191,4582,1283,3362,2005, # 1712 + 240,1762,3363,4583,4584, 836,1069,3153, 474,5192,2149,2532, 268,3586,5193,3219, # 1728 +1521,1284,5194,1658,1546,4260,5195,3587,3588,5196,4261,3364,2693,1685,4262, 961, # 1744 +1673,2632, 190,2006,2203,3841,4585,4586,5197, 570,2504,3711,1490,5198,4587,2633, # 1760 +3293,1957,4588, 584,1514, 396,1045,1945,5199,4589,1968,2449,5200,5201,4590,4013, # 1776 + 619,5202,3154,3294, 215,2007,2796,2561,3220,4591,3221,4592, 763,4263,3842,4593, # 1792 +5203,5204,1958,1767,2956,3365,3712,1174, 452,1477,4594,3366,3155,5205,2838,1253, # 1808 +2387,2189,1091,2290,4264, 492,5206, 638,1169,1825,2136,1752,4014, 648, 926,1021, # 1824 +1324,4595, 520,4596, 997, 847,1007, 892,4597,3843,2267,1872,3713,2405,1785,4598, # 1840 +1953,2957,3103,3222,1728,4265,2044,3714,4599,2008,1701,3156,1551, 30,2268,4266, # 1856 +5207,2027,4600,3589,5208, 501,5209,4267, 594,3478,2166,1822,3590,3479,3591,3223, # 1872 + 829,2839,4268,5210,1680,3157,1225,4269,5211,3295,4601,4270,3158,2341,5212,4602, # 1888 +4271,5213,4015,4016,5214,1848,2388,2606,3367,5215,4603, 374,4017, 652,4272,4273, # 1904 + 375,1140, 798,5216,5217,5218,2366,4604,2269, 546,1659, 138,3051,2450,4605,5219, # 1920 +2254, 612,1849, 910, 796,3844,1740,1371, 825,3845,3846,5220,2920,2562,5221, 692, # 1936 + 444,3052,2634, 801,4606,4274,5222,1491, 244,1053,3053,4275,4276, 340,5223,4018, # 1952 +1041,3005, 293,1168, 87,1357,5224,1539, 959,5225,2240, 721, 694,4277,3847, 219, # 1968 +1478, 644,1417,3368,2666,1413,1401,1335,1389,4019,5226,5227,3006,2367,3159,1826, # 1984 + 730,1515, 184,2840, 66,4607,5228,1660,2958, 246,3369, 378,1457, 226,3480, 975, # 2000 +4020,2959,1264,3592, 674, 696,5229, 163,5230,1141,2422,2167, 713,3593,3370,4608, # 2016 +4021,5231,5232,1186, 15,5233,1079,1070,5234,1522,3224,3594, 276,1050,2725, 758, # 2032 +1126, 653,2960,3296,5235,2342, 889,3595,4022,3104,3007, 903,1250,4609,4023,3481, # 2048 +3596,1342,1681,1718, 766,3297, 286, 89,2961,3715,5236,1713,5237,2607,3371,3008, # 2064 +5238,2962,2219,3225,2880,5239,4610,2505,2533, 181, 387,1075,4024, 731,2190,3372, # 2080 +5240,3298, 310, 313,3482,2304, 770,4278, 54,3054, 189,4611,3105,3848,4025,5241, # 2096 +1230,1617,1850, 355,3597,4279,4612,3373, 111,4280,3716,1350,3160,3483,3055,4281, # 2112 +2150,3299,3598,5242,2797,4026,4027,3009, 722,2009,5243,1071, 247,1207,2343,2478, # 2128 +1378,4613,2010, 864,1437,1214,4614, 373,3849,1142,2220, 667,4615, 442,2763,2563, # 2144 +3850,4028,1969,4282,3300,1840, 837, 170,1107, 934,1336,1883,5244,5245,2119,4283, # 2160 +2841, 743,1569,5246,4616,4284, 582,2389,1418,3484,5247,1803,5248, 357,1395,1729, # 2176 +3717,3301,2423,1564,2241,5249,3106,3851,1633,4617,1114,2086,4285,1532,5250, 482, # 2192 +2451,4618,5251,5252,1492, 833,1466,5253,2726,3599,1641,2842,5254,1526,1272,3718, # 2208 +4286,1686,1795, 416,2564,1903,1954,1804,5255,3852,2798,3853,1159,2321,5256,2881, # 2224 +4619,1610,1584,3056,2424,2764, 443,3302,1163,3161,5257,5258,4029,5259,4287,2506, # 2240 +3057,4620,4030,3162,2104,1647,3600,2011,1873,4288,5260,4289, 431,3485,5261, 250, # 2256 + 97, 81,4290,5262,1648,1851,1558, 160, 848,5263, 866, 740,1694,5264,2204,2843, # 2272 +3226,4291,4621,3719,1687, 950,2479, 426, 469,3227,3720,3721,4031,5265,5266,1188, # 2288 + 424,1996, 861,3601,4292,3854,2205,2694, 168,1235,3602,4293,5267,2087,1674,4622, # 2304 +3374,3303, 220,2565,1009,5268,3855, 670,3010, 332,1208, 717,5269,5270,3603,2452, # 2320 +4032,3375,5271, 513,5272,1209,2882,3376,3163,4623,1080,5273,5274,5275,5276,2534, # 2336 +3722,3604, 815,1587,4033,4034,5277,3605,3486,3856,1254,4624,1328,3058,1390,4035, # 2352 +1741,4036,3857,4037,5278, 236,3858,2453,3304,5279,5280,3723,3859,1273,3860,4625, # 2368 +5281, 308,5282,4626, 245,4627,1852,2480,1307,2583, 430, 715,2137,2454,5283, 270, # 2384 + 199,2883,4038,5284,3606,2727,1753, 761,1754, 725,1661,1841,4628,3487,3724,5285, # 2400 +5286, 587, 14,3305, 227,2608, 326, 480,2270, 943,2765,3607, 291, 650,1884,5287, # 2416 +1702,1226, 102,1547, 62,3488, 904,4629,3489,1164,4294,5288,5289,1224,1548,2766, # 2432 + 391, 498,1493,5290,1386,1419,5291,2056,1177,4630, 813, 880,1081,2368, 566,1145, # 2448 +4631,2291,1001,1035,2566,2609,2242, 394,1286,5292,5293,2069,5294, 86,1494,1730, # 2464 +4039, 491,1588, 745, 897,2963, 843,3377,4040,2767,2884,3306,1768, 998,2221,2070, # 2480 + 397,1827,1195,1970,3725,3011,3378, 284,5295,3861,2507,2138,2120,1904,5296,4041, # 2496 +2151,4042,4295,1036,3490,1905, 114,2567,4296, 209,1527,5297,5298,2964,2844,2635, # 2512 +2390,2728,3164, 812,2568,5299,3307,5300,1559, 737,1885,3726,1210, 885, 28,2695, # 2528 +3608,3862,5301,4297,1004,1780,4632,5302, 346,1982,2222,2696,4633,3863,1742, 797, # 2544 +1642,4043,1934,1072,1384,2152, 896,4044,3308,3727,3228,2885,3609,5303,2569,1959, # 2560 +4634,2455,1786,5304,5305,5306,4045,4298,1005,1308,3728,4299,2729,4635,4636,1528, # 2576 +2610, 161,1178,4300,1983, 987,4637,1101,4301, 631,4046,1157,3229,2425,1343,1241, # 2592 +1016,2243,2570, 372, 877,2344,2508,1160, 555,1935, 911,4047,5307, 466,1170, 169, # 2608 +1051,2921,2697,3729,2481,3012,1182,2012,2571,1251,2636,5308, 992,2345,3491,1540, # 2624 +2730,1201,2071,2406,1997,2482,5309,4638, 528,1923,2191,1503,1874,1570,2369,3379, # 2640 +3309,5310, 557,1073,5311,1828,3492,2088,2271,3165,3059,3107, 767,3108,2799,4639, # 2656 +1006,4302,4640,2346,1267,2179,3730,3230, 778,4048,3231,2731,1597,2667,5312,4641, # 2672 +5313,3493,5314,5315,5316,3310,2698,1433,3311, 131, 95,1504,4049, 723,4303,3166, # 2688 +1842,3610,2768,2192,4050,2028,2105,3731,5317,3013,4051,1218,5318,3380,3232,4052, # 2704 +4304,2584, 248,1634,3864, 912,5319,2845,3732,3060,3865, 654, 53,5320,3014,5321, # 2720 +1688,4642, 777,3494,1032,4053,1425,5322, 191, 820,2121,2846, 971,4643, 931,3233, # 2736 + 135, 664, 783,3866,1998, 772,2922,1936,4054,3867,4644,2923,3234, 282,2732, 640, # 2752 +1372,3495,1127, 922, 325,3381,5323,5324, 711,2045,5325,5326,4055,2223,2800,1937, # 2768 +4056,3382,2224,2255,3868,2305,5327,4645,3869,1258,3312,4057,3235,2139,2965,4058, # 2784 +4059,5328,2225, 258,3236,4646, 101,1227,5329,3313,1755,5330,1391,3314,5331,2924, # 2800 +2057, 893,5332,5333,5334,1402,4305,2347,5335,5336,3237,3611,5337,5338, 878,1325, # 2816 +1781,2801,4647, 259,1385,2585, 744,1183,2272,4648,5339,4060,2509,5340, 684,1024, # 2832 +4306,5341, 472,3612,3496,1165,3315,4061,4062, 322,2153, 881, 455,1695,1152,1340, # 2848 + 660, 554,2154,4649,1058,4650,4307, 830,1065,3383,4063,4651,1924,5342,1703,1919, # 2864 +5343, 932,2273, 122,5344,4652, 947, 677,5345,3870,2637, 297,1906,1925,2274,4653, # 2880 +2322,3316,5346,5347,4308,5348,4309, 84,4310, 112, 989,5349, 547,1059,4064, 701, # 2896 +3613,1019,5350,4311,5351,3497, 942, 639, 457,2306,2456, 993,2966, 407, 851, 494, # 2912 +4654,3384, 927,5352,1237,5353,2426,3385, 573,4312, 680, 921,2925,1279,1875, 285, # 2928 + 790,1448,1984, 719,2168,5354,5355,4655,4065,4066,1649,5356,1541, 563,5357,1077, # 2944 +5358,3386,3061,3498, 511,3015,4067,4068,3733,4069,1268,2572,3387,3238,4656,4657, # 2960 +5359, 535,1048,1276,1189,2926,2029,3167,1438,1373,2847,2967,1134,2013,5360,4313, # 2976 +1238,2586,3109,1259,5361, 700,5362,2968,3168,3734,4314,5363,4315,1146,1876,1907, # 2992 +4658,2611,4070, 781,2427, 132,1589, 203, 147, 273,2802,2407, 898,1787,2155,4071, # 3008 +4072,5364,3871,2803,5365,5366,4659,4660,5367,3239,5368,1635,3872, 965,5369,1805, # 3024 +2699,1516,3614,1121,1082,1329,3317,4073,1449,3873, 65,1128,2848,2927,2769,1590, # 3040 +3874,5370,5371, 12,2668, 45, 976,2587,3169,4661, 517,2535,1013,1037,3240,5372, # 3056 +3875,2849,5373,3876,5374,3499,5375,2612, 614,1999,2323,3877,3110,2733,2638,5376, # 3072 +2588,4316, 599,1269,5377,1811,3735,5378,2700,3111, 759,1060, 489,1806,3388,3318, # 3088 +1358,5379,5380,2391,1387,1215,2639,2256, 490,5381,5382,4317,1759,2392,2348,5383, # 3104 +4662,3878,1908,4074,2640,1807,3241,4663,3500,3319,2770,2349, 874,5384,5385,3501, # 3120 +3736,1859, 91,2928,3737,3062,3879,4664,5386,3170,4075,2669,5387,3502,1202,1403, # 3136 +3880,2969,2536,1517,2510,4665,3503,2511,5388,4666,5389,2701,1886,1495,1731,4076, # 3152 +2370,4667,5390,2030,5391,5392,4077,2702,1216, 237,2589,4318,2324,4078,3881,4668, # 3168 +4669,2703,3615,3504, 445,4670,5393,5394,5395,5396,2771, 61,4079,3738,1823,4080, # 3184 +5397, 687,2046, 935, 925, 405,2670, 703,1096,1860,2734,4671,4081,1877,1367,2704, # 3200 +3389, 918,2106,1782,2483, 334,3320,1611,1093,4672, 564,3171,3505,3739,3390, 945, # 3216 +2641,2058,4673,5398,1926, 872,4319,5399,3506,2705,3112, 349,4320,3740,4082,4674, # 3232 +3882,4321,3741,2156,4083,4675,4676,4322,4677,2408,2047, 782,4084, 400, 251,4323, # 3248 +1624,5400,5401, 277,3742, 299,1265, 476,1191,3883,2122,4324,4325,1109, 205,5402, # 3264 +2590,1000,2157,3616,1861,5403,5404,5405,4678,5406,4679,2573, 107,2484,2158,4085, # 3280 +3507,3172,5407,1533, 541,1301, 158, 753,4326,2886,3617,5408,1696, 370,1088,4327, # 3296 +4680,3618, 579, 327, 440, 162,2244, 269,1938,1374,3508, 968,3063, 56,1396,3113, # 3312 +2107,3321,3391,5409,1927,2159,4681,3016,5410,3619,5411,5412,3743,4682,2485,5413, # 3328 +2804,5414,1650,4683,5415,2613,5416,5417,4086,2671,3392,1149,3393,4087,3884,4088, # 3344 +5418,1076, 49,5419, 951,3242,3322,3323, 450,2850, 920,5420,1812,2805,2371,4328, # 3360 +1909,1138,2372,3885,3509,5421,3243,4684,1910,1147,1518,2428,4685,3886,5422,4686, # 3376 +2393,2614, 260,1796,3244,5423,5424,3887,3324, 708,5425,3620,1704,5426,3621,1351, # 3392 +1618,3394,3017,1887, 944,4329,3395,4330,3064,3396,4331,5427,3744, 422, 413,1714, # 3408 +3325, 500,2059,2350,4332,2486,5428,1344,1911, 954,5429,1668,5430,5431,4089,2409, # 3424 +4333,3622,3888,4334,5432,2307,1318,2512,3114, 133,3115,2887,4687, 629, 31,2851, # 3440 +2706,3889,4688, 850, 949,4689,4090,2970,1732,2089,4335,1496,1853,5433,4091, 620, # 3456 +3245, 981,1242,3745,3397,1619,3746,1643,3326,2140,2457,1971,1719,3510,2169,5434, # 3472 +3246,5435,5436,3398,1829,5437,1277,4690,1565,2048,5438,1636,3623,3116,5439, 869, # 3488 +2852, 655,3890,3891,3117,4092,3018,3892,1310,3624,4691,5440,5441,5442,1733, 558, # 3504 +4692,3747, 335,1549,3065,1756,4336,3748,1946,3511,1830,1291,1192, 470,2735,2108, # 3520 +2806, 913,1054,4093,5443,1027,5444,3066,4094,4693, 982,2672,3399,3173,3512,3247, # 3536 +3248,1947,2807,5445, 571,4694,5446,1831,5447,3625,2591,1523,2429,5448,2090, 984, # 3552 +4695,3749,1960,5449,3750, 852, 923,2808,3513,3751, 969,1519, 999,2049,2325,1705, # 3568 +5450,3118, 615,1662, 151, 597,4095,2410,2326,1049, 275,4696,3752,4337, 568,3753, # 3584 +3626,2487,4338,3754,5451,2430,2275, 409,3249,5452,1566,2888,3514,1002, 769,2853, # 3600 + 194,2091,3174,3755,2226,3327,4339, 628,1505,5453,5454,1763,2180,3019,4096, 521, # 3616 +1161,2592,1788,2206,2411,4697,4097,1625,4340,4341, 412, 42,3119, 464,5455,2642, # 3632 +4698,3400,1760,1571,2889,3515,2537,1219,2207,3893,2643,2141,2373,4699,4700,3328, # 3648 +1651,3401,3627,5456,5457,3628,2488,3516,5458,3756,5459,5460,2276,2092, 460,5461, # 3664 +4701,5462,3020, 962, 588,3629, 289,3250,2644,1116, 52,5463,3067,1797,5464,5465, # 3680 +5466,1467,5467,1598,1143,3757,4342,1985,1734,1067,4702,1280,3402, 465,4703,1572, # 3696 + 510,5468,1928,2245,1813,1644,3630,5469,4704,3758,5470,5471,2673,1573,1534,5472, # 3712 +5473, 536,1808,1761,3517,3894,3175,2645,5474,5475,5476,4705,3518,2929,1912,2809, # 3728 +5477,3329,1122, 377,3251,5478, 360,5479,5480,4343,1529, 551,5481,2060,3759,1769, # 3744 +2431,5482,2930,4344,3330,3120,2327,2109,2031,4706,1404, 136,1468,1479, 672,1171, # 3760 +3252,2308, 271,3176,5483,2772,5484,2050, 678,2736, 865,1948,4707,5485,2014,4098, # 3776 +2971,5486,2737,2227,1397,3068,3760,4708,4709,1735,2931,3403,3631,5487,3895, 509, # 3792 +2854,2458,2890,3896,5488,5489,3177,3178,4710,4345,2538,4711,2309,1166,1010, 552, # 3808 + 681,1888,5490,5491,2972,2973,4099,1287,1596,1862,3179, 358, 453, 736, 175, 478, # 3824 +1117, 905,1167,1097,5492,1854,1530,5493,1706,5494,2181,3519,2292,3761,3520,3632, # 3840 +4346,2093,4347,5495,3404,1193,2489,4348,1458,2193,2208,1863,1889,1421,3331,2932, # 3856 +3069,2182,3521, 595,2123,5496,4100,5497,5498,4349,1707,2646, 223,3762,1359, 751, # 3872 +3121, 183,3522,5499,2810,3021, 419,2374, 633, 704,3897,2394, 241,5500,5501,5502, # 3888 + 838,3022,3763,2277,2773,2459,3898,1939,2051,4101,1309,3122,2246,1181,5503,1136, # 3904 +2209,3899,2375,1446,4350,2310,4712,5504,5505,4351,1055,2615, 484,3764,5506,4102, # 3920 + 625,4352,2278,3405,1499,4353,4103,5507,4104,4354,3253,2279,2280,3523,5508,5509, # 3936 +2774, 808,2616,3765,3406,4105,4355,3123,2539, 526,3407,3900,4356, 955,5510,1620, # 3952 +4357,2647,2432,5511,1429,3766,1669,1832, 994, 928,5512,3633,1260,5513,5514,5515, # 3968 +1949,2293, 741,2933,1626,4358,2738,2460, 867,1184, 362,3408,1392,5516,5517,4106, # 3984 +4359,1770,1736,3254,2934,4713,4714,1929,2707,1459,1158,5518,3070,3409,2891,1292, # 4000 +1930,2513,2855,3767,1986,1187,2072,2015,2617,4360,5519,2574,2514,2170,3768,2490, # 4016 +3332,5520,3769,4715,5521,5522, 666,1003,3023,1022,3634,4361,5523,4716,1814,2257, # 4032 + 574,3901,1603, 295,1535, 705,3902,4362, 283, 858, 417,5524,5525,3255,4717,4718, # 4048 +3071,1220,1890,1046,2281,2461,4107,1393,1599, 689,2575, 388,4363,5526,2491, 802, # 4064 +5527,2811,3903,2061,1405,2258,5528,4719,3904,2110,1052,1345,3256,1585,5529, 809, # 4080 +5530,5531,5532, 575,2739,3524, 956,1552,1469,1144,2328,5533,2329,1560,2462,3635, # 4096 +3257,4108, 616,2210,4364,3180,2183,2294,5534,1833,5535,3525,4720,5536,1319,3770, # 4112 +3771,1211,3636,1023,3258,1293,2812,5537,5538,5539,3905, 607,2311,3906, 762,2892, # 4128 +1439,4365,1360,4721,1485,3072,5540,4722,1038,4366,1450,2062,2648,4367,1379,4723, # 4144 +2593,5541,5542,4368,1352,1414,2330,2935,1172,5543,5544,3907,3908,4724,1798,1451, # 4160 +5545,5546,5547,5548,2936,4109,4110,2492,2351, 411,4111,4112,3637,3333,3124,4725, # 4176 +1561,2674,1452,4113,1375,5549,5550, 47,2974, 316,5551,1406,1591,2937,3181,5552, # 4192 +1025,2142,3125,3182, 354,2740, 884,2228,4369,2412, 508,3772, 726,3638, 996,2433, # 4208 +3639, 729,5553, 392,2194,1453,4114,4726,3773,5554,5555,2463,3640,2618,1675,2813, # 4224 + 919,2352,2975,2353,1270,4727,4115, 73,5556,5557, 647,5558,3259,2856,2259,1550, # 4240 +1346,3024,5559,1332, 883,3526,5560,5561,5562,5563,3334,2775,5564,1212, 831,1347, # 4256 +4370,4728,2331,3909,1864,3073, 720,3910,4729,4730,3911,5565,4371,5566,5567,4731, # 4272 +5568,5569,1799,4732,3774,2619,4733,3641,1645,2376,4734,5570,2938, 669,2211,2675, # 4288 +2434,5571,2893,5572,5573,1028,3260,5574,4372,2413,5575,2260,1353,5576,5577,4735, # 4304 +3183, 518,5578,4116,5579,4373,1961,5580,2143,4374,5581,5582,3025,2354,2355,3912, # 4320 + 516,1834,1454,4117,2708,4375,4736,2229,2620,1972,1129,3642,5583,2776,5584,2976, # 4336 +1422, 577,1470,3026,1524,3410,5585,5586, 432,4376,3074,3527,5587,2594,1455,2515, # 4352 +2230,1973,1175,5588,1020,2741,4118,3528,4737,5589,2742,5590,1743,1361,3075,3529, # 4368 +2649,4119,4377,4738,2295, 895, 924,4378,2171, 331,2247,3076, 166,1627,3077,1098, # 4384 +5591,1232,2894,2231,3411,4739, 657, 403,1196,2377, 542,3775,3412,1600,4379,3530, # 4400 +5592,4740,2777,3261, 576, 530,1362,4741,4742,2540,2676,3776,4120,5593, 842,3913, # 4416 +5594,2814,2032,1014,4121, 213,2709,3413, 665, 621,4380,5595,3777,2939,2435,5596, # 4432 +2436,3335,3643,3414,4743,4381,2541,4382,4744,3644,1682,4383,3531,1380,5597, 724, # 4448 +2282, 600,1670,5598,1337,1233,4745,3126,2248,5599,1621,4746,5600, 651,4384,5601, # 4464 +1612,4385,2621,5602,2857,5603,2743,2312,3078,5604, 716,2464,3079, 174,1255,2710, # 4480 +4122,3645, 548,1320,1398, 728,4123,1574,5605,1891,1197,3080,4124,5606,3081,3082, # 4496 +3778,3646,3779, 747,5607, 635,4386,4747,5608,5609,5610,4387,5611,5612,4748,5613, # 4512 +3415,4749,2437, 451,5614,3780,2542,2073,4388,2744,4389,4125,5615,1764,4750,5616, # 4528 +4390, 350,4751,2283,2395,2493,5617,4391,4126,2249,1434,4127, 488,4752, 458,4392, # 4544 +4128,3781, 771,1330,2396,3914,2576,3184,2160,2414,1553,2677,3185,4393,5618,2494, # 4560 +2895,2622,1720,2711,4394,3416,4753,5619,2543,4395,5620,3262,4396,2778,5621,2016, # 4576 +2745,5622,1155,1017,3782,3915,5623,3336,2313, 201,1865,4397,1430,5624,4129,5625, # 4592 +5626,5627,5628,5629,4398,1604,5630, 414,1866, 371,2595,4754,4755,3532,2017,3127, # 4608 +4756,1708, 960,4399, 887, 389,2172,1536,1663,1721,5631,2232,4130,2356,2940,1580, # 4624 +5632,5633,1744,4757,2544,4758,4759,5634,4760,5635,2074,5636,4761,3647,3417,2896, # 4640 +4400,5637,4401,2650,3418,2815, 673,2712,2465, 709,3533,4131,3648,4402,5638,1148, # 4656 + 502, 634,5639,5640,1204,4762,3649,1575,4763,2623,3783,5641,3784,3128, 948,3263, # 4672 + 121,1745,3916,1110,5642,4403,3083,2516,3027,4132,3785,1151,1771,3917,1488,4133, # 4688 +1987,5643,2438,3534,5644,5645,2094,5646,4404,3918,1213,1407,2816, 531,2746,2545, # 4704 +3264,1011,1537,4764,2779,4405,3129,1061,5647,3786,3787,1867,2897,5648,2018, 120, # 4720 +4406,4407,2063,3650,3265,2314,3919,2678,3419,1955,4765,4134,5649,3535,1047,2713, # 4736 +1266,5650,1368,4766,2858, 649,3420,3920,2546,2747,1102,2859,2679,5651,5652,2000, # 4752 +5653,1111,3651,2977,5654,2495,3921,3652,2817,1855,3421,3788,5655,5656,3422,2415, # 4768 +2898,3337,3266,3653,5657,2577,5658,3654,2818,4135,1460, 856,5659,3655,5660,2899, # 4784 +2978,5661,2900,3922,5662,4408, 632,2517, 875,3923,1697,3924,2296,5663,5664,4767, # 4800 +3028,1239, 580,4768,4409,5665, 914, 936,2075,1190,4136,1039,2124,5666,5667,5668, # 4816 +5669,3423,1473,5670,1354,4410,3925,4769,2173,3084,4137, 915,3338,4411,4412,3339, # 4832 +1605,1835,5671,2748, 398,3656,4413,3926,4138, 328,1913,2860,4139,3927,1331,4414, # 4848 +3029, 937,4415,5672,3657,4140,4141,3424,2161,4770,3425, 524, 742, 538,3085,1012, # 4864 +5673,5674,3928,2466,5675, 658,1103, 225,3929,5676,5677,4771,5678,4772,5679,3267, # 4880 +1243,5680,4142, 963,2250,4773,5681,2714,3658,3186,5682,5683,2596,2332,5684,4774, # 4896 +5685,5686,5687,3536, 957,3426,2547,2033,1931,2941,2467, 870,2019,3659,1746,2780, # 4912 +2781,2439,2468,5688,3930,5689,3789,3130,3790,3537,3427,3791,5690,1179,3086,5691, # 4928 +3187,2378,4416,3792,2548,3188,3131,2749,4143,5692,3428,1556,2549,2297, 977,2901, # 4944 +2034,4144,1205,3429,5693,1765,3430,3189,2125,1271, 714,1689,4775,3538,5694,2333, # 4960 +3931, 533,4417,3660,2184, 617,5695,2469,3340,3539,2315,5696,5697,3190,5698,5699, # 4976 +3932,1988, 618, 427,2651,3540,3431,5700,5701,1244,1690,5702,2819,4418,4776,5703, # 4992 +3541,4777,5704,2284,1576, 473,3661,4419,3432, 972,5705,3662,5706,3087,5707,5708, # 5008 +4778,4779,5709,3793,4145,4146,5710, 153,4780, 356,5711,1892,2902,4420,2144, 408, # 5024 + 803,2357,5712,3933,5713,4421,1646,2578,2518,4781,4782,3934,5714,3935,4422,5715, # 5040 +2416,3433, 752,5716,5717,1962,3341,2979,5718, 746,3030,2470,4783,4423,3794, 698, # 5056 +4784,1893,4424,3663,2550,4785,3664,3936,5719,3191,3434,5720,1824,1302,4147,2715, # 5072 +3937,1974,4425,5721,4426,3192, 823,1303,1288,1236,2861,3542,4148,3435, 774,3938, # 5088 +5722,1581,4786,1304,2862,3939,4787,5723,2440,2162,1083,3268,4427,4149,4428, 344, # 5104 +1173, 288,2316, 454,1683,5724,5725,1461,4788,4150,2597,5726,5727,4789, 985, 894, # 5120 +5728,3436,3193,5729,1914,2942,3795,1989,5730,2111,1975,5731,4151,5732,2579,1194, # 5136 + 425,5733,4790,3194,1245,3796,4429,5734,5735,2863,5736, 636,4791,1856,3940, 760, # 5152 +1800,5737,4430,2212,1508,4792,4152,1894,1684,2298,5738,5739,4793,4431,4432,2213, # 5168 + 479,5740,5741, 832,5742,4153,2496,5743,2980,2497,3797, 990,3132, 627,1815,2652, # 5184 +4433,1582,4434,2126,2112,3543,4794,5744, 799,4435,3195,5745,4795,2113,1737,3031, # 5200 +1018, 543, 754,4436,3342,1676,4796,4797,4154,4798,1489,5746,3544,5747,2624,2903, # 5216 +4155,5748,5749,2981,5750,5751,5752,5753,3196,4799,4800,2185,1722,5754,3269,3270, # 5232 +1843,3665,1715, 481, 365,1976,1857,5755,5756,1963,2498,4801,5757,2127,3666,3271, # 5248 + 433,1895,2064,2076,5758, 602,2750,5759,5760,5761,5762,5763,3032,1628,3437,5764, # 5264 +3197,4802,4156,2904,4803,2519,5765,2551,2782,5766,5767,5768,3343,4804,2905,5769, # 5280 +4805,5770,2864,4806,4807,1221,2982,4157,2520,5771,5772,5773,1868,1990,5774,5775, # 5296 +5776,1896,5777,5778,4808,1897,4158, 318,5779,2095,4159,4437,5780,5781, 485,5782, # 5312 + 938,3941, 553,2680, 116,5783,3942,3667,5784,3545,2681,2783,3438,3344,2820,5785, # 5328 +3668,2943,4160,1747,2944,2983,5786,5787, 207,5788,4809,5789,4810,2521,5790,3033, # 5344 + 890,3669,3943,5791,1878,3798,3439,5792,2186,2358,3440,1652,5793,5794,5795, 941, # 5360 +2299, 208,3546,4161,2020, 330,4438,3944,2906,2499,3799,4439,4811,5796,5797,5798, # 5376 +) + diff --git a/venv/Lib/site-packages/pip/_vendor/chardet/big5prober.py b/venv/Lib/site-packages/pip/_vendor/chardet/big5prober.py new file mode 100644 index 0000000..98f9970 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/chardet/big5prober.py @@ -0,0 +1,47 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .mbcharsetprober import MultiByteCharSetProber +from .codingstatemachine import CodingStateMachine +from .chardistribution import Big5DistributionAnalysis +from .mbcssm import BIG5_SM_MODEL + + +class Big5Prober(MultiByteCharSetProber): + def __init__(self): + super(Big5Prober, self).__init__() + self.coding_sm = CodingStateMachine(BIG5_SM_MODEL) + self.distribution_analyzer = Big5DistributionAnalysis() + self.reset() + + @property + def charset_name(self): + return "Big5" + + @property + def language(self): + return "Chinese" diff --git a/venv/Lib/site-packages/pip/_vendor/chardet/chardistribution.py b/venv/Lib/site-packages/pip/_vendor/chardet/chardistribution.py new file mode 100644 index 0000000..c0395f4 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/chardet/chardistribution.py @@ -0,0 +1,233 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .euctwfreq import (EUCTW_CHAR_TO_FREQ_ORDER, EUCTW_TABLE_SIZE, + EUCTW_TYPICAL_DISTRIBUTION_RATIO) +from .euckrfreq import (EUCKR_CHAR_TO_FREQ_ORDER, EUCKR_TABLE_SIZE, + EUCKR_TYPICAL_DISTRIBUTION_RATIO) +from .gb2312freq import (GB2312_CHAR_TO_FREQ_ORDER, GB2312_TABLE_SIZE, + GB2312_TYPICAL_DISTRIBUTION_RATIO) +from .big5freq import (BIG5_CHAR_TO_FREQ_ORDER, BIG5_TABLE_SIZE, + BIG5_TYPICAL_DISTRIBUTION_RATIO) +from .jisfreq import (JIS_CHAR_TO_FREQ_ORDER, JIS_TABLE_SIZE, + JIS_TYPICAL_DISTRIBUTION_RATIO) + + +class CharDistributionAnalysis(object): + ENOUGH_DATA_THRESHOLD = 1024 + SURE_YES = 0.99 + SURE_NO = 0.01 + MINIMUM_DATA_THRESHOLD = 3 + + def __init__(self): + # Mapping table to get frequency order from char order (get from + # GetOrder()) + self._char_to_freq_order = None + self._table_size = None # Size of above table + # This is a constant value which varies from language to language, + # used in calculating confidence. See + # http://www.mozilla.org/projects/intl/UniversalCharsetDetection.html + # for further detail. + self.typical_distribution_ratio = None + self._done = None + self._total_chars = None + self._freq_chars = None + self.reset() + + def reset(self): + """reset analyser, clear any state""" + # If this flag is set to True, detection is done and conclusion has + # been made + self._done = False + self._total_chars = 0 # Total characters encountered + # The number of characters whose frequency order is less than 512 + self._freq_chars = 0 + + def feed(self, char, char_len): + """feed a character with known length""" + if char_len == 2: + # we only care about 2-bytes character in our distribution analysis + order = self.get_order(char) + else: + order = -1 + if order >= 0: + self._total_chars += 1 + # order is valid + if order < self._table_size: + if 512 > self._char_to_freq_order[order]: + self._freq_chars += 1 + + def get_confidence(self): + """return confidence based on existing data""" + # if we didn't receive any character in our consideration range, + # return negative answer + if self._total_chars <= 0 or self._freq_chars <= self.MINIMUM_DATA_THRESHOLD: + return self.SURE_NO + + if self._total_chars != self._freq_chars: + r = (self._freq_chars / ((self._total_chars - self._freq_chars) + * self.typical_distribution_ratio)) + if r < self.SURE_YES: + return r + + # normalize confidence (we don't want to be 100% sure) + return self.SURE_YES + + def got_enough_data(self): + # It is not necessary to receive all data to draw conclusion. + # For charset detection, certain amount of data is enough + return self._total_chars > self.ENOUGH_DATA_THRESHOLD + + def get_order(self, byte_str): + # We do not handle characters based on the original encoding string, + # but convert this encoding string to a number, here called order. + # This allows multiple encodings of a language to share one frequency + # table. + return -1 + + +class EUCTWDistributionAnalysis(CharDistributionAnalysis): + def __init__(self): + super(EUCTWDistributionAnalysis, self).__init__() + self._char_to_freq_order = EUCTW_CHAR_TO_FREQ_ORDER + self._table_size = EUCTW_TABLE_SIZE + self.typical_distribution_ratio = EUCTW_TYPICAL_DISTRIBUTION_RATIO + + def get_order(self, byte_str): + # for euc-TW encoding, we are interested + # first byte range: 0xc4 -- 0xfe + # second byte range: 0xa1 -- 0xfe + # no validation needed here. State machine has done that + first_char = byte_str[0] + if first_char >= 0xC4: + return 94 * (first_char - 0xC4) + byte_str[1] - 0xA1 + else: + return -1 + + +class EUCKRDistributionAnalysis(CharDistributionAnalysis): + def __init__(self): + super(EUCKRDistributionAnalysis, self).__init__() + self._char_to_freq_order = EUCKR_CHAR_TO_FREQ_ORDER + self._table_size = EUCKR_TABLE_SIZE + self.typical_distribution_ratio = EUCKR_TYPICAL_DISTRIBUTION_RATIO + + def get_order(self, byte_str): + # for euc-KR encoding, we are interested + # first byte range: 0xb0 -- 0xfe + # second byte range: 0xa1 -- 0xfe + # no validation needed here. State machine has done that + first_char = byte_str[0] + if first_char >= 0xB0: + return 94 * (first_char - 0xB0) + byte_str[1] - 0xA1 + else: + return -1 + + +class GB2312DistributionAnalysis(CharDistributionAnalysis): + def __init__(self): + super(GB2312DistributionAnalysis, self).__init__() + self._char_to_freq_order = GB2312_CHAR_TO_FREQ_ORDER + self._table_size = GB2312_TABLE_SIZE + self.typical_distribution_ratio = GB2312_TYPICAL_DISTRIBUTION_RATIO + + def get_order(self, byte_str): + # for GB2312 encoding, we are interested + # first byte range: 0xb0 -- 0xfe + # second byte range: 0xa1 -- 0xfe + # no validation needed here. State machine has done that + first_char, second_char = byte_str[0], byte_str[1] + if (first_char >= 0xB0) and (second_char >= 0xA1): + return 94 * (first_char - 0xB0) + second_char - 0xA1 + else: + return -1 + + +class Big5DistributionAnalysis(CharDistributionAnalysis): + def __init__(self): + super(Big5DistributionAnalysis, self).__init__() + self._char_to_freq_order = BIG5_CHAR_TO_FREQ_ORDER + self._table_size = BIG5_TABLE_SIZE + self.typical_distribution_ratio = BIG5_TYPICAL_DISTRIBUTION_RATIO + + def get_order(self, byte_str): + # for big5 encoding, we are interested + # first byte range: 0xa4 -- 0xfe + # second byte range: 0x40 -- 0x7e , 0xa1 -- 0xfe + # no validation needed here. State machine has done that + first_char, second_char = byte_str[0], byte_str[1] + if first_char >= 0xA4: + if second_char >= 0xA1: + return 157 * (first_char - 0xA4) + second_char - 0xA1 + 63 + else: + return 157 * (first_char - 0xA4) + second_char - 0x40 + else: + return -1 + + +class SJISDistributionAnalysis(CharDistributionAnalysis): + def __init__(self): + super(SJISDistributionAnalysis, self).__init__() + self._char_to_freq_order = JIS_CHAR_TO_FREQ_ORDER + self._table_size = JIS_TABLE_SIZE + self.typical_distribution_ratio = JIS_TYPICAL_DISTRIBUTION_RATIO + + def get_order(self, byte_str): + # for sjis encoding, we are interested + # first byte range: 0x81 -- 0x9f , 0xe0 -- 0xfe + # second byte range: 0x40 -- 0x7e, 0x81 -- oxfe + # no validation needed here. State machine has done that + first_char, second_char = byte_str[0], byte_str[1] + if (first_char >= 0x81) and (first_char <= 0x9F): + order = 188 * (first_char - 0x81) + elif (first_char >= 0xE0) and (first_char <= 0xEF): + order = 188 * (first_char - 0xE0 + 31) + else: + return -1 + order = order + second_char - 0x40 + if second_char > 0x7F: + order = -1 + return order + + +class EUCJPDistributionAnalysis(CharDistributionAnalysis): + def __init__(self): + super(EUCJPDistributionAnalysis, self).__init__() + self._char_to_freq_order = JIS_CHAR_TO_FREQ_ORDER + self._table_size = JIS_TABLE_SIZE + self.typical_distribution_ratio = JIS_TYPICAL_DISTRIBUTION_RATIO + + def get_order(self, byte_str): + # for euc-JP encoding, we are interested + # first byte range: 0xa0 -- 0xfe + # second byte range: 0xa1 -- 0xfe + # no validation needed here. State machine has done that + char = byte_str[0] + if char >= 0xA0: + return 94 * (char - 0xA1) + byte_str[1] - 0xa1 + else: + return -1 diff --git a/venv/Lib/site-packages/pip/_vendor/chardet/charsetgroupprober.py b/venv/Lib/site-packages/pip/_vendor/chardet/charsetgroupprober.py new file mode 100644 index 0000000..5812cef --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/chardet/charsetgroupprober.py @@ -0,0 +1,107 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .enums import ProbingState +from .charsetprober import CharSetProber + + +class CharSetGroupProber(CharSetProber): + def __init__(self, lang_filter=None): + super(CharSetGroupProber, self).__init__(lang_filter=lang_filter) + self._active_num = 0 + self.probers = [] + self._best_guess_prober = None + + def reset(self): + super(CharSetGroupProber, self).reset() + self._active_num = 0 + for prober in self.probers: + if prober: + prober.reset() + prober.active = True + self._active_num += 1 + self._best_guess_prober = None + + @property + def charset_name(self): + if not self._best_guess_prober: + self.get_confidence() + if not self._best_guess_prober: + return None + return self._best_guess_prober.charset_name + + @property + def language(self): + if not self._best_guess_prober: + self.get_confidence() + if not self._best_guess_prober: + return None + return self._best_guess_prober.language + + def feed(self, byte_str): + for prober in self.probers: + if not prober: + continue + if not prober.active: + continue + state = prober.feed(byte_str) + if not state: + continue + if state == ProbingState.FOUND_IT: + self._best_guess_prober = prober + self._state = ProbingState.FOUND_IT + return self.state + elif state == ProbingState.NOT_ME: + prober.active = False + self._active_num -= 1 + if self._active_num <= 0: + self._state = ProbingState.NOT_ME + return self.state + return self.state + + def get_confidence(self): + state = self.state + if state == ProbingState.FOUND_IT: + return 0.99 + elif state == ProbingState.NOT_ME: + return 0.01 + best_conf = 0.0 + self._best_guess_prober = None + for prober in self.probers: + if not prober: + continue + if not prober.active: + self.logger.debug('%s not active', prober.charset_name) + continue + conf = prober.get_confidence() + self.logger.debug('%s %s confidence = %s', prober.charset_name, prober.language, conf) + if best_conf < conf: + best_conf = conf + self._best_guess_prober = prober + if not self._best_guess_prober: + return 0.0 + return best_conf diff --git a/venv/Lib/site-packages/pip/_vendor/chardet/charsetprober.py b/venv/Lib/site-packages/pip/_vendor/chardet/charsetprober.py new file mode 100644 index 0000000..eac4e59 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/chardet/charsetprober.py @@ -0,0 +1,145 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Universal charset detector code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 2001 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# Shy Shalom - original C code +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +import logging +import re + +from .enums import ProbingState + + +class CharSetProber(object): + + SHORTCUT_THRESHOLD = 0.95 + + def __init__(self, lang_filter=None): + self._state = None + self.lang_filter = lang_filter + self.logger = logging.getLogger(__name__) + + def reset(self): + self._state = ProbingState.DETECTING + + @property + def charset_name(self): + return None + + def feed(self, buf): + pass + + @property + def state(self): + return self._state + + def get_confidence(self): + return 0.0 + + @staticmethod + def filter_high_byte_only(buf): + buf = re.sub(b'([\x00-\x7F])+', b' ', buf) + return buf + + @staticmethod + def filter_international_words(buf): + """ + We define three types of bytes: + alphabet: english alphabets [a-zA-Z] + international: international characters [\x80-\xFF] + marker: everything else [^a-zA-Z\x80-\xFF] + + The input buffer can be thought to contain a series of words delimited + by markers. This function works to filter all words that contain at + least one international character. All contiguous sequences of markers + are replaced by a single space ascii character. + + This filter applies to all scripts which do not use English characters. + """ + filtered = bytearray() + + # This regex expression filters out only words that have at-least one + # international character. The word may include one marker character at + # the end. + words = re.findall(b'[a-zA-Z]*[\x80-\xFF]+[a-zA-Z]*[^a-zA-Z\x80-\xFF]?', + buf) + + for word in words: + filtered.extend(word[:-1]) + + # If the last character in the word is a marker, replace it with a + # space as markers shouldn't affect our analysis (they are used + # similarly across all languages and may thus have similar + # frequencies). + last_char = word[-1:] + if not last_char.isalpha() and last_char < b'\x80': + last_char = b' ' + filtered.extend(last_char) + + return filtered + + @staticmethod + def filter_with_english_letters(buf): + """ + Returns a copy of ``buf`` that retains only the sequences of English + alphabet and high byte characters that are not between <> characters. + Also retains English alphabet and high byte characters immediately + before occurrences of >. + + This filter can be applied to all scripts which contain both English + characters and extended ASCII characters, but is currently only used by + ``Latin1Prober``. + """ + filtered = bytearray() + in_tag = False + prev = 0 + + for curr in range(len(buf)): + # Slice here to get bytes instead of an int with Python 3 + buf_char = buf[curr:curr + 1] + # Check if we're coming out of or entering an HTML tag + if buf_char == b'>': + in_tag = False + elif buf_char == b'<': + in_tag = True + + # If current character is not extended-ASCII and not alphabetic... + if buf_char < b'\x80' and not buf_char.isalpha(): + # ...and we're not in a tag + if curr > prev and not in_tag: + # Keep everything after last non-extended-ASCII, + # non-alphabetic character + filtered.extend(buf[prev:curr]) + # Output a space to delimit stretch we kept + filtered.extend(b' ') + prev = curr + 1 + + # If we're not in a tag... + if not in_tag: + # Keep everything after last non-extended-ASCII, non-alphabetic + # character + filtered.extend(buf[prev:]) + + return filtered diff --git a/venv/Lib/site-packages/pip/_vendor/chardet/cli/__init__.py b/venv/Lib/site-packages/pip/_vendor/chardet/cli/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/chardet/cli/__init__.py @@ -0,0 +1 @@ + diff --git a/venv/Lib/site-packages/pip/_vendor/chardet/cli/__pycache__/__init__.cpython-39.pyc b/venv/Lib/site-packages/pip/_vendor/chardet/cli/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6354d236b1e8ad2c76c7fcefc282c4d40f774e63 GIT binary patch literal 188 zcmYe~<>g`kf?j#GBt{_p7{oyaAVCKpE@lA|DGb33nv8xc8Hzx{2;x_wvsFxJacWU< zOk!SMVsVUPL4iwRNn(soesW??Oh{^OK}K+FID Dqa-pc literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_vendor/chardet/cli/__pycache__/chardetect.cpython-39.pyc b/venv/Lib/site-packages/pip/_vendor/chardet/cli/__pycache__/chardetect.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4b77f31ce2c57fcf0d49424a494c2b36125d22a8 GIT binary patch literal 2682 zcma)8-EJGl72ZECsTD;lX&S(3>&`{ont@2fMqLC%Q8chyG=L!(i4q_z)Aev?D6X`B zo*7CNOG<#;|%-K2TeCIpldwY?C=lYkw z8vh&8w=~&)d`$j;f2}YGXXpr5c$u4fLofG-ejW@1m)88OF>KWDa2VnpWX-%aY}I>> zY$uO~Q7wnrZr&cYA@7Nn*!jCV+!GxUiCst?c}KKQJypogl>-g`3#WUB-*X)&`XW(j zW!U*NO{UE7Q>j^5NLDJAmrAlpnn_l1Gu4b2f+<;*%8&{(Q<*9zq>+h{B9cW?inKV^ zQS`^Z@x039U=T$N&wZ9mxmqbQUFNd3NkR!5ie|OmW^2IC(?XQzy7%zW<42g7DND*? zk_vo7vXA?ZZ`E%N3>eo*n!cs{u>WxseKui5xp4wMRjNFLF>%0BvvxU!Piaxj44bGj zXWGD(eiZ!&sd2i#y~D@4%w|T$X-)yKol2#Ji6^rnF=<)Y{aKO1e;H?~k&0*fupBbX#8*JV%Y&B@R)Zz-jJ3vPU_y1caBrHXb+fYsqL$vJ zy9k7L*HM}9Z=%I|hPB|XvjjFogI1R=q!37H&cCZ8{<$ z>zI!LmkktHIe~JW?NZeivQ!&dT^Z1bFacyxam90%rG?Z3b_7$k$V|zOB{GDCEtCD# z8FNvs^#<%SiaC85rpFgX>TRw4> z2HVSNkyZ zFGt%Ym9!RSj3_>Fi`a6S68s-AMgN6*THXQLyTSEDMedb6V9$*B~*^Qn|s@3)_v zq&m@a+8Y7XC{Hz7SM?~#(v6IW_NxoqSs|mM@W$nYKCJIyaH7y{;V<$+m!!}Q+Y01^ePE`onRFwTifG(gY=n=%!_Mpt*bP(<(sjEL{|pce0DJ`UvIZ-?W#GIx~Bs4I3S?ckQ{3 z*)w+**gM(3@~%*7FGr$71Umn=hR2^ljK~QfmFL8f6m!Pa@eCOPt?IX@eYBg1NPztu+k^% ze|b3g=EVz^YBtlblNNvw$1Uj0pf0A>9kxoe-kX1Q^kbU>3U#X^++OAlVFOxC{I~@Z z+oP*t#Ee z0~<_bR@s0&w~Ye6Yuj8a&v$ygHF4YKTA1(Ne*l6z?rM~M*Rvt7$wPezRL=kTbvZ-E zB~!DaAUfP?cxV$KCn%rE?4r+}qqsGDa`gGL-cx4IQ#3TbqPQ9tL`IyAGhUpoa0F*H z*oS9p8Uz9+?4q2hRlDjlq#9Fp&I`lHr31Re_62%9T8Ka$?LxEBN?K2zJCsjSu)}7QmwHiJkLqX2d;xQymv37O>*LxlMq3d~( z`|kh31_d+`tdM3j_5VI@gM0I!Ud!zI4|;?C#rU9E&oEV;jZj-sopCjukat z<;DHAqD(OShfDuuc1=a{a_W8 t&83OEaVH|pt)UJ@>vwr6W|{mwk))>J2c7pk1i)*9L)(7z^XOj7{XY-e9z6g6 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_vendor/chardet/cli/chardetect.py b/venv/Lib/site-packages/pip/_vendor/chardet/cli/chardetect.py new file mode 100644 index 0000000..6d6f93a --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/chardet/cli/chardetect.py @@ -0,0 +1,84 @@ +""" +Script which takes one or more file paths and reports on their detected +encodings + +Example:: + + % chardetect somefile someotherfile + somefile: windows-1252 with confidence 0.5 + someotherfile: ascii with confidence 1.0 + +If no paths are provided, it takes its input from stdin. + +""" + +from __future__ import absolute_import, print_function, unicode_literals + +import argparse +import sys + +from pip._vendor.chardet import __version__ +from pip._vendor.chardet.compat import PY2 +from pip._vendor.chardet.universaldetector import UniversalDetector + + +def description_of(lines, name='stdin'): + """ + Return a string describing the probable encoding of a file or + list of strings. + + :param lines: The lines to get the encoding of. + :type lines: Iterable of bytes + :param name: Name of file or collection of lines + :type name: str + """ + u = UniversalDetector() + for line in lines: + line = bytearray(line) + u.feed(line) + # shortcut out of the loop to save reading further - particularly useful if we read a BOM. + if u.done: + break + u.close() + result = u.result + if PY2: + name = name.decode(sys.getfilesystemencoding(), 'ignore') + if result['encoding']: + return '{}: {} with confidence {}'.format(name, result['encoding'], + result['confidence']) + else: + return '{}: no result'.format(name) + + +def main(argv=None): + """ + Handles command line arguments and gets things started. + + :param argv: List of arguments, as if specified on the command-line. + If None, ``sys.argv[1:]`` is used instead. + :type argv: list of str + """ + # Get command line arguments + parser = argparse.ArgumentParser( + description="Takes one or more file paths and reports their detected \ + encodings") + parser.add_argument('input', + help='File whose encoding we would like to determine. \ + (default: stdin)', + type=argparse.FileType('rb'), nargs='*', + default=[sys.stdin if PY2 else sys.stdin.buffer]) + parser.add_argument('--version', action='version', + version='%(prog)s {}'.format(__version__)) + args = parser.parse_args(argv) + + for f in args.input: + if f.isatty(): + print("You are running chardetect interactively. Press " + + "CTRL-D twice at the start of a blank line to signal the " + + "end of your input. If you want help, run chardetect " + + "--help\n", file=sys.stderr) + print(description_of(f, f.name)) + + +if __name__ == '__main__': + main() diff --git a/venv/Lib/site-packages/pip/_vendor/chardet/codingstatemachine.py b/venv/Lib/site-packages/pip/_vendor/chardet/codingstatemachine.py new file mode 100644 index 0000000..68fba44 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/chardet/codingstatemachine.py @@ -0,0 +1,88 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +import logging + +from .enums import MachineState + + +class CodingStateMachine(object): + """ + A state machine to verify a byte sequence for a particular encoding. For + each byte the detector receives, it will feed that byte to every active + state machine available, one byte at a time. The state machine changes its + state based on its previous state and the byte it receives. There are 3 + states in a state machine that are of interest to an auto-detector: + + START state: This is the state to start with, or a legal byte sequence + (i.e. a valid code point) for character has been identified. + + ME state: This indicates that the state machine identified a byte sequence + that is specific to the charset it is designed for and that + there is no other possible encoding which can contain this byte + sequence. This will to lead to an immediate positive answer for + the detector. + + ERROR state: This indicates the state machine identified an illegal byte + sequence for that encoding. This will lead to an immediate + negative answer for this encoding. Detector will exclude this + encoding from consideration from here on. + """ + def __init__(self, sm): + self._model = sm + self._curr_byte_pos = 0 + self._curr_char_len = 0 + self._curr_state = None + self.logger = logging.getLogger(__name__) + self.reset() + + def reset(self): + self._curr_state = MachineState.START + + def next_state(self, c): + # for each byte we get its class + # if it is first byte, we also get byte length + byte_class = self._model['class_table'][c] + if self._curr_state == MachineState.START: + self._curr_byte_pos = 0 + self._curr_char_len = self._model['char_len_table'][byte_class] + # from byte's class and state_table, we get its next state + curr_state = (self._curr_state * self._model['class_factor'] + + byte_class) + self._curr_state = self._model['state_table'][curr_state] + self._curr_byte_pos += 1 + return self._curr_state + + def get_current_charlen(self): + return self._curr_char_len + + def get_coding_state_machine(self): + return self._model['name'] + + @property + def language(self): + return self._model['language'] diff --git a/venv/Lib/site-packages/pip/_vendor/chardet/compat.py b/venv/Lib/site-packages/pip/_vendor/chardet/compat.py new file mode 100644 index 0000000..8941572 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/chardet/compat.py @@ -0,0 +1,36 @@ +######################## BEGIN LICENSE BLOCK ######################## +# Contributor(s): +# Dan Blanchard +# Ian Cordasco +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +import sys + + +if sys.version_info < (3, 0): + PY2 = True + PY3 = False + string_types = (str, unicode) + text_type = unicode + iteritems = dict.iteritems +else: + PY2 = False + PY3 = True + string_types = (bytes, str) + text_type = str + iteritems = dict.items diff --git a/venv/Lib/site-packages/pip/_vendor/chardet/cp949prober.py b/venv/Lib/site-packages/pip/_vendor/chardet/cp949prober.py new file mode 100644 index 0000000..efd793a --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/chardet/cp949prober.py @@ -0,0 +1,49 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .chardistribution import EUCKRDistributionAnalysis +from .codingstatemachine import CodingStateMachine +from .mbcharsetprober import MultiByteCharSetProber +from .mbcssm import CP949_SM_MODEL + + +class CP949Prober(MultiByteCharSetProber): + def __init__(self): + super(CP949Prober, self).__init__() + self.coding_sm = CodingStateMachine(CP949_SM_MODEL) + # NOTE: CP949 is a superset of EUC-KR, so the distribution should be + # not different. + self.distribution_analyzer = EUCKRDistributionAnalysis() + self.reset() + + @property + def charset_name(self): + return "CP949" + + @property + def language(self): + return "Korean" diff --git a/venv/Lib/site-packages/pip/_vendor/chardet/enums.py b/venv/Lib/site-packages/pip/_vendor/chardet/enums.py new file mode 100644 index 0000000..0451207 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/chardet/enums.py @@ -0,0 +1,76 @@ +""" +All of the Enums that are used throughout the chardet package. + +:author: Dan Blanchard (dan.blanchard@gmail.com) +""" + + +class InputState(object): + """ + This enum represents the different states a universal detector can be in. + """ + PURE_ASCII = 0 + ESC_ASCII = 1 + HIGH_BYTE = 2 + + +class LanguageFilter(object): + """ + This enum represents the different language filters we can apply to a + ``UniversalDetector``. + """ + CHINESE_SIMPLIFIED = 0x01 + CHINESE_TRADITIONAL = 0x02 + JAPANESE = 0x04 + KOREAN = 0x08 + NON_CJK = 0x10 + ALL = 0x1F + CHINESE = CHINESE_SIMPLIFIED | CHINESE_TRADITIONAL + CJK = CHINESE | JAPANESE | KOREAN + + +class ProbingState(object): + """ + This enum represents the different states a prober can be in. + """ + DETECTING = 0 + FOUND_IT = 1 + NOT_ME = 2 + + +class MachineState(object): + """ + This enum represents the different states a state machine can be in. + """ + START = 0 + ERROR = 1 + ITS_ME = 2 + + +class SequenceLikelihood(object): + """ + This enum represents the likelihood of a character following the previous one. + """ + NEGATIVE = 0 + UNLIKELY = 1 + LIKELY = 2 + POSITIVE = 3 + + @classmethod + def get_num_categories(cls): + """:returns: The number of likelihood categories in the enum.""" + return 4 + + +class CharacterCategory(object): + """ + This enum represents the different categories language models for + ``SingleByteCharsetProber`` put characters into. + + Anything less than CONTROL is considered a letter. + """ + UNDEFINED = 255 + LINE_BREAK = 254 + SYMBOL = 253 + DIGIT = 252 + CONTROL = 251 diff --git a/venv/Lib/site-packages/pip/_vendor/chardet/escprober.py b/venv/Lib/site-packages/pip/_vendor/chardet/escprober.py new file mode 100644 index 0000000..c70493f --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/chardet/escprober.py @@ -0,0 +1,101 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .charsetprober import CharSetProber +from .codingstatemachine import CodingStateMachine +from .enums import LanguageFilter, ProbingState, MachineState +from .escsm import (HZ_SM_MODEL, ISO2022CN_SM_MODEL, ISO2022JP_SM_MODEL, + ISO2022KR_SM_MODEL) + + +class EscCharSetProber(CharSetProber): + """ + This CharSetProber uses a "code scheme" approach for detecting encodings, + whereby easily recognizable escape or shift sequences are relied on to + identify these encodings. + """ + + def __init__(self, lang_filter=None): + super(EscCharSetProber, self).__init__(lang_filter=lang_filter) + self.coding_sm = [] + if self.lang_filter & LanguageFilter.CHINESE_SIMPLIFIED: + self.coding_sm.append(CodingStateMachine(HZ_SM_MODEL)) + self.coding_sm.append(CodingStateMachine(ISO2022CN_SM_MODEL)) + if self.lang_filter & LanguageFilter.JAPANESE: + self.coding_sm.append(CodingStateMachine(ISO2022JP_SM_MODEL)) + if self.lang_filter & LanguageFilter.KOREAN: + self.coding_sm.append(CodingStateMachine(ISO2022KR_SM_MODEL)) + self.active_sm_count = None + self._detected_charset = None + self._detected_language = None + self._state = None + self.reset() + + def reset(self): + super(EscCharSetProber, self).reset() + for coding_sm in self.coding_sm: + if not coding_sm: + continue + coding_sm.active = True + coding_sm.reset() + self.active_sm_count = len(self.coding_sm) + self._detected_charset = None + self._detected_language = None + + @property + def charset_name(self): + return self._detected_charset + + @property + def language(self): + return self._detected_language + + def get_confidence(self): + if self._detected_charset: + return 0.99 + else: + return 0.00 + + def feed(self, byte_str): + for c in byte_str: + for coding_sm in self.coding_sm: + if not coding_sm or not coding_sm.active: + continue + coding_state = coding_sm.next_state(c) + if coding_state == MachineState.ERROR: + coding_sm.active = False + self.active_sm_count -= 1 + if self.active_sm_count <= 0: + self._state = ProbingState.NOT_ME + return self.state + elif coding_state == MachineState.ITS_ME: + self._state = ProbingState.FOUND_IT + self._detected_charset = coding_sm.get_coding_state_machine() + self._detected_language = coding_sm.language + return self.state + + return self.state diff --git a/venv/Lib/site-packages/pip/_vendor/chardet/escsm.py b/venv/Lib/site-packages/pip/_vendor/chardet/escsm.py new file mode 100644 index 0000000..0069523 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/chardet/escsm.py @@ -0,0 +1,246 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .enums import MachineState + +HZ_CLS = ( +1,0,0,0,0,0,0,0, # 00 - 07 +0,0,0,0,0,0,0,0, # 08 - 0f +0,0,0,0,0,0,0,0, # 10 - 17 +0,0,0,1,0,0,0,0, # 18 - 1f +0,0,0,0,0,0,0,0, # 20 - 27 +0,0,0,0,0,0,0,0, # 28 - 2f +0,0,0,0,0,0,0,0, # 30 - 37 +0,0,0,0,0,0,0,0, # 38 - 3f +0,0,0,0,0,0,0,0, # 40 - 47 +0,0,0,0,0,0,0,0, # 48 - 4f +0,0,0,0,0,0,0,0, # 50 - 57 +0,0,0,0,0,0,0,0, # 58 - 5f +0,0,0,0,0,0,0,0, # 60 - 67 +0,0,0,0,0,0,0,0, # 68 - 6f +0,0,0,0,0,0,0,0, # 70 - 77 +0,0,0,4,0,5,2,0, # 78 - 7f +1,1,1,1,1,1,1,1, # 80 - 87 +1,1,1,1,1,1,1,1, # 88 - 8f +1,1,1,1,1,1,1,1, # 90 - 97 +1,1,1,1,1,1,1,1, # 98 - 9f +1,1,1,1,1,1,1,1, # a0 - a7 +1,1,1,1,1,1,1,1, # a8 - af +1,1,1,1,1,1,1,1, # b0 - b7 +1,1,1,1,1,1,1,1, # b8 - bf +1,1,1,1,1,1,1,1, # c0 - c7 +1,1,1,1,1,1,1,1, # c8 - cf +1,1,1,1,1,1,1,1, # d0 - d7 +1,1,1,1,1,1,1,1, # d8 - df +1,1,1,1,1,1,1,1, # e0 - e7 +1,1,1,1,1,1,1,1, # e8 - ef +1,1,1,1,1,1,1,1, # f0 - f7 +1,1,1,1,1,1,1,1, # f8 - ff +) + +HZ_ST = ( +MachineState.START,MachineState.ERROR, 3,MachineState.START,MachineState.START,MachineState.START,MachineState.ERROR,MachineState.ERROR,# 00-07 +MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,# 08-0f +MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.START, 4,MachineState.ERROR,# 10-17 + 5,MachineState.ERROR, 6,MachineState.ERROR, 5, 5, 4,MachineState.ERROR,# 18-1f + 4,MachineState.ERROR, 4, 4, 4,MachineState.ERROR, 4,MachineState.ERROR,# 20-27 + 4,MachineState.ITS_ME,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,# 28-2f +) + +HZ_CHAR_LEN_TABLE = (0, 0, 0, 0, 0, 0) + +HZ_SM_MODEL = {'class_table': HZ_CLS, + 'class_factor': 6, + 'state_table': HZ_ST, + 'char_len_table': HZ_CHAR_LEN_TABLE, + 'name': "HZ-GB-2312", + 'language': 'Chinese'} + +ISO2022CN_CLS = ( +2,0,0,0,0,0,0,0, # 00 - 07 +0,0,0,0,0,0,0,0, # 08 - 0f +0,0,0,0,0,0,0,0, # 10 - 17 +0,0,0,1,0,0,0,0, # 18 - 1f +0,0,0,0,0,0,0,0, # 20 - 27 +0,3,0,0,0,0,0,0, # 28 - 2f +0,0,0,0,0,0,0,0, # 30 - 37 +0,0,0,0,0,0,0,0, # 38 - 3f +0,0,0,4,0,0,0,0, # 40 - 47 +0,0,0,0,0,0,0,0, # 48 - 4f +0,0,0,0,0,0,0,0, # 50 - 57 +0,0,0,0,0,0,0,0, # 58 - 5f +0,0,0,0,0,0,0,0, # 60 - 67 +0,0,0,0,0,0,0,0, # 68 - 6f +0,0,0,0,0,0,0,0, # 70 - 77 +0,0,0,0,0,0,0,0, # 78 - 7f +2,2,2,2,2,2,2,2, # 80 - 87 +2,2,2,2,2,2,2,2, # 88 - 8f +2,2,2,2,2,2,2,2, # 90 - 97 +2,2,2,2,2,2,2,2, # 98 - 9f +2,2,2,2,2,2,2,2, # a0 - a7 +2,2,2,2,2,2,2,2, # a8 - af +2,2,2,2,2,2,2,2, # b0 - b7 +2,2,2,2,2,2,2,2, # b8 - bf +2,2,2,2,2,2,2,2, # c0 - c7 +2,2,2,2,2,2,2,2, # c8 - cf +2,2,2,2,2,2,2,2, # d0 - d7 +2,2,2,2,2,2,2,2, # d8 - df +2,2,2,2,2,2,2,2, # e0 - e7 +2,2,2,2,2,2,2,2, # e8 - ef +2,2,2,2,2,2,2,2, # f0 - f7 +2,2,2,2,2,2,2,2, # f8 - ff +) + +ISO2022CN_ST = ( +MachineState.START, 3,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,# 00-07 +MachineState.START,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,# 08-0f +MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,# 10-17 +MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR, 4,MachineState.ERROR,# 18-1f +MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,# 20-27 + 5, 6,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,# 28-2f +MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,# 30-37 +MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ERROR,MachineState.START,# 38-3f +) + +ISO2022CN_CHAR_LEN_TABLE = (0, 0, 0, 0, 0, 0, 0, 0, 0) + +ISO2022CN_SM_MODEL = {'class_table': ISO2022CN_CLS, + 'class_factor': 9, + 'state_table': ISO2022CN_ST, + 'char_len_table': ISO2022CN_CHAR_LEN_TABLE, + 'name': "ISO-2022-CN", + 'language': 'Chinese'} + +ISO2022JP_CLS = ( +2,0,0,0,0,0,0,0, # 00 - 07 +0,0,0,0,0,0,2,2, # 08 - 0f +0,0,0,0,0,0,0,0, # 10 - 17 +0,0,0,1,0,0,0,0, # 18 - 1f +0,0,0,0,7,0,0,0, # 20 - 27 +3,0,0,0,0,0,0,0, # 28 - 2f +0,0,0,0,0,0,0,0, # 30 - 37 +0,0,0,0,0,0,0,0, # 38 - 3f +6,0,4,0,8,0,0,0, # 40 - 47 +0,9,5,0,0,0,0,0, # 48 - 4f +0,0,0,0,0,0,0,0, # 50 - 57 +0,0,0,0,0,0,0,0, # 58 - 5f +0,0,0,0,0,0,0,0, # 60 - 67 +0,0,0,0,0,0,0,0, # 68 - 6f +0,0,0,0,0,0,0,0, # 70 - 77 +0,0,0,0,0,0,0,0, # 78 - 7f +2,2,2,2,2,2,2,2, # 80 - 87 +2,2,2,2,2,2,2,2, # 88 - 8f +2,2,2,2,2,2,2,2, # 90 - 97 +2,2,2,2,2,2,2,2, # 98 - 9f +2,2,2,2,2,2,2,2, # a0 - a7 +2,2,2,2,2,2,2,2, # a8 - af +2,2,2,2,2,2,2,2, # b0 - b7 +2,2,2,2,2,2,2,2, # b8 - bf +2,2,2,2,2,2,2,2, # c0 - c7 +2,2,2,2,2,2,2,2, # c8 - cf +2,2,2,2,2,2,2,2, # d0 - d7 +2,2,2,2,2,2,2,2, # d8 - df +2,2,2,2,2,2,2,2, # e0 - e7 +2,2,2,2,2,2,2,2, # e8 - ef +2,2,2,2,2,2,2,2, # f0 - f7 +2,2,2,2,2,2,2,2, # f8 - ff +) + +ISO2022JP_ST = ( +MachineState.START, 3,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,# 00-07 +MachineState.START,MachineState.START,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,# 08-0f +MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,# 10-17 +MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ERROR,MachineState.ERROR,# 18-1f +MachineState.ERROR, 5,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR, 4,MachineState.ERROR,MachineState.ERROR,# 20-27 +MachineState.ERROR,MachineState.ERROR,MachineState.ERROR, 6,MachineState.ITS_ME,MachineState.ERROR,MachineState.ITS_ME,MachineState.ERROR,# 28-2f +MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ITS_ME,# 30-37 +MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,# 38-3f +MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ERROR,MachineState.START,MachineState.START,# 40-47 +) + +ISO2022JP_CHAR_LEN_TABLE = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0) + +ISO2022JP_SM_MODEL = {'class_table': ISO2022JP_CLS, + 'class_factor': 10, + 'state_table': ISO2022JP_ST, + 'char_len_table': ISO2022JP_CHAR_LEN_TABLE, + 'name': "ISO-2022-JP", + 'language': 'Japanese'} + +ISO2022KR_CLS = ( +2,0,0,0,0,0,0,0, # 00 - 07 +0,0,0,0,0,0,0,0, # 08 - 0f +0,0,0,0,0,0,0,0, # 10 - 17 +0,0,0,1,0,0,0,0, # 18 - 1f +0,0,0,0,3,0,0,0, # 20 - 27 +0,4,0,0,0,0,0,0, # 28 - 2f +0,0,0,0,0,0,0,0, # 30 - 37 +0,0,0,0,0,0,0,0, # 38 - 3f +0,0,0,5,0,0,0,0, # 40 - 47 +0,0,0,0,0,0,0,0, # 48 - 4f +0,0,0,0,0,0,0,0, # 50 - 57 +0,0,0,0,0,0,0,0, # 58 - 5f +0,0,0,0,0,0,0,0, # 60 - 67 +0,0,0,0,0,0,0,0, # 68 - 6f +0,0,0,0,0,0,0,0, # 70 - 77 +0,0,0,0,0,0,0,0, # 78 - 7f +2,2,2,2,2,2,2,2, # 80 - 87 +2,2,2,2,2,2,2,2, # 88 - 8f +2,2,2,2,2,2,2,2, # 90 - 97 +2,2,2,2,2,2,2,2, # 98 - 9f +2,2,2,2,2,2,2,2, # a0 - a7 +2,2,2,2,2,2,2,2, # a8 - af +2,2,2,2,2,2,2,2, # b0 - b7 +2,2,2,2,2,2,2,2, # b8 - bf +2,2,2,2,2,2,2,2, # c0 - c7 +2,2,2,2,2,2,2,2, # c8 - cf +2,2,2,2,2,2,2,2, # d0 - d7 +2,2,2,2,2,2,2,2, # d8 - df +2,2,2,2,2,2,2,2, # e0 - e7 +2,2,2,2,2,2,2,2, # e8 - ef +2,2,2,2,2,2,2,2, # f0 - f7 +2,2,2,2,2,2,2,2, # f8 - ff +) + +ISO2022KR_ST = ( +MachineState.START, 3,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.ERROR,MachineState.ERROR,# 00-07 +MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,# 08-0f +MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR, 4,MachineState.ERROR,MachineState.ERROR,# 10-17 +MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR, 5,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,# 18-1f +MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.START,MachineState.START,MachineState.START,MachineState.START,# 20-27 +) + +ISO2022KR_CHAR_LEN_TABLE = (0, 0, 0, 0, 0, 0) + +ISO2022KR_SM_MODEL = {'class_table': ISO2022KR_CLS, + 'class_factor': 6, + 'state_table': ISO2022KR_ST, + 'char_len_table': ISO2022KR_CHAR_LEN_TABLE, + 'name': "ISO-2022-KR", + 'language': 'Korean'} + + diff --git a/venv/Lib/site-packages/pip/_vendor/chardet/eucjpprober.py b/venv/Lib/site-packages/pip/_vendor/chardet/eucjpprober.py new file mode 100644 index 0000000..20ce8f7 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/chardet/eucjpprober.py @@ -0,0 +1,92 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .enums import ProbingState, MachineState +from .mbcharsetprober import MultiByteCharSetProber +from .codingstatemachine import CodingStateMachine +from .chardistribution import EUCJPDistributionAnalysis +from .jpcntx import EUCJPContextAnalysis +from .mbcssm import EUCJP_SM_MODEL + + +class EUCJPProber(MultiByteCharSetProber): + def __init__(self): + super(EUCJPProber, self).__init__() + self.coding_sm = CodingStateMachine(EUCJP_SM_MODEL) + self.distribution_analyzer = EUCJPDistributionAnalysis() + self.context_analyzer = EUCJPContextAnalysis() + self.reset() + + def reset(self): + super(EUCJPProber, self).reset() + self.context_analyzer.reset() + + @property + def charset_name(self): + return "EUC-JP" + + @property + def language(self): + return "Japanese" + + def feed(self, byte_str): + for i in range(len(byte_str)): + # PY3K: byte_str is a byte array, so byte_str[i] is an int, not a byte + coding_state = self.coding_sm.next_state(byte_str[i]) + if coding_state == MachineState.ERROR: + self.logger.debug('%s %s prober hit error at byte %s', + self.charset_name, self.language, i) + self._state = ProbingState.NOT_ME + break + elif coding_state == MachineState.ITS_ME: + self._state = ProbingState.FOUND_IT + break + elif coding_state == MachineState.START: + char_len = self.coding_sm.get_current_charlen() + if i == 0: + self._last_char[1] = byte_str[0] + self.context_analyzer.feed(self._last_char, char_len) + self.distribution_analyzer.feed(self._last_char, char_len) + else: + self.context_analyzer.feed(byte_str[i - 1:i + 1], + char_len) + self.distribution_analyzer.feed(byte_str[i - 1:i + 1], + char_len) + + self._last_char[0] = byte_str[-1] + + if self.state == ProbingState.DETECTING: + if (self.context_analyzer.got_enough_data() and + (self.get_confidence() > self.SHORTCUT_THRESHOLD)): + self._state = ProbingState.FOUND_IT + + return self.state + + def get_confidence(self): + context_conf = self.context_analyzer.get_confidence() + distrib_conf = self.distribution_analyzer.get_confidence() + return max(context_conf, distrib_conf) diff --git a/venv/Lib/site-packages/pip/_vendor/chardet/euckrfreq.py b/venv/Lib/site-packages/pip/_vendor/chardet/euckrfreq.py new file mode 100644 index 0000000..b68078c --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/chardet/euckrfreq.py @@ -0,0 +1,195 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +# Sampling from about 20M text materials include literature and computer technology + +# 128 --> 0.79 +# 256 --> 0.92 +# 512 --> 0.986 +# 1024 --> 0.99944 +# 2048 --> 0.99999 +# +# Idea Distribution Ratio = 0.98653 / (1-0.98653) = 73.24 +# Random Distribution Ration = 512 / (2350-512) = 0.279. +# +# Typical Distribution Ratio + +EUCKR_TYPICAL_DISTRIBUTION_RATIO = 6.0 + +EUCKR_TABLE_SIZE = 2352 + +# Char to FreqOrder table , +EUCKR_CHAR_TO_FREQ_ORDER = ( + 13, 130, 120,1396, 481,1719,1720, 328, 609, 212,1721, 707, 400, 299,1722, 87, +1397,1723, 104, 536,1117,1203,1724,1267, 685,1268, 508,1725,1726,1727,1728,1398, +1399,1729,1730,1731, 141, 621, 326,1057, 368,1732, 267, 488, 20,1733,1269,1734, + 945,1400,1735, 47, 904,1270,1736,1737, 773, 248,1738, 409, 313, 786, 429,1739, + 116, 987, 813,1401, 683, 75,1204, 145,1740,1741,1742,1743, 16, 847, 667, 622, + 708,1744,1745,1746, 966, 787, 304, 129,1747, 60, 820, 123, 676,1748,1749,1750, +1751, 617,1752, 626,1753,1754,1755,1756, 653,1757,1758,1759,1760,1761,1762, 856, + 344,1763,1764,1765,1766, 89, 401, 418, 806, 905, 848,1767,1768,1769, 946,1205, + 709,1770,1118,1771, 241,1772,1773,1774,1271,1775, 569,1776, 999,1777,1778,1779, +1780, 337, 751,1058, 28, 628, 254,1781, 177, 906, 270, 349, 891,1079,1782, 19, +1783, 379,1784, 315,1785, 629, 754,1402, 559,1786, 636, 203,1206,1787, 710, 567, +1788, 935, 814,1789,1790,1207, 766, 528,1791,1792,1208,1793,1794,1795,1796,1797, +1403,1798,1799, 533,1059,1404,1405,1156,1406, 936, 884,1080,1800, 351,1801,1802, +1803,1804,1805, 801,1806,1807,1808,1119,1809,1157, 714, 474,1407,1810, 298, 899, + 885,1811,1120, 802,1158,1812, 892,1813,1814,1408, 659,1815,1816,1121,1817,1818, +1819,1820,1821,1822, 319,1823, 594, 545,1824, 815, 937,1209,1825,1826, 573,1409, +1022,1827,1210,1828,1829,1830,1831,1832,1833, 556, 722, 807,1122,1060,1834, 697, +1835, 900, 557, 715,1836,1410, 540,1411, 752,1159, 294, 597,1211, 976, 803, 770, +1412,1837,1838, 39, 794,1413, 358,1839, 371, 925,1840, 453, 661, 788, 531, 723, + 544,1023,1081, 869, 91,1841, 392, 430, 790, 602,1414, 677,1082, 457,1415,1416, +1842,1843, 475, 327,1024,1417, 795, 121,1844, 733, 403,1418,1845,1846,1847, 300, + 119, 711,1212, 627,1848,1272, 207,1849,1850, 796,1213, 382,1851, 519,1852,1083, + 893,1853,1854,1855, 367, 809, 487, 671,1856, 663,1857,1858, 956, 471, 306, 857, +1859,1860,1160,1084,1861,1862,1863,1864,1865,1061,1866,1867,1868,1869,1870,1871, + 282, 96, 574,1872, 502,1085,1873,1214,1874, 907,1875,1876, 827, 977,1419,1420, +1421, 268,1877,1422,1878,1879,1880, 308,1881, 2, 537,1882,1883,1215,1884,1885, + 127, 791,1886,1273,1423,1887, 34, 336, 404, 643,1888, 571, 654, 894, 840,1889, + 0, 886,1274, 122, 575, 260, 908, 938,1890,1275, 410, 316,1891,1892, 100,1893, +1894,1123, 48,1161,1124,1025,1895, 633, 901,1276,1896,1897, 115, 816,1898, 317, +1899, 694,1900, 909, 734,1424, 572, 866,1425, 691, 85, 524,1010, 543, 394, 841, +1901,1902,1903,1026,1904,1905,1906,1907,1908,1909, 30, 451, 651, 988, 310,1910, +1911,1426, 810,1216, 93,1912,1913,1277,1217,1914, 858, 759, 45, 58, 181, 610, + 269,1915,1916, 131,1062, 551, 443,1000, 821,1427, 957, 895,1086,1917,1918, 375, +1919, 359,1920, 687,1921, 822,1922, 293,1923,1924, 40, 662, 118, 692, 29, 939, + 887, 640, 482, 174,1925, 69,1162, 728,1428, 910,1926,1278,1218,1279, 386, 870, + 217, 854,1163, 823,1927,1928,1929,1930, 834,1931, 78,1932, 859,1933,1063,1934, +1935,1936,1937, 438,1164, 208, 595,1938,1939,1940,1941,1219,1125,1942, 280, 888, +1429,1430,1220,1431,1943,1944,1945,1946,1947,1280, 150, 510,1432,1948,1949,1950, +1951,1952,1953,1954,1011,1087,1955,1433,1043,1956, 881,1957, 614, 958,1064,1065, +1221,1958, 638,1001, 860, 967, 896,1434, 989, 492, 553,1281,1165,1959,1282,1002, +1283,1222,1960,1961,1962,1963, 36, 383, 228, 753, 247, 454,1964, 876, 678,1965, +1966,1284, 126, 464, 490, 835, 136, 672, 529, 940,1088,1435, 473,1967,1968, 467, + 50, 390, 227, 587, 279, 378, 598, 792, 968, 240, 151, 160, 849, 882,1126,1285, + 639,1044, 133, 140, 288, 360, 811, 563,1027, 561, 142, 523,1969,1970,1971, 7, + 103, 296, 439, 407, 506, 634, 990,1972,1973,1974,1975, 645,1976,1977,1978,1979, +1980,1981, 236,1982,1436,1983,1984,1089, 192, 828, 618, 518,1166, 333,1127,1985, + 818,1223,1986,1987,1988,1989,1990,1991,1992,1993, 342,1128,1286, 746, 842,1994, +1995, 560, 223,1287, 98, 8, 189, 650, 978,1288,1996,1437,1997, 17, 345, 250, + 423, 277, 234, 512, 226, 97, 289, 42, 167,1998, 201,1999,2000, 843, 836, 824, + 532, 338, 783,1090, 182, 576, 436,1438,1439, 527, 500,2001, 947, 889,2002,2003, +2004,2005, 262, 600, 314, 447,2006, 547,2007, 693, 738,1129,2008, 71,1440, 745, + 619, 688,2009, 829,2010,2011, 147,2012, 33, 948,2013,2014, 74, 224,2015, 61, + 191, 918, 399, 637,2016,1028,1130, 257, 902,2017,2018,2019,2020,2021,2022,2023, +2024,2025,2026, 837,2027,2028,2029,2030, 179, 874, 591, 52, 724, 246,2031,2032, +2033,2034,1167, 969,2035,1289, 630, 605, 911,1091,1168,2036,2037,2038,1441, 912, +2039, 623,2040,2041, 253,1169,1290,2042,1442, 146, 620, 611, 577, 433,2043,1224, + 719,1170, 959, 440, 437, 534, 84, 388, 480,1131, 159, 220, 198, 679,2044,1012, + 819,1066,1443, 113,1225, 194, 318,1003,1029,2045,2046,2047,2048,1067,2049,2050, +2051,2052,2053, 59, 913, 112,2054, 632,2055, 455, 144, 739,1291,2056, 273, 681, + 499,2057, 448,2058,2059, 760,2060,2061, 970, 384, 169, 245,1132,2062,2063, 414, +1444,2064,2065, 41, 235,2066, 157, 252, 877, 568, 919, 789, 580,2067, 725,2068, +2069,1292,2070,2071,1445,2072,1446,2073,2074, 55, 588, 66,1447, 271,1092,2075, +1226,2076, 960,1013, 372,2077,2078,2079,2080,2081,1293,2082,2083,2084,2085, 850, +2086,2087,2088,2089,2090, 186,2091,1068, 180,2092,2093,2094, 109,1227, 522, 606, +2095, 867,1448,1093, 991,1171, 926, 353,1133,2096, 581,2097,2098,2099,1294,1449, +1450,2100, 596,1172,1014,1228,2101,1451,1295,1173,1229,2102,2103,1296,1134,1452, + 949,1135,2104,2105,1094,1453,1454,1455,2106,1095,2107,2108,2109,2110,2111,2112, +2113,2114,2115,2116,2117, 804,2118,2119,1230,1231, 805,1456, 405,1136,2120,2121, +2122,2123,2124, 720, 701,1297, 992,1457, 927,1004,2125,2126,2127,2128,2129,2130, + 22, 417,2131, 303,2132, 385,2133, 971, 520, 513,2134,1174, 73,1096, 231, 274, + 962,1458, 673,2135,1459,2136, 152,1137,2137,2138,2139,2140,1005,1138,1460,1139, +2141,2142,2143,2144, 11, 374, 844,2145, 154,1232, 46,1461,2146, 838, 830, 721, +1233, 106,2147, 90, 428, 462, 578, 566,1175, 352,2148,2149, 538,1234, 124,1298, +2150,1462, 761, 565,2151, 686,2152, 649,2153, 72, 173,2154, 460, 415,2155,1463, +2156,1235, 305,2157,2158,2159,2160,2161,2162, 579,2163,2164,2165,2166,2167, 747, +2168,2169,2170,2171,1464, 669,2172,2173,2174,2175,2176,1465,2177, 23, 530, 285, +2178, 335, 729,2179, 397,2180,2181,2182,1030,2183,2184, 698,2185,2186, 325,2187, +2188, 369,2189, 799,1097,1015, 348,2190,1069, 680,2191, 851,1466,2192,2193, 10, +2194, 613, 424,2195, 979, 108, 449, 589, 27, 172, 81,1031, 80, 774, 281, 350, +1032, 525, 301, 582,1176,2196, 674,1045,2197,2198,1467, 730, 762,2199,2200,2201, +2202,1468,2203, 993,2204,2205, 266,1070, 963,1140,2206,2207,2208, 664,1098, 972, +2209,2210,2211,1177,1469,1470, 871,2212,2213,2214,2215,2216,1471,2217,2218,2219, +2220,2221,2222,2223,2224,2225,2226,2227,1472,1236,2228,2229,2230,2231,2232,2233, +2234,2235,1299,2236,2237, 200,2238, 477, 373,2239,2240, 731, 825, 777,2241,2242, +2243, 521, 486, 548,2244,2245,2246,1473,1300, 53, 549, 137, 875, 76, 158,2247, +1301,1474, 469, 396,1016, 278, 712,2248, 321, 442, 503, 767, 744, 941,1237,1178, +1475,2249, 82, 178,1141,1179, 973,2250,1302,2251, 297,2252,2253, 570,2254,2255, +2256, 18, 450, 206,2257, 290, 292,1142,2258, 511, 162, 99, 346, 164, 735,2259, +1476,1477, 4, 554, 343, 798,1099,2260,1100,2261, 43, 171,1303, 139, 215,2262, +2263, 717, 775,2264,1033, 322, 216,2265, 831,2266, 149,2267,1304,2268,2269, 702, +1238, 135, 845, 347, 309,2270, 484,2271, 878, 655, 238,1006,1478,2272, 67,2273, + 295,2274,2275, 461,2276, 478, 942, 412,2277,1034,2278,2279,2280, 265,2281, 541, +2282,2283,2284,2285,2286, 70, 852,1071,2287,2288,2289,2290, 21, 56, 509, 117, + 432,2291,2292, 331, 980, 552,1101, 148, 284, 105, 393,1180,1239, 755,2293, 187, +2294,1046,1479,2295, 340,2296, 63,1047, 230,2297,2298,1305, 763,1306, 101, 800, + 808, 494,2299,2300,2301, 903,2302, 37,1072, 14, 5,2303, 79, 675,2304, 312, +2305,2306,2307,2308,2309,1480, 6,1307,2310,2311,2312, 1, 470, 35, 24, 229, +2313, 695, 210, 86, 778, 15, 784, 592, 779, 32, 77, 855, 964,2314, 259,2315, + 501, 380,2316,2317, 83, 981, 153, 689,1308,1481,1482,1483,2318,2319, 716,1484, +2320,2321,2322,2323,2324,2325,1485,2326,2327, 128, 57, 68, 261,1048, 211, 170, +1240, 31,2328, 51, 435, 742,2329,2330,2331, 635,2332, 264, 456,2333,2334,2335, + 425,2336,1486, 143, 507, 263, 943,2337, 363, 920,1487, 256,1488,1102, 243, 601, +1489,2338,2339,2340,2341,2342,2343,2344, 861,2345,2346,2347,2348,2349,2350, 395, +2351,1490,1491, 62, 535, 166, 225,2352,2353, 668, 419,1241, 138, 604, 928,2354, +1181,2355,1492,1493,2356,2357,2358,1143,2359, 696,2360, 387, 307,1309, 682, 476, +2361,2362, 332, 12, 222, 156,2363, 232,2364, 641, 276, 656, 517,1494,1495,1035, + 416, 736,1496,2365,1017, 586,2366,2367,2368,1497,2369, 242,2370,2371,2372,1498, +2373, 965, 713,2374,2375,2376,2377, 740, 982,1499, 944,1500,1007,2378,2379,1310, +1501,2380,2381,2382, 785, 329,2383,2384,1502,2385,2386,2387, 932,2388,1503,2389, +2390,2391,2392,1242,2393,2394,2395,2396,2397, 994, 950,2398,2399,2400,2401,1504, +1311,2402,2403,2404,2405,1049, 749,2406,2407, 853, 718,1144,1312,2408,1182,1505, +2409,2410, 255, 516, 479, 564, 550, 214,1506,1507,1313, 413, 239, 444, 339,1145, +1036,1508,1509,1314,1037,1510,1315,2411,1511,2412,2413,2414, 176, 703, 497, 624, + 593, 921, 302,2415, 341, 165,1103,1512,2416,1513,2417,2418,2419, 376,2420, 700, +2421,2422,2423, 258, 768,1316,2424,1183,2425, 995, 608,2426,2427,2428,2429, 221, +2430,2431,2432,2433,2434,2435,2436,2437, 195, 323, 726, 188, 897, 983,1317, 377, + 644,1050, 879,2438, 452,2439,2440,2441,2442,2443,2444, 914,2445,2446,2447,2448, + 915, 489,2449,1514,1184,2450,2451, 515, 64, 427, 495,2452, 583,2453, 483, 485, +1038, 562, 213,1515, 748, 666,2454,2455,2456,2457, 334,2458, 780, 996,1008, 705, +1243,2459,2460,2461,2462,2463, 114,2464, 493,1146, 366, 163,1516, 961,1104,2465, + 291,2466,1318,1105,2467,1517, 365,2468, 355, 951,1244,2469,1319,2470, 631,2471, +2472, 218,1320, 364, 320, 756,1518,1519,1321,1520,1322,2473,2474,2475,2476, 997, +2477,2478,2479,2480, 665,1185,2481, 916,1521,2482,2483,2484, 584, 684,2485,2486, + 797,2487,1051,1186,2488,2489,2490,1522,2491,2492, 370,2493,1039,1187, 65,2494, + 434, 205, 463,1188,2495, 125, 812, 391, 402, 826, 699, 286, 398, 155, 781, 771, + 585,2496, 590, 505,1073,2497, 599, 244, 219, 917,1018, 952, 646,1523,2498,1323, +2499,2500, 49, 984, 354, 741,2501, 625,2502,1324,2503,1019, 190, 357, 757, 491, + 95, 782, 868,2504,2505,2506,2507,2508,2509, 134,1524,1074, 422,1525, 898,2510, + 161,2511,2512,2513,2514, 769,2515,1526,2516,2517, 411,1325,2518, 472,1527,2519, +2520,2521,2522,2523,2524, 985,2525,2526,2527,2528,2529,2530, 764,2531,1245,2532, +2533, 25, 204, 311,2534, 496,2535,1052,2536,2537,2538,2539,2540,2541,2542, 199, + 704, 504, 468, 758, 657,1528, 196, 44, 839,1246, 272, 750,2543, 765, 862,2544, +2545,1326,2546, 132, 615, 933,2547, 732,2548,2549,2550,1189,1529,2551, 283,1247, +1053, 607, 929,2552,2553,2554, 930, 183, 872, 616,1040,1147,2555,1148,1020, 441, + 249,1075,2556,2557,2558, 466, 743,2559,2560,2561, 92, 514, 426, 420, 526,2562, +2563,2564,2565,2566,2567,2568, 185,2569,2570,2571,2572, 776,1530, 658,2573, 362, +2574, 361, 922,1076, 793,2575,2576,2577,2578,2579,2580,1531, 251,2581,2582,2583, +2584,1532, 54, 612, 237,1327,2585,2586, 275, 408, 647, 111,2587,1533,1106, 465, + 3, 458, 9, 38,2588, 107, 110, 890, 209, 26, 737, 498,2589,1534,2590, 431, + 202, 88,1535, 356, 287,1107, 660,1149,2591, 381,1536, 986,1150, 445,1248,1151, + 974,2592,2593, 846,2594, 446, 953, 184,1249,1250, 727,2595, 923, 193, 883,2596, +2597,2598, 102, 324, 539, 817,2599, 421,1041,2600, 832,2601, 94, 175, 197, 406, +2602, 459,2603,2604,2605,2606,2607, 330, 555,2608,2609,2610, 706,1108, 389,2611, +2612,2613,2614, 233,2615, 833, 558, 931, 954,1251,2616,2617,1537, 546,2618,2619, +1009,2620,2621,2622,1538, 690,1328,2623, 955,2624,1539,2625,2626, 772,2627,2628, +2629,2630,2631, 924, 648, 863, 603,2632,2633, 934,1540, 864, 865,2634, 642,1042, + 670,1190,2635,2636,2637,2638, 168,2639, 652, 873, 542,1054,1541,2640,2641,2642, # 512, 256 +) + diff --git a/venv/Lib/site-packages/pip/_vendor/chardet/euckrprober.py b/venv/Lib/site-packages/pip/_vendor/chardet/euckrprober.py new file mode 100644 index 0000000..345a060 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/chardet/euckrprober.py @@ -0,0 +1,47 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .mbcharsetprober import MultiByteCharSetProber +from .codingstatemachine import CodingStateMachine +from .chardistribution import EUCKRDistributionAnalysis +from .mbcssm import EUCKR_SM_MODEL + + +class EUCKRProber(MultiByteCharSetProber): + def __init__(self): + super(EUCKRProber, self).__init__() + self.coding_sm = CodingStateMachine(EUCKR_SM_MODEL) + self.distribution_analyzer = EUCKRDistributionAnalysis() + self.reset() + + @property + def charset_name(self): + return "EUC-KR" + + @property + def language(self): + return "Korean" diff --git a/venv/Lib/site-packages/pip/_vendor/chardet/euctwfreq.py b/venv/Lib/site-packages/pip/_vendor/chardet/euctwfreq.py new file mode 100644 index 0000000..ed7a995 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/chardet/euctwfreq.py @@ -0,0 +1,387 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +# EUCTW frequency table +# Converted from big5 work +# by Taiwan's Mandarin Promotion Council +# + +# 128 --> 0.42261 +# 256 --> 0.57851 +# 512 --> 0.74851 +# 1024 --> 0.89384 +# 2048 --> 0.97583 +# +# Idea Distribution Ratio = 0.74851/(1-0.74851) =2.98 +# Random Distribution Ration = 512/(5401-512)=0.105 +# +# Typical Distribution Ratio about 25% of Ideal one, still much higher than RDR + +EUCTW_TYPICAL_DISTRIBUTION_RATIO = 0.75 + +# Char to FreqOrder table , +EUCTW_TABLE_SIZE = 5376 + +EUCTW_CHAR_TO_FREQ_ORDER = ( + 1,1800,1506, 255,1431, 198, 9, 82, 6,7310, 177, 202,3615,1256,2808, 110, # 2742 +3735, 33,3241, 261, 76, 44,2113, 16,2931,2184,1176, 659,3868, 26,3404,2643, # 2758 +1198,3869,3313,4060, 410,2211, 302, 590, 361,1963, 8, 204, 58,4296,7311,1931, # 2774 + 63,7312,7313, 317,1614, 75, 222, 159,4061,2412,1480,7314,3500,3068, 224,2809, # 2790 +3616, 3, 10,3870,1471, 29,2774,1135,2852,1939, 873, 130,3242,1123, 312,7315, # 2806 +4297,2051, 507, 252, 682,7316, 142,1914, 124, 206,2932, 34,3501,3173, 64, 604, # 2822 +7317,2494,1976,1977, 155,1990, 645, 641,1606,7318,3405, 337, 72, 406,7319, 80, # 2838 + 630, 238,3174,1509, 263, 939,1092,2644, 756,1440,1094,3406, 449, 69,2969, 591, # 2854 + 179,2095, 471, 115,2034,1843, 60, 50,2970, 134, 806,1868, 734,2035,3407, 180, # 2870 + 995,1607, 156, 537,2893, 688,7320, 319,1305, 779,2144, 514,2374, 298,4298, 359, # 2886 +2495, 90,2707,1338, 663, 11, 906,1099,2545, 20,2436, 182, 532,1716,7321, 732, # 2902 +1376,4062,1311,1420,3175, 25,2312,1056, 113, 399, 382,1949, 242,3408,2467, 529, # 2918 +3243, 475,1447,3617,7322, 117, 21, 656, 810,1297,2295,2329,3502,7323, 126,4063, # 2934 + 706, 456, 150, 613,4299, 71,1118,2036,4064, 145,3069, 85, 835, 486,2114,1246, # 2950 +1426, 428, 727,1285,1015, 800, 106, 623, 303,1281,7324,2127,2354, 347,3736, 221, # 2966 +3503,3110,7325,1955,1153,4065, 83, 296,1199,3070, 192, 624, 93,7326, 822,1897, # 2982 +2810,3111, 795,2064, 991,1554,1542,1592, 27, 43,2853, 859, 139,1456, 860,4300, # 2998 + 437, 712,3871, 164,2392,3112, 695, 211,3017,2096, 195,3872,1608,3504,3505,3618, # 3014 +3873, 234, 811,2971,2097,3874,2229,1441,3506,1615,2375, 668,2076,1638, 305, 228, # 3030 +1664,4301, 467, 415,7327, 262,2098,1593, 239, 108, 300, 200,1033, 512,1247,2077, # 3046 +7328,7329,2173,3176,3619,2673, 593, 845,1062,3244, 88,1723,2037,3875,1950, 212, # 3062 + 266, 152, 149, 468,1898,4066,4302, 77, 187,7330,3018, 37, 5,2972,7331,3876, # 3078 +7332,7333, 39,2517,4303,2894,3177,2078, 55, 148, 74,4304, 545, 483,1474,1029, # 3094 +1665, 217,1869,1531,3113,1104,2645,4067, 24, 172,3507, 900,3877,3508,3509,4305, # 3110 + 32,1408,2811,1312, 329, 487,2355,2247,2708, 784,2674, 4,3019,3314,1427,1788, # 3126 + 188, 109, 499,7334,3620,1717,1789, 888,1217,3020,4306,7335,3510,7336,3315,1520, # 3142 +3621,3878, 196,1034, 775,7337,7338, 929,1815, 249, 439, 38,7339,1063,7340, 794, # 3158 +3879,1435,2296, 46, 178,3245,2065,7341,2376,7342, 214,1709,4307, 804, 35, 707, # 3174 + 324,3622,1601,2546, 140, 459,4068,7343,7344,1365, 839, 272, 978,2257,2572,3409, # 3190 +2128,1363,3623,1423, 697, 100,3071, 48, 70,1231, 495,3114,2193,7345,1294,7346, # 3206 +2079, 462, 586,1042,3246, 853, 256, 988, 185,2377,3410,1698, 434,1084,7347,3411, # 3222 + 314,2615,2775,4308,2330,2331, 569,2280, 637,1816,2518, 757,1162,1878,1616,3412, # 3238 + 287,1577,2115, 768,4309,1671,2854,3511,2519,1321,3737, 909,2413,7348,4069, 933, # 3254 +3738,7349,2052,2356,1222,4310, 765,2414,1322, 786,4311,7350,1919,1462,1677,2895, # 3270 +1699,7351,4312,1424,2437,3115,3624,2590,3316,1774,1940,3413,3880,4070, 309,1369, # 3286 +1130,2812, 364,2230,1653,1299,3881,3512,3882,3883,2646, 525,1085,3021, 902,2000, # 3302 +1475, 964,4313, 421,1844,1415,1057,2281, 940,1364,3116, 376,4314,4315,1381, 7, # 3318 +2520, 983,2378, 336,1710,2675,1845, 321,3414, 559,1131,3022,2742,1808,1132,1313, # 3334 + 265,1481,1857,7352, 352,1203,2813,3247, 167,1089, 420,2814, 776, 792,1724,3513, # 3350 +4071,2438,3248,7353,4072,7354, 446, 229, 333,2743, 901,3739,1200,1557,4316,2647, # 3366 +1920, 395,2744,2676,3740,4073,1835, 125, 916,3178,2616,4317,7355,7356,3741,7357, # 3382 +7358,7359,4318,3117,3625,1133,2547,1757,3415,1510,2313,1409,3514,7360,2145, 438, # 3398 +2591,2896,2379,3317,1068, 958,3023, 461, 311,2855,2677,4074,1915,3179,4075,1978, # 3414 + 383, 750,2745,2617,4076, 274, 539, 385,1278,1442,7361,1154,1964, 384, 561, 210, # 3430 + 98,1295,2548,3515,7362,1711,2415,1482,3416,3884,2897,1257, 129,7363,3742, 642, # 3446 + 523,2776,2777,2648,7364, 141,2231,1333, 68, 176, 441, 876, 907,4077, 603,2592, # 3462 + 710, 171,3417, 404, 549, 18,3118,2393,1410,3626,1666,7365,3516,4319,2898,4320, # 3478 +7366,2973, 368,7367, 146, 366, 99, 871,3627,1543, 748, 807,1586,1185, 22,2258, # 3494 + 379,3743,3180,7368,3181, 505,1941,2618,1991,1382,2314,7369, 380,2357, 218, 702, # 3510 +1817,1248,3418,3024,3517,3318,3249,7370,2974,3628, 930,3250,3744,7371, 59,7372, # 3526 + 585, 601,4078, 497,3419,1112,1314,4321,1801,7373,1223,1472,2174,7374, 749,1836, # 3542 + 690,1899,3745,1772,3885,1476, 429,1043,1790,2232,2116, 917,4079, 447,1086,1629, # 3558 +7375, 556,7376,7377,2020,1654, 844,1090, 105, 550, 966,1758,2815,1008,1782, 686, # 3574 +1095,7378,2282, 793,1602,7379,3518,2593,4322,4080,2933,2297,4323,3746, 980,2496, # 3590 + 544, 353, 527,4324, 908,2678,2899,7380, 381,2619,1942,1348,7381,1341,1252, 560, # 3606 +3072,7382,3420,2856,7383,2053, 973, 886,2080, 143,4325,7384,7385, 157,3886, 496, # 3622 +4081, 57, 840, 540,2038,4326,4327,3421,2117,1445, 970,2259,1748,1965,2081,4082, # 3638 +3119,1234,1775,3251,2816,3629, 773,1206,2129,1066,2039,1326,3887,1738,1725,4083, # 3654 + 279,3120, 51,1544,2594, 423,1578,2130,2066, 173,4328,1879,7386,7387,1583, 264, # 3670 + 610,3630,4329,2439, 280, 154,7388,7389,7390,1739, 338,1282,3073, 693,2857,1411, # 3686 +1074,3747,2440,7391,4330,7392,7393,1240, 952,2394,7394,2900,1538,2679, 685,1483, # 3702 +4084,2468,1436, 953,4085,2054,4331, 671,2395, 79,4086,2441,3252, 608, 567,2680, # 3718 +3422,4087,4088,1691, 393,1261,1791,2396,7395,4332,7396,7397,7398,7399,1383,1672, # 3734 +3748,3182,1464, 522,1119, 661,1150, 216, 675,4333,3888,1432,3519, 609,4334,2681, # 3750 +2397,7400,7401,7402,4089,3025, 0,7403,2469, 315, 231,2442, 301,3319,4335,2380, # 3766 +7404, 233,4090,3631,1818,4336,4337,7405, 96,1776,1315,2082,7406, 257,7407,1809, # 3782 +3632,2709,1139,1819,4091,2021,1124,2163,2778,1777,2649,7408,3074, 363,1655,3183, # 3798 +7409,2975,7410,7411,7412,3889,1567,3890, 718, 103,3184, 849,1443, 341,3320,2934, # 3814 +1484,7413,1712, 127, 67, 339,4092,2398, 679,1412, 821,7414,7415, 834, 738, 351, # 3830 +2976,2146, 846, 235,1497,1880, 418,1992,3749,2710, 186,1100,2147,2746,3520,1545, # 3846 +1355,2935,2858,1377, 583,3891,4093,2573,2977,7416,1298,3633,1078,2549,3634,2358, # 3862 + 78,3750,3751, 267,1289,2099,2001,1594,4094, 348, 369,1274,2194,2175,1837,4338, # 3878 +1820,2817,3635,2747,2283,2002,4339,2936,2748, 144,3321, 882,4340,3892,2749,3423, # 3894 +4341,2901,7417,4095,1726, 320,7418,3893,3026, 788,2978,7419,2818,1773,1327,2859, # 3910 +3894,2819,7420,1306,4342,2003,1700,3752,3521,2359,2650, 787,2022, 506, 824,3636, # 3926 + 534, 323,4343,1044,3322,2023,1900, 946,3424,7421,1778,1500,1678,7422,1881,4344, # 3942 + 165, 243,4345,3637,2521, 123, 683,4096, 764,4346, 36,3895,1792, 589,2902, 816, # 3958 + 626,1667,3027,2233,1639,1555,1622,3753,3896,7423,3897,2860,1370,1228,1932, 891, # 3974 +2083,2903, 304,4097,7424, 292,2979,2711,3522, 691,2100,4098,1115,4347, 118, 662, # 3990 +7425, 611,1156, 854,2381,1316,2861, 2, 386, 515,2904,7426,7427,3253, 868,2234, # 4006 +1486, 855,2651, 785,2212,3028,7428,1040,3185,3523,7429,3121, 448,7430,1525,7431, # 4022 +2164,4348,7432,3754,7433,4099,2820,3524,3122, 503, 818,3898,3123,1568, 814, 676, # 4038 +1444, 306,1749,7434,3755,1416,1030, 197,1428, 805,2821,1501,4349,7435,7436,7437, # 4054 +1993,7438,4350,7439,7440,2195, 13,2779,3638,2980,3124,1229,1916,7441,3756,2131, # 4070 +7442,4100,4351,2399,3525,7443,2213,1511,1727,1120,7444,7445, 646,3757,2443, 307, # 4086 +7446,7447,1595,3186,7448,7449,7450,3639,1113,1356,3899,1465,2522,2523,7451, 519, # 4102 +7452, 128,2132, 92,2284,1979,7453,3900,1512, 342,3125,2196,7454,2780,2214,1980, # 4118 +3323,7455, 290,1656,1317, 789, 827,2360,7456,3758,4352, 562, 581,3901,7457, 401, # 4134 +4353,2248, 94,4354,1399,2781,7458,1463,2024,4355,3187,1943,7459, 828,1105,4101, # 4150 +1262,1394,7460,4102, 605,4356,7461,1783,2862,7462,2822, 819,2101, 578,2197,2937, # 4166 +7463,1502, 436,3254,4103,3255,2823,3902,2905,3425,3426,7464,2712,2315,7465,7466, # 4182 +2332,2067, 23,4357, 193, 826,3759,2102, 699,1630,4104,3075, 390,1793,1064,3526, # 4198 +7467,1579,3076,3077,1400,7468,4105,1838,1640,2863,7469,4358,4359, 137,4106, 598, # 4214 +3078,1966, 780, 104, 974,2938,7470, 278, 899, 253, 402, 572, 504, 493,1339,7471, # 4230 +3903,1275,4360,2574,2550,7472,3640,3029,3079,2249, 565,1334,2713, 863, 41,7473, # 4246 +7474,4361,7475,1657,2333, 19, 463,2750,4107, 606,7476,2981,3256,1087,2084,1323, # 4262 +2652,2982,7477,1631,1623,1750,4108,2682,7478,2864, 791,2714,2653,2334, 232,2416, # 4278 +7479,2983,1498,7480,2654,2620, 755,1366,3641,3257,3126,2025,1609, 119,1917,3427, # 4294 + 862,1026,4109,7481,3904,3760,4362,3905,4363,2260,1951,2470,7482,1125, 817,4110, # 4310 +4111,3906,1513,1766,2040,1487,4112,3030,3258,2824,3761,3127,7483,7484,1507,7485, # 4326 +2683, 733, 40,1632,1106,2865, 345,4113, 841,2524, 230,4364,2984,1846,3259,3428, # 4342 +7486,1263, 986,3429,7487, 735, 879, 254,1137, 857, 622,1300,1180,1388,1562,3907, # 4358 +3908,2939, 967,2751,2655,1349, 592,2133,1692,3324,2985,1994,4114,1679,3909,1901, # 4374 +2185,7488, 739,3642,2715,1296,1290,7489,4115,2198,2199,1921,1563,2595,2551,1870, # 4390 +2752,2986,7490, 435,7491, 343,1108, 596, 17,1751,4365,2235,3430,3643,7492,4366, # 4406 + 294,3527,2940,1693, 477, 979, 281,2041,3528, 643,2042,3644,2621,2782,2261,1031, # 4422 +2335,2134,2298,3529,4367, 367,1249,2552,7493,3530,7494,4368,1283,3325,2004, 240, # 4438 +1762,3326,4369,4370, 836,1069,3128, 474,7495,2148,2525, 268,3531,7496,3188,1521, # 4454 +1284,7497,1658,1546,4116,7498,3532,3533,7499,4117,3327,2684,1685,4118, 961,1673, # 4470 +2622, 190,2005,2200,3762,4371,4372,7500, 570,2497,3645,1490,7501,4373,2623,3260, # 4486 +1956,4374, 584,1514, 396,1045,1944,7502,4375,1967,2444,7503,7504,4376,3910, 619, # 4502 +7505,3129,3261, 215,2006,2783,2553,3189,4377,3190,4378, 763,4119,3763,4379,7506, # 4518 +7507,1957,1767,2941,3328,3646,1174, 452,1477,4380,3329,3130,7508,2825,1253,2382, # 4534 +2186,1091,2285,4120, 492,7509, 638,1169,1824,2135,1752,3911, 648, 926,1021,1324, # 4550 +4381, 520,4382, 997, 847,1007, 892,4383,3764,2262,1871,3647,7510,2400,1784,4384, # 4566 +1952,2942,3080,3191,1728,4121,2043,3648,4385,2007,1701,3131,1551, 30,2263,4122, # 4582 +7511,2026,4386,3534,7512, 501,7513,4123, 594,3431,2165,1821,3535,3432,3536,3192, # 4598 + 829,2826,4124,7514,1680,3132,1225,4125,7515,3262,4387,4126,3133,2336,7516,4388, # 4614 +4127,7517,3912,3913,7518,1847,2383,2596,3330,7519,4389, 374,3914, 652,4128,4129, # 4630 + 375,1140, 798,7520,7521,7522,2361,4390,2264, 546,1659, 138,3031,2445,4391,7523, # 4646 +2250, 612,1848, 910, 796,3765,1740,1371, 825,3766,3767,7524,2906,2554,7525, 692, # 4662 + 444,3032,2624, 801,4392,4130,7526,1491, 244,1053,3033,4131,4132, 340,7527,3915, # 4678 +1041,2987, 293,1168, 87,1357,7528,1539, 959,7529,2236, 721, 694,4133,3768, 219, # 4694 +1478, 644,1417,3331,2656,1413,1401,1335,1389,3916,7530,7531,2988,2362,3134,1825, # 4710 + 730,1515, 184,2827, 66,4393,7532,1660,2943, 246,3332, 378,1457, 226,3433, 975, # 4726 +3917,2944,1264,3537, 674, 696,7533, 163,7534,1141,2417,2166, 713,3538,3333,4394, # 4742 +3918,7535,7536,1186, 15,7537,1079,1070,7538,1522,3193,3539, 276,1050,2716, 758, # 4758 +1126, 653,2945,3263,7539,2337, 889,3540,3919,3081,2989, 903,1250,4395,3920,3434, # 4774 +3541,1342,1681,1718, 766,3264, 286, 89,2946,3649,7540,1713,7541,2597,3334,2990, # 4790 +7542,2947,2215,3194,2866,7543,4396,2498,2526, 181, 387,1075,3921, 731,2187,3335, # 4806 +7544,3265, 310, 313,3435,2299, 770,4134, 54,3034, 189,4397,3082,3769,3922,7545, # 4822 +1230,1617,1849, 355,3542,4135,4398,3336, 111,4136,3650,1350,3135,3436,3035,4137, # 4838 +2149,3266,3543,7546,2784,3923,3924,2991, 722,2008,7547,1071, 247,1207,2338,2471, # 4854 +1378,4399,2009, 864,1437,1214,4400, 373,3770,1142,2216, 667,4401, 442,2753,2555, # 4870 +3771,3925,1968,4138,3267,1839, 837, 170,1107, 934,1336,1882,7548,7549,2118,4139, # 4886 +2828, 743,1569,7550,4402,4140, 582,2384,1418,3437,7551,1802,7552, 357,1395,1729, # 4902 +3651,3268,2418,1564,2237,7553,3083,3772,1633,4403,1114,2085,4141,1532,7554, 482, # 4918 +2446,4404,7555,7556,1492, 833,1466,7557,2717,3544,1641,2829,7558,1526,1272,3652, # 4934 +4142,1686,1794, 416,2556,1902,1953,1803,7559,3773,2785,3774,1159,2316,7560,2867, # 4950 +4405,1610,1584,3036,2419,2754, 443,3269,1163,3136,7561,7562,3926,7563,4143,2499, # 4966 +3037,4406,3927,3137,2103,1647,3545,2010,1872,4144,7564,4145, 431,3438,7565, 250, # 4982 + 97, 81,4146,7566,1648,1850,1558, 160, 848,7567, 866, 740,1694,7568,2201,2830, # 4998 +3195,4147,4407,3653,1687, 950,2472, 426, 469,3196,3654,3655,3928,7569,7570,1188, # 5014 + 424,1995, 861,3546,4148,3775,2202,2685, 168,1235,3547,4149,7571,2086,1674,4408, # 5030 +3337,3270, 220,2557,1009,7572,3776, 670,2992, 332,1208, 717,7573,7574,3548,2447, # 5046 +3929,3338,7575, 513,7576,1209,2868,3339,3138,4409,1080,7577,7578,7579,7580,2527, # 5062 +3656,3549, 815,1587,3930,3931,7581,3550,3439,3777,1254,4410,1328,3038,1390,3932, # 5078 +1741,3933,3778,3934,7582, 236,3779,2448,3271,7583,7584,3657,3780,1273,3781,4411, # 5094 +7585, 308,7586,4412, 245,4413,1851,2473,1307,2575, 430, 715,2136,2449,7587, 270, # 5110 + 199,2869,3935,7588,3551,2718,1753, 761,1754, 725,1661,1840,4414,3440,3658,7589, # 5126 +7590, 587, 14,3272, 227,2598, 326, 480,2265, 943,2755,3552, 291, 650,1883,7591, # 5142 +1702,1226, 102,1547, 62,3441, 904,4415,3442,1164,4150,7592,7593,1224,1548,2756, # 5158 + 391, 498,1493,7594,1386,1419,7595,2055,1177,4416, 813, 880,1081,2363, 566,1145, # 5174 +4417,2286,1001,1035,2558,2599,2238, 394,1286,7596,7597,2068,7598, 86,1494,1730, # 5190 +3936, 491,1588, 745, 897,2948, 843,3340,3937,2757,2870,3273,1768, 998,2217,2069, # 5206 + 397,1826,1195,1969,3659,2993,3341, 284,7599,3782,2500,2137,2119,1903,7600,3938, # 5222 +2150,3939,4151,1036,3443,1904, 114,2559,4152, 209,1527,7601,7602,2949,2831,2625, # 5238 +2385,2719,3139, 812,2560,7603,3274,7604,1559, 737,1884,3660,1210, 885, 28,2686, # 5254 +3553,3783,7605,4153,1004,1779,4418,7606, 346,1981,2218,2687,4419,3784,1742, 797, # 5270 +1642,3940,1933,1072,1384,2151, 896,3941,3275,3661,3197,2871,3554,7607,2561,1958, # 5286 +4420,2450,1785,7608,7609,7610,3942,4154,1005,1308,3662,4155,2720,4421,4422,1528, # 5302 +2600, 161,1178,4156,1982, 987,4423,1101,4157, 631,3943,1157,3198,2420,1343,1241, # 5318 +1016,2239,2562, 372, 877,2339,2501,1160, 555,1934, 911,3944,7611, 466,1170, 169, # 5334 +1051,2907,2688,3663,2474,2994,1182,2011,2563,1251,2626,7612, 992,2340,3444,1540, # 5350 +2721,1201,2070,2401,1996,2475,7613,4424, 528,1922,2188,1503,1873,1570,2364,3342, # 5366 +3276,7614, 557,1073,7615,1827,3445,2087,2266,3140,3039,3084, 767,3085,2786,4425, # 5382 +1006,4158,4426,2341,1267,2176,3664,3199, 778,3945,3200,2722,1597,2657,7616,4427, # 5398 +7617,3446,7618,7619,7620,3277,2689,1433,3278, 131, 95,1504,3946, 723,4159,3141, # 5414 +1841,3555,2758,2189,3947,2027,2104,3665,7621,2995,3948,1218,7622,3343,3201,3949, # 5430 +4160,2576, 248,1634,3785, 912,7623,2832,3666,3040,3786, 654, 53,7624,2996,7625, # 5446 +1688,4428, 777,3447,1032,3950,1425,7626, 191, 820,2120,2833, 971,4429, 931,3202, # 5462 + 135, 664, 783,3787,1997, 772,2908,1935,3951,3788,4430,2909,3203, 282,2723, 640, # 5478 +1372,3448,1127, 922, 325,3344,7627,7628, 711,2044,7629,7630,3952,2219,2787,1936, # 5494 +3953,3345,2220,2251,3789,2300,7631,4431,3790,1258,3279,3954,3204,2138,2950,3955, # 5510 +3956,7632,2221, 258,3205,4432, 101,1227,7633,3280,1755,7634,1391,3281,7635,2910, # 5526 +2056, 893,7636,7637,7638,1402,4161,2342,7639,7640,3206,3556,7641,7642, 878,1325, # 5542 +1780,2788,4433, 259,1385,2577, 744,1183,2267,4434,7643,3957,2502,7644, 684,1024, # 5558 +4162,7645, 472,3557,3449,1165,3282,3958,3959, 322,2152, 881, 455,1695,1152,1340, # 5574 + 660, 554,2153,4435,1058,4436,4163, 830,1065,3346,3960,4437,1923,7646,1703,1918, # 5590 +7647, 932,2268, 122,7648,4438, 947, 677,7649,3791,2627, 297,1905,1924,2269,4439, # 5606 +2317,3283,7650,7651,4164,7652,4165, 84,4166, 112, 989,7653, 547,1059,3961, 701, # 5622 +3558,1019,7654,4167,7655,3450, 942, 639, 457,2301,2451, 993,2951, 407, 851, 494, # 5638 +4440,3347, 927,7656,1237,7657,2421,3348, 573,4168, 680, 921,2911,1279,1874, 285, # 5654 + 790,1448,1983, 719,2167,7658,7659,4441,3962,3963,1649,7660,1541, 563,7661,1077, # 5670 +7662,3349,3041,3451, 511,2997,3964,3965,3667,3966,1268,2564,3350,3207,4442,4443, # 5686 +7663, 535,1048,1276,1189,2912,2028,3142,1438,1373,2834,2952,1134,2012,7664,4169, # 5702 +1238,2578,3086,1259,7665, 700,7666,2953,3143,3668,4170,7667,4171,1146,1875,1906, # 5718 +4444,2601,3967, 781,2422, 132,1589, 203, 147, 273,2789,2402, 898,1786,2154,3968, # 5734 +3969,7668,3792,2790,7669,7670,4445,4446,7671,3208,7672,1635,3793, 965,7673,1804, # 5750 +2690,1516,3559,1121,1082,1329,3284,3970,1449,3794, 65,1128,2835,2913,2759,1590, # 5766 +3795,7674,7675, 12,2658, 45, 976,2579,3144,4447, 517,2528,1013,1037,3209,7676, # 5782 +3796,2836,7677,3797,7678,3452,7679,2602, 614,1998,2318,3798,3087,2724,2628,7680, # 5798 +2580,4172, 599,1269,7681,1810,3669,7682,2691,3088, 759,1060, 489,1805,3351,3285, # 5814 +1358,7683,7684,2386,1387,1215,2629,2252, 490,7685,7686,4173,1759,2387,2343,7687, # 5830 +4448,3799,1907,3971,2630,1806,3210,4449,3453,3286,2760,2344, 874,7688,7689,3454, # 5846 +3670,1858, 91,2914,3671,3042,3800,4450,7690,3145,3972,2659,7691,3455,1202,1403, # 5862 +3801,2954,2529,1517,2503,4451,3456,2504,7692,4452,7693,2692,1885,1495,1731,3973, # 5878 +2365,4453,7694,2029,7695,7696,3974,2693,1216, 237,2581,4174,2319,3975,3802,4454, # 5894 +4455,2694,3560,3457, 445,4456,7697,7698,7699,7700,2761, 61,3976,3672,1822,3977, # 5910 +7701, 687,2045, 935, 925, 405,2660, 703,1096,1859,2725,4457,3978,1876,1367,2695, # 5926 +3352, 918,2105,1781,2476, 334,3287,1611,1093,4458, 564,3146,3458,3673,3353, 945, # 5942 +2631,2057,4459,7702,1925, 872,4175,7703,3459,2696,3089, 349,4176,3674,3979,4460, # 5958 +3803,4177,3675,2155,3980,4461,4462,4178,4463,2403,2046, 782,3981, 400, 251,4179, # 5974 +1624,7704,7705, 277,3676, 299,1265, 476,1191,3804,2121,4180,4181,1109, 205,7706, # 5990 +2582,1000,2156,3561,1860,7707,7708,7709,4464,7710,4465,2565, 107,2477,2157,3982, # 6006 +3460,3147,7711,1533, 541,1301, 158, 753,4182,2872,3562,7712,1696, 370,1088,4183, # 6022 +4466,3563, 579, 327, 440, 162,2240, 269,1937,1374,3461, 968,3043, 56,1396,3090, # 6038 +2106,3288,3354,7713,1926,2158,4467,2998,7714,3564,7715,7716,3677,4468,2478,7717, # 6054 +2791,7718,1650,4469,7719,2603,7720,7721,3983,2661,3355,1149,3356,3984,3805,3985, # 6070 +7722,1076, 49,7723, 951,3211,3289,3290, 450,2837, 920,7724,1811,2792,2366,4184, # 6086 +1908,1138,2367,3806,3462,7725,3212,4470,1909,1147,1518,2423,4471,3807,7726,4472, # 6102 +2388,2604, 260,1795,3213,7727,7728,3808,3291, 708,7729,3565,1704,7730,3566,1351, # 6118 +1618,3357,2999,1886, 944,4185,3358,4186,3044,3359,4187,7731,3678, 422, 413,1714, # 6134 +3292, 500,2058,2345,4188,2479,7732,1344,1910, 954,7733,1668,7734,7735,3986,2404, # 6150 +4189,3567,3809,4190,7736,2302,1318,2505,3091, 133,3092,2873,4473, 629, 31,2838, # 6166 +2697,3810,4474, 850, 949,4475,3987,2955,1732,2088,4191,1496,1852,7737,3988, 620, # 6182 +3214, 981,1242,3679,3360,1619,3680,1643,3293,2139,2452,1970,1719,3463,2168,7738, # 6198 +3215,7739,7740,3361,1828,7741,1277,4476,1565,2047,7742,1636,3568,3093,7743, 869, # 6214 +2839, 655,3811,3812,3094,3989,3000,3813,1310,3569,4477,7744,7745,7746,1733, 558, # 6230 +4478,3681, 335,1549,3045,1756,4192,3682,1945,3464,1829,1291,1192, 470,2726,2107, # 6246 +2793, 913,1054,3990,7747,1027,7748,3046,3991,4479, 982,2662,3362,3148,3465,3216, # 6262 +3217,1946,2794,7749, 571,4480,7750,1830,7751,3570,2583,1523,2424,7752,2089, 984, # 6278 +4481,3683,1959,7753,3684, 852, 923,2795,3466,3685, 969,1519, 999,2048,2320,1705, # 6294 +7754,3095, 615,1662, 151, 597,3992,2405,2321,1049, 275,4482,3686,4193, 568,3687, # 6310 +3571,2480,4194,3688,7755,2425,2270, 409,3218,7756,1566,2874,3467,1002, 769,2840, # 6326 + 194,2090,3149,3689,2222,3294,4195, 628,1505,7757,7758,1763,2177,3001,3993, 521, # 6342 +1161,2584,1787,2203,2406,4483,3994,1625,4196,4197, 412, 42,3096, 464,7759,2632, # 6358 +4484,3363,1760,1571,2875,3468,2530,1219,2204,3814,2633,2140,2368,4485,4486,3295, # 6374 +1651,3364,3572,7760,7761,3573,2481,3469,7762,3690,7763,7764,2271,2091, 460,7765, # 6390 +4487,7766,3002, 962, 588,3574, 289,3219,2634,1116, 52,7767,3047,1796,7768,7769, # 6406 +7770,1467,7771,1598,1143,3691,4198,1984,1734,1067,4488,1280,3365, 465,4489,1572, # 6422 + 510,7772,1927,2241,1812,1644,3575,7773,4490,3692,7774,7775,2663,1573,1534,7776, # 6438 +7777,4199, 536,1807,1761,3470,3815,3150,2635,7778,7779,7780,4491,3471,2915,1911, # 6454 +2796,7781,3296,1122, 377,3220,7782, 360,7783,7784,4200,1529, 551,7785,2059,3693, # 6470 +1769,2426,7786,2916,4201,3297,3097,2322,2108,2030,4492,1404, 136,1468,1479, 672, # 6486 +1171,3221,2303, 271,3151,7787,2762,7788,2049, 678,2727, 865,1947,4493,7789,2013, # 6502 +3995,2956,7790,2728,2223,1397,3048,3694,4494,4495,1735,2917,3366,3576,7791,3816, # 6518 + 509,2841,2453,2876,3817,7792,7793,3152,3153,4496,4202,2531,4497,2304,1166,1010, # 6534 + 552, 681,1887,7794,7795,2957,2958,3996,1287,1596,1861,3154, 358, 453, 736, 175, # 6550 + 478,1117, 905,1167,1097,7796,1853,1530,7797,1706,7798,2178,3472,2287,3695,3473, # 6566 +3577,4203,2092,4204,7799,3367,1193,2482,4205,1458,2190,2205,1862,1888,1421,3298, # 6582 +2918,3049,2179,3474, 595,2122,7800,3997,7801,7802,4206,1707,2636, 223,3696,1359, # 6598 + 751,3098, 183,3475,7803,2797,3003, 419,2369, 633, 704,3818,2389, 241,7804,7805, # 6614 +7806, 838,3004,3697,2272,2763,2454,3819,1938,2050,3998,1309,3099,2242,1181,7807, # 6630 +1136,2206,3820,2370,1446,4207,2305,4498,7808,7809,4208,1055,2605, 484,3698,7810, # 6646 +3999, 625,4209,2273,3368,1499,4210,4000,7811,4001,4211,3222,2274,2275,3476,7812, # 6662 +7813,2764, 808,2606,3699,3369,4002,4212,3100,2532, 526,3370,3821,4213, 955,7814, # 6678 +1620,4214,2637,2427,7815,1429,3700,1669,1831, 994, 928,7816,3578,1260,7817,7818, # 6694 +7819,1948,2288, 741,2919,1626,4215,2729,2455, 867,1184, 362,3371,1392,7820,7821, # 6710 +4003,4216,1770,1736,3223,2920,4499,4500,1928,2698,1459,1158,7822,3050,3372,2877, # 6726 +1292,1929,2506,2842,3701,1985,1187,2071,2014,2607,4217,7823,2566,2507,2169,3702, # 6742 +2483,3299,7824,3703,4501,7825,7826, 666,1003,3005,1022,3579,4218,7827,4502,1813, # 6758 +2253, 574,3822,1603, 295,1535, 705,3823,4219, 283, 858, 417,7828,7829,3224,4503, # 6774 +4504,3051,1220,1889,1046,2276,2456,4004,1393,1599, 689,2567, 388,4220,7830,2484, # 6790 + 802,7831,2798,3824,2060,1405,2254,7832,4505,3825,2109,1052,1345,3225,1585,7833, # 6806 + 809,7834,7835,7836, 575,2730,3477, 956,1552,1469,1144,2323,7837,2324,1560,2457, # 6822 +3580,3226,4005, 616,2207,3155,2180,2289,7838,1832,7839,3478,4506,7840,1319,3704, # 6838 +3705,1211,3581,1023,3227,1293,2799,7841,7842,7843,3826, 607,2306,3827, 762,2878, # 6854 +1439,4221,1360,7844,1485,3052,7845,4507,1038,4222,1450,2061,2638,4223,1379,4508, # 6870 +2585,7846,7847,4224,1352,1414,2325,2921,1172,7848,7849,3828,3829,7850,1797,1451, # 6886 +7851,7852,7853,7854,2922,4006,4007,2485,2346, 411,4008,4009,3582,3300,3101,4509, # 6902 +1561,2664,1452,4010,1375,7855,7856, 47,2959, 316,7857,1406,1591,2923,3156,7858, # 6918 +1025,2141,3102,3157, 354,2731, 884,2224,4225,2407, 508,3706, 726,3583, 996,2428, # 6934 +3584, 729,7859, 392,2191,1453,4011,4510,3707,7860,7861,2458,3585,2608,1675,2800, # 6950 + 919,2347,2960,2348,1270,4511,4012, 73,7862,7863, 647,7864,3228,2843,2255,1550, # 6966 +1346,3006,7865,1332, 883,3479,7866,7867,7868,7869,3301,2765,7870,1212, 831,1347, # 6982 +4226,4512,2326,3830,1863,3053, 720,3831,4513,4514,3832,7871,4227,7872,7873,4515, # 6998 +7874,7875,1798,4516,3708,2609,4517,3586,1645,2371,7876,7877,2924, 669,2208,2665, # 7014 +2429,7878,2879,7879,7880,1028,3229,7881,4228,2408,7882,2256,1353,7883,7884,4518, # 7030 +3158, 518,7885,4013,7886,4229,1960,7887,2142,4230,7888,7889,3007,2349,2350,3833, # 7046 + 516,1833,1454,4014,2699,4231,4519,2225,2610,1971,1129,3587,7890,2766,7891,2961, # 7062 +1422, 577,1470,3008,1524,3373,7892,7893, 432,4232,3054,3480,7894,2586,1455,2508, # 7078 +2226,1972,1175,7895,1020,2732,4015,3481,4520,7896,2733,7897,1743,1361,3055,3482, # 7094 +2639,4016,4233,4521,2290, 895, 924,4234,2170, 331,2243,3056, 166,1627,3057,1098, # 7110 +7898,1232,2880,2227,3374,4522, 657, 403,1196,2372, 542,3709,3375,1600,4235,3483, # 7126 +7899,4523,2767,3230, 576, 530,1362,7900,4524,2533,2666,3710,4017,7901, 842,3834, # 7142 +7902,2801,2031,1014,4018, 213,2700,3376, 665, 621,4236,7903,3711,2925,2430,7904, # 7158 +2431,3302,3588,3377,7905,4237,2534,4238,4525,3589,1682,4239,3484,1380,7906, 724, # 7174 +2277, 600,1670,7907,1337,1233,4526,3103,2244,7908,1621,4527,7909, 651,4240,7910, # 7190 +1612,4241,2611,7911,2844,7912,2734,2307,3058,7913, 716,2459,3059, 174,1255,2701, # 7206 +4019,3590, 548,1320,1398, 728,4020,1574,7914,1890,1197,3060,4021,7915,3061,3062, # 7222 +3712,3591,3713, 747,7916, 635,4242,4528,7917,7918,7919,4243,7920,7921,4529,7922, # 7238 +3378,4530,2432, 451,7923,3714,2535,2072,4244,2735,4245,4022,7924,1764,4531,7925, # 7254 +4246, 350,7926,2278,2390,2486,7927,4247,4023,2245,1434,4024, 488,4532, 458,4248, # 7270 +4025,3715, 771,1330,2391,3835,2568,3159,2159,2409,1553,2667,3160,4249,7928,2487, # 7286 +2881,2612,1720,2702,4250,3379,4533,7929,2536,4251,7930,3231,4252,2768,7931,2015, # 7302 +2736,7932,1155,1017,3716,3836,7933,3303,2308, 201,1864,4253,1430,7934,4026,7935, # 7318 +7936,7937,7938,7939,4254,1604,7940, 414,1865, 371,2587,4534,4535,3485,2016,3104, # 7334 +4536,1708, 960,4255, 887, 389,2171,1536,1663,1721,7941,2228,4027,2351,2926,1580, # 7350 +7942,7943,7944,1744,7945,2537,4537,4538,7946,4539,7947,2073,7948,7949,3592,3380, # 7366 +2882,4256,7950,4257,2640,3381,2802, 673,2703,2460, 709,3486,4028,3593,4258,7951, # 7382 +1148, 502, 634,7952,7953,1204,4540,3594,1575,4541,2613,3717,7954,3718,3105, 948, # 7398 +3232, 121,1745,3837,1110,7955,4259,3063,2509,3009,4029,3719,1151,1771,3838,1488, # 7414 +4030,1986,7956,2433,3487,7957,7958,2093,7959,4260,3839,1213,1407,2803, 531,2737, # 7430 +2538,3233,1011,1537,7960,2769,4261,3106,1061,7961,3720,3721,1866,2883,7962,2017, # 7446 + 120,4262,4263,2062,3595,3234,2309,3840,2668,3382,1954,4542,7963,7964,3488,1047, # 7462 +2704,1266,7965,1368,4543,2845, 649,3383,3841,2539,2738,1102,2846,2669,7966,7967, # 7478 +1999,7968,1111,3596,2962,7969,2488,3842,3597,2804,1854,3384,3722,7970,7971,3385, # 7494 +2410,2884,3304,3235,3598,7972,2569,7973,3599,2805,4031,1460, 856,7974,3600,7975, # 7510 +2885,2963,7976,2886,3843,7977,4264, 632,2510, 875,3844,1697,3845,2291,7978,7979, # 7526 +4544,3010,1239, 580,4545,4265,7980, 914, 936,2074,1190,4032,1039,2123,7981,7982, # 7542 +7983,3386,1473,7984,1354,4266,3846,7985,2172,3064,4033, 915,3305,4267,4268,3306, # 7558 +1605,1834,7986,2739, 398,3601,4269,3847,4034, 328,1912,2847,4035,3848,1331,4270, # 7574 +3011, 937,4271,7987,3602,4036,4037,3387,2160,4546,3388, 524, 742, 538,3065,1012, # 7590 +7988,7989,3849,2461,7990, 658,1103, 225,3850,7991,7992,4547,7993,4548,7994,3236, # 7606 +1243,7995,4038, 963,2246,4549,7996,2705,3603,3161,7997,7998,2588,2327,7999,4550, # 7622 +8000,8001,8002,3489,3307, 957,3389,2540,2032,1930,2927,2462, 870,2018,3604,1746, # 7638 +2770,2771,2434,2463,8003,3851,8004,3723,3107,3724,3490,3390,3725,8005,1179,3066, # 7654 +8006,3162,2373,4272,3726,2541,3163,3108,2740,4039,8007,3391,1556,2542,2292, 977, # 7670 +2887,2033,4040,1205,3392,8008,1765,3393,3164,2124,1271,1689, 714,4551,3491,8009, # 7686 +2328,3852, 533,4273,3605,2181, 617,8010,2464,3308,3492,2310,8011,8012,3165,8013, # 7702 +8014,3853,1987, 618, 427,2641,3493,3394,8015,8016,1244,1690,8017,2806,4274,4552, # 7718 +8018,3494,8019,8020,2279,1576, 473,3606,4275,3395, 972,8021,3607,8022,3067,8023, # 7734 +8024,4553,4554,8025,3727,4041,4042,8026, 153,4555, 356,8027,1891,2888,4276,2143, # 7750 + 408, 803,2352,8028,3854,8029,4277,1646,2570,2511,4556,4557,3855,8030,3856,4278, # 7766 +8031,2411,3396, 752,8032,8033,1961,2964,8034, 746,3012,2465,8035,4279,3728, 698, # 7782 +4558,1892,4280,3608,2543,4559,3609,3857,8036,3166,3397,8037,1823,1302,4043,2706, # 7798 +3858,1973,4281,8038,4282,3167, 823,1303,1288,1236,2848,3495,4044,3398, 774,3859, # 7814 +8039,1581,4560,1304,2849,3860,4561,8040,2435,2161,1083,3237,4283,4045,4284, 344, # 7830 +1173, 288,2311, 454,1683,8041,8042,1461,4562,4046,2589,8043,8044,4563, 985, 894, # 7846 +8045,3399,3168,8046,1913,2928,3729,1988,8047,2110,1974,8048,4047,8049,2571,1194, # 7862 + 425,8050,4564,3169,1245,3730,4285,8051,8052,2850,8053, 636,4565,1855,3861, 760, # 7878 +1799,8054,4286,2209,1508,4566,4048,1893,1684,2293,8055,8056,8057,4287,4288,2210, # 7894 + 479,8058,8059, 832,8060,4049,2489,8061,2965,2490,3731, 990,3109, 627,1814,2642, # 7910 +4289,1582,4290,2125,2111,3496,4567,8062, 799,4291,3170,8063,4568,2112,1737,3013, # 7926 +1018, 543, 754,4292,3309,1676,4569,4570,4050,8064,1489,8065,3497,8066,2614,2889, # 7942 +4051,8067,8068,2966,8069,8070,8071,8072,3171,4571,4572,2182,1722,8073,3238,3239, # 7958 +1842,3610,1715, 481, 365,1975,1856,8074,8075,1962,2491,4573,8076,2126,3611,3240, # 7974 + 433,1894,2063,2075,8077, 602,2741,8078,8079,8080,8081,8082,3014,1628,3400,8083, # 7990 +3172,4574,4052,2890,4575,2512,8084,2544,2772,8085,8086,8087,3310,4576,2891,8088, # 8006 +4577,8089,2851,4578,4579,1221,2967,4053,2513,8090,8091,8092,1867,1989,8093,8094, # 8022 +8095,1895,8096,8097,4580,1896,4054, 318,8098,2094,4055,4293,8099,8100, 485,8101, # 8038 + 938,3862, 553,2670, 116,8102,3863,3612,8103,3498,2671,2773,3401,3311,2807,8104, # 8054 +3613,2929,4056,1747,2930,2968,8105,8106, 207,8107,8108,2672,4581,2514,8109,3015, # 8070 + 890,3614,3864,8110,1877,3732,3402,8111,2183,2353,3403,1652,8112,8113,8114, 941, # 8086 +2294, 208,3499,4057,2019, 330,4294,3865,2892,2492,3733,4295,8115,8116,8117,8118, # 8102 +) + diff --git a/venv/Lib/site-packages/pip/_vendor/chardet/euctwprober.py b/venv/Lib/site-packages/pip/_vendor/chardet/euctwprober.py new file mode 100644 index 0000000..35669cc --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/chardet/euctwprober.py @@ -0,0 +1,46 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .mbcharsetprober import MultiByteCharSetProber +from .codingstatemachine import CodingStateMachine +from .chardistribution import EUCTWDistributionAnalysis +from .mbcssm import EUCTW_SM_MODEL + +class EUCTWProber(MultiByteCharSetProber): + def __init__(self): + super(EUCTWProber, self).__init__() + self.coding_sm = CodingStateMachine(EUCTW_SM_MODEL) + self.distribution_analyzer = EUCTWDistributionAnalysis() + self.reset() + + @property + def charset_name(self): + return "EUC-TW" + + @property + def language(self): + return "Taiwan" diff --git a/venv/Lib/site-packages/pip/_vendor/chardet/gb2312freq.py b/venv/Lib/site-packages/pip/_vendor/chardet/gb2312freq.py new file mode 100644 index 0000000..697837b --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/chardet/gb2312freq.py @@ -0,0 +1,283 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +# GB2312 most frequently used character table +# +# Char to FreqOrder table , from hz6763 + +# 512 --> 0.79 -- 0.79 +# 1024 --> 0.92 -- 0.13 +# 2048 --> 0.98 -- 0.06 +# 6768 --> 1.00 -- 0.02 +# +# Ideal Distribution Ratio = 0.79135/(1-0.79135) = 3.79 +# Random Distribution Ration = 512 / (3755 - 512) = 0.157 +# +# Typical Distribution Ratio about 25% of Ideal one, still much higher that RDR + +GB2312_TYPICAL_DISTRIBUTION_RATIO = 0.9 + +GB2312_TABLE_SIZE = 3760 + +GB2312_CHAR_TO_FREQ_ORDER = ( +1671, 749,1443,2364,3924,3807,2330,3921,1704,3463,2691,1511,1515, 572,3191,2205, +2361, 224,2558, 479,1711, 963,3162, 440,4060,1905,2966,2947,3580,2647,3961,3842, +2204, 869,4207, 970,2678,5626,2944,2956,1479,4048, 514,3595, 588,1346,2820,3409, + 249,4088,1746,1873,2047,1774, 581,1813, 358,1174,3590,1014,1561,4844,2245, 670, +1636,3112, 889,1286, 953, 556,2327,3060,1290,3141, 613, 185,3477,1367, 850,3820, +1715,2428,2642,2303,2732,3041,2562,2648,3566,3946,1349, 388,3098,2091,1360,3585, + 152,1687,1539, 738,1559, 59,1232,2925,2267,1388,1249,1741,1679,2960, 151,1566, +1125,1352,4271, 924,4296, 385,3166,4459, 310,1245,2850, 70,3285,2729,3534,3575, +2398,3298,3466,1960,2265, 217,3647, 864,1909,2084,4401,2773,1010,3269,5152, 853, +3051,3121,1244,4251,1895, 364,1499,1540,2313,1180,3655,2268, 562, 715,2417,3061, + 544, 336,3768,2380,1752,4075, 950, 280,2425,4382, 183,2759,3272, 333,4297,2155, +1688,2356,1444,1039,4540, 736,1177,3349,2443,2368,2144,2225, 565, 196,1482,3406, + 927,1335,4147, 692, 878,1311,1653,3911,3622,1378,4200,1840,2969,3149,2126,1816, +2534,1546,2393,2760, 737,2494, 13, 447, 245,2747, 38,2765,2129,2589,1079, 606, + 360, 471,3755,2890, 404, 848, 699,1785,1236, 370,2221,1023,3746,2074,2026,2023, +2388,1581,2119, 812,1141,3091,2536,1519, 804,2053, 406,1596,1090, 784, 548,4414, +1806,2264,2936,1100, 343,4114,5096, 622,3358, 743,3668,1510,1626,5020,3567,2513, +3195,4115,5627,2489,2991, 24,2065,2697,1087,2719, 48,1634, 315, 68, 985,2052, + 198,2239,1347,1107,1439, 597,2366,2172, 871,3307, 919,2487,2790,1867, 236,2570, +1413,3794, 906,3365,3381,1701,1982,1818,1524,2924,1205, 616,2586,2072,2004, 575, + 253,3099, 32,1365,1182, 197,1714,2454,1201, 554,3388,3224,2748, 756,2587, 250, +2567,1507,1517,3529,1922,2761,2337,3416,1961,1677,2452,2238,3153, 615, 911,1506, +1474,2495,1265,1906,2749,3756,3280,2161, 898,2714,1759,3450,2243,2444, 563, 26, +3286,2266,3769,3344,2707,3677, 611,1402, 531,1028,2871,4548,1375, 261,2948, 835, +1190,4134, 353, 840,2684,1900,3082,1435,2109,1207,1674, 329,1872,2781,4055,2686, +2104, 608,3318,2423,2957,2768,1108,3739,3512,3271,3985,2203,1771,3520,1418,2054, +1681,1153, 225,1627,2929, 162,2050,2511,3687,1954, 124,1859,2431,1684,3032,2894, + 585,4805,3969,2869,2704,2088,2032,2095,3656,2635,4362,2209, 256, 518,2042,2105, +3777,3657, 643,2298,1148,1779, 190, 989,3544, 414, 11,2135,2063,2979,1471, 403, +3678, 126, 770,1563, 671,2499,3216,2877, 600,1179, 307,2805,4937,1268,1297,2694, + 252,4032,1448,1494,1331,1394, 127,2256, 222,1647,1035,1481,3056,1915,1048, 873, +3651, 210, 33,1608,2516, 200,1520, 415, 102, 0,3389,1287, 817, 91,3299,2940, + 836,1814, 549,2197,1396,1669,2987,3582,2297,2848,4528,1070, 687, 20,1819, 121, +1552,1364,1461,1968,2617,3540,2824,2083, 177, 948,4938,2291, 110,4549,2066, 648, +3359,1755,2110,2114,4642,4845,1693,3937,3308,1257,1869,2123, 208,1804,3159,2992, +2531,2549,3361,2418,1350,2347,2800,2568,1291,2036,2680, 72, 842,1990, 212,1233, +1154,1586, 75,2027,3410,4900,1823,1337,2710,2676, 728,2810,1522,3026,4995, 157, + 755,1050,4022, 710, 785,1936,2194,2085,1406,2777,2400, 150,1250,4049,1206, 807, +1910, 534, 529,3309,1721,1660, 274, 39,2827, 661,2670,1578, 925,3248,3815,1094, +4278,4901,4252, 41,1150,3747,2572,2227,4501,3658,4902,3813,3357,3617,2884,2258, + 887, 538,4187,3199,1294,2439,3042,2329,2343,2497,1255, 107, 543,1527, 521,3478, +3568, 194,5062, 15, 961,3870,1241,1192,2664, 66,5215,3260,2111,1295,1127,2152, +3805,4135, 901,1164,1976, 398,1278, 530,1460, 748, 904,1054,1966,1426, 53,2909, + 509, 523,2279,1534, 536,1019, 239,1685, 460,2353, 673,1065,2401,3600,4298,2272, +1272,2363, 284,1753,3679,4064,1695, 81, 815,2677,2757,2731,1386, 859, 500,4221, +2190,2566, 757,1006,2519,2068,1166,1455, 337,2654,3203,1863,1682,1914,3025,1252, +1409,1366, 847, 714,2834,2038,3209, 964,2970,1901, 885,2553,1078,1756,3049, 301, +1572,3326, 688,2130,1996,2429,1805,1648,2930,3421,2750,3652,3088, 262,1158,1254, + 389,1641,1812, 526,1719, 923,2073,1073,1902, 468, 489,4625,1140, 857,2375,3070, +3319,2863, 380, 116,1328,2693,1161,2244, 273,1212,1884,2769,3011,1775,1142, 461, +3066,1200,2147,2212, 790, 702,2695,4222,1601,1058, 434,2338,5153,3640, 67,2360, +4099,2502, 618,3472,1329, 416,1132, 830,2782,1807,2653,3211,3510,1662, 192,2124, + 296,3979,1739,1611,3684, 23, 118, 324, 446,1239,1225, 293,2520,3814,3795,2535, +3116, 17,1074, 467,2692,2201, 387,2922, 45,1326,3055,1645,3659,2817, 958, 243, +1903,2320,1339,2825,1784,3289, 356, 576, 865,2315,2381,3377,3916,1088,3122,1713, +1655, 935, 628,4689,1034,1327, 441, 800, 720, 894,1979,2183,1528,5289,2702,1071, +4046,3572,2399,1571,3281, 79, 761,1103, 327, 134, 758,1899,1371,1615, 879, 442, + 215,2605,2579, 173,2048,2485,1057,2975,3317,1097,2253,3801,4263,1403,1650,2946, + 814,4968,3487,1548,2644,1567,1285, 2, 295,2636, 97, 946,3576, 832, 141,4257, +3273, 760,3821,3521,3156,2607, 949,1024,1733,1516,1803,1920,2125,2283,2665,3180, +1501,2064,3560,2171,1592, 803,3518,1416, 732,3897,4258,1363,1362,2458, 119,1427, + 602,1525,2608,1605,1639,3175, 694,3064, 10, 465, 76,2000,4846,4208, 444,3781, +1619,3353,2206,1273,3796, 740,2483, 320,1723,2377,3660,2619,1359,1137,1762,1724, +2345,2842,1850,1862, 912, 821,1866, 612,2625,1735,2573,3369,1093, 844, 89, 937, + 930,1424,3564,2413,2972,1004,3046,3019,2011, 711,3171,1452,4178, 428, 801,1943, + 432, 445,2811, 206,4136,1472, 730, 349, 73, 397,2802,2547, 998,1637,1167, 789, + 396,3217, 154,1218, 716,1120,1780,2819,4826,1931,3334,3762,2139,1215,2627, 552, +3664,3628,3232,1405,2383,3111,1356,2652,3577,3320,3101,1703, 640,1045,1370,1246, +4996, 371,1575,2436,1621,2210, 984,4033,1734,2638, 16,4529, 663,2755,3255,1451, +3917,2257,1253,1955,2234,1263,2951, 214,1229, 617, 485, 359,1831,1969, 473,2310, + 750,2058, 165, 80,2864,2419, 361,4344,2416,2479,1134, 796,3726,1266,2943, 860, +2715, 938, 390,2734,1313,1384, 248, 202, 877,1064,2854, 522,3907, 279,1602, 297, +2357, 395,3740, 137,2075, 944,4089,2584,1267,3802, 62,1533,2285, 178, 176, 780, +2440, 201,3707, 590, 478,1560,4354,2117,1075, 30, 74,4643,4004,1635,1441,2745, + 776,2596, 238,1077,1692,1912,2844, 605, 499,1742,3947, 241,3053, 980,1749, 936, +2640,4511,2582, 515,1543,2162,5322,2892,2993, 890,2148,1924, 665,1827,3581,1032, + 968,3163, 339,1044,1896, 270, 583,1791,1720,4367,1194,3488,3669, 43,2523,1657, + 163,2167, 290,1209,1622,3378, 550, 634,2508,2510, 695,2634,2384,2512,1476,1414, + 220,1469,2341,2138,2852,3183,2900,4939,2865,3502,1211,3680, 854,3227,1299,2976, +3172, 186,2998,1459, 443,1067,3251,1495, 321,1932,3054, 909, 753,1410,1828, 436, +2441,1119,1587,3164,2186,1258, 227, 231,1425,1890,3200,3942, 247, 959, 725,5254, +2741, 577,2158,2079, 929, 120, 174, 838,2813, 591,1115, 417,2024, 40,3240,1536, +1037, 291,4151,2354, 632,1298,2406,2500,3535,1825,1846,3451, 205,1171, 345,4238, + 18,1163, 811, 685,2208,1217, 425,1312,1508,1175,4308,2552,1033, 587,1381,3059, +2984,3482, 340,1316,4023,3972, 792,3176, 519, 777,4690, 918, 933,4130,2981,3741, + 90,3360,2911,2200,5184,4550, 609,3079,2030, 272,3379,2736, 363,3881,1130,1447, + 286, 779, 357,1169,3350,3137,1630,1220,2687,2391, 747,1277,3688,2618,2682,2601, +1156,3196,5290,4034,3102,1689,3596,3128, 874, 219,2783, 798, 508,1843,2461, 269, +1658,1776,1392,1913,2983,3287,2866,2159,2372, 829,4076, 46,4253,2873,1889,1894, + 915,1834,1631,2181,2318, 298, 664,2818,3555,2735, 954,3228,3117, 527,3511,2173, + 681,2712,3033,2247,2346,3467,1652, 155,2164,3382, 113,1994, 450, 899, 494, 994, +1237,2958,1875,2336,1926,3727, 545,1577,1550, 633,3473, 204,1305,3072,2410,1956, +2471, 707,2134, 841,2195,2196,2663,3843,1026,4940, 990,3252,4997, 368,1092, 437, +3212,3258,1933,1829, 675,2977,2893, 412, 943,3723,4644,3294,3283,2230,2373,5154, +2389,2241,2661,2323,1404,2524, 593, 787, 677,3008,1275,2059, 438,2709,2609,2240, +2269,2246,1446, 36,1568,1373,3892,1574,2301,1456,3962, 693,2276,5216,2035,1143, +2720,1919,1797,1811,2763,4137,2597,1830,1699,1488,1198,2090, 424,1694, 312,3634, +3390,4179,3335,2252,1214, 561,1059,3243,2295,2561, 975,5155,2321,2751,3772, 472, +1537,3282,3398,1047,2077,2348,2878,1323,3340,3076, 690,2906, 51, 369, 170,3541, +1060,2187,2688,3670,2541,1083,1683, 928,3918, 459, 109,4427, 599,3744,4286, 143, +2101,2730,2490, 82,1588,3036,2121, 281,1860, 477,4035,1238,2812,3020,2716,3312, +1530,2188,2055,1317, 843, 636,1808,1173,3495, 649, 181,1002, 147,3641,1159,2414, +3750,2289,2795, 813,3123,2610,1136,4368, 5,3391,4541,2174, 420, 429,1728, 754, +1228,2115,2219, 347,2223,2733, 735,1518,3003,2355,3134,1764,3948,3329,1888,2424, +1001,1234,1972,3321,3363,1672,1021,1450,1584, 226, 765, 655,2526,3404,3244,2302, +3665, 731, 594,2184, 319,1576, 621, 658,2656,4299,2099,3864,1279,2071,2598,2739, + 795,3086,3699,3908,1707,2352,2402,1382,3136,2475,1465,4847,3496,3865,1085,3004, +2591,1084, 213,2287,1963,3565,2250, 822, 793,4574,3187,1772,1789,3050, 595,1484, +1959,2770,1080,2650, 456, 422,2996, 940,3322,4328,4345,3092,2742, 965,2784, 739, +4124, 952,1358,2498,2949,2565, 332,2698,2378, 660,2260,2473,4194,3856,2919, 535, +1260,2651,1208,1428,1300,1949,1303,2942, 433,2455,2450,1251,1946, 614,1269, 641, +1306,1810,2737,3078,2912, 564,2365,1419,1415,1497,4460,2367,2185,1379,3005,1307, +3218,2175,1897,3063, 682,1157,4040,4005,1712,1160,1941,1399, 394, 402,2952,1573, +1151,2986,2404, 862, 299,2033,1489,3006, 346, 171,2886,3401,1726,2932, 168,2533, + 47,2507,1030,3735,1145,3370,1395,1318,1579,3609,4560,2857,4116,1457,2529,1965, + 504,1036,2690,2988,2405, 745,5871, 849,2397,2056,3081, 863,2359,3857,2096, 99, +1397,1769,2300,4428,1643,3455,1978,1757,3718,1440, 35,4879,3742,1296,4228,2280, + 160,5063,1599,2013, 166, 520,3479,1646,3345,3012, 490,1937,1545,1264,2182,2505, +1096,1188,1369,1436,2421,1667,2792,2460,1270,2122, 727,3167,2143, 806,1706,1012, +1800,3037, 960,2218,1882, 805, 139,2456,1139,1521, 851,1052,3093,3089, 342,2039, + 744,5097,1468,1502,1585,2087, 223, 939, 326,2140,2577, 892,2481,1623,4077, 982, +3708, 135,2131, 87,2503,3114,2326,1106, 876,1616, 547,2997,2831,2093,3441,4530, +4314, 9,3256,4229,4148, 659,1462,1986,1710,2046,2913,2231,4090,4880,5255,3392, +3274,1368,3689,4645,1477, 705,3384,3635,1068,1529,2941,1458,3782,1509, 100,1656, +2548, 718,2339, 408,1590,2780,3548,1838,4117,3719,1345,3530, 717,3442,2778,3220, +2898,1892,4590,3614,3371,2043,1998,1224,3483, 891, 635, 584,2559,3355, 733,1766, +1729,1172,3789,1891,2307, 781,2982,2271,1957,1580,5773,2633,2005,4195,3097,1535, +3213,1189,1934,5693,3262, 586,3118,1324,1598, 517,1564,2217,1868,1893,4445,3728, +2703,3139,1526,1787,1992,3882,2875,1549,1199,1056,2224,1904,2711,5098,4287, 338, +1993,3129,3489,2689,1809,2815,1997, 957,1855,3898,2550,3275,3057,1105,1319, 627, +1505,1911,1883,3526, 698,3629,3456,1833,1431, 746, 77,1261,2017,2296,1977,1885, + 125,1334,1600, 525,1798,1109,2222,1470,1945, 559,2236,1186,3443,2476,1929,1411, +2411,3135,1777,3372,2621,1841,1613,3229, 668,1430,1839,2643,2916, 195,1989,2671, +2358,1387, 629,3205,2293,5256,4439, 123,1310, 888,1879,4300,3021,3605,1003,1162, +3192,2910,2010, 140,2395,2859, 55,1082,2012,2901, 662, 419,2081,1438, 680,2774, +4654,3912,1620,1731,1625,5035,4065,2328, 512,1344, 802,5443,2163,2311,2537, 524, +3399, 98,1155,2103,1918,2606,3925,2816,1393,2465,1504,3773,2177,3963,1478,4346, + 180,1113,4655,3461,2028,1698, 833,2696,1235,1322,1594,4408,3623,3013,3225,2040, +3022, 541,2881, 607,3632,2029,1665,1219, 639,1385,1686,1099,2803,3231,1938,3188, +2858, 427, 676,2772,1168,2025, 454,3253,2486,3556, 230,1950, 580, 791,1991,1280, +1086,1974,2034, 630, 257,3338,2788,4903,1017, 86,4790, 966,2789,1995,1696,1131, + 259,3095,4188,1308, 179,1463,5257, 289,4107,1248, 42,3413,1725,2288, 896,1947, + 774,4474,4254, 604,3430,4264, 392,2514,2588, 452, 237,1408,3018, 988,4531,1970, +3034,3310, 540,2370,1562,1288,2990, 502,4765,1147, 4,1853,2708, 207, 294,2814, +4078,2902,2509, 684, 34,3105,3532,2551, 644, 709,2801,2344, 573,1727,3573,3557, +2021,1081,3100,4315,2100,3681, 199,2263,1837,2385, 146,3484,1195,2776,3949, 997, +1939,3973,1008,1091,1202,1962,1847,1149,4209,5444,1076, 493, 117,5400,2521, 972, +1490,2934,1796,4542,2374,1512,2933,2657, 413,2888,1135,2762,2314,2156,1355,2369, + 766,2007,2527,2170,3124,2491,2593,2632,4757,2437, 234,3125,3591,1898,1750,1376, +1942,3468,3138, 570,2127,2145,3276,4131, 962, 132,1445,4196, 19, 941,3624,3480, +3366,1973,1374,4461,3431,2629, 283,2415,2275, 808,2887,3620,2112,2563,1353,3610, + 955,1089,3103,1053, 96, 88,4097, 823,3808,1583, 399, 292,4091,3313, 421,1128, + 642,4006, 903,2539,1877,2082, 596, 29,4066,1790, 722,2157, 130, 995,1569, 769, +1485, 464, 513,2213, 288,1923,1101,2453,4316, 133, 486,2445, 50, 625, 487,2207, + 57, 423, 481,2962, 159,3729,1558, 491, 303, 482, 501, 240,2837, 112,3648,2392, +1783, 362, 8,3433,3422, 610,2793,3277,1390,1284,1654, 21,3823, 734, 367, 623, + 193, 287, 374,1009,1483, 816, 476, 313,2255,2340,1262,2150,2899,1146,2581, 782, +2116,1659,2018,1880, 255,3586,3314,1110,2867,2137,2564, 986,2767,5185,2006, 650, + 158, 926, 762, 881,3157,2717,2362,3587, 306,3690,3245,1542,3077,2427,1691,2478, +2118,2985,3490,2438, 539,2305, 983, 129,1754, 355,4201,2386, 827,2923, 104,1773, +2838,2771, 411,2905,3919, 376, 767, 122,1114, 828,2422,1817,3506, 266,3460,1007, +1609,4998, 945,2612,4429,2274, 726,1247,1964,2914,2199,2070,4002,4108, 657,3323, +1422, 579, 455,2764,4737,1222,2895,1670, 824,1223,1487,2525, 558, 861,3080, 598, +2659,2515,1967, 752,2583,2376,2214,4180, 977, 704,2464,4999,2622,4109,1210,2961, + 819,1541, 142,2284, 44, 418, 457,1126,3730,4347,4626,1644,1876,3671,1864, 302, +1063,5694, 624, 723,1984,3745,1314,1676,2488,1610,1449,3558,3569,2166,2098, 409, +1011,2325,3704,2306, 818,1732,1383,1824,1844,3757, 999,2705,3497,1216,1423,2683, +2426,2954,2501,2726,2229,1475,2554,5064,1971,1794,1666,2014,1343, 783, 724, 191, +2434,1354,2220,5065,1763,2752,2472,4152, 131, 175,2885,3434, 92,1466,4920,2616, +3871,3872,3866, 128,1551,1632, 669,1854,3682,4691,4125,1230, 188,2973,3290,1302, +1213, 560,3266, 917, 763,3909,3249,1760, 868,1958, 764,1782,2097, 145,2277,3774, +4462, 64,1491,3062, 971,2132,3606,2442, 221,1226,1617, 218, 323,1185,3207,3147, + 571, 619,1473,1005,1744,2281, 449,1887,2396,3685, 275, 375,3816,1743,3844,3731, + 845,1983,2350,4210,1377, 773, 967,3499,3052,3743,2725,4007,1697,1022,3943,1464, +3264,2855,2722,1952,1029,2839,2467, 84,4383,2215, 820,1391,2015,2448,3672, 377, +1948,2168, 797,2545,3536,2578,2645, 94,2874,1678, 405,1259,3071, 771, 546,1315, + 470,1243,3083, 895,2468, 981, 969,2037, 846,4181, 653,1276,2928, 14,2594, 557, +3007,2474, 156, 902,1338,1740,2574, 537,2518, 973,2282,2216,2433,1928, 138,2903, +1293,2631,1612, 646,3457, 839,2935, 111, 496,2191,2847, 589,3186, 149,3994,2060, +4031,2641,4067,3145,1870, 37,3597,2136,1025,2051,3009,3383,3549,1121,1016,3261, +1301, 251,2446,2599,2153, 872,3246, 637, 334,3705, 831, 884, 921,3065,3140,4092, +2198,1944, 246,2964, 108,2045,1152,1921,2308,1031, 203,3173,4170,1907,3890, 810, +1401,2003,1690, 506, 647,1242,2828,1761,1649,3208,2249,1589,3709,2931,5156,1708, + 498, 666,2613, 834,3817,1231, 184,2851,1124, 883,3197,2261,3710,1765,1553,2658, +1178,2639,2351, 93,1193, 942,2538,2141,4402, 235,1821, 870,1591,2192,1709,1871, +3341,1618,4126,2595,2334, 603, 651, 69, 701, 268,2662,3411,2555,1380,1606, 503, + 448, 254,2371,2646, 574,1187,2309,1770, 322,2235,1292,1801, 305, 566,1133, 229, +2067,2057, 706, 167, 483,2002,2672,3295,1820,3561,3067, 316, 378,2746,3452,1112, + 136,1981, 507,1651,2917,1117, 285,4591, 182,2580,3522,1304, 335,3303,1835,2504, +1795,1792,2248, 674,1018,2106,2449,1857,2292,2845, 976,3047,1781,2600,2727,1389, +1281, 52,3152, 153, 265,3950, 672,3485,3951,4463, 430,1183, 365, 278,2169, 27, +1407,1336,2304, 209,1340,1730,2202,1852,2403,2883, 979,1737,1062, 631,2829,2542, +3876,2592, 825,2086,2226,3048,3625, 352,1417,3724, 542, 991, 431,1351,3938,1861, +2294, 826,1361,2927,3142,3503,1738, 463,2462,2723, 582,1916,1595,2808, 400,3845, +3891,2868,3621,2254, 58,2492,1123, 910,2160,2614,1372,1603,1196,1072,3385,1700, +3267,1980, 696, 480,2430, 920, 799,1570,2920,1951,2041,4047,2540,1321,4223,2469, +3562,2228,1271,2602, 401,2833,3351,2575,5157, 907,2312,1256, 410, 263,3507,1582, + 996, 678,1849,2316,1480, 908,3545,2237, 703,2322, 667,1826,2849,1531,2604,2999, +2407,3146,2151,2630,1786,3711, 469,3542, 497,3899,2409, 858, 837,4446,3393,1274, + 786, 620,1845,2001,3311, 484, 308,3367,1204,1815,3691,2332,1532,2557,1842,2020, +2724,1927,2333,4440, 567, 22,1673,2728,4475,1987,1858,1144,1597, 101,1832,3601, + 12, 974,3783,4391, 951,1412, 1,3720, 453,4608,4041, 528,1041,1027,3230,2628, +1129, 875,1051,3291,1203,2262,1069,2860,2799,2149,2615,3278, 144,1758,3040, 31, + 475,1680, 366,2685,3184, 311,1642,4008,2466,5036,1593,1493,2809, 216,1420,1668, + 233, 304,2128,3284, 232,1429,1768,1040,2008,3407,2740,2967,2543, 242,2133, 778, +1565,2022,2620, 505,2189,2756,1098,2273, 372,1614, 708, 553,2846,2094,2278, 169, +3626,2835,4161, 228,2674,3165, 809,1454,1309, 466,1705,1095, 900,3423, 880,2667, +3751,5258,2317,3109,2571,4317,2766,1503,1342, 866,4447,1118, 63,2076, 314,1881, +1348,1061, 172, 978,3515,1747, 532, 511,3970, 6, 601, 905,2699,3300,1751, 276, +1467,3725,2668, 65,4239,2544,2779,2556,1604, 578,2451,1802, 992,2331,2624,1320, +3446, 713,1513,1013, 103,2786,2447,1661, 886,1702, 916, 654,3574,2031,1556, 751, +2178,2821,2179,1498,1538,2176, 271, 914,2251,2080,1325, 638,1953,2937,3877,2432, +2754, 95,3265,1716, 260,1227,4083, 775, 106,1357,3254, 426,1607, 555,2480, 772, +1985, 244,2546, 474, 495,1046,2611,1851,2061, 71,2089,1675,2590, 742,3758,2843, +3222,1433, 267,2180,2576,2826,2233,2092,3913,2435, 956,1745,3075, 856,2113,1116, + 451, 3,1988,2896,1398, 993,2463,1878,2049,1341,2718,2721,2870,2108, 712,2904, +4363,2753,2324, 277,2872,2349,2649, 384, 987, 435, 691,3000, 922, 164,3939, 652, +1500,1184,4153,2482,3373,2165,4848,2335,3775,3508,3154,2806,2830,1554,2102,1664, +2530,1434,2408, 893,1547,2623,3447,2832,2242,2532,3169,2856,3223,2078, 49,3770, +3469, 462, 318, 656,2259,3250,3069, 679,1629,2758, 344,1138,1104,3120,1836,1283, +3115,2154,1437,4448, 934, 759,1999, 794,2862,1038, 533,2560,1722,2342, 855,2626, +1197,1663,4476,3127, 85,4240,2528, 25,1111,1181,3673, 407,3470,4561,2679,2713, + 768,1925,2841,3986,1544,1165, 932, 373,1240,2146,1930,2673, 721,4766, 354,4333, + 391,2963, 187, 61,3364,1442,1102, 330,1940,1767, 341,3809,4118, 393,2496,2062, +2211, 105, 331, 300, 439, 913,1332, 626, 379,3304,1557, 328, 689,3952, 309,1555, + 931, 317,2517,3027, 325, 569, 686,2107,3084, 60,1042,1333,2794, 264,3177,4014, +1628, 258,3712, 7,4464,1176,1043,1778, 683, 114,1975, 78,1492, 383,1886, 510, + 386, 645,5291,2891,2069,3305,4138,3867,2939,2603,2493,1935,1066,1848,3588,1015, +1282,1289,4609, 697,1453,3044,2666,3611,1856,2412, 54, 719,1330, 568,3778,2459, +1748, 788, 492, 551,1191,1000, 488,3394,3763, 282,1799, 348,2016,1523,3155,2390, +1049, 382,2019,1788,1170, 729,2968,3523, 897,3926,2785,2938,3292, 350,2319,3238, +1718,1717,2655,3453,3143,4465, 161,2889,2980,2009,1421, 56,1908,1640,2387,2232, +1917,1874,2477,4921, 148, 83,3438, 592,4245,2882,1822,1055, 741, 115,1496,1624, + 381,1638,4592,1020, 516,3214, 458, 947,4575,1432, 211,1514,2926,1865,2142, 189, + 852,1221,1400,1486, 882,2299,4036, 351, 28,1122, 700,6479,6480,6481,6482,6483, #last 512 +) + diff --git a/venv/Lib/site-packages/pip/_vendor/chardet/gb2312prober.py b/venv/Lib/site-packages/pip/_vendor/chardet/gb2312prober.py new file mode 100644 index 0000000..8446d2d --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/chardet/gb2312prober.py @@ -0,0 +1,46 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .mbcharsetprober import MultiByteCharSetProber +from .codingstatemachine import CodingStateMachine +from .chardistribution import GB2312DistributionAnalysis +from .mbcssm import GB2312_SM_MODEL + +class GB2312Prober(MultiByteCharSetProber): + def __init__(self): + super(GB2312Prober, self).__init__() + self.coding_sm = CodingStateMachine(GB2312_SM_MODEL) + self.distribution_analyzer = GB2312DistributionAnalysis() + self.reset() + + @property + def charset_name(self): + return "GB2312" + + @property + def language(self): + return "Chinese" diff --git a/venv/Lib/site-packages/pip/_vendor/chardet/hebrewprober.py b/venv/Lib/site-packages/pip/_vendor/chardet/hebrewprober.py new file mode 100644 index 0000000..b0e1bf4 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/chardet/hebrewprober.py @@ -0,0 +1,292 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Universal charset detector code. +# +# The Initial Developer of the Original Code is +# Shy Shalom +# Portions created by the Initial Developer are Copyright (C) 2005 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .charsetprober import CharSetProber +from .enums import ProbingState + +# This prober doesn't actually recognize a language or a charset. +# It is a helper prober for the use of the Hebrew model probers + +### General ideas of the Hebrew charset recognition ### +# +# Four main charsets exist in Hebrew: +# "ISO-8859-8" - Visual Hebrew +# "windows-1255" - Logical Hebrew +# "ISO-8859-8-I" - Logical Hebrew +# "x-mac-hebrew" - ?? Logical Hebrew ?? +# +# Both "ISO" charsets use a completely identical set of code points, whereas +# "windows-1255" and "x-mac-hebrew" are two different proper supersets of +# these code points. windows-1255 defines additional characters in the range +# 0x80-0x9F as some misc punctuation marks as well as some Hebrew-specific +# diacritics and additional 'Yiddish' ligature letters in the range 0xc0-0xd6. +# x-mac-hebrew defines similar additional code points but with a different +# mapping. +# +# As far as an average Hebrew text with no diacritics is concerned, all four +# charsets are identical with respect to code points. Meaning that for the +# main Hebrew alphabet, all four map the same values to all 27 Hebrew letters +# (including final letters). +# +# The dominant difference between these charsets is their directionality. +# "Visual" directionality means that the text is ordered as if the renderer is +# not aware of a BIDI rendering algorithm. The renderer sees the text and +# draws it from left to right. The text itself when ordered naturally is read +# backwards. A buffer of Visual Hebrew generally looks like so: +# "[last word of first line spelled backwards] [whole line ordered backwards +# and spelled backwards] [first word of first line spelled backwards] +# [end of line] [last word of second line] ... etc' " +# adding punctuation marks, numbers and English text to visual text is +# naturally also "visual" and from left to right. +# +# "Logical" directionality means the text is ordered "naturally" according to +# the order it is read. It is the responsibility of the renderer to display +# the text from right to left. A BIDI algorithm is used to place general +# punctuation marks, numbers and English text in the text. +# +# Texts in x-mac-hebrew are almost impossible to find on the Internet. From +# what little evidence I could find, it seems that its general directionality +# is Logical. +# +# To sum up all of the above, the Hebrew probing mechanism knows about two +# charsets: +# Visual Hebrew - "ISO-8859-8" - backwards text - Words and sentences are +# backwards while line order is natural. For charset recognition purposes +# the line order is unimportant (In fact, for this implementation, even +# word order is unimportant). +# Logical Hebrew - "windows-1255" - normal, naturally ordered text. +# +# "ISO-8859-8-I" is a subset of windows-1255 and doesn't need to be +# specifically identified. +# "x-mac-hebrew" is also identified as windows-1255. A text in x-mac-hebrew +# that contain special punctuation marks or diacritics is displayed with +# some unconverted characters showing as question marks. This problem might +# be corrected using another model prober for x-mac-hebrew. Due to the fact +# that x-mac-hebrew texts are so rare, writing another model prober isn't +# worth the effort and performance hit. +# +#### The Prober #### +# +# The prober is divided between two SBCharSetProbers and a HebrewProber, +# all of which are managed, created, fed data, inquired and deleted by the +# SBCSGroupProber. The two SBCharSetProbers identify that the text is in +# fact some kind of Hebrew, Logical or Visual. The final decision about which +# one is it is made by the HebrewProber by combining final-letter scores +# with the scores of the two SBCharSetProbers to produce a final answer. +# +# The SBCSGroupProber is responsible for stripping the original text of HTML +# tags, English characters, numbers, low-ASCII punctuation characters, spaces +# and new lines. It reduces any sequence of such characters to a single space. +# The buffer fed to each prober in the SBCS group prober is pure text in +# high-ASCII. +# The two SBCharSetProbers (model probers) share the same language model: +# Win1255Model. +# The first SBCharSetProber uses the model normally as any other +# SBCharSetProber does, to recognize windows-1255, upon which this model was +# built. The second SBCharSetProber is told to make the pair-of-letter +# lookup in the language model backwards. This in practice exactly simulates +# a visual Hebrew model using the windows-1255 logical Hebrew model. +# +# The HebrewProber is not using any language model. All it does is look for +# final-letter evidence suggesting the text is either logical Hebrew or visual +# Hebrew. Disjointed from the model probers, the results of the HebrewProber +# alone are meaningless. HebrewProber always returns 0.00 as confidence +# since it never identifies a charset by itself. Instead, the pointer to the +# HebrewProber is passed to the model probers as a helper "Name Prober". +# When the Group prober receives a positive identification from any prober, +# it asks for the name of the charset identified. If the prober queried is a +# Hebrew model prober, the model prober forwards the call to the +# HebrewProber to make the final decision. In the HebrewProber, the +# decision is made according to the final-letters scores maintained and Both +# model probers scores. The answer is returned in the form of the name of the +# charset identified, either "windows-1255" or "ISO-8859-8". + +class HebrewProber(CharSetProber): + # windows-1255 / ISO-8859-8 code points of interest + FINAL_KAF = 0xea + NORMAL_KAF = 0xeb + FINAL_MEM = 0xed + NORMAL_MEM = 0xee + FINAL_NUN = 0xef + NORMAL_NUN = 0xf0 + FINAL_PE = 0xf3 + NORMAL_PE = 0xf4 + FINAL_TSADI = 0xf5 + NORMAL_TSADI = 0xf6 + + # Minimum Visual vs Logical final letter score difference. + # If the difference is below this, don't rely solely on the final letter score + # distance. + MIN_FINAL_CHAR_DISTANCE = 5 + + # Minimum Visual vs Logical model score difference. + # If the difference is below this, don't rely at all on the model score + # distance. + MIN_MODEL_DISTANCE = 0.01 + + VISUAL_HEBREW_NAME = "ISO-8859-8" + LOGICAL_HEBREW_NAME = "windows-1255" + + def __init__(self): + super(HebrewProber, self).__init__() + self._final_char_logical_score = None + self._final_char_visual_score = None + self._prev = None + self._before_prev = None + self._logical_prober = None + self._visual_prober = None + self.reset() + + def reset(self): + self._final_char_logical_score = 0 + self._final_char_visual_score = 0 + # The two last characters seen in the previous buffer, + # mPrev and mBeforePrev are initialized to space in order to simulate + # a word delimiter at the beginning of the data + self._prev = ' ' + self._before_prev = ' ' + # These probers are owned by the group prober. + + def set_model_probers(self, logicalProber, visualProber): + self._logical_prober = logicalProber + self._visual_prober = visualProber + + def is_final(self, c): + return c in [self.FINAL_KAF, self.FINAL_MEM, self.FINAL_NUN, + self.FINAL_PE, self.FINAL_TSADI] + + def is_non_final(self, c): + # The normal Tsadi is not a good Non-Final letter due to words like + # 'lechotet' (to chat) containing an apostrophe after the tsadi. This + # apostrophe is converted to a space in FilterWithoutEnglishLetters + # causing the Non-Final tsadi to appear at an end of a word even + # though this is not the case in the original text. + # The letters Pe and Kaf rarely display a related behavior of not being + # a good Non-Final letter. Words like 'Pop', 'Winamp' and 'Mubarak' + # for example legally end with a Non-Final Pe or Kaf. However, the + # benefit of these letters as Non-Final letters outweighs the damage + # since these words are quite rare. + return c in [self.NORMAL_KAF, self.NORMAL_MEM, + self.NORMAL_NUN, self.NORMAL_PE] + + def feed(self, byte_str): + # Final letter analysis for logical-visual decision. + # Look for evidence that the received buffer is either logical Hebrew + # or visual Hebrew. + # The following cases are checked: + # 1) A word longer than 1 letter, ending with a final letter. This is + # an indication that the text is laid out "naturally" since the + # final letter really appears at the end. +1 for logical score. + # 2) A word longer than 1 letter, ending with a Non-Final letter. In + # normal Hebrew, words ending with Kaf, Mem, Nun, Pe or Tsadi, + # should not end with the Non-Final form of that letter. Exceptions + # to this rule are mentioned above in isNonFinal(). This is an + # indication that the text is laid out backwards. +1 for visual + # score + # 3) A word longer than 1 letter, starting with a final letter. Final + # letters should not appear at the beginning of a word. This is an + # indication that the text is laid out backwards. +1 for visual + # score. + # + # The visual score and logical score are accumulated throughout the + # text and are finally checked against each other in GetCharSetName(). + # No checking for final letters in the middle of words is done since + # that case is not an indication for either Logical or Visual text. + # + # We automatically filter out all 7-bit characters (replace them with + # spaces) so the word boundary detection works properly. [MAP] + + if self.state == ProbingState.NOT_ME: + # Both model probers say it's not them. No reason to continue. + return ProbingState.NOT_ME + + byte_str = self.filter_high_byte_only(byte_str) + + for cur in byte_str: + if cur == ' ': + # We stand on a space - a word just ended + if self._before_prev != ' ': + # next-to-last char was not a space so self._prev is not a + # 1 letter word + if self.is_final(self._prev): + # case (1) [-2:not space][-1:final letter][cur:space] + self._final_char_logical_score += 1 + elif self.is_non_final(self._prev): + # case (2) [-2:not space][-1:Non-Final letter][ + # cur:space] + self._final_char_visual_score += 1 + else: + # Not standing on a space + if ((self._before_prev == ' ') and + (self.is_final(self._prev)) and (cur != ' ')): + # case (3) [-2:space][-1:final letter][cur:not space] + self._final_char_visual_score += 1 + self._before_prev = self._prev + self._prev = cur + + # Forever detecting, till the end or until both model probers return + # ProbingState.NOT_ME (handled above) + return ProbingState.DETECTING + + @property + def charset_name(self): + # Make the decision: is it Logical or Visual? + # If the final letter score distance is dominant enough, rely on it. + finalsub = self._final_char_logical_score - self._final_char_visual_score + if finalsub >= self.MIN_FINAL_CHAR_DISTANCE: + return self.LOGICAL_HEBREW_NAME + if finalsub <= -self.MIN_FINAL_CHAR_DISTANCE: + return self.VISUAL_HEBREW_NAME + + # It's not dominant enough, try to rely on the model scores instead. + modelsub = (self._logical_prober.get_confidence() + - self._visual_prober.get_confidence()) + if modelsub > self.MIN_MODEL_DISTANCE: + return self.LOGICAL_HEBREW_NAME + if modelsub < -self.MIN_MODEL_DISTANCE: + return self.VISUAL_HEBREW_NAME + + # Still no good, back to final letter distance, maybe it'll save the + # day. + if finalsub < 0.0: + return self.VISUAL_HEBREW_NAME + + # (finalsub > 0 - Logical) or (don't know what to do) default to + # Logical. + return self.LOGICAL_HEBREW_NAME + + @property + def language(self): + return 'Hebrew' + + @property + def state(self): + # Remain active as long as any of the model probers are active. + if (self._logical_prober.state == ProbingState.NOT_ME) and \ + (self._visual_prober.state == ProbingState.NOT_ME): + return ProbingState.NOT_ME + return ProbingState.DETECTING diff --git a/venv/Lib/site-packages/pip/_vendor/chardet/jisfreq.py b/venv/Lib/site-packages/pip/_vendor/chardet/jisfreq.py new file mode 100644 index 0000000..83fc082 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/chardet/jisfreq.py @@ -0,0 +1,325 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +# Sampling from about 20M text materials include literature and computer technology +# +# Japanese frequency table, applied to both S-JIS and EUC-JP +# They are sorted in order. + +# 128 --> 0.77094 +# 256 --> 0.85710 +# 512 --> 0.92635 +# 1024 --> 0.97130 +# 2048 --> 0.99431 +# +# Ideal Distribution Ratio = 0.92635 / (1-0.92635) = 12.58 +# Random Distribution Ration = 512 / (2965+62+83+86-512) = 0.191 +# +# Typical Distribution Ratio, 25% of IDR + +JIS_TYPICAL_DISTRIBUTION_RATIO = 3.0 + +# Char to FreqOrder table , +JIS_TABLE_SIZE = 4368 + +JIS_CHAR_TO_FREQ_ORDER = ( + 40, 1, 6, 182, 152, 180, 295,2127, 285, 381,3295,4304,3068,4606,3165,3510, # 16 +3511,1822,2785,4607,1193,2226,5070,4608, 171,2996,1247, 18, 179,5071, 856,1661, # 32 +1262,5072, 619, 127,3431,3512,3230,1899,1700, 232, 228,1294,1298, 284, 283,2041, # 48 +2042,1061,1062, 48, 49, 44, 45, 433, 434,1040,1041, 996, 787,2997,1255,4305, # 64 +2108,4609,1684,1648,5073,5074,5075,5076,5077,5078,3687,5079,4610,5080,3927,3928, # 80 +5081,3296,3432, 290,2285,1471,2187,5082,2580,2825,1303,2140,1739,1445,2691,3375, # 96 +1691,3297,4306,4307,4611, 452,3376,1182,2713,3688,3069,4308,5083,5084,5085,5086, # 112 +5087,5088,5089,5090,5091,5092,5093,5094,5095,5096,5097,5098,5099,5100,5101,5102, # 128 +5103,5104,5105,5106,5107,5108,5109,5110,5111,5112,4097,5113,5114,5115,5116,5117, # 144 +5118,5119,5120,5121,5122,5123,5124,5125,5126,5127,5128,5129,5130,5131,5132,5133, # 160 +5134,5135,5136,5137,5138,5139,5140,5141,5142,5143,5144,5145,5146,5147,5148,5149, # 176 +5150,5151,5152,4612,5153,5154,5155,5156,5157,5158,5159,5160,5161,5162,5163,5164, # 192 +5165,5166,5167,5168,5169,5170,5171,5172,5173,5174,5175,1472, 598, 618, 820,1205, # 208 +1309,1412,1858,1307,1692,5176,5177,5178,5179,5180,5181,5182,1142,1452,1234,1172, # 224 +1875,2043,2149,1793,1382,2973, 925,2404,1067,1241, 960,1377,2935,1491, 919,1217, # 240 +1865,2030,1406,1499,2749,4098,5183,5184,5185,5186,5187,5188,2561,4099,3117,1804, # 256 +2049,3689,4309,3513,1663,5189,3166,3118,3298,1587,1561,3433,5190,3119,1625,2998, # 272 +3299,4613,1766,3690,2786,4614,5191,5192,5193,5194,2161, 26,3377, 2,3929, 20, # 288 +3691, 47,4100, 50, 17, 16, 35, 268, 27, 243, 42, 155, 24, 154, 29, 184, # 304 + 4, 91, 14, 92, 53, 396, 33, 289, 9, 37, 64, 620, 21, 39, 321, 5, # 320 + 12, 11, 52, 13, 3, 208, 138, 0, 7, 60, 526, 141, 151,1069, 181, 275, # 336 +1591, 83, 132,1475, 126, 331, 829, 15, 69, 160, 59, 22, 157, 55,1079, 312, # 352 + 109, 38, 23, 25, 10, 19, 79,5195, 61, 382,1124, 8, 30,5196,5197,5198, # 368 +5199,5200,5201,5202,5203,5204,5205,5206, 89, 62, 74, 34,2416, 112, 139, 196, # 384 + 271, 149, 84, 607, 131, 765, 46, 88, 153, 683, 76, 874, 101, 258, 57, 80, # 400 + 32, 364, 121,1508, 169,1547, 68, 235, 145,2999, 41, 360,3027, 70, 63, 31, # 416 + 43, 259, 262,1383, 99, 533, 194, 66, 93, 846, 217, 192, 56, 106, 58, 565, # 432 + 280, 272, 311, 256, 146, 82, 308, 71, 100, 128, 214, 655, 110, 261, 104,1140, # 448 + 54, 51, 36, 87, 67,3070, 185,2618,2936,2020, 28,1066,2390,2059,5207,5208, # 464 +5209,5210,5211,5212,5213,5214,5215,5216,4615,5217,5218,5219,5220,5221,5222,5223, # 480 +5224,5225,5226,5227,5228,5229,5230,5231,5232,5233,5234,5235,5236,3514,5237,5238, # 496 +5239,5240,5241,5242,5243,5244,2297,2031,4616,4310,3692,5245,3071,5246,3598,5247, # 512 +4617,3231,3515,5248,4101,4311,4618,3808,4312,4102,5249,4103,4104,3599,5250,5251, # 528 +5252,5253,5254,5255,5256,5257,5258,5259,5260,5261,5262,5263,5264,5265,5266,5267, # 544 +5268,5269,5270,5271,5272,5273,5274,5275,5276,5277,5278,5279,5280,5281,5282,5283, # 560 +5284,5285,5286,5287,5288,5289,5290,5291,5292,5293,5294,5295,5296,5297,5298,5299, # 576 +5300,5301,5302,5303,5304,5305,5306,5307,5308,5309,5310,5311,5312,5313,5314,5315, # 592 +5316,5317,5318,5319,5320,5321,5322,5323,5324,5325,5326,5327,5328,5329,5330,5331, # 608 +5332,5333,5334,5335,5336,5337,5338,5339,5340,5341,5342,5343,5344,5345,5346,5347, # 624 +5348,5349,5350,5351,5352,5353,5354,5355,5356,5357,5358,5359,5360,5361,5362,5363, # 640 +5364,5365,5366,5367,5368,5369,5370,5371,5372,5373,5374,5375,5376,5377,5378,5379, # 656 +5380,5381, 363, 642,2787,2878,2788,2789,2316,3232,2317,3434,2011, 165,1942,3930, # 672 +3931,3932,3933,5382,4619,5383,4620,5384,5385,5386,5387,5388,5389,5390,5391,5392, # 688 +5393,5394,5395,5396,5397,5398,5399,5400,5401,5402,5403,5404,5405,5406,5407,5408, # 704 +5409,5410,5411,5412,5413,5414,5415,5416,5417,5418,5419,5420,5421,5422,5423,5424, # 720 +5425,5426,5427,5428,5429,5430,5431,5432,5433,5434,5435,5436,5437,5438,5439,5440, # 736 +5441,5442,5443,5444,5445,5446,5447,5448,5449,5450,5451,5452,5453,5454,5455,5456, # 752 +5457,5458,5459,5460,5461,5462,5463,5464,5465,5466,5467,5468,5469,5470,5471,5472, # 768 +5473,5474,5475,5476,5477,5478,5479,5480,5481,5482,5483,5484,5485,5486,5487,5488, # 784 +5489,5490,5491,5492,5493,5494,5495,5496,5497,5498,5499,5500,5501,5502,5503,5504, # 800 +5505,5506,5507,5508,5509,5510,5511,5512,5513,5514,5515,5516,5517,5518,5519,5520, # 816 +5521,5522,5523,5524,5525,5526,5527,5528,5529,5530,5531,5532,5533,5534,5535,5536, # 832 +5537,5538,5539,5540,5541,5542,5543,5544,5545,5546,5547,5548,5549,5550,5551,5552, # 848 +5553,5554,5555,5556,5557,5558,5559,5560,5561,5562,5563,5564,5565,5566,5567,5568, # 864 +5569,5570,5571,5572,5573,5574,5575,5576,5577,5578,5579,5580,5581,5582,5583,5584, # 880 +5585,5586,5587,5588,5589,5590,5591,5592,5593,5594,5595,5596,5597,5598,5599,5600, # 896 +5601,5602,5603,5604,5605,5606,5607,5608,5609,5610,5611,5612,5613,5614,5615,5616, # 912 +5617,5618,5619,5620,5621,5622,5623,5624,5625,5626,5627,5628,5629,5630,5631,5632, # 928 +5633,5634,5635,5636,5637,5638,5639,5640,5641,5642,5643,5644,5645,5646,5647,5648, # 944 +5649,5650,5651,5652,5653,5654,5655,5656,5657,5658,5659,5660,5661,5662,5663,5664, # 960 +5665,5666,5667,5668,5669,5670,5671,5672,5673,5674,5675,5676,5677,5678,5679,5680, # 976 +5681,5682,5683,5684,5685,5686,5687,5688,5689,5690,5691,5692,5693,5694,5695,5696, # 992 +5697,5698,5699,5700,5701,5702,5703,5704,5705,5706,5707,5708,5709,5710,5711,5712, # 1008 +5713,5714,5715,5716,5717,5718,5719,5720,5721,5722,5723,5724,5725,5726,5727,5728, # 1024 +5729,5730,5731,5732,5733,5734,5735,5736,5737,5738,5739,5740,5741,5742,5743,5744, # 1040 +5745,5746,5747,5748,5749,5750,5751,5752,5753,5754,5755,5756,5757,5758,5759,5760, # 1056 +5761,5762,5763,5764,5765,5766,5767,5768,5769,5770,5771,5772,5773,5774,5775,5776, # 1072 +5777,5778,5779,5780,5781,5782,5783,5784,5785,5786,5787,5788,5789,5790,5791,5792, # 1088 +5793,5794,5795,5796,5797,5798,5799,5800,5801,5802,5803,5804,5805,5806,5807,5808, # 1104 +5809,5810,5811,5812,5813,5814,5815,5816,5817,5818,5819,5820,5821,5822,5823,5824, # 1120 +5825,5826,5827,5828,5829,5830,5831,5832,5833,5834,5835,5836,5837,5838,5839,5840, # 1136 +5841,5842,5843,5844,5845,5846,5847,5848,5849,5850,5851,5852,5853,5854,5855,5856, # 1152 +5857,5858,5859,5860,5861,5862,5863,5864,5865,5866,5867,5868,5869,5870,5871,5872, # 1168 +5873,5874,5875,5876,5877,5878,5879,5880,5881,5882,5883,5884,5885,5886,5887,5888, # 1184 +5889,5890,5891,5892,5893,5894,5895,5896,5897,5898,5899,5900,5901,5902,5903,5904, # 1200 +5905,5906,5907,5908,5909,5910,5911,5912,5913,5914,5915,5916,5917,5918,5919,5920, # 1216 +5921,5922,5923,5924,5925,5926,5927,5928,5929,5930,5931,5932,5933,5934,5935,5936, # 1232 +5937,5938,5939,5940,5941,5942,5943,5944,5945,5946,5947,5948,5949,5950,5951,5952, # 1248 +5953,5954,5955,5956,5957,5958,5959,5960,5961,5962,5963,5964,5965,5966,5967,5968, # 1264 +5969,5970,5971,5972,5973,5974,5975,5976,5977,5978,5979,5980,5981,5982,5983,5984, # 1280 +5985,5986,5987,5988,5989,5990,5991,5992,5993,5994,5995,5996,5997,5998,5999,6000, # 1296 +6001,6002,6003,6004,6005,6006,6007,6008,6009,6010,6011,6012,6013,6014,6015,6016, # 1312 +6017,6018,6019,6020,6021,6022,6023,6024,6025,6026,6027,6028,6029,6030,6031,6032, # 1328 +6033,6034,6035,6036,6037,6038,6039,6040,6041,6042,6043,6044,6045,6046,6047,6048, # 1344 +6049,6050,6051,6052,6053,6054,6055,6056,6057,6058,6059,6060,6061,6062,6063,6064, # 1360 +6065,6066,6067,6068,6069,6070,6071,6072,6073,6074,6075,6076,6077,6078,6079,6080, # 1376 +6081,6082,6083,6084,6085,6086,6087,6088,6089,6090,6091,6092,6093,6094,6095,6096, # 1392 +6097,6098,6099,6100,6101,6102,6103,6104,6105,6106,6107,6108,6109,6110,6111,6112, # 1408 +6113,6114,2044,2060,4621, 997,1235, 473,1186,4622, 920,3378,6115,6116, 379,1108, # 1424 +4313,2657,2735,3934,6117,3809, 636,3233, 573,1026,3693,3435,2974,3300,2298,4105, # 1440 + 854,2937,2463, 393,2581,2417, 539, 752,1280,2750,2480, 140,1161, 440, 708,1569, # 1456 + 665,2497,1746,1291,1523,3000, 164,1603, 847,1331, 537,1997, 486, 508,1693,2418, # 1472 +1970,2227, 878,1220, 299,1030, 969, 652,2751, 624,1137,3301,2619, 65,3302,2045, # 1488 +1761,1859,3120,1930,3694,3516, 663,1767, 852, 835,3695, 269, 767,2826,2339,1305, # 1504 + 896,1150, 770,1616,6118, 506,1502,2075,1012,2519, 775,2520,2975,2340,2938,4314, # 1520 +3028,2086,1224,1943,2286,6119,3072,4315,2240,1273,1987,3935,1557, 175, 597, 985, # 1536 +3517,2419,2521,1416,3029, 585, 938,1931,1007,1052,1932,1685,6120,3379,4316,4623, # 1552 + 804, 599,3121,1333,2128,2539,1159,1554,2032,3810, 687,2033,2904, 952, 675,1467, # 1568 +3436,6121,2241,1096,1786,2440,1543,1924, 980,1813,2228, 781,2692,1879, 728,1918, # 1584 +3696,4624, 548,1950,4625,1809,1088,1356,3303,2522,1944, 502, 972, 373, 513,2827, # 1600 + 586,2377,2391,1003,1976,1631,6122,2464,1084, 648,1776,4626,2141, 324, 962,2012, # 1616 +2177,2076,1384, 742,2178,1448,1173,1810, 222, 102, 301, 445, 125,2420, 662,2498, # 1632 + 277, 200,1476,1165,1068, 224,2562,1378,1446, 450,1880, 659, 791, 582,4627,2939, # 1648 +3936,1516,1274, 555,2099,3697,1020,1389,1526,3380,1762,1723,1787,2229, 412,2114, # 1664 +1900,2392,3518, 512,2597, 427,1925,2341,3122,1653,1686,2465,2499, 697, 330, 273, # 1680 + 380,2162, 951, 832, 780, 991,1301,3073, 965,2270,3519, 668,2523,2636,1286, 535, # 1696 +1407, 518, 671, 957,2658,2378, 267, 611,2197,3030,6123, 248,2299, 967,1799,2356, # 1712 + 850,1418,3437,1876,1256,1480,2828,1718,6124,6125,1755,1664,2405,6126,4628,2879, # 1728 +2829, 499,2179, 676,4629, 557,2329,2214,2090, 325,3234, 464, 811,3001, 992,2342, # 1744 +2481,1232,1469, 303,2242, 466,1070,2163, 603,1777,2091,4630,2752,4631,2714, 322, # 1760 +2659,1964,1768, 481,2188,1463,2330,2857,3600,2092,3031,2421,4632,2318,2070,1849, # 1776 +2598,4633,1302,2254,1668,1701,2422,3811,2905,3032,3123,2046,4106,1763,1694,4634, # 1792 +1604, 943,1724,1454, 917, 868,2215,1169,2940, 552,1145,1800,1228,1823,1955, 316, # 1808 +1080,2510, 361,1807,2830,4107,2660,3381,1346,1423,1134,4108,6127, 541,1263,1229, # 1824 +1148,2540, 545, 465,1833,2880,3438,1901,3074,2482, 816,3937, 713,1788,2500, 122, # 1840 +1575, 195,1451,2501,1111,6128, 859, 374,1225,2243,2483,4317, 390,1033,3439,3075, # 1856 +2524,1687, 266, 793,1440,2599, 946, 779, 802, 507, 897,1081, 528,2189,1292, 711, # 1872 +1866,1725,1167,1640, 753, 398,2661,1053, 246, 348,4318, 137,1024,3440,1600,2077, # 1888 +2129, 825,4319, 698, 238, 521, 187,2300,1157,2423,1641,1605,1464,1610,1097,2541, # 1904 +1260,1436, 759,2255,1814,2150, 705,3235, 409,2563,3304, 561,3033,2005,2564, 726, # 1920 +1956,2343,3698,4109, 949,3812,3813,3520,1669, 653,1379,2525, 881,2198, 632,2256, # 1936 +1027, 778,1074, 733,1957, 514,1481,2466, 554,2180, 702,3938,1606,1017,1398,6129, # 1952 +1380,3521, 921, 993,1313, 594, 449,1489,1617,1166, 768,1426,1360, 495,1794,3601, # 1968 +1177,3602,1170,4320,2344, 476, 425,3167,4635,3168,1424, 401,2662,1171,3382,1998, # 1984 +1089,4110, 477,3169, 474,6130,1909, 596,2831,1842, 494, 693,1051,1028,1207,3076, # 2000 + 606,2115, 727,2790,1473,1115, 743,3522, 630, 805,1532,4321,2021, 366,1057, 838, # 2016 + 684,1114,2142,4322,2050,1492,1892,1808,2271,3814,2424,1971,1447,1373,3305,1090, # 2032 +1536,3939,3523,3306,1455,2199, 336, 369,2331,1035, 584,2393, 902, 718,2600,6131, # 2048 +2753, 463,2151,1149,1611,2467, 715,1308,3124,1268, 343,1413,3236,1517,1347,2663, # 2064 +2093,3940,2022,1131,1553,2100,2941,1427,3441,2942,1323,2484,6132,1980, 872,2368, # 2080 +2441,2943, 320,2369,2116,1082, 679,1933,3941,2791,3815, 625,1143,2023, 422,2200, # 2096 +3816,6133, 730,1695, 356,2257,1626,2301,2858,2637,1627,1778, 937, 883,2906,2693, # 2112 +3002,1769,1086, 400,1063,1325,3307,2792,4111,3077, 456,2345,1046, 747,6134,1524, # 2128 + 884,1094,3383,1474,2164,1059, 974,1688,2181,2258,1047, 345,1665,1187, 358, 875, # 2144 +3170, 305, 660,3524,2190,1334,1135,3171,1540,1649,2542,1527, 927, 968,2793, 885, # 2160 +1972,1850, 482, 500,2638,1218,1109,1085,2543,1654,2034, 876, 78,2287,1482,1277, # 2176 + 861,1675,1083,1779, 724,2754, 454, 397,1132,1612,2332, 893, 672,1237, 257,2259, # 2192 +2370, 135,3384, 337,2244, 547, 352, 340, 709,2485,1400, 788,1138,2511, 540, 772, # 2208 +1682,2260,2272,2544,2013,1843,1902,4636,1999,1562,2288,4637,2201,1403,1533, 407, # 2224 + 576,3308,1254,2071, 978,3385, 170, 136,1201,3125,2664,3172,2394, 213, 912, 873, # 2240 +3603,1713,2202, 699,3604,3699, 813,3442, 493, 531,1054, 468,2907,1483, 304, 281, # 2256 +4112,1726,1252,2094, 339,2319,2130,2639, 756,1563,2944, 748, 571,2976,1588,2425, # 2272 +2715,1851,1460,2426,1528,1392,1973,3237, 288,3309, 685,3386, 296, 892,2716,2216, # 2288 +1570,2245, 722,1747,2217, 905,3238,1103,6135,1893,1441,1965, 251,1805,2371,3700, # 2304 +2601,1919,1078, 75,2182,1509,1592,1270,2640,4638,2152,6136,3310,3817, 524, 706, # 2320 +1075, 292,3818,1756,2602, 317, 98,3173,3605,3525,1844,2218,3819,2502, 814, 567, # 2336 + 385,2908,1534,6137, 534,1642,3239, 797,6138,1670,1529, 953,4323, 188,1071, 538, # 2352 + 178, 729,3240,2109,1226,1374,2000,2357,2977, 731,2468,1116,2014,2051,6139,1261, # 2368 +1593, 803,2859,2736,3443, 556, 682, 823,1541,6140,1369,2289,1706,2794, 845, 462, # 2384 +2603,2665,1361, 387, 162,2358,1740, 739,1770,1720,1304,1401,3241,1049, 627,1571, # 2400 +2427,3526,1877,3942,1852,1500, 431,1910,1503, 677, 297,2795, 286,1433,1038,1198, # 2416 +2290,1133,1596,4113,4639,2469,1510,1484,3943,6141,2442, 108, 712,4640,2372, 866, # 2432 +3701,2755,3242,1348, 834,1945,1408,3527,2395,3243,1811, 824, 994,1179,2110,1548, # 2448 +1453, 790,3003, 690,4324,4325,2832,2909,3820,1860,3821, 225,1748, 310, 346,1780, # 2464 +2470, 821,1993,2717,2796, 828, 877,3528,2860,2471,1702,2165,2910,2486,1789, 453, # 2480 + 359,2291,1676, 73,1164,1461,1127,3311, 421, 604, 314,1037, 589, 116,2487, 737, # 2496 + 837,1180, 111, 244, 735,6142,2261,1861,1362, 986, 523, 418, 581,2666,3822, 103, # 2512 + 855, 503,1414,1867,2488,1091, 657,1597, 979, 605,1316,4641,1021,2443,2078,2001, # 2528 +1209, 96, 587,2166,1032, 260,1072,2153, 173, 94, 226,3244, 819,2006,4642,4114, # 2544 +2203, 231,1744, 782, 97,2667, 786,3387, 887, 391, 442,2219,4326,1425,6143,2694, # 2560 + 633,1544,1202, 483,2015, 592,2052,1958,2472,1655, 419, 129,4327,3444,3312,1714, # 2576 +1257,3078,4328,1518,1098, 865,1310,1019,1885,1512,1734, 469,2444, 148, 773, 436, # 2592 +1815,1868,1128,1055,4329,1245,2756,3445,2154,1934,1039,4643, 579,1238, 932,2320, # 2608 + 353, 205, 801, 115,2428, 944,2321,1881, 399,2565,1211, 678, 766,3944, 335,2101, # 2624 +1459,1781,1402,3945,2737,2131,1010, 844, 981,1326,1013, 550,1816,1545,2620,1335, # 2640 +1008, 371,2881, 936,1419,1613,3529,1456,1395,2273,1834,2604,1317,2738,2503, 416, # 2656 +1643,4330, 806,1126, 229, 591,3946,1314,1981,1576,1837,1666, 347,1790, 977,3313, # 2672 + 764,2861,1853, 688,2429,1920,1462, 77, 595, 415,2002,3034, 798,1192,4115,6144, # 2688 +2978,4331,3035,2695,2582,2072,2566, 430,2430,1727, 842,1396,3947,3702, 613, 377, # 2704 + 278, 236,1417,3388,3314,3174, 757,1869, 107,3530,6145,1194, 623,2262, 207,1253, # 2720 +2167,3446,3948, 492,1117,1935, 536,1838,2757,1246,4332, 696,2095,2406,1393,1572, # 2736 +3175,1782, 583, 190, 253,1390,2230, 830,3126,3389, 934,3245,1703,1749,2979,1870, # 2752 +2545,1656,2204, 869,2346,4116,3176,1817, 496,1764,4644, 942,1504, 404,1903,1122, # 2768 +1580,3606,2945,1022, 515, 372,1735, 955,2431,3036,6146,2797,1110,2302,2798, 617, # 2784 +6147, 441, 762,1771,3447,3607,3608,1904, 840,3037, 86, 939,1385, 572,1370,2445, # 2800 +1336, 114,3703, 898, 294, 203,3315, 703,1583,2274, 429, 961,4333,1854,1951,3390, # 2816 +2373,3704,4334,1318,1381, 966,1911,2322,1006,1155, 309, 989, 458,2718,1795,1372, # 2832 +1203, 252,1689,1363,3177, 517,1936, 168,1490, 562, 193,3823,1042,4117,1835, 551, # 2848 + 470,4645, 395, 489,3448,1871,1465,2583,2641, 417,1493, 279,1295, 511,1236,1119, # 2864 + 72,1231,1982,1812,3004, 871,1564, 984,3449,1667,2696,2096,4646,2347,2833,1673, # 2880 +3609, 695,3246,2668, 807,1183,4647, 890, 388,2333,1801,1457,2911,1765,1477,1031, # 2896 +3316,3317,1278,3391,2799,2292,2526, 163,3450,4335,2669,1404,1802,6148,2323,2407, # 2912 +1584,1728,1494,1824,1269, 298, 909,3318,1034,1632, 375, 776,1683,2061, 291, 210, # 2928 +1123, 809,1249,1002,2642,3038, 206,1011,2132, 144, 975, 882,1565, 342, 667, 754, # 2944 +1442,2143,1299,2303,2062, 447, 626,2205,1221,2739,2912,1144,1214,2206,2584, 760, # 2960 +1715, 614, 950,1281,2670,2621, 810, 577,1287,2546,4648, 242,2168, 250,2643, 691, # 2976 + 123,2644, 647, 313,1029, 689,1357,2946,1650, 216, 771,1339,1306, 808,2063, 549, # 2992 + 913,1371,2913,2914,6149,1466,1092,1174,1196,1311,2605,2396,1783,1796,3079, 406, # 3008 +2671,2117,3949,4649, 487,1825,2220,6150,2915, 448,2348,1073,6151,2397,1707, 130, # 3024 + 900,1598, 329, 176,1959,2527,1620,6152,2275,4336,3319,1983,2191,3705,3610,2155, # 3040 +3706,1912,1513,1614,6153,1988, 646, 392,2304,1589,3320,3039,1826,1239,1352,1340, # 3056 +2916, 505,2567,1709,1437,2408,2547, 906,6154,2672, 384,1458,1594,1100,1329, 710, # 3072 + 423,3531,2064,2231,2622,1989,2673,1087,1882, 333, 841,3005,1296,2882,2379, 580, # 3088 +1937,1827,1293,2585, 601, 574, 249,1772,4118,2079,1120, 645, 901,1176,1690, 795, # 3104 +2207, 478,1434, 516,1190,1530, 761,2080, 930,1264, 355, 435,1552, 644,1791, 987, # 3120 + 220,1364,1163,1121,1538, 306,2169,1327,1222, 546,2645, 218, 241, 610,1704,3321, # 3136 +1984,1839,1966,2528, 451,6155,2586,3707,2568, 907,3178, 254,2947, 186,1845,4650, # 3152 + 745, 432,1757, 428,1633, 888,2246,2221,2489,3611,2118,1258,1265, 956,3127,1784, # 3168 +4337,2490, 319, 510, 119, 457,3612, 274,2035,2007,4651,1409,3128, 970,2758, 590, # 3184 +2800, 661,2247,4652,2008,3950,1420,1549,3080,3322,3951,1651,1375,2111, 485,2491, # 3200 +1429,1156,6156,2548,2183,1495, 831,1840,2529,2446, 501,1657, 307,1894,3247,1341, # 3216 + 666, 899,2156,1539,2549,1559, 886, 349,2208,3081,2305,1736,3824,2170,2759,1014, # 3232 +1913,1386, 542,1397,2948, 490, 368, 716, 362, 159, 282,2569,1129,1658,1288,1750, # 3248 +2674, 276, 649,2016, 751,1496, 658,1818,1284,1862,2209,2087,2512,3451, 622,2834, # 3264 + 376, 117,1060,2053,1208,1721,1101,1443, 247,1250,3179,1792,3952,2760,2398,3953, # 3280 +6157,2144,3708, 446,2432,1151,2570,3452,2447,2761,2835,1210,2448,3082, 424,2222, # 3296 +1251,2449,2119,2836, 504,1581,4338, 602, 817, 857,3825,2349,2306, 357,3826,1470, # 3312 +1883,2883, 255, 958, 929,2917,3248, 302,4653,1050,1271,1751,2307,1952,1430,2697, # 3328 +2719,2359, 354,3180, 777, 158,2036,4339,1659,4340,4654,2308,2949,2248,1146,2232, # 3344 +3532,2720,1696,2623,3827,6158,3129,1550,2698,1485,1297,1428, 637, 931,2721,2145, # 3360 + 914,2550,2587, 81,2450, 612, 827,2646,1242,4655,1118,2884, 472,1855,3181,3533, # 3376 +3534, 569,1353,2699,1244,1758,2588,4119,2009,2762,2171,3709,1312,1531,6159,1152, # 3392 +1938, 134,1830, 471,3710,2276,1112,1535,3323,3453,3535, 982,1337,2950, 488, 826, # 3408 + 674,1058,1628,4120,2017, 522,2399, 211, 568,1367,3454, 350, 293,1872,1139,3249, # 3424 +1399,1946,3006,1300,2360,3324, 588, 736,6160,2606, 744, 669,3536,3828,6161,1358, # 3440 + 199, 723, 848, 933, 851,1939,1505,1514,1338,1618,1831,4656,1634,3613, 443,2740, # 3456 +3829, 717,1947, 491,1914,6162,2551,1542,4121,1025,6163,1099,1223, 198,3040,2722, # 3472 + 370, 410,1905,2589, 998,1248,3182,2380, 519,1449,4122,1710, 947, 928,1153,4341, # 3488 +2277, 344,2624,1511, 615, 105, 161,1212,1076,1960,3130,2054,1926,1175,1906,2473, # 3504 + 414,1873,2801,6164,2309, 315,1319,3325, 318,2018,2146,2157, 963, 631, 223,4342, # 3520 +4343,2675, 479,3711,1197,2625,3712,2676,2361,6165,4344,4123,6166,2451,3183,1886, # 3536 +2184,1674,1330,1711,1635,1506, 799, 219,3250,3083,3954,1677,3713,3326,2081,3614, # 3552 +1652,2073,4657,1147,3041,1752, 643,1961, 147,1974,3955,6167,1716,2037, 918,3007, # 3568 +1994, 120,1537, 118, 609,3184,4345, 740,3455,1219, 332,1615,3830,6168,1621,2980, # 3584 +1582, 783, 212, 553,2350,3714,1349,2433,2082,4124, 889,6169,2310,1275,1410, 973, # 3600 + 166,1320,3456,1797,1215,3185,2885,1846,2590,2763,4658, 629, 822,3008, 763, 940, # 3616 +1990,2862, 439,2409,1566,1240,1622, 926,1282,1907,2764, 654,2210,1607, 327,1130, # 3632 +3956,1678,1623,6170,2434,2192, 686, 608,3831,3715, 903,3957,3042,6171,2741,1522, # 3648 +1915,1105,1555,2552,1359, 323,3251,4346,3457, 738,1354,2553,2311,2334,1828,2003, # 3664 +3832,1753,2351,1227,6172,1887,4125,1478,6173,2410,1874,1712,1847, 520,1204,2607, # 3680 + 264,4659, 836,2677,2102, 600,4660,3833,2278,3084,6174,4347,3615,1342, 640, 532, # 3696 + 543,2608,1888,2400,2591,1009,4348,1497, 341,1737,3616,2723,1394, 529,3252,1321, # 3712 + 983,4661,1515,2120, 971,2592, 924, 287,1662,3186,4349,2700,4350,1519, 908,1948, # 3728 +2452, 156, 796,1629,1486,2223,2055, 694,4126,1259,1036,3392,1213,2249,2742,1889, # 3744 +1230,3958,1015, 910, 408, 559,3617,4662, 746, 725, 935,4663,3959,3009,1289, 563, # 3760 + 867,4664,3960,1567,2981,2038,2626, 988,2263,2381,4351, 143,2374, 704,1895,6175, # 3776 +1188,3716,2088, 673,3085,2362,4352, 484,1608,1921,2765,2918, 215, 904,3618,3537, # 3792 + 894, 509, 976,3043,2701,3961,4353,2837,2982, 498,6176,6177,1102,3538,1332,3393, # 3808 +1487,1636,1637, 233, 245,3962, 383, 650, 995,3044, 460,1520,1206,2352, 749,3327, # 3824 + 530, 700, 389,1438,1560,1773,3963,2264, 719,2951,2724,3834, 870,1832,1644,1000, # 3840 + 839,2474,3717, 197,1630,3394, 365,2886,3964,1285,2133, 734, 922, 818,1106, 732, # 3856 + 480,2083,1774,3458, 923,2279,1350, 221,3086, 85,2233,2234,3835,1585,3010,2147, # 3872 +1387,1705,2382,1619,2475, 133, 239,2802,1991,1016,2084,2383, 411,2838,1113, 651, # 3888 +1985,1160,3328, 990,1863,3087,1048,1276,2647, 265,2627,1599,3253,2056, 150, 638, # 3904 +2019, 656, 853, 326,1479, 680,1439,4354,1001,1759, 413,3459,3395,2492,1431, 459, # 3920 +4355,1125,3329,2265,1953,1450,2065,2863, 849, 351,2678,3131,3254,3255,1104,1577, # 3936 + 227,1351,1645,2453,2193,1421,2887, 812,2121, 634, 95,2435, 201,2312,4665,1646, # 3952 +1671,2743,1601,2554,2702,2648,2280,1315,1366,2089,3132,1573,3718,3965,1729,1189, # 3968 + 328,2679,1077,1940,1136, 558,1283, 964,1195, 621,2074,1199,1743,3460,3619,1896, # 3984 +1916,1890,3836,2952,1154,2112,1064, 862, 378,3011,2066,2113,2803,1568,2839,6178, # 4000 +3088,2919,1941,1660,2004,1992,2194, 142, 707,1590,1708,1624,1922,1023,1836,1233, # 4016 +1004,2313, 789, 741,3620,6179,1609,2411,1200,4127,3719,3720,4666,2057,3721, 593, # 4032 +2840, 367,2920,1878,6180,3461,1521, 628,1168, 692,2211,2649, 300, 720,2067,2571, # 4048 +2953,3396, 959,2504,3966,3539,3462,1977, 701,6181, 954,1043, 800, 681, 183,3722, # 4064 +1803,1730,3540,4128,2103, 815,2314, 174, 467, 230,2454,1093,2134, 755,3541,3397, # 4080 +1141,1162,6182,1738,2039, 270,3256,2513,1005,1647,2185,3837, 858,1679,1897,1719, # 4096 +2954,2324,1806, 402, 670, 167,4129,1498,2158,2104, 750,6183, 915, 189,1680,1551, # 4112 + 455,4356,1501,2455, 405,1095,2955, 338,1586,1266,1819, 570, 641,1324, 237,1556, # 4128 +2650,1388,3723,6184,1368,2384,1343,1978,3089,2436, 879,3724, 792,1191, 758,3012, # 4144 +1411,2135,1322,4357, 240,4667,1848,3725,1574,6185, 420,3045,1546,1391, 714,4358, # 4160 +1967, 941,1864, 863, 664, 426, 560,1731,2680,1785,2864,1949,2363, 403,3330,1415, # 4176 +1279,2136,1697,2335, 204, 721,2097,3838, 90,6186,2085,2505, 191,3967, 124,2148, # 4192 +1376,1798,1178,1107,1898,1405, 860,4359,1243,1272,2375,2983,1558,2456,1638, 113, # 4208 +3621, 578,1923,2609, 880, 386,4130, 784,2186,2266,1422,2956,2172,1722, 497, 263, # 4224 +2514,1267,2412,2610, 177,2703,3542, 774,1927,1344, 616,1432,1595,1018, 172,4360, # 4240 +2325, 911,4361, 438,1468,3622, 794,3968,2024,2173,1681,1829,2957, 945, 895,3090, # 4256 + 575,2212,2476, 475,2401,2681, 785,2744,1745,2293,2555,1975,3133,2865, 394,4668, # 4272 +3839, 635,4131, 639, 202,1507,2195,2766,1345,1435,2572,3726,1908,1184,1181,2457, # 4288 +3727,3134,4362, 843,2611, 437, 916,4669, 234, 769,1884,3046,3047,3623, 833,6187, # 4304 +1639,2250,2402,1355,1185,2010,2047, 999, 525,1732,1290,1488,2612, 948,1578,3728, # 4320 +2413,2477,1216,2725,2159, 334,3840,1328,3624,2921,1525,4132, 564,1056, 891,4363, # 4336 +1444,1698,2385,2251,3729,1365,2281,2235,1717,6188, 864,3841,2515, 444, 527,2767, # 4352 +2922,3625, 544, 461,6189, 566, 209,2437,3398,2098,1065,2068,3331,3626,3257,2137, # 4368 #last 512 +) + + diff --git a/venv/Lib/site-packages/pip/_vendor/chardet/jpcntx.py b/venv/Lib/site-packages/pip/_vendor/chardet/jpcntx.py new file mode 100644 index 0000000..20044e4 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/chardet/jpcntx.py @@ -0,0 +1,233 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Communicator client code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + + +# This is hiragana 2-char sequence table, the number in each cell represents its frequency category +jp2CharContext = ( +(0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1), +(2,4,0,4,0,3,0,4,0,3,4,4,4,2,4,3,3,4,3,2,3,3,4,2,3,3,3,2,4,1,4,3,3,1,5,4,3,4,3,4,3,5,3,0,3,5,4,2,0,3,1,0,3,3,0,3,3,0,1,1,0,4,3,0,3,3,0,4,0,2,0,3,5,5,5,5,4,0,4,1,0,3,4), +(0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2), +(0,4,0,5,0,5,0,4,0,4,5,4,4,3,5,3,5,1,5,3,4,3,4,4,3,4,3,3,4,3,5,4,4,3,5,5,3,5,5,5,3,5,5,3,4,5,5,3,1,3,2,0,3,4,0,4,2,0,4,2,1,5,3,2,3,5,0,4,0,2,0,5,4,4,5,4,5,0,4,0,0,4,4), +(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), +(0,3,0,4,0,3,0,3,0,4,5,4,3,3,3,3,4,3,5,4,4,3,5,4,4,3,4,3,4,4,4,4,5,3,4,4,3,4,5,5,4,5,5,1,4,5,4,3,0,3,3,1,3,3,0,4,4,0,3,3,1,5,3,3,3,5,0,4,0,3,0,4,4,3,4,3,3,0,4,1,1,3,4), +(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), +(0,4,0,3,0,3,0,4,0,3,4,4,3,2,2,1,2,1,3,1,3,3,3,3,3,4,3,1,3,3,5,3,3,0,4,3,0,5,4,3,3,5,4,4,3,4,4,5,0,1,2,0,1,2,0,2,2,0,1,0,0,5,2,2,1,4,0,3,0,1,0,4,4,3,5,4,3,0,2,1,0,4,3), +(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), +(0,3,0,5,0,4,0,2,1,4,4,2,4,1,4,2,4,2,4,3,3,3,4,3,3,3,3,1,4,2,3,3,3,1,4,4,1,1,1,4,3,3,2,0,2,4,3,2,0,3,3,0,3,1,1,0,0,0,3,3,0,4,2,2,3,4,0,4,0,3,0,4,4,5,3,4,4,0,3,0,0,1,4), +(1,4,0,4,0,4,0,4,0,3,5,4,4,3,4,3,5,4,3,3,4,3,5,4,4,4,4,3,4,2,4,3,3,1,5,4,3,2,4,5,4,5,5,4,4,5,4,4,0,3,2,2,3,3,0,4,3,1,3,2,1,4,3,3,4,5,0,3,0,2,0,4,5,5,4,5,4,0,4,0,0,5,4), +(0,5,0,5,0,4,0,3,0,4,4,3,4,3,3,3,4,0,4,4,4,3,4,3,4,3,3,1,4,2,4,3,4,0,5,4,1,4,5,4,4,5,3,2,4,3,4,3,2,4,1,3,3,3,2,3,2,0,4,3,3,4,3,3,3,4,0,4,0,3,0,4,5,4,4,4,3,0,4,1,0,1,3), +(0,3,1,4,0,3,0,2,0,3,4,4,3,1,4,2,3,3,4,3,4,3,4,3,4,4,3,2,3,1,5,4,4,1,4,4,3,5,4,4,3,5,5,4,3,4,4,3,1,2,3,1,2,2,0,3,2,0,3,1,0,5,3,3,3,4,3,3,3,3,4,4,4,4,5,4,2,0,3,3,2,4,3), +(0,2,0,3,0,1,0,1,0,0,3,2,0,0,2,0,1,0,2,1,3,3,3,1,2,3,1,0,1,0,4,2,1,1,3,3,0,4,3,3,1,4,3,3,0,3,3,2,0,0,0,0,1,0,0,2,0,0,0,0,0,4,1,0,2,3,2,2,2,1,3,3,3,4,4,3,2,0,3,1,0,3,3), +(0,4,0,4,0,3,0,3,0,4,4,4,3,3,3,3,3,3,4,3,4,2,4,3,4,3,3,2,4,3,4,5,4,1,4,5,3,5,4,5,3,5,4,0,3,5,5,3,1,3,3,2,2,3,0,3,4,1,3,3,2,4,3,3,3,4,0,4,0,3,0,4,5,4,4,5,3,0,4,1,0,3,4), +(0,2,0,3,0,3,0,0,0,2,2,2,1,0,1,0,0,0,3,0,3,0,3,0,1,3,1,0,3,1,3,3,3,1,3,3,3,0,1,3,1,3,4,0,0,3,1,1,0,3,2,0,0,0,0,1,3,0,1,0,0,3,3,2,0,3,0,0,0,0,0,3,4,3,4,3,3,0,3,0,0,2,3), +(2,3,0,3,0,2,0,1,0,3,3,4,3,1,3,1,1,1,3,1,4,3,4,3,3,3,0,0,3,1,5,4,3,1,4,3,2,5,5,4,4,4,4,3,3,4,4,4,0,2,1,1,3,2,0,1,2,0,0,1,0,4,1,3,3,3,0,3,0,1,0,4,4,4,5,5,3,0,2,0,0,4,4), +(0,2,0,1,0,3,1,3,0,2,3,3,3,0,3,1,0,0,3,0,3,2,3,1,3,2,1,1,0,0,4,2,1,0,2,3,1,4,3,2,0,4,4,3,1,3,1,3,0,1,0,0,1,0,0,0,1,0,0,0,0,4,1,1,1,2,0,3,0,0,0,3,4,2,4,3,2,0,1,0,0,3,3), +(0,1,0,4,0,5,0,4,0,2,4,4,2,3,3,2,3,3,5,3,3,3,4,3,4,2,3,0,4,3,3,3,4,1,4,3,2,1,5,5,3,4,5,1,3,5,4,2,0,3,3,0,1,3,0,4,2,0,1,3,1,4,3,3,3,3,0,3,0,1,0,3,4,4,4,5,5,0,3,0,1,4,5), +(0,2,0,3,0,3,0,0,0,2,3,1,3,0,4,0,1,1,3,0,3,4,3,2,3,1,0,3,3,2,3,1,3,0,2,3,0,2,1,4,1,2,2,0,0,3,3,0,0,2,0,0,0,1,0,0,0,0,2,2,0,3,2,1,3,3,0,2,0,2,0,0,3,3,1,2,4,0,3,0,2,2,3), +(2,4,0,5,0,4,0,4,0,2,4,4,4,3,4,3,3,3,1,2,4,3,4,3,4,4,5,0,3,3,3,3,2,0,4,3,1,4,3,4,1,4,4,3,3,4,4,3,1,2,3,0,4,2,0,4,1,0,3,3,0,4,3,3,3,4,0,4,0,2,0,3,5,3,4,5,2,0,3,0,0,4,5), +(0,3,0,4,0,1,0,1,0,1,3,2,2,1,3,0,3,0,2,0,2,0,3,0,2,0,0,0,1,0,1,1,0,0,3,1,0,0,0,4,0,3,1,0,2,1,3,0,0,0,0,0,0,3,0,0,0,0,0,0,0,4,2,2,3,1,0,3,0,0,0,1,4,4,4,3,0,0,4,0,0,1,4), +(1,4,1,5,0,3,0,3,0,4,5,4,4,3,5,3,3,4,4,3,4,1,3,3,3,3,2,1,4,1,5,4,3,1,4,4,3,5,4,4,3,5,4,3,3,4,4,4,0,3,3,1,2,3,0,3,1,0,3,3,0,5,4,4,4,4,4,4,3,3,5,4,4,3,3,5,4,0,3,2,0,4,4), +(0,2,0,3,0,1,0,0,0,1,3,3,3,2,4,1,3,0,3,1,3,0,2,2,1,1,0,0,2,0,4,3,1,0,4,3,0,4,4,4,1,4,3,1,1,3,3,1,0,2,0,0,1,3,0,0,0,0,2,0,0,4,3,2,4,3,5,4,3,3,3,4,3,3,4,3,3,0,2,1,0,3,3), +(0,2,0,4,0,3,0,2,0,2,5,5,3,4,4,4,4,1,4,3,3,0,4,3,4,3,1,3,3,2,4,3,0,3,4,3,0,3,4,4,2,4,4,0,4,5,3,3,2,2,1,1,1,2,0,1,5,0,3,3,2,4,3,3,3,4,0,3,0,2,0,4,4,3,5,5,0,0,3,0,2,3,3), +(0,3,0,4,0,3,0,1,0,3,4,3,3,1,3,3,3,0,3,1,3,0,4,3,3,1,1,0,3,0,3,3,0,0,4,4,0,1,5,4,3,3,5,0,3,3,4,3,0,2,0,1,1,1,0,1,3,0,1,2,1,3,3,2,3,3,0,3,0,1,0,1,3,3,4,4,1,0,1,2,2,1,3), +(0,1,0,4,0,4,0,3,0,1,3,3,3,2,3,1,1,0,3,0,3,3,4,3,2,4,2,0,1,0,4,3,2,0,4,3,0,5,3,3,2,4,4,4,3,3,3,4,0,1,3,0,0,1,0,0,1,0,0,0,0,4,2,3,3,3,0,3,0,0,0,4,4,4,5,3,2,0,3,3,0,3,5), +(0,2,0,3,0,0,0,3,0,1,3,0,2,0,0,0,1,0,3,1,1,3,3,0,0,3,0,0,3,0,2,3,1,0,3,1,0,3,3,2,0,4,2,2,0,2,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,2,1,2,0,1,0,1,0,0,0,1,3,1,2,0,0,0,1,0,0,1,4), +(0,3,0,3,0,5,0,1,0,2,4,3,1,3,3,2,1,1,5,2,1,0,5,1,2,0,0,0,3,3,2,2,3,2,4,3,0,0,3,3,1,3,3,0,2,5,3,4,0,3,3,0,1,2,0,2,2,0,3,2,0,2,2,3,3,3,0,2,0,1,0,3,4,4,2,5,4,0,3,0,0,3,5), +(0,3,0,3,0,3,0,1,0,3,3,3,3,0,3,0,2,0,2,1,1,0,2,0,1,0,0,0,2,1,0,0,1,0,3,2,0,0,3,3,1,2,3,1,0,3,3,0,0,1,0,0,0,0,0,2,0,0,0,0,0,2,3,1,2,3,0,3,0,1,0,3,2,1,0,4,3,0,1,1,0,3,3), +(0,4,0,5,0,3,0,3,0,4,5,5,4,3,5,3,4,3,5,3,3,2,5,3,4,4,4,3,4,3,4,5,5,3,4,4,3,4,4,5,4,4,4,3,4,5,5,4,2,3,4,2,3,4,0,3,3,1,4,3,2,4,3,3,5,5,0,3,0,3,0,5,5,5,5,4,4,0,4,0,1,4,4), +(0,4,0,4,0,3,0,3,0,3,5,4,4,2,3,2,5,1,3,2,5,1,4,2,3,2,3,3,4,3,3,3,3,2,5,4,1,3,3,5,3,4,4,0,4,4,3,1,1,3,1,0,2,3,0,2,3,0,3,0,0,4,3,1,3,4,0,3,0,2,0,4,4,4,3,4,5,0,4,0,0,3,4), +(0,3,0,3,0,3,1,2,0,3,4,4,3,3,3,0,2,2,4,3,3,1,3,3,3,1,1,0,3,1,4,3,2,3,4,4,2,4,4,4,3,4,4,3,2,4,4,3,1,3,3,1,3,3,0,4,1,0,2,2,1,4,3,2,3,3,5,4,3,3,5,4,4,3,3,0,4,0,3,2,2,4,4), +(0,2,0,1,0,0,0,0,0,1,2,1,3,0,0,0,0,0,2,0,1,2,1,0,0,1,0,0,0,0,3,0,0,1,0,1,1,3,1,0,0,0,1,1,0,1,1,0,0,0,0,0,2,0,0,0,0,0,0,0,0,1,1,2,2,0,3,4,0,0,0,1,1,0,0,1,0,0,0,0,0,1,1), +(0,1,0,0,0,1,0,0,0,0,4,0,4,1,4,0,3,0,4,0,3,0,4,0,3,0,3,0,4,1,5,1,4,0,0,3,0,5,0,5,2,0,1,0,0,0,2,1,4,0,1,3,0,0,3,0,0,3,1,1,4,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0), +(1,4,0,5,0,3,0,2,0,3,5,4,4,3,4,3,5,3,4,3,3,0,4,3,3,3,3,3,3,2,4,4,3,1,3,4,4,5,4,4,3,4,4,1,3,5,4,3,3,3,1,2,2,3,3,1,3,1,3,3,3,5,3,3,4,5,0,3,0,3,0,3,4,3,4,4,3,0,3,0,2,4,3), +(0,1,0,4,0,0,0,0,0,1,4,0,4,1,4,2,4,0,3,0,1,0,1,0,0,0,0,0,2,0,3,1,1,1,0,3,0,0,0,1,2,1,0,0,1,1,1,1,0,1,0,0,0,1,0,0,3,0,0,0,0,3,2,0,2,2,0,1,0,0,0,2,3,2,3,3,0,0,0,0,2,1,0), +(0,5,1,5,0,3,0,3,0,5,4,4,5,1,5,3,3,0,4,3,4,3,5,3,4,3,3,2,4,3,4,3,3,0,3,3,1,4,4,3,4,4,4,3,4,5,5,3,2,3,1,1,3,3,1,3,1,1,3,3,2,4,5,3,3,5,0,4,0,3,0,4,4,3,5,3,3,0,3,4,0,4,3), +(0,5,0,5,0,3,0,2,0,4,4,3,5,2,4,3,3,3,4,4,4,3,5,3,5,3,3,1,4,0,4,3,3,0,3,3,0,4,4,4,4,5,4,3,3,5,5,3,2,3,1,2,3,2,0,1,0,0,3,2,2,4,4,3,1,5,0,4,0,3,0,4,3,1,3,2,1,0,3,3,0,3,3), +(0,4,0,5,0,5,0,4,0,4,5,5,5,3,4,3,3,2,5,4,4,3,5,3,5,3,4,0,4,3,4,4,3,2,4,4,3,4,5,4,4,5,5,0,3,5,5,4,1,3,3,2,3,3,1,3,1,0,4,3,1,4,4,3,4,5,0,4,0,2,0,4,3,4,4,3,3,0,4,0,0,5,5), +(0,4,0,4,0,5,0,1,1,3,3,4,4,3,4,1,3,0,5,1,3,0,3,1,3,1,1,0,3,0,3,3,4,0,4,3,0,4,4,4,3,4,4,0,3,5,4,1,0,3,0,0,2,3,0,3,1,0,3,1,0,3,2,1,3,5,0,3,0,1,0,3,2,3,3,4,4,0,2,2,0,4,4), +(2,4,0,5,0,4,0,3,0,4,5,5,4,3,5,3,5,3,5,3,5,2,5,3,4,3,3,4,3,4,5,3,2,1,5,4,3,2,3,4,5,3,4,1,2,5,4,3,0,3,3,0,3,2,0,2,3,0,4,1,0,3,4,3,3,5,0,3,0,1,0,4,5,5,5,4,3,0,4,2,0,3,5), +(0,5,0,4,0,4,0,2,0,5,4,3,4,3,4,3,3,3,4,3,4,2,5,3,5,3,4,1,4,3,4,4,4,0,3,5,0,4,4,4,4,5,3,1,3,4,5,3,3,3,3,3,3,3,0,2,2,0,3,3,2,4,3,3,3,5,3,4,1,3,3,5,3,2,0,0,0,0,4,3,1,3,3), +(0,1,0,3,0,3,0,1,0,1,3,3,3,2,3,3,3,0,3,0,0,0,3,1,3,0,0,0,2,2,2,3,0,0,3,2,0,1,2,4,1,3,3,0,0,3,3,3,0,1,0,0,2,1,0,0,3,0,3,1,0,3,0,0,1,3,0,2,0,1,0,3,3,1,3,3,0,0,1,1,0,3,3), +(0,2,0,3,0,2,1,4,0,2,2,3,1,1,3,1,1,0,2,0,3,1,2,3,1,3,0,0,1,0,4,3,2,3,3,3,1,4,2,3,3,3,3,1,0,3,1,4,0,1,1,0,1,2,0,1,1,0,1,1,0,3,1,3,2,2,0,1,0,0,0,2,3,3,3,1,0,0,0,0,0,2,3), +(0,5,0,4,0,5,0,2,0,4,5,5,3,3,4,3,3,1,5,4,4,2,4,4,4,3,4,2,4,3,5,5,4,3,3,4,3,3,5,5,4,5,5,1,3,4,5,3,1,4,3,1,3,3,0,3,3,1,4,3,1,4,5,3,3,5,0,4,0,3,0,5,3,3,1,4,3,0,4,0,1,5,3), +(0,5,0,5,0,4,0,2,0,4,4,3,4,3,3,3,3,3,5,4,4,4,4,4,4,5,3,3,5,2,4,4,4,3,4,4,3,3,4,4,5,5,3,3,4,3,4,3,3,4,3,3,3,3,1,2,2,1,4,3,3,5,4,4,3,4,0,4,0,3,0,4,4,4,4,4,1,0,4,2,0,2,4), +(0,4,0,4,0,3,0,1,0,3,5,2,3,0,3,0,2,1,4,2,3,3,4,1,4,3,3,2,4,1,3,3,3,0,3,3,0,0,3,3,3,5,3,3,3,3,3,2,0,2,0,0,2,0,0,2,0,0,1,0,0,3,1,2,2,3,0,3,0,2,0,4,4,3,3,4,1,0,3,0,0,2,4), +(0,0,0,4,0,0,0,0,0,0,1,0,1,0,2,0,0,0,0,0,1,0,2,0,1,0,0,0,0,0,3,1,3,0,3,2,0,0,0,1,0,3,2,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,4,0,2,0,0,0,0,0,0,2), +(0,2,1,3,0,2,0,2,0,3,3,3,3,1,3,1,3,3,3,3,3,3,4,2,2,1,2,1,4,0,4,3,1,3,3,3,2,4,3,5,4,3,3,3,3,3,3,3,0,1,3,0,2,0,0,1,0,0,1,0,0,4,2,0,2,3,0,3,3,0,3,3,4,2,3,1,4,0,1,2,0,2,3), +(0,3,0,3,0,1,0,3,0,2,3,3,3,0,3,1,2,0,3,3,2,3,3,2,3,2,3,1,3,0,4,3,2,0,3,3,1,4,3,3,2,3,4,3,1,3,3,1,1,0,1,1,0,1,0,1,0,1,0,0,0,4,1,1,0,3,0,3,1,0,2,3,3,3,3,3,1,0,0,2,0,3,3), +(0,0,0,0,0,0,0,0,0,0,3,0,2,0,3,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,3,0,3,0,3,1,0,1,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,2,0,2,3,0,0,0,0,0,0,0,0,3), +(0,2,0,3,1,3,0,3,0,2,3,3,3,1,3,1,3,1,3,1,3,3,3,1,3,0,2,3,1,1,4,3,3,2,3,3,1,2,2,4,1,3,3,0,1,4,2,3,0,1,3,0,3,0,0,1,3,0,2,0,0,3,3,2,1,3,0,3,0,2,0,3,4,4,4,3,1,0,3,0,0,3,3), +(0,2,0,1,0,2,0,0,0,1,3,2,2,1,3,0,1,1,3,0,3,2,3,1,2,0,2,0,1,1,3,3,3,0,3,3,1,1,2,3,2,3,3,1,2,3,2,0,0,1,0,0,0,0,0,0,3,0,1,0,0,2,1,2,1,3,0,3,0,0,0,3,4,4,4,3,2,0,2,0,0,2,4), +(0,0,0,1,0,1,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,2,2,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,3,1,0,0,0,0,0,0,0,3), +(0,3,0,3,0,2,0,3,0,3,3,3,2,3,2,2,2,0,3,1,3,3,3,2,3,3,0,0,3,0,3,2,2,0,2,3,1,4,3,4,3,3,2,3,1,5,4,4,0,3,1,2,1,3,0,3,1,1,2,0,2,3,1,3,1,3,0,3,0,1,0,3,3,4,4,2,1,0,2,1,0,2,4), +(0,1,0,3,0,1,0,2,0,1,4,2,5,1,4,0,2,0,2,1,3,1,4,0,2,1,0,0,2,1,4,1,1,0,3,3,0,5,1,3,2,3,3,1,0,3,2,3,0,1,0,0,0,0,0,0,1,0,0,0,0,4,0,1,0,3,0,2,0,1,0,3,3,3,4,3,3,0,0,0,0,2,3), +(0,0,0,1,0,0,0,0,0,0,2,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,0,0,1,0,0,0,0,0,3), +(0,1,0,3,0,4,0,3,0,2,4,3,1,0,3,2,2,1,3,1,2,2,3,1,1,1,2,1,3,0,1,2,0,1,3,2,1,3,0,5,5,1,0,0,1,3,2,1,0,3,0,0,1,0,0,0,0,0,3,4,0,1,1,1,3,2,0,2,0,1,0,2,3,3,1,2,3,0,1,0,1,0,4), +(0,0,0,1,0,3,0,3,0,2,2,1,0,0,4,0,3,0,3,1,3,0,3,0,3,0,1,0,3,0,3,1,3,0,3,3,0,0,1,2,1,1,1,0,1,2,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,2,2,1,2,0,0,2,0,0,0,0,2,3,3,3,3,0,0,0,0,1,4), +(0,0,0,3,0,3,0,0,0,0,3,1,1,0,3,0,1,0,2,0,1,0,0,0,0,0,0,0,1,0,3,0,2,0,2,3,0,0,2,2,3,1,2,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,2,0,0,0,0,2,3), +(2,4,0,5,0,5,0,4,0,3,4,3,3,3,4,3,3,3,4,3,4,4,5,4,5,5,5,2,3,0,5,5,4,1,5,4,3,1,5,4,3,4,4,3,3,4,3,3,0,3,2,0,2,3,0,3,0,0,3,3,0,5,3,2,3,3,0,3,0,3,0,3,4,5,4,5,3,0,4,3,0,3,4), +(0,3,0,3,0,3,0,3,0,3,3,4,3,2,3,2,3,0,4,3,3,3,3,3,3,3,3,0,3,2,4,3,3,1,3,4,3,4,4,4,3,4,4,3,2,4,4,1,0,2,0,0,1,1,0,2,0,0,3,1,0,5,3,2,1,3,0,3,0,1,2,4,3,2,4,3,3,0,3,2,0,4,4), +(0,3,0,3,0,1,0,0,0,1,4,3,3,2,3,1,3,1,4,2,3,2,4,2,3,4,3,0,2,2,3,3,3,0,3,3,3,0,3,4,1,3,3,0,3,4,3,3,0,1,1,0,1,0,0,0,4,0,3,0,0,3,1,2,1,3,0,4,0,1,0,4,3,3,4,3,3,0,2,0,0,3,3), +(0,3,0,4,0,1,0,3,0,3,4,3,3,0,3,3,3,1,3,1,3,3,4,3,3,3,0,0,3,1,5,3,3,1,3,3,2,5,4,3,3,4,5,3,2,5,3,4,0,1,0,0,0,0,0,2,0,0,1,1,0,4,2,2,1,3,0,3,0,2,0,4,4,3,5,3,2,0,1,1,0,3,4), +(0,5,0,4,0,5,0,2,0,4,4,3,3,2,3,3,3,1,4,3,4,1,5,3,4,3,4,0,4,2,4,3,4,1,5,4,0,4,4,4,4,5,4,1,3,5,4,2,1,4,1,1,3,2,0,3,1,0,3,2,1,4,3,3,3,4,0,4,0,3,0,4,4,4,3,3,3,0,4,2,0,3,4), +(1,4,0,4,0,3,0,1,0,3,3,3,1,1,3,3,2,2,3,3,1,0,3,2,2,1,2,0,3,1,2,1,2,0,3,2,0,2,2,3,3,4,3,0,3,3,1,2,0,1,1,3,1,2,0,0,3,0,1,1,0,3,2,2,3,3,0,3,0,0,0,2,3,3,4,3,3,0,1,0,0,1,4), +(0,4,0,4,0,4,0,0,0,3,4,4,3,1,4,2,3,2,3,3,3,1,4,3,4,0,3,0,4,2,3,3,2,2,5,4,2,1,3,4,3,4,3,1,3,3,4,2,0,2,1,0,3,3,0,0,2,0,3,1,0,4,4,3,4,3,0,4,0,1,0,2,4,4,4,4,4,0,3,2,0,3,3), +(0,0,0,1,0,4,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,3,2,0,0,1,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,2), +(0,2,0,3,0,4,0,4,0,1,3,3,3,0,4,0,2,1,2,1,1,1,2,0,3,1,1,0,1,0,3,1,0,0,3,3,2,0,1,1,0,0,0,0,0,1,0,2,0,2,2,0,3,1,0,0,1,0,1,1,0,1,2,0,3,0,0,0,0,1,0,0,3,3,4,3,1,0,1,0,3,0,2), +(0,0,0,3,0,5,0,0,0,0,1,0,2,0,3,1,0,1,3,0,0,0,2,0,0,0,1,0,0,0,1,1,0,0,4,0,0,0,2,3,0,1,4,1,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,1,0,0,0,0,0,0,0,2,0,0,3,0,0,0,0,0,3), +(0,2,0,5,0,5,0,1,0,2,4,3,3,2,5,1,3,2,3,3,3,0,4,1,2,0,3,0,4,0,2,2,1,1,5,3,0,0,1,4,2,3,2,0,3,3,3,2,0,2,4,1,1,2,0,1,1,0,3,1,0,1,3,1,2,3,0,2,0,0,0,1,3,5,4,4,4,0,3,0,0,1,3), +(0,4,0,5,0,4,0,4,0,4,5,4,3,3,4,3,3,3,4,3,4,4,5,3,4,5,4,2,4,2,3,4,3,1,4,4,1,3,5,4,4,5,5,4,4,5,5,5,2,3,3,1,4,3,1,3,3,0,3,3,1,4,3,4,4,4,0,3,0,4,0,3,3,4,4,5,0,0,4,3,0,4,5), +(0,4,0,4,0,3,0,3,0,3,4,4,4,3,3,2,4,3,4,3,4,3,5,3,4,3,2,1,4,2,4,4,3,1,3,4,2,4,5,5,3,4,5,4,1,5,4,3,0,3,2,2,3,2,1,3,1,0,3,3,3,5,3,3,3,5,4,4,2,3,3,4,3,3,3,2,1,0,3,2,1,4,3), +(0,4,0,5,0,4,0,3,0,3,5,5,3,2,4,3,4,0,5,4,4,1,4,4,4,3,3,3,4,3,5,5,2,3,3,4,1,2,5,5,3,5,5,2,3,5,5,4,0,3,2,0,3,3,1,1,5,1,4,1,0,4,3,2,3,5,0,4,0,3,0,5,4,3,4,3,0,0,4,1,0,4,4), +(1,3,0,4,0,2,0,2,0,2,5,5,3,3,3,3,3,0,4,2,3,4,4,4,3,4,0,0,3,4,5,4,3,3,3,3,2,5,5,4,5,5,5,4,3,5,5,5,1,3,1,0,1,0,0,3,2,0,4,2,0,5,2,3,2,4,1,3,0,3,0,4,5,4,5,4,3,0,4,2,0,5,4), +(0,3,0,4,0,5,0,3,0,3,4,4,3,2,3,2,3,3,3,3,3,2,4,3,3,2,2,0,3,3,3,3,3,1,3,3,3,0,4,4,3,4,4,1,1,4,4,2,0,3,1,0,1,1,0,4,1,0,2,3,1,3,3,1,3,4,0,3,0,1,0,3,1,3,0,0,1,0,2,0,0,4,4), +(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), +(0,3,0,3,0,2,0,3,0,1,5,4,3,3,3,1,4,2,1,2,3,4,4,2,4,4,5,0,3,1,4,3,4,0,4,3,3,3,2,3,2,5,3,4,3,2,2,3,0,0,3,0,2,1,0,1,2,0,0,0,0,2,1,1,3,1,0,2,0,4,0,3,4,4,4,5,2,0,2,0,0,1,3), +(0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,1,1,0,0,1,1,0,0,0,4,2,1,1,0,1,0,3,2,0,0,3,1,1,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,1,0,0,0,2,0,0,0,1,4,0,4,2,1,0,0,0,0,0,1), +(0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,1,0,0,0,0,0,0,1,0,1,0,0,0,0,3,1,0,0,0,2,0,2,1,0,0,1,2,1,0,1,1,0,0,3,0,0,0,0,0,0,0,0,0,0,0,1,3,1,0,0,0,0,0,1,0,0,2,1,0,0,0,0,0,0,0,0,2), +(0,4,0,4,0,4,0,3,0,4,4,3,4,2,4,3,2,0,4,4,4,3,5,3,5,3,3,2,4,2,4,3,4,3,1,4,0,2,3,4,4,4,3,3,3,4,4,4,3,4,1,3,4,3,2,1,2,1,3,3,3,4,4,3,3,5,0,4,0,3,0,4,3,3,3,2,1,0,3,0,0,3,3), +(0,4,0,3,0,3,0,3,0,3,5,5,3,3,3,3,4,3,4,3,3,3,4,4,4,3,3,3,3,4,3,5,3,3,1,3,2,4,5,5,5,5,4,3,4,5,5,3,2,2,3,3,3,3,2,3,3,1,2,3,2,4,3,3,3,4,0,4,0,2,0,4,3,2,2,1,2,0,3,0,0,4,1), +) + +class JapaneseContextAnalysis(object): + NUM_OF_CATEGORY = 6 + DONT_KNOW = -1 + ENOUGH_REL_THRESHOLD = 100 + MAX_REL_THRESHOLD = 1000 + MINIMUM_DATA_THRESHOLD = 4 + + def __init__(self): + self._total_rel = None + self._rel_sample = None + self._need_to_skip_char_num = None + self._last_char_order = None + self._done = None + self.reset() + + def reset(self): + self._total_rel = 0 # total sequence received + # category counters, each integer counts sequence in its category + self._rel_sample = [0] * self.NUM_OF_CATEGORY + # if last byte in current buffer is not the last byte of a character, + # we need to know how many bytes to skip in next buffer + self._need_to_skip_char_num = 0 + self._last_char_order = -1 # The order of previous char + # If this flag is set to True, detection is done and conclusion has + # been made + self._done = False + + def feed(self, byte_str, num_bytes): + if self._done: + return + + # The buffer we got is byte oriented, and a character may span in more than one + # buffers. In case the last one or two byte in last buffer is not + # complete, we record how many byte needed to complete that character + # and skip these bytes here. We can choose to record those bytes as + # well and analyse the character once it is complete, but since a + # character will not make much difference, by simply skipping + # this character will simply our logic and improve performance. + i = self._need_to_skip_char_num + while i < num_bytes: + order, char_len = self.get_order(byte_str[i:i + 2]) + i += char_len + if i > num_bytes: + self._need_to_skip_char_num = i - num_bytes + self._last_char_order = -1 + else: + if (order != -1) and (self._last_char_order != -1): + self._total_rel += 1 + if self._total_rel > self.MAX_REL_THRESHOLD: + self._done = True + break + self._rel_sample[jp2CharContext[self._last_char_order][order]] += 1 + self._last_char_order = order + + def got_enough_data(self): + return self._total_rel > self.ENOUGH_REL_THRESHOLD + + def get_confidence(self): + # This is just one way to calculate confidence. It works well for me. + if self._total_rel > self.MINIMUM_DATA_THRESHOLD: + return (self._total_rel - self._rel_sample[0]) / self._total_rel + else: + return self.DONT_KNOW + + def get_order(self, byte_str): + return -1, 1 + +class SJISContextAnalysis(JapaneseContextAnalysis): + def __init__(self): + super(SJISContextAnalysis, self).__init__() + self._charset_name = "SHIFT_JIS" + + @property + def charset_name(self): + return self._charset_name + + def get_order(self, byte_str): + if not byte_str: + return -1, 1 + # find out current char's byte length + first_char = byte_str[0] + if (0x81 <= first_char <= 0x9F) or (0xE0 <= first_char <= 0xFC): + char_len = 2 + if (first_char == 0x87) or (0xFA <= first_char <= 0xFC): + self._charset_name = "CP932" + else: + char_len = 1 + + # return its order if it is hiragana + if len(byte_str) > 1: + second_char = byte_str[1] + if (first_char == 202) and (0x9F <= second_char <= 0xF1): + return second_char - 0x9F, char_len + + return -1, char_len + +class EUCJPContextAnalysis(JapaneseContextAnalysis): + def get_order(self, byte_str): + if not byte_str: + return -1, 1 + # find out current char's byte length + first_char = byte_str[0] + if (first_char == 0x8E) or (0xA1 <= first_char <= 0xFE): + char_len = 2 + elif first_char == 0x8F: + char_len = 3 + else: + char_len = 1 + + # return its order if it is hiragana + if len(byte_str) > 1: + second_char = byte_str[1] + if (first_char == 0xA4) and (0xA1 <= second_char <= 0xF3): + return second_char - 0xA1, char_len + + return -1, char_len + + diff --git a/venv/Lib/site-packages/pip/_vendor/chardet/langbulgarianmodel.py b/venv/Lib/site-packages/pip/_vendor/chardet/langbulgarianmodel.py new file mode 100644 index 0000000..e963a50 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/chardet/langbulgarianmodel.py @@ -0,0 +1,4650 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +from pip._vendor.chardet.sbcharsetprober import SingleByteCharSetModel + + +# 3: Positive +# 2: Likely +# 1: Unlikely +# 0: Negative + +BULGARIAN_LANG_MODEL = { + 63: { # 'e' + 63: 1, # 'e' + 45: 0, # '\xad' + 31: 0, # 'Ð' + 32: 0, # 'Б' + 35: 0, # 'Ð’' + 43: 0, # 'Г' + 37: 0, # 'Д' + 44: 0, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 0, # 'И' + 59: 0, # 'Й' + 33: 0, # 'К' + 46: 0, # 'Л' + 38: 0, # 'Ðœ' + 36: 0, # 'Ð' + 41: 0, # 'О' + 30: 0, # 'П' + 39: 0, # 'Р' + 28: 0, # 'С' + 34: 0, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Ð¥' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 0, # 'а' + 18: 1, # 'б' + 9: 1, # 'в' + 20: 1, # 'г' + 11: 1, # 'д' + 3: 1, # 'е' + 23: 1, # 'ж' + 15: 1, # 'з' + 2: 0, # 'и' + 26: 1, # 'й' + 12: 1, # 'к' + 10: 1, # 'л' + 14: 1, # 'м' + 6: 1, # 'н' + 4: 1, # 'о' + 13: 1, # 'п' + 7: 1, # 'Ñ€' + 8: 1, # 'Ñ' + 5: 1, # 'Ñ‚' + 19: 0, # 'у' + 29: 1, # 'Ñ„' + 25: 1, # 'Ñ…' + 22: 0, # 'ц' + 21: 1, # 'ч' + 27: 1, # 'ш' + 24: 1, # 'щ' + 17: 0, # 'ÑŠ' + 52: 0, # 'ÑŒ' + 42: 0, # 'ÑŽ' + 16: 1, # 'Ñ' + 58: 0, # 'Ñ”' + 62: 0, # 'â„–' + }, + 45: { # '\xad' + 63: 0, # 'e' + 45: 0, # '\xad' + 31: 0, # 'Ð' + 32: 1, # 'Б' + 35: 1, # 'Ð’' + 43: 0, # 'Г' + 37: 1, # 'Д' + 44: 0, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 1, # 'И' + 59: 0, # 'Й' + 33: 1, # 'К' + 46: 0, # 'Л' + 38: 1, # 'Ðœ' + 36: 0, # 'Ð' + 41: 1, # 'О' + 30: 1, # 'П' + 39: 1, # 'Р' + 28: 1, # 'С' + 34: 0, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 1, # 'Ð¥' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 0, # 'а' + 18: 0, # 'б' + 9: 0, # 'в' + 20: 0, # 'г' + 11: 0, # 'д' + 3: 0, # 'е' + 23: 0, # 'ж' + 15: 0, # 'з' + 2: 0, # 'и' + 26: 0, # 'й' + 12: 0, # 'к' + 10: 0, # 'л' + 14: 0, # 'м' + 6: 0, # 'н' + 4: 0, # 'о' + 13: 0, # 'п' + 7: 0, # 'Ñ€' + 8: 0, # 'Ñ' + 5: 0, # 'Ñ‚' + 19: 0, # 'у' + 29: 0, # 'Ñ„' + 25: 0, # 'Ñ…' + 22: 0, # 'ц' + 21: 0, # 'ч' + 27: 0, # 'ш' + 24: 0, # 'щ' + 17: 0, # 'ÑŠ' + 52: 0, # 'ÑŒ' + 42: 0, # 'ÑŽ' + 16: 0, # 'Ñ' + 58: 0, # 'Ñ”' + 62: 0, # 'â„–' + }, + 31: { # 'Ð' + 63: 0, # 'e' + 45: 1, # '\xad' + 31: 1, # 'Ð' + 32: 1, # 'Б' + 35: 2, # 'Ð’' + 43: 1, # 'Г' + 37: 2, # 'Д' + 44: 2, # 'Е' + 55: 1, # 'Ж' + 47: 2, # 'З' + 40: 1, # 'И' + 59: 1, # 'Й' + 33: 1, # 'К' + 46: 2, # 'Л' + 38: 1, # 'Ðœ' + 36: 2, # 'Ð' + 41: 1, # 'О' + 30: 2, # 'П' + 39: 2, # 'Р' + 28: 2, # 'С' + 34: 2, # 'Т' + 51: 1, # 'У' + 48: 2, # 'Ф' + 49: 1, # 'Ð¥' + 53: 1, # 'Ц' + 50: 1, # 'Ч' + 54: 1, # 'Ш' + 57: 2, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 1, # 'Я' + 1: 1, # 'а' + 18: 2, # 'б' + 9: 2, # 'в' + 20: 2, # 'г' + 11: 2, # 'д' + 3: 1, # 'е' + 23: 1, # 'ж' + 15: 2, # 'з' + 2: 0, # 'и' + 26: 2, # 'й' + 12: 2, # 'к' + 10: 3, # 'л' + 14: 2, # 'м' + 6: 3, # 'н' + 4: 0, # 'о' + 13: 2, # 'п' + 7: 2, # 'Ñ€' + 8: 2, # 'Ñ' + 5: 2, # 'Ñ‚' + 19: 1, # 'у' + 29: 2, # 'Ñ„' + 25: 1, # 'Ñ…' + 22: 1, # 'ц' + 21: 1, # 'ч' + 27: 1, # 'ш' + 24: 0, # 'щ' + 17: 0, # 'ÑŠ' + 52: 0, # 'ÑŒ' + 42: 0, # 'ÑŽ' + 16: 1, # 'Ñ' + 58: 0, # 'Ñ”' + 62: 0, # 'â„–' + }, + 32: { # 'Б' + 63: 0, # 'e' + 45: 0, # '\xad' + 31: 2, # 'Ð' + 32: 2, # 'Б' + 35: 1, # 'Ð’' + 43: 1, # 'Г' + 37: 2, # 'Д' + 44: 1, # 'Е' + 55: 1, # 'Ж' + 47: 2, # 'З' + 40: 1, # 'И' + 59: 0, # 'Й' + 33: 1, # 'К' + 46: 1, # 'Л' + 38: 1, # 'Ðœ' + 36: 2, # 'Ð' + 41: 2, # 'О' + 30: 1, # 'П' + 39: 1, # 'Р' + 28: 2, # 'С' + 34: 2, # 'Т' + 51: 1, # 'У' + 48: 2, # 'Ф' + 49: 1, # 'Ð¥' + 53: 1, # 'Ц' + 50: 1, # 'Ч' + 54: 0, # 'Ш' + 57: 1, # 'Щ' + 61: 2, # 'Ъ' + 60: 1, # 'Ю' + 56: 1, # 'Я' + 1: 3, # 'а' + 18: 0, # 'б' + 9: 0, # 'в' + 20: 0, # 'г' + 11: 1, # 'д' + 3: 3, # 'е' + 23: 0, # 'ж' + 15: 0, # 'з' + 2: 2, # 'и' + 26: 0, # 'й' + 12: 0, # 'к' + 10: 2, # 'л' + 14: 0, # 'м' + 6: 0, # 'н' + 4: 3, # 'о' + 13: 0, # 'п' + 7: 2, # 'Ñ€' + 8: 1, # 'Ñ' + 5: 0, # 'Ñ‚' + 19: 2, # 'у' + 29: 0, # 'Ñ„' + 25: 1, # 'Ñ…' + 22: 0, # 'ц' + 21: 0, # 'ч' + 27: 0, # 'ш' + 24: 0, # 'щ' + 17: 3, # 'ÑŠ' + 52: 1, # 'ÑŒ' + 42: 1, # 'ÑŽ' + 16: 2, # 'Ñ' + 58: 0, # 'Ñ”' + 62: 0, # 'â„–' + }, + 35: { # 'Ð’' + 63: 0, # 'e' + 45: 0, # '\xad' + 31: 2, # 'Ð' + 32: 1, # 'Б' + 35: 1, # 'Ð’' + 43: 0, # 'Г' + 37: 1, # 'Д' + 44: 2, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 2, # 'И' + 59: 0, # 'Й' + 33: 1, # 'К' + 46: 1, # 'Л' + 38: 1, # 'Ðœ' + 36: 1, # 'Ð' + 41: 1, # 'О' + 30: 1, # 'П' + 39: 2, # 'Р' + 28: 2, # 'С' + 34: 1, # 'Т' + 51: 1, # 'У' + 48: 2, # 'Ф' + 49: 0, # 'Ð¥' + 53: 1, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 1, # 'Ъ' + 60: 1, # 'Ю' + 56: 2, # 'Я' + 1: 3, # 'а' + 18: 1, # 'б' + 9: 0, # 'в' + 20: 0, # 'г' + 11: 1, # 'д' + 3: 3, # 'е' + 23: 1, # 'ж' + 15: 2, # 'з' + 2: 3, # 'и' + 26: 0, # 'й' + 12: 1, # 'к' + 10: 2, # 'л' + 14: 1, # 'м' + 6: 2, # 'н' + 4: 2, # 'о' + 13: 1, # 'п' + 7: 2, # 'Ñ€' + 8: 2, # 'Ñ' + 5: 2, # 'Ñ‚' + 19: 1, # 'у' + 29: 0, # 'Ñ„' + 25: 1, # 'Ñ…' + 22: 0, # 'ц' + 21: 2, # 'ч' + 27: 0, # 'ш' + 24: 0, # 'щ' + 17: 2, # 'ÑŠ' + 52: 1, # 'ÑŒ' + 42: 1, # 'ÑŽ' + 16: 1, # 'Ñ' + 58: 0, # 'Ñ”' + 62: 0, # 'â„–' + }, + 43: { # 'Г' + 63: 0, # 'e' + 45: 0, # '\xad' + 31: 2, # 'Ð' + 32: 1, # 'Б' + 35: 0, # 'Ð’' + 43: 0, # 'Г' + 37: 1, # 'Д' + 44: 2, # 'Е' + 55: 0, # 'Ж' + 47: 1, # 'З' + 40: 1, # 'И' + 59: 0, # 'Й' + 33: 1, # 'К' + 46: 1, # 'Л' + 38: 0, # 'Ðœ' + 36: 1, # 'Ð' + 41: 1, # 'О' + 30: 0, # 'П' + 39: 1, # 'Р' + 28: 1, # 'С' + 34: 0, # 'Т' + 51: 1, # 'У' + 48: 1, # 'Ф' + 49: 0, # 'Ð¥' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 1, # 'Щ' + 61: 1, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 2, # 'а' + 18: 1, # 'б' + 9: 1, # 'в' + 20: 0, # 'г' + 11: 1, # 'д' + 3: 3, # 'е' + 23: 1, # 'ж' + 15: 0, # 'з' + 2: 2, # 'и' + 26: 0, # 'й' + 12: 1, # 'к' + 10: 2, # 'л' + 14: 1, # 'м' + 6: 1, # 'н' + 4: 2, # 'о' + 13: 0, # 'п' + 7: 2, # 'Ñ€' + 8: 0, # 'Ñ' + 5: 0, # 'Ñ‚' + 19: 2, # 'у' + 29: 0, # 'Ñ„' + 25: 0, # 'Ñ…' + 22: 0, # 'ц' + 21: 0, # 'ч' + 27: 0, # 'ш' + 24: 1, # 'щ' + 17: 2, # 'ÑŠ' + 52: 1, # 'ÑŒ' + 42: 1, # 'ÑŽ' + 16: 1, # 'Ñ' + 58: 0, # 'Ñ”' + 62: 0, # 'â„–' + }, + 37: { # 'Д' + 63: 0, # 'e' + 45: 0, # '\xad' + 31: 2, # 'Ð' + 32: 1, # 'Б' + 35: 2, # 'Ð’' + 43: 1, # 'Г' + 37: 2, # 'Д' + 44: 2, # 'Е' + 55: 2, # 'Ж' + 47: 1, # 'З' + 40: 2, # 'И' + 59: 0, # 'Й' + 33: 1, # 'К' + 46: 1, # 'Л' + 38: 1, # 'Ðœ' + 36: 1, # 'Ð' + 41: 2, # 'О' + 30: 2, # 'П' + 39: 1, # 'Р' + 28: 2, # 'С' + 34: 1, # 'Т' + 51: 1, # 'У' + 48: 1, # 'Ф' + 49: 0, # 'Ð¥' + 53: 1, # 'Ц' + 50: 1, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 1, # 'Ъ' + 60: 1, # 'Ю' + 56: 1, # 'Я' + 1: 3, # 'а' + 18: 0, # 'б' + 9: 2, # 'в' + 20: 0, # 'г' + 11: 0, # 'д' + 3: 3, # 'е' + 23: 3, # 'ж' + 15: 1, # 'з' + 2: 3, # 'и' + 26: 0, # 'й' + 12: 0, # 'к' + 10: 1, # 'л' + 14: 1, # 'м' + 6: 2, # 'н' + 4: 3, # 'о' + 13: 0, # 'п' + 7: 2, # 'Ñ€' + 8: 0, # 'Ñ' + 5: 0, # 'Ñ‚' + 19: 2, # 'у' + 29: 0, # 'Ñ„' + 25: 0, # 'Ñ…' + 22: 0, # 'ц' + 21: 0, # 'ч' + 27: 0, # 'ш' + 24: 0, # 'щ' + 17: 2, # 'ÑŠ' + 52: 1, # 'ÑŒ' + 42: 2, # 'ÑŽ' + 16: 1, # 'Ñ' + 58: 0, # 'Ñ”' + 62: 0, # 'â„–' + }, + 44: { # 'Е' + 63: 0, # 'e' + 45: 0, # '\xad' + 31: 1, # 'Ð' + 32: 1, # 'Б' + 35: 2, # 'Ð’' + 43: 1, # 'Г' + 37: 1, # 'Д' + 44: 1, # 'Е' + 55: 1, # 'Ж' + 47: 1, # 'З' + 40: 1, # 'И' + 59: 1, # 'Й' + 33: 2, # 'К' + 46: 2, # 'Л' + 38: 1, # 'Ðœ' + 36: 2, # 'Ð' + 41: 2, # 'О' + 30: 1, # 'П' + 39: 2, # 'Р' + 28: 2, # 'С' + 34: 2, # 'Т' + 51: 1, # 'У' + 48: 2, # 'Ф' + 49: 1, # 'Ð¥' + 53: 2, # 'Ц' + 50: 1, # 'Ч' + 54: 1, # 'Ш' + 57: 1, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 1, # 'Я' + 1: 0, # 'а' + 18: 1, # 'б' + 9: 2, # 'в' + 20: 1, # 'г' + 11: 2, # 'д' + 3: 0, # 'е' + 23: 1, # 'ж' + 15: 1, # 'з' + 2: 0, # 'и' + 26: 1, # 'й' + 12: 2, # 'к' + 10: 2, # 'л' + 14: 2, # 'м' + 6: 2, # 'н' + 4: 0, # 'о' + 13: 1, # 'п' + 7: 2, # 'Ñ€' + 8: 2, # 'Ñ' + 5: 1, # 'Ñ‚' + 19: 1, # 'у' + 29: 1, # 'Ñ„' + 25: 1, # 'Ñ…' + 22: 0, # 'ц' + 21: 1, # 'ч' + 27: 1, # 'ш' + 24: 1, # 'щ' + 17: 1, # 'ÑŠ' + 52: 0, # 'ÑŒ' + 42: 1, # 'ÑŽ' + 16: 1, # 'Ñ' + 58: 0, # 'Ñ”' + 62: 0, # 'â„–' + }, + 55: { # 'Ж' + 63: 0, # 'e' + 45: 0, # '\xad' + 31: 1, # 'Ð' + 32: 0, # 'Б' + 35: 1, # 'Ð’' + 43: 0, # 'Г' + 37: 1, # 'Д' + 44: 1, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 1, # 'И' + 59: 0, # 'Й' + 33: 1, # 'К' + 46: 0, # 'Л' + 38: 0, # 'Ðœ' + 36: 1, # 'Ð' + 41: 1, # 'О' + 30: 0, # 'П' + 39: 0, # 'Р' + 28: 0, # 'С' + 34: 0, # 'Т' + 51: 1, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Ð¥' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 2, # 'а' + 18: 0, # 'б' + 9: 0, # 'в' + 20: 0, # 'г' + 11: 1, # 'д' + 3: 2, # 'е' + 23: 0, # 'ж' + 15: 0, # 'з' + 2: 2, # 'и' + 26: 0, # 'й' + 12: 0, # 'к' + 10: 0, # 'л' + 14: 0, # 'м' + 6: 0, # 'н' + 4: 2, # 'о' + 13: 1, # 'п' + 7: 1, # 'Ñ€' + 8: 0, # 'Ñ' + 5: 0, # 'Ñ‚' + 19: 1, # 'у' + 29: 0, # 'Ñ„' + 25: 0, # 'Ñ…' + 22: 0, # 'ц' + 21: 0, # 'ч' + 27: 0, # 'ш' + 24: 0, # 'щ' + 17: 1, # 'ÑŠ' + 52: 1, # 'ÑŒ' + 42: 1, # 'ÑŽ' + 16: 0, # 'Ñ' + 58: 0, # 'Ñ”' + 62: 0, # 'â„–' + }, + 47: { # 'З' + 63: 0, # 'e' + 45: 0, # '\xad' + 31: 2, # 'Ð' + 32: 1, # 'Б' + 35: 1, # 'Ð’' + 43: 1, # 'Г' + 37: 1, # 'Д' + 44: 1, # 'Е' + 55: 0, # 'Ж' + 47: 1, # 'З' + 40: 1, # 'И' + 59: 0, # 'Й' + 33: 1, # 'К' + 46: 1, # 'Л' + 38: 1, # 'Ðœ' + 36: 2, # 'Ð' + 41: 1, # 'О' + 30: 1, # 'П' + 39: 1, # 'Р' + 28: 1, # 'С' + 34: 1, # 'Т' + 51: 1, # 'У' + 48: 0, # 'Ф' + 49: 1, # 'Ð¥' + 53: 1, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 1, # 'Ъ' + 60: 0, # 'Ю' + 56: 1, # 'Я' + 1: 3, # 'а' + 18: 1, # 'б' + 9: 2, # 'в' + 20: 1, # 'г' + 11: 2, # 'д' + 3: 2, # 'е' + 23: 0, # 'ж' + 15: 0, # 'з' + 2: 1, # 'и' + 26: 0, # 'й' + 12: 0, # 'к' + 10: 2, # 'л' + 14: 1, # 'м' + 6: 1, # 'н' + 4: 1, # 'о' + 13: 0, # 'п' + 7: 1, # 'Ñ€' + 8: 0, # 'Ñ' + 5: 0, # 'Ñ‚' + 19: 1, # 'у' + 29: 0, # 'Ñ„' + 25: 0, # 'Ñ…' + 22: 0, # 'ц' + 21: 0, # 'ч' + 27: 0, # 'ш' + 24: 0, # 'щ' + 17: 1, # 'ÑŠ' + 52: 0, # 'ÑŒ' + 42: 1, # 'ÑŽ' + 16: 0, # 'Ñ' + 58: 0, # 'Ñ”' + 62: 0, # 'â„–' + }, + 40: { # 'И' + 63: 0, # 'e' + 45: 1, # '\xad' + 31: 1, # 'Ð' + 32: 1, # 'Б' + 35: 1, # 'Ð’' + 43: 1, # 'Г' + 37: 1, # 'Д' + 44: 2, # 'Е' + 55: 1, # 'Ж' + 47: 2, # 'З' + 40: 1, # 'И' + 59: 1, # 'Й' + 33: 2, # 'К' + 46: 2, # 'Л' + 38: 2, # 'Ðœ' + 36: 2, # 'Ð' + 41: 1, # 'О' + 30: 1, # 'П' + 39: 2, # 'Р' + 28: 2, # 'С' + 34: 2, # 'Т' + 51: 0, # 'У' + 48: 1, # 'Ф' + 49: 1, # 'Ð¥' + 53: 1, # 'Ц' + 50: 1, # 'Ч' + 54: 1, # 'Ш' + 57: 1, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 2, # 'Я' + 1: 1, # 'а' + 18: 1, # 'б' + 9: 3, # 'в' + 20: 2, # 'г' + 11: 1, # 'д' + 3: 1, # 'е' + 23: 0, # 'ж' + 15: 3, # 'з' + 2: 0, # 'и' + 26: 1, # 'й' + 12: 1, # 'к' + 10: 2, # 'л' + 14: 2, # 'м' + 6: 2, # 'н' + 4: 0, # 'о' + 13: 1, # 'п' + 7: 2, # 'Ñ€' + 8: 2, # 'Ñ' + 5: 2, # 'Ñ‚' + 19: 0, # 'у' + 29: 1, # 'Ñ„' + 25: 1, # 'Ñ…' + 22: 1, # 'ц' + 21: 1, # 'ч' + 27: 1, # 'ш' + 24: 1, # 'щ' + 17: 0, # 'ÑŠ' + 52: 0, # 'ÑŒ' + 42: 0, # 'ÑŽ' + 16: 0, # 'Ñ' + 58: 0, # 'Ñ”' + 62: 0, # 'â„–' + }, + 59: { # 'Й' + 63: 0, # 'e' + 45: 0, # '\xad' + 31: 0, # 'Ð' + 32: 0, # 'Б' + 35: 0, # 'Ð’' + 43: 0, # 'Г' + 37: 1, # 'Д' + 44: 1, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 0, # 'И' + 59: 0, # 'Й' + 33: 1, # 'К' + 46: 1, # 'Л' + 38: 1, # 'Ðœ' + 36: 1, # 'Ð' + 41: 1, # 'О' + 30: 0, # 'П' + 39: 0, # 'Р' + 28: 1, # 'С' + 34: 1, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Ð¥' + 53: 0, # 'Ц' + 50: 1, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 1, # 'Я' + 1: 0, # 'а' + 18: 0, # 'б' + 9: 0, # 'в' + 20: 0, # 'г' + 11: 0, # 'д' + 3: 1, # 'е' + 23: 0, # 'ж' + 15: 0, # 'з' + 2: 0, # 'и' + 26: 0, # 'й' + 12: 0, # 'к' + 10: 0, # 'л' + 14: 0, # 'м' + 6: 0, # 'н' + 4: 2, # 'о' + 13: 0, # 'п' + 7: 0, # 'Ñ€' + 8: 0, # 'Ñ' + 5: 0, # 'Ñ‚' + 19: 0, # 'у' + 29: 0, # 'Ñ„' + 25: 0, # 'Ñ…' + 22: 0, # 'ц' + 21: 0, # 'ч' + 27: 0, # 'ш' + 24: 0, # 'щ' + 17: 1, # 'ÑŠ' + 52: 0, # 'ÑŒ' + 42: 0, # 'ÑŽ' + 16: 0, # 'Ñ' + 58: 0, # 'Ñ”' + 62: 0, # 'â„–' + }, + 33: { # 'К' + 63: 0, # 'e' + 45: 1, # '\xad' + 31: 2, # 'Ð' + 32: 1, # 'Б' + 35: 1, # 'Ð’' + 43: 1, # 'Г' + 37: 1, # 'Д' + 44: 1, # 'Е' + 55: 0, # 'Ж' + 47: 1, # 'З' + 40: 2, # 'И' + 59: 0, # 'Й' + 33: 1, # 'К' + 46: 1, # 'Л' + 38: 0, # 'Ðœ' + 36: 2, # 'Ð' + 41: 2, # 'О' + 30: 2, # 'П' + 39: 1, # 'Р' + 28: 2, # 'С' + 34: 1, # 'Т' + 51: 1, # 'У' + 48: 1, # 'Ф' + 49: 1, # 'Ð¥' + 53: 1, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 1, # 'Ъ' + 60: 1, # 'Ю' + 56: 0, # 'Я' + 1: 3, # 'а' + 18: 0, # 'б' + 9: 1, # 'в' + 20: 0, # 'г' + 11: 0, # 'д' + 3: 2, # 'е' + 23: 1, # 'ж' + 15: 0, # 'з' + 2: 2, # 'и' + 26: 0, # 'й' + 12: 0, # 'к' + 10: 2, # 'л' + 14: 1, # 'м' + 6: 2, # 'н' + 4: 3, # 'о' + 13: 0, # 'п' + 7: 3, # 'Ñ€' + 8: 1, # 'Ñ' + 5: 0, # 'Ñ‚' + 19: 2, # 'у' + 29: 0, # 'Ñ„' + 25: 1, # 'Ñ…' + 22: 0, # 'ц' + 21: 0, # 'ч' + 27: 1, # 'ш' + 24: 0, # 'щ' + 17: 2, # 'ÑŠ' + 52: 1, # 'ÑŒ' + 42: 2, # 'ÑŽ' + 16: 0, # 'Ñ' + 58: 0, # 'Ñ”' + 62: 0, # 'â„–' + }, + 46: { # 'Л' + 63: 1, # 'e' + 45: 0, # '\xad' + 31: 2, # 'Ð' + 32: 1, # 'Б' + 35: 1, # 'Ð’' + 43: 2, # 'Г' + 37: 1, # 'Д' + 44: 2, # 'Е' + 55: 0, # 'Ж' + 47: 1, # 'З' + 40: 2, # 'И' + 59: 0, # 'Й' + 33: 1, # 'К' + 46: 1, # 'Л' + 38: 0, # 'Ðœ' + 36: 1, # 'Ð' + 41: 2, # 'О' + 30: 1, # 'П' + 39: 0, # 'Р' + 28: 1, # 'С' + 34: 1, # 'Т' + 51: 1, # 'У' + 48: 0, # 'Ф' + 49: 1, # 'Ð¥' + 53: 1, # 'Ц' + 50: 1, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 1, # 'Ъ' + 60: 1, # 'Ю' + 56: 1, # 'Я' + 1: 2, # 'а' + 18: 0, # 'б' + 9: 1, # 'в' + 20: 0, # 'г' + 11: 0, # 'д' + 3: 3, # 'е' + 23: 0, # 'ж' + 15: 0, # 'з' + 2: 2, # 'и' + 26: 0, # 'й' + 12: 0, # 'к' + 10: 0, # 'л' + 14: 0, # 'м' + 6: 0, # 'н' + 4: 2, # 'о' + 13: 0, # 'п' + 7: 0, # 'Ñ€' + 8: 0, # 'Ñ' + 5: 0, # 'Ñ‚' + 19: 2, # 'у' + 29: 0, # 'Ñ„' + 25: 0, # 'Ñ…' + 22: 0, # 'ц' + 21: 0, # 'ч' + 27: 0, # 'ш' + 24: 0, # 'щ' + 17: 1, # 'ÑŠ' + 52: 1, # 'ÑŒ' + 42: 2, # 'ÑŽ' + 16: 1, # 'Ñ' + 58: 0, # 'Ñ”' + 62: 0, # 'â„–' + }, + 38: { # 'Ðœ' + 63: 0, # 'e' + 45: 0, # '\xad' + 31: 2, # 'Ð' + 32: 1, # 'Б' + 35: 2, # 'Ð’' + 43: 0, # 'Г' + 37: 1, # 'Д' + 44: 1, # 'Е' + 55: 0, # 'Ж' + 47: 1, # 'З' + 40: 2, # 'И' + 59: 0, # 'Й' + 33: 1, # 'К' + 46: 1, # 'Л' + 38: 1, # 'Ðœ' + 36: 1, # 'Ð' + 41: 2, # 'О' + 30: 1, # 'П' + 39: 1, # 'Р' + 28: 2, # 'С' + 34: 1, # 'Т' + 51: 1, # 'У' + 48: 1, # 'Ф' + 49: 0, # 'Ð¥' + 53: 1, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 1, # 'Ъ' + 60: 0, # 'Ю' + 56: 1, # 'Я' + 1: 3, # 'а' + 18: 0, # 'б' + 9: 0, # 'в' + 20: 0, # 'г' + 11: 0, # 'д' + 3: 3, # 'е' + 23: 0, # 'ж' + 15: 0, # 'з' + 2: 3, # 'и' + 26: 0, # 'й' + 12: 0, # 'к' + 10: 2, # 'л' + 14: 0, # 'м' + 6: 2, # 'н' + 4: 3, # 'о' + 13: 0, # 'п' + 7: 1, # 'Ñ€' + 8: 0, # 'Ñ' + 5: 0, # 'Ñ‚' + 19: 2, # 'у' + 29: 0, # 'Ñ„' + 25: 0, # 'Ñ…' + 22: 0, # 'ц' + 21: 0, # 'ч' + 27: 0, # 'ш' + 24: 0, # 'щ' + 17: 2, # 'ÑŠ' + 52: 1, # 'ÑŒ' + 42: 2, # 'ÑŽ' + 16: 1, # 'Ñ' + 58: 0, # 'Ñ”' + 62: 0, # 'â„–' + }, + 36: { # 'Ð' + 63: 0, # 'e' + 45: 0, # '\xad' + 31: 2, # 'Ð' + 32: 2, # 'Б' + 35: 1, # 'Ð’' + 43: 1, # 'Г' + 37: 2, # 'Д' + 44: 2, # 'Е' + 55: 1, # 'Ж' + 47: 1, # 'З' + 40: 2, # 'И' + 59: 1, # 'Й' + 33: 2, # 'К' + 46: 1, # 'Л' + 38: 1, # 'Ðœ' + 36: 1, # 'Ð' + 41: 2, # 'О' + 30: 1, # 'П' + 39: 1, # 'Р' + 28: 2, # 'С' + 34: 2, # 'Т' + 51: 1, # 'У' + 48: 1, # 'Ф' + 49: 1, # 'Ð¥' + 53: 1, # 'Ц' + 50: 1, # 'Ч' + 54: 1, # 'Ш' + 57: 0, # 'Щ' + 61: 1, # 'Ъ' + 60: 1, # 'Ю' + 56: 1, # 'Я' + 1: 3, # 'а' + 18: 0, # 'б' + 9: 0, # 'в' + 20: 1, # 'г' + 11: 0, # 'д' + 3: 3, # 'е' + 23: 0, # 'ж' + 15: 0, # 'з' + 2: 3, # 'и' + 26: 0, # 'й' + 12: 0, # 'к' + 10: 0, # 'л' + 14: 0, # 'м' + 6: 0, # 'н' + 4: 3, # 'о' + 13: 0, # 'п' + 7: 0, # 'Ñ€' + 8: 0, # 'Ñ' + 5: 1, # 'Ñ‚' + 19: 1, # 'у' + 29: 0, # 'Ñ„' + 25: 0, # 'Ñ…' + 22: 0, # 'ц' + 21: 0, # 'ч' + 27: 1, # 'ш' + 24: 0, # 'щ' + 17: 0, # 'ÑŠ' + 52: 0, # 'ÑŒ' + 42: 2, # 'ÑŽ' + 16: 2, # 'Ñ' + 58: 0, # 'Ñ”' + 62: 0, # 'â„–' + }, + 41: { # 'О' + 63: 0, # 'e' + 45: 0, # '\xad' + 31: 1, # 'Ð' + 32: 1, # 'Б' + 35: 2, # 'Ð’' + 43: 1, # 'Г' + 37: 2, # 'Д' + 44: 1, # 'Е' + 55: 1, # 'Ж' + 47: 1, # 'З' + 40: 1, # 'И' + 59: 1, # 'Й' + 33: 2, # 'К' + 46: 2, # 'Л' + 38: 2, # 'Ðœ' + 36: 2, # 'Ð' + 41: 2, # 'О' + 30: 1, # 'П' + 39: 2, # 'Р' + 28: 2, # 'С' + 34: 2, # 'Т' + 51: 1, # 'У' + 48: 1, # 'Ф' + 49: 1, # 'Ð¥' + 53: 0, # 'Ц' + 50: 1, # 'Ч' + 54: 1, # 'Ш' + 57: 1, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 1, # 'Я' + 1: 1, # 'а' + 18: 2, # 'б' + 9: 2, # 'в' + 20: 2, # 'г' + 11: 1, # 'д' + 3: 1, # 'е' + 23: 1, # 'ж' + 15: 1, # 'з' + 2: 0, # 'и' + 26: 1, # 'й' + 12: 2, # 'к' + 10: 2, # 'л' + 14: 1, # 'м' + 6: 1, # 'н' + 4: 0, # 'о' + 13: 2, # 'п' + 7: 2, # 'Ñ€' + 8: 2, # 'Ñ' + 5: 3, # 'Ñ‚' + 19: 1, # 'у' + 29: 1, # 'Ñ„' + 25: 1, # 'Ñ…' + 22: 1, # 'ц' + 21: 2, # 'ч' + 27: 0, # 'ш' + 24: 2, # 'щ' + 17: 0, # 'ÑŠ' + 52: 0, # 'ÑŒ' + 42: 0, # 'ÑŽ' + 16: 1, # 'Ñ' + 58: 0, # 'Ñ”' + 62: 0, # 'â„–' + }, + 30: { # 'П' + 63: 0, # 'e' + 45: 1, # '\xad' + 31: 2, # 'Ð' + 32: 1, # 'Б' + 35: 1, # 'Ð’' + 43: 1, # 'Г' + 37: 1, # 'Д' + 44: 1, # 'Е' + 55: 0, # 'Ж' + 47: 1, # 'З' + 40: 2, # 'И' + 59: 0, # 'Й' + 33: 1, # 'К' + 46: 1, # 'Л' + 38: 1, # 'Ðœ' + 36: 1, # 'Ð' + 41: 2, # 'О' + 30: 2, # 'П' + 39: 2, # 'Р' + 28: 2, # 'С' + 34: 1, # 'Т' + 51: 2, # 'У' + 48: 1, # 'Ф' + 49: 0, # 'Ð¥' + 53: 1, # 'Ц' + 50: 1, # 'Ч' + 54: 1, # 'Ш' + 57: 0, # 'Щ' + 61: 1, # 'Ъ' + 60: 1, # 'Ю' + 56: 0, # 'Я' + 1: 3, # 'а' + 18: 0, # 'б' + 9: 0, # 'в' + 20: 0, # 'г' + 11: 2, # 'д' + 3: 3, # 'е' + 23: 0, # 'ж' + 15: 0, # 'з' + 2: 2, # 'и' + 26: 0, # 'й' + 12: 1, # 'к' + 10: 3, # 'л' + 14: 0, # 'м' + 6: 1, # 'н' + 4: 3, # 'о' + 13: 0, # 'п' + 7: 3, # 'Ñ€' + 8: 1, # 'Ñ' + 5: 1, # 'Ñ‚' + 19: 2, # 'у' + 29: 1, # 'Ñ„' + 25: 1, # 'Ñ…' + 22: 0, # 'ц' + 21: 1, # 'ч' + 27: 1, # 'ш' + 24: 0, # 'щ' + 17: 2, # 'ÑŠ' + 52: 1, # 'ÑŒ' + 42: 1, # 'ÑŽ' + 16: 1, # 'Ñ' + 58: 0, # 'Ñ”' + 62: 0, # 'â„–' + }, + 39: { # 'Р' + 63: 0, # 'e' + 45: 1, # '\xad' + 31: 2, # 'Ð' + 32: 1, # 'Б' + 35: 1, # 'Ð’' + 43: 2, # 'Г' + 37: 2, # 'Д' + 44: 2, # 'Е' + 55: 0, # 'Ж' + 47: 1, # 'З' + 40: 2, # 'И' + 59: 0, # 'Й' + 33: 1, # 'К' + 46: 0, # 'Л' + 38: 1, # 'Ðœ' + 36: 1, # 'Ð' + 41: 2, # 'О' + 30: 2, # 'П' + 39: 1, # 'Р' + 28: 1, # 'С' + 34: 1, # 'Т' + 51: 1, # 'У' + 48: 1, # 'Ф' + 49: 1, # 'Ð¥' + 53: 1, # 'Ц' + 50: 1, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 1, # 'Ъ' + 60: 1, # 'Ю' + 56: 1, # 'Я' + 1: 3, # 'а' + 18: 0, # 'б' + 9: 0, # 'в' + 20: 0, # 'г' + 11: 0, # 'д' + 3: 2, # 'е' + 23: 0, # 'ж' + 15: 0, # 'з' + 2: 2, # 'и' + 26: 0, # 'й' + 12: 0, # 'к' + 10: 0, # 'л' + 14: 0, # 'м' + 6: 1, # 'н' + 4: 3, # 'о' + 13: 0, # 'п' + 7: 0, # 'Ñ€' + 8: 1, # 'Ñ' + 5: 0, # 'Ñ‚' + 19: 3, # 'у' + 29: 0, # 'Ñ„' + 25: 0, # 'Ñ…' + 22: 0, # 'ц' + 21: 0, # 'ч' + 27: 0, # 'ш' + 24: 0, # 'щ' + 17: 1, # 'ÑŠ' + 52: 0, # 'ÑŒ' + 42: 1, # 'ÑŽ' + 16: 1, # 'Ñ' + 58: 0, # 'Ñ”' + 62: 0, # 'â„–' + }, + 28: { # 'С' + 63: 1, # 'e' + 45: 0, # '\xad' + 31: 3, # 'Ð' + 32: 2, # 'Б' + 35: 2, # 'Ð’' + 43: 1, # 'Г' + 37: 2, # 'Д' + 44: 2, # 'Е' + 55: 1, # 'Ж' + 47: 1, # 'З' + 40: 2, # 'И' + 59: 0, # 'Й' + 33: 2, # 'К' + 46: 1, # 'Л' + 38: 1, # 'Ðœ' + 36: 1, # 'Ð' + 41: 2, # 'О' + 30: 2, # 'П' + 39: 1, # 'Р' + 28: 2, # 'С' + 34: 2, # 'Т' + 51: 1, # 'У' + 48: 1, # 'Ф' + 49: 0, # 'Ð¥' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 1, # 'Ъ' + 60: 1, # 'Ю' + 56: 1, # 'Я' + 1: 3, # 'а' + 18: 1, # 'б' + 9: 2, # 'в' + 20: 1, # 'г' + 11: 1, # 'д' + 3: 3, # 'е' + 23: 0, # 'ж' + 15: 0, # 'з' + 2: 3, # 'и' + 26: 0, # 'й' + 12: 2, # 'к' + 10: 3, # 'л' + 14: 2, # 'м' + 6: 1, # 'н' + 4: 3, # 'о' + 13: 3, # 'п' + 7: 2, # 'Ñ€' + 8: 0, # 'Ñ' + 5: 3, # 'Ñ‚' + 19: 2, # 'у' + 29: 2, # 'Ñ„' + 25: 1, # 'Ñ…' + 22: 1, # 'ц' + 21: 1, # 'ч' + 27: 0, # 'ш' + 24: 0, # 'щ' + 17: 3, # 'ÑŠ' + 52: 1, # 'ÑŒ' + 42: 1, # 'ÑŽ' + 16: 1, # 'Ñ' + 58: 0, # 'Ñ”' + 62: 0, # 'â„–' + }, + 34: { # 'Т' + 63: 0, # 'e' + 45: 0, # '\xad' + 31: 2, # 'Ð' + 32: 2, # 'Б' + 35: 1, # 'Ð’' + 43: 0, # 'Г' + 37: 1, # 'Д' + 44: 2, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 2, # 'И' + 59: 0, # 'Й' + 33: 2, # 'К' + 46: 1, # 'Л' + 38: 1, # 'Ðœ' + 36: 1, # 'Ð' + 41: 2, # 'О' + 30: 1, # 'П' + 39: 2, # 'Р' + 28: 2, # 'С' + 34: 1, # 'Т' + 51: 1, # 'У' + 48: 1, # 'Ф' + 49: 0, # 'Ð¥' + 53: 1, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 1, # 'Ъ' + 60: 0, # 'Ю' + 56: 1, # 'Я' + 1: 3, # 'а' + 18: 1, # 'б' + 9: 1, # 'в' + 20: 0, # 'г' + 11: 0, # 'д' + 3: 3, # 'е' + 23: 0, # 'ж' + 15: 0, # 'з' + 2: 2, # 'и' + 26: 0, # 'й' + 12: 1, # 'к' + 10: 1, # 'л' + 14: 0, # 'м' + 6: 0, # 'н' + 4: 3, # 'о' + 13: 0, # 'п' + 7: 3, # 'Ñ€' + 8: 0, # 'Ñ' + 5: 0, # 'Ñ‚' + 19: 2, # 'у' + 29: 0, # 'Ñ„' + 25: 0, # 'Ñ…' + 22: 0, # 'ц' + 21: 0, # 'ч' + 27: 0, # 'ш' + 24: 0, # 'щ' + 17: 2, # 'ÑŠ' + 52: 0, # 'ÑŒ' + 42: 1, # 'ÑŽ' + 16: 2, # 'Ñ' + 58: 0, # 'Ñ”' + 62: 0, # 'â„–' + }, + 51: { # 'У' + 63: 0, # 'e' + 45: 1, # '\xad' + 31: 1, # 'Ð' + 32: 1, # 'Б' + 35: 1, # 'Ð’' + 43: 1, # 'Г' + 37: 1, # 'Д' + 44: 2, # 'Е' + 55: 1, # 'Ж' + 47: 1, # 'З' + 40: 1, # 'И' + 59: 0, # 'Й' + 33: 1, # 'К' + 46: 1, # 'Л' + 38: 1, # 'Ðœ' + 36: 1, # 'Ð' + 41: 0, # 'О' + 30: 1, # 'П' + 39: 1, # 'Р' + 28: 1, # 'С' + 34: 2, # 'Т' + 51: 0, # 'У' + 48: 1, # 'Ф' + 49: 1, # 'Ð¥' + 53: 1, # 'Ц' + 50: 1, # 'Ч' + 54: 1, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 1, # 'а' + 18: 1, # 'б' + 9: 2, # 'в' + 20: 1, # 'г' + 11: 1, # 'д' + 3: 2, # 'е' + 23: 1, # 'ж' + 15: 1, # 'з' + 2: 2, # 'и' + 26: 1, # 'й' + 12: 2, # 'к' + 10: 1, # 'л' + 14: 1, # 'м' + 6: 2, # 'н' + 4: 2, # 'о' + 13: 1, # 'п' + 7: 1, # 'Ñ€' + 8: 2, # 'Ñ' + 5: 1, # 'Ñ‚' + 19: 1, # 'у' + 29: 0, # 'Ñ„' + 25: 1, # 'Ñ…' + 22: 0, # 'ц' + 21: 2, # 'ч' + 27: 1, # 'ш' + 24: 0, # 'щ' + 17: 1, # 'ÑŠ' + 52: 0, # 'ÑŒ' + 42: 0, # 'ÑŽ' + 16: 0, # 'Ñ' + 58: 0, # 'Ñ”' + 62: 0, # 'â„–' + }, + 48: { # 'Ф' + 63: 0, # 'e' + 45: 0, # '\xad' + 31: 2, # 'Ð' + 32: 1, # 'Б' + 35: 1, # 'Ð’' + 43: 0, # 'Г' + 37: 0, # 'Д' + 44: 1, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 2, # 'И' + 59: 0, # 'Й' + 33: 1, # 'К' + 46: 1, # 'Л' + 38: 0, # 'Ðœ' + 36: 1, # 'Ð' + 41: 1, # 'О' + 30: 2, # 'П' + 39: 1, # 'Р' + 28: 2, # 'С' + 34: 1, # 'Т' + 51: 1, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Ð¥' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 2, # 'а' + 18: 0, # 'б' + 9: 0, # 'в' + 20: 0, # 'г' + 11: 0, # 'д' + 3: 2, # 'е' + 23: 0, # 'ж' + 15: 0, # 'з' + 2: 2, # 'и' + 26: 0, # 'й' + 12: 0, # 'к' + 10: 2, # 'л' + 14: 0, # 'м' + 6: 0, # 'н' + 4: 2, # 'о' + 13: 0, # 'п' + 7: 2, # 'Ñ€' + 8: 0, # 'Ñ' + 5: 0, # 'Ñ‚' + 19: 1, # 'у' + 29: 0, # 'Ñ„' + 25: 0, # 'Ñ…' + 22: 0, # 'ц' + 21: 0, # 'ч' + 27: 0, # 'ш' + 24: 0, # 'щ' + 17: 1, # 'ÑŠ' + 52: 1, # 'ÑŒ' + 42: 1, # 'ÑŽ' + 16: 0, # 'Ñ' + 58: 0, # 'Ñ”' + 62: 0, # 'â„–' + }, + 49: { # 'Ð¥' + 63: 0, # 'e' + 45: 0, # '\xad' + 31: 1, # 'Ð' + 32: 0, # 'Б' + 35: 1, # 'Ð’' + 43: 1, # 'Г' + 37: 1, # 'Д' + 44: 1, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 1, # 'И' + 59: 0, # 'Й' + 33: 0, # 'К' + 46: 1, # 'Л' + 38: 1, # 'Ðœ' + 36: 1, # 'Ð' + 41: 1, # 'О' + 30: 1, # 'П' + 39: 1, # 'Р' + 28: 0, # 'С' + 34: 0, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 1, # 'Ð¥' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 2, # 'а' + 18: 0, # 'б' + 9: 1, # 'в' + 20: 0, # 'г' + 11: 0, # 'д' + 3: 2, # 'е' + 23: 0, # 'ж' + 15: 0, # 'з' + 2: 2, # 'и' + 26: 0, # 'й' + 12: 0, # 'к' + 10: 1, # 'л' + 14: 1, # 'м' + 6: 0, # 'н' + 4: 2, # 'о' + 13: 0, # 'п' + 7: 2, # 'Ñ€' + 8: 0, # 'Ñ' + 5: 0, # 'Ñ‚' + 19: 2, # 'у' + 29: 0, # 'Ñ„' + 25: 0, # 'Ñ…' + 22: 0, # 'ц' + 21: 0, # 'ч' + 27: 0, # 'ш' + 24: 0, # 'щ' + 17: 2, # 'ÑŠ' + 52: 1, # 'ÑŒ' + 42: 1, # 'ÑŽ' + 16: 0, # 'Ñ' + 58: 0, # 'Ñ”' + 62: 0, # 'â„–' + }, + 53: { # 'Ц' + 63: 0, # 'e' + 45: 0, # '\xad' + 31: 1, # 'Ð' + 32: 0, # 'Б' + 35: 1, # 'Ð’' + 43: 0, # 'Г' + 37: 0, # 'Д' + 44: 1, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 2, # 'И' + 59: 0, # 'Й' + 33: 2, # 'К' + 46: 1, # 'Л' + 38: 1, # 'Ðœ' + 36: 0, # 'Ð' + 41: 0, # 'О' + 30: 0, # 'П' + 39: 1, # 'Р' + 28: 2, # 'С' + 34: 0, # 'Т' + 51: 1, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Ð¥' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 2, # 'а' + 18: 0, # 'б' + 9: 2, # 'в' + 20: 0, # 'г' + 11: 0, # 'д' + 3: 2, # 'е' + 23: 0, # 'ж' + 15: 1, # 'з' + 2: 2, # 'и' + 26: 0, # 'й' + 12: 0, # 'к' + 10: 0, # 'л' + 14: 0, # 'м' + 6: 0, # 'н' + 4: 1, # 'о' + 13: 0, # 'п' + 7: 1, # 'Ñ€' + 8: 0, # 'Ñ' + 5: 0, # 'Ñ‚' + 19: 1, # 'у' + 29: 0, # 'Ñ„' + 25: 0, # 'Ñ…' + 22: 0, # 'ц' + 21: 0, # 'ч' + 27: 0, # 'ш' + 24: 0, # 'щ' + 17: 1, # 'ÑŠ' + 52: 0, # 'ÑŒ' + 42: 1, # 'ÑŽ' + 16: 1, # 'Ñ' + 58: 0, # 'Ñ”' + 62: 0, # 'â„–' + }, + 50: { # 'Ч' + 63: 0, # 'e' + 45: 0, # '\xad' + 31: 2, # 'Ð' + 32: 1, # 'Б' + 35: 0, # 'Ð’' + 43: 0, # 'Г' + 37: 0, # 'Д' + 44: 1, # 'Е' + 55: 0, # 'Ж' + 47: 1, # 'З' + 40: 1, # 'И' + 59: 0, # 'Й' + 33: 1, # 'К' + 46: 1, # 'Л' + 38: 0, # 'Ðœ' + 36: 1, # 'Ð' + 41: 1, # 'О' + 30: 0, # 'П' + 39: 0, # 'Р' + 28: 0, # 'С' + 34: 0, # 'Т' + 51: 1, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Ð¥' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 2, # 'а' + 18: 0, # 'б' + 9: 0, # 'в' + 20: 0, # 'г' + 11: 0, # 'д' + 3: 3, # 'е' + 23: 1, # 'ж' + 15: 0, # 'з' + 2: 2, # 'и' + 26: 0, # 'й' + 12: 0, # 'к' + 10: 1, # 'л' + 14: 0, # 'м' + 6: 0, # 'н' + 4: 2, # 'о' + 13: 0, # 'п' + 7: 1, # 'Ñ€' + 8: 0, # 'Ñ' + 5: 0, # 'Ñ‚' + 19: 2, # 'у' + 29: 0, # 'Ñ„' + 25: 0, # 'Ñ…' + 22: 0, # 'ц' + 21: 0, # 'ч' + 27: 0, # 'ш' + 24: 0, # 'щ' + 17: 1, # 'ÑŠ' + 52: 1, # 'ÑŒ' + 42: 0, # 'ÑŽ' + 16: 0, # 'Ñ' + 58: 0, # 'Ñ”' + 62: 0, # 'â„–' + }, + 54: { # 'Ш' + 63: 0, # 'e' + 45: 0, # '\xad' + 31: 1, # 'Ð' + 32: 0, # 'Б' + 35: 0, # 'Ð’' + 43: 0, # 'Г' + 37: 0, # 'Д' + 44: 1, # 'Е' + 55: 0, # 'Ж' + 47: 1, # 'З' + 40: 1, # 'И' + 59: 0, # 'Й' + 33: 1, # 'К' + 46: 0, # 'Л' + 38: 0, # 'Ðœ' + 36: 1, # 'Ð' + 41: 1, # 'О' + 30: 0, # 'П' + 39: 0, # 'Р' + 28: 0, # 'С' + 34: 0, # 'Т' + 51: 1, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Ð¥' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 2, # 'а' + 18: 0, # 'б' + 9: 2, # 'в' + 20: 0, # 'г' + 11: 0, # 'д' + 3: 2, # 'е' + 23: 0, # 'ж' + 15: 0, # 'з' + 2: 2, # 'и' + 26: 0, # 'й' + 12: 1, # 'к' + 10: 1, # 'л' + 14: 1, # 'м' + 6: 1, # 'н' + 4: 2, # 'о' + 13: 1, # 'п' + 7: 1, # 'Ñ€' + 8: 0, # 'Ñ' + 5: 0, # 'Ñ‚' + 19: 2, # 'у' + 29: 0, # 'Ñ„' + 25: 0, # 'Ñ…' + 22: 0, # 'ц' + 21: 1, # 'ч' + 27: 0, # 'ш' + 24: 0, # 'щ' + 17: 1, # 'ÑŠ' + 52: 1, # 'ÑŒ' + 42: 0, # 'ÑŽ' + 16: 0, # 'Ñ' + 58: 0, # 'Ñ”' + 62: 0, # 'â„–' + }, + 57: { # 'Щ' + 63: 0, # 'e' + 45: 0, # '\xad' + 31: 1, # 'Ð' + 32: 0, # 'Б' + 35: 0, # 'Ð’' + 43: 0, # 'Г' + 37: 0, # 'Д' + 44: 1, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 1, # 'И' + 59: 0, # 'Й' + 33: 0, # 'К' + 46: 0, # 'Л' + 38: 0, # 'Ðœ' + 36: 0, # 'Ð' + 41: 1, # 'О' + 30: 0, # 'П' + 39: 0, # 'Р' + 28: 0, # 'С' + 34: 0, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Ð¥' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 2, # 'а' + 18: 0, # 'б' + 9: 0, # 'в' + 20: 0, # 'г' + 11: 0, # 'д' + 3: 2, # 'е' + 23: 0, # 'ж' + 15: 0, # 'з' + 2: 1, # 'и' + 26: 0, # 'й' + 12: 0, # 'к' + 10: 0, # 'л' + 14: 0, # 'м' + 6: 0, # 'н' + 4: 1, # 'о' + 13: 0, # 'п' + 7: 1, # 'Ñ€' + 8: 0, # 'Ñ' + 5: 0, # 'Ñ‚' + 19: 1, # 'у' + 29: 0, # 'Ñ„' + 25: 0, # 'Ñ…' + 22: 0, # 'ц' + 21: 0, # 'ч' + 27: 0, # 'ш' + 24: 0, # 'щ' + 17: 1, # 'ÑŠ' + 52: 0, # 'ÑŒ' + 42: 0, # 'ÑŽ' + 16: 1, # 'Ñ' + 58: 0, # 'Ñ”' + 62: 0, # 'â„–' + }, + 61: { # 'Ъ' + 63: 0, # 'e' + 45: 0, # '\xad' + 31: 0, # 'Ð' + 32: 1, # 'Б' + 35: 1, # 'Ð’' + 43: 0, # 'Г' + 37: 1, # 'Д' + 44: 0, # 'Е' + 55: 1, # 'Ж' + 47: 1, # 'З' + 40: 0, # 'И' + 59: 0, # 'Й' + 33: 1, # 'К' + 46: 2, # 'Л' + 38: 1, # 'Ðœ' + 36: 1, # 'Ð' + 41: 0, # 'О' + 30: 1, # 'П' + 39: 2, # 'Р' + 28: 1, # 'С' + 34: 1, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 1, # 'Ð¥' + 53: 1, # 'Ц' + 50: 1, # 'Ч' + 54: 1, # 'Ш' + 57: 1, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 0, # 'а' + 18: 0, # 'б' + 9: 0, # 'в' + 20: 0, # 'г' + 11: 0, # 'д' + 3: 0, # 'е' + 23: 0, # 'ж' + 15: 0, # 'з' + 2: 0, # 'и' + 26: 0, # 'й' + 12: 0, # 'к' + 10: 1, # 'л' + 14: 0, # 'м' + 6: 1, # 'н' + 4: 0, # 'о' + 13: 0, # 'п' + 7: 1, # 'Ñ€' + 8: 0, # 'Ñ' + 5: 0, # 'Ñ‚' + 19: 0, # 'у' + 29: 0, # 'Ñ„' + 25: 0, # 'Ñ…' + 22: 0, # 'ц' + 21: 0, # 'ч' + 27: 0, # 'ш' + 24: 0, # 'щ' + 17: 0, # 'ÑŠ' + 52: 0, # 'ÑŒ' + 42: 0, # 'ÑŽ' + 16: 0, # 'Ñ' + 58: 0, # 'Ñ”' + 62: 0, # 'â„–' + }, + 60: { # 'Ю' + 63: 0, # 'e' + 45: 0, # '\xad' + 31: 1, # 'Ð' + 32: 1, # 'Б' + 35: 0, # 'Ð’' + 43: 1, # 'Г' + 37: 1, # 'Д' + 44: 0, # 'Е' + 55: 1, # 'Ж' + 47: 0, # 'З' + 40: 0, # 'И' + 59: 0, # 'Й' + 33: 1, # 'К' + 46: 1, # 'Л' + 38: 0, # 'Ðœ' + 36: 1, # 'Ð' + 41: 0, # 'О' + 30: 0, # 'П' + 39: 1, # 'Р' + 28: 1, # 'С' + 34: 0, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Ð¥' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 0, # 'а' + 18: 1, # 'б' + 9: 1, # 'в' + 20: 2, # 'г' + 11: 1, # 'д' + 3: 0, # 'е' + 23: 2, # 'ж' + 15: 1, # 'з' + 2: 1, # 'и' + 26: 0, # 'й' + 12: 1, # 'к' + 10: 1, # 'л' + 14: 1, # 'м' + 6: 1, # 'н' + 4: 0, # 'о' + 13: 1, # 'п' + 7: 1, # 'Ñ€' + 8: 1, # 'Ñ' + 5: 1, # 'Ñ‚' + 19: 0, # 'у' + 29: 0, # 'Ñ„' + 25: 1, # 'Ñ…' + 22: 0, # 'ц' + 21: 0, # 'ч' + 27: 0, # 'ш' + 24: 0, # 'щ' + 17: 0, # 'ÑŠ' + 52: 0, # 'ÑŒ' + 42: 0, # 'ÑŽ' + 16: 0, # 'Ñ' + 58: 0, # 'Ñ”' + 62: 0, # 'â„–' + }, + 56: { # 'Я' + 63: 0, # 'e' + 45: 0, # '\xad' + 31: 0, # 'Ð' + 32: 1, # 'Б' + 35: 1, # 'Ð’' + 43: 1, # 'Г' + 37: 1, # 'Д' + 44: 0, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 0, # 'И' + 59: 0, # 'Й' + 33: 1, # 'К' + 46: 1, # 'Л' + 38: 1, # 'Ðœ' + 36: 1, # 'Ð' + 41: 0, # 'О' + 30: 0, # 'П' + 39: 0, # 'Р' + 28: 1, # 'С' + 34: 2, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Ð¥' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 0, # 'а' + 18: 1, # 'б' + 9: 1, # 'в' + 20: 1, # 'г' + 11: 1, # 'д' + 3: 0, # 'е' + 23: 0, # 'ж' + 15: 1, # 'з' + 2: 1, # 'и' + 26: 1, # 'й' + 12: 1, # 'к' + 10: 1, # 'л' + 14: 2, # 'м' + 6: 2, # 'н' + 4: 0, # 'о' + 13: 2, # 'п' + 7: 1, # 'Ñ€' + 8: 1, # 'Ñ' + 5: 1, # 'Ñ‚' + 19: 0, # 'у' + 29: 0, # 'Ñ„' + 25: 1, # 'Ñ…' + 22: 0, # 'ц' + 21: 0, # 'ч' + 27: 1, # 'ш' + 24: 0, # 'щ' + 17: 0, # 'ÑŠ' + 52: 0, # 'ÑŒ' + 42: 1, # 'ÑŽ' + 16: 0, # 'Ñ' + 58: 0, # 'Ñ”' + 62: 0, # 'â„–' + }, + 1: { # 'а' + 63: 1, # 'e' + 45: 1, # '\xad' + 31: 1, # 'Ð' + 32: 0, # 'Б' + 35: 0, # 'Ð’' + 43: 0, # 'Г' + 37: 0, # 'Д' + 44: 1, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 0, # 'И' + 59: 0, # 'Й' + 33: 0, # 'К' + 46: 0, # 'Л' + 38: 0, # 'Ðœ' + 36: 0, # 'Ð' + 41: 0, # 'О' + 30: 0, # 'П' + 39: 0, # 'Р' + 28: 0, # 'С' + 34: 0, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Ð¥' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 1, # 'а' + 18: 3, # 'б' + 9: 3, # 'в' + 20: 3, # 'г' + 11: 3, # 'д' + 3: 3, # 'е' + 23: 3, # 'ж' + 15: 3, # 'з' + 2: 3, # 'и' + 26: 3, # 'й' + 12: 3, # 'к' + 10: 3, # 'л' + 14: 3, # 'м' + 6: 3, # 'н' + 4: 2, # 'о' + 13: 3, # 'п' + 7: 3, # 'Ñ€' + 8: 3, # 'Ñ' + 5: 3, # 'Ñ‚' + 19: 3, # 'у' + 29: 3, # 'Ñ„' + 25: 3, # 'Ñ…' + 22: 3, # 'ц' + 21: 3, # 'ч' + 27: 3, # 'ш' + 24: 3, # 'щ' + 17: 0, # 'ÑŠ' + 52: 0, # 'ÑŒ' + 42: 1, # 'ÑŽ' + 16: 3, # 'Ñ' + 58: 0, # 'Ñ”' + 62: 0, # 'â„–' + }, + 18: { # 'б' + 63: 1, # 'e' + 45: 0, # '\xad' + 31: 0, # 'Ð' + 32: 0, # 'Б' + 35: 0, # 'Ð’' + 43: 0, # 'Г' + 37: 0, # 'Д' + 44: 0, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 0, # 'И' + 59: 0, # 'Й' + 33: 0, # 'К' + 46: 0, # 'Л' + 38: 0, # 'Ðœ' + 36: 0, # 'Ð' + 41: 0, # 'О' + 30: 0, # 'П' + 39: 0, # 'Р' + 28: 0, # 'С' + 34: 0, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Ð¥' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 3, # 'а' + 18: 0, # 'б' + 9: 3, # 'в' + 20: 1, # 'г' + 11: 2, # 'д' + 3: 3, # 'е' + 23: 1, # 'ж' + 15: 1, # 'з' + 2: 3, # 'и' + 26: 0, # 'й' + 12: 1, # 'к' + 10: 3, # 'л' + 14: 2, # 'м' + 6: 3, # 'н' + 4: 3, # 'о' + 13: 1, # 'п' + 7: 3, # 'Ñ€' + 8: 3, # 'Ñ' + 5: 0, # 'Ñ‚' + 19: 3, # 'у' + 29: 0, # 'Ñ„' + 25: 2, # 'Ñ…' + 22: 1, # 'ц' + 21: 1, # 'ч' + 27: 1, # 'ш' + 24: 3, # 'щ' + 17: 3, # 'ÑŠ' + 52: 1, # 'ÑŒ' + 42: 2, # 'ÑŽ' + 16: 3, # 'Ñ' + 58: 0, # 'Ñ”' + 62: 0, # 'â„–' + }, + 9: { # 'в' + 63: 1, # 'e' + 45: 1, # '\xad' + 31: 0, # 'Ð' + 32: 1, # 'Б' + 35: 0, # 'Ð’' + 43: 0, # 'Г' + 37: 0, # 'Д' + 44: 0, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 0, # 'И' + 59: 0, # 'Й' + 33: 0, # 'К' + 46: 0, # 'Л' + 38: 0, # 'Ðœ' + 36: 0, # 'Ð' + 41: 0, # 'О' + 30: 0, # 'П' + 39: 0, # 'Р' + 28: 0, # 'С' + 34: 0, # 'Т' + 51: 0, # 'У' + 48: 1, # 'Ф' + 49: 0, # 'Ð¥' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 3, # 'а' + 18: 1, # 'б' + 9: 0, # 'в' + 20: 2, # 'г' + 11: 3, # 'д' + 3: 3, # 'е' + 23: 1, # 'ж' + 15: 3, # 'з' + 2: 3, # 'и' + 26: 0, # 'й' + 12: 3, # 'к' + 10: 3, # 'л' + 14: 2, # 'м' + 6: 3, # 'н' + 4: 3, # 'о' + 13: 2, # 'п' + 7: 3, # 'Ñ€' + 8: 3, # 'Ñ' + 5: 3, # 'Ñ‚' + 19: 2, # 'у' + 29: 0, # 'Ñ„' + 25: 2, # 'Ñ…' + 22: 2, # 'ц' + 21: 3, # 'ч' + 27: 2, # 'ш' + 24: 1, # 'щ' + 17: 3, # 'ÑŠ' + 52: 1, # 'ÑŒ' + 42: 2, # 'ÑŽ' + 16: 3, # 'Ñ' + 58: 0, # 'Ñ”' + 62: 0, # 'â„–' + }, + 20: { # 'г' + 63: 0, # 'e' + 45: 0, # '\xad' + 31: 0, # 'Ð' + 32: 0, # 'Б' + 35: 0, # 'Ð’' + 43: 0, # 'Г' + 37: 0, # 'Д' + 44: 0, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 0, # 'И' + 59: 0, # 'Й' + 33: 0, # 'К' + 46: 0, # 'Л' + 38: 0, # 'Ðœ' + 36: 0, # 'Ð' + 41: 0, # 'О' + 30: 0, # 'П' + 39: 0, # 'Р' + 28: 0, # 'С' + 34: 0, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Ð¥' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 3, # 'а' + 18: 1, # 'б' + 9: 2, # 'в' + 20: 1, # 'г' + 11: 2, # 'д' + 3: 3, # 'е' + 23: 0, # 'ж' + 15: 1, # 'з' + 2: 3, # 'и' + 26: 0, # 'й' + 12: 1, # 'к' + 10: 3, # 'л' + 14: 1, # 'м' + 6: 3, # 'н' + 4: 3, # 'о' + 13: 1, # 'п' + 7: 3, # 'Ñ€' + 8: 2, # 'Ñ' + 5: 2, # 'Ñ‚' + 19: 3, # 'у' + 29: 1, # 'Ñ„' + 25: 1, # 'Ñ…' + 22: 0, # 'ц' + 21: 1, # 'ч' + 27: 0, # 'ш' + 24: 0, # 'щ' + 17: 3, # 'ÑŠ' + 52: 1, # 'ÑŒ' + 42: 1, # 'ÑŽ' + 16: 1, # 'Ñ' + 58: 0, # 'Ñ”' + 62: 0, # 'â„–' + }, + 11: { # 'д' + 63: 1, # 'e' + 45: 0, # '\xad' + 31: 0, # 'Ð' + 32: 0, # 'Б' + 35: 0, # 'Ð’' + 43: 0, # 'Г' + 37: 0, # 'Д' + 44: 0, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 0, # 'И' + 59: 0, # 'Й' + 33: 0, # 'К' + 46: 0, # 'Л' + 38: 0, # 'Ðœ' + 36: 0, # 'Ð' + 41: 0, # 'О' + 30: 0, # 'П' + 39: 0, # 'Р' + 28: 0, # 'С' + 34: 0, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Ð¥' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 3, # 'а' + 18: 2, # 'б' + 9: 3, # 'в' + 20: 2, # 'г' + 11: 2, # 'д' + 3: 3, # 'е' + 23: 3, # 'ж' + 15: 2, # 'з' + 2: 3, # 'и' + 26: 0, # 'й' + 12: 3, # 'к' + 10: 3, # 'л' + 14: 3, # 'м' + 6: 3, # 'н' + 4: 3, # 'о' + 13: 3, # 'п' + 7: 3, # 'Ñ€' + 8: 3, # 'Ñ' + 5: 1, # 'Ñ‚' + 19: 3, # 'у' + 29: 1, # 'Ñ„' + 25: 2, # 'Ñ…' + 22: 2, # 'ц' + 21: 2, # 'ч' + 27: 1, # 'ш' + 24: 1, # 'щ' + 17: 3, # 'ÑŠ' + 52: 1, # 'ÑŒ' + 42: 1, # 'ÑŽ' + 16: 3, # 'Ñ' + 58: 0, # 'Ñ”' + 62: 0, # 'â„–' + }, + 3: { # 'е' + 63: 0, # 'e' + 45: 1, # '\xad' + 31: 0, # 'Ð' + 32: 0, # 'Б' + 35: 0, # 'Ð’' + 43: 0, # 'Г' + 37: 0, # 'Д' + 44: 0, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 0, # 'И' + 59: 0, # 'Й' + 33: 0, # 'К' + 46: 0, # 'Л' + 38: 0, # 'Ðœ' + 36: 0, # 'Ð' + 41: 0, # 'О' + 30: 0, # 'П' + 39: 0, # 'Р' + 28: 0, # 'С' + 34: 0, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Ð¥' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 2, # 'а' + 18: 3, # 'б' + 9: 3, # 'в' + 20: 3, # 'г' + 11: 3, # 'д' + 3: 2, # 'е' + 23: 3, # 'ж' + 15: 3, # 'з' + 2: 2, # 'и' + 26: 3, # 'й' + 12: 3, # 'к' + 10: 3, # 'л' + 14: 3, # 'м' + 6: 3, # 'н' + 4: 3, # 'о' + 13: 3, # 'п' + 7: 3, # 'Ñ€' + 8: 3, # 'Ñ' + 5: 3, # 'Ñ‚' + 19: 2, # 'у' + 29: 3, # 'Ñ„' + 25: 3, # 'Ñ…' + 22: 3, # 'ц' + 21: 3, # 'ч' + 27: 3, # 'ш' + 24: 3, # 'щ' + 17: 1, # 'ÑŠ' + 52: 0, # 'ÑŒ' + 42: 1, # 'ÑŽ' + 16: 3, # 'Ñ' + 58: 0, # 'Ñ”' + 62: 0, # 'â„–' + }, + 23: { # 'ж' + 63: 0, # 'e' + 45: 0, # '\xad' + 31: 0, # 'Ð' + 32: 0, # 'Б' + 35: 0, # 'Ð’' + 43: 0, # 'Г' + 37: 0, # 'Д' + 44: 0, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 0, # 'И' + 59: 0, # 'Й' + 33: 0, # 'К' + 46: 0, # 'Л' + 38: 0, # 'Ðœ' + 36: 0, # 'Ð' + 41: 0, # 'О' + 30: 0, # 'П' + 39: 0, # 'Р' + 28: 0, # 'С' + 34: 0, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Ð¥' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 3, # 'а' + 18: 3, # 'б' + 9: 2, # 'в' + 20: 1, # 'г' + 11: 3, # 'д' + 3: 3, # 'е' + 23: 0, # 'ж' + 15: 0, # 'з' + 2: 3, # 'и' + 26: 0, # 'й' + 12: 2, # 'к' + 10: 1, # 'л' + 14: 1, # 'м' + 6: 3, # 'н' + 4: 2, # 'о' + 13: 1, # 'п' + 7: 1, # 'Ñ€' + 8: 1, # 'Ñ' + 5: 1, # 'Ñ‚' + 19: 2, # 'у' + 29: 0, # 'Ñ„' + 25: 0, # 'Ñ…' + 22: 1, # 'ц' + 21: 1, # 'ч' + 27: 0, # 'ш' + 24: 0, # 'щ' + 17: 2, # 'ÑŠ' + 52: 0, # 'ÑŒ' + 42: 0, # 'ÑŽ' + 16: 1, # 'Ñ' + 58: 0, # 'Ñ”' + 62: 0, # 'â„–' + }, + 15: { # 'з' + 63: 1, # 'e' + 45: 0, # '\xad' + 31: 0, # 'Ð' + 32: 0, # 'Б' + 35: 0, # 'Ð’' + 43: 0, # 'Г' + 37: 0, # 'Д' + 44: 0, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 0, # 'И' + 59: 0, # 'Й' + 33: 0, # 'К' + 46: 0, # 'Л' + 38: 0, # 'Ðœ' + 36: 0, # 'Ð' + 41: 0, # 'О' + 30: 0, # 'П' + 39: 0, # 'Р' + 28: 0, # 'С' + 34: 0, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Ð¥' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 3, # 'а' + 18: 3, # 'б' + 9: 3, # 'в' + 20: 3, # 'г' + 11: 3, # 'д' + 3: 3, # 'е' + 23: 1, # 'ж' + 15: 1, # 'з' + 2: 3, # 'и' + 26: 0, # 'й' + 12: 3, # 'к' + 10: 3, # 'л' + 14: 3, # 'м' + 6: 3, # 'н' + 4: 3, # 'о' + 13: 3, # 'п' + 7: 3, # 'Ñ€' + 8: 3, # 'Ñ' + 5: 3, # 'Ñ‚' + 19: 3, # 'у' + 29: 1, # 'Ñ„' + 25: 2, # 'Ñ…' + 22: 2, # 'ц' + 21: 2, # 'ч' + 27: 2, # 'ш' + 24: 1, # 'щ' + 17: 2, # 'ÑŠ' + 52: 1, # 'ÑŒ' + 42: 1, # 'ÑŽ' + 16: 2, # 'Ñ' + 58: 0, # 'Ñ”' + 62: 0, # 'â„–' + }, + 2: { # 'и' + 63: 1, # 'e' + 45: 1, # '\xad' + 31: 0, # 'Ð' + 32: 0, # 'Б' + 35: 0, # 'Ð’' + 43: 1, # 'Г' + 37: 0, # 'Д' + 44: 0, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 0, # 'И' + 59: 0, # 'Й' + 33: 1, # 'К' + 46: 0, # 'Л' + 38: 0, # 'Ðœ' + 36: 0, # 'Ð' + 41: 0, # 'О' + 30: 1, # 'П' + 39: 0, # 'Р' + 28: 0, # 'С' + 34: 0, # 'Т' + 51: 0, # 'У' + 48: 1, # 'Ф' + 49: 0, # 'Ð¥' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 3, # 'а' + 18: 3, # 'б' + 9: 3, # 'в' + 20: 3, # 'г' + 11: 3, # 'д' + 3: 3, # 'е' + 23: 3, # 'ж' + 15: 3, # 'з' + 2: 3, # 'и' + 26: 3, # 'й' + 12: 3, # 'к' + 10: 3, # 'л' + 14: 3, # 'м' + 6: 3, # 'н' + 4: 3, # 'о' + 13: 3, # 'п' + 7: 3, # 'Ñ€' + 8: 3, # 'Ñ' + 5: 3, # 'Ñ‚' + 19: 2, # 'у' + 29: 3, # 'Ñ„' + 25: 3, # 'Ñ…' + 22: 3, # 'ц' + 21: 3, # 'ч' + 27: 3, # 'ш' + 24: 3, # 'щ' + 17: 2, # 'ÑŠ' + 52: 0, # 'ÑŒ' + 42: 1, # 'ÑŽ' + 16: 3, # 'Ñ' + 58: 0, # 'Ñ”' + 62: 0, # 'â„–' + }, + 26: { # 'й' + 63: 0, # 'e' + 45: 0, # '\xad' + 31: 0, # 'Ð' + 32: 0, # 'Б' + 35: 0, # 'Ð’' + 43: 0, # 'Г' + 37: 0, # 'Д' + 44: 0, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 0, # 'И' + 59: 0, # 'Й' + 33: 0, # 'К' + 46: 0, # 'Л' + 38: 0, # 'Ðœ' + 36: 0, # 'Ð' + 41: 0, # 'О' + 30: 0, # 'П' + 39: 0, # 'Р' + 28: 0, # 'С' + 34: 0, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Ð¥' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 1, # 'а' + 18: 2, # 'б' + 9: 2, # 'в' + 20: 1, # 'г' + 11: 2, # 'д' + 3: 2, # 'е' + 23: 0, # 'ж' + 15: 2, # 'з' + 2: 1, # 'и' + 26: 0, # 'й' + 12: 3, # 'к' + 10: 2, # 'л' + 14: 2, # 'м' + 6: 3, # 'н' + 4: 2, # 'о' + 13: 1, # 'п' + 7: 2, # 'Ñ€' + 8: 3, # 'Ñ' + 5: 3, # 'Ñ‚' + 19: 1, # 'у' + 29: 2, # 'Ñ„' + 25: 1, # 'Ñ…' + 22: 2, # 'ц' + 21: 2, # 'ч' + 27: 1, # 'ш' + 24: 1, # 'щ' + 17: 1, # 'ÑŠ' + 52: 0, # 'ÑŒ' + 42: 0, # 'ÑŽ' + 16: 1, # 'Ñ' + 58: 0, # 'Ñ”' + 62: 0, # 'â„–' + }, + 12: { # 'к' + 63: 1, # 'e' + 45: 0, # '\xad' + 31: 0, # 'Ð' + 32: 0, # 'Б' + 35: 1, # 'Ð’' + 43: 0, # 'Г' + 37: 0, # 'Д' + 44: 0, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 1, # 'И' + 59: 0, # 'Й' + 33: 0, # 'К' + 46: 0, # 'Л' + 38: 0, # 'Ðœ' + 36: 0, # 'Ð' + 41: 0, # 'О' + 30: 0, # 'П' + 39: 0, # 'Р' + 28: 0, # 'С' + 34: 0, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Ð¥' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 3, # 'а' + 18: 1, # 'б' + 9: 3, # 'в' + 20: 2, # 'г' + 11: 1, # 'д' + 3: 3, # 'е' + 23: 0, # 'ж' + 15: 2, # 'з' + 2: 3, # 'и' + 26: 0, # 'й' + 12: 1, # 'к' + 10: 3, # 'л' + 14: 2, # 'м' + 6: 3, # 'н' + 4: 3, # 'о' + 13: 1, # 'п' + 7: 3, # 'Ñ€' + 8: 3, # 'Ñ' + 5: 3, # 'Ñ‚' + 19: 3, # 'у' + 29: 1, # 'Ñ„' + 25: 1, # 'Ñ…' + 22: 3, # 'ц' + 21: 2, # 'ч' + 27: 1, # 'ш' + 24: 0, # 'щ' + 17: 3, # 'ÑŠ' + 52: 1, # 'ÑŒ' + 42: 2, # 'ÑŽ' + 16: 1, # 'Ñ' + 58: 0, # 'Ñ”' + 62: 0, # 'â„–' + }, + 10: { # 'л' + 63: 1, # 'e' + 45: 1, # '\xad' + 31: 0, # 'Ð' + 32: 0, # 'Б' + 35: 0, # 'Ð’' + 43: 0, # 'Г' + 37: 0, # 'Д' + 44: 0, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 0, # 'И' + 59: 0, # 'Й' + 33: 0, # 'К' + 46: 0, # 'Л' + 38: 0, # 'Ðœ' + 36: 0, # 'Ð' + 41: 0, # 'О' + 30: 0, # 'П' + 39: 0, # 'Р' + 28: 1, # 'С' + 34: 0, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Ð¥' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 3, # 'а' + 18: 3, # 'б' + 9: 3, # 'в' + 20: 3, # 'г' + 11: 2, # 'д' + 3: 3, # 'е' + 23: 3, # 'ж' + 15: 2, # 'з' + 2: 3, # 'и' + 26: 0, # 'й' + 12: 3, # 'к' + 10: 1, # 'л' + 14: 2, # 'м' + 6: 3, # 'н' + 4: 3, # 'о' + 13: 2, # 'п' + 7: 2, # 'Ñ€' + 8: 3, # 'Ñ' + 5: 3, # 'Ñ‚' + 19: 3, # 'у' + 29: 2, # 'Ñ„' + 25: 2, # 'Ñ…' + 22: 2, # 'ц' + 21: 2, # 'ч' + 27: 2, # 'ш' + 24: 1, # 'щ' + 17: 3, # 'ÑŠ' + 52: 2, # 'ÑŒ' + 42: 3, # 'ÑŽ' + 16: 3, # 'Ñ' + 58: 0, # 'Ñ”' + 62: 0, # 'â„–' + }, + 14: { # 'м' + 63: 1, # 'e' + 45: 0, # '\xad' + 31: 1, # 'Ð' + 32: 0, # 'Б' + 35: 0, # 'Ð’' + 43: 0, # 'Г' + 37: 0, # 'Д' + 44: 0, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 0, # 'И' + 59: 0, # 'Й' + 33: 0, # 'К' + 46: 0, # 'Л' + 38: 0, # 'Ðœ' + 36: 0, # 'Ð' + 41: 0, # 'О' + 30: 0, # 'П' + 39: 0, # 'Р' + 28: 0, # 'С' + 34: 0, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Ð¥' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 3, # 'а' + 18: 3, # 'б' + 9: 3, # 'в' + 20: 1, # 'г' + 11: 1, # 'д' + 3: 3, # 'е' + 23: 1, # 'ж' + 15: 1, # 'з' + 2: 3, # 'и' + 26: 0, # 'й' + 12: 2, # 'к' + 10: 3, # 'л' + 14: 1, # 'м' + 6: 3, # 'н' + 4: 3, # 'о' + 13: 3, # 'п' + 7: 2, # 'Ñ€' + 8: 2, # 'Ñ' + 5: 1, # 'Ñ‚' + 19: 3, # 'у' + 29: 2, # 'Ñ„' + 25: 1, # 'Ñ…' + 22: 2, # 'ц' + 21: 2, # 'ч' + 27: 2, # 'ш' + 24: 1, # 'щ' + 17: 3, # 'ÑŠ' + 52: 1, # 'ÑŒ' + 42: 2, # 'ÑŽ' + 16: 3, # 'Ñ' + 58: 0, # 'Ñ”' + 62: 0, # 'â„–' + }, + 6: { # 'н' + 63: 1, # 'e' + 45: 0, # '\xad' + 31: 0, # 'Ð' + 32: 0, # 'Б' + 35: 0, # 'Ð’' + 43: 0, # 'Г' + 37: 0, # 'Д' + 44: 0, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 0, # 'И' + 59: 0, # 'Й' + 33: 0, # 'К' + 46: 0, # 'Л' + 38: 0, # 'Ðœ' + 36: 0, # 'Ð' + 41: 0, # 'О' + 30: 0, # 'П' + 39: 1, # 'Р' + 28: 0, # 'С' + 34: 0, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Ð¥' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 3, # 'а' + 18: 2, # 'б' + 9: 2, # 'в' + 20: 3, # 'г' + 11: 3, # 'д' + 3: 3, # 'е' + 23: 2, # 'ж' + 15: 2, # 'з' + 2: 3, # 'и' + 26: 0, # 'й' + 12: 3, # 'к' + 10: 2, # 'л' + 14: 1, # 'м' + 6: 3, # 'н' + 4: 3, # 'о' + 13: 1, # 'п' + 7: 2, # 'Ñ€' + 8: 3, # 'Ñ' + 5: 3, # 'Ñ‚' + 19: 3, # 'у' + 29: 3, # 'Ñ„' + 25: 2, # 'Ñ…' + 22: 3, # 'ц' + 21: 3, # 'ч' + 27: 2, # 'ш' + 24: 1, # 'щ' + 17: 3, # 'ÑŠ' + 52: 2, # 'ÑŒ' + 42: 2, # 'ÑŽ' + 16: 3, # 'Ñ' + 58: 0, # 'Ñ”' + 62: 0, # 'â„–' + }, + 4: { # 'о' + 63: 0, # 'e' + 45: 1, # '\xad' + 31: 0, # 'Ð' + 32: 0, # 'Б' + 35: 0, # 'Ð’' + 43: 0, # 'Г' + 37: 0, # 'Д' + 44: 0, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 0, # 'И' + 59: 0, # 'Й' + 33: 0, # 'К' + 46: 0, # 'Л' + 38: 0, # 'Ðœ' + 36: 0, # 'Ð' + 41: 0, # 'О' + 30: 0, # 'П' + 39: 0, # 'Р' + 28: 0, # 'С' + 34: 0, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Ð¥' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 2, # 'а' + 18: 3, # 'б' + 9: 3, # 'в' + 20: 3, # 'г' + 11: 3, # 'д' + 3: 3, # 'е' + 23: 3, # 'ж' + 15: 3, # 'з' + 2: 3, # 'и' + 26: 3, # 'й' + 12: 3, # 'к' + 10: 3, # 'л' + 14: 3, # 'м' + 6: 3, # 'н' + 4: 2, # 'о' + 13: 3, # 'п' + 7: 3, # 'Ñ€' + 8: 3, # 'Ñ' + 5: 3, # 'Ñ‚' + 19: 2, # 'у' + 29: 3, # 'Ñ„' + 25: 3, # 'Ñ…' + 22: 3, # 'ц' + 21: 3, # 'ч' + 27: 3, # 'ш' + 24: 3, # 'щ' + 17: 1, # 'ÑŠ' + 52: 0, # 'ÑŒ' + 42: 1, # 'ÑŽ' + 16: 3, # 'Ñ' + 58: 0, # 'Ñ”' + 62: 0, # 'â„–' + }, + 13: { # 'п' + 63: 1, # 'e' + 45: 0, # '\xad' + 31: 0, # 'Ð' + 32: 0, # 'Б' + 35: 0, # 'Ð’' + 43: 0, # 'Г' + 37: 0, # 'Д' + 44: 0, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 0, # 'И' + 59: 0, # 'Й' + 33: 0, # 'К' + 46: 0, # 'Л' + 38: 0, # 'Ðœ' + 36: 0, # 'Ð' + 41: 0, # 'О' + 30: 0, # 'П' + 39: 0, # 'Р' + 28: 0, # 'С' + 34: 0, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Ð¥' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 3, # 'а' + 18: 1, # 'б' + 9: 2, # 'в' + 20: 1, # 'г' + 11: 1, # 'д' + 3: 3, # 'е' + 23: 0, # 'ж' + 15: 1, # 'з' + 2: 3, # 'и' + 26: 1, # 'й' + 12: 2, # 'к' + 10: 3, # 'л' + 14: 1, # 'м' + 6: 2, # 'н' + 4: 3, # 'о' + 13: 1, # 'п' + 7: 3, # 'Ñ€' + 8: 2, # 'Ñ' + 5: 2, # 'Ñ‚' + 19: 3, # 'у' + 29: 1, # 'Ñ„' + 25: 1, # 'Ñ…' + 22: 2, # 'ц' + 21: 2, # 'ч' + 27: 1, # 'ш' + 24: 1, # 'щ' + 17: 3, # 'ÑŠ' + 52: 1, # 'ÑŒ' + 42: 2, # 'ÑŽ' + 16: 2, # 'Ñ' + 58: 0, # 'Ñ”' + 62: 0, # 'â„–' + }, + 7: { # 'Ñ€' + 63: 1, # 'e' + 45: 0, # '\xad' + 31: 0, # 'Ð' + 32: 0, # 'Б' + 35: 0, # 'Ð’' + 43: 0, # 'Г' + 37: 0, # 'Д' + 44: 0, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 0, # 'И' + 59: 0, # 'Й' + 33: 0, # 'К' + 46: 0, # 'Л' + 38: 0, # 'Ðœ' + 36: 0, # 'Ð' + 41: 0, # 'О' + 30: 0, # 'П' + 39: 0, # 'Р' + 28: 0, # 'С' + 34: 0, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Ð¥' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 3, # 'а' + 18: 3, # 'б' + 9: 3, # 'в' + 20: 3, # 'г' + 11: 3, # 'д' + 3: 3, # 'е' + 23: 3, # 'ж' + 15: 2, # 'з' + 2: 3, # 'и' + 26: 0, # 'й' + 12: 3, # 'к' + 10: 3, # 'л' + 14: 3, # 'м' + 6: 3, # 'н' + 4: 3, # 'о' + 13: 2, # 'п' + 7: 1, # 'Ñ€' + 8: 3, # 'Ñ' + 5: 3, # 'Ñ‚' + 19: 3, # 'у' + 29: 2, # 'Ñ„' + 25: 3, # 'Ñ…' + 22: 3, # 'ц' + 21: 2, # 'ч' + 27: 3, # 'ш' + 24: 1, # 'щ' + 17: 3, # 'ÑŠ' + 52: 1, # 'ÑŒ' + 42: 2, # 'ÑŽ' + 16: 3, # 'Ñ' + 58: 0, # 'Ñ”' + 62: 0, # 'â„–' + }, + 8: { # 'Ñ' + 63: 1, # 'e' + 45: 0, # '\xad' + 31: 0, # 'Ð' + 32: 0, # 'Б' + 35: 0, # 'Ð’' + 43: 0, # 'Г' + 37: 0, # 'Д' + 44: 0, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 0, # 'И' + 59: 0, # 'Й' + 33: 0, # 'К' + 46: 0, # 'Л' + 38: 0, # 'Ðœ' + 36: 0, # 'Ð' + 41: 0, # 'О' + 30: 0, # 'П' + 39: 0, # 'Р' + 28: 0, # 'С' + 34: 0, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Ð¥' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 3, # 'а' + 18: 2, # 'б' + 9: 3, # 'в' + 20: 2, # 'г' + 11: 2, # 'д' + 3: 3, # 'е' + 23: 0, # 'ж' + 15: 1, # 'з' + 2: 3, # 'и' + 26: 0, # 'й' + 12: 3, # 'к' + 10: 3, # 'л' + 14: 3, # 'м' + 6: 3, # 'н' + 4: 3, # 'о' + 13: 3, # 'п' + 7: 3, # 'Ñ€' + 8: 1, # 'Ñ' + 5: 3, # 'Ñ‚' + 19: 3, # 'у' + 29: 2, # 'Ñ„' + 25: 2, # 'Ñ…' + 22: 2, # 'ц' + 21: 2, # 'ч' + 27: 2, # 'ш' + 24: 0, # 'щ' + 17: 3, # 'ÑŠ' + 52: 2, # 'ÑŒ' + 42: 2, # 'ÑŽ' + 16: 3, # 'Ñ' + 58: 0, # 'Ñ”' + 62: 0, # 'â„–' + }, + 5: { # 'Ñ‚' + 63: 1, # 'e' + 45: 0, # '\xad' + 31: 0, # 'Ð' + 32: 0, # 'Б' + 35: 0, # 'Ð’' + 43: 0, # 'Г' + 37: 0, # 'Д' + 44: 0, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 0, # 'И' + 59: 0, # 'Й' + 33: 0, # 'К' + 46: 0, # 'Л' + 38: 0, # 'Ðœ' + 36: 0, # 'Ð' + 41: 0, # 'О' + 30: 0, # 'П' + 39: 0, # 'Р' + 28: 0, # 'С' + 34: 0, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Ð¥' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 3, # 'а' + 18: 3, # 'б' + 9: 3, # 'в' + 20: 2, # 'г' + 11: 2, # 'д' + 3: 3, # 'е' + 23: 1, # 'ж' + 15: 1, # 'з' + 2: 3, # 'и' + 26: 0, # 'й' + 12: 3, # 'к' + 10: 3, # 'л' + 14: 2, # 'м' + 6: 3, # 'н' + 4: 3, # 'о' + 13: 2, # 'п' + 7: 3, # 'Ñ€' + 8: 3, # 'Ñ' + 5: 3, # 'Ñ‚' + 19: 3, # 'у' + 29: 1, # 'Ñ„' + 25: 2, # 'Ñ…' + 22: 2, # 'ц' + 21: 2, # 'ч' + 27: 1, # 'ш' + 24: 1, # 'щ' + 17: 3, # 'ÑŠ' + 52: 2, # 'ÑŒ' + 42: 2, # 'ÑŽ' + 16: 3, # 'Ñ' + 58: 0, # 'Ñ”' + 62: 0, # 'â„–' + }, + 19: { # 'у' + 63: 0, # 'e' + 45: 0, # '\xad' + 31: 0, # 'Ð' + 32: 0, # 'Б' + 35: 0, # 'Ð’' + 43: 0, # 'Г' + 37: 0, # 'Д' + 44: 0, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 0, # 'И' + 59: 0, # 'Й' + 33: 0, # 'К' + 46: 0, # 'Л' + 38: 0, # 'Ðœ' + 36: 0, # 'Ð' + 41: 0, # 'О' + 30: 0, # 'П' + 39: 0, # 'Р' + 28: 0, # 'С' + 34: 0, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Ð¥' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 3, # 'а' + 18: 3, # 'б' + 9: 3, # 'в' + 20: 3, # 'г' + 11: 3, # 'д' + 3: 2, # 'е' + 23: 3, # 'ж' + 15: 3, # 'з' + 2: 2, # 'и' + 26: 2, # 'й' + 12: 3, # 'к' + 10: 3, # 'л' + 14: 3, # 'м' + 6: 3, # 'н' + 4: 2, # 'о' + 13: 3, # 'п' + 7: 3, # 'Ñ€' + 8: 3, # 'Ñ' + 5: 3, # 'Ñ‚' + 19: 1, # 'у' + 29: 2, # 'Ñ„' + 25: 2, # 'Ñ…' + 22: 2, # 'ц' + 21: 3, # 'ч' + 27: 3, # 'ш' + 24: 2, # 'щ' + 17: 1, # 'ÑŠ' + 52: 0, # 'ÑŒ' + 42: 1, # 'ÑŽ' + 16: 1, # 'Ñ' + 58: 0, # 'Ñ”' + 62: 0, # 'â„–' + }, + 29: { # 'Ñ„' + 63: 1, # 'e' + 45: 0, # '\xad' + 31: 0, # 'Ð' + 32: 0, # 'Б' + 35: 0, # 'Ð’' + 43: 0, # 'Г' + 37: 0, # 'Д' + 44: 0, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 0, # 'И' + 59: 0, # 'Й' + 33: 0, # 'К' + 46: 0, # 'Л' + 38: 0, # 'Ðœ' + 36: 0, # 'Ð' + 41: 0, # 'О' + 30: 0, # 'П' + 39: 0, # 'Р' + 28: 0, # 'С' + 34: 0, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Ð¥' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 3, # 'а' + 18: 1, # 'б' + 9: 1, # 'в' + 20: 1, # 'г' + 11: 0, # 'д' + 3: 3, # 'е' + 23: 0, # 'ж' + 15: 0, # 'з' + 2: 3, # 'и' + 26: 0, # 'й' + 12: 2, # 'к' + 10: 2, # 'л' + 14: 1, # 'м' + 6: 1, # 'н' + 4: 3, # 'о' + 13: 0, # 'п' + 7: 2, # 'Ñ€' + 8: 2, # 'Ñ' + 5: 2, # 'Ñ‚' + 19: 2, # 'у' + 29: 0, # 'Ñ„' + 25: 1, # 'Ñ…' + 22: 0, # 'ц' + 21: 1, # 'ч' + 27: 1, # 'ш' + 24: 0, # 'щ' + 17: 2, # 'ÑŠ' + 52: 2, # 'ÑŒ' + 42: 1, # 'ÑŽ' + 16: 1, # 'Ñ' + 58: 0, # 'Ñ”' + 62: 0, # 'â„–' + }, + 25: { # 'Ñ…' + 63: 0, # 'e' + 45: 0, # '\xad' + 31: 0, # 'Ð' + 32: 0, # 'Б' + 35: 0, # 'Ð’' + 43: 0, # 'Г' + 37: 0, # 'Д' + 44: 0, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 0, # 'И' + 59: 0, # 'Й' + 33: 0, # 'К' + 46: 0, # 'Л' + 38: 0, # 'Ðœ' + 36: 0, # 'Ð' + 41: 0, # 'О' + 30: 0, # 'П' + 39: 0, # 'Р' + 28: 0, # 'С' + 34: 0, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Ð¥' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 3, # 'а' + 18: 1, # 'б' + 9: 3, # 'в' + 20: 0, # 'г' + 11: 1, # 'д' + 3: 2, # 'е' + 23: 0, # 'ж' + 15: 1, # 'з' + 2: 3, # 'и' + 26: 0, # 'й' + 12: 1, # 'к' + 10: 2, # 'л' + 14: 2, # 'м' + 6: 3, # 'н' + 4: 3, # 'о' + 13: 1, # 'п' + 7: 3, # 'Ñ€' + 8: 1, # 'Ñ' + 5: 2, # 'Ñ‚' + 19: 3, # 'у' + 29: 0, # 'Ñ„' + 25: 1, # 'Ñ…' + 22: 0, # 'ц' + 21: 1, # 'ч' + 27: 0, # 'ш' + 24: 0, # 'щ' + 17: 2, # 'ÑŠ' + 52: 0, # 'ÑŒ' + 42: 1, # 'ÑŽ' + 16: 1, # 'Ñ' + 58: 0, # 'Ñ”' + 62: 0, # 'â„–' + }, + 22: { # 'ц' + 63: 1, # 'e' + 45: 0, # '\xad' + 31: 0, # 'Ð' + 32: 0, # 'Б' + 35: 0, # 'Ð’' + 43: 0, # 'Г' + 37: 0, # 'Д' + 44: 0, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 0, # 'И' + 59: 0, # 'Й' + 33: 0, # 'К' + 46: 0, # 'Л' + 38: 0, # 'Ðœ' + 36: 0, # 'Ð' + 41: 0, # 'О' + 30: 0, # 'П' + 39: 0, # 'Р' + 28: 0, # 'С' + 34: 0, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Ð¥' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 3, # 'а' + 18: 1, # 'б' + 9: 2, # 'в' + 20: 1, # 'г' + 11: 1, # 'д' + 3: 3, # 'е' + 23: 0, # 'ж' + 15: 1, # 'з' + 2: 3, # 'и' + 26: 0, # 'й' + 12: 2, # 'к' + 10: 1, # 'л' + 14: 1, # 'м' + 6: 1, # 'н' + 4: 2, # 'о' + 13: 1, # 'п' + 7: 1, # 'Ñ€' + 8: 1, # 'Ñ' + 5: 1, # 'Ñ‚' + 19: 2, # 'у' + 29: 1, # 'Ñ„' + 25: 1, # 'Ñ…' + 22: 1, # 'ц' + 21: 1, # 'ч' + 27: 1, # 'ш' + 24: 1, # 'щ' + 17: 2, # 'ÑŠ' + 52: 1, # 'ÑŒ' + 42: 0, # 'ÑŽ' + 16: 2, # 'Ñ' + 58: 0, # 'Ñ”' + 62: 0, # 'â„–' + }, + 21: { # 'ч' + 63: 1, # 'e' + 45: 0, # '\xad' + 31: 0, # 'Ð' + 32: 0, # 'Б' + 35: 0, # 'Ð’' + 43: 0, # 'Г' + 37: 0, # 'Д' + 44: 0, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 0, # 'И' + 59: 0, # 'Й' + 33: 0, # 'К' + 46: 0, # 'Л' + 38: 0, # 'Ðœ' + 36: 0, # 'Ð' + 41: 0, # 'О' + 30: 0, # 'П' + 39: 0, # 'Р' + 28: 0, # 'С' + 34: 0, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Ð¥' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 3, # 'а' + 18: 1, # 'б' + 9: 3, # 'в' + 20: 1, # 'г' + 11: 0, # 'д' + 3: 3, # 'е' + 23: 1, # 'ж' + 15: 0, # 'з' + 2: 3, # 'и' + 26: 0, # 'й' + 12: 3, # 'к' + 10: 2, # 'л' + 14: 2, # 'м' + 6: 3, # 'н' + 4: 3, # 'о' + 13: 0, # 'п' + 7: 2, # 'Ñ€' + 8: 0, # 'Ñ' + 5: 2, # 'Ñ‚' + 19: 3, # 'у' + 29: 0, # 'Ñ„' + 25: 0, # 'Ñ…' + 22: 0, # 'ц' + 21: 0, # 'ч' + 27: 1, # 'ш' + 24: 0, # 'щ' + 17: 2, # 'ÑŠ' + 52: 0, # 'ÑŒ' + 42: 1, # 'ÑŽ' + 16: 0, # 'Ñ' + 58: 0, # 'Ñ”' + 62: 0, # 'â„–' + }, + 27: { # 'ш' + 63: 1, # 'e' + 45: 0, # '\xad' + 31: 0, # 'Ð' + 32: 0, # 'Б' + 35: 0, # 'Ð’' + 43: 0, # 'Г' + 37: 0, # 'Д' + 44: 0, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 0, # 'И' + 59: 0, # 'Й' + 33: 0, # 'К' + 46: 0, # 'Л' + 38: 0, # 'Ðœ' + 36: 0, # 'Ð' + 41: 0, # 'О' + 30: 0, # 'П' + 39: 0, # 'Р' + 28: 0, # 'С' + 34: 0, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Ð¥' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 3, # 'а' + 18: 0, # 'б' + 9: 2, # 'в' + 20: 0, # 'г' + 11: 1, # 'д' + 3: 3, # 'е' + 23: 0, # 'ж' + 15: 0, # 'з' + 2: 3, # 'и' + 26: 0, # 'й' + 12: 3, # 'к' + 10: 2, # 'л' + 14: 1, # 'м' + 6: 3, # 'н' + 4: 2, # 'о' + 13: 2, # 'п' + 7: 1, # 'Ñ€' + 8: 0, # 'Ñ' + 5: 1, # 'Ñ‚' + 19: 2, # 'у' + 29: 1, # 'Ñ„' + 25: 0, # 'Ñ…' + 22: 0, # 'ц' + 21: 1, # 'ч' + 27: 0, # 'ш' + 24: 0, # 'щ' + 17: 2, # 'ÑŠ' + 52: 1, # 'ÑŒ' + 42: 1, # 'ÑŽ' + 16: 0, # 'Ñ' + 58: 0, # 'Ñ”' + 62: 0, # 'â„–' + }, + 24: { # 'щ' + 63: 1, # 'e' + 45: 0, # '\xad' + 31: 0, # 'Ð' + 32: 0, # 'Б' + 35: 0, # 'Ð’' + 43: 0, # 'Г' + 37: 0, # 'Д' + 44: 0, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 0, # 'И' + 59: 0, # 'Й' + 33: 0, # 'К' + 46: 0, # 'Л' + 38: 0, # 'Ðœ' + 36: 0, # 'Ð' + 41: 0, # 'О' + 30: 0, # 'П' + 39: 0, # 'Р' + 28: 0, # 'С' + 34: 0, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Ð¥' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 3, # 'а' + 18: 0, # 'б' + 9: 1, # 'в' + 20: 0, # 'г' + 11: 0, # 'д' + 3: 3, # 'е' + 23: 0, # 'ж' + 15: 0, # 'з' + 2: 3, # 'и' + 26: 0, # 'й' + 12: 1, # 'к' + 10: 0, # 'л' + 14: 0, # 'м' + 6: 2, # 'н' + 4: 3, # 'о' + 13: 0, # 'п' + 7: 1, # 'Ñ€' + 8: 0, # 'Ñ' + 5: 2, # 'Ñ‚' + 19: 3, # 'у' + 29: 0, # 'Ñ„' + 25: 0, # 'Ñ…' + 22: 1, # 'ц' + 21: 0, # 'ч' + 27: 0, # 'ш' + 24: 0, # 'щ' + 17: 1, # 'ÑŠ' + 52: 0, # 'ÑŒ' + 42: 0, # 'ÑŽ' + 16: 2, # 'Ñ' + 58: 0, # 'Ñ”' + 62: 0, # 'â„–' + }, + 17: { # 'ÑŠ' + 63: 0, # 'e' + 45: 0, # '\xad' + 31: 0, # 'Ð' + 32: 0, # 'Б' + 35: 0, # 'Ð’' + 43: 0, # 'Г' + 37: 0, # 'Д' + 44: 0, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 0, # 'И' + 59: 0, # 'Й' + 33: 0, # 'К' + 46: 0, # 'Л' + 38: 0, # 'Ðœ' + 36: 0, # 'Ð' + 41: 0, # 'О' + 30: 0, # 'П' + 39: 0, # 'Р' + 28: 0, # 'С' + 34: 0, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Ð¥' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 1, # 'а' + 18: 3, # 'б' + 9: 3, # 'в' + 20: 3, # 'г' + 11: 3, # 'д' + 3: 2, # 'е' + 23: 3, # 'ж' + 15: 3, # 'з' + 2: 1, # 'и' + 26: 2, # 'й' + 12: 3, # 'к' + 10: 3, # 'л' + 14: 3, # 'м' + 6: 3, # 'н' + 4: 3, # 'о' + 13: 3, # 'п' + 7: 3, # 'Ñ€' + 8: 3, # 'Ñ' + 5: 3, # 'Ñ‚' + 19: 1, # 'у' + 29: 1, # 'Ñ„' + 25: 2, # 'Ñ…' + 22: 2, # 'ц' + 21: 3, # 'ч' + 27: 2, # 'ш' + 24: 3, # 'щ' + 17: 0, # 'ÑŠ' + 52: 0, # 'ÑŒ' + 42: 2, # 'ÑŽ' + 16: 0, # 'Ñ' + 58: 0, # 'Ñ”' + 62: 0, # 'â„–' + }, + 52: { # 'ÑŒ' + 63: 0, # 'e' + 45: 0, # '\xad' + 31: 0, # 'Ð' + 32: 0, # 'Б' + 35: 0, # 'Ð’' + 43: 0, # 'Г' + 37: 0, # 'Д' + 44: 0, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 0, # 'И' + 59: 0, # 'Й' + 33: 0, # 'К' + 46: 0, # 'Л' + 38: 0, # 'Ðœ' + 36: 0, # 'Ð' + 41: 0, # 'О' + 30: 0, # 'П' + 39: 0, # 'Р' + 28: 0, # 'С' + 34: 0, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Ð¥' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 0, # 'а' + 18: 0, # 'б' + 9: 0, # 'в' + 20: 0, # 'г' + 11: 0, # 'д' + 3: 1, # 'е' + 23: 0, # 'ж' + 15: 0, # 'з' + 2: 0, # 'и' + 26: 0, # 'й' + 12: 1, # 'к' + 10: 0, # 'л' + 14: 0, # 'м' + 6: 1, # 'н' + 4: 3, # 'о' + 13: 0, # 'п' + 7: 0, # 'Ñ€' + 8: 0, # 'Ñ' + 5: 1, # 'Ñ‚' + 19: 0, # 'у' + 29: 0, # 'Ñ„' + 25: 0, # 'Ñ…' + 22: 1, # 'ц' + 21: 0, # 'ч' + 27: 0, # 'ш' + 24: 0, # 'щ' + 17: 0, # 'ÑŠ' + 52: 0, # 'ÑŒ' + 42: 1, # 'ÑŽ' + 16: 0, # 'Ñ' + 58: 0, # 'Ñ”' + 62: 0, # 'â„–' + }, + 42: { # 'ÑŽ' + 63: 0, # 'e' + 45: 0, # '\xad' + 31: 0, # 'Ð' + 32: 0, # 'Б' + 35: 0, # 'Ð’' + 43: 0, # 'Г' + 37: 0, # 'Д' + 44: 0, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 0, # 'И' + 59: 0, # 'Й' + 33: 0, # 'К' + 46: 0, # 'Л' + 38: 0, # 'Ðœ' + 36: 0, # 'Ð' + 41: 0, # 'О' + 30: 0, # 'П' + 39: 0, # 'Р' + 28: 0, # 'С' + 34: 0, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Ð¥' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 1, # 'а' + 18: 2, # 'б' + 9: 1, # 'в' + 20: 2, # 'г' + 11: 2, # 'д' + 3: 1, # 'е' + 23: 2, # 'ж' + 15: 2, # 'з' + 2: 1, # 'и' + 26: 1, # 'й' + 12: 2, # 'к' + 10: 2, # 'л' + 14: 2, # 'м' + 6: 2, # 'н' + 4: 1, # 'о' + 13: 1, # 'п' + 7: 2, # 'Ñ€' + 8: 2, # 'Ñ' + 5: 2, # 'Ñ‚' + 19: 1, # 'у' + 29: 1, # 'Ñ„' + 25: 1, # 'Ñ…' + 22: 2, # 'ц' + 21: 3, # 'ч' + 27: 1, # 'ш' + 24: 1, # 'щ' + 17: 1, # 'ÑŠ' + 52: 0, # 'ÑŒ' + 42: 0, # 'ÑŽ' + 16: 1, # 'Ñ' + 58: 0, # 'Ñ”' + 62: 0, # 'â„–' + }, + 16: { # 'Ñ' + 63: 0, # 'e' + 45: 1, # '\xad' + 31: 0, # 'Ð' + 32: 0, # 'Б' + 35: 0, # 'Ð’' + 43: 0, # 'Г' + 37: 0, # 'Д' + 44: 0, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 0, # 'И' + 59: 0, # 'Й' + 33: 0, # 'К' + 46: 0, # 'Л' + 38: 0, # 'Ðœ' + 36: 0, # 'Ð' + 41: 0, # 'О' + 30: 0, # 'П' + 39: 0, # 'Р' + 28: 0, # 'С' + 34: 0, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Ð¥' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 0, # 'а' + 18: 3, # 'б' + 9: 3, # 'в' + 20: 2, # 'г' + 11: 3, # 'д' + 3: 2, # 'е' + 23: 1, # 'ж' + 15: 2, # 'з' + 2: 1, # 'и' + 26: 2, # 'й' + 12: 3, # 'к' + 10: 3, # 'л' + 14: 3, # 'м' + 6: 3, # 'н' + 4: 1, # 'о' + 13: 2, # 'п' + 7: 2, # 'Ñ€' + 8: 3, # 'Ñ' + 5: 3, # 'Ñ‚' + 19: 1, # 'у' + 29: 1, # 'Ñ„' + 25: 3, # 'Ñ…' + 22: 2, # 'ц' + 21: 1, # 'ч' + 27: 1, # 'ш' + 24: 2, # 'щ' + 17: 0, # 'ÑŠ' + 52: 0, # 'ÑŒ' + 42: 0, # 'ÑŽ' + 16: 1, # 'Ñ' + 58: 0, # 'Ñ”' + 62: 0, # 'â„–' + }, + 58: { # 'Ñ”' + 63: 0, # 'e' + 45: 0, # '\xad' + 31: 0, # 'Ð' + 32: 0, # 'Б' + 35: 0, # 'Ð’' + 43: 0, # 'Г' + 37: 0, # 'Д' + 44: 0, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 0, # 'И' + 59: 0, # 'Й' + 33: 0, # 'К' + 46: 0, # 'Л' + 38: 0, # 'Ðœ' + 36: 0, # 'Ð' + 41: 0, # 'О' + 30: 0, # 'П' + 39: 0, # 'Р' + 28: 0, # 'С' + 34: 0, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Ð¥' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 0, # 'а' + 18: 0, # 'б' + 9: 0, # 'в' + 20: 0, # 'г' + 11: 0, # 'д' + 3: 0, # 'е' + 23: 0, # 'ж' + 15: 0, # 'з' + 2: 0, # 'и' + 26: 0, # 'й' + 12: 0, # 'к' + 10: 0, # 'л' + 14: 0, # 'м' + 6: 0, # 'н' + 4: 0, # 'о' + 13: 0, # 'п' + 7: 0, # 'Ñ€' + 8: 0, # 'Ñ' + 5: 0, # 'Ñ‚' + 19: 0, # 'у' + 29: 0, # 'Ñ„' + 25: 0, # 'Ñ…' + 22: 0, # 'ц' + 21: 0, # 'ч' + 27: 0, # 'ш' + 24: 0, # 'щ' + 17: 0, # 'ÑŠ' + 52: 0, # 'ÑŒ' + 42: 0, # 'ÑŽ' + 16: 0, # 'Ñ' + 58: 0, # 'Ñ”' + 62: 0, # 'â„–' + }, + 62: { # 'â„–' + 63: 0, # 'e' + 45: 0, # '\xad' + 31: 0, # 'Ð' + 32: 0, # 'Б' + 35: 0, # 'Ð’' + 43: 0, # 'Г' + 37: 0, # 'Д' + 44: 0, # 'Е' + 55: 0, # 'Ж' + 47: 0, # 'З' + 40: 0, # 'И' + 59: 0, # 'Й' + 33: 0, # 'К' + 46: 0, # 'Л' + 38: 0, # 'Ðœ' + 36: 0, # 'Ð' + 41: 0, # 'О' + 30: 0, # 'П' + 39: 0, # 'Р' + 28: 0, # 'С' + 34: 0, # 'Т' + 51: 0, # 'У' + 48: 0, # 'Ф' + 49: 0, # 'Ð¥' + 53: 0, # 'Ц' + 50: 0, # 'Ч' + 54: 0, # 'Ш' + 57: 0, # 'Щ' + 61: 0, # 'Ъ' + 60: 0, # 'Ю' + 56: 0, # 'Я' + 1: 0, # 'а' + 18: 0, # 'б' + 9: 0, # 'в' + 20: 0, # 'г' + 11: 0, # 'д' + 3: 0, # 'е' + 23: 0, # 'ж' + 15: 0, # 'з' + 2: 0, # 'и' + 26: 0, # 'й' + 12: 0, # 'к' + 10: 0, # 'л' + 14: 0, # 'м' + 6: 0, # 'н' + 4: 0, # 'о' + 13: 0, # 'п' + 7: 0, # 'Ñ€' + 8: 0, # 'Ñ' + 5: 0, # 'Ñ‚' + 19: 0, # 'у' + 29: 0, # 'Ñ„' + 25: 0, # 'Ñ…' + 22: 0, # 'ц' + 21: 0, # 'ч' + 27: 0, # 'ш' + 24: 0, # 'щ' + 17: 0, # 'ÑŠ' + 52: 0, # 'ÑŒ' + 42: 0, # 'ÑŽ' + 16: 0, # 'Ñ' + 58: 0, # 'Ñ”' + 62: 0, # 'â„–' + }, +} + +# 255: Undefined characters that did not exist in training text +# 254: Carriage/Return +# 253: symbol (punctuation) that does not belong to word +# 252: 0 - 9 +# 251: Control characters + +# Character Mapping Table(s): +ISO_8859_5_BULGARIAN_CHAR_TO_ORDER = { + 0: 255, # '\x00' + 1: 255, # '\x01' + 2: 255, # '\x02' + 3: 255, # '\x03' + 4: 255, # '\x04' + 5: 255, # '\x05' + 6: 255, # '\x06' + 7: 255, # '\x07' + 8: 255, # '\x08' + 9: 255, # '\t' + 10: 254, # '\n' + 11: 255, # '\x0b' + 12: 255, # '\x0c' + 13: 254, # '\r' + 14: 255, # '\x0e' + 15: 255, # '\x0f' + 16: 255, # '\x10' + 17: 255, # '\x11' + 18: 255, # '\x12' + 19: 255, # '\x13' + 20: 255, # '\x14' + 21: 255, # '\x15' + 22: 255, # '\x16' + 23: 255, # '\x17' + 24: 255, # '\x18' + 25: 255, # '\x19' + 26: 255, # '\x1a' + 27: 255, # '\x1b' + 28: 255, # '\x1c' + 29: 255, # '\x1d' + 30: 255, # '\x1e' + 31: 255, # '\x1f' + 32: 253, # ' ' + 33: 253, # '!' + 34: 253, # '"' + 35: 253, # '#' + 36: 253, # '$' + 37: 253, # '%' + 38: 253, # '&' + 39: 253, # "'" + 40: 253, # '(' + 41: 253, # ')' + 42: 253, # '*' + 43: 253, # '+' + 44: 253, # ',' + 45: 253, # '-' + 46: 253, # '.' + 47: 253, # '/' + 48: 252, # '0' + 49: 252, # '1' + 50: 252, # '2' + 51: 252, # '3' + 52: 252, # '4' + 53: 252, # '5' + 54: 252, # '6' + 55: 252, # '7' + 56: 252, # '8' + 57: 252, # '9' + 58: 253, # ':' + 59: 253, # ';' + 60: 253, # '<' + 61: 253, # '=' + 62: 253, # '>' + 63: 253, # '?' + 64: 253, # '@' + 65: 77, # 'A' + 66: 90, # 'B' + 67: 99, # 'C' + 68: 100, # 'D' + 69: 72, # 'E' + 70: 109, # 'F' + 71: 107, # 'G' + 72: 101, # 'H' + 73: 79, # 'I' + 74: 185, # 'J' + 75: 81, # 'K' + 76: 102, # 'L' + 77: 76, # 'M' + 78: 94, # 'N' + 79: 82, # 'O' + 80: 110, # 'P' + 81: 186, # 'Q' + 82: 108, # 'R' + 83: 91, # 'S' + 84: 74, # 'T' + 85: 119, # 'U' + 86: 84, # 'V' + 87: 96, # 'W' + 88: 111, # 'X' + 89: 187, # 'Y' + 90: 115, # 'Z' + 91: 253, # '[' + 92: 253, # '\\' + 93: 253, # ']' + 94: 253, # '^' + 95: 253, # '_' + 96: 253, # '`' + 97: 65, # 'a' + 98: 69, # 'b' + 99: 70, # 'c' + 100: 66, # 'd' + 101: 63, # 'e' + 102: 68, # 'f' + 103: 112, # 'g' + 104: 103, # 'h' + 105: 92, # 'i' + 106: 194, # 'j' + 107: 104, # 'k' + 108: 95, # 'l' + 109: 86, # 'm' + 110: 87, # 'n' + 111: 71, # 'o' + 112: 116, # 'p' + 113: 195, # 'q' + 114: 85, # 'r' + 115: 93, # 's' + 116: 97, # 't' + 117: 113, # 'u' + 118: 196, # 'v' + 119: 197, # 'w' + 120: 198, # 'x' + 121: 199, # 'y' + 122: 200, # 'z' + 123: 253, # '{' + 124: 253, # '|' + 125: 253, # '}' + 126: 253, # '~' + 127: 253, # '\x7f' + 128: 194, # '\x80' + 129: 195, # '\x81' + 130: 196, # '\x82' + 131: 197, # '\x83' + 132: 198, # '\x84' + 133: 199, # '\x85' + 134: 200, # '\x86' + 135: 201, # '\x87' + 136: 202, # '\x88' + 137: 203, # '\x89' + 138: 204, # '\x8a' + 139: 205, # '\x8b' + 140: 206, # '\x8c' + 141: 207, # '\x8d' + 142: 208, # '\x8e' + 143: 209, # '\x8f' + 144: 210, # '\x90' + 145: 211, # '\x91' + 146: 212, # '\x92' + 147: 213, # '\x93' + 148: 214, # '\x94' + 149: 215, # '\x95' + 150: 216, # '\x96' + 151: 217, # '\x97' + 152: 218, # '\x98' + 153: 219, # '\x99' + 154: 220, # '\x9a' + 155: 221, # '\x9b' + 156: 222, # '\x9c' + 157: 223, # '\x9d' + 158: 224, # '\x9e' + 159: 225, # '\x9f' + 160: 81, # '\xa0' + 161: 226, # 'Ð' + 162: 227, # 'Ђ' + 163: 228, # 'Ѓ' + 164: 229, # 'Є' + 165: 230, # 'Ð…' + 166: 105, # 'І' + 167: 231, # 'Ї' + 168: 232, # 'Ј' + 169: 233, # 'Љ' + 170: 234, # 'Њ' + 171: 235, # 'Ћ' + 172: 236, # 'ÐŒ' + 173: 45, # '\xad' + 174: 237, # 'ÐŽ' + 175: 238, # 'Ð' + 176: 31, # 'Ð' + 177: 32, # 'Б' + 178: 35, # 'Ð’' + 179: 43, # 'Г' + 180: 37, # 'Д' + 181: 44, # 'Е' + 182: 55, # 'Ж' + 183: 47, # 'З' + 184: 40, # 'И' + 185: 59, # 'Й' + 186: 33, # 'К' + 187: 46, # 'Л' + 188: 38, # 'Ðœ' + 189: 36, # 'Ð' + 190: 41, # 'О' + 191: 30, # 'П' + 192: 39, # 'Р' + 193: 28, # 'С' + 194: 34, # 'Т' + 195: 51, # 'У' + 196: 48, # 'Ф' + 197: 49, # 'Ð¥' + 198: 53, # 'Ц' + 199: 50, # 'Ч' + 200: 54, # 'Ш' + 201: 57, # 'Щ' + 202: 61, # 'Ъ' + 203: 239, # 'Ы' + 204: 67, # 'Ь' + 205: 240, # 'Э' + 206: 60, # 'Ю' + 207: 56, # 'Я' + 208: 1, # 'а' + 209: 18, # 'б' + 210: 9, # 'в' + 211: 20, # 'г' + 212: 11, # 'д' + 213: 3, # 'е' + 214: 23, # 'ж' + 215: 15, # 'з' + 216: 2, # 'и' + 217: 26, # 'й' + 218: 12, # 'к' + 219: 10, # 'л' + 220: 14, # 'м' + 221: 6, # 'н' + 222: 4, # 'о' + 223: 13, # 'п' + 224: 7, # 'Ñ€' + 225: 8, # 'Ñ' + 226: 5, # 'Ñ‚' + 227: 19, # 'у' + 228: 29, # 'Ñ„' + 229: 25, # 'Ñ…' + 230: 22, # 'ц' + 231: 21, # 'ч' + 232: 27, # 'ш' + 233: 24, # 'щ' + 234: 17, # 'ÑŠ' + 235: 75, # 'Ñ‹' + 236: 52, # 'ÑŒ' + 237: 241, # 'Ñ' + 238: 42, # 'ÑŽ' + 239: 16, # 'Ñ' + 240: 62, # 'â„–' + 241: 242, # 'Ñ‘' + 242: 243, # 'Ñ’' + 243: 244, # 'Ñ“' + 244: 58, # 'Ñ”' + 245: 245, # 'Ñ•' + 246: 98, # 'Ñ–' + 247: 246, # 'Ñ—' + 248: 247, # 'ј' + 249: 248, # 'Ñ™' + 250: 249, # 'Ñš' + 251: 250, # 'Ñ›' + 252: 251, # 'Ñœ' + 253: 91, # '§' + 254: 252, # 'Ñž' + 255: 253, # 'ÑŸ' +} + +ISO_8859_5_BULGARIAN_MODEL = SingleByteCharSetModel(charset_name='ISO-8859-5', + language='Bulgarian', + char_to_order_map=ISO_8859_5_BULGARIAN_CHAR_TO_ORDER, + language_model=BULGARIAN_LANG_MODEL, + typical_positive_ratio=0.969392, + keep_ascii_letters=False, + alphabet='ÐБВГДЕЖЗИЙКЛМÐОПРСТУФХЦЧШЩЪЬЮЯабвгдежзийклмнопрÑтуфхцчшщъьюÑ') + +WINDOWS_1251_BULGARIAN_CHAR_TO_ORDER = { + 0: 255, # '\x00' + 1: 255, # '\x01' + 2: 255, # '\x02' + 3: 255, # '\x03' + 4: 255, # '\x04' + 5: 255, # '\x05' + 6: 255, # '\x06' + 7: 255, # '\x07' + 8: 255, # '\x08' + 9: 255, # '\t' + 10: 254, # '\n' + 11: 255, # '\x0b' + 12: 255, # '\x0c' + 13: 254, # '\r' + 14: 255, # '\x0e' + 15: 255, # '\x0f' + 16: 255, # '\x10' + 17: 255, # '\x11' + 18: 255, # '\x12' + 19: 255, # '\x13' + 20: 255, # '\x14' + 21: 255, # '\x15' + 22: 255, # '\x16' + 23: 255, # '\x17' + 24: 255, # '\x18' + 25: 255, # '\x19' + 26: 255, # '\x1a' + 27: 255, # '\x1b' + 28: 255, # '\x1c' + 29: 255, # '\x1d' + 30: 255, # '\x1e' + 31: 255, # '\x1f' + 32: 253, # ' ' + 33: 253, # '!' + 34: 253, # '"' + 35: 253, # '#' + 36: 253, # '$' + 37: 253, # '%' + 38: 253, # '&' + 39: 253, # "'" + 40: 253, # '(' + 41: 253, # ')' + 42: 253, # '*' + 43: 253, # '+' + 44: 253, # ',' + 45: 253, # '-' + 46: 253, # '.' + 47: 253, # '/' + 48: 252, # '0' + 49: 252, # '1' + 50: 252, # '2' + 51: 252, # '3' + 52: 252, # '4' + 53: 252, # '5' + 54: 252, # '6' + 55: 252, # '7' + 56: 252, # '8' + 57: 252, # '9' + 58: 253, # ':' + 59: 253, # ';' + 60: 253, # '<' + 61: 253, # '=' + 62: 253, # '>' + 63: 253, # '?' + 64: 253, # '@' + 65: 77, # 'A' + 66: 90, # 'B' + 67: 99, # 'C' + 68: 100, # 'D' + 69: 72, # 'E' + 70: 109, # 'F' + 71: 107, # 'G' + 72: 101, # 'H' + 73: 79, # 'I' + 74: 185, # 'J' + 75: 81, # 'K' + 76: 102, # 'L' + 77: 76, # 'M' + 78: 94, # 'N' + 79: 82, # 'O' + 80: 110, # 'P' + 81: 186, # 'Q' + 82: 108, # 'R' + 83: 91, # 'S' + 84: 74, # 'T' + 85: 119, # 'U' + 86: 84, # 'V' + 87: 96, # 'W' + 88: 111, # 'X' + 89: 187, # 'Y' + 90: 115, # 'Z' + 91: 253, # '[' + 92: 253, # '\\' + 93: 253, # ']' + 94: 253, # '^' + 95: 253, # '_' + 96: 253, # '`' + 97: 65, # 'a' + 98: 69, # 'b' + 99: 70, # 'c' + 100: 66, # 'd' + 101: 63, # 'e' + 102: 68, # 'f' + 103: 112, # 'g' + 104: 103, # 'h' + 105: 92, # 'i' + 106: 194, # 'j' + 107: 104, # 'k' + 108: 95, # 'l' + 109: 86, # 'm' + 110: 87, # 'n' + 111: 71, # 'o' + 112: 116, # 'p' + 113: 195, # 'q' + 114: 85, # 'r' + 115: 93, # 's' + 116: 97, # 't' + 117: 113, # 'u' + 118: 196, # 'v' + 119: 197, # 'w' + 120: 198, # 'x' + 121: 199, # 'y' + 122: 200, # 'z' + 123: 253, # '{' + 124: 253, # '|' + 125: 253, # '}' + 126: 253, # '~' + 127: 253, # '\x7f' + 128: 206, # 'Ђ' + 129: 207, # 'Ѓ' + 130: 208, # '‚' + 131: 209, # 'Ñ“' + 132: 210, # '„' + 133: 211, # '…' + 134: 212, # '†' + 135: 213, # '‡' + 136: 120, # '€' + 137: 214, # '‰' + 138: 215, # 'Љ' + 139: 216, # '‹' + 140: 217, # 'Њ' + 141: 218, # 'ÐŒ' + 142: 219, # 'Ћ' + 143: 220, # 'Ð' + 144: 221, # 'Ñ’' + 145: 78, # '‘' + 146: 64, # '’' + 147: 83, # '“' + 148: 121, # 'â€' + 149: 98, # '•' + 150: 117, # '–' + 151: 105, # '—' + 152: 222, # None + 153: 223, # 'â„¢' + 154: 224, # 'Ñ™' + 155: 225, # '›' + 156: 226, # 'Ñš' + 157: 227, # 'Ñœ' + 158: 228, # 'Ñ›' + 159: 229, # 'ÑŸ' + 160: 88, # '\xa0' + 161: 230, # 'ÐŽ' + 162: 231, # 'Ñž' + 163: 232, # 'Ј' + 164: 233, # '¤' + 165: 122, # 'Ò' + 166: 89, # '¦' + 167: 106, # '§' + 168: 234, # 'Ð' + 169: 235, # '©' + 170: 236, # 'Є' + 171: 237, # '«' + 172: 238, # '¬' + 173: 45, # '\xad' + 174: 239, # '®' + 175: 240, # 'Ї' + 176: 73, # '°' + 177: 80, # '±' + 178: 118, # 'І' + 179: 114, # 'Ñ–' + 180: 241, # 'Ò‘' + 181: 242, # 'µ' + 182: 243, # '¶' + 183: 244, # '·' + 184: 245, # 'Ñ‘' + 185: 62, # 'â„–' + 186: 58, # 'Ñ”' + 187: 246, # '»' + 188: 247, # 'ј' + 189: 248, # 'Ð…' + 190: 249, # 'Ñ•' + 191: 250, # 'Ñ—' + 192: 31, # 'Ð' + 193: 32, # 'Б' + 194: 35, # 'Ð’' + 195: 43, # 'Г' + 196: 37, # 'Д' + 197: 44, # 'Е' + 198: 55, # 'Ж' + 199: 47, # 'З' + 200: 40, # 'И' + 201: 59, # 'Й' + 202: 33, # 'К' + 203: 46, # 'Л' + 204: 38, # 'Ðœ' + 205: 36, # 'Ð' + 206: 41, # 'О' + 207: 30, # 'П' + 208: 39, # 'Р' + 209: 28, # 'С' + 210: 34, # 'Т' + 211: 51, # 'У' + 212: 48, # 'Ф' + 213: 49, # 'Ð¥' + 214: 53, # 'Ц' + 215: 50, # 'Ч' + 216: 54, # 'Ш' + 217: 57, # 'Щ' + 218: 61, # 'Ъ' + 219: 251, # 'Ы' + 220: 67, # 'Ь' + 221: 252, # 'Э' + 222: 60, # 'Ю' + 223: 56, # 'Я' + 224: 1, # 'а' + 225: 18, # 'б' + 226: 9, # 'в' + 227: 20, # 'г' + 228: 11, # 'д' + 229: 3, # 'е' + 230: 23, # 'ж' + 231: 15, # 'з' + 232: 2, # 'и' + 233: 26, # 'й' + 234: 12, # 'к' + 235: 10, # 'л' + 236: 14, # 'м' + 237: 6, # 'н' + 238: 4, # 'о' + 239: 13, # 'п' + 240: 7, # 'Ñ€' + 241: 8, # 'Ñ' + 242: 5, # 'Ñ‚' + 243: 19, # 'у' + 244: 29, # 'Ñ„' + 245: 25, # 'Ñ…' + 246: 22, # 'ц' + 247: 21, # 'ч' + 248: 27, # 'ш' + 249: 24, # 'щ' + 250: 17, # 'ÑŠ' + 251: 75, # 'Ñ‹' + 252: 52, # 'ÑŒ' + 253: 253, # 'Ñ' + 254: 42, # 'ÑŽ' + 255: 16, # 'Ñ' +} + +WINDOWS_1251_BULGARIAN_MODEL = SingleByteCharSetModel(charset_name='windows-1251', + language='Bulgarian', + char_to_order_map=WINDOWS_1251_BULGARIAN_CHAR_TO_ORDER, + language_model=BULGARIAN_LANG_MODEL, + typical_positive_ratio=0.969392, + keep_ascii_letters=False, + alphabet='ÐБВГДЕЖЗИЙКЛМÐОПРСТУФХЦЧШЩЪЬЮЯабвгдежзийклмнопрÑтуфхцчшщъьюÑ') + diff --git a/venv/Lib/site-packages/pip/_vendor/chardet/langgreekmodel.py b/venv/Lib/site-packages/pip/_vendor/chardet/langgreekmodel.py new file mode 100644 index 0000000..d99528e --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/chardet/langgreekmodel.py @@ -0,0 +1,4398 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +from pip._vendor.chardet.sbcharsetprober import SingleByteCharSetModel + + +# 3: Positive +# 2: Likely +# 1: Unlikely +# 0: Negative + +GREEK_LANG_MODEL = { + 60: { # 'e' + 60: 2, # 'e' + 55: 1, # 'o' + 58: 2, # 't' + 36: 1, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'ÎŒ' + 31: 0, # 'Α' + 51: 0, # 'Î’' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Îœ' + 49: 0, # 'Î' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Î¥' + 56: 0, # 'Φ' + 50: 1, # 'Χ' + 57: 0, # 'Ω' + 17: 0, # 'ά' + 18: 0, # 'έ' + 22: 0, # 'ή' + 15: 0, # 'ί' + 1: 0, # 'α' + 29: 0, # 'β' + 20: 0, # 'γ' + 21: 0, # 'δ' + 3: 0, # 'ε' + 32: 0, # 'ζ' + 13: 0, # 'η' + 25: 0, # 'θ' + 5: 0, # 'ι' + 11: 0, # 'κ' + 16: 0, # 'λ' + 10: 0, # 'μ' + 6: 0, # 'ν' + 30: 0, # 'ξ' + 4: 0, # 'ο' + 9: 0, # 'Ï€' + 8: 0, # 'Ï' + 14: 0, # 'Ï‚' + 7: 0, # 'σ' + 2: 0, # 'Ï„' + 12: 0, # 'Ï…' + 28: 0, # 'φ' + 23: 0, # 'χ' + 42: 0, # 'ψ' + 24: 0, # 'ω' + 19: 0, # 'ÏŒ' + 26: 0, # 'Ï' + 27: 0, # 'ÏŽ' + }, + 55: { # 'o' + 60: 0, # 'e' + 55: 2, # 'o' + 58: 2, # 't' + 36: 1, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'ÎŒ' + 31: 0, # 'Α' + 51: 0, # 'Î’' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Îœ' + 49: 0, # 'Î' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Î¥' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 0, # 'ά' + 18: 0, # 'έ' + 22: 0, # 'ή' + 15: 0, # 'ί' + 1: 0, # 'α' + 29: 0, # 'β' + 20: 0, # 'γ' + 21: 0, # 'δ' + 3: 0, # 'ε' + 32: 0, # 'ζ' + 13: 0, # 'η' + 25: 0, # 'θ' + 5: 0, # 'ι' + 11: 0, # 'κ' + 16: 0, # 'λ' + 10: 0, # 'μ' + 6: 1, # 'ν' + 30: 0, # 'ξ' + 4: 0, # 'ο' + 9: 0, # 'Ï€' + 8: 0, # 'Ï' + 14: 0, # 'Ï‚' + 7: 0, # 'σ' + 2: 0, # 'Ï„' + 12: 1, # 'Ï…' + 28: 0, # 'φ' + 23: 0, # 'χ' + 42: 0, # 'ψ' + 24: 0, # 'ω' + 19: 0, # 'ÏŒ' + 26: 0, # 'Ï' + 27: 0, # 'ÏŽ' + }, + 58: { # 't' + 60: 2, # 'e' + 55: 1, # 'o' + 58: 1, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'ÎŒ' + 31: 0, # 'Α' + 51: 0, # 'Î’' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Îœ' + 49: 0, # 'Î' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Î¥' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 2, # 'ά' + 18: 0, # 'έ' + 22: 0, # 'ή' + 15: 0, # 'ί' + 1: 0, # 'α' + 29: 0, # 'β' + 20: 0, # 'γ' + 21: 0, # 'δ' + 3: 0, # 'ε' + 32: 0, # 'ζ' + 13: 0, # 'η' + 25: 0, # 'θ' + 5: 0, # 'ι' + 11: 0, # 'κ' + 16: 0, # 'λ' + 10: 0, # 'μ' + 6: 0, # 'ν' + 30: 0, # 'ξ' + 4: 1, # 'ο' + 9: 0, # 'Ï€' + 8: 0, # 'Ï' + 14: 0, # 'Ï‚' + 7: 0, # 'σ' + 2: 0, # 'Ï„' + 12: 0, # 'Ï…' + 28: 0, # 'φ' + 23: 0, # 'χ' + 42: 0, # 'ψ' + 24: 0, # 'ω' + 19: 0, # 'ÏŒ' + 26: 0, # 'Ï' + 27: 0, # 'ÏŽ' + }, + 36: { # '·' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'ÎŒ' + 31: 0, # 'Α' + 51: 0, # 'Î’' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Îœ' + 49: 0, # 'Î' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Î¥' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 0, # 'ά' + 18: 0, # 'έ' + 22: 0, # 'ή' + 15: 0, # 'ί' + 1: 0, # 'α' + 29: 0, # 'β' + 20: 0, # 'γ' + 21: 0, # 'δ' + 3: 0, # 'ε' + 32: 0, # 'ζ' + 13: 0, # 'η' + 25: 0, # 'θ' + 5: 0, # 'ι' + 11: 0, # 'κ' + 16: 0, # 'λ' + 10: 0, # 'μ' + 6: 0, # 'ν' + 30: 0, # 'ξ' + 4: 0, # 'ο' + 9: 0, # 'Ï€' + 8: 0, # 'Ï' + 14: 0, # 'Ï‚' + 7: 0, # 'σ' + 2: 0, # 'Ï„' + 12: 0, # 'Ï…' + 28: 0, # 'φ' + 23: 0, # 'χ' + 42: 0, # 'ψ' + 24: 0, # 'ω' + 19: 0, # 'ÏŒ' + 26: 0, # 'Ï' + 27: 0, # 'ÏŽ' + }, + 61: { # 'Ά' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'ÎŒ' + 31: 0, # 'Α' + 51: 0, # 'Î’' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Îœ' + 49: 0, # 'Î' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Î¥' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 0, # 'ά' + 18: 0, # 'έ' + 22: 0, # 'ή' + 15: 0, # 'ί' + 1: 0, # 'α' + 29: 0, # 'β' + 20: 1, # 'γ' + 21: 2, # 'δ' + 3: 0, # 'ε' + 32: 0, # 'ζ' + 13: 0, # 'η' + 25: 0, # 'θ' + 5: 0, # 'ι' + 11: 0, # 'κ' + 16: 2, # 'λ' + 10: 0, # 'μ' + 6: 0, # 'ν' + 30: 0, # 'ξ' + 4: 0, # 'ο' + 9: 1, # 'Ï€' + 8: 2, # 'Ï' + 14: 0, # 'Ï‚' + 7: 0, # 'σ' + 2: 0, # 'Ï„' + 12: 0, # 'Ï…' + 28: 0, # 'φ' + 23: 0, # 'χ' + 42: 0, # 'ψ' + 24: 0, # 'ω' + 19: 0, # 'ÏŒ' + 26: 0, # 'Ï' + 27: 0, # 'ÏŽ' + }, + 46: { # 'Έ' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'ÎŒ' + 31: 0, # 'Α' + 51: 0, # 'Î’' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Îœ' + 49: 0, # 'Î' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Î¥' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 0, # 'ά' + 18: 0, # 'έ' + 22: 0, # 'ή' + 15: 0, # 'ί' + 1: 0, # 'α' + 29: 2, # 'β' + 20: 2, # 'γ' + 21: 0, # 'δ' + 3: 0, # 'ε' + 32: 0, # 'ζ' + 13: 0, # 'η' + 25: 0, # 'θ' + 5: 0, # 'ι' + 11: 2, # 'κ' + 16: 2, # 'λ' + 10: 0, # 'μ' + 6: 3, # 'ν' + 30: 2, # 'ξ' + 4: 0, # 'ο' + 9: 2, # 'Ï€' + 8: 2, # 'Ï' + 14: 0, # 'Ï‚' + 7: 1, # 'σ' + 2: 2, # 'Ï„' + 12: 0, # 'Ï…' + 28: 2, # 'φ' + 23: 3, # 'χ' + 42: 0, # 'ψ' + 24: 0, # 'ω' + 19: 0, # 'ÏŒ' + 26: 0, # 'Ï' + 27: 0, # 'ÏŽ' + }, + 54: { # 'ÎŒ' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'ÎŒ' + 31: 0, # 'Α' + 51: 0, # 'Î’' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Îœ' + 49: 0, # 'Î' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Î¥' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 0, # 'ά' + 18: 0, # 'έ' + 22: 0, # 'ή' + 15: 0, # 'ί' + 1: 0, # 'α' + 29: 0, # 'β' + 20: 0, # 'γ' + 21: 0, # 'δ' + 3: 0, # 'ε' + 32: 0, # 'ζ' + 13: 0, # 'η' + 25: 0, # 'θ' + 5: 0, # 'ι' + 11: 0, # 'κ' + 16: 2, # 'λ' + 10: 2, # 'μ' + 6: 2, # 'ν' + 30: 0, # 'ξ' + 4: 0, # 'ο' + 9: 2, # 'Ï€' + 8: 0, # 'Ï' + 14: 0, # 'Ï‚' + 7: 2, # 'σ' + 2: 3, # 'Ï„' + 12: 0, # 'Ï…' + 28: 0, # 'φ' + 23: 2, # 'χ' + 42: 0, # 'ψ' + 24: 0, # 'ω' + 19: 0, # 'ÏŒ' + 26: 0, # 'Ï' + 27: 0, # 'ÏŽ' + }, + 31: { # 'Α' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'ÎŒ' + 31: 0, # 'Α' + 51: 2, # 'Î’' + 43: 2, # 'Γ' + 41: 1, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 2, # 'Θ' + 47: 2, # 'Ι' + 44: 2, # 'Κ' + 53: 2, # 'Λ' + 38: 2, # 'Îœ' + 49: 2, # 'Î' + 59: 1, # 'Ξ' + 39: 0, # 'Ο' + 35: 2, # 'Π' + 48: 2, # 'Ρ' + 37: 2, # 'Σ' + 33: 2, # 'Τ' + 45: 2, # 'Î¥' + 56: 2, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 0, # 'ά' + 18: 0, # 'έ' + 22: 0, # 'ή' + 15: 0, # 'ί' + 1: 0, # 'α' + 29: 0, # 'β' + 20: 2, # 'γ' + 21: 0, # 'δ' + 3: 0, # 'ε' + 32: 0, # 'ζ' + 13: 0, # 'η' + 25: 1, # 'θ' + 5: 0, # 'ι' + 11: 2, # 'κ' + 16: 3, # 'λ' + 10: 2, # 'μ' + 6: 3, # 'ν' + 30: 2, # 'ξ' + 4: 0, # 'ο' + 9: 3, # 'Ï€' + 8: 3, # 'Ï' + 14: 2, # 'Ï‚' + 7: 2, # 'σ' + 2: 0, # 'Ï„' + 12: 3, # 'Ï…' + 28: 2, # 'φ' + 23: 0, # 'χ' + 42: 0, # 'ψ' + 24: 0, # 'ω' + 19: 0, # 'ÏŒ' + 26: 2, # 'Ï' + 27: 0, # 'ÏŽ' + }, + 51: { # 'Î’' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'ÎŒ' + 31: 2, # 'Α' + 51: 0, # 'Î’' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 1, # 'Ε' + 40: 1, # 'Η' + 52: 0, # 'Θ' + 47: 1, # 'Ι' + 44: 0, # 'Κ' + 53: 1, # 'Λ' + 38: 0, # 'Îœ' + 49: 0, # 'Î' + 59: 0, # 'Ξ' + 39: 2, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Î¥' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 2, # 'ά' + 18: 2, # 'έ' + 22: 2, # 'ή' + 15: 0, # 'ί' + 1: 2, # 'α' + 29: 0, # 'β' + 20: 0, # 'γ' + 21: 0, # 'δ' + 3: 2, # 'ε' + 32: 0, # 'ζ' + 13: 0, # 'η' + 25: 0, # 'θ' + 5: 2, # 'ι' + 11: 0, # 'κ' + 16: 2, # 'λ' + 10: 0, # 'μ' + 6: 0, # 'ν' + 30: 0, # 'ξ' + 4: 2, # 'ο' + 9: 0, # 'Ï€' + 8: 2, # 'Ï' + 14: 0, # 'Ï‚' + 7: 0, # 'σ' + 2: 0, # 'Ï„' + 12: 0, # 'Ï…' + 28: 0, # 'φ' + 23: 0, # 'χ' + 42: 0, # 'ψ' + 24: 0, # 'ω' + 19: 0, # 'ÏŒ' + 26: 0, # 'Ï' + 27: 0, # 'ÏŽ' + }, + 43: { # 'Γ' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'ÎŒ' + 31: 1, # 'Α' + 51: 0, # 'Î’' + 43: 2, # 'Γ' + 41: 0, # 'Δ' + 34: 2, # 'Ε' + 40: 1, # 'Η' + 52: 0, # 'Θ' + 47: 2, # 'Ι' + 44: 1, # 'Κ' + 53: 1, # 'Λ' + 38: 0, # 'Îœ' + 49: 0, # 'Î' + 59: 0, # 'Ξ' + 39: 1, # 'Ο' + 35: 0, # 'Π' + 48: 2, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 2, # 'Î¥' + 56: 0, # 'Φ' + 50: 1, # 'Χ' + 57: 2, # 'Ω' + 17: 0, # 'ά' + 18: 0, # 'έ' + 22: 0, # 'ή' + 15: 2, # 'ί' + 1: 2, # 'α' + 29: 0, # 'β' + 20: 0, # 'γ' + 21: 0, # 'δ' + 3: 2, # 'ε' + 32: 0, # 'ζ' + 13: 0, # 'η' + 25: 0, # 'θ' + 5: 3, # 'ι' + 11: 0, # 'κ' + 16: 2, # 'λ' + 10: 0, # 'μ' + 6: 2, # 'ν' + 30: 0, # 'ξ' + 4: 0, # 'ο' + 9: 0, # 'Ï€' + 8: 2, # 'Ï' + 14: 0, # 'Ï‚' + 7: 0, # 'σ' + 2: 0, # 'Ï„' + 12: 0, # 'Ï…' + 28: 0, # 'φ' + 23: 0, # 'χ' + 42: 0, # 'ψ' + 24: 0, # 'ω' + 19: 0, # 'ÏŒ' + 26: 0, # 'Ï' + 27: 0, # 'ÏŽ' + }, + 41: { # 'Δ' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'ÎŒ' + 31: 0, # 'Α' + 51: 0, # 'Î’' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 2, # 'Ε' + 40: 2, # 'Η' + 52: 0, # 'Θ' + 47: 2, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Îœ' + 49: 0, # 'Î' + 59: 0, # 'Ξ' + 39: 2, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Î¥' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 2, # 'Ω' + 17: 0, # 'ά' + 18: 0, # 'έ' + 22: 2, # 'ή' + 15: 2, # 'ί' + 1: 0, # 'α' + 29: 0, # 'β' + 20: 0, # 'γ' + 21: 0, # 'δ' + 3: 3, # 'ε' + 32: 0, # 'ζ' + 13: 2, # 'η' + 25: 0, # 'θ' + 5: 3, # 'ι' + 11: 0, # 'κ' + 16: 0, # 'λ' + 10: 0, # 'μ' + 6: 0, # 'ν' + 30: 0, # 'ξ' + 4: 2, # 'ο' + 9: 0, # 'Ï€' + 8: 2, # 'Ï' + 14: 0, # 'Ï‚' + 7: 0, # 'σ' + 2: 0, # 'Ï„' + 12: 2, # 'Ï…' + 28: 0, # 'φ' + 23: 0, # 'χ' + 42: 0, # 'ψ' + 24: 2, # 'ω' + 19: 1, # 'ÏŒ' + 26: 2, # 'Ï' + 27: 2, # 'ÏŽ' + }, + 34: { # 'Ε' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'ÎŒ' + 31: 2, # 'Α' + 51: 0, # 'Î’' + 43: 2, # 'Γ' + 41: 2, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 2, # 'Ι' + 44: 2, # 'Κ' + 53: 2, # 'Λ' + 38: 2, # 'Îœ' + 49: 2, # 'Î' + 59: 1, # 'Ξ' + 39: 0, # 'Ο' + 35: 2, # 'Π' + 48: 2, # 'Ρ' + 37: 2, # 'Σ' + 33: 2, # 'Τ' + 45: 2, # 'Î¥' + 56: 0, # 'Φ' + 50: 2, # 'Χ' + 57: 2, # 'Ω' + 17: 3, # 'ά' + 18: 0, # 'έ' + 22: 0, # 'ή' + 15: 3, # 'ί' + 1: 0, # 'α' + 29: 0, # 'β' + 20: 3, # 'γ' + 21: 2, # 'δ' + 3: 1, # 'ε' + 32: 0, # 'ζ' + 13: 0, # 'η' + 25: 1, # 'θ' + 5: 2, # 'ι' + 11: 3, # 'κ' + 16: 3, # 'λ' + 10: 2, # 'μ' + 6: 3, # 'ν' + 30: 2, # 'ξ' + 4: 0, # 'ο' + 9: 3, # 'Ï€' + 8: 2, # 'Ï' + 14: 0, # 'Ï‚' + 7: 2, # 'σ' + 2: 2, # 'Ï„' + 12: 2, # 'Ï…' + 28: 2, # 'φ' + 23: 0, # 'χ' + 42: 0, # 'ψ' + 24: 0, # 'ω' + 19: 0, # 'ÏŒ' + 26: 1, # 'Ï' + 27: 0, # 'ÏŽ' + }, + 40: { # 'Η' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'ÎŒ' + 31: 0, # 'Α' + 51: 0, # 'Î’' + 43: 1, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 2, # 'Θ' + 47: 0, # 'Ι' + 44: 2, # 'Κ' + 53: 0, # 'Λ' + 38: 2, # 'Îœ' + 49: 2, # 'Î' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 2, # 'Π' + 48: 2, # 'Ρ' + 37: 2, # 'Σ' + 33: 2, # 'Τ' + 45: 1, # 'Î¥' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 0, # 'ά' + 18: 0, # 'έ' + 22: 0, # 'ή' + 15: 0, # 'ί' + 1: 0, # 'α' + 29: 0, # 'β' + 20: 0, # 'γ' + 21: 0, # 'δ' + 3: 0, # 'ε' + 32: 0, # 'ζ' + 13: 0, # 'η' + 25: 0, # 'θ' + 5: 0, # 'ι' + 11: 0, # 'κ' + 16: 2, # 'λ' + 10: 0, # 'μ' + 6: 1, # 'ν' + 30: 0, # 'ξ' + 4: 0, # 'ο' + 9: 0, # 'Ï€' + 8: 0, # 'Ï' + 14: 0, # 'Ï‚' + 7: 0, # 'σ' + 2: 0, # 'Ï„' + 12: 0, # 'Ï…' + 28: 0, # 'φ' + 23: 1, # 'χ' + 42: 0, # 'ψ' + 24: 0, # 'ω' + 19: 0, # 'ÏŒ' + 26: 0, # 'Ï' + 27: 0, # 'ÏŽ' + }, + 52: { # 'Θ' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'ÎŒ' + 31: 2, # 'Α' + 51: 0, # 'Î’' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 2, # 'Ε' + 40: 2, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Îœ' + 49: 0, # 'Î' + 59: 0, # 'Ξ' + 39: 2, # 'Ο' + 35: 0, # 'Π' + 48: 1, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 1, # 'Î¥' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 0, # 'ά' + 18: 2, # 'έ' + 22: 0, # 'ή' + 15: 0, # 'ί' + 1: 3, # 'α' + 29: 0, # 'β' + 20: 0, # 'γ' + 21: 0, # 'δ' + 3: 2, # 'ε' + 32: 0, # 'ζ' + 13: 0, # 'η' + 25: 0, # 'θ' + 5: 0, # 'ι' + 11: 0, # 'κ' + 16: 0, # 'λ' + 10: 0, # 'μ' + 6: 0, # 'ν' + 30: 0, # 'ξ' + 4: 0, # 'ο' + 9: 0, # 'Ï€' + 8: 0, # 'Ï' + 14: 0, # 'Ï‚' + 7: 0, # 'σ' + 2: 0, # 'Ï„' + 12: 2, # 'Ï…' + 28: 0, # 'φ' + 23: 0, # 'χ' + 42: 0, # 'ψ' + 24: 0, # 'ω' + 19: 0, # 'ÏŒ' + 26: 2, # 'Ï' + 27: 0, # 'ÏŽ' + }, + 47: { # 'Ι' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'ÎŒ' + 31: 2, # 'Α' + 51: 1, # 'Î’' + 43: 1, # 'Γ' + 41: 2, # 'Δ' + 34: 2, # 'Ε' + 40: 2, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 2, # 'Κ' + 53: 2, # 'Λ' + 38: 2, # 'Îœ' + 49: 2, # 'Î' + 59: 0, # 'Ξ' + 39: 2, # 'Ο' + 35: 0, # 'Π' + 48: 2, # 'Ρ' + 37: 2, # 'Σ' + 33: 2, # 'Τ' + 45: 0, # 'Î¥' + 56: 2, # 'Φ' + 50: 0, # 'Χ' + 57: 2, # 'Ω' + 17: 0, # 'ά' + 18: 0, # 'έ' + 22: 0, # 'ή' + 15: 0, # 'ί' + 1: 2, # 'α' + 29: 0, # 'β' + 20: 0, # 'γ' + 21: 2, # 'δ' + 3: 0, # 'ε' + 32: 0, # 'ζ' + 13: 0, # 'η' + 25: 0, # 'θ' + 5: 0, # 'ι' + 11: 0, # 'κ' + 16: 0, # 'λ' + 10: 0, # 'μ' + 6: 1, # 'ν' + 30: 0, # 'ξ' + 4: 2, # 'ο' + 9: 0, # 'Ï€' + 8: 0, # 'Ï' + 14: 0, # 'Ï‚' + 7: 2, # 'σ' + 2: 1, # 'Ï„' + 12: 0, # 'Ï…' + 28: 0, # 'φ' + 23: 0, # 'χ' + 42: 0, # 'ψ' + 24: 1, # 'ω' + 19: 0, # 'ÏŒ' + 26: 0, # 'Ï' + 27: 0, # 'ÏŽ' + }, + 44: { # 'Κ' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'ÎŒ' + 31: 2, # 'Α' + 51: 0, # 'Î’' + 43: 0, # 'Γ' + 41: 1, # 'Δ' + 34: 2, # 'Ε' + 40: 2, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 1, # 'Îœ' + 49: 0, # 'Î' + 59: 0, # 'Ξ' + 39: 2, # 'Ο' + 35: 0, # 'Π' + 48: 2, # 'Ρ' + 37: 0, # 'Σ' + 33: 1, # 'Τ' + 45: 2, # 'Î¥' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 1, # 'Ω' + 17: 3, # 'ά' + 18: 0, # 'έ' + 22: 0, # 'ή' + 15: 0, # 'ί' + 1: 3, # 'α' + 29: 0, # 'β' + 20: 0, # 'γ' + 21: 0, # 'δ' + 3: 2, # 'ε' + 32: 0, # 'ζ' + 13: 0, # 'η' + 25: 0, # 'θ' + 5: 2, # 'ι' + 11: 0, # 'κ' + 16: 2, # 'λ' + 10: 0, # 'μ' + 6: 0, # 'ν' + 30: 0, # 'ξ' + 4: 2, # 'ο' + 9: 0, # 'Ï€' + 8: 2, # 'Ï' + 14: 0, # 'Ï‚' + 7: 0, # 'σ' + 2: 0, # 'Ï„' + 12: 2, # 'Ï…' + 28: 0, # 'φ' + 23: 0, # 'χ' + 42: 0, # 'ψ' + 24: 0, # 'ω' + 19: 2, # 'ÏŒ' + 26: 2, # 'Ï' + 27: 2, # 'ÏŽ' + }, + 53: { # 'Λ' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'ÎŒ' + 31: 2, # 'Α' + 51: 0, # 'Î’' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 2, # 'Ε' + 40: 2, # 'Η' + 52: 0, # 'Θ' + 47: 2, # 'Ι' + 44: 0, # 'Κ' + 53: 2, # 'Λ' + 38: 0, # 'Îœ' + 49: 0, # 'Î' + 59: 0, # 'Ξ' + 39: 2, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 2, # 'Σ' + 33: 0, # 'Τ' + 45: 2, # 'Î¥' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 2, # 'Ω' + 17: 2, # 'ά' + 18: 2, # 'έ' + 22: 0, # 'ή' + 15: 2, # 'ί' + 1: 2, # 'α' + 29: 0, # 'β' + 20: 0, # 'γ' + 21: 0, # 'δ' + 3: 2, # 'ε' + 32: 0, # 'ζ' + 13: 0, # 'η' + 25: 0, # 'θ' + 5: 1, # 'ι' + 11: 0, # 'κ' + 16: 0, # 'λ' + 10: 0, # 'μ' + 6: 0, # 'ν' + 30: 0, # 'ξ' + 4: 2, # 'ο' + 9: 0, # 'Ï€' + 8: 0, # 'Ï' + 14: 0, # 'Ï‚' + 7: 0, # 'σ' + 2: 0, # 'Ï„' + 12: 2, # 'Ï…' + 28: 0, # 'φ' + 23: 0, # 'χ' + 42: 0, # 'ψ' + 24: 0, # 'ω' + 19: 2, # 'ÏŒ' + 26: 2, # 'Ï' + 27: 0, # 'ÏŽ' + }, + 38: { # 'Îœ' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'ÎŒ' + 31: 2, # 'Α' + 51: 2, # 'Î’' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 2, # 'Ε' + 40: 2, # 'Η' + 52: 0, # 'Θ' + 47: 2, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 2, # 'Îœ' + 49: 0, # 'Î' + 59: 0, # 'Ξ' + 39: 2, # 'Ο' + 35: 2, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Î¥' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 2, # 'ά' + 18: 2, # 'έ' + 22: 2, # 'ή' + 15: 2, # 'ί' + 1: 2, # 'α' + 29: 0, # 'β' + 20: 0, # 'γ' + 21: 0, # 'δ' + 3: 3, # 'ε' + 32: 0, # 'ζ' + 13: 2, # 'η' + 25: 0, # 'θ' + 5: 3, # 'ι' + 11: 0, # 'κ' + 16: 0, # 'λ' + 10: 0, # 'μ' + 6: 0, # 'ν' + 30: 0, # 'ξ' + 4: 2, # 'ο' + 9: 3, # 'Ï€' + 8: 0, # 'Ï' + 14: 0, # 'Ï‚' + 7: 0, # 'σ' + 2: 0, # 'Ï„' + 12: 2, # 'Ï…' + 28: 0, # 'φ' + 23: 0, # 'χ' + 42: 0, # 'ψ' + 24: 0, # 'ω' + 19: 2, # 'ÏŒ' + 26: 0, # 'Ï' + 27: 0, # 'ÏŽ' + }, + 49: { # 'Î' + 60: 2, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'ÎŒ' + 31: 2, # 'Α' + 51: 0, # 'Î’' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 2, # 'Ε' + 40: 2, # 'Η' + 52: 0, # 'Θ' + 47: 2, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Îœ' + 49: 0, # 'Î' + 59: 0, # 'Ξ' + 39: 2, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 2, # 'Τ' + 45: 0, # 'Î¥' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 2, # 'Ω' + 17: 0, # 'ά' + 18: 2, # 'έ' + 22: 0, # 'ή' + 15: 2, # 'ί' + 1: 2, # 'α' + 29: 0, # 'β' + 20: 0, # 'γ' + 21: 0, # 'δ' + 3: 1, # 'ε' + 32: 0, # 'ζ' + 13: 0, # 'η' + 25: 0, # 'θ' + 5: 0, # 'ι' + 11: 0, # 'κ' + 16: 0, # 'λ' + 10: 0, # 'μ' + 6: 0, # 'ν' + 30: 0, # 'ξ' + 4: 2, # 'ο' + 9: 0, # 'Ï€' + 8: 0, # 'Ï' + 14: 0, # 'Ï‚' + 7: 0, # 'σ' + 2: 0, # 'Ï„' + 12: 0, # 'Ï…' + 28: 0, # 'φ' + 23: 0, # 'χ' + 42: 0, # 'ψ' + 24: 1, # 'ω' + 19: 2, # 'ÏŒ' + 26: 0, # 'Ï' + 27: 0, # 'ÏŽ' + }, + 59: { # 'Ξ' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'ÎŒ' + 31: 0, # 'Α' + 51: 0, # 'Î’' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 1, # 'Ε' + 40: 1, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Îœ' + 49: 0, # 'Î' + 59: 0, # 'Ξ' + 39: 1, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Î¥' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 0, # 'ά' + 18: 2, # 'έ' + 22: 0, # 'ή' + 15: 0, # 'ί' + 1: 2, # 'α' + 29: 0, # 'β' + 20: 0, # 'γ' + 21: 0, # 'δ' + 3: 2, # 'ε' + 32: 0, # 'ζ' + 13: 0, # 'η' + 25: 0, # 'θ' + 5: 0, # 'ι' + 11: 0, # 'κ' + 16: 0, # 'λ' + 10: 0, # 'μ' + 6: 0, # 'ν' + 30: 0, # 'ξ' + 4: 0, # 'ο' + 9: 0, # 'Ï€' + 8: 0, # 'Ï' + 14: 0, # 'Ï‚' + 7: 0, # 'σ' + 2: 0, # 'Ï„' + 12: 0, # 'Ï…' + 28: 0, # 'φ' + 23: 0, # 'χ' + 42: 0, # 'ψ' + 24: 0, # 'ω' + 19: 0, # 'ÏŒ' + 26: 0, # 'Ï' + 27: 0, # 'ÏŽ' + }, + 39: { # 'Ο' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'ÎŒ' + 31: 0, # 'Α' + 51: 1, # 'Î’' + 43: 2, # 'Γ' + 41: 2, # 'Δ' + 34: 2, # 'Ε' + 40: 1, # 'Η' + 52: 2, # 'Θ' + 47: 2, # 'Ι' + 44: 2, # 'Κ' + 53: 2, # 'Λ' + 38: 2, # 'Îœ' + 49: 2, # 'Î' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 2, # 'Π' + 48: 2, # 'Ρ' + 37: 2, # 'Σ' + 33: 2, # 'Τ' + 45: 2, # 'Î¥' + 56: 2, # 'Φ' + 50: 2, # 'Χ' + 57: 0, # 'Ω' + 17: 0, # 'ά' + 18: 0, # 'έ' + 22: 0, # 'ή' + 15: 0, # 'ί' + 1: 0, # 'α' + 29: 0, # 'β' + 20: 0, # 'γ' + 21: 2, # 'δ' + 3: 0, # 'ε' + 32: 0, # 'ζ' + 13: 0, # 'η' + 25: 0, # 'θ' + 5: 3, # 'ι' + 11: 2, # 'κ' + 16: 2, # 'λ' + 10: 2, # 'μ' + 6: 2, # 'ν' + 30: 0, # 'ξ' + 4: 0, # 'ο' + 9: 2, # 'Ï€' + 8: 2, # 'Ï' + 14: 0, # 'Ï‚' + 7: 0, # 'σ' + 2: 2, # 'Ï„' + 12: 2, # 'Ï…' + 28: 1, # 'φ' + 23: 1, # 'χ' + 42: 0, # 'ψ' + 24: 0, # 'ω' + 19: 0, # 'ÏŒ' + 26: 2, # 'Ï' + 27: 0, # 'ÏŽ' + }, + 35: { # 'Π' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'ÎŒ' + 31: 2, # 'Α' + 51: 0, # 'Î’' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 2, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 2, # 'Ι' + 44: 0, # 'Κ' + 53: 2, # 'Λ' + 38: 1, # 'Îœ' + 49: 0, # 'Î' + 59: 0, # 'Ξ' + 39: 2, # 'Ο' + 35: 0, # 'Π' + 48: 2, # 'Ρ' + 37: 0, # 'Σ' + 33: 1, # 'Τ' + 45: 0, # 'Î¥' + 56: 0, # 'Φ' + 50: 1, # 'Χ' + 57: 2, # 'Ω' + 17: 2, # 'ά' + 18: 1, # 'έ' + 22: 1, # 'ή' + 15: 2, # 'ί' + 1: 3, # 'α' + 29: 0, # 'β' + 20: 0, # 'γ' + 21: 0, # 'δ' + 3: 3, # 'ε' + 32: 0, # 'ζ' + 13: 2, # 'η' + 25: 0, # 'θ' + 5: 2, # 'ι' + 11: 0, # 'κ' + 16: 2, # 'λ' + 10: 0, # 'μ' + 6: 2, # 'ν' + 30: 0, # 'ξ' + 4: 3, # 'ο' + 9: 0, # 'Ï€' + 8: 3, # 'Ï' + 14: 0, # 'Ï‚' + 7: 0, # 'σ' + 2: 0, # 'Ï„' + 12: 2, # 'Ï…' + 28: 0, # 'φ' + 23: 2, # 'χ' + 42: 0, # 'ψ' + 24: 2, # 'ω' + 19: 2, # 'ÏŒ' + 26: 0, # 'Ï' + 27: 3, # 'ÏŽ' + }, + 48: { # 'Ρ' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'ÎŒ' + 31: 2, # 'Α' + 51: 0, # 'Î’' + 43: 1, # 'Γ' + 41: 1, # 'Δ' + 34: 2, # 'Ε' + 40: 2, # 'Η' + 52: 0, # 'Θ' + 47: 2, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Îœ' + 49: 2, # 'Î' + 59: 0, # 'Ξ' + 39: 2, # 'Ο' + 35: 0, # 'Π' + 48: 2, # 'Ρ' + 37: 0, # 'Σ' + 33: 1, # 'Τ' + 45: 1, # 'Î¥' + 56: 0, # 'Φ' + 50: 1, # 'Χ' + 57: 1, # 'Ω' + 17: 0, # 'ά' + 18: 0, # 'έ' + 22: 0, # 'ή' + 15: 2, # 'ί' + 1: 0, # 'α' + 29: 0, # 'β' + 20: 0, # 'γ' + 21: 0, # 'δ' + 3: 0, # 'ε' + 32: 0, # 'ζ' + 13: 0, # 'η' + 25: 0, # 'θ' + 5: 0, # 'ι' + 11: 0, # 'κ' + 16: 0, # 'λ' + 10: 0, # 'μ' + 6: 0, # 'ν' + 30: 0, # 'ξ' + 4: 1, # 'ο' + 9: 0, # 'Ï€' + 8: 0, # 'Ï' + 14: 0, # 'Ï‚' + 7: 0, # 'σ' + 2: 0, # 'Ï„' + 12: 3, # 'Ï…' + 28: 0, # 'φ' + 23: 0, # 'χ' + 42: 0, # 'ψ' + 24: 2, # 'ω' + 19: 0, # 'ÏŒ' + 26: 2, # 'Ï' + 27: 0, # 'ÏŽ' + }, + 37: { # 'Σ' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'ÎŒ' + 31: 2, # 'Α' + 51: 0, # 'Î’' + 43: 0, # 'Γ' + 41: 1, # 'Δ' + 34: 2, # 'Ε' + 40: 2, # 'Η' + 52: 0, # 'Θ' + 47: 2, # 'Ι' + 44: 2, # 'Κ' + 53: 0, # 'Λ' + 38: 2, # 'Îœ' + 49: 0, # 'Î' + 59: 0, # 'Ξ' + 39: 2, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 2, # 'Σ' + 33: 2, # 'Τ' + 45: 2, # 'Î¥' + 56: 0, # 'Φ' + 50: 2, # 'Χ' + 57: 2, # 'Ω' + 17: 0, # 'ά' + 18: 0, # 'έ' + 22: 2, # 'ή' + 15: 2, # 'ί' + 1: 2, # 'α' + 29: 2, # 'β' + 20: 0, # 'γ' + 21: 0, # 'δ' + 3: 3, # 'ε' + 32: 0, # 'ζ' + 13: 3, # 'η' + 25: 0, # 'θ' + 5: 2, # 'ι' + 11: 2, # 'κ' + 16: 0, # 'λ' + 10: 0, # 'μ' + 6: 0, # 'ν' + 30: 0, # 'ξ' + 4: 2, # 'ο' + 9: 2, # 'Ï€' + 8: 0, # 'Ï' + 14: 0, # 'Ï‚' + 7: 0, # 'σ' + 2: 3, # 'Ï„' + 12: 3, # 'Ï…' + 28: 0, # 'φ' + 23: 2, # 'χ' + 42: 0, # 'ψ' + 24: 2, # 'ω' + 19: 0, # 'ÏŒ' + 26: 2, # 'Ï' + 27: 2, # 'ÏŽ' + }, + 33: { # 'Τ' + 60: 0, # 'e' + 55: 1, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'ÎŒ' + 31: 2, # 'Α' + 51: 0, # 'Î’' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 2, # 'Ε' + 40: 2, # 'Η' + 52: 0, # 'Θ' + 47: 2, # 'Ι' + 44: 2, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Îœ' + 49: 0, # 'Î' + 59: 0, # 'Ξ' + 39: 2, # 'Ο' + 35: 0, # 'Π' + 48: 2, # 'Ρ' + 37: 0, # 'Σ' + 33: 1, # 'Τ' + 45: 1, # 'Î¥' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 2, # 'Ω' + 17: 2, # 'ά' + 18: 2, # 'έ' + 22: 0, # 'ή' + 15: 2, # 'ί' + 1: 3, # 'α' + 29: 0, # 'β' + 20: 0, # 'γ' + 21: 0, # 'δ' + 3: 2, # 'ε' + 32: 0, # 'ζ' + 13: 2, # 'η' + 25: 0, # 'θ' + 5: 2, # 'ι' + 11: 0, # 'κ' + 16: 0, # 'λ' + 10: 2, # 'μ' + 6: 0, # 'ν' + 30: 0, # 'ξ' + 4: 3, # 'ο' + 9: 0, # 'Ï€' + 8: 2, # 'Ï' + 14: 0, # 'Ï‚' + 7: 2, # 'σ' + 2: 0, # 'Ï„' + 12: 2, # 'Ï…' + 28: 0, # 'φ' + 23: 0, # 'χ' + 42: 0, # 'ψ' + 24: 0, # 'ω' + 19: 2, # 'ÏŒ' + 26: 2, # 'Ï' + 27: 3, # 'ÏŽ' + }, + 45: { # 'Î¥' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'ÎŒ' + 31: 0, # 'Α' + 51: 0, # 'Î’' + 43: 2, # 'Γ' + 41: 0, # 'Δ' + 34: 1, # 'Ε' + 40: 2, # 'Η' + 52: 2, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 1, # 'Λ' + 38: 2, # 'Îœ' + 49: 2, # 'Î' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 2, # 'Π' + 48: 1, # 'Ρ' + 37: 2, # 'Σ' + 33: 2, # 'Τ' + 45: 0, # 'Î¥' + 56: 0, # 'Φ' + 50: 1, # 'Χ' + 57: 0, # 'Ω' + 17: 0, # 'ά' + 18: 0, # 'έ' + 22: 0, # 'ή' + 15: 0, # 'ί' + 1: 0, # 'α' + 29: 0, # 'β' + 20: 0, # 'γ' + 21: 0, # 'δ' + 3: 0, # 'ε' + 32: 0, # 'ζ' + 13: 0, # 'η' + 25: 0, # 'θ' + 5: 0, # 'ι' + 11: 0, # 'κ' + 16: 2, # 'λ' + 10: 0, # 'μ' + 6: 0, # 'ν' + 30: 0, # 'ξ' + 4: 0, # 'ο' + 9: 3, # 'Ï€' + 8: 0, # 'Ï' + 14: 0, # 'Ï‚' + 7: 0, # 'σ' + 2: 0, # 'Ï„' + 12: 0, # 'Ï…' + 28: 0, # 'φ' + 23: 0, # 'χ' + 42: 0, # 'ψ' + 24: 0, # 'ω' + 19: 0, # 'ÏŒ' + 26: 0, # 'Ï' + 27: 0, # 'ÏŽ' + }, + 56: { # 'Φ' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'ÎŒ' + 31: 1, # 'Α' + 51: 0, # 'Î’' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 1, # 'Η' + 52: 0, # 'Θ' + 47: 2, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Îœ' + 49: 0, # 'Î' + 59: 0, # 'Ξ' + 39: 2, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Î¥' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 0, # 'ά' + 18: 0, # 'έ' + 22: 0, # 'ή' + 15: 0, # 'ί' + 1: 2, # 'α' + 29: 0, # 'β' + 20: 0, # 'γ' + 21: 0, # 'δ' + 3: 2, # 'ε' + 32: 0, # 'ζ' + 13: 0, # 'η' + 25: 0, # 'θ' + 5: 2, # 'ι' + 11: 0, # 'κ' + 16: 0, # 'λ' + 10: 0, # 'μ' + 6: 0, # 'ν' + 30: 0, # 'ξ' + 4: 2, # 'ο' + 9: 0, # 'Ï€' + 8: 0, # 'Ï' + 14: 0, # 'Ï‚' + 7: 0, # 'σ' + 2: 2, # 'Ï„' + 12: 2, # 'Ï…' + 28: 0, # 'φ' + 23: 0, # 'χ' + 42: 0, # 'ψ' + 24: 0, # 'ω' + 19: 0, # 'ÏŒ' + 26: 1, # 'Ï' + 27: 1, # 'ÏŽ' + }, + 50: { # 'Χ' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'ÎŒ' + 31: 1, # 'Α' + 51: 0, # 'Î’' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 2, # 'Ε' + 40: 2, # 'Η' + 52: 0, # 'Θ' + 47: 2, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Îœ' + 49: 1, # 'Î' + 59: 0, # 'Ξ' + 39: 1, # 'Ο' + 35: 0, # 'Π' + 48: 2, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Î¥' + 56: 0, # 'Φ' + 50: 1, # 'Χ' + 57: 1, # 'Ω' + 17: 2, # 'ά' + 18: 0, # 'έ' + 22: 0, # 'ή' + 15: 0, # 'ί' + 1: 2, # 'α' + 29: 0, # 'β' + 20: 0, # 'γ' + 21: 0, # 'δ' + 3: 2, # 'ε' + 32: 0, # 'ζ' + 13: 0, # 'η' + 25: 0, # 'θ' + 5: 0, # 'ι' + 11: 0, # 'κ' + 16: 0, # 'λ' + 10: 0, # 'μ' + 6: 0, # 'ν' + 30: 0, # 'ξ' + 4: 2, # 'ο' + 9: 0, # 'Ï€' + 8: 3, # 'Ï' + 14: 0, # 'Ï‚' + 7: 0, # 'σ' + 2: 2, # 'Ï„' + 12: 0, # 'Ï…' + 28: 0, # 'φ' + 23: 0, # 'χ' + 42: 0, # 'ψ' + 24: 2, # 'ω' + 19: 0, # 'ÏŒ' + 26: 0, # 'Ï' + 27: 0, # 'ÏŽ' + }, + 57: { # 'Ω' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'ÎŒ' + 31: 0, # 'Α' + 51: 0, # 'Î’' + 43: 1, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 1, # 'Λ' + 38: 0, # 'Îœ' + 49: 2, # 'Î' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 2, # 'Ρ' + 37: 2, # 'Σ' + 33: 2, # 'Τ' + 45: 0, # 'Î¥' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 0, # 'ά' + 18: 0, # 'έ' + 22: 0, # 'ή' + 15: 0, # 'ί' + 1: 0, # 'α' + 29: 0, # 'β' + 20: 0, # 'γ' + 21: 0, # 'δ' + 3: 0, # 'ε' + 32: 0, # 'ζ' + 13: 0, # 'η' + 25: 0, # 'θ' + 5: 0, # 'ι' + 11: 0, # 'κ' + 16: 0, # 'λ' + 10: 0, # 'μ' + 6: 0, # 'ν' + 30: 0, # 'ξ' + 4: 0, # 'ο' + 9: 0, # 'Ï€' + 8: 2, # 'Ï' + 14: 2, # 'Ï‚' + 7: 2, # 'σ' + 2: 0, # 'Ï„' + 12: 0, # 'Ï…' + 28: 0, # 'φ' + 23: 1, # 'χ' + 42: 0, # 'ψ' + 24: 0, # 'ω' + 19: 0, # 'ÏŒ' + 26: 0, # 'Ï' + 27: 0, # 'ÏŽ' + }, + 17: { # 'ά' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 2, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'ÎŒ' + 31: 0, # 'Α' + 51: 0, # 'Î’' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Îœ' + 49: 0, # 'Î' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Î¥' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 0, # 'ά' + 18: 0, # 'έ' + 22: 0, # 'ή' + 15: 0, # 'ί' + 1: 0, # 'α' + 29: 3, # 'β' + 20: 3, # 'γ' + 21: 3, # 'δ' + 3: 3, # 'ε' + 32: 3, # 'ζ' + 13: 0, # 'η' + 25: 3, # 'θ' + 5: 2, # 'ι' + 11: 3, # 'κ' + 16: 3, # 'λ' + 10: 3, # 'μ' + 6: 3, # 'ν' + 30: 3, # 'ξ' + 4: 0, # 'ο' + 9: 3, # 'Ï€' + 8: 3, # 'Ï' + 14: 3, # 'Ï‚' + 7: 3, # 'σ' + 2: 3, # 'Ï„' + 12: 0, # 'Ï…' + 28: 3, # 'φ' + 23: 3, # 'χ' + 42: 3, # 'ψ' + 24: 2, # 'ω' + 19: 0, # 'ÏŒ' + 26: 0, # 'Ï' + 27: 0, # 'ÏŽ' + }, + 18: { # 'έ' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'ÎŒ' + 31: 0, # 'Α' + 51: 0, # 'Î’' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Îœ' + 49: 0, # 'Î' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Î¥' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 0, # 'ά' + 18: 0, # 'έ' + 22: 0, # 'ή' + 15: 0, # 'ί' + 1: 3, # 'α' + 29: 2, # 'β' + 20: 3, # 'γ' + 21: 2, # 'δ' + 3: 3, # 'ε' + 32: 2, # 'ζ' + 13: 0, # 'η' + 25: 3, # 'θ' + 5: 0, # 'ι' + 11: 3, # 'κ' + 16: 3, # 'λ' + 10: 3, # 'μ' + 6: 3, # 'ν' + 30: 3, # 'ξ' + 4: 3, # 'ο' + 9: 3, # 'Ï€' + 8: 3, # 'Ï' + 14: 3, # 'Ï‚' + 7: 3, # 'σ' + 2: 3, # 'Ï„' + 12: 0, # 'Ï…' + 28: 3, # 'φ' + 23: 3, # 'χ' + 42: 3, # 'ψ' + 24: 2, # 'ω' + 19: 0, # 'ÏŒ' + 26: 0, # 'Ï' + 27: 0, # 'ÏŽ' + }, + 22: { # 'ή' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 1, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'ÎŒ' + 31: 0, # 'Α' + 51: 0, # 'Î’' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Îœ' + 49: 0, # 'Î' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Î¥' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 0, # 'ά' + 18: 0, # 'έ' + 22: 0, # 'ή' + 15: 0, # 'ί' + 1: 0, # 'α' + 29: 0, # 'β' + 20: 3, # 'γ' + 21: 3, # 'δ' + 3: 0, # 'ε' + 32: 0, # 'ζ' + 13: 0, # 'η' + 25: 3, # 'θ' + 5: 0, # 'ι' + 11: 3, # 'κ' + 16: 2, # 'λ' + 10: 3, # 'μ' + 6: 3, # 'ν' + 30: 2, # 'ξ' + 4: 0, # 'ο' + 9: 3, # 'Ï€' + 8: 3, # 'Ï' + 14: 3, # 'Ï‚' + 7: 3, # 'σ' + 2: 3, # 'Ï„' + 12: 0, # 'Ï…' + 28: 2, # 'φ' + 23: 3, # 'χ' + 42: 2, # 'ψ' + 24: 0, # 'ω' + 19: 0, # 'ÏŒ' + 26: 0, # 'Ï' + 27: 0, # 'ÏŽ' + }, + 15: { # 'ί' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'ÎŒ' + 31: 0, # 'Α' + 51: 0, # 'Î’' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Îœ' + 49: 0, # 'Î' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Î¥' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 0, # 'ά' + 18: 0, # 'έ' + 22: 0, # 'ή' + 15: 0, # 'ί' + 1: 3, # 'α' + 29: 2, # 'β' + 20: 3, # 'γ' + 21: 3, # 'δ' + 3: 3, # 'ε' + 32: 3, # 'ζ' + 13: 3, # 'η' + 25: 3, # 'θ' + 5: 0, # 'ι' + 11: 3, # 'κ' + 16: 3, # 'λ' + 10: 3, # 'μ' + 6: 3, # 'ν' + 30: 3, # 'ξ' + 4: 3, # 'ο' + 9: 3, # 'Ï€' + 8: 3, # 'Ï' + 14: 3, # 'Ï‚' + 7: 3, # 'σ' + 2: 3, # 'Ï„' + 12: 0, # 'Ï…' + 28: 1, # 'φ' + 23: 3, # 'χ' + 42: 2, # 'ψ' + 24: 3, # 'ω' + 19: 0, # 'ÏŒ' + 26: 0, # 'Ï' + 27: 0, # 'ÏŽ' + }, + 1: { # 'α' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 2, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'ÎŒ' + 31: 0, # 'Α' + 51: 0, # 'Î’' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Îœ' + 49: 0, # 'Î' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Î¥' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 0, # 'ά' + 18: 2, # 'έ' + 22: 0, # 'ή' + 15: 3, # 'ί' + 1: 0, # 'α' + 29: 3, # 'β' + 20: 3, # 'γ' + 21: 3, # 'δ' + 3: 2, # 'ε' + 32: 3, # 'ζ' + 13: 1, # 'η' + 25: 3, # 'θ' + 5: 3, # 'ι' + 11: 3, # 'κ' + 16: 3, # 'λ' + 10: 3, # 'μ' + 6: 3, # 'ν' + 30: 3, # 'ξ' + 4: 2, # 'ο' + 9: 3, # 'Ï€' + 8: 3, # 'Ï' + 14: 3, # 'Ï‚' + 7: 3, # 'σ' + 2: 3, # 'Ï„' + 12: 3, # 'Ï…' + 28: 3, # 'φ' + 23: 3, # 'χ' + 42: 2, # 'ψ' + 24: 0, # 'ω' + 19: 2, # 'ÏŒ' + 26: 2, # 'Ï' + 27: 0, # 'ÏŽ' + }, + 29: { # 'β' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'ÎŒ' + 31: 0, # 'Α' + 51: 0, # 'Î’' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Îœ' + 49: 0, # 'Î' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Î¥' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 3, # 'ά' + 18: 2, # 'έ' + 22: 3, # 'ή' + 15: 2, # 'ί' + 1: 3, # 'α' + 29: 0, # 'β' + 20: 2, # 'γ' + 21: 2, # 'δ' + 3: 3, # 'ε' + 32: 0, # 'ζ' + 13: 2, # 'η' + 25: 0, # 'θ' + 5: 3, # 'ι' + 11: 0, # 'κ' + 16: 3, # 'λ' + 10: 0, # 'μ' + 6: 0, # 'ν' + 30: 0, # 'ξ' + 4: 3, # 'ο' + 9: 0, # 'Ï€' + 8: 3, # 'Ï' + 14: 0, # 'Ï‚' + 7: 0, # 'σ' + 2: 0, # 'Ï„' + 12: 0, # 'Ï…' + 28: 0, # 'φ' + 23: 0, # 'χ' + 42: 0, # 'ψ' + 24: 2, # 'ω' + 19: 2, # 'ÏŒ' + 26: 2, # 'Ï' + 27: 2, # 'ÏŽ' + }, + 20: { # 'γ' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'ÎŒ' + 31: 0, # 'Α' + 51: 0, # 'Î’' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Îœ' + 49: 0, # 'Î' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Î¥' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 3, # 'ά' + 18: 3, # 'έ' + 22: 3, # 'ή' + 15: 3, # 'ί' + 1: 3, # 'α' + 29: 0, # 'β' + 20: 3, # 'γ' + 21: 0, # 'δ' + 3: 3, # 'ε' + 32: 0, # 'ζ' + 13: 3, # 'η' + 25: 0, # 'θ' + 5: 3, # 'ι' + 11: 3, # 'κ' + 16: 3, # 'λ' + 10: 3, # 'μ' + 6: 3, # 'ν' + 30: 3, # 'ξ' + 4: 3, # 'ο' + 9: 0, # 'Ï€' + 8: 3, # 'Ï' + 14: 0, # 'Ï‚' + 7: 0, # 'σ' + 2: 0, # 'Ï„' + 12: 2, # 'Ï…' + 28: 0, # 'φ' + 23: 3, # 'χ' + 42: 0, # 'ψ' + 24: 3, # 'ω' + 19: 3, # 'ÏŒ' + 26: 2, # 'Ï' + 27: 3, # 'ÏŽ' + }, + 21: { # 'δ' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'ÎŒ' + 31: 0, # 'Α' + 51: 0, # 'Î’' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Îœ' + 49: 0, # 'Î' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Î¥' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 2, # 'ά' + 18: 3, # 'έ' + 22: 3, # 'ή' + 15: 3, # 'ί' + 1: 3, # 'α' + 29: 0, # 'β' + 20: 0, # 'γ' + 21: 0, # 'δ' + 3: 3, # 'ε' + 32: 0, # 'ζ' + 13: 3, # 'η' + 25: 0, # 'θ' + 5: 3, # 'ι' + 11: 0, # 'κ' + 16: 0, # 'λ' + 10: 0, # 'μ' + 6: 0, # 'ν' + 30: 0, # 'ξ' + 4: 3, # 'ο' + 9: 0, # 'Ï€' + 8: 3, # 'Ï' + 14: 0, # 'Ï‚' + 7: 0, # 'σ' + 2: 0, # 'Ï„' + 12: 3, # 'Ï…' + 28: 0, # 'φ' + 23: 0, # 'χ' + 42: 0, # 'ψ' + 24: 3, # 'ω' + 19: 3, # 'ÏŒ' + 26: 3, # 'Ï' + 27: 3, # 'ÏŽ' + }, + 3: { # 'ε' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 2, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'ÎŒ' + 31: 0, # 'Α' + 51: 0, # 'Î’' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Îœ' + 49: 0, # 'Î' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Î¥' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 3, # 'ά' + 18: 0, # 'έ' + 22: 0, # 'ή' + 15: 3, # 'ί' + 1: 2, # 'α' + 29: 3, # 'β' + 20: 3, # 'γ' + 21: 3, # 'δ' + 3: 2, # 'ε' + 32: 2, # 'ζ' + 13: 0, # 'η' + 25: 3, # 'θ' + 5: 3, # 'ι' + 11: 3, # 'κ' + 16: 3, # 'λ' + 10: 3, # 'μ' + 6: 3, # 'ν' + 30: 3, # 'ξ' + 4: 2, # 'ο' + 9: 3, # 'Ï€' + 8: 3, # 'Ï' + 14: 3, # 'Ï‚' + 7: 3, # 'σ' + 2: 3, # 'Ï„' + 12: 3, # 'Ï…' + 28: 3, # 'φ' + 23: 3, # 'χ' + 42: 2, # 'ψ' + 24: 3, # 'ω' + 19: 2, # 'ÏŒ' + 26: 3, # 'Ï' + 27: 2, # 'ÏŽ' + }, + 32: { # 'ζ' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'ÎŒ' + 31: 0, # 'Α' + 51: 0, # 'Î’' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Îœ' + 49: 0, # 'Î' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Î¥' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 2, # 'ά' + 18: 2, # 'έ' + 22: 2, # 'ή' + 15: 2, # 'ί' + 1: 2, # 'α' + 29: 0, # 'β' + 20: 0, # 'γ' + 21: 0, # 'δ' + 3: 3, # 'ε' + 32: 0, # 'ζ' + 13: 3, # 'η' + 25: 0, # 'θ' + 5: 2, # 'ι' + 11: 0, # 'κ' + 16: 0, # 'λ' + 10: 0, # 'μ' + 6: 0, # 'ν' + 30: 0, # 'ξ' + 4: 3, # 'ο' + 9: 0, # 'Ï€' + 8: 0, # 'Ï' + 14: 0, # 'Ï‚' + 7: 0, # 'σ' + 2: 0, # 'Ï„' + 12: 1, # 'Ï…' + 28: 0, # 'φ' + 23: 0, # 'χ' + 42: 0, # 'ψ' + 24: 3, # 'ω' + 19: 2, # 'ÏŒ' + 26: 0, # 'Ï' + 27: 2, # 'ÏŽ' + }, + 13: { # 'η' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 2, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'ÎŒ' + 31: 0, # 'Α' + 51: 0, # 'Î’' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Îœ' + 49: 0, # 'Î' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Î¥' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 0, # 'ά' + 18: 0, # 'έ' + 22: 0, # 'ή' + 15: 0, # 'ί' + 1: 0, # 'α' + 29: 0, # 'β' + 20: 3, # 'γ' + 21: 2, # 'δ' + 3: 0, # 'ε' + 32: 0, # 'ζ' + 13: 0, # 'η' + 25: 3, # 'θ' + 5: 0, # 'ι' + 11: 3, # 'κ' + 16: 3, # 'λ' + 10: 3, # 'μ' + 6: 3, # 'ν' + 30: 2, # 'ξ' + 4: 0, # 'ο' + 9: 2, # 'Ï€' + 8: 3, # 'Ï' + 14: 3, # 'Ï‚' + 7: 3, # 'σ' + 2: 3, # 'Ï„' + 12: 0, # 'Ï…' + 28: 2, # 'φ' + 23: 3, # 'χ' + 42: 2, # 'ψ' + 24: 0, # 'ω' + 19: 0, # 'ÏŒ' + 26: 0, # 'Ï' + 27: 0, # 'ÏŽ' + }, + 25: { # 'θ' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'ÎŒ' + 31: 0, # 'Α' + 51: 0, # 'Î’' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Îœ' + 49: 0, # 'Î' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Î¥' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 2, # 'ά' + 18: 3, # 'έ' + 22: 3, # 'ή' + 15: 2, # 'ί' + 1: 3, # 'α' + 29: 0, # 'β' + 20: 0, # 'γ' + 21: 0, # 'δ' + 3: 3, # 'ε' + 32: 0, # 'ζ' + 13: 3, # 'η' + 25: 0, # 'θ' + 5: 3, # 'ι' + 11: 0, # 'κ' + 16: 1, # 'λ' + 10: 3, # 'μ' + 6: 2, # 'ν' + 30: 0, # 'ξ' + 4: 3, # 'ο' + 9: 0, # 'Ï€' + 8: 3, # 'Ï' + 14: 0, # 'Ï‚' + 7: 0, # 'σ' + 2: 0, # 'Ï„' + 12: 3, # 'Ï…' + 28: 0, # 'φ' + 23: 0, # 'χ' + 42: 0, # 'ψ' + 24: 3, # 'ω' + 19: 3, # 'ÏŒ' + 26: 3, # 'Ï' + 27: 3, # 'ÏŽ' + }, + 5: { # 'ι' + 60: 0, # 'e' + 55: 1, # 'o' + 58: 0, # 't' + 36: 2, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'ÎŒ' + 31: 0, # 'Α' + 51: 0, # 'Î’' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 1, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Îœ' + 49: 0, # 'Î' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Î¥' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 3, # 'ά' + 18: 3, # 'έ' + 22: 3, # 'ή' + 15: 0, # 'ί' + 1: 3, # 'α' + 29: 3, # 'β' + 20: 3, # 'γ' + 21: 3, # 'δ' + 3: 3, # 'ε' + 32: 2, # 'ζ' + 13: 3, # 'η' + 25: 3, # 'θ' + 5: 0, # 'ι' + 11: 3, # 'κ' + 16: 3, # 'λ' + 10: 3, # 'μ' + 6: 3, # 'ν' + 30: 3, # 'ξ' + 4: 3, # 'ο' + 9: 3, # 'Ï€' + 8: 3, # 'Ï' + 14: 3, # 'Ï‚' + 7: 3, # 'σ' + 2: 3, # 'Ï„' + 12: 0, # 'Ï…' + 28: 2, # 'φ' + 23: 3, # 'χ' + 42: 2, # 'ψ' + 24: 3, # 'ω' + 19: 3, # 'ÏŒ' + 26: 0, # 'Ï' + 27: 3, # 'ÏŽ' + }, + 11: { # 'κ' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'ÎŒ' + 31: 0, # 'Α' + 51: 0, # 'Î’' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Îœ' + 49: 0, # 'Î' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Î¥' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 3, # 'ά' + 18: 3, # 'έ' + 22: 3, # 'ή' + 15: 3, # 'ί' + 1: 3, # 'α' + 29: 0, # 'β' + 20: 0, # 'γ' + 21: 3, # 'δ' + 3: 3, # 'ε' + 32: 0, # 'ζ' + 13: 3, # 'η' + 25: 2, # 'θ' + 5: 3, # 'ι' + 11: 3, # 'κ' + 16: 3, # 'λ' + 10: 3, # 'μ' + 6: 2, # 'ν' + 30: 0, # 'ξ' + 4: 3, # 'ο' + 9: 2, # 'Ï€' + 8: 3, # 'Ï' + 14: 0, # 'Ï‚' + 7: 0, # 'σ' + 2: 3, # 'Ï„' + 12: 3, # 'Ï…' + 28: 2, # 'φ' + 23: 2, # 'χ' + 42: 0, # 'ψ' + 24: 3, # 'ω' + 19: 3, # 'ÏŒ' + 26: 3, # 'Ï' + 27: 3, # 'ÏŽ' + }, + 16: { # 'λ' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'ÎŒ' + 31: 0, # 'Α' + 51: 0, # 'Î’' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Îœ' + 49: 0, # 'Î' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Î¥' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 3, # 'ά' + 18: 3, # 'έ' + 22: 3, # 'ή' + 15: 3, # 'ί' + 1: 3, # 'α' + 29: 1, # 'β' + 20: 2, # 'γ' + 21: 1, # 'δ' + 3: 3, # 'ε' + 32: 0, # 'ζ' + 13: 3, # 'η' + 25: 2, # 'θ' + 5: 3, # 'ι' + 11: 2, # 'κ' + 16: 3, # 'λ' + 10: 2, # 'μ' + 6: 2, # 'ν' + 30: 0, # 'ξ' + 4: 3, # 'ο' + 9: 3, # 'Ï€' + 8: 0, # 'Ï' + 14: 0, # 'Ï‚' + 7: 0, # 'σ' + 2: 3, # 'Ï„' + 12: 3, # 'Ï…' + 28: 2, # 'φ' + 23: 0, # 'χ' + 42: 0, # 'ψ' + 24: 3, # 'ω' + 19: 3, # 'ÏŒ' + 26: 3, # 'Ï' + 27: 3, # 'ÏŽ' + }, + 10: { # 'μ' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'ÎŒ' + 31: 0, # 'Α' + 51: 0, # 'Î’' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 1, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Îœ' + 49: 0, # 'Î' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Î¥' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 3, # 'ά' + 18: 3, # 'έ' + 22: 3, # 'ή' + 15: 3, # 'ί' + 1: 3, # 'α' + 29: 3, # 'β' + 20: 0, # 'γ' + 21: 0, # 'δ' + 3: 3, # 'ε' + 32: 0, # 'ζ' + 13: 3, # 'η' + 25: 0, # 'θ' + 5: 3, # 'ι' + 11: 0, # 'κ' + 16: 0, # 'λ' + 10: 3, # 'μ' + 6: 3, # 'ν' + 30: 0, # 'ξ' + 4: 3, # 'ο' + 9: 3, # 'Ï€' + 8: 0, # 'Ï' + 14: 0, # 'Ï‚' + 7: 0, # 'σ' + 2: 0, # 'Ï„' + 12: 2, # 'Ï…' + 28: 3, # 'φ' + 23: 0, # 'χ' + 42: 2, # 'ψ' + 24: 3, # 'ω' + 19: 3, # 'ÏŒ' + 26: 2, # 'Ï' + 27: 2, # 'ÏŽ' + }, + 6: { # 'ν' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 2, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'ÎŒ' + 31: 0, # 'Α' + 51: 0, # 'Î’' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Îœ' + 49: 0, # 'Î' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Î¥' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 3, # 'ά' + 18: 3, # 'έ' + 22: 3, # 'ή' + 15: 3, # 'ί' + 1: 3, # 'α' + 29: 0, # 'β' + 20: 0, # 'γ' + 21: 3, # 'δ' + 3: 3, # 'ε' + 32: 2, # 'ζ' + 13: 3, # 'η' + 25: 3, # 'θ' + 5: 3, # 'ι' + 11: 0, # 'κ' + 16: 1, # 'λ' + 10: 0, # 'μ' + 6: 2, # 'ν' + 30: 0, # 'ξ' + 4: 3, # 'ο' + 9: 0, # 'Ï€' + 8: 0, # 'Ï' + 14: 0, # 'Ï‚' + 7: 3, # 'σ' + 2: 3, # 'Ï„' + 12: 3, # 'Ï…' + 28: 0, # 'φ' + 23: 0, # 'χ' + 42: 0, # 'ψ' + 24: 3, # 'ω' + 19: 3, # 'ÏŒ' + 26: 3, # 'Ï' + 27: 3, # 'ÏŽ' + }, + 30: { # 'ξ' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'ÎŒ' + 31: 0, # 'Α' + 51: 0, # 'Î’' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Îœ' + 49: 0, # 'Î' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Î¥' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 2, # 'ά' + 18: 3, # 'έ' + 22: 3, # 'ή' + 15: 2, # 'ί' + 1: 3, # 'α' + 29: 0, # 'β' + 20: 0, # 'γ' + 21: 0, # 'δ' + 3: 3, # 'ε' + 32: 0, # 'ζ' + 13: 3, # 'η' + 25: 0, # 'θ' + 5: 2, # 'ι' + 11: 0, # 'κ' + 16: 0, # 'λ' + 10: 0, # 'μ' + 6: 0, # 'ν' + 30: 0, # 'ξ' + 4: 3, # 'ο' + 9: 0, # 'Ï€' + 8: 0, # 'Ï' + 14: 0, # 'Ï‚' + 7: 0, # 'σ' + 2: 3, # 'Ï„' + 12: 2, # 'Ï…' + 28: 0, # 'φ' + 23: 0, # 'χ' + 42: 0, # 'ψ' + 24: 3, # 'ω' + 19: 2, # 'ÏŒ' + 26: 3, # 'Ï' + 27: 1, # 'ÏŽ' + }, + 4: { # 'ο' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 2, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'ÎŒ' + 31: 0, # 'Α' + 51: 0, # 'Î’' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Îœ' + 49: 0, # 'Î' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Î¥' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 0, # 'ά' + 18: 2, # 'έ' + 22: 3, # 'ή' + 15: 3, # 'ί' + 1: 2, # 'α' + 29: 3, # 'β' + 20: 3, # 'γ' + 21: 3, # 'δ' + 3: 3, # 'ε' + 32: 0, # 'ζ' + 13: 3, # 'η' + 25: 3, # 'θ' + 5: 3, # 'ι' + 11: 3, # 'κ' + 16: 3, # 'λ' + 10: 3, # 'μ' + 6: 3, # 'ν' + 30: 2, # 'ξ' + 4: 2, # 'ο' + 9: 3, # 'Ï€' + 8: 3, # 'Ï' + 14: 3, # 'Ï‚' + 7: 3, # 'σ' + 2: 3, # 'Ï„' + 12: 3, # 'Ï…' + 28: 3, # 'φ' + 23: 3, # 'χ' + 42: 2, # 'ψ' + 24: 2, # 'ω' + 19: 1, # 'ÏŒ' + 26: 3, # 'Ï' + 27: 2, # 'ÏŽ' + }, + 9: { # 'Ï€' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'ÎŒ' + 31: 0, # 'Α' + 51: 0, # 'Î’' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Îœ' + 49: 0, # 'Î' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Î¥' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 3, # 'ά' + 18: 3, # 'έ' + 22: 3, # 'ή' + 15: 3, # 'ί' + 1: 3, # 'α' + 29: 0, # 'β' + 20: 0, # 'γ' + 21: 0, # 'δ' + 3: 3, # 'ε' + 32: 0, # 'ζ' + 13: 3, # 'η' + 25: 0, # 'θ' + 5: 3, # 'ι' + 11: 0, # 'κ' + 16: 3, # 'λ' + 10: 0, # 'μ' + 6: 2, # 'ν' + 30: 0, # 'ξ' + 4: 3, # 'ο' + 9: 0, # 'Ï€' + 8: 3, # 'Ï' + 14: 2, # 'Ï‚' + 7: 0, # 'σ' + 2: 3, # 'Ï„' + 12: 3, # 'Ï…' + 28: 0, # 'φ' + 23: 2, # 'χ' + 42: 0, # 'ψ' + 24: 3, # 'ω' + 19: 3, # 'ÏŒ' + 26: 2, # 'Ï' + 27: 3, # 'ÏŽ' + }, + 8: { # 'Ï' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'ÎŒ' + 31: 0, # 'Α' + 51: 0, # 'Î’' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Îœ' + 49: 0, # 'Î' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Î¥' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 3, # 'ά' + 18: 3, # 'έ' + 22: 3, # 'ή' + 15: 3, # 'ί' + 1: 3, # 'α' + 29: 2, # 'β' + 20: 3, # 'γ' + 21: 2, # 'δ' + 3: 3, # 'ε' + 32: 0, # 'ζ' + 13: 3, # 'η' + 25: 3, # 'θ' + 5: 3, # 'ι' + 11: 3, # 'κ' + 16: 1, # 'λ' + 10: 3, # 'μ' + 6: 3, # 'ν' + 30: 2, # 'ξ' + 4: 3, # 'ο' + 9: 2, # 'Ï€' + 8: 2, # 'Ï' + 14: 0, # 'Ï‚' + 7: 2, # 'σ' + 2: 3, # 'Ï„' + 12: 3, # 'Ï…' + 28: 3, # 'φ' + 23: 3, # 'χ' + 42: 0, # 'ψ' + 24: 3, # 'ω' + 19: 3, # 'ÏŒ' + 26: 3, # 'Ï' + 27: 3, # 'ÏŽ' + }, + 14: { # 'Ï‚' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 2, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'ÎŒ' + 31: 0, # 'Α' + 51: 0, # 'Î’' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Îœ' + 49: 0, # 'Î' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Î¥' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 0, # 'ά' + 18: 0, # 'έ' + 22: 0, # 'ή' + 15: 0, # 'ί' + 1: 0, # 'α' + 29: 0, # 'β' + 20: 0, # 'γ' + 21: 0, # 'δ' + 3: 0, # 'ε' + 32: 0, # 'ζ' + 13: 0, # 'η' + 25: 0, # 'θ' + 5: 0, # 'ι' + 11: 0, # 'κ' + 16: 0, # 'λ' + 10: 0, # 'μ' + 6: 0, # 'ν' + 30: 0, # 'ξ' + 4: 0, # 'ο' + 9: 0, # 'Ï€' + 8: 0, # 'Ï' + 14: 0, # 'Ï‚' + 7: 0, # 'σ' + 2: 0, # 'Ï„' + 12: 0, # 'Ï…' + 28: 0, # 'φ' + 23: 0, # 'χ' + 42: 0, # 'ψ' + 24: 0, # 'ω' + 19: 0, # 'ÏŒ' + 26: 0, # 'Ï' + 27: 0, # 'ÏŽ' + }, + 7: { # 'σ' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'ÎŒ' + 31: 0, # 'Α' + 51: 0, # 'Î’' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Îœ' + 49: 0, # 'Î' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Î¥' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 2, # 'ά' + 18: 2, # 'έ' + 22: 3, # 'ή' + 15: 3, # 'ί' + 1: 3, # 'α' + 29: 3, # 'β' + 20: 0, # 'γ' + 21: 2, # 'δ' + 3: 3, # 'ε' + 32: 0, # 'ζ' + 13: 3, # 'η' + 25: 3, # 'θ' + 5: 3, # 'ι' + 11: 3, # 'κ' + 16: 2, # 'λ' + 10: 3, # 'μ' + 6: 0, # 'ν' + 30: 0, # 'ξ' + 4: 3, # 'ο' + 9: 3, # 'Ï€' + 8: 0, # 'Ï' + 14: 0, # 'Ï‚' + 7: 3, # 'σ' + 2: 3, # 'Ï„' + 12: 3, # 'Ï…' + 28: 3, # 'φ' + 23: 3, # 'χ' + 42: 0, # 'ψ' + 24: 3, # 'ω' + 19: 3, # 'ÏŒ' + 26: 3, # 'Ï' + 27: 2, # 'ÏŽ' + }, + 2: { # 'Ï„' + 60: 0, # 'e' + 55: 2, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'ÎŒ' + 31: 0, # 'Α' + 51: 0, # 'Î’' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Îœ' + 49: 0, # 'Î' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Î¥' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 3, # 'ά' + 18: 3, # 'έ' + 22: 3, # 'ή' + 15: 3, # 'ί' + 1: 3, # 'α' + 29: 0, # 'β' + 20: 0, # 'γ' + 21: 0, # 'δ' + 3: 3, # 'ε' + 32: 2, # 'ζ' + 13: 3, # 'η' + 25: 0, # 'θ' + 5: 3, # 'ι' + 11: 2, # 'κ' + 16: 2, # 'λ' + 10: 3, # 'μ' + 6: 0, # 'ν' + 30: 0, # 'ξ' + 4: 3, # 'ο' + 9: 0, # 'Ï€' + 8: 3, # 'Ï' + 14: 0, # 'Ï‚' + 7: 3, # 'σ' + 2: 3, # 'Ï„' + 12: 3, # 'Ï…' + 28: 2, # 'φ' + 23: 0, # 'χ' + 42: 0, # 'ψ' + 24: 3, # 'ω' + 19: 3, # 'ÏŒ' + 26: 3, # 'Ï' + 27: 3, # 'ÏŽ' + }, + 12: { # 'Ï…' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'ÎŒ' + 31: 0, # 'Α' + 51: 0, # 'Î’' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Îœ' + 49: 0, # 'Î' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Î¥' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 2, # 'ά' + 18: 2, # 'έ' + 22: 3, # 'ή' + 15: 2, # 'ί' + 1: 3, # 'α' + 29: 2, # 'β' + 20: 3, # 'γ' + 21: 2, # 'δ' + 3: 2, # 'ε' + 32: 2, # 'ζ' + 13: 2, # 'η' + 25: 3, # 'θ' + 5: 2, # 'ι' + 11: 3, # 'κ' + 16: 3, # 'λ' + 10: 3, # 'μ' + 6: 3, # 'ν' + 30: 3, # 'ξ' + 4: 3, # 'ο' + 9: 3, # 'Ï€' + 8: 3, # 'Ï' + 14: 3, # 'Ï‚' + 7: 3, # 'σ' + 2: 3, # 'Ï„' + 12: 0, # 'Ï…' + 28: 2, # 'φ' + 23: 3, # 'χ' + 42: 2, # 'ψ' + 24: 2, # 'ω' + 19: 2, # 'ÏŒ' + 26: 0, # 'Ï' + 27: 2, # 'ÏŽ' + }, + 28: { # 'φ' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'ÎŒ' + 31: 0, # 'Α' + 51: 0, # 'Î’' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Îœ' + 49: 0, # 'Î' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Î¥' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 3, # 'ά' + 18: 3, # 'έ' + 22: 3, # 'ή' + 15: 3, # 'ί' + 1: 3, # 'α' + 29: 0, # 'β' + 20: 0, # 'γ' + 21: 0, # 'δ' + 3: 3, # 'ε' + 32: 0, # 'ζ' + 13: 2, # 'η' + 25: 2, # 'θ' + 5: 3, # 'ι' + 11: 0, # 'κ' + 16: 2, # 'λ' + 10: 0, # 'μ' + 6: 1, # 'ν' + 30: 0, # 'ξ' + 4: 3, # 'ο' + 9: 0, # 'Ï€' + 8: 3, # 'Ï' + 14: 0, # 'Ï‚' + 7: 0, # 'σ' + 2: 3, # 'Ï„' + 12: 3, # 'Ï…' + 28: 1, # 'φ' + 23: 0, # 'χ' + 42: 0, # 'ψ' + 24: 3, # 'ω' + 19: 3, # 'ÏŒ' + 26: 2, # 'Ï' + 27: 2, # 'ÏŽ' + }, + 23: { # 'χ' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'ÎŒ' + 31: 0, # 'Α' + 51: 0, # 'Î’' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Îœ' + 49: 0, # 'Î' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Î¥' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 3, # 'ά' + 18: 2, # 'έ' + 22: 3, # 'ή' + 15: 3, # 'ί' + 1: 3, # 'α' + 29: 0, # 'β' + 20: 0, # 'γ' + 21: 0, # 'δ' + 3: 3, # 'ε' + 32: 0, # 'ζ' + 13: 2, # 'η' + 25: 2, # 'θ' + 5: 3, # 'ι' + 11: 0, # 'κ' + 16: 2, # 'λ' + 10: 2, # 'μ' + 6: 3, # 'ν' + 30: 0, # 'ξ' + 4: 3, # 'ο' + 9: 0, # 'Ï€' + 8: 3, # 'Ï' + 14: 0, # 'Ï‚' + 7: 0, # 'σ' + 2: 3, # 'Ï„' + 12: 3, # 'Ï…' + 28: 0, # 'φ' + 23: 2, # 'χ' + 42: 0, # 'ψ' + 24: 3, # 'ω' + 19: 3, # 'ÏŒ' + 26: 3, # 'Ï' + 27: 3, # 'ÏŽ' + }, + 42: { # 'ψ' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'ÎŒ' + 31: 0, # 'Α' + 51: 0, # 'Î’' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Îœ' + 49: 0, # 'Î' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Î¥' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 2, # 'ά' + 18: 2, # 'έ' + 22: 1, # 'ή' + 15: 2, # 'ί' + 1: 2, # 'α' + 29: 0, # 'β' + 20: 0, # 'γ' + 21: 0, # 'δ' + 3: 3, # 'ε' + 32: 0, # 'ζ' + 13: 3, # 'η' + 25: 0, # 'θ' + 5: 2, # 'ι' + 11: 0, # 'κ' + 16: 0, # 'λ' + 10: 0, # 'μ' + 6: 0, # 'ν' + 30: 0, # 'ξ' + 4: 2, # 'ο' + 9: 0, # 'Ï€' + 8: 0, # 'Ï' + 14: 0, # 'Ï‚' + 7: 0, # 'σ' + 2: 2, # 'Ï„' + 12: 1, # 'Ï…' + 28: 0, # 'φ' + 23: 0, # 'χ' + 42: 0, # 'ψ' + 24: 2, # 'ω' + 19: 0, # 'ÏŒ' + 26: 0, # 'Ï' + 27: 0, # 'ÏŽ' + }, + 24: { # 'ω' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'ÎŒ' + 31: 0, # 'Α' + 51: 0, # 'Î’' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Îœ' + 49: 0, # 'Î' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Î¥' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 1, # 'ά' + 18: 0, # 'έ' + 22: 2, # 'ή' + 15: 0, # 'ί' + 1: 0, # 'α' + 29: 2, # 'β' + 20: 3, # 'γ' + 21: 2, # 'δ' + 3: 0, # 'ε' + 32: 0, # 'ζ' + 13: 0, # 'η' + 25: 3, # 'θ' + 5: 2, # 'ι' + 11: 0, # 'κ' + 16: 2, # 'λ' + 10: 3, # 'μ' + 6: 3, # 'ν' + 30: 0, # 'ξ' + 4: 0, # 'ο' + 9: 3, # 'Ï€' + 8: 3, # 'Ï' + 14: 3, # 'Ï‚' + 7: 3, # 'σ' + 2: 3, # 'Ï„' + 12: 0, # 'Ï…' + 28: 2, # 'φ' + 23: 2, # 'χ' + 42: 0, # 'ψ' + 24: 0, # 'ω' + 19: 0, # 'ÏŒ' + 26: 0, # 'Ï' + 27: 0, # 'ÏŽ' + }, + 19: { # 'ÏŒ' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'ÎŒ' + 31: 0, # 'Α' + 51: 0, # 'Î’' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Îœ' + 49: 0, # 'Î' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Î¥' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 0, # 'ά' + 18: 0, # 'έ' + 22: 0, # 'ή' + 15: 0, # 'ί' + 1: 0, # 'α' + 29: 3, # 'β' + 20: 3, # 'γ' + 21: 3, # 'δ' + 3: 1, # 'ε' + 32: 2, # 'ζ' + 13: 2, # 'η' + 25: 2, # 'θ' + 5: 2, # 'ι' + 11: 3, # 'κ' + 16: 3, # 'λ' + 10: 3, # 'μ' + 6: 3, # 'ν' + 30: 1, # 'ξ' + 4: 2, # 'ο' + 9: 3, # 'Ï€' + 8: 3, # 'Ï' + 14: 3, # 'Ï‚' + 7: 3, # 'σ' + 2: 3, # 'Ï„' + 12: 0, # 'Ï…' + 28: 2, # 'φ' + 23: 3, # 'χ' + 42: 2, # 'ψ' + 24: 0, # 'ω' + 19: 0, # 'ÏŒ' + 26: 0, # 'Ï' + 27: 0, # 'ÏŽ' + }, + 26: { # 'Ï' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'ÎŒ' + 31: 0, # 'Α' + 51: 0, # 'Î’' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Îœ' + 49: 0, # 'Î' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Î¥' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 0, # 'ά' + 18: 0, # 'έ' + 22: 0, # 'ή' + 15: 0, # 'ί' + 1: 2, # 'α' + 29: 2, # 'β' + 20: 2, # 'γ' + 21: 1, # 'δ' + 3: 3, # 'ε' + 32: 0, # 'ζ' + 13: 2, # 'η' + 25: 3, # 'θ' + 5: 0, # 'ι' + 11: 3, # 'κ' + 16: 3, # 'λ' + 10: 3, # 'μ' + 6: 3, # 'ν' + 30: 2, # 'ξ' + 4: 3, # 'ο' + 9: 3, # 'Ï€' + 8: 3, # 'Ï' + 14: 3, # 'Ï‚' + 7: 3, # 'σ' + 2: 3, # 'Ï„' + 12: 0, # 'Ï…' + 28: 2, # 'φ' + 23: 2, # 'χ' + 42: 2, # 'ψ' + 24: 2, # 'ω' + 19: 0, # 'ÏŒ' + 26: 0, # 'Ï' + 27: 0, # 'ÏŽ' + }, + 27: { # 'ÏŽ' + 60: 0, # 'e' + 55: 0, # 'o' + 58: 0, # 't' + 36: 0, # '·' + 61: 0, # 'Ά' + 46: 0, # 'Έ' + 54: 0, # 'ÎŒ' + 31: 0, # 'Α' + 51: 0, # 'Î’' + 43: 0, # 'Γ' + 41: 0, # 'Δ' + 34: 0, # 'Ε' + 40: 0, # 'Η' + 52: 0, # 'Θ' + 47: 0, # 'Ι' + 44: 0, # 'Κ' + 53: 0, # 'Λ' + 38: 0, # 'Îœ' + 49: 0, # 'Î' + 59: 0, # 'Ξ' + 39: 0, # 'Ο' + 35: 0, # 'Π' + 48: 0, # 'Ρ' + 37: 0, # 'Σ' + 33: 0, # 'Τ' + 45: 0, # 'Î¥' + 56: 0, # 'Φ' + 50: 0, # 'Χ' + 57: 0, # 'Ω' + 17: 0, # 'ά' + 18: 0, # 'έ' + 22: 0, # 'ή' + 15: 0, # 'ί' + 1: 0, # 'α' + 29: 1, # 'β' + 20: 0, # 'γ' + 21: 3, # 'δ' + 3: 0, # 'ε' + 32: 0, # 'ζ' + 13: 1, # 'η' + 25: 2, # 'θ' + 5: 2, # 'ι' + 11: 0, # 'κ' + 16: 2, # 'λ' + 10: 3, # 'μ' + 6: 3, # 'ν' + 30: 1, # 'ξ' + 4: 0, # 'ο' + 9: 2, # 'Ï€' + 8: 3, # 'Ï' + 14: 3, # 'Ï‚' + 7: 3, # 'σ' + 2: 3, # 'Ï„' + 12: 0, # 'Ï…' + 28: 1, # 'φ' + 23: 1, # 'χ' + 42: 0, # 'ψ' + 24: 0, # 'ω' + 19: 0, # 'ÏŒ' + 26: 0, # 'Ï' + 27: 0, # 'ÏŽ' + }, +} + +# 255: Undefined characters that did not exist in training text +# 254: Carriage/Return +# 253: symbol (punctuation) that does not belong to word +# 252: 0 - 9 +# 251: Control characters + +# Character Mapping Table(s): +WINDOWS_1253_GREEK_CHAR_TO_ORDER = { + 0: 255, # '\x00' + 1: 255, # '\x01' + 2: 255, # '\x02' + 3: 255, # '\x03' + 4: 255, # '\x04' + 5: 255, # '\x05' + 6: 255, # '\x06' + 7: 255, # '\x07' + 8: 255, # '\x08' + 9: 255, # '\t' + 10: 254, # '\n' + 11: 255, # '\x0b' + 12: 255, # '\x0c' + 13: 254, # '\r' + 14: 255, # '\x0e' + 15: 255, # '\x0f' + 16: 255, # '\x10' + 17: 255, # '\x11' + 18: 255, # '\x12' + 19: 255, # '\x13' + 20: 255, # '\x14' + 21: 255, # '\x15' + 22: 255, # '\x16' + 23: 255, # '\x17' + 24: 255, # '\x18' + 25: 255, # '\x19' + 26: 255, # '\x1a' + 27: 255, # '\x1b' + 28: 255, # '\x1c' + 29: 255, # '\x1d' + 30: 255, # '\x1e' + 31: 255, # '\x1f' + 32: 253, # ' ' + 33: 253, # '!' + 34: 253, # '"' + 35: 253, # '#' + 36: 253, # '$' + 37: 253, # '%' + 38: 253, # '&' + 39: 253, # "'" + 40: 253, # '(' + 41: 253, # ')' + 42: 253, # '*' + 43: 253, # '+' + 44: 253, # ',' + 45: 253, # '-' + 46: 253, # '.' + 47: 253, # '/' + 48: 252, # '0' + 49: 252, # '1' + 50: 252, # '2' + 51: 252, # '3' + 52: 252, # '4' + 53: 252, # '5' + 54: 252, # '6' + 55: 252, # '7' + 56: 252, # '8' + 57: 252, # '9' + 58: 253, # ':' + 59: 253, # ';' + 60: 253, # '<' + 61: 253, # '=' + 62: 253, # '>' + 63: 253, # '?' + 64: 253, # '@' + 65: 82, # 'A' + 66: 100, # 'B' + 67: 104, # 'C' + 68: 94, # 'D' + 69: 98, # 'E' + 70: 101, # 'F' + 71: 116, # 'G' + 72: 102, # 'H' + 73: 111, # 'I' + 74: 187, # 'J' + 75: 117, # 'K' + 76: 92, # 'L' + 77: 88, # 'M' + 78: 113, # 'N' + 79: 85, # 'O' + 80: 79, # 'P' + 81: 118, # 'Q' + 82: 105, # 'R' + 83: 83, # 'S' + 84: 67, # 'T' + 85: 114, # 'U' + 86: 119, # 'V' + 87: 95, # 'W' + 88: 99, # 'X' + 89: 109, # 'Y' + 90: 188, # 'Z' + 91: 253, # '[' + 92: 253, # '\\' + 93: 253, # ']' + 94: 253, # '^' + 95: 253, # '_' + 96: 253, # '`' + 97: 72, # 'a' + 98: 70, # 'b' + 99: 80, # 'c' + 100: 81, # 'd' + 101: 60, # 'e' + 102: 96, # 'f' + 103: 93, # 'g' + 104: 89, # 'h' + 105: 68, # 'i' + 106: 120, # 'j' + 107: 97, # 'k' + 108: 77, # 'l' + 109: 86, # 'm' + 110: 69, # 'n' + 111: 55, # 'o' + 112: 78, # 'p' + 113: 115, # 'q' + 114: 65, # 'r' + 115: 66, # 's' + 116: 58, # 't' + 117: 76, # 'u' + 118: 106, # 'v' + 119: 103, # 'w' + 120: 87, # 'x' + 121: 107, # 'y' + 122: 112, # 'z' + 123: 253, # '{' + 124: 253, # '|' + 125: 253, # '}' + 126: 253, # '~' + 127: 253, # '\x7f' + 128: 255, # '€' + 129: 255, # None + 130: 255, # '‚' + 131: 255, # 'Æ’' + 132: 255, # '„' + 133: 255, # '…' + 134: 255, # '†' + 135: 255, # '‡' + 136: 255, # None + 137: 255, # '‰' + 138: 255, # None + 139: 255, # '‹' + 140: 255, # None + 141: 255, # None + 142: 255, # None + 143: 255, # None + 144: 255, # None + 145: 255, # '‘' + 146: 255, # '’' + 147: 255, # '“' + 148: 255, # 'â€' + 149: 255, # '•' + 150: 255, # '–' + 151: 255, # '—' + 152: 255, # None + 153: 255, # 'â„¢' + 154: 255, # None + 155: 255, # '›' + 156: 255, # None + 157: 255, # None + 158: 255, # None + 159: 255, # None + 160: 253, # '\xa0' + 161: 233, # 'Î…' + 162: 61, # 'Ά' + 163: 253, # '£' + 164: 253, # '¤' + 165: 253, # 'Â¥' + 166: 253, # '¦' + 167: 253, # '§' + 168: 253, # '¨' + 169: 253, # '©' + 170: 253, # None + 171: 253, # '«' + 172: 253, # '¬' + 173: 74, # '\xad' + 174: 253, # '®' + 175: 253, # '―' + 176: 253, # '°' + 177: 253, # '±' + 178: 253, # '²' + 179: 253, # '³' + 180: 247, # '΄' + 181: 253, # 'µ' + 182: 253, # '¶' + 183: 36, # '·' + 184: 46, # 'Έ' + 185: 71, # 'Ή' + 186: 73, # 'Ί' + 187: 253, # '»' + 188: 54, # 'ÎŒ' + 189: 253, # '½' + 190: 108, # 'ÎŽ' + 191: 123, # 'Î' + 192: 110, # 'Î' + 193: 31, # 'Α' + 194: 51, # 'Î’' + 195: 43, # 'Γ' + 196: 41, # 'Δ' + 197: 34, # 'Ε' + 198: 91, # 'Ζ' + 199: 40, # 'Η' + 200: 52, # 'Θ' + 201: 47, # 'Ι' + 202: 44, # 'Κ' + 203: 53, # 'Λ' + 204: 38, # 'Îœ' + 205: 49, # 'Î' + 206: 59, # 'Ξ' + 207: 39, # 'Ο' + 208: 35, # 'Π' + 209: 48, # 'Ρ' + 210: 250, # None + 211: 37, # 'Σ' + 212: 33, # 'Τ' + 213: 45, # 'Î¥' + 214: 56, # 'Φ' + 215: 50, # 'Χ' + 216: 84, # 'Ψ' + 217: 57, # 'Ω' + 218: 120, # 'Ϊ' + 219: 121, # 'Ϋ' + 220: 17, # 'ά' + 221: 18, # 'έ' + 222: 22, # 'ή' + 223: 15, # 'ί' + 224: 124, # 'ΰ' + 225: 1, # 'α' + 226: 29, # 'β' + 227: 20, # 'γ' + 228: 21, # 'δ' + 229: 3, # 'ε' + 230: 32, # 'ζ' + 231: 13, # 'η' + 232: 25, # 'θ' + 233: 5, # 'ι' + 234: 11, # 'κ' + 235: 16, # 'λ' + 236: 10, # 'μ' + 237: 6, # 'ν' + 238: 30, # 'ξ' + 239: 4, # 'ο' + 240: 9, # 'Ï€' + 241: 8, # 'Ï' + 242: 14, # 'Ï‚' + 243: 7, # 'σ' + 244: 2, # 'Ï„' + 245: 12, # 'Ï…' + 246: 28, # 'φ' + 247: 23, # 'χ' + 248: 42, # 'ψ' + 249: 24, # 'ω' + 250: 64, # 'ÏŠ' + 251: 75, # 'Ï‹' + 252: 19, # 'ÏŒ' + 253: 26, # 'Ï' + 254: 27, # 'ÏŽ' + 255: 253, # None +} + +WINDOWS_1253_GREEK_MODEL = SingleByteCharSetModel(charset_name='windows-1253', + language='Greek', + char_to_order_map=WINDOWS_1253_GREEK_CHAR_TO_ORDER, + language_model=GREEK_LANG_MODEL, + typical_positive_ratio=0.982851, + keep_ascii_letters=False, + alphabet='ΆΈΉΊΌΎÎΑΒΓΔΕΖΗΘΙΚΛΜÎΞΟΠΡΣΤΥΦΧΨΩάέήίαβγδεζηθικλμνξοπÏςστυφχψωόÏÏŽ') + +ISO_8859_7_GREEK_CHAR_TO_ORDER = { + 0: 255, # '\x00' + 1: 255, # '\x01' + 2: 255, # '\x02' + 3: 255, # '\x03' + 4: 255, # '\x04' + 5: 255, # '\x05' + 6: 255, # '\x06' + 7: 255, # '\x07' + 8: 255, # '\x08' + 9: 255, # '\t' + 10: 254, # '\n' + 11: 255, # '\x0b' + 12: 255, # '\x0c' + 13: 254, # '\r' + 14: 255, # '\x0e' + 15: 255, # '\x0f' + 16: 255, # '\x10' + 17: 255, # '\x11' + 18: 255, # '\x12' + 19: 255, # '\x13' + 20: 255, # '\x14' + 21: 255, # '\x15' + 22: 255, # '\x16' + 23: 255, # '\x17' + 24: 255, # '\x18' + 25: 255, # '\x19' + 26: 255, # '\x1a' + 27: 255, # '\x1b' + 28: 255, # '\x1c' + 29: 255, # '\x1d' + 30: 255, # '\x1e' + 31: 255, # '\x1f' + 32: 253, # ' ' + 33: 253, # '!' + 34: 253, # '"' + 35: 253, # '#' + 36: 253, # '$' + 37: 253, # '%' + 38: 253, # '&' + 39: 253, # "'" + 40: 253, # '(' + 41: 253, # ')' + 42: 253, # '*' + 43: 253, # '+' + 44: 253, # ',' + 45: 253, # '-' + 46: 253, # '.' + 47: 253, # '/' + 48: 252, # '0' + 49: 252, # '1' + 50: 252, # '2' + 51: 252, # '3' + 52: 252, # '4' + 53: 252, # '5' + 54: 252, # '6' + 55: 252, # '7' + 56: 252, # '8' + 57: 252, # '9' + 58: 253, # ':' + 59: 253, # ';' + 60: 253, # '<' + 61: 253, # '=' + 62: 253, # '>' + 63: 253, # '?' + 64: 253, # '@' + 65: 82, # 'A' + 66: 100, # 'B' + 67: 104, # 'C' + 68: 94, # 'D' + 69: 98, # 'E' + 70: 101, # 'F' + 71: 116, # 'G' + 72: 102, # 'H' + 73: 111, # 'I' + 74: 187, # 'J' + 75: 117, # 'K' + 76: 92, # 'L' + 77: 88, # 'M' + 78: 113, # 'N' + 79: 85, # 'O' + 80: 79, # 'P' + 81: 118, # 'Q' + 82: 105, # 'R' + 83: 83, # 'S' + 84: 67, # 'T' + 85: 114, # 'U' + 86: 119, # 'V' + 87: 95, # 'W' + 88: 99, # 'X' + 89: 109, # 'Y' + 90: 188, # 'Z' + 91: 253, # '[' + 92: 253, # '\\' + 93: 253, # ']' + 94: 253, # '^' + 95: 253, # '_' + 96: 253, # '`' + 97: 72, # 'a' + 98: 70, # 'b' + 99: 80, # 'c' + 100: 81, # 'd' + 101: 60, # 'e' + 102: 96, # 'f' + 103: 93, # 'g' + 104: 89, # 'h' + 105: 68, # 'i' + 106: 120, # 'j' + 107: 97, # 'k' + 108: 77, # 'l' + 109: 86, # 'm' + 110: 69, # 'n' + 111: 55, # 'o' + 112: 78, # 'p' + 113: 115, # 'q' + 114: 65, # 'r' + 115: 66, # 's' + 116: 58, # 't' + 117: 76, # 'u' + 118: 106, # 'v' + 119: 103, # 'w' + 120: 87, # 'x' + 121: 107, # 'y' + 122: 112, # 'z' + 123: 253, # '{' + 124: 253, # '|' + 125: 253, # '}' + 126: 253, # '~' + 127: 253, # '\x7f' + 128: 255, # '\x80' + 129: 255, # '\x81' + 130: 255, # '\x82' + 131: 255, # '\x83' + 132: 255, # '\x84' + 133: 255, # '\x85' + 134: 255, # '\x86' + 135: 255, # '\x87' + 136: 255, # '\x88' + 137: 255, # '\x89' + 138: 255, # '\x8a' + 139: 255, # '\x8b' + 140: 255, # '\x8c' + 141: 255, # '\x8d' + 142: 255, # '\x8e' + 143: 255, # '\x8f' + 144: 255, # '\x90' + 145: 255, # '\x91' + 146: 255, # '\x92' + 147: 255, # '\x93' + 148: 255, # '\x94' + 149: 255, # '\x95' + 150: 255, # '\x96' + 151: 255, # '\x97' + 152: 255, # '\x98' + 153: 255, # '\x99' + 154: 255, # '\x9a' + 155: 255, # '\x9b' + 156: 255, # '\x9c' + 157: 255, # '\x9d' + 158: 255, # '\x9e' + 159: 255, # '\x9f' + 160: 253, # '\xa0' + 161: 233, # '‘' + 162: 90, # '’' + 163: 253, # '£' + 164: 253, # '€' + 165: 253, # '₯' + 166: 253, # '¦' + 167: 253, # '§' + 168: 253, # '¨' + 169: 253, # '©' + 170: 253, # 'ͺ' + 171: 253, # '«' + 172: 253, # '¬' + 173: 74, # '\xad' + 174: 253, # None + 175: 253, # '―' + 176: 253, # '°' + 177: 253, # '±' + 178: 253, # '²' + 179: 253, # '³' + 180: 247, # '΄' + 181: 248, # 'Î…' + 182: 61, # 'Ά' + 183: 36, # '·' + 184: 46, # 'Έ' + 185: 71, # 'Ή' + 186: 73, # 'Ί' + 187: 253, # '»' + 188: 54, # 'ÎŒ' + 189: 253, # '½' + 190: 108, # 'ÎŽ' + 191: 123, # 'Î' + 192: 110, # 'Î' + 193: 31, # 'Α' + 194: 51, # 'Î’' + 195: 43, # 'Γ' + 196: 41, # 'Δ' + 197: 34, # 'Ε' + 198: 91, # 'Ζ' + 199: 40, # 'Η' + 200: 52, # 'Θ' + 201: 47, # 'Ι' + 202: 44, # 'Κ' + 203: 53, # 'Λ' + 204: 38, # 'Îœ' + 205: 49, # 'Î' + 206: 59, # 'Ξ' + 207: 39, # 'Ο' + 208: 35, # 'Π' + 209: 48, # 'Ρ' + 210: 250, # None + 211: 37, # 'Σ' + 212: 33, # 'Τ' + 213: 45, # 'Î¥' + 214: 56, # 'Φ' + 215: 50, # 'Χ' + 216: 84, # 'Ψ' + 217: 57, # 'Ω' + 218: 120, # 'Ϊ' + 219: 121, # 'Ϋ' + 220: 17, # 'ά' + 221: 18, # 'έ' + 222: 22, # 'ή' + 223: 15, # 'ί' + 224: 124, # 'ΰ' + 225: 1, # 'α' + 226: 29, # 'β' + 227: 20, # 'γ' + 228: 21, # 'δ' + 229: 3, # 'ε' + 230: 32, # 'ζ' + 231: 13, # 'η' + 232: 25, # 'θ' + 233: 5, # 'ι' + 234: 11, # 'κ' + 235: 16, # 'λ' + 236: 10, # 'μ' + 237: 6, # 'ν' + 238: 30, # 'ξ' + 239: 4, # 'ο' + 240: 9, # 'Ï€' + 241: 8, # 'Ï' + 242: 14, # 'Ï‚' + 243: 7, # 'σ' + 244: 2, # 'Ï„' + 245: 12, # 'Ï…' + 246: 28, # 'φ' + 247: 23, # 'χ' + 248: 42, # 'ψ' + 249: 24, # 'ω' + 250: 64, # 'ÏŠ' + 251: 75, # 'Ï‹' + 252: 19, # 'ÏŒ' + 253: 26, # 'Ï' + 254: 27, # 'ÏŽ' + 255: 253, # None +} + +ISO_8859_7_GREEK_MODEL = SingleByteCharSetModel(charset_name='ISO-8859-7', + language='Greek', + char_to_order_map=ISO_8859_7_GREEK_CHAR_TO_ORDER, + language_model=GREEK_LANG_MODEL, + typical_positive_ratio=0.982851, + keep_ascii_letters=False, + alphabet='ΆΈΉΊΌΎÎΑΒΓΔΕΖΗΘΙΚΛΜÎΞΟΠΡΣΤΥΦΧΨΩάέήίαβγδεζηθικλμνξοπÏςστυφχψωόÏÏŽ') + diff --git a/venv/Lib/site-packages/pip/_vendor/chardet/langhebrewmodel.py b/venv/Lib/site-packages/pip/_vendor/chardet/langhebrewmodel.py new file mode 100644 index 0000000..484c652 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/chardet/langhebrewmodel.py @@ -0,0 +1,4383 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +from pip._vendor.chardet.sbcharsetprober import SingleByteCharSetModel + + +# 3: Positive +# 2: Likely +# 1: Unlikely +# 0: Negative + +HEBREW_LANG_MODEL = { + 50: { # 'a' + 50: 0, # 'a' + 60: 1, # 'c' + 61: 1, # 'd' + 42: 1, # 'e' + 53: 1, # 'i' + 56: 2, # 'l' + 54: 2, # 'n' + 49: 0, # 'o' + 51: 2, # 'r' + 43: 1, # 's' + 44: 2, # 't' + 63: 1, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 0, # 'Ö°' + 59: 0, # 'Ö±' + 41: 0, # 'Ö²' + 33: 0, # 'Ö´' + 37: 0, # 'Öµ' + 36: 0, # 'Ö¶' + 31: 0, # 'Ö·' + 29: 0, # 'Ö¸' + 35: 0, # 'Ö¹' + 62: 0, # 'Ö»' + 28: 0, # 'Ö¼' + 38: 0, # '×' + 45: 0, # 'ׂ' + 9: 0, # '×' + 8: 0, # 'ב' + 20: 0, # '×’' + 16: 0, # 'ד' + 3: 1, # '×”' + 2: 0, # 'ו' + 24: 0, # '×–' + 14: 0, # '×—' + 22: 0, # 'ט' + 1: 0, # '×™' + 25: 0, # 'ך' + 15: 0, # '×›' + 4: 0, # 'ל' + 11: 0, # '×' + 6: 1, # 'מ' + 23: 0, # 'ן' + 12: 0, # '× ' + 19: 0, # 'ס' + 13: 0, # '×¢' + 26: 0, # '×£' + 18: 0, # 'פ' + 27: 0, # '×¥' + 21: 0, # 'צ' + 17: 1, # 'ק' + 7: 0, # 'ר' + 10: 1, # 'ש' + 5: 0, # 'ת' + 32: 0, # '–' + 52: 1, # '’' + 47: 0, # '“' + 46: 1, # 'â€' + 58: 0, # '†' + 40: 1, # '…' + }, + 60: { # 'c' + 50: 1, # 'a' + 60: 1, # 'c' + 61: 0, # 'd' + 42: 1, # 'e' + 53: 1, # 'i' + 56: 1, # 'l' + 54: 0, # 'n' + 49: 1, # 'o' + 51: 1, # 'r' + 43: 1, # 's' + 44: 2, # 't' + 63: 1, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 0, # 'Ö°' + 59: 0, # 'Ö±' + 41: 0, # 'Ö²' + 33: 0, # 'Ö´' + 37: 0, # 'Öµ' + 36: 0, # 'Ö¶' + 31: 0, # 'Ö·' + 29: 0, # 'Ö¸' + 35: 0, # 'Ö¹' + 62: 0, # 'Ö»' + 28: 0, # 'Ö¼' + 38: 0, # '×' + 45: 0, # 'ׂ' + 9: 1, # '×' + 8: 0, # 'ב' + 20: 0, # '×’' + 16: 0, # 'ד' + 3: 1, # '×”' + 2: 0, # 'ו' + 24: 0, # '×–' + 14: 0, # '×—' + 22: 0, # 'ט' + 1: 0, # '×™' + 25: 0, # 'ך' + 15: 0, # '×›' + 4: 0, # 'ל' + 11: 0, # '×' + 6: 1, # 'מ' + 23: 0, # 'ן' + 12: 1, # '× ' + 19: 0, # 'ס' + 13: 0, # '×¢' + 26: 0, # '×£' + 18: 0, # 'פ' + 27: 0, # '×¥' + 21: 0, # 'צ' + 17: 0, # 'ק' + 7: 0, # 'ר' + 10: 0, # 'ש' + 5: 0, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 1, # 'â€' + 58: 0, # '†' + 40: 1, # '…' + }, + 61: { # 'd' + 50: 1, # 'a' + 60: 0, # 'c' + 61: 1, # 'd' + 42: 1, # 'e' + 53: 1, # 'i' + 56: 1, # 'l' + 54: 1, # 'n' + 49: 2, # 'o' + 51: 1, # 'r' + 43: 1, # 's' + 44: 0, # 't' + 63: 1, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 0, # 'Ö°' + 59: 0, # 'Ö±' + 41: 0, # 'Ö²' + 33: 0, # 'Ö´' + 37: 0, # 'Öµ' + 36: 0, # 'Ö¶' + 31: 0, # 'Ö·' + 29: 0, # 'Ö¸' + 35: 0, # 'Ö¹' + 62: 0, # 'Ö»' + 28: 0, # 'Ö¼' + 38: 0, # '×' + 45: 0, # 'ׂ' + 9: 0, # '×' + 8: 0, # 'ב' + 20: 0, # '×’' + 16: 0, # 'ד' + 3: 1, # '×”' + 2: 0, # 'ו' + 24: 0, # '×–' + 14: 0, # '×—' + 22: 0, # 'ט' + 1: 0, # '×™' + 25: 0, # 'ך' + 15: 0, # '×›' + 4: 0, # 'ל' + 11: 0, # '×' + 6: 0, # 'מ' + 23: 0, # 'ן' + 12: 0, # '× ' + 19: 0, # 'ס' + 13: 0, # '×¢' + 26: 0, # '×£' + 18: 0, # 'פ' + 27: 0, # '×¥' + 21: 0, # 'צ' + 17: 0, # 'ק' + 7: 0, # 'ר' + 10: 0, # 'ש' + 5: 0, # 'ת' + 32: 1, # '–' + 52: 1, # '’' + 47: 0, # '“' + 46: 1, # 'â€' + 58: 0, # '†' + 40: 1, # '…' + }, + 42: { # 'e' + 50: 1, # 'a' + 60: 1, # 'c' + 61: 2, # 'd' + 42: 1, # 'e' + 53: 1, # 'i' + 56: 2, # 'l' + 54: 2, # 'n' + 49: 1, # 'o' + 51: 2, # 'r' + 43: 2, # 's' + 44: 2, # 't' + 63: 1, # 'u' + 34: 1, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 0, # 'Ö°' + 59: 0, # 'Ö±' + 41: 0, # 'Ö²' + 33: 0, # 'Ö´' + 37: 0, # 'Öµ' + 36: 0, # 'Ö¶' + 31: 0, # 'Ö·' + 29: 0, # 'Ö¸' + 35: 0, # 'Ö¹' + 62: 0, # 'Ö»' + 28: 0, # 'Ö¼' + 38: 0, # '×' + 45: 0, # 'ׂ' + 9: 0, # '×' + 8: 0, # 'ב' + 20: 0, # '×’' + 16: 0, # 'ד' + 3: 0, # '×”' + 2: 0, # 'ו' + 24: 0, # '×–' + 14: 0, # '×—' + 22: 0, # 'ט' + 1: 0, # '×™' + 25: 0, # 'ך' + 15: 0, # '×›' + 4: 0, # 'ל' + 11: 0, # '×' + 6: 0, # 'מ' + 23: 0, # 'ן' + 12: 0, # '× ' + 19: 0, # 'ס' + 13: 0, # '×¢' + 26: 0, # '×£' + 18: 1, # 'פ' + 27: 0, # '×¥' + 21: 0, # 'צ' + 17: 0, # 'ק' + 7: 0, # 'ר' + 10: 0, # 'ש' + 5: 0, # 'ת' + 32: 1, # '–' + 52: 2, # '’' + 47: 0, # '“' + 46: 1, # 'â€' + 58: 0, # '†' + 40: 1, # '…' + }, + 53: { # 'i' + 50: 1, # 'a' + 60: 2, # 'c' + 61: 1, # 'd' + 42: 1, # 'e' + 53: 0, # 'i' + 56: 1, # 'l' + 54: 2, # 'n' + 49: 2, # 'o' + 51: 1, # 'r' + 43: 2, # 's' + 44: 2, # 't' + 63: 1, # 'u' + 34: 0, # '\xa0' + 55: 1, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 0, # 'Ö°' + 59: 0, # 'Ö±' + 41: 0, # 'Ö²' + 33: 0, # 'Ö´' + 37: 0, # 'Öµ' + 36: 0, # 'Ö¶' + 31: 0, # 'Ö·' + 29: 0, # 'Ö¸' + 35: 0, # 'Ö¹' + 62: 0, # 'Ö»' + 28: 0, # 'Ö¼' + 38: 0, # '×' + 45: 0, # 'ׂ' + 9: 0, # '×' + 8: 0, # 'ב' + 20: 0, # '×’' + 16: 0, # 'ד' + 3: 0, # '×”' + 2: 0, # 'ו' + 24: 0, # '×–' + 14: 0, # '×—' + 22: 0, # 'ט' + 1: 0, # '×™' + 25: 0, # 'ך' + 15: 0, # '×›' + 4: 0, # 'ל' + 11: 0, # '×' + 6: 0, # 'מ' + 23: 0, # 'ן' + 12: 0, # '× ' + 19: 0, # 'ס' + 13: 0, # '×¢' + 26: 0, # '×£' + 18: 0, # 'פ' + 27: 0, # '×¥' + 21: 0, # 'צ' + 17: 0, # 'ק' + 7: 0, # 'ר' + 10: 0, # 'ש' + 5: 0, # 'ת' + 32: 0, # '–' + 52: 1, # '’' + 47: 0, # '“' + 46: 0, # 'â€' + 58: 0, # '†' + 40: 0, # '…' + }, + 56: { # 'l' + 50: 1, # 'a' + 60: 1, # 'c' + 61: 1, # 'd' + 42: 2, # 'e' + 53: 2, # 'i' + 56: 2, # 'l' + 54: 1, # 'n' + 49: 1, # 'o' + 51: 0, # 'r' + 43: 1, # 's' + 44: 1, # 't' + 63: 1, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 0, # 'Ö°' + 59: 0, # 'Ö±' + 41: 0, # 'Ö²' + 33: 0, # 'Ö´' + 37: 0, # 'Öµ' + 36: 0, # 'Ö¶' + 31: 0, # 'Ö·' + 29: 0, # 'Ö¸' + 35: 0, # 'Ö¹' + 62: 0, # 'Ö»' + 28: 0, # 'Ö¼' + 38: 0, # '×' + 45: 0, # 'ׂ' + 9: 0, # '×' + 8: 0, # 'ב' + 20: 0, # '×’' + 16: 0, # 'ד' + 3: 0, # '×”' + 2: 0, # 'ו' + 24: 0, # '×–' + 14: 0, # '×—' + 22: 0, # 'ט' + 1: 0, # '×™' + 25: 0, # 'ך' + 15: 0, # '×›' + 4: 0, # 'ל' + 11: 0, # '×' + 6: 0, # 'מ' + 23: 0, # 'ן' + 12: 0, # '× ' + 19: 0, # 'ס' + 13: 0, # '×¢' + 26: 0, # '×£' + 18: 0, # 'פ' + 27: 0, # '×¥' + 21: 0, # 'צ' + 17: 0, # 'ק' + 7: 0, # 'ר' + 10: 0, # 'ש' + 5: 0, # 'ת' + 32: 0, # '–' + 52: 1, # '’' + 47: 0, # '“' + 46: 1, # 'â€' + 58: 0, # '†' + 40: 1, # '…' + }, + 54: { # 'n' + 50: 1, # 'a' + 60: 1, # 'c' + 61: 1, # 'd' + 42: 1, # 'e' + 53: 1, # 'i' + 56: 1, # 'l' + 54: 1, # 'n' + 49: 1, # 'o' + 51: 0, # 'r' + 43: 1, # 's' + 44: 2, # 't' + 63: 1, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 0, # 'Ö°' + 59: 0, # 'Ö±' + 41: 0, # 'Ö²' + 33: 0, # 'Ö´' + 37: 0, # 'Öµ' + 36: 0, # 'Ö¶' + 31: 0, # 'Ö·' + 29: 0, # 'Ö¸' + 35: 0, # 'Ö¹' + 62: 0, # 'Ö»' + 28: 0, # 'Ö¼' + 38: 0, # '×' + 45: 0, # 'ׂ' + 9: 0, # '×' + 8: 0, # 'ב' + 20: 0, # '×’' + 16: 0, # 'ד' + 3: 1, # '×”' + 2: 0, # 'ו' + 24: 0, # '×–' + 14: 0, # '×—' + 22: 0, # 'ט' + 1: 0, # '×™' + 25: 0, # 'ך' + 15: 0, # '×›' + 4: 0, # 'ל' + 11: 0, # '×' + 6: 0, # 'מ' + 23: 0, # 'ן' + 12: 0, # '× ' + 19: 0, # 'ס' + 13: 0, # '×¢' + 26: 0, # '×£' + 18: 0, # 'פ' + 27: 0, # '×¥' + 21: 0, # 'צ' + 17: 0, # 'ק' + 7: 0, # 'ר' + 10: 0, # 'ש' + 5: 0, # 'ת' + 32: 0, # '–' + 52: 2, # '’' + 47: 0, # '“' + 46: 1, # 'â€' + 58: 0, # '†' + 40: 1, # '…' + }, + 49: { # 'o' + 50: 1, # 'a' + 60: 1, # 'c' + 61: 1, # 'd' + 42: 1, # 'e' + 53: 1, # 'i' + 56: 1, # 'l' + 54: 2, # 'n' + 49: 1, # 'o' + 51: 2, # 'r' + 43: 1, # 's' + 44: 1, # 't' + 63: 1, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 0, # 'Ö°' + 59: 0, # 'Ö±' + 41: 0, # 'Ö²' + 33: 0, # 'Ö´' + 37: 0, # 'Öµ' + 36: 0, # 'Ö¶' + 31: 0, # 'Ö·' + 29: 0, # 'Ö¸' + 35: 0, # 'Ö¹' + 62: 0, # 'Ö»' + 28: 0, # 'Ö¼' + 38: 0, # '×' + 45: 0, # 'ׂ' + 9: 0, # '×' + 8: 0, # 'ב' + 20: 0, # '×’' + 16: 0, # 'ד' + 3: 0, # '×”' + 2: 0, # 'ו' + 24: 0, # '×–' + 14: 0, # '×—' + 22: 0, # 'ט' + 1: 0, # '×™' + 25: 0, # 'ך' + 15: 0, # '×›' + 4: 0, # 'ל' + 11: 0, # '×' + 6: 0, # 'מ' + 23: 0, # 'ן' + 12: 0, # '× ' + 19: 0, # 'ס' + 13: 0, # '×¢' + 26: 0, # '×£' + 18: 0, # 'פ' + 27: 0, # '×¥' + 21: 0, # 'צ' + 17: 0, # 'ק' + 7: 0, # 'ר' + 10: 0, # 'ש' + 5: 0, # 'ת' + 32: 0, # '–' + 52: 1, # '’' + 47: 0, # '“' + 46: 1, # 'â€' + 58: 0, # '†' + 40: 1, # '…' + }, + 51: { # 'r' + 50: 2, # 'a' + 60: 1, # 'c' + 61: 1, # 'd' + 42: 2, # 'e' + 53: 1, # 'i' + 56: 1, # 'l' + 54: 1, # 'n' + 49: 2, # 'o' + 51: 1, # 'r' + 43: 1, # 's' + 44: 1, # 't' + 63: 1, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 0, # 'Ö°' + 59: 0, # 'Ö±' + 41: 0, # 'Ö²' + 33: 0, # 'Ö´' + 37: 0, # 'Öµ' + 36: 0, # 'Ö¶' + 31: 0, # 'Ö·' + 29: 0, # 'Ö¸' + 35: 0, # 'Ö¹' + 62: 0, # 'Ö»' + 28: 0, # 'Ö¼' + 38: 0, # '×' + 45: 0, # 'ׂ' + 9: 0, # '×' + 8: 0, # 'ב' + 20: 0, # '×’' + 16: 0, # 'ד' + 3: 0, # '×”' + 2: 0, # 'ו' + 24: 0, # '×–' + 14: 0, # '×—' + 22: 0, # 'ט' + 1: 0, # '×™' + 25: 0, # 'ך' + 15: 0, # '×›' + 4: 0, # 'ל' + 11: 0, # '×' + 6: 0, # 'מ' + 23: 0, # 'ן' + 12: 0, # '× ' + 19: 0, # 'ס' + 13: 0, # '×¢' + 26: 0, # '×£' + 18: 0, # 'פ' + 27: 0, # '×¥' + 21: 0, # 'צ' + 17: 0, # 'ק' + 7: 0, # 'ר' + 10: 0, # 'ש' + 5: 0, # 'ת' + 32: 0, # '–' + 52: 2, # '’' + 47: 0, # '“' + 46: 1, # 'â€' + 58: 0, # '†' + 40: 1, # '…' + }, + 43: { # 's' + 50: 1, # 'a' + 60: 1, # 'c' + 61: 0, # 'd' + 42: 2, # 'e' + 53: 1, # 'i' + 56: 1, # 'l' + 54: 1, # 'n' + 49: 1, # 'o' + 51: 1, # 'r' + 43: 1, # 's' + 44: 2, # 't' + 63: 1, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 0, # 'Ö°' + 59: 0, # 'Ö±' + 41: 0, # 'Ö²' + 33: 0, # 'Ö´' + 37: 0, # 'Öµ' + 36: 0, # 'Ö¶' + 31: 0, # 'Ö·' + 29: 0, # 'Ö¸' + 35: 0, # 'Ö¹' + 62: 0, # 'Ö»' + 28: 0, # 'Ö¼' + 38: 0, # '×' + 45: 0, # 'ׂ' + 9: 0, # '×' + 8: 0, # 'ב' + 20: 0, # '×’' + 16: 0, # 'ד' + 3: 0, # '×”' + 2: 0, # 'ו' + 24: 0, # '×–' + 14: 0, # '×—' + 22: 0, # 'ט' + 1: 0, # '×™' + 25: 0, # 'ך' + 15: 0, # '×›' + 4: 0, # 'ל' + 11: 0, # '×' + 6: 0, # 'מ' + 23: 0, # 'ן' + 12: 0, # '× ' + 19: 0, # 'ס' + 13: 0, # '×¢' + 26: 0, # '×£' + 18: 0, # 'פ' + 27: 0, # '×¥' + 21: 0, # 'צ' + 17: 0, # 'ק' + 7: 0, # 'ר' + 10: 0, # 'ש' + 5: 0, # 'ת' + 32: 0, # '–' + 52: 1, # '’' + 47: 0, # '“' + 46: 2, # 'â€' + 58: 0, # '†' + 40: 2, # '…' + }, + 44: { # 't' + 50: 1, # 'a' + 60: 1, # 'c' + 61: 0, # 'd' + 42: 2, # 'e' + 53: 2, # 'i' + 56: 1, # 'l' + 54: 0, # 'n' + 49: 1, # 'o' + 51: 1, # 'r' + 43: 1, # 's' + 44: 1, # 't' + 63: 1, # 'u' + 34: 1, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 0, # 'Ö°' + 59: 0, # 'Ö±' + 41: 0, # 'Ö²' + 33: 0, # 'Ö´' + 37: 0, # 'Öµ' + 36: 0, # 'Ö¶' + 31: 0, # 'Ö·' + 29: 0, # 'Ö¸' + 35: 0, # 'Ö¹' + 62: 0, # 'Ö»' + 28: 0, # 'Ö¼' + 38: 0, # '×' + 45: 0, # 'ׂ' + 9: 0, # '×' + 8: 0, # 'ב' + 20: 0, # '×’' + 16: 0, # 'ד' + 3: 0, # '×”' + 2: 0, # 'ו' + 24: 0, # '×–' + 14: 0, # '×—' + 22: 0, # 'ט' + 1: 0, # '×™' + 25: 0, # 'ך' + 15: 0, # '×›' + 4: 0, # 'ל' + 11: 0, # '×' + 6: 0, # 'מ' + 23: 0, # 'ן' + 12: 0, # '× ' + 19: 0, # 'ס' + 13: 0, # '×¢' + 26: 0, # '×£' + 18: 0, # 'פ' + 27: 0, # '×¥' + 21: 0, # 'צ' + 17: 0, # 'ק' + 7: 0, # 'ר' + 10: 0, # 'ש' + 5: 0, # 'ת' + 32: 0, # '–' + 52: 2, # '’' + 47: 0, # '“' + 46: 1, # 'â€' + 58: 0, # '†' + 40: 1, # '…' + }, + 63: { # 'u' + 50: 1, # 'a' + 60: 1, # 'c' + 61: 1, # 'd' + 42: 1, # 'e' + 53: 1, # 'i' + 56: 1, # 'l' + 54: 1, # 'n' + 49: 0, # 'o' + 51: 1, # 'r' + 43: 2, # 's' + 44: 1, # 't' + 63: 0, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 0, # 'Ö°' + 59: 0, # 'Ö±' + 41: 0, # 'Ö²' + 33: 0, # 'Ö´' + 37: 0, # 'Öµ' + 36: 0, # 'Ö¶' + 31: 0, # 'Ö·' + 29: 0, # 'Ö¸' + 35: 0, # 'Ö¹' + 62: 0, # 'Ö»' + 28: 0, # 'Ö¼' + 38: 0, # '×' + 45: 0, # 'ׂ' + 9: 0, # '×' + 8: 0, # 'ב' + 20: 0, # '×’' + 16: 0, # 'ד' + 3: 0, # '×”' + 2: 0, # 'ו' + 24: 0, # '×–' + 14: 0, # '×—' + 22: 0, # 'ט' + 1: 0, # '×™' + 25: 0, # 'ך' + 15: 0, # '×›' + 4: 0, # 'ל' + 11: 0, # '×' + 6: 0, # 'מ' + 23: 0, # 'ן' + 12: 0, # '× ' + 19: 0, # 'ס' + 13: 0, # '×¢' + 26: 0, # '×£' + 18: 0, # 'פ' + 27: 0, # '×¥' + 21: 0, # 'צ' + 17: 0, # 'ק' + 7: 0, # 'ר' + 10: 0, # 'ש' + 5: 0, # 'ת' + 32: 0, # '–' + 52: 1, # '’' + 47: 0, # '“' + 46: 0, # 'â€' + 58: 0, # '†' + 40: 0, # '…' + }, + 34: { # '\xa0' + 50: 1, # 'a' + 60: 0, # 'c' + 61: 1, # 'd' + 42: 0, # 'e' + 53: 1, # 'i' + 56: 0, # 'l' + 54: 1, # 'n' + 49: 1, # 'o' + 51: 0, # 'r' + 43: 1, # 's' + 44: 1, # 't' + 63: 0, # 'u' + 34: 2, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 0, # 'Ö°' + 59: 0, # 'Ö±' + 41: 0, # 'Ö²' + 33: 0, # 'Ö´' + 37: 0, # 'Öµ' + 36: 0, # 'Ö¶' + 31: 0, # 'Ö·' + 29: 0, # 'Ö¸' + 35: 0, # 'Ö¹' + 62: 0, # 'Ö»' + 28: 0, # 'Ö¼' + 38: 0, # '×' + 45: 0, # 'ׂ' + 9: 2, # '×' + 8: 1, # 'ב' + 20: 1, # '×’' + 16: 1, # 'ד' + 3: 1, # '×”' + 2: 1, # 'ו' + 24: 1, # '×–' + 14: 1, # '×—' + 22: 1, # 'ט' + 1: 2, # '×™' + 25: 0, # 'ך' + 15: 1, # '×›' + 4: 1, # 'ל' + 11: 0, # '×' + 6: 2, # 'מ' + 23: 0, # 'ן' + 12: 1, # '× ' + 19: 1, # 'ס' + 13: 1, # '×¢' + 26: 0, # '×£' + 18: 1, # 'פ' + 27: 0, # '×¥' + 21: 1, # 'צ' + 17: 1, # 'ק' + 7: 1, # 'ר' + 10: 1, # 'ש' + 5: 1, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 0, # 'â€' + 58: 0, # '†' + 40: 0, # '…' + }, + 55: { # '´' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 1, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 0, # 'Ö°' + 59: 0, # 'Ö±' + 41: 0, # 'Ö²' + 33: 0, # 'Ö´' + 37: 0, # 'Öµ' + 36: 0, # 'Ö¶' + 31: 0, # 'Ö·' + 29: 0, # 'Ö¸' + 35: 0, # 'Ö¹' + 62: 0, # 'Ö»' + 28: 0, # 'Ö¼' + 38: 0, # '×' + 45: 0, # 'ׂ' + 9: 1, # '×' + 8: 0, # 'ב' + 20: 0, # '×’' + 16: 0, # 'ד' + 3: 1, # '×”' + 2: 1, # 'ו' + 24: 0, # '×–' + 14: 0, # '×—' + 22: 0, # 'ט' + 1: 2, # '×™' + 25: 0, # 'ך' + 15: 0, # '×›' + 4: 1, # 'ל' + 11: 0, # '×' + 6: 1, # 'מ' + 23: 1, # 'ן' + 12: 1, # '× ' + 19: 1, # 'ס' + 13: 0, # '×¢' + 26: 0, # '×£' + 18: 0, # 'פ' + 27: 0, # '×¥' + 21: 0, # 'צ' + 17: 0, # 'ק' + 7: 1, # 'ר' + 10: 1, # 'ש' + 5: 0, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 0, # 'â€' + 58: 0, # '†' + 40: 0, # '…' + }, + 48: { # '¼' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 0, # 'Ö°' + 59: 0, # 'Ö±' + 41: 0, # 'Ö²' + 33: 0, # 'Ö´' + 37: 0, # 'Öµ' + 36: 0, # 'Ö¶' + 31: 0, # 'Ö·' + 29: 0, # 'Ö¸' + 35: 0, # 'Ö¹' + 62: 0, # 'Ö»' + 28: 0, # 'Ö¼' + 38: 0, # '×' + 45: 0, # 'ׂ' + 9: 1, # '×' + 8: 0, # 'ב' + 20: 0, # '×’' + 16: 0, # 'ד' + 3: 0, # '×”' + 2: 1, # 'ו' + 24: 0, # '×–' + 14: 0, # '×—' + 22: 0, # 'ט' + 1: 0, # '×™' + 25: 0, # 'ך' + 15: 1, # '×›' + 4: 1, # 'ל' + 11: 0, # '×' + 6: 1, # 'מ' + 23: 0, # 'ן' + 12: 0, # '× ' + 19: 0, # 'ס' + 13: 0, # '×¢' + 26: 0, # '×£' + 18: 0, # 'פ' + 27: 0, # '×¥' + 21: 0, # 'צ' + 17: 0, # 'ק' + 7: 0, # 'ר' + 10: 0, # 'ש' + 5: 0, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 0, # 'â€' + 58: 0, # '†' + 40: 0, # '…' + }, + 39: { # '½' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 0, # 'Ö°' + 59: 0, # 'Ö±' + 41: 0, # 'Ö²' + 33: 0, # 'Ö´' + 37: 0, # 'Öµ' + 36: 0, # 'Ö¶' + 31: 0, # 'Ö·' + 29: 0, # 'Ö¸' + 35: 0, # 'Ö¹' + 62: 0, # 'Ö»' + 28: 0, # 'Ö¼' + 38: 0, # '×' + 45: 0, # 'ׂ' + 9: 0, # '×' + 8: 0, # 'ב' + 20: 0, # '×’' + 16: 0, # 'ד' + 3: 0, # '×”' + 2: 0, # 'ו' + 24: 0, # '×–' + 14: 0, # '×—' + 22: 0, # 'ט' + 1: 0, # '×™' + 25: 0, # 'ך' + 15: 1, # '×›' + 4: 1, # 'ל' + 11: 0, # '×' + 6: 0, # 'מ' + 23: 0, # 'ן' + 12: 0, # '× ' + 19: 0, # 'ס' + 13: 0, # '×¢' + 26: 0, # '×£' + 18: 0, # 'פ' + 27: 0, # '×¥' + 21: 1, # 'צ' + 17: 1, # 'ק' + 7: 0, # 'ר' + 10: 0, # 'ש' + 5: 0, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 0, # 'â€' + 58: 0, # '†' + 40: 0, # '…' + }, + 57: { # '¾' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 0, # 'Ö°' + 59: 0, # 'Ö±' + 41: 0, # 'Ö²' + 33: 0, # 'Ö´' + 37: 0, # 'Öµ' + 36: 0, # 'Ö¶' + 31: 0, # 'Ö·' + 29: 0, # 'Ö¸' + 35: 0, # 'Ö¹' + 62: 0, # 'Ö»' + 28: 0, # 'Ö¼' + 38: 0, # '×' + 45: 0, # 'ׂ' + 9: 0, # '×' + 8: 0, # 'ב' + 20: 0, # '×’' + 16: 0, # 'ד' + 3: 0, # '×”' + 2: 0, # 'ו' + 24: 0, # '×–' + 14: 0, # '×—' + 22: 0, # 'ט' + 1: 0, # '×™' + 25: 0, # 'ך' + 15: 0, # '×›' + 4: 0, # 'ל' + 11: 0, # '×' + 6: 0, # 'מ' + 23: 0, # 'ן' + 12: 0, # '× ' + 19: 0, # 'ס' + 13: 0, # '×¢' + 26: 0, # '×£' + 18: 0, # 'פ' + 27: 0, # '×¥' + 21: 0, # 'צ' + 17: 0, # 'ק' + 7: 0, # 'ר' + 10: 0, # 'ש' + 5: 0, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 0, # 'â€' + 58: 0, # '†' + 40: 0, # '…' + }, + 30: { # 'Ö°' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 0, # 'Ö°' + 59: 0, # 'Ö±' + 41: 0, # 'Ö²' + 33: 0, # 'Ö´' + 37: 0, # 'Öµ' + 36: 1, # 'Ö¶' + 31: 0, # 'Ö·' + 29: 0, # 'Ö¸' + 35: 1, # 'Ö¹' + 62: 0, # 'Ö»' + 28: 0, # 'Ö¼' + 38: 0, # '×' + 45: 0, # 'ׂ' + 9: 2, # '×' + 8: 2, # 'ב' + 20: 2, # '×’' + 16: 2, # 'ד' + 3: 2, # '×”' + 2: 2, # 'ו' + 24: 2, # '×–' + 14: 2, # '×—' + 22: 2, # 'ט' + 1: 2, # '×™' + 25: 2, # 'ך' + 15: 2, # '×›' + 4: 2, # 'ל' + 11: 1, # '×' + 6: 2, # 'מ' + 23: 0, # 'ן' + 12: 2, # '× ' + 19: 2, # 'ס' + 13: 2, # '×¢' + 26: 0, # '×£' + 18: 2, # 'פ' + 27: 0, # '×¥' + 21: 2, # 'צ' + 17: 2, # 'ק' + 7: 2, # 'ר' + 10: 2, # 'ש' + 5: 2, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 0, # 'â€' + 58: 0, # '†' + 40: 0, # '…' + }, + 59: { # 'Ö±' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 1, # 'Ö°' + 59: 0, # 'Ö±' + 41: 0, # 'Ö²' + 33: 0, # 'Ö´' + 37: 0, # 'Öµ' + 36: 0, # 'Ö¶' + 31: 0, # 'Ö·' + 29: 0, # 'Ö¸' + 35: 0, # 'Ö¹' + 62: 0, # 'Ö»' + 28: 0, # 'Ö¼' + 38: 0, # '×' + 45: 0, # 'ׂ' + 9: 0, # '×' + 8: 1, # 'ב' + 20: 1, # '×’' + 16: 0, # 'ד' + 3: 0, # '×”' + 2: 0, # 'ו' + 24: 1, # '×–' + 14: 0, # '×—' + 22: 0, # 'ט' + 1: 1, # '×™' + 25: 0, # 'ך' + 15: 1, # '×›' + 4: 2, # 'ל' + 11: 0, # '×' + 6: 2, # 'מ' + 23: 0, # 'ן' + 12: 1, # '× ' + 19: 0, # 'ס' + 13: 0, # '×¢' + 26: 0, # '×£' + 18: 0, # 'פ' + 27: 0, # '×¥' + 21: 0, # 'צ' + 17: 0, # 'ק' + 7: 1, # 'ר' + 10: 1, # 'ש' + 5: 0, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 0, # 'â€' + 58: 0, # '†' + 40: 0, # '…' + }, + 41: { # 'Ö²' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 0, # 'Ö°' + 59: 0, # 'Ö±' + 41: 0, # 'Ö²' + 33: 0, # 'Ö´' + 37: 0, # 'Öµ' + 36: 0, # 'Ö¶' + 31: 0, # 'Ö·' + 29: 0, # 'Ö¸' + 35: 0, # 'Ö¹' + 62: 0, # 'Ö»' + 28: 0, # 'Ö¼' + 38: 0, # '×' + 45: 0, # 'ׂ' + 9: 0, # '×' + 8: 2, # 'ב' + 20: 1, # '×’' + 16: 2, # 'ד' + 3: 1, # '×”' + 2: 1, # 'ו' + 24: 1, # '×–' + 14: 1, # '×—' + 22: 1, # 'ט' + 1: 1, # '×™' + 25: 1, # 'ך' + 15: 1, # '×›' + 4: 2, # 'ל' + 11: 0, # '×' + 6: 2, # 'מ' + 23: 0, # 'ן' + 12: 2, # '× ' + 19: 1, # 'ס' + 13: 0, # '×¢' + 26: 0, # '×£' + 18: 1, # 'פ' + 27: 0, # '×¥' + 21: 2, # 'צ' + 17: 1, # 'ק' + 7: 2, # 'ר' + 10: 2, # 'ש' + 5: 1, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 0, # 'â€' + 58: 0, # '†' + 40: 0, # '…' + }, + 33: { # 'Ö´' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 1, # 'Ö°' + 59: 0, # 'Ö±' + 41: 0, # 'Ö²' + 33: 1, # 'Ö´' + 37: 0, # 'Öµ' + 36: 1, # 'Ö¶' + 31: 0, # 'Ö·' + 29: 1, # 'Ö¸' + 35: 0, # 'Ö¹' + 62: 0, # 'Ö»' + 28: 1, # 'Ö¼' + 38: 0, # '×' + 45: 0, # 'ׂ' + 9: 1, # '×' + 8: 2, # 'ב' + 20: 2, # '×’' + 16: 2, # 'ד' + 3: 1, # '×”' + 2: 1, # 'ו' + 24: 2, # '×–' + 14: 1, # '×—' + 22: 1, # 'ט' + 1: 3, # '×™' + 25: 1, # 'ך' + 15: 2, # '×›' + 4: 2, # 'ל' + 11: 2, # '×' + 6: 2, # 'מ' + 23: 2, # 'ן' + 12: 2, # '× ' + 19: 2, # 'ס' + 13: 1, # '×¢' + 26: 0, # '×£' + 18: 2, # 'פ' + 27: 1, # '×¥' + 21: 2, # 'צ' + 17: 2, # 'ק' + 7: 2, # 'ר' + 10: 2, # 'ש' + 5: 2, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 0, # 'â€' + 58: 0, # '†' + 40: 0, # '…' + }, + 37: { # 'Öµ' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 0, # 'Ö°' + 59: 0, # 'Ö±' + 41: 0, # 'Ö²' + 33: 0, # 'Ö´' + 37: 0, # 'Öµ' + 36: 1, # 'Ö¶' + 31: 1, # 'Ö·' + 29: 1, # 'Ö¸' + 35: 0, # 'Ö¹' + 62: 0, # 'Ö»' + 28: 0, # 'Ö¼' + 38: 0, # '×' + 45: 0, # 'ׂ' + 9: 2, # '×' + 8: 2, # 'ב' + 20: 1, # '×’' + 16: 2, # 'ד' + 3: 2, # '×”' + 2: 1, # 'ו' + 24: 1, # '×–' + 14: 2, # '×—' + 22: 1, # 'ט' + 1: 3, # '×™' + 25: 2, # 'ך' + 15: 1, # '×›' + 4: 2, # 'ל' + 11: 2, # '×' + 6: 1, # 'מ' + 23: 2, # 'ן' + 12: 2, # '× ' + 19: 1, # 'ס' + 13: 2, # '×¢' + 26: 1, # '×£' + 18: 1, # 'פ' + 27: 1, # '×¥' + 21: 1, # 'צ' + 17: 1, # 'ק' + 7: 2, # 'ר' + 10: 2, # 'ש' + 5: 2, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 0, # 'â€' + 58: 0, # '†' + 40: 0, # '…' + }, + 36: { # 'Ö¶' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 0, # 'Ö°' + 59: 0, # 'Ö±' + 41: 0, # 'Ö²' + 33: 0, # 'Ö´' + 37: 0, # 'Öµ' + 36: 1, # 'Ö¶' + 31: 1, # 'Ö·' + 29: 1, # 'Ö¸' + 35: 0, # 'Ö¹' + 62: 0, # 'Ö»' + 28: 0, # 'Ö¼' + 38: 0, # '×' + 45: 0, # 'ׂ' + 9: 2, # '×' + 8: 2, # 'ב' + 20: 1, # '×’' + 16: 2, # 'ד' + 3: 2, # '×”' + 2: 1, # 'ו' + 24: 1, # '×–' + 14: 2, # '×—' + 22: 1, # 'ט' + 1: 2, # '×™' + 25: 2, # 'ך' + 15: 1, # '×›' + 4: 2, # 'ל' + 11: 2, # '×' + 6: 2, # 'מ' + 23: 2, # 'ן' + 12: 2, # '× ' + 19: 2, # 'ס' + 13: 1, # '×¢' + 26: 1, # '×£' + 18: 1, # 'פ' + 27: 2, # '×¥' + 21: 1, # 'צ' + 17: 1, # 'ק' + 7: 2, # 'ר' + 10: 2, # 'ש' + 5: 2, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 0, # 'â€' + 58: 0, # '†' + 40: 0, # '…' + }, + 31: { # 'Ö·' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 1, # 'Ö°' + 59: 0, # 'Ö±' + 41: 0, # 'Ö²' + 33: 0, # 'Ö´' + 37: 0, # 'Öµ' + 36: 1, # 'Ö¶' + 31: 0, # 'Ö·' + 29: 2, # 'Ö¸' + 35: 0, # 'Ö¹' + 62: 0, # 'Ö»' + 28: 0, # 'Ö¼' + 38: 0, # '×' + 45: 0, # 'ׂ' + 9: 2, # '×' + 8: 2, # 'ב' + 20: 2, # '×’' + 16: 2, # 'ד' + 3: 2, # '×”' + 2: 1, # 'ו' + 24: 2, # '×–' + 14: 2, # '×—' + 22: 2, # 'ט' + 1: 3, # '×™' + 25: 1, # 'ך' + 15: 2, # '×›' + 4: 2, # 'ל' + 11: 2, # '×' + 6: 2, # 'מ' + 23: 2, # 'ן' + 12: 2, # '× ' + 19: 2, # 'ס' + 13: 2, # '×¢' + 26: 2, # '×£' + 18: 2, # 'פ' + 27: 1, # '×¥' + 21: 2, # 'צ' + 17: 2, # 'ק' + 7: 2, # 'ר' + 10: 2, # 'ש' + 5: 2, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 0, # 'â€' + 58: 0, # '†' + 40: 0, # '…' + }, + 29: { # 'Ö¸' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 0, # 'Ö°' + 59: 0, # 'Ö±' + 41: 0, # 'Ö²' + 33: 0, # 'Ö´' + 37: 0, # 'Öµ' + 36: 0, # 'Ö¶' + 31: 1, # 'Ö·' + 29: 2, # 'Ö¸' + 35: 0, # 'Ö¹' + 62: 0, # 'Ö»' + 28: 1, # 'Ö¼' + 38: 0, # '×' + 45: 0, # 'ׂ' + 9: 2, # '×' + 8: 2, # 'ב' + 20: 2, # '×’' + 16: 2, # 'ד' + 3: 3, # '×”' + 2: 2, # 'ו' + 24: 2, # '×–' + 14: 2, # '×—' + 22: 1, # 'ט' + 1: 2, # '×™' + 25: 2, # 'ך' + 15: 2, # '×›' + 4: 2, # 'ל' + 11: 2, # '×' + 6: 2, # 'מ' + 23: 2, # 'ן' + 12: 2, # '× ' + 19: 1, # 'ס' + 13: 2, # '×¢' + 26: 1, # '×£' + 18: 2, # 'פ' + 27: 1, # '×¥' + 21: 2, # 'צ' + 17: 2, # 'ק' + 7: 2, # 'ר' + 10: 2, # 'ש' + 5: 2, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 0, # 'â€' + 58: 0, # '†' + 40: 0, # '…' + }, + 35: { # 'Ö¹' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 0, # 'Ö°' + 59: 0, # 'Ö±' + 41: 0, # 'Ö²' + 33: 0, # 'Ö´' + 37: 0, # 'Öµ' + 36: 0, # 'Ö¶' + 31: 0, # 'Ö·' + 29: 0, # 'Ö¸' + 35: 1, # 'Ö¹' + 62: 0, # 'Ö»' + 28: 0, # 'Ö¼' + 38: 0, # '×' + 45: 0, # 'ׂ' + 9: 2, # '×' + 8: 2, # 'ב' + 20: 1, # '×’' + 16: 2, # 'ד' + 3: 2, # '×”' + 2: 1, # 'ו' + 24: 1, # '×–' + 14: 1, # '×—' + 22: 1, # 'ט' + 1: 1, # '×™' + 25: 1, # 'ך' + 15: 2, # '×›' + 4: 2, # 'ל' + 11: 2, # '×' + 6: 2, # 'מ' + 23: 2, # 'ן' + 12: 2, # '× ' + 19: 2, # 'ס' + 13: 2, # '×¢' + 26: 1, # '×£' + 18: 2, # 'פ' + 27: 1, # '×¥' + 21: 2, # 'צ' + 17: 2, # 'ק' + 7: 2, # 'ר' + 10: 2, # 'ש' + 5: 2, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 0, # 'â€' + 58: 0, # '†' + 40: 0, # '…' + }, + 62: { # 'Ö»' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 0, # 'Ö°' + 59: 0, # 'Ö±' + 41: 0, # 'Ö²' + 33: 0, # 'Ö´' + 37: 0, # 'Öµ' + 36: 0, # 'Ö¶' + 31: 0, # 'Ö·' + 29: 0, # 'Ö¸' + 35: 0, # 'Ö¹' + 62: 0, # 'Ö»' + 28: 0, # 'Ö¼' + 38: 0, # '×' + 45: 0, # 'ׂ' + 9: 0, # '×' + 8: 1, # 'ב' + 20: 1, # '×’' + 16: 1, # 'ד' + 3: 1, # '×”' + 2: 1, # 'ו' + 24: 1, # '×–' + 14: 1, # '×—' + 22: 0, # 'ט' + 1: 1, # '×™' + 25: 0, # 'ך' + 15: 1, # '×›' + 4: 2, # 'ל' + 11: 1, # '×' + 6: 1, # 'מ' + 23: 1, # 'ן' + 12: 1, # '× ' + 19: 1, # 'ס' + 13: 1, # '×¢' + 26: 0, # '×£' + 18: 1, # 'פ' + 27: 0, # '×¥' + 21: 1, # 'צ' + 17: 1, # 'ק' + 7: 1, # 'ר' + 10: 1, # 'ש' + 5: 1, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 0, # 'â€' + 58: 0, # '†' + 40: 0, # '…' + }, + 28: { # 'Ö¼' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 3, # 'Ö°' + 59: 0, # 'Ö±' + 41: 1, # 'Ö²' + 33: 3, # 'Ö´' + 37: 2, # 'Öµ' + 36: 2, # 'Ö¶' + 31: 3, # 'Ö·' + 29: 3, # 'Ö¸' + 35: 2, # 'Ö¹' + 62: 1, # 'Ö»' + 28: 0, # 'Ö¼' + 38: 2, # '×' + 45: 1, # 'ׂ' + 9: 2, # '×' + 8: 2, # 'ב' + 20: 1, # '×’' + 16: 2, # 'ד' + 3: 1, # '×”' + 2: 2, # 'ו' + 24: 1, # '×–' + 14: 1, # '×—' + 22: 1, # 'ט' + 1: 2, # '×™' + 25: 2, # 'ך' + 15: 2, # '×›' + 4: 2, # 'ל' + 11: 1, # '×' + 6: 2, # 'מ' + 23: 1, # 'ן' + 12: 2, # '× ' + 19: 1, # 'ס' + 13: 2, # '×¢' + 26: 1, # '×£' + 18: 1, # 'פ' + 27: 1, # '×¥' + 21: 1, # 'צ' + 17: 1, # 'ק' + 7: 2, # 'ר' + 10: 2, # 'ש' + 5: 2, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 0, # 'â€' + 58: 0, # '†' + 40: 0, # '…' + }, + 38: { # '×' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 2, # 'Ö°' + 59: 0, # 'Ö±' + 41: 0, # 'Ö²' + 33: 2, # 'Ö´' + 37: 2, # 'Öµ' + 36: 2, # 'Ö¶' + 31: 2, # 'Ö·' + 29: 2, # 'Ö¸' + 35: 1, # 'Ö¹' + 62: 1, # 'Ö»' + 28: 0, # 'Ö¼' + 38: 0, # '×' + 45: 0, # 'ׂ' + 9: 0, # '×' + 8: 0, # 'ב' + 20: 0, # '×’' + 16: 0, # 'ד' + 3: 0, # '×”' + 2: 2, # 'ו' + 24: 0, # '×–' + 14: 0, # '×—' + 22: 0, # 'ט' + 1: 1, # '×™' + 25: 0, # 'ך' + 15: 0, # '×›' + 4: 0, # 'ל' + 11: 0, # '×' + 6: 0, # 'מ' + 23: 0, # 'ן' + 12: 0, # '× ' + 19: 0, # 'ס' + 13: 1, # '×¢' + 26: 0, # '×£' + 18: 0, # 'פ' + 27: 0, # '×¥' + 21: 0, # 'צ' + 17: 0, # 'ק' + 7: 0, # 'ר' + 10: 0, # 'ש' + 5: 0, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 0, # 'â€' + 58: 0, # '†' + 40: 0, # '…' + }, + 45: { # 'ׂ' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 2, # 'Ö°' + 59: 0, # 'Ö±' + 41: 0, # 'Ö²' + 33: 2, # 'Ö´' + 37: 1, # 'Öµ' + 36: 2, # 'Ö¶' + 31: 1, # 'Ö·' + 29: 2, # 'Ö¸' + 35: 1, # 'Ö¹' + 62: 0, # 'Ö»' + 28: 0, # 'Ö¼' + 38: 0, # '×' + 45: 0, # 'ׂ' + 9: 1, # '×' + 8: 0, # 'ב' + 20: 1, # '×’' + 16: 0, # 'ד' + 3: 1, # '×”' + 2: 2, # 'ו' + 24: 0, # '×–' + 14: 1, # '×—' + 22: 0, # 'ט' + 1: 1, # '×™' + 25: 0, # 'ך' + 15: 0, # '×›' + 4: 0, # 'ל' + 11: 1, # '×' + 6: 1, # 'מ' + 23: 0, # 'ן' + 12: 1, # '× ' + 19: 0, # 'ס' + 13: 1, # '×¢' + 26: 0, # '×£' + 18: 1, # 'פ' + 27: 0, # '×¥' + 21: 0, # 'צ' + 17: 0, # 'ק' + 7: 1, # 'ר' + 10: 0, # 'ש' + 5: 1, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 0, # 'â€' + 58: 0, # '†' + 40: 0, # '…' + }, + 9: { # '×' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 1, # '\xa0' + 55: 1, # '´' + 48: 1, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 0, # 'Ö°' + 59: 2, # 'Ö±' + 41: 2, # 'Ö²' + 33: 2, # 'Ö´' + 37: 2, # 'Öµ' + 36: 2, # 'Ö¶' + 31: 2, # 'Ö·' + 29: 2, # 'Ö¸' + 35: 2, # 'Ö¹' + 62: 1, # 'Ö»' + 28: 0, # 'Ö¼' + 38: 0, # '×' + 45: 0, # 'ׂ' + 9: 2, # '×' + 8: 3, # 'ב' + 20: 3, # '×’' + 16: 3, # 'ד' + 3: 3, # '×”' + 2: 3, # 'ו' + 24: 3, # '×–' + 14: 3, # '×—' + 22: 3, # 'ט' + 1: 3, # '×™' + 25: 3, # 'ך' + 15: 3, # '×›' + 4: 3, # 'ל' + 11: 3, # '×' + 6: 3, # 'מ' + 23: 3, # 'ן' + 12: 3, # '× ' + 19: 3, # 'ס' + 13: 2, # '×¢' + 26: 3, # '×£' + 18: 3, # 'פ' + 27: 1, # '×¥' + 21: 3, # 'צ' + 17: 3, # 'ק' + 7: 3, # 'ר' + 10: 3, # 'ש' + 5: 3, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 1, # 'â€' + 58: 0, # '†' + 40: 1, # '…' + }, + 8: { # 'ב' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 1, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 1, # '\xa0' + 55: 1, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 2, # 'Ö°' + 59: 0, # 'Ö±' + 41: 0, # 'Ö²' + 33: 2, # 'Ö´' + 37: 2, # 'Öµ' + 36: 2, # 'Ö¶' + 31: 2, # 'Ö·' + 29: 2, # 'Ö¸' + 35: 2, # 'Ö¹' + 62: 1, # 'Ö»' + 28: 3, # 'Ö¼' + 38: 0, # '×' + 45: 0, # 'ׂ' + 9: 3, # '×' + 8: 3, # 'ב' + 20: 3, # '×’' + 16: 3, # 'ד' + 3: 3, # '×”' + 2: 3, # 'ו' + 24: 3, # '×–' + 14: 3, # '×—' + 22: 3, # 'ט' + 1: 3, # '×™' + 25: 2, # 'ך' + 15: 3, # '×›' + 4: 3, # 'ל' + 11: 2, # '×' + 6: 3, # 'מ' + 23: 3, # 'ן' + 12: 3, # '× ' + 19: 3, # 'ס' + 13: 3, # '×¢' + 26: 1, # '×£' + 18: 3, # 'פ' + 27: 2, # '×¥' + 21: 3, # 'צ' + 17: 3, # 'ק' + 7: 3, # 'ר' + 10: 3, # 'ש' + 5: 3, # 'ת' + 32: 1, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 1, # 'â€' + 58: 0, # '†' + 40: 1, # '…' + }, + 20: { # '×’' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 1, # '\xa0' + 55: 2, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 2, # 'Ö°' + 59: 0, # 'Ö±' + 41: 0, # 'Ö²' + 33: 1, # 'Ö´' + 37: 1, # 'Öµ' + 36: 1, # 'Ö¶' + 31: 2, # 'Ö·' + 29: 2, # 'Ö¸' + 35: 1, # 'Ö¹' + 62: 0, # 'Ö»' + 28: 2, # 'Ö¼' + 38: 0, # '×' + 45: 0, # 'ׂ' + 9: 2, # '×' + 8: 3, # 'ב' + 20: 2, # '×’' + 16: 3, # 'ד' + 3: 3, # '×”' + 2: 3, # 'ו' + 24: 3, # '×–' + 14: 2, # '×—' + 22: 2, # 'ט' + 1: 3, # '×™' + 25: 1, # 'ך' + 15: 1, # '×›' + 4: 3, # 'ל' + 11: 3, # '×' + 6: 3, # 'מ' + 23: 3, # 'ן' + 12: 3, # '× ' + 19: 2, # 'ס' + 13: 3, # '×¢' + 26: 2, # '×£' + 18: 2, # 'פ' + 27: 1, # '×¥' + 21: 1, # 'צ' + 17: 1, # 'ק' + 7: 3, # 'ר' + 10: 3, # 'ש' + 5: 3, # 'ת' + 32: 0, # '–' + 52: 1, # '’' + 47: 0, # '“' + 46: 1, # 'â€' + 58: 0, # '†' + 40: 0, # '…' + }, + 16: { # 'ד' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 2, # 'Ö°' + 59: 0, # 'Ö±' + 41: 0, # 'Ö²' + 33: 2, # 'Ö´' + 37: 2, # 'Öµ' + 36: 2, # 'Ö¶' + 31: 2, # 'Ö·' + 29: 2, # 'Ö¸' + 35: 2, # 'Ö¹' + 62: 1, # 'Ö»' + 28: 2, # 'Ö¼' + 38: 0, # '×' + 45: 0, # 'ׂ' + 9: 3, # '×' + 8: 3, # 'ב' + 20: 3, # '×’' + 16: 3, # 'ד' + 3: 3, # '×”' + 2: 3, # 'ו' + 24: 1, # '×–' + 14: 2, # '×—' + 22: 2, # 'ט' + 1: 3, # '×™' + 25: 2, # 'ך' + 15: 2, # '×›' + 4: 3, # 'ל' + 11: 3, # '×' + 6: 3, # 'מ' + 23: 2, # 'ן' + 12: 3, # '× ' + 19: 2, # 'ס' + 13: 3, # '×¢' + 26: 2, # '×£' + 18: 3, # 'פ' + 27: 0, # '×¥' + 21: 2, # 'צ' + 17: 3, # 'ק' + 7: 3, # 'ר' + 10: 3, # 'ש' + 5: 3, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 1, # 'â€' + 58: 0, # '†' + 40: 1, # '…' + }, + 3: { # '×”' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 1, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 1, # '\xa0' + 55: 0, # '´' + 48: 1, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 1, # 'Ö°' + 59: 1, # 'Ö±' + 41: 2, # 'Ö²' + 33: 2, # 'Ö´' + 37: 2, # 'Öµ' + 36: 2, # 'Ö¶' + 31: 3, # 'Ö·' + 29: 2, # 'Ö¸' + 35: 1, # 'Ö¹' + 62: 1, # 'Ö»' + 28: 2, # 'Ö¼' + 38: 0, # '×' + 45: 0, # 'ׂ' + 9: 3, # '×' + 8: 3, # 'ב' + 20: 3, # '×’' + 16: 3, # 'ד' + 3: 3, # '×”' + 2: 3, # 'ו' + 24: 3, # '×–' + 14: 3, # '×—' + 22: 3, # 'ט' + 1: 3, # '×™' + 25: 1, # 'ך' + 15: 3, # '×›' + 4: 3, # 'ל' + 11: 3, # '×' + 6: 3, # 'מ' + 23: 3, # 'ן' + 12: 3, # '× ' + 19: 3, # 'ס' + 13: 3, # '×¢' + 26: 0, # '×£' + 18: 3, # 'פ' + 27: 1, # '×¥' + 21: 3, # 'צ' + 17: 3, # 'ק' + 7: 3, # 'ר' + 10: 3, # 'ש' + 5: 3, # 'ת' + 32: 1, # '–' + 52: 1, # '’' + 47: 0, # '“' + 46: 1, # 'â€' + 58: 0, # '†' + 40: 2, # '…' + }, + 2: { # 'ו' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 1, # 't' + 63: 0, # 'u' + 34: 1, # '\xa0' + 55: 1, # '´' + 48: 1, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 2, # 'Ö°' + 59: 0, # 'Ö±' + 41: 0, # 'Ö²' + 33: 2, # 'Ö´' + 37: 1, # 'Öµ' + 36: 1, # 'Ö¶' + 31: 2, # 'Ö·' + 29: 2, # 'Ö¸' + 35: 3, # 'Ö¹' + 62: 0, # 'Ö»' + 28: 3, # 'Ö¼' + 38: 0, # '×' + 45: 0, # 'ׂ' + 9: 3, # '×' + 8: 3, # 'ב' + 20: 3, # '×’' + 16: 3, # 'ד' + 3: 3, # '×”' + 2: 3, # 'ו' + 24: 3, # '×–' + 14: 3, # '×—' + 22: 3, # 'ט' + 1: 3, # '×™' + 25: 3, # 'ך' + 15: 3, # '×›' + 4: 3, # 'ל' + 11: 3, # '×' + 6: 3, # 'מ' + 23: 3, # 'ן' + 12: 3, # '× ' + 19: 3, # 'ס' + 13: 3, # '×¢' + 26: 3, # '×£' + 18: 3, # 'פ' + 27: 3, # '×¥' + 21: 3, # 'צ' + 17: 3, # 'ק' + 7: 3, # 'ר' + 10: 3, # 'ש' + 5: 3, # 'ת' + 32: 1, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 1, # 'â€' + 58: 0, # '†' + 40: 2, # '…' + }, + 24: { # '×–' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 0, # '\xa0' + 55: 1, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 2, # 'Ö°' + 59: 0, # 'Ö±' + 41: 1, # 'Ö²' + 33: 1, # 'Ö´' + 37: 2, # 'Öµ' + 36: 2, # 'Ö¶' + 31: 2, # 'Ö·' + 29: 2, # 'Ö¸' + 35: 1, # 'Ö¹' + 62: 1, # 'Ö»' + 28: 2, # 'Ö¼' + 38: 0, # '×' + 45: 0, # 'ׂ' + 9: 3, # '×' + 8: 2, # 'ב' + 20: 2, # '×’' + 16: 2, # 'ד' + 3: 3, # '×”' + 2: 3, # 'ו' + 24: 2, # '×–' + 14: 2, # '×—' + 22: 1, # 'ט' + 1: 3, # '×™' + 25: 1, # 'ך' + 15: 3, # '×›' + 4: 3, # 'ל' + 11: 2, # '×' + 6: 3, # 'מ' + 23: 2, # 'ן' + 12: 2, # '× ' + 19: 1, # 'ס' + 13: 2, # '×¢' + 26: 1, # '×£' + 18: 1, # 'פ' + 27: 0, # '×¥' + 21: 2, # 'צ' + 17: 3, # 'ק' + 7: 3, # 'ר' + 10: 1, # 'ש' + 5: 2, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 0, # 'â€' + 58: 0, # '†' + 40: 1, # '…' + }, + 14: { # '×—' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 1, # '\xa0' + 55: 1, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 2, # 'Ö°' + 59: 1, # 'Ö±' + 41: 2, # 'Ö²' + 33: 2, # 'Ö´' + 37: 2, # 'Öµ' + 36: 2, # 'Ö¶' + 31: 2, # 'Ö·' + 29: 2, # 'Ö¸' + 35: 2, # 'Ö¹' + 62: 1, # 'Ö»' + 28: 0, # 'Ö¼' + 38: 0, # '×' + 45: 0, # 'ׂ' + 9: 2, # '×' + 8: 3, # 'ב' + 20: 2, # '×’' + 16: 3, # 'ד' + 3: 3, # '×”' + 2: 3, # 'ו' + 24: 3, # '×–' + 14: 2, # '×—' + 22: 2, # 'ט' + 1: 3, # '×™' + 25: 1, # 'ך' + 15: 2, # '×›' + 4: 3, # 'ל' + 11: 3, # '×' + 6: 3, # 'מ' + 23: 2, # 'ן' + 12: 3, # '× ' + 19: 3, # 'ס' + 13: 1, # '×¢' + 26: 2, # '×£' + 18: 2, # 'פ' + 27: 2, # '×¥' + 21: 3, # 'צ' + 17: 3, # 'ק' + 7: 3, # 'ר' + 10: 3, # 'ש' + 5: 3, # 'ת' + 32: 0, # '–' + 52: 1, # '’' + 47: 0, # '“' + 46: 1, # 'â€' + 58: 0, # '†' + 40: 1, # '…' + }, + 22: { # 'ט' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 1, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 2, # 'Ö°' + 59: 0, # 'Ö±' + 41: 0, # 'Ö²' + 33: 2, # 'Ö´' + 37: 1, # 'Öµ' + 36: 1, # 'Ö¶' + 31: 2, # 'Ö·' + 29: 1, # 'Ö¸' + 35: 1, # 'Ö¹' + 62: 1, # 'Ö»' + 28: 1, # 'Ö¼' + 38: 0, # '×' + 45: 0, # 'ׂ' + 9: 3, # '×' + 8: 3, # 'ב' + 20: 3, # '×’' + 16: 1, # 'ד' + 3: 3, # '×”' + 2: 3, # 'ו' + 24: 2, # '×–' + 14: 3, # '×—' + 22: 2, # 'ט' + 1: 3, # '×™' + 25: 1, # 'ך' + 15: 2, # '×›' + 4: 3, # 'ל' + 11: 2, # '×' + 6: 2, # 'מ' + 23: 2, # 'ן' + 12: 3, # '× ' + 19: 2, # 'ס' + 13: 3, # '×¢' + 26: 2, # '×£' + 18: 3, # 'פ' + 27: 1, # '×¥' + 21: 2, # 'צ' + 17: 2, # 'ק' + 7: 3, # 'ר' + 10: 2, # 'ש' + 5: 3, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 0, # 'â€' + 58: 0, # '†' + 40: 1, # '…' + }, + 1: { # '×™' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 1, # '\xa0' + 55: 1, # '´' + 48: 1, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 2, # 'Ö°' + 59: 0, # 'Ö±' + 41: 0, # 'Ö²' + 33: 2, # 'Ö´' + 37: 2, # 'Öµ' + 36: 1, # 'Ö¶' + 31: 2, # 'Ö·' + 29: 2, # 'Ö¸' + 35: 2, # 'Ö¹' + 62: 1, # 'Ö»' + 28: 2, # 'Ö¼' + 38: 0, # '×' + 45: 0, # 'ׂ' + 9: 3, # '×' + 8: 3, # 'ב' + 20: 3, # '×’' + 16: 3, # 'ד' + 3: 3, # '×”' + 2: 3, # 'ו' + 24: 3, # '×–' + 14: 3, # '×—' + 22: 3, # 'ט' + 1: 3, # '×™' + 25: 3, # 'ך' + 15: 3, # '×›' + 4: 3, # 'ל' + 11: 3, # '×' + 6: 3, # 'מ' + 23: 3, # 'ן' + 12: 3, # '× ' + 19: 3, # 'ס' + 13: 3, # '×¢' + 26: 3, # '×£' + 18: 3, # 'פ' + 27: 3, # '×¥' + 21: 3, # 'צ' + 17: 3, # 'ק' + 7: 3, # 'ר' + 10: 3, # 'ש' + 5: 3, # 'ת' + 32: 1, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 1, # 'â€' + 58: 0, # '†' + 40: 2, # '…' + }, + 25: { # 'ך' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 2, # 'Ö°' + 59: 0, # 'Ö±' + 41: 0, # 'Ö²' + 33: 0, # 'Ö´' + 37: 0, # 'Öµ' + 36: 0, # 'Ö¶' + 31: 0, # 'Ö·' + 29: 2, # 'Ö¸' + 35: 0, # 'Ö¹' + 62: 0, # 'Ö»' + 28: 1, # 'Ö¼' + 38: 0, # '×' + 45: 0, # 'ׂ' + 9: 1, # '×' + 8: 0, # 'ב' + 20: 0, # '×’' + 16: 0, # 'ד' + 3: 1, # '×”' + 2: 0, # 'ו' + 24: 0, # '×–' + 14: 1, # '×—' + 22: 0, # 'ט' + 1: 0, # '×™' + 25: 0, # 'ך' + 15: 0, # '×›' + 4: 1, # 'ל' + 11: 0, # '×' + 6: 1, # 'מ' + 23: 0, # 'ן' + 12: 0, # '× ' + 19: 0, # 'ס' + 13: 0, # '×¢' + 26: 0, # '×£' + 18: 0, # 'פ' + 27: 0, # '×¥' + 21: 0, # 'צ' + 17: 0, # 'ק' + 7: 0, # 'ר' + 10: 1, # 'ש' + 5: 0, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 0, # 'â€' + 58: 0, # '†' + 40: 1, # '…' + }, + 15: { # '×›' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 2, # 'Ö°' + 59: 0, # 'Ö±' + 41: 0, # 'Ö²' + 33: 2, # 'Ö´' + 37: 2, # 'Öµ' + 36: 2, # 'Ö¶' + 31: 2, # 'Ö·' + 29: 2, # 'Ö¸' + 35: 1, # 'Ö¹' + 62: 1, # 'Ö»' + 28: 3, # 'Ö¼' + 38: 0, # '×' + 45: 0, # 'ׂ' + 9: 3, # '×' + 8: 3, # 'ב' + 20: 2, # '×’' + 16: 3, # 'ד' + 3: 3, # '×”' + 2: 3, # 'ו' + 24: 3, # '×–' + 14: 3, # '×—' + 22: 2, # 'ט' + 1: 3, # '×™' + 25: 3, # 'ך' + 15: 3, # '×›' + 4: 3, # 'ל' + 11: 3, # '×' + 6: 3, # 'מ' + 23: 3, # 'ן' + 12: 3, # '× ' + 19: 3, # 'ס' + 13: 2, # '×¢' + 26: 3, # '×£' + 18: 3, # 'פ' + 27: 1, # '×¥' + 21: 2, # 'צ' + 17: 2, # 'ק' + 7: 3, # 'ר' + 10: 3, # 'ש' + 5: 3, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 0, # 'â€' + 58: 0, # '†' + 40: 0, # '…' + }, + 4: { # 'ל' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 1, # '\xa0' + 55: 1, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 3, # 'Ö°' + 59: 0, # 'Ö±' + 41: 0, # 'Ö²' + 33: 2, # 'Ö´' + 37: 2, # 'Öµ' + 36: 2, # 'Ö¶' + 31: 2, # 'Ö·' + 29: 2, # 'Ö¸' + 35: 2, # 'Ö¹' + 62: 1, # 'Ö»' + 28: 2, # 'Ö¼' + 38: 0, # '×' + 45: 0, # 'ׂ' + 9: 3, # '×' + 8: 3, # 'ב' + 20: 3, # '×’' + 16: 3, # 'ד' + 3: 3, # '×”' + 2: 3, # 'ו' + 24: 3, # '×–' + 14: 3, # '×—' + 22: 3, # 'ט' + 1: 3, # '×™' + 25: 3, # 'ך' + 15: 3, # '×›' + 4: 3, # 'ל' + 11: 3, # '×' + 6: 3, # 'מ' + 23: 2, # 'ן' + 12: 3, # '× ' + 19: 3, # 'ס' + 13: 3, # '×¢' + 26: 2, # '×£' + 18: 3, # 'פ' + 27: 2, # '×¥' + 21: 3, # 'צ' + 17: 3, # 'ק' + 7: 3, # 'ר' + 10: 3, # 'ש' + 5: 3, # 'ת' + 32: 1, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 1, # 'â€' + 58: 0, # '†' + 40: 1, # '…' + }, + 11: { # '×' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 1, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 0, # 'Ö°' + 59: 0, # 'Ö±' + 41: 0, # 'Ö²' + 33: 0, # 'Ö´' + 37: 0, # 'Öµ' + 36: 0, # 'Ö¶' + 31: 0, # 'Ö·' + 29: 0, # 'Ö¸' + 35: 0, # 'Ö¹' + 62: 0, # 'Ö»' + 28: 0, # 'Ö¼' + 38: 0, # '×' + 45: 0, # 'ׂ' + 9: 1, # '×' + 8: 1, # 'ב' + 20: 1, # '×’' + 16: 0, # 'ד' + 3: 1, # '×”' + 2: 1, # 'ו' + 24: 1, # '×–' + 14: 1, # '×—' + 22: 0, # 'ט' + 1: 1, # '×™' + 25: 0, # 'ך' + 15: 1, # '×›' + 4: 1, # 'ל' + 11: 1, # '×' + 6: 1, # 'מ' + 23: 0, # 'ן' + 12: 1, # '× ' + 19: 0, # 'ס' + 13: 1, # '×¢' + 26: 0, # '×£' + 18: 1, # 'פ' + 27: 1, # '×¥' + 21: 1, # 'צ' + 17: 1, # 'ק' + 7: 1, # 'ר' + 10: 1, # 'ש' + 5: 1, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 1, # 'â€' + 58: 0, # '†' + 40: 2, # '…' + }, + 6: { # 'מ' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 0, # '\xa0' + 55: 1, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 2, # 'Ö°' + 59: 0, # 'Ö±' + 41: 0, # 'Ö²' + 33: 2, # 'Ö´' + 37: 2, # 'Öµ' + 36: 2, # 'Ö¶' + 31: 2, # 'Ö·' + 29: 2, # 'Ö¸' + 35: 2, # 'Ö¹' + 62: 1, # 'Ö»' + 28: 2, # 'Ö¼' + 38: 0, # '×' + 45: 0, # 'ׂ' + 9: 3, # '×' + 8: 3, # 'ב' + 20: 3, # '×’' + 16: 3, # 'ד' + 3: 3, # '×”' + 2: 3, # 'ו' + 24: 3, # '×–' + 14: 3, # '×—' + 22: 3, # 'ט' + 1: 3, # '×™' + 25: 2, # 'ך' + 15: 3, # '×›' + 4: 3, # 'ל' + 11: 3, # '×' + 6: 3, # 'מ' + 23: 3, # 'ן' + 12: 3, # '× ' + 19: 3, # 'ס' + 13: 3, # '×¢' + 26: 0, # '×£' + 18: 3, # 'פ' + 27: 2, # '×¥' + 21: 3, # 'צ' + 17: 3, # 'ק' + 7: 3, # 'ר' + 10: 3, # 'ש' + 5: 3, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 0, # 'â€' + 58: 0, # '†' + 40: 1, # '…' + }, + 23: { # 'ן' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 1, # '\xa0' + 55: 0, # '´' + 48: 1, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 0, # 'Ö°' + 59: 0, # 'Ö±' + 41: 0, # 'Ö²' + 33: 0, # 'Ö´' + 37: 0, # 'Öµ' + 36: 0, # 'Ö¶' + 31: 0, # 'Ö·' + 29: 0, # 'Ö¸' + 35: 0, # 'Ö¹' + 62: 0, # 'Ö»' + 28: 0, # 'Ö¼' + 38: 0, # '×' + 45: 0, # 'ׂ' + 9: 1, # '×' + 8: 1, # 'ב' + 20: 1, # '×’' + 16: 1, # 'ד' + 3: 1, # '×”' + 2: 1, # 'ו' + 24: 0, # '×–' + 14: 1, # '×—' + 22: 1, # 'ט' + 1: 1, # '×™' + 25: 0, # 'ך' + 15: 1, # '×›' + 4: 1, # 'ל' + 11: 1, # '×' + 6: 1, # 'מ' + 23: 0, # 'ן' + 12: 1, # '× ' + 19: 1, # 'ס' + 13: 1, # '×¢' + 26: 1, # '×£' + 18: 1, # 'פ' + 27: 0, # '×¥' + 21: 0, # 'צ' + 17: 1, # 'ק' + 7: 1, # 'ר' + 10: 1, # 'ש' + 5: 1, # 'ת' + 32: 1, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 1, # 'â€' + 58: 0, # '†' + 40: 2, # '…' + }, + 12: { # '× ' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 2, # 'Ö°' + 59: 0, # 'Ö±' + 41: 0, # 'Ö²' + 33: 2, # 'Ö´' + 37: 2, # 'Öµ' + 36: 2, # 'Ö¶' + 31: 2, # 'Ö·' + 29: 2, # 'Ö¸' + 35: 1, # 'Ö¹' + 62: 1, # 'Ö»' + 28: 2, # 'Ö¼' + 38: 0, # '×' + 45: 0, # 'ׂ' + 9: 3, # '×' + 8: 3, # 'ב' + 20: 3, # '×’' + 16: 3, # 'ד' + 3: 3, # '×”' + 2: 3, # 'ו' + 24: 3, # '×–' + 14: 3, # '×—' + 22: 3, # 'ט' + 1: 3, # '×™' + 25: 2, # 'ך' + 15: 3, # '×›' + 4: 3, # 'ל' + 11: 3, # '×' + 6: 3, # 'מ' + 23: 3, # 'ן' + 12: 3, # '× ' + 19: 3, # 'ס' + 13: 3, # '×¢' + 26: 2, # '×£' + 18: 3, # 'פ' + 27: 2, # '×¥' + 21: 3, # 'צ' + 17: 3, # 'ק' + 7: 3, # 'ר' + 10: 3, # 'ש' + 5: 3, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 0, # 'â€' + 58: 0, # '†' + 40: 0, # '…' + }, + 19: { # 'ס' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 1, # '\xa0' + 55: 1, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 2, # 'Ö°' + 59: 0, # 'Ö±' + 41: 0, # 'Ö²' + 33: 2, # 'Ö´' + 37: 1, # 'Öµ' + 36: 2, # 'Ö¶' + 31: 2, # 'Ö·' + 29: 1, # 'Ö¸' + 35: 1, # 'Ö¹' + 62: 2, # 'Ö»' + 28: 2, # 'Ö¼' + 38: 0, # '×' + 45: 0, # 'ׂ' + 9: 2, # '×' + 8: 3, # 'ב' + 20: 3, # '×’' + 16: 3, # 'ד' + 3: 3, # '×”' + 2: 3, # 'ו' + 24: 1, # '×–' + 14: 3, # '×—' + 22: 3, # 'ט' + 1: 3, # '×™' + 25: 2, # 'ך' + 15: 3, # '×›' + 4: 3, # 'ל' + 11: 2, # '×' + 6: 3, # 'מ' + 23: 2, # 'ן' + 12: 3, # '× ' + 19: 2, # 'ס' + 13: 3, # '×¢' + 26: 3, # '×£' + 18: 3, # 'פ' + 27: 0, # '×¥' + 21: 2, # 'צ' + 17: 3, # 'ק' + 7: 3, # 'ר' + 10: 1, # 'ש' + 5: 3, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 1, # 'â€' + 58: 0, # '†' + 40: 1, # '…' + }, + 13: { # '×¢' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 1, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 1, # 'Ö°' + 59: 1, # 'Ö±' + 41: 2, # 'Ö²' + 33: 2, # 'Ö´' + 37: 2, # 'Öµ' + 36: 2, # 'Ö¶' + 31: 2, # 'Ö·' + 29: 2, # 'Ö¸' + 35: 2, # 'Ö¹' + 62: 1, # 'Ö»' + 28: 0, # 'Ö¼' + 38: 0, # '×' + 45: 0, # 'ׂ' + 9: 2, # '×' + 8: 3, # 'ב' + 20: 3, # '×’' + 16: 3, # 'ד' + 3: 3, # '×”' + 2: 3, # 'ו' + 24: 3, # '×–' + 14: 1, # '×—' + 22: 3, # 'ט' + 1: 3, # '×™' + 25: 2, # 'ך' + 15: 2, # '×›' + 4: 3, # 'ל' + 11: 3, # '×' + 6: 3, # 'מ' + 23: 2, # 'ן' + 12: 3, # '× ' + 19: 3, # 'ס' + 13: 2, # '×¢' + 26: 1, # '×£' + 18: 2, # 'פ' + 27: 2, # '×¥' + 21: 3, # 'צ' + 17: 3, # 'ק' + 7: 3, # 'ר' + 10: 3, # 'ש' + 5: 3, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 1, # 'â€' + 58: 0, # '†' + 40: 1, # '…' + }, + 26: { # '×£' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 0, # 'Ö°' + 59: 0, # 'Ö±' + 41: 0, # 'Ö²' + 33: 0, # 'Ö´' + 37: 0, # 'Öµ' + 36: 0, # 'Ö¶' + 31: 0, # 'Ö·' + 29: 0, # 'Ö¸' + 35: 0, # 'Ö¹' + 62: 0, # 'Ö»' + 28: 0, # 'Ö¼' + 38: 0, # '×' + 45: 0, # 'ׂ' + 9: 1, # '×' + 8: 0, # 'ב' + 20: 0, # '×’' + 16: 0, # 'ד' + 3: 0, # '×”' + 2: 1, # 'ו' + 24: 0, # '×–' + 14: 1, # '×—' + 22: 0, # 'ט' + 1: 0, # '×™' + 25: 0, # 'ך' + 15: 1, # '×›' + 4: 1, # 'ל' + 11: 0, # '×' + 6: 1, # 'מ' + 23: 0, # 'ן' + 12: 0, # '× ' + 19: 1, # 'ס' + 13: 0, # '×¢' + 26: 1, # '×£' + 18: 1, # 'פ' + 27: 0, # '×¥' + 21: 0, # 'צ' + 17: 1, # 'ק' + 7: 1, # 'ר' + 10: 1, # 'ש' + 5: 0, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 0, # 'â€' + 58: 0, # '†' + 40: 1, # '…' + }, + 18: { # 'פ' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 0, # '\xa0' + 55: 1, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 2, # 'Ö°' + 59: 0, # 'Ö±' + 41: 0, # 'Ö²' + 33: 2, # 'Ö´' + 37: 1, # 'Öµ' + 36: 2, # 'Ö¶' + 31: 1, # 'Ö·' + 29: 2, # 'Ö¸' + 35: 1, # 'Ö¹' + 62: 1, # 'Ö»' + 28: 2, # 'Ö¼' + 38: 0, # '×' + 45: 0, # 'ׂ' + 9: 3, # '×' + 8: 2, # 'ב' + 20: 3, # '×’' + 16: 2, # 'ד' + 3: 3, # '×”' + 2: 3, # 'ו' + 24: 2, # '×–' + 14: 3, # '×—' + 22: 3, # 'ט' + 1: 3, # '×™' + 25: 2, # 'ך' + 15: 3, # '×›' + 4: 3, # 'ל' + 11: 2, # '×' + 6: 2, # 'מ' + 23: 3, # 'ן' + 12: 3, # '× ' + 19: 3, # 'ס' + 13: 3, # '×¢' + 26: 2, # '×£' + 18: 2, # 'פ' + 27: 2, # '×¥' + 21: 3, # 'צ' + 17: 3, # 'ק' + 7: 3, # 'ר' + 10: 3, # 'ש' + 5: 3, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 1, # 'â€' + 58: 0, # '†' + 40: 0, # '…' + }, + 27: { # '×¥' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 0, # '\xa0' + 55: 1, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 0, # 'Ö°' + 59: 0, # 'Ö±' + 41: 0, # 'Ö²' + 33: 0, # 'Ö´' + 37: 0, # 'Öµ' + 36: 0, # 'Ö¶' + 31: 0, # 'Ö·' + 29: 0, # 'Ö¸' + 35: 0, # 'Ö¹' + 62: 0, # 'Ö»' + 28: 0, # 'Ö¼' + 38: 0, # '×' + 45: 0, # 'ׂ' + 9: 1, # '×' + 8: 0, # 'ב' + 20: 0, # '×’' + 16: 0, # 'ד' + 3: 0, # '×”' + 2: 0, # 'ו' + 24: 0, # '×–' + 14: 0, # '×—' + 22: 0, # 'ט' + 1: 0, # '×™' + 25: 0, # 'ך' + 15: 0, # '×›' + 4: 1, # 'ל' + 11: 0, # '×' + 6: 0, # 'מ' + 23: 0, # 'ן' + 12: 0, # '× ' + 19: 1, # 'ס' + 13: 0, # '×¢' + 26: 0, # '×£' + 18: 0, # 'פ' + 27: 0, # '×¥' + 21: 0, # 'צ' + 17: 0, # 'ק' + 7: 1, # 'ר' + 10: 0, # 'ש' + 5: 1, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 0, # 'â€' + 58: 0, # '†' + 40: 1, # '…' + }, + 21: { # 'צ' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 0, # '\xa0' + 55: 1, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 2, # 'Ö°' + 59: 0, # 'Ö±' + 41: 0, # 'Ö²' + 33: 2, # 'Ö´' + 37: 2, # 'Öµ' + 36: 1, # 'Ö¶' + 31: 2, # 'Ö·' + 29: 2, # 'Ö¸' + 35: 1, # 'Ö¹' + 62: 1, # 'Ö»' + 28: 2, # 'Ö¼' + 38: 0, # '×' + 45: 0, # 'ׂ' + 9: 3, # '×' + 8: 3, # 'ב' + 20: 2, # '×’' + 16: 3, # 'ד' + 3: 3, # '×”' + 2: 3, # 'ו' + 24: 1, # '×–' + 14: 3, # '×—' + 22: 2, # 'ט' + 1: 3, # '×™' + 25: 1, # 'ך' + 15: 1, # '×›' + 4: 3, # 'ל' + 11: 2, # '×' + 6: 3, # 'מ' + 23: 2, # 'ן' + 12: 3, # '× ' + 19: 1, # 'ס' + 13: 3, # '×¢' + 26: 2, # '×£' + 18: 3, # 'פ' + 27: 2, # '×¥' + 21: 2, # 'צ' + 17: 3, # 'ק' + 7: 3, # 'ר' + 10: 0, # 'ש' + 5: 3, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 0, # 'â€' + 58: 0, # '†' + 40: 0, # '…' + }, + 17: { # 'ק' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 1, # '\xa0' + 55: 1, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 2, # 'Ö°' + 59: 0, # 'Ö±' + 41: 0, # 'Ö²' + 33: 2, # 'Ö´' + 37: 2, # 'Öµ' + 36: 1, # 'Ö¶' + 31: 2, # 'Ö·' + 29: 2, # 'Ö¸' + 35: 2, # 'Ö¹' + 62: 1, # 'Ö»' + 28: 2, # 'Ö¼' + 38: 0, # '×' + 45: 0, # 'ׂ' + 9: 3, # '×' + 8: 3, # 'ב' + 20: 2, # '×’' + 16: 3, # 'ד' + 3: 3, # '×”' + 2: 3, # 'ו' + 24: 2, # '×–' + 14: 3, # '×—' + 22: 3, # 'ט' + 1: 3, # '×™' + 25: 1, # 'ך' + 15: 1, # '×›' + 4: 3, # 'ל' + 11: 2, # '×' + 6: 3, # 'מ' + 23: 2, # 'ן' + 12: 3, # '× ' + 19: 3, # 'ס' + 13: 3, # '×¢' + 26: 2, # '×£' + 18: 3, # 'פ' + 27: 2, # '×¥' + 21: 3, # 'צ' + 17: 2, # 'ק' + 7: 3, # 'ר' + 10: 3, # 'ש' + 5: 3, # 'ת' + 32: 0, # '–' + 52: 1, # '’' + 47: 0, # '“' + 46: 1, # 'â€' + 58: 0, # '†' + 40: 1, # '…' + }, + 7: { # 'ר' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 1, # '\xa0' + 55: 2, # '´' + 48: 1, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 2, # 'Ö°' + 59: 0, # 'Ö±' + 41: 1, # 'Ö²' + 33: 2, # 'Ö´' + 37: 2, # 'Öµ' + 36: 2, # 'Ö¶' + 31: 2, # 'Ö·' + 29: 2, # 'Ö¸' + 35: 2, # 'Ö¹' + 62: 1, # 'Ö»' + 28: 0, # 'Ö¼' + 38: 0, # '×' + 45: 0, # 'ׂ' + 9: 3, # '×' + 8: 3, # 'ב' + 20: 3, # '×’' + 16: 3, # 'ד' + 3: 3, # '×”' + 2: 3, # 'ו' + 24: 3, # '×–' + 14: 3, # '×—' + 22: 3, # 'ט' + 1: 3, # '×™' + 25: 3, # 'ך' + 15: 3, # '×›' + 4: 3, # 'ל' + 11: 3, # '×' + 6: 3, # 'מ' + 23: 3, # 'ן' + 12: 3, # '× ' + 19: 3, # 'ס' + 13: 3, # '×¢' + 26: 2, # '×£' + 18: 3, # 'פ' + 27: 3, # '×¥' + 21: 3, # 'צ' + 17: 3, # 'ק' + 7: 3, # 'ר' + 10: 3, # 'ש' + 5: 3, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 1, # 'â€' + 58: 0, # '†' + 40: 2, # '…' + }, + 10: { # 'ש' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 1, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 1, # 'Ö°' + 59: 0, # 'Ö±' + 41: 0, # 'Ö²' + 33: 1, # 'Ö´' + 37: 1, # 'Öµ' + 36: 1, # 'Ö¶' + 31: 1, # 'Ö·' + 29: 1, # 'Ö¸' + 35: 1, # 'Ö¹' + 62: 1, # 'Ö»' + 28: 2, # 'Ö¼' + 38: 3, # '×' + 45: 2, # 'ׂ' + 9: 3, # '×' + 8: 3, # 'ב' + 20: 3, # '×’' + 16: 3, # 'ד' + 3: 3, # '×”' + 2: 3, # 'ו' + 24: 2, # '×–' + 14: 3, # '×—' + 22: 3, # 'ט' + 1: 3, # '×™' + 25: 3, # 'ך' + 15: 3, # '×›' + 4: 3, # 'ל' + 11: 3, # '×' + 6: 3, # 'מ' + 23: 2, # 'ן' + 12: 3, # '× ' + 19: 2, # 'ס' + 13: 3, # '×¢' + 26: 2, # '×£' + 18: 3, # 'פ' + 27: 1, # '×¥' + 21: 2, # 'צ' + 17: 3, # 'ק' + 7: 3, # 'ר' + 10: 3, # 'ש' + 5: 3, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 1, # 'â€' + 58: 0, # '†' + 40: 1, # '…' + }, + 5: { # 'ת' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 1, # '\xa0' + 55: 0, # '´' + 48: 1, # '¼' + 39: 1, # '½' + 57: 0, # '¾' + 30: 2, # 'Ö°' + 59: 0, # 'Ö±' + 41: 0, # 'Ö²' + 33: 2, # 'Ö´' + 37: 2, # 'Öµ' + 36: 2, # 'Ö¶' + 31: 2, # 'Ö·' + 29: 2, # 'Ö¸' + 35: 1, # 'Ö¹' + 62: 1, # 'Ö»' + 28: 2, # 'Ö¼' + 38: 0, # '×' + 45: 0, # 'ׂ' + 9: 3, # '×' + 8: 3, # 'ב' + 20: 3, # '×’' + 16: 2, # 'ד' + 3: 3, # '×”' + 2: 3, # 'ו' + 24: 2, # '×–' + 14: 3, # '×—' + 22: 2, # 'ט' + 1: 3, # '×™' + 25: 2, # 'ך' + 15: 3, # '×›' + 4: 3, # 'ל' + 11: 3, # '×' + 6: 3, # 'מ' + 23: 3, # 'ן' + 12: 3, # '× ' + 19: 2, # 'ס' + 13: 3, # '×¢' + 26: 2, # '×£' + 18: 3, # 'פ' + 27: 1, # '×¥' + 21: 2, # 'צ' + 17: 3, # 'ק' + 7: 3, # 'ר' + 10: 3, # 'ש' + 5: 3, # 'ת' + 32: 1, # '–' + 52: 1, # '’' + 47: 0, # '“' + 46: 0, # 'â€' + 58: 0, # '†' + 40: 2, # '…' + }, + 32: { # '–' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 1, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 0, # 'Ö°' + 59: 0, # 'Ö±' + 41: 0, # 'Ö²' + 33: 0, # 'Ö´' + 37: 0, # 'Öµ' + 36: 0, # 'Ö¶' + 31: 0, # 'Ö·' + 29: 0, # 'Ö¸' + 35: 0, # 'Ö¹' + 62: 0, # 'Ö»' + 28: 0, # 'Ö¼' + 38: 0, # '×' + 45: 0, # 'ׂ' + 9: 1, # '×' + 8: 1, # 'ב' + 20: 1, # '×’' + 16: 1, # 'ד' + 3: 1, # '×”' + 2: 1, # 'ו' + 24: 0, # '×–' + 14: 1, # '×—' + 22: 0, # 'ט' + 1: 1, # '×™' + 25: 0, # 'ך' + 15: 1, # '×›' + 4: 1, # 'ל' + 11: 0, # '×' + 6: 1, # 'מ' + 23: 0, # 'ן' + 12: 0, # '× ' + 19: 1, # 'ס' + 13: 1, # '×¢' + 26: 0, # '×£' + 18: 1, # 'פ' + 27: 0, # '×¥' + 21: 1, # 'צ' + 17: 0, # 'ק' + 7: 1, # 'ר' + 10: 1, # 'ש' + 5: 1, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 0, # 'â€' + 58: 0, # '†' + 40: 0, # '…' + }, + 52: { # '’' + 50: 1, # 'a' + 60: 0, # 'c' + 61: 1, # 'd' + 42: 1, # 'e' + 53: 1, # 'i' + 56: 1, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 1, # 'r' + 43: 2, # 's' + 44: 2, # 't' + 63: 1, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 0, # 'Ö°' + 59: 0, # 'Ö±' + 41: 0, # 'Ö²' + 33: 0, # 'Ö´' + 37: 0, # 'Öµ' + 36: 0, # 'Ö¶' + 31: 0, # 'Ö·' + 29: 0, # 'Ö¸' + 35: 0, # 'Ö¹' + 62: 0, # 'Ö»' + 28: 0, # 'Ö¼' + 38: 0, # '×' + 45: 0, # 'ׂ' + 9: 0, # '×' + 8: 0, # 'ב' + 20: 0, # '×’' + 16: 0, # 'ד' + 3: 0, # '×”' + 2: 1, # 'ו' + 24: 0, # '×–' + 14: 0, # '×—' + 22: 0, # 'ט' + 1: 0, # '×™' + 25: 0, # 'ך' + 15: 0, # '×›' + 4: 0, # 'ל' + 11: 0, # '×' + 6: 1, # 'מ' + 23: 0, # 'ן' + 12: 0, # '× ' + 19: 0, # 'ס' + 13: 0, # '×¢' + 26: 0, # '×£' + 18: 0, # 'פ' + 27: 0, # '×¥' + 21: 0, # 'צ' + 17: 0, # 'ק' + 7: 0, # 'ר' + 10: 0, # 'ש' + 5: 1, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 0, # 'â€' + 58: 0, # '†' + 40: 0, # '…' + }, + 47: { # '“' + 50: 1, # 'a' + 60: 1, # 'c' + 61: 1, # 'd' + 42: 1, # 'e' + 53: 1, # 'i' + 56: 1, # 'l' + 54: 1, # 'n' + 49: 1, # 'o' + 51: 1, # 'r' + 43: 1, # 's' + 44: 1, # 't' + 63: 1, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 0, # 'Ö°' + 59: 0, # 'Ö±' + 41: 0, # 'Ö²' + 33: 0, # 'Ö´' + 37: 0, # 'Öµ' + 36: 0, # 'Ö¶' + 31: 0, # 'Ö·' + 29: 0, # 'Ö¸' + 35: 0, # 'Ö¹' + 62: 0, # 'Ö»' + 28: 0, # 'Ö¼' + 38: 0, # '×' + 45: 0, # 'ׂ' + 9: 2, # '×' + 8: 1, # 'ב' + 20: 1, # '×’' + 16: 1, # 'ד' + 3: 1, # '×”' + 2: 1, # 'ו' + 24: 1, # '×–' + 14: 1, # '×—' + 22: 1, # 'ט' + 1: 1, # '×™' + 25: 0, # 'ך' + 15: 1, # '×›' + 4: 1, # 'ל' + 11: 0, # '×' + 6: 1, # 'מ' + 23: 0, # 'ן' + 12: 1, # '× ' + 19: 1, # 'ס' + 13: 1, # '×¢' + 26: 0, # '×£' + 18: 1, # 'פ' + 27: 0, # '×¥' + 21: 1, # 'צ' + 17: 1, # 'ק' + 7: 1, # 'ר' + 10: 1, # 'ש' + 5: 1, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 0, # 'â€' + 58: 0, # '†' + 40: 0, # '…' + }, + 46: { # 'â€' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 1, # 't' + 63: 0, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 0, # 'Ö°' + 59: 0, # 'Ö±' + 41: 0, # 'Ö²' + 33: 0, # 'Ö´' + 37: 0, # 'Öµ' + 36: 0, # 'Ö¶' + 31: 0, # 'Ö·' + 29: 0, # 'Ö¸' + 35: 0, # 'Ö¹' + 62: 0, # 'Ö»' + 28: 0, # 'Ö¼' + 38: 0, # '×' + 45: 0, # 'ׂ' + 9: 1, # '×' + 8: 1, # 'ב' + 20: 1, # '×’' + 16: 0, # 'ד' + 3: 0, # '×”' + 2: 0, # 'ו' + 24: 0, # '×–' + 14: 0, # '×—' + 22: 0, # 'ט' + 1: 1, # '×™' + 25: 0, # 'ך' + 15: 1, # '×›' + 4: 1, # 'ל' + 11: 0, # '×' + 6: 1, # 'מ' + 23: 0, # 'ן' + 12: 0, # '× ' + 19: 0, # 'ס' + 13: 0, # '×¢' + 26: 0, # '×£' + 18: 0, # 'פ' + 27: 0, # '×¥' + 21: 1, # 'צ' + 17: 0, # 'ק' + 7: 1, # 'ר' + 10: 0, # 'ש' + 5: 0, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 0, # 'â€' + 58: 0, # '†' + 40: 0, # '…' + }, + 58: { # '†' + 50: 0, # 'a' + 60: 0, # 'c' + 61: 0, # 'd' + 42: 0, # 'e' + 53: 0, # 'i' + 56: 0, # 'l' + 54: 0, # 'n' + 49: 0, # 'o' + 51: 0, # 'r' + 43: 0, # 's' + 44: 0, # 't' + 63: 0, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 0, # 'Ö°' + 59: 0, # 'Ö±' + 41: 0, # 'Ö²' + 33: 0, # 'Ö´' + 37: 0, # 'Öµ' + 36: 0, # 'Ö¶' + 31: 0, # 'Ö·' + 29: 0, # 'Ö¸' + 35: 0, # 'Ö¹' + 62: 0, # 'Ö»' + 28: 0, # 'Ö¼' + 38: 0, # '×' + 45: 0, # 'ׂ' + 9: 0, # '×' + 8: 0, # 'ב' + 20: 0, # '×’' + 16: 0, # 'ד' + 3: 0, # '×”' + 2: 0, # 'ו' + 24: 0, # '×–' + 14: 0, # '×—' + 22: 0, # 'ט' + 1: 0, # '×™' + 25: 0, # 'ך' + 15: 0, # '×›' + 4: 0, # 'ל' + 11: 0, # '×' + 6: 0, # 'מ' + 23: 0, # 'ן' + 12: 0, # '× ' + 19: 0, # 'ס' + 13: 0, # '×¢' + 26: 0, # '×£' + 18: 0, # 'פ' + 27: 0, # '×¥' + 21: 0, # 'צ' + 17: 0, # 'ק' + 7: 0, # 'ר' + 10: 0, # 'ש' + 5: 0, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 0, # 'â€' + 58: 2, # '†' + 40: 0, # '…' + }, + 40: { # '…' + 50: 1, # 'a' + 60: 1, # 'c' + 61: 1, # 'd' + 42: 1, # 'e' + 53: 1, # 'i' + 56: 0, # 'l' + 54: 1, # 'n' + 49: 0, # 'o' + 51: 1, # 'r' + 43: 1, # 's' + 44: 1, # 't' + 63: 0, # 'u' + 34: 0, # '\xa0' + 55: 0, # '´' + 48: 0, # '¼' + 39: 0, # '½' + 57: 0, # '¾' + 30: 0, # 'Ö°' + 59: 0, # 'Ö±' + 41: 0, # 'Ö²' + 33: 0, # 'Ö´' + 37: 0, # 'Öµ' + 36: 0, # 'Ö¶' + 31: 0, # 'Ö·' + 29: 0, # 'Ö¸' + 35: 0, # 'Ö¹' + 62: 0, # 'Ö»' + 28: 0, # 'Ö¼' + 38: 0, # '×' + 45: 0, # 'ׂ' + 9: 1, # '×' + 8: 0, # 'ב' + 20: 0, # '×’' + 16: 0, # 'ד' + 3: 1, # '×”' + 2: 1, # 'ו' + 24: 1, # '×–' + 14: 0, # '×—' + 22: 0, # 'ט' + 1: 1, # '×™' + 25: 0, # 'ך' + 15: 1, # '×›' + 4: 1, # 'ל' + 11: 0, # '×' + 6: 1, # 'מ' + 23: 0, # 'ן' + 12: 1, # '× ' + 19: 0, # 'ס' + 13: 0, # '×¢' + 26: 0, # '×£' + 18: 1, # 'פ' + 27: 0, # '×¥' + 21: 0, # 'צ' + 17: 0, # 'ק' + 7: 1, # 'ר' + 10: 1, # 'ש' + 5: 1, # 'ת' + 32: 0, # '–' + 52: 0, # '’' + 47: 0, # '“' + 46: 1, # 'â€' + 58: 0, # '†' + 40: 2, # '…' + }, +} + +# 255: Undefined characters that did not exist in training text +# 254: Carriage/Return +# 253: symbol (punctuation) that does not belong to word +# 252: 0 - 9 +# 251: Control characters + +# Character Mapping Table(s): +WINDOWS_1255_HEBREW_CHAR_TO_ORDER = { + 0: 255, # '\x00' + 1: 255, # '\x01' + 2: 255, # '\x02' + 3: 255, # '\x03' + 4: 255, # '\x04' + 5: 255, # '\x05' + 6: 255, # '\x06' + 7: 255, # '\x07' + 8: 255, # '\x08' + 9: 255, # '\t' + 10: 254, # '\n' + 11: 255, # '\x0b' + 12: 255, # '\x0c' + 13: 254, # '\r' + 14: 255, # '\x0e' + 15: 255, # '\x0f' + 16: 255, # '\x10' + 17: 255, # '\x11' + 18: 255, # '\x12' + 19: 255, # '\x13' + 20: 255, # '\x14' + 21: 255, # '\x15' + 22: 255, # '\x16' + 23: 255, # '\x17' + 24: 255, # '\x18' + 25: 255, # '\x19' + 26: 255, # '\x1a' + 27: 255, # '\x1b' + 28: 255, # '\x1c' + 29: 255, # '\x1d' + 30: 255, # '\x1e' + 31: 255, # '\x1f' + 32: 253, # ' ' + 33: 253, # '!' + 34: 253, # '"' + 35: 253, # '#' + 36: 253, # '$' + 37: 253, # '%' + 38: 253, # '&' + 39: 253, # "'" + 40: 253, # '(' + 41: 253, # ')' + 42: 253, # '*' + 43: 253, # '+' + 44: 253, # ',' + 45: 253, # '-' + 46: 253, # '.' + 47: 253, # '/' + 48: 252, # '0' + 49: 252, # '1' + 50: 252, # '2' + 51: 252, # '3' + 52: 252, # '4' + 53: 252, # '5' + 54: 252, # '6' + 55: 252, # '7' + 56: 252, # '8' + 57: 252, # '9' + 58: 253, # ':' + 59: 253, # ';' + 60: 253, # '<' + 61: 253, # '=' + 62: 253, # '>' + 63: 253, # '?' + 64: 253, # '@' + 65: 69, # 'A' + 66: 91, # 'B' + 67: 79, # 'C' + 68: 80, # 'D' + 69: 92, # 'E' + 70: 89, # 'F' + 71: 97, # 'G' + 72: 90, # 'H' + 73: 68, # 'I' + 74: 111, # 'J' + 75: 112, # 'K' + 76: 82, # 'L' + 77: 73, # 'M' + 78: 95, # 'N' + 79: 85, # 'O' + 80: 78, # 'P' + 81: 121, # 'Q' + 82: 86, # 'R' + 83: 71, # 'S' + 84: 67, # 'T' + 85: 102, # 'U' + 86: 107, # 'V' + 87: 84, # 'W' + 88: 114, # 'X' + 89: 103, # 'Y' + 90: 115, # 'Z' + 91: 253, # '[' + 92: 253, # '\\' + 93: 253, # ']' + 94: 253, # '^' + 95: 253, # '_' + 96: 253, # '`' + 97: 50, # 'a' + 98: 74, # 'b' + 99: 60, # 'c' + 100: 61, # 'd' + 101: 42, # 'e' + 102: 76, # 'f' + 103: 70, # 'g' + 104: 64, # 'h' + 105: 53, # 'i' + 106: 105, # 'j' + 107: 93, # 'k' + 108: 56, # 'l' + 109: 65, # 'm' + 110: 54, # 'n' + 111: 49, # 'o' + 112: 66, # 'p' + 113: 110, # 'q' + 114: 51, # 'r' + 115: 43, # 's' + 116: 44, # 't' + 117: 63, # 'u' + 118: 81, # 'v' + 119: 77, # 'w' + 120: 98, # 'x' + 121: 75, # 'y' + 122: 108, # 'z' + 123: 253, # '{' + 124: 253, # '|' + 125: 253, # '}' + 126: 253, # '~' + 127: 253, # '\x7f' + 128: 124, # '€' + 129: 202, # None + 130: 203, # '‚' + 131: 204, # 'Æ’' + 132: 205, # '„' + 133: 40, # '…' + 134: 58, # '†' + 135: 206, # '‡' + 136: 207, # 'ˆ' + 137: 208, # '‰' + 138: 209, # None + 139: 210, # '‹' + 140: 211, # None + 141: 212, # None + 142: 213, # None + 143: 214, # None + 144: 215, # None + 145: 83, # '‘' + 146: 52, # '’' + 147: 47, # '“' + 148: 46, # 'â€' + 149: 72, # '•' + 150: 32, # '–' + 151: 94, # '—' + 152: 216, # 'Ëœ' + 153: 113, # 'â„¢' + 154: 217, # None + 155: 109, # '›' + 156: 218, # None + 157: 219, # None + 158: 220, # None + 159: 221, # None + 160: 34, # '\xa0' + 161: 116, # '¡' + 162: 222, # '¢' + 163: 118, # '£' + 164: 100, # '₪' + 165: 223, # 'Â¥' + 166: 224, # '¦' + 167: 117, # '§' + 168: 119, # '¨' + 169: 104, # '©' + 170: 125, # '×' + 171: 225, # '«' + 172: 226, # '¬' + 173: 87, # '\xad' + 174: 99, # '®' + 175: 227, # '¯' + 176: 106, # '°' + 177: 122, # '±' + 178: 123, # '²' + 179: 228, # '³' + 180: 55, # '´' + 181: 229, # 'µ' + 182: 230, # '¶' + 183: 101, # '·' + 184: 231, # '¸' + 185: 232, # '¹' + 186: 120, # '÷' + 187: 233, # '»' + 188: 48, # '¼' + 189: 39, # '½' + 190: 57, # '¾' + 191: 234, # '¿' + 192: 30, # 'Ö°' + 193: 59, # 'Ö±' + 194: 41, # 'Ö²' + 195: 88, # 'Ö³' + 196: 33, # 'Ö´' + 197: 37, # 'Öµ' + 198: 36, # 'Ö¶' + 199: 31, # 'Ö·' + 200: 29, # 'Ö¸' + 201: 35, # 'Ö¹' + 202: 235, # None + 203: 62, # 'Ö»' + 204: 28, # 'Ö¼' + 205: 236, # 'Ö½' + 206: 126, # 'Ö¾' + 207: 237, # 'Ö¿' + 208: 238, # '×€' + 209: 38, # '×' + 210: 45, # 'ׂ' + 211: 239, # '׃' + 212: 240, # '×°' + 213: 241, # '×±' + 214: 242, # 'ײ' + 215: 243, # '׳' + 216: 127, # '×´' + 217: 244, # None + 218: 245, # None + 219: 246, # None + 220: 247, # None + 221: 248, # None + 222: 249, # None + 223: 250, # None + 224: 9, # '×' + 225: 8, # 'ב' + 226: 20, # '×’' + 227: 16, # 'ד' + 228: 3, # '×”' + 229: 2, # 'ו' + 230: 24, # '×–' + 231: 14, # '×—' + 232: 22, # 'ט' + 233: 1, # '×™' + 234: 25, # 'ך' + 235: 15, # '×›' + 236: 4, # 'ל' + 237: 11, # '×' + 238: 6, # 'מ' + 239: 23, # 'ן' + 240: 12, # '× ' + 241: 19, # 'ס' + 242: 13, # '×¢' + 243: 26, # '×£' + 244: 18, # 'פ' + 245: 27, # '×¥' + 246: 21, # 'צ' + 247: 17, # 'ק' + 248: 7, # 'ר' + 249: 10, # 'ש' + 250: 5, # 'ת' + 251: 251, # None + 252: 252, # None + 253: 128, # '\u200e' + 254: 96, # '\u200f' + 255: 253, # None +} + +WINDOWS_1255_HEBREW_MODEL = SingleByteCharSetModel(charset_name='windows-1255', + language='Hebrew', + char_to_order_map=WINDOWS_1255_HEBREW_CHAR_TO_ORDER, + language_model=HEBREW_LANG_MODEL, + typical_positive_ratio=0.984004, + keep_ascii_letters=False, + alphabet='×בגדהוזחטיךכל×מןנסעףפץצקרשתװױײ') + diff --git a/venv/Lib/site-packages/pip/_vendor/chardet/langhungarianmodel.py b/venv/Lib/site-packages/pip/_vendor/chardet/langhungarianmodel.py new file mode 100644 index 0000000..bbc5cda --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/chardet/langhungarianmodel.py @@ -0,0 +1,4650 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +from pip._vendor.chardet.sbcharsetprober import SingleByteCharSetModel + + +# 3: Positive +# 2: Likely +# 1: Unlikely +# 0: Negative + +HUNGARIAN_LANG_MODEL = { + 28: { # 'A' + 28: 0, # 'A' + 40: 1, # 'B' + 54: 1, # 'C' + 45: 2, # 'D' + 32: 1, # 'E' + 50: 1, # 'F' + 49: 2, # 'G' + 38: 1, # 'H' + 39: 2, # 'I' + 53: 1, # 'J' + 36: 2, # 'K' + 41: 2, # 'L' + 34: 1, # 'M' + 35: 2, # 'N' + 47: 1, # 'O' + 46: 2, # 'P' + 43: 2, # 'R' + 33: 2, # 'S' + 37: 2, # 'T' + 57: 1, # 'U' + 48: 1, # 'V' + 55: 1, # 'Y' + 52: 2, # 'Z' + 2: 0, # 'a' + 18: 1, # 'b' + 26: 1, # 'c' + 17: 2, # 'd' + 1: 1, # 'e' + 27: 1, # 'f' + 12: 1, # 'g' + 20: 1, # 'h' + 9: 1, # 'i' + 22: 1, # 'j' + 7: 2, # 'k' + 6: 2, # 'l' + 13: 2, # 'm' + 4: 2, # 'n' + 8: 0, # 'o' + 23: 2, # 'p' + 10: 2, # 'r' + 5: 1, # 's' + 3: 1, # 't' + 21: 1, # 'u' + 19: 1, # 'v' + 62: 1, # 'x' + 16: 0, # 'y' + 11: 3, # 'z' + 51: 1, # 'Ã' + 44: 0, # 'É' + 61: 1, # 'Ã' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ãœ' + 14: 0, # 'á' + 15: 0, # 'é' + 30: 0, # 'í' + 25: 0, # 'ó' + 24: 0, # 'ö' + 31: 0, # 'ú' + 29: 0, # 'ü' + 42: 0, # 'Å‘' + 56: 0, # 'ű' + }, + 40: { # 'B' + 28: 2, # 'A' + 40: 1, # 'B' + 54: 1, # 'C' + 45: 1, # 'D' + 32: 2, # 'E' + 50: 0, # 'F' + 49: 0, # 'G' + 38: 0, # 'H' + 39: 1, # 'I' + 53: 1, # 'J' + 36: 1, # 'K' + 41: 1, # 'L' + 34: 0, # 'M' + 35: 1, # 'N' + 47: 2, # 'O' + 46: 0, # 'P' + 43: 1, # 'R' + 33: 1, # 'S' + 37: 1, # 'T' + 57: 1, # 'U' + 48: 1, # 'V' + 55: 0, # 'Y' + 52: 0, # 'Z' + 2: 2, # 'a' + 18: 0, # 'b' + 26: 0, # 'c' + 17: 0, # 'd' + 1: 3, # 'e' + 27: 0, # 'f' + 12: 0, # 'g' + 20: 0, # 'h' + 9: 2, # 'i' + 22: 1, # 'j' + 7: 0, # 'k' + 6: 1, # 'l' + 13: 0, # 'm' + 4: 0, # 'n' + 8: 2, # 'o' + 23: 1, # 'p' + 10: 2, # 'r' + 5: 0, # 's' + 3: 0, # 't' + 21: 3, # 'u' + 19: 0, # 'v' + 62: 0, # 'x' + 16: 1, # 'y' + 11: 0, # 'z' + 51: 1, # 'Ã' + 44: 1, # 'É' + 61: 1, # 'Ã' + 58: 1, # 'Ó' + 59: 1, # 'Ö' + 60: 1, # 'Ú' + 63: 1, # 'Ãœ' + 14: 2, # 'á' + 15: 2, # 'é' + 30: 1, # 'í' + 25: 1, # 'ó' + 24: 1, # 'ö' + 31: 1, # 'ú' + 29: 1, # 'ü' + 42: 1, # 'Å‘' + 56: 1, # 'ű' + }, + 54: { # 'C' + 28: 1, # 'A' + 40: 1, # 'B' + 54: 1, # 'C' + 45: 1, # 'D' + 32: 1, # 'E' + 50: 0, # 'F' + 49: 0, # 'G' + 38: 1, # 'H' + 39: 2, # 'I' + 53: 1, # 'J' + 36: 1, # 'K' + 41: 1, # 'L' + 34: 1, # 'M' + 35: 0, # 'N' + 47: 1, # 'O' + 46: 1, # 'P' + 43: 1, # 'R' + 33: 2, # 'S' + 37: 1, # 'T' + 57: 1, # 'U' + 48: 0, # 'V' + 55: 1, # 'Y' + 52: 1, # 'Z' + 2: 2, # 'a' + 18: 0, # 'b' + 26: 0, # 'c' + 17: 0, # 'd' + 1: 1, # 'e' + 27: 0, # 'f' + 12: 0, # 'g' + 20: 1, # 'h' + 9: 1, # 'i' + 22: 0, # 'j' + 7: 0, # 'k' + 6: 1, # 'l' + 13: 0, # 'm' + 4: 0, # 'n' + 8: 2, # 'o' + 23: 0, # 'p' + 10: 1, # 'r' + 5: 3, # 's' + 3: 0, # 't' + 21: 1, # 'u' + 19: 0, # 'v' + 62: 0, # 'x' + 16: 1, # 'y' + 11: 1, # 'z' + 51: 1, # 'Ã' + 44: 1, # 'É' + 61: 1, # 'Ã' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ãœ' + 14: 1, # 'á' + 15: 1, # 'é' + 30: 1, # 'í' + 25: 1, # 'ó' + 24: 0, # 'ö' + 31: 0, # 'ú' + 29: 0, # 'ü' + 42: 0, # 'Å‘' + 56: 0, # 'ű' + }, + 45: { # 'D' + 28: 2, # 'A' + 40: 1, # 'B' + 54: 0, # 'C' + 45: 1, # 'D' + 32: 2, # 'E' + 50: 1, # 'F' + 49: 1, # 'G' + 38: 1, # 'H' + 39: 2, # 'I' + 53: 1, # 'J' + 36: 1, # 'K' + 41: 0, # 'L' + 34: 1, # 'M' + 35: 1, # 'N' + 47: 2, # 'O' + 46: 0, # 'P' + 43: 1, # 'R' + 33: 1, # 'S' + 37: 1, # 'T' + 57: 1, # 'U' + 48: 1, # 'V' + 55: 1, # 'Y' + 52: 1, # 'Z' + 2: 2, # 'a' + 18: 0, # 'b' + 26: 0, # 'c' + 17: 0, # 'd' + 1: 3, # 'e' + 27: 0, # 'f' + 12: 0, # 'g' + 20: 0, # 'h' + 9: 1, # 'i' + 22: 0, # 'j' + 7: 0, # 'k' + 6: 0, # 'l' + 13: 0, # 'm' + 4: 0, # 'n' + 8: 1, # 'o' + 23: 0, # 'p' + 10: 2, # 'r' + 5: 0, # 's' + 3: 0, # 't' + 21: 2, # 'u' + 19: 0, # 'v' + 62: 0, # 'x' + 16: 1, # 'y' + 11: 1, # 'z' + 51: 1, # 'Ã' + 44: 1, # 'É' + 61: 1, # 'Ã' + 58: 1, # 'Ó' + 59: 1, # 'Ö' + 60: 1, # 'Ú' + 63: 1, # 'Ãœ' + 14: 1, # 'á' + 15: 1, # 'é' + 30: 1, # 'í' + 25: 1, # 'ó' + 24: 1, # 'ö' + 31: 1, # 'ú' + 29: 1, # 'ü' + 42: 1, # 'Å‘' + 56: 0, # 'ű' + }, + 32: { # 'E' + 28: 1, # 'A' + 40: 1, # 'B' + 54: 1, # 'C' + 45: 1, # 'D' + 32: 1, # 'E' + 50: 1, # 'F' + 49: 2, # 'G' + 38: 1, # 'H' + 39: 1, # 'I' + 53: 1, # 'J' + 36: 2, # 'K' + 41: 2, # 'L' + 34: 2, # 'M' + 35: 2, # 'N' + 47: 1, # 'O' + 46: 1, # 'P' + 43: 2, # 'R' + 33: 2, # 'S' + 37: 2, # 'T' + 57: 1, # 'U' + 48: 1, # 'V' + 55: 1, # 'Y' + 52: 1, # 'Z' + 2: 1, # 'a' + 18: 1, # 'b' + 26: 1, # 'c' + 17: 2, # 'd' + 1: 1, # 'e' + 27: 1, # 'f' + 12: 3, # 'g' + 20: 1, # 'h' + 9: 1, # 'i' + 22: 1, # 'j' + 7: 1, # 'k' + 6: 2, # 'l' + 13: 2, # 'm' + 4: 2, # 'n' + 8: 0, # 'o' + 23: 1, # 'p' + 10: 2, # 'r' + 5: 2, # 's' + 3: 1, # 't' + 21: 2, # 'u' + 19: 1, # 'v' + 62: 1, # 'x' + 16: 0, # 'y' + 11: 3, # 'z' + 51: 1, # 'Ã' + 44: 1, # 'É' + 61: 0, # 'Ã' + 58: 1, # 'Ó' + 59: 1, # 'Ö' + 60: 0, # 'Ú' + 63: 1, # 'Ãœ' + 14: 0, # 'á' + 15: 0, # 'é' + 30: 0, # 'í' + 25: 0, # 'ó' + 24: 1, # 'ö' + 31: 0, # 'ú' + 29: 0, # 'ü' + 42: 0, # 'Å‘' + 56: 0, # 'ű' + }, + 50: { # 'F' + 28: 1, # 'A' + 40: 0, # 'B' + 54: 0, # 'C' + 45: 0, # 'D' + 32: 1, # 'E' + 50: 1, # 'F' + 49: 0, # 'G' + 38: 1, # 'H' + 39: 1, # 'I' + 53: 1, # 'J' + 36: 1, # 'K' + 41: 1, # 'L' + 34: 1, # 'M' + 35: 1, # 'N' + 47: 1, # 'O' + 46: 0, # 'P' + 43: 1, # 'R' + 33: 0, # 'S' + 37: 1, # 'T' + 57: 1, # 'U' + 48: 0, # 'V' + 55: 1, # 'Y' + 52: 0, # 'Z' + 2: 2, # 'a' + 18: 0, # 'b' + 26: 0, # 'c' + 17: 0, # 'd' + 1: 2, # 'e' + 27: 1, # 'f' + 12: 0, # 'g' + 20: 0, # 'h' + 9: 2, # 'i' + 22: 1, # 'j' + 7: 0, # 'k' + 6: 1, # 'l' + 13: 0, # 'm' + 4: 0, # 'n' + 8: 2, # 'o' + 23: 0, # 'p' + 10: 2, # 'r' + 5: 0, # 's' + 3: 0, # 't' + 21: 1, # 'u' + 19: 0, # 'v' + 62: 0, # 'x' + 16: 0, # 'y' + 11: 0, # 'z' + 51: 1, # 'Ã' + 44: 1, # 'É' + 61: 0, # 'Ã' + 58: 1, # 'Ó' + 59: 1, # 'Ö' + 60: 0, # 'Ú' + 63: 1, # 'Ãœ' + 14: 1, # 'á' + 15: 1, # 'é' + 30: 0, # 'í' + 25: 0, # 'ó' + 24: 2, # 'ö' + 31: 1, # 'ú' + 29: 1, # 'ü' + 42: 1, # 'Å‘' + 56: 1, # 'ű' + }, + 49: { # 'G' + 28: 2, # 'A' + 40: 1, # 'B' + 54: 1, # 'C' + 45: 1, # 'D' + 32: 2, # 'E' + 50: 1, # 'F' + 49: 1, # 'G' + 38: 1, # 'H' + 39: 1, # 'I' + 53: 1, # 'J' + 36: 1, # 'K' + 41: 1, # 'L' + 34: 1, # 'M' + 35: 1, # 'N' + 47: 1, # 'O' + 46: 1, # 'P' + 43: 1, # 'R' + 33: 1, # 'S' + 37: 1, # 'T' + 57: 1, # 'U' + 48: 1, # 'V' + 55: 2, # 'Y' + 52: 1, # 'Z' + 2: 2, # 'a' + 18: 0, # 'b' + 26: 0, # 'c' + 17: 0, # 'd' + 1: 2, # 'e' + 27: 0, # 'f' + 12: 0, # 'g' + 20: 0, # 'h' + 9: 1, # 'i' + 22: 0, # 'j' + 7: 0, # 'k' + 6: 1, # 'l' + 13: 0, # 'm' + 4: 0, # 'n' + 8: 2, # 'o' + 23: 0, # 'p' + 10: 2, # 'r' + 5: 0, # 's' + 3: 0, # 't' + 21: 1, # 'u' + 19: 0, # 'v' + 62: 0, # 'x' + 16: 2, # 'y' + 11: 0, # 'z' + 51: 1, # 'Ã' + 44: 1, # 'É' + 61: 1, # 'Ã' + 58: 1, # 'Ó' + 59: 1, # 'Ö' + 60: 1, # 'Ú' + 63: 1, # 'Ãœ' + 14: 1, # 'á' + 15: 1, # 'é' + 30: 0, # 'í' + 25: 1, # 'ó' + 24: 1, # 'ö' + 31: 1, # 'ú' + 29: 1, # 'ü' + 42: 1, # 'Å‘' + 56: 0, # 'ű' + }, + 38: { # 'H' + 28: 2, # 'A' + 40: 1, # 'B' + 54: 1, # 'C' + 45: 0, # 'D' + 32: 1, # 'E' + 50: 0, # 'F' + 49: 0, # 'G' + 38: 0, # 'H' + 39: 1, # 'I' + 53: 0, # 'J' + 36: 0, # 'K' + 41: 1, # 'L' + 34: 0, # 'M' + 35: 0, # 'N' + 47: 1, # 'O' + 46: 0, # 'P' + 43: 1, # 'R' + 33: 1, # 'S' + 37: 1, # 'T' + 57: 1, # 'U' + 48: 0, # 'V' + 55: 1, # 'Y' + 52: 0, # 'Z' + 2: 3, # 'a' + 18: 0, # 'b' + 26: 0, # 'c' + 17: 0, # 'd' + 1: 2, # 'e' + 27: 0, # 'f' + 12: 0, # 'g' + 20: 0, # 'h' + 9: 2, # 'i' + 22: 1, # 'j' + 7: 0, # 'k' + 6: 1, # 'l' + 13: 1, # 'm' + 4: 0, # 'n' + 8: 3, # 'o' + 23: 0, # 'p' + 10: 1, # 'r' + 5: 0, # 's' + 3: 0, # 't' + 21: 2, # 'u' + 19: 0, # 'v' + 62: 0, # 'x' + 16: 1, # 'y' + 11: 0, # 'z' + 51: 2, # 'Ã' + 44: 2, # 'É' + 61: 1, # 'Ã' + 58: 1, # 'Ó' + 59: 1, # 'Ö' + 60: 1, # 'Ú' + 63: 1, # 'Ãœ' + 14: 2, # 'á' + 15: 1, # 'é' + 30: 2, # 'í' + 25: 1, # 'ó' + 24: 1, # 'ö' + 31: 1, # 'ú' + 29: 1, # 'ü' + 42: 1, # 'Å‘' + 56: 1, # 'ű' + }, + 39: { # 'I' + 28: 2, # 'A' + 40: 1, # 'B' + 54: 1, # 'C' + 45: 1, # 'D' + 32: 1, # 'E' + 50: 1, # 'F' + 49: 1, # 'G' + 38: 1, # 'H' + 39: 2, # 'I' + 53: 1, # 'J' + 36: 2, # 'K' + 41: 2, # 'L' + 34: 1, # 'M' + 35: 2, # 'N' + 47: 1, # 'O' + 46: 1, # 'P' + 43: 1, # 'R' + 33: 2, # 'S' + 37: 1, # 'T' + 57: 1, # 'U' + 48: 1, # 'V' + 55: 0, # 'Y' + 52: 2, # 'Z' + 2: 0, # 'a' + 18: 1, # 'b' + 26: 1, # 'c' + 17: 2, # 'd' + 1: 0, # 'e' + 27: 1, # 'f' + 12: 2, # 'g' + 20: 1, # 'h' + 9: 0, # 'i' + 22: 1, # 'j' + 7: 1, # 'k' + 6: 2, # 'l' + 13: 2, # 'm' + 4: 1, # 'n' + 8: 0, # 'o' + 23: 1, # 'p' + 10: 2, # 'r' + 5: 2, # 's' + 3: 2, # 't' + 21: 0, # 'u' + 19: 1, # 'v' + 62: 0, # 'x' + 16: 0, # 'y' + 11: 1, # 'z' + 51: 1, # 'Ã' + 44: 1, # 'É' + 61: 0, # 'Ã' + 58: 1, # 'Ó' + 59: 1, # 'Ö' + 60: 1, # 'Ú' + 63: 1, # 'Ãœ' + 14: 0, # 'á' + 15: 0, # 'é' + 30: 0, # 'í' + 25: 0, # 'ó' + 24: 0, # 'ö' + 31: 0, # 'ú' + 29: 0, # 'ü' + 42: 0, # 'Å‘' + 56: 0, # 'ű' + }, + 53: { # 'J' + 28: 2, # 'A' + 40: 0, # 'B' + 54: 1, # 'C' + 45: 1, # 'D' + 32: 2, # 'E' + 50: 0, # 'F' + 49: 0, # 'G' + 38: 1, # 'H' + 39: 1, # 'I' + 53: 1, # 'J' + 36: 1, # 'K' + 41: 1, # 'L' + 34: 1, # 'M' + 35: 1, # 'N' + 47: 1, # 'O' + 46: 0, # 'P' + 43: 0, # 'R' + 33: 1, # 'S' + 37: 1, # 'T' + 57: 1, # 'U' + 48: 0, # 'V' + 55: 0, # 'Y' + 52: 1, # 'Z' + 2: 2, # 'a' + 18: 0, # 'b' + 26: 0, # 'c' + 17: 0, # 'd' + 1: 2, # 'e' + 27: 0, # 'f' + 12: 0, # 'g' + 20: 0, # 'h' + 9: 1, # 'i' + 22: 0, # 'j' + 7: 0, # 'k' + 6: 0, # 'l' + 13: 0, # 'm' + 4: 0, # 'n' + 8: 1, # 'o' + 23: 0, # 'p' + 10: 0, # 'r' + 5: 0, # 's' + 3: 0, # 't' + 21: 2, # 'u' + 19: 0, # 'v' + 62: 0, # 'x' + 16: 0, # 'y' + 11: 0, # 'z' + 51: 1, # 'Ã' + 44: 1, # 'É' + 61: 0, # 'Ã' + 58: 1, # 'Ó' + 59: 1, # 'Ö' + 60: 1, # 'Ú' + 63: 1, # 'Ãœ' + 14: 2, # 'á' + 15: 1, # 'é' + 30: 0, # 'í' + 25: 2, # 'ó' + 24: 2, # 'ö' + 31: 1, # 'ú' + 29: 0, # 'ü' + 42: 1, # 'Å‘' + 56: 0, # 'ű' + }, + 36: { # 'K' + 28: 2, # 'A' + 40: 1, # 'B' + 54: 1, # 'C' + 45: 1, # 'D' + 32: 2, # 'E' + 50: 1, # 'F' + 49: 0, # 'G' + 38: 1, # 'H' + 39: 2, # 'I' + 53: 1, # 'J' + 36: 1, # 'K' + 41: 1, # 'L' + 34: 1, # 'M' + 35: 1, # 'N' + 47: 2, # 'O' + 46: 0, # 'P' + 43: 1, # 'R' + 33: 1, # 'S' + 37: 1, # 'T' + 57: 1, # 'U' + 48: 1, # 'V' + 55: 1, # 'Y' + 52: 0, # 'Z' + 2: 2, # 'a' + 18: 0, # 'b' + 26: 0, # 'c' + 17: 0, # 'd' + 1: 2, # 'e' + 27: 1, # 'f' + 12: 0, # 'g' + 20: 1, # 'h' + 9: 3, # 'i' + 22: 0, # 'j' + 7: 0, # 'k' + 6: 1, # 'l' + 13: 1, # 'm' + 4: 1, # 'n' + 8: 2, # 'o' + 23: 0, # 'p' + 10: 2, # 'r' + 5: 0, # 's' + 3: 0, # 't' + 21: 1, # 'u' + 19: 1, # 'v' + 62: 0, # 'x' + 16: 1, # 'y' + 11: 0, # 'z' + 51: 1, # 'Ã' + 44: 1, # 'É' + 61: 1, # 'Ã' + 58: 1, # 'Ó' + 59: 2, # 'Ö' + 60: 1, # 'Ú' + 63: 1, # 'Ãœ' + 14: 2, # 'á' + 15: 2, # 'é' + 30: 1, # 'í' + 25: 1, # 'ó' + 24: 2, # 'ö' + 31: 1, # 'ú' + 29: 2, # 'ü' + 42: 1, # 'Å‘' + 56: 0, # 'ű' + }, + 41: { # 'L' + 28: 2, # 'A' + 40: 1, # 'B' + 54: 1, # 'C' + 45: 1, # 'D' + 32: 2, # 'E' + 50: 1, # 'F' + 49: 1, # 'G' + 38: 1, # 'H' + 39: 2, # 'I' + 53: 1, # 'J' + 36: 1, # 'K' + 41: 2, # 'L' + 34: 1, # 'M' + 35: 1, # 'N' + 47: 2, # 'O' + 46: 0, # 'P' + 43: 1, # 'R' + 33: 1, # 'S' + 37: 2, # 'T' + 57: 1, # 'U' + 48: 1, # 'V' + 55: 1, # 'Y' + 52: 1, # 'Z' + 2: 2, # 'a' + 18: 0, # 'b' + 26: 0, # 'c' + 17: 0, # 'd' + 1: 3, # 'e' + 27: 0, # 'f' + 12: 0, # 'g' + 20: 0, # 'h' + 9: 2, # 'i' + 22: 1, # 'j' + 7: 0, # 'k' + 6: 1, # 'l' + 13: 0, # 'm' + 4: 0, # 'n' + 8: 2, # 'o' + 23: 0, # 'p' + 10: 0, # 'r' + 5: 0, # 's' + 3: 0, # 't' + 21: 2, # 'u' + 19: 0, # 'v' + 62: 0, # 'x' + 16: 1, # 'y' + 11: 0, # 'z' + 51: 2, # 'Ã' + 44: 1, # 'É' + 61: 1, # 'Ã' + 58: 1, # 'Ó' + 59: 1, # 'Ö' + 60: 1, # 'Ú' + 63: 1, # 'Ãœ' + 14: 2, # 'á' + 15: 1, # 'é' + 30: 1, # 'í' + 25: 1, # 'ó' + 24: 1, # 'ö' + 31: 0, # 'ú' + 29: 1, # 'ü' + 42: 0, # 'Å‘' + 56: 0, # 'ű' + }, + 34: { # 'M' + 28: 2, # 'A' + 40: 1, # 'B' + 54: 0, # 'C' + 45: 0, # 'D' + 32: 2, # 'E' + 50: 1, # 'F' + 49: 0, # 'G' + 38: 1, # 'H' + 39: 2, # 'I' + 53: 1, # 'J' + 36: 1, # 'K' + 41: 1, # 'L' + 34: 1, # 'M' + 35: 1, # 'N' + 47: 1, # 'O' + 46: 1, # 'P' + 43: 1, # 'R' + 33: 1, # 'S' + 37: 1, # 'T' + 57: 1, # 'U' + 48: 1, # 'V' + 55: 1, # 'Y' + 52: 1, # 'Z' + 2: 3, # 'a' + 18: 0, # 'b' + 26: 1, # 'c' + 17: 0, # 'd' + 1: 3, # 'e' + 27: 0, # 'f' + 12: 0, # 'g' + 20: 0, # 'h' + 9: 3, # 'i' + 22: 0, # 'j' + 7: 0, # 'k' + 6: 0, # 'l' + 13: 1, # 'm' + 4: 1, # 'n' + 8: 3, # 'o' + 23: 0, # 'p' + 10: 1, # 'r' + 5: 0, # 's' + 3: 0, # 't' + 21: 2, # 'u' + 19: 0, # 'v' + 62: 0, # 'x' + 16: 1, # 'y' + 11: 0, # 'z' + 51: 2, # 'Ã' + 44: 1, # 'É' + 61: 1, # 'Ã' + 58: 1, # 'Ó' + 59: 1, # 'Ö' + 60: 1, # 'Ú' + 63: 1, # 'Ãœ' + 14: 2, # 'á' + 15: 2, # 'é' + 30: 1, # 'í' + 25: 1, # 'ó' + 24: 1, # 'ö' + 31: 1, # 'ú' + 29: 1, # 'ü' + 42: 0, # 'Å‘' + 56: 1, # 'ű' + }, + 35: { # 'N' + 28: 2, # 'A' + 40: 1, # 'B' + 54: 1, # 'C' + 45: 2, # 'D' + 32: 2, # 'E' + 50: 1, # 'F' + 49: 1, # 'G' + 38: 1, # 'H' + 39: 1, # 'I' + 53: 1, # 'J' + 36: 1, # 'K' + 41: 1, # 'L' + 34: 1, # 'M' + 35: 1, # 'N' + 47: 1, # 'O' + 46: 1, # 'P' + 43: 1, # 'R' + 33: 1, # 'S' + 37: 2, # 'T' + 57: 1, # 'U' + 48: 1, # 'V' + 55: 2, # 'Y' + 52: 1, # 'Z' + 2: 3, # 'a' + 18: 0, # 'b' + 26: 0, # 'c' + 17: 0, # 'd' + 1: 3, # 'e' + 27: 0, # 'f' + 12: 0, # 'g' + 20: 0, # 'h' + 9: 2, # 'i' + 22: 0, # 'j' + 7: 0, # 'k' + 6: 0, # 'l' + 13: 0, # 'm' + 4: 1, # 'n' + 8: 2, # 'o' + 23: 0, # 'p' + 10: 0, # 'r' + 5: 0, # 's' + 3: 0, # 't' + 21: 1, # 'u' + 19: 0, # 'v' + 62: 0, # 'x' + 16: 2, # 'y' + 11: 0, # 'z' + 51: 1, # 'Ã' + 44: 1, # 'É' + 61: 1, # 'Ã' + 58: 1, # 'Ó' + 59: 1, # 'Ö' + 60: 1, # 'Ú' + 63: 1, # 'Ãœ' + 14: 1, # 'á' + 15: 2, # 'é' + 30: 1, # 'í' + 25: 1, # 'ó' + 24: 1, # 'ö' + 31: 0, # 'ú' + 29: 0, # 'ü' + 42: 1, # 'Å‘' + 56: 0, # 'ű' + }, + 47: { # 'O' + 28: 1, # 'A' + 40: 1, # 'B' + 54: 1, # 'C' + 45: 1, # 'D' + 32: 1, # 'E' + 50: 1, # 'F' + 49: 1, # 'G' + 38: 1, # 'H' + 39: 1, # 'I' + 53: 1, # 'J' + 36: 2, # 'K' + 41: 2, # 'L' + 34: 2, # 'M' + 35: 2, # 'N' + 47: 1, # 'O' + 46: 1, # 'P' + 43: 2, # 'R' + 33: 2, # 'S' + 37: 2, # 'T' + 57: 1, # 'U' + 48: 1, # 'V' + 55: 1, # 'Y' + 52: 1, # 'Z' + 2: 0, # 'a' + 18: 1, # 'b' + 26: 1, # 'c' + 17: 1, # 'd' + 1: 1, # 'e' + 27: 1, # 'f' + 12: 1, # 'g' + 20: 1, # 'h' + 9: 1, # 'i' + 22: 1, # 'j' + 7: 2, # 'k' + 6: 2, # 'l' + 13: 1, # 'm' + 4: 1, # 'n' + 8: 1, # 'o' + 23: 1, # 'p' + 10: 2, # 'r' + 5: 1, # 's' + 3: 2, # 't' + 21: 1, # 'u' + 19: 0, # 'v' + 62: 1, # 'x' + 16: 0, # 'y' + 11: 1, # 'z' + 51: 1, # 'Ã' + 44: 1, # 'É' + 61: 0, # 'Ã' + 58: 1, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ãœ' + 14: 0, # 'á' + 15: 0, # 'é' + 30: 0, # 'í' + 25: 0, # 'ó' + 24: 0, # 'ö' + 31: 0, # 'ú' + 29: 0, # 'ü' + 42: 0, # 'Å‘' + 56: 0, # 'ű' + }, + 46: { # 'P' + 28: 1, # 'A' + 40: 1, # 'B' + 54: 1, # 'C' + 45: 1, # 'D' + 32: 1, # 'E' + 50: 1, # 'F' + 49: 1, # 'G' + 38: 1, # 'H' + 39: 1, # 'I' + 53: 1, # 'J' + 36: 1, # 'K' + 41: 1, # 'L' + 34: 0, # 'M' + 35: 1, # 'N' + 47: 1, # 'O' + 46: 1, # 'P' + 43: 2, # 'R' + 33: 1, # 'S' + 37: 1, # 'T' + 57: 1, # 'U' + 48: 1, # 'V' + 55: 0, # 'Y' + 52: 1, # 'Z' + 2: 2, # 'a' + 18: 0, # 'b' + 26: 0, # 'c' + 17: 0, # 'd' + 1: 2, # 'e' + 27: 1, # 'f' + 12: 0, # 'g' + 20: 1, # 'h' + 9: 2, # 'i' + 22: 0, # 'j' + 7: 0, # 'k' + 6: 1, # 'l' + 13: 0, # 'm' + 4: 1, # 'n' + 8: 2, # 'o' + 23: 0, # 'p' + 10: 2, # 'r' + 5: 1, # 's' + 3: 0, # 't' + 21: 1, # 'u' + 19: 0, # 'v' + 62: 0, # 'x' + 16: 1, # 'y' + 11: 0, # 'z' + 51: 2, # 'Ã' + 44: 1, # 'É' + 61: 1, # 'Ã' + 58: 1, # 'Ó' + 59: 1, # 'Ö' + 60: 0, # 'Ú' + 63: 1, # 'Ãœ' + 14: 3, # 'á' + 15: 2, # 'é' + 30: 0, # 'í' + 25: 1, # 'ó' + 24: 1, # 'ö' + 31: 0, # 'ú' + 29: 1, # 'ü' + 42: 1, # 'Å‘' + 56: 0, # 'ű' + }, + 43: { # 'R' + 28: 2, # 'A' + 40: 1, # 'B' + 54: 1, # 'C' + 45: 1, # 'D' + 32: 2, # 'E' + 50: 1, # 'F' + 49: 1, # 'G' + 38: 1, # 'H' + 39: 2, # 'I' + 53: 1, # 'J' + 36: 1, # 'K' + 41: 1, # 'L' + 34: 1, # 'M' + 35: 1, # 'N' + 47: 2, # 'O' + 46: 1, # 'P' + 43: 1, # 'R' + 33: 2, # 'S' + 37: 2, # 'T' + 57: 1, # 'U' + 48: 1, # 'V' + 55: 1, # 'Y' + 52: 1, # 'Z' + 2: 2, # 'a' + 18: 0, # 'b' + 26: 0, # 'c' + 17: 0, # 'd' + 1: 2, # 'e' + 27: 0, # 'f' + 12: 0, # 'g' + 20: 1, # 'h' + 9: 2, # 'i' + 22: 0, # 'j' + 7: 0, # 'k' + 6: 0, # 'l' + 13: 0, # 'm' + 4: 0, # 'n' + 8: 2, # 'o' + 23: 0, # 'p' + 10: 0, # 'r' + 5: 0, # 's' + 3: 0, # 't' + 21: 1, # 'u' + 19: 0, # 'v' + 62: 0, # 'x' + 16: 1, # 'y' + 11: 0, # 'z' + 51: 2, # 'Ã' + 44: 1, # 'É' + 61: 1, # 'Ã' + 58: 2, # 'Ó' + 59: 1, # 'Ö' + 60: 1, # 'Ú' + 63: 1, # 'Ãœ' + 14: 2, # 'á' + 15: 2, # 'é' + 30: 1, # 'í' + 25: 2, # 'ó' + 24: 1, # 'ö' + 31: 1, # 'ú' + 29: 1, # 'ü' + 42: 0, # 'Å‘' + 56: 0, # 'ű' + }, + 33: { # 'S' + 28: 2, # 'A' + 40: 1, # 'B' + 54: 1, # 'C' + 45: 1, # 'D' + 32: 2, # 'E' + 50: 1, # 'F' + 49: 1, # 'G' + 38: 1, # 'H' + 39: 2, # 'I' + 53: 1, # 'J' + 36: 1, # 'K' + 41: 1, # 'L' + 34: 1, # 'M' + 35: 1, # 'N' + 47: 2, # 'O' + 46: 1, # 'P' + 43: 1, # 'R' + 33: 2, # 'S' + 37: 2, # 'T' + 57: 1, # 'U' + 48: 1, # 'V' + 55: 1, # 'Y' + 52: 3, # 'Z' + 2: 2, # 'a' + 18: 0, # 'b' + 26: 1, # 'c' + 17: 0, # 'd' + 1: 2, # 'e' + 27: 0, # 'f' + 12: 0, # 'g' + 20: 1, # 'h' + 9: 2, # 'i' + 22: 0, # 'j' + 7: 1, # 'k' + 6: 1, # 'l' + 13: 1, # 'm' + 4: 0, # 'n' + 8: 2, # 'o' + 23: 1, # 'p' + 10: 0, # 'r' + 5: 0, # 's' + 3: 1, # 't' + 21: 1, # 'u' + 19: 1, # 'v' + 62: 0, # 'x' + 16: 1, # 'y' + 11: 3, # 'z' + 51: 2, # 'Ã' + 44: 1, # 'É' + 61: 1, # 'Ã' + 58: 1, # 'Ó' + 59: 1, # 'Ö' + 60: 1, # 'Ú' + 63: 1, # 'Ãœ' + 14: 2, # 'á' + 15: 1, # 'é' + 30: 1, # 'í' + 25: 1, # 'ó' + 24: 1, # 'ö' + 31: 1, # 'ú' + 29: 1, # 'ü' + 42: 1, # 'Å‘' + 56: 1, # 'ű' + }, + 37: { # 'T' + 28: 2, # 'A' + 40: 1, # 'B' + 54: 1, # 'C' + 45: 1, # 'D' + 32: 2, # 'E' + 50: 1, # 'F' + 49: 1, # 'G' + 38: 1, # 'H' + 39: 2, # 'I' + 53: 1, # 'J' + 36: 1, # 'K' + 41: 1, # 'L' + 34: 1, # 'M' + 35: 1, # 'N' + 47: 2, # 'O' + 46: 1, # 'P' + 43: 2, # 'R' + 33: 1, # 'S' + 37: 2, # 'T' + 57: 1, # 'U' + 48: 1, # 'V' + 55: 1, # 'Y' + 52: 1, # 'Z' + 2: 2, # 'a' + 18: 0, # 'b' + 26: 0, # 'c' + 17: 0, # 'd' + 1: 2, # 'e' + 27: 0, # 'f' + 12: 0, # 'g' + 20: 1, # 'h' + 9: 2, # 'i' + 22: 0, # 'j' + 7: 0, # 'k' + 6: 0, # 'l' + 13: 0, # 'm' + 4: 0, # 'n' + 8: 2, # 'o' + 23: 0, # 'p' + 10: 1, # 'r' + 5: 1, # 's' + 3: 0, # 't' + 21: 2, # 'u' + 19: 0, # 'v' + 62: 0, # 'x' + 16: 1, # 'y' + 11: 1, # 'z' + 51: 2, # 'Ã' + 44: 2, # 'É' + 61: 1, # 'Ã' + 58: 1, # 'Ó' + 59: 1, # 'Ö' + 60: 1, # 'Ú' + 63: 1, # 'Ãœ' + 14: 2, # 'á' + 15: 1, # 'é' + 30: 1, # 'í' + 25: 1, # 'ó' + 24: 2, # 'ö' + 31: 1, # 'ú' + 29: 1, # 'ü' + 42: 1, # 'Å‘' + 56: 1, # 'ű' + }, + 57: { # 'U' + 28: 1, # 'A' + 40: 1, # 'B' + 54: 1, # 'C' + 45: 1, # 'D' + 32: 1, # 'E' + 50: 1, # 'F' + 49: 1, # 'G' + 38: 1, # 'H' + 39: 1, # 'I' + 53: 1, # 'J' + 36: 1, # 'K' + 41: 1, # 'L' + 34: 1, # 'M' + 35: 1, # 'N' + 47: 1, # 'O' + 46: 1, # 'P' + 43: 1, # 'R' + 33: 2, # 'S' + 37: 1, # 'T' + 57: 0, # 'U' + 48: 1, # 'V' + 55: 0, # 'Y' + 52: 1, # 'Z' + 2: 0, # 'a' + 18: 1, # 'b' + 26: 1, # 'c' + 17: 1, # 'd' + 1: 1, # 'e' + 27: 0, # 'f' + 12: 2, # 'g' + 20: 0, # 'h' + 9: 0, # 'i' + 22: 1, # 'j' + 7: 1, # 'k' + 6: 1, # 'l' + 13: 1, # 'm' + 4: 1, # 'n' + 8: 0, # 'o' + 23: 1, # 'p' + 10: 1, # 'r' + 5: 1, # 's' + 3: 1, # 't' + 21: 0, # 'u' + 19: 0, # 'v' + 62: 0, # 'x' + 16: 0, # 'y' + 11: 1, # 'z' + 51: 0, # 'Ã' + 44: 0, # 'É' + 61: 1, # 'Ã' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ãœ' + 14: 0, # 'á' + 15: 0, # 'é' + 30: 0, # 'í' + 25: 0, # 'ó' + 24: 0, # 'ö' + 31: 0, # 'ú' + 29: 0, # 'ü' + 42: 0, # 'Å‘' + 56: 0, # 'ű' + }, + 48: { # 'V' + 28: 2, # 'A' + 40: 0, # 'B' + 54: 0, # 'C' + 45: 1, # 'D' + 32: 2, # 'E' + 50: 1, # 'F' + 49: 0, # 'G' + 38: 0, # 'H' + 39: 2, # 'I' + 53: 1, # 'J' + 36: 1, # 'K' + 41: 0, # 'L' + 34: 1, # 'M' + 35: 1, # 'N' + 47: 1, # 'O' + 46: 1, # 'P' + 43: 1, # 'R' + 33: 1, # 'S' + 37: 1, # 'T' + 57: 1, # 'U' + 48: 1, # 'V' + 55: 1, # 'Y' + 52: 0, # 'Z' + 2: 3, # 'a' + 18: 0, # 'b' + 26: 0, # 'c' + 17: 0, # 'd' + 1: 2, # 'e' + 27: 0, # 'f' + 12: 0, # 'g' + 20: 0, # 'h' + 9: 2, # 'i' + 22: 0, # 'j' + 7: 0, # 'k' + 6: 1, # 'l' + 13: 0, # 'm' + 4: 0, # 'n' + 8: 2, # 'o' + 23: 0, # 'p' + 10: 0, # 'r' + 5: 0, # 's' + 3: 0, # 't' + 21: 1, # 'u' + 19: 0, # 'v' + 62: 0, # 'x' + 16: 0, # 'y' + 11: 0, # 'z' + 51: 2, # 'Ã' + 44: 2, # 'É' + 61: 1, # 'Ã' + 58: 1, # 'Ó' + 59: 1, # 'Ö' + 60: 0, # 'Ú' + 63: 1, # 'Ãœ' + 14: 2, # 'á' + 15: 2, # 'é' + 30: 1, # 'í' + 25: 0, # 'ó' + 24: 1, # 'ö' + 31: 0, # 'ú' + 29: 0, # 'ü' + 42: 0, # 'Å‘' + 56: 0, # 'ű' + }, + 55: { # 'Y' + 28: 2, # 'A' + 40: 1, # 'B' + 54: 1, # 'C' + 45: 1, # 'D' + 32: 2, # 'E' + 50: 1, # 'F' + 49: 1, # 'G' + 38: 1, # 'H' + 39: 1, # 'I' + 53: 1, # 'J' + 36: 1, # 'K' + 41: 1, # 'L' + 34: 1, # 'M' + 35: 1, # 'N' + 47: 1, # 'O' + 46: 1, # 'P' + 43: 1, # 'R' + 33: 1, # 'S' + 37: 1, # 'T' + 57: 1, # 'U' + 48: 1, # 'V' + 55: 0, # 'Y' + 52: 2, # 'Z' + 2: 1, # 'a' + 18: 0, # 'b' + 26: 0, # 'c' + 17: 1, # 'd' + 1: 1, # 'e' + 27: 0, # 'f' + 12: 0, # 'g' + 20: 0, # 'h' + 9: 0, # 'i' + 22: 0, # 'j' + 7: 0, # 'k' + 6: 0, # 'l' + 13: 0, # 'm' + 4: 0, # 'n' + 8: 1, # 'o' + 23: 1, # 'p' + 10: 0, # 'r' + 5: 0, # 's' + 3: 0, # 't' + 21: 0, # 'u' + 19: 1, # 'v' + 62: 0, # 'x' + 16: 0, # 'y' + 11: 0, # 'z' + 51: 1, # 'Ã' + 44: 1, # 'É' + 61: 1, # 'Ã' + 58: 1, # 'Ó' + 59: 1, # 'Ö' + 60: 1, # 'Ú' + 63: 1, # 'Ãœ' + 14: 0, # 'á' + 15: 0, # 'é' + 30: 0, # 'í' + 25: 0, # 'ó' + 24: 0, # 'ö' + 31: 0, # 'ú' + 29: 0, # 'ü' + 42: 0, # 'Å‘' + 56: 0, # 'ű' + }, + 52: { # 'Z' + 28: 2, # 'A' + 40: 1, # 'B' + 54: 0, # 'C' + 45: 1, # 'D' + 32: 2, # 'E' + 50: 1, # 'F' + 49: 1, # 'G' + 38: 1, # 'H' + 39: 2, # 'I' + 53: 1, # 'J' + 36: 1, # 'K' + 41: 1, # 'L' + 34: 1, # 'M' + 35: 1, # 'N' + 47: 2, # 'O' + 46: 1, # 'P' + 43: 1, # 'R' + 33: 2, # 'S' + 37: 1, # 'T' + 57: 1, # 'U' + 48: 1, # 'V' + 55: 1, # 'Y' + 52: 1, # 'Z' + 2: 1, # 'a' + 18: 0, # 'b' + 26: 0, # 'c' + 17: 0, # 'd' + 1: 1, # 'e' + 27: 0, # 'f' + 12: 0, # 'g' + 20: 0, # 'h' + 9: 1, # 'i' + 22: 0, # 'j' + 7: 0, # 'k' + 6: 0, # 'l' + 13: 0, # 'm' + 4: 1, # 'n' + 8: 1, # 'o' + 23: 0, # 'p' + 10: 1, # 'r' + 5: 2, # 's' + 3: 0, # 't' + 21: 1, # 'u' + 19: 0, # 'v' + 62: 0, # 'x' + 16: 0, # 'y' + 11: 0, # 'z' + 51: 2, # 'Ã' + 44: 1, # 'É' + 61: 1, # 'Ã' + 58: 1, # 'Ó' + 59: 1, # 'Ö' + 60: 1, # 'Ú' + 63: 1, # 'Ãœ' + 14: 1, # 'á' + 15: 1, # 'é' + 30: 0, # 'í' + 25: 0, # 'ó' + 24: 1, # 'ö' + 31: 1, # 'ú' + 29: 1, # 'ü' + 42: 0, # 'Å‘' + 56: 0, # 'ű' + }, + 2: { # 'a' + 28: 0, # 'A' + 40: 0, # 'B' + 54: 0, # 'C' + 45: 0, # 'D' + 32: 0, # 'E' + 50: 0, # 'F' + 49: 0, # 'G' + 38: 0, # 'H' + 39: 0, # 'I' + 53: 0, # 'J' + 36: 0, # 'K' + 41: 0, # 'L' + 34: 0, # 'M' + 35: 0, # 'N' + 47: 0, # 'O' + 46: 0, # 'P' + 43: 0, # 'R' + 33: 0, # 'S' + 37: 0, # 'T' + 57: 0, # 'U' + 48: 0, # 'V' + 55: 0, # 'Y' + 52: 0, # 'Z' + 2: 1, # 'a' + 18: 3, # 'b' + 26: 3, # 'c' + 17: 3, # 'd' + 1: 2, # 'e' + 27: 2, # 'f' + 12: 3, # 'g' + 20: 3, # 'h' + 9: 3, # 'i' + 22: 3, # 'j' + 7: 3, # 'k' + 6: 3, # 'l' + 13: 3, # 'm' + 4: 3, # 'n' + 8: 2, # 'o' + 23: 3, # 'p' + 10: 3, # 'r' + 5: 3, # 's' + 3: 3, # 't' + 21: 3, # 'u' + 19: 3, # 'v' + 62: 1, # 'x' + 16: 2, # 'y' + 11: 3, # 'z' + 51: 0, # 'Ã' + 44: 0, # 'É' + 61: 0, # 'Ã' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ãœ' + 14: 1, # 'á' + 15: 1, # 'é' + 30: 1, # 'í' + 25: 1, # 'ó' + 24: 1, # 'ö' + 31: 1, # 'ú' + 29: 1, # 'ü' + 42: 0, # 'Å‘' + 56: 0, # 'ű' + }, + 18: { # 'b' + 28: 0, # 'A' + 40: 0, # 'B' + 54: 0, # 'C' + 45: 0, # 'D' + 32: 0, # 'E' + 50: 0, # 'F' + 49: 0, # 'G' + 38: 0, # 'H' + 39: 0, # 'I' + 53: 0, # 'J' + 36: 0, # 'K' + 41: 0, # 'L' + 34: 0, # 'M' + 35: 0, # 'N' + 47: 0, # 'O' + 46: 0, # 'P' + 43: 0, # 'R' + 33: 0, # 'S' + 37: 0, # 'T' + 57: 0, # 'U' + 48: 0, # 'V' + 55: 0, # 'Y' + 52: 0, # 'Z' + 2: 3, # 'a' + 18: 3, # 'b' + 26: 1, # 'c' + 17: 1, # 'd' + 1: 3, # 'e' + 27: 1, # 'f' + 12: 1, # 'g' + 20: 1, # 'h' + 9: 3, # 'i' + 22: 2, # 'j' + 7: 2, # 'k' + 6: 2, # 'l' + 13: 1, # 'm' + 4: 2, # 'n' + 8: 3, # 'o' + 23: 1, # 'p' + 10: 3, # 'r' + 5: 2, # 's' + 3: 1, # 't' + 21: 3, # 'u' + 19: 1, # 'v' + 62: 0, # 'x' + 16: 1, # 'y' + 11: 1, # 'z' + 51: 0, # 'Ã' + 44: 0, # 'É' + 61: 0, # 'Ã' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ãœ' + 14: 3, # 'á' + 15: 3, # 'é' + 30: 2, # 'í' + 25: 3, # 'ó' + 24: 2, # 'ö' + 31: 2, # 'ú' + 29: 2, # 'ü' + 42: 2, # 'Å‘' + 56: 1, # 'ű' + }, + 26: { # 'c' + 28: 0, # 'A' + 40: 0, # 'B' + 54: 1, # 'C' + 45: 0, # 'D' + 32: 0, # 'E' + 50: 0, # 'F' + 49: 1, # 'G' + 38: 0, # 'H' + 39: 0, # 'I' + 53: 0, # 'J' + 36: 0, # 'K' + 41: 0, # 'L' + 34: 0, # 'M' + 35: 0, # 'N' + 47: 0, # 'O' + 46: 0, # 'P' + 43: 0, # 'R' + 33: 0, # 'S' + 37: 0, # 'T' + 57: 0, # 'U' + 48: 0, # 'V' + 55: 0, # 'Y' + 52: 0, # 'Z' + 2: 2, # 'a' + 18: 1, # 'b' + 26: 2, # 'c' + 17: 1, # 'd' + 1: 3, # 'e' + 27: 1, # 'f' + 12: 1, # 'g' + 20: 3, # 'h' + 9: 3, # 'i' + 22: 1, # 'j' + 7: 2, # 'k' + 6: 1, # 'l' + 13: 1, # 'm' + 4: 1, # 'n' + 8: 3, # 'o' + 23: 1, # 'p' + 10: 2, # 'r' + 5: 3, # 's' + 3: 2, # 't' + 21: 2, # 'u' + 19: 1, # 'v' + 62: 0, # 'x' + 16: 1, # 'y' + 11: 2, # 'z' + 51: 0, # 'Ã' + 44: 0, # 'É' + 61: 0, # 'Ã' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ãœ' + 14: 2, # 'á' + 15: 2, # 'é' + 30: 2, # 'í' + 25: 1, # 'ó' + 24: 1, # 'ö' + 31: 1, # 'ú' + 29: 1, # 'ü' + 42: 0, # 'Å‘' + 56: 0, # 'ű' + }, + 17: { # 'd' + 28: 0, # 'A' + 40: 0, # 'B' + 54: 0, # 'C' + 45: 0, # 'D' + 32: 0, # 'E' + 50: 0, # 'F' + 49: 0, # 'G' + 38: 0, # 'H' + 39: 0, # 'I' + 53: 0, # 'J' + 36: 0, # 'K' + 41: 0, # 'L' + 34: 0, # 'M' + 35: 0, # 'N' + 47: 0, # 'O' + 46: 0, # 'P' + 43: 0, # 'R' + 33: 0, # 'S' + 37: 0, # 'T' + 57: 0, # 'U' + 48: 0, # 'V' + 55: 0, # 'Y' + 52: 0, # 'Z' + 2: 3, # 'a' + 18: 2, # 'b' + 26: 1, # 'c' + 17: 2, # 'd' + 1: 3, # 'e' + 27: 1, # 'f' + 12: 1, # 'g' + 20: 2, # 'h' + 9: 3, # 'i' + 22: 3, # 'j' + 7: 2, # 'k' + 6: 1, # 'l' + 13: 2, # 'm' + 4: 3, # 'n' + 8: 3, # 'o' + 23: 1, # 'p' + 10: 3, # 'r' + 5: 3, # 's' + 3: 3, # 't' + 21: 3, # 'u' + 19: 3, # 'v' + 62: 0, # 'x' + 16: 2, # 'y' + 11: 2, # 'z' + 51: 0, # 'Ã' + 44: 0, # 'É' + 61: 0, # 'Ã' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ãœ' + 14: 3, # 'á' + 15: 3, # 'é' + 30: 3, # 'í' + 25: 3, # 'ó' + 24: 3, # 'ö' + 31: 2, # 'ú' + 29: 2, # 'ü' + 42: 2, # 'Å‘' + 56: 1, # 'ű' + }, + 1: { # 'e' + 28: 0, # 'A' + 40: 0, # 'B' + 54: 0, # 'C' + 45: 0, # 'D' + 32: 0, # 'E' + 50: 0, # 'F' + 49: 0, # 'G' + 38: 0, # 'H' + 39: 0, # 'I' + 53: 0, # 'J' + 36: 0, # 'K' + 41: 0, # 'L' + 34: 0, # 'M' + 35: 0, # 'N' + 47: 0, # 'O' + 46: 0, # 'P' + 43: 0, # 'R' + 33: 0, # 'S' + 37: 0, # 'T' + 57: 0, # 'U' + 48: 0, # 'V' + 55: 0, # 'Y' + 52: 0, # 'Z' + 2: 2, # 'a' + 18: 3, # 'b' + 26: 3, # 'c' + 17: 3, # 'd' + 1: 2, # 'e' + 27: 3, # 'f' + 12: 3, # 'g' + 20: 3, # 'h' + 9: 3, # 'i' + 22: 3, # 'j' + 7: 3, # 'k' + 6: 3, # 'l' + 13: 3, # 'm' + 4: 3, # 'n' + 8: 2, # 'o' + 23: 3, # 'p' + 10: 3, # 'r' + 5: 3, # 's' + 3: 3, # 't' + 21: 2, # 'u' + 19: 3, # 'v' + 62: 2, # 'x' + 16: 2, # 'y' + 11: 3, # 'z' + 51: 0, # 'Ã' + 44: 0, # 'É' + 61: 0, # 'Ã' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ãœ' + 14: 3, # 'á' + 15: 1, # 'é' + 30: 1, # 'í' + 25: 1, # 'ó' + 24: 1, # 'ö' + 31: 1, # 'ú' + 29: 1, # 'ü' + 42: 0, # 'Å‘' + 56: 0, # 'ű' + }, + 27: { # 'f' + 28: 0, # 'A' + 40: 0, # 'B' + 54: 0, # 'C' + 45: 0, # 'D' + 32: 0, # 'E' + 50: 0, # 'F' + 49: 0, # 'G' + 38: 0, # 'H' + 39: 0, # 'I' + 53: 0, # 'J' + 36: 0, # 'K' + 41: 0, # 'L' + 34: 0, # 'M' + 35: 0, # 'N' + 47: 0, # 'O' + 46: 0, # 'P' + 43: 0, # 'R' + 33: 0, # 'S' + 37: 0, # 'T' + 57: 0, # 'U' + 48: 0, # 'V' + 55: 0, # 'Y' + 52: 0, # 'Z' + 2: 3, # 'a' + 18: 1, # 'b' + 26: 1, # 'c' + 17: 1, # 'd' + 1: 3, # 'e' + 27: 2, # 'f' + 12: 1, # 'g' + 20: 1, # 'h' + 9: 3, # 'i' + 22: 2, # 'j' + 7: 1, # 'k' + 6: 1, # 'l' + 13: 1, # 'm' + 4: 1, # 'n' + 8: 3, # 'o' + 23: 0, # 'p' + 10: 3, # 'r' + 5: 1, # 's' + 3: 1, # 't' + 21: 2, # 'u' + 19: 1, # 'v' + 62: 0, # 'x' + 16: 1, # 'y' + 11: 0, # 'z' + 51: 0, # 'Ã' + 44: 0, # 'É' + 61: 0, # 'Ã' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ãœ' + 14: 3, # 'á' + 15: 3, # 'é' + 30: 1, # 'í' + 25: 1, # 'ó' + 24: 3, # 'ö' + 31: 1, # 'ú' + 29: 2, # 'ü' + 42: 1, # 'Å‘' + 56: 1, # 'ű' + }, + 12: { # 'g' + 28: 0, # 'A' + 40: 0, # 'B' + 54: 0, # 'C' + 45: 0, # 'D' + 32: 0, # 'E' + 50: 0, # 'F' + 49: 0, # 'G' + 38: 0, # 'H' + 39: 0, # 'I' + 53: 0, # 'J' + 36: 0, # 'K' + 41: 0, # 'L' + 34: 0, # 'M' + 35: 0, # 'N' + 47: 0, # 'O' + 46: 0, # 'P' + 43: 0, # 'R' + 33: 0, # 'S' + 37: 0, # 'T' + 57: 0, # 'U' + 48: 0, # 'V' + 55: 0, # 'Y' + 52: 0, # 'Z' + 2: 3, # 'a' + 18: 3, # 'b' + 26: 2, # 'c' + 17: 2, # 'd' + 1: 3, # 'e' + 27: 2, # 'f' + 12: 3, # 'g' + 20: 3, # 'h' + 9: 3, # 'i' + 22: 3, # 'j' + 7: 2, # 'k' + 6: 3, # 'l' + 13: 2, # 'm' + 4: 3, # 'n' + 8: 3, # 'o' + 23: 1, # 'p' + 10: 3, # 'r' + 5: 3, # 's' + 3: 3, # 't' + 21: 3, # 'u' + 19: 3, # 'v' + 62: 0, # 'x' + 16: 3, # 'y' + 11: 2, # 'z' + 51: 0, # 'Ã' + 44: 0, # 'É' + 61: 0, # 'Ã' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ãœ' + 14: 3, # 'á' + 15: 3, # 'é' + 30: 2, # 'í' + 25: 3, # 'ó' + 24: 2, # 'ö' + 31: 2, # 'ú' + 29: 2, # 'ü' + 42: 2, # 'Å‘' + 56: 1, # 'ű' + }, + 20: { # 'h' + 28: 0, # 'A' + 40: 0, # 'B' + 54: 0, # 'C' + 45: 0, # 'D' + 32: 0, # 'E' + 50: 0, # 'F' + 49: 0, # 'G' + 38: 0, # 'H' + 39: 0, # 'I' + 53: 0, # 'J' + 36: 0, # 'K' + 41: 0, # 'L' + 34: 0, # 'M' + 35: 0, # 'N' + 47: 0, # 'O' + 46: 0, # 'P' + 43: 0, # 'R' + 33: 0, # 'S' + 37: 0, # 'T' + 57: 0, # 'U' + 48: 0, # 'V' + 55: 0, # 'Y' + 52: 0, # 'Z' + 2: 3, # 'a' + 18: 1, # 'b' + 26: 1, # 'c' + 17: 0, # 'd' + 1: 3, # 'e' + 27: 0, # 'f' + 12: 1, # 'g' + 20: 2, # 'h' + 9: 3, # 'i' + 22: 1, # 'j' + 7: 1, # 'k' + 6: 1, # 'l' + 13: 1, # 'm' + 4: 1, # 'n' + 8: 3, # 'o' + 23: 0, # 'p' + 10: 1, # 'r' + 5: 2, # 's' + 3: 1, # 't' + 21: 3, # 'u' + 19: 1, # 'v' + 62: 0, # 'x' + 16: 2, # 'y' + 11: 0, # 'z' + 51: 0, # 'Ã' + 44: 0, # 'É' + 61: 0, # 'Ã' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ãœ' + 14: 3, # 'á' + 15: 3, # 'é' + 30: 3, # 'í' + 25: 2, # 'ó' + 24: 2, # 'ö' + 31: 2, # 'ú' + 29: 1, # 'ü' + 42: 1, # 'Å‘' + 56: 1, # 'ű' + }, + 9: { # 'i' + 28: 0, # 'A' + 40: 0, # 'B' + 54: 0, # 'C' + 45: 0, # 'D' + 32: 0, # 'E' + 50: 0, # 'F' + 49: 0, # 'G' + 38: 0, # 'H' + 39: 0, # 'I' + 53: 0, # 'J' + 36: 0, # 'K' + 41: 0, # 'L' + 34: 0, # 'M' + 35: 0, # 'N' + 47: 0, # 'O' + 46: 0, # 'P' + 43: 0, # 'R' + 33: 0, # 'S' + 37: 0, # 'T' + 57: 0, # 'U' + 48: 0, # 'V' + 55: 0, # 'Y' + 52: 0, # 'Z' + 2: 3, # 'a' + 18: 3, # 'b' + 26: 3, # 'c' + 17: 3, # 'd' + 1: 3, # 'e' + 27: 3, # 'f' + 12: 3, # 'g' + 20: 3, # 'h' + 9: 2, # 'i' + 22: 2, # 'j' + 7: 3, # 'k' + 6: 3, # 'l' + 13: 3, # 'm' + 4: 3, # 'n' + 8: 2, # 'o' + 23: 2, # 'p' + 10: 3, # 'r' + 5: 3, # 's' + 3: 3, # 't' + 21: 3, # 'u' + 19: 3, # 'v' + 62: 1, # 'x' + 16: 1, # 'y' + 11: 3, # 'z' + 51: 0, # 'Ã' + 44: 0, # 'É' + 61: 0, # 'Ã' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ãœ' + 14: 3, # 'á' + 15: 2, # 'é' + 30: 1, # 'í' + 25: 3, # 'ó' + 24: 1, # 'ö' + 31: 2, # 'ú' + 29: 1, # 'ü' + 42: 0, # 'Å‘' + 56: 1, # 'ű' + }, + 22: { # 'j' + 28: 0, # 'A' + 40: 0, # 'B' + 54: 0, # 'C' + 45: 0, # 'D' + 32: 0, # 'E' + 50: 0, # 'F' + 49: 0, # 'G' + 38: 0, # 'H' + 39: 0, # 'I' + 53: 0, # 'J' + 36: 0, # 'K' + 41: 0, # 'L' + 34: 0, # 'M' + 35: 0, # 'N' + 47: 0, # 'O' + 46: 0, # 'P' + 43: 0, # 'R' + 33: 0, # 'S' + 37: 0, # 'T' + 57: 0, # 'U' + 48: 0, # 'V' + 55: 0, # 'Y' + 52: 0, # 'Z' + 2: 3, # 'a' + 18: 2, # 'b' + 26: 1, # 'c' + 17: 3, # 'd' + 1: 3, # 'e' + 27: 1, # 'f' + 12: 1, # 'g' + 20: 2, # 'h' + 9: 1, # 'i' + 22: 2, # 'j' + 7: 2, # 'k' + 6: 2, # 'l' + 13: 1, # 'm' + 4: 2, # 'n' + 8: 3, # 'o' + 23: 1, # 'p' + 10: 2, # 'r' + 5: 2, # 's' + 3: 3, # 't' + 21: 3, # 'u' + 19: 1, # 'v' + 62: 0, # 'x' + 16: 0, # 'y' + 11: 2, # 'z' + 51: 0, # 'Ã' + 44: 0, # 'É' + 61: 0, # 'Ã' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ãœ' + 14: 3, # 'á' + 15: 3, # 'é' + 30: 1, # 'í' + 25: 3, # 'ó' + 24: 3, # 'ö' + 31: 3, # 'ú' + 29: 2, # 'ü' + 42: 1, # 'Å‘' + 56: 1, # 'ű' + }, + 7: { # 'k' + 28: 0, # 'A' + 40: 0, # 'B' + 54: 0, # 'C' + 45: 0, # 'D' + 32: 0, # 'E' + 50: 0, # 'F' + 49: 0, # 'G' + 38: 0, # 'H' + 39: 0, # 'I' + 53: 0, # 'J' + 36: 0, # 'K' + 41: 0, # 'L' + 34: 0, # 'M' + 35: 0, # 'N' + 47: 0, # 'O' + 46: 0, # 'P' + 43: 0, # 'R' + 33: 0, # 'S' + 37: 0, # 'T' + 57: 0, # 'U' + 48: 0, # 'V' + 55: 0, # 'Y' + 52: 0, # 'Z' + 2: 3, # 'a' + 18: 3, # 'b' + 26: 2, # 'c' + 17: 1, # 'd' + 1: 3, # 'e' + 27: 1, # 'f' + 12: 1, # 'g' + 20: 2, # 'h' + 9: 3, # 'i' + 22: 2, # 'j' + 7: 3, # 'k' + 6: 3, # 'l' + 13: 1, # 'm' + 4: 3, # 'n' + 8: 3, # 'o' + 23: 1, # 'p' + 10: 3, # 'r' + 5: 3, # 's' + 3: 3, # 't' + 21: 3, # 'u' + 19: 2, # 'v' + 62: 0, # 'x' + 16: 2, # 'y' + 11: 1, # 'z' + 51: 0, # 'Ã' + 44: 0, # 'É' + 61: 0, # 'Ã' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ãœ' + 14: 3, # 'á' + 15: 3, # 'é' + 30: 3, # 'í' + 25: 2, # 'ó' + 24: 3, # 'ö' + 31: 1, # 'ú' + 29: 3, # 'ü' + 42: 1, # 'Å‘' + 56: 1, # 'ű' + }, + 6: { # 'l' + 28: 0, # 'A' + 40: 0, # 'B' + 54: 0, # 'C' + 45: 0, # 'D' + 32: 0, # 'E' + 50: 0, # 'F' + 49: 0, # 'G' + 38: 0, # 'H' + 39: 0, # 'I' + 53: 0, # 'J' + 36: 1, # 'K' + 41: 0, # 'L' + 34: 0, # 'M' + 35: 1, # 'N' + 47: 0, # 'O' + 46: 0, # 'P' + 43: 0, # 'R' + 33: 0, # 'S' + 37: 0, # 'T' + 57: 0, # 'U' + 48: 0, # 'V' + 55: 0, # 'Y' + 52: 0, # 'Z' + 2: 3, # 'a' + 18: 2, # 'b' + 26: 3, # 'c' + 17: 3, # 'd' + 1: 3, # 'e' + 27: 3, # 'f' + 12: 3, # 'g' + 20: 3, # 'h' + 9: 3, # 'i' + 22: 3, # 'j' + 7: 3, # 'k' + 6: 3, # 'l' + 13: 3, # 'm' + 4: 3, # 'n' + 8: 3, # 'o' + 23: 2, # 'p' + 10: 2, # 'r' + 5: 3, # 's' + 3: 3, # 't' + 21: 3, # 'u' + 19: 3, # 'v' + 62: 0, # 'x' + 16: 3, # 'y' + 11: 2, # 'z' + 51: 0, # 'Ã' + 44: 0, # 'É' + 61: 0, # 'Ã' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ãœ' + 14: 3, # 'á' + 15: 3, # 'é' + 30: 3, # 'í' + 25: 3, # 'ó' + 24: 3, # 'ö' + 31: 2, # 'ú' + 29: 2, # 'ü' + 42: 3, # 'Å‘' + 56: 1, # 'ű' + }, + 13: { # 'm' + 28: 0, # 'A' + 40: 0, # 'B' + 54: 0, # 'C' + 45: 0, # 'D' + 32: 0, # 'E' + 50: 0, # 'F' + 49: 0, # 'G' + 38: 0, # 'H' + 39: 0, # 'I' + 53: 0, # 'J' + 36: 0, # 'K' + 41: 0, # 'L' + 34: 0, # 'M' + 35: 0, # 'N' + 47: 0, # 'O' + 46: 0, # 'P' + 43: 0, # 'R' + 33: 0, # 'S' + 37: 0, # 'T' + 57: 0, # 'U' + 48: 0, # 'V' + 55: 0, # 'Y' + 52: 0, # 'Z' + 2: 3, # 'a' + 18: 3, # 'b' + 26: 2, # 'c' + 17: 1, # 'd' + 1: 3, # 'e' + 27: 1, # 'f' + 12: 1, # 'g' + 20: 2, # 'h' + 9: 3, # 'i' + 22: 2, # 'j' + 7: 1, # 'k' + 6: 3, # 'l' + 13: 3, # 'm' + 4: 2, # 'n' + 8: 3, # 'o' + 23: 3, # 'p' + 10: 2, # 'r' + 5: 2, # 's' + 3: 2, # 't' + 21: 3, # 'u' + 19: 1, # 'v' + 62: 0, # 'x' + 16: 1, # 'y' + 11: 2, # 'z' + 51: 0, # 'Ã' + 44: 0, # 'É' + 61: 0, # 'Ã' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ãœ' + 14: 3, # 'á' + 15: 3, # 'é' + 30: 2, # 'í' + 25: 2, # 'ó' + 24: 2, # 'ö' + 31: 2, # 'ú' + 29: 2, # 'ü' + 42: 1, # 'Å‘' + 56: 2, # 'ű' + }, + 4: { # 'n' + 28: 0, # 'A' + 40: 0, # 'B' + 54: 0, # 'C' + 45: 0, # 'D' + 32: 0, # 'E' + 50: 0, # 'F' + 49: 0, # 'G' + 38: 0, # 'H' + 39: 0, # 'I' + 53: 0, # 'J' + 36: 0, # 'K' + 41: 0, # 'L' + 34: 0, # 'M' + 35: 0, # 'N' + 47: 0, # 'O' + 46: 0, # 'P' + 43: 0, # 'R' + 33: 0, # 'S' + 37: 0, # 'T' + 57: 0, # 'U' + 48: 0, # 'V' + 55: 0, # 'Y' + 52: 0, # 'Z' + 2: 3, # 'a' + 18: 3, # 'b' + 26: 3, # 'c' + 17: 3, # 'd' + 1: 3, # 'e' + 27: 2, # 'f' + 12: 3, # 'g' + 20: 3, # 'h' + 9: 3, # 'i' + 22: 2, # 'j' + 7: 3, # 'k' + 6: 2, # 'l' + 13: 2, # 'm' + 4: 3, # 'n' + 8: 3, # 'o' + 23: 2, # 'p' + 10: 2, # 'r' + 5: 3, # 's' + 3: 3, # 't' + 21: 3, # 'u' + 19: 2, # 'v' + 62: 1, # 'x' + 16: 3, # 'y' + 11: 3, # 'z' + 51: 0, # 'Ã' + 44: 0, # 'É' + 61: 0, # 'Ã' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ãœ' + 14: 3, # 'á' + 15: 3, # 'é' + 30: 2, # 'í' + 25: 2, # 'ó' + 24: 3, # 'ö' + 31: 2, # 'ú' + 29: 3, # 'ü' + 42: 2, # 'Å‘' + 56: 1, # 'ű' + }, + 8: { # 'o' + 28: 0, # 'A' + 40: 0, # 'B' + 54: 0, # 'C' + 45: 0, # 'D' + 32: 0, # 'E' + 50: 0, # 'F' + 49: 0, # 'G' + 38: 0, # 'H' + 39: 0, # 'I' + 53: 0, # 'J' + 36: 0, # 'K' + 41: 0, # 'L' + 34: 0, # 'M' + 35: 0, # 'N' + 47: 1, # 'O' + 46: 0, # 'P' + 43: 0, # 'R' + 33: 0, # 'S' + 37: 0, # 'T' + 57: 0, # 'U' + 48: 0, # 'V' + 55: 0, # 'Y' + 52: 0, # 'Z' + 2: 2, # 'a' + 18: 3, # 'b' + 26: 3, # 'c' + 17: 3, # 'd' + 1: 2, # 'e' + 27: 2, # 'f' + 12: 3, # 'g' + 20: 3, # 'h' + 9: 2, # 'i' + 22: 2, # 'j' + 7: 3, # 'k' + 6: 3, # 'l' + 13: 3, # 'm' + 4: 3, # 'n' + 8: 1, # 'o' + 23: 3, # 'p' + 10: 3, # 'r' + 5: 3, # 's' + 3: 3, # 't' + 21: 2, # 'u' + 19: 3, # 'v' + 62: 1, # 'x' + 16: 1, # 'y' + 11: 3, # 'z' + 51: 0, # 'Ã' + 44: 0, # 'É' + 61: 0, # 'Ã' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ãœ' + 14: 1, # 'á' + 15: 2, # 'é' + 30: 1, # 'í' + 25: 1, # 'ó' + 24: 1, # 'ö' + 31: 1, # 'ú' + 29: 1, # 'ü' + 42: 0, # 'Å‘' + 56: 0, # 'ű' + }, + 23: { # 'p' + 28: 0, # 'A' + 40: 0, # 'B' + 54: 0, # 'C' + 45: 0, # 'D' + 32: 0, # 'E' + 50: 0, # 'F' + 49: 0, # 'G' + 38: 0, # 'H' + 39: 0, # 'I' + 53: 0, # 'J' + 36: 0, # 'K' + 41: 0, # 'L' + 34: 0, # 'M' + 35: 0, # 'N' + 47: 0, # 'O' + 46: 0, # 'P' + 43: 0, # 'R' + 33: 0, # 'S' + 37: 0, # 'T' + 57: 0, # 'U' + 48: 0, # 'V' + 55: 0, # 'Y' + 52: 0, # 'Z' + 2: 3, # 'a' + 18: 1, # 'b' + 26: 2, # 'c' + 17: 1, # 'd' + 1: 3, # 'e' + 27: 1, # 'f' + 12: 1, # 'g' + 20: 2, # 'h' + 9: 3, # 'i' + 22: 2, # 'j' + 7: 2, # 'k' + 6: 3, # 'l' + 13: 1, # 'm' + 4: 2, # 'n' + 8: 3, # 'o' + 23: 3, # 'p' + 10: 3, # 'r' + 5: 2, # 's' + 3: 2, # 't' + 21: 3, # 'u' + 19: 2, # 'v' + 62: 0, # 'x' + 16: 1, # 'y' + 11: 2, # 'z' + 51: 0, # 'Ã' + 44: 0, # 'É' + 61: 0, # 'Ã' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ãœ' + 14: 3, # 'á' + 15: 3, # 'é' + 30: 2, # 'í' + 25: 2, # 'ó' + 24: 2, # 'ö' + 31: 1, # 'ú' + 29: 2, # 'ü' + 42: 1, # 'Å‘' + 56: 1, # 'ű' + }, + 10: { # 'r' + 28: 0, # 'A' + 40: 0, # 'B' + 54: 0, # 'C' + 45: 0, # 'D' + 32: 0, # 'E' + 50: 0, # 'F' + 49: 0, # 'G' + 38: 0, # 'H' + 39: 0, # 'I' + 53: 0, # 'J' + 36: 0, # 'K' + 41: 0, # 'L' + 34: 0, # 'M' + 35: 0, # 'N' + 47: 0, # 'O' + 46: 0, # 'P' + 43: 0, # 'R' + 33: 0, # 'S' + 37: 0, # 'T' + 57: 0, # 'U' + 48: 0, # 'V' + 55: 0, # 'Y' + 52: 0, # 'Z' + 2: 3, # 'a' + 18: 3, # 'b' + 26: 3, # 'c' + 17: 3, # 'd' + 1: 3, # 'e' + 27: 2, # 'f' + 12: 3, # 'g' + 20: 2, # 'h' + 9: 3, # 'i' + 22: 3, # 'j' + 7: 3, # 'k' + 6: 3, # 'l' + 13: 3, # 'm' + 4: 3, # 'n' + 8: 3, # 'o' + 23: 2, # 'p' + 10: 3, # 'r' + 5: 3, # 's' + 3: 3, # 't' + 21: 3, # 'u' + 19: 3, # 'v' + 62: 1, # 'x' + 16: 2, # 'y' + 11: 3, # 'z' + 51: 0, # 'Ã' + 44: 0, # 'É' + 61: 0, # 'Ã' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ãœ' + 14: 3, # 'á' + 15: 3, # 'é' + 30: 2, # 'í' + 25: 3, # 'ó' + 24: 3, # 'ö' + 31: 3, # 'ú' + 29: 3, # 'ü' + 42: 2, # 'Å‘' + 56: 2, # 'ű' + }, + 5: { # 's' + 28: 0, # 'A' + 40: 0, # 'B' + 54: 0, # 'C' + 45: 0, # 'D' + 32: 0, # 'E' + 50: 0, # 'F' + 49: 0, # 'G' + 38: 0, # 'H' + 39: 0, # 'I' + 53: 0, # 'J' + 36: 0, # 'K' + 41: 0, # 'L' + 34: 0, # 'M' + 35: 0, # 'N' + 47: 0, # 'O' + 46: 0, # 'P' + 43: 0, # 'R' + 33: 0, # 'S' + 37: 0, # 'T' + 57: 0, # 'U' + 48: 0, # 'V' + 55: 0, # 'Y' + 52: 0, # 'Z' + 2: 3, # 'a' + 18: 3, # 'b' + 26: 2, # 'c' + 17: 2, # 'd' + 1: 3, # 'e' + 27: 2, # 'f' + 12: 2, # 'g' + 20: 2, # 'h' + 9: 3, # 'i' + 22: 1, # 'j' + 7: 3, # 'k' + 6: 2, # 'l' + 13: 3, # 'm' + 4: 3, # 'n' + 8: 3, # 'o' + 23: 2, # 'p' + 10: 3, # 'r' + 5: 3, # 's' + 3: 3, # 't' + 21: 3, # 'u' + 19: 2, # 'v' + 62: 0, # 'x' + 16: 1, # 'y' + 11: 3, # 'z' + 51: 0, # 'Ã' + 44: 0, # 'É' + 61: 0, # 'Ã' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ãœ' + 14: 3, # 'á' + 15: 3, # 'é' + 30: 3, # 'í' + 25: 3, # 'ó' + 24: 3, # 'ö' + 31: 3, # 'ú' + 29: 3, # 'ü' + 42: 2, # 'Å‘' + 56: 1, # 'ű' + }, + 3: { # 't' + 28: 0, # 'A' + 40: 0, # 'B' + 54: 0, # 'C' + 45: 0, # 'D' + 32: 0, # 'E' + 50: 0, # 'F' + 49: 0, # 'G' + 38: 0, # 'H' + 39: 0, # 'I' + 53: 0, # 'J' + 36: 0, # 'K' + 41: 0, # 'L' + 34: 0, # 'M' + 35: 0, # 'N' + 47: 0, # 'O' + 46: 0, # 'P' + 43: 0, # 'R' + 33: 0, # 'S' + 37: 0, # 'T' + 57: 0, # 'U' + 48: 0, # 'V' + 55: 0, # 'Y' + 52: 0, # 'Z' + 2: 3, # 'a' + 18: 3, # 'b' + 26: 2, # 'c' + 17: 1, # 'd' + 1: 3, # 'e' + 27: 2, # 'f' + 12: 1, # 'g' + 20: 3, # 'h' + 9: 3, # 'i' + 22: 3, # 'j' + 7: 3, # 'k' + 6: 3, # 'l' + 13: 2, # 'm' + 4: 3, # 'n' + 8: 3, # 'o' + 23: 1, # 'p' + 10: 3, # 'r' + 5: 3, # 's' + 3: 3, # 't' + 21: 3, # 'u' + 19: 3, # 'v' + 62: 0, # 'x' + 16: 3, # 'y' + 11: 1, # 'z' + 51: 0, # 'Ã' + 44: 0, # 'É' + 61: 0, # 'Ã' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ãœ' + 14: 3, # 'á' + 15: 3, # 'é' + 30: 2, # 'í' + 25: 3, # 'ó' + 24: 3, # 'ö' + 31: 3, # 'ú' + 29: 3, # 'ü' + 42: 3, # 'Å‘' + 56: 2, # 'ű' + }, + 21: { # 'u' + 28: 0, # 'A' + 40: 0, # 'B' + 54: 0, # 'C' + 45: 0, # 'D' + 32: 0, # 'E' + 50: 0, # 'F' + 49: 0, # 'G' + 38: 0, # 'H' + 39: 0, # 'I' + 53: 0, # 'J' + 36: 0, # 'K' + 41: 0, # 'L' + 34: 0, # 'M' + 35: 0, # 'N' + 47: 0, # 'O' + 46: 0, # 'P' + 43: 0, # 'R' + 33: 0, # 'S' + 37: 0, # 'T' + 57: 0, # 'U' + 48: 0, # 'V' + 55: 0, # 'Y' + 52: 0, # 'Z' + 2: 1, # 'a' + 18: 2, # 'b' + 26: 2, # 'c' + 17: 3, # 'd' + 1: 2, # 'e' + 27: 1, # 'f' + 12: 3, # 'g' + 20: 2, # 'h' + 9: 2, # 'i' + 22: 2, # 'j' + 7: 3, # 'k' + 6: 3, # 'l' + 13: 3, # 'm' + 4: 3, # 'n' + 8: 1, # 'o' + 23: 2, # 'p' + 10: 3, # 'r' + 5: 3, # 's' + 3: 3, # 't' + 21: 1, # 'u' + 19: 3, # 'v' + 62: 1, # 'x' + 16: 1, # 'y' + 11: 2, # 'z' + 51: 0, # 'Ã' + 44: 0, # 'É' + 61: 0, # 'Ã' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ãœ' + 14: 2, # 'á' + 15: 1, # 'é' + 30: 1, # 'í' + 25: 1, # 'ó' + 24: 0, # 'ö' + 31: 1, # 'ú' + 29: 0, # 'ü' + 42: 0, # 'Å‘' + 56: 0, # 'ű' + }, + 19: { # 'v' + 28: 0, # 'A' + 40: 0, # 'B' + 54: 0, # 'C' + 45: 0, # 'D' + 32: 0, # 'E' + 50: 0, # 'F' + 49: 0, # 'G' + 38: 0, # 'H' + 39: 0, # 'I' + 53: 0, # 'J' + 36: 0, # 'K' + 41: 0, # 'L' + 34: 0, # 'M' + 35: 0, # 'N' + 47: 0, # 'O' + 46: 0, # 'P' + 43: 0, # 'R' + 33: 0, # 'S' + 37: 0, # 'T' + 57: 0, # 'U' + 48: 0, # 'V' + 55: 0, # 'Y' + 52: 0, # 'Z' + 2: 3, # 'a' + 18: 2, # 'b' + 26: 1, # 'c' + 17: 1, # 'd' + 1: 3, # 'e' + 27: 1, # 'f' + 12: 1, # 'g' + 20: 1, # 'h' + 9: 3, # 'i' + 22: 1, # 'j' + 7: 1, # 'k' + 6: 1, # 'l' + 13: 1, # 'm' + 4: 1, # 'n' + 8: 3, # 'o' + 23: 1, # 'p' + 10: 1, # 'r' + 5: 2, # 's' + 3: 2, # 't' + 21: 2, # 'u' + 19: 2, # 'v' + 62: 0, # 'x' + 16: 1, # 'y' + 11: 1, # 'z' + 51: 0, # 'Ã' + 44: 0, # 'É' + 61: 0, # 'Ã' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ãœ' + 14: 3, # 'á' + 15: 3, # 'é' + 30: 2, # 'í' + 25: 2, # 'ó' + 24: 2, # 'ö' + 31: 1, # 'ú' + 29: 2, # 'ü' + 42: 1, # 'Å‘' + 56: 1, # 'ű' + }, + 62: { # 'x' + 28: 0, # 'A' + 40: 0, # 'B' + 54: 0, # 'C' + 45: 0, # 'D' + 32: 0, # 'E' + 50: 0, # 'F' + 49: 0, # 'G' + 38: 0, # 'H' + 39: 0, # 'I' + 53: 0, # 'J' + 36: 0, # 'K' + 41: 0, # 'L' + 34: 0, # 'M' + 35: 0, # 'N' + 47: 0, # 'O' + 46: 0, # 'P' + 43: 0, # 'R' + 33: 0, # 'S' + 37: 0, # 'T' + 57: 0, # 'U' + 48: 0, # 'V' + 55: 0, # 'Y' + 52: 0, # 'Z' + 2: 1, # 'a' + 18: 1, # 'b' + 26: 1, # 'c' + 17: 0, # 'd' + 1: 1, # 'e' + 27: 1, # 'f' + 12: 0, # 'g' + 20: 0, # 'h' + 9: 1, # 'i' + 22: 0, # 'j' + 7: 1, # 'k' + 6: 1, # 'l' + 13: 1, # 'm' + 4: 1, # 'n' + 8: 1, # 'o' + 23: 1, # 'p' + 10: 1, # 'r' + 5: 1, # 's' + 3: 1, # 't' + 21: 1, # 'u' + 19: 0, # 'v' + 62: 0, # 'x' + 16: 0, # 'y' + 11: 0, # 'z' + 51: 0, # 'Ã' + 44: 0, # 'É' + 61: 0, # 'Ã' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ãœ' + 14: 1, # 'á' + 15: 1, # 'é' + 30: 1, # 'í' + 25: 1, # 'ó' + 24: 0, # 'ö' + 31: 0, # 'ú' + 29: 0, # 'ü' + 42: 0, # 'Å‘' + 56: 0, # 'ű' + }, + 16: { # 'y' + 28: 0, # 'A' + 40: 0, # 'B' + 54: 0, # 'C' + 45: 0, # 'D' + 32: 0, # 'E' + 50: 0, # 'F' + 49: 0, # 'G' + 38: 0, # 'H' + 39: 0, # 'I' + 53: 0, # 'J' + 36: 0, # 'K' + 41: 0, # 'L' + 34: 0, # 'M' + 35: 0, # 'N' + 47: 0, # 'O' + 46: 0, # 'P' + 43: 0, # 'R' + 33: 0, # 'S' + 37: 0, # 'T' + 57: 0, # 'U' + 48: 0, # 'V' + 55: 0, # 'Y' + 52: 0, # 'Z' + 2: 3, # 'a' + 18: 2, # 'b' + 26: 1, # 'c' + 17: 1, # 'd' + 1: 3, # 'e' + 27: 2, # 'f' + 12: 2, # 'g' + 20: 2, # 'h' + 9: 3, # 'i' + 22: 2, # 'j' + 7: 2, # 'k' + 6: 2, # 'l' + 13: 2, # 'm' + 4: 3, # 'n' + 8: 3, # 'o' + 23: 2, # 'p' + 10: 2, # 'r' + 5: 3, # 's' + 3: 3, # 't' + 21: 3, # 'u' + 19: 3, # 'v' + 62: 0, # 'x' + 16: 0, # 'y' + 11: 2, # 'z' + 51: 0, # 'Ã' + 44: 0, # 'É' + 61: 0, # 'Ã' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ãœ' + 14: 3, # 'á' + 15: 3, # 'é' + 30: 2, # 'í' + 25: 2, # 'ó' + 24: 3, # 'ö' + 31: 2, # 'ú' + 29: 2, # 'ü' + 42: 1, # 'Å‘' + 56: 2, # 'ű' + }, + 11: { # 'z' + 28: 0, # 'A' + 40: 0, # 'B' + 54: 0, # 'C' + 45: 0, # 'D' + 32: 0, # 'E' + 50: 0, # 'F' + 49: 0, # 'G' + 38: 0, # 'H' + 39: 0, # 'I' + 53: 0, # 'J' + 36: 0, # 'K' + 41: 0, # 'L' + 34: 0, # 'M' + 35: 0, # 'N' + 47: 0, # 'O' + 46: 0, # 'P' + 43: 0, # 'R' + 33: 0, # 'S' + 37: 0, # 'T' + 57: 0, # 'U' + 48: 0, # 'V' + 55: 0, # 'Y' + 52: 0, # 'Z' + 2: 3, # 'a' + 18: 2, # 'b' + 26: 1, # 'c' + 17: 3, # 'd' + 1: 3, # 'e' + 27: 1, # 'f' + 12: 2, # 'g' + 20: 2, # 'h' + 9: 3, # 'i' + 22: 1, # 'j' + 7: 3, # 'k' + 6: 2, # 'l' + 13: 3, # 'm' + 4: 3, # 'n' + 8: 3, # 'o' + 23: 1, # 'p' + 10: 2, # 'r' + 5: 3, # 's' + 3: 3, # 't' + 21: 3, # 'u' + 19: 2, # 'v' + 62: 0, # 'x' + 16: 1, # 'y' + 11: 3, # 'z' + 51: 0, # 'Ã' + 44: 0, # 'É' + 61: 0, # 'Ã' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ãœ' + 14: 3, # 'á' + 15: 3, # 'é' + 30: 3, # 'í' + 25: 3, # 'ó' + 24: 3, # 'ö' + 31: 2, # 'ú' + 29: 3, # 'ü' + 42: 2, # 'Å‘' + 56: 1, # 'ű' + }, + 51: { # 'Ã' + 28: 0, # 'A' + 40: 1, # 'B' + 54: 1, # 'C' + 45: 1, # 'D' + 32: 0, # 'E' + 50: 1, # 'F' + 49: 2, # 'G' + 38: 1, # 'H' + 39: 1, # 'I' + 53: 1, # 'J' + 36: 1, # 'K' + 41: 2, # 'L' + 34: 1, # 'M' + 35: 2, # 'N' + 47: 0, # 'O' + 46: 1, # 'P' + 43: 2, # 'R' + 33: 2, # 'S' + 37: 1, # 'T' + 57: 0, # 'U' + 48: 1, # 'V' + 55: 0, # 'Y' + 52: 1, # 'Z' + 2: 0, # 'a' + 18: 1, # 'b' + 26: 1, # 'c' + 17: 1, # 'd' + 1: 0, # 'e' + 27: 0, # 'f' + 12: 1, # 'g' + 20: 1, # 'h' + 9: 0, # 'i' + 22: 1, # 'j' + 7: 1, # 'k' + 6: 2, # 'l' + 13: 2, # 'm' + 4: 0, # 'n' + 8: 0, # 'o' + 23: 1, # 'p' + 10: 1, # 'r' + 5: 1, # 's' + 3: 1, # 't' + 21: 0, # 'u' + 19: 0, # 'v' + 62: 0, # 'x' + 16: 0, # 'y' + 11: 1, # 'z' + 51: 0, # 'Ã' + 44: 0, # 'É' + 61: 1, # 'Ã' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ãœ' + 14: 0, # 'á' + 15: 0, # 'é' + 30: 0, # 'í' + 25: 0, # 'ó' + 24: 0, # 'ö' + 31: 0, # 'ú' + 29: 0, # 'ü' + 42: 0, # 'Å‘' + 56: 0, # 'ű' + }, + 44: { # 'É' + 28: 0, # 'A' + 40: 1, # 'B' + 54: 1, # 'C' + 45: 1, # 'D' + 32: 1, # 'E' + 50: 0, # 'F' + 49: 2, # 'G' + 38: 1, # 'H' + 39: 1, # 'I' + 53: 1, # 'J' + 36: 1, # 'K' + 41: 2, # 'L' + 34: 1, # 'M' + 35: 2, # 'N' + 47: 0, # 'O' + 46: 1, # 'P' + 43: 2, # 'R' + 33: 2, # 'S' + 37: 2, # 'T' + 57: 0, # 'U' + 48: 1, # 'V' + 55: 0, # 'Y' + 52: 1, # 'Z' + 2: 0, # 'a' + 18: 1, # 'b' + 26: 1, # 'c' + 17: 1, # 'd' + 1: 0, # 'e' + 27: 0, # 'f' + 12: 1, # 'g' + 20: 1, # 'h' + 9: 0, # 'i' + 22: 1, # 'j' + 7: 1, # 'k' + 6: 2, # 'l' + 13: 1, # 'm' + 4: 2, # 'n' + 8: 0, # 'o' + 23: 1, # 'p' + 10: 2, # 'r' + 5: 3, # 's' + 3: 1, # 't' + 21: 0, # 'u' + 19: 1, # 'v' + 62: 0, # 'x' + 16: 0, # 'y' + 11: 0, # 'z' + 51: 0, # 'Ã' + 44: 1, # 'É' + 61: 0, # 'Ã' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ãœ' + 14: 0, # 'á' + 15: 0, # 'é' + 30: 0, # 'í' + 25: 0, # 'ó' + 24: 0, # 'ö' + 31: 0, # 'ú' + 29: 0, # 'ü' + 42: 0, # 'Å‘' + 56: 0, # 'ű' + }, + 61: { # 'Ã' + 28: 0, # 'A' + 40: 1, # 'B' + 54: 1, # 'C' + 45: 1, # 'D' + 32: 0, # 'E' + 50: 1, # 'F' + 49: 1, # 'G' + 38: 0, # 'H' + 39: 0, # 'I' + 53: 1, # 'J' + 36: 0, # 'K' + 41: 1, # 'L' + 34: 1, # 'M' + 35: 1, # 'N' + 47: 0, # 'O' + 46: 1, # 'P' + 43: 1, # 'R' + 33: 1, # 'S' + 37: 1, # 'T' + 57: 0, # 'U' + 48: 1, # 'V' + 55: 0, # 'Y' + 52: 1, # 'Z' + 2: 0, # 'a' + 18: 0, # 'b' + 26: 0, # 'c' + 17: 0, # 'd' + 1: 0, # 'e' + 27: 0, # 'f' + 12: 2, # 'g' + 20: 0, # 'h' + 9: 0, # 'i' + 22: 0, # 'j' + 7: 0, # 'k' + 6: 0, # 'l' + 13: 1, # 'm' + 4: 0, # 'n' + 8: 0, # 'o' + 23: 0, # 'p' + 10: 1, # 'r' + 5: 0, # 's' + 3: 1, # 't' + 21: 0, # 'u' + 19: 0, # 'v' + 62: 0, # 'x' + 16: 0, # 'y' + 11: 1, # 'z' + 51: 0, # 'Ã' + 44: 0, # 'É' + 61: 0, # 'Ã' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ãœ' + 14: 0, # 'á' + 15: 0, # 'é' + 30: 0, # 'í' + 25: 0, # 'ó' + 24: 0, # 'ö' + 31: 0, # 'ú' + 29: 0, # 'ü' + 42: 0, # 'Å‘' + 56: 0, # 'ű' + }, + 58: { # 'Ó' + 28: 1, # 'A' + 40: 1, # 'B' + 54: 1, # 'C' + 45: 1, # 'D' + 32: 0, # 'E' + 50: 1, # 'F' + 49: 1, # 'G' + 38: 1, # 'H' + 39: 1, # 'I' + 53: 1, # 'J' + 36: 1, # 'K' + 41: 2, # 'L' + 34: 1, # 'M' + 35: 1, # 'N' + 47: 0, # 'O' + 46: 1, # 'P' + 43: 1, # 'R' + 33: 1, # 'S' + 37: 1, # 'T' + 57: 0, # 'U' + 48: 1, # 'V' + 55: 0, # 'Y' + 52: 1, # 'Z' + 2: 0, # 'a' + 18: 1, # 'b' + 26: 1, # 'c' + 17: 1, # 'd' + 1: 0, # 'e' + 27: 0, # 'f' + 12: 0, # 'g' + 20: 2, # 'h' + 9: 0, # 'i' + 22: 0, # 'j' + 7: 1, # 'k' + 6: 1, # 'l' + 13: 0, # 'm' + 4: 1, # 'n' + 8: 0, # 'o' + 23: 1, # 'p' + 10: 1, # 'r' + 5: 1, # 's' + 3: 0, # 't' + 21: 0, # 'u' + 19: 1, # 'v' + 62: 0, # 'x' + 16: 0, # 'y' + 11: 1, # 'z' + 51: 0, # 'Ã' + 44: 1, # 'É' + 61: 0, # 'Ã' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ãœ' + 14: 0, # 'á' + 15: 0, # 'é' + 30: 0, # 'í' + 25: 0, # 'ó' + 24: 0, # 'ö' + 31: 0, # 'ú' + 29: 0, # 'ü' + 42: 0, # 'Å‘' + 56: 0, # 'ű' + }, + 59: { # 'Ö' + 28: 0, # 'A' + 40: 1, # 'B' + 54: 1, # 'C' + 45: 1, # 'D' + 32: 0, # 'E' + 50: 0, # 'F' + 49: 1, # 'G' + 38: 1, # 'H' + 39: 0, # 'I' + 53: 1, # 'J' + 36: 1, # 'K' + 41: 1, # 'L' + 34: 1, # 'M' + 35: 1, # 'N' + 47: 0, # 'O' + 46: 1, # 'P' + 43: 1, # 'R' + 33: 1, # 'S' + 37: 1, # 'T' + 57: 0, # 'U' + 48: 1, # 'V' + 55: 0, # 'Y' + 52: 1, # 'Z' + 2: 0, # 'a' + 18: 0, # 'b' + 26: 1, # 'c' + 17: 1, # 'd' + 1: 0, # 'e' + 27: 0, # 'f' + 12: 0, # 'g' + 20: 0, # 'h' + 9: 0, # 'i' + 22: 0, # 'j' + 7: 1, # 'k' + 6: 1, # 'l' + 13: 1, # 'm' + 4: 1, # 'n' + 8: 0, # 'o' + 23: 0, # 'p' + 10: 2, # 'r' + 5: 1, # 's' + 3: 1, # 't' + 21: 0, # 'u' + 19: 1, # 'v' + 62: 0, # 'x' + 16: 0, # 'y' + 11: 1, # 'z' + 51: 0, # 'Ã' + 44: 0, # 'É' + 61: 0, # 'Ã' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ãœ' + 14: 0, # 'á' + 15: 0, # 'é' + 30: 0, # 'í' + 25: 0, # 'ó' + 24: 0, # 'ö' + 31: 0, # 'ú' + 29: 0, # 'ü' + 42: 0, # 'Å‘' + 56: 0, # 'ű' + }, + 60: { # 'Ú' + 28: 0, # 'A' + 40: 1, # 'B' + 54: 1, # 'C' + 45: 1, # 'D' + 32: 0, # 'E' + 50: 1, # 'F' + 49: 1, # 'G' + 38: 0, # 'H' + 39: 0, # 'I' + 53: 1, # 'J' + 36: 1, # 'K' + 41: 1, # 'L' + 34: 1, # 'M' + 35: 1, # 'N' + 47: 0, # 'O' + 46: 0, # 'P' + 43: 1, # 'R' + 33: 1, # 'S' + 37: 1, # 'T' + 57: 0, # 'U' + 48: 1, # 'V' + 55: 0, # 'Y' + 52: 1, # 'Z' + 2: 0, # 'a' + 18: 0, # 'b' + 26: 0, # 'c' + 17: 0, # 'd' + 1: 0, # 'e' + 27: 0, # 'f' + 12: 2, # 'g' + 20: 0, # 'h' + 9: 0, # 'i' + 22: 2, # 'j' + 7: 0, # 'k' + 6: 0, # 'l' + 13: 0, # 'm' + 4: 1, # 'n' + 8: 0, # 'o' + 23: 0, # 'p' + 10: 1, # 'r' + 5: 1, # 's' + 3: 1, # 't' + 21: 0, # 'u' + 19: 0, # 'v' + 62: 0, # 'x' + 16: 0, # 'y' + 11: 0, # 'z' + 51: 0, # 'Ã' + 44: 0, # 'É' + 61: 0, # 'Ã' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ãœ' + 14: 0, # 'á' + 15: 0, # 'é' + 30: 0, # 'í' + 25: 0, # 'ó' + 24: 0, # 'ö' + 31: 0, # 'ú' + 29: 0, # 'ü' + 42: 0, # 'Å‘' + 56: 0, # 'ű' + }, + 63: { # 'Ãœ' + 28: 0, # 'A' + 40: 1, # 'B' + 54: 0, # 'C' + 45: 1, # 'D' + 32: 0, # 'E' + 50: 0, # 'F' + 49: 1, # 'G' + 38: 1, # 'H' + 39: 0, # 'I' + 53: 1, # 'J' + 36: 1, # 'K' + 41: 1, # 'L' + 34: 1, # 'M' + 35: 1, # 'N' + 47: 0, # 'O' + 46: 0, # 'P' + 43: 1, # 'R' + 33: 1, # 'S' + 37: 1, # 'T' + 57: 0, # 'U' + 48: 1, # 'V' + 55: 0, # 'Y' + 52: 1, # 'Z' + 2: 0, # 'a' + 18: 1, # 'b' + 26: 0, # 'c' + 17: 1, # 'd' + 1: 0, # 'e' + 27: 0, # 'f' + 12: 1, # 'g' + 20: 0, # 'h' + 9: 0, # 'i' + 22: 0, # 'j' + 7: 0, # 'k' + 6: 1, # 'l' + 13: 0, # 'm' + 4: 1, # 'n' + 8: 0, # 'o' + 23: 0, # 'p' + 10: 1, # 'r' + 5: 1, # 's' + 3: 1, # 't' + 21: 0, # 'u' + 19: 1, # 'v' + 62: 0, # 'x' + 16: 0, # 'y' + 11: 1, # 'z' + 51: 0, # 'Ã' + 44: 0, # 'É' + 61: 0, # 'Ã' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ãœ' + 14: 0, # 'á' + 15: 0, # 'é' + 30: 0, # 'í' + 25: 0, # 'ó' + 24: 0, # 'ö' + 31: 0, # 'ú' + 29: 0, # 'ü' + 42: 0, # 'Å‘' + 56: 0, # 'ű' + }, + 14: { # 'á' + 28: 0, # 'A' + 40: 0, # 'B' + 54: 0, # 'C' + 45: 0, # 'D' + 32: 0, # 'E' + 50: 0, # 'F' + 49: 0, # 'G' + 38: 0, # 'H' + 39: 0, # 'I' + 53: 0, # 'J' + 36: 0, # 'K' + 41: 0, # 'L' + 34: 0, # 'M' + 35: 0, # 'N' + 47: 0, # 'O' + 46: 0, # 'P' + 43: 0, # 'R' + 33: 0, # 'S' + 37: 0, # 'T' + 57: 0, # 'U' + 48: 0, # 'V' + 55: 0, # 'Y' + 52: 0, # 'Z' + 2: 1, # 'a' + 18: 3, # 'b' + 26: 3, # 'c' + 17: 3, # 'd' + 1: 1, # 'e' + 27: 2, # 'f' + 12: 3, # 'g' + 20: 2, # 'h' + 9: 2, # 'i' + 22: 3, # 'j' + 7: 3, # 'k' + 6: 3, # 'l' + 13: 3, # 'm' + 4: 3, # 'n' + 8: 1, # 'o' + 23: 2, # 'p' + 10: 3, # 'r' + 5: 3, # 's' + 3: 3, # 't' + 21: 2, # 'u' + 19: 3, # 'v' + 62: 0, # 'x' + 16: 1, # 'y' + 11: 3, # 'z' + 51: 0, # 'Ã' + 44: 0, # 'É' + 61: 0, # 'Ã' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ãœ' + 14: 1, # 'á' + 15: 2, # 'é' + 30: 1, # 'í' + 25: 0, # 'ó' + 24: 1, # 'ö' + 31: 0, # 'ú' + 29: 1, # 'ü' + 42: 0, # 'Å‘' + 56: 0, # 'ű' + }, + 15: { # 'é' + 28: 0, # 'A' + 40: 0, # 'B' + 54: 0, # 'C' + 45: 0, # 'D' + 32: 0, # 'E' + 50: 0, # 'F' + 49: 0, # 'G' + 38: 0, # 'H' + 39: 0, # 'I' + 53: 0, # 'J' + 36: 0, # 'K' + 41: 0, # 'L' + 34: 0, # 'M' + 35: 0, # 'N' + 47: 0, # 'O' + 46: 0, # 'P' + 43: 0, # 'R' + 33: 0, # 'S' + 37: 0, # 'T' + 57: 0, # 'U' + 48: 0, # 'V' + 55: 0, # 'Y' + 52: 0, # 'Z' + 2: 1, # 'a' + 18: 3, # 'b' + 26: 2, # 'c' + 17: 3, # 'd' + 1: 1, # 'e' + 27: 1, # 'f' + 12: 3, # 'g' + 20: 3, # 'h' + 9: 2, # 'i' + 22: 2, # 'j' + 7: 3, # 'k' + 6: 3, # 'l' + 13: 3, # 'm' + 4: 3, # 'n' + 8: 1, # 'o' + 23: 3, # 'p' + 10: 3, # 'r' + 5: 3, # 's' + 3: 3, # 't' + 21: 0, # 'u' + 19: 3, # 'v' + 62: 0, # 'x' + 16: 0, # 'y' + 11: 3, # 'z' + 51: 0, # 'Ã' + 44: 0, # 'É' + 61: 0, # 'Ã' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ãœ' + 14: 1, # 'á' + 15: 1, # 'é' + 30: 0, # 'í' + 25: 0, # 'ó' + 24: 0, # 'ö' + 31: 0, # 'ú' + 29: 1, # 'ü' + 42: 0, # 'Å‘' + 56: 0, # 'ű' + }, + 30: { # 'í' + 28: 0, # 'A' + 40: 0, # 'B' + 54: 0, # 'C' + 45: 0, # 'D' + 32: 0, # 'E' + 50: 0, # 'F' + 49: 0, # 'G' + 38: 0, # 'H' + 39: 0, # 'I' + 53: 0, # 'J' + 36: 0, # 'K' + 41: 0, # 'L' + 34: 0, # 'M' + 35: 0, # 'N' + 47: 0, # 'O' + 46: 0, # 'P' + 43: 0, # 'R' + 33: 0, # 'S' + 37: 0, # 'T' + 57: 0, # 'U' + 48: 0, # 'V' + 55: 0, # 'Y' + 52: 0, # 'Z' + 2: 0, # 'a' + 18: 1, # 'b' + 26: 2, # 'c' + 17: 1, # 'd' + 1: 0, # 'e' + 27: 1, # 'f' + 12: 3, # 'g' + 20: 0, # 'h' + 9: 0, # 'i' + 22: 1, # 'j' + 7: 1, # 'k' + 6: 2, # 'l' + 13: 2, # 'm' + 4: 3, # 'n' + 8: 0, # 'o' + 23: 1, # 'p' + 10: 3, # 'r' + 5: 2, # 's' + 3: 3, # 't' + 21: 0, # 'u' + 19: 3, # 'v' + 62: 0, # 'x' + 16: 0, # 'y' + 11: 2, # 'z' + 51: 0, # 'Ã' + 44: 0, # 'É' + 61: 0, # 'Ã' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ãœ' + 14: 0, # 'á' + 15: 0, # 'é' + 30: 0, # 'í' + 25: 0, # 'ó' + 24: 0, # 'ö' + 31: 0, # 'ú' + 29: 0, # 'ü' + 42: 0, # 'Å‘' + 56: 0, # 'ű' + }, + 25: { # 'ó' + 28: 0, # 'A' + 40: 0, # 'B' + 54: 0, # 'C' + 45: 0, # 'D' + 32: 0, # 'E' + 50: 0, # 'F' + 49: 0, # 'G' + 38: 0, # 'H' + 39: 0, # 'I' + 53: 0, # 'J' + 36: 0, # 'K' + 41: 0, # 'L' + 34: 0, # 'M' + 35: 0, # 'N' + 47: 0, # 'O' + 46: 0, # 'P' + 43: 0, # 'R' + 33: 0, # 'S' + 37: 0, # 'T' + 57: 0, # 'U' + 48: 0, # 'V' + 55: 0, # 'Y' + 52: 0, # 'Z' + 2: 2, # 'a' + 18: 3, # 'b' + 26: 2, # 'c' + 17: 3, # 'd' + 1: 1, # 'e' + 27: 2, # 'f' + 12: 2, # 'g' + 20: 2, # 'h' + 9: 2, # 'i' + 22: 2, # 'j' + 7: 3, # 'k' + 6: 3, # 'l' + 13: 2, # 'm' + 4: 3, # 'n' + 8: 1, # 'o' + 23: 2, # 'p' + 10: 3, # 'r' + 5: 3, # 's' + 3: 3, # 't' + 21: 1, # 'u' + 19: 2, # 'v' + 62: 0, # 'x' + 16: 0, # 'y' + 11: 3, # 'z' + 51: 0, # 'Ã' + 44: 0, # 'É' + 61: 0, # 'Ã' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ãœ' + 14: 1, # 'á' + 15: 1, # 'é' + 30: 1, # 'í' + 25: 0, # 'ó' + 24: 1, # 'ö' + 31: 1, # 'ú' + 29: 1, # 'ü' + 42: 0, # 'Å‘' + 56: 0, # 'ű' + }, + 24: { # 'ö' + 28: 0, # 'A' + 40: 0, # 'B' + 54: 0, # 'C' + 45: 0, # 'D' + 32: 0, # 'E' + 50: 0, # 'F' + 49: 0, # 'G' + 38: 0, # 'H' + 39: 0, # 'I' + 53: 0, # 'J' + 36: 0, # 'K' + 41: 0, # 'L' + 34: 0, # 'M' + 35: 0, # 'N' + 47: 0, # 'O' + 46: 0, # 'P' + 43: 0, # 'R' + 33: 0, # 'S' + 37: 0, # 'T' + 57: 0, # 'U' + 48: 0, # 'V' + 55: 0, # 'Y' + 52: 0, # 'Z' + 2: 0, # 'a' + 18: 3, # 'b' + 26: 1, # 'c' + 17: 2, # 'd' + 1: 0, # 'e' + 27: 1, # 'f' + 12: 2, # 'g' + 20: 1, # 'h' + 9: 0, # 'i' + 22: 1, # 'j' + 7: 3, # 'k' + 6: 3, # 'l' + 13: 3, # 'm' + 4: 3, # 'n' + 8: 0, # 'o' + 23: 2, # 'p' + 10: 3, # 'r' + 5: 3, # 's' + 3: 3, # 't' + 21: 0, # 'u' + 19: 3, # 'v' + 62: 0, # 'x' + 16: 0, # 'y' + 11: 3, # 'z' + 51: 0, # 'Ã' + 44: 0, # 'É' + 61: 0, # 'Ã' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ãœ' + 14: 0, # 'á' + 15: 0, # 'é' + 30: 0, # 'í' + 25: 0, # 'ó' + 24: 0, # 'ö' + 31: 0, # 'ú' + 29: 0, # 'ü' + 42: 0, # 'Å‘' + 56: 0, # 'ű' + }, + 31: { # 'ú' + 28: 0, # 'A' + 40: 0, # 'B' + 54: 0, # 'C' + 45: 0, # 'D' + 32: 0, # 'E' + 50: 0, # 'F' + 49: 0, # 'G' + 38: 0, # 'H' + 39: 0, # 'I' + 53: 0, # 'J' + 36: 0, # 'K' + 41: 0, # 'L' + 34: 0, # 'M' + 35: 0, # 'N' + 47: 0, # 'O' + 46: 0, # 'P' + 43: 0, # 'R' + 33: 0, # 'S' + 37: 0, # 'T' + 57: 0, # 'U' + 48: 0, # 'V' + 55: 0, # 'Y' + 52: 0, # 'Z' + 2: 1, # 'a' + 18: 1, # 'b' + 26: 2, # 'c' + 17: 1, # 'd' + 1: 1, # 'e' + 27: 2, # 'f' + 12: 3, # 'g' + 20: 1, # 'h' + 9: 1, # 'i' + 22: 3, # 'j' + 7: 1, # 'k' + 6: 3, # 'l' + 13: 1, # 'm' + 4: 2, # 'n' + 8: 0, # 'o' + 23: 1, # 'p' + 10: 3, # 'r' + 5: 3, # 's' + 3: 2, # 't' + 21: 1, # 'u' + 19: 1, # 'v' + 62: 0, # 'x' + 16: 0, # 'y' + 11: 2, # 'z' + 51: 0, # 'Ã' + 44: 0, # 'É' + 61: 0, # 'Ã' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ãœ' + 14: 1, # 'á' + 15: 1, # 'é' + 30: 0, # 'í' + 25: 0, # 'ó' + 24: 0, # 'ö' + 31: 0, # 'ú' + 29: 0, # 'ü' + 42: 0, # 'Å‘' + 56: 0, # 'ű' + }, + 29: { # 'ü' + 28: 0, # 'A' + 40: 0, # 'B' + 54: 0, # 'C' + 45: 0, # 'D' + 32: 0, # 'E' + 50: 0, # 'F' + 49: 0, # 'G' + 38: 0, # 'H' + 39: 0, # 'I' + 53: 0, # 'J' + 36: 0, # 'K' + 41: 0, # 'L' + 34: 0, # 'M' + 35: 0, # 'N' + 47: 0, # 'O' + 46: 0, # 'P' + 43: 0, # 'R' + 33: 0, # 'S' + 37: 0, # 'T' + 57: 0, # 'U' + 48: 0, # 'V' + 55: 0, # 'Y' + 52: 0, # 'Z' + 2: 1, # 'a' + 18: 1, # 'b' + 26: 1, # 'c' + 17: 2, # 'd' + 1: 1, # 'e' + 27: 1, # 'f' + 12: 3, # 'g' + 20: 2, # 'h' + 9: 1, # 'i' + 22: 1, # 'j' + 7: 3, # 'k' + 6: 3, # 'l' + 13: 1, # 'm' + 4: 3, # 'n' + 8: 0, # 'o' + 23: 1, # 'p' + 10: 2, # 'r' + 5: 2, # 's' + 3: 2, # 't' + 21: 0, # 'u' + 19: 2, # 'v' + 62: 0, # 'x' + 16: 0, # 'y' + 11: 2, # 'z' + 51: 0, # 'Ã' + 44: 0, # 'É' + 61: 0, # 'Ã' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ãœ' + 14: 0, # 'á' + 15: 1, # 'é' + 30: 0, # 'í' + 25: 0, # 'ó' + 24: 0, # 'ö' + 31: 0, # 'ú' + 29: 0, # 'ü' + 42: 0, # 'Å‘' + 56: 0, # 'ű' + }, + 42: { # 'Å‘' + 28: 0, # 'A' + 40: 0, # 'B' + 54: 0, # 'C' + 45: 0, # 'D' + 32: 0, # 'E' + 50: 0, # 'F' + 49: 0, # 'G' + 38: 0, # 'H' + 39: 0, # 'I' + 53: 0, # 'J' + 36: 0, # 'K' + 41: 0, # 'L' + 34: 0, # 'M' + 35: 0, # 'N' + 47: 0, # 'O' + 46: 0, # 'P' + 43: 0, # 'R' + 33: 0, # 'S' + 37: 0, # 'T' + 57: 0, # 'U' + 48: 0, # 'V' + 55: 0, # 'Y' + 52: 0, # 'Z' + 2: 1, # 'a' + 18: 2, # 'b' + 26: 1, # 'c' + 17: 2, # 'd' + 1: 1, # 'e' + 27: 1, # 'f' + 12: 1, # 'g' + 20: 1, # 'h' + 9: 1, # 'i' + 22: 1, # 'j' + 7: 2, # 'k' + 6: 3, # 'l' + 13: 1, # 'm' + 4: 2, # 'n' + 8: 1, # 'o' + 23: 1, # 'p' + 10: 2, # 'r' + 5: 2, # 's' + 3: 2, # 't' + 21: 1, # 'u' + 19: 1, # 'v' + 62: 0, # 'x' + 16: 0, # 'y' + 11: 2, # 'z' + 51: 0, # 'Ã' + 44: 0, # 'É' + 61: 0, # 'Ã' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ãœ' + 14: 0, # 'á' + 15: 1, # 'é' + 30: 1, # 'í' + 25: 0, # 'ó' + 24: 0, # 'ö' + 31: 0, # 'ú' + 29: 1, # 'ü' + 42: 0, # 'Å‘' + 56: 0, # 'ű' + }, + 56: { # 'ű' + 28: 0, # 'A' + 40: 0, # 'B' + 54: 0, # 'C' + 45: 0, # 'D' + 32: 0, # 'E' + 50: 0, # 'F' + 49: 0, # 'G' + 38: 0, # 'H' + 39: 0, # 'I' + 53: 0, # 'J' + 36: 0, # 'K' + 41: 0, # 'L' + 34: 0, # 'M' + 35: 0, # 'N' + 47: 0, # 'O' + 46: 0, # 'P' + 43: 0, # 'R' + 33: 0, # 'S' + 37: 0, # 'T' + 57: 0, # 'U' + 48: 0, # 'V' + 55: 0, # 'Y' + 52: 0, # 'Z' + 2: 1, # 'a' + 18: 1, # 'b' + 26: 0, # 'c' + 17: 1, # 'd' + 1: 1, # 'e' + 27: 1, # 'f' + 12: 1, # 'g' + 20: 1, # 'h' + 9: 1, # 'i' + 22: 1, # 'j' + 7: 1, # 'k' + 6: 1, # 'l' + 13: 0, # 'm' + 4: 2, # 'n' + 8: 0, # 'o' + 23: 0, # 'p' + 10: 1, # 'r' + 5: 1, # 's' + 3: 1, # 't' + 21: 0, # 'u' + 19: 1, # 'v' + 62: 0, # 'x' + 16: 0, # 'y' + 11: 2, # 'z' + 51: 0, # 'Ã' + 44: 0, # 'É' + 61: 0, # 'Ã' + 58: 0, # 'Ó' + 59: 0, # 'Ö' + 60: 0, # 'Ú' + 63: 0, # 'Ãœ' + 14: 0, # 'á' + 15: 0, # 'é' + 30: 0, # 'í' + 25: 0, # 'ó' + 24: 0, # 'ö' + 31: 0, # 'ú' + 29: 0, # 'ü' + 42: 0, # 'Å‘' + 56: 0, # 'ű' + }, +} + +# 255: Undefined characters that did not exist in training text +# 254: Carriage/Return +# 253: symbol (punctuation) that does not belong to word +# 252: 0 - 9 +# 251: Control characters + +# Character Mapping Table(s): +WINDOWS_1250_HUNGARIAN_CHAR_TO_ORDER = { + 0: 255, # '\x00' + 1: 255, # '\x01' + 2: 255, # '\x02' + 3: 255, # '\x03' + 4: 255, # '\x04' + 5: 255, # '\x05' + 6: 255, # '\x06' + 7: 255, # '\x07' + 8: 255, # '\x08' + 9: 255, # '\t' + 10: 254, # '\n' + 11: 255, # '\x0b' + 12: 255, # '\x0c' + 13: 254, # '\r' + 14: 255, # '\x0e' + 15: 255, # '\x0f' + 16: 255, # '\x10' + 17: 255, # '\x11' + 18: 255, # '\x12' + 19: 255, # '\x13' + 20: 255, # '\x14' + 21: 255, # '\x15' + 22: 255, # '\x16' + 23: 255, # '\x17' + 24: 255, # '\x18' + 25: 255, # '\x19' + 26: 255, # '\x1a' + 27: 255, # '\x1b' + 28: 255, # '\x1c' + 29: 255, # '\x1d' + 30: 255, # '\x1e' + 31: 255, # '\x1f' + 32: 253, # ' ' + 33: 253, # '!' + 34: 253, # '"' + 35: 253, # '#' + 36: 253, # '$' + 37: 253, # '%' + 38: 253, # '&' + 39: 253, # "'" + 40: 253, # '(' + 41: 253, # ')' + 42: 253, # '*' + 43: 253, # '+' + 44: 253, # ',' + 45: 253, # '-' + 46: 253, # '.' + 47: 253, # '/' + 48: 252, # '0' + 49: 252, # '1' + 50: 252, # '2' + 51: 252, # '3' + 52: 252, # '4' + 53: 252, # '5' + 54: 252, # '6' + 55: 252, # '7' + 56: 252, # '8' + 57: 252, # '9' + 58: 253, # ':' + 59: 253, # ';' + 60: 253, # '<' + 61: 253, # '=' + 62: 253, # '>' + 63: 253, # '?' + 64: 253, # '@' + 65: 28, # 'A' + 66: 40, # 'B' + 67: 54, # 'C' + 68: 45, # 'D' + 69: 32, # 'E' + 70: 50, # 'F' + 71: 49, # 'G' + 72: 38, # 'H' + 73: 39, # 'I' + 74: 53, # 'J' + 75: 36, # 'K' + 76: 41, # 'L' + 77: 34, # 'M' + 78: 35, # 'N' + 79: 47, # 'O' + 80: 46, # 'P' + 81: 72, # 'Q' + 82: 43, # 'R' + 83: 33, # 'S' + 84: 37, # 'T' + 85: 57, # 'U' + 86: 48, # 'V' + 87: 64, # 'W' + 88: 68, # 'X' + 89: 55, # 'Y' + 90: 52, # 'Z' + 91: 253, # '[' + 92: 253, # '\\' + 93: 253, # ']' + 94: 253, # '^' + 95: 253, # '_' + 96: 253, # '`' + 97: 2, # 'a' + 98: 18, # 'b' + 99: 26, # 'c' + 100: 17, # 'd' + 101: 1, # 'e' + 102: 27, # 'f' + 103: 12, # 'g' + 104: 20, # 'h' + 105: 9, # 'i' + 106: 22, # 'j' + 107: 7, # 'k' + 108: 6, # 'l' + 109: 13, # 'm' + 110: 4, # 'n' + 111: 8, # 'o' + 112: 23, # 'p' + 113: 67, # 'q' + 114: 10, # 'r' + 115: 5, # 's' + 116: 3, # 't' + 117: 21, # 'u' + 118: 19, # 'v' + 119: 65, # 'w' + 120: 62, # 'x' + 121: 16, # 'y' + 122: 11, # 'z' + 123: 253, # '{' + 124: 253, # '|' + 125: 253, # '}' + 126: 253, # '~' + 127: 253, # '\x7f' + 128: 161, # '€' + 129: 162, # None + 130: 163, # '‚' + 131: 164, # None + 132: 165, # '„' + 133: 166, # '…' + 134: 167, # '†' + 135: 168, # '‡' + 136: 169, # None + 137: 170, # '‰' + 138: 171, # 'Å ' + 139: 172, # '‹' + 140: 173, # 'Åš' + 141: 174, # 'Ť' + 142: 175, # 'Ž' + 143: 176, # 'Ź' + 144: 177, # None + 145: 178, # '‘' + 146: 179, # '’' + 147: 180, # '“' + 148: 78, # 'â€' + 149: 181, # '•' + 150: 69, # '–' + 151: 182, # '—' + 152: 183, # None + 153: 184, # 'â„¢' + 154: 185, # 'Å¡' + 155: 186, # '›' + 156: 187, # 'Å›' + 157: 188, # 'Å¥' + 158: 189, # 'ž' + 159: 190, # 'ź' + 160: 191, # '\xa0' + 161: 192, # 'ˇ' + 162: 193, # '˘' + 163: 194, # 'Å' + 164: 195, # '¤' + 165: 196, # 'Ä„' + 166: 197, # '¦' + 167: 76, # '§' + 168: 198, # '¨' + 169: 199, # '©' + 170: 200, # 'Åž' + 171: 201, # '«' + 172: 202, # '¬' + 173: 203, # '\xad' + 174: 204, # '®' + 175: 205, # 'Å»' + 176: 81, # '°' + 177: 206, # '±' + 178: 207, # 'Ë›' + 179: 208, # 'Å‚' + 180: 209, # '´' + 181: 210, # 'µ' + 182: 211, # '¶' + 183: 212, # '·' + 184: 213, # '¸' + 185: 214, # 'Ä…' + 186: 215, # 'ÅŸ' + 187: 216, # '»' + 188: 217, # 'Ľ' + 189: 218, # 'Ë' + 190: 219, # 'ľ' + 191: 220, # 'ż' + 192: 221, # 'Å”' + 193: 51, # 'Ã' + 194: 83, # 'Â' + 195: 222, # 'Ä‚' + 196: 80, # 'Ä' + 197: 223, # 'Ĺ' + 198: 224, # 'Ć' + 199: 225, # 'Ç' + 200: 226, # 'ÄŒ' + 201: 44, # 'É' + 202: 227, # 'Ę' + 203: 228, # 'Ë' + 204: 229, # 'Äš' + 205: 61, # 'Ã' + 206: 230, # 'ÃŽ' + 207: 231, # 'ÄŽ' + 208: 232, # 'Ä' + 209: 233, # 'Ń' + 210: 234, # 'Ň' + 211: 58, # 'Ó' + 212: 235, # 'Ô' + 213: 66, # 'Å' + 214: 59, # 'Ö' + 215: 236, # '×' + 216: 237, # 'Ř' + 217: 238, # 'Å®' + 218: 60, # 'Ú' + 219: 70, # 'Å°' + 220: 63, # 'Ãœ' + 221: 239, # 'Ã' + 222: 240, # 'Å¢' + 223: 241, # 'ß' + 224: 84, # 'Å•' + 225: 14, # 'á' + 226: 75, # 'â' + 227: 242, # 'ă' + 228: 71, # 'ä' + 229: 82, # 'ĺ' + 230: 243, # 'ć' + 231: 73, # 'ç' + 232: 244, # 'Ä' + 233: 15, # 'é' + 234: 85, # 'Ä™' + 235: 79, # 'ë' + 236: 86, # 'Ä›' + 237: 30, # 'í' + 238: 77, # 'î' + 239: 87, # 'Ä' + 240: 245, # 'Ä‘' + 241: 246, # 'Å„' + 242: 247, # 'ň' + 243: 25, # 'ó' + 244: 74, # 'ô' + 245: 42, # 'Å‘' + 246: 24, # 'ö' + 247: 248, # '÷' + 248: 249, # 'Å™' + 249: 250, # 'ů' + 250: 31, # 'ú' + 251: 56, # 'ű' + 252: 29, # 'ü' + 253: 251, # 'ý' + 254: 252, # 'Å£' + 255: 253, # 'Ë™' +} + +WINDOWS_1250_HUNGARIAN_MODEL = SingleByteCharSetModel(charset_name='windows-1250', + language='Hungarian', + char_to_order_map=WINDOWS_1250_HUNGARIAN_CHAR_TO_ORDER, + language_model=HUNGARIAN_LANG_MODEL, + typical_positive_ratio=0.947368, + keep_ascii_letters=True, + alphabet='ABCDEFGHIJKLMNOPRSTUVZabcdefghijklmnoprstuvzÃÉÃÓÖÚÜáéíóöúüÅőŰű') + +ISO_8859_2_HUNGARIAN_CHAR_TO_ORDER = { + 0: 255, # '\x00' + 1: 255, # '\x01' + 2: 255, # '\x02' + 3: 255, # '\x03' + 4: 255, # '\x04' + 5: 255, # '\x05' + 6: 255, # '\x06' + 7: 255, # '\x07' + 8: 255, # '\x08' + 9: 255, # '\t' + 10: 254, # '\n' + 11: 255, # '\x0b' + 12: 255, # '\x0c' + 13: 254, # '\r' + 14: 255, # '\x0e' + 15: 255, # '\x0f' + 16: 255, # '\x10' + 17: 255, # '\x11' + 18: 255, # '\x12' + 19: 255, # '\x13' + 20: 255, # '\x14' + 21: 255, # '\x15' + 22: 255, # '\x16' + 23: 255, # '\x17' + 24: 255, # '\x18' + 25: 255, # '\x19' + 26: 255, # '\x1a' + 27: 255, # '\x1b' + 28: 255, # '\x1c' + 29: 255, # '\x1d' + 30: 255, # '\x1e' + 31: 255, # '\x1f' + 32: 253, # ' ' + 33: 253, # '!' + 34: 253, # '"' + 35: 253, # '#' + 36: 253, # '$' + 37: 253, # '%' + 38: 253, # '&' + 39: 253, # "'" + 40: 253, # '(' + 41: 253, # ')' + 42: 253, # '*' + 43: 253, # '+' + 44: 253, # ',' + 45: 253, # '-' + 46: 253, # '.' + 47: 253, # '/' + 48: 252, # '0' + 49: 252, # '1' + 50: 252, # '2' + 51: 252, # '3' + 52: 252, # '4' + 53: 252, # '5' + 54: 252, # '6' + 55: 252, # '7' + 56: 252, # '8' + 57: 252, # '9' + 58: 253, # ':' + 59: 253, # ';' + 60: 253, # '<' + 61: 253, # '=' + 62: 253, # '>' + 63: 253, # '?' + 64: 253, # '@' + 65: 28, # 'A' + 66: 40, # 'B' + 67: 54, # 'C' + 68: 45, # 'D' + 69: 32, # 'E' + 70: 50, # 'F' + 71: 49, # 'G' + 72: 38, # 'H' + 73: 39, # 'I' + 74: 53, # 'J' + 75: 36, # 'K' + 76: 41, # 'L' + 77: 34, # 'M' + 78: 35, # 'N' + 79: 47, # 'O' + 80: 46, # 'P' + 81: 71, # 'Q' + 82: 43, # 'R' + 83: 33, # 'S' + 84: 37, # 'T' + 85: 57, # 'U' + 86: 48, # 'V' + 87: 64, # 'W' + 88: 68, # 'X' + 89: 55, # 'Y' + 90: 52, # 'Z' + 91: 253, # '[' + 92: 253, # '\\' + 93: 253, # ']' + 94: 253, # '^' + 95: 253, # '_' + 96: 253, # '`' + 97: 2, # 'a' + 98: 18, # 'b' + 99: 26, # 'c' + 100: 17, # 'd' + 101: 1, # 'e' + 102: 27, # 'f' + 103: 12, # 'g' + 104: 20, # 'h' + 105: 9, # 'i' + 106: 22, # 'j' + 107: 7, # 'k' + 108: 6, # 'l' + 109: 13, # 'm' + 110: 4, # 'n' + 111: 8, # 'o' + 112: 23, # 'p' + 113: 67, # 'q' + 114: 10, # 'r' + 115: 5, # 's' + 116: 3, # 't' + 117: 21, # 'u' + 118: 19, # 'v' + 119: 65, # 'w' + 120: 62, # 'x' + 121: 16, # 'y' + 122: 11, # 'z' + 123: 253, # '{' + 124: 253, # '|' + 125: 253, # '}' + 126: 253, # '~' + 127: 253, # '\x7f' + 128: 159, # '\x80' + 129: 160, # '\x81' + 130: 161, # '\x82' + 131: 162, # '\x83' + 132: 163, # '\x84' + 133: 164, # '\x85' + 134: 165, # '\x86' + 135: 166, # '\x87' + 136: 167, # '\x88' + 137: 168, # '\x89' + 138: 169, # '\x8a' + 139: 170, # '\x8b' + 140: 171, # '\x8c' + 141: 172, # '\x8d' + 142: 173, # '\x8e' + 143: 174, # '\x8f' + 144: 175, # '\x90' + 145: 176, # '\x91' + 146: 177, # '\x92' + 147: 178, # '\x93' + 148: 179, # '\x94' + 149: 180, # '\x95' + 150: 181, # '\x96' + 151: 182, # '\x97' + 152: 183, # '\x98' + 153: 184, # '\x99' + 154: 185, # '\x9a' + 155: 186, # '\x9b' + 156: 187, # '\x9c' + 157: 188, # '\x9d' + 158: 189, # '\x9e' + 159: 190, # '\x9f' + 160: 191, # '\xa0' + 161: 192, # 'Ä„' + 162: 193, # '˘' + 163: 194, # 'Å' + 164: 195, # '¤' + 165: 196, # 'Ľ' + 166: 197, # 'Åš' + 167: 75, # '§' + 168: 198, # '¨' + 169: 199, # 'Å ' + 170: 200, # 'Åž' + 171: 201, # 'Ť' + 172: 202, # 'Ź' + 173: 203, # '\xad' + 174: 204, # 'Ž' + 175: 205, # 'Å»' + 176: 79, # '°' + 177: 206, # 'Ä…' + 178: 207, # 'Ë›' + 179: 208, # 'Å‚' + 180: 209, # '´' + 181: 210, # 'ľ' + 182: 211, # 'Å›' + 183: 212, # 'ˇ' + 184: 213, # '¸' + 185: 214, # 'Å¡' + 186: 215, # 'ÅŸ' + 187: 216, # 'Å¥' + 188: 217, # 'ź' + 189: 218, # 'Ë' + 190: 219, # 'ž' + 191: 220, # 'ż' + 192: 221, # 'Å”' + 193: 51, # 'Ã' + 194: 81, # 'Â' + 195: 222, # 'Ä‚' + 196: 78, # 'Ä' + 197: 223, # 'Ĺ' + 198: 224, # 'Ć' + 199: 225, # 'Ç' + 200: 226, # 'ÄŒ' + 201: 44, # 'É' + 202: 227, # 'Ę' + 203: 228, # 'Ë' + 204: 229, # 'Äš' + 205: 61, # 'Ã' + 206: 230, # 'ÃŽ' + 207: 231, # 'ÄŽ' + 208: 232, # 'Ä' + 209: 233, # 'Ń' + 210: 234, # 'Ň' + 211: 58, # 'Ó' + 212: 235, # 'Ô' + 213: 66, # 'Å' + 214: 59, # 'Ö' + 215: 236, # '×' + 216: 237, # 'Ř' + 217: 238, # 'Å®' + 218: 60, # 'Ú' + 219: 69, # 'Å°' + 220: 63, # 'Ãœ' + 221: 239, # 'Ã' + 222: 240, # 'Å¢' + 223: 241, # 'ß' + 224: 82, # 'Å•' + 225: 14, # 'á' + 226: 74, # 'â' + 227: 242, # 'ă' + 228: 70, # 'ä' + 229: 80, # 'ĺ' + 230: 243, # 'ć' + 231: 72, # 'ç' + 232: 244, # 'Ä' + 233: 15, # 'é' + 234: 83, # 'Ä™' + 235: 77, # 'ë' + 236: 84, # 'Ä›' + 237: 30, # 'í' + 238: 76, # 'î' + 239: 85, # 'Ä' + 240: 245, # 'Ä‘' + 241: 246, # 'Å„' + 242: 247, # 'ň' + 243: 25, # 'ó' + 244: 73, # 'ô' + 245: 42, # 'Å‘' + 246: 24, # 'ö' + 247: 248, # '÷' + 248: 249, # 'Å™' + 249: 250, # 'ů' + 250: 31, # 'ú' + 251: 56, # 'ű' + 252: 29, # 'ü' + 253: 251, # 'ý' + 254: 252, # 'Å£' + 255: 253, # 'Ë™' +} + +ISO_8859_2_HUNGARIAN_MODEL = SingleByteCharSetModel(charset_name='ISO-8859-2', + language='Hungarian', + char_to_order_map=ISO_8859_2_HUNGARIAN_CHAR_TO_ORDER, + language_model=HUNGARIAN_LANG_MODEL, + typical_positive_ratio=0.947368, + keep_ascii_letters=True, + alphabet='ABCDEFGHIJKLMNOPRSTUVZabcdefghijklmnoprstuvzÃÉÃÓÖÚÜáéíóöúüÅőŰű') + diff --git a/venv/Lib/site-packages/pip/_vendor/chardet/langrussianmodel.py b/venv/Lib/site-packages/pip/_vendor/chardet/langrussianmodel.py new file mode 100644 index 0000000..5594452 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/chardet/langrussianmodel.py @@ -0,0 +1,5718 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +from pip._vendor.chardet.sbcharsetprober import SingleByteCharSetModel + + +# 3: Positive +# 2: Likely +# 1: Unlikely +# 0: Negative + +RUSSIAN_LANG_MODEL = { + 37: { # 'Ð' + 37: 0, # 'Ð' + 44: 1, # 'Б' + 33: 1, # 'Ð’' + 46: 1, # 'Г' + 41: 1, # 'Д' + 48: 1, # 'Е' + 56: 1, # 'Ж' + 51: 1, # 'З' + 42: 1, # 'И' + 60: 1, # 'Й' + 36: 1, # 'К' + 49: 1, # 'Л' + 38: 1, # 'Ðœ' + 31: 2, # 'Ð' + 34: 1, # 'О' + 35: 1, # 'П' + 45: 1, # 'Р' + 32: 1, # 'С' + 40: 1, # 'Т' + 52: 1, # 'У' + 53: 1, # 'Ф' + 55: 1, # 'Ð¥' + 58: 1, # 'Ц' + 50: 1, # 'Ч' + 57: 1, # 'Ш' + 63: 1, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 1, # 'Ю' + 43: 1, # 'Я' + 3: 1, # 'а' + 21: 2, # 'б' + 10: 2, # 'в' + 19: 2, # 'г' + 13: 2, # 'д' + 2: 0, # 'е' + 24: 1, # 'ж' + 20: 1, # 'з' + 4: 0, # 'и' + 23: 1, # 'й' + 11: 2, # 'к' + 8: 3, # 'л' + 12: 2, # 'м' + 5: 2, # 'н' + 1: 0, # 'о' + 15: 2, # 'п' + 9: 2, # 'Ñ€' + 7: 2, # 'Ñ' + 6: 2, # 'Ñ‚' + 14: 2, # 'у' + 39: 2, # 'Ñ„' + 26: 2, # 'Ñ…' + 28: 0, # 'ц' + 22: 1, # 'ч' + 25: 2, # 'ш' + 29: 0, # 'щ' + 54: 0, # 'ÑŠ' + 18: 0, # 'Ñ‹' + 17: 0, # 'ÑŒ' + 30: 1, # 'Ñ' + 27: 0, # 'ÑŽ' + 16: 0, # 'Ñ' + }, + 44: { # 'Б' + 37: 1, # 'Ð' + 44: 0, # 'Б' + 33: 1, # 'Ð’' + 46: 1, # 'Г' + 41: 0, # 'Д' + 48: 1, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 1, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 1, # 'Л' + 38: 1, # 'Ðœ' + 31: 1, # 'Ð' + 34: 1, # 'О' + 35: 0, # 'П' + 45: 1, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 1, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Ð¥' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 1, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 1, # 'Я' + 3: 2, # 'а' + 21: 0, # 'б' + 10: 0, # 'в' + 19: 0, # 'г' + 13: 1, # 'д' + 2: 3, # 'е' + 24: 0, # 'ж' + 20: 0, # 'з' + 4: 2, # 'и' + 23: 0, # 'й' + 11: 0, # 'к' + 8: 2, # 'л' + 12: 0, # 'м' + 5: 0, # 'н' + 1: 3, # 'о' + 15: 0, # 'п' + 9: 2, # 'Ñ€' + 7: 0, # 'Ñ' + 6: 0, # 'Ñ‚' + 14: 2, # 'у' + 39: 0, # 'Ñ„' + 26: 0, # 'Ñ…' + 28: 0, # 'ц' + 22: 0, # 'ч' + 25: 0, # 'ш' + 29: 0, # 'щ' + 54: 0, # 'ÑŠ' + 18: 2, # 'Ñ‹' + 17: 1, # 'ÑŒ' + 30: 2, # 'Ñ' + 27: 1, # 'ÑŽ' + 16: 1, # 'Ñ' + }, + 33: { # 'Ð’' + 37: 2, # 'Ð' + 44: 0, # 'Б' + 33: 1, # 'Ð’' + 46: 0, # 'Г' + 41: 1, # 'Д' + 48: 1, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 1, # 'И' + 60: 0, # 'Й' + 36: 1, # 'К' + 49: 1, # 'Л' + 38: 1, # 'Ðœ' + 31: 1, # 'Ð' + 34: 1, # 'О' + 35: 1, # 'П' + 45: 1, # 'Р' + 32: 1, # 'С' + 40: 1, # 'Т' + 52: 1, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Ð¥' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 1, # 'Ш' + 63: 0, # 'Щ' + 62: 1, # 'Ы' + 61: 1, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 1, # 'Я' + 3: 2, # 'а' + 21: 1, # 'б' + 10: 1, # 'в' + 19: 1, # 'г' + 13: 2, # 'д' + 2: 3, # 'е' + 24: 0, # 'ж' + 20: 2, # 'з' + 4: 2, # 'и' + 23: 0, # 'й' + 11: 1, # 'к' + 8: 2, # 'л' + 12: 2, # 'м' + 5: 2, # 'н' + 1: 3, # 'о' + 15: 2, # 'п' + 9: 2, # 'Ñ€' + 7: 3, # 'Ñ' + 6: 2, # 'Ñ‚' + 14: 2, # 'у' + 39: 0, # 'Ñ„' + 26: 1, # 'Ñ…' + 28: 1, # 'ц' + 22: 2, # 'ч' + 25: 1, # 'ш' + 29: 0, # 'щ' + 54: 1, # 'ÑŠ' + 18: 3, # 'Ñ‹' + 17: 1, # 'ÑŒ' + 30: 2, # 'Ñ' + 27: 0, # 'ÑŽ' + 16: 1, # 'Ñ' + }, + 46: { # 'Г' + 37: 1, # 'Ð' + 44: 1, # 'Б' + 33: 0, # 'Ð’' + 46: 0, # 'Г' + 41: 1, # 'Д' + 48: 1, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 1, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 1, # 'Л' + 38: 1, # 'Ðœ' + 31: 1, # 'Ð' + 34: 1, # 'О' + 35: 1, # 'П' + 45: 1, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 1, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Ð¥' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 2, # 'а' + 21: 0, # 'б' + 10: 1, # 'в' + 19: 0, # 'г' + 13: 2, # 'д' + 2: 2, # 'е' + 24: 0, # 'ж' + 20: 0, # 'з' + 4: 2, # 'и' + 23: 0, # 'й' + 11: 0, # 'к' + 8: 2, # 'л' + 12: 1, # 'м' + 5: 1, # 'н' + 1: 3, # 'о' + 15: 0, # 'п' + 9: 2, # 'Ñ€' + 7: 0, # 'Ñ' + 6: 0, # 'Ñ‚' + 14: 2, # 'у' + 39: 0, # 'Ñ„' + 26: 0, # 'Ñ…' + 28: 0, # 'ц' + 22: 0, # 'ч' + 25: 0, # 'ш' + 29: 0, # 'щ' + 54: 0, # 'ÑŠ' + 18: 0, # 'Ñ‹' + 17: 1, # 'ÑŒ' + 30: 1, # 'Ñ' + 27: 1, # 'ÑŽ' + 16: 0, # 'Ñ' + }, + 41: { # 'Д' + 37: 1, # 'Ð' + 44: 0, # 'Б' + 33: 1, # 'Ð’' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 2, # 'Е' + 56: 1, # 'Ж' + 51: 0, # 'З' + 42: 1, # 'И' + 60: 0, # 'Й' + 36: 1, # 'К' + 49: 1, # 'Л' + 38: 0, # 'Ðœ' + 31: 1, # 'Ð' + 34: 1, # 'О' + 35: 0, # 'П' + 45: 1, # 'Р' + 32: 1, # 'С' + 40: 0, # 'Т' + 52: 1, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Ð¥' + 58: 1, # 'Ц' + 50: 1, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 1, # 'Ы' + 61: 1, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 1, # 'Я' + 3: 3, # 'а' + 21: 0, # 'б' + 10: 2, # 'в' + 19: 0, # 'г' + 13: 0, # 'д' + 2: 2, # 'е' + 24: 3, # 'ж' + 20: 1, # 'з' + 4: 2, # 'и' + 23: 0, # 'й' + 11: 0, # 'к' + 8: 2, # 'л' + 12: 1, # 'м' + 5: 1, # 'н' + 1: 3, # 'о' + 15: 0, # 'п' + 9: 2, # 'Ñ€' + 7: 0, # 'Ñ' + 6: 0, # 'Ñ‚' + 14: 2, # 'у' + 39: 0, # 'Ñ„' + 26: 1, # 'Ñ…' + 28: 0, # 'ц' + 22: 0, # 'ч' + 25: 0, # 'ш' + 29: 0, # 'щ' + 54: 0, # 'ÑŠ' + 18: 1, # 'Ñ‹' + 17: 1, # 'ÑŒ' + 30: 2, # 'Ñ' + 27: 1, # 'ÑŽ' + 16: 1, # 'Ñ' + }, + 48: { # 'Е' + 37: 1, # 'Ð' + 44: 1, # 'Б' + 33: 1, # 'Ð’' + 46: 1, # 'Г' + 41: 1, # 'Д' + 48: 1, # 'Е' + 56: 1, # 'Ж' + 51: 1, # 'З' + 42: 1, # 'И' + 60: 1, # 'Й' + 36: 1, # 'К' + 49: 1, # 'Л' + 38: 1, # 'Ðœ' + 31: 2, # 'Ð' + 34: 1, # 'О' + 35: 1, # 'П' + 45: 2, # 'Р' + 32: 2, # 'С' + 40: 1, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 1, # 'Ð¥' + 58: 1, # 'Ц' + 50: 1, # 'Ч' + 57: 1, # 'Ш' + 63: 1, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 1, # 'Я' + 3: 0, # 'а' + 21: 0, # 'б' + 10: 2, # 'в' + 19: 2, # 'г' + 13: 2, # 'д' + 2: 2, # 'е' + 24: 1, # 'ж' + 20: 1, # 'з' + 4: 0, # 'и' + 23: 2, # 'й' + 11: 1, # 'к' + 8: 2, # 'л' + 12: 2, # 'м' + 5: 1, # 'н' + 1: 0, # 'о' + 15: 1, # 'п' + 9: 1, # 'Ñ€' + 7: 3, # 'Ñ' + 6: 0, # 'Ñ‚' + 14: 0, # 'у' + 39: 1, # 'Ñ„' + 26: 1, # 'Ñ…' + 28: 0, # 'ц' + 22: 0, # 'ч' + 25: 1, # 'ш' + 29: 2, # 'щ' + 54: 0, # 'ÑŠ' + 18: 0, # 'Ñ‹' + 17: 0, # 'ÑŒ' + 30: 0, # 'Ñ' + 27: 1, # 'ÑŽ' + 16: 0, # 'Ñ' + }, + 56: { # 'Ж' + 37: 1, # 'Ð' + 44: 0, # 'Б' + 33: 0, # 'Ð’' + 46: 0, # 'Г' + 41: 1, # 'Д' + 48: 1, # 'Е' + 56: 0, # 'Ж' + 51: 1, # 'З' + 42: 1, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 0, # 'Л' + 38: 0, # 'Ðœ' + 31: 1, # 'Ð' + 34: 1, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 1, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Ð¥' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 2, # 'а' + 21: 1, # 'б' + 10: 0, # 'в' + 19: 1, # 'г' + 13: 1, # 'д' + 2: 2, # 'е' + 24: 1, # 'ж' + 20: 0, # 'з' + 4: 2, # 'и' + 23: 0, # 'й' + 11: 0, # 'к' + 8: 0, # 'л' + 12: 1, # 'м' + 5: 0, # 'н' + 1: 2, # 'о' + 15: 0, # 'п' + 9: 1, # 'Ñ€' + 7: 0, # 'Ñ' + 6: 0, # 'Ñ‚' + 14: 2, # 'у' + 39: 0, # 'Ñ„' + 26: 0, # 'Ñ…' + 28: 0, # 'ц' + 22: 0, # 'ч' + 25: 0, # 'ш' + 29: 0, # 'щ' + 54: 0, # 'ÑŠ' + 18: 0, # 'Ñ‹' + 17: 0, # 'ÑŒ' + 30: 0, # 'Ñ' + 27: 2, # 'ÑŽ' + 16: 0, # 'Ñ' + }, + 51: { # 'З' + 37: 1, # 'Ð' + 44: 0, # 'Б' + 33: 1, # 'Ð’' + 46: 1, # 'Г' + 41: 1, # 'Д' + 48: 1, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 1, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 1, # 'Л' + 38: 1, # 'Ðœ' + 31: 1, # 'Ð' + 34: 1, # 'О' + 35: 0, # 'П' + 45: 1, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 1, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Ð¥' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 1, # 'Ы' + 61: 1, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 3, # 'а' + 21: 1, # 'б' + 10: 2, # 'в' + 19: 0, # 'г' + 13: 2, # 'д' + 2: 2, # 'е' + 24: 0, # 'ж' + 20: 0, # 'з' + 4: 2, # 'и' + 23: 0, # 'й' + 11: 0, # 'к' + 8: 1, # 'л' + 12: 1, # 'м' + 5: 2, # 'н' + 1: 2, # 'о' + 15: 0, # 'п' + 9: 1, # 'Ñ€' + 7: 0, # 'Ñ' + 6: 0, # 'Ñ‚' + 14: 1, # 'у' + 39: 0, # 'Ñ„' + 26: 0, # 'Ñ…' + 28: 0, # 'ц' + 22: 0, # 'ч' + 25: 0, # 'ш' + 29: 0, # 'щ' + 54: 0, # 'ÑŠ' + 18: 1, # 'Ñ‹' + 17: 0, # 'ÑŒ' + 30: 0, # 'Ñ' + 27: 0, # 'ÑŽ' + 16: 1, # 'Ñ' + }, + 42: { # 'И' + 37: 1, # 'Ð' + 44: 1, # 'Б' + 33: 1, # 'Ð’' + 46: 1, # 'Г' + 41: 1, # 'Д' + 48: 2, # 'Е' + 56: 1, # 'Ж' + 51: 1, # 'З' + 42: 1, # 'И' + 60: 1, # 'Й' + 36: 1, # 'К' + 49: 1, # 'Л' + 38: 1, # 'Ðœ' + 31: 1, # 'Ð' + 34: 1, # 'О' + 35: 1, # 'П' + 45: 1, # 'Р' + 32: 2, # 'С' + 40: 1, # 'Т' + 52: 0, # 'У' + 53: 1, # 'Ф' + 55: 1, # 'Ð¥' + 58: 1, # 'Ц' + 50: 1, # 'Ч' + 57: 0, # 'Ш' + 63: 1, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 1, # 'Ю' + 43: 1, # 'Я' + 3: 1, # 'а' + 21: 2, # 'б' + 10: 2, # 'в' + 19: 2, # 'г' + 13: 2, # 'д' + 2: 2, # 'е' + 24: 0, # 'ж' + 20: 2, # 'з' + 4: 1, # 'и' + 23: 0, # 'й' + 11: 1, # 'к' + 8: 2, # 'л' + 12: 2, # 'м' + 5: 2, # 'н' + 1: 1, # 'о' + 15: 1, # 'п' + 9: 2, # 'Ñ€' + 7: 2, # 'Ñ' + 6: 2, # 'Ñ‚' + 14: 1, # 'у' + 39: 1, # 'Ñ„' + 26: 2, # 'Ñ…' + 28: 0, # 'ц' + 22: 0, # 'ч' + 25: 1, # 'ш' + 29: 1, # 'щ' + 54: 0, # 'ÑŠ' + 18: 0, # 'Ñ‹' + 17: 0, # 'ÑŒ' + 30: 0, # 'Ñ' + 27: 1, # 'ÑŽ' + 16: 0, # 'Ñ' + }, + 60: { # 'Й' + 37: 0, # 'Ð' + 44: 0, # 'Б' + 33: 0, # 'Ð’' + 46: 0, # 'Г' + 41: 1, # 'Д' + 48: 0, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 0, # 'И' + 60: 0, # 'Й' + 36: 1, # 'К' + 49: 1, # 'Л' + 38: 0, # 'Ðœ' + 31: 1, # 'Ð' + 34: 0, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 1, # 'С' + 40: 1, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 1, # 'Ð¥' + 58: 1, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 0, # 'а' + 21: 0, # 'б' + 10: 0, # 'в' + 19: 0, # 'г' + 13: 0, # 'д' + 2: 1, # 'е' + 24: 0, # 'ж' + 20: 0, # 'з' + 4: 0, # 'и' + 23: 0, # 'й' + 11: 0, # 'к' + 8: 0, # 'л' + 12: 0, # 'м' + 5: 0, # 'н' + 1: 2, # 'о' + 15: 0, # 'п' + 9: 0, # 'Ñ€' + 7: 0, # 'Ñ' + 6: 0, # 'Ñ‚' + 14: 0, # 'у' + 39: 0, # 'Ñ„' + 26: 0, # 'Ñ…' + 28: 0, # 'ц' + 22: 0, # 'ч' + 25: 0, # 'ш' + 29: 0, # 'щ' + 54: 0, # 'ÑŠ' + 18: 0, # 'Ñ‹' + 17: 0, # 'ÑŒ' + 30: 0, # 'Ñ' + 27: 0, # 'ÑŽ' + 16: 0, # 'Ñ' + }, + 36: { # 'К' + 37: 2, # 'Ð' + 44: 0, # 'Б' + 33: 1, # 'Ð’' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 1, # 'Е' + 56: 0, # 'Ж' + 51: 1, # 'З' + 42: 1, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 1, # 'Л' + 38: 0, # 'Ðœ' + 31: 1, # 'Ð' + 34: 2, # 'О' + 35: 1, # 'П' + 45: 1, # 'Р' + 32: 1, # 'С' + 40: 1, # 'Т' + 52: 1, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Ð¥' + 58: 1, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 3, # 'а' + 21: 0, # 'б' + 10: 1, # 'в' + 19: 0, # 'г' + 13: 0, # 'д' + 2: 2, # 'е' + 24: 0, # 'ж' + 20: 0, # 'з' + 4: 2, # 'и' + 23: 0, # 'й' + 11: 0, # 'к' + 8: 2, # 'л' + 12: 0, # 'м' + 5: 1, # 'н' + 1: 3, # 'о' + 15: 0, # 'п' + 9: 2, # 'Ñ€' + 7: 2, # 'Ñ' + 6: 2, # 'Ñ‚' + 14: 2, # 'у' + 39: 0, # 'Ñ„' + 26: 1, # 'Ñ…' + 28: 0, # 'ц' + 22: 0, # 'ч' + 25: 0, # 'ш' + 29: 0, # 'щ' + 54: 0, # 'ÑŠ' + 18: 1, # 'Ñ‹' + 17: 1, # 'ÑŒ' + 30: 2, # 'Ñ' + 27: 1, # 'ÑŽ' + 16: 0, # 'Ñ' + }, + 49: { # 'Л' + 37: 2, # 'Ð' + 44: 0, # 'Б' + 33: 0, # 'Ð’' + 46: 1, # 'Г' + 41: 0, # 'Д' + 48: 1, # 'Е' + 56: 1, # 'Ж' + 51: 0, # 'З' + 42: 1, # 'И' + 60: 0, # 'Й' + 36: 1, # 'К' + 49: 1, # 'Л' + 38: 1, # 'Ðœ' + 31: 0, # 'Ð' + 34: 1, # 'О' + 35: 1, # 'П' + 45: 0, # 'Р' + 32: 1, # 'С' + 40: 1, # 'Т' + 52: 1, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Ð¥' + 58: 0, # 'Ц' + 50: 1, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 1, # 'Ы' + 61: 1, # 'Ь' + 47: 0, # 'Э' + 59: 1, # 'Ю' + 43: 1, # 'Я' + 3: 2, # 'а' + 21: 0, # 'б' + 10: 0, # 'в' + 19: 1, # 'г' + 13: 0, # 'д' + 2: 2, # 'е' + 24: 1, # 'ж' + 20: 0, # 'з' + 4: 2, # 'и' + 23: 0, # 'й' + 11: 0, # 'к' + 8: 1, # 'л' + 12: 0, # 'м' + 5: 1, # 'н' + 1: 2, # 'о' + 15: 0, # 'п' + 9: 0, # 'Ñ€' + 7: 0, # 'Ñ' + 6: 0, # 'Ñ‚' + 14: 2, # 'у' + 39: 0, # 'Ñ„' + 26: 1, # 'Ñ…' + 28: 0, # 'ц' + 22: 0, # 'ч' + 25: 0, # 'ш' + 29: 0, # 'щ' + 54: 0, # 'ÑŠ' + 18: 1, # 'Ñ‹' + 17: 1, # 'ÑŒ' + 30: 2, # 'Ñ' + 27: 2, # 'ÑŽ' + 16: 1, # 'Ñ' + }, + 38: { # 'Ðœ' + 37: 1, # 'Ð' + 44: 1, # 'Б' + 33: 1, # 'Ð’' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 1, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 1, # 'И' + 60: 0, # 'Й' + 36: 1, # 'К' + 49: 1, # 'Л' + 38: 1, # 'Ðœ' + 31: 1, # 'Ð' + 34: 1, # 'О' + 35: 1, # 'П' + 45: 1, # 'Р' + 32: 1, # 'С' + 40: 1, # 'Т' + 52: 1, # 'У' + 53: 1, # 'Ф' + 55: 1, # 'Ð¥' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 1, # 'Ы' + 61: 0, # 'Ь' + 47: 1, # 'Э' + 59: 0, # 'Ю' + 43: 1, # 'Я' + 3: 3, # 'а' + 21: 0, # 'б' + 10: 0, # 'в' + 19: 1, # 'г' + 13: 0, # 'д' + 2: 2, # 'е' + 24: 0, # 'ж' + 20: 0, # 'з' + 4: 3, # 'и' + 23: 0, # 'й' + 11: 0, # 'к' + 8: 1, # 'л' + 12: 1, # 'м' + 5: 2, # 'н' + 1: 3, # 'о' + 15: 0, # 'п' + 9: 1, # 'Ñ€' + 7: 1, # 'Ñ' + 6: 0, # 'Ñ‚' + 14: 2, # 'у' + 39: 0, # 'Ñ„' + 26: 0, # 'Ñ…' + 28: 0, # 'ц' + 22: 0, # 'ч' + 25: 0, # 'ш' + 29: 0, # 'щ' + 54: 0, # 'ÑŠ' + 18: 3, # 'Ñ‹' + 17: 1, # 'ÑŒ' + 30: 2, # 'Ñ' + 27: 1, # 'ÑŽ' + 16: 1, # 'Ñ' + }, + 31: { # 'Ð' + 37: 2, # 'Ð' + 44: 0, # 'Б' + 33: 0, # 'Ð’' + 46: 1, # 'Г' + 41: 1, # 'Д' + 48: 1, # 'Е' + 56: 0, # 'Ж' + 51: 1, # 'З' + 42: 2, # 'И' + 60: 0, # 'Й' + 36: 1, # 'К' + 49: 0, # 'Л' + 38: 0, # 'Ðœ' + 31: 1, # 'Ð' + 34: 1, # 'О' + 35: 0, # 'П' + 45: 1, # 'Р' + 32: 1, # 'С' + 40: 1, # 'Т' + 52: 1, # 'У' + 53: 1, # 'Ф' + 55: 1, # 'Ð¥' + 58: 1, # 'Ц' + 50: 1, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 1, # 'Ы' + 61: 1, # 'Ь' + 47: 1, # 'Э' + 59: 0, # 'Ю' + 43: 1, # 'Я' + 3: 3, # 'а' + 21: 0, # 'б' + 10: 0, # 'в' + 19: 0, # 'г' + 13: 0, # 'д' + 2: 3, # 'е' + 24: 0, # 'ж' + 20: 0, # 'з' + 4: 3, # 'и' + 23: 0, # 'й' + 11: 0, # 'к' + 8: 0, # 'л' + 12: 0, # 'м' + 5: 0, # 'н' + 1: 3, # 'о' + 15: 0, # 'п' + 9: 1, # 'Ñ€' + 7: 0, # 'Ñ' + 6: 0, # 'Ñ‚' + 14: 3, # 'у' + 39: 0, # 'Ñ„' + 26: 1, # 'Ñ…' + 28: 0, # 'ц' + 22: 0, # 'ч' + 25: 0, # 'ш' + 29: 0, # 'щ' + 54: 0, # 'ÑŠ' + 18: 1, # 'Ñ‹' + 17: 2, # 'ÑŒ' + 30: 1, # 'Ñ' + 27: 1, # 'ÑŽ' + 16: 1, # 'Ñ' + }, + 34: { # 'О' + 37: 0, # 'Ð' + 44: 1, # 'Б' + 33: 1, # 'Ð’' + 46: 1, # 'Г' + 41: 2, # 'Д' + 48: 1, # 'Е' + 56: 1, # 'Ж' + 51: 1, # 'З' + 42: 1, # 'И' + 60: 1, # 'Й' + 36: 1, # 'К' + 49: 2, # 'Л' + 38: 1, # 'Ðœ' + 31: 2, # 'Ð' + 34: 1, # 'О' + 35: 1, # 'П' + 45: 2, # 'Р' + 32: 1, # 'С' + 40: 1, # 'Т' + 52: 1, # 'У' + 53: 1, # 'Ф' + 55: 1, # 'Ð¥' + 58: 0, # 'Ц' + 50: 1, # 'Ч' + 57: 1, # 'Ш' + 63: 1, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 1, # 'Я' + 3: 1, # 'а' + 21: 2, # 'б' + 10: 1, # 'в' + 19: 2, # 'г' + 13: 2, # 'д' + 2: 0, # 'е' + 24: 1, # 'ж' + 20: 1, # 'з' + 4: 0, # 'и' + 23: 1, # 'й' + 11: 2, # 'к' + 8: 2, # 'л' + 12: 1, # 'м' + 5: 3, # 'н' + 1: 0, # 'о' + 15: 2, # 'п' + 9: 2, # 'Ñ€' + 7: 2, # 'Ñ' + 6: 2, # 'Ñ‚' + 14: 1, # 'у' + 39: 1, # 'Ñ„' + 26: 2, # 'Ñ…' + 28: 1, # 'ц' + 22: 2, # 'ч' + 25: 2, # 'ш' + 29: 1, # 'щ' + 54: 0, # 'ÑŠ' + 18: 0, # 'Ñ‹' + 17: 0, # 'ÑŒ' + 30: 0, # 'Ñ' + 27: 0, # 'ÑŽ' + 16: 0, # 'Ñ' + }, + 35: { # 'П' + 37: 1, # 'Ð' + 44: 0, # 'Б' + 33: 0, # 'Ð’' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 1, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 1, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 1, # 'Л' + 38: 0, # 'Ðœ' + 31: 1, # 'Ð' + 34: 1, # 'О' + 35: 1, # 'П' + 45: 2, # 'Р' + 32: 1, # 'С' + 40: 1, # 'Т' + 52: 1, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Ð¥' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 1, # 'Ы' + 61: 1, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 1, # 'Я' + 3: 2, # 'а' + 21: 0, # 'б' + 10: 0, # 'в' + 19: 0, # 'г' + 13: 0, # 'д' + 2: 2, # 'е' + 24: 0, # 'ж' + 20: 0, # 'з' + 4: 2, # 'и' + 23: 0, # 'й' + 11: 0, # 'к' + 8: 2, # 'л' + 12: 0, # 'м' + 5: 1, # 'н' + 1: 3, # 'о' + 15: 0, # 'п' + 9: 3, # 'Ñ€' + 7: 1, # 'Ñ' + 6: 1, # 'Ñ‚' + 14: 2, # 'у' + 39: 1, # 'Ñ„' + 26: 0, # 'Ñ…' + 28: 0, # 'ц' + 22: 0, # 'ч' + 25: 1, # 'ш' + 29: 0, # 'щ' + 54: 0, # 'ÑŠ' + 18: 1, # 'Ñ‹' + 17: 2, # 'ÑŒ' + 30: 1, # 'Ñ' + 27: 0, # 'ÑŽ' + 16: 2, # 'Ñ' + }, + 45: { # 'Р' + 37: 2, # 'Ð' + 44: 1, # 'Б' + 33: 1, # 'Ð’' + 46: 1, # 'Г' + 41: 1, # 'Д' + 48: 2, # 'Е' + 56: 1, # 'Ж' + 51: 0, # 'З' + 42: 2, # 'И' + 60: 0, # 'Й' + 36: 1, # 'К' + 49: 1, # 'Л' + 38: 1, # 'Ðœ' + 31: 1, # 'Ð' + 34: 2, # 'О' + 35: 0, # 'П' + 45: 1, # 'Р' + 32: 1, # 'С' + 40: 1, # 'Т' + 52: 1, # 'У' + 53: 0, # 'Ф' + 55: 1, # 'Ð¥' + 58: 1, # 'Ц' + 50: 1, # 'Ч' + 57: 1, # 'Ш' + 63: 0, # 'Щ' + 62: 1, # 'Ы' + 61: 1, # 'Ь' + 47: 1, # 'Э' + 59: 1, # 'Ю' + 43: 1, # 'Я' + 3: 3, # 'а' + 21: 0, # 'б' + 10: 1, # 'в' + 19: 0, # 'г' + 13: 0, # 'д' + 2: 2, # 'е' + 24: 1, # 'ж' + 20: 0, # 'з' + 4: 2, # 'и' + 23: 0, # 'й' + 11: 0, # 'к' + 8: 0, # 'л' + 12: 0, # 'м' + 5: 0, # 'н' + 1: 3, # 'о' + 15: 0, # 'п' + 9: 1, # 'Ñ€' + 7: 0, # 'Ñ' + 6: 0, # 'Ñ‚' + 14: 2, # 'у' + 39: 0, # 'Ñ„' + 26: 0, # 'Ñ…' + 28: 0, # 'ц' + 22: 0, # 'ч' + 25: 0, # 'ш' + 29: 0, # 'щ' + 54: 0, # 'ÑŠ' + 18: 2, # 'Ñ‹' + 17: 0, # 'ÑŒ' + 30: 1, # 'Ñ' + 27: 1, # 'ÑŽ' + 16: 2, # 'Ñ' + }, + 32: { # 'С' + 37: 1, # 'Ð' + 44: 1, # 'Б' + 33: 1, # 'Ð’' + 46: 1, # 'Г' + 41: 1, # 'Д' + 48: 1, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 1, # 'И' + 60: 0, # 'Й' + 36: 1, # 'К' + 49: 1, # 'Л' + 38: 1, # 'Ðœ' + 31: 1, # 'Ð' + 34: 1, # 'О' + 35: 1, # 'П' + 45: 1, # 'Р' + 32: 1, # 'С' + 40: 2, # 'Т' + 52: 1, # 'У' + 53: 0, # 'Ф' + 55: 1, # 'Ð¥' + 58: 1, # 'Ц' + 50: 1, # 'Ч' + 57: 1, # 'Ш' + 63: 0, # 'Щ' + 62: 1, # 'Ы' + 61: 1, # 'Ь' + 47: 1, # 'Э' + 59: 1, # 'Ю' + 43: 1, # 'Я' + 3: 2, # 'а' + 21: 1, # 'б' + 10: 2, # 'в' + 19: 1, # 'г' + 13: 2, # 'д' + 2: 3, # 'е' + 24: 1, # 'ж' + 20: 1, # 'з' + 4: 2, # 'и' + 23: 0, # 'й' + 11: 2, # 'к' + 8: 2, # 'л' + 12: 2, # 'м' + 5: 2, # 'н' + 1: 2, # 'о' + 15: 2, # 'п' + 9: 2, # 'Ñ€' + 7: 1, # 'Ñ' + 6: 3, # 'Ñ‚' + 14: 2, # 'у' + 39: 1, # 'Ñ„' + 26: 1, # 'Ñ…' + 28: 1, # 'ц' + 22: 1, # 'ч' + 25: 0, # 'ш' + 29: 0, # 'щ' + 54: 1, # 'ÑŠ' + 18: 1, # 'Ñ‹' + 17: 1, # 'ÑŒ' + 30: 2, # 'Ñ' + 27: 1, # 'ÑŽ' + 16: 1, # 'Ñ' + }, + 40: { # 'Т' + 37: 1, # 'Ð' + 44: 0, # 'Б' + 33: 1, # 'Ð’' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 1, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 1, # 'И' + 60: 0, # 'Й' + 36: 1, # 'К' + 49: 1, # 'Л' + 38: 1, # 'Ðœ' + 31: 1, # 'Ð' + 34: 2, # 'О' + 35: 0, # 'П' + 45: 1, # 'Р' + 32: 1, # 'С' + 40: 1, # 'Т' + 52: 1, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Ð¥' + 58: 0, # 'Ц' + 50: 1, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 1, # 'Ы' + 61: 1, # 'Ь' + 47: 1, # 'Э' + 59: 1, # 'Ю' + 43: 1, # 'Я' + 3: 3, # 'а' + 21: 1, # 'б' + 10: 2, # 'в' + 19: 0, # 'г' + 13: 0, # 'д' + 2: 3, # 'е' + 24: 0, # 'ж' + 20: 0, # 'з' + 4: 2, # 'и' + 23: 0, # 'й' + 11: 1, # 'к' + 8: 1, # 'л' + 12: 0, # 'м' + 5: 0, # 'н' + 1: 3, # 'о' + 15: 0, # 'п' + 9: 2, # 'Ñ€' + 7: 1, # 'Ñ' + 6: 0, # 'Ñ‚' + 14: 2, # 'у' + 39: 0, # 'Ñ„' + 26: 0, # 'Ñ…' + 28: 0, # 'ц' + 22: 0, # 'ч' + 25: 0, # 'ш' + 29: 1, # 'щ' + 54: 0, # 'ÑŠ' + 18: 3, # 'Ñ‹' + 17: 1, # 'ÑŒ' + 30: 2, # 'Ñ' + 27: 1, # 'ÑŽ' + 16: 1, # 'Ñ' + }, + 52: { # 'У' + 37: 1, # 'Ð' + 44: 1, # 'Б' + 33: 1, # 'Ð’' + 46: 1, # 'Г' + 41: 1, # 'Д' + 48: 1, # 'Е' + 56: 1, # 'Ж' + 51: 0, # 'З' + 42: 0, # 'И' + 60: 1, # 'Й' + 36: 1, # 'К' + 49: 1, # 'Л' + 38: 1, # 'Ðœ' + 31: 1, # 'Ð' + 34: 1, # 'О' + 35: 1, # 'П' + 45: 1, # 'Р' + 32: 1, # 'С' + 40: 1, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 1, # 'Ð¥' + 58: 0, # 'Ц' + 50: 1, # 'Ч' + 57: 1, # 'Ш' + 63: 1, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 1, # 'Ю' + 43: 0, # 'Я' + 3: 1, # 'а' + 21: 2, # 'б' + 10: 2, # 'в' + 19: 1, # 'г' + 13: 2, # 'д' + 2: 1, # 'е' + 24: 2, # 'ж' + 20: 2, # 'з' + 4: 2, # 'и' + 23: 1, # 'й' + 11: 1, # 'к' + 8: 2, # 'л' + 12: 2, # 'м' + 5: 1, # 'н' + 1: 2, # 'о' + 15: 1, # 'п' + 9: 2, # 'Ñ€' + 7: 2, # 'Ñ' + 6: 2, # 'Ñ‚' + 14: 0, # 'у' + 39: 1, # 'Ñ„' + 26: 1, # 'Ñ…' + 28: 1, # 'ц' + 22: 2, # 'ч' + 25: 1, # 'ш' + 29: 1, # 'щ' + 54: 0, # 'ÑŠ' + 18: 0, # 'Ñ‹' + 17: 0, # 'ÑŒ' + 30: 2, # 'Ñ' + 27: 1, # 'ÑŽ' + 16: 0, # 'Ñ' + }, + 53: { # 'Ф' + 37: 1, # 'Ð' + 44: 1, # 'Б' + 33: 0, # 'Ð’' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 1, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 1, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 1, # 'Л' + 38: 0, # 'Ðœ' + 31: 0, # 'Ð' + 34: 1, # 'О' + 35: 0, # 'П' + 45: 1, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 1, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Ð¥' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 2, # 'а' + 21: 0, # 'б' + 10: 0, # 'в' + 19: 0, # 'г' + 13: 0, # 'д' + 2: 2, # 'е' + 24: 0, # 'ж' + 20: 0, # 'з' + 4: 2, # 'и' + 23: 0, # 'й' + 11: 0, # 'к' + 8: 2, # 'л' + 12: 0, # 'м' + 5: 0, # 'н' + 1: 2, # 'о' + 15: 0, # 'п' + 9: 2, # 'Ñ€' + 7: 0, # 'Ñ' + 6: 1, # 'Ñ‚' + 14: 2, # 'у' + 39: 0, # 'Ñ„' + 26: 0, # 'Ñ…' + 28: 0, # 'ц' + 22: 0, # 'ч' + 25: 0, # 'ш' + 29: 0, # 'щ' + 54: 0, # 'ÑŠ' + 18: 0, # 'Ñ‹' + 17: 1, # 'ÑŒ' + 30: 2, # 'Ñ' + 27: 0, # 'ÑŽ' + 16: 0, # 'Ñ' + }, + 55: { # 'Ð¥' + 37: 1, # 'Ð' + 44: 0, # 'Б' + 33: 1, # 'Ð’' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 0, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 1, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 1, # 'Л' + 38: 1, # 'Ðœ' + 31: 1, # 'Ð' + 34: 1, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Ð¥' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 2, # 'а' + 21: 0, # 'б' + 10: 2, # 'в' + 19: 0, # 'г' + 13: 0, # 'д' + 2: 2, # 'е' + 24: 0, # 'ж' + 20: 0, # 'з' + 4: 2, # 'и' + 23: 0, # 'й' + 11: 0, # 'к' + 8: 2, # 'л' + 12: 1, # 'м' + 5: 0, # 'н' + 1: 2, # 'о' + 15: 0, # 'п' + 9: 2, # 'Ñ€' + 7: 0, # 'Ñ' + 6: 0, # 'Ñ‚' + 14: 1, # 'у' + 39: 0, # 'Ñ„' + 26: 0, # 'Ñ…' + 28: 0, # 'ц' + 22: 0, # 'ч' + 25: 0, # 'ш' + 29: 0, # 'щ' + 54: 0, # 'ÑŠ' + 18: 0, # 'Ñ‹' + 17: 1, # 'ÑŒ' + 30: 1, # 'Ñ' + 27: 0, # 'ÑŽ' + 16: 0, # 'Ñ' + }, + 58: { # 'Ц' + 37: 1, # 'Ð' + 44: 0, # 'Б' + 33: 0, # 'Ð’' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 1, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 1, # 'И' + 60: 0, # 'Й' + 36: 1, # 'К' + 49: 0, # 'Л' + 38: 0, # 'Ðœ' + 31: 0, # 'Ð' + 34: 1, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 1, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Ð¥' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 1, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 1, # 'а' + 21: 0, # 'б' + 10: 1, # 'в' + 19: 0, # 'г' + 13: 0, # 'д' + 2: 2, # 'е' + 24: 0, # 'ж' + 20: 0, # 'з' + 4: 2, # 'и' + 23: 0, # 'й' + 11: 0, # 'к' + 8: 0, # 'л' + 12: 0, # 'м' + 5: 0, # 'н' + 1: 0, # 'о' + 15: 0, # 'п' + 9: 0, # 'Ñ€' + 7: 0, # 'Ñ' + 6: 0, # 'Ñ‚' + 14: 1, # 'у' + 39: 0, # 'Ñ„' + 26: 0, # 'Ñ…' + 28: 0, # 'ц' + 22: 0, # 'ч' + 25: 0, # 'ш' + 29: 0, # 'щ' + 54: 0, # 'ÑŠ' + 18: 1, # 'Ñ‹' + 17: 0, # 'ÑŒ' + 30: 0, # 'Ñ' + 27: 1, # 'ÑŽ' + 16: 0, # 'Ñ' + }, + 50: { # 'Ч' + 37: 1, # 'Ð' + 44: 0, # 'Б' + 33: 0, # 'Ð’' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 1, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 1, # 'И' + 60: 0, # 'Й' + 36: 1, # 'К' + 49: 0, # 'Л' + 38: 0, # 'Ðœ' + 31: 1, # 'Ð' + 34: 0, # 'О' + 35: 1, # 'П' + 45: 0, # 'Р' + 32: 0, # 'С' + 40: 1, # 'Т' + 52: 1, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Ð¥' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 1, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 2, # 'а' + 21: 0, # 'б' + 10: 0, # 'в' + 19: 0, # 'г' + 13: 0, # 'д' + 2: 2, # 'е' + 24: 0, # 'ж' + 20: 0, # 'з' + 4: 2, # 'и' + 23: 0, # 'й' + 11: 0, # 'к' + 8: 1, # 'л' + 12: 0, # 'м' + 5: 0, # 'н' + 1: 1, # 'о' + 15: 0, # 'п' + 9: 1, # 'Ñ€' + 7: 0, # 'Ñ' + 6: 3, # 'Ñ‚' + 14: 2, # 'у' + 39: 0, # 'Ñ„' + 26: 0, # 'Ñ…' + 28: 0, # 'ц' + 22: 0, # 'ч' + 25: 0, # 'ш' + 29: 0, # 'щ' + 54: 0, # 'ÑŠ' + 18: 0, # 'Ñ‹' + 17: 1, # 'ÑŒ' + 30: 0, # 'Ñ' + 27: 0, # 'ÑŽ' + 16: 0, # 'Ñ' + }, + 57: { # 'Ш' + 37: 1, # 'Ð' + 44: 0, # 'Б' + 33: 0, # 'Ð’' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 1, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 1, # 'И' + 60: 0, # 'Й' + 36: 1, # 'К' + 49: 1, # 'Л' + 38: 0, # 'Ðœ' + 31: 1, # 'Ð' + 34: 1, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 1, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Ð¥' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 2, # 'а' + 21: 0, # 'б' + 10: 1, # 'в' + 19: 0, # 'г' + 13: 0, # 'д' + 2: 2, # 'е' + 24: 0, # 'ж' + 20: 0, # 'з' + 4: 1, # 'и' + 23: 0, # 'й' + 11: 1, # 'к' + 8: 2, # 'л' + 12: 1, # 'м' + 5: 1, # 'н' + 1: 2, # 'о' + 15: 2, # 'п' + 9: 1, # 'Ñ€' + 7: 0, # 'Ñ' + 6: 2, # 'Ñ‚' + 14: 2, # 'у' + 39: 0, # 'Ñ„' + 26: 1, # 'Ñ…' + 28: 0, # 'ц' + 22: 0, # 'ч' + 25: 1, # 'ш' + 29: 0, # 'щ' + 54: 0, # 'ÑŠ' + 18: 0, # 'Ñ‹' + 17: 0, # 'ÑŒ' + 30: 1, # 'Ñ' + 27: 0, # 'ÑŽ' + 16: 0, # 'Ñ' + }, + 63: { # 'Щ' + 37: 1, # 'Ð' + 44: 0, # 'Б' + 33: 0, # 'Ð’' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 1, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 1, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 0, # 'Л' + 38: 0, # 'Ðœ' + 31: 0, # 'Ð' + 34: 0, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Ð¥' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 1, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 1, # 'а' + 21: 0, # 'б' + 10: 0, # 'в' + 19: 0, # 'г' + 13: 0, # 'д' + 2: 1, # 'е' + 24: 0, # 'ж' + 20: 0, # 'з' + 4: 1, # 'и' + 23: 0, # 'й' + 11: 0, # 'к' + 8: 0, # 'л' + 12: 0, # 'м' + 5: 0, # 'н' + 1: 1, # 'о' + 15: 0, # 'п' + 9: 0, # 'Ñ€' + 7: 0, # 'Ñ' + 6: 0, # 'Ñ‚' + 14: 1, # 'у' + 39: 0, # 'Ñ„' + 26: 0, # 'Ñ…' + 28: 0, # 'ц' + 22: 0, # 'ч' + 25: 0, # 'ш' + 29: 0, # 'щ' + 54: 0, # 'ÑŠ' + 18: 0, # 'Ñ‹' + 17: 0, # 'ÑŒ' + 30: 0, # 'Ñ' + 27: 0, # 'ÑŽ' + 16: 0, # 'Ñ' + }, + 62: { # 'Ы' + 37: 0, # 'Ð' + 44: 0, # 'Б' + 33: 1, # 'Ð’' + 46: 1, # 'Г' + 41: 0, # 'Д' + 48: 1, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 0, # 'И' + 60: 1, # 'Й' + 36: 1, # 'К' + 49: 1, # 'Л' + 38: 1, # 'Ðœ' + 31: 1, # 'Ð' + 34: 0, # 'О' + 35: 1, # 'П' + 45: 1, # 'Р' + 32: 1, # 'С' + 40: 1, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 1, # 'Ð¥' + 58: 1, # 'Ц' + 50: 0, # 'Ч' + 57: 1, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 0, # 'а' + 21: 0, # 'б' + 10: 0, # 'в' + 19: 0, # 'г' + 13: 0, # 'д' + 2: 0, # 'е' + 24: 0, # 'ж' + 20: 0, # 'з' + 4: 0, # 'и' + 23: 0, # 'й' + 11: 0, # 'к' + 8: 0, # 'л' + 12: 0, # 'м' + 5: 0, # 'н' + 1: 0, # 'о' + 15: 0, # 'п' + 9: 0, # 'Ñ€' + 7: 0, # 'Ñ' + 6: 0, # 'Ñ‚' + 14: 0, # 'у' + 39: 0, # 'Ñ„' + 26: 0, # 'Ñ…' + 28: 0, # 'ц' + 22: 0, # 'ч' + 25: 0, # 'ш' + 29: 0, # 'щ' + 54: 0, # 'ÑŠ' + 18: 0, # 'Ñ‹' + 17: 0, # 'ÑŒ' + 30: 0, # 'Ñ' + 27: 0, # 'ÑŽ' + 16: 0, # 'Ñ' + }, + 61: { # 'Ь' + 37: 0, # 'Ð' + 44: 1, # 'Б' + 33: 1, # 'Ð’' + 46: 0, # 'Г' + 41: 1, # 'Д' + 48: 1, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 1, # 'И' + 60: 0, # 'Й' + 36: 1, # 'К' + 49: 0, # 'Л' + 38: 1, # 'Ðœ' + 31: 1, # 'Ð' + 34: 1, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 1, # 'С' + 40: 0, # 'Т' + 52: 0, # 'У' + 53: 1, # 'Ф' + 55: 0, # 'Ð¥' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 1, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 1, # 'Ю' + 43: 1, # 'Я' + 3: 0, # 'а' + 21: 0, # 'б' + 10: 0, # 'в' + 19: 0, # 'г' + 13: 0, # 'д' + 2: 0, # 'е' + 24: 0, # 'ж' + 20: 0, # 'з' + 4: 0, # 'и' + 23: 0, # 'й' + 11: 0, # 'к' + 8: 0, # 'л' + 12: 0, # 'м' + 5: 0, # 'н' + 1: 0, # 'о' + 15: 0, # 'п' + 9: 0, # 'Ñ€' + 7: 0, # 'Ñ' + 6: 0, # 'Ñ‚' + 14: 0, # 'у' + 39: 0, # 'Ñ„' + 26: 0, # 'Ñ…' + 28: 0, # 'ц' + 22: 0, # 'ч' + 25: 0, # 'ш' + 29: 0, # 'щ' + 54: 0, # 'ÑŠ' + 18: 0, # 'Ñ‹' + 17: 0, # 'ÑŒ' + 30: 0, # 'Ñ' + 27: 0, # 'ÑŽ' + 16: 0, # 'Ñ' + }, + 47: { # 'Э' + 37: 0, # 'Ð' + 44: 0, # 'Б' + 33: 1, # 'Ð’' + 46: 0, # 'Г' + 41: 1, # 'Д' + 48: 0, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 0, # 'И' + 60: 1, # 'Й' + 36: 1, # 'К' + 49: 1, # 'Л' + 38: 1, # 'Ðœ' + 31: 1, # 'Ð' + 34: 0, # 'О' + 35: 1, # 'П' + 45: 1, # 'Р' + 32: 1, # 'С' + 40: 1, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Ð¥' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 1, # 'а' + 21: 1, # 'б' + 10: 2, # 'в' + 19: 1, # 'г' + 13: 2, # 'д' + 2: 0, # 'е' + 24: 1, # 'ж' + 20: 0, # 'з' + 4: 0, # 'и' + 23: 2, # 'й' + 11: 2, # 'к' + 8: 2, # 'л' + 12: 2, # 'м' + 5: 2, # 'н' + 1: 0, # 'о' + 15: 1, # 'п' + 9: 2, # 'Ñ€' + 7: 1, # 'Ñ' + 6: 3, # 'Ñ‚' + 14: 1, # 'у' + 39: 1, # 'Ñ„' + 26: 1, # 'Ñ…' + 28: 0, # 'ц' + 22: 0, # 'ч' + 25: 1, # 'ш' + 29: 0, # 'щ' + 54: 0, # 'ÑŠ' + 18: 0, # 'Ñ‹' + 17: 0, # 'ÑŒ' + 30: 0, # 'Ñ' + 27: 0, # 'ÑŽ' + 16: 0, # 'Ñ' + }, + 59: { # 'Ю' + 37: 1, # 'Ð' + 44: 1, # 'Б' + 33: 0, # 'Ð’' + 46: 0, # 'Г' + 41: 1, # 'Д' + 48: 0, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 0, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 0, # 'Л' + 38: 0, # 'Ðœ' + 31: 1, # 'Ð' + 34: 0, # 'О' + 35: 0, # 'П' + 45: 1, # 'Р' + 32: 0, # 'С' + 40: 1, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Ð¥' + 58: 0, # 'Ц' + 50: 1, # 'Ч' + 57: 0, # 'Ш' + 63: 1, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 0, # 'а' + 21: 1, # 'б' + 10: 0, # 'в' + 19: 1, # 'г' + 13: 1, # 'д' + 2: 0, # 'е' + 24: 1, # 'ж' + 20: 0, # 'з' + 4: 0, # 'и' + 23: 0, # 'й' + 11: 1, # 'к' + 8: 2, # 'л' + 12: 1, # 'м' + 5: 2, # 'н' + 1: 0, # 'о' + 15: 1, # 'п' + 9: 1, # 'Ñ€' + 7: 1, # 'Ñ' + 6: 0, # 'Ñ‚' + 14: 0, # 'у' + 39: 0, # 'Ñ„' + 26: 1, # 'Ñ…' + 28: 0, # 'ц' + 22: 0, # 'ч' + 25: 0, # 'ш' + 29: 0, # 'щ' + 54: 0, # 'ÑŠ' + 18: 0, # 'Ñ‹' + 17: 0, # 'ÑŒ' + 30: 0, # 'Ñ' + 27: 0, # 'ÑŽ' + 16: 0, # 'Ñ' + }, + 43: { # 'Я' + 37: 0, # 'Ð' + 44: 0, # 'Б' + 33: 1, # 'Ð’' + 46: 1, # 'Г' + 41: 0, # 'Д' + 48: 1, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 1, # 'И' + 60: 0, # 'Й' + 36: 1, # 'К' + 49: 0, # 'Л' + 38: 0, # 'Ðœ' + 31: 1, # 'Ð' + 34: 0, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 1, # 'С' + 40: 1, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 1, # 'Ð¥' + 58: 0, # 'Ц' + 50: 1, # 'Ч' + 57: 0, # 'Ш' + 63: 1, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 1, # 'Ю' + 43: 1, # 'Я' + 3: 0, # 'а' + 21: 1, # 'б' + 10: 1, # 'в' + 19: 1, # 'г' + 13: 1, # 'д' + 2: 0, # 'е' + 24: 0, # 'ж' + 20: 1, # 'з' + 4: 0, # 'и' + 23: 1, # 'й' + 11: 1, # 'к' + 8: 1, # 'л' + 12: 1, # 'м' + 5: 2, # 'н' + 1: 0, # 'о' + 15: 1, # 'п' + 9: 1, # 'Ñ€' + 7: 1, # 'Ñ' + 6: 0, # 'Ñ‚' + 14: 0, # 'у' + 39: 0, # 'Ñ„' + 26: 1, # 'Ñ…' + 28: 0, # 'ц' + 22: 0, # 'ч' + 25: 1, # 'ш' + 29: 1, # 'щ' + 54: 0, # 'ÑŠ' + 18: 0, # 'Ñ‹' + 17: 0, # 'ÑŒ' + 30: 0, # 'Ñ' + 27: 0, # 'ÑŽ' + 16: 0, # 'Ñ' + }, + 3: { # 'а' + 37: 0, # 'Ð' + 44: 0, # 'Б' + 33: 0, # 'Ð’' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 0, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 1, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 0, # 'Л' + 38: 0, # 'Ðœ' + 31: 1, # 'Ð' + 34: 0, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Ð¥' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 2, # 'а' + 21: 3, # 'б' + 10: 3, # 'в' + 19: 3, # 'г' + 13: 3, # 'д' + 2: 3, # 'е' + 24: 3, # 'ж' + 20: 3, # 'з' + 4: 3, # 'и' + 23: 3, # 'й' + 11: 3, # 'к' + 8: 3, # 'л' + 12: 3, # 'м' + 5: 3, # 'н' + 1: 2, # 'о' + 15: 3, # 'п' + 9: 3, # 'Ñ€' + 7: 3, # 'Ñ' + 6: 3, # 'Ñ‚' + 14: 3, # 'у' + 39: 2, # 'Ñ„' + 26: 3, # 'Ñ…' + 28: 3, # 'ц' + 22: 3, # 'ч' + 25: 3, # 'ш' + 29: 3, # 'щ' + 54: 0, # 'ÑŠ' + 18: 0, # 'Ñ‹' + 17: 0, # 'ÑŒ' + 30: 2, # 'Ñ' + 27: 3, # 'ÑŽ' + 16: 3, # 'Ñ' + }, + 21: { # 'б' + 37: 0, # 'Ð' + 44: 0, # 'Б' + 33: 0, # 'Ð’' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 0, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 0, # 'И' + 60: 0, # 'Й' + 36: 1, # 'К' + 49: 0, # 'Л' + 38: 0, # 'Ðœ' + 31: 0, # 'Ð' + 34: 0, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Ð¥' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 3, # 'а' + 21: 2, # 'б' + 10: 2, # 'в' + 19: 1, # 'г' + 13: 2, # 'д' + 2: 3, # 'е' + 24: 2, # 'ж' + 20: 1, # 'з' + 4: 3, # 'и' + 23: 0, # 'й' + 11: 2, # 'к' + 8: 3, # 'л' + 12: 2, # 'м' + 5: 3, # 'н' + 1: 3, # 'о' + 15: 1, # 'п' + 9: 3, # 'Ñ€' + 7: 3, # 'Ñ' + 6: 2, # 'Ñ‚' + 14: 3, # 'у' + 39: 0, # 'Ñ„' + 26: 2, # 'Ñ…' + 28: 1, # 'ц' + 22: 1, # 'ч' + 25: 2, # 'ш' + 29: 3, # 'щ' + 54: 2, # 'ÑŠ' + 18: 3, # 'Ñ‹' + 17: 2, # 'ÑŒ' + 30: 1, # 'Ñ' + 27: 2, # 'ÑŽ' + 16: 3, # 'Ñ' + }, + 10: { # 'в' + 37: 0, # 'Ð' + 44: 0, # 'Б' + 33: 0, # 'Ð’' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 0, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 0, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 0, # 'Л' + 38: 0, # 'Ðœ' + 31: 0, # 'Ð' + 34: 0, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Ð¥' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 3, # 'а' + 21: 2, # 'б' + 10: 2, # 'в' + 19: 2, # 'г' + 13: 3, # 'д' + 2: 3, # 'е' + 24: 1, # 'ж' + 20: 3, # 'з' + 4: 3, # 'и' + 23: 0, # 'й' + 11: 3, # 'к' + 8: 3, # 'л' + 12: 2, # 'м' + 5: 3, # 'н' + 1: 3, # 'о' + 15: 3, # 'п' + 9: 3, # 'Ñ€' + 7: 3, # 'Ñ' + 6: 3, # 'Ñ‚' + 14: 3, # 'у' + 39: 1, # 'Ñ„' + 26: 2, # 'Ñ…' + 28: 2, # 'ц' + 22: 2, # 'ч' + 25: 3, # 'ш' + 29: 2, # 'щ' + 54: 2, # 'ÑŠ' + 18: 3, # 'Ñ‹' + 17: 3, # 'ÑŒ' + 30: 1, # 'Ñ' + 27: 1, # 'ÑŽ' + 16: 3, # 'Ñ' + }, + 19: { # 'г' + 37: 0, # 'Ð' + 44: 0, # 'Б' + 33: 0, # 'Ð’' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 0, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 0, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 0, # 'Л' + 38: 0, # 'Ðœ' + 31: 0, # 'Ð' + 34: 0, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Ð¥' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 3, # 'а' + 21: 1, # 'б' + 10: 2, # 'в' + 19: 1, # 'г' + 13: 3, # 'д' + 2: 3, # 'е' + 24: 0, # 'ж' + 20: 1, # 'з' + 4: 3, # 'и' + 23: 0, # 'й' + 11: 2, # 'к' + 8: 3, # 'л' + 12: 2, # 'м' + 5: 3, # 'н' + 1: 3, # 'о' + 15: 0, # 'п' + 9: 3, # 'Ñ€' + 7: 2, # 'Ñ' + 6: 2, # 'Ñ‚' + 14: 3, # 'у' + 39: 1, # 'Ñ„' + 26: 1, # 'Ñ…' + 28: 1, # 'ц' + 22: 2, # 'ч' + 25: 1, # 'ш' + 29: 0, # 'щ' + 54: 0, # 'ÑŠ' + 18: 1, # 'Ñ‹' + 17: 1, # 'ÑŒ' + 30: 1, # 'Ñ' + 27: 1, # 'ÑŽ' + 16: 0, # 'Ñ' + }, + 13: { # 'д' + 37: 0, # 'Ð' + 44: 0, # 'Б' + 33: 0, # 'Ð’' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 0, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 0, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 0, # 'Л' + 38: 0, # 'Ðœ' + 31: 0, # 'Ð' + 34: 0, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Ð¥' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 3, # 'а' + 21: 2, # 'б' + 10: 3, # 'в' + 19: 2, # 'г' + 13: 2, # 'д' + 2: 3, # 'е' + 24: 2, # 'ж' + 20: 2, # 'з' + 4: 3, # 'и' + 23: 0, # 'й' + 11: 3, # 'к' + 8: 3, # 'л' + 12: 2, # 'м' + 5: 3, # 'н' + 1: 3, # 'о' + 15: 2, # 'п' + 9: 3, # 'Ñ€' + 7: 3, # 'Ñ' + 6: 3, # 'Ñ‚' + 14: 3, # 'у' + 39: 1, # 'Ñ„' + 26: 2, # 'Ñ…' + 28: 3, # 'ц' + 22: 2, # 'ч' + 25: 2, # 'ш' + 29: 1, # 'щ' + 54: 2, # 'ÑŠ' + 18: 3, # 'Ñ‹' + 17: 3, # 'ÑŒ' + 30: 1, # 'Ñ' + 27: 2, # 'ÑŽ' + 16: 3, # 'Ñ' + }, + 2: { # 'е' + 37: 0, # 'Ð' + 44: 0, # 'Б' + 33: 0, # 'Ð’' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 0, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 0, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 0, # 'Л' + 38: 0, # 'Ðœ' + 31: 0, # 'Ð' + 34: 0, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Ð¥' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 2, # 'а' + 21: 3, # 'б' + 10: 3, # 'в' + 19: 3, # 'г' + 13: 3, # 'д' + 2: 3, # 'е' + 24: 3, # 'ж' + 20: 3, # 'з' + 4: 2, # 'и' + 23: 3, # 'й' + 11: 3, # 'к' + 8: 3, # 'л' + 12: 3, # 'м' + 5: 3, # 'н' + 1: 3, # 'о' + 15: 3, # 'п' + 9: 3, # 'Ñ€' + 7: 3, # 'Ñ' + 6: 3, # 'Ñ‚' + 14: 2, # 'у' + 39: 2, # 'Ñ„' + 26: 3, # 'Ñ…' + 28: 3, # 'ц' + 22: 3, # 'ч' + 25: 3, # 'ш' + 29: 3, # 'щ' + 54: 0, # 'ÑŠ' + 18: 0, # 'Ñ‹' + 17: 0, # 'ÑŒ' + 30: 1, # 'Ñ' + 27: 2, # 'ÑŽ' + 16: 3, # 'Ñ' + }, + 24: { # 'ж' + 37: 0, # 'Ð' + 44: 0, # 'Б' + 33: 0, # 'Ð’' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 0, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 0, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 0, # 'Л' + 38: 0, # 'Ðœ' + 31: 0, # 'Ð' + 34: 0, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Ð¥' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 3, # 'а' + 21: 2, # 'б' + 10: 1, # 'в' + 19: 2, # 'г' + 13: 3, # 'д' + 2: 3, # 'е' + 24: 2, # 'ж' + 20: 1, # 'з' + 4: 3, # 'и' + 23: 0, # 'й' + 11: 2, # 'к' + 8: 2, # 'л' + 12: 1, # 'м' + 5: 3, # 'н' + 1: 2, # 'о' + 15: 1, # 'п' + 9: 2, # 'Ñ€' + 7: 2, # 'Ñ' + 6: 1, # 'Ñ‚' + 14: 3, # 'у' + 39: 1, # 'Ñ„' + 26: 0, # 'Ñ…' + 28: 1, # 'ц' + 22: 2, # 'ч' + 25: 0, # 'ш' + 29: 0, # 'щ' + 54: 0, # 'ÑŠ' + 18: 1, # 'Ñ‹' + 17: 2, # 'ÑŒ' + 30: 1, # 'Ñ' + 27: 1, # 'ÑŽ' + 16: 1, # 'Ñ' + }, + 20: { # 'з' + 37: 0, # 'Ð' + 44: 0, # 'Б' + 33: 0, # 'Ð’' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 0, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 0, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 0, # 'Л' + 38: 0, # 'Ðœ' + 31: 0, # 'Ð' + 34: 0, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Ð¥' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 3, # 'а' + 21: 3, # 'б' + 10: 3, # 'в' + 19: 3, # 'г' + 13: 3, # 'д' + 2: 3, # 'е' + 24: 2, # 'ж' + 20: 2, # 'з' + 4: 3, # 'и' + 23: 0, # 'й' + 11: 3, # 'к' + 8: 3, # 'л' + 12: 3, # 'м' + 5: 3, # 'н' + 1: 3, # 'о' + 15: 0, # 'п' + 9: 3, # 'Ñ€' + 7: 2, # 'Ñ' + 6: 2, # 'Ñ‚' + 14: 3, # 'у' + 39: 0, # 'Ñ„' + 26: 0, # 'Ñ…' + 28: 1, # 'ц' + 22: 2, # 'ч' + 25: 1, # 'ш' + 29: 0, # 'щ' + 54: 2, # 'ÑŠ' + 18: 3, # 'Ñ‹' + 17: 2, # 'ÑŒ' + 30: 1, # 'Ñ' + 27: 1, # 'ÑŽ' + 16: 3, # 'Ñ' + }, + 4: { # 'и' + 37: 1, # 'Ð' + 44: 0, # 'Б' + 33: 0, # 'Ð’' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 0, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 0, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 0, # 'Л' + 38: 0, # 'Ðœ' + 31: 1, # 'Ð' + 34: 0, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Ð¥' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 3, # 'а' + 21: 3, # 'б' + 10: 3, # 'в' + 19: 3, # 'г' + 13: 3, # 'д' + 2: 3, # 'е' + 24: 3, # 'ж' + 20: 3, # 'з' + 4: 3, # 'и' + 23: 3, # 'й' + 11: 3, # 'к' + 8: 3, # 'л' + 12: 3, # 'м' + 5: 3, # 'н' + 1: 3, # 'о' + 15: 3, # 'п' + 9: 3, # 'Ñ€' + 7: 3, # 'Ñ' + 6: 3, # 'Ñ‚' + 14: 2, # 'у' + 39: 2, # 'Ñ„' + 26: 3, # 'Ñ…' + 28: 3, # 'ц' + 22: 3, # 'ч' + 25: 3, # 'ш' + 29: 3, # 'щ' + 54: 0, # 'ÑŠ' + 18: 0, # 'Ñ‹' + 17: 0, # 'ÑŒ' + 30: 2, # 'Ñ' + 27: 3, # 'ÑŽ' + 16: 3, # 'Ñ' + }, + 23: { # 'й' + 37: 0, # 'Ð' + 44: 0, # 'Б' + 33: 0, # 'Ð’' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 0, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 0, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 0, # 'Л' + 38: 0, # 'Ðœ' + 31: 0, # 'Ð' + 34: 0, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Ð¥' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 1, # 'а' + 21: 1, # 'б' + 10: 1, # 'в' + 19: 2, # 'г' + 13: 3, # 'д' + 2: 2, # 'е' + 24: 0, # 'ж' + 20: 2, # 'з' + 4: 1, # 'и' + 23: 0, # 'й' + 11: 2, # 'к' + 8: 2, # 'л' + 12: 2, # 'м' + 5: 3, # 'н' + 1: 2, # 'о' + 15: 1, # 'п' + 9: 2, # 'Ñ€' + 7: 3, # 'Ñ' + 6: 3, # 'Ñ‚' + 14: 1, # 'у' + 39: 2, # 'Ñ„' + 26: 1, # 'Ñ…' + 28: 2, # 'ц' + 22: 3, # 'ч' + 25: 2, # 'ш' + 29: 1, # 'щ' + 54: 0, # 'ÑŠ' + 18: 0, # 'Ñ‹' + 17: 0, # 'ÑŒ' + 30: 1, # 'Ñ' + 27: 1, # 'ÑŽ' + 16: 2, # 'Ñ' + }, + 11: { # 'к' + 37: 0, # 'Ð' + 44: 0, # 'Б' + 33: 0, # 'Ð’' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 0, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 0, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 0, # 'Л' + 38: 0, # 'Ðœ' + 31: 0, # 'Ð' + 34: 0, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Ð¥' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 3, # 'а' + 21: 1, # 'б' + 10: 3, # 'в' + 19: 1, # 'г' + 13: 1, # 'д' + 2: 3, # 'е' + 24: 2, # 'ж' + 20: 2, # 'з' + 4: 3, # 'и' + 23: 0, # 'й' + 11: 2, # 'к' + 8: 3, # 'л' + 12: 1, # 'м' + 5: 3, # 'н' + 1: 3, # 'о' + 15: 0, # 'п' + 9: 3, # 'Ñ€' + 7: 3, # 'Ñ' + 6: 3, # 'Ñ‚' + 14: 3, # 'у' + 39: 1, # 'Ñ„' + 26: 2, # 'Ñ…' + 28: 2, # 'ц' + 22: 1, # 'ч' + 25: 2, # 'ш' + 29: 0, # 'щ' + 54: 0, # 'ÑŠ' + 18: 1, # 'Ñ‹' + 17: 1, # 'ÑŒ' + 30: 1, # 'Ñ' + 27: 1, # 'ÑŽ' + 16: 1, # 'Ñ' + }, + 8: { # 'л' + 37: 0, # 'Ð' + 44: 0, # 'Б' + 33: 0, # 'Ð’' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 0, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 0, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 0, # 'Л' + 38: 0, # 'Ðœ' + 31: 0, # 'Ð' + 34: 0, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Ð¥' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 3, # 'а' + 21: 2, # 'б' + 10: 2, # 'в' + 19: 3, # 'г' + 13: 2, # 'д' + 2: 3, # 'е' + 24: 3, # 'ж' + 20: 2, # 'з' + 4: 3, # 'и' + 23: 0, # 'й' + 11: 3, # 'к' + 8: 3, # 'л' + 12: 2, # 'м' + 5: 3, # 'н' + 1: 3, # 'о' + 15: 2, # 'п' + 9: 1, # 'Ñ€' + 7: 3, # 'Ñ' + 6: 2, # 'Ñ‚' + 14: 3, # 'у' + 39: 2, # 'Ñ„' + 26: 2, # 'Ñ…' + 28: 1, # 'ц' + 22: 3, # 'ч' + 25: 2, # 'ш' + 29: 1, # 'щ' + 54: 0, # 'ÑŠ' + 18: 3, # 'Ñ‹' + 17: 3, # 'ÑŒ' + 30: 1, # 'Ñ' + 27: 3, # 'ÑŽ' + 16: 3, # 'Ñ' + }, + 12: { # 'м' + 37: 0, # 'Ð' + 44: 0, # 'Б' + 33: 0, # 'Ð’' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 0, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 0, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 0, # 'Л' + 38: 0, # 'Ðœ' + 31: 0, # 'Ð' + 34: 0, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Ð¥' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 3, # 'а' + 21: 2, # 'б' + 10: 2, # 'в' + 19: 2, # 'г' + 13: 1, # 'д' + 2: 3, # 'е' + 24: 1, # 'ж' + 20: 1, # 'з' + 4: 3, # 'и' + 23: 0, # 'й' + 11: 2, # 'к' + 8: 3, # 'л' + 12: 2, # 'м' + 5: 3, # 'н' + 1: 3, # 'о' + 15: 2, # 'п' + 9: 2, # 'Ñ€' + 7: 3, # 'Ñ' + 6: 2, # 'Ñ‚' + 14: 3, # 'у' + 39: 2, # 'Ñ„' + 26: 2, # 'Ñ…' + 28: 2, # 'ц' + 22: 2, # 'ч' + 25: 1, # 'ш' + 29: 1, # 'щ' + 54: 0, # 'ÑŠ' + 18: 3, # 'Ñ‹' + 17: 2, # 'ÑŒ' + 30: 2, # 'Ñ' + 27: 1, # 'ÑŽ' + 16: 3, # 'Ñ' + }, + 5: { # 'н' + 37: 0, # 'Ð' + 44: 0, # 'Б' + 33: 0, # 'Ð’' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 0, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 0, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 0, # 'Л' + 38: 0, # 'Ðœ' + 31: 0, # 'Ð' + 34: 0, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Ð¥' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 3, # 'а' + 21: 2, # 'б' + 10: 2, # 'в' + 19: 3, # 'г' + 13: 3, # 'д' + 2: 3, # 'е' + 24: 2, # 'ж' + 20: 2, # 'з' + 4: 3, # 'и' + 23: 0, # 'й' + 11: 3, # 'к' + 8: 2, # 'л' + 12: 1, # 'м' + 5: 3, # 'н' + 1: 3, # 'о' + 15: 1, # 'п' + 9: 2, # 'Ñ€' + 7: 3, # 'Ñ' + 6: 3, # 'Ñ‚' + 14: 3, # 'у' + 39: 2, # 'Ñ„' + 26: 2, # 'Ñ…' + 28: 3, # 'ц' + 22: 3, # 'ч' + 25: 2, # 'ш' + 29: 2, # 'щ' + 54: 1, # 'ÑŠ' + 18: 3, # 'Ñ‹' + 17: 3, # 'ÑŒ' + 30: 1, # 'Ñ' + 27: 3, # 'ÑŽ' + 16: 3, # 'Ñ' + }, + 1: { # 'о' + 37: 0, # 'Ð' + 44: 0, # 'Б' + 33: 0, # 'Ð’' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 0, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 0, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 0, # 'Л' + 38: 0, # 'Ðœ' + 31: 0, # 'Ð' + 34: 0, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Ð¥' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 2, # 'а' + 21: 3, # 'б' + 10: 3, # 'в' + 19: 3, # 'г' + 13: 3, # 'д' + 2: 3, # 'е' + 24: 3, # 'ж' + 20: 3, # 'з' + 4: 3, # 'и' + 23: 3, # 'й' + 11: 3, # 'к' + 8: 3, # 'л' + 12: 3, # 'м' + 5: 3, # 'н' + 1: 3, # 'о' + 15: 3, # 'п' + 9: 3, # 'Ñ€' + 7: 3, # 'Ñ' + 6: 3, # 'Ñ‚' + 14: 2, # 'у' + 39: 2, # 'Ñ„' + 26: 3, # 'Ñ…' + 28: 2, # 'ц' + 22: 3, # 'ч' + 25: 3, # 'ш' + 29: 3, # 'щ' + 54: 0, # 'ÑŠ' + 18: 0, # 'Ñ‹' + 17: 0, # 'ÑŒ' + 30: 2, # 'Ñ' + 27: 3, # 'ÑŽ' + 16: 3, # 'Ñ' + }, + 15: { # 'п' + 37: 0, # 'Ð' + 44: 0, # 'Б' + 33: 0, # 'Ð’' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 0, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 0, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 0, # 'Л' + 38: 0, # 'Ðœ' + 31: 0, # 'Ð' + 34: 0, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Ð¥' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 3, # 'а' + 21: 1, # 'б' + 10: 0, # 'в' + 19: 0, # 'г' + 13: 0, # 'д' + 2: 3, # 'е' + 24: 0, # 'ж' + 20: 0, # 'з' + 4: 3, # 'и' + 23: 0, # 'й' + 11: 2, # 'к' + 8: 3, # 'л' + 12: 1, # 'м' + 5: 3, # 'н' + 1: 3, # 'о' + 15: 2, # 'п' + 9: 3, # 'Ñ€' + 7: 2, # 'Ñ' + 6: 2, # 'Ñ‚' + 14: 3, # 'у' + 39: 1, # 'Ñ„' + 26: 0, # 'Ñ…' + 28: 2, # 'ц' + 22: 2, # 'ч' + 25: 1, # 'ш' + 29: 1, # 'щ' + 54: 0, # 'ÑŠ' + 18: 3, # 'Ñ‹' + 17: 2, # 'ÑŒ' + 30: 1, # 'Ñ' + 27: 1, # 'ÑŽ' + 16: 3, # 'Ñ' + }, + 9: { # 'Ñ€' + 37: 0, # 'Ð' + 44: 0, # 'Б' + 33: 0, # 'Ð’' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 0, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 0, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 0, # 'Л' + 38: 0, # 'Ðœ' + 31: 0, # 'Ð' + 34: 0, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Ð¥' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 3, # 'а' + 21: 2, # 'б' + 10: 3, # 'в' + 19: 3, # 'г' + 13: 3, # 'д' + 2: 3, # 'е' + 24: 3, # 'ж' + 20: 2, # 'з' + 4: 3, # 'и' + 23: 0, # 'й' + 11: 3, # 'к' + 8: 2, # 'л' + 12: 3, # 'м' + 5: 3, # 'н' + 1: 3, # 'о' + 15: 2, # 'п' + 9: 2, # 'Ñ€' + 7: 3, # 'Ñ' + 6: 3, # 'Ñ‚' + 14: 3, # 'у' + 39: 2, # 'Ñ„' + 26: 3, # 'Ñ…' + 28: 2, # 'ц' + 22: 2, # 'ч' + 25: 3, # 'ш' + 29: 2, # 'щ' + 54: 0, # 'ÑŠ' + 18: 3, # 'Ñ‹' + 17: 3, # 'ÑŒ' + 30: 2, # 'Ñ' + 27: 2, # 'ÑŽ' + 16: 3, # 'Ñ' + }, + 7: { # 'Ñ' + 37: 0, # 'Ð' + 44: 0, # 'Б' + 33: 0, # 'Ð’' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 0, # 'Е' + 56: 0, # 'Ж' + 51: 1, # 'З' + 42: 0, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 0, # 'Л' + 38: 0, # 'Ðœ' + 31: 0, # 'Ð' + 34: 0, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Ð¥' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 3, # 'а' + 21: 2, # 'б' + 10: 3, # 'в' + 19: 2, # 'г' + 13: 3, # 'д' + 2: 3, # 'е' + 24: 2, # 'ж' + 20: 2, # 'з' + 4: 3, # 'и' + 23: 0, # 'й' + 11: 3, # 'к' + 8: 3, # 'л' + 12: 3, # 'м' + 5: 3, # 'н' + 1: 3, # 'о' + 15: 3, # 'п' + 9: 3, # 'Ñ€' + 7: 3, # 'Ñ' + 6: 3, # 'Ñ‚' + 14: 3, # 'у' + 39: 2, # 'Ñ„' + 26: 3, # 'Ñ…' + 28: 2, # 'ц' + 22: 3, # 'ч' + 25: 2, # 'ш' + 29: 1, # 'щ' + 54: 2, # 'ÑŠ' + 18: 3, # 'Ñ‹' + 17: 3, # 'ÑŒ' + 30: 2, # 'Ñ' + 27: 3, # 'ÑŽ' + 16: 3, # 'Ñ' + }, + 6: { # 'Ñ‚' + 37: 0, # 'Ð' + 44: 0, # 'Б' + 33: 0, # 'Ð’' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 0, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 0, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 0, # 'Л' + 38: 0, # 'Ðœ' + 31: 0, # 'Ð' + 34: 0, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Ð¥' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 3, # 'а' + 21: 2, # 'б' + 10: 3, # 'в' + 19: 2, # 'г' + 13: 2, # 'д' + 2: 3, # 'е' + 24: 1, # 'ж' + 20: 1, # 'з' + 4: 3, # 'и' + 23: 0, # 'й' + 11: 3, # 'к' + 8: 3, # 'л' + 12: 2, # 'м' + 5: 3, # 'н' + 1: 3, # 'о' + 15: 2, # 'п' + 9: 3, # 'Ñ€' + 7: 3, # 'Ñ' + 6: 2, # 'Ñ‚' + 14: 3, # 'у' + 39: 2, # 'Ñ„' + 26: 2, # 'Ñ…' + 28: 2, # 'ц' + 22: 2, # 'ч' + 25: 2, # 'ш' + 29: 2, # 'щ' + 54: 2, # 'ÑŠ' + 18: 3, # 'Ñ‹' + 17: 3, # 'ÑŒ' + 30: 2, # 'Ñ' + 27: 2, # 'ÑŽ' + 16: 3, # 'Ñ' + }, + 14: { # 'у' + 37: 0, # 'Ð' + 44: 0, # 'Б' + 33: 0, # 'Ð’' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 0, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 0, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 0, # 'Л' + 38: 0, # 'Ðœ' + 31: 0, # 'Ð' + 34: 0, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Ð¥' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 2, # 'а' + 21: 3, # 'б' + 10: 3, # 'в' + 19: 3, # 'г' + 13: 3, # 'д' + 2: 3, # 'е' + 24: 3, # 'ж' + 20: 3, # 'з' + 4: 2, # 'и' + 23: 2, # 'й' + 11: 3, # 'к' + 8: 3, # 'л' + 12: 3, # 'м' + 5: 3, # 'н' + 1: 2, # 'о' + 15: 3, # 'п' + 9: 3, # 'Ñ€' + 7: 3, # 'Ñ' + 6: 3, # 'Ñ‚' + 14: 1, # 'у' + 39: 2, # 'Ñ„' + 26: 3, # 'Ñ…' + 28: 2, # 'ц' + 22: 3, # 'ч' + 25: 3, # 'ш' + 29: 3, # 'щ' + 54: 0, # 'ÑŠ' + 18: 0, # 'Ñ‹' + 17: 0, # 'ÑŒ' + 30: 2, # 'Ñ' + 27: 3, # 'ÑŽ' + 16: 2, # 'Ñ' + }, + 39: { # 'Ñ„' + 37: 0, # 'Ð' + 44: 0, # 'Б' + 33: 0, # 'Ð’' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 0, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 0, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 0, # 'Л' + 38: 0, # 'Ðœ' + 31: 0, # 'Ð' + 34: 0, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Ð¥' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 3, # 'а' + 21: 1, # 'б' + 10: 0, # 'в' + 19: 1, # 'г' + 13: 0, # 'д' + 2: 3, # 'е' + 24: 0, # 'ж' + 20: 0, # 'з' + 4: 3, # 'и' + 23: 0, # 'й' + 11: 1, # 'к' + 8: 2, # 'л' + 12: 1, # 'м' + 5: 1, # 'н' + 1: 3, # 'о' + 15: 1, # 'п' + 9: 2, # 'Ñ€' + 7: 2, # 'Ñ' + 6: 2, # 'Ñ‚' + 14: 2, # 'у' + 39: 2, # 'Ñ„' + 26: 0, # 'Ñ…' + 28: 0, # 'ц' + 22: 1, # 'ч' + 25: 1, # 'ш' + 29: 0, # 'щ' + 54: 0, # 'ÑŠ' + 18: 2, # 'Ñ‹' + 17: 1, # 'ÑŒ' + 30: 2, # 'Ñ' + 27: 1, # 'ÑŽ' + 16: 1, # 'Ñ' + }, + 26: { # 'Ñ…' + 37: 0, # 'Ð' + 44: 0, # 'Б' + 33: 0, # 'Ð’' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 0, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 0, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 0, # 'Л' + 38: 0, # 'Ðœ' + 31: 0, # 'Ð' + 34: 0, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Ð¥' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 3, # 'а' + 21: 0, # 'б' + 10: 3, # 'в' + 19: 1, # 'г' + 13: 1, # 'д' + 2: 2, # 'е' + 24: 0, # 'ж' + 20: 1, # 'з' + 4: 3, # 'и' + 23: 0, # 'й' + 11: 1, # 'к' + 8: 2, # 'л' + 12: 2, # 'м' + 5: 3, # 'н' + 1: 3, # 'о' + 15: 1, # 'п' + 9: 3, # 'Ñ€' + 7: 2, # 'Ñ' + 6: 2, # 'Ñ‚' + 14: 2, # 'у' + 39: 1, # 'Ñ„' + 26: 1, # 'Ñ…' + 28: 1, # 'ц' + 22: 1, # 'ч' + 25: 2, # 'ш' + 29: 0, # 'щ' + 54: 1, # 'ÑŠ' + 18: 0, # 'Ñ‹' + 17: 1, # 'ÑŒ' + 30: 1, # 'Ñ' + 27: 1, # 'ÑŽ' + 16: 0, # 'Ñ' + }, + 28: { # 'ц' + 37: 0, # 'Ð' + 44: 0, # 'Б' + 33: 0, # 'Ð’' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 0, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 0, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 0, # 'Л' + 38: 0, # 'Ðœ' + 31: 0, # 'Ð' + 34: 0, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Ð¥' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 3, # 'а' + 21: 1, # 'б' + 10: 2, # 'в' + 19: 1, # 'г' + 13: 1, # 'д' + 2: 3, # 'е' + 24: 0, # 'ж' + 20: 1, # 'з' + 4: 3, # 'и' + 23: 0, # 'й' + 11: 2, # 'к' + 8: 1, # 'л' + 12: 1, # 'м' + 5: 1, # 'н' + 1: 3, # 'о' + 15: 0, # 'п' + 9: 1, # 'Ñ€' + 7: 0, # 'Ñ' + 6: 1, # 'Ñ‚' + 14: 3, # 'у' + 39: 0, # 'Ñ„' + 26: 0, # 'Ñ…' + 28: 1, # 'ц' + 22: 0, # 'ч' + 25: 1, # 'ш' + 29: 0, # 'щ' + 54: 0, # 'ÑŠ' + 18: 3, # 'Ñ‹' + 17: 1, # 'ÑŒ' + 30: 0, # 'Ñ' + 27: 1, # 'ÑŽ' + 16: 0, # 'Ñ' + }, + 22: { # 'ч' + 37: 0, # 'Ð' + 44: 0, # 'Б' + 33: 0, # 'Ð’' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 0, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 0, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 0, # 'Л' + 38: 0, # 'Ðœ' + 31: 0, # 'Ð' + 34: 0, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Ð¥' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 3, # 'а' + 21: 1, # 'б' + 10: 1, # 'в' + 19: 0, # 'г' + 13: 0, # 'д' + 2: 3, # 'е' + 24: 1, # 'ж' + 20: 0, # 'з' + 4: 3, # 'и' + 23: 0, # 'й' + 11: 3, # 'к' + 8: 2, # 'л' + 12: 1, # 'м' + 5: 3, # 'н' + 1: 2, # 'о' + 15: 0, # 'п' + 9: 2, # 'Ñ€' + 7: 1, # 'Ñ' + 6: 3, # 'Ñ‚' + 14: 3, # 'у' + 39: 1, # 'Ñ„' + 26: 1, # 'Ñ…' + 28: 0, # 'ц' + 22: 1, # 'ч' + 25: 2, # 'ш' + 29: 0, # 'щ' + 54: 0, # 'ÑŠ' + 18: 0, # 'Ñ‹' + 17: 3, # 'ÑŒ' + 30: 0, # 'Ñ' + 27: 0, # 'ÑŽ' + 16: 0, # 'Ñ' + }, + 25: { # 'ш' + 37: 0, # 'Ð' + 44: 0, # 'Б' + 33: 0, # 'Ð’' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 0, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 0, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 0, # 'Л' + 38: 0, # 'Ðœ' + 31: 0, # 'Ð' + 34: 0, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Ð¥' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 3, # 'а' + 21: 1, # 'б' + 10: 2, # 'в' + 19: 1, # 'г' + 13: 0, # 'д' + 2: 3, # 'е' + 24: 0, # 'ж' + 20: 0, # 'з' + 4: 3, # 'и' + 23: 0, # 'й' + 11: 3, # 'к' + 8: 3, # 'л' + 12: 2, # 'м' + 5: 3, # 'н' + 1: 3, # 'о' + 15: 2, # 'п' + 9: 2, # 'Ñ€' + 7: 1, # 'Ñ' + 6: 2, # 'Ñ‚' + 14: 3, # 'у' + 39: 2, # 'Ñ„' + 26: 1, # 'Ñ…' + 28: 1, # 'ц' + 22: 1, # 'ч' + 25: 1, # 'ш' + 29: 0, # 'щ' + 54: 0, # 'ÑŠ' + 18: 0, # 'Ñ‹' + 17: 3, # 'ÑŒ' + 30: 1, # 'Ñ' + 27: 1, # 'ÑŽ' + 16: 0, # 'Ñ' + }, + 29: { # 'щ' + 37: 0, # 'Ð' + 44: 0, # 'Б' + 33: 0, # 'Ð’' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 0, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 0, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 0, # 'Л' + 38: 0, # 'Ðœ' + 31: 0, # 'Ð' + 34: 0, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Ð¥' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 3, # 'а' + 21: 0, # 'б' + 10: 1, # 'в' + 19: 0, # 'г' + 13: 0, # 'д' + 2: 3, # 'е' + 24: 0, # 'ж' + 20: 0, # 'з' + 4: 3, # 'и' + 23: 0, # 'й' + 11: 0, # 'к' + 8: 0, # 'л' + 12: 1, # 'м' + 5: 2, # 'н' + 1: 1, # 'о' + 15: 0, # 'п' + 9: 2, # 'Ñ€' + 7: 0, # 'Ñ' + 6: 0, # 'Ñ‚' + 14: 2, # 'у' + 39: 0, # 'Ñ„' + 26: 0, # 'Ñ…' + 28: 0, # 'ц' + 22: 0, # 'ч' + 25: 0, # 'ш' + 29: 0, # 'щ' + 54: 0, # 'ÑŠ' + 18: 0, # 'Ñ‹' + 17: 2, # 'ÑŒ' + 30: 0, # 'Ñ' + 27: 0, # 'ÑŽ' + 16: 0, # 'Ñ' + }, + 54: { # 'ÑŠ' + 37: 0, # 'Ð' + 44: 0, # 'Б' + 33: 0, # 'Ð’' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 0, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 0, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 0, # 'Л' + 38: 0, # 'Ðœ' + 31: 0, # 'Ð' + 34: 0, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Ð¥' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 0, # 'а' + 21: 0, # 'б' + 10: 0, # 'в' + 19: 0, # 'г' + 13: 0, # 'д' + 2: 2, # 'е' + 24: 0, # 'ж' + 20: 0, # 'з' + 4: 0, # 'и' + 23: 0, # 'й' + 11: 0, # 'к' + 8: 0, # 'л' + 12: 0, # 'м' + 5: 0, # 'н' + 1: 0, # 'о' + 15: 0, # 'п' + 9: 0, # 'Ñ€' + 7: 0, # 'Ñ' + 6: 0, # 'Ñ‚' + 14: 0, # 'у' + 39: 0, # 'Ñ„' + 26: 0, # 'Ñ…' + 28: 0, # 'ц' + 22: 0, # 'ч' + 25: 0, # 'ш' + 29: 0, # 'щ' + 54: 0, # 'ÑŠ' + 18: 0, # 'Ñ‹' + 17: 0, # 'ÑŒ' + 30: 0, # 'Ñ' + 27: 1, # 'ÑŽ' + 16: 2, # 'Ñ' + }, + 18: { # 'Ñ‹' + 37: 0, # 'Ð' + 44: 0, # 'Б' + 33: 0, # 'Ð’' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 0, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 0, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 0, # 'Л' + 38: 0, # 'Ðœ' + 31: 0, # 'Ð' + 34: 0, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Ð¥' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 0, # 'а' + 21: 3, # 'б' + 10: 3, # 'в' + 19: 2, # 'г' + 13: 2, # 'д' + 2: 3, # 'е' + 24: 2, # 'ж' + 20: 2, # 'з' + 4: 2, # 'и' + 23: 3, # 'й' + 11: 3, # 'к' + 8: 3, # 'л' + 12: 3, # 'м' + 5: 3, # 'н' + 1: 1, # 'о' + 15: 3, # 'п' + 9: 3, # 'Ñ€' + 7: 3, # 'Ñ' + 6: 3, # 'Ñ‚' + 14: 1, # 'у' + 39: 0, # 'Ñ„' + 26: 3, # 'Ñ…' + 28: 2, # 'ц' + 22: 3, # 'ч' + 25: 3, # 'ш' + 29: 2, # 'щ' + 54: 0, # 'ÑŠ' + 18: 0, # 'Ñ‹' + 17: 0, # 'ÑŒ' + 30: 0, # 'Ñ' + 27: 0, # 'ÑŽ' + 16: 2, # 'Ñ' + }, + 17: { # 'ÑŒ' + 37: 0, # 'Ð' + 44: 0, # 'Б' + 33: 0, # 'Ð’' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 0, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 0, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 0, # 'Л' + 38: 0, # 'Ðœ' + 31: 0, # 'Ð' + 34: 0, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Ð¥' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 0, # 'а' + 21: 2, # 'б' + 10: 2, # 'в' + 19: 2, # 'г' + 13: 2, # 'д' + 2: 3, # 'е' + 24: 1, # 'ж' + 20: 3, # 'з' + 4: 2, # 'и' + 23: 0, # 'й' + 11: 3, # 'к' + 8: 0, # 'л' + 12: 3, # 'м' + 5: 3, # 'н' + 1: 2, # 'о' + 15: 2, # 'п' + 9: 1, # 'Ñ€' + 7: 3, # 'Ñ' + 6: 2, # 'Ñ‚' + 14: 0, # 'у' + 39: 2, # 'Ñ„' + 26: 1, # 'Ñ…' + 28: 2, # 'ц' + 22: 2, # 'ч' + 25: 3, # 'ш' + 29: 2, # 'щ' + 54: 0, # 'ÑŠ' + 18: 0, # 'Ñ‹' + 17: 0, # 'ÑŒ' + 30: 1, # 'Ñ' + 27: 3, # 'ÑŽ' + 16: 3, # 'Ñ' + }, + 30: { # 'Ñ' + 37: 0, # 'Ð' + 44: 0, # 'Б' + 33: 0, # 'Ð’' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 0, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 0, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 0, # 'Л' + 38: 1, # 'Ðœ' + 31: 1, # 'Ð' + 34: 0, # 'О' + 35: 0, # 'П' + 45: 1, # 'Р' + 32: 1, # 'С' + 40: 0, # 'Т' + 52: 0, # 'У' + 53: 1, # 'Ф' + 55: 0, # 'Ð¥' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 0, # 'а' + 21: 1, # 'б' + 10: 1, # 'в' + 19: 1, # 'г' + 13: 2, # 'д' + 2: 1, # 'е' + 24: 0, # 'ж' + 20: 1, # 'з' + 4: 0, # 'и' + 23: 2, # 'й' + 11: 2, # 'к' + 8: 2, # 'л' + 12: 2, # 'м' + 5: 2, # 'н' + 1: 0, # 'о' + 15: 2, # 'п' + 9: 2, # 'Ñ€' + 7: 2, # 'Ñ' + 6: 3, # 'Ñ‚' + 14: 1, # 'у' + 39: 2, # 'Ñ„' + 26: 1, # 'Ñ…' + 28: 0, # 'ц' + 22: 0, # 'ч' + 25: 1, # 'ш' + 29: 0, # 'щ' + 54: 0, # 'ÑŠ' + 18: 0, # 'Ñ‹' + 17: 0, # 'ÑŒ' + 30: 1, # 'Ñ' + 27: 1, # 'ÑŽ' + 16: 1, # 'Ñ' + }, + 27: { # 'ÑŽ' + 37: 0, # 'Ð' + 44: 0, # 'Б' + 33: 0, # 'Ð’' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 0, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 0, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 0, # 'Л' + 38: 0, # 'Ðœ' + 31: 0, # 'Ð' + 34: 0, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Ð¥' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 2, # 'а' + 21: 3, # 'б' + 10: 1, # 'в' + 19: 2, # 'г' + 13: 3, # 'д' + 2: 1, # 'е' + 24: 2, # 'ж' + 20: 2, # 'з' + 4: 1, # 'и' + 23: 1, # 'й' + 11: 2, # 'к' + 8: 2, # 'л' + 12: 2, # 'м' + 5: 2, # 'н' + 1: 1, # 'о' + 15: 2, # 'п' + 9: 2, # 'Ñ€' + 7: 3, # 'Ñ' + 6: 3, # 'Ñ‚' + 14: 0, # 'у' + 39: 1, # 'Ñ„' + 26: 2, # 'Ñ…' + 28: 2, # 'ц' + 22: 2, # 'ч' + 25: 2, # 'ш' + 29: 3, # 'щ' + 54: 0, # 'ÑŠ' + 18: 0, # 'Ñ‹' + 17: 0, # 'ÑŒ' + 30: 1, # 'Ñ' + 27: 2, # 'ÑŽ' + 16: 1, # 'Ñ' + }, + 16: { # 'Ñ' + 37: 0, # 'Ð' + 44: 0, # 'Б' + 33: 0, # 'Ð’' + 46: 0, # 'Г' + 41: 0, # 'Д' + 48: 0, # 'Е' + 56: 0, # 'Ж' + 51: 0, # 'З' + 42: 0, # 'И' + 60: 0, # 'Й' + 36: 0, # 'К' + 49: 0, # 'Л' + 38: 0, # 'Ðœ' + 31: 0, # 'Ð' + 34: 0, # 'О' + 35: 0, # 'П' + 45: 0, # 'Р' + 32: 0, # 'С' + 40: 0, # 'Т' + 52: 0, # 'У' + 53: 0, # 'Ф' + 55: 0, # 'Ð¥' + 58: 0, # 'Ц' + 50: 0, # 'Ч' + 57: 0, # 'Ш' + 63: 0, # 'Щ' + 62: 0, # 'Ы' + 61: 0, # 'Ь' + 47: 0, # 'Э' + 59: 0, # 'Ю' + 43: 0, # 'Я' + 3: 0, # 'а' + 21: 2, # 'б' + 10: 3, # 'в' + 19: 2, # 'г' + 13: 3, # 'д' + 2: 3, # 'е' + 24: 3, # 'ж' + 20: 3, # 'з' + 4: 2, # 'и' + 23: 2, # 'й' + 11: 3, # 'к' + 8: 3, # 'л' + 12: 3, # 'м' + 5: 3, # 'н' + 1: 0, # 'о' + 15: 2, # 'п' + 9: 2, # 'Ñ€' + 7: 3, # 'Ñ' + 6: 3, # 'Ñ‚' + 14: 1, # 'у' + 39: 1, # 'Ñ„' + 26: 3, # 'Ñ…' + 28: 2, # 'ц' + 22: 2, # 'ч' + 25: 2, # 'ш' + 29: 3, # 'щ' + 54: 0, # 'ÑŠ' + 18: 0, # 'Ñ‹' + 17: 0, # 'ÑŒ' + 30: 0, # 'Ñ' + 27: 2, # 'ÑŽ' + 16: 2, # 'Ñ' + }, +} + +# 255: Undefined characters that did not exist in training text +# 254: Carriage/Return +# 253: symbol (punctuation) that does not belong to word +# 252: 0 - 9 +# 251: Control characters + +# Character Mapping Table(s): +IBM866_RUSSIAN_CHAR_TO_ORDER = { + 0: 255, # '\x00' + 1: 255, # '\x01' + 2: 255, # '\x02' + 3: 255, # '\x03' + 4: 255, # '\x04' + 5: 255, # '\x05' + 6: 255, # '\x06' + 7: 255, # '\x07' + 8: 255, # '\x08' + 9: 255, # '\t' + 10: 254, # '\n' + 11: 255, # '\x0b' + 12: 255, # '\x0c' + 13: 254, # '\r' + 14: 255, # '\x0e' + 15: 255, # '\x0f' + 16: 255, # '\x10' + 17: 255, # '\x11' + 18: 255, # '\x12' + 19: 255, # '\x13' + 20: 255, # '\x14' + 21: 255, # '\x15' + 22: 255, # '\x16' + 23: 255, # '\x17' + 24: 255, # '\x18' + 25: 255, # '\x19' + 26: 255, # '\x1a' + 27: 255, # '\x1b' + 28: 255, # '\x1c' + 29: 255, # '\x1d' + 30: 255, # '\x1e' + 31: 255, # '\x1f' + 32: 253, # ' ' + 33: 253, # '!' + 34: 253, # '"' + 35: 253, # '#' + 36: 253, # '$' + 37: 253, # '%' + 38: 253, # '&' + 39: 253, # "'" + 40: 253, # '(' + 41: 253, # ')' + 42: 253, # '*' + 43: 253, # '+' + 44: 253, # ',' + 45: 253, # '-' + 46: 253, # '.' + 47: 253, # '/' + 48: 252, # '0' + 49: 252, # '1' + 50: 252, # '2' + 51: 252, # '3' + 52: 252, # '4' + 53: 252, # '5' + 54: 252, # '6' + 55: 252, # '7' + 56: 252, # '8' + 57: 252, # '9' + 58: 253, # ':' + 59: 253, # ';' + 60: 253, # '<' + 61: 253, # '=' + 62: 253, # '>' + 63: 253, # '?' + 64: 253, # '@' + 65: 142, # 'A' + 66: 143, # 'B' + 67: 144, # 'C' + 68: 145, # 'D' + 69: 146, # 'E' + 70: 147, # 'F' + 71: 148, # 'G' + 72: 149, # 'H' + 73: 150, # 'I' + 74: 151, # 'J' + 75: 152, # 'K' + 76: 74, # 'L' + 77: 153, # 'M' + 78: 75, # 'N' + 79: 154, # 'O' + 80: 155, # 'P' + 81: 156, # 'Q' + 82: 157, # 'R' + 83: 158, # 'S' + 84: 159, # 'T' + 85: 160, # 'U' + 86: 161, # 'V' + 87: 162, # 'W' + 88: 163, # 'X' + 89: 164, # 'Y' + 90: 165, # 'Z' + 91: 253, # '[' + 92: 253, # '\\' + 93: 253, # ']' + 94: 253, # '^' + 95: 253, # '_' + 96: 253, # '`' + 97: 71, # 'a' + 98: 172, # 'b' + 99: 66, # 'c' + 100: 173, # 'd' + 101: 65, # 'e' + 102: 174, # 'f' + 103: 76, # 'g' + 104: 175, # 'h' + 105: 64, # 'i' + 106: 176, # 'j' + 107: 177, # 'k' + 108: 77, # 'l' + 109: 72, # 'm' + 110: 178, # 'n' + 111: 69, # 'o' + 112: 67, # 'p' + 113: 179, # 'q' + 114: 78, # 'r' + 115: 73, # 's' + 116: 180, # 't' + 117: 181, # 'u' + 118: 79, # 'v' + 119: 182, # 'w' + 120: 183, # 'x' + 121: 184, # 'y' + 122: 185, # 'z' + 123: 253, # '{' + 124: 253, # '|' + 125: 253, # '}' + 126: 253, # '~' + 127: 253, # '\x7f' + 128: 37, # 'Ð' + 129: 44, # 'Б' + 130: 33, # 'Ð’' + 131: 46, # 'Г' + 132: 41, # 'Д' + 133: 48, # 'Е' + 134: 56, # 'Ж' + 135: 51, # 'З' + 136: 42, # 'И' + 137: 60, # 'Й' + 138: 36, # 'К' + 139: 49, # 'Л' + 140: 38, # 'Ðœ' + 141: 31, # 'Ð' + 142: 34, # 'О' + 143: 35, # 'П' + 144: 45, # 'Р' + 145: 32, # 'С' + 146: 40, # 'Т' + 147: 52, # 'У' + 148: 53, # 'Ф' + 149: 55, # 'Ð¥' + 150: 58, # 'Ц' + 151: 50, # 'Ч' + 152: 57, # 'Ш' + 153: 63, # 'Щ' + 154: 70, # 'Ъ' + 155: 62, # 'Ы' + 156: 61, # 'Ь' + 157: 47, # 'Э' + 158: 59, # 'Ю' + 159: 43, # 'Я' + 160: 3, # 'а' + 161: 21, # 'б' + 162: 10, # 'в' + 163: 19, # 'г' + 164: 13, # 'д' + 165: 2, # 'е' + 166: 24, # 'ж' + 167: 20, # 'з' + 168: 4, # 'и' + 169: 23, # 'й' + 170: 11, # 'к' + 171: 8, # 'л' + 172: 12, # 'м' + 173: 5, # 'н' + 174: 1, # 'о' + 175: 15, # 'п' + 176: 191, # 'â–‘' + 177: 192, # 'â–’' + 178: 193, # 'â–“' + 179: 194, # '│' + 180: 195, # '┤' + 181: 196, # 'â•¡' + 182: 197, # 'â•¢' + 183: 198, # 'â•–' + 184: 199, # 'â••' + 185: 200, # 'â•£' + 186: 201, # 'â•‘' + 187: 202, # 'â•—' + 188: 203, # 'â•' + 189: 204, # 'â•œ' + 190: 205, # 'â•›' + 191: 206, # 'â”' + 192: 207, # 'â””' + 193: 208, # 'â”´' + 194: 209, # '┬' + 195: 210, # '├' + 196: 211, # '─' + 197: 212, # '┼' + 198: 213, # 'â•ž' + 199: 214, # 'â•Ÿ' + 200: 215, # 'â•š' + 201: 216, # 'â•”' + 202: 217, # 'â•©' + 203: 218, # '╦' + 204: 219, # 'â• ' + 205: 220, # 'â•' + 206: 221, # '╬' + 207: 222, # '╧' + 208: 223, # '╨' + 209: 224, # '╤' + 210: 225, # 'â•¥' + 211: 226, # 'â•™' + 212: 227, # '╘' + 213: 228, # 'â•’' + 214: 229, # 'â•“' + 215: 230, # 'â•«' + 216: 231, # '╪' + 217: 232, # '┘' + 218: 233, # '┌' + 219: 234, # 'â–ˆ' + 220: 235, # 'â–„' + 221: 236, # 'â–Œ' + 222: 237, # 'â–' + 223: 238, # 'â–€' + 224: 9, # 'Ñ€' + 225: 7, # 'Ñ' + 226: 6, # 'Ñ‚' + 227: 14, # 'у' + 228: 39, # 'Ñ„' + 229: 26, # 'Ñ…' + 230: 28, # 'ц' + 231: 22, # 'ч' + 232: 25, # 'ш' + 233: 29, # 'щ' + 234: 54, # 'ÑŠ' + 235: 18, # 'Ñ‹' + 236: 17, # 'ÑŒ' + 237: 30, # 'Ñ' + 238: 27, # 'ÑŽ' + 239: 16, # 'Ñ' + 240: 239, # 'Ð' + 241: 68, # 'Ñ‘' + 242: 240, # 'Є' + 243: 241, # 'Ñ”' + 244: 242, # 'Ї' + 245: 243, # 'Ñ—' + 246: 244, # 'ÐŽ' + 247: 245, # 'Ñž' + 248: 246, # '°' + 249: 247, # '∙' + 250: 248, # '·' + 251: 249, # '√' + 252: 250, # 'â„–' + 253: 251, # '¤' + 254: 252, # 'â– ' + 255: 255, # '\xa0' +} + +IBM866_RUSSIAN_MODEL = SingleByteCharSetModel(charset_name='IBM866', + language='Russian', + char_to_order_map=IBM866_RUSSIAN_CHAR_TO_ORDER, + language_model=RUSSIAN_LANG_MODEL, + typical_positive_ratio=0.976601, + keep_ascii_letters=False, + alphabet='ÐÐБВГДЕЖЗИЙКЛМÐОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрÑтуфхцчшщъыьÑÑŽÑÑ‘') + +WINDOWS_1251_RUSSIAN_CHAR_TO_ORDER = { + 0: 255, # '\x00' + 1: 255, # '\x01' + 2: 255, # '\x02' + 3: 255, # '\x03' + 4: 255, # '\x04' + 5: 255, # '\x05' + 6: 255, # '\x06' + 7: 255, # '\x07' + 8: 255, # '\x08' + 9: 255, # '\t' + 10: 254, # '\n' + 11: 255, # '\x0b' + 12: 255, # '\x0c' + 13: 254, # '\r' + 14: 255, # '\x0e' + 15: 255, # '\x0f' + 16: 255, # '\x10' + 17: 255, # '\x11' + 18: 255, # '\x12' + 19: 255, # '\x13' + 20: 255, # '\x14' + 21: 255, # '\x15' + 22: 255, # '\x16' + 23: 255, # '\x17' + 24: 255, # '\x18' + 25: 255, # '\x19' + 26: 255, # '\x1a' + 27: 255, # '\x1b' + 28: 255, # '\x1c' + 29: 255, # '\x1d' + 30: 255, # '\x1e' + 31: 255, # '\x1f' + 32: 253, # ' ' + 33: 253, # '!' + 34: 253, # '"' + 35: 253, # '#' + 36: 253, # '$' + 37: 253, # '%' + 38: 253, # '&' + 39: 253, # "'" + 40: 253, # '(' + 41: 253, # ')' + 42: 253, # '*' + 43: 253, # '+' + 44: 253, # ',' + 45: 253, # '-' + 46: 253, # '.' + 47: 253, # '/' + 48: 252, # '0' + 49: 252, # '1' + 50: 252, # '2' + 51: 252, # '3' + 52: 252, # '4' + 53: 252, # '5' + 54: 252, # '6' + 55: 252, # '7' + 56: 252, # '8' + 57: 252, # '9' + 58: 253, # ':' + 59: 253, # ';' + 60: 253, # '<' + 61: 253, # '=' + 62: 253, # '>' + 63: 253, # '?' + 64: 253, # '@' + 65: 142, # 'A' + 66: 143, # 'B' + 67: 144, # 'C' + 68: 145, # 'D' + 69: 146, # 'E' + 70: 147, # 'F' + 71: 148, # 'G' + 72: 149, # 'H' + 73: 150, # 'I' + 74: 151, # 'J' + 75: 152, # 'K' + 76: 74, # 'L' + 77: 153, # 'M' + 78: 75, # 'N' + 79: 154, # 'O' + 80: 155, # 'P' + 81: 156, # 'Q' + 82: 157, # 'R' + 83: 158, # 'S' + 84: 159, # 'T' + 85: 160, # 'U' + 86: 161, # 'V' + 87: 162, # 'W' + 88: 163, # 'X' + 89: 164, # 'Y' + 90: 165, # 'Z' + 91: 253, # '[' + 92: 253, # '\\' + 93: 253, # ']' + 94: 253, # '^' + 95: 253, # '_' + 96: 253, # '`' + 97: 71, # 'a' + 98: 172, # 'b' + 99: 66, # 'c' + 100: 173, # 'd' + 101: 65, # 'e' + 102: 174, # 'f' + 103: 76, # 'g' + 104: 175, # 'h' + 105: 64, # 'i' + 106: 176, # 'j' + 107: 177, # 'k' + 108: 77, # 'l' + 109: 72, # 'm' + 110: 178, # 'n' + 111: 69, # 'o' + 112: 67, # 'p' + 113: 179, # 'q' + 114: 78, # 'r' + 115: 73, # 's' + 116: 180, # 't' + 117: 181, # 'u' + 118: 79, # 'v' + 119: 182, # 'w' + 120: 183, # 'x' + 121: 184, # 'y' + 122: 185, # 'z' + 123: 253, # '{' + 124: 253, # '|' + 125: 253, # '}' + 126: 253, # '~' + 127: 253, # '\x7f' + 128: 191, # 'Ђ' + 129: 192, # 'Ѓ' + 130: 193, # '‚' + 131: 194, # 'Ñ“' + 132: 195, # '„' + 133: 196, # '…' + 134: 197, # '†' + 135: 198, # '‡' + 136: 199, # '€' + 137: 200, # '‰' + 138: 201, # 'Љ' + 139: 202, # '‹' + 140: 203, # 'Њ' + 141: 204, # 'ÐŒ' + 142: 205, # 'Ћ' + 143: 206, # 'Ð' + 144: 207, # 'Ñ’' + 145: 208, # '‘' + 146: 209, # '’' + 147: 210, # '“' + 148: 211, # 'â€' + 149: 212, # '•' + 150: 213, # '–' + 151: 214, # '—' + 152: 215, # None + 153: 216, # 'â„¢' + 154: 217, # 'Ñ™' + 155: 218, # '›' + 156: 219, # 'Ñš' + 157: 220, # 'Ñœ' + 158: 221, # 'Ñ›' + 159: 222, # 'ÑŸ' + 160: 223, # '\xa0' + 161: 224, # 'ÐŽ' + 162: 225, # 'Ñž' + 163: 226, # 'Ј' + 164: 227, # '¤' + 165: 228, # 'Ò' + 166: 229, # '¦' + 167: 230, # '§' + 168: 231, # 'Ð' + 169: 232, # '©' + 170: 233, # 'Є' + 171: 234, # '«' + 172: 235, # '¬' + 173: 236, # '\xad' + 174: 237, # '®' + 175: 238, # 'Ї' + 176: 239, # '°' + 177: 240, # '±' + 178: 241, # 'І' + 179: 242, # 'Ñ–' + 180: 243, # 'Ò‘' + 181: 244, # 'µ' + 182: 245, # '¶' + 183: 246, # '·' + 184: 68, # 'Ñ‘' + 185: 247, # 'â„–' + 186: 248, # 'Ñ”' + 187: 249, # '»' + 188: 250, # 'ј' + 189: 251, # 'Ð…' + 190: 252, # 'Ñ•' + 191: 253, # 'Ñ—' + 192: 37, # 'Ð' + 193: 44, # 'Б' + 194: 33, # 'Ð’' + 195: 46, # 'Г' + 196: 41, # 'Д' + 197: 48, # 'Е' + 198: 56, # 'Ж' + 199: 51, # 'З' + 200: 42, # 'И' + 201: 60, # 'Й' + 202: 36, # 'К' + 203: 49, # 'Л' + 204: 38, # 'Ðœ' + 205: 31, # 'Ð' + 206: 34, # 'О' + 207: 35, # 'П' + 208: 45, # 'Р' + 209: 32, # 'С' + 210: 40, # 'Т' + 211: 52, # 'У' + 212: 53, # 'Ф' + 213: 55, # 'Ð¥' + 214: 58, # 'Ц' + 215: 50, # 'Ч' + 216: 57, # 'Ш' + 217: 63, # 'Щ' + 218: 70, # 'Ъ' + 219: 62, # 'Ы' + 220: 61, # 'Ь' + 221: 47, # 'Э' + 222: 59, # 'Ю' + 223: 43, # 'Я' + 224: 3, # 'а' + 225: 21, # 'б' + 226: 10, # 'в' + 227: 19, # 'г' + 228: 13, # 'д' + 229: 2, # 'е' + 230: 24, # 'ж' + 231: 20, # 'з' + 232: 4, # 'и' + 233: 23, # 'й' + 234: 11, # 'к' + 235: 8, # 'л' + 236: 12, # 'м' + 237: 5, # 'н' + 238: 1, # 'о' + 239: 15, # 'п' + 240: 9, # 'Ñ€' + 241: 7, # 'Ñ' + 242: 6, # 'Ñ‚' + 243: 14, # 'у' + 244: 39, # 'Ñ„' + 245: 26, # 'Ñ…' + 246: 28, # 'ц' + 247: 22, # 'ч' + 248: 25, # 'ш' + 249: 29, # 'щ' + 250: 54, # 'ÑŠ' + 251: 18, # 'Ñ‹' + 252: 17, # 'ÑŒ' + 253: 30, # 'Ñ' + 254: 27, # 'ÑŽ' + 255: 16, # 'Ñ' +} + +WINDOWS_1251_RUSSIAN_MODEL = SingleByteCharSetModel(charset_name='windows-1251', + language='Russian', + char_to_order_map=WINDOWS_1251_RUSSIAN_CHAR_TO_ORDER, + language_model=RUSSIAN_LANG_MODEL, + typical_positive_ratio=0.976601, + keep_ascii_letters=False, + alphabet='ÐÐБВГДЕЖЗИЙКЛМÐОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрÑтуфхцчшщъыьÑÑŽÑÑ‘') + +IBM855_RUSSIAN_CHAR_TO_ORDER = { + 0: 255, # '\x00' + 1: 255, # '\x01' + 2: 255, # '\x02' + 3: 255, # '\x03' + 4: 255, # '\x04' + 5: 255, # '\x05' + 6: 255, # '\x06' + 7: 255, # '\x07' + 8: 255, # '\x08' + 9: 255, # '\t' + 10: 254, # '\n' + 11: 255, # '\x0b' + 12: 255, # '\x0c' + 13: 254, # '\r' + 14: 255, # '\x0e' + 15: 255, # '\x0f' + 16: 255, # '\x10' + 17: 255, # '\x11' + 18: 255, # '\x12' + 19: 255, # '\x13' + 20: 255, # '\x14' + 21: 255, # '\x15' + 22: 255, # '\x16' + 23: 255, # '\x17' + 24: 255, # '\x18' + 25: 255, # '\x19' + 26: 255, # '\x1a' + 27: 255, # '\x1b' + 28: 255, # '\x1c' + 29: 255, # '\x1d' + 30: 255, # '\x1e' + 31: 255, # '\x1f' + 32: 253, # ' ' + 33: 253, # '!' + 34: 253, # '"' + 35: 253, # '#' + 36: 253, # '$' + 37: 253, # '%' + 38: 253, # '&' + 39: 253, # "'" + 40: 253, # '(' + 41: 253, # ')' + 42: 253, # '*' + 43: 253, # '+' + 44: 253, # ',' + 45: 253, # '-' + 46: 253, # '.' + 47: 253, # '/' + 48: 252, # '0' + 49: 252, # '1' + 50: 252, # '2' + 51: 252, # '3' + 52: 252, # '4' + 53: 252, # '5' + 54: 252, # '6' + 55: 252, # '7' + 56: 252, # '8' + 57: 252, # '9' + 58: 253, # ':' + 59: 253, # ';' + 60: 253, # '<' + 61: 253, # '=' + 62: 253, # '>' + 63: 253, # '?' + 64: 253, # '@' + 65: 142, # 'A' + 66: 143, # 'B' + 67: 144, # 'C' + 68: 145, # 'D' + 69: 146, # 'E' + 70: 147, # 'F' + 71: 148, # 'G' + 72: 149, # 'H' + 73: 150, # 'I' + 74: 151, # 'J' + 75: 152, # 'K' + 76: 74, # 'L' + 77: 153, # 'M' + 78: 75, # 'N' + 79: 154, # 'O' + 80: 155, # 'P' + 81: 156, # 'Q' + 82: 157, # 'R' + 83: 158, # 'S' + 84: 159, # 'T' + 85: 160, # 'U' + 86: 161, # 'V' + 87: 162, # 'W' + 88: 163, # 'X' + 89: 164, # 'Y' + 90: 165, # 'Z' + 91: 253, # '[' + 92: 253, # '\\' + 93: 253, # ']' + 94: 253, # '^' + 95: 253, # '_' + 96: 253, # '`' + 97: 71, # 'a' + 98: 172, # 'b' + 99: 66, # 'c' + 100: 173, # 'd' + 101: 65, # 'e' + 102: 174, # 'f' + 103: 76, # 'g' + 104: 175, # 'h' + 105: 64, # 'i' + 106: 176, # 'j' + 107: 177, # 'k' + 108: 77, # 'l' + 109: 72, # 'm' + 110: 178, # 'n' + 111: 69, # 'o' + 112: 67, # 'p' + 113: 179, # 'q' + 114: 78, # 'r' + 115: 73, # 's' + 116: 180, # 't' + 117: 181, # 'u' + 118: 79, # 'v' + 119: 182, # 'w' + 120: 183, # 'x' + 121: 184, # 'y' + 122: 185, # 'z' + 123: 253, # '{' + 124: 253, # '|' + 125: 253, # '}' + 126: 253, # '~' + 127: 253, # '\x7f' + 128: 191, # 'Ñ’' + 129: 192, # 'Ђ' + 130: 193, # 'Ñ“' + 131: 194, # 'Ѓ' + 132: 68, # 'Ñ‘' + 133: 195, # 'Ð' + 134: 196, # 'Ñ”' + 135: 197, # 'Є' + 136: 198, # 'Ñ•' + 137: 199, # 'Ð…' + 138: 200, # 'Ñ–' + 139: 201, # 'І' + 140: 202, # 'Ñ—' + 141: 203, # 'Ї' + 142: 204, # 'ј' + 143: 205, # 'Ј' + 144: 206, # 'Ñ™' + 145: 207, # 'Љ' + 146: 208, # 'Ñš' + 147: 209, # 'Њ' + 148: 210, # 'Ñ›' + 149: 211, # 'Ћ' + 150: 212, # 'Ñœ' + 151: 213, # 'ÐŒ' + 152: 214, # 'Ñž' + 153: 215, # 'ÐŽ' + 154: 216, # 'ÑŸ' + 155: 217, # 'Ð' + 156: 27, # 'ÑŽ' + 157: 59, # 'Ю' + 158: 54, # 'ÑŠ' + 159: 70, # 'Ъ' + 160: 3, # 'а' + 161: 37, # 'Ð' + 162: 21, # 'б' + 163: 44, # 'Б' + 164: 28, # 'ц' + 165: 58, # 'Ц' + 166: 13, # 'д' + 167: 41, # 'Д' + 168: 2, # 'е' + 169: 48, # 'Е' + 170: 39, # 'Ñ„' + 171: 53, # 'Ф' + 172: 19, # 'г' + 173: 46, # 'Г' + 174: 218, # '«' + 175: 219, # '»' + 176: 220, # 'â–‘' + 177: 221, # 'â–’' + 178: 222, # 'â–“' + 179: 223, # '│' + 180: 224, # '┤' + 181: 26, # 'Ñ…' + 182: 55, # 'Ð¥' + 183: 4, # 'и' + 184: 42, # 'И' + 185: 225, # 'â•£' + 186: 226, # 'â•‘' + 187: 227, # 'â•—' + 188: 228, # 'â•' + 189: 23, # 'й' + 190: 60, # 'Й' + 191: 229, # 'â”' + 192: 230, # 'â””' + 193: 231, # 'â”´' + 194: 232, # '┬' + 195: 233, # '├' + 196: 234, # '─' + 197: 235, # '┼' + 198: 11, # 'к' + 199: 36, # 'К' + 200: 236, # 'â•š' + 201: 237, # 'â•”' + 202: 238, # 'â•©' + 203: 239, # '╦' + 204: 240, # 'â• ' + 205: 241, # 'â•' + 206: 242, # '╬' + 207: 243, # '¤' + 208: 8, # 'л' + 209: 49, # 'Л' + 210: 12, # 'м' + 211: 38, # 'Ðœ' + 212: 5, # 'н' + 213: 31, # 'Ð' + 214: 1, # 'о' + 215: 34, # 'О' + 216: 15, # 'п' + 217: 244, # '┘' + 218: 245, # '┌' + 219: 246, # 'â–ˆ' + 220: 247, # 'â–„' + 221: 35, # 'П' + 222: 16, # 'Ñ' + 223: 248, # 'â–€' + 224: 43, # 'Я' + 225: 9, # 'Ñ€' + 226: 45, # 'Р' + 227: 7, # 'Ñ' + 228: 32, # 'С' + 229: 6, # 'Ñ‚' + 230: 40, # 'Т' + 231: 14, # 'у' + 232: 52, # 'У' + 233: 24, # 'ж' + 234: 56, # 'Ж' + 235: 10, # 'в' + 236: 33, # 'Ð’' + 237: 17, # 'ÑŒ' + 238: 61, # 'Ь' + 239: 249, # 'â„–' + 240: 250, # '\xad' + 241: 18, # 'Ñ‹' + 242: 62, # 'Ы' + 243: 20, # 'з' + 244: 51, # 'З' + 245: 25, # 'ш' + 246: 57, # 'Ш' + 247: 30, # 'Ñ' + 248: 47, # 'Э' + 249: 29, # 'щ' + 250: 63, # 'Щ' + 251: 22, # 'ч' + 252: 50, # 'Ч' + 253: 251, # '§' + 254: 252, # 'â– ' + 255: 255, # '\xa0' +} + +IBM855_RUSSIAN_MODEL = SingleByteCharSetModel(charset_name='IBM855', + language='Russian', + char_to_order_map=IBM855_RUSSIAN_CHAR_TO_ORDER, + language_model=RUSSIAN_LANG_MODEL, + typical_positive_ratio=0.976601, + keep_ascii_letters=False, + alphabet='ÐÐБВГДЕЖЗИЙКЛМÐОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрÑтуфхцчшщъыьÑÑŽÑÑ‘') + +KOI8_R_RUSSIAN_CHAR_TO_ORDER = { + 0: 255, # '\x00' + 1: 255, # '\x01' + 2: 255, # '\x02' + 3: 255, # '\x03' + 4: 255, # '\x04' + 5: 255, # '\x05' + 6: 255, # '\x06' + 7: 255, # '\x07' + 8: 255, # '\x08' + 9: 255, # '\t' + 10: 254, # '\n' + 11: 255, # '\x0b' + 12: 255, # '\x0c' + 13: 254, # '\r' + 14: 255, # '\x0e' + 15: 255, # '\x0f' + 16: 255, # '\x10' + 17: 255, # '\x11' + 18: 255, # '\x12' + 19: 255, # '\x13' + 20: 255, # '\x14' + 21: 255, # '\x15' + 22: 255, # '\x16' + 23: 255, # '\x17' + 24: 255, # '\x18' + 25: 255, # '\x19' + 26: 255, # '\x1a' + 27: 255, # '\x1b' + 28: 255, # '\x1c' + 29: 255, # '\x1d' + 30: 255, # '\x1e' + 31: 255, # '\x1f' + 32: 253, # ' ' + 33: 253, # '!' + 34: 253, # '"' + 35: 253, # '#' + 36: 253, # '$' + 37: 253, # '%' + 38: 253, # '&' + 39: 253, # "'" + 40: 253, # '(' + 41: 253, # ')' + 42: 253, # '*' + 43: 253, # '+' + 44: 253, # ',' + 45: 253, # '-' + 46: 253, # '.' + 47: 253, # '/' + 48: 252, # '0' + 49: 252, # '1' + 50: 252, # '2' + 51: 252, # '3' + 52: 252, # '4' + 53: 252, # '5' + 54: 252, # '6' + 55: 252, # '7' + 56: 252, # '8' + 57: 252, # '9' + 58: 253, # ':' + 59: 253, # ';' + 60: 253, # '<' + 61: 253, # '=' + 62: 253, # '>' + 63: 253, # '?' + 64: 253, # '@' + 65: 142, # 'A' + 66: 143, # 'B' + 67: 144, # 'C' + 68: 145, # 'D' + 69: 146, # 'E' + 70: 147, # 'F' + 71: 148, # 'G' + 72: 149, # 'H' + 73: 150, # 'I' + 74: 151, # 'J' + 75: 152, # 'K' + 76: 74, # 'L' + 77: 153, # 'M' + 78: 75, # 'N' + 79: 154, # 'O' + 80: 155, # 'P' + 81: 156, # 'Q' + 82: 157, # 'R' + 83: 158, # 'S' + 84: 159, # 'T' + 85: 160, # 'U' + 86: 161, # 'V' + 87: 162, # 'W' + 88: 163, # 'X' + 89: 164, # 'Y' + 90: 165, # 'Z' + 91: 253, # '[' + 92: 253, # '\\' + 93: 253, # ']' + 94: 253, # '^' + 95: 253, # '_' + 96: 253, # '`' + 97: 71, # 'a' + 98: 172, # 'b' + 99: 66, # 'c' + 100: 173, # 'd' + 101: 65, # 'e' + 102: 174, # 'f' + 103: 76, # 'g' + 104: 175, # 'h' + 105: 64, # 'i' + 106: 176, # 'j' + 107: 177, # 'k' + 108: 77, # 'l' + 109: 72, # 'm' + 110: 178, # 'n' + 111: 69, # 'o' + 112: 67, # 'p' + 113: 179, # 'q' + 114: 78, # 'r' + 115: 73, # 's' + 116: 180, # 't' + 117: 181, # 'u' + 118: 79, # 'v' + 119: 182, # 'w' + 120: 183, # 'x' + 121: 184, # 'y' + 122: 185, # 'z' + 123: 253, # '{' + 124: 253, # '|' + 125: 253, # '}' + 126: 253, # '~' + 127: 253, # '\x7f' + 128: 191, # '─' + 129: 192, # '│' + 130: 193, # '┌' + 131: 194, # 'â”' + 132: 195, # 'â””' + 133: 196, # '┘' + 134: 197, # '├' + 135: 198, # '┤' + 136: 199, # '┬' + 137: 200, # 'â”´' + 138: 201, # '┼' + 139: 202, # 'â–€' + 140: 203, # 'â–„' + 141: 204, # 'â–ˆ' + 142: 205, # 'â–Œ' + 143: 206, # 'â–' + 144: 207, # 'â–‘' + 145: 208, # 'â–’' + 146: 209, # 'â–“' + 147: 210, # '⌠' + 148: 211, # 'â– ' + 149: 212, # '∙' + 150: 213, # '√' + 151: 214, # '≈' + 152: 215, # '≤' + 153: 216, # '≥' + 154: 217, # '\xa0' + 155: 218, # '⌡' + 156: 219, # '°' + 157: 220, # '²' + 158: 221, # '·' + 159: 222, # '÷' + 160: 223, # 'â•' + 161: 224, # 'â•‘' + 162: 225, # 'â•’' + 163: 68, # 'Ñ‘' + 164: 226, # 'â•“' + 165: 227, # 'â•”' + 166: 228, # 'â••' + 167: 229, # 'â•–' + 168: 230, # 'â•—' + 169: 231, # '╘' + 170: 232, # 'â•™' + 171: 233, # 'â•š' + 172: 234, # 'â•›' + 173: 235, # 'â•œ' + 174: 236, # 'â•' + 175: 237, # 'â•ž' + 176: 238, # 'â•Ÿ' + 177: 239, # 'â• ' + 178: 240, # 'â•¡' + 179: 241, # 'Ð' + 180: 242, # 'â•¢' + 181: 243, # 'â•£' + 182: 244, # '╤' + 183: 245, # 'â•¥' + 184: 246, # '╦' + 185: 247, # '╧' + 186: 248, # '╨' + 187: 249, # 'â•©' + 188: 250, # '╪' + 189: 251, # 'â•«' + 190: 252, # '╬' + 191: 253, # '©' + 192: 27, # 'ÑŽ' + 193: 3, # 'а' + 194: 21, # 'б' + 195: 28, # 'ц' + 196: 13, # 'д' + 197: 2, # 'е' + 198: 39, # 'Ñ„' + 199: 19, # 'г' + 200: 26, # 'Ñ…' + 201: 4, # 'и' + 202: 23, # 'й' + 203: 11, # 'к' + 204: 8, # 'л' + 205: 12, # 'м' + 206: 5, # 'н' + 207: 1, # 'о' + 208: 15, # 'п' + 209: 16, # 'Ñ' + 210: 9, # 'Ñ€' + 211: 7, # 'Ñ' + 212: 6, # 'Ñ‚' + 213: 14, # 'у' + 214: 24, # 'ж' + 215: 10, # 'в' + 216: 17, # 'ÑŒ' + 217: 18, # 'Ñ‹' + 218: 20, # 'з' + 219: 25, # 'ш' + 220: 30, # 'Ñ' + 221: 29, # 'щ' + 222: 22, # 'ч' + 223: 54, # 'ÑŠ' + 224: 59, # 'Ю' + 225: 37, # 'Ð' + 226: 44, # 'Б' + 227: 58, # 'Ц' + 228: 41, # 'Д' + 229: 48, # 'Е' + 230: 53, # 'Ф' + 231: 46, # 'Г' + 232: 55, # 'Ð¥' + 233: 42, # 'И' + 234: 60, # 'Й' + 235: 36, # 'К' + 236: 49, # 'Л' + 237: 38, # 'Ðœ' + 238: 31, # 'Ð' + 239: 34, # 'О' + 240: 35, # 'П' + 241: 43, # 'Я' + 242: 45, # 'Р' + 243: 32, # 'С' + 244: 40, # 'Т' + 245: 52, # 'У' + 246: 56, # 'Ж' + 247: 33, # 'Ð’' + 248: 61, # 'Ь' + 249: 62, # 'Ы' + 250: 51, # 'З' + 251: 57, # 'Ш' + 252: 47, # 'Э' + 253: 63, # 'Щ' + 254: 50, # 'Ч' + 255: 70, # 'Ъ' +} + +KOI8_R_RUSSIAN_MODEL = SingleByteCharSetModel(charset_name='KOI8-R', + language='Russian', + char_to_order_map=KOI8_R_RUSSIAN_CHAR_TO_ORDER, + language_model=RUSSIAN_LANG_MODEL, + typical_positive_ratio=0.976601, + keep_ascii_letters=False, + alphabet='ÐÐБВГДЕЖЗИЙКЛМÐОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрÑтуфхцчшщъыьÑÑŽÑÑ‘') + +MACCYRILLIC_RUSSIAN_CHAR_TO_ORDER = { + 0: 255, # '\x00' + 1: 255, # '\x01' + 2: 255, # '\x02' + 3: 255, # '\x03' + 4: 255, # '\x04' + 5: 255, # '\x05' + 6: 255, # '\x06' + 7: 255, # '\x07' + 8: 255, # '\x08' + 9: 255, # '\t' + 10: 254, # '\n' + 11: 255, # '\x0b' + 12: 255, # '\x0c' + 13: 254, # '\r' + 14: 255, # '\x0e' + 15: 255, # '\x0f' + 16: 255, # '\x10' + 17: 255, # '\x11' + 18: 255, # '\x12' + 19: 255, # '\x13' + 20: 255, # '\x14' + 21: 255, # '\x15' + 22: 255, # '\x16' + 23: 255, # '\x17' + 24: 255, # '\x18' + 25: 255, # '\x19' + 26: 255, # '\x1a' + 27: 255, # '\x1b' + 28: 255, # '\x1c' + 29: 255, # '\x1d' + 30: 255, # '\x1e' + 31: 255, # '\x1f' + 32: 253, # ' ' + 33: 253, # '!' + 34: 253, # '"' + 35: 253, # '#' + 36: 253, # '$' + 37: 253, # '%' + 38: 253, # '&' + 39: 253, # "'" + 40: 253, # '(' + 41: 253, # ')' + 42: 253, # '*' + 43: 253, # '+' + 44: 253, # ',' + 45: 253, # '-' + 46: 253, # '.' + 47: 253, # '/' + 48: 252, # '0' + 49: 252, # '1' + 50: 252, # '2' + 51: 252, # '3' + 52: 252, # '4' + 53: 252, # '5' + 54: 252, # '6' + 55: 252, # '7' + 56: 252, # '8' + 57: 252, # '9' + 58: 253, # ':' + 59: 253, # ';' + 60: 253, # '<' + 61: 253, # '=' + 62: 253, # '>' + 63: 253, # '?' + 64: 253, # '@' + 65: 142, # 'A' + 66: 143, # 'B' + 67: 144, # 'C' + 68: 145, # 'D' + 69: 146, # 'E' + 70: 147, # 'F' + 71: 148, # 'G' + 72: 149, # 'H' + 73: 150, # 'I' + 74: 151, # 'J' + 75: 152, # 'K' + 76: 74, # 'L' + 77: 153, # 'M' + 78: 75, # 'N' + 79: 154, # 'O' + 80: 155, # 'P' + 81: 156, # 'Q' + 82: 157, # 'R' + 83: 158, # 'S' + 84: 159, # 'T' + 85: 160, # 'U' + 86: 161, # 'V' + 87: 162, # 'W' + 88: 163, # 'X' + 89: 164, # 'Y' + 90: 165, # 'Z' + 91: 253, # '[' + 92: 253, # '\\' + 93: 253, # ']' + 94: 253, # '^' + 95: 253, # '_' + 96: 253, # '`' + 97: 71, # 'a' + 98: 172, # 'b' + 99: 66, # 'c' + 100: 173, # 'd' + 101: 65, # 'e' + 102: 174, # 'f' + 103: 76, # 'g' + 104: 175, # 'h' + 105: 64, # 'i' + 106: 176, # 'j' + 107: 177, # 'k' + 108: 77, # 'l' + 109: 72, # 'm' + 110: 178, # 'n' + 111: 69, # 'o' + 112: 67, # 'p' + 113: 179, # 'q' + 114: 78, # 'r' + 115: 73, # 's' + 116: 180, # 't' + 117: 181, # 'u' + 118: 79, # 'v' + 119: 182, # 'w' + 120: 183, # 'x' + 121: 184, # 'y' + 122: 185, # 'z' + 123: 253, # '{' + 124: 253, # '|' + 125: 253, # '}' + 126: 253, # '~' + 127: 253, # '\x7f' + 128: 37, # 'Ð' + 129: 44, # 'Б' + 130: 33, # 'Ð’' + 131: 46, # 'Г' + 132: 41, # 'Д' + 133: 48, # 'Е' + 134: 56, # 'Ж' + 135: 51, # 'З' + 136: 42, # 'И' + 137: 60, # 'Й' + 138: 36, # 'К' + 139: 49, # 'Л' + 140: 38, # 'Ðœ' + 141: 31, # 'Ð' + 142: 34, # 'О' + 143: 35, # 'П' + 144: 45, # 'Р' + 145: 32, # 'С' + 146: 40, # 'Т' + 147: 52, # 'У' + 148: 53, # 'Ф' + 149: 55, # 'Ð¥' + 150: 58, # 'Ц' + 151: 50, # 'Ч' + 152: 57, # 'Ш' + 153: 63, # 'Щ' + 154: 70, # 'Ъ' + 155: 62, # 'Ы' + 156: 61, # 'Ь' + 157: 47, # 'Э' + 158: 59, # 'Ю' + 159: 43, # 'Я' + 160: 191, # '†' + 161: 192, # '°' + 162: 193, # 'Ò' + 163: 194, # '£' + 164: 195, # '§' + 165: 196, # '•' + 166: 197, # '¶' + 167: 198, # 'І' + 168: 199, # '®' + 169: 200, # '©' + 170: 201, # 'â„¢' + 171: 202, # 'Ђ' + 172: 203, # 'Ñ’' + 173: 204, # '≠' + 174: 205, # 'Ѓ' + 175: 206, # 'Ñ“' + 176: 207, # '∞' + 177: 208, # '±' + 178: 209, # '≤' + 179: 210, # '≥' + 180: 211, # 'Ñ–' + 181: 212, # 'µ' + 182: 213, # 'Ò‘' + 183: 214, # 'Ј' + 184: 215, # 'Є' + 185: 216, # 'Ñ”' + 186: 217, # 'Ї' + 187: 218, # 'Ñ—' + 188: 219, # 'Љ' + 189: 220, # 'Ñ™' + 190: 221, # 'Њ' + 191: 222, # 'Ñš' + 192: 223, # 'ј' + 193: 224, # 'Ð…' + 194: 225, # '¬' + 195: 226, # '√' + 196: 227, # 'Æ’' + 197: 228, # '≈' + 198: 229, # '∆' + 199: 230, # '«' + 200: 231, # '»' + 201: 232, # '…' + 202: 233, # '\xa0' + 203: 234, # 'Ћ' + 204: 235, # 'Ñ›' + 205: 236, # 'ÐŒ' + 206: 237, # 'Ñœ' + 207: 238, # 'Ñ•' + 208: 239, # '–' + 209: 240, # '—' + 210: 241, # '“' + 211: 242, # 'â€' + 212: 243, # '‘' + 213: 244, # '’' + 214: 245, # '÷' + 215: 246, # '„' + 216: 247, # 'ÐŽ' + 217: 248, # 'Ñž' + 218: 249, # 'Ð' + 219: 250, # 'ÑŸ' + 220: 251, # 'â„–' + 221: 252, # 'Ð' + 222: 68, # 'Ñ‘' + 223: 16, # 'Ñ' + 224: 3, # 'а' + 225: 21, # 'б' + 226: 10, # 'в' + 227: 19, # 'г' + 228: 13, # 'д' + 229: 2, # 'е' + 230: 24, # 'ж' + 231: 20, # 'з' + 232: 4, # 'и' + 233: 23, # 'й' + 234: 11, # 'к' + 235: 8, # 'л' + 236: 12, # 'м' + 237: 5, # 'н' + 238: 1, # 'о' + 239: 15, # 'п' + 240: 9, # 'Ñ€' + 241: 7, # 'Ñ' + 242: 6, # 'Ñ‚' + 243: 14, # 'у' + 244: 39, # 'Ñ„' + 245: 26, # 'Ñ…' + 246: 28, # 'ц' + 247: 22, # 'ч' + 248: 25, # 'ш' + 249: 29, # 'щ' + 250: 54, # 'ÑŠ' + 251: 18, # 'Ñ‹' + 252: 17, # 'ÑŒ' + 253: 30, # 'Ñ' + 254: 27, # 'ÑŽ' + 255: 255, # '€' +} + +MACCYRILLIC_RUSSIAN_MODEL = SingleByteCharSetModel(charset_name='MacCyrillic', + language='Russian', + char_to_order_map=MACCYRILLIC_RUSSIAN_CHAR_TO_ORDER, + language_model=RUSSIAN_LANG_MODEL, + typical_positive_ratio=0.976601, + keep_ascii_letters=False, + alphabet='ÐÐБВГДЕЖЗИЙКЛМÐОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрÑтуфхцчшщъыьÑÑŽÑÑ‘') + +ISO_8859_5_RUSSIAN_CHAR_TO_ORDER = { + 0: 255, # '\x00' + 1: 255, # '\x01' + 2: 255, # '\x02' + 3: 255, # '\x03' + 4: 255, # '\x04' + 5: 255, # '\x05' + 6: 255, # '\x06' + 7: 255, # '\x07' + 8: 255, # '\x08' + 9: 255, # '\t' + 10: 254, # '\n' + 11: 255, # '\x0b' + 12: 255, # '\x0c' + 13: 254, # '\r' + 14: 255, # '\x0e' + 15: 255, # '\x0f' + 16: 255, # '\x10' + 17: 255, # '\x11' + 18: 255, # '\x12' + 19: 255, # '\x13' + 20: 255, # '\x14' + 21: 255, # '\x15' + 22: 255, # '\x16' + 23: 255, # '\x17' + 24: 255, # '\x18' + 25: 255, # '\x19' + 26: 255, # '\x1a' + 27: 255, # '\x1b' + 28: 255, # '\x1c' + 29: 255, # '\x1d' + 30: 255, # '\x1e' + 31: 255, # '\x1f' + 32: 253, # ' ' + 33: 253, # '!' + 34: 253, # '"' + 35: 253, # '#' + 36: 253, # '$' + 37: 253, # '%' + 38: 253, # '&' + 39: 253, # "'" + 40: 253, # '(' + 41: 253, # ')' + 42: 253, # '*' + 43: 253, # '+' + 44: 253, # ',' + 45: 253, # '-' + 46: 253, # '.' + 47: 253, # '/' + 48: 252, # '0' + 49: 252, # '1' + 50: 252, # '2' + 51: 252, # '3' + 52: 252, # '4' + 53: 252, # '5' + 54: 252, # '6' + 55: 252, # '7' + 56: 252, # '8' + 57: 252, # '9' + 58: 253, # ':' + 59: 253, # ';' + 60: 253, # '<' + 61: 253, # '=' + 62: 253, # '>' + 63: 253, # '?' + 64: 253, # '@' + 65: 142, # 'A' + 66: 143, # 'B' + 67: 144, # 'C' + 68: 145, # 'D' + 69: 146, # 'E' + 70: 147, # 'F' + 71: 148, # 'G' + 72: 149, # 'H' + 73: 150, # 'I' + 74: 151, # 'J' + 75: 152, # 'K' + 76: 74, # 'L' + 77: 153, # 'M' + 78: 75, # 'N' + 79: 154, # 'O' + 80: 155, # 'P' + 81: 156, # 'Q' + 82: 157, # 'R' + 83: 158, # 'S' + 84: 159, # 'T' + 85: 160, # 'U' + 86: 161, # 'V' + 87: 162, # 'W' + 88: 163, # 'X' + 89: 164, # 'Y' + 90: 165, # 'Z' + 91: 253, # '[' + 92: 253, # '\\' + 93: 253, # ']' + 94: 253, # '^' + 95: 253, # '_' + 96: 253, # '`' + 97: 71, # 'a' + 98: 172, # 'b' + 99: 66, # 'c' + 100: 173, # 'd' + 101: 65, # 'e' + 102: 174, # 'f' + 103: 76, # 'g' + 104: 175, # 'h' + 105: 64, # 'i' + 106: 176, # 'j' + 107: 177, # 'k' + 108: 77, # 'l' + 109: 72, # 'm' + 110: 178, # 'n' + 111: 69, # 'o' + 112: 67, # 'p' + 113: 179, # 'q' + 114: 78, # 'r' + 115: 73, # 's' + 116: 180, # 't' + 117: 181, # 'u' + 118: 79, # 'v' + 119: 182, # 'w' + 120: 183, # 'x' + 121: 184, # 'y' + 122: 185, # 'z' + 123: 253, # '{' + 124: 253, # '|' + 125: 253, # '}' + 126: 253, # '~' + 127: 253, # '\x7f' + 128: 191, # '\x80' + 129: 192, # '\x81' + 130: 193, # '\x82' + 131: 194, # '\x83' + 132: 195, # '\x84' + 133: 196, # '\x85' + 134: 197, # '\x86' + 135: 198, # '\x87' + 136: 199, # '\x88' + 137: 200, # '\x89' + 138: 201, # '\x8a' + 139: 202, # '\x8b' + 140: 203, # '\x8c' + 141: 204, # '\x8d' + 142: 205, # '\x8e' + 143: 206, # '\x8f' + 144: 207, # '\x90' + 145: 208, # '\x91' + 146: 209, # '\x92' + 147: 210, # '\x93' + 148: 211, # '\x94' + 149: 212, # '\x95' + 150: 213, # '\x96' + 151: 214, # '\x97' + 152: 215, # '\x98' + 153: 216, # '\x99' + 154: 217, # '\x9a' + 155: 218, # '\x9b' + 156: 219, # '\x9c' + 157: 220, # '\x9d' + 158: 221, # '\x9e' + 159: 222, # '\x9f' + 160: 223, # '\xa0' + 161: 224, # 'Ð' + 162: 225, # 'Ђ' + 163: 226, # 'Ѓ' + 164: 227, # 'Є' + 165: 228, # 'Ð…' + 166: 229, # 'І' + 167: 230, # 'Ї' + 168: 231, # 'Ј' + 169: 232, # 'Љ' + 170: 233, # 'Њ' + 171: 234, # 'Ћ' + 172: 235, # 'ÐŒ' + 173: 236, # '\xad' + 174: 237, # 'ÐŽ' + 175: 238, # 'Ð' + 176: 37, # 'Ð' + 177: 44, # 'Б' + 178: 33, # 'Ð’' + 179: 46, # 'Г' + 180: 41, # 'Д' + 181: 48, # 'Е' + 182: 56, # 'Ж' + 183: 51, # 'З' + 184: 42, # 'И' + 185: 60, # 'Й' + 186: 36, # 'К' + 187: 49, # 'Л' + 188: 38, # 'Ðœ' + 189: 31, # 'Ð' + 190: 34, # 'О' + 191: 35, # 'П' + 192: 45, # 'Р' + 193: 32, # 'С' + 194: 40, # 'Т' + 195: 52, # 'У' + 196: 53, # 'Ф' + 197: 55, # 'Ð¥' + 198: 58, # 'Ц' + 199: 50, # 'Ч' + 200: 57, # 'Ш' + 201: 63, # 'Щ' + 202: 70, # 'Ъ' + 203: 62, # 'Ы' + 204: 61, # 'Ь' + 205: 47, # 'Э' + 206: 59, # 'Ю' + 207: 43, # 'Я' + 208: 3, # 'а' + 209: 21, # 'б' + 210: 10, # 'в' + 211: 19, # 'г' + 212: 13, # 'д' + 213: 2, # 'е' + 214: 24, # 'ж' + 215: 20, # 'з' + 216: 4, # 'и' + 217: 23, # 'й' + 218: 11, # 'к' + 219: 8, # 'л' + 220: 12, # 'м' + 221: 5, # 'н' + 222: 1, # 'о' + 223: 15, # 'п' + 224: 9, # 'Ñ€' + 225: 7, # 'Ñ' + 226: 6, # 'Ñ‚' + 227: 14, # 'у' + 228: 39, # 'Ñ„' + 229: 26, # 'Ñ…' + 230: 28, # 'ц' + 231: 22, # 'ч' + 232: 25, # 'ш' + 233: 29, # 'щ' + 234: 54, # 'ÑŠ' + 235: 18, # 'Ñ‹' + 236: 17, # 'ÑŒ' + 237: 30, # 'Ñ' + 238: 27, # 'ÑŽ' + 239: 16, # 'Ñ' + 240: 239, # 'â„–' + 241: 68, # 'Ñ‘' + 242: 240, # 'Ñ’' + 243: 241, # 'Ñ“' + 244: 242, # 'Ñ”' + 245: 243, # 'Ñ•' + 246: 244, # 'Ñ–' + 247: 245, # 'Ñ—' + 248: 246, # 'ј' + 249: 247, # 'Ñ™' + 250: 248, # 'Ñš' + 251: 249, # 'Ñ›' + 252: 250, # 'Ñœ' + 253: 251, # '§' + 254: 252, # 'Ñž' + 255: 255, # 'ÑŸ' +} + +ISO_8859_5_RUSSIAN_MODEL = SingleByteCharSetModel(charset_name='ISO-8859-5', + language='Russian', + char_to_order_map=ISO_8859_5_RUSSIAN_CHAR_TO_ORDER, + language_model=RUSSIAN_LANG_MODEL, + typical_positive_ratio=0.976601, + keep_ascii_letters=False, + alphabet='ÐÐБВГДЕЖЗИЙКЛМÐОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрÑтуфхцчшщъыьÑÑŽÑÑ‘') + diff --git a/venv/Lib/site-packages/pip/_vendor/chardet/langthaimodel.py b/venv/Lib/site-packages/pip/_vendor/chardet/langthaimodel.py new file mode 100644 index 0000000..9a37db5 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/chardet/langthaimodel.py @@ -0,0 +1,4383 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +from pip._vendor.chardet.sbcharsetprober import SingleByteCharSetModel + + +# 3: Positive +# 2: Likely +# 1: Unlikely +# 0: Negative + +THAI_LANG_MODEL = { + 5: { # 'à¸' + 5: 2, # 'à¸' + 30: 2, # 'ข' + 24: 2, # 'ค' + 8: 2, # 'ง' + 26: 2, # 'จ' + 52: 0, # 'ฉ' + 34: 1, # 'ช' + 51: 1, # 'ซ' + 47: 0, # 'à¸' + 58: 3, # 'ฎ' + 57: 2, # 'à¸' + 49: 0, # 'à¸' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 2, # 'ณ' + 20: 2, # 'ด' + 19: 3, # 'ต' + 44: 0, # 'ถ' + 14: 2, # 'ท' + 48: 0, # 'ธ' + 3: 2, # 'น' + 17: 1, # 'บ' + 25: 2, # 'ป' + 39: 1, # 'ผ' + 62: 1, # 'à¸' + 31: 1, # 'พ' + 54: 0, # 'ฟ' + 45: 1, # 'ภ' + 9: 2, # 'ม' + 16: 1, # 'ย' + 2: 3, # 'ร' + 61: 2, # 'ฤ' + 15: 3, # 'ล' + 12: 3, # 'ว' + 42: 2, # 'ศ' + 46: 3, # 'ษ' + 18: 2, # 'ส' + 21: 2, # 'ห' + 4: 3, # 'อ' + 63: 1, # 'ฯ' + 22: 2, # 'ะ' + 10: 3, # 'ั' + 1: 3, # 'า' + 36: 3, # 'ำ' + 23: 3, # 'ิ' + 13: 3, # 'ี' + 40: 0, # 'ึ' + 27: 2, # 'ื' + 32: 2, # 'ุ' + 35: 1, # 'ู' + 11: 2, # 'เ' + 28: 2, # 'à¹' + 41: 1, # 'โ' + 29: 1, # 'ใ' + 33: 2, # 'ไ' + 50: 1, # 'ๆ' + 37: 3, # '็' + 6: 3, # '่' + 7: 3, # '้' + 38: 2, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 30: { # 'ข' + 5: 1, # 'à¸' + 30: 0, # 'ข' + 24: 1, # 'ค' + 8: 1, # 'ง' + 26: 1, # 'จ' + 52: 0, # 'ฉ' + 34: 0, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'à¸' + 58: 0, # 'ฎ' + 57: 0, # 'à¸' + 49: 0, # 'à¸' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 2, # 'ณ' + 20: 0, # 'ด' + 19: 2, # 'ต' + 44: 0, # 'ถ' + 14: 1, # 'ท' + 48: 0, # 'ธ' + 3: 2, # 'น' + 17: 1, # 'บ' + 25: 1, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'à¸' + 31: 0, # 'พ' + 54: 0, # 'ฟ' + 45: 0, # 'ภ' + 9: 0, # 'ม' + 16: 2, # 'ย' + 2: 1, # 'ร' + 61: 0, # 'ฤ' + 15: 0, # 'ล' + 12: 2, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 1, # 'ส' + 21: 1, # 'ห' + 4: 3, # 'อ' + 63: 0, # 'ฯ' + 22: 0, # 'ะ' + 10: 3, # 'ั' + 1: 3, # 'า' + 36: 0, # 'ำ' + 23: 0, # 'ิ' + 13: 2, # 'ี' + 40: 3, # 'ึ' + 27: 1, # 'ื' + 32: 1, # 'ุ' + 35: 0, # 'ู' + 11: 0, # 'เ' + 28: 0, # 'à¹' + 41: 0, # 'โ' + 29: 1, # 'ใ' + 33: 0, # 'ไ' + 50: 0, # 'ๆ' + 37: 1, # '็' + 6: 2, # '่' + 7: 3, # '้' + 38: 1, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 24: { # 'ค' + 5: 0, # 'à¸' + 30: 0, # 'ข' + 24: 2, # 'ค' + 8: 2, # 'ง' + 26: 0, # 'จ' + 52: 0, # 'ฉ' + 34: 0, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'à¸' + 58: 0, # 'ฎ' + 57: 0, # 'à¸' + 49: 0, # 'à¸' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 2, # 'ณ' + 20: 2, # 'ด' + 19: 2, # 'ต' + 44: 0, # 'ถ' + 14: 1, # 'ท' + 48: 0, # 'ธ' + 3: 3, # 'น' + 17: 0, # 'บ' + 25: 1, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'à¸' + 31: 0, # 'พ' + 54: 0, # 'ฟ' + 45: 0, # 'ภ' + 9: 2, # 'ม' + 16: 2, # 'ย' + 2: 3, # 'ร' + 61: 0, # 'ฤ' + 15: 3, # 'ล' + 12: 3, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 1, # 'ส' + 21: 0, # 'ห' + 4: 2, # 'อ' + 63: 0, # 'ฯ' + 22: 2, # 'ะ' + 10: 3, # 'ั' + 1: 2, # 'า' + 36: 3, # 'ำ' + 23: 3, # 'ิ' + 13: 2, # 'ี' + 40: 0, # 'ึ' + 27: 3, # 'ื' + 32: 3, # 'ุ' + 35: 2, # 'ู' + 11: 1, # 'เ' + 28: 0, # 'à¹' + 41: 3, # 'โ' + 29: 0, # 'ใ' + 33: 0, # 'ไ' + 50: 0, # 'ๆ' + 37: 1, # '็' + 6: 3, # '่' + 7: 3, # '้' + 38: 3, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 8: { # 'ง' + 5: 3, # 'à¸' + 30: 2, # 'ข' + 24: 3, # 'ค' + 8: 2, # 'ง' + 26: 2, # 'จ' + 52: 1, # 'ฉ' + 34: 2, # 'ช' + 51: 1, # 'ซ' + 47: 0, # 'à¸' + 58: 0, # 'ฎ' + 57: 0, # 'à¸' + 49: 0, # 'à¸' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 2, # 'ด' + 19: 2, # 'ต' + 44: 1, # 'ถ' + 14: 3, # 'ท' + 48: 1, # 'ธ' + 3: 3, # 'น' + 17: 2, # 'บ' + 25: 2, # 'ป' + 39: 2, # 'ผ' + 62: 1, # 'à¸' + 31: 2, # 'พ' + 54: 0, # 'ฟ' + 45: 1, # 'ภ' + 9: 2, # 'ม' + 16: 1, # 'ย' + 2: 2, # 'ร' + 61: 0, # 'ฤ' + 15: 2, # 'ล' + 12: 2, # 'ว' + 42: 2, # 'ศ' + 46: 1, # 'ษ' + 18: 3, # 'ส' + 21: 3, # 'ห' + 4: 2, # 'อ' + 63: 0, # 'ฯ' + 22: 0, # 'ะ' + 10: 1, # 'ั' + 1: 3, # 'า' + 36: 0, # 'ำ' + 23: 2, # 'ิ' + 13: 1, # 'ี' + 40: 0, # 'ึ' + 27: 1, # 'ื' + 32: 1, # 'ุ' + 35: 0, # 'ู' + 11: 3, # 'เ' + 28: 2, # 'à¹' + 41: 1, # 'โ' + 29: 2, # 'ใ' + 33: 2, # 'ไ' + 50: 3, # 'ๆ' + 37: 0, # '็' + 6: 2, # '่' + 7: 0, # '้' + 38: 0, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 26: { # 'จ' + 5: 2, # 'à¸' + 30: 1, # 'ข' + 24: 0, # 'ค' + 8: 2, # 'ง' + 26: 3, # 'จ' + 52: 0, # 'ฉ' + 34: 0, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'à¸' + 58: 0, # 'ฎ' + 57: 0, # 'à¸' + 49: 0, # 'à¸' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 2, # 'ด' + 19: 1, # 'ต' + 44: 1, # 'ถ' + 14: 2, # 'ท' + 48: 0, # 'ธ' + 3: 3, # 'น' + 17: 1, # 'บ' + 25: 0, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'à¸' + 31: 1, # 'พ' + 54: 0, # 'ฟ' + 45: 0, # 'ภ' + 9: 1, # 'ม' + 16: 1, # 'ย' + 2: 3, # 'ร' + 61: 0, # 'ฤ' + 15: 0, # 'ล' + 12: 1, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 2, # 'ส' + 21: 1, # 'ห' + 4: 2, # 'อ' + 63: 0, # 'ฯ' + 22: 3, # 'ะ' + 10: 3, # 'ั' + 1: 3, # 'า' + 36: 3, # 'ำ' + 23: 2, # 'ิ' + 13: 1, # 'ี' + 40: 3, # 'ึ' + 27: 1, # 'ื' + 32: 3, # 'ุ' + 35: 2, # 'ู' + 11: 1, # 'เ' + 28: 1, # 'à¹' + 41: 0, # 'โ' + 29: 1, # 'ใ' + 33: 1, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 2, # '่' + 7: 2, # '้' + 38: 0, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 52: { # 'ฉ' + 5: 0, # 'à¸' + 30: 0, # 'ข' + 24: 0, # 'ค' + 8: 0, # 'ง' + 26: 0, # 'จ' + 52: 0, # 'ฉ' + 34: 0, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'à¸' + 58: 0, # 'ฎ' + 57: 0, # 'à¸' + 49: 0, # 'à¸' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 0, # 'ด' + 19: 0, # 'ต' + 44: 0, # 'ถ' + 14: 0, # 'ท' + 48: 0, # 'ธ' + 3: 0, # 'น' + 17: 3, # 'บ' + 25: 0, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'à¸' + 31: 3, # 'พ' + 54: 0, # 'ฟ' + 45: 0, # 'ภ' + 9: 1, # 'ม' + 16: 1, # 'ย' + 2: 0, # 'ร' + 61: 0, # 'ฤ' + 15: 2, # 'ล' + 12: 1, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 0, # 'ส' + 21: 0, # 'ห' + 4: 0, # 'อ' + 63: 0, # 'ฯ' + 22: 1, # 'ะ' + 10: 1, # 'ั' + 1: 1, # 'า' + 36: 0, # 'ำ' + 23: 1, # 'ิ' + 13: 1, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 1, # 'ุ' + 35: 0, # 'ู' + 11: 0, # 'เ' + 28: 0, # 'à¹' + 41: 0, # 'โ' + 29: 0, # 'ใ' + 33: 0, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 0, # '่' + 7: 0, # '้' + 38: 0, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 34: { # 'ช' + 5: 1, # 'à¸' + 30: 0, # 'ข' + 24: 0, # 'ค' + 8: 1, # 'ง' + 26: 0, # 'จ' + 52: 0, # 'ฉ' + 34: 0, # 'ช' + 51: 0, # 'ซ' + 47: 1, # 'à¸' + 58: 0, # 'ฎ' + 57: 0, # 'à¸' + 49: 0, # 'à¸' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 0, # 'ด' + 19: 0, # 'ต' + 44: 0, # 'ถ' + 14: 1, # 'ท' + 48: 0, # 'ธ' + 3: 3, # 'น' + 17: 2, # 'บ' + 25: 0, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'à¸' + 31: 0, # 'พ' + 54: 0, # 'ฟ' + 45: 0, # 'ภ' + 9: 2, # 'ม' + 16: 1, # 'ย' + 2: 1, # 'ร' + 61: 0, # 'ฤ' + 15: 0, # 'ล' + 12: 1, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 0, # 'ส' + 21: 0, # 'ห' + 4: 2, # 'อ' + 63: 0, # 'ฯ' + 22: 0, # 'ะ' + 10: 2, # 'ั' + 1: 3, # 'า' + 36: 1, # 'ำ' + 23: 3, # 'ิ' + 13: 2, # 'ี' + 40: 0, # 'ึ' + 27: 3, # 'ื' + 32: 3, # 'ุ' + 35: 1, # 'ู' + 11: 0, # 'เ' + 28: 0, # 'à¹' + 41: 0, # 'โ' + 29: 0, # 'ใ' + 33: 0, # 'ไ' + 50: 0, # 'ๆ' + 37: 1, # '็' + 6: 3, # '่' + 7: 3, # '้' + 38: 0, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 51: { # 'ซ' + 5: 0, # 'à¸' + 30: 0, # 'ข' + 24: 0, # 'ค' + 8: 0, # 'ง' + 26: 0, # 'จ' + 52: 0, # 'ฉ' + 34: 0, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'à¸' + 58: 0, # 'ฎ' + 57: 0, # 'à¸' + 49: 0, # 'à¸' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 0, # 'ด' + 19: 0, # 'ต' + 44: 0, # 'ถ' + 14: 0, # 'ท' + 48: 0, # 'ธ' + 3: 1, # 'น' + 17: 0, # 'บ' + 25: 0, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'à¸' + 31: 0, # 'พ' + 54: 0, # 'ฟ' + 45: 0, # 'ภ' + 9: 0, # 'ม' + 16: 0, # 'ย' + 2: 0, # 'ร' + 61: 0, # 'ฤ' + 15: 1, # 'ล' + 12: 0, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 1, # 'ส' + 21: 0, # 'ห' + 4: 2, # 'อ' + 63: 0, # 'ฯ' + 22: 0, # 'ะ' + 10: 1, # 'ั' + 1: 1, # 'า' + 36: 0, # 'ำ' + 23: 1, # 'ิ' + 13: 2, # 'ี' + 40: 3, # 'ึ' + 27: 2, # 'ื' + 32: 1, # 'ุ' + 35: 1, # 'ู' + 11: 1, # 'เ' + 28: 0, # 'à¹' + 41: 0, # 'โ' + 29: 0, # 'ใ' + 33: 0, # 'ไ' + 50: 0, # 'ๆ' + 37: 1, # '็' + 6: 1, # '่' + 7: 2, # '้' + 38: 1, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 47: { # 'à¸' + 5: 1, # 'à¸' + 30: 1, # 'ข' + 24: 0, # 'ค' + 8: 0, # 'ง' + 26: 0, # 'จ' + 52: 0, # 'ฉ' + 34: 1, # 'ช' + 51: 0, # 'ซ' + 47: 3, # 'à¸' + 58: 0, # 'ฎ' + 57: 0, # 'à¸' + 49: 0, # 'à¸' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 0, # 'ด' + 19: 0, # 'ต' + 44: 0, # 'ถ' + 14: 1, # 'ท' + 48: 0, # 'ธ' + 3: 0, # 'น' + 17: 1, # 'บ' + 25: 1, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'à¸' + 31: 0, # 'พ' + 54: 0, # 'ฟ' + 45: 0, # 'ภ' + 9: 1, # 'ม' + 16: 0, # 'ย' + 2: 0, # 'ร' + 61: 0, # 'ฤ' + 15: 1, # 'ล' + 12: 0, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 1, # 'ส' + 21: 2, # 'ห' + 4: 1, # 'อ' + 63: 0, # 'ฯ' + 22: 1, # 'ะ' + 10: 2, # 'ั' + 1: 3, # 'า' + 36: 0, # 'ำ' + 23: 1, # 'ิ' + 13: 1, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 0, # 'ุ' + 35: 0, # 'ู' + 11: 1, # 'เ' + 28: 1, # 'à¹' + 41: 0, # 'โ' + 29: 1, # 'ใ' + 33: 0, # 'ไ' + 50: 1, # 'ๆ' + 37: 0, # '็' + 6: 2, # '่' + 7: 0, # '้' + 38: 0, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 58: { # 'ฎ' + 5: 2, # 'à¸' + 30: 0, # 'ข' + 24: 0, # 'ค' + 8: 0, # 'ง' + 26: 0, # 'จ' + 52: 0, # 'ฉ' + 34: 0, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'à¸' + 58: 0, # 'ฎ' + 57: 0, # 'à¸' + 49: 0, # 'à¸' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 0, # 'ด' + 19: 0, # 'ต' + 44: 0, # 'ถ' + 14: 0, # 'ท' + 48: 0, # 'ธ' + 3: 0, # 'น' + 17: 0, # 'บ' + 25: 0, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'à¸' + 31: 0, # 'พ' + 54: 0, # 'ฟ' + 45: 0, # 'ภ' + 9: 0, # 'ม' + 16: 0, # 'ย' + 2: 0, # 'ร' + 61: 0, # 'ฤ' + 15: 0, # 'ล' + 12: 0, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 0, # 'ส' + 21: 1, # 'ห' + 4: 0, # 'อ' + 63: 0, # 'ฯ' + 22: 0, # 'ะ' + 10: 0, # 'ั' + 1: 0, # 'า' + 36: 0, # 'ำ' + 23: 1, # 'ิ' + 13: 2, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 0, # 'ุ' + 35: 0, # 'ู' + 11: 0, # 'เ' + 28: 0, # 'à¹' + 41: 0, # 'โ' + 29: 0, # 'ใ' + 33: 0, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 0, # '่' + 7: 0, # '้' + 38: 0, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 57: { # 'à¸' + 5: 0, # 'à¸' + 30: 0, # 'ข' + 24: 0, # 'ค' + 8: 0, # 'ง' + 26: 0, # 'จ' + 52: 0, # 'ฉ' + 34: 0, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'à¸' + 58: 0, # 'ฎ' + 57: 0, # 'à¸' + 49: 0, # 'à¸' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 0, # 'ด' + 19: 0, # 'ต' + 44: 0, # 'ถ' + 14: 0, # 'ท' + 48: 0, # 'ธ' + 3: 0, # 'น' + 17: 0, # 'บ' + 25: 0, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'à¸' + 31: 0, # 'พ' + 54: 0, # 'ฟ' + 45: 0, # 'ภ' + 9: 0, # 'ม' + 16: 0, # 'ย' + 2: 0, # 'ร' + 61: 0, # 'ฤ' + 15: 0, # 'ล' + 12: 0, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 0, # 'ส' + 21: 0, # 'ห' + 4: 0, # 'อ' + 63: 0, # 'ฯ' + 22: 0, # 'ะ' + 10: 0, # 'ั' + 1: 0, # 'า' + 36: 0, # 'ำ' + 23: 3, # 'ิ' + 13: 1, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 0, # 'ุ' + 35: 0, # 'ู' + 11: 0, # 'เ' + 28: 0, # 'à¹' + 41: 0, # 'โ' + 29: 0, # 'ใ' + 33: 0, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 0, # '่' + 7: 0, # '้' + 38: 0, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 49: { # 'à¸' + 5: 1, # 'à¸' + 30: 0, # 'ข' + 24: 0, # 'ค' + 8: 0, # 'ง' + 26: 0, # 'จ' + 52: 0, # 'ฉ' + 34: 0, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'à¸' + 58: 0, # 'ฎ' + 57: 0, # 'à¸' + 49: 0, # 'à¸' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 0, # 'ด' + 19: 0, # 'ต' + 44: 0, # 'ถ' + 14: 0, # 'ท' + 48: 0, # 'ธ' + 3: 0, # 'น' + 17: 2, # 'บ' + 25: 0, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'à¸' + 31: 0, # 'พ' + 54: 0, # 'ฟ' + 45: 0, # 'ภ' + 9: 2, # 'ม' + 16: 0, # 'ย' + 2: 0, # 'ร' + 61: 0, # 'ฤ' + 15: 0, # 'ล' + 12: 0, # 'ว' + 42: 1, # 'ศ' + 46: 0, # 'ษ' + 18: 0, # 'ส' + 21: 0, # 'ห' + 4: 1, # 'อ' + 63: 0, # 'ฯ' + 22: 0, # 'ะ' + 10: 0, # 'ั' + 1: 3, # 'า' + 36: 0, # 'ำ' + 23: 0, # 'ิ' + 13: 0, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 0, # 'ุ' + 35: 0, # 'ู' + 11: 0, # 'เ' + 28: 0, # 'à¹' + 41: 0, # 'โ' + 29: 0, # 'ใ' + 33: 0, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 0, # '่' + 7: 0, # '้' + 38: 1, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 53: { # 'ฑ' + 5: 0, # 'à¸' + 30: 0, # 'ข' + 24: 0, # 'ค' + 8: 0, # 'ง' + 26: 0, # 'จ' + 52: 0, # 'ฉ' + 34: 0, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'à¸' + 58: 0, # 'ฎ' + 57: 0, # 'à¸' + 49: 0, # 'à¸' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 0, # 'ด' + 19: 0, # 'ต' + 44: 0, # 'ถ' + 14: 0, # 'ท' + 48: 0, # 'ธ' + 3: 0, # 'น' + 17: 0, # 'บ' + 25: 0, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'à¸' + 31: 0, # 'พ' + 54: 0, # 'ฟ' + 45: 0, # 'ภ' + 9: 0, # 'ม' + 16: 0, # 'ย' + 2: 0, # 'ร' + 61: 0, # 'ฤ' + 15: 0, # 'ล' + 12: 0, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 0, # 'ส' + 21: 0, # 'ห' + 4: 0, # 'อ' + 63: 0, # 'ฯ' + 22: 0, # 'ะ' + 10: 0, # 'ั' + 1: 0, # 'า' + 36: 0, # 'ำ' + 23: 2, # 'ิ' + 13: 0, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 0, # 'ุ' + 35: 0, # 'ู' + 11: 0, # 'เ' + 28: 0, # 'à¹' + 41: 0, # 'โ' + 29: 0, # 'ใ' + 33: 0, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 0, # '่' + 7: 0, # '้' + 38: 3, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 55: { # 'ฒ' + 5: 0, # 'à¸' + 30: 0, # 'ข' + 24: 0, # 'ค' + 8: 0, # 'ง' + 26: 0, # 'จ' + 52: 0, # 'ฉ' + 34: 0, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'à¸' + 58: 0, # 'ฎ' + 57: 0, # 'à¸' + 49: 0, # 'à¸' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 0, # 'ด' + 19: 0, # 'ต' + 44: 0, # 'ถ' + 14: 0, # 'ท' + 48: 0, # 'ธ' + 3: 3, # 'น' + 17: 0, # 'บ' + 25: 0, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'à¸' + 31: 1, # 'พ' + 54: 0, # 'ฟ' + 45: 0, # 'ภ' + 9: 0, # 'ม' + 16: 0, # 'ย' + 2: 0, # 'ร' + 61: 0, # 'ฤ' + 15: 0, # 'ล' + 12: 0, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 0, # 'ส' + 21: 0, # 'ห' + 4: 0, # 'อ' + 63: 0, # 'ฯ' + 22: 0, # 'ะ' + 10: 0, # 'ั' + 1: 0, # 'า' + 36: 0, # 'ำ' + 23: 1, # 'ิ' + 13: 0, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 0, # 'ุ' + 35: 0, # 'ู' + 11: 0, # 'เ' + 28: 0, # 'à¹' + 41: 0, # 'โ' + 29: 0, # 'ใ' + 33: 0, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 0, # '่' + 7: 0, # '้' + 38: 0, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 43: { # 'ณ' + 5: 1, # 'à¸' + 30: 0, # 'ข' + 24: 0, # 'ค' + 8: 0, # 'ง' + 26: 0, # 'จ' + 52: 0, # 'ฉ' + 34: 0, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'à¸' + 58: 0, # 'ฎ' + 57: 0, # 'à¸' + 49: 0, # 'à¸' + 53: 3, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 0, # 'ด' + 19: 0, # 'ต' + 44: 0, # 'ถ' + 14: 0, # 'ท' + 48: 0, # 'ธ' + 3: 0, # 'น' + 17: 0, # 'บ' + 25: 0, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'à¸' + 31: 0, # 'พ' + 54: 0, # 'ฟ' + 45: 3, # 'ภ' + 9: 0, # 'ม' + 16: 0, # 'ย' + 2: 1, # 'ร' + 61: 0, # 'ฤ' + 15: 0, # 'ล' + 12: 1, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 1, # 'ส' + 21: 1, # 'ห' + 4: 0, # 'อ' + 63: 0, # 'ฯ' + 22: 3, # 'ะ' + 10: 0, # 'ั' + 1: 3, # 'า' + 36: 0, # 'ำ' + 23: 1, # 'ิ' + 13: 2, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 0, # 'ุ' + 35: 0, # 'ู' + 11: 1, # 'เ' + 28: 1, # 'à¹' + 41: 0, # 'โ' + 29: 1, # 'ใ' + 33: 1, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 0, # '่' + 7: 0, # '้' + 38: 3, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 20: { # 'ด' + 5: 2, # 'à¸' + 30: 2, # 'ข' + 24: 2, # 'ค' + 8: 3, # 'ง' + 26: 2, # 'จ' + 52: 0, # 'ฉ' + 34: 1, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'à¸' + 58: 0, # 'ฎ' + 57: 0, # 'à¸' + 49: 0, # 'à¸' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 1, # 'ด' + 19: 2, # 'ต' + 44: 1, # 'ถ' + 14: 2, # 'ท' + 48: 0, # 'ธ' + 3: 1, # 'น' + 17: 1, # 'บ' + 25: 1, # 'ป' + 39: 1, # 'ผ' + 62: 0, # 'à¸' + 31: 1, # 'พ' + 54: 0, # 'ฟ' + 45: 1, # 'ภ' + 9: 2, # 'ม' + 16: 3, # 'ย' + 2: 2, # 'ร' + 61: 0, # 'ฤ' + 15: 2, # 'ล' + 12: 2, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 2, # 'ส' + 21: 2, # 'ห' + 4: 1, # 'อ' + 63: 0, # 'ฯ' + 22: 0, # 'ะ' + 10: 3, # 'ั' + 1: 2, # 'า' + 36: 2, # 'ำ' + 23: 3, # 'ิ' + 13: 3, # 'ี' + 40: 1, # 'ึ' + 27: 2, # 'ื' + 32: 3, # 'ุ' + 35: 2, # 'ู' + 11: 2, # 'เ' + 28: 2, # 'à¹' + 41: 1, # 'โ' + 29: 2, # 'ใ' + 33: 2, # 'ไ' + 50: 2, # 'ๆ' + 37: 2, # '็' + 6: 1, # '่' + 7: 3, # '้' + 38: 1, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 19: { # 'ต' + 5: 2, # 'à¸' + 30: 1, # 'ข' + 24: 1, # 'ค' + 8: 0, # 'ง' + 26: 1, # 'จ' + 52: 0, # 'ฉ' + 34: 1, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'à¸' + 58: 0, # 'ฎ' + 57: 0, # 'à¸' + 49: 0, # 'à¸' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 1, # 'ด' + 19: 1, # 'ต' + 44: 2, # 'ถ' + 14: 1, # 'ท' + 48: 0, # 'ธ' + 3: 2, # 'น' + 17: 1, # 'บ' + 25: 1, # 'ป' + 39: 1, # 'ผ' + 62: 0, # 'à¸' + 31: 1, # 'พ' + 54: 0, # 'ฟ' + 45: 2, # 'ภ' + 9: 1, # 'ม' + 16: 1, # 'ย' + 2: 3, # 'ร' + 61: 0, # 'ฤ' + 15: 2, # 'ล' + 12: 1, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 3, # 'ส' + 21: 0, # 'ห' + 4: 3, # 'อ' + 63: 1, # 'ฯ' + 22: 2, # 'ะ' + 10: 3, # 'ั' + 1: 3, # 'า' + 36: 2, # 'ำ' + 23: 3, # 'ิ' + 13: 2, # 'ี' + 40: 1, # 'ึ' + 27: 1, # 'ื' + 32: 3, # 'ุ' + 35: 2, # 'ู' + 11: 1, # 'เ' + 28: 1, # 'à¹' + 41: 1, # 'โ' + 29: 1, # 'ใ' + 33: 1, # 'ไ' + 50: 0, # 'ๆ' + 37: 2, # '็' + 6: 3, # '่' + 7: 3, # '้' + 38: 2, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 44: { # 'ถ' + 5: 1, # 'à¸' + 30: 0, # 'ข' + 24: 1, # 'ค' + 8: 0, # 'ง' + 26: 1, # 'จ' + 52: 0, # 'ฉ' + 34: 0, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'à¸' + 58: 0, # 'ฎ' + 57: 0, # 'à¸' + 49: 0, # 'à¸' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 0, # 'ด' + 19: 1, # 'ต' + 44: 0, # 'ถ' + 14: 1, # 'ท' + 48: 0, # 'ธ' + 3: 1, # 'น' + 17: 2, # 'บ' + 25: 0, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'à¸' + 31: 1, # 'พ' + 54: 0, # 'ฟ' + 45: 0, # 'ภ' + 9: 0, # 'ม' + 16: 0, # 'ย' + 2: 1, # 'ร' + 61: 0, # 'ฤ' + 15: 1, # 'ล' + 12: 1, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 1, # 'ส' + 21: 0, # 'ห' + 4: 1, # 'อ' + 63: 0, # 'ฯ' + 22: 0, # 'ะ' + 10: 2, # 'ั' + 1: 3, # 'า' + 36: 0, # 'ำ' + 23: 2, # 'ิ' + 13: 1, # 'ี' + 40: 3, # 'ึ' + 27: 2, # 'ื' + 32: 2, # 'ุ' + 35: 3, # 'ู' + 11: 1, # 'เ' + 28: 1, # 'à¹' + 41: 0, # 'โ' + 29: 1, # 'ใ' + 33: 1, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 2, # '่' + 7: 3, # '้' + 38: 0, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 14: { # 'ท' + 5: 1, # 'à¸' + 30: 1, # 'ข' + 24: 3, # 'ค' + 8: 1, # 'ง' + 26: 1, # 'จ' + 52: 0, # 'ฉ' + 34: 0, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'à¸' + 58: 0, # 'ฎ' + 57: 0, # 'à¸' + 49: 0, # 'à¸' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 2, # 'ด' + 19: 1, # 'ต' + 44: 0, # 'ถ' + 14: 1, # 'ท' + 48: 3, # 'ธ' + 3: 3, # 'น' + 17: 2, # 'บ' + 25: 2, # 'ป' + 39: 1, # 'ผ' + 62: 0, # 'à¸' + 31: 2, # 'พ' + 54: 0, # 'ฟ' + 45: 0, # 'ภ' + 9: 1, # 'ม' + 16: 3, # 'ย' + 2: 3, # 'ร' + 61: 1, # 'ฤ' + 15: 1, # 'ล' + 12: 2, # 'ว' + 42: 3, # 'ศ' + 46: 1, # 'ษ' + 18: 1, # 'ส' + 21: 0, # 'ห' + 4: 2, # 'อ' + 63: 0, # 'ฯ' + 22: 2, # 'ะ' + 10: 3, # 'ั' + 1: 3, # 'า' + 36: 3, # 'ำ' + 23: 2, # 'ิ' + 13: 3, # 'ี' + 40: 2, # 'ึ' + 27: 1, # 'ื' + 32: 3, # 'ุ' + 35: 1, # 'ู' + 11: 0, # 'เ' + 28: 1, # 'à¹' + 41: 0, # 'โ' + 29: 1, # 'ใ' + 33: 0, # 'ไ' + 50: 0, # 'ๆ' + 37: 1, # '็' + 6: 3, # '่' + 7: 3, # '้' + 38: 2, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 48: { # 'ธ' + 5: 0, # 'à¸' + 30: 0, # 'ข' + 24: 0, # 'ค' + 8: 1, # 'ง' + 26: 0, # 'จ' + 52: 0, # 'ฉ' + 34: 0, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'à¸' + 58: 0, # 'ฎ' + 57: 0, # 'à¸' + 49: 0, # 'à¸' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 0, # 'ด' + 19: 0, # 'ต' + 44: 0, # 'ถ' + 14: 0, # 'ท' + 48: 0, # 'ธ' + 3: 1, # 'น' + 17: 0, # 'บ' + 25: 0, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'à¸' + 31: 0, # 'พ' + 54: 0, # 'ฟ' + 45: 0, # 'ภ' + 9: 0, # 'ม' + 16: 0, # 'ย' + 2: 2, # 'ร' + 61: 0, # 'ฤ' + 15: 0, # 'ล' + 12: 0, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 0, # 'ส' + 21: 0, # 'ห' + 4: 0, # 'อ' + 63: 0, # 'ฯ' + 22: 0, # 'ะ' + 10: 0, # 'ั' + 1: 2, # 'า' + 36: 0, # 'ำ' + 23: 3, # 'ิ' + 13: 3, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 2, # 'ุ' + 35: 0, # 'ู' + 11: 0, # 'เ' + 28: 0, # 'à¹' + 41: 0, # 'โ' + 29: 0, # 'ใ' + 33: 0, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 0, # '่' + 7: 0, # '้' + 38: 3, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 3: { # 'น' + 5: 3, # 'à¸' + 30: 2, # 'ข' + 24: 3, # 'ค' + 8: 1, # 'ง' + 26: 2, # 'จ' + 52: 0, # 'ฉ' + 34: 1, # 'ช' + 51: 1, # 'ซ' + 47: 0, # 'à¸' + 58: 0, # 'ฎ' + 57: 0, # 'à¸' + 49: 1, # 'à¸' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 3, # 'ด' + 19: 3, # 'ต' + 44: 2, # 'ถ' + 14: 3, # 'ท' + 48: 3, # 'ธ' + 3: 2, # 'น' + 17: 2, # 'บ' + 25: 2, # 'ป' + 39: 2, # 'ผ' + 62: 0, # 'à¸' + 31: 2, # 'พ' + 54: 1, # 'ฟ' + 45: 1, # 'ภ' + 9: 2, # 'ม' + 16: 2, # 'ย' + 2: 2, # 'ร' + 61: 1, # 'ฤ' + 15: 2, # 'ล' + 12: 3, # 'ว' + 42: 1, # 'ศ' + 46: 0, # 'ษ' + 18: 2, # 'ส' + 21: 2, # 'ห' + 4: 3, # 'อ' + 63: 1, # 'ฯ' + 22: 2, # 'ะ' + 10: 3, # 'ั' + 1: 3, # 'า' + 36: 3, # 'ำ' + 23: 3, # 'ิ' + 13: 3, # 'ี' + 40: 3, # 'ึ' + 27: 3, # 'ื' + 32: 3, # 'ุ' + 35: 2, # 'ู' + 11: 3, # 'เ' + 28: 2, # 'à¹' + 41: 3, # 'โ' + 29: 3, # 'ใ' + 33: 3, # 'ไ' + 50: 2, # 'ๆ' + 37: 1, # '็' + 6: 3, # '่' + 7: 3, # '้' + 38: 2, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 17: { # 'บ' + 5: 3, # 'à¸' + 30: 2, # 'ข' + 24: 2, # 'ค' + 8: 1, # 'ง' + 26: 1, # 'จ' + 52: 1, # 'ฉ' + 34: 1, # 'ช' + 51: 1, # 'ซ' + 47: 0, # 'à¸' + 58: 0, # 'ฎ' + 57: 0, # 'à¸' + 49: 0, # 'à¸' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 1, # 'ด' + 19: 2, # 'ต' + 44: 1, # 'ถ' + 14: 3, # 'ท' + 48: 0, # 'ธ' + 3: 3, # 'น' + 17: 3, # 'บ' + 25: 2, # 'ป' + 39: 2, # 'ผ' + 62: 0, # 'à¸' + 31: 1, # 'พ' + 54: 1, # 'ฟ' + 45: 1, # 'ภ' + 9: 1, # 'ม' + 16: 0, # 'ย' + 2: 3, # 'ร' + 61: 0, # 'ฤ' + 15: 2, # 'ล' + 12: 3, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 2, # 'ส' + 21: 2, # 'ห' + 4: 2, # 'อ' + 63: 1, # 'ฯ' + 22: 0, # 'ะ' + 10: 3, # 'ั' + 1: 3, # 'า' + 36: 2, # 'ำ' + 23: 2, # 'ิ' + 13: 2, # 'ี' + 40: 0, # 'ึ' + 27: 2, # 'ื' + 32: 3, # 'ุ' + 35: 2, # 'ู' + 11: 2, # 'เ' + 28: 2, # 'à¹' + 41: 1, # 'โ' + 29: 2, # 'ใ' + 33: 2, # 'ไ' + 50: 0, # 'ๆ' + 37: 1, # '็' + 6: 2, # '่' + 7: 2, # '้' + 38: 0, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 25: { # 'ป' + 5: 2, # 'à¸' + 30: 0, # 'ข' + 24: 1, # 'ค' + 8: 0, # 'ง' + 26: 1, # 'จ' + 52: 0, # 'ฉ' + 34: 0, # 'ช' + 51: 1, # 'ซ' + 47: 0, # 'à¸' + 58: 1, # 'ฎ' + 57: 3, # 'à¸' + 49: 1, # 'à¸' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 1, # 'ด' + 19: 1, # 'ต' + 44: 1, # 'ถ' + 14: 1, # 'ท' + 48: 0, # 'ธ' + 3: 2, # 'น' + 17: 0, # 'บ' + 25: 1, # 'ป' + 39: 1, # 'ผ' + 62: 1, # 'à¸' + 31: 1, # 'พ' + 54: 0, # 'ฟ' + 45: 0, # 'ภ' + 9: 1, # 'ม' + 16: 0, # 'ย' + 2: 3, # 'ร' + 61: 0, # 'ฤ' + 15: 3, # 'ล' + 12: 1, # 'ว' + 42: 0, # 'ศ' + 46: 1, # 'ษ' + 18: 2, # 'ส' + 21: 1, # 'ห' + 4: 2, # 'อ' + 63: 0, # 'ฯ' + 22: 1, # 'ะ' + 10: 3, # 'ั' + 1: 1, # 'า' + 36: 0, # 'ำ' + 23: 2, # 'ิ' + 13: 3, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 1, # 'ุ' + 35: 0, # 'ู' + 11: 1, # 'เ' + 28: 2, # 'à¹' + 41: 0, # 'โ' + 29: 1, # 'ใ' + 33: 2, # 'ไ' + 50: 0, # 'ๆ' + 37: 3, # '็' + 6: 1, # '่' + 7: 2, # '้' + 38: 1, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 39: { # 'ผ' + 5: 1, # 'à¸' + 30: 0, # 'ข' + 24: 0, # 'ค' + 8: 1, # 'ง' + 26: 0, # 'จ' + 52: 0, # 'ฉ' + 34: 0, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'à¸' + 58: 0, # 'ฎ' + 57: 0, # 'à¸' + 49: 0, # 'à¸' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 0, # 'ด' + 19: 0, # 'ต' + 44: 0, # 'ถ' + 14: 0, # 'ท' + 48: 0, # 'ธ' + 3: 2, # 'น' + 17: 0, # 'บ' + 25: 0, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'à¸' + 31: 0, # 'พ' + 54: 0, # 'ฟ' + 45: 0, # 'ภ' + 9: 1, # 'ม' + 16: 2, # 'ย' + 2: 0, # 'ร' + 61: 0, # 'ฤ' + 15: 3, # 'ล' + 12: 0, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 1, # 'ส' + 21: 0, # 'ห' + 4: 0, # 'อ' + 63: 0, # 'ฯ' + 22: 1, # 'ะ' + 10: 1, # 'ั' + 1: 0, # 'า' + 36: 0, # 'ำ' + 23: 2, # 'ิ' + 13: 0, # 'ี' + 40: 0, # 'ึ' + 27: 1, # 'ื' + 32: 0, # 'ุ' + 35: 3, # 'ู' + 11: 0, # 'เ' + 28: 0, # 'à¹' + 41: 0, # 'โ' + 29: 0, # 'ใ' + 33: 0, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 3, # '่' + 7: 1, # '้' + 38: 0, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 62: { # 'à¸' + 5: 0, # 'à¸' + 30: 0, # 'ข' + 24: 0, # 'ค' + 8: 0, # 'ง' + 26: 0, # 'จ' + 52: 0, # 'ฉ' + 34: 0, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'à¸' + 58: 0, # 'ฎ' + 57: 0, # 'à¸' + 49: 0, # 'à¸' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 0, # 'ด' + 19: 0, # 'ต' + 44: 0, # 'ถ' + 14: 0, # 'ท' + 48: 0, # 'ธ' + 3: 1, # 'น' + 17: 0, # 'บ' + 25: 0, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'à¸' + 31: 0, # 'พ' + 54: 0, # 'ฟ' + 45: 0, # 'ภ' + 9: 0, # 'ม' + 16: 0, # 'ย' + 2: 1, # 'ร' + 61: 0, # 'ฤ' + 15: 0, # 'ล' + 12: 0, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 0, # 'ส' + 21: 0, # 'ห' + 4: 0, # 'อ' + 63: 0, # 'ฯ' + 22: 0, # 'ะ' + 10: 1, # 'ั' + 1: 0, # 'า' + 36: 0, # 'ำ' + 23: 0, # 'ิ' + 13: 1, # 'ี' + 40: 2, # 'ึ' + 27: 0, # 'ื' + 32: 0, # 'ุ' + 35: 0, # 'ู' + 11: 0, # 'เ' + 28: 0, # 'à¹' + 41: 0, # 'โ' + 29: 0, # 'ใ' + 33: 0, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 2, # '่' + 7: 1, # '้' + 38: 0, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 31: { # 'พ' + 5: 1, # 'à¸' + 30: 1, # 'ข' + 24: 1, # 'ค' + 8: 1, # 'ง' + 26: 1, # 'จ' + 52: 0, # 'ฉ' + 34: 0, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'à¸' + 58: 0, # 'ฎ' + 57: 0, # 'à¸' + 49: 0, # 'à¸' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 1, # 'ณ' + 20: 1, # 'ด' + 19: 1, # 'ต' + 44: 0, # 'ถ' + 14: 2, # 'ท' + 48: 1, # 'ธ' + 3: 3, # 'น' + 17: 2, # 'บ' + 25: 0, # 'ป' + 39: 1, # 'ผ' + 62: 0, # 'à¸' + 31: 1, # 'พ' + 54: 0, # 'ฟ' + 45: 0, # 'ภ' + 9: 1, # 'ม' + 16: 2, # 'ย' + 2: 3, # 'ร' + 61: 2, # 'ฤ' + 15: 2, # 'ล' + 12: 2, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 1, # 'ส' + 21: 1, # 'ห' + 4: 2, # 'อ' + 63: 1, # 'ฯ' + 22: 0, # 'ะ' + 10: 3, # 'ั' + 1: 3, # 'า' + 36: 0, # 'ำ' + 23: 3, # 'ิ' + 13: 2, # 'ี' + 40: 1, # 'ึ' + 27: 3, # 'ื' + 32: 1, # 'ุ' + 35: 2, # 'ู' + 11: 1, # 'เ' + 28: 1, # 'à¹' + 41: 0, # 'โ' + 29: 1, # 'ใ' + 33: 1, # 'ไ' + 50: 0, # 'ๆ' + 37: 1, # '็' + 6: 0, # '่' + 7: 1, # '้' + 38: 3, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 54: { # 'ฟ' + 5: 0, # 'à¸' + 30: 0, # 'ข' + 24: 0, # 'ค' + 8: 0, # 'ง' + 26: 0, # 'จ' + 52: 0, # 'ฉ' + 34: 1, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'à¸' + 58: 0, # 'ฎ' + 57: 0, # 'à¸' + 49: 0, # 'à¸' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 0, # 'ด' + 19: 1, # 'ต' + 44: 0, # 'ถ' + 14: 1, # 'ท' + 48: 0, # 'ธ' + 3: 0, # 'น' + 17: 0, # 'บ' + 25: 0, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'à¸' + 31: 0, # 'พ' + 54: 2, # 'ฟ' + 45: 0, # 'ภ' + 9: 0, # 'ม' + 16: 0, # 'ย' + 2: 1, # 'ร' + 61: 0, # 'ฤ' + 15: 2, # 'ล' + 12: 0, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 1, # 'ส' + 21: 0, # 'ห' + 4: 1, # 'อ' + 63: 0, # 'ฯ' + 22: 0, # 'ะ' + 10: 2, # 'ั' + 1: 0, # 'า' + 36: 0, # 'ำ' + 23: 1, # 'ิ' + 13: 1, # 'ี' + 40: 0, # 'ึ' + 27: 1, # 'ื' + 32: 1, # 'ุ' + 35: 0, # 'ู' + 11: 0, # 'เ' + 28: 1, # 'à¹' + 41: 0, # 'โ' + 29: 0, # 'ใ' + 33: 0, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 0, # '่' + 7: 2, # '้' + 38: 0, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 45: { # 'ภ' + 5: 0, # 'à¸' + 30: 0, # 'ข' + 24: 1, # 'ค' + 8: 0, # 'ง' + 26: 0, # 'จ' + 52: 0, # 'ฉ' + 34: 0, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'à¸' + 58: 0, # 'ฎ' + 57: 0, # 'à¸' + 49: 0, # 'à¸' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 0, # 'ด' + 19: 0, # 'ต' + 44: 0, # 'ถ' + 14: 3, # 'ท' + 48: 0, # 'ธ' + 3: 0, # 'น' + 17: 0, # 'บ' + 25: 0, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'à¸' + 31: 1, # 'พ' + 54: 0, # 'ฟ' + 45: 0, # 'ภ' + 9: 0, # 'ม' + 16: 0, # 'ย' + 2: 1, # 'ร' + 61: 0, # 'ฤ' + 15: 0, # 'ล' + 12: 0, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 0, # 'ส' + 21: 0, # 'ห' + 4: 0, # 'อ' + 63: 0, # 'ฯ' + 22: 0, # 'ะ' + 10: 3, # 'ั' + 1: 3, # 'า' + 36: 0, # 'ำ' + 23: 1, # 'ิ' + 13: 0, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 0, # 'ุ' + 35: 2, # 'ู' + 11: 0, # 'เ' + 28: 0, # 'à¹' + 41: 0, # 'โ' + 29: 0, # 'ใ' + 33: 0, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 0, # '่' + 7: 0, # '้' + 38: 1, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 9: { # 'ม' + 5: 2, # 'à¸' + 30: 2, # 'ข' + 24: 2, # 'ค' + 8: 2, # 'ง' + 26: 2, # 'จ' + 52: 0, # 'ฉ' + 34: 1, # 'ช' + 51: 1, # 'ซ' + 47: 0, # 'à¸' + 58: 0, # 'ฎ' + 57: 0, # 'à¸' + 49: 0, # 'à¸' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 1, # 'ณ' + 20: 2, # 'ด' + 19: 2, # 'ต' + 44: 1, # 'ถ' + 14: 2, # 'ท' + 48: 1, # 'ธ' + 3: 3, # 'น' + 17: 2, # 'บ' + 25: 2, # 'ป' + 39: 1, # 'ผ' + 62: 0, # 'à¸' + 31: 3, # 'พ' + 54: 0, # 'ฟ' + 45: 1, # 'ภ' + 9: 2, # 'ม' + 16: 1, # 'ย' + 2: 2, # 'ร' + 61: 2, # 'ฤ' + 15: 2, # 'ล' + 12: 2, # 'ว' + 42: 1, # 'ศ' + 46: 1, # 'ษ' + 18: 3, # 'ส' + 21: 3, # 'ห' + 4: 3, # 'อ' + 63: 0, # 'ฯ' + 22: 1, # 'ะ' + 10: 3, # 'ั' + 1: 3, # 'า' + 36: 0, # 'ำ' + 23: 3, # 'ิ' + 13: 3, # 'ี' + 40: 0, # 'ึ' + 27: 3, # 'ื' + 32: 3, # 'ุ' + 35: 3, # 'ู' + 11: 2, # 'เ' + 28: 2, # 'à¹' + 41: 2, # 'โ' + 29: 2, # 'ใ' + 33: 2, # 'ไ' + 50: 1, # 'ๆ' + 37: 1, # '็' + 6: 3, # '่' + 7: 2, # '้' + 38: 1, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 16: { # 'ย' + 5: 3, # 'à¸' + 30: 1, # 'ข' + 24: 2, # 'ค' + 8: 3, # 'ง' + 26: 2, # 'จ' + 52: 0, # 'ฉ' + 34: 2, # 'ช' + 51: 0, # 'ซ' + 47: 2, # 'à¸' + 58: 0, # 'ฎ' + 57: 0, # 'à¸' + 49: 0, # 'à¸' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 2, # 'ด' + 19: 2, # 'ต' + 44: 1, # 'ถ' + 14: 2, # 'ท' + 48: 1, # 'ธ' + 3: 3, # 'น' + 17: 3, # 'บ' + 25: 1, # 'ป' + 39: 1, # 'ผ' + 62: 0, # 'à¸' + 31: 1, # 'พ' + 54: 0, # 'ฟ' + 45: 1, # 'ภ' + 9: 2, # 'ม' + 16: 0, # 'ย' + 2: 2, # 'ร' + 61: 0, # 'ฤ' + 15: 1, # 'ล' + 12: 3, # 'ว' + 42: 1, # 'ศ' + 46: 0, # 'ษ' + 18: 2, # 'ส' + 21: 1, # 'ห' + 4: 2, # 'อ' + 63: 0, # 'ฯ' + 22: 2, # 'ะ' + 10: 3, # 'ั' + 1: 3, # 'า' + 36: 0, # 'ำ' + 23: 2, # 'ิ' + 13: 3, # 'ี' + 40: 1, # 'ึ' + 27: 2, # 'ื' + 32: 2, # 'ุ' + 35: 3, # 'ู' + 11: 2, # 'เ' + 28: 1, # 'à¹' + 41: 1, # 'โ' + 29: 2, # 'ใ' + 33: 2, # 'ไ' + 50: 2, # 'ๆ' + 37: 1, # '็' + 6: 3, # '่' + 7: 2, # '้' + 38: 3, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 2: { # 'ร' + 5: 3, # 'à¸' + 30: 2, # 'ข' + 24: 2, # 'ค' + 8: 3, # 'ง' + 26: 2, # 'จ' + 52: 0, # 'ฉ' + 34: 2, # 'ช' + 51: 1, # 'ซ' + 47: 0, # 'à¸' + 58: 0, # 'ฎ' + 57: 0, # 'à¸' + 49: 3, # 'à¸' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 3, # 'ณ' + 20: 2, # 'ด' + 19: 2, # 'ต' + 44: 3, # 'ถ' + 14: 3, # 'ท' + 48: 1, # 'ธ' + 3: 2, # 'น' + 17: 2, # 'บ' + 25: 3, # 'ป' + 39: 2, # 'ผ' + 62: 1, # 'à¸' + 31: 2, # 'พ' + 54: 1, # 'ฟ' + 45: 1, # 'ภ' + 9: 3, # 'ม' + 16: 2, # 'ย' + 2: 3, # 'ร' + 61: 0, # 'ฤ' + 15: 2, # 'ล' + 12: 3, # 'ว' + 42: 2, # 'ศ' + 46: 2, # 'ษ' + 18: 2, # 'ส' + 21: 2, # 'ห' + 4: 3, # 'อ' + 63: 1, # 'ฯ' + 22: 3, # 'ะ' + 10: 3, # 'ั' + 1: 3, # 'า' + 36: 0, # 'ำ' + 23: 3, # 'ิ' + 13: 3, # 'ี' + 40: 2, # 'ึ' + 27: 3, # 'ื' + 32: 3, # 'ุ' + 35: 3, # 'ู' + 11: 3, # 'เ' + 28: 3, # 'à¹' + 41: 1, # 'โ' + 29: 2, # 'ใ' + 33: 1, # 'ไ' + 50: 0, # 'ๆ' + 37: 3, # '็' + 6: 3, # '่' + 7: 3, # '้' + 38: 3, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 61: { # 'ฤ' + 5: 0, # 'à¸' + 30: 0, # 'ข' + 24: 0, # 'ค' + 8: 0, # 'ง' + 26: 0, # 'จ' + 52: 0, # 'ฉ' + 34: 0, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'à¸' + 58: 0, # 'ฎ' + 57: 0, # 'à¸' + 49: 0, # 'à¸' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 0, # 'ด' + 19: 2, # 'ต' + 44: 0, # 'ถ' + 14: 2, # 'ท' + 48: 0, # 'ธ' + 3: 0, # 'น' + 17: 0, # 'บ' + 25: 0, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'à¸' + 31: 0, # 'พ' + 54: 0, # 'ฟ' + 45: 0, # 'ภ' + 9: 1, # 'ม' + 16: 0, # 'ย' + 2: 0, # 'ร' + 61: 0, # 'ฤ' + 15: 0, # 'ล' + 12: 0, # 'ว' + 42: 0, # 'ศ' + 46: 2, # 'ษ' + 18: 0, # 'ส' + 21: 0, # 'ห' + 4: 0, # 'อ' + 63: 0, # 'ฯ' + 22: 0, # 'ะ' + 10: 0, # 'ั' + 1: 0, # 'า' + 36: 0, # 'ำ' + 23: 0, # 'ิ' + 13: 0, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 0, # 'ุ' + 35: 0, # 'ู' + 11: 0, # 'เ' + 28: 0, # 'à¹' + 41: 0, # 'โ' + 29: 0, # 'ใ' + 33: 0, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 0, # '่' + 7: 0, # '้' + 38: 0, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 15: { # 'ล' + 5: 2, # 'à¸' + 30: 3, # 'ข' + 24: 1, # 'ค' + 8: 3, # 'ง' + 26: 1, # 'จ' + 52: 0, # 'ฉ' + 34: 1, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'à¸' + 58: 0, # 'ฎ' + 57: 0, # 'à¸' + 49: 0, # 'à¸' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 2, # 'ด' + 19: 2, # 'ต' + 44: 1, # 'ถ' + 14: 2, # 'ท' + 48: 0, # 'ธ' + 3: 1, # 'น' + 17: 2, # 'บ' + 25: 2, # 'ป' + 39: 1, # 'ผ' + 62: 0, # 'à¸' + 31: 0, # 'พ' + 54: 0, # 'ฟ' + 45: 1, # 'ภ' + 9: 1, # 'ม' + 16: 3, # 'ย' + 2: 1, # 'ร' + 61: 0, # 'ฤ' + 15: 1, # 'ล' + 12: 1, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 2, # 'ส' + 21: 1, # 'ห' + 4: 3, # 'อ' + 63: 2, # 'ฯ' + 22: 3, # 'ะ' + 10: 3, # 'ั' + 1: 3, # 'า' + 36: 2, # 'ำ' + 23: 3, # 'ิ' + 13: 3, # 'ี' + 40: 2, # 'ึ' + 27: 3, # 'ื' + 32: 2, # 'ุ' + 35: 3, # 'ู' + 11: 2, # 'เ' + 28: 1, # 'à¹' + 41: 1, # 'โ' + 29: 2, # 'ใ' + 33: 1, # 'ไ' + 50: 0, # 'ๆ' + 37: 2, # '็' + 6: 3, # '่' + 7: 3, # '้' + 38: 2, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 12: { # 'ว' + 5: 3, # 'à¸' + 30: 2, # 'ข' + 24: 1, # 'ค' + 8: 3, # 'ง' + 26: 2, # 'จ' + 52: 0, # 'ฉ' + 34: 1, # 'ช' + 51: 1, # 'ซ' + 47: 0, # 'à¸' + 58: 0, # 'ฎ' + 57: 0, # 'à¸' + 49: 0, # 'à¸' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 1, # 'ณ' + 20: 2, # 'ด' + 19: 1, # 'ต' + 44: 1, # 'ถ' + 14: 1, # 'ท' + 48: 0, # 'ธ' + 3: 3, # 'น' + 17: 2, # 'บ' + 25: 1, # 'ป' + 39: 1, # 'ผ' + 62: 0, # 'à¸' + 31: 1, # 'พ' + 54: 1, # 'ฟ' + 45: 0, # 'ภ' + 9: 3, # 'ม' + 16: 3, # 'ย' + 2: 3, # 'ร' + 61: 0, # 'ฤ' + 15: 3, # 'ล' + 12: 1, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 2, # 'ส' + 21: 2, # 'ห' + 4: 2, # 'อ' + 63: 0, # 'ฯ' + 22: 2, # 'ะ' + 10: 3, # 'ั' + 1: 3, # 'า' + 36: 0, # 'ำ' + 23: 3, # 'ิ' + 13: 2, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 2, # 'ุ' + 35: 0, # 'ู' + 11: 3, # 'เ' + 28: 2, # 'à¹' + 41: 1, # 'โ' + 29: 1, # 'ใ' + 33: 2, # 'ไ' + 50: 1, # 'ๆ' + 37: 0, # '็' + 6: 3, # '่' + 7: 3, # '้' + 38: 1, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 42: { # 'ศ' + 5: 1, # 'à¸' + 30: 0, # 'ข' + 24: 1, # 'ค' + 8: 0, # 'ง' + 26: 1, # 'จ' + 52: 0, # 'ฉ' + 34: 0, # 'ช' + 51: 0, # 'ซ' + 47: 1, # 'à¸' + 58: 0, # 'ฎ' + 57: 0, # 'à¸' + 49: 0, # 'à¸' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 0, # 'ด' + 19: 1, # 'ต' + 44: 0, # 'ถ' + 14: 1, # 'ท' + 48: 0, # 'ธ' + 3: 2, # 'น' + 17: 0, # 'บ' + 25: 0, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'à¸' + 31: 0, # 'พ' + 54: 0, # 'ฟ' + 45: 0, # 'ภ' + 9: 0, # 'ม' + 16: 0, # 'ย' + 2: 2, # 'ร' + 61: 0, # 'ฤ' + 15: 0, # 'ล' + 12: 2, # 'ว' + 42: 1, # 'ศ' + 46: 2, # 'ษ' + 18: 1, # 'ส' + 21: 0, # 'ห' + 4: 0, # 'อ' + 63: 0, # 'ฯ' + 22: 0, # 'ะ' + 10: 2, # 'ั' + 1: 3, # 'า' + 36: 0, # 'ำ' + 23: 2, # 'ิ' + 13: 0, # 'ี' + 40: 3, # 'ึ' + 27: 0, # 'ื' + 32: 0, # 'ุ' + 35: 2, # 'ู' + 11: 0, # 'เ' + 28: 1, # 'à¹' + 41: 0, # 'โ' + 29: 1, # 'ใ' + 33: 1, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 0, # '่' + 7: 0, # '้' + 38: 1, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 46: { # 'ษ' + 5: 0, # 'à¸' + 30: 0, # 'ข' + 24: 0, # 'ค' + 8: 0, # 'ง' + 26: 0, # 'จ' + 52: 0, # 'ฉ' + 34: 0, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'à¸' + 58: 2, # 'ฎ' + 57: 1, # 'à¸' + 49: 2, # 'à¸' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 3, # 'ณ' + 20: 0, # 'ด' + 19: 1, # 'ต' + 44: 0, # 'ถ' + 14: 1, # 'ท' + 48: 0, # 'ธ' + 3: 0, # 'น' + 17: 0, # 'บ' + 25: 0, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'à¸' + 31: 0, # 'พ' + 54: 0, # 'ฟ' + 45: 1, # 'ภ' + 9: 1, # 'ม' + 16: 2, # 'ย' + 2: 2, # 'ร' + 61: 0, # 'ฤ' + 15: 0, # 'ล' + 12: 0, # 'ว' + 42: 1, # 'ศ' + 46: 0, # 'ษ' + 18: 0, # 'ส' + 21: 0, # 'ห' + 4: 0, # 'อ' + 63: 0, # 'ฯ' + 22: 2, # 'ะ' + 10: 2, # 'ั' + 1: 3, # 'า' + 36: 0, # 'ำ' + 23: 0, # 'ิ' + 13: 1, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 0, # 'ุ' + 35: 0, # 'ู' + 11: 1, # 'เ' + 28: 0, # 'à¹' + 41: 0, # 'โ' + 29: 0, # 'ใ' + 33: 0, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 0, # '่' + 7: 0, # '้' + 38: 2, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 18: { # 'ส' + 5: 2, # 'à¸' + 30: 0, # 'ข' + 24: 0, # 'ค' + 8: 2, # 'ง' + 26: 1, # 'จ' + 52: 0, # 'ฉ' + 34: 0, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'à¸' + 58: 0, # 'ฎ' + 57: 0, # 'à¸' + 49: 0, # 'à¸' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 3, # 'ด' + 19: 3, # 'ต' + 44: 3, # 'ถ' + 14: 0, # 'ท' + 48: 0, # 'ธ' + 3: 3, # 'น' + 17: 2, # 'บ' + 25: 1, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'à¸' + 31: 0, # 'พ' + 54: 0, # 'ฟ' + 45: 2, # 'ภ' + 9: 3, # 'ม' + 16: 1, # 'ย' + 2: 3, # 'ร' + 61: 0, # 'ฤ' + 15: 1, # 'ล' + 12: 2, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 0, # 'ส' + 21: 2, # 'ห' + 4: 3, # 'อ' + 63: 0, # 'ฯ' + 22: 2, # 'ะ' + 10: 3, # 'ั' + 1: 3, # 'า' + 36: 3, # 'ำ' + 23: 3, # 'ิ' + 13: 3, # 'ี' + 40: 2, # 'ึ' + 27: 3, # 'ื' + 32: 3, # 'ุ' + 35: 3, # 'ู' + 11: 2, # 'เ' + 28: 0, # 'à¹' + 41: 1, # 'โ' + 29: 0, # 'ใ' + 33: 1, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 3, # '่' + 7: 1, # '้' + 38: 2, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 21: { # 'ห' + 5: 3, # 'à¸' + 30: 0, # 'ข' + 24: 0, # 'ค' + 8: 1, # 'ง' + 26: 0, # 'จ' + 52: 0, # 'ฉ' + 34: 0, # 'ช' + 51: 0, # 'ซ' + 47: 2, # 'à¸' + 58: 0, # 'ฎ' + 57: 0, # 'à¸' + 49: 0, # 'à¸' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 1, # 'ด' + 19: 3, # 'ต' + 44: 0, # 'ถ' + 14: 0, # 'ท' + 48: 0, # 'ธ' + 3: 3, # 'น' + 17: 0, # 'บ' + 25: 1, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'à¸' + 31: 1, # 'พ' + 54: 0, # 'ฟ' + 45: 0, # 'ภ' + 9: 3, # 'ม' + 16: 2, # 'ย' + 2: 3, # 'ร' + 61: 0, # 'ฤ' + 15: 3, # 'ล' + 12: 2, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 0, # 'ส' + 21: 0, # 'ห' + 4: 3, # 'อ' + 63: 0, # 'ฯ' + 22: 1, # 'ะ' + 10: 3, # 'ั' + 1: 3, # 'า' + 36: 0, # 'ำ' + 23: 1, # 'ิ' + 13: 1, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 1, # 'ุ' + 35: 1, # 'ู' + 11: 0, # 'เ' + 28: 0, # 'à¹' + 41: 0, # 'โ' + 29: 0, # 'ใ' + 33: 0, # 'ไ' + 50: 0, # 'ๆ' + 37: 3, # '็' + 6: 3, # '่' + 7: 3, # '้' + 38: 2, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 4: { # 'อ' + 5: 3, # 'à¸' + 30: 1, # 'ข' + 24: 2, # 'ค' + 8: 3, # 'ง' + 26: 1, # 'จ' + 52: 0, # 'ฉ' + 34: 1, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'à¸' + 58: 0, # 'ฎ' + 57: 0, # 'à¸' + 49: 0, # 'à¸' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 3, # 'ด' + 19: 2, # 'ต' + 44: 1, # 'ถ' + 14: 2, # 'ท' + 48: 1, # 'ธ' + 3: 3, # 'น' + 17: 3, # 'บ' + 25: 1, # 'ป' + 39: 1, # 'ผ' + 62: 0, # 'à¸' + 31: 1, # 'พ' + 54: 1, # 'ฟ' + 45: 1, # 'ภ' + 9: 3, # 'ม' + 16: 3, # 'ย' + 2: 3, # 'ร' + 61: 0, # 'ฤ' + 15: 2, # 'ล' + 12: 2, # 'ว' + 42: 1, # 'ศ' + 46: 0, # 'ษ' + 18: 2, # 'ส' + 21: 2, # 'ห' + 4: 3, # 'อ' + 63: 0, # 'ฯ' + 22: 2, # 'ะ' + 10: 3, # 'ั' + 1: 3, # 'า' + 36: 2, # 'ำ' + 23: 2, # 'ิ' + 13: 3, # 'ี' + 40: 0, # 'ึ' + 27: 3, # 'ื' + 32: 3, # 'ุ' + 35: 0, # 'ู' + 11: 3, # 'เ' + 28: 1, # 'à¹' + 41: 1, # 'โ' + 29: 2, # 'ใ' + 33: 2, # 'ไ' + 50: 1, # 'ๆ' + 37: 1, # '็' + 6: 2, # '่' + 7: 2, # '้' + 38: 0, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 63: { # 'ฯ' + 5: 0, # 'à¸' + 30: 0, # 'ข' + 24: 0, # 'ค' + 8: 0, # 'ง' + 26: 0, # 'จ' + 52: 0, # 'ฉ' + 34: 0, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'à¸' + 58: 0, # 'ฎ' + 57: 0, # 'à¸' + 49: 0, # 'à¸' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 0, # 'ด' + 19: 0, # 'ต' + 44: 0, # 'ถ' + 14: 0, # 'ท' + 48: 0, # 'ธ' + 3: 0, # 'น' + 17: 0, # 'บ' + 25: 0, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'à¸' + 31: 0, # 'พ' + 54: 0, # 'ฟ' + 45: 0, # 'ภ' + 9: 0, # 'ม' + 16: 0, # 'ย' + 2: 0, # 'ร' + 61: 0, # 'ฤ' + 15: 2, # 'ล' + 12: 0, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 0, # 'ส' + 21: 0, # 'ห' + 4: 0, # 'อ' + 63: 0, # 'ฯ' + 22: 0, # 'ะ' + 10: 0, # 'ั' + 1: 0, # 'า' + 36: 0, # 'ำ' + 23: 0, # 'ิ' + 13: 0, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 0, # 'ุ' + 35: 0, # 'ู' + 11: 0, # 'เ' + 28: 0, # 'à¹' + 41: 0, # 'โ' + 29: 0, # 'ใ' + 33: 0, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 0, # '่' + 7: 0, # '้' + 38: 0, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 22: { # 'ะ' + 5: 3, # 'à¸' + 30: 1, # 'ข' + 24: 2, # 'ค' + 8: 1, # 'ง' + 26: 2, # 'จ' + 52: 0, # 'ฉ' + 34: 3, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'à¸' + 58: 0, # 'ฎ' + 57: 0, # 'à¸' + 49: 0, # 'à¸' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 3, # 'ด' + 19: 3, # 'ต' + 44: 1, # 'ถ' + 14: 3, # 'ท' + 48: 1, # 'ธ' + 3: 2, # 'น' + 17: 3, # 'บ' + 25: 2, # 'ป' + 39: 1, # 'ผ' + 62: 0, # 'à¸' + 31: 2, # 'พ' + 54: 0, # 'ฟ' + 45: 1, # 'ภ' + 9: 3, # 'ม' + 16: 2, # 'ย' + 2: 2, # 'ร' + 61: 0, # 'ฤ' + 15: 2, # 'ล' + 12: 2, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 3, # 'ส' + 21: 3, # 'ห' + 4: 2, # 'อ' + 63: 1, # 'ฯ' + 22: 1, # 'ะ' + 10: 0, # 'ั' + 1: 0, # 'า' + 36: 0, # 'ำ' + 23: 0, # 'ิ' + 13: 0, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 0, # 'ุ' + 35: 0, # 'ู' + 11: 3, # 'เ' + 28: 2, # 'à¹' + 41: 1, # 'โ' + 29: 2, # 'ใ' + 33: 2, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 0, # '่' + 7: 0, # '้' + 38: 0, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 10: { # 'ั' + 5: 3, # 'à¸' + 30: 0, # 'ข' + 24: 1, # 'ค' + 8: 3, # 'ง' + 26: 3, # 'จ' + 52: 0, # 'ฉ' + 34: 1, # 'ช' + 51: 0, # 'ซ' + 47: 3, # 'à¸' + 58: 0, # 'ฎ' + 57: 0, # 'à¸' + 49: 2, # 'à¸' + 53: 0, # 'ฑ' + 55: 3, # 'ฒ' + 43: 3, # 'ณ' + 20: 3, # 'ด' + 19: 3, # 'ต' + 44: 0, # 'ถ' + 14: 2, # 'ท' + 48: 0, # 'ธ' + 3: 3, # 'น' + 17: 3, # 'บ' + 25: 1, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'à¸' + 31: 2, # 'พ' + 54: 0, # 'ฟ' + 45: 0, # 'ภ' + 9: 3, # 'ม' + 16: 3, # 'ย' + 2: 0, # 'ร' + 61: 0, # 'ฤ' + 15: 2, # 'ล' + 12: 3, # 'ว' + 42: 2, # 'ศ' + 46: 0, # 'ษ' + 18: 3, # 'ส' + 21: 0, # 'ห' + 4: 0, # 'อ' + 63: 0, # 'ฯ' + 22: 0, # 'ะ' + 10: 0, # 'ั' + 1: 0, # 'า' + 36: 0, # 'ำ' + 23: 0, # 'ิ' + 13: 0, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 0, # 'ุ' + 35: 0, # 'ู' + 11: 0, # 'เ' + 28: 0, # 'à¹' + 41: 0, # 'โ' + 29: 0, # 'ใ' + 33: 0, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 3, # '่' + 7: 3, # '้' + 38: 0, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 1: { # 'า' + 5: 3, # 'à¸' + 30: 2, # 'ข' + 24: 3, # 'ค' + 8: 3, # 'ง' + 26: 3, # 'จ' + 52: 0, # 'ฉ' + 34: 3, # 'ช' + 51: 1, # 'ซ' + 47: 2, # 'à¸' + 58: 0, # 'ฎ' + 57: 0, # 'à¸' + 49: 0, # 'à¸' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 3, # 'ณ' + 20: 3, # 'ด' + 19: 3, # 'ต' + 44: 1, # 'ถ' + 14: 3, # 'ท' + 48: 2, # 'ธ' + 3: 3, # 'น' + 17: 3, # 'บ' + 25: 2, # 'ป' + 39: 1, # 'ผ' + 62: 1, # 'à¸' + 31: 3, # 'พ' + 54: 1, # 'ฟ' + 45: 1, # 'ภ' + 9: 3, # 'ม' + 16: 3, # 'ย' + 2: 3, # 'ร' + 61: 0, # 'ฤ' + 15: 3, # 'ล' + 12: 3, # 'ว' + 42: 2, # 'ศ' + 46: 3, # 'ษ' + 18: 3, # 'ส' + 21: 3, # 'ห' + 4: 2, # 'อ' + 63: 1, # 'ฯ' + 22: 3, # 'ะ' + 10: 0, # 'ั' + 1: 0, # 'า' + 36: 0, # 'ำ' + 23: 0, # 'ิ' + 13: 0, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 0, # 'ุ' + 35: 0, # 'ู' + 11: 3, # 'เ' + 28: 2, # 'à¹' + 41: 1, # 'โ' + 29: 2, # 'ใ' + 33: 2, # 'ไ' + 50: 1, # 'ๆ' + 37: 0, # '็' + 6: 0, # '่' + 7: 0, # '้' + 38: 0, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 36: { # 'ำ' + 5: 2, # 'à¸' + 30: 1, # 'ข' + 24: 3, # 'ค' + 8: 2, # 'ง' + 26: 1, # 'จ' + 52: 0, # 'ฉ' + 34: 0, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'à¸' + 58: 0, # 'ฎ' + 57: 0, # 'à¸' + 49: 1, # 'à¸' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 1, # 'ด' + 19: 1, # 'ต' + 44: 1, # 'ถ' + 14: 1, # 'ท' + 48: 0, # 'ธ' + 3: 3, # 'น' + 17: 1, # 'บ' + 25: 1, # 'ป' + 39: 1, # 'ผ' + 62: 0, # 'à¸' + 31: 1, # 'พ' + 54: 0, # 'ฟ' + 45: 1, # 'ภ' + 9: 1, # 'ม' + 16: 0, # 'ย' + 2: 2, # 'ร' + 61: 0, # 'ฤ' + 15: 2, # 'ล' + 12: 1, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 1, # 'ส' + 21: 3, # 'ห' + 4: 1, # 'อ' + 63: 0, # 'ฯ' + 22: 0, # 'ะ' + 10: 0, # 'ั' + 1: 0, # 'า' + 36: 0, # 'ำ' + 23: 0, # 'ิ' + 13: 0, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 0, # 'ุ' + 35: 0, # 'ู' + 11: 3, # 'เ' + 28: 2, # 'à¹' + 41: 1, # 'โ' + 29: 2, # 'ใ' + 33: 2, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 0, # '่' + 7: 0, # '้' + 38: 0, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 23: { # 'ิ' + 5: 3, # 'à¸' + 30: 1, # 'ข' + 24: 2, # 'ค' + 8: 3, # 'ง' + 26: 3, # 'จ' + 52: 0, # 'ฉ' + 34: 3, # 'ช' + 51: 0, # 'ซ' + 47: 2, # 'à¸' + 58: 0, # 'ฎ' + 57: 0, # 'à¸' + 49: 0, # 'à¸' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 3, # 'ด' + 19: 3, # 'ต' + 44: 1, # 'ถ' + 14: 3, # 'ท' + 48: 3, # 'ธ' + 3: 3, # 'น' + 17: 3, # 'บ' + 25: 2, # 'ป' + 39: 2, # 'ผ' + 62: 0, # 'à¸' + 31: 3, # 'พ' + 54: 1, # 'ฟ' + 45: 2, # 'ภ' + 9: 3, # 'ม' + 16: 2, # 'ย' + 2: 2, # 'ร' + 61: 0, # 'ฤ' + 15: 2, # 'ล' + 12: 3, # 'ว' + 42: 3, # 'ศ' + 46: 2, # 'ษ' + 18: 2, # 'ส' + 21: 3, # 'ห' + 4: 1, # 'อ' + 63: 1, # 'ฯ' + 22: 0, # 'ะ' + 10: 0, # 'ั' + 1: 0, # 'า' + 36: 0, # 'ำ' + 23: 0, # 'ิ' + 13: 0, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 0, # 'ุ' + 35: 0, # 'ู' + 11: 3, # 'เ' + 28: 1, # 'à¹' + 41: 1, # 'โ' + 29: 1, # 'ใ' + 33: 0, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 3, # '่' + 7: 2, # '้' + 38: 2, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 13: { # 'ี' + 5: 3, # 'à¸' + 30: 2, # 'ข' + 24: 2, # 'ค' + 8: 0, # 'ง' + 26: 1, # 'จ' + 52: 0, # 'ฉ' + 34: 1, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'à¸' + 58: 0, # 'ฎ' + 57: 0, # 'à¸' + 49: 0, # 'à¸' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 2, # 'ด' + 19: 1, # 'ต' + 44: 0, # 'ถ' + 14: 2, # 'ท' + 48: 0, # 'ธ' + 3: 1, # 'น' + 17: 2, # 'บ' + 25: 2, # 'ป' + 39: 1, # 'ผ' + 62: 0, # 'à¸' + 31: 2, # 'พ' + 54: 0, # 'ฟ' + 45: 0, # 'ภ' + 9: 2, # 'ม' + 16: 3, # 'ย' + 2: 2, # 'ร' + 61: 0, # 'ฤ' + 15: 1, # 'ล' + 12: 2, # 'ว' + 42: 1, # 'ศ' + 46: 0, # 'ษ' + 18: 2, # 'ส' + 21: 1, # 'ห' + 4: 2, # 'อ' + 63: 0, # 'ฯ' + 22: 0, # 'ะ' + 10: 0, # 'ั' + 1: 0, # 'า' + 36: 0, # 'ำ' + 23: 0, # 'ิ' + 13: 0, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 0, # 'ุ' + 35: 0, # 'ู' + 11: 2, # 'เ' + 28: 2, # 'à¹' + 41: 1, # 'โ' + 29: 1, # 'ใ' + 33: 1, # 'ไ' + 50: 1, # 'ๆ' + 37: 0, # '็' + 6: 3, # '่' + 7: 3, # '้' + 38: 0, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 40: { # 'ึ' + 5: 3, # 'à¸' + 30: 0, # 'ข' + 24: 0, # 'ค' + 8: 3, # 'ง' + 26: 0, # 'จ' + 52: 0, # 'ฉ' + 34: 0, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'à¸' + 58: 0, # 'ฎ' + 57: 0, # 'à¸' + 49: 0, # 'à¸' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 1, # 'ด' + 19: 0, # 'ต' + 44: 0, # 'ถ' + 14: 0, # 'ท' + 48: 0, # 'ธ' + 3: 0, # 'น' + 17: 0, # 'บ' + 25: 0, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'à¸' + 31: 0, # 'พ' + 54: 0, # 'ฟ' + 45: 0, # 'ภ' + 9: 1, # 'ม' + 16: 0, # 'ย' + 2: 0, # 'ร' + 61: 0, # 'ฤ' + 15: 0, # 'ล' + 12: 0, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 0, # 'ส' + 21: 0, # 'ห' + 4: 0, # 'อ' + 63: 0, # 'ฯ' + 22: 0, # 'ะ' + 10: 0, # 'ั' + 1: 0, # 'า' + 36: 0, # 'ำ' + 23: 0, # 'ิ' + 13: 0, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 0, # 'ุ' + 35: 0, # 'ู' + 11: 0, # 'เ' + 28: 0, # 'à¹' + 41: 0, # 'โ' + 29: 0, # 'ใ' + 33: 0, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 3, # '่' + 7: 3, # '้' + 38: 0, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 27: { # 'ื' + 5: 0, # 'à¸' + 30: 0, # 'ข' + 24: 0, # 'ค' + 8: 0, # 'ง' + 26: 0, # 'จ' + 52: 0, # 'ฉ' + 34: 1, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'à¸' + 58: 0, # 'ฎ' + 57: 0, # 'à¸' + 49: 0, # 'à¸' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 1, # 'ด' + 19: 0, # 'ต' + 44: 0, # 'ถ' + 14: 0, # 'ท' + 48: 0, # 'ธ' + 3: 2, # 'น' + 17: 3, # 'บ' + 25: 0, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'à¸' + 31: 0, # 'พ' + 54: 0, # 'ฟ' + 45: 0, # 'ภ' + 9: 2, # 'ม' + 16: 0, # 'ย' + 2: 0, # 'ร' + 61: 0, # 'ฤ' + 15: 0, # 'ล' + 12: 0, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 0, # 'ส' + 21: 0, # 'ห' + 4: 3, # 'อ' + 63: 0, # 'ฯ' + 22: 0, # 'ะ' + 10: 0, # 'ั' + 1: 0, # 'า' + 36: 0, # 'ำ' + 23: 0, # 'ิ' + 13: 0, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 0, # 'ุ' + 35: 0, # 'ู' + 11: 0, # 'เ' + 28: 0, # 'à¹' + 41: 0, # 'โ' + 29: 0, # 'ใ' + 33: 0, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 3, # '่' + 7: 3, # '้' + 38: 0, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 32: { # 'ุ' + 5: 3, # 'à¸' + 30: 2, # 'ข' + 24: 3, # 'ค' + 8: 3, # 'ง' + 26: 0, # 'จ' + 52: 0, # 'ฉ' + 34: 0, # 'ช' + 51: 0, # 'ซ' + 47: 2, # 'à¸' + 58: 0, # 'ฎ' + 57: 0, # 'à¸' + 49: 0, # 'à¸' + 53: 0, # 'ฑ' + 55: 1, # 'ฒ' + 43: 3, # 'ณ' + 20: 3, # 'ด' + 19: 3, # 'ต' + 44: 1, # 'ถ' + 14: 2, # 'ท' + 48: 1, # 'ธ' + 3: 2, # 'น' + 17: 2, # 'บ' + 25: 2, # 'ป' + 39: 2, # 'ผ' + 62: 0, # 'à¸' + 31: 1, # 'พ' + 54: 0, # 'ฟ' + 45: 1, # 'ภ' + 9: 3, # 'ม' + 16: 1, # 'ย' + 2: 2, # 'ร' + 61: 0, # 'ฤ' + 15: 2, # 'ล' + 12: 1, # 'ว' + 42: 1, # 'ศ' + 46: 2, # 'ษ' + 18: 1, # 'ส' + 21: 1, # 'ห' + 4: 1, # 'อ' + 63: 0, # 'ฯ' + 22: 0, # 'ะ' + 10: 0, # 'ั' + 1: 0, # 'า' + 36: 0, # 'ำ' + 23: 0, # 'ิ' + 13: 0, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 0, # 'ุ' + 35: 0, # 'ู' + 11: 1, # 'เ' + 28: 0, # 'à¹' + 41: 1, # 'โ' + 29: 0, # 'ใ' + 33: 1, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 3, # '่' + 7: 2, # '้' + 38: 1, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 35: { # 'ู' + 5: 3, # 'à¸' + 30: 0, # 'ข' + 24: 0, # 'ค' + 8: 2, # 'ง' + 26: 1, # 'จ' + 52: 0, # 'ฉ' + 34: 0, # 'ช' + 51: 0, # 'ซ' + 47: 2, # 'à¸' + 58: 0, # 'ฎ' + 57: 0, # 'à¸' + 49: 0, # 'à¸' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 1, # 'ณ' + 20: 2, # 'ด' + 19: 2, # 'ต' + 44: 0, # 'ถ' + 14: 1, # 'ท' + 48: 0, # 'ธ' + 3: 2, # 'น' + 17: 0, # 'บ' + 25: 3, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'à¸' + 31: 0, # 'พ' + 54: 0, # 'ฟ' + 45: 0, # 'ภ' + 9: 2, # 'ม' + 16: 0, # 'ย' + 2: 1, # 'ร' + 61: 0, # 'ฤ' + 15: 3, # 'ล' + 12: 1, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 0, # 'ส' + 21: 0, # 'ห' + 4: 0, # 'อ' + 63: 0, # 'ฯ' + 22: 0, # 'ะ' + 10: 0, # 'ั' + 1: 0, # 'า' + 36: 0, # 'ำ' + 23: 0, # 'ิ' + 13: 0, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 0, # 'ุ' + 35: 0, # 'ู' + 11: 1, # 'เ' + 28: 1, # 'à¹' + 41: 1, # 'โ' + 29: 0, # 'ใ' + 33: 0, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 3, # '่' + 7: 3, # '้' + 38: 0, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 11: { # 'เ' + 5: 3, # 'à¸' + 30: 3, # 'ข' + 24: 3, # 'ค' + 8: 2, # 'ง' + 26: 3, # 'จ' + 52: 3, # 'ฉ' + 34: 3, # 'ช' + 51: 2, # 'ซ' + 47: 0, # 'à¸' + 58: 0, # 'ฎ' + 57: 0, # 'à¸' + 49: 0, # 'à¸' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 1, # 'ณ' + 20: 3, # 'ด' + 19: 3, # 'ต' + 44: 1, # 'ถ' + 14: 3, # 'ท' + 48: 1, # 'ธ' + 3: 3, # 'น' + 17: 3, # 'บ' + 25: 3, # 'ป' + 39: 2, # 'ผ' + 62: 1, # 'à¸' + 31: 3, # 'พ' + 54: 1, # 'ฟ' + 45: 3, # 'ภ' + 9: 3, # 'ม' + 16: 2, # 'ย' + 2: 3, # 'ร' + 61: 0, # 'ฤ' + 15: 3, # 'ล' + 12: 3, # 'ว' + 42: 2, # 'ศ' + 46: 0, # 'ษ' + 18: 3, # 'ส' + 21: 3, # 'ห' + 4: 3, # 'อ' + 63: 0, # 'ฯ' + 22: 0, # 'ะ' + 10: 0, # 'ั' + 1: 0, # 'า' + 36: 0, # 'ำ' + 23: 0, # 'ิ' + 13: 0, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 0, # 'ุ' + 35: 0, # 'ู' + 11: 0, # 'เ' + 28: 0, # 'à¹' + 41: 0, # 'โ' + 29: 0, # 'ใ' + 33: 0, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 0, # '่' + 7: 0, # '้' + 38: 0, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 28: { # 'à¹' + 5: 3, # 'à¸' + 30: 2, # 'ข' + 24: 2, # 'ค' + 8: 1, # 'ง' + 26: 2, # 'จ' + 52: 0, # 'ฉ' + 34: 1, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'à¸' + 58: 0, # 'ฎ' + 57: 0, # 'à¸' + 49: 0, # 'à¸' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 2, # 'ด' + 19: 3, # 'ต' + 44: 2, # 'ถ' + 14: 3, # 'ท' + 48: 0, # 'ธ' + 3: 3, # 'น' + 17: 3, # 'บ' + 25: 2, # 'ป' + 39: 3, # 'ผ' + 62: 0, # 'à¸' + 31: 2, # 'พ' + 54: 2, # 'ฟ' + 45: 0, # 'ภ' + 9: 2, # 'ม' + 16: 2, # 'ย' + 2: 2, # 'ร' + 61: 0, # 'ฤ' + 15: 3, # 'ล' + 12: 2, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 3, # 'ส' + 21: 3, # 'ห' + 4: 1, # 'อ' + 63: 0, # 'ฯ' + 22: 0, # 'ะ' + 10: 0, # 'ั' + 1: 0, # 'า' + 36: 0, # 'ำ' + 23: 0, # 'ิ' + 13: 0, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 0, # 'ุ' + 35: 0, # 'ู' + 11: 0, # 'เ' + 28: 0, # 'à¹' + 41: 0, # 'โ' + 29: 0, # 'ใ' + 33: 0, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 0, # '่' + 7: 0, # '้' + 38: 0, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 41: { # 'โ' + 5: 2, # 'à¸' + 30: 1, # 'ข' + 24: 2, # 'ค' + 8: 0, # 'ง' + 26: 1, # 'จ' + 52: 1, # 'ฉ' + 34: 1, # 'ช' + 51: 1, # 'ซ' + 47: 0, # 'à¸' + 58: 0, # 'ฎ' + 57: 0, # 'à¸' + 49: 0, # 'à¸' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 3, # 'ด' + 19: 2, # 'ต' + 44: 0, # 'ถ' + 14: 2, # 'ท' + 48: 0, # 'ธ' + 3: 3, # 'น' + 17: 1, # 'บ' + 25: 3, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'à¸' + 31: 1, # 'พ' + 54: 1, # 'ฟ' + 45: 1, # 'ภ' + 9: 1, # 'ม' + 16: 2, # 'ย' + 2: 2, # 'ร' + 61: 0, # 'ฤ' + 15: 3, # 'ล' + 12: 0, # 'ว' + 42: 1, # 'ศ' + 46: 0, # 'ษ' + 18: 2, # 'ส' + 21: 0, # 'ห' + 4: 2, # 'อ' + 63: 0, # 'ฯ' + 22: 0, # 'ะ' + 10: 0, # 'ั' + 1: 0, # 'า' + 36: 0, # 'ำ' + 23: 0, # 'ิ' + 13: 0, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 0, # 'ุ' + 35: 0, # 'ู' + 11: 0, # 'เ' + 28: 0, # 'à¹' + 41: 0, # 'โ' + 29: 0, # 'ใ' + 33: 0, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 0, # '่' + 7: 0, # '้' + 38: 0, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 29: { # 'ใ' + 5: 2, # 'à¸' + 30: 0, # 'ข' + 24: 1, # 'ค' + 8: 0, # 'ง' + 26: 3, # 'จ' + 52: 0, # 'ฉ' + 34: 3, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'à¸' + 58: 0, # 'ฎ' + 57: 0, # 'à¸' + 49: 0, # 'à¸' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 3, # 'ด' + 19: 1, # 'ต' + 44: 0, # 'ถ' + 14: 0, # 'ท' + 48: 0, # 'ธ' + 3: 3, # 'น' + 17: 2, # 'บ' + 25: 0, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'à¸' + 31: 0, # 'พ' + 54: 0, # 'ฟ' + 45: 0, # 'ภ' + 9: 0, # 'ม' + 16: 1, # 'ย' + 2: 0, # 'ร' + 61: 0, # 'ฤ' + 15: 0, # 'ล' + 12: 0, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 3, # 'ส' + 21: 3, # 'ห' + 4: 0, # 'อ' + 63: 0, # 'ฯ' + 22: 0, # 'ะ' + 10: 0, # 'ั' + 1: 0, # 'า' + 36: 0, # 'ำ' + 23: 0, # 'ิ' + 13: 0, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 0, # 'ุ' + 35: 0, # 'ู' + 11: 0, # 'เ' + 28: 0, # 'à¹' + 41: 0, # 'โ' + 29: 0, # 'ใ' + 33: 0, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 0, # '่' + 7: 0, # '้' + 38: 0, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 33: { # 'ไ' + 5: 1, # 'à¸' + 30: 2, # 'ข' + 24: 0, # 'ค' + 8: 0, # 'ง' + 26: 0, # 'จ' + 52: 0, # 'ฉ' + 34: 1, # 'ช' + 51: 1, # 'ซ' + 47: 0, # 'à¸' + 58: 0, # 'ฎ' + 57: 0, # 'à¸' + 49: 0, # 'à¸' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 3, # 'ด' + 19: 1, # 'ต' + 44: 0, # 'ถ' + 14: 3, # 'ท' + 48: 0, # 'ธ' + 3: 0, # 'น' + 17: 1, # 'บ' + 25: 3, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'à¸' + 31: 0, # 'พ' + 54: 2, # 'ฟ' + 45: 0, # 'ภ' + 9: 3, # 'ม' + 16: 0, # 'ย' + 2: 3, # 'ร' + 61: 0, # 'ฤ' + 15: 1, # 'ล' + 12: 3, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 1, # 'ส' + 21: 2, # 'ห' + 4: 0, # 'อ' + 63: 0, # 'ฯ' + 22: 0, # 'ะ' + 10: 0, # 'ั' + 1: 0, # 'า' + 36: 0, # 'ำ' + 23: 0, # 'ิ' + 13: 0, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 0, # 'ุ' + 35: 0, # 'ู' + 11: 0, # 'เ' + 28: 0, # 'à¹' + 41: 0, # 'โ' + 29: 0, # 'ใ' + 33: 0, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 0, # '่' + 7: 0, # '้' + 38: 0, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 50: { # 'ๆ' + 5: 0, # 'à¸' + 30: 0, # 'ข' + 24: 0, # 'ค' + 8: 0, # 'ง' + 26: 0, # 'จ' + 52: 0, # 'ฉ' + 34: 0, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'à¸' + 58: 0, # 'ฎ' + 57: 0, # 'à¸' + 49: 0, # 'à¸' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 0, # 'ด' + 19: 0, # 'ต' + 44: 0, # 'ถ' + 14: 0, # 'ท' + 48: 0, # 'ธ' + 3: 0, # 'น' + 17: 0, # 'บ' + 25: 0, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'à¸' + 31: 0, # 'พ' + 54: 0, # 'ฟ' + 45: 0, # 'ภ' + 9: 0, # 'ม' + 16: 0, # 'ย' + 2: 0, # 'ร' + 61: 0, # 'ฤ' + 15: 0, # 'ล' + 12: 0, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 0, # 'ส' + 21: 0, # 'ห' + 4: 0, # 'อ' + 63: 0, # 'ฯ' + 22: 0, # 'ะ' + 10: 0, # 'ั' + 1: 0, # 'า' + 36: 0, # 'ำ' + 23: 0, # 'ิ' + 13: 0, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 0, # 'ุ' + 35: 0, # 'ู' + 11: 0, # 'เ' + 28: 0, # 'à¹' + 41: 0, # 'โ' + 29: 0, # 'ใ' + 33: 0, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 0, # '่' + 7: 0, # '้' + 38: 0, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 37: { # '็' + 5: 2, # 'à¸' + 30: 1, # 'ข' + 24: 2, # 'ค' + 8: 2, # 'ง' + 26: 3, # 'จ' + 52: 0, # 'ฉ' + 34: 0, # 'ช' + 51: 0, # 'ซ' + 47: 1, # 'à¸' + 58: 0, # 'ฎ' + 57: 0, # 'à¸' + 49: 0, # 'à¸' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 1, # 'ด' + 19: 2, # 'ต' + 44: 0, # 'ถ' + 14: 1, # 'ท' + 48: 0, # 'ธ' + 3: 3, # 'น' + 17: 3, # 'บ' + 25: 0, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'à¸' + 31: 0, # 'พ' + 54: 0, # 'ฟ' + 45: 0, # 'ภ' + 9: 2, # 'ม' + 16: 1, # 'ย' + 2: 0, # 'ร' + 61: 0, # 'ฤ' + 15: 0, # 'ล' + 12: 2, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 1, # 'ส' + 21: 0, # 'ห' + 4: 1, # 'อ' + 63: 0, # 'ฯ' + 22: 0, # 'ะ' + 10: 0, # 'ั' + 1: 0, # 'า' + 36: 0, # 'ำ' + 23: 0, # 'ิ' + 13: 0, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 0, # 'ุ' + 35: 0, # 'ู' + 11: 1, # 'เ' + 28: 0, # 'à¹' + 41: 0, # 'โ' + 29: 0, # 'ใ' + 33: 1, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 0, # '่' + 7: 0, # '้' + 38: 0, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 6: { # '่' + 5: 2, # 'à¸' + 30: 1, # 'ข' + 24: 2, # 'ค' + 8: 3, # 'ง' + 26: 2, # 'จ' + 52: 0, # 'ฉ' + 34: 1, # 'ช' + 51: 1, # 'ซ' + 47: 0, # 'à¸' + 58: 0, # 'ฎ' + 57: 0, # 'à¸' + 49: 1, # 'à¸' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 1, # 'ด' + 19: 2, # 'ต' + 44: 1, # 'ถ' + 14: 2, # 'ท' + 48: 1, # 'ธ' + 3: 3, # 'น' + 17: 1, # 'บ' + 25: 2, # 'ป' + 39: 2, # 'ผ' + 62: 1, # 'à¸' + 31: 1, # 'พ' + 54: 0, # 'ฟ' + 45: 0, # 'ภ' + 9: 3, # 'ม' + 16: 3, # 'ย' + 2: 2, # 'ร' + 61: 0, # 'ฤ' + 15: 2, # 'ล' + 12: 3, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 2, # 'ส' + 21: 1, # 'ห' + 4: 3, # 'อ' + 63: 0, # 'ฯ' + 22: 1, # 'ะ' + 10: 0, # 'ั' + 1: 3, # 'า' + 36: 2, # 'ำ' + 23: 0, # 'ิ' + 13: 0, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 0, # 'ุ' + 35: 0, # 'ู' + 11: 3, # 'เ' + 28: 2, # 'à¹' + 41: 1, # 'โ' + 29: 2, # 'ใ' + 33: 2, # 'ไ' + 50: 1, # 'ๆ' + 37: 0, # '็' + 6: 0, # '่' + 7: 0, # '้' + 38: 0, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 7: { # '้' + 5: 2, # 'à¸' + 30: 1, # 'ข' + 24: 2, # 'ค' + 8: 3, # 'ง' + 26: 2, # 'จ' + 52: 0, # 'ฉ' + 34: 1, # 'ช' + 51: 1, # 'ซ' + 47: 0, # 'à¸' + 58: 0, # 'ฎ' + 57: 0, # 'à¸' + 49: 0, # 'à¸' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 1, # 'ด' + 19: 2, # 'ต' + 44: 1, # 'ถ' + 14: 2, # 'ท' + 48: 0, # 'ธ' + 3: 3, # 'น' + 17: 2, # 'บ' + 25: 2, # 'ป' + 39: 2, # 'ผ' + 62: 0, # 'à¸' + 31: 1, # 'พ' + 54: 1, # 'ฟ' + 45: 0, # 'ภ' + 9: 3, # 'ม' + 16: 2, # 'ย' + 2: 2, # 'ร' + 61: 0, # 'ฤ' + 15: 1, # 'ล' + 12: 3, # 'ว' + 42: 1, # 'ศ' + 46: 0, # 'ษ' + 18: 2, # 'ส' + 21: 2, # 'ห' + 4: 3, # 'อ' + 63: 0, # 'ฯ' + 22: 0, # 'ะ' + 10: 0, # 'ั' + 1: 3, # 'า' + 36: 2, # 'ำ' + 23: 0, # 'ิ' + 13: 0, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 0, # 'ุ' + 35: 0, # 'ู' + 11: 2, # 'เ' + 28: 2, # 'à¹' + 41: 1, # 'โ' + 29: 2, # 'ใ' + 33: 2, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 0, # '่' + 7: 0, # '้' + 38: 0, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 38: { # '์' + 5: 2, # 'à¸' + 30: 1, # 'ข' + 24: 1, # 'ค' + 8: 0, # 'ง' + 26: 1, # 'จ' + 52: 0, # 'ฉ' + 34: 1, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'à¸' + 58: 0, # 'ฎ' + 57: 0, # 'à¸' + 49: 0, # 'à¸' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 2, # 'ด' + 19: 1, # 'ต' + 44: 1, # 'ถ' + 14: 1, # 'ท' + 48: 0, # 'ธ' + 3: 1, # 'น' + 17: 1, # 'บ' + 25: 1, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'à¸' + 31: 1, # 'พ' + 54: 1, # 'ฟ' + 45: 0, # 'ภ' + 9: 2, # 'ม' + 16: 0, # 'ย' + 2: 1, # 'ร' + 61: 1, # 'ฤ' + 15: 1, # 'ล' + 12: 1, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 1, # 'ส' + 21: 1, # 'ห' + 4: 2, # 'อ' + 63: 1, # 'ฯ' + 22: 0, # 'ะ' + 10: 0, # 'ั' + 1: 0, # 'า' + 36: 0, # 'ำ' + 23: 0, # 'ิ' + 13: 0, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 0, # 'ุ' + 35: 0, # 'ู' + 11: 2, # 'เ' + 28: 2, # 'à¹' + 41: 1, # 'โ' + 29: 1, # 'ใ' + 33: 1, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 0, # '่' + 7: 0, # '้' + 38: 0, # '์' + 56: 0, # '๑' + 59: 0, # '๒' + 60: 0, # '๕' + }, + 56: { # '๑' + 5: 0, # 'à¸' + 30: 0, # 'ข' + 24: 0, # 'ค' + 8: 0, # 'ง' + 26: 0, # 'จ' + 52: 0, # 'ฉ' + 34: 0, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'à¸' + 58: 0, # 'ฎ' + 57: 0, # 'à¸' + 49: 0, # 'à¸' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 0, # 'ด' + 19: 0, # 'ต' + 44: 0, # 'ถ' + 14: 0, # 'ท' + 48: 0, # 'ธ' + 3: 0, # 'น' + 17: 0, # 'บ' + 25: 0, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'à¸' + 31: 0, # 'พ' + 54: 0, # 'ฟ' + 45: 0, # 'ภ' + 9: 0, # 'ม' + 16: 0, # 'ย' + 2: 0, # 'ร' + 61: 0, # 'ฤ' + 15: 0, # 'ล' + 12: 0, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 0, # 'ส' + 21: 0, # 'ห' + 4: 0, # 'อ' + 63: 0, # 'ฯ' + 22: 0, # 'ะ' + 10: 0, # 'ั' + 1: 0, # 'า' + 36: 0, # 'ำ' + 23: 0, # 'ิ' + 13: 0, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 0, # 'ุ' + 35: 0, # 'ู' + 11: 0, # 'เ' + 28: 0, # 'à¹' + 41: 0, # 'โ' + 29: 0, # 'ใ' + 33: 0, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 0, # '่' + 7: 0, # '้' + 38: 0, # '์' + 56: 2, # '๑' + 59: 1, # '๒' + 60: 1, # '๕' + }, + 59: { # '๒' + 5: 0, # 'à¸' + 30: 0, # 'ข' + 24: 0, # 'ค' + 8: 0, # 'ง' + 26: 0, # 'จ' + 52: 0, # 'ฉ' + 34: 0, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'à¸' + 58: 0, # 'ฎ' + 57: 0, # 'à¸' + 49: 0, # 'à¸' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 0, # 'ด' + 19: 0, # 'ต' + 44: 0, # 'ถ' + 14: 0, # 'ท' + 48: 0, # 'ธ' + 3: 0, # 'น' + 17: 0, # 'บ' + 25: 0, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'à¸' + 31: 0, # 'พ' + 54: 0, # 'ฟ' + 45: 0, # 'ภ' + 9: 0, # 'ม' + 16: 0, # 'ย' + 2: 0, # 'ร' + 61: 0, # 'ฤ' + 15: 0, # 'ล' + 12: 0, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 0, # 'ส' + 21: 0, # 'ห' + 4: 0, # 'อ' + 63: 0, # 'ฯ' + 22: 0, # 'ะ' + 10: 0, # 'ั' + 1: 0, # 'า' + 36: 0, # 'ำ' + 23: 0, # 'ิ' + 13: 0, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 0, # 'ุ' + 35: 0, # 'ู' + 11: 0, # 'เ' + 28: 0, # 'à¹' + 41: 0, # 'โ' + 29: 0, # 'ใ' + 33: 0, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 0, # '่' + 7: 0, # '้' + 38: 0, # '์' + 56: 1, # '๑' + 59: 1, # '๒' + 60: 3, # '๕' + }, + 60: { # '๕' + 5: 0, # 'à¸' + 30: 0, # 'ข' + 24: 0, # 'ค' + 8: 0, # 'ง' + 26: 0, # 'จ' + 52: 0, # 'ฉ' + 34: 0, # 'ช' + 51: 0, # 'ซ' + 47: 0, # 'à¸' + 58: 0, # 'ฎ' + 57: 0, # 'à¸' + 49: 0, # 'à¸' + 53: 0, # 'ฑ' + 55: 0, # 'ฒ' + 43: 0, # 'ณ' + 20: 0, # 'ด' + 19: 0, # 'ต' + 44: 0, # 'ถ' + 14: 0, # 'ท' + 48: 0, # 'ธ' + 3: 0, # 'น' + 17: 0, # 'บ' + 25: 0, # 'ป' + 39: 0, # 'ผ' + 62: 0, # 'à¸' + 31: 0, # 'พ' + 54: 0, # 'ฟ' + 45: 0, # 'ภ' + 9: 0, # 'ม' + 16: 0, # 'ย' + 2: 0, # 'ร' + 61: 0, # 'ฤ' + 15: 0, # 'ล' + 12: 0, # 'ว' + 42: 0, # 'ศ' + 46: 0, # 'ษ' + 18: 0, # 'ส' + 21: 0, # 'ห' + 4: 0, # 'อ' + 63: 0, # 'ฯ' + 22: 0, # 'ะ' + 10: 0, # 'ั' + 1: 0, # 'า' + 36: 0, # 'ำ' + 23: 0, # 'ิ' + 13: 0, # 'ี' + 40: 0, # 'ึ' + 27: 0, # 'ื' + 32: 0, # 'ุ' + 35: 0, # 'ู' + 11: 0, # 'เ' + 28: 0, # 'à¹' + 41: 0, # 'โ' + 29: 0, # 'ใ' + 33: 0, # 'ไ' + 50: 0, # 'ๆ' + 37: 0, # '็' + 6: 0, # '่' + 7: 0, # '้' + 38: 0, # '์' + 56: 2, # '๑' + 59: 1, # '๒' + 60: 0, # '๕' + }, +} + +# 255: Undefined characters that did not exist in training text +# 254: Carriage/Return +# 253: symbol (punctuation) that does not belong to word +# 252: 0 - 9 +# 251: Control characters + +# Character Mapping Table(s): +TIS_620_THAI_CHAR_TO_ORDER = { + 0: 255, # '\x00' + 1: 255, # '\x01' + 2: 255, # '\x02' + 3: 255, # '\x03' + 4: 255, # '\x04' + 5: 255, # '\x05' + 6: 255, # '\x06' + 7: 255, # '\x07' + 8: 255, # '\x08' + 9: 255, # '\t' + 10: 254, # '\n' + 11: 255, # '\x0b' + 12: 255, # '\x0c' + 13: 254, # '\r' + 14: 255, # '\x0e' + 15: 255, # '\x0f' + 16: 255, # '\x10' + 17: 255, # '\x11' + 18: 255, # '\x12' + 19: 255, # '\x13' + 20: 255, # '\x14' + 21: 255, # '\x15' + 22: 255, # '\x16' + 23: 255, # '\x17' + 24: 255, # '\x18' + 25: 255, # '\x19' + 26: 255, # '\x1a' + 27: 255, # '\x1b' + 28: 255, # '\x1c' + 29: 255, # '\x1d' + 30: 255, # '\x1e' + 31: 255, # '\x1f' + 32: 253, # ' ' + 33: 253, # '!' + 34: 253, # '"' + 35: 253, # '#' + 36: 253, # '$' + 37: 253, # '%' + 38: 253, # '&' + 39: 253, # "'" + 40: 253, # '(' + 41: 253, # ')' + 42: 253, # '*' + 43: 253, # '+' + 44: 253, # ',' + 45: 253, # '-' + 46: 253, # '.' + 47: 253, # '/' + 48: 252, # '0' + 49: 252, # '1' + 50: 252, # '2' + 51: 252, # '3' + 52: 252, # '4' + 53: 252, # '5' + 54: 252, # '6' + 55: 252, # '7' + 56: 252, # '8' + 57: 252, # '9' + 58: 253, # ':' + 59: 253, # ';' + 60: 253, # '<' + 61: 253, # '=' + 62: 253, # '>' + 63: 253, # '?' + 64: 253, # '@' + 65: 182, # 'A' + 66: 106, # 'B' + 67: 107, # 'C' + 68: 100, # 'D' + 69: 183, # 'E' + 70: 184, # 'F' + 71: 185, # 'G' + 72: 101, # 'H' + 73: 94, # 'I' + 74: 186, # 'J' + 75: 187, # 'K' + 76: 108, # 'L' + 77: 109, # 'M' + 78: 110, # 'N' + 79: 111, # 'O' + 80: 188, # 'P' + 81: 189, # 'Q' + 82: 190, # 'R' + 83: 89, # 'S' + 84: 95, # 'T' + 85: 112, # 'U' + 86: 113, # 'V' + 87: 191, # 'W' + 88: 192, # 'X' + 89: 193, # 'Y' + 90: 194, # 'Z' + 91: 253, # '[' + 92: 253, # '\\' + 93: 253, # ']' + 94: 253, # '^' + 95: 253, # '_' + 96: 253, # '`' + 97: 64, # 'a' + 98: 72, # 'b' + 99: 73, # 'c' + 100: 114, # 'd' + 101: 74, # 'e' + 102: 115, # 'f' + 103: 116, # 'g' + 104: 102, # 'h' + 105: 81, # 'i' + 106: 201, # 'j' + 107: 117, # 'k' + 108: 90, # 'l' + 109: 103, # 'm' + 110: 78, # 'n' + 111: 82, # 'o' + 112: 96, # 'p' + 113: 202, # 'q' + 114: 91, # 'r' + 115: 79, # 's' + 116: 84, # 't' + 117: 104, # 'u' + 118: 105, # 'v' + 119: 97, # 'w' + 120: 98, # 'x' + 121: 92, # 'y' + 122: 203, # 'z' + 123: 253, # '{' + 124: 253, # '|' + 125: 253, # '}' + 126: 253, # '~' + 127: 253, # '\x7f' + 128: 209, # '\x80' + 129: 210, # '\x81' + 130: 211, # '\x82' + 131: 212, # '\x83' + 132: 213, # '\x84' + 133: 88, # '\x85' + 134: 214, # '\x86' + 135: 215, # '\x87' + 136: 216, # '\x88' + 137: 217, # '\x89' + 138: 218, # '\x8a' + 139: 219, # '\x8b' + 140: 220, # '\x8c' + 141: 118, # '\x8d' + 142: 221, # '\x8e' + 143: 222, # '\x8f' + 144: 223, # '\x90' + 145: 224, # '\x91' + 146: 99, # '\x92' + 147: 85, # '\x93' + 148: 83, # '\x94' + 149: 225, # '\x95' + 150: 226, # '\x96' + 151: 227, # '\x97' + 152: 228, # '\x98' + 153: 229, # '\x99' + 154: 230, # '\x9a' + 155: 231, # '\x9b' + 156: 232, # '\x9c' + 157: 233, # '\x9d' + 158: 234, # '\x9e' + 159: 235, # '\x9f' + 160: 236, # None + 161: 5, # 'à¸' + 162: 30, # 'ข' + 163: 237, # 'ฃ' + 164: 24, # 'ค' + 165: 238, # 'ฅ' + 166: 75, # 'ฆ' + 167: 8, # 'ง' + 168: 26, # 'จ' + 169: 52, # 'ฉ' + 170: 34, # 'ช' + 171: 51, # 'ซ' + 172: 119, # 'ฌ' + 173: 47, # 'à¸' + 174: 58, # 'ฎ' + 175: 57, # 'à¸' + 176: 49, # 'à¸' + 177: 53, # 'ฑ' + 178: 55, # 'ฒ' + 179: 43, # 'ณ' + 180: 20, # 'ด' + 181: 19, # 'ต' + 182: 44, # 'ถ' + 183: 14, # 'ท' + 184: 48, # 'ธ' + 185: 3, # 'น' + 186: 17, # 'บ' + 187: 25, # 'ป' + 188: 39, # 'ผ' + 189: 62, # 'à¸' + 190: 31, # 'พ' + 191: 54, # 'ฟ' + 192: 45, # 'ภ' + 193: 9, # 'ม' + 194: 16, # 'ย' + 195: 2, # 'ร' + 196: 61, # 'ฤ' + 197: 15, # 'ล' + 198: 239, # 'ฦ' + 199: 12, # 'ว' + 200: 42, # 'ศ' + 201: 46, # 'ษ' + 202: 18, # 'ส' + 203: 21, # 'ห' + 204: 76, # 'ฬ' + 205: 4, # 'อ' + 206: 66, # 'ฮ' + 207: 63, # 'ฯ' + 208: 22, # 'ะ' + 209: 10, # 'ั' + 210: 1, # 'า' + 211: 36, # 'ำ' + 212: 23, # 'ิ' + 213: 13, # 'ี' + 214: 40, # 'ึ' + 215: 27, # 'ื' + 216: 32, # 'ุ' + 217: 35, # 'ู' + 218: 86, # 'ฺ' + 219: 240, # None + 220: 241, # None + 221: 242, # None + 222: 243, # None + 223: 244, # '฿' + 224: 11, # 'เ' + 225: 28, # 'à¹' + 226: 41, # 'โ' + 227: 29, # 'ใ' + 228: 33, # 'ไ' + 229: 245, # 'ๅ' + 230: 50, # 'ๆ' + 231: 37, # '็' + 232: 6, # '่' + 233: 7, # '้' + 234: 67, # '๊' + 235: 77, # '๋' + 236: 38, # '์' + 237: 93, # 'à¹' + 238: 246, # '๎' + 239: 247, # 'à¹' + 240: 68, # 'à¹' + 241: 56, # '๑' + 242: 59, # '๒' + 243: 65, # '๓' + 244: 69, # '๔' + 245: 60, # '๕' + 246: 70, # '๖' + 247: 80, # '๗' + 248: 71, # '๘' + 249: 87, # '๙' + 250: 248, # '๚' + 251: 249, # '๛' + 252: 250, # None + 253: 251, # None + 254: 252, # None + 255: 253, # None +} + +TIS_620_THAI_MODEL = SingleByteCharSetModel(charset_name='TIS-620', + language='Thai', + char_to_order_map=TIS_620_THAI_CHAR_TO_ORDER, + language_model=THAI_LANG_MODEL, + typical_positive_ratio=0.926386, + keep_ascii_letters=False, + alphabet='à¸à¸‚ฃคฅฆงจฉชซฌà¸à¸Žà¸à¸à¸‘ฒณดตถทธนบปผà¸à¸žà¸Ÿà¸ à¸¡à¸¢à¸£à¸¤à¸¥à¸¦à¸§à¸¨à¸©à¸ªà¸«à¸¬à¸­à¸®à¸¯à¸°à¸±à¸²à¸³à¸´à¸µà¸¶à¸·à¸¸à¸¹à¸ºà¸¿à¹€à¹à¹‚ใไๅๆ็่้๊๋์à¹à¹Žà¹à¹à¹‘๒๓๔๕๖๗๘๙๚๛') + diff --git a/venv/Lib/site-packages/pip/_vendor/chardet/langturkishmodel.py b/venv/Lib/site-packages/pip/_vendor/chardet/langturkishmodel.py new file mode 100644 index 0000000..43f4230 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/chardet/langturkishmodel.py @@ -0,0 +1,4383 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +from pip._vendor.chardet.sbcharsetprober import SingleByteCharSetModel + + +# 3: Positive +# 2: Likely +# 1: Unlikely +# 0: Negative + +TURKISH_LANG_MODEL = { + 23: { # 'A' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 0, # 'F' + 36: 0, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 0, # 'K' + 49: 0, # 'L' + 20: 0, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 0, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 0, # 'T' + 51: 0, # 'U' + 38: 0, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 0, # 'Z' + 1: 3, # 'a' + 21: 0, # 'b' + 28: 0, # 'c' + 12: 2, # 'd' + 2: 3, # 'e' + 18: 0, # 'f' + 27: 1, # 'g' + 25: 1, # 'h' + 3: 1, # 'i' + 24: 0, # 'j' + 10: 2, # 'k' + 5: 1, # 'l' + 13: 1, # 'm' + 4: 1, # 'n' + 15: 0, # 'o' + 26: 0, # 'p' + 7: 1, # 'r' + 8: 1, # 's' + 9: 1, # 't' + 14: 1, # 'u' + 32: 0, # 'v' + 57: 0, # 'w' + 58: 0, # 'x' + 11: 3, # 'y' + 22: 0, # 'z' + 63: 0, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ãœ' + 59: 0, # 'â' + 33: 1, # 'ç' + 61: 0, # 'î' + 34: 0, # 'ö' + 17: 0, # 'ü' + 30: 0, # 'ÄŸ' + 41: 0, # 'Ä°' + 6: 0, # 'ı' + 40: 0, # 'Åž' + 19: 0, # 'ÅŸ' + }, + 37: { # 'B' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 2, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 2, # 'F' + 36: 0, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 1, # 'K' + 49: 0, # 'L' + 20: 0, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 1, # 'P' + 44: 0, # 'R' + 35: 1, # 'S' + 31: 0, # 'T' + 51: 0, # 'U' + 38: 1, # 'V' + 62: 0, # 'W' + 43: 1, # 'Y' + 56: 0, # 'Z' + 1: 2, # 'a' + 21: 0, # 'b' + 28: 2, # 'c' + 12: 0, # 'd' + 2: 3, # 'e' + 18: 0, # 'f' + 27: 0, # 'g' + 25: 0, # 'h' + 3: 0, # 'i' + 24: 0, # 'j' + 10: 0, # 'k' + 5: 0, # 'l' + 13: 1, # 'm' + 4: 1, # 'n' + 15: 0, # 'o' + 26: 0, # 'p' + 7: 0, # 'r' + 8: 0, # 's' + 9: 0, # 't' + 14: 2, # 'u' + 32: 0, # 'v' + 57: 0, # 'w' + 58: 0, # 'x' + 11: 0, # 'y' + 22: 1, # 'z' + 63: 0, # '·' + 54: 0, # 'Ç' + 50: 1, # 'Ö' + 55: 0, # 'Ãœ' + 59: 0, # 'â' + 33: 0, # 'ç' + 61: 0, # 'î' + 34: 1, # 'ö' + 17: 0, # 'ü' + 30: 0, # 'ÄŸ' + 41: 0, # 'Ä°' + 6: 0, # 'ı' + 40: 1, # 'Åž' + 19: 1, # 'ÅŸ' + }, + 47: { # 'C' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 1, # 'F' + 36: 0, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 0, # 'K' + 49: 1, # 'L' + 20: 0, # 'M' + 46: 1, # 'N' + 42: 0, # 'O' + 48: 1, # 'P' + 44: 1, # 'R' + 35: 0, # 'S' + 31: 0, # 'T' + 51: 0, # 'U' + 38: 1, # 'V' + 62: 0, # 'W' + 43: 1, # 'Y' + 56: 0, # 'Z' + 1: 3, # 'a' + 21: 0, # 'b' + 28: 2, # 'c' + 12: 0, # 'd' + 2: 3, # 'e' + 18: 0, # 'f' + 27: 0, # 'g' + 25: 0, # 'h' + 3: 0, # 'i' + 24: 2, # 'j' + 10: 1, # 'k' + 5: 2, # 'l' + 13: 2, # 'm' + 4: 2, # 'n' + 15: 1, # 'o' + 26: 0, # 'p' + 7: 2, # 'r' + 8: 0, # 's' + 9: 0, # 't' + 14: 3, # 'u' + 32: 0, # 'v' + 57: 0, # 'w' + 58: 0, # 'x' + 11: 0, # 'y' + 22: 2, # 'z' + 63: 0, # '·' + 54: 0, # 'Ç' + 50: 1, # 'Ö' + 55: 0, # 'Ãœ' + 59: 0, # 'â' + 33: 1, # 'ç' + 61: 0, # 'î' + 34: 1, # 'ö' + 17: 0, # 'ü' + 30: 0, # 'ÄŸ' + 41: 1, # 'Ä°' + 6: 3, # 'ı' + 40: 0, # 'Åž' + 19: 0, # 'ÅŸ' + }, + 39: { # 'D' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 1, # 'F' + 36: 0, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 1, # 'K' + 49: 0, # 'L' + 20: 0, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 1, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 0, # 'T' + 51: 0, # 'U' + 38: 0, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 0, # 'Z' + 1: 2, # 'a' + 21: 0, # 'b' + 28: 2, # 'c' + 12: 0, # 'd' + 2: 2, # 'e' + 18: 0, # 'f' + 27: 0, # 'g' + 25: 0, # 'h' + 3: 0, # 'i' + 24: 0, # 'j' + 10: 0, # 'k' + 5: 1, # 'l' + 13: 3, # 'm' + 4: 0, # 'n' + 15: 1, # 'o' + 26: 0, # 'p' + 7: 0, # 'r' + 8: 0, # 's' + 9: 0, # 't' + 14: 1, # 'u' + 32: 0, # 'v' + 57: 0, # 'w' + 58: 0, # 'x' + 11: 0, # 'y' + 22: 1, # 'z' + 63: 0, # '·' + 54: 1, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ãœ' + 59: 0, # 'â' + 33: 1, # 'ç' + 61: 0, # 'î' + 34: 0, # 'ö' + 17: 0, # 'ü' + 30: 1, # 'ÄŸ' + 41: 0, # 'Ä°' + 6: 1, # 'ı' + 40: 1, # 'Åž' + 19: 0, # 'ÅŸ' + }, + 29: { # 'E' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 1, # 'E' + 52: 0, # 'F' + 36: 0, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 3, # 'K' + 49: 0, # 'L' + 20: 1, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 0, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 0, # 'T' + 51: 0, # 'U' + 38: 0, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 0, # 'Z' + 1: 3, # 'a' + 21: 0, # 'b' + 28: 0, # 'c' + 12: 2, # 'd' + 2: 3, # 'e' + 18: 0, # 'f' + 27: 1, # 'g' + 25: 0, # 'h' + 3: 1, # 'i' + 24: 1, # 'j' + 10: 0, # 'k' + 5: 3, # 'l' + 13: 3, # 'm' + 4: 3, # 'n' + 15: 0, # 'o' + 26: 0, # 'p' + 7: 0, # 'r' + 8: 1, # 's' + 9: 1, # 't' + 14: 1, # 'u' + 32: 1, # 'v' + 57: 0, # 'w' + 58: 0, # 'x' + 11: 2, # 'y' + 22: 0, # 'z' + 63: 0, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ãœ' + 59: 0, # 'â' + 33: 0, # 'ç' + 61: 0, # 'î' + 34: 0, # 'ö' + 17: 0, # 'ü' + 30: 0, # 'ÄŸ' + 41: 0, # 'Ä°' + 6: 3, # 'ı' + 40: 0, # 'Åž' + 19: 0, # 'ÅŸ' + }, + 52: { # 'F' + 23: 0, # 'A' + 37: 1, # 'B' + 47: 1, # 'C' + 39: 1, # 'D' + 29: 1, # 'E' + 52: 2, # 'F' + 36: 0, # 'G' + 45: 2, # 'H' + 53: 1, # 'I' + 60: 0, # 'J' + 16: 0, # 'K' + 49: 0, # 'L' + 20: 1, # 'M' + 46: 1, # 'N' + 42: 1, # 'O' + 48: 2, # 'P' + 44: 1, # 'R' + 35: 1, # 'S' + 31: 1, # 'T' + 51: 1, # 'U' + 38: 1, # 'V' + 62: 0, # 'W' + 43: 2, # 'Y' + 56: 0, # 'Z' + 1: 0, # 'a' + 21: 1, # 'b' + 28: 1, # 'c' + 12: 1, # 'd' + 2: 0, # 'e' + 18: 1, # 'f' + 27: 0, # 'g' + 25: 0, # 'h' + 3: 2, # 'i' + 24: 1, # 'j' + 10: 0, # 'k' + 5: 0, # 'l' + 13: 1, # 'm' + 4: 2, # 'n' + 15: 1, # 'o' + 26: 0, # 'p' + 7: 2, # 'r' + 8: 1, # 's' + 9: 1, # 't' + 14: 1, # 'u' + 32: 0, # 'v' + 57: 0, # 'w' + 58: 0, # 'x' + 11: 1, # 'y' + 22: 1, # 'z' + 63: 0, # '·' + 54: 0, # 'Ç' + 50: 1, # 'Ö' + 55: 2, # 'Ãœ' + 59: 0, # 'â' + 33: 0, # 'ç' + 61: 0, # 'î' + 34: 2, # 'ö' + 17: 0, # 'ü' + 30: 1, # 'ÄŸ' + 41: 1, # 'Ä°' + 6: 2, # 'ı' + 40: 0, # 'Åž' + 19: 2, # 'ÅŸ' + }, + 36: { # 'G' + 23: 1, # 'A' + 37: 0, # 'B' + 47: 1, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 1, # 'F' + 36: 2, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 2, # 'K' + 49: 0, # 'L' + 20: 0, # 'M' + 46: 2, # 'N' + 42: 1, # 'O' + 48: 1, # 'P' + 44: 1, # 'R' + 35: 1, # 'S' + 31: 0, # 'T' + 51: 1, # 'U' + 38: 2, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 0, # 'Z' + 1: 3, # 'a' + 21: 0, # 'b' + 28: 1, # 'c' + 12: 0, # 'd' + 2: 3, # 'e' + 18: 0, # 'f' + 27: 0, # 'g' + 25: 0, # 'h' + 3: 0, # 'i' + 24: 1, # 'j' + 10: 1, # 'k' + 5: 0, # 'l' + 13: 3, # 'm' + 4: 2, # 'n' + 15: 0, # 'o' + 26: 1, # 'p' + 7: 0, # 'r' + 8: 1, # 's' + 9: 1, # 't' + 14: 3, # 'u' + 32: 0, # 'v' + 57: 0, # 'w' + 58: 1, # 'x' + 11: 0, # 'y' + 22: 2, # 'z' + 63: 0, # '·' + 54: 1, # 'Ç' + 50: 2, # 'Ö' + 55: 0, # 'Ãœ' + 59: 1, # 'â' + 33: 2, # 'ç' + 61: 0, # 'î' + 34: 0, # 'ö' + 17: 0, # 'ü' + 30: 1, # 'ÄŸ' + 41: 1, # 'Ä°' + 6: 2, # 'ı' + 40: 2, # 'Åž' + 19: 1, # 'ÅŸ' + }, + 45: { # 'H' + 23: 0, # 'A' + 37: 1, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 2, # 'F' + 36: 2, # 'G' + 45: 1, # 'H' + 53: 1, # 'I' + 60: 0, # 'J' + 16: 2, # 'K' + 49: 1, # 'L' + 20: 0, # 'M' + 46: 1, # 'N' + 42: 1, # 'O' + 48: 1, # 'P' + 44: 0, # 'R' + 35: 2, # 'S' + 31: 0, # 'T' + 51: 1, # 'U' + 38: 2, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 0, # 'Z' + 1: 3, # 'a' + 21: 0, # 'b' + 28: 2, # 'c' + 12: 0, # 'd' + 2: 3, # 'e' + 18: 0, # 'f' + 27: 0, # 'g' + 25: 0, # 'h' + 3: 2, # 'i' + 24: 0, # 'j' + 10: 1, # 'k' + 5: 0, # 'l' + 13: 2, # 'm' + 4: 0, # 'n' + 15: 1, # 'o' + 26: 1, # 'p' + 7: 1, # 'r' + 8: 0, # 's' + 9: 0, # 't' + 14: 3, # 'u' + 32: 0, # 'v' + 57: 0, # 'w' + 58: 0, # 'x' + 11: 0, # 'y' + 22: 2, # 'z' + 63: 0, # '·' + 54: 1, # 'Ç' + 50: 1, # 'Ö' + 55: 0, # 'Ãœ' + 59: 0, # 'â' + 33: 1, # 'ç' + 61: 0, # 'î' + 34: 1, # 'ö' + 17: 0, # 'ü' + 30: 2, # 'ÄŸ' + 41: 1, # 'Ä°' + 6: 0, # 'ı' + 40: 2, # 'Åž' + 19: 1, # 'ÅŸ' + }, + 53: { # 'I' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 1, # 'F' + 36: 0, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 2, # 'K' + 49: 0, # 'L' + 20: 0, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 1, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 0, # 'T' + 51: 0, # 'U' + 38: 0, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 0, # 'Z' + 1: 2, # 'a' + 21: 0, # 'b' + 28: 2, # 'c' + 12: 0, # 'd' + 2: 2, # 'e' + 18: 0, # 'f' + 27: 0, # 'g' + 25: 0, # 'h' + 3: 0, # 'i' + 24: 0, # 'j' + 10: 0, # 'k' + 5: 2, # 'l' + 13: 2, # 'm' + 4: 0, # 'n' + 15: 0, # 'o' + 26: 0, # 'p' + 7: 0, # 'r' + 8: 0, # 's' + 9: 0, # 't' + 14: 2, # 'u' + 32: 0, # 'v' + 57: 0, # 'w' + 58: 0, # 'x' + 11: 0, # 'y' + 22: 2, # 'z' + 63: 0, # '·' + 54: 1, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ãœ' + 59: 0, # 'â' + 33: 2, # 'ç' + 61: 0, # 'î' + 34: 1, # 'ö' + 17: 0, # 'ü' + 30: 0, # 'ÄŸ' + 41: 0, # 'Ä°' + 6: 0, # 'ı' + 40: 1, # 'Åž' + 19: 1, # 'ÅŸ' + }, + 60: { # 'J' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 0, # 'F' + 36: 0, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 0, # 'K' + 49: 0, # 'L' + 20: 1, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 0, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 0, # 'T' + 51: 0, # 'U' + 38: 0, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 0, # 'Z' + 1: 0, # 'a' + 21: 1, # 'b' + 28: 0, # 'c' + 12: 1, # 'd' + 2: 0, # 'e' + 18: 0, # 'f' + 27: 0, # 'g' + 25: 0, # 'h' + 3: 1, # 'i' + 24: 0, # 'j' + 10: 0, # 'k' + 5: 0, # 'l' + 13: 0, # 'm' + 4: 1, # 'n' + 15: 0, # 'o' + 26: 0, # 'p' + 7: 0, # 'r' + 8: 1, # 's' + 9: 0, # 't' + 14: 0, # 'u' + 32: 0, # 'v' + 57: 0, # 'w' + 58: 0, # 'x' + 11: 0, # 'y' + 22: 0, # 'z' + 63: 0, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ãœ' + 59: 0, # 'â' + 33: 0, # 'ç' + 61: 0, # 'î' + 34: 0, # 'ö' + 17: 0, # 'ü' + 30: 0, # 'ÄŸ' + 41: 0, # 'Ä°' + 6: 0, # 'ı' + 40: 0, # 'Åž' + 19: 0, # 'ÅŸ' + }, + 16: { # 'K' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 3, # 'E' + 52: 0, # 'F' + 36: 0, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 0, # 'K' + 49: 0, # 'L' + 20: 2, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 0, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 2, # 'T' + 51: 0, # 'U' + 38: 0, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 0, # 'Z' + 1: 2, # 'a' + 21: 3, # 'b' + 28: 0, # 'c' + 12: 3, # 'd' + 2: 1, # 'e' + 18: 3, # 'f' + 27: 3, # 'g' + 25: 3, # 'h' + 3: 3, # 'i' + 24: 2, # 'j' + 10: 3, # 'k' + 5: 0, # 'l' + 13: 0, # 'm' + 4: 3, # 'n' + 15: 0, # 'o' + 26: 1, # 'p' + 7: 3, # 'r' + 8: 3, # 's' + 9: 3, # 't' + 14: 0, # 'u' + 32: 3, # 'v' + 57: 0, # 'w' + 58: 0, # 'x' + 11: 2, # 'y' + 22: 1, # 'z' + 63: 0, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ãœ' + 59: 0, # 'â' + 33: 0, # 'ç' + 61: 0, # 'î' + 34: 0, # 'ö' + 17: 2, # 'ü' + 30: 0, # 'ÄŸ' + 41: 1, # 'Ä°' + 6: 3, # 'ı' + 40: 0, # 'Åž' + 19: 0, # 'ÅŸ' + }, + 49: { # 'L' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 2, # 'E' + 52: 0, # 'F' + 36: 1, # 'G' + 45: 1, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 0, # 'K' + 49: 0, # 'L' + 20: 1, # 'M' + 46: 0, # 'N' + 42: 2, # 'O' + 48: 0, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 0, # 'T' + 51: 0, # 'U' + 38: 0, # 'V' + 62: 0, # 'W' + 43: 1, # 'Y' + 56: 0, # 'Z' + 1: 0, # 'a' + 21: 3, # 'b' + 28: 0, # 'c' + 12: 2, # 'd' + 2: 0, # 'e' + 18: 0, # 'f' + 27: 0, # 'g' + 25: 0, # 'h' + 3: 2, # 'i' + 24: 0, # 'j' + 10: 1, # 'k' + 5: 0, # 'l' + 13: 0, # 'm' + 4: 2, # 'n' + 15: 1, # 'o' + 26: 1, # 'p' + 7: 1, # 'r' + 8: 1, # 's' + 9: 1, # 't' + 14: 0, # 'u' + 32: 0, # 'v' + 57: 0, # 'w' + 58: 0, # 'x' + 11: 2, # 'y' + 22: 0, # 'z' + 63: 0, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 2, # 'Ãœ' + 59: 0, # 'â' + 33: 0, # 'ç' + 61: 0, # 'î' + 34: 1, # 'ö' + 17: 1, # 'ü' + 30: 1, # 'ÄŸ' + 41: 0, # 'Ä°' + 6: 2, # 'ı' + 40: 0, # 'Åž' + 19: 0, # 'ÅŸ' + }, + 20: { # 'M' + 23: 1, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 0, # 'F' + 36: 0, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 1, # 'J' + 16: 3, # 'K' + 49: 0, # 'L' + 20: 2, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 0, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 1, # 'T' + 51: 0, # 'U' + 38: 0, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 0, # 'Z' + 1: 3, # 'a' + 21: 2, # 'b' + 28: 0, # 'c' + 12: 3, # 'd' + 2: 3, # 'e' + 18: 0, # 'f' + 27: 1, # 'g' + 25: 1, # 'h' + 3: 2, # 'i' + 24: 2, # 'j' + 10: 2, # 'k' + 5: 2, # 'l' + 13: 3, # 'm' + 4: 3, # 'n' + 15: 0, # 'o' + 26: 1, # 'p' + 7: 3, # 'r' + 8: 0, # 's' + 9: 2, # 't' + 14: 3, # 'u' + 32: 0, # 'v' + 57: 0, # 'w' + 58: 0, # 'x' + 11: 2, # 'y' + 22: 0, # 'z' + 63: 0, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ãœ' + 59: 0, # 'â' + 33: 3, # 'ç' + 61: 0, # 'î' + 34: 0, # 'ö' + 17: 0, # 'ü' + 30: 0, # 'ÄŸ' + 41: 0, # 'Ä°' + 6: 3, # 'ı' + 40: 0, # 'Åž' + 19: 0, # 'ÅŸ' + }, + 46: { # 'N' + 23: 0, # 'A' + 37: 1, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 1, # 'F' + 36: 1, # 'G' + 45: 1, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 2, # 'K' + 49: 0, # 'L' + 20: 0, # 'M' + 46: 1, # 'N' + 42: 0, # 'O' + 48: 0, # 'P' + 44: 1, # 'R' + 35: 1, # 'S' + 31: 0, # 'T' + 51: 1, # 'U' + 38: 2, # 'V' + 62: 0, # 'W' + 43: 1, # 'Y' + 56: 0, # 'Z' + 1: 3, # 'a' + 21: 0, # 'b' + 28: 2, # 'c' + 12: 0, # 'd' + 2: 3, # 'e' + 18: 0, # 'f' + 27: 1, # 'g' + 25: 0, # 'h' + 3: 0, # 'i' + 24: 2, # 'j' + 10: 1, # 'k' + 5: 1, # 'l' + 13: 3, # 'm' + 4: 2, # 'n' + 15: 1, # 'o' + 26: 1, # 'p' + 7: 1, # 'r' + 8: 0, # 's' + 9: 0, # 't' + 14: 3, # 'u' + 32: 0, # 'v' + 57: 0, # 'w' + 58: 1, # 'x' + 11: 1, # 'y' + 22: 2, # 'z' + 63: 0, # '·' + 54: 1, # 'Ç' + 50: 1, # 'Ö' + 55: 0, # 'Ãœ' + 59: 0, # 'â' + 33: 0, # 'ç' + 61: 0, # 'î' + 34: 1, # 'ö' + 17: 0, # 'ü' + 30: 0, # 'ÄŸ' + 41: 1, # 'Ä°' + 6: 2, # 'ı' + 40: 1, # 'Åž' + 19: 1, # 'ÅŸ' + }, + 42: { # 'O' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 1, # 'F' + 36: 0, # 'G' + 45: 1, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 2, # 'K' + 49: 1, # 'L' + 20: 0, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 2, # 'P' + 44: 1, # 'R' + 35: 1, # 'S' + 31: 0, # 'T' + 51: 1, # 'U' + 38: 1, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 0, # 'Z' + 1: 3, # 'a' + 21: 0, # 'b' + 28: 2, # 'c' + 12: 0, # 'd' + 2: 2, # 'e' + 18: 0, # 'f' + 27: 0, # 'g' + 25: 0, # 'h' + 3: 0, # 'i' + 24: 0, # 'j' + 10: 0, # 'k' + 5: 3, # 'l' + 13: 3, # 'm' + 4: 0, # 'n' + 15: 1, # 'o' + 26: 0, # 'p' + 7: 0, # 'r' + 8: 0, # 's' + 9: 0, # 't' + 14: 2, # 'u' + 32: 0, # 'v' + 57: 0, # 'w' + 58: 0, # 'x' + 11: 0, # 'y' + 22: 2, # 'z' + 63: 0, # '·' + 54: 2, # 'Ç' + 50: 1, # 'Ö' + 55: 0, # 'Ãœ' + 59: 0, # 'â' + 33: 2, # 'ç' + 61: 0, # 'î' + 34: 1, # 'ö' + 17: 0, # 'ü' + 30: 1, # 'ÄŸ' + 41: 2, # 'Ä°' + 6: 1, # 'ı' + 40: 1, # 'Åž' + 19: 1, # 'ÅŸ' + }, + 48: { # 'P' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 2, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 2, # 'F' + 36: 1, # 'G' + 45: 1, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 2, # 'K' + 49: 0, # 'L' + 20: 0, # 'M' + 46: 1, # 'N' + 42: 1, # 'O' + 48: 1, # 'P' + 44: 0, # 'R' + 35: 1, # 'S' + 31: 0, # 'T' + 51: 0, # 'U' + 38: 1, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 0, # 'Z' + 1: 2, # 'a' + 21: 0, # 'b' + 28: 2, # 'c' + 12: 0, # 'd' + 2: 3, # 'e' + 18: 0, # 'f' + 27: 0, # 'g' + 25: 0, # 'h' + 3: 0, # 'i' + 24: 0, # 'j' + 10: 1, # 'k' + 5: 0, # 'l' + 13: 2, # 'm' + 4: 0, # 'n' + 15: 2, # 'o' + 26: 0, # 'p' + 7: 0, # 'r' + 8: 0, # 's' + 9: 0, # 't' + 14: 2, # 'u' + 32: 0, # 'v' + 57: 0, # 'w' + 58: 2, # 'x' + 11: 0, # 'y' + 22: 2, # 'z' + 63: 0, # '·' + 54: 1, # 'Ç' + 50: 2, # 'Ö' + 55: 0, # 'Ãœ' + 59: 0, # 'â' + 33: 0, # 'ç' + 61: 0, # 'î' + 34: 2, # 'ö' + 17: 0, # 'ü' + 30: 1, # 'ÄŸ' + 41: 1, # 'Ä°' + 6: 0, # 'ı' + 40: 2, # 'Åž' + 19: 1, # 'ÅŸ' + }, + 44: { # 'R' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 1, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 1, # 'F' + 36: 0, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 3, # 'K' + 49: 0, # 'L' + 20: 0, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 1, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 0, # 'T' + 51: 0, # 'U' + 38: 0, # 'V' + 62: 0, # 'W' + 43: 1, # 'Y' + 56: 0, # 'Z' + 1: 3, # 'a' + 21: 1, # 'b' + 28: 1, # 'c' + 12: 0, # 'd' + 2: 2, # 'e' + 18: 0, # 'f' + 27: 0, # 'g' + 25: 0, # 'h' + 3: 0, # 'i' + 24: 0, # 'j' + 10: 1, # 'k' + 5: 2, # 'l' + 13: 2, # 'm' + 4: 0, # 'n' + 15: 1, # 'o' + 26: 0, # 'p' + 7: 0, # 'r' + 8: 0, # 's' + 9: 0, # 't' + 14: 2, # 'u' + 32: 0, # 'v' + 57: 0, # 'w' + 58: 0, # 'x' + 11: 1, # 'y' + 22: 2, # 'z' + 63: 0, # '·' + 54: 0, # 'Ç' + 50: 1, # 'Ö' + 55: 0, # 'Ãœ' + 59: 0, # 'â' + 33: 1, # 'ç' + 61: 0, # 'î' + 34: 1, # 'ö' + 17: 1, # 'ü' + 30: 1, # 'ÄŸ' + 41: 0, # 'Ä°' + 6: 2, # 'ı' + 40: 1, # 'Åž' + 19: 1, # 'ÅŸ' + }, + 35: { # 'S' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 1, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 1, # 'F' + 36: 1, # 'G' + 45: 1, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 3, # 'K' + 49: 1, # 'L' + 20: 1, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 1, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 0, # 'T' + 51: 1, # 'U' + 38: 1, # 'V' + 62: 0, # 'W' + 43: 1, # 'Y' + 56: 0, # 'Z' + 1: 3, # 'a' + 21: 0, # 'b' + 28: 2, # 'c' + 12: 0, # 'd' + 2: 3, # 'e' + 18: 0, # 'f' + 27: 0, # 'g' + 25: 0, # 'h' + 3: 0, # 'i' + 24: 0, # 'j' + 10: 1, # 'k' + 5: 1, # 'l' + 13: 2, # 'm' + 4: 1, # 'n' + 15: 0, # 'o' + 26: 0, # 'p' + 7: 0, # 'r' + 8: 0, # 's' + 9: 1, # 't' + 14: 2, # 'u' + 32: 0, # 'v' + 57: 0, # 'w' + 58: 0, # 'x' + 11: 0, # 'y' + 22: 1, # 'z' + 63: 0, # '·' + 54: 2, # 'Ç' + 50: 2, # 'Ö' + 55: 0, # 'Ãœ' + 59: 0, # 'â' + 33: 3, # 'ç' + 61: 0, # 'î' + 34: 1, # 'ö' + 17: 0, # 'ü' + 30: 0, # 'ÄŸ' + 41: 0, # 'Ä°' + 6: 3, # 'ı' + 40: 2, # 'Åž' + 19: 1, # 'ÅŸ' + }, + 31: { # 'T' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 0, # 'F' + 36: 0, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 1, # 'J' + 16: 2, # 'K' + 49: 0, # 'L' + 20: 1, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 0, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 2, # 'T' + 51: 0, # 'U' + 38: 0, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 0, # 'Z' + 1: 3, # 'a' + 21: 2, # 'b' + 28: 0, # 'c' + 12: 1, # 'd' + 2: 3, # 'e' + 18: 2, # 'f' + 27: 2, # 'g' + 25: 0, # 'h' + 3: 1, # 'i' + 24: 1, # 'j' + 10: 2, # 'k' + 5: 2, # 'l' + 13: 3, # 'm' + 4: 3, # 'n' + 15: 0, # 'o' + 26: 2, # 'p' + 7: 2, # 'r' + 8: 0, # 's' + 9: 2, # 't' + 14: 2, # 'u' + 32: 1, # 'v' + 57: 1, # 'w' + 58: 1, # 'x' + 11: 2, # 'y' + 22: 0, # 'z' + 63: 0, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ãœ' + 59: 0, # 'â' + 33: 0, # 'ç' + 61: 0, # 'î' + 34: 0, # 'ö' + 17: 1, # 'ü' + 30: 0, # 'ÄŸ' + 41: 0, # 'Ä°' + 6: 3, # 'ı' + 40: 0, # 'Åž' + 19: 0, # 'ÅŸ' + }, + 51: { # 'U' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 1, # 'F' + 36: 1, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 1, # 'K' + 49: 0, # 'L' + 20: 0, # 'M' + 46: 1, # 'N' + 42: 0, # 'O' + 48: 1, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 0, # 'T' + 51: 1, # 'U' + 38: 1, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 0, # 'Z' + 1: 3, # 'a' + 21: 0, # 'b' + 28: 1, # 'c' + 12: 0, # 'd' + 2: 3, # 'e' + 18: 0, # 'f' + 27: 2, # 'g' + 25: 0, # 'h' + 3: 0, # 'i' + 24: 0, # 'j' + 10: 1, # 'k' + 5: 1, # 'l' + 13: 3, # 'm' + 4: 2, # 'n' + 15: 0, # 'o' + 26: 1, # 'p' + 7: 0, # 'r' + 8: 0, # 's' + 9: 0, # 't' + 14: 2, # 'u' + 32: 0, # 'v' + 57: 0, # 'w' + 58: 0, # 'x' + 11: 0, # 'y' + 22: 2, # 'z' + 63: 0, # '·' + 54: 1, # 'Ç' + 50: 1, # 'Ö' + 55: 0, # 'Ãœ' + 59: 0, # 'â' + 33: 0, # 'ç' + 61: 0, # 'î' + 34: 0, # 'ö' + 17: 0, # 'ü' + 30: 1, # 'ÄŸ' + 41: 1, # 'Ä°' + 6: 2, # 'ı' + 40: 0, # 'Åž' + 19: 1, # 'ÅŸ' + }, + 38: { # 'V' + 23: 1, # 'A' + 37: 1, # 'B' + 47: 1, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 2, # 'F' + 36: 0, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 3, # 'K' + 49: 0, # 'L' + 20: 3, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 1, # 'P' + 44: 1, # 'R' + 35: 0, # 'S' + 31: 0, # 'T' + 51: 1, # 'U' + 38: 1, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 0, # 'Z' + 1: 3, # 'a' + 21: 0, # 'b' + 28: 2, # 'c' + 12: 0, # 'd' + 2: 3, # 'e' + 18: 0, # 'f' + 27: 0, # 'g' + 25: 0, # 'h' + 3: 0, # 'i' + 24: 0, # 'j' + 10: 0, # 'k' + 5: 2, # 'l' + 13: 2, # 'm' + 4: 0, # 'n' + 15: 2, # 'o' + 26: 0, # 'p' + 7: 0, # 'r' + 8: 0, # 's' + 9: 1, # 't' + 14: 3, # 'u' + 32: 0, # 'v' + 57: 0, # 'w' + 58: 0, # 'x' + 11: 1, # 'y' + 22: 2, # 'z' + 63: 0, # '·' + 54: 1, # 'Ç' + 50: 1, # 'Ö' + 55: 0, # 'Ãœ' + 59: 1, # 'â' + 33: 2, # 'ç' + 61: 0, # 'î' + 34: 1, # 'ö' + 17: 0, # 'ü' + 30: 1, # 'ÄŸ' + 41: 1, # 'Ä°' + 6: 3, # 'ı' + 40: 2, # 'Åž' + 19: 1, # 'ÅŸ' + }, + 62: { # 'W' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 0, # 'F' + 36: 0, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 0, # 'K' + 49: 0, # 'L' + 20: 0, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 0, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 0, # 'T' + 51: 0, # 'U' + 38: 0, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 0, # 'Z' + 1: 0, # 'a' + 21: 0, # 'b' + 28: 0, # 'c' + 12: 0, # 'd' + 2: 0, # 'e' + 18: 0, # 'f' + 27: 0, # 'g' + 25: 0, # 'h' + 3: 0, # 'i' + 24: 0, # 'j' + 10: 0, # 'k' + 5: 0, # 'l' + 13: 0, # 'm' + 4: 0, # 'n' + 15: 0, # 'o' + 26: 0, # 'p' + 7: 0, # 'r' + 8: 0, # 's' + 9: 0, # 't' + 14: 0, # 'u' + 32: 0, # 'v' + 57: 0, # 'w' + 58: 0, # 'x' + 11: 0, # 'y' + 22: 0, # 'z' + 63: 0, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ãœ' + 59: 0, # 'â' + 33: 0, # 'ç' + 61: 0, # 'î' + 34: 0, # 'ö' + 17: 0, # 'ü' + 30: 0, # 'ÄŸ' + 41: 0, # 'Ä°' + 6: 0, # 'ı' + 40: 0, # 'Åž' + 19: 0, # 'ÅŸ' + }, + 43: { # 'Y' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 1, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 2, # 'F' + 36: 0, # 'G' + 45: 1, # 'H' + 53: 1, # 'I' + 60: 0, # 'J' + 16: 2, # 'K' + 49: 0, # 'L' + 20: 0, # 'M' + 46: 2, # 'N' + 42: 0, # 'O' + 48: 2, # 'P' + 44: 1, # 'R' + 35: 1, # 'S' + 31: 0, # 'T' + 51: 1, # 'U' + 38: 2, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 0, # 'Z' + 1: 3, # 'a' + 21: 0, # 'b' + 28: 2, # 'c' + 12: 0, # 'd' + 2: 2, # 'e' + 18: 0, # 'f' + 27: 0, # 'g' + 25: 0, # 'h' + 3: 0, # 'i' + 24: 1, # 'j' + 10: 1, # 'k' + 5: 1, # 'l' + 13: 3, # 'm' + 4: 0, # 'n' + 15: 2, # 'o' + 26: 0, # 'p' + 7: 0, # 'r' + 8: 0, # 's' + 9: 0, # 't' + 14: 3, # 'u' + 32: 0, # 'v' + 57: 0, # 'w' + 58: 1, # 'x' + 11: 0, # 'y' + 22: 2, # 'z' + 63: 0, # '·' + 54: 1, # 'Ç' + 50: 2, # 'Ö' + 55: 1, # 'Ãœ' + 59: 1, # 'â' + 33: 0, # 'ç' + 61: 0, # 'î' + 34: 1, # 'ö' + 17: 0, # 'ü' + 30: 1, # 'ÄŸ' + 41: 1, # 'Ä°' + 6: 0, # 'ı' + 40: 2, # 'Åž' + 19: 1, # 'ÅŸ' + }, + 56: { # 'Z' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 0, # 'F' + 36: 0, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 0, # 'K' + 49: 0, # 'L' + 20: 0, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 0, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 0, # 'T' + 51: 0, # 'U' + 38: 0, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 2, # 'Z' + 1: 2, # 'a' + 21: 1, # 'b' + 28: 0, # 'c' + 12: 0, # 'd' + 2: 2, # 'e' + 18: 0, # 'f' + 27: 0, # 'g' + 25: 0, # 'h' + 3: 2, # 'i' + 24: 1, # 'j' + 10: 0, # 'k' + 5: 0, # 'l' + 13: 1, # 'm' + 4: 1, # 'n' + 15: 0, # 'o' + 26: 0, # 'p' + 7: 1, # 'r' + 8: 1, # 's' + 9: 0, # 't' + 14: 2, # 'u' + 32: 0, # 'v' + 57: 0, # 'w' + 58: 0, # 'x' + 11: 0, # 'y' + 22: 0, # 'z' + 63: 0, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ãœ' + 59: 0, # 'â' + 33: 0, # 'ç' + 61: 0, # 'î' + 34: 0, # 'ö' + 17: 1, # 'ü' + 30: 0, # 'ÄŸ' + 41: 0, # 'Ä°' + 6: 1, # 'ı' + 40: 0, # 'Åž' + 19: 0, # 'ÅŸ' + }, + 1: { # 'a' + 23: 3, # 'A' + 37: 0, # 'B' + 47: 1, # 'C' + 39: 0, # 'D' + 29: 3, # 'E' + 52: 0, # 'F' + 36: 1, # 'G' + 45: 1, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 0, # 'K' + 49: 0, # 'L' + 20: 3, # 'M' + 46: 1, # 'N' + 42: 0, # 'O' + 48: 1, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 3, # 'T' + 51: 0, # 'U' + 38: 1, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 2, # 'Z' + 1: 2, # 'a' + 21: 3, # 'b' + 28: 0, # 'c' + 12: 3, # 'd' + 2: 2, # 'e' + 18: 3, # 'f' + 27: 3, # 'g' + 25: 3, # 'h' + 3: 3, # 'i' + 24: 3, # 'j' + 10: 3, # 'k' + 5: 0, # 'l' + 13: 2, # 'm' + 4: 3, # 'n' + 15: 1, # 'o' + 26: 3, # 'p' + 7: 3, # 'r' + 8: 3, # 's' + 9: 3, # 't' + 14: 3, # 'u' + 32: 3, # 'v' + 57: 2, # 'w' + 58: 0, # 'x' + 11: 3, # 'y' + 22: 0, # 'z' + 63: 1, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ãœ' + 59: 0, # 'â' + 33: 1, # 'ç' + 61: 1, # 'î' + 34: 1, # 'ö' + 17: 3, # 'ü' + 30: 0, # 'ÄŸ' + 41: 0, # 'Ä°' + 6: 3, # 'ı' + 40: 0, # 'Åž' + 19: 1, # 'ÅŸ' + }, + 21: { # 'b' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 0, # 'F' + 36: 1, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 1, # 'J' + 16: 2, # 'K' + 49: 0, # 'L' + 20: 2, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 0, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 1, # 'T' + 51: 0, # 'U' + 38: 0, # 'V' + 62: 0, # 'W' + 43: 1, # 'Y' + 56: 0, # 'Z' + 1: 3, # 'a' + 21: 2, # 'b' + 28: 0, # 'c' + 12: 3, # 'd' + 2: 3, # 'e' + 18: 0, # 'f' + 27: 3, # 'g' + 25: 1, # 'h' + 3: 3, # 'i' + 24: 2, # 'j' + 10: 3, # 'k' + 5: 3, # 'l' + 13: 3, # 'm' + 4: 3, # 'n' + 15: 0, # 'o' + 26: 3, # 'p' + 7: 1, # 'r' + 8: 2, # 's' + 9: 2, # 't' + 14: 2, # 'u' + 32: 1, # 'v' + 57: 0, # 'w' + 58: 1, # 'x' + 11: 3, # 'y' + 22: 0, # 'z' + 63: 0, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ãœ' + 59: 0, # 'â' + 33: 1, # 'ç' + 61: 0, # 'î' + 34: 0, # 'ö' + 17: 0, # 'ü' + 30: 1, # 'ÄŸ' + 41: 0, # 'Ä°' + 6: 2, # 'ı' + 40: 0, # 'Åž' + 19: 0, # 'ÅŸ' + }, + 28: { # 'c' + 23: 0, # 'A' + 37: 1, # 'B' + 47: 1, # 'C' + 39: 1, # 'D' + 29: 2, # 'E' + 52: 0, # 'F' + 36: 2, # 'G' + 45: 2, # 'H' + 53: 1, # 'I' + 60: 0, # 'J' + 16: 0, # 'K' + 49: 0, # 'L' + 20: 2, # 'M' + 46: 1, # 'N' + 42: 1, # 'O' + 48: 2, # 'P' + 44: 1, # 'R' + 35: 1, # 'S' + 31: 2, # 'T' + 51: 2, # 'U' + 38: 2, # 'V' + 62: 0, # 'W' + 43: 3, # 'Y' + 56: 0, # 'Z' + 1: 1, # 'a' + 21: 1, # 'b' + 28: 2, # 'c' + 12: 2, # 'd' + 2: 1, # 'e' + 18: 1, # 'f' + 27: 2, # 'g' + 25: 2, # 'h' + 3: 3, # 'i' + 24: 1, # 'j' + 10: 3, # 'k' + 5: 0, # 'l' + 13: 2, # 'm' + 4: 3, # 'n' + 15: 2, # 'o' + 26: 2, # 'p' + 7: 3, # 'r' + 8: 3, # 's' + 9: 3, # 't' + 14: 1, # 'u' + 32: 0, # 'v' + 57: 1, # 'w' + 58: 0, # 'x' + 11: 2, # 'y' + 22: 1, # 'z' + 63: 1, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 1, # 'Ãœ' + 59: 0, # 'â' + 33: 0, # 'ç' + 61: 1, # 'î' + 34: 2, # 'ö' + 17: 2, # 'ü' + 30: 2, # 'ÄŸ' + 41: 1, # 'Ä°' + 6: 3, # 'ı' + 40: 0, # 'Åž' + 19: 2, # 'ÅŸ' + }, + 12: { # 'd' + 23: 1, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 0, # 'F' + 36: 0, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 2, # 'J' + 16: 3, # 'K' + 49: 0, # 'L' + 20: 3, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 0, # 'P' + 44: 0, # 'R' + 35: 1, # 'S' + 31: 1, # 'T' + 51: 0, # 'U' + 38: 0, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 0, # 'Z' + 1: 3, # 'a' + 21: 2, # 'b' + 28: 1, # 'c' + 12: 3, # 'd' + 2: 3, # 'e' + 18: 1, # 'f' + 27: 3, # 'g' + 25: 3, # 'h' + 3: 2, # 'i' + 24: 3, # 'j' + 10: 2, # 'k' + 5: 3, # 'l' + 13: 3, # 'm' + 4: 3, # 'n' + 15: 1, # 'o' + 26: 2, # 'p' + 7: 3, # 'r' + 8: 2, # 's' + 9: 2, # 't' + 14: 3, # 'u' + 32: 1, # 'v' + 57: 0, # 'w' + 58: 1, # 'x' + 11: 3, # 'y' + 22: 1, # 'z' + 63: 1, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ãœ' + 59: 0, # 'â' + 33: 0, # 'ç' + 61: 0, # 'î' + 34: 0, # 'ö' + 17: 1, # 'ü' + 30: 0, # 'ÄŸ' + 41: 0, # 'Ä°' + 6: 2, # 'ı' + 40: 0, # 'Åž' + 19: 0, # 'ÅŸ' + }, + 2: { # 'e' + 23: 2, # 'A' + 37: 0, # 'B' + 47: 2, # 'C' + 39: 0, # 'D' + 29: 3, # 'E' + 52: 1, # 'F' + 36: 0, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 1, # 'K' + 49: 0, # 'L' + 20: 3, # 'M' + 46: 1, # 'N' + 42: 0, # 'O' + 48: 1, # 'P' + 44: 1, # 'R' + 35: 0, # 'S' + 31: 3, # 'T' + 51: 0, # 'U' + 38: 1, # 'V' + 62: 0, # 'W' + 43: 1, # 'Y' + 56: 0, # 'Z' + 1: 3, # 'a' + 21: 3, # 'b' + 28: 0, # 'c' + 12: 3, # 'd' + 2: 2, # 'e' + 18: 3, # 'f' + 27: 3, # 'g' + 25: 3, # 'h' + 3: 3, # 'i' + 24: 3, # 'j' + 10: 3, # 'k' + 5: 0, # 'l' + 13: 2, # 'm' + 4: 3, # 'n' + 15: 1, # 'o' + 26: 3, # 'p' + 7: 3, # 'r' + 8: 3, # 's' + 9: 3, # 't' + 14: 3, # 'u' + 32: 3, # 'v' + 57: 2, # 'w' + 58: 0, # 'x' + 11: 3, # 'y' + 22: 1, # 'z' + 63: 1, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ãœ' + 59: 0, # 'â' + 33: 1, # 'ç' + 61: 0, # 'î' + 34: 1, # 'ö' + 17: 3, # 'ü' + 30: 0, # 'ÄŸ' + 41: 0, # 'Ä°' + 6: 3, # 'ı' + 40: 0, # 'Åž' + 19: 0, # 'ÅŸ' + }, + 18: { # 'f' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 0, # 'F' + 36: 0, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 2, # 'K' + 49: 0, # 'L' + 20: 2, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 0, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 2, # 'T' + 51: 0, # 'U' + 38: 0, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 0, # 'Z' + 1: 3, # 'a' + 21: 1, # 'b' + 28: 0, # 'c' + 12: 3, # 'd' + 2: 3, # 'e' + 18: 2, # 'f' + 27: 1, # 'g' + 25: 1, # 'h' + 3: 1, # 'i' + 24: 1, # 'j' + 10: 1, # 'k' + 5: 3, # 'l' + 13: 3, # 'm' + 4: 3, # 'n' + 15: 0, # 'o' + 26: 2, # 'p' + 7: 1, # 'r' + 8: 3, # 's' + 9: 3, # 't' + 14: 1, # 'u' + 32: 2, # 'v' + 57: 0, # 'w' + 58: 0, # 'x' + 11: 1, # 'y' + 22: 0, # 'z' + 63: 0, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ãœ' + 59: 0, # 'â' + 33: 1, # 'ç' + 61: 0, # 'î' + 34: 0, # 'ö' + 17: 1, # 'ü' + 30: 0, # 'ÄŸ' + 41: 0, # 'Ä°' + 6: 1, # 'ı' + 40: 0, # 'Åž' + 19: 0, # 'ÅŸ' + }, + 27: { # 'g' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 0, # 'F' + 36: 0, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 3, # 'K' + 49: 0, # 'L' + 20: 0, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 0, # 'P' + 44: 0, # 'R' + 35: 1, # 'S' + 31: 1, # 'T' + 51: 0, # 'U' + 38: 2, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 0, # 'Z' + 1: 3, # 'a' + 21: 1, # 'b' + 28: 0, # 'c' + 12: 1, # 'd' + 2: 3, # 'e' + 18: 0, # 'f' + 27: 2, # 'g' + 25: 1, # 'h' + 3: 2, # 'i' + 24: 3, # 'j' + 10: 2, # 'k' + 5: 3, # 'l' + 13: 3, # 'm' + 4: 2, # 'n' + 15: 0, # 'o' + 26: 1, # 'p' + 7: 2, # 'r' + 8: 2, # 's' + 9: 3, # 't' + 14: 3, # 'u' + 32: 1, # 'v' + 57: 0, # 'w' + 58: 0, # 'x' + 11: 1, # 'y' + 22: 0, # 'z' + 63: 1, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ãœ' + 59: 0, # 'â' + 33: 0, # 'ç' + 61: 0, # 'î' + 34: 0, # 'ö' + 17: 0, # 'ü' + 30: 0, # 'ÄŸ' + 41: 0, # 'Ä°' + 6: 2, # 'ı' + 40: 0, # 'Åž' + 19: 0, # 'ÅŸ' + }, + 25: { # 'h' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 0, # 'F' + 36: 0, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 2, # 'K' + 49: 0, # 'L' + 20: 0, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 0, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 0, # 'T' + 51: 0, # 'U' + 38: 0, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 0, # 'Z' + 1: 3, # 'a' + 21: 0, # 'b' + 28: 0, # 'c' + 12: 2, # 'd' + 2: 3, # 'e' + 18: 0, # 'f' + 27: 1, # 'g' + 25: 2, # 'h' + 3: 2, # 'i' + 24: 3, # 'j' + 10: 3, # 'k' + 5: 3, # 'l' + 13: 3, # 'm' + 4: 3, # 'n' + 15: 1, # 'o' + 26: 1, # 'p' + 7: 3, # 'r' + 8: 3, # 's' + 9: 2, # 't' + 14: 3, # 'u' + 32: 2, # 'v' + 57: 1, # 'w' + 58: 0, # 'x' + 11: 1, # 'y' + 22: 0, # 'z' + 63: 0, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ãœ' + 59: 0, # 'â' + 33: 0, # 'ç' + 61: 0, # 'î' + 34: 0, # 'ö' + 17: 0, # 'ü' + 30: 0, # 'ÄŸ' + 41: 0, # 'Ä°' + 6: 3, # 'ı' + 40: 0, # 'Åž' + 19: 0, # 'ÅŸ' + }, + 3: { # 'i' + 23: 2, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 0, # 'F' + 36: 0, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 1, # 'J' + 16: 3, # 'K' + 49: 0, # 'L' + 20: 3, # 'M' + 46: 0, # 'N' + 42: 1, # 'O' + 48: 0, # 'P' + 44: 0, # 'R' + 35: 1, # 'S' + 31: 2, # 'T' + 51: 0, # 'U' + 38: 1, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 0, # 'Z' + 1: 3, # 'a' + 21: 2, # 'b' + 28: 0, # 'c' + 12: 3, # 'd' + 2: 3, # 'e' + 18: 2, # 'f' + 27: 3, # 'g' + 25: 1, # 'h' + 3: 3, # 'i' + 24: 2, # 'j' + 10: 3, # 'k' + 5: 3, # 'l' + 13: 3, # 'm' + 4: 3, # 'n' + 15: 1, # 'o' + 26: 3, # 'p' + 7: 3, # 'r' + 8: 3, # 's' + 9: 3, # 't' + 14: 3, # 'u' + 32: 2, # 'v' + 57: 1, # 'w' + 58: 1, # 'x' + 11: 3, # 'y' + 22: 1, # 'z' + 63: 1, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 1, # 'Ãœ' + 59: 0, # 'â' + 33: 2, # 'ç' + 61: 0, # 'î' + 34: 0, # 'ö' + 17: 3, # 'ü' + 30: 0, # 'ÄŸ' + 41: 1, # 'Ä°' + 6: 2, # 'ı' + 40: 0, # 'Åž' + 19: 0, # 'ÅŸ' + }, + 24: { # 'j' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 0, # 'F' + 36: 0, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 1, # 'J' + 16: 2, # 'K' + 49: 0, # 'L' + 20: 2, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 1, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 1, # 'T' + 51: 0, # 'U' + 38: 0, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 1, # 'Z' + 1: 3, # 'a' + 21: 1, # 'b' + 28: 1, # 'c' + 12: 3, # 'd' + 2: 3, # 'e' + 18: 2, # 'f' + 27: 1, # 'g' + 25: 1, # 'h' + 3: 2, # 'i' + 24: 1, # 'j' + 10: 2, # 'k' + 5: 2, # 'l' + 13: 3, # 'm' + 4: 2, # 'n' + 15: 0, # 'o' + 26: 1, # 'p' + 7: 2, # 'r' + 8: 3, # 's' + 9: 2, # 't' + 14: 3, # 'u' + 32: 2, # 'v' + 57: 0, # 'w' + 58: 2, # 'x' + 11: 1, # 'y' + 22: 0, # 'z' + 63: 0, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ãœ' + 59: 0, # 'â' + 33: 1, # 'ç' + 61: 0, # 'î' + 34: 0, # 'ö' + 17: 1, # 'ü' + 30: 0, # 'ÄŸ' + 41: 0, # 'Ä°' + 6: 3, # 'ı' + 40: 0, # 'Åž' + 19: 0, # 'ÅŸ' + }, + 10: { # 'k' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 0, # 'F' + 36: 0, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 3, # 'K' + 49: 0, # 'L' + 20: 2, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 0, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 3, # 'T' + 51: 0, # 'U' + 38: 1, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 1, # 'Z' + 1: 3, # 'a' + 21: 2, # 'b' + 28: 0, # 'c' + 12: 2, # 'd' + 2: 3, # 'e' + 18: 1, # 'f' + 27: 2, # 'g' + 25: 2, # 'h' + 3: 3, # 'i' + 24: 2, # 'j' + 10: 2, # 'k' + 5: 3, # 'l' + 13: 3, # 'm' + 4: 3, # 'n' + 15: 0, # 'o' + 26: 3, # 'p' + 7: 2, # 'r' + 8: 2, # 's' + 9: 2, # 't' + 14: 3, # 'u' + 32: 0, # 'v' + 57: 0, # 'w' + 58: 1, # 'x' + 11: 3, # 'y' + 22: 0, # 'z' + 63: 1, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ãœ' + 59: 0, # 'â' + 33: 3, # 'ç' + 61: 0, # 'î' + 34: 1, # 'ö' + 17: 3, # 'ü' + 30: 1, # 'ÄŸ' + 41: 0, # 'Ä°' + 6: 3, # 'ı' + 40: 0, # 'Åž' + 19: 1, # 'ÅŸ' + }, + 5: { # 'l' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 3, # 'E' + 52: 0, # 'F' + 36: 0, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 0, # 'K' + 49: 0, # 'L' + 20: 2, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 0, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 1, # 'T' + 51: 0, # 'U' + 38: 0, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 0, # 'Z' + 1: 0, # 'a' + 21: 3, # 'b' + 28: 0, # 'c' + 12: 3, # 'd' + 2: 1, # 'e' + 18: 3, # 'f' + 27: 3, # 'g' + 25: 2, # 'h' + 3: 3, # 'i' + 24: 2, # 'j' + 10: 3, # 'k' + 5: 1, # 'l' + 13: 1, # 'm' + 4: 3, # 'n' + 15: 0, # 'o' + 26: 2, # 'p' + 7: 3, # 'r' + 8: 3, # 's' + 9: 3, # 't' + 14: 2, # 'u' + 32: 2, # 'v' + 57: 0, # 'w' + 58: 0, # 'x' + 11: 3, # 'y' + 22: 0, # 'z' + 63: 0, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ãœ' + 59: 0, # 'â' + 33: 1, # 'ç' + 61: 0, # 'î' + 34: 0, # 'ö' + 17: 2, # 'ü' + 30: 0, # 'ÄŸ' + 41: 0, # 'Ä°' + 6: 3, # 'ı' + 40: 0, # 'Åž' + 19: 0, # 'ÅŸ' + }, + 13: { # 'm' + 23: 1, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 3, # 'E' + 52: 0, # 'F' + 36: 0, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 0, # 'K' + 49: 0, # 'L' + 20: 3, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 0, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 3, # 'T' + 51: 0, # 'U' + 38: 0, # 'V' + 62: 0, # 'W' + 43: 1, # 'Y' + 56: 0, # 'Z' + 1: 2, # 'a' + 21: 3, # 'b' + 28: 0, # 'c' + 12: 3, # 'd' + 2: 2, # 'e' + 18: 3, # 'f' + 27: 3, # 'g' + 25: 3, # 'h' + 3: 3, # 'i' + 24: 3, # 'j' + 10: 3, # 'k' + 5: 0, # 'l' + 13: 2, # 'm' + 4: 3, # 'n' + 15: 1, # 'o' + 26: 2, # 'p' + 7: 3, # 'r' + 8: 3, # 's' + 9: 3, # 't' + 14: 2, # 'u' + 32: 2, # 'v' + 57: 1, # 'w' + 58: 0, # 'x' + 11: 3, # 'y' + 22: 0, # 'z' + 63: 0, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ãœ' + 59: 0, # 'â' + 33: 0, # 'ç' + 61: 0, # 'î' + 34: 0, # 'ö' + 17: 3, # 'ü' + 30: 0, # 'ÄŸ' + 41: 0, # 'Ä°' + 6: 3, # 'ı' + 40: 0, # 'Åž' + 19: 1, # 'ÅŸ' + }, + 4: { # 'n' + 23: 1, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 0, # 'F' + 36: 0, # 'G' + 45: 1, # 'H' + 53: 0, # 'I' + 60: 2, # 'J' + 16: 3, # 'K' + 49: 0, # 'L' + 20: 3, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 0, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 2, # 'T' + 51: 0, # 'U' + 38: 0, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 0, # 'Z' + 1: 3, # 'a' + 21: 2, # 'b' + 28: 1, # 'c' + 12: 3, # 'd' + 2: 3, # 'e' + 18: 1, # 'f' + 27: 2, # 'g' + 25: 3, # 'h' + 3: 2, # 'i' + 24: 2, # 'j' + 10: 3, # 'k' + 5: 3, # 'l' + 13: 3, # 'm' + 4: 3, # 'n' + 15: 1, # 'o' + 26: 3, # 'p' + 7: 2, # 'r' + 8: 3, # 's' + 9: 3, # 't' + 14: 3, # 'u' + 32: 2, # 'v' + 57: 0, # 'w' + 58: 2, # 'x' + 11: 3, # 'y' + 22: 0, # 'z' + 63: 0, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ãœ' + 59: 0, # 'â' + 33: 1, # 'ç' + 61: 0, # 'î' + 34: 0, # 'ö' + 17: 2, # 'ü' + 30: 0, # 'ÄŸ' + 41: 0, # 'Ä°' + 6: 1, # 'ı' + 40: 0, # 'Åž' + 19: 0, # 'ÅŸ' + }, + 15: { # 'o' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 1, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 2, # 'F' + 36: 1, # 'G' + 45: 1, # 'H' + 53: 1, # 'I' + 60: 0, # 'J' + 16: 3, # 'K' + 49: 2, # 'L' + 20: 0, # 'M' + 46: 2, # 'N' + 42: 1, # 'O' + 48: 2, # 'P' + 44: 1, # 'R' + 35: 0, # 'S' + 31: 0, # 'T' + 51: 0, # 'U' + 38: 0, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 0, # 'Z' + 1: 3, # 'a' + 21: 0, # 'b' + 28: 2, # 'c' + 12: 0, # 'd' + 2: 3, # 'e' + 18: 0, # 'f' + 27: 0, # 'g' + 25: 0, # 'h' + 3: 1, # 'i' + 24: 2, # 'j' + 10: 1, # 'k' + 5: 3, # 'l' + 13: 3, # 'm' + 4: 2, # 'n' + 15: 2, # 'o' + 26: 0, # 'p' + 7: 1, # 'r' + 8: 0, # 's' + 9: 0, # 't' + 14: 3, # 'u' + 32: 0, # 'v' + 57: 0, # 'w' + 58: 2, # 'x' + 11: 0, # 'y' + 22: 2, # 'z' + 63: 0, # '·' + 54: 1, # 'Ç' + 50: 2, # 'Ö' + 55: 0, # 'Ãœ' + 59: 0, # 'â' + 33: 3, # 'ç' + 61: 0, # 'î' + 34: 1, # 'ö' + 17: 0, # 'ü' + 30: 2, # 'ÄŸ' + 41: 2, # 'Ä°' + 6: 3, # 'ı' + 40: 2, # 'Åž' + 19: 2, # 'ÅŸ' + }, + 26: { # 'p' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 0, # 'F' + 36: 0, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 3, # 'K' + 49: 0, # 'L' + 20: 1, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 0, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 0, # 'T' + 51: 0, # 'U' + 38: 0, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 0, # 'Z' + 1: 3, # 'a' + 21: 1, # 'b' + 28: 0, # 'c' + 12: 1, # 'd' + 2: 3, # 'e' + 18: 0, # 'f' + 27: 1, # 'g' + 25: 1, # 'h' + 3: 2, # 'i' + 24: 3, # 'j' + 10: 1, # 'k' + 5: 3, # 'l' + 13: 3, # 'm' + 4: 2, # 'n' + 15: 0, # 'o' + 26: 2, # 'p' + 7: 2, # 'r' + 8: 1, # 's' + 9: 1, # 't' + 14: 3, # 'u' + 32: 0, # 'v' + 57: 0, # 'w' + 58: 1, # 'x' + 11: 1, # 'y' + 22: 0, # 'z' + 63: 0, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ãœ' + 59: 0, # 'â' + 33: 3, # 'ç' + 61: 0, # 'î' + 34: 0, # 'ö' + 17: 1, # 'ü' + 30: 0, # 'ÄŸ' + 41: 0, # 'Ä°' + 6: 3, # 'ı' + 40: 0, # 'Åž' + 19: 0, # 'ÅŸ' + }, + 7: { # 'r' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 1, # 'F' + 36: 0, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 2, # 'J' + 16: 3, # 'K' + 49: 0, # 'L' + 20: 2, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 0, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 2, # 'T' + 51: 1, # 'U' + 38: 0, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 1, # 'Z' + 1: 3, # 'a' + 21: 1, # 'b' + 28: 0, # 'c' + 12: 3, # 'd' + 2: 3, # 'e' + 18: 0, # 'f' + 27: 2, # 'g' + 25: 3, # 'h' + 3: 2, # 'i' + 24: 2, # 'j' + 10: 3, # 'k' + 5: 3, # 'l' + 13: 3, # 'm' + 4: 3, # 'n' + 15: 0, # 'o' + 26: 2, # 'p' + 7: 3, # 'r' + 8: 3, # 's' + 9: 3, # 't' + 14: 3, # 'u' + 32: 2, # 'v' + 57: 0, # 'w' + 58: 1, # 'x' + 11: 2, # 'y' + 22: 0, # 'z' + 63: 1, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ãœ' + 59: 0, # 'â' + 33: 2, # 'ç' + 61: 0, # 'î' + 34: 0, # 'ö' + 17: 3, # 'ü' + 30: 0, # 'ÄŸ' + 41: 0, # 'Ä°' + 6: 2, # 'ı' + 40: 0, # 'Åž' + 19: 0, # 'ÅŸ' + }, + 8: { # 's' + 23: 1, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 0, # 'F' + 36: 1, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 3, # 'K' + 49: 0, # 'L' + 20: 3, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 0, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 2, # 'T' + 51: 0, # 'U' + 38: 0, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 1, # 'Z' + 1: 3, # 'a' + 21: 2, # 'b' + 28: 1, # 'c' + 12: 3, # 'd' + 2: 3, # 'e' + 18: 0, # 'f' + 27: 2, # 'g' + 25: 2, # 'h' + 3: 2, # 'i' + 24: 3, # 'j' + 10: 3, # 'k' + 5: 3, # 'l' + 13: 3, # 'm' + 4: 3, # 'n' + 15: 0, # 'o' + 26: 3, # 'p' + 7: 3, # 'r' + 8: 3, # 's' + 9: 3, # 't' + 14: 3, # 'u' + 32: 2, # 'v' + 57: 0, # 'w' + 58: 1, # 'x' + 11: 2, # 'y' + 22: 1, # 'z' + 63: 0, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ãœ' + 59: 0, # 'â' + 33: 2, # 'ç' + 61: 0, # 'î' + 34: 0, # 'ö' + 17: 2, # 'ü' + 30: 0, # 'ÄŸ' + 41: 0, # 'Ä°' + 6: 3, # 'ı' + 40: 0, # 'Åž' + 19: 1, # 'ÅŸ' + }, + 9: { # 't' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 0, # 'F' + 36: 0, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 1, # 'J' + 16: 3, # 'K' + 49: 0, # 'L' + 20: 2, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 0, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 2, # 'T' + 51: 0, # 'U' + 38: 0, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 1, # 'Z' + 1: 3, # 'a' + 21: 3, # 'b' + 28: 0, # 'c' + 12: 3, # 'd' + 2: 3, # 'e' + 18: 2, # 'f' + 27: 2, # 'g' + 25: 2, # 'h' + 3: 2, # 'i' + 24: 2, # 'j' + 10: 3, # 'k' + 5: 3, # 'l' + 13: 3, # 'm' + 4: 3, # 'n' + 15: 0, # 'o' + 26: 2, # 'p' + 7: 3, # 'r' + 8: 3, # 's' + 9: 3, # 't' + 14: 3, # 'u' + 32: 3, # 'v' + 57: 0, # 'w' + 58: 2, # 'x' + 11: 2, # 'y' + 22: 0, # 'z' + 63: 0, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ãœ' + 59: 0, # 'â' + 33: 3, # 'ç' + 61: 0, # 'î' + 34: 0, # 'ö' + 17: 2, # 'ü' + 30: 0, # 'ÄŸ' + 41: 0, # 'Ä°' + 6: 3, # 'ı' + 40: 0, # 'Åž' + 19: 0, # 'ÅŸ' + }, + 14: { # 'u' + 23: 3, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 3, # 'E' + 52: 0, # 'F' + 36: 0, # 'G' + 45: 1, # 'H' + 53: 0, # 'I' + 60: 1, # 'J' + 16: 0, # 'K' + 49: 0, # 'L' + 20: 3, # 'M' + 46: 2, # 'N' + 42: 0, # 'O' + 48: 1, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 3, # 'T' + 51: 0, # 'U' + 38: 0, # 'V' + 62: 0, # 'W' + 43: 1, # 'Y' + 56: 2, # 'Z' + 1: 2, # 'a' + 21: 3, # 'b' + 28: 0, # 'c' + 12: 3, # 'd' + 2: 2, # 'e' + 18: 2, # 'f' + 27: 3, # 'g' + 25: 3, # 'h' + 3: 3, # 'i' + 24: 2, # 'j' + 10: 3, # 'k' + 5: 0, # 'l' + 13: 3, # 'm' + 4: 3, # 'n' + 15: 0, # 'o' + 26: 3, # 'p' + 7: 3, # 'r' + 8: 3, # 's' + 9: 3, # 't' + 14: 3, # 'u' + 32: 2, # 'v' + 57: 2, # 'w' + 58: 0, # 'x' + 11: 3, # 'y' + 22: 0, # 'z' + 63: 1, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ãœ' + 59: 0, # 'â' + 33: 0, # 'ç' + 61: 0, # 'î' + 34: 0, # 'ö' + 17: 3, # 'ü' + 30: 1, # 'ÄŸ' + 41: 0, # 'Ä°' + 6: 3, # 'ı' + 40: 0, # 'Åž' + 19: 0, # 'ÅŸ' + }, + 32: { # 'v' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 0, # 'F' + 36: 0, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 3, # 'K' + 49: 0, # 'L' + 20: 1, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 0, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 0, # 'T' + 51: 0, # 'U' + 38: 0, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 0, # 'Z' + 1: 3, # 'a' + 21: 0, # 'b' + 28: 0, # 'c' + 12: 3, # 'd' + 2: 3, # 'e' + 18: 0, # 'f' + 27: 0, # 'g' + 25: 0, # 'h' + 3: 0, # 'i' + 24: 1, # 'j' + 10: 1, # 'k' + 5: 3, # 'l' + 13: 2, # 'm' + 4: 3, # 'n' + 15: 0, # 'o' + 26: 1, # 'p' + 7: 1, # 'r' + 8: 2, # 's' + 9: 3, # 't' + 14: 3, # 'u' + 32: 1, # 'v' + 57: 0, # 'w' + 58: 0, # 'x' + 11: 0, # 'y' + 22: 0, # 'z' + 63: 0, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ãœ' + 59: 0, # 'â' + 33: 2, # 'ç' + 61: 0, # 'î' + 34: 0, # 'ö' + 17: 0, # 'ü' + 30: 0, # 'ÄŸ' + 41: 0, # 'Ä°' + 6: 1, # 'ı' + 40: 0, # 'Åž' + 19: 0, # 'ÅŸ' + }, + 57: { # 'w' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 0, # 'F' + 36: 0, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 0, # 'K' + 49: 0, # 'L' + 20: 0, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 0, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 0, # 'T' + 51: 1, # 'U' + 38: 0, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 0, # 'Z' + 1: 1, # 'a' + 21: 0, # 'b' + 28: 0, # 'c' + 12: 0, # 'd' + 2: 2, # 'e' + 18: 0, # 'f' + 27: 0, # 'g' + 25: 1, # 'h' + 3: 0, # 'i' + 24: 0, # 'j' + 10: 1, # 'k' + 5: 0, # 'l' + 13: 0, # 'm' + 4: 1, # 'n' + 15: 0, # 'o' + 26: 0, # 'p' + 7: 0, # 'r' + 8: 1, # 's' + 9: 0, # 't' + 14: 1, # 'u' + 32: 0, # 'v' + 57: 2, # 'w' + 58: 0, # 'x' + 11: 0, # 'y' + 22: 0, # 'z' + 63: 1, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ãœ' + 59: 0, # 'â' + 33: 0, # 'ç' + 61: 0, # 'î' + 34: 0, # 'ö' + 17: 1, # 'ü' + 30: 0, # 'ÄŸ' + 41: 0, # 'Ä°' + 6: 0, # 'ı' + 40: 0, # 'Åž' + 19: 0, # 'ÅŸ' + }, + 58: { # 'x' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 1, # 'E' + 52: 0, # 'F' + 36: 0, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 1, # 'J' + 16: 0, # 'K' + 49: 0, # 'L' + 20: 1, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 0, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 0, # 'T' + 51: 0, # 'U' + 38: 0, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 0, # 'Z' + 1: 0, # 'a' + 21: 1, # 'b' + 28: 0, # 'c' + 12: 2, # 'd' + 2: 1, # 'e' + 18: 0, # 'f' + 27: 0, # 'g' + 25: 0, # 'h' + 3: 2, # 'i' + 24: 2, # 'j' + 10: 1, # 'k' + 5: 0, # 'l' + 13: 0, # 'm' + 4: 2, # 'n' + 15: 0, # 'o' + 26: 0, # 'p' + 7: 1, # 'r' + 8: 2, # 's' + 9: 1, # 't' + 14: 0, # 'u' + 32: 0, # 'v' + 57: 0, # 'w' + 58: 0, # 'x' + 11: 2, # 'y' + 22: 0, # 'z' + 63: 0, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ãœ' + 59: 0, # 'â' + 33: 0, # 'ç' + 61: 0, # 'î' + 34: 0, # 'ö' + 17: 1, # 'ü' + 30: 0, # 'ÄŸ' + 41: 0, # 'Ä°' + 6: 2, # 'ı' + 40: 0, # 'Åž' + 19: 0, # 'ÅŸ' + }, + 11: { # 'y' + 23: 1, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 0, # 'F' + 36: 0, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 1, # 'J' + 16: 3, # 'K' + 49: 0, # 'L' + 20: 1, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 0, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 1, # 'T' + 51: 0, # 'U' + 38: 0, # 'V' + 62: 0, # 'W' + 43: 1, # 'Y' + 56: 1, # 'Z' + 1: 3, # 'a' + 21: 1, # 'b' + 28: 0, # 'c' + 12: 2, # 'd' + 2: 3, # 'e' + 18: 0, # 'f' + 27: 2, # 'g' + 25: 2, # 'h' + 3: 2, # 'i' + 24: 1, # 'j' + 10: 2, # 'k' + 5: 3, # 'l' + 13: 3, # 'm' + 4: 3, # 'n' + 15: 0, # 'o' + 26: 1, # 'p' + 7: 2, # 'r' + 8: 1, # 's' + 9: 2, # 't' + 14: 3, # 'u' + 32: 0, # 'v' + 57: 0, # 'w' + 58: 1, # 'x' + 11: 3, # 'y' + 22: 0, # 'z' + 63: 0, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ãœ' + 59: 0, # 'â' + 33: 3, # 'ç' + 61: 0, # 'î' + 34: 0, # 'ö' + 17: 2, # 'ü' + 30: 0, # 'ÄŸ' + 41: 0, # 'Ä°' + 6: 3, # 'ı' + 40: 0, # 'Åž' + 19: 0, # 'ÅŸ' + }, + 22: { # 'z' + 23: 2, # 'A' + 37: 2, # 'B' + 47: 1, # 'C' + 39: 2, # 'D' + 29: 3, # 'E' + 52: 1, # 'F' + 36: 2, # 'G' + 45: 2, # 'H' + 53: 1, # 'I' + 60: 0, # 'J' + 16: 0, # 'K' + 49: 0, # 'L' + 20: 3, # 'M' + 46: 2, # 'N' + 42: 2, # 'O' + 48: 2, # 'P' + 44: 1, # 'R' + 35: 1, # 'S' + 31: 3, # 'T' + 51: 2, # 'U' + 38: 2, # 'V' + 62: 0, # 'W' + 43: 2, # 'Y' + 56: 1, # 'Z' + 1: 1, # 'a' + 21: 2, # 'b' + 28: 1, # 'c' + 12: 2, # 'd' + 2: 2, # 'e' + 18: 3, # 'f' + 27: 2, # 'g' + 25: 2, # 'h' + 3: 3, # 'i' + 24: 2, # 'j' + 10: 3, # 'k' + 5: 0, # 'l' + 13: 2, # 'm' + 4: 3, # 'n' + 15: 2, # 'o' + 26: 2, # 'p' + 7: 3, # 'r' + 8: 3, # 's' + 9: 3, # 't' + 14: 0, # 'u' + 32: 2, # 'v' + 57: 0, # 'w' + 58: 0, # 'x' + 11: 3, # 'y' + 22: 2, # 'z' + 63: 1, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 2, # 'Ãœ' + 59: 1, # 'â' + 33: 0, # 'ç' + 61: 0, # 'î' + 34: 2, # 'ö' + 17: 2, # 'ü' + 30: 2, # 'ÄŸ' + 41: 1, # 'Ä°' + 6: 3, # 'ı' + 40: 1, # 'Åž' + 19: 2, # 'ÅŸ' + }, + 63: { # '·' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 0, # 'F' + 36: 0, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 0, # 'K' + 49: 0, # 'L' + 20: 0, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 0, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 0, # 'T' + 51: 0, # 'U' + 38: 0, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 0, # 'Z' + 1: 0, # 'a' + 21: 0, # 'b' + 28: 0, # 'c' + 12: 0, # 'd' + 2: 1, # 'e' + 18: 0, # 'f' + 27: 0, # 'g' + 25: 0, # 'h' + 3: 0, # 'i' + 24: 0, # 'j' + 10: 0, # 'k' + 5: 0, # 'l' + 13: 2, # 'm' + 4: 0, # 'n' + 15: 0, # 'o' + 26: 0, # 'p' + 7: 0, # 'r' + 8: 0, # 's' + 9: 0, # 't' + 14: 2, # 'u' + 32: 0, # 'v' + 57: 0, # 'w' + 58: 0, # 'x' + 11: 0, # 'y' + 22: 0, # 'z' + 63: 0, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ãœ' + 59: 0, # 'â' + 33: 0, # 'ç' + 61: 0, # 'î' + 34: 0, # 'ö' + 17: 0, # 'ü' + 30: 0, # 'ÄŸ' + 41: 0, # 'Ä°' + 6: 0, # 'ı' + 40: 0, # 'Åž' + 19: 0, # 'ÅŸ' + }, + 54: { # 'Ç' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 1, # 'C' + 39: 1, # 'D' + 29: 0, # 'E' + 52: 0, # 'F' + 36: 1, # 'G' + 45: 1, # 'H' + 53: 1, # 'I' + 60: 0, # 'J' + 16: 0, # 'K' + 49: 0, # 'L' + 20: 0, # 'M' + 46: 0, # 'N' + 42: 1, # 'O' + 48: 1, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 0, # 'T' + 51: 1, # 'U' + 38: 1, # 'V' + 62: 0, # 'W' + 43: 2, # 'Y' + 56: 0, # 'Z' + 1: 0, # 'a' + 21: 1, # 'b' + 28: 0, # 'c' + 12: 1, # 'd' + 2: 0, # 'e' + 18: 0, # 'f' + 27: 1, # 'g' + 25: 0, # 'h' + 3: 3, # 'i' + 24: 0, # 'j' + 10: 1, # 'k' + 5: 0, # 'l' + 13: 0, # 'm' + 4: 2, # 'n' + 15: 1, # 'o' + 26: 0, # 'p' + 7: 2, # 'r' + 8: 0, # 's' + 9: 1, # 't' + 14: 0, # 'u' + 32: 2, # 'v' + 57: 0, # 'w' + 58: 0, # 'x' + 11: 0, # 'y' + 22: 0, # 'z' + 63: 0, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 2, # 'Ãœ' + 59: 0, # 'â' + 33: 0, # 'ç' + 61: 0, # 'î' + 34: 1, # 'ö' + 17: 0, # 'ü' + 30: 0, # 'ÄŸ' + 41: 0, # 'Ä°' + 6: 2, # 'ı' + 40: 0, # 'Åž' + 19: 1, # 'ÅŸ' + }, + 50: { # 'Ö' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 1, # 'C' + 39: 1, # 'D' + 29: 2, # 'E' + 52: 0, # 'F' + 36: 1, # 'G' + 45: 2, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 0, # 'K' + 49: 0, # 'L' + 20: 1, # 'M' + 46: 1, # 'N' + 42: 2, # 'O' + 48: 2, # 'P' + 44: 1, # 'R' + 35: 0, # 'S' + 31: 0, # 'T' + 51: 1, # 'U' + 38: 1, # 'V' + 62: 0, # 'W' + 43: 2, # 'Y' + 56: 0, # 'Z' + 1: 0, # 'a' + 21: 2, # 'b' + 28: 1, # 'c' + 12: 2, # 'd' + 2: 0, # 'e' + 18: 1, # 'f' + 27: 1, # 'g' + 25: 1, # 'h' + 3: 2, # 'i' + 24: 0, # 'j' + 10: 2, # 'k' + 5: 0, # 'l' + 13: 0, # 'm' + 4: 3, # 'n' + 15: 2, # 'o' + 26: 2, # 'p' + 7: 3, # 'r' + 8: 1, # 's' + 9: 2, # 't' + 14: 0, # 'u' + 32: 1, # 'v' + 57: 0, # 'w' + 58: 0, # 'x' + 11: 0, # 'y' + 22: 1, # 'z' + 63: 0, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ãœ' + 59: 0, # 'â' + 33: 0, # 'ç' + 61: 0, # 'î' + 34: 2, # 'ö' + 17: 2, # 'ü' + 30: 1, # 'ÄŸ' + 41: 0, # 'Ä°' + 6: 2, # 'ı' + 40: 0, # 'Åž' + 19: 1, # 'ÅŸ' + }, + 55: { # 'Ãœ' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 2, # 'F' + 36: 0, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 1, # 'K' + 49: 0, # 'L' + 20: 0, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 1, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 0, # 'T' + 51: 0, # 'U' + 38: 1, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 0, # 'Z' + 1: 2, # 'a' + 21: 0, # 'b' + 28: 2, # 'c' + 12: 0, # 'd' + 2: 2, # 'e' + 18: 0, # 'f' + 27: 1, # 'g' + 25: 0, # 'h' + 3: 0, # 'i' + 24: 0, # 'j' + 10: 0, # 'k' + 5: 1, # 'l' + 13: 1, # 'm' + 4: 1, # 'n' + 15: 0, # 'o' + 26: 0, # 'p' + 7: 0, # 'r' + 8: 0, # 's' + 9: 1, # 't' + 14: 2, # 'u' + 32: 0, # 'v' + 57: 0, # 'w' + 58: 0, # 'x' + 11: 0, # 'y' + 22: 1, # 'z' + 63: 0, # '·' + 54: 0, # 'Ç' + 50: 1, # 'Ö' + 55: 0, # 'Ãœ' + 59: 0, # 'â' + 33: 0, # 'ç' + 61: 0, # 'î' + 34: 1, # 'ö' + 17: 0, # 'ü' + 30: 1, # 'ÄŸ' + 41: 1, # 'Ä°' + 6: 0, # 'ı' + 40: 0, # 'Åž' + 19: 1, # 'ÅŸ' + }, + 59: { # 'â' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 0, # 'F' + 36: 1, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 1, # 'K' + 49: 0, # 'L' + 20: 0, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 0, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 0, # 'T' + 51: 0, # 'U' + 38: 0, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 0, # 'Z' + 1: 2, # 'a' + 21: 0, # 'b' + 28: 0, # 'c' + 12: 0, # 'd' + 2: 2, # 'e' + 18: 0, # 'f' + 27: 0, # 'g' + 25: 0, # 'h' + 3: 0, # 'i' + 24: 0, # 'j' + 10: 0, # 'k' + 5: 0, # 'l' + 13: 2, # 'm' + 4: 0, # 'n' + 15: 1, # 'o' + 26: 0, # 'p' + 7: 0, # 'r' + 8: 0, # 's' + 9: 0, # 't' + 14: 2, # 'u' + 32: 0, # 'v' + 57: 0, # 'w' + 58: 0, # 'x' + 11: 0, # 'y' + 22: 1, # 'z' + 63: 0, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ãœ' + 59: 0, # 'â' + 33: 0, # 'ç' + 61: 0, # 'î' + 34: 0, # 'ö' + 17: 0, # 'ü' + 30: 0, # 'ÄŸ' + 41: 0, # 'Ä°' + 6: 1, # 'ı' + 40: 1, # 'Åž' + 19: 0, # 'ÅŸ' + }, + 33: { # 'ç' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 3, # 'E' + 52: 0, # 'F' + 36: 0, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 0, # 'K' + 49: 0, # 'L' + 20: 1, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 0, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 2, # 'T' + 51: 0, # 'U' + 38: 1, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 0, # 'Z' + 1: 0, # 'a' + 21: 3, # 'b' + 28: 0, # 'c' + 12: 2, # 'd' + 2: 0, # 'e' + 18: 2, # 'f' + 27: 1, # 'g' + 25: 3, # 'h' + 3: 3, # 'i' + 24: 0, # 'j' + 10: 3, # 'k' + 5: 0, # 'l' + 13: 0, # 'm' + 4: 3, # 'n' + 15: 0, # 'o' + 26: 1, # 'p' + 7: 3, # 'r' + 8: 2, # 's' + 9: 3, # 't' + 14: 0, # 'u' + 32: 2, # 'v' + 57: 0, # 'w' + 58: 0, # 'x' + 11: 2, # 'y' + 22: 0, # 'z' + 63: 0, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ãœ' + 59: 0, # 'â' + 33: 0, # 'ç' + 61: 0, # 'î' + 34: 0, # 'ö' + 17: 1, # 'ü' + 30: 0, # 'ÄŸ' + 41: 0, # 'Ä°' + 6: 3, # 'ı' + 40: 0, # 'Åž' + 19: 0, # 'ÅŸ' + }, + 61: { # 'î' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 0, # 'F' + 36: 0, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 0, # 'K' + 49: 0, # 'L' + 20: 0, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 0, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 0, # 'T' + 51: 0, # 'U' + 38: 0, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 1, # 'Z' + 1: 2, # 'a' + 21: 0, # 'b' + 28: 0, # 'c' + 12: 0, # 'd' + 2: 2, # 'e' + 18: 0, # 'f' + 27: 0, # 'g' + 25: 0, # 'h' + 3: 0, # 'i' + 24: 1, # 'j' + 10: 0, # 'k' + 5: 0, # 'l' + 13: 1, # 'm' + 4: 1, # 'n' + 15: 0, # 'o' + 26: 0, # 'p' + 7: 0, # 'r' + 8: 0, # 's' + 9: 0, # 't' + 14: 1, # 'u' + 32: 0, # 'v' + 57: 0, # 'w' + 58: 0, # 'x' + 11: 0, # 'y' + 22: 1, # 'z' + 63: 0, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ãœ' + 59: 0, # 'â' + 33: 0, # 'ç' + 61: 1, # 'î' + 34: 0, # 'ö' + 17: 0, # 'ü' + 30: 0, # 'ÄŸ' + 41: 0, # 'Ä°' + 6: 1, # 'ı' + 40: 0, # 'Åž' + 19: 0, # 'ÅŸ' + }, + 34: { # 'ö' + 23: 0, # 'A' + 37: 1, # 'B' + 47: 1, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 2, # 'F' + 36: 1, # 'G' + 45: 1, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 3, # 'K' + 49: 1, # 'L' + 20: 0, # 'M' + 46: 1, # 'N' + 42: 1, # 'O' + 48: 2, # 'P' + 44: 1, # 'R' + 35: 1, # 'S' + 31: 1, # 'T' + 51: 1, # 'U' + 38: 1, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 1, # 'Z' + 1: 3, # 'a' + 21: 1, # 'b' + 28: 2, # 'c' + 12: 1, # 'd' + 2: 3, # 'e' + 18: 0, # 'f' + 27: 2, # 'g' + 25: 2, # 'h' + 3: 1, # 'i' + 24: 2, # 'j' + 10: 1, # 'k' + 5: 2, # 'l' + 13: 3, # 'm' + 4: 2, # 'n' + 15: 2, # 'o' + 26: 0, # 'p' + 7: 0, # 'r' + 8: 3, # 's' + 9: 1, # 't' + 14: 3, # 'u' + 32: 0, # 'v' + 57: 0, # 'w' + 58: 0, # 'x' + 11: 1, # 'y' + 22: 2, # 'z' + 63: 0, # '·' + 54: 1, # 'Ç' + 50: 2, # 'Ö' + 55: 0, # 'Ãœ' + 59: 0, # 'â' + 33: 2, # 'ç' + 61: 0, # 'î' + 34: 2, # 'ö' + 17: 0, # 'ü' + 30: 2, # 'ÄŸ' + 41: 1, # 'Ä°' + 6: 1, # 'ı' + 40: 2, # 'Åž' + 19: 1, # 'ÅŸ' + }, + 17: { # 'ü' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 1, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 0, # 'F' + 36: 0, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 1, # 'J' + 16: 1, # 'K' + 49: 0, # 'L' + 20: 1, # 'M' + 46: 0, # 'N' + 42: 0, # 'O' + 48: 0, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 1, # 'T' + 51: 0, # 'U' + 38: 0, # 'V' + 62: 0, # 'W' + 43: 0, # 'Y' + 56: 1, # 'Z' + 1: 3, # 'a' + 21: 0, # 'b' + 28: 0, # 'c' + 12: 1, # 'd' + 2: 3, # 'e' + 18: 1, # 'f' + 27: 2, # 'g' + 25: 0, # 'h' + 3: 1, # 'i' + 24: 1, # 'j' + 10: 2, # 'k' + 5: 3, # 'l' + 13: 2, # 'm' + 4: 3, # 'n' + 15: 0, # 'o' + 26: 2, # 'p' + 7: 2, # 'r' + 8: 3, # 's' + 9: 2, # 't' + 14: 3, # 'u' + 32: 1, # 'v' + 57: 1, # 'w' + 58: 0, # 'x' + 11: 0, # 'y' + 22: 0, # 'z' + 63: 0, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ãœ' + 59: 0, # 'â' + 33: 1, # 'ç' + 61: 0, # 'î' + 34: 0, # 'ö' + 17: 2, # 'ü' + 30: 0, # 'ÄŸ' + 41: 0, # 'Ä°' + 6: 2, # 'ı' + 40: 0, # 'Åž' + 19: 0, # 'ÅŸ' + }, + 30: { # 'ÄŸ' + 23: 0, # 'A' + 37: 2, # 'B' + 47: 1, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 2, # 'F' + 36: 1, # 'G' + 45: 0, # 'H' + 53: 1, # 'I' + 60: 0, # 'J' + 16: 3, # 'K' + 49: 0, # 'L' + 20: 1, # 'M' + 46: 2, # 'N' + 42: 2, # 'O' + 48: 1, # 'P' + 44: 1, # 'R' + 35: 0, # 'S' + 31: 1, # 'T' + 51: 0, # 'U' + 38: 2, # 'V' + 62: 0, # 'W' + 43: 2, # 'Y' + 56: 0, # 'Z' + 1: 3, # 'a' + 21: 0, # 'b' + 28: 2, # 'c' + 12: 0, # 'd' + 2: 2, # 'e' + 18: 0, # 'f' + 27: 0, # 'g' + 25: 0, # 'h' + 3: 0, # 'i' + 24: 3, # 'j' + 10: 1, # 'k' + 5: 2, # 'l' + 13: 3, # 'm' + 4: 0, # 'n' + 15: 1, # 'o' + 26: 0, # 'p' + 7: 1, # 'r' + 8: 0, # 's' + 9: 0, # 't' + 14: 3, # 'u' + 32: 0, # 'v' + 57: 0, # 'w' + 58: 0, # 'x' + 11: 0, # 'y' + 22: 2, # 'z' + 63: 0, # '·' + 54: 2, # 'Ç' + 50: 2, # 'Ö' + 55: 0, # 'Ãœ' + 59: 0, # 'â' + 33: 1, # 'ç' + 61: 0, # 'î' + 34: 2, # 'ö' + 17: 0, # 'ü' + 30: 1, # 'ÄŸ' + 41: 2, # 'Ä°' + 6: 2, # 'ı' + 40: 2, # 'Åž' + 19: 1, # 'ÅŸ' + }, + 41: { # 'Ä°' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 1, # 'C' + 39: 1, # 'D' + 29: 1, # 'E' + 52: 0, # 'F' + 36: 2, # 'G' + 45: 2, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 0, # 'K' + 49: 0, # 'L' + 20: 2, # 'M' + 46: 1, # 'N' + 42: 1, # 'O' + 48: 2, # 'P' + 44: 0, # 'R' + 35: 1, # 'S' + 31: 1, # 'T' + 51: 1, # 'U' + 38: 1, # 'V' + 62: 0, # 'W' + 43: 2, # 'Y' + 56: 0, # 'Z' + 1: 1, # 'a' + 21: 2, # 'b' + 28: 1, # 'c' + 12: 2, # 'd' + 2: 1, # 'e' + 18: 0, # 'f' + 27: 3, # 'g' + 25: 2, # 'h' + 3: 2, # 'i' + 24: 2, # 'j' + 10: 2, # 'k' + 5: 0, # 'l' + 13: 1, # 'm' + 4: 3, # 'n' + 15: 1, # 'o' + 26: 1, # 'p' + 7: 3, # 'r' + 8: 3, # 's' + 9: 2, # 't' + 14: 0, # 'u' + 32: 0, # 'v' + 57: 1, # 'w' + 58: 0, # 'x' + 11: 2, # 'y' + 22: 0, # 'z' + 63: 0, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 1, # 'Ãœ' + 59: 1, # 'â' + 33: 0, # 'ç' + 61: 0, # 'î' + 34: 1, # 'ö' + 17: 1, # 'ü' + 30: 2, # 'ÄŸ' + 41: 0, # 'Ä°' + 6: 3, # 'ı' + 40: 0, # 'Åž' + 19: 1, # 'ÅŸ' + }, + 6: { # 'ı' + 23: 2, # 'A' + 37: 0, # 'B' + 47: 0, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 0, # 'F' + 36: 1, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 2, # 'J' + 16: 3, # 'K' + 49: 0, # 'L' + 20: 3, # 'M' + 46: 1, # 'N' + 42: 0, # 'O' + 48: 0, # 'P' + 44: 0, # 'R' + 35: 0, # 'S' + 31: 2, # 'T' + 51: 0, # 'U' + 38: 0, # 'V' + 62: 0, # 'W' + 43: 2, # 'Y' + 56: 1, # 'Z' + 1: 3, # 'a' + 21: 2, # 'b' + 28: 1, # 'c' + 12: 3, # 'd' + 2: 3, # 'e' + 18: 3, # 'f' + 27: 3, # 'g' + 25: 2, # 'h' + 3: 3, # 'i' + 24: 3, # 'j' + 10: 3, # 'k' + 5: 3, # 'l' + 13: 3, # 'm' + 4: 3, # 'n' + 15: 0, # 'o' + 26: 3, # 'p' + 7: 3, # 'r' + 8: 3, # 's' + 9: 3, # 't' + 14: 3, # 'u' + 32: 3, # 'v' + 57: 1, # 'w' + 58: 1, # 'x' + 11: 3, # 'y' + 22: 0, # 'z' + 63: 1, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 0, # 'Ãœ' + 59: 0, # 'â' + 33: 2, # 'ç' + 61: 0, # 'î' + 34: 0, # 'ö' + 17: 3, # 'ü' + 30: 0, # 'ÄŸ' + 41: 0, # 'Ä°' + 6: 3, # 'ı' + 40: 0, # 'Åž' + 19: 0, # 'ÅŸ' + }, + 40: { # 'Åž' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 1, # 'C' + 39: 1, # 'D' + 29: 1, # 'E' + 52: 0, # 'F' + 36: 1, # 'G' + 45: 2, # 'H' + 53: 1, # 'I' + 60: 0, # 'J' + 16: 0, # 'K' + 49: 0, # 'L' + 20: 2, # 'M' + 46: 1, # 'N' + 42: 1, # 'O' + 48: 2, # 'P' + 44: 2, # 'R' + 35: 1, # 'S' + 31: 1, # 'T' + 51: 0, # 'U' + 38: 1, # 'V' + 62: 0, # 'W' + 43: 2, # 'Y' + 56: 1, # 'Z' + 1: 0, # 'a' + 21: 2, # 'b' + 28: 0, # 'c' + 12: 2, # 'd' + 2: 0, # 'e' + 18: 3, # 'f' + 27: 0, # 'g' + 25: 2, # 'h' + 3: 3, # 'i' + 24: 2, # 'j' + 10: 1, # 'k' + 5: 0, # 'l' + 13: 1, # 'm' + 4: 3, # 'n' + 15: 2, # 'o' + 26: 0, # 'p' + 7: 3, # 'r' + 8: 2, # 's' + 9: 2, # 't' + 14: 1, # 'u' + 32: 3, # 'v' + 57: 0, # 'w' + 58: 0, # 'x' + 11: 2, # 'y' + 22: 0, # 'z' + 63: 0, # '·' + 54: 0, # 'Ç' + 50: 0, # 'Ö' + 55: 1, # 'Ãœ' + 59: 0, # 'â' + 33: 0, # 'ç' + 61: 0, # 'î' + 34: 2, # 'ö' + 17: 1, # 'ü' + 30: 2, # 'ÄŸ' + 41: 0, # 'Ä°' + 6: 2, # 'ı' + 40: 1, # 'Åž' + 19: 2, # 'ÅŸ' + }, + 19: { # 'ÅŸ' + 23: 0, # 'A' + 37: 0, # 'B' + 47: 1, # 'C' + 39: 0, # 'D' + 29: 0, # 'E' + 52: 2, # 'F' + 36: 1, # 'G' + 45: 0, # 'H' + 53: 0, # 'I' + 60: 0, # 'J' + 16: 3, # 'K' + 49: 2, # 'L' + 20: 0, # 'M' + 46: 1, # 'N' + 42: 1, # 'O' + 48: 1, # 'P' + 44: 1, # 'R' + 35: 1, # 'S' + 31: 0, # 'T' + 51: 1, # 'U' + 38: 1, # 'V' + 62: 0, # 'W' + 43: 1, # 'Y' + 56: 0, # 'Z' + 1: 3, # 'a' + 21: 1, # 'b' + 28: 2, # 'c' + 12: 0, # 'd' + 2: 3, # 'e' + 18: 0, # 'f' + 27: 2, # 'g' + 25: 1, # 'h' + 3: 1, # 'i' + 24: 0, # 'j' + 10: 2, # 'k' + 5: 2, # 'l' + 13: 3, # 'm' + 4: 0, # 'n' + 15: 0, # 'o' + 26: 1, # 'p' + 7: 3, # 'r' + 8: 0, # 's' + 9: 0, # 't' + 14: 3, # 'u' + 32: 0, # 'v' + 57: 0, # 'w' + 58: 0, # 'x' + 11: 0, # 'y' + 22: 2, # 'z' + 63: 0, # '·' + 54: 1, # 'Ç' + 50: 2, # 'Ö' + 55: 0, # 'Ãœ' + 59: 0, # 'â' + 33: 1, # 'ç' + 61: 1, # 'î' + 34: 2, # 'ö' + 17: 0, # 'ü' + 30: 1, # 'ÄŸ' + 41: 1, # 'Ä°' + 6: 1, # 'ı' + 40: 1, # 'Åž' + 19: 1, # 'ÅŸ' + }, +} + +# 255: Undefined characters that did not exist in training text +# 254: Carriage/Return +# 253: symbol (punctuation) that does not belong to word +# 252: 0 - 9 +# 251: Control characters + +# Character Mapping Table(s): +ISO_8859_9_TURKISH_CHAR_TO_ORDER = { + 0: 255, # '\x00' + 1: 255, # '\x01' + 2: 255, # '\x02' + 3: 255, # '\x03' + 4: 255, # '\x04' + 5: 255, # '\x05' + 6: 255, # '\x06' + 7: 255, # '\x07' + 8: 255, # '\x08' + 9: 255, # '\t' + 10: 255, # '\n' + 11: 255, # '\x0b' + 12: 255, # '\x0c' + 13: 255, # '\r' + 14: 255, # '\x0e' + 15: 255, # '\x0f' + 16: 255, # '\x10' + 17: 255, # '\x11' + 18: 255, # '\x12' + 19: 255, # '\x13' + 20: 255, # '\x14' + 21: 255, # '\x15' + 22: 255, # '\x16' + 23: 255, # '\x17' + 24: 255, # '\x18' + 25: 255, # '\x19' + 26: 255, # '\x1a' + 27: 255, # '\x1b' + 28: 255, # '\x1c' + 29: 255, # '\x1d' + 30: 255, # '\x1e' + 31: 255, # '\x1f' + 32: 255, # ' ' + 33: 255, # '!' + 34: 255, # '"' + 35: 255, # '#' + 36: 255, # '$' + 37: 255, # '%' + 38: 255, # '&' + 39: 255, # "'" + 40: 255, # '(' + 41: 255, # ')' + 42: 255, # '*' + 43: 255, # '+' + 44: 255, # ',' + 45: 255, # '-' + 46: 255, # '.' + 47: 255, # '/' + 48: 255, # '0' + 49: 255, # '1' + 50: 255, # '2' + 51: 255, # '3' + 52: 255, # '4' + 53: 255, # '5' + 54: 255, # '6' + 55: 255, # '7' + 56: 255, # '8' + 57: 255, # '9' + 58: 255, # ':' + 59: 255, # ';' + 60: 255, # '<' + 61: 255, # '=' + 62: 255, # '>' + 63: 255, # '?' + 64: 255, # '@' + 65: 23, # 'A' + 66: 37, # 'B' + 67: 47, # 'C' + 68: 39, # 'D' + 69: 29, # 'E' + 70: 52, # 'F' + 71: 36, # 'G' + 72: 45, # 'H' + 73: 53, # 'I' + 74: 60, # 'J' + 75: 16, # 'K' + 76: 49, # 'L' + 77: 20, # 'M' + 78: 46, # 'N' + 79: 42, # 'O' + 80: 48, # 'P' + 81: 69, # 'Q' + 82: 44, # 'R' + 83: 35, # 'S' + 84: 31, # 'T' + 85: 51, # 'U' + 86: 38, # 'V' + 87: 62, # 'W' + 88: 65, # 'X' + 89: 43, # 'Y' + 90: 56, # 'Z' + 91: 255, # '[' + 92: 255, # '\\' + 93: 255, # ']' + 94: 255, # '^' + 95: 255, # '_' + 96: 255, # '`' + 97: 1, # 'a' + 98: 21, # 'b' + 99: 28, # 'c' + 100: 12, # 'd' + 101: 2, # 'e' + 102: 18, # 'f' + 103: 27, # 'g' + 104: 25, # 'h' + 105: 3, # 'i' + 106: 24, # 'j' + 107: 10, # 'k' + 108: 5, # 'l' + 109: 13, # 'm' + 110: 4, # 'n' + 111: 15, # 'o' + 112: 26, # 'p' + 113: 64, # 'q' + 114: 7, # 'r' + 115: 8, # 's' + 116: 9, # 't' + 117: 14, # 'u' + 118: 32, # 'v' + 119: 57, # 'w' + 120: 58, # 'x' + 121: 11, # 'y' + 122: 22, # 'z' + 123: 255, # '{' + 124: 255, # '|' + 125: 255, # '}' + 126: 255, # '~' + 127: 255, # '\x7f' + 128: 180, # '\x80' + 129: 179, # '\x81' + 130: 178, # '\x82' + 131: 177, # '\x83' + 132: 176, # '\x84' + 133: 175, # '\x85' + 134: 174, # '\x86' + 135: 173, # '\x87' + 136: 172, # '\x88' + 137: 171, # '\x89' + 138: 170, # '\x8a' + 139: 169, # '\x8b' + 140: 168, # '\x8c' + 141: 167, # '\x8d' + 142: 166, # '\x8e' + 143: 165, # '\x8f' + 144: 164, # '\x90' + 145: 163, # '\x91' + 146: 162, # '\x92' + 147: 161, # '\x93' + 148: 160, # '\x94' + 149: 159, # '\x95' + 150: 101, # '\x96' + 151: 158, # '\x97' + 152: 157, # '\x98' + 153: 156, # '\x99' + 154: 155, # '\x9a' + 155: 154, # '\x9b' + 156: 153, # '\x9c' + 157: 152, # '\x9d' + 158: 151, # '\x9e' + 159: 106, # '\x9f' + 160: 150, # '\xa0' + 161: 149, # '¡' + 162: 148, # '¢' + 163: 147, # '£' + 164: 146, # '¤' + 165: 145, # 'Â¥' + 166: 144, # '¦' + 167: 100, # '§' + 168: 143, # '¨' + 169: 142, # '©' + 170: 141, # 'ª' + 171: 140, # '«' + 172: 139, # '¬' + 173: 138, # '\xad' + 174: 137, # '®' + 175: 136, # '¯' + 176: 94, # '°' + 177: 80, # '±' + 178: 93, # '²' + 179: 135, # '³' + 180: 105, # '´' + 181: 134, # 'µ' + 182: 133, # '¶' + 183: 63, # '·' + 184: 132, # '¸' + 185: 131, # '¹' + 186: 130, # 'º' + 187: 129, # '»' + 188: 128, # '¼' + 189: 127, # '½' + 190: 126, # '¾' + 191: 125, # '¿' + 192: 124, # 'À' + 193: 104, # 'Ã' + 194: 73, # 'Â' + 195: 99, # 'Ã' + 196: 79, # 'Ä' + 197: 85, # 'Ã…' + 198: 123, # 'Æ' + 199: 54, # 'Ç' + 200: 122, # 'È' + 201: 98, # 'É' + 202: 92, # 'Ê' + 203: 121, # 'Ë' + 204: 120, # 'ÃŒ' + 205: 91, # 'Ã' + 206: 103, # 'ÃŽ' + 207: 119, # 'Ã' + 208: 68, # 'Äž' + 209: 118, # 'Ñ' + 210: 117, # 'Ã’' + 211: 97, # 'Ó' + 212: 116, # 'Ô' + 213: 115, # 'Õ' + 214: 50, # 'Ö' + 215: 90, # '×' + 216: 114, # 'Ø' + 217: 113, # 'Ù' + 218: 112, # 'Ú' + 219: 111, # 'Û' + 220: 55, # 'Ãœ' + 221: 41, # 'Ä°' + 222: 40, # 'Åž' + 223: 86, # 'ß' + 224: 89, # 'à' + 225: 70, # 'á' + 226: 59, # 'â' + 227: 78, # 'ã' + 228: 71, # 'ä' + 229: 82, # 'Ã¥' + 230: 88, # 'æ' + 231: 33, # 'ç' + 232: 77, # 'è' + 233: 66, # 'é' + 234: 84, # 'ê' + 235: 83, # 'ë' + 236: 110, # 'ì' + 237: 75, # 'í' + 238: 61, # 'î' + 239: 96, # 'ï' + 240: 30, # 'ÄŸ' + 241: 67, # 'ñ' + 242: 109, # 'ò' + 243: 74, # 'ó' + 244: 87, # 'ô' + 245: 102, # 'õ' + 246: 34, # 'ö' + 247: 95, # '÷' + 248: 81, # 'ø' + 249: 108, # 'ù' + 250: 76, # 'ú' + 251: 72, # 'û' + 252: 17, # 'ü' + 253: 6, # 'ı' + 254: 19, # 'ÅŸ' + 255: 107, # 'ÿ' +} + +ISO_8859_9_TURKISH_MODEL = SingleByteCharSetModel(charset_name='ISO-8859-9', + language='Turkish', + char_to_order_map=ISO_8859_9_TURKISH_CHAR_TO_ORDER, + language_model=TURKISH_LANG_MODEL, + typical_positive_ratio=0.97029, + keep_ascii_letters=True, + alphabet='ABCDEFGHIJKLMNOPRSTUVYZabcdefghijklmnoprstuvyzÂÇÎÖÛÜâçîöûüĞğİıŞş') + diff --git a/venv/Lib/site-packages/pip/_vendor/chardet/latin1prober.py b/venv/Lib/site-packages/pip/_vendor/chardet/latin1prober.py new file mode 100644 index 0000000..7d1e8c2 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/chardet/latin1prober.py @@ -0,0 +1,145 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Universal charset detector code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 2001 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# Shy Shalom - original C code +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .charsetprober import CharSetProber +from .enums import ProbingState + +FREQ_CAT_NUM = 4 + +UDF = 0 # undefined +OTH = 1 # other +ASC = 2 # ascii capital letter +ASS = 3 # ascii small letter +ACV = 4 # accent capital vowel +ACO = 5 # accent capital other +ASV = 6 # accent small vowel +ASO = 7 # accent small other +CLASS_NUM = 8 # total classes + +Latin1_CharToClass = ( + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # 00 - 07 + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # 08 - 0F + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # 10 - 17 + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # 18 - 1F + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # 20 - 27 + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # 28 - 2F + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # 30 - 37 + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # 38 - 3F + OTH, ASC, ASC, ASC, ASC, ASC, ASC, ASC, # 40 - 47 + ASC, ASC, ASC, ASC, ASC, ASC, ASC, ASC, # 48 - 4F + ASC, ASC, ASC, ASC, ASC, ASC, ASC, ASC, # 50 - 57 + ASC, ASC, ASC, OTH, OTH, OTH, OTH, OTH, # 58 - 5F + OTH, ASS, ASS, ASS, ASS, ASS, ASS, ASS, # 60 - 67 + ASS, ASS, ASS, ASS, ASS, ASS, ASS, ASS, # 68 - 6F + ASS, ASS, ASS, ASS, ASS, ASS, ASS, ASS, # 70 - 77 + ASS, ASS, ASS, OTH, OTH, OTH, OTH, OTH, # 78 - 7F + OTH, UDF, OTH, ASO, OTH, OTH, OTH, OTH, # 80 - 87 + OTH, OTH, ACO, OTH, ACO, UDF, ACO, UDF, # 88 - 8F + UDF, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # 90 - 97 + OTH, OTH, ASO, OTH, ASO, UDF, ASO, ACO, # 98 - 9F + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # A0 - A7 + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # A8 - AF + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # B0 - B7 + OTH, OTH, OTH, OTH, OTH, OTH, OTH, OTH, # B8 - BF + ACV, ACV, ACV, ACV, ACV, ACV, ACO, ACO, # C0 - C7 + ACV, ACV, ACV, ACV, ACV, ACV, ACV, ACV, # C8 - CF + ACO, ACO, ACV, ACV, ACV, ACV, ACV, OTH, # D0 - D7 + ACV, ACV, ACV, ACV, ACV, ACO, ACO, ACO, # D8 - DF + ASV, ASV, ASV, ASV, ASV, ASV, ASO, ASO, # E0 - E7 + ASV, ASV, ASV, ASV, ASV, ASV, ASV, ASV, # E8 - EF + ASO, ASO, ASV, ASV, ASV, ASV, ASV, OTH, # F0 - F7 + ASV, ASV, ASV, ASV, ASV, ASO, ASO, ASO, # F8 - FF +) + +# 0 : illegal +# 1 : very unlikely +# 2 : normal +# 3 : very likely +Latin1ClassModel = ( +# UDF OTH ASC ASS ACV ACO ASV ASO + 0, 0, 0, 0, 0, 0, 0, 0, # UDF + 0, 3, 3, 3, 3, 3, 3, 3, # OTH + 0, 3, 3, 3, 3, 3, 3, 3, # ASC + 0, 3, 3, 3, 1, 1, 3, 3, # ASS + 0, 3, 3, 3, 1, 2, 1, 2, # ACV + 0, 3, 3, 3, 3, 3, 3, 3, # ACO + 0, 3, 1, 3, 1, 1, 1, 3, # ASV + 0, 3, 1, 3, 1, 1, 3, 3, # ASO +) + + +class Latin1Prober(CharSetProber): + def __init__(self): + super(Latin1Prober, self).__init__() + self._last_char_class = None + self._freq_counter = None + self.reset() + + def reset(self): + self._last_char_class = OTH + self._freq_counter = [0] * FREQ_CAT_NUM + CharSetProber.reset(self) + + @property + def charset_name(self): + return "ISO-8859-1" + + @property + def language(self): + return "" + + def feed(self, byte_str): + byte_str = self.filter_with_english_letters(byte_str) + for c in byte_str: + char_class = Latin1_CharToClass[c] + freq = Latin1ClassModel[(self._last_char_class * CLASS_NUM) + + char_class] + if freq == 0: + self._state = ProbingState.NOT_ME + break + self._freq_counter[freq] += 1 + self._last_char_class = char_class + + return self.state + + def get_confidence(self): + if self.state == ProbingState.NOT_ME: + return 0.01 + + total = sum(self._freq_counter) + if total < 0.01: + confidence = 0.0 + else: + confidence = ((self._freq_counter[3] - self._freq_counter[1] * 20.0) + / total) + if confidence < 0.0: + confidence = 0.0 + # lower the confidence of latin1 so that other more accurate + # detector can take priority. + confidence = confidence * 0.73 + return confidence diff --git a/venv/Lib/site-packages/pip/_vendor/chardet/mbcharsetprober.py b/venv/Lib/site-packages/pip/_vendor/chardet/mbcharsetprober.py new file mode 100644 index 0000000..6256ecf --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/chardet/mbcharsetprober.py @@ -0,0 +1,91 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Universal charset detector code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 2001 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# Shy Shalom - original C code +# Proofpoint, Inc. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .charsetprober import CharSetProber +from .enums import ProbingState, MachineState + + +class MultiByteCharSetProber(CharSetProber): + """ + MultiByteCharSetProber + """ + + def __init__(self, lang_filter=None): + super(MultiByteCharSetProber, self).__init__(lang_filter=lang_filter) + self.distribution_analyzer = None + self.coding_sm = None + self._last_char = [0, 0] + + def reset(self): + super(MultiByteCharSetProber, self).reset() + if self.coding_sm: + self.coding_sm.reset() + if self.distribution_analyzer: + self.distribution_analyzer.reset() + self._last_char = [0, 0] + + @property + def charset_name(self): + raise NotImplementedError + + @property + def language(self): + raise NotImplementedError + + def feed(self, byte_str): + for i in range(len(byte_str)): + coding_state = self.coding_sm.next_state(byte_str[i]) + if coding_state == MachineState.ERROR: + self.logger.debug('%s %s prober hit error at byte %s', + self.charset_name, self.language, i) + self._state = ProbingState.NOT_ME + break + elif coding_state == MachineState.ITS_ME: + self._state = ProbingState.FOUND_IT + break + elif coding_state == MachineState.START: + char_len = self.coding_sm.get_current_charlen() + if i == 0: + self._last_char[1] = byte_str[0] + self.distribution_analyzer.feed(self._last_char, char_len) + else: + self.distribution_analyzer.feed(byte_str[i - 1:i + 1], + char_len) + + self._last_char[0] = byte_str[-1] + + if self.state == ProbingState.DETECTING: + if (self.distribution_analyzer.got_enough_data() and + (self.get_confidence() > self.SHORTCUT_THRESHOLD)): + self._state = ProbingState.FOUND_IT + + return self.state + + def get_confidence(self): + return self.distribution_analyzer.get_confidence() diff --git a/venv/Lib/site-packages/pip/_vendor/chardet/mbcsgroupprober.py b/venv/Lib/site-packages/pip/_vendor/chardet/mbcsgroupprober.py new file mode 100644 index 0000000..530abe7 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/chardet/mbcsgroupprober.py @@ -0,0 +1,54 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Universal charset detector code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 2001 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# Shy Shalom - original C code +# Proofpoint, Inc. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .charsetgroupprober import CharSetGroupProber +from .utf8prober import UTF8Prober +from .sjisprober import SJISProber +from .eucjpprober import EUCJPProber +from .gb2312prober import GB2312Prober +from .euckrprober import EUCKRProber +from .cp949prober import CP949Prober +from .big5prober import Big5Prober +from .euctwprober import EUCTWProber + + +class MBCSGroupProber(CharSetGroupProber): + def __init__(self, lang_filter=None): + super(MBCSGroupProber, self).__init__(lang_filter=lang_filter) + self.probers = [ + UTF8Prober(), + SJISProber(), + EUCJPProber(), + GB2312Prober(), + EUCKRProber(), + CP949Prober(), + Big5Prober(), + EUCTWProber() + ] + self.reset() diff --git a/venv/Lib/site-packages/pip/_vendor/chardet/mbcssm.py b/venv/Lib/site-packages/pip/_vendor/chardet/mbcssm.py new file mode 100644 index 0000000..8360d0f --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/chardet/mbcssm.py @@ -0,0 +1,572 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .enums import MachineState + +# BIG5 + +BIG5_CLS = ( + 1,1,1,1,1,1,1,1, # 00 - 07 #allow 0x00 as legal value + 1,1,1,1,1,1,0,0, # 08 - 0f + 1,1,1,1,1,1,1,1, # 10 - 17 + 1,1,1,0,1,1,1,1, # 18 - 1f + 1,1,1,1,1,1,1,1, # 20 - 27 + 1,1,1,1,1,1,1,1, # 28 - 2f + 1,1,1,1,1,1,1,1, # 30 - 37 + 1,1,1,1,1,1,1,1, # 38 - 3f + 2,2,2,2,2,2,2,2, # 40 - 47 + 2,2,2,2,2,2,2,2, # 48 - 4f + 2,2,2,2,2,2,2,2, # 50 - 57 + 2,2,2,2,2,2,2,2, # 58 - 5f + 2,2,2,2,2,2,2,2, # 60 - 67 + 2,2,2,2,2,2,2,2, # 68 - 6f + 2,2,2,2,2,2,2,2, # 70 - 77 + 2,2,2,2,2,2,2,1, # 78 - 7f + 4,4,4,4,4,4,4,4, # 80 - 87 + 4,4,4,4,4,4,4,4, # 88 - 8f + 4,4,4,4,4,4,4,4, # 90 - 97 + 4,4,4,4,4,4,4,4, # 98 - 9f + 4,3,3,3,3,3,3,3, # a0 - a7 + 3,3,3,3,3,3,3,3, # a8 - af + 3,3,3,3,3,3,3,3, # b0 - b7 + 3,3,3,3,3,3,3,3, # b8 - bf + 3,3,3,3,3,3,3,3, # c0 - c7 + 3,3,3,3,3,3,3,3, # c8 - cf + 3,3,3,3,3,3,3,3, # d0 - d7 + 3,3,3,3,3,3,3,3, # d8 - df + 3,3,3,3,3,3,3,3, # e0 - e7 + 3,3,3,3,3,3,3,3, # e8 - ef + 3,3,3,3,3,3,3,3, # f0 - f7 + 3,3,3,3,3,3,3,0 # f8 - ff +) + +BIG5_ST = ( + MachineState.ERROR,MachineState.START,MachineState.START, 3,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#00-07 + MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ERROR,#08-0f + MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START#10-17 +) + +BIG5_CHAR_LEN_TABLE = (0, 1, 1, 2, 0) + +BIG5_SM_MODEL = {'class_table': BIG5_CLS, + 'class_factor': 5, + 'state_table': BIG5_ST, + 'char_len_table': BIG5_CHAR_LEN_TABLE, + 'name': 'Big5'} + +# CP949 + +CP949_CLS = ( + 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,0,0, # 00 - 0f + 1,1,1,1,1,1,1,1, 1,1,1,0,1,1,1,1, # 10 - 1f + 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, # 20 - 2f + 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, # 30 - 3f + 1,4,4,4,4,4,4,4, 4,4,4,4,4,4,4,4, # 40 - 4f + 4,4,5,5,5,5,5,5, 5,5,5,1,1,1,1,1, # 50 - 5f + 1,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5, # 60 - 6f + 5,5,5,5,5,5,5,5, 5,5,5,1,1,1,1,1, # 70 - 7f + 0,6,6,6,6,6,6,6, 6,6,6,6,6,6,6,6, # 80 - 8f + 6,6,6,6,6,6,6,6, 6,6,6,6,6,6,6,6, # 90 - 9f + 6,7,7,7,7,7,7,7, 7,7,7,7,7,8,8,8, # a0 - af + 7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7, # b0 - bf + 7,7,7,7,7,7,9,2, 2,3,2,2,2,2,2,2, # c0 - cf + 2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2, # d0 - df + 2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2, # e0 - ef + 2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,0, # f0 - ff +) + +CP949_ST = ( +#cls= 0 1 2 3 4 5 6 7 8 9 # previous state = + MachineState.ERROR,MachineState.START, 3,MachineState.ERROR,MachineState.START,MachineState.START, 4, 5,MachineState.ERROR, 6, # MachineState.START + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR, # MachineState.ERROR + MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME, # MachineState.ITS_ME + MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START, # 3 + MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START, # 4 + MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START, # 5 + MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START, # 6 +) + +CP949_CHAR_LEN_TABLE = (0, 1, 2, 0, 1, 1, 2, 2, 0, 2) + +CP949_SM_MODEL = {'class_table': CP949_CLS, + 'class_factor': 10, + 'state_table': CP949_ST, + 'char_len_table': CP949_CHAR_LEN_TABLE, + 'name': 'CP949'} + +# EUC-JP + +EUCJP_CLS = ( + 4,4,4,4,4,4,4,4, # 00 - 07 + 4,4,4,4,4,4,5,5, # 08 - 0f + 4,4,4,4,4,4,4,4, # 10 - 17 + 4,4,4,5,4,4,4,4, # 18 - 1f + 4,4,4,4,4,4,4,4, # 20 - 27 + 4,4,4,4,4,4,4,4, # 28 - 2f + 4,4,4,4,4,4,4,4, # 30 - 37 + 4,4,4,4,4,4,4,4, # 38 - 3f + 4,4,4,4,4,4,4,4, # 40 - 47 + 4,4,4,4,4,4,4,4, # 48 - 4f + 4,4,4,4,4,4,4,4, # 50 - 57 + 4,4,4,4,4,4,4,4, # 58 - 5f + 4,4,4,4,4,4,4,4, # 60 - 67 + 4,4,4,4,4,4,4,4, # 68 - 6f + 4,4,4,4,4,4,4,4, # 70 - 77 + 4,4,4,4,4,4,4,4, # 78 - 7f + 5,5,5,5,5,5,5,5, # 80 - 87 + 5,5,5,5,5,5,1,3, # 88 - 8f + 5,5,5,5,5,5,5,5, # 90 - 97 + 5,5,5,5,5,5,5,5, # 98 - 9f + 5,2,2,2,2,2,2,2, # a0 - a7 + 2,2,2,2,2,2,2,2, # a8 - af + 2,2,2,2,2,2,2,2, # b0 - b7 + 2,2,2,2,2,2,2,2, # b8 - bf + 2,2,2,2,2,2,2,2, # c0 - c7 + 2,2,2,2,2,2,2,2, # c8 - cf + 2,2,2,2,2,2,2,2, # d0 - d7 + 2,2,2,2,2,2,2,2, # d8 - df + 0,0,0,0,0,0,0,0, # e0 - e7 + 0,0,0,0,0,0,0,0, # e8 - ef + 0,0,0,0,0,0,0,0, # f0 - f7 + 0,0,0,0,0,0,0,5 # f8 - ff +) + +EUCJP_ST = ( + 3, 4, 3, 5,MachineState.START,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#00-07 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,#08-0f + MachineState.ITS_ME,MachineState.ITS_ME,MachineState.START,MachineState.ERROR,MachineState.START,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#10-17 + MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR, 3,MachineState.ERROR,#18-1f + 3,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.START#20-27 +) + +EUCJP_CHAR_LEN_TABLE = (2, 2, 2, 3, 1, 0) + +EUCJP_SM_MODEL = {'class_table': EUCJP_CLS, + 'class_factor': 6, + 'state_table': EUCJP_ST, + 'char_len_table': EUCJP_CHAR_LEN_TABLE, + 'name': 'EUC-JP'} + +# EUC-KR + +EUCKR_CLS = ( + 1,1,1,1,1,1,1,1, # 00 - 07 + 1,1,1,1,1,1,0,0, # 08 - 0f + 1,1,1,1,1,1,1,1, # 10 - 17 + 1,1,1,0,1,1,1,1, # 18 - 1f + 1,1,1,1,1,1,1,1, # 20 - 27 + 1,1,1,1,1,1,1,1, # 28 - 2f + 1,1,1,1,1,1,1,1, # 30 - 37 + 1,1,1,1,1,1,1,1, # 38 - 3f + 1,1,1,1,1,1,1,1, # 40 - 47 + 1,1,1,1,1,1,1,1, # 48 - 4f + 1,1,1,1,1,1,1,1, # 50 - 57 + 1,1,1,1,1,1,1,1, # 58 - 5f + 1,1,1,1,1,1,1,1, # 60 - 67 + 1,1,1,1,1,1,1,1, # 68 - 6f + 1,1,1,1,1,1,1,1, # 70 - 77 + 1,1,1,1,1,1,1,1, # 78 - 7f + 0,0,0,0,0,0,0,0, # 80 - 87 + 0,0,0,0,0,0,0,0, # 88 - 8f + 0,0,0,0,0,0,0,0, # 90 - 97 + 0,0,0,0,0,0,0,0, # 98 - 9f + 0,2,2,2,2,2,2,2, # a0 - a7 + 2,2,2,2,2,3,3,3, # a8 - af + 2,2,2,2,2,2,2,2, # b0 - b7 + 2,2,2,2,2,2,2,2, # b8 - bf + 2,2,2,2,2,2,2,2, # c0 - c7 + 2,3,2,2,2,2,2,2, # c8 - cf + 2,2,2,2,2,2,2,2, # d0 - d7 + 2,2,2,2,2,2,2,2, # d8 - df + 2,2,2,2,2,2,2,2, # e0 - e7 + 2,2,2,2,2,2,2,2, # e8 - ef + 2,2,2,2,2,2,2,2, # f0 - f7 + 2,2,2,2,2,2,2,0 # f8 - ff +) + +EUCKR_ST = ( + MachineState.ERROR,MachineState.START, 3,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#00-07 + MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.START #08-0f +) + +EUCKR_CHAR_LEN_TABLE = (0, 1, 2, 0) + +EUCKR_SM_MODEL = {'class_table': EUCKR_CLS, + 'class_factor': 4, + 'state_table': EUCKR_ST, + 'char_len_table': EUCKR_CHAR_LEN_TABLE, + 'name': 'EUC-KR'} + +# EUC-TW + +EUCTW_CLS = ( + 2,2,2,2,2,2,2,2, # 00 - 07 + 2,2,2,2,2,2,0,0, # 08 - 0f + 2,2,2,2,2,2,2,2, # 10 - 17 + 2,2,2,0,2,2,2,2, # 18 - 1f + 2,2,2,2,2,2,2,2, # 20 - 27 + 2,2,2,2,2,2,2,2, # 28 - 2f + 2,2,2,2,2,2,2,2, # 30 - 37 + 2,2,2,2,2,2,2,2, # 38 - 3f + 2,2,2,2,2,2,2,2, # 40 - 47 + 2,2,2,2,2,2,2,2, # 48 - 4f + 2,2,2,2,2,2,2,2, # 50 - 57 + 2,2,2,2,2,2,2,2, # 58 - 5f + 2,2,2,2,2,2,2,2, # 60 - 67 + 2,2,2,2,2,2,2,2, # 68 - 6f + 2,2,2,2,2,2,2,2, # 70 - 77 + 2,2,2,2,2,2,2,2, # 78 - 7f + 0,0,0,0,0,0,0,0, # 80 - 87 + 0,0,0,0,0,0,6,0, # 88 - 8f + 0,0,0,0,0,0,0,0, # 90 - 97 + 0,0,0,0,0,0,0,0, # 98 - 9f + 0,3,4,4,4,4,4,4, # a0 - a7 + 5,5,1,1,1,1,1,1, # a8 - af + 1,1,1,1,1,1,1,1, # b0 - b7 + 1,1,1,1,1,1,1,1, # b8 - bf + 1,1,3,1,3,3,3,3, # c0 - c7 + 3,3,3,3,3,3,3,3, # c8 - cf + 3,3,3,3,3,3,3,3, # d0 - d7 + 3,3,3,3,3,3,3,3, # d8 - df + 3,3,3,3,3,3,3,3, # e0 - e7 + 3,3,3,3,3,3,3,3, # e8 - ef + 3,3,3,3,3,3,3,3, # f0 - f7 + 3,3,3,3,3,3,3,0 # f8 - ff +) + +EUCTW_ST = ( + MachineState.ERROR,MachineState.ERROR,MachineState.START, 3, 3, 3, 4,MachineState.ERROR,#00-07 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ITS_ME,#08-0f + MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ERROR,MachineState.START,MachineState.ERROR,#10-17 + MachineState.START,MachineState.START,MachineState.START,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#18-1f + 5,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.ERROR,MachineState.START,MachineState.START,#20-27 + MachineState.START,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START #28-2f +) + +EUCTW_CHAR_LEN_TABLE = (0, 0, 1, 2, 2, 2, 3) + +EUCTW_SM_MODEL = {'class_table': EUCTW_CLS, + 'class_factor': 7, + 'state_table': EUCTW_ST, + 'char_len_table': EUCTW_CHAR_LEN_TABLE, + 'name': 'x-euc-tw'} + +# GB2312 + +GB2312_CLS = ( + 1,1,1,1,1,1,1,1, # 00 - 07 + 1,1,1,1,1,1,0,0, # 08 - 0f + 1,1,1,1,1,1,1,1, # 10 - 17 + 1,1,1,0,1,1,1,1, # 18 - 1f + 1,1,1,1,1,1,1,1, # 20 - 27 + 1,1,1,1,1,1,1,1, # 28 - 2f + 3,3,3,3,3,3,3,3, # 30 - 37 + 3,3,1,1,1,1,1,1, # 38 - 3f + 2,2,2,2,2,2,2,2, # 40 - 47 + 2,2,2,2,2,2,2,2, # 48 - 4f + 2,2,2,2,2,2,2,2, # 50 - 57 + 2,2,2,2,2,2,2,2, # 58 - 5f + 2,2,2,2,2,2,2,2, # 60 - 67 + 2,2,2,2,2,2,2,2, # 68 - 6f + 2,2,2,2,2,2,2,2, # 70 - 77 + 2,2,2,2,2,2,2,4, # 78 - 7f + 5,6,6,6,6,6,6,6, # 80 - 87 + 6,6,6,6,6,6,6,6, # 88 - 8f + 6,6,6,6,6,6,6,6, # 90 - 97 + 6,6,6,6,6,6,6,6, # 98 - 9f + 6,6,6,6,6,6,6,6, # a0 - a7 + 6,6,6,6,6,6,6,6, # a8 - af + 6,6,6,6,6,6,6,6, # b0 - b7 + 6,6,6,6,6,6,6,6, # b8 - bf + 6,6,6,6,6,6,6,6, # c0 - c7 + 6,6,6,6,6,6,6,6, # c8 - cf + 6,6,6,6,6,6,6,6, # d0 - d7 + 6,6,6,6,6,6,6,6, # d8 - df + 6,6,6,6,6,6,6,6, # e0 - e7 + 6,6,6,6,6,6,6,6, # e8 - ef + 6,6,6,6,6,6,6,6, # f0 - f7 + 6,6,6,6,6,6,6,0 # f8 - ff +) + +GB2312_ST = ( + MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START, 3,MachineState.ERROR,#00-07 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ITS_ME,#08-0f + MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ERROR,MachineState.ERROR,MachineState.START,#10-17 + 4,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#18-1f + MachineState.ERROR,MachineState.ERROR, 5,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ERROR,#20-27 + MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.START #28-2f +) + +# To be accurate, the length of class 6 can be either 2 or 4. +# But it is not necessary to discriminate between the two since +# it is used for frequency analysis only, and we are validating +# each code range there as well. So it is safe to set it to be +# 2 here. +GB2312_CHAR_LEN_TABLE = (0, 1, 1, 1, 1, 1, 2) + +GB2312_SM_MODEL = {'class_table': GB2312_CLS, + 'class_factor': 7, + 'state_table': GB2312_ST, + 'char_len_table': GB2312_CHAR_LEN_TABLE, + 'name': 'GB2312'} + +# Shift_JIS + +SJIS_CLS = ( + 1,1,1,1,1,1,1,1, # 00 - 07 + 1,1,1,1,1,1,0,0, # 08 - 0f + 1,1,1,1,1,1,1,1, # 10 - 17 + 1,1,1,0,1,1,1,1, # 18 - 1f + 1,1,1,1,1,1,1,1, # 20 - 27 + 1,1,1,1,1,1,1,1, # 28 - 2f + 1,1,1,1,1,1,1,1, # 30 - 37 + 1,1,1,1,1,1,1,1, # 38 - 3f + 2,2,2,2,2,2,2,2, # 40 - 47 + 2,2,2,2,2,2,2,2, # 48 - 4f + 2,2,2,2,2,2,2,2, # 50 - 57 + 2,2,2,2,2,2,2,2, # 58 - 5f + 2,2,2,2,2,2,2,2, # 60 - 67 + 2,2,2,2,2,2,2,2, # 68 - 6f + 2,2,2,2,2,2,2,2, # 70 - 77 + 2,2,2,2,2,2,2,1, # 78 - 7f + 3,3,3,3,3,2,2,3, # 80 - 87 + 3,3,3,3,3,3,3,3, # 88 - 8f + 3,3,3,3,3,3,3,3, # 90 - 97 + 3,3,3,3,3,3,3,3, # 98 - 9f + #0xa0 is illegal in sjis encoding, but some pages does + #contain such byte. We need to be more error forgiven. + 2,2,2,2,2,2,2,2, # a0 - a7 + 2,2,2,2,2,2,2,2, # a8 - af + 2,2,2,2,2,2,2,2, # b0 - b7 + 2,2,2,2,2,2,2,2, # b8 - bf + 2,2,2,2,2,2,2,2, # c0 - c7 + 2,2,2,2,2,2,2,2, # c8 - cf + 2,2,2,2,2,2,2,2, # d0 - d7 + 2,2,2,2,2,2,2,2, # d8 - df + 3,3,3,3,3,3,3,3, # e0 - e7 + 3,3,3,3,3,4,4,4, # e8 - ef + 3,3,3,3,3,3,3,3, # f0 - f7 + 3,3,3,3,3,0,0,0) # f8 - ff + + +SJIS_ST = ( + MachineState.ERROR,MachineState.START,MachineState.START, 3,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#00-07 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,#08-0f + MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.START #10-17 +) + +SJIS_CHAR_LEN_TABLE = (0, 1, 1, 2, 0, 0) + +SJIS_SM_MODEL = {'class_table': SJIS_CLS, + 'class_factor': 6, + 'state_table': SJIS_ST, + 'char_len_table': SJIS_CHAR_LEN_TABLE, + 'name': 'Shift_JIS'} + +# UCS2-BE + +UCS2BE_CLS = ( + 0,0,0,0,0,0,0,0, # 00 - 07 + 0,0,1,0,0,2,0,0, # 08 - 0f + 0,0,0,0,0,0,0,0, # 10 - 17 + 0,0,0,3,0,0,0,0, # 18 - 1f + 0,0,0,0,0,0,0,0, # 20 - 27 + 0,3,3,3,3,3,0,0, # 28 - 2f + 0,0,0,0,0,0,0,0, # 30 - 37 + 0,0,0,0,0,0,0,0, # 38 - 3f + 0,0,0,0,0,0,0,0, # 40 - 47 + 0,0,0,0,0,0,0,0, # 48 - 4f + 0,0,0,0,0,0,0,0, # 50 - 57 + 0,0,0,0,0,0,0,0, # 58 - 5f + 0,0,0,0,0,0,0,0, # 60 - 67 + 0,0,0,0,0,0,0,0, # 68 - 6f + 0,0,0,0,0,0,0,0, # 70 - 77 + 0,0,0,0,0,0,0,0, # 78 - 7f + 0,0,0,0,0,0,0,0, # 80 - 87 + 0,0,0,0,0,0,0,0, # 88 - 8f + 0,0,0,0,0,0,0,0, # 90 - 97 + 0,0,0,0,0,0,0,0, # 98 - 9f + 0,0,0,0,0,0,0,0, # a0 - a7 + 0,0,0,0,0,0,0,0, # a8 - af + 0,0,0,0,0,0,0,0, # b0 - b7 + 0,0,0,0,0,0,0,0, # b8 - bf + 0,0,0,0,0,0,0,0, # c0 - c7 + 0,0,0,0,0,0,0,0, # c8 - cf + 0,0,0,0,0,0,0,0, # d0 - d7 + 0,0,0,0,0,0,0,0, # d8 - df + 0,0,0,0,0,0,0,0, # e0 - e7 + 0,0,0,0,0,0,0,0, # e8 - ef + 0,0,0,0,0,0,0,0, # f0 - f7 + 0,0,0,0,0,0,4,5 # f8 - ff +) + +UCS2BE_ST = ( + 5, 7, 7,MachineState.ERROR, 4, 3,MachineState.ERROR,MachineState.ERROR,#00-07 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,#08-0f + MachineState.ITS_ME,MachineState.ITS_ME, 6, 6, 6, 6,MachineState.ERROR,MachineState.ERROR,#10-17 + 6, 6, 6, 6, 6,MachineState.ITS_ME, 6, 6,#18-1f + 6, 6, 6, 6, 5, 7, 7,MachineState.ERROR,#20-27 + 5, 8, 6, 6,MachineState.ERROR, 6, 6, 6,#28-2f + 6, 6, 6, 6,MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.START #30-37 +) + +UCS2BE_CHAR_LEN_TABLE = (2, 2, 2, 0, 2, 2) + +UCS2BE_SM_MODEL = {'class_table': UCS2BE_CLS, + 'class_factor': 6, + 'state_table': UCS2BE_ST, + 'char_len_table': UCS2BE_CHAR_LEN_TABLE, + 'name': 'UTF-16BE'} + +# UCS2-LE + +UCS2LE_CLS = ( + 0,0,0,0,0,0,0,0, # 00 - 07 + 0,0,1,0,0,2,0,0, # 08 - 0f + 0,0,0,0,0,0,0,0, # 10 - 17 + 0,0,0,3,0,0,0,0, # 18 - 1f + 0,0,0,0,0,0,0,0, # 20 - 27 + 0,3,3,3,3,3,0,0, # 28 - 2f + 0,0,0,0,0,0,0,0, # 30 - 37 + 0,0,0,0,0,0,0,0, # 38 - 3f + 0,0,0,0,0,0,0,0, # 40 - 47 + 0,0,0,0,0,0,0,0, # 48 - 4f + 0,0,0,0,0,0,0,0, # 50 - 57 + 0,0,0,0,0,0,0,0, # 58 - 5f + 0,0,0,0,0,0,0,0, # 60 - 67 + 0,0,0,0,0,0,0,0, # 68 - 6f + 0,0,0,0,0,0,0,0, # 70 - 77 + 0,0,0,0,0,0,0,0, # 78 - 7f + 0,0,0,0,0,0,0,0, # 80 - 87 + 0,0,0,0,0,0,0,0, # 88 - 8f + 0,0,0,0,0,0,0,0, # 90 - 97 + 0,0,0,0,0,0,0,0, # 98 - 9f + 0,0,0,0,0,0,0,0, # a0 - a7 + 0,0,0,0,0,0,0,0, # a8 - af + 0,0,0,0,0,0,0,0, # b0 - b7 + 0,0,0,0,0,0,0,0, # b8 - bf + 0,0,0,0,0,0,0,0, # c0 - c7 + 0,0,0,0,0,0,0,0, # c8 - cf + 0,0,0,0,0,0,0,0, # d0 - d7 + 0,0,0,0,0,0,0,0, # d8 - df + 0,0,0,0,0,0,0,0, # e0 - e7 + 0,0,0,0,0,0,0,0, # e8 - ef + 0,0,0,0,0,0,0,0, # f0 - f7 + 0,0,0,0,0,0,4,5 # f8 - ff +) + +UCS2LE_ST = ( + 6, 6, 7, 6, 4, 3,MachineState.ERROR,MachineState.ERROR,#00-07 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,#08-0f + MachineState.ITS_ME,MachineState.ITS_ME, 5, 5, 5,MachineState.ERROR,MachineState.ITS_ME,MachineState.ERROR,#10-17 + 5, 5, 5,MachineState.ERROR, 5,MachineState.ERROR, 6, 6,#18-1f + 7, 6, 8, 8, 5, 5, 5,MachineState.ERROR,#20-27 + 5, 5, 5,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR, 5, 5,#28-2f + 5, 5, 5,MachineState.ERROR, 5,MachineState.ERROR,MachineState.START,MachineState.START #30-37 +) + +UCS2LE_CHAR_LEN_TABLE = (2, 2, 2, 2, 2, 2) + +UCS2LE_SM_MODEL = {'class_table': UCS2LE_CLS, + 'class_factor': 6, + 'state_table': UCS2LE_ST, + 'char_len_table': UCS2LE_CHAR_LEN_TABLE, + 'name': 'UTF-16LE'} + +# UTF-8 + +UTF8_CLS = ( + 1,1,1,1,1,1,1,1, # 00 - 07 #allow 0x00 as a legal value + 1,1,1,1,1,1,0,0, # 08 - 0f + 1,1,1,1,1,1,1,1, # 10 - 17 + 1,1,1,0,1,1,1,1, # 18 - 1f + 1,1,1,1,1,1,1,1, # 20 - 27 + 1,1,1,1,1,1,1,1, # 28 - 2f + 1,1,1,1,1,1,1,1, # 30 - 37 + 1,1,1,1,1,1,1,1, # 38 - 3f + 1,1,1,1,1,1,1,1, # 40 - 47 + 1,1,1,1,1,1,1,1, # 48 - 4f + 1,1,1,1,1,1,1,1, # 50 - 57 + 1,1,1,1,1,1,1,1, # 58 - 5f + 1,1,1,1,1,1,1,1, # 60 - 67 + 1,1,1,1,1,1,1,1, # 68 - 6f + 1,1,1,1,1,1,1,1, # 70 - 77 + 1,1,1,1,1,1,1,1, # 78 - 7f + 2,2,2,2,3,3,3,3, # 80 - 87 + 4,4,4,4,4,4,4,4, # 88 - 8f + 4,4,4,4,4,4,4,4, # 90 - 97 + 4,4,4,4,4,4,4,4, # 98 - 9f + 5,5,5,5,5,5,5,5, # a0 - a7 + 5,5,5,5,5,5,5,5, # a8 - af + 5,5,5,5,5,5,5,5, # b0 - b7 + 5,5,5,5,5,5,5,5, # b8 - bf + 0,0,6,6,6,6,6,6, # c0 - c7 + 6,6,6,6,6,6,6,6, # c8 - cf + 6,6,6,6,6,6,6,6, # d0 - d7 + 6,6,6,6,6,6,6,6, # d8 - df + 7,8,8,8,8,8,8,8, # e0 - e7 + 8,8,8,8,8,9,8,8, # e8 - ef + 10,11,11,11,11,11,11,11, # f0 - f7 + 12,13,13,13,14,15,0,0 # f8 - ff +) + +UTF8_ST = ( + MachineState.ERROR,MachineState.START,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR, 12, 10,#00-07 + 9, 11, 8, 7, 6, 5, 4, 3,#08-0f + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#10-17 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#18-1f + MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,#20-27 + MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,MachineState.ITS_ME,#28-2f + MachineState.ERROR,MachineState.ERROR, 5, 5, 5, 5,MachineState.ERROR,MachineState.ERROR,#30-37 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#38-3f + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR, 5, 5, 5,MachineState.ERROR,MachineState.ERROR,#40-47 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#48-4f + MachineState.ERROR,MachineState.ERROR, 7, 7, 7, 7,MachineState.ERROR,MachineState.ERROR,#50-57 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#58-5f + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR, 7, 7,MachineState.ERROR,MachineState.ERROR,#60-67 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#68-6f + MachineState.ERROR,MachineState.ERROR, 9, 9, 9, 9,MachineState.ERROR,MachineState.ERROR,#70-77 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#78-7f + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR, 9,MachineState.ERROR,MachineState.ERROR,#80-87 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#88-8f + MachineState.ERROR,MachineState.ERROR, 12, 12, 12, 12,MachineState.ERROR,MachineState.ERROR,#90-97 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#98-9f + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR, 12,MachineState.ERROR,MachineState.ERROR,#a0-a7 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#a8-af + MachineState.ERROR,MachineState.ERROR, 12, 12, 12,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#b0-b7 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,#b8-bf + MachineState.ERROR,MachineState.ERROR,MachineState.START,MachineState.START,MachineState.START,MachineState.START,MachineState.ERROR,MachineState.ERROR,#c0-c7 + MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR,MachineState.ERROR #c8-cf +) + +UTF8_CHAR_LEN_TABLE = (0, 1, 0, 0, 0, 0, 2, 3, 3, 3, 4, 4, 5, 5, 6, 6) + +UTF8_SM_MODEL = {'class_table': UTF8_CLS, + 'class_factor': 16, + 'state_table': UTF8_ST, + 'char_len_table': UTF8_CHAR_LEN_TABLE, + 'name': 'UTF-8'} diff --git a/venv/Lib/site-packages/pip/_vendor/chardet/metadata/__init__.py b/venv/Lib/site-packages/pip/_vendor/chardet/metadata/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/venv/Lib/site-packages/pip/_vendor/chardet/metadata/__pycache__/__init__.cpython-39.pyc b/venv/Lib/site-packages/pip/_vendor/chardet/metadata/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..08ca21165bb0076926c04b4f40c9109326120d23 GIT binary patch literal 193 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_vendor/chardet/metadata/languages.py b/venv/Lib/site-packages/pip/_vendor/chardet/metadata/languages.py new file mode 100644 index 0000000..3237d5a --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/chardet/metadata/languages.py @@ -0,0 +1,310 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +""" +Metadata about languages used by our model training code for our +SingleByteCharSetProbers. Could be used for other things in the future. + +This code is based on the language metadata from the uchardet project. +""" +from __future__ import absolute_import, print_function + +from string import ascii_letters + + +# TODO: Add Ukranian (KOI8-U) + +class Language(object): + """Metadata about a language useful for training models + + :ivar name: The human name for the language, in English. + :type name: str + :ivar iso_code: 2-letter ISO 639-1 if possible, 3-letter ISO code otherwise, + or use another catalog as a last resort. + :type iso_code: str + :ivar use_ascii: Whether or not ASCII letters should be included in trained + models. + :type use_ascii: bool + :ivar charsets: The charsets we want to support and create data for. + :type charsets: list of str + :ivar alphabet: The characters in the language's alphabet. If `use_ascii` is + `True`, you only need to add those not in the ASCII set. + :type alphabet: str + :ivar wiki_start_pages: The Wikipedia pages to start from if we're crawling + Wikipedia for training data. + :type wiki_start_pages: list of str + """ + def __init__(self, name=None, iso_code=None, use_ascii=True, charsets=None, + alphabet=None, wiki_start_pages=None): + super(Language, self).__init__() + self.name = name + self.iso_code = iso_code + self.use_ascii = use_ascii + self.charsets = charsets + if self.use_ascii: + if alphabet: + alphabet += ascii_letters + else: + alphabet = ascii_letters + elif not alphabet: + raise ValueError('Must supply alphabet if use_ascii is False') + self.alphabet = ''.join(sorted(set(alphabet))) if alphabet else None + self.wiki_start_pages = wiki_start_pages + + def __repr__(self): + return '{}({})'.format(self.__class__.__name__, + ', '.join('{}={!r}'.format(k, v) + for k, v in self.__dict__.items() + if not k.startswith('_'))) + + +LANGUAGES = {'Arabic': Language(name='Arabic', + iso_code='ar', + use_ascii=False, + # We only support encodings that use isolated + # forms, because the current recommendation is + # that the rendering system handles presentation + # forms. This means we purposefully skip IBM864. + charsets=['ISO-8859-6', 'WINDOWS-1256', + 'CP720', 'CP864'], + alphabet=u'ءآأؤإئابةتثجحخدذرزسشصضطظعغػؼؽؾؿـÙقكلمنهوىيًٌÙÙŽÙÙÙ‘', + wiki_start_pages=[u'الصÙحة_الرئيسية']), + 'Belarusian': Language(name='Belarusian', + iso_code='be', + use_ascii=False, + charsets=['ISO-8859-5', 'WINDOWS-1251', + 'IBM866', 'MacCyrillic'], + alphabet=(u'ÐБВГДЕÐЖЗІЙКЛМÐОПРСТУЎФХЦЧШЫЬЭЮЯ' + u'абвгдеёжзійклмнопрÑтуўфхцчшыьÑÑŽÑʼ'), + wiki_start_pages=[u'ГалоўнаÑ_Ñтаронка']), + 'Bulgarian': Language(name='Bulgarian', + iso_code='bg', + use_ascii=False, + charsets=['ISO-8859-5', 'WINDOWS-1251', + 'IBM855'], + alphabet=(u'ÐБВГДЕЖЗИЙКЛМÐОПРСТУФХЦЧШЩЪЬЮЯ' + u'абвгдежзийклмнопрÑтуфхцчшщъьюÑ'), + wiki_start_pages=[u'Ðачална_Ñтраница']), + 'Czech': Language(name='Czech', + iso_code='cz', + use_ascii=True, + charsets=['ISO-8859-2', 'WINDOWS-1250'], + alphabet=u'áÄÄéěíňóřšťúůýžÃČĎÉĚÃŇÓŘŠŤÚŮÃŽ', + wiki_start_pages=[u'Hlavní_strana']), + 'Danish': Language(name='Danish', + iso_code='da', + use_ascii=True, + charsets=['ISO-8859-1', 'ISO-8859-15', + 'WINDOWS-1252'], + alphabet=u'æøåÆØÅ', + wiki_start_pages=[u'Forside']), + 'German': Language(name='German', + iso_code='de', + use_ascii=True, + charsets=['ISO-8859-1', 'WINDOWS-1252'], + alphabet=u'äöüßÄÖÜ', + wiki_start_pages=[u'Wikipedia:Hauptseite']), + 'Greek': Language(name='Greek', + iso_code='el', + use_ascii=False, + charsets=['ISO-8859-7', 'WINDOWS-1253'], + alphabet=(u'αβγδεζηθικλμνξοπÏσςτυφχψωάέήίόÏÏŽ' + u'ΑΒΓΔΕΖΗΘΙΚΛΜÎΞΟΠΡΣΣΤΥΦΧΨΩΆΈΉΊΌΎÎ'), + wiki_start_pages=[u'ΠÏλη:ΚÏÏια']), + 'English': Language(name='English', + iso_code='en', + use_ascii=True, + charsets=['ISO-8859-1', 'WINDOWS-1252'], + wiki_start_pages=[u'Main_Page']), + 'Esperanto': Language(name='Esperanto', + iso_code='eo', + # Q, W, X, and Y not used at all + use_ascii=False, + charsets=['ISO-8859-3'], + alphabet=(u'abcĉdefgÄhÄ¥ijĵklmnoprsÅtuÅ­vz' + u'ABCĈDEFGÄœHĤIJÄ´KLMNOPRSÅœTUŬVZ'), + wiki_start_pages=[u'Vikipedio:ĈefpaÄo']), + 'Spanish': Language(name='Spanish', + iso_code='es', + use_ascii=True, + charsets=['ISO-8859-1', 'ISO-8859-15', + 'WINDOWS-1252'], + alphabet=u'ñáéíóúüÑÃÉÃÓÚÜ', + wiki_start_pages=[u'Wikipedia:Portada']), + 'Estonian': Language(name='Estonian', + iso_code='et', + use_ascii=False, + charsets=['ISO-8859-4', 'ISO-8859-13', + 'WINDOWS-1257'], + # C, F, Å , Q, W, X, Y, Z, Ž are only for + # loanwords + alphabet=(u'ABDEGHIJKLMNOPRSTUVÕÄÖÜ' + u'abdeghijklmnoprstuvõäöü'), + wiki_start_pages=[u'Esileht']), + 'Finnish': Language(name='Finnish', + iso_code='fi', + use_ascii=True, + charsets=['ISO-8859-1', 'ISO-8859-15', + 'WINDOWS-1252'], + alphabet=u'ÅÄÖŠŽåäöšž', + wiki_start_pages=[u'Wikipedia:Etusivu']), + 'French': Language(name='French', + iso_code='fr', + use_ascii=True, + charsets=['ISO-8859-1', 'ISO-8859-15', + 'WINDOWS-1252'], + alphabet=u'œàâçèéîïùûêŒÀÂÇÈÉÎÃÙÛÊ', + wiki_start_pages=[u'Wikipédia:Accueil_principal', + u'BÅ“uf (animal)']), + 'Hebrew': Language(name='Hebrew', + iso_code='he', + use_ascii=False, + charsets=['ISO-8859-8', 'WINDOWS-1255'], + alphabet=u'×בגדהוזחטיךכל×מןנסעףפץצקרשתװױײ', + wiki_start_pages=[u'עמוד_ר×שי']), + 'Croatian': Language(name='Croatian', + iso_code='hr', + # Q, W, X, Y are only used for foreign words. + use_ascii=False, + charsets=['ISO-8859-2', 'WINDOWS-1250'], + alphabet=(u'abcÄćdÄ‘efghijklmnoprsÅ¡tuvzž' + u'ABCČĆDÄEFGHIJKLMNOPRSÅ TUVZŽ'), + wiki_start_pages=[u'Glavna_stranica']), + 'Hungarian': Language(name='Hungarian', + iso_code='hu', + # Q, W, X, Y are only used for foreign words. + use_ascii=False, + charsets=['ISO-8859-2', 'WINDOWS-1250'], + alphabet=(u'abcdefghijklmnoprstuvzáéíóöőúüű' + u'ABCDEFGHIJKLMNOPRSTUVZÃÉÃÓÖÅÚÜŰ'), + wiki_start_pages=[u'KezdÅ‘lap']), + 'Italian': Language(name='Italian', + iso_code='it', + use_ascii=True, + charsets=['ISO-8859-1', 'ISO-8859-15', + 'WINDOWS-1252'], + alphabet=u'ÀÈÉÌÒÓÙàèéìòóù', + wiki_start_pages=[u'Pagina_principale']), + 'Lithuanian': Language(name='Lithuanian', + iso_code='lt', + use_ascii=False, + charsets=['ISO-8859-13', 'WINDOWS-1257', + 'ISO-8859-4'], + # Q, W, and X not used at all + alphabet=(u'AÄ„BCÄŒDEĘĖFGHIÄ®YJKLMNOPRSÅ TUŲŪVZŽ' + u'aÄ…bcÄdeęėfghiįyjklmnoprsÅ¡tuųūvzž'), + wiki_start_pages=[u'Pagrindinis_puslapis']), + 'Latvian': Language(name='Latvian', + iso_code='lv', + use_ascii=False, + charsets=['ISO-8859-13', 'WINDOWS-1257', + 'ISO-8859-4'], + # Q, W, X, Y are only for loanwords + alphabet=(u'AÄ€BCÄŒDEÄ’FGÄ¢HIĪJKĶLÄ»MNÅ…OPRSÅ TUŪVZŽ' + u'aÄbcÄdeÄ“fgÄ£hiÄ«jkÄ·lļmnņoprsÅ¡tuÅ«vzž'), + wiki_start_pages=[u'SÄkumlapa']), + 'Macedonian': Language(name='Macedonian', + iso_code='mk', + use_ascii=False, + charsets=['ISO-8859-5', 'WINDOWS-1251', + 'MacCyrillic', 'IBM855'], + alphabet=(u'ÐБВГДЃЕЖЗЅИЈКЛЉМÐЊОПРСТЌУФХЦЧÐШ' + u'абвгдѓежзѕијклљмнњопрÑтќуфхцчџш'), + wiki_start_pages=[u'Главна_Ñтраница']), + 'Dutch': Language(name='Dutch', + iso_code='nl', + use_ascii=True, + charsets=['ISO-8859-1', 'WINDOWS-1252'], + wiki_start_pages=[u'Hoofdpagina']), + 'Polish': Language(name='Polish', + iso_code='pl', + # Q and X are only used for foreign words. + use_ascii=False, + charsets=['ISO-8859-2', 'WINDOWS-1250'], + alphabet=(u'AÄ„BCĆDEĘFGHIJKLÅMNŃOÓPRSÅšTUWYZŹŻ' + u'aÄ…bcćdeÄ™fghijklÅ‚mnÅ„oóprsÅ›tuwyzźż'), + wiki_start_pages=[u'Wikipedia:Strona_główna']), + 'Portuguese': Language(name='Portuguese', + iso_code='pt', + use_ascii=True, + charsets=['ISO-8859-1', 'ISO-8859-15', + 'WINDOWS-1252'], + alphabet=u'ÃÂÃÀÇÉÊÃÓÔÕÚáâãàçéêíóôõú', + wiki_start_pages=[u'Wikipédia:Página_principal']), + 'Romanian': Language(name='Romanian', + iso_code='ro', + use_ascii=True, + charsets=['ISO-8859-2', 'WINDOWS-1250'], + alphabet=u'ăâîșțĂÂÎȘȚ', + wiki_start_pages=[u'Pagina_principală']), + 'Russian': Language(name='Russian', + iso_code='ru', + use_ascii=False, + charsets=['ISO-8859-5', 'WINDOWS-1251', + 'KOI8-R', 'MacCyrillic', 'IBM866', + 'IBM855'], + alphabet=(u'абвгдеёжзийклмнопрÑтуфхцчшщъыьÑÑŽÑ' + u'ÐБВГДЕÐЖЗИЙКЛМÐОПРСТУФХЦЧШЩЪЫЬЭЮЯ'), + wiki_start_pages=[u'ЗаглавнаÑ_Ñтраница']), + 'Slovak': Language(name='Slovak', + iso_code='sk', + use_ascii=True, + charsets=['ISO-8859-2', 'WINDOWS-1250'], + alphabet=u'áäÄÄéíĺľňóôŕšťúýžÃÄČĎÉÃĹĽŇÓÔŔŠŤÚÃŽ', + wiki_start_pages=[u'Hlavná_stránka']), + 'Slovene': Language(name='Slovene', + iso_code='sl', + # Q, W, X, Y are only used for foreign words. + use_ascii=False, + charsets=['ISO-8859-2', 'WINDOWS-1250'], + alphabet=(u'abcÄdefghijklmnoprsÅ¡tuvzž' + u'ABCÄŒDEFGHIJKLMNOPRSÅ TUVZŽ'), + wiki_start_pages=[u'Glavna_stran']), + # Serbian can be written in both Latin and Cyrillic, but there's no + # simple way to get the Latin alphabet pages from Wikipedia through + # the API, so for now we just support Cyrillic. + 'Serbian': Language(name='Serbian', + iso_code='sr', + alphabet=(u'ÐБВГДЂЕЖЗИЈКЛЉМÐЊОПРСТЋУФХЦЧÐШ' + u'абвгдђежзијклљмнњопрÑтћуфхцчџш'), + charsets=['ISO-8859-5', 'WINDOWS-1251', + 'MacCyrillic', 'IBM855'], + wiki_start_pages=[u'Главна_Ñтрана']), + 'Thai': Language(name='Thai', + iso_code='th', + use_ascii=False, + charsets=['ISO-8859-11', 'TIS-620', 'CP874'], + alphabet=u'à¸à¸‚ฃคฅฆงจฉชซฌà¸à¸Žà¸à¸à¸‘ฒณดตถทธนบปผà¸à¸žà¸Ÿà¸ à¸¡à¸¢à¸£à¸¤à¸¥à¸¦à¸§à¸¨à¸©à¸ªà¸«à¸¬à¸­à¸®à¸¯à¸°à¸±à¸²à¸³à¸´à¸µà¸¶à¸·à¸ºà¸¸à¸¹à¸¿à¹€à¹à¹‚ใไๅๆ็่้๊๋์à¹à¹Žà¹à¹à¹‘๒๓๔๕๖๗๘๙๚๛', + wiki_start_pages=[u'หน้าหลัà¸']), + 'Turkish': Language(name='Turkish', + iso_code='tr', + # Q, W, and X are not used by Turkish + use_ascii=False, + charsets=['ISO-8859-3', 'ISO-8859-9', + 'WINDOWS-1254'], + alphabet=(u'abcçdefgÄŸhıijklmnoöprsÅŸtuüvyzâîû' + u'ABCÇDEFGÄžHIÄ°JKLMNOÖPRSÅžTUÃœVYZÂÎÛ'), + wiki_start_pages=[u'Ana_Sayfa']), + 'Vietnamese': Language(name='Vietnamese', + iso_code='vi', + use_ascii=False, + # Windows-1258 is the only common 8-bit + # Vietnamese encoding supported by Python. + # From Wikipedia: + # For systems that lack support for Unicode, + # dozens of 8-bit Vietnamese code pages are + # available.[1] The most common are VISCII + # (TCVN 5712:1993), VPS, and Windows-1258.[3] + # Where ASCII is required, such as when + # ensuring readability in plain text e-mail, + # Vietnamese letters are often encoded + # according to Vietnamese Quoted-Readable + # (VIQR) or VSCII Mnemonic (VSCII-MNEM),[4] + # though usage of either variable-width + # scheme has declined dramatically following + # the adoption of Unicode on the World Wide + # Web. + charsets=['WINDOWS-1258'], + alphabet=(u'aăâbcdÄ‘eêghiklmnoôơpqrstuÆ°vxy' + u'AĂÂBCDÄEÊGHIKLMNOÔƠPQRSTUƯVXY'), + wiki_start_pages=[u'Chữ_Quốc_ngữ']), + } diff --git a/venv/Lib/site-packages/pip/_vendor/chardet/sbcharsetprober.py b/venv/Lib/site-packages/pip/_vendor/chardet/sbcharsetprober.py new file mode 100644 index 0000000..46ba835 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/chardet/sbcharsetprober.py @@ -0,0 +1,145 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Universal charset detector code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 2001 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# Shy Shalom - original C code +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from collections import namedtuple + +from .charsetprober import CharSetProber +from .enums import CharacterCategory, ProbingState, SequenceLikelihood + + +SingleByteCharSetModel = namedtuple('SingleByteCharSetModel', + ['charset_name', + 'language', + 'char_to_order_map', + 'language_model', + 'typical_positive_ratio', + 'keep_ascii_letters', + 'alphabet']) + + +class SingleByteCharSetProber(CharSetProber): + SAMPLE_SIZE = 64 + SB_ENOUGH_REL_THRESHOLD = 1024 # 0.25 * SAMPLE_SIZE^2 + POSITIVE_SHORTCUT_THRESHOLD = 0.95 + NEGATIVE_SHORTCUT_THRESHOLD = 0.05 + + def __init__(self, model, reversed=False, name_prober=None): + super(SingleByteCharSetProber, self).__init__() + self._model = model + # TRUE if we need to reverse every pair in the model lookup + self._reversed = reversed + # Optional auxiliary prober for name decision + self._name_prober = name_prober + self._last_order = None + self._seq_counters = None + self._total_seqs = None + self._total_char = None + self._freq_char = None + self.reset() + + def reset(self): + super(SingleByteCharSetProber, self).reset() + # char order of last character + self._last_order = 255 + self._seq_counters = [0] * SequenceLikelihood.get_num_categories() + self._total_seqs = 0 + self._total_char = 0 + # characters that fall in our sampling range + self._freq_char = 0 + + @property + def charset_name(self): + if self._name_prober: + return self._name_prober.charset_name + else: + return self._model.charset_name + + @property + def language(self): + if self._name_prober: + return self._name_prober.language + else: + return self._model.language + + def feed(self, byte_str): + # TODO: Make filter_international_words keep things in self.alphabet + if not self._model.keep_ascii_letters: + byte_str = self.filter_international_words(byte_str) + if not byte_str: + return self.state + char_to_order_map = self._model.char_to_order_map + language_model = self._model.language_model + for char in byte_str: + order = char_to_order_map.get(char, CharacterCategory.UNDEFINED) + # XXX: This was SYMBOL_CAT_ORDER before, with a value of 250, but + # CharacterCategory.SYMBOL is actually 253, so we use CONTROL + # to make it closer to the original intent. The only difference + # is whether or not we count digits and control characters for + # _total_char purposes. + if order < CharacterCategory.CONTROL: + self._total_char += 1 + # TODO: Follow uchardet's lead and discount confidence for frequent + # control characters. + # See https://github.com/BYVoid/uchardet/commit/55b4f23971db61 + if order < self.SAMPLE_SIZE: + self._freq_char += 1 + if self._last_order < self.SAMPLE_SIZE: + self._total_seqs += 1 + if not self._reversed: + lm_cat = language_model[self._last_order][order] + else: + lm_cat = language_model[order][self._last_order] + self._seq_counters[lm_cat] += 1 + self._last_order = order + + charset_name = self._model.charset_name + if self.state == ProbingState.DETECTING: + if self._total_seqs > self.SB_ENOUGH_REL_THRESHOLD: + confidence = self.get_confidence() + if confidence > self.POSITIVE_SHORTCUT_THRESHOLD: + self.logger.debug('%s confidence = %s, we have a winner', + charset_name, confidence) + self._state = ProbingState.FOUND_IT + elif confidence < self.NEGATIVE_SHORTCUT_THRESHOLD: + self.logger.debug('%s confidence = %s, below negative ' + 'shortcut threshhold %s', charset_name, + confidence, + self.NEGATIVE_SHORTCUT_THRESHOLD) + self._state = ProbingState.NOT_ME + + return self.state + + def get_confidence(self): + r = 0.01 + if self._total_seqs > 0: + r = ((1.0 * self._seq_counters[SequenceLikelihood.POSITIVE]) / + self._total_seqs / self._model.typical_positive_ratio) + r = r * self._freq_char / self._total_char + if r >= 1.0: + r = 0.99 + return r diff --git a/venv/Lib/site-packages/pip/_vendor/chardet/sbcsgroupprober.py b/venv/Lib/site-packages/pip/_vendor/chardet/sbcsgroupprober.py new file mode 100644 index 0000000..bdeef4e --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/chardet/sbcsgroupprober.py @@ -0,0 +1,83 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Universal charset detector code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 2001 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# Shy Shalom - original C code +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .charsetgroupprober import CharSetGroupProber +from .hebrewprober import HebrewProber +from .langbulgarianmodel import (ISO_8859_5_BULGARIAN_MODEL, + WINDOWS_1251_BULGARIAN_MODEL) +from .langgreekmodel import ISO_8859_7_GREEK_MODEL, WINDOWS_1253_GREEK_MODEL +from .langhebrewmodel import WINDOWS_1255_HEBREW_MODEL +# from .langhungarianmodel import (ISO_8859_2_HUNGARIAN_MODEL, +# WINDOWS_1250_HUNGARIAN_MODEL) +from .langrussianmodel import (IBM855_RUSSIAN_MODEL, IBM866_RUSSIAN_MODEL, + ISO_8859_5_RUSSIAN_MODEL, KOI8_R_RUSSIAN_MODEL, + MACCYRILLIC_RUSSIAN_MODEL, + WINDOWS_1251_RUSSIAN_MODEL) +from .langthaimodel import TIS_620_THAI_MODEL +from .langturkishmodel import ISO_8859_9_TURKISH_MODEL +from .sbcharsetprober import SingleByteCharSetProber + + +class SBCSGroupProber(CharSetGroupProber): + def __init__(self): + super(SBCSGroupProber, self).__init__() + hebrew_prober = HebrewProber() + logical_hebrew_prober = SingleByteCharSetProber(WINDOWS_1255_HEBREW_MODEL, + False, hebrew_prober) + # TODO: See if using ISO-8859-8 Hebrew model works better here, since + # it's actually the visual one + visual_hebrew_prober = SingleByteCharSetProber(WINDOWS_1255_HEBREW_MODEL, + True, hebrew_prober) + hebrew_prober.set_model_probers(logical_hebrew_prober, + visual_hebrew_prober) + # TODO: ORDER MATTERS HERE. I changed the order vs what was in master + # and several tests failed that did not before. Some thought + # should be put into the ordering, and we should consider making + # order not matter here, because that is very counter-intuitive. + self.probers = [ + SingleByteCharSetProber(WINDOWS_1251_RUSSIAN_MODEL), + SingleByteCharSetProber(KOI8_R_RUSSIAN_MODEL), + SingleByteCharSetProber(ISO_8859_5_RUSSIAN_MODEL), + SingleByteCharSetProber(MACCYRILLIC_RUSSIAN_MODEL), + SingleByteCharSetProber(IBM866_RUSSIAN_MODEL), + SingleByteCharSetProber(IBM855_RUSSIAN_MODEL), + SingleByteCharSetProber(ISO_8859_7_GREEK_MODEL), + SingleByteCharSetProber(WINDOWS_1253_GREEK_MODEL), + SingleByteCharSetProber(ISO_8859_5_BULGARIAN_MODEL), + SingleByteCharSetProber(WINDOWS_1251_BULGARIAN_MODEL), + # TODO: Restore Hungarian encodings (iso-8859-2 and windows-1250) + # after we retrain model. + # SingleByteCharSetProber(ISO_8859_2_HUNGARIAN_MODEL), + # SingleByteCharSetProber(WINDOWS_1250_HUNGARIAN_MODEL), + SingleByteCharSetProber(TIS_620_THAI_MODEL), + SingleByteCharSetProber(ISO_8859_9_TURKISH_MODEL), + hebrew_prober, + logical_hebrew_prober, + visual_hebrew_prober, + ] + self.reset() diff --git a/venv/Lib/site-packages/pip/_vendor/chardet/sjisprober.py b/venv/Lib/site-packages/pip/_vendor/chardet/sjisprober.py new file mode 100644 index 0000000..9e29623 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/chardet/sjisprober.py @@ -0,0 +1,92 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .mbcharsetprober import MultiByteCharSetProber +from .codingstatemachine import CodingStateMachine +from .chardistribution import SJISDistributionAnalysis +from .jpcntx import SJISContextAnalysis +from .mbcssm import SJIS_SM_MODEL +from .enums import ProbingState, MachineState + + +class SJISProber(MultiByteCharSetProber): + def __init__(self): + super(SJISProber, self).__init__() + self.coding_sm = CodingStateMachine(SJIS_SM_MODEL) + self.distribution_analyzer = SJISDistributionAnalysis() + self.context_analyzer = SJISContextAnalysis() + self.reset() + + def reset(self): + super(SJISProber, self).reset() + self.context_analyzer.reset() + + @property + def charset_name(self): + return self.context_analyzer.charset_name + + @property + def language(self): + return "Japanese" + + def feed(self, byte_str): + for i in range(len(byte_str)): + coding_state = self.coding_sm.next_state(byte_str[i]) + if coding_state == MachineState.ERROR: + self.logger.debug('%s %s prober hit error at byte %s', + self.charset_name, self.language, i) + self._state = ProbingState.NOT_ME + break + elif coding_state == MachineState.ITS_ME: + self._state = ProbingState.FOUND_IT + break + elif coding_state == MachineState.START: + char_len = self.coding_sm.get_current_charlen() + if i == 0: + self._last_char[1] = byte_str[0] + self.context_analyzer.feed(self._last_char[2 - char_len:], + char_len) + self.distribution_analyzer.feed(self._last_char, char_len) + else: + self.context_analyzer.feed(byte_str[i + 1 - char_len:i + 3 + - char_len], char_len) + self.distribution_analyzer.feed(byte_str[i - 1:i + 1], + char_len) + + self._last_char[0] = byte_str[-1] + + if self.state == ProbingState.DETECTING: + if (self.context_analyzer.got_enough_data() and + (self.get_confidence() > self.SHORTCUT_THRESHOLD)): + self._state = ProbingState.FOUND_IT + + return self.state + + def get_confidence(self): + context_conf = self.context_analyzer.get_confidence() + distrib_conf = self.distribution_analyzer.get_confidence() + return max(context_conf, distrib_conf) diff --git a/venv/Lib/site-packages/pip/_vendor/chardet/universaldetector.py b/venv/Lib/site-packages/pip/_vendor/chardet/universaldetector.py new file mode 100644 index 0000000..055a8ac --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/chardet/universaldetector.py @@ -0,0 +1,286 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is Mozilla Universal charset detector code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 2001 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# Shy Shalom - original C code +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### +""" +Module containing the UniversalDetector detector class, which is the primary +class a user of ``chardet`` should use. + +:author: Mark Pilgrim (initial port to Python) +:author: Shy Shalom (original C code) +:author: Dan Blanchard (major refactoring for 3.0) +:author: Ian Cordasco +""" + + +import codecs +import logging +import re + +from .charsetgroupprober import CharSetGroupProber +from .enums import InputState, LanguageFilter, ProbingState +from .escprober import EscCharSetProber +from .latin1prober import Latin1Prober +from .mbcsgroupprober import MBCSGroupProber +from .sbcsgroupprober import SBCSGroupProber + + +class UniversalDetector(object): + """ + The ``UniversalDetector`` class underlies the ``chardet.detect`` function + and coordinates all of the different charset probers. + + To get a ``dict`` containing an encoding and its confidence, you can simply + run: + + .. code:: + + u = UniversalDetector() + u.feed(some_bytes) + u.close() + detected = u.result + + """ + + MINIMUM_THRESHOLD = 0.20 + HIGH_BYTE_DETECTOR = re.compile(b'[\x80-\xFF]') + ESC_DETECTOR = re.compile(b'(\033|~{)') + WIN_BYTE_DETECTOR = re.compile(b'[\x80-\x9F]') + ISO_WIN_MAP = {'iso-8859-1': 'Windows-1252', + 'iso-8859-2': 'Windows-1250', + 'iso-8859-5': 'Windows-1251', + 'iso-8859-6': 'Windows-1256', + 'iso-8859-7': 'Windows-1253', + 'iso-8859-8': 'Windows-1255', + 'iso-8859-9': 'Windows-1254', + 'iso-8859-13': 'Windows-1257'} + + def __init__(self, lang_filter=LanguageFilter.ALL): + self._esc_charset_prober = None + self._charset_probers = [] + self.result = None + self.done = None + self._got_data = None + self._input_state = None + self._last_char = None + self.lang_filter = lang_filter + self.logger = logging.getLogger(__name__) + self._has_win_bytes = None + self.reset() + + def reset(self): + """ + Reset the UniversalDetector and all of its probers back to their + initial states. This is called by ``__init__``, so you only need to + call this directly in between analyses of different documents. + """ + self.result = {'encoding': None, 'confidence': 0.0, 'language': None} + self.done = False + self._got_data = False + self._has_win_bytes = False + self._input_state = InputState.PURE_ASCII + self._last_char = b'' + if self._esc_charset_prober: + self._esc_charset_prober.reset() + for prober in self._charset_probers: + prober.reset() + + def feed(self, byte_str): + """ + Takes a chunk of a document and feeds it through all of the relevant + charset probers. + + After calling ``feed``, you can check the value of the ``done`` + attribute to see if you need to continue feeding the + ``UniversalDetector`` more data, or if it has made a prediction + (in the ``result`` attribute). + + .. note:: + You should always call ``close`` when you're done feeding in your + document if ``done`` is not already ``True``. + """ + if self.done: + return + + if not len(byte_str): + return + + if not isinstance(byte_str, bytearray): + byte_str = bytearray(byte_str) + + # First check for known BOMs, since these are guaranteed to be correct + if not self._got_data: + # If the data starts with BOM, we know it is UTF + if byte_str.startswith(codecs.BOM_UTF8): + # EF BB BF UTF-8 with BOM + self.result = {'encoding': "UTF-8-SIG", + 'confidence': 1.0, + 'language': ''} + elif byte_str.startswith((codecs.BOM_UTF32_LE, + codecs.BOM_UTF32_BE)): + # FF FE 00 00 UTF-32, little-endian BOM + # 00 00 FE FF UTF-32, big-endian BOM + self.result = {'encoding': "UTF-32", + 'confidence': 1.0, + 'language': ''} + elif byte_str.startswith(b'\xFE\xFF\x00\x00'): + # FE FF 00 00 UCS-4, unusual octet order BOM (3412) + self.result = {'encoding': "X-ISO-10646-UCS-4-3412", + 'confidence': 1.0, + 'language': ''} + elif byte_str.startswith(b'\x00\x00\xFF\xFE'): + # 00 00 FF FE UCS-4, unusual octet order BOM (2143) + self.result = {'encoding': "X-ISO-10646-UCS-4-2143", + 'confidence': 1.0, + 'language': ''} + elif byte_str.startswith((codecs.BOM_LE, codecs.BOM_BE)): + # FF FE UTF-16, little endian BOM + # FE FF UTF-16, big endian BOM + self.result = {'encoding': "UTF-16", + 'confidence': 1.0, + 'language': ''} + + self._got_data = True + if self.result['encoding'] is not None: + self.done = True + return + + # If none of those matched and we've only see ASCII so far, check + # for high bytes and escape sequences + if self._input_state == InputState.PURE_ASCII: + if self.HIGH_BYTE_DETECTOR.search(byte_str): + self._input_state = InputState.HIGH_BYTE + elif self._input_state == InputState.PURE_ASCII and \ + self.ESC_DETECTOR.search(self._last_char + byte_str): + self._input_state = InputState.ESC_ASCII + + self._last_char = byte_str[-1:] + + # If we've seen escape sequences, use the EscCharSetProber, which + # uses a simple state machine to check for known escape sequences in + # HZ and ISO-2022 encodings, since those are the only encodings that + # use such sequences. + if self._input_state == InputState.ESC_ASCII: + if not self._esc_charset_prober: + self._esc_charset_prober = EscCharSetProber(self.lang_filter) + if self._esc_charset_prober.feed(byte_str) == ProbingState.FOUND_IT: + self.result = {'encoding': + self._esc_charset_prober.charset_name, + 'confidence': + self._esc_charset_prober.get_confidence(), + 'language': + self._esc_charset_prober.language} + self.done = True + # If we've seen high bytes (i.e., those with values greater than 127), + # we need to do more complicated checks using all our multi-byte and + # single-byte probers that are left. The single-byte probers + # use character bigram distributions to determine the encoding, whereas + # the multi-byte probers use a combination of character unigram and + # bigram distributions. + elif self._input_state == InputState.HIGH_BYTE: + if not self._charset_probers: + self._charset_probers = [MBCSGroupProber(self.lang_filter)] + # If we're checking non-CJK encodings, use single-byte prober + if self.lang_filter & LanguageFilter.NON_CJK: + self._charset_probers.append(SBCSGroupProber()) + self._charset_probers.append(Latin1Prober()) + for prober in self._charset_probers: + if prober.feed(byte_str) == ProbingState.FOUND_IT: + self.result = {'encoding': prober.charset_name, + 'confidence': prober.get_confidence(), + 'language': prober.language} + self.done = True + break + if self.WIN_BYTE_DETECTOR.search(byte_str): + self._has_win_bytes = True + + def close(self): + """ + Stop analyzing the current document and come up with a final + prediction. + + :returns: The ``result`` attribute, a ``dict`` with the keys + `encoding`, `confidence`, and `language`. + """ + # Don't bother with checks if we're already done + if self.done: + return self.result + self.done = True + + if not self._got_data: + self.logger.debug('no data received!') + + # Default to ASCII if it is all we've seen so far + elif self._input_state == InputState.PURE_ASCII: + self.result = {'encoding': 'ascii', + 'confidence': 1.0, + 'language': ''} + + # If we have seen non-ASCII, return the best that met MINIMUM_THRESHOLD + elif self._input_state == InputState.HIGH_BYTE: + prober_confidence = None + max_prober_confidence = 0.0 + max_prober = None + for prober in self._charset_probers: + if not prober: + continue + prober_confidence = prober.get_confidence() + if prober_confidence > max_prober_confidence: + max_prober_confidence = prober_confidence + max_prober = prober + if max_prober and (max_prober_confidence > self.MINIMUM_THRESHOLD): + charset_name = max_prober.charset_name + lower_charset_name = max_prober.charset_name.lower() + confidence = max_prober.get_confidence() + # Use Windows encoding name instead of ISO-8859 if we saw any + # extra Windows-specific bytes + if lower_charset_name.startswith('iso-8859'): + if self._has_win_bytes: + charset_name = self.ISO_WIN_MAP.get(lower_charset_name, + charset_name) + self.result = {'encoding': charset_name, + 'confidence': confidence, + 'language': max_prober.language} + + # Log all prober confidences if none met MINIMUM_THRESHOLD + if self.logger.getEffectiveLevel() <= logging.DEBUG: + if self.result['encoding'] is None: + self.logger.debug('no probers hit minimum threshold') + for group_prober in self._charset_probers: + if not group_prober: + continue + if isinstance(group_prober, CharSetGroupProber): + for prober in group_prober.probers: + self.logger.debug('%s %s confidence = %s', + prober.charset_name, + prober.language, + prober.get_confidence()) + else: + self.logger.debug('%s %s confidence = %s', + group_prober.charset_name, + group_prober.language, + group_prober.get_confidence()) + return self.result diff --git a/venv/Lib/site-packages/pip/_vendor/chardet/utf8prober.py b/venv/Lib/site-packages/pip/_vendor/chardet/utf8prober.py new file mode 100644 index 0000000..6c3196c --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/chardet/utf8prober.py @@ -0,0 +1,82 @@ +######################## BEGIN LICENSE BLOCK ######################## +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is +# Netscape Communications Corporation. +# Portions created by the Initial Developer are Copyright (C) 1998 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Pilgrim - port to Python +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA +######################### END LICENSE BLOCK ######################### + +from .charsetprober import CharSetProber +from .enums import ProbingState, MachineState +from .codingstatemachine import CodingStateMachine +from .mbcssm import UTF8_SM_MODEL + + + +class UTF8Prober(CharSetProber): + ONE_CHAR_PROB = 0.5 + + def __init__(self): + super(UTF8Prober, self).__init__() + self.coding_sm = CodingStateMachine(UTF8_SM_MODEL) + self._num_mb_chars = None + self.reset() + + def reset(self): + super(UTF8Prober, self).reset() + self.coding_sm.reset() + self._num_mb_chars = 0 + + @property + def charset_name(self): + return "utf-8" + + @property + def language(self): + return "" + + def feed(self, byte_str): + for c in byte_str: + coding_state = self.coding_sm.next_state(c) + if coding_state == MachineState.ERROR: + self._state = ProbingState.NOT_ME + break + elif coding_state == MachineState.ITS_ME: + self._state = ProbingState.FOUND_IT + break + elif coding_state == MachineState.START: + if self.coding_sm.get_current_charlen() >= 2: + self._num_mb_chars += 1 + + if self.state == ProbingState.DETECTING: + if self.get_confidence() > self.SHORTCUT_THRESHOLD: + self._state = ProbingState.FOUND_IT + + return self.state + + def get_confidence(self): + unlike = 0.99 + if self._num_mb_chars < 6: + unlike *= self.ONE_CHAR_PROB ** self._num_mb_chars + return 1.0 - unlike + else: + return unlike diff --git a/venv/Lib/site-packages/pip/_vendor/chardet/version.py b/venv/Lib/site-packages/pip/_vendor/chardet/version.py new file mode 100644 index 0000000..70369b9 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/chardet/version.py @@ -0,0 +1,9 @@ +""" +This module exists only to simplify retrieving the version number of chardet +from within setup.py and from chardet subpackages. + +:author: Dan Blanchard (dan.blanchard@gmail.com) +""" + +__version__ = "4.0.0" +VERSION = __version__.split('.') diff --git a/venv/Lib/site-packages/pip/_vendor/colorama/__init__.py b/venv/Lib/site-packages/pip/_vendor/colorama/__init__.py new file mode 100644 index 0000000..b149ed7 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/colorama/__init__.py @@ -0,0 +1,6 @@ +# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. +from .initialise import init, deinit, reinit, colorama_text +from .ansi import Fore, Back, Style, Cursor +from .ansitowin32 import AnsiToWin32 + +__version__ = '0.4.4' diff --git a/venv/Lib/site-packages/pip/_vendor/colorama/__pycache__/__init__.cpython-39.pyc b/venv/Lib/site-packages/pip/_vendor/colorama/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6a7c9fc2832198bf68935a11639e969099e9540a GIT binary patch literal 436 zcmYk2%}N6?5Xbi;yWMtMy!Pfz*h7nG5fKqxuT5^}pR>o>mgf5@fRxI_cs1FY|$^LjUo?I6L*8@qxq_Et; z1SSR`K;q#L^VduYaR-nAx{%2s)9M!xH1IVpr}UW{D|Aiidti2;6!3jFJ0Umz0ZUk2 zGfSpTGiNO$SGr`9EV*h(Bbw2wZhY&!8ofMlE=NblkHVIA13BWA>q;B)H#4CWI;V8p WtX+1hbhVQF3?{J9>@XaL{pbhnoOX-= literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_vendor/colorama/__pycache__/ansi.cpython-39.pyc b/venv/Lib/site-packages/pip/_vendor/colorama/__pycache__/ansi.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..07deccbdb4e5dd8186ff9a41cdc8db2c74d8f5bd GIT binary patch literal 3221 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 aQ_9y(%uw4*s_mJV5GgELHrlSWxcq+_wEooq literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_vendor/colorama/__pycache__/initialise.cpython-39.pyc b/venv/Lib/site-packages/pip/_vendor/colorama/__pycache__/initialise.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..957c3f2ea8ff2f4c18cefcfdfe2284e456a41b21 GIT binary patch literal 1703 zcma)6OK%%D5GJ_~tyT{|(x$DEwn7d87Kn?Y0fHiEiUw(YC<`8lnV|yoFO^;%{P>tPRy{q{QTC_-y4km zL&|#dQTYzLu_zQ%JZHn@$cNnNVkneQUhYl(q0iAn2G~RF4eXKfWm5$zJY&OH?W#yM z&-k#VV%5Txw&q72)mEJ|cFKoc)m2-#x}~<&4vyQ3KVr$X*LXAQzvd_tUbh|;CL5Gb zvf|EH2V*j=H-XAS?B-(>76YAe_`ovDPx-mHU>F{I#9r}!;(>=Ab*qGIGBQ?`Gg~)7 z8*N82&tEY>FqY!qUmo5|e>NISDvLsz^g&g9FRe^}D#tQU2YOniRaWiKib{^3X|+E; z)H>h4`}I*~#^!`<>FBvGR0-+0%uA3{nPx?1Gnr>be^DJnh$rqYPw7b3}o`UBzUhxNals(+=F{ zod!O$V&usN`8ux@y_(J|e8(%0O&gmt+d6OC&ILy#g^UT!#Ot5jo`bCJAIRM3-ncA& z&9kvJy?JI2d$Kt0mG)3WPr~H>0A_lSbZZZn>-e$EXZi<#5^B#Jn>t)30s{O!r)Yqy z6p_-Uiz=;FDQl6A3TQdqFuI-6>fbUuQe~m*aH-T0=t*WQ+6m3XubXmaOPBe&fw4c= zVCw)+%&OX_)32BS5yj z5=lqGQnEPQupVkY!3&i5BygBO3+K=#(IwF#aY@wW%*7ZgO;O%KyP*Z*R7kwq!}&%$ zR4{ZxiQU{rL6pjnRDbioFv%y|iao}%c|s+GV-YRKFI^!mV-xN#-O-7teM~cE^4Xlm zwcuP_omByhFf;ZZ-RZ&;T`qVe;8R@L2oH63S<^jK{x4ix=(`5j4yo^l3mjaov^L

t$hm9R!gNe^Jcz!TmTH#kZz;E~jv{1dB-$Q^EnN4aAifbbu!^Fn@gJ*yVcq}$ literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_vendor/colorama/__pycache__/win32.cpython-39.pyc b/venv/Lib/site-packages/pip/_vendor/colorama/__pycache__/win32.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d57b37fac8a62e2f3c8cfbd9b23517d3f6d1240c GIT binary patch literal 3935 zcmai1TXPf16`r1(MzU;duEuylK+K{oa0n#XWQ(FOvbof1Wy%t9cH-33SlzNEB#r19 zVeAr5=5v5@yTZXTF0`2cxd< zGGpE7-m(pm5njXG-DC#+xCI%PXWkipmV3I+eQW%cb^SXA=4LT>!k_5m{d{NApX^Ne zQ&`g)BPziv(L6n zF{k;LP^bK?KdoaiYhurxg_p*OQbEm<(GUQzu@(TV{&6@;0C#J;|)!4%kSBH{U zhmzO)>sk_fd?I^&D0_V<`wM>oGBxHG8-F-CkIKDfsQ3Z6VsXfBU;uGp@&b#M=m7 zi!P7kMm=grGVFvKQ0d;?#on&+?zh9vCJ!G>VZVQ(7?ND{|EnrV=Tu8~)Y3|Ohl`w| z28Bb>R?ge)bHMi5zWLTntbw`Ds)i1WqODg^mx3oEDMj5lYKv-J3ekPkZ#0B_)@?*` z0xKzdGm6?pOS#)&m$!wo>+xn&W#WFlF5-AhdyRHJfP03$W&p=aHZVWdmkqQxnRj5D z@(YaBQI36daIHHTDS^{*^PQ2f1p0zn`>bIu8#o2DFItsjM>jEpjvrGw4>B2Gx;A*2J4+l*o#f zyoc$^36a|3RPT?py>P7-uh8JdYMK z`%5MZ6ae4R>Jg&F@pEw%*$V^Ls`~>%GkxT2A5&>;buqmAC^3$-sGwx|Pv)i-xV} zrQSY?Rh27nOX77yW>(I!PQvrS<7T@(%yz5&q}NYMxZlHiBIHtJq=Veb*}8Y{FkR&HVgD@SAH3|zvBP}&O%pC~nouA7DJAuzWJl;Ic0UJ$nm zcwj_bdM$t%MUtmi#jV1PIsq83r$7{nsU6(Z4g|ftM&uy~u9}l~PxI0t>J;E|nI^6f zp$w(6G^igm@-Yp56!~)}ul*gw(~BPt39yH7%dathEXPvRQRdRFNw--F_F*n%YGy3N zYR#lA*74|Y5^8;{ wu(UO0|a)@h|VYUcu?L;A-ke| z@2<*^-&?8O9%_kDZfTX2`*f+YTwYNbi7OrdB&2z0frRWwtE*-C8#GfpQ?$$96X((= z_85z_B@!d}`m|@-2d?FrsG0j;*G^mZsAV3tFb}JIa5F=h3rSp)_P%2TwtvxXsZjIh(UzxxUh)WL<%7FYDqet*Yytr&y%j_ z9rk!Xq<-1+{?hlujAN~AEZ4r2=E}zInzYup*4FCMtnDq=rLncPDhrR6*VpPh%hKLk z+t}FrTAC2qd!dQf@eW0P{HAulxf=x{YWm%-A2pYcj#mBHZ*KHje%Raz4v(5g?V~&W z?vda6HsE)Tp9Dd8=i_^wcGQYah}ZPK3%a}~nk}->KlGb$U>u0UyGKt28Aw(|6%dD+ zBY%qfYDdpw$<>aAQ!VAx?f7XJ2<1Qr(ieXNsaI`L!c&xqOn^wczPa^ic|+POTMyU2 z*pbue(_4Y_*0(ly>#IYLq`f&>OA1V*MPxy$yqbGSWwLUK1b+Y-s?7Cg8t`Fo6Hg$J z+jv@hfjhkTi~%h_<0W23ufX5t6MPaqhu`K?ynRapS~b`Xyi;V%DCpVY3QMW2Dh z+8K+rj(*NMMxuFUqMccZ)-lhKP3BJgMSH&=2NBTDg9E=G#R*JWXkm^-kP&t&=cYfFp#?%+L!Fmr(<&VZ( zHhD?;L6qyS)}G!C94eP)I3$O{p65U%N8d9tovCmu(4;Ul)yu`(q+E$!)k?vre4T4u z>~#Se9tbg}xh#r6=@*7%UZ#I}ME`-rgO&-I{73zP_ct(r&$YfLCZV@>3ZFw~mgwSx zL^A=8*yxy>2$`pMXNEIV+9NfGHCAF|)&fE=^m>(vkFYBO^DZ7~bQFGu(fN@0W*Qh% zC6J|3KrI}zRD2BKU!z5nAR0h#Gg~*=j6TCo$~n+zlmDNU;4AEEyW8kT+r= zCBOKDM9DAX=H0{Gr)WQE9&OR0pyfa64}z#bcvTQ7yKw_hP(*N2wGC0l;xw<7o<^1- zsv2FXo792k(ub} z8AQh#OrshoZh^=OKd$vf)DvIzqITTwbtU_=WP8;#EaDF&;~ZtYF-v5bDs0Z&g=iL{ zvN1`uU^X}Bve>I5MfPNoQfDSkTc)CPgU($?e1~>2#xj4{RRy%S0>nNh=TDu?_B9pw;8$kZWOsNoPZF*_z)LDZhr;Gle5pfN^;jy0#9+5iswRu>JL zIV~hsV$W-*PWK+>bAj{^rH#lf|~xe1N|&JQCT3mlV50A`CgTFk^r3g;%Hu?z5N zXQgv3pUZamH+W^pT6y`X+UaFaeaHxk{Eut_hbkqXBH1la)fENWG#71tyxl$t(vU5Y zFkL*QRomR$T9wxyw8JpFGj8_dqkdd_;tRipPl+pdgR+#CF$I8P3IG!yOTiET(riWh zZ8_Bn!Z5;R&x_QBR9;Ib_5(WIyfmWHJrKP^To!tQ%gIzA?sdC2%S|~f{RU>7}mG1Xt+&ehsaoz+|<2cyBqui>}UaG z5F-_z8PEzYr;4ihoXq5TK3qI9u~ zA}Hv(BokWyf$V*K$kvvt7q= zT-SBn1@{d>lK51Y=@mrUz5Pzmiq*da)JL`wxau9!`854+$Y&G=bvG}Yl~Tp}A2@@v A%m4rY literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_vendor/colorama/ansi.py b/venv/Lib/site-packages/pip/_vendor/colorama/ansi.py new file mode 100644 index 0000000..11ec695 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/colorama/ansi.py @@ -0,0 +1,102 @@ +# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. +''' +This module generates ANSI character codes to printing colors to terminals. +See: http://en.wikipedia.org/wiki/ANSI_escape_code +''' + +CSI = '\033[' +OSC = '\033]' +BEL = '\a' + + +def code_to_chars(code): + return CSI + str(code) + 'm' + +def set_title(title): + return OSC + '2;' + title + BEL + +def clear_screen(mode=2): + return CSI + str(mode) + 'J' + +def clear_line(mode=2): + return CSI + str(mode) + 'K' + + +class AnsiCodes(object): + def __init__(self): + # the subclasses declare class attributes which are numbers. + # Upon instantiation we define instance attributes, which are the same + # as the class attributes but wrapped with the ANSI escape sequence + for name in dir(self): + if not name.startswith('_'): + value = getattr(self, name) + setattr(self, name, code_to_chars(value)) + + +class AnsiCursor(object): + def UP(self, n=1): + return CSI + str(n) + 'A' + def DOWN(self, n=1): + return CSI + str(n) + 'B' + def FORWARD(self, n=1): + return CSI + str(n) + 'C' + def BACK(self, n=1): + return CSI + str(n) + 'D' + def POS(self, x=1, y=1): + return CSI + str(y) + ';' + str(x) + 'H' + + +class AnsiFore(AnsiCodes): + BLACK = 30 + RED = 31 + GREEN = 32 + YELLOW = 33 + BLUE = 34 + MAGENTA = 35 + CYAN = 36 + WHITE = 37 + RESET = 39 + + # These are fairly well supported, but not part of the standard. + LIGHTBLACK_EX = 90 + LIGHTRED_EX = 91 + LIGHTGREEN_EX = 92 + LIGHTYELLOW_EX = 93 + LIGHTBLUE_EX = 94 + LIGHTMAGENTA_EX = 95 + LIGHTCYAN_EX = 96 + LIGHTWHITE_EX = 97 + + +class AnsiBack(AnsiCodes): + BLACK = 40 + RED = 41 + GREEN = 42 + YELLOW = 43 + BLUE = 44 + MAGENTA = 45 + CYAN = 46 + WHITE = 47 + RESET = 49 + + # These are fairly well supported, but not part of the standard. + LIGHTBLACK_EX = 100 + LIGHTRED_EX = 101 + LIGHTGREEN_EX = 102 + LIGHTYELLOW_EX = 103 + LIGHTBLUE_EX = 104 + LIGHTMAGENTA_EX = 105 + LIGHTCYAN_EX = 106 + LIGHTWHITE_EX = 107 + + +class AnsiStyle(AnsiCodes): + BRIGHT = 1 + DIM = 2 + NORMAL = 22 + RESET_ALL = 0 + +Fore = AnsiFore() +Back = AnsiBack() +Style = AnsiStyle() +Cursor = AnsiCursor() diff --git a/venv/Lib/site-packages/pip/_vendor/colorama/ansitowin32.py b/venv/Lib/site-packages/pip/_vendor/colorama/ansitowin32.py new file mode 100644 index 0000000..6039a05 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/colorama/ansitowin32.py @@ -0,0 +1,258 @@ +# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. +import re +import sys +import os + +from .ansi import AnsiFore, AnsiBack, AnsiStyle, Style, BEL +from .winterm import WinTerm, WinColor, WinStyle +from .win32 import windll, winapi_test + + +winterm = None +if windll is not None: + winterm = WinTerm() + + +class StreamWrapper(object): + ''' + Wraps a stream (such as stdout), acting as a transparent proxy for all + attribute access apart from method 'write()', which is delegated to our + Converter instance. + ''' + def __init__(self, wrapped, converter): + # double-underscore everything to prevent clashes with names of + # attributes on the wrapped stream object. + self.__wrapped = wrapped + self.__convertor = converter + + def __getattr__(self, name): + return getattr(self.__wrapped, name) + + def __enter__(self, *args, **kwargs): + # special method lookup bypasses __getattr__/__getattribute__, see + # https://stackoverflow.com/questions/12632894/why-doesnt-getattr-work-with-exit + # thus, contextlib magic methods are not proxied via __getattr__ + return self.__wrapped.__enter__(*args, **kwargs) + + def __exit__(self, *args, **kwargs): + return self.__wrapped.__exit__(*args, **kwargs) + + def write(self, text): + self.__convertor.write(text) + + def isatty(self): + stream = self.__wrapped + if 'PYCHARM_HOSTED' in os.environ: + if stream is not None and (stream is sys.__stdout__ or stream is sys.__stderr__): + return True + try: + stream_isatty = stream.isatty + except AttributeError: + return False + else: + return stream_isatty() + + @property + def closed(self): + stream = self.__wrapped + try: + return stream.closed + except AttributeError: + return True + + +class AnsiToWin32(object): + ''' + Implements a 'write()' method which, on Windows, will strip ANSI character + sequences from the text, and if outputting to a tty, will convert them into + win32 function calls. + ''' + ANSI_CSI_RE = re.compile('\001?\033\\[((?:\\d|;)*)([a-zA-Z])\002?') # Control Sequence Introducer + ANSI_OSC_RE = re.compile('\001?\033\\]([^\a]*)(\a)\002?') # Operating System Command + + def __init__(self, wrapped, convert=None, strip=None, autoreset=False): + # The wrapped stream (normally sys.stdout or sys.stderr) + self.wrapped = wrapped + + # should we reset colors to defaults after every .write() + self.autoreset = autoreset + + # create the proxy wrapping our output stream + self.stream = StreamWrapper(wrapped, self) + + on_windows = os.name == 'nt' + # We test if the WinAPI works, because even if we are on Windows + # we may be using a terminal that doesn't support the WinAPI + # (e.g. Cygwin Terminal). In this case it's up to the terminal + # to support the ANSI codes. + conversion_supported = on_windows and winapi_test() + + # should we strip ANSI sequences from our output? + if strip is None: + strip = conversion_supported or (not self.stream.closed and not self.stream.isatty()) + self.strip = strip + + # should we should convert ANSI sequences into win32 calls? + if convert is None: + convert = conversion_supported and not self.stream.closed and self.stream.isatty() + self.convert = convert + + # dict of ansi codes to win32 functions and parameters + self.win32_calls = self.get_win32_calls() + + # are we wrapping stderr? + self.on_stderr = self.wrapped is sys.stderr + + def should_wrap(self): + ''' + True if this class is actually needed. If false, then the output + stream will not be affected, nor will win32 calls be issued, so + wrapping stdout is not actually required. This will generally be + False on non-Windows platforms, unless optional functionality like + autoreset has been requested using kwargs to init() + ''' + return self.convert or self.strip or self.autoreset + + def get_win32_calls(self): + if self.convert and winterm: + return { + AnsiStyle.RESET_ALL: (winterm.reset_all, ), + AnsiStyle.BRIGHT: (winterm.style, WinStyle.BRIGHT), + AnsiStyle.DIM: (winterm.style, WinStyle.NORMAL), + AnsiStyle.NORMAL: (winterm.style, WinStyle.NORMAL), + AnsiFore.BLACK: (winterm.fore, WinColor.BLACK), + AnsiFore.RED: (winterm.fore, WinColor.RED), + AnsiFore.GREEN: (winterm.fore, WinColor.GREEN), + AnsiFore.YELLOW: (winterm.fore, WinColor.YELLOW), + AnsiFore.BLUE: (winterm.fore, WinColor.BLUE), + AnsiFore.MAGENTA: (winterm.fore, WinColor.MAGENTA), + AnsiFore.CYAN: (winterm.fore, WinColor.CYAN), + AnsiFore.WHITE: (winterm.fore, WinColor.GREY), + AnsiFore.RESET: (winterm.fore, ), + AnsiFore.LIGHTBLACK_EX: (winterm.fore, WinColor.BLACK, True), + AnsiFore.LIGHTRED_EX: (winterm.fore, WinColor.RED, True), + AnsiFore.LIGHTGREEN_EX: (winterm.fore, WinColor.GREEN, True), + AnsiFore.LIGHTYELLOW_EX: (winterm.fore, WinColor.YELLOW, True), + AnsiFore.LIGHTBLUE_EX: (winterm.fore, WinColor.BLUE, True), + AnsiFore.LIGHTMAGENTA_EX: (winterm.fore, WinColor.MAGENTA, True), + AnsiFore.LIGHTCYAN_EX: (winterm.fore, WinColor.CYAN, True), + AnsiFore.LIGHTWHITE_EX: (winterm.fore, WinColor.GREY, True), + AnsiBack.BLACK: (winterm.back, WinColor.BLACK), + AnsiBack.RED: (winterm.back, WinColor.RED), + AnsiBack.GREEN: (winterm.back, WinColor.GREEN), + AnsiBack.YELLOW: (winterm.back, WinColor.YELLOW), + AnsiBack.BLUE: (winterm.back, WinColor.BLUE), + AnsiBack.MAGENTA: (winterm.back, WinColor.MAGENTA), + AnsiBack.CYAN: (winterm.back, WinColor.CYAN), + AnsiBack.WHITE: (winterm.back, WinColor.GREY), + AnsiBack.RESET: (winterm.back, ), + AnsiBack.LIGHTBLACK_EX: (winterm.back, WinColor.BLACK, True), + AnsiBack.LIGHTRED_EX: (winterm.back, WinColor.RED, True), + AnsiBack.LIGHTGREEN_EX: (winterm.back, WinColor.GREEN, True), + AnsiBack.LIGHTYELLOW_EX: (winterm.back, WinColor.YELLOW, True), + AnsiBack.LIGHTBLUE_EX: (winterm.back, WinColor.BLUE, True), + AnsiBack.LIGHTMAGENTA_EX: (winterm.back, WinColor.MAGENTA, True), + AnsiBack.LIGHTCYAN_EX: (winterm.back, WinColor.CYAN, True), + AnsiBack.LIGHTWHITE_EX: (winterm.back, WinColor.GREY, True), + } + return dict() + + def write(self, text): + if self.strip or self.convert: + self.write_and_convert(text) + else: + self.wrapped.write(text) + self.wrapped.flush() + if self.autoreset: + self.reset_all() + + + def reset_all(self): + if self.convert: + self.call_win32('m', (0,)) + elif not self.strip and not self.stream.closed: + self.wrapped.write(Style.RESET_ALL) + + + def write_and_convert(self, text): + ''' + Write the given text to our wrapped stream, stripping any ANSI + sequences from the text, and optionally converting them into win32 + calls. + ''' + cursor = 0 + text = self.convert_osc(text) + for match in self.ANSI_CSI_RE.finditer(text): + start, end = match.span() + self.write_plain_text(text, cursor, start) + self.convert_ansi(*match.groups()) + cursor = end + self.write_plain_text(text, cursor, len(text)) + + + def write_plain_text(self, text, start, end): + if start < end: + self.wrapped.write(text[start:end]) + self.wrapped.flush() + + + def convert_ansi(self, paramstring, command): + if self.convert: + params = self.extract_params(command, paramstring) + self.call_win32(command, params) + + + def extract_params(self, command, paramstring): + if command in 'Hf': + params = tuple(int(p) if len(p) != 0 else 1 for p in paramstring.split(';')) + while len(params) < 2: + # defaults: + params = params + (1,) + else: + params = tuple(int(p) for p in paramstring.split(';') if len(p) != 0) + if len(params) == 0: + # defaults: + if command in 'JKm': + params = (0,) + elif command in 'ABCD': + params = (1,) + + return params + + + def call_win32(self, command, params): + if command == 'm': + for param in params: + if param in self.win32_calls: + func_args = self.win32_calls[param] + func = func_args[0] + args = func_args[1:] + kwargs = dict(on_stderr=self.on_stderr) + func(*args, **kwargs) + elif command in 'J': + winterm.erase_screen(params[0], on_stderr=self.on_stderr) + elif command in 'K': + winterm.erase_line(params[0], on_stderr=self.on_stderr) + elif command in 'Hf': # cursor position - absolute + winterm.set_cursor_position(params, on_stderr=self.on_stderr) + elif command in 'ABCD': # cursor position - relative + n = params[0] + # A - up, B - down, C - forward, D - back + x, y = {'A': (0, -n), 'B': (0, n), 'C': (n, 0), 'D': (-n, 0)}[command] + winterm.cursor_adjust(x, y, on_stderr=self.on_stderr) + + + def convert_osc(self, text): + for match in self.ANSI_OSC_RE.finditer(text): + start, end = match.span() + text = text[:start] + text[end:] + paramstring, command = match.groups() + if command == BEL: + if paramstring.count(";") == 1: + params = paramstring.split(";") + # 0 - change title and icon (we will only change title) + # 1 - change icon (we don't support this) + # 2 - change title + if params[0] in '02': + winterm.set_title(params[1]) + return text diff --git a/venv/Lib/site-packages/pip/_vendor/colorama/initialise.py b/venv/Lib/site-packages/pip/_vendor/colorama/initialise.py new file mode 100644 index 0000000..430d066 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/colorama/initialise.py @@ -0,0 +1,80 @@ +# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. +import atexit +import contextlib +import sys + +from .ansitowin32 import AnsiToWin32 + + +orig_stdout = None +orig_stderr = None + +wrapped_stdout = None +wrapped_stderr = None + +atexit_done = False + + +def reset_all(): + if AnsiToWin32 is not None: # Issue #74: objects might become None at exit + AnsiToWin32(orig_stdout).reset_all() + + +def init(autoreset=False, convert=None, strip=None, wrap=True): + + if not wrap and any([autoreset, convert, strip]): + raise ValueError('wrap=False conflicts with any other arg=True') + + global wrapped_stdout, wrapped_stderr + global orig_stdout, orig_stderr + + orig_stdout = sys.stdout + orig_stderr = sys.stderr + + if sys.stdout is None: + wrapped_stdout = None + else: + sys.stdout = wrapped_stdout = \ + wrap_stream(orig_stdout, convert, strip, autoreset, wrap) + if sys.stderr is None: + wrapped_stderr = None + else: + sys.stderr = wrapped_stderr = \ + wrap_stream(orig_stderr, convert, strip, autoreset, wrap) + + global atexit_done + if not atexit_done: + atexit.register(reset_all) + atexit_done = True + + +def deinit(): + if orig_stdout is not None: + sys.stdout = orig_stdout + if orig_stderr is not None: + sys.stderr = orig_stderr + + +@contextlib.contextmanager +def colorama_text(*args, **kwargs): + init(*args, **kwargs) + try: + yield + finally: + deinit() + + +def reinit(): + if wrapped_stdout is not None: + sys.stdout = wrapped_stdout + if wrapped_stderr is not None: + sys.stderr = wrapped_stderr + + +def wrap_stream(stream, convert, strip, autoreset, wrap): + if wrap: + wrapper = AnsiToWin32(stream, + convert=convert, strip=strip, autoreset=autoreset) + if wrapper.should_wrap(): + stream = wrapper.stream + return stream diff --git a/venv/Lib/site-packages/pip/_vendor/colorama/win32.py b/venv/Lib/site-packages/pip/_vendor/colorama/win32.py new file mode 100644 index 0000000..c2d8360 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/colorama/win32.py @@ -0,0 +1,152 @@ +# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. + +# from winbase.h +STDOUT = -11 +STDERR = -12 + +try: + import ctypes + from ctypes import LibraryLoader + windll = LibraryLoader(ctypes.WinDLL) + from ctypes import wintypes +except (AttributeError, ImportError): + windll = None + SetConsoleTextAttribute = lambda *_: None + winapi_test = lambda *_: None +else: + from ctypes import byref, Structure, c_char, POINTER + + COORD = wintypes._COORD + + class CONSOLE_SCREEN_BUFFER_INFO(Structure): + """struct in wincon.h.""" + _fields_ = [ + ("dwSize", COORD), + ("dwCursorPosition", COORD), + ("wAttributes", wintypes.WORD), + ("srWindow", wintypes.SMALL_RECT), + ("dwMaximumWindowSize", COORD), + ] + def __str__(self): + return '(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)' % ( + self.dwSize.Y, self.dwSize.X + , self.dwCursorPosition.Y, self.dwCursorPosition.X + , self.wAttributes + , self.srWindow.Top, self.srWindow.Left, self.srWindow.Bottom, self.srWindow.Right + , self.dwMaximumWindowSize.Y, self.dwMaximumWindowSize.X + ) + + _GetStdHandle = windll.kernel32.GetStdHandle + _GetStdHandle.argtypes = [ + wintypes.DWORD, + ] + _GetStdHandle.restype = wintypes.HANDLE + + _GetConsoleScreenBufferInfo = windll.kernel32.GetConsoleScreenBufferInfo + _GetConsoleScreenBufferInfo.argtypes = [ + wintypes.HANDLE, + POINTER(CONSOLE_SCREEN_BUFFER_INFO), + ] + _GetConsoleScreenBufferInfo.restype = wintypes.BOOL + + _SetConsoleTextAttribute = windll.kernel32.SetConsoleTextAttribute + _SetConsoleTextAttribute.argtypes = [ + wintypes.HANDLE, + wintypes.WORD, + ] + _SetConsoleTextAttribute.restype = wintypes.BOOL + + _SetConsoleCursorPosition = windll.kernel32.SetConsoleCursorPosition + _SetConsoleCursorPosition.argtypes = [ + wintypes.HANDLE, + COORD, + ] + _SetConsoleCursorPosition.restype = wintypes.BOOL + + _FillConsoleOutputCharacterA = windll.kernel32.FillConsoleOutputCharacterA + _FillConsoleOutputCharacterA.argtypes = [ + wintypes.HANDLE, + c_char, + wintypes.DWORD, + COORD, + POINTER(wintypes.DWORD), + ] + _FillConsoleOutputCharacterA.restype = wintypes.BOOL + + _FillConsoleOutputAttribute = windll.kernel32.FillConsoleOutputAttribute + _FillConsoleOutputAttribute.argtypes = [ + wintypes.HANDLE, + wintypes.WORD, + wintypes.DWORD, + COORD, + POINTER(wintypes.DWORD), + ] + _FillConsoleOutputAttribute.restype = wintypes.BOOL + + _SetConsoleTitleW = windll.kernel32.SetConsoleTitleW + _SetConsoleTitleW.argtypes = [ + wintypes.LPCWSTR + ] + _SetConsoleTitleW.restype = wintypes.BOOL + + def _winapi_test(handle): + csbi = CONSOLE_SCREEN_BUFFER_INFO() + success = _GetConsoleScreenBufferInfo( + handle, byref(csbi)) + return bool(success) + + def winapi_test(): + return any(_winapi_test(h) for h in + (_GetStdHandle(STDOUT), _GetStdHandle(STDERR))) + + def GetConsoleScreenBufferInfo(stream_id=STDOUT): + handle = _GetStdHandle(stream_id) + csbi = CONSOLE_SCREEN_BUFFER_INFO() + success = _GetConsoleScreenBufferInfo( + handle, byref(csbi)) + return csbi + + def SetConsoleTextAttribute(stream_id, attrs): + handle = _GetStdHandle(stream_id) + return _SetConsoleTextAttribute(handle, attrs) + + def SetConsoleCursorPosition(stream_id, position, adjust=True): + position = COORD(*position) + # If the position is out of range, do nothing. + if position.Y <= 0 or position.X <= 0: + return + # Adjust for Windows' SetConsoleCursorPosition: + # 1. being 0-based, while ANSI is 1-based. + # 2. expecting (x,y), while ANSI uses (y,x). + adjusted_position = COORD(position.Y - 1, position.X - 1) + if adjust: + # Adjust for viewport's scroll position + sr = GetConsoleScreenBufferInfo(STDOUT).srWindow + adjusted_position.Y += sr.Top + adjusted_position.X += sr.Left + # Resume normal processing + handle = _GetStdHandle(stream_id) + return _SetConsoleCursorPosition(handle, adjusted_position) + + def FillConsoleOutputCharacter(stream_id, char, length, start): + handle = _GetStdHandle(stream_id) + char = c_char(char.encode()) + length = wintypes.DWORD(length) + num_written = wintypes.DWORD(0) + # Note that this is hard-coded for ANSI (vs wide) bytes. + success = _FillConsoleOutputCharacterA( + handle, char, length, start, byref(num_written)) + return num_written.value + + def FillConsoleOutputAttribute(stream_id, attr, length, start): + ''' FillConsoleOutputAttribute( hConsole, csbi.wAttributes, dwConSize, coordScreen, &cCharsWritten )''' + handle = _GetStdHandle(stream_id) + attribute = wintypes.WORD(attr) + length = wintypes.DWORD(length) + num_written = wintypes.DWORD(0) + # Note that this is hard-coded for ANSI (vs wide) bytes. + return _FillConsoleOutputAttribute( + handle, attribute, length, start, byref(num_written)) + + def SetConsoleTitle(title): + return _SetConsoleTitleW(title) diff --git a/venv/Lib/site-packages/pip/_vendor/colorama/winterm.py b/venv/Lib/site-packages/pip/_vendor/colorama/winterm.py new file mode 100644 index 0000000..0fdb4ec --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/colorama/winterm.py @@ -0,0 +1,169 @@ +# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. +from . import win32 + + +# from wincon.h +class WinColor(object): + BLACK = 0 + BLUE = 1 + GREEN = 2 + CYAN = 3 + RED = 4 + MAGENTA = 5 + YELLOW = 6 + GREY = 7 + +# from wincon.h +class WinStyle(object): + NORMAL = 0x00 # dim text, dim background + BRIGHT = 0x08 # bright text, dim background + BRIGHT_BACKGROUND = 0x80 # dim text, bright background + +class WinTerm(object): + + def __init__(self): + self._default = win32.GetConsoleScreenBufferInfo(win32.STDOUT).wAttributes + self.set_attrs(self._default) + self._default_fore = self._fore + self._default_back = self._back + self._default_style = self._style + # In order to emulate LIGHT_EX in windows, we borrow the BRIGHT style. + # So that LIGHT_EX colors and BRIGHT style do not clobber each other, + # we track them separately, since LIGHT_EX is overwritten by Fore/Back + # and BRIGHT is overwritten by Style codes. + self._light = 0 + + def get_attrs(self): + return self._fore + self._back * 16 + (self._style | self._light) + + def set_attrs(self, value): + self._fore = value & 7 + self._back = (value >> 4) & 7 + self._style = value & (WinStyle.BRIGHT | WinStyle.BRIGHT_BACKGROUND) + + def reset_all(self, on_stderr=None): + self.set_attrs(self._default) + self.set_console(attrs=self._default) + self._light = 0 + + def fore(self, fore=None, light=False, on_stderr=False): + if fore is None: + fore = self._default_fore + self._fore = fore + # Emulate LIGHT_EX with BRIGHT Style + if light: + self._light |= WinStyle.BRIGHT + else: + self._light &= ~WinStyle.BRIGHT + self.set_console(on_stderr=on_stderr) + + def back(self, back=None, light=False, on_stderr=False): + if back is None: + back = self._default_back + self._back = back + # Emulate LIGHT_EX with BRIGHT_BACKGROUND Style + if light: + self._light |= WinStyle.BRIGHT_BACKGROUND + else: + self._light &= ~WinStyle.BRIGHT_BACKGROUND + self.set_console(on_stderr=on_stderr) + + def style(self, style=None, on_stderr=False): + if style is None: + style = self._default_style + self._style = style + self.set_console(on_stderr=on_stderr) + + def set_console(self, attrs=None, on_stderr=False): + if attrs is None: + attrs = self.get_attrs() + handle = win32.STDOUT + if on_stderr: + handle = win32.STDERR + win32.SetConsoleTextAttribute(handle, attrs) + + def get_position(self, handle): + position = win32.GetConsoleScreenBufferInfo(handle).dwCursorPosition + # Because Windows coordinates are 0-based, + # and win32.SetConsoleCursorPosition expects 1-based. + position.X += 1 + position.Y += 1 + return position + + def set_cursor_position(self, position=None, on_stderr=False): + if position is None: + # I'm not currently tracking the position, so there is no default. + # position = self.get_position() + return + handle = win32.STDOUT + if on_stderr: + handle = win32.STDERR + win32.SetConsoleCursorPosition(handle, position) + + def cursor_adjust(self, x, y, on_stderr=False): + handle = win32.STDOUT + if on_stderr: + handle = win32.STDERR + position = self.get_position(handle) + adjusted_position = (position.Y + y, position.X + x) + win32.SetConsoleCursorPosition(handle, adjusted_position, adjust=False) + + def erase_screen(self, mode=0, on_stderr=False): + # 0 should clear from the cursor to the end of the screen. + # 1 should clear from the cursor to the beginning of the screen. + # 2 should clear the entire screen, and move cursor to (1,1) + handle = win32.STDOUT + if on_stderr: + handle = win32.STDERR + csbi = win32.GetConsoleScreenBufferInfo(handle) + # get the number of character cells in the current buffer + cells_in_screen = csbi.dwSize.X * csbi.dwSize.Y + # get number of character cells before current cursor position + cells_before_cursor = csbi.dwSize.X * csbi.dwCursorPosition.Y + csbi.dwCursorPosition.X + if mode == 0: + from_coord = csbi.dwCursorPosition + cells_to_erase = cells_in_screen - cells_before_cursor + elif mode == 1: + from_coord = win32.COORD(0, 0) + cells_to_erase = cells_before_cursor + elif mode == 2: + from_coord = win32.COORD(0, 0) + cells_to_erase = cells_in_screen + else: + # invalid mode + return + # fill the entire screen with blanks + win32.FillConsoleOutputCharacter(handle, ' ', cells_to_erase, from_coord) + # now set the buffer's attributes accordingly + win32.FillConsoleOutputAttribute(handle, self.get_attrs(), cells_to_erase, from_coord) + if mode == 2: + # put the cursor where needed + win32.SetConsoleCursorPosition(handle, (1, 1)) + + def erase_line(self, mode=0, on_stderr=False): + # 0 should clear from the cursor to the end of the line. + # 1 should clear from the cursor to the beginning of the line. + # 2 should clear the entire line. + handle = win32.STDOUT + if on_stderr: + handle = win32.STDERR + csbi = win32.GetConsoleScreenBufferInfo(handle) + if mode == 0: + from_coord = csbi.dwCursorPosition + cells_to_erase = csbi.dwSize.X - csbi.dwCursorPosition.X + elif mode == 1: + from_coord = win32.COORD(0, csbi.dwCursorPosition.Y) + cells_to_erase = csbi.dwCursorPosition.X + elif mode == 2: + from_coord = win32.COORD(0, csbi.dwCursorPosition.Y) + cells_to_erase = csbi.dwSize.X + else: + # invalid mode + return + # fill the entire screen with blanks + win32.FillConsoleOutputCharacter(handle, ' ', cells_to_erase, from_coord) + # now set the buffer's attributes accordingly + win32.FillConsoleOutputAttribute(handle, self.get_attrs(), cells_to_erase, from_coord) + + def set_title(self, title): + win32.SetConsoleTitle(title) diff --git a/venv/Lib/site-packages/pip/_vendor/distlib/__init__.py b/venv/Lib/site-packages/pip/_vendor/distlib/__init__.py new file mode 100644 index 0000000..1154948 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/distlib/__init__.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2012-2019 Vinay Sajip. +# Licensed to the Python Software Foundation under a contributor agreement. +# See LICENSE.txt and CONTRIBUTORS.txt. +# +import logging + +__version__ = '0.3.3' + +class DistlibException(Exception): + pass + +try: + from logging import NullHandler +except ImportError: # pragma: no cover + class NullHandler(logging.Handler): + def handle(self, record): pass + def emit(self, record): pass + def createLock(self): self.lock = None + +logger = logging.getLogger(__name__) +logger.addHandler(NullHandler()) diff --git a/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/__init__.cpython-39.pyc b/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1c3164930f61796391e522ccbbd7ed614aa9b328 GIT binary patch literal 1049 zcmah|OKTKC5U!s0?k2iM5pQ0Cu!k&xKoAj$BteC+2vNjgq?t^&n@M_S#-3Rj z1u+OGW-mav!aD)sN$1#&-B}+|U%|wSJqGWfSoT2rN3R*shtYuuF*=lR5MaFb9tvj_ zB%FpaI%9E1c22v}JBBmHkYyJJ(NAQA(ac{Rt_{~Ra^{7hvw^2xKqVn&0%FHrbWDFM zuN#%`ZGX*V)#PO{8n`CnyhtaKbJOK~Qi`b}dx7&$(^R#{Ip_ehS@rwF=9A=YEp?rw zMUmFY^QziPn>5)evs5K-GHrZ<`@^)fAllKQWnDRhJGETg*aSvV&UyX|wtp72G0 zzAr)=qNWGT=;Ec2O~c#7Q+ucc?7}%4*{;tWnf5wyA0RZjyL%k~en=xJ4BGc?yCuD*sZ*rj~3wluf`l;I=7CgERG1 znH>(8rg7io>SkJ|jl@SiyhpHQyg$!)9WWXM+NB_xn)XR8lDbXm4ymi{X)PL=eE3QrKYAdo`&_-E3=JY7<^8i0O=Fvx7OL qwuPC15=w2lsSp=2|EkGEPuoAhGpexeQ(=zh^j(Mb*#djuciA86#M|ot literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/compat.cpython-39.pyc b/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/compat.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..60c51527e82a5b4e8062c00c08c79722ee6e5d4a GIT binary patch literal 31814 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 PBaOe?i^mIl3w!=A{V2Px literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/index.cpython-39.pyc b/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/index.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8106a8613d01c597d8a853db4c555e48c5b10ff2 GIT binary patch literal 17282 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 JU^v;<{{SoXTFC$a literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/locators.cpython-39.pyc b/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/locators.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c8b36ebb1db46faaeeae37b018282cd297076dcc GIT binary patch literal 38246 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%0Dxm~#9gftn9w~fe?Eps!PxwWCCBgm0 z=sGMV7|F!-Kaf@i!d7zIhhQEb)-rPI?aqPKAspi=V{3HlU}v;*5Jq!oC~lh=Lwwi{ zJ60mD0#6@_bHg3Pl;G;6@a>r^L|5fmZ1J%4c?6?!eQT^UmYf6JdmGP4Bc5Z7qX}wx zh;I#e=$(-<%t%VTBr`G=%?Li~_7X<0wf^%ovtaA8qxT7mhdPJwtVcQDm=kP(RXv9J zI)?jyPWps7*L}kMx@1^GQ|Ayi%93rxYG1+nijjq|dOHL?Mo*DqC7CYz$%Wn>{MOEH z+LXYEySV-^gjSO$Akk#Qkoe=yM0hj#ONL0kY*6d@1a&M4bn#nA-{>5}?K-eaKc$Gs zj>KYm(4d&c8GJR=1^NyrZ!s8T=h)h3lVHE_+&sF2wND?`suaRm-PyWb$Z?xbFCr*)@r1P2^sWFN<{?>P5 zLa#G?fkAH}t&7B}OF-(8zO8HY*1>jB<+vLWWlyv_zhmaR)~!T5t4xj1O%RpvOZLdc z?ap$qy4jl{wAnYid)G;KF|5(>)A3i@z<1WV_X~4~VpK~&EV!<9CY>Q!Pc;+LXr4pB+osnE4Te=^oiGPNOFv!mBLMmHMt#CS$* zk$Bd+bg_ucjG8lw`*8E-NoAsXOFCB`Wdy&^6K-d*u6aZ7NNt+h6L z7x}FgHsvDFv%%0N*^hW*SezN6^(CI>JA30;<0SAL0Q!1LhY z_-c4@$JS=s^SnYHPAwwA*6|zMJx@l|tqchAj86wObVuhw9tsSuKlK*xCyOY|Vx=r$ zEP$8jLsG&i207Wrz^xqIbCFDi9~%5QG*jtMU~QRFy}j?h<|Ar&7$&c6w<`lZqpDrc zZt^v9@JN-o(rqJ?^XK@c2jstoQFsyuvCF!dom6hecY2>mqFMM35zaIR4D@tcGA zry-BLEnVz&Ehv!F+&@^8`e}O0R(`C!>_*@p(Z~XzvKW0y0<-jgoSDSSGlTbM9 zCx|a2KroQdYu<61-8n0j*;0<7NVRZFNGj5`yErwWinY2Nk|2le z|KQ=It(m{V;@@KOyG$4Zr9(vMC@6kQVy0Brc=}7c%6UvEHscA#KB3LFz0q)<<7m1! zkPxH^u=-zb*aHv*;GNHm0%#`*x~U?7llp83YlGzn%RgfLi1A|iO!;zo7J0w?Liy41 WvGV6q5Zp3YD4A61&vLn3`u_zwn#{@o literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/manifest.cpython-39.pyc b/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/manifest.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..583993205977921ebf99ba9e18498c8bcec6cbe3 GIT binary patch literal 10185 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/metadata.cpython-39.pyc b/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/metadata.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..97c86fef46379e52feb1f18e3a634ee54f030fcc GIT binary patch literal 26580 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 Ee>b&@8vpQ^!$N#kOQQPMvjO$#%`kp=UX>yF+nF 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 A)&Kwi literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/scripts.cpython-39.pyc b/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/scripts.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..063d232173ef317cdffd3b39fb2183c5887fbb32 GIT binary patch literal 11235 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 V@P{v4a=MEcI2J^=oJ`R&{tt&Jb(H`B literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/util.cpython-39.pyc b/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/util.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4b812dfc3c5667e25502fee4550d94c927331afe GIT binary patch literal 52598 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μ(rTC{hli`O#oy#H~|A8qDz^U*k1iGvb+ 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/version.cpython-39.pyc b/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/version.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2d25510ccae739ccbe12a2c730909bae24804c38 GIT binary patch literal 20348 zcmch9d2n1udf&U|&0uhn1P@RY`9zT-h9qXeV|8#TiWCotYY9t}lvV~o4hPc@;DCdf zVZQ++&JI+&rtHK?*_Jo)CUz+aAjfvNc51g=wN>#x85`a8N&930FV`26C&7iRzXhGF~(6P=#{B+lX+ zOk0K_jA=ud!m60lruwy}Eny3%VlO(=j%gsCs-za(Y1cI74dH%jPN#iyHRJcKnbX-f z43QR@j|`FV`ybfT14#FYEYewj5a}VL`^5m#11df2TdN~t5G}WeAu;@sF}>B_I=v0G zM#L7>+TstP)u`AiwxMi0@<+vX|96uFye7vo&6rsb>>pj zyHxw5nE9BP5P8gQxA>Bn#P2hz{+v>pB2aP?*zUlg@u1#{v5b5*c z0@4>$>lcu|C@vv=Nv+i(|B%1U-{C*=z(#DJ|D1S3y!nx#QV0AO{M`?1arqN_dfXou zUmY_L{?uthyd~boSUF)`GjdbS53`pS>lJ^|uQrN}a;@ss=DeaeSMfh6&sKbI*_Q!w z%hh==DBVFduP$rLWuY>b>h+pzcyl%BUAcH=;^fK6quIc3EY%yeS|yk$)fVgMlid`n z!VCPxVzp5&b@Z9fJ|fjmJu(sI%y1xRNc3E2+^_q=Lo?h`FUr6#NdMkaSt=NFnQ+Tg zO)eHI<)$y*)zEcjy~&zwIs^G*P?%oMBD zVlZ>AUcXRm6ldP5m5P;_>;7VWre3a3ELH2p(p_Inynn~{D-$oiyig8GL6c=Og=N1g zYH~)DgGQx1I}?#WzJ6c9KgRhv2r{N)s+@Ibuu*!J)jmMbMuV_GcQ!c}ejSk#E`C#* zJ59TqD@~_0H=53fK{15#J~1pt@S7D|#8&+Fi)~^QzXM{s*n!_cu~Y2A?~p$%#>8$= zzd1c3o&jy|3DeQ)mcT@l4}s(NJiftM1TAybSTh`>WfaU6vt_JWEpyFOX?w+LI4!G@ zdSC@dziRxf*>GFd12EycPH>uOVPGI@N-FwIhbhu;Jxmug9fv7JzoA>eZzBk^<)B;* z8pUeK4^!AC6+g5qel=%@PT*JOLNib;8bNzO%pr3G-{wd( z$9!C+YqFd;ziP6iz6MT`2WA3zb1#4>2EJF0nSfWWdPOf-nk`j|0r%jxsahjp5x!8H z;Gre=pfmX_gM|1Lta2yv4&oaqq?^sb7(j)Kb_fVx8{m%A7cPrVSi zg@S*tP&kUB2#l=R97@1Yg`1DfHIBy~0C7rA=bMAgBkbm6*Tll{Z)xbGLZbBqOxyI--{X69fp ze&}FuDEH6~`v5svRG}b;&_I$HB`K>@&7+M8+9 zp>QOF^A`$lbc{6I-ny!6-9QPtH{#Fxu57@cWA5w+dFf%O4W~U=4hnVYOJ8;H)dV7| zxjlxctHxAri$>%yd!zs(dDIjuQN+SiO>!^o#Wx@kWz3A5u`>?-F|?D=woFyCgi2kXKBUg#8~i$gwv<6(OW2T+ z9Tlcj=&CTS!i)<0RG3v^|0fy9BLiX(azrZ9dR(pVK$FU7T?cYSpVoCCi|i0PQMX_0 z5@Yxs5WB@Q_#G5`#IyJv5_`oy{0<9jo17P>BcXDtL>iAjj3;Z)Go2^h-I&Z2#z5xg za%h%9v)+M0A}`FGt`rw%Me)par2ad;Msp+@CLb3)#c)o{y413eOY{sRxryIl{_6-f z?~w$fCScWv)=xxk*7Lhxpy#K9`RkwGbAogn&FY}kbKeZs_x_*v_%om1<2t-P-Rxmh z_`DTMW^X^$>}TR0bD78H>Br`o$JXgrA6sYeef8DH_Nxf25Al8O)pbW%7nN)2E*_Gn zzueED`w)>ScY*`B_=mhvKq*mQE^i)XC8!I;QGxCQFFBmt)jJ4vR7jqR1WzCeI zwjALsoAM*{lxjIqPtX&D`*YS9OfiE&BnE!oq;kH~OZUd!u6^sQabz+J1*cBzg-u2<+#H4RhjQik?j|9;rt(PNl_Vi~+&ZrlmoV!e)p+|BkBg>&h) zMiH8FI#sGb{S2*IecD>ChAvLBx$+0SM8X3~;2ZF0GR&-*fl8ExUOIr-0DfJIX=>NX{_o8|M_jR29HgDq zRLcS-rBFYm>R*7qi1-6*CDlp=w;|M6sFz;IP^4LL8+|QTQDmxRw(OSkzz%l9oCj`n zZ@0j%%sI^;WxeQgo_dN`p7Wr_L`E2_TeLLZqB45~s;~p)`E1hu6gEzAF>Y|myN+(+ z){UC(z$?yU?Slrop@|~WRrBpWs9VLYPI=dqwZ?<_=aeG5Q@10@;`Rn@n`59al3b!{ z#$*>e zIjl48-YdrH3933=;-puW+PGJ{!Na= z)iAooQR=zL?C8Td_mEmJ%GWXJsb83`cE<80W_cXt9kV>aWX~x~q5dJh@z@=V^NVY7 zF0?q9YUGzW;6|fTi}>A*NBs$vHTm*pV^B%?UdI^2?bTCiT5hCQ8&YgZNtHYtv~pBn z>?;h43>4jvG9(wRMx29ySJ8K8=nzJp3AA9@tHglxx=~f@nUPXRcgsnj>S0^=f~@{pwXEY{&G8cWc)^P zqIqs&dPdwlg4!La+-vCIKo^(m2gHe#^>;vY+*)hKiqU{<)iQ7ff-4038#XyYECa1N zr~zB5R?k|NaK?;PS3nB70G{%|T(KKz$~nTh>&QyW7B1x_a7@M{`Dw+zcL^=iV@A*v z=@q9s+Q{g1Tm${UVkzK)=|uTb~v1$dDPkQ|}J(q$2x$tN|{i5QysM-WUuQzzpi9!`%) ziH|6>J)%kAQI^2~gFyta&QGbqVYxDk@(#1i&}=d&AV|%XtHnyLUx~8e7WlCUz`GZ( zUc3CYslwHZQf+Z|7rOJZwp0(4&H-m{oCxjydFHRox*~W57ZlI1OZF)3N0@(J!ad_2IIg#W$b`u-?)# z?f9vA*jqjYAxyh|T6=a72kC;qGLj2aybLyR&Vw)qcVe*;lUXF7zEP`*Q;C>)EPp(f zdcEg8I{!eLa8P=XQ}?4VKe@lNZho>eRXo<2%AY76?@rJ5l$Uza`IAZg>tDO@wNu_) zxl+*rac!xg<>}XpozNz*dVqEjj+(`#MX&LG&BLP4Li$Sj1L(!L^7CF~ne!_CvS0BQ zmmqfEDK7h7F)4u`uUxEjHqW1!Rmm{T1w*J(Js zK=6?PE!7711(%DtFSJYWM=V!r>I-jsIg7!iV9+B+%pq?p2taT2!|Ob_d8O5Fw&&$M zn&;BtaG{#Ge#s+bgF~qe%3Y?l$z{Y)Gr}%))}_GDrP}JHyv@2FFi@>}K;4OgEI#WND7CpJkVoc!MPZW3`Lb`&v{coOfcrHwI7}_Qfi>VhLk*?NQH6l!cKwnjSR24LaA5!* zUwD6M_fW?L+`Z-pp?NNjqKj($nKqq?B0FR4WDde^X`vq-UE@% zdoZ$j4~adP^s|!ZFTAN5{fZ}TqGm-oizBrt?TgWvoJ+(gJVGn$ryQv3W!Z8XYRUqqhg;CP@yZ zj2t;vbERo!DElhGn(hbHlTD`w?Y>$Bp2X1T*Eh@jyg}KHV})Fzhd2^iJMb~fAJUi6Z5WeFCwz1X(c4JouPQ4 zPnR#X*-J9-mRV3zHdqhtOd5U`4;i-twW%VP82`qF{ux1gs^iZ);vwK z8=>u2(L@jcG9=j5_HVj3lS8O${4U&0qKhZs4i19qK#aQq2;vF$^SE?Ot3Sc*)|R%Q-#Df~#*7Vh~(?EejGKgq$@9 zMfXNv=FAJ2I~#QVQ2@fu4lW@FDVPht+j8hSrmJT)O$YG`RBn;N#z}GGz*PtX9=4c^ zjrU81RKj)&7zmIHe*&_7WQgC9ry(6s?|JTIq2Ua13u%~WCT3cMVT1OEZg|P41 zs73D$O6fqxJ^3G?br=4*vgA36-%t!`4r#*!y^~)D9XfEP-1kfv)=lGQjH)$Bj)aRV zE3g`M>`@ckh)No{QJ!2#KqUhw!qpa)0=MZ%fmd{-US&J_K^>{lu90w8zoTqtR|2Wwup-k0a;RF@g6Vd{k+$f58l$HkIPgy>lw^=9#OK&V0aaA+3x>gD7S zQ8aqsm6oK0@xF4OPYYm+^-%Z9{VSLA-Wv+LMNcd()-kf`sBwqrk3knp#5k&-N2BAD zldl~0P9A^xC4vbIEozs+gm?VJvE$zOmrvwhIdL!-U1eE^Xmu#SgzuH^6sz;T8qL!u z1(&+G)TqHsfcHt!K?6LgIuqWBlP{h0#$P^`pFEj#kB2jy4WU!0Z8!23eM~}VDmklf z-2~n@fU_0vT-7Vfbqf^J6@3F|B_2@8YT%t~Q%;PH80}c^san-P%G*H6(I@;RR_vNCVx{Woe9Wc zaam>}GKa*anS4)1dIIK8kZx2#oetVOYDvjas2=33$EFu|;pRKXlL0Gn?52Z(4@@(h zY&vk9A&zjexdXoI+0sqAyKl@)%qXe#NbW$>nK=eIba#|TcejqdCY8G!HBu04DXQMc ze|YmX-AisJ|C; z$QHtxykuXh73$=fb-Xz=p?&k(^M0VY^#+{w6F1q6jr@v&3bD!N5XRD_IiwFXhsPCO zS{k3Z0~#r#97DDyS`(earSo(zV!W{krWQPtt=VR09aRKmQpjE|`|r0VqU!>HwuC7i zKhsRtBk-gCj^U!!w}=)Rwxl}T(>!8}B_DndU;Zw${{n)Xqy3*2E^awBS)P}_$0DVm zBw9-NOmgJL%*Ge7kn}?yx?BQdi^U@q2dQgi>;ZSk9x{hgLk@oJtT~WE9I@!1JJdIn zMjV!Y9@JS={sDSuZdJD%ZXRi2)mp&m#Lb+d;HIlkI`P;%i8=5GIH3z@`!>?XdZs-9#;5FVzQ@L?Cf%^ww{Ew^Jb4y{y=2wL7n<~=2j_9vN4h$V;=B>+nFHz?A1qCK3l;T7 zwEMb2(pdfj_WchT+(FPxYv3os%w+Tdm6OjZNLD#6h+$jhsAIgTLYcfgcCLP?3mogc3AS$qQzLG13)NtoFMEN9!g-r8!n=sKEAw#mzABh*XF z1t_gI$LXiW8%r1!WfoM1=Ns52h=KYHnH9KQ4RSwuFRSQ^9))CGt^?J(2;Ue3B1AJE zTbpigGvhBZ=*GQzk#d{xkD$=Nm540FcK0(2F&Fl=?%8y?Kd0aopsPg=GhlQ5KIX~3 zNFsNJyxbMNo2=sN*A7=^4*0rRx>S3T(GcC8-7OLILBiYWl+Fl z6yD}ZOS%EIVTew$=Fly&@V3o^%MgDE4q3%{e1qEvz_Dlo9MG=L1uzYm0KsJ_CGsoSFMTfDe9dcCd0D;9%C;aSM9xGhnF-(RbebR30lr3OQT z4AbuyCEu{?%Q&vocXw#!+t>xCRmKfmZwj#_d*#HZU)I4URd;7_Jy_p6$E(qOnuL1X zPi)IVdrUuMuIY8BhYJTCrSf=8n| zfP+CjV`VLs-<(pU0HH)3>e0{m1h4u{PP~#_`$HUNG+ZNu>;f5Qv%>BhfjF((UUUww zPn@;btAa}c*}}DpZ{uQBe5nc?W+M!LAB}&3Q@|I@MKayROgP7cnN*R8&s?oP^EeCk zfTe)>;jsr!Oz6zft8;acFcn+NaCP5Nk1=rhUZ2AcNZU3q?}^L<3(qmqxL_AO#ZVXK zcqzYcs*8;h6z*Gf-jcVq4E5dwrolOQO{)ix#!U?lx{C7^Tgk@T5bZU!X|z)}2(;r^ zTg^8#m?ua2ehi^Jrn_ldqwP-a#xI6gGpm4K`%i(~zmJL#@!!Xf{6ii089&RQO+1Qj z=)e0_AY7Z%zf6OQ`dba%N8@7gu3u2^);BU?VJv03*^R!UGjQ51LMf~^^f9=1{lHd(GRmAJ3s595GB(*gxouuY=?uOULdWHJiSC1OF+R&NZ#v^v~z z823e{5*TbFANv*bApb3cf5)IbamAbVA@BP!#tlelkkNK@0k`qrz97YuP8GpUBGSb3 zEy^^o8bYLm2x`GzxC8b=>;B=$S_ow*vKE3NKeXY<#Aa5Iy@d|cj(!+Pmug4fW^OmU z;Rr}cU8Rmy*&h&ieHDaiDIXD0`{1Y@I3&KV+=krIG7bxQA{d(i(qk1`W3jUEE zX2Y!||09DRGx$#o{)9mrGb*O`VTgk7aWt|hTs==I|8bvWe%Dk{2X>5Ts$70*Zt8B0 z?sq@3Iz~{PpF`fiK|>{gs5j@hCYf!Ug&@i+U41$epMml}qe+++{#+4{-@3#A4xZq8 z4-zeiqj;1%$|u0_gA_`OV_;HvAkf^oRJ~iRyt}p@Y4%D9~%6as8K|sc8XMw4-U&MC<@cmL#Tf!S>Dx(fKpgPXQ@%HsMpT;vq1$s z$Hm`yq5afFLw4%YVeg4;lQ3fl@^%Wy^oX;QI{J;jYdm9yw~w<$qy})9gS;LN53N z1^Vw+ogpB>&m(YB5K$~R%Pd@~wntJU$3_IG=vBuaIgsfe`MP$awZjY^?ON8r|8Rzr zy#MWFvUVm9LWYH};Jf!0sH>~ DCY|{0 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/wheel.cpython-39.pyc b/venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/wheel.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b2cd3e846992adf218f9297cf0a7a5974a9c8dec GIT binary patch literal 27161 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_vendor/distlib/_backport/__init__.py b/venv/Lib/site-packages/pip/_vendor/distlib/_backport/__init__.py new file mode 100644 index 0000000..f7dbf4c --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/distlib/_backport/__init__.py @@ -0,0 +1,6 @@ +"""Modules copied from Python 3 standard libraries, for internal use only. + +Individual classes and functions are found in d2._backport.misc. Intended +usage is to always import things missing from 3.1 from that module: the +built-in/stdlib objects will be used if found. +""" diff --git a/venv/Lib/site-packages/pip/_vendor/distlib/_backport/__pycache__/__init__.cpython-39.pyc b/venv/Lib/site-packages/pip/_vendor/distlib/_backport/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bea6e05e7797f0380b0cf62989ef29104992339f GIT binary patch literal 476 zcmYjO%}OLO5YBi}TIS*lSf>TSX;}r4L1dTpBB%(umn9IYJDHi%bP`f&hw&ZuL3|~z zK7uz-Ry!aTR8fCl@qG!7$CVQMzx$)v87cKT6yHsH>X$fgNwDglvZGtIw}IO-xQe#- zj-ic-oP}AA9o($SA_h1DE*LCk3!a*cnH=xKEM}lkTn^}=X9qF(Rb5pV!O|nyUb?ME zX1OU~nDwD86oXXR3AmRY1+a&;X|R1rF_*d{Zfk%Gxf-mqRnItgKnx`U`X#Oys2et+ zEGWzw1i+H4*&fwD*GXAmf$me!R5o4J^yJHg!T}d63LrN3t}P5p@*WyDuop73HLJS1 z-W$Da8e?N?%(KcH@>rkYeg0>v|FX-hF$84&JEe0hs4ruSUf;Pc=|pMLha`%eoh%p5 t`N{Fgz3AenVW!QaNQ+rp;v!V^mw0Uq1uDkWY4x&ox~6|N{Mehg`T%6fnFas= literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_vendor/distlib/_backport/__pycache__/misc.cpython-39.pyc b/venv/Lib/site-packages/pip/_vendor/distlib/_backport/__pycache__/misc.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..921196c84e0d8d50a08e993822a71f799b87260e GIT binary patch literal 1096 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 Kf)TQG{(k{puR1&c literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_vendor/distlib/_backport/__pycache__/sysconfig.cpython-39.pyc b/venv/Lib/site-packages/pip/_vendor/distlib/_backport/__pycache__/sysconfig.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c180f628e4840ab54f0fe76d0de002cc4d28acde GIT binary patch literal 15960 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_vendor/distlib/_backport/__pycache__/tarfile.cpython-39.pyc b/venv/Lib/site-packages/pip/_vendor/distlib/_backport/__pycache__/tarfile.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3e8d0906a0f7d4386f9403187006876f5dd864e2 GIT binary patch literal 62724 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 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: + os.symlink(linkto, dstname) + 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 + 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 EnvironmentError as why: + errors.append((srcname, dstname, str(why))) + try: + copystat(src, dst) + except OSError as why: + if WindowsError is not None and isinstance(why, WindowsError): + # Copying file access times may fail on Windows + pass + else: + errors.extend((src, dst, str(why))) + if errors: + raise Error(errors) + +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 os.listdir, os.remove, or os.rmdir; + 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 + 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 + names = [] + try: + names = os.listdir(path) + except os.error: + onerror(os.listdir, path, sys.exc_info()) + for name in names: + fullname = os.path.join(path, name) + try: + mode = os.lstat(fullname).st_mode + except os.error: + mode = 0 + if stat.S_ISDIR(mode): + rmtree(fullname, ignore_errors, onerror) + else: + try: + os.remove(fullname) + except os.error: + onerror(os.remove, fullname, sys.exc_info()) + try: + os.rmdir(path) + except os.error: + onerror(os.rmdir, path, sys.exc_info()) + + +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. + return os.path.basename(path.rstrip(os.path.sep)) + +def move(src, dst): + """Recursively move a file or directory to another location. This is + similar to the Unix "mv" command. + + 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. + 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.isdir(src): + if _destinsrc(src, dst): + raise Error("Cannot move a directory '%s' into itself '%s'." % (src, dst)) + copytree(src, real_dst, symlinks=True) + rmtree(src) + else: + copy2(src, real_dst) + os.unlink(src) + +def _destinsrc(src, dst): + src = abspath(src) + dst = 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", 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", or ".bz2"). + + Returns the output filename. + """ + tar_compression = {'gzip': 'gz', None: ''} + compress_ext = {'gzip': '.gz'} + + if _BZ2_SUPPORTED: + tar_compression['bzip2'] = 'bz2' + compress_ext['bzip2'] = '.bz2' + + # flags for compression program, each element of list will be an argument + if compress is not None and compress not in compress_ext: + raise ValueError("bad value for 'compress', or compression format not " + "supported : {0}".format(compress)) + + archive_name = base_name + '.tar' + compress_ext.get(compress, '') + archive_dir = os.path.dirname(archive_name) + + if 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[compress]) + try: + tar.add(base_dir, filter=_set_uid_gid) + finally: + tar.close() + + return archive_name + +def _call_external_zip(base_dir, zip_filename, verbose=False, dry_run=False): + # XXX see if we want to keep an external call here + if verbose: + zipoptions = "-r" + else: + zipoptions = "-rq" + from distutils.errors import DistutilsExecError + from distutils.spawn import spawn + try: + spawn(["zip", zipoptions, zip_filename, base_dir], dry_run=dry_run) + except DistutilsExecError: + # XXX really should distinguish between "couldn't find + # external 'zip' command" and "zip failed". + raise ExecError("unable to create zip file '%s': " + "could neither import the 'zipfile' module nor " + "find a standalone zip utility") % zip_filename + +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". Uses either the + "zipfile" Python module (if available) or the InfoZIP "zip" utility + (if installed and found on the default search path). If neither tool is + available, raises ExecError. Returns the name of the output zip + file. + """ + zip_filename = base_name + ".zip" + archive_dir = os.path.dirname(base_name) + + if 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 zipfile module is not available, try spawning an external 'zip' + # command. + try: + import zipfile + except ImportError: + zipfile = None + + if zipfile is None: + _call_external_zip(base_dir, zip_filename, verbose, dry_run) + else: + if logger is not None: + logger.info("creating '%s' and adding '%s' to it", + zip_filename, base_dir) + + if not dry_run: + zip = zipfile.ZipFile(zip_filename, "w", + compression=zipfile.ZIP_DEFLATED) + + for dirpath, dirnames, filenames in os.walk(base_dir): + for name in filenames: + path = os.path.normpath(os.path.join(dirpath, name)) + if os.path.isfile(path): + zip.write(path, path) + if logger is not None: + logger.info("adding '%s'", path) + zip.close() + + return zip_filename + +_ARCHIVE_FORMATS = { + 'gztar': (_make_tarball, [('compress', 'gzip')], "gzip'ed tar-file"), + 'bztar': (_make_tarball, [('compress', 'bzip2')], "bzip2'ed tar-file"), + 'tar': (_make_tarball, [('compress', None)], "uncompressed tar file"), + 'zip': (_make_zipfile, [], "ZIP file"), + } + +if _BZ2_SUPPORTED: + _ARCHIVE_FORMATS['bztar'] = (_make_tarball, [('compress', 'bzip2')], + "bzip2'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 isinstance(function, Callable): + 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", "bztar" + or "gztar". + + '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) + + 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 isinstance(function, Callable): + 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` + """ + try: + import zipfile + except ImportError: + raise ReadError('zlib not supported, cannot unpack this archive.') + + 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 `filename` to `extract_dir` + """ + 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 = { + 'gztar': (['.tar.gz', '.tgz'], _unpack_tarfile, [], "gzip'ed tar-file"), + 'tar': (['.tar'], _unpack_tarfile, [], "uncompressed tar file"), + 'zip': (['.zip'], _unpack_zipfile, [], "ZIP file") + } + +if _BZ2_SUPPORTED: + _UNPACK_FORMATS['bztar'] = (['.bz2'], _unpack_tarfile, [], + "bzip2'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", or "gztar". 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() + + if format is not None: + try: + format_info = _UNPACK_FORMATS[format] + except KeyError: + raise ValueError("Unknown unpack format '{0}'".format(format)) + + 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) diff --git a/venv/Lib/site-packages/pip/_vendor/distlib/_backport/sysconfig.cfg b/venv/Lib/site-packages/pip/_vendor/distlib/_backport/sysconfig.cfg new file mode 100644 index 0000000..1746bd0 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/distlib/_backport/sysconfig.cfg @@ -0,0 +1,84 @@ +[posix_prefix] +# Configuration directories. Some of these come straight out of the +# configure script. They are for implementing the other variables, not to +# be used directly in [resource_locations]. +confdir = /etc +datadir = /usr/share +libdir = /usr/lib +statedir = /var +# User resource directory +local = ~/.local/{distribution.name} + +stdlib = {base}/lib/python{py_version_short} +platstdlib = {platbase}/lib/python{py_version_short} +purelib = {base}/lib/python{py_version_short}/site-packages +platlib = {platbase}/lib/python{py_version_short}/site-packages +include = {base}/include/python{py_version_short}{abiflags} +platinclude = {platbase}/include/python{py_version_short}{abiflags} +data = {base} + +[posix_home] +stdlib = {base}/lib/python +platstdlib = {base}/lib/python +purelib = {base}/lib/python +platlib = {base}/lib/python +include = {base}/include/python +platinclude = {base}/include/python +scripts = {base}/bin +data = {base} + +[nt] +stdlib = {base}/Lib +platstdlib = {base}/Lib +purelib = {base}/Lib/site-packages +platlib = {base}/Lib/site-packages +include = {base}/Include +platinclude = {base}/Include +scripts = {base}/Scripts +data = {base} + +[os2] +stdlib = {base}/Lib +platstdlib = {base}/Lib +purelib = {base}/Lib/site-packages +platlib = {base}/Lib/site-packages +include = {base}/Include +platinclude = {base}/Include +scripts = {base}/Scripts +data = {base} + +[os2_home] +stdlib = {userbase}/lib/python{py_version_short} +platstdlib = {userbase}/lib/python{py_version_short} +purelib = {userbase}/lib/python{py_version_short}/site-packages +platlib = {userbase}/lib/python{py_version_short}/site-packages +include = {userbase}/include/python{py_version_short} +scripts = {userbase}/bin +data = {userbase} + +[nt_user] +stdlib = {userbase}/Python{py_version_nodot} +platstdlib = {userbase}/Python{py_version_nodot} +purelib = {userbase}/Python{py_version_nodot}/site-packages +platlib = {userbase}/Python{py_version_nodot}/site-packages +include = {userbase}/Python{py_version_nodot}/Include +scripts = {userbase}/Scripts +data = {userbase} + +[posix_user] +stdlib = {userbase}/lib/python{py_version_short} +platstdlib = {userbase}/lib/python{py_version_short} +purelib = {userbase}/lib/python{py_version_short}/site-packages +platlib = {userbase}/lib/python{py_version_short}/site-packages +include = {userbase}/include/python{py_version_short} +scripts = {userbase}/bin +data = {userbase} + +[osx_framework_user] +stdlib = {userbase}/lib/python +platstdlib = {userbase}/lib/python +purelib = {userbase}/lib/python/site-packages +platlib = {userbase}/lib/python/site-packages +include = {userbase}/include +scripts = {userbase}/bin +data = {userbase} diff --git a/venv/Lib/site-packages/pip/_vendor/distlib/_backport/sysconfig.py b/venv/Lib/site-packages/pip/_vendor/distlib/_backport/sysconfig.py new file mode 100644 index 0000000..b470a37 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/distlib/_backport/sysconfig.py @@ -0,0 +1,786 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2012 The Python Software Foundation. +# See LICENSE.txt and CONTRIBUTORS.txt. +# +"""Access to Python's configuration information.""" + +import codecs +import os +import re +import sys +from os.path import pardir, realpath +try: + import configparser +except ImportError: + import ConfigParser as configparser + + +__all__ = [ + 'get_config_h_filename', + 'get_config_var', + 'get_config_vars', + 'get_makefile_filename', + 'get_path', + 'get_path_names', + 'get_paths', + 'get_platform', + 'get_python_version', + 'get_scheme_names', + 'parse_config_h', +] + + +def _safe_realpath(path): + try: + return realpath(path) + except OSError: + return path + + +if sys.executable: + _PROJECT_BASE = os.path.dirname(_safe_realpath(sys.executable)) +else: + # sys.executable can be empty if argv[0] has been changed and Python is + # unable to retrieve the real program name + _PROJECT_BASE = _safe_realpath(os.getcwd()) + +if os.name == "nt" and "pcbuild" in _PROJECT_BASE[-8:].lower(): + _PROJECT_BASE = _safe_realpath(os.path.join(_PROJECT_BASE, pardir)) +# PC/VS7.1 +if os.name == "nt" and "\\pc\\v" in _PROJECT_BASE[-10:].lower(): + _PROJECT_BASE = _safe_realpath(os.path.join(_PROJECT_BASE, pardir, pardir)) +# PC/AMD64 +if os.name == "nt" and "\\pcbuild\\amd64" in _PROJECT_BASE[-14:].lower(): + _PROJECT_BASE = _safe_realpath(os.path.join(_PROJECT_BASE, pardir, pardir)) + + +def is_python_build(): + for fn in ("Setup.dist", "Setup.local"): + if os.path.isfile(os.path.join(_PROJECT_BASE, "Modules", fn)): + return True + return False + +_PYTHON_BUILD = is_python_build() + +_cfg_read = False + +def _ensure_cfg_read(): + global _cfg_read + if not _cfg_read: + from ..resources import finder + backport_package = __name__.rsplit('.', 1)[0] + _finder = finder(backport_package) + _cfgfile = _finder.find('sysconfig.cfg') + assert _cfgfile, 'sysconfig.cfg exists' + with _cfgfile.as_stream() as s: + _SCHEMES.readfp(s) + if _PYTHON_BUILD: + for scheme in ('posix_prefix', 'posix_home'): + _SCHEMES.set(scheme, 'include', '{srcdir}/Include') + _SCHEMES.set(scheme, 'platinclude', '{projectbase}/.') + + _cfg_read = True + + +_SCHEMES = configparser.RawConfigParser() +_VAR_REPL = re.compile(r'\{([^{]*?)\}') + +def _expand_globals(config): + _ensure_cfg_read() + if config.has_section('globals'): + globals = config.items('globals') + else: + globals = tuple() + + sections = config.sections() + for section in sections: + if section == 'globals': + continue + for option, value in globals: + if config.has_option(section, option): + continue + config.set(section, option, value) + config.remove_section('globals') + + # now expanding local variables defined in the cfg file + # + for section in config.sections(): + variables = dict(config.items(section)) + + def _replacer(matchobj): + name = matchobj.group(1) + if name in variables: + return variables[name] + return matchobj.group(0) + + for option, value in config.items(section): + config.set(section, option, _VAR_REPL.sub(_replacer, value)) + +#_expand_globals(_SCHEMES) + +_PY_VERSION = '%s.%s.%s' % sys.version_info[:3] +_PY_VERSION_SHORT = '%s.%s' % sys.version_info[:2] +_PY_VERSION_SHORT_NO_DOT = '%s%s' % sys.version_info[:2] +_PREFIX = os.path.normpath(sys.prefix) +_EXEC_PREFIX = os.path.normpath(sys.exec_prefix) +_CONFIG_VARS = None +_USER_BASE = None + + +def _subst_vars(path, local_vars): + """In the string `path`, replace tokens like {some.thing} with the + corresponding value from the map `local_vars`. + + If there is no corresponding value, leave the token unchanged. + """ + def _replacer(matchobj): + name = matchobj.group(1) + if name in local_vars: + return local_vars[name] + elif name in os.environ: + return os.environ[name] + return matchobj.group(0) + return _VAR_REPL.sub(_replacer, path) + + +def _extend_dict(target_dict, other_dict): + target_keys = target_dict.keys() + for key, value in other_dict.items(): + if key in target_keys: + continue + target_dict[key] = value + + +def _expand_vars(scheme, vars): + res = {} + if vars is None: + vars = {} + _extend_dict(vars, get_config_vars()) + + for key, value in _SCHEMES.items(scheme): + if os.name in ('posix', 'nt'): + value = os.path.expanduser(value) + res[key] = os.path.normpath(_subst_vars(value, vars)) + return res + + +def format_value(value, vars): + def _replacer(matchobj): + name = matchobj.group(1) + if name in vars: + return vars[name] + return matchobj.group(0) + return _VAR_REPL.sub(_replacer, value) + + +def _get_default_scheme(): + if os.name == 'posix': + # the default scheme for posix is posix_prefix + return 'posix_prefix' + return os.name + + +def _getuserbase(): + env_base = os.environ.get("PYTHONUSERBASE", None) + + def joinuser(*args): + return os.path.expanduser(os.path.join(*args)) + + # what about 'os2emx', 'riscos' ? + if os.name == "nt": + base = os.environ.get("APPDATA") or "~" + if env_base: + return env_base + else: + return joinuser(base, "Python") + + if sys.platform == "darwin": + framework = get_config_var("PYTHONFRAMEWORK") + if framework: + if env_base: + return env_base + else: + return joinuser("~", "Library", framework, "%d.%d" % + sys.version_info[:2]) + + if env_base: + return env_base + else: + return joinuser("~", ".local") + + +def _parse_makefile(filename, vars=None): + """Parse a Makefile-style file. + + A dictionary containing name/value pairs is returned. If an + optional dictionary is passed in as the second argument, it is + used instead of a new dictionary. + """ + # Regexes needed for parsing Makefile (and similar syntaxes, + # like old-style Setup files). + _variable_rx = re.compile(r"([a-zA-Z][a-zA-Z0-9_]+)\s*=\s*(.*)") + _findvar1_rx = re.compile(r"\$\(([A-Za-z][A-Za-z0-9_]*)\)") + _findvar2_rx = re.compile(r"\${([A-Za-z][A-Za-z0-9_]*)}") + + if vars is None: + vars = {} + done = {} + notdone = {} + + with codecs.open(filename, encoding='utf-8', errors="surrogateescape") as f: + lines = f.readlines() + + for line in lines: + if line.startswith('#') or line.strip() == '': + continue + m = _variable_rx.match(line) + if m: + n, v = m.group(1, 2) + v = v.strip() + # `$$' is a literal `$' in make + tmpv = v.replace('$$', '') + + if "$" in tmpv: + notdone[n] = v + else: + try: + v = int(v) + except ValueError: + # insert literal `$' + done[n] = v.replace('$$', '$') + else: + done[n] = v + + # do variable interpolation here + variables = list(notdone.keys()) + + # Variables with a 'PY_' prefix in the makefile. These need to + # be made available without that prefix through sysconfig. + # Special care is needed to ensure that variable expansion works, even + # if the expansion uses the name without a prefix. + renamed_variables = ('CFLAGS', 'LDFLAGS', 'CPPFLAGS') + + while len(variables) > 0: + for name in tuple(variables): + value = notdone[name] + m = _findvar1_rx.search(value) or _findvar2_rx.search(value) + if m is not None: + n = m.group(1) + found = True + if n in done: + item = str(done[n]) + elif n in notdone: + # get it on a subsequent round + found = False + elif n in os.environ: + # do it like make: fall back to environment + item = os.environ[n] + + elif n in renamed_variables: + if (name.startswith('PY_') and + name[3:] in renamed_variables): + item = "" + + elif 'PY_' + n in notdone: + found = False + + else: + item = str(done['PY_' + n]) + + else: + done[n] = item = "" + + if found: + after = value[m.end():] + value = value[:m.start()] + item + after + if "$" in after: + notdone[name] = value + else: + try: + value = int(value) + except ValueError: + done[name] = value.strip() + else: + done[name] = value + variables.remove(name) + + if (name.startswith('PY_') and + name[3:] in renamed_variables): + + name = name[3:] + if name not in done: + done[name] = value + + else: + # bogus variable reference (e.g. "prefix=$/opt/python"); + # just drop it since we can't deal + done[name] = value + variables.remove(name) + + # strip spurious spaces + for k, v in done.items(): + if isinstance(v, str): + done[k] = v.strip() + + # save the results in the global dictionary + vars.update(done) + return vars + + +def get_makefile_filename(): + """Return the path of the Makefile.""" + if _PYTHON_BUILD: + return os.path.join(_PROJECT_BASE, "Makefile") + if hasattr(sys, 'abiflags'): + config_dir_name = 'config-%s%s' % (_PY_VERSION_SHORT, sys.abiflags) + else: + config_dir_name = 'config' + return os.path.join(get_path('stdlib'), config_dir_name, 'Makefile') + + +def _init_posix(vars): + """Initialize the module as appropriate for POSIX systems.""" + # load the installed Makefile: + makefile = get_makefile_filename() + try: + _parse_makefile(makefile, vars) + except IOError as e: + msg = "invalid Python installation: unable to open %s" % makefile + if hasattr(e, "strerror"): + msg = msg + " (%s)" % e.strerror + raise IOError(msg) + # load the installed pyconfig.h: + config_h = get_config_h_filename() + try: + with open(config_h) as f: + parse_config_h(f, vars) + except IOError as e: + msg = "invalid Python installation: unable to open %s" % config_h + if hasattr(e, "strerror"): + msg = msg + " (%s)" % e.strerror + raise IOError(msg) + # On AIX, there are wrong paths to the linker scripts in the Makefile + # -- these paths are relative to the Python source, but when installed + # the scripts are in another directory. + if _PYTHON_BUILD: + vars['LDSHARED'] = vars['BLDSHARED'] + + +def _init_non_posix(vars): + """Initialize the module as appropriate for NT""" + # set basic install directories + vars['LIBDEST'] = get_path('stdlib') + vars['BINLIBDEST'] = get_path('platstdlib') + vars['INCLUDEPY'] = get_path('include') + vars['SO'] = '.pyd' + vars['EXE'] = '.exe' + vars['VERSION'] = _PY_VERSION_SHORT_NO_DOT + vars['BINDIR'] = os.path.dirname(_safe_realpath(sys.executable)) + +# +# public APIs +# + + +def parse_config_h(fp, vars=None): + """Parse a config.h-style file. + + A dictionary containing name/value pairs is returned. If an + optional dictionary is passed in as the second argument, it is + used instead of a new dictionary. + """ + if vars is None: + vars = {} + define_rx = re.compile("#define ([A-Z][A-Za-z0-9_]+) (.*)\n") + undef_rx = re.compile("/[*] #undef ([A-Z][A-Za-z0-9_]+) [*]/\n") + + while True: + line = fp.readline() + if not line: + break + m = define_rx.match(line) + if m: + n, v = m.group(1, 2) + try: + v = int(v) + except ValueError: + pass + vars[n] = v + else: + m = undef_rx.match(line) + if m: + vars[m.group(1)] = 0 + return vars + + +def get_config_h_filename(): + """Return the path of pyconfig.h.""" + if _PYTHON_BUILD: + if os.name == "nt": + inc_dir = os.path.join(_PROJECT_BASE, "PC") + else: + inc_dir = _PROJECT_BASE + else: + inc_dir = get_path('platinclude') + return os.path.join(inc_dir, 'pyconfig.h') + + +def get_scheme_names(): + """Return a tuple containing the schemes names.""" + return tuple(sorted(_SCHEMES.sections())) + + +def get_path_names(): + """Return a tuple containing the paths names.""" + # xxx see if we want a static list + return _SCHEMES.options('posix_prefix') + + +def get_paths(scheme=_get_default_scheme(), vars=None, expand=True): + """Return a mapping containing an install scheme. + + ``scheme`` is the install scheme name. If not provided, it will + return the default scheme for the current platform. + """ + _ensure_cfg_read() + if expand: + return _expand_vars(scheme, vars) + else: + return dict(_SCHEMES.items(scheme)) + + +def get_path(name, scheme=_get_default_scheme(), vars=None, expand=True): + """Return a path corresponding to the scheme. + + ``scheme`` is the install scheme name. + """ + return get_paths(scheme, vars, expand)[name] + + +def get_config_vars(*args): + """With no arguments, return a dictionary of all configuration + variables relevant for the current platform. + + On Unix, this means every variable defined in Python's installed Makefile; + On Windows and Mac OS it's a much smaller set. + + With arguments, return a list of values that result from looking up + each argument in the configuration variable dictionary. + """ + global _CONFIG_VARS + if _CONFIG_VARS is None: + _CONFIG_VARS = {} + # Normalized versions of prefix and exec_prefix are handy to have; + # in fact, these are the standard versions used most places in the + # distutils2 module. + _CONFIG_VARS['prefix'] = _PREFIX + _CONFIG_VARS['exec_prefix'] = _EXEC_PREFIX + _CONFIG_VARS['py_version'] = _PY_VERSION + _CONFIG_VARS['py_version_short'] = _PY_VERSION_SHORT + _CONFIG_VARS['py_version_nodot'] = _PY_VERSION[0] + _PY_VERSION[2] + _CONFIG_VARS['base'] = _PREFIX + _CONFIG_VARS['platbase'] = _EXEC_PREFIX + _CONFIG_VARS['projectbase'] = _PROJECT_BASE + try: + _CONFIG_VARS['abiflags'] = sys.abiflags + except AttributeError: + # sys.abiflags may not be defined on all platforms. + _CONFIG_VARS['abiflags'] = '' + + if os.name in ('nt', 'os2'): + _init_non_posix(_CONFIG_VARS) + if os.name == 'posix': + _init_posix(_CONFIG_VARS) + # Setting 'userbase' is done below the call to the + # init function to enable using 'get_config_var' in + # the init-function. + if sys.version >= '2.6': + _CONFIG_VARS['userbase'] = _getuserbase() + + if 'srcdir' not in _CONFIG_VARS: + _CONFIG_VARS['srcdir'] = _PROJECT_BASE + else: + _CONFIG_VARS['srcdir'] = _safe_realpath(_CONFIG_VARS['srcdir']) + + # Convert srcdir into an absolute path if it appears necessary. + # Normally it is relative to the build directory. However, during + # testing, for example, we might be running a non-installed python + # from a different directory. + if _PYTHON_BUILD and os.name == "posix": + base = _PROJECT_BASE + try: + cwd = os.getcwd() + except OSError: + cwd = None + if (not os.path.isabs(_CONFIG_VARS['srcdir']) and + base != cwd): + # srcdir is relative and we are not in the same directory + # as the executable. Assume executable is in the build + # directory and make srcdir absolute. + srcdir = os.path.join(base, _CONFIG_VARS['srcdir']) + _CONFIG_VARS['srcdir'] = os.path.normpath(srcdir) + + if sys.platform == 'darwin': + kernel_version = os.uname()[2] # Kernel version (8.4.3) + major_version = int(kernel_version.split('.')[0]) + + if major_version < 8: + # On Mac OS X before 10.4, check if -arch and -isysroot + # are in CFLAGS or LDFLAGS and remove them if they are. + # This is needed when building extensions on a 10.3 system + # using a universal build of python. + for key in ('LDFLAGS', 'BASECFLAGS', + # a number of derived variables. These need to be + # patched up as well. + 'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'): + flags = _CONFIG_VARS[key] + flags = re.sub(r'-arch\s+\w+\s', ' ', flags) + flags = re.sub('-isysroot [^ \t]*', ' ', flags) + _CONFIG_VARS[key] = flags + else: + # Allow the user to override the architecture flags using + # an environment variable. + # NOTE: This name was introduced by Apple in OSX 10.5 and + # is used by several scripting languages distributed with + # that OS release. + if 'ARCHFLAGS' in os.environ: + arch = os.environ['ARCHFLAGS'] + for key in ('LDFLAGS', 'BASECFLAGS', + # a number of derived variables. These need to be + # patched up as well. + 'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'): + + flags = _CONFIG_VARS[key] + flags = re.sub(r'-arch\s+\w+\s', ' ', flags) + flags = flags + ' ' + arch + _CONFIG_VARS[key] = flags + + # If we're on OSX 10.5 or later and the user tries to + # compiles an extension using an SDK that is not present + # on the current machine it is better to not use an SDK + # than to fail. + # + # The major usecase for this is users using a Python.org + # binary installer on OSX 10.6: that installer uses + # the 10.4u SDK, but that SDK is not installed by default + # when you install Xcode. + # + CFLAGS = _CONFIG_VARS.get('CFLAGS', '') + m = re.search(r'-isysroot\s+(\S+)', CFLAGS) + if m is not None: + sdk = m.group(1) + if not os.path.exists(sdk): + for key in ('LDFLAGS', 'BASECFLAGS', + # a number of derived variables. These need to be + # patched up as well. + 'CFLAGS', 'PY_CFLAGS', 'BLDSHARED'): + + flags = _CONFIG_VARS[key] + flags = re.sub(r'-isysroot\s+\S+(\s|$)', ' ', flags) + _CONFIG_VARS[key] = flags + + if args: + vals = [] + for name in args: + vals.append(_CONFIG_VARS.get(name)) + return vals + else: + return _CONFIG_VARS + + +def get_config_var(name): + """Return the value of a single variable using the dictionary returned by + 'get_config_vars()'. + + Equivalent to get_config_vars().get(name) + """ + return get_config_vars().get(name) + + +def get_platform(): + """Return a string that identifies the current platform. + + This is used mainly to distinguish platform-specific build directories and + platform-specific built distributions. Typically includes the OS name + and version and the architecture (as supplied by 'os.uname()'), + although the exact information included depends on the OS; eg. for IRIX + the architecture isn't particularly important (IRIX only runs on SGI + hardware), but for Linux the kernel version isn't particularly + important. + + Examples of returned values: + linux-i586 + linux-alpha (?) + solaris-2.6-sun4u + irix-5.3 + irix64-6.2 + + Windows will return one of: + win-amd64 (64bit Windows on AMD64 (aka x86_64, Intel64, EM64T, etc) + win-ia64 (64bit Windows on Itanium) + win32 (all others - specifically, sys.platform is returned) + + For other non-POSIX platforms, currently just returns 'sys.platform'. + """ + if os.name == 'nt': + # sniff sys.version for architecture. + prefix = " bit (" + i = sys.version.find(prefix) + if i == -1: + return sys.platform + j = sys.version.find(")", i) + look = sys.version[i+len(prefix):j].lower() + if look == 'amd64': + return 'win-amd64' + if look == 'itanium': + return 'win-ia64' + return sys.platform + + if os.name != "posix" or not hasattr(os, 'uname'): + # XXX what about the architecture? NT is Intel or Alpha, + # Mac OS is M68k or PPC, etc. + return sys.platform + + # Try to distinguish various flavours of Unix + osname, host, release, version, machine = os.uname() + + # Convert the OS name to lowercase, remove '/' characters + # (to accommodate BSD/OS), and translate spaces (for "Power Macintosh") + osname = osname.lower().replace('/', '') + machine = machine.replace(' ', '_') + machine = machine.replace('/', '-') + + if osname[:5] == "linux": + # At least on Linux/Intel, 'machine' is the processor -- + # i386, etc. + # XXX what about Alpha, SPARC, etc? + return "%s-%s" % (osname, machine) + elif osname[:5] == "sunos": + if release[0] >= "5": # SunOS 5 == Solaris 2 + osname = "solaris" + release = "%d.%s" % (int(release[0]) - 3, release[2:]) + # fall through to standard osname-release-machine representation + elif osname[:4] == "irix": # could be "irix64"! + return "%s-%s" % (osname, release) + elif osname[:3] == "aix": + return "%s-%s.%s" % (osname, version, release) + elif osname[:6] == "cygwin": + osname = "cygwin" + rel_re = re.compile(r'[\d.]+') + m = rel_re.match(release) + if m: + release = m.group() + elif osname[:6] == "darwin": + # + # For our purposes, we'll assume that the system version from + # distutils' perspective is what MACOSX_DEPLOYMENT_TARGET is set + # to. This makes the compatibility story a bit more sane because the + # machine is going to compile and link as if it were + # MACOSX_DEPLOYMENT_TARGET. + cfgvars = get_config_vars() + macver = cfgvars.get('MACOSX_DEPLOYMENT_TARGET') + + if True: + # Always calculate the release of the running machine, + # needed to determine if we can build fat binaries or not. + + macrelease = macver + # Get the system version. Reading this plist is a documented + # way to get the system version (see the documentation for + # the Gestalt Manager) + try: + f = open('/System/Library/CoreServices/SystemVersion.plist') + except IOError: + # We're on a plain darwin box, fall back to the default + # behaviour. + pass + else: + try: + m = re.search(r'ProductUserVisibleVersion\s*' + r'(.*?)', f.read()) + finally: + f.close() + if m is not None: + macrelease = '.'.join(m.group(1).split('.')[:2]) + # else: fall back to the default behaviour + + if not macver: + macver = macrelease + + if macver: + release = macver + osname = "macosx" + + if ((macrelease + '.') >= '10.4.' and + '-arch' in get_config_vars().get('CFLAGS', '').strip()): + # The universal build will build fat binaries, but not on + # systems before 10.4 + # + # Try to detect 4-way universal builds, those have machine-type + # 'universal' instead of 'fat'. + + machine = 'fat' + cflags = get_config_vars().get('CFLAGS') + + archs = re.findall(r'-arch\s+(\S+)', cflags) + archs = tuple(sorted(set(archs))) + + if len(archs) == 1: + machine = archs[0] + elif archs == ('i386', 'ppc'): + machine = 'fat' + elif archs == ('i386', 'x86_64'): + machine = 'intel' + elif archs == ('i386', 'ppc', 'x86_64'): + machine = 'fat3' + elif archs == ('ppc64', 'x86_64'): + machine = 'fat64' + elif archs == ('i386', 'ppc', 'ppc64', 'x86_64'): + machine = 'universal' + else: + raise ValueError( + "Don't know machine value for archs=%r" % (archs,)) + + elif machine == 'i386': + # On OSX the machine type returned by uname is always the + # 32-bit variant, even if the executable architecture is + # the 64-bit variant + if sys.maxsize >= 2**32: + machine = 'x86_64' + + elif machine in ('PowerPC', 'Power_Macintosh'): + # Pick a sane name for the PPC architecture. + # See 'i386' case + if sys.maxsize >= 2**32: + machine = 'ppc64' + else: + machine = 'ppc' + + return "%s-%s-%s" % (osname, release, machine) + + +def get_python_version(): + return _PY_VERSION_SHORT + + +def _print_dict(title, data): + for index, (key, value) in enumerate(sorted(data.items())): + if index == 0: + print('%s: ' % (title)) + print('\t%s = "%s"' % (key, value)) + + +def _main(): + """Display all information sysconfig detains.""" + print('Platform: "%s"' % get_platform()) + print('Python version: "%s"' % get_python_version()) + print('Current installation scheme: "%s"' % _get_default_scheme()) + print() + _print_dict('Paths', get_paths()) + print() + _print_dict('Variables', get_config_vars()) + + +if __name__ == '__main__': + _main() diff --git a/venv/Lib/site-packages/pip/_vendor/distlib/_backport/tarfile.py b/venv/Lib/site-packages/pip/_vendor/distlib/_backport/tarfile.py new file mode 100644 index 0000000..d66d856 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/distlib/_backport/tarfile.py @@ -0,0 +1,2607 @@ +#------------------------------------------------------------------- +# 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. +# +from __future__ import print_function + +"""Read from and write to tar format archives. +""" + +__version__ = "$Revision$" + +version = "0.9.0" +__author__ = "Lars Gust\u00e4bel (lars@gustaebel.de)" +__date__ = "$Date: 2011-02-25 17:42:01 +0200 (Fri, 25 Feb 2011) $" +__cvsid__ = "$Id: tarfile.py 88586 2011-02-25 15:42:01Z marc-andre.lemburg $" +__credits__ = "Gustavo Niemeyer, Niels Gust\u00e4bel, Richard Townsend." + +#--------- +# Imports +#--------- +import sys +import os +import stat +import errno +import time +import struct +import copy +import re + +try: + import grp, pwd +except ImportError: + grp = pwd = None + +# os.symlink on Windows prior to 6.0 raises NotImplementedError +symlink_exception = (AttributeError, NotImplementedError) +try: + # WindowsError (1314) will be raised if the caller does not hold the + # SeCreateSymbolicLinkPrivilege privilege + symlink_exception += (WindowsError,) +except NameError: + pass + +# from tarfile import * +__all__ = ["TarFile", "TarInfo", "is_tarfile", "TarError"] + +if sys.version_info[0] < 3: + import __builtin__ as builtins +else: + import builtins + +_open = builtins.open # Since 'open' is TarFile.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 = set(("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 +} + +#--------------------------------------------------------- +# Bits used in the mode field, values in octal. +#--------------------------------------------------------- +S_IFLNK = 0o120000 # symbolic link +S_IFREG = 0o100000 # regular file +S_IFBLK = 0o060000 # block device +S_IFDIR = 0o040000 # directory +S_IFCHR = 0o020000 # character device +S_IFIFO = 0o010000 # fifo + +TSUID = 0o4000 # set UID on execution +TSGID = 0o2000 # set GID on execution +TSVTX = 0o1000 # reserved + +TUREAD = 0o400 # read by owner +TUWRITE = 0o200 # write by owner +TUEXEC = 0o100 # execute/search by owner +TGREAD = 0o040 # read by group +TGWRITE = 0o020 # write by group +TGEXEC = 0o010 # execute/search by group +TOREAD = 0o004 # read by other +TOWRITE = 0o002 # write by other +TOEXEC = 0o001 # execute/search by other + +#--------------------------------------------------------- +# initialization +#--------------------------------------------------------- +if os.name in ("nt", "ce"): + 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] != chr(0o200): + try: + n = int(nts(s, "ascii", "strict") or "0", 8) + except ValueError: + raise InvalidHeaderError("invalid header") + else: + n = 0 + for i in range(len(s) - 1): + n <<= 8 + n += ord(s[i + 1]) + 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 byte indicates this particular + # encoding, the following digits-1 bytes are a big-endian + # representation. This allows values up to (256**(digits-1))-1. + if 0 <= n < 8 ** (digits - 1): + s = ("%0*o" % (digits - 1, n)).encode("ascii") + NUL + else: + if format != GNU_FORMAT or n >= 256 ** (digits - 1): + raise ValueError("overflow in number field") + + if n < 0: + # XXX We mimic GNU tar's behaviour with negative numbers, + # this could raise OverflowError. + n = struct.unpack("L", struct.pack("l", n))[0] + + s = bytearray() + for i in range(digits - 1): + s.insert(0, n & 0o377) + n >>= 8 + s.insert(0, 0o200) + 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("148B", buf[:148]) + struct.unpack("356B", buf[156:512])) + signed_chksum = 256 + sum(struct.unpack("148b", buf[:148]) + struct.unpack("356b", buf[156:512])) + return unsigned_chksum, signed_chksum + +def copyfileobj(src, dst, length=None): + """Copy length bytes from fileobj src to fileobj dst. + If length is None, copy the entire content. + """ + if length == 0: + return + if length is None: + while True: + buf = src.read(16*1024) + if not buf: + break + dst.write(buf) + return + + BUFSIZE = 16 * 1024 + blocks, remainder = divmod(length, BUFSIZE) + for b in range(blocks): + buf = src.read(BUFSIZE) + if len(buf) < BUFSIZE: + raise IOError("end of file reached") + dst.write(buf) + + if remainder != 0: + buf = src.read(remainder) + if len(buf) < remainder: + raise IOError("end of file reached") + dst.write(buf) + return + +filemode_table = ( + ((S_IFLNK, "l"), + (S_IFREG, "-"), + (S_IFBLK, "b"), + (S_IFDIR, "d"), + (S_IFCHR, "c"), + (S_IFIFO, "p")), + + ((TUREAD, "r"),), + ((TUWRITE, "w"),), + ((TUEXEC|TSUID, "s"), + (TSUID, "S"), + (TUEXEC, "x")), + + ((TGREAD, "r"),), + ((TGWRITE, "w"),), + ((TGEXEC|TSGID, "s"), + (TSGID, "S"), + (TGEXEC, "x")), + + ((TOREAD, "r"),), + ((TOWRITE, "w"),), + ((TOEXEC|TSVTX, "t"), + (TSVTX, "T"), + (TOEXEC, "x")) +) + +def filemode(mode): + """Convert a file's mode to a string of the form + -rwxrwxrwx. + Used by TarFile.list() + """ + 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) + +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(object): + """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(object): + """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() + else: + self._init_write_gz() + + if comptype == "bz2": + try: + import bz2 + except ImportError: + raise CompressionError("bz2 module is not available") + if mode == "r": + self.dbuf = b"" + self.cmp = bz2.BZ2Decompressor() + else: + self.cmp = bz2.BZ2Compressor() + 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 + + 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": + # The native zlib crc is an unsigned 32-bit integer, but + # the Python wrapper implicitly casts that to a signed C + # long. So, on a 32-bit box self.crc may "look negative", + # while the same crc on a 64-bit box may "look positive". + # To avoid irksome warnings from the `struct` module, force + # it to look positive on all boxes. + 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 = "".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) + while c < size: + buf = self.__read(self.bufsize) + if not buf: + break + try: + buf = self.cmp.decompress(buf) + except IOError: + raise ReadError("invalid compressed data") + self.dbuf += buf + c += len(buf) + buf = self.dbuf[:size] + self.dbuf = self.dbuf[size:] + return buf + + def __read(self, size): + """Return size bytes from stream. If internal buffer is empty, + read another block from the stream. + """ + c = len(self.buf) + while c < size: + buf = self.fileobj.read(self.bufsize) + if not buf: + break + self.buf += buf + c += len(buf) + buf = self.buf[:size] + self.buf = self.buf[size:] + return buf +# 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"\037\213\010"): + return "gz" + if self.buf.startswith(b"BZh91"): + return "bz2" + return "tar" + + def close(self): + self.fileobj.close() +# class StreamProxy + +class _BZ2Proxy(object): + """Small proxy class that enables external file object + support for "r:bz2" and "w:bz2" modes. This is actually + a workaround for a limitation in bz2 module's BZ2File + class which (unlike gzip.GzipFile) has no support for + a file object argument. + """ + + blocksize = 16 * 1024 + + def __init__(self, fileobj, mode): + self.fileobj = fileobj + self.mode = mode + self.name = getattr(self.fileobj, "name", None) + self.init() + + def init(self): + import bz2 + self.pos = 0 + if self.mode == "r": + self.bz2obj = bz2.BZ2Decompressor() + self.fileobj.seek(0) + self.buf = b"" + else: + self.bz2obj = bz2.BZ2Compressor() + + def read(self, size): + x = len(self.buf) + while x < size: + raw = self.fileobj.read(self.blocksize) + if not raw: + break + data = self.bz2obj.decompress(raw) + self.buf += data + x += len(data) + + buf = self.buf[:size] + self.buf = self.buf[size:] + self.pos += len(buf) + return buf + + def seek(self, pos): + if pos < self.pos: + self.init() + self.read(pos - self.pos) + + def tell(self): + return self.pos + + def write(self, data): + self.pos += len(data) + raw = self.bz2obj.compress(data) + self.fileobj.write(raw) + + def close(self): + if self.mode == "w": + raw = self.bz2obj.flush() + self.fileobj.write(raw) +# class _BZ2Proxy + +#------------------------ +# 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 + + 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 seekable(self): + if not hasattr(self.fileobj, "seekable"): + # XXX gzip.GzipFile and bz2.BZ2File + return True + return self.fileobj.seekable() + + def tell(self): + """Return the current file position. + """ + return self.position + + def seek(self, position): + """Seek to a position in the file. + """ + self.position = 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)) + buf += self.fileobj.read(length) + else: + buf += NUL * length + size -= length + self.position += length + return buf +#class _FileInFile + + +class ExFileObject(object): + """File-like object for reading an archive member. + Is returned by TarFile.extractfile(). + """ + blocksize = 1024 + + def __init__(self, tarfile, tarinfo): + self.fileobj = _FileInFile(tarfile.fileobj, + tarinfo.offset_data, + tarinfo.size, + tarinfo.sparse) + self.name = tarinfo.name + self.mode = "r" + self.closed = False + self.size = tarinfo.size + + self.position = 0 + self.buffer = b"" + + def readable(self): + return True + + def writable(self): + return False + + def seekable(self): + return self.fileobj.seekable() + + def read(self, size=None): + """Read at most size bytes from the file. If size is not + present or None, read all data until EOF is reached. + """ + if self.closed: + raise ValueError("I/O operation on closed file") + + buf = b"" + if self.buffer: + if size is None: + buf = self.buffer + self.buffer = b"" + else: + buf = self.buffer[:size] + self.buffer = self.buffer[size:] + + if size is None: + buf += self.fileobj.read() + else: + buf += self.fileobj.read(size - len(buf)) + + self.position += len(buf) + return buf + + # XXX TextIOWrapper uses the read1() method. + read1 = read + + def readline(self, size=-1): + """Read one entire line from the file. If size is present + and non-negative, return a string with at most that + size, which may be an incomplete line. + """ + if self.closed: + raise ValueError("I/O operation on closed file") + + pos = self.buffer.find(b"\n") + 1 + if pos == 0: + # no newline found. + while True: + buf = self.fileobj.read(self.blocksize) + self.buffer += buf + if not buf or b"\n" in buf: + pos = self.buffer.find(b"\n") + 1 + if pos == 0: + # no newline found. + pos = len(self.buffer) + break + + if size != -1: + pos = min(size, pos) + + buf = self.buffer[:pos] + self.buffer = self.buffer[pos:] + self.position += len(buf) + return buf + + def readlines(self): + """Return a list with all remaining lines. + """ + result = [] + while True: + line = self.readline() + if not line: break + result.append(line) + return result + + def tell(self): + """Return the current file position. + """ + if self.closed: + raise ValueError("I/O operation on closed file") + + return self.position + + def seek(self, pos, whence=os.SEEK_SET): + """Seek to a position in the file. + """ + if self.closed: + raise ValueError("I/O operation on closed file") + + if whence == os.SEEK_SET: + self.position = min(max(pos, 0), self.size) + elif whence == os.SEEK_CUR: + if pos < 0: + self.position = max(self.position + pos, 0) + else: + self.position = min(self.position + pos, self.size) + elif whence == os.SEEK_END: + self.position = max(min(self.size + pos, self.size), 0) + else: + raise ValueError("Invalid argument") + + self.buffer = b"" + self.fileobj.seek(self.position) + + def close(self): + """Close the file object. + """ + self.closed = True + + def __iter__(self): + """Get an iterator over the file's lines. + """ + while True: + line = self.readline() + if not line: + break + yield line +#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". + def _getpath(self): + return self.name + def _setpath(self, name): + self.name = name + path = property(_getpath, _setpath) + + def _getlinkpath(self): + return self.linkname + def _setlinkpath(self, linkname): + self.linkname = linkname + linkpath = property(_getlinkpath, _setlinkpath) + + 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"]) > LENGTH_LINK: + raise ValueError("linkname is too long") + + if len(info["name"]) > LENGTH_NAME: + info["prefix"], info["name"] = self._posix_split_name(info["name"]) + + 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"]) > LENGTH_LINK: + buf += self._create_gnu_long_header(info["linkname"], GNUTYPE_LONGLINK, encoding, errors) + + if len(info["name"]) > 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, "utf8") + + def _posix_split_name(self, name): + """Split a name longer than 100 chars into a prefix + and a name part. + """ + prefix = name[:LENGTH_PREFIX + 1] + while prefix and prefix[-1] != "/": + prefix = prefix[:-1] + + name = name[len(prefix):] + prefix = prefix[:-1] + + if not prefix or len(name) > LENGTH_NAME: + 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] + ("%06o\0" % chksum).encode("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("utf8", "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("utf8") + 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("utf8") + + 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 the 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("utf8") + + # 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 = "utf8" + + # 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 "utf8" 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, "utf8", "utf8", + 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, "utf8", "utf8", + 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 default ExFileObject class to use. + + 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): + """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. + """ + if len(mode) > 1 or mode not in "raw": + raise ValueError("mode must be 'r', 'a' or 'w'") + self.mode = mode + self._mode = {"r": "rb", "a": "r+b", "w": "wb"}[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"): + 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.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 "aw": + 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 + '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 + + '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 + '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 + """ + + 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. + for comptype in cls.OPEN_METH: + 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) as e: + 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 "rw": + 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 "aw": + 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 len(mode) > 1 or mode not in "raw": + raise ValueError("mode must be 'r', 'a' or 'w'") + 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 len(mode) > 1 or mode not in "rw": + raise ValueError("mode must be 'r' or 'w'") + + try: + import gzip + gzip.GzipFile + except (ImportError, AttributeError): + raise CompressionError("gzip module is not available") + + extfileobj = fileobj is not None + try: + fileobj = gzip.GzipFile(name, mode + "b", compresslevel, fileobj) + t = cls.taropen(name, mode, fileobj, **kwargs) + except IOError: + if not extfileobj and fileobj is not None: + fileobj.close() + if fileobj is None: + raise + raise ReadError("not a gzip file") + except: + if not extfileobj and fileobj is not None: + fileobj.close() + raise + t._extfileobj = extfileobj + 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 len(mode) > 1 or mode not in "rw": + raise ValueError("mode must be 'r' or 'w'.") + + try: + import bz2 + except ImportError: + raise CompressionError("bz2 module is not available") + + if fileobj is not None: + fileobj = _BZ2Proxy(fileobj, mode) + else: + fileobj = bz2.BZ2File(name, mode, compresslevel=compresslevel) + + try: + t = cls.taropen(name, mode, fileobj, **kwargs) + except (IOError, EOFError): + fileobj.close() + raise ReadError("not a bzip2 file") + 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 + } + + #-------------------------------------------------------------------------- + # 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 + + if self.mode in "aw": + 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)) + + if not self._extfileobj: + self.fileobj.close() + self.closed = True + + 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 for either the file `name' or the file + object `fileobj' (using os.fstat on its file descriptor). You can + modify some of the TarInfo's attributes before you add it using + addfile(). If given, `arcname' specifies an alternative name for the + file in the archive. + """ + self._check("aw") + + # 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 + + # 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): + """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. + """ + self._check() + + for tarinfo in self: + if verbose: + print(filemode(tarinfo.mode), end=' ') + print("%s/%s" % (tarinfo.uname or tarinfo.uid, + tarinfo.gname or tarinfo.gid), end=' ') + if tarinfo.ischr() or tarinfo.isblk(): + print("%10s" % ("%d,%d" \ + % (tarinfo.devmajor, tarinfo.devminor)), end=' ') + else: + print("%10d" % tarinfo.size, end=' ') + print("%d-%02d-%02d %02d:%02d:%02d" \ + % time.localtime(tarinfo.mtime)[:6], end=' ') + + print(tarinfo.name + ("/" if tarinfo.isdir() else ""), end=' ') + + if verbose: + if tarinfo.issym(): + print("->", tarinfo.linkname, end=' ') + if tarinfo.islnk(): + print("link to", tarinfo.linkname, end=' ') + print() + + def add(self, name, arcname=None, recursive=True, exclude=None, 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. `exclude' is a function that should + return True for each filename to be excluded. `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("aw") + + if arcname is None: + arcname = name + + # Exclude pathnames. + if exclude is not None: + import warnings + warnings.warn("use the filter argument instead", + DeprecationWarning, 2) + if exclude(name): + self._dbg(2, "tarfile: Excluded %r" % name) + return + + # 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(): + f = bltn_open(name, "rb") + self.addfile(tarinfo, f) + f.close() + + elif tarinfo.isdir(): + self.addfile(tarinfo) + if recursive: + for f in os.listdir(name): + self.add(os.path.join(name, f), os.path.join(arcname, f), + recursive, exclude, filter=filter) + + else: + self.addfile(tarinfo) + + def addfile(self, tarinfo, fileobj=None): + """Add the TarInfo object `tarinfo' to the archive. If `fileobj' is + given, tarinfo.size bytes are read from it and added to the archive. + You can create TarInfo objects using gettarinfo(). + On Windows platforms, `fileobj' should always be opened with mode + 'rb' to avoid irritation about the file size. + """ + self._check("aw") + + tarinfo = copy.copy(tarinfo) + + buf = tarinfo.tobuf(self.format, self.encoding, self.errors) + self.fileobj.write(buf) + self.offset += len(buf) + + # If there's data to follow, append it. + if fileobj is not None: + copyfileobj(fileobj, self.fileobj, tarinfo.size) + 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): + """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(). + """ + 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()) + + # 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) + 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): + """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. + """ + 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) + except EnvironmentError 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, a + file-like object is returned. If `member' is a link, a file-like + object is constructed from the link's target. If `member' is none of + the above, None is returned. + The file-like object is read-only and provides the following + methods: read(), readline(), readlines(), seek() and tell() + """ + self._check("r") + + if isinstance(member, str): + tarinfo = self.getmember(member) + else: + tarinfo = member + + if tarinfo.isreg(): + return self.fileobject(self, tarinfo) + + elif tarinfo.type not in SUPPORTED_TYPES: + # If a member's type is unknown, it is treated as a + # regular file. + 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): + """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) + 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 EnvironmentError as e: + if e.errno != errno.EEXIST: + raise + + def makefile(self, tarinfo, targetpath): + """Make a file called targetpath. + """ + source = self.fileobj + source.seek(tarinfo.offset_data) + target = bltn_open(targetpath, "wb") + if tarinfo.sparse is not None: + for offset, size in tarinfo.sparse: + target.seek(offset) + copyfileobj(source, target, size) + else: + copyfileobj(source, target, tarinfo.size) + target.seek(tarinfo.size) + target.truncate() + target.close() + + 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: + if tarinfo.issym(): + linkpath = os.path.join(os.path.dirname(tarinfo.name), + tarinfo.linkname) + else: + linkpath = tarinfo.linkname + else: + 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): + """Set owner of targetpath according to tarinfo. + """ + if pwd and hasattr(os, "geteuid") and os.geteuid() == 0: + # We have to be root to do so. + try: + g = grp.getgrnam(tarinfo.gname)[2] + except KeyError: + g = tarinfo.gid + try: + u = pwd.getpwnam(tarinfo.uname)[2] + except KeyError: + u = tarinfo.uid + try: + if tarinfo.issym() and hasattr(os, "lchown"): + os.lchown(targetpath, u, g) + else: + if sys.platform != "os2emx": + os.chown(targetpath, u, g) + except EnvironmentError as e: + 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 EnvironmentError as e: + 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 EnvironmentError as e: + 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 + + # Read the next block. + self.fileobj.seek(self.offset) + 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 IOError("%s is closed" % self.__class__.__name__) + if mode is not None and self.mode not in mode: + raise IOError("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 = 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: + return iter(self.members) + else: + return TarIter(self) + + 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 +# class TarFile + +class TarIter(object): + """Iterator Class. + + for tarinfo in TarFile(...): + suite... + """ + + def __init__(self, tarfile): + """Construct a TarIter object. + """ + self.tarfile = tarfile + self.index = 0 + def __iter__(self): + """Return iterator object. + """ + return self + + def __next__(self): + """Return the next item using TarFile's next() method. + When all members have been read, set TarFile as _loaded. + """ + # Fix for SF #1100429: Under rare circumstances it can + # happen that getmembers() is called during iteration, + # which will cause TarIter to stop prematurely. + if not self.tarfile._loaded: + tarinfo = self.tarfile.next() + if not tarinfo: + self.tarfile._loaded = True + raise StopIteration + else: + try: + tarinfo = self.tarfile.members[self.index] + except IndexError: + raise StopIteration + self.index += 1 + return tarinfo + + next = __next__ # for Python 2.x + +#-------------------- +# 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 + +bltn_open = open +open = TarFile.open diff --git a/venv/Lib/site-packages/pip/_vendor/distlib/compat.py b/venv/Lib/site-packages/pip/_vendor/distlib/compat.py new file mode 100644 index 0000000..e594106 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/distlib/compat.py @@ -0,0 +1,1122 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2013-2017 Vinay Sajip. +# Licensed to the Python Software Foundation under a contributor agreement. +# See LICENSE.txt and CONTRIBUTORS.txt. +# +from __future__ import absolute_import + +import os +import re +import sys + +try: + import ssl +except ImportError: # pragma: no cover + ssl = None + +if sys.version_info[0] < 3: # pragma: no cover + from StringIO import StringIO + string_types = basestring, + text_type = unicode + from types import FileType as file_type + import __builtin__ as builtins + import ConfigParser as configparser + from ._backport import shutil + from urlparse import urlparse, urlunparse, urljoin, urlsplit, urlunsplit + from urllib import (urlretrieve, quote as _quote, unquote, url2pathname, + pathname2url, ContentTooShortError, splittype) + + def quote(s): + if isinstance(s, unicode): + s = s.encode('utf-8') + return _quote(s) + + import urllib2 + from urllib2 import (Request, urlopen, URLError, HTTPError, + HTTPBasicAuthHandler, HTTPPasswordMgr, + HTTPHandler, HTTPRedirectHandler, + build_opener) + if ssl: + from urllib2 import HTTPSHandler + import httplib + import xmlrpclib + import Queue as queue + from HTMLParser import HTMLParser + import htmlentitydefs + raw_input = raw_input + from itertools import ifilter as filter + from itertools import ifilterfalse as filterfalse + + # Leaving this around for now, in case it needs resurrecting in some way + # _userprog = None + # def splituser(host): + # """splituser('user[:passwd]@host[:port]') --> 'user[:passwd]', 'host[:port]'.""" + # global _userprog + # if _userprog is None: + # import re + # _userprog = re.compile('^(.*)@(.*)$') + + # match = _userprog.match(host) + # if match: return match.group(1, 2) + # return None, host + +else: # pragma: no cover + from io import StringIO + string_types = str, + text_type = str + from io import TextIOWrapper as file_type + import builtins + import configparser + import shutil + from urllib.parse import (urlparse, urlunparse, urljoin, quote, + unquote, urlsplit, urlunsplit, splittype) + from urllib.request import (urlopen, urlretrieve, Request, url2pathname, + pathname2url, + HTTPBasicAuthHandler, HTTPPasswordMgr, + HTTPHandler, HTTPRedirectHandler, + build_opener) + if ssl: + from urllib.request import HTTPSHandler + from urllib.error import HTTPError, URLError, ContentTooShortError + import http.client as httplib + import urllib.request as urllib2 + import xmlrpc.client as xmlrpclib + import queue + from html.parser import HTMLParser + import html.entities as htmlentitydefs + raw_input = input + from itertools import filterfalse + filter = filter + + +try: + from ssl import match_hostname, CertificateError +except ImportError: # pragma: no cover + class CertificateError(ValueError): + pass + + + def _dnsname_match(dn, hostname, max_wildcards=1): + """Matching according to RFC 6125, section 6.4.3 + + http://tools.ietf.org/html/rfc6125#section-6.4.3 + """ + pats = [] + if not dn: + return False + + parts = dn.split('.') + leftmost, remainder = parts[0], parts[1:] + + wildcards = leftmost.count('*') + if wildcards > max_wildcards: + # Issue #17980: avoid denials of service by refusing more + # than one wildcard per fragment. A survey of established + # policy among SSL implementations showed it to be a + # reasonable choice. + raise CertificateError( + "too many wildcards in certificate DNS name: " + repr(dn)) + + # speed up common case w/o wildcards + if not wildcards: + return dn.lower() == hostname.lower() + + # RFC 6125, section 6.4.3, subitem 1. + # The client SHOULD NOT attempt to match a presented identifier in which + # the wildcard character comprises a label other than the left-most label. + if leftmost == '*': + # When '*' is a fragment by itself, it matches a non-empty dotless + # fragment. + pats.append('[^.]+') + elif leftmost.startswith('xn--') or hostname.startswith('xn--'): + # RFC 6125, section 6.4.3, subitem 3. + # The client SHOULD NOT attempt to match a presented identifier + # where the wildcard character is embedded within an A-label or + # U-label of an internationalized domain name. + pats.append(re.escape(leftmost)) + else: + # Otherwise, '*' matches any dotless string, e.g. www* + pats.append(re.escape(leftmost).replace(r'\*', '[^.]*')) + + # add the remaining fragments, ignore any wildcards + for frag in remainder: + pats.append(re.escape(frag)) + + pat = re.compile(r'\A' + r'\.'.join(pats) + r'\Z', re.IGNORECASE) + return pat.match(hostname) + + + def match_hostname(cert, hostname): + """Verify that *cert* (in decoded format as returned by + SSLSocket.getpeercert()) matches the *hostname*. RFC 2818 and RFC 6125 + rules are followed, but IP addresses are not accepted for *hostname*. + + CertificateError is raised on failure. On success, the function + returns nothing. + """ + if not cert: + raise ValueError("empty or no certificate, match_hostname needs a " + "SSL socket or SSL context with either " + "CERT_OPTIONAL or CERT_REQUIRED") + dnsnames = [] + san = cert.get('subjectAltName', ()) + for key, value in san: + if key == 'DNS': + if _dnsname_match(value, hostname): + return + dnsnames.append(value) + if not dnsnames: + # The subject is only checked when there is no dNSName entry + # in subjectAltName + for sub in cert.get('subject', ()): + for key, value in sub: + # XXX according to RFC 2818, the most specific Common Name + # must be used. + if key == 'commonName': + if _dnsname_match(value, hostname): + return + dnsnames.append(value) + if len(dnsnames) > 1: + raise CertificateError("hostname %r " + "doesn't match either of %s" + % (hostname, ', '.join(map(repr, dnsnames)))) + elif len(dnsnames) == 1: + raise CertificateError("hostname %r " + "doesn't match %r" + % (hostname, dnsnames[0])) + else: + raise CertificateError("no appropriate commonName or " + "subjectAltName fields were found") + + +try: + from types import SimpleNamespace as Container +except ImportError: # pragma: no cover + class Container(object): + """ + A generic container for when multiple values need to be returned + """ + def __init__(self, **kwargs): + self.__dict__.update(kwargs) + + +try: + from shutil import which +except ImportError: # pragma: no cover + # Implementation from Python 3.3 + 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", os.defpath) + 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 + + +# ZipFile is a context manager in 2.7, but not in 2.6 + +from zipfile import ZipFile as BaseZipFile + +if hasattr(BaseZipFile, '__enter__'): # pragma: no cover + ZipFile = BaseZipFile +else: # pragma: no cover + from zipfile import ZipExtFile as BaseZipExtFile + + class ZipExtFile(BaseZipExtFile): + def __init__(self, base): + self.__dict__.update(base.__dict__) + + def __enter__(self): + return self + + def __exit__(self, *exc_info): + self.close() + # return None, so if an exception occurred, it will propagate + + class ZipFile(BaseZipFile): + def __enter__(self): + return self + + def __exit__(self, *exc_info): + self.close() + # return None, so if an exception occurred, it will propagate + + def open(self, *args, **kwargs): + base = BaseZipFile.open(self, *args, **kwargs) + return ZipExtFile(base) + +try: + from platform import python_implementation +except ImportError: # pragma: no cover + def python_implementation(): + """Return a string identifying the Python implementation.""" + if 'PyPy' in sys.version: + return 'PyPy' + if os.name == 'java': + return 'Jython' + if sys.version.startswith('IronPython'): + return 'IronPython' + return 'CPython' + +try: + import sysconfig +except ImportError: # pragma: no cover + from ._backport import sysconfig + +try: + callable = callable +except NameError: # pragma: no cover + from collections.abc import Callable + + def callable(obj): + return isinstance(obj, Callable) + + +try: + fsencode = os.fsencode + fsdecode = os.fsdecode +except AttributeError: # pragma: no cover + # Issue #99: on some systems (e.g. containerised), + # sys.getfilesystemencoding() returns None, and we need a real value, + # so fall back to utf-8. From the CPython 2.7 docs relating to Unix and + # sys.getfilesystemencoding(): the return value is "the user’s preference + # according to the result of nl_langinfo(CODESET), or None if the + # nl_langinfo(CODESET) failed." + _fsencoding = sys.getfilesystemencoding() or 'utf-8' + if _fsencoding == 'mbcs': + _fserrors = 'strict' + else: + _fserrors = 'surrogateescape' + + def fsencode(filename): + if isinstance(filename, bytes): + return filename + elif isinstance(filename, text_type): + return filename.encode(_fsencoding, _fserrors) + else: + raise TypeError("expect bytes or str, not %s" % + type(filename).__name__) + + def fsdecode(filename): + if isinstance(filename, text_type): + return filename + elif isinstance(filename, bytes): + return filename.decode(_fsencoding, _fserrors) + else: + raise TypeError("expect bytes or str, not %s" % + type(filename).__name__) + +try: + from tokenize import detect_encoding +except ImportError: # pragma: no cover + from codecs import BOM_UTF8, lookup + import re + + cookie_re = re.compile(r"coding[:=]\s*([-\w.]+)") + + 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) + + matches = cookie_re.findall(line_string) + if not matches: + return None + encoding = _get_normal_name(matches[0]) + 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 codec.name != '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] + + second = read_or_stop() + if not second: + return default, [first] + + encoding = find_cookie(second) + if encoding: + return encoding, [first, second] + + return default, [first, second] + +# For converting & <-> & etc. +try: + from html import escape +except ImportError: + from cgi import escape +if sys.version_info[:2] < (3, 4): + unescape = HTMLParser().unescape +else: + from html import unescape + +try: + from collections import ChainMap +except ImportError: # pragma: no cover + from collections import MutableMapping + + try: + from reprlib import recursive_repr as _recursive_repr + except ImportError: + 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.__annotations__ = getattr(user_function, '__annotations__', {}) + return wrapper + + return decorating_function + + class ChainMap(MutableMapping): + ''' A ChainMap groups multiple dicts (or other mappings) together + to create a single, updateable view. + + The underlying mappings are stored in a list. That list is public and can + accessed or updated using the *maps* attribute. There is no other state. + + Lookups search the underlying mappings successively until a key is found. + In contrast, writes, updates, and deletions only operate on the first + mapping. + + ''' + + def __init__(self, *maps): + '''Initialize a ChainMap by setting *maps* to the given mappings. + If no mappings are provided, a single empty dictionary is used. + + ''' + self.maps = list(maps) or [{}] # always at least one map + + def __missing__(self, key): + raise KeyError(key) + + def __getitem__(self, key): + for mapping in self.maps: + try: + return mapping[key] # can't use 'key in mapping' with defaultdict + except KeyError: + pass + return self.__missing__(key) # support subclasses that define __missing__ + + def get(self, key, default=None): + return self[key] if key in self else default + + def __len__(self): + return len(set().union(*self.maps)) # reuses stored hash values if possible + + def __iter__(self): + return iter(set().union(*self.maps)) + + def __contains__(self, key): + return any(key in m for m in self.maps) + + def __bool__(self): + return any(self.maps) + + @_recursive_repr() + def __repr__(self): + return '{0.__class__.__name__}({1})'.format( + self, ', '.join(map(repr, self.maps))) + + @classmethod + def fromkeys(cls, iterable, *args): + 'Create a ChainMap with a single dict created from the iterable.' + return cls(dict.fromkeys(iterable, *args)) + + def copy(self): + 'New ChainMap or subclass with a new copy of maps[0] and refs to maps[1:]' + return self.__class__(self.maps[0].copy(), *self.maps[1:]) + + __copy__ = copy + + def new_child(self): # like Django's Context.push() + 'New ChainMap with a new dict followed by all previous maps.' + return self.__class__({}, *self.maps) + + @property + def parents(self): # like Django's Context.pop() + 'New ChainMap from maps[1:].' + return self.__class__(*self.maps[1:]) + + def __setitem__(self, key, value): + self.maps[0][key] = value + + def __delitem__(self, key): + try: + del self.maps[0][key] + except KeyError: + raise KeyError('Key not found in the first mapping: {!r}'.format(key)) + + def popitem(self): + 'Remove and return an item pair from maps[0]. Raise KeyError is maps[0] is empty.' + try: + return self.maps[0].popitem() + except KeyError: + raise KeyError('No keys found in the first mapping.') + + def pop(self, key, *args): + 'Remove *key* from maps[0] and return its value. Raise KeyError if *key* not in maps[0].' + try: + return self.maps[0].pop(key, *args) + except KeyError: + raise KeyError('Key not found in the first mapping: {!r}'.format(key)) + + def clear(self): + 'Clear maps[0], leaving maps[1:] intact.' + self.maps[0].clear() + +try: + from importlib.util import cache_from_source # Python >= 3.4 +except ImportError: # pragma: no cover + try: + from imp import cache_from_source + except ImportError: # pragma: no cover + def cache_from_source(path, debug_override=None): + assert path.endswith('.py') + if debug_override is None: + debug_override = __debug__ + if debug_override: + suffix = 'c' + else: + suffix = 'o' + return path + suffix + +try: + from collections import OrderedDict +except ImportError: # pragma: no cover +## {{{ http://code.activestate.com/recipes/576693/ (r9) +# Backport of OrderedDict() class that runs on Python 2.4, 2.5, 2.6, 2.7 and pypy. +# Passes Python2.7's test suite and incorporates all the latest updates. + try: + from thread import get_ident as _get_ident + except ImportError: + from dummy_thread import get_ident as _get_ident + + try: + from _abcoll import KeysView, ValuesView, ItemsView + except ImportError: + pass + + + class OrderedDict(dict): + 'Dictionary that remembers insertion order' + # An inherited dict maps keys to values. + # The inherited dict provides __getitem__, __len__, __contains__, and get. + # The remaining methods are order-aware. + # Big-O running times for all methods are the same as for regular dictionaries. + + # The internal self.__map dictionary maps keys to links in a doubly linked list. + # The circular doubly linked list starts and ends with a sentinel element. + # The sentinel element never gets deleted (this simplifies the algorithm). + # Each link is stored as a list of length three: [PREV, NEXT, KEY]. + + def __init__(self, *args, **kwds): + '''Initialize an ordered dictionary. Signature is the same as for + regular dictionaries, but keyword arguments are not recommended + because their insertion order is arbitrary. + + ''' + if len(args) > 1: + raise TypeError('expected at most 1 arguments, got %d' % len(args)) + try: + self.__root + except AttributeError: + self.__root = root = [] # sentinel node + root[:] = [root, root, None] + self.__map = {} + self.__update(*args, **kwds) + + def __setitem__(self, key, value, dict_setitem=dict.__setitem__): + 'od.__setitem__(i, y) <==> od[i]=y' + # Setting a new item creates a new link which goes at the end of the linked + # list, and the inherited dictionary is updated with the new key/value pair. + if key not in self: + root = self.__root + last = root[0] + last[1] = root[0] = self.__map[key] = [last, root, key] + dict_setitem(self, key, value) + + def __delitem__(self, key, dict_delitem=dict.__delitem__): + 'od.__delitem__(y) <==> del od[y]' + # Deleting an existing item uses self.__map to find the link which is + # then removed by updating the links in the predecessor and successor nodes. + dict_delitem(self, key) + link_prev, link_next, key = self.__map.pop(key) + link_prev[1] = link_next + link_next[0] = link_prev + + def __iter__(self): + 'od.__iter__() <==> iter(od)' + root = self.__root + curr = root[1] + while curr is not root: + yield curr[2] + curr = curr[1] + + def __reversed__(self): + 'od.__reversed__() <==> reversed(od)' + root = self.__root + curr = root[0] + while curr is not root: + yield curr[2] + curr = curr[0] + + def clear(self): + 'od.clear() -> None. Remove all items from od.' + try: + for node in self.__map.itervalues(): + del node[:] + root = self.__root + root[:] = [root, root, None] + self.__map.clear() + except AttributeError: + pass + dict.clear(self) + + def popitem(self, last=True): + '''od.popitem() -> (k, v), return and remove a (key, value) pair. + Pairs are returned in LIFO order if last is true or FIFO order if false. + + ''' + if not self: + raise KeyError('dictionary is empty') + root = self.__root + if last: + link = root[0] + link_prev = link[0] + link_prev[1] = root + root[0] = link_prev + else: + link = root[1] + link_next = link[1] + root[1] = link_next + link_next[0] = root + key = link[2] + del self.__map[key] + value = dict.pop(self, key) + return key, value + + # -- the following methods do not depend on the internal structure -- + + def keys(self): + 'od.keys() -> list of keys in od' + return list(self) + + def values(self): + 'od.values() -> list of values in od' + return [self[key] for key in self] + + def items(self): + 'od.items() -> list of (key, value) pairs in od' + return [(key, self[key]) for key in self] + + def iterkeys(self): + 'od.iterkeys() -> an iterator over the keys in od' + return iter(self) + + def itervalues(self): + 'od.itervalues -> an iterator over the values in od' + for k in self: + yield self[k] + + def iteritems(self): + 'od.iteritems -> an iterator over the (key, value) items in od' + for k in self: + yield (k, self[k]) + + def update(*args, **kwds): + '''od.update(E, **F) -> None. Update od from dict/iterable E and F. + + If E is a dict instance, does: for k in E: od[k] = E[k] + If E has a .keys() method, does: for k in E.keys(): od[k] = E[k] + Or if E is an iterable of items, does: for k, v in E: od[k] = v + In either case, this is followed by: for k, v in F.items(): od[k] = v + + ''' + if len(args) > 2: + raise TypeError('update() takes at most 2 positional ' + 'arguments (%d given)' % (len(args),)) + elif not args: + raise TypeError('update() takes at least 1 argument (0 given)') + self = args[0] + # Make progressively weaker assumptions about "other" + other = () + if len(args) == 2: + other = args[1] + if isinstance(other, dict): + 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 + + __update = update # let subclasses override update without breaking __init__ + + __marker = object() + + def pop(self, key, default=__marker): + '''od.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. + + ''' + if key in self: + result = self[key] + del self[key] + return result + if default is self.__marker: + raise KeyError(key) + return default + + def setdefault(self, key, default=None): + 'od.setdefault(k[,d]) -> od.get(k,d), also set od[k]=d if k not in od' + if key in self: + return self[key] + self[key] = default + return default + + def __repr__(self, _repr_running=None): + 'od.__repr__() <==> repr(od)' + if not _repr_running: _repr_running = {} + call_key = id(self), _get_ident() + if call_key in _repr_running: + return '...' + _repr_running[call_key] = 1 + try: + if not self: + return '%s()' % (self.__class__.__name__,) + return '%s(%r)' % (self.__class__.__name__, self.items()) + finally: + del _repr_running[call_key] + + def __reduce__(self): + 'Return state information for pickling' + items = [[k, self[k]] for k in self] + inst_dict = vars(self).copy() + for k in vars(OrderedDict()): + inst_dict.pop(k, None) + if inst_dict: + return (self.__class__, (items,), inst_dict) + return self.__class__, (items,) + + def copy(self): + 'od.copy() -> a shallow copy of od' + return self.__class__(self) + + @classmethod + def fromkeys(cls, iterable, value=None): + '''OD.fromkeys(S[, v]) -> New ordered dictionary with keys from S + and values equal to v (which defaults to None). + + ''' + d = cls() + for key in iterable: + d[key] = value + return d + + def __eq__(self, other): + '''od.__eq__(y) <==> od==y. Comparison to another OD is order-sensitive + while comparison to a regular mapping is order-insensitive. + + ''' + if isinstance(other, OrderedDict): + return len(self)==len(other) and self.items() == other.items() + return dict.__eq__(self, other) + + def __ne__(self, other): + return not self == other + + # -- the following methods are only used in Python 2.7 -- + + def viewkeys(self): + "od.viewkeys() -> a set-like object providing a view on od's keys" + return KeysView(self) + + def viewvalues(self): + "od.viewvalues() -> an object providing a view on od's values" + return ValuesView(self) + + def viewitems(self): + "od.viewitems() -> a set-like object providing a view on od's items" + return ItemsView(self) + +try: + from logging.config import BaseConfigurator, valid_ident +except ImportError: # pragma: no cover + IDENTIFIER = re.compile('^[a-z_][a-z0-9_]*$', re.I) + + + def valid_ident(s): + m = IDENTIFIER.match(s) + if not m: + raise ValueError('Not a valid Python identifier: %r' % s) + return True + + + # The ConvertingXXX classes are wrappers around standard Python containers, + # and they serve to convert any suitable values in the container. The + # conversion converts base dicts, lists and tuples to their wrapped + # equivalents, whereas strings which match a conversion format are converted + # appropriately. + # + # Each wrapper should have a configurator attribute holding the actual + # configurator to use for conversion. + + class ConvertingDict(dict): + """A converting dictionary wrapper.""" + + def __getitem__(self, key): + value = dict.__getitem__(self, key) + result = self.configurator.convert(value) + #If the converted value is different, save for next time + if value is not result: + self[key] = result + if type(result) in (ConvertingDict, ConvertingList, + ConvertingTuple): + result.parent = self + result.key = key + return result + + def get(self, key, default=None): + value = dict.get(self, key, default) + result = self.configurator.convert(value) + #If the converted value is different, save for next time + if value is not result: + self[key] = result + if type(result) in (ConvertingDict, ConvertingList, + ConvertingTuple): + result.parent = self + result.key = key + return result + + def pop(self, key, default=None): + value = dict.pop(self, key, default) + result = self.configurator.convert(value) + if value is not result: + if type(result) in (ConvertingDict, ConvertingList, + ConvertingTuple): + result.parent = self + result.key = key + return result + + class ConvertingList(list): + """A converting list wrapper.""" + def __getitem__(self, key): + value = list.__getitem__(self, key) + result = self.configurator.convert(value) + #If the converted value is different, save for next time + if value is not result: + self[key] = result + if type(result) in (ConvertingDict, ConvertingList, + ConvertingTuple): + result.parent = self + result.key = key + return result + + def pop(self, idx=-1): + value = list.pop(self, idx) + result = self.configurator.convert(value) + if value is not result: + if type(result) in (ConvertingDict, ConvertingList, + ConvertingTuple): + result.parent = self + return result + + class ConvertingTuple(tuple): + """A converting tuple wrapper.""" + def __getitem__(self, key): + value = tuple.__getitem__(self, key) + result = self.configurator.convert(value) + if value is not result: + if type(result) in (ConvertingDict, ConvertingList, + ConvertingTuple): + result.parent = self + result.key = key + return result + + class BaseConfigurator(object): + """ + The configurator base class which defines some useful defaults. + """ + + CONVERT_PATTERN = re.compile(r'^(?P[a-z]+)://(?P.*)$') + + WORD_PATTERN = re.compile(r'^\s*(\w+)\s*') + DOT_PATTERN = re.compile(r'^\.\s*(\w+)\s*') + INDEX_PATTERN = re.compile(r'^\[\s*(\w+)\s*\]\s*') + DIGIT_PATTERN = re.compile(r'^\d+$') + + value_converters = { + 'ext' : 'ext_convert', + 'cfg' : 'cfg_convert', + } + + # We might want to use a different one, e.g. importlib + importer = staticmethod(__import__) + + def __init__(self, config): + self.config = ConvertingDict(config) + self.config.configurator = self + + def resolve(self, s): + """ + Resolve strings to objects using standard import and attribute + syntax. + """ + name = s.split('.') + used = name.pop(0) + try: + found = self.importer(used) + for frag in name: + used += '.' + frag + try: + found = getattr(found, frag) + except AttributeError: + self.importer(used) + found = getattr(found, frag) + return found + except ImportError: + e, tb = sys.exc_info()[1:] + v = ValueError('Cannot resolve %r: %s' % (s, e)) + v.__cause__, v.__traceback__ = e, tb + raise v + + def ext_convert(self, value): + """Default converter for the ext:// protocol.""" + return self.resolve(value) + + def cfg_convert(self, value): + """Default converter for the cfg:// protocol.""" + rest = value + m = self.WORD_PATTERN.match(rest) + if m is None: + raise ValueError("Unable to convert %r" % value) + else: + rest = rest[m.end():] + d = self.config[m.groups()[0]] + #print d, rest + while rest: + m = self.DOT_PATTERN.match(rest) + if m: + d = d[m.groups()[0]] + else: + m = self.INDEX_PATTERN.match(rest) + if m: + idx = m.groups()[0] + if not self.DIGIT_PATTERN.match(idx): + d = d[idx] + else: + try: + n = int(idx) # try as number first (most likely) + d = d[n] + except TypeError: + d = d[idx] + if m: + rest = rest[m.end():] + else: + raise ValueError('Unable to convert ' + '%r at %r' % (value, rest)) + #rest should be empty + return d + + def convert(self, value): + """ + Convert values to an appropriate type. dicts, lists and tuples are + replaced by their converting alternatives. Strings are checked to + see if they have a conversion format and are converted if they do. + """ + if not isinstance(value, ConvertingDict) and isinstance(value, dict): + value = ConvertingDict(value) + value.configurator = self + elif not isinstance(value, ConvertingList) and isinstance(value, list): + value = ConvertingList(value) + value.configurator = self + elif not isinstance(value, ConvertingTuple) and\ + isinstance(value, tuple): + value = ConvertingTuple(value) + value.configurator = self + elif isinstance(value, string_types): + m = self.CONVERT_PATTERN.match(value) + if m: + d = m.groupdict() + prefix = d['prefix'] + converter = self.value_converters.get(prefix, None) + if converter: + suffix = d['suffix'] + converter = getattr(self, converter) + value = converter(suffix) + return value + + def configure_custom(self, config): + """Configure an object with a user-supplied factory.""" + c = config.pop('()') + if not callable(c): + c = self.resolve(c) + props = config.pop('.', None) + # Check for valid identifiers + kwargs = dict([(k, config[k]) for k in config if valid_ident(k)]) + result = c(**kwargs) + if props: + for name, value in props.items(): + setattr(result, name, value) + return result + + def as_tuple(self, value): + """Utility function which converts lists to tuples.""" + if isinstance(value, list): + value = tuple(value) + return value diff --git a/venv/Lib/site-packages/pip/_vendor/distlib/database.py b/venv/Lib/site-packages/pip/_vendor/distlib/database.py new file mode 100644 index 0000000..0a90c30 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/distlib/database.py @@ -0,0 +1,1339 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2012-2017 The Python Software Foundation. +# See LICENSE.txt and CONTRIBUTORS.txt. +# +"""PEP 376 implementation.""" + +from __future__ import unicode_literals + +import base64 +import codecs +import contextlib +import hashlib +import logging +import os +import posixpath +import sys +import zipimport + +from . import DistlibException, resources +from .compat import StringIO +from .version import get_scheme, UnsupportedVersionError +from .metadata import (Metadata, METADATA_FILENAME, WHEEL_METADATA_FILENAME, + LEGACY_METADATA_FILENAME) +from .util import (parse_requirement, cached_property, parse_name_and_version, + read_exports, write_exports, CSVReader, CSVWriter) + + +__all__ = ['Distribution', 'BaseInstalledDistribution', + 'InstalledDistribution', 'EggInfoDistribution', + 'DistributionPath'] + + +logger = logging.getLogger(__name__) + +EXPORTS_FILENAME = 'pydist-exports.json' +COMMANDS_FILENAME = 'pydist-commands.json' + +DIST_FILES = ('INSTALLER', METADATA_FILENAME, 'RECORD', 'REQUESTED', + 'RESOURCES', EXPORTS_FILENAME, 'SHARED') + +DISTINFO_EXT = '.dist-info' + + +class _Cache(object): + """ + A simple cache mapping names and .dist-info paths to distributions + """ + def __init__(self): + """ + Initialise an instance. There is normally one for each DistributionPath. + """ + self.name = {} + self.path = {} + self.generated = False + + def clear(self): + """ + Clear the cache, setting it to its initial state. + """ + self.name.clear() + self.path.clear() + self.generated = False + + def add(self, dist): + """ + Add a distribution to the cache. + :param dist: The distribution to add. + """ + if dist.path not in self.path: + self.path[dist.path] = dist + self.name.setdefault(dist.key, []).append(dist) + + +class DistributionPath(object): + """ + Represents a set of distributions installed on a path (typically sys.path). + """ + def __init__(self, path=None, include_egg=False): + """ + Create an instance from a path, optionally including legacy (distutils/ + setuptools/distribute) distributions. + :param path: The path to use, as a list of directories. If not specified, + sys.path is used. + :param include_egg: If True, this instance will look for and return legacy + distributions as well as those based on PEP 376. + """ + if path is None: + path = sys.path + self.path = path + self._include_dist = True + self._include_egg = include_egg + + self._cache = _Cache() + self._cache_egg = _Cache() + self._cache_enabled = True + self._scheme = get_scheme('default') + + def _get_cache_enabled(self): + return self._cache_enabled + + def _set_cache_enabled(self, value): + self._cache_enabled = value + + cache_enabled = property(_get_cache_enabled, _set_cache_enabled) + + def clear_cache(self): + """ + Clears the internal cache. + """ + self._cache.clear() + self._cache_egg.clear() + + + def _yield_distributions(self): + """ + Yield .dist-info and/or .egg(-info) distributions. + """ + # We need to check if we've seen some resources already, because on + # some Linux systems (e.g. some Debian/Ubuntu variants) there are + # symlinks which alias other files in the environment. + seen = set() + for path in self.path: + finder = resources.finder_for_path(path) + if finder is None: + continue + r = finder.find('') + if not r or not r.is_container: + continue + rset = sorted(r.resources) + for entry in rset: + r = finder.find(entry) + if not r or r.path in seen: + continue + if self._include_dist and entry.endswith(DISTINFO_EXT): + possible_filenames = [METADATA_FILENAME, + WHEEL_METADATA_FILENAME, + LEGACY_METADATA_FILENAME] + for metadata_filename in possible_filenames: + metadata_path = posixpath.join(entry, metadata_filename) + pydist = finder.find(metadata_path) + if pydist: + break + else: + continue + + with contextlib.closing(pydist.as_stream()) as stream: + metadata = Metadata(fileobj=stream, scheme='legacy') + logger.debug('Found %s', r.path) + seen.add(r.path) + yield new_dist_class(r.path, metadata=metadata, + env=self) + elif self._include_egg and entry.endswith(('.egg-info', + '.egg')): + logger.debug('Found %s', r.path) + seen.add(r.path) + yield old_dist_class(r.path, self) + + def _generate_cache(self): + """ + Scan the path for distributions and populate the cache with + those that are found. + """ + gen_dist = not self._cache.generated + gen_egg = self._include_egg and not self._cache_egg.generated + if gen_dist or gen_egg: + for dist in self._yield_distributions(): + if isinstance(dist, InstalledDistribution): + self._cache.add(dist) + else: + self._cache_egg.add(dist) + + if gen_dist: + self._cache.generated = True + if gen_egg: + self._cache_egg.generated = True + + @classmethod + def distinfo_dirname(cls, name, version): + """ + The *name* and *version* parameters are converted into their + filename-escaped form, i.e. any ``'-'`` characters are replaced + with ``'_'`` other than the one in ``'dist-info'`` and the one + separating the name from the version number. + + :parameter name: is converted to a standard distribution name by replacing + any runs of non- alphanumeric characters with a single + ``'-'``. + :type name: string + :parameter version: is converted to a standard version string. Spaces + become dots, and all other non-alphanumeric characters + (except dots) become dashes, with runs of multiple + dashes condensed to a single dash. + :type version: string + :returns: directory name + :rtype: string""" + name = name.replace('-', '_') + return '-'.join([name, version]) + DISTINFO_EXT + + def get_distributions(self): + """ + Provides an iterator that looks for distributions and returns + :class:`InstalledDistribution` or + :class:`EggInfoDistribution` instances for each one of them. + + :rtype: iterator of :class:`InstalledDistribution` and + :class:`EggInfoDistribution` instances + """ + if not self._cache_enabled: + for dist in self._yield_distributions(): + yield dist + else: + self._generate_cache() + + for dist in self._cache.path.values(): + yield dist + + if self._include_egg: + for dist in self._cache_egg.path.values(): + yield dist + + def get_distribution(self, name): + """ + Looks for a named distribution on the path. + + This function only returns the first result found, as no more than one + value is expected. If nothing is found, ``None`` is returned. + + :rtype: :class:`InstalledDistribution`, :class:`EggInfoDistribution` + or ``None`` + """ + result = None + name = name.lower() + if not self._cache_enabled: + for dist in self._yield_distributions(): + if dist.key == name: + result = dist + break + else: + self._generate_cache() + + if name in self._cache.name: + result = self._cache.name[name][0] + elif self._include_egg and name in self._cache_egg.name: + result = self._cache_egg.name[name][0] + return result + + def provides_distribution(self, name, version=None): + """ + Iterates over all distributions to find which distributions provide *name*. + If a *version* is provided, it will be used to filter the results. + + This function only returns the first result found, since no more than + one values are expected. If the directory is not found, returns ``None``. + + :parameter version: a version specifier that indicates the version + required, conforming to the format in ``PEP-345`` + + :type name: string + :type version: string + """ + matcher = None + if version is not None: + try: + matcher = self._scheme.matcher('%s (%s)' % (name, version)) + except ValueError: + raise DistlibException('invalid name or version: %r, %r' % + (name, version)) + + for dist in self.get_distributions(): + # We hit a problem on Travis where enum34 was installed and doesn't + # have a provides attribute ... + if not hasattr(dist, 'provides'): + logger.debug('No "provides": %s', dist) + else: + provided = dist.provides + + for p in provided: + p_name, p_ver = parse_name_and_version(p) + if matcher is None: + if p_name == name: + yield dist + break + else: + if p_name == name and matcher.match(p_ver): + yield dist + break + + def get_file_path(self, name, relative_path): + """ + Return the path to a resource file. + """ + dist = self.get_distribution(name) + if dist is None: + raise LookupError('no distribution named %r found' % name) + return dist.get_resource_path(relative_path) + + def get_exported_entries(self, category, name=None): + """ + Return all of the exported entries in a particular category. + + :param category: The category to search for entries. + :param name: If specified, only entries with that name are returned. + """ + for dist in self.get_distributions(): + r = dist.exports + if category in r: + d = r[category] + if name is not None: + if name in d: + yield d[name] + else: + for v in d.values(): + yield v + + +class Distribution(object): + """ + A base class for distributions, whether installed or from indexes. + Either way, it must have some metadata, so that's all that's needed + for construction. + """ + + build_time_dependency = False + """ + Set to True if it's known to be only a build-time dependency (i.e. + not needed after installation). + """ + + requested = False + """A boolean that indicates whether the ``REQUESTED`` metadata file is + present (in other words, whether the package was installed by user + request or it was installed as a dependency).""" + + def __init__(self, metadata): + """ + Initialise an instance. + :param metadata: The instance of :class:`Metadata` describing this + distribution. + """ + self.metadata = metadata + self.name = metadata.name + self.key = self.name.lower() # for case-insensitive comparisons + self.version = metadata.version + self.locator = None + self.digest = None + self.extras = None # additional features requested + self.context = None # environment marker overrides + self.download_urls = set() + self.digests = {} + + @property + def source_url(self): + """ + The source archive download URL for this distribution. + """ + return self.metadata.source_url + + download_url = source_url # Backward compatibility + + @property + def name_and_version(self): + """ + A utility property which displays the name and version in parentheses. + """ + return '%s (%s)' % (self.name, self.version) + + @property + def provides(self): + """ + A set of distribution names and versions provided by this distribution. + :return: A set of "name (version)" strings. + """ + plist = self.metadata.provides + s = '%s (%s)' % (self.name, self.version) + if s not in plist: + plist.append(s) + return plist + + def _get_requirements(self, req_attr): + md = self.metadata + logger.debug('Getting requirements from metadata %r', md.todict()) + reqts = getattr(md, req_attr) + return set(md.get_requirements(reqts, extras=self.extras, + env=self.context)) + + @property + def run_requires(self): + return self._get_requirements('run_requires') + + @property + def meta_requires(self): + return self._get_requirements('meta_requires') + + @property + def build_requires(self): + return self._get_requirements('build_requires') + + @property + def test_requires(self): + return self._get_requirements('test_requires') + + @property + def dev_requires(self): + return self._get_requirements('dev_requires') + + def matches_requirement(self, req): + """ + Say if this instance matches (fulfills) a requirement. + :param req: The requirement to match. + :rtype req: str + :return: True if it matches, else False. + """ + # Requirement may contain extras - parse to lose those + # from what's passed to the matcher + r = parse_requirement(req) + scheme = get_scheme(self.metadata.scheme) + try: + matcher = scheme.matcher(r.requirement) + except UnsupportedVersionError: + # XXX compat-mode if cannot read the version + logger.warning('could not read version %r - using name only', + req) + name = req.split()[0] + matcher = scheme.matcher(name) + + name = matcher.key # case-insensitive + + result = False + for p in self.provides: + p_name, p_ver = parse_name_and_version(p) + if p_name != name: + continue + try: + result = matcher.match(p_ver) + break + except UnsupportedVersionError: + pass + return result + + def __repr__(self): + """ + Return a textual representation of this instance, + """ + if self.source_url: + suffix = ' [%s]' % self.source_url + else: + suffix = '' + return '' % (self.name, self.version, suffix) + + def __eq__(self, other): + """ + See if this distribution is the same as another. + :param other: The distribution to compare with. To be equal to one + another. distributions must have the same type, name, + version and source_url. + :return: True if it is the same, else False. + """ + if type(other) is not type(self): + result = False + else: + result = (self.name == other.name and + self.version == other.version and + self.source_url == other.source_url) + return result + + def __hash__(self): + """ + Compute hash in a way which matches the equality test. + """ + return hash(self.name) + hash(self.version) + hash(self.source_url) + + +class BaseInstalledDistribution(Distribution): + """ + This is the base class for installed distributions (whether PEP 376 or + legacy). + """ + + hasher = None + + def __init__(self, metadata, path, env=None): + """ + Initialise an instance. + :param metadata: An instance of :class:`Metadata` which describes the + distribution. This will normally have been initialised + from a metadata file in the ``path``. + :param path: The path of the ``.dist-info`` or ``.egg-info`` + directory for the distribution. + :param env: This is normally the :class:`DistributionPath` + instance where this distribution was found. + """ + super(BaseInstalledDistribution, self).__init__(metadata) + self.path = path + self.dist_path = env + + def get_hash(self, data, hasher=None): + """ + Get the hash of some data, using a particular hash algorithm, if + specified. + + :param data: The data to be hashed. + :type data: bytes + :param hasher: The name of a hash implementation, supported by hashlib, + or ``None``. Examples of valid values are ``'sha1'``, + ``'sha224'``, ``'sha384'``, '``sha256'``, ``'md5'`` and + ``'sha512'``. If no hasher is specified, the ``hasher`` + attribute of the :class:`InstalledDistribution` instance + is used. If the hasher is determined to be ``None``, MD5 + is used as the hashing algorithm. + :returns: The hash of the data. If a hasher was explicitly specified, + the returned hash will be prefixed with the specified hasher + followed by '='. + :rtype: str + """ + if hasher is None: + hasher = self.hasher + if hasher is None: + hasher = hashlib.md5 + prefix = '' + else: + hasher = getattr(hashlib, hasher) + prefix = '%s=' % self.hasher + digest = hasher(data).digest() + digest = base64.urlsafe_b64encode(digest).rstrip(b'=').decode('ascii') + return '%s%s' % (prefix, digest) + + +class InstalledDistribution(BaseInstalledDistribution): + """ + Created with the *path* of the ``.dist-info`` directory provided to the + constructor. It reads the metadata contained in ``pydist.json`` when it is + instantiated., or uses a passed in Metadata instance (useful for when + dry-run mode is being used). + """ + + hasher = 'sha256' + + def __init__(self, path, metadata=None, env=None): + self.modules = [] + self.finder = finder = resources.finder_for_path(path) + if finder is None: + raise ValueError('finder unavailable for %s' % path) + if env and env._cache_enabled and path in env._cache.path: + metadata = env._cache.path[path].metadata + elif metadata is None: + r = finder.find(METADATA_FILENAME) + # Temporary - for Wheel 0.23 support + if r is None: + r = finder.find(WHEEL_METADATA_FILENAME) + # Temporary - for legacy support + if r is None: + r = finder.find(LEGACY_METADATA_FILENAME) + if r is None: + raise ValueError('no %s found in %s' % (METADATA_FILENAME, + path)) + with contextlib.closing(r.as_stream()) as stream: + metadata = Metadata(fileobj=stream, scheme='legacy') + + super(InstalledDistribution, self).__init__(metadata, path, env) + + if env and env._cache_enabled: + env._cache.add(self) + + r = finder.find('REQUESTED') + self.requested = r is not None + p = os.path.join(path, 'top_level.txt') + if os.path.exists(p): + with open(p, 'rb') as f: + data = f.read().decode('utf-8') + self.modules = data.splitlines() + + def __repr__(self): + return '' % ( + self.name, self.version, self.path) + + def __str__(self): + return "%s %s" % (self.name, self.version) + + def _get_records(self): + """ + Get the list of installed files for the distribution + :return: A list of tuples of path, hash and size. Note that hash and + size might be ``None`` for some entries. The path is exactly + as stored in the file (which is as in PEP 376). + """ + results = [] + r = self.get_distinfo_resource('RECORD') + with contextlib.closing(r.as_stream()) as stream: + with CSVReader(stream=stream) as record_reader: + # Base location is parent dir of .dist-info dir + #base_location = os.path.dirname(self.path) + #base_location = os.path.abspath(base_location) + for row in record_reader: + missing = [None for i in range(len(row), 3)] + path, checksum, size = row + missing + #if not os.path.isabs(path): + # path = path.replace('/', os.sep) + # path = os.path.join(base_location, path) + results.append((path, checksum, size)) + return results + + @cached_property + def exports(self): + """ + Return the information exported by this distribution. + :return: A dictionary of exports, mapping an export category to a dict + of :class:`ExportEntry` instances describing the individual + export entries, and keyed by name. + """ + result = {} + r = self.get_distinfo_resource(EXPORTS_FILENAME) + if r: + result = self.read_exports() + return result + + def read_exports(self): + """ + Read exports data from a file in .ini format. + + :return: A dictionary of exports, mapping an export category to a list + of :class:`ExportEntry` instances describing the individual + export entries. + """ + result = {} + r = self.get_distinfo_resource(EXPORTS_FILENAME) + if r: + with contextlib.closing(r.as_stream()) as stream: + result = read_exports(stream) + return result + + def write_exports(self, exports): + """ + Write a dictionary of exports to a file in .ini format. + :param exports: A dictionary of exports, mapping an export category to + a list of :class:`ExportEntry` instances describing the + individual export entries. + """ + rf = self.get_distinfo_file(EXPORTS_FILENAME) + with open(rf, 'w') as f: + write_exports(exports, f) + + def get_resource_path(self, relative_path): + """ + NOTE: This API may change in the future. + + Return the absolute path to a resource file with the given relative + path. + + :param relative_path: The path, relative to .dist-info, of the resource + of interest. + :return: The absolute path where the resource is to be found. + """ + r = self.get_distinfo_resource('RESOURCES') + with contextlib.closing(r.as_stream()) as stream: + with CSVReader(stream=stream) as resources_reader: + for relative, destination in resources_reader: + if relative == relative_path: + return destination + raise KeyError('no resource file with relative path %r ' + 'is installed' % relative_path) + + def list_installed_files(self): + """ + Iterates over the ``RECORD`` entries and returns a tuple + ``(path, hash, size)`` for each line. + + :returns: iterator of (path, hash, size) + """ + for result in self._get_records(): + yield result + + def write_installed_files(self, paths, prefix, dry_run=False): + """ + Writes the ``RECORD`` file, using the ``paths`` iterable passed in. Any + existing ``RECORD`` file is silently overwritten. + + prefix is used to determine when to write absolute paths. + """ + prefix = os.path.join(prefix, '') + base = os.path.dirname(self.path) + base_under_prefix = base.startswith(prefix) + base = os.path.join(base, '') + record_path = self.get_distinfo_file('RECORD') + logger.info('creating %s', record_path) + if dry_run: + return None + with CSVWriter(record_path) as writer: + for path in paths: + if os.path.isdir(path) or path.endswith(('.pyc', '.pyo')): + # do not put size and hash, as in PEP-376 + hash_value = size = '' + else: + size = '%d' % os.path.getsize(path) + with open(path, 'rb') as fp: + hash_value = self.get_hash(fp.read()) + if path.startswith(base) or (base_under_prefix and + path.startswith(prefix)): + path = os.path.relpath(path, base) + writer.writerow((path, hash_value, size)) + + # add the RECORD file itself + if record_path.startswith(base): + record_path = os.path.relpath(record_path, base) + writer.writerow((record_path, '', '')) + return record_path + + def check_installed_files(self): + """ + Checks that the hashes and sizes of the files in ``RECORD`` are + matched by the files themselves. Returns a (possibly empty) list of + mismatches. Each entry in the mismatch list will be a tuple consisting + of the path, 'exists', 'size' or 'hash' according to what didn't match + (existence is checked first, then size, then hash), the expected + value and the actual value. + """ + mismatches = [] + base = os.path.dirname(self.path) + record_path = self.get_distinfo_file('RECORD') + for path, hash_value, size in self.list_installed_files(): + if not os.path.isabs(path): + path = os.path.join(base, path) + if path == record_path: + continue + if not os.path.exists(path): + mismatches.append((path, 'exists', True, False)) + elif os.path.isfile(path): + actual_size = str(os.path.getsize(path)) + if size and actual_size != size: + mismatches.append((path, 'size', size, actual_size)) + elif hash_value: + if '=' in hash_value: + hasher = hash_value.split('=', 1)[0] + else: + hasher = None + + with open(path, 'rb') as f: + actual_hash = self.get_hash(f.read(), hasher) + if actual_hash != hash_value: + mismatches.append((path, 'hash', hash_value, actual_hash)) + return mismatches + + @cached_property + def shared_locations(self): + """ + A dictionary of shared locations whose keys are in the set 'prefix', + 'purelib', 'platlib', 'scripts', 'headers', 'data' and 'namespace'. + The corresponding value is the absolute path of that category for + this distribution, and takes into account any paths selected by the + user at installation time (e.g. via command-line arguments). In the + case of the 'namespace' key, this would be a list of absolute paths + for the roots of namespace packages in this distribution. + + The first time this property is accessed, the relevant information is + read from the SHARED file in the .dist-info directory. + """ + result = {} + shared_path = os.path.join(self.path, 'SHARED') + if os.path.isfile(shared_path): + with codecs.open(shared_path, 'r', encoding='utf-8') as f: + lines = f.read().splitlines() + for line in lines: + key, value = line.split('=', 1) + if key == 'namespace': + result.setdefault(key, []).append(value) + else: + result[key] = value + return result + + def write_shared_locations(self, paths, dry_run=False): + """ + Write shared location information to the SHARED file in .dist-info. + :param paths: A dictionary as described in the documentation for + :meth:`shared_locations`. + :param dry_run: If True, the action is logged but no file is actually + written. + :return: The path of the file written to. + """ + shared_path = os.path.join(self.path, 'SHARED') + logger.info('creating %s', shared_path) + if dry_run: + return None + lines = [] + for key in ('prefix', 'lib', 'headers', 'scripts', 'data'): + path = paths[key] + if os.path.isdir(paths[key]): + lines.append('%s=%s' % (key, path)) + for ns in paths.get('namespace', ()): + lines.append('namespace=%s' % ns) + + with codecs.open(shared_path, 'w', encoding='utf-8') as f: + f.write('\n'.join(lines)) + return shared_path + + def get_distinfo_resource(self, path): + if path not in DIST_FILES: + raise DistlibException('invalid path for a dist-info file: ' + '%r at %r' % (path, self.path)) + finder = resources.finder_for_path(self.path) + if finder is None: + raise DistlibException('Unable to get a finder for %s' % self.path) + return finder.find(path) + + def get_distinfo_file(self, path): + """ + Returns a path located under the ``.dist-info`` directory. Returns a + string representing the path. + + :parameter path: a ``'/'``-separated path relative to the + ``.dist-info`` directory or an absolute path; + If *path* is an absolute path and doesn't start + with the ``.dist-info`` directory path, + a :class:`DistlibException` is raised + :type path: str + :rtype: str + """ + # Check if it is an absolute path # XXX use relpath, add tests + if path.find(os.sep) >= 0: + # it's an absolute path? + distinfo_dirname, path = path.split(os.sep)[-2:] + if distinfo_dirname != self.path.split(os.sep)[-1]: + raise DistlibException( + 'dist-info file %r does not belong to the %r %s ' + 'distribution' % (path, self.name, self.version)) + + # The file must be relative + if path not in DIST_FILES: + raise DistlibException('invalid path for a dist-info file: ' + '%r at %r' % (path, self.path)) + + return os.path.join(self.path, path) + + def list_distinfo_files(self): + """ + Iterates over the ``RECORD`` entries and returns paths for each line if + the path is pointing to a file located in the ``.dist-info`` directory + or one of its subdirectories. + + :returns: iterator of paths + """ + base = os.path.dirname(self.path) + for path, checksum, size in self._get_records(): + # XXX add separator or use real relpath algo + if not os.path.isabs(path): + path = os.path.join(base, path) + if path.startswith(self.path): + yield path + + def __eq__(self, other): + return (isinstance(other, InstalledDistribution) and + self.path == other.path) + + # See http://docs.python.org/reference/datamodel#object.__hash__ + __hash__ = object.__hash__ + + +class EggInfoDistribution(BaseInstalledDistribution): + """Created with the *path* of the ``.egg-info`` directory or file provided + to the constructor. It reads the metadata contained in the file itself, or + if the given path happens to be a directory, the metadata is read from the + file ``PKG-INFO`` under that directory.""" + + requested = True # as we have no way of knowing, assume it was + shared_locations = {} + + def __init__(self, path, env=None): + def set_name_and_version(s, n, v): + s.name = n + s.key = n.lower() # for case-insensitive comparisons + s.version = v + + self.path = path + self.dist_path = env + if env and env._cache_enabled and path in env._cache_egg.path: + metadata = env._cache_egg.path[path].metadata + set_name_and_version(self, metadata.name, metadata.version) + else: + metadata = self._get_metadata(path) + + # Need to be set before caching + set_name_and_version(self, metadata.name, metadata.version) + + if env and env._cache_enabled: + env._cache_egg.add(self) + super(EggInfoDistribution, self).__init__(metadata, path, env) + + def _get_metadata(self, path): + requires = None + + def parse_requires_data(data): + """Create a list of dependencies from a requires.txt file. + + *data*: the contents of a setuptools-produced requires.txt file. + """ + reqs = [] + lines = data.splitlines() + for line in lines: + line = line.strip() + if line.startswith('['): + logger.warning('Unexpected line: quitting requirement scan: %r', + line) + break + r = parse_requirement(line) + if not r: + logger.warning('Not recognised as a requirement: %r', line) + continue + if r.extras: + logger.warning('extra requirements in requires.txt are ' + 'not supported') + if not r.constraints: + reqs.append(r.name) + else: + cons = ', '.join('%s%s' % c for c in r.constraints) + reqs.append('%s (%s)' % (r.name, cons)) + return reqs + + def parse_requires_path(req_path): + """Create a list of dependencies from a requires.txt file. + + *req_path*: the path to a setuptools-produced requires.txt file. + """ + + reqs = [] + try: + with codecs.open(req_path, 'r', 'utf-8') as fp: + reqs = parse_requires_data(fp.read()) + except IOError: + pass + return reqs + + tl_path = tl_data = None + if path.endswith('.egg'): + if os.path.isdir(path): + p = os.path.join(path, 'EGG-INFO') + meta_path = os.path.join(p, 'PKG-INFO') + metadata = Metadata(path=meta_path, scheme='legacy') + req_path = os.path.join(p, 'requires.txt') + tl_path = os.path.join(p, 'top_level.txt') + requires = parse_requires_path(req_path) + else: + # FIXME handle the case where zipfile is not available + zipf = zipimport.zipimporter(path) + fileobj = StringIO( + zipf.get_data('EGG-INFO/PKG-INFO').decode('utf8')) + metadata = Metadata(fileobj=fileobj, scheme='legacy') + try: + data = zipf.get_data('EGG-INFO/requires.txt') + tl_data = zipf.get_data('EGG-INFO/top_level.txt').decode('utf-8') + requires = parse_requires_data(data.decode('utf-8')) + except IOError: + requires = None + elif path.endswith('.egg-info'): + if os.path.isdir(path): + req_path = os.path.join(path, 'requires.txt') + requires = parse_requires_path(req_path) + path = os.path.join(path, 'PKG-INFO') + tl_path = os.path.join(path, 'top_level.txt') + metadata = Metadata(path=path, scheme='legacy') + else: + raise DistlibException('path must end with .egg-info or .egg, ' + 'got %r' % path) + + if requires: + metadata.add_requirements(requires) + # look for top-level modules in top_level.txt, if present + if tl_data is None: + if tl_path is not None and os.path.exists(tl_path): + with open(tl_path, 'rb') as f: + tl_data = f.read().decode('utf-8') + if not tl_data: + tl_data = [] + else: + tl_data = tl_data.splitlines() + self.modules = tl_data + return metadata + + def __repr__(self): + return '' % ( + self.name, self.version, self.path) + + def __str__(self): + return "%s %s" % (self.name, self.version) + + def check_installed_files(self): + """ + Checks that the hashes and sizes of the files in ``RECORD`` are + matched by the files themselves. Returns a (possibly empty) list of + mismatches. Each entry in the mismatch list will be a tuple consisting + of the path, 'exists', 'size' or 'hash' according to what didn't match + (existence is checked first, then size, then hash), the expected + value and the actual value. + """ + mismatches = [] + record_path = os.path.join(self.path, 'installed-files.txt') + if os.path.exists(record_path): + for path, _, _ in self.list_installed_files(): + if path == record_path: + continue + if not os.path.exists(path): + mismatches.append((path, 'exists', True, False)) + return mismatches + + def list_installed_files(self): + """ + Iterates over the ``installed-files.txt`` entries and returns a tuple + ``(path, hash, size)`` for each line. + + :returns: a list of (path, hash, size) + """ + + def _md5(path): + f = open(path, 'rb') + try: + content = f.read() + finally: + f.close() + return hashlib.md5(content).hexdigest() + + def _size(path): + return os.stat(path).st_size + + record_path = os.path.join(self.path, 'installed-files.txt') + result = [] + if os.path.exists(record_path): + with codecs.open(record_path, 'r', encoding='utf-8') as f: + for line in f: + line = line.strip() + p = os.path.normpath(os.path.join(self.path, line)) + # "./" is present as a marker between installed files + # and installation metadata files + if not os.path.exists(p): + logger.warning('Non-existent file: %s', p) + if p.endswith(('.pyc', '.pyo')): + continue + #otherwise fall through and fail + if not os.path.isdir(p): + result.append((p, _md5(p), _size(p))) + result.append((record_path, None, None)) + return result + + def list_distinfo_files(self, absolute=False): + """ + Iterates over the ``installed-files.txt`` entries and returns paths for + each line if the path is pointing to a file located in the + ``.egg-info`` directory or one of its subdirectories. + + :parameter absolute: If *absolute* is ``True``, each returned path is + transformed into a local absolute path. Otherwise the + raw value from ``installed-files.txt`` is returned. + :type absolute: boolean + :returns: iterator of paths + """ + record_path = os.path.join(self.path, 'installed-files.txt') + if os.path.exists(record_path): + skip = True + with codecs.open(record_path, 'r', encoding='utf-8') as f: + for line in f: + line = line.strip() + if line == './': + skip = False + continue + if not skip: + p = os.path.normpath(os.path.join(self.path, line)) + if p.startswith(self.path): + if absolute: + yield p + else: + yield line + + def __eq__(self, other): + return (isinstance(other, EggInfoDistribution) and + self.path == other.path) + + # See http://docs.python.org/reference/datamodel#object.__hash__ + __hash__ = object.__hash__ + +new_dist_class = InstalledDistribution +old_dist_class = EggInfoDistribution + + +class DependencyGraph(object): + """ + Represents a dependency graph between distributions. + + The dependency relationships are stored in an ``adjacency_list`` that maps + distributions to a list of ``(other, label)`` tuples where ``other`` + is a distribution and the edge is labeled with ``label`` (i.e. the version + specifier, if such was provided). Also, for more efficient traversal, for + every distribution ``x``, a list of predecessors is kept in + ``reverse_list[x]``. An edge from distribution ``a`` to + distribution ``b`` means that ``a`` depends on ``b``. If any missing + dependencies are found, they are stored in ``missing``, which is a + dictionary that maps distributions to a list of requirements that were not + provided by any other distributions. + """ + + def __init__(self): + self.adjacency_list = {} + self.reverse_list = {} + self.missing = {} + + def add_distribution(self, distribution): + """Add the *distribution* to the graph. + + :type distribution: :class:`distutils2.database.InstalledDistribution` + or :class:`distutils2.database.EggInfoDistribution` + """ + self.adjacency_list[distribution] = [] + self.reverse_list[distribution] = [] + #self.missing[distribution] = [] + + def add_edge(self, x, y, label=None): + """Add an edge from distribution *x* to distribution *y* with the given + *label*. + + :type x: :class:`distutils2.database.InstalledDistribution` or + :class:`distutils2.database.EggInfoDistribution` + :type y: :class:`distutils2.database.InstalledDistribution` or + :class:`distutils2.database.EggInfoDistribution` + :type label: ``str`` or ``None`` + """ + self.adjacency_list[x].append((y, label)) + # multiple edges are allowed, so be careful + if x not in self.reverse_list[y]: + self.reverse_list[y].append(x) + + def add_missing(self, distribution, requirement): + """ + Add a missing *requirement* for the given *distribution*. + + :type distribution: :class:`distutils2.database.InstalledDistribution` + or :class:`distutils2.database.EggInfoDistribution` + :type requirement: ``str`` + """ + logger.debug('%s missing %r', distribution, requirement) + self.missing.setdefault(distribution, []).append(requirement) + + def _repr_dist(self, dist): + return '%s %s' % (dist.name, dist.version) + + def repr_node(self, dist, level=1): + """Prints only a subgraph""" + output = [self._repr_dist(dist)] + for other, label in self.adjacency_list[dist]: + dist = self._repr_dist(other) + if label is not None: + dist = '%s [%s]' % (dist, label) + output.append(' ' * level + str(dist)) + suboutput = self.repr_node(other, level + 1) + subs = suboutput.split('\n') + output.extend(subs[1:]) + return '\n'.join(output) + + def to_dot(self, f, skip_disconnected=True): + """Writes a DOT output for the graph to the provided file *f*. + + If *skip_disconnected* is set to ``True``, then all distributions + that are not dependent on any other distribution are skipped. + + :type f: has to support ``file``-like operations + :type skip_disconnected: ``bool`` + """ + disconnected = [] + + f.write("digraph dependencies {\n") + for dist, adjs in self.adjacency_list.items(): + if len(adjs) == 0 and not skip_disconnected: + disconnected.append(dist) + for other, label in adjs: + if not label is None: + f.write('"%s" -> "%s" [label="%s"]\n' % + (dist.name, other.name, label)) + else: + f.write('"%s" -> "%s"\n' % (dist.name, other.name)) + if not skip_disconnected and len(disconnected) > 0: + f.write('subgraph disconnected {\n') + f.write('label = "Disconnected"\n') + f.write('bgcolor = red\n') + + for dist in disconnected: + f.write('"%s"' % dist.name) + f.write('\n') + f.write('}\n') + f.write('}\n') + + def topological_sort(self): + """ + Perform a topological sort of the graph. + :return: A tuple, the first element of which is a topologically sorted + list of distributions, and the second element of which is a + list of distributions that cannot be sorted because they have + circular dependencies and so form a cycle. + """ + result = [] + # Make a shallow copy of the adjacency list + alist = {} + for k, v in self.adjacency_list.items(): + alist[k] = v[:] + while True: + # See what we can remove in this run + to_remove = [] + for k, v in list(alist.items())[:]: + if not v: + to_remove.append(k) + del alist[k] + if not to_remove: + # What's left in alist (if anything) is a cycle. + break + # Remove from the adjacency list of others + for k, v in alist.items(): + alist[k] = [(d, r) for d, r in v if d not in to_remove] + logger.debug('Moving to result: %s', + ['%s (%s)' % (d.name, d.version) for d in to_remove]) + result.extend(to_remove) + return result, list(alist.keys()) + + def __repr__(self): + """Representation of the graph""" + output = [] + for dist, adjs in self.adjacency_list.items(): + output.append(self.repr_node(dist)) + return '\n'.join(output) + + +def make_graph(dists, scheme='default'): + """Makes a dependency graph from the given distributions. + + :parameter dists: a list of distributions + :type dists: list of :class:`distutils2.database.InstalledDistribution` and + :class:`distutils2.database.EggInfoDistribution` instances + :rtype: a :class:`DependencyGraph` instance + """ + scheme = get_scheme(scheme) + graph = DependencyGraph() + provided = {} # maps names to lists of (version, dist) tuples + + # first, build the graph and find out what's provided + for dist in dists: + graph.add_distribution(dist) + + for p in dist.provides: + name, version = parse_name_and_version(p) + logger.debug('Add to provided: %s, %s, %s', name, version, dist) + provided.setdefault(name, []).append((version, dist)) + + # now make the edges + for dist in dists: + requires = (dist.run_requires | dist.meta_requires | + dist.build_requires | dist.dev_requires) + for req in requires: + try: + matcher = scheme.matcher(req) + except UnsupportedVersionError: + # XXX compat-mode if cannot read the version + logger.warning('could not read version %r - using name only', + req) + name = req.split()[0] + matcher = scheme.matcher(name) + + name = matcher.key # case-insensitive + + matched = False + if name in provided: + for version, provider in provided[name]: + try: + match = matcher.match(version) + except UnsupportedVersionError: + match = False + + if match: + graph.add_edge(dist, provider, req) + matched = True + break + if not matched: + graph.add_missing(dist, req) + return graph + + +def get_dependent_dists(dists, dist): + """Recursively generate a list of distributions from *dists* that are + dependent on *dist*. + + :param dists: a list of distributions + :param dist: a distribution, member of *dists* for which we are interested + """ + if dist not in dists: + raise DistlibException('given distribution %r is not a member ' + 'of the list' % dist.name) + graph = make_graph(dists) + + dep = [dist] # dependent distributions + todo = graph.reverse_list[dist] # list of nodes we should inspect + + while todo: + d = todo.pop() + dep.append(d) + for succ in graph.reverse_list[d]: + if succ not in dep: + todo.append(succ) + + dep.pop(0) # remove dist from dep, was there to prevent infinite loops + return dep + + +def get_required_dists(dists, dist): + """Recursively generate a list of distributions from *dists* that are + required by *dist*. + + :param dists: a list of distributions + :param dist: a distribution, member of *dists* for which we are interested + """ + if dist not in dists: + raise DistlibException('given distribution %r is not a member ' + 'of the list' % dist.name) + graph = make_graph(dists) + + req = [] # required distributions + todo = graph.adjacency_list[dist] # list of nodes we should inspect + + while todo: + d = todo.pop()[0] + req.append(d) + for pred in graph.adjacency_list[d]: + if pred not in req: + todo.append(pred) + + return req + + +def make_dist(name, version, **kwargs): + """ + A convenience method for making a dist given just a name and version. + """ + summary = kwargs.pop('summary', 'Placeholder for summary') + md = Metadata(**kwargs) + md.name = name + md.version = version + md.summary = summary or 'Placeholder for summary' + return Distribution(md) diff --git a/venv/Lib/site-packages/pip/_vendor/distlib/index.py b/venv/Lib/site-packages/pip/_vendor/distlib/index.py new file mode 100644 index 0000000..b1fbbf8 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/distlib/index.py @@ -0,0 +1,509 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2013 Vinay Sajip. +# Licensed to the Python Software Foundation under a contributor agreement. +# See LICENSE.txt and CONTRIBUTORS.txt. +# +import hashlib +import logging +import os +import shutil +import subprocess +import tempfile +try: + from threading import Thread +except ImportError: + from dummy_threading import Thread + +from . import DistlibException +from .compat import (HTTPBasicAuthHandler, Request, HTTPPasswordMgr, + urlparse, build_opener, string_types) +from .util import zip_dir, ServerProxy + +logger = logging.getLogger(__name__) + +DEFAULT_INDEX = 'https://pypi.org/pypi' +DEFAULT_REALM = 'pypi' + +class PackageIndex(object): + """ + This class represents a package index compatible with PyPI, the Python + Package Index. + """ + + boundary = b'----------ThIs_Is_tHe_distlib_index_bouNdaRY_$' + + def __init__(self, url=None): + """ + Initialise an instance. + + :param url: The URL of the index. If not specified, the URL for PyPI is + used. + """ + self.url = url or DEFAULT_INDEX + self.read_configuration() + scheme, netloc, path, params, query, frag = urlparse(self.url) + if params or query or frag or scheme not in ('http', 'https'): + raise DistlibException('invalid repository: %s' % self.url) + self.password_handler = None + self.ssl_verifier = None + self.gpg = None + self.gpg_home = None + with open(os.devnull, 'w') as sink: + # Use gpg by default rather than gpg2, as gpg2 insists on + # prompting for passwords + for s in ('gpg', 'gpg2'): + try: + rc = subprocess.check_call([s, '--version'], stdout=sink, + stderr=sink) + if rc == 0: + self.gpg = s + break + except OSError: + pass + + def _get_pypirc_command(self): + """ + Get the distutils command for interacting with PyPI configurations. + :return: the command. + """ + from .util import _get_pypirc_command as cmd + return cmd() + + def read_configuration(self): + """ + Read the PyPI access configuration as supported by distutils. This populates + ``username``, ``password``, ``realm`` and ``url`` attributes from the + configuration. + """ + from .util import _load_pypirc + cfg = _load_pypirc(self) + self.username = cfg.get('username') + self.password = cfg.get('password') + self.realm = cfg.get('realm', 'pypi') + self.url = cfg.get('repository', self.url) + + def save_configuration(self): + """ + Save the PyPI access configuration. You must have set ``username`` and + ``password`` attributes before calling this method. + """ + self.check_credentials() + from .util import _store_pypirc + _store_pypirc(self) + + def check_credentials(self): + """ + Check that ``username`` and ``password`` have been set, and raise an + exception if not. + """ + if self.username is None or self.password is None: + raise DistlibException('username and password must be set') + pm = HTTPPasswordMgr() + _, netloc, _, _, _, _ = urlparse(self.url) + pm.add_password(self.realm, netloc, self.username, self.password) + self.password_handler = HTTPBasicAuthHandler(pm) + + def register(self, metadata): + """ + Register a distribution on PyPI, using the provided metadata. + + :param metadata: A :class:`Metadata` instance defining at least a name + and version number for the distribution to be + registered. + :return: The HTTP response received from PyPI upon submission of the + request. + """ + self.check_credentials() + metadata.validate() + d = metadata.todict() + d[':action'] = 'verify' + request = self.encode_request(d.items(), []) + response = self.send_request(request) + d[':action'] = 'submit' + request = self.encode_request(d.items(), []) + return self.send_request(request) + + def _reader(self, name, stream, outbuf): + """ + Thread runner for reading lines of from a subprocess into a buffer. + + :param name: The logical name of the stream (used for logging only). + :param stream: The stream to read from. This will typically a pipe + connected to the output stream of a subprocess. + :param outbuf: The list to append the read lines to. + """ + while True: + s = stream.readline() + if not s: + break + s = s.decode('utf-8').rstrip() + outbuf.append(s) + logger.debug('%s: %s' % (name, s)) + stream.close() + + def get_sign_command(self, filename, signer, sign_password, + keystore=None): + """ + Return a suitable command for signing a file. + + :param filename: The pathname to the file to be signed. + :param signer: The identifier of the signer of the file. + :param sign_password: The passphrase for the signer's + private key used for signing. + :param keystore: The path to a directory which contains the keys + used in verification. If not specified, the + instance's ``gpg_home`` attribute is used instead. + :return: The signing command as a list suitable to be + passed to :class:`subprocess.Popen`. + """ + cmd = [self.gpg, '--status-fd', '2', '--no-tty'] + if keystore is None: + keystore = self.gpg_home + if keystore: + cmd.extend(['--homedir', keystore]) + if sign_password is not None: + cmd.extend(['--batch', '--passphrase-fd', '0']) + td = tempfile.mkdtemp() + sf = os.path.join(td, os.path.basename(filename) + '.asc') + cmd.extend(['--detach-sign', '--armor', '--local-user', + signer, '--output', sf, filename]) + logger.debug('invoking: %s', ' '.join(cmd)) + return cmd, sf + + def run_command(self, cmd, input_data=None): + """ + Run a command in a child process , passing it any input data specified. + + :param cmd: The command to run. + :param input_data: If specified, this must be a byte string containing + data to be sent to the child process. + :return: A tuple consisting of the subprocess' exit code, a list of + lines read from the subprocess' ``stdout``, and a list of + lines read from the subprocess' ``stderr``. + """ + kwargs = { + 'stdout': subprocess.PIPE, + 'stderr': subprocess.PIPE, + } + if input_data is not None: + kwargs['stdin'] = subprocess.PIPE + stdout = [] + stderr = [] + p = subprocess.Popen(cmd, **kwargs) + # We don't use communicate() here because we may need to + # get clever with interacting with the command + t1 = Thread(target=self._reader, args=('stdout', p.stdout, stdout)) + t1.start() + t2 = Thread(target=self._reader, args=('stderr', p.stderr, stderr)) + t2.start() + if input_data is not None: + p.stdin.write(input_data) + p.stdin.close() + + p.wait() + t1.join() + t2.join() + return p.returncode, stdout, stderr + + def sign_file(self, filename, signer, sign_password, keystore=None): + """ + Sign a file. + + :param filename: The pathname to the file to be signed. + :param signer: The identifier of the signer of the file. + :param sign_password: The passphrase for the signer's + private key used for signing. + :param keystore: The path to a directory which contains the keys + used in signing. If not specified, the instance's + ``gpg_home`` attribute is used instead. + :return: The absolute pathname of the file where the signature is + stored. + """ + cmd, sig_file = self.get_sign_command(filename, signer, sign_password, + keystore) + rc, stdout, stderr = self.run_command(cmd, + sign_password.encode('utf-8')) + if rc != 0: + raise DistlibException('sign command failed with error ' + 'code %s' % rc) + return sig_file + + def upload_file(self, metadata, filename, signer=None, sign_password=None, + filetype='sdist', pyversion='source', keystore=None): + """ + Upload a release file to the index. + + :param metadata: A :class:`Metadata` instance defining at least a name + and version number for the file to be uploaded. + :param filename: The pathname of the file to be uploaded. + :param signer: The identifier of the signer of the file. + :param sign_password: The passphrase for the signer's + private key used for signing. + :param filetype: The type of the file being uploaded. This is the + distutils command which produced that file, e.g. + ``sdist`` or ``bdist_wheel``. + :param pyversion: The version of Python which the release relates + to. For code compatible with any Python, this would + be ``source``, otherwise it would be e.g. ``3.2``. + :param keystore: The path to a directory which contains the keys + used in signing. If not specified, the instance's + ``gpg_home`` attribute is used instead. + :return: The HTTP response received from PyPI upon submission of the + request. + """ + self.check_credentials() + if not os.path.exists(filename): + raise DistlibException('not found: %s' % filename) + metadata.validate() + d = metadata.todict() + sig_file = None + if signer: + if not self.gpg: + logger.warning('no signing program available - not signed') + else: + sig_file = self.sign_file(filename, signer, sign_password, + keystore) + with open(filename, 'rb') as f: + file_data = f.read() + md5_digest = hashlib.md5(file_data).hexdigest() + sha256_digest = hashlib.sha256(file_data).hexdigest() + d.update({ + ':action': 'file_upload', + 'protocol_version': '1', + 'filetype': filetype, + 'pyversion': pyversion, + 'md5_digest': md5_digest, + 'sha256_digest': sha256_digest, + }) + files = [('content', os.path.basename(filename), file_data)] + if sig_file: + with open(sig_file, 'rb') as f: + sig_data = f.read() + files.append(('gpg_signature', os.path.basename(sig_file), + sig_data)) + shutil.rmtree(os.path.dirname(sig_file)) + request = self.encode_request(d.items(), files) + return self.send_request(request) + + def upload_documentation(self, metadata, doc_dir): + """ + Upload documentation to the index. + + :param metadata: A :class:`Metadata` instance defining at least a name + and version number for the documentation to be + uploaded. + :param doc_dir: The pathname of the directory which contains the + documentation. This should be the directory that + contains the ``index.html`` for the documentation. + :return: The HTTP response received from PyPI upon submission of the + request. + """ + self.check_credentials() + if not os.path.isdir(doc_dir): + raise DistlibException('not a directory: %r' % doc_dir) + fn = os.path.join(doc_dir, 'index.html') + if not os.path.exists(fn): + raise DistlibException('not found: %r' % fn) + metadata.validate() + name, version = metadata.name, metadata.version + zip_data = zip_dir(doc_dir).getvalue() + fields = [(':action', 'doc_upload'), + ('name', name), ('version', version)] + files = [('content', name, zip_data)] + request = self.encode_request(fields, files) + return self.send_request(request) + + def get_verify_command(self, signature_filename, data_filename, + keystore=None): + """ + Return a suitable command for verifying a file. + + :param signature_filename: The pathname to the file containing the + signature. + :param data_filename: The pathname to the file containing the + signed data. + :param keystore: The path to a directory which contains the keys + used in verification. If not specified, the + instance's ``gpg_home`` attribute is used instead. + :return: The verifying command as a list suitable to be + passed to :class:`subprocess.Popen`. + """ + cmd = [self.gpg, '--status-fd', '2', '--no-tty'] + if keystore is None: + keystore = self.gpg_home + if keystore: + cmd.extend(['--homedir', keystore]) + cmd.extend(['--verify', signature_filename, data_filename]) + logger.debug('invoking: %s', ' '.join(cmd)) + return cmd + + def verify_signature(self, signature_filename, data_filename, + keystore=None): + """ + Verify a signature for a file. + + :param signature_filename: The pathname to the file containing the + signature. + :param data_filename: The pathname to the file containing the + signed data. + :param keystore: The path to a directory which contains the keys + used in verification. If not specified, the + instance's ``gpg_home`` attribute is used instead. + :return: True if the signature was verified, else False. + """ + if not self.gpg: + raise DistlibException('verification unavailable because gpg ' + 'unavailable') + cmd = self.get_verify_command(signature_filename, data_filename, + keystore) + rc, stdout, stderr = self.run_command(cmd) + if rc not in (0, 1): + raise DistlibException('verify command failed with error ' + 'code %s' % rc) + return rc == 0 + + def download_file(self, url, destfile, digest=None, reporthook=None): + """ + This is a convenience method for downloading a file from an URL. + Normally, this will be a file from the index, though currently + no check is made for this (i.e. a file can be downloaded from + anywhere). + + The method is just like the :func:`urlretrieve` function in the + standard library, except that it allows digest computation to be + done during download and checking that the downloaded data + matched any expected value. + + :param url: The URL of the file to be downloaded (assumed to be + available via an HTTP GET request). + :param destfile: The pathname where the downloaded file is to be + saved. + :param digest: If specified, this must be a (hasher, value) + tuple, where hasher is the algorithm used (e.g. + ``'md5'``) and ``value`` is the expected value. + :param reporthook: The same as for :func:`urlretrieve` in the + standard library. + """ + if digest is None: + digester = None + logger.debug('No digest specified') + else: + if isinstance(digest, (list, tuple)): + hasher, digest = digest + else: + hasher = 'md5' + digester = getattr(hashlib, hasher)() + logger.debug('Digest specified: %s' % digest) + # The following code is equivalent to urlretrieve. + # We need to do it this way so that we can compute the + # digest of the file as we go. + with open(destfile, 'wb') as dfp: + # addinfourl is not a context manager on 2.x + # so we have to use try/finally + sfp = self.send_request(Request(url)) + try: + headers = sfp.info() + blocksize = 8192 + size = -1 + read = 0 + blocknum = 0 + if "content-length" in headers: + size = int(headers["Content-Length"]) + if reporthook: + reporthook(blocknum, blocksize, size) + while True: + block = sfp.read(blocksize) + if not block: + break + read += len(block) + dfp.write(block) + if digester: + digester.update(block) + blocknum += 1 + if reporthook: + reporthook(blocknum, blocksize, size) + finally: + sfp.close() + + # check that we got the whole file, if we can + if size >= 0 and read < size: + raise DistlibException( + 'retrieval incomplete: got only %d out of %d bytes' + % (read, size)) + # if we have a digest, it must match. + if digester: + actual = digester.hexdigest() + if digest != actual: + raise DistlibException('%s digest mismatch for %s: expected ' + '%s, got %s' % (hasher, destfile, + digest, actual)) + logger.debug('Digest verified: %s', digest) + + def send_request(self, req): + """ + Send a standard library :class:`Request` to PyPI and return its + response. + + :param req: The request to send. + :return: The HTTP response from PyPI (a standard library HTTPResponse). + """ + handlers = [] + if self.password_handler: + handlers.append(self.password_handler) + if self.ssl_verifier: + handlers.append(self.ssl_verifier) + opener = build_opener(*handlers) + return opener.open(req) + + def encode_request(self, fields, files): + """ + Encode fields and files for posting to an HTTP server. + + :param fields: The fields to send as a list of (fieldname, value) + tuples. + :param files: The files to send as a list of (fieldname, filename, + file_bytes) tuple. + """ + # Adapted from packaging, which in turn was adapted from + # http://code.activestate.com/recipes/146306 + + parts = [] + boundary = self.boundary + for k, values in fields: + if not isinstance(values, (list, tuple)): + values = [values] + + for v in values: + parts.extend(( + b'--' + boundary, + ('Content-Disposition: form-data; name="%s"' % + k).encode('utf-8'), + b'', + v.encode('utf-8'))) + for key, filename, value in files: + parts.extend(( + b'--' + boundary, + ('Content-Disposition: form-data; name="%s"; filename="%s"' % + (key, filename)).encode('utf-8'), + b'', + value)) + + parts.extend((b'--' + boundary + b'--', b'')) + + body = b'\r\n'.join(parts) + ct = b'multipart/form-data; boundary=' + boundary + headers = { + 'Content-type': ct, + 'Content-length': str(len(body)) + } + return Request(self.url, body, headers) + + def search(self, terms, operator=None): + if isinstance(terms, string_types): + terms = {'name': terms} + rpc_proxy = ServerProxy(self.url, timeout=3.0) + try: + return rpc_proxy.search(terms, operator or 'and') + finally: + rpc_proxy('close')() diff --git a/venv/Lib/site-packages/pip/_vendor/distlib/locators.py b/venv/Lib/site-packages/pip/_vendor/distlib/locators.py new file mode 100644 index 0000000..0c7d639 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/distlib/locators.py @@ -0,0 +1,1300 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2012-2015 Vinay Sajip. +# Licensed to the Python Software Foundation under a contributor agreement. +# See LICENSE.txt and CONTRIBUTORS.txt. +# + +import gzip +from io import BytesIO +import json +import logging +import os +import posixpath +import re +try: + import threading +except ImportError: # pragma: no cover + import dummy_threading as threading +import zlib + +from . import DistlibException +from .compat import (urljoin, urlparse, urlunparse, url2pathname, pathname2url, + queue, quote, unescape, build_opener, + HTTPRedirectHandler as BaseRedirectHandler, text_type, + Request, HTTPError, URLError) +from .database import Distribution, DistributionPath, make_dist +from .metadata import Metadata, MetadataInvalidError +from .util import (cached_property, ensure_slash, split_filename, get_project_data, + parse_requirement, parse_name_and_version, ServerProxy, + normalize_name) +from .version import get_scheme, UnsupportedVersionError +from .wheel import Wheel, is_compatible + +logger = logging.getLogger(__name__) + +HASHER_HASH = re.compile(r'^(\w+)=([a-f0-9]+)') +CHARSET = re.compile(r';\s*charset\s*=\s*(.*)\s*$', re.I) +HTML_CONTENT_TYPE = re.compile('text/html|application/x(ht)?ml') +DEFAULT_INDEX = 'https://pypi.org/pypi' + +def get_all_distribution_names(url=None): + """ + Return all distribution names known by an index. + :param url: The URL of the index. + :return: A list of all known distribution names. + """ + if url is None: + url = DEFAULT_INDEX + client = ServerProxy(url, timeout=3.0) + try: + return client.list_packages() + finally: + client('close')() + +class RedirectHandler(BaseRedirectHandler): + """ + A class to work around a bug in some Python 3.2.x releases. + """ + # There's a bug in the base version for some 3.2.x + # (e.g. 3.2.2 on Ubuntu Oneiric). If a Location header + # returns e.g. /abc, it bails because it says the scheme '' + # is bogus, when actually it should use the request's + # URL for the scheme. See Python issue #13696. + def http_error_302(self, req, fp, code, msg, headers): + # Some servers (incorrectly) return multiple Location headers + # (so probably same goes for URI). Use first header. + newurl = None + for key in ('location', 'uri'): + if key in headers: + newurl = headers[key] + break + if newurl is None: # pragma: no cover + return + urlparts = urlparse(newurl) + if urlparts.scheme == '': + newurl = urljoin(req.get_full_url(), newurl) + if hasattr(headers, 'replace_header'): + headers.replace_header(key, newurl) + else: + headers[key] = newurl + return BaseRedirectHandler.http_error_302(self, req, fp, code, msg, + headers) + + http_error_301 = http_error_303 = http_error_307 = http_error_302 + +class Locator(object): + """ + A base class for locators - things that locate distributions. + """ + source_extensions = ('.tar.gz', '.tar.bz2', '.tar', '.zip', '.tgz', '.tbz') + binary_extensions = ('.egg', '.exe', '.whl') + excluded_extensions = ('.pdf',) + + # A list of tags indicating which wheels you want to match. The default + # value of None matches against the tags compatible with the running + # Python. If you want to match other values, set wheel_tags on a locator + # instance to a list of tuples (pyver, abi, arch) which you want to match. + wheel_tags = None + + downloadable_extensions = source_extensions + ('.whl',) + + def __init__(self, scheme='default'): + """ + Initialise an instance. + :param scheme: Because locators look for most recent versions, they + need to know the version scheme to use. This specifies + the current PEP-recommended scheme - use ``'legacy'`` + if you need to support existing distributions on PyPI. + """ + self._cache = {} + self.scheme = scheme + # Because of bugs in some of the handlers on some of the platforms, + # we use our own opener rather than just using urlopen. + self.opener = build_opener(RedirectHandler()) + # If get_project() is called from locate(), the matcher instance + # is set from the requirement passed to locate(). See issue #18 for + # why this can be useful to know. + self.matcher = None + self.errors = queue.Queue() + + def get_errors(self): + """ + Return any errors which have occurred. + """ + result = [] + while not self.errors.empty(): # pragma: no cover + try: + e = self.errors.get(False) + result.append(e) + except self.errors.Empty: + continue + self.errors.task_done() + return result + + def clear_errors(self): + """ + Clear any errors which may have been logged. + """ + # Just get the errors and throw them away + self.get_errors() + + def clear_cache(self): + self._cache.clear() + + def _get_scheme(self): + return self._scheme + + def _set_scheme(self, value): + self._scheme = value + + scheme = property(_get_scheme, _set_scheme) + + def _get_project(self, name): + """ + For a given project, get a dictionary mapping available versions to Distribution + instances. + + This should be implemented in subclasses. + + If called from a locate() request, self.matcher will be set to a + matcher for the requirement to satisfy, otherwise it will be None. + """ + raise NotImplementedError('Please implement in the subclass') + + def get_distribution_names(self): + """ + Return all the distribution names known to this locator. + """ + raise NotImplementedError('Please implement in the subclass') + + def get_project(self, name): + """ + For a given project, get a dictionary mapping available versions to Distribution + instances. + + This calls _get_project to do all the work, and just implements a caching layer on top. + """ + if self._cache is None: # pragma: no cover + result = self._get_project(name) + elif name in self._cache: + result = self._cache[name] + else: + self.clear_errors() + result = self._get_project(name) + self._cache[name] = result + return result + + def score_url(self, url): + """ + Give an url a score which can be used to choose preferred URLs + for a given project release. + """ + t = urlparse(url) + basename = posixpath.basename(t.path) + compatible = True + is_wheel = basename.endswith('.whl') + is_downloadable = basename.endswith(self.downloadable_extensions) + if is_wheel: + compatible = is_compatible(Wheel(basename), self.wheel_tags) + return (t.scheme == 'https', 'pypi.org' in t.netloc, + is_downloadable, is_wheel, compatible, basename) + + def prefer_url(self, url1, url2): + """ + Choose one of two URLs where both are candidates for distribution + archives for the same version of a distribution (for example, + .tar.gz vs. zip). + + The current implementation favours https:// URLs over http://, archives + from PyPI over those from other locations, wheel compatibility (if a + wheel) and then the archive name. + """ + result = url2 + if url1: + s1 = self.score_url(url1) + s2 = self.score_url(url2) + if s1 > s2: + result = url1 + if result != url2: + logger.debug('Not replacing %r with %r', url1, url2) + else: + logger.debug('Replacing %r with %r', url1, url2) + return result + + def split_filename(self, filename, project_name): + """ + Attempt to split a filename in project name, version and Python version. + """ + return split_filename(filename, project_name) + + def convert_url_to_download_info(self, url, project_name): + """ + See if a URL is a candidate for a download URL for a project (the URL + has typically been scraped from an HTML page). + + If it is, a dictionary is returned with keys "name", "version", + "filename" and "url"; otherwise, None is returned. + """ + def same_project(name1, name2): + return normalize_name(name1) == normalize_name(name2) + + result = None + scheme, netloc, path, params, query, frag = urlparse(url) + if frag.lower().startswith('egg='): # pragma: no cover + logger.debug('%s: version hint in fragment: %r', + project_name, frag) + m = HASHER_HASH.match(frag) + if m: + algo, digest = m.groups() + else: + algo, digest = None, None + origpath = path + if path and path[-1] == '/': # pragma: no cover + path = path[:-1] + if path.endswith('.whl'): + try: + wheel = Wheel(path) + if not is_compatible(wheel, self.wheel_tags): + logger.debug('Wheel not compatible: %s', path) + else: + if project_name is None: + include = True + else: + include = same_project(wheel.name, project_name) + if include: + result = { + 'name': wheel.name, + 'version': wheel.version, + 'filename': wheel.filename, + 'url': urlunparse((scheme, netloc, origpath, + params, query, '')), + 'python-version': ', '.join( + ['.'.join(list(v[2:])) for v in wheel.pyver]), + } + except Exception as e: # pragma: no cover + logger.warning('invalid path for wheel: %s', path) + elif not path.endswith(self.downloadable_extensions): # pragma: no cover + logger.debug('Not downloadable: %s', path) + else: # downloadable extension + path = filename = posixpath.basename(path) + for ext in self.downloadable_extensions: + if path.endswith(ext): + path = path[:-len(ext)] + t = self.split_filename(path, project_name) + if not t: # pragma: no cover + logger.debug('No match for project/version: %s', path) + else: + name, version, pyver = t + if not project_name or same_project(project_name, name): + result = { + 'name': name, + 'version': version, + 'filename': filename, + 'url': urlunparse((scheme, netloc, origpath, + params, query, '')), + #'packagetype': 'sdist', + } + if pyver: # pragma: no cover + result['python-version'] = pyver + break + if result and algo: + result['%s_digest' % algo] = digest + return result + + def _get_digest(self, info): + """ + Get a digest from a dictionary by looking at a "digests" dictionary + or keys of the form 'algo_digest'. + + Returns a 2-tuple (algo, digest) if found, else None. Currently + looks only for SHA256, then MD5. + """ + result = None + if 'digests' in info: + digests = info['digests'] + for algo in ('sha256', 'md5'): + if algo in digests: + result = (algo, digests[algo]) + break + if not result: + for algo in ('sha256', 'md5'): + key = '%s_digest' % algo + if key in info: + result = (algo, info[key]) + break + return result + + def _update_version_data(self, result, info): + """ + Update a result dictionary (the final result from _get_project) with a + dictionary for a specific version, which typically holds information + gleaned from a filename or URL for an archive for the distribution. + """ + name = info.pop('name') + version = info.pop('version') + if version in result: + dist = result[version] + md = dist.metadata + else: + dist = make_dist(name, version, scheme=self.scheme) + md = dist.metadata + dist.digest = digest = self._get_digest(info) + url = info['url'] + result['digests'][url] = digest + if md.source_url != info['url']: + md.source_url = self.prefer_url(md.source_url, url) + result['urls'].setdefault(version, set()).add(url) + dist.locator = self + result[version] = dist + + def locate(self, requirement, prereleases=False): + """ + Find the most recent distribution which matches the given + requirement. + + :param requirement: A requirement of the form 'foo (1.0)' or perhaps + 'foo (>= 1.0, < 2.0, != 1.3)' + :param prereleases: If ``True``, allow pre-release versions + to be located. Otherwise, pre-release versions + are not returned. + :return: A :class:`Distribution` instance, or ``None`` if no such + distribution could be located. + """ + result = None + r = parse_requirement(requirement) + if r is None: # pragma: no cover + raise DistlibException('Not a valid requirement: %r' % requirement) + scheme = get_scheme(self.scheme) + self.matcher = matcher = scheme.matcher(r.requirement) + logger.debug('matcher: %s (%s)', matcher, type(matcher).__name__) + versions = self.get_project(r.name) + if len(versions) > 2: # urls and digests keys are present + # sometimes, versions are invalid + slist = [] + vcls = matcher.version_class + for k in versions: + if k in ('urls', 'digests'): + continue + try: + if not matcher.match(k): + pass # logger.debug('%s did not match %r', matcher, k) + else: + if prereleases or not vcls(k).is_prerelease: + slist.append(k) + # else: + # logger.debug('skipping pre-release ' + # 'version %s of %s', k, matcher.name) + except Exception: # pragma: no cover + logger.warning('error matching %s with %r', matcher, k) + pass # slist.append(k) + if len(slist) > 1: + slist = sorted(slist, key=scheme.key) + if slist: + logger.debug('sorted list: %s', slist) + version = slist[-1] + result = versions[version] + if result: + if r.extras: + result.extras = r.extras + result.download_urls = versions.get('urls', {}).get(version, set()) + d = {} + sd = versions.get('digests', {}) + for url in result.download_urls: + if url in sd: # pragma: no cover + d[url] = sd[url] + result.digests = d + self.matcher = None + return result + + +class PyPIRPCLocator(Locator): + """ + This locator uses XML-RPC to locate distributions. It therefore + cannot be used with simple mirrors (that only mirror file content). + """ + def __init__(self, url, **kwargs): + """ + Initialise an instance. + + :param url: The URL to use for XML-RPC. + :param kwargs: Passed to the superclass constructor. + """ + super(PyPIRPCLocator, self).__init__(**kwargs) + self.base_url = url + self.client = ServerProxy(url, timeout=3.0) + + def get_distribution_names(self): + """ + Return all the distribution names known to this locator. + """ + return set(self.client.list_packages()) + + def _get_project(self, name): + result = {'urls': {}, 'digests': {}} + versions = self.client.package_releases(name, True) + for v in versions: + urls = self.client.release_urls(name, v) + data = self.client.release_data(name, v) + metadata = Metadata(scheme=self.scheme) + metadata.name = data['name'] + metadata.version = data['version'] + metadata.license = data.get('license') + metadata.keywords = data.get('keywords', []) + metadata.summary = data.get('summary') + dist = Distribution(metadata) + if urls: + info = urls[0] + metadata.source_url = info['url'] + dist.digest = self._get_digest(info) + dist.locator = self + result[v] = dist + for info in urls: + url = info['url'] + digest = self._get_digest(info) + result['urls'].setdefault(v, set()).add(url) + result['digests'][url] = digest + return result + +class PyPIJSONLocator(Locator): + """ + This locator uses PyPI's JSON interface. It's very limited in functionality + and probably not worth using. + """ + def __init__(self, url, **kwargs): + super(PyPIJSONLocator, self).__init__(**kwargs) + self.base_url = ensure_slash(url) + + def get_distribution_names(self): + """ + Return all the distribution names known to this locator. + """ + raise NotImplementedError('Not available from this locator') + + def _get_project(self, name): + result = {'urls': {}, 'digests': {}} + url = urljoin(self.base_url, '%s/json' % quote(name)) + try: + resp = self.opener.open(url) + data = resp.read().decode() # for now + d = json.loads(data) + md = Metadata(scheme=self.scheme) + data = d['info'] + md.name = data['name'] + md.version = data['version'] + md.license = data.get('license') + md.keywords = data.get('keywords', []) + md.summary = data.get('summary') + dist = Distribution(md) + dist.locator = self + urls = d['urls'] + result[md.version] = dist + for info in d['urls']: + url = info['url'] + dist.download_urls.add(url) + dist.digests[url] = self._get_digest(info) + result['urls'].setdefault(md.version, set()).add(url) + result['digests'][url] = self._get_digest(info) + # Now get other releases + for version, infos in d['releases'].items(): + if version == md.version: + continue # already done + omd = Metadata(scheme=self.scheme) + omd.name = md.name + omd.version = version + odist = Distribution(omd) + odist.locator = self + result[version] = odist + for info in infos: + url = info['url'] + odist.download_urls.add(url) + odist.digests[url] = self._get_digest(info) + result['urls'].setdefault(version, set()).add(url) + result['digests'][url] = self._get_digest(info) +# for info in urls: +# md.source_url = info['url'] +# dist.digest = self._get_digest(info) +# dist.locator = self +# for info in urls: +# url = info['url'] +# result['urls'].setdefault(md.version, set()).add(url) +# result['digests'][url] = self._get_digest(info) + except Exception as e: + self.errors.put(text_type(e)) + logger.exception('JSON fetch failed: %s', e) + return result + + +class Page(object): + """ + This class represents a scraped HTML page. + """ + # The following slightly hairy-looking regex just looks for the contents of + # an anchor link, which has an attribute "href" either immediately preceded + # or immediately followed by a "rel" attribute. The attribute values can be + # declared with double quotes, single quotes or no quotes - which leads to + # the length of the expression. + _href = re.compile(""" +(rel\\s*=\\s*(?:"(?P[^"]*)"|'(?P[^']*)'|(?P[^>\\s\n]*))\\s+)? +href\\s*=\\s*(?:"(?P[^"]*)"|'(?P[^']*)'|(?P[^>\\s\n]*)) +(\\s+rel\\s*=\\s*(?:"(?P[^"]*)"|'(?P[^']*)'|(?P[^>\\s\n]*)))? +""", re.I | re.S | re.X) + _base = re.compile(r"""]+)""", re.I | re.S) + + def __init__(self, data, url): + """ + Initialise an instance with the Unicode page contents and the URL they + came from. + """ + self.data = data + self.base_url = self.url = url + m = self._base.search(self.data) + if m: + self.base_url = m.group(1) + + _clean_re = re.compile(r'[^a-z0-9$&+,/:;=?@.#%_\\|-]', re.I) + + @cached_property + def links(self): + """ + Return the URLs of all the links on a page together with information + about their "rel" attribute, for determining which ones to treat as + downloads and which ones to queue for further scraping. + """ + def clean(url): + "Tidy up an URL." + scheme, netloc, path, params, query, frag = urlparse(url) + return urlunparse((scheme, netloc, quote(path), + params, query, frag)) + + result = set() + for match in self._href.finditer(self.data): + d = match.groupdict('') + rel = (d['rel1'] or d['rel2'] or d['rel3'] or + d['rel4'] or d['rel5'] or d['rel6']) + url = d['url1'] or d['url2'] or d['url3'] + url = urljoin(self.base_url, url) + url = unescape(url) + url = self._clean_re.sub(lambda m: '%%%2x' % ord(m.group(0)), url) + result.add((url, rel)) + # We sort the result, hoping to bring the most recent versions + # to the front + result = sorted(result, key=lambda t: t[0], reverse=True) + return result + + +class SimpleScrapingLocator(Locator): + """ + A locator which scrapes HTML pages to locate downloads for a distribution. + This runs multiple threads to do the I/O; performance is at least as good + as pip's PackageFinder, which works in an analogous fashion. + """ + + # These are used to deal with various Content-Encoding schemes. + decoders = { + 'deflate': zlib.decompress, + 'gzip': lambda b: gzip.GzipFile(fileobj=BytesIO(b)).read(), + 'none': lambda b: b, + } + + def __init__(self, url, timeout=None, num_workers=10, **kwargs): + """ + Initialise an instance. + :param url: The root URL to use for scraping. + :param timeout: The timeout, in seconds, to be applied to requests. + This defaults to ``None`` (no timeout specified). + :param num_workers: The number of worker threads you want to do I/O, + This defaults to 10. + :param kwargs: Passed to the superclass. + """ + super(SimpleScrapingLocator, self).__init__(**kwargs) + self.base_url = ensure_slash(url) + self.timeout = timeout + self._page_cache = {} + self._seen = set() + self._to_fetch = queue.Queue() + self._bad_hosts = set() + self.skip_externals = False + self.num_workers = num_workers + self._lock = threading.RLock() + # See issue #45: we need to be resilient when the locator is used + # in a thread, e.g. with concurrent.futures. We can't use self._lock + # as it is for coordinating our internal threads - the ones created + # in _prepare_threads. + self._gplock = threading.RLock() + self.platform_check = False # See issue #112 + + def _prepare_threads(self): + """ + Threads are created only when get_project is called, and terminate + before it returns. They are there primarily to parallelise I/O (i.e. + fetching web pages). + """ + self._threads = [] + for i in range(self.num_workers): + t = threading.Thread(target=self._fetch) + t.setDaemon(True) + t.start() + self._threads.append(t) + + def _wait_threads(self): + """ + Tell all the threads to terminate (by sending a sentinel value) and + wait for them to do so. + """ + # Note that you need two loops, since you can't say which + # thread will get each sentinel + for t in self._threads: + self._to_fetch.put(None) # sentinel + for t in self._threads: + t.join() + self._threads = [] + + def _get_project(self, name): + result = {'urls': {}, 'digests': {}} + with self._gplock: + self.result = result + self.project_name = name + url = urljoin(self.base_url, '%s/' % quote(name)) + self._seen.clear() + self._page_cache.clear() + self._prepare_threads() + try: + logger.debug('Queueing %s', url) + self._to_fetch.put(url) + self._to_fetch.join() + finally: + self._wait_threads() + del self.result + return result + + platform_dependent = re.compile(r'\b(linux_(i\d86|x86_64|arm\w+)|' + r'win(32|_amd64)|macosx_?\d+)\b', re.I) + + def _is_platform_dependent(self, url): + """ + Does an URL refer to a platform-specific download? + """ + return self.platform_dependent.search(url) + + def _process_download(self, url): + """ + See if an URL is a suitable download for a project. + + If it is, register information in the result dictionary (for + _get_project) about the specific version it's for. + + Note that the return value isn't actually used other than as a boolean + value. + """ + if self.platform_check and self._is_platform_dependent(url): + info = None + else: + info = self.convert_url_to_download_info(url, self.project_name) + logger.debug('process_download: %s -> %s', url, info) + if info: + with self._lock: # needed because self.result is shared + self._update_version_data(self.result, info) + return info + + def _should_queue(self, link, referrer, rel): + """ + Determine whether a link URL from a referring page and with a + particular "rel" attribute should be queued for scraping. + """ + scheme, netloc, path, _, _, _ = urlparse(link) + if path.endswith(self.source_extensions + self.binary_extensions + + self.excluded_extensions): + result = False + elif self.skip_externals and not link.startswith(self.base_url): + result = False + elif not referrer.startswith(self.base_url): + result = False + elif rel not in ('homepage', 'download'): + result = False + elif scheme not in ('http', 'https', 'ftp'): + result = False + elif self._is_platform_dependent(link): + result = False + else: + host = netloc.split(':', 1)[0] + if host.lower() == 'localhost': + result = False + else: + result = True + logger.debug('should_queue: %s (%s) from %s -> %s', link, rel, + referrer, result) + return result + + def _fetch(self): + """ + Get a URL to fetch from the work queue, get the HTML page, examine its + links for download candidates and candidates for further scraping. + + This is a handy method to run in a thread. + """ + while True: + url = self._to_fetch.get() + try: + if url: + page = self.get_page(url) + if page is None: # e.g. after an error + continue + for link, rel in page.links: + if link not in self._seen: + try: + self._seen.add(link) + if (not self._process_download(link) and + self._should_queue(link, url, rel)): + logger.debug('Queueing %s from %s', link, url) + self._to_fetch.put(link) + except MetadataInvalidError: # e.g. invalid versions + pass + except Exception as e: # pragma: no cover + self.errors.put(text_type(e)) + finally: + # always do this, to avoid hangs :-) + self._to_fetch.task_done() + if not url: + #logger.debug('Sentinel seen, quitting.') + break + + def get_page(self, url): + """ + Get the HTML for an URL, possibly from an in-memory cache. + + XXX TODO Note: this cache is never actually cleared. It's assumed that + the data won't get stale over the lifetime of a locator instance (not + necessarily true for the default_locator). + """ + # http://peak.telecommunity.com/DevCenter/EasyInstall#package-index-api + scheme, netloc, path, _, _, _ = urlparse(url) + if scheme == 'file' and os.path.isdir(url2pathname(path)): + url = urljoin(ensure_slash(url), 'index.html') + + if url in self._page_cache: + result = self._page_cache[url] + logger.debug('Returning %s from cache: %s', url, result) + else: + host = netloc.split(':', 1)[0] + result = None + if host in self._bad_hosts: + logger.debug('Skipping %s due to bad host %s', url, host) + else: + req = Request(url, headers={'Accept-encoding': 'identity'}) + try: + logger.debug('Fetching %s', url) + resp = self.opener.open(req, timeout=self.timeout) + logger.debug('Fetched %s', url) + headers = resp.info() + content_type = headers.get('Content-Type', '') + if HTML_CONTENT_TYPE.match(content_type): + final_url = resp.geturl() + data = resp.read() + encoding = headers.get('Content-Encoding') + if encoding: + decoder = self.decoders[encoding] # fail if not found + data = decoder(data) + encoding = 'utf-8' + m = CHARSET.search(content_type) + if m: + encoding = m.group(1) + try: + data = data.decode(encoding) + except UnicodeError: # pragma: no cover + data = data.decode('latin-1') # fallback + result = Page(data, final_url) + self._page_cache[final_url] = result + except HTTPError as e: + if e.code != 404: + logger.exception('Fetch failed: %s: %s', url, e) + except URLError as e: # pragma: no cover + logger.exception('Fetch failed: %s: %s', url, e) + with self._lock: + self._bad_hosts.add(host) + except Exception as e: # pragma: no cover + logger.exception('Fetch failed: %s: %s', url, e) + finally: + self._page_cache[url] = result # even if None (failure) + return result + + _distname_re = re.compile(']*>([^<]+)<') + + def get_distribution_names(self): + """ + Return all the distribution names known to this locator. + """ + result = set() + page = self.get_page(self.base_url) + if not page: + raise DistlibException('Unable to get %s' % self.base_url) + for match in self._distname_re.finditer(page.data): + result.add(match.group(1)) + return result + +class DirectoryLocator(Locator): + """ + This class locates distributions in a directory tree. + """ + + def __init__(self, path, **kwargs): + """ + Initialise an instance. + :param path: The root of the directory tree to search. + :param kwargs: Passed to the superclass constructor, + except for: + * recursive - if True (the default), subdirectories are + recursed into. If False, only the top-level directory + is searched, + """ + self.recursive = kwargs.pop('recursive', True) + super(DirectoryLocator, self).__init__(**kwargs) + path = os.path.abspath(path) + if not os.path.isdir(path): # pragma: no cover + raise DistlibException('Not a directory: %r' % path) + self.base_dir = path + + def should_include(self, filename, parent): + """ + Should a filename be considered as a candidate for a distribution + archive? As well as the filename, the directory which contains it + is provided, though not used by the current implementation. + """ + return filename.endswith(self.downloadable_extensions) + + def _get_project(self, name): + result = {'urls': {}, 'digests': {}} + for root, dirs, files in os.walk(self.base_dir): + for fn in files: + if self.should_include(fn, root): + fn = os.path.join(root, fn) + url = urlunparse(('file', '', + pathname2url(os.path.abspath(fn)), + '', '', '')) + info = self.convert_url_to_download_info(url, name) + if info: + self._update_version_data(result, info) + if not self.recursive: + break + return result + + def get_distribution_names(self): + """ + Return all the distribution names known to this locator. + """ + result = set() + for root, dirs, files in os.walk(self.base_dir): + for fn in files: + if self.should_include(fn, root): + fn = os.path.join(root, fn) + url = urlunparse(('file', '', + pathname2url(os.path.abspath(fn)), + '', '', '')) + info = self.convert_url_to_download_info(url, None) + if info: + result.add(info['name']) + if not self.recursive: + break + return result + +class JSONLocator(Locator): + """ + This locator uses special extended metadata (not available on PyPI) and is + the basis of performant dependency resolution in distlib. Other locators + require archive downloads before dependencies can be determined! As you + might imagine, that can be slow. + """ + def get_distribution_names(self): + """ + Return all the distribution names known to this locator. + """ + raise NotImplementedError('Not available from this locator') + + def _get_project(self, name): + result = {'urls': {}, 'digests': {}} + data = get_project_data(name) + if data: + for info in data.get('files', []): + if info['ptype'] != 'sdist' or info['pyversion'] != 'source': + continue + # We don't store summary in project metadata as it makes + # the data bigger for no benefit during dependency + # resolution + dist = make_dist(data['name'], info['version'], + summary=data.get('summary', + 'Placeholder for summary'), + scheme=self.scheme) + md = dist.metadata + md.source_url = info['url'] + # TODO SHA256 digest + if 'digest' in info and info['digest']: + dist.digest = ('md5', info['digest']) + md.dependencies = info.get('requirements', {}) + dist.exports = info.get('exports', {}) + result[dist.version] = dist + result['urls'].setdefault(dist.version, set()).add(info['url']) + return result + +class DistPathLocator(Locator): + """ + This locator finds installed distributions in a path. It can be useful for + adding to an :class:`AggregatingLocator`. + """ + def __init__(self, distpath, **kwargs): + """ + Initialise an instance. + + :param distpath: A :class:`DistributionPath` instance to search. + """ + super(DistPathLocator, self).__init__(**kwargs) + assert isinstance(distpath, DistributionPath) + self.distpath = distpath + + def _get_project(self, name): + dist = self.distpath.get_distribution(name) + if dist is None: + result = {'urls': {}, 'digests': {}} + else: + result = { + dist.version: dist, + 'urls': {dist.version: set([dist.source_url])}, + 'digests': {dist.version: set([None])} + } + return result + + +class AggregatingLocator(Locator): + """ + This class allows you to chain and/or merge a list of locators. + """ + def __init__(self, *locators, **kwargs): + """ + Initialise an instance. + + :param locators: The list of locators to search. + :param kwargs: Passed to the superclass constructor, + except for: + * merge - if False (the default), the first successful + search from any of the locators is returned. If True, + the results from all locators are merged (this can be + slow). + """ + self.merge = kwargs.pop('merge', False) + self.locators = locators + super(AggregatingLocator, self).__init__(**kwargs) + + def clear_cache(self): + super(AggregatingLocator, self).clear_cache() + for locator in self.locators: + locator.clear_cache() + + def _set_scheme(self, value): + self._scheme = value + for locator in self.locators: + locator.scheme = value + + scheme = property(Locator.scheme.fget, _set_scheme) + + def _get_project(self, name): + result = {} + for locator in self.locators: + d = locator.get_project(name) + if d: + if self.merge: + files = result.get('urls', {}) + digests = result.get('digests', {}) + # next line could overwrite result['urls'], result['digests'] + result.update(d) + df = result.get('urls') + if files and df: + for k, v in files.items(): + if k in df: + df[k] |= v + else: + df[k] = v + dd = result.get('digests') + if digests and dd: + dd.update(digests) + else: + # See issue #18. If any dists are found and we're looking + # for specific constraints, we only return something if + # a match is found. For example, if a DirectoryLocator + # returns just foo (1.0) while we're looking for + # foo (>= 2.0), we'll pretend there was nothing there so + # that subsequent locators can be queried. Otherwise we + # would just return foo (1.0) which would then lead to a + # failure to find foo (>= 2.0), because other locators + # weren't searched. Note that this only matters when + # merge=False. + if self.matcher is None: + found = True + else: + found = False + for k in d: + if self.matcher.match(k): + found = True + break + if found: + result = d + break + return result + + def get_distribution_names(self): + """ + Return all the distribution names known to this locator. + """ + result = set() + for locator in self.locators: + try: + result |= locator.get_distribution_names() + except NotImplementedError: + pass + return result + + +# We use a legacy scheme simply because most of the dists on PyPI use legacy +# versions which don't conform to PEP 426 / PEP 440. +default_locator = AggregatingLocator( + JSONLocator(), + SimpleScrapingLocator('https://pypi.org/simple/', + timeout=3.0), + scheme='legacy') + +locate = default_locator.locate + + +class DependencyFinder(object): + """ + Locate dependencies for distributions. + """ + + def __init__(self, locator=None): + """ + Initialise an instance, using the specified locator + to locate distributions. + """ + self.locator = locator or default_locator + self.scheme = get_scheme(self.locator.scheme) + + def add_distribution(self, dist): + """ + Add a distribution to the finder. This will update internal information + about who provides what. + :param dist: The distribution to add. + """ + logger.debug('adding distribution %s', dist) + name = dist.key + self.dists_by_name[name] = dist + self.dists[(name, dist.version)] = dist + for p in dist.provides: + name, version = parse_name_and_version(p) + logger.debug('Add to provided: %s, %s, %s', name, version, dist) + self.provided.setdefault(name, set()).add((version, dist)) + + def remove_distribution(self, dist): + """ + Remove a distribution from the finder. This will update internal + information about who provides what. + :param dist: The distribution to remove. + """ + logger.debug('removing distribution %s', dist) + name = dist.key + del self.dists_by_name[name] + del self.dists[(name, dist.version)] + for p in dist.provides: + name, version = parse_name_and_version(p) + logger.debug('Remove from provided: %s, %s, %s', name, version, dist) + s = self.provided[name] + s.remove((version, dist)) + if not s: + del self.provided[name] + + def get_matcher(self, reqt): + """ + Get a version matcher for a requirement. + :param reqt: The requirement + :type reqt: str + :return: A version matcher (an instance of + :class:`distlib.version.Matcher`). + """ + try: + matcher = self.scheme.matcher(reqt) + except UnsupportedVersionError: # pragma: no cover + # XXX compat-mode if cannot read the version + name = reqt.split()[0] + matcher = self.scheme.matcher(name) + return matcher + + def find_providers(self, reqt): + """ + Find the distributions which can fulfill a requirement. + + :param reqt: The requirement. + :type reqt: str + :return: A set of distribution which can fulfill the requirement. + """ + matcher = self.get_matcher(reqt) + name = matcher.key # case-insensitive + result = set() + provided = self.provided + if name in provided: + for version, provider in provided[name]: + try: + match = matcher.match(version) + except UnsupportedVersionError: + match = False + + if match: + result.add(provider) + break + return result + + def try_to_replace(self, provider, other, problems): + """ + Attempt to replace one provider with another. This is typically used + when resolving dependencies from multiple sources, e.g. A requires + (B >= 1.0) while C requires (B >= 1.1). + + For successful replacement, ``provider`` must meet all the requirements + which ``other`` fulfills. + + :param provider: The provider we are trying to replace with. + :param other: The provider we're trying to replace. + :param problems: If False is returned, this will contain what + problems prevented replacement. This is currently + a tuple of the literal string 'cantreplace', + ``provider``, ``other`` and the set of requirements + that ``provider`` couldn't fulfill. + :return: True if we can replace ``other`` with ``provider``, else + False. + """ + rlist = self.reqts[other] + unmatched = set() + for s in rlist: + matcher = self.get_matcher(s) + if not matcher.match(provider.version): + unmatched.add(s) + if unmatched: + # can't replace other with provider + problems.add(('cantreplace', provider, other, + frozenset(unmatched))) + result = False + else: + # can replace other with provider + self.remove_distribution(other) + del self.reqts[other] + for s in rlist: + self.reqts.setdefault(provider, set()).add(s) + self.add_distribution(provider) + result = True + return result + + def find(self, requirement, meta_extras=None, prereleases=False): + """ + Find a distribution and all distributions it depends on. + + :param requirement: The requirement specifying the distribution to + find, or a Distribution instance. + :param meta_extras: A list of meta extras such as :test:, :build: and + so on. + :param prereleases: If ``True``, allow pre-release versions to be + returned - otherwise, don't return prereleases + unless they're all that's available. + + Return a set of :class:`Distribution` instances and a set of + problems. + + The distributions returned should be such that they have the + :attr:`required` attribute set to ``True`` if they were + from the ``requirement`` passed to ``find()``, and they have the + :attr:`build_time_dependency` attribute set to ``True`` unless they + are post-installation dependencies of the ``requirement``. + + The problems should be a tuple consisting of the string + ``'unsatisfied'`` and the requirement which couldn't be satisfied + by any distribution known to the locator. + """ + + self.provided = {} + self.dists = {} + self.dists_by_name = {} + self.reqts = {} + + meta_extras = set(meta_extras or []) + if ':*:' in meta_extras: + meta_extras.remove(':*:') + # :meta: and :run: are implicitly included + meta_extras |= set([':test:', ':build:', ':dev:']) + + if isinstance(requirement, Distribution): + dist = odist = requirement + logger.debug('passed %s as requirement', odist) + else: + dist = odist = self.locator.locate(requirement, + prereleases=prereleases) + if dist is None: + raise DistlibException('Unable to locate %r' % requirement) + logger.debug('located %s', odist) + dist.requested = True + problems = set() + todo = set([dist]) + install_dists = set([odist]) + while todo: + dist = todo.pop() + name = dist.key # case-insensitive + if name not in self.dists_by_name: + self.add_distribution(dist) + else: + #import pdb; pdb.set_trace() + other = self.dists_by_name[name] + if other != dist: + self.try_to_replace(dist, other, problems) + + ireqts = dist.run_requires | dist.meta_requires + sreqts = dist.build_requires + ereqts = set() + if meta_extras and dist in install_dists: + for key in ('test', 'build', 'dev'): + e = ':%s:' % key + if e in meta_extras: + ereqts |= getattr(dist, '%s_requires' % key) + all_reqts = ireqts | sreqts | ereqts + for r in all_reqts: + providers = self.find_providers(r) + if not providers: + logger.debug('No providers found for %r', r) + provider = self.locator.locate(r, prereleases=prereleases) + # If no provider is found and we didn't consider + # prereleases, consider them now. + if provider is None and not prereleases: + provider = self.locator.locate(r, prereleases=True) + if provider is None: + logger.debug('Cannot satisfy %r', r) + problems.add(('unsatisfied', r)) + else: + n, v = provider.key, provider.version + if (n, v) not in self.dists: + todo.add(provider) + providers.add(provider) + if r in ireqts and dist in install_dists: + install_dists.add(provider) + logger.debug('Adding %s to install_dists', + provider.name_and_version) + for p in providers: + name = p.key + if name not in self.dists_by_name: + self.reqts.setdefault(p, set()).add(r) + else: + other = self.dists_by_name[name] + if other != p: + # see if other can be replaced by p + self.try_to_replace(p, other, problems) + + dists = set(self.dists.values()) + for dist in dists: + dist.build_time_dependency = dist not in install_dists + if dist.build_time_dependency: + logger.debug('%s is a build-time dependency only.', + dist.name_and_version) + logger.debug('find done for %s', odist) + return dists, problems diff --git a/venv/Lib/site-packages/pip/_vendor/distlib/manifest.py b/venv/Lib/site-packages/pip/_vendor/distlib/manifest.py new file mode 100644 index 0000000..ca0fe44 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/distlib/manifest.py @@ -0,0 +1,393 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2012-2013 Python Software Foundation. +# See LICENSE.txt and CONTRIBUTORS.txt. +# +""" +Class representing the list of files in a distribution. + +Equivalent to distutils.filelist, but fixes some problems. +""" +import fnmatch +import logging +import os +import re +import sys + +from . import DistlibException +from .compat import fsdecode +from .util import convert_path + + +__all__ = ['Manifest'] + +logger = logging.getLogger(__name__) + +# a \ followed by some spaces + EOL +_COLLAPSE_PATTERN = re.compile('\\\\w*\n', re.M) +_COMMENTED_LINE = re.compile('#.*?(?=\n)|\n(?=$)', re.M | re.S) + +# +# Due to the different results returned by fnmatch.translate, we need +# to do slightly different processing for Python 2.7 and 3.2 ... this needed +# to be brought in for Python 3.6 onwards. +# +_PYTHON_VERSION = sys.version_info[:2] + +class Manifest(object): + """A list of files built by on exploring the filesystem and filtered by + applying various patterns to what we find there. + """ + + def __init__(self, base=None): + """ + Initialise an instance. + + :param base: The base directory to explore under. + """ + self.base = os.path.abspath(os.path.normpath(base or os.getcwd())) + self.prefix = self.base + os.sep + self.allfiles = None + self.files = set() + + # + # Public API + # + + def findall(self): + """Find all files under the base and set ``allfiles`` to the absolute + pathnames of files found. + """ + from stat import S_ISREG, S_ISDIR, S_ISLNK + + self.allfiles = allfiles = [] + root = self.base + stack = [root] + pop = stack.pop + push = stack.append + + while stack: + root = pop() + names = os.listdir(root) + + for name in names: + fullname = os.path.join(root, name) + + # Avoid excess stat calls -- just one will do, thank you! + stat = os.stat(fullname) + mode = stat.st_mode + if S_ISREG(mode): + allfiles.append(fsdecode(fullname)) + elif S_ISDIR(mode) and not S_ISLNK(mode): + push(fullname) + + def add(self, item): + """ + Add a file to the manifest. + + :param item: The pathname to add. This can be relative to the base. + """ + if not item.startswith(self.prefix): + item = os.path.join(self.base, item) + self.files.add(os.path.normpath(item)) + + def add_many(self, items): + """ + Add a list of files to the manifest. + + :param items: The pathnames to add. These can be relative to the base. + """ + for item in items: + self.add(item) + + def sorted(self, wantdirs=False): + """ + Return sorted files in directory order + """ + + def add_dir(dirs, d): + dirs.add(d) + logger.debug('add_dir added %s', d) + if d != self.base: + parent, _ = os.path.split(d) + assert parent not in ('', '/') + add_dir(dirs, parent) + + result = set(self.files) # make a copy! + if wantdirs: + dirs = set() + for f in result: + add_dir(dirs, os.path.dirname(f)) + result |= dirs + return [os.path.join(*path_tuple) for path_tuple in + sorted(os.path.split(path) for path in result)] + + def clear(self): + """Clear all collected files.""" + self.files = set() + self.allfiles = [] + + def process_directive(self, directive): + """ + Process a directive which either adds some files from ``allfiles`` to + ``files``, or removes some files from ``files``. + + :param directive: The directive to process. This should be in a format + compatible with distutils ``MANIFEST.in`` files: + + http://docs.python.org/distutils/sourcedist.html#commands + """ + # Parse the line: split it up, make sure the right number of words + # is there, and return the relevant words. 'action' is always + # defined: it's the first word of the line. Which of the other + # three are defined depends on the action; it'll be either + # patterns, (dir and patterns), or (dirpattern). + action, patterns, thedir, dirpattern = self._parse_directive(directive) + + # OK, now we know that the action is valid and we have the + # right number of words on the line for that action -- so we + # can proceed with minimal error-checking. + if action == 'include': + for pattern in patterns: + if not self._include_pattern(pattern, anchor=True): + logger.warning('no files found matching %r', pattern) + + elif action == 'exclude': + for pattern in patterns: + found = self._exclude_pattern(pattern, anchor=True) + #if not found: + # logger.warning('no previously-included files ' + # 'found matching %r', pattern) + + elif action == 'global-include': + for pattern in patterns: + if not self._include_pattern(pattern, anchor=False): + logger.warning('no files found matching %r ' + 'anywhere in distribution', pattern) + + elif action == 'global-exclude': + for pattern in patterns: + found = self._exclude_pattern(pattern, anchor=False) + #if not found: + # logger.warning('no previously-included files ' + # 'matching %r found anywhere in ' + # 'distribution', pattern) + + elif action == 'recursive-include': + for pattern in patterns: + if not self._include_pattern(pattern, prefix=thedir): + logger.warning('no files found matching %r ' + 'under directory %r', pattern, thedir) + + elif action == 'recursive-exclude': + for pattern in patterns: + found = self._exclude_pattern(pattern, prefix=thedir) + #if not found: + # logger.warning('no previously-included files ' + # 'matching %r found under directory %r', + # pattern, thedir) + + elif action == 'graft': + if not self._include_pattern(None, prefix=dirpattern): + logger.warning('no directories found matching %r', + dirpattern) + + elif action == 'prune': + if not self._exclude_pattern(None, prefix=dirpattern): + logger.warning('no previously-included directories found ' + 'matching %r', dirpattern) + else: # pragma: no cover + # This should never happen, as it should be caught in + # _parse_template_line + raise DistlibException( + 'invalid action %r' % action) + + # + # Private API + # + + def _parse_directive(self, directive): + """ + Validate a directive. + :param directive: The directive to validate. + :return: A tuple of action, patterns, thedir, dir_patterns + """ + words = directive.split() + if len(words) == 1 and words[0] not in ('include', 'exclude', + 'global-include', + 'global-exclude', + 'recursive-include', + 'recursive-exclude', + 'graft', 'prune'): + # no action given, let's use the default 'include' + words.insert(0, 'include') + + action = words[0] + patterns = thedir = dir_pattern = None + + if action in ('include', 'exclude', + 'global-include', 'global-exclude'): + if len(words) < 2: + raise DistlibException( + '%r expects ...' % action) + + patterns = [convert_path(word) for word in words[1:]] + + elif action in ('recursive-include', 'recursive-exclude'): + if len(words) < 3: + raise DistlibException( + '%r expects

2_x~U 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/req/__pycache__/req_tracker.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/req/__pycache__/req_tracker.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..08d96c587bc2cfd10414699122784da6ea7d2132 GIT binary patch literal 4246 zcmZ`+&vO*V74Dvyot<5+mPPy&2E3^XiPr@R5aJMuxWIrD45iqBL%gMAYP8)*v&_z{ zdU`=x?^dNOt~UPw2gwIlanC7-obxB7`jAUb`4{3#zSpx7(jsQ6d-~_=?)Sa^-kWH4 zw#x8)`~J_Ck2M(k4^{R)9x6AG@_!%`Oz?!Yi!X0;TX))y{km-zUnlW;rFMza7&q~I z<#xFjw1ZxyUFlWZ)!s~drdMm%Y`>Sx_Ui4rEtir*y+*rX%YJgWH`kuyOgdXfvLy6Ln}3I33^ z4*eHrV2dqoW*@1jBbTGj(?=V9+47BdJML%`+|^P=I#VY2Ltn>P8YRYkD7Eoum??dk zq7Bo%`*Hdd-?_VKuA?M*AlC-5l0BJfD_r*aw^8pv(niZM<<4r9uE^Z@O6q}1JG70R zr;GwY@DwTk7c$Mde9X18$;M91#_ou1x!deE`}6fBXY7qj!^Vh@ym>ZqN8WYzn5CyY zroD~NIHPyu6zyNJ)Vat;B^rC3t(_cxBG@0%{}}To@)oQ-f8>vx0aJgak-ueYtGYDu zwZG})-+jiu;pi#(7MtO*_)KxmK;RszEiz*O6KQ9!JtF4dr^AYp6WzMe3)|MmqHXk$XZh716r5^JU;DG_$ zAMve{_Jt$dZ!w}<9y8k#px>hw&U9s~DoP`^?Vvm}Vw?Qs@v$><3d0i2!@KEnmNqW2 zynoReBxhe)vzzMuZf`G{N6TL{hd#gidHCSY7vZA^H*ej$^I$jwWnP#llkVNqI2A3f zeuA?Mn|IS#$59dwrD!e>;zTs<$T(eTM!I<}Z`G`Z6=;nam&~R*0U(K&P36vdtRHG9 z&&H^yKK}ds2NH>u3ACO5#wA*&1E4Xk#gs$*j zcx?}KTLS(0qKsNe`m!v8c{a~b!WVf31j$A4$`cjPqSvm<8OWG{1WTFinw&*{9rZ(^ zf&Th#{jiur{SbO-g(Ko9Y7Kd~J11x55lhH4>zFuhiT9|b+7nhyi!DcyeHW(bptSQ) znOw^)q`Zj?9Ku4T`6k2HA>$Ni=~`2>=HV<3=Wi*AtF#Yosjd;!B~uCuKyu(5;I?TM z%Upc`(Tem98uoITJSp}=H-8UML5M3H>oEK^+H)Tn<34a1zW4S;Ti6+^ni$sMGF(a~aI>sF`w*!yizS*!^fB@L~C48n0s}j-yVY1Q~Non2Q^%k%c+lQ1 zQ-8ddixE)F*??lH2q+LpoP+~+wh&5m*~r^=#_$rO(k4f6Kv%Tr&@JI7^|DejFyRS0eAQ>*RJ0yeFiwPENIa^$Q5J$5OP(sWYhu)HY=hZy-W-eD%ZkrZ4f0zkG)RnGK8vMQbtCr=+DZ`eiG&K&U#1M z|2akQsH>DwU~I3lqQ9>_o31aN8eyjxzuW`Cjt@|Ety{AaHx`xb@DYOLfSjPg@z%}P~kNDHs=u-#jzgXCwiD=&* zOp$S#dHjAX?EZc%KshqW7wiq7^R>_H?^kkd0SOZ1KQ^QwEzGB literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/req/__pycache__/req_uninstall.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/req/__pycache__/req_uninstall.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fa55a0ab6d2fbc46e737702b705c00836d4f4f1d GIT binary patch literal 18827 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/req/constructors.py b/venv/Lib/site-packages/pip/_internal/req/constructors.py new file mode 100644 index 0000000..25bfb39 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/req/constructors.py @@ -0,0 +1,490 @@ +"""Backing implementation for InstallRequirement's various constructors + +The idea here is that these formed a major chunk of InstallRequirement's size +so, moving them and support code dedicated to them outside of that class +helps creates for better understandability for the rest of the code. + +These are meant to be used elsewhere within pip to create instances of +InstallRequirement. +""" + +import logging +import os +import re +from typing import Any, Dict, Optional, Set, Tuple, Union + +from pip._vendor.packaging.markers import Marker +from pip._vendor.packaging.requirements import InvalidRequirement, Requirement +from pip._vendor.packaging.specifiers import Specifier + +from pip._internal.exceptions import InstallationError +from pip._internal.models.index import PyPI, TestPyPI +from pip._internal.models.link import Link +from pip._internal.models.wheel import Wheel +from pip._internal.req.req_file import ParsedRequirement +from pip._internal.req.req_install import InstallRequirement +from pip._internal.utils.filetypes import is_archive_file +from pip._internal.utils.misc import is_installable_dir +from pip._internal.utils.packaging import get_requirement +from pip._internal.utils.urls import path_to_url +from pip._internal.vcs import is_url, vcs + +__all__ = [ + "install_req_from_editable", + "install_req_from_line", + "parse_editable", +] + +logger = logging.getLogger(__name__) +operators = Specifier._operators.keys() + + +def _strip_extras(path: str) -> Tuple[str, Optional[str]]: + m = re.match(r"^(.+)(\[[^\]]+\])$", path) + extras = None + if m: + path_no_extras = m.group(1) + extras = m.group(2) + else: + path_no_extras = path + + return path_no_extras, extras + + +def convert_extras(extras: Optional[str]) -> Set[str]: + if not extras: + return set() + return get_requirement("placeholder" + extras.lower()).extras + + +def parse_editable(editable_req: str) -> Tuple[Optional[str], str, Set[str]]: + """Parses an editable requirement into: + - a requirement name + - an URL + - extras + - editable options + Accepted requirements: + svn+http://blahblah@rev#egg=Foobar[baz]&subdirectory=version_subdir + .[some_extra] + """ + + url = editable_req + + # If a file path is specified with extras, strip off the extras. + url_no_extras, extras = _strip_extras(url) + + if os.path.isdir(url_no_extras): + # Treating it as code that has already been checked out + url_no_extras = path_to_url(url_no_extras) + + if url_no_extras.lower().startswith("file:"): + package_name = Link(url_no_extras).egg_fragment + if extras: + return ( + package_name, + url_no_extras, + get_requirement("placeholder" + extras.lower()).extras, + ) + else: + return package_name, url_no_extras, set() + + for version_control in vcs: + if url.lower().startswith(f"{version_control}:"): + url = f"{version_control}+{url}" + break + + link = Link(url) + + if not link.is_vcs: + backends = ", ".join(vcs.all_schemes) + raise InstallationError( + f"{editable_req} is not a valid editable requirement. " + f"It should either be a path to a local project or a VCS URL " + f"(beginning with {backends})." + ) + + package_name = link.egg_fragment + if not package_name: + raise InstallationError( + "Could not detect requirement name for '{}', please specify one " + "with #egg=your_package_name".format(editable_req) + ) + return package_name, url, set() + + +def check_first_requirement_in_file(filename: str) -> None: + """Check if file is parsable as a requirements file. + + This is heavily based on ``pkg_resources.parse_requirements``, but + simplified to just check the first meaningful line. + + :raises InvalidRequirement: If the first meaningful line cannot be parsed + as an requirement. + """ + with open(filename, encoding="utf-8", errors="ignore") as f: + # Create a steppable iterator, so we can handle \-continuations. + lines = ( + line + for line in (line.strip() for line in f) + if line and not line.startswith("#") # Skip blank lines/comments. + ) + + for line in lines: + # Drop comments -- a hash without a space may be in a URL. + if " #" in line: + line = line[: line.find(" #")] + # If there is a line continuation, drop it, and append the next line. + if line.endswith("\\"): + line = line[:-2].strip() + next(lines, "") + Requirement(line) + return + + +def deduce_helpful_msg(req: str) -> str: + """Returns helpful msg in case requirements file does not exist, + or cannot be parsed. + + :params req: Requirements file path + """ + if not os.path.exists(req): + return f" File '{req}' does not exist." + msg = " The path does exist. " + # Try to parse and check if it is a requirements file. + try: + check_first_requirement_in_file(req) + except InvalidRequirement: + logger.debug("Cannot parse '%s' as requirements file", req) + else: + msg += ( + f"The argument you provided " + f"({req}) appears to be a" + f" requirements file. If that is the" + f" case, use the '-r' flag to install" + f" the packages specified within it." + ) + return msg + + +class RequirementParts: + def __init__( + self, + requirement: Optional[Requirement], + link: Optional[Link], + markers: Optional[Marker], + extras: Set[str], + ): + self.requirement = requirement + self.link = link + self.markers = markers + self.extras = extras + + +def parse_req_from_editable(editable_req: str) -> RequirementParts: + name, url, extras_override = parse_editable(editable_req) + + if name is not None: + try: + req: Optional[Requirement] = Requirement(name) + except InvalidRequirement: + raise InstallationError(f"Invalid requirement: '{name}'") + else: + req = None + + link = Link(url) + + return RequirementParts(req, link, None, extras_override) + + +# ---- The actual constructors follow ---- + + +def install_req_from_editable( + editable_req: str, + comes_from: Optional[Union[InstallRequirement, str]] = None, + use_pep517: Optional[bool] = None, + isolated: bool = False, + options: Optional[Dict[str, Any]] = None, + constraint: bool = False, + user_supplied: bool = False, + permit_editable_wheels: bool = False, +) -> InstallRequirement: + + parts = parse_req_from_editable(editable_req) + + return InstallRequirement( + parts.requirement, + comes_from=comes_from, + user_supplied=user_supplied, + editable=True, + permit_editable_wheels=permit_editable_wheels, + link=parts.link, + constraint=constraint, + use_pep517=use_pep517, + isolated=isolated, + install_options=options.get("install_options", []) if options else [], + global_options=options.get("global_options", []) if options else [], + hash_options=options.get("hashes", {}) if options else {}, + extras=parts.extras, + ) + + +def _looks_like_path(name: str) -> bool: + """Checks whether the string "looks like" a path on the filesystem. + + This does not check whether the target actually exists, only judge from the + appearance. + + Returns true if any of the following conditions is true: + * a path separator is found (either os.path.sep or os.path.altsep); + * a dot is found (which represents the current directory). + """ + if os.path.sep in name: + return True + if os.path.altsep is not None and os.path.altsep in name: + return True + if name.startswith("."): + return True + return False + + +def _get_url_from_path(path: str, name: str) -> Optional[str]: + """ + First, it checks whether a provided path is an installable directory. If it + is, returns the path. + + If false, check if the path is an archive file (such as a .whl). + The function checks if the path is a file. If false, if the path has + an @, it will treat it as a PEP 440 URL requirement and return the path. + """ + if _looks_like_path(name) and os.path.isdir(path): + if is_installable_dir(path): + return path_to_url(path) + # TODO: The is_installable_dir test here might not be necessary + # now that it is done in load_pyproject_toml too. + raise InstallationError( + f"Directory {name!r} is not installable. Neither 'setup.py' " + "nor 'pyproject.toml' found." + ) + if not is_archive_file(path): + return None + if os.path.isfile(path): + return path_to_url(path) + urlreq_parts = name.split("@", 1) + if len(urlreq_parts) >= 2 and not _looks_like_path(urlreq_parts[0]): + # If the path contains '@' and the part before it does not look + # like a path, try to treat it as a PEP 440 URL req instead. + return None + logger.warning( + "Requirement %r looks like a filename, but the file does not exist", + name, + ) + return path_to_url(path) + + +def parse_req_from_line(name: str, line_source: Optional[str]) -> RequirementParts: + if is_url(name): + marker_sep = "; " + else: + marker_sep = ";" + if marker_sep in name: + name, markers_as_string = name.split(marker_sep, 1) + markers_as_string = markers_as_string.strip() + if not markers_as_string: + markers = None + else: + markers = Marker(markers_as_string) + else: + markers = None + name = name.strip() + req_as_string = None + path = os.path.normpath(os.path.abspath(name)) + link = None + extras_as_string = None + + if is_url(name): + link = Link(name) + else: + p, extras_as_string = _strip_extras(path) + url = _get_url_from_path(p, name) + if url is not None: + link = Link(url) + + # it's a local file, dir, or url + if link: + # Handle relative file URLs + if link.scheme == "file" and re.search(r"\.\./", link.url): + link = Link(path_to_url(os.path.normpath(os.path.abspath(link.path)))) + # wheel file + if link.is_wheel: + wheel = Wheel(link.filename) # can raise InvalidWheelFilename + req_as_string = f"{wheel.name}=={wheel.version}" + else: + # set the req to the egg fragment. when it's not there, this + # will become an 'unnamed' requirement + req_as_string = link.egg_fragment + + # a requirement specifier + else: + req_as_string = name + + extras = convert_extras(extras_as_string) + + def with_source(text: str) -> str: + if not line_source: + return text + return f"{text} (from {line_source})" + + def _parse_req_string(req_as_string: str) -> Requirement: + try: + req = get_requirement(req_as_string) + except InvalidRequirement: + if os.path.sep in req_as_string: + add_msg = "It looks like a path." + add_msg += deduce_helpful_msg(req_as_string) + elif "=" in req_as_string and not any( + op in req_as_string for op in operators + ): + add_msg = "= is not a valid operator. Did you mean == ?" + else: + add_msg = "" + msg = with_source(f"Invalid requirement: {req_as_string!r}") + if add_msg: + msg += f"\nHint: {add_msg}" + raise InstallationError(msg) + else: + # Deprecate extras after specifiers: "name>=1.0[extras]" + # This currently works by accident because _strip_extras() parses + # any extras in the end of the string and those are saved in + # RequirementParts + for spec in req.specifier: + spec_str = str(spec) + if spec_str.endswith("]"): + msg = f"Extras after version '{spec_str}'." + raise InstallationError(msg) + return req + + if req_as_string is not None: + req: Optional[Requirement] = _parse_req_string(req_as_string) + else: + req = None + + return RequirementParts(req, link, markers, extras) + + +def install_req_from_line( + name: str, + comes_from: Optional[Union[str, InstallRequirement]] = None, + use_pep517: Optional[bool] = None, + isolated: bool = False, + options: Optional[Dict[str, Any]] = None, + constraint: bool = False, + line_source: Optional[str] = None, + user_supplied: bool = False, +) -> InstallRequirement: + """Creates an InstallRequirement from a name, which might be a + requirement, directory containing 'setup.py', filename, or URL. + + :param line_source: An optional string describing where the line is from, + for logging purposes in case of an error. + """ + parts = parse_req_from_line(name, line_source) + + return InstallRequirement( + parts.requirement, + comes_from, + link=parts.link, + markers=parts.markers, + use_pep517=use_pep517, + isolated=isolated, + install_options=options.get("install_options", []) if options else [], + global_options=options.get("global_options", []) if options else [], + hash_options=options.get("hashes", {}) if options else {}, + constraint=constraint, + extras=parts.extras, + user_supplied=user_supplied, + ) + + +def install_req_from_req_string( + req_string: str, + comes_from: Optional[InstallRequirement] = None, + isolated: bool = False, + use_pep517: Optional[bool] = None, + user_supplied: bool = False, +) -> InstallRequirement: + try: + req = get_requirement(req_string) + except InvalidRequirement: + raise InstallationError(f"Invalid requirement: '{req_string}'") + + domains_not_allowed = [ + PyPI.file_storage_domain, + TestPyPI.file_storage_domain, + ] + if ( + req.url + and comes_from + and comes_from.link + and comes_from.link.netloc in domains_not_allowed + ): + # Explicitly disallow pypi packages that depend on external urls + raise InstallationError( + "Packages installed from PyPI cannot depend on packages " + "which are not also hosted on PyPI.\n" + "{} depends on {} ".format(comes_from.name, req) + ) + + return InstallRequirement( + req, + comes_from, + isolated=isolated, + use_pep517=use_pep517, + user_supplied=user_supplied, + ) + + +def install_req_from_parsed_requirement( + parsed_req: ParsedRequirement, + isolated: bool = False, + use_pep517: Optional[bool] = None, + user_supplied: bool = False, +) -> InstallRequirement: + if parsed_req.is_editable: + req = install_req_from_editable( + parsed_req.requirement, + comes_from=parsed_req.comes_from, + use_pep517=use_pep517, + constraint=parsed_req.constraint, + isolated=isolated, + user_supplied=user_supplied, + ) + + else: + req = install_req_from_line( + parsed_req.requirement, + comes_from=parsed_req.comes_from, + use_pep517=use_pep517, + isolated=isolated, + options=parsed_req.options, + constraint=parsed_req.constraint, + line_source=parsed_req.line_source, + user_supplied=user_supplied, + ) + return req + + +def install_req_from_link_and_ireq( + link: Link, ireq: InstallRequirement +) -> InstallRequirement: + return InstallRequirement( + req=ireq.req, + comes_from=ireq.comes_from, + editable=ireq.editable, + link=link, + markers=ireq.markers, + use_pep517=ireq.use_pep517, + isolated=ireq.isolated, + install_options=ireq.install_options, + global_options=ireq.global_options, + hash_options=ireq.hash_options, + ) diff --git a/venv/Lib/site-packages/pip/_internal/req/req_file.py b/venv/Lib/site-packages/pip/_internal/req/req_file.py new file mode 100644 index 0000000..03ae504 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/req/req_file.py @@ -0,0 +1,536 @@ +""" +Requirements file parsing +""" + +import optparse +import os +import re +import shlex +import urllib.parse +from optparse import Values +from typing import ( + TYPE_CHECKING, + Any, + Callable, + Dict, + Iterable, + Iterator, + List, + Optional, + Tuple, +) + +from pip._internal.cli import cmdoptions +from pip._internal.exceptions import InstallationError, RequirementsFileParseError +from pip._internal.models.search_scope import SearchScope +from pip._internal.network.session import PipSession +from pip._internal.network.utils import raise_for_status +from pip._internal.utils.encoding import auto_decode +from pip._internal.utils.urls import get_url_scheme + +if TYPE_CHECKING: + # NoReturn introduced in 3.6.2; imported only for type checking to maintain + # pip compatibility with older patch versions of Python 3.6 + from typing import NoReturn + + from pip._internal.index.package_finder import PackageFinder + +__all__ = ["parse_requirements"] + +ReqFileLines = Iterable[Tuple[int, str]] + +LineParser = Callable[[str], Tuple[str, Values]] + +SCHEME_RE = re.compile(r"^(http|https|file):", re.I) +COMMENT_RE = re.compile(r"(^|\s+)#.*$") + +# Matches environment variable-style values in '${MY_VARIABLE_1}' with the +# variable name consisting of only uppercase letters, digits or the '_' +# (underscore). This follows the POSIX standard defined in IEEE Std 1003.1, +# 2013 Edition. +ENV_VAR_RE = re.compile(r"(?P\$\{(?P[A-Z0-9_]+)\})") + +SUPPORTED_OPTIONS: List[Callable[..., optparse.Option]] = [ + cmdoptions.index_url, + cmdoptions.extra_index_url, + cmdoptions.no_index, + cmdoptions.constraints, + cmdoptions.requirements, + cmdoptions.editable, + cmdoptions.find_links, + cmdoptions.no_binary, + cmdoptions.only_binary, + cmdoptions.prefer_binary, + cmdoptions.require_hashes, + cmdoptions.pre, + cmdoptions.trusted_host, + cmdoptions.use_new_feature, +] + +# options to be passed to requirements +SUPPORTED_OPTIONS_REQ: List[Callable[..., optparse.Option]] = [ + cmdoptions.install_options, + cmdoptions.global_options, + cmdoptions.hash, +] + +# the 'dest' string values +SUPPORTED_OPTIONS_REQ_DEST = [str(o().dest) for o in SUPPORTED_OPTIONS_REQ] + + +class ParsedRequirement: + def __init__( + self, + requirement: str, + is_editable: bool, + comes_from: str, + constraint: bool, + options: Optional[Dict[str, Any]] = None, + line_source: Optional[str] = None, + ) -> None: + self.requirement = requirement + self.is_editable = is_editable + self.comes_from = comes_from + self.options = options + self.constraint = constraint + self.line_source = line_source + + +class ParsedLine: + def __init__( + self, + filename: str, + lineno: int, + args: str, + opts: Values, + constraint: bool, + ) -> None: + self.filename = filename + self.lineno = lineno + self.opts = opts + self.constraint = constraint + + if args: + self.is_requirement = True + self.is_editable = False + self.requirement = args + elif opts.editables: + self.is_requirement = True + self.is_editable = True + # We don't support multiple -e on one line + self.requirement = opts.editables[0] + else: + self.is_requirement = False + + +def parse_requirements( + filename: str, + session: PipSession, + finder: Optional["PackageFinder"] = None, + options: Optional[optparse.Values] = None, + constraint: bool = False, +) -> Iterator[ParsedRequirement]: + """Parse a requirements file and yield ParsedRequirement instances. + + :param filename: Path or url of requirements file. + :param session: PipSession instance. + :param finder: Instance of pip.index.PackageFinder. + :param options: cli options. + :param constraint: If true, parsing a constraint file rather than + requirements file. + """ + line_parser = get_line_parser(finder) + parser = RequirementsFileParser(session, line_parser) + + for parsed_line in parser.parse(filename, constraint): + parsed_req = handle_line( + parsed_line, options=options, finder=finder, session=session + ) + if parsed_req is not None: + yield parsed_req + + +def preprocess(content: str) -> ReqFileLines: + """Split, filter, and join lines, and return a line iterator + + :param content: the content of the requirements file + """ + lines_enum: ReqFileLines = enumerate(content.splitlines(), start=1) + lines_enum = join_lines(lines_enum) + lines_enum = ignore_comments(lines_enum) + lines_enum = expand_env_variables(lines_enum) + return lines_enum + + +def handle_requirement_line( + line: ParsedLine, + options: Optional[optparse.Values] = None, +) -> ParsedRequirement: + + # preserve for the nested code path + line_comes_from = "{} {} (line {})".format( + "-c" if line.constraint else "-r", + line.filename, + line.lineno, + ) + + assert line.is_requirement + + if line.is_editable: + # For editable requirements, we don't support per-requirement + # options, so just return the parsed requirement. + return ParsedRequirement( + requirement=line.requirement, + is_editable=line.is_editable, + comes_from=line_comes_from, + constraint=line.constraint, + ) + else: + if options: + # Disable wheels if the user has specified build options + cmdoptions.check_install_build_global(options, line.opts) + + # get the options that apply to requirements + req_options = {} + for dest in SUPPORTED_OPTIONS_REQ_DEST: + if dest in line.opts.__dict__ and line.opts.__dict__[dest]: + req_options[dest] = line.opts.__dict__[dest] + + line_source = f"line {line.lineno} of {line.filename}" + return ParsedRequirement( + requirement=line.requirement, + is_editable=line.is_editable, + comes_from=line_comes_from, + constraint=line.constraint, + options=req_options, + line_source=line_source, + ) + + +def handle_option_line( + opts: Values, + filename: str, + lineno: int, + finder: Optional["PackageFinder"] = None, + options: Optional[optparse.Values] = None, + session: Optional[PipSession] = None, +) -> None: + + if options: + # percolate options upward + if opts.require_hashes: + options.require_hashes = opts.require_hashes + if opts.features_enabled: + options.features_enabled.extend( + f for f in opts.features_enabled if f not in options.features_enabled + ) + + # set finder options + if finder: + find_links = finder.find_links + index_urls = finder.index_urls + if opts.index_url: + index_urls = [opts.index_url] + if opts.no_index is True: + index_urls = [] + if opts.extra_index_urls: + index_urls.extend(opts.extra_index_urls) + if opts.find_links: + # FIXME: it would be nice to keep track of the source + # of the find_links: support a find-links local path + # relative to a requirements file. + value = opts.find_links[0] + req_dir = os.path.dirname(os.path.abspath(filename)) + relative_to_reqs_file = os.path.join(req_dir, value) + if os.path.exists(relative_to_reqs_file): + value = relative_to_reqs_file + find_links.append(value) + + if session: + # We need to update the auth urls in session + session.update_index_urls(index_urls) + + search_scope = SearchScope( + find_links=find_links, + index_urls=index_urls, + ) + finder.search_scope = search_scope + + if opts.pre: + finder.set_allow_all_prereleases() + + if opts.prefer_binary: + finder.set_prefer_binary() + + if session: + for host in opts.trusted_hosts or []: + source = f"line {lineno} of {filename}" + session.add_trusted_host(host, source=source) + + +def handle_line( + line: ParsedLine, + options: Optional[optparse.Values] = None, + finder: Optional["PackageFinder"] = None, + session: Optional[PipSession] = None, +) -> Optional[ParsedRequirement]: + """Handle a single parsed requirements line; This can result in + creating/yielding requirements, or updating the finder. + + :param line: The parsed line to be processed. + :param options: CLI options. + :param finder: The finder - updated by non-requirement lines. + :param session: The session - updated by non-requirement lines. + + Returns a ParsedRequirement object if the line is a requirement line, + otherwise returns None. + + For lines that contain requirements, the only options that have an effect + are from SUPPORTED_OPTIONS_REQ, and they are scoped to the + requirement. Other options from SUPPORTED_OPTIONS may be present, but are + ignored. + + For lines that do not contain requirements, the only options that have an + effect are from SUPPORTED_OPTIONS. Options from SUPPORTED_OPTIONS_REQ may + be present, but are ignored. These lines may contain multiple options + (although our docs imply only one is supported), and all our parsed and + affect the finder. + """ + + if line.is_requirement: + parsed_req = handle_requirement_line(line, options) + return parsed_req + else: + handle_option_line( + line.opts, + line.filename, + line.lineno, + finder, + options, + session, + ) + return None + + +class RequirementsFileParser: + def __init__( + self, + session: PipSession, + line_parser: LineParser, + ) -> None: + self._session = session + self._line_parser = line_parser + + def parse(self, filename: str, constraint: bool) -> Iterator[ParsedLine]: + """Parse a given file, yielding parsed lines.""" + yield from self._parse_and_recurse(filename, constraint) + + def _parse_and_recurse( + self, filename: str, constraint: bool + ) -> Iterator[ParsedLine]: + for line in self._parse_file(filename, constraint): + if not line.is_requirement and ( + line.opts.requirements or line.opts.constraints + ): + # parse a nested requirements file + if line.opts.requirements: + req_path = line.opts.requirements[0] + nested_constraint = False + else: + req_path = line.opts.constraints[0] + nested_constraint = True + + # original file is over http + if SCHEME_RE.search(filename): + # do a url join so relative paths work + req_path = urllib.parse.urljoin(filename, req_path) + # original file and nested file are paths + elif not SCHEME_RE.search(req_path): + # do a join so relative paths work + req_path = os.path.join( + os.path.dirname(filename), + req_path, + ) + + yield from self._parse_and_recurse(req_path, nested_constraint) + else: + yield line + + def _parse_file(self, filename: str, constraint: bool) -> Iterator[ParsedLine]: + _, content = get_file_content(filename, self._session) + + lines_enum = preprocess(content) + + for line_number, line in lines_enum: + try: + args_str, opts = self._line_parser(line) + except OptionParsingError as e: + # add offending line + msg = f"Invalid requirement: {line}\n{e.msg}" + raise RequirementsFileParseError(msg) + + yield ParsedLine( + filename, + line_number, + args_str, + opts, + constraint, + ) + + +def get_line_parser(finder: Optional["PackageFinder"]) -> LineParser: + def parse_line(line: str) -> Tuple[str, Values]: + # Build new parser for each line since it accumulates appendable + # options. + parser = build_parser() + defaults = parser.get_default_values() + defaults.index_url = None + if finder: + defaults.format_control = finder.format_control + + args_str, options_str = break_args_options(line) + + opts, _ = parser.parse_args(shlex.split(options_str), defaults) + + return args_str, opts + + return parse_line + + +def break_args_options(line: str) -> Tuple[str, str]: + """Break up the line into an args and options string. We only want to shlex + (and then optparse) the options, not the args. args can contain markers + which are corrupted by shlex. + """ + tokens = line.split(" ") + args = [] + options = tokens[:] + for token in tokens: + if token.startswith("-") or token.startswith("--"): + break + else: + args.append(token) + options.pop(0) + return " ".join(args), " ".join(options) + + +class OptionParsingError(Exception): + def __init__(self, msg: str) -> None: + self.msg = msg + + +def build_parser() -> optparse.OptionParser: + """ + Return a parser for parsing requirement lines + """ + parser = optparse.OptionParser(add_help_option=False) + + option_factories = SUPPORTED_OPTIONS + SUPPORTED_OPTIONS_REQ + for option_factory in option_factories: + option = option_factory() + parser.add_option(option) + + # By default optparse sys.exits on parsing errors. We want to wrap + # that in our own exception. + def parser_exit(self: Any, msg: str) -> "NoReturn": + raise OptionParsingError(msg) + + # NOTE: mypy disallows assigning to a method + # https://github.com/python/mypy/issues/2427 + parser.exit = parser_exit # type: ignore + + return parser + + +def join_lines(lines_enum: ReqFileLines) -> ReqFileLines: + """Joins a line ending in '\' with the previous line (except when following + comments). The joined line takes on the index of the first line. + """ + primary_line_number = None + new_line: List[str] = [] + for line_number, line in lines_enum: + if not line.endswith("\\") or COMMENT_RE.match(line): + if COMMENT_RE.match(line): + # this ensures comments are always matched later + line = " " + line + if new_line: + new_line.append(line) + assert primary_line_number is not None + yield primary_line_number, "".join(new_line) + new_line = [] + else: + yield line_number, line + else: + if not new_line: + primary_line_number = line_number + new_line.append(line.strip("\\")) + + # last line contains \ + if new_line: + assert primary_line_number is not None + yield primary_line_number, "".join(new_line) + + # TODO: handle space after '\'. + + +def ignore_comments(lines_enum: ReqFileLines) -> ReqFileLines: + """ + Strips comments and filter empty lines. + """ + for line_number, line in lines_enum: + line = COMMENT_RE.sub("", line) + line = line.strip() + if line: + yield line_number, line + + +def expand_env_variables(lines_enum: ReqFileLines) -> ReqFileLines: + """Replace all environment variables that can be retrieved via `os.getenv`. + + The only allowed format for environment variables defined in the + requirement file is `${MY_VARIABLE_1}` to ensure two things: + + 1. Strings that contain a `$` aren't accidentally (partially) expanded. + 2. Ensure consistency across platforms for requirement files. + + These points are the result of a discussion on the `github pull + request #3514 `_. + + Valid characters in variable names follow the `POSIX standard + `_ and are limited + to uppercase letter, digits and the `_` (underscore). + """ + for line_number, line in lines_enum: + for env_var, var_name in ENV_VAR_RE.findall(line): + value = os.getenv(var_name) + if not value: + continue + + line = line.replace(env_var, value) + + yield line_number, line + + +def get_file_content(url: str, session: PipSession) -> Tuple[str, str]: + """Gets the content of a file; it may be a filename, file: URL, or + http: URL. Returns (location, content). Content is unicode. + Respects # -*- coding: declarations on the retrieved files. + + :param url: File path or url. + :param session: PipSession instance. + """ + scheme = get_url_scheme(url) + + # Pip has special support for file:// URLs (LocalFSAdapter). + if scheme in ["http", "https", "file"]: + resp = session.get(url) + raise_for_status(resp) + return resp.url, resp.text + + # Assume this is a bare path. + try: + with open(url, "rb") as f: + content = auto_decode(f.read()) + except OSError as exc: + raise InstallationError(f"Could not open requirements file: {exc}") + return url, content diff --git a/venv/Lib/site-packages/pip/_internal/req/req_install.py b/venv/Lib/site-packages/pip/_internal/req/req_install.py new file mode 100644 index 0000000..02dbda1 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/req/req_install.py @@ -0,0 +1,858 @@ +# The following comment should be removed at some point in the future. +# mypy: strict-optional=False + +import functools +import logging +import os +import shutil +import sys +import uuid +import zipfile +from typing import Any, Collection, Dict, Iterable, List, Optional, Sequence, Union + +from pip._vendor.packaging.markers import Marker +from pip._vendor.packaging.requirements import Requirement +from pip._vendor.packaging.specifiers import SpecifierSet +from pip._vendor.packaging.utils import canonicalize_name +from pip._vendor.packaging.version import Version +from pip._vendor.packaging.version import parse as parse_version +from pip._vendor.pep517.wrappers import Pep517HookCaller + +from pip._internal.build_env import BuildEnvironment, NoOpBuildEnvironment +from pip._internal.exceptions import InstallationError, LegacyInstallFailure +from pip._internal.locations import get_scheme +from pip._internal.metadata import ( + BaseDistribution, + get_default_environment, + get_directory_distribution, +) +from pip._internal.models.link import Link +from pip._internal.operations.build.metadata import generate_metadata +from pip._internal.operations.build.metadata_editable import generate_editable_metadata +from pip._internal.operations.build.metadata_legacy import ( + generate_metadata as generate_metadata_legacy, +) +from pip._internal.operations.install.editable_legacy import ( + install_editable as install_editable_legacy, +) +from pip._internal.operations.install.legacy import install as install_legacy +from pip._internal.operations.install.wheel import install_wheel +from pip._internal.pyproject import load_pyproject_toml, make_pyproject_path +from pip._internal.req.req_uninstall import UninstallPathSet +from pip._internal.utils.deprecation import deprecated +from pip._internal.utils.direct_url_helpers import ( + direct_url_for_editable, + direct_url_from_link, +) +from pip._internal.utils.hashes import Hashes +from pip._internal.utils.misc import ( + ask_path_exists, + backup_dir, + display_path, + hide_url, + redact_auth_from_url, +) +from pip._internal.utils.packaging import safe_extra +from pip._internal.utils.subprocess import runner_with_spinner_message +from pip._internal.utils.temp_dir import TempDirectory, tempdir_kinds +from pip._internal.utils.virtualenv import running_under_virtualenv +from pip._internal.vcs import vcs + +logger = logging.getLogger(__name__) + + +class InstallRequirement: + """ + Represents something that may be installed later on, may have information + about where to fetch the relevant requirement and also contains logic for + installing the said requirement. + """ + + def __init__( + self, + req: Optional[Requirement], + comes_from: Optional[Union[str, "InstallRequirement"]], + editable: bool = False, + link: Optional[Link] = None, + markers: Optional[Marker] = None, + use_pep517: Optional[bool] = None, + isolated: bool = False, + install_options: Optional[List[str]] = None, + global_options: Optional[List[str]] = None, + hash_options: Optional[Dict[str, List[str]]] = None, + constraint: bool = False, + extras: Collection[str] = (), + user_supplied: bool = False, + permit_editable_wheels: bool = False, + ) -> None: + assert req is None or isinstance(req, Requirement), req + self.req = req + self.comes_from = comes_from + self.constraint = constraint + self.editable = editable + self.permit_editable_wheels = permit_editable_wheels + self.legacy_install_reason: Optional[int] = None + + # source_dir is the local directory where the linked requirement is + # located, or unpacked. In case unpacking is needed, creating and + # populating source_dir is done by the RequirementPreparer. Note this + # is not necessarily the directory where pyproject.toml or setup.py is + # located - that one is obtained via unpacked_source_directory. + self.source_dir: Optional[str] = None + if self.editable: + assert link + if link.is_file: + self.source_dir = os.path.normpath(os.path.abspath(link.file_path)) + + if link is None and req and req.url: + # PEP 508 URL requirement + link = Link(req.url) + self.link = self.original_link = link + self.original_link_is_in_wheel_cache = False + + # Path to any downloaded or already-existing package. + self.local_file_path: Optional[str] = None + if self.link and self.link.is_file: + self.local_file_path = self.link.file_path + + if extras: + self.extras = extras + elif req: + self.extras = {safe_extra(extra) for extra in req.extras} + else: + self.extras = set() + if markers is None and req: + markers = req.marker + self.markers = markers + + # This holds the Distribution object if this requirement is already installed. + self.satisfied_by: Optional[BaseDistribution] = None + # Whether the installation process should try to uninstall an existing + # distribution before installing this requirement. + self.should_reinstall = False + # Temporary build location + self._temp_build_dir: Optional[TempDirectory] = None + # Set to True after successful installation + self.install_succeeded: Optional[bool] = None + # Supplied options + self.install_options = install_options if install_options else [] + self.global_options = global_options if global_options else [] + self.hash_options = hash_options if hash_options else {} + # Set to True after successful preparation of this requirement + self.prepared = False + # User supplied requirement are explicitly requested for installation + # by the user via CLI arguments or requirements files, as opposed to, + # e.g. dependencies, extras or constraints. + self.user_supplied = user_supplied + + self.isolated = isolated + self.build_env: BuildEnvironment = NoOpBuildEnvironment() + + # For PEP 517, the directory where we request the project metadata + # gets stored. We need this to pass to build_wheel, so the backend + # can ensure that the wheel matches the metadata (see the PEP for + # details). + self.metadata_directory: Optional[str] = None + + # The static build requirements (from pyproject.toml) + self.pyproject_requires: Optional[List[str]] = None + + # Build requirements that we will check are available + self.requirements_to_check: List[str] = [] + + # The PEP 517 backend we should use to build the project + self.pep517_backend: Optional[Pep517HookCaller] = None + + # Are we using PEP 517 for this requirement? + # After pyproject.toml has been loaded, the only valid values are True + # and False. Before loading, None is valid (meaning "use the default"). + # Setting an explicit value before loading pyproject.toml is supported, + # but after loading this flag should be treated as read only. + self.use_pep517 = use_pep517 + + # This requirement needs more preparation before it can be built + self.needs_more_preparation = False + + def __str__(self) -> str: + if self.req: + s = str(self.req) + if self.link: + s += " from {}".format(redact_auth_from_url(self.link.url)) + elif self.link: + s = redact_auth_from_url(self.link.url) + else: + s = "" + if self.satisfied_by is not None: + s += " in {}".format(display_path(self.satisfied_by.location)) + if self.comes_from: + if isinstance(self.comes_from, str): + comes_from: Optional[str] = self.comes_from + else: + comes_from = self.comes_from.from_path() + if comes_from: + s += f" (from {comes_from})" + return s + + def __repr__(self) -> str: + return "<{} object: {} editable={!r}>".format( + self.__class__.__name__, str(self), self.editable + ) + + def format_debug(self) -> str: + """An un-tested helper for getting state, for debugging.""" + attributes = vars(self) + names = sorted(attributes) + + state = ("{}={!r}".format(attr, attributes[attr]) for attr in sorted(names)) + return "<{name} object: {{{state}}}>".format( + name=self.__class__.__name__, + state=", ".join(state), + ) + + # Things that are valid for all kinds of requirements? + @property + def name(self) -> Optional[str]: + if self.req is None: + return None + return self.req.name + + @functools.lru_cache() # use cached_property in python 3.8+ + def supports_pyproject_editable(self) -> bool: + if not self.use_pep517: + return False + assert self.pep517_backend + with self.build_env: + runner = runner_with_spinner_message( + "Checking if build backend supports build_editable" + ) + with self.pep517_backend.subprocess_runner(runner): + return "build_editable" in self.pep517_backend._supported_features() + + @property + def specifier(self) -> SpecifierSet: + return self.req.specifier + + @property + def is_pinned(self) -> bool: + """Return whether I am pinned to an exact version. + + For example, some-package==1.2 is pinned; some-package>1.2 is not. + """ + specifiers = self.specifier + return len(specifiers) == 1 and next(iter(specifiers)).operator in {"==", "==="} + + def match_markers(self, extras_requested: Optional[Iterable[str]] = None) -> bool: + if not extras_requested: + # Provide an extra to safely evaluate the markers + # without matching any extra + extras_requested = ("",) + if self.markers is not None: + return any( + self.markers.evaluate({"extra": extra}) for extra in extras_requested + ) + else: + return True + + @property + def has_hash_options(self) -> bool: + """Return whether any known-good hashes are specified as options. + + These activate --require-hashes mode; hashes specified as part of a + URL do not. + + """ + return bool(self.hash_options) + + def hashes(self, trust_internet: bool = True) -> Hashes: + """Return a hash-comparer that considers my option- and URL-based + hashes to be known-good. + + Hashes in URLs--ones embedded in the requirements file, not ones + downloaded from an index server--are almost peers with ones from + flags. They satisfy --require-hashes (whether it was implicitly or + explicitly activated) but do not activate it. md5 and sha224 are not + allowed in flags, which should nudge people toward good algos. We + always OR all hashes together, even ones from URLs. + + :param trust_internet: Whether to trust URL-based (#md5=...) hashes + downloaded from the internet, as by populate_link() + + """ + good_hashes = self.hash_options.copy() + link = self.link if trust_internet else self.original_link + if link and link.hash: + good_hashes.setdefault(link.hash_name, []).append(link.hash) + return Hashes(good_hashes) + + def from_path(self) -> Optional[str]: + """Format a nice indicator to show where this "comes from" """ + if self.req is None: + return None + s = str(self.req) + if self.comes_from: + if isinstance(self.comes_from, str): + comes_from = self.comes_from + else: + comes_from = self.comes_from.from_path() + if comes_from: + s += "->" + comes_from + return s + + def ensure_build_location( + self, build_dir: str, autodelete: bool, parallel_builds: bool + ) -> str: + assert build_dir is not None + if self._temp_build_dir is not None: + assert self._temp_build_dir.path + return self._temp_build_dir.path + if self.req is None: + # Some systems have /tmp as a symlink which confuses custom + # builds (such as numpy). Thus, we ensure that the real path + # is returned. + self._temp_build_dir = TempDirectory( + kind=tempdir_kinds.REQ_BUILD, globally_managed=True + ) + + return self._temp_build_dir.path + + # This is the only remaining place where we manually determine the path + # for the temporary directory. It is only needed for editables where + # it is the value of the --src option. + + # When parallel builds are enabled, add a UUID to the build directory + # name so multiple builds do not interfere with each other. + dir_name: str = canonicalize_name(self.name) + if parallel_builds: + dir_name = f"{dir_name}_{uuid.uuid4().hex}" + + # FIXME: Is there a better place to create the build_dir? (hg and bzr + # need this) + if not os.path.exists(build_dir): + logger.debug("Creating directory %s", build_dir) + os.makedirs(build_dir) + actual_build_dir = os.path.join(build_dir, dir_name) + # `None` indicates that we respect the globally-configured deletion + # settings, which is what we actually want when auto-deleting. + delete_arg = None if autodelete else False + return TempDirectory( + path=actual_build_dir, + delete=delete_arg, + kind=tempdir_kinds.REQ_BUILD, + globally_managed=True, + ).path + + def _set_requirement(self) -> None: + """Set requirement after generating metadata.""" + assert self.req is None + assert self.metadata is not None + assert self.source_dir is not None + + # Construct a Requirement object from the generated metadata + if isinstance(parse_version(self.metadata["Version"]), Version): + op = "==" + else: + op = "===" + + self.req = Requirement( + "".join( + [ + self.metadata["Name"], + op, + self.metadata["Version"], + ] + ) + ) + + def warn_on_mismatching_name(self) -> None: + metadata_name = canonicalize_name(self.metadata["Name"]) + if canonicalize_name(self.req.name) == metadata_name: + # Everything is fine. + return + + # If we're here, there's a mismatch. Log a warning about it. + logger.warning( + "Generating metadata for package %s " + "produced metadata for project name %s. Fix your " + "#egg=%s fragments.", + self.name, + metadata_name, + self.name, + ) + self.req = Requirement(metadata_name) + + def check_if_exists(self, use_user_site: bool) -> None: + """Find an installed distribution that satisfies or conflicts + with this requirement, and set self.satisfied_by or + self.should_reinstall appropriately. + """ + if self.req is None: + return + existing_dist = get_default_environment().get_distribution(self.req.name) + if not existing_dist: + return + + version_compatible = self.req.specifier.contains( + existing_dist.version, + prereleases=True, + ) + if not version_compatible: + self.satisfied_by = None + if use_user_site: + if existing_dist.in_usersite: + self.should_reinstall = True + elif running_under_virtualenv() and existing_dist.in_site_packages: + raise InstallationError( + f"Will not install to the user site because it will " + f"lack sys.path precedence to {existing_dist.raw_name} " + f"in {existing_dist.location}" + ) + else: + self.should_reinstall = True + else: + if self.editable: + self.should_reinstall = True + # when installing editables, nothing pre-existing should ever + # satisfy + self.satisfied_by = None + else: + self.satisfied_by = existing_dist + + # Things valid for wheels + @property + def is_wheel(self) -> bool: + if not self.link: + return False + return self.link.is_wheel + + # Things valid for sdists + @property + def unpacked_source_directory(self) -> str: + return os.path.join( + self.source_dir, self.link and self.link.subdirectory_fragment or "" + ) + + @property + def setup_py_path(self) -> str: + assert self.source_dir, f"No source dir for {self}" + setup_py = os.path.join(self.unpacked_source_directory, "setup.py") + + return setup_py + + @property + def setup_cfg_path(self) -> str: + assert self.source_dir, f"No source dir for {self}" + setup_cfg = os.path.join(self.unpacked_source_directory, "setup.cfg") + + return setup_cfg + + @property + def pyproject_toml_path(self) -> str: + assert self.source_dir, f"No source dir for {self}" + return make_pyproject_path(self.unpacked_source_directory) + + def load_pyproject_toml(self) -> None: + """Load the pyproject.toml file. + + After calling this routine, all of the attributes related to PEP 517 + processing for this requirement have been set. In particular, the + use_pep517 attribute can be used to determine whether we should + follow the PEP 517 or legacy (setup.py) code path. + """ + pyproject_toml_data = load_pyproject_toml( + self.use_pep517, self.pyproject_toml_path, self.setup_py_path, str(self) + ) + + if pyproject_toml_data is None: + self.use_pep517 = False + return + + self.use_pep517 = True + requires, backend, check, backend_path = pyproject_toml_data + self.requirements_to_check = check + self.pyproject_requires = requires + self.pep517_backend = Pep517HookCaller( + self.unpacked_source_directory, + backend, + backend_path=backend_path, + ) + + def isolated_editable_sanity_check(self) -> None: + """Check that an editable requirement if valid for use with PEP 517/518. + + This verifies that an editable that has a pyproject.toml either supports PEP 660 + or as a setup.py or a setup.cfg + """ + if ( + self.editable + and self.use_pep517 + and not self.supports_pyproject_editable() + and not os.path.isfile(self.setup_py_path) + and not os.path.isfile(self.setup_cfg_path) + ): + raise InstallationError( + f"Project {self} has a 'pyproject.toml' and its build " + f"backend is missing the 'build_editable' hook. Since it does not " + f"have a 'setup.py' nor a 'setup.cfg', " + f"it cannot be installed in editable mode. " + f"Consider using a build backend that supports PEP 660." + ) + + def prepare_metadata(self) -> None: + """Ensure that project metadata is available. + + Under PEP 517 and PEP 660, call the backend hook to prepare the metadata. + Under legacy processing, call setup.py egg-info. + """ + assert self.source_dir + details = self.name or f"from {self.link}" + + if self.use_pep517: + assert self.pep517_backend is not None + if ( + self.editable + and self.permit_editable_wheels + and self.supports_pyproject_editable() + ): + self.metadata_directory = generate_editable_metadata( + build_env=self.build_env, + backend=self.pep517_backend, + details=details, + ) + else: + self.metadata_directory = generate_metadata( + build_env=self.build_env, + backend=self.pep517_backend, + details=details, + ) + else: + self.metadata_directory = generate_metadata_legacy( + build_env=self.build_env, + setup_py_path=self.setup_py_path, + source_dir=self.unpacked_source_directory, + isolated=self.isolated, + details=details, + ) + + # Act on the newly generated metadata, based on the name and version. + if not self.name: + self._set_requirement() + else: + self.warn_on_mismatching_name() + + self.assert_source_matches_version() + + @property + def metadata(self) -> Any: + if not hasattr(self, "_metadata"): + self._metadata = self.get_dist().metadata + + return self._metadata + + def get_dist(self) -> BaseDistribution: + return get_directory_distribution(self.metadata_directory) + + def assert_source_matches_version(self) -> None: + assert self.source_dir + version = self.metadata["version"] + if self.req.specifier and version not in self.req.specifier: + logger.warning( + "Requested %s, but installing version %s", + self, + version, + ) + else: + logger.debug( + "Source in %s has version %s, which satisfies requirement %s", + display_path(self.source_dir), + version, + self, + ) + + # For both source distributions and editables + def ensure_has_source_dir( + self, + parent_dir: str, + autodelete: bool = False, + parallel_builds: bool = False, + ) -> None: + """Ensure that a source_dir is set. + + This will create a temporary build dir if the name of the requirement + isn't known yet. + + :param parent_dir: The ideal pip parent_dir for the source_dir. + Generally src_dir for editables and build_dir for sdists. + :return: self.source_dir + """ + if self.source_dir is None: + self.source_dir = self.ensure_build_location( + parent_dir, + autodelete=autodelete, + parallel_builds=parallel_builds, + ) + + # For editable installations + def update_editable(self) -> None: + if not self.link: + logger.debug( + "Cannot update repository at %s; repository location is unknown", + self.source_dir, + ) + return + assert self.editable + assert self.source_dir + if self.link.scheme == "file": + # Static paths don't get updated + return + vcs_backend = vcs.get_backend_for_scheme(self.link.scheme) + # Editable requirements are validated in Requirement constructors. + # So here, if it's neither a path nor a valid VCS URL, it's a bug. + assert vcs_backend, f"Unsupported VCS URL {self.link.url}" + hidden_url = hide_url(self.link.url) + vcs_backend.obtain(self.source_dir, url=hidden_url, verbosity=0) + + # Top-level Actions + def uninstall( + self, auto_confirm: bool = False, verbose: bool = False + ) -> Optional[UninstallPathSet]: + """ + Uninstall the distribution currently satisfying this requirement. + + Prompts before removing or modifying files unless + ``auto_confirm`` is True. + + Refuses to delete or modify files outside of ``sys.prefix`` - + thus uninstallation within a virtual environment can only + modify that virtual environment, even if the virtualenv is + linked to global site-packages. + + """ + assert self.req + dist = get_default_environment().get_distribution(self.req.name) + if not dist: + logger.warning("Skipping %s as it is not installed.", self.name) + return None + logger.info("Found existing installation: %s", dist) + + uninstalled_pathset = UninstallPathSet.from_dist(dist) + uninstalled_pathset.remove(auto_confirm, verbose) + return uninstalled_pathset + + def _get_archive_name(self, path: str, parentdir: str, rootdir: str) -> str: + def _clean_zip_name(name: str, prefix: str) -> str: + assert name.startswith( + prefix + os.path.sep + ), f"name {name!r} doesn't start with prefix {prefix!r}" + name = name[len(prefix) + 1 :] + name = name.replace(os.path.sep, "/") + return name + + path = os.path.join(parentdir, path) + name = _clean_zip_name(path, rootdir) + return self.name + "/" + name + + def archive(self, build_dir: Optional[str]) -> None: + """Saves archive to provided build_dir. + + Used for saving downloaded VCS requirements as part of `pip download`. + """ + assert self.source_dir + if build_dir is None: + return + + create_archive = True + archive_name = "{}-{}.zip".format(self.name, self.metadata["version"]) + archive_path = os.path.join(build_dir, archive_name) + + if os.path.exists(archive_path): + response = ask_path_exists( + "The file {} exists. (i)gnore, (w)ipe, " + "(b)ackup, (a)bort ".format(display_path(archive_path)), + ("i", "w", "b", "a"), + ) + if response == "i": + create_archive = False + elif response == "w": + logger.warning("Deleting %s", display_path(archive_path)) + os.remove(archive_path) + elif response == "b": + dest_file = backup_dir(archive_path) + logger.warning( + "Backing up %s to %s", + display_path(archive_path), + display_path(dest_file), + ) + shutil.move(archive_path, dest_file) + elif response == "a": + sys.exit(-1) + + if not create_archive: + return + + zip_output = zipfile.ZipFile( + archive_path, + "w", + zipfile.ZIP_DEFLATED, + allowZip64=True, + ) + with zip_output: + dir = os.path.normcase(os.path.abspath(self.unpacked_source_directory)) + for dirpath, dirnames, filenames in os.walk(dir): + for dirname in dirnames: + dir_arcname = self._get_archive_name( + dirname, + parentdir=dirpath, + rootdir=dir, + ) + zipdir = zipfile.ZipInfo(dir_arcname + "/") + zipdir.external_attr = 0x1ED << 16 # 0o755 + zip_output.writestr(zipdir, "") + for filename in filenames: + file_arcname = self._get_archive_name( + filename, + parentdir=dirpath, + rootdir=dir, + ) + filename = os.path.join(dirpath, filename) + zip_output.write(filename, file_arcname) + + logger.info("Saved %s", display_path(archive_path)) + + def install( + self, + install_options: List[str], + global_options: Optional[Sequence[str]] = None, + root: Optional[str] = None, + home: Optional[str] = None, + prefix: Optional[str] = None, + warn_script_location: bool = True, + use_user_site: bool = False, + pycompile: bool = True, + ) -> None: + scheme = get_scheme( + self.name, + user=use_user_site, + home=home, + root=root, + isolated=self.isolated, + prefix=prefix, + ) + + global_options = global_options if global_options is not None else [] + if self.editable and not self.is_wheel: + install_editable_legacy( + install_options, + global_options, + prefix=prefix, + home=home, + use_user_site=use_user_site, + name=self.name, + setup_py_path=self.setup_py_path, + isolated=self.isolated, + build_env=self.build_env, + unpacked_source_directory=self.unpacked_source_directory, + ) + self.install_succeeded = True + return + + if self.is_wheel: + assert self.local_file_path + direct_url = None + if self.editable: + direct_url = direct_url_for_editable(self.unpacked_source_directory) + elif self.original_link: + direct_url = direct_url_from_link( + self.original_link, + self.source_dir, + self.original_link_is_in_wheel_cache, + ) + install_wheel( + self.name, + self.local_file_path, + scheme=scheme, + req_description=str(self.req), + pycompile=pycompile, + warn_script_location=warn_script_location, + direct_url=direct_url, + requested=self.user_supplied, + ) + self.install_succeeded = True + return + + # TODO: Why don't we do this for editable installs? + + # Extend the list of global and install options passed on to + # the setup.py call with the ones from the requirements file. + # Options specified in requirements file override those + # specified on the command line, since the last option given + # to setup.py is the one that is used. + global_options = list(global_options) + self.global_options + install_options = list(install_options) + self.install_options + + try: + success = install_legacy( + install_options=install_options, + global_options=global_options, + root=root, + home=home, + prefix=prefix, + use_user_site=use_user_site, + pycompile=pycompile, + scheme=scheme, + setup_py_path=self.setup_py_path, + isolated=self.isolated, + req_name=self.name, + build_env=self.build_env, + unpacked_source_directory=self.unpacked_source_directory, + req_description=str(self.req), + ) + except LegacyInstallFailure as exc: + self.install_succeeded = False + raise exc + except Exception: + self.install_succeeded = True + raise + + self.install_succeeded = success + + if success and self.legacy_install_reason == 8368: + deprecated( + reason=( + "{} was installed using the legacy 'setup.py install' " + "method, because a wheel could not be built for it.".format( + self.name + ) + ), + replacement="to fix the wheel build issue reported above", + gone_in=None, + issue=8368, + ) + + +def check_invalid_constraint_type(req: InstallRequirement) -> str: + + # Check for unsupported forms + problem = "" + if not req.name: + problem = "Unnamed requirements are not allowed as constraints" + elif req.editable: + problem = "Editable requirements are not allowed as constraints" + elif req.extras: + problem = "Constraints cannot have extras" + + if problem: + deprecated( + reason=( + "Constraints are only allowed to take the form of a package " + "name and a version specifier. Other forms were originally " + "permitted as an accident of the implementation, but were " + "undocumented. The new implementation of the resolver no " + "longer supports these forms." + ), + replacement="replacing the constraint with a requirement", + # No plan yet for when the new resolver becomes default + gone_in=None, + issue=8210, + ) + + return problem diff --git a/venv/Lib/site-packages/pip/_internal/req/req_set.py b/venv/Lib/site-packages/pip/_internal/req/req_set.py new file mode 100644 index 0000000..6626c37 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/req/req_set.py @@ -0,0 +1,189 @@ +import logging +from collections import OrderedDict +from typing import Dict, Iterable, List, Optional, Tuple + +from pip._vendor.packaging.utils import canonicalize_name + +from pip._internal.exceptions import InstallationError +from pip._internal.models.wheel import Wheel +from pip._internal.req.req_install import InstallRequirement +from pip._internal.utils import compatibility_tags + +logger = logging.getLogger(__name__) + + +class RequirementSet: + def __init__(self, check_supported_wheels: bool = True) -> None: + """Create a RequirementSet.""" + + self.requirements: Dict[str, InstallRequirement] = OrderedDict() + self.check_supported_wheels = check_supported_wheels + + self.unnamed_requirements: List[InstallRequirement] = [] + + def __str__(self) -> str: + requirements = sorted( + (req for req in self.requirements.values() if not req.comes_from), + key=lambda req: canonicalize_name(req.name or ""), + ) + return " ".join(str(req.req) for req in requirements) + + def __repr__(self) -> str: + requirements = sorted( + self.requirements.values(), + key=lambda req: canonicalize_name(req.name or ""), + ) + + format_string = "<{classname} object; {count} requirement(s): {reqs}>" + return format_string.format( + classname=self.__class__.__name__, + count=len(requirements), + reqs=", ".join(str(req.req) for req in requirements), + ) + + def add_unnamed_requirement(self, install_req: InstallRequirement) -> None: + assert not install_req.name + self.unnamed_requirements.append(install_req) + + def add_named_requirement(self, install_req: InstallRequirement) -> None: + assert install_req.name + + project_name = canonicalize_name(install_req.name) + self.requirements[project_name] = install_req + + def add_requirement( + self, + install_req: InstallRequirement, + parent_req_name: Optional[str] = None, + extras_requested: Optional[Iterable[str]] = None, + ) -> Tuple[List[InstallRequirement], Optional[InstallRequirement]]: + """Add install_req as a requirement to install. + + :param parent_req_name: The name of the requirement that needed this + added. The name is used because when multiple unnamed requirements + resolve to the same name, we could otherwise end up with dependency + links that point outside the Requirements set. parent_req must + already be added. Note that None implies that this is a user + supplied requirement, vs an inferred one. + :param extras_requested: an iterable of extras used to evaluate the + environment markers. + :return: Additional requirements to scan. That is either [] if + the requirement is not applicable, or [install_req] if the + requirement is applicable and has just been added. + """ + # If the markers do not match, ignore this requirement. + if not install_req.match_markers(extras_requested): + logger.info( + "Ignoring %s: markers '%s' don't match your environment", + install_req.name, + install_req.markers, + ) + return [], None + + # If the wheel is not supported, raise an error. + # Should check this after filtering out based on environment markers to + # allow specifying different wheels based on the environment/OS, in a + # single requirements file. + if install_req.link and install_req.link.is_wheel: + wheel = Wheel(install_req.link.filename) + tags = compatibility_tags.get_supported() + if self.check_supported_wheels and not wheel.supported(tags): + raise InstallationError( + "{} is not a supported wheel on this platform.".format( + wheel.filename + ) + ) + + # This next bit is really a sanity check. + assert ( + not install_req.user_supplied or parent_req_name is None + ), "a user supplied req shouldn't have a parent" + + # Unnamed requirements are scanned again and the requirement won't be + # added as a dependency until after scanning. + if not install_req.name: + self.add_unnamed_requirement(install_req) + return [install_req], None + + try: + existing_req: Optional[InstallRequirement] = self.get_requirement( + install_req.name + ) + except KeyError: + existing_req = None + + has_conflicting_requirement = ( + parent_req_name is None + and existing_req + and not existing_req.constraint + and existing_req.extras == install_req.extras + and existing_req.req + and install_req.req + and existing_req.req.specifier != install_req.req.specifier + ) + if has_conflicting_requirement: + raise InstallationError( + "Double requirement given: {} (already in {}, name={!r})".format( + install_req, existing_req, install_req.name + ) + ) + + # When no existing requirement exists, add the requirement as a + # dependency and it will be scanned again after. + if not existing_req: + self.add_named_requirement(install_req) + # We'd want to rescan this requirement later + return [install_req], install_req + + # Assume there's no need to scan, and that we've already + # encountered this for scanning. + if install_req.constraint or not existing_req.constraint: + return [], existing_req + + does_not_satisfy_constraint = install_req.link and not ( + existing_req.link and install_req.link.path == existing_req.link.path + ) + if does_not_satisfy_constraint: + raise InstallationError( + "Could not satisfy constraints for '{}': " + "installation from path or url cannot be " + "constrained to a version".format(install_req.name) + ) + # If we're now installing a constraint, mark the existing + # object for real installation. + existing_req.constraint = False + # If we're now installing a user supplied requirement, + # mark the existing object as such. + if install_req.user_supplied: + existing_req.user_supplied = True + existing_req.extras = tuple( + sorted(set(existing_req.extras) | set(install_req.extras)) + ) + logger.debug( + "Setting %s extras to: %s", + existing_req, + existing_req.extras, + ) + # Return the existing requirement for addition to the parent and + # scanning again. + return [existing_req], existing_req + + def has_requirement(self, name: str) -> bool: + project_name = canonicalize_name(name) + + return ( + project_name in self.requirements + and not self.requirements[project_name].constraint + ) + + def get_requirement(self, name: str) -> InstallRequirement: + project_name = canonicalize_name(name) + + if project_name in self.requirements: + return self.requirements[project_name] + + raise KeyError(f"No project with the name {name!r}") + + @property + def all_requirements(self) -> List[InstallRequirement]: + return self.unnamed_requirements + list(self.requirements.values()) diff --git a/venv/Lib/site-packages/pip/_internal/req/req_tracker.py b/venv/Lib/site-packages/pip/_internal/req/req_tracker.py new file mode 100644 index 0000000..24d3c53 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/req/req_tracker.py @@ -0,0 +1,124 @@ +import contextlib +import hashlib +import logging +import os +from types import TracebackType +from typing import Dict, Iterator, Optional, Set, Type, Union + +from pip._internal.models.link import Link +from pip._internal.req.req_install import InstallRequirement +from pip._internal.utils.temp_dir import TempDirectory + +logger = logging.getLogger(__name__) + + +@contextlib.contextmanager +def update_env_context_manager(**changes: str) -> Iterator[None]: + target = os.environ + + # Save values from the target and change them. + non_existent_marker = object() + saved_values: Dict[str, Union[object, str]] = {} + for name, new_value in changes.items(): + try: + saved_values[name] = target[name] + except KeyError: + saved_values[name] = non_existent_marker + target[name] = new_value + + try: + yield + finally: + # Restore original values in the target. + for name, original_value in saved_values.items(): + if original_value is non_existent_marker: + del target[name] + else: + assert isinstance(original_value, str) # for mypy + target[name] = original_value + + +@contextlib.contextmanager +def get_requirement_tracker() -> Iterator["RequirementTracker"]: + root = os.environ.get("PIP_REQ_TRACKER") + with contextlib.ExitStack() as ctx: + if root is None: + root = ctx.enter_context(TempDirectory(kind="req-tracker")).path + ctx.enter_context(update_env_context_manager(PIP_REQ_TRACKER=root)) + logger.debug("Initialized build tracking at %s", root) + + with RequirementTracker(root) as tracker: + yield tracker + + +class RequirementTracker: + def __init__(self, root: str) -> None: + self._root = root + self._entries: Set[InstallRequirement] = set() + logger.debug("Created build tracker: %s", self._root) + + def __enter__(self) -> "RequirementTracker": + logger.debug("Entered build tracker: %s", self._root) + return self + + def __exit__( + self, + exc_type: Optional[Type[BaseException]], + exc_val: Optional[BaseException], + exc_tb: Optional[TracebackType], + ) -> None: + self.cleanup() + + def _entry_path(self, link: Link) -> str: + hashed = hashlib.sha224(link.url_without_fragment.encode()).hexdigest() + return os.path.join(self._root, hashed) + + def add(self, req: InstallRequirement) -> None: + """Add an InstallRequirement to build tracking.""" + + assert req.link + # Get the file to write information about this requirement. + entry_path = self._entry_path(req.link) + + # Try reading from the file. If it exists and can be read from, a build + # is already in progress, so a LookupError is raised. + try: + with open(entry_path) as fp: + contents = fp.read() + except FileNotFoundError: + pass + else: + message = "{} is already being built: {}".format(req.link, contents) + raise LookupError(message) + + # If we're here, req should really not be building already. + assert req not in self._entries + + # Start tracking this requirement. + with open(entry_path, "w", encoding="utf-8") as fp: + fp.write(str(req)) + self._entries.add(req) + + logger.debug("Added %s to build tracker %r", req, self._root) + + def remove(self, req: InstallRequirement) -> None: + """Remove an InstallRequirement from build tracking.""" + + assert req.link + # Delete the created file and the corresponding entries. + os.unlink(self._entry_path(req.link)) + self._entries.remove(req) + + logger.debug("Removed %s from build tracker %r", req, self._root) + + def cleanup(self) -> None: + for req in set(self._entries): + self.remove(req) + + logger.debug("Removed build tracker: %r", self._root) + + @contextlib.contextmanager + def track(self, req: InstallRequirement) -> Iterator[None]: + self.add(req) + yield + self.remove(req) diff --git a/venv/Lib/site-packages/pip/_internal/req/req_uninstall.py b/venv/Lib/site-packages/pip/_internal/req/req_uninstall.py new file mode 100644 index 0000000..472090a --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/req/req_uninstall.py @@ -0,0 +1,633 @@ +import functools +import os +import sys +import sysconfig +from importlib.util import cache_from_source +from typing import Any, Callable, Dict, Iterable, Iterator, List, Optional, Set, Tuple + +from pip._internal.exceptions import UninstallationError +from pip._internal.locations import get_bin_prefix, get_bin_user +from pip._internal.metadata import BaseDistribution +from pip._internal.utils.compat import WINDOWS +from pip._internal.utils.egg_link import egg_link_path_from_location +from pip._internal.utils.logging import getLogger, indent_log +from pip._internal.utils.misc import ask, is_local, normalize_path, renames, rmtree +from pip._internal.utils.temp_dir import AdjacentTempDirectory, TempDirectory + +logger = getLogger(__name__) + + +def _script_names(bin_dir: str, script_name: str, is_gui: bool) -> Iterator[str]: + """Create the fully qualified name of the files created by + {console,gui}_scripts for the given ``dist``. + Returns the list of file names + """ + exe_name = os.path.join(bin_dir, script_name) + yield exe_name + if not WINDOWS: + return + yield f"{exe_name}.exe" + yield f"{exe_name}.exe.manifest" + if is_gui: + yield f"{exe_name}-script.pyw" + else: + yield f"{exe_name}-script.py" + + +def _unique(fn: Callable[..., Iterator[Any]]) -> Callable[..., Iterator[Any]]: + @functools.wraps(fn) + def unique(*args: Any, **kw: Any) -> Iterator[Any]: + seen: Set[Any] = set() + for item in fn(*args, **kw): + if item not in seen: + seen.add(item) + yield item + + return unique + + +@_unique +def uninstallation_paths(dist: BaseDistribution) -> Iterator[str]: + """ + Yield all the uninstallation paths for dist based on RECORD-without-.py[co] + + Yield paths to all the files in RECORD. For each .py file in RECORD, add + the .pyc and .pyo in the same directory. + + UninstallPathSet.add() takes care of the __pycache__ .py[co]. + + If RECORD is not found, raises UninstallationError, + with possible information from the INSTALLER file. + + https://packaging.python.org/specifications/recording-installed-packages/ + """ + location = dist.location + assert location is not None, "not installed" + + entries = dist.iter_declared_entries() + if entries is None: + msg = "Cannot uninstall {dist}, RECORD file not found.".format(dist=dist) + installer = dist.installer + if not installer or installer == "pip": + dep = "{}=={}".format(dist.raw_name, dist.version) + msg += ( + " You might be able to recover from this via: " + "'pip install --force-reinstall --no-deps {}'.".format(dep) + ) + else: + msg += " Hint: The package was installed by {}.".format(installer) + raise UninstallationError(msg) + + for entry in entries: + path = os.path.join(location, entry) + yield path + if path.endswith(".py"): + dn, fn = os.path.split(path) + base = fn[:-3] + path = os.path.join(dn, base + ".pyc") + yield path + path = os.path.join(dn, base + ".pyo") + yield path + + +def compact(paths: Iterable[str]) -> Set[str]: + """Compact a path set to contain the minimal number of paths + necessary to contain all paths in the set. If /a/path/ and + /a/path/to/a/file.txt are both in the set, leave only the + shorter path.""" + + sep = os.path.sep + short_paths: Set[str] = set() + for path in sorted(paths, key=len): + should_skip = any( + path.startswith(shortpath.rstrip("*")) + and path[len(shortpath.rstrip("*").rstrip(sep))] == sep + for shortpath in short_paths + ) + if not should_skip: + short_paths.add(path) + return short_paths + + +def compress_for_rename(paths: Iterable[str]) -> Set[str]: + """Returns a set containing the paths that need to be renamed. + + This set may include directories when the original sequence of paths + included every file on disk. + """ + case_map = {os.path.normcase(p): p for p in paths} + remaining = set(case_map) + unchecked = sorted({os.path.split(p)[0] for p in case_map.values()}, key=len) + wildcards: Set[str] = set() + + def norm_join(*a: str) -> str: + return os.path.normcase(os.path.join(*a)) + + for root in unchecked: + if any(os.path.normcase(root).startswith(w) for w in wildcards): + # This directory has already been handled. + continue + + all_files: Set[str] = set() + all_subdirs: Set[str] = set() + for dirname, subdirs, files in os.walk(root): + all_subdirs.update(norm_join(root, dirname, d) for d in subdirs) + all_files.update(norm_join(root, dirname, f) for f in files) + # If all the files we found are in our remaining set of files to + # remove, then remove them from the latter set and add a wildcard + # for the directory. + if not (all_files - remaining): + remaining.difference_update(all_files) + wildcards.add(root + os.sep) + + return set(map(case_map.__getitem__, remaining)) | wildcards + + +def compress_for_output_listing(paths: Iterable[str]) -> Tuple[Set[str], Set[str]]: + """Returns a tuple of 2 sets of which paths to display to user + + The first set contains paths that would be deleted. Files of a package + are not added and the top-level directory of the package has a '*' added + at the end - to signify that all it's contents are removed. + + The second set contains files that would have been skipped in the above + folders. + """ + + will_remove = set(paths) + will_skip = set() + + # Determine folders and files + folders = set() + files = set() + for path in will_remove: + if path.endswith(".pyc"): + continue + if path.endswith("__init__.py") or ".dist-info" in path: + folders.add(os.path.dirname(path)) + files.add(path) + + # probably this one https://github.com/python/mypy/issues/390 + _normcased_files = set(map(os.path.normcase, files)) # type: ignore + + folders = compact(folders) + + # This walks the tree using os.walk to not miss extra folders + # that might get added. + for folder in folders: + for dirpath, _, dirfiles in os.walk(folder): + for fname in dirfiles: + if fname.endswith(".pyc"): + continue + + file_ = os.path.join(dirpath, fname) + if ( + os.path.isfile(file_) + and os.path.normcase(file_) not in _normcased_files + ): + # We are skipping this file. Add it to the set. + will_skip.add(file_) + + will_remove = files | {os.path.join(folder, "*") for folder in folders} + + return will_remove, will_skip + + +class StashedUninstallPathSet: + """A set of file rename operations to stash files while + tentatively uninstalling them.""" + + def __init__(self) -> None: + # Mapping from source file root to [Adjacent]TempDirectory + # for files under that directory. + self._save_dirs: Dict[str, TempDirectory] = {} + # (old path, new path) tuples for each move that may need + # to be undone. + self._moves: List[Tuple[str, str]] = [] + + def _get_directory_stash(self, path: str) -> str: + """Stashes a directory. + + Directories are stashed adjacent to their original location if + possible, or else moved/copied into the user's temp dir.""" + + try: + save_dir: TempDirectory = AdjacentTempDirectory(path) + except OSError: + save_dir = TempDirectory(kind="uninstall") + self._save_dirs[os.path.normcase(path)] = save_dir + + return save_dir.path + + def _get_file_stash(self, path: str) -> str: + """Stashes a file. + + If no root has been provided, one will be created for the directory + in the user's temp directory.""" + path = os.path.normcase(path) + head, old_head = os.path.dirname(path), None + save_dir = None + + while head != old_head: + try: + save_dir = self._save_dirs[head] + break + except KeyError: + pass + head, old_head = os.path.dirname(head), head + else: + # Did not find any suitable root + head = os.path.dirname(path) + save_dir = TempDirectory(kind="uninstall") + self._save_dirs[head] = save_dir + + relpath = os.path.relpath(path, head) + if relpath and relpath != os.path.curdir: + return os.path.join(save_dir.path, relpath) + return save_dir.path + + def stash(self, path: str) -> str: + """Stashes the directory or file and returns its new location. + Handle symlinks as files to avoid modifying the symlink targets. + """ + path_is_dir = os.path.isdir(path) and not os.path.islink(path) + if path_is_dir: + new_path = self._get_directory_stash(path) + else: + new_path = self._get_file_stash(path) + + self._moves.append((path, new_path)) + if path_is_dir and os.path.isdir(new_path): + # If we're moving a directory, we need to + # remove the destination first or else it will be + # moved to inside the existing directory. + # We just created new_path ourselves, so it will + # be removable. + os.rmdir(new_path) + renames(path, new_path) + return new_path + + def commit(self) -> None: + """Commits the uninstall by removing stashed files.""" + for _, save_dir in self._save_dirs.items(): + save_dir.cleanup() + self._moves = [] + self._save_dirs = {} + + def rollback(self) -> None: + """Undoes the uninstall by moving stashed files back.""" + for p in self._moves: + logger.info("Moving to %s\n from %s", *p) + + for new_path, path in self._moves: + try: + logger.debug("Replacing %s from %s", new_path, path) + if os.path.isfile(new_path) or os.path.islink(new_path): + os.unlink(new_path) + elif os.path.isdir(new_path): + rmtree(new_path) + renames(path, new_path) + except OSError as ex: + logger.error("Failed to restore %s", new_path) + logger.debug("Exception: %s", ex) + + self.commit() + + @property + def can_rollback(self) -> bool: + return bool(self._moves) + + +class UninstallPathSet: + """A set of file paths to be removed in the uninstallation of a + requirement.""" + + def __init__(self, dist: BaseDistribution) -> None: + self._paths: Set[str] = set() + self._refuse: Set[str] = set() + self._pth: Dict[str, UninstallPthEntries] = {} + self._dist = dist + self._moved_paths = StashedUninstallPathSet() + + def _permitted(self, path: str) -> bool: + """ + Return True if the given path is one we are permitted to + remove/modify, False otherwise. + + """ + return is_local(path) + + def add(self, path: str) -> None: + head, tail = os.path.split(path) + + # we normalize the head to resolve parent directory symlinks, but not + # the tail, since we only want to uninstall symlinks, not their targets + path = os.path.join(normalize_path(head), os.path.normcase(tail)) + + if not os.path.exists(path): + return + if self._permitted(path): + self._paths.add(path) + else: + self._refuse.add(path) + + # __pycache__ files can show up after 'installed-files.txt' is created, + # due to imports + if os.path.splitext(path)[1] == ".py": + self.add(cache_from_source(path)) + + def add_pth(self, pth_file: str, entry: str) -> None: + pth_file = normalize_path(pth_file) + if self._permitted(pth_file): + if pth_file not in self._pth: + self._pth[pth_file] = UninstallPthEntries(pth_file) + self._pth[pth_file].add(entry) + else: + self._refuse.add(pth_file) + + def remove(self, auto_confirm: bool = False, verbose: bool = False) -> None: + """Remove paths in ``self._paths`` with confirmation (unless + ``auto_confirm`` is True).""" + + if not self._paths: + logger.info( + "Can't uninstall '%s'. No files were found to uninstall.", + self._dist.raw_name, + ) + return + + dist_name_version = f"{self._dist.raw_name}-{self._dist.version}" + logger.info("Uninstalling %s:", dist_name_version) + + with indent_log(): + if auto_confirm or self._allowed_to_proceed(verbose): + moved = self._moved_paths + + for_rename = compress_for_rename(self._paths) + + for path in sorted(compact(for_rename)): + moved.stash(path) + logger.verbose("Removing file or directory %s", path) + + for pth in self._pth.values(): + pth.remove() + + logger.info("Successfully uninstalled %s", dist_name_version) + + def _allowed_to_proceed(self, verbose: bool) -> bool: + """Display which files would be deleted and prompt for confirmation""" + + def _display(msg: str, paths: Iterable[str]) -> None: + if not paths: + return + + logger.info(msg) + with indent_log(): + for path in sorted(compact(paths)): + logger.info(path) + + if not verbose: + will_remove, will_skip = compress_for_output_listing(self._paths) + else: + # In verbose mode, display all the files that are going to be + # deleted. + will_remove = set(self._paths) + will_skip = set() + + _display("Would remove:", will_remove) + _display("Would not remove (might be manually added):", will_skip) + _display("Would not remove (outside of prefix):", self._refuse) + if verbose: + _display("Will actually move:", compress_for_rename(self._paths)) + + return ask("Proceed (Y/n)? ", ("y", "n", "")) != "n" + + def rollback(self) -> None: + """Rollback the changes previously made by remove().""" + if not self._moved_paths.can_rollback: + logger.error( + "Can't roll back %s; was not uninstalled", + self._dist.raw_name, + ) + return + logger.info("Rolling back uninstall of %s", self._dist.raw_name) + self._moved_paths.rollback() + for pth in self._pth.values(): + pth.rollback() + + def commit(self) -> None: + """Remove temporary save dir: rollback will no longer be possible.""" + self._moved_paths.commit() + + @classmethod + def from_dist(cls, dist: BaseDistribution) -> "UninstallPathSet": + dist_location = dist.location + info_location = dist.info_location + if dist_location is None: + logger.info( + "Not uninstalling %s since it is not installed", + dist.canonical_name, + ) + return cls(dist) + + normalized_dist_location = normalize_path(dist_location) + if not dist.local: + logger.info( + "Not uninstalling %s at %s, outside environment %s", + dist.canonical_name, + normalized_dist_location, + sys.prefix, + ) + return cls(dist) + + if normalized_dist_location in { + p + for p in {sysconfig.get_path("stdlib"), sysconfig.get_path("platstdlib")} + if p + }: + logger.info( + "Not uninstalling %s at %s, as it is in the standard library.", + dist.canonical_name, + normalized_dist_location, + ) + return cls(dist) + + paths_to_remove = cls(dist) + develop_egg_link = egg_link_path_from_location(dist.raw_name) + + # Distribution is installed with metadata in a "flat" .egg-info + # directory. This means it is not a modern .dist-info installation, an + # egg, or legacy editable. + setuptools_flat_installation = ( + dist.installed_with_setuptools_egg_info + and info_location is not None + and os.path.exists(info_location) + # If dist is editable and the location points to a ``.egg-info``, + # we are in fact in the legacy editable case. + and not info_location.endswith(f"{dist.setuptools_filename}.egg-info") + ) + + # Uninstall cases order do matter as in the case of 2 installs of the + # same package, pip needs to uninstall the currently detected version + if setuptools_flat_installation: + if info_location is not None: + paths_to_remove.add(info_location) + installed_files = dist.iter_declared_entries() + if installed_files is not None: + for installed_file in installed_files: + paths_to_remove.add(os.path.join(dist_location, installed_file)) + # FIXME: need a test for this elif block + # occurs with --single-version-externally-managed/--record outside + # of pip + elif dist.is_file("top_level.txt"): + try: + namespace_packages = dist.read_text("namespace_packages.txt") + except FileNotFoundError: + namespaces = [] + else: + namespaces = namespace_packages.splitlines(keepends=False) + for top_level_pkg in [ + p + for p in dist.read_text("top_level.txt").splitlines() + if p and p not in namespaces + ]: + path = os.path.join(dist_location, top_level_pkg) + paths_to_remove.add(path) + paths_to_remove.add(f"{path}.py") + paths_to_remove.add(f"{path}.pyc") + paths_to_remove.add(f"{path}.pyo") + + elif dist.installed_by_distutils: + raise UninstallationError( + "Cannot uninstall {!r}. It is a distutils installed project " + "and thus we cannot accurately determine which files belong " + "to it which would lead to only a partial uninstall.".format( + dist.raw_name, + ) + ) + + elif dist.installed_as_egg: + # package installed by easy_install + # We cannot match on dist.egg_name because it can slightly vary + # i.e. setuptools-0.6c11-py2.6.egg vs setuptools-0.6rc11-py2.6.egg + paths_to_remove.add(dist_location) + easy_install_egg = os.path.split(dist_location)[1] + easy_install_pth = os.path.join( + os.path.dirname(dist_location), + "easy-install.pth", + ) + paths_to_remove.add_pth(easy_install_pth, "./" + easy_install_egg) + + elif dist.installed_with_dist_info: + for path in uninstallation_paths(dist): + paths_to_remove.add(path) + + elif develop_egg_link: + # PEP 660 modern editable is handled in the ``.dist-info`` case + # above, so this only covers the setuptools-style editable. + with open(develop_egg_link) as fh: + link_pointer = os.path.normcase(fh.readline().strip()) + assert link_pointer == dist_location, ( + f"Egg-link {link_pointer} does not match installed location of " + f"{dist.raw_name} (at {dist_location})" + ) + paths_to_remove.add(develop_egg_link) + easy_install_pth = os.path.join( + os.path.dirname(develop_egg_link), "easy-install.pth" + ) + paths_to_remove.add_pth(easy_install_pth, dist_location) + + else: + logger.debug( + "Not sure how to uninstall: %s - Check: %s", + dist, + dist_location, + ) + + if dist.in_usersite: + bin_dir = get_bin_user() + else: + bin_dir = get_bin_prefix() + + # find distutils scripts= scripts + try: + for script in dist.iterdir("scripts"): + paths_to_remove.add(os.path.join(bin_dir, script.name)) + if WINDOWS: + paths_to_remove.add(os.path.join(bin_dir, f"{script.name}.bat")) + except (FileNotFoundError, NotADirectoryError): + pass + + # find console_scripts and gui_scripts + def iter_scripts_to_remove( + dist: BaseDistribution, + bin_dir: str, + ) -> Iterator[str]: + for entry_point in dist.iter_entry_points(): + if entry_point.group == "console_scripts": + yield from _script_names(bin_dir, entry_point.name, False) + elif entry_point.group == "gui_scripts": + yield from _script_names(bin_dir, entry_point.name, True) + + for s in iter_scripts_to_remove(dist, bin_dir): + paths_to_remove.add(s) + + return paths_to_remove + + +class UninstallPthEntries: + def __init__(self, pth_file: str) -> None: + self.file = pth_file + self.entries: Set[str] = set() + self._saved_lines: Optional[List[bytes]] = None + + def add(self, entry: str) -> None: + entry = os.path.normcase(entry) + # On Windows, os.path.normcase converts the entry to use + # backslashes. This is correct for entries that describe absolute + # paths outside of site-packages, but all the others use forward + # slashes. + # os.path.splitdrive is used instead of os.path.isabs because isabs + # treats non-absolute paths with drive letter markings like c:foo\bar + # as absolute paths. It also does not recognize UNC paths if they don't + # have more than "\\sever\share". Valid examples: "\\server\share\" or + # "\\server\share\folder". + if WINDOWS and not os.path.splitdrive(entry)[0]: + entry = entry.replace("\\", "/") + self.entries.add(entry) + + def remove(self) -> None: + logger.verbose("Removing pth entries from %s:", self.file) + + # If the file doesn't exist, log a warning and return + if not os.path.isfile(self.file): + logger.warning("Cannot remove entries from nonexistent file %s", self.file) + return + with open(self.file, "rb") as fh: + # windows uses '\r\n' with py3k, but uses '\n' with py2.x + lines = fh.readlines() + self._saved_lines = lines + if any(b"\r\n" in line for line in lines): + endline = "\r\n" + else: + endline = "\n" + # handle missing trailing newline + if lines and not lines[-1].endswith(endline.encode("utf-8")): + lines[-1] = lines[-1] + endline.encode("utf-8") + for entry in self.entries: + try: + logger.verbose("Removing entry: %s", entry) + lines.remove((entry + endline).encode("utf-8")) + except ValueError: + pass + with open(self.file, "wb") as fh: + fh.writelines(lines) + + def rollback(self) -> bool: + if self._saved_lines is None: + logger.error("Cannot roll back changes to %s, none were made", self.file) + return False + logger.debug("Rolling %s back to previous state", self.file) + with open(self.file, "wb") as fh: + fh.writelines(self._saved_lines) + return True diff --git a/venv/Lib/site-packages/pip/_internal/resolution/__init__.py b/venv/Lib/site-packages/pip/_internal/resolution/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/venv/Lib/site-packages/pip/_internal/resolution/__pycache__/__init__.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/resolution/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..64c80ef260e3767bbf455df7167928608fc2f448 GIT binary patch literal 189 zcmYe~<>g`kf?j#GBoO@=L?8o3AjbiSi&=m~3PUi1CZpdY!wq)oLW>I zlbDy6SRCV6P~ehSk{IKYpPZNz6Ox)+5L1v@pj(<(keHmEnxb2tk(!#LYi5y^S)5#4 z1(J)2&&(@HEy@EbFG?-W&nYd*%+HI72a0Bv#K-FuRNmsS$<0qG%}KQb+5H)a835y) BGT;CJ literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/resolution/__pycache__/base.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/resolution/__pycache__/base.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..77b11f0a29b3b907934ff210c5ef3aa417733d4a GIT binary patch literal 1046 zcmZ`&%}x|S5bo~z*;!anfsm|;@nB-I2RIUAj8V}L60#c5%VgqYcDjI(o}caR#lTUx z`UboJuhdshzJdp|YF2QK*h$w^SJiZV-&Zr)!onQG_4VQ7(UxHB8y#kskB1ky%`O_r zBv-8DF)u|dN-y>}#f0+9AP!pJQ(@VOJDdTB2s{Y->_9-UFZwL*ZZYZ0;GD_eOvH0C z++%~zcf6MkJQr21bF!T(VdoB)`uffKc)aPYUUs`*8=tX&8ZK`2x+-iOZ`B7>nO;c+NGW~oApo|MO*om%kZw3wd9QP(}Ly}u|#=an=J$A{5 zm)tE6Yr9=Gs$~cAjn*}_^9`td9pMYQi{_H)JNWqVar0^N!GJbNR#llvUN+6^%x1|> zoo6a}4`q`yMYA@knk+v8xz-|E+j#P+Fu6IUT#^=*1&snHn%GT9?PP>x*P9d9X=BIG z!)6A*3&yI(sVq@)HI`MNIIa# z{-~~%4(UwI^fH-0;98Fm>JA#BVu(s4A}+3aq2S?Fn;8z~U1(35qB_td#i)AezII<**XgYBYcQwg5acv|c$qQ`qe J@Wr2g@C#?42yFlW literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/resolution/base.py b/venv/Lib/site-packages/pip/_internal/resolution/base.py new file mode 100644 index 0000000..42dade1 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/resolution/base.py @@ -0,0 +1,20 @@ +from typing import Callable, List, Optional + +from pip._internal.req.req_install import InstallRequirement +from pip._internal.req.req_set import RequirementSet + +InstallRequirementProvider = Callable[ + [str, Optional[InstallRequirement]], InstallRequirement +] + + +class BaseResolver: + def resolve( + self, root_reqs: List[InstallRequirement], check_supported_wheels: bool + ) -> RequirementSet: + raise NotImplementedError() + + def get_installation_order( + self, req_set: RequirementSet + ) -> List[InstallRequirement]: + raise NotImplementedError() diff --git a/venv/Lib/site-packages/pip/_internal/resolution/legacy/__init__.py b/venv/Lib/site-packages/pip/_internal/resolution/legacy/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/venv/Lib/site-packages/pip/_internal/resolution/legacy/__pycache__/__init__.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/resolution/legacy/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ed93c03ef1ac205a71cc50cc1ecc826aa8046bba GIT binary patch literal 196 zcmYe~<>g`kf?j#GBoO@=L?8o3AjbiSi&=m~3PUi1CZpdI zlbDy6SRCV6P~ehSk{IKYpPZNz6Ox)+5L1v@pj(<(keHmEnxb2tk(!#LYi5y^S)5#4 z1(J)2&&(@HEy@EbFG?-W&nYd*%+HI-Nli~ou8fHXN@kYC$LkeT-r}&y%}*)KNwotx J;WH33003)9HMjr( literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/resolution/legacy/__pycache__/resolver.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/resolution/legacy/__pycache__/resolver.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5979439a6ded7c412e13ec88f18ba94afb77b516 GIT binary patch literal 12184 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 XH@U88C9R%UenY#aLi_8p%GdrE8IqRc literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/resolution/legacy/resolver.py b/venv/Lib/site-packages/pip/_internal/resolution/legacy/resolver.py new file mode 100644 index 0000000..8c149d4 --- /dev/null +++ b/venv/Lib/site-packages/pip/_internal/resolution/legacy/resolver.py @@ -0,0 +1,467 @@ +"""Dependency Resolution + +The dependency resolution in pip is performed as follows: + +for top-level requirements: + a. only one spec allowed per project, regardless of conflicts or not. + otherwise a "double requirement" exception is raised + b. they override sub-dependency requirements. +for sub-dependencies + a. "first found, wins" (where the order is breadth first) +""" + +# The following comment should be removed at some point in the future. +# mypy: strict-optional=False + +import logging +import sys +from collections import defaultdict +from itertools import chain +from typing import DefaultDict, Iterable, List, Optional, Set, Tuple + +from pip._vendor.packaging import specifiers +from pip._vendor.packaging.requirements import Requirement + +from pip._internal.cache import WheelCache +from pip._internal.exceptions import ( + BestVersionAlreadyInstalled, + DistributionNotFound, + HashError, + HashErrors, + NoneMetadataError, + UnsupportedPythonVersion, +) +from pip._internal.index.package_finder import PackageFinder +from pip._internal.metadata import BaseDistribution +from pip._internal.models.link import Link +from pip._internal.operations.prepare import RequirementPreparer +from pip._internal.req.req_install import ( + InstallRequirement, + check_invalid_constraint_type, +) +from pip._internal.req.req_set import RequirementSet +from pip._internal.resolution.base import BaseResolver, InstallRequirementProvider +from pip._internal.utils.compatibility_tags import get_supported +from pip._internal.utils.logging import indent_log +from pip._internal.utils.misc import normalize_version_info +from pip._internal.utils.packaging import check_requires_python + +logger = logging.getLogger(__name__) + +DiscoveredDependencies = DefaultDict[str, List[InstallRequirement]] + + +def _check_dist_requires_python( + dist: BaseDistribution, + version_info: Tuple[int, int, int], + ignore_requires_python: bool = False, +) -> None: + """ + Check whether the given Python version is compatible with a distribution's + "Requires-Python" value. + + :param version_info: A 3-tuple of ints representing the Python + major-minor-micro version to check. + :param ignore_requires_python: Whether to ignore the "Requires-Python" + value if the given Python version isn't compatible. + + :raises UnsupportedPythonVersion: When the given Python version isn't + compatible. + """ + # This idiosyncratically converts the SpecifierSet to str and let + # check_requires_python then parse it again into SpecifierSet. But this + # is the legacy resolver so I'm just not going to bother refactoring. + try: + requires_python = str(dist.requires_python) + except FileNotFoundError as e: + raise NoneMetadataError(dist, str(e)) + try: + is_compatible = check_requires_python( + requires_python, + version_info=version_info, + ) + except specifiers.InvalidSpecifier as exc: + logger.warning( + "Package %r has an invalid Requires-Python: %s", dist.raw_name, exc + ) + return + + if is_compatible: + return + + version = ".".join(map(str, version_info)) + if ignore_requires_python: + logger.debug( + "Ignoring failed Requires-Python check for package %r: %s not in %r", + dist.raw_name, + version, + requires_python, + ) + return + + raise UnsupportedPythonVersion( + "Package {!r} requires a different Python: {} not in {!r}".format( + dist.raw_name, version, requires_python + ) + ) + + +class Resolver(BaseResolver): + """Resolves which packages need to be installed/uninstalled to perform \ + the requested operation without breaking the requirements of any package. + """ + + _allowed_strategies = {"eager", "only-if-needed", "to-satisfy-only"} + + def __init__( + self, + preparer: RequirementPreparer, + finder: PackageFinder, + wheel_cache: Optional[WheelCache], + make_install_req: InstallRequirementProvider, + use_user_site: bool, + ignore_dependencies: bool, + ignore_installed: bool, + ignore_requires_python: bool, + force_reinstall: bool, + upgrade_strategy: str, + py_version_info: Optional[Tuple[int, ...]] = None, + ) -> None: + super().__init__() + assert upgrade_strategy in self._allowed_strategies + + if py_version_info is None: + py_version_info = sys.version_info[:3] + else: + py_version_info = normalize_version_info(py_version_info) + + self._py_version_info = py_version_info + + self.preparer = preparer + self.finder = finder + self.wheel_cache = wheel_cache + + self.upgrade_strategy = upgrade_strategy + self.force_reinstall = force_reinstall + self.ignore_dependencies = ignore_dependencies + self.ignore_installed = ignore_installed + self.ignore_requires_python = ignore_requires_python + self.use_user_site = use_user_site + self._make_install_req = make_install_req + + self._discovered_dependencies: DiscoveredDependencies = defaultdict(list) + + def resolve( + self, root_reqs: List[InstallRequirement], check_supported_wheels: bool + ) -> RequirementSet: + """Resolve what operations need to be done + + As a side-effect of this method, the packages (and their dependencies) + are downloaded, unpacked and prepared for installation. This + preparation is done by ``pip.operations.prepare``. + + Once PyPI has static dependency metadata available, it would be + possible to move the preparation to become a step separated from + dependency resolution. + """ + requirement_set = RequirementSet(check_supported_wheels=check_supported_wheels) + for req in root_reqs: + if req.constraint: + check_invalid_constraint_type(req) + requirement_set.add_requirement(req) + + # Actually prepare the files, and collect any exceptions. Most hash + # exceptions cannot be checked ahead of time, because + # _populate_link() needs to be called before we can make decisions + # based on link type. + discovered_reqs: List[InstallRequirement] = [] + hash_errors = HashErrors() + for req in chain(requirement_set.all_requirements, discovered_reqs): + try: + discovered_reqs.extend(self._resolve_one(requirement_set, req)) + except HashError as exc: + exc.req = req + hash_errors.append(exc) + + if hash_errors: + raise hash_errors + + return requirement_set + + def _is_upgrade_allowed(self, req: InstallRequirement) -> bool: + if self.upgrade_strategy == "to-satisfy-only": + return False + elif self.upgrade_strategy == "eager": + return True + else: + assert self.upgrade_strategy == "only-if-needed" + return req.user_supplied or req.constraint + + def _set_req_to_reinstall(self, req: InstallRequirement) -> None: + """ + Set a requirement to be installed. + """ + # Don't uninstall the conflict if doing a user install and the + # conflict is not a user install. + if not self.use_user_site or req.satisfied_by.in_usersite: + req.should_reinstall = True + req.satisfied_by = None + + def _check_skip_installed( + self, req_to_install: InstallRequirement + ) -> Optional[str]: + """Check if req_to_install should be skipped. + + This will check if the req is installed, and whether we should upgrade + or reinstall it, taking into account all the relevant user options. + + After calling this req_to_install will only have satisfied_by set to + None if the req_to_install is to be upgraded/reinstalled etc. Any + other value will be a dist recording the current thing installed that + satisfies the requirement. + + Note that for vcs urls and the like we can't assess skipping in this + routine - we simply identify that we need to pull the thing down, + then later on it is pulled down and introspected to assess upgrade/ + reinstalls etc. + + :return: A text reason for why it was skipped, or None. + """ + if self.ignore_installed: + return None + + req_to_install.check_if_exists(self.use_user_site) + if not req_to_install.satisfied_by: + return None + + if self.force_reinstall: + self._set_req_to_reinstall(req_to_install) + return None + + if not self._is_upgrade_allowed(req_to_install): + if self.upgrade_strategy == "only-if-needed": + return "already satisfied, skipping upgrade" + return "already satisfied" + + # Check for the possibility of an upgrade. For link-based + # requirements we have to pull the tree down and inspect to assess + # the version #, so it's handled way down. + if not req_to_install.link: + try: + self.finder.find_requirement(req_to_install, upgrade=True) + except BestVersionAlreadyInstalled: + # Then the best version is installed. + return "already up-to-date" + except DistributionNotFound: + # No distribution found, so we squash the error. It will + # be raised later when we re-try later to do the install. + # Why don't we just raise here? + pass + + self._set_req_to_reinstall(req_to_install) + return None + + def _find_requirement_link(self, req: InstallRequirement) -> Optional[Link]: + upgrade = self._is_upgrade_allowed(req) + best_candidate = self.finder.find_requirement(req, upgrade) + if not best_candidate: + return None + + # Log a warning per PEP 592 if necessary before returning. + link = best_candidate.link + if link.is_yanked: + reason = link.yanked_reason or "" + msg = ( + # Mark this as a unicode string to prevent + # "UnicodeEncodeError: 'ascii' codec can't encode character" + # in Python 2 when the reason contains non-ascii characters. + "The candidate selected for download or install is a " + "yanked version: {candidate}\n" + "Reason for being yanked: {reason}" + ).format(candidate=best_candidate, reason=reason) + logger.warning(msg) + + return link + + def _populate_link(self, req: InstallRequirement) -> None: + """Ensure that if a link can be found for this, that it is found. + + Note that req.link may still be None - if the requirement is already + installed and not needed to be upgraded based on the return value of + _is_upgrade_allowed(). + + If preparer.require_hashes is True, don't use the wheel cache, because + cached wheels, always built locally, have different hashes than the + files downloaded from the index server and thus throw false hash + mismatches. Furthermore, cached wheels at present have undeterministic + contents due to file modification times. + """ + if req.link is None: + req.link = self._find_requirement_link(req) + + if self.wheel_cache is None or self.preparer.require_hashes: + return + cache_entry = self.wheel_cache.get_cache_entry( + link=req.link, + package_name=req.name, + supported_tags=get_supported(), + ) + if cache_entry is not None: + logger.debug("Using cached wheel link: %s", cache_entry.link) + if req.link is req.original_link and cache_entry.persistent: + req.original_link_is_in_wheel_cache = True + req.link = cache_entry.link + + def _get_dist_for(self, req: InstallRequirement) -> BaseDistribution: + """Takes a InstallRequirement and returns a single AbstractDist \ + representing a prepared variant of the same. + """ + if req.editable: + return self.preparer.prepare_editable_requirement(req) + + # satisfied_by is only evaluated by calling _check_skip_installed, + # so it must be None here. + assert req.satisfied_by is None + skip_reason = self._check_skip_installed(req) + + if req.satisfied_by: + return self.preparer.prepare_installed_requirement(req, skip_reason) + + # We eagerly populate the link, since that's our "legacy" behavior. + self._populate_link(req) + dist = self.preparer.prepare_linked_requirement(req) + + # NOTE + # The following portion is for determining if a certain package is + # going to be re-installed/upgraded or not and reporting to the user. + # This should probably get cleaned up in a future refactor. + + # req.req is only avail after unpack for URL + # pkgs repeat check_if_exists to uninstall-on-upgrade + # (#14) + if not self.ignore_installed: + req.check_if_exists(self.use_user_site) + + if req.satisfied_by: + should_modify = ( + self.upgrade_strategy != "to-satisfy-only" + or self.force_reinstall + or self.ignore_installed + or req.link.scheme == "file" + ) + if should_modify: + self._set_req_to_reinstall(req) + else: + logger.info( + "Requirement already satisfied (use --upgrade to upgrade): %s", + req, + ) + return dist + + def _resolve_one( + self, + requirement_set: RequirementSet, + req_to_install: InstallRequirement, + ) -> List[InstallRequirement]: + """Prepare a single requirements file. + + :return: A list of additional InstallRequirements to also install. + """ + # Tell user what we are doing for this requirement: + # obtain (editable), skipping, processing (local url), collecting + # (remote url or package name) + if req_to_install.constraint or req_to_install.prepared: + return [] + + req_to_install.prepared = True + + # Parse and return dependencies + dist = self._get_dist_for(req_to_install) + # This will raise UnsupportedPythonVersion if the given Python + # version isn't compatible with the distribution's Requires-Python. + _check_dist_requires_python( + dist, + version_info=self._py_version_info, + ignore_requires_python=self.ignore_requires_python, + ) + + more_reqs: List[InstallRequirement] = [] + + def add_req(subreq: Requirement, extras_requested: Iterable[str]) -> None: + # This idiosyncratically converts the Requirement to str and let + # make_install_req then parse it again into Requirement. But this is + # the legacy resolver so I'm just not going to bother refactoring. + sub_install_req = self._make_install_req(str(subreq), req_to_install) + parent_req_name = req_to_install.name + to_scan_again, add_to_parent = requirement_set.add_requirement( + sub_install_req, + parent_req_name=parent_req_name, + extras_requested=extras_requested, + ) + if parent_req_name and add_to_parent: + self._discovered_dependencies[parent_req_name].append(add_to_parent) + more_reqs.extend(to_scan_again) + + with indent_log(): + # We add req_to_install before its dependencies, so that we + # can refer to it when adding dependencies. + if not requirement_set.has_requirement(req_to_install.name): + # 'unnamed' requirements will get added here + # 'unnamed' requirements can only come from being directly + # provided by the user. + assert req_to_install.user_supplied + requirement_set.add_requirement(req_to_install, parent_req_name=None) + + if not self.ignore_dependencies: + if req_to_install.extras: + logger.debug( + "Installing extra requirements: %r", + ",".join(req_to_install.extras), + ) + missing_requested = sorted( + set(req_to_install.extras) - set(dist.iter_provided_extras()) + ) + for missing in missing_requested: + logger.warning( + "%s %s does not provide the extra '%s'", + dist.raw_name, + dist.version, + missing, + ) + + available_requested = sorted( + set(dist.iter_provided_extras()) & set(req_to_install.extras) + ) + for subreq in dist.iter_dependencies(available_requested): + add_req(subreq, extras_requested=available_requested) + + return more_reqs + + def get_installation_order( + self, req_set: RequirementSet + ) -> List[InstallRequirement]: + """Create the installation order. + + The installation order is topological - requirements are installed + before the requiring thing. We break cycles at an arbitrary point, + and make no other guarantees. + """ + # The current implementation, which we may change at any point + # installs the user specified things in the order given, except when + # dependencies must come earlier to achieve topological order. + order = [] + ordered_reqs: Set[InstallRequirement] = set() + + def schedule(req: InstallRequirement) -> None: + if req.satisfied_by or req in ordered_reqs: + return + if req.constraint: + return + ordered_reqs.add(req) + for dep in self._discovered_dependencies[req.name]: + schedule(dep) + order.append(req) + + for install_req in req_set.requirements.values(): + schedule(install_req) + return order diff --git a/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__init__.py b/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/__init__.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c31d41ae206eed55bccbda73e6490e827f98cdb9 GIT binary patch literal 200 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 S&lSxbjF(%*v`D5@(fL1O(C#n* literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/found_candidates.cpython-39.pyc b/venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/found_candidates.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9d288d7d642ec5a13dd5c6146fbf4eda76e2ef73 GIT binary patch literal 4831 zcmcIoOK%*<5$<{Ha(B4Pmt>3bBc3RV?X{^*kQk1U2#RG&u^Ah50MQ1rpfMay_mU&c zi`_G%NURPq1=trO$SD^cGUE_yCq&@;#9(R2Aj z#uxbFW5yT7;;}V&ft&YOZ^{3&!PsYc7=?K#l$)n+QtOqlFUrF3N~>W0eo-M99IJbcRyQk6q-nhA+fY0`JsayLx&(`a8P zXDISu7sFRv@i3QuKzdi)EX_rdhkk^C+eH|0njlVj5s?`(ja`)%G7u}32||X$Lx?y$ zRJjbd3!2A`Mef6JznTz>+!ay`Qz@{>B7kx%NV+f!Ke3+#g52;xh|CdWc}`}zG=_Y0 z=)xFM;U4&hE>91V71-b&2sce&WS$nm?$iM^nV+NA@wZhP6}f;+A_T7tPSV`HMmnO@ z=ate_M*Nz4uq%>@PLhXq;ldh43rdHMO0g<3tnYjWn6mYrQMT@hy+XkL-b~ru`0a1* zdaEDZUHy1%{ln6_og9{}RhaH?N1|-4<+KT@EL)#uSt$QLb8yiIy3Fzv0ANWdq zUQPHNFv8H-UL9kgXO@jH8K$aiN|6^b2}or8H1J{L4e+WDP~_~GJu*h@4*TLKo8}|) zku@?$#y*p;>^UO~efG%aM#1C?>h|Z%U?bzHF*3h347TTR14uQG{xmjPZ`an=uLy+` zi`3Q@5b5IC*ahmsdVz$%LcxF9qqJ?AA3X4P1a*-6{RklDhXA6=;U2;J?o_ANr(qT* zTs#DXV*&wmL!S04lu!cDL~bfM&`0}0Hmt)zmV!eqpYvWrcHx9_uHHZ8=>t^G)b-LH z7D-UHgRys?G5G=p{G(X?`Q~Q|d$8#ziLW+qXW1R#c=MAq@T1KQ5oeoOnB6E6T9e>6 zutpKxc=x^gp$gOy^=*1#0&B6qn^I^1VzaByeG!G*o7xg@GPCMuhvlqC-t*|ZjIduG7nub7&4s8d5(LP$zKsH7X;fx0u~$yT&5`p@xM8 z7yuZ6#r3_VkquZhMhy*%cTjKWF(zPPX;>^(u<$q5`xEaC&ysi&qjgK3X zMe6;XI84W#^-nh_WE9zs^ttE*fq>T-Pt#yPkOO9_*rV0>5rT+v4?_`gV00Ktl~<8r zGC>{Yo{K-N=L`lZh6W zg+d6s4^%v8$oFbwnNLk>Bb=PV(MOOSeV=FSd6ai~b`Puo00T{P$qc$~2N=q=Xo0SZD1zvJzL=m1(iF zt51MNuyRv^_Z0AIg^q!cl*_d`bYFNd#6u)};s%s_x2xQYjEaaX^Xha^3QloIBm%8g zg;W>r`w`4KH6IeWKcx6fS^BIwZaAa^h!hU*kw792gd9g~OU?slQ}D~HR6T?6tLG42 ztx)h!Agx|O!Mb&%G#$js&Lm!TEXR;9qo2~^sfY6A`*_utC1 z;$1%XjUn2)eV#8owvUa$CB8_ku$(`WTz$&#w=4dmYL-DEFO%th$U&sWsSB`3b=({W z(@9dMod=ntI9I4T0YkO|F@_*G>P)*e1j4=82OSjZ&E6KVE5glKq27JWHwGd)D;$#0 z#J0GI@({Rn^Dq{`A*f(Q(EK0}stWD;Bx!XS*`pbP6fr30`1FCj5>kS^09q>IMg*Z^ z7%?p#qEp_ev@)$n6=6

...' % action) + + thedir = convert_path(words[1]) + patterns = [convert_path(word) for word in words[2:]] + + elif action in ('graft', 'prune'): + if len(words) != 2: + raise DistlibException( + '%r expects a single ' % action) + + dir_pattern = convert_path(words[1]) + + else: + raise DistlibException('unknown action %r' % action) + + return action, patterns, thedir, dir_pattern + + def _include_pattern(self, pattern, anchor=True, prefix=None, + is_regex=False): + """Select strings (presumably filenames) from 'self.files' that + match 'pattern', a Unix-style wildcard (glob) pattern. + + Patterns are not quite the same as implemented by the 'fnmatch' + module: '*' and '?' match non-special characters, where "special" + is platform-dependent: slash on Unix; colon, slash, and backslash on + DOS/Windows; and colon on Mac OS. + + If 'anchor' is true (the default), then the pattern match is more + stringent: "*.py" will match "foo.py" but not "foo/bar.py". If + 'anchor' is false, both of these will match. + + If 'prefix' is supplied, then only filenames starting with 'prefix' + (itself a pattern) and ending with 'pattern', with anything in between + them, will match. 'anchor' is ignored in this case. + + If 'is_regex' is true, 'anchor' and 'prefix' are ignored, and + 'pattern' is assumed to be either a string containing a regex or a + regex object -- no translation is done, the regex is just compiled + and used as-is. + + Selected strings will be added to self.files. + + Return True if files are found. + """ + # XXX docstring lying about what the special chars are? + found = False + pattern_re = self._translate_pattern(pattern, anchor, prefix, is_regex) + + # delayed loading of allfiles list + if self.allfiles is None: + self.findall() + + for name in self.allfiles: + if pattern_re.search(name): + self.files.add(name) + found = True + return found + + def _exclude_pattern(self, pattern, anchor=True, prefix=None, + is_regex=False): + """Remove strings (presumably filenames) from 'files' that match + 'pattern'. + + Other parameters are the same as for 'include_pattern()', above. + The list 'self.files' is modified in place. Return True if files are + found. + + This API is public to allow e.g. exclusion of SCM subdirs, e.g. when + packaging source distributions + """ + found = False + pattern_re = self._translate_pattern(pattern, anchor, prefix, is_regex) + for f in list(self.files): + if pattern_re.search(f): + self.files.remove(f) + found = True + return found + + def _translate_pattern(self, pattern, anchor=True, prefix=None, + is_regex=False): + """Translate a shell-like wildcard pattern to a compiled regular + expression. + + Return the compiled regex. If 'is_regex' true, + then 'pattern' is directly compiled to a regex (if it's a string) + or just returned as-is (assumes it's a regex object). + """ + if is_regex: + if isinstance(pattern, str): + return re.compile(pattern) + else: + return pattern + + if _PYTHON_VERSION > (3, 2): + # ditch start and end characters + start, _, end = self._glob_to_re('_').partition('_') + + if pattern: + pattern_re = self._glob_to_re(pattern) + if _PYTHON_VERSION > (3, 2): + assert pattern_re.startswith(start) and pattern_re.endswith(end) + else: + pattern_re = '' + + base = re.escape(os.path.join(self.base, '')) + if prefix is not None: + # ditch end of pattern character + if _PYTHON_VERSION <= (3, 2): + empty_pattern = self._glob_to_re('') + prefix_re = self._glob_to_re(prefix)[:-len(empty_pattern)] + else: + prefix_re = self._glob_to_re(prefix) + assert prefix_re.startswith(start) and prefix_re.endswith(end) + prefix_re = prefix_re[len(start): len(prefix_re) - len(end)] + sep = os.sep + if os.sep == '\\': + sep = r'\\' + if _PYTHON_VERSION <= (3, 2): + pattern_re = '^' + base + sep.join((prefix_re, + '.*' + pattern_re)) + else: + pattern_re = pattern_re[len(start): len(pattern_re) - len(end)] + pattern_re = r'%s%s%s%s.*%s%s' % (start, base, prefix_re, sep, + pattern_re, end) + else: # no prefix -- respect anchor flag + if anchor: + if _PYTHON_VERSION <= (3, 2): + pattern_re = '^' + base + pattern_re + else: + pattern_re = r'%s%s%s' % (start, base, pattern_re[len(start):]) + + return re.compile(pattern_re) + + def _glob_to_re(self, pattern): + """Translate a shell-like glob pattern to a regular expression. + + Return a string containing the regex. Differs from + 'fnmatch.translate()' in that '*' does not match "special characters" + (which are platform-specific). + """ + pattern_re = fnmatch.translate(pattern) + + # '?' and '*' in the glob pattern become '.' and '.*' in the RE, which + # IMHO is wrong -- '?' and '*' aren't supposed to match slash in Unix, + # and by extension they shouldn't match such "special characters" under + # any OS. So change all non-escaped dots in the RE to match any + # character except the special characters (currently: just os.sep). + sep = os.sep + if os.sep == '\\': + # we're using a regex to manipulate a regex, so we need + # to escape the backslash twice + sep = r'\\\\' + escaped = r'\1[^%s]' % sep + pattern_re = re.sub(r'((? y, + '!=': lambda x, y: x != y, + '<': lambda x, y: x < y, + '<=': lambda x, y: x == y or x < y, + '>': lambda x, y: x > y, + '>=': lambda x, y: x == y or x > y, + 'and': lambda x, y: x and y, + 'or': lambda x, y: x or y, + 'in': lambda x, y: x in y, + 'not in': lambda x, y: x not in y, + } + + def evaluate(self, expr, context): + """ + Evaluate a marker expression returned by the :func:`parse_requirement` + function in the specified context. + """ + if isinstance(expr, string_types): + if expr[0] in '\'"': + result = expr[1:-1] + else: + if expr not in context: + raise SyntaxError('unknown variable: %s' % expr) + result = context[expr] + else: + assert isinstance(expr, dict) + op = expr['op'] + if op not in self.operations: + raise NotImplementedError('op not implemented: %s' % op) + elhs = expr['lhs'] + erhs = expr['rhs'] + if _is_literal(expr['lhs']) and _is_literal(expr['rhs']): + raise SyntaxError('invalid comparison: %s %s %s' % (elhs, op, erhs)) + + lhs = self.evaluate(elhs, context) + rhs = self.evaluate(erhs, context) + if ((elhs == 'python_version' or erhs == 'python_version') and + op in ('<', '<=', '>', '>=', '===', '==', '!=', '~=')): + lhs = NV(lhs) + rhs = NV(rhs) + elif elhs == 'python_version' and op in ('in', 'not in'): + lhs = NV(lhs) + rhs = _get_versions(rhs) + result = self.operations[op](lhs, rhs) + return result + +def default_context(): + def format_full_version(info): + version = '%s.%s.%s' % (info.major, info.minor, info.micro) + kind = info.releaselevel + if kind != 'final': + version += kind[0] + str(info.serial) + return version + + if hasattr(sys, 'implementation'): + implementation_version = format_full_version(sys.implementation.version) + implementation_name = sys.implementation.name + else: + implementation_version = '0' + implementation_name = '' + + result = { + 'implementation_name': implementation_name, + 'implementation_version': implementation_version, + 'os_name': os.name, + 'platform_machine': platform.machine(), + 'platform_python_implementation': platform.python_implementation(), + 'platform_release': platform.release(), + 'platform_system': platform.system(), + 'platform_version': platform.version(), + 'platform_in_venv': str(in_venv()), + 'python_full_version': platform.python_version(), + 'python_version': platform.python_version()[:3], + 'sys_platform': sys.platform, + } + return result + +DEFAULT_CONTEXT = default_context() +del default_context + +evaluator = Evaluator() + +def interpret(marker, execution_context=None): + """ + Interpret a marker and return a result depending on environment. + + :param marker: The marker to interpret. + :type marker: str + :param execution_context: The context used for name lookup. + :type execution_context: mapping + """ + try: + expr, rest = parse_marker(marker) + except Exception as e: + raise SyntaxError('Unable to interpret marker syntax: %s: %s' % (marker, e)) + if rest and rest[0] != '#': + raise SyntaxError('unexpected trailing data in marker: %s: %s' % (marker, rest)) + context = dict(DEFAULT_CONTEXT) + if execution_context: + context.update(execution_context) + return evaluator.evaluate(expr, context) diff --git a/venv/Lib/site-packages/pip/_vendor/distlib/metadata.py b/venv/Lib/site-packages/pip/_vendor/distlib/metadata.py new file mode 100644 index 0000000..6a26b0a --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/distlib/metadata.py @@ -0,0 +1,1058 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2012 The Python Software Foundation. +# See LICENSE.txt and CONTRIBUTORS.txt. +# +"""Implementation of the Metadata for Python packages PEPs. + +Supports all metadata formats (1.0, 1.1, 1.2, 1.3/2.1 and withdrawn 2.0). +""" +from __future__ import unicode_literals + +import codecs +from email import message_from_file +import json +import logging +import re + + +from . import DistlibException, __version__ +from .compat import StringIO, string_types, text_type +from .markers import interpret +from .util import extract_by_key, get_extras +from .version import get_scheme, PEP440_VERSION_RE + +logger = logging.getLogger(__name__) + + +class MetadataMissingError(DistlibException): + """A required metadata is missing""" + + +class MetadataConflictError(DistlibException): + """Attempt to read or write metadata fields that are conflictual.""" + + +class MetadataUnrecognizedVersionError(DistlibException): + """Unknown metadata version number.""" + + +class MetadataInvalidError(DistlibException): + """A metadata value is invalid""" + +# public API of this module +__all__ = ['Metadata', 'PKG_INFO_ENCODING', 'PKG_INFO_PREFERRED_VERSION'] + +# Encoding used for the PKG-INFO files +PKG_INFO_ENCODING = 'utf-8' + +# preferred version. Hopefully will be changed +# to 1.2 once PEP 345 is supported everywhere +PKG_INFO_PREFERRED_VERSION = '1.1' + +_LINE_PREFIX_1_2 = re.compile('\n \\|') +_LINE_PREFIX_PRE_1_2 = re.compile('\n ') +_241_FIELDS = ('Metadata-Version', 'Name', 'Version', 'Platform', + 'Summary', 'Description', + 'Keywords', 'Home-page', 'Author', 'Author-email', + 'License') + +_314_FIELDS = ('Metadata-Version', 'Name', 'Version', 'Platform', + 'Supported-Platform', 'Summary', 'Description', + 'Keywords', 'Home-page', 'Author', 'Author-email', + 'License', 'Classifier', 'Download-URL', 'Obsoletes', + 'Provides', 'Requires') + +_314_MARKERS = ('Obsoletes', 'Provides', 'Requires', 'Classifier', + 'Download-URL') + +_345_FIELDS = ('Metadata-Version', 'Name', 'Version', 'Platform', + 'Supported-Platform', 'Summary', 'Description', + 'Keywords', 'Home-page', 'Author', 'Author-email', + 'Maintainer', 'Maintainer-email', 'License', + 'Classifier', 'Download-URL', 'Obsoletes-Dist', + 'Project-URL', 'Provides-Dist', 'Requires-Dist', + 'Requires-Python', 'Requires-External') + +_345_MARKERS = ('Provides-Dist', 'Requires-Dist', 'Requires-Python', + 'Obsoletes-Dist', 'Requires-External', 'Maintainer', + 'Maintainer-email', 'Project-URL') + +_426_FIELDS = ('Metadata-Version', 'Name', 'Version', 'Platform', + 'Supported-Platform', 'Summary', 'Description', + 'Keywords', 'Home-page', 'Author', 'Author-email', + 'Maintainer', 'Maintainer-email', 'License', + 'Classifier', 'Download-URL', 'Obsoletes-Dist', + 'Project-URL', 'Provides-Dist', 'Requires-Dist', + 'Requires-Python', 'Requires-External', 'Private-Version', + 'Obsoleted-By', 'Setup-Requires-Dist', 'Extension', + 'Provides-Extra') + +_426_MARKERS = ('Private-Version', 'Provides-Extra', 'Obsoleted-By', + 'Setup-Requires-Dist', 'Extension') + +# See issue #106: Sometimes 'Requires' and 'Provides' occur wrongly in +# the metadata. Include them in the tuple literal below to allow them +# (for now). +# Ditto for Obsoletes - see issue #140. +_566_FIELDS = _426_FIELDS + ('Description-Content-Type', + 'Requires', 'Provides', 'Obsoletes') + +_566_MARKERS = ('Description-Content-Type',) + +_ALL_FIELDS = set() +_ALL_FIELDS.update(_241_FIELDS) +_ALL_FIELDS.update(_314_FIELDS) +_ALL_FIELDS.update(_345_FIELDS) +_ALL_FIELDS.update(_426_FIELDS) +_ALL_FIELDS.update(_566_FIELDS) + +EXTRA_RE = re.compile(r'''extra\s*==\s*("([^"]+)"|'([^']+)')''') + + +def _version2fieldlist(version): + if version == '1.0': + return _241_FIELDS + elif version == '1.1': + return _314_FIELDS + elif version == '1.2': + return _345_FIELDS + elif version in ('1.3', '2.1'): + # avoid adding field names if already there + return _345_FIELDS + tuple(f for f in _566_FIELDS if f not in _345_FIELDS) + elif version == '2.0': + return _426_FIELDS + raise MetadataUnrecognizedVersionError(version) + + +def _best_version(fields): + """Detect the best version depending on the fields used.""" + def _has_marker(keys, markers): + for marker in markers: + if marker in keys: + return True + return False + + keys = [] + for key, value in fields.items(): + if value in ([], 'UNKNOWN', None): + continue + keys.append(key) + + possible_versions = ['1.0', '1.1', '1.2', '1.3', '2.0', '2.1'] + + # first let's try to see if a field is not part of one of the version + for key in keys: + if key not in _241_FIELDS and '1.0' in possible_versions: + possible_versions.remove('1.0') + logger.debug('Removed 1.0 due to %s', key) + if key not in _314_FIELDS and '1.1' in possible_versions: + possible_versions.remove('1.1') + logger.debug('Removed 1.1 due to %s', key) + if key not in _345_FIELDS and '1.2' in possible_versions: + possible_versions.remove('1.2') + logger.debug('Removed 1.2 due to %s', key) + if key not in _566_FIELDS and '1.3' in possible_versions: + possible_versions.remove('1.3') + logger.debug('Removed 1.3 due to %s', key) + if key not in _566_FIELDS and '2.1' in possible_versions: + if key != 'Description': # In 2.1, description allowed after headers + possible_versions.remove('2.1') + logger.debug('Removed 2.1 due to %s', key) + if key not in _426_FIELDS and '2.0' in possible_versions: + possible_versions.remove('2.0') + logger.debug('Removed 2.0 due to %s', key) + + # possible_version contains qualified versions + if len(possible_versions) == 1: + return possible_versions[0] # found ! + elif len(possible_versions) == 0: + logger.debug('Out of options - unknown metadata set: %s', fields) + raise MetadataConflictError('Unknown metadata set') + + # let's see if one unique marker is found + is_1_1 = '1.1' in possible_versions and _has_marker(keys, _314_MARKERS) + is_1_2 = '1.2' in possible_versions and _has_marker(keys, _345_MARKERS) + is_2_1 = '2.1' in possible_versions and _has_marker(keys, _566_MARKERS) + is_2_0 = '2.0' in possible_versions and _has_marker(keys, _426_MARKERS) + if int(is_1_1) + int(is_1_2) + int(is_2_1) + int(is_2_0) > 1: + raise MetadataConflictError('You used incompatible 1.1/1.2/2.0/2.1 fields') + + # we have the choice, 1.0, or 1.2, or 2.0 + # - 1.0 has a broken Summary field but works with all tools + # - 1.1 is to avoid + # - 1.2 fixes Summary but has little adoption + # - 2.0 adds more features and is very new + if not is_1_1 and not is_1_2 and not is_2_1 and not is_2_0: + # we couldn't find any specific marker + if PKG_INFO_PREFERRED_VERSION in possible_versions: + return PKG_INFO_PREFERRED_VERSION + if is_1_1: + return '1.1' + if is_1_2: + return '1.2' + if is_2_1: + return '2.1' + + return '2.0' + +# This follows the rules about transforming keys as described in +# https://www.python.org/dev/peps/pep-0566/#id17 +_ATTR2FIELD = { + name.lower().replace("-", "_"): name for name in _ALL_FIELDS +} +_FIELD2ATTR = {field: attr for attr, field in _ATTR2FIELD.items()} + +_PREDICATE_FIELDS = ('Requires-Dist', 'Obsoletes-Dist', 'Provides-Dist') +_VERSIONS_FIELDS = ('Requires-Python',) +_VERSION_FIELDS = ('Version',) +_LISTFIELDS = ('Platform', 'Classifier', 'Obsoletes', + 'Requires', 'Provides', 'Obsoletes-Dist', + 'Provides-Dist', 'Requires-Dist', 'Requires-External', + 'Project-URL', 'Supported-Platform', 'Setup-Requires-Dist', + 'Provides-Extra', 'Extension') +_LISTTUPLEFIELDS = ('Project-URL',) + +_ELEMENTSFIELD = ('Keywords',) + +_UNICODEFIELDS = ('Author', 'Maintainer', 'Summary', 'Description') + +_MISSING = object() + +_FILESAFE = re.compile('[^A-Za-z0-9.]+') + + +def _get_name_and_version(name, version, for_filename=False): + """Return the distribution name with version. + + If for_filename is true, return a filename-escaped form.""" + if for_filename: + # For both name and version any runs of non-alphanumeric or '.' + # characters are replaced with a single '-'. Additionally any + # spaces in the version string become '.' + name = _FILESAFE.sub('-', name) + version = _FILESAFE.sub('-', version.replace(' ', '.')) + return '%s-%s' % (name, version) + + +class LegacyMetadata(object): + """The legacy metadata of a release. + + Supports versions 1.0, 1.1, 1.2, 2.0 and 1.3/2.1 (auto-detected). You can + instantiate the class with one of these arguments (or none): + - *path*, the path to a metadata file + - *fileobj* give a file-like object with metadata as content + - *mapping* is a dict-like object + - *scheme* is a version scheme name + """ + # TODO document the mapping API and UNKNOWN default key + + def __init__(self, path=None, fileobj=None, mapping=None, + scheme='default'): + if [path, fileobj, mapping].count(None) < 2: + raise TypeError('path, fileobj and mapping are exclusive') + self._fields = {} + self.requires_files = [] + self._dependencies = None + self.scheme = scheme + if path is not None: + self.read(path) + elif fileobj is not None: + self.read_file(fileobj) + elif mapping is not None: + self.update(mapping) + self.set_metadata_version() + + def set_metadata_version(self): + self._fields['Metadata-Version'] = _best_version(self._fields) + + def _write_field(self, fileobj, name, value): + fileobj.write('%s: %s\n' % (name, value)) + + def __getitem__(self, name): + return self.get(name) + + def __setitem__(self, name, value): + return self.set(name, value) + + def __delitem__(self, name): + field_name = self._convert_name(name) + try: + del self._fields[field_name] + except KeyError: + raise KeyError(name) + + def __contains__(self, name): + return (name in self._fields or + self._convert_name(name) in self._fields) + + def _convert_name(self, name): + if name in _ALL_FIELDS: + return name + name = name.replace('-', '_').lower() + return _ATTR2FIELD.get(name, name) + + def _default_value(self, name): + if name in _LISTFIELDS or name in _ELEMENTSFIELD: + return [] + return 'UNKNOWN' + + def _remove_line_prefix(self, value): + if self.metadata_version in ('1.0', '1.1'): + return _LINE_PREFIX_PRE_1_2.sub('\n', value) + else: + return _LINE_PREFIX_1_2.sub('\n', value) + + def __getattr__(self, name): + if name in _ATTR2FIELD: + return self[name] + raise AttributeError(name) + + # + # Public API + # + +# dependencies = property(_get_dependencies, _set_dependencies) + + def get_fullname(self, filesafe=False): + """Return the distribution name with version. + + If filesafe is true, return a filename-escaped form.""" + return _get_name_and_version(self['Name'], self['Version'], filesafe) + + def is_field(self, name): + """return True if name is a valid metadata key""" + name = self._convert_name(name) + return name in _ALL_FIELDS + + def is_multi_field(self, name): + name = self._convert_name(name) + return name in _LISTFIELDS + + def read(self, filepath): + """Read the metadata values from a file path.""" + fp = codecs.open(filepath, 'r', encoding='utf-8') + try: + self.read_file(fp) + finally: + fp.close() + + def read_file(self, fileob): + """Read the metadata values from a file object.""" + msg = message_from_file(fileob) + self._fields['Metadata-Version'] = msg['metadata-version'] + + # When reading, get all the fields we can + for field in _ALL_FIELDS: + if field not in msg: + continue + if field in _LISTFIELDS: + # we can have multiple lines + values = msg.get_all(field) + if field in _LISTTUPLEFIELDS and values is not None: + values = [tuple(value.split(',')) for value in values] + self.set(field, values) + else: + # single line + value = msg[field] + if value is not None and value != 'UNKNOWN': + self.set(field, value) + + # PEP 566 specifies that the body be used for the description, if + # available + body = msg.get_payload() + self["Description"] = body if body else self["Description"] + # logger.debug('Attempting to set metadata for %s', self) + # self.set_metadata_version() + + def write(self, filepath, skip_unknown=False): + """Write the metadata fields to filepath.""" + fp = codecs.open(filepath, 'w', encoding='utf-8') + try: + self.write_file(fp, skip_unknown) + finally: + fp.close() + + def write_file(self, fileobject, skip_unknown=False): + """Write the PKG-INFO format data to a file object.""" + self.set_metadata_version() + + for field in _version2fieldlist(self['Metadata-Version']): + values = self.get(field) + if skip_unknown and values in ('UNKNOWN', [], ['UNKNOWN']): + continue + if field in _ELEMENTSFIELD: + self._write_field(fileobject, field, ','.join(values)) + continue + if field not in _LISTFIELDS: + if field == 'Description': + if self.metadata_version in ('1.0', '1.1'): + values = values.replace('\n', '\n ') + else: + values = values.replace('\n', '\n |') + values = [values] + + if field in _LISTTUPLEFIELDS: + values = [','.join(value) for value in values] + + for value in values: + self._write_field(fileobject, field, value) + + def update(self, other=None, **kwargs): + """Set metadata values from the given iterable `other` and kwargs. + + Behavior is like `dict.update`: If `other` has a ``keys`` method, + they are looped over and ``self[key]`` is assigned ``other[key]``. + Else, ``other`` is an iterable of ``(key, value)`` iterables. + + Keys that don't match a metadata field or that have an empty value are + dropped. + """ + def _set(key, value): + if key in _ATTR2FIELD and value: + self.set(self._convert_name(key), value) + + if not other: + # other is None or empty container + pass + elif hasattr(other, 'keys'): + for k in other.keys(): + _set(k, other[k]) + else: + for k, v in other: + _set(k, v) + + if kwargs: + for k, v in kwargs.items(): + _set(k, v) + + def set(self, name, value): + """Control then set a metadata field.""" + name = self._convert_name(name) + + if ((name in _ELEMENTSFIELD or name == 'Platform') and + not isinstance(value, (list, tuple))): + if isinstance(value, string_types): + value = [v.strip() for v in value.split(',')] + else: + value = [] + elif (name in _LISTFIELDS and + not isinstance(value, (list, tuple))): + if isinstance(value, string_types): + value = [value] + else: + value = [] + + if logger.isEnabledFor(logging.WARNING): + project_name = self['Name'] + + scheme = get_scheme(self.scheme) + if name in _PREDICATE_FIELDS and value is not None: + for v in value: + # check that the values are valid + if not scheme.is_valid_matcher(v.split(';')[0]): + logger.warning( + "'%s': '%s' is not valid (field '%s')", + project_name, v, name) + # FIXME this rejects UNKNOWN, is that right? + elif name in _VERSIONS_FIELDS and value is not None: + if not scheme.is_valid_constraint_list(value): + logger.warning("'%s': '%s' is not a valid version (field '%s')", + project_name, value, name) + elif name in _VERSION_FIELDS and value is not None: + if not scheme.is_valid_version(value): + logger.warning("'%s': '%s' is not a valid version (field '%s')", + project_name, value, name) + + if name in _UNICODEFIELDS: + if name == 'Description': + value = self._remove_line_prefix(value) + + self._fields[name] = value + + def get(self, name, default=_MISSING): + """Get a metadata field.""" + name = self._convert_name(name) + if name not in self._fields: + if default is _MISSING: + default = self._default_value(name) + return default + if name in _UNICODEFIELDS: + value = self._fields[name] + return value + elif name in _LISTFIELDS: + value = self._fields[name] + if value is None: + return [] + res = [] + for val in value: + if name not in _LISTTUPLEFIELDS: + res.append(val) + else: + # That's for Project-URL + res.append((val[0], val[1])) + return res + + elif name in _ELEMENTSFIELD: + value = self._fields[name] + if isinstance(value, string_types): + return value.split(',') + return self._fields[name] + + def check(self, strict=False): + """Check if the metadata is compliant. If strict is True then raise if + no Name or Version are provided""" + self.set_metadata_version() + + # XXX should check the versions (if the file was loaded) + missing, warnings = [], [] + + for attr in ('Name', 'Version'): # required by PEP 345 + if attr not in self: + missing.append(attr) + + if strict and missing != []: + msg = 'missing required metadata: %s' % ', '.join(missing) + raise MetadataMissingError(msg) + + for attr in ('Home-page', 'Author'): + if attr not in self: + missing.append(attr) + + # checking metadata 1.2 (XXX needs to check 1.1, 1.0) + if self['Metadata-Version'] != '1.2': + return missing, warnings + + scheme = get_scheme(self.scheme) + + def are_valid_constraints(value): + for v in value: + if not scheme.is_valid_matcher(v.split(';')[0]): + return False + return True + + for fields, controller in ((_PREDICATE_FIELDS, are_valid_constraints), + (_VERSIONS_FIELDS, + scheme.is_valid_constraint_list), + (_VERSION_FIELDS, + scheme.is_valid_version)): + for field in fields: + value = self.get(field, None) + if value is not None and not controller(value): + warnings.append("Wrong value for '%s': %s" % (field, value)) + + return missing, warnings + + def todict(self, skip_missing=False): + """Return fields as a dict. + + Field names will be converted to use the underscore-lowercase style + instead of hyphen-mixed case (i.e. home_page instead of Home-page). + This is as per https://www.python.org/dev/peps/pep-0566/#id17. + """ + self.set_metadata_version() + + fields = _version2fieldlist(self['Metadata-Version']) + + data = {} + + for field_name in fields: + if not skip_missing or field_name in self._fields: + key = _FIELD2ATTR[field_name] + if key != 'project_url': + data[key] = self[field_name] + else: + data[key] = [','.join(u) for u in self[field_name]] + + return data + + def add_requirements(self, requirements): + if self['Metadata-Version'] == '1.1': + # we can't have 1.1 metadata *and* Setuptools requires + for field in ('Obsoletes', 'Requires', 'Provides'): + if field in self: + del self[field] + self['Requires-Dist'] += requirements + + # Mapping API + # TODO could add iter* variants + + def keys(self): + return list(_version2fieldlist(self['Metadata-Version'])) + + def __iter__(self): + for key in self.keys(): + yield key + + def values(self): + return [self[key] for key in self.keys()] + + def items(self): + return [(key, self[key]) for key in self.keys()] + + def __repr__(self): + return '<%s %s %s>' % (self.__class__.__name__, self.name, + self.version) + + +METADATA_FILENAME = 'pydist.json' +WHEEL_METADATA_FILENAME = 'metadata.json' +LEGACY_METADATA_FILENAME = 'METADATA' + + +class Metadata(object): + """ + The metadata of a release. This implementation uses 2.0 (JSON) + metadata where possible. If not possible, it wraps a LegacyMetadata + instance which handles the key-value metadata format. + """ + + METADATA_VERSION_MATCHER = re.compile(r'^\d+(\.\d+)*$') + + NAME_MATCHER = re.compile('^[0-9A-Z]([0-9A-Z_.-]*[0-9A-Z])?$', re.I) + + VERSION_MATCHER = PEP440_VERSION_RE + + SUMMARY_MATCHER = re.compile('.{1,2047}') + + METADATA_VERSION = '2.0' + + GENERATOR = 'distlib (%s)' % __version__ + + MANDATORY_KEYS = { + 'name': (), + 'version': (), + 'summary': ('legacy',), + } + + INDEX_KEYS = ('name version license summary description author ' + 'author_email keywords platform home_page classifiers ' + 'download_url') + + DEPENDENCY_KEYS = ('extras run_requires test_requires build_requires ' + 'dev_requires provides meta_requires obsoleted_by ' + 'supports_environments') + + SYNTAX_VALIDATORS = { + 'metadata_version': (METADATA_VERSION_MATCHER, ()), + 'name': (NAME_MATCHER, ('legacy',)), + 'version': (VERSION_MATCHER, ('legacy',)), + 'summary': (SUMMARY_MATCHER, ('legacy',)), + } + + __slots__ = ('_legacy', '_data', 'scheme') + + def __init__(self, path=None, fileobj=None, mapping=None, + scheme='default'): + if [path, fileobj, mapping].count(None) < 2: + raise TypeError('path, fileobj and mapping are exclusive') + self._legacy = None + self._data = None + self.scheme = scheme + #import pdb; pdb.set_trace() + if mapping is not None: + try: + self._validate_mapping(mapping, scheme) + self._data = mapping + except MetadataUnrecognizedVersionError: + self._legacy = LegacyMetadata(mapping=mapping, scheme=scheme) + self.validate() + else: + data = None + if path: + with open(path, 'rb') as f: + data = f.read() + elif fileobj: + data = fileobj.read() + if data is None: + # Initialised with no args - to be added + self._data = { + 'metadata_version': self.METADATA_VERSION, + 'generator': self.GENERATOR, + } + else: + if not isinstance(data, text_type): + data = data.decode('utf-8') + try: + self._data = json.loads(data) + self._validate_mapping(self._data, scheme) + except ValueError: + # Note: MetadataUnrecognizedVersionError does not + # inherit from ValueError (it's a DistlibException, + # which should not inherit from ValueError). + # The ValueError comes from the json.load - if that + # succeeds and we get a validation error, we want + # that to propagate + self._legacy = LegacyMetadata(fileobj=StringIO(data), + scheme=scheme) + self.validate() + + common_keys = set(('name', 'version', 'license', 'keywords', 'summary')) + + none_list = (None, list) + none_dict = (None, dict) + + mapped_keys = { + 'run_requires': ('Requires-Dist', list), + 'build_requires': ('Setup-Requires-Dist', list), + 'dev_requires': none_list, + 'test_requires': none_list, + 'meta_requires': none_list, + 'extras': ('Provides-Extra', list), + 'modules': none_list, + 'namespaces': none_list, + 'exports': none_dict, + 'commands': none_dict, + 'classifiers': ('Classifier', list), + 'source_url': ('Download-URL', None), + 'metadata_version': ('Metadata-Version', None), + } + + del none_list, none_dict + + def __getattribute__(self, key): + common = object.__getattribute__(self, 'common_keys') + mapped = object.__getattribute__(self, 'mapped_keys') + if key in mapped: + lk, maker = mapped[key] + if self._legacy: + if lk is None: + result = None if maker is None else maker() + else: + result = self._legacy.get(lk) + else: + value = None if maker is None else maker() + if key not in ('commands', 'exports', 'modules', 'namespaces', + 'classifiers'): + result = self._data.get(key, value) + else: + # special cases for PEP 459 + sentinel = object() + result = sentinel + d = self._data.get('extensions') + if d: + if key == 'commands': + result = d.get('python.commands', value) + elif key == 'classifiers': + d = d.get('python.details') + if d: + result = d.get(key, value) + else: + d = d.get('python.exports') + if not d: + d = self._data.get('python.exports') + if d: + result = d.get(key, value) + if result is sentinel: + result = value + elif key not in common: + result = object.__getattribute__(self, key) + elif self._legacy: + result = self._legacy.get(key) + else: + result = self._data.get(key) + return result + + def _validate_value(self, key, value, scheme=None): + if key in self.SYNTAX_VALIDATORS: + pattern, exclusions = self.SYNTAX_VALIDATORS[key] + if (scheme or self.scheme) not in exclusions: + m = pattern.match(value) + if not m: + raise MetadataInvalidError("'%s' is an invalid value for " + "the '%s' property" % (value, + key)) + + def __setattr__(self, key, value): + self._validate_value(key, value) + common = object.__getattribute__(self, 'common_keys') + mapped = object.__getattribute__(self, 'mapped_keys') + if key in mapped: + lk, _ = mapped[key] + if self._legacy: + if lk is None: + raise NotImplementedError + self._legacy[lk] = value + elif key not in ('commands', 'exports', 'modules', 'namespaces', + 'classifiers'): + self._data[key] = value + else: + # special cases for PEP 459 + d = self._data.setdefault('extensions', {}) + if key == 'commands': + d['python.commands'] = value + elif key == 'classifiers': + d = d.setdefault('python.details', {}) + d[key] = value + else: + d = d.setdefault('python.exports', {}) + d[key] = value + elif key not in common: + object.__setattr__(self, key, value) + else: + if key == 'keywords': + if isinstance(value, string_types): + value = value.strip() + if value: + value = value.split() + else: + value = [] + if self._legacy: + self._legacy[key] = value + else: + self._data[key] = value + + @property + def name_and_version(self): + return _get_name_and_version(self.name, self.version, True) + + @property + def provides(self): + if self._legacy: + result = self._legacy['Provides-Dist'] + else: + result = self._data.setdefault('provides', []) + s = '%s (%s)' % (self.name, self.version) + if s not in result: + result.append(s) + return result + + @provides.setter + def provides(self, value): + if self._legacy: + self._legacy['Provides-Dist'] = value + else: + self._data['provides'] = value + + def get_requirements(self, reqts, extras=None, env=None): + """ + Base method to get dependencies, given a set of extras + to satisfy and an optional environment context. + :param reqts: A list of sometimes-wanted dependencies, + perhaps dependent on extras and environment. + :param extras: A list of optional components being requested. + :param env: An optional environment for marker evaluation. + """ + if self._legacy: + result = reqts + else: + result = [] + extras = get_extras(extras or [], self.extras) + for d in reqts: + if 'extra' not in d and 'environment' not in d: + # unconditional + include = True + else: + if 'extra' not in d: + # Not extra-dependent - only environment-dependent + include = True + else: + include = d.get('extra') in extras + if include: + # Not excluded because of extras, check environment + marker = d.get('environment') + if marker: + include = interpret(marker, env) + if include: + result.extend(d['requires']) + for key in ('build', 'dev', 'test'): + e = ':%s:' % key + if e in extras: + extras.remove(e) + # A recursive call, but it should terminate since 'test' + # has been removed from the extras + reqts = self._data.get('%s_requires' % key, []) + result.extend(self.get_requirements(reqts, extras=extras, + env=env)) + return result + + @property + def dictionary(self): + if self._legacy: + return self._from_legacy() + return self._data + + @property + def dependencies(self): + if self._legacy: + raise NotImplementedError + else: + return extract_by_key(self._data, self.DEPENDENCY_KEYS) + + @dependencies.setter + def dependencies(self, value): + if self._legacy: + raise NotImplementedError + else: + self._data.update(value) + + def _validate_mapping(self, mapping, scheme): + if mapping.get('metadata_version') != self.METADATA_VERSION: + raise MetadataUnrecognizedVersionError() + missing = [] + for key, exclusions in self.MANDATORY_KEYS.items(): + if key not in mapping: + if scheme not in exclusions: + missing.append(key) + if missing: + msg = 'Missing metadata items: %s' % ', '.join(missing) + raise MetadataMissingError(msg) + for k, v in mapping.items(): + self._validate_value(k, v, scheme) + + def validate(self): + if self._legacy: + missing, warnings = self._legacy.check(True) + if missing or warnings: + logger.warning('Metadata: missing: %s, warnings: %s', + missing, warnings) + else: + self._validate_mapping(self._data, self.scheme) + + def todict(self): + if self._legacy: + return self._legacy.todict(True) + else: + result = extract_by_key(self._data, self.INDEX_KEYS) + return result + + def _from_legacy(self): + assert self._legacy and not self._data + result = { + 'metadata_version': self.METADATA_VERSION, + 'generator': self.GENERATOR, + } + lmd = self._legacy.todict(True) # skip missing ones + for k in ('name', 'version', 'license', 'summary', 'description', + 'classifier'): + if k in lmd: + if k == 'classifier': + nk = 'classifiers' + else: + nk = k + result[nk] = lmd[k] + kw = lmd.get('Keywords', []) + if kw == ['']: + kw = [] + result['keywords'] = kw + keys = (('requires_dist', 'run_requires'), + ('setup_requires_dist', 'build_requires')) + for ok, nk in keys: + if ok in lmd and lmd[ok]: + result[nk] = [{'requires': lmd[ok]}] + result['provides'] = self.provides + author = {} + maintainer = {} + return result + + LEGACY_MAPPING = { + 'name': 'Name', + 'version': 'Version', + ('extensions', 'python.details', 'license'): 'License', + 'summary': 'Summary', + 'description': 'Description', + ('extensions', 'python.project', 'project_urls', 'Home'): 'Home-page', + ('extensions', 'python.project', 'contacts', 0, 'name'): 'Author', + ('extensions', 'python.project', 'contacts', 0, 'email'): 'Author-email', + 'source_url': 'Download-URL', + ('extensions', 'python.details', 'classifiers'): 'Classifier', + } + + def _to_legacy(self): + def process_entries(entries): + reqts = set() + for e in entries: + extra = e.get('extra') + env = e.get('environment') + rlist = e['requires'] + for r in rlist: + if not env and not extra: + reqts.add(r) + else: + marker = '' + if extra: + marker = 'extra == "%s"' % extra + if env: + if marker: + marker = '(%s) and %s' % (env, marker) + else: + marker = env + reqts.add(';'.join((r, marker))) + return reqts + + assert self._data and not self._legacy + result = LegacyMetadata() + nmd = self._data + # import pdb; pdb.set_trace() + for nk, ok in self.LEGACY_MAPPING.items(): + if not isinstance(nk, tuple): + if nk in nmd: + result[ok] = nmd[nk] + else: + d = nmd + found = True + for k in nk: + try: + d = d[k] + except (KeyError, IndexError): + found = False + break + if found: + result[ok] = d + r1 = process_entries(self.run_requires + self.meta_requires) + r2 = process_entries(self.build_requires + self.dev_requires) + if self.extras: + result['Provides-Extra'] = sorted(self.extras) + result['Requires-Dist'] = sorted(r1) + result['Setup-Requires-Dist'] = sorted(r2) + # TODO: any other fields wanted + return result + + def write(self, path=None, fileobj=None, legacy=False, skip_unknown=True): + if [path, fileobj].count(None) != 1: + raise ValueError('Exactly one of path and fileobj is needed') + self.validate() + if legacy: + if self._legacy: + legacy_md = self._legacy + else: + legacy_md = self._to_legacy() + if path: + legacy_md.write(path, skip_unknown=skip_unknown) + else: + legacy_md.write_file(fileobj, skip_unknown=skip_unknown) + else: + if self._legacy: + d = self._from_legacy() + else: + d = self._data + if fileobj: + json.dump(d, fileobj, ensure_ascii=True, indent=2, + sort_keys=True) + else: + with codecs.open(path, 'w', 'utf-8') as f: + json.dump(d, f, ensure_ascii=True, indent=2, + sort_keys=True) + + def add_requirements(self, requirements): + if self._legacy: + self._legacy.add_requirements(requirements) + else: + run_requires = self._data.setdefault('run_requires', []) + always = None + for entry in run_requires: + if 'environment' not in entry and 'extra' not in entry: + always = entry + break + if always is None: + always = { 'requires': requirements } + run_requires.insert(0, always) + else: + rset = set(always['requires']) | set(requirements) + always['requires'] = sorted(rset) + + def __repr__(self): + name = self.name or '(no name)' + version = self.version or 'no version' + return '<%s %s %s (%s)>' % (self.__class__.__name__, + self.metadata_version, name, version) diff --git a/venv/Lib/site-packages/pip/_vendor/distlib/resources.py b/venv/Lib/site-packages/pip/_vendor/distlib/resources.py new file mode 100644 index 0000000..fef52aa --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/distlib/resources.py @@ -0,0 +1,358 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2013-2017 Vinay Sajip. +# Licensed to the Python Software Foundation under a contributor agreement. +# See LICENSE.txt and CONTRIBUTORS.txt. +# +from __future__ import unicode_literals + +import bisect +import io +import logging +import os +import pkgutil +import sys +import types +import zipimport + +from . import DistlibException +from .util import cached_property, get_cache_base, Cache + +logger = logging.getLogger(__name__) + + +cache = None # created when needed + + +class ResourceCache(Cache): + def __init__(self, base=None): + if base is None: + # Use native string to avoid issues on 2.x: see Python #20140. + base = os.path.join(get_cache_base(), str('resource-cache')) + super(ResourceCache, self).__init__(base) + + def is_stale(self, resource, path): + """ + Is the cache stale for the given resource? + + :param resource: The :class:`Resource` being cached. + :param path: The path of the resource in the cache. + :return: True if the cache is stale. + """ + # Cache invalidation is a hard problem :-) + return True + + def get(self, resource): + """ + Get a resource into the cache, + + :param resource: A :class:`Resource` instance. + :return: The pathname of the resource in the cache. + """ + prefix, path = resource.finder.get_cache_info(resource) + if prefix is None: + result = path + else: + result = os.path.join(self.base, self.prefix_to_dir(prefix), path) + dirname = os.path.dirname(result) + if not os.path.isdir(dirname): + os.makedirs(dirname) + if not os.path.exists(result): + stale = True + else: + stale = self.is_stale(resource, path) + if stale: + # write the bytes of the resource to the cache location + with open(result, 'wb') as f: + f.write(resource.bytes) + return result + + +class ResourceBase(object): + def __init__(self, finder, name): + self.finder = finder + self.name = name + + +class Resource(ResourceBase): + """ + A class representing an in-package resource, such as a data file. This is + not normally instantiated by user code, but rather by a + :class:`ResourceFinder` which manages the resource. + """ + is_container = False # Backwards compatibility + + def as_stream(self): + """ + Get the resource as a stream. + + This is not a property to make it obvious that it returns a new stream + each time. + """ + return self.finder.get_stream(self) + + @cached_property + def file_path(self): + global cache + if cache is None: + cache = ResourceCache() + return cache.get(self) + + @cached_property + def bytes(self): + return self.finder.get_bytes(self) + + @cached_property + def size(self): + return self.finder.get_size(self) + + +class ResourceContainer(ResourceBase): + is_container = True # Backwards compatibility + + @cached_property + def resources(self): + return self.finder.get_resources(self) + + +class ResourceFinder(object): + """ + Resource finder for file system resources. + """ + + if sys.platform.startswith('java'): + skipped_extensions = ('.pyc', '.pyo', '.class') + else: + skipped_extensions = ('.pyc', '.pyo') + + def __init__(self, module): + self.module = module + self.loader = getattr(module, '__loader__', None) + self.base = os.path.dirname(getattr(module, '__file__', '')) + + def _adjust_path(self, path): + return os.path.realpath(path) + + def _make_path(self, resource_name): + # Issue #50: need to preserve type of path on Python 2.x + # like os.path._get_sep + if isinstance(resource_name, bytes): # should only happen on 2.x + sep = b'/' + else: + sep = '/' + parts = resource_name.split(sep) + parts.insert(0, self.base) + result = os.path.join(*parts) + return self._adjust_path(result) + + def _find(self, path): + return os.path.exists(path) + + def get_cache_info(self, resource): + return None, resource.path + + def find(self, resource_name): + path = self._make_path(resource_name) + if not self._find(path): + result = None + else: + if self._is_directory(path): + result = ResourceContainer(self, resource_name) + else: + result = Resource(self, resource_name) + result.path = path + return result + + def get_stream(self, resource): + return open(resource.path, 'rb') + + def get_bytes(self, resource): + with open(resource.path, 'rb') as f: + return f.read() + + def get_size(self, resource): + return os.path.getsize(resource.path) + + def get_resources(self, resource): + def allowed(f): + return (f != '__pycache__' and not + f.endswith(self.skipped_extensions)) + return set([f for f in os.listdir(resource.path) if allowed(f)]) + + def is_container(self, resource): + return self._is_directory(resource.path) + + _is_directory = staticmethod(os.path.isdir) + + def iterator(self, resource_name): + resource = self.find(resource_name) + if resource is not None: + todo = [resource] + while todo: + resource = todo.pop(0) + yield resource + if resource.is_container: + rname = resource.name + for name in resource.resources: + if not rname: + new_name = name + else: + new_name = '/'.join([rname, name]) + child = self.find(new_name) + if child.is_container: + todo.append(child) + else: + yield child + + +class ZipResourceFinder(ResourceFinder): + """ + Resource finder for resources in .zip files. + """ + def __init__(self, module): + super(ZipResourceFinder, self).__init__(module) + archive = self.loader.archive + self.prefix_len = 1 + len(archive) + # PyPy doesn't have a _files attr on zipimporter, and you can't set one + if hasattr(self.loader, '_files'): + self._files = self.loader._files + else: + self._files = zipimport._zip_directory_cache[archive] + self.index = sorted(self._files) + + def _adjust_path(self, path): + return path + + def _find(self, path): + path = path[self.prefix_len:] + if path in self._files: + result = True + else: + if path and path[-1] != os.sep: + path = path + os.sep + i = bisect.bisect(self.index, path) + try: + result = self.index[i].startswith(path) + except IndexError: + result = False + if not result: + logger.debug('_find failed: %r %r', path, self.loader.prefix) + else: + logger.debug('_find worked: %r %r', path, self.loader.prefix) + return result + + def get_cache_info(self, resource): + prefix = self.loader.archive + path = resource.path[1 + len(prefix):] + return prefix, path + + def get_bytes(self, resource): + return self.loader.get_data(resource.path) + + def get_stream(self, resource): + return io.BytesIO(self.get_bytes(resource)) + + def get_size(self, resource): + path = resource.path[self.prefix_len:] + return self._files[path][3] + + def get_resources(self, resource): + path = resource.path[self.prefix_len:] + if path and path[-1] != os.sep: + path += os.sep + plen = len(path) + result = set() + i = bisect.bisect(self.index, path) + while i < len(self.index): + if not self.index[i].startswith(path): + break + s = self.index[i][plen:] + result.add(s.split(os.sep, 1)[0]) # only immediate children + i += 1 + return result + + def _is_directory(self, path): + path = path[self.prefix_len:] + if path and path[-1] != os.sep: + path += os.sep + i = bisect.bisect(self.index, path) + try: + result = self.index[i].startswith(path) + except IndexError: + result = False + return result + + +_finder_registry = { + type(None): ResourceFinder, + zipimport.zipimporter: ZipResourceFinder +} + +try: + # In Python 3.6, _frozen_importlib -> _frozen_importlib_external + try: + import _frozen_importlib_external as _fi + except ImportError: + import _frozen_importlib as _fi + _finder_registry[_fi.SourceFileLoader] = ResourceFinder + _finder_registry[_fi.FileFinder] = ResourceFinder + # See issue #146 + _finder_registry[_fi.SourcelessFileLoader] = ResourceFinder + del _fi +except (ImportError, AttributeError): + pass + + +def register_finder(loader, finder_maker): + _finder_registry[type(loader)] = finder_maker + + +_finder_cache = {} + + +def finder(package): + """ + Return a resource finder for a package. + :param package: The name of the package. + :return: A :class:`ResourceFinder` instance for the package. + """ + if package in _finder_cache: + result = _finder_cache[package] + else: + if package not in sys.modules: + __import__(package) + module = sys.modules[package] + path = getattr(module, '__path__', None) + if path is None: + raise DistlibException('You cannot get a finder for a module, ' + 'only for a package') + loader = getattr(module, '__loader__', None) + finder_maker = _finder_registry.get(type(loader)) + if finder_maker is None: + raise DistlibException('Unable to locate finder for %r' % package) + result = finder_maker(module) + _finder_cache[package] = result + return result + + +_dummy_module = types.ModuleType(str('__dummy__')) + + +def finder_for_path(path): + """ + Return a resource finder for a path, which should represent a container. + + :param path: The path. + :return: A :class:`ResourceFinder` instance for the path. + """ + result = None + # calls any path hooks, gets importer into cache + pkgutil.get_importer(path) + loader = sys.path_importer_cache.get(path) + finder = _finder_registry.get(type(loader)) + if finder: + module = _dummy_module + module.__file__ = os.path.join(path, '') + module.__loader__ = loader + result = finder(module) + return result diff --git a/venv/Lib/site-packages/pip/_vendor/distlib/scripts.py b/venv/Lib/site-packages/pip/_vendor/distlib/scripts.py new file mode 100644 index 0000000..913912c --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/distlib/scripts.py @@ -0,0 +1,429 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2013-2015 Vinay Sajip. +# Licensed to the Python Software Foundation under a contributor agreement. +# See LICENSE.txt and CONTRIBUTORS.txt. +# +from io import BytesIO +import logging +import os +import re +import struct +import sys + +from .compat import sysconfig, detect_encoding, ZipFile +from .resources import finder +from .util import (FileOperator, get_export_entry, convert_path, + get_executable, get_platform, in_venv) + +logger = logging.getLogger(__name__) + +_DEFAULT_MANIFEST = ''' + + + + + + + + + + + + +'''.strip() + +# check if Python is called on the first line with this expression +FIRST_LINE_RE = re.compile(b'^#!.*pythonw?[0-9.]*([ \t].*)?$') +SCRIPT_TEMPLATE = r'''# -*- coding: utf-8 -*- +import re +import sys +from %(module)s import %(import_name)s +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(%(func)s()) +''' + + +def enquote_executable(executable): + if ' ' in executable: + # make sure we quote only the executable in case of env + # for example /usr/bin/env "/dir with spaces/bin/jython" + # instead of "/usr/bin/env /dir with spaces/bin/jython" + # otherwise whole + if executable.startswith('/usr/bin/env '): + env, _executable = executable.split(' ', 1) + if ' ' in _executable and not _executable.startswith('"'): + executable = '%s "%s"' % (env, _executable) + else: + if not executable.startswith('"'): + executable = '"%s"' % executable + return executable + +# Keep the old name around (for now), as there is at least one project using it! +_enquote_executable = enquote_executable + +class ScriptMaker(object): + """ + A class to copy or create scripts from source scripts or callable + specifications. + """ + script_template = SCRIPT_TEMPLATE + + executable = None # for shebangs + + def __init__(self, source_dir, target_dir, add_launchers=True, + dry_run=False, fileop=None): + self.source_dir = source_dir + self.target_dir = target_dir + self.add_launchers = add_launchers + self.force = False + self.clobber = False + # It only makes sense to set mode bits on POSIX. + self.set_mode = (os.name == 'posix') or (os.name == 'java' and + os._name == 'posix') + self.variants = set(('', 'X.Y')) + self._fileop = fileop or FileOperator(dry_run) + + self._is_nt = os.name == 'nt' or ( + os.name == 'java' and os._name == 'nt') + self.version_info = sys.version_info + + def _get_alternate_executable(self, executable, options): + if options.get('gui', False) and self._is_nt: # pragma: no cover + dn, fn = os.path.split(executable) + fn = fn.replace('python', 'pythonw') + executable = os.path.join(dn, fn) + return executable + + if sys.platform.startswith('java'): # pragma: no cover + def _is_shell(self, executable): + """ + Determine if the specified executable is a script + (contains a #! line) + """ + try: + with open(executable) as fp: + return fp.read(2) == '#!' + except (OSError, IOError): + logger.warning('Failed to open %s', executable) + return False + + def _fix_jython_executable(self, executable): + if self._is_shell(executable): + # Workaround for Jython is not needed on Linux systems. + import java + + if java.lang.System.getProperty('os.name') == 'Linux': + return executable + elif executable.lower().endswith('jython.exe'): + # Use wrapper exe for Jython on Windows + return executable + return '/usr/bin/env %s' % executable + + def _build_shebang(self, executable, post_interp): + """ + Build a shebang line. In the simple case (on Windows, or a shebang line + which is not too long or contains spaces) use a simple formulation for + the shebang. Otherwise, use /bin/sh as the executable, with a contrived + shebang which allows the script to run either under Python or sh, using + suitable quoting. Thanks to Harald Nordgren for his input. + + See also: http://www.in-ulm.de/~mascheck/various/shebang/#length + https://hg.mozilla.org/mozilla-central/file/tip/mach + """ + if os.name != 'posix': + simple_shebang = True + else: + # Add 3 for '#!' prefix and newline suffix. + shebang_length = len(executable) + len(post_interp) + 3 + if sys.platform == 'darwin': + max_shebang_length = 512 + else: + max_shebang_length = 127 + simple_shebang = ((b' ' not in executable) and + (shebang_length <= max_shebang_length)) + + if simple_shebang: + result = b'#!' + executable + post_interp + b'\n' + else: + result = b'#!/bin/sh\n' + result += b"'''exec' " + executable + post_interp + b' "$0" "$@"\n' + result += b"' '''" + return result + + def _get_shebang(self, encoding, post_interp=b'', options=None): + enquote = True + if self.executable: + executable = self.executable + enquote = False # assume this will be taken care of + elif not sysconfig.is_python_build(): + executable = get_executable() + elif in_venv(): # pragma: no cover + executable = os.path.join(sysconfig.get_path('scripts'), + 'python%s' % sysconfig.get_config_var('EXE')) + else: # pragma: no cover + executable = os.path.join( + sysconfig.get_config_var('BINDIR'), + 'python%s%s' % (sysconfig.get_config_var('VERSION'), + sysconfig.get_config_var('EXE'))) + if not os.path.isfile(executable): + # for Python builds from source on Windows, no Python executables with + # a version suffix are created, so we use python.exe + executable = os.path.join(sysconfig.get_config_var('BINDIR'), + 'python%s' % (sysconfig.get_config_var('EXE'))) + if options: + executable = self._get_alternate_executable(executable, options) + + if sys.platform.startswith('java'): # pragma: no cover + executable = self._fix_jython_executable(executable) + + # Normalise case for Windows - COMMENTED OUT + # executable = os.path.normcase(executable) + # N.B. The normalising operation above has been commented out: See + # issue #124. Although paths in Windows are generally case-insensitive, + # they aren't always. For example, a path containing a ẞ (which is a + # LATIN CAPITAL LETTER SHARP S - U+1E9E) is normcased to ß (which is a + # LATIN SMALL LETTER SHARP S' - U+00DF). The two are not considered by + # Windows as equivalent in path names. + + # If the user didn't specify an executable, it may be necessary to + # cater for executable paths with spaces (not uncommon on Windows) + if enquote: + executable = enquote_executable(executable) + # Issue #51: don't use fsencode, since we later try to + # check that the shebang is decodable using utf-8. + executable = executable.encode('utf-8') + # in case of IronPython, play safe and enable frames support + if (sys.platform == 'cli' and '-X:Frames' not in post_interp + and '-X:FullFrames' not in post_interp): # pragma: no cover + post_interp += b' -X:Frames' + shebang = self._build_shebang(executable, post_interp) + # Python parser starts to read a script using UTF-8 until + # it gets a #coding:xxx cookie. The shebang has to be the + # first line of a file, the #coding:xxx cookie cannot be + # written before. So the shebang has to be decodable from + # UTF-8. + try: + shebang.decode('utf-8') + except UnicodeDecodeError: # pragma: no cover + raise ValueError( + 'The shebang (%r) is not decodable from utf-8' % shebang) + # If the script is encoded to a custom encoding (use a + # #coding:xxx cookie), the shebang has to be decodable from + # the script encoding too. + if encoding != 'utf-8': + try: + shebang.decode(encoding) + except UnicodeDecodeError: # pragma: no cover + raise ValueError( + 'The shebang (%r) is not decodable ' + 'from the script encoding (%r)' % (shebang, encoding)) + return shebang + + def _get_script_text(self, entry): + return self.script_template % dict(module=entry.prefix, + import_name=entry.suffix.split('.')[0], + func=entry.suffix) + + manifest = _DEFAULT_MANIFEST + + def get_manifest(self, exename): + base = os.path.basename(exename) + return self.manifest % base + + def _write_script(self, names, shebang, script_bytes, filenames, ext): + use_launcher = self.add_launchers and self._is_nt + linesep = os.linesep.encode('utf-8') + if not shebang.endswith(linesep): + shebang += linesep + if not use_launcher: + script_bytes = shebang + script_bytes + else: # pragma: no cover + if ext == 'py': + launcher = self._get_launcher('t') + else: + launcher = self._get_launcher('w') + stream = BytesIO() + with ZipFile(stream, 'w') as zf: + zf.writestr('__main__.py', script_bytes) + zip_data = stream.getvalue() + script_bytes = launcher + shebang + zip_data + for name in names: + outname = os.path.join(self.target_dir, name) + if use_launcher: # pragma: no cover + n, e = os.path.splitext(outname) + if e.startswith('.py'): + outname = n + outname = '%s.exe' % outname + try: + self._fileop.write_binary_file(outname, script_bytes) + except Exception: + # Failed writing an executable - it might be in use. + logger.warning('Failed to write executable - trying to ' + 'use .deleteme logic') + dfname = '%s.deleteme' % outname + if os.path.exists(dfname): + os.remove(dfname) # Not allowed to fail here + os.rename(outname, dfname) # nor here + self._fileop.write_binary_file(outname, script_bytes) + logger.debug('Able to replace executable using ' + '.deleteme logic') + try: + os.remove(dfname) + except Exception: + pass # still in use - ignore error + else: + if self._is_nt and not outname.endswith('.' + ext): # pragma: no cover + outname = '%s.%s' % (outname, ext) + if os.path.exists(outname) and not self.clobber: + logger.warning('Skipping existing file %s', outname) + continue + self._fileop.write_binary_file(outname, script_bytes) + if self.set_mode: + self._fileop.set_executable_mode([outname]) + filenames.append(outname) + + variant_separator = '-' + + def get_script_filenames(self, name): + result = set() + if '' in self.variants: + result.add(name) + if 'X' in self.variants: + result.add('%s%s' % (name, self.version_info[0])) + if 'X.Y' in self.variants: + result.add('%s%s%s.%s' % (name, self.variant_separator, + self.version_info[0], self.version_info[1])) + return result + + def _make_script(self, entry, filenames, options=None): + post_interp = b'' + if options: + args = options.get('interpreter_args', []) + if args: + args = ' %s' % ' '.join(args) + post_interp = args.encode('utf-8') + shebang = self._get_shebang('utf-8', post_interp, options=options) + script = self._get_script_text(entry).encode('utf-8') + scriptnames = self.get_script_filenames(entry.name) + if options and options.get('gui', False): + ext = 'pyw' + else: + ext = 'py' + self._write_script(scriptnames, shebang, script, filenames, ext) + + def _copy_script(self, script, filenames): + adjust = False + script = os.path.join(self.source_dir, convert_path(script)) + outname = os.path.join(self.target_dir, os.path.basename(script)) + if not self.force and not self._fileop.newer(script, outname): + logger.debug('not copying %s (up-to-date)', script) + return + + # Always open the file, but ignore failures in dry-run mode -- + # that way, we'll get accurate feedback if we can read the + # script. + try: + f = open(script, 'rb') + except IOError: # pragma: no cover + if not self.dry_run: + raise + f = None + else: + first_line = f.readline() + if not first_line: # pragma: no cover + logger.warning('%s is an empty file (skipping)', script) + return + + match = FIRST_LINE_RE.match(first_line.replace(b'\r\n', b'\n')) + if match: + adjust = True + post_interp = match.group(1) or b'' + + if not adjust: + if f: + f.close() + self._fileop.copy_file(script, outname) + if self.set_mode: + self._fileop.set_executable_mode([outname]) + filenames.append(outname) + else: + logger.info('copying and adjusting %s -> %s', script, + self.target_dir) + if not self._fileop.dry_run: + encoding, lines = detect_encoding(f.readline) + f.seek(0) + shebang = self._get_shebang(encoding, post_interp) + if b'pythonw' in first_line: # pragma: no cover + ext = 'pyw' + else: + ext = 'py' + n = os.path.basename(outname) + self._write_script([n], shebang, f.read(), filenames, ext) + if f: + f.close() + + @property + def dry_run(self): + return self._fileop.dry_run + + @dry_run.setter + def dry_run(self, value): + self._fileop.dry_run = value + + if os.name == 'nt' or (os.name == 'java' and os._name == 'nt'): # pragma: no cover + # Executable launcher support. + # Launchers are from https://bitbucket.org/vinay.sajip/simple_launcher/ + + def _get_launcher(self, kind): + if struct.calcsize('P') == 8: # 64-bit + bits = '64' + else: + bits = '32' + platform_suffix = '-arm' if get_platform() == 'win-arm64' else '' + name = '%s%s%s.exe' % (kind, bits, platform_suffix) + # Issue 31: don't hardcode an absolute package name, but + # determine it relative to the current package + distlib_package = __name__.rsplit('.', 1)[0] + resource = finder(distlib_package).find(name) + if not resource: + msg = ('Unable to find resource %s in package %s' % (name, + distlib_package)) + raise ValueError(msg) + return resource.bytes + + # Public API follows + + def make(self, specification, options=None): + """ + Make a script. + + :param specification: The specification, which is either a valid export + entry specification (to make a script from a + callable) or a filename (to make a script by + copying from a source location). + :param options: A dictionary of options controlling script generation. + :return: A list of all absolute pathnames written to. + """ + filenames = [] + entry = get_export_entry(specification) + if entry is None: + self._copy_script(specification, filenames) + else: + self._make_script(entry, filenames, options=options) + return filenames + + def make_multiple(self, specifications, options=None): + """ + Take a list of specifications and make scripts from them, + :param specifications: A list of specifications. + :return: A list of all absolute pathnames written to, + """ + filenames = [] + for specification in specifications: + filenames.extend(self.make(specification, options)) + return filenames diff --git a/venv/Lib/site-packages/pip/_vendor/distlib/t32.exe b/venv/Lib/site-packages/pip/_vendor/distlib/t32.exe new file mode 100644 index 0000000000000000000000000000000000000000..8932a18e4596952373a38c60b81b7116d4ef9ee8 GIT binary patch literal 96768 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 F{{j_Hb~FG0 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_vendor/distlib/t64-arm.exe b/venv/Lib/site-packages/pip/_vendor/distlib/t64-arm.exe new file mode 100644 index 0000000000000000000000000000000000000000..c5df4869da5ee0970ef4f652d967caa80d5ec63d GIT binary patch literal 180736 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�=7K@@+*KjCK2bkM{rnwW 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_vendor/distlib/t64.exe b/venv/Lib/site-packages/pip/_vendor/distlib/t64.exe new file mode 100644 index 0000000000000000000000000000000000000000..325b8057c08cf7113d4fd889991fa5638d443793 GIT binary patch literal 105984 zcmeFadwf*owfH^BWXJ#sdr(FK3XTvIjhE0=O&rh+%*Y;@2r6h)P&62^qEeUtotB*9DH^Zx#M z|9Sc7?EO6ZxvpnD>sf0(YpvAWu-4^vxm*SOZ`&?cD^K}Xt$zRUkHzN^r*9bH`tPCJ z&uGnyZ9ik~;yacHmM**J_GP!+6{x%A?z``a2X4JBuq<(R;EuZk;n~*&?z(5uZRZyk z4=c?!{p(8>-uvE-BPQkkkNbZ(>0Q!CxBPa}7WMqir0=We+DRYs{BYu$SlZ0ZU{1v4TJ-H9t_RLKHb0klz%{`&Jb#$WwV#~-baJ~c z;^|ZG)p_!e_k5SjBR~AhJzYN104>p+5B#bdbCt4nDd{wldq~}Ej=Z`aJ3r4gRlVf7 zelv%cwRx`7hD%27U%qPz11NWspUe7RJ@Z_x&QQO!^!f4IR>t}A;rsl^fMo8n_=Elh zT&{)ZFI#j={1%tXx>!CikV+m0}DYHtETx(sFWQ<}(`v&e7D2l5lFe zt*2t8<$5w)8nAvF097haqD(4GUP@o6r~Lbh@?4f(>~gJ_b+P?xKXSRYb!^-A6@Ah& zeO3(WlbnChXX8Tp+%)pUKK~$n&KT3*=V{qK_2m3gubzyT`mWQB{Q=YSU(=bJd000; zuGkwhyJM;8N42MRMa^!j`DE#~OK)zAk25`{Dz_sP%!_K_m!o!jw2Z>xs-u}*x*0F6 z)XfgvoX?z%O@W&`w)OW@q9<3C2Iht4hUSH?4PB?3`{}njW~O5)&shu-_$<9z9yOJb zinn9Q+bXSv?1_-Mt+|bFMHJC~&~EKIZri#^8Q_{^} zn(dILAB|MBnJ-!C(`61)ZB=RBQw6|3WWE$Nw};IwmZyXzG`H*KF6&*@`W~6;>5OEb z^fF35%=;a!*V)msW4ilD`a3M&laPx7bF1}J&FPm;AqYpB8Qp<_e!rRRH*9u9&6jj@ zhxMb;QhtXtx{}_QAG5o1I5TIS<{s_gc5DAJ=1A|l`CO<~=!f;<?!jGBax;eL5W#I~_?c-=>$4wl3nT4|+}_JK?D@ z-^tWVYpEY8`0ZvM&jUZ}_g`r7*;8^YJ~?dg(5KMom8tnNFoSzu5c> z8EHN-wnFwo=|YzDxuI;lTV=7y-;(jDPE|YBS{XHaWKQqv`l)UD#LeuL@|$lOm}~#O ztk%s}bn}qyPtm?^OmuZZP2@CtN~WL&(iJne>gG%A?r<_D*d8kltQSVc_TNXz7-g7dPhlR|(pk}Mop#8!&9Gqj+|pWBBk37-T^@zQ z(kxiN(Dr{n`&w%}13XU6rDUJXVIGoB`H#{flMhLAG0E?+ILxwpRrVZ66E7{f4tjsB z95A~1KD9oimcr-rKoQ7%=qd1q97S=%+PYcZdeE?}-Z(TNJ}G3rXsze$0h7m2_b*a6 zHOp)J4+!*Coy0c1d2f7p)D3#~rgutPDgTct7-|)MN;h{}bwhKM>X+mqbbIBc-z#ohc-wN4G;S|A#u%u&$Tl#+LkS@ggZc&KaAfo3GV}tImv%(bf%@ ze2{rU(7WQab)m&;W;icz@S+><1J=}1`0Dyl z^6S@b@w8Osx#n0Cff~ng%D-WVTDR=kT@K07Q-(CIo5zLR1@|l;-B48=*BYvZ#fRy3 zyB_RX_F=}&KA=AQLdyR=nvfO$1QJx;aQP^?j-44|%08u$wh)Fh0~m`rdZiPUL^mp|^MY(%X?56z?@a%I66Srb}-TbDtwEL@GWAnVa?IZtdYV7G<>c zt%;m^F8D*2Rmf{aTe^{VRc5y;6MvNigz+3FwZmEqlPvTc%$_6rx!Af$wZT%lGEYCA2!EFg| z2?w-oTlF<^Iz>%z@fqEGnRz7q);eg+JB!NfPpu*&?za|76M$^EbuDkO4b@4n zh>It-!76MCl~8bZVzqVsRH`Ir_;hn^n}9!gvTnAts<&BQJ?K9M2O2-cZ0I7Z+4D5# zNWyDPy+levU_JkNHk+wxhBtnyZqD$TEvi`YBT{Ur6`7*iW(YHUJ*tKL#3)0R$=@=g zB#%SKm;Z^jI&bh8`_Ht+tlv_E+LeLOTu`VQZYFA4&YlRFn`%VZct!>aMvb*@3-mAK zL9o3QE^>AH_v-WR_#48tf`iXmhhZCIAZj2|RW~YenO@ebtvl_~dgDlF*)V=@SW!@K zbOeMP8+|IPPi3_Qgi7o7_IPzY{7|qyxF^0P^L3aNp}zs^BcRABpc2};J=W_2Rbdyh zwT4M8kJQ@6!Ktn5C~FT_!jr~}ge5FDekpJ}rbHGw>a*JjioKY%s}9WvfdIke3O3R1 znE7&*=kiJ*yaE`+zm=Uolg=XYL4+(df9fJ%G&BEL*()=&bwww`_o-POQnP9gaB81a zZyZ*6hgIIjK-AcnAGN#UjJaFJ{7ih4wr-=guDh%Y#FZvttF3v$l&khn)N{xdHxBJv zvC0w0n!9x^atL(4>tdn0-HCwp-gKBihUl^$sOHU-PRvn54`})=o-USNCU%xGEYGr9P1@Dez2r zzBw+>)#1=5)ARO%JlB(=3!ulsR#EU}Ji!hv)}hyRZGg#hB|YsFv5rOBdHMH|<{C-U_c^dS+2L^R5t- zl>f+Sd9FxGcSp^xSjzt~Y!rl3Z}0OMZ=4=A3pVO^cGt$tQF&40unkvk96lcR)Uc0- zbmp@jcGPZ@)}wZJ;%~I4w!Pqu6^y!E4bv80l;?8AJ=XTi6|{H97!XUCz6Gu!OQ&V| zQpL3lLl3^Z>{5XA>gn>nXT{g#IBfm>zpH=e=w;99z3=Poham#b=mS|VD=1^l0=)RPZXqf66S$oI!H z%!+cj1ai|0K%?fi2X7ZifBHVX_ha4Y%U@PI z3j*rX8xOfS30F+fQz)*2?JI`qtp`M0N4(LEeFv<^7@c0WPk7^U81MMmorT-Bu>nrD zUIfM9xa4rsI$eMNyDUqmF9V_(z_STUSHlu*w{909!ej+aR?uVx zO;#{Ls&D_ys-zY=x!dCpKO9fxY)_^Yln&zIwS=K@r%IqQV0lb|<_EySf%&GfC38tHWEp1?}Wraqt z&M-aE-cMt}u6xhcjpKIQhhDQ{x2QGSWIauhq2j+DRIqQw!%;N&+875m7Q2>Euh}v6_ zQ4~aE4=E6kV`XYZY$7`PLwdh|+tTbtT9zdzup0iBit&M7P)`jaSP_ z3rR#oj+u*KXOuvo^q~k@uwpfwZ{|iF{g+iOFm%xWEBJQB{!JFny@%#=ynBhYi~(k` z-S#WqJ^eZZmohmyD3)4;68j7pf6vU4YOVR(6p$6GpX;pHIY!^{_$0k-aK8ub9ZgjJ*tc2a7-yD^hjQOynvV#x|Tvc(<@geCds;wl~(*P3J4(C(^^jI zsJp1GCsf%GKiS&C0JCGgM#j3sX2YH%Bl#1vF!$7$LMXC2!=2VvhL;m5>R6JsQu3gX zFcB#xBU&k;q8?a!l}rJ@CzSt{`e0W=1g1!<92}&U`#70=XCdyd>(0xkwc z;~<+`S{^prZU4*{fLk{R;?dUeL0i|Zt=l?LxIGcK6z>_S*jr=nLWl#85~HopV3o2H zdWctu-1h~vFq>}+n|EQ~S8* z9?>P%gn=pj5e*|`F?|C-v@W@t#Qk15cONJ)>b!_;=nBz+=UKPkBMU&22V~kH>Y<2-KO0uKekpeGzakM8`wHM8}qcLKk`vVm?*6HApI*6 zW%v7P%>6ayr|$c`(e~q>knzsxv&@16HFthc8|n#r=xtSQ7WvjM7r0!(Es2RrgxjgR zyK;l*RD)<=_Hplw5?26nFasntUu5>yUDSahw!8@aQQUH{Z^g)-871EMa48I%VD`n` z=KZDcY-d;Jxvrph)pJ2S-|j5yO@%LHD-EbNMXw3H5K2HM5Q#3-n3t4aV}ouymjtN=LnYX zXv3lq)+qL0zo&GoAUeo+`+@o{0z1A7Arjr4S zxR3vLMH|r+*_Yirv@^1Ym(`iV8L5KOWCUG8jUF>2?8Ta0(AALrf^bPa@%bQC)UMgH z5_vqbtEEJKWi^tKU71mOYThnnu*Mlo8uD|7e3Y^UEhQOW_T!@L#{$T*R<&SH{q*Gg z`s3Q89jO_|<(gy;7lMey%O`Uo$i?7Wxy!&TYzE&isG|fmRMbpIg(}I783&2h^s$<9 zTf#3}eTlD zyXdE&^IY7Bl1bFC*41*@^&L+vwVJ49R8G*Eze_{by`+*Q=>~cK2Jf`>)_h?cxNv4i ztM*vtFSI9O5>#Tz&BvwHvBK}Lnv#CZEp$eM0w>_Ie#9_9#T?HEW$K4FEUq$=D4N5N5S!L82dh|_#jCcqc0CN%Xm@x9)k@6>3?3u_{|$jB29bm8x}I&IvP&i zSdtkV>gmXfkK)%G9}&_vyftiDVdsoe5pt!{^++LMvr}<84_~iv3f1W5R76dzTqed8 z&@Vf?$Kg}ims~#$Y|fCmM+SVNdTr;3eo)QlRYrdvnvh|}k-WIaIFg_EyVdkD`xU*j z@bNpX4`tKtk+*__yuqu^|B}9eSI(}&nD)#xD6MXetK*R4>RM|uKnme*D)g#xmy#Jz zSV!(4E9seY1~U4(#X`C68*06KySyZ@lo)rG)Ma3^Wb0in*GB)rN5$L>2aV$u)}xXR zcHTQiH;307Q}3IW&>ZQ*`lw!-i4Q@-@@97GrkmS^mH9bV2pwFfU~-74S4LT9(_B`OGM-lxgn`S8n$JsBSX+V8DXObj z@+@bB`Dg%9+WHk&h(3sOL9V8)-NO~L^3^P0RtFHNK#$cepdBGR!%$%=#;#vU z@_CeX38k|8x0B%x@624@6Dl#{mskrgl11NY_F20HVb~g%!W07p+rb$R&14|RvnI>P zhgp-~mu*}(*=5v~xSSJ4sV|g%i8JQJvx~}uj;~SHU+6qLj>~w3PM^s*s^de9TS{D+ z1J*Y_%${Tya$-0q*+*n$*eJ3o9F%hI50vFbYt0RE(dPLHx5{YE_hu^fI!`wVh~u~A z;cjoN6tl#{TkD5|2=!HZNn%gMUZb^%H6C&A(5grJc+np2VCdD>Xe3BhWr8s+fMO#b zz0r9WpszcPB38$_InCYBvq>&FD_8V0lw49YUy4FBUDhN0MPHjtvilwo#H!;ndvMr# z^bRiT42szPtNbyR6U3q|I++vxZ96n`9}b)>_D5 zK#M|FY&)4T({t%WG>S>jWju7#AK+mYpTe&-?OlPXoH0-esjx^IUcpahwAp8@Dy>G* zP4@NVY_sm+cdfI)I)E={fuYlrtvi_w>B;GP*>FM^VO6+wZDCjd{re1``+S*~=~*S( zA^NKoJ|D(=p~#B0)(dSiQ@NL+&pEDmNar51lKM0dMuy@O)@`Wwo#P|rnM$Mb9*9vN z@ro8jY*@(VGiWO_K{uO9)c}$nuk@M9CXF`8rsrX)ZhAgct$1!0MIYtYN`FbuLUKDj z7m+!%z}432Dd!F1Diw;6^QGIxybsO3FSY#_b&F#3G0HhBFam(co$o2+1A&{j%F5=E zFs6NrLU6}Uxp!G$+h5Yft)g@Vp|SnDN$HK7WbE*M%0}=;Z!~#lNi?}UAohZT^&-_Z z=6&88bBY-%h?@6R)|BjTs75 zd;pVHQ`Y%-AResPT{Ze%6sEJiW{A19Eh{whc-&iLBX+m@f}@w0WZpppcek0bP9N;s z5OYaqQN|sH#{+JdTm&y(K2Nu~seG$IcfW4VKtpt3S(O8|Myaew& z8lP+gT`+;*;!2piKj(#*jvfZGHSW%ky(>5LW&fjKkTpvao3uNtVM7PoqzUBtY6yBzZj zt*L`tc;2Q@fj`$e#-VFg-xvQzsBEX!^ekCMdU$-M-5tNwNSDOVGSb81V~j%uiSI^) zPyROwM9f{rPG9=BQhmcmg=xXQ>Yh&26oO&K&g%3URccRW71{ZTdyV&w8}A-9cIImv zJ}k^ErJ=;FG!hzaXX=df-1uxGJt97pF3*v^M;nKRXw756k={;M8+-2}dKrNmG_cjm ze@9f(YBh&3jFU1~awl+}D#DgfMP7fqzle__BQs?bnV^akW{dn)715f9Ih~E5nD2z4 zgsUpFX2&uVy<-Fk-|S?kiiubQ3vC(8oq4>B+ROHQb_yFBa+pk%BqOJVlL>B`6O3gu z4*)_JLLfGg$H=vTrH!tX2}TVAm@H7n2h{S;yRY*BItr(Hb*txambjK8iI zvO7Txm5r$fTybnj3l8*Dml%n8z11bI2G%x~nt9CV^R4iuX8WvFYZRl)jA8Bd$y-4J>fJ_DNma z|MW&VrN`+~#60bYuu;N>k89+GS&6a*{>sPCM0tVHnsu7(oFEOb5OQw}n5!LiWA!tS(So1 zE(KxYdNR^r`+wUm2e8>^`~QVE=|H#r4ZN~CK2#S)#t|C^X{)v9c0QXanY>=H&6@Xj z7Ay6$Qh^Sd0nVZ2N-Hq`X1Nc6*Kx?_hS8kXp_HCy{fvFYy0>wHOP*i|j1YHe!|7}= z{dN{Xai|>5AjlPCunsd{jtWbA5dMhrVRLKlE@!)d>x`JNG%@Zt0yby2TH+<5QFhGV z;J^As>VS0<15r9kc;ZE+0nUYfabyLb7?#M{*!A4v#^j<6y<#|3?F|l#m)UJm_b#LF zyk!Sdp%09{kt>F@BLBEL8r#EEY(+E6l_3K2Ghv-iy}TQ?3WQ_)|ByS(Xq;P&@a@&pzIvD6$N3l?NZ zp(JOJqmu>1gZ>S&H)`C!hc&IKXshAcSuBZS!dF=W>} zm2-crw9+SA-*$2qO3n(!2-u!~ADQPuX9!d2O4P+tlfE{ZiP!Z-jj2ani86JcWDPkJ zv`iKp6`+^ssTl!fvyyZx&!gmw(&P+pW=zy9Ix1=nA4mEOuRQeREYNRwx?BYy>`$rH3=qvT)yaqP?+Nim!#{5|BMdq*q@vym%$9yH6 z$dU+wS<3&l*0fh`+gio(gY?X9ZxtoSxz?RzWW~rn`bAG4u3YeVe7J5#9y1>6VjYg5 zcS(;QCZsmfAlE=!QN>RVnFqrxdv(M-9Kxz3Iqy%X<3G@v-W&?t%muBA`g5HJI}}b` z-z7443=)GzqUC9dAdGLW50!P)b8F`3&@bKTA4 zPYLa*QTgqM3+Q)=`Hb*Rr+PU)&=XFiNqO$brqO1rbba}+1VkiU&I81 z?b`Rej8khW1;SYFXiZzdCZlhL)}*VKh}QJq>SdpcRim#~Yr31dT$aNz z_1&U1{ZM_c)0&`DE~R*nnnR+-7EX8}Kfo`jo7^UFP<`#`^JoK&+S|jImuOFm_dqR` zTt6<`_-tR;>`Tiw2y0JQ3Z!e(Nm6K=?kEN!*wMEvg$EQxNMGizQ12%3cuKe^mS zquOS$Zr$DzvOD<=2klj_h#pUkI*iTcQmy%32!5z%Q?=FEmKgBep^p1*cDP8r>_A5osky#Rv&R^)^lcI7O;&Ylp^NG&9;`jnzai( z4OXDH1#anw)mq-BeRni^UDi6elezFTW*Cu2Q8Qn^3pY4k0P-(>VH z*P2#ww5?BMKfNgBRyv914!)#9f6PQ!{M^K46@D>XR9 zw8n9(x4IetV)H(fCwM<(S>eBl$embe?NOe^Y=DWAFfbd&0&kLUG zsb*^YQ3jGjQj}#p*1a~0<5&z8|G3gEMheq zdI-$V-w-AHmn@_`bxg18p;nvipD3)N>=0&JZq~G5lFpm3g>BdeAV~>+!w!YaqmA#e zQm*)^5m4+D8f~Ca+y5py0onVI7JHY%d^Lx$*+SQ-LVp`vNYR1n%3#8)7DuFg$kH?5 zkw6d9BqZ#4aEay3i)*cD!5|CVWu)JBGV|jnw+3>Vsg-XqLOnB-DeEdbOf&Oi=91Et zk+R-!Suf2LB~DUz&t?}YW^v}2I-OCQiPr3mG#JkZx&9Gzr{#R466U4+79{+t(0W<7 zZ0+MAIZ-ixtxa%x*$>{Ln@2(>(o$rtLv3QEi?Y;*J0*LEwSBSLB(XXRE2l|HTOn88 ziyWKU6*L!hA7kdtJ*zjUk!Q|U4{q!kQ8iZ3u+%7@82d{A%Ngc2s!>OP*4(plf{ZnO znln~`PIjzUQz{Erv1FMOdQv_zR0m}uPyo1S>$&I9OoB9WGH@t6rP5`5l_S^ai^k^| zeT(BW)-R!UusvR)4r;U+TJsoHXv6;DX^l6m^1bR?VuT#tvcyH{o;=zyw)xT@@WNS> z-X|GClIlZ7m=in6vCR)-*R$pCnpsOI0?CJ=gq4%&EZXs%q41p)Y>rl?KzTb?YyiXle*=qMEIKn>J4G5)pn zvWHl;iR*=P;ANCT=U}_DQa8}3H-q)xwt`HQ-@MEWS%kvOR1*1_iIj=SDV z%a0y0-;`;{du`?7OtG9c*L5=vc|_kVp77OiZnQL zr;x9om6nU_*|wLczmTEMRbRtfIfu=lMfp}!-;@?03_B3Ih}*?(bRhz{o&(|(Gy;fkZD+-dy| z0gueB!pZ%m(_O@bA43aw{$5LR;y`mW{ z5Y7ul#jAhjj!gE098*(y%5?-5X)SqJ7ufB=j%A;%371~G1(qxzhMd=C&eoo|E-$P- z(H0JFTyaXMj1#Esid3vX+(7gG60m+!N*5TquPJP5OFU;@UW620sg_#AmU8p*0>pdX zILexrLYI_QTx8QQ6u$c#?94@_)h>#e*A|giiF#!zLRGmGm@HHjL%)uSZnCg{g?xXZ zc(X8%C)Nllo0M#&yQsv$xHLxpl+?>!jHMoxk?5%_$HmIFgnHb0@u3YveQUzQ-pY(1 znIHEx3=M?VguQRIGzzdXgYHI$;(PU75=SH?JHA9DWf>RR@f|F)O?@lbRmL z6mdB}X2l3v0eL^y1}b;}{oFE)S5s)2mNo-~3aKJG{_1*Z#| zpL)O^4*!tyw0V7_2wk`3QNFS{Mr-25qH|pM`zL{4R zG^T$8?U!qcg7~RM8gELj5eg7## z)l(1ppmgg+5QEGqOU$Zqt5LFQ&8?i!qJqH4P`2E_#1;kwrgQJ&XWWv{K>YSM3;ssK zuGy*ZIX;{qLX{=)DV5jf#n08A7^yuG$_wsVF$R+GwQ->}?vVTWkT*|qYuwwgECTlJ z`IQ&~!tHo#+^bq2e7L-d(xTOlQOkf z*^7Xi!TM&UR-Ni~_AG0WPc$fQD8d zhHpq0glZ5Xek=L9`9o))c7;eV3CsM?#lg zP@EG@l@$$cll|Y#5Rz&L2W)rGx4S5uuQea$(c^iNqb1L|V0}tx3_$p-L~h4t6eK;r z2HVXU-lXT}>ZK^@`LVpbgc)SPzuPwaNx(Slc>q({XS8+USw0+ooAi~}BfV_Qyh)4& zzBe8goPXeCimVBbIc<7NQ{K{_nZbT zJ79ZdO2t0johdyi3zHmYAC!-7#vB?A8kb=`mpBtRtou+3zKYzA{Bt#BE&uyDty;!Y z0q{N&|4K&@9se@ZW~C!Hrp*(bQDW430B&1D!TV0nWn_^l=d9?557@Z7HTuXA7Rjxs zX=C8TWXXxi^1;bes5aCp=*SJ%*M)9Z%{d^-KA+gp&>RZlm3_(|0mr2NthRvovtWSK zSW9CE?1qIrFfT&m_9NO7SBnGTJdTh4krj{z9Q{MfrE_D;rE`OG(t}6$Lx8PD#|4ub zofP3tR)z;%b%vMCbH;~*s58EBUW*J6J77hx*)=(PFG@^SUohrri{FRh@u%P=2EXyU zbkoRz^%kSjm6)%arUTgS_$fveF1Xf;EwZ^xX~9|!=fS%(pZ*f_29Q9ZCBV)nc@eA}M z8|)eDd=MQ6v^d^r&shIKB4k`5zRoGnB5*Sn+yyzggl!wxneZ`>MY1jI@%oZhy z@(67%zV!eHP)R>8Gs60t`u<285Xh9R7xvs*GfEhmlqq@KYzm)iUCUmh8K=MK7Q%@Qy%T)8X{tVB*)~T_Ky3Qgp*8%$p zHE!GQ{VjC5_!3%>i^0RBfEW8GLENmo4PA1iOoEm>nehs|?G$*o z1FWR&e?{^P;)EpKIA)i2C}s)%WrHfKZe+7kQ+A!d=`4_R=uPQ9YYKSVzbuLdoeiJ{ zm|VFaF{71&ZysyYMp@lix|4dsN!2>3$DPz-C-oC2wbV&{*Ga8(QV*(>*`NR_&EDl? zJSG__&r477P`vLv@}E}c+D>a6KxLIoStX^FleSKi^KvwG42#?x(>%mFjf!hIu`PID zXH8xksjBBzF># zx;dsg3s>16))Gxv$@oGj;h)v=%=ir_zo&){#5P=4%e$VEE-N%#Ml1^-pJEo53DuA_ zKKN_Z!gz!kPQM~Ky8J!lW!Jb>>ax&VVMY3Pu(L0G$^j*3ISM{#`+}W}k&` z2?JlS&$xe-D{+>#ZXUAH)A%Kh5kKpVfrba5O`Kgd2eO<#j>eg#+PWH_5`^(RUOq`l zi`Gd<4WQ2u!fE+3)1(BuM~JKTM1ePRt~m>v_(&k6=BeWJ5FQEnIE=`651R?jhl+8c zn?%0YsX%ryTYip;59PpCoa%a+IywyT5WW2~frbb&kH|>RRi7 zAz%F3FBJ_@y8HAFR%+We=Y8V{dC#unZ6dpKe@;BC5o&8}wJv&HvbI{+szYk4b$Ryr zin_Jms(MU|jq)}eW0#-z1tNvj8bi*Pv320a|N62I22+QD;w-3yqjW_obV6X>Ba?QS_6&6lCtsp2}`t)I_Sxa5_|Uo9EM*8nKuBMH1x#hpB?2LTRU z-9Y-22>3D31pG4m#VLG)Ym?RhcOd9zxeTDmaPO$<0IG_ zI9fe;eA!a#7JSt7s=`Em=3U9SnUmc1`&9isR#-kJ3+?A2M`c7H)F`+^9N3eLr#JqG4h^f)9`Yx*z`Me>zy>!CY^)Pgc1ph?Cz$pFENjcGgfDO{S*herD- zBi5RPoa(9b-a(HL`s*mSh+&>b{wN)8mmora-$fUA;%UvJD2T%0Ln)|YDb*)0Oapmr z(ro{TN6AGy_a6P6Lknlpf)k4HXEeap_YYXX2-*d#%2xrRIQ2ev5uFKC`ljAHQ!+M^ zK@)p{T4+53VtBF0U*Wx@Wt+LYB<3MkC)PHY;V)}<-(K3K`dX?hmx1lp7*#Y8!hb!R zQ|RPy;Q3FJZd!dX=FHf7x1K9@_y(3TXSCxCH!012J~KWz(tv2? z8i(I(6HQ;Zw0h0(P>Z*|svn#)zvNkU0T5sTRZ0nD3oQ^ zT$HWmPKf|0;IsV&KwLM!t588i{ZfuQF_;o$aSW#J#9(T9W!9C-;lbcB6-2F@001}= zAMGS(JMb81O#8!YUPH8@f%1u**F!7H7edk2Iuxq84*ju zQOF_0OQCaA5AfMp+NX5Z1Q>MO%0ck8&LYdSBEW1zE$P%Zx>%3#tUq?O@CCG-@QT*v zPT37f&mu1?=5evv&F#tJOC=TDwLHS+BH+~(y>@-)blWv7oLuJS?E=@ZEz_q+YG$}) z*$g(*B&lF*tR>(=uhWb~>Dp`-e~R9YJM(zytyJeB`T}Y3ohL%0|g9=P5&>**HbMrTIiiNA z%8|k-cG&*w)F^(Q9YwPoHRdOb;?q#@Q&9~3!%<{;!9jOo%8!<%5W{>9jrT>dN#p@# z+KC_dHtWtW4#w9%m}h<@Aju7;4}GvRn9oAN&k|3{U|0>Yz;c$PT9{xb%-8^rCju`a zY*VxItea8eu1($S=8O*n$9b^Ve&9B}?h|Oy%VPSg45?|W=zwzm@>#QRk&;7Wh}{WW zR%#p>wQ355{~(1a8C@ zW71z|uUWUV4cYS^=zS(2{@c|I0)O-F?F9SzW54r)V`kSn4{lBug@Vs zt>ya#^4%=jr81QSixdRd(yA6d?yMCEK@?x{L|-Ti2Hz^4=&Epf7}W-^Uv}O? zdr%?IeG}r-Q?WN{9yL~b^Acz3bz2;oxJAb-08#&IpRkgtqAooNYd`4+>M%Hy`(LBe zXB;VA)vZo%XTj9!F$f38=M#gfLx*oQN;g3vGkXW0>k?EkC z!lMCt0P29u%C^&UgH(2Rvq`#8uYLN@q*!f7XY0U79LNKD-OFN0LYvcW&hSi(wqE5J z;{Mc%6BN?ndo~bH2ooON4R3W`9t}s0RmZ@^0>XOTw|+9!tRo@}IRs6!?%qAf8lYAg zv{|r}qPE%UR85?hJ(>QCfk6aE3s&FrC)D#_8>ripDUK%RA9H1fSabPA?c!28xBX{Q zDPw%uqKL9U%~L_2$#JtkXP-b~FSO-#(b;~+i6>lCN*`%WBgiBWdVOF+0;{&~e*so1 zhU@<(7D1_py66V|);FHbT~%1UyVOlv=HC851Q1^*zyL>~y*d_rgV1@L4BE_gIE!7K zCq^kC9zlNqf(ilQ=Db7l&iEWlxP1c3#nx6D7&{$Iou_=Q*n954Z6mQ3YzOMNB;#RiGK}+KDQ#cyLsK zg>oW__-lzRra1O5vCbEONmK!0D6IggWJ%^hYcwzLXj5ruAfy0|aT|e6g5!ITYfSi> zE#cE`fHDwK;6)5*Xg5(|ZR0IWM1iw0gPgpjP?Z{IJwa}NK!M+>#3?d@i=>_tP@sD7 ziRVPdD2EoYl`8w4A0|5<57sXj1N2J#92_}0BJ;;1uA3MDeW4y#LCkzMPTbyVZ%y4C ztd?T#X9-smoA_+Bt^?xeQ=va}ukN1Z?FqTHcoEmCZbEwLkHp+vv5IGi$>|&y=lvcc z$QUN$aL73L@T`>twH)H5B$mN6Qk@9VI#}90=3(<=oXsBOOxh)T@M7jG5u6q)_f=r4 z^mY>0Dqy}8HoJsBdHQ=SIHU(y3_3!U-T=Xjdxw({9rEyC5_wkQzHD6f;U@s$3;zcB zM;QBY+!<9W&O6>3{uBe(?Z%Dow;W5j#y4FDYEnN%MQ?|; zxFt7nfbe^z5<$`nJbZN3Z;P|IguC4UAx9m8U~-xDigjG%rCB9<-GQF=hoE>*p~viW z4W$cpWFuaQ%+u3e9WSz*oGpgK4xceiQ9w5IR_i~Oai9~fh2FKM z6wPyBz-17o25YN4Ix%OI+FiI+G=K2mm@pQZJFFkpQK~O z<^{{6@|L{JDWcitFe5w>Ma|9DsjBPXF|BzsCAB9++r}DzfJ+8&!@2ixmVVHBqsK7% zyvwf9p4c5-pO^hd@Umygu3k1??|s>LqcA=sR@Sa3eFVQDHdWNvcUiPOJtR@(BnnBm z<0I?q>({Q8i!Y)#N{q!%#SVE`%Sf>a;&!#CLp#0NC58AeO02xoT(0HiQa*VVr{PsT z>Q(dH!~grJ&%@$>l!sUKCH7=~koCvWI!5YR2Q~O{s_?Q$QmPV9OA-gyjreKO#M@qFCSngjtJuhyDH%lUXdhksXq$RcU( z28h;?$E$-{h1RO2atolFArxlZVDGfVVXI*j=QKAe@-v%EN)J-r#deud4^)$$wOf}Z0@J(}?d?`V&4 z0Kq%$tro%_w%Z=#T|zZ|_fX(&RgYS)CPcppc(xP-EeN9bquy`!xk(J~z@RUOE| zk-nMFVe>ul$i0-;$FbMANLq(RJ{w-MWJ)DEM9M|-KM3u@$o{GA;g-7=V&XFjJRWX# z^zM2*FaEgk*72BmFtae5e&pFqD2Uzu^gR%aCWv6n3CMb?)r*NlHeyJT8Ust^O7DXu zf!n}rTw-JGL}XxEMNBJZ?wMsasVPBr%d2w60o|p$24$^K&1mbBWX$N1ZVPb({)^s48_X$t??(<*#Cr2s<}LY4C0T=@4ka z{1#xW*Ufts&!(1Dyi+K+OZ(0@c|}E<_Z?UP_nUOuC#x%yZqS-8u&CU7BwDu#1y7CnVbr}vPev>itbnMfsF3BZQWQl~$7)UQ%ljpp z;>F6a6a`Uw8#(ZAmTq@(Gq8MgG!@B{0AslBY|hU-$i+bV*A!u9YDh9O*t}Yqn&a?E zBiT6yTh!?>%=WKmN#M`ws~&hYehc$D``flXcv5 zEQIQITld`oRz=>9nRm?zmA&??g=uY#xkb3rirwlj8Av31^t#8IgdXe@Hk$kYW-4`A zjSO0b`wWN^?BH4!q4cgM+rAdWY&j*o8nv+yOAgJ1@qFvuYi{eVOEX{VvYqd`J)NG#85sLr2m6% z1vmfBGY73KZtih#6Nn=lZqCml=g*lTa~)y(Ph;Y8eey#JfS?X@0}eGApGVT5nq7U> zygfwq=1*~~i9n^CeITg1Ci3#2WL0iOTjrKul8Ffx`}*rA@Uc2Mb1_S$cW#uk00QW? zcH9nb2>|JR2)(PGPRSJI@(wRHNx9}-_E}7^U##$AmIAe+is{R-g2RS2+O||_OdN=(Yzf-H$GtolyF@@E{f@ND8W z%Q!$boxgrC5N_A;7k9X@jjEE2#+vO^%DBzYX@HY!p3mzAqv9Zc0BtUT_LT4RwN4`s zP%{?>Y$)%HYO1iIC+QfJ6G)a*=|#&sl^NqvFJWEfZ+}Qsv(0+&$nqj~wy}P#ah8Qr zbIaLWtG`W``a@|sxXxA7E+NSL9f1xWa@X421!WNJx$==-D%{s%G!+ewlQeX05r(Wh zYWw}8W2ENu|6FU_FVO1DZ_D{dKPGly=UTJK$TGisp3eD4KO$x)k+p;Tqc_06ilUMj zmesH=^Hw8gH2)SrDOptpoAUd1PzKH8WEj2p#8_P$1<$3RSSlO)ka-SyYVK^St#LPX z%K@K}$hs66N|8`cHPK?vmfGW`_81j&cB2HERX0BpZ1xB3iY=H<#MpDKA28PJu+QMt zaqB*D*dgNox*4{3ipi~+;6Z0(4SUY<>{h-(S>JAaO9@yb93igVp(kB{otsdB-D2_R z{vBWBf@t5=+7%~7wWl_*yT0q)cM_p+zu?NvrymS+AwxKh+zTB??yDGxIBtM+qV!CMM&Basd&^n;oI7?%YpNuvoVZ_L9gIGlxaCgJ=);M7 zoO-z?9#; z55^)RP*6-R@eDifPo5P zozk;8FxVYhK`^~k78C$E?$GAk(pc6J+Da4(eiSY5_lG`TEv>XdEX~dRPSB$rCupC_ z8{`D7(u4h-9Wd`TK^I>a6 zgTFTf&r|Ns9|-?1w0$o~0>rD?Sppvki!fhnzJY10^_wC%;9XuQD0d!i>OGtD;yy`~ zDaUmH63dJvH$Se51Tq%)HnFe@drq@U!)1$TwCp{KDPMjW8ekO9X}9cbB^?XP+nvIA(E`I8W1O&p%z{GmFr#o3t| zh1F5UHeBeOQk_E!FN?1gf(ji`>qP(Aci^S4+N+`D-E!(@m&=L zV}M&-&;fo#O}!}L4>hdJa~!3`xB3GuT?3c*+U1P_R0rJ+Vz4N7nbtV2yeJ8>(9Te;v2zHQTKJnaxbeSsY$7 z0hNW~nbdhN+x*0$YbcssgY>_^)G+sR5-0=uiv*U8$_HaRw+$H$B&$`<(X`??N7ts$b}9zqAx1GVK84@1 z_ym5>|gh3SmgB{bMB&1apxQ|vhsn_L*}%Qa;J)P6*k|@N>?RT1I-%&msQ(8y!7`V!Oh(( zmj|brZ=#OAQ#W6anIA>lk0DZBxRxxmt2)|M#G(%os7jPT6+z_r(|ku*`miU=ErF7i z*v5Pie|u!5Q>=skodbeZ=ydD|OXGnPV#%r2#}ts^bPp7~RvGX$Rur;ucWTLKAgJgjA$;> z6iU>-p-^uEC=8A?wdS9kJne}SB296jT|_*XcCK*HYu!d6eAbKdLhb1SxmjEsG7fpU zX_5xbZZ0CVrYo`{N)34;vh-!szs)|^W}lJl^DIYnX`YiERDbNLlk$btzmNk*#h%&* z*;Qf-+Cp9sTSUdE#Fjs+7h+Gfv-nDM5q4K%Pt8`br+%isBf3oBB@6C ztfXQ!U4Q}y@+YyHdXR4*r%uRpsQKa@C?#9=`k(WT0^Bp67o|NPKui zCumjX`x3DVswvbmEY=U>)@_tU+G_oAlHv-uut?twLJy7yg$1Ynl`*TXVK!h-HfGfw zsx=Ws{%H)Y5VuNe^6`?3UG+P*yCdfiA7RTt?5Y>j@5_PkB|)e{>cUWkrcpCd!9OHo z(bo|W7Qt<(I8?WNE)LZqSS0?Y(}Zkq_YIf2O9p~aMa*OA2k7zh5vWvb0nGg1m=^5f z&wp@aiWD^vg-TC9N?J)(mDJBgq3Z09LM1G>lCCy^2K`Z}ex-0?Y5W!?Vf|iea(t)& zRiX&(k3#hsjY||Ne4_R`GZ(4q)OHbDSw_y5e-w!7_ndw?`6?TT%8{+u^Glx+#Xux= zhcH|Bt&%uYXhxTm&KFrrz1p5|Ju+T$_Dd!Wb?6vVc@4 z2xJ5|_>zEBc&TS2Qaz`F{^iDeRvN*@%B>Vl^ovCIkA zH8>j8!*{V`|L>wv9YmpP`|;|hfv=24wOJLqU~nNtm%b2?0WnJas*qF*PY6kM$#}J0J|B{5q2lkYx8X?#LQ)A!xH5B|dTU3hLs+-A4g#u3Lt4YY9o%oV+P%1N~m5xm2gsM`S6RY$ywFv1QkaH(Y72>oKx737l zVX83Y(~?K&-aO7dimnVWPK;8er?Gp0cTrKQ^z>FW)US+Er6e%Xe*!@#N>y!Iu2=d6 zF`{4P1hEDw_WveI)pa!L&0Hl-XD;VAFHSad=D{?wlr6>HgVQn3MWah*_)hoAz znCt!@_Ra)8>grnjce0Qn3zGoRu*rZRQ3N7H4F+sR5}atFVH32diCG{uBr%y0P|!ev zC5(BcYFlfyrE0D9)s|;n0IP;Yh>8$gQEN%9+Fy)I+#o74|L?i?Hcc+H8b;JN1)p&EvOroS)6(iGf{P9LTQGdQxSN;I@9w)l2xQ z8G0PJFHDaLP)!egz9n)f-So&C{{rnTil>Kr7n?_zdl!3K=rv-y z*iVOwZ6fCMtUa5)#eFr`W5`R%%P=qaKl38a#oe`Fi%0_sJvg7_o}ZRS6rss12DK4x zvTolr^>bAL>r{65C1c#o5zlk=OYS5FlOHO@S25ave9I70(og7E2a(m2%~F3uo|XdL*sL|JSDT9r|fwL_w`FQX+0`G)50)YL;Sg1#rYk#0oF}WZxW# z;C30qP}$#9?eIFBeG7uTq?t6iGjntO4@E#FL z4I~sk!P)AqCdRqo?FY%QUH?7z^TIj_Ca{wJ z{DJFKnmHnwRBA65k$&zX>x2BUL$Rv=8(gR00&co}2G=P=bDhp6?QnMd$2zIr7nZyUpf{#zI*VPcMbnV?Xxk$!s z<8%Hfa~1b0_R~O-4r9sT4Xob)X_330I+c5$O{<&5#CtAsnezRRnO8rfaOZJld11@d zAd8i}fX4|d1})DRkbI5yC*(EeI#FA9Sc@QIDFsux(#*ZwR1teUzW$B^|Z zvBo#n2zoU8=j_z(&Oir9D?HC@_Y zqD_W+N3U+)M}4N%PoKV*c>U4VD=6cq)QncWZY^dwrhy3E>rmmWI&B4bX|`jn%bnsp0~0ks2QSbyNBrO zM(Y9N!q5;Mxu1yqj}hr`B9-{ER}!v%Y&=G)d>lFvF4=RuA==DfdIIepqOB+IGNbcD zjPcgzD|B?f0$1%yuS5En(?V~vit61$l;d-q&{NOYng_Ex@S10rC}*JfFZg2e8WAYl z;hge8UFK+i5{&i_vK}4nx~-Y5b--dh8qC2TFJ7#RTpQyJ?s7dkMO^k+MHfrKIcVtR z0oSaCgT7(x-X6@VJL2~B<8OceFC~)xJI{w54NvO1DF-2wtKqNYqArs&<+{xNejcOS z-tn=vm$kXvz~S|(X=5aNo?t&)p8>OaaC>lTUFJd`ag6q#)$pu;1mZcI+RZ>Rb2QN~ zY{!X`1mrSqYYueoYwt)xSe*3x?TlGS86?ZB9Xq6X_%7ysSm!ji@BC@~eKR1)*{&yB ztcHt(IzdXoBUJ0i@OE8z324)yBMv7BvR&*n4G@OBRI0%4bEVt>AwN9m^)GnSzQ=?1~Rn0x-z(wq5l?Lu!c zvIJgKJJrtO`GJqUnfq#3W<6^?u^sOU zn%&$X9JZ3MP16Sh`qtla^jabu?$Z@I-1~rU6VBXrWW99#U4&z-NmJgZCf|Kv!cRFJ z<%LeRFNYYXqf2n+jZE2j1(SDu7dJ^inEWs(w+eEnyn%j|9{6qI1>YGV$Lq0>y;?>d zi$vMU@WbZh{oYMe?Bwz?59GPBsizSi-pQz_~C>V`qbpCj*X|;+CBKx9R(&q|fjoE6AJk(m>=CE)6im0O5Pvx=A;mVWTj0hb` znu`%=A*R4nf}Tg}c%y->^R65#1)J=qMUKXm`?J=rT;Oe7*_qSuywBOVvdi;WVnv|m{nmMT(l}jfPUW~oi{h;5^d}zLsj^}iMyBTM_eJK!ejV6jbd|^=x!H5_ zGbsFJEcShuD-9mL49mynqcMZCLhAyskjUgKKVdNmMeZEaf`7yV>Hs~(1F{319YeAX z?sWQ`B&kU90}msX%IZK~r!$aW$WvdI$ap=zSE|wNWe+c zRTSX#=_(qKI$iYx3}DMYqJ0cilM{HSW02>MxG4lu{)krwrJTTDHrIhQ=I{2b>GYkj zF8VaqG6!2n=PbUzuF12?mED39CCl=i;M&qY6o$=*iS^G$krnKvRIV-W#@F`q#M%Cs z`tUcbBbG3Uz8LV~c(fLOhcqJPczcwU2sI6j-~F+y{iT+zH$VfbUG|DF5wo%bIXlqs zRj^A6i|9IyXT_K_+77Cn^DSNgkRgrT*y#(XkH(xfeIaa30Kc30nmvJ?CvWA{cZR-T znAOnfn@Sv^NGZg@k$pxe1qvp=I=?$oKO*&U9D4t3yL8a4J?^Nn-`FYV?ni>jf1XDk zTdet%!5Sz9$!Px>^wpcIfkeijd7+7B?l(pA6CI7{^CAvP-xf^16D!txzp)NKK2o!-E_wm_U!m`Soa!|!biW!Sz3fW$yfY?tI(9*@sn zy8;y)#SGbflqsXmvu@WI@7kPJ*P42g%xQql_$!*4r{Qy-KMQCh2OAG#o z&7^Cvr`)h@@`*nokhA~fZT_gZk2@mbI;r$+ zH1`?PWu@sml`R!uG^PmM9kKv&nK4S~?N*fXkH}t|v!LU|&GK%e-C|<7;k2M5N`@QL zlMw=>33_;7F*~rbxp8HSYt1jj0?AFv+I;d>VpLhK1`!_>w9Z$Zxz)8s7{mJRNR1$w z?_8VcsXrWb?F9Ztb0mwU>&g5D+`W<`fqLoXuq>>4Uc<)ui9TC7t=eCP>F^D0#_BOlO?0G&H2nDvp?!Cp zJg3ub4?nwP_;IcI5!v=Mbdp05)1#k7=&i?C6dr~cln(JsNWR4(rwF0Z!d?v~=fRED z^f;4u5+r1c^)d1ldBwwWxxOGQ8M?LbVx&ap)s>_;k5G}Z88o08xDvW#&uVe;FHjVO zxOgCbkGC-@78&pfUuZ^w?rkip8DHI2?t0mDh1O?TdYvR|xfSqmIcoS(GaWa@nnVsl zQ{&@=2yE8^L-j7%-NHH$Z@$-fk7^k@WIczr-be+@M5|bv;PRBdvYjpb&TQm50$XJb zEh{eTb&j3_@-{{~fzz1E@IA^~jJ)4gU2{#zgPB!j3}yuLBKxGr-+;^d3k8;2e>Jo; zve7P!6SLT6$*J|HaR1#C*eVAHg}i;5$MS-?gvQP6fwX9LfGLB6*yprN4eM076A$CV zpTbJW^_WAr=L5?!Bhc(F7sl%~ciI0gF0RL7$Foq9^-=v7NBjxaKnP;^SsmxW%$k^) z;C%vS7K%N1(JWc`i$@Q+QViFV*-oxyXLSs;Ui?8QxK#)WL51C;>x5-f#Td8ENXud^ z`}p3N9@<20@u%2+1>FVV3CeLBkAo>5La zI?4&(93>Z3h3hO)M%q!LL}#yc5C*a2a*P<-g#KRTvG18*k2)6F=Y?399_0T!2F5jRYV_B8cJ;dYGg=5?|oa=3>7&C@TzROPF zvaj3&ro_qn_+!)3}B!pYp+^fu7m_yMDOnt$N&eQ&Ls4TU9QJ=c4T>rFBY-& zBaIh3sq<5ar>yY|-nlP6AM55L`iAo|nsH27W16=<23ES>Exk(itj!)NIn7_hP@`zM z(r~L~>$J>ln1lxz?vt`-y73pty2omQ#j#J6ZM(kVMUMCSJM@l)keYc6d%F=1nlz(l z9Nwu3V_4nM3t7wB{F83I^7Cx{A?!KL9U`sq=LO#&k;NL24U=K4oG?To+A&JT1pQF0 zPfmCk9rBP|mh7SpmDPBgoLW77wVYaA-j*}9c(DIu*_QWnJqiILvolJ&^hKIZ`yfd# z(mEb=J?dhq&}Ow!GT}M?M3*qXEj!Q{PlMx3&v8SVC-dVK3Pv7%VP!zku_EiH7u#;^v5+1A?;iib(H;6ELc z?DdY)e}IYu?{C<3D4(lr{W_HXG&j89yYl`R|EIZ|f=Bf4hFso+(Z5wFYe(w=joq0S z`K^gp1uqAVQ(*nneh`|2r zK0u zxtls^2>e_;BX$M+sHXGUau4yyMps15#TPc^O-S^j0D_&v($l<69v7Mim%@&x@3wVX z*FDb2FuqM5*U1ug+i!Qp?1t;rG057e>s+5l#qLsXzDape4kdng4NmU)Y9=BX6qzjg zh-5E$5Sf!smPfX-1AaA14uJXN_Q+%C9Aoa%>kl8NC8!}0pCVhx=9Apztm*P`ZM9lX z38Zsne(d@ID!1r!Ig6Q1Q^VnjOY_^!i%h}2hhSb&aFjddot2oI*|L;} z=S`twyvfr@9F1s)hWuE^rG3|;BmA_oZOgZlG4G5Kgdm@~NH)PPM?3tVJF?TTe z4hSGBQ+?9{Io0HdjKjp?Kpg%QgE6%hCuPyggN_8dYcJNtft11Ib%cj+)^uU#s;NSA zf3$UR85wE1xZC1fECOg%%XfOGJa46zNIq$t0UBq3#@SSw7-AxX^+E{`R6p8NEouSx z$t+gDtxlxLEuX~JFh*8V*{~v-f!aBn;U))}m3UhlKJ#BfSCMS>`+bOnPT5pc06U#3D zOC&b3{TfE$p7E{cJW?K}t9fJ-5h_@Bf38AHJaww+?z<$oY|l_e=40VKdx zFPSu&dNxy;$Ce+RLF;oPQ9N{X1$l$dgz89Fkhi`)qDLj^3c@ZbTuGq{D(J4D`gW(# zR1?nO4_8o(sUQw|!byC~`pJ&%5=wNEuvAbAb&)6)1mOmoWIQ~ToaBF5S5K{}p6>eA z^~3DB)YK1kA=MJDCR0CKd(=;!ou1IQOXv&1^I{?W+*qlETubcQ#BRUXwURGgLsEUS zsK`8%GgCoMER(*eezs6Q`qcbww(j~ta9KSEa-G&Wh0^;kjR~WoN@M?os3tnRIWr8m-c%9&R245?9mciEx zo^J5l1y42jV!?+S{C>d`4ZczED1&bjyz6pZ_GZD~H+YNSZ3b@@{3U~L5WL0U`vw1_ z!P^AiXmCsLdkx+x`0WPo68vU^%dvu0XK;BU-SQbcQSikEPZ4~f!QFxv7(7+*Y=fr> zo?-9|!B00htXT9W8r&=RV1pM3?lkxU!4EIgWiJ%G)8LB*f7{^Ig6}u@GQoEnyiV|D zgRd3*VS}$1{CaCo~c=jZM0-LE%ns5`yf z6g#9PbW&ZdUF5%8t8|C1V zE&>q9Q#|YcfZ+ZCYm=-iB;aTg?06a_HqV9^MBVER7DIV~XJrjEY@Or0b%Xn#v(0}A z8VHDLzW2~p*(UqnUEjSOzMyGv|FTtY1zlyUzU*=>eU3#i3NvXU+x$=EZV7Fl^CDmH z)_2mN&s7*NDZ*g(^Nw?(V*RHZ9fa8VKeVTQ|43o?xQshHVy&a_V=jzuN9`TC zTF*)@!gn_1@n#akcTw#}GiMt2=V>i}po#wJptR2H*cAUnS&)g^!{=pQ53MhL779O1 zmmTL1WeLcwF-Q^q0`cfHZ1K9DVIyo(57$iZ@=2!srjoiVLCQMPR2K!I#^$q}^j$=q zT@b3Xzx1l8eLX7bX`Q!v%h_FF*P_L-Gf1`B)wQ)FUPu$7`nRvEwGxa%2;bO>U*TBBxLx@&ejb&eao2#n_loX22o?76Wt| zfrNQt6C8VRD#C@Dmzb#aF7?#8loogm^@C`zo^mj-ul_x_yib!K5Z_huCtv<7sDCfg zH>du+DBr~T_xkxx2tMmO(;Bs0*kvc++4|iw*j!ogn&12x=>-yA0kq4}2Uf2es}}(s zD==>}=EuccVKs2-WW-R6IH8=Hb&Dv7k2HXQSxf-RyL>2-mPs>-pFkt!Dt<2 ztc@0L5y+W06*=<*r;q7ylUlY(Z8{)y;jxf+e==kxZ{?!PTkk&)lhu4=xMDp``H|Lb zKjkn4E{YTN#oqhS?_B?t)0b5LRh%!r{;Md2$Y6Y?cATCUcv6-|d9u0n*54;MZ`3;d zgR%pUZUohL)Rk~JF@&!2P(#(rCwXfkxE@g7WW4*C0zAdS)ce?q%wuNb{okO3e&LGl74b^%0o>nbFw zd`OEE^~&JMmJ0QM?8K97EJPcC0&Xf_{g{LhKS6MP9T zF$cM)fkZaiB9b}a2_$%QYI}X@!Q|hin{1zoY_DNFj>JQ%?O{+bxykmx9$H>{!%raL ziysRSYi*ZAu71E~LXn*ILOW@eLm;ml0tGLo9dMQsQgd+mckOq4UGimtcxCGzB2uO${YECR#7oWHuRqt{BAt(QphtbPRQ9naYVi0 zkPb_)&cLiMIGhb-aSeDVi?Etdc$Uk#ntyoy_}9r)MA?kSs6n}$vdX#ZB;f(IcckWx z-#3FZk)gc)8<{KekGKgV3L#V04{vLYceo8BLD!l}209&OTv_A7Sw|39FX&h=xu}&~ zNRit8c+vAOCwA`oFCuP8sQ)6;e?lO7@fw=hs6ccfurc8>F%7aZ31`o8E!S`=sTCTA zY>cQQD7MH*0~E#cM% zlgp>*wo5bhSMm1C4_V;T@1L{IKq!bJkN4Jp)pqR@VlxsO>uz#ml-;Qa02T_8wVXQU2$F&V%_y(fyuO%@V5!bkf ziUc7NcPNh>g&Gx;w@*Cle69?c?F+La4ra9;LDD-y%X@SG2Dvk>6ZsC$ z!E6^=%M-Xq`<&KVerOOC@SOG10jWe+!?SEANhF6vE(k=m;XOu9um6Cxb$Fc~%Q?he z$f~eekK@t9@HzF;!IBeXI9#sVwg;0hrtT!Nm4t$m&F!Cqt_Il>bKZgz6hPkNO_;$8 zbC3#e$j3#ztZAU#twUJ6?u%H?f^p9yD_dA1%4;f~`V}V@D4*N2F8jp1wRvNTJhJgs zYqL?UR9}LVoURvkpzZG&>xRGTCYhc~^^M=28_9~97w!J-K|RC3p*BHj1y&S3wN%nW z;)clka9cu$79zZC>#uLw9)2hu5Io7yf729$;zG^?#}t}Nvic^|lov#LBU&iKVWDul zd7qZ`GD=B=9v4Xzgky>=8RHf@oAqdXi->}A-b4X}h&h2B!Q`t5CxPU6i?@`T%U~)e@?w#b6cosNZH_L?x zbf#tV?)Y`I9EWZ>5&o07T*twCS$$V*8Rg+(>}@+lv|G*}@?_lz=;8ew*JDDoAD;{- zJQMH!MfJNPMBr+at=c)Tn`xm0FSTJWBq<5&qR8py)1J(owWqYd_jNFcuzyqXX4ZGX zT@>am&)RHP9?kMC&#vs40%)MfORB*B_V+Pp+YS&Yd_AFs5W3;hl8<05 z)5JTv#mUtM-3CX%9&MVFAQ}a-y-km}>2W;5$!WUD&N$Dys4=<09n)g{acfU7Iy~6A z@qcYUlzMOq6r>;3?D39TC@S98NO;t-W{+p`%%;A18}z4A_wie`8Y)?#>zbB&_oCrU z{0Eb(CYUOp#0)@fpqqsz^kxzlxXJozVITSVg0WX`pECjQ$$g&xx7U2FD- z3MCvY?eTcUn#`m|x$1XBNCo>54mrU?g^7MOJvB2umo>6D#<=Q>BT~Zc$1h>hw^@Cev>21Q2WtwMB|_^mZHD)BS0Jdv{;MzDU~*l`XkJdSN=*FLG@WFBlI)=ytcn$FFWq21td6G} z?6$;Xbc6BGCz4%*x}b&V276_3n4}$`6wK%bi%5c`q8sdGV{1Lw?eQG3>QgtEluxUc z?!J4f^+_jMmEqu8y8&_xYgy%?MEb5DQKFS{afrvT%)QgQv9e2qjHTQ=HQLTZHS{)D z_}-~#I~$KxCRTbUvV~^A+Jj5A&Es@~U?)i9Nw$(m9A(h&aV%{sgVV~QPl7s>ageny z>|k918ooBfitecUsD0=>8ymd9xh%mOh**m#ScL1*tsPF8rho8LqCuuMs()k;6=!GfUgYF=z|Lf6KHc+&cao?Ht`0{^z$MWKWs3#l!vEv)`K98k$SS83*u&eSm=4=oy#p%`@EbL`r zTdBB-)`z1ND2ou-8*qF*Xri$7K3_hzr{3r9$cnZpImL&c%$>f}9(teC@tFI~dY_Z< z64v{?^IPhDzLUJ#**+DtuWYk6Z68CnrMQ8)@OfCz??U(EQF@eZ^*-B*)tb4bG}HBHL;qG>JzFibs_B(v7fMiMKJ^4z zSfaZcipiOX!ru%lOJKSUKeg@uY{NTk*gzIUWPXff<)5zzIwrS%ms2({lR^s7zP%#o zjeeoybJqR)8RPp>1U-_erl%t4UEin(y4*z9ry}TZNUaF^Vx&@fD1zR|&_v}^h@%ui zpZ|YN5p*H_3VQxC6+wSTs@r<%B|SLkRR_~G`f0heTh@3ss>se};qnhCg4WHaW1_^W zW9e1|eSTMmD1rur6+weX>0XCFH|No!}`pUJ8m&a8Ejl5;T6E$qcg?K#`L8p$Q z9sHLRLEk{M!Q?i##M74|=u5PFb5HkU6hXg0BZ1?RMbBbn`yW*V{e9t12XZ#(3(m4c zFX*9e>?9Udw4mcCg3cqTUVb)DMaTTNQUrZXoIQMe8%59?j1nJLmZg7K6ZBIf5TIK(T5EznlZ7%9 zjxW|z-xY)Ud8qWwilJ-HF^lMLQVcyE#lwqz6Zsob485M~JRih$G}fI{!JU!dHZjJx zFO>-o)zIz2o&<5XGgk-K8AZ@2haOyao#=*^4U`0MwaW~NZfLPbHMDJyYUqh#U&6x% z0?Sca~jn1yezw3~V z!{KGKQGW2!FrBu6LMOZUaM1hKA0>Ckv|PEHd|s28@Q0hoXSsfWc*0ZQ=vvaZ34`SG z4aw)%yfi19+8nZ*67-#0KmBZ--Elp#JFJiFPI)1iyi*tu5{0)uK9W0Z_l>o zqLx9s$HwG=`9iYf8R zpWbwFe{0-LA|Rm6Lz#-FB--ys*QV$v&|f(D%V74Dc=OcsR}E~2d8O{cK>WM-9g-MK ze*Z*v|Lm2+XCO?@S;DIIn)a;aICO~zl8>Wrt4fK9CXp*TV}DCL!uROwTs_OEPJB0K z$_GtXh{~>j5W?-Dxmt5`Jt?-(fcXBJ# z!NB=lrWZCL*{Br$n|R&~y_NOIYME5gl5o^TJeo_EIXBk)JtvG=BuqF(Gq?NThI1;% z&63yTFw9)-lOwx`QD{MG=S-4AvS)me_5Fjk8p>;vt*m+72e-TDGTm?QC_&vomR$6+ z4ooq({5Jm*0@I|{E9ekCzM^PvA!>p?;^T{#*yS|%7bv$@MBOQ{~A+sSp1 zQv-Nz{dPstfO#RZOL5m;d&>#kJ#3H0Twj_BEBr!+{v0lQ$V91cKIb*%WSDDytnEd* zhxH35P3x2Ork#3()!lEtc2c(7+z} zi#(Z)qy)FyTC6Dgo`@iDwy{_wPYSt%1)W=EPPSwSc*EzWB@d_Isrm}Z&cMrDak4Lp zMNry~6UXn@+69`tM_k^mTHhe!KsGFPxsk<`1B=}UL!Q`W0v2tH=KMB=wN7HsGhEb8 zPWd44B_ck7H)(1-GyIp?(h%s*%Bloy{}L=OFbefiMpf39=~##`&a^aXY8JhY^HcGZ z*=982mrY$9;SHR5`_*ztz%#YC?eb=xc?%|g6&KqBAJVZz-&MzDoUk~#)H`*6|MOsT zSchfdbwVGy1%n$`P@25`t*2{sRnQrleZ#!tKazdM8aPs-3XN?jBQCNI&3 z6ndGr@ysD4NIIeC-=e?x9?c}^%au5?t=~ULjE&Jzr4;k(-%5X8zTCQlXVG!3w%(i- zqJf^r!|lFX28;HeLu^q@rUxYHlbgIw>y+g>(jSnLq(YBRg%0br@u1(WHPTrQ;TDA`{vu3#Z^t?dZ1{bVJIOf@tn) zb=AwN6h^^qaE3jbs3~RrNXktquJ5QJC)W$h*yN<0%0&vU6yiQ^BTvrK)x0y(Nfj@ zNilmWx43J*&2?n3ki^`_>e!RB$9-BdFb>wiKxYyv$RW!Nb-ZZ$M6*ohghJO~z zD7g$Smgh5;pXQBxg$(Dqa$XK5{{n^{eg?2awtj}pkQq*;TR%O)5R+Htc3Yb;kR`M< z+|5MNtzu8A+HGBO5nB}T_Cw>X{SG{Z&IW9`mMjqf(RUHup1>Du5iASOlC@O1vFvGB z5jny?lBSd_c5b8=vKVmn4d#<~if9vsjMmaFecfed3}NID?dr^3ECK`jJe#>?3a_%6 z+tSG0pp3Q8F^@fqQ6m<3Z%R_QTavKm)k+Iqt~|o;nFlxs$#LcH!usSlnR3WVy!UpKlN*M0ykUKjk8MV@KhD|< zW_0~{(OD|*=j^d=)mgoZqf)IywndiNzsA%tZ~5gAipcSF%g3gWMprWy4}K=q#Qw1Y zuZQ+~haq2h04)Jt7FYhUR#`Y9>v~WvDKrqDven^0L$eWxTwXifW1Sg}{1EM()q()M z*39Gil%^5OuamJtKWUk3KWT|Tz;oxV%XVaN08`OD9?v(vVp zI+6*hBQ_9ySrzngKyleRg!)Ovn3T{VBa<(pU+f31jCC}XIVoJ9KDcc)8j`w*#y;`8 zFvYz|YoW-XpB&ryN;Gr+NJ~#ZgcpCG+ysKxGmAuuntST4SnkfyU@ltDS;U& zxYf6PRNoTOI3wjZatYf%$+~iaRDUx!JoftrShI|&5EE~;@3Ag@T#qQUaP%j427`xY zu)SlorghT<#(M*E631Vi$dz z9j;rDSH4hVcI1ffB#{F}2&gH!b{Xp*6tuvC&`Me&0k;(?_)BYl2zq?HMDthr2NU+#9 zdqp`+ytP@^WWp=PCP-_PR?solNHW+`Dsx3}ike|)YGS2N=3jF?md!e=UaO@EwK;oi zPSb1oXMA~9+C5B85t2fa*THJW3XT)9>M3TTmzVFg0@oI6BUQ(=fy&Tb9VsT|?n%L# z$x*E+AT}c$auOtqhH=V7aWIsin1??snDvT~s$D-;#_DIbkTQ3Y8UKUHKZ+$6jnN-| zS4zIaYxLtVJ-?|f(4Z181o8C?COnZA!h5>J>0`i z^-t6hExRhS60GmbkGD9Vys?r`?z)z$2n>GKit9m;V=BOuFQd<>0tsU-k!E`e#5<~f zr1Vm8Q|a;{hfvH%mxdMJlxJ3DL@U+ox@~KKf4%FuekGcrrmz96u3wpsMmKLUvbK8b z%s%|HS~L8hA4+!6Mn6=nwe`b3>al)hq0*N-u4X|P%2k+lR%1yYwx}eue0F3<*DWnx zS)=-j$#6jW^>8}6$YwkLE(@JdCZy8-_3KH2+s}{zQK|cExXFe)ZP;eRPi)w4vhhFM zh8Z@TYr`@duCU=PHvF9pci3>h4J{jX*)Va6iGQ>Wcb{#{TWt7%4cFUnh3#*x4R5pI zZ*924hOgMrvf*JHrlgzr&$8hKHoU@y%WQbF4ezkwHXFWR!?$eMWy5}Fns^7>&~3xh zYFiZ1|83ciQj;8@_GBPiz=znE8!`IP-m$;m18Wm{Y5HQ%}^JsY;EgRUUiOI z!oPEfM`AL+5@r6KuH59o{BvtNu~}~all?+l-#*+zzUSbl8k^oRc$8l);;Y3?eiwjOkdx3)%$0-+{XE1{qssAP ze)*~hbFo@%n`h$pDs24PzGpl|#M5nS%A=IYzk;5UU#@xUd`j6RU!nXMSczHElUPkY zj9I8*(iMM_j>J<$e139LVu!$z-%OqRZo9eUTzu8`@;9G+l<1Nl?J^hNr9FJ-L*vRG zVdvm}v{~{IN>|a!Bt4}}{9=~)q#P2D;}AE?sg}X}F`-7m)3KQ=BtVSp6oHqU3?__z-n~|L}^L%ga1sCS!UvzQ7tl4ws!scCY z>1E$tc=;7q78YGqTvA%LXmR=XuC7>8Syg>aO|8#=?b2n-ue*N5${TJ}GpcHGmX-So zYO0D$rFNIlmWrwS8d^cAnn+8k(0xmKP$ey=93Q2O7}Do!v_H2lM}m@dm$aWe`pz8w z_4E^RmG+cNA3Ogzt}?D%OxyElUwy?eoAEDAP2r!!Ie~aQ2ks`x7-h~zV0 zrOWjg0ewBN;)s1~emGZ}AWY?OXjPN^4Rs?`0rT#s!%;}Z9B(k#cl zg1^_<{-pQB>fUAI7k?$V7i)Lvv67~n)MQ+7<5J1r<>XOP6}M{sNsJ~$IWCpdha1XB zDNU?Pu$7V0t$kii{!QL}^lB-+)M70$R%ky}sth}cPwF&OG8vz`=`=ypX$fh|m?~qA zTct816l1DUr(!B2zDmqeX33M-NJ|iUN{No8RHe?Nv>-DFNcp6N^$eM<^CY9Gs`_a(R~K_o{L%PN9w@17)lGxB%c%iDeWUvo)F#A!sQ6%DMY`%N>CD} zyP-yi9+O#zg!-G*ev$4ard-n7`ije~+n}`LP@cN!J6W9_jxUs-Z&#m7NvrP^`>s<% zhslf@q5OaQ^rUA=pZ(9IcV;-fYTBr21J@E)4ROk^JLeP}wj9%?YawRd!_+Z8y8Na0M^fd>B;_7ZsXY^=KlHX(FTLRT(6ckD<*7Z@O z$2K!YTz%YhLizpAw4b9>k~N;tyeGB0>D}E=rB-Cr@Gv!;$To90rGK3Rj5`;i^l!aw9%!4hZ1W)7+?HVcBZZ`Y)wX$vZFbw{p|*Kryz!63 znf_(j=Ha%vGtRi5WSj4|%_D7dTdZ+++vaN9JjyoLIgLA~1o~HKn?noeEZcmY?e4bC zhix-Q7JA*x~fq@K*EH$#o*pPLy{daCqDv!cuclbxEh z5|fKqdrc_`Ow|8)XN|g+*cWM^vgVN4$iyJ=U9DTdQvRN+^VK_*9KxA(>nLK6WpCRv zwsVNj{8EWQMvMyjp!`xR{S_6U{p7zxaYz~2PxXsPjLON$iI(4)X~ZQS-5CW7Vw~#i zw6ysJuwUJ7-Nc-QiwpTFwXAv>KPNtTNyg~}IQb{WfBm3<`JjDzOiv2MrOc&V9h z`q!Y2{dctgRjT`+Lw&n{J!4p{y8lJM^Z7RaLgC&2Y6HjAzs!LD!!5wED*VrARsZ{c zLp3OHwWIrAgyY-&3xz+nMgOBVf3F8fN`v_qN>NPRc%rRG{_mIA_~`Bb+m*K4SEB01 z4d!5U?f%uRT3z3;=BDqjZCn?)x#{12u>Oa)+gzu550yYIR8 zSNHw;{@*CHbMX#2}se|`I%cmHO!zt{2p2Ooaa`SB;8e)jpnLtS5d z`PE@mas8JWG{8D#(4<&Wn471@LEZvX;fG>BueP-2;;X(_TI|cMEUT(nq8;WFMt->G71jDY#lG@uOAD&1 z{ncT6V`rjM`EW6d7L}e?wakQ^2mddJwdNFd6cgbtqC&<5wEy<2tGlUgRUHeu$eZeJ zT3t6dI+_*Tnl)=6d|FyvLET#ARH@@K3g*|bUSm;LP_UMu?$o-qb%atZ>lQCw>~zK~ ztFB&JU46`YPEKYn;*;~6G5DXUcQR%r+>?hY`x)Wl73o#6oL`8mtVhSPb`I@A2w&tY zs&JRq)Kt~D%PZX#MgGd-#icdpxX0FNPc^KeINMOo_*C-xK{t zXvdFxmEU)K54c05(x~t0E)gfNH_?$?*%lJaSNz{KWDNdpuC6!6I$*w%~%UM=U z2Qf8kYL0l9EGeQ6sXd_}WE(e;`W`1(?c&m_imS%luuJKp-O5L=P9?kQ3nVxn`-?);Uz3|h{Rr+w%CeYj-$(Z<;mirbpb8 z)#%j!kz{-HBVAsbp2%7Ct_Mh_%V+v!PrB=z_4Hp-s+&SjKW=}m5N6)onG?*3Z%_X^ z<#8vEa~IjAkXF<)G$|bGf7CcgTTxN9R3etpy_$m|*fHUbuF+np^pQ?c%_6^4c&$6N z^jb!m@-lbnl4{@bQ~!Q?SJBk$L8yp~($7o7jaeG3dr9e%D*H%pwB6H2>k(1s#nMD}7>hi5W-@nU4Ec;!YamRD(+5)u8k^HE6c0HK94KI+bb^Uehg1 z*pKj~cbO=*fbZ#HP8u4ehE6`AI=OIgnuL+~HpA5Ut1x!#Fpk&=6+5|K+K>qeXO7(A zQp0=$)QKetq!+JTQ(|lSwMDf?zW`H&uKWh02@~t5Tq8%G@}WLRnH~4{jaUoLHSSxStwa;-oAwQWi~T37U;t;ahB{y9fNQJF+5%k zFL9~ia|fv5)bsG!DV-;@*)(wVQ!eVt1x;PEyJ)9+Iw9e1juTa#&ntt?Q7OzN*r@;#zXDtTC)l>P^Gl4GMvw9~F8?Ica77){qu z8>*S5)H8g44CQ~MleF2J)^xX5Y2z8>@9(wS{qvM+xTHI-Bxw(mBf@=b#$`%f%J-_B zmdTH)XUUJWjaYZ$B9nH-2Upsxj^dt z#L0uIwY&Hk-d_#BoAR|KwYr)Us^bge(qd`rNs&2ls5%C>Y!SellY)Vo0(~13q$36Frd@{zHoe+UIU<4 z0`!VkgKvRelE&Ov(qQ~x>@f9D9WhQ1p|0)mzd0$XpGusX z{QmJ-rOHEeJ&F0}mbkY5tuf8f)lr3!1rcdNSE0p_v*Og)^lKu=I?5vZnj_r9$e;At z$-DmO80N?FL(R2WQY5%mXAvN7JmHFc7cBS6u`-APj0z9EZsTXat zBbl*}_LTh4fa-+8_yRpHV`e?nIj}9U)wJf=g5#{WI%U1(h>lRv>6~N?lztFPKLAcP zAszi4s{d8A8R>tkfqD$G`)&ahV?g|Dv(|Ksj8`LlNor(CBI}0%YGn8PX3E7F)MLJBll9(^vlG-Q zzQgL2lCRV$>0hc-9G|K1tjHKE`B={}o6i4vj29E7^_ySX6u}*8nJtShw$<3(9?|W` z`0W1sFZp&un}5l-8#?@7k#8UA=qbk8w7`mYte1C2zM_8@!HHBh5ie>!OsP|R2&7&-}gU(hnDynKj zrVDdsUzC$KW%9(53RbrPCG?*STjN??ggG$t=BpgX9A6Fpb1BU^+6Pq!<4sC8$D23b zQ;@5JzZ&5!EvlYbQ%e3`)VN33Ch8NFQwjTNMoqa7W@*J77#qS;SDBG{rA6149%El^ z%34F+&0StCsodPFy?E4~s1PTuoBnS_&8u9j=~I%ktQbLUQlTP9n)yrUb6n?$$lTiO z(yRQ77M0c%)RfjrlQ<=6wy)xn@*1DNsA66vT&fbKMv7ftRn^u0>X|UMB>{>iET9x| znNd`YbhflEU+FTR8Y^}tXwEX#5s_O70g5Whuj^f8Pi4uR>hj7NResX_5NZkkt)Qx0 zsHUD1+4LUfH#B9B?jK4$AT+xK29l=i%i53WDTs7v>J>-}RF#5zW-v3IDw~*Bmvcq7)hXNs)Oo@{6iz(X=p9+a5WaoJxdB`6M+#L*!SB z98%PrZq~60S36(*Me@;?gBsFZCW%W%0{XB!I@HDIR)zb$`i&VM3QBAAX+&i)?T2B%3Mw@`fC?UWas(I%4ljz-6quPF)EcHufL?a zsHQYb+fwn-gGQGW)szcUb-pSxE+rS2NtEogr5tv#WE@fIPo|~QU${4IT7*5qk^STR z>Z*;LSI9YJKI+syG30uDC~IFc!yeyHPZ#ko-@ktUqQJi>@SmqZsLxHl`@n>sj#ujW z%iS-Oy(G#H%un1;;0yIPIlmX2t)EKai{?w<>&M3yk27&|uFqCbpYMxZJYOuIxW(~> z+$3HJE6~L!@ybvkc1e7&+4Lv&qxi%g*1GoRvCT7VGef8jGuyVGV?!CaB>qeJByAR5 zI-Vs!Hy^{Eez1Whi_X84L;TnANuF2Pa5YfMQqL#u4SbTHAM%~b2MbJ_e+iWQ-peQH z!K%{sj{&7jd-%ltRX%Y~fha;B`GhY2++X5xelcpyhF|IsvzSn3y?({(Zgu7B-+O&>FW-#EFYf=doB^D1g9(Ysq2P=jzP$FmgKQgS z*>IW-Gi;b{!!#SF+R$yo6dO8i*wxR_`F$I<+3-&`+;78|Y}jhU-8O8o;SL)%+whMz z++@RtZMe~f_uKGx8{TZg1{;RrUtyblHmtB=p$!+<&}+jC8>ZRtbQ`*D=(J&1v?+Ig zCVWQ^I(ORkmJQo%xZj4YHf*tBvkf=eaDxrk+i;l;3vF0n!wegy*)Y|HZX2f9Fwuri z8!8)iMVb6}+R(CLn+^Bdu*HTOZMeaP>unf{zs@#S+py4vUK?iE&}~Df4G%|}e0*lZ zHXClT;RYM_q;U^&|F@$J7nuAUFXI1gccH^K(V}y9-}x^bY}a>+fz?9|TyK}RAm5l7 zHuM^|8;1J(Rdzp4J!tgs{CB~LBrIQOylJz?on^%)AOBT&qy2l^ zj(3F}?>`EqzeqlN_Z!)3%1_ow@>3T^%NF;)@5ip8Ms^OIvm)A{-sS6@;7}IuVm7=B zPj#pQ;136JR}(+C0ap%I>U8irUafVBZBib0oZH@C@K`KJl{xIKpjk zH}I@caK?F!GXvPlCus@1X|yR9x}p?%pLAG(Kj9NUw*$Yj?GFPdj4^&T0q;3QsTHJq zFYqJ2dnG@>q2rJh10N2Y14CgG_*~#ue68SzfkRG1h2>cM052F1&Bs6!;6r>;mWP40 zr<*+ZfTz(QQt@*-uz@cdT;R_qaZa9!&MDvrX~;Ta-w7OWhKWBBxQ%ZGes%!QWf@+F zpDf^4d{U=}fk&p0XY5rv=Vg3C!wTTLe4W@^z>8qm90o4{?m7#e3;AyWzRoAK`V;V! z4DyD($V`kqhj;`BMo%Yi;7;I`=TZjn#lSy&N2%X}KMZ__PvWtF^Rs9J)Yk&wwR}RW zW?&ni_z}qU1dR)v$tQU(1UB&P$NzfZ{d{fU8-f49_qN0X+{$Nx?*RVjJmfUMZwKz> zI}F|m+>sA&>=gU}hhAjT8V-DvPiV3Un0>LKt-$nI)Div#e#qwq?*!J(CN0V$@bkIw zt+4L`zH$jqK7*s5Oq4X~vZO6g>NhaBq+WgtjJ(X0D+;)rZxjC40w3fPI&1`%vK8Bp z{bJzze3CbTi3?3wfio_LF9m(Fflu=Zty+M0UBUhld;{<`KC%B3@Dm%4zmmSsC-w!v zdcL{f4ZtV(B&}v(RiVMFfx#m7t@z2fN~tUOB<#(=_7dbdz~2W>;#@-Vp8>p@PyEP9 z#<`1?dKf$l_#|H|cr$QDxxur6&)E2G;N0&)Tl@$-!l!8GTohN!`GkfmfGvCyzrcqp z@PeOaU^a}y#oz*;@&>*em{?`XCGa4h^tCQv)-~jZ_yu0UC+)KkxSdbZ z64{l%@JSip26}2ZlOb#!a1UQ6cq{O7AEMyk)xgXAq(__!fxo-fo)s{DGJq%EOuNKS3h-h+$#Vhl zmwXcTUf{V+hPGM2J8n09;ZER=pVDXXBXGeTCJ#Q~)Sn@5jr}y>HFp~N_<&#V32hGp zH{E6EDe(HA6F>e}0RO-zd3YH3IiJuCJ$)+i7X}yDw!y?BF!63a`jo%}_n5J<4fx8v z45irb2k!or8S@23-DlDjIL*cde#Dn2eG}&HR=x$`JAf6x=j<0;;JF)Vx8Pa88a}D( z4Zt9u~B1Mhv3HViKCmTlx4{5GK4Zsrkzu{(@?Ja7r0 z(76tn_B3V0e-= zBXG)o!h)v*<6fgI;PJrOd=md$U^}0T5AOpXf7|qhKLTgHW9n!w@a%VK(}c|c2KXfG z&A_RDGwp2}@Lj%6{8+$+mdU3;M>}O>&2u_1y#tzp3+#HI^#r)U_zz5*5%>_Fj2jOF zt3HP2_^AeV@X6WL9f1s5oC^MVUZ_`={KZ!hxhVlPl+#swF++{Q(2T;#jOUZBW>3NG+P z8y7yJ$OMbMK#_Zuya^PURIlh`>>~Vs=_|(CGawFw11&^#JKi2_O~C${{G|GYaQ`@#NTop|ND<)Z}nj>eAq7R zop&>?K)kn20aWL`teLS7nN#j_sQaDW=H}ng{~&6}J@sMS$99`rU&EZ(ZC>^s{)s!} zzwJZJlqqEPe&j%AsoR{2o0~6-56NNv9{)FS;zV`+`RA+o^XIGb@^a<(`&FHIudCyK zox1(@+tsgs{cE*(^JdlD+^k-G^;LD`$Pp#mSMjAiW9Sr9y!yfJI_|ygTDp{>9^>BN zM~Ca;4=-K1Vug74D7gFZ-r(*-IPb#j#DK2zAm*h@#cb_G>9;mx8&ppId=xxfrrnpW z=ybkM;NVW%ymYU#OTw3x5x@Ly6#u*TmX+-#eQnn9mzD9*K@dMTO8kd$mmhw#e+e(Y zibI$Wlm6bF+Dsx6{{cx~{|=EpZ#(QIf5cW+Ciy$O_lpCV4vGhz|J8@r?LNHwpu{2O zBeNIg;^A-w@nequ<1>R#y>s_oiclu>aqfR`)gU1NKZaE0{Cdsgq`cjG@o_WWiT^iu zoRMKXXmi)|d+#0n+uho)xD)Pu&$M6{!Q-|6y}S3^Gk15_;k|XuVun7!ujf70byz!# zf9TtOXID@=Yx+wRmT?yUTIu?J?%4&lHaUnIDL zPdAO@Kyep;J;O;neSJ4#AFNXjzDT|pJ{RA}ptSQuJ~!XrYv<|d>FB>jbmQ$ z(|HTE@%8K1s|Ox?w8Q zQy)E5c6F7ykt!;CDj2-+sg5gY30L3v;pbOA3UcGm-{D2jugX?F^Ul0^^PVcpOaFJ^ zl~-SI&BejsBUc7*XdL&{cjsNHZVcY@)Fbo$UwdZ)US*N&{YGT~7Z%YW;F1uwK-7SU zAX^d=mPDf9++lFL5s^Vq)(FBVn=-Bpk{L%)L`dR-p=lh<=erWo<=Y6ZYs=BJWx~k6``g?pj{ZBI6{>?XwoR{LOQq+j&8x^EO+OWi``>0N4n>3In%8zy38dlH+Rx% zb8Vh8m->vkb}yRi{EE2?UN)DpQQ@+;%=IlXm#6yY56qqaiMfHB&0YMtxhYeoxEpW0 z(dFmoyW4NS-Q97=9qz8X?s9YI&UN?Rd#|70MT-`>M<0FE+p;I0e9~=rdXc;4OLLEw zntS%yXWa`gyx?Ab`DM3m-8#2%<3{(^TW`5{-+kBZ_-K>c@Rhmu-+$lB#iyTs>UQqf z=05z^Txn^k`{tW(ysW_1LsGO?>7z3^5}KMbWy9B>b@GAwsUhrFD z;F}9Rt&jE?Bjs1laBlh{#Ulj2x>Uav7W^i`zbE()1^=nwcL;uW417v+#pTi^>*vd# zx58d5Am3U05L;i**`_wm-tFs5n_}CR@2qsOv)${;@lQEM@QH$NE%>g2&k?-( zDjg#D@%5bD)W+HDzRn&Tzp1H5unA_Rc-0o54zR5TD?P7D^ud{Oa;{<=Q z;8O*Ej^GCheyrec5d0nWOn=+K+#`L>tsZ6W)qHdBEH?Mqy1no<1rG;~75s66Z!Gxc zfvZt0o+tKO}Wnl(*K zY~Hi{f%I6y7FC$(tNtZC1lO>(0TWM=8M{$=SyW@c`3OCIRiGa-6E zJ13)icB;DXo{^r~Ej{-n9%$Aqv2pZ%R!&-ac6vr;hTy^Ml#`N^yGC*3k?fr8P{f2S6uLqK%4>Zped}=x!WMtWn2U_tV?AYu&cip*4@r(#?!+lI7D*%gES! zKR35q`q`ao*QkEFM##ve_pHplW~^~+|NjrxMl}%@elq;z|xMWSNrVT zjGWX?lC|>Nx*tlfy7kV;Nf#fpVs69#O#g(wZ{IeflT;=4w(no_o1G~^% z{cEDL(mU=8E&bTH8*N3QAa7Tr0~wO=EjLUyj#8|M1Scfe;D zr}nnnZgaC{&2qD6&vpd`1@4}E?(x3D!w)~~{lO=mc*5Z;yteXwH%tD;BKZo>JoAiu z<&{^wZ?NTq68FIeAGj@Bwz$te`^_K0g^%Uxev<3`yAmv8U5#rBcb@4f4cOVNVZ zCr|D7QCy?Ot>Wv}u6?5X;f9Gx&6>4nmQt^7ot8)Gx>4gM zEn4W=dUfMdl2el1@rkXHQcgHLrJf$BebiAW9^bfGQpypBC!HAmA|WBERZ7j8Ms8%CU&!(iDP^&uq z|1s{6`no!z$>FtXC2JqhxY==s9_$SPnGv_Z_cb4tgvE$<}zWCx3tvw%X-@g4LwIw@u?%bh$ z>6Ulid1vwS&p&^&&iN#F?%Y|D?`hJa;rr3<%Fo-c;U9C&!hCe|=FOX^g;#`^t5V|5 zKmYvH(^d5Faf&0}qJ6ZjSh2!B`Q#JRdTNTh5TLS>k`mMY+qf?pOndNmw{G3~sc3zF z{rdHHuUfTgQnzm1+NvMs>3G!!s`XUCg?T+ZTKNo*x%Wra6I2^0R?&9Po;}J8Xj@cu z{2PkjuSy3`qmTCO+cyV4;pOpv@x>QSF;WwLwsh%IkGEn-_VLFb+uF5jO)&-k95C_` z_L6oUxokIUw>`#W%8ReY0^$SoW5<_Hd9QuoX@Ym`l`M8=9?Z*&5y^Ox!JsV zv%UTH+x{AwLY2?sKTGCze);8>dn9+?tIw_9efOPx_0?BjzxLW|kAL{#hb0>8TVO=z zzoc*Ngu`@Te=YvS-pC-rvdp;yvdjY#hJXkfFn8~9ro>p4I7M#ZZIFT=m)w3%u6r5 z46KXlMrW~r~3o%VuR z%Clz4tISSWX?D(wX7fKX+qHZ52I&g=UzOtVU%q^Ke$%E++sTKYE_-R34^IO&hdF?+ z(8FASJD-{V_uhNYS3bjY_zk|u0n&994>in1Xb(nD&;#VzP^+qO-VEKG$C&4Z^W&_N3?kt6tD z86EH)o-;?t4f2oO)t=2Gbhhw6^X)Pky6N|mU4?5$(V%#;jTBwrKV*Yh(j%?UQqs|zv6wCXvmiQ_Yl9K zp^N@R_Zcsj(a>7Dpg6fDt?-XyN2^ji{<6jSit)G8JWNN=uq~C*fxO4gNsudA_|JXT z1z@o=v8CS@=_oY3YnCM%x{HQI+hd>D@8>Ud=g$2Q)9~AGzcsBh`&4KMHPBJnoCI28 z>G=Np?`_@Vv+driv+d4Nsdn3lG>_PMADjL8L$kh{&2pgO&8R+0W;zFb#wJOhu}RIP z2k7(3k|%WfC*|2Hp~2&?`JSfOMWXEbRA|8-(gqr6k$dF2A{{}#kac9K*V5 zMPs_y-FaO-4G?hQr)K9yY3Ng8)>}CB5)I}03=L6zJ_Va3o7zk^sj+B?Us`5c)yOgoN?PXe*U6rJN<;LF^+kSGd4+~hE7B2kC6*38Lj&cpNoUwYS9i39 zf9qrqj1vuGyV$PMZT5!L85(j$gK}*4ml%D%2i zVUsS&w42AAXYakS)}SHQ$ME_rn?$J$f7yF4|H5ZFxPuohIDt3%0H4F0VB=%`WBeg# zME;+?p{qS58kUNNM<$2{=>qx;4d^pA=?>XdXqW*FL%Z4amx_kJX4=F{x_cVH6CZ>1 zIrtduw7#kQO#ZPMtikvZ)OqvfS#fc(;g^OQ=7aV?dZM_jt-X7It-7|oJvl`*NEaR! z4G%{38JkovrmM{!-PLA}Oto8wr`au+r`ye<;X2W9jcAx48YmTgjQ^HysQk?SfWKtH z%fIA$Dzsd8-E|g;L_9r#2HO460Zqsjuv^zXY^$fXx0Rw{nP~9(EE=#$L7(T!CfzkU z)ove|X8#fm(?!EgqT%n7qbY+jJ)+p8^cWxGVd=ff&+I?=2l?;RsZ(=s08gC?DW`#X ziKXK}wEXzv5BC15JMGzN8Mflu4z?_+&)B4(&-chCLBp&l4gZuJO}{MNZX8lZ1BiMb zL;iMe)!DLFKbgH$LH4<9$ee5a&DS}G?BT&m`r2%mJ;W|eHGwP?}8a&vP{XEO}HE-x?7uDId~n>KBl*K37* zyxqYUs*DzR&)R^k!WY6HWj{bcpI^OijQ#MP_8UcG{rVj1W84wd=NZxkN@d7~?-Z-3 zBVYf&bnWp!`Q(#N*U_Hg`V-rq$&dE)P*_-KXP1>hx;~)Pp<&^B!TW|IFu)l}j z(7;;2I)PkK*~35s_7pi}ErdtU+?;9a?+5?g_ToKb_xc#p1$+$j8Jl$HxE#>`#r>CJ ze>W->ItBTWtmkXr-%jUXBGO^gJ=5R3GwFnJedd{GdcQ~KVZ8kWcW`BnpdnPggWt#= z`y6~b<^p{{r@cOF9$24)K4X(&_4$7un}Z)XEAaY2?HOmBajVYs_&5k-M|IhBM$vR8 z$rRJFmMvSFd~1&jc;GL^R%i${&_PRoRAegjjct8-_Qm$(-_x`{m-!g1&&3lm?6H3h zwzpqeV!LxKw^2e5MeEr(^4}D2@=PE{7a@AE={REym zH|i@o9cXCPs+H;Nnx6;O3}hbPC(r@D;E&8hCwl{0^Z^|~AHtl_B7^uQVeMh>&Hh>P z@~h&X=oa!XSt`(Zv5n}dGU9gi)mQs@fClWUV$0UQe}Dfya{vvYLPOa1vZutyM()9r z78!!JAYXisPleAdTk=oEo=(>}!&}%x91Q-*Jr!9Z-V9CPM$B1f@4WtIWMo)cTAJx} zik}DW0~2VV4RRIcBf`k?tX z$(xq})+qSQ^Hi>(0Xqs$vHuS}^pGuFxX`bG4?g&yha*NHK5dn4yHIQ7)xv$XzPnyX zllQ1<{-z=L;{Ra(rH|9OM&D?`g?Yy=NKU;kp*)GVtlxG0+ldpoQPqCav9m zpMXrU*2eM|T)75+<|g0GXt@4)lemgkTqWS#F>1He7xN3=)MFAfhHcaJ|~g#EA9p6SRXYY=pxgYXIafvsab zik%a9yJX1{yYtRFy*$J3P@x;yL3i+*xJG8^kF`KH^M1WL;b8d=?i3$?h+P-KKU8Q4 z^+0n1O*#|p*DGWU7-$1uWNU?NC$t3I<)7Ynkn&!J_1^z|{73rb_rF@dr$P(-rww$_ z20CcrDfR_jpfWdn$2?#=(NpFOTSP8_92B&`ca3o{c4jZe`+oBH2lTKd4>TwE z_xL~1MP81IY|%dV+;iUU!UOabc?W;=K=OExhX1WH6H7ru_!;7#vJ>U;A826h#DBs5 zAqT8Stex6Zrj7Ia&{J2I2o?Wem6+ey*Z%GzqQNx~;VHBI#(&uJYdQ2bje^1NSPQ8PV7 zRZ(!;tr}anCZkd@9;ogrEsPbXy=>*Z2YE7Lp=pZWlJh2Cyzy(ZR~41h?~y29==uGX z6J*1SH0B=cCpMD(5;#yp4kPOG|0KKmwQTMN+07^Dn4Bs3M)F+bSBQy|A9`)4*;>(F zg(>^l{nuzqd-=q@U0h4 z%<#EB@-xH{DU3}e_e%bloL{Uwa+ZZ04Y@vYOvq#MQyz487#}|<Vw`RccHHbpuXiv#l5uYx@4{Jz%-&e9-{74mfPjIVsk0L2yh#p1!($T=;A zd>c6u@`dE7mfSw_7juT&zB3zLqMWC2;5-jHLC%&E=*O=ZKYsl1Ns}fG#RsJZJcygX z3kvada!uqo$d!?2BELbNj2siW4RU1Um#!XIR&Tpzh=GHbN9A2Z?wkH%$HxXx@olKF zcz_G@zv}u_Bj5Fqa3H2hY@8em@<^VG{0g~7pW}*-KjD%d4CQqq$YU4rL8W~D@y(Qn z7@*%>_QMvi-^V|PZg7DIwCjt8_`D(cDss2v49PvuiRKH@3GyT43MVT^6?nj4u{N6A ztxCE4qg(oI?{L}wq39xZhkXHiJ9vWafgd}!zG*N1tB=nU5T8aK$>9^54mv@eiCiCf zvPn@K7_3i8Sswoajs4Cyd{b_N;_)w$LG%!xpB6l*@Pi5-@QHaiP}#8hL7y`vS2tBS zkT0!JerEp||K^)-9&q>FclRSVgg*`*@SJ@$durmQ-~lhNN8F>3zvUc2(22_Ak>{ea zR#_8|kF9vcaK&4O!G~LJxy9Q(>@Mpc_8(b*AIKtOg9`7w6np_||o<|lS;n2Trg`&j9gjke>%*Z0b!bb|af@;Gba zxeQ+2h0z=`FiVH_DaEJ z_V~5w{wzR{$HMVF?4f^;w9mH4IoT^~`>>&F*RE|9?;Q^v%43eW_~MJ7*YCIOvdb>> zabTU1^s$Su_kri|1OBtWLl)o%_*X3Sspr;9wqn=Xea7cPd9goB@BKcIwVu2Txh45o zrgPt(?y&y?4=VfskBV~xeym&A4)&$${&ZFRy91SY_Mq}VwvkIDFQMO=8u3?f7&U5? z=R5X*b&$S;3@{dUA?T{si64}g87x`OlaKV12Ib7tFYT$~;gxtl>UCD^}d1fouQL;JWYiU-{bs`W;l^865PU z0MmN~?5wlS^0e~;s7mqn7yF}g^h4>dL@{~Rd~6Q6 z1--Mt=a|t8@T0(o5aY#PCZ~emE*kFApj90k{QUSqp5ZGMJgAJvdZc$Gc-z2PRcJ@% zm@jw@-PmNsUheyqWBc(LN4Cb>|H|+PKCpgsVEVnIj}_w=5_3Wxf5X^*eCQ49FR}!^ z^hw3$p>yaqbRuJ%-{I_qeiz{F!$H!`*pztaugLdU{xb(uY%jKtdDc52kiYGUhux?? zh@Tv6;kPDr53-_PzhvL`i`NhF`ps^&^55&mPZlp!tEsvwRGtek@dBZy>bp=U=`+

^h^N4aZyJe%k(7BL*-gn=9``8`j0CuR45%cHI z_uuQ8!-|TEvJ}r=zF@%uKc8U@W1eNxUymJ(e45Tb6KDNieQcKe?L-gR8zZj^wFmi= z{5sAxrfP3BOZz~T$3h=Gi%jFg1%D>!6t*l^`zH2G#1PiYtvOBSI#q&y?8qN57P^LA zq9U)rQU+*y!XEgsGMCJM7yWOS+9lW~^axz>9gyv{Pu^qsBg%ZkfzkaN`$zV#>=oFn zwANnf4&g*eu~pAMC~1dl8FZ-^aeQgZ7=osPU=58@oke z55pen;eU@Z`iL!`$;1-VA&$VF4gN7ttU>relx5d-_x=|95B47HeeiYJZ$$38(ddJH zcrW3>{OR2@KF^H}gAbdZDX=AzyZHSizB_(9`v&$-69)D4WBjSaY@YVD`kl8;nl#Cu z5h1U}Tp}-l|Nde9w|3Pc@Aps8-X~fh_EGq!b-~*$a&nv>05-_n;)z{t+vW|PpX{Oj zKE#i|Gsq9Jhpor%Fqiu6y5}jjnz?*$b)h|UO;3NGd-k|9?ZqeVXL!9~vaIO0E8bVb zejzv5ZG0}~1A7{a3!hob11v4ihxvzh!S5>3I?4E~N9+^m8@sHve^M+wb{f3t2VUsD z*C*C&;z_`=&t~mbE@mHC`k7cGl3rKU9U84p?fzGxTg1q z)-Ai@eQSs49?#VDZ(BQ5_sXt#*VAn)X1Lk5l>kvHP6SDZX>#ITM7@`jxR;sQ>OG+Pe$CuXbGOdj zGq+|zTtQMnhk{-O{R=KF7*}vZ!OVhr1xpLo6l^NkTCk^}W?@_*Z|>hH7&o`>+{q8j zm_Kv=-1+n7FPgt}{>u4l=C7T3KtbFEnHc+rVzeuEi5hE<2hHiD6S}>D5l co{tw5U0O7=?|={2,3}|[~!]=)\s*') +MARKER_OP = re.compile(r'^((<=?)|(>=?)|={2,3}|[~!]=|in|not\s+in)\s*') +OR = re.compile(r'^or\b\s*') +AND = re.compile(r'^and\b\s*') +NON_SPACE = re.compile(r'(\S+)\s*') +STRING_CHUNK = re.compile(r'([\s\w\.{}()*+#:;,/?!~`@$%^&=|<>\[\]-]+)') + + +def parse_marker(marker_string): + """ + Parse a marker string and return a dictionary containing a marker expression. + + The dictionary will contain keys "op", "lhs" and "rhs" for non-terminals in + the expression grammar, or strings. A string contained in quotes is to be + interpreted as a literal string, and a string not contained in quotes is a + variable (such as os_name). + """ + def marker_var(remaining): + # either identifier, or literal string + m = IDENTIFIER.match(remaining) + if m: + result = m.groups()[0] + remaining = remaining[m.end():] + elif not remaining: + raise SyntaxError('unexpected end of input') + else: + q = remaining[0] + if q not in '\'"': + raise SyntaxError('invalid expression: %s' % remaining) + oq = '\'"'.replace(q, '') + remaining = remaining[1:] + parts = [q] + while remaining: + # either a string chunk, or oq, or q to terminate + if remaining[0] == q: + break + elif remaining[0] == oq: + parts.append(oq) + remaining = remaining[1:] + else: + m = STRING_CHUNK.match(remaining) + if not m: + raise SyntaxError('error in string literal: %s' % remaining) + parts.append(m.groups()[0]) + remaining = remaining[m.end():] + else: + s = ''.join(parts) + raise SyntaxError('unterminated string: %s' % s) + parts.append(q) + result = ''.join(parts) + remaining = remaining[1:].lstrip() # skip past closing quote + return result, remaining + + def marker_expr(remaining): + if remaining and remaining[0] == '(': + result, remaining = marker(remaining[1:].lstrip()) + if remaining[0] != ')': + raise SyntaxError('unterminated parenthesis: %s' % remaining) + remaining = remaining[1:].lstrip() + else: + lhs, remaining = marker_var(remaining) + while remaining: + m = MARKER_OP.match(remaining) + if not m: + break + op = m.groups()[0] + remaining = remaining[m.end():] + rhs, remaining = marker_var(remaining) + lhs = {'op': op, 'lhs': lhs, 'rhs': rhs} + result = lhs + return result, remaining + + def marker_and(remaining): + lhs, remaining = marker_expr(remaining) + while remaining: + m = AND.match(remaining) + if not m: + break + remaining = remaining[m.end():] + rhs, remaining = marker_expr(remaining) + lhs = {'op': 'and', 'lhs': lhs, 'rhs': rhs} + return lhs, remaining + + def marker(remaining): + lhs, remaining = marker_and(remaining) + while remaining: + m = OR.match(remaining) + if not m: + break + remaining = remaining[m.end():] + rhs, remaining = marker_and(remaining) + lhs = {'op': 'or', 'lhs': lhs, 'rhs': rhs} + return lhs, remaining + + return marker(marker_string) + + +def parse_requirement(req): + """ + Parse a requirement passed in as a string. Return a Container + whose attributes contain the various parts of the requirement. + """ + remaining = req.strip() + if not remaining or remaining.startswith('#'): + return None + m = IDENTIFIER.match(remaining) + if not m: + raise SyntaxError('name expected: %s' % remaining) + distname = m.groups()[0] + remaining = remaining[m.end():] + extras = mark_expr = versions = uri = None + if remaining and remaining[0] == '[': + i = remaining.find(']', 1) + if i < 0: + raise SyntaxError('unterminated extra: %s' % remaining) + s = remaining[1:i] + remaining = remaining[i + 1:].lstrip() + extras = [] + while s: + m = IDENTIFIER.match(s) + if not m: + raise SyntaxError('malformed extra: %s' % s) + extras.append(m.groups()[0]) + s = s[m.end():] + if not s: + break + if s[0] != ',': + raise SyntaxError('comma expected in extras: %s' % s) + s = s[1:].lstrip() + if not extras: + extras = None + if remaining: + if remaining[0] == '@': + # it's a URI + remaining = remaining[1:].lstrip() + m = NON_SPACE.match(remaining) + if not m: + raise SyntaxError('invalid URI: %s' % remaining) + uri = m.groups()[0] + t = urlparse(uri) + # there are issues with Python and URL parsing, so this test + # is a bit crude. See bpo-20271, bpo-23505. Python doesn't + # always parse invalid URLs correctly - it should raise + # exceptions for malformed URLs + if not (t.scheme and t.netloc): + raise SyntaxError('Invalid URL: %s' % uri) + remaining = remaining[m.end():].lstrip() + else: + + def get_versions(ver_remaining): + """ + Return a list of operator, version tuples if any are + specified, else None. + """ + m = COMPARE_OP.match(ver_remaining) + versions = None + if m: + versions = [] + while True: + op = m.groups()[0] + ver_remaining = ver_remaining[m.end():] + m = VERSION_IDENTIFIER.match(ver_remaining) + if not m: + raise SyntaxError('invalid version: %s' % ver_remaining) + v = m.groups()[0] + versions.append((op, v)) + ver_remaining = ver_remaining[m.end():] + if not ver_remaining or ver_remaining[0] != ',': + break + ver_remaining = ver_remaining[1:].lstrip() + # Some packages have a trailing comma which would break things + # See issue #148 + if not ver_remaining: + break + m = COMPARE_OP.match(ver_remaining) + if not m: + raise SyntaxError('invalid constraint: %s' % ver_remaining) + if not versions: + versions = None + return versions, ver_remaining + + if remaining[0] != '(': + versions, remaining = get_versions(remaining) + else: + i = remaining.find(')', 1) + if i < 0: + raise SyntaxError('unterminated parenthesis: %s' % remaining) + s = remaining[1:i] + remaining = remaining[i + 1:].lstrip() + # As a special diversion from PEP 508, allow a version number + # a.b.c in parentheses as a synonym for ~= a.b.c (because this + # is allowed in earlier PEPs) + if COMPARE_OP.match(s): + versions, _ = get_versions(s) + else: + m = VERSION_IDENTIFIER.match(s) + if not m: + raise SyntaxError('invalid constraint: %s' % s) + v = m.groups()[0] + s = s[m.end():].lstrip() + if s: + raise SyntaxError('invalid constraint: %s' % s) + versions = [('~=', v)] + + if remaining: + if remaining[0] != ';': + raise SyntaxError('invalid requirement: %s' % remaining) + remaining = remaining[1:].lstrip() + + mark_expr, remaining = parse_marker(remaining) + + if remaining and remaining[0] != '#': + raise SyntaxError('unexpected trailing data: %s' % remaining) + + if not versions: + rs = distname + else: + rs = '%s %s' % (distname, ', '.join(['%s %s' % con for con in versions])) + return Container(name=distname, extras=extras, constraints=versions, + marker=mark_expr, url=uri, requirement=rs) + + +def get_resources_dests(resources_root, rules): + """Find destinations for resources files""" + + def get_rel_path(root, path): + # normalizes and returns a lstripped-/-separated path + root = root.replace(os.path.sep, '/') + path = path.replace(os.path.sep, '/') + assert path.startswith(root) + return path[len(root):].lstrip('/') + + destinations = {} + for base, suffix, dest in rules: + prefix = os.path.join(resources_root, base) + for abs_base in iglob(prefix): + abs_glob = os.path.join(abs_base, suffix) + for abs_path in iglob(abs_glob): + resource_file = get_rel_path(resources_root, abs_path) + if dest is None: # remove the entry if it was here + destinations.pop(resource_file, None) + else: + rel_path = get_rel_path(abs_base, abs_path) + rel_dest = dest.replace(os.path.sep, '/').rstrip('/') + destinations[resource_file] = rel_dest + '/' + rel_path + return destinations + + +def in_venv(): + if hasattr(sys, 'real_prefix'): + # virtualenv venvs + result = True + else: + # PEP 405 venvs + result = sys.prefix != getattr(sys, 'base_prefix', sys.prefix) + return result + + +def get_executable(): +# The __PYVENV_LAUNCHER__ dance is apparently no longer needed, as +# changes to the stub launcher mean that sys.executable always points +# to the stub on OS X +# if sys.platform == 'darwin' and ('__PYVENV_LAUNCHER__' +# in os.environ): +# result = os.environ['__PYVENV_LAUNCHER__'] +# else: +# result = sys.executable +# return result + # Avoid normcasing: see issue #143 + # result = os.path.normcase(sys.executable) + result = sys.executable + if not isinstance(result, text_type): + result = fsdecode(result) + return result + + +def proceed(prompt, allowed_chars, error_prompt=None, default=None): + p = prompt + while True: + s = raw_input(p) + p = prompt + if not s and default: + s = default + if s: + c = s[0].lower() + if c in allowed_chars: + break + if error_prompt: + p = '%c: %s\n%s' % (c, error_prompt, prompt) + return c + + +def extract_by_key(d, keys): + if isinstance(keys, string_types): + keys = keys.split() + result = {} + for key in keys: + if key in d: + result[key] = d[key] + return result + +def read_exports(stream): + if sys.version_info[0] >= 3: + # needs to be a text stream + stream = codecs.getreader('utf-8')(stream) + # Try to load as JSON, falling back on legacy format + data = stream.read() + stream = StringIO(data) + try: + jdata = json.load(stream) + result = jdata['extensions']['python.exports']['exports'] + for group, entries in result.items(): + for k, v in entries.items(): + s = '%s = %s' % (k, v) + entry = get_export_entry(s) + assert entry is not None + entries[k] = entry + return result + except Exception: + stream.seek(0, 0) + + def read_stream(cp, stream): + if hasattr(cp, 'read_file'): + cp.read_file(stream) + else: + cp.readfp(stream) + + cp = configparser.ConfigParser() + try: + read_stream(cp, stream) + except configparser.MissingSectionHeaderError: + stream.close() + data = textwrap.dedent(data) + stream = StringIO(data) + read_stream(cp, stream) + + result = {} + for key in cp.sections(): + result[key] = entries = {} + for name, value in cp.items(key): + s = '%s = %s' % (name, value) + entry = get_export_entry(s) + assert entry is not None + #entry.dist = self + entries[name] = entry + return result + + +def write_exports(exports, stream): + if sys.version_info[0] >= 3: + # needs to be a text stream + stream = codecs.getwriter('utf-8')(stream) + cp = configparser.ConfigParser() + for k, v in exports.items(): + # TODO check k, v for valid values + cp.add_section(k) + for entry in v.values(): + if entry.suffix is None: + s = entry.prefix + else: + s = '%s:%s' % (entry.prefix, entry.suffix) + if entry.flags: + s = '%s [%s]' % (s, ', '.join(entry.flags)) + cp.set(k, entry.name, s) + cp.write(stream) + + +@contextlib.contextmanager +def tempdir(): + td = tempfile.mkdtemp() + try: + yield td + finally: + shutil.rmtree(td) + +@contextlib.contextmanager +def chdir(d): + cwd = os.getcwd() + try: + os.chdir(d) + yield + finally: + os.chdir(cwd) + + +@contextlib.contextmanager +def socket_timeout(seconds=15): + cto = socket.getdefaulttimeout() + try: + socket.setdefaulttimeout(seconds) + yield + finally: + socket.setdefaulttimeout(cto) + + +class cached_property(object): + def __init__(self, func): + self.func = func + #for attr in ('__name__', '__module__', '__doc__'): + # setattr(self, attr, getattr(func, attr, None)) + + def __get__(self, obj, cls=None): + if obj is None: + return self + value = self.func(obj) + object.__setattr__(obj, self.func.__name__, value) + #obj.__dict__[self.func.__name__] = value = self.func(obj) + return value + +def convert_path(pathname): + """Return 'pathname' as a name that will work on the native filesystem. + + The path is split on '/' and put back together again using the current + directory separator. Needed because filenames in the setup script are + always supplied in Unix style, and have to be converted to the local + convention before we can actually use them in the filesystem. Raises + ValueError on non-Unix-ish systems if 'pathname' either starts or + ends with a slash. + """ + if os.sep == '/': + return pathname + if not pathname: + return pathname + if pathname[0] == '/': + raise ValueError("path '%s' cannot be absolute" % pathname) + if pathname[-1] == '/': + raise ValueError("path '%s' cannot end with '/'" % pathname) + + paths = pathname.split('/') + while os.curdir in paths: + paths.remove(os.curdir) + if not paths: + return os.curdir + return os.path.join(*paths) + + +class FileOperator(object): + def __init__(self, dry_run=False): + self.dry_run = dry_run + self.ensured = set() + self._init_record() + + def _init_record(self): + self.record = False + self.files_written = set() + self.dirs_created = set() + + def record_as_written(self, path): + if self.record: + self.files_written.add(path) + + def newer(self, source, target): + """Tell if the target is newer than the source. + + Returns true if 'source' exists and is more recently modified than + 'target', or if 'source' exists and 'target' doesn't. + + Returns false if both exist and 'target' is the same age or younger + than 'source'. Raise PackagingFileError if 'source' does not exist. + + Note that this test is not very accurate: files created in the same + second will have the same "age". + """ + if not os.path.exists(source): + raise DistlibException("file '%r' does not exist" % + os.path.abspath(source)) + if not os.path.exists(target): + return True + + return os.stat(source).st_mtime > os.stat(target).st_mtime + + def copy_file(self, infile, outfile, check=True): + """Copy a file respecting dry-run and force flags. + """ + self.ensure_dir(os.path.dirname(outfile)) + logger.info('Copying %s to %s', infile, outfile) + if not self.dry_run: + msg = None + if check: + if os.path.islink(outfile): + msg = '%s is a symlink' % outfile + elif os.path.exists(outfile) and not os.path.isfile(outfile): + msg = '%s is a non-regular file' % outfile + if msg: + raise ValueError(msg + ' which would be overwritten') + shutil.copyfile(infile, outfile) + self.record_as_written(outfile) + + def copy_stream(self, instream, outfile, encoding=None): + assert not os.path.isdir(outfile) + self.ensure_dir(os.path.dirname(outfile)) + logger.info('Copying stream %s to %s', instream, outfile) + if not self.dry_run: + if encoding is None: + outstream = open(outfile, 'wb') + else: + outstream = codecs.open(outfile, 'w', encoding=encoding) + try: + shutil.copyfileobj(instream, outstream) + finally: + outstream.close() + self.record_as_written(outfile) + + def write_binary_file(self, path, data): + self.ensure_dir(os.path.dirname(path)) + if not self.dry_run: + if os.path.exists(path): + os.remove(path) + with open(path, 'wb') as f: + f.write(data) + self.record_as_written(path) + + def write_text_file(self, path, data, encoding): + self.write_binary_file(path, data.encode(encoding)) + + def set_mode(self, bits, mask, files): + if os.name == 'posix' or (os.name == 'java' and os._name == 'posix'): + # Set the executable bits (owner, group, and world) on + # all the files specified. + for f in files: + if self.dry_run: + logger.info("changing mode of %s", f) + else: + mode = (os.stat(f).st_mode | bits) & mask + logger.info("changing mode of %s to %o", f, mode) + os.chmod(f, mode) + + set_executable_mode = lambda s, f: s.set_mode(0o555, 0o7777, f) + + def ensure_dir(self, path): + path = os.path.abspath(path) + if path not in self.ensured and not os.path.exists(path): + self.ensured.add(path) + d, f = os.path.split(path) + self.ensure_dir(d) + logger.info('Creating %s' % path) + if not self.dry_run: + os.mkdir(path) + if self.record: + self.dirs_created.add(path) + + def byte_compile(self, path, optimize=False, force=False, prefix=None, hashed_invalidation=False): + dpath = cache_from_source(path, not optimize) + logger.info('Byte-compiling %s to %s', path, dpath) + if not self.dry_run: + if force or self.newer(path, dpath): + if not prefix: + diagpath = None + else: + assert path.startswith(prefix) + diagpath = path[len(prefix):] + compile_kwargs = {} + if hashed_invalidation and hasattr(py_compile, 'PycInvalidationMode'): + compile_kwargs['invalidation_mode'] = py_compile.PycInvalidationMode.CHECKED_HASH + py_compile.compile(path, dpath, diagpath, True, **compile_kwargs) # raise error + self.record_as_written(dpath) + return dpath + + def ensure_removed(self, path): + if os.path.exists(path): + if os.path.isdir(path) and not os.path.islink(path): + logger.debug('Removing directory tree at %s', path) + if not self.dry_run: + shutil.rmtree(path) + if self.record: + if path in self.dirs_created: + self.dirs_created.remove(path) + else: + if os.path.islink(path): + s = 'link' + else: + s = 'file' + logger.debug('Removing %s %s', s, path) + if not self.dry_run: + os.remove(path) + if self.record: + if path in self.files_written: + self.files_written.remove(path) + + def is_writable(self, path): + result = False + while not result: + if os.path.exists(path): + result = os.access(path, os.W_OK) + break + parent = os.path.dirname(path) + if parent == path: + break + path = parent + return result + + def commit(self): + """ + Commit recorded changes, turn off recording, return + changes. + """ + assert self.record + result = self.files_written, self.dirs_created + self._init_record() + return result + + def rollback(self): + if not self.dry_run: + for f in list(self.files_written): + if os.path.exists(f): + os.remove(f) + # dirs should all be empty now, except perhaps for + # __pycache__ subdirs + # reverse so that subdirs appear before their parents + dirs = sorted(self.dirs_created, reverse=True) + for d in dirs: + flist = os.listdir(d) + if flist: + assert flist == ['__pycache__'] + sd = os.path.join(d, flist[0]) + os.rmdir(sd) + os.rmdir(d) # should fail if non-empty + self._init_record() + +def resolve(module_name, dotted_path): + if module_name in sys.modules: + mod = sys.modules[module_name] + else: + mod = __import__(module_name) + if dotted_path is None: + result = mod + else: + parts = dotted_path.split('.') + result = getattr(mod, parts.pop(0)) + for p in parts: + result = getattr(result, p) + return result + + +class ExportEntry(object): + def __init__(self, name, prefix, suffix, flags): + self.name = name + self.prefix = prefix + self.suffix = suffix + self.flags = flags + + @cached_property + def value(self): + return resolve(self.prefix, self.suffix) + + def __repr__(self): # pragma: no cover + return '' % (self.name, self.prefix, + self.suffix, self.flags) + + def __eq__(self, other): + if not isinstance(other, ExportEntry): + result = False + else: + result = (self.name == other.name and + self.prefix == other.prefix and + self.suffix == other.suffix and + self.flags == other.flags) + return result + + __hash__ = object.__hash__ + + +ENTRY_RE = re.compile(r'''(?P(\w|[-.+])+) + \s*=\s*(?P(\w+)([:\.]\w+)*) + \s*(\[\s*(?P[\w-]+(=\w+)?(,\s*\w+(=\w+)?)*)\s*\])? + ''', re.VERBOSE) + +def get_export_entry(specification): + m = ENTRY_RE.search(specification) + if not m: + result = None + if '[' in specification or ']' in specification: + raise DistlibException("Invalid specification " + "'%s'" % specification) + else: + d = m.groupdict() + name = d['name'] + path = d['callable'] + colons = path.count(':') + if colons == 0: + prefix, suffix = path, None + else: + if colons != 1: + raise DistlibException("Invalid specification " + "'%s'" % specification) + prefix, suffix = path.split(':') + flags = d['flags'] + if flags is None: + if '[' in specification or ']' in specification: + raise DistlibException("Invalid specification " + "'%s'" % specification) + flags = [] + else: + flags = [f.strip() for f in flags.split(',')] + result = ExportEntry(name, prefix, suffix, flags) + return result + + +def get_cache_base(suffix=None): + """ + Return the default base location for distlib caches. If the directory does + not exist, it is created. Use the suffix provided for the base directory, + and default to '.distlib' if it isn't provided. + + On Windows, if LOCALAPPDATA is defined in the environment, then it is + assumed to be a directory, and will be the parent directory of the result. + On POSIX, and on Windows if LOCALAPPDATA is not defined, the user's home + directory - using os.expanduser('~') - will be the parent directory of + the result. + + The result is just the directory '.distlib' in the parent directory as + determined above, or with the name specified with ``suffix``. + """ + if suffix is None: + suffix = '.distlib' + if os.name == 'nt' and 'LOCALAPPDATA' in os.environ: + result = os.path.expandvars('$localappdata') + else: + # Assume posix, or old Windows + result = os.path.expanduser('~') + # we use 'isdir' instead of 'exists', because we want to + # fail if there's a file with that name + if os.path.isdir(result): + usable = os.access(result, os.W_OK) + if not usable: + logger.warning('Directory exists but is not writable: %s', result) + else: + try: + os.makedirs(result) + usable = True + except OSError: + logger.warning('Unable to create %s', result, exc_info=True) + usable = False + if not usable: + result = tempfile.mkdtemp() + logger.warning('Default location unusable, using %s', result) + return os.path.join(result, suffix) + + +def path_to_cache_dir(path): + """ + Convert an absolute path to a directory name for use in a cache. + + The algorithm used is: + + #. On Windows, any ``':'`` in the drive is replaced with ``'---'``. + #. Any occurrence of ``os.sep`` is replaced with ``'--'``. + #. ``'.cache'`` is appended. + """ + d, p = os.path.splitdrive(os.path.abspath(path)) + if d: + d = d.replace(':', '---') + p = p.replace(os.sep, '--') + return d + p + '.cache' + + +def ensure_slash(s): + if not s.endswith('/'): + return s + '/' + return s + + +def parse_credentials(netloc): + username = password = None + if '@' in netloc: + prefix, netloc = netloc.rsplit('@', 1) + if ':' not in prefix: + username = prefix + else: + username, password = prefix.split(':', 1) + if username: + username = unquote(username) + if password: + password = unquote(password) + return username, password, netloc + + +def get_process_umask(): + result = os.umask(0o22) + os.umask(result) + return result + +def is_string_sequence(seq): + result = True + i = None + for i, s in enumerate(seq): + if not isinstance(s, string_types): + result = False + break + assert i is not None + return result + +PROJECT_NAME_AND_VERSION = re.compile('([a-z0-9_]+([.-][a-z_][a-z0-9_]*)*)-' + '([a-z0-9_.+-]+)', re.I) +PYTHON_VERSION = re.compile(r'-py(\d\.?\d?)') + + +def split_filename(filename, project_name=None): + """ + Extract name, version, python version from a filename (no extension) + + Return name, version, pyver or None + """ + result = None + pyver = None + filename = unquote(filename).replace(' ', '-') + m = PYTHON_VERSION.search(filename) + if m: + pyver = m.group(1) + filename = filename[:m.start()] + if project_name and len(filename) > len(project_name) + 1: + m = re.match(re.escape(project_name) + r'\b', filename) + if m: + n = m.end() + result = filename[:n], filename[n + 1:], pyver + if result is None: + m = PROJECT_NAME_AND_VERSION.match(filename) + if m: + result = m.group(1), m.group(3), pyver + return result + +# Allow spaces in name because of legacy dists like "Twisted Core" +NAME_VERSION_RE = re.compile(r'(?P[\w .-]+)\s*' + r'\(\s*(?P[^\s)]+)\)$') + +def parse_name_and_version(p): + """ + A utility method used to get name and version from a string. + + From e.g. a Provides-Dist value. + + :param p: A value in a form 'foo (1.0)' + :return: The name and version as a tuple. + """ + m = NAME_VERSION_RE.match(p) + if not m: + raise DistlibException('Ill-formed name/version string: \'%s\'' % p) + d = m.groupdict() + return d['name'].strip().lower(), d['ver'] + +def get_extras(requested, available): + result = set() + requested = set(requested or []) + available = set(available or []) + if '*' in requested: + requested.remove('*') + result |= available + for r in requested: + if r == '-': + result.add(r) + elif r.startswith('-'): + unwanted = r[1:] + if unwanted not in available: + logger.warning('undeclared extra: %s' % unwanted) + if unwanted in result: + result.remove(unwanted) + else: + if r not in available: + logger.warning('undeclared extra: %s' % r) + result.add(r) + return result +# +# Extended metadata functionality +# + +def _get_external_data(url): + result = {} + try: + # urlopen might fail if it runs into redirections, + # because of Python issue #13696. Fixed in locators + # using a custom redirect handler. + resp = urlopen(url) + headers = resp.info() + ct = headers.get('Content-Type') + if not ct.startswith('application/json'): + logger.debug('Unexpected response for JSON request: %s', ct) + else: + reader = codecs.getreader('utf-8')(resp) + #data = reader.read().decode('utf-8') + #result = json.loads(data) + result = json.load(reader) + except Exception as e: + logger.exception('Failed to get external data for %s: %s', url, e) + return result + +_external_data_base_url = 'https://www.red-dove.com/pypi/projects/' + +def get_project_data(name): + url = '%s/%s/project.json' % (name[0].upper(), name) + url = urljoin(_external_data_base_url, url) + result = _get_external_data(url) + return result + +def get_package_data(name, version): + url = '%s/%s/package-%s.json' % (name[0].upper(), name, version) + url = urljoin(_external_data_base_url, url) + return _get_external_data(url) + + +class Cache(object): + """ + A class implementing a cache for resources that need to live in the file system + e.g. shared libraries. This class was moved from resources to here because it + could be used by other modules, e.g. the wheel module. + """ + + def __init__(self, base): + """ + Initialise an instance. + + :param base: The base directory where the cache should be located. + """ + # we use 'isdir' instead of 'exists', because we want to + # fail if there's a file with that name + if not os.path.isdir(base): # pragma: no cover + os.makedirs(base) + if (os.stat(base).st_mode & 0o77) != 0: + logger.warning('Directory \'%s\' is not private', base) + self.base = os.path.abspath(os.path.normpath(base)) + + def prefix_to_dir(self, prefix): + """ + Converts a resource prefix to a directory name in the cache. + """ + return path_to_cache_dir(prefix) + + def clear(self): + """ + Clear the cache. + """ + not_removed = [] + for fn in os.listdir(self.base): + fn = os.path.join(self.base, fn) + try: + if os.path.islink(fn) or os.path.isfile(fn): + os.remove(fn) + elif os.path.isdir(fn): + shutil.rmtree(fn) + except Exception: + not_removed.append(fn) + return not_removed + + +class EventMixin(object): + """ + A very simple publish/subscribe system. + """ + def __init__(self): + self._subscribers = {} + + def add(self, event, subscriber, append=True): + """ + Add a subscriber for an event. + + :param event: The name of an event. + :param subscriber: The subscriber to be added (and called when the + event is published). + :param append: Whether to append or prepend the subscriber to an + existing subscriber list for the event. + """ + subs = self._subscribers + if event not in subs: + subs[event] = deque([subscriber]) + else: + sq = subs[event] + if append: + sq.append(subscriber) + else: + sq.appendleft(subscriber) + + def remove(self, event, subscriber): + """ + Remove a subscriber for an event. + + :param event: The name of an event. + :param subscriber: The subscriber to be removed. + """ + subs = self._subscribers + if event not in subs: + raise ValueError('No subscribers: %r' % event) + subs[event].remove(subscriber) + + def get_subscribers(self, event): + """ + Return an iterator for the subscribers for an event. + :param event: The event to return subscribers for. + """ + return iter(self._subscribers.get(event, ())) + + def publish(self, event, *args, **kwargs): + """ + Publish a event and return a list of values returned by its + subscribers. + + :param event: The event to publish. + :param args: The positional arguments to pass to the event's + subscribers. + :param kwargs: The keyword arguments to pass to the event's + subscribers. + """ + result = [] + for subscriber in self.get_subscribers(event): + try: + value = subscriber(event, *args, **kwargs) + except Exception: + logger.exception('Exception during event publication') + value = None + result.append(value) + logger.debug('publish %s: args = %s, kwargs = %s, result = %s', + event, args, kwargs, result) + return result + +# +# Simple sequencing +# +class Sequencer(object): + def __init__(self): + self._preds = {} + self._succs = {} + self._nodes = set() # nodes with no preds/succs + + def add_node(self, node): + self._nodes.add(node) + + def remove_node(self, node, edges=False): + if node in self._nodes: + self._nodes.remove(node) + if edges: + for p in set(self._preds.get(node, ())): + self.remove(p, node) + for s in set(self._succs.get(node, ())): + self.remove(node, s) + # Remove empties + for k, v in list(self._preds.items()): + if not v: + del self._preds[k] + for k, v in list(self._succs.items()): + if not v: + del self._succs[k] + + def add(self, pred, succ): + assert pred != succ + self._preds.setdefault(succ, set()).add(pred) + self._succs.setdefault(pred, set()).add(succ) + + def remove(self, pred, succ): + assert pred != succ + try: + preds = self._preds[succ] + succs = self._succs[pred] + except KeyError: # pragma: no cover + raise ValueError('%r not a successor of anything' % succ) + try: + preds.remove(pred) + succs.remove(succ) + except KeyError: # pragma: no cover + raise ValueError('%r not a successor of %r' % (succ, pred)) + + def is_step(self, step): + return (step in self._preds or step in self._succs or + step in self._nodes) + + def get_steps(self, final): + if not self.is_step(final): + raise ValueError('Unknown: %r' % final) + result = [] + todo = [] + seen = set() + todo.append(final) + while todo: + step = todo.pop(0) + if step in seen: + # if a step was already seen, + # move it to the end (so it will appear earlier + # when reversed on return) ... but not for the + # final step, as that would be confusing for + # users + if step != final: + result.remove(step) + result.append(step) + else: + seen.add(step) + result.append(step) + preds = self._preds.get(step, ()) + todo.extend(preds) + return reversed(result) + + @property + def strong_connections(self): + #http://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm + index_counter = [0] + stack = [] + lowlinks = {} + index = {} + result = [] + + graph = self._succs + + def strongconnect(node): + # set the depth index for this node to the smallest unused index + index[node] = index_counter[0] + lowlinks[node] = index_counter[0] + index_counter[0] += 1 + stack.append(node) + + # Consider successors + try: + successors = graph[node] + except Exception: + successors = [] + for successor in successors: + if successor not in lowlinks: + # Successor has not yet been visited + strongconnect(successor) + lowlinks[node] = min(lowlinks[node],lowlinks[successor]) + elif successor in stack: + # the successor is in the stack and hence in the current + # strongly connected component (SCC) + lowlinks[node] = min(lowlinks[node],index[successor]) + + # If `node` is a root node, pop the stack and generate an SCC + if lowlinks[node] == index[node]: + connected_component = [] + + while True: + successor = stack.pop() + connected_component.append(successor) + if successor == node: break + component = tuple(connected_component) + # storing the result + result.append(component) + + for node in graph: + if node not in lowlinks: + strongconnect(node) + + return result + + @property + def dot(self): + result = ['digraph G {'] + for succ in self._preds: + preds = self._preds[succ] + for pred in preds: + result.append(' %s -> %s;' % (pred, succ)) + for node in self._nodes: + result.append(' %s;' % node) + result.append('}') + return '\n'.join(result) + +# +# Unarchiving functionality for zip, tar, tgz, tbz, whl +# + +ARCHIVE_EXTENSIONS = ('.tar.gz', '.tar.bz2', '.tar', '.zip', + '.tgz', '.tbz', '.whl') + +def unarchive(archive_filename, dest_dir, format=None, check=True): + + def check_path(path): + if not isinstance(path, text_type): + path = path.decode('utf-8') + p = os.path.abspath(os.path.join(dest_dir, path)) + if not p.startswith(dest_dir) or p[plen] != os.sep: + raise ValueError('path outside destination: %r' % p) + + dest_dir = os.path.abspath(dest_dir) + plen = len(dest_dir) + archive = None + if format is None: + if archive_filename.endswith(('.zip', '.whl')): + format = 'zip' + elif archive_filename.endswith(('.tar.gz', '.tgz')): + format = 'tgz' + mode = 'r:gz' + elif archive_filename.endswith(('.tar.bz2', '.tbz')): + format = 'tbz' + mode = 'r:bz2' + elif archive_filename.endswith('.tar'): + format = 'tar' + mode = 'r' + else: # pragma: no cover + raise ValueError('Unknown format for %r' % archive_filename) + try: + if format == 'zip': + archive = ZipFile(archive_filename, 'r') + if check: + names = archive.namelist() + for name in names: + check_path(name) + else: + archive = tarfile.open(archive_filename, mode) + if check: + names = archive.getnames() + for name in names: + check_path(name) + if format != 'zip' and sys.version_info[0] < 3: + # See Python issue 17153. If the dest path contains Unicode, + # tarfile extraction fails on Python 2.x if a member path name + # contains non-ASCII characters - it leads to an implicit + # bytes -> unicode conversion using ASCII to decode. + for tarinfo in archive.getmembers(): + if not isinstance(tarinfo.name, text_type): + tarinfo.name = tarinfo.name.decode('utf-8') + archive.extractall(dest_dir) + + finally: + if archive: + archive.close() + + +def zip_dir(directory): + """zip a directory tree into a BytesIO object""" + result = io.BytesIO() + dlen = len(directory) + with ZipFile(result, "w") as zf: + for root, dirs, files in os.walk(directory): + for name in files: + full = os.path.join(root, name) + rel = root[dlen:] + dest = os.path.join(rel, name) + zf.write(full, dest) + return result + +# +# Simple progress bar +# + +UNITS = ('', 'K', 'M', 'G','T','P') + + +class Progress(object): + unknown = 'UNKNOWN' + + def __init__(self, minval=0, maxval=100): + assert maxval is None or maxval >= minval + self.min = self.cur = minval + self.max = maxval + self.started = None + self.elapsed = 0 + self.done = False + + def update(self, curval): + assert self.min <= curval + assert self.max is None or curval <= self.max + self.cur = curval + now = time.time() + if self.started is None: + self.started = now + else: + self.elapsed = now - self.started + + def increment(self, incr): + assert incr >= 0 + self.update(self.cur + incr) + + def start(self): + self.update(self.min) + return self + + def stop(self): + if self.max is not None: + self.update(self.max) + self.done = True + + @property + def maximum(self): + return self.unknown if self.max is None else self.max + + @property + def percentage(self): + if self.done: + result = '100 %' + elif self.max is None: + result = ' ?? %' + else: + v = 100.0 * (self.cur - self.min) / (self.max - self.min) + result = '%3d %%' % v + return result + + def format_duration(self, duration): + if (duration <= 0) and self.max is None or self.cur == self.min: + result = '??:??:??' + #elif duration < 1: + # result = '--:--:--' + else: + result = time.strftime('%H:%M:%S', time.gmtime(duration)) + return result + + @property + def ETA(self): + if self.done: + prefix = 'Done' + t = self.elapsed + #import pdb; pdb.set_trace() + else: + prefix = 'ETA ' + if self.max is None: + t = -1 + elif self.elapsed == 0 or (self.cur == self.min): + t = 0 + else: + #import pdb; pdb.set_trace() + t = float(self.max - self.min) + t /= self.cur - self.min + t = (t - 1) * self.elapsed + return '%s: %s' % (prefix, self.format_duration(t)) + + @property + def speed(self): + if self.elapsed == 0: + result = 0.0 + else: + result = (self.cur - self.min) / self.elapsed + for unit in UNITS: + if result < 1000: + break + result /= 1000.0 + return '%d %sB/s' % (result, unit) + +# +# Glob functionality +# + +RICH_GLOB = re.compile(r'\{([^}]*)\}') +_CHECK_RECURSIVE_GLOB = re.compile(r'[^/\\,{]\*\*|\*\*[^/\\,}]') +_CHECK_MISMATCH_SET = re.compile(r'^[^{]*\}|\{[^}]*$') + + +def iglob(path_glob): + """Extended globbing function that supports ** and {opt1,opt2,opt3}.""" + if _CHECK_RECURSIVE_GLOB.search(path_glob): + msg = """invalid glob %r: recursive glob "**" must be used alone""" + raise ValueError(msg % path_glob) + if _CHECK_MISMATCH_SET.search(path_glob): + msg = """invalid glob %r: mismatching set marker '{' or '}'""" + raise ValueError(msg % path_glob) + return _iglob(path_glob) + + +def _iglob(path_glob): + rich_path_glob = RICH_GLOB.split(path_glob, 1) + if len(rich_path_glob) > 1: + assert len(rich_path_glob) == 3, rich_path_glob + prefix, set, suffix = rich_path_glob + for item in set.split(','): + for path in _iglob(''.join((prefix, item, suffix))): + yield path + else: + if '**' not in path_glob: + for item in std_iglob(path_glob): + yield item + else: + prefix, radical = path_glob.split('**', 1) + if prefix == '': + prefix = '.' + if radical == '': + radical = '*' + else: + # we support both + radical = radical.lstrip('/') + radical = radical.lstrip('\\') + for path, dir, files in os.walk(prefix): + path = os.path.normpath(path) + for fn in _iglob(os.path.join(path, radical)): + yield fn + +if ssl: + from .compat import (HTTPSHandler as BaseHTTPSHandler, match_hostname, + CertificateError) + + +# +# HTTPSConnection which verifies certificates/matches domains +# + + class HTTPSConnection(httplib.HTTPSConnection): + ca_certs = None # set this to the path to the certs file (.pem) + check_domain = True # only used if ca_certs is not None + + # noinspection PyPropertyAccess + def connect(self): + sock = socket.create_connection((self.host, self.port), self.timeout) + if getattr(self, '_tunnel_host', False): + self.sock = sock + self._tunnel() + + if not hasattr(ssl, 'SSLContext'): + # For 2.x + if self.ca_certs: + cert_reqs = ssl.CERT_REQUIRED + else: + cert_reqs = ssl.CERT_NONE + self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file, + cert_reqs=cert_reqs, + ssl_version=ssl.PROTOCOL_SSLv23, + ca_certs=self.ca_certs) + else: # pragma: no cover + context = ssl.SSLContext(ssl.PROTOCOL_SSLv23) + if hasattr(ssl, 'OP_NO_SSLv2'): + context.options |= ssl.OP_NO_SSLv2 + if self.cert_file: + context.load_cert_chain(self.cert_file, self.key_file) + kwargs = {} + if self.ca_certs: + context.verify_mode = ssl.CERT_REQUIRED + context.load_verify_locations(cafile=self.ca_certs) + if getattr(ssl, 'HAS_SNI', False): + kwargs['server_hostname'] = self.host + self.sock = context.wrap_socket(sock, **kwargs) + if self.ca_certs and self.check_domain: + try: + match_hostname(self.sock.getpeercert(), self.host) + logger.debug('Host verified: %s', self.host) + except CertificateError: # pragma: no cover + self.sock.shutdown(socket.SHUT_RDWR) + self.sock.close() + raise + + class HTTPSHandler(BaseHTTPSHandler): + def __init__(self, ca_certs, check_domain=True): + BaseHTTPSHandler.__init__(self) + self.ca_certs = ca_certs + self.check_domain = check_domain + + def _conn_maker(self, *args, **kwargs): + """ + This is called to create a connection instance. Normally you'd + pass a connection class to do_open, but it doesn't actually check for + a class, and just expects a callable. As long as we behave just as a + constructor would have, we should be OK. If it ever changes so that + we *must* pass a class, we'll create an UnsafeHTTPSConnection class + which just sets check_domain to False in the class definition, and + choose which one to pass to do_open. + """ + result = HTTPSConnection(*args, **kwargs) + if self.ca_certs: + result.ca_certs = self.ca_certs + result.check_domain = self.check_domain + return result + + def https_open(self, req): + try: + return self.do_open(self._conn_maker, req) + except URLError as e: + if 'certificate verify failed' in str(e.reason): + raise CertificateError('Unable to verify server certificate ' + 'for %s' % req.host) + else: + raise + + # + # To prevent against mixing HTTP traffic with HTTPS (examples: A Man-In-The- + # Middle proxy using HTTP listens on port 443, or an index mistakenly serves + # HTML containing a http://xyz link when it should be https://xyz), + # you can use the following handler class, which does not allow HTTP traffic. + # + # It works by inheriting from HTTPHandler - so build_opener won't add a + # handler for HTTP itself. + # + class HTTPSOnlyHandler(HTTPSHandler, HTTPHandler): + def http_open(self, req): + raise URLError('Unexpected HTTP request on what should be a secure ' + 'connection: %s' % req) + +# +# XML-RPC with timeouts +# + +_ver_info = sys.version_info[:2] + +if _ver_info == (2, 6): + class HTTP(httplib.HTTP): + def __init__(self, host='', port=None, **kwargs): + if port == 0: # 0 means use port 0, not the default port + port = None + self._setup(self._connection_class(host, port, **kwargs)) + + + if ssl: + class HTTPS(httplib.HTTPS): + def __init__(self, host='', port=None, **kwargs): + if port == 0: # 0 means use port 0, not the default port + port = None + self._setup(self._connection_class(host, port, **kwargs)) + + +class Transport(xmlrpclib.Transport): + def __init__(self, timeout, use_datetime=0): + self.timeout = timeout + xmlrpclib.Transport.__init__(self, use_datetime) + + def make_connection(self, host): + h, eh, x509 = self.get_host_info(host) + if _ver_info == (2, 6): + result = HTTP(h, timeout=self.timeout) + else: + if not self._connection or host != self._connection[0]: + self._extra_headers = eh + self._connection = host, httplib.HTTPConnection(h) + result = self._connection[1] + return result + +if ssl: + class SafeTransport(xmlrpclib.SafeTransport): + def __init__(self, timeout, use_datetime=0): + self.timeout = timeout + xmlrpclib.SafeTransport.__init__(self, use_datetime) + + def make_connection(self, host): + h, eh, kwargs = self.get_host_info(host) + if not kwargs: + kwargs = {} + kwargs['timeout'] = self.timeout + if _ver_info == (2, 6): + result = HTTPS(host, None, **kwargs) + else: + if not self._connection or host != self._connection[0]: + self._extra_headers = eh + self._connection = host, httplib.HTTPSConnection(h, None, + **kwargs) + result = self._connection[1] + return result + + +class ServerProxy(xmlrpclib.ServerProxy): + def __init__(self, uri, **kwargs): + self.timeout = timeout = kwargs.pop('timeout', None) + # The above classes only come into play if a timeout + # is specified + if timeout is not None: + # scheme = splittype(uri) # deprecated as of Python 3.8 + scheme = urlparse(uri)[0] + use_datetime = kwargs.get('use_datetime', 0) + if scheme == 'https': + tcls = SafeTransport + else: + tcls = Transport + kwargs['transport'] = t = tcls(timeout, use_datetime=use_datetime) + self.transport = t + xmlrpclib.ServerProxy.__init__(self, uri, **kwargs) + +# +# CSV functionality. This is provided because on 2.x, the csv module can't +# handle Unicode. However, we need to deal with Unicode in e.g. RECORD files. +# + +def _csv_open(fn, mode, **kwargs): + if sys.version_info[0] < 3: + mode += 'b' + else: + kwargs['newline'] = '' + # Python 3 determines encoding from locale. Force 'utf-8' + # file encoding to match other forced utf-8 encoding + kwargs['encoding'] = 'utf-8' + return open(fn, mode, **kwargs) + + +class CSVBase(object): + defaults = { + 'delimiter': str(','), # The strs are used because we need native + 'quotechar': str('"'), # str in the csv API (2.x won't take + 'lineterminator': str('\n') # Unicode) + } + + def __enter__(self): + return self + + def __exit__(self, *exc_info): + self.stream.close() + + +class CSVReader(CSVBase): + def __init__(self, **kwargs): + if 'stream' in kwargs: + stream = kwargs['stream'] + if sys.version_info[0] >= 3: + # needs to be a text stream + stream = codecs.getreader('utf-8')(stream) + self.stream = stream + else: + self.stream = _csv_open(kwargs['path'], 'r') + self.reader = csv.reader(self.stream, **self.defaults) + + def __iter__(self): + return self + + def next(self): + result = next(self.reader) + if sys.version_info[0] < 3: + for i, item in enumerate(result): + if not isinstance(item, text_type): + result[i] = item.decode('utf-8') + return result + + __next__ = next + +class CSVWriter(CSVBase): + def __init__(self, fn, **kwargs): + self.stream = _csv_open(fn, 'w') + self.writer = csv.writer(self.stream, **self.defaults) + + def writerow(self, row): + if sys.version_info[0] < 3: + r = [] + for item in row: + if isinstance(item, text_type): + item = item.encode('utf-8') + r.append(item) + row = r + self.writer.writerow(row) + +# +# Configurator functionality +# + +class Configurator(BaseConfigurator): + + value_converters = dict(BaseConfigurator.value_converters) + value_converters['inc'] = 'inc_convert' + + def __init__(self, config, base=None): + super(Configurator, self).__init__(config) + self.base = base or os.getcwd() + + def configure_custom(self, config): + def convert(o): + if isinstance(o, (list, tuple)): + result = type(o)([convert(i) for i in o]) + elif isinstance(o, dict): + if '()' in o: + result = self.configure_custom(o) + else: + result = {} + for k in o: + result[k] = convert(o[k]) + else: + result = self.convert(o) + return result + + c = config.pop('()') + if not callable(c): + c = self.resolve(c) + props = config.pop('.', None) + # Check for valid identifiers + args = config.pop('[]', ()) + if args: + args = tuple([convert(o) for o in args]) + items = [(k, convert(config[k])) for k in config if valid_ident(k)] + kwargs = dict(items) + result = c(*args, **kwargs) + if props: + for n, v in props.items(): + setattr(result, n, convert(v)) + return result + + def __getitem__(self, key): + result = self.config[key] + if isinstance(result, dict) and '()' in result: + self.config[key] = result = self.configure_custom(result) + return result + + def inc_convert(self, value): + """Default converter for the inc:// protocol.""" + if not os.path.isabs(value): + value = os.path.join(self.base, value) + with codecs.open(value, 'r', encoding='utf-8') as f: + result = json.load(f) + return result + + +class SubprocessMixin(object): + """ + Mixin for running subprocesses and capturing their output + """ + def __init__(self, verbose=False, progress=None): + self.verbose = verbose + self.progress = progress + + def reader(self, stream, context): + """ + Read lines from a subprocess' output stream and either pass to a progress + callable (if specified) or write progress information to sys.stderr. + """ + progress = self.progress + verbose = self.verbose + while True: + s = stream.readline() + if not s: + break + if progress is not None: + progress(s, context) + else: + if not verbose: + sys.stderr.write('.') + else: + sys.stderr.write(s.decode('utf-8')) + sys.stderr.flush() + stream.close() + + def run_command(self, cmd, **kwargs): + p = subprocess.Popen(cmd, stdout=subprocess.PIPE, + stderr=subprocess.PIPE, **kwargs) + t1 = threading.Thread(target=self.reader, args=(p.stdout, 'stdout')) + t1.start() + t2 = threading.Thread(target=self.reader, args=(p.stderr, 'stderr')) + t2.start() + p.wait() + t1.join() + t2.join() + if self.progress is not None: + self.progress('done.', 'main') + elif self.verbose: + sys.stderr.write('done.\n') + return p + + +def normalize_name(name): + """Normalize a python package name a la PEP 503""" + # https://www.python.org/dev/peps/pep-0503/#normalized-names + return re.sub('[-_.]+', '-', name).lower() + +# def _get_pypirc_command(): + # """ + # Get the distutils command for interacting with PyPI configurations. + # :return: the command. + # """ + # from distutils.core import Distribution + # from distutils.config import PyPIRCCommand + # d = Distribution() + # return PyPIRCCommand(d) + +class PyPIRCFile(object): + + DEFAULT_REPOSITORY = 'https://upload.pypi.org/legacy/' + DEFAULT_REALM = 'pypi' + + def __init__(self, fn=None, url=None): + if fn is None: + fn = os.path.join(os.path.expanduser('~'), '.pypirc') + self.filename = fn + self.url = url + + def read(self): + result = {} + + if os.path.exists(self.filename): + repository = self.url or self.DEFAULT_REPOSITORY + + config = configparser.RawConfigParser() + config.read(self.filename) + sections = config.sections() + if 'distutils' in sections: + # let's get the list of servers + index_servers = config.get('distutils', 'index-servers') + _servers = [server.strip() for server in + index_servers.split('\n') + if server.strip() != ''] + if _servers == []: + # nothing set, let's try to get the default pypi + if 'pypi' in sections: + _servers = ['pypi'] + else: + for server in _servers: + result = {'server': server} + result['username'] = config.get(server, 'username') + + # optional params + for key, default in (('repository', self.DEFAULT_REPOSITORY), + ('realm', self.DEFAULT_REALM), + ('password', None)): + if config.has_option(server, key): + result[key] = config.get(server, key) + else: + result[key] = default + + # work around people having "repository" for the "pypi" + # section of their config set to the HTTP (rather than + # HTTPS) URL + if (server == 'pypi' and + repository in (self.DEFAULT_REPOSITORY, 'pypi')): + result['repository'] = self.DEFAULT_REPOSITORY + elif (result['server'] != repository and + result['repository'] != repository): + result = {} + elif 'server-login' in sections: + # old format + server = 'server-login' + if config.has_option(server, 'repository'): + repository = config.get(server, 'repository') + else: + repository = self.DEFAULT_REPOSITORY + result = { + 'username': config.get(server, 'username'), + 'password': config.get(server, 'password'), + 'repository': repository, + 'server': server, + 'realm': self.DEFAULT_REALM + } + return result + + def update(self, username, password): + # import pdb; pdb.set_trace() + config = configparser.RawConfigParser() + fn = self.filename + config.read(fn) + if not config.has_section('pypi'): + config.add_section('pypi') + config.set('pypi', 'username', username) + config.set('pypi', 'password', password) + with open(fn, 'w') as f: + config.write(f) + +def _load_pypirc(index): + """ + Read the PyPI access configuration as supported by distutils. + """ + return PyPIRCFile(url=index.url).read() + +def _store_pypirc(index): + PyPIRCFile().update(index.username, index.password) + +# +# get_platform()/get_host_platform() copied from Python 3.10.a0 source, with some minor +# tweaks +# + +def get_host_platform(): + """Return a string that identifies the current platform. This is used mainly to + distinguish platform-specific build directories and platform-specific built + distributions. Typically includes the OS name and version and the + architecture (as supplied by 'os.uname()'), although the exact information + included depends on the OS; eg. on Linux, the kernel version isn't + particularly important. + + Examples of returned values: + linux-i586 + linux-alpha (?) + solaris-2.6-sun4u + + Windows will return one of: + win-amd64 (64bit Windows on AMD64 (aka x86_64, Intel64, EM64T, etc) + win32 (all others - specifically, sys.platform is returned) + + For other non-POSIX platforms, currently just returns 'sys.platform'. + + """ + if os.name == 'nt': + if 'amd64' in sys.version.lower(): + return 'win-amd64' + if '(arm)' in sys.version.lower(): + return 'win-arm32' + if '(arm64)' in sys.version.lower(): + return 'win-arm64' + return sys.platform + + # Set for cross builds explicitly + if "_PYTHON_HOST_PLATFORM" in os.environ: + return os.environ["_PYTHON_HOST_PLATFORM"] + + if os.name != 'posix' or not hasattr(os, 'uname'): + # XXX what about the architecture? NT is Intel or Alpha, + # Mac OS is M68k or PPC, etc. + return sys.platform + + # Try to distinguish various flavours of Unix + + (osname, host, release, version, machine) = os.uname() + + # Convert the OS name to lowercase, remove '/' characters, and translate + # spaces (for "Power Macintosh") + osname = osname.lower().replace('/', '') + machine = machine.replace(' ', '_').replace('/', '-') + + if osname[:5] == 'linux': + # At least on Linux/Intel, 'machine' is the processor -- + # i386, etc. + # XXX what about Alpha, SPARC, etc? + return "%s-%s" % (osname, machine) + + elif osname[:5] == 'sunos': + if release[0] >= '5': # SunOS 5 == Solaris 2 + osname = 'solaris' + release = '%d.%s' % (int(release[0]) - 3, release[2:]) + # We can't use 'platform.architecture()[0]' because a + # bootstrap problem. We use a dict to get an error + # if some suspicious happens. + bitness = {2147483647:'32bit', 9223372036854775807:'64bit'} + machine += '.%s' % bitness[sys.maxsize] + # fall through to standard osname-release-machine representation + elif osname[:3] == 'aix': + from _aix_support import aix_platform + return aix_platform() + elif osname[:6] == 'cygwin': + osname = 'cygwin' + rel_re = re.compile (r'[\d.]+', re.ASCII) + m = rel_re.match(release) + if m: + release = m.group() + elif osname[:6] == 'darwin': + import _osx_support, distutils.sysconfig + osname, release, machine = _osx_support.get_platform_osx( + distutils.sysconfig.get_config_vars(), + osname, release, machine) + + return '%s-%s-%s' % (osname, release, machine) + + +_TARGET_TO_PLAT = { + 'x86' : 'win32', + 'x64' : 'win-amd64', + 'arm' : 'win-arm32', +} + + +def get_platform(): + if os.name != 'nt': + return get_host_platform() + cross_compilation_target = os.environ.get('VSCMD_ARG_TGT_ARCH') + if cross_compilation_target not in _TARGET_TO_PLAT: + return get_host_platform() + return _TARGET_TO_PLAT[cross_compilation_target] diff --git a/venv/Lib/site-packages/pip/_vendor/distlib/version.py b/venv/Lib/site-packages/pip/_vendor/distlib/version.py new file mode 100644 index 0000000..c7c8bb6 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/distlib/version.py @@ -0,0 +1,739 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2012-2017 The Python Software Foundation. +# See LICENSE.txt and CONTRIBUTORS.txt. +# +""" +Implementation of a flexible versioning scheme providing support for PEP-440, +setuptools-compatible and semantic versioning. +""" + +import logging +import re + +from .compat import string_types +from .util import parse_requirement + +__all__ = ['NormalizedVersion', 'NormalizedMatcher', + 'LegacyVersion', 'LegacyMatcher', + 'SemanticVersion', 'SemanticMatcher', + 'UnsupportedVersionError', 'get_scheme'] + +logger = logging.getLogger(__name__) + + +class UnsupportedVersionError(ValueError): + """This is an unsupported version.""" + pass + + +class Version(object): + def __init__(self, s): + self._string = s = s.strip() + self._parts = parts = self.parse(s) + assert isinstance(parts, tuple) + assert len(parts) > 0 + + def parse(self, s): + raise NotImplementedError('please implement in a subclass') + + def _check_compatible(self, other): + if type(self) != type(other): + raise TypeError('cannot compare %r and %r' % (self, other)) + + def __eq__(self, other): + self._check_compatible(other) + return self._parts == other._parts + + def __ne__(self, other): + return not self.__eq__(other) + + def __lt__(self, other): + self._check_compatible(other) + return self._parts < other._parts + + def __gt__(self, other): + return not (self.__lt__(other) or self.__eq__(other)) + + def __le__(self, other): + return self.__lt__(other) or self.__eq__(other) + + def __ge__(self, other): + return self.__gt__(other) or self.__eq__(other) + + # See http://docs.python.org/reference/datamodel#object.__hash__ + def __hash__(self): + return hash(self._parts) + + def __repr__(self): + return "%s('%s')" % (self.__class__.__name__, self._string) + + def __str__(self): + return self._string + + @property + def is_prerelease(self): + raise NotImplementedError('Please implement in subclasses.') + + +class Matcher(object): + version_class = None + + # value is either a callable or the name of a method + _operators = { + '<': lambda v, c, p: v < c, + '>': lambda v, c, p: v > c, + '<=': lambda v, c, p: v == c or v < c, + '>=': lambda v, c, p: v == c or v > c, + '==': lambda v, c, p: v == c, + '===': lambda v, c, p: v == c, + # by default, compatible => >=. + '~=': lambda v, c, p: v == c or v > c, + '!=': lambda v, c, p: v != c, + } + + # this is a method only to support alternative implementations + # via overriding + def parse_requirement(self, s): + return parse_requirement(s) + + def __init__(self, s): + if self.version_class is None: + raise ValueError('Please specify a version class') + self._string = s = s.strip() + r = self.parse_requirement(s) + if not r: + raise ValueError('Not valid: %r' % s) + self.name = r.name + self.key = self.name.lower() # for case-insensitive comparisons + clist = [] + if r.constraints: + # import pdb; pdb.set_trace() + for op, s in r.constraints: + if s.endswith('.*'): + if op not in ('==', '!='): + raise ValueError('\'.*\' not allowed for ' + '%r constraints' % op) + # Could be a partial version (e.g. for '2.*') which + # won't parse as a version, so keep it as a string + vn, prefix = s[:-2], True + # Just to check that vn is a valid version + self.version_class(vn) + else: + # Should parse as a version, so we can create an + # instance for the comparison + vn, prefix = self.version_class(s), False + clist.append((op, vn, prefix)) + self._parts = tuple(clist) + + def match(self, version): + """ + Check if the provided version matches the constraints. + + :param version: The version to match against this instance. + :type version: String or :class:`Version` instance. + """ + if isinstance(version, string_types): + version = self.version_class(version) + for operator, constraint, prefix in self._parts: + f = self._operators.get(operator) + if isinstance(f, string_types): + f = getattr(self, f) + if not f: + msg = ('%r not implemented ' + 'for %s' % (operator, self.__class__.__name__)) + raise NotImplementedError(msg) + if not f(version, constraint, prefix): + return False + return True + + @property + def exact_version(self): + result = None + if len(self._parts) == 1 and self._parts[0][0] in ('==', '==='): + result = self._parts[0][1] + return result + + def _check_compatible(self, other): + if type(self) != type(other) or self.name != other.name: + raise TypeError('cannot compare %s and %s' % (self, other)) + + def __eq__(self, other): + self._check_compatible(other) + return self.key == other.key and self._parts == other._parts + + def __ne__(self, other): + return not self.__eq__(other) + + # See http://docs.python.org/reference/datamodel#object.__hash__ + def __hash__(self): + return hash(self.key) + hash(self._parts) + + def __repr__(self): + return "%s(%r)" % (self.__class__.__name__, self._string) + + def __str__(self): + return self._string + + +PEP440_VERSION_RE = re.compile(r'^v?(\d+!)?(\d+(\.\d+)*)((a|b|c|rc)(\d+))?' + r'(\.(post)(\d+))?(\.(dev)(\d+))?' + r'(\+([a-zA-Z\d]+(\.[a-zA-Z\d]+)?))?$') + + +def _pep_440_key(s): + s = s.strip() + m = PEP440_VERSION_RE.match(s) + if not m: + raise UnsupportedVersionError('Not a valid version: %s' % s) + groups = m.groups() + nums = tuple(int(v) for v in groups[1].split('.')) + while len(nums) > 1 and nums[-1] == 0: + nums = nums[:-1] + + if not groups[0]: + epoch = 0 + else: + epoch = int(groups[0][:-1]) + pre = groups[4:6] + post = groups[7:9] + dev = groups[10:12] + local = groups[13] + if pre == (None, None): + pre = () + else: + pre = pre[0], int(pre[1]) + if post == (None, None): + post = () + else: + post = post[0], int(post[1]) + if dev == (None, None): + dev = () + else: + dev = dev[0], int(dev[1]) + if local is None: + local = () + else: + parts = [] + for part in local.split('.'): + # to ensure that numeric compares as > lexicographic, avoid + # comparing them directly, but encode a tuple which ensures + # correct sorting + if part.isdigit(): + part = (1, int(part)) + else: + part = (0, part) + parts.append(part) + local = tuple(parts) + if not pre: + # either before pre-release, or final release and after + if not post and dev: + # before pre-release + pre = ('a', -1) # to sort before a0 + else: + pre = ('z',) # to sort after all pre-releases + # now look at the state of post and dev. + if not post: + post = ('_',) # sort before 'a' + if not dev: + dev = ('final',) + + #print('%s -> %s' % (s, m.groups())) + return epoch, nums, pre, post, dev, local + + +_normalized_key = _pep_440_key + + +class NormalizedVersion(Version): + """A rational version. + + Good: + 1.2 # equivalent to "1.2.0" + 1.2.0 + 1.2a1 + 1.2.3a2 + 1.2.3b1 + 1.2.3c1 + 1.2.3.4 + TODO: fill this out + + Bad: + 1 # minimum two numbers + 1.2a # release level must have a release serial + 1.2.3b + """ + def parse(self, s): + result = _normalized_key(s) + # _normalized_key loses trailing zeroes in the release + # clause, since that's needed to ensure that X.Y == X.Y.0 == X.Y.0.0 + # However, PEP 440 prefix matching needs it: for example, + # (~= 1.4.5.0) matches differently to (~= 1.4.5.0.0). + m = PEP440_VERSION_RE.match(s) # must succeed + groups = m.groups() + self._release_clause = tuple(int(v) for v in groups[1].split('.')) + return result + + PREREL_TAGS = set(['a', 'b', 'c', 'rc', 'dev']) + + @property + def is_prerelease(self): + return any(t[0] in self.PREREL_TAGS for t in self._parts if t) + + +def _match_prefix(x, y): + x = str(x) + y = str(y) + if x == y: + return True + if not x.startswith(y): + return False + n = len(y) + return x[n] == '.' + + +class NormalizedMatcher(Matcher): + version_class = NormalizedVersion + + # value is either a callable or the name of a method + _operators = { + '~=': '_match_compatible', + '<': '_match_lt', + '>': '_match_gt', + '<=': '_match_le', + '>=': '_match_ge', + '==': '_match_eq', + '===': '_match_arbitrary', + '!=': '_match_ne', + } + + def _adjust_local(self, version, constraint, prefix): + if prefix: + strip_local = '+' not in constraint and version._parts[-1] + else: + # both constraint and version are + # NormalizedVersion instances. + # If constraint does not have a local component, + # ensure the version doesn't, either. + strip_local = not constraint._parts[-1] and version._parts[-1] + if strip_local: + s = version._string.split('+', 1)[0] + version = self.version_class(s) + return version, constraint + + def _match_lt(self, version, constraint, prefix): + version, constraint = self._adjust_local(version, constraint, prefix) + if version >= constraint: + return False + release_clause = constraint._release_clause + pfx = '.'.join([str(i) for i in release_clause]) + return not _match_prefix(version, pfx) + + def _match_gt(self, version, constraint, prefix): + version, constraint = self._adjust_local(version, constraint, prefix) + if version <= constraint: + return False + release_clause = constraint._release_clause + pfx = '.'.join([str(i) for i in release_clause]) + return not _match_prefix(version, pfx) + + def _match_le(self, version, constraint, prefix): + version, constraint = self._adjust_local(version, constraint, prefix) + return version <= constraint + + def _match_ge(self, version, constraint, prefix): + version, constraint = self._adjust_local(version, constraint, prefix) + return version >= constraint + + def _match_eq(self, version, constraint, prefix): + version, constraint = self._adjust_local(version, constraint, prefix) + if not prefix: + result = (version == constraint) + else: + result = _match_prefix(version, constraint) + return result + + def _match_arbitrary(self, version, constraint, prefix): + return str(version) == str(constraint) + + def _match_ne(self, version, constraint, prefix): + version, constraint = self._adjust_local(version, constraint, prefix) + if not prefix: + result = (version != constraint) + else: + result = not _match_prefix(version, constraint) + return result + + def _match_compatible(self, version, constraint, prefix): + version, constraint = self._adjust_local(version, constraint, prefix) + if version == constraint: + return True + if version < constraint: + return False +# if not prefix: +# return True + release_clause = constraint._release_clause + if len(release_clause) > 1: + release_clause = release_clause[:-1] + pfx = '.'.join([str(i) for i in release_clause]) + return _match_prefix(version, pfx) + +_REPLACEMENTS = ( + (re.compile('[.+-]$'), ''), # remove trailing puncts + (re.compile(r'^[.](\d)'), r'0.\1'), # .N -> 0.N at start + (re.compile('^[.-]'), ''), # remove leading puncts + (re.compile(r'^\((.*)\)$'), r'\1'), # remove parentheses + (re.compile(r'^v(ersion)?\s*(\d+)'), r'\2'), # remove leading v(ersion) + (re.compile(r'^r(ev)?\s*(\d+)'), r'\2'), # remove leading v(ersion) + (re.compile('[.]{2,}'), '.'), # multiple runs of '.' + (re.compile(r'\b(alfa|apha)\b'), 'alpha'), # misspelt alpha + (re.compile(r'\b(pre-alpha|prealpha)\b'), + 'pre.alpha'), # standardise + (re.compile(r'\(beta\)$'), 'beta'), # remove parentheses +) + +_SUFFIX_REPLACEMENTS = ( + (re.compile('^[:~._+-]+'), ''), # remove leading puncts + (re.compile('[,*")([\\]]'), ''), # remove unwanted chars + (re.compile('[~:+_ -]'), '.'), # replace illegal chars + (re.compile('[.]{2,}'), '.'), # multiple runs of '.' + (re.compile(r'\.$'), ''), # trailing '.' +) + +_NUMERIC_PREFIX = re.compile(r'(\d+(\.\d+)*)') + + +def _suggest_semantic_version(s): + """ + Try to suggest a semantic form for a version for which + _suggest_normalized_version couldn't come up with anything. + """ + result = s.strip().lower() + for pat, repl in _REPLACEMENTS: + result = pat.sub(repl, result) + if not result: + result = '0.0.0' + + # Now look for numeric prefix, and separate it out from + # the rest. + #import pdb; pdb.set_trace() + m = _NUMERIC_PREFIX.match(result) + if not m: + prefix = '0.0.0' + suffix = result + else: + prefix = m.groups()[0].split('.') + prefix = [int(i) for i in prefix] + while len(prefix) < 3: + prefix.append(0) + if len(prefix) == 3: + suffix = result[m.end():] + else: + suffix = '.'.join([str(i) for i in prefix[3:]]) + result[m.end():] + prefix = prefix[:3] + prefix = '.'.join([str(i) for i in prefix]) + suffix = suffix.strip() + if suffix: + #import pdb; pdb.set_trace() + # massage the suffix. + for pat, repl in _SUFFIX_REPLACEMENTS: + suffix = pat.sub(repl, suffix) + + if not suffix: + result = prefix + else: + sep = '-' if 'dev' in suffix else '+' + result = prefix + sep + suffix + if not is_semver(result): + result = None + return result + + +def _suggest_normalized_version(s): + """Suggest a normalized version close to the given version string. + + If you have a version string that isn't rational (i.e. NormalizedVersion + doesn't like it) then you might be able to get an equivalent (or close) + rational version from this function. + + This does a number of simple normalizations to the given string, based + on observation of versions currently in use on PyPI. Given a dump of + those version during PyCon 2009, 4287 of them: + - 2312 (53.93%) match NormalizedVersion without change + with the automatic suggestion + - 3474 (81.04%) match when using this suggestion method + + @param s {str} An irrational version string. + @returns A rational version string, or None, if couldn't determine one. + """ + try: + _normalized_key(s) + return s # already rational + except UnsupportedVersionError: + pass + + rs = s.lower() + + # part of this could use maketrans + for orig, repl in (('-alpha', 'a'), ('-beta', 'b'), ('alpha', 'a'), + ('beta', 'b'), ('rc', 'c'), ('-final', ''), + ('-pre', 'c'), + ('-release', ''), ('.release', ''), ('-stable', ''), + ('+', '.'), ('_', '.'), (' ', ''), ('.final', ''), + ('final', '')): + rs = rs.replace(orig, repl) + + # if something ends with dev or pre, we add a 0 + rs = re.sub(r"pre$", r"pre0", rs) + rs = re.sub(r"dev$", r"dev0", rs) + + # if we have something like "b-2" or "a.2" at the end of the + # version, that is probably beta, alpha, etc + # let's remove the dash or dot + rs = re.sub(r"([abc]|rc)[\-\.](\d+)$", r"\1\2", rs) + + # 1.0-dev-r371 -> 1.0.dev371 + # 0.1-dev-r79 -> 0.1.dev79 + rs = re.sub(r"[\-\.](dev)[\-\.]?r?(\d+)$", r".\1\2", rs) + + # Clean: 2.0.a.3, 2.0.b1, 0.9.0~c1 + rs = re.sub(r"[.~]?([abc])\.?", r"\1", rs) + + # Clean: v0.3, v1.0 + if rs.startswith('v'): + rs = rs[1:] + + # Clean leading '0's on numbers. + #TODO: unintended side-effect on, e.g., "2003.05.09" + # PyPI stats: 77 (~2%) better + rs = re.sub(r"\b0+(\d+)(?!\d)", r"\1", rs) + + # Clean a/b/c with no version. E.g. "1.0a" -> "1.0a0". Setuptools infers + # zero. + # PyPI stats: 245 (7.56%) better + rs = re.sub(r"(\d+[abc])$", r"\g<1>0", rs) + + # the 'dev-rNNN' tag is a dev tag + rs = re.sub(r"\.?(dev-r|dev\.r)\.?(\d+)$", r".dev\2", rs) + + # clean the - when used as a pre delimiter + rs = re.sub(r"-(a|b|c)(\d+)$", r"\1\2", rs) + + # a terminal "dev" or "devel" can be changed into ".dev0" + rs = re.sub(r"[\.\-](dev|devel)$", r".dev0", rs) + + # a terminal "dev" can be changed into ".dev0" + rs = re.sub(r"(?![\.\-])dev$", r".dev0", rs) + + # a terminal "final" or "stable" can be removed + rs = re.sub(r"(final|stable)$", "", rs) + + # The 'r' and the '-' tags are post release tags + # 0.4a1.r10 -> 0.4a1.post10 + # 0.9.33-17222 -> 0.9.33.post17222 + # 0.9.33-r17222 -> 0.9.33.post17222 + rs = re.sub(r"\.?(r|-|-r)\.?(\d+)$", r".post\2", rs) + + # Clean 'r' instead of 'dev' usage: + # 0.9.33+r17222 -> 0.9.33.dev17222 + # 1.0dev123 -> 1.0.dev123 + # 1.0.git123 -> 1.0.dev123 + # 1.0.bzr123 -> 1.0.dev123 + # 0.1a0dev.123 -> 0.1a0.dev123 + # PyPI stats: ~150 (~4%) better + rs = re.sub(r"\.?(dev|git|bzr)\.?(\d+)$", r".dev\2", rs) + + # Clean '.pre' (normalized from '-pre' above) instead of 'c' usage: + # 0.2.pre1 -> 0.2c1 + # 0.2-c1 -> 0.2c1 + # 1.0preview123 -> 1.0c123 + # PyPI stats: ~21 (0.62%) better + rs = re.sub(r"\.?(pre|preview|-c)(\d+)$", r"c\g<2>", rs) + + # Tcl/Tk uses "px" for their post release markers + rs = re.sub(r"p(\d+)$", r".post\1", rs) + + try: + _normalized_key(rs) + except UnsupportedVersionError: + rs = None + return rs + +# +# Legacy version processing (distribute-compatible) +# + +_VERSION_PART = re.compile(r'([a-z]+|\d+|[\.-])', re.I) +_VERSION_REPLACE = { + 'pre': 'c', + 'preview': 'c', + '-': 'final-', + 'rc': 'c', + 'dev': '@', + '': None, + '.': None, +} + + +def _legacy_key(s): + def get_parts(s): + result = [] + for p in _VERSION_PART.split(s.lower()): + p = _VERSION_REPLACE.get(p, p) + if p: + if '0' <= p[:1] <= '9': + p = p.zfill(8) + else: + p = '*' + p + result.append(p) + result.append('*final') + return result + + result = [] + for p in get_parts(s): + if p.startswith('*'): + if p < '*final': + while result and result[-1] == '*final-': + result.pop() + while result and result[-1] == '00000000': + result.pop() + result.append(p) + return tuple(result) + + +class LegacyVersion(Version): + def parse(self, s): + return _legacy_key(s) + + @property + def is_prerelease(self): + result = False + for x in self._parts: + if (isinstance(x, string_types) and x.startswith('*') and + x < '*final'): + result = True + break + return result + + +class LegacyMatcher(Matcher): + version_class = LegacyVersion + + _operators = dict(Matcher._operators) + _operators['~='] = '_match_compatible' + + numeric_re = re.compile(r'^(\d+(\.\d+)*)') + + def _match_compatible(self, version, constraint, prefix): + if version < constraint: + return False + m = self.numeric_re.match(str(constraint)) + if not m: + logger.warning('Cannot compute compatible match for version %s ' + ' and constraint %s', version, constraint) + return True + s = m.groups()[0] + if '.' in s: + s = s.rsplit('.', 1)[0] + return _match_prefix(version, s) + +# +# Semantic versioning +# + +_SEMVER_RE = re.compile(r'^(\d+)\.(\d+)\.(\d+)' + r'(-[a-z0-9]+(\.[a-z0-9-]+)*)?' + r'(\+[a-z0-9]+(\.[a-z0-9-]+)*)?$', re.I) + + +def is_semver(s): + return _SEMVER_RE.match(s) + + +def _semantic_key(s): + def make_tuple(s, absent): + if s is None: + result = (absent,) + else: + parts = s[1:].split('.') + # We can't compare ints and strings on Python 3, so fudge it + # by zero-filling numeric values so simulate a numeric comparison + result = tuple([p.zfill(8) if p.isdigit() else p for p in parts]) + return result + + m = is_semver(s) + if not m: + raise UnsupportedVersionError(s) + groups = m.groups() + major, minor, patch = [int(i) for i in groups[:3]] + # choose the '|' and '*' so that versions sort correctly + pre, build = make_tuple(groups[3], '|'), make_tuple(groups[5], '*') + return (major, minor, patch), pre, build + + +class SemanticVersion(Version): + def parse(self, s): + return _semantic_key(s) + + @property + def is_prerelease(self): + return self._parts[1][0] != '|' + + +class SemanticMatcher(Matcher): + version_class = SemanticVersion + + +class VersionScheme(object): + def __init__(self, key, matcher, suggester=None): + self.key = key + self.matcher = matcher + self.suggester = suggester + + def is_valid_version(self, s): + try: + self.matcher.version_class(s) + result = True + except UnsupportedVersionError: + result = False + return result + + def is_valid_matcher(self, s): + try: + self.matcher(s) + result = True + except UnsupportedVersionError: + result = False + return result + + def is_valid_constraint_list(self, s): + """ + Used for processing some metadata fields + """ + # See issue #140. Be tolerant of a single trailing comma. + if s.endswith(','): + s = s[:-1] + return self.is_valid_matcher('dummy_name (%s)' % s) + + def suggest(self, s): + if self.suggester is None: + result = None + else: + result = self.suggester(s) + return result + +_SCHEMES = { + 'normalized': VersionScheme(_normalized_key, NormalizedMatcher, + _suggest_normalized_version), + 'legacy': VersionScheme(_legacy_key, LegacyMatcher, lambda self, s: s), + 'semantic': VersionScheme(_semantic_key, SemanticMatcher, + _suggest_semantic_version), +} + +_SCHEMES['default'] = _SCHEMES['normalized'] + + +def get_scheme(name): + if name not in _SCHEMES: + raise ValueError('unknown scheme name: %r' % name) + return _SCHEMES[name] diff --git a/venv/Lib/site-packages/pip/_vendor/distlib/w32.exe b/venv/Lib/site-packages/pip/_vendor/distlib/w32.exe new file mode 100644 index 0000000000000000000000000000000000000000..e6439e9e45897365d5ac6a85a46864c158a225fd GIT binary patch literal 90112 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�gPVRVBXt_FM7e4<}XM;HRH{62JZSn^<*L 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 OB+yBqlfeHwf&T)jA)JE% literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_vendor/distlib/w64-arm.exe b/venv/Lib/site-packages/pip/_vendor/distlib/w64-arm.exe new file mode 100644 index 0000000000000000000000000000000000000000..70a2ec2685231fe363cbc6e9109fd4e8a09f6db4 GIT binary patch literal 166400 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�L=7(0pY6Ly8H~~{Ts}z` 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_vendor/distlib/w64.exe b/venv/Lib/site-packages/pip/_vendor/distlib/w64.exe new file mode 100644 index 0000000000000000000000000000000000000000..46139dbf9400b7bc0b64e6756ce17b4eb5fd7436 GIT binary patch literal 99840 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

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 = {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.tokenizer: + 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 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 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 = {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] + info = {"type": type_names[token['type']]} + 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 + """ + __slots__ = ("parser", "tree", "__startTagCache", "__endTagCache") + + def __init__(self, parser, tree): + self.parser = parser + self.tree = tree + self.__startTagCache = {} + self.__endTagCache = {} + + 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): + # Note the caching is done here rather than BoundMethodDispatcher as doing it there + # requires a circular reference to the Phase, and this ends up with a significant + # (CPython 2.7, 3.8) GC cost when parsing many short inputs + name = token["name"] + # In Py2, using `in` is quicker in general than try/except KeyError + # In Py3, `in` is quicker when there are few cache hits (typically short inputs) + if name in self.__startTagCache: + func = self.__startTagCache[name] + else: + func = self.__startTagCache[name] = self.startTagHandler[name] + # bound the cache size in case we get loads of unknown tags + while len(self.__startTagCache) > len(self.startTagHandler) * 1.1: + # this makes the eviction policy random on Py < 3.7 and FIFO >= 3.7 + self.__startTagCache.pop(next(iter(self.__startTagCache))) + return func(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): + # Note the caching is done here rather than BoundMethodDispatcher as doing it there + # requires a circular reference to the Phase, and this ends up with a significant + # (CPython 2.7, 3.8) GC cost when parsing many short inputs + name = token["name"] + # In Py2, using `in` is quicker in general than try/except KeyError + # In Py3, `in` is quicker when there are few cache hits (typically short inputs) + if name in self.__endTagCache: + func = self.__endTagCache[name] + else: + func = self.__endTagCache[name] = self.endTagHandler[name] + # bound the cache size in case we get loads of unknown tags + while len(self.__endTagCache) > len(self.endTagHandler) * 1.1: + # this makes the eviction policy random on Py < 3.7 and FIFO >= 3.7 + self.__endTagCache.pop(next(iter(self.__endTagCache))) + return func(token) + + class InitialPhase(Phase): + __slots__ = tuple() + + 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): + __slots__ = tuple() + + # 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): + __slots__ = tuple() + + 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"]}) + + startTagHandler = _utils.MethodDispatcher([ + ("html", startTagHtml), + ("head", startTagHead) + ]) + startTagHandler.default = startTagOther + + endTagHandler = _utils.MethodDispatcher([ + (("head", "body", "html", "br"), endTagImplyHead) + ]) + endTagHandler.default = endTagOther + + class InHeadPhase(Phase): + __slots__ = tuple() + + # 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")) + + startTagHandler = _utils.MethodDispatcher([ + ("html", startTagHtml), + ("title", startTagTitle), + (("noframes", "style"), startTagNoFramesStyle), + ("noscript", startTagNoscript), + ("script", startTagScript), + (("base", "basefont", "bgsound", "command", "link"), + startTagBaseLinkCommand), + ("meta", startTagMeta), + ("head", startTagHead) + ]) + startTagHandler.default = startTagOther + + endTagHandler = _utils.MethodDispatcher([ + ("head", endTagHead), + (("br", "html", "body"), endTagHtmlBodyBr) + ]) + endTagHandler.default = endTagOther + + class InHeadNoscriptPhase(Phase): + __slots__ = tuple() + + 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")) + + startTagHandler = _utils.MethodDispatcher([ + ("html", startTagHtml), + (("basefont", "bgsound", "link", "meta", "noframes", "style"), startTagBaseLinkCommand), + (("head", "noscript"), startTagHeadNoscript), + ]) + startTagHandler.default = startTagOther + + endTagHandler = _utils.MethodDispatcher([ + ("noscript", endTagNoscript), + ("br", endTagBr), + ]) + endTagHandler.default = endTagOther + + class AfterHeadPhase(Phase): + __slots__ = tuple() + + 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 + + startTagHandler = _utils.MethodDispatcher([ + ("html", startTagHtml), + ("body", startTagBody), + ("frameset", startTagFrameset), + (("base", "basefont", "bgsound", "link", "meta", "noframes", "script", + "style", "title"), + startTagFromHead), + ("head", startTagHead) + ]) + startTagHandler.default = startTagOther + endTagHandler = _utils.MethodDispatcher([(("body", "html", "br"), + endTagHtmlBodyBr)]) + endTagHandler.default = endTagOther + + class InBodyPhase(Phase): + # http://www.whatwg.org/specs/web-apps/current-work/#parsing-main-inbody + # the really-really-really-very crazy mode + __slots__ = ("processSpaceCharacters",) + + def __init__(self, *args, **kwargs): + super(InBodyPhase, self).__init__(*args, **kwargs) + # Set this to the default handler + self.processSpaceCharacters = self.processSpaceCharactersNonPre + + 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 ";
+	support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;
+
+	// Support: IE <=9 only
+	// IE <=9 replaces ";
+	support.option = !!div.lastChild;
+} )();
+
+
+// We have to close these tags to support XHTML (#13200)
+var wrapMap = {
+
+	// XHTML parsers do not magically insert elements in the
+	// same way that tag soup parsers do. So we cannot shorten
+	// this by omitting  or other required elements.
+	thead: [ 1, "", "
" ], + col: [ 2, "", "
" ], + tr: [ 2, "", "
" ], + td: [ 3, "", "
" ], + + _default: [ 0, "", "" ] +}; + +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +// Support: IE <=9 only +if ( !support.option ) { + wrapMap.optgroup = wrapMap.option = [ 1, "" ]; +} + + +function getAll( context, tag ) { + + // Support: IE <=9 - 11 only + // Use typeof to avoid zero-argument method invocation on host objects (#15151) + var ret; + + if ( typeof context.getElementsByTagName !== "undefined" ) { + ret = context.getElementsByTagName( tag || "*" ); + + } else if ( typeof context.querySelectorAll !== "undefined" ) { + ret = context.querySelectorAll( tag || "*" ); + + } else { + ret = []; + } + + if ( tag === undefined || tag && nodeName( context, tag ) ) { + return jQuery.merge( [ context ], ret ); + } + + return ret; +} + + +// Mark scripts as having already been evaluated +function setGlobalEval( elems, refElements ) { + var i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + dataPriv.set( + elems[ i ], + "globalEval", + !refElements || dataPriv.get( refElements[ i ], "globalEval" ) + ); + } +} + + +var rhtml = /<|&#?\w+;/; + +function buildFragment( elems, context, scripts, selection, ignored ) { + var elem, tmp, tag, wrap, attached, j, + fragment = context.createDocumentFragment(), + nodes = [], + i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + elem = elems[ i ]; + + if ( elem || elem === 0 ) { + + // Add nodes directly + if ( toType( elem ) === "object" ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); + + // Convert non-html into a text node + } else if ( !rhtml.test( elem ) ) { + nodes.push( context.createTextNode( elem ) ); + + // Convert html into DOM nodes + } else { + tmp = tmp || fragment.appendChild( context.createElement( "div" ) ); + + // Deserialize a standard representation + tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase(); + wrap = wrapMap[ tag ] || wrapMap._default; + tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ]; + + // Descend through wrappers to the right content + j = wrap[ 0 ]; + while ( j-- ) { + tmp = tmp.lastChild; + } + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, tmp.childNodes ); + + // Remember the top-level container + tmp = fragment.firstChild; + + // Ensure the created nodes are orphaned (#12392) + tmp.textContent = ""; + } + } + } + + // Remove wrapper from fragment + fragment.textContent = ""; + + i = 0; + while ( ( elem = nodes[ i++ ] ) ) { + + // Skip elements already in the context collection (trac-4087) + if ( selection && jQuery.inArray( elem, selection ) > -1 ) { + if ( ignored ) { + ignored.push( elem ); + } + continue; + } + + attached = isAttached( elem ); + + // Append to fragment + tmp = getAll( fragment.appendChild( elem ), "script" ); + + // Preserve script evaluation history + if ( attached ) { + setGlobalEval( tmp ); + } + + // Capture executables + if ( scripts ) { + j = 0; + while ( ( elem = tmp[ j++ ] ) ) { + if ( rscriptType.test( elem.type || "" ) ) { + scripts.push( elem ); + } + } + } + } + + return fragment; +} + + +var + rkeyEvent = /^key/, + rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/, + rtypenamespace = /^([^.]*)(?:\.(.+)|)/; + +function returnTrue() { + return true; +} + +function returnFalse() { + return false; +} + +// Support: IE <=9 - 11+ +// focus() and blur() are asynchronous, except when they are no-op. +// So expect focus to be synchronous when the element is already active, +// and blur to be synchronous when the element is not already active. +// (focus and blur are always synchronous in other supported browsers, +// this just defines when we can count on it). +function expectSync( elem, type ) { + return ( elem === safeActiveElement() ) === ( type === "focus" ); +} + +// Support: IE <=9 only +// Accessing document.activeElement can throw unexpectedly +// https://bugs.jquery.com/ticket/13393 +function safeActiveElement() { + try { + return document.activeElement; + } catch ( err ) { } +} + +function on( elem, types, selector, data, fn, one ) { + var origFn, type; + + // Types can be a map of types/handlers + if ( typeof types === "object" ) { + + // ( types-Object, selector, data ) + if ( typeof selector !== "string" ) { + + // ( types-Object, data ) + data = data || selector; + selector = undefined; + } + for ( type in types ) { + on( elem, type, selector, data, types[ type ], one ); + } + return elem; + } + + if ( data == null && fn == null ) { + + // ( types, fn ) + fn = selector; + data = selector = undefined; + } else if ( fn == null ) { + if ( typeof selector === "string" ) { + + // ( types, selector, fn ) + fn = data; + data = undefined; + } else { + + // ( types, data, fn ) + fn = data; + data = selector; + selector = undefined; + } + } + if ( fn === false ) { + fn = returnFalse; + } else if ( !fn ) { + return elem; + } + + if ( one === 1 ) { + origFn = fn; + fn = function( event ) { + + // Can use an empty set, since event contains the info + jQuery().off( event ); + return origFn.apply( this, arguments ); + }; + + // Use same guid so caller can remove using origFn + fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); + } + return elem.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + } ); +} + +/* + * Helper functions for managing events -- not part of the public interface. + * Props to Dean Edwards' addEvent library for many of the ideas. + */ +jQuery.event = { + + global: {}, + + add: function( elem, types, handler, data, selector ) { + + var handleObjIn, eventHandle, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.get( elem ); + + // Only attach events to objects that accept data + if ( !acceptData( elem ) ) { + return; + } + + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + selector = handleObjIn.selector; + } + + // Ensure that invalid selectors throw exceptions at attach time + // Evaluate against documentElement in case elem is a non-element node (e.g., document) + if ( selector ) { + jQuery.find.matchesSelector( documentElement, selector ); + } + + // Make sure that the handler has a unique ID, used to find/remove it later + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure and main handler, if this is the first + if ( !( events = elemData.events ) ) { + events = elemData.events = Object.create( null ); + } + if ( !( eventHandle = elemData.handle ) ) { + eventHandle = elemData.handle = function( e ) { + + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ? + jQuery.event.dispatch.apply( elem, arguments ) : undefined; + }; + } + + // Handle multiple events separated by a space + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // There *must* be a type, no attaching namespace-only handlers + if ( !type ) { + continue; + } + + // If event changes its type, use the special event handlers for the changed type + special = jQuery.event.special[ type ] || {}; + + // If selector defined, determine special event api type, otherwise given type + type = ( selector ? special.delegateType : special.bindType ) || type; + + // Update special based on newly reset type + special = jQuery.event.special[ type ] || {}; + + // handleObj is passed to all event handlers + handleObj = jQuery.extend( { + type: type, + origType: origType, + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + needsContext: selector && jQuery.expr.match.needsContext.test( selector ), + namespace: namespaces.join( "." ) + }, handleObjIn ); + + // Init the event handler queue if we're the first + if ( !( handlers = events[ type ] ) ) { + handlers = events[ type ] = []; + handlers.delegateCount = 0; + + // Only use addEventListener if the special events handler returns false + if ( !special.setup || + special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add to the element's handler list, delegates in front + if ( selector ) { + handlers.splice( handlers.delegateCount++, 0, handleObj ); + } else { + handlers.push( handleObj ); + } + + // Keep track of which events have ever been used, for event optimization + jQuery.event.global[ type ] = true; + } + + }, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, selector, mappedTypes ) { + + var j, origCount, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.hasData( elem ) && dataPriv.get( elem ); + + if ( !elemData || !( events = elemData.events ) ) { + return; + } + + // Once for each type.namespace in types; type may be omitted + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // Unbind all events (on this namespace, if provided) for the element + if ( !type ) { + for ( type in events ) { + jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); + } + continue; + } + + special = jQuery.event.special[ type ] || {}; + type = ( selector ? special.delegateType : special.bindType ) || type; + handlers = events[ type ] || []; + tmp = tmp[ 2 ] && + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ); + + // Remove matching events + origCount = j = handlers.length; + while ( j-- ) { + handleObj = handlers[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !tmp || tmp.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || + selector === "**" && handleObj.selector ) ) { + handlers.splice( j, 1 ); + + if ( handleObj.selector ) { + handlers.delegateCount--; + } + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + } + + // Remove generic event handler if we removed something and no more handlers exist + // (avoids potential for endless recursion during removal of special event handlers) + if ( origCount && !handlers.length ) { + if ( !special.teardown || + special.teardown.call( elem, namespaces, elemData.handle ) === false ) { + + jQuery.removeEvent( elem, type, elemData.handle ); + } + + delete events[ type ]; + } + } + + // Remove data and the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + dataPriv.remove( elem, "handle events" ); + } + }, + + dispatch: function( nativeEvent ) { + + var i, j, ret, matched, handleObj, handlerQueue, + args = new Array( arguments.length ), + + // Make a writable jQuery.Event from the native event object + event = jQuery.event.fix( nativeEvent ), + + handlers = ( + dataPriv.get( this, "events" ) || Object.create( null ) + )[ event.type ] || [], + special = jQuery.event.special[ event.type ] || {}; + + // Use the fix-ed jQuery.Event rather than the (read-only) native event + args[ 0 ] = event; + + for ( i = 1; i < arguments.length; i++ ) { + args[ i ] = arguments[ i ]; + } + + event.delegateTarget = this; + + // Call the preDispatch hook for the mapped type, and let it bail if desired + if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { + return; + } + + // Determine handlers + handlerQueue = jQuery.event.handlers.call( this, event, handlers ); + + // Run delegates first; they may want to stop propagation beneath us + i = 0; + while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) { + event.currentTarget = matched.elem; + + j = 0; + while ( ( handleObj = matched.handlers[ j++ ] ) && + !event.isImmediatePropagationStopped() ) { + + // If the event is namespaced, then each handler is only invoked if it is + // specially universal or its namespaces are a superset of the event's. + if ( !event.rnamespace || handleObj.namespace === false || + event.rnamespace.test( handleObj.namespace ) ) { + + event.handleObj = handleObj; + event.data = handleObj.data; + + ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle || + handleObj.handler ).apply( matched.elem, args ); + + if ( ret !== undefined ) { + if ( ( event.result = ret ) === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + // Call the postDispatch hook for the mapped type + if ( special.postDispatch ) { + special.postDispatch.call( this, event ); + } + + return event.result; + }, + + handlers: function( event, handlers ) { + var i, handleObj, sel, matchedHandlers, matchedSelectors, + handlerQueue = [], + delegateCount = handlers.delegateCount, + cur = event.target; + + // Find delegate handlers + if ( delegateCount && + + // Support: IE <=9 + // Black-hole SVG instance trees (trac-13180) + cur.nodeType && + + // Support: Firefox <=42 + // Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861) + // https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click + // Support: IE 11 only + // ...but not arrow key "clicks" of radio inputs, which can have `button` -1 (gh-2343) + !( event.type === "click" && event.button >= 1 ) ) { + + for ( ; cur !== this; cur = cur.parentNode || this ) { + + // Don't check non-elements (#13208) + // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) + if ( cur.nodeType === 1 && !( event.type === "click" && cur.disabled === true ) ) { + matchedHandlers = []; + matchedSelectors = {}; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + + // Don't conflict with Object.prototype properties (#13203) + sel = handleObj.selector + " "; + + if ( matchedSelectors[ sel ] === undefined ) { + matchedSelectors[ sel ] = handleObj.needsContext ? + jQuery( sel, this ).index( cur ) > -1 : + jQuery.find( sel, this, null, [ cur ] ).length; + } + if ( matchedSelectors[ sel ] ) { + matchedHandlers.push( handleObj ); + } + } + if ( matchedHandlers.length ) { + handlerQueue.push( { elem: cur, handlers: matchedHandlers } ); + } + } + } + } + + // Add the remaining (directly-bound) handlers + cur = this; + if ( delegateCount < handlers.length ) { + handlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } ); + } + + return handlerQueue; + }, + + addProp: function( name, hook ) { + Object.defineProperty( jQuery.Event.prototype, name, { + enumerable: true, + configurable: true, + + get: isFunction( hook ) ? + function() { + if ( this.originalEvent ) { + return hook( this.originalEvent ); + } + } : + function() { + if ( this.originalEvent ) { + return this.originalEvent[ name ]; + } + }, + + set: function( value ) { + Object.defineProperty( this, name, { + enumerable: true, + configurable: true, + writable: true, + value: value + } ); + } + } ); + }, + + fix: function( originalEvent ) { + return originalEvent[ jQuery.expando ] ? + originalEvent : + new jQuery.Event( originalEvent ); + }, + + special: { + load: { + + // Prevent triggered image.load events from bubbling to window.load + noBubble: true + }, + click: { + + // Utilize native event to ensure correct state for checkable inputs + setup: function( data ) { + + // For mutual compressibility with _default, replace `this` access with a local var. + // `|| data` is dead code meant only to preserve the variable through minification. + var el = this || data; + + // Claim the first handler + if ( rcheckableType.test( el.type ) && + el.click && nodeName( el, "input" ) ) { + + // dataPriv.set( el, "click", ... ) + leverageNative( el, "click", returnTrue ); + } + + // Return false to allow normal processing in the caller + return false; + }, + trigger: function( data ) { + + // For mutual compressibility with _default, replace `this` access with a local var. + // `|| data` is dead code meant only to preserve the variable through minification. + var el = this || data; + + // Force setup before triggering a click + if ( rcheckableType.test( el.type ) && + el.click && nodeName( el, "input" ) ) { + + leverageNative( el, "click" ); + } + + // Return non-false to allow normal event-path propagation + return true; + }, + + // For cross-browser consistency, suppress native .click() on links + // Also prevent it if we're currently inside a leveraged native-event stack + _default: function( event ) { + var target = event.target; + return rcheckableType.test( target.type ) && + target.click && nodeName( target, "input" ) && + dataPriv.get( target, "click" ) || + nodeName( target, "a" ); + } + }, + + beforeunload: { + postDispatch: function( event ) { + + // Support: Firefox 20+ + // Firefox doesn't alert if the returnValue field is not set. + if ( event.result !== undefined && event.originalEvent ) { + event.originalEvent.returnValue = event.result; + } + } + } + } +}; + +// Ensure the presence of an event listener that handles manually-triggered +// synthetic events by interrupting progress until reinvoked in response to +// *native* events that it fires directly, ensuring that state changes have +// already occurred before other listeners are invoked. +function leverageNative( el, type, expectSync ) { + + // Missing expectSync indicates a trigger call, which must force setup through jQuery.event.add + if ( !expectSync ) { + if ( dataPriv.get( el, type ) === undefined ) { + jQuery.event.add( el, type, returnTrue ); + } + return; + } + + // Register the controller as a special universal handler for all event namespaces + dataPriv.set( el, type, false ); + jQuery.event.add( el, type, { + namespace: false, + handler: function( event ) { + var notAsync, result, + saved = dataPriv.get( this, type ); + + if ( ( event.isTrigger & 1 ) && this[ type ] ) { + + // Interrupt processing of the outer synthetic .trigger()ed event + // Saved data should be false in such cases, but might be a leftover capture object + // from an async native handler (gh-4350) + if ( !saved.length ) { + + // Store arguments for use when handling the inner native event + // There will always be at least one argument (an event object), so this array + // will not be confused with a leftover capture object. + saved = slice.call( arguments ); + dataPriv.set( this, type, saved ); + + // Trigger the native event and capture its result + // Support: IE <=9 - 11+ + // focus() and blur() are asynchronous + notAsync = expectSync( this, type ); + this[ type ](); + result = dataPriv.get( this, type ); + if ( saved !== result || notAsync ) { + dataPriv.set( this, type, false ); + } else { + result = {}; + } + if ( saved !== result ) { + + // Cancel the outer synthetic event + event.stopImmediatePropagation(); + event.preventDefault(); + return result.value; + } + + // If this is an inner synthetic event for an event with a bubbling surrogate + // (focus or blur), assume that the surrogate already propagated from triggering the + // native event and prevent that from happening again here. + // This technically gets the ordering wrong w.r.t. to `.trigger()` (in which the + // bubbling surrogate propagates *after* the non-bubbling base), but that seems + // less bad than duplication. + } else if ( ( jQuery.event.special[ type ] || {} ).delegateType ) { + event.stopPropagation(); + } + + // If this is a native event triggered above, everything is now in order + // Fire an inner synthetic event with the original arguments + } else if ( saved.length ) { + + // ...and capture the result + dataPriv.set( this, type, { + value: jQuery.event.trigger( + + // Support: IE <=9 - 11+ + // Extend with the prototype to reset the above stopImmediatePropagation() + jQuery.extend( saved[ 0 ], jQuery.Event.prototype ), + saved.slice( 1 ), + this + ) + } ); + + // Abort handling of the native event + event.stopImmediatePropagation(); + } + } + } ); +} + +jQuery.removeEvent = function( elem, type, handle ) { + + // This "if" is needed for plain objects + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle ); + } +}; + +jQuery.Event = function( src, props ) { + + // Allow instantiation without the 'new' keyword + if ( !( this instanceof jQuery.Event ) ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = src.defaultPrevented || + src.defaultPrevented === undefined && + + // Support: Android <=2.3 only + src.returnValue === false ? + returnTrue : + returnFalse; + + // Create target properties + // Support: Safari <=6 - 7 only + // Target should not be a text node (#504, #13143) + this.target = ( src.target && src.target.nodeType === 3 ) ? + src.target.parentNode : + src.target; + + this.currentTarget = src.currentTarget; + this.relatedTarget = src.relatedTarget; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || Date.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + constructor: jQuery.Event, + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse, + isSimulated: false, + + preventDefault: function() { + var e = this.originalEvent; + + this.isDefaultPrevented = returnTrue; + + if ( e && !this.isSimulated ) { + e.preventDefault(); + } + }, + stopPropagation: function() { + var e = this.originalEvent; + + this.isPropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopPropagation(); + } + }, + stopImmediatePropagation: function() { + var e = this.originalEvent; + + this.isImmediatePropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopImmediatePropagation(); + } + + this.stopPropagation(); + } +}; + +// Includes all common event props including KeyEvent and MouseEvent specific props +jQuery.each( { + altKey: true, + bubbles: true, + cancelable: true, + changedTouches: true, + ctrlKey: true, + detail: true, + eventPhase: true, + metaKey: true, + pageX: true, + pageY: true, + shiftKey: true, + view: true, + "char": true, + code: true, + charCode: true, + key: true, + keyCode: true, + button: true, + buttons: true, + clientX: true, + clientY: true, + offsetX: true, + offsetY: true, + pointerId: true, + pointerType: true, + screenX: true, + screenY: true, + targetTouches: true, + toElement: true, + touches: true, + + which: function( event ) { + var button = event.button; + + // Add which for key events + if ( event.which == null && rkeyEvent.test( event.type ) ) { + return event.charCode != null ? event.charCode : event.keyCode; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + if ( !event.which && button !== undefined && rmouseEvent.test( event.type ) ) { + if ( button & 1 ) { + return 1; + } + + if ( button & 2 ) { + return 3; + } + + if ( button & 4 ) { + return 2; + } + + return 0; + } + + return event.which; + } +}, jQuery.event.addProp ); + +jQuery.each( { focus: "focusin", blur: "focusout" }, function( type, delegateType ) { + jQuery.event.special[ type ] = { + + // Utilize native event if possible so blur/focus sequence is correct + setup: function() { + + // Claim the first handler + // dataPriv.set( this, "focus", ... ) + // dataPriv.set( this, "blur", ... ) + leverageNative( this, type, expectSync ); + + // Return false to allow normal processing in the caller + return false; + }, + trigger: function() { + + // Force setup before trigger + leverageNative( this, type ); + + // Return non-false to allow normal event-path propagation + return true; + }, + + delegateType: delegateType + }; +} ); + +// Create mouseenter/leave events using mouseover/out and event-time checks +// so that event delegation works in jQuery. +// Do the same for pointerenter/pointerleave and pointerover/pointerout +// +// Support: Safari 7 only +// Safari sends mouseenter too often; see: +// https://bugs.chromium.org/p/chromium/issues/detail?id=470258 +// for the description of the bug (it existed in older Chrome versions as well). +jQuery.each( { + mouseenter: "mouseover", + mouseleave: "mouseout", + pointerenter: "pointerover", + pointerleave: "pointerout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + delegateType: fix, + bindType: fix, + + handle: function( event ) { + var ret, + target = this, + related = event.relatedTarget, + handleObj = event.handleObj; + + // For mouseenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) { + event.type = handleObj.origType; + ret = handleObj.handler.apply( this, arguments ); + event.type = fix; + } + return ret; + } + }; +} ); + +jQuery.fn.extend( { + + on: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn ); + }, + one: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn, 1 ); + }, + off: function( types, selector, fn ) { + var handleObj, type; + if ( types && types.preventDefault && types.handleObj ) { + + // ( event ) dispatched jQuery.Event + handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace ? + handleObj.origType + "." + handleObj.namespace : + handleObj.origType, + handleObj.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + + // ( types-object [, selector] ) + for ( type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; + } + if ( selector === false || typeof selector === "function" ) { + + // ( types [, fn] ) + fn = selector; + selector = undefined; + } + if ( fn === false ) { + fn = returnFalse; + } + return this.each( function() { + jQuery.event.remove( this, types, fn, selector ); + } ); + } +} ); + + +var + + // Support: IE <=10 - 11, Edge 12 - 13 only + // In IE/Edge using regex groups here causes severe slowdowns. + // See https://connect.microsoft.com/IE/feedback/details/1736512/ + rnoInnerhtml = /\s*$/g; + +// Prefer a tbody over its parent table for containing new rows +function manipulationTarget( elem, content ) { + if ( nodeName( elem, "table" ) && + nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ) { + + return jQuery( elem ).children( "tbody" )[ 0 ] || elem; + } + + return elem; +} + +// Replace/restore the type attribute of script elements for safe DOM manipulation +function disableScript( elem ) { + elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type; + return elem; +} +function restoreScript( elem ) { + if ( ( elem.type || "" ).slice( 0, 5 ) === "true/" ) { + elem.type = elem.type.slice( 5 ); + } else { + elem.removeAttribute( "type" ); + } + + return elem; +} + +function cloneCopyEvent( src, dest ) { + var i, l, type, pdataOld, udataOld, udataCur, events; + + if ( dest.nodeType !== 1 ) { + return; + } + + // 1. Copy private data: events, handlers, etc. + if ( dataPriv.hasData( src ) ) { + pdataOld = dataPriv.get( src ); + events = pdataOld.events; + + if ( events ) { + dataPriv.remove( dest, "handle events" ); + + for ( type in events ) { + for ( i = 0, l = events[ type ].length; i < l; i++ ) { + jQuery.event.add( dest, type, events[ type ][ i ] ); + } + } + } + } + + // 2. Copy user data + if ( dataUser.hasData( src ) ) { + udataOld = dataUser.access( src ); + udataCur = jQuery.extend( {}, udataOld ); + + dataUser.set( dest, udataCur ); + } +} + +// Fix IE bugs, see support tests +function fixInput( src, dest ) { + var nodeName = dest.nodeName.toLowerCase(); + + // Fails to persist the checked state of a cloned checkbox or radio button. + if ( nodeName === "input" && rcheckableType.test( src.type ) ) { + dest.checked = src.checked; + + // Fails to return the selected option to the default selected state when cloning options + } else if ( nodeName === "input" || nodeName === "textarea" ) { + dest.defaultValue = src.defaultValue; + } +} + +function domManip( collection, args, callback, ignored ) { + + // Flatten any nested arrays + args = flat( args ); + + var fragment, first, scripts, hasScripts, node, doc, + i = 0, + l = collection.length, + iNoClone = l - 1, + value = args[ 0 ], + valueIsFunction = isFunction( value ); + + // We can't cloneNode fragments that contain checked, in WebKit + if ( valueIsFunction || + ( l > 1 && typeof value === "string" && + !support.checkClone && rchecked.test( value ) ) ) { + return collection.each( function( index ) { + var self = collection.eq( index ); + if ( valueIsFunction ) { + args[ 0 ] = value.call( this, index, self.html() ); + } + domManip( self, args, callback, ignored ); + } ); + } + + if ( l ) { + fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored ); + first = fragment.firstChild; + + if ( fragment.childNodes.length === 1 ) { + fragment = first; + } + + // Require either new content or an interest in ignored elements to invoke the callback + if ( first || ignored ) { + scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); + hasScripts = scripts.length; + + // Use the original fragment for the last item + // instead of the first because it can end up + // being emptied incorrectly in certain situations (#8070). + for ( ; i < l; i++ ) { + node = fragment; + + if ( i !== iNoClone ) { + node = jQuery.clone( node, true, true ); + + // Keep references to cloned scripts for later restoration + if ( hasScripts ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( scripts, getAll( node, "script" ) ); + } + } + + callback.call( collection[ i ], node, i ); + } + + if ( hasScripts ) { + doc = scripts[ scripts.length - 1 ].ownerDocument; + + // Reenable scripts + jQuery.map( scripts, restoreScript ); + + // Evaluate executable scripts on first document insertion + for ( i = 0; i < hasScripts; i++ ) { + node = scripts[ i ]; + if ( rscriptType.test( node.type || "" ) && + !dataPriv.access( node, "globalEval" ) && + jQuery.contains( doc, node ) ) { + + if ( node.src && ( node.type || "" ).toLowerCase() !== "module" ) { + + // Optional AJAX dependency, but won't run scripts if not present + if ( jQuery._evalUrl && !node.noModule ) { + jQuery._evalUrl( node.src, { + nonce: node.nonce || node.getAttribute( "nonce" ) + }, doc ); + } + } else { + DOMEval( node.textContent.replace( rcleanScript, "" ), node, doc ); + } + } + } + } + } + } + + return collection; +} + +function remove( elem, selector, keepData ) { + var node, + nodes = selector ? jQuery.filter( selector, elem ) : elem, + i = 0; + + for ( ; ( node = nodes[ i ] ) != null; i++ ) { + if ( !keepData && node.nodeType === 1 ) { + jQuery.cleanData( getAll( node ) ); + } + + if ( node.parentNode ) { + if ( keepData && isAttached( node ) ) { + setGlobalEval( getAll( node, "script" ) ); + } + node.parentNode.removeChild( node ); + } + } + + return elem; +} + +jQuery.extend( { + htmlPrefilter: function( html ) { + return html; + }, + + clone: function( elem, dataAndEvents, deepDataAndEvents ) { + var i, l, srcElements, destElements, + clone = elem.cloneNode( true ), + inPage = isAttached( elem ); + + // Fix IE cloning issues + if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) && + !jQuery.isXMLDoc( elem ) ) { + + // We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2 + destElements = getAll( clone ); + srcElements = getAll( elem ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + fixInput( srcElements[ i ], destElements[ i ] ); + } + } + + // Copy the events from the original to the clone + if ( dataAndEvents ) { + if ( deepDataAndEvents ) { + srcElements = srcElements || getAll( elem ); + destElements = destElements || getAll( clone ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + cloneCopyEvent( srcElements[ i ], destElements[ i ] ); + } + } else { + cloneCopyEvent( elem, clone ); + } + } + + // Preserve script evaluation history + destElements = getAll( clone, "script" ); + if ( destElements.length > 0 ) { + setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); + } + + // Return the cloned set + return clone; + }, + + cleanData: function( elems ) { + var data, elem, type, + special = jQuery.event.special, + i = 0; + + for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) { + if ( acceptData( elem ) ) { + if ( ( data = elem[ dataPriv.expando ] ) ) { + if ( data.events ) { + for ( type in data.events ) { + if ( special[ type ] ) { + jQuery.event.remove( elem, type ); + + // This is a shortcut to avoid jQuery.event.remove's overhead + } else { + jQuery.removeEvent( elem, type, data.handle ); + } + } + } + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataPriv.expando ] = undefined; + } + if ( elem[ dataUser.expando ] ) { + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataUser.expando ] = undefined; + } + } + } + } +} ); + +jQuery.fn.extend( { + detach: function( selector ) { + return remove( this, selector, true ); + }, + + remove: function( selector ) { + return remove( this, selector ); + }, + + text: function( value ) { + return access( this, function( value ) { + return value === undefined ? + jQuery.text( this ) : + this.empty().each( function() { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + this.textContent = value; + } + } ); + }, null, value, arguments.length ); + }, + + append: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.appendChild( elem ); + } + } ); + }, + + prepend: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.insertBefore( elem, target.firstChild ); + } + } ); + }, + + before: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this ); + } + } ); + }, + + after: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this.nextSibling ); + } + } ); + }, + + empty: function() { + var elem, + i = 0; + + for ( ; ( elem = this[ i ] ) != null; i++ ) { + if ( elem.nodeType === 1 ) { + + // Prevent memory leaks + jQuery.cleanData( getAll( elem, false ) ); + + // Remove any remaining nodes + elem.textContent = ""; + } + } + + return this; + }, + + clone: function( dataAndEvents, deepDataAndEvents ) { + dataAndEvents = dataAndEvents == null ? false : dataAndEvents; + deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; + + return this.map( function() { + return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); + } ); + }, + + html: function( value ) { + return access( this, function( value ) { + var elem = this[ 0 ] || {}, + i = 0, + l = this.length; + + if ( value === undefined && elem.nodeType === 1 ) { + return elem.innerHTML; + } + + // See if we can take a shortcut and just use innerHTML + if ( typeof value === "string" && !rnoInnerhtml.test( value ) && + !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) { + + value = jQuery.htmlPrefilter( value ); + + try { + for ( ; i < l; i++ ) { + elem = this[ i ] || {}; + + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + elem.innerHTML = value; + } + } + + elem = 0; + + // If using innerHTML throws an exception, use the fallback method + } catch ( e ) {} + } + + if ( elem ) { + this.empty().append( value ); + } + }, null, value, arguments.length ); + }, + + replaceWith: function() { + var ignored = []; + + // Make the changes, replacing each non-ignored context element with the new content + return domManip( this, arguments, function( elem ) { + var parent = this.parentNode; + + if ( jQuery.inArray( this, ignored ) < 0 ) { + jQuery.cleanData( getAll( this ) ); + if ( parent ) { + parent.replaceChild( elem, this ); + } + } + + // Force callback invocation + }, ignored ); + } +} ); + +jQuery.each( { + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" +}, function( name, original ) { + jQuery.fn[ name ] = function( selector ) { + var elems, + ret = [], + insert = jQuery( selector ), + last = insert.length - 1, + i = 0; + + for ( ; i <= last; i++ ) { + elems = i === last ? this : this.clone( true ); + jQuery( insert[ i ] )[ original ]( elems ); + + // Support: Android <=4.0 only, PhantomJS 1 only + // .get() because push.apply(_, arraylike) throws on ancient WebKit + push.apply( ret, elems.get() ); + } + + return this.pushStack( ret ); + }; +} ); +var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" ); + +var getStyles = function( elem ) { + + // Support: IE <=11 only, Firefox <=30 (#15098, #14150) + // IE throws on elements created in popups + // FF meanwhile throws on frame elements through "defaultView.getComputedStyle" + var view = elem.ownerDocument.defaultView; + + if ( !view || !view.opener ) { + view = window; + } + + return view.getComputedStyle( elem ); + }; + +var swap = function( elem, options, callback ) { + var ret, name, + old = {}; + + // Remember the old values, and insert the new ones + for ( name in options ) { + old[ name ] = elem.style[ name ]; + elem.style[ name ] = options[ name ]; + } + + ret = callback.call( elem ); + + // Revert the old values + for ( name in options ) { + elem.style[ name ] = old[ name ]; + } + + return ret; +}; + + +var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" ); + + + +( function() { + + // Executing both pixelPosition & boxSizingReliable tests require only one layout + // so they're executed at the same time to save the second computation. + function computeStyleTests() { + + // This is a singleton, we need to execute it only once + if ( !div ) { + return; + } + + container.style.cssText = "position:absolute;left:-11111px;width:60px;" + + "margin-top:1px;padding:0;border:0"; + div.style.cssText = + "position:relative;display:block;box-sizing:border-box;overflow:scroll;" + + "margin:auto;border:1px;padding:1px;" + + "width:60%;top:1%"; + documentElement.appendChild( container ).appendChild( div ); + + var divStyle = window.getComputedStyle( div ); + pixelPositionVal = divStyle.top !== "1%"; + + // Support: Android 4.0 - 4.3 only, Firefox <=3 - 44 + reliableMarginLeftVal = roundPixelMeasures( divStyle.marginLeft ) === 12; + + // Support: Android 4.0 - 4.3 only, Safari <=9.1 - 10.1, iOS <=7.0 - 9.3 + // Some styles come back with percentage values, even though they shouldn't + div.style.right = "60%"; + pixelBoxStylesVal = roundPixelMeasures( divStyle.right ) === 36; + + // Support: IE 9 - 11 only + // Detect misreporting of content dimensions for box-sizing:border-box elements + boxSizingReliableVal = roundPixelMeasures( divStyle.width ) === 36; + + // Support: IE 9 only + // Detect overflow:scroll screwiness (gh-3699) + // Support: Chrome <=64 + // Don't get tricked when zoom affects offsetWidth (gh-4029) + div.style.position = "absolute"; + scrollboxSizeVal = roundPixelMeasures( div.offsetWidth / 3 ) === 12; + + documentElement.removeChild( container ); + + // Nullify the div so it wouldn't be stored in the memory and + // it will also be a sign that checks already performed + div = null; + } + + function roundPixelMeasures( measure ) { + return Math.round( parseFloat( measure ) ); + } + + var pixelPositionVal, boxSizingReliableVal, scrollboxSizeVal, pixelBoxStylesVal, + reliableTrDimensionsVal, reliableMarginLeftVal, + container = document.createElement( "div" ), + div = document.createElement( "div" ); + + // Finish early in limited (non-browser) environments + if ( !div.style ) { + return; + } + + // Support: IE <=9 - 11 only + // Style of cloned element affects source element cloned (#8908) + div.style.backgroundClip = "content-box"; + div.cloneNode( true ).style.backgroundClip = ""; + support.clearCloneStyle = div.style.backgroundClip === "content-box"; + + jQuery.extend( support, { + boxSizingReliable: function() { + computeStyleTests(); + return boxSizingReliableVal; + }, + pixelBoxStyles: function() { + computeStyleTests(); + return pixelBoxStylesVal; + }, + pixelPosition: function() { + computeStyleTests(); + return pixelPositionVal; + }, + reliableMarginLeft: function() { + computeStyleTests(); + return reliableMarginLeftVal; + }, + scrollboxSize: function() { + computeStyleTests(); + return scrollboxSizeVal; + }, + + // Support: IE 9 - 11+, Edge 15 - 18+ + // IE/Edge misreport `getComputedStyle` of table rows with width/height + // set in CSS while `offset*` properties report correct values. + // Behavior in IE 9 is more subtle than in newer versions & it passes + // some versions of this test; make sure not to make it pass there! + reliableTrDimensions: function() { + var table, tr, trChild, trStyle; + if ( reliableTrDimensionsVal == null ) { + table = document.createElement( "table" ); + tr = document.createElement( "tr" ); + trChild = document.createElement( "div" ); + + table.style.cssText = "position:absolute;left:-11111px"; + tr.style.height = "1px"; + trChild.style.height = "9px"; + + documentElement + .appendChild( table ) + .appendChild( tr ) + .appendChild( trChild ); + + trStyle = window.getComputedStyle( tr ); + reliableTrDimensionsVal = parseInt( trStyle.height ) > 3; + + documentElement.removeChild( table ); + } + return reliableTrDimensionsVal; + } + } ); +} )(); + + +function curCSS( elem, name, computed ) { + var width, minWidth, maxWidth, ret, + + // Support: Firefox 51+ + // Retrieving style before computed somehow + // fixes an issue with getting wrong values + // on detached elements + style = elem.style; + + computed = computed || getStyles( elem ); + + // getPropertyValue is needed for: + // .css('filter') (IE 9 only, #12537) + // .css('--customProperty) (#3144) + if ( computed ) { + ret = computed.getPropertyValue( name ) || computed[ name ]; + + if ( ret === "" && !isAttached( elem ) ) { + ret = jQuery.style( elem, name ); + } + + // A tribute to the "awesome hack by Dean Edwards" + // Android Browser returns percentage for some values, + // but width seems to be reliably pixels. + // This is against the CSSOM draft spec: + // https://drafts.csswg.org/cssom/#resolved-values + if ( !support.pixelBoxStyles() && rnumnonpx.test( ret ) && rboxStyle.test( name ) ) { + + // Remember the original values + width = style.width; + minWidth = style.minWidth; + maxWidth = style.maxWidth; + + // Put in the new values to get a computed value out + style.minWidth = style.maxWidth = style.width = ret; + ret = computed.width; + + // Revert the changed values + style.width = width; + style.minWidth = minWidth; + style.maxWidth = maxWidth; + } + } + + return ret !== undefined ? + + // Support: IE <=9 - 11 only + // IE returns zIndex value as an integer. + ret + "" : + ret; +} + + +function addGetHookIf( conditionFn, hookFn ) { + + // Define the hook, we'll check on the first run if it's really needed. + return { + get: function() { + if ( conditionFn() ) { + + // Hook not needed (or it's not possible to use it due + // to missing dependency), remove it. + delete this.get; + return; + } + + // Hook needed; redefine it so that the support test is not executed again. + return ( this.get = hookFn ).apply( this, arguments ); + } + }; +} + + +var cssPrefixes = [ "Webkit", "Moz", "ms" ], + emptyStyle = document.createElement( "div" ).style, + vendorProps = {}; + +// Return a vendor-prefixed property or undefined +function vendorPropName( name ) { + + // Check for vendor prefixed names + var capName = name[ 0 ].toUpperCase() + name.slice( 1 ), + i = cssPrefixes.length; + + while ( i-- ) { + name = cssPrefixes[ i ] + capName; + if ( name in emptyStyle ) { + return name; + } + } +} + +// Return a potentially-mapped jQuery.cssProps or vendor prefixed property +function finalPropName( name ) { + var final = jQuery.cssProps[ name ] || vendorProps[ name ]; + + if ( final ) { + return final; + } + if ( name in emptyStyle ) { + return name; + } + return vendorProps[ name ] = vendorPropName( name ) || name; +} + + +var + + // Swappable if display is none or starts with table + // except "table", "table-cell", or "table-caption" + // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display + rdisplayswap = /^(none|table(?!-c[ea]).+)/, + rcustomProp = /^--/, + cssShow = { position: "absolute", visibility: "hidden", display: "block" }, + cssNormalTransform = { + letterSpacing: "0", + fontWeight: "400" + }; + +function setPositiveNumber( _elem, value, subtract ) { + + // Any relative (+/-) values have already been + // normalized at this point + var matches = rcssNum.exec( value ); + return matches ? + + // Guard against undefined "subtract", e.g., when used as in cssHooks + Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) : + value; +} + +function boxModelAdjustment( elem, dimension, box, isBorderBox, styles, computedVal ) { + var i = dimension === "width" ? 1 : 0, + extra = 0, + delta = 0; + + // Adjustment may not be necessary + if ( box === ( isBorderBox ? "border" : "content" ) ) { + return 0; + } + + for ( ; i < 4; i += 2 ) { + + // Both box models exclude margin + if ( box === "margin" ) { + delta += jQuery.css( elem, box + cssExpand[ i ], true, styles ); + } + + // If we get here with a content-box, we're seeking "padding" or "border" or "margin" + if ( !isBorderBox ) { + + // Add padding + delta += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + + // For "border" or "margin", add border + if ( box !== "padding" ) { + delta += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + + // But still keep track of it otherwise + } else { + extra += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + + // If we get here with a border-box (content + padding + border), we're seeking "content" or + // "padding" or "margin" + } else { + + // For "content", subtract padding + if ( box === "content" ) { + delta -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + } + + // For "content" or "padding", subtract border + if ( box !== "margin" ) { + delta -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + } + } + + // Account for positive content-box scroll gutter when requested by providing computedVal + if ( !isBorderBox && computedVal >= 0 ) { + + // offsetWidth/offsetHeight is a rounded sum of content, padding, scroll gutter, and border + // Assuming integer scroll gutter, subtract the rest and round down + delta += Math.max( 0, Math.ceil( + elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - + computedVal - + delta - + extra - + 0.5 + + // If offsetWidth/offsetHeight is unknown, then we can't determine content-box scroll gutter + // Use an explicit zero to avoid NaN (gh-3964) + ) ) || 0; + } + + return delta; +} + +function getWidthOrHeight( elem, dimension, extra ) { + + // Start with computed style + var styles = getStyles( elem ), + + // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-4322). + // Fake content-box until we know it's needed to know the true value. + boxSizingNeeded = !support.boxSizingReliable() || extra, + isBorderBox = boxSizingNeeded && + jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + valueIsBorderBox = isBorderBox, + + val = curCSS( elem, dimension, styles ), + offsetProp = "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ); + + // Support: Firefox <=54 + // Return a confounding non-pixel value or feign ignorance, as appropriate. + if ( rnumnonpx.test( val ) ) { + if ( !extra ) { + return val; + } + val = "auto"; + } + + + // Support: IE 9 - 11 only + // Use offsetWidth/offsetHeight for when box sizing is unreliable. + // In those cases, the computed value can be trusted to be border-box. + if ( ( !support.boxSizingReliable() && isBorderBox || + + // Support: IE 10 - 11+, Edge 15 - 18+ + // IE/Edge misreport `getComputedStyle` of table rows with width/height + // set in CSS while `offset*` properties report correct values. + // Interestingly, in some cases IE 9 doesn't suffer from this issue. + !support.reliableTrDimensions() && nodeName( elem, "tr" ) || + + // Fall back to offsetWidth/offsetHeight when value is "auto" + // This happens for inline elements with no explicit setting (gh-3571) + val === "auto" || + + // Support: Android <=4.1 - 4.3 only + // Also use offsetWidth/offsetHeight for misreported inline dimensions (gh-3602) + !parseFloat( val ) && jQuery.css( elem, "display", false, styles ) === "inline" ) && + + // Make sure the element is visible & connected + elem.getClientRects().length ) { + + isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box"; + + // Where available, offsetWidth/offsetHeight approximate border box dimensions. + // Where not available (e.g., SVG), assume unreliable box-sizing and interpret the + // retrieved value as a content box dimension. + valueIsBorderBox = offsetProp in elem; + if ( valueIsBorderBox ) { + val = elem[ offsetProp ]; + } + } + + // Normalize "" and auto + val = parseFloat( val ) || 0; + + // Adjust for the element's box model + return ( val + + boxModelAdjustment( + elem, + dimension, + extra || ( isBorderBox ? "border" : "content" ), + valueIsBorderBox, + styles, + + // Provide the current computed size to request scroll gutter calculation (gh-3589) + val + ) + ) + "px"; +} + +jQuery.extend( { + + // Add in style property hooks for overriding the default + // behavior of getting and setting a style property + cssHooks: { + opacity: { + get: function( elem, computed ) { + if ( computed ) { + + // We should always get a number back from opacity + var ret = curCSS( elem, "opacity" ); + return ret === "" ? "1" : ret; + } + } + } + }, + + // Don't automatically add "px" to these possibly-unitless properties + cssNumber: { + "animationIterationCount": true, + "columnCount": true, + "fillOpacity": true, + "flexGrow": true, + "flexShrink": true, + "fontWeight": true, + "gridArea": true, + "gridColumn": true, + "gridColumnEnd": true, + "gridColumnStart": true, + "gridRow": true, + "gridRowEnd": true, + "gridRowStart": true, + "lineHeight": true, + "opacity": true, + "order": true, + "orphans": true, + "widows": true, + "zIndex": true, + "zoom": true + }, + + // Add in properties whose names you wish to fix before + // setting or getting the value + cssProps: {}, + + // Get and set the style property on a DOM Node + style: function( elem, name, value, extra ) { + + // Don't set styles on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { + return; + } + + // Make sure that we're working with the right name + var ret, type, hooks, + origName = camelCase( name ), + isCustomProp = rcustomProp.test( name ), + style = elem.style; + + // Make sure that we're working with the right name. We don't + // want to query the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Gets hook for the prefixed version, then unprefixed version + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // Check if we're setting a value + if ( value !== undefined ) { + type = typeof value; + + // Convert "+=" or "-=" to relative numbers (#7345) + if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) { + value = adjustCSS( elem, name, ret ); + + // Fixes bug #9237 + type = "number"; + } + + // Make sure that null and NaN values aren't set (#7116) + if ( value == null || value !== value ) { + return; + } + + // If a number was passed in, add the unit (except for certain CSS properties) + // The isCustomProp check can be removed in jQuery 4.0 when we only auto-append + // "px" to a few hardcoded values. + if ( type === "number" && !isCustomProp ) { + value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" ); + } + + // background-* props affect original clone's values + if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) { + style[ name ] = "inherit"; + } + + // If a hook was provided, use that value, otherwise just set the specified value + if ( !hooks || !( "set" in hooks ) || + ( value = hooks.set( elem, value, extra ) ) !== undefined ) { + + if ( isCustomProp ) { + style.setProperty( name, value ); + } else { + style[ name ] = value; + } + } + + } else { + + // If a hook was provided get the non-computed value from there + if ( hooks && "get" in hooks && + ( ret = hooks.get( elem, false, extra ) ) !== undefined ) { + + return ret; + } + + // Otherwise just get the value from the style object + return style[ name ]; + } + }, + + css: function( elem, name, extra, styles ) { + var val, num, hooks, + origName = camelCase( name ), + isCustomProp = rcustomProp.test( name ); + + // Make sure that we're working with the right name. We don't + // want to modify the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Try prefixed name followed by the unprefixed name + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // If a hook was provided get the computed value from there + if ( hooks && "get" in hooks ) { + val = hooks.get( elem, true, extra ); + } + + // Otherwise, if a way to get the computed value exists, use that + if ( val === undefined ) { + val = curCSS( elem, name, styles ); + } + + // Convert "normal" to computed value + if ( val === "normal" && name in cssNormalTransform ) { + val = cssNormalTransform[ name ]; + } + + // Make numeric if forced or a qualifier was provided and val looks numeric + if ( extra === "" || extra ) { + num = parseFloat( val ); + return extra === true || isFinite( num ) ? num || 0 : val; + } + + return val; + } +} ); + +jQuery.each( [ "height", "width" ], function( _i, dimension ) { + jQuery.cssHooks[ dimension ] = { + get: function( elem, computed, extra ) { + if ( computed ) { + + // Certain elements can have dimension info if we invisibly show them + // but it must have a current display style that would benefit + return rdisplayswap.test( jQuery.css( elem, "display" ) ) && + + // Support: Safari 8+ + // Table columns in Safari have non-zero offsetWidth & zero + // getBoundingClientRect().width unless display is changed. + // Support: IE <=11 only + // Running getBoundingClientRect on a disconnected node + // in IE throws an error. + ( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ? + swap( elem, cssShow, function() { + return getWidthOrHeight( elem, dimension, extra ); + } ) : + getWidthOrHeight( elem, dimension, extra ); + } + }, + + set: function( elem, value, extra ) { + var matches, + styles = getStyles( elem ), + + // Only read styles.position if the test has a chance to fail + // to avoid forcing a reflow. + scrollboxSizeBuggy = !support.scrollboxSize() && + styles.position === "absolute", + + // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-3991) + boxSizingNeeded = scrollboxSizeBuggy || extra, + isBorderBox = boxSizingNeeded && + jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + subtract = extra ? + boxModelAdjustment( + elem, + dimension, + extra, + isBorderBox, + styles + ) : + 0; + + // Account for unreliable border-box dimensions by comparing offset* to computed and + // faking a content-box to get border and padding (gh-3699) + if ( isBorderBox && scrollboxSizeBuggy ) { + subtract -= Math.ceil( + elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - + parseFloat( styles[ dimension ] ) - + boxModelAdjustment( elem, dimension, "border", false, styles ) - + 0.5 + ); + } + + // Convert to pixels if value adjustment is needed + if ( subtract && ( matches = rcssNum.exec( value ) ) && + ( matches[ 3 ] || "px" ) !== "px" ) { + + elem.style[ dimension ] = value; + value = jQuery.css( elem, dimension ); + } + + return setPositiveNumber( elem, value, subtract ); + } + }; +} ); + +jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft, + function( elem, computed ) { + if ( computed ) { + return ( parseFloat( curCSS( elem, "marginLeft" ) ) || + elem.getBoundingClientRect().left - + swap( elem, { marginLeft: 0 }, function() { + return elem.getBoundingClientRect().left; + } ) + ) + "px"; + } + } +); + +// These hooks are used by animate to expand properties +jQuery.each( { + margin: "", + padding: "", + border: "Width" +}, function( prefix, suffix ) { + jQuery.cssHooks[ prefix + suffix ] = { + expand: function( value ) { + var i = 0, + expanded = {}, + + // Assumes a single number if not a string + parts = typeof value === "string" ? value.split( " " ) : [ value ]; + + for ( ; i < 4; i++ ) { + expanded[ prefix + cssExpand[ i ] + suffix ] = + parts[ i ] || parts[ i - 2 ] || parts[ 0 ]; + } + + return expanded; + } + }; + + if ( prefix !== "margin" ) { + jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber; + } +} ); + +jQuery.fn.extend( { + css: function( name, value ) { + return access( this, function( elem, name, value ) { + var styles, len, + map = {}, + i = 0; + + if ( Array.isArray( name ) ) { + styles = getStyles( elem ); + len = name.length; + + for ( ; i < len; i++ ) { + map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); + } + + return map; + } + + return value !== undefined ? + jQuery.style( elem, name, value ) : + jQuery.css( elem, name ); + }, name, value, arguments.length > 1 ); + } +} ); + + +function Tween( elem, options, prop, end, easing ) { + return new Tween.prototype.init( elem, options, prop, end, easing ); +} +jQuery.Tween = Tween; + +Tween.prototype = { + constructor: Tween, + init: function( elem, options, prop, end, easing, unit ) { + this.elem = elem; + this.prop = prop; + this.easing = easing || jQuery.easing._default; + this.options = options; + this.start = this.now = this.cur(); + this.end = end; + this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" ); + }, + cur: function() { + var hooks = Tween.propHooks[ this.prop ]; + + return hooks && hooks.get ? + hooks.get( this ) : + Tween.propHooks._default.get( this ); + }, + run: function( percent ) { + var eased, + hooks = Tween.propHooks[ this.prop ]; + + if ( this.options.duration ) { + this.pos = eased = jQuery.easing[ this.easing ]( + percent, this.options.duration * percent, 0, 1, this.options.duration + ); + } else { + this.pos = eased = percent; + } + this.now = ( this.end - this.start ) * eased + this.start; + + if ( this.options.step ) { + this.options.step.call( this.elem, this.now, this ); + } + + if ( hooks && hooks.set ) { + hooks.set( this ); + } else { + Tween.propHooks._default.set( this ); + } + return this; + } +}; + +Tween.prototype.init.prototype = Tween.prototype; + +Tween.propHooks = { + _default: { + get: function( tween ) { + var result; + + // Use a property on the element directly when it is not a DOM element, + // or when there is no matching style property that exists. + if ( tween.elem.nodeType !== 1 || + tween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) { + return tween.elem[ tween.prop ]; + } + + // Passing an empty string as a 3rd parameter to .css will automatically + // attempt a parseFloat and fallback to a string if the parse fails. + // Simple values such as "10px" are parsed to Float; + // complex values such as "rotate(1rad)" are returned as-is. + result = jQuery.css( tween.elem, tween.prop, "" ); + + // Empty strings, null, undefined and "auto" are converted to 0. + return !result || result === "auto" ? 0 : result; + }, + set: function( tween ) { + + // Use step hook for back compat. + // Use cssHook if its there. + // Use .style if available and use plain properties where available. + if ( jQuery.fx.step[ tween.prop ] ) { + jQuery.fx.step[ tween.prop ]( tween ); + } else if ( tween.elem.nodeType === 1 && ( + jQuery.cssHooks[ tween.prop ] || + tween.elem.style[ finalPropName( tween.prop ) ] != null ) ) { + jQuery.style( tween.elem, tween.prop, tween.now + tween.unit ); + } else { + tween.elem[ tween.prop ] = tween.now; + } + } + } +}; + +// Support: IE <=9 only +// Panic based approach to setting things on disconnected nodes +Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = { + set: function( tween ) { + if ( tween.elem.nodeType && tween.elem.parentNode ) { + tween.elem[ tween.prop ] = tween.now; + } + } +}; + +jQuery.easing = { + linear: function( p ) { + return p; + }, + swing: function( p ) { + return 0.5 - Math.cos( p * Math.PI ) / 2; + }, + _default: "swing" +}; + +jQuery.fx = Tween.prototype.init; + +// Back compat <1.8 extension point +jQuery.fx.step = {}; + + + + +var + fxNow, inProgress, + rfxtypes = /^(?:toggle|show|hide)$/, + rrun = /queueHooks$/; + +function schedule() { + if ( inProgress ) { + if ( document.hidden === false && window.requestAnimationFrame ) { + window.requestAnimationFrame( schedule ); + } else { + window.setTimeout( schedule, jQuery.fx.interval ); + } + + jQuery.fx.tick(); + } +} + +// Animations created synchronously will run synchronously +function createFxNow() { + window.setTimeout( function() { + fxNow = undefined; + } ); + return ( fxNow = Date.now() ); +} + +// Generate parameters to create a standard animation +function genFx( type, includeWidth ) { + var which, + i = 0, + attrs = { height: type }; + + // If we include width, step value is 1 to do all cssExpand values, + // otherwise step value is 2 to skip over Left and Right + includeWidth = includeWidth ? 1 : 0; + for ( ; i < 4; i += 2 - includeWidth ) { + which = cssExpand[ i ]; + attrs[ "margin" + which ] = attrs[ "padding" + which ] = type; + } + + if ( includeWidth ) { + attrs.opacity = attrs.width = type; + } + + return attrs; +} + +function createTween( value, prop, animation ) { + var tween, + collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ), + index = 0, + length = collection.length; + for ( ; index < length; index++ ) { + if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) { + + // We're done with this property + return tween; + } + } +} + +function defaultPrefilter( elem, props, opts ) { + var prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display, + isBox = "width" in props || "height" in props, + anim = this, + orig = {}, + style = elem.style, + hidden = elem.nodeType && isHiddenWithinTree( elem ), + dataShow = dataPriv.get( elem, "fxshow" ); + + // Queue-skipping animations hijack the fx hooks + if ( !opts.queue ) { + hooks = jQuery._queueHooks( elem, "fx" ); + if ( hooks.unqueued == null ) { + hooks.unqueued = 0; + oldfire = hooks.empty.fire; + hooks.empty.fire = function() { + if ( !hooks.unqueued ) { + oldfire(); + } + }; + } + hooks.unqueued++; + + anim.always( function() { + + // Ensure the complete handler is called before this completes + anim.always( function() { + hooks.unqueued--; + if ( !jQuery.queue( elem, "fx" ).length ) { + hooks.empty.fire(); + } + } ); + } ); + } + + // Detect show/hide animations + for ( prop in props ) { + value = props[ prop ]; + if ( rfxtypes.test( value ) ) { + delete props[ prop ]; + toggle = toggle || value === "toggle"; + if ( value === ( hidden ? "hide" : "show" ) ) { + + // Pretend to be hidden if this is a "show" and + // there is still data from a stopped show/hide + if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) { + hidden = true; + + // Ignore all other no-op show/hide data + } else { + continue; + } + } + orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop ); + } + } + + // Bail out if this is a no-op like .hide().hide() + propTween = !jQuery.isEmptyObject( props ); + if ( !propTween && jQuery.isEmptyObject( orig ) ) { + return; + } + + // Restrict "overflow" and "display" styles during box animations + if ( isBox && elem.nodeType === 1 ) { + + // Support: IE <=9 - 11, Edge 12 - 15 + // Record all 3 overflow attributes because IE does not infer the shorthand + // from identically-valued overflowX and overflowY and Edge just mirrors + // the overflowX value there. + opts.overflow = [ style.overflow, style.overflowX, style.overflowY ]; + + // Identify a display type, preferring old show/hide data over the CSS cascade + restoreDisplay = dataShow && dataShow.display; + if ( restoreDisplay == null ) { + restoreDisplay = dataPriv.get( elem, "display" ); + } + display = jQuery.css( elem, "display" ); + if ( display === "none" ) { + if ( restoreDisplay ) { + display = restoreDisplay; + } else { + + // Get nonempty value(s) by temporarily forcing visibility + showHide( [ elem ], true ); + restoreDisplay = elem.style.display || restoreDisplay; + display = jQuery.css( elem, "display" ); + showHide( [ elem ] ); + } + } + + // Animate inline elements as inline-block + if ( display === "inline" || display === "inline-block" && restoreDisplay != null ) { + if ( jQuery.css( elem, "float" ) === "none" ) { + + // Restore the original display value at the end of pure show/hide animations + if ( !propTween ) { + anim.done( function() { + style.display = restoreDisplay; + } ); + if ( restoreDisplay == null ) { + display = style.display; + restoreDisplay = display === "none" ? "" : display; + } + } + style.display = "inline-block"; + } + } + } + + if ( opts.overflow ) { + style.overflow = "hidden"; + anim.always( function() { + style.overflow = opts.overflow[ 0 ]; + style.overflowX = opts.overflow[ 1 ]; + style.overflowY = opts.overflow[ 2 ]; + } ); + } + + // Implement show/hide animations + propTween = false; + for ( prop in orig ) { + + // General show/hide setup for this element animation + if ( !propTween ) { + if ( dataShow ) { + if ( "hidden" in dataShow ) { + hidden = dataShow.hidden; + } + } else { + dataShow = dataPriv.access( elem, "fxshow", { display: restoreDisplay } ); + } + + // Store hidden/visible for toggle so `.stop().toggle()` "reverses" + if ( toggle ) { + dataShow.hidden = !hidden; + } + + // Show elements before animating them + if ( hidden ) { + showHide( [ elem ], true ); + } + + /* eslint-disable no-loop-func */ + + anim.done( function() { + + /* eslint-enable no-loop-func */ + + // The final step of a "hide" animation is actually hiding the element + if ( !hidden ) { + showHide( [ elem ] ); + } + dataPriv.remove( elem, "fxshow" ); + for ( prop in orig ) { + jQuery.style( elem, prop, orig[ prop ] ); + } + } ); + } + + // Per-property setup + propTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim ); + if ( !( prop in dataShow ) ) { + dataShow[ prop ] = propTween.start; + if ( hidden ) { + propTween.end = propTween.start; + propTween.start = 0; + } + } + } +} + +function propFilter( props, specialEasing ) { + var index, name, easing, value, hooks; + + // camelCase, specialEasing and expand cssHook pass + for ( index in props ) { + name = camelCase( index ); + easing = specialEasing[ name ]; + value = props[ index ]; + if ( Array.isArray( value ) ) { + easing = value[ 1 ]; + value = props[ index ] = value[ 0 ]; + } + + if ( index !== name ) { + props[ name ] = value; + delete props[ index ]; + } + + hooks = jQuery.cssHooks[ name ]; + if ( hooks && "expand" in hooks ) { + value = hooks.expand( value ); + delete props[ name ]; + + // Not quite $.extend, this won't overwrite existing keys. + // Reusing 'index' because we have the correct "name" + for ( index in value ) { + if ( !( index in props ) ) { + props[ index ] = value[ index ]; + specialEasing[ index ] = easing; + } + } + } else { + specialEasing[ name ] = easing; + } + } +} + +function Animation( elem, properties, options ) { + var result, + stopped, + index = 0, + length = Animation.prefilters.length, + deferred = jQuery.Deferred().always( function() { + + // Don't match elem in the :animated selector + delete tick.elem; + } ), + tick = function() { + if ( stopped ) { + return false; + } + var currentTime = fxNow || createFxNow(), + remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ), + + // Support: Android 2.3 only + // Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497) + temp = remaining / animation.duration || 0, + percent = 1 - temp, + index = 0, + length = animation.tweens.length; + + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( percent ); + } + + deferred.notifyWith( elem, [ animation, percent, remaining ] ); + + // If there's more to do, yield + if ( percent < 1 && length ) { + return remaining; + } + + // If this was an empty animation, synthesize a final progress notification + if ( !length ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + } + + // Resolve the animation and report its conclusion + deferred.resolveWith( elem, [ animation ] ); + return false; + }, + animation = deferred.promise( { + elem: elem, + props: jQuery.extend( {}, properties ), + opts: jQuery.extend( true, { + specialEasing: {}, + easing: jQuery.easing._default + }, options ), + originalProperties: properties, + originalOptions: options, + startTime: fxNow || createFxNow(), + duration: options.duration, + tweens: [], + createTween: function( prop, end ) { + var tween = jQuery.Tween( elem, animation.opts, prop, end, + animation.opts.specialEasing[ prop ] || animation.opts.easing ); + animation.tweens.push( tween ); + return tween; + }, + stop: function( gotoEnd ) { + var index = 0, + + // If we are going to the end, we want to run all the tweens + // otherwise we skip this part + length = gotoEnd ? animation.tweens.length : 0; + if ( stopped ) { + return this; + } + stopped = true; + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( 1 ); + } + + // Resolve when we played the last frame; otherwise, reject + if ( gotoEnd ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + deferred.resolveWith( elem, [ animation, gotoEnd ] ); + } else { + deferred.rejectWith( elem, [ animation, gotoEnd ] ); + } + return this; + } + } ), + props = animation.props; + + propFilter( props, animation.opts.specialEasing ); + + for ( ; index < length; index++ ) { + result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts ); + if ( result ) { + if ( isFunction( result.stop ) ) { + jQuery._queueHooks( animation.elem, animation.opts.queue ).stop = + result.stop.bind( result ); + } + return result; + } + } + + jQuery.map( props, createTween, animation ); + + if ( isFunction( animation.opts.start ) ) { + animation.opts.start.call( elem, animation ); + } + + // Attach callbacks from options + animation + .progress( animation.opts.progress ) + .done( animation.opts.done, animation.opts.complete ) + .fail( animation.opts.fail ) + .always( animation.opts.always ); + + jQuery.fx.timer( + jQuery.extend( tick, { + elem: elem, + anim: animation, + queue: animation.opts.queue + } ) + ); + + return animation; +} + +jQuery.Animation = jQuery.extend( Animation, { + + tweeners: { + "*": [ function( prop, value ) { + var tween = this.createTween( prop, value ); + adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween ); + return tween; + } ] + }, + + tweener: function( props, callback ) { + if ( isFunction( props ) ) { + callback = props; + props = [ "*" ]; + } else { + props = props.match( rnothtmlwhite ); + } + + var prop, + index = 0, + length = props.length; + + for ( ; index < length; index++ ) { + prop = props[ index ]; + Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || []; + Animation.tweeners[ prop ].unshift( callback ); + } + }, + + prefilters: [ defaultPrefilter ], + + prefilter: function( callback, prepend ) { + if ( prepend ) { + Animation.prefilters.unshift( callback ); + } else { + Animation.prefilters.push( callback ); + } + } +} ); + +jQuery.speed = function( speed, easing, fn ) { + var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : { + complete: fn || !fn && easing || + isFunction( speed ) && speed, + duration: speed, + easing: fn && easing || easing && !isFunction( easing ) && easing + }; + + // Go to the end state if fx are off + if ( jQuery.fx.off ) { + opt.duration = 0; + + } else { + if ( typeof opt.duration !== "number" ) { + if ( opt.duration in jQuery.fx.speeds ) { + opt.duration = jQuery.fx.speeds[ opt.duration ]; + + } else { + opt.duration = jQuery.fx.speeds._default; + } + } + } + + // Normalize opt.queue - true/undefined/null -> "fx" + if ( opt.queue == null || opt.queue === true ) { + opt.queue = "fx"; + } + + // Queueing + opt.old = opt.complete; + + opt.complete = function() { + if ( isFunction( opt.old ) ) { + opt.old.call( this ); + } + + if ( opt.queue ) { + jQuery.dequeue( this, opt.queue ); + } + }; + + return opt; +}; + +jQuery.fn.extend( { + fadeTo: function( speed, to, easing, callback ) { + + // Show any hidden elements after setting opacity to 0 + return this.filter( isHiddenWithinTree ).css( "opacity", 0 ).show() + + // Animate to the value specified + .end().animate( { opacity: to }, speed, easing, callback ); + }, + animate: function( prop, speed, easing, callback ) { + var empty = jQuery.isEmptyObject( prop ), + optall = jQuery.speed( speed, easing, callback ), + doAnimation = function() { + + // Operate on a copy of prop so per-property easing won't be lost + var anim = Animation( this, jQuery.extend( {}, prop ), optall ); + + // Empty animations, or finishing resolves immediately + if ( empty || dataPriv.get( this, "finish" ) ) { + anim.stop( true ); + } + }; + doAnimation.finish = doAnimation; + + return empty || optall.queue === false ? + this.each( doAnimation ) : + this.queue( optall.queue, doAnimation ); + }, + stop: function( type, clearQueue, gotoEnd ) { + var stopQueue = function( hooks ) { + var stop = hooks.stop; + delete hooks.stop; + stop( gotoEnd ); + }; + + if ( typeof type !== "string" ) { + gotoEnd = clearQueue; + clearQueue = type; + type = undefined; + } + if ( clearQueue ) { + this.queue( type || "fx", [] ); + } + + return this.each( function() { + var dequeue = true, + index = type != null && type + "queueHooks", + timers = jQuery.timers, + data = dataPriv.get( this ); + + if ( index ) { + if ( data[ index ] && data[ index ].stop ) { + stopQueue( data[ index ] ); + } + } else { + for ( index in data ) { + if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) { + stopQueue( data[ index ] ); + } + } + } + + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && + ( type == null || timers[ index ].queue === type ) ) { + + timers[ index ].anim.stop( gotoEnd ); + dequeue = false; + timers.splice( index, 1 ); + } + } + + // Start the next in the queue if the last step wasn't forced. + // Timers currently will call their complete callbacks, which + // will dequeue but only if they were gotoEnd. + if ( dequeue || !gotoEnd ) { + jQuery.dequeue( this, type ); + } + } ); + }, + finish: function( type ) { + if ( type !== false ) { + type = type || "fx"; + } + return this.each( function() { + var index, + data = dataPriv.get( this ), + queue = data[ type + "queue" ], + hooks = data[ type + "queueHooks" ], + timers = jQuery.timers, + length = queue ? queue.length : 0; + + // Enable finishing flag on private data + data.finish = true; + + // Empty the queue first + jQuery.queue( this, type, [] ); + + if ( hooks && hooks.stop ) { + hooks.stop.call( this, true ); + } + + // Look for any active animations, and finish them + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && timers[ index ].queue === type ) { + timers[ index ].anim.stop( true ); + timers.splice( index, 1 ); + } + } + + // Look for any animations in the old queue and finish them + for ( index = 0; index < length; index++ ) { + if ( queue[ index ] && queue[ index ].finish ) { + queue[ index ].finish.call( this ); + } + } + + // Turn off finishing flag + delete data.finish; + } ); + } +} ); + +jQuery.each( [ "toggle", "show", "hide" ], function( _i, name ) { + var cssFn = jQuery.fn[ name ]; + jQuery.fn[ name ] = function( speed, easing, callback ) { + return speed == null || typeof speed === "boolean" ? + cssFn.apply( this, arguments ) : + this.animate( genFx( name, true ), speed, easing, callback ); + }; +} ); + +// Generate shortcuts for custom animations +jQuery.each( { + slideDown: genFx( "show" ), + slideUp: genFx( "hide" ), + slideToggle: genFx( "toggle" ), + fadeIn: { opacity: "show" }, + fadeOut: { opacity: "hide" }, + fadeToggle: { opacity: "toggle" } +}, function( name, props ) { + jQuery.fn[ name ] = function( speed, easing, callback ) { + return this.animate( props, speed, easing, callback ); + }; +} ); + +jQuery.timers = []; +jQuery.fx.tick = function() { + var timer, + i = 0, + timers = jQuery.timers; + + fxNow = Date.now(); + + for ( ; i < timers.length; i++ ) { + timer = timers[ i ]; + + // Run the timer and safely remove it when done (allowing for external removal) + if ( !timer() && timers[ i ] === timer ) { + timers.splice( i--, 1 ); + } + } + + if ( !timers.length ) { + jQuery.fx.stop(); + } + fxNow = undefined; +}; + +jQuery.fx.timer = function( timer ) { + jQuery.timers.push( timer ); + jQuery.fx.start(); +}; + +jQuery.fx.interval = 13; +jQuery.fx.start = function() { + if ( inProgress ) { + return; + } + + inProgress = true; + schedule(); +}; + +jQuery.fx.stop = function() { + inProgress = null; +}; + +jQuery.fx.speeds = { + slow: 600, + fast: 200, + + // Default speed + _default: 400 +}; + + +// Based off of the plugin by Clint Helfers, with permission. +// https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/ +jQuery.fn.delay = function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; + type = type || "fx"; + + return this.queue( type, function( next, hooks ) { + var timeout = window.setTimeout( next, time ); + hooks.stop = function() { + window.clearTimeout( timeout ); + }; + } ); +}; + + +( function() { + var input = document.createElement( "input" ), + select = document.createElement( "select" ), + opt = select.appendChild( document.createElement( "option" ) ); + + input.type = "checkbox"; + + // Support: Android <=4.3 only + // Default value for a checkbox should be "on" + support.checkOn = input.value !== ""; + + // Support: IE <=11 only + // Must access selectedIndex to make default options select + support.optSelected = opt.selected; + + // Support: IE <=11 only + // An input loses its value after becoming a radio + input = document.createElement( "input" ); + input.value = "t"; + input.type = "radio"; + support.radioValue = input.value === "t"; +} )(); + + +var boolHook, + attrHandle = jQuery.expr.attrHandle; + +jQuery.fn.extend( { + attr: function( name, value ) { + return access( this, jQuery.attr, name, value, arguments.length > 1 ); + }, + + removeAttr: function( name ) { + return this.each( function() { + jQuery.removeAttr( this, name ); + } ); + } +} ); + +jQuery.extend( { + attr: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set attributes on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + // Fallback to prop when attributes are not supported + if ( typeof elem.getAttribute === "undefined" ) { + return jQuery.prop( elem, name, value ); + } + + // Attribute hooks are determined by the lowercase version + // Grab necessary hook if one is defined + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + hooks = jQuery.attrHooks[ name.toLowerCase() ] || + ( jQuery.expr.match.bool.test( name ) ? boolHook : undefined ); + } + + if ( value !== undefined ) { + if ( value === null ) { + jQuery.removeAttr( elem, name ); + return; + } + + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + elem.setAttribute( name, value + "" ); + return value; + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + ret = jQuery.find.attr( elem, name ); + + // Non-existent attributes return null, we normalize to undefined + return ret == null ? undefined : ret; + }, + + attrHooks: { + type: { + set: function( elem, value ) { + if ( !support.radioValue && value === "radio" && + nodeName( elem, "input" ) ) { + var val = elem.value; + elem.setAttribute( "type", value ); + if ( val ) { + elem.value = val; + } + return value; + } + } + } + }, + + removeAttr: function( elem, value ) { + var name, + i = 0, + + // Attribute names can contain non-HTML whitespace characters + // https://html.spec.whatwg.org/multipage/syntax.html#attributes-2 + attrNames = value && value.match( rnothtmlwhite ); + + if ( attrNames && elem.nodeType === 1 ) { + while ( ( name = attrNames[ i++ ] ) ) { + elem.removeAttribute( name ); + } + } + } +} ); + +// Hooks for boolean attributes +boolHook = { + set: function( elem, value, name ) { + if ( value === false ) { + + // Remove boolean attributes when set to false + jQuery.removeAttr( elem, name ); + } else { + elem.setAttribute( name, name ); + } + return name; + } +}; + +jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( _i, name ) { + var getter = attrHandle[ name ] || jQuery.find.attr; + + attrHandle[ name ] = function( elem, name, isXML ) { + var ret, handle, + lowercaseName = name.toLowerCase(); + + if ( !isXML ) { + + // Avoid an infinite loop by temporarily removing this function from the getter + handle = attrHandle[ lowercaseName ]; + attrHandle[ lowercaseName ] = ret; + ret = getter( elem, name, isXML ) != null ? + lowercaseName : + null; + attrHandle[ lowercaseName ] = handle; + } + return ret; + }; +} ); + + + + +var rfocusable = /^(?:input|select|textarea|button)$/i, + rclickable = /^(?:a|area)$/i; + +jQuery.fn.extend( { + prop: function( name, value ) { + return access( this, jQuery.prop, name, value, arguments.length > 1 ); + }, + + removeProp: function( name ) { + return this.each( function() { + delete this[ jQuery.propFix[ name ] || name ]; + } ); + } +} ); + +jQuery.extend( { + prop: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set properties on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + + // Fix name and attach hooks + name = jQuery.propFix[ name ] || name; + hooks = jQuery.propHooks[ name ]; + } + + if ( value !== undefined ) { + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + return ( elem[ name ] = value ); + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + return elem[ name ]; + }, + + propHooks: { + tabIndex: { + get: function( elem ) { + + // Support: IE <=9 - 11 only + // elem.tabIndex doesn't always return the + // correct value when it hasn't been explicitly set + // https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + // Use proper attribute retrieval(#12072) + var tabindex = jQuery.find.attr( elem, "tabindex" ); + + if ( tabindex ) { + return parseInt( tabindex, 10 ); + } + + if ( + rfocusable.test( elem.nodeName ) || + rclickable.test( elem.nodeName ) && + elem.href + ) { + return 0; + } + + return -1; + } + } + }, + + propFix: { + "for": "htmlFor", + "class": "className" + } +} ); + +// Support: IE <=11 only +// Accessing the selectedIndex property +// forces the browser to respect setting selected +// on the option +// The getter ensures a default option is selected +// when in an optgroup +// eslint rule "no-unused-expressions" is disabled for this code +// since it considers such accessions noop +if ( !support.optSelected ) { + jQuery.propHooks.selected = { + get: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent && parent.parentNode ) { + parent.parentNode.selectedIndex; + } + return null; + }, + set: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent ) { + parent.selectedIndex; + + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + } + }; +} + +jQuery.each( [ + "tabIndex", + "readOnly", + "maxLength", + "cellSpacing", + "cellPadding", + "rowSpan", + "colSpan", + "useMap", + "frameBorder", + "contentEditable" +], function() { + jQuery.propFix[ this.toLowerCase() ] = this; +} ); + + + + + // Strip and collapse whitespace according to HTML spec + // https://infra.spec.whatwg.org/#strip-and-collapse-ascii-whitespace + function stripAndCollapse( value ) { + var tokens = value.match( rnothtmlwhite ) || []; + return tokens.join( " " ); + } + + +function getClass( elem ) { + return elem.getAttribute && elem.getAttribute( "class" ) || ""; +} + +function classesToArray( value ) { + if ( Array.isArray( value ) ) { + return value; + } + if ( typeof value === "string" ) { + return value.match( rnothtmlwhite ) || []; + } + return []; +} + +jQuery.fn.extend( { + addClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).addClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + if ( cur.indexOf( " " + clazz + " " ) < 0 ) { + cur += clazz + " "; + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + if ( !arguments.length ) { + return this.attr( "class", "" ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + + // This expression is here for better compressibility (see addClass) + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + + // Remove *all* instances + while ( cur.indexOf( " " + clazz + " " ) > -1 ) { + cur = cur.replace( " " + clazz + " ", " " ); + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value, + isValidValue = type === "string" || Array.isArray( value ); + + if ( typeof stateVal === "boolean" && isValidValue ) { + return stateVal ? this.addClass( value ) : this.removeClass( value ); + } + + if ( isFunction( value ) ) { + return this.each( function( i ) { + jQuery( this ).toggleClass( + value.call( this, i, getClass( this ), stateVal ), + stateVal + ); + } ); + } + + return this.each( function() { + var className, i, self, classNames; + + if ( isValidValue ) { + + // Toggle individual class names + i = 0; + self = jQuery( this ); + classNames = classesToArray( value ); + + while ( ( className = classNames[ i++ ] ) ) { + + // Check each className given, space separated list + if ( self.hasClass( className ) ) { + self.removeClass( className ); + } else { + self.addClass( className ); + } + } + + // Toggle whole class name + } else if ( value === undefined || type === "boolean" ) { + className = getClass( this ); + if ( className ) { + + // Store className if set + dataPriv.set( this, "__className__", className ); + } + + // If the element has a class name or if we're passed `false`, + // then remove the whole classname (if there was one, the above saved it). + // Otherwise bring back whatever was previously saved (if anything), + // falling back to the empty string if nothing was stored. + if ( this.setAttribute ) { + this.setAttribute( "class", + className || value === false ? + "" : + dataPriv.get( this, "__className__" ) || "" + ); + } + } + } ); + }, + + hasClass: function( selector ) { + var className, elem, + i = 0; + + className = " " + selector + " "; + while ( ( elem = this[ i++ ] ) ) { + if ( elem.nodeType === 1 && + ( " " + stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) { + return true; + } + } + + return false; + } +} ); + + + + +var rreturn = /\r/g; + +jQuery.fn.extend( { + val: function( value ) { + var hooks, ret, valueIsFunction, + elem = this[ 0 ]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.type ] || + jQuery.valHooks[ elem.nodeName.toLowerCase() ]; + + if ( hooks && + "get" in hooks && + ( ret = hooks.get( elem, "value" ) ) !== undefined + ) { + return ret; + } + + ret = elem.value; + + // Handle most common string cases + if ( typeof ret === "string" ) { + return ret.replace( rreturn, "" ); + } + + // Handle cases where value is null/undef or number + return ret == null ? "" : ret; + } + + return; + } + + valueIsFunction = isFunction( value ); + + return this.each( function( i ) { + var val; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( valueIsFunction ) { + val = value.call( this, i, jQuery( this ).val() ); + } else { + val = value; + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + + } else if ( typeof val === "number" ) { + val += ""; + + } else if ( Array.isArray( val ) ) { + val = jQuery.map( val, function( value ) { + return value == null ? "" : value + ""; + } ); + } + + hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; + + // If set returns undefined, fall back to normal setting + if ( !hooks || !( "set" in hooks ) || hooks.set( this, val, "value" ) === undefined ) { + this.value = val; + } + } ); + } +} ); + +jQuery.extend( { + valHooks: { + option: { + get: function( elem ) { + + var val = jQuery.find.attr( elem, "value" ); + return val != null ? + val : + + // Support: IE <=10 - 11 only + // option.text throws exceptions (#14686, #14858) + // Strip and collapse whitespace + // https://html.spec.whatwg.org/#strip-and-collapse-whitespace + stripAndCollapse( jQuery.text( elem ) ); + } + }, + select: { + get: function( elem ) { + var value, option, i, + options = elem.options, + index = elem.selectedIndex, + one = elem.type === "select-one", + values = one ? null : [], + max = one ? index + 1 : options.length; + + if ( index < 0 ) { + i = max; + + } else { + i = one ? index : 0; + } + + // Loop through all the selected options + for ( ; i < max; i++ ) { + option = options[ i ]; + + // Support: IE <=9 only + // IE8-9 doesn't update selected after form reset (#2551) + if ( ( option.selected || i === index ) && + + // Don't return options that are disabled or in a disabled optgroup + !option.disabled && + ( !option.parentNode.disabled || + !nodeName( option.parentNode, "optgroup" ) ) ) { + + // Get the specific value for the option + value = jQuery( option ).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + return values; + }, + + set: function( elem, value ) { + var optionSet, option, + options = elem.options, + values = jQuery.makeArray( value ), + i = options.length; + + while ( i-- ) { + option = options[ i ]; + + /* eslint-disable no-cond-assign */ + + if ( option.selected = + jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1 + ) { + optionSet = true; + } + + /* eslint-enable no-cond-assign */ + } + + // Force browsers to behave consistently when non-matching value is set + if ( !optionSet ) { + elem.selectedIndex = -1; + } + return values; + } + } + } +} ); + +// Radios and checkboxes getter/setter +jQuery.each( [ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = { + set: function( elem, value ) { + if ( Array.isArray( value ) ) { + return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 ); + } + } + }; + if ( !support.checkOn ) { + jQuery.valHooks[ this ].get = function( elem ) { + return elem.getAttribute( "value" ) === null ? "on" : elem.value; + }; + } +} ); + + + + +// Return jQuery for attributes-only inclusion + + +support.focusin = "onfocusin" in window; + + +var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, + stopPropagationCallback = function( e ) { + e.stopPropagation(); + }; + +jQuery.extend( jQuery.event, { + + trigger: function( event, data, elem, onlyHandlers ) { + + var i, cur, tmp, bubbleType, ontype, handle, special, lastElement, + eventPath = [ elem || document ], + type = hasOwn.call( event, "type" ) ? event.type : event, + namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : []; + + cur = lastElement = tmp = elem = elem || document; + + // Don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // focus/blur morphs to focusin/out; ensure we're not firing them right now + if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { + return; + } + + if ( type.indexOf( "." ) > -1 ) { + + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split( "." ); + type = namespaces.shift(); + namespaces.sort(); + } + ontype = type.indexOf( ":" ) < 0 && "on" + type; + + // Caller can pass in a jQuery.Event object, Object, or just an event type string + event = event[ jQuery.expando ] ? + event : + new jQuery.Event( type, typeof event === "object" && event ); + + // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) + event.isTrigger = onlyHandlers ? 2 : 3; + event.namespace = namespaces.join( "." ); + event.rnamespace = event.namespace ? + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) : + null; + + // Clean up the event in case it is being reused + event.result = undefined; + if ( !event.target ) { + event.target = elem; + } + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data == null ? + [ event ] : + jQuery.makeArray( data, [ event ] ); + + // Allow special events to draw outside the lines + special = jQuery.event.special[ type ] || {}; + if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { + return; + } + + // Determine event propagation path in advance, per W3C events spec (#9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) + if ( !onlyHandlers && !special.noBubble && !isWindow( elem ) ) { + + bubbleType = special.delegateType || type; + if ( !rfocusMorph.test( bubbleType + type ) ) { + cur = cur.parentNode; + } + for ( ; cur; cur = cur.parentNode ) { + eventPath.push( cur ); + tmp = cur; + } + + // Only add window if we got to document (e.g., not plain obj or detached DOM) + if ( tmp === ( elem.ownerDocument || document ) ) { + eventPath.push( tmp.defaultView || tmp.parentWindow || window ); + } + } + + // Fire handlers on the event path + i = 0; + while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) { + lastElement = cur; + event.type = i > 1 ? + bubbleType : + special.bindType || type; + + // jQuery handler + handle = ( + dataPriv.get( cur, "events" ) || Object.create( null ) + )[ event.type ] && + dataPriv.get( cur, "handle" ); + if ( handle ) { + handle.apply( cur, data ); + } + + // Native handler + handle = ontype && cur[ ontype ]; + if ( handle && handle.apply && acceptData( cur ) ) { + event.result = handle.apply( cur, data ); + if ( event.result === false ) { + event.preventDefault(); + } + } + } + event.type = type; + + // If nobody prevented the default action, do it now + if ( !onlyHandlers && !event.isDefaultPrevented() ) { + + if ( ( !special._default || + special._default.apply( eventPath.pop(), data ) === false ) && + acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name as the event. + // Don't do default actions on window, that's where global variables be (#6170) + if ( ontype && isFunction( elem[ type ] ) && !isWindow( elem ) ) { + + // Don't re-trigger an onFOO event when we call its FOO() method + tmp = elem[ ontype ]; + + if ( tmp ) { + elem[ ontype ] = null; + } + + // Prevent re-triggering of the same event, since we already bubbled it above + jQuery.event.triggered = type; + + if ( event.isPropagationStopped() ) { + lastElement.addEventListener( type, stopPropagationCallback ); + } + + elem[ type ](); + + if ( event.isPropagationStopped() ) { + lastElement.removeEventListener( type, stopPropagationCallback ); + } + + jQuery.event.triggered = undefined; + + if ( tmp ) { + elem[ ontype ] = tmp; + } + } + } + } + + return event.result; + }, + + // Piggyback on a donor event to simulate a different one + // Used only for `focus(in | out)` events + simulate: function( type, elem, event ) { + var e = jQuery.extend( + new jQuery.Event(), + event, + { + type: type, + isSimulated: true + } + ); + + jQuery.event.trigger( e, null, elem ); + } + +} ); + +jQuery.fn.extend( { + + trigger: function( type, data ) { + return this.each( function() { + jQuery.event.trigger( type, data, this ); + } ); + }, + triggerHandler: function( type, data ) { + var elem = this[ 0 ]; + if ( elem ) { + return jQuery.event.trigger( type, data, elem, true ); + } + } +} ); + + +// Support: Firefox <=44 +// Firefox doesn't have focus(in | out) events +// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787 +// +// Support: Chrome <=48 - 49, Safari <=9.0 - 9.1 +// focus(in | out) events fire after focus & blur events, +// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order +// Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857 +if ( !support.focusin ) { + jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler on the document while someone wants focusin/focusout + var handler = function( event ) { + jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) ); + }; + + jQuery.event.special[ fix ] = { + setup: function() { + + // Handle: regular nodes (via `this.ownerDocument`), window + // (via `this.document`) & document (via `this`). + var doc = this.ownerDocument || this.document || this, + attaches = dataPriv.access( doc, fix ); + + if ( !attaches ) { + doc.addEventListener( orig, handler, true ); + } + dataPriv.access( doc, fix, ( attaches || 0 ) + 1 ); + }, + teardown: function() { + var doc = this.ownerDocument || this.document || this, + attaches = dataPriv.access( doc, fix ) - 1; + + if ( !attaches ) { + doc.removeEventListener( orig, handler, true ); + dataPriv.remove( doc, fix ); + + } else { + dataPriv.access( doc, fix, attaches ); + } + } + }; + } ); +} +var location = window.location; + +var nonce = { guid: Date.now() }; + +var rquery = ( /\?/ ); + + + +// Cross-browser xml parsing +jQuery.parseXML = function( data ) { + var xml; + if ( !data || typeof data !== "string" ) { + return null; + } + + // Support: IE 9 - 11 only + // IE throws on parseFromString with invalid input. + try { + xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" ); + } catch ( e ) { + xml = undefined; + } + + if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) { + jQuery.error( "Invalid XML: " + data ); + } + return xml; +}; + + +var + rbracket = /\[\]$/, + rCRLF = /\r?\n/g, + rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i, + rsubmittable = /^(?:input|select|textarea|keygen)/i; + +function buildParams( prefix, obj, traditional, add ) { + var name; + + if ( Array.isArray( obj ) ) { + + // Serialize array item. + jQuery.each( obj, function( i, v ) { + if ( traditional || rbracket.test( prefix ) ) { + + // Treat each array item as a scalar. + add( prefix, v ); + + } else { + + // Item is non-scalar (array or object), encode its numeric index. + buildParams( + prefix + "[" + ( typeof v === "object" && v != null ? i : "" ) + "]", + v, + traditional, + add + ); + } + } ); + + } else if ( !traditional && toType( obj ) === "object" ) { + + // Serialize object item. + for ( name in obj ) { + buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add ); + } + + } else { + + // Serialize scalar item. + add( prefix, obj ); + } +} + +// Serialize an array of form elements or a set of +// key/values into a query string +jQuery.param = function( a, traditional ) { + var prefix, + s = [], + add = function( key, valueOrFunction ) { + + // If value is a function, invoke it and use its return value + var value = isFunction( valueOrFunction ) ? + valueOrFunction() : + valueOrFunction; + + s[ s.length ] = encodeURIComponent( key ) + "=" + + encodeURIComponent( value == null ? "" : value ); + }; + + if ( a == null ) { + return ""; + } + + // If an array was passed in, assume that it is an array of form elements. + if ( Array.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) { + + // Serialize the form elements + jQuery.each( a, function() { + add( this.name, this.value ); + } ); + + } else { + + // If traditional, encode the "old" way (the way 1.3.2 or older + // did it), otherwise encode params recursively. + for ( prefix in a ) { + buildParams( prefix, a[ prefix ], traditional, add ); + } + } + + // Return the resulting serialization + return s.join( "&" ); +}; + +jQuery.fn.extend( { + serialize: function() { + return jQuery.param( this.serializeArray() ); + }, + serializeArray: function() { + return this.map( function() { + + // Can add propHook for "elements" to filter or add form elements + var elements = jQuery.prop( this, "elements" ); + return elements ? jQuery.makeArray( elements ) : this; + } ) + .filter( function() { + var type = this.type; + + // Use .is( ":disabled" ) so that fieldset[disabled] works + return this.name && !jQuery( this ).is( ":disabled" ) && + rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) && + ( this.checked || !rcheckableType.test( type ) ); + } ) + .map( function( _i, elem ) { + var val = jQuery( this ).val(); + + if ( val == null ) { + return null; + } + + if ( Array.isArray( val ) ) { + return jQuery.map( val, function( val ) { + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ); + } + + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ).get(); + } +} ); + + +var + r20 = /%20/g, + rhash = /#.*$/, + rantiCache = /([?&])_=[^&]*/, + rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg, + + // #7653, #8125, #8152: local protocol detection + rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/, + rnoContent = /^(?:GET|HEAD)$/, + rprotocol = /^\/\//, + + /* Prefilters + * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example) + * 2) These are called: + * - BEFORE asking for a transport + * - AFTER param serialization (s.data is a string if s.processData is true) + * 3) key is the dataType + * 4) the catchall symbol "*" can be used + * 5) execution will start with transport dataType and THEN continue down to "*" if needed + */ + prefilters = {}, + + /* Transports bindings + * 1) key is the dataType + * 2) the catchall symbol "*" can be used + * 3) selection will start with transport dataType and THEN go to "*" if needed + */ + transports = {}, + + // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression + allTypes = "*/".concat( "*" ), + + // Anchor tag for parsing the document origin + originAnchor = document.createElement( "a" ); + originAnchor.href = location.href; + +// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport +function addToPrefiltersOrTransports( structure ) { + + // dataTypeExpression is optional and defaults to "*" + return function( dataTypeExpression, func ) { + + if ( typeof dataTypeExpression !== "string" ) { + func = dataTypeExpression; + dataTypeExpression = "*"; + } + + var dataType, + i = 0, + dataTypes = dataTypeExpression.toLowerCase().match( rnothtmlwhite ) || []; + + if ( isFunction( func ) ) { + + // For each dataType in the dataTypeExpression + while ( ( dataType = dataTypes[ i++ ] ) ) { + + // Prepend if requested + if ( dataType[ 0 ] === "+" ) { + dataType = dataType.slice( 1 ) || "*"; + ( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func ); + + // Otherwise append + } else { + ( structure[ dataType ] = structure[ dataType ] || [] ).push( func ); + } + } + } + }; +} + +// Base inspection function for prefilters and transports +function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) { + + var inspected = {}, + seekingTransport = ( structure === transports ); + + function inspect( dataType ) { + var selected; + inspected[ dataType ] = true; + jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) { + var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR ); + if ( typeof dataTypeOrTransport === "string" && + !seekingTransport && !inspected[ dataTypeOrTransport ] ) { + + options.dataTypes.unshift( dataTypeOrTransport ); + inspect( dataTypeOrTransport ); + return false; + } else if ( seekingTransport ) { + return !( selected = dataTypeOrTransport ); + } + } ); + return selected; + } + + return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" ); +} + +// A special extend for ajax options +// that takes "flat" options (not to be deep extended) +// Fixes #9887 +function ajaxExtend( target, src ) { + var key, deep, + flatOptions = jQuery.ajaxSettings.flatOptions || {}; + + for ( key in src ) { + if ( src[ key ] !== undefined ) { + ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ]; + } + } + if ( deep ) { + jQuery.extend( true, target, deep ); + } + + return target; +} + +/* Handles responses to an ajax request: + * - finds the right dataType (mediates between content-type and expected dataType) + * - returns the corresponding response + */ +function ajaxHandleResponses( s, jqXHR, responses ) { + + var ct, type, finalDataType, firstDataType, + contents = s.contents, + dataTypes = s.dataTypes; + + // Remove auto dataType and get content-type in the process + while ( dataTypes[ 0 ] === "*" ) { + dataTypes.shift(); + if ( ct === undefined ) { + ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" ); + } + } + + // Check if we're dealing with a known content-type + if ( ct ) { + for ( type in contents ) { + if ( contents[ type ] && contents[ type ].test( ct ) ) { + dataTypes.unshift( type ); + break; + } + } + } + + // Check to see if we have a response for the expected dataType + if ( dataTypes[ 0 ] in responses ) { + finalDataType = dataTypes[ 0 ]; + } else { + + // Try convertible dataTypes + for ( type in responses ) { + if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) { + finalDataType = type; + break; + } + if ( !firstDataType ) { + firstDataType = type; + } + } + + // Or just use first one + finalDataType = finalDataType || firstDataType; + } + + // If we found a dataType + // We add the dataType to the list if needed + // and return the corresponding response + if ( finalDataType ) { + if ( finalDataType !== dataTypes[ 0 ] ) { + dataTypes.unshift( finalDataType ); + } + return responses[ finalDataType ]; + } +} + +/* Chain conversions given the request and the original response + * Also sets the responseXXX fields on the jqXHR instance + */ +function ajaxConvert( s, response, jqXHR, isSuccess ) { + var conv2, current, conv, tmp, prev, + converters = {}, + + // Work with a copy of dataTypes in case we need to modify it for conversion + dataTypes = s.dataTypes.slice(); + + // Create converters map with lowercased keys + if ( dataTypes[ 1 ] ) { + for ( conv in s.converters ) { + converters[ conv.toLowerCase() ] = s.converters[ conv ]; + } + } + + current = dataTypes.shift(); + + // Convert to each sequential dataType + while ( current ) { + + if ( s.responseFields[ current ] ) { + jqXHR[ s.responseFields[ current ] ] = response; + } + + // Apply the dataFilter if provided + if ( !prev && isSuccess && s.dataFilter ) { + response = s.dataFilter( response, s.dataType ); + } + + prev = current; + current = dataTypes.shift(); + + if ( current ) { + + // There's only work to do if current dataType is non-auto + if ( current === "*" ) { + + current = prev; + + // Convert response if prev dataType is non-auto and differs from current + } else if ( prev !== "*" && prev !== current ) { + + // Seek a direct converter + conv = converters[ prev + " " + current ] || converters[ "* " + current ]; + + // If none found, seek a pair + if ( !conv ) { + for ( conv2 in converters ) { + + // If conv2 outputs current + tmp = conv2.split( " " ); + if ( tmp[ 1 ] === current ) { + + // If prev can be converted to accepted input + conv = converters[ prev + " " + tmp[ 0 ] ] || + converters[ "* " + tmp[ 0 ] ]; + if ( conv ) { + + // Condense equivalence converters + if ( conv === true ) { + conv = converters[ conv2 ]; + + // Otherwise, insert the intermediate dataType + } else if ( converters[ conv2 ] !== true ) { + current = tmp[ 0 ]; + dataTypes.unshift( tmp[ 1 ] ); + } + break; + } + } + } + } + + // Apply converter (if not an equivalence) + if ( conv !== true ) { + + // Unless errors are allowed to bubble, catch and return them + if ( conv && s.throws ) { + response = conv( response ); + } else { + try { + response = conv( response ); + } catch ( e ) { + return { + state: "parsererror", + error: conv ? e : "No conversion from " + prev + " to " + current + }; + } + } + } + } + } + } + + return { state: "success", data: response }; +} + +jQuery.extend( { + + // Counter for holding the number of active queries + active: 0, + + // Last-Modified header cache for next request + lastModified: {}, + etag: {}, + + ajaxSettings: { + url: location.href, + type: "GET", + isLocal: rlocalProtocol.test( location.protocol ), + global: true, + processData: true, + async: true, + contentType: "application/x-www-form-urlencoded; charset=UTF-8", + + /* + timeout: 0, + data: null, + dataType: null, + username: null, + password: null, + cache: null, + throws: false, + traditional: false, + headers: {}, + */ + + accepts: { + "*": allTypes, + text: "text/plain", + html: "text/html", + xml: "application/xml, text/xml", + json: "application/json, text/javascript" + }, + + contents: { + xml: /\bxml\b/, + html: /\bhtml/, + json: /\bjson\b/ + }, + + responseFields: { + xml: "responseXML", + text: "responseText", + json: "responseJSON" + }, + + // Data converters + // Keys separate source (or catchall "*") and destination types with a single space + converters: { + + // Convert anything to text + "* text": String, + + // Text to html (true = no transformation) + "text html": true, + + // Evaluate text as a json expression + "text json": JSON.parse, + + // Parse text as xml + "text xml": jQuery.parseXML + }, + + // For options that shouldn't be deep extended: + // you can add your own custom options here if + // and when you create one that shouldn't be + // deep extended (see ajaxExtend) + flatOptions: { + url: true, + context: true + } + }, + + // Creates a full fledged settings object into target + // with both ajaxSettings and settings fields. + // If target is omitted, writes into ajaxSettings. + ajaxSetup: function( target, settings ) { + return settings ? + + // Building a settings object + ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) : + + // Extending ajaxSettings + ajaxExtend( jQuery.ajaxSettings, target ); + }, + + ajaxPrefilter: addToPrefiltersOrTransports( prefilters ), + ajaxTransport: addToPrefiltersOrTransports( transports ), + + // Main method + ajax: function( url, options ) { + + // If url is an object, simulate pre-1.5 signature + if ( typeof url === "object" ) { + options = url; + url = undefined; + } + + // Force options to be an object + options = options || {}; + + var transport, + + // URL without anti-cache param + cacheURL, + + // Response headers + responseHeadersString, + responseHeaders, + + // timeout handle + timeoutTimer, + + // Url cleanup var + urlAnchor, + + // Request state (becomes false upon send and true upon completion) + completed, + + // To know if global events are to be dispatched + fireGlobals, + + // Loop variable + i, + + // uncached part of the url + uncached, + + // Create the final options object + s = jQuery.ajaxSetup( {}, options ), + + // Callbacks context + callbackContext = s.context || s, + + // Context for global events is callbackContext if it is a DOM node or jQuery collection + globalEventContext = s.context && + ( callbackContext.nodeType || callbackContext.jquery ) ? + jQuery( callbackContext ) : + jQuery.event, + + // Deferreds + deferred = jQuery.Deferred(), + completeDeferred = jQuery.Callbacks( "once memory" ), + + // Status-dependent callbacks + statusCode = s.statusCode || {}, + + // Headers (they are sent all at once) + requestHeaders = {}, + requestHeadersNames = {}, + + // Default abort message + strAbort = "canceled", + + // Fake xhr + jqXHR = { + readyState: 0, + + // Builds headers hashtable if needed + getResponseHeader: function( key ) { + var match; + if ( completed ) { + if ( !responseHeaders ) { + responseHeaders = {}; + while ( ( match = rheaders.exec( responseHeadersString ) ) ) { + responseHeaders[ match[ 1 ].toLowerCase() + " " ] = + ( responseHeaders[ match[ 1 ].toLowerCase() + " " ] || [] ) + .concat( match[ 2 ] ); + } + } + match = responseHeaders[ key.toLowerCase() + " " ]; + } + return match == null ? null : match.join( ", " ); + }, + + // Raw string + getAllResponseHeaders: function() { + return completed ? responseHeadersString : null; + }, + + // Caches the header + setRequestHeader: function( name, value ) { + if ( completed == null ) { + name = requestHeadersNames[ name.toLowerCase() ] = + requestHeadersNames[ name.toLowerCase() ] || name; + requestHeaders[ name ] = value; + } + return this; + }, + + // Overrides response content-type header + overrideMimeType: function( type ) { + if ( completed == null ) { + s.mimeType = type; + } + return this; + }, + + // Status-dependent callbacks + statusCode: function( map ) { + var code; + if ( map ) { + if ( completed ) { + + // Execute the appropriate callbacks + jqXHR.always( map[ jqXHR.status ] ); + } else { + + // Lazy-add the new callbacks in a way that preserves old ones + for ( code in map ) { + statusCode[ code ] = [ statusCode[ code ], map[ code ] ]; + } + } + } + return this; + }, + + // Cancel the request + abort: function( statusText ) { + var finalText = statusText || strAbort; + if ( transport ) { + transport.abort( finalText ); + } + done( 0, finalText ); + return this; + } + }; + + // Attach deferreds + deferred.promise( jqXHR ); + + // Add protocol if not provided (prefilters might expect it) + // Handle falsy url in the settings object (#10093: consistency with old signature) + // We also use the url parameter if available + s.url = ( ( url || s.url || location.href ) + "" ) + .replace( rprotocol, location.protocol + "//" ); + + // Alias method option to type as per ticket #12004 + s.type = options.method || options.type || s.method || s.type; + + // Extract dataTypes list + s.dataTypes = ( s.dataType || "*" ).toLowerCase().match( rnothtmlwhite ) || [ "" ]; + + // A cross-domain request is in order when the origin doesn't match the current origin. + if ( s.crossDomain == null ) { + urlAnchor = document.createElement( "a" ); + + // Support: IE <=8 - 11, Edge 12 - 15 + // IE throws exception on accessing the href property if url is malformed, + // e.g. http://example.com:80x/ + try { + urlAnchor.href = s.url; + + // Support: IE <=8 - 11 only + // Anchor's host property isn't correctly set when s.url is relative + urlAnchor.href = urlAnchor.href; + s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !== + urlAnchor.protocol + "//" + urlAnchor.host; + } catch ( e ) { + + // If there is an error parsing the URL, assume it is crossDomain, + // it can be rejected by the transport if it is invalid + s.crossDomain = true; + } + } + + // Convert data if not already a string + if ( s.data && s.processData && typeof s.data !== "string" ) { + s.data = jQuery.param( s.data, s.traditional ); + } + + // Apply prefilters + inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ); + + // If request was aborted inside a prefilter, stop there + if ( completed ) { + return jqXHR; + } + + // We can fire global events as of now if asked to + // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118) + fireGlobals = jQuery.event && s.global; + + // Watch for a new set of requests + if ( fireGlobals && jQuery.active++ === 0 ) { + jQuery.event.trigger( "ajaxStart" ); + } + + // Uppercase the type + s.type = s.type.toUpperCase(); + + // Determine if request has content + s.hasContent = !rnoContent.test( s.type ); + + // Save the URL in case we're toying with the If-Modified-Since + // and/or If-None-Match header later on + // Remove hash to simplify url manipulation + cacheURL = s.url.replace( rhash, "" ); + + // More options handling for requests with no content + if ( !s.hasContent ) { + + // Remember the hash so we can put it back + uncached = s.url.slice( cacheURL.length ); + + // If data is available and should be processed, append data to url + if ( s.data && ( s.processData || typeof s.data === "string" ) ) { + cacheURL += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data; + + // #9682: remove data so that it's not used in an eventual retry + delete s.data; + } + + // Add or update anti-cache param if needed + if ( s.cache === false ) { + cacheURL = cacheURL.replace( rantiCache, "$1" ); + uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce.guid++ ) + + uncached; + } + + // Put hash and anti-cache on the URL that will be requested (gh-1732) + s.url = cacheURL + uncached; + + // Change '%20' to '+' if this is encoded form body content (gh-2658) + } else if ( s.data && s.processData && + ( s.contentType || "" ).indexOf( "application/x-www-form-urlencoded" ) === 0 ) { + s.data = s.data.replace( r20, "+" ); + } + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + if ( jQuery.lastModified[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] ); + } + if ( jQuery.etag[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] ); + } + } + + // Set the correct header, if data is being sent + if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { + jqXHR.setRequestHeader( "Content-Type", s.contentType ); + } + + // Set the Accepts header for the server, depending on the dataType + jqXHR.setRequestHeader( + "Accept", + s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ? + s.accepts[ s.dataTypes[ 0 ] ] + + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) : + s.accepts[ "*" ] + ); + + // Check for headers option + for ( i in s.headers ) { + jqXHR.setRequestHeader( i, s.headers[ i ] ); + } + + // Allow custom headers/mimetypes and early abort + if ( s.beforeSend && + ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || completed ) ) { + + // Abort if not done already and return + return jqXHR.abort(); + } + + // Aborting is no longer a cancellation + strAbort = "abort"; + + // Install callbacks on deferreds + completeDeferred.add( s.complete ); + jqXHR.done( s.success ); + jqXHR.fail( s.error ); + + // Get transport + transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); + + // If no transport, we auto-abort + if ( !transport ) { + done( -1, "No Transport" ); + } else { + jqXHR.readyState = 1; + + // Send global event + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); + } + + // If request was aborted inside ajaxSend, stop there + if ( completed ) { + return jqXHR; + } + + // Timeout + if ( s.async && s.timeout > 0 ) { + timeoutTimer = window.setTimeout( function() { + jqXHR.abort( "timeout" ); + }, s.timeout ); + } + + try { + completed = false; + transport.send( requestHeaders, done ); + } catch ( e ) { + + // Rethrow post-completion exceptions + if ( completed ) { + throw e; + } + + // Propagate others as results + done( -1, e ); + } + } + + // Callback for when everything is done + function done( status, nativeStatusText, responses, headers ) { + var isSuccess, success, error, response, modified, + statusText = nativeStatusText; + + // Ignore repeat invocations + if ( completed ) { + return; + } + + completed = true; + + // Clear timeout if it exists + if ( timeoutTimer ) { + window.clearTimeout( timeoutTimer ); + } + + // Dereference transport for early garbage collection + // (no matter how long the jqXHR object will be used) + transport = undefined; + + // Cache response headers + responseHeadersString = headers || ""; + + // Set readyState + jqXHR.readyState = status > 0 ? 4 : 0; + + // Determine if successful + isSuccess = status >= 200 && status < 300 || status === 304; + + // Get response data + if ( responses ) { + response = ajaxHandleResponses( s, jqXHR, responses ); + } + + // Use a noop converter for missing script + if ( !isSuccess && jQuery.inArray( "script", s.dataTypes ) > -1 ) { + s.converters[ "text script" ] = function() {}; + } + + // Convert no matter what (that way responseXXX fields are always set) + response = ajaxConvert( s, response, jqXHR, isSuccess ); + + // If successful, handle type chaining + if ( isSuccess ) { + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + modified = jqXHR.getResponseHeader( "Last-Modified" ); + if ( modified ) { + jQuery.lastModified[ cacheURL ] = modified; + } + modified = jqXHR.getResponseHeader( "etag" ); + if ( modified ) { + jQuery.etag[ cacheURL ] = modified; + } + } + + // if no content + if ( status === 204 || s.type === "HEAD" ) { + statusText = "nocontent"; + + // if not modified + } else if ( status === 304 ) { + statusText = "notmodified"; + + // If we have data, let's convert it + } else { + statusText = response.state; + success = response.data; + error = response.error; + isSuccess = !error; + } + } else { + + // Extract error from statusText and normalize for non-aborts + error = statusText; + if ( status || !statusText ) { + statusText = "error"; + if ( status < 0 ) { + status = 0; + } + } + } + + // Set data for the fake xhr object + jqXHR.status = status; + jqXHR.statusText = ( nativeStatusText || statusText ) + ""; + + // Success/Error + if ( isSuccess ) { + deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); + } else { + deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); + } + + // Status-dependent callbacks + jqXHR.statusCode( statusCode ); + statusCode = undefined; + + if ( fireGlobals ) { + globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError", + [ jqXHR, s, isSuccess ? success : error ] ); + } + + // Complete + completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] ); + + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] ); + + // Handle the global AJAX counter + if ( !( --jQuery.active ) ) { + jQuery.event.trigger( "ajaxStop" ); + } + } + } + + return jqXHR; + }, + + getJSON: function( url, data, callback ) { + return jQuery.get( url, data, callback, "json" ); + }, + + getScript: function( url, callback ) { + return jQuery.get( url, undefined, callback, "script" ); + } +} ); + +jQuery.each( [ "get", "post" ], function( _i, method ) { + jQuery[ method ] = function( url, data, callback, type ) { + + // Shift arguments if data argument was omitted + if ( isFunction( data ) ) { + type = type || callback; + callback = data; + data = undefined; + } + + // The url can be an options object (which then must have .url) + return jQuery.ajax( jQuery.extend( { + url: url, + type: method, + dataType: type, + data: data, + success: callback + }, jQuery.isPlainObject( url ) && url ) ); + }; +} ); + +jQuery.ajaxPrefilter( function( s ) { + var i; + for ( i in s.headers ) { + if ( i.toLowerCase() === "content-type" ) { + s.contentType = s.headers[ i ] || ""; + } + } +} ); + + +jQuery._evalUrl = function( url, options, doc ) { + return jQuery.ajax( { + url: url, + + // Make this explicit, since user can override this through ajaxSetup (#11264) + type: "GET", + dataType: "script", + cache: true, + async: false, + global: false, + + // Only evaluate the response if it is successful (gh-4126) + // dataFilter is not invoked for failure responses, so using it instead + // of the default converter is kludgy but it works. + converters: { + "text script": function() {} + }, + dataFilter: function( response ) { + jQuery.globalEval( response, options, doc ); + } + } ); +}; + + +jQuery.fn.extend( { + wrapAll: function( html ) { + var wrap; + + if ( this[ 0 ] ) { + if ( isFunction( html ) ) { + html = html.call( this[ 0 ] ); + } + + // The elements to wrap the target around + wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true ); + + if ( this[ 0 ].parentNode ) { + wrap.insertBefore( this[ 0 ] ); + } + + wrap.map( function() { + var elem = this; + + while ( elem.firstElementChild ) { + elem = elem.firstElementChild; + } + + return elem; + } ).append( this ); + } + + return this; + }, + + wrapInner: function( html ) { + if ( isFunction( html ) ) { + return this.each( function( i ) { + jQuery( this ).wrapInner( html.call( this, i ) ); + } ); + } + + return this.each( function() { + var self = jQuery( this ), + contents = self.contents(); + + if ( contents.length ) { + contents.wrapAll( html ); + + } else { + self.append( html ); + } + } ); + }, + + wrap: function( html ) { + var htmlIsFunction = isFunction( html ); + + return this.each( function( i ) { + jQuery( this ).wrapAll( htmlIsFunction ? html.call( this, i ) : html ); + } ); + }, + + unwrap: function( selector ) { + this.parent( selector ).not( "body" ).each( function() { + jQuery( this ).replaceWith( this.childNodes ); + } ); + return this; + } +} ); + + +jQuery.expr.pseudos.hidden = function( elem ) { + return !jQuery.expr.pseudos.visible( elem ); +}; +jQuery.expr.pseudos.visible = function( elem ) { + return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length ); +}; + + + + +jQuery.ajaxSettings.xhr = function() { + try { + return new window.XMLHttpRequest(); + } catch ( e ) {} +}; + +var xhrSuccessStatus = { + + // File protocol always yields status code 0, assume 200 + 0: 200, + + // Support: IE <=9 only + // #1450: sometimes IE returns 1223 when it should be 204 + 1223: 204 + }, + xhrSupported = jQuery.ajaxSettings.xhr(); + +support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported ); +support.ajax = xhrSupported = !!xhrSupported; + +jQuery.ajaxTransport( function( options ) { + var callback, errorCallback; + + // Cross domain only allowed if supported through XMLHttpRequest + if ( support.cors || xhrSupported && !options.crossDomain ) { + return { + send: function( headers, complete ) { + var i, + xhr = options.xhr(); + + xhr.open( + options.type, + options.url, + options.async, + options.username, + options.password + ); + + // Apply custom fields if provided + if ( options.xhrFields ) { + for ( i in options.xhrFields ) { + xhr[ i ] = options.xhrFields[ i ]; + } + } + + // Override mime type if needed + if ( options.mimeType && xhr.overrideMimeType ) { + xhr.overrideMimeType( options.mimeType ); + } + + // X-Requested-With header + // For cross-domain requests, seeing as conditions for a preflight are + // akin to a jigsaw puzzle, we simply never set it to be sure. + // (it can always be set on a per-request basis or even using ajaxSetup) + // For same-domain requests, won't change header if already provided. + if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) { + headers[ "X-Requested-With" ] = "XMLHttpRequest"; + } + + // Set headers + for ( i in headers ) { + xhr.setRequestHeader( i, headers[ i ] ); + } + + // Callback + callback = function( type ) { + return function() { + if ( callback ) { + callback = errorCallback = xhr.onload = + xhr.onerror = xhr.onabort = xhr.ontimeout = + xhr.onreadystatechange = null; + + if ( type === "abort" ) { + xhr.abort(); + } else if ( type === "error" ) { + + // Support: IE <=9 only + // On a manual native abort, IE9 throws + // errors on any property access that is not readyState + if ( typeof xhr.status !== "number" ) { + complete( 0, "error" ); + } else { + complete( + + // File: protocol always yields status 0; see #8605, #14207 + xhr.status, + xhr.statusText + ); + } + } else { + complete( + xhrSuccessStatus[ xhr.status ] || xhr.status, + xhr.statusText, + + // Support: IE <=9 only + // IE9 has no XHR2 but throws on binary (trac-11426) + // For XHR2 non-text, let the caller handle it (gh-2498) + ( xhr.responseType || "text" ) !== "text" || + typeof xhr.responseText !== "string" ? + { binary: xhr.response } : + { text: xhr.responseText }, + xhr.getAllResponseHeaders() + ); + } + } + }; + }; + + // Listen to events + xhr.onload = callback(); + errorCallback = xhr.onerror = xhr.ontimeout = callback( "error" ); + + // Support: IE 9 only + // Use onreadystatechange to replace onabort + // to handle uncaught aborts + if ( xhr.onabort !== undefined ) { + xhr.onabort = errorCallback; + } else { + xhr.onreadystatechange = function() { + + // Check readyState before timeout as it changes + if ( xhr.readyState === 4 ) { + + // Allow onerror to be called first, + // but that will not handle a native abort + // Also, save errorCallback to a variable + // as xhr.onerror cannot be accessed + window.setTimeout( function() { + if ( callback ) { + errorCallback(); + } + } ); + } + }; + } + + // Create the abort callback + callback = callback( "abort" ); + + try { + + // Do send the request (this may raise an exception) + xhr.send( options.hasContent && options.data || null ); + } catch ( e ) { + + // #14683: Only rethrow if this hasn't been notified as an error yet + if ( callback ) { + throw e; + } + } + }, + + abort: function() { + if ( callback ) { + callback(); + } + } + }; + } +} ); + + + + +// Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432) +jQuery.ajaxPrefilter( function( s ) { + if ( s.crossDomain ) { + s.contents.script = false; + } +} ); + +// Install script dataType +jQuery.ajaxSetup( { + accepts: { + script: "text/javascript, application/javascript, " + + "application/ecmascript, application/x-ecmascript" + }, + contents: { + script: /\b(?:java|ecma)script\b/ + }, + converters: { + "text script": function( text ) { + jQuery.globalEval( text ); + return text; + } + } +} ); + +// Handle cache's special case and crossDomain +jQuery.ajaxPrefilter( "script", function( s ) { + if ( s.cache === undefined ) { + s.cache = false; + } + if ( s.crossDomain ) { + s.type = "GET"; + } +} ); + +// Bind script tag hack transport +jQuery.ajaxTransport( "script", function( s ) { + + // This transport only deals with cross domain or forced-by-attrs requests + if ( s.crossDomain || s.scriptAttrs ) { + var script, callback; + return { + send: function( _, complete ) { + script = jQuery( " + + + + + + + + + + +
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/c_api/base.html b/venv/Lib/site-packages/pygame/docs/generated/c_api/base.html new file mode 100644 index 0000000..6486af9 --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/c_api/base.html @@ -0,0 +1,365 @@ + + + + + + + + + High level API exported by pygame.base — pygame v2.1.2 documentation + + + + + + + + + + + + + +
+ +
+ + + + + +
+
+ +
+
+ +
+
+

src_c/base.c¶

+

This extension module defines general purpose routines for starting and stopping +SDL as well as various conversion routines uses elsewhere in pygame.

+

C header: src_c/include/pygame.h

+
+
+PyObject *pgExc_SDLError¶
+

This is pygame.error, the exception type used to raise SDL errors.

+
+ +
+
+int pg_mod_autoinit(const char *modname)¶
+

Inits a pygame module, which has the name modname +Return 1 on success, 0 on error, with python +error set.

+
+ +
+
+void pg_mod_autoquit(const char *modname)¶
+

Quits a pygame module, which has the name modname

+
+ +
+
+void pg_RegisterQuit(void (*f)(void))¶
+

Register function f as a callback on Pygame termination. +Multiple functions can be registered. +Functions are called in the reverse order they were registered.

+
+ +
+
+int pg_IntFromObj(PyObject *obj, int *val)¶
+

Convert number like object obj to C int and place in argument val. +Return 1 on success, else 0. +No Python exceptions are raised.

+
+ +
+
+int pg_IntFromObjIndex(PyObject *obj, int index, int *val)¶
+

Convert number like object at position i in sequence obj +to C int and place in argument val. +Return 1 on success, 0 on failure. +No Python exceptions are raised.

+
+ +
+
+int pg_TwoIntsFromObj(PyObject *obj, int *val1, int *v2)¶
+

Convert the two number like objects in length 2 sequence obj +to C int and place in arguments val1 and val2 respectively. +Return 1 on success, 0 on failure. +No Python exceptions are raised.

+
+ +
+
+int pg_FloatFromObj(PyObject *obj, float *val)¶
+

Convert number like object obj to C float and place in argument val. +Returns 1 on success, 0 on failure. +No Python exceptions are raised.

+
+ +
+
+int pg_FloatFromObjIndex(PyObject *obj, int index, float *val)¶
+

Convert number like object at position i in sequence obj +to C float and place in argument val. +Return 1 on success, else 0. +No Python exceptions are raised.

+
+ +
+
+int pg_TwoFloatsFromObj(PyObject *obj, float *val1, float *val2)¶
+

Convert the two number like objects in length 2 sequence obj +to C float and place in arguments val1 and val2 respectively. +Return 1 on success, else 0. +No Python exceptions are raised.

+
+ +
+
+int pg_UintFromObj(PyObject *obj, Uint32 *val)¶
+

Convert number like object obj to unsigned 32 bit integer and place +in argument val. +Return 1 on success, else 0. +No Python exceptions are raised.

+
+ +
+
+int pg_UintFromObjIndex(PyObject *obj, int _index, Uint32 *val)¶
+

Convert number like object at position i in sequence obj +to unsigned 32 bit integer and place in argument val. +Return 1 on success, else 0. +No Python exceptions are raised.

+
+ +
+
+int pg_RGBAFromObj(PyObject *obj, Uint8 *RGBA)¶
+

Convert the color represented by object obj into a red, green, blue, alpha +length 4 C array RGBA. +The object must be a length 3 or 4 sequence of numbers having values +between 0 and 255 inclusive. +For a length 3 sequence an alpha value of 255 is assumed. +Return 1 on success, 0 otherwise. +No Python exceptions are raised.

+
+ +
+
+type pg_buffer¶
+
+
+Py_buffer view¶
+

A standard buffer description

+
+ +
+
+PyObject *consumer¶
+

The object holding the buffer

+
+ +
+
+pybuffer_releaseproc release_buffer¶
+

A buffer release callback.

+
+ +
+ +
+
+PyObject *pgExc_BufferError¶
+

Python exception type raised for any pg_buffer related errors.

+
+ +
+
+PyObject *pgBuffer_AsArrayInterface(Py_buffer *view_p)¶
+

Return a Python array interface object representation of buffer view_p. +On failure raise a Python exception and return NULL.

+
+ +
+
+PyObject *pgBuffer_AsArrayStruct(Py_buffer *view_p)¶
+

Return a Python array struct object representation of buffer view_p. +On failure raise a Python exception and return NULL.

+
+ +
+
+int pgObject_GetBuffer(PyObject *obj, pg_buffer *pg_view_p, int flags)¶
+

Request a buffer for object obj. +Argument flags are PyBUF options. +Return the buffer description in pg_view_p. +An object may support the Python buffer interface, the NumPy array interface, +or the NumPy array struct interface. +Return 0 on success, raise a Python exception and return -1 on failure.

+
+ +
+
+void pgBuffer_Release(Pg_buffer *pg_view_p)¶
+

Release the Pygame pg_view_p buffer.

+
+ +
+
+int pgDict_AsBuffer(Pg_buffer *pg_view_p, PyObject *dict, int flags)¶
+

Write the array interface dictionary buffer description dict into a Pygame +buffer description struct pg_view_p. +The flags PyBUF options describe the view type requested. +Return 0 on success, or raise a Python exception and return -1 on failure.

+
+ +
+
+void import_pygame_base()¶
+

Import the pygame.base module C API into an extension module. +On failure raise a Python exception.

+
+ +
+
+SDL_Window *pg_GetDefaultWindow(void)¶
+

Return the Pygame default SDL window created by a +pygame.display.set_mode() call, or NULL.

+

Availability: SDL 2.

+
+ +
+
+void pg_SetDefaultWindow(SDL_Window *win)¶
+

Replace the Pygame default window with win. +The previous window, if any, is destroyed. +Argument win may be NULL. +This function is called by pygame.display.set_mode().

+

Availability: SDL 2.

+
+ +
+
+pgSurfaceObject *pg_GetDefaultWindowSurface(void)¶
+

Return a borrowed reference to the Pygame default window display surface, +or NULL if no default window is open.

+

Availability: SDL 2.

+
+ +
+
+void pg_SetDefaultWindowSurface(pgSurfaceObject *screen)¶
+

Replace the Pygame default display surface with object screen. +The previous surface object, if any, is invalidated. +Argument screen may be NULL. +This functions is called by pygame.display.set_mode().

+

Availability: SDL 2.

+
+ +
+
+ + +

+
+Edit on GitHub +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/c_api/bufferproxy.html b/venv/Lib/site-packages/pygame/docs/generated/c_api/bufferproxy.html new file mode 100644 index 0000000..2b2b352 --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/c_api/bufferproxy.html @@ -0,0 +1,183 @@ + + + + + + + + + Class BufferProxy API exported by pgyame.bufferproxy — pygame v2.1.2 documentation + + + + + + + + + + + + + +
+ +
+ + + + + +
+
+ +
+
+ +
+
+

src_c/bufferproxy.c¶

+

This extension module defines Python type pygame.BufferProxypygame object to export a surface buffer through an array protocol.

+

Header file: src_c/include/pygame_bufferproxy.h

+
+
+PyTypeObject *pgBufproxy_Type¶
+

The pygame buffer proxy object type pygame.BufferProxy.

+
+ +
+
+int pgBufproxy_Check(PyObject *x)¶
+

Return true if Python object x is a pygame.BufferProxy instance, +false otherwise. +This will return false on pygame.BufferProxy subclass instances as well.

+
+ +
+
+PyObject *pgBufproxy_New(PyObject *obj, getbufferproc get_buffer)¶
+

Return a new pygame.BufferProxy instance. +Argument obj is the Python object that has its data exposed. +It may be NULL. +Argument get_buffer is the pg_buffer get callback. +It must not be NULL. +On failure raise a Python error and return NULL.

+
+ +
+
+PyObject *pgBufproxy_GetParent(PyObject *obj)¶
+

Return the Python object wrapped by buffer proxy obj. +Argument obj must not be NULL. +On failure, raise a Python error and return NULL.

+
+ +
+
+int pgBufproxy_Trip(PyObject *obj)¶
+

Cause the buffer proxy object obj to create a pg_buffer view of its parent. +Argument obj must not be NULL. +Return 0 on success, otherwise raise a Python error and return -1.

+
+ +
+
+ + +

+
+Edit on GitHub +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/c_api/cdrom.html b/venv/Lib/site-packages/pygame/docs/generated/c_api/cdrom.html new file mode 100644 index 0000000..07f524a --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/c_api/cdrom.html @@ -0,0 +1,178 @@ + + + + + + + + + API exported by pygame.cdrom — pygame v2.1.2 documentation + + + + + + + + + + + + + +
+ +
+ + + + + +
+
+ +
+
+ +
+
+

src_c/cdrom.c¶

+

The pygame.cdrompygame module for audio cdrom control extension module. Only available for SDL 1.

+

Header file: src_c/include/pygame.h

+
+
+type pgCDObject¶
+

The pygame.cdrom.CD instance C struct.

+
+ +
+
+PyTypeObject pgCD_Type¶
+

The pygame.cdrom.CD Python type.

+
+ +
+
+PyObject *pgCD_New(int id)¶
+

Return a new pygame.cdrom.CD instance for CD drive id. +On error raise a Python exception and return NULL.

+
+ +
+
+int pgCD_Check(PyObject *x)¶
+

Return true if x is a pygame.cdrom.CD instance. +Will return false for a subclass of CD. +This is a macro. No check is made that x is not NULL.

+
+ +
+
+int pgCD_AsID(PyObject *x)¶
+

Return the CD identifier associated with the pygame.cdrom.CD +instance x. +This is a macro. No check is made that x is a pygame.cdrom.CD +instance or is not NULL.

+
+ +
+
+ + +

+
+Edit on GitHub +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/c_api/color.html b/venv/Lib/site-packages/pygame/docs/generated/c_api/color.html new file mode 100644 index 0000000..7fef935 --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/c_api/color.html @@ -0,0 +1,172 @@ + + + + + + + + + Class Color API exported by pygame.color — pygame v2.1.2 documentation + + + + + + + + + + + + + +
+ +
+ + + + + +
+
+ +
+
+ +
+
+

src_c/color.c¶

+

This extension module defines the Python type pygame.Colorpygame object for color representations.

+

Header file: src_c/include/pygame.h

+
+
+PyTypeObject *pgColor_Type¶
+

The Pygame color object type pygame.Color.

+
+ +
+
+int pgColor_Check(PyObject *obj)¶
+

Return true if obj is an instance of type pgColor_Type, +but not a pgColor_Type subclass instance. +This macro does not check if obj is not NULL or indeed a Python type.

+
+ +
+
+PyObject *pgColor_New(Uint8 rgba[])¶
+

Return a new pygame.Color instance for the the four element array rgba. +On failure, raise a Python exception and return NULL.

+
+ +
+
+PyObject *pgColor_NewLength(Uint8 rgba[], Uint8 length)¶
+

Return a new pygame.Color instance having length elements, +with element values taken from the first length elements of array rgba. +Argument length must be between 1 and 4 inclusive. +On failure, raise a Python exception and return NULL.

+
+ +
+
+ + +

+
+Edit on GitHub +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/c_api/display.html b/venv/Lib/site-packages/pygame/docs/generated/c_api/display.html new file mode 100644 index 0000000..c83184f --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/c_api/display.html @@ -0,0 +1,177 @@ + + + + + + + + + API exported by pygame.display — pygame v2.1.2 documentation + + + + + + + + + + + + + +
+ +
+ + + + + +
+
+ +
+
+ +
+
+

src_c/display.c¶

+

This is the pygame.displaypygame module to control the display window and screen extension module.

+

Header file: src_c/include/pygame.h

+
+
+type pgVidInfoObject¶
+

A pygame object that wraps an SDL_VideoInfo struct. +The object returned by pgyame.display.Info().

+
+ +
+
+PyTypeObject *pgVidInfo_Type¶
+

The pgVidInfoObject object Python type.

+
+ +
+
+SDL_VideoInfo pgVidInfo_AsVidInfo(PyObject *obj)¶
+

Return the SDL_VideoInfo field of obj, a pgVidInfo_Type instance. +This macro does not check that obj is not NULL or an actual pgVidInfoObject object.

+
+ +
+
+PyObject *pgVidInfo_New(SDL_VideoInfo *i)¶
+

Return a new pgVidInfoObject object for the SDL_VideoInfo i. +On failure, raise a Python exception and return NULL.

+
+ +
+
+int pgVidInfo_Check(PyObject *x)¶
+

Return true if x is a pgVidInfo_Type instance

+

Will return false if x is a subclass of pgVidInfo_Type. +This macro does not check that x is not NULL.

+
+ +
+
+ + +

+
+Edit on GitHub +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/c_api/event.html b/venv/Lib/site-packages/pygame/docs/generated/c_api/event.html new file mode 100644 index 0000000..be5bf1d --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/c_api/event.html @@ -0,0 +1,192 @@ + + + + + + + + + API exported by pygame.event — pygame v2.1.2 documentation + + + + + + + + + + + + + +
+ +
+ + + + + +
+
+ +
+
+ +
+
+

src_c/event.c¶

+

The extsion module pygame.eventpygame module for interacting with events and queues.

+

Header file: src_c/include/pygame.h

+
+
+type pgEventObject¶
+

The pygame.event.EventType object C struct.

+
+
+int type¶
+

The event type code.

+
+ +
+ +
+
+type pgEvent_Type¶
+

The pygame event object type pygame.event.EventType.

+
+ +
+
+int pgEvent_Check(PyObject *x)¶
+

Return true if x is a pygame event instance

+

Will return false if x is a subclass of event. +This is a macro. No check is made that x is not NULL.

+
+ +
+
+PyObject *pgEvent_New(SDL_Event *event)¶
+

Return a new pygame event instance for the SDL event. +If event is NULL then create an empty event object. +On failure raise a Python exception and return NULL.

+
+ +
+
+PyObject *pgEvent_New2(int type, PyObject *dict)¶
+

Return a new pygame event instance of SDL type and with +attribute dictionary dict. +If dict is NULL an empty attribute dictionary is created. +On failure raise a Python exception and return NULL.

+
+ +
+
+int pgEvent_FillUserEvent(pgEventObject *e, SDL_Event *event)¶
+

Fill SDL event event with information from pygame user event instance e. +Return 0 on success, -1 otherwise.

+
+ +
+
+ + +

+
+Edit on GitHub +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/c_api/freetype.html b/venv/Lib/site-packages/pygame/docs/generated/c_api/freetype.html new file mode 100644 index 0000000..db0f46a --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/c_api/freetype.html @@ -0,0 +1,180 @@ + + + + + + + + + API exported by pygame._freetype — pygame v2.1.2 documentation + + + + + + + + + + + + + +
+ +
+ + + + + +
+
+ +
+
+ +
+
+

src_c/_freetype.c¶

+

This extension module defines Python type pygame.freetype.FontCreate a new Font instance from a supported font file..

+

Header file: src_c/include/pygame_freetype.h

+
+
+type pgFontObject¶
+

The pygame.freetype.Font instance C struct.

+
+ +
+
+type pgFont_Type¶
+

The pygame.freetype.Font Python type.

+
+ +
+
+PyObject *pgFont_New(const char *filename, long font_index)¶
+

Open the font file with path filename and return a new +new pygame.freetype.Font instance for that font. +Set font_index to 0 unless the file contains multiple, indexed, fonts. +On error raise a Python exception and return NULL.

+
+ +
+
+int pgFont_Check(PyObject *x)¶
+

Return true if x is a pygame.freetype.Font instance. +Will return false for a subclass of Font. +This is a macro. No check is made that x is not NULL.

+
+ +
+
+int pgFont_IS_ALIVE(PyObject *o)¶
+

Return true if pygame.freetype.Font object o +is an open font file. +This is a macro. No check is made that o is not NULL +or not a Font instance.

+
+ +
+
+ + +

+
+Edit on GitHub +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/c_api/mixer.html b/venv/Lib/site-packages/pygame/docs/generated/c_api/mixer.html new file mode 100644 index 0000000..2128b79 --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/c_api/mixer.html @@ -0,0 +1,213 @@ + + + + + + + + + API exported by pygame.mixer — pygame v2.1.2 documentation + + + + + + + + + + + + + +
+ +
+ + + + + +
+
+ +
+
+ +
+
+

src_c/mixer.c¶

+

Python types and module startup/shutdown functions defined in the +pygame.mixerpygame module for loading and playing sounds extension module.

+

Header file: src_c/include/pygame_mixer.h

+
+
+type pgSoundObject¶
+

The pygame.mixer.Sound instance C structure.

+
+ +
+
+PyTypeObject *pgSound_Type¶
+

The pygame.mixer.Sound Python type.

+
+ +
+
+PyObject *pgSound_New(Mix_Chunk *chunk)¶
+

Return a new pygame.mixer.Sound instance for the SDL mixer chunk chunk. +On failure, raise a Python exception and return NULL.

+
+ +
+
+int pgSound_Check(PyObject *obj)¶
+

Return true if obj is an instance of type pgSound_Type, +but not a pgSound_Type subclass instance. +A macro.

+
+ +
+
+Mix_Chunk *pgSound_AsChunk(PyObject *x)¶
+

Return the SDL Mix_Chunk struct associated with the +pgSound_Type instance x. +A macro that does no NULL or Python type check on x.

+
+ +
+
+type pgChannelObject¶
+

The pygame.mixer.Channel instance C structure.

+
+ +
+
+PyTypeObject *pgChannel_Type¶
+

The pygame.mixer.Channel Python type.

+
+ +
+
+PyObject *pgChannel_New(int channelnum)¶
+

Return a new pygame.mixer.Channel instance for the SDL mixer +channel channelnum. +On failure, raise a Python exception and return NULL.

+
+ +
+
+int pgChannel_Check(PyObject *obj)¶
+

Return true if obj is an instance of type pgChannel_Type, +but not a pgChannel_Type subclass instance. +A macro.

+
+ +
+
+int pgChannel_AsInt(PyObject *x)¶
+

Return the SDL mixer music channel number associated with pgChannel_Type instance x. +A macro that does no NULL or Python type check on x.

+
+ +
+
+ + +

+
+Edit on GitHub +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/c_api/rect.html b/venv/Lib/site-packages/pygame/docs/generated/c_api/rect.html new file mode 100644 index 0000000..21708e3 --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/c_api/rect.html @@ -0,0 +1,202 @@ + + + + + + + + + Class Rect API exported by pygame.rect — pygame v2.1.2 documentation + + + + + + + + + + + + + +
+ +
+ + + + + +
+
+ +
+
+ +
+
+

src_c/rect.c¶

+

This extension module defines Python type pygame.Rectpygame object for storing rectangular coordinates.

+

Header file: src_c/include/pygame.h

+
+
+type pgRectObject¶
+
+
+SDL_Rect r¶
+
+ +

The Pygame rectangle type instance.

+
+ +
+
+PyTypeObject *pgRect_Type¶
+

The Pygame rectangle object type pygame.Rect.

+
+ +
+
+SDL_Rect pgRect_AsRect(PyObject *obj)¶
+

A macro to access the SDL_Rect field of a pygame.Rect instance.

+
+ +
+
+PyObject *pgRect_New(SDL_Rect *r)¶
+

Return a new pygame.Rect instance from the SDL_Rect r. +On failure, raise a Python exception and return NULL.

+
+ +
+
+PyObject *pgRect_New4(int x, int y, int w, int h)¶
+

Return a new pygame.Rect instance with position (x, y) and +size (w, h). +On failure raise a Python exception and return NULL.

+
+ +
+
+SDL_Rect *pgRect_FromObject(PyObject *obj, SDL_Rect *temp)¶
+

Translate a Python rectangle representation as a Pygame SDL_Rect. +A rectangle can be a length 4 sequence integers (x, y, w, h), +or a length 2 sequence of position (x, y) and size (w, h), +or a length 1 tuple containing a rectangle representation, +or have a method rect that returns a rectangle. +Pass a pointer to a locally declared SDL_Rect as temp. +Do not rely on this being filled in; use the function's return value instead. +On success, return a pointer to a SDL_Rect representation +of the rectangle, else return NULL. +No Python exceptions are raised.

+
+ +
+
+void pgRect_Normalize(SDL_Rect *rect)¶
+

Normalize the given rect. A rect with a negative size (negative width and/or +height) will be adjusted to have a positive size.

+
+ +
+
+ + +

+
+Edit on GitHub +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/c_api/rwobject.html b/venv/Lib/site-packages/pygame/docs/generated/c_api/rwobject.html new file mode 100644 index 0000000..f767e41 --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/c_api/rwobject.html @@ -0,0 +1,207 @@ + + + + + + + + + API exported by pygame.rwobject — pygame v2.1.2 documentation + + + + + + + + + + + + + +
+ +
+ + + + + +
+
+ +
+
+ +
+
+

src_c/rwobject.c¶

+

This extension module implements functions for wrapping a Python file like +object in a SDL_RWops struct for SDL file access.

+

Header file: src_c/include/pygame.h

+
+
+SDL_RWops *pgRWops_FromObject(PyObject *obj)¶
+

Return a SDL_RWops struct filled to access obj. +If obj is a string then let SDL open the file it names. +Otherwise, if obj is a Python file-like object then use its read, write, +seek, tell, and close methods. If threads are available, +the Python GIL is acquired before calling any of the obj methods. +On error raise a Python exception and return NULL.

+
+ +
+
+SDL_RWops *pgRWops_FromFileObject(PyObject *obj)¶
+

Return a SDL_RWops struct filled to access the Python file-like object obj. +Uses its read, write, seek, tell, and close methods. +If threads are available, the Python GIL is acquired before calling any of the obj methods. +On error raise a Python exception and return NULL.

+
+ +
+
+int pgRWops_IsFileObject(SDL_RWops *rw)¶
+

Return true if rw is a Python file-like object wrapper returned by pgRWops_FromObject() +or pgRWops_FromFileObject().

+
+ +
+
+char *pgRWops_GetFileExtension(SDL_RWops *rw)¶
+

Return a string that contains the file extension of the original file +loaded into the SDL_RWops object, or NULL if the SDL_RWops object comes +from a file object.

+
+ +
+
+int pgRWops_ReleaseObject(SDL_RWops *context)¶
+

Free a SDL_RWops struct. If it is attached to a Python file-like object, decrement its +refcount. Otherwise, close the file handle. +Return 0 on success. On error, raise a Python exception and return a negative value.

+
+ +
+
+PyObject *pg_EncodeFilePath(PyObject *obj, PyObject *eclass)¶
+

Return the file path obj as a byte string properly encoded for the OS. +Null bytes are forbidden in the encoded file path. +On error raise a Python exception and return NULL, +using eclass as the exception type if it is not NULL. +If obj is NULL assume an exception was already raised and pass it on.

+
+ +
+
+PyObject *pg_EncodeString(PyObject *obj, const char *encoding, const char *errors, PyObject *eclass)¶
+

Return string obj as an encoded byte string. +The C string arguments encoding and errors are the same as for +PyUnicode_AsEncodedString(). +On error raise a Python exception and return NULL, +using eclass as the exception type if it is not NULL. +If obj is NULL assume an exception was already raised and pass it on.

+
+ +
+
+ + +

+
+Edit on GitHub +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/c_api/slots.html b/venv/Lib/site-packages/pygame/docs/generated/c_api/slots.html new file mode 100644 index 0000000..852765d --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/c_api/slots.html @@ -0,0 +1,157 @@ + + + + + + + + + Slots and c_api - Making functions and data available from other modules — pygame v2.1.2 documentation + + + + + + + + + + + + + +
+ +
+ + + + + +
+
+ +
+
+ +
+

One example is pg_RGBAFromObj where the implementation is defined in base.c, and also exported in base.c (and _pygame.h).

+

base.c has this exposing the pg_RGBAFromObj function to the c_api structure:

+
+

c_api[12] = pg_RGBAFromObj;

+
+

Then in src_c/include/_pygame.h there is an

+
+

#define pg_RGBAFromObj.

+
+

Also in _pygame.h, it needs to define the number of slots the base module uses. This is PYGAMEAPI_BASE_NUMSLOTS. So if you were adding another function, you need to increment this PYGAMEAPI_BASE_NUMSLOTS number.

+

Then to use the pg_RGBAFromObj in other files,

+
    +
  1. include the "pygame.h" file,

  2. +
  3. they have to make sure base is imported with:

    +
    +

    import_pygame_base();

    +
    +
  4. +
+

Examples that use pg_RGBAFromObj are: _freetype.c, color.c, gfxdraw.c, and surface.c.

+
+ + +

+
+Edit on GitHub +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/c_api/surface.html b/venv/Lib/site-packages/pygame/docs/generated/c_api/surface.html new file mode 100644 index 0000000..4013702 --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/c_api/surface.html @@ -0,0 +1,194 @@ + + + + + + + + + Class Surface API exported by pygame.surface — pygame v2.1.2 documentation + + + + + + + + + + + + + +
+ +
+ + + + + +
+
+ +
+
+ +
+
+

src_c/surface.c¶

+

This extension module defines Python type pygame.Surfacepygame object for representing images.

+

Header file: src_c/include/pygame.h

+
+
+type pgSurfaceObject¶
+

A pygame.Surface instance.

+
+ +
+
+PyTypeObject *pgSurface_Type¶
+

The pygame.Surface Python type.

+
+ +
+
+int pgSurface_Check(PyObject *x)¶
+

Return true if x is a pygame.Surface instance

+

Will return false if x is a subclass of Surface. +This is a macro. No check is made that x is not NULL.

+
+ +
+
+pgSurfaceObject *pgSurface_New(SDL_Surface *s)¶
+

Return a new new pygame surface instance for SDL surface s. +Return NULL on error.

+
+ +
+
+SDL_Surface *pgSurface_AsSurface(PyObject *x)¶
+

Return a pointer the SDL surface represented by the pygame Surface instance +x.

+

This is a macro. Argument x is assumed to be a Surface, or subclass of +Surface, instance.

+
+ +
+
+int pgSurface_Blit(PyObject *dstobj, PyObject *srcobj, SDL_Rect *dstrect, SDL_Rect *srcrect, int the_args)¶
+

Blit the srcrect portion of Surface srcobj onto Surface dstobj at srcobj

+

Argument the_args indicates the type of blit to perform: +Normal blit (0), PYGAME_BLEND_ADD, PYGAME_BLEND_SUB, +PYGAME_BLEND_SUB, PYGAME_BLEND_MULT, PYGAME_BLEND_MIN, +PYGAME_BLEND_MAX, PYGAME_BLEND_RGBA_ADD, PYGAME_BLEND_RGBA_SUB, +PYGAME_BLEND_RGBA_MULT, PYGAME_BLEND_RGBA_MIN, +PYGAME_BLEND_RGBA_MAX, PYGAME_BLEND_ALPHA_SDL2 and PYGAME_BLEND_PREMULTIPLIED. +Argument dstrect is updated to the actual area on dstobj affected +by the blit.

+

The C version of the pygame.Surface.blit() method. +Return 1 on success, 0 on an exception.

+
+ +
+
+ + +

+
+Edit on GitHub +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/c_api/surflock.html b/venv/Lib/site-packages/pygame/docs/generated/c_api/surflock.html new file mode 100644 index 0000000..f25e3b4 --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/c_api/surflock.html @@ -0,0 +1,231 @@ + + + + + + + + + API exported by pygame.surflock — pygame v2.1.2 documentation + + + + + + + + + + + + + +
+ +
+ + + + + +
+
+ +
+
+ +
+
+

src_c/surflock.c¶

+

This extension module implements SDL surface locking for the +pygame.Surfacepygame object for representing images type.

+

Header file: src_c/include/pygame.h

+
+
+type pgLifetimeLockObject¶
+
+
+PyObject *surface¶
+

An SDL locked pygame surface.

+
+ +
+
+PyObject *lockobj¶
+

The Python object which owns the lock on the surface. +This field does not own a reference to the object.

+
+ +

The lifetime lock type instance. +A lifetime lock pairs a locked pygame surface with +the Python object that locked the surface for modification. +The lock is removed automatically when the lifetime lock instance +is garbage collected.

+
+ +
+
+PyTypeObject *pgLifetimeLock_Type¶
+

The pygame internal surflock lifetime lock object type.

+
+ +
+
+int pgLifetimeLock_Check(PyObject *x)¶
+

Return true if Python object x is a pgLifetimeLock_Type instance, +false otherwise. +This will return false on pgLifetimeLock_Type subclass instances as well.

+
+ +
+
+void pgSurface_Prep(pgSurfaceObject *surfobj)¶
+

If surfobj is a subsurface, then lock the parent surface with surfobj +the owner of the lock.

+
+ +
+
+void pgSurface_Unprep(pgSurfaceObject *surfobj)¶
+

If surfobj is a subsurface, then release its lock on the parent surface.

+
+ +
+
+int pgSurface_Lock(pgSurfaceObject *surfobj)¶
+

Lock pygame surface surfobj, with surfobj owning its own lock.

+
+ +
+
+int pgSurface_LockBy(pgSurfaceObject *surfobj, PyObject *lockobj)¶
+

Lock pygame surface surfobj with Python object lockobj the owning +the lock.

+

The surface will keep a weak reference to object lockobj, +and eventually remove the lock on itself if lockobj is garbage collected. +However, it is best if lockobj also keep a reference to the locked surface +and call to pgSurface_UnLockBy() when finished with the surface.

+
+ +
+
+int pgSurface_UnLock(pgSurfaceObject *surfobj)¶
+

Remove the pygame surface surfobj object's lock on itself.

+
+ +
+
+int pgSurface_UnLockBy(pgSurfaceObject *surfobj, PyObject *lockobj)¶
+

Remove the lock on pygame surface surfobj owned by Python object lockobj.

+
+ +
+
+PyObject *pgSurface_LockLifetime(PyObject *surfobj, PyObject *lockobj)¶
+

Lock pygame surface surfobj for Python object lockobj and return a +new pgLifetimeLock_Type instance for the lock.

+

This function is not called anywhere within pygame. +It and pgLifetimeLock_Type are candidates for removal.

+
+ +
+
+ + +

+
+Edit on GitHub +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/c_api/version.html b/venv/Lib/site-packages/pygame/docs/generated/c_api/version.html new file mode 100644 index 0000000..e05ad33 --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/c_api/version.html @@ -0,0 +1,173 @@ + + + + + + + + + API exported by pygame.version — pygame v2.1.2 documentation + + + + + + + + + + + + + +
+ +
+ + + + + +
+
+ +
+
+ +
+
+

src_py/version.py¶

+

Header file: src_c/include/pygame.h

+

Version information can be retrieved at compile-time using these macros.

+
+

New in pygame 1.9.5.

+
+
+
+PG_MAJOR_VERSION¶
+
+ +
+
+PG_MINOR_VERSION¶
+
+ +
+
+PG_PATCH_VERSION¶
+
+ +
+
+PG_VERSIONNUM(MAJOR, MINOR, PATCH)¶
+

Returns an integer representing the given version.

+
+ +
+
+PG_VERSION_ATLEAST(MAJOR, MINOR, PATCH)¶
+

Returns true if the current version is at least equal +to the specified version.

+
+ +
+
+ + +

+
+Edit on GitHub +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/filepaths.html b/venv/Lib/site-packages/pygame/docs/generated/filepaths.html new file mode 100644 index 0000000..be6419c --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/filepaths.html @@ -0,0 +1,145 @@ + + + + + + + + + File Path Function Arguments — pygame v2.1.2 documentation + + + + + + + + + + + + +
+ +
+ + + + + +
+
+ +
+
+ +
+

A pygame function or method which takes a file path argument will accept +either a Unicode or a byte (8-bit or ASCII character) string. +Unicode strings are translated to Python's default filesystem encoding, +as returned by sys.getfilesystemencoding(). A Unicode code point +above U+FFFF (\uFFFF) can be coded directly with a 32-bit escape sequences +(\Uxxxxxxxx), even for Python interpreters built with an UCS-2 +(16-bit character) Unicode type. Byte strings are passed +to the operating system unchanged.

+

Null characters (\x00) are not permitted in the path, raising an exception. +An exception is also raised if an Unicode file path cannot be encoded. +How UTF-16 surrogate codes are handled is Python-interpreter-dependent. +Use UTF-32 code points and 32-bit escape sequences instead. +The exception types are function-dependent.

+
+ + +

+
+Edit on GitHub +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/genindex.html b/venv/Lib/site-packages/pygame/docs/generated/genindex.html new file mode 100644 index 0000000..45d036c --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/genindex.html @@ -0,0 +1,2604 @@ + + + + + + + + Index — pygame v2.1.2 documentation + + + + + + + + + + + + +
+
+
+ + +

Index

+ +
+ _ + | A + | B + | C + | D + | E + | F + | G + | H + | I + | J + | K + | L + | M + | N + | O + | P + | Q + | R + | S + | T + | U + | V + | W + +
+

_

+ + + +
+ +

A

+ + + +
+ +

B

+ + + +
+ +

C

+ + + +
+ +

D

+ + + +
+ +

E

+ + + +
+ +

F

+ + + +
+ +

G

+ + + +
+ +

H

+ + + +
+ +

I

+ + + +
+ +

J

+ + + +
+ +

K

+ + + +
+ +

L

+ + + +
+ +

M

+ + + +
+ +

N

+ + + +
+ +

O

+ + + +
+ +

P

+ + + +
+ +

Q

+ + +
+ +

R

+ + + +
+ +

S

+ + + +
+ +

T

+ + + +
+ +

U

+ + + +
+ +

V

+ + + +
+ +

W

+ + + +
+ + + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/index.html b/venv/Lib/site-packages/pygame/docs/generated/index.html new file mode 100644 index 0000000..6cc1417 --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/index.html @@ -0,0 +1,258 @@ + + + + + + + + + Pygame Front Page — pygame v2.1.2 documentation + + + + + + + + + + + + +
+ +
+ + + + + +
+
+ +
+
+ +
+

Pygame Front Page¶

+
+
+
+

Documents¶

+
+
Readme

Basic information about pygame: what it is, who is involved, and where to find it.

+
+
Install

Steps needed to compile pygame on several platforms. +Also help on finding and installing prebuilt binaries for your system.

+
+
File Path Function Arguments

How pygame handles file system paths.

+
+
LGPL License

This is the license pygame is distributed under. +It provides for pygame to be distributed with open source and commercial software. +Generally, if pygame is not changed, it can be used with any type of program.

+
+
+
+
+

Tutorials¶

+
+
Introduction to Pygame

An introduction to the basics of pygame. +This is written for users of Python and appeared in volume two of the Py magazine.

+
+
Import and Initialize

The beginning steps on importing and initializing pygame. +The pygame package is made of several modules. +Some modules are not included on all platforms.

+
+
How do I move an Image?

A basic tutorial that covers the concepts behind 2D computer animation. +Information about drawing and clearing objects to make them appear animated.

+
+
Chimp Tutorial, Line by Line

The pygame examples include a simple program with an interactive fist and a chimpanzee. +This was inspired by the annoying flash banner of the early 2000s. +This tutorial examines every line of code used in the example.

+
+
Sprite Module Introduction

Pygame includes a higher level sprite module to help organize games. +The sprite module includes several classes that help manage details found in almost all games types. +The Sprite classes are a bit more advanced than the regular pygame modules, +and need more understanding to be properly used.

+
+
Surfarray Introduction

Pygame used the NumPy python module to allow efficient per pixel effects on images. +Using the surface arrays is an advanced feature that allows custom effects and filters. +This also examines some of the simple effects from the pygame example, arraydemo.py.

+
+
Camera Module Introduction

Pygame, as of 1.9, has a camera module that allows you to capture images, +watch live streams, and do some basic computer vision. +This tutorial covers those use cases.

+
+
Newbie Guide

A list of thirteen helpful tips for people to get comfortable using pygame.

+
+
Making Games Tutorial

A large tutorial that covers the bigger topics needed to create an entire game.

+
+
Display Modes

Getting a display surface for the screen.

+
+
한국어 튜토리얼 (Korean Tutorial)

ë¹¨ê°„ë¸”ë¡ ê²€ì€ë¸”ë¡

+
+
+
+
+

Reference¶

+
+
Index

A list of all functions, classes, and methods in the pygame package.

+
+
pygame.BufferProxy

An array protocol view of surface pixels

+
+
pygame.Color

Color representation.

+
+
pygame.cursors

Loading and compiling cursor images.

+
+
pygame.display

Configure the display surface.

+
+
pygame.draw

Drawing simple shapes like lines and ellipses to surfaces.

+
+
pygame.event

Manage the incoming events from various input devices and the windowing platform.

+
+
pygame.examples

Various programs demonstrating the use of individual pygame modules.

+
+
pygame.font

Loading and rendering TrueType fonts.

+
+
pygame.freetype

Enhanced pygame module for loading and rendering font faces.

+
+
pygame.gfxdraw

Anti-aliasing draw functions.

+
+
pygame.image

Loading, saving, and transferring of surfaces.

+
+
pygame.joystick

Manage the joystick devices.

+
+
pygame.key

Manage the keyboard device.

+
+
pygame.locals

Pygame constants.

+
+
pygame.mixer

Load and play sounds

+
+
pygame.mouse

Manage the mouse device and display.

+
+
pygame.mixer.music

Play streaming music tracks.

+
+
pygame

Top level functions to manage pygame.

+
+
pygame.PixelArray

Manipulate image pixel data.

+
+
pygame.Rect

Flexible container for a rectangle.

+
+
pygame.scrap

Native clipboard access.

+
+
pygame.sndarray

Manipulate sound sample data.

+
+
pygame.sprite

Higher level objects to represent game images.

+
+
pygame.Surface

Objects for images and the screen.

+
+
pygame.surfarray

Manipulate image pixel data.

+
+
pygame.tests

Test pygame.

+
+
pygame.time

Manage timing and framerate.

+
+
pygame.transform

Resize and move images.

+
+
pygame C API

The C api shared amongst pygame extension modules.

+
+
Search Page

Search pygame documents by keyword.

+
+
+
+
+ + +

+
+Edit on GitHub +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/py-modindex.html b/venv/Lib/site-packages/pygame/docs/generated/py-modindex.html new file mode 100644 index 0000000..45a5aa1 --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/py-modindex.html @@ -0,0 +1,251 @@ + + + + + + + + Python Module Index — pygame v2.1.2 documentation + + + + + + + + + + + + + + + +
+
+
+ + +

Python Module Index

+ +
+ . | + p +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 
+ .
    + pygame._sdl2.controller + pygame module to work with controllers
    + pygame._sdl2.touch + pygame module to work with touch input
    + pygame._sdl2.video + Experimental pygame module for porting new SDL video systems
    + pygame.camera + pygame module for camera use
    + pygame.cdrom + pygame module for audio cdrom control
    + pygame.cursors + pygame module for cursor resources
    + pygame.display + pygame module to control the display window and screen
    + pygame.draw + pygame module for drawing shapes
    + pygame.event + pygame module for interacting with events and queues
    + pygame.examples + module of example programs
    + pygame.fastevent + pygame module for interacting with events and queues from multiple +threads.
    + pygame.font + pygame module for loading and rendering fonts
    + pygame.freetype + Enhanced pygame module for loading and rendering computer fonts
    + pygame.gfxdraw + pygame module for drawing shapes
    + pygame.image + pygame module for image transfer
    + pygame.joystick + Pygame module for interacting with joysticks, gamepads, and trackballs.
    + pygame.key + pygame module to work with the keyboard
    + pygame.locals + pygame constants
    + pygame.mask + pygame module for image masks.
    + pygame.math + pygame module for vector classes
    + pygame.midi + pygame module for interacting with midi input and output.
    + pygame.mixer + pygame module for loading and playing sounds
    + pygame.mixer.music + pygame module for controlling streamed audio
    + pygame.mouse + pygame module to work with the mouse
    + pygame.pixelcopy + pygame module for general pixel array copying
    + pygame.scrap + pygame module for clipboard support.
    + pygame.sndarray + pygame module for accessing sound sample data
    + pygame.sprite + pygame module with basic game object classes
    + pygame.surfarray + pygame module for accessing surface pixel data using array interfaces
    + pygame.tests + Pygame unit test suite package
    + pygame.time + pygame module for monitoring time
    + pygame.transform + pygame module to transform surfaces
    + pygame.version + small module containing version information
 
+ p
+ pygame + the top level pygame package
+ + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/ref/bufferproxy.html b/venv/Lib/site-packages/pygame/docs/generated/ref/bufferproxy.html new file mode 100644 index 0000000..d41ad94 --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/ref/bufferproxy.html @@ -0,0 +1,283 @@ + + + + + + + + + pygame.BufferProxy — pygame v2.1.2 documentation + + + + + + + + + + + + + +
+ +
+ + + + + +
+
+ +
+
+ +
+
+
+pygame.BufferProxy¶
+
+
pygame object to export a surface buffer through an array protocol
+
BufferProxy(<parent>) -> BufferProxy
+
+ +++++ + + + + + + + + + + + + + + + + + + +
+—Return wrapped exporting object.
+—The size, in bytes, of the exported buffer.
+—A copy of the exported buffer as a single block of bytes.
+—Write raw bytes to object buffer.
+

BufferProxy is a pygame support type, designed as the return value +of the Surface.get_buffer() and Surface.get_view() methods. +For all Python versions a BufferProxy object exports a C struct +and Python level array interface on behalf of its parent object's buffer. +A new buffer interface is also exported. +In pygame, BufferProxy is key to implementing the +pygame.surfarraypygame module for accessing surface pixel data using array interfaces module.

+

BufferProxy instances can be created directly from Python code, +either for a parent that exports an interface, or from a Python dict +describing an object's buffer layout. The dict entries are based on the +Python level array interface mapping. The following keys are recognized:

+
+
+
"shape"tuple

The length of each array dimension as a tuple of integers. The +length of the tuple is the number of dimensions in the array.

+
+
"typestr"string

The array element type as a length 3 string. The first character +gives byteorder, '<' for little-endian, '>' for big-endian, and +'|' for not applicable. The second character is the element type, +'i' for signed integer, 'u' for unsigned integer, 'f' for floating +point, and 'V' for an chunk of bytes. The third character gives the +bytesize of the element, from '1' to '9' bytes. So, for example, +"<u4" is an unsigned 4 byte little-endian integer, such as a +32 bit pixel on a PC, while "|V3" would represent a 24 bit pixel, +which has no integer equivalent.

+
+
"data"tuple

The physical buffer start address and a read-only flag as a length +2 tuple. The address is an integer value, while the read-only flag +is a bool—False for writable, True for read-only.

+
+
"strides"tuple(optional)

Array stride information as a tuple of integers. It is required +only of non C-contiguous arrays. The tuple length must match +that of "shape".

+
+
"parent"object(optional)

The exporting object. It can be used to keep the parent object +alive while its buffer is visible.

+
+
"before"callable(optional)

Callback invoked when the BufferProxy instance +exports the buffer. The callback is given one argument, the +"parent" object if given, otherwise None. +The callback is useful for setting a lock on the parent.

+
+
"after"callable(optional)

Callback invoked when an exported buffer is released. +The callback is passed on argument, the "parent" object if given, +otherwise None. The callback is useful for releasing a lock on the +parent.

+
+
+
+

The BufferProxy class supports subclassing, instance variables, and weak +references.

+
+

New in pygame 1.8.0.

+
+
+

Extended in pygame 1.9.2.

+
+
+
+parent¶
+
+
Return wrapped exporting object.
+
parent -> Surface
+
parent -> <parent>
+
+

The Surface which returned the BufferProxy object or +the object passed to a BufferProxy call.

+
+ +
+
+length¶
+
+
The size, in bytes, of the exported buffer.
+
length -> int
+
+

The number of valid bytes of data exported. For discontinuous data, +that is data which is not a single block of memory, the bytes within +the gaps are excluded from the count. This property is equivalent to +the Py_buffer C struct len field.

+
+ +
+
+raw¶
+
+
A copy of the exported buffer as a single block of bytes.
+
raw -> bytes
+
+

The buffer data as a str/bytes object. +Any gaps in the exported data are removed.

+
+ +
+
+write()¶
+
+
Write raw bytes to object buffer.
+
write(buffer, offset=0)
+
+

Overwrite bytes in the parent object's data. The data must be C or F +contiguous, otherwise a ValueError is raised. Argument buffer is a +str/bytes object. An optional offset gives a +start position, in bytes, within the buffer where overwriting begins. +If the offset is negative or greater that or equal to the buffer proxy's +length value, an IndexException is raised. +If len(buffer) > proxy.length + offset, a ValueError is raised.

+
+ +
+ +
+ + +

+
+Edit on GitHub +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/ref/camera.html b/venv/Lib/site-packages/pygame/docs/generated/ref/camera.html new file mode 100644 index 0000000..1ee0b29 --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/ref/camera.html @@ -0,0 +1,472 @@ + + + + + + + + + pygame.camera — pygame v2.1.2 documentation + + + + + + + + + + + + + +
+ +
+ + + + + +
+
+ +
+
+ +
+
+
+pygame.camera
+
+
pygame module for camera use
+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + +
+—Module init
+—Get the backends supported on this system
+—Surface colorspace conversion
+—returns a list of available cameras
+—load a camera
+

Pygame currently supports Linux (V4L2) and Windows (MSMF) cameras natively, +with wider platform support available via an integrated OpenCV backend.

+
+

New in pygame 2.0.2: Windows native camera support

+
+
+

New in pygame 2.0.3: New OpenCV backends

+
+

EXPERIMENTAL!: This API may change or disappear in later pygame releases. If +you use this, your code will very likely break with the next pygame release.

+

The Bayer to RGB function is based on:

+
Sonix SN9C101 based webcam basic I/F routines
+Copyright (C) 2004 Takafumi Mizuno <taka-qce@ls-a.jp>
+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.
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+
+
+

New in pygame 1.9.0.

+
+
+pygame.camera.init()¶
+
+
Module init
+
init(backend = None) -> None
+
+

This function starts up the camera module, choosing the best webcam backend +it can find for your system. This is not guaranteed to succeed, and may even +attempt to import third party modules, like OpenCV. If you want to +override its backend choice, you can call pass the name of the backend you +want into this function. More about backends in +get_backends().

+
+

Changed in pygame 2.0.3: Option to explicitly select backend

+
+
+ +
+
+pygame.camera.get_backends()¶
+
+
Get the backends supported on this system
+
get_backends() -> [str]
+
+

This function returns every backend it thinks has a possibility of working +on your system, in order of priority.

+

pygame.camera Backends:

+
Backend           OS        Description
+---------------------------------------------------------------------------------
+_camera (MSMF)    Windows   Builtin, works on Windows 8+ Python3
+_camera (V4L2)    Linux     Builtin
+OpenCV            Any       Uses `opencv-python` module, can't enumerate cameras
+OpenCV-Mac        Mac       Same as OpenCV, but has camera enumeration
+VideoCapture      Windows   Uses abandoned `VideoCapture` module, can't enumerate
+                            cameras, may be removed in the future
+
+
+

There are two main differences among backends.

+

The _camera backends are built in to pygame itself, and require no third +party imports. All the other backends do. For the OpenCV and VideoCapture +backends, those modules need to be installed on your system.

+

The other big difference is "camera enumeration." Some backends don't have +a way to list out camera names, or even the number of cameras on the +system. In these cases, list_cameras() will return +something like [0]. If you know you have multiple cameras on the +system, these backend ports will pass through a "camera index number" +through if you use that as the device parameter.

+
+

New in pygame 2.0.3.

+
+
+ +
+
+pygame.camera.colorspace()¶
+
+
Surface colorspace conversion
+
colorspace(Surface, format, DestSurface = None) -> Surface
+
+

Allows for conversion from "RGB" to a destination colorspace of "HSV" or +"YUV". The source and destination surfaces must be the same size and pixel +depth. This is useful for computer vision on devices with limited processing +power. Capture as small of an image as possible, transform.scale() it +even smaller, and then convert the colorspace to YUV or HSV before +doing any processing on it.

+
+ +
+
+pygame.camera.list_cameras()¶
+
+
returns a list of available cameras
+
list_cameras() -> [cameras]
+
+

Checks the computer for available cameras and returns a list of strings of +camera names, ready to be fed into pygame.camera.Cameraload a camera.

+

If the camera backend doesn't support webcam enumeration, this will return +something like [0]. See get_backends() for much more +information.

+
+ +
+
+pygame.camera.Camera¶
+
+
load a camera
+
Camera(device, (width, height), format) -> Camera
+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+—opens, initializes, and starts capturing
+—stops, uninitializes, and closes the camera
+—gets current values of user controls
+—changes camera settings if supported by the camera
+—returns the dimensions of the images being recorded
+—checks if a frame is ready
+—captures an image as a Surface
+—returns an unmodified image as bytes
+

Loads a camera. On Linux, the device is typically something like +"/dev/video0". Default width and height are 640 by 480. +Format is the desired colorspace of the output. +This is useful for computer vision purposes. The default is +RGB. The following are supported:

+
+
    +
  • RGB - Red, Green, Blue

  • +
  • YUV - Luma, Blue Chrominance, Red Chrominance

  • +
  • HSV - Hue, Saturation, Value

  • +
+
+
+
+start()¶
+
+
opens, initializes, and starts capturing
+
start() -> None
+
+

Opens the camera device, attempts to initialize it, and begins recording +images to a buffer. The camera must be started before any of the below +functions can be used.

+
+ +
+
+stop()¶
+
+
stops, uninitializes, and closes the camera
+
stop() -> None
+
+

Stops recording, uninitializes the camera, and closes it. Once a camera +is stopped, the below functions cannot be used until it is started again.

+
+ +
+
+get_controls()¶
+
+
gets current values of user controls
+
get_controls() -> (hflip = bool, vflip = bool, brightness)
+
+

If the camera supports it, get_controls will return the current settings +for horizontal and vertical image flip as bools and brightness as an int. +If unsupported, it will return the default values of (0, 0, 0). Note that +the return values here may be different than those returned by +set_controls, though these are more likely to be correct.

+
+ +
+
+set_controls()¶
+
+
changes camera settings if supported by the camera
+
set_controls(hflip = bool, vflip = bool, brightness) -> (hflip = bool, vflip = bool, brightness)
+
+

Allows you to change camera settings if the camera supports it. The +return values will be the input values if the camera claims it succeeded +or the values previously in use if not. Each argument is optional, and +the desired one can be chosen by supplying the keyword, like hflip. Note +that the actual settings being used by the camera may not be the same as +those returned by set_controls. On Windows, hflip and vflip are +implemented by pygame, not by the Camera, so they should always work, but +brightness is unsupported.

+
+ +
+
+get_size()¶
+
+
returns the dimensions of the images being recorded
+
get_size() -> (width, height)
+
+

Returns the current dimensions of the images being captured by the +camera. This will return the actual size, which may be different than the +one specified during initialization if the camera did not support that +size.

+
+ +
+
+query_image()¶
+
+
checks if a frame is ready
+
query_image() -> bool
+
+

If an image is ready to get, it returns true. Otherwise it returns false. +Note that some webcams will always return False and will only queue a +frame when called with a blocking function like get_image(). +On Windows (MSMF), and the OpenCV backends, query_image() +should be reliable, though. This is useful to separate the framerate of +the game from that of the camera without having to use threading.

+
+ +
+
+get_image()¶
+
+
captures an image as a Surface
+
get_image(Surface = None) -> Surface
+
+

Pulls an image off of the buffer as an RGB Surface. It can optionally +reuse an existing Surface to save time. The bit-depth of the surface is +24 bits on Linux, 32 bits on Windows, or the same as the optionally +supplied Surface.

+
+ +
+
+get_raw()¶
+
+
returns an unmodified image as bytes
+
get_raw() -> bytes
+
+

Gets an image from a camera as a string in the native pixelformat of the +camera. Useful for integration with other libraries. This returns a +bytes object

+
+ +
+ +
+ +
+ + +

+
+Edit on GitHub +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/ref/cdrom.html b/venv/Lib/site-packages/pygame/docs/generated/ref/cdrom.html new file mode 100644 index 0000000..8cdfa31 --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/ref/cdrom.html @@ -0,0 +1,592 @@ + + + + + + + + + pygame.cdrom — pygame v2.1.2 documentation + + + + + + + + + + + + + +
+ +
+ + + + + +
+
+ +
+
+ +
+
+
+pygame.cdrom
+
+
pygame module for audio cdrom control
+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + +
+—initialize the cdrom module
+—uninitialize the cdrom module
+—true if the cdrom module is initialized
+—number of cd drives on the system
+—class to manage a cdrom drive
+
+

Warning

+

This module is non functional in pygame 2.0 and above, unless you have manually compiled pygame with SDL1. +This module will not be supported in the future. +One alternative for python cdrom functionality is pycdio.

+
+

The cdrom module manages the CD and DVD drives on a computer. It can +also control the playback of audio CDs. This module needs to be initialized +before it can do anything. Each CD object you create represents a cdrom +drive and must also be initialized individually before it can do most things.

+
+
+pygame.cdrom.init()¶
+
+
initialize the cdrom module
+
init() -> None
+
+

Initialize the cdrom module. This will scan the system for all CD +devices. The module must be initialized before any other functions will +work. This automatically happens when you call pygame.init().

+

It is safe to call this function more than once.

+
+ +
+
+pygame.cdrom.quit()¶
+
+
uninitialize the cdrom module
+
quit() -> None
+
+

Uninitialize the cdrom module. After you call this any existing CD +objects will no longer work.

+

It is safe to call this function more than once.

+
+ +
+
+pygame.cdrom.get_init()¶
+
+
true if the cdrom module is initialized
+
get_init() -> bool
+
+

Test if the cdrom module is initialized or not. This is different than the +CD.init() since each drive must also be initialized individually.

+
+ +
+
+pygame.cdrom.get_count()¶
+
+
number of cd drives on the system
+
get_count() -> count
+
+

Return the number of cd drives on the system. When you create CD objects +you need to pass an integer id that must be lower than this count. The count +will be 0 if there are no drives on the system.

+
+ +
+
+pygame.cdrom.CD¶
+
+
class to manage a cdrom drive
+
CD(id) -> CD
+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+—initialize a cdrom drive for use
+—uninitialize a cdrom drive for use
+—true if this cd device initialized
+—start playing audio
+—stop audio playback
+—temporarily stop audio playback
+—unpause audio playback
+—eject or open the cdrom drive
+—the index of the cdrom drive
+—the system name of the cdrom drive
+—true if the drive is playing audio
+—true if the drive is paused
+—the current audio playback position
+—False if a cdrom is in the drive
+—the number of tracks on the cdrom
+—true if the cdrom track has audio data
+—get all track information
+—start time of a cdrom track
+—length of a cdrom track
+

You can create a CD object for each cdrom on the system. Use +pygame.cdrom.get_count() to determine how many drives actually exist. +The id argument is an integer of the drive, starting at zero.

+

The CD object is not initialized, you can only call CD.get_id() and +CD.get_name() on an uninitialized drive.

+

It is safe to create multiple CD objects for the same drive, they will +all cooperate normally.

+
+
+init()¶
+
+
initialize a cdrom drive for use
+
init() -> None
+
+

Initialize the cdrom drive for use. The drive must be initialized for +most CD methods to work. Even if the rest of pygame has been +initialized.

+

There may be a brief pause while the drive is initialized. Avoid +CD.init() if the program should not stop for a second or two.

+
+ +
+
+quit()¶
+
+
uninitialize a cdrom drive for use
+
quit() -> None
+
+

Uninitialize a drive for use. Call this when your program will not be +accessing the drive for awhile.

+
+ +
+
+get_init()¶
+
+
true if this cd device initialized
+
get_init() -> bool
+
+

Test if this CDROM device is initialized. This is different than the +pygame.cdrom.init() since each drive must also be initialized +individually.

+
+ +
+
+play()¶
+
+
start playing audio
+
play(track, start=None, end=None) -> None
+
+

Playback audio from an audio cdrom in the drive. Besides the track number +argument, you can also pass a starting and ending time for playback. The +start and end time are in seconds, and can limit the section of an audio +track played.

+

If you pass a start time but no end, the audio will play to the end of +the track. If you pass a start time and 'None' for the end time, the +audio will play to the end of the entire disc.

+

See the CD.get_numtracks() and CD.get_track_audio() to find +tracks to playback.

+

Note, track 0 is the first track on the CD. Track numbers start at +zero.

+
+ +
+
+stop()¶
+
+
stop audio playback
+
stop() -> None
+
+

Stops playback of audio from the cdrom. This will also lose the current +playback position. This method does nothing if the drive isn't already +playing audio.

+
+ +
+
+pause()¶
+
+
temporarily stop audio playback
+
pause() -> None
+
+

Temporarily stop audio playback on the CD. The playback can be +resumed at the same point with the CD.resume() method. If the CD +is not playing this method does nothing.

+

Note, track 0 is the first track on the CD. Track numbers start at +zero.

+
+ +
+
+resume()¶
+
+
unpause audio playback
+
resume() -> None
+
+

Unpause a paused CD. If the CD is not paused or already playing, +this method does nothing.

+
+ +
+
+eject()¶
+
+
eject or open the cdrom drive
+
eject() -> None
+
+

This will open the cdrom drive and eject the cdrom. If the drive is +playing or paused it will be stopped.

+
+ +
+
+get_id()¶
+
+
the index of the cdrom drive
+
get_id() -> id
+
+

Returns the integer id that was used to create the CD instance. This +method can work on an uninitialized CD.

+
+ +
+
+get_name()¶
+
+
the system name of the cdrom drive
+
get_name() -> name
+
+

Return the string name of the drive. This is the system name used to +represent the drive. It is often the drive letter or device name. This +method can work on an uninitialized CD.

+
+ +
+
+get_busy()¶
+
+
true if the drive is playing audio
+
get_busy() -> bool
+
+

Returns True if the drive busy playing back audio.

+
+ +
+
+get_paused()¶
+
+
true if the drive is paused
+
get_paused() -> bool
+
+

Returns True if the drive is currently paused.

+
+ +
+
+get_current()¶
+
+
the current audio playback position
+
get_current() -> track, seconds
+
+

Returns both the current track and time of that track. This method works +when the drive is either playing or paused.

+

Note, track 0 is the first track on the CD. Track numbers start at +zero.

+
+ +
+
+get_empty()¶
+
+
False if a cdrom is in the drive
+
get_empty() -> bool
+
+

Return False if there is a cdrom currently in the drive. If the drive is +empty this will return True.

+
+ +
+
+get_numtracks()¶
+
+
the number of tracks on the cdrom
+
get_numtracks() -> count
+
+

Return the number of tracks on the cdrom in the drive. This will return +zero of the drive is empty or has no tracks.

+
+ +
+
+get_track_audio()¶
+
+
true if the cdrom track has audio data
+
get_track_audio(track) -> bool
+
+

Determine if a track on a cdrom contains audio data. You can also call +CD.num_tracks() and CD.get_all() to determine more information +about the cdrom.

+

Note, track 0 is the first track on the CD. Track numbers start at +zero.

+
+ +
+
+get_all()¶
+
+
get all track information
+
get_all() -> [(audio, start, end, length), ...]
+
+

Return a list with information for every track on the cdrom. The +information consists of a tuple with four values. The audio value is True +if the track contains audio data. The start, end, and length values are +floating point numbers in seconds. Start and end represent absolute times +on the entire disc.

+
+ +
+
+get_track_start()¶
+
+
start time of a cdrom track
+
get_track_start(track) -> seconds
+
+

Return the absolute time in seconds where at start of the cdrom track.

+

Note, track 0 is the first track on the CD. Track numbers start at +zero.

+
+ +
+
+get_track_length()¶
+
+
length of a cdrom track
+
get_track_length(track) -> seconds
+
+

Return a floating point value in seconds of the length of the cdrom +track.

+

Note, track 0 is the first track on the CD. Track numbers start at +zero.

+
+ +
+ +
+ +
+ + +

+
+Edit on GitHub +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/ref/color.html b/venv/Lib/site-packages/pygame/docs/generated/ref/color.html new file mode 100644 index 0000000..1de2df9 --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/ref/color.html @@ -0,0 +1,508 @@ + + + + + + + + + pygame.Color — pygame v2.1.2 documentation + + + + + + + + + + + + + +
+ +
+ + + + + +
+
+ +
+
+ +
+
+
+pygame.Color¶
+
+
pygame object for color representations
+
Color(r, g, b) -> Color
+
Color(r, g, b, a=255) -> Color
+
Color(color_value) -> Color
+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+—Gets or sets the red value of the Color.
+—Gets or sets the green value of the Color.
+—Gets or sets the blue value of the Color.
+—Gets or sets the alpha value of the Color.
+—Gets or sets the CMY representation of the Color.
+—Gets or sets the HSVA representation of the Color.
+—Gets or sets the HSLA representation of the Color.
+—Gets or sets the I1I2I3 representation of the Color.
+—Returns the normalized RGBA values of the Color.
+—Applies a certain gamma value to the Color.
+—Set the number of elements in the Color to 1,2,3, or 4.
+—returns a linear interpolation to the given Color.
+—returns a Color where the r,g,b components have been multiplied by the alpha.
+—Sets the elements of the color
+

The Color class represents RGBA color values using a value range of +0 to 255 inclusive. It allows basic arithmetic operations — binary +operations +, -, *, //, %, and unary operation ~ — to +create new colors, supports conversions to other color spaces such as HSV +or HSL and lets you adjust single color channels. +Alpha defaults to 255 (fully opaque) when not given. +The arithmetic operations and correct_gamma() method preserve subclasses. +For the binary operators, the class of the returned color is that of the +left hand color object of the operator.

+

Color objects support equality comparison with other color objects and 3 or +4 element tuples of integers. There was a bug in pygame 1.8.1 +where the default alpha was 0, not 255 like previously.

+

Color objects export the C level array interface. The interface exports a +read-only one dimensional unsigned byte array of the same assigned length +as the color. The new buffer interface is also exported, with the same +characteristics as the array interface.

+

The floor division, //, and modulus, %, operators do not raise +an exception for division by zero. Instead, if a color, or alpha, channel +in the right hand color is 0, then the result is 0. For example:

+
# These expressions are True
+Color(255, 255, 255, 255) // Color(0, 64, 64, 64) == Color(0, 3, 3, 3)
+Color(255, 255, 255, 255) % Color(64, 64, 64, 0) == Color(63, 63, 63, 0)
+
+
+

Use int(color) to return the immutable integer value of the color, +usable as a dict key. This integer value differs from the mapped +pixel values of pygame.Surface.get_at_mapped()get the mapped color value at a single pixel, +pygame.Surface.map_rgb()convert a color into a mapped color value and pygame.Surface.unmap_rgb()convert a mapped integer color value into a Color. +It can be passed as a color_value argument to Color +(useful with sets).

+

See Named Colors for samples of the available named colors.

+
+
Parameters
+
    +
  • r (int) -- red value in the range of 0 to 255 inclusive

  • +
  • g (int) -- green value in the range of 0 to 255 inclusive

  • +
  • b (int) -- blue value in the range of 0 to 255 inclusive

  • +
  • a (int) -- (optional) alpha value in the range of 0 to 255 inclusive, +default is 255

  • +
  • color_value (Color or str or int or tuple(int, int, int, [int]) or +list(int, int, int, [int])) --

    color value (see note below for the supported formats)

    +
    +

    Note

    +
    +
    Supported color_value formats:
    +
    - Color object: clones the given Color object
    +
    - Color name: str: name of the color to use, e.g. 'red' +(all the supported name strings can be found in the + Named Colors, with sample swatches)
    +
    - HTML color format str: '#rrggbbaa' or '#rrggbb', +where rr, gg, bb, and aa are 2-digit hex numbers in the range +of 0 to 0xFF inclusive, the aa (alpha) value defaults to 0xFF +if not provided
    +
    - hex number str: '0xrrggbbaa' or '0xrrggbb', where +rr, gg, bb, and aa are 2-digit hex numbers in the range of 0x00 +to 0xFF inclusive, the aa (alpha) value defaults to 0xFF if not +provided
    +
    - int: int value of the color to use, using hex numbers can +make this parameter more readable, e.g. 0xrrggbbaa, where rr, +gg, bb, and aa are 2-digit hex numbers in the range of 0x00 to +0xFF inclusive, note that the aa (alpha) value is not optional for +the int format and must be provided
    +
    - tuple/list of int color values: (R, G, B, A) or +(R, G, B), where R, G, B, and A are int values in the range of +0 to 255 inclusive, the A (alpha) value defaults to 255 if not +provided
    +
    +
    +
    +
    +

  • +
+
+
Returns
+

a newly created Color object

+
+
Return type
+

Color

+
+
+
+

Changed in pygame 2.0.0: Support for tuples, lists, and Color objects when creating +Color objects.

+
+
+

Changed in pygame 1.9.2: Color objects export the C level array interface.

+
+
+

Changed in pygame 1.9.0: Color objects support 4-element tuples of integers.

+
+
+

Changed in pygame 1.8.1: New implementation of the class.

+
+
+
+r¶
+
+
Gets or sets the red value of the Color.
+
r -> int
+
+

The red value of the Color.

+
+ +
+
+g¶
+
+
Gets or sets the green value of the Color.
+
g -> int
+
+

The green value of the Color.

+
+ +
+
+b¶
+
+
Gets or sets the blue value of the Color.
+
b -> int
+
+

The blue value of the Color.

+
+ +
+
+a¶
+
+
Gets or sets the alpha value of the Color.
+
a -> int
+
+

The alpha value of the Color.

+
+ +
+
+cmy¶
+
+
Gets or sets the CMY representation of the Color.
+
cmy -> tuple
+
+

The CMY representation of the Color. The CMY components are in +the ranges C = [0, 1], M = [0, 1], Y = [0, 1]. Note that this +will not return the absolutely exact CMY values for the set RGB +values in all cases. Due to the RGB mapping from 0-255 and the +CMY mapping from 0-1 rounding errors may cause the CMY values to +differ slightly from what you might expect.

+
+ +
+
+hsva¶
+
+
Gets or sets the HSVA representation of the Color.
+
hsva -> tuple
+
+

The HSVA representation of the Color. The HSVA components are in +the ranges H = [0, 360], S = [0, 100], V = [0, 100], A = [0, +100]. Note that this will not return the absolutely exact HSV values +for the set RGB values in all cases. Due to the RGB mapping from +0-255 and the HSV mapping from 0-100 and 0-360 rounding errors may +cause the HSV values to differ slightly from what you might expect.

+
+ +
+
+hsla¶
+
+
Gets or sets the HSLA representation of the Color.
+
hsla -> tuple
+
+

The HSLA representation of the Color. The HSLA components are in +the ranges H = [0, 360], S = [0, 100], V = [0, 100], A = [0, +100]. Note that this will not return the absolutely exact HSL values +for the set RGB values in all cases. Due to the RGB mapping from +0-255 and the HSL mapping from 0-100 and 0-360 rounding errors may +cause the HSL values to differ slightly from what you might expect.

+
+ +
+
+i1i2i3¶
+
+
Gets or sets the I1I2I3 representation of the Color.
+
i1i2i3 -> tuple
+
+

The I1I2I3 representation of the Color. The I1I2I3 components are +in the ranges I1 = [0, 1], I2 = [-0.5, 0.5], I3 = [-0.5, +0.5]. Note that this will not return the absolutely exact I1I2I3 +values for the set RGB values in all cases. Due to the RGB +mapping from 0-255 and the I1I2I3 mapping from 0-1 rounding errors +may cause the I1I2I3 values to differ slightly from what you might +expect.

+
+ +
+
+normalize()¶
+
+
Returns the normalized RGBA values of the Color.
+
normalize() -> tuple
+
+

Returns the normalized RGBA values of the Color as floating point +values.

+
+ +
+
+correct_gamma()¶
+
+
Applies a certain gamma value to the Color.
+
correct_gamma (gamma) -> Color
+
+

Applies a certain gamma value to the Color and returns a new Color with +the adjusted RGBA values.

+
+ +
+
+set_length()¶
+
+
Set the number of elements in the Color to 1,2,3, or 4.
+
set_length(len) -> None
+
+

The default Color length is 4. Colors can have lengths 1,2,3 or 4. This +is useful if you want to unpack to r,g,b and not r,g,b,a. If you want to +get the length of a Color do len(acolor).

+
+

New in pygame 1.9.0.

+
+
+ +
+
+lerp()¶
+
+
returns a linear interpolation to the given Color.
+
lerp(Color, float) -> Color
+
+

Returns a Color which is a linear interpolation between self and the +given Color in RGBA space. The second parameter determines how far +between self and other the result is going to be. +It must be a value between 0 and 1 where 0 means self and 1 means +other will be returned.

+
+

New in pygame 2.0.1.

+
+
+ +
+
+premul_alpha()¶
+
+
returns a Color where the r,g,b components have been multiplied by the alpha.
+
premul_alpha() -> Color
+
+

Returns a new Color where each of the red, green and blue colour +channels have been multiplied by the alpha channel of the original +color. The alpha channel remains unchanged.

+

This is useful when working with the BLEND_PREMULTIPLIED blending mode +flag for pygame.Surface.blit()draw one image onto another, which assumes that all surfaces using +it are using pre-multiplied alpha colors.

+
+

New in pygame 2.0.0.

+
+
+ +
+
+update()¶
+
+
Sets the elements of the color
+
update(r, g, b) -> None
+
update(r, g, b, a=255) -> None
+
update(color_value) -> None
+
+

Sets the elements of the color. See parameters for pygame.Color()pygame object for color representations for the +parameters of this function. If the alpha value was not set it will not change.

+
+

New in pygame 2.0.1.

+
+
+ +
+ +
+ + +

+
+Edit on GitHub +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/ref/color_list.html b/venv/Lib/site-packages/pygame/docs/generated/ref/color_list.html new file mode 100644 index 0000000..269c796 --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/ref/color_list.html @@ -0,0 +1,2813 @@ + + + + + + + + + Named Colors — pygame v2.1.2 documentation + + + + + + + + + + + + + +
+ +
+ + + + + +
+
+ +
+
+ +
+

pygame.Colorpygame object for color representations lets you specify any of these named colors when creating a new +pygame.Color (taken from the +colordict module).

+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Name

Color

aliceblue

████████

antiquewhite

████████

antiquewhite1

████████

antiquewhite2

████████

antiquewhite3

████████

antiquewhite4

████████

aqua

████████

aquamarine

████████

aquamarine1

████████

aquamarine2

████████

aquamarine3

████████

aquamarine4

████████

azure

████████

azure1

████████

azure2

████████

azure3

████████

azure4

████████

beige

████████

bisque

████████

bisque1

████████

bisque2

████████

bisque3

████████

bisque4

████████

black

████████

blanchedalmond

████████

blue

████████

blue1

████████

blue2

████████

blue3

████████

blue4

████████

blueviolet

████████

brown

████████

brown1

████████

brown2

████████

brown3

████████

brown4

████████

burlywood

████████

burlywood1

████████

burlywood2

████████

burlywood3

████████

burlywood4

████████

cadetblue

████████

cadetblue1

████████

cadetblue2

████████

cadetblue3

████████

cadetblue4

████████

chartreuse

████████

chartreuse1

████████

chartreuse2

████████

chartreuse3

████████

chartreuse4

████████

chocolate

████████

chocolate1

████████

chocolate2

████████

chocolate3

████████

chocolate4

████████

coral

████████

coral1

████████

coral2

████████

coral3

████████

coral4

████████

cornflowerblue

████████

cornsilk

████████

cornsilk1

████████

cornsilk2

████████

cornsilk3

████████

cornsilk4

████████

crimson

████████

cyan

████████

cyan1

████████

cyan2

████████

cyan3

████████

cyan4

████████

darkblue

████████

darkcyan

████████

darkgoldenrod

████████

darkgoldenrod1

████████

darkgoldenrod2

████████

darkgoldenrod3

████████

darkgoldenrod4

████████

darkgray

████████

darkgreen

████████

darkgrey

████████

darkkhaki

████████

darkmagenta

████████

darkolivegreen

████████

darkolivegreen1

████████

darkolivegreen2

████████

darkolivegreen3

████████

darkolivegreen4

████████

darkorange

████████

darkorange1

████████

darkorange2

████████

darkorange3

████████

darkorange4

████████

darkorchid

████████

darkorchid1

████████

darkorchid2

████████

darkorchid3

████████

darkorchid4

████████

darkred

████████

darksalmon

████████

darkseagreen

████████

darkseagreen1

████████

darkseagreen2

████████

darkseagreen3

████████

darkseagreen4

████████

darkslateblue

████████

darkslategray

████████

darkslategray1

████████

darkslategray2

████████

darkslategray3

████████

darkslategray4

████████

darkslategrey

████████

darkturquoise

████████

darkviolet

████████

deeppink

████████

deeppink1

████████

deeppink2

████████

deeppink3

████████

deeppink4

████████

deepskyblue

████████

deepskyblue1

████████

deepskyblue2

████████

deepskyblue3

████████

deepskyblue4

████████

dimgray

████████

dimgrey

████████

dodgerblue

████████

dodgerblue1

████████

dodgerblue2

████████

dodgerblue3

████████

dodgerblue4

████████

firebrick

████████

firebrick1

████████

firebrick2

████████

firebrick3

████████

firebrick4

████████

floralwhite

████████

forestgreen

████████

fuchsia

████████

gainsboro

████████

ghostwhite

████████

gold

████████

gold1

████████

gold2

████████

gold3

████████

gold4

████████

goldenrod

████████

goldenrod1

████████

goldenrod2

████████

goldenrod3

████████

goldenrod4

████████

gray

████████

gray0

████████

gray1

████████

gray2

████████

gray3

████████

gray4

████████

gray5

████████

gray6

████████

gray7

████████

gray8

████████

gray9

████████

gray10

████████

gray11

████████

gray12

████████

gray13

████████

gray14

████████

gray15

████████

gray16

████████

gray17

████████

gray18

████████

gray19

████████

gray20

████████

gray21

████████

gray22

████████

gray23

████████

gray24

████████

gray25

████████

gray26

████████

gray27

████████

gray28

████████

gray29

████████

gray30

████████

gray31

████████

gray32

████████

gray33

████████

gray34

████████

gray35

████████

gray36

████████

gray37

████████

gray38

████████

gray39

████████

gray40

████████

gray41

████████

gray42

████████

gray43

████████

gray44

████████

gray45

████████

gray46

████████

gray47

████████

gray48

████████

gray49

████████

gray50

████████

gray51

████████

gray52

████████

gray53

████████

gray54

████████

gray55

████████

gray56

████████

gray57

████████

gray58

████████

gray59

████████

gray60

████████

gray61

████████

gray62

████████

gray63

████████

gray64

████████

gray65

████████

gray66

████████

gray67

████████

gray68

████████

gray69

████████

gray70

████████

gray71

████████

gray72

████████

gray73

████████

gray74

████████

gray75

████████

gray76

████████

gray77

████████

gray78

████████

gray79

████████

gray80

████████

gray81

████████

gray82

████████

gray83

████████

gray84

████████

gray85

████████

gray86

████████

gray87

████████

gray88

████████

gray89

████████

gray90

████████

gray91

████████

gray92

████████

gray93

████████

gray94

████████

gray95

████████

gray96

████████

gray97

████████

gray98

████████

gray99

████████

gray100

████████

green

████████

green1

████████

green2

████████

green3

████████

green4

████████

greenyellow

████████

grey

████████

grey0

████████

grey1

████████

grey2

████████

grey3

████████

grey4

████████

grey5

████████

grey6

████████

grey7

████████

grey8

████████

grey9

████████

grey10

████████

grey11

████████

grey12

████████

grey13

████████

grey14

████████

grey15

████████

grey16

████████

grey17

████████

grey18

████████

grey19

████████

grey20

████████

grey21

████████

grey22

████████

grey23

████████

grey24

████████

grey25

████████

grey26

████████

grey27

████████

grey28

████████

grey29

████████

grey30

████████

grey31

████████

grey32

████████

grey33

████████

grey34

████████

grey35

████████

grey36

████████

grey37

████████

grey38

████████

grey39

████████

grey40

████████

grey41

████████

grey42

████████

grey43

████████

grey44

████████

grey45

████████

grey46

████████

grey47

████████

grey48

████████

grey49

████████

grey50

████████

grey51

████████

grey52

████████

grey53

████████

grey54

████████

grey55

████████

grey56

████████

grey57

████████

grey58

████████

grey59

████████

grey60

████████

grey61

████████

grey62

████████

grey63

████████

grey64

████████

grey65

████████

grey66

████████

grey67

████████

grey68

████████

grey69

████████

grey70

████████

grey71

████████

grey72

████████

grey73

████████

grey74

████████

grey75

████████

grey76

████████

grey77

████████

grey78

████████

grey79

████████

grey80

████████

grey81

████████

grey82

████████

grey83

████████

grey84

████████

grey85

████████

grey86

████████

grey87

████████

grey88

████████

grey89

████████

grey90

████████

grey91

████████

grey92

████████

grey93

████████

grey94

████████

grey95

████████

grey96

████████

grey97

████████

grey98

████████

grey99

████████

grey100

████████

honeydew

████████

honeydew1

████████

honeydew2

████████

honeydew3

████████

honeydew4

████████

hotpink

████████

hotpink1

████████

hotpink2

████████

hotpink3

████████

hotpink4

████████

indianred

████████

indianred1

████████

indianred2

████████

indianred3

████████

indianred4

████████

indigo

████████

ivory

████████

ivory1

████████

ivory2

████████

ivory3

████████

ivory4

████████

khaki

████████

khaki1

████████

khaki2

████████

khaki3

████████

khaki4

████████

lavender

████████

lavenderblush

████████

lavenderblush1

████████

lavenderblush2

████████

lavenderblush3

████████

lavenderblush4

████████

lawngreen

████████

lemonchiffon

████████

lemonchiffon1

████████

lemonchiffon2

████████

lemonchiffon3

████████

lemonchiffon4

████████

lightblue

████████

lightblue1

████████

lightblue2

████████

lightblue3

████████

lightblue4

████████

lightcoral

████████

lightcyan

████████

lightcyan1

████████

lightcyan2

████████

lightcyan3

████████

lightcyan4

████████

lightgoldenrod

████████

lightgoldenrod1

████████

lightgoldenrod2

████████

lightgoldenrod3

████████

lightgoldenrod4

████████

lightgoldenrodyellow

████████

lightgray

████████

lightgreen

████████

lightgrey

████████

lightpink

████████

lightpink1

████████

lightpink2

████████

lightpink3

████████

lightpink4

████████

lightsalmon

████████

lightsalmon1

████████

lightsalmon2

████████

lightsalmon3

████████

lightsalmon4

████████

lightseagreen

████████

lightskyblue

████████

lightskyblue1

████████

lightskyblue2

████████

lightskyblue3

████████

lightskyblue4

████████

lightslateblue

████████

lightslategray

████████

lightslategrey

████████

lightsteelblue

████████

lightsteelblue1

████████

lightsteelblue2

████████

lightsteelblue3

████████

lightsteelblue4

████████

lightyellow

████████

lightyellow1

████████

lightyellow2

████████

lightyellow3

████████

lightyellow4

████████

lime

████████

limegreen

████████

linen

████████

magenta

████████

magenta1

████████

magenta2

████████

magenta3

████████

magenta4

████████

maroon

████████

maroon1

████████

maroon2

████████

maroon3

████████

maroon4

████████

mediumaquamarine

████████

mediumblue

████████

mediumorchid

████████

mediumorchid1

████████

mediumorchid2

████████

mediumorchid3

████████

mediumorchid4

████████

mediumpurple

████████

mediumpurple1

████████

mediumpurple2

████████

mediumpurple3

████████

mediumpurple4

████████

mediumseagreen

████████

mediumslateblue

████████

mediumspringgreen

████████

mediumturquoise

████████

mediumvioletred

████████

midnightblue

████████

mintcream

████████

mistyrose

████████

mistyrose1

████████

mistyrose2

████████

mistyrose3

████████

mistyrose4

████████

moccasin

████████

navajowhite

████████

navajowhite1

████████

navajowhite2

████████

navajowhite3

████████

navajowhite4

████████

navy

████████

navyblue

████████

oldlace

████████

olive

████████

olivedrab

████████

olivedrab1

████████

olivedrab2

████████

olivedrab3

████████

olivedrab4

████████

orange

████████

orange1

████████

orange2

████████

orange3

████████

orange4

████████

orangered

████████

orangered1

████████

orangered2

████████

orangered3

████████

orangered4

████████

orchid

████████

orchid1

████████

orchid2

████████

orchid3

████████

orchid4

████████

palegoldenrod

████████

palegreen

████████

palegreen1

████████

palegreen2

████████

palegreen3

████████

palegreen4

████████

paleturquoise

████████

paleturquoise1

████████

paleturquoise2

████████

paleturquoise3

████████

paleturquoise4

████████

palevioletred

████████

palevioletred1

████████

palevioletred2

████████

palevioletred3

████████

palevioletred4

████████

papayawhip

████████

peachpuff

████████

peachpuff1

████████

peachpuff2

████████

peachpuff3

████████

peachpuff4

████████

peru

████████

pink

████████

pink1

████████

pink2

████████

pink3

████████

pink4

████████

plum

████████

plum1

████████

plum2

████████

plum3

████████

plum4

████████

powderblue

████████

purple

████████

purple1

████████

purple2

████████

purple3

████████

purple4

████████

red

████████

red1

████████

red2

████████

red3

████████

red4

████████

rosybrown

████████

rosybrown1

████████

rosybrown2

████████

rosybrown3

████████

rosybrown4

████████

royalblue

████████

royalblue1

████████

royalblue2

████████

royalblue3

████████

royalblue4

████████

saddlebrown

████████

salmon

████████

salmon1

████████

salmon2

████████

salmon3

████████

salmon4

████████

sandybrown

████████

seagreen

████████

seagreen1

████████

seagreen2

████████

seagreen3

████████

seagreen4

████████

seashell

████████

seashell1

████████

seashell2

████████

seashell3

████████

seashell4

████████

sienna

████████

sienna1

████████

sienna2

████████

sienna3

████████

sienna4

████████

silver

████████

skyblue

████████

skyblue1

████████

skyblue2

████████

skyblue3

████████

skyblue4

████████

slateblue

████████

slateblue1

████████

slateblue2

████████

slateblue3

████████

slateblue4

████████

slategray

████████

slategray1

████████

slategray2

████████

slategray3

████████

slategray4

████████

slategrey

████████

snow

████████

snow1

████████

snow2

████████

snow3

████████

snow4

████████

springgreen

████████

springgreen1

████████

springgreen2

████████

springgreen3

████████

springgreen4

████████

steelblue

████████

steelblue1

████████

steelblue2

████████

steelblue3

████████

steelblue4

████████

tan

████████

tan1

████████

tan2

████████

tan3

████████

tan4

████████

teal

████████

thistle

████████

thistle1

████████

thistle2

████████

thistle3

████████

thistle4

████████

tomato

████████

tomato1

████████

tomato2

████████

tomato3

████████

tomato4

████████

turquoise

████████

turquoise1

████████

turquoise2

████████

turquoise3

████████

turquoise4

████████

violet

████████

violetred

████████

violetred1

████████

violetred2

████████

violetred3

████████

violetred4

████████

wheat

████████

wheat1

████████

wheat2

████████

wheat3

████████

wheat4

████████

white

████████

whitesmoke

████████

yellow

████████

yellow1

████████

yellow2

████████

yellow3

████████

yellow4

████████

yellowgreen

████████

+
+ + +

+
+Edit on GitHub +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/ref/cursors.html b/venv/Lib/site-packages/pygame/docs/generated/ref/cursors.html new file mode 100644 index 0000000..81e4c20 --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/ref/cursors.html @@ -0,0 +1,452 @@ + + + + + + + + + pygame.cursors — pygame v2.1.2 documentation + + + + + + + + + + + + + +
+ +
+ + + + + +
+
+ +
+
+ +
+
+
+pygame.cursors
+
+
pygame module for cursor resources
+
+ +++++ + + + + + + + + + + + + + + +
+—create binary cursor data from simple strings
+—load cursor data from an XBM file
+—pygame object representing a cursor
+

Pygame offers control over the system hardware cursor. Pygame supports +black and white cursors (bitmap cursors), as well as system variant cursors and color cursors. +You control the cursor with functions inside pygame.mousepygame module to work with the mouse.

+

This cursors module contains functions for loading and decoding various +cursor formats. These allow you to easily store your cursors in external files +or directly as encoded python strings.

+

The module includes several standard cursors. The pygame.mouse.set_cursor()set the mouse cursor to a new cursor +function takes several arguments. All those arguments have been stored in a +single tuple you can call like this:

+
>>> pygame.mouse.set_cursor(*pygame.cursors.arrow)
+
+
+

The following variables can be passed to pygame.mouse.set_cursor function:

+
+
    +
  • pygame.cursors.arrow

  • +
  • pygame.cursors.diamond

  • +
  • pygame.cursors.broken_x

  • +
  • pygame.cursors.tri_left

  • +
  • pygame.cursors.tri_right

  • +
+
+

This module also contains a few cursors as formatted strings. You'll need to +pass these to pygame.cursors.compile() function before you can use them. +The example call would look like this:

+
>>> cursor = pygame.cursors.compile(pygame.cursors.textmarker_strings)
+>>> pygame.mouse.set_cursor((8, 16), (0, 0), *cursor)
+
+
+

The following strings can be converted into cursor bitmaps with +pygame.cursors.compile() :

+
+
    +
  • pygame.cursors.thickarrow_strings

  • +
  • pygame.cursors.sizer_x_strings

  • +
  • pygame.cursors.sizer_y_strings

  • +
  • pygame.cursors.sizer_xy_strings

  • +
  • pygame.cursor.textmarker_strings

  • +
+
+
+
+pygame.cursors.compile()¶
+
+
create binary cursor data from simple strings
+
compile(strings, black='X', white='.', xor='o') -> data, mask
+
+

A sequence of strings can be used to create binary cursor data for the +system cursor. This returns the binary data in the form of two tuples. +Those can be passed as the third and fourth arguments respectively of the +pygame.mouse.set_cursor()set the mouse cursor to a new cursor function.

+

If you are creating your own cursor strings, you can use any value represent +the black and white pixels. Some system allow you to set a special toggle +color for the system color, this is also called the xor color. If the system +does not support xor cursors, that color will simply be black.

+

The height must be divisible by 8. The width of the strings must all be equal +and be divisible by 8. If these two conditions are not met, ValueError is +raised. +An example set of cursor strings looks like this

+
thickarrow_strings = (               #sized 24x24
+  "XX                      ",
+  "XXX                     ",
+  "XXXX                    ",
+  "XX.XX                   ",
+  "XX..XX                  ",
+  "XX...XX                 ",
+  "XX....XX                ",
+  "XX.....XX               ",
+  "XX......XX              ",
+  "XX.......XX             ",
+  "XX........XX            ",
+  "XX........XXX           ",
+  "XX......XXXXX           ",
+  "XX.XXX..XX              ",
+  "XXXX XX..XX             ",
+  "XX   XX..XX             ",
+  "     XX..XX             ",
+  "      XX..XX            ",
+  "      XX..XX            ",
+  "       XXXX             ",
+  "       XX               ",
+  "                        ",
+  "                        ",
+  "                        ")
+
+
+
+ +
+
+pygame.cursors.load_xbm()¶
+
+
load cursor data from an XBM file
+
load_xbm(cursorfile) -> cursor_args
+
load_xbm(cursorfile, maskfile) -> cursor_args
+
+

This loads cursors for a simple subset of XBM files. XBM files are +traditionally used to store cursors on UNIX systems, they are an ASCII +format used to represent simple images.

+

Sometimes the black and white color values will be split into two separate +XBM files. You can pass a second maskfile argument to load the two +images into a single cursor.

+

The cursorfile and maskfile arguments can either be filenames or file-like +object with the readlines method.

+

The return value cursor_args can be passed directly to the +pygame.mouse.set_cursor() function.

+
+ +
+
+pygame.cursors.Cursor¶
+
+
pygame object representing a cursor
+
Cursor(size, hotspot, xormasks, andmasks) -> Cursor
+
Cursor(hotspot, surface) -> Cursor
+
Cursor(constant) -> Cursor
+
Cursor(Cursor) -> Cursor
+
Cursor() -> Cursor
+
+ +++++ + + + + + + + + + + + + + + +
+—
+—Gets the cursor type
+—Gets the cursor data
+

In pygame 2, there are 3 types of cursors you can create to give your +game that little bit of extra polish. There's bitmap type cursors, +which existed in pygame 1.x, and are compiled from a string or load from an xbm file. +Then there are system type cursors, where you choose a preset that will +convey the same meaning but look native across different operating systems. +Finally you can create a color cursor, which displays a pygame surface as the cursor.

+

Creating a system cursor

+

Choose a constant from this list, pass it into pygame.cursors.Cursor(constant), +and you're good to go. Be advised that not all systems support every system +cursor, and you may get a substitution instead. For example, on MacOS, +WAIT/WAITARROW should show up as an arrow, and SIZENWSE/SIZENESW/SIZEALL +should show up as a closed hand. And on Wayland, every SIZE cursor should +show up as a hand.

+
Pygame Cursor Constant           Description
+--------------------------------------------
+pygame.SYSTEM_CURSOR_ARROW       arrow
+pygame.SYSTEM_CURSOR_IBEAM       i-beam
+pygame.SYSTEM_CURSOR_WAIT        wait
+pygame.SYSTEM_CURSOR_CROSSHAIR   crosshair
+pygame.SYSTEM_CURSOR_WAITARROW   small wait cursor
+                                 (or wait if not available)
+pygame.SYSTEM_CURSOR_SIZENWSE    double arrow pointing
+                                 northwest and southeast
+pygame.SYSTEM_CURSOR_SIZENESW    double arrow pointing
+                                 northeast and southwest
+pygame.SYSTEM_CURSOR_SIZEWE      double arrow pointing
+                                 west and east
+pygame.SYSTEM_CURSOR_SIZENS      double arrow pointing
+                                 north and south
+pygame.SYSTEM_CURSOR_SIZEALL     four pointed arrow pointing
+                                 north, south, east, and west
+pygame.SYSTEM_CURSOR_NO          slashed circle or crossbones
+pygame.SYSTEM_CURSOR_HAND        hand
+
+
+

Creating a cursor without passing arguments

+

In addition to the cursor constants available and described above, +you can also call pygame.cursors.Cursor(), and your cursor is ready (doing that is the same as +calling pygame.cursors.Cursor(pygame.SYSTEM_CURSOR_ARROW). +Doing one of those calls actually creates a system cursor using the default native image.

+

Creating a color cursor

+

To create a color cursor, create a Cursor from a hotspot and a surface. +hotspot is an (x,y) coordinate that determines where in the cursor the exact point is. +The hotspot position must be within the bounds of the surface.

+

Creating a bitmap cursor

+

When the mouse cursor is visible, it will be displayed as a black and white +bitmap using the given bitmask arrays. The size is a sequence containing +the cursor width and height. hotspot is a sequence containing the cursor +hotspot position.

+

A cursor has a width and height, but a mouse position is represented by a +set of point coordinates. So the value passed into the cursor hotspot +variable helps pygame to actually determine at what exact point the cursor +is at.

+

xormasks is a sequence of bytes containing the cursor xor data masks. +Lastly andmasks, a sequence of bytes containing the cursor bitmask data. +To create these variables, we can make use of the +pygame.cursors.compile()create binary cursor data from simple strings function.

+

Width and height must be a multiple of 8, and the mask arrays must be the +correct size for the given width and height. Otherwise an exception is raised.

+
+
+copy()¶
+
+| :sl:`copy the current cursor`
+
+| :sg:`copy() -> Cursor`
+

Returns a new Cursor object with the same data and hotspot as the original.

+
+ +
+
+type¶
+
+
Gets the cursor type
+
type -> string
+
+

The type will be "system", "bitmap", or "color".

+
+ +
+
+data¶
+
+
Gets the cursor data
+
data -> tuple
+
+

Returns the data that was used to create this cursor object, wrapped up in a tuple.

+
+ +
+

New in pygame 2.0.1.

+
+
+ +

Example code for creating and settings cursors. (Click the mouse to switch cursor)

+
# pygame setup
+import pygame as pg
+
+pg.init()
+screen = pg.display.set_mode([600, 400])
+pg.display.set_caption("Example code for the cursors module")
+
+# create a system cursor
+system = pg.cursors.Cursor(pg.SYSTEM_CURSOR_NO)
+
+# create bitmap cursors
+bitmap_1 = pg.cursors.Cursor(*pg.cursors.arrow)
+bitmap_2 = pg.cursors.Cursor(
+    (24, 24), (0, 0), *pg.cursors.compile(pg.cursors.thickarrow_strings)
+)
+
+# create a color cursor
+surf = pg.Surface((40, 40)) # you could also load an image 
+surf.fill((120, 50, 50))        # and use that as your surface
+color = pg.cursors.Cursor((20, 20), surf)
+
+cursors = [system, bitmap_1, bitmap_2, color]
+cursor_index = 0
+
+pg.mouse.set_cursor(cursors[cursor_index])
+
+clock = pg.time.Clock()
+going = True
+while going:
+    clock.tick(60)
+    screen.fill((0, 75, 30))
+    pg.display.flip()
+
+    for event in pg.event.get():
+        if event.type == pg.QUIT or (event.type == pg.KEYDOWN and event.key == pg.K_ESCAPE):
+            going = False
+
+        # if the mouse is clicked it will switch to a new cursor
+        if event.type == pg.MOUSEBUTTONDOWN:
+            cursor_index += 1
+            cursor_index %= len(cursors)
+            pg.mouse.set_cursor(cursors[cursor_index])
+
+pg.quit()
+
+
+
+ +
+ + +

+
+Edit on GitHub +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/ref/display.html b/venv/Lib/site-packages/pygame/docs/generated/ref/display.html new file mode 100644 index 0000000..edaab32 --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/ref/display.html @@ -0,0 +1,990 @@ + + + + + + + + + pygame.display — pygame v2.1.2 documentation + + + + + + + + + + + + + +
+ +
+ + + + + +
+
+ +
+
+ +
+
+
+pygame.display
+
+
pygame module to control the display window and screen
+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+—Initialize the display module
+—Uninitialize the display module
+—Returns True if the display module has been initialized
+—Initialize a window or screen for display
+—Get a reference to the currently set display surface
+—Update the full display Surface to the screen
+—Update portions of the screen for software displays
+—Get the name of the pygame display backend
+—Create a video display information object
+—Get information about the current windowing system
+—Get sizes of active desktops
+—Get list of available fullscreen modes
+—Pick the best color depth for a display mode
+—Get the value for an OpenGL flag for the current display
+—Request an OpenGL display attribute for the display mode
+—Returns True when the display is active on the screen
+—Iconify the display surface
+—Switch between fullscreen and windowed displays
+—Change the hardware gamma ramps
+—Change the hardware gamma ramps with a custom lookup
+—Change the system image for the display window
+—Set the current window caption
+—Get the current window caption
+—Set the display color palette for indexed displays
+—Return the number of displays
+—Return the size of the window or screen
+—Return whether the screensaver is allowed to run.
+—Set whether the screensaver may run
+

This module offers control over the pygame display. Pygame has a single display +Surface that is either contained in a window or runs full screen. Once you +create the display you treat it as a regular Surface. Changes are not +immediately visible onscreen; you must choose one of the two flipping functions +to update the actual display.

+

The origin of the display, where x = 0 and y = 0, is the top left of the +screen. Both axes increase positively towards the bottom right of the screen.

+

The pygame display can actually be initialized in one of several modes. By +default, the display is a basic software driven framebuffer. You can request +special modules like automatic scaling or OpenGL support. These are +controlled by flags passed to pygame.display.set_mode().

+

Pygame can only have a single display active at any time. Creating a new one +with pygame.display.set_mode() will close the previous display. To detect +the number and size of attached screens, you can use +pygame.display.get_desktop_sizes and then select appropriate window size +and display index to pass to pygame.display.set_mode().

+

For backward compatibility pygame.display allows precise control over +the pixel format or display resolutions. This used to be necessary with old +grahics cards and CRT screens, but is usually not needed any more. Use the +functions pygame.display.mode_ok(), pygame.display.list_modes(), and +pygame.display.Info() to query detailed information about the display.

+

Once the display Surface is created, the functions from this module affect the +single existing display. The Surface becomes invalid if the module is +uninitialized. If a new display mode is set, the existing Surface will +automatically switch to operate on the new display.

+

When the display mode is set, several events are placed on the pygame event +queue. pygame.QUIT is sent when the user has requested the program to +shut down. The window will receive pygame.ACTIVEEVENT events as the display +gains and loses input focus. If the display is set with the +pygame.RESIZABLE flag, pygame.VIDEORESIZE events will be sent when the +user adjusts the window dimensions. Hardware displays that draw direct to the +screen will get pygame.VIDEOEXPOSE events when portions of the window must +be redrawn.

+

A new windowevent API was introduced in pygame 2.0.1. Check event module docs +for more information on that

+

Some display environments have an option for automatically stretching all +windows. When this option is enabled, this automatic stretching distorts the +appearance of the pygame window. In the pygame examples directory, there is +example code (prevent_display_stretching.py) which shows how to disable this +automatic stretching of the pygame display on Microsoft Windows (Vista or newer +required).

+
+
+pygame.display.init()¶
+
+
Initialize the display module
+
init() -> None
+
+

Initializes the pygame display module. The display module cannot do anything +until it is initialized. This is usually handled for you automatically when +you call the higher level pygame.init().

+

Pygame will select from one of several internal display backends when it is +initialized. The display mode will be chosen depending on the platform and +permissions of current user. Before the display module is initialized the +environment variable SDL_VIDEODRIVER can be set to control which backend +is used. The systems with multiple choices are listed here.

+
Windows : windib, directx
+Unix    : x11, dga, fbcon, directfb, ggi, vgl, svgalib, aalib
+
+
+

On some platforms it is possible to embed the pygame display into an already +existing window. To do this, the environment variable SDL_WINDOWID must +be set to a string containing the window id or handle. The environment +variable is checked when the pygame display is initialized. Be aware that +there can be many strange side effects when running in an embedded display.

+

It is harmless to call this more than once, repeated calls have no effect.

+
+ +
+
+pygame.display.quit()¶
+
+
Uninitialize the display module
+
quit() -> None
+
+

This will shut down the entire display module. This means any active +displays will be closed. This will also be handled automatically when the +program exits.

+

It is harmless to call this more than once, repeated calls have no effect.

+
+ +
+
+pygame.display.get_init()¶
+
+
Returns True if the display module has been initialized
+
get_init() -> bool
+
+

Returns True if the pygame.displaypygame module to control the display window and screen module is currently initialized.

+
+ +
+
+pygame.display.set_mode()¶
+
+
Initialize a window or screen for display
+
set_mode(size=(0, 0), flags=0, depth=0, display=0, vsync=0) -> Surface
+
+

This function will create a display Surface. The arguments passed in are +requests for a display type. The actual created display will be the best +possible match supported by the system.

+

Note that calling this function implicitly initializes pygame.display, if +it was not initialized before.

+

The size argument is a pair of numbers representing the width and +height. The flags argument is a collection of additional options. The depth +argument represents the number of bits to use for color.

+

The Surface that gets returned can be drawn to like a regular Surface but +changes will eventually be seen on the monitor.

+

If no size is passed or is set to (0, 0) and pygame uses SDL +version 1.2.10 or above, the created Surface will have the same size as the +current screen resolution. If only the width or height are set to 0, the +Surface will have the same width or height as the screen resolution. Using a +SDL version prior to 1.2.10 will raise an exception.

+

It is usually best to not pass the depth argument. It will default to the +best and fastest color depth for the system. If your game requires a +specific color format you can control the depth with this argument. Pygame +will emulate an unavailable color depth which can be slow.

+

When requesting fullscreen display modes, sometimes an exact match for the +requested size cannot be made. In these situations pygame will select +the closest compatible match. The returned surface will still always match +the requested size.

+

On high resolution displays(4k, 1080p) and tiny graphics games (640x480) +show up very small so that they are unplayable. SCALED scales up the window +for you. The game thinks it's a 640x480 window, but really it can be bigger. +Mouse events are scaled for you, so your game doesn't need to do it. Note +that SCALED is considered an experimental API and may change in future +releases.

+

The flags argument controls which type of display you want. There are +several to choose from, and you can even combine multiple types using the +bitwise or operator, (the pipe "|" character). Here are the display +flags you will want to choose from:

+
pygame.FULLSCREEN    create a fullscreen display
+pygame.DOUBLEBUF     (obsolete in pygame 2) recommended for HWSURFACE or OPENGL
+pygame.HWSURFACE     (obsolete in pygame 2) hardware accelerated, only in FULLSCREEN
+pygame.OPENGL        create an OpenGL-renderable display
+pygame.RESIZABLE     display window should be sizeable
+pygame.NOFRAME       display window will have no border or controls
+pygame.SCALED        resolution depends on desktop size and scale graphics
+pygame.SHOWN         window is opened in visible mode (default)
+pygame.HIDDEN        window is opened in hidden mode
+
+
+
+

New in pygame 2.0.0: SCALED, SHOWN and HIDDEN

+
+

By setting the vsync parameter to 1, it is possible to get a display +with vertical sync, but you are not guaranteed to get one. The request only +works at all for calls to set_mode() with the pygame.OPENGL or +pygame.SCALED flags set, and is still not guaranteed even with one of +those set. What you get depends on the hardware and driver configuration +of the system pygame is running on. Here is an example usage of a call +to set_mode() that may give you a display with vsync:

+
flags = pygame.OPENGL | pygame.FULLSCREEN
+window_surface = pygame.display.set_mode((1920, 1080), flags, vsync=1)
+
+
+

Vsync behaviour is considered experimental, and may change in future releases.

+
+

New in pygame 2.0.0: vsync

+
+

Basic example:

+
# Open a window on the screen
+screen_width=700
+screen_height=400
+screen=pygame.display.set_mode([screen_width, screen_height])
+
+
+

The display index 0 means the default display is used. If no display +index argument is provided, the default display can be overridden with an +environment variable.

+
+

Changed in pygame 1.9.5: display argument added

+
+
+ +
+
+pygame.display.get_surface()¶
+
+
Get a reference to the currently set display surface
+
get_surface() -> Surface
+
+

Return a reference to the currently set display Surface. If no display mode +has been set this will return None.

+
+ +
+
+pygame.display.flip()¶
+
+
Update the full display Surface to the screen
+
flip() -> None
+
+

This will update the contents of the entire display. If your display mode is +using the flags pygame.HWSURFACE and pygame.DOUBLEBUF on pygame 1, +this will wait for a vertical retrace and swap the surfaces.

+

When using an pygame.OPENGL display mode this will perform a gl buffer +swap.

+
+ +
+
+pygame.display.update()¶
+
+
Update portions of the screen for software displays
+
update(rectangle=None) -> None
+
update(rectangle_list) -> None
+
+

This function is like an optimized version of pygame.display.flip() for +software displays. It allows only a portion of the screen to updated, +instead of the entire area. If no argument is passed it updates the entire +Surface area like pygame.display.flip().

+

Note that calling display.update(None) means no part of the window is +updated. Whereas display.update() means the whole window is updated.

+

You can pass the function a single rectangle, or a sequence of rectangles. +It is more efficient to pass many rectangles at once than to call update +multiple times with single or a partial list of rectangles. If passing a +sequence of rectangles it is safe to include None values in the list, which +will be skipped.

+

This call cannot be used on pygame.OPENGL displays and will generate an +exception.

+
+ +
+
+pygame.display.get_driver()¶
+
+
Get the name of the pygame display backend
+
get_driver() -> name
+
+

Pygame chooses one of many available display backends when it is +initialized. This returns the internal name used for the display backend. +This can be used to provide limited information about what display +capabilities might be accelerated. See the SDL_VIDEODRIVER flags in +pygame.display.set_mode() to see some of the common options.

+
+ +
+
+pygame.display.Info()¶
+
+
Create a video display information object
+
Info() -> VideoInfo
+
+

Creates a simple object containing several attributes to describe the +current graphics environment. If this is called before +pygame.display.set_mode() some platforms can provide information about +the default display mode. This can also be called after setting the display +mode to verify specific display options were satisfied. The VidInfo object +has several attributes:

+
hw:         1 if the display is hardware accelerated
+wm:         1 if windowed display modes can be used
+video_mem:  The megabytes of video memory on the display. This is 0 if
+            unknown
+bitsize:    Number of bits used to store each pixel
+bytesize:   Number of bytes used to store each pixel
+masks:      Four values used to pack RGBA values into pixels
+shifts:     Four values used to pack RGBA values into pixels
+losses:     Four values used to pack RGBA values into pixels
+blit_hw:    1 if hardware Surface blitting is accelerated
+blit_hw_CC: 1 if hardware Surface colorkey blitting is accelerated
+blit_hw_A:  1 if hardware Surface pixel alpha blitting is accelerated
+blit_sw:    1 if software Surface blitting is accelerated
+blit_sw_CC: 1 if software Surface colorkey blitting is accelerated
+blit_sw_A:  1 if software Surface pixel alpha blitting is accelerated
+current_h, current_w:  Height and width of the current video mode, or
+            of the desktop mode if called before the display.set_mode
+            is called. (current_h, current_w are available since
+            SDL 1.2.10, and pygame 1.8.0). They are -1 on error, or if
+            an old SDL is being used.
+
+
+
+ +
+
+pygame.display.get_wm_info()¶
+
+
Get information about the current windowing system
+
get_wm_info() -> dict
+
+

Creates a dictionary filled with string keys. The strings and values are +arbitrarily created by the system. Some systems may have no information and +an empty dictionary will be returned. Most platforms will return a "window" +key with the value set to the system id for the current display.

+
+

New in pygame 1.7.1.

+
+
+ +
+
+pygame.display.get_desktop_sizes()¶
+
+
Get sizes of active desktops
+
get_desktop_sizes() -> list
+
+

This function returns the sizes of the currrently configured +virtual desktops as a list of (x, y) tuples of integers.

+

The length of the list is not the same as the number of attached monitors, +as a desktop can be mirrored across multiple monitors. The desktop sizes +do not indicate the maximum monitor resolutions supported by the hardware, +but the desktop size configured in the operating system.

+

In order to fit windows into the desktop as it is currently configured, and +to respect the resolution configured by the operating system in fullscreen +mode, this function should be used to replace many use cases of +pygame.display.list_modes() whenever applicable.

+
+

New in pygame 2.0.0.

+
+
+ +
+
+pygame.display.list_modes()¶
+
+
Get list of available fullscreen modes
+
list_modes(depth=0, flags=pygame.FULLSCREEN, display=0) -> list
+
+

This function returns a list of possible sizes for a specified color +depth. The return value will be an empty list if no display modes are +available with the given arguments. A return value of -1 means that +any requested size should work (this is likely the case for windowed +modes). Mode sizes are sorted from biggest to smallest.

+

If depth is 0, the current/best color depth for the display is used. +The flags defaults to pygame.FULLSCREEN, but you may need to add +additional flags for specific fullscreen modes.

+

The display index 0 means the default display is used.

+

Since pygame 2.0, pygame.display.get_desktop_sizes() has taken over +some use cases from pygame.display.list_modes():

+

To find a suitable size for non-fullscreen windows, it is preferable to +use pygame.display.get_desktop_sizes() to get the size of the current +desktop, and to then choose a smaller window size. This way, the window is +guaranteed to fit, even when the monitor is configured to a lower resolution +than the maximum supported by the hardware.

+

To avoid changing the physical monitor resolution, it is also preferable to +use pygame.display.get_desktop_sizes() to determine the fullscreen +resolution. Developers are strongly advised to default to the current +physical monitor resolution unless the user explicitly requests a different +one (e.g. in an options menu or configuration file).

+
+

Changed in pygame 1.9.5: display argument added

+
+
+ +
+
+pygame.display.mode_ok()¶
+
+
Pick the best color depth for a display mode
+
mode_ok(size, flags=0, depth=0, display=0) -> depth
+
+

This function uses the same arguments as pygame.display.set_mode(). It +is used to determine if a requested display mode is available. It will +return 0 if the display mode cannot be set. Otherwise it will return a +pixel depth that best matches the display asked for.

+

Usually the depth argument is not passed, but some platforms can support +multiple display depths. If passed it will hint to which depth is a better +match.

+

The function will return 0 if the passed display flags cannot be set.

+

The display index 0 means the default display is used.

+
+

Changed in pygame 1.9.5: display argument added

+
+
+ +
+
+pygame.display.gl_get_attribute()¶
+
+
Get the value for an OpenGL flag for the current display
+
gl_get_attribute(flag) -> value
+
+

After calling pygame.display.set_mode() with the pygame.OPENGL flag, +it is a good idea to check the value of any requested OpenGL attributes. See +pygame.display.gl_set_attribute() for a list of valid flags.

+
+ +
+
+pygame.display.gl_set_attribute()¶
+
+
Request an OpenGL display attribute for the display mode
+
gl_set_attribute(flag, value) -> None
+
+

When calling pygame.display.set_mode() with the pygame.OPENGL flag, +Pygame automatically handles setting the OpenGL attributes like color and +double-buffering. OpenGL offers several other attributes you may want control +over. Pass one of these attributes as the flag, and its appropriate value. +This must be called before pygame.display.set_mode().

+

Many settings are the requested minimum. Creating a window with an OpenGL context +will fail if OpenGL cannot provide the requested attribute, but it may for example +give you a stencil buffer even if you request none, or it may give you a larger +one than requested.

+

The OPENGL flags are:

+
GL_ALPHA_SIZE, GL_DEPTH_SIZE, GL_STENCIL_SIZE, GL_ACCUM_RED_SIZE,
+GL_ACCUM_GREEN_SIZE,  GL_ACCUM_BLUE_SIZE, GL_ACCUM_ALPHA_SIZE,
+GL_MULTISAMPLEBUFFERS, GL_MULTISAMPLESAMPLES, GL_STEREO
+
+
+

GL_MULTISAMPLEBUFFERS

+
+

Whether to enable multisampling anti-aliasing. +Defaults to 0 (disabled).

+

Set GL_MULTISAMPLESAMPLES to a value +above 0 to control the amount of anti-aliasing. +A typical value is 2 or 3.

+
+

GL_STENCIL_SIZE

+
+

Minimum bit size of the stencil buffer. Defaults to 0.

+
+

GL_DEPTH_SIZE

+
+

Minimum bit size of the depth buffer. Defaults to 16.

+
+

GL_STEREO

+
+

1 enables stereo 3D. Defaults to 0.

+
+

GL_BUFFER_SIZE

+
+

Minimum bit size of the frame buffer. Defaults to 0.

+
+
+

New in pygame 2.0.0: Additional attributes:

+
+
GL_ACCELERATED_VISUAL,
+GL_CONTEXT_MAJOR_VERSION, GL_CONTEXT_MINOR_VERSION,
+GL_CONTEXT_FLAGS, GL_CONTEXT_PROFILE_MASK,
+GL_SHARE_WITH_CURRENT_CONTEXT,
+GL_CONTEXT_RELEASE_BEHAVIOR,
+GL_FRAMEBUFFER_SRGB_CAPABLE
+
+
+

GL_CONTEXT_PROFILE_MASK

+
+

Sets the OpenGL profile to one of these values:

+
GL_CONTEXT_PROFILE_CORE             disable deprecated features
+GL_CONTEXT_PROFILE_COMPATIBILITY    allow deprecated features
+GL_CONTEXT_PROFILE_ES               allow only the ES feature
+                                    subset of OpenGL
+
+
+
+

GL_ACCELERATED_VISUAL

+
+

Set to 1 to require hardware acceleration, or 0 to force software render. +By default, both are allowed.

+
+
+ +
+
+pygame.display.get_active()¶
+
+
Returns True when the display is active on the screen
+
get_active() -> bool
+
+

Returns True when the display Surface is considered actively +renderable on the screen and may be visible to the user. This is +the default state immediately after pygame.display.set_mode(). +This method may return True even if the application is fully hidden +behind another application window.

+

This will return False if the display Surface has been iconified or +minimized (either via pygame.display.iconify() or via an OS +specific method such as the minimize-icon available on most +desktops).

+

The method can also return False for other reasons without the +application being explicitly iconified or minimized by the user. A +notable example being if the user has multiple virtual desktops and +the display Surface is not on the active virtual desktop.

+
+

Note

+

This function returning True is unrelated to whether the +application has input focus. Please see +pygame.key.get_focused() and pygame.mouse.get_focused() +for APIs related to input focus.

+
+
+ +
+
+pygame.display.iconify()¶
+
+
Iconify the display surface
+
iconify() -> bool
+
+

Request the window for the display surface be iconified or hidden. Not all +systems and displays support an iconified display. The function will return +True if successful.

+

When the display is iconified pygame.display.get_active() will return +False. The event queue should receive an ACTIVEEVENT event when the +window has been iconified. Additionally, the event queue also recieves a +WINDOWEVENT_MINIMIZED event when the window has been iconified on pygame 2.

+
+ +
+
+pygame.display.toggle_fullscreen()¶
+
+
Switch between fullscreen and windowed displays
+
toggle_fullscreen() -> int
+
+

Switches the display window between windowed and fullscreen modes. +Display driver support is not great when using pygame 1, but with +pygame 2 it is the most reliable method to switch to and from fullscreen.

+

Supported display drivers in pygame 1:

+
+
    +
  • x11 (Linux/Unix)

  • +
  • wayland (Linux/Unix)

  • +
+
+

Supported display drivers in pygame 2:

+
+
    +
  • windows (Windows)

  • +
  • x11 (Linux/Unix)

  • +
  • wayland (Linux/Unix)

  • +
  • cocoa (OSX/Mac)

  • +
+
+
+

Note

+

toggle_fullscreen() doesn't work on Windows +unless the window size is in pygame.display.list_modes()Get list of available fullscreen modes or +the window is created with the flag pygame.SCALED. +See issue #2380.

+
+
+ +
+
+pygame.display.set_gamma()¶
+
+
Change the hardware gamma ramps
+
set_gamma(red, green=None, blue=None) -> bool
+
+

Set the red, green, and blue gamma values on the display hardware. If the +green and blue arguments are not passed, they will both be the same as red. +Not all systems and hardware support gamma ramps, if the function succeeds +it will return True.

+

A gamma value of 1.0 creates a linear color table. Lower values will +darken the display and higher values will brighten.

+
+ +
+
+pygame.display.set_gamma_ramp()¶
+
+
Change the hardware gamma ramps with a custom lookup
+
set_gamma_ramp(red, green, blue) -> bool
+
+

Set the red, green, and blue gamma ramps with an explicit lookup table. Each +argument should be sequence of 256 integers. The integers should range +between 0 and 0xffff. Not all systems and hardware support gamma +ramps, if the function succeeds it will return True.

+
+ +
+
+pygame.display.set_icon()¶
+
+
Change the system image for the display window
+
set_icon(Surface) -> None
+
+

Sets the runtime icon the system will use to represent the display window. +All windows default to a simple pygame logo for the window icon.

+

Note that calling this function implicitly initializes pygame.display, if +it was not initialized before.

+

You can pass any surface, but most systems want a smaller image around +32x32. The image can have colorkey transparency which will be passed to the +system.

+

Some systems do not allow the window icon to change after it has been shown. +This function can be called before pygame.display.set_mode() to create +the icon before the display mode is set.

+
+ +
+
+pygame.display.set_caption()¶
+
+
Set the current window caption
+
set_caption(title, icontitle=None) -> None
+
+

If the display has a window title, this function will change the name on the +window. In pygame 1.x, some systems supported an alternate shorter title to +be used for minimized displays, but in pygame 2 icontitle does nothing.

+
+ +
+
+pygame.display.get_caption()¶
+
+
Get the current window caption
+
get_caption() -> (title, icontitle)
+
+

Returns the title and icontitle for the display window. In pygame 2.x +these will always be the same value.

+
+ +
+
+pygame.display.set_palette()¶
+
+
Set the display color palette for indexed displays
+
set_palette(palette=None) -> None
+
+

This will change the video display color palette for 8-bit displays. This +does not change the palette for the actual display Surface, only the palette +that is used to display the Surface. If no palette argument is passed, the +system default palette will be restored. The palette is a sequence of +RGB triplets.

+
+ +
+
+pygame.display.get_num_displays()¶
+
+
Return the number of displays
+
get_num_displays() -> int
+
+

Returns the number of available displays. This is always 1 if +pygame.get_sdl_version()get the version number of SDL returns a major version number below 2.

+
+

New in pygame 1.9.5.

+
+
+ +
+
+pygame.display.get_window_size()¶
+
+
Return the size of the window or screen
+
get_window_size() -> tuple
+
+

Returns the size of the window initialized with pygame.display.set_mode()Initialize a window or screen for display. +This may differ from the size of the display surface if SCALED is used.

+
+

New in pygame 2.0.0.

+
+
+ +
+
+pygame.display.get_allow_screensaver()¶
+
+
Return whether the screensaver is allowed to run.
+
get_allow_screensaver() -> bool
+
+

Return whether screensaver is allowed to run whilst the app is running. +Default is False. +By default pygame does not allow the screensaver during game play.

+
+

Note

+

Some platforms do not have a screensaver or support +disabling the screensaver. Please see +pygame.display.set_allow_screensaver()Set whether the screensaver may run for +caveats with screensaver support.

+
+
+

New in pygame 2.0.0.

+
+
+ +
+
+pygame.display.set_allow_screensaver()¶
+
+
Set whether the screensaver may run
+
set_allow_screensaver(bool) -> None
+
+

Change whether screensavers should be allowed whilst the app is running. +The default value of the argument to the function is True. +By default pygame does not allow the screensaver during game play.

+

If the screensaver has been disallowed due to this function, it will automatically +be allowed to run when pygame.quit()uninitialize all pygame modules is called.

+

It is possible to influence the default value via the environment variable +SDL_HINT_VIDEO_ALLOW_SCREENSAVER, which can be set to either 0 (disable) +or 1 (enable).

+
+

Note

+

Disabling screensaver is subject to platform support. +When platform support is absent, this function will +silently appear to work even though the screensaver state +is unchanged. The lack of feedback is due to SDL not +providing any supported method for determining whether +it supports changing the screensaver state. +SDL_HINT_VIDEO_ALLOW_SCREENSAVER is available in SDL 2.0.2 or later. +SDL1.2 does not implement this.

+
+
+

New in pygame 2.0.0.

+
+
+ +
+ +
+ + +

+
+Edit on GitHub +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/ref/draw.html b/venv/Lib/site-packages/pygame/docs/generated/ref/draw.html new file mode 100644 index 0000000..a8a7bb6 --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/ref/draw.html @@ -0,0 +1,971 @@ + + + + + + + + + pygame.draw — pygame v2.1.2 documentation + + + + + + + + + + + + + +
+ +
+ + + + + +
+
+ +
+
+ +
+
+
+pygame.draw
+
+
pygame module for drawing shapes
+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+—draw a rectangle
+—draw a polygon
+—draw a circle
+—draw an ellipse
+—draw an elliptical arc
+—draw a straight line
+—draw multiple contiguous straight line segments
+—draw a straight antialiased line
+—draw multiple contiguous straight antialiased line segments
+

Draw several simple shapes to a surface. These functions will work for +rendering to any format of surface. Rendering to hardware surfaces will be +slower than regular software surfaces.

+

Most of the functions take a width argument to represent the size of stroke +(thickness) around the edge of the shape. If a width of 0 is passed the shape +will be filled (solid).

+

All the drawing functions respect the clip area for the surface and will be +constrained to that area. The functions return a rectangle representing the +bounding area of changed pixels. This bounding rectangle is the 'minimum' +bounding box that encloses the affected area.

+

All the drawing functions accept a color argument that can be one of the +following formats:

+
+
+
+

A color's alpha value will be written directly into the surface (if the +surface contains pixel alphas), but the draw function will not draw +transparently.

+

These functions temporarily lock the surface they are operating on. Many +sequential drawing calls can be sped up by locking and unlocking the surface +object around the draw calls (see pygame.Surface.lock()lock the Surface memory for pixel access and +pygame.Surface.unlock()unlock the Surface memory from pixel access).

+
+

Note

+

See the pygame.gfxdrawpygame module for drawing shapes module for alternative draw methods.

+
+
+
+pygame.draw.rect()¶
+
+
draw a rectangle
+
rect(surface, color, rect) -> Rect
+
rect(surface, color, rect, width=0, border_radius=0, border_top_left_radius=-1, border_top_right_radius=-1, border_bottom_left_radius=-1, border_bottom_right_radius=-1) -> Rect
+
+

Draws a rectangle on the given surface.

+
+
Parameters
+
    +
  • surface (Surface) -- surface to draw on

  • +
  • color (Color or int or tuple(int, int, int, [int])) -- color to draw with, the alpha value is optional if using a +tuple (RGB[A])

  • +
  • rect (Rect) -- rectangle to draw, position and dimensions

  • +
  • width (int) --

    (optional) used for line thickness or to indicate that +the rectangle is to be filled (not to be confused with the width value +of the rect parameter)

    +
    +
    +
    if width == 0, (default) fill the rectangle
    +
    if width > 0, used for line thickness
    +
    if width < 0, nothing will be drawn
    +

    +
    +
    +

    Note

    +

    When using width values > 1, the edge lines will grow +outside the original boundary of the rect. For more details on +how the thickness for edge lines grow, refer to the width notes +of the pygame.draw.line()draw a straight line function.

    +
    +
    +

  • +
  • border_radius (int) -- (optional) used for drawing rectangle with rounded corners. +The supported range is [0, min(height, width) / 2], with 0 representing a rectangle +without rounded corners.

  • +
  • border_top_left_radius (int) -- (optional) used for setting the value of top left +border. If you don't set this value, it will use the border_radius value.

  • +
  • border_top_right_radius (int) -- (optional) used for setting the value of top right +border. If you don't set this value, it will use the border_radius value.

  • +
  • border_bottom_left_radius (int) -- (optional) used for setting the value of bottom left +border. If you don't set this value, it will use the border_radius value.

  • +
  • border_bottom_right_radius (int) --

    (optional) used for setting the value of bottom right +border. If you don't set this value, it will use the border_radius value.

    +
    +
    +
    if border_radius < 1 it will draw rectangle without rounded corners
    +
    if any of border radii has the value < 0 it will use value of the border_radius
    +
    If sum of radii on the same side of the rectangle is greater than the rect size the radii
    +
    will get scaled
    +
    +
    +

  • +
+
+
Returns
+

a rect bounding the changed pixels, if nothing is drawn the +bounding rect's position will be the position of the given rect +parameter and its width and height will be 0

+
+
Return type
+

Rect

+
+
+
+

Note

+

The pygame.Surface.fill()fill Surface with a solid color method works just as well for drawing +filled rectangles and can be hardware accelerated on some platforms with +both software and hardware display modes.

+
+
+

Changed in pygame 2.0.0: Added support for keyword arguments.

+
+
+

Changed in pygame 2.0.0.dev8: Added support for border radius.

+
+
+ +
+
+pygame.draw.polygon()¶
+
+
draw a polygon
+
polygon(surface, color, points) -> Rect
+
polygon(surface, color, points, width=0) -> Rect
+
+

Draws a polygon on the given surface.

+
+
Parameters
+
    +
  • surface (Surface) -- surface to draw on

  • +
  • color (Color or int or tuple(int, int, int, [int])) -- color to draw with, the alpha value is optional if using a +tuple (RGB[A])

  • +
  • points (tuple(coordinate) or list(coordinate)) -- a sequence of 3 or more (x, y) coordinates that make up the +vertices of the polygon, each coordinate in the sequence must be a +tuple/list/pygame.math.Vector2a 2-Dimensional Vector of 2 ints/floats, +e.g. [(x1, y1), (x2, y2), (x3, y3)]

  • +
  • width (int) --

    (optional) used for line thickness or to indicate that +the polygon is to be filled

    +
    +
    +
    if width == 0, (default) fill the polygon
    +
    if width > 0, used for line thickness
    +
    if width < 0, nothing will be drawn
    +

    +
    +
    +

    Note

    +

    When using width values > 1, the edge lines will grow +outside the original boundary of the polygon. For more details on +how the thickness for edge lines grow, refer to the width notes +of the pygame.draw.line()draw a straight line function.

    +
    +
    +

  • +
+
+
Returns
+

a rect bounding the changed pixels, if nothing is drawn the +bounding rect's position will be the position of the first point in the +points parameter (float values will be truncated) and its width and +height will be 0

+
+
Return type
+

Rect

+
+
Raises
+
    +
  • ValueError -- if len(points) < 3 (must have at least 3 points)

  • +
  • TypeError -- if points is not a sequence or points does not +contain number pairs

  • +
+
+
+
+

Note

+

For an aapolygon, use aalines() with closed=True.

+
+
+

Changed in pygame 2.0.0: Added support for keyword arguments.

+
+
+ +
+
+pygame.draw.circle()¶
+
+
draw a circle
+
circle(surface, color, center, radius) -> Rect
+
circle(surface, color, center, radius, width=0, draw_top_right=None, draw_top_left=None, draw_bottom_left=None, draw_bottom_right=None) -> Rect
+
+

Draws a circle on the given surface.

+
+
Parameters
+
    +
  • surface (Surface) -- surface to draw on

  • +
  • color (Color or int or tuple(int, int, int, [int])) -- color to draw with, the alpha value is optional if using a +tuple (RGB[A])

  • +
  • center (tuple(int or float, int or float) or +list(int or float, int or float) or Vector2(int or float, int or float)) -- center point of the circle as a sequence of 2 ints/floats, +e.g. (x, y)

  • +
  • radius (int or float) -- radius of the circle, measured from the center parameter, +nothing will be drawn if the radius is less than 1

  • +
  • width (int) --

    (optional) used for line thickness or to indicate that +the circle is to be filled

    +
    +
    +
    if width == 0, (default) fill the circle
    +
    if width > 0, used for line thickness
    +
    if width < 0, nothing will be drawn
    +

    +
    +
    +

    Note

    +

    When using width values > 1, the edge lines will only grow +inward.

    +
    +
    +

  • +
  • draw_top_right (bool) -- (optional) if this is set to True then the top right corner +of the circle will be drawn

  • +
  • draw_top_left (bool) -- (optional) if this is set to True then the top left corner +of the circle will be drawn

  • +
  • draw_bottom_left (bool) -- (optional) if this is set to True then the bottom left corner +of the circle will be drawn

  • +
  • draw_bottom_right (bool) --

    (optional) if this is set to True then the bottom right corner +of the circle will be drawn

    +
    +
    +
    if any of the draw_circle_part is True then it will draw all circle parts that have the True
    +
    value, otherwise it will draw the entire circle.
    +
    +
    +

  • +
+
+
Returns
+

a rect bounding the changed pixels, if nothing is drawn the +bounding rect's position will be the center parameter value (float +values will be truncated) and its width and height will be 0

+
+
Return type
+

Rect

+
+
Raises
+
    +
  • TypeError -- if center is not a sequence of two numbers

  • +
  • TypeError -- if radius is not a number

  • +
+
+
+
+

Changed in pygame 2.0.0: Added support for keyword arguments. +Nothing is drawn when the radius is 0 (a pixel at the center coordinates +used to be drawn when the radius equaled 0). +Floats, and Vector2 are accepted for the center param. +The drawing algorithm was improved to look more like a circle.

+
+
+

Changed in pygame 2.0.0.dev8: Added support for drawing circle quadrants.

+
+
+ +
+
+pygame.draw.ellipse()¶
+
+
draw an ellipse
+
ellipse(surface, color, rect) -> Rect
+
ellipse(surface, color, rect, width=0) -> Rect
+
+

Draws an ellipse on the given surface.

+
+
Parameters
+
    +
  • surface (Surface) -- surface to draw on

  • +
  • color (Color or int or tuple(int, int, int, [int])) -- color to draw with, the alpha value is optional if using a +tuple (RGB[A])

  • +
  • rect (Rect) -- rectangle to indicate the position and dimensions of the +ellipse, the ellipse will be centered inside the rectangle and bounded +by it

  • +
  • width (int) --

    (optional) used for line thickness or to indicate that +the ellipse is to be filled (not to be confused with the width value +of the rect parameter)

    +
    +
    +
    if width == 0, (default) fill the ellipse
    +
    if width > 0, used for line thickness
    +
    if width < 0, nothing will be drawn
    +

    +
    +
    +

    Note

    +

    When using width values > 1, the edge lines will only grow +inward from the original boundary of the rect parameter.

    +
    +
    +

  • +
+
+
Returns
+

a rect bounding the changed pixels, if nothing is drawn the +bounding rect's position will be the position of the given rect +parameter and its width and height will be 0

+
+
Return type
+

Rect

+
+
+
+

Changed in pygame 2.0.0: Added support for keyword arguments.

+
+
+ +
+
+pygame.draw.arc()¶
+
+
draw an elliptical arc
+
arc(surface, color, rect, start_angle, stop_angle) -> Rect
+
arc(surface, color, rect, start_angle, stop_angle, width=1) -> Rect
+
+

Draws an elliptical arc on the given surface.

+

The two angle arguments are given in radians and indicate the start and stop +positions of the arc. The arc is drawn in a counterclockwise direction from +the start_angle to the stop_angle.

+
+
Parameters
+
    +
  • surface (Surface) -- surface to draw on

  • +
  • color (Color or int or tuple(int, int, int, [int])) -- color to draw with, the alpha value is optional if using a +tuple (RGB[A])

  • +
  • rect (Rect) -- rectangle to indicate the position and dimensions of the +ellipse which the arc will be based on, the ellipse will be centered +inside the rectangle

  • +
  • start_angle (float) -- start angle of the arc in radians

  • +
  • stop_angle (float) --

    stop angle of the arc in +radians

    +
    +
    +
    if start_angle < stop_angle, the arc is drawn in a +counterclockwise direction from the start_angle to the +stop_angle
    +
    if start_angle > stop_angle, tau (tau == 2 * pi) will be added +to the stop_angle, if the resulting stop angle value is greater +than the start_angle the above start_angle < stop_angle case +applies, otherwise nothing will be drawn
    +
    if start_angle == stop_angle, nothing will be drawn
    +

    +
    +
    +

  • +
  • width (int) --

    (optional) used for line thickness (not to be confused +with the width value of the rect parameter)

    +
    +
    +
    if width == 0, nothing will be drawn
    +
    if width > 0, (default is 1) used for line thickness
    +
    if width < 0, same as width == 0
    +
    +
    +

    Note

    +

    When using width values > 1, the edge lines will only grow +inward from the original boundary of the rect parameter.

    +
    +
    +

  • +
+
+
Returns
+

a rect bounding the changed pixels, if nothing is drawn the +bounding rect's position will be the position of the given rect +parameter and its width and height will be 0

+
+
Return type
+

Rect

+
+
+
+

Changed in pygame 2.0.0: Added support for keyword arguments.

+
+
+ +
+
+pygame.draw.line()¶
+
+
draw a straight line
+
line(surface, color, start_pos, end_pos) -> Rect
+
line(surface, color, start_pos, end_pos, width=1) -> Rect
+
+

Draws a straight line on the given surface. There are no endcaps. For thick +lines the ends are squared off.

+
+
Parameters
+
    +
  • surface (Surface) -- surface to draw on

  • +
  • color (Color or int or tuple(int, int, int, [int])) -- color to draw with, the alpha value is optional if using a +tuple (RGB[A])

  • +
  • start_pos (tuple(int or float, int or float) or +list(int or float, int or float) or Vector2(int or float, int or float)) -- start position of the line, (x, y)

  • +
  • end_pos (tuple(int or float, int or float) or +list(int or float, int or float) or Vector2(int or float, int or float)) -- end position of the line, (x, y)

  • +
  • width (int) --

    (optional) used for line thickness

    +
    +
    if width >= 1, used for line thickness (default is 1)
    +
    if width < 1, nothing will be drawn
    +

    +
    +
    +

    Note

    +

    When using width values > 1, lines will grow as follows.

    +

    For odd width values, the thickness of each line grows with the +original line being in the center.

    +

    For even width values, the thickness of each line grows with the +original line being offset from the center (as there is no exact +center line drawn). As a result, lines with a slope < 1 +(horizontal-ish) will have 1 more pixel of thickness below the +original line (in the y direction). Lines with a slope >= 1 +(vertical-ish) will have 1 more pixel of thickness to the right of +the original line (in the x direction).

    +
    +

  • +
+
+
Returns
+

a rect bounding the changed pixels, if nothing is drawn the +bounding rect's position will be the start_pos parameter value (float +values will be truncated) and its width and height will be 0

+
+
Return type
+

Rect

+
+
Raises
+

TypeError -- if start_pos or end_pos is not a sequence of +two numbers

+
+
+
+

Changed in pygame 2.0.0: Added support for keyword arguments.

+
+
+ +
+
+pygame.draw.lines()¶
+
+
draw multiple contiguous straight line segments
+
lines(surface, color, closed, points) -> Rect
+
lines(surface, color, closed, points, width=1) -> Rect
+
+

Draws a sequence of contiguous straight lines on the given surface. There are +no endcaps or miter joints. For thick lines the ends are squared off. +Drawing thick lines with sharp corners can have undesired looking results.

+
+
Parameters
+
    +
  • surface (Surface) -- surface to draw on

  • +
  • color (Color or int or tuple(int, int, int, [int])) -- color to draw with, the alpha value is optional if using a +tuple (RGB[A])

  • +
  • closed (bool) -- if True an additional line segment is drawn between +the first and last points in the points sequence

  • +
  • points (tuple(coordinate) or list(coordinate)) -- a sequence of 2 or more (x, y) coordinates, where each +coordinate in the sequence must be a +tuple/list/pygame.math.Vector2a 2-Dimensional Vector of 2 ints/floats and adjacent +coordinates will be connected by a line segment, e.g. for the +points [(x1, y1), (x2, y2), (x3, y3)] a line segment will be drawn +from (x1, y1) to (x2, y2) and from (x2, y2) to (x3, y3), +additionally if the closed parameter is True another line segment +will be drawn from (x3, y3) to (x1, y1)

  • +
  • width (int) --

    (optional) used for line thickness

    +
    +
    if width >= 1, used for line thickness (default is 1)
    +
    if width < 1, nothing will be drawn
    +

    +
    +
    +

    Note

    +

    When using width values > 1 refer to the width notes +of line() for details on how thick lines grow.

    +
    +

  • +
+
+
Returns
+

a rect bounding the changed pixels, if nothing is drawn the +bounding rect's position will be the position of the first point in the +points parameter (float values will be truncated) and its width and +height will be 0

+
+
Return type
+

Rect

+
+
Raises
+
    +
  • ValueError -- if len(points) < 2 (must have at least 2 points)

  • +
  • TypeError -- if points is not a sequence or points does not +contain number pairs

  • +
+
+
+
+

Changed in pygame 2.0.0: Added support for keyword arguments.

+
+
+ +
+
+pygame.draw.aaline()¶
+
+
draw a straight antialiased line
+
aaline(surface, color, start_pos, end_pos) -> Rect
+
aaline(surface, color, start_pos, end_pos, blend=1) -> Rect
+
+

Draws a straight antialiased line on the given surface.

+

The line has a thickness of one pixel and the endpoints have a height and +width of one pixel each.

+
+
The way a line and its endpoints are drawn:

If both endpoints are equal, only a single pixel is drawn (after +rounding floats to nearest integer).

+

Otherwise if the line is not steep (i.e. if the length along the x-axis +is greater than the height along the y-axis):

+
+

For each endpoint:

+
+

If x, the endpoint's x-coordinate, is a whole number find +which pixels would be covered by it and draw them.

+

Otherwise:

+
+

Calculate the position of the nearest point with a whole number +for its x-coordinate, when extending the line past the +endpoint.

+

Find which pixels would be covered and how much by that point.

+

If the endpoint is the left one, multiply the coverage by (1 - +the decimal part of x).

+

Otherwise multiply the coverage by the decimal part of x.

+

Then draw those pixels.

+
+
e.g.:
+
The left endpoint of the line ((1, 1.3), (5, 3)) would +cover 70% of the pixel (1, 1) and 30% of the pixel +(1, 2) while the right one would cover 100% of the +pixel (5, 3).
+
The left endpoint of the line ((1.2, 1.4), (4.6, 3.1)) +would cover 56% (i.e. 0.8 * 70%) of the pixel (1, 1) +and 24% (i.e. 0.8 * 30%) of the pixel (1, 2) while +the right one would cover 42% (i.e. 0.6 * 70%) of the +pixel (5, 3) and 18% (i.e. 0.6 * 30%) of the pixel +(5, 4) while the right
+
+
+
+
+
+

Then for each point between the endpoints, along the line, whose +x-coordinate is a whole number:

+
+

Find which pixels would be covered and how much by that point and +draw them.

+
+
e.g.:
+
The points along the line ((1, 1), (4, 2.5)) would be +(2, 1.5) and (3, 2) and would cover 50% of the pixel +(2, 1), 50% of the pixel (2, 2) and 100% of the pixel +(3, 2).
+
The points along the line ((1.2, 1.4), (4.6, 3.1)) would +be (2, 1.8) (covering 20% of the pixel (2, 1) and 80% +of the pixel (2, 2)), (3, 2.3) (covering 70% of the +pixel (3, 2) and 30% of the pixel (3, 3)) and (4, +2.8) (covering 20% of the pixel (2, 1) and 80% of the +pixel (2, 2))
+
+
+
+
+
+

Otherwise do the same for steep lines as for non-steep lines except +along the y-axis instead of the x-axis (using y instead of x, +top instead of left and bottom instead of right).

+
+
+
+

Note

+

Regarding float values for coordinates, a point with coordinate +consisting of two whole numbers is considered being right in the center +of said pixel (and having a height and width of 1 pixel would therefore +completely cover it), while a point with coordinate where one (or both) +of the numbers have non-zero decimal parts would be partially covering +two (or four if both numbers have decimal parts) adjacent pixels, e.g. +the point (1.4, 2) covers 60% of the pixel (1, 2) and 40% of the +pixel (2,2).

+
+
+
Parameters
+
    +
  • surface (Surface) -- surface to draw on

  • +
  • color (Color or int or tuple(int, int, int, [int])) -- color to draw with, the alpha value is optional if using a +tuple (RGB[A])

  • +
  • start_pos (tuple(int or float, int or float) or +list(int or float, int or float) or Vector2(int or float, int or float)) -- start position of the line, (x, y)

  • +
  • end_pos (tuple(int or float, int or float) or +list(int or float, int or float) or Vector2(int or float, int or float)) -- end position of the line, (x, y)

  • +
  • blend (int) -- (optional) if non-zero (default) the line will be blended +with the surface's existing pixel shades, otherwise it will overwrite them

  • +
+
+
Returns
+

a rect bounding the changed pixels, if nothing is drawn the +bounding rect's position will be the start_pos parameter value (float +values will be truncated) and its width and height will be 0

+
+
Return type
+

Rect

+
+
Raises
+

TypeError -- if start_pos or end_pos is not a sequence of +two numbers

+
+
+
+

Changed in pygame 2.0.0: Added support for keyword arguments.

+
+
+ +
+
+pygame.draw.aalines()¶
+
+
draw multiple contiguous straight antialiased line segments
+
aalines(surface, color, closed, points) -> Rect
+
aalines(surface, color, closed, points, blend=1) -> Rect
+
+

Draws a sequence of contiguous straight antialiased lines on the given +surface.

+
+
Parameters
+
    +
  • surface (Surface) -- surface to draw on

  • +
  • color (Color or int or tuple(int, int, int, [int])) -- color to draw with, the alpha value is optional if using a +tuple (RGB[A])

  • +
  • closed (bool) -- if True an additional line segment is drawn between +the first and last points in the points sequence

  • +
  • points (tuple(coordinate) or list(coordinate)) -- a sequence of 2 or more (x, y) coordinates, where each +coordinate in the sequence must be a +tuple/list/pygame.math.Vector2a 2-Dimensional Vector of 2 ints/floats and adjacent +coordinates will be connected by a line segment, e.g. for the +points [(x1, y1), (x2, y2), (x3, y3)] a line segment will be drawn +from (x1, y1) to (x2, y2) and from (x2, y2) to (x3, y3), +additionally if the closed parameter is True another line segment +will be drawn from (x3, y3) to (x1, y1)

  • +
  • blend (int) -- (optional) if non-zero (default) each line will be blended +with the surface's existing pixel shades, otherwise the pixels will be +overwritten

  • +
+
+
Returns
+

a rect bounding the changed pixels, if nothing is drawn the +bounding rect's position will be the position of the first point in the +points parameter (float values will be truncated) and its width and +height will be 0

+
+
Return type
+

Rect

+
+
Raises
+
    +
  • ValueError -- if len(points) < 2 (must have at least 2 points)

  • +
  • TypeError -- if points is not a sequence or points does not +contain number pairs

  • +
+
+
+
+

Changed in pygame 2.0.0: Added support for keyword arguments.

+
+
+ +
+draw module example +
+

Example code for draw module.¶

+
+
+
# Import a library of functions called 'pygame'
+import pygame
+from math import pi
+ 
+# Initialize the game engine
+pygame.init()
+ 
+# Define the colors we will use in RGB format
+BLACK = (  0,   0,   0)
+WHITE = (255, 255, 255)
+BLUE =  (  0,   0, 255)
+GREEN = (  0, 255,   0)
+RED =   (255,   0,   0)
+ 
+# Set the height and width of the screen
+size = [400, 300]
+screen = pygame.display.set_mode(size)
+ 
+pygame.display.set_caption("Example code for the draw module")
+ 
+#Loop until the user clicks the close button.
+done = False
+clock = pygame.time.Clock()
+ 
+while not done:
+ 
+    # This limits the while loop to a max of 10 times per second.
+    # Leave this out and we will use all CPU we can.
+    clock.tick(10)
+     
+    for event in pygame.event.get(): # User did something
+        if event.type == pygame.QUIT: # If user clicked close
+            done=True # Flag that we are done so we exit this loop
+ 
+    # All drawing code happens after the for loop and but
+    # inside the main while done==False loop.
+     
+    # Clear the screen and set the screen background
+    screen.fill(WHITE)
+ 
+    # Draw on the screen a GREEN line from (0, 0) to (50, 30) 
+    # 5 pixels wide.
+    pygame.draw.line(screen, GREEN, [0, 0], [50,30], 5)
+ 
+    # Draw on the screen 3 BLACK lines, each 5 pixels wide.
+    # The 'False' means the first and last points are not connected.
+    pygame.draw.lines(screen, BLACK, False, [[0, 80], [50, 90], [200, 80], [220, 30]], 5)
+    
+    # Draw on the screen a GREEN line from (0, 50) to (50, 80) 
+    # Because it is an antialiased line, it is 1 pixel wide.
+    pygame.draw.aaline(screen, GREEN, [0, 50],[50, 80], True)
+
+    # Draw a rectangle outline
+    pygame.draw.rect(screen, BLACK, [75, 10, 50, 20], 2)
+     
+    # Draw a solid rectangle
+    pygame.draw.rect(screen, BLACK, [150, 10, 50, 20])
+
+    # Draw a rectangle with rounded corners
+    pygame.draw.rect(screen, GREEN, [115, 210, 70, 40], 10, border_radius=15)
+    pygame.draw.rect(screen, RED, [135, 260, 50, 30], 0, border_radius=10, border_top_left_radius=0,
+                     border_bottom_right_radius=15)
+
+    # Draw an ellipse outline, using a rectangle as the outside boundaries
+    pygame.draw.ellipse(screen, RED, [225, 10, 50, 20], 2) 
+
+    # Draw an solid ellipse, using a rectangle as the outside boundaries
+    pygame.draw.ellipse(screen, RED, [300, 10, 50, 20]) 
+ 
+    # This draws a triangle using the polygon command
+    pygame.draw.polygon(screen, BLACK, [[100, 100], [0, 200], [200, 200]], 5)
+  
+    # Draw an arc as part of an ellipse. 
+    # Use radians to determine what angle to draw.
+    pygame.draw.arc(screen, BLACK,[210, 75, 150, 125], 0, pi/2, 2)
+    pygame.draw.arc(screen, GREEN,[210, 75, 150, 125], pi/2, pi, 2)
+    pygame.draw.arc(screen, BLUE, [210, 75, 150, 125], pi,3*pi/2, 2)
+    pygame.draw.arc(screen, RED,  [210, 75, 150, 125], 3*pi/2, 2*pi, 2)
+    
+    # Draw a circle
+    pygame.draw.circle(screen, BLUE, [60, 250], 40)
+
+    # Draw only one circle quadrant
+    pygame.draw.circle(screen, BLUE, [250, 250], 40, 0, draw_top_right=True)
+    pygame.draw.circle(screen, RED, [250, 250], 40, 30, draw_top_left=True)
+    pygame.draw.circle(screen, GREEN, [250, 250], 40, 20, draw_bottom_left=True)
+    pygame.draw.circle(screen, BLACK, [250, 250], 40, 10, draw_bottom_right=True)
+
+    # Go ahead and update the screen with what we've drawn.
+    # This MUST happen after all the other drawing commands.
+    pygame.display.flip()
+ 
+# Be IDLE friendly
+pygame.quit()
+
+
+
+ +
+ + +

+
+Edit on GitHub +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/ref/event.html b/venv/Lib/site-packages/pygame/docs/generated/ref/event.html new file mode 100644 index 0000000..4906eb6 --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/ref/event.html @@ -0,0 +1,715 @@ + + + + + + + + + pygame.event — pygame v2.1.2 documentation + + + + + + + + + + + + + +
+ +
+ + + + + +
+
+ +
+
+ +
+
+
+pygame.event
+
+
pygame module for interacting with events and queues
+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+—internally process pygame event handlers
+—get events from the queue
+—get a single event from the queue
+—wait for a single event from the queue
+—test if event types are waiting on the queue
+—remove all events from the queue
+—get the string name from an event id
+—control which events are allowed on the queue
+—control which events are allowed on the queue
+—test if a type of event is blocked from the queue
+—control the sharing of input devices with other applications
+—test if the program is sharing input devices
+—place a new event on the queue
+—make custom user event type
+—create a new event object
+—pygame object for representing events
+

Pygame handles all its event messaging through an event queue. The routines in +this module help you manage that event queue. The input queue is heavily +dependent on the pygame.displaypygame module to control the display window and screen module. If the display has not been +initialized and a video mode not set, the event queue may not work properly.

+

The event queue has an upper limit on the number of events it can hold. When +the queue becomes full new events are quietly dropped. To prevent lost events, +especially input events which signal a quit command, your program must handle +events every frame (with pygame.event.get(), pygame.event.pump(), +pygame.event.wait(), pygame.event.peek() or pygame.event.clear()) +and process them. Not handling events may cause your system to decide your +program has locked up. To speed up queue processing use +pygame.event.set_blocked()control which events are allowed on the queue to limit which events get queued.

+

To get the state of various input devices, you can forego the event queue and +access the input devices directly with their appropriate modules: +pygame.mousepygame module to work with the mouse, pygame.keypygame module to work with the keyboard, and pygame.joystickPygame module for interacting with joysticks, gamepads, and trackballs.. If you use +this method, remember that pygame requires some form of communication with the +system window manager and other parts of the platform. To keep pygame in sync +with the system, you will need to call pygame.event.pump()internally process pygame event handlers to keep +everything current. Usually, this should be called once per game loop. +Note: Joysticks will not send any events until the device has been initialized.

+

The event queue contains pygame.event.EventTypepygame object for representing events event objects. +There are a variety of ways to access the queued events, from simply +checking for the existence of events, to grabbing them directly off the stack. +The event queue also offers some simple filtering which can slightly help +performance by blocking certain event types from the queue. Use +pygame.event.set_allowed()control which events are allowed on the queue and pygame.event.set_blocked()control which events are allowed on the queue to +change this filtering. By default, all event types can be placed on the queue.

+

All pygame.event.EventTypepygame object for representing events instances contain an event type identifier +and attributes specific to that event type. The event type identifier is +accessible as the pygame.event.EventType.typeevent type identifier. property. Any of the +event specific attributes can be accessed through the +pygame.event.EventType.__dict__event attribute dictionary attribute or directly as an attribute +of the event object (as member lookups are passed through to the object's +dictionary values). The event object has no method functions. Users can create +their own new events with the pygame.event.Event()create a new event object function.

+

The event type identifier is in between the values of NOEVENT and +NUMEVENTS. User defined events should have a value in the inclusive range +of USEREVENT to NUMEVENTS - 1. User defined events can get a custom +event number with pygame.event.custom_type()make custom user event type. +It is recommended all user events follow this system.

+

Events support equality and inequality comparisons. Two events are equal if +they are the same type and have identical attribute values.

+

While debugging and experimenting, you can print an event object for a quick +display of its type and members. The function pygame.event.event_name()get the string name from an event id +can be used to get a string representing the name of the event type.

+

Events that come from the system will have a guaranteed set of member +attributes based on the type. The following is a list event types with their +specific attributes.

+
QUIT              none
+ACTIVEEVENT       gain, state
+KEYDOWN           key, mod, unicode, scancode
+KEYUP             key, mod, unicode, scancode
+MOUSEMOTION       pos, rel, buttons, touch
+MOUSEBUTTONUP     pos, button, touch
+MOUSEBUTTONDOWN   pos, button, touch
+JOYAXISMOTION     joy (deprecated), instance_id, axis, value
+JOYBALLMOTION     joy (deprecated), instance_id, ball, rel
+JOYHATMOTION      joy (deprecated), instance_id, hat, value
+JOYBUTTONUP       joy (deprecated), instance_id, button
+JOYBUTTONDOWN     joy (deprecated), instance_id, button
+VIDEORESIZE       size, w, h
+VIDEOEXPOSE       none
+USEREVENT         code
+
+
+
+

Changed in pygame 2.0.0: The joy attribute was deprecated, instance_id was added.

+
+
+

Changed in pygame 2.0.1: The unicode attribute was added to KEYUP event.

+
+

You can also find a list of constants for keyboard keys +here.

+
+

+
+

On MacOSX when a file is opened using a pygame application, a USEREVENT +with its code attribute set to pygame.USEREVENT_DROPFILE is generated. +There is an additional attribute called filename where the name of the file +being accessed is stored.

+
USEREVENT         code=pygame.USEREVENT_DROPFILE, filename
+
+
+
+

New in pygame 1.9.2.

+
+
+

+
+

When compiled with SDL2, pygame has these additional events and their +attributes.

+
AUDIODEVICEADDED   which, iscapture
+AUDIODEVICEREMOVED which, iscapture
+FINGERMOTION       touch_id, finger_id, x, y, dx, dy
+FINGERDOWN         touch_id, finger_id, x, y, dx, dy
+FINGERUP           touch_id, finger_id, x, y, dx, dy
+MOUSEWHEEL         which, flipped, x, y, touch
+MULTIGESTURE       touch_id, x, y, pinched, rotated, num_fingers
+TEXTEDITING        text, start, length
+TEXTINPUT          text
+
+
+
+

New in pygame 1.9.5.

+
+
+

Changed in pygame 2.0.2: Fixed amount horizontal scroll (x, positive to the right and negative to the left).

+
+
+

Changed in pygame 2.0.2: The touch attribute was added to all the MOUSE events.

+
+

The touch attribute of MOUSE events indicates whether or not the events were generated +by a touch input device, and not a real mouse. You might want to ignore such events, if your application +already handles FINGERMOTION, FINGERDOWN and FINGERUP events.

+
+

+
+

Many new events were introduced in pygame 2.

+

pygame can recognize text or files dropped in its window. If a file +is dropped, DROPFILE event will be sent, file will be its path. +The DROPTEXT event is only supported on X11.

+

MIDIIN and MIDIOUT are events reserved for pygame.midipygame module for interacting with midi input and output. use.

+

pygame 2 also supports controller hot-plugging

+
DROPBEGIN
+DROPCOMPLETE
+DROPFILE                 file
+DROPTEXT                 text
+MIDIIN
+MIDIOUT
+CONTROLLERDEVICEADDED    device_index
+JOYDEVICEADDED           device_index
+CONTROLLERDEVICEREMOVED  instance_id
+JOYDEVICEREMOVED         instance_id
+CONTROLLERDEVICEREMAPPED instance_id
+
+
+

Also in this version, instance_id attributes were added to joystick events, +and the joy attribute was deprecated.

+
+

New in pygame 2.0.0.

+
+

Since pygame 2.0.1, there are a new set of events, called window events. +Here is a list of all window events, along with a short description

+
Event type                Short description
+
+WINDOWSHOWN            Window became shown
+WINDOWHIDDEN           Window became hidden
+WINDOWEXPOSED          Window got updated by some external event
+WINDOWMOVED            Window got moved
+WINDOWRESIZED          Window got resized
+WINDOWSIZECHANGED      Window changed its size
+WINDOWMINIMIZED        Window was minimized
+WINDOWMAXIMIZED        Window was maximized
+WINDOWRESTORED         Window was restored
+WINDOWENTER            Mouse entered the window
+WINDOWLEAVE            Mouse left the window
+WINDOWFOCUSGAINED      Window gained focus
+WINDOWFOCUSLOST        Window lost focus
+WINDOWCLOSE            Window was closed
+WINDOWTAKEFOCUS        Window was offered focus
+WINDOWHITTEST          Window has a special hit test
+
+
+

If SDL version used is less than 2.0.5, the last two events WINDOWTAKEFOCUS +and WINDOWHITTEST will not work.

+

Most these window events do not have any attributes, except WINDOWMOVED, +WINDOWRESIZED and WINDOWSIZECHANGED, these have x and y attributes

+
+

+
+
+
+pygame.event.pump()¶
+
+
internally process pygame event handlers
+
pump() -> None
+
+

For each frame of your game, you will need to make some sort of call to the +event queue. This ensures your program can internally interact with the rest +of the operating system. If you are not using other event functions in your +game, you should call pygame.event.pump() to allow pygame to handle +internal actions.

+

This function is not necessary if your program is consistently processing +events on the queue through the other pygame.eventpygame module for interacting with events and queues functions.

+

There are important things that must be dealt with internally in the event +queue. The main window may need to be repainted or respond to the system. If +you fail to make a call to the event queue for too long, the system may +decide your program has locked up.

+
+

Caution

+

This function should only be called in the thread that initialized pygame.displaypygame module to control the display window and screen.

+
+
+ +
+
+pygame.event.get()¶
+
+
get events from the queue
+
get(eventtype=None) -> Eventlist
+
get(eventtype=None, pump=True) -> Eventlist
+
get(eventtype=None, pump=True, exclude=None) -> Eventlist
+
+

This will get all the messages and remove them from the queue. If a type or +sequence of types is given only those messages will be removed from the +queue and returned.

+

If a type or sequence of types is passed in the exclude argument +instead, then all only other messages will be removed from the queue. If +an exclude parameter is passed, the eventtype parameter must be +None.

+

If you are only taking specific events from the queue, be aware that the +queue could eventually fill up with the events you are not interested.

+

If pump is True (the default), then pygame.event.pump()internally process pygame event handlers will be called.

+
+

Changed in pygame 1.9.5: Added pump argument

+
+
+

Changed in pygame 2.0.2: Added exclude argument

+
+
+ +
+
+pygame.event.poll()¶
+
+
get a single event from the queue
+
poll() -> EventType instance
+
+

Returns a single event from the queue. If the event queue is empty an event +of type pygame.NOEVENT will be returned immediately. The returned event +is removed from the queue.

+
+

Caution

+

This function should only be called in the thread that initialized pygame.displaypygame module to control the display window and screen.

+
+
+ +
+
+pygame.event.wait()¶
+
+
wait for a single event from the queue
+
wait() -> EventType instance
+
wait(timeout) -> EventType instance
+
+

Returns a single event from the queue. If the queue is empty this function +will wait until one is created. From pygame 2.0.0, if a timeout argument +is given, the function will return an event of type pygame.NOEVENT +if no events enter the queue in timeout milliseconds. The event is removed +from the queue once it has been returned. While the program is waiting it will +sleep in an idle state. This is important for programs that want to share the +system with other applications.

+
+

Changed in pygame 2.0.0.dev13: Added timeout argument

+
+
+

Caution

+

This function should only be called in the thread that initialized pygame.displaypygame module to control the display window and screen.

+
+
+ +
+
+pygame.event.peek()¶
+
+
test if event types are waiting on the queue
+
peek(eventtype=None) -> bool
+
peek(eventtype=None, pump=True) -> bool
+
+

Returns True if there are any events of the given type waiting on the +queue. If a sequence of event types is passed, this will return True if +any of those events are on the queue.

+

If pump is True (the default), then pygame.event.pump()internally process pygame event handlers will be called.

+
+

Changed in pygame 1.9.5: Added pump argument

+
+
+ +
+
+pygame.event.clear()¶
+
+
remove all events from the queue
+
clear(eventtype=None) -> None
+
clear(eventtype=None, pump=True) -> None
+
+

Removes all events from the queue. If eventtype is given, removes the given event +or sequence of events. This has the same effect as pygame.event.get()get events from the queue except None +is returned. It can be slightly more efficient when clearing a full event queue.

+

If pump is True (the default), then pygame.event.pump()internally process pygame event handlers will be called.

+
+

Changed in pygame 1.9.5: Added pump argument

+
+
+ +
+
+pygame.event.event_name()¶
+
+
get the string name from an event id
+
event_name(type) -> string
+
+

Returns a string representing the name (in CapWords style) of the given +event type.

+

"UserEvent" is returned for all values in the user event id range. +"Unknown" is returned when the event type does not exist.

+
+ +
+
+pygame.event.set_blocked()¶
+
+
control which events are allowed on the queue
+
set_blocked(type) -> None
+
set_blocked(typelist) -> None
+
set_blocked(None) -> None
+
+

The given event types are not allowed to appear on the event queue. By +default all events can be placed on the queue. It is safe to disable an +event type multiple times.

+

If None is passed as the argument, ALL of the event types are blocked +from being placed on the queue.

+
+ +
+
+pygame.event.set_allowed()¶
+
+
control which events are allowed on the queue
+
set_allowed(type) -> None
+
set_allowed(typelist) -> None
+
set_allowed(None) -> None
+
+

The given event types are allowed to appear on the event queue. By default, +all event types can be placed on the queue. It is safe to enable an event +type multiple times.

+

If None is passed as the argument, ALL of the event types are allowed +to be placed on the queue.

+
+ +
+
+pygame.event.get_blocked()¶
+
+
test if a type of event is blocked from the queue
+
get_blocked(type) -> bool
+
get_blocked(typelist) -> bool
+
+

Returns True if the given event type is blocked from the queue. If a +sequence of event types is passed, this will return True if any of those +event types are blocked.

+
+ +
+
+pygame.event.set_grab()¶
+
+
control the sharing of input devices with other applications
+
set_grab(bool) -> None
+
+

When your program runs in a windowed environment, it will share the mouse +and keyboard devices with other applications that have focus. If your +program sets the event grab to True, it will lock all input into your +program.

+

It is best to not always grab the input, since it prevents the user from +doing other things on their system.

+
+ +
+
+pygame.event.get_grab()¶
+
+
test if the program is sharing input devices
+
get_grab() -> bool
+
+

Returns True when the input events are grabbed for this application.

+
+ +
+
+pygame.event.post()¶
+
+
place a new event on the queue
+
post(Event) -> bool
+
+

Places the given event at the end of the event queue.

+

This is usually used for placing custom events on the event queue. +Any type of event can be posted, and the events posted can have any attributes.

+

This returns a boolean on whether the event was posted or not. Blocked events +cannot be posted, and this function returns False if you try to post them.

+
+

Changed in pygame 2.0.1: returns a boolean, previously returned None

+
+
+ +
+
+pygame.event.custom_type()¶
+
+
make custom user event type
+
custom_type() -> int
+
+

Reserves a pygame.USEREVENT for a custom use.

+

If too many events are made a pygame.errorstandard pygame exception is raised.

+
+

New in pygame 2.0.0.dev3.

+
+
+ +
+
+pygame.event.Event()¶
+
+
create a new event object
+
Event(type, dict) -> EventType instance
+
Event(type, **attributes) -> EventType instance
+
+

Creates a new event with the given type and attributes. The attributes can +come from a dictionary argument with string keys or from keyword arguments.

+
+ +
+
+pygame.event.EventType¶
+
+
pygame object for representing events
+
+ +++++ + + + + + + + + + + +
+—event type identifier.
+—event attribute dictionary
+

A pygame object that represents an event. User event instances are created +with an pygame.event.Event()create a new event object function call. The EventType type +is not directly callable. EventType instances support attribute +assignment and deletion.

+
+
+type¶
+
+
event type identifier.
+
type -> int
+
+

Read-only. The event type identifier. For user created event +objects, this is the type argument passed to +pygame.event.Event()create a new event object.

+

For example, some predefined event identifiers are QUIT and +MOUSEMOTION.

+
+ +
+
+__dict__¶
+
+
event attribute dictionary
+
__dict__ -> dict
+
+

Read-only. The event type specific attributes of an event. The +dict attribute is a synonym for backward compatibility.

+

For example, the attributes of a KEYDOWN event would be unicode, +key, and mod

+
+ +
+

New in pygame 1.9.2: Mutable attributes.

+
+
+ +
+ +
+ + +

+
+Edit on GitHub +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/ref/examples.html b/venv/Lib/site-packages/pygame/docs/generated/ref/examples.html new file mode 100644 index 0000000..22322e1 --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/ref/examples.html @@ -0,0 +1,712 @@ + + + + + + + + + pygame.examples — pygame v2.1.2 documentation + + + + + + + + + + + + + +
+ +
+ + + + + +
+
+ +
+
+ +
+
+
+pygame.examples
+
+
module of example programs
+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+—play the full aliens example
+—run a simple starfield example
+—hit the moving chimp
+—display animated objects on the screen
+—run a font rendering example
+—run a FreeType rendering example
+—display a vertical gradient
+—display pygame events
+—show various surfarray effects
+—load and play a sound
+—play various sndarray effects
+—display an animated liquid effect
+—display an animated 3D cube using OpenGL
+—access the clipboard
+—display multiple images bounce off each other using collision detection
+—show lots of sprites moving around
+—write an image file that is smoothscaled copy of an input file
+—demonstrate joystick functionality
+—demonstrate the various surface.fill method blend options
+—uses alternative additive fill to that of surface.fill
+—display two different custom cursors
+—display various pixelarray generated effects
+—interactively scale an image using smoothscale
+—run a midi example
+—run a Surface.scroll example that shows a magnified image
+—display video captured live from an attached camera
+—play an audio file
+

These examples should help get you started with pygame. Here is a brief rundown +of what you get. The source code for these examples is in the public domain. +Feel free to use for your own projects.

+

There are several ways to run the examples. First they can be run as +stand-alone programs. Second they can be imported and their main() methods +called (see below). Finally, the easiest way is to use the python -m option:

+
python -m pygame.examples.<example name> <example arguments>
+
+
+

eg:

+
python -m pygame.examples.scaletest someimage.png
+
+
+

Resources such as images and sounds for the examples are found in the +pygame/examples/data subdirectory.

+

You can find where the example files are installed by using the following +commands inside the python interpreter.

+
>>> import pygame.examples.scaletest
+>>> pygame.examples.scaletest.__file__
+'/usr/lib/python2.6/site-packages/pygame/examples/scaletest.py'
+
+
+

On each OS and version of Python the location will be slightly different. +For example on Windows it might be in 'C:/Python26/Lib/site-packages/pygame/examples/' +On Mac OS X it might be in '/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages/pygame/examples/'

+

You can also run the examples in the python interpreter by calling each modules main() function.

+
>>> import pygame.examples.scaletest
+>>> pygame.examples.scaletest.main()
+
+
+

We're always on the lookout for more examples and/or example requests. Code +like this is probably the best way to start getting involved with python +gaming.

+

examples as a package is new to pygame 1.9.0. But most of the examples came with +pygame much earlier.

+
+
+aliens.main()¶
+
+
play the full aliens example
+
aliens.main() -> None
+
+

This started off as a port of the SDL demonstration, Aliens. Now it has +evolved into something sort of resembling fun. This demonstrates a lot of +different uses of sprites and optimized blitting. Also transparency, +colorkeys, fonts, sound, music, joystick, and more. (PS, my high score is +117! goodluck)

+
+ +
+
+stars.main()¶
+
+
run a simple starfield example
+
stars.main() -> None
+
+

A simple starfield example. You can change the center of perspective by +leftclicking the mouse on the screen.

+
+ +
+
+chimp.main()¶
+
+
hit the moving chimp
+
chimp.main() -> None
+
+

This simple example is derived from the line-by-line tutorial that comes +with pygame. It is based on a 'popular' web banner. Note there are comments +here, but for the full explanation, follow along in the tutorial.

+
+ +
+
+moveit.main()¶
+
+
display animated objects on the screen
+
moveit.main() -> None
+
+

This is the full and final example from the Pygame Tutorial, "How Do I Make +It Move". It creates 10 objects and animates them on the screen.

+

Note it's a bit scant on error checking, but it's easy to read. :] +Fortunately, this is python, and we needn't wrestle with a pile of error +codes.

+
+ +
+
+fonty.main()¶
+
+
run a font rendering example
+
fonty.main() -> None
+
+

Super quick, super simple application demonstrating the different ways to +render fonts with the font module

+
+ +
+
+freetype_misc.main()¶
+
+
run a FreeType rendering example
+
freetype_misc.main() -> None
+
+

A showcase of rendering features the pygame.freetype.FontCreate a new Font instance from a supported font file. +class provides in addition to those available with pygame.font.Fontcreate a new Font object from a file. +It is a demonstration of direct to surface rendering, with vertical text +and rotated text, opaque text and semi transparent text, horizontally +stretched text and vertically stretched text.

+
+ +
+
+vgrade.main()¶
+
+
display a vertical gradient
+
vgrade.main() -> None
+
+

Demonstrates creating a vertical gradient with pixelcopy and NumPy python. +The app will create a new gradient every half second and report the time +needed to create and display the image. If you're not prepared to start +working with the NumPy arrays, don't worry about the source for this one :]

+
+ +
+
+eventlist.main()¶
+
+
display pygame events
+
eventlist.main() -> None
+
+

Eventlist is a sloppy style of pygame, but is a handy tool for learning +about pygame events and input. At the top of the screen are the state of +several device values, and a scrolling list of events are displayed on the +bottom.

+

This is not quality 'ui' code at all, but you can see how to implement very +non-interactive status displays, or even a crude text output control.

+
+ +
+
+arraydemo.main()¶
+
+
show various surfarray effects
+
arraydemo.main(arraytype=None) -> None
+
+

Another example filled with various surfarray effects. It requires the +surfarray and image modules to be installed. This little demo can also make +a good starting point for any of your own tests with surfarray

+

The arraytype parameter is deprecated; passing any value besides 'numpy' +will raise ValueError.

+
+ +
+
+sound.main()¶
+
+
load and play a sound
+
sound.main(file_path=None) -> None
+
+

Extremely basic testing of the mixer module. Load a sound and play it. All +from the command shell, no graphics.

+

If provided, use the audio file 'file_path', otherwise use a default file.

+

sound.py optional command line argument: an audio file

+
+ +
+
+sound_array_demos.main()¶
+
+
play various sndarray effects
+
sound_array_demos.main(arraytype=None) -> None
+
+

Uses sndarray and NumPy to create offset faded copies of the +original sound. Currently it just uses hardcoded values for the number of +echoes and the delay. Easy for you to recreate as needed.

+

The arraytype parameter is deprecated; passing any value besides 'numpy' +will raise ValueError.

+
+ +
+
+liquid.main()¶
+
+
display an animated liquid effect
+
liquid.main() -> None
+
+

This example was created in a quick comparison with the BlitzBasic gaming +language. Nonetheless, it demonstrates a quick 8-bit setup (with colormap).

+
+ +
+
+glcube.main()¶
+
+
display an animated 3D cube using OpenGL
+
glcube.main() -> None
+
+

Using PyOpenGL and pygame, this creates a spinning 3D multicolored cube.

+
+ +
+
+scrap_clipboard.main()¶
+
+
access the clipboard
+
scrap_clipboard.main() -> None
+
+

A simple demonstration example for the clipboard support.

+
+ +
+
+mask.main()¶
+
+
display multiple images bounce off each other using collision detection
+
mask.main(*args) -> None
+
+

Positional arguments:

+
one or more image file names.
+
+
+

This pygame.masks demo will display multiple moving sprites bouncing off +each other. More than one sprite image can be provided.

+

If run as a program then mask.py takes one or more image files as +command line arguments.

+
+ +
+
+testsprite.main()¶
+
+
show lots of sprites moving around
+
testsprite.main(update_rects = True, use_static = False, use_FastRenderGroup = False, screen_dims = [640, 480], use_alpha = False, flags = 0) -> None
+
+

Optional keyword arguments:

+
update_rects - use the RenderUpdate sprite group class
+use_static - include non-moving images
+use_FastRenderGroup - Use the FastRenderGroup sprite group
+screen_dims - pygame window dimensions
+use_alpha - use alpha blending
+flags - additional display mode flags
+
+
+

Like the testsprite.c that comes with SDL, this pygame version shows +lots of sprites moving around.

+

If run as a stand-alone program then no command line arguments are taken.

+
+ +
+
+headless_no_windows_needed.main()¶
+
+
write an image file that is smoothscaled copy of an input file
+
headless_no_windows_needed.main(fin, fout, w, h) -> None
+
+

arguments:

+
fin - name of an input image file
+fout - name of the output file to create/overwrite
+w, h - size of the rescaled image, as integer width and height
+
+
+

How to use pygame with no windowing system, like on headless servers.

+

Thumbnail generation with scaling is an example of what you can do with +pygame.

+

NOTE: the pygame scale function uses MMX/SSE if available, and can be +run in multiple threads.

+

If headless_no_windows_needed.py is run as a program it takes the +following command line arguments:

+
-scale inputimage outputimage new_width new_height
+eg. -scale in.png outpng 50 50
+
+
+
+ +
+
+joystick.main()¶
+
+
demonstrate joystick functionality
+
joystick.main() -> None
+
+

A demo showing full joystick support.

+
+

New in pygame 2.0.2.

+
+
+ +
+
+blend_fill.main()¶
+
+
demonstrate the various surface.fill method blend options
+
blend_fill.main() -> None
+
+

A interactive demo that lets one choose which BLEND_xxx option to apply to a +surface.

+
+ +
+
+blit_blends.main()¶
+
+
uses alternative additive fill to that of surface.fill
+
blit_blends.main() -> None
+
+

Fake additive blending. Using NumPy. it doesn't clamp. Press r,g,b Somewhat +like blend_fill.

+
+ +
+
+cursors.main()¶
+
+
display two different custom cursors
+
cursors.main() -> None
+
+

Display an arrow or circle with crossbar cursor.

+
+ +
+
+pixelarray.main()¶
+
+
display various pixelarray generated effects
+
pixelarray.main() -> None
+
+

Display various pixelarray generated effects.

+
+ +
+
+scaletest.main()¶
+
+
interactively scale an image using smoothscale
+
scaletest.main(imagefile, convert_alpha=False, run_speed_test=True) -> None
+
+

arguments:

+
imagefile - file name of source image (required)
+convert_alpha - use convert_alpha() on the surf (default False)
+run_speed_test - (default False)
+
+
+

A smoothscale example that resized an image on the screen. Vertical and +horizontal arrow keys are used to change the width and height of the +displayed image. If the convert_alpha option is True then the source image +is forced to have source alpha, whether or not the original images does. If +run_speed_test is True then a background timing test is performed instead of +the interactive scaler.

+

If scaletest.py is run as a program then the command line options are:

+
ImageFile [-t] [-convert_alpha]
+[-t] = Run Speed Test
+[-convert_alpha] = Use convert_alpha() on the surf.
+
+
+
+ +
+
+midi.main()¶
+
+
run a midi example
+
midi.main(mode='output', device_id=None) -> None
+
+

Arguments:

+
mode - if 'output' run a midi keyboard output example
+          'input' run a midi event logger input example
+          'list' list available midi devices
+       (default 'output')
+device_id - midi device number; if None then use the default midi input or
+            output device for the system
+
+
+

The output example shows how to translate mouse clicks or computer keyboard +events into midi notes. It implements a rudimentary button widget and state +machine.

+

The input example shows how to translate midi input to pygame events.

+

With the use of a virtual midi patch cord the output and input examples can +be run as separate processes and connected so the keyboard output is +displayed on a console.

+

new to pygame 1.9.0

+
+ +
+
+scroll.main()¶
+
+
run a Surface.scroll example that shows a magnified image
+
scroll.main(image_file=None) -> None
+
+

This example shows a scrollable image that has a zoom factor of eight. It +uses the Surface.scroll() +function to shift the image on the display surface. +A clip rectangle protects a margin area. If called as a function, +the example accepts an optional image file path. If run as a program it +takes an optional file path command line argument. If no file is provided a +default image file is used.

+

When running click on a black triangle to move one pixel in the direction +the triangle points. Or use the arrow keys. Close the window or press +ESC to quit.

+
+ +
+
+camera.main()¶
+
+
display video captured live from an attached camera
+
camera.main() -> None
+
+

A simple live video player, it uses the first available camera it finds on +the system.

+
+ +
+
+playmus.main()¶
+
+
play an audio file
+
playmus.main(file_path) -> None
+
+

A simple music player with window and keyboard playback control. Playback can +be paused and rewound to the beginning.

+
+ +
+ +
+ + +

+
+Edit on GitHub +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/ref/fastevent.html b/venv/Lib/site-packages/pygame/docs/generated/ref/fastevent.html new file mode 100644 index 0000000..c5c8d33 --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/ref/fastevent.html @@ -0,0 +1,286 @@ + + + + + + + + + pygame.fastevent — pygame v2.1.2 documentation + + + + + + + + + + + + + +
+ +
+ + + + + +
+
+ +
+
+ +
+
+
+pygame.fastevent
+
+
pygame module for interacting with events and queues
+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+—initialize pygame.fastevent
+—returns True if the fastevent module is currently initialized
+—internally process pygame event handlers
+—wait for an event
+—get an available event
+—get all events from the queue
+—place an event on the queue
+

IMPORTANT NOTE: THIS MODULE IS DEPRECATED IN PYGAME 2.2

+

In older pygame versions before pygame 2, pygame.eventpygame module for interacting with events and queues was not well +suited for posting events from different threads. This module served as a +replacement (with less features) for multithreaded use. Now, the usage of this +module is highly discouraged in favour of use of the main pygame.eventpygame module for interacting with events and queues +module. This module will be removed in a future pygame version.

+

Below, the legacy docs of the module is provided

+
+
+pygame.fastevent.init()¶
+
+
initialize pygame.fastevent
+
init() -> None
+
+

Initialize the pygame.fastevent module.

+
+ +
+
+pygame.fastevent.get_init()¶
+
+
returns True if the fastevent module is currently initialized
+
get_init() -> bool
+
+

Returns True if the pygame.fastevent module is currently initialized.

+
+ +
+
+pygame.fastevent.pump()¶
+
+
internally process pygame event handlers
+
pump() -> None
+
+

For each frame of your game, you will need to make some sort of call to the +event queue. This ensures your program can internally interact with the rest +of the operating system.

+

This function is not necessary if your program is consistently processing +events on the queue through the other pygame.fasteventpygame module for interacting with events and queues functions.

+

There are important things that must be dealt with internally in the event +queue. The main window may need to be repainted or respond to the system. If +you fail to make a call to the event queue for too long, the system may +decide your program has locked up.

+
+ +
+
+pygame.fastevent.wait()¶
+
+
wait for an event
+
wait() -> Event
+
+

Returns the current event on the queue. If there are no messages +waiting on the queue, this will not return until one is available. +Sometimes it is important to use this wait to get events from the queue, +it will allow your application to idle when the user isn't doing anything +with it.

+
+ +
+
+pygame.fastevent.poll()¶
+
+
get an available event
+
poll() -> Event
+
+

Returns next event on queue. If there is no event waiting on the queue, +this will return an event with type NOEVENT.

+
+ +
+
+pygame.fastevent.get()¶
+
+
get all events from the queue
+
get() -> list of Events
+
+

This will get all the messages and remove them from the queue.

+
+ +
+
+pygame.fastevent.post()¶
+
+
place an event on the queue
+
post(Event) -> None
+
+

This will post your own event objects onto the event queue. You can post +any event type you want, but some care must be taken. For example, if you +post a MOUSEBUTTONDOWN event to the queue, it is likely any code receiving +the event will expect the standard MOUSEBUTTONDOWN attributes to be +available, like 'pos' and 'button'.

+

Because pygame.fastevent.post() may have to wait for the queue to empty, +you can get into a dead lock if you try to append an event on to a full +queue from the thread that processes events. For that reason I do not +recommend using this function in the main thread of an SDL program.

+
+ +
+ +
+ + +

+
+Edit on GitHub +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/ref/font.html b/venv/Lib/site-packages/pygame/docs/generated/ref/font.html new file mode 100644 index 0000000..322a582 --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/ref/font.html @@ -0,0 +1,698 @@ + + + + + + + + + pygame.font — pygame v2.1.2 documentation + + + + + + + + + + + + + +
+ +
+ + + + + +
+
+ +
+
+ +
+
+
+pygame.font
+
+
pygame module for loading and rendering fonts
+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+—initialize the font module
+—uninitialize the font module
+—true if the font module is initialized
+—get the filename of the default font
+—get all available fonts
+—find a specific font on the system
+—create a Font object from the system fonts
+—create a new Font object from a file
+

The font module allows for rendering TrueType fonts into a new Surface object. +It accepts any UCS-2 character ('u0001' to 'uFFFF'). This module is optional +and requires SDL_ttf as a dependency. You should test that pygame.fontpygame module for loading and rendering fonts +is available and initialized before attempting to use the module.

+

Most of the work done with fonts are done by using the actual Font objects. The +module by itself only has routines to initialize the module and create Font +objects with pygame.font.Font().

+

You can load fonts from the system by using the pygame.font.SysFont() +function. There are a few other functions to help lookup the system fonts.

+

Pygame comes with a builtin default font. This can always be accessed by +passing None as the font name.

+

To use the pygame.freetypeEnhanced pygame module for loading and rendering computer fonts based pygame.ftfont as +pygame.fontpygame module for loading and rendering fonts define the environment variable PYGAME_FREETYPE before the +first import of pygamethe top level pygame package. Module pygame.ftfont is a pygame.fontpygame module for loading and rendering fonts +compatible module that passes all but one of the font module unit tests: +it does not have the UCS-2 limitation of the SDL_ttf based font module, so +fails to raise an exception for a code point greater than 'uFFFF'. If +pygame.freetypeEnhanced pygame module for loading and rendering computer fonts is unavailable then the SDL_ttf font module will be +loaded instead.

+
+
+pygame.font.init()¶
+
+
initialize the font module
+
init() -> None
+
+

This method is called automatically by pygame.init(). It initializes the +font module. The module must be initialized before any other functions will +work.

+

It is safe to call this function more than once.

+
+ +
+
+pygame.font.quit()¶
+
+
uninitialize the font module
+
quit() -> None
+
+

Manually uninitialize SDL_ttf's font system. This is called automatically by +pygame.quit().

+

It is safe to call this function even if font is currently not initialized.

+
+ +
+
+pygame.font.get_init()¶
+
+
true if the font module is initialized
+
get_init() -> bool
+
+

Test if the font module is initialized or not.

+
+ +
+
+pygame.font.get_default_font()¶
+
+
get the filename of the default font
+
get_default_font() -> string
+
+

Return the filename of the system font. This is not the full path to the +file. This file can usually be found in the same directory as the font +module, but it can also be bundled in separate archives.

+
+ +
+
+pygame.font.get_fonts()¶
+
+
get all available fonts
+
get_fonts() -> list of strings
+
+

Returns a list of all the fonts available on the system. The names of the +fonts will be set to lowercase with all spaces and punctuation removed. This +works on most systems, but some will return an empty list if they cannot +find fonts.

+
+ +
+
+pygame.font.match_font()¶
+
+
find a specific font on the system
+
match_font(name, bold=False, italic=False) -> path
+
+

Returns the full path to a font file on the system. If bold or italic are +set to true, this will attempt to find the correct family of font.

+

The font name can also be an iterable of font names, a string of +comma-separated font names, or a bytes of comma-separated font names, in +which case the set of names will be searched in order. +If none of the given names are found, None is returned.

+
+

New in pygame 2.0.1: Accept an iterable of font names.

+
+

Example:

+
print pygame.font.match_font('bitstreamverasans')
+# output is: /usr/share/fonts/truetype/ttf-bitstream-vera/Vera.ttf
+# (but only if you have Vera on your system)
+
+
+
+ +
+
+pygame.font.SysFont()¶
+
+
create a Font object from the system fonts
+
SysFont(name, size, bold=False, italic=False) -> Font
+
+

Return a new Font object that is loaded from the system fonts. The font will +match the requested bold and italic flags. Pygame uses a small set of common +font aliases. If the specific font you ask for is not available, a reasonable +alternative may be used. If a suitable system font is not found this will +fall back on loading the default pygame font.

+

The font name can also be an iterable of font names, a string of +comma-separated font names, or a bytes of comma-separated font names, in +which case the set of names will be searched in order.

+
+

New in pygame 2.0.1: Accept an iterable of font names.

+
+
+ +
+
+pygame.font.Font¶
+
+
create a new Font object from a file
+
Font(filename, size) -> Font
+
Font(pathlib.Path, size) -> Font
+
Font(object, size) -> Font
+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+—Gets or sets whether the font should be rendered in (faked) bold.
+—Gets or sets whether the font should be rendered in (faked) italics.
+—Gets or sets whether the font should be rendered with an underline.
+—draw text on a new Surface
+—determine the amount of space needed to render text
+—control if text is rendered with an underline
+—check if text will be rendered with an underline
+—enable fake rendering of bold text
+—check if text will be rendered bold
+—enable fake rendering of italic text
+—gets the metrics for each character in the passed string
+—check if the text will be rendered italic
+—get the line space of the font text
+—get the height of the font
+—get the ascent of the font
+—get the descent of the font
+

Load a new font from a given filename or a python file object. The size is +the height of the font in pixels. If the filename is None the pygame default +font will be loaded. If a font cannot be loaded from the arguments given an +exception will be raised. Once the font is created the size cannot be +changed.

+

Font objects are mainly used to render text into new Surface objects. The +render can emulate bold or italic features, but it is better to load from a +font with actual italic or bold glyphs. The rendered text can be regular +strings or unicode.

+
+
+bold¶
+
+
Gets or sets whether the font should be rendered in (faked) bold.
+
bold -> bool
+
+

Whether the font should be rendered in bold.

+

When set to True, this enables the bold rendering of text. This +is a fake stretching of the font that doesn't look good on many +font types. If possible load the font from a real bold font +file. While bold, the font will have a different width than when +normal. This can be mixed with the italic and underline modes.

+
+

New in pygame 2.0.0.

+
+
+ +
+
+italic¶
+
+
Gets or sets whether the font should be rendered in (faked) italics.
+
italic -> bool
+
+

Whether the font should be rendered in italic.

+

When set to True, this enables fake rendering of italic +text. This is a fake skewing of the font that doesn't look good +on many font types. If possible load the font from a real italic +font file. While italic the font will have a different width +than when normal. This can be mixed with the bold and underline +modes.

+
+

New in pygame 2.0.0.

+
+
+ +
+
+underline¶
+
+
Gets or sets whether the font should be rendered with an underline.
+
underline -> bool
+
+

Whether the font should be rendered in underline.

+

When set to True, all rendered fonts will include an +underline. The underline is always one pixel thick, regardless +of font size. This can be mixed with the bold and italic modes.

+
+

New in pygame 2.0.0.

+
+
+ +
+
+render()¶
+
+
draw text on a new Surface
+
render(text, antialias, color, background=None) -> Surface
+
+

This creates a new Surface with the specified text rendered on it. pygame +provides no way to directly draw text on an existing Surface: instead you +must use Font.render() to create an image (Surface) of the text, then +blit this image onto another Surface.

+

The text can only be a single line: newline characters are not rendered. +Null characters ('x00') raise a TypeError. Both Unicode and char (byte) +strings are accepted. For Unicode strings only UCS-2 characters +('u0001' to 'uFFFF') were previously supported and any greater unicode +codepoint would raise a UnicodeError. Now, characters in the UCS-4 range +are supported. For char strings a LATIN1 encoding is assumed. The +antialias argument is a boolean: if true the characters will have smooth +edges. The color argument is the color of the text +[e.g.: (0,0,255) for blue]. The optional background argument is a color +to use for the text background. If no background is passed the area +outside the text will be transparent.

+

The Surface returned will be of the dimensions required to hold the text. +(the same as those returned by Font.size()). If an empty string is passed +for the text, a blank surface will be returned that is zero pixel wide and +the height of the font.

+

Depending on the type of background and antialiasing used, this returns +different types of Surfaces. For performance reasons, it is good to know +what type of image will be used. If antialiasing is not used, the return +image will always be an 8-bit image with a two-color palette. If the +background is transparent a colorkey will be set. Antialiased images are +rendered to 24-bit RGB images. If the background is transparent a +pixel alpha will be included.

+

Optimization: if you know that the final destination for the text (on the +screen) will always have a solid background, and the text is antialiased, +you can improve performance by specifying the background color. This will +cause the resulting image to maintain transparency information by +colorkey rather than (much less efficient) alpha values.

+

If you render '\n' an unknown char will be rendered. Usually a +rectangle. Instead you need to handle new lines yourself.

+

Font rendering is not thread safe: only a single thread can render text +at any time.

+
+

Changed in pygame 2.0.3: Rendering UCS_4 unicode works and does not +raise an exception. Use if hasattr(pygame.font, 'UCS_4'): to see if +pygame supports rendering UCS_4 unicode including more languages and +emoji.

+
+
+ +
+
+size()¶
+
+
determine the amount of space needed to render text
+
size(text) -> (width, height)
+
+

Returns the dimensions needed to render the text. This can be used to +help determine the positioning needed for text before it is rendered. It +can also be used for wordwrapping and other layout effects.

+

Be aware that most fonts use kerning which adjusts the widths for +specific letter pairs. For example, the width for "ae" will not always +match the width for "a" + "e".

+
+ +
+
+set_underline()¶
+
+
control if text is rendered with an underline
+
set_underline(bool) -> None
+
+

When enabled, all rendered fonts will include an underline. The underline +is always one pixel thick, regardless of font size. This can be mixed +with the bold and italic modes.

+
+

Note

+

This is the same as the underline attribute.

+
+
+ +
+
+get_underline()¶
+
+
check if text will be rendered with an underline
+
get_underline() -> bool
+
+

Return True when the font underline is enabled.

+
+
+

Note

+

This is the same as the underline attribute.

+
+
+
+ +
+
+set_bold()¶
+
+
enable fake rendering of bold text
+
set_bold(bool) -> None
+
+

Enables the bold rendering of text. This is a fake stretching of the font +that doesn't look good on many font types. If possible load the font from +a real bold font file. While bold, the font will have a different width +than when normal. This can be mixed with the italic and underline modes.

+
+

Note

+

This is the same as the bold attribute.

+
+
+ +
+
+get_bold()¶
+
+
check if text will be rendered bold
+
get_bold() -> bool
+
+

Return True when the font bold rendering mode is enabled.

+
+

Note

+

This is the same as the bold attribute.

+
+
+ +
+
+set_italic()¶
+
+
enable fake rendering of italic text
+
set_italic(bool) -> None
+
+

Enables fake rendering of italic text. This is a fake skewing of the font +that doesn't look good on many font types. If possible load the font from +a real italic font file. While italic the font will have a different +width than when normal. This can be mixed with the bold and underline +modes.

+
+

Note

+

This is the same as the italic attribute.

+
+
+ +
+
+metrics()¶
+
+
gets the metrics for each character in the passed string
+
metrics(text) -> list
+
+

The list contains tuples for each character, which contain the minimum +X offset, the maximum X offset, the minimum Y offset, the +maximum Y offset and the advance offset (bearing plus width) of the +character. [(minx, maxx, miny, maxy, advance), (minx, maxx, miny, maxy, +advance), ...]. None is entered in the list for each unrecognized +character.

+
+ +
+
+get_italic()¶
+
+
check if the text will be rendered italic
+
get_italic() -> bool
+
+

Return True when the font italic rendering mode is enabled.

+
+

Note

+

This is the same as the italic attribute.

+
+
+ +
+
+get_linesize()¶
+
+
get the line space of the font text
+
get_linesize() -> int
+
+

Return the height in pixels for a line of text with the font. When +rendering multiple lines of text this is the recommended amount of space +between lines.

+
+ +
+
+get_height()¶
+
+
get the height of the font
+
get_height() -> int
+
+

Return the height in pixels of the actual rendered text. This is the +average size for each glyph in the font.

+
+ +
+
+get_ascent()¶
+
+
get the ascent of the font
+
get_ascent() -> int
+
+

Return the height in pixels for the font ascent. The ascent is the number +of pixels from the font baseline to the top of the font.

+
+ +
+
+get_descent()¶
+
+
get the descent of the font
+
get_descent() -> int
+
+

Return the height in pixels for the font descent. The descent is the +number of pixels from the font baseline to the bottom of the font.

+
+ +
+ +
+ +
+ + +

+
+Edit on GitHub +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/ref/freetype.html b/venv/Lib/site-packages/pygame/docs/generated/ref/freetype.html new file mode 100644 index 0000000..8c293e8 --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/ref/freetype.html @@ -0,0 +1,1270 @@ + + + + + + + + + pygame.freetype — pygame v2.1.2 documentation + + + + + + + + + + + + + +
+ +
+ + + + + +
+
+ +
+
+ +
+
+
+pygame.freetype
+
+
Enhanced pygame module for loading and rendering computer fonts
+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+—Return the latest FreeType error
+—Return the FreeType version
+—Initialize the underlying FreeType library.
+—Shut down the underlying FreeType library.
+—Returns True if the FreeType module is currently initialized.
+—DEPRECATED: Use get_init() instead.
+—Return the glyph case size
+—Return the default pixel size in dots per inch
+—Set the default pixel size in dots per inch for the module
+—create a Font object from the system fonts
+—Get the filename of the default font
+—Create a new Font instance from a supported font file.
+

The pygame.freetype module is a replacement for pygame.fontpygame module for loading and rendering fonts. +It has all of the functionality of the original, plus many new features. +Yet is has absolutely no dependencies on the SDL_ttf library. +It is implemented directly on the FreeType 2 library. +The pygame.freetype module is not itself backward compatible with +pygame.fontpygame module for loading and rendering fonts. +Instead, use the pygame.ftfont module as a drop-in replacement +for pygame.fontpygame module for loading and rendering fonts.

+

All font file formats supported by FreeType can be rendered by +pygame.freetype, namely TTF, Type1, CFF, OpenType, +SFNT, PCF, FNT, BDF, PFR and Type42 fonts. +All glyphs having UTF-32 code points are accessible +(see Font.ucs4).

+

Most work on fonts is done using Font instances. +The module itself only has routines for initialization and creation +of Font objects. +You can load fonts from the system using the SysFont() function.

+

Extra support of bitmap fonts is available. Available bitmap sizes can +be listed (see Font.get_sizes()). For bitmap only fonts Font +can set the size for you (see the Font.size property).

+

For now undefined character codes are replaced with the .notdef +(not defined) character. +How undefined codes are handled may become configurable in a future release.

+

Pygame comes with a built-in default font. This can always be accessed by +passing None as the font name to the Font constructor.

+

Extra rendering features available to pygame.freetype.FontCreate a new Font instance from a supported font file. +are direct to surface rendering (see Font.render_to()), character kerning +(see Font.kerning), vertical layout (see Font.vertical), +rotation of rendered text (see Font.rotation), +and the strong style (see Font.strong). +Some properties are configurable, such as +strong style strength (see Font.strength) and underline positioning +(see Font.underline_adjustment). Text can be positioned by the upper +right corner of the text box or by the text baseline (see Font.origin). +Finally, a font's vertical and horizontal size can be adjusted separately +(see Font.size). +The pygame.examples.freetype_misc +example shows these features in use.

+

The pygame package does not import freetype automatically when +loaded. This module must be imported explicitly to be used.

+
import pygame
+import pygame.freetype
+
+
+
+

New in pygame 1.9.2: freetype

+
+
+
+pygame.freetype.get_error()¶
+
+
Return the latest FreeType error
+
get_error() -> str
+
get_error() -> None
+
+

Return a description of the last error which occurred in the FreeType2 +library, or None if no errors have occurred.

+
+ +
+
+pygame.freetype.get_version()¶
+
+
Return the FreeType version
+
get_version() -> (int, int, int)
+
+

Returns the version of the FreeType library in use by this module.

+

Note that the freetype module depends on the FreeType 2 library. +It will not compile with the original FreeType 1.0. Hence, the first element +of the tuple will always be "2".

+
+ +
+
+pygame.freetype.init()¶
+
+
Initialize the underlying FreeType library.
+
init(cache_size=64, resolution=72) -> None
+
+

This function initializes the underlying FreeType library and must be +called before trying to use any of the functionality of the freetype +module.

+

However, pygame.init()initialize all imported pygame modules will automatically call this function +if the freetype module is already imported. It is safe to call this +function more than once.

+

Optionally, you may specify a default cache_size for the Glyph cache: the +maximum number of glyphs that will be cached at any given time by the +module. Exceedingly small values will be automatically tuned for +performance. Also a default pixel resolution, in dots per inch, can +be given to adjust font scaling.

+
+ +
+
+pygame.freetype.quit()¶
+
+
Shut down the underlying FreeType library.
+
quit() -> None
+
+

This function closes the freetype module. After calling this +function, you should not invoke any class, method or function related to the +freetype module as they are likely to fail or might give unpredictable +results. It is safe to call this function even if the module hasn't been +initialized yet.

+
+ +
+
+pygame.freetype.get_init()¶
+
+
Returns True if the FreeType module is currently initialized.
+
get_init() -> bool
+
+

Returns True if the pygame.freetype module is currently initialized.

+
+

New in pygame 1.9.5.

+
+
+ +
+
+pygame.freetype.was_init()¶
+
+
DEPRECATED: Use get_init() instead.
+
was_init() -> bool
+
+

DEPRECATED: Returns True if the pygame.freetype module is currently +initialized. Use get_init() instead.

+
+ +
+
+pygame.freetype.get_cache_size()¶
+
+
Return the glyph case size
+
get_cache_size() -> long
+
+

See pygame.freetype.init()Initialize the underlying FreeType library..

+
+ +
+
+pygame.freetype.get_default_resolution()¶
+
+
Return the default pixel size in dots per inch
+
get_default_resolution() -> long
+
+

Returns the default pixel size, in dots per inch, for the module. +The default is 72 DPI.

+
+ +
+
+pygame.freetype.set_default_resolution()¶
+
+
Set the default pixel size in dots per inch for the module
+
set_default_resolution([resolution])
+
+

Set the default pixel size, in dots per inch, for the module. If the +optional argument is omitted or zero the resolution is reset to 72 DPI.

+
+ +
+
+pygame.freetype.SysFont()¶
+
+
create a Font object from the system fonts
+
SysFont(name, size, bold=False, italic=False) -> Font
+
+

Return a new Font object that is loaded from the system fonts. The font will +match the requested bold and italic flags. Pygame uses a small set of +common font aliases. If the specific font you ask for is not available, a +reasonable alternative may be used. If a suitable system font is not found +this will fall back on loading the default pygame font.

+

The font name can also be an iterable of font names, a string of +comma-separated font names, or a bytes of comma-separated font names, in +which case the set of names will be searched in order.

+
+

New in pygame 2.0.1: Accept an iterable of font names.

+
+
+ +
+
+pygame.freetype.get_default_font()¶
+
+
Get the filename of the default font
+
get_default_font() -> string
+
+

Return the filename of the default pygame font. This is not the full path +to the file. The file is usually in the same directory as the font module, +but can also be bundled in a separate archive.

+
+ +
+
+pygame.freetype.Font¶
+
+
Create a new Font instance from a supported font file.
+
Font(file, size=0, font_index=0, resolution=0, ucs4=False) -> Font
+
Font(pathlib.Path) -> Font
+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+—Proper font name.
+—Font file path
+—The default point size used in rendering
+—Return the size and offset of rendered text
+—Return the glyph metrics for the given text
+—The unscaled height of the font in font units
+—The unscaled ascent of the font in font units
+—The unscaled descent of the font in font units
+—The scaled ascent of the font in pixels
+—The scaled descent of the font in pixels
+—The scaled height of the font in pixels
+—The scaled bounding box height of the font in pixels
+—return the available sizes of embedded bitmaps
+—Return rendered text as a surface
+—Render text onto an existing surface
+—Return rendered text as a string of bytes
+—Render text into an array of ints
+—The font's style flags
+—The state of the font's underline style flag
+—The state of the font's strong style flag
+—The state of the font's oblique style flag
+—The state of the font's wide style flag
+—The strength associated with the strong or wide font styles
+—Adjustment factor for the underline position
+—Gets whether the font is fixed-width
+—the number of available bitmap sizes for the font
+—Gets whether the font is scalable
+—allow the use of embedded bitmaps in an outline font file
+—Font anti-aliasing mode
+—Character kerning mode
+—Font vertical mode
+—text rotation in degrees counterclockwise
+—default foreground color
+—default background color
+—Font render to text origin mode
+—padded boundary mode
+—Enable UCS-4 mode
+—Pixel resolution in dots per inch
+

Argument file can be either a string representing the font's filename, a +file-like object containing the font, or None; if None, a default, +Pygame, font is used.

+

Optionally, a size argument may be specified to set the default size in +points, which determines the size of the rendered characters. +The size can also be passed explicitly to each method call. +Because of the way the caching system works, specifying a default size on +the constructor doesn't imply a performance gain over manually passing +the size on each function call. If the font is bitmap and no size +is given, the default size is set to the first available size for the font.

+

If the font file has more than one font, the font to load can be chosen with +the index argument. An exception is raised for an out-of-range font index +value.

+

The optional resolution argument sets the pixel size, in dots per inch, +for use in scaling glyphs for this Font instance. If 0 then the default +module value, set by init(), is used. The Font object's +resolution can only be changed by re-initializing the Font instance.

+

The optional ucs4 argument, an integer, sets the default text translation +mode: 0 (False) recognize UTF-16 surrogate pairs, any other value (True), +to treat Unicode text as UCS-4, with no surrogate pairs. See +Font.ucs4.

+
+
+name¶
+
+
Proper font name.
+
name -> string
+
+

Read only. Returns the real (long) name of the font, as +recorded in the font file.

+
+ +
+
+path¶
+
+
Font file path
+
path -> unicode
+
+

Read only. Returns the path of the loaded font file

+
+ +
+
+size¶
+
+
The default point size used in rendering
+
size -> float
+
size -> (float, float)
+
+

Get or set the default size for text metrics and rendering. It can be +a single point size, given as a Python int or float, or a +font ppem (width, height) tuple. Size values are non-negative. +A zero size or width represents an undefined size. In this case +the size must be given as a method argument, or an exception is +raised. A zero width but non-zero height is a ValueError.

+

For a scalable font, a single number value is equivalent to a tuple +with width equal height. A font can be stretched vertically with +height set greater than width, or horizontally with width set +greater than height. For embedded bitmaps, as listed by get_sizes(), +use the nominal width and height to select an available size.

+

Font size differs for a non-scalable, bitmap, font. During a +method call it must match one of the available sizes returned by +method get_sizes(). If not, an exception is raised. +If the size is a single number, the size is first matched against the +point size value. If no match, then the available size with the +same nominal width and height is chosen.

+
+ +
+
+get_rect()¶
+
+
Return the size and offset of rendered text
+
get_rect(text, style=STYLE_DEFAULT, rotation=0, size=0) -> rect
+
+

Gets the final dimensions and origin, in pixels, of text using the +optional size in points, style, and rotation. For other +relevant render properties, and for any optional argument not given, +the default values set for the Font instance are used.

+

Returns a Rect instance containing the +width and height of the text's bounding box and the position of the +text's origin. +The origin is useful in aligning separately rendered pieces of text. +It gives the baseline position and bearing at the start of the text. +See the render_to() method for an example.

+

If text is a char (byte) string, its encoding is assumed to be +LATIN1.

+

Optionally, text can be None, which will return the bounding +rectangle for the text passed to a previous get_rect(), +render(), render_to(), render_raw(), or +render_raw_to() call. See render_to() for more +details.

+
+ +
+
+get_metrics()¶
+
+
Return the glyph metrics for the given text
+
get_metrics(text, size=0) -> [(...), ...]
+
+

Returns the glyph metrics for each character in text.

+

The glyph metrics are returned as a list of tuples. Each tuple gives +metrics of a single character glyph. The glyph metrics are:

+
(min_x, max_x, min_y, max_y, horizontal_advance_x, horizontal_advance_y)
+
+
+

The bounding box min_x, max_x, min_y, and max_y values are returned as +grid-fitted pixel coordinates of type int. The advance values are +float values.

+

The calculations are done using the font's default size in points. +Optionally you may specify another point size with the size argument.

+

The metrics are adjusted for the current rotation, strong, and oblique +settings.

+

If text is a char (byte) string, then its encoding is assumed to be +LATIN1.

+
+ +
+
+height¶
+
+
The unscaled height of the font in font units
+
height -> int
+
+

Read only. Gets the height of the font. This is the average value of all +glyphs in the font.

+
+ +
+
+ascender¶
+
+
The unscaled ascent of the font in font units
+
ascender -> int
+
+

Read only. Return the number of units from the font's baseline to +the top of the bounding box.

+
+ +
+
+descender¶
+
+
The unscaled descent of the font in font units
+
descender -> int
+
+

Read only. Return the height in font units for the font descent. +The descent is the number of units from the font's baseline to the +bottom of the bounding box.

+
+ +
+
+get_sized_ascender()¶
+
+
The scaled ascent of the font in pixels
+
get_sized_ascender(<size>=0) -> int
+
+

Return the number of units from the font's baseline to the top of the +bounding box. It is not adjusted for strong or rotation.

+
+ +
+
+get_sized_descender()¶
+
+
The scaled descent of the font in pixels
+
get_sized_descender(<size>=0) -> int
+
+

Return the number of pixels from the font's baseline to the top of the +bounding box. It is not adjusted for strong or rotation.

+
+ +
+
+get_sized_height()¶
+
+
The scaled height of the font in pixels
+
get_sized_height(<size>=0) -> int
+
+

Returns the height of the font. This is the average value of all +glyphs in the font. It is not adjusted for strong or rotation.

+
+ +
+
+get_sized_glyph_height()¶
+
+
The scaled bounding box height of the font in pixels
+
get_sized_glyph_height(<size>=0) -> int
+
+

Return the glyph bounding box height of the font in pixels. +This is the average value of all glyphs in the font. +It is not adjusted for strong or rotation.

+
+ +
+
+get_sizes()¶
+
+
return the available sizes of embedded bitmaps
+
get_sizes() -> [(int, int, int, float, float), ...]
+
get_sizes() -> []
+
+

Returns a list of tuple records, one for each point size +supported. Each tuple containing the point size, the height in pixels, +width in pixels, horizontal ppem (nominal width) in fractional pixels, +and vertical ppem (nominal height) in fractional pixels.

+
+ +
+
+render()¶
+
+
Return rendered text as a surface
+
render(text, fgcolor=None, bgcolor=None, style=STYLE_DEFAULT, rotation=0, size=0) -> (Surface, Rect)
+
+

Returns a new Surface, +with the text rendered to it +in the color given by 'fgcolor'. If no foreground color is given, +the default foreground color, fgcolor is used. +If bgcolor is given, the surface +will be filled with this color. When no background color is given, +the surface background is transparent, zero alpha. Normally the returned +surface has a 32 bit pixel size. However, if bgcolor is None +and anti-aliasing is disabled a monochrome 8 bit colorkey surface, +with colorkey set for the background color, is returned.

+

The return value is a tuple: the new surface and the bounding +rectangle giving the size and origin of the rendered text.

+

If an empty string is passed for text then the returned Rect is zero +width and the height of the font.

+

Optional fgcolor, style, rotation, and size arguments override +the default values set for the Font instance.

+

If text is a char (byte) string, then its encoding is assumed to be +LATIN1.

+

Optionally, text can be None, which will render the text +passed to a previous get_rect(), render(), render_to(), +render_raw(), or render_raw_to() call. +See render_to() for details.

+
+ +
+
+render_to()¶
+
+
Render text onto an existing surface
+
render_to(surf, dest, text, fgcolor=None, bgcolor=None, style=STYLE_DEFAULT, rotation=0, size=0) -> Rect
+
+

Renders the string text to the pygame.Surfacepygame object for representing images surf, +at position dest, a (x, y) surface coordinate pair. +If either x or y is not an integer it is converted to one if possible. +Any sequence where the first two items are x and y positional elements +is accepted, including a Rect instance. +As with render(), +optional fgcolor, style, rotation, and size argument are +available.

+

If a background color bgcolor is given, the text bounding box is +first filled with that color. The text is blitted next. +Both the background fill and text rendering involve full alpha blits. +That is, the alpha values of the foreground, background, and destination +target surface all affect the blit.

+

The return value is a rectangle giving the size and position of the +rendered text within the surface.

+

If an empty string is passed for text then the returned +Rect is zero width and the height of the font. +The rect will test False.

+

Optionally, text can be set None, which will re-render text +passed to a previous render_to(), get_rect(), render(), +render_raw(), or render_raw_to() call. Primarily, this +feature is an aid to using render_to() in combination with +get_rect(). An example:

+
def word_wrap(surf, text, font, color=(0, 0, 0)):
+    font.origin = True
+    words = text.split(' ')
+    width, height = surf.get_size()
+    line_spacing = font.get_sized_height() + 2
+    x, y = 0, line_spacing
+    space = font.get_rect(' ')
+    for word in words:
+        bounds = font.get_rect(word)
+        if x + bounds.width + bounds.x >= width:
+            x, y = 0, y + line_spacing
+        if x + bounds.width + bounds.x >= width:
+            raise ValueError("word too wide for the surface")
+        if y + bounds.height - bounds.y >= height:
+            raise ValueError("text to long for the surface")
+        font.render_to(surf, (x, y), None, color)
+        x += bounds.width + space.width
+    return x, y
+
+
+

When render_to() is called with the same +font properties ― size, style, strength, +wide, antialiased, vertical, rotation, +kerning, and use_bitmap_strikes ― as get_rect(), +render_to() will use the layout calculated by get_rect(). +Otherwise, render_to() will recalculate the layout if called +with a text string or one of the above properties has changed +after the get_rect() call.

+

If text is a char (byte) string, then its encoding is assumed to be +LATIN1.

+
+ +
+
+render_raw()¶
+
+
Return rendered text as a string of bytes
+
render_raw(text, style=STYLE_DEFAULT, rotation=0, size=0, invert=False) -> (bytes, (int, int))
+
+

Like render() but with the pixels returned as a byte string +of 8-bit gray-scale values. The foreground color is 255, the +background 0, useful as an alpha mask for a foreground pattern.

+
+ +
+
+render_raw_to()¶
+
+
Render text into an array of ints
+
render_raw_to(array, text, dest=None, style=STYLE_DEFAULT, rotation=0, size=0, invert=False) -> Rect
+
+

Render to an array object exposing an array struct interface. The array +must be two dimensional with integer items. The default dest value, +None, is equivalent to position (0, 0). See render_to(). +As with the other render methods, text can be None to +render a text string passed previously to another method.

+

The return value is a pygame.Rect()pygame object for storing rectangular coordinates giving the size and position of +the rendered text.

+
+ +
+
+style¶
+
+
The font's style flags
+
style -> int
+
+

Gets or sets the default style of the Font. This default style will be +used for all text rendering and size calculations unless overridden +specifically a render or get_rect() call. +The style value may be a bit-wise OR of one or more of the following +constants:

+
STYLE_NORMAL
+STYLE_UNDERLINE
+STYLE_OBLIQUE
+STYLE_STRONG
+STYLE_WIDE
+STYLE_DEFAULT
+
+
+

These constants may be found on the FreeType constants module. +Optionally, the default style can be modified or obtained accessing the +individual style attributes (underline, oblique, strong).

+

The STYLE_OBLIQUE and STYLE_STRONG styles are for +scalable fonts only. An attempt to set either for a bitmap font raises +an AttributeError. An attempt to set either for an inactive font, +as returned by Font.__new__(), raises a RuntimeError.

+

Assigning STYLE_DEFAULT to the style property leaves +the property unchanged, as this property defines the default. +The style property will never return STYLE_DEFAULT.

+
+ +
+
+underline¶
+
+
The state of the font's underline style flag
+
underline -> bool
+
+

Gets or sets whether the font will be underlined when drawing text. This +default style value will be used for all text rendering and size +calculations unless overridden specifically in a render or +get_rect() call, via the 'style' parameter.

+
+ +
+
+strong¶
+
+
The state of the font's strong style flag
+
strong -> bool
+
+

Gets or sets whether the font will be bold when drawing text. This +default style value will be used for all text rendering and size +calculations unless overridden specifically in a render or +get_rect() call, via the 'style' parameter.

+
+ +
+
+oblique¶
+
+
The state of the font's oblique style flag
+
oblique -> bool
+
+

Gets or sets whether the font will be rendered as oblique. This +default style value will be used for all text rendering and size +calculations unless overridden specifically in a render or +get_rect() call, via the style parameter.

+

The oblique style is only supported for scalable (outline) fonts. +An attempt to set this style on a bitmap font will raise an +AttributeError. If the font object is inactive, as returned by +Font.__new__(), setting this property raises a RuntimeError.

+
+ +
+
+wide¶
+
+
The state of the font's wide style flag
+
wide -> bool
+
+

Gets or sets whether the font will be stretched horizontally +when drawing text. It produces a result similar to +pygame.font.Fontcreate a new Font object from a file's bold. This style not available for +rotated text.

+
+ +
+
+strength¶
+
+
The strength associated with the strong or wide font styles
+
strength -> float
+
+

The amount by which a font glyph's size is enlarged for the +strong or wide transformations, as a fraction of the untransformed +size. For the wide style only the horizontal dimension is +increased. For strong text both the horizontal and vertical +dimensions are enlarged. A wide style of strength 0.08333 ( 1/12 ) is +equivalent to the pygame.font.Fontcreate a new Font object from a file bold style. +The default is 0.02778 ( 1/36 ).

+

The strength style is only supported for scalable (outline) fonts. +An attempt to set this property on a bitmap font will raise an +AttributeError. If the font object is inactive, as returned by +Font.__new__(), assignment to this property raises a RuntimeError.

+
+ +
+
+underline_adjustment¶
+
+
Adjustment factor for the underline position
+
underline_adjustment -> float
+
+

Gets or sets a factor which, when positive, is multiplied with the +font's underline offset to adjust the underline position. A negative +value turns an underline into a strike-through or overline. It is +multiplied with the ascender. Accepted values range between -2.0 and 2.0 +inclusive. A value of 0.5 closely matches Tango underlining. A value of +1.0 mimics pygame.font.Fontcreate a new Font object from a file underlining.

+
+ +
+
+fixed_width¶
+
+
Gets whether the font is fixed-width
+
fixed_width -> bool
+
+

Read only. Returns True if the font contains fixed-width +characters (for example Courier, Bitstream Vera Sans Mono, Andale Mono).

+
+ +
+
+fixed_sizes¶
+
+
the number of available bitmap sizes for the font
+
fixed_sizes -> int
+
+

Read only. Returns the number of point sizes for which the font contains +bitmap character images. If zero then the font is not a bitmap font. +A scalable font may contain pre-rendered point sizes as strikes.

+
+ +
+
+scalable¶
+
+
Gets whether the font is scalable
+
scalable -> bool
+
+

Read only. Returns True if the font contains outline glyphs. +If so, the point size is not limited to available bitmap sizes.

+
+ +
+
+use_bitmap_strikes¶
+
+
allow the use of embedded bitmaps in an outline font file
+
use_bitmap_strikes -> bool
+
+

Some scalable fonts include embedded bitmaps for particular point +sizes. This property controls whether or not those bitmap strikes +are used. Set it False to disable the loading of any bitmap +strike. Set it True, the default, to permit bitmap strikes +for a non-rotated render with no style other than wide or +underline. This property is ignored for bitmap fonts.

+

See also fixed_sizes and get_sizes().

+
+ +
+
+antialiased¶
+
+
Font anti-aliasing mode
+
antialiased -> bool
+
+

Gets or sets the font's anti-aliasing mode. This defaults to +True on all fonts, which are rendered with full 8 bit blending.

+

Set to False to do monochrome rendering. This should +provide a small speed gain and reduce cache memory size.

+
+ +
+
+kerning¶
+
+
Character kerning mode
+
kerning -> bool
+
+

Gets or sets the font's kerning mode. This defaults to False +on all fonts, which will be rendered without kerning.

+

Set to True to add kerning between character pairs, if supported +by the font, when positioning glyphs.

+
+ +
+
+vertical¶
+
+
Font vertical mode
+
vertical -> bool
+
+

Gets or sets whether the characters are laid out vertically rather +than horizontally. May be useful when rendering Kanji or some other +vertical script.

+

Set to True to switch to a vertical text layout. The default +is False, place horizontally.

+

Note that the Font class does not automatically determine +script orientation. Vertical layout must be selected explicitly.

+

Also note that several font formats (especially bitmap based ones) don't +contain the necessary metrics to draw glyphs vertically, so drawing in +those cases will give unspecified results.

+
+ +
+
+rotation¶
+
+
text rotation in degrees counterclockwise
+
rotation -> int
+
+

Gets or sets the baseline angle of the rendered text. The angle is +represented as integer degrees. The default angle is 0, with horizontal +text rendered along the X-axis, and vertical text along the Y-axis. +A positive value rotates these axes counterclockwise that many degrees. +A negative angle corresponds to a clockwise rotation. The rotation +value is normalized to a value within the range 0 to 359 inclusive +(eg. 390 -> 390 - 360 -> 30, -45 -> 360 + -45 -> 315, +720 -> 720 - (2 * 360) -> 0).

+

Only scalable (outline) fonts can be rotated. An attempt to change +the rotation of a bitmap font raises an AttributeError. +An attempt to change the rotation of an inactive font instance, as +returned by Font.__new__(), raises a RuntimeError.

+
+ +
+
+fgcolor¶
+
+
default foreground color
+
fgcolor -> Color
+
+

Gets or sets the default glyph rendering color. It is initially opaque +black ― (0, 0, 0, 255). Applies to render() and render_to().

+
+ +
+
+bgcolor¶
+
+
default background color
+
bgcolor -> Color
+
+

Gets or sets the default background rendering color. Initially it is +unset and text will render with a transparent background by default. +Applies to render() and render_to().

+
+ +
+

New in pygame 2.0.0.

+
+
+
+origin¶
+
+
Font render to text origin mode
+
origin -> bool
+
+

If set True, render_to() and render_raw_to() will +take the dest position to be that of the text origin, as opposed to +the top-left corner of the bounding box. See get_rect() for +details.

+
+ +
+
+pad¶
+
+
padded boundary mode
+
pad -> bool
+
+

If set True, then the text boundary rectangle will be inflated +to match that of font.Font. +Otherwise, the boundary rectangle is just large enough for the text.

+
+ +
+
+ucs4¶
+
+
Enable UCS-4 mode
+
ucs4 -> bool
+
+

Gets or sets the decoding of Unicode text. By default, the +freetype module performs UTF-16 surrogate pair decoding on Unicode text. +This allows 32-bit escape sequences ('Uxxxxxxxx') between 0x10000 and +0x10FFFF to represent their corresponding UTF-32 code points on Python +interpreters built with a UCS-2 Unicode type (on Windows, for instance). +It also means character values within the UTF-16 surrogate area (0xD800 +to 0xDFFF) are considered part of a surrogate pair. A malformed surrogate +pair will raise a UnicodeEncodeError. Setting ucs4 True turns +surrogate pair decoding off, allowing access the full UCS-4 character +range to a Python interpreter built with four-byte Unicode character +support.

+
+ +
+
+resolution¶
+
+
Pixel resolution in dots per inch
+
resolution -> int
+
+

Read only. Gets pixel size used in scaling font glyphs for this +Font instance.

+
+ +
+ +
+ +
+ + +

+
+Edit on GitHub +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/ref/gfxdraw.html b/venv/Lib/site-packages/pygame/docs/generated/ref/gfxdraw.html new file mode 100644 index 0000000..c97f7be --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/ref/gfxdraw.html @@ -0,0 +1,1058 @@ + + + + + + + + + pygame.gfxdraw — pygame v2.1.2 documentation + + + + + + + + + + + + + +
+ +
+ + + + + +
+
+ +
+
+ +
+
+
+pygame.gfxdraw
+
+
pygame module for drawing shapes
+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+—draw a pixel
+—draw a horizontal line
+—draw a vertical line
+—draw a line
+—draw a rectangle
+—draw a filled rectangle
+—draw a circle
+—draw an antialiased circle
+—draw a filled circle
+—draw an ellipse
+—draw an antialiased ellipse
+—draw a filled ellipse
+—draw an arc
+—draw a pie
+—draw a trigon/triangle
+—draw an antialiased trigon/triangle
+—draw a filled trigon/triangle
+—draw a polygon
+—draw an antialiased polygon
+—draw a filled polygon
+—draw a textured polygon
+—draw a Bezier curve
+

EXPERIMENTAL!: This API may change or disappear in later pygame releases. If +you use this, your code may break with the next pygame release.

+

The pygame package does not import gfxdraw automatically when loaded, so it +must imported explicitly to be used.

+
import pygame
+import pygame.gfxdraw
+
+
+

For all functions the arguments are strictly positional and integers are +accepted for coordinates and radii. The color argument can be one of the +following formats:

+
+
+
+

The functions rectangle() and box() will accept any (x, y, w, h) +sequence for their rect argument, though pygame.Rectpygame object for storing rectangular coordinates instances are +preferred.

+

To draw a filled antialiased shape, first use the antialiased (aa*) version +of the function, and then use the filled (filled_*) version. +For example:

+
col = (255, 0, 0)
+surf.fill((255, 255, 255))
+pygame.gfxdraw.aacircle(surf, x, y, 30, col)
+pygame.gfxdraw.filled_circle(surf, x, y, 30, col)
+
+
+
+

Note

+

For threading, each of the functions releases the GIL during the C part of +the call.

+
+
+

Note

+

See the pygame.drawpygame module for drawing shapes module for alternative draw methods. +The pygame.gfxdraw module differs from the pygame.drawpygame module for drawing shapes module in +the API it uses and the different draw functions available. +pygame.gfxdraw wraps the primitives from the library called SDL_gfx, +rather than using modified versions.

+
+
+

New in pygame 1.9.0.

+
+
+
+pygame.gfxdraw.pixel()¶
+
+
draw a pixel
+
pixel(surface, x, y, color) -> None
+
+

Draws a single pixel, at position (x ,y), on the given surface.

+
+
Parameters
+
    +
  • surface (Surface) -- surface to draw on

  • +
  • x (int) -- x coordinate of the pixel

  • +
  • y (int) -- y coordinate of the pixel

  • +
  • color (Color or tuple(int, int, int, [int])) -- color to draw with, the alpha value is optional if using a +tuple (RGB[A])

  • +
+
+
Returns
+

None

+
+
Return type
+

NoneType

+
+
+
+ +
+
+pygame.gfxdraw.hline()¶
+
+
draw a horizontal line
+
hline(surface, x1, x2, y, color) -> None
+
+

Draws a straight horizontal line ((x1, y) to (x2, y)) on the given +surface. There are no endcaps.

+
+
Parameters
+
    +
  • surface (Surface) -- surface to draw on

  • +
  • x1 (int) -- x coordinate of one end of the line

  • +
  • x2 (int) -- x coordinate of the other end of the line

  • +
  • y (int) -- y coordinate of the line

  • +
  • color (Color or tuple(int, int, int, [int])) -- color to draw with, the alpha value is optional if using a +tuple (RGB[A])

  • +
+
+
Returns
+

None

+
+
Return type
+

NoneType

+
+
+
+ +
+
+pygame.gfxdraw.vline()¶
+
+
draw a vertical line
+
vline(surface, x, y1, y2, color) -> None
+
+

Draws a straight vertical line ((x, y1) to (x, y2)) on the given +surface. There are no endcaps.

+
+
Parameters
+
    +
  • surface (Surface) -- surface to draw on

  • +
  • x (int) -- x coordinate of the line

  • +
  • y1 (int) -- y coordinate of one end of the line

  • +
  • y2 (int) -- y coordinate of the other end of the line

  • +
  • color (Color or tuple(int, int, int, [int])) -- color to draw with, the alpha value is optional if using a +tuple (RGB[A])

  • +
+
+
Returns
+

None

+
+
Return type
+

NoneType

+
+
+
+ +
+
+pygame.gfxdraw.line()¶
+
+
draw a line
+
line(surface, x1, y1, x2, y2, color) -> None
+
+

Draws a straight line ((x1, y1) to (x2, y2)) on the given surface. +There are no endcaps.

+
+
Parameters
+
    +
  • surface (Surface) -- surface to draw on

  • +
  • x1 (int) -- x coordinate of one end of the line

  • +
  • y1 (int) -- y coordinate of one end of the line

  • +
  • x2 (int) -- x coordinate of the other end of the line

  • +
  • y2 (int) -- y coordinate of the other end of the line

  • +
  • color (Color or tuple(int, int, int, [int])) -- color to draw with, the alpha value is optional if using a +tuple (RGB[A])

  • +
+
+
Returns
+

None

+
+
Return type
+

NoneType

+
+
+
+ +
+
+pygame.gfxdraw.rectangle()¶
+
+
draw a rectangle
+
rectangle(surface, rect, color) -> None
+
+

Draws an unfilled rectangle on the given surface. For a filled rectangle use +box().

+
+
Parameters
+
    +
  • surface (Surface) -- surface to draw on

  • +
  • rect (Rect) -- rectangle to draw, position and dimensions

  • +
  • color (Color or tuple(int, int, int, [int])) -- color to draw with, the alpha value is optional if using a +tuple (RGB[A])

  • +
+
+
Returns
+

None

+
+
Return type
+

NoneType

+
+
+
+

Note

+

The rect.bottom and rect.right attributes of a pygame.Rectpygame object for storing rectangular coordinates +always lie one pixel outside of its actual border. Therefore, these +values will not be included as part of the drawing.

+
+
+ +
+
+pygame.gfxdraw.box()¶
+
+
draw a filled rectangle
+
box(surface, rect, color) -> None
+
+

Draws a filled rectangle on the given surface. For an unfilled rectangle use +rectangle().

+
+
Parameters
+
    +
  • surface (Surface) -- surface to draw on

  • +
  • rect (Rect) -- rectangle to draw, position and dimensions

  • +
  • color (Color or tuple(int, int, int, [int])) -- color to draw with, the alpha value is optional if using a +tuple (RGB[A])

  • +
+
+
Returns
+

None

+
+
Return type
+

NoneType

+
+
+
+

Note

+

The rect.bottom and rect.right attributes of a pygame.Rectpygame object for storing rectangular coordinates +always lie one pixel outside of its actual border. Therefore, these +values will not be included as part of the drawing.

+
+
+

Note

+

The pygame.Surface.fill()fill Surface with a solid color method works just as well for drawing +filled rectangles. In fact pygame.Surface.fill()fill Surface with a solid color can be hardware +accelerated on some platforms with both software and hardware display +modes.

+
+
+ +
+
+pygame.gfxdraw.circle()¶
+
+
draw a circle
+
circle(surface, x, y, r, color) -> None
+
+

Draws an unfilled circle on the given surface. For a filled circle use +filled_circle().

+
+
Parameters
+
    +
  • surface (Surface) -- surface to draw on

  • +
  • x (int) -- x coordinate of the center of the circle

  • +
  • y (int) -- y coordinate of the center of the circle

  • +
  • r (int) -- radius of the circle

  • +
  • color (Color or tuple(int, int, int, [int])) -- color to draw with, the alpha value is optional if using a +tuple (RGB[A])

  • +
+
+
Returns
+

None

+
+
Return type
+

NoneType

+
+
+
+ +
+
+pygame.gfxdraw.aacircle()¶
+
+
draw an antialiased circle
+
aacircle(surface, x, y, r, color) -> None
+
+

Draws an unfilled antialiased circle on the given surface.

+
+
Parameters
+
    +
  • surface (Surface) -- surface to draw on

  • +
  • x (int) -- x coordinate of the center of the circle

  • +
  • y (int) -- y coordinate of the center of the circle

  • +
  • r (int) -- radius of the circle

  • +
  • color (Color or tuple(int, int, int, [int])) -- color to draw with, the alpha value is optional if using a +tuple (RGB[A])

  • +
+
+
Returns
+

None

+
+
Return type
+

NoneType

+
+
+
+ +
+
+pygame.gfxdraw.filled_circle()¶
+
+
draw a filled circle
+
filled_circle(surface, x, y, r, color) -> None
+
+

Draws a filled circle on the given surface. For an unfilled circle use +circle().

+
+
Parameters
+
    +
  • surface (Surface) -- surface to draw on

  • +
  • x (int) -- x coordinate of the center of the circle

  • +
  • y (int) -- y coordinate of the center of the circle

  • +
  • r (int) -- radius of the circle

  • +
  • color (Color or tuple(int, int, int, [int])) -- color to draw with, the alpha value is optional if using a +tuple (RGB[A])

  • +
+
+
Returns
+

None

+
+
Return type
+

NoneType

+
+
+
+ +
+
+pygame.gfxdraw.ellipse()¶
+
+
draw an ellipse
+
ellipse(surface, x, y, rx, ry, color) -> None
+
+

Draws an unfilled ellipse on the given surface. For a filled ellipse use +filled_ellipse().

+
+
Parameters
+
    +
  • surface (Surface) -- surface to draw on

  • +
  • x (int) -- x coordinate of the center of the ellipse

  • +
  • y (int) -- y coordinate of the center of the ellipse

  • +
  • rx (int) -- horizontal radius of the ellipse

  • +
  • ry (int) -- vertical radius of the ellipse

  • +
  • color (Color or tuple(int, int, int, [int])) -- color to draw with, the alpha value is optional if using a +tuple (RGB[A])

  • +
+
+
Returns
+

None

+
+
Return type
+

NoneType

+
+
+
+ +
+
+pygame.gfxdraw.aaellipse()¶
+
+
draw an antialiased ellipse
+
aaellipse(surface, x, y, rx, ry, color) -> None
+
+

Draws an unfilled antialiased ellipse on the given surface.

+
+
Parameters
+
    +
  • surface (Surface) -- surface to draw on

  • +
  • x (int) -- x coordinate of the center of the ellipse

  • +
  • y (int) -- y coordinate of the center of the ellipse

  • +
  • rx (int) -- horizontal radius of the ellipse

  • +
  • ry (int) -- vertical radius of the ellipse

  • +
  • color (Color or tuple(int, int, int, [int])) -- color to draw with, the alpha value is optional if using a +tuple (RGB[A])

  • +
+
+
Returns
+

None

+
+
Return type
+

NoneType

+
+
+
+ +
+
+pygame.gfxdraw.filled_ellipse()¶
+
+
draw a filled ellipse
+
filled_ellipse(surface, x, y, rx, ry, color) -> None
+
+

Draws a filled ellipse on the given surface. For an unfilled ellipse use +ellipse().

+
+
Parameters
+
    +
  • surface (Surface) -- surface to draw on

  • +
  • x (int) -- x coordinate of the center of the ellipse

  • +
  • y (int) -- y coordinate of the center of the ellipse

  • +
  • rx (int) -- horizontal radius of the ellipse

  • +
  • ry (int) -- vertical radius of the ellipse

  • +
  • color (Color or tuple(int, int, int, [int])) -- color to draw with, the alpha value is optional if using a +tuple (RGB[A])

  • +
+
+
Returns
+

None

+
+
Return type
+

NoneType

+
+
+
+ +
+
+pygame.gfxdraw.arc()¶
+
+
draw an arc
+
arc(surface, x, y, r, start_angle, stop_angle, color) -> None
+
+

Draws an arc on the given surface. For an arc with its endpoints connected +to its center use pie().

+

The two angle arguments are given in degrees and indicate the start and stop +positions of the arc. The arc is drawn in a clockwise direction from the +start_angle to the stop_angle. If start_angle == stop_angle, +nothing will be drawn

+
+
Parameters
+
    +
  • surface (Surface) -- surface to draw on

  • +
  • x (int) -- x coordinate of the center of the arc

  • +
  • y (int) -- y coordinate of the center of the arc

  • +
  • r (int) -- radius of the arc

  • +
  • start_angle (int) -- start angle in degrees

  • +
  • stop_angle (int) -- stop angle in degrees

  • +
  • color (Color or tuple(int, int, int, [int])) -- color to draw with, the alpha value is optional if using a +tuple (RGB[A])

  • +
+
+
Returns
+

None

+
+
Return type
+

NoneType

+
+
+
+

Note

+

This function uses degrees while the pygame.draw.arc()draw an elliptical arc function +uses radians.

+
+
+ +
+
+pygame.gfxdraw.pie()¶
+
+
draw a pie
+
pie(surface, x, y, r, start_angle, stop_angle, color) -> None
+
+

Draws an unfilled pie on the given surface. A pie is an arc() with its +endpoints connected to its center.

+

The two angle arguments are given in degrees and indicate the start and stop +positions of the pie. The pie is drawn in a clockwise direction from the +start_angle to the stop_angle. If start_angle == stop_angle, +a straight line will be drawn from the center position at the given angle, +to a length of the radius.

+
+
Parameters
+
    +
  • surface (Surface) -- surface to draw on

  • +
  • x (int) -- x coordinate of the center of the pie

  • +
  • y (int) -- y coordinate of the center of the pie

  • +
  • r (int) -- radius of the pie

  • +
  • start_angle (int) -- start angle in degrees

  • +
  • stop_angle (int) -- stop angle in degrees

  • +
  • color (Color or tuple(int, int, int, [int])) -- color to draw with, the alpha value is optional if using a +tuple (RGB[A])

  • +
+
+
Returns
+

None

+
+
Return type
+

NoneType

+
+
+
+ +
+
+pygame.gfxdraw.trigon()¶
+
+
draw a trigon/triangle
+
trigon(surface, x1, y1, x2, y2, x3, y3, color) -> None
+
+

Draws an unfilled trigon (triangle) on the given surface. For a filled +trigon use filled_trigon().

+

A trigon can also be drawn using polygon() e.g. +polygon(surface, ((x1, y1), (x2, y2), (x3, y3)), color)

+
+
Parameters
+
    +
  • surface (Surface) -- surface to draw on

  • +
  • x1 (int) -- x coordinate of the first corner of the trigon

  • +
  • y1 (int) -- y coordinate of the first corner of the trigon

  • +
  • x2 (int) -- x coordinate of the second corner of the trigon

  • +
  • y2 (int) -- y coordinate of the second corner of the trigon

  • +
  • x3 (int) -- x coordinate of the third corner of the trigon

  • +
  • y3 (int) -- y coordinate of the third corner of the trigon

  • +
  • color (Color or tuple(int, int, int, [int])) -- color to draw with, the alpha value is optional if using a +tuple (RGB[A])

  • +
+
+
Returns
+

None

+
+
Return type
+

NoneType

+
+
+
+ +
+
+pygame.gfxdraw.aatrigon()¶
+
+
draw an antialiased trigon/triangle
+
aatrigon(surface, x1, y1, x2, y2, x3, y3, color) -> None
+
+

Draws an unfilled antialiased trigon (triangle) on the given surface.

+

An aatrigon can also be drawn using aapolygon() e.g. +aapolygon(surface, ((x1, y1), (x2, y2), (x3, y3)), color)

+
+
Parameters
+
    +
  • surface (Surface) -- surface to draw on

  • +
  • x1 (int) -- x coordinate of the first corner of the trigon

  • +
  • y1 (int) -- y coordinate of the first corner of the trigon

  • +
  • x2 (int) -- x coordinate of the second corner of the trigon

  • +
  • y2 (int) -- y coordinate of the second corner of the trigon

  • +
  • x3 (int) -- x coordinate of the third corner of the trigon

  • +
  • y3 (int) -- y coordinate of the third corner of the trigon

  • +
  • color (Color or tuple(int, int, int, [int])) -- color to draw with, the alpha value is optional if using a +tuple (RGB[A])

  • +
+
+
Returns
+

None

+
+
Return type
+

NoneType

+
+
+
+ +
+
+pygame.gfxdraw.filled_trigon()¶
+
+
draw a filled trigon/triangle
+
filled_trigon(surface, x1, y1, x2, y2, x3, y3, color) -> None
+
+

Draws a filled trigon (triangle) on the given surface. For an unfilled +trigon use trigon().

+

A filled_trigon can also be drawn using filled_polygon() e.g. +filled_polygon(surface, ((x1, y1), (x2, y2), (x3, y3)), color)

+
+
Parameters
+
    +
  • surface (Surface) -- surface to draw on

  • +
  • x1 (int) -- x coordinate of the first corner of the trigon

  • +
  • y1 (int) -- y coordinate of the first corner of the trigon

  • +
  • x2 (int) -- x coordinate of the second corner of the trigon

  • +
  • y2 (int) -- y coordinate of the second corner of the trigon

  • +
  • x3 (int) -- x coordinate of the third corner of the trigon

  • +
  • y3 (int) -- y coordinate of the third corner of the trigon

  • +
  • color (Color or tuple(int, int, int, [int])) -- color to draw with, the alpha value is optional if using a +tuple (RGB[A])

  • +
+
+
Returns
+

None

+
+
Return type
+

NoneType

+
+
+
+ +
+
+pygame.gfxdraw.polygon()¶
+
+
draw a polygon
+
polygon(surface, points, color) -> None
+
+

Draws an unfilled polygon on the given surface. For a filled polygon use +filled_polygon().

+

The adjacent coordinates in the points argument, as well as the first +and last points, will be connected by line segments. +e.g. For the points [(x1, y1), (x2, y2), (x3, y3)] a line segment will +be drawn from (x1, y1) to (x2, y2), from (x2, y2) to +(x3, y3), and from (x3, y3) to (x1, y1).

+
+
Parameters
+
    +
  • surface (Surface) -- surface to draw on

  • +
  • points (tuple(coordinate) or list(coordinate)) -- a sequence of 3 or more (x, y) coordinates, where each +coordinate in the sequence must be a +tuple/list/pygame.math.Vector2a 2-Dimensional Vector of 2 ints/floats (float values +will be truncated)

  • +
  • color (Color or tuple(int, int, int, [int])) -- color to draw with, the alpha value is optional if using a +tuple (RGB[A])

  • +
+
+
Returns
+

None

+
+
Return type
+

NoneType

+
+
Raises
+
    +
  • ValueError -- if len(points) < 3 (must have at least 3 points)

  • +
  • IndexError -- if len(coordinate) < 2 (each coordinate must have +at least 2 items)

  • +
+
+
+
+ +
+
+pygame.gfxdraw.aapolygon()¶
+
+
draw an antialiased polygon
+
aapolygon(surface, points, color) -> None
+
+

Draws an unfilled antialiased polygon on the given surface.

+

The adjacent coordinates in the points argument, as well as the first +and last points, will be connected by line segments. +e.g. For the points [(x1, y1), (x2, y2), (x3, y3)] a line segment will +be drawn from (x1, y1) to (x2, y2), from (x2, y2) to +(x3, y3), and from (x3, y3) to (x1, y1).

+
+
Parameters
+
    +
  • surface (Surface) -- surface to draw on

  • +
  • points (tuple(coordinate) or list(coordinate)) -- a sequence of 3 or more (x, y) coordinates, where each +coordinate in the sequence must be a +tuple/list/pygame.math.Vector2a 2-Dimensional Vector of 2 ints/floats (float values +will be truncated)

  • +
  • color (Color or tuple(int, int, int, [int])) -- color to draw with, the alpha value is optional if using a +tuple (RGB[A])

  • +
+
+
Returns
+

None

+
+
Return type
+

NoneType

+
+
Raises
+
    +
  • ValueError -- if len(points) < 3 (must have at least 3 points)

  • +
  • IndexError -- if len(coordinate) < 2 (each coordinate must have +at least 2 items)

  • +
+
+
+
+ +
+
+pygame.gfxdraw.filled_polygon()¶
+
+
draw a filled polygon
+
filled_polygon(surface, points, color) -> None
+
+

Draws a filled polygon on the given surface. For an unfilled polygon use +polygon().

+

The adjacent coordinates in the points argument, as well as the first +and last points, will be connected by line segments. +e.g. For the points [(x1, y1), (x2, y2), (x3, y3)] a line segment will +be drawn from (x1, y1) to (x2, y2), from (x2, y2) to +(x3, y3), and from (x3, y3) to (x1, y1).

+
+
Parameters
+
    +
  • surface (Surface) -- surface to draw on

  • +
  • points (tuple(coordinate) or list(coordinate)) -- a sequence of 3 or more (x, y) coordinates, where each +coordinate in the sequence must be a +tuple/list/pygame.math.Vector2a 2-Dimensional Vector of 2 ints/floats (float values +will be truncated)`

  • +
  • color (Color or tuple(int, int, int, [int])) -- color to draw with, the alpha value is optional if using a +tuple (RGB[A])

  • +
+
+
Returns
+

None

+
+
Return type
+

NoneType

+
+
Raises
+
    +
  • ValueError -- if len(points) < 3 (must have at least 3 points)

  • +
  • IndexError -- if len(coordinate) < 2 (each coordinate must have +at least 2 items)

  • +
+
+
+
+ +
+
+pygame.gfxdraw.textured_polygon()¶
+
+
draw a textured polygon
+
textured_polygon(surface, points, texture, tx, ty) -> None
+
+

Draws a textured polygon on the given surface. For better performance, the +surface and the texture should have the same format.

+

A per-pixel alpha texture blit to a per-pixel alpha surface will differ from +a pygame.Surface.blit()draw one image onto another blit. Also, a per-pixel alpha texture cannot be +used with an 8-bit per pixel destination.

+

The adjacent coordinates in the points argument, as well as the first +and last points, will be connected by line segments. +e.g. For the points [(x1, y1), (x2, y2), (x3, y3)] a line segment will +be drawn from (x1, y1) to (x2, y2), from (x2, y2) to +(x3, y3), and from (x3, y3) to (x1, y1).

+
+
Parameters
+
    +
  • surface (Surface) -- surface to draw on

  • +
  • points (tuple(coordinate) or list(coordinate)) -- a sequence of 3 or more (x, y) coordinates, where each +coordinate in the sequence must be a +tuple/list/pygame.math.Vector2a 2-Dimensional Vector of 2 ints/floats (float values +will be truncated)

  • +
  • texture (Surface) -- texture to draw on the polygon

  • +
  • tx (int) -- x offset of the texture

  • +
  • ty (int) -- y offset of the texture

  • +
+
+
Returns
+

None

+
+
Return type
+

NoneType

+
+
Raises
+
    +
  • ValueError -- if len(points) < 3 (must have at least 3 points)

  • +
  • IndexError -- if len(coordinate) < 2 (each coordinate must have +at least 2 items)

  • +
+
+
+
+ +
+
+pygame.gfxdraw.bezier()¶
+
+
draw a Bezier curve
+
bezier(surface, points, steps, color) -> None
+
+

Draws a Bézier curve on the given surface.

+
+
Parameters
+
    +
  • surface (Surface) -- surface to draw on

  • +
  • points (tuple(coordinate) or list(coordinate)) -- a sequence of 3 or more (x, y) coordinates used to form a +curve, where each coordinate in the sequence must be a +tuple/list/pygame.math.Vector2a 2-Dimensional Vector of 2 ints/floats (float values +will be truncated)

  • +
  • steps (int) -- number of steps for the interpolation, the minimum is 2

  • +
  • color (Color or tuple(int, int, int, [int])) -- color to draw with, the alpha value is optional if using a +tuple (RGB[A])

  • +
+
+
Returns
+

None

+
+
Return type
+

NoneType

+
+
Raises
+
    +
  • ValueError -- if steps < 2

  • +
  • ValueError -- if len(points) < 3 (must have at least 3 points)

  • +
  • IndexError -- if len(coordinate) < 2 (each coordinate must have +at least 2 items)

  • +
+
+
+
+ +
+ +
+ + +

+
+Edit on GitHub +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/ref/image.html b/venv/Lib/site-packages/pygame/docs/generated/ref/image.html new file mode 100644 index 0000000..2444caa --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/ref/image.html @@ -0,0 +1,459 @@ + + + + + + + + + pygame.image — pygame v2.1.2 documentation + + + + + + + + + + + + + +
+ +
+ + + + + +
+
+ +
+
+ +
+
+
+pygame.image
+
+
pygame module for image transfer
+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+—load new image from a file (or file-like object)
+—save an image to file (or file-like object)
+—get version number of the SDL_Image library being used
+—test if extended image formats can be loaded
+—transfer image to string buffer
+—create new Surface from a string buffer
+—create a new Surface that shares data inside a bytes buffer
+—load new BMP image from a file (or file-like object)
+—load an image from a file (or file-like object)
+—save a png/jpg image to file (or file-like object)
+

The image module contains functions for loading and saving pictures, as well as +transferring Surfaces to formats usable by other packages.

+

Note that there is no Image class; an image is loaded as a Surface object. The +Surface class allows manipulation (drawing lines, setting pixels, capturing +regions, etc.).

+

The image module is a required dependency of pygame, but it only optionally +supports any extended file formats. By default it can only load uncompressed +BMP images. When built with full image support, the pygame.image.load() +function can support the following formats.

+
+
    +
  • BMP

  • +
  • GIF (non-animated)

  • +
  • JPEG

  • +
  • LBM (and PBM, PGM, PPM)

  • +
  • PCX

  • +
  • PNG

  • +
  • PNM

  • +
  • SVG (limited support, using Nano SVG)

  • +
  • TGA (uncompressed)

  • +
  • TIFF

  • +
  • WEBP

  • +
  • XPM

  • +
+
+
+

New in pygame 2.0: Loading SVG, WebP, PNM

+
+

Saving images only supports a limited set of formats. You can save to the +following formats.

+
+
    +
  • BMP

  • +
  • JPEG

  • +
  • PNG

  • +
  • TGA

  • +
+
+

JPEG and JPG, as well as TIF and TIFF refer to the same file format

+
+

New in pygame 1.8: Saving PNG and JPEG files.

+
+
+
+pygame.image.load()¶
+
+
load new image from a file (or file-like object)
+
load(filename) -> Surface
+
load(fileobj, namehint="") -> Surface
+
+

Load an image from a file source. You can pass either a filename, a Python +file-like object, or a pathlib.Path.

+

Pygame will automatically determine the image type (e.g., GIF or bitmap) +and create a new Surface object from the data. In some cases it will need to +know the file extension (e.g., GIF images should end in ".gif"). If you +pass a raw file-like object, you may also want to pass the original filename +as the namehint argument.

+

The returned Surface will contain the same color format, colorkey and alpha +transparency as the file it came from. You will often want to call +Surface.convert() with no arguments, to create a copy that will draw +more quickly on the screen.

+

For alpha transparency, like in .png images, use the convert_alpha() +method after loading so that the image has per pixel transparency.

+

pygame may not always be built to support all image formats. At minimum it +will support uncompressed BMP. If pygame.image.get_extended() +returns 'True', you should be able to load most images (including PNG, JPG +and GIF).

+

You should use os.path.join() for compatibility.

+
eg. asurf = pygame.image.load(os.path.join('data', 'bla.png'))
+
+
+
+ +
+
+pygame.image.save()¶
+
+
save an image to file (or file-like object)
+
save(Surface, filename) -> None
+
save(Surface, fileobj, namehint="") -> None
+
+

This will save your Surface as either a BMP, TGA, PNG, or +JPEG image. If the filename extension is unrecognized it will default to +TGA. Both TGA, and BMP file formats create uncompressed files. +You can pass a filename, a pathlib.Path or a Python file-like object. +For file-like object, the image is saved to TGA format unless +a namehint with a recognizable extension is passed in.

+
+

Note

+

When saving to a file-like object, it seems that for most formats, +the object needs to be flushed after saving to it to make loading +from it possible.

+
+
+

Changed in pygame 1.8: Saving PNG and JPEG files.

+
+
+

Changed in pygame 2.0.0: The namehint parameter was added to make it possible +to save other formats than TGA to a file-like object. +Saving to a file-like object with JPEG is possible.

+
+
+ +
+
+pygame.image.get_sdl_image_version()¶
+
+
get version number of the SDL_Image library being used
+
get_sdl_image_version() -> None
+
get_sdl_image_version() -> (major, minor, patch)
+
+

If pygame is built with extended image formats, then this function will +return the SDL_Image library's version number as a tuple of 3 integers +(major, minor, patch). If not, then it will return None.

+
+

New in pygame 2.0.0.

+
+
+ +
+
+pygame.image.get_extended()¶
+
+
test if extended image formats can be loaded
+
get_extended() -> bool
+
+

If pygame is built with extended image formats this function will return +True. It is still not possible to determine which formats will be available, +but generally you will be able to load them all.

+
+ +
+
+pygame.image.tostring()¶
+
+
transfer image to string buffer
+
tostring(Surface, format, flipped=False) -> string
+
+

Creates a string that can be transferred with the 'fromstring' method in +other Python imaging packages. Some Python image packages prefer their +images in bottom-to-top format (PyOpenGL for example). If you pass True for +the flipped argument, the string buffer will be vertically flipped.

+

The format argument is a string of one of the following values. Note that +only 8-bit Surfaces can use the "P" format. The other formats will work for +any Surface. Also note that other Python image packages support more formats +than pygame.

+
+
    +
  • P, 8-bit palettized Surfaces

  • +
  • RGB, 24-bit image

  • +
  • RGBX, 32-bit image with unused space

  • +
  • RGBA, 32-bit image with an alpha channel

  • +
  • ARGB, 32-bit image with alpha channel first

  • +
  • RGBA_PREMULT, 32-bit image with colors scaled by alpha channel

  • +
  • ARGB_PREMULT, 32-bit image with colors scaled by alpha channel, alpha channel first

  • +
+
+
+ +
+
+pygame.image.fromstring()¶
+
+
create new Surface from a string buffer
+
fromstring(string, size, format, flipped=False) -> Surface
+
+

This function takes arguments similar to pygame.image.tostring(). The +size argument is a pair of numbers representing the width and height. Once +the new Surface is created you can destroy the string buffer.

+

The size and format image must compute the exact same size as the passed +string buffer. Otherwise an exception will be raised.

+

See the pygame.image.frombuffer() method for a potentially faster way to +transfer images into pygame.

+
+ +
+
+pygame.image.frombuffer()¶
+
+
create a new Surface that shares data inside a bytes buffer
+
frombuffer(bytes, size, format) -> Surface
+
+

Create a new Surface that shares pixel data directly from a bytes buffer. +This method takes similar arguments to pygame.image.fromstring(), but +is unable to vertically flip the source data.

+

This will run much faster than pygame.image.fromstring()create new Surface from a string buffer, since no +pixel data must be allocated and copied.

+

It accepts the following 'format' arguments:

+
+
    +
  • P, 8-bit palettized Surfaces

  • +
  • RGB, 24-bit image

  • +
  • BGR, 24-bit image, red and blue channels swapped.

  • +
  • RGBX, 32-bit image with unused space

  • +
  • RGBA, 32-bit image with an alpha channel

  • +
  • ARGB, 32-bit image with alpha channel first

  • +
+
+
+ +
+
+pygame.image.load_basic()¶
+
+
load new BMP image from a file (or file-like object)
+
load_basic(file) -> Surface
+
+

Load an image from a file source. You can pass either a filename or a Python +file-like object, or a pathlib.Path.

+

This function only supports loading "basic" image format, ie BMP +format. +This function is always available, no matter how pygame was built.

+
+ +
+
+pygame.image.load_extended()¶
+
+
load an image from a file (or file-like object)
+
load_extended(filename) -> Surface
+
load_extended(fileobj, namehint="") -> Surface
+
+

This function is similar to pygame.image.load(), except that this +function can only be used if pygame was built with extended image format +support.

+

From version 2.0.1, this function is always available, but raises an +error if extended image formats are not supported. Previously, this +function may or may not be available, depending on the state of +extended image format support.

+
+

Changed in pygame 2.0.1.

+
+
+ +
+
+pygame.image.save_extended()¶
+
+
save a png/jpg image to file (or file-like object)
+
save_extended(Surface, filename) -> None
+
save_extended(Surface, fileobj, namehint="") -> None
+
+

This will save your Surface as either a PNG or JPEG image.

+

Incase the image is being saved to a file-like object, this function +uses the namehint argument to determine the format of the file being +saved. Saves to JPEG incase the namehint was not specified while +saving to file-like object.

+
+

Changed in pygame 2.0.1: This function is always available, but raises an +error if extended image formats are not supported. +Previously, this function may or may not be +available, depending on the state of extended image +format support.

+
+
+ +
+ +
+ + +

+
+Edit on GitHub +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/ref/joystick.html b/venv/Lib/site-packages/pygame/docs/generated/ref/joystick.html new file mode 100644 index 0000000..703da99 --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/ref/joystick.html @@ -0,0 +1,984 @@ + + + + + + + + + pygame.joystick — pygame v2.1.2 documentation + + + + + + + + + + + + + +
+ +
+ + + + + +
+
+ +
+
+ +
+
+
+pygame.joystick
+
+
Pygame module for interacting with joysticks, gamepads, and trackballs.
+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + +
+—Initialize the joystick module.
+—Uninitialize the joystick module.
+—Returns True if the joystick module is initialized.
+—Returns the number of joysticks.
+—Create a new Joystick object.
+

The joystick module manages the joystick devices on a computer. +Joystick devices include trackballs and video-game-style +gamepads, and the module allows the use of multiple buttons and "hats". +Computers may manage multiple joysticks at a time.

+

Each instance of the Joystick class represents one gaming device plugged +into the computer. If a gaming pad has multiple joysticks on it, then the +joystick object can actually represent multiple joysticks on that single +game device.

+

For a quick way to initialise the joystick module and get a list of Joystick instances +use the following code:

+
pygame.joystick.init()
+joysticks = [pygame.joystick.Joystick(x) for x in range(pygame.joystick.get_count())]
+
+
+

The following event types will be generated by the joysticks

+
JOYAXISMOTION JOYBALLMOTION JOYBUTTONDOWN JOYBUTTONUP JOYHATMOTION
+
+
+

And in pygame 2, which supports hotplugging:

+
JOYDEVICEADDED JOYDEVICEREMOVED
+
+
+

Note that in pygame 2, joysticks events use a unique "instance ID". The device index +passed in the constructor to a Joystick object is not unique after devices have +been added and removed. You must call Joystick.get_instance_id() to find +the instance ID that was assigned to a Joystick on opening.

+

The event queue needs to be pumped frequently for some of the methods to work. +So call one of pygame.event.get, pygame.event.wait, or pygame.event.pump regularly.

+
+
+pygame.joystick.init()¶
+
+
Initialize the joystick module.
+
init() -> None
+
+

This function is called automatically by pygame.init().

+

It initializes the joystick module. The module must be initialized before any +other functions will work.

+

It is safe to call this function more than once.

+
+ +
+
+pygame.joystick.quit()¶
+
+
Uninitialize the joystick module.
+
quit() -> None
+
+

Uninitialize the joystick module. After you call this any existing joystick +objects will no longer work.

+

It is safe to call this function more than once.

+
+ +
+
+pygame.joystick.get_init()¶
+
+
Returns True if the joystick module is initialized.
+
get_init() -> bool
+
+

Test if the pygame.joystick.init() function has been called.

+
+ +
+
+pygame.joystick.get_count()¶
+
+
Returns the number of joysticks.
+
get_count() -> count
+
+

Return the number of joystick devices on the system. The count will be 0 +if there are no joysticks on the system.

+

When you create Joystick objects using Joystick(id), you pass an integer +that must be lower than this count.

+
+ +
+
+pygame.joystick.Joystick¶
+
+
Create a new Joystick object.
+
Joystick(id) -> Joystick
+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+—initialize the Joystick
+—uninitialize the Joystick
+—check if the Joystick is initialized
+—get the device index (deprecated)
+—get the joystick instance id
+—get the joystick GUID
+—get the approximate power status of the device
+—get the Joystick system name
+—get the number of axes on a Joystick
+—get the current position of an axis
+—get the number of trackballs on a Joystick
+—get the relative position of a trackball
+—get the number of buttons on a Joystick
+—get the current button state
+—get the number of hat controls on a Joystick
+—get the position of a joystick hat
+—Start a rumbling effect
+—Stop any rumble effect playing
+

Create a new joystick to access a physical device. The id argument must be a +value from 0 to pygame.joystick.get_count() - 1.

+

Joysticks are initialised on creation and are shut down when deallocated. +Once the device is initialized the pygame event queue will start receiving +events about its input.

+
+

Changed in pygame 2.0.0: Joystick objects are now opened immediately on creation.

+
+
+
+init()¶
+
+
initialize the Joystick
+
init() -> None
+
+

Initialize the joystick, if it has been closed. It is safe to call this +even if the joystick is already initialized.

+
+

Deprecated since pygame 2.0.0: In future it will not be possible to reinitialise a closed Joystick +object. Will be removed in Pygame 2.1.

+
+
+ +
+
+quit()¶
+
+
uninitialize the Joystick
+
quit() -> None
+
+

Close a Joystick object. After this the pygame event queue will no longer +receive events from the device.

+

It is safe to call this more than once.

+
+ +
+
+get_init()¶
+
+
check if the Joystick is initialized
+
get_init() -> bool
+
+

Return True if the Joystick object is currently initialised.

+
+ +
+
+get_id()¶
+
+
get the device index (deprecated)
+
get_id() -> int
+
+

Returns the original device index for this device. This is the same +value that was passed to the Joystick() constructor. This method can +safely be called while the Joystick is not initialized.

+
+

Deprecated since pygame 2.0.0: The original device index is not useful in pygame 2. Use +get_instance_id() instead. Will be removed in Pygame 2.1.

+
+
+ +
+
+get_instance_id() int¶
+
+
get the joystick instance id
+
get_instance_id() -> int
+
+

Get the joystick instance ID. This matches the instance_id field +that is given in joystick events.

+
+

New in pygame 2.0.0dev11.

+
+
+ +
+
+get_guid() str¶
+
+
get the joystick GUID
+
get_guid() -> str
+
+

Get the GUID string. This identifies the exact hardware of the joystick +device.

+
+

New in pygame 2.0.0dev11.

+
+
+ +
+
+get_power_level() str¶
+
+
get the approximate power status of the device
+
get_power_level() -> str
+
+

Get a string giving the power status of the device.

+

One of: empty, low, medium, full, wired, max, or +unknown.

+
+

New in pygame 2.0.0dev11.

+
+
+ +
+
+get_name()¶
+
+
get the Joystick system name
+
get_name() -> string
+
+

Returns the system name for this joystick device. It is unknown what name +the system will give to the Joystick, but it should be a unique name that +identifies the device. This method can safely be called while the +Joystick is not initialized.

+
+ +
+
+get_numaxes()¶
+
+
get the number of axes on a Joystick
+
get_numaxes() -> int
+
+

Returns the number of input axes are on a Joystick. There will usually be +two for the position. Controls like rudders and throttles are treated as +additional axes.

+

The pygame.JOYAXISMOTION events will be in the range from -1.0 +to 1.0. A value of 0.0 means the axis is centered. Gamepad devices +will usually be -1, 0, or 1 with no values in between. Older +analog joystick axes will not always use the full -1 to 1 range, +and the centered value will be some area around 0.

+

Analog joysticks usually have a bit of noise in their axis, which will +generate a lot of rapid small motion events.

+
+ +
+
+get_axis()¶
+
+
get the current position of an axis
+
get_axis(axis_number) -> float
+
+

Returns the current position of a joystick axis. The value will range +from -1 to 1 with a value of 0 being centered. You may want +to take into account some tolerance to handle jitter, and joystick drift +may keep the joystick from centering at 0 or using the full range of +position values.

+

The axis number must be an integer from 0 to get_numaxes() - 1.

+

When using gamepads both the control sticks and the analog triggers are +usually reported as axes.

+
+ +
+
+get_numballs()¶
+
+
get the number of trackballs on a Joystick
+
get_numballs() -> int
+
+

Returns the number of trackball devices on a Joystick. These devices work +similar to a mouse but they have no absolute position; they only have +relative amounts of movement.

+

The pygame.JOYBALLMOTION event will be sent when the trackball is +rolled. It will report the amount of movement on the trackball.

+
+ +
+
+get_ball()¶
+
+
get the relative position of a trackball
+
get_ball(ball_number) -> x, y
+
+

Returns the relative movement of a joystick button. The value is a x, y +pair holding the relative movement since the last call to get_ball.

+

The ball number must be an integer from 0 to get_numballs() - 1.

+
+ +
+
+get_numbuttons()¶
+
+
get the number of buttons on a Joystick
+
get_numbuttons() -> int
+
+

Returns the number of pushable buttons on the joystick. These buttons +have a boolean (on or off) state.

+

Buttons generate a pygame.JOYBUTTONDOWN and pygame.JOYBUTTONUP +event when they are pressed and released.

+
+ +
+
+get_button()¶
+
+
get the current button state
+
get_button(button) -> bool
+
+

Returns the current state of a joystick button.

+
+ +
+
+get_numhats()¶
+
+
get the number of hat controls on a Joystick
+
get_numhats() -> int
+
+

Returns the number of joystick hats on a Joystick. Hat devices are like +miniature digital joysticks on a joystick. Each hat has two axes of +input.

+

The pygame.JOYHATMOTION event is generated when the hat changes +position. The position attribute for the event contains a pair of +values that are either -1, 0, or 1. A position of (0, 0) +means the hat is centered.

+
+ +
+
+get_hat()¶
+
+
get the position of a joystick hat
+
get_hat(hat_number) -> x, y
+
+

Returns the current position of a position hat. The position is given as +two values representing the x and y position for the hat. (0, 0) +means centered. A value of -1 means left/down and a value of 1 means +right/up: so (-1, 0) means left; (1, 0) means right; (0, 1) means +up; (1, 1) means upper-right; etc.

+

This value is digital, i.e., each coordinate can be -1, 0 or 1 +but never in-between.

+

The hat number must be between 0 and get_numhats() - 1.

+
+ +
+
+rumble()¶
+
+
Start a rumbling effect
+
rumble(low_frequency, high_frequency, duration) -> bool
+
+

Start a rumble effect on the joystick, with the specified strength ranging +from 0 to 1. Duration is length of the effect, in ms. Setting the duration +to 0 will play the effect until another one overwrites it or +Joystick.stop_rumble() is called. If an effect is already +playing, then it will be overwritten.

+

Returns True if the rumble was played successfully or False if the +joystick does not support it or pygame.version.SDL()tupled integers of the SDL library version is below 2.0.9.

+
+

New in pygame 2.0.2.

+
+
+ +
+
+stop_rumble()¶
+
+
Stop any rumble effect playing
+
stop_rumble() -> None
+
+

Stops any rumble effect playing on the joystick. See +Joystick.rumble() for more information.

+
+

New in pygame 2.0.2.

+
+
+ +
+ +
+joystick module example +
+

Example code for joystick module.¶

+
+
+
import pygame
+
+
+# Define some colors.
+BLACK = pygame.Color('black')
+WHITE = pygame.Color('white')
+
+
+# This is a simple class that will help us print to the screen.
+# It has nothing to do with the joysticks, just outputting the
+# information.
+class TextPrint(object):
+    def __init__(self):
+        self.reset()
+        self.font = pygame.font.Font(None, 20)
+
+    def tprint(self, screen, textString):
+        textBitmap = self.font.render(textString, True, BLACK)
+        screen.blit(textBitmap, (self.x, self.y))
+        self.y += self.line_height
+
+    def reset(self):
+        self.x = 10
+        self.y = 10
+        self.line_height = 15
+
+    def indent(self):
+        self.x += 10
+
+    def unindent(self):
+        self.x -= 10
+
+
+pygame.init()
+
+# Set the width and height of the screen (width, height).
+screen = pygame.display.set_mode((500, 700))
+
+pygame.display.set_caption("My Game")
+
+# Loop until the user clicks the close button.
+done = False
+
+# Used to manage how fast the screen updates.
+clock = pygame.time.Clock()
+
+# Initialize the joysticks.
+pygame.joystick.init()
+
+# Get ready to print.
+textPrint = TextPrint()
+
+# -------- Main Program Loop -----------
+while not done:
+    #
+    # EVENT PROCESSING STEP
+    #
+    # Possible joystick actions: JOYAXISMOTION, JOYBALLMOTION, JOYBUTTONDOWN,
+    # JOYBUTTONUP, JOYHATMOTION
+    for event in pygame.event.get(): # User did something.
+        if event.type == pygame.QUIT: # If user clicked close.
+            done = True # Flag that we are done so we exit this loop.
+        elif event.type == pygame.JOYBUTTONDOWN:
+            print("Joystick button pressed.")
+        elif event.type == pygame.JOYBUTTONUP:
+            print("Joystick button released.")
+
+    #
+    # DRAWING STEP
+    #
+    # First, clear the screen to white. Don't put other drawing commands
+    # above this, or they will be erased with this command.
+    screen.fill(WHITE)
+    textPrint.reset()
+
+    # Get count of joysticks.
+    joystick_count = pygame.joystick.get_count()
+
+    textPrint.tprint(screen, "Number of joysticks: {}".format(joystick_count))
+    textPrint.indent()
+
+    # For each joystick:
+    for i in range(joystick_count):
+        joystick = pygame.joystick.Joystick(i)
+        joystick.init()
+
+        try:
+            jid = joystick.get_instance_id()
+        except AttributeError:
+            # get_instance_id() is an SDL2 method
+            jid = joystick.get_id()
+        textPrint.tprint(screen, "Joystick {}".format(jid))
+        textPrint.indent()
+
+        # Get the name from the OS for the controller/joystick.
+        name = joystick.get_name()
+        textPrint.tprint(screen, "Joystick name: {}".format(name))
+
+        try:
+            guid = joystick.get_guid()
+        except AttributeError:
+            # get_guid() is an SDL2 method
+            pass
+        else:
+            textPrint.tprint(screen, "GUID: {}".format(guid))
+
+        # Usually axis run in pairs, up/down for one, and left/right for
+        # the other.
+        axes = joystick.get_numaxes()
+        textPrint.tprint(screen, "Number of axes: {}".format(axes))
+        textPrint.indent()
+
+        for i in range(axes):
+            axis = joystick.get_axis(i)
+            textPrint.tprint(screen, "Axis {} value: {:>6.3f}".format(i, axis))
+        textPrint.unindent()
+
+        buttons = joystick.get_numbuttons()
+        textPrint.tprint(screen, "Number of buttons: {}".format(buttons))
+        textPrint.indent()
+
+        for i in range(buttons):
+            button = joystick.get_button(i)
+            textPrint.tprint(screen,
+                             "Button {:>2} value: {}".format(i, button))
+        textPrint.unindent()
+
+        hats = joystick.get_numhats()
+        textPrint.tprint(screen, "Number of hats: {}".format(hats))
+        textPrint.indent()
+
+        # Hat position. All or nothing for direction, not a float like
+        # get_axis(). Position is a tuple of int values (x, y).
+        for i in range(hats):
+            hat = joystick.get_hat(i)
+            textPrint.tprint(screen, "Hat {} value: {}".format(i, str(hat)))
+        textPrint.unindent()
+
+        textPrint.unindent()
+
+    #
+    # ALL CODE TO DRAW SHOULD GO ABOVE THIS COMMENT
+    #
+
+    # Go ahead and update the screen with what we've drawn.
+    pygame.display.flip()
+
+    # Limit to 20 frames per second.
+    clock.tick(20)
+
+# Close the window and quit.
+# If you forget this line, the program will 'hang'
+# on exit if running from IDLE.
+pygame.quit()
+
+
+
+

Common Controller Axis Mappings

+

Controller mappings are drawn from the underlying SDL library which pygame uses and they differ +between pygame 1 and pygame 2. Below are a couple of mappings for two popular game pads.

+

Pygame 2

+

Axis and hat mappings are listed from -1 to +1.

+

X-Box 360 Controller (name: "Xbox 360 Controller")

+

In pygame 2 the X360 controller mapping has 6 Axes, 11 buttons and 1 hat.

+
    +
  • Left Stick:

    +
    Left -> Right   - Axis 0
    +Up   -> Down    - Axis 1
    +
    +
    +
  • +
  • Right Stick:

    +
    Left -> Right   - Axis 3
    +Up   -> Down    - Axis 4
    +
    +
    +
  • +
  • Left Trigger:

    +
    Out -> In       - Axis 2
    +
    +
    +
  • +
  • Right Trigger:

    +
    Out -> In       - Axis 5
    +
    +
    +
  • +
  • Buttons:

    +
    A Button        - Button 0
    +B Button        - Button 1
    +X Button        - Button 2
    +Y Button        - Button 3
    +Left Bumper     - Button 4
    +Right Bumper    - Button 5
    +Back Button     - Button 6
    +Start Button    - Button 7
    +L. Stick In     - Button 8
    +R. Stick In     - Button 9
    +Guide Button    - Button 10
    +
    +
    +
  • +
  • Hat/D-pad:

    +
    Down -> Up      - Y Axis
    +Left -> Right   - X Axis
    +
    +
    +
  • +
+

Playstation 4 Controller (name: "PS4 Controller")

+

In pygame 2 the PS4 controller mapping has 6 Axes and 16 buttons.

+
    +
  • Left Stick:

    +
    Left -> Right   - Axis 0
    +Up   -> Down    - Axis 1
    +
    +
    +
  • +
  • Right Stick:

    +
    Left -> Right   - Axis 2
    +Up   -> Down    - Axis 3
    +
    +
    +
  • +
  • Left Trigger:

    +
    Out -> In       - Axis 4
    +
    +
    +
  • +
  • Right Trigger:

    +
    Out -> In       - Axis 5
    +
    +
    +
  • +
  • Buttons:

    +
    Cross Button    - Button 0
    +Circle Button   - Button 1
    +Square Button   - Button 2
    +Triangle Button - Button 3
    +Share Button    - Button 4
    +PS Button       - Button 5
    +Options Button  - Button 6
    +L. Stick In     - Button 7
    +R. Stick In     - Button 8
    +Left Bumper     - Button 9
    +Right Bumper    - Button 10
    +D-pad Up        - Button 11
    +D-pad Down      - Button 12
    +D-pad Left      - Button 13
    +D-pad Right     - Button 14
    +Touch Pad Click - Button 15
    +
    +
    +
  • +
+

Pygame 1

+

Axis and hat mappings are listed from -1 to +1.

+

X-Box 360 Controller (name: "Controller (XBOX 360 For Windows)")

+

In pygame 1 the X360 controller mapping has 5 Axes, 10 buttons and 1 hat.

+
    +
  • Left Stick:

    +
    Left -> Right   - Axis 0
    +Up   -> Down    - Axis 1
    +
    +
    +
  • +
  • Right Stick:

    +
    Left -> Right   - Axis 4
    +Up   -> Down    - Axis 3
    +
    +
    +
  • +
  • Left Trigger & Right Trigger:

    +
    RT -> LT        - Axis 2
    +
    +
    +
  • +
  • Buttons:

    +
    A Button        - Button 0
    +B Button        - Button 1
    +X Button        - Button 2
    +Y Button        - Button 3
    +Left Bumper     - Button 4
    +Right Bumper    - Button 5
    +Back Button     - Button 6
    +Start Button    - Button 7
    +L. Stick In     - Button 8
    +R. Stick In     - Button 9
    +
    +
    +
  • +
  • Hat/D-pad:

    +
    Down -> Up      - Y Axis
    +Left -> Right   - X Axis
    +
    +
    +
  • +
+

Playstation 4 Controller (name: "Wireless Controller")

+

In pygame 1 the PS4 controller mapping has 6 Axes and 14 buttons and 1 hat.

+
    +
  • Left Stick:

    +
    Left -> Right   - Axis 0
    +Up   -> Down    - Axis 1
    +
    +
    +
  • +
  • Right Stick:

    +
    Left -> Right   - Axis 2
    +Up   -> Down    - Axis 3
    +
    +
    +
  • +
  • Left Trigger:

    +
    Out -> In       - Axis 5
    +
    +
    +
  • +
  • Right Trigger:

    +
    Out -> In       - Axis 4
    +
    +
    +
  • +
  • Buttons:

    +
    Cross Button    - Button 0
    +Circle Button   - Button 1
    +Square Button   - Button 2
    +Triangle Button - Button 3
    +Left Bumper     - Button 4
    +Right Bumper    - Button 5
    +L. Trigger(Full)- Button 6
    +R. Trigger(Full)- Button 7
    +Share Button    - Button 8
    +Options Button  - Button 9
    +L. Stick In     - Button 10
    +R. Stick In     - Button 11
    +PS Button       - Button 12
    +Touch Pad Click - Button 13
    +
    +
    +
  • +
  • Hat/D-pad:

    +
    Down -> Up      - Y Axis
    +Left -> Right   - X Axis
    +
    +
    +
  • +
+
+ +
+ + +

+
+Edit on GitHub +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/ref/key.html b/venv/Lib/site-packages/pygame/docs/generated/ref/key.html new file mode 100644 index 0000000..c662fb2 --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/ref/key.html @@ -0,0 +1,628 @@ + + + + + + + + + pygame.key — pygame v2.1.2 documentation + + + + + + + + + + + + + +
+ +
+ + + + + +
+
+ +
+
+ +
+
+
+pygame.key
+
+
pygame module to work with the keyboard
+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+—true if the display is receiving keyboard input from the system
+—get the state of all keyboard buttons
+—determine which modifier keys are being held
+—temporarily set which modifier keys are pressed
+—control how held keys are repeated
+—see how held keys are repeated
+—get the name of a key identifier
+—get the key identifier from a key name
+—start handling Unicode text input events
+—stop handling Unicode text input events
+—controls the position of the candidate list
+

This module contains functions for dealing with the keyboard.

+

The pygame.eventpygame module for interacting with events and queues queue gets pygame.KEYDOWN and pygame.KEYUP +events when the keyboard buttons are pressed and released. Both events have +key and mod attributes.

+
+
    +
  • key: an integer ID representing every key +on the keyboard

  • +
  • mod: a bitmask of all the modifier keys +that were in a pressed state when the event occurred

  • +
+
+

The pygame.KEYDOWN event has the additional attributes unicode and +scancode.

+
+
    +
  • unicode: a single character string that is the fully translated +character entered, this takes into account the shift and composition keys

  • +
  • scancode: the platform-specific key code, which could be different from +keyboard to keyboard, but is useful for key selection of weird keys like +the multimedia keys

  • +
+
+
+

New in pygame 2.0.0: The pygame.TEXTINPUT event is preferred to the unicode attribute +of pygame.KEYDOWN. The attribute text contains the input.

+
+

The following is a list of all the constants (from pygame.localspygame constants) used to +represent keyboard keys.

+

Portability note: The integers for key constants differ between pygame 1 and 2. +Always use key constants (K_a) rather than integers directly (97) so +that your key handling code works well on both pygame 1 and pygame 2.

+
pygame
+Constant      ASCII   Description
+---------------------------------
+K_BACKSPACE   \b      backspace
+K_TAB         \t      tab
+K_CLEAR               clear
+K_RETURN      \r      return
+K_PAUSE               pause
+K_ESCAPE      ^[      escape
+K_SPACE               space
+K_EXCLAIM     !       exclaim
+K_QUOTEDBL    "       quotedbl
+K_HASH        #       hash
+K_DOLLAR      $       dollar
+K_AMPERSAND   &       ampersand
+K_QUOTE               quote
+K_LEFTPAREN   (       left parenthesis
+K_RIGHTPAREN  )       right parenthesis
+K_ASTERISK    *       asterisk
+K_PLUS        +       plus sign
+K_COMMA       ,       comma
+K_MINUS       -       minus sign
+K_PERIOD      .       period
+K_SLASH       /       forward slash
+K_0           0       0
+K_1           1       1
+K_2           2       2
+K_3           3       3
+K_4           4       4
+K_5           5       5
+K_6           6       6
+K_7           7       7
+K_8           8       8
+K_9           9       9
+K_COLON       :       colon
+K_SEMICOLON   ;       semicolon
+K_LESS        <       less-than sign
+K_EQUALS      =       equals sign
+K_GREATER     >       greater-than sign
+K_QUESTION    ?       question mark
+K_AT          @       at
+K_LEFTBRACKET [       left bracket
+K_BACKSLASH   \       backslash
+K_RIGHTBRACKET ]      right bracket
+K_CARET       ^       caret
+K_UNDERSCORE  _       underscore
+K_BACKQUOTE   `       grave
+K_a           a       a
+K_b           b       b
+K_c           c       c
+K_d           d       d
+K_e           e       e
+K_f           f       f
+K_g           g       g
+K_h           h       h
+K_i           i       i
+K_j           j       j
+K_k           k       k
+K_l           l       l
+K_m           m       m
+K_n           n       n
+K_o           o       o
+K_p           p       p
+K_q           q       q
+K_r           r       r
+K_s           s       s
+K_t           t       t
+K_u           u       u
+K_v           v       v
+K_w           w       w
+K_x           x       x
+K_y           y       y
+K_z           z       z
+K_DELETE              delete
+K_KP0                 keypad 0
+K_KP1                 keypad 1
+K_KP2                 keypad 2
+K_KP3                 keypad 3
+K_KP4                 keypad 4
+K_KP5                 keypad 5
+K_KP6                 keypad 6
+K_KP7                 keypad 7
+K_KP8                 keypad 8
+K_KP9                 keypad 9
+K_KP_PERIOD   .       keypad period
+K_KP_DIVIDE   /       keypad divide
+K_KP_MULTIPLY *       keypad multiply
+K_KP_MINUS    -       keypad minus
+K_KP_PLUS     +       keypad plus
+K_KP_ENTER    \r      keypad enter
+K_KP_EQUALS   =       keypad equals
+K_UP                  up arrow
+K_DOWN                down arrow
+K_RIGHT               right arrow
+K_LEFT                left arrow
+K_INSERT              insert
+K_HOME                home
+K_END                 end
+K_PAGEUP              page up
+K_PAGEDOWN            page down
+K_F1                  F1
+K_F2                  F2
+K_F3                  F3
+K_F4                  F4
+K_F5                  F5
+K_F6                  F6
+K_F7                  F7
+K_F8                  F8
+K_F9                  F9
+K_F10                 F10
+K_F11                 F11
+K_F12                 F12
+K_F13                 F13
+K_F14                 F14
+K_F15                 F15
+K_NUMLOCK             numlock
+K_CAPSLOCK            capslock
+K_SCROLLOCK           scrollock
+K_RSHIFT              right shift
+K_LSHIFT              left shift
+K_RCTRL               right control
+K_LCTRL               left control
+K_RALT                right alt
+K_LALT                left alt
+K_RMETA               right meta
+K_LMETA               left meta
+K_LSUPER              left Windows key
+K_RSUPER              right Windows key
+K_MODE                mode shift
+K_HELP                help
+K_PRINT               print screen
+K_SYSREQ              sysrq
+K_BREAK               break
+K_MENU                menu
+K_POWER               power
+K_EURO                Euro
+K_AC_BACK             Android back button
+
+
+

The keyboard also has a list of modifier states (from pygame.localspygame constants) that +can be assembled by bitwise-ORing them together.

+
pygame
+Constant      Description
+-------------------------
+KMOD_NONE     no modifier keys pressed
+KMOD_LSHIFT   left shift
+KMOD_RSHIFT   right shift
+KMOD_SHIFT    left shift or right shift or both
+KMOD_LCTRL    left control
+KMOD_RCTRL    right control
+KMOD_CTRL     left control or right control or both
+KMOD_LALT     left alt
+KMOD_RALT     right alt
+KMOD_ALT      left alt or right alt or both
+KMOD_LMETA    left meta
+KMOD_RMETA    right meta
+KMOD_META     left meta or right meta or both
+KMOD_CAPS     caps lock
+KMOD_NUM      num lock
+KMOD_MODE     AltGr
+
+
+

The modifier information is contained in the mod attribute of the +pygame.KEYDOWN and pygame.KEYUP events. The mod attribute is a +bitmask of all the modifier keys that were in a pressed state when the event +occurred. The modifier information can be decoded using a bitwise AND (except +for KMOD_NONE, which should be compared using equals ==). For example:

+
for event in pygame.event.get():
+    if event.type == pygame.KEYDOWN or event.type == pygame.KEYUP:
+        if event.mod == pygame.KMOD_NONE:
+            print('No modifier keys were in a pressed state when this '
+                  'event occurred.')
+        else:
+            if event.mod & pygame.KMOD_LSHIFT:
+                print('Left shift was in a pressed state when this event '
+                      'occurred.')
+            if event.mod & pygame.KMOD_RSHIFT:
+                print('Right shift was in a pressed state when this event '
+                      'occurred.')
+            if event.mod & pygame.KMOD_SHIFT:
+                print('Left shift or right shift or both were in a '
+                      'pressed state when this event occurred.')
+
+
+
+
+pygame.key.get_focused()¶
+
+
true if the display is receiving keyboard input from the system
+
get_focused() -> bool
+
+

Returns True when the display window has keyboard focus from the +system. If the display needs to ensure it does not lose keyboard focus, it +can use pygame.event.set_grab()control the sharing of input devices with other applications to grab all input.

+
+ +
+
+pygame.key.get_pressed()¶
+
+
get the state of all keyboard buttons
+
get_pressed() -> bools
+
+

Returns a sequence of boolean values representing the state of every key on +the keyboard. Use the key constant values to index the array. A True +value means that the button is pressed.

+
+

Note

+

Getting the list of pushed buttons with this function is not the proper +way to handle text entry from the user. There is no way to know the order +of keys pressed, and rapidly pushed keys can be completely unnoticed +between two calls to pygame.key.get_pressed(). There is also no way to +translate these pushed keys into a fully translated character value. See +the pygame.KEYDOWN events on the pygame.eventpygame module for interacting with events and queues queue for this +functionality.

+
+
+ +
+
+pygame.key.get_mods()¶
+
+
determine which modifier keys are being held
+
get_mods() -> int
+
+

Returns a single integer representing a bitmask of all the modifier keys +being held. Using bitwise operators you can test if specific +modifier keys are pressed.

+
+ +
+
+pygame.key.set_mods()¶
+
+
temporarily set which modifier keys are pressed
+
set_mods(int) -> None
+
+

Create a bitmask of the modifier key constants +you want to impose on your program.

+
+ +
+
+pygame.key.set_repeat()¶
+
+
control how held keys are repeated
+
set_repeat() -> None
+
set_repeat(delay) -> None
+
set_repeat(delay, interval) -> None
+
+

When the keyboard repeat is enabled, keys that are held down will generate +multiple pygame.KEYDOWN events. The delay parameter is the number of +milliseconds before the first repeated pygame.KEYDOWN event will be sent. +After that, another pygame.KEYDOWN event will be sent every interval +milliseconds. If a delay value is provided and an interval value is +not provided or is 0, then the interval will be set to the same value as +delay.

+

To disable key repeat call this function with no arguments or with delay +set to 0.

+

When pygame is initialized the key repeat is disabled.

+
+
Raises
+

ValueError -- if delay or interval is < 0

+
+
+
+

Changed in pygame 2.0.0: A ValueError is now raised (instead of a +pygame.error) if delay or interval is < 0.

+
+
+ +
+
+pygame.key.get_repeat()¶
+
+
see how held keys are repeated
+
get_repeat() -> (delay, interval)
+
+

Get the delay and interval keyboard repeat values. Refer to +pygame.key.set_repeat()control how held keys are repeated for a description of these values.

+
+

New in pygame 1.8.

+
+
+ +
+
+pygame.key.name()¶
+
+
get the name of a key identifier
+
name(key) -> string
+
+

Get the descriptive name of the button from a keyboard button id constant.

+
+ +
+
+pygame.key.key_code()¶
+
+
get the key identifier from a key name
+
key_code(name=string) -> int
+
+

Get the key identifier code from the descriptive name of the key. This +returns an integer matching one of the K_* keycodes. For example:

+
>>> pygame.key.key_code("return") == pygame.K_RETURN
+True
+>>> pygame.key.key_code("0") == pygame.K_0
+True
+>>> pygame.key.key_code("space") == pygame.K_SPACE
+True
+
+
+
+
Raises
+
    +
  • ValueError -- if the key name is not known.

  • +
  • NotImplementedError -- if used with SDL 1.

  • +
+
+
+
+

New in pygame 2.0.0.

+
+
+ +
+
+pygame.key.start_text_input()¶
+
+
start handling Unicode text input events
+
start_text_input() -> None
+
+

Start receiving pygame.TEXTEDITING and pygame.TEXTINPUT +events. If applicable, show the on-screen keyboard or IME editor.

+

For many languages, key presses will automatically generate a +corresponding pygame.TEXTINPUT event. Special keys like +escape or function keys, and certain key combinations will not +generate pygame.TEXTINPUT events.

+

In other languages, entering a single symbol may require multiple +key presses, or a language-specific user interface. In this case, +pygame.TEXTINPUT events are preferable to pygame.KEYDOWN +events for text input.

+

A pygame.TEXTEDITING event is received when an IME composition +is started or changed. It contains the composition text, length, +and editing start position within the composition (attributes +text, length, and start, respectively). +When the composition is committed (or non-IME input is received), +a pygame.TEXTINPUT event is generated.

+

Text input events handling is on by default.

+
+

New in pygame 2.0.0.

+
+
+ +
+
+pygame.key.stop_text_input()¶
+
+
stop handling Unicode text input events
+
stop_text_input() -> None
+
+

Stop receiving pygame.TEXTEDITING and pygame.TEXTINPUT +events. If an on-screen keyboard or IME editor was shown with +pygame.key.start_text_input(), hide it again.

+

Text input events handling is on by default.

+

To avoid triggering the IME editor or the on-screen keyboard +when the user is holding down a key during gameplay, text input +should be disabled once text entry is finished, or when the user +clicks outside of a text box.

+
+

New in pygame 2.0.0.

+
+
+ +
+
+pygame.key.set_text_input_rect()¶
+
+
controls the position of the candidate list
+
set_text_input_rect(Rect) -> None
+
+

This sets the rectangle used for typing with an IME. +It controls where the candidate list will open, if supported.

+
+

New in pygame 2.0.0.

+
+
+ +
+ +
+ + +

+
+Edit on GitHub +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/ref/locals.html b/venv/Lib/site-packages/pygame/docs/generated/ref/locals.html new file mode 100644 index 0000000..baa5f8e --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/ref/locals.html @@ -0,0 +1,161 @@ + + + + + + + + + pygame.locals — pygame v2.1.2 documentation + + + + + + + + + + + + + +
+ +
+ + + + + +
+
+ +
+
+ +
+
+
+pygame.locals
+
+
pygame constants
+
+

This module contains various constants used by pygame. Its contents are +automatically placed in the pygame module namespace. However, an application +can use pygame.locals to include only the pygame constants with a from +pygame.locals import *.

+

Detailed descriptions of the various constants can be found throughout the +pygame documentation. Here are the locations of some of them.

+
+
+
+
+ +
+ + +

+
+Edit on GitHub +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/ref/mask.html b/venv/Lib/site-packages/pygame/docs/generated/ref/mask.html new file mode 100644 index 0000000..88e1219 --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/ref/mask.html @@ -0,0 +1,1123 @@ + + + + + + + + + pygame.mask — pygame v2.1.2 documentation + + + + + + + + + + + + + +
+ +
+ + + + + +
+
+ +
+
+ +
+
+
+pygame.mask
+
+
pygame module for image masks.
+
+ +++++ + + + + + + + + + + + + + + +
+—Creates a Mask from the given surface
+—Creates a mask by thresholding Surfaces
+—pygame object for representing 2D bitmasks
+

Useful for fast pixel perfect collision detection. A mask uses 1 bit per-pixel +to store which parts collide.

+
+

New in pygame 1.8.

+
+
+

Changed in pygame 2.0.2: Mask functions now support keyword arguments.

+
+
+

Changed in pygame 2.0.2: Mask functions that take positions or offsets now +support pygame.math.Vector2a 2-Dimensional Vector arguments.

+
+
+
+pygame.mask.from_surface()¶
+
+
Creates a Mask from the given surface
+
from_surface(surface) -> Mask
+
from_surface(surface, threshold=127) -> Mask
+
+

Creates a Mask object from the given surface by setting all the +opaque pixels and not setting the transparent pixels.

+

If the surface uses a color-key, then it is used to decide which bits in +the resulting mask are set. All the pixels that are not equal to the +color-key are set and the pixels equal to the color-key are not set.

+

If a color-key is not used, then the alpha value of each pixel is used to +decide which bits in the resulting mask are set. All the pixels that have an +alpha value greater than the threshold parameter are set and the +pixels with an alpha value less than or equal to the threshold are +not set.

+
+
Parameters
+
    +
  • surface (Surface) -- the surface to create the mask from

  • +
  • threshold (int) -- (optional) the alpha threshold (default is 127) to +compare with each surface pixel's alpha value, if the surface is +color-keyed this parameter is ignored

  • +
+
+
Returns
+

a newly created Mask object from the given surface

+
+
Return type
+

Mask

+
+
+
+

Note

+

This function is used to create the masks for +pygame.sprite.collide_mask()Collision detection between two sprites, using masks..

+
+
+ +
+
+pygame.mask.from_threshold()¶
+
+
Creates a mask by thresholding Surfaces
+
from_threshold(surface, color) -> Mask
+
from_threshold(surface, color, threshold=(0, 0, 0, 255), othersurface=None, palette_colors=1) -> Mask
+
+

This is a more featureful method of getting a Mask from a surface.

+

If the optional othersurface is not used, all the pixels within the +threshold of the color parameter are set in the resulting mask.

+

If the optional othersurface is used, every pixel in the first surface +that is within the threshold of the corresponding pixel in +othersurface is set in the resulting mask.

+
+
Parameters
+
    +
  • surface (Surface) -- the surface to create the mask from

  • +
  • color (Color or int or tuple(int, int, int, [int]) or list[int, int, int, [int]]) -- color used to check if the surface's pixels are within the +given threshold range, this parameter is ignored if the optional +othersurface parameter is supplied

  • +
  • threshold (Color or int or tuple(int, int, int, [int]) or list[int, int, int, [int]]) -- (optional) the threshold range used to check the difference +between two colors (default is (0, 0, 0, 255))

  • +
  • othersurface (Surface) -- (optional) used to check whether the pixels of +the first surface are within the given threshold range of the pixels +from this surface (default is None)

  • +
  • palette_colors (int) -- (optional) indicates whether to use the palette +colors or not, a nonzero value causes the palette colors to be used and a +0 causes them not to be used (default is 1)

  • +
+
+
Returns
+

a newly created Mask object from the given surface

+
+
Return type
+

Mask

+
+
+
+ +
+
+pygame.mask.Mask¶
+
+
pygame object for representing 2D bitmasks
+
Mask(size=(width, height)) -> Mask
+
Mask(size=(width, height), fill=False) -> Mask
+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+—Returns a new copy of the mask
+—Returns the size of the mask
+—Returns a Rect based on the size of the mask
+—Gets the bit at the given position
+—Sets the bit at the given position
+—Returns the point of intersection
+—Returns the number of overlapping set bits
+—Returns a mask of the overlapping set bits
+—Sets all bits to 1
+—Sets all bits to 0
+—Flips all the bits
+—Resizes a mask
+—Draws a mask onto another
+—Erases a mask from another
+—Returns the number of set bits
+—Returns the centroid of the set bits
+—Returns the orientation of the set bits
+—Returns a list of points outlining an object
+—Returns the convolution of this mask with another mask
+—Returns a mask containing a connected component
+—Returns a list of masks of connected components
+—Returns a list of bounding rects of connected components
+—Returns a surface with the mask drawn on it
+

A Mask object is used to represent a 2D bitmask. Each bit in +the mask represents a pixel. 1 is used to indicate a set bit and 0 is used +to indicate an unset bit. Set bits in a mask can be used to detect collisions +with other masks and their set bits.

+

A filled mask has all of its bits set to 1, conversely an +unfilled/cleared/empty mask has all of its bits set to 0. Masks can be +created unfilled (default) or filled by using the fill parameter. Masks +can also be cleared or filled using the pygame.mask.Mask.clear()Sets all bits to 0 and +pygame.mask.Mask.fill()Sets all bits to 1 methods respectively.

+

A mask's coordinates start in the top left corner at (0, 0) just like +pygame.Surfacepygame object for representing images. Individual bits can be accessed using the +pygame.mask.Mask.get_at()Gets the bit at the given position and pygame.mask.Mask.set_at()Sets the bit at the given position +methods.

+

The methods overlap(), overlap_area(), overlap_mask(), +draw(), erase(), and convolve() use an offset parameter +to indicate the offset of another mask's top left corner from the calling +mask's top left corner. The calling mask's top left corner is considered to +be the origin (0, 0). Offsets are a sequence of two values +(x_offset, y_offset). Positive and negative offset values are supported.

+
           0 to x (x_offset)
+           :    :
+   0 ..... +----:---------+
+   to      |    :         |
+   y .......... +-----------+
+(y_offset) |    | othermask |
+           |    +-----------+
+           | calling_mask |
+           +--------------+
+
+
+
+
Parameters
+
    +
  • size -- the dimensions of the mask (width and height)

  • +
  • fill (bool) -- (optional) create an unfilled mask (default: False) or +filled mask (True)

  • +
+
+
Returns
+

a newly created Mask object

+
+
Return type
+

Mask

+
+
+
+

Changed in pygame 2.0.0: Shallow copy support added. The Mask class supports the special +method __copy__() and shallow copying via copy.copy(mask).

+
+
+

Changed in pygame 2.0.0: Subclassing support added. The Mask class +can be used as a base class.

+
+
+

Changed in pygame 1.9.5: Added support for keyword arguments.

+
+
+

Changed in pygame 1.9.5: Added the optional keyword parameter fill.

+
+
+

Changed in pygame 1.9.5: Added support for masks with a width and/or a +height of 0.

+
+
+
+copy()¶
+
+
Returns a new copy of the mask
+
copy() -> Mask
+
+
+
Returns
+

a new copy of this mask, the new mask will have the same width, +height, and set/unset bits as the original

+
+
Return type
+

Mask

+
+
+
+

Note

+

If a mask subclass needs to copy any instance specific attributes +then it should override the __copy__() method. The overridden +__copy__() method needs to call super().__copy__() and then +copy the required data as in the following example code.

+
class SubMask(pygame.mask.Mask):
+    def __copy__(self):
+        new_mask = super().__copy__()
+        # Do any SubMask attribute copying here.
+        return new_mask
+
+
+
+
+

New in pygame 2.0.0.

+
+
+ +
+
+get_size()¶
+
+
Returns the size of the mask
+
get_size() -> (width, height)
+
+
+
Returns
+

the size of the mask, (width, height)

+
+
Return type
+

tuple(int, int)

+
+
+
+ +
+
+get_rect()¶
+
+
Returns a Rect based on the size of the mask
+
get_rect(**kwargs) -> Rect
+
+

Returns a new pygame.Rect()pygame object for storing rectangular coordinates object based on the size of this mask. +The rect's default position will be (0, 0) and its default width and +height will be the same as this mask's. The rect's attributes can be +altered via pygame.Rect()pygame object for storing rectangular coordinates attribute keyword arguments/values passed +into this method. As an example, a_mask.get_rect(center=(10, 5)) would +create a pygame.Rect()pygame object for storing rectangular coordinates based on the mask's size centered at the +given position.

+
+
Parameters
+

kwargs (dict) -- pygame.Rect()pygame object for storing rectangular coordinates attribute keyword arguments/values +that will be applied to the rect

+
+
Returns
+

a new pygame.Rect()pygame object for storing rectangular coordinates object based on the size of this mask +with any pygame.Rect()pygame object for storing rectangular coordinates attribute keyword arguments/values applied +to it

+
+
Return type
+

Rect

+
+
+
+

New in pygame 2.0.0.

+
+
+ +
+
+get_at()¶
+
+
Gets the bit at the given position
+
get_at(pos) -> int
+
+
+
Parameters
+

pos -- the position of the bit to get (x, y)

+
+
Returns
+

1 if the bit is set, 0 if the bit is not set

+
+
Return type
+

int

+
+
Raises
+

IndexError -- if the position is outside of the mask's bounds

+
+
+
+ +
+
+set_at()¶
+
+
Sets the bit at the given position
+
set_at(pos) -> None
+
set_at(pos, value=1) -> None
+
+
+
Parameters
+
    +
  • pos -- the position of the bit to set (x, y)

  • +
  • value (int) -- any nonzero int will set the bit to 1, 0 will set the +bit to 0 (default is 1)

  • +
+
+
Returns
+

None

+
+
Return type
+

NoneType

+
+
Raises
+

IndexError -- if the position is outside of the mask's bounds

+
+
+
+ +
+
+overlap()¶
+
+
Returns the point of intersection
+
overlap(other, offset) -> (x, y)
+
overlap(other, offset) -> None
+
+

Returns the first point of intersection encountered between this mask and +other. A point of intersection is 2 overlapping set bits.

+

The current algorithm searches the overlapping area in +sizeof(unsigned long int) * CHAR_BIT bit wide column blocks (the value +of sizeof(unsigned long int) * CHAR_BIT is platform dependent, for +clarity it will be referred to as W). Starting at the top left corner +it checks bits 0 to W - 1 of the first row ((0, 0) to +(W - 1, 0)) then continues to the next row ((0, 1) to +(W - 1, 1)). Once this entire column block is checked, it continues to +the next one (W to 2 * W - 1). This is repeated until it finds a +point of intersection or the entire overlapping area is checked.

+
+
Parameters
+
    +
  • other (Mask) -- the other mask to overlap with this mask

  • +
  • offset -- the offset of other from this mask, for more +details refer to the Mask offset notes

  • +
+
+
Returns
+

point of intersection or None if no intersection

+
+
Return type
+

tuple(int, int) or NoneType

+
+
+
+ +
+
+overlap_area()¶
+
+
Returns the number of overlapping set bits
+
overlap_area(other, offset) -> numbits
+
+

Returns the number of overlapping set bits between between this mask and +other.

+

This can be useful for collision detection. An approximate collision +normal can be found by calculating the gradient of the overlapping area +through the finite difference.

+
dx = mask.overlap_area(other, (x + 1, y)) - mask.overlap_area(other, (x - 1, y))
+dy = mask.overlap_area(other, (x, y + 1)) - mask.overlap_area(other, (x, y - 1))
+
+
+
+
Parameters
+
    +
  • other (Mask) -- the other mask to overlap with this mask

  • +
  • offset -- the offset of other from this mask, for more +details refer to the Mask offset notes

  • +
+
+
Returns
+

the number of overlapping set bits

+
+
Return type
+

int

+
+
+
+ +
+
+overlap_mask()¶
+
+
Returns a mask of the overlapping set bits
+
overlap_mask(other, offset) -> Mask
+
+

Returns a Mask, the same size as this mask, containing the +overlapping set bits between this mask and other.

+
+
Parameters
+
    +
  • other (Mask) -- the other mask to overlap with this mask

  • +
  • offset -- the offset of other from this mask, for more +details refer to the Mask offset notes

  • +
+
+
Returns
+

a newly created Mask with the overlapping bits set

+
+
Return type
+

Mask

+
+
+
+ +
+
+fill()¶
+
+
Sets all bits to 1
+
fill() -> None
+
+

Sets all bits in the mask to 1.

+
+
Returns
+

None

+
+
Return type
+

NoneType

+
+
+
+ +
+
+clear()¶
+
+
Sets all bits to 0
+
clear() -> None
+
+

Sets all bits in the mask to 0.

+
+
Returns
+

None

+
+
Return type
+

NoneType

+
+
+
+ +
+
+invert()¶
+
+
Flips all the bits
+
invert() -> None
+
+

Flips all of the bits in the mask. All the set bits are cleared to 0 and +all the unset bits are set to 1.

+
+
Returns
+

None

+
+
Return type
+

NoneType

+
+
+
+ +
+
+scale()¶
+
+
Resizes a mask
+
scale((width, height)) -> Mask
+
+

Creates a new Mask of the requested size with its bits scaled +from this mask.

+
+
Parameters
+

size -- the width and height (size) of the mask to create

+
+
Returns
+

a new Mask object with its bits scaled from this mask

+
+
Return type
+

Mask

+
+
Raises
+

ValueError -- if width < 0 or height < 0

+
+
+
+ +
+
+draw()¶
+
+
Draws a mask onto another
+
draw(other, offset) -> None
+
+

Performs a bitwise OR, drawing othermask onto this mask.

+
+
Parameters
+
    +
  • other (Mask) -- the mask to draw onto this mask

  • +
  • offset -- the offset of other from this mask, for more +details refer to the Mask offset notes

  • +
+
+
Returns
+

None

+
+
Return type
+

NoneType

+
+
+
+ +
+
+erase()¶
+
+
Erases a mask from another
+
erase(other, offset) -> None
+
+

Erases (clears) all bits set in other from this mask.

+
+
Parameters
+
    +
  • other (Mask) -- the mask to erase from this mask

  • +
  • offset -- the offset of other from this mask, for more +details refer to the Mask offset notes

  • +
+
+
Returns
+

None

+
+
Return type
+

NoneType

+
+
+
+ +
+
+count()¶
+
+
Returns the number of set bits
+
count() -> bits
+
+
+
Returns
+

the number of set bits in the mask

+
+
Return type
+

int

+
+
+
+ +
+
+centroid()¶
+
+
Returns the centroid of the set bits
+
centroid() -> (x, y)
+
+

Finds the centroid (the center mass of the set bits) for this mask.

+
+
Returns
+

a coordinate tuple indicating the centroid of the mask, it will +return (0, 0) if the mask has no bits set

+
+
Return type
+

tuple(int, int)

+
+
+
+ +
+
+angle()¶
+
+
Returns the orientation of the set bits
+
angle() -> theta
+
+

Finds the approximate orientation (from -90 to 90 degrees) of the set bits +in the mask. This works best if performed on a mask with only one +connected component.

+
+
Returns
+

the orientation of the set bits in the mask, it will return +0.0 if the mask has no bits set

+
+
Return type
+

float

+
+
+
+

Note

+

See connected_component() for details on how a connected +component is calculated.

+
+
+ +
+
+outline()¶
+
+
Returns a list of points outlining an object
+
outline() -> [(x, y), ...]
+
outline(every=1) -> [(x, y), ...]
+
+

Returns a list of points of the outline of the first connected component +encountered in the mask. To find a connected component, the mask is +searched per row (left to right) starting in the top left corner.

+

The every optional parameter skips set bits in the outline. For +example, setting it to 10 would return a list of every 10th set bit in the +outline.

+
+
Parameters
+

every (int) -- (optional) indicates the number of bits to skip over in +the outline (default is 1)

+
+
Returns
+

a list of points outlining the first connected component +encountered, an empty list is returned if the mask has no bits set

+
+
Return type
+

list[tuple(int, int)]

+
+
+
+

Note

+

See connected_component() for details on how a connected +component is calculated.

+
+
+ +
+
+convolve()¶
+
+
Returns the convolution of this mask with another mask
+
convolve(other) -> Mask
+
convolve(other, output=None, offset=(0, 0)) -> Mask
+
+

Convolve this mask with the given other Mask.

+
+
Parameters
+
    +
  • other (Mask) -- mask to convolve this mask with

  • +
  • output (Mask or NoneType) -- (optional) mask for output (default is None)

  • +
  • offset -- the offset of other from this mask, (default is +(0, 0))

  • +
+
+
Returns
+

a Mask with the (i - offset[0], j - offset[1]) bit +set, if shifting other (such that its bottom right corner is at +(i, j)) causes it to overlap with this mask

+

If an output Mask is specified, the output is drawn onto it and +it is returned. Otherwise a mask of size (MAX(0, width + other mask's +width - 1), MAX(0, height + other mask's height - 1)) is created and +returned.

+

+
+
Return type
+

Mask

+
+
+
+ +
+
+connected_component()¶
+
+
Returns a mask containing a connected component
+
connected_component() -> Mask
+
connected_component(pos) -> Mask
+
+

A connected component is a group (1 or more) of connected set bits +(orthogonally and diagonally). The SAUF algorithm, which checks 8 point +connectivity, is used to find a connected component in the mask.

+

By default this method will return a Mask containing the largest +connected component in the mask. Optionally, a bit coordinate can be +specified and the connected component containing it will be returned. If +the bit at the given location is not set, the returned Mask will +be empty (no bits set).

+
+
Parameters
+

pos -- (optional) selects the connected component that contains the +bit at this position

+
+
Returns
+

a Mask object (same size as this mask) with the largest +connected component from this mask, if this mask has no bits set then +an empty mask will be returned

+

If the pos parameter is provided then the mask returned will have +the connected component that contains this position. An empty mask will +be returned if the pos parameter selects an unset bit.

+

+
+
Return type
+

Mask

+
+
Raises
+

IndexError -- if the optional pos parameter is outside of the +mask's bounds

+
+
+
+ +
+
+connected_components()¶
+
+
Returns a list of masks of connected components
+
connected_components() -> [Mask, ...]
+
connected_components(minimum=0) -> [Mask, ...]
+
+

Provides a list containing a Mask object for each connected +component.

+
+
Parameters
+

minimum (int) -- (optional) indicates the minimum number of bits (to +filter out noise) per connected component (default is 0, which equates +to no minimum and is equivalent to setting it to 1, as a connected +component must have at least 1 bit set)

+
+
Returns
+

a list containing a Mask object for each connected +component, an empty list is returned if the mask has no bits set

+
+
Return type
+

list[Mask]

+
+
+
+

Note

+

See connected_component() for details on how a connected +component is calculated.

+
+
+ +
+
+get_bounding_rects()¶
+
+
Returns a list of bounding rects of connected components
+
get_bounding_rects() -> [Rect, ...]
+
+

Provides a list containing a bounding rect for each connected component.

+
+
Returns
+

a list containing a bounding rect for each connected component, +an empty list is returned if the mask has no bits set

+
+
Return type
+

list[Rect]

+
+
+
+

Note

+

See connected_component() for details on how a connected +component is calculated.

+
+
+ +
+
+to_surface()¶
+
+
Returns a surface with the mask drawn on it
+
to_surface() -> Surface
+
to_surface(surface=None, setsurface=None, unsetsurface=None, setcolor=(255, 255, 255, 255), unsetcolor=(0, 0, 0, 255), dest=(0, 0)) -> Surface
+
+

Draws this mask on the given surface. Set bits (bits set to 1) and unset +bits (bits set to 0) can be drawn onto a surface.

+
+
Parameters
+
    +
  • surface (Surface or None) -- (optional) Surface to draw mask onto, if no surface is +provided one will be created (default is None, which will cause a +surface with the parameters +Surface(size=mask.get_size(), flags=SRCALPHA, depth=32) to be +created, drawn on, and returned)

  • +
  • setsurface (Surface or None) -- (optional) use this surface's color values to draw +set bits (default is None), if this surface is smaller than the +mask any bits outside its bounds will use the setcolor value

  • +
  • unsetsurface (Surface or None) -- (optional) use this surface's color values to draw +unset bits (default is None), if this surface is smaller than the +mask any bits outside its bounds will use the unsetcolor value

  • +
  • setcolor (Color or str or int or tuple(int, int, int, [int]) or +list(int, int, int, [int]) or None) -- (optional) color to draw set bits (default is +(255, 255, 255, 255), white), use None to skip drawing the set +bits, the setsurface parameter (if set) will takes precedence over +this parameter

  • +
  • unsetcolor (Color or str or int or tuple(int, int, int, [int]) or +list(int, int, int, [int]) or None) -- (optional) color to draw unset bits (default is +(0, 0, 0, 255), black), use None to skip drawing the unset +bits, the unsetsurface parameter (if set) will takes precedence +over this parameter

  • +
  • dest (Rect or tuple(int, int) or list(int, int) or Vector2(int, int)) -- (optional) surface destination of where to position the +topleft corner of the mask being drawn (default is (0, 0)), if a +Rect is used as the dest parameter, its x and y attributes +will be used as the destination, NOTE1: rects with a negative width +or height value will not be normalized before using their x and +y values, NOTE2: this destination value is only used to +position the mask on the surface, it does not offset the setsurface +and unsetsurface from the mask, they are always aligned with the +mask (i.e. position (0, 0) on the mask always corresponds to +position (0, 0) on the setsurface and unsetsurface)

  • +
+
+
Returns
+

the surface parameter (or a newly created surface if no +surface parameter was provided) with this mask drawn on it

+
+
Return type
+

Surface

+
+
Raises
+

ValueError -- if the setsurface parameter or unsetsurface +parameter does not have the same format (bytesize/bitsize/alpha) as +the surface parameter

+
+
+
+

Note

+

To skip drawing the set bits, both setsurface and setcolor must +be None. The setsurface parameter defaults to None, but +setcolor defaults to a color value and therefore must be set to +None.

+
+
+

Note

+

To skip drawing the unset bits, both unsetsurface and +unsetcolor must be None. The unsetsurface parameter +defaults to None, but unsetcolor defaults to a color value and +therefore must be set to None.

+
+
+

New in pygame 2.0.0.

+
+
+ +
+ +
+ +
+ + +

+
+Edit on GitHub +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/ref/math.html b/venv/Lib/site-packages/pygame/docs/generated/ref/math.html new file mode 100644 index 0000000..fe824c5 --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/ref/math.html @@ -0,0 +1,1509 @@ + + + + + + + + + pygame.math — pygame v2.1.2 documentation + + + + + + + + + + + + + +
+ +
+ + + + + +
+
+ +
+
+ +
+
+
+pygame.math
+
+
pygame module for vector classes
+
+ +++++ + + + + + + + + + + +
+—a 2-Dimensional Vector
+—a 3-Dimensional Vector
+

The pygame math module currently provides Vector classes in two and three +dimensions, Vector2 and Vector3 respectively.

+

They support the following numerical operations: vec+vec, vec-vec, +vec*number, number*vec, vec/number, vec//number, vec+=vec, +vec-=vec, vec*=number, vec/=number, vec//=number.

+

All these operations will be performed elementwise. +In addition vec*vec will perform a scalar-product (a.k.a. dot-product). +If you want to multiply every element from vector v with every element from +vector w you can use the elementwise method: v.elementwise() * w

+

The coordinates of a vector can be retrieved or set using attributes or +subscripts

+
v = pygame.Vector3()
+
+v.x = 5
+v[1] = 2 * v.x
+print(v[1]) # 10
+
+v.x == v[0]
+v.y == v[1]
+v.z == v[2]
+
+
+

Multiple coordinates can be set using slices or swizzling

+
v = pygame.Vector2()
+v.xy = 1, 2
+v[:] = 1, 2
+
+
+
+

New in pygame 1.9.2pre.

+
+
+

Changed in pygame 1.9.4: Removed experimental notice.

+
+
+

Changed in pygame 1.9.4: Allow scalar construction like GLSL Vector2(2) == Vector2(2.0, 2.0)

+
+
+

Changed in pygame 1.9.4: pygame.mathpygame module for vector classes required import. More convenient pygame.Vector2 and pygame.Vector3.

+
+
+
+pygame.math.Vector2¶
+
+
a 2-Dimensional Vector
+
Vector2() -> Vector2
+
Vector2(int) -> Vector2
+
Vector2(float) -> Vector2
+
Vector2(Vector2) -> Vector2
+
Vector2(x, y) -> Vector2
+
Vector2((x, y)) -> Vector2
+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+—calculates the dot- or scalar-product with the other vector
+—calculates the cross- or vector-product
+—returns the Euclidean magnitude of the vector.
+—returns the squared magnitude of the vector.
+—returns the Euclidean length of the vector.
+—returns the squared Euclidean length of the vector.
+—returns a vector with the same direction but length 1.
+—normalizes the vector in place so that its length is 1.
+—tests if the vector is normalized i.e. has length == 1.
+—scales the vector to a given length.
+—returns a vector reflected of a given normal.
+—reflect the vector of a given normal in place.
+—calculates the Euclidean distance to a given vector.
+—calculates the squared Euclidean distance to a given vector.
+—returns a linear interpolation to the given vector.
+—returns a spherical interpolation to the given vector.
+—The next operation will be performed elementwise.
+—rotates a vector by a given angle in degrees.
+—rotates a vector by a given angle in radians.
+—rotates the vector by a given angle in degrees in place.
+—rotates the vector by a given angle in radians in place.
+—rotates the vector by a given angle in radians in place.
+—calculates the angle to a given vector in degrees.
+—returns a tuple with radial distance and azimuthal angle.
+—Sets x and y from a polar coordinates tuple.
+—projects a vector onto another.
+—Returns a copy of itself.
+—Sets the coordinates of the vector.
+

Some general information about the Vector2 class.

+
+
+dot()¶
+
+
calculates the dot- or scalar-product with the other vector
+
dot(Vector2) -> float
+
+
+ +
+
+cross()¶
+
+
calculates the cross- or vector-product
+
cross(Vector2) -> Vector2
+
+

calculates the third component of the cross-product.

+
+ +
+
+magnitude()¶
+
+
returns the Euclidean magnitude of the vector.
+
magnitude() -> float
+
+

calculates the magnitude of the vector which follows from the +theorem: vec.magnitude() == math.sqrt(vec.x**2 + vec.y**2)

+
+ +
+
+magnitude_squared()¶
+
+
returns the squared magnitude of the vector.
+
magnitude_squared() -> float
+
+

calculates the magnitude of the vector which follows from the +theorem: vec.magnitude_squared() == vec.x**2 + vec.y**2. This +is faster than vec.magnitude() because it avoids the square root.

+
+ +
+
+length()¶
+
+
returns the Euclidean length of the vector.
+
length() -> float
+
+

calculates the Euclidean length of the vector which follows from the +Pythagorean theorem: vec.length() == math.sqrt(vec.x**2 + vec.y**2)

+
+ +
+
+length_squared()¶
+
+
returns the squared Euclidean length of the vector.
+
length_squared() -> float
+
+

calculates the Euclidean length of the vector which follows from the +Pythagorean theorem: vec.length_squared() == vec.x**2 + vec.y**2. +This is faster than vec.length() because it avoids the square root.

+
+ +
+
+normalize()¶
+
+
returns a vector with the same direction but length 1.
+
normalize() -> Vector2
+
+

Returns a new vector that has length equal to 1 and the same +direction as self.

+
+ +
+
+normalize_ip()¶
+
+
normalizes the vector in place so that its length is 1.
+
normalize_ip() -> None
+
+

Normalizes the vector so that it has length equal to 1. +The direction of the vector is not changed.

+
+ +
+
+is_normalized()¶
+
+
tests if the vector is normalized i.e. has length == 1.
+
is_normalized() -> Bool
+
+

Returns True if the vector has length equal to 1. Otherwise +it returns False.

+
+ +
+
+scale_to_length()¶
+
+
scales the vector to a given length.
+
scale_to_length(float) -> None
+
+

Scales the vector so that it has the given length. The direction of the +vector is not changed. You can also scale to length 0. If the vector +is the zero vector (i.e. has length 0 thus no direction) a +ValueError is raised.

+
+ +
+
+reflect()¶
+
+
returns a vector reflected of a given normal.
+
reflect(Vector2) -> Vector2
+
+

Returns a new vector that points in the direction as if self would bounce +of a surface characterized by the given surface normal. The length of the +new vector is the same as self's.

+
+ +
+
+reflect_ip()¶
+
+
reflect the vector of a given normal in place.
+
reflect_ip(Vector2) -> None
+
+

Changes the direction of self as if it would have been reflected of a +surface with the given surface normal.

+
+ +
+
+distance_to()¶
+
+
calculates the Euclidean distance to a given vector.
+
distance_to(Vector2) -> float
+
+
+ +
+
+distance_squared_to()¶
+
+
calculates the squared Euclidean distance to a given vector.
+
distance_squared_to(Vector2) -> float
+
+
+ +
+
+lerp()¶
+
+
returns a linear interpolation to the given vector.
+
lerp(Vector2, float) -> Vector2
+
+

Returns a Vector which is a linear interpolation between self and the +given Vector. The second parameter determines how far between self and +other the result is going to be. It must be a value between 0 and 1 +where 0 means self and 1 means other will be returned.

+
+ +
+
+slerp()¶
+
+
returns a spherical interpolation to the given vector.
+
slerp(Vector2, float) -> Vector2
+
+

Calculates the spherical interpolation from self to the given Vector. The +second argument - often called t - must be in the range [-1, 1]. It +parametrizes where - in between the two vectors - the result should be. +If a negative value is given the interpolation will not take the +complement of the shortest path.

+
+ +
+
+elementwise()¶
+
+
The next operation will be performed elementwise.
+
elementwise() -> VectorElementwiseProxy
+
+

Applies the following operation to each element of the vector.

+
+ +
+
+rotate()¶
+
+
rotates a vector by a given angle in degrees.
+
rotate(angle) -> Vector2
+
+

Returns a vector which has the same length as self but is rotated +counterclockwise by the given angle in degrees. +(Note that due to pygame's inverted y coordinate system, the rotation +will look clockwise if displayed).

+
+ +
+
+rotate_rad()¶
+
+
rotates a vector by a given angle in radians.
+
rotate_rad(angle) -> Vector2
+
+

Returns a vector which has the same length as self but is rotated +counterclockwise by the given angle in radians. +(Note that due to pygame's inverted y coordinate system, the rotation +will look clockwise if displayed).

+
+

New in pygame 2.0.0.

+
+
+ +
+
+rotate_ip()¶
+
+
rotates the vector by a given angle in degrees in place.
+
rotate_ip(angle) -> None
+
+

Rotates the vector counterclockwise by the given angle in degrees. The +length of the vector is not changed. +(Note that due to pygame's inverted y coordinate system, the rotation +will look clockwise if displayed).

+
+ +
+
+rotate_ip_rad()¶
+
+
rotates the vector by a given angle in radians in place.
+
rotate_ip_rad(angle) -> None
+
+

DEPRECATED: Use rotate_rad_ip() instead.

+
+

New in pygame 2.0.0.

+
+
+

Deprecated since pygame 2.1.1.

+
+
+ +
+
+rotate_rad_ip()¶
+
+
rotates the vector by a given angle in radians in place.
+
rotate_rad_ip(angle) -> None
+
+

Rotates the vector counterclockwise by the given angle in radians. The +length of the vector is not changed. +(Note that due to pygame's inverted y coordinate system, the rotation +will look clockwise if displayed).

+
+

New in pygame 2.1.1.

+
+
+ +
+
+angle_to()¶
+
+
calculates the angle to a given vector in degrees.
+
angle_to(Vector2) -> float
+
+

Returns the angle between self and the given vector.

+
+ +
+
+as_polar()¶
+
+
returns a tuple with radial distance and azimuthal angle.
+
as_polar() -> (r, phi)
+
+

Returns a tuple (r, phi) where r is the radial distance, and phi +is the azimuthal angle.

+
+ +
+
+from_polar()¶
+
+
Sets x and y from a polar coordinates tuple.
+
from_polar((r, phi)) -> None
+
+

Sets x and y from a tuple (r, phi) where r is the radial distance, and +phi is the azimuthal angle.

+
+ +
+
+project()¶
+
+
projects a vector onto another.
+
project(Vector2) -> Vector2
+
+

Returns the projected vector. This is useful for collision detection in finding the components in a certain direction (e.g. in direction of the wall). +For a more detailed explanation see Wikipedia.

+
+

New in pygame 2.0.2.

+
+
+ +
+
+copy()¶
+
+
Returns a copy of itself.
+
copy() -> Vector2
+
+

Returns a new Vector2 having the same dimensions.

+
+

New in pygame 2.1.1.

+
+
+ +
+
+update()¶
+
+
Sets the coordinates of the vector.
+
update() -> None
+
update(int) -> None
+
update(float) -> None
+
update(Vector2) -> None
+
update(x, y) -> None
+
update((x, y)) -> None
+
+

Sets coordinates x and y in place.

+
+

New in pygame 1.9.5.

+
+
+ +
+ +
+
+pygame.math.Vector3¶
+
+
a 3-Dimensional Vector
+
Vector3() -> Vector3
+
Vector3(int) -> Vector3
+
Vector3(float) -> Vector3
+
Vector3(Vector3) -> Vector3
+
Vector3(x, y, z) -> Vector3
+
Vector3((x, y, z)) -> Vector3
+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+—calculates the dot- or scalar-product with the other vector
+—calculates the cross- or vector-product
+—returns the Euclidean magnitude of the vector.
+—returns the squared Euclidean magnitude of the vector.
+—returns the Euclidean length of the vector.
+—returns the squared Euclidean length of the vector.
+—returns a vector with the same direction but length 1.
+—normalizes the vector in place so that its length is 1.
+—tests if the vector is normalized i.e. has length == 1.
+—scales the vector to a given length.
+—returns a vector reflected of a given normal.
+—reflect the vector of a given normal in place.
+—calculates the Euclidean distance to a given vector.
+—calculates the squared Euclidean distance to a given vector.
+—returns a linear interpolation to the given vector.
+—returns a spherical interpolation to the given vector.
+—The next operation will be performed elementwise.
+—rotates a vector by a given angle in degrees.
+—rotates a vector by a given angle in radians.
+—rotates the vector by a given angle in degrees in place.
+—rotates the vector by a given angle in radians in place.
+—rotates the vector by a given angle in radians in place.
+—rotates a vector around the x-axis by the angle in degrees.
+—rotates a vector around the x-axis by the angle in radians.
+—rotates the vector around the x-axis by the angle in degrees in place.
+—rotates the vector around the x-axis by the angle in radians in place.
+—rotates the vector around the x-axis by the angle in radians in place.
+—rotates a vector around the y-axis by the angle in degrees.
+—rotates a vector around the y-axis by the angle in radians.
+—rotates the vector around the y-axis by the angle in degrees in place.
+—rotates the vector around the y-axis by the angle in radians in place.
+—rotates the vector around the y-axis by the angle in radians in place.
+—rotates a vector around the z-axis by the angle in degrees.
+—rotates a vector around the z-axis by the angle in radians.
+—rotates the vector around the z-axis by the angle in degrees in place.
+—rotates the vector around the z-axis by the angle in radians in place.
+—rotates the vector around the z-axis by the angle in radians in place.
+—calculates the angle to a given vector in degrees.
+—returns a tuple with radial distance, inclination and azimuthal angle.
+—Sets x, y and z from a spherical coordinates 3-tuple.
+—projects a vector onto another.
+—Returns a copy of itself.
+—Sets the coordinates of the vector.
+

Some general information about the Vector3 class.

+
+
+dot()¶
+
+
calculates the dot- or scalar-product with the other vector
+
dot(Vector3) -> float
+
+
+ +
+
+cross()¶
+
+
calculates the cross- or vector-product
+
cross(Vector3) -> Vector3
+
+

calculates the cross-product.

+
+ +
+
+magnitude()¶
+
+
returns the Euclidean magnitude of the vector.
+
magnitude() -> float
+
+

calculates the magnitude of the vector which follows from the +theorem: vec.magnitude() == math.sqrt(vec.x**2 + vec.y**2 + vec.z**2)

+
+ +
+
+magnitude_squared()¶
+
+
returns the squared Euclidean magnitude of the vector.
+
magnitude_squared() -> float
+
+

calculates the magnitude of the vector which follows from the +theorem: +vec.magnitude_squared() == vec.x**2 + vec.y**2 + vec.z**2. +This is faster than vec.magnitude() because it avoids the +square root.

+
+ +
+
+length()¶
+
+
returns the Euclidean length of the vector.
+
length() -> float
+
+

calculates the Euclidean length of the vector which follows from the +Pythagorean theorem: +vec.length() == math.sqrt(vec.x**2 + vec.y**2 + vec.z**2)

+
+ +
+
+length_squared()¶
+
+
returns the squared Euclidean length of the vector.
+
length_squared() -> float
+
+

calculates the Euclidean length of the vector which follows from the +Pythagorean theorem: +vec.length_squared() == vec.x**2 + vec.y**2 + vec.z**2. +This is faster than vec.length() because it avoids the square root.

+
+ +
+
+normalize()¶
+
+
returns a vector with the same direction but length 1.
+
normalize() -> Vector3
+
+

Returns a new vector that has length equal to 1 and the same +direction as self.

+
+ +
+
+normalize_ip()¶
+
+
normalizes the vector in place so that its length is 1.
+
normalize_ip() -> None
+
+

Normalizes the vector so that it has length equal to 1. The +direction of the vector is not changed.

+
+ +
+
+is_normalized()¶
+
+
tests if the vector is normalized i.e. has length == 1.
+
is_normalized() -> Bool
+
+

Returns True if the vector has length equal to 1. Otherwise it +returns False.

+
+ +
+
+scale_to_length()¶
+
+
scales the vector to a given length.
+
scale_to_length(float) -> None
+
+

Scales the vector so that it has the given length. The direction of the +vector is not changed. You can also scale to length 0. If the vector +is the zero vector (i.e. has length 0 thus no direction) a +ValueError is raised.

+
+ +
+
+reflect()¶
+
+
returns a vector reflected of a given normal.
+
reflect(Vector3) -> Vector3
+
+

Returns a new vector that points in the direction as if self would bounce +of a surface characterized by the given surface normal. The length of the +new vector is the same as self's.

+
+ +
+
+reflect_ip()¶
+
+
reflect the vector of a given normal in place.
+
reflect_ip(Vector3) -> None
+
+

Changes the direction of self as if it would have been reflected of a +surface with the given surface normal.

+
+ +
+
+distance_to()¶
+
+
calculates the Euclidean distance to a given vector.
+
distance_to(Vector3) -> float
+
+
+ +
+
+distance_squared_to()¶
+
+
calculates the squared Euclidean distance to a given vector.
+
distance_squared_to(Vector3) -> float
+
+
+ +
+
+lerp()¶
+
+
returns a linear interpolation to the given vector.
+
lerp(Vector3, float) -> Vector3
+
+

Returns a Vector which is a linear interpolation between self and the +given Vector. The second parameter determines how far between self an +other the result is going to be. It must be a value between 0 and +1, where 0 means self and 1 means other will be returned.

+
+ +
+
+slerp()¶
+
+
returns a spherical interpolation to the given vector.
+
slerp(Vector3, float) -> Vector3
+
+

Calculates the spherical interpolation from self to the given Vector. The +second argument - often called t - must be in the range [-1, 1]. It +parametrizes where - in between the two vectors - the result should be. +If a negative value is given the interpolation will not take the +complement of the shortest path.

+
+ +
+
+elementwise()¶
+
+
The next operation will be performed elementwise.
+
elementwise() -> VectorElementwiseProxy
+
+

Applies the following operation to each element of the vector.

+
+ +
+
+rotate()¶
+
+
rotates a vector by a given angle in degrees.
+
rotate(angle, Vector3) -> Vector3
+
+

Returns a vector which has the same length as self but is rotated +counterclockwise by the given angle in degrees around the given axis. +(Note that due to pygame's inverted y coordinate system, the rotation +will look clockwise if displayed).

+
+ +
+
+rotate_rad()¶
+
+
rotates a vector by a given angle in radians.
+
rotate_rad(angle, Vector3) -> Vector3
+
+

Returns a vector which has the same length as self but is rotated +counterclockwise by the given angle in radians around the given axis. +(Note that due to pygame's inverted y coordinate system, the rotation +will look clockwise if displayed).

+
+

New in pygame 2.0.0.

+
+
+ +
+
+rotate_ip()¶
+
+
rotates the vector by a given angle in degrees in place.
+
rotate_ip(angle, Vector3) -> None
+
+

Rotates the vector counterclockwise around the given axis by the given +angle in degrees. The length of the vector is not changed. +(Note that due to pygame's inverted y coordinate system, the rotation +will look clockwise if displayed).

+
+ +
+
+rotate_ip_rad()¶
+
+
rotates the vector by a given angle in radians in place.
+
rotate_ip_rad(angle, Vector3) -> None
+
+

DEPRECATED: Use rotate_rad_ip() instead.

+
+

New in pygame 2.0.0.

+
+
+

Deprecated since pygame 2.1.1.

+
+
+ +
+
+rotate_rad_ip()¶
+
+
rotates the vector by a given angle in radians in place.
+
rotate_rad_ip(angle, Vector3) -> None
+
+

Rotates the vector counterclockwise around the given axis by the given +angle in radians. The length of the vector is not changed. +(Note that due to pygame's inverted y coordinate system, the rotation +will look clockwise if displayed).

+
+

New in pygame 2.1.1.

+
+
+ +
+
+rotate_x()¶
+
+
rotates a vector around the x-axis by the angle in degrees.
+
rotate_x(angle) -> Vector3
+
+

Returns a vector which has the same length as self but is rotated +counterclockwise around the x-axis by the given angle in degrees. +(Note that due to pygame's inverted y coordinate system, the rotation +will look clockwise if displayed).

+
+ +
+
+rotate_x_rad()¶
+
+
rotates a vector around the x-axis by the angle in radians.
+
rotate_x_rad(angle) -> Vector3
+
+

Returns a vector which has the same length as self but is rotated +counterclockwise around the x-axis by the given angle in radians. +(Note that due to pygame's inverted y coordinate system, the rotation +will look clockwise if displayed).

+
+

New in pygame 2.0.0.

+
+
+ +
+
+rotate_x_ip()¶
+
+
rotates the vector around the x-axis by the angle in degrees in place.
+
rotate_x_ip(angle) -> None
+
+

Rotates the vector counterclockwise around the x-axis by the given angle +in degrees. The length of the vector is not changed. +(Note that due to pygame's inverted y coordinate system, the rotation +will look clockwise if displayed).

+
+ +
+
+rotate_x_ip_rad()¶
+
+
rotates the vector around the x-axis by the angle in radians in place.
+
rotate_x_ip_rad(angle) -> None
+
+

DEPRECATED: Use rotate_x_rad_ip() instead.

+
+

New in pygame 2.0.0.

+
+
+

Deprecated since pygame 2.1.1.

+
+
+ +
+
+rotate_x_rad_ip()¶
+
+
rotates the vector around the x-axis by the angle in radians in place.
+
rotate_x_rad_ip(angle) -> None
+
+

Rotates the vector counterclockwise around the x-axis by the given angle +in radians. The length of the vector is not changed. +(Note that due to pygame's inverted y coordinate system, the rotation +will look clockwise if displayed).

+
+

New in pygame 2.1.1.

+
+
+ +
+
+rotate_y()¶
+
+
rotates a vector around the y-axis by the angle in degrees.
+
rotate_y(angle) -> Vector3
+
+

Returns a vector which has the same length as self but is rotated +counterclockwise around the y-axis by the given angle in degrees. +(Note that due to pygame's inverted y coordinate system, the rotation +will look clockwise if displayed).

+
+ +
+
+rotate_y_rad()¶
+
+
rotates a vector around the y-axis by the angle in radians.
+
rotate_y_rad(angle) -> Vector3
+
+

Returns a vector which has the same length as self but is rotated +counterclockwise around the y-axis by the given angle in radians. +(Note that due to pygame's inverted y coordinate system, the rotation +will look clockwise if displayed).

+
+

New in pygame 2.0.0.

+
+
+ +
+
+rotate_y_ip()¶
+
+
rotates the vector around the y-axis by the angle in degrees in place.
+
rotate_y_ip(angle) -> None
+
+

Rotates the vector counterclockwise around the y-axis by the given angle +in degrees. The length of the vector is not changed. +(Note that due to pygame's inverted y coordinate system, the rotation +will look clockwise if displayed).

+
+ +
+
+rotate_y_ip_rad()¶
+
+
rotates the vector around the y-axis by the angle in radians in place.
+
rotate_y_ip_rad(angle) -> None
+
+

DEPRECATED: Use rotate_y_rad_ip() instead.

+
+

New in pygame 2.0.0.

+
+
+

Deprecated since pygame 2.1.1.

+
+
+ +
+
+rotate_y_rad_ip()¶
+
+
rotates the vector around the y-axis by the angle in radians in place.
+
rotate_y_rad_ip(angle) -> None
+
+

Rotates the vector counterclockwise around the y-axis by the given angle +in radians. The length of the vector is not changed. +(Note that due to pygame's inverted y coordinate system, the rotation +will look clockwise if displayed).

+
+

New in pygame 2.1.1.

+
+
+ +
+
+rotate_z()¶
+
+
rotates a vector around the z-axis by the angle in degrees.
+
rotate_z(angle) -> Vector3
+
+

Returns a vector which has the same length as self but is rotated +counterclockwise around the z-axis by the given angle in degrees. +(Note that due to pygame's inverted y coordinate system, the rotation +will look clockwise if displayed).

+
+ +
+
+rotate_z_rad()¶
+
+
rotates a vector around the z-axis by the angle in radians.
+
rotate_z_rad(angle) -> Vector3
+
+

Returns a vector which has the same length as self but is rotated +counterclockwise around the z-axis by the given angle in radians. +(Note that due to pygame's inverted y coordinate system, the rotation +will look clockwise if displayed).

+
+

New in pygame 2.0.0.

+
+
+ +
+
+rotate_z_ip()¶
+
+
rotates the vector around the z-axis by the angle in degrees in place.
+
rotate_z_ip(angle) -> None
+
+

Rotates the vector counterclockwise around the z-axis by the given angle +in degrees. The length of the vector is not changed. +(Note that due to pygame's inverted y coordinate system, the rotation +will look clockwise if displayed).

+
+ +
+
+rotate_z_ip_rad()¶
+
+
rotates the vector around the z-axis by the angle in radians in place.
+
rotate_z_ip_rad(angle) -> None
+
+

DEPRECATED: Use rotate_z_rad_ip() instead.

+
+

Deprecated since pygame 2.1.1.

+
+
+ +
+
+rotate_z_rad_ip()¶
+
+
rotates the vector around the z-axis by the angle in radians in place.
+
rotate_z_rad_ip(angle) -> None
+
+

Rotates the vector counterclockwise around the z-axis by the given angle +in radians. The length of the vector is not changed. +(Note that due to pygame's inverted y coordinate system, the rotation +will look clockwise if displayed).

+
+

New in pygame 2.1.1.

+
+
+ +
+
+angle_to()¶
+
+
calculates the angle to a given vector in degrees.
+
angle_to(Vector3) -> float
+
+

Returns the angle between self and the given vector.

+
+ +
+
+as_spherical()¶
+
+
returns a tuple with radial distance, inclination and azimuthal angle.
+
as_spherical() -> (r, theta, phi)
+
+

Returns a tuple (r, theta, phi) where r is the radial distance, theta is +the inclination angle and phi is the azimuthal angle.

+
+ +
+
+from_spherical()¶
+
+
Sets x, y and z from a spherical coordinates 3-tuple.
+
from_spherical((r, theta, phi)) -> None
+
+

Sets x, y and z from a tuple (r, theta, phi) where r is the radial +distance, theta is the inclination angle and phi is the azimuthal angle.

+
+ +
+
+project()¶
+
+
projects a vector onto another.
+
project(Vector3) -> Vector3
+
+

Returns the projected vector. This is useful for collision detection in finding the components in a certain direction (e.g. in direction of the wall). +For a more detailed explanation see Wikipedia.

+
+

New in pygame 2.0.2.

+
+
+ +
+
+copy()¶
+
+
Returns a copy of itself.
+
copy() -> Vector3
+
+

Returns a new Vector3 having the same dimensions.

+
+

New in pygame 2.1.1.

+
+
+ +
+
+update()¶
+
+
Sets the coordinates of the vector.
+
update() -> None
+
update(int) -> None
+
update(float) -> None
+
update(Vector3) -> None
+
update(x, y, z) -> None
+
update((x, y, z)) -> None
+
+

Sets coordinates x, y, and z in place.

+
+

New in pygame 1.9.5.

+
+
+ +
+ +
+ +
+ + +

+
+Edit on GitHub +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/ref/midi.html b/venv/Lib/site-packages/pygame/docs/generated/ref/midi.html new file mode 100644 index 0000000..de8cabe --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/ref/midi.html @@ -0,0 +1,845 @@ + + + + + + + + + pygame.midi — pygame v2.1.2 documentation + + + + + + + + + + + + + +
+ +
+ + + + + +
+
+ +
+
+ +
+
+
+pygame.midi
+
+
pygame module for interacting with midi input and output.
+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+—initialize the midi module
+—uninitialize the midi module
+—returns True if the midi module is currently initialized
+—Input is used to get midi input from midi devices.
+—Output is used to send midi to an output device
+—gets the number of devices.
+—gets default input device number
+—gets default output device number
+—returns information about a midi device
+—converts midi events to pygame events
+—returns the current time in ms of the PortMidi timer
+—Converts a frequency into a MIDI note. Rounds to the closest midi note.
+—Converts a midi note to a frequency.
+—Returns the Ansi Note name for a midi number.
+—exception that pygame.midi functions and classes can raise
+
+

New in pygame 1.9.0.

+
+

The midi module can send output to midi devices and get input from midi +devices. It can also list midi devices on the system.

+

The midi module supports real and virtual midi devices.

+

It uses the portmidi library. Is portable to which ever platforms portmidi +supports (currently Windows, Mac OS X, and Linux).

+

This uses pyportmidi for now, but may use its own bindings at some point in the +future. The pyportmidi bindings are included with pygame.

+
+

+
+
+

New in pygame 2.0.0.

+
+

These are pygame events (pygame.eventpygame module for interacting with events and queues) reserved for midi use. The +MIDIIN event is used by pygame.midi.midis2events()converts midi events to pygame events when converting +midi events to pygame events.

+
MIDIIN
+MIDIOUT
+
+
+
+

+
+
+
+pygame.midi.init()¶
+
+
initialize the midi module
+
init() -> None
+
+

Initializes the pygame.midipygame module for interacting with midi input and output. module. Must be called before using the +pygame.midipygame module for interacting with midi input and output. module.

+

It is safe to call this more than once.

+
+ +
+
+pygame.midi.quit()¶
+
+
uninitialize the midi module
+
quit() -> None
+
+

Uninitializes the pygame.midipygame module for interacting with midi input and output. module. If pygame.midi.init()initialize the midi module was +called to initialize the pygame.midipygame module for interacting with midi input and output. module, then this function will +be called automatically when your program exits.

+

It is safe to call this function more than once.

+
+ +
+
+pygame.midi.get_init()¶
+
+
returns True if the midi module is currently initialized
+
get_init() -> bool
+
+

Gets the initialization state of the pygame.midipygame module for interacting with midi input and output. module.

+
+
Returns
+

True if the pygame.midipygame module for interacting with midi input and output. module is currently initialized.

+
+
Return type
+

bool

+
+
+
+

New in pygame 1.9.5.

+
+
+ +
+
+pygame.midi.Input¶
+
+
Input is used to get midi input from midi devices.
+
Input(device_id) -> None
+
Input(device_id, buffer_size) -> None
+
+ +++++ + + + + + + + + + + + + + + +
+—closes a midi stream, flushing any pending buffers.
+—returns True if there's data, or False if not.
+—reads num_events midi events from the buffer.
+
+
Parameters
+
    +
  • device_id (int) -- midi device id

  • +
  • buffer_size (int) -- (optional) the number of input events to be buffered

  • +
+
+
+
+
+close()¶
+
+
closes a midi stream, flushing any pending buffers.
+
close() -> None
+
+

PortMidi attempts to close open streams when the application exits.

+
+

Note

+

This is particularly difficult under Windows.

+
+
+ +
+
+poll()¶
+
+
returns True if there's data, or False if not.
+
poll() -> bool
+
+

Used to indicate if any data exists.

+
+
Returns
+

True if there is data, False otherwise

+
+
Return type
+

bool

+
+
Raises
+

MidiException -- on error

+
+
+
+ +
+
+read()¶
+
+
reads num_events midi events from the buffer.
+
read(num_events) -> midi_event_list
+
+

Reads from the input buffer and gives back midi events.

+
+
Parameters
+

num_events (int) -- number of input events to read

+
+
Returns
+

the format for midi_event_list is +[[[status, data1, data2, data3], timestamp], ...]

+
+
Return type
+

list

+
+
+
+ +
+ +
+
+pygame.midi.Output¶
+
+
Output is used to send midi to an output device
+
Output(device_id) -> None
+
Output(device_id, latency=0) -> None
+
Output(device_id, buffer_size=256) -> None
+
Output(device_id, latency, buffer_size) -> None
+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+—terminates outgoing messages immediately
+—closes a midi stream, flushing any pending buffers.
+—turns a midi note off (note must be on)
+—turns a midi note on (note must be off)
+—select an instrument, with a value between 0 and 127
+—modify the pitch of a channel.
+—writes a list of midi data to the Output
+—writes up to 3 bytes of midi data to the Output
+—writes a timestamped system-exclusive midi message.
+

The buffer_size specifies the number of output events to be buffered +waiting for output. In some cases (see below) PortMidi does not buffer +output at all and merely passes data to a lower-level API, in which case +buffersize is ignored.

+

latency is the delay in milliseconds applied to timestamps to determine +when the output should actually occur. If latency is <<0, 0 is assumed.

+

If latency is zero, timestamps are ignored and all output is delivered +immediately. If latency is greater than zero, output is delayed until the +message timestamp plus the latency. In some cases, PortMidi can obtain +better timing than your application by passing timestamps along to the +device driver or hardware. Latency may also help you to synchronize midi +data to audio data by matching midi latency to the audio buffer latency.

+
+

Note

+

Time is measured relative to the time source indicated by time_proc. +Timestamps are absolute, not relative delays or offsets.

+
+
+
+abort()¶
+
+
terminates outgoing messages immediately
+
abort() -> None
+
+

The caller should immediately close the output port; this call may result +in transmission of a partial midi message. There is no abort for Midi +input because the user can simply ignore messages in the buffer and close +an input device at any time.

+
+ +
+
+close()¶
+
+
closes a midi stream, flushing any pending buffers.
+
close() -> None
+
+

PortMidi attempts to close open streams when the application exits.

+
+

Note

+

This is particularly difficult under Windows.

+
+
+ +
+
+note_off()¶
+
+
turns a midi note off (note must be on)
+
note_off(note, velocity=None, channel=0) -> None
+
+

Turn a note off in the output stream. The note must already be on for +this to work correctly.

+
+ +
+
+note_on()¶
+
+
turns a midi note on (note must be off)
+
note_on(note, velocity=None, channel=0) -> None
+
+

Turn a note on in the output stream. The note must already be off for +this to work correctly.

+
+ +
+
+set_instrument()¶
+
+
select an instrument, with a value between 0 and 127
+
set_instrument(instrument_id, channel=0) -> None
+
+

Select an instrument.

+
+ +
+
+pitch_bend()¶
+
+
modify the pitch of a channel.
+
set_instrument(value=0, channel=0) -> None
+
+

Adjust the pitch of a channel. The value is a signed integer +from -8192 to +8191. For example, 0 means "no change", +4096 is +typically a semitone higher, and -8192 is 1 whole tone lower (though +the musical range corresponding to the pitch bend range can also be +changed in some synthesizers).

+

If no value is given, the pitch bend is returned to "no change".

+
+

New in pygame 1.9.4.

+
+
+ +
+
+write()¶
+
+
writes a list of midi data to the Output
+
write(data) -> None
+
+

Writes series of MIDI information in the form of a list.

+
+
Parameters
+

data (list) -- data to write, the expected format is +[[[status, data1=0, data2=0, ...], timestamp], ...] +with the data# fields being optional

+
+
Raises
+

IndexError -- if more than 1024 elements in the data list

+
+
+

Example:

+
# Program change at time 20000 and 500ms later send note 65 with
+# velocity 100.
+write([[[0xc0, 0, 0], 20000], [[0x90, 60, 100], 20500]])
+
+
+
+

Note

+
    +
  • Timestamps will be ignored if latency = 0

  • +
  • To get a note to play immediately, send MIDI info with timestamp +read from function Time

  • +
  • Optional data fields: write([[[0xc0, 0, 0], 20000]]) is +equivalent to write([[[0xc0], 20000]])

  • +
+
+
+ +
+
+write_short()¶
+
+
writes up to 3 bytes of midi data to the Output
+
write_short(status) -> None
+
write_short(status, data1=0, data2=0) -> None
+
+

Output MIDI information of 3 bytes or less. The data fields are +optional and assumed to be 0 if omitted.

+

Examples of status byte values:

+
0xc0  # program change
+0x90  # note on
+# etc.
+
+
+

Example:

+
# note 65 on with velocity 100
+write_short(0x90, 65, 100)
+
+
+
+ +
+
+write_sys_ex()¶
+
+
writes a timestamped system-exclusive midi message.
+
write_sys_ex(when, msg) -> None
+
+

Writes a timestamped system-exclusive midi message.

+
+
Parameters
+
    +
  • msg (list[int] or str) -- midi message

  • +
  • when -- timestamp in milliseconds

  • +
+
+
+

Example:

+
midi_output.write_sys_ex(0, '\xF0\x7D\x10\x11\x12\x13\xF7')
+
+# is equivalent to
+
+midi_output.write_sys_ex(pygame.midi.time(),
+                         [0xF0, 0x7D, 0x10, 0x11, 0x12, 0x13, 0xF7])
+
+
+
+ +
+ +
+
+pygame.midi.get_count()¶
+
+
gets the number of devices.
+
get_count() -> num_devices
+
+

Device ids range from 0 to get_count() - 1

+
+ +
+
+pygame.midi.get_default_input_id()¶
+
+
gets default input device number
+
get_default_input_id() -> default_id
+
+

The following describes the usage details for this function and the +get_default_output_id() function.

+

Return the default device ID or -1 if there are no devices. The result +can be passed to the Input/Output class.

+

On a PC the user can specify a default device by setting an environment +variable. To use device #1, for example:

+
set PM_RECOMMENDED_INPUT_DEVICE=1
+or
+set PM_RECOMMENDED_OUTPUT_DEVICE=1
+
+
+

The user should first determine the available device ID by using the +supplied application "testin" or "testout".

+

In general, the registry is a better place for this kind of info. With +USB devices that can come and go, using integers is not very reliable +for device identification. Under Windows, if PM_RECOMMENDED_INPUT_DEVICE +(or PM_RECOMMENDED_OUTPUT_DEVICE) is NOT found in the environment, +then the default device is obtained by looking for a string in the registry +under:

+
HKEY_LOCAL_MACHINE/SOFTWARE/PortMidi/Recommended_Input_Device
+or
+HKEY_LOCAL_MACHINE/SOFTWARE/PortMidi/Recommended_Output_Device
+
+
+

The number of the first device with a substring that matches the +string exactly is returned. For example, if the string in the registry is +"USB" and device 1 is named "In USB MidiSport 1x1", then that will be +the default input because it contains the string "USB".

+

In addition to the name, get_device_info() returns "interf", which is +the interface name. The "interface" is the underlying software system or +API used by PortMidi to access devices. Supported interfaces:

+
MMSystem   # the only Win32 interface currently supported
+ALSA       # the only Linux interface currently supported
+CoreMIDI   # the only Mac OS X interface currently supported
+# DirectX - not implemented
+# OSS     - not implemented
+
+
+

To specify both the interface and the device name in the registry, separate +the two with a comma and a space. The string before the comma must be a +substring of the "interf" string and the string after the space must be a +substring of the "name" name string in order to match the device. e.g.:

+
MMSystem, In USB MidiSport 1x1
+
+
+
+

Note

+

In the current release, the default is simply the first device (the +input or output device with the lowest PmDeviceID).

+
+
+ +
+
+pygame.midi.get_default_output_id()¶
+
+
gets default output device number
+
get_default_output_id() -> default_id
+
+

See get_default_input_id() for usage details.

+
+ +
+
+pygame.midi.get_device_info()¶
+
+
returns information about a midi device
+
get_device_info(an_id) -> (interf, name, input, output, opened)
+
get_device_info(an_id) -> None
+
+

Gets the device info for a given id.

+
+
Parameters
+

an_id (int) -- id of the midi device being queried

+
+
Returns
+

if the id is out of range None is returned, otherwise +a tuple of (interf, name, input, output, opened) is returned.

+
+
    +
  • interf: string describing the device interface (e.g. 'ALSA')

  • +
  • name: string name of the device (e.g. 'Midi Through Port-0')

  • +
  • input: 1 if the device is an input device, otherwise 0

  • +
  • output: 1 if the device is an output device, otherwise 0

  • +
  • opened: 1 if the device is opened, otherwise 0

  • +
+
+

+
+
Return type
+

tuple or None

+
+
+
+ +
+
+pygame.midi.midis2events()¶
+
+
converts midi events to pygame events
+
midis2events(midi_events, device_id) -> [Event, ...]
+
+

Takes a sequence of midi events and returns list of pygame events.

+

The midi_events data is expected to be a sequence of +((status, data1, data2, data3), timestamp) midi events (all values +required).

+
+
Returns
+

a list of pygame events of event type MIDIIN

+
+
Return type
+

list

+
+
+
+ +
+
+pygame.midi.time()¶
+
+
returns the current time in ms of the PortMidi timer
+
time() -> time
+
+

The time is reset to 0 when the pygame.midipygame module for interacting with midi input and output. module is initialized.

+
+ +
+
+pygame.midi.frequency_to_midi()¶
+
+
Converts a frequency into a MIDI note. Rounds to the closest midi note.
+
frequency_to_midi(midi_note) -> midi_note
+
+

example:

+
frequency_to_midi(27.5) == 21
+
+
+
+

New in pygame 1.9.5.

+
+
+ +
+
+pygame.midi.midi_to_frequency()¶
+
+
Converts a midi note to a frequency.
+
midi_to_frequency(midi_note) -> frequency
+
+

example:

+
midi_to_frequency(21) == 27.5
+
+
+
+

New in pygame 1.9.5.

+
+
+ +
+
+pygame.midi.midi_to_ansi_note()¶
+
+
Returns the Ansi Note name for a midi number.
+
midi_to_ansi_note(midi_note) -> ansi_note
+
+

example:

+
midi_to_ansi_note(21) == 'A0'
+
+
+
+

New in pygame 1.9.5.

+
+
+ +
+
+exception pygame.midi.MidiException¶
+
+
exception that pygame.midi functions and classes can raise
+
MidiException(errno) -> None
+
+
+ +
+ +
+ + +

+
+Edit on GitHub +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/ref/mixer.html b/venv/Lib/site-packages/pygame/docs/generated/ref/mixer.html new file mode 100644 index 0000000..76c2ca9 --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/ref/mixer.html @@ -0,0 +1,995 @@ + + + + + + + + + pygame.mixer — pygame v2.1.2 documentation + + + + + + + + + + + + + +
+ +
+ + + + + +
+
+ +
+
+ +
+
+
+pygame.mixer
+
+
pygame module for loading and playing sounds
+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+—initialize the mixer module
+—preset the mixer init arguments
+—uninitialize the mixer
+—test if the mixer is initialized
+—stop playback of all sound channels
+—temporarily stop playback of all sound channels
+—resume paused playback of sound channels
+—fade out the volume on all sounds before stopping
+—set the total number of playback channels
+—get the total number of playback channels
+—reserve channels from being automatically used
+—find an unused channel
+—test if any sound is being mixed
+—get the mixer's SDL version
+—Create a new Sound object from a file or buffer object
+—Create a Channel object for controlling playback
+

This module contains classes for loading Sound objects and controlling +playback. The mixer module is optional and depends on SDL_mixer. Your program +should test that pygame.mixerpygame module for loading and playing sounds is available and initialized before using +it.

+

The mixer module has a limited number of channels for playback of sounds. +Usually programs tell pygame to start playing audio and it selects an available +channel automatically. The default is 8 simultaneous channels, but complex +programs can get more precise control over the number of channels and their +use.

+

All sound playback is mixed in background threads. When you begin to play a +Sound object, it will return immediately while the sound continues to play. A +single Sound object can also be actively played back multiple times.

+

The mixer also has a special streaming channel. This is for music playback and +is accessed through the pygame.mixer.musicpygame module for controlling streamed audio module. Consider using this +module for playing long running music. Unlike mixer module, the music module +streams the music from the files without loading music at once into memory.

+

The mixer module must be initialized like other pygame modules, but it has some +extra conditions. The pygame.mixer.init() function takes several optional +arguments to control the playback rate and sample size. Pygame will default to +reasonable values, but pygame cannot perform Sound resampling, so the mixer +should be initialized to match the values of your audio resources.

+

NOTE: For less laggy sound use a smaller buffer size. The default +is set to reduce the chance of scratchy sounds on some computers. You can +change the default buffer by calling pygame.mixer.pre_init()preset the mixer init arguments before +pygame.mixer.init()initialize the mixer module or pygame.init()initialize all imported pygame modules is called. For example: +pygame.mixer.pre_init(44100,-16,2, 1024)

+
+
+pygame.mixer.init()¶
+
+
initialize the mixer module
+
init(frequency=44100, size=-16, channels=2, buffer=512, devicename=None, allowedchanges=AUDIO_ALLOW_FREQUENCY_CHANGE | AUDIO_ALLOW_CHANNELS_CHANGE) -> None
+
+

Initialize the mixer module for Sound loading and playback. The default +arguments can be overridden to provide specific audio mixing. Keyword +arguments are accepted. For backwards compatibility, argument values of +0 are replaced with the startup defaults, except for allowedchanges, +where -1 is used. (startup defaults may be changed by a pre_init() call).

+

The size argument represents how many bits are used for each audio sample. +If the value is negative then signed sample values will be used. Positive +values mean unsigned audio samples will be used. An invalid value raises an +exception.

+

The channels argument is used to specify whether to use mono or stereo. 1 +for mono and 2 for stereo.

+

The buffer argument controls the number of internal samples used in the +sound mixer. The default value should work for most cases. It can be lowered +to reduce latency, but sound dropout may occur. It can be raised to larger +values to ensure playback never skips, but it will impose latency on sound +playback. The buffer size must be a power of two (if not it is rounded up to +the next nearest power of 2).

+

Some platforms require the pygame.mixerpygame module for loading and playing sounds module to be initialized +after the display modules have initialized. The top level pygame.init() +takes care of this automatically, but cannot pass any arguments to the mixer +init. To solve this, mixer has a function pygame.mixer.pre_init() to set +the proper defaults before the toplevel init is used.

+

When using allowedchanges=0 it will convert the samples at runtime to match +what the hardware supports. For example a sound card may not +support 16bit sound samples, so instead it will use 8bit samples internally. +If AUDIO_ALLOW_FORMAT_CHANGE is supplied, then the requested format will +change to the closest that SDL2 supports.

+

Apart from 0, allowedchanged accepts the following constants ORed together:

+
+
    +
  • AUDIO_ALLOW_FREQUENCY_CHANGE

  • +
  • AUDIO_ALLOW_FORMAT_CHANGE

  • +
  • AUDIO_ALLOW_CHANNELS_CHANGE

  • +
  • AUDIO_ALLOW_ANY_CHANGE

  • +
+
+

It is safe to call this more than once, but after the mixer is initialized +you cannot change the playback arguments without first calling +pygame.mixer.quit().

+
+

Changed in pygame 1.8: The default buffersize changed from 1024 to 3072.

+
+
+

Changed in pygame 1.9.1: The default buffersize changed from 3072 to 4096.

+
+
+

Changed in pygame 2.0.0: The default buffersize changed from 4096 to 512.

+
+
+

Changed in pygame 2.0.0: The default frequency changed from 22050 to 44100.

+
+
+

Changed in pygame 2.0.0: size can be 32 (32-bit floats).

+
+
+

Changed in pygame 2.0.0: channels can also be 4 or 6.

+
+
+

New in pygame 2.0.0: allowedchanges, devicename arguments added

+
+
+ +
+
+pygame.mixer.pre_init()¶
+
+
preset the mixer init arguments
+
pre_init(frequency=44100, size=-16, channels=2, buffer=512, devicename=None, allowedchanges=AUDIO_ALLOW_FREQUENCY_CHANGE | AUDIO_ALLOW_CHANNELS_CHANGE) -> None
+
+

Call pre_init to change the defaults used when the real +pygame.mixer.init() is called. Keyword arguments are accepted. The best +way to set custom mixer playback values is to call +pygame.mixer.pre_init() before calling the top level pygame.init(). +For backwards compatibility, argument values of 0 are replaced with the +startup defaults, except for allowedchanges, where -1 is used.

+
+

Changed in pygame 1.8: The default buffersize changed from 1024 to 3072.

+
+
+

Changed in pygame 1.9.1: The default buffersize changed from 3072 to 4096.

+
+
+

Changed in pygame 2.0.0: The default buffersize changed from 4096 to 512.

+
+
+

Changed in pygame 2.0.0: The default frequency changed from 22050 to 44100.

+
+
+

New in pygame 2.0.0: allowedchanges, devicename arguments added

+
+
+ +
+
+pygame.mixer.quit()¶
+
+
uninitialize the mixer
+
quit() -> None
+
+

This will uninitialize pygame.mixerpygame module for loading and playing sounds. All playback will stop and any +loaded Sound objects may not be compatible with the mixer if it is +reinitialized later.

+
+ +
+
+pygame.mixer.get_init()¶
+
+
test if the mixer is initialized
+
get_init() -> (frequency, format, channels)
+
+

If the mixer is initialized, this returns the playback arguments it is +using. If the mixer has not been initialized this returns None.

+
+ +
+
+pygame.mixer.stop()¶
+
+
stop playback of all sound channels
+
stop() -> None
+
+

This will stop all playback of all active mixer channels.

+
+ +
+
+pygame.mixer.pause()¶
+
+
temporarily stop playback of all sound channels
+
pause() -> None
+
+

This will temporarily stop all playback on the active mixer channels. The +playback can later be resumed with pygame.mixer.unpause()

+
+ +
+
+pygame.mixer.unpause()¶
+
+
resume paused playback of sound channels
+
unpause() -> None
+
+

This will resume all active sound channels after they have been paused.

+
+ +
+
+pygame.mixer.fadeout()¶
+
+
fade out the volume on all sounds before stopping
+
fadeout(time) -> None
+
+

This will fade out the volume on all active channels over the time argument +in milliseconds. After the sound is muted the playback will stop.

+
+ +
+
+pygame.mixer.set_num_channels()¶
+
+
set the total number of playback channels
+
set_num_channels(count) -> None
+
+

Sets the number of available channels for the mixer. The default value is 8. +The value can be increased or decreased. If the value is decreased, sounds +playing on the truncated channels are stopped.

+
+ +
+
+pygame.mixer.get_num_channels()¶
+
+
get the total number of playback channels
+
get_num_channels() -> count
+
+

Returns the number of currently active playback channels.

+
+ +
+
+pygame.mixer.set_reserved()¶
+
+
reserve channels from being automatically used
+
set_reserved(count) -> count
+
+

The mixer can reserve any number of channels that will not be automatically +selected for playback by Sounds. If sounds are currently playing on the +reserved channels they will not be stopped.

+

This allows the application to reserve a specific number of channels for +important sounds that must not be dropped or have a guaranteed channel to +play on.

+

Will return number of channels actually reserved, this may be less than requested +depending on the number of channels previously allocated.

+
+ +
+
+pygame.mixer.find_channel()¶
+
+
find an unused channel
+
find_channel(force=False) -> Channel
+
+

This will find and return an inactive Channel object. If there are no +inactive Channels this function will return None. If there are no +inactive channels and the force argument is True, this will find the +Channel with the longest running Sound and return it.

+
+ +
+
+pygame.mixer.get_busy()¶
+
+
test if any sound is being mixed
+
get_busy() -> bool
+
+

Returns True if the mixer is busy mixing any channels. If the mixer is +idle then this return False.

+
+ +
+
+pygame.mixer.get_sdl_mixer_version()¶
+
+
get the mixer's SDL version
+
get_sdl_mixer_version() -> (major, minor, patch)
+
get_sdl_mixer_version(linked=True) -> (major, minor, patch)
+
+
+
Parameters
+

linked (bool) -- if True (default) the linked version number is +returned, otherwise the compiled version number is returned

+
+
Returns
+

the mixer's SDL library version number (linked or compiled +depending on the linked parameter) as a tuple of 3 integers +(major, minor, patch)

+
+
Return type
+

tuple

+
+
+
+

Note

+

The linked and compile version numbers should be the same.

+
+
+

New in pygame 2.0.0.

+
+
+ +
+
+pygame.mixer.Sound¶
+
+
Create a new Sound object from a file or buffer object
+
Sound(filename) -> Sound
+
Sound(file=filename) -> Sound
+
Sound(file=pathlib_path) -> Sound
+
Sound(buffer) -> Sound
+
Sound(buffer=buffer) -> Sound
+
Sound(object) -> Sound
+
Sound(file=object) -> Sound
+
Sound(array=object) -> Sound
+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+—begin sound playback
+—stop sound playback
+—stop sound playback after fading out
+—set the playback volume for this Sound
+—get the playback volume
+—count how many times this Sound is playing
+—get the length of the Sound
+—return a bytestring copy of the Sound samples.
+

Load a new sound buffer from a filename, a python file object or a readable +buffer object. Limited resampling will be performed to help the sample match +the initialize arguments for the mixer. A Unicode string can only be a file +pathname. A bytes object can be either a pathname or a buffer object. +Use the 'file' or 'buffer' keywords to avoid ambiguity; otherwise Sound may +guess wrong. If the array keyword is used, the object is expected to export +a new buffer interface (The object is checked for a buffer interface first.)

+

The Sound object represents actual sound sample data. Methods that change +the state of the Sound object will the all instances of the Sound playback. +A Sound object also exports a new buffer interface.

+

The Sound can be loaded from an OGG audio file or from an uncompressed +WAV.

+

Note: The buffer will be copied internally, no data will be shared between +it and the Sound object.

+

For now buffer and array support is consistent with sndarray.make_sound +for Numeric arrays, in that sample sign and byte order are ignored. This +will change, either by correctly handling sign and byte order, or by raising +an exception when different. Also, source samples are truncated to fit the +audio sample size. This will not change.

+
+

New in pygame 1.8: pygame.mixer.Sound(buffer)

+
+
+

New in pygame 1.9.2: pygame.mixer.SoundCreate a new Sound object from a file or buffer object keyword arguments and array interface support

+
+
+

New in pygame 2.0.1: pathlib.Path support on Python 3.

+
+
+
+play()¶
+
+
begin sound playback
+
play(loops=0, maxtime=0, fade_ms=0) -> Channel
+
+

Begin playback of the Sound (i.e., on the computer's speakers) on an +available Channel. This will forcibly select a Channel, so playback may +cut off a currently playing sound if necessary.

+

The loops argument controls how many times the sample will be repeated +after being played the first time. A value of 5 means that the sound will +be played once, then repeated five times, and so is played a total of six +times. The default value (zero) means the Sound is not repeated, and so +is only played once. If loops is set to -1 the Sound will loop +indefinitely (though you can still call stop() to stop it).

+

The maxtime argument can be used to stop playback after a given number of +milliseconds.

+

The fade_ms argument will make the sound start playing at 0 volume and +fade up to full volume over the time given. The sample may end before the +fade-in is complete.

+

This returns the Channel object for the channel that was selected.

+
+ +
+
+stop()¶
+
+
stop sound playback
+
stop() -> None
+
+

This will stop the playback of this Sound on any active Channels.

+
+ +
+
+fadeout()¶
+
+
stop sound playback after fading out
+
fadeout(time) -> None
+
+

This will stop playback of the sound after fading it out over the time +argument in milliseconds. The Sound will fade and stop on all actively +playing channels.

+
+ +
+
+set_volume()¶
+
+
set the playback volume for this Sound
+
set_volume(value) -> None
+
+

This will set the playback volume (loudness) for this Sound. This will +immediately affect the Sound if it is playing. It will also affect any +future playback of this Sound.

+
+
Parameters
+

value (float) --

volume in the range of 0.0 to 1.0 (inclusive)

+
+
If value < 0.0, the volume will not be changed
+
If value > 1.0, the volume will be set to 1.0
+
+

+
+
+
+ +
+
+get_volume()¶
+
+
get the playback volume
+
get_volume() -> value
+
+

Return a value from 0.0 to 1.0 representing the volume for this Sound.

+
+ +
+
+get_num_channels()¶
+
+
count how many times this Sound is playing
+
get_num_channels() -> count
+
+

Return the number of active channels this sound is playing on.

+
+ +
+
+get_length()¶
+
+
get the length of the Sound
+
get_length() -> seconds
+
+

Return the length of this Sound in seconds.

+
+ +
+
+get_raw()¶
+
+
return a bytestring copy of the Sound samples.
+
get_raw() -> bytes
+
+

Return a copy of the Sound object buffer as a bytes.

+
+

New in pygame 1.9.2.

+
+
+ +
+ +
+
+pygame.mixer.Channel¶
+
+
Create a Channel object for controlling playback
+
Channel(id) -> Channel
+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+—play a Sound on a specific Channel
+—stop playback on a Channel
+—temporarily stop playback of a channel
+—resume pause playback of a channel
+—stop playback after fading channel out
+—set the volume of a playing channel
+—get the volume of the playing channel
+—check if the channel is active
+—get the currently playing Sound
+—queue a Sound object to follow the current
+—return any Sound that is queued
+—have the channel send an event when playback stops
+—get the event a channel sends when playback stops
+

Return a Channel object for one of the current channels. The id must be a +value from 0 to the value of pygame.mixer.get_num_channels().

+

The Channel object can be used to get fine control over the playback of +Sounds. A channel can only playback a single Sound at time. Using channels +is entirely optional since pygame can manage them by default.

+
+
+play()¶
+
+
play a Sound on a specific Channel
+
play(Sound, loops=0, maxtime=0, fade_ms=0) -> None
+
+

This will begin playback of a Sound on a specific Channel. If the Channel +is currently playing any other Sound it will be stopped.

+

The loops argument has the same meaning as in Sound.play(): it is the +number of times to repeat the sound after the first time. If it is 3, the +sound will be played 4 times (the first time, then three more). If loops +is -1 then the playback will repeat indefinitely.

+

As in Sound.play(), the maxtime argument can be used to stop playback +of the Sound after a given number of milliseconds.

+

As in Sound.play(), the fade_ms argument can be used fade in the +sound.

+
+ +
+
+stop()¶
+
+
stop playback on a Channel
+
stop() -> None
+
+

Stop sound playback on a channel. After playback is stopped the channel +becomes available for new Sounds to play on it.

+
+ +
+
+pause()¶
+
+
temporarily stop playback of a channel
+
pause() -> None
+
+

Temporarily stop the playback of sound on a channel. It can be resumed at +a later time with Channel.unpause()

+
+ +
+
+unpause()¶
+
+
resume pause playback of a channel
+
unpause() -> None
+
+

Resume the playback on a paused channel.

+
+ +
+
+fadeout()¶
+
+
stop playback after fading channel out
+
fadeout(time) -> None
+
+

Stop playback of a channel after fading out the sound over the given time +argument in milliseconds.

+
+ +
+
+set_volume()¶
+
+
set the volume of a playing channel
+
set_volume(value) -> None
+
set_volume(left, right) -> None
+
+

Set the volume (loudness) of a playing sound. When a channel starts to +play its volume value is reset. This only affects the current sound. The +value argument is between 0.0 and 1.0.

+

If one argument is passed, it will be the volume of both speakers. If two +arguments are passed and the mixer is in stereo mode, the first argument +will be the volume of the left speaker and the second will be the volume +of the right speaker. (If the second argument is None, the first +argument will be the volume of both speakers.)

+

If the channel is playing a Sound on which set_volume() has also been +called, both calls are taken into account. For example:

+
sound = pygame.mixer.Sound("s.wav")
+channel = s.play()      # Sound plays at full volume by default
+sound.set_volume(0.9)   # Now plays at 90% of full volume.
+sound.set_volume(0.6)   # Now plays at 60% (previous value replaced).
+channel.set_volume(0.5) # Now plays at 30% (0.6 * 0.5).
+
+
+
+ +
+
+get_volume()¶
+
+
get the volume of the playing channel
+
get_volume() -> value
+
+

Return the volume of the channel for the current playing sound. This does +not take into account stereo separation used by +Channel.set_volume(). The Sound object also has its own volume +which is mixed with the channel.

+
+ +
+
+get_busy()¶
+
+
check if the channel is active
+
get_busy() -> bool
+
+

Returns True if the channel is actively mixing sound. If the channel +is idle this returns False.

+
+ +
+
+get_sound()¶
+
+
get the currently playing Sound
+
get_sound() -> Sound
+
+

Return the actual Sound object currently playing on this channel. If the +channel is idle None is returned.

+
+ +
+
+queue()¶
+
+
queue a Sound object to follow the current
+
queue(Sound) -> None
+
+

When a Sound is queued on a Channel, it will begin playing immediately +after the current Sound is finished. Each channel can only have a single +Sound queued at a time. The queued Sound will only play if the current +playback finished automatically. It is cleared on any other call to +Channel.stop() or Channel.play().

+

If there is no sound actively playing on the Channel then the Sound will +begin playing immediately.

+
+ +
+
+get_queue()¶
+
+
return any Sound that is queued
+
get_queue() -> Sound
+
+

If a Sound is already queued on this channel it will be returned. Once +the queued sound begins playback it will no longer be on the queue.

+
+ +
+
+set_endevent()¶
+
+
have the channel send an event when playback stops
+
set_endevent() -> None
+
set_endevent(type) -> None
+
+

When an endevent is set for a channel, it will send an event to the +pygame queue every time a sound finishes playing on that channel (not +just the first time). Use pygame.event.get() to retrieve the endevent +once it's sent.

+

Note that if you called Sound.play(n) or Channel.play(sound,n), +the end event is sent only once: after the sound has been played "n+1" +times (see the documentation of Sound.play).

+

If Channel.stop() or Channel.play() is called while the sound was +still playing, the event will be posted immediately.

+

The type argument will be the event id sent to the queue. This can be any +valid event type, but a good choice would be a value between +pygame.locals.USEREVENT and pygame.locals.NUMEVENTS. If no type +argument is given then the Channel will stop sending endevents.

+
+ +
+
+get_endevent()¶
+
+
get the event a channel sends when playback stops
+
get_endevent() -> type
+
+

Returns the event type to be sent every time the Channel finishes +playback of a Sound. If there is no endevent the function returns +pygame.NOEVENT.

+
+ +
+ +
+ +
+ + +

+
+Edit on GitHub +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/ref/mouse.html b/venv/Lib/site-packages/pygame/docs/generated/ref/mouse.html new file mode 100644 index 0000000..1af1d62 --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/ref/mouse.html @@ -0,0 +1,406 @@ + + + + + + + + + pygame.mouse — pygame v2.1.2 documentation + + + + + + + + + + + + + +
+ +
+ + + + + +
+
+ +
+
+ +
+
+
+pygame.mouse
+
+
pygame module to work with the mouse
+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+—get the state of the mouse buttons
+—get the mouse cursor position
+—get the amount of mouse movement
+—set the mouse cursor position
+—hide or show the mouse cursor
+—get the current visibility state of the mouse cursor
+—check if the display is receiving mouse input
+—set the mouse cursor to a new cursor
+—get the current mouse cursor
+

The mouse functions can be used to get the current state of the mouse device. +These functions can also alter the system cursor for the mouse.

+

When the display mode is set, the event queue will start receiving mouse +events. The mouse buttons generate pygame.MOUSEBUTTONDOWN and +pygame.MOUSEBUTTONUP events when they are pressed and released. These +events contain a button attribute representing which button was pressed. The +mouse wheel will generate pygame.MOUSEBUTTONDOWN and +pygame.MOUSEBUTTONUP events when rolled. The button will be set to 4 +when the wheel is rolled up, and to button 5 when the wheel is rolled down. +Whenever the mouse is moved it generates a pygame.MOUSEMOTION event. The +mouse movement is broken into small and accurate motion events. As the mouse +is moving many motion events will be placed on the queue. Mouse motion events +that are not properly cleaned from the event queue are the primary reason the +event queue fills up.

+

If the mouse cursor is hidden, and input is grabbed to the current display the +mouse will enter a virtual input mode, where the relative movements of the +mouse will never be stopped by the borders of the screen. See the functions +pygame.mouse.set_visible() and pygame.event.set_grab() to get this +configured.

+

Mouse Wheel Behavior in pygame 2

+

There is proper functionality for mouse wheel behaviour with pygame 2 supporting +pygame.MOUSEWHEEL events. The new events support horizontal and vertical +scroll movements, with signed integer values representing the amount scrolled +(x and y), as well as flipped direction (the set positive and +negative values for each axis is flipped). Read more about SDL2 +input-related changes here https://wiki.libsdl.org/MigrationGuide#Input

+

In pygame 2, the mouse wheel functionality can be used by listening for the +pygame.MOUSEWHEEL type of an event (Bear in mind they still emit +pygame.MOUSEBUTTONDOWN events like in pygame 1.x, as well). +When this event is triggered, a developer can access the appropriate Event object +with pygame.event.get(). The object can be used to access data about the mouse +scroll, such as which (it will tell you what exact mouse device trigger the event).

+
+
Code example of mouse scroll (tested on 2.0.0.dev7)¶
+
# Taken from husano896's PR thread (slightly modified)
+import pygame
+from pygame.locals import *
+pygame.init()
+screen = pygame.display.set_mode((640, 480))
+clock = pygame.time.Clock()
+
+def main():
+   while True:
+      for event in pygame.event.get():
+            if event.type == QUIT:
+               pygame.quit()
+               return
+            elif event.type == MOUSEWHEEL:
+               print(event)
+               print(event.x, event.y)
+               print(event.flipped)
+               print(event.which)
+               # can access properties with
+               # proper notation(ex: event.y)
+      clock.tick(60)
+
+# Execute game:
+main()
+
+
+
+
+
+pygame.mouse.get_pressed()¶
+
+
get the state of the mouse buttons
+
get_pressed(num_buttons=3) -> (button1, button2, button3)
+
get_pressed(num_buttons=5) -> (button1, button2, button3, button4, button5)
+
+

Returns a sequence of booleans representing the state of all the mouse +buttons. A true value means the mouse is currently being pressed at the time +of the call.

+

Note, to get all of the mouse events it is better to use either +pygame.event.wait() or pygame.event.get() and check all of those +events to see if they are MOUSEBUTTONDOWN, MOUSEBUTTONUP, or +MOUSEMOTION.

+

Note, that on X11 some X servers use middle button emulation. When you +click both buttons 1 and 3 at the same time a 2 button event +can be emitted.

+

Note, remember to call pygame.event.get() before this function. +Otherwise it will not work as expected.

+

To support five button mice, an optional parameter num_buttons has been +added in pygame 2. When this is set to 5, button4 and button5 +are added to the returned tuple. Only 3 and 5 are valid values +for this parameter.

+
+

Changed in pygame 2.0.0: num_buttons argument added

+
+
+ +
+
+pygame.mouse.get_pos()¶
+
+
get the mouse cursor position
+
get_pos() -> (x, y)
+
+

Returns the x and y position of the mouse cursor. The position is +relative to the top-left corner of the display. The cursor position can be +located outside of the display window, but is always constrained to the +screen.

+
+ +
+
+pygame.mouse.get_rel()¶
+
+
get the amount of mouse movement
+
get_rel() -> (x, y)
+
+

Returns the amount of movement in x and y since the previous call to +this function. The relative movement of the mouse cursor is constrained to +the edges of the screen, but see the virtual input mouse mode for a way +around this. Virtual input mode is described at the top of the page.

+
+ +
+
+pygame.mouse.set_pos()¶
+
+
set the mouse cursor position
+
set_pos([x, y]) -> None
+
+

Set the current mouse position to arguments given. If the mouse cursor is +visible it will jump to the new coordinates. Moving the mouse will generate +a new pygame.MOUSEMOTION event.

+
+ +
+
+pygame.mouse.set_visible()¶
+
+
hide or show the mouse cursor
+
set_visible(bool) -> bool
+
+

If the bool argument is true, the mouse cursor will be visible. This will +return the previous visible state of the cursor.

+
+ +
+
+pygame.mouse.get_visible()¶
+
+
get the current visibility state of the mouse cursor
+
get_visible() -> bool
+
+

Get the current visibility state of the mouse cursor. True if the mouse is +visible, False otherwise.

+
+

New in pygame 2.0.0.

+
+
+ +
+
+pygame.mouse.get_focused()¶
+
+
check if the display is receiving mouse input
+
get_focused() -> bool
+
+

Returns true when pygame is receiving mouse input events (or, in windowing +terminology, is "active" or has the "focus").

+

This method is most useful when working in a window. By contrast, in +full-screen mode, this method always returns true.

+

Note: under MS Windows, the window that has the mouse focus also has the +keyboard focus. But under X-Windows, one window can receive mouse events and +another receive keyboard events. pygame.mouse.get_focused() indicates +whether the pygame window receives mouse events.

+
+ +
+
+pygame.mouse.set_cursor()¶
+
+
set the mouse cursor to a new cursor
+
set_cursor(pygame.cursors.Cursor) -> None
+
set_cursor(size, hotspot, xormasks, andmasks) -> None
+
set_cursor(hotspot, surface) -> None
+
set_cursor(constant) -> None
+
+

Set the mouse cursor to something new. This function accepts either an explicit +Cursor object or arguments to create a Cursor object.

+

See pygame.cursors.Cursorpygame object representing a cursor for help creating cursors and for examples.

+
+

Changed in pygame 2.0.1.

+
+
+ +
+
+pygame.mouse.get_cursor()¶
+
+
get the current mouse cursor
+
get_cursor() -> pygame.cursors.Cursor
+
+

Get the information about the mouse system cursor. The return value contains +the same data as the arguments passed into pygame.mouse.set_cursor()set the mouse cursor to a new cursor.

+
+

Note

+

Code that unpacked a get_cursor() call into +size, hotspot, xormasks, andmasks will still work, +assuming the call returns an old school type cursor.

+
+
+

Changed in pygame 2.0.1.

+
+
+ +
+ +
+ + +

+
+Edit on GitHub +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/ref/music.html b/venv/Lib/site-packages/pygame/docs/generated/ref/music.html new file mode 100644 index 0000000..f9d86ba --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/ref/music.html @@ -0,0 +1,502 @@ + + + + + + + + + pygame.mixer.music — pygame v2.1.2 documentation + + + + + + + + + + + + + +
+ +
+ + + + + +
+
+ +
+
+ +
+
+
+pygame.mixer.music
+
+
pygame module for controlling streamed audio
+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+—Load a music file for playback
+—Unload the currently loaded music to free up resources
+—Start the playback of the music stream
+—restart music
+—stop the music playback
+—temporarily stop music playback
+—resume paused music
+—stop music playback after fading out
+—set the music volume
+—get the music volume
+—check if the music stream is playing
+—set position to play from
+—get the music play time
+—queue a sound file to follow the current
+—have the music send an event when playback stops
+—get the event a channel sends when playback stops
+

The music module is closely tied to pygame.mixerpygame module for loading and playing sounds. Use the music module +to control the playback of music in the sound mixer.

+

The difference between the music playback and regular Sound playback is that +the music is streamed, and never actually loaded all at once. The mixer system +only supports a single music stream at once.

+

On older pygame versions, MP3 support was limited under Mac and Linux. This +changed in pygame v2.0.2 which got improved MP3 support. Consider using +OGG file format for music as that can give slightly better compression than +MP3 in most cases.

+
+
+pygame.mixer.music.load()¶
+
+
Load a music file for playback
+
load(filename) -> None
+
load(fileobj, namehint="") -> None
+
+

This will load a music filename/file object and prepare it for playback. If +a music stream is already playing it will be stopped. This does not start +the music playing.

+

If you are loading from a file object, the namehint parameter can be used to specify +the type of music data in the object. For example: load(fileobj, "ogg").

+
+

Changed in pygame 2.0.2: Added optional namehint argument

+
+
+ +
+
+pygame.mixer.music.unload()¶
+
+
Unload the currently loaded music to free up resources
+
unload() -> None
+
+

This closes resources like files for any music that may be loaded.

+
+

New in pygame 2.0.0.

+
+
+ +
+
+pygame.mixer.music.play()¶
+
+
Start the playback of the music stream
+
play(loops=0, start=0.0, fade_ms=0) -> None
+
+

This will play the loaded music stream. If the music is already playing it +will be restarted.

+

loops is an optional integer argument, which is 0 by default, which +indicates how many times to repeat the music. The music repeats indefinitely if +this argument is set to -1.

+

start is an optional float argument, which is 0.0 by default, which +denotes the position in time from which the music starts playing. The starting +position depends on the format of the music played. MP3 and OGG use +the position as time in seconds. For MP3 files the start time position +selected may not be accurate as things like variable bit rate encoding and ID3 +tags can throw off the timing calculations. For MOD music it is the pattern +order number. Passing a start position will raise a NotImplementedError if +the start position cannot be set.

+

fade_ms is an optional integer argument, which is 0 by default, +which denotes the period of time (in milliseconds) over which the music +will fade up from volume level 0.0 to full volume (or the volume level +previously set by set_volume()). The sample may end before the fade-in +is complete. If the music is already streaming fade_ms is ignored.

+
+

Changed in pygame 2.0.0: Added optional fade_ms argument

+
+
+ +
+
+pygame.mixer.music.rewind()¶
+
+
restart music
+
rewind() -> None
+
+

Resets playback of the current music to the beginning. If pause() has +previoulsy been used to pause the music, the music will remain paused.

+
+

Note

+

rewind() supports a limited number of file types and notably +WAV files are NOT supported. For unsupported file types use play() +which will restart the music that's already playing (note that this +will start the music playing again even if previously paused).

+
+
+ +
+
+pygame.mixer.music.stop()¶
+
+
stop the music playback
+
stop() -> None
+
+

Stops the music playback if it is currently playing. +endevent will be triggered, if set. +It won't unload the music.

+
+ +
+
+pygame.mixer.music.pause()¶
+
+
temporarily stop music playback
+
pause() -> None
+
+

Temporarily stop playback of the music stream. It can be resumed with the +unpause() function.

+
+ +
+
+pygame.mixer.music.unpause()¶
+
+
resume paused music
+
unpause() -> None
+
+

This will resume the playback of a music stream after it has been paused.

+
+ +
+
+pygame.mixer.music.fadeout()¶
+
+
stop music playback after fading out
+
fadeout(time) -> None
+
+

Fade out and stop the currently playing music.

+

The time argument denotes the integer milliseconds for which the +fading effect is generated.

+

Note, that this function blocks until the music has faded out. Calls +to fadeout() and set_volume() will have no effect during +this time. If an event was set using set_endevent() it will be +called after the music has faded.

+
+ +
+
+pygame.mixer.music.set_volume()¶
+
+
set the music volume
+
set_volume(volume) -> None
+
+

Set the volume of the music playback.

+

The volume argument is a float between 0.0 and 1.0 that sets +the volume level. When new music is loaded the volume is reset to full +volume. If volume is a negative value it will be ignored and the +volume will remain set at the current level. If the volume argument +is greater than 1.0, the volume will be set to 1.0.

+
+ +
+
+pygame.mixer.music.get_volume()¶
+
+
get the music volume
+
get_volume() -> value
+
+

Returns the current volume for the mixer. The value will be between 0.0 +and 1.0.

+
+ +
+
+pygame.mixer.music.get_busy()¶
+
+
check if the music stream is playing
+
get_busy() -> bool
+
+

Returns True when the music stream is actively playing. When the music is +idle this returns False. In pygame 2.0.1 and above this function returns +False when the music is paused. In pygame 1 it returns True when the music +is paused.

+
+

Changed in pygame 2.0.1: Returns False when music paused.

+
+
+ +
+
+pygame.mixer.music.set_pos()¶
+
+
set position to play from
+
set_pos(pos) -> None
+
+

This sets the position in the music file where playback will start. +The meaning of "pos", a float (or a number that can be converted to a float), +depends on the music format.

+

For MOD files, pos is the integer pattern number in the module. +For OGG it is the absolute position, in seconds, from +the beginning of the sound. For MP3 files, it is the relative position, +in seconds, from the current position. For absolute positioning in an MP3 +file, first call rewind().

+

Other file formats are unsupported. Newer versions of SDL_mixer have +better positioning support than earlier ones. An SDLError is raised if a +particular format does not support positioning.

+

Function set_pos() calls underlining SDL_mixer function +Mix_SetMusicPosition.

+
+

New in pygame 1.9.2.

+
+
+ +
+
+pygame.mixer.music.get_pos()¶
+
+
get the music play time
+
get_pos() -> time
+
+

This gets the number of milliseconds that the music has been playing for. +The returned time only represents how long the music has been playing; it +does not take into account any starting position offsets.

+
+ +
+
+pygame.mixer.music.queue()¶
+
+
queue a sound file to follow the current
+
queue(filename) -> None
+
queue(fileobj, namehint="", loops=0) -> None
+
+

This will load a sound file and queue it. A queued sound file will begin as +soon as the current sound naturally ends. Only one sound can be queued at a +time. Queuing a new sound while another sound is queued will result in the +new sound becoming the queued sound. Also, if the current sound is ever +stopped or changed, the queued sound will be lost.

+

If you are loading from a file object, the namehint parameter can be used to specify +the type of music data in the object. For example: queue(fileobj, "ogg").

+

The following example will play music by Bach six times, then play music by +Mozart once:

+
pygame.mixer.music.load('bach.ogg')
+pygame.mixer.music.play(5)        # Plays six times, not five!
+pygame.mixer.music.queue('mozart.ogg')
+
+
+
+

Changed in pygame 2.0.2: Added optional namehint argument

+
+
+ +
+
+pygame.mixer.music.set_endevent()¶
+
+
have the music send an event when playback stops
+
set_endevent() -> None
+
set_endevent(type) -> None
+
+

This causes pygame to signal (by means of the event queue) when the music is +done playing. The argument determines the type of event that will be queued.

+

The event will be queued every time the music finishes, not just the first +time. To stop the event from being queued, call this method with no +argument.

+
+ +
+
+pygame.mixer.music.get_endevent()¶
+
+
get the event a channel sends when playback stops
+
get_endevent() -> type
+
+

Returns the event type to be sent every time the music finishes playback. If +there is no endevent the function returns pygame.NOEVENT.

+
+ +
+ +
+ + +

+
+Edit on GitHub +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/ref/overlay.html b/venv/Lib/site-packages/pygame/docs/generated/ref/overlay.html new file mode 100644 index 0000000..00ecdca --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/ref/overlay.html @@ -0,0 +1,231 @@ + + + + + + + + + pygame.Overlay — pygame v2.1.2 documentation + + + + + + + + + + + + + +
+ +
+ + + + + +
+
+ +
+
+ +
+
+

Warning

+

This module is non functional in pygame 2.0 and above, unless you have manually compiled pygame with SDL1. +This module will not be supported in the future.

+
+
+
+pygame.Overlay¶
+
+
pygame object for video overlay graphics
+
Overlay(format, (width, height)) -> Overlay
+
+ +++++ + + + + + + + + + + + + + + +
+—set the overlay pixel data
+—control where the overlay is displayed
+—test if the Overlay is hardware accelerated
+

The Overlay objects provide support for accessing hardware video overlays. +Video overlays do not use standard RGB pixel formats, and can use +multiple resolutions of data to create a single image.

+

The Overlay objects represent lower level access to the display hardware. To +use the object you must understand the technical details of video overlays.

+

The Overlay format determines the type of pixel data used. Not all hardware +will support all types of overlay formats. Here is a list of available +format types:

+
YV12_OVERLAY, IYUV_OVERLAY, YUY2_OVERLAY, UYVY_OVERLAY, YVYU_OVERLAY
+
+
+

The width and height arguments control the size for the overlay image data. +The overlay image can be displayed at any size, not just the resolution of +the overlay.

+

The overlay objects are always visible, and always show above the regular +display contents.

+
+
+display()¶
+
+
set the overlay pixel data
+
display((y, u, v)) -> None
+
display() -> None
+
+

Display the YUV data in SDL's overlay planes. The y, u, and v arguments +are strings of binary data. The data must be in the correct format used +to create the Overlay.

+

If no argument is passed in, the Overlay will simply be redrawn with the +current data. This can be useful when the Overlay is not really hardware +accelerated.

+

The strings are not validated, and improperly sized strings could crash +the program.

+
+ +
+
+set_location()¶
+
+
control where the overlay is displayed
+
set_location(rect) -> None
+
+

Set the location for the overlay. The overlay will always be shown +relative to the main display Surface. This does not actually redraw the +overlay, it will be updated on the next call to Overlay.display().

+
+ +
+
+get_hardware()¶
+
+
test if the Overlay is hardware accelerated
+
get_hardware(rect) -> int
+
+

Returns a True value when the Overlay is hardware accelerated. If the +platform does not support acceleration, software rendering is used.

+
+ +
+ +
+ + +

+
+Edit on GitHub +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/ref/pixelarray.html b/venv/Lib/site-packages/pygame/docs/generated/ref/pixelarray.html new file mode 100644 index 0000000..dad2d87 --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/ref/pixelarray.html @@ -0,0 +1,486 @@ + + + + + + + + + pygame.PixelArray — pygame v2.1.2 documentation + + + + + + + + + + + + + +
+ +
+ + + + + +
+
+ +
+
+ +
+
+
+pygame.PixelArray¶
+
+
pygame object for direct pixel access of surfaces
+
PixelArray(Surface) -> PixelArray
+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+—Gets the Surface the PixelArray uses.
+—Returns the byte size of a pixel array item
+—Returns the number of dimensions.
+—Returns the array size.
+—Returns byte offsets for each array dimension.
+—Creates a new Surface from the current PixelArray.
+—Replaces the passed color in the PixelArray with another one.
+—Extracts the passed color from the PixelArray.
+—Compares the PixelArray with another one.
+—Exchanges the x and y axis.
+—Closes the PixelArray, and releases Surface lock.
+

The PixelArray wraps a Surface and provides direct access to the +surface's pixels. A pixel array can be one or two dimensional. +A two dimensional array, like its surface, is indexed [column, row]. +Pixel arrays support slicing, both for returning a subarray or +for assignment. A pixel array sliced on a single column or row +returns a one dimensional pixel array. Arithmetic and other operations +are not supported. A pixel array can be safely assigned to itself. +Finally, pixel arrays export an array struct interface, allowing +them to interact with pygame.pixelcopypygame module for general pixel array copying methods and NumPy +arrays.

+

A PixelArray pixel item can be assigned a raw integer values, a +pygame.Colorpygame object for color representations instance, or a (r, g, b[, a]) tuple.

+
pxarray[x, y] = 0xFF00FF
+pxarray[x, y] = pygame.Color(255, 0, 255)
+pxarray[x, y] = (255, 0, 255)
+
+
+

However, only a pixel's integer value is returned. So, to compare a pixel +to a particular color the color needs to be first mapped using +the Surface.map_rgb() method of the Surface object for which the +PixelArray was created.

+
pxarray = pygame.PixelArray(surface)
+# Check, if the first pixel at the topleft corner is blue
+if pxarray[0, 0] == surface.map_rgb((0, 0, 255)):
+    ...
+
+
+

When assigning to a range of of pixels, a non tuple sequence of colors or +a PixelArray can be used as the value. For a sequence, the length must +match the PixelArray width.

+
pxarray[a:b] = 0xFF00FF                   # set all pixels to 0xFF00FF
+pxarray[a:b] = (0xFF00FF, 0xAACCEE, ... ) # first pixel = 0xFF00FF,
+                                          # second pixel  = 0xAACCEE, ...
+pxarray[a:b] = [(255, 0, 255), (170, 204, 238), ...] # same as above
+pxarray[a:b] = [(255, 0, 255), 0xAACCEE, ...]        # same as above
+pxarray[a:b] = otherarray[x:y]            # slice sizes must match
+
+
+

For PixelArray assignment, if the right hand side array has a row length +of 1, then the column is broadcast over the target array's rows. An +array of height 1 is broadcast over the target's columns, and is equivalent +to assigning a 1D PixelArray.

+

Subscript slices can also be used to assign to a rectangular subview of +the target PixelArray.

+
# Create some new PixelArray objects providing a different view
+# of the original array/surface.
+newarray = pxarray[2:4, 3:5]
+otherarray = pxarray[::2, ::2]
+
+
+

Subscript slices can also be used to do fast rectangular pixel manipulations +instead of iterating over the x or y axis. The

+
pxarray[::2, :] = (0, 0, 0)               # Make even columns black.
+pxarray[::2] = (0, 0, 0)                  # Same as [::2, :]
+
+
+

During its lifetime, the PixelArray locks the surface, thus you explicitly +have to close() it once its not used any more and the surface should perform +operations in the same scope. It is best to use it as a context manager +using the with PixelArray(surf) as pixel_array: style. So it works on pypy too.

+

A simple : slice index for the column can be omitted.

+
pxarray[::2, ...] = (0, 0, 0)             # Same as pxarray[::2, :]
+pxarray[...] = (255, 0, 0)                # Same as pxarray[:]
+
+
+

A note about PixelArray to PixelArray assignment, for arrays with an +item size of 3 (created from 24 bit surfaces) pixel values are translated +from the source to the destinations format. The red, green, and blue +color elements of each pixel are shifted to match the format of the +target surface. For all other pixel sizes no such remapping occurs. +This should change in later pygame releases, where format conversions +are performed for all pixel sizes. To avoid code breakage when full mapped +copying is implemented it is suggested PixelArray to PixelArray copies be +only between surfaces of identical format.

+
+

New in pygame 1.9.4:

+
    +
  • close() method was added. For explicitly cleaning up.

  • +
  • being able to use PixelArray as a context manager for cleanup.

  • +
  • both of these are useful for when working without reference counting (pypy).

  • +
+
+
+

New in pygame 1.9.2:

+
    +
  • array struct interface

  • +
  • transpose method

  • +
  • broadcasting for a length 1 dimension

  • +
+
+
+

Changed in pygame 1.9.2:

+
    +
  • A 2D PixelArray can have a length 1 dimension. +Only an integer index on a 2D PixelArray returns a 1D array.

  • +
  • For assignment, a tuple can only be a color. Any other sequence type +is a sequence of colors.

  • +
+
+
+
+surface¶
+
+
Gets the Surface the PixelArray uses.
+
surface -> Surface
+
+

The Surface the PixelArray was created for.

+
+ +
+
+itemsize¶
+
+
Returns the byte size of a pixel array item
+
itemsize -> int
+
+

This is the same as Surface.get_bytesize() for the +pixel array's surface.

+
+

New in pygame 1.9.2.

+
+
+ +
+
+ndim¶
+
+
Returns the number of dimensions.
+
ndim -> int
+
+

A pixel array can be 1 or 2 dimensional.

+
+

New in pygame 1.9.2.

+
+
+ +
+
+shape¶
+
+
Returns the array size.
+
shape -> tuple of int's
+
+

A tuple or length ndim giving the length of each +dimension. Analogous to Surface.get_size().

+
+

New in pygame 1.9.2.

+
+
+ +
+
+strides¶
+
+
Returns byte offsets for each array dimension.
+
strides -> tuple of int's
+
+

A tuple or length ndim byte counts. When a stride is +multiplied by the corresponding index it gives the offset +of that index from the start of the array. A stride is negative +for an array that has is inverted (has a negative step).

+
+

New in pygame 1.9.2.

+
+
+ +
+
+make_surface()¶
+
+
Creates a new Surface from the current PixelArray.
+
make_surface() -> Surface
+
+

Creates a new Surface from the current PixelArray. Depending on the +current PixelArray the size, pixel order etc. will be different from the +original Surface.

+
# Create a new surface flipped around the vertical axis.
+sf = pxarray[:,::-1].make_surface ()
+
+
+
+

New in pygame 1.8.1.

+
+
+ +
+
+replace()¶
+
+
Replaces the passed color in the PixelArray with another one.
+
replace(color, repcolor, distance=0, weights=(0.299, 0.587, 0.114)) -> None
+
+

Replaces the pixels with the passed color in the PixelArray by changing +them them to the passed replacement color.

+

It uses a simple weighted Euclidean distance formula to calculate the +distance between the colors. The distance space ranges from 0.0 to 1.0 +and is used as threshold for the color detection. This causes the +replacement to take pixels with a similar, but not exactly identical +color, into account as well.

+

This is an in place operation that directly affects the pixels of the +PixelArray.

+
+

New in pygame 1.8.1.

+
+
+ +
+
+extract()¶
+
+
Extracts the passed color from the PixelArray.
+
extract(color, distance=0, weights=(0.299, 0.587, 0.114)) -> PixelArray
+
+

Extracts the passed color by changing all matching pixels to white, while +non-matching pixels are changed to black. This returns a new PixelArray +with the black/white color mask.

+

It uses a simple weighted Euclidean distance formula to calculate the +distance between the colors. The distance space ranges from 0.0 to 1.0 +and is used as threshold for the color detection. This causes the +extraction to take pixels with a similar, but not exactly identical +color, into account as well.

+
+

New in pygame 1.8.1.

+
+
+ +
+
+compare()¶
+
+
Compares the PixelArray with another one.
+
compare(array, distance=0, weights=(0.299, 0.587, 0.114)) -> PixelArray
+
+

Compares the contents of the PixelArray with those from the passed in +PixelArray. It returns a new PixelArray with a black/white color mask +that indicates the differences (black) of both arrays. Both PixelArray +objects must have identical bit depths and dimensions.

+

It uses a simple weighted Euclidean distance formula to calculate the +distance between the colors. The distance space ranges from 0.0 to 1.0 +and is used as a threshold for the color detection. This causes the +comparison to mark pixels with a similar, but not exactly identical +color, as white.

+
+

New in pygame 1.8.1.

+
+
+ +
+
+transpose()¶
+
+
Exchanges the x and y axis.
+
transpose() -> PixelArray
+
+

This method returns a new view of the pixel array with the rows and +columns swapped. So for a (w, h) sized array a (h, w) slice is returned. +If an array is one dimensional, then a length 1 x dimension is added, +resulting in a 2D pixel array.

+
+

New in pygame 1.9.2.

+
+
+ +
+
+close()¶
+
+
Closes the PixelArray, and releases Surface lock.
+
transpose() -> PixelArray
+
+

This method is for explicitly closing the PixelArray, and releasing +a lock on the Suface.

+
+

New in pygame 1.9.4.

+
+
+ +
+ +
+ + +

+
+Edit on GitHub +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/ref/pixelcopy.html b/venv/Lib/site-packages/pygame/docs/generated/ref/pixelcopy.html new file mode 100644 index 0000000..55fa60a --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/ref/pixelcopy.html @@ -0,0 +1,262 @@ + + + + + + + + + pygame.pixelcopy — pygame v2.1.2 documentation + + + + + + + + + + + + + +
+ +
+ + + + + +
+
+ +
+
+ +
+
+
+pygame.pixelcopy
+
+
pygame module for general pixel array copying
+
+ +++++ + + + + + + + + + + + + + + + + + + +
+—copy surface pixels to an array object
+—copy an array object to a surface
+—copy an array to another array, using surface format
+—Copy an array to a new surface
+

The pygame.pixelcopy module contains functions for copying between +surfaces and objects exporting an array structure interface. It is a backend +for pygame.surfarraypygame module for accessing surface pixel data using array interfaces, adding NumPy support. But pixelcopy is more +general, and intended for direct use.

+

The array struct interface exposes an array's data in a standard way. +It was introduced in NumPy. In Python 2.7 and above it is replaced by the +new buffer protocol, though the buffer protocol is still a work in progress. +The array struct interface, on the other hand, is stable and works with earlier +Python versions. So for now the array struct interface is the predominate way +pygame handles array introspection.

+

For 2d arrays of integer pixel values, the values are mapped to the +pixel format of the related surface. To get the actual color of a pixel +value use pygame.Surface.unmap_rgb()convert a mapped integer color value into a Color. 2d arrays can only be used +directly between surfaces having the same pixel layout.

+

New in pygame 1.9.2.

+
+
+pygame.pixelcopy.surface_to_array()¶
+
+
copy surface pixels to an array object
+
surface_to_array(array, surface, kind='P', opaque=255, clear=0) -> None
+
+

The surface_to_array function copies pixels from a Surface object +to a 2D or 3D array. Depending on argument kind and the target array +dimension, a copy may be raw pixel value, RGB, a color component slice, +or colorkey alpha transparency value. Recognized kind values are the +single character codes 'P', 'R', 'G', 'B', 'A', and 'C'. Kind codes are case +insensitive, so 'p' is equivalent to 'P'. The first two dimensions +of the target must be the surface size (w, h).

+

The default 'P' kind code does a direct raw integer pixel (mapped) value +copy to a 2D array and a 'RGB' pixel component (unmapped) copy to a 3D array +having shape (w, h, 3). For an 8 bit colormap surface this means the +table index is copied to a 2D array, not the table value itself. A 2D +array's item size must be at least as large as the surface's pixel +byte size. The item size of a 3D array must be at least one byte.

+

For the 'R', 'G', 'B', and 'A' copy kinds a single color component +of the unmapped surface pixels are copied to the target 2D array. +For kind 'A' and surfaces with source alpha (the surface was created with +the SRCALPHA flag), has a colorkey +(set with Surface.set_colorkey()), +or has a blanket alpha +(set with Surface.set_alpha()) +then the alpha values are those expected for a SDL surface. +If a surface has no explicit alpha value, then the target array +is filled with the value of the optional opaque surface_to_array +argument (default 255: not transparent).

+

Copy kind 'C' is a special case for alpha copy of a source surface +with colorkey. Unlike the 'A' color component copy, the clear +argument value is used for colorkey matches, opaque otherwise. +By default, a match has alpha 0 (totally transparent), while everything +else is alpha 255 (totally opaque). It is a more general implementation +of pygame.surfarray.array_colorkey()Copy the colorkey values into a 2d array.

+

Specific to surface_to_array, a ValueError is raised for target arrays +with incorrect shape or item size. A TypeError is raised for an incorrect +kind code. Surface specific problems, such as locking, raise a pygame.error.

+
+ +
+
+pygame.pixelcopy.array_to_surface()¶
+
+
copy an array object to a surface
+
array_to_surface(<surface>, <array>) -> None
+
+

See pygame.surfarray.blit_array()Blit directly from a array values.

+
+ +
+
+pygame.pixelcopy.map_array()¶
+
+
copy an array to another array, using surface format
+
map_array(<array>, <array>, <surface>) -> None
+
+

Map an array of color element values - (w, h, ..., 3) - to an array of +pixels - (w, h) according to the format of <surface>.

+
+ +
+
+pygame.pixelcopy.make_surface()¶
+
+
Copy an array to a new surface
+
pygame.pixelcopy.make_surface(array) -> Surface
+
+

Create a new Surface that best resembles the data and format of the array. +The array can be 2D or 3D with any sized integer values.

+
+ +
+ +
+ + +

+
+Edit on GitHub +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/ref/pygame.html b/venv/Lib/site-packages/pygame/docs/generated/ref/pygame.html new file mode 100644 index 0000000..8b48ddd --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/ref/pygame.html @@ -0,0 +1,693 @@ + + + + + + + + + pygame — pygame v2.1.2 documentation + + + + + + + + + + + + + +
+ +
+ + + + + +
+
+ +
+
+ +
+
+
+pygame
+
+
the top level pygame package
+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+—initialize all imported pygame modules
+—uninitialize all pygame modules
+—returns True if pygame is currently initialized
+—standard pygame exception
+—get the current error message
+—set the current error message
+—get the version number of SDL
+—get the byte order of SDL
+—register a function to be called when pygame quits
+—Encode a Unicode or bytes object
+—Encode a Unicode or bytes object as a file system path
+

The pygame package represents the top-level package for others to use. Pygame +itself is broken into many submodules, but this does not affect programs that +use pygame.

+

As a convenience, most of the top-level variables in pygame have been placed +inside a module named pygame.localspygame constants. This is meant to be used with +from pygame.locals import *, in addition to import pygame.

+

When you import pygame all available pygame submodules are automatically +imported. Be aware that some of the pygame modules are considered optional, +and may not be available. In that case, pygame will provide a placeholder +object instead of the module, which can be used to test for availability.

+
+
+pygame.init()¶
+
+
initialize all imported pygame modules
+
init() -> (numpass, numfail)
+
+

Initialize all imported pygame modules. No exceptions will be raised if a +module fails, but the total number if successful and failed inits will be +returned as a tuple. You can always initialize individual modules manually, +but pygame.init()initialize all imported pygame modules is a convenient way to get everything started. The +init() functions for individual modules will raise exceptions when they +fail.

+

You may want to initialize the different modules separately to speed up your +program or to not use modules your game does not require.

+

It is safe to call this init() more than once as repeated calls will have +no effect. This is true even if you have pygame.quit() all the modules.

+
+ +
+
+pygame.quit()¶
+
+
uninitialize all pygame modules
+
quit() -> None
+
+

Uninitialize all pygame modules that have previously been initialized. When +the Python interpreter shuts down, this method is called regardless, so your +program should not need it, except when it wants to terminate its pygame +resources and continue. It is safe to call this function more than once as +repeated calls have no effect.

+
+

Note

+

Calling pygame.quit()uninitialize all pygame modules will not exit your program. Consider letting +your program end in the same way a normal Python program will end.

+
+
+ +
+
+pygame.get_init()¶
+
+
returns True if pygame is currently initialized
+
get_init() -> bool
+
+

Returns True if pygame is currently initialized.

+
+

New in pygame 1.9.5.

+
+
+ +
+
+exception pygame.error¶
+
+
standard pygame exception
+
raise pygame.error(message)
+
+

This exception is raised whenever a pygame or SDL operation fails. You +can catch any anticipated problems and deal with the error. The exception is +always raised with a descriptive message about the problem.

+

Derived from the RuntimeError exception, which can also be used to catch +these raised errors.

+
+ +
+
+pygame.get_error()¶
+
+
get the current error message
+
get_error() -> errorstr
+
+

SDL maintains an internal error message. This message will usually be +given to you when pygame.error()standard pygame exception is raised, so this function will +rarely be needed.

+
+ +
+
+pygame.set_error()¶
+
+
set the current error message
+
set_error(error_msg) -> None
+
+

SDL maintains an internal error message. This message will usually be +given to you when pygame.error()standard pygame exception is raised, so this function will +rarely be needed.

+
+ +
+
+pygame.get_sdl_version()¶
+
+
get the version number of SDL
+
get_sdl_version() -> major, minor, patch
+
+

Returns the three version numbers of the SDL library. This version is built +at compile time. It can be used to detect which features may or may not be +available through pygame.

+
+

New in pygame 1.7.0.

+
+
+ +
+
+pygame.get_sdl_byteorder()¶
+
+
get the byte order of SDL
+
get_sdl_byteorder() -> int
+
+

Returns the byte order of the SDL library. It returns 1234 for little +endian byte order and 4321 for big endian byte order.

+
+

New in pygame 1.8.

+
+
+ +
+
+pygame.register_quit()¶
+
+
register a function to be called when pygame quits
+
register_quit(callable) -> None
+
+

When pygame.quit()uninitialize all pygame modules is called, all registered quit functions are +called. Pygame modules do this automatically when they are initializing, so +this function will rarely be needed.

+
+ +
+
+pygame.encode_string()¶
+
+
Encode a Unicode or bytes object
+
encode_string([obj [, encoding [, errors [, etype]]]]) -> bytes or None
+
+

obj: If Unicode, encode; if bytes, return unaltered; if anything else, +return None; if not given, raise SyntaxError.

+

encoding (string): If present, encoding to use. The default is +'unicode_escape'.

+

errors (string): If given, how to handle unencodable characters. The default +is 'backslashreplace'.

+

etype (exception type): If given, the exception type to raise for an +encoding error. The default is UnicodeEncodeError, as returned by +PyUnicode_AsEncodedString(). For the default encoding and errors values +there should be no encoding errors.

+

This function is used in encoding file paths. Keyword arguments are +supported.

+
+

New in pygame 1.9.2: (primarily for use in unit tests)

+
+
+ +
+
+pygame.encode_file_path()¶
+
+
Encode a Unicode or bytes object as a file system path
+
encode_file_path([obj [, etype]]) -> bytes or None
+
+

obj: If Unicode, encode; if bytes, return unaltered; if anything else, +return None; if not given, raise SyntaxError.

+

etype (exception type): If given, the exception type to raise for an +encoding error. The default is UnicodeEncodeError, as returned by +PyUnicode_AsEncodedString().

+

This function is used to encode file paths in pygame. Encoding is to the +codec as returned by sys.getfilesystemencoding(). Keyword arguments are +supported.

+
+

New in pygame 1.9.2: (primarily for use in unit tests)

+
+
+ +
+ +
+
+
+
+pygame.version
+
+
small module containing version information
+
+ +++++ + + + + + + + + + + + + + + + + + + +
+—version number as a string
+—tupled integers of the version
+—repository revision of the build
+—tupled integers of the SDL library version
+

This module is automatically imported into the pygame package and can be used to +check which version of pygame has been imported.

+
+
+pygame.version.ver¶
+
+
version number as a string
+
ver = '1.2'
+
+

This is the version represented as a string. It can contain a micro release +number as well, e.g. '1.5.2'

+
+ +
+
+pygame.version.vernum¶
+
+
tupled integers of the version
+
vernum = (1, 5, 3)
+
+

This version information can easily be compared with other version +numbers of the same format. An example of checking pygame version numbers +would look like this:

+
if pygame.version.vernum < (1, 5):
+    print('Warning, older version of pygame (%s)' %  pygame.version.ver)
+    disable_advanced_features = True
+
+
+
+

New in pygame 1.9.6: Attributes major, minor, and patch.

+
+
vernum.major == vernum[0]
+vernum.minor == vernum[1]
+vernum.patch == vernum[2]
+
+
+
+

Changed in pygame 1.9.6: str(pygame.version.vernum) returns a string like "2.0.0" instead +of "(2, 0, 0)".

+
+
+

Changed in pygame 1.9.6: repr(pygame.version.vernum) returns a string like +"PygameVersion(major=2, minor=0, patch=0)" instead of "(2, 0, 0)".

+
+
+ +
+
+pygame.version.rev¶
+
+
repository revision of the build
+
rev = 'a6f89747b551+'
+
+

The Mercurial node identifier of the repository checkout from which this +package was built. If the identifier ends with a plus sign '+' then the +package contains uncommitted changes. Please include this revision number +in bug reports, especially for non-release pygame builds.

+

Important note: pygame development has moved to github, this variable is +obsolete now. As soon as development shifted to github, this variable started +returning an empty string "". +It has always been returning an empty string since v1.9.5.

+
+

Changed in pygame 1.9.5: Always returns an empty string "".

+
+
+ +
+
+pygame.version.SDL¶
+
+
tupled integers of the SDL library version
+
SDL = '(2, 0, 12)'
+
+

This is the SDL library version represented as an extended tuple. It also has +attributes 'major', 'minor' & 'patch' that can be accessed like this:

+
>>> pygame.version.SDL.major
+2
+
+
+

printing the whole thing returns a string like this:

+
>>> pygame.version.SDL
+SDLVersion(major=2, minor=0, patch=12)
+
+
+
+

New in pygame 2.0.0.

+
+
+ +

Setting Environment Variables

+

Some aspects of pygame's behaviour can be controlled by setting environment variables, they cover a wide +range of the library's functionality. Some of the variables are from pygame itself, while others come from +the underlying C SDL library that pygame uses.

+

In python, environment variables are usually set in code like this:

+
import os
+os.environ['NAME_OF_ENVIRONMENT_VARIABLE'] = 'value_to_set'
+
+
+

Or to preserve users ability to override the variable:

+
import os
+os.environ['ENV_VAR'] = os.environ.get('ENV_VAR', 'value')
+
+
+

If the variable is more useful for users of an app to set than the developer then they can set it like this:

+

Windows:

+
set NAME_OF_ENVIRONMENT_VARIABLE=value_to_set
+python my_application.py
+
+
+

Linux/Mac:

+
ENV_VAR=value python my_application.py
+
+
+

For some variables they need to be set before initialising pygame, some must be set before even importing pygame, +and others can simply be set right before the area of code they control is run.

+

Below is a list of environment variables, their settable values, and a brief description of what they do.

+
+

+
+

Pygame Environment Variables

+

These variables are defined by pygame itself.

+
+

+
+
PYGAME_DISPLAY - Experimental (subject to change)
+Set index of the display to use, "0" is the default.
+
+
+

This sets the display where pygame will open its window +or screen. The value set here will be used if set before +calling pygame.display.set_mode()Initialize a window or screen for display, and as long as no +'display' parameter is passed into pygame.display.set_mode()Initialize a window or screen for display.

+
+

+
+
PYGAME_FORCE_SCALE -
+Set to "photo" or "default".
+
+
+

This forces set_mode() to use the SCALED display mode and, +if "photo" is set, makes the scaling use the slowest, but +highest quality anisotropic scaling algorithm, if it is +available. Must be set before calling pygame.display.set_mode()Initialize a window or screen for display.

+
+

+
+
PYGAME_BLEND_ALPHA_SDL2 - New in pygame 2.0.0
+Set to "1" to enable the SDL2 blitter.
+
+
+

This makes pygame use the SDL2 blitter for all alpha +blending. The SDL2 blitter is sometimes faster than +the default blitter but uses a different formula so +the final colours may differ. Must be set before +pygame.init()initialize all imported pygame modules is called.

+
+

+
+
PYGAME_HIDE_SUPPORT_PROMPT -
+Set to "1" to hide the prompt.
+
+
+

This stops the welcome message popping up in the +console that tells you which version of python, +pygame & SDL you are using. Must be set before +importing pygame.

+
+

+
+
PYGAME_FREETYPE -
+Set to "1" to enable.
+
+
+

This switches the pygame.font module to a pure +freetype implementation that bypasses SDL_ttf. +See the font module for why you might want to +do this. Must be set before importing pygame.

+
+

+
+
PYGAME_CAMERA -
+Set to "opencv" or "vidcapture"
+
+
+

Forces the library backend used in the camera +module, overriding the platform defaults. Must +be set before calling pygame.camera.init()Module init.

+

In pygame 2.0.3, backends can be set programmatically instead, and the old +OpenCV backend has been replaced with one on top of "opencv-python," rather +than the old "highgui" OpenCV port. Also, there is a new native Windows +backend available.

+
+

+

+
+

SDL Environment Variables

+

These variables are defined by SDL.

+

For documentation on the environment variables available in +pygame 1 try here. +For Pygame 2, some selected environment variables are listed below.

+
+

+
+
SDL_VIDEO_CENTERED -
+Set to "1" to enable centering the window.
+
+
+

This will make the pygame window open in the centre of the display. +Must be set before calling pygame.display.set_mode()Initialize a window or screen for display.

+
+

+
+
SDL_VIDEO_WINDOW_POS -
+Set to "x,y" to position the top left corner of the window.
+
+
+

This allows control over the placement of the pygame window within +the display. Must be set before calling pygame.display.set_mode()Initialize a window or screen for display.

+
+

+
+
SDL_VIDEODRIVER -
+Set to "drivername" to change the video driver used.
+
+
+

On some platforms there are multiple video drivers available and +this allows users to pick between them. More information is available +here. Must be set before +calling pygame.init()initialize all imported pygame modules or pygame.display.init()Initialize the display module.

+
+

+
+
SDL_AUDIODRIVER -
+Set to "drivername" to change the audio driver used.
+
+
+

On some platforms there are multiple audio drivers available and +this allows users to pick between them. More information is available +here. Must be set before +calling pygame.init()initialize all imported pygame modules or pygame.mixer.init()initialize the mixer module.

+
+

+
+
SDL_VIDEO_ALLOW_SCREENSAVER
+Set to "1" to allow screensavers while pygame apps are running.
+
+
+

By default pygame apps disable screensavers while +they are running. Setting this environment variable allows users or +developers to change that and make screensavers run again.

+
+

+
+
SDL_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR
+Set to "0" to re-enable the compositor.
+
+
+

By default SDL tries to disable the X11 compositor for all pygame +apps. This is usually a good thing as it's faster, however if you +have an app which doesn't update every frame and are using linux +you may want to disable this bypass. The bypass has reported problems +on KDE linux. This variable is only used on x11/linux platforms.

+
+ +
+ + +

+
+Edit on GitHub +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/ref/rect.html b/venv/Lib/site-packages/pygame/docs/generated/ref/rect.html new file mode 100644 index 0000000..11c4188 --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/ref/rect.html @@ -0,0 +1,672 @@ + + + + + + + + + pygame.Rect — pygame v2.1.2 documentation + + + + + + + + + + + + + +
+ +
+ + + + + +
+
+ +
+
+ +
+
+
+pygame.Rect¶
+
+
pygame object for storing rectangular coordinates
+
Rect(left, top, width, height) -> Rect
+
Rect((left, top), (width, height)) -> Rect
+
Rect(object) -> Rect
+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+—copy the rectangle
+—moves the rectangle
+—moves the rectangle, in place
+—grow or shrink the rectangle size
+—grow or shrink the rectangle size, in place
+—sets the position and size of the rectangle
+—moves the rectangle inside another
+—moves the rectangle inside another, in place
+—crops a rectangle inside another
+—crops a line inside a rectangle
+—joins two rectangles into one
+—joins two rectangles into one, in place
+—the union of many rectangles
+—the union of many rectangles, in place
+—resize and move a rectangle with aspect ratio
+—correct negative sizes
+—test if one rectangle is inside another
+—test if a point is inside a rectangle
+—test if two rectangles overlap
+—test if one rectangle in a list intersects
+—test if all rectangles in a list intersect
+—test if one rectangle in a dictionary intersects
+—test if all rectangles in a dictionary intersect
+

Pygame uses Rect objects to store and manipulate rectangular areas. A Rect +can be created from a combination of left, top, width, and height values. +Rects can also be created from python objects that are already a Rect or +have an attribute named "rect".

+

Any pygame function that requires a Rect argument also accepts any of these +values to construct a Rect. This makes it easier to create Rects on the fly +as arguments to functions.

+

The Rect functions that change the position or size of a Rect return a new +copy of the Rect with the affected changes. The original Rect is not +modified. Some methods have an alternate "in-place" version that returns +None but affects the original Rect. These "in-place" methods are denoted +with the "ip" suffix.

+

The Rect object has several virtual attributes which can be used to move and +align the Rect:

+
x,y
+top, left, bottom, right
+topleft, bottomleft, topright, bottomright
+midtop, midleft, midbottom, midright
+center, centerx, centery
+size, width, height
+w,h
+
+
+

All of these attributes can be assigned to:

+
rect1.right = 10
+rect2.center = (20,30)
+
+
+

Assigning to size, width or height changes the dimensions of the rectangle; +all other assignments move the rectangle without resizing it. Notice that +some attributes are integers and others are pairs of integers.

+

If a Rect has a nonzero width or height, it will return True for a +nonzero test. Some methods return a Rect with 0 size to represent an invalid +rectangle. A Rect with a 0 size will not collide when using collision +detection methods (e.g. collidepoint(), colliderect(), etc.).

+

The coordinates for Rect objects are all integers. The size values can be +programmed to have negative values, but these are considered illegal Rects +for most operations.

+

There are several collision tests between other rectangles. Most python +containers can be searched for collisions against a single Rect.

+

The area covered by a Rect does not include the right- and bottom-most edge +of pixels. If one Rect's bottom border is another Rect's top border (i.e., +rect1.bottom=rect2.top), the two meet exactly on the screen but do not +overlap, and rect1.colliderect(rect2) returns false.

+
+

New in pygame 1.9.2: The Rect class can be subclassed. Methods such as copy() and move() +will recognize this and return instances of the subclass. +However, the subclass's __init__() method is not called, +and __new__() is assumed to take no arguments. So these methods should be +overridden if any extra attributes need to be copied.

+
+
+
+copy()¶
+
+
copy the rectangle
+
copy() -> Rect
+
+

Returns a new rectangle having the same position and size as the original.

+

New in pygame 1.9

+
+ +
+
+move()¶
+
+
moves the rectangle
+
move(x, y) -> Rect
+
+

Returns a new rectangle that is moved by the given offset. The x and y +arguments can be any integer value, positive or negative.

+
+ +
+
+move_ip()¶
+
+
moves the rectangle, in place
+
move_ip(x, y) -> None
+
+

Same as the Rect.move() method, but operates in place.

+
+ +
+
+inflate()¶
+
+
grow or shrink the rectangle size
+
inflate(x, y) -> Rect
+
+

Returns a new rectangle with the size changed by the given offset. The +rectangle remains centered around its current center. Negative values +will shrink the rectangle. Note, uses integers, if the offset given is +too small(< 2 > -2), center will be off.

+
+ +
+
+inflate_ip()¶
+
+
grow or shrink the rectangle size, in place
+
inflate_ip(x, y) -> None
+
+

Same as the Rect.inflate() method, but operates in place.

+
+ +
+
+update()¶
+
+
sets the position and size of the rectangle
+
update(left, top, width, height) -> None
+
update((left, top), (width, height)) -> None
+
update(object) -> None
+
+

Sets the position and size of the rectangle, in place. See +parameters for pygame.Rect()pygame object for storing rectangular coordinates for the parameters of this function.

+
+

New in pygame 2.0.1.

+
+
+ +
+
+clamp()¶
+
+
moves the rectangle inside another
+
clamp(Rect) -> Rect
+
+

Returns a new rectangle that is moved to be completely inside the +argument Rect. If the rectangle is too large to fit inside, it is +centered inside the argument Rect, but its size is not changed.

+
+ +
+
+clamp_ip()¶
+
+
moves the rectangle inside another, in place
+
clamp_ip(Rect) -> None
+
+

Same as the Rect.clamp() method, but operates in place.

+
+ +
+
+clip()¶
+
+
crops a rectangle inside another
+
clip(Rect) -> Rect
+
+

Returns a new rectangle that is cropped to be completely inside the +argument Rect. If the two rectangles do not overlap to begin with, a Rect +with 0 size is returned.

+
+ +
+
+clipline()¶
+
+
crops a line inside a rectangle
+
clipline(x1, y1, x2, y2) -> ((cx1, cy1), (cx2, cy2))
+
clipline(x1, y1, x2, y2) -> ()
+
clipline((x1, y1), (x2, y2)) -> ((cx1, cy1), (cx2, cy2))
+
clipline((x1, y1), (x2, y2)) -> ()
+
clipline((x1, y1, x2, y2)) -> ((cx1, cy1), (cx2, cy2))
+
clipline((x1, y1, x2, y2)) -> ()
+
clipline(((x1, y1), (x2, y2))) -> ((cx1, cy1), (cx2, cy2))
+
clipline(((x1, y1), (x2, y2))) -> ()
+
+

Returns the coordinates of a line that is cropped to be completely inside +the rectangle. If the line does not overlap the rectangle, then an empty +tuple is returned.

+

The line to crop can be any of the following formats (floats can be used +in place of ints, but they will be truncated):

+
+
    +
  • four ints

  • +
  • 2 lists/tuples/Vector2s of 2 ints

  • +
  • a list/tuple of four ints

  • +
  • a list/tuple of 2 lists/tuples/Vector2s of 2 ints

  • +
+
+
+
Returns
+

a tuple with the coordinates of the given line cropped to be +completely inside the rectangle is returned, if the given line does +not overlap the rectangle, an empty tuple is returned

+
+
Return type
+

tuple(tuple(int, int), tuple(int, int)) or ()

+
+
Raises
+

TypeError -- if the line coordinates are not given as one of the +above described line formats

+
+
+
+

Note

+

This method can be used for collision detection between a rect and a +line. See example code below.

+
+
+

Note

+

The rect.bottom and rect.right attributes of a +pygame.Rectpygame object for storing rectangular coordinates always lie one pixel outside of its actual border.

+
+
# Example using clipline().
+clipped_line = rect.clipline(line)
+
+if clipped_line:
+    # If clipped_line is not an empty tuple then the line
+    # collides/overlaps with the rect. The returned value contains
+    # the endpoints of the clipped line.
+    start, end = clipped_line
+    x1, y1 = start
+    x2, y2 = end
+else:
+    print("No clipping. The line is fully outside the rect.")
+
+
+
+

New in pygame 2.0.0.

+
+
+ +
+
+union()¶
+
+
joins two rectangles into one
+
union(Rect) -> Rect
+
+

Returns a new rectangle that completely covers the area of the two +provided rectangles. There may be area inside the new Rect that is not +covered by the originals.

+
+ +
+
+union_ip()¶
+
+
joins two rectangles into one, in place
+
union_ip(Rect) -> None
+
+

Same as the Rect.union() method, but operates in place.

+
+ +
+
+unionall()¶
+
+
the union of many rectangles
+
unionall(Rect_sequence) -> Rect
+
+

Returns the union of one rectangle with a sequence of many rectangles.

+
+ +
+
+unionall_ip()¶
+
+
the union of many rectangles, in place
+
unionall_ip(Rect_sequence) -> None
+
+

The same as the Rect.unionall() method, but operates in place.

+
+ +
+
+fit()¶
+
+
resize and move a rectangle with aspect ratio
+
fit(Rect) -> Rect
+
+

Returns a new rectangle that is moved and resized to fit another. The +aspect ratio of the original Rect is preserved, so the new rectangle may +be smaller than the target in either width or height.

+
+ +
+
+normalize()¶
+
+
correct negative sizes
+
normalize() -> None
+
+

This will flip the width or height of a rectangle if it has a negative +size. The rectangle will remain in the same place, with only the sides +swapped.

+
+ +
+
+contains()¶
+
+
test if one rectangle is inside another
+
contains(Rect) -> bool
+
+

Returns true when the argument is completely inside the Rect.

+
+ +
+
+collidepoint()¶
+
+
test if a point is inside a rectangle
+
collidepoint(x, y) -> bool
+
collidepoint((x,y)) -> bool
+
+

Returns true if the given point is inside the rectangle. A point along +the right or bottom edge is not considered to be inside the rectangle.

+
+

Note

+

For collision detection between a rect and a line the clipline() +method can be used.

+
+
+ +
+
+colliderect()¶
+
+
test if two rectangles overlap
+
colliderect(Rect) -> bool
+
+

Returns true if any portion of either rectangle overlap (except the +top+bottom or left+right edges).

+
+

Note

+

For collision detection between a rect and a line the clipline() +method can be used.

+
+
+ +
+
+collidelist()¶
+
+
test if one rectangle in a list intersects
+
collidelist(list) -> index
+
+

Test whether the rectangle collides with any in a sequence of rectangles. +The index of the first collision found is returned. If no collisions are +found an index of -1 is returned.

+
+ +
+
+collidelistall()¶
+
+
test if all rectangles in a list intersect
+
collidelistall(list) -> indices
+
+

Returns a list of all the indices that contain rectangles that collide +with the Rect. If no intersecting rectangles are found, an empty list is +returned.

+
+ +
+
+collidedict()¶
+
+
test if one rectangle in a dictionary intersects
+
collidedict(dict) -> (key, value)
+
collidedict(dict) -> None
+
collidedict(dict, use_values=0) -> (key, value)
+
collidedict(dict, use_values=0) -> None
+
+

Returns the first key and value pair that intersects with the calling +Rect object. If no collisions are found, None is returned. If +use_values is 0 (default) then the dict's keys will be used in the +collision detection, otherwise the dict's values will be used.

+
+

Note

+

Rect objects cannot be used as keys in a dictionary (they are not +hashable), so they must be converted to a tuple. +e.g. rect.collidedict({tuple(key_rect) : value})

+
+
+ +
+
+collidedictall()¶
+
+
test if all rectangles in a dictionary intersect
+
collidedictall(dict) -> [(key, value), ...]
+
collidedictall(dict, use_values=0) -> [(key, value), ...]
+
+

Returns a list of all the key and value pairs that intersect with the +calling Rect object. If no collisions are found an empty list is returned. +If use_values is 0 (default) then the dict's keys will be used in the +collision detection, otherwise the dict's values will be used.

+
+

Note

+

Rect objects cannot be used as keys in a dictionary (they are not +hashable), so they must be converted to a tuple. +e.g. rect.collidedictall({tuple(key_rect) : value})

+
+
+ +
+ +
+ + +

+
+Edit on GitHub +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/ref/scrap.html b/venv/Lib/site-packages/pygame/docs/generated/ref/scrap.html new file mode 100644 index 0000000..96c7eec --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/ref/scrap.html @@ -0,0 +1,458 @@ + + + + + + + + + pygame.scrap — pygame v2.1.2 documentation + + + + + + + + + + + + + +
+ +
+ + + + + +
+
+ +
+
+ +
+
+
+pygame.scrap
+
+
pygame module for clipboard support.
+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+—Initializes the scrap module.
+—Returns True if the scrap module is currently initialized.
+—Gets the data for the specified type from the clipboard.
+—Gets a list of the available clipboard types.
+—Places data into the clipboard.
+—Checks whether data for a given type is available in the clipboard.
+—Indicates if the clipboard ownership has been lost by the pygame application.
+—Sets the clipboard access mode.
+

EXPERIMENTAL!: This API may change or disappear in later pygame releases. If +you use this, your code may break with the next pygame release.

+

The scrap module is for transferring data to/from the clipboard. This allows +for cutting and pasting data between pygame and other applications. Some basic +data (MIME) types are defined and registered:

+
 pygame         string
+constant        value        description
+--------------------------------------------------
+SCRAP_TEXT   "text/plain"    plain text
+SCRAP_BMP    "image/bmp"     BMP encoded image data
+SCRAP_PBM    "image/pbm"     PBM encoded image data
+SCRAP_PPM    "image/ppm"     PPM encoded image data
+
+
+

pygame.SCRAP_PPM, pygame.SCRAP_PBM and pygame.SCRAP_BMP are +suitable for surface buffers to be shared with other applications. +pygame.SCRAP_TEXT is an alias for the plain text clipboard type.

+

Depending on the platform, additional types are automatically registered when +data is placed into the clipboard to guarantee a consistent sharing behaviour +with other applications. The following listed types can be used as strings to +be passed to the respective pygame.scrappygame module for clipboard support. module functions.

+

For Windows platforms, these additional types are supported automatically +and resolve to their internal definitions:

+
"text/plain;charset=utf-8"   UTF-8 encoded text
+"audio/wav"                  WAV encoded audio
+"image/tiff"                 TIFF encoded image data
+
+
+

For X11 platforms, these additional types are supported automatically and +resolve to their internal definitions:

+
"text/plain;charset=utf-8"   UTF-8 encoded text
+"UTF8_STRING"                UTF-8 encoded text
+"COMPOUND_TEXT"              COMPOUND text
+
+
+

User defined types can be used, but the data might not be accessible by other +applications unless they know what data type to look for. +Example: Data placed into the clipboard by +pygame.scrap.put("my_data_type", byte_data) can only be accessed by +applications which query the clipboard for the "my_data_type" data type.

+

For an example of how the scrap module works refer to the examples page +(pygame.examples.scrap_clipboard.main()access the clipboard) or the code directly in GitHub +(pygame/examples/scrap_clipboard.py).

+
+

New in pygame 1.8.

+
+
+

Note

+

The scrap module is currently only supported for Windows, X11 and Mac OS X. +On Mac OS X only text works at the moment - other types may be supported in +future releases.

+
+
+
+pygame.scrap.init()¶
+
+
Initializes the scrap module.
+
init() -> None
+
+

Initialize the scrap module.

+
+
Raises
+

pygame.errorstandard pygame exception -- if unable to initialize scrap module

+
+
+
+

Note

+

The scrap module requires pygame.display.set_mode()Initialize a window or screen for display be +called before being initialized.

+
+
+ +
+
+pygame.scrap.get_init()¶
+
+
Returns True if the scrap module is currently initialized.
+
get_init() -> bool
+
+

Gets the scrap module's initialization state.

+
+
Returns
+

True if the pygame.scrappygame module for clipboard support. module is currently +initialized, False otherwise

+
+
Return type
+

bool

+
+
+
+

New in pygame 1.9.5.

+
+
+ +
+
+pygame.scrap.get()¶
+
+
Gets the data for the specified type from the clipboard.
+
get(type) -> bytes | None
+
+

Retrieves the data for the specified type from the clipboard. The data is +returned as a byte string and might need further processing (such as +decoding to Unicode).

+
+
Parameters
+

type (string) -- data type to retrieve from the clipboard

+
+
Returns
+

data (bytes object) for the given type identifier or None if +no data for the given type is available

+
+
Return type
+

bytes | None

+
+
+
text = pygame.scrap.get(pygame.SCRAP_TEXT)
+if text:
+    print("There is text in the clipboard.")
+else:
+    print("There does not seem to be text in the clipboard.")
+
+
+
+ +
+
+pygame.scrap.get_types()¶
+
+
Gets a list of the available clipboard types.
+
get_types() -> list
+
+

Gets a list of data type string identifiers for the data currently +available on the clipboard. Each identifier can be used in the +pygame.scrap.get()Gets the data for the specified type from the clipboard. method to get the clipboard content of the +specific type.

+
+
Returns
+

list of strings of the available clipboard data types, if there +is no data in the clipboard an empty list is returned

+
+
Return type
+

list

+
+
+
for t in pygame.scrap.get_types():
+    if "text" in t:
+        # There is some content with the word "text" in its type string.
+        print(pygame.scrap.get(t))
+
+
+
+ +
+
+pygame.scrap.put()¶
+
+
Places data into the clipboard.
+
put(type, data) -> None
+
+

Places data for a given clipboard type into the clipboard. The data must +be a string buffer. The type is a string identifying the type of data to be +placed into the clipboard. This can be one of the predefined +pygame.SCRAP_PBM, pygame.SCRAP_PPM, pygame.SCRAP_BMP or +pygame.SCRAP_TEXT values or a user defined string identifier.

+
+
Parameters
+
    +
  • type (string) -- type identifier of the data to be placed into the +clipboard

  • +
  • data (bytes) -- data to be place into the clipboard, a bytes object

  • +
+
+
Raises
+

pygame.errorstandard pygame exception -- if unable to put the data into the clipboard

+
+
+
with open("example.bmp", "rb") as fp:
+    pygame.scrap.put(pygame.SCRAP_BMP, fp.read())
+# The image data is now on the clipboard for other applications to access
+# it.
+pygame.scrap.put(pygame.SCRAP_TEXT, b"A text to copy")
+pygame.scrap.put("Plain text", b"Data for user defined type 'Plain text'")
+
+
+
+ +
+
+pygame.scrap.contains()¶
+
+
Checks whether data for a given type is available in the clipboard.
+
contains(type) -> bool
+
+

Checks whether data for the given type is currently available in the +clipboard.

+
+
Parameters
+

type (string) -- data type to check availability of

+
+
Returns
+

True if data for the passed type is available in the +clipboard, False otherwise

+
+
Return type
+

bool

+
+
+
if pygame.scrap.contains(pygame.SCRAP_TEXT):
+    print("There is text in the clipboard.")
+if pygame.scrap.contains("own_data_type"):
+    print("There is stuff in the clipboard.")
+
+
+
+ +
+
+pygame.scrap.lost()¶
+
+
Indicates if the clipboard ownership has been lost by the pygame application.
+
lost() -> bool
+
+

Indicates if the clipboard ownership has been lost by the pygame +application.

+
+
Returns
+

True, if the clipboard ownership has been lost by the pygame +application, False if the pygame application still owns the clipboard

+
+
Return type
+

bool

+
+
+
if pygame.scrap.lost():
+    print("The clipboard is in use by another application.")
+
+
+
+ +
+
+pygame.scrap.set_mode()¶
+
+
Sets the clipboard access mode.
+
set_mode(mode) -> None
+
+

Sets the access mode for the clipboard. This is only of interest for X11 +environments where clipboard modes pygame.SCRAP_SELECTION (for mouse +selections) and pygame.SCRAP_CLIPBOARD (for the clipboard) are +available. Setting the mode to pygame.SCRAP_SELECTION in other +environments will not change the mode from pygame.SCRAP_CLIPBOARD.

+
+
Parameters
+

mode -- access mode, supported values are pygame.SCRAP_CLIPBOARD +and pygame.SCRAP_SELECTION (pygame.SCRAP_SELECTION only has an +effect when used on X11 platforms)

+
+
Raises
+

ValueError -- if the mode parameter is not +pygame.SCRAP_CLIPBOARD or pygame.SCRAP_SELECTION

+
+
+
+ +
+ +
+ + +

+
+Edit on GitHub +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/ref/sdl2_controller.html b/venv/Lib/site-packages/pygame/docs/generated/ref/sdl2_controller.html new file mode 100644 index 0000000..a62ed46 --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/ref/sdl2_controller.html @@ -0,0 +1,569 @@ + + + + + + + + + pygame._sdl2.controller — pygame v2.1.2 documentation + + + + + + + + + + + + + +
+ +
+ + + + + +
+
+ +
+
+ +
+
+
+pygame._sdl2.controller
+
+
Pygame module to work with controllers.
+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+—initialize the controller module
+—Uninitialize the controller module.
+—Returns True if the controller module is initialized.
+—Sets the current state of events related to controllers
+—Gets the current state of events related to controllers
+—Get the number of joysticks connected
+—Check if the given joystick is supported by the game controller interface
+—Get the name of the contoller
+—Create a new Controller object.
+

This module offers control over common controller types like the dualshock 4 or +the xbox 360 controllers: They have two analog sticks, two triggers, two shoulder buttons, +a dpad, 4 buttons on the side, 2 (or 3) buttons in the middle.

+

Pygame uses xbox controllers naming conventions (like a, b, x, y for buttons) but +they always refer to the same buttons. For example CONTROLLER_BUTTON_X is +always the leftmost button of the 4 buttons on the right.

+

Controllers can generate the following events:

+
CONTROLLERAXISMOTION, CONTROLLERBUTTONDOWN, CONTROLLERBUTTONUP,
+CONTROLLERDEVICEREMAPPED, CONTROLLERDEVICEADDED, CONTROLLERDEVICEREMOVED
+
+
+

Additionally if pygame is built with SDL 2.0.14 or higher the following events can also be generated +(to get the version of sdl pygame is built with use pygame.version.SDL()tupled integers of the SDL library version):

+
CONTROLLERTOUCHPADDOWN, CONTROLLERTOUCHPADMOTION, CONTROLLERTOUCHPADUP
+
+
+

These events can be enabled/disabled by pygame._sdl2.controller.set_eventstate()Sets the current state of events related to controllers +Note that controllers can generate joystick events as well. This function only toggles +events related to controllers.

+
+

Note

+

See the pygame.joystickPygame module for interacting with joysticks, gamepads, and trackballs. for a more versatile but more advanced api.

+
+
+

New in pygame 2: This module requires SDL2.

+
+
+
+pygame._sdl2.controller.init()¶
+
+
initialize the controller module
+
init() -> None
+
+

Initialize the controller module.

+
+ +
+
+pygame._sdl2.controller.quit()¶
+
+
Uninitialize the controller module.
+
quit() -> None
+
+

Uninitialize the controller module.

+
+ +
+
+pygame._sdl2.controller.get_init()¶
+
+
Returns True if the controller module is initialized.
+
get_init() -> bool
+
+

Test if pygame._sdl2.controller.init() was called.

+
+
+
+ +
+
+pygame._sdl2.controller.set_eventstate()¶
+
+
Sets the current state of events related to controllers
+
set_eventstate(state) -> None
+
+

Enable or disable events connected to controllers.

+
+

Note

+

Controllers can still generate joystick events, which will not be toggled by this function.

+
+
+

Changed in pygame 2.0.2:: Changed return type from int to None

+
+
+ +
+
+pygame._sdl2.controller.get_eventstate()¶
+
+
Gets the current state of events related to controllers
+
get_eventstate() -> bool
+
+

Returns the current state of events related to controllers, True meaning +events will be posted.

+
+

New in pygame 2.0.2.

+
+
+ +
+
+pygame._sdl2.controller.get_count()¶
+
+
Get the number of joysticks connected
+
get_count() -> int
+
+

Get the number of joysticks connected.

+
+ +
+
+pygame._sdl2.controller.is_controller()¶
+
+
Check if the given joystick is supported by the game controller interface
+
is_controller(index) -> bool
+
+

Returns True if the index given can be used to create a controller object.

+
+ +
+
+pygame._sdl2.controller.name_forindex()¶
+
+
Get the name of the contoller
+
name_forindex(index) -> name or None
+
+

Returns the name of controller, or None if there's no name or the +index is invalid.

+
+ +
+
+pygame._sdl2.controller.Controller¶
+
+
+
Create a new Controller object.
+
Controller(index) -> Controller
+
+

Create a new Controller object. Index should be integer between +0 and pygame._sdl2.contoller.get_count(). Controllers also +can be created from a pygame.joystick.Joystick using +pygame._sdl2.controller.from_joystick. Controllers are +initialized on creation.

+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+—uninitialize the Controller
+—check if the Controller is initialized
+—Create a Controller from a pygame.joystick.Joystick object
+—Check if the Controller has been opened and is currently connected.
+—Returns a pygame.joystick.Joystick() object
+—Get the current state of a joystick axis
+—Get the current state of a button
+—Get the mapping assigned to the controller
+—Assign a mapping to the controller
+—Start a rumbling effect
+—Stop any rumble effect playing
+
+
+quit()¶
+
+
uninitialize the Controller
+
quit() -> None
+
+

Close a Controller object. After this the pygame event queue will no longer +receive events from the device.

+

It is safe to call this more than once.

+
+ +
+
+get_init()¶
+
+
check if the Controller is initialized
+
get_init() -> bool
+
+

Returns True if the Controller object is currently initialised.

+
+ +
+
+static from_joystick()¶
+
+
Create a Controller from a pygame.joystick.Joystick object
+
from_joystick(joystick) -> Controller
+
+

Create a Controller object from a pygame.joystick.Joystick object

+
+ +
+
+attached()¶
+
+
Check if the Controller has been opened and is currently connected.
+
attached() -> bool
+
+

Returns True if the Controller object is opened and connected.

+
+ +
+
+as_joystick()¶
+
+
Returns a pygame.joystick.Joystick() object
+
as_joystick() -> Joystick object
+
+

Returns a pygame.joystick.Joystick() object created from this controller's index

+
+ +
+
+get_axis()¶
+
+
Get the current state of a joystick axis
+
get_axis(axis) -> int
+
+

Get the current state of a trigger or joystick axis. +The axis argument must be one of the following constants:

+
CONTROLLER_AXIS_LEFTX, CONTROLLER_AXIS_LEFTY,
+CONTROLLER_AXIS_RIGHTX, CONTROLLER_AXIS_RIGHTY,
+CONTROLLER_AXIS_TRIGGERLEFT, CONTROLLER_AXIS_TRIGGERRIGHT
+
+
+

Joysticks can return a value between -32768 and 32767. Triggers however +can only return a value between 0 and 32768.

+
+ +
+
+get_button()¶
+
+
Get the current state of a button
+
get_button(button) -> bool
+
+

Get the current state of a button, True meaning it is pressed down. +The button argument must be one of the following constants:

+
CONTROLLER_BUTTON_A, CONTROLLER_BUTTON_B,
+CONTROLLER_BUTTON_X, CONTROLLER_BUTTON_Y
+CONTROLLER_BUTTON_DPAD_UP, CONTROLLER_BUTTON_DPAD_DOWN,
+CONTROLLER_BUTTON_DPAD_LEFT, CONTROLLER_BUTTON_DPAD_RIGHT,
+CONTROLLER_BUTTON_LEFTSHOULDER, CONTROLLER_BUTTON_RIGHTSHOULDER,
+CONTROLLER_BUTTON_LEFTSTICK, CONTROLLER_BUTTON_RIGHTSTICK,
+CONTROLLER_BUTTON_BACK, CONTROLLER_BUTTON_GUIDE,
+CONTROLLER_BUTTON_START
+
+
+
+ +
+
+get_mapping()¶
+
+
Get the mapping assigned to the controller
+
get_mapping() -> mapping
+
+

Returns a dict containing the mapping of the Controller. For more +information see Controller.set_mapping()

+
+

Changed in pygame 2.0.2:: Return type changed from str to dict

+
+
+ +
+
+set_mapping()¶
+
+
Assign a mapping to the controller
+
set_mapping(mapping) -> int
+
+

Rebind buttons, axes, triggers and dpads. The mapping should be a +dict containing all buttons, hats and axes. The easiest way to get this +is to use the dict returned by Controller.get_mapping(). To edit +this mapping assign a value to the original button. The value of the +dictionary must be a button, hat or axis represented in the following way:

+
    +
  • For a button use: bX where X is the index of the button.

  • +
  • For a hat use: hX.Y where X is the index and the Y is the direction (up: 1, right: 2, down: 3, left: 4).

  • +
  • For an axis use: aX where x is the index of the axis.

  • +
+

An example of mapping:

+
mapping = controller.get_mapping() # Get current mapping
+mapping["a"] = "b3" # Remap button a to y
+mapping["y"] = "b0" # Remap button y to a
+controller.set_mapping(mapping) # Set the mapping
+
+
+

The function will return 1 if a new mapping is added or 0 if an existing one is updated.

+
+

Changed in pygame 2.0.2:: Renamed from add_mapping to set_mapping

+
+
+

Changed in pygame 2.0.2:: Argument type changed from str to dict

+
+
+ +
+
+rumble()¶
+
+
Start a rumbling effect
+
rumble(low_frequency, high_frequency, duration) -> bool
+
+

Start a rumble effect on the controller, with the specified strength ranging +from 0 to 1. Duration is length of the effect, in ms. Setting the duration +to 0 will play the effect until another one overwrites it or +Controller.stop_rumble() is called. If an effect is already +playing, then it will be overwritten.

+

Returns True if the rumble was played successfully or False if the +controller does not support it or pygame.version.SDL()tupled integers of the SDL library version is below 2.0.9.

+
+

New in pygame 2.0.2.

+
+
+ +
+
+stop_rumble()¶
+
+
Stop any rumble effect playing
+
stop_rumble() -> None
+
+

Stops any rumble effect playing on the controller. See +Controller.rumble() for more information.

+
+

New in pygame 2.0.2.

+
+
+ +
+ +
+ +
+ + +

+
+Edit on GitHub +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/ref/sdl2_video.html b/venv/Lib/site-packages/pygame/docs/generated/ref/sdl2_video.html new file mode 100644 index 0000000..7968b16 --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/ref/sdl2_video.html @@ -0,0 +1,1091 @@ + + + + + + + + + pygame.sdl2_video — pygame v2.1.2 documentation + + + + + + + + + + + + + +
+ +
+ + + + + +
+
+ +
+
+ +
+
+
+pygame.sdl2_video
+
+

Warning

+

This module isn't ready for prime time yet, it's still in development. +These docs are primarily meant to help the pygame developers and super-early adopters +who are in communication with the developers. This API will change.

+
+ +++++ + + + + + + + + + + + + + + + + + + +
+—pygame object that represents a window
+—pygame object that representing a Texture.
+—Easy way to use a portion of a Texture without worrying about srcrect all the time.
+—Create a 2D rendering context for a window.
+
+
Experimental pygame module for porting new SDL video systems
+
+
+
+pygame._sdl2.video.Window¶
+
+
pygame object that represents a window
+
Window(title="pygame", size=(640, 480), position=None, fullscreen=False, fullscreen_desktop=False, keywords) -> Window
+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+—Creates window using window created by pygame.display.set_mode().
+—Gets or sets whether the mouse is confined to the window.
+—Gets or sets the window's relative mouse motion state.
+—Enable windowed mode (exit fullscreen).
+—Enter fullscreen.
+—Gets or sets whether the window title.
+—Destroys the window.
+—Hide the window.
+—Show the window.
+—Raise the window above other windows and set the input focus. The "input_only" argument is only supported on X11.
+—Restore the size and position of a minimized or maximized window.
+—Maximize the window.
+—Minimize the window.
+—Gets and sets whether the window is resizable.
+—Add or remove the border from the window.
+—Set the icon for the window.
+—Get the unique window ID. *Read-only*
+—Gets and sets the window size.
+—Gets and sets the window position.
+—Gets and sets the window opacity. Between 0.0 (fully transparent) and 1.0 (fully opaque).
+—Gets and sets the brightness (gamma multiplier) for the display that owns the window.
+—Get the index of the display that owns the window. *Read-only*
+—Set the window as a modal for a parent window. This function is only supported on X11.
+
+
+classmethod from_display_module()¶
+
+
Creates window using window created by pygame.display.set_mode().
+
from_display_module() -> Window
+
+
+ +
+
+grab¶
+
+
Gets or sets whether the mouse is confined to the window.
+
grab -> bool
+
+
+ +
+
+relative_mouse¶
+
+
Gets or sets the window's relative mouse motion state.
+
relative_mouse -> bool
+
+
+ +
+
+set_windowed()¶
+
+
Enable windowed mode (exit fullscreen).
+
set_windowed() -> None
+
+
+ +
+
+set_fullscreen()¶
+
+
Enter fullscreen.
+
set_fullscreen(desktop=False) -> None
+
+
+ +
+
+title¶
+
+
Gets or sets whether the window title.
+
title -> string
+
+
+ +
+
+destroy()¶
+
+
Destroys the window.
+
destroy() -> None
+
+
+ +
+
+hide()¶
+
+
Hide the window.
+
hide() -> None
+
+
+ +
+
+show()¶
+
+
Show the window.
+
show() -> None
+
+
+ +
+
+focus()¶
+
+
Raise the window above other windows and set the input focus. The "input_only" argument is only supported on X11.
+
focus(input_only=False) -> None
+
+
+ +
+
+restore()¶
+
+
Restore the size and position of a minimized or maximized window.
+
restore() -> None
+
+
+ +
+
+maximize()¶
+
+
Maximize the window.
+
maximize() -> None
+
+
+ +
+
+minimize()¶
+
+
Minimize the window.
+
maximize() -> None
+
+
+ +
+
+resizable¶
+
+
Gets and sets whether the window is resizable.
+
resizable -> bool
+
+
+ +
+
+borderless¶
+
+
Add or remove the border from the window.
+
borderless -> bool
+
+
+ +
+
+set_icon()¶
+
+
Set the icon for the window.
+
set_icon(surface) -> None
+
+
+ +
+
+id¶
+
+
Get the unique window ID. *Read-only*
+
id -> int
+
+
+ +
+
+size¶
+
+
Gets and sets the window size.
+
size -> (int, int)
+
+
+ +
+
+position¶
+
+
Gets and sets the window position.
+
position -> (int, int) or WINDOWPOS_CENTERED or WINDOWPOS_UNDEFINED
+
+
+ +
+
+opacity¶
+
+
Gets and sets the window opacity. Between 0.0 (fully transparent) and 1.0 (fully opaque).
+
opacity -> float
+
+
+ +
+
+brightness¶
+
+
Gets and sets the brightness (gamma multiplier) for the display that owns the window.
+
brightness -> float
+
+
+ +
+
+display_index¶
+
+
Get the index of the display that owns the window. *Read-only*
+
display_index -> int
+
+
+ +
+
+set_modal_for()¶
+
+
Set the window as a modal for a parent window. This function is only supported on X11.
+
set_modal_for(Window) -> None
+
+
+ +
+ +
+
+pygame._sdl2.video.Texture¶
+
+
pygame object that representing a Texture.
+
Texture(renderer, size, depth=0, static=False, streaming=False, target=False) -> Texture
+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+—Create a texture from an existing surface.
+—Gets the renderer associated with the Texture. *Read-only*
+—Gets the width of the Texture. *Read-only*
+—Gets the height of the Texture. *Read-only*
+—Gets and sets an additional alpha value multiplied into render copy operations.
+—Gets and sets the blend mode for the Texture.
+—Gets and sets an additional color value multiplied into render copy operations.
+—Get the rectangular area of the texture.
+—Copy a portion of the texture to the rendering target.
+—Update the texture with a Surface. WARNING: Slow operation, use sparingly.
+
+
+static from_surface()¶
+
+
Create a texture from an existing surface.
+
from_surface(renderer, surface) -> Texture
+
+
+ +
+
+renderer¶
+
+
Gets the renderer associated with the Texture. *Read-only*
+
renderer -> Renderer
+
+
+ +
+
+width¶
+
+
Gets the width of the Texture. *Read-only*
+
width -> int
+
+
+ +
+
+height¶
+
+
Gets the height of the Texture. *Read-only*
+
height -> int
+
+
+ +
+
+alpha¶
+
+
Gets and sets an additional alpha value multiplied into render copy operations.
+
alpha -> int
+
+
+ +
+
+blend_mode¶
+
+
Gets and sets the blend mode for the Texture.
+
blend_mode -> int
+
+
+ +
+
+color¶
+
+
Gets and sets an additional color value multiplied into render copy operations.
+
color -> color
+
+
+ +
+
+get_rect()¶
+
+
Get the rectangular area of the texture.
+
get_rect(**kwargs) -> Rect
+
+
+ +
+
+draw()¶
+
+
Copy a portion of the texture to the rendering target.
+
draw(srcrect=None, dstrect=None, angle=0, origin=None, flipX=False, flipY=False) -> None
+
+
+ +
+
+update()¶
+
+
Update the texture with a Surface. WARNING: Slow operation, use sparingly.
+
update(surface, area=None) -> None
+
+
+ +
+ +
+
+pygame._sdl2.video.Image¶
+
+
Easy way to use a portion of a Texture without worrying about srcrect all the time.
+
Image(textureOrImage, srcrect=None) -> Image
+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+—Get the rectangular area of the Image.
+—Copy a portion of the Image to the rendering target.
+—Gets and sets the angle the Image draws itself with.
+—Gets and sets the origin. Origin=None means the Image will be rotated around its center.
+—Gets and sets whether the Image is flipped on the x axis.
+—Gets and sets whether the Image is flipped on the y axis.
+—Gets and sets the Image color modifier.
+—Gets and sets the Image alpha modifier.
+—Gets and sets the blend mode for the Image.
+—Gets and sets the Texture the Image is based on.
+—Gets and sets the Rect the Image is based on.
+
+
+get_rect()¶
+
+
Get the rectangular area of the Image.
+
get_rect() -> Rect
+
+
+ +
+
+draw()¶
+
+
Copy a portion of the Image to the rendering target.
+
draw(srcrect=None, dstrect=None) -> None
+
+
+ +
+
+angle¶
+
+
Gets and sets the angle the Image draws itself with.
+
angle -> float
+
+
+ +
+
+origin¶
+
+
Gets and sets the origin. Origin=None means the Image will be rotated around its center.
+
origin -> (float, float) or None.
+
+
+ +
+
+flipX¶
+
+
Gets and sets whether the Image is flipped on the x axis.
+
flipX -> bool
+
+
+ +
+
+flipY¶
+
+
Gets and sets whether the Image is flipped on the y axis.
+
flipY -> bool
+
+
+ +
+
+color¶
+
+
Gets and sets the Image color modifier.
+
color -> Color
+
+
+ +
+
+alpha¶
+
+
Gets and sets the Image alpha modifier.
+
alpha -> float
+
+
+ +
+
+blend_mode¶
+
+
Gets and sets the blend mode for the Image.
+
blend_mode -> int
+
+
+ +
+
+texture¶
+
+
Gets and sets the Texture the Image is based on.
+
texture -> Texture
+
+
+ +
+
+srcrect¶
+
+
Gets and sets the Rect the Image is based on.
+
srcrect -> Rect
+
+
+ +
+ +
+
+pygame._sdl2.video.Renderer¶
+
+
Create a 2D rendering context for a window.
+
Renderer(window, index=-1, accelerated=-1, vsync=False, target_texture=False) -> Renderer
+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+—Easy way to create a Renderer.
+—Gets and sets the blend mode used by the drawing functions.
+—Gets and sets the color used by the drawing functions.
+—Clear the current rendering target with the drawing color.
+—Updates the screen with any new rendering since previous call.
+—Returns the drawing area on the target.
+—Set the drawing area on the target. If area is None, the entire target will be used.
+—Gets and sets the logical size.
+—Gets and sets the scale.
+—Gets and sets the render target. None represents the default target (the renderer).
+—For compatibility purposes. Textures created by different Renderers cannot be shared!
+—Draws a line.
+—Draws a point.
+—Draws a rectangle.
+—Fills a rectangle.
+—Read pixels from current render target and create a pygame.Surface. WARNING: Slow operation, use sparingly.
+
+
+classmethod from_window()¶
+
+
Easy way to create a Renderer.
+
from_window(window) -> Renderer
+
+
+ +
+
+draw_blend_mode¶
+
+
Gets and sets the blend mode used by the drawing functions.
+
draw_blend_mode -> int
+
+
+ +
+
+draw_color¶
+
+
Gets and sets the color used by the drawing functions.
+
draw_color -> Color
+
+
+ +
+
+clear()¶
+
+
Clear the current rendering target with the drawing color.
+
clear() -> None
+
+
+ +
+
+present()¶
+
+
Updates the screen with any new rendering since previous call.
+
present() -> None
+
+
+ +
+
+get_viewport()¶
+
+
Returns the drawing area on the target.
+
get_viewport() -> Rect
+
+
+ +
+
+set_viewport()¶
+
+
Set the drawing area on the target. If area is None, the entire target will be used.
+
set_viewport(area) -> None
+
+
+ +
+
+logical_size¶
+
+
Gets and sets the logical size.
+
logical_size -> (int width, int height)
+
+
+ +
+
+scale¶
+
+
Gets and sets the scale.
+
scale -> (float x_scale, float y_scale)
+
+
+ +
+
+target¶
+
+
Gets and sets the render target. None represents the default target (the renderer).
+
target -> Texture or None
+
+
+ +
+
+blit()¶
+
+
For compatibility purposes. Textures created by different Renderers cannot be shared!
+
blit(soure, dest, area=None, special_flags=0)-> Rect
+
+
+ +
+
+draw_line()¶
+
+
Draws a line.
+
draw_line(p1, p2) -> None
+
+
+ +
+
+draw_point()¶
+
+
Draws a point.
+
draw_point(point) -> None
+
+
+ +
+
+draw_rect()¶
+
+
Draws a rectangle.
+
draw_rect(rect)-> None
+
+
+ +
+
+fill_rect()¶
+
+
Fills a rectangle.
+
fill_rect(rect)-> None
+
+
+ +
+
+to_surface()¶
+
+
Read pixels from current render target and create a pygame.Surface. WARNING: Slow operation, use sparingly.
+
to_surface(surface=None, area=None)-> Surface
+
+
+ +
+ +
+ +
+ + +

+
+Edit on GitHub +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/ref/sndarray.html b/venv/Lib/site-packages/pygame/docs/generated/ref/sndarray.html new file mode 100644 index 0000000..f12d6ee --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/ref/sndarray.html @@ -0,0 +1,274 @@ + + + + + + + + + pygame.sndarray — pygame v2.1.2 documentation + + + + + + + + + + + + + +
+ +
+ + + + + +
+
+ +
+
+ +
+
+
+pygame.sndarray
+
+
pygame module for accessing sound sample data
+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+—copy Sound samples into an array
+—reference Sound samples into an array
+—convert an array into a Sound object
+—Sets the array system to be used for sound arrays
+—Gets the currently active array type.
+—Gets the array system types currently supported.
+

Functions to convert between NumPy arrays and Sound objects. This +module will only be functional when pygame can use the external NumPy +package. If NumPy can't be imported, surfarray becomes a MissingModule +object.

+

Sound data is made of thousands of samples per second, and each sample is the +amplitude of the wave at a particular moment in time. For example, in 22-kHz +format, element number 5 of the array is the amplitude of the wave after +5/22000 seconds.

+

The arrays are indexed by the X axis first, followed by the Y axis. +Each sample is an 8-bit or 16-bit integer, depending on the data format. A +stereo sound file has two values per sample, while a mono sound file only has +one.

+
+
+pygame.sndarray.array()¶
+
+
copy Sound samples into an array
+
array(Sound) -> array
+
+

Creates a new array for the sound data and copies the samples. The array +will always be in the format returned from pygame.mixer.get_init().

+
+ +
+
+pygame.sndarray.samples()¶
+
+
reference Sound samples into an array
+
samples(Sound) -> array
+
+

Creates a new array that directly references the samples in a Sound object. +Modifying the array will change the Sound. The array will always be in the +format returned from pygame.mixer.get_init().

+
+ +
+
+pygame.sndarray.make_sound()¶
+
+
convert an array into a Sound object
+
make_sound(array) -> Sound
+
+

Create a new playable Sound object from an array. The mixer module must be +initialized and the array format must be similar to the mixer audio format.

+
+ +
+
+pygame.sndarray.use_arraytype()¶
+
+
Sets the array system to be used for sound arrays
+
use_arraytype (arraytype) -> None
+
+

DEPRECATED: Uses the requested array type for the module functions. The +only supported arraytype is 'numpy'. Other values will raise ValueError. +Using this function will raise a DeprecationWarning. +.. ## pygame.sndarray.use_arraytype ##

+
+ +
+
+pygame.sndarray.get_arraytype()¶
+
+
Gets the currently active array type.
+
get_arraytype () -> str
+
+

DEPRECATED: Returns the currently active array type. This will be a value of the +get_arraytypes() tuple and indicates which type of array module is used +for the array creation. Using this function will raise a DeprecationWarning.

+
+

New in pygame 1.8.

+
+
+ +
+
+pygame.sndarray.get_arraytypes()¶
+
+
Gets the array system types currently supported.
+
get_arraytypes () -> tuple
+
+

DEPRECATED: Checks, which array systems are available and returns them as a tuple of +strings. The values of the tuple can be used directly in the +pygame.sndarray.use_arraytype()Sets the array system to be used for sound arrays () method. If no supported array +system could be found, None will be returned. Using this function will raise a +DeprecationWarning.

+
+

New in pygame 1.8.

+
+
+ +
+ +
+ + +

+
+Edit on GitHub +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/ref/sprite.html b/venv/Lib/site-packages/pygame/docs/generated/ref/sprite.html new file mode 100644 index 0000000..653e292 --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/ref/sprite.html @@ -0,0 +1,1381 @@ + + + + + + + + + pygame.sprite — pygame v2.1.2 documentation + + + + + + + + + + + + + +
+ +
+ + + + + +
+
+ +
+
+ +
+
+
+pygame.sprite
+
+
pygame module with basic game object classes
+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+—Simple base class for visible game objects.
+—A subclass of Sprite with more attributes and features.
+—A container class to hold and manage multiple Sprite objects.
+—Same as pygame.sprite.Group
+—Same as pygame.sprite.Group
+—Group sub-class that tracks dirty updates.
+—RenderUpdates sub-class that draws Sprites in order of addition.
+—LayeredUpdates is a sprite group that handles layers and draws like OrderedUpdates.
+—LayeredDirty group is for DirtySprite objects. Subclasses LayeredUpdates.
+—Group container that holds a single sprite.
+—Find sprites in a group that intersect another sprite.
+—Collision detection between two sprites, using rects.
+—Collision detection between two sprites, using rects scaled to a ratio.
+—Collision detection between two sprites, using circles.
+—Collision detection between two sprites, using circles scaled to a ratio.
+—Collision detection between two sprites, using masks.
+—Find all sprites that collide between two groups.
+—Simple test if a sprite intersects anything in a group.
+

This module contains several simple classes to be used within games. There is +the main Sprite class and several Group classes that contain Sprites. The use +of these classes is entirely optional when using pygame. The classes are fairly +lightweight and only provide a starting place for the code that is common to +most games.

+

The Sprite class is intended to be used as a base class for the different types +of objects in the game. There is also a base Group class that simply stores +sprites. A game could create new types of Group classes that operate on +specially customized Sprite instances they contain.

+

The basic Sprite class can draw the Sprites it contains to a Surface. The +Group.draw() method requires that each Sprite have a Surface.image +attribute and a Surface.rect. The Group.clear() method requires these +same attributes, and can be used to erase all the Sprites with background. +There are also more advanced Groups: pygame.sprite.RenderUpdates() and +pygame.sprite.OrderedUpdates().

+

Lastly, this module contains several collision functions. These help find +sprites inside multiple groups that have intersecting bounding rectangles. To +find the collisions, the Sprites are required to have a Surface.rect +attribute assigned.

+

The groups are designed for high efficiency in removing and adding Sprites to +them. They also allow cheap testing to see if a Sprite already exists in a +Group. A given Sprite can exist in any number of groups. A game could use some +groups to control object rendering, and a completely separate set of groups to +control interaction or player movement. Instead of adding type attributes or +bools to a derived Sprite class, consider keeping the Sprites inside organized +Groups. This will allow for easier lookup later in the game.

+

Sprites and Groups manage their relationships with the add() and +remove() methods. These methods can accept a single or multiple targets for +membership. The default initializers for these classes also takes a single or +list of targets for initial membership. It is safe to repeatedly add and remove +the same Sprite from a Group.

+

While it is possible to design sprite and group classes that don't derive from +the Sprite and AbstractGroup classes below, it is strongly recommended that you +extend those when you add a Sprite or Group class.

+

Sprites are not thread safe. So lock them yourself if using threads.

+
+
+pygame.sprite.Sprite¶
+
+
Simple base class for visible game objects.
+
Sprite(*groups) -> Sprite
+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+—method to control sprite behavior
+—add the sprite to groups
+—remove the sprite from groups
+—remove the Sprite from all Groups
+—does the sprite belong to any groups
+—list of Groups that contain this Sprite
+

The base class for visible game objects. Derived classes will want to +override the Sprite.update() and assign a Sprite.image and +Sprite.rect attributes. The initializer can accept any number of Group +instances to be added to.

+

When subclassing the Sprite, be sure to call the base initializer before +adding the Sprite to Groups. For example:

+
class Block(pygame.sprite.Sprite):
+
+    # Constructor. Pass in the color of the block,
+    # and its x and y position
+    def __init__(self, color, width, height):
+       # Call the parent class (Sprite) constructor
+       pygame.sprite.Sprite.__init__(self)
+
+       # Create an image of the block, and fill it with a color.
+       # This could also be an image loaded from the disk.
+       self.image = pygame.Surface([width, height])
+       self.image.fill(color)
+
+       # Fetch the rectangle object that has the dimensions of the image
+       # Update the position of this object by setting the values of rect.x and rect.y
+       self.rect = self.image.get_rect()
+
+
+
+
+update()¶
+
+
method to control sprite behavior
+
update(*args, **kwargs) -> None
+
+

The default implementation of this method does nothing; it's just a +convenient "hook" that you can override. This method is called by +Group.update() with whatever arguments you give it.

+

There is no need to use this method if not using the convenience method +by the same name in the Group class.

+
+ +
+
+add()¶
+
+
add the sprite to groups
+
add(*groups) -> None
+
+

Any number of Group instances can be passed as arguments. The Sprite will +be added to the Groups it is not already a member of.

+
+ +
+
+remove()¶
+
+
remove the sprite from groups
+
remove(*groups) -> None
+
+

Any number of Group instances can be passed as arguments. The Sprite will +be removed from the Groups it is currently a member of.

+
+ +
+
+kill()¶
+
+
remove the Sprite from all Groups
+
kill() -> None
+
+

The Sprite is removed from all the Groups that contain it. This won't +change anything about the state of the Sprite. It is possible to continue +to use the Sprite after this method has been called, including adding it +to Groups.

+
+ +
+
+alive()¶
+
+
does the sprite belong to any groups
+
alive() -> bool
+
+

Returns True when the Sprite belongs to one or more Groups.

+
+ +
+
+groups()¶
+
+
list of Groups that contain this Sprite
+
groups() -> group_list
+
+

Return a list of all the Groups that contain this Sprite.

+
+ +
+ +
+
+pygame.sprite.DirtySprite¶
+
+
A subclass of Sprite with more attributes and features.
+
DirtySprite(*groups) -> DirtySprite
+
+

Extra DirtySprite attributes with their default values:

+

dirty = 1

+
if set to 1, it is repainted and then set to 0 again
+if set to 2 then it is always dirty ( repainted each frame,
+flag is not reset)
+0 means that it is not dirty and therefore not repainted again
+
+
+

blendmode = 0

+
its the special_flags argument of blit, blendmodes
+
+
+

source_rect = None

+
source rect to use, remember that it is relative to
+topleft (0,0) of self.image
+
+
+

visible = 1

+
normally 1, if set to 0 it will not be repainted
+(you must set it dirty too to be erased from screen)
+
+
+

layer = 0

+
(READONLY value, it is read when adding it to the
+LayeredDirty, for details see doc of LayeredDirty)
+
+
+
+ +
+
+pygame.sprite.Group¶
+
+
A container class to hold and manage multiple Sprite objects.
+
Group(*sprites) -> Group
+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+—list of the Sprites this Group contains
+—duplicate the Group
+—add Sprites to this Group
+—remove Sprites from the Group
+—test if a Group contains Sprites
+—call the update method on contained Sprites
+—blit the Sprite images
+—draw a background over the Sprites
+—remove all Sprites
+

A simple container for Sprite objects. This class can be inherited to create +containers with more specific behaviors. The constructor takes any number of +Sprite arguments to add to the Group. The group supports the following +standard Python operations:

+
in      test if a Sprite is contained
+len     the number of Sprites contained
+bool    test if any Sprites are contained
+iter    iterate through all the Sprites
+
+
+

The Sprites in the Group are ordered only on python 3.6 and higher. +Below python 3.6 drawing and iterating over the Sprites is in no particular order.

+
+
+sprites()¶
+
+
list of the Sprites this Group contains
+
sprites() -> sprite_list
+
+

Return a list of all the Sprites this group contains. You can also get an +iterator from the group, but you cannot iterate over a Group while +modifying it.

+
+ +
+
+copy()¶
+
+
duplicate the Group
+
copy() -> Group
+
+

Creates a new Group with all the same Sprites as the original. If you +have subclassed Group, the new object will have the same (sub-)class as +the original. This only works if the derived class's constructor takes +the same arguments as the Group class's.

+
+ +
+
+add()¶
+
+
add Sprites to this Group
+
add(*sprites) -> None
+
+

Add any number of Sprites to this Group. This will only add Sprites that +are not already members of the Group.

+

Each sprite argument can also be a iterator containing Sprites.

+
+ +
+
+remove()¶
+
+
remove Sprites from the Group
+
remove(*sprites) -> None
+
+

Remove any number of Sprites from the Group. This will only remove +Sprites that are already members of the Group.

+

Each sprite argument can also be a iterator containing Sprites.

+
+ +
+
+has()¶
+
+
test if a Group contains Sprites
+
has(*sprites) -> bool
+
+

Return True if the Group contains all of the given sprites. This is +similar to using the "in" operator on the Group ("if sprite in group: +..."), which tests if a single Sprite belongs to a Group.

+

Each sprite argument can also be a iterator containing Sprites.

+
+ +
+
+update()¶
+
+
call the update method on contained Sprites
+
update(*args, **kwargs) -> None
+
+

Calls the update() method on all Sprites in the Group. The base +Sprite class has an update method that takes any number of arguments and +does nothing. The arguments passed to Group.update() will be passed +to each Sprite.

+

There is no way to get the return value from the Sprite.update() +methods.

+
+ +
+
+draw()¶
+
+
blit the Sprite images
+
draw(Surface) -> List[Rect]
+
+

Draws the contained Sprites to the Surface argument. This uses the +Sprite.image attribute for the source surface, and Sprite.rect +for the position.

+

The Group does not keep sprites in any order, so the draw order is +arbitrary.

+
+ +
+
+clear()¶
+
+
draw a background over the Sprites
+
clear(Surface_dest, background) -> None
+
+

Erases the Sprites used in the last Group.draw() call. The +destination Surface is cleared by filling the drawn Sprite positions with +the background.

+

The background is usually a Surface image the same dimensions as the +destination Surface. However, it can also be a callback function that +takes two arguments; the destination Surface and an area to clear. The +background callback function will be called several times each clear.

+

Here is an example callback that will clear the Sprites with solid red:

+
def clear_callback(surf, rect):
+    color = 255, 0, 0
+    surf.fill(color, rect)
+
+
+
+ +
+
+empty()¶
+
+
remove all Sprites
+
empty() -> None
+
+

Removes all Sprites from this Group.

+
+ +
+ +
+
+pygame.sprite.RenderPlain¶
+
+
Same as pygame.sprite.Group
+
+

This class is an alias to pygame.sprite.Group(). It has no additional functionality.

+
+ +
+
+pygame.sprite.RenderClear¶
+
+
Same as pygame.sprite.Group
+
+

This class is an alias to pygame.sprite.Group(). It has no additional functionality.

+
+ +
+
+pygame.sprite.RenderUpdates¶
+
+
Group sub-class that tracks dirty updates.
+
RenderUpdates(*sprites) -> RenderUpdates
+
+ +++++ + + + + + + +
+—blit the Sprite images and track changed areas
+

This class is derived from pygame.sprite.Group(). It has an extended +draw() method that tracks the changed areas of the screen.

+
+
+draw()¶
+
+
blit the Sprite images and track changed areas
+
draw(surface) -> Rect_list
+
+

Draws all the Sprites to the surface, the same as Group.draw(). This +method also returns a list of Rectangular areas on the screen that have +been changed. The returned changes include areas of the screen that have +been affected by previous Group.clear() calls.

+

The returned Rect list should be passed to pygame.display.update(). +This will help performance on software driven display modes. This type of +updating is usually only helpful on destinations with non-animating +backgrounds.

+
+ +
+ +
+
+pygame.sprite.OrderedUpdates()¶
+
+
RenderUpdates sub-class that draws Sprites in order of addition.
+
OrderedUpdates(*spites) -> OrderedUpdates
+
+

This class derives from pygame.sprite.RenderUpdates(). It maintains the +order in which the Sprites were added to the Group for rendering. This makes +adding and removing Sprites from the Group a little slower than regular +Groups.

+
+ +
+
+pygame.sprite.LayeredUpdates¶
+
+
LayeredUpdates is a sprite group that handles layers and draws like OrderedUpdates.
+
LayeredUpdates(*spites, **kwargs) -> LayeredUpdates
+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+—add a sprite or sequence of sprites to a group
+—returns a ordered list of sprites (first back, last top).
+—draw all sprites in the right order onto the passed surface.
+—returns a list with all sprites at that position.
+—returns the sprite at the index idx from the groups sprites
+—removes all sprites from a layer and returns them as a list.
+—returns a list of layers defined (unique), sorted from bottom up.
+—changes the layer of the sprite
+—returns the layer that sprite is currently in.
+—returns the top layer
+—returns the bottom layer
+—brings the sprite to front layer
+—moves the sprite to the bottom layer
+—returns the topmost sprite
+—returns all sprites from a layer, ordered by how they where added
+—switches the sprites from layer1 to layer2
+

This group is fully compatible with pygame.sprite.SpriteSimple base class for visible game objects..

+

You can set the default layer through kwargs using 'default_layer' and an +integer for the layer. The default layer is 0.

+

If the sprite you add has an attribute _layer then that layer will be used. +If the **kwarg contains 'layer' then the sprites passed will be added to +that layer (overriding the sprite.layer attribute). If neither sprite +has attribute layer nor **kwarg then the default layer is used to add the +sprites.

+
+

New in pygame 1.8.

+
+
+
+add()¶
+
+
add a sprite or sequence of sprites to a group
+
add(*sprites, **kwargs) -> None
+
+

If the sprite(s) have an attribute layer then that is used for the +layer. If **kwargs contains 'layer' then the sprite(s) will be added +to that argument (overriding the sprite layer attribute). If neither is +passed then the sprite(s) will be added to the default layer.

+
+ +
+
+sprites()¶
+
+
returns a ordered list of sprites (first back, last top).
+
sprites() -> sprites
+
+
+ +
+
+draw()¶
+
+
draw all sprites in the right order onto the passed surface.
+
draw(surface) -> Rect_list
+
+
+ +
+
+get_sprites_at()¶
+
+
returns a list with all sprites at that position.
+
get_sprites_at(pos) -> colliding_sprites
+
+

Bottom sprites first, top last.

+
+ +
+
+get_sprite()¶
+
+
returns the sprite at the index idx from the groups sprites
+
get_sprite(idx) -> sprite
+
+

Raises IndexOutOfBounds if the idx is not within range.

+
+ +
+
+remove_sprites_of_layer()¶
+
+
removes all sprites from a layer and returns them as a list.
+
remove_sprites_of_layer(layer_nr) -> sprites
+
+
+ +
+
+layers()¶
+
+
returns a list of layers defined (unique), sorted from bottom up.
+
layers() -> layers
+
+
+ +
+
+change_layer()¶
+
+
changes the layer of the sprite
+
change_layer(sprite, new_layer) -> None
+
+

sprite must have been added to the renderer. It is not checked.

+
+ +
+
+get_layer_of_sprite()¶
+
+
returns the layer that sprite is currently in.
+
get_layer_of_sprite(sprite) -> layer
+
+

If the sprite is not found then it will return the default layer.

+
+ +
+
+get_top_layer()¶
+
+
returns the top layer
+
get_top_layer() -> layer
+
+
+ +
+
+get_bottom_layer()¶
+
+
returns the bottom layer
+
get_bottom_layer() -> layer
+
+
+ +
+
+move_to_front()¶
+
+
brings the sprite to front layer
+
move_to_front(sprite) -> None
+
+

Brings the sprite to front, changing sprite layer to topmost layer (added +at the end of that layer).

+
+ +
+
+move_to_back()¶
+
+
moves the sprite to the bottom layer
+
move_to_back(sprite) -> None
+
+

Moves the sprite to the bottom layer, moving it behind all other layers +and adding one additional layer.

+
+ +
+
+get_top_sprite()¶
+
+
returns the topmost sprite
+
get_top_sprite() -> Sprite
+
+
+ +
+
+get_sprites_from_layer()¶
+
+
returns all sprites from a layer, ordered by how they where added
+
get_sprites_from_layer(layer) -> sprites
+
+

Returns all sprites from a layer, ordered by how they where added. It +uses linear search and the sprites are not removed from layer.

+
+ +
+
+switch_layer()¶
+
+
switches the sprites from layer1 to layer2
+
switch_layer(layer1_nr, layer2_nr) -> None
+
+

The layers number must exist, it is not checked.

+
+ +
+ +
+
+pygame.sprite.LayeredDirty¶
+
+
LayeredDirty group is for DirtySprite objects. Subclasses LayeredUpdates.
+
LayeredDirty(*spites, **kwargs) -> LayeredDirty
+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+—draw all sprites in the right order onto the passed surface.
+—used to set background
+—repaints the given area
+—clip the area where to draw. Just pass None (default) to reset the clip
+—clip the area where to draw. Just pass None (default) to reset the clip
+—changes the layer of the sprite
+—sets the threshold in milliseconds
+—sets the threshold in milliseconds
+

This group requires pygame.sprite.DirtySpriteA subclass of Sprite with more attributes and features. or any sprite that +has the following attributes:

+
image, rect, dirty, visible, blendmode (see doc of DirtySprite).
+
+
+

It uses the dirty flag technique and is therefore faster than the +pygame.sprite.RenderUpdatesGroup sub-class that tracks dirty updates. if you have many static sprites. It +also switches automatically between dirty rect update and full screen +drawing, so you do not have to worry what would be faster.

+

Same as for the pygame.sprite.GroupA container class to hold and manage multiple Sprite objects.. You can specify some +additional attributes through kwargs:

+
_use_update: True/False   default is False
+_default_layer: default layer where sprites without a layer are added.
+_time_threshold: threshold time for switching between dirty rect mode
+    and fullscreen mode, defaults to 1000./80  == 1000./fps
+
+
+
+

New in pygame 1.8.

+
+
+
+draw()¶
+
+
draw all sprites in the right order onto the passed surface.
+
draw(surface, bgd=None) -> Rect_list
+
+

You can pass the background too. If a background is already set, then the +bgd argument has no effect.

+
+ +
+
+clear()¶
+
+
used to set background
+
clear(surface, bgd) -> None
+
+
+ +
+
+repaint_rect()¶
+
+
repaints the given area
+
repaint_rect(screen_rect) -> None
+
+

screen_rect is in screen coordinates.

+
+ +
+
+set_clip()¶
+
+
clip the area where to draw. Just pass None (default) to reset the clip
+
set_clip(screen_rect=None) -> None
+
+
+ +
+
+get_clip()¶
+
+
clip the area where to draw. Just pass None (default) to reset the clip
+
get_clip() -> Rect
+
+
+ +
+
+change_layer()¶
+
+
changes the layer of the sprite
+
change_layer(sprite, new_layer) -> None
+
+

sprite must have been added to the renderer. It is not checked.

+
+ +
+
+set_timing_treshold()¶
+
+
sets the threshold in milliseconds
+
set_timing_treshold(time_ms) -> None
+
+

DEPRECATED: Use set_timing_threshold() instead.

+
+

Deprecated since pygame 2.1.1.

+
+
+ +
+
+set_timing_threshold()¶
+
+
sets the threshold in milliseconds
+
set_timing_threshold(time_ms) -> None
+
+

Defaults to 1000.0 / 80.0. This means that the screen will be painted +using the flip method rather than the update method if the update +method is taking so long to update the screen that the frame rate falls +below 80 frames per second.

+
+

New in pygame 2.1.1.

+
+
+
Raises
+

TypeError -- if time_ms is not int or float

+
+
+
+ +
+ +
+
+pygame.sprite.GroupSingle()¶
+
+
Group container that holds a single sprite.
+
GroupSingle(sprite=None) -> GroupSingle
+
+

The GroupSingle container only holds a single Sprite. When a new Sprite is +added, the old one is removed.

+

There is a special property, GroupSingle.sprite, that accesses the +Sprite that this Group contains. It can be None when the Group is empty. The +property can also be assigned to add a Sprite into the GroupSingle +container.

+
+ +
+
+pygame.sprite.spritecollide()¶
+
+
Find sprites in a group that intersect another sprite.
+
spritecollide(sprite, group, dokill, collided = None) -> Sprite_list
+
+

Return a list containing all Sprites in a Group that intersect with another +Sprite. Intersection is determined by comparing the Sprite.rect +attribute of each Sprite.

+

The dokill argument is a bool. If set to True, all Sprites that collide will +be removed from the Group.

+

The collided argument is a callback function used to calculate if two +sprites are colliding. it should take two sprites as values, and return a +bool value indicating if they are colliding. If collided is not passed, all +sprites must have a "rect" value, which is a rectangle of the sprite area, +which will be used to calculate the collision.

+

collided callables:

+
collide_rect, collide_rect_ratio, collide_circle,
+collide_circle_ratio, collide_mask
+
+
+

Example:

+
# See if the Sprite block has collided with anything in the Group block_list
+# The True flag will remove the sprite in block_list
+blocks_hit_list = pygame.sprite.spritecollide(player, block_list, True)
+
+# Check the list of colliding sprites, and add one to the score for each one
+for block in blocks_hit_list:
+    score +=1
+
+
+
+ +
+
+pygame.sprite.collide_rect()¶
+
+
Collision detection between two sprites, using rects.
+
collide_rect(left, right) -> bool
+
+

Tests for collision between two sprites. Uses the pygame rect colliderect +function to calculate the collision. Intended to be passed as a collided +callback function to the *collide functions. Sprites must have a "rect" +attributes.

+
+

New in pygame 1.8.

+
+
+ +
+
+pygame.sprite.collide_rect_ratio()¶
+
+
Collision detection between two sprites, using rects scaled to a ratio.
+
collide_rect_ratio(ratio) -> collided_callable
+
+

A callable class that checks for collisions between two sprites, using a +scaled version of the sprites rects.

+

Is created with a ratio, the instance is then intended to be passed as a +collided callback function to the *collide functions.

+

A ratio is a floating point number - 1.0 is the same size, 2.0 is twice as +big, and 0.5 is half the size.

+
+

New in pygame 1.8.1.

+
+
+ +
+
+pygame.sprite.collide_circle()¶
+
+
Collision detection between two sprites, using circles.
+
collide_circle(left, right) -> bool
+
+

Tests for collision between two sprites, by testing to see if two circles +centered on the sprites overlap. If the sprites have a "radius" attribute, +that is used to create the circle, otherwise a circle is created that is big +enough to completely enclose the sprites rect as given by the "rect" +attribute. Intended to be passed as a collided callback function to the +*collide functions. Sprites must have a "rect" and an optional "radius" +attribute.

+
+

New in pygame 1.8.1.

+
+
+ +
+
+pygame.sprite.collide_circle_ratio()¶
+
+
Collision detection between two sprites, using circles scaled to a ratio.
+
collide_circle_ratio(ratio) -> collided_callable
+
+

A callable class that checks for collisions between two sprites, using a +scaled version of the sprites radius.

+

Is created with a floating point ratio, the instance is then intended to be +passed as a collided callback function to the *collide functions.

+

A ratio is a floating point number - 1.0 is the same size, 2.0 is twice as +big, and 0.5 is half the size.

+

The created callable tests for collision between two sprites, by testing to +see if two circles centered on the sprites overlap, after scaling the +circles radius by the stored ratio. If the sprites have a "radius" +attribute, that is used to create the circle, otherwise a circle is created +that is big enough to completely enclose the sprites rect as given by the +"rect" attribute. Intended to be passed as a collided callback function to +the *collide functions. Sprites must have a "rect" and an optional "radius" +attribute.

+
+

New in pygame 1.8.1.

+
+
+ +
+
+pygame.sprite.collide_mask()¶
+
+
Collision detection between two sprites, using masks.
+
collide_mask(sprite1, sprite2) -> (int, int)
+
collide_mask(sprite1, sprite2) -> None
+
+

Tests for collision between two sprites, by testing if their bitmasks +overlap (uses pygame.mask.Mask.overlap()Returns the point of intersection). If the sprites have a +mask attribute, it is used as the mask, otherwise a mask is created from +the sprite's image (uses pygame.mask.from_surface()Creates a Mask from the given surface). Sprites must +have a rect attribute; the mask attribute is optional.

+

The first point of collision between the masks is returned. The collision +point is offset from sprite1's mask's topleft corner (which is always +(0, 0)). The collision point is a position within the mask and is not +related to the actual screen position of sprite1.

+

This function is intended to be passed as a collided callback function +to the group collide functions (see spritecollide(), +groupcollide(), spritecollideany()).

+
+

Note

+

To increase performance, create and set a mask attibute for all +sprites that will use this function to check for collisions. Otherwise, +each time this function is called it will create new masks.

+
+
+

Note

+

A new mask needs to be recreated each time a sprite's image is changed +(e.g. if a new image is used or the existing image is rotated).

+
+
# Example of mask creation for a sprite.
+sprite.mask = pygame.mask.from_surface(sprite.image)
+
+
+
+
Returns
+

first point of collision between the masks or None if no +collision

+
+
Return type
+

tuple(int, int) or NoneType

+
+
+
+

New in pygame 1.8.0.

+
+
+ +
+
+pygame.sprite.groupcollide()¶
+
+
Find all sprites that collide between two groups.
+
groupcollide(group1, group2, dokill1, dokill2, collided = None) -> Sprite_dict
+
+

This will find collisions between all the Sprites in two groups. +Collision is determined by comparing the Sprite.rect attribute of +each Sprite or by using the collided function if it is not None.

+

Every Sprite inside group1 is added to the return dictionary. The value for +each item is the list of Sprites in group2 that intersect.

+

If either dokill argument is True, the colliding Sprites will be removed +from their respective Group.

+

The collided argument is a callback function used to calculate if two sprites are +colliding. It should take two sprites as values and return a bool value +indicating if they are colliding. If collided is not passed, then all +sprites must have a "rect" value, which is a rectangle of the sprite area, +which will be used to calculate the collision.

+
+ +
+
+pygame.sprite.spritecollideany()¶
+
+
Simple test if a sprite intersects anything in a group.
+
spritecollideany(sprite, group, collided = None) -> Sprite Collision with the returned sprite.
+
spritecollideany(sprite, group, collided = None) -> None No collision
+
+

If the sprite collides with any single sprite in the group, a single +sprite from the group is returned. On no collision None is returned.

+

If you don't need all the features of the pygame.sprite.spritecollide() function, this +function will be a bit quicker.

+

The collided argument is a callback function used to calculate if two sprites are +colliding. It should take two sprites as values and return a bool value +indicating if they are colliding. If collided is not passed, then all +sprites must have a "rect" value, which is a rectangle of the sprite area, +which will be used to calculate the collision.

+
+ +
+ +
+ + +

+
+Edit on GitHub +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/ref/surface.html b/venv/Lib/site-packages/pygame/docs/generated/ref/surface.html new file mode 100644 index 0000000..8a5da1c --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/ref/surface.html @@ -0,0 +1,1290 @@ + + + + + + + + + pygame.Surface — pygame v2.1.2 documentation + + + + + + + + + + + + + +
+ +
+ + + + + +
+
+ +
+
+ +
+
+
+pygame.Surface¶
+
+
pygame object for representing images
+
Surface((width, height), flags=0, depth=0, masks=None) -> Surface
+
Surface((width, height), flags=0, Surface) -> Surface
+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+—draw one image onto another
+—draw many images onto another
+—change the pixel format of an image
+—change the pixel format of an image including per pixel alphas
+—create a new copy of a Surface
+—fill Surface with a solid color
+—Shift the surface image in place
+—Set the transparent colorkey
+—Get the current transparent colorkey
+—set the alpha value for the full Surface image
+—get the current Surface transparency value
+—lock the Surface memory for pixel access
+—unlock the Surface memory from pixel access
+—test if the Surface requires locking
+—test if the Surface is current locked
+—Gets the locks for the Surface
+—get the color value at a single pixel
+—set the color value for a single pixel
+—get the mapped color value at a single pixel
+—get the color index palette for an 8-bit Surface
+—get the color for a single entry in a palette
+—set the color palette for an 8-bit Surface
+—set the color for a single index in an 8-bit Surface palette
+—convert a color into a mapped color value
+—convert a mapped integer color value into a Color
+—set the current clipping area of the Surface
+—get the current clipping area of the Surface
+—create a new surface that references its parent
+—find the parent of a subsurface
+—find the top level parent of a subsurface
+—find the position of a child subsurface inside a parent
+—find the absolute position of a child subsurface inside its top level parent
+—get the dimensions of the Surface
+—get the width of the Surface
+—get the height of the Surface
+—get the rectangular area of the Surface
+—get the bit depth of the Surface pixel format
+—get the bytes used per Surface pixel
+—get the additional flags used for the Surface
+—get the number of bytes used per Surface row
+—the bitmasks needed to convert between a color and a mapped integer
+—set the bitmasks needed to convert between a color and a mapped integer
+—the bit shifts needed to convert between a color and a mapped integer
+—sets the bit shifts needed to convert between a color and a mapped integer
+—the significant bits used to convert between a color and a mapped integer
+—find the smallest rect containing data
+—return a buffer view of the Surface's pixels.
+—acquires a buffer object for the pixels of the Surface.
+—pixel buffer address
+

A pygame Surface is used to represent any image. The Surface has a fixed +resolution and pixel format. Surfaces with 8-bit pixels use a color palette +to map to 24-bit color.

+

Call pygame.Surface()pygame object for representing images to create a new image object. The Surface will +be cleared to all black. The only required arguments are the sizes. With no +additional arguments, the Surface will be created in a format that best +matches the display Surface.

+

The pixel format can be controlled by passing the bit depth or an existing +Surface. The flags argument is a bitmask of additional features for the +surface. You can pass any combination of these flags:

+
HWSURFACE    (obsolete in pygame 2) creates the image in video memory
+SRCALPHA     the pixel format will include a per-pixel alpha
+
+
+

Both flags are only a request, and may not be possible for all displays and +formats.

+

Advance users can combine a set of bitmasks with a depth value. The masks +are a set of 4 integers representing which bits in a pixel will represent +each color. Normal Surfaces should not require the masks argument.

+

Surfaces can have many extra attributes like alpha planes, colorkeys, source +rectangle clipping. These functions mainly effect how the Surface is blitted +to other Surfaces. The blit routines will attempt to use hardware +acceleration when possible, otherwise they will use highly optimized +software blitting methods.

+

There are three types of transparency supported in pygame: colorkeys, +surface alphas, and pixel alphas. Surface alphas can be mixed with +colorkeys, but an image with per pixel alphas cannot use the other modes. +Colorkey transparency makes a single color value transparent. Any pixels +matching the colorkey will not be drawn. The surface alpha value is a single +value that changes the transparency for the entire image. A surface alpha of +255 is opaque, and a value of 0 is completely transparent.

+

Per pixel alphas are different because they store a transparency value for +every pixel. This allows for the most precise transparency effects, but it +also the slowest. Per pixel alphas cannot be mixed with surface alpha and +colorkeys.

+

There is support for pixel access for the Surfaces. Pixel access on hardware +surfaces is slow and not recommended. Pixels can be accessed using the +get_at() and set_at() functions. These methods are fine for +simple access, but will be considerably slow when doing of pixel work with +them. If you plan on doing a lot of pixel level work, it is recommended to +use a pygame.PixelArraypygame object for direct pixel access of surfaces, which gives an array like view of the +surface. For involved mathematical manipulations try the +pygame.surfarraypygame module for accessing surface pixel data using array interfaces module (It's quite quick, but requires NumPy.)

+

Any functions that directly access a surface's pixel data will need that +surface to be lock()'ed. These functions can lock() and +unlock() the surfaces themselves without assistance. But, if a +function will be called many times, there will be a lot of overhead for +multiple locking and unlocking of the surface. It is best to lock the +surface manually before making the function call many times, and then +unlocking when you are finished. All functions that need a locked surface +will say so in their docs. Remember to leave the Surface locked only while +necessary.

+

Surface pixels are stored internally as a single number that has all the +colors encoded into it. Use the map_rgb() and +unmap_rgb() to convert between individual red, green, and blue +values into a packed integer for that Surface.

+

Surfaces can also reference sections of other Surfaces. These are created +with the subsurface() method. Any change to either Surface will +effect the other.

+

Each Surface contains a clipping area. By default the clip area covers the +entire Surface. If it is changed, all drawing operations will only effect +the smaller area.

+
+
+blit()¶
+
+
draw one image onto another
+
blit(source, dest, area=None, special_flags=0) -> Rect
+
+

Draws a source Surface onto this Surface. The draw can be positioned with +the dest argument. The dest argument can either be a pair of coordinates representing the position of +the upper left corner of the blit or a Rect, where the upper left corner of the rectangle will be used as the +position for the blit. The size of the destination rectangle does not +effect the blit.

+

An optional area rectangle can be passed as well. This represents a +smaller portion of the source Surface to draw.

+
+

New in pygame 1.8: Optional special_flags: BLEND_ADD, BLEND_SUB, +BLEND_MULT, BLEND_MIN, BLEND_MAX.

+
+
+

New in pygame 1.8.1: Optional special_flags: BLEND_RGBA_ADD, BLEND_RGBA_SUB, +BLEND_RGBA_MULT, BLEND_RGBA_MIN, BLEND_RGBA_MAX +BLEND_RGB_ADD, BLEND_RGB_SUB, BLEND_RGB_MULT, +BLEND_RGB_MIN, BLEND_RGB_MAX.

+
+
+

New in pygame 1.9.2: Optional special_flags: BLEND_PREMULTIPLIED

+
+
+

New in pygame 2.0.0: Optional special_flags: BLEND_ALPHA_SDL2 - Uses the SDL2 blitter for alpha blending, +this gives different results than the default blitter, which is modelled after SDL1, due to +different approximations used for the alpha blending formula. The SDL2 blitter also supports +RLE on alpha blended surfaces which the pygame one does not.

+
+

The return rectangle is the area of the affected pixels, excluding any +pixels outside the destination Surface, or outside the clipping area.

+

Pixel alphas will be ignored when blitting to an 8 bit Surface.

+

For a surface with colorkey or blanket alpha, a blit to self may give +slightly different colors than a non self-blit.

+
+ +
+
+blits()¶
+
+
draw many images onto another
+
blits(blit_sequence=((source, dest), ...), doreturn=1) -> [Rect, ...] or None
+
blits(((source, dest, area), ...)) -> [Rect, ...]
+
blits(((source, dest, area, special_flags), ...)) -> [Rect, ...]
+
+

Draws many surfaces onto this Surface. It takes a sequence as input, +with each of the elements corresponding to the ones of blit(). +It needs at minimum a sequence of (source, dest).

+
+
Parameters
+
    +
  • blit_sequence -- a sequence of surfaces and arguments to blit them, +they correspond to the blit() arguments

  • +
  • doreturn -- if True, return a list of rects of the areas changed, +otherwise return None

  • +
+
+
Returns
+

a list of rects of the areas changed if doreturn is +True, otherwise None

+
+
Return type
+

list or None

+
+
+

New in pygame 1.9.4.

+
+ +
+
+convert()¶
+
+
change the pixel format of an image
+
convert(Surface=None) -> Surface
+
convert(depth, flags=0) -> Surface
+
convert(masks, flags=0) -> Surface
+
+

Creates a new copy of the Surface with the pixel format changed. The new +pixel format can be determined from another existing Surface. Otherwise +depth, flags, and masks arguments can be used, similar to the +pygame.Surface()pygame object for representing images call.

+

If no arguments are passed the new Surface will have the same pixel +format as the display Surface. This is always the fastest format for +blitting. It is a good idea to convert all Surfaces before they are +blitted many times.

+

The converted Surface will have no pixel alphas. They will be stripped if +the original had them. See convert_alpha() for preserving or +creating per-pixel alphas.

+

The new copy will have the same class as the copied surface. This lets +as Surface subclass inherit this method without the need to override, +unless subclass specific instance attributes also need copying.

+
+ +
+
+convert_alpha()¶
+
+
change the pixel format of an image including per pixel alphas
+
convert_alpha(Surface) -> Surface
+
convert_alpha() -> Surface
+
+

Creates a new copy of the surface with the desired pixel format. The new +surface will be in a format suited for quick blitting to the given format +with per pixel alpha. If no surface is given, the new surface will be +optimized for blitting to the current display.

+

Unlike the convert() method, the pixel format for the new +image will not be exactly the same as the requested source, but it will +be optimized for fast alpha blitting to the destination.

+

As with convert() the returned surface has the same class as +the converted surface.

+
+ +
+
+copy()¶
+
+
create a new copy of a Surface
+
copy() -> Surface
+
+

Makes a duplicate copy of a Surface. The new surface will have the same +pixel formats, color palettes, transparency settings, and class as the +original. If a Surface subclass also needs to copy any instance specific +attributes then it should override copy().

+
+ +
+
+fill()¶
+
+
fill Surface with a solid color
+
fill(color, rect=None, special_flags=0) -> Rect
+
+

Fill the Surface with a solid color. If no rect argument is given the +entire Surface will be filled. The rect argument will limit the fill to a +specific area. The fill will also be contained by the Surface clip area.

+

The color argument can be either a RGB sequence, a RGBA sequence +or a mapped color index. If using RGBA, the Alpha (A part of +RGBA) is ignored unless the surface uses per pixel alpha (Surface has +the SRCALPHA flag).

+
+

New in pygame 1.8: Optional special_flags: BLEND_ADD, BLEND_SUB, +BLEND_MULT, BLEND_MIN, BLEND_MAX.

+
+
+

New in pygame 1.8.1: Optional special_flags: BLEND_RGBA_ADD, BLEND_RGBA_SUB, +BLEND_RGBA_MULT, BLEND_RGBA_MIN, BLEND_RGBA_MAX +BLEND_RGB_ADD, BLEND_RGB_SUB, BLEND_RGB_MULT, +BLEND_RGB_MIN, BLEND_RGB_MAX.

+
+

This will return the affected Surface area.

+
+ +
+
+scroll()¶
+
+
Shift the surface image in place
+
scroll(dx=0, dy=0) -> None
+
+

Move the image by dx pixels right and dy pixels down. dx and dy may be +negative for left and up scrolls respectively. Areas of the surface that +are not overwritten retain their original pixel values. Scrolling is +contained by the Surface clip area. It is safe to have dx and dy values +that exceed the surface size.

+
+

New in pygame 1.9.

+
+
+ +
+
+set_colorkey()¶
+
+
Set the transparent colorkey
+
set_colorkey(Color, flags=0) -> None
+
set_colorkey(None) -> None
+
+

Set the current color key for the Surface. When blitting this Surface +onto a destination, any pixels that have the same color as the colorkey +will be transparent. The color can be an RGB color or a mapped color +integer. If None is passed, the colorkey will be unset.

+

The colorkey will be ignored if the Surface is formatted to use per pixel +alpha values. The colorkey can be mixed with the full Surface alpha +value.

+

The optional flags argument can be set to pygame.RLEACCEL to provide +better performance on non accelerated displays. An RLEACCEL Surface +will be slower to modify, but quicker to blit as a source.

+
+ +
+
+get_colorkey()¶
+
+
Get the current transparent colorkey
+
get_colorkey() -> RGB or None
+
+

Return the current colorkey value for the Surface. If the colorkey is not +set then None is returned.

+
+ +
+
+set_alpha()¶
+
+
set the alpha value for the full Surface image
+
set_alpha(value, flags=0) -> None
+
set_alpha(None) -> None
+
+

Set the current alpha value for the Surface. When blitting this Surface +onto a destination, the pixels will be drawn slightly transparent. The +alpha value is an integer from 0 to 255, 0 is fully transparent and 255 +is fully opaque. If None is passed for the alpha value, then alpha +blending will be disabled, including per-pixel alpha.

+

This value is different than the per pixel Surface alpha. For a surface +with per pixel alpha, blanket alpha is ignored and None is returned.

+
+

Changed in pygame 2.0: per-surface alpha can be combined with per-pixel +alpha.

+
+

The optional flags argument can be set to pygame.RLEACCEL to provide +better performance on non accelerated displays. An RLEACCEL Surface +will be slower to modify, but quicker to blit as a source.

+
+ +
+
+get_alpha()¶
+
+
get the current Surface transparency value
+
get_alpha() -> int_value
+
+

Return the current alpha value for the Surface.

+
+ +
+
+lock()¶
+
+
lock the Surface memory for pixel access
+
lock() -> None
+
+

Lock the pixel data of a Surface for access. On accelerated Surfaces, the +pixel data may be stored in volatile video memory or nonlinear compressed +forms. When a Surface is locked the pixel memory becomes available to +access by regular software. Code that reads or writes pixel values will +need the Surface to be locked.

+

Surfaces should not remain locked for more than necessary. A locked +Surface can often not be displayed or managed by pygame.

+

Not all Surfaces require locking. The mustlock() method can +determine if it is actually required. There is no performance penalty for +locking and unlocking a Surface that does not need it.

+

All pygame functions will automatically lock and unlock the Surface data +as needed. If a section of code is going to make calls that will +repeatedly lock and unlock the Surface many times, it can be helpful to +wrap the block inside a lock and unlock pair.

+

It is safe to nest locking and unlocking calls. The surface will only be +unlocked after the final lock is released.

+
+ +
+
+unlock()¶
+
+
unlock the Surface memory from pixel access
+
unlock() -> None
+
+

Unlock the Surface pixel data after it has been locked. The unlocked +Surface can once again be drawn and managed by pygame. See the +lock() documentation for more details.

+

All pygame functions will automatically lock and unlock the Surface data +as needed. If a section of code is going to make calls that will +repeatedly lock and unlock the Surface many times, it can be helpful to +wrap the block inside a lock and unlock pair.

+

It is safe to nest locking and unlocking calls. The surface will only be +unlocked after the final lock is released.

+
+ +
+
+mustlock()¶
+
+
test if the Surface requires locking
+
mustlock() -> bool
+
+

Returns True if the Surface is required to be locked to access pixel +data. Usually pure software Surfaces do not require locking. This method +is rarely needed, since it is safe and quickest to just lock all Surfaces +as needed.

+

All pygame functions will automatically lock and unlock the Surface data +as needed. If a section of code is going to make calls that will +repeatedly lock and unlock the Surface many times, it can be helpful to +wrap the block inside a lock and unlock pair.

+
+ +
+
+get_locked()¶
+
+
test if the Surface is current locked
+
get_locked() -> bool
+
+

Returns True when the Surface is locked. It doesn't matter how many +times the Surface is locked.

+
+ +
+
+get_locks()¶
+
+
Gets the locks for the Surface
+
get_locks() -> tuple
+
+

Returns the currently existing locks for the Surface.

+
+ +
+
+get_at()¶
+
+
get the color value at a single pixel
+
get_at((x, y)) -> Color
+
+

Return a copy of the RGBA Color value at the given pixel. If the +Surface has no per pixel alpha, then the alpha value will always be 255 +(opaque). If the pixel position is outside the area of the Surface an +IndexError exception will be raised.

+

Getting and setting pixels one at a time is generally too slow to be used +in a game or realtime situation. It is better to use methods which +operate on many pixels at a time like with the blit, fill and draw +methods - or by using pygame.surfarraypygame module for accessing surface pixel data using array interfaces/pygame.PixelArraypygame object for direct pixel access of surfaces.

+

This function will temporarily lock and unlock the Surface as needed.

+
+

New in pygame 1.9: Returning a Color instead of tuple. Use tuple(surf.get_at((x,y))) +if you want a tuple, and not a Color. This should only matter if +you want to use the color as a key in a dict.

+
+
+ +
+
+set_at()¶
+
+
set the color value for a single pixel
+
set_at((x, y), Color) -> None
+
+

Set the RGBA or mapped integer color value for a single pixel. If the +Surface does not have per pixel alphas, the alpha value is ignored. +Setting pixels outside the Surface area or outside the Surface clipping +will have no effect.

+

Getting and setting pixels one at a time is generally too slow to be used +in a game or realtime situation.

+

This function will temporarily lock and unlock the Surface as needed.

+
+ +
+
+get_at_mapped()¶
+
+
get the mapped color value at a single pixel
+
get_at_mapped((x, y)) -> Color
+
+

Return the integer value of the given pixel. If the pixel position is +outside the area of the Surface an IndexError exception will be +raised.

+

This method is intended for pygame unit testing. It unlikely has any use +in an application.

+

This function will temporarily lock and unlock the Surface as needed.

+
+

New in pygame 1.9.2.

+
+
+ +
+
+get_palette()¶
+
+
get the color index palette for an 8-bit Surface
+
get_palette() -> [RGB, RGB, RGB, ...]
+
+

Return a list of up to 256 color elements that represent the indexed +colors used in an 8-bit Surface. The returned list is a copy of the +palette, and changes will have no effect on the Surface.

+

Returning a list of Color(with length 3) instances instead of tuples.

+
+

New in pygame 1.9.

+
+
+ +
+
+get_palette_at()¶
+
+
get the color for a single entry in a palette
+
get_palette_at(index) -> RGB
+
+

Returns the red, green, and blue color values for a single index in a +Surface palette. The index should be a value from 0 to 255.

+
+

New in pygame 1.9: Returning Color(with length 3) instance instead of a tuple.

+
+
+ +
+
+set_palette()¶
+
+
set the color palette for an 8-bit Surface
+
set_palette([RGB, RGB, RGB, ...]) -> None
+
+

Set the full palette for an 8-bit Surface. This will replace the colors in +the existing palette. A partial palette can be passed and only the first +colors in the original palette will be changed.

+

This function has no effect on a Surface with more than 8-bits per pixel.

+
+ +
+
+set_palette_at()¶
+
+
set the color for a single index in an 8-bit Surface palette
+
set_palette_at(index, RGB) -> None
+
+

Set the palette value for a single entry in a Surface palette. The index +should be a value from 0 to 255.

+

This function has no effect on a Surface with more than 8-bits per pixel.

+
+ +
+
+map_rgb()¶
+
+
convert a color into a mapped color value
+
map_rgb(Color) -> mapped_int
+
+

Convert an RGBA color into the mapped integer value for this Surface. +The returned integer will contain no more bits than the bit depth of the +Surface. Mapped color values are not often used inside pygame, but can be +passed to most functions that require a Surface and a color.

+

See the Surface object documentation for more information about colors +and pixel formats.

+
+ +
+
+unmap_rgb()¶
+
+
convert a mapped integer color value into a Color
+
unmap_rgb(mapped_int) -> Color
+
+

Convert an mapped integer color into the RGB color components for +this Surface. Mapped color values are not often used inside pygame, but +can be passed to most functions that require a Surface and a color.

+

See the Surface object documentation for more information about colors +and pixel formats.

+
+ +
+
+set_clip()¶
+
+
set the current clipping area of the Surface
+
set_clip(rect) -> None
+
set_clip(None) -> None
+
+

Each Surface has an active clipping area. This is a rectangle that +represents the only pixels on the Surface that can be modified. If +None is passed for the rectangle the full Surface will be available +for changes.

+

The clipping area is always restricted to the area of the Surface itself. +If the clip rectangle is too large it will be shrunk to fit inside the +Surface.

+
+ +
+
+get_clip()¶
+
+
get the current clipping area of the Surface
+
get_clip() -> Rect
+
+

Return a rectangle of the current clipping area. The Surface will always +return a valid rectangle that will never be outside the bounds of the +image. If the Surface has had None set for the clipping area, the +Surface will return a rectangle with the full area of the Surface.

+
+ +
+
+subsurface()¶
+
+
create a new surface that references its parent
+
subsurface(Rect) -> Surface
+
+

Returns a new Surface that shares its pixels with its new parent. The new +Surface is considered a child of the original. Modifications to either +Surface pixels will effect each other. Surface information like clipping +area and color keys are unique to each Surface.

+

The new Surface will inherit the palette, color key, and alpha settings +from its parent.

+

It is possible to have any number of subsurfaces and subsubsurfaces on +the parent. It is also possible to subsurface the display Surface if the +display mode is not hardware accelerated.

+

See get_offset() and get_parent() to learn more +about the state of a subsurface.

+

A subsurface will have the same class as the parent surface.

+
+ +
+
+get_parent()¶
+
+
find the parent of a subsurface
+
get_parent() -> Surface
+
+

Returns the parent Surface of a subsurface. If this is not a subsurface +then None will be returned.

+
+ +
+
+get_abs_parent()¶
+
+
find the top level parent of a subsurface
+
get_abs_parent() -> Surface
+
+

Returns the parent Surface of a subsurface. If this is not a subsurface +then this surface will be returned.

+
+ +
+
+get_offset()¶
+
+
find the position of a child subsurface inside a parent
+
get_offset() -> (x, y)
+
+

Get the offset position of a child subsurface inside of a parent. If the +Surface is not a subsurface this will return (0, 0).

+
+ +
+
+get_abs_offset()¶
+
+
find the absolute position of a child subsurface inside its top level parent
+
get_abs_offset() -> (x, y)
+
+

Get the offset position of a child subsurface inside of its top level +parent Surface. If the Surface is not a subsurface this will return (0, +0).

+
+ +
+
+get_size()¶
+
+
get the dimensions of the Surface
+
get_size() -> (width, height)
+
+

Return the width and height of the Surface in pixels.

+
+ +
+
+get_width()¶
+
+
get the width of the Surface
+
get_width() -> width
+
+

Return the width of the Surface in pixels.

+
+ +
+
+get_height()¶
+
+
get the height of the Surface
+
get_height() -> height
+
+

Return the height of the Surface in pixels.

+
+ +
+
+get_rect()¶
+
+
get the rectangular area of the Surface
+
get_rect(**kwargs) -> Rect
+
+

Returns a new rectangle covering the entire surface. This rectangle will +always start at (0, 0) with a width and height the same size as the image.

+

You can pass keyword argument values to this function. These named values +will be applied to the attributes of the Rect before it is returned. An +example would be mysurf.get_rect(center=(100, 100)) to create a +rectangle for the Surface centered at a given position.

+
+ +
+
+get_bitsize()¶
+
+
get the bit depth of the Surface pixel format
+
get_bitsize() -> int
+
+

Returns the number of bits used to represent each pixel. This value may +not exactly fill the number of bytes used per pixel. For example a 15 bit +Surface still requires a full 2 bytes.

+
+ +
+
+get_bytesize()¶
+
+
get the bytes used per Surface pixel
+
get_bytesize() -> int
+
+

Return the number of bytes used per pixel.

+
+ +
+
+get_flags()¶
+
+
get the additional flags used for the Surface
+
get_flags() -> int
+
+

Returns a set of current Surface features. Each feature is a bit in the +flags bitmask. Typical flags are RLEACCEL, SRCALPHA, and +SRCCOLORKEY.

+

Here is a more complete list of flags. A full list can be found in +SDL_video.h

+
SWSURFACE      0x00000000    # Surface is in system memory
+HWSURFACE      0x00000001    # (obsolete in pygame 2) Surface is in video memory
+ASYNCBLIT      0x00000004    # (obsolete in pygame 2) Use asynchronous blits if possible
+
+
+

See pygame.display.set_mode()Initialize a window or screen for display for flags exclusive to the +display surface.

+

Used internally (read-only)

+
HWACCEL        0x00000100    # Blit uses hardware acceleration
+SRCCOLORKEY    0x00001000    # Blit uses a source color key
+RLEACCELOK     0x00002000    # Private flag
+RLEACCEL       0x00004000    # Surface is RLE encoded
+SRCALPHA       0x00010000    # Blit uses source alpha blending
+PREALLOC       0x01000000    # Surface uses preallocated memory
+
+
+
+ +
+
+get_pitch()¶
+
+
get the number of bytes used per Surface row
+
get_pitch() -> int
+
+

Return the number of bytes separating each row in the Surface. Surfaces +in video memory are not always linearly packed. Subsurfaces will also +have a larger pitch than their real width.

+

This value is not needed for normal pygame usage.

+
+ +
+
+get_masks()¶
+
+
the bitmasks needed to convert between a color and a mapped integer
+
get_masks() -> (R, G, B, A)
+
+

Returns the bitmasks used to isolate each color in a mapped integer.

+

This value is not needed for normal pygame usage.

+
+ +
+
+set_masks()¶
+
+
set the bitmasks needed to convert between a color and a mapped integer
+
set_masks((r,g,b,a)) -> None
+
+

This is not needed for normal pygame usage.

+
+

Note

+

In SDL2, the masks are read-only and accordingly this method will raise +an AttributeError if called.

+
+
+

New in pygame 1.8.1.

+
+
+ +
+
+get_shifts()¶
+
+
the bit shifts needed to convert between a color and a mapped integer
+
get_shifts() -> (R, G, B, A)
+
+

Returns the pixel shifts need to convert between each color and a mapped +integer.

+

This value is not needed for normal pygame usage.

+
+ +
+
+set_shifts()¶
+
+
sets the bit shifts needed to convert between a color and a mapped integer
+
set_shifts((r,g,b,a)) -> None
+
+

This is not needed for normal pygame usage.

+
+

Note

+

In SDL2, the shifts are read-only and accordingly this method will raise +an AttributeError if called.

+
+
+

New in pygame 1.8.1.

+
+
+ +
+
+get_losses()¶
+
+
the significant bits used to convert between a color and a mapped integer
+
get_losses() -> (R, G, B, A)
+
+

Return the least significant number of bits stripped from each color in a +mapped integer.

+

This value is not needed for normal pygame usage.

+
+ +
+
+get_bounding_rect()¶
+
+
find the smallest rect containing data
+
get_bounding_rect(min_alpha = 1) -> Rect
+
+

Returns the smallest rectangular region that contains all the pixels in +the surface that have an alpha value greater than or equal to the minimum +alpha value.

+

This function will temporarily lock and unlock the Surface as needed.

+
+

New in pygame 1.8.

+
+
+ +
+
+get_view()¶
+
+
return a buffer view of the Surface's pixels.
+
get_view(<kind>='2') -> BufferProxy
+
+

Return an object which exports a surface's internal pixel buffer as +a C level array struct, Python level array interface or a C level +buffer interface. The new buffer protocol is supported.

+

The kind argument is the length 1 string '0', '1', '2', '3', +'r', 'g', 'b', or 'a'. The letters are case insensitive; +'A' will work as well. The argument can be either a Unicode or byte (char) +string. The default is '2'.

+

'0' returns a contiguous unstructured bytes view. No surface shape +information is given. A ValueError is raised if the surface's pixels +are discontinuous.

+

'1' returns a (surface-width * surface-height) array of continuous +pixels. A ValueError is raised if the surface pixels are +discontinuous.

+

'2' returns a (surface-width, surface-height) array of raw pixels. +The pixels are surface-bytesize-d unsigned integers. The pixel format is +surface specific. The 3 byte unsigned integers of 24 bit surfaces are +unlikely accepted by anything other than other pygame functions.

+

'3' returns a (surface-width, surface-height, 3) array of RGB color +components. Each of the red, green, and blue components are unsigned +bytes. Only 24-bit and 32-bit surfaces are supported. The color +components must be in either RGB or BGR order within the pixel.

+

'r' for red, 'g' for green, 'b' for blue, and 'a' for alpha return a +(surface-width, surface-height) view of a single color component within a +surface: a color plane. Color components are unsigned bytes. Both 24-bit +and 32-bit surfaces support 'r', 'g', and 'b'. Only 32-bit surfaces with +SRCALPHA support 'a'.

+

The surface is locked only when an exposed interface is accessed. +For new buffer interface accesses, the surface is unlocked once the +last buffer view is released. For array interface and old buffer +interface accesses, the surface remains locked until the BufferProxy +object is released.

+
+

New in pygame 1.9.2.

+
+
+ +
+
+get_buffer()¶
+
+
acquires a buffer object for the pixels of the Surface.
+
get_buffer() -> BufferProxy
+
+

Return a buffer object for the pixels of the Surface. The buffer can be +used for direct pixel access and manipulation. Surface pixel data is +represented as an unstructured block of memory, with a start address +and length in bytes. The data need not be contiguous. Any gaps are +included in the length, but otherwise ignored.

+

This method implicitly locks the Surface. The lock will be released when +the returned pygame.BufferProxypygame object to export a surface buffer through an array protocol object is garbage collected.

+
+

New in pygame 1.8.

+
+
+ +
+
+_pixels_address¶
+
+
pixel buffer address
+
_pixels_address -> int
+
+

The starting address of the surface's raw pixel bytes.

+
+

New in pygame 1.9.2.

+
+
+ +
+ +
+ + +

+
+Edit on GitHub +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/ref/surfarray.html b/venv/Lib/site-packages/pygame/docs/generated/ref/surfarray.html new file mode 100644 index 0000000..fb22728 --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/ref/surfarray.html @@ -0,0 +1,571 @@ + + + + + + + + + pygame.surfarray — pygame v2.1.2 documentation + + + + + + + + + + + + + +
+ +
+ + + + + +
+
+ +
+
+ +
+
+
+pygame.surfarray
+
+
pygame module for accessing surface pixel data using array interfaces
+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+—Copy pixels into a 2d array
+—Reference pixels into a 2d array
+—Copy pixels into a 3d array
+—Reference pixels into a 3d array
+—Copy pixel alphas into a 2d array
+—Reference pixel alphas into a 2d array
+—Copy red pixels into a 2d array
+—Reference pixel red into a 2d array.
+—Copy green pixels into a 2d array
+—Reference pixel green into a 2d array.
+—Copy blue pixels into a 2d array
+—Reference pixel blue into a 2d array.
+—Copy the colorkey values into a 2d array
+—Copy an array to a new surface
+—Blit directly from a array values
+—Map a 3d array into a 2d array
+—Sets the array system to be used for surface arrays
+—Gets the currently active array type.
+—Gets the array system types currently supported.
+

Functions to convert between NumPy arrays and Surface objects. This module +will only be functional when pygame can use the external NumPy package. +If NumPy can't be imported, surfarray becomes a MissingModule object.

+

Every pixel is stored as a single integer value to represent the red, green, +and blue colors. The 8-bit images use a value that looks into a colormap. Pixels +with higher depth use a bit packing process to place three or four values into +a single number.

+

The arrays are indexed by the X axis first, followed by the Y axis. +Arrays that treat the pixels as a single integer are referred to as 2D arrays. +This module can also separate the red, green, and blue color values into +separate indices. These types of arrays are referred to as 3D arrays, and the +last index is 0 for red, 1 for green, and 2 for blue.

+

The pixels of a 2D array as returned by array2d() and pixels2d() +are mapped to the specific surface. Use pygame.Surface.unmap_rgb()convert a mapped integer color value into a Color +to convert to a color, and pygame.Surface.map_rgb()convert a color into a mapped color value to get the surface +specific pixel value of a color. Integer pixel values can only be used directly +between surfaces with matching pixel layouts (see pygame.Surfacepygame object for representing images).

+

All functions that refer to "array" will copy the surface information to a new +numpy array. All functions that refer to "pixels" will directly reference the +pixels from the surface and any changes performed to the array will make changes +in the surface. As this last functions share memory with the surface, this one +will be locked during the lifetime of the array.

+
+
+pygame.surfarray.array2d()¶
+
+
Copy pixels into a 2d array
+
array2d(Surface) -> array
+
+

Copy the mapped (raw) pixels from a Surface +into a 2D array. +The bit depth of the surface will control the size of the integer values, +and will work for any type of pixel format.

+

This function will temporarily lock the Surface as pixels are copied +(see the pygame.Surface.lock()lock the Surface memory for pixel access - lock the Surface memory for pixel +access method).

+
+ +
+
+pygame.surfarray.pixels2d()¶
+
+
Reference pixels into a 2d array
+
pixels2d(Surface) -> array
+
+

Create a new 2D array that directly references the pixel values in a +Surface. Any changes to the array will affect the pixels in the Surface. +This is a fast operation since no data is copied.

+

Pixels from a 24-bit Surface cannot be referenced, but all other Surface bit +depths can.

+

The Surface this references will remain locked for the lifetime of the array, +since the array generated by this function shares memory with the surface. +See the pygame.Surface.lock()lock the Surface memory for pixel access - lock the Surface memory for pixel +access method.

+
+ +
+
+pygame.surfarray.array3d()¶
+
+
Copy pixels into a 3d array
+
array3d(Surface) -> array
+
+

Copy the pixels from a Surface into a 3D array. The bit depth of the surface +will control the size of the integer values, and will work for any type of +pixel format.

+

This function will temporarily lock the Surface as pixels are copied (see +the pygame.Surface.lock()lock the Surface memory for pixel access - lock the Surface memory for pixel +access method).

+
+ +
+
+pygame.surfarray.pixels3d()¶
+
+
Reference pixels into a 3d array
+
pixels3d(Surface) -> array
+
+

Create a new 3D array that directly references the pixel values in a +Surface. Any changes to the array will affect the pixels in the Surface. +This is a fast operation since no data is copied.

+

This will only work on Surfaces that have 24-bit or 32-bit formats. Lower +pixel formats cannot be referenced.

+

The Surface this references will remain locked for the lifetime of the array, +since the array generated by this function shares memory with the surface. +See the pygame.Surface.lock()lock the Surface memory for pixel access - lock the Surface memory for pixel +access method.

+
+ +
+
+pygame.surfarray.array_alpha()¶
+
+
Copy pixel alphas into a 2d array
+
array_alpha(Surface) -> array
+
+

Copy the pixel alpha values (degree of transparency) from a Surface into a +2D array. This will work for any type of Surface format. Surfaces without a +pixel alpha will return an array with all opaque values.

+

This function will temporarily lock the Surface as pixels are copied (see +the pygame.Surface.lock()lock the Surface memory for pixel access - lock the Surface memory for pixel +access method).

+
+ +
+
+pygame.surfarray.pixels_alpha()¶
+
+
Reference pixel alphas into a 2d array
+
pixels_alpha(Surface) -> array
+
+

Create a new 2D array that directly references the alpha values (degree of +transparency) in a Surface. Any changes to the array will affect the pixels +in the Surface. This is a fast operation since no data is copied.

+

This can only work on 32-bit Surfaces with a per-pixel alpha value.

+

The Surface this references will remain locked for the lifetime of the array, +since the array generated by this function shares memory with the surface. +See the pygame.Surface.lock()lock the Surface memory for pixel access - lock the Surface memory for pixel +access method.

+
+ +
+
+pygame.surfarray.array_red()¶
+
+
Copy red pixels into a 2d array
+
array_red(Surface) -> array
+
+

Copy the pixel red values from a Surface into a 2D array. This will work +for any type of Surface format.

+

This function will temporarily lock the Surface as pixels are copied (see +the pygame.Surface.lock()lock the Surface memory for pixel access - lock the Surface memory for pixel +access method).

+
+

New in pygame 2.0.2.

+
+
+ +
+
+pygame.surfarray.pixels_red()¶
+
+
Reference pixel red into a 2d array.
+
pixels_red (Surface) -> array
+
+

Create a new 2D array that directly references the red values in a Surface. +Any changes to the array will affect the pixels in the Surface. This is a +fast operation since no data is copied.

+

This can only work on 24-bit or 32-bit Surfaces.

+

The Surface this references will remain locked for the lifetime of the array, +since the array generated by this function shares memory with the surface. +See the pygame.Surface.lock()lock the Surface memory for pixel access - lock the Surface memory for pixel +access method.

+
+ +
+
+pygame.surfarray.array_green()¶
+
+
Copy green pixels into a 2d array
+
array_green(Surface) -> array
+
+

Copy the pixel green values from a Surface into a 2D array. This will work +for any type of Surface format.

+

This function will temporarily lock the Surface as pixels are copied (see +the pygame.Surface.lock()lock the Surface memory for pixel access - lock the Surface memory for pixel +access method).

+
+

New in pygame 2.0.2.

+
+
+ +
+
+pygame.surfarray.pixels_green()¶
+
+
Reference pixel green into a 2d array.
+
pixels_green (Surface) -> array
+
+

Create a new 2D array that directly references the green values in a +Surface. Any changes to the array will affect the pixels in the Surface. +This is a fast operation since no data is copied.

+

This can only work on 24-bit or 32-bit Surfaces.

+

The Surface this references will remain locked for the lifetime of the array, +since the array generated by this function shares memory with the surface. +See the pygame.Surface.lock()lock the Surface memory for pixel access - lock the Surface memory for pixel +access method.

+
+ +
+
+pygame.surfarray.array_blue()¶
+
+
Copy blue pixels into a 2d array
+
array_blue(Surface) -> array
+
+

Copy the pixel blue values from a Surface into a 2D array. This will work +for any type of Surface format.

+

This function will temporarily lock the Surface as pixels are copied (see +the pygame.Surface.lock()lock the Surface memory for pixel access - lock the Surface memory for pixel +access method).

+
+

New in pygame 2.0.2.

+
+
+ +
+
+pygame.surfarray.pixels_blue()¶
+
+
Reference pixel blue into a 2d array.
+
pixels_blue (Surface) -> array
+
+

Create a new 2D array that directly references the blue values in a Surface. +Any changes to the array will affect the pixels in the Surface. This is a +fast operation since no data is copied.

+

This can only work on 24-bit or 32-bit Surfaces.

+

The Surface this references will remain locked for the lifetime of the array, +since the array generated by this function shares memory with the surface. +See the pygame.Surface.lock()lock the Surface memory for pixel access - lock the Surface memory for pixel +access method.

+
+ +
+
+pygame.surfarray.array_colorkey()¶
+
+
Copy the colorkey values into a 2d array
+
array_colorkey(Surface) -> array
+
+

Create a new array with the colorkey transparency value from each pixel. If +the pixel matches the colorkey it will be fully transparent; otherwise it +will be fully opaque.

+

This will work on any type of Surface format. If the image has no colorkey a +solid opaque array will be returned.

+

This function will temporarily lock the Surface as pixels are copied.

+
+ +
+
+pygame.surfarray.make_surface()¶
+
+
Copy an array to a new surface
+
make_surface(array) -> Surface
+
+

Create a new Surface that best resembles the data and format on the array. +The array can be 2D or 3D with any sized integer values. Function +make_surface uses the array struct interface to acquire array properties, +so is not limited to just NumPy arrays. See pygame.pixelcopypygame module for general pixel array copying.

+

New in pygame 1.9.2: array struct interface support.

+
+ +
+
+pygame.surfarray.blit_array()¶
+
+
Blit directly from a array values
+
blit_array(Surface, array) -> None
+
+

Directly copy values from an array into a Surface. This is faster than +converting the array into a Surface and blitting. The array must be the same +dimensions as the Surface and will completely replace all pixel values. Only +integer, ASCII character and record arrays are accepted.

+

This function will temporarily lock the Surface as the new values are +copied.

+
+ +
+
+pygame.surfarray.map_array()¶
+
+
Map a 3d array into a 2d array
+
map_array(Surface, array3d) -> array2d
+
+

Convert a 3D array into a 2D array. This will use the given Surface format +to control the conversion. Palette surface formats are supported for NumPy +arrays.

+
+ +
+
+pygame.surfarray.use_arraytype()¶
+
+
Sets the array system to be used for surface arrays
+
use_arraytype (arraytype) -> None
+
+

DEPRECATED: Uses the requested array type for the module functions. +The only supported arraytype is 'numpy'. Other values will raise +ValueError. Using this function will raise a DeprecationWarning.

+
+ +
+
+pygame.surfarray.get_arraytype()¶
+
+
Gets the currently active array type.
+
get_arraytype () -> str
+
+

DEPRECATED: Returns the currently active array type. This will be a value of the +get_arraytypes() tuple and indicates which type of array module is used +for the array creation. Using this function will raise a DeprecationWarning.

+
+

New in pygame 1.8.

+
+
+ +
+
+pygame.surfarray.get_arraytypes()¶
+
+
Gets the array system types currently supported.
+
get_arraytypes () -> tuple
+
+

DEPRECATED: Checks, which array systems are available and returns them as a tuple of +strings. The values of the tuple can be used directly in the +pygame.surfarray.use_arraytype()Sets the array system to be used for surface arrays () method. If no supported array +system could be found, None will be returned. Using this function will raise a +DeprecationWarning.

+
+

New in pygame 1.8.

+
+
+ +
+ +
+ + +

+
+Edit on GitHub +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/ref/tests.html b/venv/Lib/site-packages/pygame/docs/generated/ref/tests.html new file mode 100644 index 0000000..ad9bc67 --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/ref/tests.html @@ -0,0 +1,241 @@ + + + + + + + + + pygame.tests — pygame v2.1.2 documentation + + + + + + + + + + + + + +
+ +
+ + + + + +
+
+ +
+
+ +
+
+
+pygame.tests
+
+
Pygame unit test suite package
+
+ +++++ + + + + + + +
+—Run the pygame unit test suite
+

A quick way to run the test suite package from the command line is to import +the go submodule with the Python -m option:

+
python -m pygame.tests [<test options>]
+
+
+

Command line option --help displays a usage message. Available options +correspond to the pygame.tests.run()Run the pygame unit test suite arguments.

+

The xxxx_test submodules of the tests package are unit test suites for +individual parts of pygame. Each can also be run as a main program. This is +useful if the test, such as cdrom_test, is interactive.

+

For pygame development the test suite can be run from a pygame distribution +root directory. Program run_tests.py is provided for convenience, though +test/go.py can be run directly.

+

Module level tags control which modules are included in a unit test run. Tags +are assigned to a unit test module with a corresponding <name>_tags.py module. +The tags module has the global __tags__, a list of tag names. For example, +cdrom_test.py has a tag file cdrom_tags.py containing a tags list that +has the 'interactive' string. The 'interactive' tag indicates cdrom_test.py +expects user input. It is excluded from a run_tests.py or +pygame.tests.go run. Two other tags that are excluded are 'ignore' and +'subprocess_ignore'. These two tags indicate unit tests that will not run on a +particular platform, or for which no corresponding pygame module is available. +The test runner will list each excluded module along with the tag responsible.

+
+
+pygame.tests.run()¶
+
+
Run the pygame unit test suite
+
run(*args, **kwds) -> tuple
+
+

Positional arguments (optional):

+
The names of tests to include. If omitted then all tests are run. Test names
+need not include the trailing '_test'.
+
+
+

Keyword arguments:

+
incomplete - fail incomplete tests (default False)
+nosubprocess - run all test suites in the current process
+               (default False, use separate subprocesses)
+dump - dump failures/errors as dict ready to eval (default False)
+file - if provided, the name of a file into which to dump failures/errors
+timings - if provided, the number of times to run each individual test to
+          get an average run time (default is run each test once)
+exclude - A list of TAG names to exclude from the run
+show_output - show silenced stderr/stdout on errors (default False)
+all - dump all results, not just errors (default False)
+randomize - randomize order of tests (default False)
+seed - if provided, a seed randomizer integer
+multi_thread - if provided, the number of THREADS in which to run
+               subprocessed tests
+time_out - if subprocess is True then the time limit in seconds before
+           killing a test (default 30)
+fake - if provided, the name of the fake tests package in the
+       run_tests__tests subpackage to run instead of the normal
+       pygame tests
+python - the path to a python executable to run subprocessed tests
+         (default sys.executable)
+
+
+

Return value:

+
A tuple of total number of tests run, dictionary of error information.
+The dictionary is empty if no errors were recorded.
+
+
+

By default individual test modules are run in separate subprocesses. This +recreates normal pygame usage where pygame.init() and pygame.quit() +are called only once per program execution, and avoids unfortunate +interactions between test modules. Also, a time limit is placed on test +execution, so frozen tests are killed when there time allotment expired. Use +the single process option if threading is not working properly or if tests +are taking too long. It is not guaranteed that all tests will pass in single +process mode.

+

Tests are run in a randomized order if the randomize argument is True or a +seed argument is provided. If no seed integer is provided then the system +time is used.

+

Individual test modules may have a __tags__ attribute, a list of tag strings +used to selectively omit modules from a run. By default only 'interactive' +modules such as cdrom_test are ignored. An interactive module must be run +from the console as a Python program.

+

This function can only be called once per Python session. It is not +reentrant.

+
+ +
+ +
+ + +

+
+Edit on GitHub +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/ref/time.html b/venv/Lib/site-packages/pygame/docs/generated/ref/time.html new file mode 100644 index 0000000..112d5f7 --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/ref/time.html @@ -0,0 +1,370 @@ + + + + + + + + + pygame.time — pygame v2.1.2 documentation + + + + + + + + + + + + + +
+ +
+ + + + + +
+
+ +
+
+ +
+
+
+pygame.time
+
+
pygame module for monitoring time
+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + +
+—get the time in milliseconds
+—pause the program for an amount of time
+—pause the program for an amount of time
+—repeatedly create an event on the event queue
+—create an object to help track time
+

Times in pygame are represented in milliseconds (1/1000 seconds). Most +platforms have a limited time resolution of around 10 milliseconds. This +resolution, in milliseconds, is given in the TIMER_RESOLUTION constant.

+
+
+pygame.time.get_ticks()¶
+
+
get the time in milliseconds
+
get_ticks() -> milliseconds
+
+

Return the number of milliseconds since pygame.init() was called. Before +pygame is initialized this will always be 0.

+
+ +
+
+pygame.time.wait()¶
+
+
pause the program for an amount of time
+
wait(milliseconds) -> time
+
+

Will pause for a given number of milliseconds. This function sleeps the +process to share the processor with other programs. A program that waits for +even a few milliseconds will consume very little processor time. It is +slightly less accurate than the pygame.time.delay() function.

+

This returns the actual number of milliseconds used.

+
+ +
+
+pygame.time.delay()¶
+
+
pause the program for an amount of time
+
delay(milliseconds) -> time
+
+

Will pause for a given number of milliseconds. This function will use the +processor (rather than sleeping) in order to make the delay more accurate +than pygame.time.wait().

+

This returns the actual number of milliseconds used.

+
+ +
+
+pygame.time.set_timer()¶
+
+
repeatedly create an event on the event queue
+
set_timer(event, millis) -> None
+
set_timer(event, millis, loops=0) -> None
+
+

Set an event to appear on the event queue every given number of milliseconds. +The first event will not appear until the amount of time has passed.

+

The event attribute can be a pygame.event.Event object or an integer +type that denotes an event.

+

loops is an integer that denotes the number of events posted. If 0 (default) +then the events will keep getting posted, unless explicitly stopped.

+

To disable the timer for such an event, call the function again with the same +event argument with millis argument set to 0.

+

It is also worth mentioning that a particular event type can only be put on a +timer once. In other words, there cannot be two timers for the same event type. +Setting an event timer for a particular event discards the old one for that +event type.

+

loops replaces the once argument, and this does not break backward +compatability

+
+

New in pygame 2.0.0.dev3: once argument added.

+
+
+

Changed in pygame 2.0.1: event argument supports pygame.event.Event object

+
+
+

New in pygame 2.0.1: added loops argument to replace once argument

+
+
+ +
+
+pygame.time.Clock¶
+
+
create an object to help track time
+
Clock() -> Clock
+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + +
+—update the clock
+—update the clock
+—time used in the previous tick
+—actual time used in the previous tick
+—compute the clock framerate
+

Creates a new Clock object that can be used to track an amount of time. The +clock also provides several functions to help control a game's framerate.

+
+
+tick()¶
+
+
update the clock
+
tick(framerate=0) -> milliseconds
+
+

This method should be called once per frame. It will compute how many +milliseconds have passed since the previous call.

+

If you pass the optional framerate argument the function will delay to +keep the game running slower than the given ticks per second. This can be +used to help limit the runtime speed of a game. By calling +Clock.tick(40) once per frame, the program will never run at more +than 40 frames per second.

+

Note that this function uses SDL_Delay function which is not accurate on +every platform, but does not use much CPU. Use tick_busy_loop if you want +an accurate timer, and don't mind chewing CPU.

+
+ +
+
+tick_busy_loop()¶
+
+
update the clock
+
tick_busy_loop(framerate=0) -> milliseconds
+
+

This method should be called once per frame. It will compute how many +milliseconds have passed since the previous call.

+

If you pass the optional framerate argument the function will delay to +keep the game running slower than the given ticks per second. This can be +used to help limit the runtime speed of a game. By calling +Clock.tick_busy_loop(40) once per frame, the program will never run at +more than 40 frames per second.

+

Note that this function uses pygame.time.delay()pause the program for an amount of time, which uses lots +of CPU in a busy loop to make sure that timing is more accurate.

+
+

New in pygame 1.8.

+
+
+ +
+
+get_time()¶
+
+
time used in the previous tick
+
get_time() -> milliseconds
+
+

The number of milliseconds that passed between the previous two calls to +Clock.tick().

+
+ +
+
+get_rawtime()¶
+
+
actual time used in the previous tick
+
get_rawtime() -> milliseconds
+
+

Similar to Clock.get_time(), but does not include any time used +while Clock.tick() was delaying to limit the framerate.

+
+ +
+
+get_fps()¶
+
+
compute the clock framerate
+
get_fps() -> float
+
+

Compute your game's framerate (in frames per second). It is computed by +averaging the last ten calls to Clock.tick().

+
+ +
+ +
+ +
+ + +

+
+Edit on GitHub +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/ref/touch.html b/venv/Lib/site-packages/pygame/docs/generated/ref/touch.html new file mode 100644 index 0000000..198a5ff --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/ref/touch.html @@ -0,0 +1,240 @@ + + + + + + + + + pygame._sdl2.touch — pygame v2.1.2 documentation + + + + + + + + + + + + + +
+ +
+ + + + + +
+
+ +
+
+ +
+
+
+pygame._sdl2.touch
+
+
pygame module to work with touch input
+
+ +++++ + + + + + + + + + + + + + + + + + + +
+—get the number of touch devices
+—get the a touch device id for a given index
+—the number of active fingers for a given touch device
+—get information about an active finger
+
+

New in pygame 2: This module requires SDL2.

+
+
+
+pygame._sdl2.touch.get_num_devices()¶
+
+
get the number of touch devices
+
get_num_devices() -> int
+
+

Return the number of available touch devices.

+
+ +
+
+pygame._sdl2.touch.get_device()¶
+
+
get the a touch device id for a given index
+
get_device(index) -> touchid
+
+
+
Parameters
+

index (int) -- This number is at least 0 and less than the +number of devices.

+
+
+

Return an integer id associated with the given index.

+
+ +
+
+pygame._sdl2.touch.get_num_fingers()¶
+
+
the number of active fingers for a given touch device
+
get_num_fingers(touchid) -> int
+
+

Return the number of fingers active for the touch device +whose id is touchid.

+
+ +
+
+pygame._sdl2.touch.get_finger()¶
+
+
get information about an active finger
+
get_finger(touchid, index) -> int
+
+
+
Parameters
+
    +
  • touchid (int) -- The touch device id.

  • +
  • index (int) -- The index of the finger to return +information about, between 0 and the +number of active fingers.

  • +
+
+
+

Return a dict for the finger index active on touchid. +The dict contains these keys:

+
id         the id of the finger (an integer).
+x          the normalized x position of the finger, between 0 and 1.
+y          the normalized y position of the finger, between 0 and 1.
+pressure   the amount of pressure applied by the finger, between 0 and 1.
+
+
+
+ +
+ +
+ + +

+
+Edit on GitHub +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/ref/transform.html b/venv/Lib/site-packages/pygame/docs/generated/ref/transform.html new file mode 100644 index 0000000..da5a1a5 --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/ref/transform.html @@ -0,0 +1,535 @@ + + + + + + + + + pygame.transform — pygame v2.1.2 documentation + + + + + + + + + + + + + +
+ +
+ + + + + +
+
+ +
+
+ +
+
+
+pygame.transform
+
+
pygame module to transform surfaces
+
+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+—flip vertically and horizontally
+—resize to new resolution
+—rotate an image
+—filtered scale and rotation
+—specialized image doubler
+—scale a surface to an arbitrary size smoothly
+—return smoothscale filter version in use: 'GENERIC', 'MMX', or 'SSE'
+—set smoothscale filter version to one of: 'GENERIC', 'MMX', or 'SSE'
+—gets a copy of an image with an interior area removed
+—find edges in a surface
+—find the average surface from many surfaces.
+—finds the average color of a surface
+—finds which, and how many pixels in a surface are within a threshold of a 'search_color' or a 'search_surf'.
+

A Surface transform is an operation that moves or resizes the pixels. All these +functions take a Surface to operate on and return a new Surface with the +results.

+

Some of the transforms are considered destructive. These means every time they +are performed they lose pixel data. Common examples of this are resizing and +rotating. For this reason, it is better to re-transform the original surface +than to keep transforming an image multiple times. (For example, suppose you +are animating a bouncing spring which expands and contracts. If you applied the +size changes incrementally to the previous images, you would lose detail. +Instead, always begin with the original image and scale to the desired size.)

+
+

Changed in pygame 2.0.2: transform functions now support keyword arguments.

+
+
+
+pygame.transform.flip()¶
+
+
flip vertically and horizontally
+
flip(surface, flip_x, flip_y) -> Surface
+
+

This can flip a Surface either vertically, horizontally, or both. +The arguments flip_x and flip_y are booleans that control whether +to flip each axis. Flipping a Surface is non-destructive and returns a new +Surface with the same dimensions.

+
+ +
+
+pygame.transform.scale()¶
+
+
resize to new resolution
+
scale(surface, size, dest_surface=None) -> Surface
+
+

Resizes the Surface to a new size, given as (width, height). +This is a fast scale operation that does not sample the results.

+

An optional destination surface can be used, rather than have it create a +new one. This is quicker if you want to repeatedly scale something. However +the destination must be the same size as the size (width, height) passed in. Also +the destination surface must be the same format.

+
+ +
+
+pygame.transform.rotate()¶
+
+
rotate an image
+
rotate(surface, angle) -> Surface
+
+

Unfiltered counterclockwise rotation. The angle argument represents degrees +and can be any floating point value. Negative angle amounts will rotate +clockwise.

+

Unless rotating by 90 degree increments, the image will be padded larger to +hold the new size. If the image has pixel alphas, the padded area will be +transparent. Otherwise pygame will pick a color that matches the Surface +colorkey or the topleft pixel value.

+
+ +
+
+pygame.transform.rotozoom()¶
+
+
filtered scale and rotation
+
rotozoom(surface, angle, scale) -> Surface
+
+

This is a combined scale and rotation transform. The resulting Surface will +be a filtered 32-bit Surface. The scale argument is a floating point value +that will be multiplied by the current resolution. The angle argument is a +floating point value that represents the counterclockwise degrees to rotate. +A negative rotation angle will rotate clockwise.

+
+ +
+
+pygame.transform.scale2x()¶
+
+
specialized image doubler
+
scale2x(surface, dest_surface=None) -> Surface
+
+

This will return a new image that is double the size of the original. It +uses the AdvanceMAME Scale2X algorithm which does a 'jaggie-less' scale of +bitmap graphics.

+

This really only has an effect on simple images with solid colors. On +photographic and antialiased images it will look like a regular unfiltered +scale.

+

An optional destination surface can be used, rather than have it create a +new one. This is quicker if you want to repeatedly scale something. However +the destination must be twice the size of the source surface passed in. Also +the destination surface must be the same format.

+
+ +
+
+pygame.transform.smoothscale()¶
+
+
scale a surface to an arbitrary size smoothly
+
smoothscale(surface, size, dest_surface=None) -> Surface
+
+

Uses one of two different algorithms for scaling each dimension of the input +surface as required. For shrinkage, the output pixels are area averages of +the colors they cover. For expansion, a bilinear filter is used. For the +x86-64 and i686 architectures, optimized MMX routines are included and +will run much faster than other machine types. The size is a 2 number +sequence for (width, height). This function only works for 24-bit or 32-bit +surfaces. An exception will be thrown if the input surface bit depth is less +than 24.

+
+

New in pygame 1.8.

+
+
+ +
+
+pygame.transform.get_smoothscale_backend()¶
+
+
return smoothscale filter version in use: 'GENERIC', 'MMX', or 'SSE'
+
get_smoothscale_backend() -> string
+
+

Shows whether or not smoothscale is using MMX or SSE acceleration. +If no acceleration is available then "GENERIC" is returned. For a x86 +processor the level of acceleration to use is determined at runtime.

+

This function is provided for pygame testing and debugging.

+
+ +
+
+pygame.transform.set_smoothscale_backend()¶
+
+
set smoothscale filter version to one of: 'GENERIC', 'MMX', or 'SSE'
+
set_smoothscale_backend(backend) -> None
+
+

Sets smoothscale acceleration. Takes a string argument. A value of 'GENERIC' +turns off acceleration. 'MMX' uses MMX instructions only. 'SSE' allows +SSE extensions as well. A value error is raised if type is not +recognized or not supported by the current processor.

+

This function is provided for pygame testing and debugging. If smoothscale +causes an invalid instruction error then it is a pygame/SDL bug that should +be reported. Use this function as a temporary fix only.

+
+ +
+
+pygame.transform.chop()¶
+
+
gets a copy of an image with an interior area removed
+
chop(surface, rect) -> Surface
+
+

Extracts a portion of an image. All vertical and horizontal pixels +surrounding the given rectangle area are removed. The corner areas (diagonal +to the rect) are then brought together. (The original image is not altered +by this operation.)

+

NOTE: If you want a "crop" that returns the part of an image within a +rect, you can blit with a rect to a new surface or copy a subsurface.

+
+ +
+
+pygame.transform.laplacian()¶
+
+
find edges in a surface
+
laplacian(surface, dest_surface=None) -> Surface
+
+

Finds the edges in a surface using the laplacian algorithm.

+
+

New in pygame 1.8.

+
+
+ +
+
+pygame.transform.average_surfaces()¶
+
+
find the average surface from many surfaces.
+
average_surfaces(surfaces, dest_surface=None, palette_colors=1) -> Surface
+
+

Takes a sequence of surfaces and returns a surface with average colors from +each of the surfaces.

+

palette_colors - if true we average the colors in palette, otherwise we +average the pixel values. This is useful if the surface is actually +greyscale colors, and not palette colors.

+

Note, this function currently does not handle palette using surfaces +correctly.

+
+

New in pygame 1.8.

+
+
+

New in pygame 1.9: palette_colors argument

+
+
+ +
+
+pygame.transform.average_color()¶
+
+
finds the average color of a surface
+
average_color(surface, rect=None) -> Color
+
+

Finds the average color of a Surface or a region of a surface specified by a +Rect, and returns it as a Color.

+
+ +
+
+pygame.transform.threshold()¶
+
+
finds which, and how many pixels in a surface are within a threshold of a 'search_color' or a 'search_surf'.
+
threshold(dest_surface, surface, search_color, threshold=(0,0,0,0), set_color=(0,0,0,0), set_behavior=1, search_surf=None, inverse_set=False) -> num_threshold_pixels
+
+

This versatile function can be used for find colors in a 'surf' close to a 'search_color' +or close to colors in a separate 'search_surf'.

+

It can also be used to transfer pixels into a 'dest_surf' that match or don't match.

+

By default it sets pixels in the 'dest_surf' where all of the pixels NOT within the +threshold are changed to set_color. If inverse_set is optionally set to True, +the pixels that ARE within the threshold are changed to set_color.

+

If the optional 'search_surf' surface is given, it is used to threshold against +rather than the specified 'set_color'. That is, it will find each pixel in the +'surf' that is within the 'threshold' of the pixel at the same coordinates +of the 'search_surf'.

+
+
Parameters
+
+
+
Return type
+

int

+
+
Returns
+

The number of pixels that are within the 'threshold' in 'surf' +compared to either 'search_color' or search_surf.

+
+
Examples
+

+
+

See the threshold tests for a full of examples: https://github.com/pygame/pygame/blob/master/test/transform_test.py

+
    def test_threshold_dest_surf_not_change(self):
+        """the pixels within the threshold.
+
+        All pixels not within threshold are changed to set_color.
+        So there should be none changed in this test.
+        """
+        (w, h) = size = (32, 32)
+        threshold = (20, 20, 20, 20)
+        original_color = (25, 25, 25, 25)
+        original_dest_color = (65, 65, 65, 55)
+        threshold_color = (10, 10, 10, 10)
+        set_color = (255, 10, 10, 10)
+
+        surf = pygame.Surface(size, pygame.SRCALPHA, 32)
+        dest_surf = pygame.Surface(size, pygame.SRCALPHA, 32)
+        search_surf = pygame.Surface(size, pygame.SRCALPHA, 32)
+
+        surf.fill(original_color)
+        search_surf.fill(threshold_color)
+        dest_surf.fill(original_dest_color)
+
+        # set_behavior=1, set dest_surface from set_color.
+        # all within threshold of third_surface, so no color is set.
+
+        THRESHOLD_BEHAVIOR_FROM_SEARCH_COLOR = 1
+        pixels_within_threshold = pygame.transform.threshold(
+            dest_surface=dest_surf,
+            surface=surf,
+            search_color=None,
+            threshold=threshold,
+            set_color=set_color,
+            set_behavior=THRESHOLD_BEHAVIOR_FROM_SEARCH_COLOR,
+            search_surf=search_surf,
+        )
+
+        # # Return, of pixels within threshold is correct
+        self.assertEqual(w * h, pixels_within_threshold)
+
+        # # Size of dest surface is correct
+        dest_rect = dest_surf.get_rect()
+        dest_size = dest_rect.size
+        self.assertEqual(size, dest_size)
+
+        # The color is not the change_color specified for every pixel As all
+        # pixels are within threshold
+
+        for pt in test_utils.rect_area_pts(dest_rect):
+            self.assertNotEqual(dest_surf.get_at(pt), set_color)
+            self.assertEqual(dest_surf.get_at(pt), original_dest_color)
+
+
+
+

New in pygame 1.8.

+
+
+

Changed in pygame 1.9.4: Fixed a lot of bugs and added keyword arguments. Test your code.

+
+
+ +
+ +
+ + +

+
+Edit on GitHub +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/search.html b/venv/Lib/site-packages/pygame/docs/generated/search.html new file mode 100644 index 0000000..1f1e1b3 --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/search.html @@ -0,0 +1,96 @@ + + + + + + + + Search — pygame v2.1.2 documentation + + + + + + + + + + + + + + + + + + +
+
+
+ +

Search

+ + + + +

+ Searching for multiple words only shows matches that contain + all words. +

+ + +
+ + + +
+ + + +
+ +
+ + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/searchindex.js b/venv/Lib/site-packages/pygame/docs/generated/searchindex.js new file mode 100644 index 0000000..16b2a61 --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/searchindex.js @@ -0,0 +1 @@ +Search.setIndex({docnames:["c_api","c_api/base","c_api/bufferproxy","c_api/cdrom","c_api/color","c_api/display","c_api/event","c_api/freetype","c_api/mixer","c_api/rect","c_api/rwobject","c_api/slots","c_api/surface","c_api/surflock","c_api/version","filepaths","index","ref/bufferproxy","ref/camera","ref/cdrom","ref/color","ref/color_list","ref/cursors","ref/display","ref/draw","ref/event","ref/examples","ref/fastevent","ref/font","ref/freetype","ref/gfxdraw","ref/image","ref/joystick","ref/key","ref/locals","ref/mask","ref/math","ref/midi","ref/mixer","ref/mouse","ref/music","ref/overlay","ref/pixelarray","ref/pixelcopy","ref/pygame","ref/rect","ref/scrap","ref/sdl2_controller","ref/sdl2_video","ref/sndarray","ref/sprite","ref/surface","ref/surfarray","ref/tests","ref/time","ref/touch","ref/transform","tut/CameraIntro","tut/ChimpLineByLine","tut/DisplayModes","tut/ImportInit","tut/MakeGames","tut/MoveIt","tut/PygameIntro","tut/SpriteIntro","tut/SurfarrayIntro","tut/chimp.py","tut/en/Red_or_Black/1.Prolog/introduction","tut/en/Red_or_Black/2.Print_text/Basic TEMPLATE and OUTPUT","tut/en/Red_or_Black/3.Move_text/Basic PROCESS","tut/en/Red_or_Black/4.Control_text/Basic INPUT","tut/en/Red_or_Black/5.HP_bar/Advanced OUTPUT with Advanced PROCESS","tut/en/Red_or_Black/6.Buttons/Advanced INPUT with Advanced OUTPUT","tut/en/Red_or_Black/7.Game_board/Advanced OUTPUT and plus alpha","tut/en/Red_or_Black/8.Epilog/Epilog","tut/ko/\ube68\uac04\ube14\ub85d \uac80\uc740\ube14\ub85d/1.\ud504\ub864\ub85c\uadf8/\uc18c\uac1c","tut/ko/\ube68\uac04\ube14\ub85d \uac80\uc740\ube14\ub85d/2.\ud14d\uc2a4\ud2b8 \ucd9c\ub825/\uae30\ucd08 \ud15c\ud50c\ub9bf\uacfc \ucd9c\ub825","tut/ko/\ube68\uac04\ube14\ub85d \uac80\uc740\ube14\ub85d/3.\ud14d\uc2a4\ud2b8 \uc774\ub3d9/\uae30\ucd08 \ucc98\ub9ac","tut/ko/\ube68\uac04\ube14\ub85d \uac80\uc740\ube14\ub85d/4.\ud14d\uc2a4\ud2b8 \uc870\uc885/\uae30\ucd08 \uc785\ub825","tut/ko/\ube68\uac04\ube14\ub85d \uac80\uc740\ube14\ub85d/5.HP\ubc14/\uc2ec\ud654 \ucd9c\ub825 \uadf8\ub9ac\uace0 \uc2ec\ud654 \ucc98\ub9ac","tut/ko/\ube68\uac04\ube14\ub85d \uac80\uc740\ube14\ub85d/6.\ubc84\ud2bc\ub4e4/\uc2ec\ud654 \uc785\ub825 \uadf8\ub9ac\uace0 \uc2ec\ud654 \ucd9c\ub825","tut/ko/\ube68\uac04\ube14\ub85d \uac80\uc740\ube14\ub85d/7.\uac8c\uc784\ud310/\uc2ec\ud654 \ucd9c\ub825 \uadf8\ub9ac\uace0 \uc870\uae08 \ub354","tut/ko/\ube68\uac04\ube14\ub85d \uac80\uc740\ube14\ub85d/8.\uc5d0\ud544\ub85c\uadf8/\uc5d0\ud544\ub85c\uadf8","tut/ko/\ube68\uac04\ube14\ub85d \uac80\uc740\ube14\ub85d/overview","tut/newbieguide","tut/tom_games2","tut/tom_games3","tut/tom_games4","tut/tom_games5","tut/tom_games6"],envversion:{"sphinx.domains.c":2,"sphinx.domains.changeset":1,"sphinx.domains.citation":1,"sphinx.domains.cpp":4,"sphinx.domains.index":1,"sphinx.domains.javascript":2,"sphinx.domains.math":2,"sphinx.domains.python":3,"sphinx.domains.rst":2,"sphinx.domains.std":2,sphinx:56},filenames:["c_api.rst","c_api\\base.rst","c_api\\bufferproxy.rst","c_api\\cdrom.rst","c_api\\color.rst","c_api\\display.rst","c_api\\event.rst","c_api\\freetype.rst","c_api\\mixer.rst","c_api\\rect.rst","c_api\\rwobject.rst","c_api\\slots.rst","c_api\\surface.rst","c_api\\surflock.rst","c_api\\version.rst","filepaths.rst","index.rst","ref\\bufferproxy.rst","ref\\camera.rst","ref\\cdrom.rst","ref\\color.rst","ref\\color_list.rst","ref\\cursors.rst","ref\\display.rst","ref\\draw.rst","ref\\event.rst","ref\\examples.rst","ref\\fastevent.rst","ref\\font.rst","ref\\freetype.rst","ref\\gfxdraw.rst","ref\\image.rst","ref\\joystick.rst","ref\\key.rst","ref\\locals.rst","ref\\mask.rst","ref\\math.rst","ref\\midi.rst","ref\\mixer.rst","ref\\mouse.rst","ref\\music.rst","ref\\overlay.rst","ref\\pixelarray.rst","ref\\pixelcopy.rst","ref\\pygame.rst","ref\\rect.rst","ref\\scrap.rst","ref\\sdl2_controller.rst","ref\\sdl2_video.rst","ref\\sndarray.rst","ref\\sprite.rst","ref\\surface.rst","ref\\surfarray.rst","ref\\tests.rst","ref\\time.rst","ref\\touch.rst","ref\\transform.rst","tut\\CameraIntro.rst","tut\\ChimpLineByLine.rst","tut\\DisplayModes.rst","tut\\ImportInit.rst","tut\\MakeGames.rst","tut\\MoveIt.rst","tut\\PygameIntro.rst","tut\\SpriteIntro.rst","tut\\SurfarrayIntro.rst","tut\\chimp.py.rst","tut\\en\\Red_or_Black\\1.Prolog\\introduction.rst","tut\\en\\Red_or_Black\\2.Print_text\\Basic TEMPLATE and OUTPUT.rst","tut\\en\\Red_or_Black\\3.Move_text\\Basic PROCESS.rst","tut\\en\\Red_or_Black\\4.Control_text\\Basic INPUT.rst","tut\\en\\Red_or_Black\\5.HP_bar\\Advanced OUTPUT with Advanced PROCESS.rst","tut\\en\\Red_or_Black\\6.Buttons\\Advanced INPUT with Advanced OUTPUT.rst","tut\\en\\Red_or_Black\\7.Game_board\\Advanced OUTPUT and plus alpha.rst","tut\\en\\Red_or_Black\\8.Epilog\\Epilog.rst","tut\\ko\\\ube68\uac04\ube14\ub85d \uac80\uc740\ube14\ub85d\\1.\ud504\ub864\ub85c\uadf8\\\uc18c\uac1c.rst","tut\\ko\\\ube68\uac04\ube14\ub85d \uac80\uc740\ube14\ub85d\\2.\ud14d\uc2a4\ud2b8 \ucd9c\ub825\\\uae30\ucd08 \ud15c\ud50c\ub9bf\uacfc \ucd9c\ub825.rst","tut\\ko\\\ube68\uac04\ube14\ub85d \uac80\uc740\ube14\ub85d\\3.\ud14d\uc2a4\ud2b8 \uc774\ub3d9\\\uae30\ucd08 \ucc98\ub9ac.rst","tut\\ko\\\ube68\uac04\ube14\ub85d \uac80\uc740\ube14\ub85d\\4.\ud14d\uc2a4\ud2b8 \uc870\uc885\\\uae30\ucd08 \uc785\ub825.rst","tut\\ko\\\ube68\uac04\ube14\ub85d \uac80\uc740\ube14\ub85d\\5.HP\ubc14\\\uc2ec\ud654 \ucd9c\ub825 \uadf8\ub9ac\uace0 \uc2ec\ud654 \ucc98\ub9ac.rst","tut\\ko\\\ube68\uac04\ube14\ub85d \uac80\uc740\ube14\ub85d\\6.\ubc84\ud2bc\ub4e4\\\uc2ec\ud654 \uc785\ub825 \uadf8\ub9ac\uace0 \uc2ec\ud654 \ucd9c\ub825.rst","tut\\ko\\\ube68\uac04\ube14\ub85d \uac80\uc740\ube14\ub85d\\7.\uac8c\uc784\ud310\\\uc2ec\ud654 \ucd9c\ub825 \uadf8\ub9ac\uace0 \uc870\uae08 \ub354.rst","tut\\ko\\\ube68\uac04\ube14\ub85d \uac80\uc740\ube14\ub85d\\8.\uc5d0\ud544\ub85c\uadf8\\\uc5d0\ud544\ub85c\uadf8.rst","tut\\ko\\\ube68\uac04\ube14\ub85d \uac80\uc740\ube14\ub85d\\overview.rst","tut\\newbieguide.rst","tut\\tom_games2.rst","tut\\tom_games3.rst","tut\\tom_games4.rst","tut\\tom_games5.rst","tut\\tom_games6.rst"],objects:{"":[[14,0,1,"c.PG_MAJOR_VERSION","PG_MAJOR_VERSION"],[14,0,1,"c.PG_MINOR_VERSION","PG_MINOR_VERSION"],[14,0,1,"c.PG_PATCH_VERSION","PG_PATCH_VERSION"],[14,0,1,"c.PG_VERSIONNUM","PG_VERSIONNUM"],[14,0,1,"c.PG_VERSION_ATLEAST","PG_VERSION_ATLEAST"],[1,1,1,"c.import_pygame_base","import_pygame_base"],[1,1,1,"c.pgBuffer_AsArrayInterface","pgBuffer_AsArrayInterface"],[1,1,1,"c.pgBuffer_AsArrayStruct","pgBuffer_AsArrayStruct"],[1,1,1,"c.pgBuffer_Release","pgBuffer_Release"],[2,1,1,"c.pgBufproxy_Check","pgBufproxy_Check"],[2,1,1,"c.pgBufproxy_GetParent","pgBufproxy_GetParent"],[2,1,1,"c.pgBufproxy_New","pgBufproxy_New"],[2,1,1,"c.pgBufproxy_Trip","pgBufproxy_Trip"],[2,3,1,"c.pgBufproxy_Type","pgBufproxy_Type"],[3,4,1,"c.pgCDObject","pgCDObject"],[3,1,1,"c.pgCD_AsID","pgCD_AsID"],[3,1,1,"c.pgCD_Check","pgCD_Check"],[3,1,1,"c.pgCD_New","pgCD_New"],[3,3,1,"c.pgCD_Type","pgCD_Type"],[8,4,1,"c.pgChannelObject","pgChannelObject"],[8,1,1,"c.pgChannel_AsInt","pgChannel_AsInt"],[8,1,1,"c.pgChannel_Check","pgChannel_Check"],[8,1,1,"c.pgChannel_New","pgChannel_New"],[8,3,1,"c.pgChannel_Type","pgChannel_Type"],[4,1,1,"c.pgColor_Check","pgColor_Check"],[4,1,1,"c.pgColor_New","pgColor_New"],[4,1,1,"c.pgColor_NewLength","pgColor_NewLength"],[4,3,1,"c.pgColor_Type","pgColor_Type"],[1,1,1,"c.pgDict_AsBuffer","pgDict_AsBuffer"],[6,4,1,"c.pgEventObject","pgEventObject"],[6,1,1,"c.pgEvent_Check","pgEvent_Check"],[6,1,1,"c.pgEvent_FillUserEvent","pgEvent_FillUserEvent"],[6,1,1,"c.pgEvent_New","pgEvent_New"],[6,1,1,"c.pgEvent_New2","pgEvent_New2"],[6,4,1,"c.pgEvent_Type","pgEvent_Type"],[1,3,1,"c.pgExc_BufferError","pgExc_BufferError"],[1,3,1,"c.pgExc_SDLError","pgExc_SDLError"],[7,4,1,"c.pgFontObject","pgFontObject"],[7,1,1,"c.pgFont_Check","pgFont_Check"],[7,1,1,"c.pgFont_IS_ALIVE","pgFont_IS_ALIVE"],[7,1,1,"c.pgFont_New","pgFont_New"],[7,4,1,"c.pgFont_Type","pgFont_Type"],[13,4,1,"c.pgLifetimeLockObject","pgLifetimeLockObject"],[13,1,1,"c.pgLifetimeLock_Check","pgLifetimeLock_Check"],[13,3,1,"c.pgLifetimeLock_Type","pgLifetimeLock_Type"],[1,1,1,"c.pgObject_GetBuffer","pgObject_GetBuffer"],[10,1,1,"c.pgRWops_FromFileObject","pgRWops_FromFileObject"],[10,1,1,"c.pgRWops_FromObject","pgRWops_FromObject"],[10,1,1,"c.pgRWops_GetFileExtension","pgRWops_GetFileExtension"],[10,1,1,"c.pgRWops_IsFileObject","pgRWops_IsFileObject"],[10,1,1,"c.pgRWops_ReleaseObject","pgRWops_ReleaseObject"],[9,4,1,"c.pgRectObject","pgRectObject"],[9,1,1,"c.pgRect_AsRect","pgRect_AsRect"],[9,1,1,"c.pgRect_FromObject","pgRect_FromObject"],[9,1,1,"c.pgRect_New","pgRect_New"],[9,1,1,"c.pgRect_New4","pgRect_New4"],[9,1,1,"c.pgRect_Normalize","pgRect_Normalize"],[9,3,1,"c.pgRect_Type","pgRect_Type"],[8,4,1,"c.pgSoundObject","pgSoundObject"],[8,1,1,"c.pgSound_AsChunk","pgSound_AsChunk"],[8,1,1,"c.pgSound_Check","pgSound_Check"],[8,1,1,"c.pgSound_New","pgSound_New"],[8,3,1,"c.pgSound_Type","pgSound_Type"],[12,4,1,"c.pgSurfaceObject","pgSurfaceObject"],[12,1,1,"c.pgSurface_AsSurface","pgSurface_AsSurface"],[12,1,1,"c.pgSurface_Blit","pgSurface_Blit"],[12,1,1,"c.pgSurface_Check","pgSurface_Check"],[13,1,1,"c.pgSurface_Lock","pgSurface_Lock"],[13,1,1,"c.pgSurface_LockBy","pgSurface_LockBy"],[13,1,1,"c.pgSurface_LockLifetime","pgSurface_LockLifetime"],[12,1,1,"c.pgSurface_New","pgSurface_New"],[13,1,1,"c.pgSurface_Prep","pgSurface_Prep"],[12,3,1,"c.pgSurface_Type","pgSurface_Type"],[13,1,1,"c.pgSurface_UnLock","pgSurface_UnLock"],[13,1,1,"c.pgSurface_UnLockBy","pgSurface_UnLockBy"],[13,1,1,"c.pgSurface_Unprep","pgSurface_Unprep"],[5,4,1,"c.pgVidInfoObject","pgVidInfoObject"],[5,1,1,"c.pgVidInfo_AsVidInfo","pgVidInfo_AsVidInfo"],[5,1,1,"c.pgVidInfo_Check","pgVidInfo_Check"],[5,1,1,"c.pgVidInfo_New","pgVidInfo_New"],[5,3,1,"c.pgVidInfo_Type","pgVidInfo_Type"],[10,1,1,"c.pg_EncodeFilePath","pg_EncodeFilePath"],[10,1,1,"c.pg_EncodeString","pg_EncodeString"],[1,1,1,"c.pg_FloatFromObj","pg_FloatFromObj"],[1,1,1,"c.pg_FloatFromObjIndex","pg_FloatFromObjIndex"],[1,1,1,"c.pg_GetDefaultWindow","pg_GetDefaultWindow"],[1,1,1,"c.pg_GetDefaultWindowSurface","pg_GetDefaultWindowSurface"],[1,1,1,"c.pg_IntFromObj","pg_IntFromObj"],[1,1,1,"c.pg_IntFromObjIndex","pg_IntFromObjIndex"],[1,1,1,"c.pg_RGBAFromObj","pg_RGBAFromObj"],[1,1,1,"c.pg_RegisterQuit","pg_RegisterQuit"],[1,1,1,"c.pg_SetDefaultWindow","pg_SetDefaultWindow"],[1,1,1,"c.pg_SetDefaultWindowSurface","pg_SetDefaultWindowSurface"],[1,1,1,"c.pg_TwoFloatsFromObj","pg_TwoFloatsFromObj"],[1,1,1,"c.pg_TwoIntsFromObj","pg_TwoIntsFromObj"],[1,1,1,"c.pg_UintFromObj","pg_UintFromObj"],[1,1,1,"c.pg_UintFromObjIndex","pg_UintFromObjIndex"],[1,4,1,"c.pg_buffer","pg_buffer"],[1,1,1,"c.pg_mod_autoinit","pg_mod_autoinit"],[1,1,1,"c.pg_mod_autoquit","pg_mod_autoquit"],[44,5,0,"-","pygame"]],"pygame.BufferProxy":[[17,7,1,"","length"],[17,7,1,"","parent"],[17,7,1,"","raw"],[17,8,1,"","write"]],"pygame.Color":[[20,7,1,"","a"],[20,7,1,"","b"],[20,7,1,"","cmy"],[20,8,1,"","correct_gamma"],[20,7,1,"","g"],[20,7,1,"","hsla"],[20,7,1,"","hsva"],[20,7,1,"","i1i2i3"],[20,8,1,"","lerp"],[20,8,1,"","normalize"],[20,8,1,"","premul_alpha"],[20,7,1,"","r"],[20,8,1,"","set_length"],[20,8,1,"","update"]],"pygame.Overlay":[[41,8,1,"","display"],[41,8,1,"","get_hardware"],[41,8,1,"","set_location"]],"pygame.PixelArray":[[42,8,1,"","close"],[42,8,1,"","compare"],[42,8,1,"","extract"],[42,7,1,"","itemsize"],[42,8,1,"","make_surface"],[42,7,1,"","ndim"],[42,8,1,"","replace"],[42,7,1,"","shape"],[42,7,1,"","strides"],[42,7,1,"","surface"],[42,8,1,"","transpose"]],"pygame.Rect":[[45,8,1,"","clamp"],[45,8,1,"","clamp_ip"],[45,8,1,"","clip"],[45,8,1,"","clipline"],[45,8,1,"","collidedict"],[45,8,1,"","collidedictall"],[45,8,1,"","collidelist"],[45,8,1,"","collidelistall"],[45,8,1,"","collidepoint"],[45,8,1,"","colliderect"],[45,8,1,"","contains"],[45,8,1,"","copy"],[45,8,1,"","fit"],[45,8,1,"","inflate"],[45,8,1,"","inflate_ip"],[45,8,1,"","move"],[45,8,1,"","move_ip"],[45,8,1,"","normalize"],[45,8,1,"","union"],[45,8,1,"","union_ip"],[45,8,1,"","unionall"],[45,8,1,"","unionall_ip"],[45,8,1,"","update"]],"pygame.Surface":[[51,7,1,"","_pixels_address"],[51,8,1,"","blit"],[51,8,1,"","blits"],[51,8,1,"","convert"],[51,8,1,"","convert_alpha"],[51,8,1,"","copy"],[51,8,1,"","fill"],[51,8,1,"","get_abs_offset"],[51,8,1,"","get_abs_parent"],[51,8,1,"","get_alpha"],[51,8,1,"","get_at"],[51,8,1,"","get_at_mapped"],[51,8,1,"","get_bitsize"],[51,8,1,"","get_bounding_rect"],[51,8,1,"","get_buffer"],[51,8,1,"","get_bytesize"],[51,8,1,"","get_clip"],[51,8,1,"","get_colorkey"],[51,8,1,"","get_flags"],[51,8,1,"","get_height"],[51,8,1,"","get_locked"],[51,8,1,"","get_locks"],[51,8,1,"","get_losses"],[51,8,1,"","get_masks"],[51,8,1,"","get_offset"],[51,8,1,"","get_palette"],[51,8,1,"","get_palette_at"],[51,8,1,"","get_parent"],[51,8,1,"","get_pitch"],[51,8,1,"","get_rect"],[51,8,1,"","get_shifts"],[51,8,1,"","get_size"],[51,8,1,"","get_view"],[51,8,1,"","get_width"],[51,8,1,"","lock"],[51,8,1,"","map_rgb"],[51,8,1,"","mustlock"],[51,8,1,"","scroll"],[51,8,1,"","set_alpha"],[51,8,1,"","set_at"],[51,8,1,"","set_clip"],[51,8,1,"","set_colorkey"],[51,8,1,"","set_masks"],[51,8,1,"","set_palette"],[51,8,1,"","set_palette_at"],[51,8,1,"","set_shifts"],[51,8,1,"","subsurface"],[51,8,1,"","unlock"],[51,8,1,"","unmap_rgb"]],"pygame._sdl2":[[47,5,0,"-","controller"],[55,5,0,"-","touch"],[48,5,0,"-","video"]],"pygame._sdl2.controller":[[47,6,1,"","Controller"],[47,9,1,"","get_count"],[47,9,1,"","get_eventstate"],[47,9,1,"","get_init"],[47,9,1,"","init"],[47,9,1,"","is_controller"],[47,9,1,"","name_forindex"],[47,9,1,"","quit"],[47,9,1,"","set_eventstate"]],"pygame._sdl2.controller.Controller":[[47,8,1,"","as_joystick"],[47,8,1,"","attached"],[47,8,1,"","from_joystick"],[47,8,1,"","get_axis"],[47,8,1,"","get_button"],[47,8,1,"","get_init"],[47,8,1,"","get_mapping"],[47,8,1,"","quit"],[47,8,1,"","rumble"],[47,8,1,"","set_mapping"],[47,8,1,"","stop_rumble"]],"pygame._sdl2.touch":[[55,9,1,"","get_device"],[55,9,1,"","get_finger"],[55,9,1,"","get_num_devices"],[55,9,1,"","get_num_fingers"]],"pygame._sdl2.video":[[48,6,1,"","Image"],[48,6,1,"","Renderer"],[48,6,1,"","Texture"],[48,6,1,"","Window"]],"pygame._sdl2.video.Image":[[48,7,1,"","alpha"],[48,7,1,"","angle"],[48,7,1,"","blend_mode"],[48,7,1,"","color"],[48,8,1,"","draw"],[48,7,1,"","flipX"],[48,7,1,"","flipY"],[48,8,1,"","get_rect"],[48,7,1,"","origin"],[48,7,1,"","srcrect"],[48,7,1,"","texture"]],"pygame._sdl2.video.Renderer":[[48,8,1,"","blit"],[48,8,1,"","clear"],[48,7,1,"","draw_blend_mode"],[48,7,1,"","draw_color"],[48,8,1,"","draw_line"],[48,8,1,"","draw_point"],[48,8,1,"","draw_rect"],[48,8,1,"","fill_rect"],[48,8,1,"","from_window"],[48,8,1,"","get_viewport"],[48,7,1,"","logical_size"],[48,8,1,"","present"],[48,7,1,"","scale"],[48,8,1,"","set_viewport"],[48,7,1,"","target"],[48,8,1,"","to_surface"]],"pygame._sdl2.video.Texture":[[48,7,1,"","alpha"],[48,7,1,"","blend_mode"],[48,7,1,"","color"],[48,8,1,"","draw"],[48,8,1,"","from_surface"],[48,8,1,"","get_rect"],[48,7,1,"","height"],[48,7,1,"","renderer"],[48,8,1,"","update"],[48,7,1,"","width"]],"pygame._sdl2.video.Window":[[48,7,1,"","borderless"],[48,7,1,"","brightness"],[48,8,1,"","destroy"],[48,7,1,"","display_index"],[48,8,1,"","focus"],[48,8,1,"","from_display_module"],[48,7,1,"","grab"],[48,8,1,"","hide"],[48,7,1,"","id"],[48,8,1,"","maximize"],[48,8,1,"","minimize"],[48,7,1,"","opacity"],[48,7,1,"","position"],[48,7,1,"","relative_mouse"],[48,7,1,"","resizable"],[48,8,1,"","restore"],[48,8,1,"","set_fullscreen"],[48,8,1,"","set_icon"],[48,8,1,"","set_modal_for"],[48,8,1,"","set_windowed"],[48,8,1,"","show"],[48,7,1,"","size"],[48,7,1,"","title"]],"pygame.camera":[[18,6,1,"","Camera"],[18,9,1,"","colorspace"],[18,9,1,"","get_backends"],[18,9,1,"","init"],[18,9,1,"","list_cameras"]],"pygame.camera.Camera":[[18,8,1,"","get_controls"],[18,8,1,"","get_image"],[18,8,1,"","get_raw"],[18,8,1,"","get_size"],[18,8,1,"","query_image"],[18,8,1,"","set_controls"],[18,8,1,"","start"],[18,8,1,"","stop"]],"pygame.cdrom":[[19,6,1,"","CD"],[19,9,1,"","get_count"],[19,9,1,"","get_init"],[19,9,1,"","init"],[19,9,1,"","quit"]],"pygame.cdrom.CD":[[19,8,1,"","eject"],[19,8,1,"","get_all"],[19,8,1,"","get_busy"],[19,8,1,"","get_current"],[19,8,1,"","get_empty"],[19,8,1,"","get_id"],[19,8,1,"","get_init"],[19,8,1,"","get_name"],[19,8,1,"","get_numtracks"],[19,8,1,"","get_paused"],[19,8,1,"","get_track_audio"],[19,8,1,"","get_track_length"],[19,8,1,"","get_track_start"],[19,8,1,"","init"],[19,8,1,"","pause"],[19,8,1,"","play"],[19,8,1,"","quit"],[19,8,1,"","resume"],[19,8,1,"","stop"]],"pygame.cursors":[[22,6,1,"","Cursor"],[22,9,1,"","compile"],[22,9,1,"","load_xbm"]],"pygame.cursors.Cursor":[[22,8,1,"","copy"],[22,7,1,"","data"],[22,7,1,"","type"]],"pygame.display":[[23,9,1,"","Info"],[23,9,1,"","flip"],[23,9,1,"","get_active"],[23,9,1,"","get_allow_screensaver"],[23,9,1,"","get_caption"],[23,9,1,"","get_desktop_sizes"],[23,9,1,"","get_driver"],[23,9,1,"","get_init"],[23,9,1,"","get_num_displays"],[23,9,1,"","get_surface"],[23,9,1,"","get_window_size"],[23,9,1,"","get_wm_info"],[23,9,1,"","gl_get_attribute"],[23,9,1,"","gl_set_attribute"],[23,9,1,"","iconify"],[23,9,1,"","init"],[23,9,1,"","list_modes"],[23,9,1,"","mode_ok"],[23,9,1,"","quit"],[23,9,1,"","set_allow_screensaver"],[23,9,1,"","set_caption"],[23,9,1,"","set_gamma"],[23,9,1,"","set_gamma_ramp"],[23,9,1,"","set_icon"],[23,9,1,"","set_mode"],[23,9,1,"","set_palette"],[23,9,1,"","toggle_fullscreen"],[23,9,1,"","update"]],"pygame.draw":[[24,9,1,"","aaline"],[24,9,1,"","aalines"],[24,9,1,"","arc"],[24,9,1,"","circle"],[24,9,1,"","ellipse"],[24,9,1,"","line"],[24,9,1,"","lines"],[24,9,1,"","polygon"],[24,9,1,"","rect"]],"pygame.event":[[25,9,1,"","Event"],[25,6,1,"","EventType"],[25,9,1,"","clear"],[25,9,1,"","custom_type"],[25,9,1,"","event_name"],[25,9,1,"","get"],[25,9,1,"","get_blocked"],[25,9,1,"","get_grab"],[25,9,1,"","peek"],[25,9,1,"","poll"],[25,9,1,"","post"],[25,9,1,"","pump"],[25,9,1,"","set_allowed"],[25,9,1,"","set_blocked"],[25,9,1,"","set_grab"],[25,9,1,"","wait"]],"pygame.event.EventType":[[25,7,1,"","__dict__"],[25,7,1,"","type"]],"pygame.examples.aliens":[[26,9,1,"","main"]],"pygame.examples.arraydemo":[[26,9,1,"","main"]],"pygame.examples.blend_fill":[[26,9,1,"","main"]],"pygame.examples.blit_blends":[[26,9,1,"","main"]],"pygame.examples.camera":[[26,9,1,"","main"]],"pygame.examples.chimp":[[26,9,1,"","main"]],"pygame.examples.cursors":[[26,9,1,"","main"]],"pygame.examples.eventlist":[[26,9,1,"","main"]],"pygame.examples.fonty":[[26,9,1,"","main"]],"pygame.examples.freetype_misc":[[26,9,1,"","main"]],"pygame.examples.glcube":[[26,9,1,"","main"]],"pygame.examples.headless_no_windows_needed":[[26,9,1,"","main"]],"pygame.examples.joystick":[[26,9,1,"","main"]],"pygame.examples.liquid":[[26,9,1,"","main"]],"pygame.examples.mask":[[26,9,1,"","main"]],"pygame.examples.midi":[[26,9,1,"","main"]],"pygame.examples.moveit":[[26,9,1,"","main"]],"pygame.examples.pixelarray":[[26,9,1,"","main"]],"pygame.examples.playmus":[[26,9,1,"","main"]],"pygame.examples.scaletest":[[26,9,1,"","main"]],"pygame.examples.scrap_clipboard":[[26,9,1,"","main"]],"pygame.examples.scroll":[[26,9,1,"","main"]],"pygame.examples.sound":[[26,9,1,"","main"]],"pygame.examples.sound_array_demos":[[26,9,1,"","main"]],"pygame.examples.stars":[[26,9,1,"","main"]],"pygame.examples.testsprite":[[26,9,1,"","main"]],"pygame.examples.vgrade":[[26,9,1,"","main"]],"pygame.fastevent":[[27,9,1,"","get"],[27,9,1,"","get_init"],[27,9,1,"","init"],[27,9,1,"","poll"],[27,9,1,"","post"],[27,9,1,"","pump"],[27,9,1,"","wait"]],"pygame.font":[[28,6,1,"","Font"],[28,9,1,"","SysFont"],[28,9,1,"","get_default_font"],[28,9,1,"","get_fonts"],[28,9,1,"","get_init"],[28,9,1,"","init"],[28,9,1,"","match_font"],[28,9,1,"","quit"]],"pygame.font.Font":[[28,7,1,"","bold"],[28,8,1,"","get_ascent"],[28,8,1,"","get_bold"],[28,8,1,"","get_descent"],[28,8,1,"","get_height"],[28,8,1,"","get_italic"],[28,8,1,"","get_linesize"],[28,8,1,"","get_underline"],[28,7,1,"","italic"],[28,8,1,"","metrics"],[28,8,1,"","render"],[28,8,1,"","set_bold"],[28,8,1,"","set_italic"],[28,8,1,"","set_underline"],[28,8,1,"","size"],[28,7,1,"","underline"]],"pygame.freetype":[[29,6,1,"","Font"],[29,9,1,"","SysFont"],[29,9,1,"","get_cache_size"],[29,9,1,"","get_default_font"],[29,9,1,"","get_default_resolution"],[29,9,1,"","get_error"],[29,9,1,"","get_init"],[29,9,1,"","get_version"],[29,9,1,"","init"],[29,9,1,"","quit"],[29,9,1,"","set_default_resolution"],[29,9,1,"","was_init"]],"pygame.freetype.Font":[[29,7,1,"","antialiased"],[29,7,1,"","ascender"],[29,7,1,"","bgcolor"],[29,7,1,"","descender"],[29,7,1,"","fgcolor"],[29,7,1,"","fixed_sizes"],[29,7,1,"","fixed_width"],[29,8,1,"","get_metrics"],[29,8,1,"","get_rect"],[29,8,1,"","get_sized_ascender"],[29,8,1,"","get_sized_descender"],[29,8,1,"","get_sized_glyph_height"],[29,8,1,"","get_sized_height"],[29,8,1,"","get_sizes"],[29,7,1,"","height"],[29,7,1,"","kerning"],[29,7,1,"","name"],[29,7,1,"","oblique"],[29,7,1,"","origin"],[29,7,1,"","pad"],[29,7,1,"","path"],[29,8,1,"","render"],[29,8,1,"","render_raw"],[29,8,1,"","render_raw_to"],[29,8,1,"","render_to"],[29,7,1,"","resolution"],[29,7,1,"","rotation"],[29,7,1,"","scalable"],[29,7,1,"","size"],[29,7,1,"","strength"],[29,7,1,"","strong"],[29,7,1,"","style"],[29,7,1,"","ucs4"],[29,7,1,"","underline"],[29,7,1,"","underline_adjustment"],[29,7,1,"","use_bitmap_strikes"],[29,7,1,"","vertical"],[29,7,1,"","wide"]],"pygame.gfxdraw":[[30,9,1,"","aacircle"],[30,9,1,"","aaellipse"],[30,9,1,"","aapolygon"],[30,9,1,"","aatrigon"],[30,9,1,"","arc"],[30,9,1,"","bezier"],[30,9,1,"","box"],[30,9,1,"","circle"],[30,9,1,"","ellipse"],[30,9,1,"","filled_circle"],[30,9,1,"","filled_ellipse"],[30,9,1,"","filled_polygon"],[30,9,1,"","filled_trigon"],[30,9,1,"","hline"],[30,9,1,"","line"],[30,9,1,"","pie"],[30,9,1,"","pixel"],[30,9,1,"","polygon"],[30,9,1,"","rectangle"],[30,9,1,"","textured_polygon"],[30,9,1,"","trigon"],[30,9,1,"","vline"]],"pygame.image":[[31,9,1,"","frombuffer"],[31,9,1,"","fromstring"],[31,9,1,"","get_extended"],[31,9,1,"","get_sdl_image_version"],[31,9,1,"","load"],[31,9,1,"","load_basic"],[31,9,1,"","load_extended"],[31,9,1,"","save"],[31,9,1,"","save_extended"],[31,9,1,"","tostring"]],"pygame.joystick":[[32,6,1,"","Joystick"],[32,9,1,"","get_count"],[32,9,1,"","get_init"],[32,9,1,"","init"],[32,9,1,"","quit"]],"pygame.joystick.Joystick":[[32,8,1,"","get_axis"],[32,8,1,"","get_ball"],[32,8,1,"","get_button"],[32,8,1,"","get_guid"],[32,8,1,"","get_hat"],[32,8,1,"","get_id"],[32,8,1,"","get_init"],[32,8,1,"","get_instance_id"],[32,8,1,"","get_name"],[32,8,1,"","get_numaxes"],[32,8,1,"","get_numballs"],[32,8,1,"","get_numbuttons"],[32,8,1,"","get_numhats"],[32,8,1,"","get_power_level"],[32,8,1,"","init"],[32,8,1,"","quit"],[32,8,1,"","rumble"],[32,8,1,"","stop_rumble"]],"pygame.key":[[33,9,1,"","get_focused"],[33,9,1,"","get_mods"],[33,9,1,"","get_pressed"],[33,9,1,"","get_repeat"],[33,9,1,"","key_code"],[33,9,1,"","name"],[33,9,1,"","set_mods"],[33,9,1,"","set_repeat"],[33,9,1,"","set_text_input_rect"],[33,9,1,"","start_text_input"],[33,9,1,"","stop_text_input"]],"pygame.mask":[[35,6,1,"","Mask"],[35,9,1,"","from_surface"],[35,9,1,"","from_threshold"]],"pygame.mask.Mask":[[35,8,1,"","angle"],[35,8,1,"","centroid"],[35,8,1,"","clear"],[35,8,1,"","connected_component"],[35,8,1,"","connected_components"],[35,8,1,"","convolve"],[35,8,1,"","copy"],[35,8,1,"","count"],[35,8,1,"","draw"],[35,8,1,"","erase"],[35,8,1,"","fill"],[35,8,1,"","get_at"],[35,8,1,"","get_bounding_rects"],[35,8,1,"","get_rect"],[35,8,1,"","get_size"],[35,8,1,"","invert"],[35,8,1,"","outline"],[35,8,1,"","overlap"],[35,8,1,"","overlap_area"],[35,8,1,"","overlap_mask"],[35,8,1,"","scale"],[35,8,1,"","set_at"],[35,8,1,"","to_surface"]],"pygame.math":[[36,6,1,"","Vector2"],[36,6,1,"","Vector3"]],"pygame.math.Vector2":[[36,8,1,"","angle_to"],[36,8,1,"","as_polar"],[36,8,1,"","copy"],[36,8,1,"","cross"],[36,8,1,"","distance_squared_to"],[36,8,1,"","distance_to"],[36,8,1,"","dot"],[36,8,1,"","elementwise"],[36,8,1,"","from_polar"],[36,8,1,"","is_normalized"],[36,8,1,"","length"],[36,8,1,"","length_squared"],[36,8,1,"","lerp"],[36,8,1,"","magnitude"],[36,8,1,"","magnitude_squared"],[36,8,1,"","normalize"],[36,8,1,"","normalize_ip"],[36,8,1,"","project"],[36,8,1,"","reflect"],[36,8,1,"","reflect_ip"],[36,8,1,"","rotate"],[36,8,1,"","rotate_ip"],[36,8,1,"","rotate_ip_rad"],[36,8,1,"","rotate_rad"],[36,8,1,"","rotate_rad_ip"],[36,8,1,"","scale_to_length"],[36,8,1,"","slerp"],[36,8,1,"","update"]],"pygame.math.Vector3":[[36,8,1,"","angle_to"],[36,8,1,"","as_spherical"],[36,8,1,"","copy"],[36,8,1,"","cross"],[36,8,1,"","distance_squared_to"],[36,8,1,"","distance_to"],[36,8,1,"","dot"],[36,8,1,"","elementwise"],[36,8,1,"","from_spherical"],[36,8,1,"","is_normalized"],[36,8,1,"","length"],[36,8,1,"","length_squared"],[36,8,1,"","lerp"],[36,8,1,"","magnitude"],[36,8,1,"","magnitude_squared"],[36,8,1,"","normalize"],[36,8,1,"","normalize_ip"],[36,8,1,"","project"],[36,8,1,"","reflect"],[36,8,1,"","reflect_ip"],[36,8,1,"","rotate"],[36,8,1,"","rotate_ip"],[36,8,1,"","rotate_ip_rad"],[36,8,1,"","rotate_rad"],[36,8,1,"","rotate_rad_ip"],[36,8,1,"","rotate_x"],[36,8,1,"","rotate_x_ip"],[36,8,1,"","rotate_x_ip_rad"],[36,8,1,"","rotate_x_rad"],[36,8,1,"","rotate_x_rad_ip"],[36,8,1,"","rotate_y"],[36,8,1,"","rotate_y_ip"],[36,8,1,"","rotate_y_ip_rad"],[36,8,1,"","rotate_y_rad"],[36,8,1,"","rotate_y_rad_ip"],[36,8,1,"","rotate_z"],[36,8,1,"","rotate_z_ip"],[36,8,1,"","rotate_z_ip_rad"],[36,8,1,"","rotate_z_rad"],[36,8,1,"","rotate_z_rad_ip"],[36,8,1,"","scale_to_length"],[36,8,1,"","slerp"],[36,8,1,"","update"]],"pygame.midi":[[37,6,1,"","Input"],[37,10,1,"","MidiException"],[37,6,1,"","Output"],[37,9,1,"","frequency_to_midi"],[37,9,1,"","get_count"],[37,9,1,"","get_default_input_id"],[37,9,1,"","get_default_output_id"],[37,9,1,"","get_device_info"],[37,9,1,"","get_init"],[37,9,1,"","init"],[37,9,1,"","midi_to_ansi_note"],[37,9,1,"","midi_to_frequency"],[37,9,1,"","midis2events"],[37,9,1,"","quit"],[37,9,1,"","time"]],"pygame.midi.Input":[[37,8,1,"","close"],[37,8,1,"","poll"],[37,8,1,"","read"]],"pygame.midi.Output":[[37,8,1,"","abort"],[37,8,1,"","close"],[37,8,1,"","note_off"],[37,8,1,"","note_on"],[37,8,1,"","pitch_bend"],[37,8,1,"","set_instrument"],[37,8,1,"","write"],[37,8,1,"","write_short"],[37,8,1,"","write_sys_ex"]],"pygame.mixer":[[38,6,1,"","Channel"],[38,6,1,"","Sound"],[38,9,1,"","fadeout"],[38,9,1,"","find_channel"],[38,9,1,"","get_busy"],[38,9,1,"","get_init"],[38,9,1,"","get_num_channels"],[38,9,1,"","get_sdl_mixer_version"],[38,9,1,"","init"],[40,5,0,"-","music"],[38,9,1,"","pause"],[38,9,1,"","pre_init"],[38,9,1,"","quit"],[38,9,1,"","set_num_channels"],[38,9,1,"","set_reserved"],[38,9,1,"","stop"],[38,9,1,"","unpause"]],"pygame.mixer.Channel":[[38,8,1,"","fadeout"],[38,8,1,"","get_busy"],[38,8,1,"","get_endevent"],[38,8,1,"","get_queue"],[38,8,1,"","get_sound"],[38,8,1,"","get_volume"],[38,8,1,"","pause"],[38,8,1,"","play"],[38,8,1,"","queue"],[38,8,1,"","set_endevent"],[38,8,1,"","set_volume"],[38,8,1,"","stop"],[38,8,1,"","unpause"]],"pygame.mixer.Sound":[[38,8,1,"","fadeout"],[38,8,1,"","get_length"],[38,8,1,"","get_num_channels"],[38,8,1,"","get_raw"],[38,8,1,"","get_volume"],[38,8,1,"","play"],[38,8,1,"","set_volume"],[38,8,1,"","stop"]],"pygame.mixer.music":[[40,9,1,"","fadeout"],[40,9,1,"","get_busy"],[40,9,1,"","get_endevent"],[40,9,1,"","get_pos"],[40,9,1,"","get_volume"],[40,9,1,"","load"],[40,9,1,"","pause"],[40,9,1,"","play"],[40,9,1,"","queue"],[40,9,1,"","rewind"],[40,9,1,"","set_endevent"],[40,9,1,"","set_pos"],[40,9,1,"","set_volume"],[40,9,1,"","stop"],[40,9,1,"","unload"],[40,9,1,"","unpause"]],"pygame.mouse":[[39,9,1,"","get_cursor"],[39,9,1,"","get_focused"],[39,9,1,"","get_pos"],[39,9,1,"","get_pressed"],[39,9,1,"","get_rel"],[39,9,1,"","get_visible"],[39,9,1,"","set_cursor"],[39,9,1,"","set_pos"],[39,9,1,"","set_visible"]],"pygame.pixelcopy":[[43,9,1,"","array_to_surface"],[43,9,1,"","make_surface"],[43,9,1,"","map_array"],[43,9,1,"","surface_to_array"]],"pygame.scrap":[[46,9,1,"","contains"],[46,9,1,"","get"],[46,9,1,"","get_init"],[46,9,1,"","get_types"],[46,9,1,"","init"],[46,9,1,"","lost"],[46,9,1,"","put"],[46,9,1,"","set_mode"]],"pygame.sndarray":[[49,9,1,"","array"],[49,9,1,"","get_arraytype"],[49,9,1,"","get_arraytypes"],[49,9,1,"","make_sound"],[49,9,1,"","samples"],[49,9,1,"","use_arraytype"]],"pygame.sprite":[[50,6,1,"","DirtySprite"],[50,6,1,"","Group"],[50,9,1,"","GroupSingle"],[50,6,1,"","LayeredDirty"],[50,6,1,"","LayeredUpdates"],[50,9,1,"","OrderedUpdates"],[50,6,1,"","RenderClear"],[50,6,1,"","RenderPlain"],[50,6,1,"","RenderUpdates"],[50,6,1,"","Sprite"],[50,9,1,"","collide_circle"],[50,9,1,"","collide_circle_ratio"],[50,9,1,"","collide_mask"],[50,9,1,"","collide_rect"],[50,9,1,"","collide_rect_ratio"],[50,9,1,"","groupcollide"],[50,9,1,"","spritecollide"],[50,9,1,"","spritecollideany"]],"pygame.sprite.Group":[[50,8,1,"","add"],[50,8,1,"","clear"],[50,8,1,"","copy"],[50,8,1,"","draw"],[50,8,1,"","empty"],[50,8,1,"","has"],[50,8,1,"","remove"],[50,8,1,"","sprites"],[50,8,1,"","update"]],"pygame.sprite.LayeredDirty":[[50,8,1,"","change_layer"],[50,8,1,"","clear"],[50,8,1,"","draw"],[50,8,1,"","get_clip"],[50,8,1,"","repaint_rect"],[50,8,1,"","set_clip"],[50,8,1,"","set_timing_threshold"],[50,8,1,"","set_timing_treshold"]],"pygame.sprite.LayeredUpdates":[[50,8,1,"","add"],[50,8,1,"","change_layer"],[50,8,1,"","draw"],[50,8,1,"","get_bottom_layer"],[50,8,1,"","get_layer_of_sprite"],[50,8,1,"","get_sprite"],[50,8,1,"","get_sprites_at"],[50,8,1,"","get_sprites_from_layer"],[50,8,1,"","get_top_layer"],[50,8,1,"","get_top_sprite"],[50,8,1,"","layers"],[50,8,1,"","move_to_back"],[50,8,1,"","move_to_front"],[50,8,1,"","remove_sprites_of_layer"],[50,8,1,"","sprites"],[50,8,1,"","switch_layer"]],"pygame.sprite.RenderUpdates":[[50,8,1,"","draw"]],"pygame.sprite.Sprite":[[50,8,1,"","add"],[50,8,1,"","alive"],[50,8,1,"","groups"],[50,8,1,"","kill"],[50,8,1,"","remove"],[50,8,1,"","update"]],"pygame.surfarray":[[52,9,1,"","array2d"],[52,9,1,"","array3d"],[52,9,1,"","array_alpha"],[52,9,1,"","array_blue"],[52,9,1,"","array_colorkey"],[52,9,1,"","array_green"],[52,9,1,"","array_red"],[52,9,1,"","blit_array"],[52,9,1,"","get_arraytype"],[52,9,1,"","get_arraytypes"],[52,9,1,"","make_surface"],[52,9,1,"","map_array"],[52,9,1,"","pixels2d"],[52,9,1,"","pixels3d"],[52,9,1,"","pixels_alpha"],[52,9,1,"","pixels_blue"],[52,9,1,"","pixels_green"],[52,9,1,"","pixels_red"],[52,9,1,"","use_arraytype"]],"pygame.tests":[[53,9,1,"","run"]],"pygame.time":[[54,6,1,"","Clock"],[54,9,1,"","delay"],[54,9,1,"","get_ticks"],[54,9,1,"","set_timer"],[54,9,1,"","wait"]],"pygame.time.Clock":[[54,8,1,"","get_fps"],[54,8,1,"","get_rawtime"],[54,8,1,"","get_time"],[54,8,1,"","tick"],[54,8,1,"","tick_busy_loop"]],"pygame.transform":[[56,9,1,"","average_color"],[56,9,1,"","average_surfaces"],[56,9,1,"","chop"],[56,9,1,"","flip"],[56,9,1,"","get_smoothscale_backend"],[56,9,1,"","laplacian"],[56,9,1,"","rotate"],[56,9,1,"","rotozoom"],[56,9,1,"","scale"],[56,9,1,"","scale2x"],[56,9,1,"","set_smoothscale_backend"],[56,9,1,"","smoothscale"],[56,9,1,"","threshold"]],"pygame.version":[[44,11,1,"","SDL"],[44,11,1,"","rev"],[44,11,1,"","ver"],[44,11,1,"","vernum"]],pgBuffer_AsArrayInterface:[[1,2,1,"c.pgBuffer_AsArrayInterface","view_p"]],pgBuffer_AsArrayStruct:[[1,2,1,"c.pgBuffer_AsArrayStruct","view_p"]],pgBuffer_Release:[[1,2,1,"c.pgBuffer_Release","pg_view_p"]],pgBufproxy_Check:[[2,2,1,"c.pgBufproxy_Check","x"]],pgBufproxy_GetParent:[[2,2,1,"c.pgBufproxy_GetParent","obj"]],pgBufproxy_New:[[2,2,1,"c.pgBufproxy_New","get_buffer"],[2,2,1,"c.pgBufproxy_New","obj"]],pgBufproxy_Trip:[[2,2,1,"c.pgBufproxy_Trip","obj"]],pgCD_AsID:[[3,2,1,"c.pgCD_AsID","x"]],pgCD_Check:[[3,2,1,"c.pgCD_Check","x"]],pgCD_New:[[3,2,1,"c.pgCD_New","id"]],pgChannel_AsInt:[[8,2,1,"c.pgChannel_AsInt","x"]],pgChannel_Check:[[8,2,1,"c.pgChannel_Check","obj"]],pgChannel_New:[[8,2,1,"c.pgChannel_New","channelnum"]],pgColor_Check:[[4,2,1,"c.pgColor_Check","obj"]],pgColor_New:[[4,2,1,"c.pgColor_New","rgba"]],pgColor_NewLength:[[4,2,1,"c.pgColor_NewLength","length"],[4,2,1,"c.pgColor_NewLength","rgba"]],pgDict_AsBuffer:[[1,2,1,"c.pgDict_AsBuffer","dict"],[1,2,1,"c.pgDict_AsBuffer","flags"],[1,2,1,"c.pgDict_AsBuffer","pg_view_p"]],pgEventObject:[[6,3,1,"c.pgEventObject.type","type"]],pgEvent_Check:[[6,2,1,"c.pgEvent_Check","x"]],pgEvent_FillUserEvent:[[6,2,1,"c.pgEvent_FillUserEvent","e"],[6,2,1,"c.pgEvent_FillUserEvent","event"]],pgEvent_New2:[[6,2,1,"c.pgEvent_New2","dict"],[6,2,1,"c.pgEvent_New2","type"]],pgEvent_New:[[6,2,1,"c.pgEvent_New","event"]],pgFont_Check:[[7,2,1,"c.pgFont_Check","x"]],pgFont_IS_ALIVE:[[7,2,1,"c.pgFont_IS_ALIVE","o"]],pgFont_New:[[7,2,1,"c.pgFont_New","filename"],[7,2,1,"c.pgFont_New","font_index"]],pgLifetimeLockObject:[[13,3,1,"c.pgLifetimeLockObject.lockobj","lockobj"],[13,3,1,"c.pgLifetimeLockObject.surface","surface"]],pgLifetimeLock_Check:[[13,2,1,"c.pgLifetimeLock_Check","x"]],pgObject_GetBuffer:[[1,2,1,"c.pgObject_GetBuffer","flags"],[1,2,1,"c.pgObject_GetBuffer","obj"],[1,2,1,"c.pgObject_GetBuffer","pg_view_p"]],pgRWops_FromFileObject:[[10,2,1,"c.pgRWops_FromFileObject","obj"]],pgRWops_FromObject:[[10,2,1,"c.pgRWops_FromObject","obj"]],pgRWops_GetFileExtension:[[10,2,1,"c.pgRWops_GetFileExtension","rw"]],pgRWops_IsFileObject:[[10,2,1,"c.pgRWops_IsFileObject","rw"]],pgRWops_ReleaseObject:[[10,2,1,"c.pgRWops_ReleaseObject","context"]],pgRectObject:[[9,3,1,"c.pgRectObject.r","r"]],pgRect_AsRect:[[9,2,1,"c.pgRect_AsRect","obj"]],pgRect_FromObject:[[9,2,1,"c.pgRect_FromObject","obj"],[9,2,1,"c.pgRect_FromObject","temp"]],pgRect_New4:[[9,2,1,"c.pgRect_New4","h"],[9,2,1,"c.pgRect_New4","w"],[9,2,1,"c.pgRect_New4","x"],[9,2,1,"c.pgRect_New4","y"]],pgRect_New:[[9,2,1,"c.pgRect_New","r"]],pgRect_Normalize:[[9,2,1,"c.pgRect_Normalize","rect"]],pgSound_AsChunk:[[8,2,1,"c.pgSound_AsChunk","x"]],pgSound_Check:[[8,2,1,"c.pgSound_Check","obj"]],pgSound_New:[[8,2,1,"c.pgSound_New","chunk"]],pgSurface_AsSurface:[[12,2,1,"c.pgSurface_AsSurface","x"]],pgSurface_Blit:[[12,2,1,"c.pgSurface_Blit","dstobj"],[12,2,1,"c.pgSurface_Blit","dstrect"],[12,2,1,"c.pgSurface_Blit","srcobj"],[12,2,1,"c.pgSurface_Blit","srcrect"],[12,2,1,"c.pgSurface_Blit","the_args"]],pgSurface_Check:[[12,2,1,"c.pgSurface_Check","x"]],pgSurface_Lock:[[13,2,1,"c.pgSurface_Lock","surfobj"]],pgSurface_LockBy:[[13,2,1,"c.pgSurface_LockBy","lockobj"],[13,2,1,"c.pgSurface_LockBy","surfobj"]],pgSurface_LockLifetime:[[13,2,1,"c.pgSurface_LockLifetime","lockobj"],[13,2,1,"c.pgSurface_LockLifetime","surfobj"]],pgSurface_New:[[12,2,1,"c.pgSurface_New","s"]],pgSurface_Prep:[[13,2,1,"c.pgSurface_Prep","surfobj"]],pgSurface_UnLock:[[13,2,1,"c.pgSurface_UnLock","surfobj"]],pgSurface_UnLockBy:[[13,2,1,"c.pgSurface_UnLockBy","lockobj"],[13,2,1,"c.pgSurface_UnLockBy","surfobj"]],pgSurface_Unprep:[[13,2,1,"c.pgSurface_Unprep","surfobj"]],pgVidInfo_AsVidInfo:[[5,2,1,"c.pgVidInfo_AsVidInfo","obj"]],pgVidInfo_Check:[[5,2,1,"c.pgVidInfo_Check","x"]],pgVidInfo_New:[[5,2,1,"c.pgVidInfo_New","i"]],pg_EncodeFilePath:[[10,2,1,"c.pg_EncodeFilePath","eclass"],[10,2,1,"c.pg_EncodeFilePath","obj"]],pg_EncodeString:[[10,2,1,"c.pg_EncodeString","eclass"],[10,2,1,"c.pg_EncodeString","encoding"],[10,2,1,"c.pg_EncodeString","errors"],[10,2,1,"c.pg_EncodeString","obj"]],pg_FloatFromObj:[[1,2,1,"c.pg_FloatFromObj","obj"],[1,2,1,"c.pg_FloatFromObj","val"]],pg_FloatFromObjIndex:[[1,2,1,"c.pg_FloatFromObjIndex","index"],[1,2,1,"c.pg_FloatFromObjIndex","obj"],[1,2,1,"c.pg_FloatFromObjIndex","val"]],pg_IntFromObj:[[1,2,1,"c.pg_IntFromObj","obj"],[1,2,1,"c.pg_IntFromObj","val"]],pg_IntFromObjIndex:[[1,2,1,"c.pg_IntFromObjIndex","index"],[1,2,1,"c.pg_IntFromObjIndex","obj"],[1,2,1,"c.pg_IntFromObjIndex","val"]],pg_RGBAFromObj:[[1,2,1,"c.pg_RGBAFromObj","RGBA"],[1,2,1,"c.pg_RGBAFromObj","obj"]],pg_RegisterQuit:[[1,2,1,"c.pg_RegisterQuit","f"]],pg_SetDefaultWindow:[[1,2,1,"c.pg_SetDefaultWindow","win"]],pg_SetDefaultWindowSurface:[[1,2,1,"c.pg_SetDefaultWindowSurface","screen"]],pg_TwoFloatsFromObj:[[1,2,1,"c.pg_TwoFloatsFromObj","obj"],[1,2,1,"c.pg_TwoFloatsFromObj","val1"],[1,2,1,"c.pg_TwoFloatsFromObj","val2"]],pg_TwoIntsFromObj:[[1,2,1,"c.pg_TwoIntsFromObj","obj"],[1,2,1,"c.pg_TwoIntsFromObj","v2"],[1,2,1,"c.pg_TwoIntsFromObj","val1"]],pg_UintFromObj:[[1,2,1,"c.pg_UintFromObj","obj"],[1,2,1,"c.pg_UintFromObj","val"]],pg_UintFromObjIndex:[[1,2,1,"c.pg_UintFromObjIndex","_index"],[1,2,1,"c.pg_UintFromObjIndex","obj"],[1,2,1,"c.pg_UintFromObjIndex","val"]],pg_buffer:[[1,3,1,"c.pg_buffer.consumer","consumer"],[1,3,1,"c.pg_buffer.release_buffer","release_buffer"],[1,3,1,"c.pg_buffer.view","view"]],pg_mod_autoinit:[[1,2,1,"c.pg_mod_autoinit","modname"]],pg_mod_autoquit:[[1,2,1,"c.pg_mod_autoquit","modname"]],pygame:[[17,6,1,"","BufferProxy"],[20,6,1,"","Color"],[41,6,1,"","Overlay"],[42,6,1,"","PixelArray"],[45,6,1,"","Rect"],[51,6,1,"","Surface"],[18,5,0,"-","camera"],[19,5,0,"-","cdrom"],[22,5,0,"-","cursors"],[23,5,0,"-","display"],[24,5,0,"-","draw"],[44,9,1,"","encode_file_path"],[44,9,1,"","encode_string"],[44,10,1,"","error"],[25,5,0,"-","event"],[26,5,0,"-","examples"],[27,5,0,"-","fastevent"],[28,5,0,"-","font"],[29,5,0,"-","freetype"],[44,9,1,"","get_error"],[44,9,1,"","get_init"],[44,9,1,"","get_sdl_byteorder"],[44,9,1,"","get_sdl_version"],[30,5,0,"-","gfxdraw"],[31,5,0,"-","image"],[44,9,1,"","init"],[32,5,0,"-","joystick"],[33,5,0,"-","key"],[34,5,0,"-","locals"],[35,5,0,"-","mask"],[36,5,0,"-","math"],[37,5,0,"-","midi"],[38,5,0,"-","mixer"],[39,5,0,"-","mouse"],[43,5,0,"-","pixelcopy"],[44,9,1,"","quit"],[44,9,1,"","register_quit"],[46,5,0,"-","scrap"],[44,9,1,"","set_error"],[49,5,0,"-","sndarray"],[50,5,0,"-","sprite"],[52,5,0,"-","surfarray"],[53,5,0,"-","tests"],[54,5,0,"-","time"],[56,5,0,"-","transform"],[44,5,0,"-","version"]]},objnames:{"0":["c","macro","C macro"],"1":["c","function","C function"],"10":["py","exception","Python exception"],"11":["py","data","Python data"],"2":["c","functionParam","C function parameter"],"3":["c","member","C member"],"4":["c","type","C type"],"5":["py","module","Python module"],"6":["py","class","Python class"],"7":["py","attribute","Python attribute"],"8":["py","method","Python method"],"9":["py","function","Python function"]},objtypes:{"0":"c:macro","1":"c:function","10":"py:exception","11":"py:data","2":"c:functionParam","3":"c:member","4":"c:type","5":"py:module","6":"py:class","7":"py:attribute","8":"py:method","9":"py:function"},terms:{"0":[1,2,6,7,10,12,17,18,19,20,22,23,24,25,26,28,29,30,31,32,33,35,36,37,38,39,40,41,42,43,44,45,47,48,50,51,52,54,55,56,57,58,59,62,63,64,65,66,67,68,69,70,71,72,73,75,76,77,78,79,80,81,84,85,86,88,89],"02778":29,"08333":29,"0\uac1c":[78,79],"0\ucc28\uc6d0":81,"0d":73,"0dev11":32,"0x00":20,"0x00000000":51,"0x00000001":51,"0x00000004":51,"0x00000100":51,"0x00001000":51,"0x00002000":51,"0x00004000":51,"0x00010000":51,"0x01000000":51,"0x10":37,"0x10000":29,"0x10ffff":29,"0x11":37,"0x12":37,"0x13":37,"0x7d":37,"0x90":37,"0xaacce":42,"0xc0":37,"0xd800":29,"0xdfff":29,"0xf0":37,"0xf7":37,"0xff":20,"0xff00ff":42,"0xffff":23,"0xrrggbb":20,"0xrrggbbaa":20,"1":[1,2,3,4,6,9,12,14,16,17,18,20,22,23,24,25,26,28,29,30,31,32,33,35,36,37,38,39,40,42,43,44,45,46,47,48,49,50,51,52,54,55,56,57,58,59,60,62,63,64,65,66,67,68,69,70,71,72,73,75,76,77,78,79,80,81,83,84],"10":[23,24,26,32,35,36,45,54,56,58,62,63,65,66,68,69,70,71,72,73,76,77,78,79,80,81,84,85,88,89],"100":[20,24,37,51,57,62,65,84],"1000":[50,54,84],"1024":[37,38],"105":57,"1080":[23,59],"1080p":23,"10\ub610\ub294":79,"10\uc758":76,"10\uc774":77,"10th":35,"11":[32,68,69,76,77],"114":42,"115":24,"117":26,"11\uc744":77,"11\uc758":76,"11\uc774":77,"12":[11,29,32,44,58,66,68,76],"120":22,"1234":44,"125":24,"127":[35,37,71,72,73,79,80,81],"128":65,"1280":[58,66],"13":[32,63,65,68,76,89],"135":24,"14":[32,47,68,76],"140":[67,68,69,70,75,76,77,78],"145":57,"14\uc758":76,"15":[24,32,51,58,66,68,69,76,77],"150":[24,85],"15\uc758":76,"16":[15,22,23,29,32,38,49,59,65,68,76],"16711680":59,"16bit":38,"17":[63,68,76],"170":[42,57,58,66],"17\uc5d0\uc11c\uc758":76,"18":[24,58,63,66,68,76],"187":[58,66],"19":[68,76],"192":84,"1920":[23,59],"19\ub294":76,"19\uc5d0\uc11c":76,"1\uac1c":78,"1\uac1c\uc758":76,"1\uacfc":77,"1\uc778":75,"1\uc778\uc9c0":81,"1\uc904\uc9dc\ub9ac":76,"1\ucc28\uc6d0":81,"1\ucd08\uc5d0":77,"1d":[42,73],"1s":62,"1x1":37,"2":[1,9,15,17,18,19,20,22,23,24,25,26,27,28,29,30,31,32,33,35,36,37,38,39,40,41,42,43,44,45,47,50,51,52,54,55,56,57,58,61,63,65,66,67,68,69,70,71,72,73,75,76,77,78,79,80,81,83,84],"20":[22,24,32,45,56,65,68,71,72,73,76,79,80,81,84],"200":[24,63],"2000":[16,63],"20000":37,"2001":63,"2004":18,"204":42,"20500":37,"20\uc77c":79,"20\uc904\uc9dc\ub9ac":76,"21":[37,63],"210":24,"22":49,"220":[24,67,68,69,70,75,76,77,78],"22000":49,"22050":38,"225":24,"23":63,"235":[58,66],"238":[42,58,66],"2380":23,"24":[17,18,22,24,28,31,42,51,52,56,63,65],"240":[63,68,69,70,71,72,73,76,77,78,79,80,81],"24x24":22,"25":[56,58,66],"250":[24,85],"255":[1,20,24,28,29,30,35,42,43,50,51,56,57,58,59,65,68,69,70,71,72,73,76,77,78,79,80,81,84,85],"256":[23,37,51],"260":24,"27":37,"270":[72,73,80,81],"28":84,"299":42,"2\uac1c\ub97c":80,"2\uac1c\uc758":78,"2\ucc28\ub235":81,"2\ucc28\uc6d0":81,"2d":[16,35,42,43,48,52,63,64,65,68,73,76],"2d\uc6a9":76,"2pre":36,"2s":62,"2x2":65,"3":[1,17,18,20,22,23,24,28,30,31,32,33,36,37,38,39,42,43,44,47,50,51,61,62,63,64,65,67,68,69,70,71,73,76,77,78,79,81,83,84],"30":[22,24,29,30,38,45,53,57,63,71,84],"300":24,"3072":38,"30\uc73c\ub85c":79,"315":29,"32":[1,15,17,18,29,31,35,38,51,52,56,59,65,68,69,70,71,72,73,76,77,78,79,80,81],"320":[63,68,69,70,71,72,73,76,77,78,79,80,81],"325":[72,73,80,81],"32767":47,"32768":47,"32x32":23,"33":65,"35":[74,84],"359":29,"35\ub144":82,"36":[29,85],"360":[20,29,32,47,58,66],"390":29,"3\uac1c\uc758":[76,79],"3d":[23,26,43,52,63,65,67],"3f":32,"3rd":63,"3x3":65,"4":[1,4,9,17,20,24,28,29,32,33,36,37,38,39,42,47,51,56,57,58,59,60,61,62,65,66,68,69,70,71,72,73,76,77,78,79,80,81,83,84,86,89],"40":[22,24,54,56,62,63,71,72,73,79,80,81,84],"400":[22,23,24,57],"4096":[37,38],"42":24,"425":[72,73,80,81],"4321":44,"44100":38,"45":[29,72,73,80,81],"47":89,"480":[18,26,39,48,57,58,59,62,66,68,69,70,71,72,73,76,77,78,79,80,81,89],"480\uc73c\ub85c":76,"4\uac1c\uc758":[76,79],"4k":23,"4th":65,"5":[14,20,23,24,25,29,32,33,35,36,37,38,39,40,42,44,46,49,50,57,58,61,62,63,65,66,68,69,70,71,72,73,76,77,78,79,80,81,83,89],"50":[22,24,26,57,65,73,81,84,85],"500":32,"500m":37,"512":38,"55":56,"56":24,"587":42,"5\uac00":77,"5\uac1c\uc758":76,"5\uc5d0":78,"5x5":[73,81],"6":[24,26,32,33,38,44,50,61,62,65,68,69,70,71,73,76,77,78,79,81,83],"60":[22,24,37,38,39,58,66,69,71,72,73,77,79,80,81,89],"600":[22,59,62],"60\uc774\ub77c\ub294":77,"63":20,"64":[20,29,56,58,66],"640":[18,26,39,48,57,59,62,68,69,70,71,72,73,76,77,78,79,80,81,89],"640x480":[23,62,65],"65":[37,56],"65280":59,"6\uc744":79,"6x":84,"7":[23,32,33,43,44,63,65,68,69,70,71,76,77,78,79,83],"70":24,"700":[23,32],"72":29,"720":29,"75":[22,24,69,77],"7\uc5d0\uc11c":79,"7\uc758":76,"8":[15,17,18,20,22,23,24,26,28,29,30,31,32,33,35,38,42,43,44,46,49,50,51,52,54,56,59,62,63,65,68,69,70,76,77,78,83,89],"80":[24,50,58,66],"800":59,"8191":37,"8192":37,"8\uc758":76,"8bit":38,"9":[14,16,17,18,20,23,25,26,29,30,32,33,35,36,37,38,40,42,43,44,45,46,47,51,52,56,57,65,68,69,70,76,77,78],"90":[24,35,38,56,57,58,66,89],"97":33,"9\uc758":76,"\uac00":[76,77,81],"\uac00\ub2a5":80,"\uac00\ub3c5\uc131\uc744":76,"\uac00\ubcf4\uc790":78,"\uac00\uc18d":77,"\uac00\uc7a5":[76,79,82],"\uac00\uc815\ud558\uba74":76,"\uac00\uc815\ud574":75,"\uac00\uc9c0\uace0":[75,78,81],"\uac00\uc9c0\uae30":76,"\uac00\uc9c0\ub294":76,"\uac00\uc9c0\ubbc0\ub85c":[76,79],"\uac00\uc9c4\ub2e4":[76,80],"\uac00\uc9c4\ub2e4\ub294":75,"\uac00\uc9c8":82,"\uac01\uac01":79,"\uac01\uac01\uc758":79,"\uac04\ub2e8\ud558\ub2e4":81,"\uac10\uc18c\uc2dc\ud0a4\ub294":80,"\uac10\uc18c\ud55c\ub2e4":81,"\uac12":79,"\uac12\ub9cc\uc774":79,"\uac12\uc740":[76,79],"\uac12\uc744":[76,79,80],"\uac12\uc774":79,"\uac12\uc774\uace0":79,"\uac16\ub294":[81,82],"\uac19\ub2e4":[75,76,82],"\uac19\uc544":[77,81],"\uac19\uc740":[76,77,82],"\uac19\uc74c":81,"\uac19\uc774":[76,79],"\uac1c\ub150\uc740":82,"\uac1c\ub150\uc744":77,"\uac1c\ub150\uc774\ub2e4":82,"\uac1c\ubc1c\uc790\uac00":75,"\uac1c\uc120\uc758":81,"\uac1c\uc218\ub97c":81,"\uac1c\uc218\ub9cc\ud07c":79,"\uac1d\uccb4":[76,78],"\uac1d\uccb4\uc5d0":76,"\uac1d\uccb4\uc758":76,"\uac70\uc758":[75,76],"\uac71\uc815\ud558\uc9c0":82,"\uac78\ub9ac\ub294":76,"\uac80\uc740":[79,81],"\uac80\uc740\ube14\ub85d":16,"\uac83":[75,76,78],"\uac83\uacfc":[80,82],"\uac83\ub4e4\uc774":81,"\uac83\ub4e4\uc774\ub2e4":76,"\uac83\ubcf4\ub2e4":79,"\uac83\uc5d0":[75,77,78],"\uac83\uc5d0\ub9cc":75,"\uac83\uc740":[76,77,78,79,80,82],"\uac83\uc744":79,"\uac83\uc774":[75,76,79,80],"\uac83\uc774\uae30":78,"\uac83\uc774\ub2e4":[75,76,77,78,79,80,81,82],"\uac83\uc778\ub2e4":80,"\uac83\ucc98\ub7fc":[77,80],"\uac8c\uc784":[75,76,77,78,81,82],"\uac8c\uc784\ub3c4":[75,82],"\uac8c\uc784\ub9cc\uc758":82,"\uac8c\uc784\uc5d0\uc11c\uc758":79,"\uac8c\uc784\uc5d0\uc120":77,"\uac8c\uc784\uc5d4\uc9c4":75,"\uac8c\uc784\uc5d4\uc9c4\uc774\ub098":75,"\uac8c\uc784\uc740":[75,78,81],"\uac8c\uc784\uc744":[75,78,82],"\uac8c\uc784\uc758":[75,78],"\uac8c\uc784\uc774":[75,77,78,80,81,82],"\uac8c\uc784\uc774\ub098":82,"\uac8c\uc784\uc774\ub2e4":81,"\uac8c\uc784\uc774\ub77c\uace0":78,"\uac8c\uc784\uc774\ubbc0\ub85c":76,"\uac8c\uc784\ud310":83,"\uac8c\uc784\ud310\uc740":81,"\uac8c\uc784\ud310\uc744":81,"\uacaa\uc5b4":82,"\uacb0\uacfc":[76,77,78],"\uacb0\uacfc\uac00":77,"\uacb0\uacfc\ub294":[78,81],"\uacb0\uacfc\ub97c":77,"\uacb0\uacfc\ubb3c\ub4e4\uc744":76,"\uacb0\uacfc\ubb3c\uc740":76,"\uacb0\ub860\uc774":82,"\uacb0\uc815\ud560":76,"\uacbd\uc6b0":[76,78,79,80],"\uacbd\uc6b0\ub97c":78,"\uacbd\uc6b0\uc758":82,"\uacbd\ud5d8\uc774":78,"\uacc4\uc0b0\ub9cc":76,"\uacc4\uc0b0\uc744":80,"\uacc4\uc0b0\ud558\uae30":77,"\uacc4\uc0b0\ud574\uc57c":81,"\uacc4\uc18d":[75,76,78],"\uace0":81,"\uace0\uae09":75,"\uace0\ub824\ub418\uc5c8\uc744":82,"\uace0\ub824\ub418\uc9c0":77,"\uace0\ub824\ud558\uc5ec":76,"\uace0\ub974\ub294":81,"\uace0\uc815":77,"\uace0\uc815\ub418\uc5b4":[76,79],"\uace0\uc815\ub41c":76,"\uace0\uc815\ub420":77,"\uace0\uc815\uc2dc\ucf1c":77,"\uace0\uc815\uc2dc\ud0a4\ub294":77,"\uace0\uc815\uc2dc\ud0a8\ub2e4":76,"\uace0\uc815\ud558\ub294":77,"\uacf5\uac04":76,"\uacf5\uac04\uc0c1\uc5d0\uc11c\uc758":75,"\uacf5\uac04\uc744":[76,80],"\uacf5\uc774\ub098":77,"\uacfc":[76,80],"\uad00\ub828":75,"\uad6c\uc131":76,"\uad6c\uc131\ub41c\ub2e4":75,"\uad6c\uc131\ud560":75,"\uad6c\uc2dd\uc774\uace0":75,"\uad6c\uc5ed\uc744":76,"\uad6c\uc5ed\uc758":76,"\uad6c\uccb4\uc801\uc778":[78,80],"\uad6c\ud604\ud55c":[81,82],"\uad6c\ud604\ud55c\ub2e4\uba74":81,"\uad6c\ud604\ud560":82,"\uaddc\uce59":[78,82],"\uaddc\uce59\uc740":81,"\uaddc\uce59\uc744":[81,82],"\uaddc\uce59\uc774":82,"\uadf8":[75,76,77,79,80,81],"\uadf8\uac83\uc740":79,"\uadf8\uac83\uc774":[78,82],"\uadf8\uac83\uc774\ub2e4":76,"\uadf8\ub2e4\uc9c0":76,"\uadf8\ub798\uc11c":[75,76,77],"\uadf8\ub798\ud53d":75,"\uadf8\ub798\ud53d\uc744":75,"\uadf8\ub7ec\ub098":[77,78,82],"\uadf8\ub7ec\uba74":[75,77,81],"\uadf8\ub7ec\ubbc0\ub85c":[76,77,80,82],"\uadf8\ub7f0\uac00":78,"\uadf8\ub807\ub2e4\uba74":[76,77],"\uadf8\ub807\uc9c0":80,"\uadf8\ub824\uc9c0\uace0":76,"\uadf8\ub824\uc9c0\ub294":76,"\uadf8\ub824\uc9c4\ub2e4":81,"\uadf8\ub9ac\uace0":[75,76,77],"\uadf8\ub9ac\uae30":75,"\uadf8\ub9ac\ub294":[76,79],"\uadf8\ub9b0\ub2e4":[79,80],"\uadf9\uc18c\uc218\ub9cc\uc744":82,"\uae30\ub2a5":77,"\uae30\ub2a5\uc744":[76,77],"\uae30\ub85d\ud574\uc57c":80,"\uae30\ubc18":76,"\uae30\ubc18\uc73c\ub85c":76,"\uae30\ubc18\ud558\uc600\uae30":75,"\uae30\uc874\uc758":82,"\uae38\uc774\ub97c":76,"\uae4c\uba39\uc5b4\uc120":76,"\uae5c\ube61\uac70\ub9ac\ub294":75,"\uaf64":76,"\ub049\uaca8":75,"\ub05d\ub09c":76,"\ub05d\uc774":82,"\ub098":81,"\ub098\uac8c":82,"\ub098\ub220\uc9c8":76,"\ub098\ub294":78,"\ub098\uba74":76,"\ub098\uc544\uc84c\ub2e4":79,"\ub098\uc911\uc5d0":[76,77,78],"\ub098\ud0c0\ub0b8\ub2e4":80,"\ub09c\ub2e4":82,"\ub09c\uc218":82,"\ub09c\uc218\uac00":82,"\ub09c\uc218\uae4c\uc9c0":82,"\ub0ab\ub2e4":75,"\ub0b4\ubd80":[76,78],"\ub0b4\ubd80\ub97c":80,"\ub0b4\ubd80\uc5d0\uc11c":80,"\ub0b4\ubd80\uc600\ub2e4\uba74":80,"\ub0b4\uc5d0\uc11c":[77,81,82],"\ub0b4\uc6a9":76,"\ub0b4\uc6a9\uacfc":76,"\ub0b4\uc6a9\uc740":80,"\ub108\ubb34":77,"\ub118\uac8c":82,"\ub123\ub294\ub2e4\uba74":81,"\ub123\uc73c\uba74":81,"\ub124\ubc88\uc9f8":79,"\ub192\ub2e4\ub294":75,"\ub192\uc774\uae30":76,"\ub204\ub974\ub294":77,"\ub204\ub974\uba74":78,"\ub208\uc0ac\ud0dc":82,"\ub208\uc0ac\ud0dc\ub97c":82,"\ub20c\ub7ec":79,"\ub20c\ub824\uc788\ub294":78,"\ub20c\ub838\ub2e4":78,"\ub20c\ub9ac\uc9c0":78,"\ub20c\ub9b0":78,"\ub294":76,"\ub2a5\ub825\uc774\ub2e4":82,"\ub2e4\ub8e8\uaca0\ub2e4":78,"\ub2e4\ub8e8\uae30":78,"\ub2e4\ub974\uac8c":78,"\ub2e4\ub974\ub2e4":77,"\ub2e4\ub974\uc9c0":79,"\ub2e4\ub978":[76,78,82],"\ub2e4\uc2dc":79,"\ub2e4\uc591\uc131":78,"\ub2e4\uc591\ud788":81,"\ub2e4\uc6e0\ub2e4":82,"\ub2e4\uc74c":[76,79,80,81],"\ub2e4\uc911":77,"\ub2e4\ud589\ud788":75,"\ub2e8":77,"\ub2e8\uacc4\ub85c":78,"\ub2e8\uacc4\ub97c":76,"\ub2e8\uacc4\uc5d0\uc11c\uc758":78,"\ub2e8\uc0c9":76,"\ub2e8\uc21c\ud558\uae30":81,"\ub2e8\uc21c\ud558\ub2e4":[79,80],"\ub2e8\uc21c\ud558\uc9c0\ub9cc":81,"\ub2e8\uc21c\ud788":[78,81],"\ub2e8\uc5b4\ub294":78,"\ub2e8\uc810\uc740":77,"\ub2e8\uc810\uc774":75,"\ub2ec\ub77c\uc9c0\ubbc0\ub85c":77,"\ub2ec\ub77c\uc9c4\ub2e4":81,"\ub2ec\ub77c\uc9c8":78,"\ub2f4\uc558\ub294\ub370":79,"\ub2f9\uc5f0\ud55c":76,"\ub300\ub2e8\ud788":[81,82],"\ub300\ub85c":81,"\ub300\ubcf4\uac8c":75,"\ub300\uc0c1\uc5d0":82,"\ub300\uccb4\ud558\ub294\uac00":76,"\ub300\ud55c":76,"\ub354":[75,78,79,82],"\ub370":76,"\ub370\uc5d0\ub9cc":80,"\ub370\uc774\ud130":[78,81],"\ub370\uc774\ud130\uac00":76,"\ub370\uc774\ud130\ub4e4\uc744":79,"\ub370\uc774\ud130\ub97c":79,"\ub3c4":[76,78],"\ub3c4\uc6c0":78,"\ub3c4\uc6c0\uc774":78,"\ub3c4\uc911":76,"\ub3c4\ud615":75,"\ub3c4\ud615\uc744":79,"\ub3d9\uae30\ubd80\uc5ec":78,"\ub3d9\uc2dc\uc5d0":75,"\ub3d9\uc77c\ud55c":[76,79,80],"\ub3d9\uc77c\ud574\uc57c":80,"\ub3d9\uc791\ud558\ub3c4\ub85d":78,"\ub3d9\uce58\uad00\uacc4\ub77c\ub294":75,"\ub418\uae30":78,"\ub418\ub3cc\uc544\uac00\uc57c":76,"\ub418\uc5b4\uc57c\ub9cc":77,"\ub418\uc5c8\ub294\uc9c0":78,"\ub418\uc9c0":79,"\ub41c":[78,80],"\ub41c\ub2e4":[75,76,77,78,79,80,81,82],"\ub41c\ub2e4\uba74":82,"\ub420":[75,77,79],"\ub450":[79,80,81,82],"\ub450\uaed8":79,"\ub450\uaed8\ub9cc":80,"\ub450\ub294":[79,80],"\ub450\ub294\ub370":76,"\ub450\uba74":77,"\ub450\ubc88\uc9f8":[78,79],"\ub450\uc5c8\ub2e4":76,"\ub458":75,"\ub458\uc9f8":[75,80],"\ub4a4\uc5d0":78,"\ub4b7\ubd80\ubd84\uc5d0":77,"\ub4e4\uba74":79,"\ub4e4\uc5b4\uc11c":76,"\ub4e4\uc744":80,"\ub4f1":[75,78],"\ub4f1\uc740":82,"\ub4f1\uc758":75,"\ub514\ub809\ud1a0\ub9ac\uc5d0":76,"\ub514\uc2a4\ud50c\ub808\uc774":75,"\ub514\uc790\uc778\ud560":79,"\ub51c\ub808\ub9c8\uac00":75,"\ub51c\ub808\ub9c8\ub97c":75,"\ub51c\ub808\uc774":77,"\ub530\ub77c":[77,81],"\ub530\uc62c":79,"\ub530\uc838\uc11c":79,"\ub54c":[76,77,79,81,82],"\ub54c\ub9c8\ub2e4":79,"\ub54c\ub9cc":76,"\ub54c\ubb38\uc5d0":[75,76,77,78,81],"\ub54c\ubb38\uc774\ub2e4":[76,77,78,80,81],"\ub54c\uc758":79,"\ub610\ub294":[75,79,82],"\ub610\ud55c":[77,81],"\ub611\uac19\uc740":78,"\ub73b\uc774\ub2e4":78,"\ub77c\uace0":[78,82],"\ub77c\ub294":[76,82],"\ub77c\uc774\ube0c\ub7ec\ub9ac\uc774\uae30":75,"\ub77c\uc774\ube0c\ub7ec\ub9ac\uc774\ub2e4":75,"\ub80c\ub354\ub9c1":79,"\ub85c\uc9c1\uc740":79,"\ub85c\uc9c1\uc744":[76,78],"\ub85c\uc9c1\uc774":77,"\ub8e8\ud2b82":77,"\ub97c":[76,77,78,80],"\ub9c8\ub77c":82,"\ub9c8\uc6b0\uc2a4":[75,78,80],"\ub9c8\uc6b0\uc2a4\uac00up":80,"\ub9c8\uc9c0\ub9c9\uc5d0":76,"\ub9c8\uc9c0\ub9c9\uc73c\ub85c":[78,79],"\ub9c8\ucc2c\uac00\uc9c0\uc774\ub2e4":82,"\ub9cc":75,"\ub9cc\ub4dc\ub294":[75,80,82],"\ub9cc\ub4e0":75,"\ub9cc\ub4e0\ub2e4\uace0":75,"\ub9cc\ub4e4":[75,79,82],"\ub9cc\ub4e4\uace0":81,"\ub9cc\ub4e4\uc5b4":[79,81],"\ub9cc\ub4e4\uc5b4\uc11c":82,"\ub9cc\ub4e4\uc5b4\uc57c":80,"\ub9cc\ub4e4\uc5b4\uc9c4":81,"\ub9cc\ub4e4\uc5b4\uc9c4\ub2e4\uba74":82,"\ub9cc\ub4e4\uc5c8\ub2e4":79,"\ub9cc\uc57d":[76,79,80,82],"\ub9cc\uc744":[76,79],"\ub9ce\ub2e4":81,"\ub9ce\uc73c\ubbc0\ub85c":77,"\ub9ce\uc740":81,"\ub9d0\uc774\ub2e4":76,"\ub9d0\ud558\ub294":78,"\ub9d0\ud55c":76,"\ub9d0\ud588\ub2e4":82,"\ub9d0\ud588\ub4ef":76,"\ub9de\ub294\uac00":78,"\ub9de\uc744":76,"\ub9e4\uac1c":79,"\ub9e4\uc6b0":[78,82],"\uba39\ud788\ub294":76,"\uba3c\uc800":[78,79],"\uba54\ubaa8\ub9ac":75,"\uba64\ubc84":76,"\uba85\ub839\uc5b4\uac00":78,"\uba87":77,"\uba87\uba87":[76,78],"\ubaa8\ub2c8\ud130":76,"\ubaa8\ub450":[75,76],"\ubaa8\ub4c8\ub4e4\uc744":76,"\ubaa8\ub4e0":[75,76,78,81,82],"\ubaa9\ub85d\uc740":78,"\ubaa9\ud45c\uac00":75,"\ubab8\uc758":78,"\ubb34\uc5b8\uac00\ub97c":[76,78],"\ubb34\uc5c7\uc744":77,"\ubb34\uc5c7\uc774\ub4e0\uc9c0":82,"\ubb34\uc5c7\uc778\uac00":[77,79,82],"\ubb34\uc5c7\uc778\uc9c0\ub294":79,"\ubb34\uc791\uc704\ub85c":81,"\ubb34\ud55c":76,"\ubb36\uc744":80,"\ubb38\uad6c\uc774\ub2e4":76,"\ubb38\uc790\uc5f4\uc740":76,"\ubb38\uc790\uc5f4\uc774\ub2e4":76,"\ubb38\uc7a5\ub4e4":76,"\ubb38\uc81c\uac00":[76,77],"\ubb38\uc81c\ub97c":81,"\ubb3c\ub860":[75,76,77,78,79],"\ubb54\uac00":80,"\ubbf8\uce58\uac8c":82,"\ubc0f":78,"\ubc14\uafb8\uace0":77,"\ubc14\uafb8\ub294":77,"\ubc14\uafb8\ub294\uac00":79,"\ubc14\uafb8\uba74":81,"\ubc14\uafbc":78,"\ubc14\uafc0":77,"\ubc14\uafd4":79,"\ubc14\ub00c\ub294\uac00":77,"\ubc14\ub00c\ub294\uc9c0\ub97c":77,"\ubc14\ub294":79,"\ubc14\ub85c":[77,82],"\ubc18\ub4dc\uc2dc":[77,78],"\ubc18\ubcf5\ubb38":76,"\ubc18\uc601":78,"\ubc18\ud544\uc218\uc801\uc73c\ub85c":76,"\ubc18\ud658":76,"\ubc18\ud658\ud55c\ub2e4":[76,81],"\ubc1c\uc0dd":76,"\ubc1c\uc0dd\ud558\uba74":76,"\ubc1c\uc0dd\ud55c":76,"\ubc1c\uc804\ub41c":75,"\ubc1c\ud718\ub41c":82,"\ubc29\ubc95":78,"\ubc29\ubc95\uc740":[78,79],"\ubc29\ubc95\uc744":[77,78],"\ubc29\ubc95\uc774\ub2e4":79,"\ubc29\uc2dd":75,"\ubc29\ud5a5\uc73c\ub85c":78,"\ubc29\ud5a5\ud0a4\ub97c":78,"\ubc30\uc5f4\uacfc":81,"\ubc30\uc5f4\uc5d0\uc11c":81,"\ubc30\uc5f4\uc740":81,"\ubc30\uc5f4\uc744":[76,81],"\ubc30\uc5f4\uc774":81,"\ubc30\uc5f4\ucc98\ub7fc":81,"\ubc30\uc6b0\uace0":[78,82],"\ubc30\uc6b0\ub294":[75,76],"\ubc30\uc6b4\ub2e4":78,"\ubc30\ud2c0\uc2ed":75,"\ubc84\ud2bc":81,"\ubc84\ud2bc\ub4e4":83,"\ubc84\ud2bc\ub4e4\uc740":80,"\ubc84\ud2bc\ub4e4\uc744":80,"\ubc84\ud2bc\uc744":[77,80,81],"\ubc84\ud2bc\uc758":80,"\ubc88":77,"\ubc94\uc704\uac00":80,"\ubc95\uc744":81,"\ubcc0\uacbd\ud558\uba74\uc11c":79,"\ubcc0\uc218":[76,79,80],"\ubcc0\uc218\uac00":[76,77,79,80],"\ubcc0\uc218\ub294":[76,79],"\ubcc0\uc218\ub3c4":80,"\ubcc0\uc218\ub4e4\uc744":80,"\ubcc0\uc218\ub4e4\uc774":76,"\ubcc0\uc218\ub85c":[79,80],"\ubcc0\uc218\ub97c":[76,77,79,80],"\ubcc0\uc218\uc640":78,"\ubcc0\uc218\uc758":79,"\ubcc0\uc218\uc774\uace0":79,"\ubcc0\uc218\uc774\ub2e4":79,"\ubcc0\uc704\uac00":77,"\ubcc0\uc704\ub294":77,"\ubcc0\uc704\ub9cc":77,"\ubcc0\ud55c\ub2e4\uba74":79,"\ubcc0\ud560":79,"\ubcf4\uace0":75,"\ubcf4\ub2e4":77,"\ubcf4\uba74":[77,80],"\ubcf4\uc544\ub77c":[78,79,82],"\ubcf4\uc774\ub294":80,"\ubcf4\uc774\uc9c4":81,"\ubcf4\uc778\ub2e4":77,"\ubcf4\uc778\ub2e4\ub294":[75,77],"\ubcf4\uc77c":77,"\ubcf4\uc790":[75,82],"\ubcf4\ud1b5":75,"\ubcf5\uc18c\uc218\uc88c\ud45c\ub97c":75,"\ubcf5\uc7a1\ub3c4\ub294":77,"\ubcf5\uc7a1\ub3c4\ub97c":77,"\ubcf5\uc7a1\ud558\ub2e4":76,"\ubcf5\uc7a1\ud55c":75,"\ubcf8\uaca9\uc801\uc73c\ub85c":79,"\ubcfc\ub9cc":75,"\ubd80":83,"\ubd80\ubd84\uc5d0\uc11c":78,"\ubd80\ubd84\uc73c\ub85c":76,"\ubd80\ubd84\uc758":81,"\ubd80\uc5ec\ud560":82,"\ubd84\uc11d\ud558\uc9c0":77,"\ubd88\uacfc\ud558\ub2e4":78,"\ubd88\uacfc\ud558\ubbc0\ub85c":77,"\ubd88\ub9b4":78,"\ubd88\uc5f0\uc18d\uc801":79,"\ube14\ub85d":81,"\ube14\ub85d\uc744":81,"\ube14\ub85d\uc758":81,"\ube44\uad50\ud558\uc5ec":78,"\ube44\ud45c\uc900":75,"\ube44\ud558\uba74":76,"\ube48\ub3c4\uc5d0":77,"\ube60\ub978":75,"\ube60\ub97c\uae4c":77,"\ube60\uc9c0\uba74":75,"\ube68\uac04":[76,79,81],"\ube68\uac04\ube14\ub85d":16,"\ube68\ub9ac":75,"\ubfcc\uc694\ubfcc\uc694":75,"\uc0ac\uae30\uac00":80,"\uc0ac\ub78c\ub4e4\uc774":82,"\uc0ac\ub78c\uc774":82,"\uc0ac\uc2e4":81,"\uc0ac\uc6a9\ub418\uc5c8\uae30":80,"\uc0ac\uc6a9\ub418\uc5c8\uc9c0\ub9cc":80,"\uc0ac\uc6a9\ub41c":79,"\uc0ac\uc6a9\uc790\uac00":[76,80],"\uc0ac\uc6a9\ud558\uae30":76,"\uc0ac\uc6a9\ud558\ub294":76,"\uc0ac\uc6a9\ud558\uc5ec":76,"\uc0ac\uc6a9\ud560":76,"\uc0ac\uc774\uc5d0\ub294":75,"\uc0ac\uc774\uc758":75,"\uc0ac\uc9c4":75,"\uc0b4\ud3b4\ubcf4\uc790":76,"\uc0bd\uc785\ud558\uba74":76,"\uc0c1\uc138\ud558\uac8c":79,"\uc0c1\uc218":80,"\uc0c1\uc218\ub4e4\uc744":76,"\uc0c1\ud0dc":78,"\uc0c1\ud0dc\ub97c":75,"\uc0c1\ud638\uc791\uc6a9\uc774":78,"\uc0c8\ub85c\uc6b4":[79,81,82],"\uc0c9":[75,76,79],"\uc0c9\uc0c1":[76,79],"\uc0c9\uc0c1\uacfc":76,"\uc0c9\uc0c1\uc740":[76,81],"\uc0c9\uc0c1\uc744":[76,81],"\uc0c9\uc0c1\uc758":81,"\uc0c9\uc774":76,"\uc0dd\uac01\uc77c":80,"\uc0dd\uac01\ud574":82,"\uc0dd\uac01\ud574\ubcf4\uba74":78,"\uc0dd\uac01\ud574\ubd10\ub77c":78,"\uc0dd\uacbc\ub2e4":78,"\uc0dd\uae38":76,"\uc0dd\uc131\ud558\uace0":76,"\uc11c\ub85c":76,"\uc120\uc5b8":76,"\uc120\uc5b8\ub418\uc5b4\uc57c":76,"\uc120\ud0dd\uc801\uc73c\ub85c":75,"\uc120\ud0dd\uc801\uc778":77,"\uc120\ud0dd\uc9c0\ub294":81,"\uc120\ud589\ub418\uc5b4\uc57c":79,"\uc124\uba85\uc774":76,"\uc124\uba85\uc774\uc5c8\ub2e4":76,"\uc124\uba85\ud558\ub294":79,"\uc124\uba85\ud560":81,"\uc124\uc815":75,"\uc131\ubd84":76,"\uc131\ubd84\uc774":76,"\uc138\uace0":81,"\uc138\ud305":78,"\uc148\uc774\ub2e4":76,"\uc18c\uac1c":83,"\uc18c\ub9ac":[75,78],"\uc18c\uc124":82,"\uc18c\uc2a4":[75,76,77,78],"\uc18c\uc2a4\ucf54\ub4dc":76,"\uc18c\uc2a4\ucf54\ub4dc\uac00":76,"\uc18c\uc2a4\ucf54\ub4dc\ub294":76,"\uc18c\uc2a4\ucf54\ub4dc\ub97c":[75,76],"\uc18c\uc2a4\ucf54\ub4dc\uc5d0":76,"\uc18c\uc2a4\ucf54\ub4dc\uc640":75,"\uc18c\uc2a4\ucf54\ub4dc\uc758":76,"\uc18c\uc2a4\ud30c\uc77c\uc5d0":75,"\uc18c\uc2a4\ud30c\uc77c\uc740":75,"\uc18d":76,"\uc18d\ub3c4\ub97c":77,"\uc18d\ub3c4\uc5d0":77,"\uc18d\ub3c4\uc774\ub77c\ub294":77,"\uc18d\uc5d0\ub294":77,"\uc190\uac00\ub77d":78,"\uc190\uc744":75,"\uc218":[75,76,77,78,79,80,81,82],"\uc218\uac00":82,"\uc218\ub294":[77,82],"\uc218\ub3c4":82,"\uc218\ub97c":81,"\uc218\ub9ce\uc740":75,"\uc218\uc815\ud558\ub294":76,"\uc218\uc815\ud55c\ub2e4\uba74":76,"\uc218\uc900":75,"\uc218\ud589\ub418\uc5b4\uc57c":76,"\uc218\ud589\ud55c\ub2e4":76,"\uc21c\ucc28\uc801\uc73c\ub85c":76,"\uc26c\uc6b4":79,"\uc27d\uac8c":[77,79],"\uc27d\ub2e4":[77,78,80],"\uc2a4\ud06c\ub9b0":76,"\uc2b5\ub4dd\ud560":82,"\uc2dc\uac01\uc801":81,"\uc2dc\uac01\ud654":[78,79],"\uc2dc\uac04":[77,78,81],"\uc2dc\uac04\ubcf4\ub2e4":82,"\uc2dc\uac04\uc21c\uc73c\ub85c":76,"\uc2dc\uac04\uc740":77,"\uc2dc\uac04\uc744":[77,82],"\uc2dc\uac04\uc774":[76,82],"\uc2dc\uac04\uc774\ub2e4":82,"\uc2dc\ub3c4\ud574":75,"\uc2dc\uc2a4\ud15c\uc744":78,"\uc2dc\uc2a4\ud15c\uc774":76,"\uc2dc\uc791\ub418\uae30":77,"\uc2dc\uc791\ub420":77,"\uc2dc\uc791\ud558\ub294":77,"\uc2dc\ud589":82,"\uc2dd\uc758":75,"\uc2e0\uacbd":80,"\uc2e4\uc81c\ub85c":76,"\uc2e4\ud589":[76,77,78,81],"\uc2e4\ud589\ub418\uac70\ub098":75,"\uc2e4\ud589\ub418\ub294":[75,77],"\uc2e4\ud589\ub418\uba74":76,"\uc2e4\ud589\ub418\uc57c":77,"\uc2e4\ud589\ub418\uc5b4\uc57c":76,"\uc2e4\ud589\ub418\uc9c0":76,"\uc2e4\ud589\ub41c\ub2e4":76,"\uc2e4\ud589\ub41c\ub2e4\ub294":75,"\uc2e4\ud589\ub428":75,"\uc2e4\ud589\ud558\ub294":75,"\uc2eb\ub2e4\uba74":80,"\uc2ec\ud654":78,"\uc2ec\ud654\ub41c":78,"\uc2f6\ub2e4\uba74":75,"\uc2f6\uc744":76,"\uc368\uc57c":80,"\uc4f0\uba74":76,"\uc4f8":75,"\uc544\ub2c8\ub2e4":78,"\uc544\ub2c8\ub77c":77,"\uc544\ub2c8\ubbc0\ub85c":77,"\uc544\ub2c8\uc9c0\ub9cc":78,"\uc544\ub2cc":[75,76,77,79,80,81],"\uc544\ub2cc\uc9c0\ub97c":78,"\uc544\ub798\ub97c":79,"\uc544\ub798\uc640":79,"\uc544\ub798\ucabd\uc774":76,"\uc544\ub9c8\ub3c4":78,"\uc544\ubb34":82,"\uc544\ubb34\ub798\ub3c4":75,"\uc544\uc2a4\ud0a4\uc544\ud2b8\ub97c":75,"\uc544\uc774\ub514\uc5b4\ub294":79,"\uc544\uc774\ub514\uc5b4\ub97c":79,"\uc544\uc774\ub514\uc5b4\uc640":79,"\uc544\uc774\ub514\uc5b4\ucc98\ub7fc":80,"\uc544\uc9c1":[79,80],"\uc544\uc9c1\ub3c4":[77,80],"\uc548\ub418\ub294":77,"\uc548\ub41c\ub2e4":76,"\uc54a\ub294":[76,77],"\uc54a\ub294\ub2e4":[77,78,79,81],"\uc54a\ub2e4":79,"\uc54a\ub2e4\uba74":80,"\uc54a\uc558\uc9c0\ub9cc":78,"\uc54a\uc73c\uba74":76,"\uc54a\uc744":[76,77],"\uc54c":[76,80,81],"\uc54c\uace0":[77,78],"\uc54c\uace0\ub9ac\uc998\uc73c\ub85c":75,"\uc54c\uace0\ub9ac\uc998\uc758":78,"\uc54c\uace0\ub9ac\uc998\uc774":78,"\uc54c\ub809\uc138\uc774":82,"\uc54c\uc544\ub0b4\uae30":80,"\uc54c\uc544\ub0bc":[76,77],"\uc54c\uc544\uc57c":78,"\uc54c\uc558\ub2e4":77,"\uc54c\uce74\ub178\uc774\ub4dc\uc758":77,"\uc55e\ubd80\ubd84\uc5d0":77,"\uc55e\uc11c":76,"\uc55e\uc11c\uc11c":76,"\uc55e\uc5d0":78,"\uc560\ub2c8\uba54\uc774\uc158":[75,77],"\uc57d\uac04":78,"\uc57d\uac04\uc758":76,"\uc5b4\ub5a4":[76,82],"\uc5b4\ub5a4\uac00":79,"\uc5b4\ub5a8\uae4c":[76,80],"\uc5b4\ub5bb\uac8c":[76,77,79,80,81],"\uc5b4\ub835\uc9c0":76,"\uc5b4\uca0c\ub4e0":78,"\uc5b4\ucc0c\ub410\ub4e0":76,"\uc5b8\uae09\ud558\uaca0\ub2e4":76,"\uc5b8\uae09\ud55c":81,"\uc5b8\uc5b4\uc758":76,"\uc5bc\ub9c8\ub098":77,"\uc5bc\ub9cc\ud07c\uc758":82,"\uc5c5\ub370\uc774\ud2b8":77,"\uc5c5\ub370\uc774\ud2b8\uac00":76,"\uc5c5\ub370\uc774\ud2b8\ub418\uac70\ub098":76,"\uc5c5\ub370\uc774\ud2b8\ub418\uac8c":77,"\uc5c5\ub370\uc774\ud2b8\ub418\uc5c8\ub294\uc9c0\ub97c":77,"\uc5c5\ub370\uc774\ud2b8\ub41c\ub2e4":78,"\uc5c5\ub370\uc774\ud2b8\ud558\ub294":[77,78,80],"\uc5c6\uace0":[78,80],"\uc5c6\uae30":[76,77,78],"\uc5c6\ub294":[75,76,82],"\uc5c6\ub2e4":[77,78,81],"\uc5c6\uc73c\ubbc0\ub85c":[77,80],"\uc5c6\uc774":[76,78],"\uc5d0":76,"\uc5d0\uc11c":82,"\uc5d0\uc120":76,"\uc5d0\ud544\ub85c\uadf8":83,"\uc5d4\uc9c4":75,"\uc5d4\uc9c4\uc5d0\ub3c4":75,"\uc5d4\uc9c4\uc740":75,"\uc5d4\uc9c4\uc744":75,"\uc5d4\uc9c4\uc758":75,"\uc5d4\ud130":75,"\uc5ec\uae30\uc11c":77,"\uc5ec\uae30\uc5d0":76,"\uc5ec\uae30\uc5d0\uc11c":82,"\uc5ec\ub7ec":75,"\uc5ec\ub7ec\uac00\uc9c0":76,"\uc5ec\uc804\ud788":79,"\uc5ec\uc9c0\uac00":81,"\uc5f0\uacb0\uc2dc\ud0a4\uba74\uc11c":82,"\uc5f0\uacb0\uc810\uc774":75,"\uc601\uc5ed":80,"\uc601\uc5ed\uacfc":80,"\uc601\uc5ed\uc744":80,"\uc601\uc5ed\uc774":80,"\uc601\ud5a5\uc744":82,"\uc601\ud654":82,"\uc608\ub97c":[76,79],"\uc608\uc2dc":75,"\uc608\uc2dc\uc774\ub2e4":82,"\uc608\uc678\uc801\uc73c\ub85c":76,"\uc608\uc81c\uc778":76,"\uc608\uce21\ub418\uae30":77,"\uc624\uac8c":76,"\uc624\uac8c\ub054":76,"\uc624\ub2f5\uc774\ub77c\uba74":81,"\uc624\ub2f5\uc77c":81,"\uc624\ub798":76,"\uc624\ub978\ucabd\uc774":76,"\uc624\ube0c\uc81d\ud2b8\uac04":78,"\uc624\ube0c\uc81d\ud2b8\uc758":77,"\uc624\uc9c1":[79,80],"\uc640":[76,77,78,80,82],"\uc640\uc57c":77,"\uc644\ubcbd\ud788":82,"\uc644\uc131\ub418\uc5c8\ub2e4":78,"\uc644\uc804\ud55c":80,"\uc644\uc804\ud788":78,"\uc65c":78,"\uc65c\ub098\ud558\uba74":76,"\uc65c\ub0d0\uba74":78,"\uc65c\ub0d0\ud558\uba74":[77,78],"\uc678\ubd80":75,"\uc678\uc758":76,"\uc694\uc18c":[78,81],"\uc694\uc18c\ub97c":76,"\uc694\uc57d\ud558\uc790\uba74":75,"\uc6a9":80,"\uc6a9\ub3c4\uac00":79,"\uc6a9\uc774\ub2e4":81,"\uc6b0":80,"\uc6b0\ub9ac\uac00":77,"\uc6b0\ub9ac\ub294":[77,78,81,82],"\uc6b0\ub9ac\uc758":82,"\uc6b0\uc120":[76,77,78,79,81],"\uc6c0\uc9c1\uc774\uac8c":77,"\uc6c0\uc9c1\uc774\ub294":77,"\uc6c0\uc9c1\uc778\ub2e4":[77,78],"\uc6c0\uc9c1\uc778\ub2e4\ub294":78,"\uc6c0\uc9c1\uc77c\uae4c":77,"\uc6d0\ub9ac\ub97c":76,"\uc704":79,"\uc704\uce58":[76,79],"\uc704\uce58\uac00":77,"\uc704\uce58\ub97c":76,"\uc704\uce58\uc5d0\uc11c\uc758":80,"\uc704\ud55c":[75,76,80,81],"\uc704\ud574":[76,78,82],"\uc704\ud574\uc11c\ub294":78,"\uc704\ud574\uc120":76,"\uc708\ub3c4\uc6b0":76,"\uc708\ub3c4\uc6b0\uc758":77,"\uc720\ub2c8\ud2f0":75,"\uc720\uc6a9\ud55c":76,"\uc73c\ub85c":[75,76],"\uc740":77,"\uc744":[77,78,81],"\uc74c\uc545":82,"\uc758":75,"\uc758\ubbf8\ub97c":80,"\uc758\ubbf8\ud558\uac8c":[77,80],"\uc758\ubbf8\ud558\uace0":78,"\uc758\ubbf8\ud558\uc9c0\ub294":78,"\uc758\ubbf8\ud55c\ub2e4":[76,77,78],"\uc774":[75,76,77,78,79,80,81,82],"\uc774\uac83\ub4e4\uc740":79,"\uc774\uac83\uc740":[76,77,81],"\uc774\uac83\uc774":[75,76,82],"\uc774\ub294":[77,78],"\uc774\ub2e4":76,"\uc774\ub3d9":83,"\uc774\ub780":75,"\uc774\ub7f0":[75,78],"\uc774\ub807\uac8c":75,"\uc774\ub8e8\uc5b4\uc9c4\ub2e4":[76,79],"\uc774\ub8e8\uc5b4\uc9d0\uc5d0":78,"\uc774\ub97c":77,"\uc774\ub984":78,"\uc774\ub984\uc73c\ub85c\ub294":78,"\uc774\ub984\uc744":78,"\uc774\ub984\uc758":76,"\uc774\ubbf8":82,"\uc774\ubbf8\uc9c0":[77,78,81],"\uc774\ubca4\ud2b8\uac00":[76,78],"\uc774\ubca4\ud2b8\ub4e4\uc740":76,"\uc774\ubca4\ud2b8\ub4e4\uc744":76,"\uc774\ubca4\ud2b8\ub4e4\uc758":76,"\uc774\ubca4\ud2b8\ub97c":[76,78,80],"\uc774\ubca4\ud2b8\uc801":75,"\uc774\ubcc4\uc744":76,"\uc774\uc0c1":[75,77],"\uc774\uc0c1\uc758":78,"\uc774\uc5d0":76,"\uc774\uc6a9\ud558\uba74":77,"\uc774\uc6a9\ud55c":75,"\uc774\uc6a9\ud560":78,"\uc774\uc720\ub294":80,"\uc774\uc720\uc774\ub2e4":[75,78,82],"\uc774\uc804":[77,78],"\uc774\uc804\uacfc":79,"\uc774\uc804\ubd80\ud130":78,"\uc774\uc804\uc5d0\ub294":78,"\uc774\uc804\uc758":[76,78,80],"\uc774\uc81c":[77,78,80,81,82],"\uc774\uc81c\ub294":79,"\uc774\uc820":77,"\uc774\ud574\ud558\ub294":76,"\uc774\ud574\ud560":[78,79],"\uc774\ud574\ud588\ub2e4\uba74":76,"\uc774\ud6c4":76,"\uc774\ud6c4\uc5d0":76,"\uc778\uc790\ub97c":78,"\uc778\ud130\ud398\uc774\uc2a4":78,"\uc778\ud130\ud398\uc774\uc2a4\ub97c":81,"\uc77c\ubc18\uc801\uc73c\ub85c":76,"\uc77c\ubd80":[76,77,78],"\uc77c\ubd80\ubd84":78,"\uc77c\ubd80\uc774\uae30":75,"\uc77c\uc5b4\ub0ac\ub294\uc9c0":80,"\uc77c\uc73c\ud0a4\ub294":82,"\uc77c\uc885\uc758":77,"\uc77c\uce58\ud558\uc9c0":76,"\uc784\ub9c8\ub204\uc5d8":82,"\uc784\uc740":77,"\uc785\ub825":[75,76,77,80],"\uc785\ub825\ubcf4\ub2e4":82,"\uc785\ub825\uc2dc\ud0a4\ub294":82,"\uc785\ub825\uc740":[75,80],"\uc785\ub825\uc744":[78,80],"\uc785\ub825\uc774":[77,78],"\uc785\ub825\uc774\ub098":77,"\uc785\ub825\uc774\ub780":80,"\uc785\ub825\ud558\ub294":78,"\uc785\ubb38\uc7a5\ubcbd\uc774":75,"\uc788\uac8c":[75,76],"\uc788\uace0":79,"\uc788\uae30":78,"\uc788\ub290\ub0d0":78,"\uc788\ub294":[75,76,80,81,82],"\uc788\ub294\ub370":79,"\uc788\ub2e4":[75,76,77,78,79,80,81,82],"\uc788\ub2e4\uace0":76,"\uc788\ub3c4\ub85d":79,"\uc788\uc5b4\uc57c":77,"\uc788\uc73c\uba74":75,"\uc788\uc744\uae4c":[75,76],"\uc788\uc74c":80,"\uc788\uc74c\uc744":[77,78,80],"\uc790\ub3d9\uc801\uc73c\ub85c":[76,77],"\uc790\uc8fc":77,"\uc791\ub3d9":76,"\uc791\ub3d9\ud558\uc9c0":77,"\uc791\uc131\ub418\uc5b4\uc57c":76,"\uc791\uc131\uc740":81,"\uc791\uc131\ud558\ub294":75,"\uc791\uc131\ud55c":75,"\uc791\uc5c5\uc774":76,"\uc791\uc740":[79,80],"\uc7a5":77,"\uc7a5\uc774":77,"\uc7a5\uc810\ub3c4":75,"\uc7a5\uc810\uc740":75,"\uc7a5\uc810\uc744":75,"\uc800\uae09":75,"\uc800\uc7a5\ud574":76,"\uc801\uc6a9\ub418\uc5b4":80,"\uc801\uc808\ud55c":[76,77,78,80],"\uc801\uc808\ud788":76,"\uc804\uc138\uacc4":82,"\uc804\uc5ed":76,"\uc804\uccb4":[76,81],"\uc804\uccb4\ub97c":79,"\uc804\ud600":78,"\uc808\ucc28\uc801\uc73c\ub85c":75,"\uc808\ucc28\uc801\uc774":75,"\uc810\uc218\ub3c4":78,"\uc810\uc740":80,"\uc811\uadfc\uc131\uc774":75,"\uc811\uadfc\ud560":75,"\uc815\ub2f5\uc774\uac70\ub098":81,"\uc815\ub2f5\uc774\ub77c\uba74":81,"\uc815\ub82c\ub41c\ub2e4":76,"\uc815\ub9ac\ub97c":77,"\uc815\ubcf4\ub4e4\uc740":76,"\uc815\ubcf4\ub97c":76,"\uc815\uc0ac\uac01\ud615":80,"\uc815\uc0ac\uac01\ud615\uc744":80,"\uc815\uc218":[79,81],"\uc815\uc2e0\uc5c6\uc774":77,"\uc815\uc758":78,"\uc815\uc911\uc559\uc5d0":76,"\uc815\uc911\uc559\uc73c\ub85c":76,"\uc815\uc911\uc559\uc740":76,"\uc815\uc911\uc559\uc744":76,"\uc815\uc9c0\ub41c":77,"\uc815\ud558\uace0":76,"\uc815\ud558\ub294":79,"\uc815\ud55c\ub2e4":76,"\uc815\ud560":[76,77],"\uc815\ud574\uc57c":76,"\uc815\ud574\uc838\uc57c":76,"\uc815\ud655\ud788\ub294":76,"\uc81c\uacf5\ud558\uae30":75,"\uc81c\uc57d\uc870\uac74":78,"\uc81c\uc678\ud654\uba74":75,"\uc81c\uc791":75,"\uc81c\ud55c\uc744":81,"\uc870\uac74\ubb38\uc774":76,"\uc870\uac74\uc774":76,"\uc870\uc808\ud558\uac8c":79,"\uc870\uc885":83,"\uc874\uc7ac\ud558\uace0":80,"\uc874\uc7ac\ud558\uae30":77,"\uc874\uc7ac\ud568\uc744":80,"\uc885\ub8cc":77,"\uc885\ub8cc\ub418\uac8c":76,"\uc885\ub8cc\ub418\uace0":78,"\uc885\ub8cc\ub418\uc5b4\uc57c":76,"\uc885\ub8cc\ub41c":76,"\uc885\ub8cc\ud558\uace0":76,"\uc885\ub8cc\ud558\ub294":77,"\uc885\ub958\uc758":76,"\uc88b\ub2e4\ub294":75,"\uc88b\uc740":[75,80],"\uc88b\uc744":79,"\uc88c\ud45c":76,"\uc88c\ud45c\ub97c":[78,79],"\uc88c\ud45c\uc5d0":77,"\uc8fc\ub294":75,"\uc8fc\ub85c":76,"\uc8fc\ubaa9\ud574\ub77c":78,"\uc8fc\uc5b4\uc9c4":76,"\uc904\ub4e4\uc740":78,"\uc911":[75,77],"\uc911\uc694\ud55c":82,"\uc990\uae38":78,"\uc99d\uac00\uc2dc\ud0a4\uac70\ub098":80,"\uc99d\uac00\ud558\uace0":81,"\uc9c0\uae08\uae4c\uc9c0":78,"\uc9c0\uae08\uc740":78,"\uc9c0\ub294":80,"\uc9c0\uc2dd\ub9cc\uc73c\ub85c":82,"\uc9c0\uc2dd\ubcf4\ub2e4":82,"\uc9c0\uc2dd\uc5d0":82,"\uc9c0\uc2dd\uc744":82,"\uc9c0\uc5d0":81,"\uc9c0\uc6b0\ub294":75,"\uc9c0\uc810\uc744":80,"\uc9c1\uad00\uc801\uc73c\ub85c":78,"\uc9c1\uad00\uc801\uc778":78,"\uc9c1\uc0ac\uac01\ud615":76,"\uc9c1\uc0ac\uac01\ud615\ub4e4\uc5d0":79,"\uc9c1\uc0ac\uac01\ud615\ub4e4\uc744":79,"\uc9c1\uc0ac\uac01\ud615\uc744":79,"\uc9c1\uc811":79,"\uc9c4\uc9dc":78,"\uc9c4\ud589\ub420":76,"\uc9c8":81,"\uc9c8\ub9b0\ub2e4\uba74":75,"\uc9d1\uc911\ud558\uba74":75,"\uc9dc\uc99d\ub0a0":81,"\ucc28\uc774\uc810\uc774":78,"\ucc28\uc774\uc810\uc774\ub2e4":78,"\ucc29\uc624\ub97c":82,"\ucc38\uace0":[76,77,78,79,80,81],"\ucc3d\uc758\uc801\uc778":82,"\ucc3e\uc544\ub0b4\uba74":77,"\ucc3e\uc744":79,"\ucc44\ub85c":78,"\ucc44\uc6b0\ub294":76,"\ucc98\ub9ac":[75,76,78],"\ucc98\ub9ac\uac00":[76,77],"\ucc98\ub9ac\ub294":75,"\ucc98\ub9ac\ub97c":79,"\ucc98\ub9ac\ub9cc\uc774":80,"\ucc98\ub9ac\uc758":76,"\ucc98\ub9ac\ud558\uace0":76,"\ucc98\ub9ac\ud558\ub294":80,"\ucc98\ub9ac\ud558\ub294\uc9c0\ub294":77,"\ucc98\ub9ac\ud558\ub824\uba74":81,"\ucc98\ub9ac\ud560":76,"\ucc9c\uc7ac\uc131\uc774\ub780":82,"\uccab\ubc88\uc9f8":79,"\uccab\uc9f8":[75,80],"\uccab\uc9f8\ub294":78,"\uccab\uc9f8\ub85c":76,"\uccb4\ud06c\ud558\ub294":76,"\ucd08\uae30\ud654\ub418\uac70\ub098":76,"\ucd08\uae30\ud654\ub41c\ub2e4":76,"\ucd08\uae30\ud654\ub428\uc744":77,"\ucd08\ub85d":76,"\ucd1d":79,"\ucd5c\ub300":79,"\ucd5c\ub300\uac12\uc774":79,"\ucd5c\ub300\ud55c":75,"\ucd5c\uc18c":76,"\ucd94\uac00":77,"\ucd94\uac00\ub418\uba74":81,"\ucd94\uac00\ub418\uc5c8\uace0":77,"\ucd94\uac00\ub418\uc5c8\ub2e4":[77,80],"\ucd94\uac00\ub41c":76,"\ucd94\uac00\ub41c\ub2e4":78,"\ucd94\uac00\uc801\uc73c\ub85c":78,"\ucd94\uac00\uc801\uc778":[76,77,78,79],"\ucd94\uac00\ud558\uac70\ub098":76,"\ucd94\uac00\ud558\ub294":[76,78],"\ucd94\uac00\ud558\ub824":81,"\ucd94\uac00\ud574\ubcf4\uc790":78,"\ucd94\uac00\ud574\uc57c":77,"\ucd9c\ub825":[75,78,79,81,83],"\ucd9c\ub825\ub418\uac8c":76,"\ucd9c\ub825\ub418\ub294":76,"\ucd9c\ub825\ub420":79,"\ucd9c\ub825\uc6a9\uc774\ub2e4":80,"\ucd9c\ub825\uc73c\ub85c":75,"\ucd9c\ub825\uc740":[75,78],"\ucd9c\ub825\uc744":[76,77,80],"\ucd9c\ub825\uc758":78,"\ucd9c\ub825\uc774":82,"\ucd9c\ub825\ud558\uae30":76,"\ucd9c\ub825\ud558\ub294":[76,78,79,81],"\ucd9c\ub825\ud55c\ub2e4":81,"\ucd9c\ub825\ud574\uc57c":81,"\ucda9\ub3cc":75,"\ucda9\ubd84\ud788":79,"\uce58\uace4":76,"\uce5c\uc219\ud55c":76,"\uce60\ud558\uae30":75,"\uce78\ud2b8\ub294":82,"\uce94\ubc84\uc2a4":[76,79],"\uce94\ubc84\uc2a4\ub97c":76,"\uce94\ubc84\uc2a4\uc5d0":76,"\uce94\ubc84\uc2a4\uc758":76,"\ucea1\uc158\uc5d0":76,"\ucee4\uc9c0\uac8c":82,"\ucee8\ud150\uce20":78,"\ucef4\ud4e8\ud130\ub294":82,"\ucef4\ud4e8\ud130\ub9c8\ub2e4":77,"\ucef4\ud4e8\ud130\uc5d0\uac8c":82,"\ucf54\ub4dc":[76,77,78,79,80,81],"\ucf54\ub4dc\uac00":76,"\ucf54\ub4dc\ub97c":75,"\ucf54\ub4dc\uc640":76,"\ucf54\ub529\ud558\uac8c":75,"\ucf54\ub529\ud574":75,"\ucf58\uc194":75,"\ucf58\uc194\uc5d0\uc11c":75,"\ud06c\uac8c":[79,81],"\ud06c\uace0":76,"\ud06c\uae30":76,"\ud06c\uae30\uac00":76,"\ud06c\uae30\ub97c":[76,81],"\ud06c\uae30\uc640":76,"\ud06c\ub2e4\ub294":82,"\ud06c\uba74":77,"\ud070":[75,78,79,80],"\ud074\uae4c":82,"\ud074\ub9ad":80,"\ud074\ub9ad\uc774":80,"\ud074\ub9ad\ud588\ub2e4":80,"\ud07c\uc744":76,"\ud0a4":78,"\ud0a4\ub294":78,"\ud0a4\ub4e4\ub3c4":78,"\ud0a4\ub97c":78,"\ud0a4\ubcf4\ub4dc":[75,78,79],"\ud0a4\ubcf4\ub4dc\uac00down\ub41c":80,"\ud0a4\ubcf4\ub4dc\uc5d0":78,"\ud0a4\uc758":78,"\ud0c4\ucc3d\uc5d0\uc11c":79,"\ud14c\ub450\ub9ac\ub97c":[79,81],"\ud14c\ud2b8\ub9ac\uc2a4\ub97c":82,"\ud14d\uc2a4\ud2b8":[76,83],"\ud14d\uc2a4\ud2b8\uac00":[76,79],"\ud14d\uc2a4\ud2b8\ub294":76,"\ud14d\uc2a4\ud2b8\ub97c":[76,77,79],"\ud14d\uc2a4\ud2b8\uc758":[76,77],"\ud14d\uc2a4\ud2b8\uc774\ub2e4":79,"\ud1b5\ud574":80,"\ud22c\uc790\ud588\uc744\uae4c":82,"\ud234\uc774":75,"\ud29c\ud1a0\ub9ac\uc5bc":[16,81],"\ud29c\ud1a0\ub9ac\uc5bc\uc740":82,"\ud2b8\ub9ac\uac70":78,"\ud2b8\ub9ac\uac70\ub418\uba74":76,"\ud2b9\uc131":[76,81],"\ud2b9\uc131\uc774":82,"\ud2b9\uc131\uc774\ub2e4":82,"\ud2b9\uc774\ud55c":80,"\ud2b9\uc815":[76,77,80],"\ud2b9\uc815\ud55c":80,"\ud30c\uc774\uac8c\uc784":[76,81],"\ud30c\uc774\uac8c\uc784\uc740":[75,76],"\ud30c\uc774\uac8c\uc784\uc744":75,"\ud30c\uc774\uac8c\uc784\uc758":[75,76,77,82],"\ud30c\uc774\uac8c\uc784\uc774":[75,76],"\ud30c\uc774\uc36c\uc5d0":75,"\ud30c\uc774\uc36c\uc758":[75,76],"\ud30c\uc77c":75,"\ud30c\uc77c\ub85c":81,"\ud30c\uc77c\uc744":[75,76],"\ud30c\uc77c\uc774\ub098":75,"\ud30c\uc9c0\ud2b8\ub178\ud504\uac00":82,"\ud310\ub2e8\ud558\ub294":78,"\ud310\uc815":80,"\ud3ec\ud568":82,"\ud3ed\ub113\uc740":82,"\ud3f0\ud2b8":76,"\ud3f0\ud2b8\ub97c":76,"\ud3f0\ud2b8\uc640":76,"\ud479":75,"\ud48d\uc131\ud558\uac8c":78,"\ud504\ub85c\uadf8\ub798\uba38\uac00":75,"\ud504\ub85c\uadf8\ub798\uba38\ub294":75,"\ud504\ub85c\uadf8\ub798\ubc0d":76,"\ud504\ub85c\uadf8\ub798\ubc0d\uacfc":82,"\ud504\ub85c\uadf8\ub798\ubc0d\uc740":82,"\ud504\ub85c\uadf8\ub798\ubc0d\uc758":82,"\ud504\ub85c\uadf8\ub7a8":[76,77],"\ud504\ub85c\uadf8\ub7a8\uacfc":75,"\ud504\ub85c\uadf8\ub7a8\uc5d0":81,"\ud504\ub85c\uadf8\ub7a8\uc5d0\uc120":78,"\ud504\ub85c\uadf8\ub7a8\uc740":[81,82],"\ud504\ub85c\uadf8\ub7a8\uc744":[76,77,79,82],"\ud504\ub85c\uadf8\ub7a8\uc758":[75,76,78],"\ud504\ub85c\uadf8\ub7a8\uc774":79,"\ud504\ub85c\uc81d\ud2b8":77,"\ud504\ub85c\uc81d\ud2b8\uac00":[76,78],"\ud504\ub85c\uc81d\ud2b8\ub294":[76,77,78],"\ud504\ub85c\uc81d\ud2b8\ub85c":76,"\ud504\ub85c\uc81d\ud2b8\uc5d0\uc11c":76,"\ud504\ub85c\uc81d\ud2b8\uc640":78,"\ud504\ub85c\uc81d\ud2b8\uc740":75,"\ud504\ub85c\uc81d\ud2b8\uc758":[76,77,78],"\ud504\ub85c\uc81d\ud2b8\uc774\uba70":76,"\ud504\ub864\ub85c\uadf8":83,"\ud504\ub864\ub85c\uadf8\uc5d0\uc11c":81,"\ud504\ub9b0\ud2b8":80,"\ud50c\ub808\uc774":[78,82],"\ud53c\ud0c0\uace0\ub77c\uc2a4":77,"\ud544\uc218\uc870\uac74\uc774":78,"\ud544\uc218\uc870\uac74\uc774\uae30":78,"\ud544\uc694":[75,76,81],"\ud544\uc694\ub85c":76,"\ud544\uc694\ud558\uac8c":80,"\ud544\uc694\ud558\ub2e4":[76,78],"\ud544\uc694\ud560":77,"\ud558\uaca0\ub2e4":79,"\ud558\uace0":81,"\ud558\uae30":[76,78],"\ud558\uae30\ub9cc":79,"\ud558\ub098":75,"\ud558\ub098\ub85c":80,"\ud558\ub098\ub9cc":81,"\ud558\ub098\uc758":[75,76,77,79,82],"\ud558\ub098\uc774\ub2e4":77,"\ud558\ub294":[76,77,80],"\ud558\ub294\ub370":80,"\ud558\ub294\uc9c0":76,"\ud558\ub2e4":75,"\ud558\uba74":[76,77,79],"\ud558\uc580":79,"\ud558\uc580\uc0c9":76,"\ud558\uc600\ub2e4":79,"\ud558\uc9c0\ub9cc":[75,76,77,79,80,82],"\ud55c":[77,80,82],"\ud55c\uad6d\uc5b4":16,"\ud55c\ub2e4":[76,77,78,79,80,81],"\ud55c\ubc88\ub9cc":76,"\ud55c\ubc88\ucbe4\uc740":75,"\ud560":[76,77,79,82],"\ud560\uae4c":79,"\ud560\ub2f9\ub41c":76,"\ud568\uc218":[76,77],"\ud568\uc218\uac00":[76,77],"\ud568\uc218\ub294":[76,77,80,81],"\ud568\uc218\ub4e4\uacfc":75,"\ud568\uc218\ub4e4\uc740":[75,76],"\ud568\uc218\ub4e4\uc744":[75,76],"\ud568\uc218\ub4e4\uc774":75,"\ud568\uc218\ub85c":75,"\ud568\uc218\ub97c":[76,79],"\ud568\uc218\ubcf4\ub2e4":77,"\ud568\uc218\uc5d0\uc120":79,"\ud568\uc218\uc640":[76,77],"\ud568\uc218\uc758":76,"\ud568\uc218\uc774\uae30":76,"\ud568\uc218\uc774\ub2e4":77,"\ud568\uc218\ud654":78,"\ud568\uc218\ud654\ub97c":79,"\ud56d\uc0c1":[75,76,78,80],"\ud574":75,"\ud574\uacb0\ud560":75,"\ud574\ub2f9":78,"\ud574\ub2f9\ub418\ub294":77,"\ud574\uc11c":81,"\ud574\uc57c":[76,79],"\ud5f7\uac08\ub9ac\uba74":76,"\ud604\uc7ac":79,"\ud615\uc2dd\uc5d0":76,"\ud615\uc2dd\uc744":76,"\ud615\uc2dd\uc774":76,"\ud638\ucd9c\ub418\ub294\ub370":76,"\ud638\ucd9c\ub418\uba74":76,"\ud638\ucd9c\ub418\uc5b4\uc57c":76,"\ud638\ucd9c\ub41c\ub2e4":76,"\ud638\ud658\uc131":75,"\ud654\ub824\ud55c":76,"\ud654\uba74":[76,79],"\ud654\uba74\uacfc":76,"\ud654\uba74\ubcf4\ub2e4\ub294":77,"\ud654\uba74\ubcf4\ud638\uae30\ucc98\ub7fc":77,"\ud654\uba74\uc744":[75,77],"\ud654\uba74\uc758":76,"\ud655\uc2e4\ud558\ub2e4":77,"\ud655\uc778\ud558\ub294":[75,79],"\ud655\uc778\ud558\ub77c":80,"\ud655\uc778\ud558\uba74":[79,80],"\ud655\uc778\ud560":[77,78,79],"\ud655\uc778\ud574\uc57c":78,"\ud655\uc815\ub41c\ub2e4\uba74":76,"\ud658\uacbd":75,"\ud658\uacbd\uacfc":75,"\ud658\uacbd\uc5d0\uc11c":75,"\ud658\uacbd\uc5d0\uc11c\uc758":75,"\ud658\uacbd\uc6a9":75,"\ud658\uacbd\uc740":75,"\ud65c\ub3d9\uc774\ub2e4":82,"\ud65c\uc131\ud654\ub418\uba74":80,"\ud65c\uc6a9\ud558\uace0":82,"\ud65c\uc6a9\ud55c":75,"\ud65c\uc6a9\ud574":75,"\ud69f\uc218\ub97c":77,"\ud6a8\uacfc\uac00":[80,82],"\ud6a8\uacfc\ub97c":81,"\ud6a8\uacfc\uc74c\uc744":81,"\ud6c4":[75,78],"\ud6e8\uc52c":79,"\ud765\ubbf8\ub85c\uc6b4":82,"always\ubb38":[76,77],"always\ubb38\uacfc":79,"always\ubb38\uc5d0":[76,77],"always\ubb38\uc5d0\uc11c":76,"always\ubb38\uc758":77,"always\ubb38\uc774":77,"b\u00e9zier":30,"b\uac12":76,"blit\uc774":76,"blit\ud568\uc218\ub294":76,"boolean":[25,28,32,33,39,56,64],"break":[18,30,33,46,54,62,88],"byte":[10,15,17,18,20,22,23,28,29,31,37,38,42,43,44,46,51],"c\ub85c":75,"case":[16,18,20,23,24,28,29,31,33,37,38,40,43,44,51,57,58,64,68,70,72,73,74,84,85,87,88],"catch":[44,64,89],"center\ub77c\ub294":76,"char":[1,7,10,28,29,51],"class":[0,16,17,19,20,26,29,31,32,35,37,38,45,51,57,61,62,66,84,86,89],"collidepoint\ub97c":80,"const":[1,7,10,70],"cui\uac00":75,"cui\uace0":75,"cui\ud658\uacbd\uc5d0\uc11c\ub9cc":76,"default":[1,15,18,20,22,23,24,25,26,28,29,31,33,35,37,38,40,43,44,45,48,50,51,53,54,56,58,59,63],"do":[9,16,18,19,20,22,23,24,25,26,27,29,32,35,41,42,44,45,50,51,56,57,58,59,60,61,63,64,65,67,68,69,74,85,86,87,88,89],"drawbuttons\uc5d0":80,"drawhp\ub77c\ub294":79,"else\ubb38\uc740":77,"event\ubb38":[76,78],"event\ubb38\uc5d0":80,"event\ubb38\uc5d0\uc11c":79,"event\ubb38\uc744":79,"event\ubb38\uc774":78,"export":[0,11,20,38,42,43,51],"fill\ud568\uc218\ub098":76,"final":[22,26,28,29,42,44,51,58,61,62,71,84,85,86,89],"float":[1,17,19,20,24,29,30,32,35,36,38,40,45,48,50,54,56,65],"fps\uac00":77,"fps\uac12\uc774":77,"fps\ub294":77,"fps\ub300\ub85c":77,"function":[0,1,8,9,10,13,16,18,19,20,22,23,24,25,26,27,28,29,30,31,32,33,35,37,38,39,40,41,43,44,45,46,47,48,49,50,51,52,53,54,56,57,58,60,61,63,64,66,67,68,69,70,72,73,84,85,87,88,89],"g\uac12":76,"gui\uac00":80,"gui\ub97c":76,"gui\uc5d0\uc11c\uc758":80,"gui\uc774\ubbc0\ub85c":76,"gui\uc774\uc9c0\ub9cc":81,"gui\uc784\uc744":76,"gui\ud658\uacbd\uc5d0\uc11c":76,"header\uc5d0\uc120":76,"header\uc758":78,"hp\ub294":[79,81],"hp\ub97c":[79,80],"hp\ubc14":83,"hp\uc744":79,"hp\uc758":79,"import":[1,11,16,18,22,24,25,26,27,28,29,30,32,34,36,38,39,44,49,52,53,59,61,62,63,64,66,67,68,69,70,71,72,73,75,76,77,78,79,80,81,84,85,86,89],"import\ud558\ub294":76,"in\ubb38\uc744":76,"initial\ubb38":76,"initial\ubb38\uc5d0":76,"initial\ubb38\uc758":77,"input\ud568\uc218\ub97c":76,"input\ud568\uc218\uc640\ub294":76,"int":[1,2,3,4,5,6,7,8,9,10,12,13,17,18,20,23,24,25,28,29,30,32,33,35,36,37,41,42,44,45,47,48,50,51,55,56,71,72,73,79,80,81],"it\uc744":81,"k_\uc2dc\ub9ac\uc988\uc774\ub2e4":78,"kewdown\uc740":78,"key\ub294":78,"keydown\uac00":80,"keyup\uc774\ub77c\ub294":78,"l_f4\ub4f1\uc774":78,"locals\ub85c\ubd80\ud130":78,"long":[7,25,27,29,35,38,40,44,50,53,63,64,84,88],"main\ud568\uc218\ub97c":79,"main\ud568\uc218\uc5d0":79,"mousebuttonup\uc774":80,"mytext\uac1d\uccb4\uc758":76,"mytext\ub77c\ub294":76,"mytextarea\ub294":76,"mytextarea\ub77c\ub294":76,"mytextfont\uac1d\uccb4\uc758":76,"mytextfont\ub77c\ub294":76,"name\uc5d0\uc11c":78,"new":[2,3,4,5,6,7,8,9,12,13,14,17,18,20,21,22,23,25,26,28,29,30,31,32,33,35,36,37,38,39,40,42,43,44,45,46,47,48,49,50,51,52,54,55,56,58,59,61,62,63,64,65,69,71,72,73,74,84,85,86,87,89],"null":[1,2,3,4,5,6,7,8,9,10,12,15,28],"play\ub77c\ub294":78,"play\ud55c\ub2e4":78,"pos\ub294":80,"print\ud568\uc218\ub098":76,"public":[26,86,89],"quit\uac19\uc740":76,"quit\ub77c\ub294":76,"r\uac12":76,"return":[1,2,3,4,5,6,7,8,9,10,12,13,14,15,17,18,19,20,22,23,24,25,27,28,29,30,31,32,33,35,36,37,38,39,40,41,42,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,62,63,64,65,66,68,71,72,73,79,80,81,84,85,86,87,88,89],"short":[25,63,65,84],"statement\uc5d0":77,"statement\uc5d0\uc11c":77,"static":[47,48,50,69],"super":[26,35,48,64],"switch":[22,23,29,44,50,59,89],"sys\ub294":76,"throw":[40,62,64],"tick\ud568\uc218\ub294":77,"true":[2,3,4,5,6,7,8,10,12,13,14,17,18,19,20,22,23,24,25,26,27,28,29,31,32,33,35,36,37,38,39,40,41,44,45,46,47,50,51,53,56,57,58,60,64,66,68,69,70,71,72,73,76,77,78,79,80,81,89],"try":[25,27,29,32,44,51,58,61,62,63,64,65,67,84,85,86,89],"ttf\ud30c\uc77c\ub85c":76,"ttf\ud655\uc7a5\uc790\ub97c":76,"update\ud568\uc218\uac00":76,"void":[1,9,13],"while":[0,17,19,22,24,25,28,30,31,32,38,39,40,42,43,44,49,50,51,54,57,62,63,64,65,66,67,68,69,70,71,72,73,75,76,77,78,79,80,81,84,85,87,89],"world\uac00":[77,78],"world\ub294":77,"world\uc758":77,"x\uac12\uacfc":80,"x\uc88c\ud45c\uac00":76,"y\uac12\uc744":80,"y\uc131\ubd84\uc744":76,"y\uc88c\ud45c\uac00":76,A:[1,5,8,9,12,13,15,16,17,18,20,22,23,24,25,26,29,30,32,33,35,38,39,40,42,43,45,46,49,50,51,53,54,56,58,63,64,85,86,89],AND:[18,33],ANDing:84,AS:18,And:[22,32,58,62,66,68,69,71,74,84,85,89],As:[24,29,35,38,39,44,51,52,56,57,58,64,65,67,68,84,85,86,88,89],At:[26,31,63,64,65],BE:18,BUT:18,BY:18,Be:[22,23,24,28,44,65],Being:63,But:[26,39,43,51,58,62,64,65,68,69,71,72,74,85,87,88],By:[23,25,29,31,35,39,43,44,51,53,54,56,57,61,62,64,85,86],FOR:18,For:[1,17,18,20,22,23,24,25,26,27,28,29,30,31,32,33,35,36,37,38,40,42,43,44,45,46,47,48,49,50,51,53,56,57,60,61,62,63,64,65,67,68,71,84,85,86,88],IF:18,IN:[18,27],IS:[18,27],If:[6,10,13,17,18,19,20,22,23,24,25,26,27,28,29,30,31,32,33,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,56,58,59,60,61,62,63,64,65,67,68,69,71,72,73,74,84,85,87,88,89],In:[17,18,22,23,27,29,30,31,32,33,36,37,39,40,43,44,51,54,57,58,59,61,62,63,64,65,68,70,72,84,85,86,87,88,89],Is:[37,50,63],It:[2,13,16,17,18,19,20,23,25,26,28,29,31,32,33,36,37,38,40,42,43,44,47,50,51,53,54,56,57,58,59,60,61,63,64,65,66,68,69,72,73,84,86,87,88,89],Its:34,NO:18,NOT:[18,37,40,56],No:[1,3,6,7,9,12,33,44,45,50,51,67,70],Not:[23,25,41,51,60,63,64,65,69,70],OF:18,ON:18,OR:[18,29,35],ORed:38,ORing:33,Of:[57,69,70,71],On:[1,2,3,4,5,6,7,8,9,10,18,23,25,26,37,40,44,46,50,51,56,63,66,84],One:[11,19,32,62,63,65,84],Or:[26,44,64,74],SUCH:18,THE:18,TO:[18,32],That:[29,56,58,62,63,64,67,68,69,70,71,73,74,84],The:[1,2,3,4,5,6,7,8,9,10,12,13,15,16,17,18,19,20,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,59,60,61,63,65,66,68,71,84,87,88],Then:[11,22,24,58,62,64,65,68,71,73,84,85,86,88,89],There:[18,19,20,22,23,24,25,26,27,28,30,32,33,37,39,45,46,50,51,57,58,59,60,62,64,65,69,70,72,73,85],These:[20,22,23,24,26,29,32,37,39,44,45,47,48,50,51,52,53,56,58,59,62,64,65,84,85,87],To:[22,23,25,28,30,33,35,37,38,39,40,41,42,43,47,50,54,57,58,65,87,88],Will:[3,5,6,7,12,32,38,54],With:[26,37,51,62,63,65,84,85,87,88],_:33,__copy__:35,__dict__:25,__file__:[26,58,66],__init__:[32,45,50,57,58,62,64,66,86,87,88,89],__main__:[66,71,72,73,79,80,81,85,89],__name__:[66,71,72,73,79,80,81,85,89],__new__:[29,45],__tags__:53,_camera:18,_default_lay:50,_freetyp:[0,11],_index:1,_layer:50,_pixels_address:51,_pygam:11,_sdl2:48,_spin:[58,66],_sprite__g:64,_spritegroup:64,_tag:53,_test:53,_time_threshold:50,_use_upd:50,_walk:[58,66],a0:37,a6f89747b551:44,a_mask:35,aa:[20,30,65],aaa:65,aacircl:30,aaellips:30,aalib:23,aalin:24,aapolygon:[24,30],aatrigon:30,abandon:18,abil:[44,58,63],abl:[31,42,58,63,84,89],abnorm:89,abort:37,about:[16,18,19,23,26,32,36,37,39,42,44,48,50,51,55,58,59,61,62,63,64,65,67,68,70,71,72,73,74,84,85,87,88],abov:[15,18,19,22,23,24,29,32,40,41,42,43,45,48,57,58,62,64,65,74,84,87],absent:23,absolut:[19,20,29,32,37,40,51,84],abspath:[58,66],abstractgroup:50,acceler:[23,24,30,41,48,51,56,63,69,84],accept:[15,24,26,28,29,30,31,38,39,45,50,51,52,62],access:[9,10,16,17,19,24,25,26,28,29,32,35,37,38,39,41,43,44,46,50,51,59,64,65,67,84],accord:[43,69],accordingli:51,account:[32,33,38,40,42,68,84],accur:[39,40,54],achiev:[62,86],acolor:20,acquir:[10,51,52],across:[22,23,58,62,65,66,84,87,88,89],act:[58,63,70,84],action:[25,32,63,65,88],activ:[23,38,39,40,49,51,52,55,72,74],activeev:[23,25],actual:[5,12,18,19,22,23,28,30,32,37,38,40,41,43,45,50,51,54,56,58,59,62,63,64,65,73,84,85,88],ad:[11,23,24,25,31,32,35,38,39,40,42,43,47,50,54,56,58,62,64,65,68,69,70,72,73,84,87,89],add:[23,29,48,50,57,58,61,62,63,64,65,68,69,70,89],add_intern:64,add_map:47,addit:[22,23,24,25,26,32,33,36,37,44,46,48,50,51],addition:[23,24,47],address:[17,51,84,86],adequ:72,adjac:[24,30],adjust:[9,20,23,28,29,37,71,89],admit:84,adopt:[48,61],advanc:[16,28,29,47,50,51,58,62,63,67,70],advancedinputoutput1:[72,80],advancedinputoutput2:[72,80],advancedinputoutput3:[72,80],advancedinputoutput4:[72,80],advancedinputoutput5:[72,80],advancedoutputalpha1:[73,81],advancedoutputalpha2:[73,81],advancedoutputalpha3:[73,81],advancedoutputprocess1:[71,79],advancedoutputprocess2:[71,79],advancedoutputprocess3:[71,79],advancedoutputprocess4:[71,79],advancedoutputprocess5:[71,79],advancedoutputprocess6:[71,79],advancemam:56,advantag:[59,63,64,67,84,87],advic:[63,84],advis:[18,22,23],ae:28,affect:[12,23,24,29,38,42,44,45,50,51,52,65,74],afraid:65,after:[17,19,23,24,29,31,32,33,37,38,40,47,49,50,51,57,58,59,62,63,65,68,69,70,84,89],again:[18,33,40,44,50,51,54,59,61,62,64,65,84,85,88,89],against:[29,45,56,57,64],ago:63,agp:65,ahead:[24,32],ai:[84,86,89],aid:29,aim:61,alexei:74,algorithm:[24,35,44,56,67,70],alia:[46,50],alias:[16,23,28,29,85],aliceblu:21,alien:[26,64],align:[29,35,45,84],aliv:[17,50,64],all:[16,17,18,19,20,22,23,24,25,26,27,28,29,30,31,32,33,35,36,37,38,39,40,41,42,44,45,47,48,50,51,52,53,56,57,59,60,61,63,64,65,67,68,84,85,86,87,88],all_my_sprites_list:84,allblack:65,alloc:[31,38,68],allot:53,allow:[16,18,20,22,23,25,27,28,29,31,32,36,38,42,44,46,50,51,56,57,58,59,64,65,87,89],allowedchang:38,allsprit:[58,66],almost:[16,58,61,63,64,65,67,86],alon:[26,84],along:[24,25,26,29,37,45,53,63,64,65,66,74,84,87],alpha:[1,20,23,24,26,28,29,30,31,35,43,44,48,51,52,56,63,65,86],alreadi:[10,19,23,25,29,32,37,38,40,45,47,50,57,62,63,64,65,88],alsa:37,also:[11,13,15,16,17,19,20,22,23,25,26,28,29,30,31,33,35,36,37,38,39,40,42,44,45,47,50,51,52,53,54,56,57,58,59,60,61,62,63,64,65,68,69,72,73,84,85,86,87,88,89],alt:33,alter:[35,39,56],altern:[19,23,24,26,28,29,30,45],altgr:33,although:[58,68,86],alwai:[18,23,25,26,28,29,30,31,32,33,35,39,41,44,45,47,49,50,51,54,56,58,59,60,62,63,64,65,68,69,70,71,77,86,87,89],ambigu:38,among:18,amongst:16,amount:[23,25,28,29,32,39,54,55,56,58,63],ampersand:33,amplitud:49,an:[1,2,4,5,6,7,8,10,11,12,13,14,15,16,18,19,20,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,63,64,65,67,69,84,85,86,87,88,89],an_id:37,analog:[32,42,47],andal:29,andmask:[22,39],android:33,angl:[24,29,30,35,36,48,56,57,87,89],angle_to:36,angular:87,ani:[1,10,16,17,18,19,21,22,23,24,25,26,27,28,29,30,31,32,35,37,38,40,41,42,43,44,45,47,48,50,51,52,54,56,57,58,59,60,61,62,63,64,65,67,68,74,84,85,86,87,88],anim:[16,26,31,50,56,62,63,64,67],anisotrop:44,annoi:[16,61,73],anoth:[11,20,23,24,26,28,29,30,32,33,35,36,39,40,42,43,45,46,47,50,51,62,63,64,65,73,74,84,86,89],ansi:37,ansi_not:37,answer:[63,84],anti:[16,23,29,85],antialia:28,antialias:[24,28,29,30,56,58],anticip:[44,69],antiquewhit:21,antiquewhite1:21,antiquewhite2:21,antiquewhite3:21,antiquewhite4:21,anyon:64,anyth:[19,23,27,44,50,51,58,62,63,64,65,74,84],anywai:[65,70,84,85],anywher:[13,62],apart:38,api:[16,18,23,30,37,46,47,48,57],app:[23,26,44,57],appear:[16,23,25,54,62,63,64,70,84],append:[27,57,62,64,69,73,81,84],appli:[20,24,26,29,35,36,37,51,55,56,65,84],applic:[0,17,23,25,26,27,33,34,37,38,46,51,84,88],appreci:84,approach:61,appropri:[23,25,39,58,59,64,69,88],approxim:[32,35,51,57],aptitud:74,aqua:21,aquamarin:21,aquamarine1:21,aquamarine2:21,aquamarine3:21,aquamarine4:21,ar:[1,9,10,11,13,15,16,17,18,19,20,22,23,24,25,26,27,28,29,30,31,32,33,34,35,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,56,57,58,59,60,61,63,64,65,66,67,68,70,71,72,73,74,85,86,87,88,89],arang:65,arbitrari:[50,56,62],arbitrarili:23,arc:[24,30],arcad:[63,84],architectur:56,archiv:[28,29,84],area:[12,23,24,26,28,29,32,35,44,45,48,50,51,56,57,58,62,63,64,66,68,72,84,85,87,88,89],aren:[58,62,84],arg:[26,50,53],argb:31,argb_premult:31,argument:[1,2,4,10,12,16,17,18,19,20,22,23,24,25,26,28,29,30,31,32,33,35,36,38,39,40,41,43,44,45,47,48,50,51,53,54,56,58,59,62,64,84,85],aris:18,arithmet:[20,42,65],arkanoid:69,around:[23,24,26,32,36,39,42,45,48,54,57,58,59,62,63,65,84,85,86,89],arrai:[1,2,4,16,20,22,26,29,33,38,42,49,51,62,63,65,72,73,80],arrang:[65,68],array2d:[52,65],array3d:[52,65],array_alpha:[52,65],array_blu:52,array_colorkei:[43,52,65],array_green:52,array_r:52,array_to_surfac:43,arraydemo:[16,26,65],arraytyp:[26,49,52],arrayxd:65,arriv:84,arrow:[22,26,33,70],art:[67,74],articl:[62,63],as_joystick:47,as_polar:36,as_spher:36,ascend:29,ascent:[28,29],ascii:[15,22,33,52,67],asid:67,ask:[23,28,29,57,58,59,62,63,84],aspect:[44,45],assembl:[33,63],assertequ:56,assertnotequ:56,assign:[20,25,29,32,42,45,47,50,53,58,62,65,88],assist:51,associ:[3,8,29,48,55],assum:[1,10,12,20,28,29,37,39,45,57,61,64,86,88],asterisk:33,astonish:84,astyp:65,asurf:31,asyncblit:51,asynchron:51,attach:[10,23,26,47,57],attack:63,attempt:[18,28,29,37,51,58,60,65],attent:[63,70],attibut:50,attract:70,attribut:[6,23,25,27,28,29,30,32,33,34,35,36,39,44,45,50,51,53,54,58,64,85,87,88,89],attributeerror:[29,32,51,64],audio:[3,26,37,38,44,46,49,63],audio_allow_any_chang:38,audio_allow_channels_chang:38,audio_allow_format_chang:38,audio_allow_frequency_chang:38,audiodevicead:25,audiodeviceremov:25,author:[18,57,58,59,60,62,63,64,65,84],autom:84,automat:[13,19,23,28,29,30,31,32,33,34,37,38,44,46,50,51,58,60,65,68,69],avail:[0,1,3,10,18,20,22,23,26,27,28,29,30,31,37,38,41,44,46,49,51,52,53,55,56,58,59,60,62,63,64,65,84],avalanch:74,averag:[28,29,53,54,56,57,65,84],average_color:[56,57],average_surfac:[56,57],avid:84,avoid:[19,23,33,36,38,42,53,65,89],awai:[64,71,89],awar:[23,25,28,44,65],awhil:19,awkward:[62,84],ax:[23,29,32,47,87],axi:[24,25,29,32,36,39,42,47,48,49,52,56,85,87],axis_numb:32,azimuth:36,azur:21,azure1:21,azure2:21,azure3:21,azure4:21,b0:47,b3:47,b:[20,26,32,33,42,43,46,47,51,56,65],b_black:[73,81],b_height:[73,81],b_red:[73,81],b_width:[73,81],bach:40,back:[19,28,29,32,33,37,38,50,57,58,59,66,68,88,89],backend:[18,23,43,44,56,59],backgound:66,background:[24,26,28,29,38,50,57,61,64,66,84,85,87,89],backslash:33,backslashreplac:44,backspac:33,backward:[23,25,29,38,54],backyard:63,bad:84,bagic:[68,69,70,76,77,78],baker:63,ball:[25,32,61,63,67,68,69,70,71,72,73,75,76,77,78,79,80,81,85,86,88],ball_numb:32,ballrect:[63,67,68,69,70,71,72,73,75,76,77,78,79,80,81],ballsprit:89,banner:[16,26,58,66],bar:[71,79],barrier:67,base:[0,11,17,18,24,25,26,28,29,35,48,50,57,58,62,64,65,66,67,68,87,89],baselin:[28,29],basic:[16,18,20,23,26,31,46,58,61,62,63,64,65,76,84,86,87,88,89],bat:61,battleship:[67,75],bayer:18,bb:20,bdf:29,beam:22,bear:[28,29,39],beauti:62,becam:25,becaus:[24,27,29,36,37,51,58,61,64,65,67,68,69,70,72,73,84,85,86,87,88,89],becom:[23,25,29,38,40,49,51,52,62,63,64,65,68,73],been:[19,20,22,23,24,25,29,32,36,38,39,40,44,46,47,50,51,59,60,62,63,64,84,88,89],befor:[10,17,18,19,22,23,27,28,29,32,33,35,37,38,39,40,44,46,50,51,53,54,57,58,59,60,61,62,63,64,65,68,69,70,71,84,87,88],begin:[16,17,18,26,38,40,45,56,62,63,65,69,87],beginn:65,behalf:17,behavior:[39,50],behaviour:[23,39,44,46,89],behind:[16,23,50,87,88,89],beig:21,being:[9,18,23,24,25,31,32,33,35,37,38,39,40,42,46,63,64,69,84,88],believ:84,belong:[50,58,64,85],below:[18,20,23,24,26,27,32,37,44,45,47,50,57,62,71],bend:37,benefit:[62,64],beo:84,besid:[19,26,65],best:[13,18,23,25,26,35,38,42,43,51,52,59,62,63,64,65,72,84,86],bet:59,better:[23,28,30,37,39,40,51,56,62,63,64,65,71,84,85],between:[1,4,20,23,24,25,28,29,32,33,35,36,37,38,40,42,43,44,45,46,47,48,49,50,51,52,53,54,55,57,64,65,67,70,84],bezier:30,bg:57,bgcolor:29,bgd:50,bgr:[31,51,65],bid:58,big:[17,18,44,50,57,62,64,65,70,71,72],bigger:[16,23,58,73],biggest:[23,59],bilinear:56,bin:[66,85,86,87],binari:[16,18,20,22,41],bind:[37,59],bisqu:21,bisque1:21,bisque2:21,bisque3:21,bisque4:21,bit:[1,15,16,17,18,22,23,26,28,29,30,31,32,35,38,40,42,43,49,50,51,52,56,57,58,59,61,62,64,65,87,89],bitblt:62,bitmap:[22,29,31,56,62],bitmap_1:22,bitmap_2:22,bitmask:[22,33,35,50,51],bitsiz:[23,35,59],bitstream:[28,29],bitstreamverasan:28,bitwis:[23,33,35],bl:89,bla:31,black:[21,22,24,26,29,32,35,42,51,57,58,63,65,67,68,69,70,71,72,73,75,76,77,78,79,80,81,84],blade:63,blanchedalmond:21,blank:[28,57,62,84,85],blanket:[43,51],blend:[20,24,26,29,44,48,51],blend_add:51,blend_alpha_sdl2:51,blend_fil:26,blend_max:51,blend_min:51,blend_mod:48,blend_mult:51,blend_premultipli:[20,51],blend_rgb_add:51,blend_rgb_max:51,blend_rgb_min:51,blend_rgb_mult:51,blend_rgb_sub:51,blend_rgba_add:51,blend_rgba_max:51,blend_rgba_min:51,blend_rgba_mult:51,blend_rgba_sub:51,blend_sub:51,blend_xxx:26,blendmod:50,blink:67,blit:[12,20,23,26,28,29,30,32,43,48,50,51,52,56,57,58,61,63,64,65,66,67,68,69,70,71,72,73,75,76,77,78,79,80,81,84,87,88,89],blit_arrai:[43,52,65],blit_blend:26,blit_hw:[23,59],blit_hw_a:[23,59],blit_hw_cc:[23,59],blit_sequ:51,blit_sw:[23,59],blit_sw_a:[23,59],blit_sw_cc:[23,59],blitter:[44,51,62],blitzbas:26,blob:[56,57],block:[17,18,25,35,40,50,51,57,58,73,84],block_list:50,blocks_hit_list:50,bloodi:63,blt:62,blue1:21,blue2:21,blue3:21,blue4:21,blue:[1,18,20,21,23,24,28,31,42,51,52,56,57,65,68,71,72,73,79,80,81,85,87],blueviolet:21,bluish:65,bmp:[31,46,62,63],board:[73,81],bodi:70,bold:[28,29],bomb:64,bonu:62,bool:[17,18,19,23,24,25,27,28,29,31,32,33,35,36,37,38,39,40,44,45,46,47,48,50,51,56],boom:64,boom_sound:64,border:[23,24,30,39,45,48],border_bottom_left_radiu:24,border_bottom_right_radiu:24,border_radiu:24,border_top_left_radiu:24,border_top_right_radiu:24,borderless:48,bore:[67,86],borrow:[1,63,86],both:[19,23,24,28,29,30,31,32,33,35,37,38,39,42,51,56,57,62,63,64,65,67,71,74,84,87,89],bother:[58,61,86],bottom:[23,24,26,28,29,30,31,35,45,50,63,67,68,69,70,71,72,73,75,76,77,78,79,80,81,89],bottomleft:[45,89],bottomright:[45,89],bounc:[26,36,56,63,89],bound:[22,24,29,35,50,51],boundari:[24,29],box:[24,29,30,32,33,57,64,88],br:89,bracket:[33,87],breakag:42,breakdown:63,brief:[19,26,44,61,62],briefli:85,bright:[18,48,57],brighten:23,brightmap:65,bring:[50,63],broadcast:[42,65],broken:[39,44],broken_x:22,brought:56,brown1:21,brown2:21,brown3:21,brown4:21,brown:21,bu:[65,84],buffer:[1,2,18,20,23,31,37,38,43,46,51,58,63,64,84],buffer_s:37,bufferproxi:[0,16,17,51],buffers:[37,38],bug:[20,44,56,63,89],build:[44,64,65,85,89],built:[15,18,29,31,44,47,85],builtin:[18,28,64],bullet:[64,84],bump:84,bumper:32,bunch:[57,64],bundl:[28,29],burlywood1:21,burlywood2:21,burlywood3:21,burlywood4:21,burlywood:21,busi:[18,19,38,54,62],button1:39,button2:39,button3:39,button4:39,button5:39,button:[24,25,26,27,32,33,39,47,58,61,62,69,73,80,84,85,88],bx:47,bye:68,bypass:44,byte_data:46,bytecod:63,byteord:17,bytes:[17,23,35,51,59],bytestr:38,c:[11,16,17,18,20,26,30,33,43,44,51,60,63,65,67,75],c_api:0,cach:29,cache_s:29,cadetblu:21,cadetblue1:21,cadetblue2:21,cadetblue3:21,cadetblue4:21,cadillac:64,calcnewpo:[87,89],calcul:[24,29,35,36,40,42,50,68,69,72,73,87,88],calibr:57,call:[1,10,13,17,18,19,22,23,24,25,26,27,28,29,30,31,32,33,35,36,37,38,39,40,41,44,45,46,47,48,50,51,53,54,57,58,59,60,61,62,63,64,65,66,68,69,70,84,85,86,87,88,89],callabl:[17,25,44,50],callback:[1,2,17,50],caller:37,calling_mask:35,cam:57,came:[26,31],camera:[16,26,44],camlist:57,can:[1,9,14,15,16,17,18,19,20,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,49,50,51,52,53,54,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,84,85,86,87,88,89],candid:[13,33],cannot:[15,18,23,25,28,30,38,40,45,48,50,51,52,54,62,63,64,69,84,86,89],canva:[68,71],cap:33,capabl:[23,59,63,86,87],capslock:33,caption:[23,68],captur:[16,18,26,31],capword:25,card:[23,38,65],care:[27,38,58,65,72,85],caret:33,carri:89,castl:63,categor:64,caught:63,caus:[2,18,20,25,28,35,40,42,56,58,64,65,66,68,84,88],caveat:23,cc:57,ccolor:57,cd:[3,19],cdrom:[0,63],cdrom_tag:53,cdrom_test:53,ceil:63,center:[24,26,30,32,35,44,45,48,50,51,57,66,68,69,70,71,72,73,76,77,78,79,80,81,85],centeri:45,centerx:[45,58,66,85],centr:44,centroid:[35,57],certain:[20,25,33,36,57,58,61,67,68,69,70,71,72,84],certainli:[62,65],cff:29,challeng:63,chanc:[38,65,84],chang:[16,18,20,23,24,25,26,28,29,30,31,32,33,35,36,37,38,39,40,42,44,45,46,47,48,49,50,51,52,54,56,57,58,59,61,63,64,65,68,69,70,71,73,84,87,88,89],change_color:56,change_lay:50,channel:[8,20,31,37,38,40,65,84],channelnum:8,char_bit:35,charact:[15,17,23,28,29,33,43,44,52,62,84,88],character:36,characterist:[20,74],charset:46,chart:65,chartreus:21,chartreuse1:21,chartreuse2:21,chartreuse3:21,chartreuse4:21,chase:64,chaser:64,chatroom:62,cheap:[50,64],check:[3,4,5,6,7,8,12,18,23,25,26,28,32,35,38,39,40,42,44,46,47,49,50,52,57,58,60,62,63,64,67,68,70,71,72,84,85,86,87,88,89],checkout:44,chew:54,chief:86,child:51,chimp:[16,26,61,64,86],chimpanze:16,chocol:21,chocolate1:21,chocolate2:21,chocolate3:21,chocolate4:21,choic:[18,23,38,57],choos:[18,22,23,26,59,61,65,73,84],chop:56,chord:84,chore:84,chose:73,chosen:[18,23,29],chromin:18,chunk:[8,17,89],circl:[22,24,26,30,32,50,57],circular:64,circumst:89,claim:18,clamp:[26,45],clamp_ip:45,clariti:35,clark:84,classless:[86,87],classmethod:48,claus:89,clean:[39,42,58,60,62,63,64],cleaner:[62,63],cleanli:[60,62,63,64,89],cleanup:42,clear:[16,24,25,32,33,35,38,43,48,50,51,62,63,64,67,75,84],clear_callback:50,clearer:60,clench:[58,66],click:[22,24,26,32,33,39,69,72,84,85],clip:[24,26,45,50,51,62],clipboard:[16,26],cliplin:45,clipped_lin:45,clist:57,clock:[22,24,32,39,54,58,66,69,70,71,72,73,77,78,79,80,81,89],clockwis:[29,30,36,56,87],clone:20,close:[10,18,22,23,24,25,26,29,32,37,40,42,47,56,57,62,65,85,86],close_to_play:64,close_to_player2:64,close_to_player3:64,closest:[23,37,38,59],cmy:20,co:[87,89],cocoa:23,code:[6,15,16,17,18,22,23,24,25,26,27,28,29,30,32,33,35,39,42,43,44,45,46,50,51,56,57,58,62,63,64,65,67,68,69,70,71,72,73,84,85,86,87,88,89],codec:44,codepoint:28,coercion:65,col:30,collect:[13,23,51,60],collid:[35,45,50,58,64,66,87,89],collide_circl:50,collide_circle_ratio:50,collide_mask:[35,50],collide_rect:50,collide_rect_ratio:50,collided_cal:50,collidedict:45,collidedictal:45,collidelist:45,collidelistal:45,collidepoint:[45,72,73,80,81,84,89],colliderect:[45,50,58,66,89],colliding_sprit:50,collis:[26,35,36,45,50,57,67,89],colon:33,color:[0,1,11,16,22,23,24,28,29,30,31,32,35,42,43,48,50,51,52,56,57,58,59,62,63,65,67,68,71,72,73,80,81,84,85],color_valu:20,colordict:21,colorkei:[23,26,28,29,31,43,51,52,56,58,63,65,66],colormap:[26,43,52],colorspac:18,colour:[20,44],column:[35,42,65,73,81],com:56,combin:[23,29,33,45,51,56,63,64,84,89],come:[10,25,26,28,29,37,44,57,62,63,64,65,66,84,87,88,89],comfort:[16,87],comma:[28,29,33,37,65],command:[24,25,26,32,53,65,67,68,69,70],commend:65,comment:[26,32,61,64,66,87,89],commerci:[16,63],commit:[33,63],common:[23,28,29,32,47,50,56,60,61,62,63,84],commun:[25,48,84],comp:84,compani:63,compar:[33,35,42,44,50,56,63,68,84],comparison:[20,25,26,42,65,70,74],compat:[23,25,28,29,31,38,48,50,54,67,86],compens:63,compil:[14,16,19,22,25,29,38,41,44],complement:36,complet:[24,33,38,40,45,50,51,52,63,64,84,89],complex:[38,58,63,64,67,69,84,86,87,88],complic:[68,84],compon:[20,35,36,43,51,65,68],composit:33,compositor:44,compound:46,compound_text:46,compress:[40,51],comput:[16,18,19,26,28,31,32,38,54,58,62,63,64,69,74,84],concept:[16,61,62,63,65,69,74],concern:[64,74],conclud:63,conclus:74,condit:[18,22,38,68,89],confid:84,configur:[16,23,29,39,65],confin:48,confus:[24,62,68,84],connect:[24,26,30,35,47,61,62,74,86],connected_compon:[35,57],consequ:86,consequenti:18,consid:[23,24,29,35,38,40,44,45,50,51,56,84,89],consider:51,consist:[19,24,25,27,38,46,61,65,85,86],consol:[26,44,53,67],constant:[16,22,25,29,33,38,39,44,46,47,54,57,60,68,72],constantli:84,constrain:[24,39,70],construct:[36,45,62],constructor:[29,32,50,58,64],consum:[1,54,65,84],contact:[57,58,59,60,62,63,64,65],contain:[0,7,9,10,16,19,22,23,24,25,28,29,31,32,33,34,35,37,38,39,43,45,46,47,50,51,53,55,58,59,62,63,64,66,84,86,88,89],content:[23,34,41,42,46,58,59,68,70],context:[10,23,42,48],contigu:[17,24,51],continu:[35,38,44,50,51,63,85],contol:47,contract:[18,56],contrast:[39,70,87],contribut:64,contributor:18,control:[3,5,18,22,25,26,28,29,32,33,34,38,41,44,50,51,52,53,54,56,58,59,60,61,63,69,70,78,84,86],controller_axis_lefti:47,controller_axis_leftx:47,controller_axis_righti:47,controller_axis_rightx:47,controller_axis_triggerleft:47,controller_axis_triggerright:47,controller_button_a:47,controller_button_b:47,controller_button_back:47,controller_button_dpad_down:47,controller_button_dpad_left:47,controller_button_dpad_right:47,controller_button_dpad_up:47,controller_button_guid:47,controller_button_i:47,controller_button_leftshould:47,controller_button_leftstick:47,controller_button_rightshould:47,controller_button_rightstick:47,controller_button_start:47,controller_button_x:47,controlleraxismot:47,controllerbuttondown:47,controllerbuttonup:47,controllerdevicead:[25,47],controllerdeviceremap:[25,47],controllerdeviceremov:[25,47],controllertouchpaddown:47,controllertouchpadmot:47,controllertouchpadup:47,convei:22,conveni:[36,44,50,53,62,63],convent:47,convers:[1,18,20,35,42,52,84],convert:[1,18,20,22,24,29,31,37,38,40,43,45,49,51,52,58,59,62,65,66,85,86,89],convert_alpha:[26,31,51,86,89],convolut:[35,65],convolv:35,cool:84,cooper:19,coord:57,coordin:[9,22,24,29,30,32,35,36,39,50,51,56,85,89],copi:[17,22,26,31,35,36,38,42,45,46,48,49,50,51,52,56,58,62,63,64,65,84,85],copyright:18,coral1:21,coral2:21,coral3:21,coral4:21,coral:21,cord:26,coremidi:37,corner:[24,29,30,35,39,42,44,50,51,56,57,58,62,84,89],cornflowerblu:21,cornsilk1:21,cornsilk2:21,cornsilk3:21,cornsilk4:21,cornsilk:21,correct:[18,22,28,41,45,56,62,65,68,73],correct_gamma:20,correctli:[37,38,56,57,58,62,65,84],correspond:[29,33,35,37,42,51,53,68,84,89],cost:84,could:[22,25,33,41,49,50,52,56,57,58,61,62,64,65,84,85,86,87],couldn:[86,89],count:[17,19,32,35,38,42,56,57,69,73],counterclockwis:[24,29,36,56],coupl:[32,58,62,64,65],courier:29,cours:[57,69,70,71,85,86,87,89],cover:[16,24,44,45,51,56,57,59,62,74,85],coverag:24,cpu:[24,54,67,75,84],cram:84,crash:[41,64],crate:87,creat:[1,2,6,7,16,17,19,20,21,22,23,25,26,28,29,31,32,33,35,38,39,41,42,43,45,47,48,49,50,51,52,54,56,57,59,63,64,65,66,74,84,85,86,87,88,89],create_graphics_screen:62,create_screen:62,creation:[29,32,47,49,50,52,62],creativ:74,crect:57,crimson:21,critic:84,critter:[58,66],crop:[45,56],cross:[32,36,58,63,65,84,86],crossbar:26,crossbon:22,crossfad:65,crosshair:22,crt:23,crucial:84,crude:[26,58,62],cryptic:64,cube:26,cui:[67,68,73,81],current:[14,18,19,22,23,25,26,27,28,29,32,35,36,37,38,39,40,41,42,44,45,46,47,48,49,50,51,52,53,56,58,59,63,64,67,68,69,71,84,87,88,89],current_h:[23,59],current_w:[23,59],currrent:23,cursor:[16,26,39,58,63,84],cursor_arg:22,cursor_index:22,cursorfil:22,curv:30,custom:[16,23,25,26,38,50,63],custom_typ:25,customis:86,cut:[38,46],cutout:62,cx1:45,cx2:45,cy1:45,cy2:45,cyan1:21,cyan2:21,cyan3:21,cyan4:21,cyan:21,d:[32,33,51,62,84,85,87],da:61,dai:[63,64],damag:18,dark:[58,63],darkblu:21,darkcyan:21,darken:23,darkgoldenrod1:21,darkgoldenrod2:21,darkgoldenrod3:21,darkgoldenrod4:21,darkgoldenrod:21,darkgrai:21,darkgreen:21,darkgrei:21,darkkhaki:21,darkmagenta:21,darkolivegreen1:21,darkolivegreen2:21,darkolivegreen3:21,darkolivegreen4:21,darkolivegreen:21,darkorang:21,darkorange1:21,darkorange2:21,darkorange3:21,darkorange4:21,darkorchid1:21,darkorchid2:21,darkorchid3:21,darkorchid4:21,darkorchid:21,darkr:21,darksalmon:21,darkseagreen1:21,darkseagreen2:21,darkseagreen3:21,darkseagreen4:21,darkseagreen:21,darkslateblu:21,darkslategrai:21,darkslategray1:21,darkslategray2:21,darkslategray3:21,darkslategray4:21,darkslategrei:21,darkturquois:21,darkviolet:21,data1:37,data2:37,data3:37,data:[0,2,16,17,18,19,22,26,31,35,37,38,39,40,41,43,46,51,56,58,62,63,65,66,68,70,71,72,73,84,86,89],data_dir:[58,66],datatyp:65,david:84,dead:27,deal:[33,44,65,68,84,88],dealloc:32,dealt:[25,27,88],death:63,debat:84,debug:[25,56,88],decapit:63,decept:72,decid:[25,27,35,58,61,64,68],decim:24,declar:[9,65],decod:[22,29,33,46,63],decor:85,decreas:[38,72],decrement:10,dedic:64,deeppink1:21,deeppink2:21,deeppink3:21,deeppink4:21,deeppink:21,deepskyblu:21,deepskyblue1:21,deepskyblue2:21,deepskyblue3:21,deepskyblue4:21,def:[29,32,35,39,50,56,57,58,62,64,66,71,72,73,79,80,81,85,86,87,88,89],default_id:37,default_lay:50,defin:[1,2,4,7,8,9,11,12,24,25,28,29,32,34,44,46,50,58,61,84,85,88],definit:[46,60,64,65,70],deflat:89,degre:[29,30,35,36,52,56,58,87,89],del:65,delai:[26,33,37,54,62,69,84],delet:[25,33,62,64,84],deliv:37,demo:[26,58,65],demonstr:[16,26,58,65],denot:[40,45,54],depend:[15,23,25,28,29,31,35,38,40,42,43,46,49,58,63,66,69,71,84],deprec:[23,25,26,27,29,32,36,49,50,52],deprecationwarn:[49,52],depth:[18,23,35,42,48,51,52,56,57,58,59,62],deriv:[26,44,50,58,64],descend:29,descent:[28,29],describ:[1,17,22,23,37,39,45,57,59,86],descript:[1,18,22,25,29,33,34,44,46,62,64],design:[17,50,61,62,63,64,68,71,88],desir:[18,51,56,58,59,84],desktop:[23,48,59],desper:62,dest:[29,35,48,51,56,65],dest_rect:56,dest_siz:56,dest_surf:56,dest_surfac:56,destin:[18,28,29,30,35,42,50,51,56,62,63,85],destroi:[1,31,48,64],destruct:[56,58],destsurfac:18,detail:[16,23,24,29,34,35,36,37,41,50,51,56,57,61,71,84],detect:[23,26,35,36,42,44,45,50,57],determin:[19,20,22,23,24,28,29,31,33,36,37,40,41,50,51,56,59,64,65,68,69,72,87],dev13:25,dev3:[25,54],dev7:39,dev8:24,dev:[18,57],develop:[23,39,44,48,53,63,67,86],devic:[16,18,19,25,26,32,33,37,39,47,55,57,59,63,84],device_id:[26,37],device_index:25,devicenam:38,dga2:84,dga:23,diagon:[35,56],diagram:[87,88],diamond:22,dict:[1,6,17,20,23,25,35,45,47,51,53,55],dictionari:[1,6,23,25,45,47,50,53,64,84],did:[18,24,32,62,63,64],didn:[84,85],diff:65,differ:[18,19,20,22,23,26,27,28,29,30,32,33,35,38,40,42,44,48,50,51,56,57,58,59,60,62,63,64,65,68,69,70,84,85,87,88],difficult:[37,61,63],digit:[20,32],dilemma:67,dimens:[17,18,23,24,26,28,29,30,35,36,42,43,45,50,51,52,56,58,65,89],dimension:[20,24,29,30,35,36,42,62,65],dimgrai:21,dimgrei:21,direct:[18,23,24,26,29,30,32,36,39,43,47,51,58,65,70,87,89],directfb:23,directli:[15,17,22,24,25,28,29,31,33,42,43,46,49,51,52,53,62,64,65,67,84],directmedia:63,directori:[23,28,29,53,58,62,67,68,86],directx:[23,37,63],dirti:[50,64],dirty_rect:84,dirtysprit:50,disabl:[23,25,29,33,44,47,51,54,58,66],disable_advanced_featur:44,disadvantag:[59,84],disallow:23,disappear:[18,30,46],disc:19,discard:54,disclaim:18,disconnect:61,discontinu:[17,51,67],discourag:27,discov:[63,84],discret:71,discuss:[64,84],disk:[50,84],displac:69,displai:[0,1,16,22,24,25,26,30,32,33,34,36,38,39,41,44,46,48,50,51,53,57,62,63,64,65,66,67,68,69,70,71,72,73,75,76,77,78,79,80,81,84,85,87,88,89],display_index:48,distanc:[36,42,56],distance_squared_to:36,distance_to:36,distil:84,distort:23,distribut:[16,18,53,58],dive:68,divers:61,divid:[33,61],divis:[20,22],dizzi:[58,66],doc:[23,27,48,50,51,70,78],document:[18,34,38,44,51,57,59,61,63,64,65,84,86,87],dodgerblu:21,dodgerblue1:21,dodgerblue2:21,dodgerblue3:21,dodgerblue4:21,doe:[4,5,8,13,19,22,23,24,25,26,28,29,30,32,33,35,37,38,40,41,43,44,45,46,47,50,51,54,56,57,58,62,64,65,68,84,86,88],doesn:[18,23,26,28,29,44,51,58,62,64,72,73,84,86,87,88,89],dokil:[50,64],dokill1:[50,64],dokill2:[50,64],dollar:33,domain:26,don:[18,24,26,29,32,50,54,56,57,58,61,62,63,64,65,68,70,74,85,86,87,89],done:[24,28,29,32,40,58,62,63,65,68,70,71,84,87],doreturn:51,dot:[29,36],doubl:[22,23,56,58,63,65,84],doublebuf:[23,84],doubler:56,down:[23,29,32,33,39,44,47,51,57,59,62,63,65,68,69,71,72,84,88],download:[63,65,89],dozen:84,dpad:47,dpi:29,drastic:85,draw:[16,20,23,28,29,31,32,35,48,50,51,57,62,63,64,66,67,68,71,72,73,79,80,81,84,85,89],draw_blend_mod:48,draw_bottom_left:24,draw_bottom_right:24,draw_circle_part:24,draw_color:48,draw_lin:48,draw_point:48,draw_rect:48,draw_top_left:24,draw_top_right:24,drawback:84,drawboard:[73,81],drawbutton:[72,73,80,81],drawhp:[71,72,73,79,80,81],drawn:[23,24,30,32,35,50,51,58,62,63,64,68,85],drawplain:58,dream:67,drew:62,drift:32,drive:[3,19],driven:[23,50,67],driver:[23,37,44,59,84],drivernam:44,drop:[25,29,38],dropbegin:25,dropcomplet:25,dropfil:25,dropout:38,droptext:25,dstobj:12,dstrect:[12,48],dualshock:47,due:[20,23,36,51],dull:84,dummi:[58,64,88],dump:53,dungeon:63,duplic:[50,51],durat:[32,47],dure:[18,23,29,30,33,40,42,52,65],dvd:[19,69,77],dx:[25,35,51,87,89],dy:[25,35,51,87,89],dynam:69,e:[6,20,23,24,28,30,31,32,33,35,36,37,38,44,45,50,57,61,85,87,88],each:[17,18,19,20,23,24,25,26,27,28,29,30,32,35,36,38,39,42,46,49,50,51,52,53,56,57,58,60,61,62,63,64,65,71,84,85,87,88,89],earli:[16,48,63,84],earlier:[26,40,43],easi:[26,48,59,60,61,62,63,64,65,70,84,88,89],easier:[45,50,59,60,62,87],easiest:[26,47,62,71,85],easili:[22,44,57,58,60,62,64,65,69,74,84,87],east:22,eat:64,echo:26,eclass:10,eclecti:57,ed:[51,64],edg:[24,28,39,45,56,89],edit:[33,47],editbox:84,editor:[33,84],effect:[16,23,25,26,28,32,40,44,46,47,50,51,56,57,58,62,63,64,65,73,84,86],effici:[16,23,25,28,50,62,64],effort:74,eg:[26,29,31],eight:26,either:[15,17,19,22,23,29,31,32,38,39,45,50,51,56,58,59,89],eject:19,element:[4,17,20,29,36,37,42,43,49,51,62,64,65],elementari:87,elementwis:36,elif:[32,39,58,66,69,70,71,72,73,77,78,79,80,81,88,89],ellips:[16,24,30],ellipt:[24,30],els:[1,9,32,33,43,44,45,46,58,59,64,66,69,84,86,89],elsewher:1,emb:23,embed:[23,29],emit:39,emoji:28,empti:[6,19,23,25,27,28,29,32,35,44,45,46,50,53,59,64],emul:[23,28,39,59],enabl:[23,25,28,29,33,44,47,48,63,67],encapsul:88,enclos:[24,50,68],encod:[10,15,22,28,29,40,44,46,51],encode_file_path:44,encode_str:44,encount:35,end:[19,24,25,30,31,33,38,40,44,45,50,58,61,62,63,66,69,74,84,85,88],end_index:65,end_po:24,endcap:[24,30],endev:[38,40],endian:[17,44],endpoint:[24,30,45],enemi:64,engin:[24,63,67,84],enhanc:[16,28,29],enjoy:70,enlarg:29,enough:[29,50,57,58,60,62,63,64,65,67,71,84],ensur:[25,27,33,38,63,84,85,86],enter:[25,28,33,39,48,58,67],entir:[16,19,23,24,35,38,48,50,51,62,63,64,68,69,70,72,84],entri:[17,33,51,84],enumer:18,env:[66,86],env_var:44,environ:[23,25,28,37,44,46,63,67,68,86,87],equal:[14,17,20,22,24,25,29,33,35,36,51,67,73],equat:[35,69],equip:65,equival:[17,29,35,37,42,43],eras:[32,35,50,58,62,63,64,84],err:[86,89],errno:37,error:[1,2,3,7,10,12,20,23,25,26,29,31,33,37,43,44,46,53,56,58,60,64,65,74,84,86,89],error_msg:44,errorstr:44,es:23,esc:26,escap:[15,29,33,58,89],especi:[25,29,44,64,65,84,86],essenti:65,etc:[31,32,37,42,45,61,65,67,84],etyp:44,euclidean:[36,42],euro:33,eval:53,evalu:58,even:[15,18,19,23,24,26,28,29,32,40,42,44,54,57,62,63,64,65,67,68,72,84],event:[0,16,18,22,23,24,26,32,33,34,37,38,39,40,47,54,57,61,62,63,66,67,69,71,72,73,75,76,77,78,79,80,81,89],event_nam:25,eventlist:[25,26],eventtyp:[6,25],eventu:[13,23,25],ever:[37,40,59],everi:[16,18,19,22,25,26,33,35,36,38,40,44,50,51,52,54,56,59,61,63,64,65,67,68,69,70,71,74,84,85,86,88],everyth:[25,43,44,62,63,64,65,66,67,68,73,84,85,89],evil:84,evolv:26,ex:[39,70],exact:[20,22,23,24,31,32,39,57,59,72,73],exactli:[37,42,45,51,58,62,63,64,65,68,84],examin:16,exampl:[11,16,17,20,22,23,24,25,27,28,29,30,31,32,33,35,37,38,39,40,44,45,46,47,49,50,51,53,56,57,60,61,62,63,64,67,68,70,71,74,84,85,86,87,88],exce:51,exceedingli:29,excel:[58,62,63],except:[1,3,4,5,6,7,8,9,10,12,15,20,22,23,24,25,28,29,31,32,33,37,38,44,45,46,51,56,60,61,65,69,86,89],exchang:42,excit:[58,62,63,65],exclaim:33,exclud:[17,25,51,53],exclus:[37,51],execut:[39,53,66,67,68,69,70,71,73],exemplari:18,exist:[18,19,22,23,24,25,28,29,32,37,47,48,50,51,64],exit:[23,24,32,37,44,48,62,63,67,68,69,70,71,72,73,75,76,77,78,79,80,81,85,86,89],exmapl:67,expand:[56,61],expans:56,expect:[20,27,37,38,39,43,53,57,62],expens:65,experi:[25,63,64,70],experiment:[18,23,30,36,44,46,48,57],expir:53,explain:[58,62,64,68,71,73,86,87,89],explan:[26,36,60,64,66,68,70,84],explanatori:58,explicit:[23,39,43],explicitli:[18,23,29,30,42,54,58,60],explor:63,explos:64,expos:[2,11,29,43,51],express:[18,20],extend:[17,24,31,44,50],extens:[1,2,3,4,5,7,8,9,10,12,13,16,31,56,63],extern:[22,25,49,52,67],extra:[22,29,38,45,50,51,58,59,62,63,64,65,70,89],extract:[42,56,58],extrem:[26,58,65],extsion:6,ey:63,f10:33,f11:33,f12:33,f13:33,f14:33,f15:33,f1:33,f2:33,f3:33,f4:33,f5:33,f6:33,f7:33,f8:33,f9:33,f:[1,17,18,33,84],face:16,fact:[30,64,84],factor:[26,29,65],fade:[26,38,40,65],fade_m:[38,40],fadeout:[38,40],fail:[23,25,27,28,29,44,53,58,60],failur:[1,2,4,5,6,8,9,53],fairli:[50,60,63,84,86,87],fake:[26,28,53],fall:[28,29,50],fals:[2,3,5,6,7,12,13,17,18,19,22,23,24,25,26,28,29,31,32,35,36,37,38,39,40,45,46,47,48,50,53,56,57,58,66,89],famili:28,familiar:[62,63,64,84,85,88],fantast:62,far:[20,36,58,62,71,84,87,88,89],farther:[58,62],fast:[32,35,42,51,52,56,58,62,63,64,65,69,84],faster:[31,36,44,50,52,56,58,64,65,67,84],fastest:[23,51,58,63],fastev:27,fastrendergroup:26,fault:84,favorit:84,favour:27,fbcon:23,featur:[16,23,26,27,28,29,35,44,50,51,59,64,65,87],fed:18,feed:89,feedback:23,feel:[26,62,64,84],felt:63,fetch:50,fever:[58,66],few:[22,28,54,62,63,64,65,74,84,86],ffff:15,fgcolor:29,field:[5,9,13,17,32,37],fighter:63,figur:62,file:[0,2,3,4,5,6,7,8,9,10,11,12,13,14,16,22,23,25,26,28,29,31,38,40,44,49,53,58,61,63,65,67,68,73,84,86],file_path:26,filenam:[7,22,25,28,29,31,38,40,62,86],fileobj:[31,40],filesystem:15,fill:[6,9,10,22,23,24,25,26,29,30,32,35,39,43,48,50,51,56,57,58,62,63,64,66,67,68,69,70,71,72,73,75,76,77,78,79,80,81,84,85,89],fill_rect:48,filled_:30,filled_circl:30,filled_ellips:30,filled_polygon:30,filled_trigon:30,filter:[16,25,35,56,65],fin:26,find:[16,18,19,23,24,25,26,28,32,35,36,38,50,51,56,57,58,59,62,63,64,65,69,71,84,87,89],find_channel:38,fine:[38,51,59,64,84],finer:57,finger:[55,70,86],finger_id:25,fingerdown:25,fingermot:25,fingerup:25,finish:[13,33,38,40,51,60,61,62,63,65],finit:35,fire:[65,84],firebrick1:21,firebrick2:21,firebrick3:21,firebrick4:21,firebrick:21,firmer:[61,63],first:[4,17,19,24,26,28,29,30,31,32,33,35,37,38,40,42,43,45,49,50,51,52,54,57,58,59,60,61,63,64,65,68,69,70,71,72,73,84,85,87,88,89],firstli:70,fist:[16,58,66],fist_offset:[58,66],fit:[18,23,29,38,45,51,85],five:[38,39,40],fix:[25,29,51,56,63,65,68,69,71,89],fixed_s:29,fixed_width:29,flag:[1,17,20,23,24,26,28,29,32,34,35,43,50,51,58,59,64,84],flame:65,flash:16,flavor:84,flexibl:[16,60,64,86,87],flickeri:84,flip:[18,22,23,24,25,31,32,35,39,42,45,48,50,56,57,58,63,65,66,67,68,69,70,71,72,73,75,76,77,78,79,80,81,84,85,89],flip_i:56,flip_x:56,flipi:48,flipx:48,flood:[73,81],floor:20,floralwhit:21,flourish:70,flush:[31,37],fly:[45,84,85,88],fnt:29,focu:[23,25,33,39,48,57,67],folder:58,folk:62,follow:[17,18,22,24,25,26,29,30,31,32,33,35,36,37,38,40,45,46,47,49,50,52,58,61,63,64,65,66,67,84],font:[7,16,26,32,44,58,60,63,66,68,69,70,71,72,73,76,77,78,79,80,81,84,85],font_index:[7,29],fonti:26,foo:84,fool:[63,65],forbidden:10,forc:[23,26,38,44,63],forcibl:38,forego:25,foreground:29,foreign:62,forestgreen:21,forev:62,forget:[32,64,87],form:[18,22,25,30,37,51,85],formal:62,format:[18,20,22,23,24,29,30,31,32,35,37,38,40,41,42,43,44,45,49,51,52,56,58,59,62,63,65,68,84,85],formula:[42,44,51,87],forth:58,fortun:[26,62,65],forward:33,found:[16,20,26,28,29,34,35,37,45,49,50,51,52,58,59,62,65,70,85,88],four:[4,19,22,23,24,29,45,52,70,89],fourth:[22,71],fout:26,fp:[46,50,69,77,84],fpsclock:[69,70,71,72,73,77,78,79,80,81],fraction:29,frame:[18,23,25,27,32,44,50,54,57,58,62,63,64,69,77,84,85,88,89],framebuff:23,framer:[16,18,54,57,58,84],framework:[26,63],free:[10,26,40,62,64],freedom:63,freetyp:[7,16,26,28,29,44],freetype2:29,freetype_misc:[26,29],frequenc:[37,38],frequency_to_midi:37,frequent:[32,62,64,69],friendli:[24,68],friendlier:63,frill:64,from:[0,4,6,7,9,10,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,42,43,44,45,46,47,48,49,50,51,52,53,56,57,58,60,61,63,64,65,67,68,69,70,71,72,73,76,77,78,79,80,81,84,85,86,87,88,89],from_display_modul:48,from_joystick:47,from_polar:36,from_spher:36,from_surfac:[35,48,50],from_threshold:[35,57],from_window:48,frombuff:31,fromstr:31,front:50,frozen:53,ftfont:[28,29],fuchsia:21,full:[23,25,26,27,28,29,31,32,38,39,40,42,50,51,56,57,58,59,62,63,64,66,70,85,86,89],fulli:[20,23,33,45,48,50,51,52,58,65,84],fullnam:[58,66,86,89],fullscreen:[23,34,48,50,59,84],fullscreen_desktop:48,fun:[26,57,62,63,65],fundament:61,funni:64,further:46,furthermor:[68,70,71],futur:[18,19,23,27,29,32,37,38,41,46,64],g:[20,23,24,26,28,30,31,33,36,37,42,43,44,45,50,51,56,87,88],gain:[23,25,29,57,84],gainsboro:21,game:[16,18,22,23,24,25,26,27,32,39,44,47,51,54,57,59,60,62,64,66,67,68,69,70,71,72,73,74,84,86,88,89],gameobject:62,gamepad:[25,47],gameplai:[33,64],gamma:[20,23,48],gap:[17,51],garbag:[13,51],gather:59,gaussian:65,gener:[1,16,23,25,26,31,32,33,36,37,39,40,42,47,51,52,56,57,58,63,64,65,68,73,86,89],generateboard:[73,81],geniu:74,geometri:[67,71],get:[2,16,18,19,20,22,23,24,25,26,27,28,29,31,32,33,35,37,38,39,40,42,43,44,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,62,63,64,65,66,67,68,69,70,71,72,73,75,76,77,78,79,80,81,85,86,87,88,89],get_abs_offset:51,get_abs_par:51,get_act:23,get_al:19,get_allow_screensav:23,get_alpha:[51,86,89],get_and_flip:57,get_arraytyp:[49,52],get_asc:28,get_at:[35,51,56,58,65,66,84],get_at_map:[20,51],get_axi:[32,47],get_backend:18,get_bal:32,get_bits:51,get_block:25,get_bold:28,get_bottom_lay:50,get_bounding_rect:[35,51],get_buff:[2,17,51],get_busi:[19,38,40],get_button:[32,47],get_bytes:[42,51],get_cache_s:29,get_capt:23,get_clip:[50,51],get_colorkei:51,get_control:[18,57],get_count:[19,32,37,47],get_curr:19,get_cursor:39,get_default_font:[28,29],get_default_input_id:37,get_default_output_id:37,get_default_resolut:29,get_desc:28,get_desktop_s:23,get_devic:55,get_device_info:37,get_driv:[23,59],get_empti:19,get_endev:[38,40],get_error:[29,44],get_eventst:47,get_extend:31,get_fing:55,get_flag:51,get_focus:[23,33,39],get_font:28,get_fp:54,get_grab:25,get_guid:32,get_hardwar:41,get_hat:32,get_height:[28,51],get_id:[19,32],get_imag:[18,57],get_init:[19,23,27,28,29,32,37,38,44,46,47,49,58,60,66],get_instance_id:32,get_ital:28,get_layer_of_sprit:50,get_length:38,get_lines:28,get_lock:51,get_loss:51,get_map:47,get_mask:51,get_metr:29,get_mod:33,get_nam:[19,32],get_num_channel:38,get_num_devic:55,get_num_displai:23,get_num_fing:55,get_numax:32,get_numbal:32,get_numbutton:32,get_numhat:32,get_numtrack:19,get_offset:51,get_palett:51,get_palette_at:51,get_par:51,get_paus:19,get_pitch:51,get_po:[39,40,58,66,84],get_power_level:32,get_press:[33,39,84],get_queu:38,get_raw:[18,38],get_rawtim:54,get_rect:[29,35,48,50,51,56,58,62,63,66,67,68,69,70,71,72,73,75,76,77,78,79,80,81,85,86,87,88,89],get_rel:39,get_repeat:33,get_sdl_byteord:44,get_sdl_image_vers:31,get_sdl_mixer_vers:38,get_sdl_vers:[23,44],get_shift:51,get_siz:[18,29,35,42,51,58,66,85,89],get_sized_ascend:29,get_sized_descend:29,get_sized_glyph_height:29,get_sized_height:29,get_smoothscale_backend:56,get_sound:38,get_sprit:50,get_sprites_at:50,get_sprites_from_lay:50,get_surfac:[23,58,66,87,88,89],get_tick:54,get_tim:54,get_top_lay:50,get_top_sprit:50,get_track_audio:19,get_track_length:19,get_track_start:19,get_typ:46,get_underlin:28,get_vers:29,get_view:[17,51],get_viewport:48,get_vis:39,get_volum:[38,40],get_width:[51,58,66],get_window_s:23,get_wm_info:23,getbufferproc:2,getch:[67,75],getfilesystemencod:[15,44],getopt:[86,89],gfxdraw:[11,16,24,30],gg:20,ggi:23,ghost:64,ghostwhit:21,gif:[31,63,71,72,73,79,80,81,84],gil:[10,30],github:[44,46,56],give:[17,22,23,29,32,37,40,42,50,51,58,59,60,61,65,74,84,85,86,87],given:[9,14,17,20,22,23,24,25,28,29,30,32,35,36,37,38,39,44,45,46,47,50,51,52,54,55,56,58,59,64,68,70,73,84],gl:23,gl_accelerated_visu:23,gl_accum_alpha_s:23,gl_accum_blue_s:23,gl_accum_green_s:23,gl_accum_red_s:23,gl_alpha_s:23,gl_buffer_s:23,gl_context_flag:23,gl_context_major_vers:23,gl_context_minor_vers:23,gl_context_profile_:23,gl_context_profile_compat:23,gl_context_profile_cor:23,gl_context_profile_mask:23,gl_context_release_behavior:23,gl_depth_siz:23,gl_framebuffer_srgb_cap:23,gl_get_attribut:23,gl_multisamplebuff:23,gl_multisamplesampl:23,gl_set_attribut:23,gl_share_with_current_context:23,gl_stencil_s:23,gl_stereo:23,glcube:26,glitch:89,global:[53,60,68,86,89],glsl:36,glue:89,glyph:[28,29],gnu:[86,89],go:[20,22,24,32,36,37,51,53,57,58,59,60,61,64,65,66,68,70,74,84,85,86,88,89],goal:63,goe:[58,62,64,68,89],gold1:21,gold2:21,gold3:21,gold4:21,gold:21,golden:59,goldenrod1:21,goldenrod2:21,goldenrod3:21,goldenrod4:21,goldenrod:21,gone:[62,89],good:[18,22,23,26,28,38,44,51,58,61,62,63,64,65,67,68,84,85,86,87,89],goodluck:26,got:[25,40,57,62,64,84],gotten:62,grab:[25,33,39,48,64,89],grace:89,gradient:[26,35,65],grahic:23,grai:[21,29,71,72,73,79,80,81],graphic:[23,26,56,58,59,62,63,64,65,67,68,84],grasp:[61,89],grave:33,gray0:21,gray100:21,gray10:21,gray11:21,gray12:21,gray13:21,gray14:21,gray15:21,gray16:21,gray17:21,gray18:21,gray19:21,gray1:21,gray20:21,gray21:21,gray22:21,gray23:21,gray24:21,gray25:21,gray26:21,gray27:21,gray28:21,gray29:21,gray2:21,gray30:21,gray31:21,gray32:21,gray33:21,gray34:21,gray35:21,gray36:21,gray37:21,gray38:21,gray39:21,gray3:21,gray40:21,gray41:21,gray42:21,gray43:21,gray44:21,gray45:21,gray46:21,gray47:21,gray48:21,gray49:21,gray4:21,gray50:21,gray51:21,gray52:21,gray53:21,gray54:21,gray55:21,gray56:21,gray57:21,gray58:21,gray59:21,gray5:21,gray60:21,gray61:21,gray62:21,gray63:21,gray64:21,gray65:21,gray66:21,gray67:21,gray68:21,gray69:21,gray6:21,gray70:21,gray71:21,gray72:21,gray73:21,gray74:21,gray75:21,gray76:21,gray77:21,gray78:21,gray79:21,gray7:21,gray80:21,gray81:21,gray82:21,gray83:21,gray84:21,gray85:21,gray86:21,gray87:21,gray88:21,gray89:21,gray8:21,gray90:21,gray91:21,gray92:21,gray93:21,gray94:21,gray95:21,gray96:21,gray97:21,gray98:21,gray99:21,gray9:21,great:[23,57,63,65,84],greater:[17,24,28,29,33,35,37,40,51,74],green1:21,green2:21,green3:21,green4:21,green:[1,18,20,21,23,24,42,51,52,57,58,65,68,69,70,71,72,73,76,77,78,79,80,81,85],greenyellow:21,grei:[21,58],grey0:21,grey100:21,grey10:21,grey11:21,grey12:21,grey13:21,grey14:21,grey15:21,grey16:21,grey17:21,grey18:21,grey19:21,grey1:21,grey20:21,grey21:21,grey22:21,grey23:21,grey24:21,grey25:21,grey26:21,grey27:21,grey28:21,grey29:21,grey2:21,grey30:21,grey31:21,grey32:21,grey33:21,grey34:21,grey35:21,grey36:21,grey37:21,grey38:21,grey39:21,grey3:21,grey40:21,grey41:21,grey42:21,grey43:21,grey44:21,grey45:21,grey46:21,grey47:21,grey48:21,grey49:21,grey4:21,grey50:21,grey51:21,grey52:21,grey53:21,grey54:21,grey55:21,grey56:21,grey57:21,grey58:21,grey59:21,grey5:21,grey60:21,grey61:21,grey62:21,grey63:21,grey64:21,grey65:21,grey66:21,grey67:21,grey68:21,grey69:21,grey6:21,grey70:21,grey71:21,grey72:21,grey73:21,grey74:21,grey75:21,grey76:21,grey77:21,grey78:21,grey79:21,grey7:21,grey80:21,grey81:21,grey82:21,grey83:21,grey84:21,grey85:21,grey86:21,grey87:21,grey88:21,grey89:21,grey8:21,grey90:21,grey91:21,grey92:21,grey93:21,grey94:21,grey95:21,grey96:21,grey97:21,grey98:21,grey99:21,grey9:21,greyscal:56,grid:29,ground:62,group1:[50,64],group2:[50,64],group:[26,35,50,58,63,86],group_list:50,groupcollid:[50,64,87],groupmulti:64,groupsingl:[50,64],grow:[24,45,84],guarante:[18,23,25,38,46,53],guess:[38,84],gui:[63,67,71,72,73,75,79],guid:[16,32,57,85],gun:71,h:[1,2,3,4,5,6,7,8,9,10,11,12,13,14,20,25,26,30,33,42,43,45,51,56],ha:[1,2,11,16,17,18,19,22,23,24,25,26,27,28,29,31,32,33,35,36,38,39,40,42,43,44,45,46,47,49,50,51,52,53,54,56,57,58,59,60,62,63,64,65,67,68,69,70,71,72,73,84,86,87,89],habit:87,had:[51,63,64,84],hadn:84,half:[26,50,63,84],hand:[20,22,42,43,58,60,62,84,87],handi:[26,61,86,87,88,89],handili:89,handl:[10,15,16,23,25,28,29,32,33,38,43,44,50,56,59,61,63,64,65,66,70,87,89],handler:[25,27],hang:[32,84],happen:[19,24,58,60,63,64,84,85,88,89],hard:[62,63,65,68],hardcod:26,harder:[61,65],hardest:64,hardwar:[22,23,24,30,32,37,38,41,51,63,64,65],harmless:23,hasattr:28,hash:33,hashabl:45,hasn:29,hat:[25,32,47],hat_numb:32,have:[1,4,9,11,18,19,20,22,23,24,25,26,27,28,29,30,32,33,35,36,38,40,41,42,43,44,45,47,50,51,52,53,54,56,57,58,59,60,61,62,63,64,65,67,68,69,70,72,73,84,85,86,87,88,89],haven:84,he:[58,84,85],headach:84,header:[0,1,2,3,4,5,6,7,8,9,10,12,13,14,68,70,76],headless:26,headless_no_windows_need:26,heavili:25,hei:84,height:[9,18,22,23,24,26,28,29,31,32,35,41,42,45,48,50,51,56,59,62,63,67,68,69,70,71,72,73,75,76,77,78,79,80,81,84],held:[33,88],hello:[68,69,70,76,77,78,85],help:[16,22,25,26,28,32,33,37,38,39,48,50,51,53,54,58,59,61,64,65,70,86,87,88],helper:63,henc:29,here:[18,23,25,26,34,35,39,41,44,50,51,58,59,60,64,65,66,68,70,84,85,86,87,88,89],hex:20,hflip:[18,57],hi:[58,62],hidden:[23,25,39],hide:[33,39,44,48,58],high:[0,23,26,50,67,69,84],high_frequ:[32,47],higher:[16,23,37,47,50,52,59,63,64],highest:44,highgui:44,highli:[27,51],him:[58,62],hint:[23,84],hit:[25,26,58,61,84,85,87,88],hitbox:[58,66],hkey_local_machin:37,hline:30,hmm:62,hold:[1,25,28,32,33,50,56,64,65,70],holdov:64,home:33,honeydew1:21,honeydew2:21,honeydew3:21,honeydew4:21,honeydew:21,hook:50,hoonwhitecatr:[68,69,70,71,72,73,76,77,78,79,80,81],hope:64,hopefulli:[62,65,87],horizont:[18,24,25,26,29,30,39,56,58,65],horizontal_advance_i:29,horizontal_advance_x:29,hot:25,hotpink1:21,hotpink2:21,hotpink3:21,hotpink4:21,hotpink:21,hotplug:32,hotspot:[22,39],hour:84,how:[15,16,19,20,23,24,26,29,31,32,33,35,36,38,40,44,46,50,51,54,56,58,61,63,64,65,68,69,70,71,72,73,74,84,87,88,89],howev:[13,18,29,34,42,44,45,47,50,56,67,68,69,70,74,84],hp:[70,71,72,73,78,79,80,81],hsl:20,hsla:20,hsv:[18,20,57],hsva:20,html:[20,70,78],http:[39,56,70,78,86,89],hue:18,human:[63,74,86],humung:63,hundr:63,husano896:39,hw:[23,59],hwaccel:51,hwsurfac:[23,51,65,84],hx:47,i1:20,i1i2i3:20,i2:20,i3:20,i686:56,i:[1,5,16,17,18,22,24,26,27,32,33,35,36,38,45,57,61,63,64,65,68,70,71,72,73,79,80,81,84,85,86,87,88,89],iceberg:64,icon:[23,48],iconifi:23,icontitl:23,id3:40,id:[3,19,23,25,32,33,37,38,48,55],idea:[23,51,57,59,61,63,65,70,71,72,73,86,87],ident:[25,42,72],identif:37,identifi:[3,25,32,33,44,46,57],idiom:[58,84],idl:[24,25,27,32,38,40],idx:50,ie:[31,65,84],ignor:[25,29,35,37,38,40,51,53,84],illeg:45,illus:62,illustr:[62,65,87],im:33,imag:[12,13,16,18,20,22,23,26,28,29,30,41,46,48,50,52,56,58,59,61,63,64,65,66,67,68,69,70,71,72,73,75,76,77,78,79,80,81,84,85,86,87,88,89],image_fil:26,imagefil:26,imagin:[62,85,89],imgsurfac:65,immanuel:74,immedi:[23,25,32,37,38,58],immut:20,implement:[10,11,13,17,18,20,23,26,29,37,42,43,44,50,61,63,64,73,74,84,89],impli:[18,29],implicitli:[23,51],import_pygame_bas:[1,11],importantli:62,importerror:[65,86,89],impos:[33,38],imprecis:84,impress:63,improperli:41,improv:[24,28,40,58,73,84],inact:[29,38],inadequ:84,incas:31,inch:29,incident:18,inclin:36,includ:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,16,18,22,23,26,28,29,30,31,32,34,37,44,45,50,51,53,54,56,58,61,63,64,65,67,70,74,84,86,87],inclus:[1,4,20,25,29,38],incom:16,incomplet:53,incorrect:43,increas:[23,29,38,50,68,72,74,84],incred:[74,84],increment:[11,56,65],inde:4,indefinit:[38,40],indent:[32,61],independ:[58,86],index:[1,7,16,18,19,23,29,32,33,42,43,44,45,47,48,49,50,51,52,55,62,65,84],indexerror:[30,35,37,51],indexexcept:17,indexoutofbound:50,indianr:21,indianred1:21,indianred2:21,indianred3:21,indianred4:21,indic:[12,23,24,25,30,35,37,39,40,42,45,46,49,50,52,53,65],indigo:21,indirect:18,individu:[16,19,29,35,44,51,53,58,84],ineffici:58,inequ:25,infinit:[58,63,68],inflat:[29,45,58,66,84,89],inflate_ip:45,influenc:23,info:[5,23,37,59,86],inform:[6,14,16,17,18,19,23,28,32,33,36,37,39,47,51,52,53,55,59,62,64,65,68],inherit:[50,51,64,86,87],init:[1,18,19,22,23,24,27,28,29,32,37,38,39,44,46,47,53,54,58,59,62,63,66,67,68,69,70,71,72,73,75,76,77,78,79,80,81,85,89],initi:[16,18,19,23,24,25,27,28,29,32,33,34,37,38,44,46,47,49,50,51,54,57,59,63,64,66,68,69,77,87],initialis:[32,44,47,61,85,88,89],innat:74,inner:72,input:[16,18,23,25,26,32,33,39,48,51,53,56,57,61,63,66,67,68,69,72,73,74,78,84,87],input_onli:48,inputimag:26,insensit:[43,51],insert:[33,69,73],insid:[22,24,26,31,44,45,50,51,57,58,63,65,71,72,89],insight:84,inspir:16,instal:[16,18,26,58,65,84],instanc:[2,3,4,5,6,7,8,9,12,13,17,19,25,26,29,30,32,35,38,42,45,50,51,58,61,64,85,87,88],instance_id:[25,32],instead:[9,15,20,22,23,24,25,26,28,29,32,33,36,38,42,44,50,51,53,56,62,64,65,69,84,87],instruct:56,instrument:37,instrument_id:37,int32:65,int8:65,int_valu:51,integ:[1,9,14,17,19,20,23,24,26,29,30,31,32,33,37,38,39,40,42,43,44,45,47,49,50,51,52,53,54,55,65,71,73],integr:18,intend:[43,50,51],interact:[6,16,26,33,34,42,47,50,53,63,65,70,87],interest:[25,46,63,67,74,84],interf:37,interfac:[1,17,20,29,33,37,38,42,43,47,51,57,63,70,73],interior:56,intern:[0,13,23,25,27,38,44,46,51,58,68,70,84,89],interpol:[20,30,36],interpret:[15,26,29,44,61,84],interrupt:18,intersect:[35,45,50,64,67],interv:33,intial:[58,66],intimid:65,intric:63,intro_bal:63,introduc:[23,25,43,61,62,65,87,89],introduct:[16,60,67,75],introspect:43,intuit:70,invalid:[1,23,38,45,47,56],invalu:87,inverse_set:56,invert:[29,35,36,42],invis:85,invok:[17,29,88],involv:[16,26,29,51,64,84,87,89],inward:24,ip:45,irc:84,is_control:47,is_norm:36,iscaptur:25,ish:24,isn:[19,27,48,57,61,62,64,69,71,84,88],isol:[51,57],issu:[23,62,63],ital:[28,29],item:[29,30,42,43,50,62,64],items:42,iter:[28,29,42,50,64,85,88,89],its:[2,10,13,17,18,23,24,25,29,30,32,35,36,37,38,42,44,45,46,48,50,51,58,59,61,62,63,64,68,69,70,84,85,86,87,88,89],itself:[13,18,28,29,36,42,43,44,48,51,58,61,62,63,64,87,88,89],ivori:21,ivory1:21,ivory2:21,ivory3:21,ivory4:21,iyuv_overlai:41,j:[33,35,73,81],jaggi:56,jid:32,jitter:32,job:[63,64],joi:25,join:[31,45,58,66,86,89],joint:24,journal:84,joyaxismot:[25,32],joyballmot:[25,32],joybuttondown:[25,32],joybuttonup:[25,32],joydevicead:[25,32],joydeviceremov:[25,32],joyhatmot:[25,32],joystick:[16,25,26,47,63,84,85,88],joystick_count:32,jp:18,jpeg:[31,84],jpg:[31,63],jumbl:84,jump:[39,62,63,65,84],just:[24,26,29,30,32,35,38,40,41,50,51,52,53,56,57,58,59,60,63,64,65,67,68,69,70,71,73,84,85,87,88,89],k:[33,36],k_0:33,k_1:33,k_2:33,k_3:33,k_4:33,k_5:33,k_6:33,k_7:33,k_8:[33,70,78],k_9:33,k_:[33,34,70],k_a:[33,70,78,89],k_ac_back:33,k_ampersand:33,k_asterisk:33,k_at:33,k_b:33,k_backquot:33,k_backslash:33,k_backspac:33,k_break:33,k_c:33,k_capslock:33,k_caret:33,k_clear:33,k_colon:33,k_comma:33,k_d:33,k_delet:[33,70,78],k_dollar:33,k_down:[33,70,71,72,73,78,79,80,81,88,89],k_e:33,k_end:33,k_equal:33,k_escap:[22,33,57,58,66],k_euro:33,k_exclaim:33,k_f10:33,k_f11:33,k_f12:33,k_f13:33,k_f14:33,k_f15:33,k_f1:33,k_f2:33,k_f3:33,k_f4:[33,70],k_f5:33,k_f6:33,k_f7:33,k_f8:33,k_f9:33,k_f:[33,84],k_g:33,k_greater:33,k_h:33,k_hash:33,k_help:33,k_home:33,k_i:33,k_insert:33,k_j:33,k_k:33,k_kp0:33,k_kp1:33,k_kp2:33,k_kp3:33,k_kp4:33,k_kp5:33,k_kp6:33,k_kp7:33,k_kp8:33,k_kp9:33,k_kp_divid:33,k_kp_enter:33,k_kp_equal:33,k_kp_minu:33,k_kp_multipli:33,k_kp_period:33,k_kp_plu:33,k_l:[33,70,78],k_lalt:33,k_lctrl:[33,70,78],k_left:[33,70,78],k_leftbracket:33,k_leftparen:33,k_less:33,k_lmeta:33,k_lshift:33,k_lsuper:33,k_m:33,k_menu:33,k_minu:33,k_mode:33,k_n:33,k_numlock:33,k_o:33,k_p:33,k_pagedown:33,k_pageup:33,k_paus:33,k_period:33,k_plu:33,k_power:33,k_print:33,k_q:33,k_question:33,k_quot:33,k_quotedbl:33,k_r:33,k_ralt:33,k_rctrl:33,k_return:33,k_right:[33,70,78],k_rightbracket:33,k_rightparen:33,k_rmeta:33,k_rshift:33,k_rsuper:33,k_scrollock:33,k_semicolon:33,k_slash:33,k_space:33,k_sysreq:33,k_t:[33,84],k_tab:33,k_u:33,k_underscor:33,k_up:[33,70,71,72,73,78,79,80,81,88,89],k_v:33,k_w:33,k_x:33,k_y:33,k_z:[33,89],kanji:29,kant:74,kde:44,keep:[13,17,25,32,50,54,56,57,58,59,60,61,62,63,64,84,88],kei:[16,17,20,22,23,25,26,33,34,35,45,51,55,57,58,61,63,64,66,70,71,72,73,74,78,79,80,81,84,88,89],kern:[28,29],kewdown:78,key_cod:33,key_rect:45,keyboard:[16,25,26,34,39,62,63,67,70,84,85],keycod:33,keydown:[22,25,33,34,57,58,62,66,70,71,72,73,78,79,80,81,88,89],keypad:33,keypress:84,keyup:[25,33,34,70,88,89],keyword:[16,18,24,25,26,35,38,44,48,51,53,56],khaki1:21,khaki2:21,khaki3:21,khaki4:21,khaki:21,khz:49,kick:61,kill:[50,53,64],kind:[37,43,51,61,65,67,84],kmod_alt:33,kmod_cap:33,kmod_ctrl:33,kmod_lalt:33,kmod_lctrl:33,kmod_lmeta:33,kmod_lshift:33,kmod_meta:33,kmod_mod:33,kmod_non:33,kmod_num:33,kmod_ralt:33,kmod_rctrl:33,kmod_rmeta:33,kmod_rshift:33,kmod_shift:33,know:[18,28,31,33,46,57,58,62,64,65,67,68,69,70,73,87,88,89],knowledg:[74,84],known:[33,84],korean:16,kwarg:[35,48,50,51],kwd:53,l:[32,33],l_margin:[73,81],lack:23,laggi:38,laid:[29,61],landscap:62,lang:84,languag:[26,28,33,62,63,84],lantinga:63,laplacian:56,larg:[16,29,43,45,51,61,64,65,87],larger:[23,38,51,56,58,65,67],largest:[35,57,59,63,65],last:[24,25,29,30,32,50,51,52,54,58,62,63,64,65,68,84],lastli:[22,50,58,59,62,64,65],late:84,latenc:[37,38,84],later:[18,23,30,37,38,42,46,50,57,58,59,60,62,63,64,65,68,86,89],latest:[29,70],latin1:[28,29],lavend:21,lavenderblush1:21,lavenderblush2:21,lavenderblush3:21,lavenderblush4:21,lavenderblush:21,lawngreen:21,layer1:50,layer1_nr:50,layer2:50,layer2_nr:50,layer:[50,63,64],layer_nr:50,layereddirti:50,layeredupd:50,layout:[17,28,29,43,52,88],lbm:31,leak:62,learn:[26,51,59,62,63,65,67,68,69,70,73,74,84],learnt:89,least:[14,24,30,35,43,51,55,61,65,67,70,84],leav:[24,29,51,65],left:[20,23,24,25,29,32,33,35,38,39,44,45,47,50,51,57,58,62,63,66,67,68,69,70,71,72,73,75,76,77,78,79,80,81,84,85,86,87,88,89],leftclick:26,leftmost:47,legaci:[27,67,75],lemonchiffon1:21,lemonchiffon2:21,lemonchiffon3:21,lemonchiffon4:21,lemonchiffon:21,len:[17,20,22,24,30,50,64,65],length:[1,4,9,17,19,20,23,24,25,30,32,33,36,38,42,47,51,58,68,87],length_squar:36,leonidovich:74,lerp:[20,36],less:[24,25,27,28,33,35,37,38,54,55,56,67,85],lesson:84,let:[10,20,21,26,44,51,58,59,61,63,65,69,70,71,84,88],letter:[19,28,51],level:[0,16,17,20,23,28,37,38,40,41,51,53,56,63,64,65,67,70],lgpl:16,li:84,liabil:18,liabl:18,lib:26,librari:[18,24,26,29,30,31,32,37,38,44,47,59,62,63,67],libsdl:39,licens:[16,86,89],lie:[30,45],life:[57,59],lifetim:[13,42,52,65],lightblu:21,lightblue1:21,lightblue2:21,lightblue3:21,lightblue4:21,lightcor:21,lightcyan1:21,lightcyan2:21,lightcyan3:21,lightcyan4:21,lightcyan:21,lightgoldenrod1:21,lightgoldenrod2:21,lightgoldenrod3:21,lightgoldenrod4:21,lightgoldenrod:21,lightgoldenrodyellow:21,lightgrai:21,lightgreen:21,lightgrei:21,lightpink1:21,lightpink2:21,lightpink3:21,lightpink4:21,lightpink:21,lightsalmon1:21,lightsalmon2:21,lightsalmon3:21,lightsalmon4:21,lightsalmon:21,lightseagreen:21,lightskyblu:21,lightskyblue1:21,lightskyblue2:21,lightskyblue3:21,lightskyblue4:21,lightslateblu:21,lightslategrai:21,lightslategrei:21,lightsteelblu:21,lightsteelblue1:21,lightsteelblue2:21,lightsteelblue3:21,lightsteelblue4:21,lightweight:[50,84],lightyellow1:21,lightyellow2:21,lightyellow3:21,lightyellow4:21,lightyellow:21,like:[1,10,16,18,20,22,23,24,26,27,29,31,32,33,34,35,36,38,39,40,42,44,47,50,51,56,57,58,59,60,61,62,63,64,65,68,69,70,72,73,74,84,85,86,87,88,89],lime:21,limegreen:21,limit:[18,19,23,24,25,28,29,31,32,38,40,51,52,53,54,60,63,64,65,73,84],line:[16,24,26,28,30,31,32,45,48,53,60,61,62,63,64,65,66,68,69,70,84,87,89],line_height:32,line_spac:29,linear:[20,23,36,50,65],linearli:51,linen:21,link:38,linux:[18,23,37,40,44,57,63,84],liquid:[26,62],list:[16,18,19,20,22,23,24,25,26,27,28,29,30,32,33,34,35,37,41,44,45,46,50,51,53,58,59,64,65,68,70,84],list_camera:[18,57],list_mod:[23,59],listen:39,littl:[17,22,26,44,50,54,58,59,61,62,64,65,68,84,87,88],live:[16,26,65],ll:[22,58,61,62,63,64,65,84,85,87,88,89],load:[8,10,16,18,22,26,30,31,40,50,59,61,62,63,65,66,67,68,69,70,71,72,73,75,76,77,78,79,80,81,84,87,89],load_background_imag:62,load_bas:31,load_extend:31,load_imag:[58,66],load_player_imag:62,load_png:[86,87,88,89],load_sound:[58,66,86],load_xbm:22,local:[9,16,33,34,38,39,44,57,58,60,61,68,69,70,71,72,73,76,77,78,79,80,81,85,86,89],locat:[26,34,35,39,41,58,68,69,70,71,72,73,84],lock:[13,17,24,25,27,33,42,43,50,51,52,84],lockobj:13,logger:26,logic:[48,58,61,63,65,68,69,70,71,84,86],logical_s:48,logo:23,loki:63,longer:[19,32,38,47,87,88],longest:38,look:[22,24,28,36,37,44,46,52,56,57,58,62,63,64,65,68,69,70,72,84,85,86,87,88,89],lookout:26,lookup:[23,25,28,50,58,65],loop:[24,25,32,38,40,54,57,61,62,63,64,66,68,84,86,87,88,89],lose:[19,23,33,56,84],loss:[18,23,58,59],lost:[25,40,46,62],lostsprit:64,lot:[26,32,51,54,56,58,59,61,62,63,64,65,67,73,84,85,87,89],loud:38,love:84,low:[32,63,67],low_frequ:[32,47],lower:[19,23,32,37,38,41,52,84],lowercas:28,lowest:37,lowli:84,ls:18,lt:32,luck:65,luckili:84,luma:18,m:[20,26,33,53,58,65,84],mac:[18,23,26,37,40,44,46,63,84],machin:[26,56,64,65,84],maco:22,macosx:25,macro:[3,4,5,6,7,8,9,12,14],made:[3,6,7,12,16,23,25,49,62,71,73,74,84,87],magazin:[16,71],magenta1:21,magenta2:21,magenta3:21,magenta4:21,magenta:21,magic:87,magnifi:26,magnitud:36,magnitude_squar:36,mai:[1,2,18,19,20,22,23,25,27,28,29,30,31,32,33,37,38,40,43,44,45,46,51,53,57,59,62,63,64,65,84],mail:[62,84],main:[18,24,25,26,27,32,39,41,46,50,53,57,61,62,64,65,66,71,72,73,79,80,81,85,86,87,88,89],main_dir:[58,66],mainli:[28,51,62,64,65],maintain:[28,44,50,61],major:[14,23,31,38,44,63],make:[0,16,20,22,24,25,26,27,31,38,42,44,45,50,51,52,54,56,57,58,59,60,63,64,65,67,68,70,71,72,73,74,84,85,86,87,88,89],make_sound:[38,49],make_surfac:[42,43,52],maker:[67,74],malform:29,man:67,manag:[16,19,25,32,38,42,50,51,59,63,64],mani:[19,23,24,25,28,29,33,38,39,40,44,45,50,51,54,56,58,59,62,63,84],manipul:[16,31,42,45,51,63,65,84,87],manner:[59,87],manual:[19,28,29,41,44,51,57,64,84],map:[17,20,24,32,42,43,47,51,52,59,65],map_arrai:[43,52],map_rgb:[20,24,42,51,52],mapped_int:51,margin:[26,68,71,72,73,80,81],mario:88,mark:[33,42,57,63],maroon1:21,maroon2:21,maroon3:21,maroon4:21,maroon:21,mask:[22,23,26,29,42,50,51,59,84],maskfil:22,mass:35,master:[56,65,67],match:[17,23,28,29,32,33,37,38,42,43,51,52,56,58,59,64,65,68],match_font:28,materi:18,math:[24,30,35,36,86,87,89],mathemat:[51,61,65],matter:[31,51,62,64,84,87],max:[24,32,35,57,71],max_i:29,max_x:29,maxhp:[71,72,73,79,80,81],maxi:28,maxim:[25,48],maximum:[23,28,29,84],maxtim:38,maxx:28,mayb:[62,64,70,84,86],me:[59,63,65],mean:[20,22,23,24,29,32,33,36,37,38,39,40,43,47,48,50,56,57,58,59,62,63,64,68,69,70,71,72,84,88],meant:[44,48,64,84],measur:[24,37,84,87],mechanim:67,mechanin:75,mediev:63,medium:32,mediumaquamarin:21,mediumblu:21,mediumorchid1:21,mediumorchid2:21,mediumorchid3:21,mediumorchid4:21,mediumorchid:21,mediumpurpl:21,mediumpurple1:21,mediumpurple2:21,mediumpurple3:21,mediumpurple4:21,mediumseagreen:21,mediumslateblu:21,mediumspringgreen:21,mediumturquois:21,mediumvioletr:21,meet:[45,84],megabyt:23,member:[25,50,59,64,68,84],membership:[50,64],memori:[17,23,24,29,38,51,52,62,67,84],mental:74,mention:[54,58,64,68,70,84],menu:[23,33,61],merchant:18,mercuri:44,mere:[37,84],merg:64,merrili:89,messag:[25,27,37,44,53,58,86,89],messi:64,met:[18,22],meta:33,method:[9,10,12,15,16,17,19,20,22,23,24,25,26,28,29,30,31,32,35,36,38,39,40,42,44,45,46,49,50,51,52,54,58,59,61,62,63,64,65,71,73,84,85,86,87,89],metric:[28,29],mice:39,micro:44,microsoft:23,midbottom:45,middl:[39,47,57,62,65],midi:[25,26],midi_ev:37,midi_event_list:37,midi_not:37,midi_output:37,midi_to_ansi_not:37,midi_to_frequ:37,midiexcept:37,midiin:[25,37],midiout:[25,37],midis2ev:37,midisport:37,midleft:[45,88,89],midnightblu:21,midright:[45,88,89],midtop:45,might:[20,23,25,26,29,44,46,60,61,62,64,65,84,86,87,89],mighti:62,migrationguid:39,milli:54,millisecond:[25,33,37,38,40,50,54,63,84],mime:46,mimic:29,min:[24,57],min_alpha:51,min_i:29,min_x:29,mind:[39,54,60,65],minhp:73,mini:28,miniatur:32,minim:[23,25,48,64],minimum:[23,24,28,30,31,35,51],minor:[14,31,38,44,63],mintcream:21,minu:33,minx:28,mirror:[23,58],miss:[58,66,84],missingmodul:[49,52],mistyros:21,mistyrose1:21,mistyrose2:21,mistyrose3:21,mistyrose4:21,misunderstand:84,miter:24,mix:[28,38,51,63,65,84],mix_chunk:8,mix_setmusicposit:40,mixer:[0,16,26,38,44,49,58,66],mizuno:18,mmsystem:37,mmx:[26,56],moccasin:21,mod:[25,33,34,40,67],mod_:34,modal:48,mode:[16,20,23,24,25,26,28,29,30,33,38,39,44,46,48,50,51,53,58,63,65],mode_ok:[23,59],model:51,modif:[13,18,51,86],modifi:[29,30,33,34,37,39,45,48,49,50,51,64,65,85],modnam:1,modul:[0,1,2,3,4,5,6,7,8,9,10,12,13,16,17,21,26,34,41,42,48,51,53,59,60,61,62,65,66,68,87,89],modulu:20,moment:[46,49,84,87],momma:62,monitor:[23,34,59,63,68],monkei:[58,63,66],mono:[29,38,49],monochrom:29,monster:64,month:63,moon:84,more:[16,18,19,20,23,24,25,26,28,29,30,31,32,35,36,37,38,39,42,43,44,47,50,51,54,57,58,59,60,61,62,63,64,70,71,73,74,85,86,87,88,89],most:[19,23,24,25,26,28,29,31,38,39,40,44,45,50,51,54,57,59,60,61,63,64,65,74,84,85],mostli:70,motion:[32,39,48,63,87,89],motiv:70,mous:[16,22,23,25,26,32,46,48,58,61,62,63,66,67,70,72,84,85,88],mousebuttondown:[22,25,27,39,58,66,84],mousebuttonup:[25,39,58,66,72,73,80,81,84],mousemot:[25,39],mousewheel:[25,39],movabl:[88,89],move:[16,25,26,39,44,45,50,51,56,58,61,63,65,66,67,68,69,70,71,72,73,75,76,77,78,79,80,81,84,85,87,88,89],move_and_draw_all_game_object:62,move_ip:[45,58,66],move_to_back:50,move_to_front:50,movedown:[70,78,88,89],moveit:[26,62],movement:[32,39,50,58,87,88],movepo:[88,89],moveright:[69,70,77,78],moveup:[69,77,88,89],movi:74,mozart:40,mp3:40,ms:[32,37,39,47],msg:37,msmf:18,much:[18,24,26,28,31,54,56,58,59,60,61,62,63,65,67,68,71,73,74,84,85,87,89],multi_thread:53,multicolor:26,multidimension:65,multigestur:25,multimedia:[33,63,84],multipl:[1,7,18,19,22,23,24,25,26,28,32,33,36,38,41,44,50,51,56,57,61,63,64,65,69],multipli:[20,24,29,33,36,42,48,56,65],multisampl:23,multithread:27,music:[8,16,26,37,38,40,63,74,86],must:[1,2,4,17,18,19,20,22,23,24,25,27,28,29,30,31,32,35,36,37,38,41,42,43,44,45,46,47,49,50,51,52,53,56,58,59,60,63,64,65,68,72],mustlock:51,mutabl:25,mute:38,my:[26,32,61,62,63,65,84,86,89],my_appl:44,my_data_typ:46,mygroup:64,myscreen:[68,69,70,71,72,73,76,77,78,79,80,81],mysprit:64,mysurf:51,mytext:[68,69,70,71,72,73,76,77,78,79,80,81],mytextarea:[68,69,70,71,72,73,76,77,78,79,80,81],mytextfont:[68,69,70,71,72,73,76,77,78,79,80,81],n:[28,33,38,65],name:[1,10,18,19,20,23,25,26,28,29,32,33,37,44,45,47,50,51,53,58,59,61,62,63,64,65,66,68,70,86,88,89],name_forindex:47,name_of_environment_vari:44,namehint:[31,40],namespac:[34,58,60],nano:31,nasti:86,nativ:[16,18,22,44,57,84],natur:[40,65,74,84,86],navajowhit:21,navajowhite1:21,navajowhite2:21,navajowhite3:21,navajowhite4:21,navi:21,navyblu:21,ndim:42,nearest:[24,38],nearli:[64,67],neater:88,necessari:[23,25,27,29,38,51,60,61,64,68,84,85,87,88,89],necessarili:63,need:[11,16,18,19,22,23,25,26,27,28,31,32,33,35,42,44,45,46,50,51,53,57,58,59,60,62,63,64,65,66,67,68,69,70,71,72,73,85,86,87,88,89],needless:[68,71,73,84],needn:[26,61,89],neg:[9,10,17,25,29,35,36,38,39,40,42,45,51,56,65,89],neglig:18,neither:[50,69,70],nest:51,net:[86,89],network:[61,86],never:[29,32,38,39,40,51,54,57,63,65,84],new_height:26,new_lay:50,new_mask:35,new_width:26,newarrai:42,newbi:16,newcom:84,newer:[23,40],newest:68,newli:[20,35],newlin:28,newpo:[58,66,87,88,89],newrect:64,newtonian:63,next:[18,27,29,30,35,36,38,41,46,58,64,68,73,85,88,89],nice:[58,61,62,65,87],nirav:57,node:44,noevent:[25,27,38,40,84],nofram:23,nois:[32,35,57],nomin:29,non:[17,19,23,24,26,29,31,33,41,42,44,50,51,56,58,64,84,86],none:[17,18,19,20,23,24,25,26,27,28,29,30,31,32,33,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,54,56,58,60,65,66,85,86,87,89],nonesound:[58,66],nonetheless:26,nonetyp:[30,35,50],nonlinear:51,nonzero:[35,45],nor:[50,70],normal:[9,12,19,20,28,29,35,36,44,45,50,51,53,55,58,64,65,71,87,89],normalize_ip:36,north:22,northeast:22,northwest:22,nosubprocess:53,notabl:[23,40,87],notat:39,notdef:29,note1:35,note2:35,note:[18,19,20,23,24,25,26,27,29,31,32,33,35,36,37,38,39,40,42,44,45,47,54,56,57,58,59,60,62,64,66,84,86,87,89],note_off:37,note_on:37,noteworthi:63,noth:[19,23,24,30,32,50,58,59,63,64,84,85,86],notic:[18,36,45,62,68,69,70,72,84,87,88,89],notifi:64,notimplementederror:[33,40],novel:74,now:[26,27,28,29,32,33,35,37,38,43,44,46,56,57,58,61,62,63,64,65,67,68,69,70,71,72,73,74,84,85,87,89],nowadai:63,nrp:57,num:[33,72,73,80,81],num_button:39,num_devic:37,num_ev:37,num_fing:25,num_threshold_pixel:56,num_track:19,number:[1,8,11,17,18,19,20,23,24,25,26,28,29,30,31,32,33,35,36,37,38,40,42,44,47,49,50,51,52,53,54,55,56,62,64,65,69,73,74,84],numbit:35,numer:[36,38],numev:[25,38],numfail:44,numlock:33,numpass:44,numpi:[1,16,26,42,43,49,51,52,63],o:[7,22,33,62],obj:[1,2,4,5,8,9,10,44],object:[1,2,4,5,6,7,9,10,12,13,16,18,19,21,22,23,24,25,26,27,28,29,30,31,32,35,38,39,40,43,44,46,47,48,49,52,54,56,57,59,61,62,63,64,65,66,68,69,70,86,89],obliqu:29,obscur:[61,84],obsolet:[23,44,51],obtain:[29,37],obviou:61,obvious:[64,85],occasion:64,occupi:85,occur:[29,33,37,38,42,68],octob:63,odd:[24,65,89],ofcod:89,off:[18,24,25,26,29,32,37,38,40,45,56,58,61,62,64,84,89],offcourt:89,offer:[22,23,25,47,57],offici:62,offset:[17,24,26,28,29,30,35,37,40,42,45,50,51,58],often:[19,31,36,51,61,63,65,69,84,86],ogg:[38,40],oh:89,ok:[65,84,85,87],okai:[69,72],old:[23,39,44,50,51,54,58,62,64,74,84,88],older:[27,32,40,44,64],oldest:68,oldlac:21,oliv:21,olivedrab1:21,olivedrab2:21,olivedrab3:21,olivedrab4:21,olivedrab:21,omit:[29,37,42,53],onc:[18,19,23,25,28,29,31,32,33,35,37,38,40,42,44,47,51,53,54,58,60,63,64,65,84,85,86,87,89],one:[17,18,20,22,23,24,25,26,27,28,29,30,31,32,33,35,38,39,40,42,43,44,45,46,47,49,50,51,52,54,56,57,58,59,60,61,62,63,64,65,67,68,69,70,71,73,84,85,86,87,88,89],ones:[29,40,51,60,64,87,88],onli:[3,17,18,19,20,23,24,25,28,29,31,32,34,35,37,38,39,40,42,43,44,45,46,47,48,49,50,51,52,53,54,56,57,58,59,60,61,62,63,64,65,67,68,72,73,74,84,85,86,87,89],ons:63,onscreen:23,onto:[12,20,27,28,29,30,35,36,50,51,58,62,63,65,68,84,85,87],ooo:84,opac:[48,84],opaqu:[20,26,29,35,43,48,51,52,65,84],open:[1,7,10,16,18,19,23,25,32,33,37,44,46,47,57,58,63,85,86],opencv:[18,44,57],opengl:[23,26],opentyp:29,oper:[15,20,22,23,24,25,27,33,36,42,44,45,48,50,51,52,56,64,65,85],operand:65,oppos:29,optim:[23,26,28,51,56,64,65],optimis:84,option:[1,17,18,20,23,24,26,28,29,30,31,32,35,37,38,39,40,43,44,50,51,53,54,56,57,58,60,62,65,84],orang:21,orange1:21,orange2:21,orange3:21,orange4:21,orangered1:21,orangered2:21,orangered3:21,orangered4:21,orchid1:21,orchid2:21,orchid3:21,orchid4:21,orchid:21,order:[1,18,23,28,29,33,37,38,40,42,44,50,51,53,54,58,62,65,68,84,89],orderedupd:50,ordinari:64,org:[39,58,59,60,62,63,64,65,70,78],organ:[16,50,64,84],organis:61,orient:[29,35,62],origin:[10,20,22,23,24,26,29,31,32,35,42,45,47,48,50,51,56,58,62,63,64,65,66],original_color:56,original_dest_color:56,orthogon:35,os:[10,18,23,26,31,32,37,44,46,58,66,84,86,89],oss:37,osx:[23,63],other:[0,18,19,20,23,24,25,26,27,28,29,30,31,32,33,35,36,38,40,42,43,44,45,46,48,49,50,51,52,53,54,56,57,58,61,62,63,64,68,70,71,84,85,86,87,88,89],otherarrai:42,othermask:35,othersurfac:35,otherwis:[1,2,6,10,13,17,18,22,23,24,26,29,31,35,36,37,38,39,43,45,46,50,51,52,56,62,72,73,89],ouput:[68,76],our:[58,62,63,65,66,74,85],out:[18,24,29,32,35,37,38,40,57,58,59,61,62,64,65,84,85,86,87,88,89],outdat:67,outer:72,outgo:37,outlin:[24,29,35,57],outpng:26,output:[18,25,26,28,32,35,56,67,69,70,73,74,84,88],outputimag:26,outsid:[24,28,30,33,35,39,45,51,56,58,63,68],over:[22,23,29,35,38,40,42,44,47,50,57,60,62,63,64,65,66,84,86],overal:65,overboard:86,overcom:67,overflow:65,overhead:[51,64,84],overlai:64,overlap:[35,45,50,62,64,84,87,89],overlap_area:35,overlap_mask:35,overlin:29,overrid:[18,29,35,44,50,51,63,84],overridden:[23,29,35,38,45],overwrit:[17,24,26,32,47],overwritten:[24,32,47,51],own:[13,22,25,26,27,37,38,46,48,59,61,63,65,84,86],own_data_typ:46,owner:13,ownership:46,p1:48,p2:48,p:[31,33,43],pac:64,pack:[23,51,52,59],packag:[16,26,28,29,30,31,49,52,58,60,63,65],pacman:64,pad:[29,32,56],page:[33,39,46,65],pai:70,pain:84,painless:86,paint:[50,85],pair:[13,23,24,28,29,31,32,45,51],pajitnov:74,palegoldenrod:21,palegreen1:21,palegreen2:21,palegreen3:21,palegreen4:21,palegreen:21,palett:[23,28,31,35,51,52,56],palette_color:[35,56],paleturquois:21,paleturquoise1:21,paleturquoise2:21,paleturquoise3:21,paleturquoise4:21,palevioletr:21,palevioletred1:21,palevioletred2:21,palevioletred3:21,palevioletred4:21,panic:84,papayawhip:21,paper:84,parallax:84,param:24,paramet:[18,20,23,24,25,26,29,30,31,33,35,36,37,38,39,40,44,45,46,51,55,56,57,70,71],parametr:36,parent:[2,13,17,48,50,51],parenthesi:33,pars:[84,87],part:[23,24,25,29,30,35,51,53,56,62,63,64,65,68,69,70,72,86],parti:[18,63],partial:[23,24,37,51,84],particular:[18,29,40,42,49,50,53,54,59,84],particularli:37,pass:[9,10,15,17,18,19,20,22,23,24,25,26,28,29,31,32,35,37,38,39,40,41,42,44,46,50,51,53,54,56,58,62,63,64,66,86],past:[24,46,58,63,84],patch:[14,26,31,38,44,63],patel:57,path:[7,10,16,25,26,28,29,31,36,38,44,53,57,58,66,86,89],pathlib:[28,29,31,38],pathlib_path:38,pathnam:[38,58,86],pattern:[29,40],paus:[19,26,33,38,40,54,86],pbm:[31,46],pc:[17,37],pcf:29,pci:65,pcx:31,peachpuff1:21,peachpuff2:21,peachpuff3:21,peachpuff4:21,peachpuff:21,peek:25,pellet:64,penalti:[51,59,64],pend:37,peopl:[16,58,61,62,63,84],per:[16,24,25,29,30,31,32,35,49,50,51,52,53,54,58,59,63,65,69,77,84,88,89],perfect:35,perfectli:84,perform:[12,23,25,26,28,29,30,35,36,38,42,50,51,52,56,57,59,64,65,84,85,88],perhap:[62,64,84,86],period:[33,40],permiss:23,permit:[15,18,29],person:[62,63,88],perspect:[26,63],peru:21,pete:[58,59,60,62,63,64,65,84],pfr:29,pg:[22,58,66],pg_buffer:[1,2],pg_encodefilepath:10,pg_encodestr:10,pg_floatfromobj:1,pg_floatfromobjindex:1,pg_getdefaultwindow:1,pg_getdefaultwindowsurfac:1,pg_intfromobj:1,pg_intfromobjindex:1,pg_major_vers:14,pg_minor_vers:14,pg_mod_autoinit:1,pg_mod_autoquit:1,pg_patch_vers:14,pg_registerquit:1,pg_rgbafromobj:[1,11],pg_setdefaultwindow:1,pg_setdefaultwindowsurfac:1,pg_twofloatsfromobj:1,pg_twointsfromobj:1,pg_uintfromobj:1,pg_uintfromobjindex:1,pg_version_atleast:14,pg_versionnum:14,pg_view_p:1,pgbuffer_asarrayinterfac:1,pgbuffer_asarraystruct:1,pgbuffer_releas:1,pgbufproxy_check:2,pgbufproxy_getpar:2,pgbufproxy_new:2,pgbufproxy_trip:2,pgbufproxy_typ:2,pgcd_asid:3,pgcd_check:3,pgcd_new:3,pgcd_type:3,pgcdobject:3,pgchannel_asint:8,pgchannel_check:8,pgchannel_new:8,pgchannel_typ:8,pgchannelobject:8,pgcolor_check:4,pgcolor_new:4,pgcolor_newlength:4,pgcolor_typ:4,pgdict_asbuff:1,pgevent_check:6,pgevent_filluserev:6,pgevent_new2:6,pgevent_new:6,pgevent_typ:6,pgeventobject:6,pgexc_buffererror:1,pgexc_sdlerror:1,pgfont_check:7,pgfont_is_al:7,pgfont_new:7,pgfont_typ:7,pgfontobject:7,pglifetimelock_check:13,pglifetimelock_typ:13,pglifetimelockobject:13,pgm:31,pgobject_getbuff:1,pgrect_asrect:9,pgrect_fromobject:9,pgrect_new4:9,pgrect_new:9,pgrect_norm:9,pgrect_typ:9,pgrectobject:9,pgrwops_fromfileobject:10,pgrwops_fromobject:10,pgrwops_getfileextens:10,pgrwops_isfileobject:10,pgrwops_releaseobject:10,pgsound_aschunk:8,pgsound_check:8,pgsound_new:8,pgsound_typ:8,pgsoundobject:8,pgsurface_assurfac:12,pgsurface_blit:12,pgsurface_check:12,pgsurface_lock:13,pgsurface_lockbi:13,pgsurface_locklifetim:13,pgsurface_new:12,pgsurface_prep:13,pgsurface_typ:12,pgsurface_unlock:13,pgsurface_unlockbi:13,pgsurface_unprep:13,pgsurfaceobject:[1,12,13],pgvidinfo_asvidinfo:5,pgvidinfo_check:5,pgvidinfo_new:5,pgvidinfo_typ:5,pgvidinfoobject:5,pgyam:[0,5],phase:[69,70],phi:36,photo:44,photograph:56,physic:[17,23,32,61,63,86,88,89],pi:[24,89],pick:[23,44,56,59,62,64],pictur:[31,63],pie:30,piec:[29,84],pile:26,pinch:25,pink1:21,pink2:21,pink3:21,pink4:21,pink:21,pipe:23,pitch:[37,51,62],pitch_bend:37,pixel2d:65,pixel3d:65,pixel:[16,17,18,20,22,23,24,26,28,29,30,31,35,41,45,48,51,56,58,59,63,65,85,88,89],pixel_arrai:42,pixelarrai:[16,26,42,51],pixelcopi:[26,42,43,52],pixelformat:18,pixels2d:[52,65],pixels3d:[52,65],pixels_alpha:[52,65],pixels_blu:52,pixels_green:52,pixels_r:52,pixels_within_threshold:56,place:[1,23,25,27,29,34,36,37,39,42,44,45,46,50,51,52,53,58,62,63,64,65,68,84,87,88],placehold:44,placement:44,plai:[8,16,19,23,26,32,37,40,47,58,62,63,64,66,70,74,84,86,89],plain:46,plan:[51,63],plane:[41,51],plant:65,platform:[16,18,23,24,25,30,33,35,37,38,41,44,46,53,54,57,58,59,63,84,86,88],playabl:49,playback:[19,26,38,40,63],player1:[61,89],player2:89,player:[26,50,58,61,62,64,68,70,73,74,84,88,89],playerimag:62,playerpo:62,playersprit:89,playmu:26,playstat:32,pleas:[23,44,84],plenti:61,plot:61,plu:[28,29,33,37,44,64],plug:[25,32],plum1:21,plum2:21,plum3:21,plum4:21,plum:21,pm_recommended_input_devic:37,pm_recommended_output_devic:37,pmdeviceid:37,png:[26,31,58,63,65,66,67,68,69,70,75,76,77,78,84,86,87,88,89],pnm:31,po:[25,27,35,40,50,58,62,66,72,73,80,81],point:[15,17,19,20,22,24,26,28,29,30,35,36,37,45,48,50,56,57,62,63,64,65,67,72,84,89],pointer:[9,12,58,84],polar:36,polish:[22,63],poll:[25,27,37,84],polygon:[24,30],pong:[61,86,89],poor:61,poorli:61,pop:44,popular:[26,32,66],port:[18,26,37,44,48],portabl:[33,37,63],portion:[12,23,45,48,51,56,63,64],portmidi:37,posit:[1,9,17,19,22,23,24,25,26,28,29,30,32,33,35,38,39,40,44,45,48,50,51,53,55,57,58,62,63,64,66,68,69,84,85,87,88,89],possibl:[18,23,28,29,31,32,50,51,57,58,61,63,65,67,68],post:[25,27,38,47,54],potenti:[31,64,84,88],powderblu:21,power:[18,32,33,38,64,74],ppem:29,ppm:[31,46],pr:39,practic:[84,86],pre:[20,29],pre_init:38,prealloc:51,prebuilt:16,preced:[35,68],precis:[23,38,51,65,84],predecessor:[65,84],predefin:[25,46],predomin:43,prefer:[23,30,31,33],prefix:58,prematur:84,premul_alpha:20,prepar:[26,40,66],present:[44,48,60,63,64],preserv:[20,44,45,51],preset:[22,38],press:[26,32,33,39,47,57,58,62,70,71,84],pressur:55,pretend:62,pretti:[59,62,64,65,84,85,88,89],prevar:84,prevent:[25,89],prevent_display_stretch:23,previou:[1,23,29,38,39,48,50,54,56,58,62,64,65,69,70,72,73,85,89],previoulsi:40,previous:[18,20,25,28,29,31,38,40,44,59,85],primari:39,primarili:[29,44,48],prime:48,primer:65,primit:30,principl:[88,89],print:[25,28,32,33,36,39,44,45,46,57,58,59,62,66,68,70,71,72,73,76,84,86,89],printboard:[73,81],printf:[67,75],prior:23,prioriti:18,privat:[51,58],probabl:[26,62,64,68,84,85],problem:[43,44,58,61,69,84,86],procedur:[67,68],process:[18,25,26,27,32,46,52,53,54,60,62,67,68,70,72,73,77,84],processor:[54,56],procur:18,produc:[29,84],product:[36,61],profil:[23,84],profit:18,program:[16,19,23,25,27,32,33,37,38,41,44,45,53,54,58,61,62,63,64,65,66,67,68,69,70,71,73,74,84,85,86,87,88],programm:[63,64,84,86,87],programmat:44,progress:43,project:[26,36,61,63,67,68,69,70,71,72,73,76,77,78,79,80,81,84,86,87,89],prolog:73,promis:[58,62],prompt:[44,63,65],proper:[29,33,38,39,64,65],properli:[10,16,25,39,53,58,62,64,65,84],properti:[17,25,29,39,50,52],propos:63,protect:[26,58],protocol:[2,16,43,51],proud:62,provid:[16,18,20,23,26,27,28,29,33,35,36,38,41,42,44,45,50,51,53,54,56,57,58,67,84,86,87],proxi:[2,17],ps4:32,ps:[26,32],pseudo:87,pt:56,pull:[18,58,66],pummel:[58,66],pump:[25,27,32,88,89],punch:[58,63,66],punch_sound:[58,66],punchabl:58,punctuat:28,pure:[44,51],purpl:21,purple1:21,purple2:21,purple3:21,purple4:21,purpos:[1,18,48,57,61],push:[33,71,88],pushabl:32,put:[32,46,54,60,61,63,64,66,68,85,86,87],puyopuyo:[67,75],pxarrai:42,py:[16,23,26,44,46,53,56,61,62,63,65],py_buff:[1,17],pybuf:1,pybuffer_releaseproc:1,pycdio:19,pygam:[2,11,15,21,68,69,70,71,72,73,74,75,76,77,78,79,80,81,86,87,89],pygame_blend_add:12,pygame_blend_alpha_sdl2:[12,44],pygame_blend_max:12,pygame_blend_min:12,pygame_blend_mult:12,pygame_blend_premultipli:12,pygame_blend_rgba_add:12,pygame_blend_rgba_max:12,pygame_blend_rgba_min:12,pygame_blend_rgba_mult:12,pygame_blend_rgba_sub:12,pygame_blend_sub:12,pygame_bufferproxi:2,pygame_camera:44,pygame_displai:44,pygame_force_scal:44,pygame_freetyp:[7,28,44],pygame_hide_support_prompt:44,pygame_mix:8,pygameapi_base_numslot:11,pygamevers:44,pyobject:[1,2,3,4,5,6,7,8,9,10,12,13],pyopengl:[26,31,63],pypi:42,pyportmidi:37,pysdl:[63,84],pythagorean:[36,69],python26:26,python2:26,python3:18,python:[1,2,3,4,5,6,7,8,9,10,12,13,15,16,17,18,19,22,26,28,29,31,38,43,44,45,50,51,53,58,60,61,62,64,66,67,68,85,86,87],pytypeobject:[2,3,4,5,8,9,12,13],pyunicode_asencodedstr:[10,44],q:33,qce:18,quadrant:24,quadruplet:[24,30],quake3:63,qualiti:[26,44,58,63],quaternion:67,queri:[23,37,46,59],query_imag:[18,57],question:[33,62,84],queu:[25,38,40],queue:[6,18,23,32,33,34,37,38,39,40,47,54,58,63,84,88],quick:[25,26,32,51,53,60,64,65,84,88],quicker:[50,51,56,64],quickest:51,quickli:[31,58,59,62,63,64,65,84],quietli:25,quit:[1,19,22,23,24,25,26,28,29,32,37,38,39,44,47,51,53,57,58,62,63,65,66,67,68,69,70,71,72,73,75,76,77,78,79,80,81,85,88,89],quiz:73,quot:33,quotedbl:33,r:[9,20,26,30,32,33,36,42,43,51,56,64,65,71,72,73,79,80,81],r_margin:[72,73,80,81],radial:[36,65],radian:[24,30,36,87,89],radii:[24,30],radiu:[24,30,50],radom:74,rais:[1,2,3,4,5,6,7,8,9,10,15,17,20,22,23,24,25,26,28,29,30,31,33,35,36,37,38,40,43,44,45,46,48,49,50,51,52,56,57,60,65,86,89],ramp:23,ran:85,rand:89,randint:[73,81,89],random:[53,61,73,74,81,86,89],randomli:73,rang:[20,23,24,25,28,29,32,35,36,37,38,42,44,47,50,57,62,63,65,68,71,72,73,79,80,81],rank:84,rapid:32,rapidli:[33,62],rare:[44,51,84],rate:[38,40,50,69,84],rather:[28,29,30,33,44,50,54,56,69,85,87],ratio:[45,50],raw:[17,31,42,43,51,52,65],rb:46,re:[22,26,29,44,56,59,61,62,64,71,85,87,88],reach:63,read:[10,17,20,25,26,29,37,39,46,48,50,51,61,62,65,84],readabl:[20,38,68,86],readi:[18,22,32,48,53,57,58,62,63],readlin:22,readm:16,readonli:50,real:[25,28,29,37,38,51,57,59,62,64,70,84],realist:[86,89],realiti:59,realiz:[63,84],realli:[23,41,56,58,59,62,63,64,65,70,85,87,88],realtim:[51,63,65],reason:[23,27,28,29,38,39,56,57,61,62,64,84,87],rebel:63,rebind:47,recalcul:29,recap:61,receiv:[23,27,32,33,39,47,84],recent:[58,63,64,65],reciev:23,recogn:[17,25,29,43,45,56],recogniz:31,recommend:[23,25,27,28,50,51],recommended_input_devic:37,recommended_output_devic:37,recompil:89,record:[18,29,52,53,72,84],recreat:[26,50,53],rect1:45,rect2:45,rect:[0,16,24,29,30,33,35,41,45,48,50,51,56,57,58,62,63,64,66,71,72,73,79,80,81,86,87,88,89],rect_area_pt:56,rect_list:50,rect_sequ:45,rectangl:[9,16,23,24,26,28,29,30,33,45,48,50,51,56,64,68,84,85,87,89],rectangle_list:23,rectangular:[9,29,30,35,42,48,50,51,62,63,71,84],rectstyl:84,red1:21,red2:21,red3:21,red4:21,red:[1,18,20,21,23,24,31,42,50,51,52,65,68,69,70,71,72,73,76,77,78,79,80,81,85],redimg:65,redistribut:18,redraw:[41,62],redrawn:[23,41],reduc:[29,38,64,88],reentrant:53,ref:[70,78],refcount:10,refer:[1,13,17,23,24,31,33,35,42,46,47,49,51,52,57,58,59,62,63,64,65,68,69,70,71,72,73,84,88],referenc:[52,58,64,65],reflect:36,reflect_ip:36,regard:[24,68],regardless:[28,44],region:[31,51,56,86],regist:[1,44,46,87],register_quit:44,registri:37,regular:[16,23,24,28,40,41,50,51,56,64],regularli:32,reinit:[88,89],reiniti:38,reinitialis:32,rel:[25,32,37,39,40,41,48,50,61,86],relat:[1,23,29,34,39,43,47,50,84],relationship:50,relative_mous:48,releas:[1,13,17,18,23,29,30,32,33,37,39,42,44,46,51,58,63,84,86,88,89],release_buff:1,relev:[29,84],reli:[9,88],reliabl:[18,23,37,84],remain:[20,40,45,51,52,85],remap:[42,47],rememb:[25,39,50,51,59,61,63,64,65,68,73,84,86,87],remind:68,remov:[13,17,18,25,27,28,32,36,48,50,56,58,64,89],remove_intern:64,remove_sprites_of_lay:50,renam:47,render:[16,23,24,26,32,41,48,50,58,63,66,68,69,70,71,72,73,76,77,78,79,80,81,84,85,87,88],render_raw:29,render_raw_to:29,render_to:29,renderclear:[50,64],renderplain:[50,58,64,66,89],renderupd:[26,50,64],renderupdatesdraw:64,repaint:[25,27,50],repaint_rect:50,repcolor:42,repeat:[23,33,35,38,40,44,61],repeatedli:[50,51,54,56,58],replac:[1,23,27,29,38,42,43,44,51,52,54,62,65,68],report:[26,32,44,56,84],repositori:[44,84],repr:44,repres:[1,12,13,14,16,17,19,20,22,23,24,25,29,31,32,33,35,38,39,40,41,44,45,47,48,52,54,56,58,62,63,64,65,84,87],represent:[1,4,9,16,21,24,30,42,56,58],reproduc:18,request:[1,23,26,28,29,35,38,49,51,52,59],requir:[17,18,23,25,26,28,31,33,35,36,37,38,44,45,46,47,50,51,55,56,59,61,62,63,64,65,68,70,84,85,86,88],resampl:38,rescal:26,resembl:[26,43,52],reserv:[25,37,38],reset:[29,32,37,38,40,50,58,89],resist:84,resiz:[16,23,25,26,35,45,48,56,58,85],resolut:[23,29,41,51,54,56,58,59],resolv:[46,68,87],resourc:[26,38,40,44,59,61,66,87],respect:[1,22,23,24,33,35,36,46,50,51],respond:[25,27,62],respons:53,rest:[19,25,27,57,58,62,63,65,84],restart:[40,86],restor:[23,25,48],restrict:51,result:[20,24,28,29,35,36,37,40,42,51,53,56,58,62,63,64,65,68,69,70,73,76,84,89],resultscreen:[69,70,77,78],resum:[19,38,40],retail:63,retain:[18,51],retrac:23,retriev:[14,36,38,46,84,88],reus:[18,86],reusabl:86,rev:44,revers:[1,58,63,65,89],revis:[44,61,63],reward:[58,63],rewind:40,rewound:26,rgb:[18,20,23,24,28,30,31,41,43,51,57,58,63,65,84,85],rgba:[1,4,20,23,24,30,31,51],rgba_premult:31,rgbarrai:65,rgbx:31,rich:58,rid:57,ridicul:61,right:[20,23,24,25,29,30,32,33,35,38,42,44,45,47,50,51,58,62,63,64,65,66,67,68,69,70,71,72,73,75,76,77,78,79,80,81,84,87,88,89],rle:51,rleaccel:[51,58,66],rleaccelok:51,road:62,roll:[32,39,64],root:[36,53,84],rosybrown1:21,rosybrown2:21,rosybrown3:21,rosybrown4:21,rosybrown:21,rotat:[25,26,29,36,48,50,56,58,63,66],rotate_i:36,rotate_ip:36,rotate_ip_rad:36,rotate_rad:36,rotate_rad_ip:36,rotate_x:36,rotate_x_ip:36,rotate_x_ip_rad:36,rotate_x_rad:36,rotate_x_rad_ip:36,rotate_y_ip:36,rotate_y_ip_rad:36,rotate_y_rad:36,rotate_y_rad_ip:36,rotate_z:36,rotate_z_ip:36,rotate_z_ip_rad:36,rotate_z_rad:36,rotate_z_rad_ip:36,rotozoom:56,round:[20,24,37,38,88],routin:[1,18,25,28,29,51,56,58,59,68],row1:65,row2:65,row:[35,42,51,65],royalblu:21,royalblue1:21,royalblue2:21,royalblue3:21,royalblue4:21,rr:20,rrggbb:20,rrggbbaa:20,rt:32,rudder:32,rudimentari:26,ruin:65,rule:[59,70,73,74,89],rumbl:[32,47],run:[23,25,26,31,32,38,44,53,54,56,58,59,62,63,64,65,66,67,84,85,89],run_speed_test:26,run_test:53,run_tests__test:53,rundown:26,runner:53,runtim:[23,38,54,56,63],runtimeerror:[29,44],rw:10,rwobject:0,rx:30,ry:30,s:[9,12,13,15,17,20,22,23,24,25,26,28,29,31,33,35,36,37,38,39,40,41,42,43,44,45,46,47,48,50,51,54,58,59,61,63,64,65,67,68,69,70,71,74,84,85,86,87,88,89],saddlebrown:21,safe:[19,23,25,28,29,32,37,38,42,44,47,50,51,57,60],sai:[51,61,62,64,68,84],said:[24,61,68,70,74,84,85],sake:85,salmon1:21,salmon2:21,salmon3:21,salmon4:21,salmon:21,sam:63,same:[10,18,19,20,22,23,24,25,28,29,30,31,32,33,35,36,38,39,42,43,44,45,47,50,51,52,54,56,57,58,59,62,63,64,65,67,68,70,71,72,73,84,85,89],sampl:[16,20,38,40,56,57,62,64,65,88],san:29,sandybrown:21,satisfactori:86,satisfi:23,satur:18,sauf:35,save:[16,18,31,61,63,84],save_extend:31,saw:[57,58,62],scalabl:29,scalar:[36,58],scale2x:56,scale:[18,23,24,26,29,31,35,36,44,48,50,56,58,63,65,66],scale_to_length:36,scaledown:65,scaler:26,scaletest:26,scaleup:65,scan:19,scancod:[25,33],scanf:[67,75],scanlin:62,scant:26,scene:57,school:39,scipi:65,scope:[42,65],score:[26,50,61,70,89],scoreboard:61,scoreup:61,scrap:[16,46],scrap_bmp:46,scrap_clipboard:[26,46],scrap_pbm:46,scrap_ppm:46,scrap_select:46,scrap_text:46,scratch:64,scratchi:38,screen:[1,5,16,22,24,25,26,28,31,32,33,34,39,44,45,46,48,50,51,57,58,59,61,63,64,65,66,67,68,69,70,71,72,73,75,76,77,78,79,80,81,84,85,87,88,89],screen_dim:26,screen_height:23,screen_rect:50,screen_width:23,screensav:[23,44,69],screenshot:58,script:[29,60,63,66],scroll:[25,26,39,51,62,63,64,84],scrollabl:26,scroller:84,scrollock:33,sdl1:[19,23,41,51],sdl2:[25,32,38,39,44,47,51,55],sdl:[1,3,6,8,10,12,13,23,25,26,27,32,33,38,41,43,44,47,48,56,59,63,84],sdl_audiodriv:44,sdl_delai:54,sdl_event:6,sdl_gfx:30,sdl_hint_video_allow_screensav:23,sdl_imag:[31,63],sdl_mixer:[38,40],sdl_rect:[9,12],sdl_rwop:10,sdl_surfac:12,sdl_ttf:[28,29,44],sdl_video:51,sdl_video_allow_screensav:44,sdl_video_cent:44,sdl_video_window_po:44,sdl_video_x11_net_wm_bypass_compositor:44,sdl_videodriv:[23,44],sdl_videoinfo:5,sdl_window:1,sdl_windowid:23,sdlerror:40,sdlversion:44,seagreen1:21,seagreen2:21,seagreen3:21,seagreen4:21,seagreen:21,search:[16,28,29,35,45,50,56],search_color:56,search_surf:56,seashel:21,seashell1:21,seashell2:21,seashell3:21,seashell4:21,second:[17,19,20,22,24,26,30,32,36,38,40,42,49,50,53,54,58,60,62,63,65,69,70,71,72,77,84,88,89],secondari:84,section:[19,51,58,61,62,64,65,67,68,86,89],secur:86,see:[18,19,20,23,24,26,28,29,30,31,32,33,35,36,37,38,39,43,44,45,47,50,51,52,56,57,58,60,61,62,63,64,65,84,85,87,88,89],seed:[53,65],seek:10,seem:[31,46,61,62,63,64,68,72,73,84,85,87],seemingli:61,seen:[23,61,65,88,89],segment:[24,30],select:[18,23,29,33,35,37,38,40,44,46,53,59,67,69,73,84],self:[20,32,35,36,50,51,56,57,58,62,64,66,87,88,89],sell:62,semi:[26,84],semicolon:33,semiton:37,send:[25,37,38,40,89],sens:[62,87,88,89],sensit:84,sent:[23,25,32,33,38,40],separ:[18,22,26,28,29,37,38,44,50,51,52,53,56,57,61,62,64,65,72,84,86],sequenc:[1,9,15,22,23,24,25,29,30,33,35,37,39,42,45,50,51,56,59,63,64,84,88],sequenti:24,seri:[37,63,70],serv:[27,63],server:[26,39],servic:18,session:53,set:[1,7,17,18,20,22,23,24,25,28,29,31,32,33,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,54,56,58,60,62,65,67,68,70,71,72,73,84,85,86,87,88,89],set_allow:25,set_allow_screensav:23,set_alpha:[43,51],set_at:[35,51,65,84],set_behavior:56,set_block:[25,84],set_bold:28,set_capt:[22,23,24,32,58,66,68,69,70,71,72,73,76,77,78,79,80,81,85,89],set_clip:[50,51],set_color:56,set_colorkei:[43,51,58,66,84],set_control:[18,57],set_cursor:[22,39],set_default_resolut:29,set_endev:[38,40],set_error:44,set_eventst:47,set_fullscreen:48,set_gamma:23,set_gamma_ramp:23,set_grab:[25,33,39],set_icon:[23,48],set_instru:37,set_ital:28,set_length:20,set_loc:41,set_map:47,set_mask:51,set_mod:[1,22,23,24,32,33,34,39,44,46,48,51,57,58,59,62,63,66,67,68,69,70,71,72,73,75,76,77,78,79,80,81,84,85,89],set_modal_for:48,set_num_channel:38,set_palett:[23,51],set_palette_at:51,set_po:[39,40],set_repeat:33,set_reserv:38,set_shift:51,set_smoothscale_backend:56,set_text_input_rect:33,set_tim:54,set_timing_threshold:50,set_timing_treshold:50,set_underlin:28,set_viewport:48,set_vis:[39,58,66],set_volum:[38,40],set_window:48,setcolor:35,setsurfac:35,settabl:44,setup:[22,26],sever:[16,22,23,24,26,29,38,45,50,54,59,60,62,63,64,65,84,85,89],sf:42,sfnt:29,sg:22,shade:24,shall:18,shallow:35,shape:[16,17,42,43,51,63,65,72,84],share:[16,25,28,31,32,33,38,46,48,51,52,54],sharp:24,she:85,shell:26,shift:[23,26,33,35,42,44,51,59,65],shinner:[58,59,60,62,63,64,65,84],shoot:63,shortcut:64,shorter:[23,58,65],shortest:36,shot:64,should:[18,19,22,23,25,26,28,29,30,31,32,33,35,36,37,38,42,44,45,47,50,51,54,56,58,59,61,62,63,64,65,68,69,84,85,86,87,89],shoulder:47,shouldn:88,show:[22,23,26,29,33,39,41,48,53,56,57,58,59,62,65,88,89],show_output:53,showcas:[26,84],shown:[23,25,33,41,57,62,87],shrink:[45,84,89],shrinkag:56,shrunk:51,shtml:[86,89],shut:[23,29,32,44,69],shutdown:[8,63],side:[23,24,42,45,47,58,61,63,87,88],sienna1:21,sienna2:21,sienna3:21,sienna4:21,sienna:21,sign:[17,33,37,38,39,44],signal:[25,40,85],signific:51,silenc:53,silent:[23,60,84],silver:21,similar:[29,31,32,42,49,50,51,54,58,62,64,65,85,86,88,89],simpl:[16,22,23,24,25,26,32,42,50,51,56,57,58,60,61,62,63,64,65,66,67,69,71,72,73,74,84,85,86,89],simpler:[62,63,64],simplest:[57,71],simpli:[22,25,37,41,44,50,57,58,59,62,63,65,67,84,85,87,89],simul:[58,67],simultan:[38,67],sin:[87,89],sinc:[19,23,25,31,32,36,38,39,44,48,50,51,52,54,57,58,59,60,62,63,64,65,84],singl:[17,20,22,23,24,25,28,29,30,32,33,38,40,41,42,43,45,50,51,52,53,58,60,61,62,63,64,65,67,68,69,70,71,73,85],sit:84,site:26,situat:[23,51,58,64,65],six:[38,40,61,63],sizabl:84,size:[9,17,18,22,23,24,25,26,28,29,31,35,38,39,41,42,43,45,48,50,51,52,56,57,58,59,61,62,63,65,66,67,68,69,70,71,72,73,75,76,77,78,79,80,81,84,85],sizeabl:23,sizeal:22,sizenesw:22,sizenws:22,sizeof:35,sizer_x_str:22,sizer_xy_str:22,sizer_y_str:22,skew:28,skip:[23,35,38,58],skyblu:21,skyblue1:21,skyblue2:21,skyblue3:21,skyblue4:21,sl:22,slash:[22,33],slateblu:21,slateblue1:21,slateblue2:21,slateblue3:21,slateblue4:21,slategrai:21,slategray1:21,slategray2:21,slategray3:21,slategray4:21,slategrei:21,sleep:[25,54],slerp:36,slice:[36,42,43,65,84],slight:[58,64],slightli:[20,25,26,39,40,51,54,58,64,84,85],slope:24,sloppi:26,slot:0,slow:[23,48,51,57,59,62,65,84,85],slower:[24,50,51,54,62,84],slowest:[44,51,85],small:[18,22,23,28,29,32,39,44,45,58,62,63,65,71,72,85,87],smaller:[18,23,35,38,45,51,71,72,84],smallest:[23,51,59],smart:[62,64],smooth:[28,58,84],smoother:62,smoothli:[56,62,84],smoothscal:[26,56],sn9c101:18,snapshot:57,sndarrai:[16,26,38,49,63],snow1:21,snow2:21,snow3:21,snow4:21,snow:21,so:[11,17,18,22,23,24,26,28,29,30,31,32,33,36,38,42,43,44,45,50,51,52,53,56,58,59,61,63,64,65,67,68,69,70,71,72,74,84,85,86,87,88,89],socket:[86,89],soften:65,softwar:[16,18,23,24,30,37,41,50,51,58,63,84],solarwolf:[63,84],solid:[24,28,30,50,51,52,56,65],solut:[84,85],solv:[38,61,67],some:[16,18,22,23,24,25,27,28,29,30,31,32,34,36,37,38,39,42,44,45,46,50,56,57,58,59,60,61,63,64,65,67,68,69,70,72,84,85,86,87,88,89],someimag:26,someth:[18,24,26,32,39,56,57,59,62,63,64,65,68,69,70,84,85],sometim:[22,23,27,44,64,84],somewhat:[26,64],somewher:[64,68],sonix:18,soon:[40,44,64,88],sophist:[86,87],sorri:[57,59],sort:[23,25,26,27,50,58,59,62,64,84,89],sound:[8,16,26,40,58,61,63,64,66,67,70,73,84,86],sound_array_demo:26,sour:48,sourc:[16,18,26,31,37,38,42,43,50,51,56,58,61,62,63,64,67,68,69,70,84,86,89],source_rect:50,sourcecod:[68,69,70,76,77,78],south:22,southeast:22,southwest:22,space:[20,28,29,31,33,37,42,62],sparingli:48,speak:[85,86],speaker:38,special:[18,22,23,25,33,35,38,43,50,56,58,59,62,64,65,68,84,85],special_flag:[48,50,51],specif:[23,25,28,29,33,35,38,43,46,50,51,52,57,58,59,64,65,68,70,71,72,84],specifi:[14,18,21,23,28,29,31,32,35,37,38,40,46,47,50,56,59,65,84,89],sped:24,speed:[25,26,29,44,54,62,63,64,67,68,69,70,71,72,73,75,76,77,78,79,80,81,84,85,87,88,89],spend:84,spent:[63,74,84],spheric:36,spin:[26,58,66,88,89],spite:50,split:[22,29,58,63,64,66,84],sport:63,spot:84,spread:84,spring:56,springgreen1:21,springgreen2:21,springgreen3:21,springgreen4:21,springgreen:21,sprite1:50,sprite2:50,sprite:[16,26,35,50,61,66,84,88,89],sprite_dict:50,sprite_list:50,spritecollid:[50,64,87],spritecollideani:50,spritedict:64,sprites_click:84,sqrt:[36,69],squar:[24,32,36,72],src:65,src_c:[0,11,14],srcalpha:[35,43,51,56],srccolorkei:51,srcobj:12,srcrect:[12,48],sse:[26,56],stabl:43,stack:25,stage:57,stai:[61,65,70],stand:26,standard:[1,22,25,27,41,43,44,46,50,57,58,59,61,63,64,65,68],star:26,starfield:[26,84],start:[1,17,18,19,24,25,26,29,30,32,33,35,38,39,40,42,44,45,47,50,51,57,58,59,61,62,63,64,65,66,67,69,74,84,85,86,88,89],start_angl:[24,30],start_index:65,start_po:24,start_text_input:33,startup:[8,38],state:[23,25,26,29,31,32,33,37,38,39,46,47,48,50,51,58,64,66,67,84,88,89],statement:[68,69,70,71,72,89],stationari:64,statu:[26,32,37,70],stderr:53,stdin:65,stdout:53,steelblu:21,steelblue1:21,steelblue2:21,steelblue3:21,steelblue4:21,steep:24,stencil:23,step:[16,30,32,42,58,65,68,70,73,84,88],stereo:[23,38,49],stick:[32,47,62,65,84],still:[23,31,38,39,43,46,47,48,51,57,58,61,62,63,64,65,71,72,73,84,85,88,89],stop:[1,18,19,24,30,32,33,38,39,40,44,47,54,57,62,64,84,88,89],stop_angl:[24,30],stop_rumbl:[32,47],stop_text_input:33,store:[9,22,23,25,29,30,35,50,51,52,58,62,64,68],str:[17,18,20,29,32,35,37,44,47,49,52,71,72,73,79,80,81],straight:[24,30,62,63,65,86],straighten:62,straightforward:[62,63],strang:[23,63],strateg:84,strategi:84,stream:[16,37,38,48,63],strength:[29,32,47],stress:63,stretch:[23,26,28,29],strict:[18,61],strictli:[30,85],stride:[17,42],strike:29,string:[10,15,17,18,19,20,22,23,25,28,29,31,32,33,37,38,41,44,46,48,49,51,52,53,56,68,84,86,87],strip:51,stripe:65,stroke:24,strong:29,strongli:[23,50],struct:[1,3,5,6,7,8,10,17,29,42,43,51,52],structur:[8,11,43,85,87,88],stuck:62,studi:[65,87],studio:63,stuff:[46,57,61,62,65],style:[25,26,29,32,42,63,86],style_default:29,style_norm:29,style_obliqu:29,style_strong:29,style_underlin:29,style_wid:29,sub:[50,84],subarrai:42,subclass:[2,3,4,5,6,7,8,12,13,17,20,35,45,50,51],subdirectori:[26,58],subgroup:67,subject:[23,44],submask:35,submit:84,submodul:[44,53],subpackag:53,subprocess:53,subprocess_ignor:53,subscript:[36,42],subsect:62,subsequ:57,subset:[22,23,84],substanti:84,substitut:[18,22],substr:37,subsubsurfac:51,subsurfac:[13,51,56],subtract:89,subview:42,succe:[18,23],succeed:18,success:[1,2,6,9,10,12,23,44,84],successfulli:[32,47],sudden:63,sufac:42,suffix:45,suggest:[42,58,84],suit:[27,51,59],suitabl:[23,28,29,46,63,68,86],sum:[24,74],summari:64,summer:63,suppli:[18,35,37,38,57,58,65,85],support:[1,7,17,18,19,20,22,23,24,25,26,28,29,31,32,33,35,36,37,38,39,40,41,42,43,44,47,48,49,50,51,52,54,56,57,58,59,63,84,87],suppos:[56,84],sure:[11,50,54,57,58,63,64,65,69,70,84,89],surf:[22,26,29,30,42,50,51,56],surfac:[0,1,2,11,13,16,18,20,22,23,24,26,28,29,30,31,35,36,39,41,43,46,48,50,51,57,58,59,62,63,64,66,85,89],surface_dest:50,surface_to_arrai:43,surfarrai:[16,17,26,43,49,51,52,63,84],surfdemo_show:65,surflock:0,surfobj:13,surpris:[62,63],surrog:[15,29],surround:[56,85],suspend:84,svg:31,svgalib:23,swap:[23,31,42,45],swatch:20,swig:63,switch_lay:50,swizzl:36,swsurfac:[51,84],sy:[15,44,53,62,63,67,68,69,70,71,72,73,75,76,77,78,79,80,81,86,89],symbol:33,sync:[23,25],synchron:37,synonym:25,syntax:[65,84],syntaxerror:44,synthes:37,sysfont:[28,29],sysrq:33,system:[15,16,18,19,22,23,25,26,27,28,29,32,33,36,37,39,40,44,48,49,51,52,53,59,68,70,84,85,88],system_cursor_arrow:22,system_cursor_crosshair:22,system_cursor_hand:22,system_cursor_ibeam:22,system_cursor_no:22,system_cursor_sizeal:22,system_cursor_sizen:22,system_cursor_sizenesw:22,system_cursor_sizenws:22,system_cursor_sizew:22,system_cursor_wait:22,system_cursor_waitarrow:22,systemexit:[86,89],t:[18,19,23,24,26,27,28,29,32,33,36,40,44,46,48,49,50,51,52,54,56,57,58,61,62,63,64,65,68,69,70,71,72,73,74,85,86,87,88,89],ta:61,tab:33,tabl:[23,43],tag:[40,53],taka:18,takafumi:18,take:[15,22,24,25,26,29,31,32,33,35,36,37,38,40,42,45,50,51,53,56,57,58,59,63,64,65,68,84,85,86,88,89],taken:[4,21,23,26,27,38,39,87],talk:62,tan1:21,tan2:21,tan3:21,tan4:21,tan:21,tango:29,target:[29,42,43,45,48,50,58,64,66],target_textur:48,task:[59,86],tau:24,teach:62,teal:21,technic:41,techniqu:[50,84],tell:[10,38,39,44,58,59,62,64,84,88],temp:9,temporari:[56,65],temporarili:[19,24,33,38,40,51,52],tempt:84,temptat:84,ten:54,tenni:[88,89],term:[62,64,85],termin:[1,37,44,58,68],terminolog:[39,84],terrain1:62,terrain2:62,test:[16,19,25,26,28,29,31,32,33,36,38,39,41,44,45,47,50,51,56,58,59,60,65],test_threshold_dest_surf_not_chang:56,test_util:56,testin:37,testout:37,testsprit:26,tetri:74,text:[25,26,28,29,33,46,66,68,69,70,71,84,85,87],textbitmap:32,textedit:[25,33],textinput:[25,33],textmarker_str:22,textpo:[58,66,85],textprint:32,textstr:32,textur:[30,48],textured_polygon:30,textureorimag:48,tga:[31,63],than:[16,18,19,23,24,25,26,28,29,30,31,32,33,35,36,37,38,40,44,45,47,50,51,52,54,55,56,57,58,59,60,62,63,64,65,69,70,74,85,86,87,88,89],thank:88,the_arg:12,the_dirty_rectangl:84,thei:[1,11,18,19,22,23,24,25,26,28,29,32,35,36,38,39,44,45,46,47,50,51,56,58,59,62,63,64,65,68,69,71,72,86,87,88,89],them:[16,22,24,25,26,27,31,33,34,35,38,42,44,49,50,51,52,57,58,59,62,63,65,71,84,85,86,87,88,89],themselv:[51,61,64,85],theorem:36,theori:18,therefor:[24,30,35,50,64,84,87],theta:[35,36],thi:[1,2,3,4,5,6,7,9,10,11,12,13,16,17,18,19,20,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,72,73,74,84,85,86,87,88,89],thick:[24,28],thickarrow_str:22,thin:58,thing:[19,25,27,40,44,57,58,59,60,61,62,63,64,65,85,87],think:[18,23,62,64,65,70,74,84,89],third:[17,18,22,30,36,62,63,65,71,85],third_surfac:56,thirteen:16,thistl:21,thistle1:21,thistle2:21,thistle3:21,thistle4:21,thorough:89,those:[16,18,22,23,24,25,26,28,29,39,42,43,50,57,61,62,64,65,84,86,87,88,89],though:[18,23,30,37,38,43,53,61,65,85,86,87,88,89],thought:84,thousand:49,thread:[10,18,25,26,27,28,30,38,39,50,53,57],three:[36,38,44,51,52,64,65,68,84,85,88],threshold:[35,42,50,56],threshold_behavior_from_search_color:56,threshold_color:56,throttl:32,through:[2,18,25,27,29,35,37,38,44,50,51,58,61,62,63,64,74,84,85,88],throughout:34,thrown:[56,89],thru:63,thu:[36,42,87],thumbnail:26,ti:40,tick:[22,24,32,39,54,58,66,69,71,72,73,77,79,80,81,89],tick_busy_loop:54,tie:[57,72],tif:31,tiff:[31,46],tile:62,time:[14,16,18,19,22,23,24,25,26,28,29,32,34,37,38,39,40,44,48,49,50,51,53,56,57,58,59,61,62,63,64,65,66,67,68,69,70,71,72,73,74,77,78,79,80,81,84,85,86,87,89],time_m:50,time_out:53,time_proc:37,timeout:25,timer:[37,54],timer_resolut:[34,54],timestamp:37,tini:[23,84],tip:[16,64,84],titl:[23,48,58,63,68],tl:89,to_surfac:[35,48],todo:64,togeth:[33,38,56,61,63,65,86],toggl:[22,47],toggle_fullscreen:23,toler:32,tom:[86,89],tomato1:21,tomato2:21,tomato3:21,tomato4:21,tomato:21,tomchanc:[86,89],tompong:[61,89],tone:37,too:[25,27,29,42,45,50,51,53,58,62,65,67,68,69,73,84,85],took:63,tool:[26,64,67,87],top:[16,23,24,26,28,29,31,35,38,39,45,50,51,62,63,67,68,69,70,71,72,73,75,76,77,78,79,80,81,84,85,86,89],topic:16,topleft:[35,42,45,50,56,58,62,66,89],toplevel:38,topmost:50,topright:[45,89],tort:18,tortur:84,tostr:31,total:[38,43,44,53,62,68,86],touch:[25,32,84],touch_id:25,touchid:55,toward:[23,61,63],tp:[67,75],tprint:32,tr:89,traceback:[65,86],track:[16,19,50,54,57,62,64,84],trackbal:[25,47],tradition:22,trail:[53,63],train:84,trait:[68,74],transfer:[16,46,56,61,65],transform:[16,18,29,57,58,62,63,65,66],transform_test:56,translat:[9,15,26,29,33,42],transluc:84,transmiss:37,transpar:[23,24,26,28,29,31,35,43,48,51,52,56,58,62,63,84,86],transpos:42,travel:89,treat:[23,29,32,52,65],tree:57,trend:63,tri:[44,62,63,84,86],tri_left:22,tri_right:22,trial:[74,84],triangl:[24,26,30,32],trick:89,tricki:[64,65,84],trickier:65,trigger:[32,33,39,40,47,68,70],trigon:30,trigonometri:87,triplet:[23,24,30,58],truetyp:[16,28,58,63],truncat:[24,30,38,45,65],truth:64,ttf:[28,29,68,69,70,71,72,73,76,77,78,79,80,81],tune:[29,64],tupl:[9,17,19,20,22,23,24,28,29,30,31,32,35,36,37,38,39,42,44,45,47,49,50,51,52,53,62,65,84],turn:[29,37,56,58,62,64,66,84],turquois:21,turquoise1:21,turquoise2:21,turquoise3:21,turquoise4:21,turtl:68,tutori:[26,61,63,66,73,74,85,89],tweak:64,twice:[50,56,65],twitch:84,two:[1,16,18,19,22,23,24,25,26,28,29,30,32,33,35,36,37,38,42,43,45,47,49,50,53,54,56,58,62,63,64,65,70,71,72,73,84,85,87],tx:30,ty:30,type1:29,type42:29,type:[1,2,3,4,5,6,7,8,9,10,12,13,15,16,17,20,22,23,24,25,27,28,29,30,31,32,33,34,35,37,38,39,40,41,42,44,45,46,47,49,50,51,52,54,56,57,58,59,62,63,65,66,67,68,69,70,71,72,73,75,76,77,78,79,80,81,84,85,87,88,89],typeerror:[24,28,43,45,50],typelist:25,typestr:17,typic:[18,23,37,51,58],u0001:28,u4:17,u:[15,17,33,41],u_margin:[73,81],uc:[15,28,29],ucs4:29,ucs_4:28,uffff:[15,28],ufo:63,ufunc:65,ugh:84,ui:26,uint32:1,uint8:[1,4],uint:65,uklinux:[86,89],ultim:74,unabl:[31,46,64],unaccept:84,unalt:[44,84],unari:20,unavail:[23,28,58,84],unchang:[15,20,23,29],uncommit:44,uncommon:58,uncompress:[31,38],undefin:[29,65],under:[16,37,39,40,63,84,86,89],underli:[29,32,37,44],underlin:[28,29,40],underline_adjust:29,underneath:65,underscor:[33,58],understand:[16,41,59,61,62,63,64,65,68,69,70,71,84,85,86,88,89],understood:71,undesir:24,unencod:44,unfamiliar:[62,84],unfil:[30,35],unfilt:56,unfortun:[53,84],unicod:[15,25,28,29,33,38,44,46,51],unicode_escap:44,unicodeencodeerror:[29,44],unicodeerror:28,unind:32,uniniti:[18,19,23,28,32,37,38,44,47],union:[45,64,84],union_ip:45,unional:45,unionall_ip:45,uniqu:[32,48,50,51,62,67,72,74],unit:[28,29,44,51],uniti:[67,75],unix:[22,23,63,84],unknown:[23,25,28,32],unless:[7,19,23,29,31,41,46,51,54,56,58,62,64,68,69,84,87,88],unlik:[38,43,51,65,88],unload:40,unlock:[24,51,84],unmap:43,unmap_rgb:[20,24,43,51,52],unmodifi:18,unnorm:67,unnot:33,unpack:[20,39],unpaus:[19,38,40],unplay:[23,63],unpredict:29,unpunch:[58,66],unreal:[63,67,75],unrealist:89,unrecogn:[28,31],unrel:23,unscal:29,unset:[29,35,51,89],unsetcolor:35,unsetsurfac:35,unsign:[1,17,20,35,38,51,65],unspecifi:29,unstructur:51,unsupport:[18,40],until:[18,23,24,25,27,32,35,37,40,47,51,54,57,62,64,66,84,85,88],untransform:29,unus:[31,38],unwieldi:84,up:[18,22,23,24,25,27,32,33,37,38,39,40,42,44,47,50,51,58,60,62,64,65,71,72,73,80,81,84,85,86,87,88],updat:[12,20,23,24,25,32,36,41,44,45,47,48,50,54,59,60,61,62,63,64,66,68,69,70,71,72,73,76,77,78,79,80,81,84,85,87,88,89],update_rect:26,upon:89,upper:[25,29,32,51,57],us:[0,1,9,10,11,14,15,16,17,19,20,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,53,54,56,58,59,61,62,63,64,65,66,67,68,71,72,85,86,87,88,89],usabl:[20,31,57],usag:[23,27,37,51,53],usb:37,use_alpha:26,use_arraytyp:[49,52],use_bitmap_strik:29,use_fastrendergroup:26,use_stat:26,use_valu:45,user:[6,16,18,23,24,25,27,32,33,37,44,46,51,53,58,61,62,63,64,65,67,72,84,85,87],userev:[25,38],userevent_dropfil:25,userrect:84,usr:[26,28,66,85,86,87],usual:[23,25,28,29,32,38,44,50,51,58,59,60,62,63,64,65,70,84,86],utf8_str:46,utf:[15,29,46],util:[63,74,84],uxxxxxxxx:[15,29],uyvy_overlai:41,v1:44,v2:[1,40],v3:17,v4l2:[18,57],v:[17,20,33,36,41],val1:1,val2:1,val:[1,65],valid:[17,23,38,39,41,51,57,64],valu:[1,4,9,10,17,18,19,20,22,23,24,25,26,28,29,30,31,32,33,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,56,58,59,62,64,65,68,69,71,72,84,85,88,89],value_to_set:44,valueerror:[17,22,24,26,29,30,33,35,36,43,46,49,51,52,57,65],vanish:84,vari:71,variabl:[17,22,23,28,37,40,44,57,58,63,64,65,69,70,71,74,89],variant:22,varieti:[25,63,70,84],variou:[1,16,22,25,26,34,84,89],ve:[24,32,58,61,62,63,64,65,84,85,87,88,89],vec:36,vector2:[24,30,35,36,45],vector3:36,vector:[24,30,35,61,89],vectorelementwiseproxi:36,veloc:[37,69],ver:44,vera:[28,29],veri:[18,23,26,37,54,58,60,62,63,64,65,70,84,87,88,89],verifi:23,vernum:44,versatil:[47,56],version:[0,12,17,23,25,26,27,29,30,31,32,38,40,43,45,47,50,56,57,58,60,61,62,63,64,84,86,89],vertic:[18,23,24,26,29,30,31,39,42,56,58,65],vflip:[18,57],vgl:23,vgrade:[26,65],via:[18,23,29,35,57],vidcaptur:44,video0:[18,57],video:[23,25,26,32,44,48,51,57,59,64,84],video_mem:[23,59],videocaptur:[18,57],videoexpos:[23,25],videoinfo:[23,59],videores:[23,25],vidinfo:[23,59],view:[1,2,16,42,51],view_p:1,violet:21,violetr:21,violetred1:21,violetred2:21,violetred3:21,violetred4:21,virtual:[23,26,37,39,45],visibl:[17,22,23,39,41,50,58,59,62,63],vision:[16,18],visit:63,vista:23,visual:[70,71,72,73],visualis:87,vline:30,volatil:51,volum:[16,38,40,63],vsync:[23,48],w:[9,25,26,30,33,35,36,42,43,45,56],wa:[10,16,19,20,22,23,24,25,26,27,31,32,33,35,37,38,39,40,42,43,44,47,54,57,58,62,63,64,65,68,70,73,84,86,88],wai:[18,23,24,25,26,28,29,31,32,33,38,39,43,44,47,48,50,53,58,60,61,62,63,64,65,71,85,87,88,89],wait:[22,23,25,27,32,37,39,54,58,84],waitarrow:22,walk:[58,66],wall:[36,57,89],want:[18,20,23,25,27,31,32,33,36,44,50,51,54,56,57,58,59,61,62,63,64,65,67,68,84,85,86,87,88,89],wargam:84,warn:[44,48,58,66],warranti:18,warrior:63,was_init:29,wasn:63,wast:[84,87],watch:[16,57,61,85],wav:[38,40,46,58,66],wave:49,wayland:[22,23],we:[22,24,26,32,56,57,58,60,62,63,64,65,67,68,69,70,71,72,73,74,84,85,86,87,88,89],weak:[13,17,84],web:[26,66],webcam:18,webp:31,websit:63,week:63,weight:[42,65],weird:33,welcom:44,well:[1,2,13,22,24,27,30,31,33,39,42,44,47,51,56,61,62,63,64,65,84,89],were:[1,11,23,25,28,33,50,53,62,63,64,69,84,86,89],west:22,what:[16,20,22,23,24,26,28,32,38,39,44,46,50,57,58,59,60,61,63,64,65,68,69,71,74,85,86,88,89],whatev:[50,57,58,61,64,84],wheat1:21,wheat2:21,wheat3:21,wheat4:21,wheat:21,wheel:39,when:[13,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,37,38,39,40,41,42,44,45,46,49,50,51,52,53,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,73,74,84,85,87,88,89],whenev:[23,39,44,65],where:[11,16,17,19,20,22,23,24,25,26,29,30,33,35,36,38,39,40,41,42,44,46,47,50,51,53,56,57,58,62,64,65,68,84,85,88,89],wherea:[23,87],wherev:65,whether:[18,23,25,26,28,29,35,38,39,45,46,48,56,61,71,72,84,85],which:[1,13,15,17,18,20,22,23,24,25,26,28,29,31,32,33,35,36,37,38,39,40,42,44,45,46,47,49,50,51,52,53,54,56,58,59,60,61,62,63,64,65,67,68,69,70,71,72,73,74,85,86,87,88,89],whiff:[58,66],whiff_sound:[58,66],whilst:23,white:[21,22,24,32,35,42,57,58,68,69,70,71,72,73,76,77,78,79,80,81,85],whitesmok:21,whitespac:61,who:[16,48,61,62,64,84,89],whole:[23,24,37,44,62,84,87],whoop:62,whose:[24,55],why:[44,63,70,74,87],wide:[24,28,29,35,44,62,63],wider:18,widget:26,width:[9,18,22,23,24,26,28,29,31,32,35,41,42,45,48,50,51,56,59,62,63,67,68,69,70,71,72,73,75,76,77,78,79,80,81,84],wiki:39,wikipedia:36,win32:37,win:[1,58,66,73],windib:23,window:[1,5,16,18,25,26,27,29,32,33,34,37,39,44,46,48,51,58,59,62,63,68,69,84,85,88],window_surfac:23,windowclos:25,windowent:25,windowev:23,windowevent_minim:23,windowexpos:25,windowfocusgain:25,windowfocuslost:25,windowhidden:25,windowhittest:25,windowleav:25,windowmaxim:25,windowminim:25,windowmov:25,windowpos_cent:48,windowpos_undefin:48,windowres:25,windowrestor:25,windowshown:25,windowsizechang:25,windowtakefocu:25,wire:32,wireless:32,wisdom:65,wise:[29,65],wish:86,within:[13,17,22,29,33,35,44,50,51,56,68,74,84],without:[18,22,23,24,29,38,42,45,48,50,51,52,58,59,62,63,64,65,69,70,72,88,89],wm:[23,59],won:[40,50,58,61,62,64,65,84,86,87,88],wonder:[57,84],word:[29,46,54,62,64,88],word_wrap:29,wordwrap:28,work:[18,19,20,22,23,24,25,26,28,29,30,31,32,34,35,37,38,42,43,46,50,51,52,53,56,57,58,59,61,62,63,64,65,68,69,85,87,89],world:[57,68,69,70,74,76,77,78,84],worri:[26,48,50,64,65,74,84],wors:[58,84],worst:61,worth:54,would:[17,22,24,25,28,35,36,38,44,50,51,56,57,58,60,61,62,63,64,65,84,85,87,88,89],wow:68,wrap:[2,5,10,17,22,30,42,51,63],wrapper:[10,84],wrestl:26,writabl:17,write:[1,10,17,26,37,51,61,63,67,84,86,87],write_short:37,write_sys_ex:37,written:[16,24,60,61,63,64,84,86,87],wrong:[38,65,84],wrote:84,www:[70,78,86,89],x00:[15,28],x10:37,x11:[23,25,37,39,44,46,48],x12:37,x13:37,x1:[24,30,45],x2:[24,30,45],x360:32,x3:[24,30],x4:84,x7d:37,x86:56,x:[2,3,5,6,7,8,9,12,13,22,23,24,25,26,28,29,30,32,33,35,36,37,39,42,44,45,46,47,48,49,50,51,52,55,58,59,62,68,69,70,72,73,76,77,78,80,81,84,85,87,89],x_offset:35,x_scale:48,xbm:22,xbox:[32,47],xf0:37,xf7:37,xfade:65,xor:22,xormask:[22,39],xpm:31,xx:22,xxx:22,xxxx:22,xxxx_test:53,xxxxx:22,xy:[36,89],y1:[24,30,45],y2:[24,30,45],y3:[24,30],y:[9,20,22,23,24,25,28,29,30,32,33,35,36,39,41,42,44,45,47,48,49,50,51,52,55,58,62,66,68,69,70,72,73,77,78,80,81,84,85,87,88,89],y_offset:35,y_scale:48,ye:[65,67,85],yeah:71,year:[63,74,84],yellow1:21,yellow2:21,yellow3:21,yellow4:21,yellow:21,yellowgreen:21,yet:[29,48,65,84,88],you:[11,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,36,37,38,39,40,41,42,44,46,50,51,54,56,57,58,59,60,61,63,64,65,67,68,71,72,74,85,86,87,88,89],your:[16,18,19,22,23,25,26,27,28,30,31,33,37,38,44,46,54,56,57,58,59,60,61,63,65,67,70,85,86,87,88,89],yourself:[28,50,58,63,65,86,87],yup:84,yuv:[18,41,57],yuy2_overlai:41,yv12_overlai:41,yvyu_overlai:41,z:[33,36,87,89],zero:[19,20,24,28,29,36,37,38,59,64,65,89],zine:63,zip:84,zoom:26},titles:["pygame C API","High level API exported by pygame.base","Class BufferProxy API exported by pgyame.bufferproxy","API exported by pygame.cdrom","Class Color API exported by pygame.color","API exported by pygame.display","API exported by pygame.event","API exported by pygame._freetype","API exported by pygame.mixer","Class Rect API exported by pygame.rect","API exported by pygame.rwobject","Slots and c_api - Making functions and data available from other modules","Class Surface API exported by pygame.surface","API exported by pygame.surflock","API exported by pygame.version","File Path Function Arguments","Pygame Front Page","pygame.BufferProxy","pygame.camera","pygame.cdrom","pygame.Color","Named Colors","pygame.cursors","pygame.display","pygame.draw","pygame.event","pygame.examples","pygame.fastevent","pygame.font","pygame.freetype","pygame.gfxdraw","pygame.image","pygame.joystick","pygame.key","pygame.locals","pygame.mask","pygame.math","pygame.midi","pygame.mixer","pygame.mouse","pygame.mixer.music","pygame.Overlay","pygame.PixelArray","pygame.pixelcopy","pygame","pygame.Rect","pygame.scrap","pygame._sdl2.controller","pygame.sdl2_video","pygame.sndarray","pygame.sprite","pygame.Surface","pygame.surfarray","pygame.tests","pygame.time","pygame._sdl2.touch","pygame.transform","Pygame Tutorials - Camera Module Introduction","Pygame Tutorials - Line By Line Chimp Example","Pygame Tutorials - Setting Display Modes","Pygame Tutorials - Import and Initialize","Making Games With Pygame","Pygame Tutorials - Help! How Do I Move An Image?","Pygame Intro","Pygame Tutorials - Sprite Module Introduction","Pygame Tutorials - Surfarray Introduction","pygame/examples/chimp.py","Author: Youngwook Kim (Korean)","Author: Youngwook Kim (Korean)","Author: Youngwook Kim (Korean)","Author: Youngwook Kim (Korean)","Author: Youngwook Kim (Korean)","Author: Youngwook Kim (Korean)","Author: Youngwook Kim (Korean)","Author: Youngwook Kim (Korean)","Author: Youngwook Kim (Korean)","Author: Youngwook Kim (Korean)","Author: Youngwook Kim (Korean)","Author: Youngwook Kim (Korean)","Author: Youngwook Kim (Korean)","Author: Youngwook Kim (Korean)","Author: Youngwook Kim (Korean)","Author: Youngwook Kim (Korean)","\ud55c\uad6d\uc5b4 \ud29c\ud1a0\ub9ac\uc5bc","A Newbie Guide to pygame","Revision: Pygame fundamentals","Kicking things off","Game object classes","User-controllable objects","Putting it all together"],titleterms:{"1":[61,85,86,87,88,89],"2":[62,85,86,87,89],"3":[85,86,88,89],"4":[85,87],"5":[85,88],"6":89,"\uadf8\ub9ac\uace0":[79,80,81],"\uae30\ubc18\uacfc":76,"\uae30\ubc18\uc73c\ub85c\uc758":76,"\uae30\ubcf8":76,"\uae30\ucd08":[76,77,78],"\ub354":81,"\ubc84\ud2bc":80,"\uc0c8\ub85c\uc6b4":78,"\uc2ec\ud654":[79,80],"\uc5d0\ud544\ub85c\uadf8":82,"\uc65c":75,"\uc6c0\uc9c1\uc774\uae30":77,"\uc704\ud55c":77,"\uc774\ubca4\ud2b8":[76,78],"\uc785\ub825":78,"\uc785\ub825\uc740":78,"\uc785\ubb38":76,"\uc870\uac74":77,"\uc870\uae08":81,"\ucc98\ub9ac":[77,79],"\ucd9c\ub825":[76,80],"\ud29c\ud1a0\ub9ac\uc5bc":83,"\ud30c\uc774\uac8c\uc784":75,"\ud504\ub864\ub85c\uadf8":75,"\ud558\ud544":75,"\ud55c\uad6d\uc5b4":83,"\ud568\uc218\ud654":79,"\ud615\uc2dd\uacfc":76,"\ud654\uba74\uc774":77,"class":[2,4,9,12,36,50,58,64,87,88],"do":[62,84],"export":[1,2,3,4,5,6,7,8,9,10,12,13,14,17],"function":[11,15,59,62,65,71,86],"import":[57,58,60,65],"new":70,"while":58,A:[61,62,84,87,88],AND:63,By:58,Into:68,It:62,NO:84,On:[58,62],The:[58,62,64,85,86,89],There:84,To:62,With:61,_freetyp:7,_sdl2:[47,55],access:[42,49,52],advanc:[64,65,71,72],all:[58,62,89],alpha:[73,84],an:[17,62],anim:[69,84],api:[0,1,2,3,4,5,6,7,8,9,10,12,13,14],ar:[62,84],argument:15,arrai:[17,43,52],audio:[19,40],author:[67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82],avail:11,back:62,background:[58,62],ball:[87,89],base:1,basic:[50,57,59,68,69,70,85],bat:[88,89],blit:[62,85],bother:84,buffer:17,bufferproxi:2,bufferproxypygam:17,button:72,c:[0,1,2,3,4,5,6,7,8,9,10,12,13],c_api:11,camera:[18,57],camerapygam:18,captur:57,cdrom:[3,19],cdrompygam:19,center:58,chang:62,chimp:[58,66],clipboard:46,close:63,code:61,collis:[64,84],color:[4,20,21],colorkei:84,colorpygam:20,colorspac:57,com:[67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82],comfort:84,common:64,comput:[29,57],connect:57,constant:34,contact:[67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82],contain:44,content:61,control:[19,23,40,47,57,88],controllerpygam:47,convert:84,coordin:[45,62],copi:43,creat:[58,62],cursor:22,cursorspygam:22,da:85,data:[11,49,52],decid:59,definit:62,detect:[64,84],direct:42,dirti:84,displai:[5,23,58,59],displaypygam:23,distract:84,divers:[87,88],document:16,don:84,draw:[24,30,58],drawpygam:24,driven:68,entir:58,epilog:74,event:[6,25,27,58,68,70,84,85,88],eventpygam:25,everyth:58,exampl:[26,58,59,65,66],examplesmodul:26,extend:64,fasteventpygam:27,file:15,finish:[58,89],first:[62,86],font:[28,29],fontpygam:28,freetypeenhanc:29,friend:84,from:[11,62],front:16,fundament:85,game:[50,58,61,63,85,87],gamepad:32,gener:43,get:84,gfxdrawpygam:30,gmail:[67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82],go:62,graduat:65,graphic:41,group:64,gui:[68,76],guid:84,handl:[58,62,86],hardwar:84,help:62,here:62,hero:62,high:1,histori:[63,64],hit:89,how:[59,62],i:62,imag:[31,35,51,57,62],imagepygam:31,inform:44,init:[57,60],initi:[58,60],input:[37,55,58,62,70],interact:[25,27,32,37],interfac:52,intro:63,introduct:[57,58,59,61,63,64,65],issu:84,joystick:32,joystickpygam:32,just:62,keyboard:33,keypygam:33,kick:86,kim:[67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82],know:84,korean:[67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82],lesson:64,let:[62,89],level:[1,44],line:[58,86],list:[57,62],live:57,load:[28,29,38,58,86],localspygam:34,lock:65,loop:[58,85],main:58,make:[11,61,62],manag:84,mani:64,map:62,mask:[35,57],maskpygam:35,mathpygam:36,midi:37,midipygam:37,mix:64,mixer:[8,40],mixerpygam:38,mode:59,modul:[11,18,19,22,23,24,25,27,28,29,30,31,32,33,35,36,37,38,39,40,43,44,46,47,49,50,52,54,55,56,57,58,63,64,86],monitor:54,more:[65,84],mous:39,mousepygam:39,move:62,movement:62,multipl:62,musicpygam:40,mysteri:62,name:21,need:84,newbi:84,next:62,note:61,numer:65,numpi:65,object:[17,20,41,42,45,50,51,58,85,87,88],off:86,other:[11,65],output:[37,68,72],over:58,overlai:41,overlaypygam:41,overview:63,own:[62,64],packag:[44,53],page:16,part:84,path:15,perfect:84,pgyam:2,physic:87,pixel:[42,43,52,62,84],pixelarraypygam:42,pixelcopypygam:43,plai:38,plu:73,prepar:58,problem:64,process:[69,71],product:89,program:26,prolog:67,protocol:17,put:[58,62,89],py:[14,66],pygam:[0,1,3,4,5,6,7,8,9,10,12,13,14,16,17,18,19,20,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,84,85,88],pygameth:44,python:[63,65,84],pythoni:84,queue:[25,27],quit:60,re:84,realli:84,recogn:84,rect:[9,84],rectangular:45,rectpygam:45,refer:16,render:[28,29,64],repres:51,represent:20,resourc:[22,58,86],revis:85,rule:84,rumia0601:[67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82],rwobject:10,s:62,sampl:49,scene:58,scrappygam:46,screen:[23,62],sdl2_video:48,set:[59,69],setup:58,shape:[24,30],side:[84,89],simpl:[87,88],singl:57,six:84,slot:11,smooth:62,sndarraypygam:49,so:62,some:62,sound:[38,49],sprite:[58,64,87],spritepygam:50,src_c:[1,2,3,4,5,6,7,8,9,10,12,13],src_py:14,step:62,store:45,stream:[40,57],style:61,subsystem:84,suit:53,support:46,surfac:[12,17,42,52,56,65,84],surfacepygam:51,surfarrai:65,surfarraypygam:52,surflock:13,t:84,ta:85,tabl:61,take:62,tast:63,templat:68,test:53,testspygam:53,text:58,than:84,thei:84,them:64,thing:[84,86],threshold:57,through:17,time:54,timepygam:54,togeth:[62,64,89],top:44,touch:55,touchpygam:55,trackbal:32,transfer:31,transform:56,transformpygam:56,transpar:65,troubl:84,tutori:[16,57,58,59,60,62,64,65],type:64,unit:53,updat:58,us:[18,52,57,84],user:88,vector:[36,87],version:[14,44],versionsmal:44,video:41,vision:57,vs:84,wai:84,what:[62,84],which:84,why:67,window:23,work:[33,39,47,55,84],worth:84,you:[62,84],youngwook:[67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82],your:[62,64,84]}}) \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/tut/CameraIntro.html b/venv/Lib/site-packages/pygame/docs/generated/tut/CameraIntro.html new file mode 100644 index 0000000..400dc61 --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/tut/CameraIntro.html @@ -0,0 +1,378 @@ + + + + + + + + + Pygame Tutorials - Camera Module Introduction — pygame v2.1.2 documentation + + + + + + + + + + + + + +
+ +
+ + + + + +
+
+ +
+
+ +
+
+

Camera Module Introduction¶

+
+
Author
+

by Nirav Patel

+
+
Contact
+

nrp@eclecti.cc

+
+
+

Pygame 1.9 comes with support for interfacing cameras, allowing you to capture +still images, watch live streams, and do some simple computer vision. This +tutorial will cover all of those use cases, providing code samples you can base +your app or game on. You can refer to the reference documentation +for the full API.

+
+

Note

+

As of Pygame 1.9, the camera module offers native support for cameras +that use v4l2 on Linux. There is support for other platforms via Videocapture +or OpenCV, but this guide will focus on the native module. Most of the code +will be valid for other platforms, but certain things like controls will not +work. The module is also marked as EXPERIMENTAL, meaning the API could +change in subsequent versions.

+
+
+

Import and Init¶

+
import pygame
+import pygame.camera
+from pygame.locals import *
+
+pygame.init()
+pygame.camera.init()
+
+
+

As the camera module is optional, it needs to be imported and initialized +manually as shown above.

+
+
+

Capturing a Single Image¶

+

Now we will go over the simplest case of opening a camera and capturing a frame +as a surface. In the below example, we assume that there is a camera at +/dev/video0 on the computer, and initialize it with a size of 640 by 480. +The surface called image is whatever the camera was seeing when get_image() was +called.

+
cam = pygame.camera.Camera("/dev/video0",(640,480))
+cam.start()
+image = cam.get_image()
+
+
+
+

Listing Connected Cameras¶

+

You may be wondering, what if we don't know the exact path of the camera? +We can ask the module to provide a list of cameras attached to the +computer and initialize the first camera in the list.

+
camlist = pygame.camera.list_cameras()
+if camlist:
+    cam = pygame.camera.Camera(camlist[0],(640,480))
+
+
+
+
+

Using Camera Controls¶

+

Most cameras support controls like flipping the image and changing brightness. +set_controls() and get_controls() can be used at any point after using start().

+
cam.set_controls(hflip = True, vflip = False)
+print camera.get_controls()
+
+
+
+
+
+

Capturing a Live Stream¶

+

The rest of this tutorial will be based around capturing a live stream of +images. For this, we will be using the class below. As described, it will +simply blit a constant stream of camera frames to the screen, effectively +showing live video. It is basically what you would expect, looping get_image(), +blitting to the display surface, and flipping it. For performance reasons, +we will be supplying the camera with the same surface to use each time.

+
class Capture(object):
+    def __init__(self):
+        self.size = (640,480)
+        # create a display surface. standard pygame stuff
+        self.display = pygame.display.set_mode(self.size, 0)
+
+        # this is the same as what we saw before
+        self.clist = pygame.camera.list_cameras()
+        if not self.clist:
+            raise ValueError("Sorry, no cameras detected.")
+        self.cam = pygame.camera.Camera(self.clist[0], self.size)
+        self.cam.start()
+
+        # create a surface to capture to.  for performance purposes
+        # bit depth is the same as that of the display surface.
+        self.snapshot = pygame.surface.Surface(self.size, 0, self.display)
+
+    def get_and_flip(self):
+        # if you don't want to tie the framerate to the camera, you can check
+        # if the camera has an image ready.  note that while this works
+        # on most cameras, some will never return true.
+        if self.cam.query_image():
+            self.snapshot = self.cam.get_image(self.snapshot)
+
+        # blit it to the display surface.  simple!
+        self.display.blit(self.snapshot, (0,0))
+        pygame.display.flip()
+
+    def main(self):
+        going = True
+        while going:
+            events = pygame.event.get()
+            for e in events:
+                if e.type == QUIT or (e.type == KEYDOWN and e.key == K_ESCAPE):
+                    # close the camera safely
+                    self.cam.stop()
+                    going = False
+
+            self.get_and_flip()
+
+
+

Since get_image() is a blocking call that could take quite a bit of time on a +slow camera, this example uses query_image() to see if the camera is ready. +This allows you to separate the framerate of your game from that of your camera. +It is also possible to have the camera capturing images in a separate thread, +for approximately the same performance gain, if you find that your camera does +not support the query_image() function correctly.

+
+
+

Basic Computer Vision¶

+

By using the camera, transform, and mask modules, pygame can do some basic +computer vision.

+
+

Colorspaces¶

+

When initializing a camera, colorspace is an optional parameter, with 'RGB', +'YUV', and 'HSV' as the possible choices. YUV and HSV are both generally more +useful for computer vision than RGB, and allow you to more easily threshold by +color, something we will look at later in the tutorial.

+
self.cam = pygame.camera.Camera(self.clist[0], self.size, "RGB")
+
+
+../_images/camera_rgb.jpg +
self.cam = pygame.camera.Camera(self.clist[0], self.size, "YUV")
+
+
+../_images/camera_yuv.jpg +
self.cam = pygame.camera.Camera(self.clist[0], self.size, "HSV")
+
+
+../_images/camera_hsv.jpg +
+
+

Thresholding¶

+

Using the threshold() function from the transform module, one can do simple +green screen like effects, or isolate specifically colored objects in a scene. +In the below example, we threshold out just the green tree and make the rest +of the image black. Check the reference documentation for details on the +threshold function.

+
self.thresholded = pygame.surface.Surface(self.size, 0, self.display)
+self.snapshot = self.cam.get_image(self.snapshot)
+pygame.transform.threshold(self.thresholded,self.snapshot,(0,255,0),(90,170,170),(0,0,0),2)
+
+
+../_images/camera_thresholded.jpg +

Of course, this is only useful if you already know the exact color of the object +you are looking for. To get around this and make thresholding usable in the +real world, we need to add a calibration stage where we identify the color of an +object and use it to threshold against. We will be using the average_color() +function of the transform module to do this. Below is an example calibration +function that you could loop until an event like a key press, and an image of +what it would look like. The color inside the box will be the one that is +used for the threshold. Note that we are using the HSV colorspace in the below +images.

+
def calibrate(self):
+    # capture the image
+    self.snapshot = self.cam.get_image(self.snapshot)
+    # blit it to the display surface
+    self.display.blit(self.snapshot, (0,0))
+    # make a rect in the middle of the screen
+    crect = pygame.draw.rect(self.display, (255,0,0), (145,105,30,30), 4)
+    # get the average color of the area inside the rect
+    self.ccolor = pygame.transform.average_color(self.snapshot, crect)
+    # fill the upper left corner with that color
+    self.display.fill(self.ccolor, (0,0,50,50))
+    pygame.display.flip()
+
+
+../_images/camera_average.jpg +
pygame.transform.threshold(self.thresholded,self.snapshot,self.ccolor,(30,30,30),(0,0,0),2)
+
+
+../_images/camera_thresh.jpg +

You can use the same idea to do a simple green screen/blue screen, by first +getting a background image and then thresholding against it. The below example +just has the camera pointed at a blank white wall in HSV colorspace.

+
def calibrate(self):
+    # capture a bunch of background images
+    bg = []
+    for i in range(0,5):
+      bg.append(self.cam.get_image(self.background))
+    # average them down to one to get rid of some noise
+    pygame.transform.average_surfaces(bg,self.background)
+    # blit it to the display surface
+    self.display.blit(self.background, (0,0))
+    pygame.display.flip()
+
+
+../_images/camera_background.jpg +
pygame.transform.threshold(self.thresholded,self.snapshot,(0,255,0),(30,30,30),(0,0,0),1,self.background)
+
+
+../_images/camera_green.jpg +
+
+

Using the Mask Module¶

+

The stuff above is great if you just want to display images, but with the +mask module, you can also use a camera as an +input device for a game. For example, going back to the example of +thresholding out a specific object, we can find the position of that object and +use it to control an on screen object.

+
def get_and_flip(self):
+    self.snapshot = self.cam.get_image(self.snapshot)
+    # threshold against the color we got before
+    mask = pygame.mask.from_threshold(self.snapshot, self.ccolor, (30, 30, 30))
+    self.display.blit(self.snapshot,(0,0))
+    # keep only the largest blob of that color
+    connected = mask.connected_component()
+    # make sure the blob is big enough that it isn't just noise
+    if mask.count() > 100:
+        # find the center of the blob
+        coord = mask.centroid()
+        # draw a circle with size variable on the size of the blob
+        pygame.draw.circle(self.display, (0,255,0), coord, max(min(50,mask.count()/400),5))
+    pygame.display.flip()
+
+
+../_images/camera_mask.jpg +

This is just the most basic example. You can track multiple different colored +blobs, find the outlines of objects, have collision detection between real life +and in game objects, get the angle of an object to allow for even finer control, +and more. Have fun!

+
+
+
+
+ + +

+
+Edit on GitHub +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/tut/ChimpLineByLine.html b/venv/Lib/site-packages/pygame/docs/generated/tut/ChimpLineByLine.html new file mode 100644 index 0000000..6f1e21f --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/tut/ChimpLineByLine.html @@ -0,0 +1,597 @@ + + + + + + + + + Pygame Tutorials - Line By Line Chimp Example — pygame v2.1.2 documentation + + + + + + + + + + + + + +
+ +
+ + + + + +
+
+ +
+
+ +
+
+

Line By Line Chimp¶

+
+
Author
+

Pete Shinners

+
+
Contact
+

pete@shinners.org

+
+
+
+
+
+

Introduction¶

+

In the pygame examples there is a simple example named "chimp". +This example simulates a punchable monkey moving around the screen with +promises of riches and reward. The example itself is very simple, and a +bit thin on error-checking code. This example program demonstrates many of +pygame's abilities, like creating a window, loading images and sounds, +rendering text, and basic event and mouse handling.

+

The program and images can be found inside the standard source distribution +of pygame. You can run it by running python -m pygame.examples.chimp in +your terminal.

+

This tutorial will go through the code block by block. Explaining how +the code works. There will also be mention of how the code could be improved +and what error checking could help out.

+

This is an excellent tutorial for people getting their first look at +the pygame code. Once pygame is fully installed, you can find +and run the chimp demo for yourself in the examples directory.

+
+

(no, this is not a banner ad, it's the screenshot)

+chimp game banner +

Full Source

+
+
+
+

Import Modules¶

+

This is the code that imports all the needed modules into your program. +It also checks for the availability of some of the optional pygame modules.

+
# Import Modules
+import os
+import pygame as pg
+
+if not pg.font:
+    print("Warning, fonts disabled")
+if not pg.mixer:
+    print("Warning, sound disabled")
+
+main_dir = os.path.split(os.path.abspath(__file__))[0]
+data_dir = os.path.join(main_dir, "data")
+
+
+

First, we import the standard "os" python module. This allow +us to do things like create platform independent file paths.

+

In the next line, we import the pygame package. In our case, we import +pygame as pg, so that all of the functionality of pygame is able to +be referenced from the namespace pg.

+

Some pygame modules are optional, and if they aren't found, +they evaluate to False. Because of that, we decide to print +a nice warning message if the font or +mixer modules in pygame are not available. +(Although they will only be unavailable in very uncommon situations).

+

Lastly, we prepare two paths for the rest of the code to use. +main_dir uses the os.path module and the __file__ variable provided +by Python to locate the game's python file, and extract the folder from +that path. It then prepares the variable data_dir to tell the +loading functions exactly where to look.

+
+
+

Loading Resources¶

+

Here we have two functions we can use to load images and sounds. We will +look at each function individually in this section.

+
def load_image(name, colorkey=None, scale=1):
+    fullname = os.path.join(data_dir, name)
+    image = pg.image.load(fullname)
+
+    size = image.get_size()
+    size = (size[0] * scale, size[1] * scale)
+    image = pg.transform.scale(image, size)
+
+    image = image.convert()
+    if colorkey is not None:
+        if colorkey == -1:
+            colorkey = image.get_at((0, 0))
+        image.set_colorkey(colorkey, pg.RLEACCEL)
+    return image, image.get_rect()
+
+
+

This function takes the name of an image to load. It also optionally +takes an argument it can use to set a colorkey for the image, and an argument +to scale the image. A colorkey is used in graphics to represent a color of the +image that is transparent.

+

The first thing this function does is create a full pathname to the file. +In this example all the resources are in a "data" subdirectory. By using +the os.path.join function, a pathname will be created that works for whatever +platform the game is running on.

+

Next we load the image using the pygame.image.load()load new image from a file (or file-like object) function. +After the image is loaded, we make an important +call to the convert() function. This makes a new copy of a Surface and converts +its color format and depth to match the display. This means blitting the +image to the screen will happen as quickly as possible.

+

We then scale the image, using the pygame.transform.scale()resize to new resolution function. +This function takes a Surface and the size it should be scaled to. To scale +by a scalar, we can get the size and scale the x and y by the scalar.

+

Last, we set the colorkey for the image. If the user supplied an argument +for the colorkey argument we use that value as the colorkey for the image. +This would usually just be a color RGB value, like (255, 255, 255) for +white. You can also pass a value of -1 as the colorkey. In this case the +function will lookup the color at the topleft pixel of the image, and use +that color for the colorkey.

+
def load_sound(name):
+    class NoneSound:
+        def play(self):
+            pass
+
+    if not pg.mixer or not pg.mixer.get_init():
+        return NoneSound()
+
+    fullname = os.path.join(data_dir, name)
+    sound = pg.mixer.Sound(fullname)
+
+    return sound
+
+
+

Next is the function to load a sound file. The first thing this function +does is check to see if the pygame.mixerpygame module for loading and playing sounds module was imported correctly. +If not, it returns a small class instance that has a dummy play method. +This will act enough like a normal Sound object for this game to run without +any extra error checking.

+

This function is similar to the image loading function, but handles some +different problems. First we create a full path to the sound image, and +load the sound file. Then we simply return the loaded Sound object.

+
+
+

Game Object Classes¶

+

Here we create two classes to represent the objects in our game. Almost +all the logic for the game goes into these two classes. We will look over +them one at a time here.

+
class Fist(pg.sprite.Sprite):
+    """moves a clenched fist on the screen, following the mouse"""
+
+    def __init__(self):
+        pg.sprite.Sprite.__init__(self)  # call Sprite initializer
+        self.image, self.rect = load_image("fist.png", -1)
+        self.fist_offset = (-235, -80)
+        self.punching = False
+
+    def update(self):
+        """move the fist based on the mouse position"""
+        pos = pg.mouse.get_pos()
+        self.rect.topleft = pos
+        self.rect.move_ip(self.fist_offset)
+        if self.punching:
+            self.rect.move_ip(15, 25)
+
+    def punch(self, target):
+        """returns true if the fist collides with the target"""
+        if not self.punching:
+            self.punching = True
+            hitbox = self.rect.inflate(-5, -5)
+            return hitbox.colliderect(target.rect)
+
+    def unpunch(self):
+        """called to pull the fist back"""
+        self.punching = False
+
+
+

Here we create a class to represent the players fist. It is derived from +the Sprite class included in the pygame.spritepygame module with basic game object classes module. The __init__ function +is called when new instances of this class are created. The first thing +we do is be sure to call the __init__ function for our base class. This +allows the Sprite's __init__ function to prepare our object for use as a +sprite. This game uses one of the sprite drawing Group classes. These classes +can draw sprites that have an "image" and "rect" attribute. By simply changing +these two attributes, the renderer will draw the current image at the current +position.

+

All sprites have an update() method. This function is typically called +once per frame. It is where you should put code that moves and updates +the variables for the sprite. The update() method for the fist moves the +fist to the location of the mouse pointer. It also offsets the fist position +slightly if the fist is in the "punching" state.

+

The following two functions punch() and unpunch() change the punching +state for the fist. The punch() method also returns a true value if the fist +is colliding with the given target sprite.

+
class Chimp(pg.sprite.Sprite):
+    """moves a monkey critter across the screen. it can spin the
+    monkey when it is punched."""
+
+    def __init__(self):
+        pg.sprite.Sprite.__init__(self)  # call Sprite intializer
+        self.image, self.rect = load_image("chimp.png", -1, 4)
+        screen = pg.display.get_surface()
+        self.area = screen.get_rect()
+        self.rect.topleft = 10, 90
+        self.move = 18
+        self.dizzy = False
+
+    def update(self):
+        """walk or spin, depending on the monkeys state"""
+        if self.dizzy:
+            self._spin()
+        else:
+            self._walk()
+
+    def _walk(self):
+        """move the monkey across the screen, and turn at the ends"""
+        newpos = self.rect.move((self.move, 0))
+        if not self.area.contains(newpos):
+            if self.rect.left < self.area.left or self.rect.right > self.area.right:
+                self.move = -self.move
+                newpos = self.rect.move((self.move, 0))
+                self.image = pg.transform.flip(self.image, True, False)
+        self.rect = newpos
+
+    def _spin(self):
+        """spin the monkey image"""
+        center = self.rect.center
+        self.dizzy = self.dizzy + 12
+        if self.dizzy >= 360:
+            self.dizzy = False
+            self.image = self.original
+        else:
+            rotate = pg.transform.rotate
+            self.image = rotate(self.original, self.dizzy)
+        self.rect = self.image.get_rect(center=center)
+
+    def punched(self):
+        """this will cause the monkey to start spinning"""
+        if not self.dizzy:
+            self.dizzy = True
+            self.original = self.image
+
+
+

The Chimp class is doing a little more work than the fist, but nothing +more complex. This class will move the chimp back and forth across the +screen. When the monkey is punched, he will spin around to exciting effect. +This class is also derived from the base Sprite +class, and is initialized the same as the fist. While initializing, the class +also sets the attribute "area" to be the size of the display screen.

+

The update function for the chimp simply looks at the current "dizzy" +state, which is true when the monkey is spinning from a punch. It calls either +the _spin or _walk method. These functions are prefixed with an underscore. +This is just a standard python idiom which suggests these methods should +only be used by the Chimp class. We could go so far as to give them a double +underscore, which would tell python to really try to make them private +methods, but we don't need such protection. :)

+

The _walk method creates a new position for the monkey by moving the current +rect by a given offset. If this new position crosses outside the display +area of the screen, it reverses the movement offset. It also mirrors the +image using the pygame.transform.flip()flip vertically and horizontally function. This is a crude effect +that makes the monkey look like he's turning the direction he is moving.

+

The _spin method is called when the monkey is currently "dizzy". The dizzy +attribute is used to store the current amount of rotation. When the monkey +has rotated all the way around (360 degrees) it resets the monkey image +back to the original, non-rotated version. Before calling the +pygame.transform.rotate()rotate an image function, you'll see the code makes a local +reference to the function simply named "rotate". There is no need to do that +for this example, it is just done here to keep the following line's length a +little shorter. Note that when calling the rotate function, we are always +rotating from the original monkey image. When rotating, there is a slight loss +of quality. Repeatedly rotating the same image and the quality would get worse +each time. Also, when rotating an image, the size of the image will actually +change. This is because the corners of the image will be rotated out, making +the image bigger. We make sure the center of the new image matches the center +of the old image, so it rotates without moving.

+

The last method is punched() which tells the sprite to enter its dizzy +state. This will cause the image to start spinning. It also makes a copy +of the current image named "original".

+
+
+

Initialize Everything¶

+

Before we can do much with pygame, we need to make sure its modules +are initialized. In this case we will also open a simple graphics window. +Now we are in the main() function of the program, which actually runs everything.

+
pg.init()
+screen = pg.display.set_mode((1280, 480), pg.SCALED)
+pg.display.set_caption("Monkey Fever")
+pg.mouse.set_visible(False)
+
+
+

The first line to initialize pygame takes care of a bit of +work for us. It checks through the imported pygame modules and attempts +to initialize each one of them. It is possible to go back and check if modules +failed to initialize, but we won't bother here. It is also possible to +take a lot more control and initialize each specific module by hand. That +type of control is generally not needed, but is available if you desire.

+

Next we set up the display graphics mode. Note that the pygame.displaypygame module to control the display window and screen +module is used to control all the display settings. In this case we are +asking for a 1280 by 480 window, with the SCALED display flag. +This automatically scales up the window for displays much larger than the +window.

+

Last we set the window title and turn off the mouse cursor for our +window. Very basic to do, and now we have a small black window ready to +do our bidding. Usually the cursor defaults to visible, so there is no need +to really set the state unless we want to hide it.

+
+
+

Create The Background¶

+

Our program is going to have text message in the background. It would +be nice for us to create a single surface to represent the background and +repeatedly use that. The first step is to create the surface.

+
background = pg.Surface(screen.get_size())
+background = background.convert()
+background.fill((170, 238, 187))
+
+
+

This creates a new surface for us that is the same size as the display +window. Note the extra call to convert() after creating the Surface. The +convert with no arguments will make sure our background is the same format +as the display window, which will give us the fastest results.

+

We also fill the entire background with a certain green color. The fill() +function usually takes an RGB triplet as arguments, but supports many +input formats. See the pygame.Colorpygame object for color representations for all the color formats.

+
+
+

Put Text On The Background, Centered¶

+

Now that we have a background surface, lets get the text rendered to it. We +only do this if we see the pygame.fontpygame module for loading and rendering fonts module has imported properly. +If not, we just skip this section.

+
if pg.font:
+    font = pg.font.Font(None, 64)
+    text = font.render("Pummel The Chimp, And Win $$$", True, (10, 10, 10))
+    textpos = text.get_rect(centerx=background.get_width() / 2, y=10)
+    background.blit(text, textpos)
+
+
+

As you see, there are a couple steps to getting this done. First we +must create the font object and render it into a new surface. We then find +the center of that new surface and blit (paste) it onto the background.

+

The font is created with the font module's Font() constructor. Usually +you will pass the name of a TrueType font file to this function, but we +can also pass None, which will use a default font. The Font constructor +also needs to know the size of font we want to create.

+

We then render that font into a new surface. The render function creates +a new surface that is the appropriate size for our text. In this case +we are also telling render to create antialiased text (for a nice smooth +look) and to use a dark grey color.

+

Next we need to find the centered position of the text on our display. +We create a "Rect" object from the text dimensions, which allows us to +easily assign it to the screen center.

+

Finally we blit (blit is like a copy or paste) the text onto the background +image.

+
+
+

Display The Background While Setup Finishes¶

+

We still have a black window on the screen. Lets show our background +while we wait for the other resources to load.

+
screen.blit(background, (0, 0))
+pygame.display.flip()
+
+
+

This will blit our entire background onto the display window. The +blit is self explanatory, but what about this flip routine?

+

In pygame, changes to the display surface are not immediately visible. +Normally, a display must be updated in areas that have changed for them +to be visible to the user. In this case the flip() function works nicely +because it simply handles the entire window area.

+
+
+

Prepare Game Object¶

+

Here we create all the objects that the game is going to need.

+
whiff_sound = load_sound("whiff.wav")
+punch_sound = load_sound("punch.wav")
+chimp = Chimp()
+fist = Fist()
+allsprites = pg.sprite.RenderPlain((chimp, fist))
+clock = pg.time.Clock()
+
+
+

First we load two sound effects using the load_sound function we defined +above. Then we create an instance of each of our sprite classes. And lastly +we create a sprite Group which will contain all +our sprites.

+

We actually use a special sprite group named RenderPlain. This sprite group can draw all the sprites it +contains to the screen. It is called RenderPlain because there are actually +more advanced Render groups. But for our game, we just need simple drawing. We +create the group named "allsprites" by passing a list with all the sprites that +should belong in the group. We could later on add or remove sprites from this +group, but in this game we won't need to.

+

The clock object we create will be used to help control our game's framerate. +we will use it in the main loop of our game to make sure it doesn't run too fast.

+
+
+

Main Loop¶

+

Nothing much here, just an infinite loop.

+
going = True
+while going:
+    clock.tick(60)
+
+
+

All games run in some sort of loop. The usual order of things is to +check on the state of the computer and user input, move and update the +state of all the objects, and then draw them to the screen. You'll see +that this example is no different.

+

We also make a call to our clock object, which will make sure our game +doesn't run faster than 60 frames per second.

+
+
+

Handle All Input Events¶

+

This is an extremely simple case of working the event queue.

+
for event in pg.event.get():
+    if event.type == pg.QUIT:
+        going = False
+    elif event.type == pg.KEYDOWN and event.key == pg.K_ESCAPE:
+        going = False
+    elif event.type == pg.MOUSEBUTTONDOWN:
+        if fist.punch(chimp):
+            punch_sound.play()  # punch
+            chimp.punched()
+        else:
+            whiff_sound.play()  # miss
+    elif event.type == pg.MOUSEBUTTONUP:
+        fist.unpunch()
+
+
+

First we get all the available Events from pygame and loop through each +of them. The first two tests see if the user has quit our game, or pressed +the escape key. In these cases we just set going to False, allowing +us out of the infinite loop.

+

Next we just check to see if the mouse button was pressed or released. +If the button was pressed, we ask the fist object if it has collided with +the chimp. We play the appropriate sound effect, and if the monkey was hit, +we tell him to start spinning (by calling his punched() method).

+
+
+

Update the Sprites¶

+
allsprites.update()
+
+
+

Sprite groups have an update() method, which simply calls the update method +for all the sprites it contains. Each of the objects will move around, depending +on which state they are in. This is where the chimp will move one step side +to side, or spin a little farther if he was recently punched.

+
+
+

Draw The Entire Scene¶

+

Now that all the objects are in the right place, time to draw them.

+
screen.blit(background, (0, 0))
+allsprites.draw(screen)
+pygame.display.flip()
+
+
+

The first blit call will draw the background onto the entire screen. This +erases everything we saw from the previous frame (slightly inefficient, but +good enough for this game). Next we call the draw() method of the sprite +container. Since this sprite container is really an instance of the "DrawPlain" +sprite group, it knows how to draw our sprites. Lastly, we flip() the contents +of pygame's software double buffer to the screen. This makes everything we've +drawn visible all at once.

+
+
+

Game Over¶

+

User has quit, time to clean up.

+
pg.quit()
+
+
+

Cleaning up the running game in pygame is extremely simple. +Since all variables are automatically destructed, we don't really have to do +anything, but calling pg.quit() explicitly cleans up pygame's internals.

+
+
+
+ + +

+
+Edit on GitHub +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/tut/DisplayModes.html b/venv/Lib/site-packages/pygame/docs/generated/tut/DisplayModes.html new file mode 100644 index 0000000..b0d7d82 --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/tut/DisplayModes.html @@ -0,0 +1,314 @@ + + + + + + + + + Pygame Tutorials - Setting Display Modes — pygame v2.1.2 documentation + + + + + + + + + + + + + +
+ +
+ + + + + +
+
+ +
+
+ +
+
+

Setting Display Modes¶

+
+
Author
+

Pete Shinners

+
+
Contact
+

pete@shinners.org

+
+
+
+

Introduction¶

+

Setting the display mode in pygame creates a visible image surface +on the monitor. +This surface can either cover the full screen, or be windowed +on platforms that support a window manager. +The display surface is nothing more than a standard pygame surface object. +There are special functions needed in the pygame.displaypygame module to control the display window and screen +module to keep the image surface contents updated on the monitor.

+

Setting the display mode in pygame is an easier task than with most +graphic libraries. +The advantage is if your display mode is not available, +pygame will emulate the display mode that you asked for. +Pygame will select a display resolution and color depth that best matches +the settings you have requested, +then allow you to access the display with the format you have requested. +In reality, since the pygame.displaypygame module to control the display window and screen module is +a binding around the SDL library, SDL is really doing all this work.

+

There are advantages and disadvantages to setting the display mode in this +manner. +The advantage is that if your game requires a specific display mode, +your game will run on platforms that do not support your requirements. +It also makes life easier when you're getting something started, +it is always easy to go back later and make the mode selection a little more +particular. +The disadvantage is that what you request is not always what you will get. +There is also a performance penalty when the display mode must be emulated. +This tutorial will help you understand the different methods for querying +the platforms display capabilities, and setting the display mode for your game.

+
+
+

Setting Basics¶

+

The first thing to learn about is how to actually set the current display mode. +The display mode may be set at any time after the pygame.displaypygame module to control the display window and screen +module has been initialized. +If you have previously set the display mode, +setting it again will change the current mode. +Setting the display mode is handled with the function +pygame.display.set_mode((width, height), flags, depth)Initialize a window or screen for display. +The only required argument in this function is a sequence containing +the width and height of the new display mode. +The depth flag is the requested bits per pixel for the surface. +If the given depth is 8, pygame will create a color-mapped surface. +When given a higher bit depth, pygame will use a packed color mode. +Much more information about depths and color modes can be found in the +documentation for the display and surface modules. +The default value for depth is 0. +When given an argument of 0, pygame will select the best bit depth to use, +usually the same as the system's current bit depth. +The flags argument lets you control extra features for the display mode. +Again, more information about this is found in the pygame reference documents.

+
+
+

How to Decide¶

+

So how do you select a display mode that is going to work best with your +graphic resources and the platform your game is running on? +There are several methods for gathering information about the display device. +All of these methods must be called after the display module has been +initialized, but you likely want to call them before setting the display mode. +First, pygame.display.Info()Create a video display information object +will return a special object type of VidInfo, +which can tell you a lot about the graphics driver capabilities. +The function +pygame.display.list_modes(depth, flags)Get list of available fullscreen modes +can be used to find the supported graphic modes by the system. +pygame.display.mode_ok((width, height), flags, depth)Pick the best color depth for a display mode takes the same arguments as +set_mode(), +but returns the closest matching bit depth to the one you request. +Lastly, pygame.display.get_driver()Get the name of the pygame display backend +will return the name of the graphics driver selected by pygame.

+

Just remember the golden rule. +Pygame will work with pretty much any display mode you request. +Some display modes will need to be emulated, +which will slow your game down, +since pygame will need to convert every update you make to the +"real" display mode. The best bet is to always let pygame +choose the best bit depth, +and convert all your graphic resources to that format when they are loaded. +You let pygame choose its bit depth by calling +set_mode() +with no depth argument or a depth of 0, +or you can call +mode_ok() +to find a closest matching bit depth to what you need.

+

When your display mode is windowed, +you usually must match the same bit depth as the desktop. +When you are fullscreen, some platforms can switch to any bit depth that +best suits your needs. +You can find the depth of the current desktop if you get a VidInfo object +before ever setting your display mode.

+

After setting the display mode, +you can find out information about its settings by getting a VidInfo object, +or by calling any of the Surface.get* methods on the display surface.

+
+
+

Functions¶

+

These are the routines you can use to determine the most appropriate +display mode. +You can find more information about these functions in the display module +documentation.

+
+

pygame.display.mode_ok(size, flags, depth)Pick the best color depth for a display mode

+
+

This function takes the exact same arguments as pygame.display.set_mode(). +It returns the best available bit depth for the mode you have described. +If this returns zero, +then the desired display mode is not available without emulation.

+
+

pygame.display.list_modes(depth, flags)Get list of available fullscreen modes

+
+

Returns a list of supported display modes with the requested +depth and flags. +An empty list is returned when there are no modes. +The flags argument defaults to FULLSCREEN. +If you specify your own flags without FULLSCREEN, +you will likely get a return value of -1. +This means that any display size is fine, since the display will be windowed. +Note that the listed modes are sorted largest to smallest.

+
+

pygame.display.Info()Create a video display information object

+
+

This function returns an object with many members describing +the display device. +Printing the VidInfo object will quickly show you all the +members and values for this object.

+
>>> import pygame.display
+>>> pygame.display.init()
+>>> info = pygame.display.Info()
+>>> print(info)
+<VideoInfo(hw = 0, wm = 1,video_mem = 0
+        blit_hw = 0, blit_hw_CC = 0, blit_hw_A = 0,
+        blit_sw = 0, blit_sw_CC = 0, blit_sw_A = 0,
+        bitsize  = 32, bytesize = 4,
+        masks =  (16711680, 65280, 255, 0),
+        shifts = (16, 8, 0, 0),
+        losses =  (0, 0, 0, 8),
+        current_w = 1920, current_h = 1080
+>
+
+
+
+
+

You can test all these flags as simply members of the VidInfo object.

+
+
+

Examples¶

+

Here are some examples of different methods to init the graphics display. +They should help you get an idea of how to go about setting your display mode.

+
>>> #give me the best depth with a 640 x 480 windowed display
+>>> pygame.display.set_mode((640, 480))
+
+>>> #give me the biggest 16-bit display available
+>>> modes = pygame.display.list_modes(16)
+>>> if not modes:
+...     print('16-bit not supported')
+... else:
+...     print('Found Resolution:', modes[0])
+...     pygame.display.set_mode(modes[0], FULLSCREEN, 16)
+
+>>> #need an 8-bit surface, nothing else will do
+>>> if pygame.display.mode_ok((800, 600), 0, 8) != 8:
+...     print('Can only work with an 8-bit display, sorry')
+... else:
+...     pygame.display.set_mode((800, 600), 0, 8)
+
+
+
+
+
+ + +

+
+Edit on GitHub +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/tut/ImportInit.html b/venv/Lib/site-packages/pygame/docs/generated/tut/ImportInit.html new file mode 100644 index 0000000..2b11c40 --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/tut/ImportInit.html @@ -0,0 +1,197 @@ + + + + + + + + + Pygame Tutorials - Import and Initialize — pygame v2.1.2 documentation + + + + + + + + + + + + + +
+ +
+ + + + + +
+
+ +
+
+ +
+
+

Import and Initialize¶

+
+
Author
+

Pete Shinners

+
+
Contact
+

pete@shinners.org

+
+
+

Getting pygame imported and initialized is a very simple process. It is also +flexible enough to give you control over what is happening. Pygame is a +collection of different modules in a single python package. Some of the +modules are written in C, and some are written in python. Some modules +are also optional, and might not always be present.

+

This is just a quick introduction on what is going on when you import pygame. +For a clearer explanation definitely see the pygame examples.

+
+

Import¶

+

First we must import the pygame package. Since pygame version 1.4 this +has been updated to be much easier. Most games will import all of pygame like this.

+
import pygame
+from pygame.locals import *
+
+
+

The first line here is the only necessary one. It imports all the available pygame +modules into the pygame package. The second line is optional, and puts a limited +set of constants and functions into the global namespace of your script.

+

An important thing to keep in mind is that several pygame modules are optional. +For example, one of these is the font module. When you "import pygame", pygame +will check to see if the font module is available. If the font module is available +it will be imported as "pygame.font". If the module is not available, "pygame.font" +will be set to None. This makes it fairly easy to later on test if the font module is available.

+
+
+

Init¶

+

Before you can do much with pygame, you will need to initialize it. The most common +way to do this is just make one call.

+
pygame.init()
+
+
+

This will attempt to initialize all the pygame modules for you. Not all pygame modules +need to be initialized, but this will automatically initialize the ones that do. You can +also easily initialize each pygame module by hand. For example to only initialize the +font module you would just call.

+
pygame.font.init()
+
+
+

Note that if there is an error when you initialize with "pygame.init()", it will silently fail. +When hand initializing modules like this, any errors will raise an exception. Any +modules that must be initialized also have a "get_init()" function, which will return true +if the module has been initialized.

+

It is safe to call the init() function for any module more than once.

+
+
+

Quit¶

+

Modules that are initialized also usually have a quit() function that will clean up. +There is no need to explicitly call these, as pygame will cleanly quit all the +initialized modules when python finishes.

+
+
+
+ + +

+
+Edit on GitHub +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/tut/MakeGames.html b/venv/Lib/site-packages/pygame/docs/generated/tut/MakeGames.html new file mode 100644 index 0000000..b9f6ed9 --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/tut/MakeGames.html @@ -0,0 +1,237 @@ + + + + + + + + + Making Games With Pygame — pygame v2.1.2 documentation + + + + + + + + + + + + + +
+ +
+ + + + + +
+
+ +
+
+ +
+
+

Making Games With Pygame¶

+
+
+
+

Table of Contents¶

+

1. Introduction

+
+
+

2. Revision: Pygame fundamentals

+
+
+

3. Kicking things off

+
+
+

4. Game object classes

+
+
+

5. User-controllable objects

+
+
+

6. Putting it all together

+
+
+
+
+

1. Introduction¶

+

First of all, I will assume you have read the Line By Line Chimp +tutorial, which introduces the basics of Python and pygame. Give it a read before reading this +tutorial, as I won't bother repeating what that tutorial says (or at least not in as much detail). This tutorial is aimed at those +who understand how to make a ridiculously simple little "game", and who would like to make a relatively simple game like Pong. +It introduces you to some concepts of game design, some simple mathematics to work out ball physics, and some ways to keep your +game easy to maintain and expand.

+

All the code in this tutorial works toward implementing TomPong, +a game I've written. By the end of the tutorial, you should not only have a firmer grasp of pygame, but +you should also understand how TomPong works, and how to make your own version.

+

Now, for a brief recap of the basics of pygame. A common method of organising the code for a game is to divide it into the following +six sections:

+
+
    +
  • Load modules which are required in the game. Standard stuff, except that you should +remember to import the pygame local names as well as the pygame module itself

  • +
  • Resource handling classes; define some classes to handle your most basic resources, +which will be loading images and sounds, as well as connecting and disconnecting to and from networks, loading save game +files, and any other resources you might have.

  • +
  • Game object classes; define the classes for your game object. In the pong example, +these will be one for the player's bat (which you can initialise multiple times, one for each player in the game), and one +for the ball (which can again have multiple instances). If you're going to have a nice in-game menu, it's also a good idea to make a +menu class.

  • +
  • Any other game functions; define other necessary functions, such as scoreboards, menu +handling, etc. Any code that you could put into the main game logic, but that would make understanding said logic harder, should +be put into its own function. So as plotting a scoreboard isn't game logic, it should be moved into a function.

  • +
  • Initialise the game, including the pygame objects themselves, the background, the game +objects (initialising instances of the classes) and any other little bits of code you might want to add in.

  • +
  • The main loop, into which you put any input handling (i.e. watching for users hitting +keys/mouse buttons), the code for updating the game objects, and finally for updating the screen.

  • +
+
+

Every game you make will have some or all of those sections, possibly with more of your own. For the purposes of this tutorial, I will +write about how TomPong is laid out, and the ideas I write about can be transferred to almost any kind of game you might make. I will +also assume that you want to keep all of the code in a single file, but if you're making a reasonably large game, it's often a good +idea to source certain sections into module files. Putting the game object classes into a file called objects.py, for +example, can help you keep game logic separate from game objects. If you have a lot of resource handling code, it can also be handy +to put that into resources.py. You can then from objects,resources import * to import all of the +classes and functions.

+
+
+

1.1. A note on coding styles¶

+

The first thing to remember when approaching any programming project is to decide on a coding style, and stay consistent. Python +solves a lot of the problems because of its strict interpretation of whitespace and indentation, but you can still choose the size +of your indentations, whether you put each module import on a new line, how you comment code, etc. You'll see how I do all of this +in the code examples; you needn't use my style, but whatever style you adopt, use it all the way through the program code. Also try +to document all of your classes, and comment on any bits of code that seem obscure, though don't start commenting the obvious. I've +seen plenty of people do the following:

+
player1.score += scoreup        # Add scoreup to player1 score
+
+
+

The worst code is poorly laid out, with seemingly random changes in style, and poor documentation. Poor code is not only annoying +for other people, but it also makes it difficult for you to maintain.

+
+
+
+ + +

+
+Edit on GitHub +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/tut/MoveIt.html b/venv/Lib/site-packages/pygame/docs/generated/tut/MoveIt.html new file mode 100644 index 0000000..67469fa --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/tut/MoveIt.html @@ -0,0 +1,539 @@ + + + + + + + + + Pygame Tutorials - Help! How Do I Move An Image? — pygame v2.1.2 documentation + + + + + + + + + + + + + +
+ +
+ + + + + +
+
+ +
+
+ +
+
+

Help! How Do I Move An Image?¶

+
+
Author
+

Pete Shinners

+
+
Contact
+

pete@shinners.org

+
+
+

Many people new to programming and graphics have a hard time figuring +out how to make an image move around the screen. Without understanding +all the concepts, it can be very confusing. You're not the first person +to be stuck here, I'll do my best to take things step by step. We'll even +try to end with methods of keeping your animations efficient.

+

Note that we won't be teaching you to program with python in this article, +just introduce you to some of the basics with pygame.

+
+

Just Pixels On The Screen¶

+

Pygame has a display Surface. This is basically an image that is visible +on the screen, and the image is made up of pixels. The main way you change +these pixels is by calling the blit() function. This copies the pixels +from one image onto another.

+

This is the first thing to understand. When you blit an image onto the +screen, you are simply changing the color of the pixels on the screen. +Pixels aren't added or moved, we just change the colors of the pixels already +on the screen. These images you blit to the screen are also Surfaces in +pygame, but they are in no way connected to the display Surface. When they +are blitted to the screen they are copied into the display, but you still +have a unique copy of the original.

+

With this brief description. Perhaps you can already understand what +is needed to "move" an image. We don't actually move anything at all. We +simply blit the image in a new position. But before we draw the image in +the new position, we'll need to "erase" the old one. Otherwise the image +will be visible in two places on the screen. By rapidly erasing the image +and redrawing it in a new place, we achieve the "illusion" of movement.

+

Through the rest of this tutorial we will break this process down into +simpler steps. Even explaining the best ways to have multiple images moving +around the screen. You probably already have questions. Like, how do we +"erase" the image before drawing it in a new position? Perhaps you're still +totally lost? Well hopefully the rest of this tutorial can straighten things +out for you.

+
+
+

Let's Go Back A Step¶

+

Perhaps the concept of pixels and images is still a little foreign to +you? Well good news, for the next few sections we are going to use code that +does everything we want, it just doesn't use pixels. We're going to create +a small python list of 6 numbers, and imagine it represents some fantastic +graphics we could see on the screen. It might actually be surprising how +closely this represents exactly what we'll later be doing with real graphics.

+

So let's begin by creating our screen list and fill it with a beautiful +landscape of 1s and 2s.

+
>>> screen = [1, 1, 2, 2, 2, 1]
+>>> print screen
+[1, 1, 2, 2, 2, 1]
+
+
+

Now we've created our background. It's not going to be very exciting +unless we also draw a player on the screen. We'll create a mighty hero +that looks like the number 8. Let's stick him near the middle of the map +and see what it looks like.

+
>>> screen[3] = 8
+>>> print screen
+[1, 1, 2, 8, 2, 1]
+
+
+

This might have been as far as you've gotten if you jumped right in doing +some graphics programming with pygame. You've got some nice looking stuff +on the screen, but it cannot move anywhere. Perhaps now that our screen +is just a list of numbers, it's easier to see how to move him?

+
+
+

Making The Hero Move¶

+

Before we can start moving the character. We need to keep track of some +sort of position for him. In the last section when we drew him, we just picked +an arbitrary position. Let's do it a little more officially this time.

+
>>> playerpos = 3
+>>> screen[playerpos] = 8
+>>> print screen
+[1, 1, 2, 8, 2, 1]
+
+
+

Now it is pretty easy to move him to a new position. We simply change +the value of playerpos, and draw him on the screen again.

+
>>> playerpos = playerpos - 1
+>>> screen[playerpos] = 8
+>>> print screen
+[1, 1, 8, 8, 2, 1]
+
+
+

Whoops. Now we can see two heroes. One in the old position, and one +in his new position. This is exactly the reason we need to "erase" the hero +in his old position before we draw him in the new position. To erase him, +we need to change that value in the list back to what it was before the hero +was there. That means we need to keep track of the values on the screen before +the hero replaced them. There's several way you could do this, but the easiest +is usually to keep a separate copy of the screen background. This means +we need to make some changes to our little game.

+
+
+

Creating A Map¶

+

What we want to do is create a separate list we will call our background. +We will create the background so it looks like our original screen did, +with 1s and 2s. Then we will copy each item from the background to the screen. +After that we can finally draw our hero back onto the screen.

+
>>> background = [1, 1, 2, 2, 2, 1]
+>>> screen = [0]*6                         #a new blank screen
+>>> for i in range(6):
+...     screen[i] = background[i]
+>>> print screen
+[1, 1, 2, 2, 2, 1]
+>>> playerpos = 3
+>>> screen[playerpos] = 8
+>>> print screen
+[1, 1, 2, 8, 2, 1]
+
+
+

It may seem like a lot of extra work. We're no farther off than we were +before the last time we tried to make him move. But this time we have the +extra information we need to move him properly.

+
+
+

Making The Hero Move (Take 2)¶

+

This time it will be easy to move the hero around. First we will erase +the hero from his old position. We do this by copying the correct value +from the background onto the screen. Then we will draw the character in his +new position on the screen

+
>>> print screen
+[1, 1, 2, 8, 2, 1]
+>>> screen[playerpos] = background[playerpos]
+>>> playerpos = playerpos - 1
+>>> screen[playerpos] = 8
+>>> print screen
+[1, 1, 8, 2, 2, 1]
+
+
+

There it is. The hero has moved one space to the left. We can use this +same code to move him to the left again.

+
>>> screen[playerpos] = background[playerpos]
+>>> playerpos = playerpos - 1
+>>> screen[playerpos] = 8
+>>> print screen
+[1, 8, 2, 2, 2, 1]
+
+
+

Excellent! This isn't exactly what you'd call smooth animation. But with +a couple small changes, we'll make this work directly with graphics on +the screen.

+
+
+

Definition: "blit"¶

+

In the next sections we will transform our program from using lists to +using real graphics on the screen. When displaying the graphics we will +use the term blit frequently. If you are new to doing graphics +work, you are probably unfamiliar with this common term.

+

BLIT: Basically, blit means to copy graphics from one image +to another. A more formal definition is to copy an array of data +to a bitmapped array destination. You can think of blit as just +"assigning" pixels. Much like setting values in our screen-list +above, blitting assigns the color of pixels in our image.

+

Other graphics libraries will use the word bitblt, or just blt, +but they are talking about the same thing. It is basically copying +memory from one place to another. Actually, it is a bit more advanced than +straight copying of memory, since it needs to handle things like pixel +formats, clipping, and scanline pitches. Advanced blitters can also +handle things like transparency and other special effects.

+
+
+

Going From The List To The Screen¶

+

To take the code we see in the above to examples and make them work with +pygame is very straightforward. We'll pretend we have loaded some pretty +graphics and named them "terrain1", "terrain2", and "hero". Where before +we assigned numbers to a list, we now blit graphics to the screen. Another +big change, instead of using positions as a single index (0 through 5), we +now need a two dimensional coordinate. We'll pretend each of the graphics +in our game is 10 pixels wide.

+
>>> background = [terrain1, terrain1, terrain2, terrain2, terrain2, terrain1]
+>>> screen = create_graphics_screen()
+>>> for i in range(6):
+...     screen.blit(background[i], (i*10, 0))
+>>> playerpos = 3
+>>> screen.blit(playerimage, (playerpos*10, 0))
+
+
+

Hmm, that code should seem very familiar, and hopefully more importantly; +the code above should make a little sense. Hopefully my illustration of setting +simple values in a list shows the similarity of setting pixels on the screen +(with blit). The only part that's really extra work is converting the player position +into coordinates on the screen. For now we just use a crude (playerpos*10, 0) , +but we can certainly do better than that. Now let's move the player +image over a space. This code should have no surprises.

+
>>> screen.blit(background[playerpos], (playerpos*10, 0))
+>>> playerpos = playerpos - 1
+>>> screen.blit(playerimage, (playerpos*10, 0))
+
+
+

There you have it. With this code we've shown how to display a simple background +with a hero's image on it. Then we've properly moved that hero one space +to the left. So where do we go from here? Well for one the code is still +a little awkward. First thing we'll want to do is find a cleaner way to represent +the background and player position. Then perhaps a bit of smoother, real +animation.

+
+
+

Screen Coordinates¶

+

To position an object on the screen, we need to tell the blit() function +where to put the image. In pygame we always pass positions as an (X,Y) coordinate. +This represents the number of pixels to the right, and the number of pixels +down to place the image. The top-left corner of a Surface is coordinate (0, +0). Moving to the right a little would be (10, 0), and then moving down just +as much would be (10, 10). When blitting, the position argument represents +where the topleft corner of the source should be placed on the destination.

+

Pygame comes with a convenient container for these coordinates, it is a +Rect. The Rect basically represents a rectangular area in these coordinates. +It has topleft corner and a size. The Rect comes with a lot of convenient +methods which help you move and position them. In our next examples we will +represent the positions of our objects with the Rects.

+

Also know that many functions in pygame expect Rect arguments. All of these +functions can also accept a simple tuple of 4 elements (left, top, width, +height). You aren't always required to use these Rect objects, but you will +mainly want to. Also, the blit() function can accept a Rect as its position +argument, it simply uses the topleft corner of the Rect as the real position.

+
+
+

Changing The Background¶

+

In all our previous sections, we've been storing the background as a list +of different types of ground. That is a good way to create a tile-based game, +but we want smooth scrolling. To make that a little easier, we're going to +change the background into a single image that covers the whole screen. This +way, when we want to "erase" our objects (before redrawing them) we only need +to blit the section of the erased background onto the screen.

+

By passing an optional third Rect argument to blit, we tell blit to only +use that subsection of the source image. You'll see that in use below as we +erase the player image.

+

Also note, now when we finish drawing to the screen, we call pygame.display.update() +which will show everything we've drawn onto the screen.

+
+
+

Smooth Movement¶

+

To make something appear to move smoothly, we only want to move it a couple +pixels at a time. Here is the code to make an object move smoothly across +the screen. Based on what we already now know, this should look pretty simple.

+
>>> screen = create_screen()
+>>> player = load_player_image()
+>>> background = load_background_image()
+>>> screen.blit(background, (0, 0))        #draw the background
+>>> position = player.get_rect()
+>>> screen.blit(player, position)          #draw the player
+>>> pygame.display.update()                #and show it all
+>>> for x in range(100):                   #animate 100 frames
+...     screen.blit(background, position, position) #erase
+...     position = position.move(2, 0)     #move player
+...     screen.blit(player, position)      #draw new player
+...     pygame.display.update()            #and show it all
+...     pygame.time.delay(100)             #stop the program for 1/10 second
+
+
+

There you have it. This is all the code that is needed to smoothly animate +an object across the screen. We can even use a pretty background character. +Another benefit of doing the background this way, the image for the player +can have transparency or cutout sections and it will still draw correctly +over the background (a free bonus).

+

We also throw in a call to pygame.time.delay() at the end of our loop above. +This slows down our program a little, otherwise it might run so fast you might +not see it.

+
+
+

So, What Next?¶

+

Well there we have it. Hopefully this article has done everything it promised +to do. But, at this point the code really isn't ready for the next best-selling +game. How do we easily have multiple moving objects? What exactly are those +mysterious functions like load_player_image()? We also need a way to get simple +user input, and loop for more than 100 frames. We'll take the example we +have here, and turn it into an object oriented creation that would make momma +proud.

+
+
+

First, The Mystery Functions¶

+

Full information on these types of functions can be found in other tutorials +and reference. The pygame.image module has a load() function which will do +what we want. The lines to load the images should become this.

+
>>> player = pygame.image.load('player.bmp').convert()
+>>> background = pygame.image.load('liquid.bmp').convert()
+
+
+

We can see that's pretty simple, the load function just takes a filename +and returns a new Surface with the loaded image. After loading we make a call +to the Surface method, convert(). Convert returns us a new Surface of the +image, but now converted to the same pixel format as our display. Since the +images will be the same format at the screen, they will blit very quickly. +If we did not convert, the blit() function is slower, since it has to convert +from one type of pixel to another as it goes.

+

You may also have noticed that both the load() and convert() return new +Surfaces. This means we're really creating two Surfaces on each of these +lines. In other programming languages, this results in a memory leak (not +a good thing). Fortunately Python is smart enough to handle this, and pygame +will properly clean up the Surface we end up not using.

+

The other mystery function we saw in the above example was create_screen(). +In pygame it is simple to create a new window for graphics. The code to create +a 640x480 surface is below. By passing no other arguments, pygame will just +pick the best color depth and pixel format for us.

+
>>> screen = pygame.display.set_mode((640, 480))
+
+
+
+
+

Handling Some Input¶

+

We desperately need to change the main loop to look for any user input, (like +when the user closes the window). We need to add "event handling" to our +program. All graphical programs use this Event Based design. The program +gets events like "keyboard pressed" or "mouse moved" from the computer. Then +the program responds to the different events. Here's what the code should +look like. Instead of looping for 100 frames, we'll keep looping until the +user asks us to stop.

+
>>> while 1:
+...     for event in pygame.event.get():
+...         if event.type in (QUIT, KEYDOWN):
+...             sys.exit()
+...     move_and_draw_all_game_objects()
+
+
+

What this code simply does is, first loop forever, then check if there are +any events from the user. We exit the program if the user presses the keyboard +or the close button on the window. After we've checked all the events we +move and draw our game objects. (We'll also erase them before they move, +too)

+
+
+

Moving Multiple Images¶

+

Here's the part where we're really going to change things around. Let's +say we want 10 different images moving around on the screen. A good way to +handle this is to use python's classes. We'll create a class that represents +our game object. This object will have a function to move itself, and then +we can create as many as we like. The functions to draw and move the object +need to work in a way where they only move one frame (or one step) at a time. +Here's the python code to create our class.

+
>>> class GameObject:
+...     def __init__(self, image, height, speed):
+...         self.speed = speed
+...         self.image = image
+...         self.pos = image.get_rect().move(0, height)
+...     def move(self):
+...         self.pos = self.pos.move(0, self.speed)
+...         if self.pos.right > 600:
+...             self.pos.left = 0
+
+
+

So we have two functions in our class. The init function constructs our object. +It positions the object and sets its speed. The move method moves the object +one step. If it's gone too far, it moves the object back to the left.

+
+
+

Putting It All Together¶

+

Now with our new object class, we can put together the entire game. Here +is what the main function for our program will look like.

+
>>> screen = pygame.display.set_mode((640, 480))
+>>> player = pygame.image.load('player.bmp').convert()
+>>> background = pygame.image.load('background.bmp').convert()
+>>> screen.blit(background, (0, 0))
+>>> objects = []
+>>> for x in range(10):                    #create 10 objects</i>
+...     o = GameObject(player, x*40, x)
+...     objects.append(o)
+>>> while 1:
+...     for event in pygame.event.get():
+...         if event.type in (QUIT, KEYDOWN):
+...             sys.exit()
+...     for o in objects:
+...         screen.blit(background, o.pos, o.pos)
+...     for o in objects:
+...         o.move()
+...         screen.blit(o.image, o.pos)
+...     pygame.display.update()
+...     pygame.time.delay(100)
+
+
+

And there it is. This is the code we need to animate 10 objects on the screen. +The only point that might need explaining is the two loops we use to clear +all the objects and draw all the objects. In order to do things properly, +we need to erase all the objects before drawing any of them. In our sample +here it may not matter, but when objects are overlapping, using two loops +like this becomes important.

+
+
+

You Are On Your Own From Here¶

+

So what would be next on your road to learning? Well first playing around +with this example a bit. The full running version of this example is available +in the pygame examples directory. It is the example named +moveit.py . +Take a look at the code and play with it, run it, learn it.

+

Things you may want to work on is maybe having more than one type of object. +Finding a way to cleanly "delete" objects when you don't want to show them +any more. Also updating the display.update() call to pass a list of the areas +on-screen that have changed.

+

There are also other tutorials and examples in pygame that cover these +issues. So when you're ready to keep learning, keep on reading. :-)

+

Lastly, you can feel free to come to the pygame mailing list or chatroom +with any questions on this stuff. There's always folks on hand who can help +you out with this sort of business.

+

Lastly, have fun, that's what games are for!

+
+
+
+ + +

+
+Edit on GitHub +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/tut/PygameIntro.html b/venv/Lib/site-packages/pygame/docs/generated/tut/PygameIntro.html new file mode 100644 index 0000000..0331936 --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/tut/PygameIntro.html @@ -0,0 +1,418 @@ + + + + + + + + + Pygame Intro — pygame v2.1.2 documentation + + + + + + + + + + + + + +
+ +
+ + + + + +
+
+ +
+
+ +
+
+

Python Pygame Introduction¶

+
+
Author
+

Pete Shinners

+
+
Contact
+

pete@shinners.org

+
+
+

This article is an introduction to the pygame library +for Python programmers. +The original version appeared in the Py Zine, +volume 1 issue 3. This version contains minor revisions, to +create an all-around better article. Pygame is a Python extension +library that wraps the SDL library +and its helpers.

+
+

HISTORY¶

+

Pygame started in the summer of 2000. Being a C programmer of many +years, I discovered both Python and SDL at about the same time. You are +already familiar with Python, which was at version 1.5.2. You may need +an introduction to SDL, which is the Simple DirectMedia Layer. +Created by Sam Lantinga, SDL is a cross-platform C library for +controlling multimedia, comparable to DirectX. It has been used for +hundreds of commercial and open source games. I was impressed at how clean +and straightforward both projects were and it wasn't long before I +realized mixing Python and SDL was an interesting proposal.

+

I discovered a small project already under-way with exactly the same +idea, PySDL. Created by Mark Baker, PySDL was a straightforward +implementation of SDL as a Python extension. The interface was cleaner +than a generic SWIG wrapping, but I felt it forced a "C style" of code. +The sudden death of PySDL prompted me to take on a new project of my +own.

+

I wanted to put together a project that really took advantage of +Python. My goal was to make it easy to do the simple things, and +straightforward to do the difficult things. Pygame was started in +October, 2000. Six months later pygame version 1.0 was released.

+
+
+

TASTE¶

+

I find the best way to understand a new library is to jump straight +into an example. In the early days of pygame, I created a bouncing ball +animation with 7 lines of code. Let's take a look at a friendlier +version of that same thing. This should be simple enough to follow +along, and a complete breakdown follows.

+../_images/intro_ball.gif +
 1import sys, pygame
+ 2pygame.init()
+ 3
+ 4size = width, height = 320, 240
+ 5speed = [2, 2]
+ 6black = 0, 0, 0
+ 7
+ 8screen = pygame.display.set_mode(size)
+ 9
+10ball = pygame.image.load("intro_ball.gif")
+11ballrect = ball.get_rect()
+12
+13while 1:
+14    for event in pygame.event.get():
+15        if event.type == pygame.QUIT: sys.exit()
+16
+17    ballrect = ballrect.move(speed)
+18    if ballrect.left < 0 or ballrect.right > width:
+19        speed[0] = -speed[0]
+20    if ballrect.top < 0 or ballrect.bottom > height:
+21        speed[1] = -speed[1]
+22
+23    screen.fill(black)
+24    screen.blit(ball, ballrect)
+25    pygame.display.flip()
+
+
+

This is as simple as you can get for a bouncing animation. +First we see importing and initializing pygame is nothing noteworthy. +The import pygame imports the package with all the available +pygame modules. +The call to pygame.init() initializes each of these modules.

+

On line 8 we create a +graphical window with the call to pygame.display.set_mode(). +Pygame and SDL make this easy by defaulting to the best graphics modes +for the graphics hardware. You can override the mode and SDL will +compensate for anything the hardware cannot do. Pygame represents +images as Surface objects. +The display.set_mode() function creates a new Surface +object that represents the actual displayed graphics. Any drawing you +do to this Surface will become visible on the monitor.

+

At line 10 we load +our ball image. Pygame supports a variety of image formats through the +SDL_image library, including BMP, JPG, PNG, TGA, and GIF. +The pygame.image.load() function +returns us a Surface with the ball data. The Surface will keep any +colorkey or alpha transparency from the file. After loading the ball +image we create a variable named ballrect. Pygame comes with a +convenient utility object type named Rect, +which represents a rectangular area. Later, in the animation part of +the code, we will see what the Rect objects can do.

+

At this point, line 13, +our program is initialized and ready to run. Inside an infinite loop we +check for user input, move the ball, and then draw the ball. If you are +familiar with GUI programming, you have had experience with events and +event loops. In pygame this is no different, +we check if a QUIT event has happened. If so we +simply exit the program, pygame will ensure everything is cleanly +shutdown.

+

It is time to update our position for the ball. +Lines 17 moves the ballrect variable by the current speed. +Lines 18 thru 21 reverse the speed if the ball has moved outside the screen. +Not exactly Newtonian physics, but it is all we need.

+

On line 23 we erase +the screen by filling it with a black RGB color. If you have never +worked with animations this may seem strange. You may be asking "Why do +we need to erase anything, why don't we just move the ball on the +screen?" That is not quite the way computer animation works. Animation +is nothing more than a series of single images, which when displayed in +sequence do a very good job of fooling the human eye into seeing +motion. The screen is just a single image that the user sees. If we did +not take the time to erase the ball from the screen, we would actually +see a "trail" of the ball as we continuously draw the ball in its new +positions.

+

On line 24 we draw the ball image onto the screen. +Drawing of images is handled by the +Surface.blit() method. +A blit basically means copying pixel colors from one image to another. +We pass the blit method a source Surface +to copy from, and a position to place the source onto the destination.

+

The last thing we need to do is actually update the visible display. +Pygame manages the display with a double buffer. When we are finished +drawing we call the pygame.display.flip()Update the full display Surface to the screen method. +This makes everything we have drawn on the screen Surface +become visible. This buffering makes sure we only see completely drawn +frames on the screen. Without it, the user would see the half completed +parts of the screen as they are being created.

+

That concludes this short introduction to pygame. Pygame also has +modules to do things like input handling for the keyboard, mouse, and +joystick. It can mix audio and decode streaming music. +With the Surfaces you can draw simple +shapes, rotate and scale the picture, and even manipulate the pixels of +an image in realtime as numpy arrays. +Pygame also has the ability to act as a +cross platform display layer for PyOpenGL. Most of the pygame modules +are written in C, few are actually done in Python.

+

The pygame website has full reference documentation for every pygame +function and tutorials for all ranges of users. The pygame source comes +with many examples of things like monkey punching and UFO shooting.

+
+
+

PYTHON AND GAMING¶

+

"Is Python suitable for gaming?" The answer is, "It depends on the +game."

+

Python is actually quite capable at running games. It will likely even +surprise you how much is possible in under 30 milliseconds. Still, it +is not hard to reach the ceiling once your game begins to get more +complex. Any game running in realtime will be making full use of the +computer.

+../_images/intro_blade.jpg +

Over the past several years there has been an interesting trend in game development, +the move towards higher level languages. Usually a game is split into +two major parts. The game engine, which must be as fast as possible, +and the game logic, which makes the engine actually do something. It +wasn't long ago when the engine of a game was written in assembly, with +portions written in C. Nowadays, C has moved to the game engine, while +often the game itself is written in higher level scripting languages. +Games like Quake3 and Unreal run these scripts as portable bytecode.

+

In early 2001, developer Rebel Act Studios finished their game, +Severance: Blade of Darkness. Using their own custom 3D engine, the +rest of the game is written with Python. The game is a bloody action +3rd person perspective fighter. You control medieval warriors into +intricate decapitating combination attacks while exploring dungeons and +castles. You can download third party add-ons for this game, and find +they are nothing more than Python source files.

+

More recently, Python has been used in a variety of games like Freedom +Force, and Humungous' Backyard Sports Series.

+../_images/intro_freedom.jpg +

Pygame and SDL serve as an excellent C engine for 2D games. +Games will still find the largest part of their runtime is spent +inside SDL handling the graphics. +SDL can take advantage of graphics hardware acceleration. +Enabling this can change a game from running around 40 frames per +second to over 200 frames per second. When you see your Python game +running at 200 frames per second, you realize that Python and games can +work together.

+

It is impressive how well both Python and SDL work on multiple +platforms. For example, in May of 2001 I released my own full pygame +project, SolarWolf, an arcade style action game. One thing that has +surprised me is that one year later there has been no need for any +patches, bug fixes, or updates. The game was developed entirely on +windows, but runs on Linux, Mac OSX, and many Unixes without any extra +work on my end.

+

Still, there are very clear limitations. The best way to manage +hardware accelerated graphics is not always the way to get fastest +results from software rendering. Hardware support is not available on +all platforms. When a game gets more complex, it often must commit to +one or the other. SDL has some other design limitations, things like +full screen scrolling graphics can quickly bring your game down to +unplayable speeds. While SDL is not suitable for all types of games, +remember companies like Loki have used SDL to run a wide variety of +retail quality titles.

+

Pygame is fairly low-level when it comes to writing games. You'll +quickly find yourself needing to wrap common functions into your own +game environment. The great thing about this is there is nothing inside +pygame to get in your way. Your program is in full control of +everything. The side effect of that is you will find yourself borrowing +a lot of code to get a more advanced framework put together. You'll +need a better understanding of what you are doing.

+
+
+

CLOSING¶

+

Developing games is very rewarding, there is something exciting about +being able to see and interact with the code you've written. Pygame +currently has almost 30 other projects using it. Several of them are +ready to play now. You may be surprised to visit the pygame website, +and see what other users have been able to do with Python.

+

One thing that has caught my attention is the amount of people coming +to Python for the first time to try game development. I can see why +games are a draw for new programmers, but it can be difficult since +creating games requires a firmer understanding of the language. I've +tried to support this group of users by writing many examples and +pygame tutorials for people new to these concepts.

+

In the end, my advice is to keep it simple. I cannot stress this +enough. If you are planning to create your first game, there is a +lot to learn. Even a simpler game will challenge your designs, and +complex games don't necessarily mean fun games. When you understand +Python, you can use pygame to create a simple game in only one or two +weeks. From there you'll need a surprising amount of time to add +the polish to make that into a full presentable game.

+
+

Pygame Modules Overview¶

+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

cdrom

playback

cursors

load cursor images, includes standard cursors

display

control the display window or screen

draw

draw simple shapes onto a Surface

event

manage events and the event queue

font

create and render TrueType fonts

image

save and load images

joystick

manage joystick devices

key

manage the keyboard

mouse

manage the mouse

sndarray

manipulate sounds with numpy

surfarray

manipulate images with numpy

time

control timing

transform

scale, rotate, and flip images

+
+
+
+
+ + +

+
+Edit on GitHub +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/tut/SpriteIntro.html b/venv/Lib/site-packages/pygame/docs/generated/tut/SpriteIntro.html new file mode 100644 index 0000000..b691185 --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/tut/SpriteIntro.html @@ -0,0 +1,498 @@ + + + + + + + + + Pygame Tutorials - Sprite Module Introduction — pygame v2.1.2 documentation + + + + + + + + + + + + + +
+ +
+ + + + + +
+
+ +
+
+ +
+
+

Sprite Module Introduction¶

+
+
Author
+

Pete Shinners

+
+
Contact
+

pete@shinners.org

+
+
+

Pygame version 1.3 comes with a new module, pygame.sprite. This module is +written in Python and includes some higher-level classes to manage your game +objects. By using this module to its full potential, you can easily manage and +draw your game objects. The sprite classes are very optimized, so it's likely +your game will run faster with the sprite module than without.

+

The sprite module is also meant to be very generic. It turns out you can use it +with nearly any type of gameplay. All this flexibility comes with a slight +penalty, it needs a little understanding to properly use it. The +reference documentation for the sprite module can keep +you running, but you'll probably need a bit more explanation of how to use +pygame.sprite in your own game.

+

Several of the pygame examples (like "chimp" and "aliens") have been updated to +use the sprite module. You may want to look into those first to see what this +sprite module is all about. The chimp module even has its own line-by-line +tutorial, which may help get more an understanding of programming with python +and pygame.

+

Note that this introduction will assume you have a bit of experience +programming with python, and are somewhat familiar with the different parts of +creating a simple game. In this tutorial the word "reference" is occasionally +used. This represents a python variable. Variables in python are references, +so you can have several variables all pointing to the same object.

+
+

History Lesson¶

+

The term "sprite" is a holdover from older computer and game machines. These +older boxes were unable to draw and erase normal graphics fast enough for them +to work as games. These machines had special hardware to handle game like +objects that needed to animate very quickly. These objects were called +"sprites" and had special limitations, but could be drawn and updated very +fast. They usually existed in special overlay buffers in the video. These days +computers have become generally fast enough to handle sprite like objects +without dedicated hardware. The term sprite is still used to represent just +about anything in a 2D game that is animated.

+
+
+

The Classes¶

+

The sprite module comes with two main classes. The first is Sprite, which should be used as a base class for all your game +objects. This class doesn't really do anything on its own, it just includes +several functions to help manage the game object. The other type of class is +Group. The Group class is a container for +different Sprite objects. There are actually several different types of +group classes. Some of the Groups can draw all the elements they contain, +for example.

+

This is all there really is to it. We'll start with a description of what each +type of class does, and then discuss the proper ways to use these two classes.

+
+
+

The Sprite Class¶

+

As mentioned before, the Sprite class is designed to be a base class for all +your game objects. You cannot really use it on its own, as it only has several +methods to help it work with the different Group classes. The sprite keeps +track of which groups it belongs to. +The class constructor (__init__ method) takes an argument of a +Group (or list of Groups) the Sprite instance should belong to. +You can also change the Group membership for the Sprite with the +add() and +remove() methods. +There is also a groups() method, +which returns a list of the current groups containing the sprite.

+

When using the your Sprite classes it's best to think of them as "valid" or +"alive" when they are belonging to one or more Groups. When you remove the +instance from all groups pygame will clean up the object. (Unless you have your +own references to the instance somewhere else.) The kill() method removes the sprite from all groups it +belongs to. This will cleanly delete the sprite object. If you've put some +little games together, you'll know sometimes cleanly deleting a game object can +be tricky. The sprite also comes with an alive() method, which returns true if it is still a +member of any groups.

+
+
+

The Group Class¶

+

The Group class is just a simple container. Similar to the sprite, it has +an add() and remove() method which can change which sprites belong to +the group. You also can pass a sprite or list of sprites to the constructor +(__init__() method) to create a Group instance that contains some +initial sprites.

+

The Group has a few other methods like empty() to remove all sprites from the group and +copy() which will return a copy of the group +with all the same members. Also the has() +method will quickly check if the Group contains a sprite or list of +sprites.

+

The other function you will use frequently is the sprites() method. This returns an object that can be +looped on to access every sprite the group contains. Currently this is just a +list of the sprites, but in later version of python this will likely use +iterators for better performance.

+

As a shortcut, the Group also has an update() method, which will call an update() method on +every sprite in the group. Passing the same arguments to each one. Usually in a +game you need some function that updates the state of a game object. It's very +easy to call your own methods using the Group.sprites() method, but this is +a shortcut that's used enough to be included. Also note that the base +Sprite class has a "dummy" update() method that takes any sort of +arguments and does nothing.

+

Lastly, the Group has a couple other methods that allow you to use it with +the builtin len() function, getting the number of sprites it contains, and +the "truth" operator, which allows you to do "if mygroup:" to check if the +group has any sprites.

+
+
+

Mixing Them Together¶

+

At this point the two classes seem pretty basic. Not doing a lot more than you +can do with a simple list and your own class of game objects. But there are +some big advantages to using the Sprite and Group together. A sprite +can belong to as many groups as you want. Remember as soon as it belongs to no +groups, it will usually be cleared up (unless you have other "non-group" +references to that object).

+

The first big thing is a fast simple way to categorize sprites. For example, +say we had a Pacman-like game. We could make separate groups for the different +types of objects in the game. Ghosts, Pac, and Pellets. When Pac eats a power +pellet, we can change the state for all ghost objects by effecting everything +in the Ghost group. This is quicker and simpler than looping through a list +of all the game objects and checking which ones are ghosts.

+

Adding and removing groups and sprites from each other is a very fast +operation, quicker than using lists to store everything. Therefore you can very +efficiently change group memberships. Groups can be used to work like simple +attributes for each game object. Instead of tracking some attribute like +"close_to_player" for a bunch of enemy objects, you could add them to a +separate group. Then when you need to access all the enemies that are near the +player, you already have a list of them, instead of going through a list of all +the enemies, checking for the "close_to_player" flag. Later on your game could +add multiple players, and instead of adding more "close_to_player2", +"close_to_player3" attributes, you can easily add them to different groups or +each player.

+

Another important benefit of using the Sprites and Groups is that the groups +cleanly handle the deleting (or killing) of game objects. In a game where many +objects are referencing other objects, sometimes deleting an object can be the +hardest part, since it can't go away until it is not referenced by anyone. Say +we have an object that is "chasing" another object. The chaser can keep a +simple Group that references the object (or objects) it is chasing. If the +object being chased happens to be destroyed, we don't need to worry about +notifying the chaser to stop chasing. The chaser can see for itself that its +group is now empty, and perhaps find a new target.

+

Again, the thing to remember is that adding and removing sprites from groups is +a very cheap/fast operation. You may be best off by adding many groups to +contain and organize your game objects. Some could even be empty for large +portions of the game, there isn't any penalties for managing your game like +this.

+
+
+

The Many Group Types¶

+

The above examples and reasons to use Sprites and Groups are only a tip +of the iceberg. Another advantage is that the sprite module comes with several +different types of Groups. These groups all work just like a regular old +Group, but they also have added functionality (or slightly different +functionality). Here's a list of the Group classes included with the +sprite module.

+
+

Group

+
+

This is the standard "no frills" group mainly explained above. Most of the +other Groups are derived from this one, but not all.

+
+

GroupSingle

+
+

This works exactly like the regular Group class, but it only contains +the most recently added sprite. Therefore when you add a sprite to this group, +it "forgets" about any previous sprites it had. Therefore it always contains +only one or zero sprites.

+
+

RenderPlain

+
+

This is a standard group derived from Group. It has a draw() method +that draws all the sprites it contains to the screen (or any Surface). For +this to work, it requires all sprites it contains to have a "image" and "rect" +attributes. It uses these to know what to blit, and where to blit it.

+
+

RenderClear

+
+

This is derived from the RenderPlain group, and adds a method named +clear(). This will erase the previous position of all drawn sprites. It +uses a background image to fill in the areas where the sprite were. It is smart +enough to handle deleted sprites and properly clear them from the screen when +the clear() method is called.

+
+

RenderUpdates

+
+

This is the Cadillac of rendering Groups. It is inherited from +RenderClear, but changes the draw() method to also return a list of +pygame Rects, which represent all the areas on screen that have been +changed.

+
+
+

That is the list of different groups available We'll discuss more about these +rendering groups in the next section. There's nothing stopping you from +creating your own Group classes as well. They are just python code, so you can +inherit from one of these and add/change whatever you want. In the future I +hope we can add a couple more Groups to this list. A GroupMulti which +is like the GroupSingle, but can hold up to a given number of sprites (in +some sort of circular buffer?). Also a super-render group that can clear the +position of the old sprites without needing a background image to do it (by +grabbing a copy of the screen before blitting). Who knows really, but in the +future we can add more useful classes to this list.

+
+
+

The Rendering Groups¶

+

From above we can see there are three different rendering groups. We could +probably just get away with the RenderUpdates one, but it adds overhead not +really needed for something like a scrolling game. So we have a couple tools +here, pick the right one for the right job.

+

For a scrolling type game, where the background completely changes every frame, +we obviously don't need to worry about python's update rectangles in the call +to display.update(). You should definitely go with the RenderPlain +group here to manage your rendering.

+

For games where the background is more stationary, you definitely don't want +pygame updating the entire screen (since it doesn't need to). This type of game +usually involves erasing the old position of each object, then drawing it in a +new place for each frame. This way we are only changing what is necessary. +Most of the time you will just want to use the RenderUpdates class here. +Since you will also want to pass this list of changes to the +display.update() function.

+

The RenderUpdates class also does a good job at minimizing overlapping +areas in the list of updated rectangles. If the previous position and current +position of an object overlap, it will merge them into a single rectangle. +Combined with the fact that it properly handles deleted objects, this is +one powerful Group class. If you've written a game that manages the changed +rectangles for the objects in a game, you know this the cause for a lot of +messy code in your game. Especially once you start to throw in objects that can +be deleted at any time. All this work is reduced to a clear() and +draw() method with this monster class. Plus with the overlap checking, it +is likely faster than when you did it manually.

+

Also note that there's nothing stopping you from mixing and matching these +render groups in your game. You should definitely use multiple rendering groups +when you want to do layering with your sprites. Also if the screen is split +into multiple sections, perhaps each section of the screen should use an +appropriate render group?

+
+
+

Collision Detection¶

+

The sprite module also comes with two very generic collision detection +functions. For more complex games, these really won't work for you, but you +can easily grab the source code for them, and modify them as needed.

+

Here's a summary of what they are, and what they do.

+
+

spritecollide(sprite, group, dokill) -> list

+
+

This checks for collisions between a single sprite and the sprites in a group. +It requires a "rect" attribute for all the sprites used. It returns a list of +all the sprites that overlap with the first sprite. The "dokill" argument is a +boolean argument. If it is true, the function will call the kill() method +on all the sprites. This means the last reference to each sprite is probably in +the returned list. Once the list goes away so do the sprites. A quick example +of using this in a loop

+
>>> for bomb in sprite.spritecollide(player, bombs, 1):
+...     boom_sound.play()
+...     Explosion(bomb, 0)
+
+
+

This finds all the sprites in the "bomb" group that collide with the player. +Because of the "dokill" argument it deletes all the crashed bombs. For each +bomb that did collide, it plays a "boom" sound effect, and creates a new +Explosion where the bomb was. (Note, the Explosion class here knows to +add each instance to the appropriate class, so we don't need to store it in a +variable, that last line might feel a little "funny" to you python programmers.

+
+

groupcollide(group1, group2, dokill1, dokill2) -> dictionary

+
+

This is similar to the spritecollide function, but a little more complex. +It checks for collisions for all the sprites in one group, to the sprites in +another. There is a dokill argument for the sprites in each list. When +dokill1 is true, the colliding sprites in group1 will be kill()``ed. +When ``dokill2 is true, we get the same results for group2. The +dictionary it returns works like this; each key in the dictionary is a sprite +from group1 that had a collision. The value for that key is a list of the +sprites that it collided with. Perhaps another quick code sample explains it +best

+
>>> for alien in sprite.groupcollide(aliens, shots, 1, 1).keys()
+...     boom_sound.play()
+...     Explosion(alien, 0)
+...     kills += 1
+
+
+

This code checks for the collisions between player bullets and all the aliens +they might intersect. In this case we only loop over the dictionary keys, but +we could loop over the values() or items() if we wanted to do something +to the specific shots that collided with aliens. If we did loop over the +values() we would be looping through lists that contain sprites. The same +sprite may even appear more than once in these different loops, since the same +"shot" could have collided against multiple "aliens".

+
+
+

Those are the basic collision functions that come with pygame. It should be +easy to roll your own that perhaps use something different than the "rect" +attribute. Or maybe try to fine-tweak your code a little more by directly +effecting the collision object, instead of building a list of the collision? +The code in the sprite collision functions is very optimized, but you could +speed it up slightly by taking out some functionality you don't need.

+
+
+

Common Problems¶

+

Currently there is one main problem that catches new users. When you derive +your new sprite class with the Sprite base, you must call the +Sprite.__init__() method from your own class __init__() method. If you +forget to call the Sprite.__init__() method, you get a cryptic error, like +this

+
AttributeError: 'mysprite' instance has no attribute '_Sprite__g'
+
+
+
+
+

Extending Your Own Classes (Advanced)¶

+

Because of speed concerns, the current Group classes try to only do exactly +what they need, and not handle a lot of general situations. If you decide you +need extra features, you may want to create your own Group class.

+

The Sprite and Group classes were designed to be extended, so feel free +to create your own Group classes to do specialized things. The best place +to start is probably the actual python source code for the sprite module. +Looking at the current Sprite groups should be enough example on how to +create your own.

+

For example, here is the source code for a rendering Group that calls a +render() method for each sprite, instead of just blitting an "image" +variable from it. Since we want it to also handle updated areas, we will start +with a copy of the original RenderUpdates group, here is the code:

+
class RenderUpdatesDraw(RenderClear):
+    """call sprite.draw(screen) to render sprites"""
+    def draw(self, surface):
+        dirty = self.lostsprites
+        self.lostsprites = []
+        for s, r in self.spritedict.items():
+            newrect = s.draw(screen) #Here's the big change
+            if r is 0:
+                dirty.append(newrect)
+            else:
+                dirty.append(newrect.union(r))
+            self.spritedict[s] = newrect
+        return dirty
+
+
+

Following is more information on how you could create your own Sprite and +Group objects from scratch.

+

The Sprite objects only "require" two methods. "add_internal()" and +"remove_internal()". These are called by the Group classes when they are +removing a sprite from themselves. The add_internal() and +remove_internal() have a single argument which is a group. Your Sprite +will need some way to also keep track of the Groups it belongs to. You will +likely want to try to match the other methods and arguments to the real +Sprite class, but if you're not going to use those methods, you sure don't +need them.

+

It is almost the same requirements for creating your own Group. In fact, if +you look at the source you'll see the GroupSingle isn't derived from the +Group class, it just implements the same methods so you can't really tell +the difference. Again you need an "add_internal()" and "remove_internal()" +method that the sprites call when they want to belong or remove themselves from +the group. The add_internal() and remove_internal() have a single +argument which is a sprite. The only other requirement for the Group +classes is they have a dummy attribute named "_spritegroup". It doesn't matter +what the value is, as long as the attribute is present. The Sprite classes can +look for this attribute to determine the difference between a "group" and any +ordinary python container. (This is important, because several sprite methods +can take an argument of a single group, or a sequence of groups. Since they +both look similar, this is the most flexible way to "see" the difference.)

+

You should go through the code for the sprite module. While the code is a bit +"tuned", it's got enough comments to help you follow along. There's even a +TODO section in the source if you feel like contributing.

+
+
+
+ + +

+
+Edit on GitHub +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/tut/SurfarrayIntro.html b/venv/Lib/site-packages/pygame/docs/generated/tut/SurfarrayIntro.html new file mode 100644 index 0000000..9bc37f4 --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/tut/SurfarrayIntro.html @@ -0,0 +1,661 @@ + + + + + + + + + Pygame Tutorials - Surfarray Introduction — pygame v2.1.2 documentation + + + + + + + + + + + + + +
+ +
+ + + + + +
+
+ +
+
+ +
+
+

Surfarray Introduction¶

+
+
Author
+

Pete Shinners

+
+
Contact
+

pete@shinners.org

+
+
+
+

Introduction¶

+

This tutorial will attempt to introduce users to both NumPy and the pygame +surfarray module. To beginners, the code that uses surfarray can be quite +intimidating. But actually there are only a few concepts to understand and +you will be up and running. Using the surfarray module, it becomes possible +to perform pixel level operations from straight python code. The performance +can become quite close to the level of doing the code in C.

+

You may just want to jump down to the "Examples" section to get an +idea of what is possible with this module, then start at the beginning here +to work your way up.

+

Now I won't try to fool you into thinking everything is very easy. To get +more advanced effects by modifying pixel values is very tricky. Just mastering +Numeric Python (SciPy's original array package was Numeric, the predecessor of NumPy) +takes a lot of learning. In this tutorial I'll be sticking with +the basics and using a lot of examples in an attempt to plant seeds of wisdom. +After finishing the tutorial you should have a basic handle on how the surfarray +works.

+
+
+

Numeric Python¶

+

If you do not have the python NumPy package installed, +you will need to do that now. +You can download the package from the +NumPy Downloads Page +To make sure NumPy is working for you, +you should get something like this from the interactive python prompt.

+
>>> from numpy import *                    #import numeric
+>>> a = array((1,2,3,4,5))                 #create an array
+>>> a                                      #display the array
+array([1, 2, 3, 4, 5])
+>>> a[2]                                   #index into the array
+3
+>>> a*2                                    #new array with twiced values
+array([ 2,  4,  6,  8, 10])
+
+
+

As you can see, the NumPy module gives us a new data type, the array. +This object holds an array of fixed size, and all values inside are of the same +type. The arrays can also be multidimensional, which is how we will use them +with images. There's a bit more to it than this, but it is enough to get us +started.

+

If you look at the last command above, you'll see that mathematical operations +on NumPy arrays apply to all values in the array. This is called "element-wise +operations". These arrays can also be sliced like normal lists. The slicing +syntax is the same as used on standard python objects. +(so study up if you need to :] ). +Here are some more examples of working with arrays.

+
>>> len(a)                                 #get array size
+5
+>>> a[2:]                                  #elements 2 and up
+array([3, 4, 5])
+>>> a[:-2]                                 #all except last 2
+array([1, 2, 3])
+>>> a[2:] + a[:-2]                         #add first and last
+array([4, 6, 8])
+>>> array((1,2,3)) + array((3,4))          #add arrays of wrong sizes
+Traceback (most recent call last):
+  File "<stdin>", line 1, in <module>
+ValueError: operands could not be broadcast together with shapes (3,) (2,)
+
+
+

We get an error on the last commend, because we try add together two arrays +that are different sizes. In order for two arrays two operate with each other, +including comparisons and assignment, they must have the same dimensions. It is +very important to know that the new arrays created from slicing the original all +reference the same values. So changing the values in a slice also changes the +original values. It is important how this is done.

+
>>> a                                      #show our starting array
+array([1, 2, 3, 4, 5])
+>>> aa = a[1:3]                            #slice middle 2 elements
+>>> aa                                     #show the slice
+array([2, 3])
+>>> aa[1] = 13                             #chance value in slice
+>>> a                                      #show change in original
+array([ 1, 2, 13,  4,  5])
+>>> aaa = array(a)                         #make copy of array
+>>> aaa                                    #show copy
+array([ 1, 2, 13,  4,  5])
+>>> aaa[1:4] = 0                           #set middle values to 0
+>>> aaa                                    #show copy
+array([1, 0, 0, 0, 5])
+>>> a                                      #show original again
+array([ 1, 2, 13,  4,  5])
+
+
+

Now we will look at small arrays with two +dimensions. Don't be too worried, getting started it is the same as having a +two dimensional tuple (a tuple inside a tuple). Let's get started with +two dimensional arrays.

+
>>> row1 = (1,2,3)                         #create a tuple of vals
+>>> row2 = (3,4,5)                         #another tuple
+>>> (row1,row2)                            #show as a 2D tuple
+((1, 2, 3), (3, 4, 5))
+>>> b = array((row1, row2))                #create a 2D array
+>>> b                                      #show the array
+array([[1, 2, 3],
+       [3, 4, 5]])
+>>> array(((1,2),(3,4),(5,6)))             #show a new 2D array
+array([[1, 2],
+       [3, 4],
+       [5, 6]])
+
+
+

Now with this two +dimensional array (from now on as "2D") we can index specific values +and do slicing on both dimensions. Simply using a comma to separate the indices +allows us to lookup/slice in multiple dimensions. Just using ":" as an +index (or not supplying enough indices) gives us all the values in +that dimension. Let's see how this works.

+
>>> b                                      #show our array from above
+array([[1, 2, 3],
+       [3, 4, 5]])
+>>> b[0,1]                                 #index a single value
+2
+>>> b[1,:]                                 #slice second row
+array([3, 4, 5])
+>>> b[1]                                   #slice second row (same as above)
+array([3, 4, 5])
+>>> b[:,2]                                 #slice last column
+array([3, 5])
+>>> b[:,:2]                                #slice into a 2x2 array
+array([[1, 2],
+       [3, 4]])
+
+
+

Ok, stay with me here, this is about as hard as it gets. When using NumPy +there is one more feature to slicing. Slicing arrays also allow you to specify +a slice increment. The syntax for a slice with increment is +start_index : end_index : increment.

+
>>> c = arange(10)                         #like range, but makes an array
+>>> c                                      #show the array
+array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
+>>> c[1:6:2]                               #slice odd values from 1 to 6
+array([1, 3, 5])
+>>> c[4::4]                                #slice every 4th val starting at 4
+array([4, 8])
+>>> c[8:1:-1]                              #slice 1 to 8, reversed
+array([8, 7, 6, 5, 4, 3, 2])
+
+
+

Well that is it. There's enough information there to get you started using +NumPy with the surfarray module. There's certainly a lot more to NumPy, but +this is only an introduction. Besides, we want to get on to the fun stuff, +correct?

+
+
+

Import Surfarray¶

+

In order to use the surfarray module we need to import it. Since both surfarray +and NumPy are optional components for pygame, it is nice to make sure they +import correctly before using them. In these examples I'm going to import +NumPy into a variable named N. This will let you know which functions +I'm using are from the NumPy package. +(and is a lot shorter than typing NumPy before each function)

+
try:
+    import numpy as N
+    import pygame.surfarray as surfarray
+except ImportError:
+    raise ImportError, "NumPy and Surfarray are required."
+
+
+
+
+

Surfarray Introduction¶

+

There are two main types of functions in surfarray. One set of functions for +creating an array that is a copy of a surface pixel data. The other functions +create a referenced copy of the array pixel data, so that changes to the array +directly affect the original surface. There are other functions that allow you +to access any per-pixel alpha values as arrays along with a few other helpful +functions. We will look at these other functions later on.

+

When working with these surface arrays, there are two ways of representing the +pixel values. First, they can be represented as mapped integers. This type of +array is a simple 2D array with a single integer representing the surface's +mapped color value. This type of array is good for moving parts of an image +around. The other type of array uses three RGB values to represent each pixel +color. This type of array makes it extremely simple to do types of effects that +change the color of each pixel. This type of array is also a little trickier to +deal with, since it is essentially a 3D numeric array. Still, once you get your +mind into the right mode, it is not much harder than using the normal 2D arrays.

+

The NumPy module uses a machine's natural number types to represent the data +values, so a NumPy array can consist of integers that are 8-bits, 16-bits, and 32-bits. +(the arrays can also use other types like floats and doubles, but for our image +manipulation we mainly need to worry about the integer types). +Because of this limitation of integer sizes, you must take a little extra care +that the type of arrays that reference pixel data can be properly mapped to a +proper type of data. The functions create these arrays from surfaces are:

+
+
+surfarray.pixels2d(surface)
+

Creates a 2D array (integer pixel values) that reference the original surface data. +This will work for all surface formats except 24-bit.

+
+ +
+
+surfarray.array2d(surface)
+

Creates a 2D array (integer pixel values) that is copied from any type of surface.

+
+ +
+
+surfarray.pixels3d(surface)
+

Creates a 3D array (RGB pixel values) that reference the original surface data. +This will only work on 24-bit and 32-bit surfaces that have RGB or BGR formatting.

+
+ +
+
+surfarray.array3d(surface)
+

Creates a 3D array (RGB pixel values) that is copied from any type of surface.

+
+ +

Here is a small chart that might better illustrate what types of functions +should be used on which surfaces. As you can see, both the arrayXD functions +will work with any type of surface.

+ +++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

32-bit

24-bit

16-bit

8-bit(c-map)

pixel2d

yes

yes

yes

array2d

yes

yes

yes

yes

pixel3d

yes

yes

array3d

yes

yes

yes

yes

+
+
+

Examples¶

+

With this information, we are equipped to start trying things with surface +arrays. The following are short little demonstrations that create a NumPy +array and display them in pygame. These different tests are found in the +arraydemo.py example. There is a simple function named surfdemo_show +that displays an array on the screen.

+
+
+allblack +
allblack = N.zeros((128, 128))
+surfdemo_show(allblack, 'allblack')
+
+
+

Our first example creates an all black array. Whenever you need +to create a new numeric array of a specific size, it is best to use the +zeros function. Here we create a 2D array of all zeros and display +it.

+
+
+
+
+striped +
striped = N.zeros((128, 128, 3))
+striped[:] = (255, 0, 0)
+striped[:,::3] = (0, 255, 255)
+surfdemo_show(striped, 'striped')
+
+
+

Here we are dealing with a 3D array. We start by creating an all red image. +Then we slice out every third row and assign it to a blue/green color. As you +can see, we can treat the 3D arrays almost exactly the same as 2D arrays, just +be sure to assign them 3 values instead of a single mapped integer.

+
+
+
+
+rgbarray +
imgsurface = pygame.image.load('surfarray.png')
+rgbarray = surfarray.array3d(imgsurface)
+surfdemo_show(rgbarray, 'rgbarray')
+
+
+

Here we load an image with the image module, then convert it to a 3D +array of integer RGB color elements. An RGB copy of a surface always +has the colors arranged as a[r,c,0] for the red component, +a[r,c,1] for the green component, and a[r,c,2] for blue. This can then +be used without caring how the pixels of the actual surface are configured, +unlike a 2D array which is a copy of the mapped +(raw) surface pixels. We will use this image in the rest of the samples.

+
+
+
+
+flipped +
flipped = rgbarray[:,::-1]
+surfdemo_show(flipped, 'flipped')
+
+
+

Here we flip the image vertically. All we need to do is take the original +image array and slice it using a negative increment.

+
+
+
+
+scaledown +
scaledown = rgbarray[::2,::2]
+surfdemo_show(scaledown, 'scaledown')
+
+
+

Based on the last example, scaling an image down is pretty logical. We just +slice out all the pixels using an increment of 2 vertically and horizontally.

+
+
+
+
+scaleup +
shape = rgbarray.shape
+scaleup = N.zeros((shape[0]*2, shape[1]*2, shape[2]))
+scaleup[::2,::2,:] = rgbarray
+scaleup[1::2,::2,:] = rgbarray
+scaleup[:,1::2] = scaleup[:,::2]
+surfdemo_show(scaleup, 'scaleup')
+
+
+

Scaling the image up is a little more work, but is similar to the previous +scaling down, we do it all with slicing. First we create an array that is +double the size of our original. First we copy the original array into every +other pixel of the new array. Then we do it again for every other pixel doing +the odd columns. At this point we have the image scaled properly going across, +but every other row is black, so we simply need to copy each row to the one +underneath it. Then we have an image doubled in size.

+
+
+
+
+redimg +
redimg = N.array(rgbarray)
+redimg[:,:,1:] = 0
+surfdemo_show(redimg, 'redimg')
+
+
+

Now we are using 3D arrays to change the colors. Here we +set all the values in green and blue to zero. +This leaves us with just the red channel.

+
+
+
+
+soften +
factor = N.array((8,), N.int32)
+soften = N.array(rgbarray, N.int32)
+soften[1:,:]  += rgbarray[:-1,:] * factor
+soften[:-1,:] += rgbarray[1:,:] * factor
+soften[:,1:]  += rgbarray[:,:-1] * factor
+soften[:,:-1] += rgbarray[:,1:] * factor
+soften //= 33
+surfdemo_show(soften, 'soften')
+
+
+

Here we perform a 3x3 convolution filter that will soften our image. +It looks like a lot of steps here, but what we are doing is shifting +the image 1 pixel in each direction and adding them all together (with some +multiplication for weighting). Then average all the values. It's no Gaussian, +but it's fast. One point with NumPy arrays, the precision of arithmetic +operations is determined by the array with the largest data type. +So if factor was not declared as a 1 element array of type numpy.int32, +the multiplications would be performed using numpy.int8, the 8 bit integer +type of each rgbarray element. This will cause value truncation. The soften +array must also be declared to have a larger integer size than rgbarray to +avoid truncation.

+
+
+
+
+xfade +
src = N.array(rgbarray)
+dest = N.zeros(rgbarray.shape)
+dest[:] = 20, 50, 100
+diff = (dest - src) * 0.50
+xfade = src + diff.astype(N.uint)
+surfdemo_show(xfade, 'xfade')
+
+
+

Lastly, we are cross fading between the original image and a solid bluish +image. Not exciting, but the dest image could be anything, and changing the 0.50 +multiplier will let you choose any step in a linear crossfade between two images.

+
+
+
+
+

Hopefully by this point you are starting to see how surfarray can be used to +perform special effects and transformations that are only possible at the pixel +level. At the very least, you can use the surfarray to do a lot of Surface.set_at() +Surface.get_at() type operations very quickly. But don't think you are finished +yet, there is still much to learn.

+
+
+

Surface Locking¶

+

Like the rest of pygame, surfarray will lock any Surfaces it needs to +automatically when accessing pixel data. There is one extra thing to be aware +of though. When creating the pixel arrays, the original surface will +be locked during the lifetime of that pixel array. This is important to remember. +Be sure to "del" the pixel array or let it go out of scope +(ie, when the function returns, etc).

+

Also be aware that you really don't want to be doing much (if any) +direct pixel access on hardware surfaces (HWSURFACE). This is because +the actual surface data lives on the graphics card, and transferring pixel +changes over the PCI/AGP bus is not fast.

+
+
+

Transparency¶

+

The surfarray module has several methods for accessing a Surface's alpha/colorkey +values. None of the alpha functions are affected by overall transparency of a +Surface, just the pixel alpha values. Here's the list of those functions.

+
+
+surfarray.pixels_alpha(surface)
+

Creates a 2D array (integer pixel values) that references the original +surface alpha data. +This will only work on 32-bit images with an 8-bit alpha component.

+
+ +
+
+surfarray.array_alpha(surface)
+

Creates a 2D array (integer pixel values) that is copied from any +type of surface. +If the surface has no alpha values, +the array will be fully opaque values (255).

+
+ +
+
+surfarray.array_colorkey(surface)
+

Creates a 2D array (integer pixel values) that is set to transparent +(0) wherever that pixel color matches the Surface colorkey.

+
+ +
+
+

Other Surfarray Functions¶

+

There are only a few other functions available in surfarray. You can get a better +list with more documentation on the +surfarray reference page. +There is one very useful function though.

+
+
+surfarray.blit_array(surface, array)
+

This will transfer any type of 2D or 3D surface array onto a Surface +of the same dimensions. +This surfarray blit will generally be faster than assigning an array to a +referenced pixel array. +Still, it should not be as fast as normal Surface blitting, +since those are very optimized.

+
+ +
+
+

More Advanced NumPy¶

+

There's a couple last things you should know about NumPy arrays. When dealing +with very large arrays, like the kind that are 640x480 big, there are some extra +things you should be careful about. Mainly, while using the operators like + and +* on the arrays makes them easy to use, it is also very expensive on big arrays. +These operators must make new temporary copies of the array, that are then +usually copied into another array. This can get very time consuming. Fortunately, +all the NumPy operators come with special functions that can perform the +operation "in place". For example, you would want to replace +screen[:] = screen + brightmap with the much faster +add(screen, brightmap, screen). +Anyway, you'll want to read up on the NumPy UFunc +documentation for more about this. +It is important when dealing with the arrays.

+

Another thing to be aware of when working with NumPy arrays is the datatype +of the array. Some of the arrays (especially the mapped pixel type) often return +arrays with an unsigned 8-bit value. These arrays will easily overflow if you are +not careful. NumPy will use the same coercion that you find in C programs, so +mixing an operation with 8-bit numbers and 32-bit numbers will give a result as +32-bit numbers. You can convert the datatype of an array, but definitely be +aware of what types of arrays you have, if NumPy gets in a situation where +precision would be ruined, it will raise an exception.

+

Lastly, be aware that when assigning values into the 3D arrays, they must be +between 0 and 255, or you will get some undefined truncating.

+
+
+

Graduation¶

+

Well there you have it. My quick primer on Numeric Python and surfarray. +Hopefully now you see what is possible, and even if you never use them for +yourself, you do not have to be afraid when you see code that does. Look into +the vgrade example for more numeric array action. There are also some "flame" +demos floating around that use surfarray to create a realtime fire effect.

+

Best of all, try some things on your own. Take it slow at first and build up, +I've seen some great things with surfarray already like radial gradients and +more. Good Luck.

+
+
+
+ + +

+
+Edit on GitHub +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/tut/chimp.py.html b/venv/Lib/site-packages/pygame/docs/generated/tut/chimp.py.html new file mode 100644 index 0000000..3d2925f --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/tut/chimp.py.html @@ -0,0 +1,342 @@ + + + + + + + + + pygame/examples/chimp.py — pygame v2.1.2 documentation + + + + + + + + + + + + + +
+ +
+ + + + + +
+
+ +
+
+ +
+
#!/usr/bin/env python
+""" pygame.examples.chimp
+
+This simple example is used for the line-by-line tutorial
+that comes with pygame. It is based on a 'popular' web banner.
+Note there are comments here, but for the full explanation,
+follow along in the tutorial.
+"""
+
+
+# Import Modules
+import os
+import pygame as pg
+
+if not pg.font:
+    print("Warning, fonts disabled")
+if not pg.mixer:
+    print("Warning, sound disabled")
+
+main_dir = os.path.split(os.path.abspath(__file__))[0]
+data_dir = os.path.join(main_dir, "data")
+
+
+# functions to create our resources
+def load_image(name, colorkey=None, scale=1):
+    fullname = os.path.join(data_dir, name)
+    image = pg.image.load(fullname)
+    image = image.convert()
+
+    size = image.get_size()
+    size = (size[0] * scale, size[1] * scale)
+    image = pg.transform.scale(image, size)
+
+    if colorkey is not None:
+        if colorkey == -1:
+            colorkey = image.get_at((0, 0))
+        image.set_colorkey(colorkey, pg.RLEACCEL)
+    return image, image.get_rect()
+
+
+def load_sound(name):
+    class NoneSound:
+        def play(self):
+            pass
+
+    if not pg.mixer or not pg.mixer.get_init():
+        return NoneSound()
+
+    fullname = os.path.join(data_dir, name)
+    sound = pg.mixer.Sound(fullname)
+
+    return sound
+
+
+# classes for our game objects
+class Fist(pg.sprite.Sprite):
+    """moves a clenched fist on the screen, following the mouse"""
+
+    def __init__(self):
+        pg.sprite.Sprite.__init__(self)  # call Sprite initializer
+        self.image, self.rect = load_image("fist.png", -1)
+        self.fist_offset = (-235, -80)
+        self.punching = False
+
+    def update(self):
+        """move the fist based on the mouse position"""
+        pos = pg.mouse.get_pos()
+        self.rect.topleft = pos
+        self.rect.move_ip(self.fist_offset)
+        if self.punching:
+            self.rect.move_ip(15, 25)
+
+    def punch(self, target):
+        """returns true if the fist collides with the target"""
+        if not self.punching:
+            self.punching = True
+            hitbox = self.rect.inflate(-5, -5)
+            return hitbox.colliderect(target.rect)
+
+    def unpunch(self):
+        """called to pull the fist back"""
+        self.punching = False
+
+
+class Chimp(pg.sprite.Sprite):
+    """moves a monkey critter across the screen. it can spin the
+    monkey when it is punched."""
+
+    def __init__(self):
+        pg.sprite.Sprite.__init__(self)  # call Sprite intializer
+        self.image, self.rect = load_image("chimp.png", -1, 4)
+        screen = pg.display.get_surface()
+        self.area = screen.get_rect()
+        self.rect.topleft = 10, 90
+        self.move = 18
+        self.dizzy = False
+
+    def update(self):
+        """walk or spin, depending on the monkeys state"""
+        if self.dizzy:
+            self._spin()
+        else:
+            self._walk()
+
+    def _walk(self):
+        """move the monkey across the screen, and turn at the ends"""
+        newpos = self.rect.move((self.move, 0))
+        if not self.area.contains(newpos):
+            if self.rect.left < self.area.left or self.rect.right > self.area.right:
+                self.move = -self.move
+                newpos = self.rect.move((self.move, 0))
+                self.image = pg.transform.flip(self.image, True, False)
+        self.rect = newpos
+
+    def _spin(self):
+        """spin the monkey image"""
+        center = self.rect.center
+        self.dizzy = self.dizzy + 12
+        if self.dizzy >= 360:
+            self.dizzy = False
+            self.image = self.original
+        else:
+            rotate = pg.transform.rotate
+            self.image = rotate(self.original, self.dizzy)
+        self.rect = self.image.get_rect(center=center)
+
+    def punched(self):
+        """this will cause the monkey to start spinning"""
+        if not self.dizzy:
+            self.dizzy = True
+            self.original = self.image
+
+
+def main():
+    """this function is called when the program starts.
+    it initializes everything it needs, then runs in
+    a loop until the function returns."""
+    # Initialize Everything
+    pg.init()
+    screen = pg.display.set_mode((1280, 480), pg.SCALED)
+    pg.display.set_caption("Monkey Fever")
+    pg.mouse.set_visible(False)
+
+    # Create The Backgound
+    background = pg.Surface(screen.get_size())
+    background = background.convert()
+    background.fill((170, 238, 187))
+
+    # Put Text On The Background, Centered
+    if pg.font:
+        font = pg.font.Font(None, 64)
+        text = font.render("Pummel The Chimp, And Win $$$", True, (10, 10, 10))
+        textpos = text.get_rect(centerx=background.get_width() / 2, y=10)
+        background.blit(text, textpos)
+
+    # Display The Background
+    screen.blit(background, (0, 0))
+    pg.display.flip()
+
+    # Prepare Game Objects
+    whiff_sound = load_sound("whiff.wav")
+    punch_sound = load_sound("punch.wav")
+    chimp = Chimp()
+    fist = Fist()
+    allsprites = pg.sprite.RenderPlain((chimp, fist))
+    clock = pg.time.Clock()
+
+    # Main Loop
+    going = True
+    while going:
+        clock.tick(60)
+
+        # Handle Input Events
+        for event in pg.event.get():
+            if event.type == pg.QUIT:
+                going = False
+            elif event.type == pg.KEYDOWN and event.key == pg.K_ESCAPE:
+                going = False
+            elif event.type == pg.MOUSEBUTTONDOWN:
+                if fist.punch(chimp):
+                    punch_sound.play()  # punch
+                    chimp.punched()
+                else:
+                    whiff_sound.play()  # miss
+            elif event.type == pg.MOUSEBUTTONUP:
+                fist.unpunch()
+
+        allsprites.update()
+
+        # Draw Everything
+        screen.blit(background, (0, 0))
+        allsprites.draw(screen)
+        pg.display.flip()
+
+    pg.quit()
+
+
+# Game Over
+
+
+# this calls the 'main' function when this script is executed
+if __name__ == "__main__":
+    main()
+
+
+
+ + +

+
+Edit on GitHub +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/tut/newbieguide.html b/venv/Lib/site-packages/pygame/docs/generated/tut/newbieguide.html new file mode 100644 index 0000000..b5e36a6 --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/tut/newbieguide.html @@ -0,0 +1,475 @@ + + + + + + + + + A Newbie Guide to pygame — pygame v2.1.2 documentation + + + + + + + + + + + + + +
+ +
+ + + + + +
+
+ +
+
+ +
+
+

A Newbie Guide to pygame¶

+

or Things I learned by trial and error so you don't have to,

+

or How I learned to stop worrying and love the blit.

+

Pygame is a python wrapper for SDL, written by Pete Shinners. What this +means is that, using pygame, you can write games or other multimedia +applications in Python that will run unaltered on any of SDL's supported +platforms (Windows, Unix, Mac, BeOS and others).

+

Pygame may be easy to learn, but the world of graphics programming can be +pretty confusing to the newcomer. I wrote this to try to distill the practical +knowledge I've gained over the past year or so of working with pygame, and its +predecessor, PySDL. I've tried to rank these suggestions in order of +importance, but how relevant any particular hint is will depend on your own +background and the details of your project.

+
+

Get comfortable working in Python.¶

+

The most important thing is to feel confident using python. Learning something +as potentially complicated as graphics programming will be a real chore if +you're also unfamiliar with the language you're using. Write a few sizable +non-graphical programs in python -- parse some text files, write a guessing +game or a journal-entry program or something. Get comfortable with string and +list manipulation -- know how to split, slice and combine strings and lists. +Know how import works -- try writing a program that is spread across +several source files. Write your own functions, and practice manipulating +numbers and characters; know how to convert between the two. Get to the point +where the syntax for using lists and dictionaries is second-nature -- you don't +want to have to run to the documentation every time you need to slice a list or +sort a set of keys. Resist the temptation to run to a mailing list, +comp.lang.python, or IRC when you run into trouble. Instead, fire up the +interpreter and play with the problem for a few hours. Print out the Python +2.0 Quick Reference and keep it by your computer.

+

This may sound incredibly dull, but the confidence you'll gain through your +familiarity with python will work wonders when it comes time to write your +game. The time you spend making python code second-nature will be nothing +compared to the time you'll save when you're writing real code.

+
+
+

Recognize which parts of pygame you really need.¶

+

Looking at the jumble of classes at the top of the pygame Documentation index +may be confusing. The important thing is to realize that you can do a great +deal with only a tiny subset of functions. Many classes you'll probably never +use -- in a year, I haven't touched the Channel, Joystick, cursors, +Userrect, surfarray or version functions.

+
+
+

Know what a surface is.¶

+

The most important part of pygame is the surface. Just think of a surface as a +blank piece of paper. You can do a lot of things with a surface -- you can +draw lines on it, fill parts of it with color, copy images to and from it, and +set or read individual pixel colors on it. A surface can be any size (within +reason) and you can have as many of them as you like (again, within reason). +One surface is special -- the one you create with +pygame.display.set_mode(). This 'display surface' represents the screen; +whatever you do to it will appear on the user's screen. You can only have one +of these -- that's an SDL limitation, not a pygame one.

+

So how do you create surfaces? As mentioned above, you create the special +'display surface' with pygame.display.set_mode(). You can create a surface +that contains an image by using image.load(), or you can make a surface +that contains text with font.render(). You can even create a surface that +contains nothing at all with Surface().

+

Most of the surface functions are not critical. Just learn blit(), +fill(), set_at() and get_at(), and you'll be fine.

+
+
+

Use surface.convert().¶

+

When I first read the documentation for surface.convert(), I didn't think +it was something I had to worry about. 'I only use PNGs, therefore everything I +do will be in the same format. So I don't need convert()';. It turns out I +was very, very wrong.

+

The 'format' that convert() refers to isn't the file format (ie PNG, +JPEG, GIF), it's what's called the 'pixel format'. This refers to the +particular way that a surface records individual colors in a specific pixel. +If the surface format isn't the same as the display format, SDL will have to +convert it on-the-fly for every blit -- a fairly time-consuming process. Don't +worry too much about the explanation; just note that convert() is necessary +if you want to get any kind of speed out of your blits.

+

How do you use convert? Just call it after creating a surface with the +image.load() function. Instead of just doing:

+
surface = pygame.image.load('foo.png')
+
+
+

Do:

+
surface = pygame.image.load('foo.png').convert()
+
+
+

It's that easy. You just need to call it once per surface, when you load an +image off the disk. You'll be pleased with the results; I see about a 6x +increase in blitting speed by calling convert().

+

The only times you don't want to use convert() is when you really need to +have absolute control over an image's internal format -- say you were writing +an image conversion program or something, and you needed to ensure that the +output file had the same pixel format as the input file. If you're writing a +game, you need speed. Use convert().

+
+
+

Dirty rect animation.¶

+

The most common cause of inadequate frame rates in pygame programs results from +misunderstanding the pygame.display.update() function. With pygame, merely +drawing something to the display surface doesn't cause it to appear on the +screen -- you need to call pygame.display.update(). There are three ways +of calling this function:

+
+
    +
  • pygame.display.update() -- This updates the whole window (or the whole screen for fullscreen displays).

  • +
  • pygame.display.flip() -- This does the same thing, and will also do the right thing if you're using double-buffered hardware acceleration, which you're not, so on to...

  • +
  • pygame.display.update(a rectangle or some list of rectangles) -- This updates just the rectangular areas of the screen you specify.

  • +
+
+

Most people new to graphics programming use the first option -- they update the +whole screen every frame. The problem is that this is unacceptably slow for +most people. Calling update() takes 35 milliseconds on my machine, which +doesn't sound like much, until you realize that 1000 / 35 = 28 frames per +second maximum. And that's with no game logic, no blits, no input, no AI, +nothing. I'm just sitting there updating the screen, and 28 fps is my maximum +framerate. Ugh.

+

The solution is called 'dirty rect animation'. Instead of updating the whole +screen every frame, only the parts that changed since the last frame are +updated. I do this by keeping track of those rectangles in a list, then +calling update(the_dirty_rectangles) at the end of the frame. In detail +for a moving sprite, I:

+
+
    +
  • Blit a piece of the background over the sprite's current location, erasing it.

  • +
  • Append the sprite's current location rectangle to a list called dirty_rects.

  • +
  • Move the sprite.

  • +
  • Draw the sprite at its new location.

  • +
  • Append the sprite's new location to my dirty_rects list.

  • +
  • Call display.update(dirty_rects)

  • +
+
+

The difference in speed is astonishing. Consider that SolarWolf has dozens of +constantly moving sprites updating smoothly, and still has enough time left +over to display a parallax starfield in the background, and update that too.

+

There are two cases where this technique just won't work. The first is where +the whole window or screen really is being updated every frame -- think of a +smooth-scrolling engine like an overhead real-time strategy game or a +side-scroller. So what do you do in this case? Well, the short answer is -- +don't write this kind of game in pygame. The long answer is to scroll in steps +of several pixels at a time; don't try to make scrolling perfectly smooth. +Your player will appreciate a game that scrolls quickly, and won't notice the +background jumping along too much.

+

A final note -- not every game requires high framerates. A strategic wargame +could easily get by on just a few updates per second -- in this case, the added +complexity of dirty rect animation may not be necessary.

+
+
+

There is NO rule six.¶

+
+
+

Hardware surfaces are more trouble than they're worth.¶

+

Especially in pygame 2, because HWSURFACE now does nothing

+

If you've been looking at the various flags you can use with +pygame.display.set_mode(), you may have thought like this: Hey, +HWSURFACE! Well, I want that -- who doesn't like hardware acceleration. Ooo... +DOUBLEBUF; well, that sounds fast, I guess I want that too!. It's not +your fault; we've been trained by years of 3-d gaming to believe that hardware +acceleration is good, and software rendering is slow.

+

Unfortunately, hardware rendering comes with a long list of drawbacks:

+
+
    +
  • It only works on some platforms. Windows machines can usually get hardware surfaces if you ask for them. Most other platforms can't. Linux, for example, may be able to provide a hardware surface if X4 is installed, if DGA2 is working properly, and if the moons are aligned correctly. If a hardware surface is unavailable, SDL will silently give you a software surface instead.

  • +
  • It only works fullscreen.

  • +
  • It complicates per-pixel access. If you have a hardware surface, you need to Lock the surface before writing or reading individual pixel values on it. If you don't, Bad Things Happen. Then you need to quickly Unlock the surface again, before the OS gets all confused and starts to panic. Most of this process is automated for you in pygame, but it's something else to take into account.

  • +
  • You lose the mouse pointer. If you specify HWSURFACE (and actually get it), your pointer will usually just vanish (or worse, hang around in a half-there, half-not flickery state). You'll need to create a sprite to act as a manual mouse pointer, and you'll need to worry about pointer acceleration and sensitivity. What a pain.

  • +
  • It might be slower anyway. Many drivers are not accelerated for the types of drawing that we do, and since everything has to be blitted across the video bus (unless you can cram your source surface into video memory as well), it might end up being slower than software access anyway.

  • +
+
+

Hardware rendering has its place. It works pretty reliably under Windows, so +if you're not interested in cross-platform performance, it may provide you with +a substantial speed increase. However, it comes at a cost -- increased +headaches and complexity. It's best to stick with good old reliable +SWSURFACE until you're sure you know what you're doing.

+
+
+

Don't get distracted by side issues.¶

+

Sometimes, new game programmers spend too much time worrying about issues that +aren't really critical to their game's success. The desire to get secondary +issues 'right' is understandable, but early in the process of creating a game, +you cannot even know what the important questions are, let alone what answers +you should choose. The result can be a lot of needless prevarication.

+

For example, consider the question of how to organize your graphics files. +Should each frame have its own graphics file, or each sprite? Perhaps all the +graphics should be zipped up into one archive? A great deal of time has been +wasted on a lot of projects, asking these questions on mailing lists, debating +the answers, profiling, etc, etc. This is a secondary issue; any time spent +discussing it should have been spent coding the actual game.

+

The insight here is that it is far better to have a 'pretty good' solution that +was actually implemented, than a perfect solution that you never got around to +writing.

+
+
+

Rects are your friends.¶

+

Pete Shinners' wrapper may have cool alpha effects and fast blitting speeds, +but I have to admit my favorite part of pygame is the lowly Rect class. A +rect is simply a rectangle -- defined only by the position of its top left +corner, its width, and its height. Many pygame functions take rects as +arguments, and they also take 'rectstyles', a sequence that has the same values +as a rect. So if I need a rectangle that defines the area between 10, 20 and +40, 50, I can do any of the following:

+
rect = pygame.Rect(10, 20, 30, 30)
+rect = pygame.Rect((10, 20, 30, 30))
+rect = pygame.Rect((10, 20), (30, 30))
+rect = (10, 20, 30, 30)
+rect = ((10, 20, 30, 30))
+
+
+

If you use any of the first three versions, however, you get access to Rect's +utility functions. These include functions to move, shrink and inflate rects, +find the union of two rects, and a variety of collision-detection functions.

+

For example, suppose I'd like to get a list of all the sprites that contain a +point (x, y) -- maybe the player clicked there, or maybe that's the current +location of a bullet. It's simple if each sprite has a .rect member -- I just +do:

+
sprites_clicked = [sprite for sprite in all_my_sprites_list if sprite.rect.collidepoint(x, y)]
+
+
+

Rects have no other relation to surfaces or graphics functions, other than the +fact that you can use them as arguments. You can also use them in places that +have nothing to do with graphics, but still need to be defined as rectangles. +Every project I discover a few new places to use rects where I never thought +I'd need them.

+
+
+

Don't bother with pixel-perfect collision detection.¶

+

So you've got your sprites moving around, and you need to know whether or not they're bumping into one another. It's tempting to write something like the following:

+
+
    +
  • Check to see if the rects are in collision. If they aren't, ignore them.

  • +
  • For each pixel in the overlapping area, see if the corresponding pixels from both sprites are opaque. If so, there's a collision.

  • +
+
+

There are other ways to do this, with ANDing sprite masks and so on, but any +way you do it in pygame, it's probably going to be too slow. For most games, +it's probably better just to do 'sub-rect collision' -- create a rect for each +sprite that's a little smaller than the actual image, and use that for +collisions instead. It will be much faster, and in most cases the player won't +notice the imprecision.

+
+
+

Managing the event subsystem.¶

+

Pygame's event system is kind of tricky. There are actually two different ways +to find out what an input device (keyboard, mouse or joystick) is doing.

+

The first is by directly checking the state of the device. You do this by +calling, say, pygame.mouse.get_pos() or pygame.key.get_pressed(). +This will tell you the state of that device at the moment you call the +function.

+

The second method uses the SDL event queue. This queue is a list of events -- +events are added to the list as they're detected, and they're deleted from the +queue as they're read off.

+

There are advantages and disadvantages to each system. State-checking (system +1) gives you precision -- you know exactly when a given input was made -- if +mouse.get_pressed([0]) is 1, that means that the left mouse button is +down right at this moment. The event queue merely reports that the +mouse was down at some time in the past; if you check the queue fairly often, +that can be ok, but if you're delayed from checking it by other code, input +latency can grow. Another advantage of the state-checking system is that it +detects "chording" easily; that is, several states at the same time. If you +want to know whether the t and f keys are down at the same time, just +check:

+
if (key.get_pressed[K_t] and key.get_pressed[K_f]):
+    print "Yup!"
+
+
+

In the queue system, however, each keypress arrives in the queue as a +completely separate event, so you'd need to remember that the t key was +down, and hadn't come up yet, while checking for the f key. A little more +complicated.

+

The state system has one great weakness, however. It only reports what the +state of the device is at the moment it's called; if the user hits a mouse +button then releases it just before a call to mouse.get_pressed(), the +mouse button will return 0 -- get_pressed() missed the mouse button press +completely. The two events, MOUSEBUTTONDOWN and MOUSEBUTTONUP, will +still be sitting in the event queue, however, waiting to be retrieved and +processed.

+

The lesson is: choose the system that meets your requirements. If you don't +have much going on in your loop -- say you're just sitting in a while 1 +loop, waiting for input, use get_pressed() or another state function; the +latency will be lower. On the other hand, if every keypress is crucial, but +latency isn't as important -- say your user is typing something in an editbox, +use the event queue. Some keypresses may be slightly late, but at least you'll +get them all.

+

A note about event.poll() vs. wait() -- poll() may seem better, +since it doesn't block your program from doing anything while it's waiting for +input -- wait() suspends the program until an event is received. +However, poll() will consume 100% of available CPU time while it runs, +and it will fill the event queue with NOEVENTS. Use set_blocked() to +select just those event types you're interested in -- your queue will be much +more manageable.

+
+
+

Colorkey vs. Alpha.¶

+

There's a lot of confusion around these two techniques, and much of it comes from the terminology used.

+

'Colorkey blitting' involves telling pygame that all pixels of a certain color +in a certain image are transparent instead of whatever color they happen to be. +These transparent pixels are not blitted when the rest of the image is blitted, +and so don't obscure the background. This is how we make sprites that aren't +rectangular in shape. Simply call surface.set_colorkey(color), where +color is an RGB tuple -- say (0,0,0). This would make every pixel in the source +image transparent instead of black.

+

'Alpha' is different, and it comes in two flavors. 'Image alpha' applies to the +whole image, and is probably what you want. Properly known as 'translucency', +alpha causes each pixel in the source image to be only partially opaque. +For example, if you set a surface's alpha to 192 and then blitted it onto a +background, 3/4 of each pixel's color would come from the source image, and 1/4 +from the background. Alpha is measured from 255 to 0, where 0 is completely +transparent, and 255 is completely opaque. Note that colorkey and alpha +blitting can be combined -- this produces an image that is fully transparent in +some spots, and semi-transparent in others.

+

'Per-pixel alpha' is the other flavor of alpha, and it's more complicated. +Basically, each pixel in the source image has its own alpha value, from 0 to +255. Each pixel, therefore, can have a different opacity when blitted onto a +background. This type of alpha can't be mixed with colorkey blitting, +and it overrides per-image alpha. Per-pixel alpha is rarely used in +games, and to use it you have to save your source image in a graphic +editor with a special alpha channel. It's complicated -- don't use it +yet.

+
+
+

Do things the pythony way.¶

+

A final note (this isn't the least important one; it just comes at the end). +Pygame is a pretty lightweight wrapper around SDL, which is in turn a pretty +lightweight wrapper around your native OS graphics calls. Chances are pretty +good that if your code is still slow, and you've done the things I've mentioned +above, then the problem lies in the way you're addressing your data in python. +Certain idioms are just going to be slow in python no matter what you do. +Luckily, python is a very clear language -- if a piece of code looks awkward or +unwieldy, chances are its speed can be improved, too. Read over Python +Performance Tips for some great advice on how you can improve the speed of +your code. That said, premature optimisation is the root of all evil; if it's +just not fast enough, don't torture the code trying to make it faster. Some +things are just not meant to be :)

+

There you go. Now you know practically everything I know about using pygame. +Now, go write that game!

+
+

David Clark is an avid pygame user and the editor of the Pygame Code +Repository, a showcase for community-submitted python game code. He is also +the author of Twitch, an entirely average pygame arcade game.

+
+
+
+ + +

+
+Edit on GitHub +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/tut/tom_games2.html b/venv/Lib/site-packages/pygame/docs/generated/tut/tom_games2.html new file mode 100644 index 0000000..5d54038 --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/tut/tom_games2.html @@ -0,0 +1,240 @@ + + + + + + + + + Revision: Pygame fundamentals — pygame v2.1.2 documentation + + + + + + + + + + + + + +
+ +
+ + + + + +
+
+ +
+
+ +
+
+

2. Revision: Pygame fundamentals¶

+
+

2.1. The basic Pygame game¶

+

For the sake of revision, and to ensure that you are familiar with the basic structure of a Pygame program, I'll briefly run through +a basic Pygame program, which will display no more than a window with some text in it, that should, by the end, look something like +this (though of course the window decoration will probably be different on your system):

+../_images/tom_basic.png +

The full code for this example looks like this:

+
#!/usr/bin/python
+
+import pygame
+from pygame.locals import *
+
+def main():
+    # Initialise screen
+    pygame.init()
+    screen = pygame.display.set_mode((150, 50))
+    pygame.display.set_caption('Basic Pygame program')
+
+    # Fill background
+    background = pygame.Surface(screen.get_size())
+    background = background.convert()
+    background.fill((250, 250, 250))
+
+    # Display some text
+    font = pygame.font.Font(None, 36)
+    text = font.render("Hello There", 1, (10, 10, 10))
+    textpos = text.get_rect()
+    textpos.centerx = background.get_rect().centerx
+    background.blit(text, textpos)
+
+    # Blit everything to the screen
+    screen.blit(background, (0, 0))
+    pygame.display.flip()
+
+    # Event loop
+    while 1:
+        for event in pygame.event.get():
+            if event.type == QUIT:
+                return
+
+        screen.blit(background, (0, 0))
+        pygame.display.flip()
+
+
+if __name__ == '__main__': main()
+
+
+
+
+

2.2. Basic Pygame objects¶

+

As you can see, the code consists of three main objects: the screen, the background, and the text. Each of these objects is created +by first calling an instance of an in-built Pygame object, and then modifying it to fit our needs. The screen is a slightly special +case, because we still modify the display through Pygame calls, rather than calling methods belonging to the screen object. But for +all other Pygame objects, we first create the object as a copy of a Pygame object, giving it some attributes, and build our game +objects from them.

+

With the background, we first create a Pygame Surface object, and make it the size of the screen. We then perform the convert() +operation to convert the Surface to a single pixel format. This is more obviously necessary when we have several images and surfaces, +all of different pixel formats, which makes rendering them quite slow. By converting all the surfaces, we can drastically speed up +rendering times. Finally, we fill the background surface with white (255, 255, 255). These values are RGB (Red Green +Blue), and can be worked out from any good paint program.

+

With the text, we require more than one object. First, we create a font object, which defines which font to use, and the size of the +font. Then we create a text object, by using the render method that belongs to our font object, supplying three arguments: +the text to be rendered, whether or not it should be anti-aliased (1=yes, 0=no), and the color of the text (again in RGB format). Next +we create a third text object, which gets the rectangle for the text. The easiest way to understand this is to imagine drawing a +rectangle that will surround all of the text; you can then use this rectangle to get/set the position of the text on the screen. So +in this example we get the rectangle, set its centerx attribute to be the centerx attribute of the +background (so the text's center will be the same as the background's center, i.e. the text will be centered on the screen on the x +axis). We could also set the y coordinate, but it's not any different so I left the text at the top of the screen. As the screen is +small anyway, it didn't seem necessary.

+
+
+

2.3. Blitting¶

+

Now we have created our game objects, we need to actually render them. If we didn't and we ran the program, we'd just see a +blank window, and the objects would remain invisible. The term used for rendering objects is blitting, which is where +you copy the pixels belonging to said object onto the destination object. So to render the background object, you blit it onto the +screen. In this example, to make things simple, we blit the text onto the background (so the background will now have a copy of the +text on it), and then blit the background onto the screen.

+

Blitting is one of the slowest operations in any game, so you need to be careful not to blit too much onto the screen in every frame. +If you have a background image, and a ball flying around the screen, then you could blit the background and then the ball in every +frame, which would cover up the ball's previous position and render the new ball, but this would be pretty slow. A better solution is +to blit the background onto the area that the ball previously occupied, which can be found by the ball's previous rectangle, and then +blitting the ball, so that you are only blitting two small areas.

+
+
+

2.4. The event loop¶

+

Once you've set the game up, you need to put it into a loop so that it will continuously run until the user signals that he/she wants +to exit. So you start an open while loop, and then for each iteration of the loop, which will be each frame of the game, +update the game. The first thing is to check for any Pygame events, which will be the user hitting the keyboard, clicking a mouse +button, moving a joystick, resizing the window, or trying to close it. In this case, we simply want to watch out for for user trying +to quit the game by closing the window, in which case the game should return, which will end the while loop. +Then we simply need to re-blit the background, and flip (update) the display to have everything drawn. OK, as nothing moves or happens +in this example, we don't strictly speaking need to re-blit the background in every iteration, but I put it in because when things are +moving around on the screen, you will need to do all your blitting here.

+
+
+

2.5. Ta-da!¶

+

And that's it - your most basic Pygame game! All games will take a form similar to this, but with lots more code for the actual game +functions themselves, which are more to do your with programming, and less guided in structure by the workings of Pygame. This is what +this tutorial is really about, and will now go onto.

+
+
+
+ + +

+
+Edit on GitHub +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/tut/tom_games3.html b/venv/Lib/site-packages/pygame/docs/generated/tut/tom_games3.html new file mode 100644 index 0000000..a17fb21 --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/tut/tom_games3.html @@ -0,0 +1,220 @@ + + + + + + + + + Kicking things off — pygame v2.1.2 documentation + + + + + + + + + + + + + +
+ +
+ + + + + +
+
+ +
+
+ +
+
+

3. Kicking things off¶

+

The first sections of code are relatively simple, and, once written, can usually be reused in every game you consequently make. They +will do all of the boring, generic tasks like loading modules, loading images, opening networking connections, playing music, and so +on. They will also include some simple but effective error handling, and any customisation you wish to provide on top of functions +provided by modules like sys and pygame.

+
+

3.1. The first lines, and loading modules¶

+

First off, you need to start off your game and load up your modules. It's always a good idea to set a few things straight at the top of +the main source file, such as the name of the file, what it contains, the license it is under, and any other helpful info you might +want to give those will will be looking at it. Then you can load modules, with some error checking so that Python doesn't print out +a nasty traceback, which non-programmers won't understand. The code is fairly simple, so I won't bother explaining any of it:

+
#!/usr/bin/env python
+#
+# Tom's Pong
+# A simple pong game with realistic physics and AI
+# http://www.tomchance.uklinux.net/projects/pong.shtml
+#
+# Released under the GNU General Public License
+
+VERSION = "0.4"
+
+try:
+    import sys
+    import random
+    import math
+    import os
+    import getopt
+    import pygame
+    from socket import *
+    from pygame.locals import *
+except ImportError, err:
+    print "couldn't load module. %s" % (err)
+    sys.exit(2)
+
+
+
+
+

3.2. Resource handling functions¶

+

In the Line By Line Chimp example, the first code to be written was for loading images and sounds. As these +were totally independent of any game logic or game objects, they were written as separate functions, and were written first so +that later code could make use of them. I generally put all my code of this nature first, in their own, classless functions; these +will, generally speaking, be resource handling functions. You can of course create classes for these, so that you can group them +together, and maybe have an object with which you can control all of your resources. As with any good programming environment, it's up +to you to develop your own best practice and style.

+

It's always a good idea to write your own resource handling functions, +because although Pygame has methods for opening images and sounds, and other modules will have their methods of opening other +resources, those methods can take up more than one line, they can require consistent modification by yourself, and they often don't +provide satisfactory error handling. Writing resource handling functions gives you sophisticated, reusable code, and gives you more +control over your resources. Take this example of an image loading function:

+
def load_png(name):
+    """ Load image and return image object"""
+    fullname = os.path.join('data', name)
+    try:
+        image = pygame.image.load(fullname)
+        if image.get_alpha() is None:
+            image = image.convert()
+        else:
+            image = image.convert_alpha()
+    except pygame.error, message:
+        print 'Cannot load image:', fullname
+        raise SystemExit, message
+    return image, image.get_rect()
+
+
+

Here we make a more sophisticated image loading function than the one provided by pygame.image.load()load new image from a file (or file-like object). Note that +the first line of the function is a documentation string describing what the function does, and what object(s) it returns. The +function assumes that all of your images are in a directory called data, and so it takes the filename and creates the full pathname, +for example data/ball.png, using the os module to ensure cross-platform compatibility. Then it +tries to load the image, and convert any alpha regions so you can achieve transparency, and it returns a more human-readable error +if there's a problem. Finally it returns the image object, and its rect.

+

You can make similar functions for loading any other resources, such as loading sounds. You can also make resource handling classes, +to give you more flexibility with more complex resources. For example, you could make a music class, with an __init__ +function that loads the sound (perhaps borrowing from a load_sound() function), a function to pause the music, and a +function to restart. Another handy resource handling class is for network connections. Functions to open sockets, pass data with +suitable security and error checking, close sockets, finger addresses, and other network tasks, can make writing a game with network +capabilities relatively painless.

+

Remember the chief task of these functions/classes is to ensure that by the time you get around to writing game object classes, +and the main loop, there's almost nothing left to do. Class inheritance can make these basic classes especially handy. Don't go +overboard though; functions which will only be used by one class should be written as part of that class, not as a global +function.

+
+
+
+ + +

+
+Edit on GitHub +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/tut/tom_games4.html b/venv/Lib/site-packages/pygame/docs/generated/tut/tom_games4.html new file mode 100644 index 0000000..0504256 --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/tut/tom_games4.html @@ -0,0 +1,249 @@ + + + + + + + + + Game object classes — pygame v2.1.2 documentation + + + + + + + + + + + + + +
+ +
+ + + + + +
+
+ +
+
+ +
+
+

4. Game object classes¶

+

Once you've loaded your modules, and written your resource handling functions, you'll want to get on to writing some game objects. +The way this is done is fairly simple, though it can seem complex at first. You write a class for each type of object in the game, +and then create an instance of those classes for the objects. You can then use those classes' methods to manipulate the objects, +giving objects some motion and interactive capabilities. So your game, in pseudo-code, will look like this:

+
#!/usr/bin/python
+
+# [load modules here]
+
+# [resource handling functions here]
+
+class Ball:
+    # [ball functions (methods) here]
+    # [e.g. a function to calculate new position]
+    # [and a function to check if it hits the side]
+
+def main:
+    # [initiate game environment here]
+
+    # [create new object as instance of ball class]
+    ball = Ball()
+
+    while 1:
+        # [check for user input]
+
+        # [call ball's update function]
+        ball.update()
+
+
+

This is, of course, a very simple example, and you'd need to put in all the code, instead of those little bracketed comments. But +you should get the basic idea. You crate a class, into which you put all the functions for a ball, including __init__, +which would create all the ball's attributes, and update, which would move the ball to its new position, before blitting +it onto the screen in this position.

+

You can then create more classes for all of your other game objects, and then create instances of them so that you can handle them +easily in the main function and the main program loop. Contrast this with initiating the ball in the main +function, and then having lots of classless functions to manipulate a set ball object, and you'll hopefully see why using classes is +an advantage: It allows you to put all of the code for each object in one place; it makes using objects easier; it makes adding new +objects, and manipulating them, more flexible. Rather than adding more code for each new ball object, you could simply create new +instances of the Ball class for each new ball object. Magic!

+
+

4.1. A simple ball class¶

+

Here is a simple class with the functions necessary for creating a ball object that will, if the update function is called +in the main loop, move across the screen:

+
class Ball(pygame.sprite.Sprite):
+    """A ball that will move across the screen
+    Returns: ball object
+    Functions: update, calcnewpos
+    Attributes: area, vector"""
+
+    def __init__(self, vector):
+        pygame.sprite.Sprite.__init__(self)
+        self.image, self.rect = load_png('ball.png')
+        screen = pygame.display.get_surface()
+        self.area = screen.get_rect()
+        self.vector = vector
+
+    def update(self):
+        newpos = self.calcnewpos(self.rect,self.vector)
+        self.rect = newpos
+
+    def calcnewpos(self,rect,vector):
+        (angle,z) = vector
+        (dx,dy) = (z*math.cos(angle),z*math.sin(angle))
+        return rect.move(dx,dy)
+
+
+

Here we have the Ball class, with an __init__ function that sets the ball up, an update +function that changes the ball's rectangle to be in the new position, and a calcnewpos function to calculate the ball's +new position based on its current position, and the vector by which it is moving. I'll explain the physics in a moment. The one other +thing to note is the documentation string, which is a little bit longer this time, and explains the basics of the class. These strings +are handy not only to yourself and other programmers looking at the code, but also for tools to parse your code and document it. They +won't make much of a difference in small programs, but with large ones they're invaluable, so it's a good habit to get into.

+
+

4.1.1. Diversion 1: Sprites¶

+

The other reason for creating a class for each object is sprites. Each image you render in your game will be a sprite object, and so +to begin with, the class for each object should inherit the Sprite class. +This is a really nice feature of Python - class +inheritance. Now the Ball class has all of the functions that come with the Sprite class, and any object +instances of the Ball class will be registered by Pygame as sprites. Whereas with text and the background, which don't +move, it's OK to blit the object onto the background, Pygame handles sprite objects in a different manner, which you'll see when we +look at the whole program's code.

+

Basically, you create both a ball object, and a sprite object for that ball, and you then call the ball's update function on the +sprite object, thus updating the sprite. Sprites also give you sophisticated ways of determining if two objects have collided. +Normally you might just check in the main loop to see if their rectangles overlap, but that would involve a lot of code, which would +be a waste because the Sprite class provides two functions (spritecollide and groupcollide) +to do this for you.

+
+
+

4.1.2. Diversion 2: Vector physics¶

+

Other than the structure of the Ball class, the notable thing about this code is the vector physics, used to calculate +the ball's movement. With any game involving angular movement, you won't get very far unless you're comfortable with trigonometry, so +I'll just introduce the basics you need to know to make sense of the calcnewpos function.

+

To begin with, you'll notice that the ball has an attribute vector, which is made up of angle and z. +The angle is measured in radians, and will give you the direction in which the ball is moving. Z is the speed at which the ball +moves. So by using this vector, we can determine the direction and speed of the ball, and therefore how much it will move on the x and +y axes:

+../_images/tom_radians.png +

The diagram above illustrates the basic maths behind vectors. In the left hand diagram, you can see the ball's projected movement +represented by the blue line. The length of that line (z) represents its speed, and the angle is the direction in which +it will move. The angle for the ball's movement will always be taken from the x axis on the right, and it is measured clockwise from +that line, as shown in the diagram.

+

From the angle and speed of the ball, we can then work out how much it has moved along the x and y axes. We need to do this because +Pygame doesn't support vectors itself, and we can only move the ball by moving its rectangle along the two axes. So we need to +resolve the angle and speed into its movement on the x axis (dx) and on the y axis (dy). This is a simple matter of +trigonometry, and can be done with the formulae shown in the diagram.

+

If you've studied elementary trigonometry before, none of this should be news to you. But just in case you're forgetful, here are some +useful formulae to remember, that will help you visualise the angles (I find it easier to visualise angles in degrees than in radians!)

+../_images/tom_formulae.png +
+
+
+
+ + +

+
+Edit on GitHub +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/tut/tom_games5.html b/venv/Lib/site-packages/pygame/docs/generated/tut/tom_games5.html new file mode 100644 index 0000000..97f8f87 --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/tut/tom_games5.html @@ -0,0 +1,238 @@ + + + + + + + + + User-controllable objects — pygame v2.1.2 documentation + + + + + + + + + + + + + +
+ +
+ + + + + +
+
+ +
+
+ +
+
+

5. User-controllable objects¶

+

So far you can create a Pygame window, and render a ball that will fly across the screen. The next step is to make some bats which +the user can control. This is potentially far more simple than the ball, because it requires no physics (unless your user-controlled +object will move in ways more complex than up and down, e.g. a platform character like Mario, in which case you'll need more physics). +User-controllable objects are pretty easy to create, thanks to Pygame's event queue system, as you'll see.

+
+

5.1. A simple bat class¶

+

The principle behind the bat class is similar to that of the ball class. You need an __init__ function to initialise the +ball (so you can create object instances for each bat), an update function to perform per-frame changes on the bat before +it is blitted the bat to the screen, and the functions that will define what this class will actually do. Here's some sample code:

+
class Bat(pygame.sprite.Sprite):
+    """Movable tennis 'bat' with which one hits the ball
+    Returns: bat object
+    Functions: reinit, update, moveup, movedown
+    Attributes: which, speed"""
+
+    def __init__(self, side):
+        pygame.sprite.Sprite.__init__(self)
+        self.image, self.rect = load_png('bat.png')
+        screen = pygame.display.get_surface()
+        self.area = screen.get_rect()
+        self.side = side
+        self.speed = 10
+        self.state = "still"
+        self.reinit()
+
+    def reinit(self):
+        self.state = "still"
+        self.movepos = [0,0]
+        if self.side == "left":
+            self.rect.midleft = self.area.midleft
+        elif self.side == "right":
+            self.rect.midright = self.area.midright
+
+    def update(self):
+        newpos = self.rect.move(self.movepos)
+        if self.area.contains(newpos):
+            self.rect = newpos
+        pygame.event.pump()
+
+    def moveup(self):
+        self.movepos[1] = self.movepos[1] - (self.speed)
+        self.state = "moveup"
+
+    def movedown(self):
+        self.movepos[1] = self.movepos[1] + (self.speed)
+        self.state = "movedown"
+
+
+

As you can see, this class is very similar to the ball class in its structure. But there are differences in what each function does. +First of all, there is a reinit function, which is used when a round ends, and the bat needs to be set back in its starting place, +with any attributes set back to their necessary values. Next, the way in which the bat is moved is a little more complex than with the +ball, because here its movement is simple (up/down), but it relies on the user telling it to move, unlike the ball which just keeps +moving in every frame. To make sense of how the ball moves, it is helpful to look at a quick diagram to show the sequence of events:

+../_images/tom_event-flowchart.png +

What happens here is that the person controlling the bat pushes down on the key that moves the bat up. For each iteration of the main +game loop (for every frame), if the key is still held down, then the state attribute of that bat object will be set to +"moving", and the moveup function will be called, causing the ball's y position to be reduced by the value of the +speed attribute (in this example, 10). In other words, so long as the key is held down, the bat will move up the screen +by 10 pixels per frame. The state attribute isn't used here yet, but it's useful to know if you're dealing with spin, or +would like some useful debugging output.

+

As soon as the player lets go of that key, the second set of boxes is invoked, and the state attribute of the bat object +will be set back to "still", and the movepos attribute will be set back to [0,0], meaning that when the update function is called, it won't move the bat any more. So when the player lets go of the key, the bat stops moving. Simple!

+
+

5.1.1. Diversion 3: Pygame events¶

+

So how do we know when the player is pushing keys down, and then releasing them? With the Pygame event queue system, dummy! It's a +really easy system to use and understand, so this shouldn't take long :) You've already seen the event queue in action in the basic +Pygame program, where it was used to check if the user was quitting the application. The code for moving the bat is about as simple +as that:

+
for event in pygame.event.get():
+    if event.type == QUIT:
+        return
+    elif event.type == KEYDOWN:
+        if event.key == K_UP:
+            player.moveup()
+        if event.key == K_DOWN:
+            player.movedown()
+    elif event.type == KEYUP:
+        if event.key == K_UP or event.key == K_DOWN:
+            player.movepos = [0,0]
+            player.state = "still"
+
+
+

Here assume that you've already created an instance of a bat, and called the object player. You can see the familiar +layout of the for structure, which iterates through each event found in the Pygame event queue, which is retrieved with +the event.get() function. As the user hits keys, pushes mouse buttons and moves the joystick about, those actions are +pumped into the Pygame event queue, and left there until dealt with. So in each iteration of the main game loop, you go through +these events, checking if they're ones you want to deal with, and then dealing with them appropriately. The event.pump() +function that was in the Bat.update function is then called in every iteration to pump out old events, and keep the queue +current.

+

First we check if the user is quitting the program, and quit it if they are. Then we check if any keys are being pushed down, and if +they are, we check if they're the designated keys for moving the bat up and down. If they are, then we call the appropriate moving +function, and set the player state appropriately (though the states moveup and movedown and changed in the moveup() and +movedown() functions, which makes for neater code, and doesn't break encapsulation, which means that you +assign attributes to the object itself, without referring to the name of the instance of that object). Notice here we have three +states: still, moveup, and movedown. Again, these come in handy if you want to debug or calculate spin. We also check if any keys have +been "let go" (i.e. are no longer being held down), and again if they're the right keys, we stop the bat from moving.

+
+
+
+
+ + +

+
+Edit on GitHub +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/docs/generated/tut/tom_games6.html b/venv/Lib/site-packages/pygame/docs/generated/tut/tom_games6.html new file mode 100644 index 0000000..3ab1389 --- /dev/null +++ b/venv/Lib/site-packages/pygame/docs/generated/tut/tom_games6.html @@ -0,0 +1,436 @@ + + + + + + + + + Putting it all together — pygame v2.1.2 documentation + + + + + + + + + + + + + +
+ +
+ + + + + +
+
+ +
+
+ +
+
+

6. Putting it all together¶

+

So far you've learnt all the basics necessary to build a simple game. You should understand how to create Pygame objects, how Pygame +displays objects, how it handles events, and how you can use physics to introduce some motion into your game. Now I'll just show how +you can take all those chunks of code and put them together into a working game. What we need first is to let the ball hit the sides +of the screen, and for the bat to be able to hit the ball, otherwise there's not going to be much game play involved. We do this +using Pygame's collision methods.

+
+

6.1. Let the ball hit sides¶

+

The basics principle behind making it bounce of the sides is easy to grasp. You grab the coordinates of the four corners of the ball, +and check to see if they correspond with the x or y coordinate of the edge of the screen. So if the top right and top left corners both +have a y coordinate of zero, you know that the ball is currently on the top edge of the screen. We do all this in the update function, +after we've worked out the new position of the ball.

+
if not self.area.contains(newpos):
+      tl = not self.area.collidepoint(newpos.topleft)
+      tr = not self.area.collidepoint(newpos.topright)
+      bl = not self.area.collidepoint(newpos.bottomleft)
+      br = not self.area.collidepoint(newpos.bottomright)
+      if tr and tl or (br and bl):
+              angle = -angle
+      if tl and bl:
+              self.offcourt(player=2)
+      if tr and br:
+              self.offcourt(player=1)
+
+self.vector = (angle,z)
+
+
+

Here we check to see if the area +contains the new position of the ball (it always should, so we needn't have an else clause, +though in other circumstances you might want to consider it. We then check if the coordinates for the four corners +are colliding with the area's edges, and create objects for each result. If they are, the objects will have a value of 1, +or True. If they don't, then the value will be None, or False. We then see if it has hit the top or bottom, and if it +has we change the ball's direction. Handily, using radians we can do this by simply reversing its positive/negative value. +We also check to see if the ball has gone off the sides, and if it has we call the offcourt function. +This, in my game, resets the ball, adds 1 point to the score of the player specified when calling the function, and displays the new score.

+

Finally, we recompile the vector based on the new angle. And that is it. The ball will now merrily bounce off the walls and go +offcourt with good grace.

+
+
+

6.2. Let the ball hit bats¶

+

Making the ball hit the bats is very similar to making it hit the sides of the screen. We still use the collide method, but this time +we check to see if the rectangles for the ball and either bat collide. In this code I've also put in some extra code to avoid various +glitches. You'll find that you'll have to put all sorts of extra code in to avoid glitches and bugs, so it's good to get used to seeing +it.

+
else:
+    # Deflate the rectangles so you can't catch a ball behind the bat
+    player1.rect.inflate(-3, -3)
+    player2.rect.inflate(-3, -3)
+
+    # Do ball and bat collide?
+    # Note I put in an odd rule that sets self.hit to 1 when they collide, and unsets it in the next
+    # iteration. this is to stop odd ball behaviour where it finds a collision *inside* the
+    # bat, the ball reverses, and is still inside the bat, so bounces around inside.
+    # This way, the ball can always escape and bounce away cleanly
+    if self.rect.colliderect(player1.rect) == 1 and not self.hit:
+        angle = math.pi - angle
+        self.hit = not self.hit
+    elif self.rect.colliderect(player2.rect) == 1 and not self.hit:
+        angle = math.pi - angle
+        self.hit = not self.hit
+    elif self.hit:
+        self.hit = not self.hit
+self.vector = (angle,z)
+
+
+

We start this section with an else statement, because this carries on from the previous chunk of code to check if the ball +hits the sides. It makes sense that if it doesn't hit the sides, it might hit a bat, so we carry on the conditional statement. The +first glitch to fix is to shrink the players' rectangles by 3 pixels in both dimensions, to stop the bat catching a ball that goes +behind them (if you imagine you just move the bat so that as the ball travels behind it, the rectangles overlap, and so normally the +ball would then have been "hit" - this prevents that).

+

Next we check if the rectangles collide, with one more glitch fix. Notice that I've commented on these odd bits of code - it's always +good to explain bits of code that are abnormal, both for others who look at your code, and so you understand it when you come back to +it. The without the fix, the ball might hit a corner of the bat, change direction, and one frame later still find itself inside the +bat. Then it would again think it has been hit, and change its direction. This can happen several times, making the ball's motion +completely unrealistic. So we have a variable, self.hit, which we set to True when it has been hit, and False one frame +later. When we check if the rectangles have collided, we also check if self.hit is True/False, to stop internal bouncing.

+

The important code here is pretty easy to understand. All rectangles have a colliderect +function, into which you feed the rectangle of another object, which returns True if the rectangles do overlap, and False if not. +If they do, we can change the direction by subtracting the current angle from pi (again, a handy trick you can do with radians, +which will adjust the angle by 90 degrees and send it off in the right direction; you might find at this point that a thorough +understanding of radians is in order!). Just to finish the glitch checking, we switch self.hit back to False if it's the frame +after they were hit.

+

We also then recompile the vector. You would of course want to remove the same line in the previous chunk of code, so that you only do +this once after the if-else conditional statement. And that's it! The combined code will now allow the ball to hit sides and bats.

+
+
+

6.3. The Finished product¶

+

The final product, with all the bits of code thrown together, as well as some other bits ofcode to glue it all together, will look +like this:

+
#
+# Tom's Pong
+# A simple pong game with realistic physics and AI
+# http://www.tomchance.uklinux.net/projects/pong.shtml
+#
+# Released under the GNU General Public License
+
+VERSION = "0.4"
+
+try:
+    import sys
+    import random
+    import math
+    import os
+    import getopt
+    import pygame
+    from socket import *
+    from pygame.locals import *
+except ImportError, err:
+    print "couldn't load module. %s" % (err)
+    sys.exit(2)
+
+def load_png(name):
+    """ Load image and return image object"""
+    fullname = os.path.join('data', name)
+    try:
+        image = pygame.image.load(fullname)
+        if image.get_alpha is None:
+            image = image.convert()
+        else:
+            image = image.convert_alpha()
+    except pygame.error, message:
+        print 'Cannot load image:', fullname
+        raise SystemExit, message
+    return image, image.get_rect()
+
+class Ball(pygame.sprite.Sprite):
+    """A ball that will move across the screen
+    Returns: ball object
+    Functions: update, calcnewpos
+    Attributes: area, vector"""
+
+    def __init__(self, (xy), vector):
+        pygame.sprite.Sprite.__init__(self)
+        self.image, self.rect = load_png('ball.png')
+        screen = pygame.display.get_surface()
+        self.area = screen.get_rect()
+        self.vector = vector
+        self.hit = 0
+
+    def update(self):
+        newpos = self.calcnewpos(self.rect,self.vector)
+        self.rect = newpos
+        (angle,z) = self.vector
+
+        if not self.area.contains(newpos):
+            tl = not self.area.collidepoint(newpos.topleft)
+            tr = not self.area.collidepoint(newpos.topright)
+            bl = not self.area.collidepoint(newpos.bottomleft)
+            br = not self.area.collidepoint(newpos.bottomright)
+            if tr and tl or (br and bl):
+                angle = -angle
+            if tl and bl:
+                #self.offcourt()
+                angle = math.pi - angle
+            if tr and br:
+                angle = math.pi - angle
+                #self.offcourt()
+        else:
+            # Deflate the rectangles so you can't catch a ball behind the bat
+            player1.rect.inflate(-3, -3)
+            player2.rect.inflate(-3, -3)
+
+            # Do ball and bat collide?
+            # Note I put in an odd rule that sets self.hit to 1 when they collide, and unsets it in the next
+            # iteration. this is to stop odd ball behaviour where it finds a collision *inside* the
+            # bat, the ball reverses, and is still inside the bat, so bounces around inside.
+            # This way, the ball can always escape and bounce away cleanly
+            if self.rect.colliderect(player1.rect) == 1 and not self.hit:
+                angle = math.pi - angle
+                self.hit = not self.hit
+            elif self.rect.colliderect(player2.rect) == 1 and not self.hit:
+                angle = math.pi - angle
+                self.hit = not self.hit
+            elif self.hit:
+                self.hit = not self.hit
+        self.vector = (angle,z)
+
+    def calcnewpos(self,rect,vector):
+        (angle,z) = vector
+        (dx,dy) = (z*math.cos(angle),z*math.sin(angle))
+        return rect.move(dx,dy)
+
+class Bat(pygame.sprite.Sprite):
+    """Movable tennis 'bat' with which one hits the ball
+    Returns: bat object
+    Functions: reinit, update, moveup, movedown
+    Attributes: which, speed"""
+
+    def __init__(self, side):
+        pygame.sprite.Sprite.__init__(self)
+        self.image, self.rect = load_png('bat.png')
+        screen = pygame.display.get_surface()
+        self.area = screen.get_rect()
+        self.side = side
+        self.speed = 10
+        self.state = "still"
+        self.reinit()
+
+    def reinit(self):
+        self.state = "still"
+        self.movepos = [0,0]
+        if self.side == "left":
+            self.rect.midleft = self.area.midleft
+        elif self.side == "right":
+            self.rect.midright = self.area.midright
+
+    def update(self):
+        newpos = self.rect.move(self.movepos)
+        if self.area.contains(newpos):
+            self.rect = newpos
+        pygame.event.pump()
+
+    def moveup(self):
+        self.movepos[1] = self.movepos[1] - (self.speed)
+        self.state = "moveup"
+
+    def movedown(self):
+        self.movepos[1] = self.movepos[1] + (self.speed)
+        self.state = "movedown"
+
+
+def main():
+    # Initialise screen
+    pygame.init()
+    screen = pygame.display.set_mode((640, 480))
+    pygame.display.set_caption('Basic Pong')
+
+    # Fill background
+    background = pygame.Surface(screen.get_size())
+    background = background.convert()
+    background.fill((0, 0, 0))
+
+    # Initialise players
+    global player1
+    global player2
+    player1 = Bat("left")
+    player2 = Bat("right")
+
+    # Initialise ball
+    speed = 13
+    rand = ((0.1 * (random.randint(5,8))))
+    ball = Ball((0,0),(0.47,speed))
+
+    # Initialise sprites
+    playersprites = pygame.sprite.RenderPlain((player1, player2))
+    ballsprite = pygame.sprite.RenderPlain(ball)
+
+    # Blit everything to the screen
+    screen.blit(background, (0, 0))
+    pygame.display.flip()
+
+    # Initialise clock
+    clock = pygame.time.Clock()
+
+    # Event loop
+    while 1:
+        # Make sure game doesn't run at more than 60 frames per second
+        clock.tick(60)
+
+        for event in pygame.event.get():
+            if event.type == QUIT:
+                return
+            elif event.type == KEYDOWN:
+                if event.key == K_a:
+                    player1.moveup()
+                if event.key == K_z:
+                    player1.movedown()
+                if event.key == K_UP:
+                    player2.moveup()
+                if event.key == K_DOWN:
+                    player2.movedown()
+            elif event.type == KEYUP:
+                if event.key == K_a or event.key == K_z:
+                    player1.movepos = [0,0]
+                    player1.state = "still"
+                if event.key == K_UP or event.key == K_DOWN:
+                    player2.movepos = [0,0]
+                    player2.state = "still"
+
+        screen.blit(background, ball.rect, ball.rect)
+        screen.blit(background, player1.rect, player1.rect)
+        screen.blit(background, player2.rect, player2.rect)
+        ballsprite.update()
+        playersprites.update()
+        ballsprite.draw(screen)
+        playersprites.draw(screen)
+        pygame.display.flip()
+
+
+if __name__ == '__main__': main()
+
+
+

As well as showing you the final product, I'll point you back to TomPong, upon which all of this is based. Download it, have a look +at the source code, and you'll see a full implementation of pong using all of the code you've seen in this tutorial, as well as lots of +other code I've added in various versions, such as some extra physics for spinning, and various other bug and glitch fixes.

+

Oh, find TomPong at http://www.tomchance.uklinux.net/projects/pong.shtml.

+
+
+
+ + +

+
+Edit on GitHub +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/draw.cp39-win_amd64.pyd b/venv/Lib/site-packages/pygame/draw.cp39-win_amd64.pyd new file mode 100644 index 0000000000000000000000000000000000000000..70528da7aa8e7bd2b64e286665c2164a6ebf222d GIT binary patch literal 48128 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

+Um_140aE?;-3MJT(37yGQDwWFp_o>6@*o_ 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 F{{`N>BHaK0 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/draw.pyi b/venv/Lib/site-packages/pygame/draw.pyi new file mode 100644 index 0000000..8a24089 --- /dev/null +++ b/venv/Lib/site-packages/pygame/draw.pyi @@ -0,0 +1,74 @@ +from typing import Optional, Sequence + +from pygame.rect import Rect +from pygame.surface import Surface + +from ._common import _ColorValue, _Coordinate, _RectValue + +def rect( + surface: Surface, + color: _ColorValue, + rect: _RectValue, + width: int = 0, + border_radius: int = -1, + border_top_left_radius: int = -1, + border_top_right_radius: int = -1, + border_bottom_left_radius: int = -1, + border_bottom_right_radius: int = -1, +) -> Rect: ... +def polygon( + surface: Surface, + color: _ColorValue, + points: Sequence[_Coordinate], + width: int = 0, +) -> Rect: ... +def circle( + surface: Surface, + color: _ColorValue, + center: _Coordinate, + radius: float, + width: int = 0, + draw_top_right: Optional[bool] = None, + draw_top_left: Optional[bool] = None, + draw_bottom_left: Optional[bool] = None, + draw_bottom_right: Optional[bool] = None, +) -> Rect: ... +def ellipse( + surface: Surface, color: _ColorValue, rect: _RectValue, width: int = 0 +) -> Rect: ... +def arc( + surface: Surface, + color: _ColorValue, + rect: _RectValue, + start_angle: float, + stop_angle: float, + width: int = 1, +) -> Rect: ... +def line( + surface: Surface, + color: _ColorValue, + start_pos: _Coordinate, + end_pos: _Coordinate, + width: int = 1, +) -> Rect: ... +def lines( + surface: Surface, + color: _ColorValue, + closed: bool, + points: Sequence[_Coordinate], + width: int = 1, +) -> Rect: ... +def aaline( + surface: Surface, + color: _ColorValue, + start_pos: _Coordinate, + end_pos: _Coordinate, + blend: int = 1, +) -> Rect: ... +def aalines( + surface: Surface, + color: _ColorValue, + closed: bool, + points: Sequence[_Coordinate], + blend: int = 1, +) -> Rect: ... diff --git a/venv/Lib/site-packages/pygame/draw_py.py b/venv/Lib/site-packages/pygame/draw_py.py new file mode 100644 index 0000000..edd1c0c --- /dev/null +++ b/venv/Lib/site-packages/pygame/draw_py.py @@ -0,0 +1,564 @@ +# -*- coding: utf-8 -*- +"""Pygame Drawing algorithms written in Python. (Work in Progress) + +Implement Pygame's Drawing Algorithms in a Python version for testing +and debugging. +""" + +from collections import namedtuple +from math import floor, ceil + + +# H E L P E R F U N C T I O N S # + +# fractional part of x + + +def frac(value): + """return fractional part of x""" + return value - floor(value) + + +def inv_frac(value): + """return inverse fractional part of x""" + return 1 - (value - floor(value)) # eg, 1 - frac(x) + + +BoundingBox = namedtuple("BoundingBox", ["left", "top", "right", "bottom"]) +Point = namedtuple("Point", ["x", "y"]) + + +# L O W L E V E L D R A W F U N C T I O N S # +# (They are too low-level to be translated into python, right?) + + +def set_at(surf, in_x, in_y, color): + """Set the color of a pixel in a surface""" + surf.set_at((in_x, in_y), color) + + +def draw_pixel(surf, pos, color, bright, blend=True): + """draw one blended pixel with given brightness.""" + try: + other_col = surf.get_at(pos) if blend else (0, 0, 0, 0) + except IndexError: # pixel outside the surface + return + new_color = tuple( + (bright * col + (1 - bright) * pix) for col, pix in zip(color, other_col) + ) + # FIXME what should happen if only one, color or surf_col, has alpha? + surf.set_at(pos, new_color) + + +def _drawhorzline(surf, color, x_from, in_y, x_to): + if x_from == x_to: + surf.set_at((x_from, in_y), color) + return + + start, end = (x_from, x_to) if x_from <= x_to else (x_to, x_from) + for line_x in range(start, end + 1): + surf.set_at((line_x, in_y), color) + + +def _drawvertline(surf, color, in_x, y_from, y_to): + if y_from == y_to: + surf.set_at((in_x, y_from), color) + return + + start, end = (y_from, y_to) if y_from <= y_to else (y_to, y_from) + for line_y in range(start, end + 1): + surf.set_at((in_x, line_y), color) + + +# I N T E R N A L D R A W L I N E F U N C T I O N S # + + +def _clip_and_draw_horizline(surf, color, x_from, in_y, x_to): + """draw clipped horizontal line.""" + # check Y inside surf + clip = surf.get_clip() + if in_y < clip.y or in_y >= clip.y + clip.h: + return + + x_from = max(x_from, clip.x) + x_to = min(x_to, clip.x + clip.w - 1) + + # check any x inside surf + if x_to < clip.x or x_from >= clip.x + clip.w: + return + + _drawhorzline(surf, color, x_from, in_y, x_to) + + +def _clip_and_draw_vertline(surf, color, in_x, y_from, y_to): + """draw clipped vertical line.""" + # check X inside surf + clip = surf.get_clip() + + if in_x < clip.x or in_x >= clip.x + clip.w: + return + + y_from = max(y_from, clip.y) + y_to = min(y_to, clip.y + clip.h - 1) + + # check any y inside surf + if y_to < clip.y or y_from >= clip.y + clip.h: + return + + _drawvertline(surf, color, in_x, y_from, y_to) + + +# These constants xxx_EDGE are "outside-the-bounding-box"-flags +LEFT_EDGE = 0x1 +RIGHT_EDGE = 0x2 +BOTTOM_EDGE = 0x4 +TOP_EDGE = 0x8 + + +def encode(pos, b_box): + """returns a code that defines position with respect to a bounding box""" + # we use the fact that python interprets booleans (the inequalities) + # as 0/1, and then multiply them with the xxx_EDGE flags + return ( + (pos[0] < b_box.left) * LEFT_EDGE + + (pos[0] > b_box.right) * RIGHT_EDGE + + (pos[1] < b_box.top) * TOP_EDGE + + (pos[1] > b_box.bottom) * BOTTOM_EDGE + ) + + +def clip_line(line, b_box, use_float=False): + """Algorithm to calculate the clipped line. + + We calculate the coordinates of the part of the line segment within the + bounding box (defined by left, top, right, bottom). The we write + the coordinates of the line segment into "line", much like the C-algorithm. + With `use_float` True, clip_line is usable for float-clipping. + + Returns: true if the line segment cuts the bounding box (false otherwise) + """ + + def inside(code): + return not code + + def accept(code_a, code_b): + return not (code_a or code_b) + + def reject(code_a, code_b): + return code_a and code_b + + assert isinstance(line, list) + x_1, y_1, x_2, y_2 = line + dtype = float if use_float else int + + while True: + # the coordinates are progressively modified with the codes, + # until they are either rejected or correspond to the final result. + code1 = encode((x_1, y_1), b_box) + code2 = encode((x_2, y_2), b_box) + + if accept(code1, code2): + # write coordinates into "line" ! + line[:] = x_1, y_1, x_2, y_2 + return True + if reject(code1, code2): + return False + + # We operate on the (x_1, y_1) point, + # and swap if it is inside the bbox: + if inside(code1): + x_1, x_2 = x_2, x_1 + y_1, y_2 = y_2, y_1 + code1, code2 = code2, code1 + slope = (y_2 - y_1) / float(x_2 - x_1) if (x_2 != x_1) else 1.0 + # Each case, if true, means that we are outside the border: + # calculate x_1 and y_1 to be the "first point" inside the bbox... + if code1 & LEFT_EDGE: + y_1 += dtype((b_box.left - x_1) * slope) + x_1 = b_box.left + elif code1 & RIGHT_EDGE: + y_1 += dtype((b_box.right - x_1) * slope) + x_1 = b_box.right + elif code1 & BOTTOM_EDGE: + if x_2 != x_1: + x_1 += dtype((b_box.bottom - y_1) / slope) + y_1 = b_box.bottom + elif code1 & TOP_EDGE: + if x_2 != x_1: + x_1 += dtype((b_box.top - y_1) / slope) + y_1 = b_box.top + + +def _draw_line(surf, color, start, end): + """draw a non-horizontal line (without anti-aliasing).""" + # Variant of https://en.wikipedia.org/wiki/Bresenham's_line_algorithm + # + # This strongly differs from craw.c implementation, because we use a + # "slope" variable (instead of delta_x and delta_y) and a "error" variable. + # And we can not do pointer-arithmetic with "BytesPerPixel", like in + # the C-algorithm. + if start.x == end.x: + # This case should not happen... + raise ValueError + + slope = abs((end.y - start.y) / (end.x - start.x)) + error = 0.0 + + if slope < 1: + # Here, it's a rather horizontal line + + # 1. check in which octants we are & set init values + if end.x < start.x: + start.x, end.x = end.x, start.x + start.y, end.y = end.y, start.y + line_y = start.y + dy_sign = 1 if (start.y < end.y) else -1 + + # 2. step along x coordinate + for line_x in range(start.x, end.x + 1): + set_at(surf, line_x, line_y, color) + error += slope + if error >= 0.5: + line_y += dy_sign + error -= 1 + else: + # Case of a rather vertical line + + # 1. check in which octants we are & set init values + if start.y > end.y: + start.x, end.x = end.x, start.x + start.y, end.y = end.y, start.y + line_x = start.x + slope = 1 / slope + dx_sign = 1 if (start.x < end.x) else -1 + + # 2. step along y coordinate + for line_y in range(start.y, end.y + 1): + set_at(surf, line_x, line_y, color) + error += slope + if error >= 0.5: + line_x += dx_sign + error -= 1 + + +def _draw_aaline(surf, color, start, end, blend): + """draw an anti-aliased line. + + The algorithm yields identical results with _draw_line for horizontal, + vertical or diagonal lines, and results changes smoothly when changing + any of the endpoint coordinates. + + Note that this yields strange results for very short lines, eg + a line from (0, 0) to (0, 1) will draw 2 pixels, and a line from + (0, 0) to (0, 1.1) will blend 10 % on the pixel (0, 2). + """ + # The different requirements that we have on an antialiasing algorithm + # implies to make some compromises: + # 1. We want smooth evolution wrt to the 4 endpoint coordinates + # (this means also that we want a smooth evolution when the angle + # passes +/- 45° + # 2. We want the same behavior when swapping the endpoints + # 3. We want understandable results for the endpoint values + # (eg we want to avoid half-integer values to draw a simple plain + # horizontal or vertical line between two integer l endpoints) + # + # This implies to somehow make the line artificially 1 pixel longer + # and to draw a full pixel when we have the endpoints are identical. + d_x = end.x - start.x + d_y = end.y - start.y + + if d_x == 0 and d_y == 0: + # For smoothness reasons, we could also do some blending here, + # but it seems overshoot... + set_at(surf, int(start.x), int(start.y), color) + return + + if start.x > end.x or start.y > end.y: + start.x, end.x = end.x, start.x + start.y, end.y = end.y, start.y + d_x = -d_x + d_y = -d_y + + if abs(d_x) >= abs(d_y): + slope = d_y / d_x + + def draw_two_pixel(in_x, float_y, factor): + flr_y = floor(float_y) + draw_pixel(surf, (in_x, flr_y), color, factor * inv_frac(float_y), blend) + draw_pixel(surf, (in_x, flr_y + 1), color, factor * frac(float_y), blend) + + _draw_aaline_dx(d_x, slope, end, start, draw_two_pixel) + else: + slope = d_x / d_y + + def draw_two_pixel(float_x, in_y, factor): + fl_x = floor(float_x) + draw_pixel(surf, (fl_x, in_y), color, factor * inv_frac(float_x), blend) + draw_pixel(surf, (fl_x + 1, in_y), color, factor * frac(float_x), blend) + + _draw_aaline_dy(d_y, slope, end, start, draw_two_pixel) + + +def _draw_aaline_dy(d_y, slope, end, start, draw_two_pixel): + g_y = ceil(start.y) + g_x = start.x + (g_y - start.y) * slope + # 1. Draw start of the segment + if start.y < g_y: + draw_two_pixel(g_x - slope, floor(start.y), inv_frac(start.y)) + # 2. Draw end of the segment + rest = frac(end.y) + s_y = ceil(end.y) + if rest > 0: + s_x = start.x + slope * (d_y + 1 - rest) + draw_two_pixel(s_x, s_y, rest) + else: + s_y += 1 + # 3. loop for other points + for line_y in range(g_y, s_y): + line_x = g_x + slope * (line_y - g_y) + draw_two_pixel(line_x, line_y, 1) + + +def _draw_aaline_dx(d_x, slope, end, start, draw_two_pixel): + # A and G are respectively left and right to the "from" point, but + # with integer-x-coordinate, (and only if from_x is not integer). + # Hence they appear in following order on the line in general case: + # A from-pt G . . . to-pt S + # |------*-------|--- . . . ---|-----*------|- + g_x = ceil(start.x) + g_y = start.y + (g_x - start.x) * slope + # 1. Draw start of the segment if we have a non-integer-part + if start.x < g_x: + # this corresponds to the point "A" + draw_two_pixel(floor(start.x), g_y - slope, inv_frac(start.x)) + # 2. Draw end of the segment: we add one pixel for homogeneity reasons + rest = frac(end.x) + s_x = ceil(end.x) + if rest > 0: + # Again we draw only if we have a non-integer-part + s_y = start.y + slope * (d_x + 1 - rest) + draw_two_pixel(s_x, s_y, rest) + else: + s_x += 1 + # 3. loop for other points + for line_x in range(g_x, s_x): + line_y = g_y + slope * (line_x - g_x) + draw_two_pixel(line_x, line_y, 1) + + +# C L I P A N D D R A W L I N E F U N C T I O N S # + + +def _clip_and_draw_line(surf, rect, color, pts): + """clip the line into the rectangle and draw if needed. + + Returns true if anything has been drawn, else false.""" + # "pts" is a list with the four coordinates of the two endpoints + # of the line to be drawn : pts = x1, y1, x2, y2. + # The data format is like that to stay closer to the C-algorithm. + if not clip_line( + pts, BoundingBox(rect.x, rect.y, rect.x + rect.w - 1, rect.y + rect.h - 1) + ): + # The line segment defined by "pts" is not crossing the rectangle + return 0 + if pts[1] == pts[3]: # eg y1 == y2 + _drawhorzline(surf, color, pts[0], pts[1], pts[2]) + elif pts[0] == pts[2]: # eg x1 == x2 + _drawvertline(surf, color, pts[0], pts[1], pts[3]) + else: + _draw_line(surf, color, Point(pts[0], pts[1]), Point(pts[2], pts[3])) + return 1 + + +def _clip_and_draw_line_width(surf, rect, color, line, width): + yinc = xinc = 0 + if abs(line[0] - line[2]) > abs(line[1] - line[3]): + yinc = 1 + else: + xinc = 1 + newpts = line[:] + if _clip_and_draw_line(surf, rect, color, newpts): + anydrawn = 1 + frame = newpts[:] + else: + anydrawn = 0 + frame = [10000, 10000, -10000, -10000] + + for loop in range(1, width // 2 + 1): + newpts[0] = line[0] + xinc * loop + newpts[1] = line[1] + yinc * loop + newpts[2] = line[2] + xinc * loop + newpts[3] = line[3] + yinc * loop + if _clip_and_draw_line(surf, rect, color, newpts): + anydrawn = 1 + frame[0] = min(newpts[0], frame[0]) + frame[1] = min(newpts[1], frame[1]) + frame[2] = max(newpts[2], frame[2]) + frame[3] = max(newpts[3], frame[3]) + + if loop * 2 < width: + newpts[0] = line[0] - xinc * loop + newpts[1] = line[1] - yinc * loop + newpts[2] = line[2] - xinc * loop + newpts[3] = line[3] - yinc * loop + if _clip_and_draw_line(surf, rect, color, newpts): + anydrawn = 1 + frame[0] = min(newpts[0], frame[0]) + frame[1] = min(newpts[1], frame[1]) + frame[2] = max(newpts[2], frame[2]) + frame[3] = max(newpts[3], frame[3]) + + return anydrawn + + +def _clip_and_draw_aaline(surf, rect, color, line, blend): + """draw anti-aliased line between two endpoints.""" + if not clip_line( + line, + BoundingBox(rect.x - 1, rect.y - 1, rect.x + rect.w, rect.y + rect.h), + use_float=True, + ): + return # TODO Rect(rect.x, rect.y, 0, 0) + _draw_aaline(surf, color, Point(line[0], line[1]), Point(line[2], line[3]), blend) + return # TODO Rect(-- affected area --) + + +# D R A W L I N E F U N C T I O N S # + + +def draw_aaline(surf, color, from_point, to_point, blend=True): + """draw anti-aliased line between two endpoints.""" + line = [from_point[0], from_point[1], to_point[0], to_point[1]] + return _clip_and_draw_aaline(surf, surf.get_clip(), color, line, blend) + + +def draw_line(surf, color, from_point, to_point, width=1): + """draw anti-aliased line between two endpoints.""" + line = [from_point[0], from_point[1], to_point[0], to_point[1]] + return _clip_and_draw_line_width(surf, surf.get_clip(), color, line, width) + + +# M U L T I L I N E F U N C T I O N S # + + +def _multi_lines( + surf, + color, + closed, # pylint: disable=too-many-arguments + points, + width=1, + blend=False, + aaline=False, +): + """draw several lines, either anti-aliased or not.""" + # The code for anti-aliased or not is almost identical, so it's factorized + if len(points) <= 2: + raise TypeError + line = [0] * 4 # store x1, y1 & x2, y2 of the lines to be drawn + + xlist = [pt[0] for pt in points] + ylist = [pt[1] for pt in points] + line[0] = xlist[0] + line[1] = ylist[0] + b_box = BoundingBox(left=xlist[0], right=xlist[0], top=ylist[0], bottom=ylist[0]) + + for line_x, line_y in points[1:]: + b_box.left = min(b_box.left, line_x) + b_box.right = max(b_box.right, line_x) + b_box.top = min(b_box.top, line_y) + b_box.bottom = max(b_box.bottom, line_y) + + rect = surf.get_clip() + for loop in range(1, len(points)): + + line[0] = xlist[loop - 1] + line[1] = ylist[loop - 1] + line[2] = xlist[loop] + line[3] = ylist[loop] + if aaline: + _clip_and_draw_aaline(surf, rect, color, line, blend) + else: + _clip_and_draw_line_width(surf, rect, color, line, width) + + if closed: + line[0] = xlist[len(points) - 1] + line[1] = ylist[len(points) - 1] + line[2] = xlist[0] + line[3] = ylist[0] + if aaline: + _clip_and_draw_aaline(surf, rect, color, line, blend) + else: + _clip_and_draw_line_width(surf, rect, color, line, width) + + # TODO Rect(...) + + +def draw_lines(surf, color, closed, points, width=1): + """draw several lines connected through the points.""" + return _multi_lines(surf, color, closed, points, width, aaline=False) + + +def draw_aalines(surf, color, closed, points, blend=True): + """draw several anti-aliased lines connected through the points.""" + return _multi_lines(surf, color, closed, points, blend=blend, aaline=True) + + +def draw_polygon(surface, color, points, width): + """Draw a polygon""" + if width: + draw_lines(surface, color, 1, points, width) + return # TODO Rect(...) + num_points = len(points) + point_x = [x for x, y in points] + point_y = [y for x, y in points] + + miny = min(point_y) + maxy = max(point_y) + + if miny == maxy: + minx = min(point_x) + maxx = max(point_x) + _clip_and_draw_horizline(surface, color, minx, miny, maxx) + return # TODO Rect(...) + + for y_coord in range(miny, maxy + 1): + x_intersect = [] + for i in range(num_points): + _draw_polygon_inner_loop(i, point_x, point_y, y_coord, x_intersect) + + x_intersect.sort() + for i in range(0, len(x_intersect), 2): + _clip_and_draw_horizline( + surface, color, x_intersect[i], y_coord, x_intersect[i + 1] + ) + + # special case : horizontal border lines + for i in range(num_points): + i_prev = i - 1 if i else num_points - 1 + if miny < point_y[i] == point_y[i_prev] < maxy: + _clip_and_draw_horizline( + surface, color, point_x[i], point_y[i], point_x[i_prev] + ) + + return # TODO Rect(...) + + +def _draw_polygon_inner_loop(index, point_x, point_y, y_coord, x_intersect): + i_prev = index - 1 if index else len(point_x) - 1 + + y_1 = point_y[i_prev] + y_2 = point_y[index] + + if y_1 < y_2: + x_1 = point_x[i_prev] + x_2 = point_x[index] + elif y_1 > y_2: + y_2 = point_y[i_prev] + y_1 = point_y[index] + x_2 = point_x[i_prev] + x_1 = point_x[index] + else: # special case handled below + return + + if (y_2 > y_coord >= y_1) or ((y_coord == max(point_y)) and (y_coord <= y_2)): + x_intersect.append((y_coord - y_1) * (x_2 - x_1) // (y_2 - y_1) + x_1) diff --git a/venv/Lib/site-packages/pygame/event.cp39-win_amd64.pyd b/venv/Lib/site-packages/pygame/event.cp39-win_amd64.pyd new file mode 100644 index 0000000000000000000000000000000000000000..03cf7a6ef653d255dab7f63f47eda11d7ce7366b GIT binary patch literal 40448 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 None: ... + @overload + def __init__(self, type: int, **attributes: Any) -> None: ... + def __getattr__(self, name: str) -> Any: ... + +_EventTypes = Union[SupportsInt, Tuple[SupportsInt, ...], List[SupportsInt]] + +def pump() -> None: ... +def get( + eventtype: Optional[_EventTypes] = None, + pump: Any = True, + exclude: Optional[_EventTypes] = None, +) -> List[Event]: ... +def poll() -> Event: ... +def wait(timeout: int = 0) -> Event: ... +def peek(eventtype: Optional[_EventTypes] = None, pump: Any = True) -> bool: ... +def clear(eventtype: Optional[_EventTypes] = None, pump: Any = True) -> None: ... +def event_name(type: int) -> str: ... +def set_blocked(type: Optional[_EventTypes]) -> None: ... +def set_allowed(type: Optional[_EventTypes]) -> None: ... +def get_blocked(type: _EventTypes) -> bool: ... +def set_grab(grab: bool) -> None: ... +def get_grab() -> bool: ... +def post(event: Event) -> bool: ... +def custom_type() -> int: ... diff --git a/venv/Lib/site-packages/pygame/examples/README.rst b/venv/Lib/site-packages/pygame/examples/README.rst new file mode 100644 index 0000000..a319922 --- /dev/null +++ b/venv/Lib/site-packages/pygame/examples/README.rst @@ -0,0 +1,142 @@ +These examples should help get you started with pygame. Here is a +brief rundown of what you get. The source code for all examples +is in the public domain. Feel free to use for your own projects. + +aliens.py + This started off as a port of the SDL demonstration, Aliens. + Now it has evolved into something sort of resembling fun. + This demonstrates a lot of different uses of sprites and + optimized blitting. Also transparancy, colorkeys, fonts, sound, + music, joystick, and more. (PS, my high score is 117! goodluck) + +arraydemo.py + Another example filled with various surfarray effects. + It requires the surfarray and image modules to be installed. + This little demo can also make a good starting point for any of + your own tests with surfarray + +audiocapture.py + Record sound from a microphone, and play back the recorded sound. + +blend_fill.py + BLEND_ing colors in different ways with Surface.fill(). + +blit_blends.py + BLEND_ing colors Surface.blit(). + +camera.py + Basic image capturing and display using pygame.camera + +cursors.py + Make custom cursors :) + +dropevent.py + Drag and drop files. Using the following events. + DROPBEGIN, DROPCOMPLETE, DROPTEXT, DROPFILE + +eventlist.py + Learn about pygame events and input. + Watch the events fly by. Click the mouse, and see the mouse + event come up. Press a keyboard key, and see the key up event. + +font_viewer.py + Display all available fonts in a scrolling window. + +fonty.py + Super quick, super simple application demonstrating + the different ways to render fonts with the font module + +freetype_misc.py + FreeType is a world famous font project. + +glcube.py + Using PyOpenGL and Pygame, this creates a spinning 3D multicolored cube. + +headless_no_windows_needed.py + For using pygame in scripts. + +liquid.py + This example was created in a quick comparison with the + BlitzBasic gaming language. Nonetheless, it demonstrates a quick + 8-bit setup (with colormap). + +mask.py + Single bit pixel manipulation. Fast for collision detection, + and also good for computer vision. + +midi.py + For connecting pygame to musical equipment. + +moveit.py + A very simple example of moving stuff. + +music_drop_fade.py + Fade in and play music from a list while observing + several events. Uses fade_ms added in pygame2, as well as set_endevent, + set_volume, drag and drop events, and the scrap module. + +overlay.py + An old way of displaying video content. + +pixelarray.py + Process whole arrays of pixels at a time. + Like numpy, but for pixels, and also built into pygame. + +playmus.py + Simple music playing example. + +prevent_display_stretching.py + A windows specific example. + +scaletest.py + Showing how to scale Surfaces. + +scrap_clipboard.py + A simple demonstration example for the clipboard support. + +setmodescale.py + SCALED allows you to work in 320x200 and have it show up big. + It handles mouse scaling and selection of a good sized window depending + on the display. + +sound.py + Extremely basic testing of the mixer module. Load a + sound and play it. All from the command shell, no graphics. + +sound_array_demos.py + Echo, delay and other array based processing of sounds. + +sprite_texture.py + Shows how to use hardware Image Textures with pygame.sprite. + +stars.py + A simple starfield example. You can change the center of + perspective by leftclicking the mouse on the screen. + +testsprite.py + More of a test example. If you're interested in how to use sprites, + then check out the aliens.py example instead. + +textinput.py + A little "console" where you can write in text. + Shows how to use the TEXTEDITING and TEXTINPUT events. + +vgrade.py + Demonstrates creating a vertical gradient with + Numpy. The app will create a new gradient every half + second and report the time needed to create and display the + image. If you're not prepared to start working with the + Numpy arrays, don't worry about the source for this one :] + +video.py + It explores some new video APIs in pygame 2. + Including multiple windows, Textures, and such. + +data/ + Directory with the resources for the examples. + +There's LOTS of examples on the pygame website, and on places like github. + +We're always on the lookout for more examples and/or example +requests. Code like this is probably the best way to start +getting involved with Python gaming. diff --git a/venv/Lib/site-packages/pygame/examples/__init__.py b/venv/Lib/site-packages/pygame/examples/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/venv/Lib/site-packages/pygame/examples/__pycache__/__init__.cpython-39.pyc b/venv/Lib/site-packages/pygame/examples/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bc6994f9712d271ae2072e4774efeeb7b490856b GIT binary patch literal 197 zcmYe~<>g`kg1-uCNg(<$h(HF6K#l_t7qb9~6oz01O-8?!3`HPe1o11&*(xTqIJKxa zCNVEBu{g#hwK%&ZzaXZdC_gJTyQDI{xTG{CGcm@|Grl~(Dm6R4JToOHzq~T0EH$qz z#wRl=rZ}@CRkt89IXf{uwK%4rGCeUjRX?>NF}ENmwOBtsJ~J<~BtBlRpz;=nO>TZl OX-=vg$PJ%?m;nG+jWRATo5o-uL=+Txu~)oiNgAi?I<+VG zAjy#%pMevf!B52ZRwPJE-LxH@EXN-D|=ZrAZ{RqS@X%;yLR# z#SuHmVlf6(v=te8x*QNZ*sHMB97d=>C9VLoK>MV$IIi#r4N*xssj#t@HfT;|{4TdD zYlK1a%9$bN&=Yqm3jMevQq+dz171V#nj?#QBMMRH$~r{N@R=bUT8oI&%EqX>4S2I) zuT^AH)hioA#Lw|MpEXz$bYp243wKQp*hqQabb0&=pMjo5I@z*ogS)R7rxey6tJ}@!d5c6KNy&JQrqj9%& zRXf?B%?^a7GLeOLxl~!q2HI1i2oF*Yjy)O2zPr=Q_gEyf*9M1@$HMn^UaqceZa-b| zsd*Hd#xfDw&RNnHzI*aie2=k6=20wsx*J0UXQ}~gEHiD3Ly;7k_8GWnF~}h7#p`FU ze0O90?b`DpQC}+w0oxB{G_{)$Pfm=9gNFBXq2(3E)xlz7;)yz3tR3*ST_rT_o{ literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/examples/__pycache__/aliens.cpython-39.pyc b/venv/Lib/site-packages/pygame/examples/__pycache__/aliens.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9e311709d0aa3a92a38da184bda77075ce7bf870 GIT binary patch literal 9945 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/examples/__pycache__/arraydemo.cpython-39.pyc b/venv/Lib/site-packages/pygame/examples/__pycache__/arraydemo.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6060dd08055d9b884fcc1811bdf9e27be137302c GIT binary patch literal 2747 zcmZWr>yO*U5#QxQqA2Nf5BVOp<1%UDM8Wma#(g0;q>scO0=MTD_B9P5K;UUtI_fBr z-d){U0tFOt@82kN{nmeJ`=vlX>0c;Nq%%w1!zl&M&d$vKc6N3+qo~>R2|WJ|9-sVV zjgWuijml5X8#QG=`b4e1O7T1=Lwewkr2_8@p0z+U-P7& zjd`H5K%Mg7M)R)kA4?E}ES-$=X{ibFsDBm>jrllA<9w1tiU)c8nkVwW_g|jIGC<(q zB2JP(o@N)pG@ArbFyI#e7NS8R3gr~46-zc75KP>;E|&a)ipU01LJ+)LfPtZV8lp&0k8Z!5Jg6GVHISA z@wG0kJ;H3}T-kF=ISaP{&6PzxURXa%Rh&-v(Grg=D3E0UWab>?>9Et*RzB3#6_)lSSG{q@xOU}f zlyiZLLjNR*RnG)YI~f14j&}VhS8!PyBKv~#R8#&BBJP2I|2g~Ovo0i}kliRvBia3u%QKbb-CSfNex{~9sU|Fr zy1)6VcahEbS??ldNp>;qg5T%e-^C|g87uyyRo=>O`6+yI{V9BMlkf-mR5vl$n7%#C z-21S<+yz3c`?NuQ+OXiI4&AM{Vf3ij0bL&ruAeqARd`LhHEj5>@uMbl9PNaR>70(O zxiz-uHl!0IoVol8b5wQVT@g&KZSn?Ft-{>ZSi!L%3!h;cT60I$3x|1cAWe<5W~46j z3zu1#(uaiAuX&WP#-%*~DXeo@6W6K6sJU2EEw;v5kopznjMf($MdgaltKi9IQ3cKe zdylP~eY_Icplu-99+}rbUt^oMdbV|G8w(hXg%1`!YnK+It$7{&E$Udh*jAeWckhPV z+9LzooTO2BMdKRh?s#bp>_cL-_dtGUH?&%5&B{wWwXr}yN;HtIR;^;uVB5wsvS=4j zQs+%Zi)M+mqF`U5!a163=h~X>8b8senD&k zr)a&cTiL&b@qhM+U;1>5U+xLJn3KMZe@A!Y&mD~K;qN^p^A?=6#qM99)Wl`o+?qGq zf*5VE2gODi9XP{AvA#>#!#0_37VE|4;$C52(H%110+cQG4x&JgZ)1*|R`h80$aIAB zNW|GhmZc3_QNRZS-dEC;u%nI*^&?eJKGp67#$Rd&hnaUQp?w4&$k|7K5FGjg_NFo5 z@Ze;k6m$eAi4i-G(moGN{W+NJ-&(#W-wU8Vp%GRkv${VK0?OOUx??T>0^hE907QFH zlAI*a?K-v*7_x*fnsn^tcW8#?))25T{38??@(ysiTJ|cY9Tur**1WAWC*xduVt8UC z%kSXPRV=+ZX99PCW`^w%d*Tw20Sf1nTvr5VP%S%j>4ALtE-EW!g9Nv*`Yb<1!hj6n zh38+t((Y?)rJWt^npQ5brincySmFfsNA1KZlxH^=5bClsG>6a!jEh+IwGS;JR#6hq zc<9bJbZArlw3SKi2?Xg%0_}2rtNfxoNYH*$~fo^Np%)&|}5m~H* z44M@^`o3ciK_PwsB&?bH#1;|yaQ;hZqjKzb2I6ymWF(uhXBL{u|8F2E?K#1khHoj2mJsTQ;+kmpaO?`Xav;*Hpei!5w z`j|d~-$yX_>HU@Ek7@byj1<>4=o;|ibKJ}8^-QFCou;n#dMxYrdg2La!b;hr%)OYa z5I@BQF8n2cE2>5((u5lT264h+)z3j~F5?CnBL#}v;~CDJ(L03y0F#7&j_qG!?45NF PPT8<_ZSR5i%%lGU6l21g literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/examples/__pycache__/audiocapture.cpython-39.pyc b/venv/Lib/site-packages/pygame/examples/__pycache__/audiocapture.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ad88641e95c5c4429c2fa07a14d78e7756eddfea GIT binary patch literal 1675 zcma)6&uimG6xPU+EXz)uIN5a5lp+f4;-&RMdMl;WO}gzunm{+p!e9`x=Gj)FUpq63 zW3#vPy8nZ7Ec7qZwWpkWDTPAcjGS&Rh02~^Z{Ezj_kG_?xUu0G`2FpFHa>6+<99W9 z_^H`%v4{>a3}#S+5oRWYn!0V!2DXjFN^NSV4t3HdZKf`DiSo0OR_alY7+_wsR~=?E zhc%gdYbncWwFleQ7L4rT1J+wThV5Iz zcHR-X4_#KT-d}yFV|>5LTpcJ2GhZ70N6WciET&-!1Go;;A^|Z7OBUx*Sjdut=MC5M z{-F=o1@Jh9Ob$Hnsm~$GIrBwcX3U@PJoQ6AjU%2HvpfTID3WmDkHhHFmor$q!+L>t zrwBUjTh-naWT4Ls7+l2>1Q~`Ss`gODajZ>MYxwH;#aZzD%fo8F?ha2*&Rz%4&wl=C zcpe=6I6VE~`#z~U0yisiA%ir&j*ovcj5{CCxihhf4Xn>2)xG~z-@HH0O(}80Nnkd;=5uD?9pX^hy91qcF=tF**iuDf41f@caTU9P4Tmht<}4GPuw5DO!b+kzw};-@&%;Qm^Jk zX_>ZSu||lt{?){qzDds0P||i*rqK*3f<#oUn(=rEw2Nrwb5J4(GsIs*x!kGmo=z;5 zGyln_;>n$j2QNQ4FL|cyDoIqT%<)zh(*Y&}eDG4~=?@ht-W6wDPA0&Y2kM@xC7QK* z=lg5g|EOvP0n4KxpiWIaHH#^th3^3Ete=iRu;h>{u6aXM3Jb2np}mJ5br2k1XagTw z6%cg`4nds7h`+9FefRm6a&ff!1#hX{l!7$0m8}&=?IJ7%RJKR}3To@jD(fPTGqkBR zsipF&tT$yWA5f?+1=l>fU#B@M6Zl32F22LcYP!TVA3L2!kGKuhw}{nnJ-6kWCUJ=Q V@b{%alHdT5XECq4x<1`g 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 B0BZmM literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/examples/__pycache__/camera.cpython-39.pyc b/venv/Lib/site-packages/pygame/examples/__pycache__/camera.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c623bcc9bba8b957c04bcbb3d4ce1f462c5992e2 GIT binary patch literal 2385 zcmZuzOK;mo5Z>imwB$H$kat@K2$Bd$6sM;qD1zFK69jIZhx0%P6$H&)%amx6*`?x0 zkb$BOkXui^6$NCVm-NtI(-Thxddi`Hpg@7nEak*@y}~YMXJ@&y-+VJv*l4%}+P~hV zwLhi^`3ooen*o!rq08GaFya$NnU+vrQ%~Ke_XyLO@rE#i8#}shGLu+{_a$TM^7e=(-D`j3Y1J3_IM5!o28eHJsGEh@11Lx6~j zrWSv%5fcAN35lS8XrP3Rgg}UiybHsKbV--4lbDR?uk=SsNud?`i0o)xEtYw!<_H zW%~}7y&}uoxyZV_R}2DK^jRFX=kEtw*^u{wt(Ya*)}Z~0r?1-I#A|IC7yMctMm->$ zY*(zhzQ@Yz6-`?CKv>}YN$ApnfzVlcQlFv2bN`3FwRgh^FTB?<*0^&Ky8H=-0#F}o zyMTY77Y5*}?*Nwglotz=(H;5&9ZutXM9+|I?Kw%$8>FxXD-_bGvSb>rydbGISG~_3 zX&51a+&P)8k{x4y|XD?Qs=FV`X@5H4|cR75F>J5$Q2r z@TlOdr9xclkMAusXG^QXsGLHaGEutsQ^sE_ z*|!!|8VW2uKoiVNVWVsm@h11p#UzV*CA3EZ@YIFGSx`<; zSWn`-N!7Iu`Cry?7nH>SZLokyOlxA!%nm<4!s-3i2mHoe$Zh5K?;tR`O-EGxwnxxy zZKT~H->q%yBfYDG*63;S_Cz+JvM+#afgY>;0@Gl3Wru4g)tUpVHSA131%>4m0X-SJ zlYO<*1k1=v)J-8ifLVRqP_&)y9vjavOpp5b_%31Q&jz!8(UrZSC~L1gx%(dZGpsGn zf4lT}{(^U9sJFgYADZ6XhpWxzY=x!CA?1rw2Oxl5gPi-uqo?5jZ`Uu`rF_9YZbE!iw!n00K(-WEl^Wmu@f{HtvHLR&A z~pSx_fx5YbqsGS5oSj- zw7TP*b30A?2`Js*x z%2(rMA67mlvXYdGxEw;CRA)rYrPU@t2XP95rc>JRZOS6JrV1Wb8ozPik3?x@Yh5UI h9}g9m(T5|>ES;|^tZ(C$C6*qe?odacdEnR%{SW3LMO6R* literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/examples/__pycache__/chimp.cpython-39.pyc b/venv/Lib/site-packages/pygame/examples/__pycache__/chimp.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e2a1d1261eab01bc70c2fe7f0c9f8b5e506c4779 GIT binary patch literal 5806 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 aHas!9x~<`H%5awLQ|GRnd)vNktN#JC3w)CR literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/examples/__pycache__/cursors.cpython-39.pyc b/venv/Lib/site-packages/pygame/examples/__pycache__/cursors.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b9eec4bb00f8d84a991da69a921a2ab4a59bea9a GIT binary patch literal 2504 zcmZ{m-EP}96o5(nTTS}2c11R1n+o)29=a6k#efyV&^2wb0b6p>1T!=bf?_g`Vq20a zI*ASGX4zGr!oJ+y9%N6z+g;@q3JlvJCE3p6Q4mG)JLm9_JU(=|zV0F@e|rxPzPg6c zU$V1YH0V5sH~SJQf_y|U(fZiei0o??^#3l}WEozfSPh(H1b&fD1+8fk# zCqH}XxEl`W7Cj3GX`g0Woe|3tmbvbBKkD?n&>JM9jCuzn&Xd^tG&=Og$;dkjPpFr~ z^j^~oW8(26>XnLK=O~Q3V8?YYz%jJb+?Z^fwY-&OveDXFjU-u(6j_N%vIoSd+RBL(r5$lBm%Is#+BRp-Tw*3$j2UbD02otY)}MYOPD8ia0fw zs+PPiw?vIDysoWCDA5ur5%^Of)lz#a7bCjcV{1W~0tgRJVp+jF+{Y~f_g_)ZKpCGoG8@YC<6&R!8v*Bir2^wLx2EFfw zYpRD>n?nZ7(Ot0jEAFDg$`ROoSm?Pm)pC8R6Ud7*4Ze^W)fY13Oq)rYgd4}^)XFVl z5DP{PnB6WMZs&+JJ^+idb&kP<21q*7M&8JAZs#BgxfID%J-Wx_b_m>Jj{0t~hWaKQkZjX)H{Yy?r;MJSZi=tQj(vocea< zpul5c^rM)T?ii54nb5MQ!YVa{F$lAsFtTVue@E;i@aEFy`R<_%6PK*(V^=k%D!R!8s4U zKcK_W6wlxyuiJ=0|nDLclr zp)9)m+Mx!a_q@>fTCSag4rxFb>g)ilu1~L5^R7>C%w&k(DU94Wz6tCWT+nZcTj;~L zLpB8I>3dRE1=zKniw*F*sYM>-(5M9&xQrA1;vX1i_v&hLv%I=_;)UcSj63u~#gneY z7gbYRwD(>&Z?juqK^RdSabX-LG53wvPz#$x83fu`I5LU`388?ae&06^`XFjC2u8|; zHA;z$R4q=}`_dPA2EwFp;$SHq4N{?ZDVXNtl=?S*+}(fk>c#%v-tNxJ-Jf=ZF&ss_ zX|nrLOFQVY524|k-6V>;0#g-sW%aR?fS8QpeP~tj;9wVDhlp_D{9U{Tkzl|h$JU@` zUq~G%2&7gJG#z0F0ZBSR;9F(rsl}Ime+IJ3`MFjM|B!-U$p!fvV9F2YYuJ!cpME1R T#Oyj$hUw_Wrm^YVh6n!(3Scnk literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/examples/__pycache__/dropevent.cpython-39.pyc b/venv/Lib/site-packages/pygame/examples/__pycache__/dropevent.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c2dbfac8034eb8f3728ef10c8a7f971052c70e17 GIT binary patch literal 1638 zcmaJBJ8#=Y`0n@=Ez7Q*v`O5g^in_t>Hr-&1VzxqmJ0)}lR63z98?gL?krQHNcxU` zNTAS%+r48(YV6XnL#O@@P6aw?>s%mkzoRY1?hpd^-S>X+`_5lnbP#-R+>hIT+6euv zi0dB#;!8O4DFB8jVwjN-Q^HBEO%T)iNVr^Q`Z@j)1J9TsjF`d9pAa><#jHLNkGXlS zxa0+@+oK=cWZ3lwe1o6)gCyi~gNZmf2tw{STf*ljlewVv(|NoT&%S=X+h{hf$Y$eJ^9tSG*=;yeCoxm)-ye~foo(~-Mva?col}mCLAk6zhLnjSUUN_ z1Z@HJtuwYWyH^F?A~bcx>@hlOUvX-{d7Un0_BqBVU1Ak=&!x*C{r#HMxgmWIr2ovM zDnszO@~#}`epkV={XffF@3I8Xx7Y$hKa;y?T*)e|dV;_M>fO%YSF#DtKY)&ynVH{V zixa2;Fx4Y#-XqJaKzy9vWwla{^Lv?|855#(p=Yl_b}utCOL4$6&ezmPW?KFsTT&KB z`zgxrmt%@xAeZ-=brO6JqY(TBf07zcMBs62=T{kCwNUS~v#m~}9 zT5T2N0fiSvxv_;F#y%^oP8^+Zk(X?2sC^aTO?? zn0Og@CL9|(*WfbHwUSm?RZ|u#paEQ>^uR*hM0^B(3)}NlB+skch2?oH?sy(GFH;j0 z(4b3dG9(K<_)jv3qoUF{>+mF1s2)T?I(HPoo9%gJv#tR(n}z)aOyY6KAFBsd)&S@W NHi6WMt=XU3_&<(K#IFDV literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/examples/__pycache__/eventlist.cpython-39.pyc b/venv/Lib/site-packages/pygame/examples/__pycache__/eventlist.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6a24b6959734da0888a59fe1f3ec45b7eb11e7bf GIT binary patch literal 4876 zcmaJ_&2QYs73Yv#F2()OrzKf&62^&RZ)z)v<20#}rgbd2RcuRXB_{}>bV2QKS6or# zddQWu0v9Oi^imXs(L*o2tS&|KFZ5LO)W3m;qG&JCx#*=p;r`xmSCZ|dTyZ$_=Dm4u z-n_4oTd7zIp8wjfZ(W~Llz-CT>|r3tZ-!6osNy%?^dnkRTUTn6hkv#^y_UP{EqVv;ZYS{KMQ_gw zlfaJ?%ev>eBDCGDsGAJYY&jd-Zpdvv>~xbw%es}=$+l-FQOAy&vKu#q=YdcFikUcZ z6OZO%PzyJ(xwq#xJbTX#x?X(MqQzVrL{Sj+!F4V$1g8}`W?Zarxt!|`y0sfwfFqk-wHe;-hc}B{g6ldcEb(rEzcHS>>qlZ zCUe0_OF5k@qAt_{X<}~#%k@CmDj#9q{u+a&SZBNoGx z^qZjTNxSF--Bt_o`yuTsU;AR?;`7JQ@9x+D{c3x?!@C|+S z7?!07YL1CTP0#cu1jr2Gh1?UFz7_b1GuHBw`o7PT?V6EkIOt64L~*7k-a(QT8c`65 zthm*Z9j8c8f4B9OBFb3uKRdT?Za#>yolQ3k-FS1!i+A8in;j9gy`7|2kCQI<-OXDo z_5JA3+aX3lwBOr=lkRQa^S3r*Kk=@0+{TXE^5V_hnco~a^P5uf$;abO-P(6u_k!kJj-6<&hQRj!lH5wD)78he_GR}jsf#j>7Vn~(E} z5tig#I#T*tQcgAE`JUpIlM4Faihd=jCgT!o;z)VKlJQh~#OBcJ>wGfRXO(_|c9lx2 z;Zu(a!(C4EnG+t9kD0j1&n1&s#~Mr}lSizn5@o3K*>9nr6D>^-X3p%_Xv^_q z7X3=f2VInvz9Dsdo-aI2of;$UrUs<>8-F3eE^{ez`JdG{c|pD(uE5?etk$&S>o{~V zK5A;ZwEo-$ey+j~4ls3CT1P^CvTQOdIpqh~U(GsW9@1J~$9z^4I4OZ_@gj{1vi`_4q>Ieh z_NW+fEIPxyKRm^(xSh+CX|OOy?~w(tZL*2b%b0lf)Jk+}Ly`vA#I%7tP3Slr`c1F} zCcX#gQ%6CjOvfQp#u7Ry8z5~QF&u&lCBN0z5OUQWHLh~>_7w5j!)n5CJTiqKedstA zWk6|~G38-Zsu%VP!c|4v*&2{^=^z@TKB{HP!AE1V!~8lrnG+*uegOVY3SskD0h-H z|A1p8V)C4I7U!|?XtQfvXmi>HO~`SPpF|eU?-}Umc870)wu%`f4&E{s`D)dulL^q{~i5Gc@WW5vE%E+?>+a!+A+N zE8zuRLOC=?Bzbr+;`f-vs+6?yO?bT8FQ&!Es`wr7=LhGH zlqKac`{I+nnVRhdz+TuLadiU6uYq@E zP?PN&&tQLNN5f8U@JYGWRpNNW&|Z^C`2T2=(lA$kiBc3rR<4&ta8tzwR)WO<_9lAL zW`^@`Noi(DQ;*rh+2rjMCl9S$N1?)`eu(lNX?;rj#^7B(P5T0_0jvD3gunL-CVgyX z74c{S#_Rtbq3G~cnY3(~TcLUhLgZRGmN{N#_L=3-#l?u9spW6lh@V5~=*n=@7BZtRtVSm{m6&b^D)+fv2G7Yu6^=%oIsMm0+lnZ2Pm-la{N_#sq9>2f#V14UE37z|m#3_Bcvb4M=HM^YY zblr9IpFCLEkU3mt4-`Xz-@(Rw)FAr4i=)yXcF|hvxR`po%LjgfL?}xUir^VL$XEmU z4%aHymf_nev?Bb&AY-0WX>HJ;e^3oVH=;5EyoCzHz_*H@p&4i`HbXP0QfA~^WmKD>a#5>n3a_b}pt68rGVwDK z*{s)zbG?q*uUN11s8O$rJD72d{H7)i)tMXq4@Mfz;;E5{dq5TUsiBN2?xM*`E4!UY zB+EiXA~#H(=EwxZtJJ(k4PEI@buG=}L?k*U$Z?wcWKR}t<_By{2JaHOuChdDmqB1Nm+1W&i*H literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/examples/__pycache__/font_viewer.cpython-39.pyc b/venv/Lib/site-packages/pygame/examples/__pycache__/font_viewer.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fab7c9e48206714b49e93241e739262ca242fc11 GIT binary patch literal 7593 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/examples/__pycache__/fonty.cpython-39.pyc b/venv/Lib/site-packages/pygame/examples/__pycache__/fonty.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a0ba8149463d824e2f6e8c51fff4331f974db75f GIT binary patch literal 1494 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/examples/__pycache__/liquid.cpython-39.pyc b/venv/Lib/site-packages/pygame/examples/__pycache__/liquid.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4019b2c07afc5d7a892364208b89a46fb4005580 GIT binary patch literal 1850 zcmZuy-EJH;6!!e=?(FR52MA3IrI;JaN{~jqj1Z-1ni5(PK@vrbwhZ2}XV=Nhcw&2# zY?zgh+DG64cDX~UcoZIBu0UMnf*UT8kT{-fpsMi5_VMxg^XGFsWNyw!(Ei5n_x@-i z^t)NS+-k7+6uRocKv96GMeW22>}qxb2WBU6(^^ooF8As|ojHe%iC2wH=1;AuMXehs zXi=Beo}-}6=4k!Mmfx`UGh`uVPv)mEQ+pS68sxT(5Y9(^lCl+cM$$ZCY9-;vLr#5v zZ@?9vaWQ47$dr~uGldCO9Avo~;8S2o%;K0u8jBc{%;zcTvlYChG0~c(xmH*U97zVE zpgJIuo)XD0%I2IDeL>W)RoSG0;@U{SJ zMg<0jBasN1lH8A_NGnbv2xSyM+Su(!)6Z5Y&mj4HubVM$`ziObq)291Td4u&mFnAORPEqQq-Y{R_xR zwB4~vNAWB&i>uZK!X)+s=<0I|A&n-MNivNN?Fl3;%r5lWI-1&Jr0XVOb(7lEnL1;$ z>rYw*B<|P-x;>dI>{samnY5)YBytAyLSau9r)X+fDD!}RZHmS=t&JW1I<3Mx_QQ@9}U z?bs_keWP#+kG7W3GJ0mwwwb91GR>j}GHYYM@GBYre`Hz^^IL^oc!eL^MYCv8k9x5? zbu4uJ=kYHPjXin0LhR<`9ojPII{wi_(wW=t*cabJm0tV`z?Lo~KRNd=D|Dro<`*7- z-iKZ_2{K4JFkCDd%7vl--O|sGemno+-i&yD?_vSiom-`y_e+;&T$hbm=9ivgI!qzy zg63xjyZc{l-hc2gXm0H6uRnRXzQ0-8LX~b#^q_PP1OU^`g&VrPFBLfPBf**1)_#!gtKO9!l%t{&w~0$3<;dr)hoYhDmw^OTh}l`xif z+GSnAQ^c~MSw(E>IH*Hh@OT6+$vA|3)=NZmq=Lq1M)*pLymF*UiM>)m3@P57?v*lP;>>+O9M7`ypJK&}~4+Ys}0$NRvu>XzsH1N;ggd;kCd literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/examples/__pycache__/mask.cpython-39.pyc b/venv/Lib/site-packages/pygame/examples/__pycache__/mask.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5eaac2f1a632b08265b578a0c66219b4c3ad4574 GIT binary patch literal 5661 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 QuB_EuvGLVp9YW>5uAR3nH`2t)&tZEm?KDu5bI zyNyip<8XKFP&3>J_Hr*%&N+fHFqV}-qy*E-A6zQ(C;<&X5b%2C^I@KHA!FHG` z43PF(&?mGM?Yrv@Y}NC`MoMFus-cCnw4_v)Ev<|S(>5M(pL_6mf;oVt?u-^XbOo8z zp(t}y&n8ow-u0l4q1Q>;pjovK4{G`Ibx=YrcfS52!3~0!2yPL)Ob`$#g3lAg1YaQ7 zBIppjM$jPmB0-DbI6=EMalU@x%-Q8rmq2J|mTS)W`k60XIeFo7t#ZD8>D*gy_n(ZP zuM07fcxqXKl=(>UXy34S)E}|PM@iwLXmGU(<)Q%#N*vIPOuU-K&=oZYia@K7m7+!$ zveH@uLeV69@z$k_SC&pMUc7Me60)0(cCC21Ba(aKuw`A|SKh6p&}sY7z>;y`wXTA7 ztjtJpLTck|e+49ZJ@9Me?_9ic`OG^Pm(N{XN^*FT*tfh!tSDsHCgtI&E6d9lm$aP5 zMm$JzSnP?zStDbs6-npyR+!{G->*#!y>;c?nxh}CttAD%&}k

O3hKEdHW$>HYk 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/examples/__pycache__/moveit.cpython-39.pyc b/venv/Lib/site-packages/pygame/examples/__pycache__/moveit.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1199c8df122b7101d61b589cb7142b2e43ab77a5 GIT binary patch literal 2034 zcmZ8i-EJF26rP!#wKp3lEorF=s$hsjiy^p_%L<{Q21*1CAW{J!}&{`qit z07G$@IEoO*oMbq{ZY7Z?@R%-rH#bCcg;zj%14Y3j#63=5AWqLow84Gec!8pjH+cZ- zrfBhv36VdG&2xm2@RnOESULF~wZr5-Mu?S*VKNmR@hq8^nNXc+aUxP3hDW1RG5FUb z!3MJ|V@b~0AkCAEUGTDjET)eBt&_oyX1b7RlI?}NUlwz=U$6uAIGG4`pxI*(yW6q5 zz7&ZTirxE&6}_?OYvn{Ic{;WCAt;=(B6ornFpInshKGd~EY){_m-SN3R6ohJ) z%cMU6BUHD}vb&dAcDK&5PPs5a9H)7z|BKT5 zaH!B2Edir3;O&rcH)D^J36-}2FQ8wb<<)4VKSH?LzO-tkEkOr@@udaC&`b<;8%wCy z8Wx9*w1w=LZ^Gun;vL+=r&rc2whkUbFu=VWf*i*tjN@s+XPMo%;`n%$WHm)@UJ9(` z+W@R-vI(_gHCbN+9Qe}Syn=+iu-3bLVX)C?3|XRWj-ZuyhBY1g%SHuFW7%BQ**t(^L85t9GnBkg;^MTR`)duUY#Yk3ZgV z9AMA!Zy=8>uUXo$cE#E}Y?JgC2wVC)Wbx@{nI#J$?{$Xh;55wA<5|i(y=mDduBP4e z(!%@lJ($|puRi~2|C=8U*D9p$8M6}7N3@%!QTOPm zQTt%R9@P9$7Bi6AylC(SKQp+HyI}SI^M%@Mdlv}Gx`uFoTLhAvwqR`$3T1T_x4dn< zg9Es~4)g%;5cvV{+S+ot8n?GiGmd%Dk7H>|1&ndONDe2LrnV_s-cWEXaw&B(7*lxzrFdM literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/examples/__pycache__/music_drop_fade.cpython-39.pyc b/venv/Lib/site-packages/pygame/examples/__pycache__/music_drop_fade.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e2df202c71dfb083613b3b4157735bdccb9920c4 GIT binary patch literal 6579 zcmb7I&2t>bb)T=@9SjyA2!datK1LKJaYYHFCC74DiX{dFDVQXPkU(fn!I=!U2f!?L zXO=y^0C%-;rHXcLNp#35l}asAIoOvRQaR<6v&#n`e43N&T!Q}~rBurKz1M>!KvktG zv$Z`vuV24@{rY`&G&SWJc>c$KXXD+s4C6oOm-$7lHGKSv{sz!0Xe+Gb$!+YW4g zJAotYpduVm`Kb|9MOD=Bt_fF6;O&aD!V{A}HG>IJ7gK&}Q_;CCBRDT+f(znwa8b;PGobZKd`ZmhSn{9Z zSDqWDA*{zn<6QKmWf*?9zZG@j`S@AX>9*s1zSGN-W+-IV4L2hZdw0k=-QN(r^O9i>~mN{PRlwR@d-jNOhm72(TdYg^HTJdSt#KftS* z5sS&uew94FNSrsLF34v7(_W&+)S?uJMLY60dP-%?LB5l836X@8#?RETqbEfoFrB-1 z2x~Exx4xYF=exfh{OzYrlfKJ``c?cF@X!Ap&CnRZtf2VTMPp$wF5uRJzXrBxl(XiWZ4xuXf{nMNu!oLf�%`$cmoQGkfcyOuxb+hE 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/examples/__pycache__/playmus.cpython-39.pyc b/venv/Lib/site-packages/pygame/examples/__pycache__/playmus.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..04a5f73fa37cfd7a096941a25213a367b2e860ae GIT binary patch literal 4294 zcmZu!TaOz_74GVb-EKQGj+1OIn_Zd(lC?yfMF0yn)Z45@ z{Vl(r4TqSfu#0zpG4WQG<}yo^cje8;^VBHn3;&AV;p!+FL()7O3=-i<2<~G<3X;ZK zue$3I7k)O*z3qyj@@(XJhcJh+(kFWSvCz4JSKS2>2FzpxCTB2{8Q7(P0;e)ftujrW zH@HV8;!WPde}lLA5?}s|1)es<$)fgD>u36>#~Z?rMx!L|M|qs3mzDoOo2OEsR=$7J zFQ@x)s`4nsb)lkYAe5hDxmGaN`q?@R!F?_x+;>01dbMt`Btk9iVxe=lTSX$GI4@Ewfz!2^*66xzISm~PaFHOUUpF@Oh zL!xOE?m`nqEnC|Z{k*7$VJaqJSeTDD-I{PvC6e_QhFr$}U&OaQTm|N(T8+{)QmeOx+5$>eM>5+KTlsFNa^O8$y?HO3 zWK*#fPGX*9ligJydS~^ccx_e1xwryoZjqfK3$OYk2&sN<&e#Eizq6SU0-~Vy%penh+BBkP)wMy~ z&Bok2YBf3H%>k`waaz*~PvlGVKVLpDxN{nD1Y_-rck&pogIR67opT0eoSGT)(;TjF zU_uT926k7v_Thga;o(1toFVcO1l%^Y&k^xKB;uuUNaXPV1kZndH2s_RKnkV&%iEWI z1d7Xd9^Jb6;ErzhlZ?E51E>b#Dc%6{+v7N2EP3?c<}FNJgsH2(jt`4bsYlA_Ky%2M z*2ExAQ*xj8acUmPyt|mbuBYqhQAR(+5I@@y(*K^XL_b5&^1RAXCvlQ!Ne~zFYzW`( zM+uy4vH^IPs|C%MecpS)Vobr+*DbEx( zLT&<@#G|5C!Ypvt0rGrzB&17Q+IJB?F@gmLI=n0U5gS8H3HS~@Y!|I4^<%l(N)@_P0;JR}?gIlx4x;b;f@eXWeY+uWph+ij4t-wz9 zik7}$-XUGOyHxs+yFj{p58R?5((zD8R4s*rGy;Wv9c=kFkqbl!v_V5^hY9mco+sv! z3(Je>cD)h>HhFMilV22UQm~Ekh+3*WrC@Q;&^}&H*nQI$-@sO%;8heO4V@HRV8dnS z;2$;Cd1>1h*|byH=eQ5DGPE?w-%`|j$c$b{NpPG{yA_7p<0z>{kUV+T55p1^l#%4O zh`dka3K0T@Bx#OGsBxnqLr5geDC)V)uG^;DbkDk$YrD3FTOR|jJ#T=QGb&Sa6so#h zrLM` zjiRGAvPn3mGs7Wr4*u65^pQ)-8|b~}hGg^xUJZQ{cgg|BefFIFq1a;pwl3-kq`A3i zZR&dQcZ?a&*>uhwfSqo?$!Ta7l#bJM@* zolfh$e>^j|$D6-4&l~eICWrW1 zGtTNWHnnWauig3_ZB;*yqB!sn7oNF^#@WXK(XL8y9hR{?$>eUFiEH>Gi3$ z()=AQcZ(z}+aF+rH*Hi~`xZ{_d9=<4}<#sJD=YE_~}Yv;Y$#`P?u>zeVpp@EO5#{>wYK;2URtyl3H1% z1>mg*b*jN|0qSiB?)|VV2~okLL=Wswp4@vZdvv2((V#F9j-q^{uqG&bYI_7J+o7l=pJ}2;)4r{_FK9~+?rlR zYulKAG{@|i-)Hh6orBm+Cxzi5g~LN_hL*feLzdcA@*T8vVhNV3ulA$Lj>?46U^l2m x+sPk-6jmZq{b93n>{dsix^Sl-7c|Gry#e$Nymn$yJWGk zjwPNznU!DLKaH%$sh3$#&MxLz4avekRcVb_NaU4fPKeVAi2P#6~IZL?#uu(V+1Cxp$>J7{q?{Q$AtV>Vrd zJHOcCPdr;oKO9=S*7u8a4c6NC@npT@plprZpr~`Y2FvM3;12B!*MsySEJKmmuzKRa zQpVNHqGfhN_o@c0G8;8kQD+AEM4en?Io*KUY#vcp(DMcm^i^qZqSQhAd+En)A&+%4 z{Ul>!mCbx=A!6eTYm=c{FgYN)1@O{G8B@-owSLpzaV(1@gQnkw3cT{WNd&Tz2si_- z>MWE=D&(jY$~TdG6{0R4fJ`6=(RN_)cJUDZT4A%bvHQGwi5asR z5k;E9Pg-FhFGFKeDi#WX_gfgz@2R+pzJttRP7n$k1B1(Z2L(AUL>wlHFhB%o<}1Ju zL_yHv;b{*{DkQIssf9ART;bp6%wRQ8FfXjZUf2y)mZaSBvdr@cUB6>obFz);8JHtp z(Ot}u1OLnqBfk;Bm6DSCXIMn^E4^nslHb?wAb7vw%kc*4nI@>b*>kq_+>}v7n_QbNv2}tcGzG~@m!OxndBNI7_ zXvy4^$B*djA*kmf4nRu01>1dJfF8@6SGyq(74=>`Jv`VuKB^w<>#_t@@5T&tX>{|n zdlGX+-DmjLC1H3Jw2YDJvL{Yx87a+HdQ9{<$A;Ff3cEmyJ5g-9C&+%rg1Co?3th}+ zk}e=csE8?3_nYJD5k|p5fd83<-`8#way)NDh;7P5GON14)OD#5E4-EzW1w^QB*N@n zY(e##B`T(j=Jn5yJ6pA5OkdV~&V5YQ;By?xmZbP{XUlfE z;M({&x9qZmPhr+BIj&u{XPvTH6;K0pJk*)Q_ceTG(ZcLYj@gwR&%JBkEli??hfg^> F`wuzTjgtTX literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/examples/__pycache__/resizing_new.cpython-39.pyc b/venv/Lib/site-packages/pygame/examples/__pycache__/resizing_new.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7257e3def8b94315f525b2a17befa3a1bf01994a GIT binary patch literal 1048 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 NQQP>lXK?qC{vX&}_#FTM literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/examples/__pycache__/scroll.cpython-39.pyc b/venv/Lib/site-packages/pygame/examples/__pycache__/scroll.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..32e43aeb582fde23ec388dd3854eaa2f5f16dccf GIT binary patch literal 4512 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 HLvjBDr)`a$ literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/examples/__pycache__/setmodescale.cpython-39.pyc b/venv/Lib/site-packages/pygame/examples/__pycache__/setmodescale.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ca2b3313e3a5e52828d43bdfa79da9b2d83002a7 GIT binary patch literal 1838 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/examples/__pycache__/sprite_texture.cpython-39.pyc b/venv/Lib/site-packages/pygame/examples/__pycache__/sprite_texture.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4488170834f39f4d1053edf4f44ffdfd47bd1cb2 GIT binary patch literal 2690 zcmZuy&2!th6$eO4q8Zzw>waW6aTBMuleo^f>Drm?V$@=20g@1{L=eNw2r$8VHi*g1%o>7p9x?L>i4S;zS?BnV zN?!5EXpkvZV)o~VOmnj{lf5@Y zu*d9_vukXOjSUUpO3Yzb*!Z6eGRqx4dyYwk+u0ni@M$)2j={(LGsGs@)z1;T3VRni zi{~b}&ad+^J`ZtWKHs^)%tZwAO*J>Ia|66AuqnRKd7rv$TF*=Qj&lsUWza2aT|O@< z&O)7A%)EgNL~o7w+avzAIyd{?5Rp6lPWFAiJj4*WS}mxRMsJ0zFifiK3b_l`Kgd1+ z>w9d5S7?pjePf7!f^;?e;Sg=1-+W0{`D*7wkgOdUZ?O0?dym`=vytpaT6PLt87zLR zxxZ_RKa6BQ(Xy}9y&!6rl|NEZyWwv~`k!k3zuxNa=lVw@{e93IqCCW-VDo@H6EEf6V6CJYUH+fL6>0n8Js-k8@HtC&AodPq_b-$sGxkySeQyFI-R*X1>S;&tPI zC$%INe#&XePtu;?jTfAxn9WJ{jC>kwW=kHpZXz- z`m!`SLl$&!(*A^pj0-NL#k|yO0N&qzYF&h}2_u;WlA;dIjMVH{Ss^W+p`kIv@Jx8G zT9QWGk_BJkBds9vm^7k9T5!|0v^tR=N?ZA-%okNGt)?IFzacRNPQQsaAJpN|L{j&{ z&`auDJUL3ExE_nB!;jJdP0}9oz50_K+K*285$*ddi28&2F%OUHFZ{!L0_kus287}C zq@Le@^)g*nznd<#cpz;RAoaVgin^J?5@9g|^g{J!VtEN`9#kW6+xDY08Tr2;ZtT8awzw?Y#4C2q@NB>a{i zRt;$-JZMT2u+)#4lWBFx9FW^El5rpiPZ|y`8dG@6IGyrm7K*?4Mv*ljRqNuvFbS2>IZ=^471w}X zDB;DtA`D0i20~v)8~Fl#{dlyveJMd3t-t<7eP2AjSO?qF($kmw58U7VzPc+*l(MKn zskj0PQp{6P15K_fIHA+fV@P#B3Z=6@NK)S2KJimBKB{)zJ%q{#VJV`YOVyxID2fRn zvXI1qpURSVnCS8X+*CQip_9r+<*_V5$BP4RAT9Nn(mdh=;w1V#p$~$fuPRcEYM+cZ zMbxE9Pc*#-mnL*pq3T_z`p{6y0u&vTaKh^j*uZuW zb7KAK)y@Ga?QVaz^~+E9h`md<_cx!s+$P0c`eOU3QqfO#o;^QM0&QaL(pN8)bLjm# zf5lCRj}*MH6~Niez>j~OPoF^!tJ4y|r7#M>3*xp%EEN+e#n1~N9s*%Qyk?RLS!_lE zu0=}fWt(v#3#p$5(Ep$jr~fZYrM;f#^&?e*i2!0bHnyQGY&>T!o3`aZp^O7JWtJzF vVYW@h0S|@aVE7rfVPOkaMWcu(;rEu#0CzdchVq;1Ch-b(O|{d(bH@Jw_QA>q literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/examples/__pycache__/stars.cpython-39.pyc b/venv/Lib/site-packages/pygame/examples/__pycache__/stars.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..035036c13011fd76522b406dcaafaaca9856a6d7 GIT binary patch literal 2756 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 KfqrFl4E4W{{NLgL literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/examples/__pycache__/textinput.cpython-39.pyc b/venv/Lib/site-packages/pygame/examples/__pycache__/textinput.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f1d428361f6c4c5c4868b66f28d47bbf3583389d GIT binary patch literal 3097 zcmZWr-EZ5-5$BSWL{YLVJB~l{$t0J{DNUR-y*5R92+pzPSguYgOhdxU8*8iX=`Zx5Uk9;cHKGe^B3tFVJ)Q62b2^`Ms{APD{W@nbx z)RZp4?|;U}U(H^Xq<;$G@-Gg;=kWMxBuPZV5MwJ8!fnUva9v+9S~lk`YTT{5j_h7^`05Q00bbM;?IyK7qx8?j=psyXrZ8Uk6(ORcvF}ye)ZM%+p zS#z2lYevvVIM=qT%=O&^-l$WjR;Tt)20C`juGKldH_>#h%eY7ygRZyzn#=2Uwe5H8 zG3N~#thN2N?NsY7j;%1;YMsuMAp-@GwsE}PqeoQ{%JEOcR)MDqk3SD2kltl_h)V%F zLtnsYIFyM5=K&RSC{%pTa&jmyKMm2zA0?Io{QKtWi^{%FnP0IS$MP#{)NgXvt9Z<9 z&?fJiKJO6Qs;m^uWA~Ic&10Li+~aNq(tK3evcIbMa9kdHR<&u>s9zc8@yYn)J(--m zWv?41KdVuPo_Or#r?B>a;E~uAkn=@BvOrGL`@Zeej04xUiNNz@)udr;>+nZ$bvyj6I|YEmx_)-ll$)}Vgg{jHY> z5{(3mX-%2cVZNl87px(ABaI$aU7x4eH#{9AL`?>W{ee#f&`U@h>^8(&hZ}&03^Xz@ z@-NWJkyd5@2oykxH~0d4Vo~~?yd(uO@DaBl^<+Lh)}6^c#rgASu57e+c4#@VN-ThX zLK2qF??>2~2)q2FnY@v9Hq!3$D?`tOAJAXKTE!7!4t&3QAVXh~*^P<+qT_JbTf9FX zK!1anPX+Na#21<>XugN>MG}wVJ&JV{2NBVwXvM$s6yW|cjvUc?2-dsSQ-NOZ#U|(* zB90OE-xKUGgX*Q-gXO}HA{Qv&5saUq=Tc8O+~7C+xA^VIQ=@T*FI<;;8ow)iUX$KE ztjN7&Pv`ggAMu;qXxxYA;~*Jma}dh|Ineoofr=mkhcEai{oFw6rAYE(eTa8DfRhx& zMD&RczNkTLk_*WBIH$b~e<;=nQbAhG*_#ehs?@k2OgDb^T#_a8{zN~;9}tN@YCImq zd)W~x`x8`V=o!Ryx&I_O`%n8n=g-7G4_`*Lo+_U2LW$U)L!)3Z;MT)o>pd5pqx>Gd ze2;?MFGAU?g-Vllan|P++^> z%3Fm}+1y@vTPk3f)N?(Yx^zK-pRlzs7HtzJg(kYH!gvWT1?q(Af!%6_iC3>zceZx+ z!t`Xy-JMbxhh`4_Jxo%k)27VgG)%5TcPh25RtqN?I6;}oT_(O&LIh1tEHIoYC1!fH z^VSp-sZ|$Rpek&`7<5ry548hWKMLY>sr=ruv{+~Aa1*v{vP4Oe{)YeEng$Z%M2yRMI?FJU5W=F)%w zXsdOLZ`p8HEWw6wstTexiUG2*D&#OZJTe~OlXja%XJ_kz-M(P=urAKc2ywx0N7v7g zq($V^wq-jnfb+ixA|-W{MQK?@lfMEo(okH^z?cS_G`wXwjppQQA7mv9Gl!0Uh#HgT{84lL6nUIlzs(E*heGoe{{P=y-yn)k0VIwcEt)p2bnO$PxSn}tfpNl~2a?;`PKqG6)oD|o23+|rL;3UJ2UU&_j~Wn@RgOw z!SCPf-QL&Bj`LRx!=fvA1q#>*lU^)H-wMKnYc{i=w>68Z~rO)QT+ zJ(m|=LW1xfJFQjT4;+W(!?t|ECwVGO`(UWKkWsWdN(@_kWkOC=W(v&NJy0$ zGdn4xiNt2X)BtjGrL7Vx){29bW~v8VYd&i;YhSe?I!w}(4S15W8?e4F2h%j2-Czmi z6bx=;s$l#8^SqbJcC>xtK(az7Qm{$#g3L=Y#$ic8s{3j(ky&Bb;Yez%8%cZ;5=)1p zA|g>e$&5?~KnLz+yij_!0Ua5vmw?ca)(M|6Q;=Oo$_b?Rk|H7mv!QIW`;zO-;-c8p z$O=0)P`U!turwKyYS>=zF)-&5_LFt#V&?|yO$kxSaz0Z7cuH&)T25p-0~Q936F1R> zXGuOy!I%PF8LJ3tN6|fKdpH~NiDb9iKW)EnF`nidmD)4rd1@3hBX!v4hU{ROJY)j| zz*Nf!_I$%gFHMTB9rooNW?5oAt+>EWVzSM)2iR}aRQF{yAB{MyM({|DnZraNj9}GB z64d1FZL(&um^{=nhiWO{BB{e$R4BV-p_uVhorRl7z@s6zv1UM2kgUZ*Sd#&!ez6g8 zb`yGTw@9^p+h8BG77l1>rYT~<28cmarson66)AR*V4(TSDG&!#GlcaxQ-=(YRY>-b zE@Q)lI?URPK$pBfVusRfgJ0)=j8_@x%5l4n(iuIHh;6}*4Lhb`f z16OIW%?KMC-zp6h%b<;PkW=vWfKsU)y+XBfI!8bIR#nmR`7{B-i}0tCK|Av*D97bcAX1#Fs-4pNB;l6MmJ7=R~ckUMc6%@QT9pQi1IrfS` z1aoKZiJA!K_zZOJ62AAzcK1*n$#EA6ma4}1YFGR=Oo^oG$$F3cD zbi!fe&AqvM#X0up4$-&g9S6rXtnlYG;fvr)Z(e)TISvcwB$$UFt@b+)v$cVD)e+&) z74=j9IGnq4e;!_PPD0T*bwP7D5AohSC0*DsLEv_EM@ zrI+Pp%_eHuAi7O*B;%0V)1VBisutH#TKS8_V8W0%?UA77c^<^g3D3J$N~>N5^gV8X z7+Z(prJgDZHL-&-5XoRr)@(&B!>XQ^A?Bu&%mz=@G)ckwQ@Hu*qP*O-OMZ;+W*v>= zt-7mj!(H~)-M77U?`=cH62wsqg{gG0rD*#KVNmX@05{d;KOH?r?njnAmA2coR z6``hAsG&GLYM!}vr_*ZMI4zr5-mRpSb?QNqb;|;-FJV_4+0(3ItiC9hWkA)mPCRUf8T|K4+>w#k9d~5O{{b^AeuO)$d^3r;lepik@>M|AYY|-mMVX z_fC9z6Yenz86hY94=Ja@llq+ch6pUq&VKVG!g%Qv2%=v;SwXuhY8GRfy>N;WIQRC~ z@ckklDx2RK_y>+Ip8x*&!^O-hZi)|!OLLc)c>WNURQero5_Vc%@@wFn{1L#H?(KLT zSGw-g?ai&7?%l1Q~P!43K zTaf*~^ac~2WS?QeP%=2kkE#-`BU{$|$i0lZxa>xrZezA=bi1^^+ikg>*2S{k?F!ZJ zcJ;fMjKiwvRshxPU01Ks#Ik*FFTymedi^~TxU_9A$6Hz}T}F>*rjV1Z7fGRUm3M4} zSJ6!Ib#6k2dmfa26R7sh7J$Zw)dBl+${h0+n&7R5+weR%wgyL5y}*x_8y6c<<5I)@ EFNkKh>;M1& literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/examples/__pycache__/video.cpython-39.pyc b/venv/Lib/site-packages/pygame/examples/__pycache__/video.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6e16fc3a6f0792ef273feee8236230069c7784a8 GIT binary patch literal 3406 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/examples/aacircle.py b/venv/Lib/site-packages/pygame/examples/aacircle.py new file mode 100644 index 0000000..de3733d --- /dev/null +++ b/venv/Lib/site-packages/pygame/examples/aacircle.py @@ -0,0 +1,41 @@ +#!/usr/bin/env python + +"""Proof of concept gfxdraw example""" + +import pygame +import pygame.gfxdraw + + +def main(): + pygame.init() + screen = pygame.display.set_mode((500, 500)) + screen.fill((255, 0, 0)) + s = pygame.Surface(screen.get_size(), pygame.SRCALPHA, 32) + pygame.draw.line(s, (0, 0, 0), (250, 250), (250 + 200, 250)) + + width = 1 + for a_radius in range(width): + radius = 200 + pygame.gfxdraw.aacircle(s, 250, 250, radius - a_radius, (0, 0, 0)) + + screen.blit(s, (0, 0)) + + pygame.draw.circle(screen, "green", (50, 100), 10) + pygame.draw.circle(screen, "black", (50, 100), 10, 1) + + pygame.display.flip() + try: + while 1: + event = pygame.event.wait() + if event.type == pygame.QUIT: + break + if event.type == pygame.KEYDOWN: + if event.key == pygame.K_ESCAPE or event.unicode == "q": + break + pygame.display.flip() + finally: + pygame.quit() + + +if __name__ == "__main__": + main() diff --git a/venv/Lib/site-packages/pygame/examples/aliens.py b/venv/Lib/site-packages/pygame/examples/aliens.py new file mode 100644 index 0000000..9fecb3f --- /dev/null +++ b/venv/Lib/site-packages/pygame/examples/aliens.py @@ -0,0 +1,401 @@ +#!/usr/bin/env python +""" pygame.examples.aliens + +Shows a mini game where you have to defend against aliens. + +What does it show you about pygame? + +* pg.sprite, the difference between Sprite and Group. +* dirty rectangle optimization for processing for speed. +* music with pg.mixer.music, including fadeout +* sound effects with pg.Sound +* event processing, keyboard handling, QUIT handling. +* a main loop frame limited with a game clock from pg.time.Clock +* fullscreen switching. + + +Controls +-------- + +* Left and right arrows to move. +* Space bar to shoot +* f key to toggle between fullscreen. + +""" + +import random +import os + +# import basic pygame modules +import pygame as pg + +# see if we can load more than standard BMP +if not pg.image.get_extended(): + raise SystemExit("Sorry, extended image module required") + + +# game constants +MAX_SHOTS = 2 # most player bullets onscreen +ALIEN_ODDS = 22 # chances a new alien appears +BOMB_ODDS = 60 # chances a new bomb will drop +ALIEN_RELOAD = 12 # frames between new aliens +SCREENRECT = pg.Rect(0, 0, 640, 480) +SCORE = 0 + +main_dir = os.path.split(os.path.abspath(__file__))[0] + + +def load_image(file): + """loads an image, prepares it for play""" + file = os.path.join(main_dir, "data", file) + try: + surface = pg.image.load(file) + except pg.error: + raise SystemExit('Could not load image "%s" %s' % (file, pg.get_error())) + return surface.convert() + + +def load_sound(file): + """because pygame can be be compiled without mixer.""" + if not pg.mixer: + return None + file = os.path.join(main_dir, "data", file) + try: + sound = pg.mixer.Sound(file) + return sound + except pg.error: + print("Warning, unable to load, %s" % file) + return None + + +# Each type of game object gets an init and an update function. +# The update function is called once per frame, and it is when each object should +# change its current position and state. +# +# The Player object actually gets a "move" function instead of update, +# since it is passed extra information about the keyboard. + + +class Player(pg.sprite.Sprite): + """Representing the player as a moon buggy type car.""" + + speed = 10 + bounce = 24 + gun_offset = -11 + images = [] + + def __init__(self): + pg.sprite.Sprite.__init__(self, self.containers) + self.image = self.images[0] + self.rect = self.image.get_rect(midbottom=SCREENRECT.midbottom) + self.reloading = 0 + self.origtop = self.rect.top + self.facing = -1 + + def move(self, direction): + if direction: + self.facing = direction + self.rect.move_ip(direction * self.speed, 0) + self.rect = self.rect.clamp(SCREENRECT) + if direction < 0: + self.image = self.images[0] + elif direction > 0: + self.image = self.images[1] + self.rect.top = self.origtop - (self.rect.left // self.bounce % 2) + + def gunpos(self): + pos = self.facing * self.gun_offset + self.rect.centerx + return pos, self.rect.top + + +class Alien(pg.sprite.Sprite): + """An alien space ship. That slowly moves down the screen.""" + + speed = 13 + animcycle = 12 + images = [] + + def __init__(self): + pg.sprite.Sprite.__init__(self, self.containers) + self.image = self.images[0] + self.rect = self.image.get_rect() + self.facing = random.choice((-1, 1)) * Alien.speed + self.frame = 0 + if self.facing < 0: + self.rect.right = SCREENRECT.right + + def update(self): + self.rect.move_ip(self.facing, 0) + if not SCREENRECT.contains(self.rect): + self.facing = -self.facing + self.rect.top = self.rect.bottom + 1 + self.rect = self.rect.clamp(SCREENRECT) + self.frame = self.frame + 1 + self.image = self.images[self.frame // self.animcycle % 3] + + +class Explosion(pg.sprite.Sprite): + """An explosion. Hopefully the Alien and not the player!""" + + defaultlife = 12 + animcycle = 3 + images = [] + + def __init__(self, actor): + pg.sprite.Sprite.__init__(self, self.containers) + self.image = self.images[0] + self.rect = self.image.get_rect(center=actor.rect.center) + self.life = self.defaultlife + + def update(self): + """called every time around the game loop. + + Show the explosion surface for 'defaultlife'. + Every game tick(update), we decrease the 'life'. + + Also we animate the explosion. + """ + self.life = self.life - 1 + self.image = self.images[self.life // self.animcycle % 2] + if self.life <= 0: + self.kill() + + +class Shot(pg.sprite.Sprite): + """a bullet the Player sprite fires.""" + + speed = -11 + images = [] + + def __init__(self, pos): + pg.sprite.Sprite.__init__(self, self.containers) + self.image = self.images[0] + self.rect = self.image.get_rect(midbottom=pos) + + def update(self): + """called every time around the game loop. + + Every tick we move the shot upwards. + """ + self.rect.move_ip(0, self.speed) + if self.rect.top <= 0: + self.kill() + + +class Bomb(pg.sprite.Sprite): + """A bomb the aliens drop.""" + + speed = 9 + images = [] + + def __init__(self, alien): + pg.sprite.Sprite.__init__(self, self.containers) + self.image = self.images[0] + self.rect = self.image.get_rect(midbottom=alien.rect.move(0, 5).midbottom) + + def update(self): + """called every time around the game loop. + + Every frame we move the sprite 'rect' down. + When it reaches the bottom we: + + - make an explosion. + - remove the Bomb. + """ + self.rect.move_ip(0, self.speed) + if self.rect.bottom >= 470: + Explosion(self) + self.kill() + + +class Score(pg.sprite.Sprite): + """to keep track of the score.""" + + def __init__(self): + pg.sprite.Sprite.__init__(self) + self.font = pg.font.Font(None, 20) + self.font.set_italic(1) + self.color = "white" + self.lastscore = -1 + self.update() + self.rect = self.image.get_rect().move(10, 450) + + def update(self): + """We only update the score in update() when it has changed.""" + if SCORE != self.lastscore: + self.lastscore = SCORE + msg = "Score: %d" % SCORE + self.image = self.font.render(msg, 0, self.color) + + +def main(winstyle=0): + # Initialize pygame + if pg.get_sdl_version()[0] == 2: + pg.mixer.pre_init(44100, 32, 2, 1024) + pg.init() + if pg.mixer and not pg.mixer.get_init(): + print("Warning, no sound") + pg.mixer = None + + fullscreen = False + # Set the display mode + winstyle = 0 # |FULLSCREEN + bestdepth = pg.display.mode_ok(SCREENRECT.size, winstyle, 32) + screen = pg.display.set_mode(SCREENRECT.size, winstyle, bestdepth) + + # Load images, assign to sprite classes + # (do this before the classes are used, after screen setup) + img = load_image("player1.gif") + Player.images = [img, pg.transform.flip(img, 1, 0)] + img = load_image("explosion1.gif") + Explosion.images = [img, pg.transform.flip(img, 1, 1)] + Alien.images = [load_image(im) for im in ("alien1.gif", "alien2.gif", "alien3.gif")] + Bomb.images = [load_image("bomb.gif")] + Shot.images = [load_image("shot.gif")] + + # decorate the game window + icon = pg.transform.scale(Alien.images[0], (32, 32)) + pg.display.set_icon(icon) + pg.display.set_caption("Pygame Aliens") + pg.mouse.set_visible(0) + + # create the background, tile the bgd image + bgdtile = load_image("background.gif") + background = pg.Surface(SCREENRECT.size) + for x in range(0, SCREENRECT.width, bgdtile.get_width()): + background.blit(bgdtile, (x, 0)) + screen.blit(background, (0, 0)) + pg.display.flip() + + # load the sound effects + boom_sound = load_sound("boom.wav") + shoot_sound = load_sound("car_door.wav") + if pg.mixer: + music = os.path.join(main_dir, "data", "house_lo.wav") + pg.mixer.music.load(music) + pg.mixer.music.play(-1) + + # Initialize Game Groups + aliens = pg.sprite.Group() + shots = pg.sprite.Group() + bombs = pg.sprite.Group() + all = pg.sprite.RenderUpdates() + lastalien = pg.sprite.GroupSingle() + + # assign default groups to each sprite class + Player.containers = all + Alien.containers = aliens, all, lastalien + Shot.containers = shots, all + Bomb.containers = bombs, all + Explosion.containers = all + Score.containers = all + + # Create Some Starting Values + global score + alienreload = ALIEN_RELOAD + clock = pg.time.Clock() + + # initialize our starting sprites + global SCORE + player = Player() + Alien() # note, this 'lives' because it goes into a sprite group + if pg.font: + all.add(Score()) + + # Run our main loop whilst the player is alive. + while player.alive(): + + # get input + for event in pg.event.get(): + if event.type == pg.QUIT: + return + if event.type == pg.KEYDOWN and event.key == pg.K_ESCAPE: + return + elif event.type == pg.KEYDOWN: + if event.key == pg.K_f: + if not fullscreen: + print("Changing to FULLSCREEN") + screen_backup = screen.copy() + screen = pg.display.set_mode( + SCREENRECT.size, winstyle | pg.FULLSCREEN, bestdepth + ) + screen.blit(screen_backup, (0, 0)) + else: + print("Changing to windowed mode") + screen_backup = screen.copy() + screen = pg.display.set_mode( + SCREENRECT.size, winstyle, bestdepth + ) + screen.blit(screen_backup, (0, 0)) + pg.display.flip() + fullscreen = not fullscreen + + keystate = pg.key.get_pressed() + + # clear/erase the last drawn sprites + all.clear(screen, background) + + # update all the sprites + all.update() + + # handle player input + direction = keystate[pg.K_RIGHT] - keystate[pg.K_LEFT] + player.move(direction) + firing = keystate[pg.K_SPACE] + if not player.reloading and firing and len(shots) < MAX_SHOTS: + Shot(player.gunpos()) + if pg.mixer: + shoot_sound.play() + player.reloading = firing + + # Create new alien + if alienreload: + alienreload = alienreload - 1 + elif not int(random.random() * ALIEN_ODDS): + Alien() + alienreload = ALIEN_RELOAD + + # Drop bombs + if lastalien and not int(random.random() * BOMB_ODDS): + Bomb(lastalien.sprite) + + # Detect collisions between aliens and players. + for alien in pg.sprite.spritecollide(player, aliens, 1): + if pg.mixer: + boom_sound.play() + Explosion(alien) + Explosion(player) + SCORE = SCORE + 1 + player.kill() + + # See if shots hit the aliens. + for alien in pg.sprite.groupcollide(aliens, shots, 1, 1).keys(): + if pg.mixer: + boom_sound.play() + Explosion(alien) + SCORE = SCORE + 1 + + # See if alien boms hit the player. + for bomb in pg.sprite.spritecollide(player, bombs, 1): + if pg.mixer: + boom_sound.play() + Explosion(player) + Explosion(bomb) + player.kill() + + # draw the scene + dirty = all.draw(screen) + pg.display.update(dirty) + + # cap the framerate at 40fps. Also called 40HZ or 40 times per second. + clock.tick(40) + + if pg.mixer: + pg.mixer.music.fadeout(1000) + pg.time.wait(1000) + + +# call the "main" function if running this script +if __name__ == "__main__": + main() + pg.quit() diff --git a/venv/Lib/site-packages/pygame/examples/arraydemo.py b/venv/Lib/site-packages/pygame/examples/arraydemo.py new file mode 100644 index 0000000..c35f376 --- /dev/null +++ b/venv/Lib/site-packages/pygame/examples/arraydemo.py @@ -0,0 +1,129 @@ +#!/usr/bin/env python +""" pygame.examples.arraydemo + +Welcome to the arraydemo! + +Use the numpy array package to manipulate pixels. + +This demo will show you a few things: + +* scale up, scale down, flip, +* cross fade +* soften +* put stripes on it! + +""" + + +import os + +import pygame as pg +from pygame import surfarray + +main_dir = os.path.split(os.path.abspath(__file__))[0] + + +def surfdemo_show(array_img, name): + "displays a surface, waits for user to continue" + screen = pg.display.set_mode(array_img.shape[:2], 0, 32) + surfarray.blit_array(screen, array_img) + pg.display.flip() + pg.display.set_caption(name) + while 1: + e = pg.event.wait() + if e.type == pg.MOUSEBUTTONDOWN: + break + elif e.type == pg.KEYDOWN and e.key == pg.K_s: + # pg.image.save(screen, name+'.bmp') + # s = pg.Surface(screen.get_size(), 0, 32) + # s = s.convert_alpha() + # s.fill((0,0,0,255)) + # s.blit(screen, (0,0)) + # s.fill((222,0,0,50), (0,0,40,40)) + # pg.image.save_extended(s, name+'.png') + # pg.image.save(s, name+'.png') + # pg.image.save(screen, name+'_screen.png') + # pg.image.save(s, name+'.tga') + pg.image.save(screen, name + ".png") + elif e.type == pg.QUIT: + pg.quit() + raise SystemExit() + + +def main(): + """show various surfarray effects""" + import numpy as N + from numpy import int32, uint8, uint + + pg.init() + print("Using %s" % surfarray.get_arraytype().capitalize()) + print("Press the mouse button to advance image.") + print('Press the "s" key to save the current image.') + + # allblack + allblack = N.zeros((128, 128), int32) + surfdemo_show(allblack, "allblack") + + # striped + # the element type is required for N.zeros in numpy else + # an array of float is returned. + striped = N.zeros((128, 128, 3), int32) + striped[:] = (255, 0, 0) + striped[:, ::3] = (0, 255, 255) + surfdemo_show(striped, "striped") + + # rgbarray + imagename = os.path.join(main_dir, "data", "arraydemo.bmp") + imgsurface = pg.image.load(imagename) + rgbarray = surfarray.array3d(imgsurface) + surfdemo_show(rgbarray, "rgbarray") + + # flipped + flipped = rgbarray[:, ::-1] + surfdemo_show(flipped, "flipped") + + # scaledown + scaledown = rgbarray[::2, ::2] + surfdemo_show(scaledown, "scaledown") + + # scaleup + # the element type is required for N.zeros in numpy else + # an #array of floats is returned. + shape = rgbarray.shape + scaleup = N.zeros((shape[0] * 2, shape[1] * 2, shape[2]), int32) + scaleup[::2, ::2, :] = rgbarray + scaleup[1::2, ::2, :] = rgbarray + scaleup[:, 1::2] = scaleup[:, ::2] + surfdemo_show(scaleup, "scaleup") + + # redimg + redimg = N.array(rgbarray) + redimg[:, :, 1:] = 0 + surfdemo_show(redimg, "redimg") + + # soften + # having factor as an array forces integer upgrade during multiplication + # of rgbarray, even for numpy. + factor = N.array((8,), int32) + soften = N.array(rgbarray, int32) + soften[1:, :] += rgbarray[:-1, :] * factor + soften[:-1, :] += rgbarray[1:, :] * factor + soften[:, 1:] += rgbarray[:, :-1] * factor + soften[:, :-1] += rgbarray[:, 1:] * factor + soften //= 33 + surfdemo_show(soften, "soften") + + # crossfade (50%) + src = N.array(rgbarray) + dest = N.zeros(rgbarray.shape) # dest is float64 by default. + dest[:] = 20, 50, 100 + diff = (dest - src) * 0.50 + xfade = src + diff.astype(uint) + surfdemo_show(xfade, "xfade") + + # alldone + pg.quit() + + +if __name__ == "__main__": + main() diff --git a/venv/Lib/site-packages/pygame/examples/audiocapture.py b/venv/Lib/site-packages/pygame/examples/audiocapture.py new file mode 100644 index 0000000..aa50fcf --- /dev/null +++ b/venv/Lib/site-packages/pygame/examples/audiocapture.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python +""" pygame.examples.audiocapture + +A pygame 2 experiment. + +* record sound from a microphone +* play back the recorded sound +""" +import pygame as pg +import time + +from pygame._sdl2 import ( + get_audio_device_names, + AudioDevice, + AUDIO_F32, + AUDIO_ALLOW_FORMAT_CHANGE, +) +from pygame._sdl2.mixer import set_post_mix + + +pg.mixer.pre_init(44100, 32, 2, 512) +pg.init() + +# init_subsystem(INIT_AUDIO) +names = get_audio_device_names(True) +print(names) + +sounds = [] +sound_chunks = [] + + +def callback(audiodevice, audiomemoryview): + """This is called in the sound thread. + + Note, that the frequency and such you request may not be what you get. + """ + # print(type(audiomemoryview), len(audiomemoryview)) + # print(audiodevice) + sound_chunks.append(bytes(audiomemoryview)) + + +def postmix_callback(postmix, audiomemoryview): + """This is called in the sound thread. + + At the end of mixing we get this data. + """ + print(type(audiomemoryview), len(audiomemoryview)) + print(postmix) + + +set_post_mix(postmix_callback) + +audio = AudioDevice( + devicename=names[0], + iscapture=True, + frequency=44100, + audioformat=AUDIO_F32, + numchannels=2, + chunksize=512, + allowed_changes=AUDIO_ALLOW_FORMAT_CHANGE, + callback=callback, +) +# start recording. +audio.pause(0) + +print(audio) + +print("recording with '%s'" % names[0]) +time.sleep(5) + + +print("Turning data into a pg.mixer.Sound") +sound = pg.mixer.Sound(buffer=b"".join(sound_chunks)) + +print("playing back recorded sound") +sound.play() +time.sleep(5) +pg.quit() diff --git a/venv/Lib/site-packages/pygame/examples/blend_fill.py b/venv/Lib/site-packages/pygame/examples/blend_fill.py new file mode 100644 index 0000000..301888b --- /dev/null +++ b/venv/Lib/site-packages/pygame/examples/blend_fill.py @@ -0,0 +1,115 @@ +#!/usr/bin/env python +""" pygame.examples.blend_fill + +BLEND_ing colors in different ways with Surface.fill(). + +Keyboard Controls: + +* Press R, G, B to increase the color channel values, +* 1-9 to set the step range for the increment, +* A - ADD, S- SUB, M- MULT, - MIN, + MAX to change the blend modes + +""" +import os +import pygame as pg +from pygame import K_1, K_2, K_3, K_4, K_5, K_6, K_7, K_8, K_9 + + +def usage(): + print("Press R, G, B to increase the color channel values,") + print("1-9 to set the step range for the increment,") + print("A - ADD, S- SUB, M- MULT, - MIN, + MAX") + print(" to change the blend modes") + + +main_dir = os.path.split(os.path.abspath(__file__))[0] +data_dir = os.path.join(main_dir, "data") + + +def main(): + color = [0, 0, 0] + changed = False + blendtype = 0 + step = 5 + + pg.init() + screen = pg.display.set_mode((640, 480), 0, 32) + screen.fill((100, 100, 100)) + + image = pg.image.load(os.path.join(data_dir, "liquid.bmp")).convert() + blendimage = pg.image.load(os.path.join(data_dir, "liquid.bmp")).convert() + screen.blit(image, (10, 10)) + screen.blit(blendimage, (200, 10)) + + pg.display.flip() + pg.key.set_repeat(500, 30) + usage() + + going = True + while going: + for event in pg.event.get(): + if event.type == pg.QUIT: + going = False + + if event.type == pg.KEYDOWN: + usage() + + if event.key == pg.K_ESCAPE: + going = False + + if event.key == pg.K_r: + color[0] += step + if color[0] > 255: + color[0] = 0 + changed = True + + elif event.key == pg.K_g: + color[1] += step + if color[1] > 255: + color[1] = 0 + changed = True + + elif event.key == pg.K_b: + color[2] += step + if color[2] > 255: + color[2] = 0 + changed = True + + elif event.key == pg.K_a: + blendtype = pg.BLEND_ADD + changed = True + elif event.key == pg.K_s: + blendtype = pg.BLEND_SUB + changed = True + elif event.key == pg.K_m: + blendtype = pg.BLEND_MULT + changed = True + elif event.key == pg.K_PLUS: + blendtype = pg.BLEND_MAX + changed = True + elif event.key == pg.K_MINUS: + blendtype = pg.BLEND_MIN + changed = True + + elif event.key in (K_1, K_2, K_3, K_4, K_5, K_6, K_7, K_8, K_9): + step = int(event.unicode) + + if changed: + screen.fill((100, 100, 100)) + screen.blit(image, (10, 10)) + blendimage.blit(image, (0, 0)) + # blendimage.fill (color, (0, 0, 20, 20), blendtype) + blendimage.fill(color, None, blendtype) + screen.blit(blendimage, (200, 10)) + print( + "Color: %s, Pixel (0,0): %s" + % (tuple(color), [blendimage.get_at((0, 0))]) + ) + changed = False + pg.display.flip() + + pg.quit() + + +if __name__ == "__main__": + main() diff --git a/venv/Lib/site-packages/pygame/examples/blit_blends.py b/venv/Lib/site-packages/pygame/examples/blit_blends.py new file mode 100644 index 0000000..8bc8978 --- /dev/null +++ b/venv/Lib/site-packages/pygame/examples/blit_blends.py @@ -0,0 +1,198 @@ +#!/usr/bin/env python +""" pygame.examples.blit_blends + +Blending colors in different ways with different blend modes. + +It also shows some tricks with the surfarray. +Including how to do additive blending. + + +Keyboard Controls +----------------- + +* R, G, B - add a bit of Red, Green, or Blue. +* A - Add blend mode +* S - Subtractive blend mode +* M - Multiply blend mode +* = key BLEND_MAX blend mode. +* - key BLEND_MIN blend mode. +* 1, 2, 3, 4 - use different images. + +""" +import os +import pygame as pg +import time + +main_dir = os.path.split(os.path.abspath(__file__))[0] +data_dir = os.path.join(main_dir, "data") + +try: + import pygame.surfarray + import numpy +except ImportError: + print("no surfarray for you! install numpy") + + +def main(): + pg.init() + pg.mixer.quit() # remove ALSA underflow messages for Debian squeeze + screen = pg.display.set_mode((640, 480)) + + im1 = pg.Surface(screen.get_size()) + # im1= im1.convert() + im1.fill((100, 0, 0)) + + im2 = pg.Surface(screen.get_size()) + im2.fill((0, 50, 0)) + # we make a srcalpha copy of it. + # im3= im2.convert(SRCALPHA) + im3 = im2 + im3.set_alpha(127) + + images = {} + images[pg.K_1] = im2 + images[pg.K_2] = pg.image.load(os.path.join(data_dir, "chimp.png")) + images[pg.K_3] = pg.image.load(os.path.join(data_dir, "alien3.gif")) + images[pg.K_4] = pg.image.load(os.path.join(data_dir, "liquid.bmp")) + img_to_blit = im2.convert() + iaa = img_to_blit.convert_alpha() + + blits = {} + blits[pg.K_a] = pg.BLEND_ADD + blits[pg.K_s] = pg.BLEND_SUB + blits[pg.K_m] = pg.BLEND_MULT + blits[pg.K_EQUALS] = pg.BLEND_MAX + blits[pg.K_MINUS] = pg.BLEND_MIN + + blitsn = {} + blitsn[pg.K_a] = "BLEND_ADD" + blitsn[pg.K_s] = "BLEND_SUB" + blitsn[pg.K_m] = "BLEND_MULT" + blitsn[pg.K_EQUALS] = "BLEND_MAX" + blitsn[pg.K_MINUS] = "BLEND_MIN" + + screen.blit(im1, (0, 0)) + pg.display.flip() + clock = pg.time.Clock() + print("one pixel is:%s:" % [im1.get_at((0, 0))]) + + going = True + while going: + clock.tick(60) + + for event in pg.event.get(): + if event.type == pg.QUIT: + going = False + if event.type == pg.KEYDOWN: + usage() + + if event.type == pg.KEYDOWN and event.key == pg.K_ESCAPE: + going = False + + elif event.type == pg.KEYDOWN and event.key in images.keys(): + img_to_blit = images[event.key] + iaa = img_to_blit.convert_alpha() + + elif event.type == pg.KEYDOWN and event.key in blits.keys(): + t1 = time.time() + # blits is a dict keyed with key -> blit flag. eg BLEND_ADD. + im1.blit(img_to_blit, (0, 0), None, blits[event.key]) + t2 = time.time() + print("one pixel is:%s:" % [im1.get_at((0, 0))]) + print("time to do:%s:" % (t2 - t1)) + + elif event.type == pg.KEYDOWN and event.key in [pg.K_t]: + + for bkey in blits.keys(): + t1 = time.time() + + for x in range(300): + im1.blit(img_to_blit, (0, 0), None, blits[bkey]) + + t2 = time.time() + + # show which key we're doing... + onedoing = blitsn[bkey] + print("time to do :%s: is :%s:" % (onedoing, t2 - t1)) + + elif event.type == pg.KEYDOWN and event.key in [pg.K_o]: + t1 = time.time() + # blits is a dict keyed with key -> blit flag. eg BLEND_ADD. + im1.blit(iaa, (0, 0)) + t2 = time.time() + print("one pixel is:%s:" % [im1.get_at((0, 0))]) + print("time to do:%s:" % (t2 - t1)) + + elif event.type == pg.KEYDOWN and event.key == pg.K_SPACE: + # this additive blend without clamp two surfaces. + # im1.set_alpha(127) + # im1.blit(im1, (0,0)) + # im1.set_alpha(255) + t1 = time.time() + + im1p = pygame.surfarray.pixels2d(im1) + im2p = pygame.surfarray.pixels2d(im2) + im1p += im2p + del im1p + del im2p + t2 = time.time() + print("one pixel is:%s:" % [im1.get_at((0, 0))]) + print("time to do:%s:" % (t2 - t1)) + + elif event.type == pg.KEYDOWN and event.key in [pg.K_z]: + t1 = time.time() + im1p = pygame.surfarray.pixels3d(im1) + im2p = pygame.surfarray.pixels3d(im2) + im1p16 = im1p.astype(numpy.uint16) + im2p16 = im1p.astype(numpy.uint16) + im1p16 += im2p16 + im1p16 = numpy.minimum(im1p16, 255) + pygame.surfarray.blit_array(im1, im1p16) + + del im1p + del im2p + t2 = time.time() + print("one pixel is:%s:" % [im1.get_at((0, 0))]) + print("time to do:%s:" % (t2 - t1)) + + elif event.type == pg.KEYDOWN and event.key in [pg.K_r, pg.K_g, pg.K_b]: + # this adds one to each pixel. + colmap = {} + colmap[pg.K_r] = 0x10000 + colmap[pg.K_g] = 0x00100 + colmap[pg.K_b] = 0x00001 + im1p = pygame.surfarray.pixels2d(im1) + im1p += colmap[event.key] + del im1p + print("one pixel is:%s:" % [im1.get_at((0, 0))]) + + elif event.type == pg.KEYDOWN and event.key == pg.K_p: + print("one pixel is:%s:" % [im1.get_at((0, 0))]) + + elif event.type == pg.KEYDOWN and event.key == pg.K_f: + # this additive blend without clamp two surfaces. + + t1 = time.time() + im1.set_alpha(127) + im1.blit(im2, (0, 0)) + im1.set_alpha(255) + + t2 = time.time() + print("one pixel is:%s:" % [im1.get_at((0, 0))]) + print("time to do:%s:" % (t2 - t1)) + + screen.blit(im1, (0, 0)) + pg.display.flip() + + pg.quit() + + +def usage(): + print("press keys 1-5 to change image to blit.") + print("A - ADD, S- SUB, M- MULT, - MIN, + MAX") + print("T - timing test for special blend modes.") + + +if __name__ == "__main__": + usage() + main() diff --git a/venv/Lib/site-packages/pygame/examples/camera.py b/venv/Lib/site-packages/pygame/examples/camera.py new file mode 100644 index 0000000..34fc46e --- /dev/null +++ b/venv/Lib/site-packages/pygame/examples/camera.py @@ -0,0 +1,105 @@ +#!/usr/bin/env python +""" pygame.examples.camera + +Basic image capturing and display using pygame.camera + +Keyboard controls +----------------- + +- 0, start camera 0. +- 1, start camera 1. +- 9, start camera 9. +- 10, start camera... wait a minute! There's not 10 key! +""" +import pygame as pg +import pygame.camera + + +class VideoCapturePlayer(object): + + size = (640, 480) + + def __init__(self, **argd): + self.__dict__.update(**argd) + super(VideoCapturePlayer, self).__init__(**argd) + + # create a display surface. standard pygame stuff + self.display = pg.display.set_mode(self.size) + self.init_cams(0) + + def init_cams(self, which_cam_idx): + + # gets a list of available cameras. + self.clist = pygame.camera.list_cameras() + print(self.clist) + + if not self.clist: + raise ValueError("Sorry, no cameras detected.") + + try: + cam_id = self.clist[which_cam_idx] + except IndexError: + cam_id = self.clist[0] + + # creates the camera of the specified size and in RGB colorspace + self.camera = pygame.camera.Camera(cam_id, self.size, "RGB") + + # starts the camera + self.camera.start() + + self.clock = pg.time.Clock() + + # create a surface to capture to. for performance purposes, you want the + # bit depth to be the same as that of the display surface. + self.snapshot = pg.surface.Surface(self.size, 0, self.display) + + def get_and_flip(self): + # if you don't want to tie the framerate to the camera, you can check and + # see if the camera has an image ready. note that while this works + # on most cameras, some will never return true. + + self.snapshot = self.camera.get_image(self.display) + + # if 0 and self.camera.query_image(): + # # capture an image + + # self.snapshot = self.camera.get_image(self.snapshot) + + # if 0: + # self.snapshot = self.camera.get_image(self.snapshot) + # # self.snapshot = self.camera.get_image() + + # # blit it to the display surface. simple! + # self.display.blit(self.snapshot, (0, 0)) + # else: + + # self.snapshot = self.camera.get_image(self.display) + # # self.display.blit(self.snapshot, (0,0)) + + pg.display.flip() + + def main(self): + going = True + while going: + events = pg.event.get() + for e in events: + if e.type == pg.QUIT or (e.type == pg.KEYDOWN and e.key == pg.K_ESCAPE): + going = False + if e.type == pg.KEYDOWN: + if e.key in range(pg.K_0, pg.K_0 + 10): + self.init_cams(e.key - pg.K_0) + + self.get_and_flip() + self.clock.tick() + pygame.display.set_caption(f"CAMERA! ({self.clock.get_fps():.2f} FPS)") + + +def main(): + pg.init() + pygame.camera.init() + VideoCapturePlayer().main() + pg.quit() + + +if __name__ == "__main__": + main() diff --git a/venv/Lib/site-packages/pygame/examples/chimp.py b/venv/Lib/site-packages/pygame/examples/chimp.py new file mode 100644 index 0000000..4612be5 --- /dev/null +++ b/venv/Lib/site-packages/pygame/examples/chimp.py @@ -0,0 +1,203 @@ +#!/usr/bin/env python +""" pygame.examples.chimp + +This simple example is used for the line-by-line tutorial +that comes with pygame. It is based on a 'popular' web banner. +Note there are comments here, but for the full explanation, +follow along in the tutorial. +""" + + +# Import Modules +import os +import pygame as pg + +if not pg.font: + print("Warning, fonts disabled") +if not pg.mixer: + print("Warning, sound disabled") + +main_dir = os.path.split(os.path.abspath(__file__))[0] +data_dir = os.path.join(main_dir, "data") + + +# functions to create our resources +def load_image(name, colorkey=None, scale=1): + fullname = os.path.join(data_dir, name) + image = pg.image.load(fullname) + image = image.convert() + + size = image.get_size() + size = (size[0] * scale, size[1] * scale) + image = pg.transform.scale(image, size) + + if colorkey is not None: + if colorkey == -1: + colorkey = image.get_at((0, 0)) + image.set_colorkey(colorkey, pg.RLEACCEL) + return image, image.get_rect() + + +def load_sound(name): + class NoneSound: + def play(self): + pass + + if not pg.mixer or not pg.mixer.get_init(): + return NoneSound() + + fullname = os.path.join(data_dir, name) + sound = pg.mixer.Sound(fullname) + + return sound + + +# classes for our game objects +class Fist(pg.sprite.Sprite): + """moves a clenched fist on the screen, following the mouse""" + + def __init__(self): + pg.sprite.Sprite.__init__(self) # call Sprite initializer + self.image, self.rect = load_image("fist.png", -1) + self.fist_offset = (-235, -80) + self.punching = False + + def update(self): + """move the fist based on the mouse position""" + pos = pg.mouse.get_pos() + self.rect.topleft = pos + self.rect.move_ip(self.fist_offset) + if self.punching: + self.rect.move_ip(15, 25) + + def punch(self, target): + """returns true if the fist collides with the target""" + if not self.punching: + self.punching = True + hitbox = self.rect.inflate(-5, -5) + return hitbox.colliderect(target.rect) + + def unpunch(self): + """called to pull the fist back""" + self.punching = False + + +class Chimp(pg.sprite.Sprite): + """moves a monkey critter across the screen. it can spin the + monkey when it is punched.""" + + def __init__(self): + pg.sprite.Sprite.__init__(self) # call Sprite intializer + self.image, self.rect = load_image("chimp.png", -1, 4) + screen = pg.display.get_surface() + self.area = screen.get_rect() + self.rect.topleft = 10, 90 + self.move = 18 + self.dizzy = False + + def update(self): + """walk or spin, depending on the monkeys state""" + if self.dizzy: + self._spin() + else: + self._walk() + + def _walk(self): + """move the monkey across the screen, and turn at the ends""" + newpos = self.rect.move((self.move, 0)) + if not self.area.contains(newpos): + if self.rect.left < self.area.left or self.rect.right > self.area.right: + self.move = -self.move + newpos = self.rect.move((self.move, 0)) + self.image = pg.transform.flip(self.image, True, False) + self.rect = newpos + + def _spin(self): + """spin the monkey image""" + center = self.rect.center + self.dizzy = self.dizzy + 12 + if self.dizzy >= 360: + self.dizzy = False + self.image = self.original + else: + rotate = pg.transform.rotate + self.image = rotate(self.original, self.dizzy) + self.rect = self.image.get_rect(center=center) + + def punched(self): + """this will cause the monkey to start spinning""" + if not self.dizzy: + self.dizzy = True + self.original = self.image + + +def main(): + """this function is called when the program starts. + it initializes everything it needs, then runs in + a loop until the function returns.""" + # Initialize Everything + pg.init() + screen = pg.display.set_mode((1280, 480), pg.SCALED) + pg.display.set_caption("Monkey Fever") + pg.mouse.set_visible(False) + + # Create The Backgound + background = pg.Surface(screen.get_size()) + background = background.convert() + background.fill((170, 238, 187)) + + # Put Text On The Background, Centered + if pg.font: + font = pg.font.Font(None, 64) + text = font.render("Pummel The Chimp, And Win $$$", True, (10, 10, 10)) + textpos = text.get_rect(centerx=background.get_width() / 2, y=10) + background.blit(text, textpos) + + # Display The Background + screen.blit(background, (0, 0)) + pg.display.flip() + + # Prepare Game Objects + whiff_sound = load_sound("whiff.wav") + punch_sound = load_sound("punch.wav") + chimp = Chimp() + fist = Fist() + allsprites = pg.sprite.RenderPlain((chimp, fist)) + clock = pg.time.Clock() + + # Main Loop + going = True + while going: + clock.tick(60) + + # Handle Input Events + for event in pg.event.get(): + if event.type == pg.QUIT: + going = False + elif event.type == pg.KEYDOWN and event.key == pg.K_ESCAPE: + going = False + elif event.type == pg.MOUSEBUTTONDOWN: + if fist.punch(chimp): + punch_sound.play() # punch + chimp.punched() + else: + whiff_sound.play() # miss + elif event.type == pg.MOUSEBUTTONUP: + fist.unpunch() + + allsprites.update() + + # Draw Everything + screen.blit(background, (0, 0)) + allsprites.draw(screen) + pg.display.flip() + + pg.quit() + + +# Game Over + + +# this calls the 'main' function when this script is executed +if __name__ == "__main__": + main() diff --git a/venv/Lib/site-packages/pygame/examples/cursors.py b/venv/Lib/site-packages/pygame/examples/cursors.py new file mode 100644 index 0000000..09e5d1f --- /dev/null +++ b/venv/Lib/site-packages/pygame/examples/cursors.py @@ -0,0 +1,105 @@ +#!/usr/bin/env python +""" pygame.examples.cursors + +Click a mouse button (if you have one!) and the cursor changes. + +""" +import pygame as pg + + +arrow = ( + "xX ", + "X.X ", + "X..X ", + "X...X ", + "X....X ", + "X.....X ", + "X......X ", + "X.......X ", + "X........X ", + "X.........X ", + "X......XXXXX ", + "X...X..X ", + "X..XX..X ", + "X.X XX..X ", + "XX X..X ", + "X X..X ", + " X..X ", + " X..X ", + " X..X ", + " XX ", + " ", + " ", + " ", + " ", +) + + +no = ( + " ", + " ", + " XXXXXX ", + " XX......XX ", + " X..........X ", + " X....XXXX....X ", + " X...XX XX...X ", + " X.....X X...X ", + " X..X...X X..X ", + " X...XX...X X...X ", + " X..X X...X X..X ", + " X..X X...X X..X ", + " X..X X.,.X X..X ", + " X..X X...X X..X ", + " X...X X...XX...X ", + " X..X X...X..X ", + " X...X X.....X ", + " X...XX X...X ", + " X....XXXXX...X ", + " X..........X ", + " XX......XX ", + " XXXXXX ", + " ", + " ", +) + + +def TestCursor(arrow): + hotspot = None + for y, line in enumerate(arrow): + for x, char in enumerate(line): + if char in ["x", ",", "O"]: + hotspot = x, y + break + if hotspot is not None: + break + if hotspot is None: + raise Exception("No hotspot specified for cursor '%s'!" % arrow) + s2 = [] + for line in arrow: + s2.append(line.replace("x", "X").replace(",", ".").replace("O", "o")) + cursor, mask = pg.cursors.compile(s2, "X", ".", "o") + size = len(arrow[0]), len(arrow) + pg.mouse.set_cursor(size, hotspot, cursor, mask) + + +def main(): + pg.init() + pg.font.init() + font = pg.font.Font(None, 24) + bg = pg.display.set_mode((800, 600), 0, 24) + bg.fill((255, 255, 255)) + bg.blit(font.render("Click to advance", 1, (0, 0, 0)), (0, 0)) + pg.display.update() + for cursor in [no, arrow]: + TestCursor(cursor) + going = True + while going: + pg.event.pump() + for e in pg.event.get(): + if e.type == pg.MOUSEBUTTONDOWN: + going = False + pg.quit() + + +if __name__ == "__main__": + main() diff --git a/venv/Lib/site-packages/pygame/examples/data/BGR.png b/venv/Lib/site-packages/pygame/examples/data/BGR.png new file mode 100644 index 0000000000000000000000000000000000000000..f5dba748febfe5458216a36cb19f0b92ef48e493 GIT binary patch literal 244 zcmeAS@N?(olHy`uVBq!ia0vp^Mj*_=1SBWM%0B~AY)RhkE)4%caKYZ?lYt_f1s;*b z3=G`DAk4@xYmNj^kiEpy*OmPV8ygpoK=}UVZ$Kg0%#er@=ltB<)VvZPmw~~#C^fMp zHASI3vm`^o-P1Q9MK6^dC?4VI;usQf`0cfgybT6CE`jWUsU}h1e2!;j9+pynUD>4m zv&-I3^sy85}Sb4q9e02o9~W&i*H literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/examples/data/alien1.gif b/venv/Lib/site-packages/pygame/examples/data/alien1.gif new file mode 100644 index 0000000000000000000000000000000000000000..c4497e08d8b9da563731f96a3545cbc5bbbe5f2c GIT binary patch literal 3826 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 Hv@`iX|5k2y literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/examples/data/alien1.png b/venv/Lib/site-packages/pygame/examples/data/alien1.png new file mode 100644 index 0000000000000000000000000000000000000000..471d6a440621835ca48442f4cfed1b1b581ec74d GIT binary patch literal 3522 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/examples/data/alien2.gif b/venv/Lib/site-packages/pygame/examples/data/alien2.gif new file mode 100644 index 0000000000000000000000000000000000000000..8df05a34e4f880f4897d7d5ad9d0e5036348b78a GIT binary patch literal 3834 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 VqT2pL?HG6OP}pdL8&|&Pe*yNpI^+NV literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/examples/data/alien2.png b/venv/Lib/site-packages/pygame/examples/data/alien2.png new file mode 100644 index 0000000000000000000000000000000000000000..aef5ace8e06ae08393191ee078788e83059f0be3 GIT binary patch literal 3526 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 AqyPW_ literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/examples/data/alien3.gif b/venv/Lib/site-packages/pygame/examples/data/alien3.gif new file mode 100644 index 0000000000000000000000000000000000000000..5305d419431cfa2718a7dcf0f6ed9970cbf6fc9f GIT binary patch literal 3829 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 H0Py-hSIjqc literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/examples/data/alien3.png b/venv/Lib/site-packages/pygame/examples/data/alien3.png new file mode 100644 index 0000000000000000000000000000000000000000..90d0f7ce216b1e7466d7ed5d485ee7a45d15afd6 GIT binary patch literal 3518 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/examples/data/arraydemo.bmp b/venv/Lib/site-packages/pygame/examples/data/arraydemo.bmp new file mode 100644 index 0000000000000000000000000000000000000000..ad96338e7b4e4a853aa2d91b44ca5f90cf5d268e GIT binary patch literal 76854 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 VsVNzd0U3}18IXa048-i8{{aTI3E2Pu literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/examples/data/bomb.gif b/venv/Lib/site-packages/pygame/examples/data/bomb.gif new file mode 100644 index 0000000000000000000000000000000000000000..f885cbb7feabda955f2cea9eaea65d38829ace06 GIT binary patch literal 1170 zcmb`F>rWF00KiW`$B-qEu(@Q@;m`y&M!GQ(L`#ppjzW1qtoQ&G20AvdQ-o!k5~pz# zl}8qo2?(_V3bds!u1~JLyWaId+bhL_JS-b8XST&`31%NQ{U7%G`1|zx@Z)B2QqwA< zfVY8q0NDE?Y#RWq0g1p%Ub!2S`f?Jf!jMWYT1z4)U6vEL#Z17RSX`&w2)u`pCdhZ>x>V+8I9PqZdY;}*kbrf;ZjaQj;r5f4s z{`W^9EfrYP#gGp0^`MNut1N$g>%X%#(bT6zc5*+q*cTR?evOtBLV*q@@hU z3SDRctY(UPGrKzu-D*qu{#rU_E+@?e7Ja@!&J*{fc%6+ic=fbJpqYUB`{=V&*Bteo z7p+2ceCYu5@tk5~RUTaE^0{hlc$r~>)ps`|xMF&`sq)yX^;+(PBIl?31siMjXX}>D z)iIyF(l(W6N7%5EKQ1nQG%H(MM>aR~%fX)cnad8W)P?a;BhRd6PpWw0hb0U1qwBxH z!R5jEz&A7Aa~`t9PVfjM6SeZJ8m>&9J1h|d+#Tyn!)q%8!KHR5n&m_w82tzWRD8~wOjWWJUE%1Aq=6n~a=~L6rTsy|HOwnyq z*(NQ|AS<5rT?$Ya%xX}rpz9P6VXO$a>mBwI7mH8B;(^eU6$=I*>A}9<&)i6U;(j5Y{oY znhbdOh+L8)894Ow1GaXu+MqdZ)fFKswpq>8D?qg>O(kcjrJ(d7I5q$d^)Rf4Is`6< z$N5SbS1V=96-?y_dqTk)8)d2_(7<5Yt9AcB!v6(a+rncjfU6-pBBN5T#9j>%M(v{2 zc&3oh@aR~moADroC44KXg6OXdy%7?2=<*h@awa@F4(g&cgs>yt{P3u1t7aN&1!$*< zZgB8=+dGGwR)_~@Ub`*M|9Wd{+rID_apv`?gwwx1wZ%al@dAtZW|=Uzci+|LaX)k= zlnoavT7nTjCLYr;Rw>M}i&lw>_7>qeRB{b9B(O@_dJfjF5HC`1|zl?}uM()kO_2-q4hwCvT#UrInr~MJ`-C)bY zWW(PPrHKNir?B-S?URnyB;7O1&Lrd3^PMy#JUQ~?ftWKnNw(Nd(I*a?Pn5iNIF$eC nAe8*Z0l%}tbs%td(8YaR?`u1_d?hqHbw$L?O^ezd2BiN75pPd@ literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/examples/data/boom.wav b/venv/Lib/site-packages/pygame/examples/data/boom.wav new file mode 100644 index 0000000000000000000000000000000000000000..f19126a08228734b1ee412c059cfbd70c7b15687 GIT binary patch literal 12562 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 AEdT%j literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/examples/data/car_door.wav b/venv/Lib/site-packages/pygame/examples/data/car_door.wav new file mode 100644 index 0000000000000000000000000000000000000000..60acf9e9fb18537bd18234613f46c3bdc6261b74 GIT binary patch literal 3910 zcmZuzd2kfhnIErRDd)!PBbAh?C|R;50oz~#SYQJNa|i>H5J&g=8VHK^TlN#xY4HTS?06-8i*J)z((U|D?9c?AO9hoT_~4>G!?& z-M{bY^*dg2;J~i$S}awsRql8AiK2hBSS*jg-xC`wtG`DqkHd1a|G%C9seoAa$n-f+YOGScVk)RnZtui8u*}dA8Pd@zh*zf-1-tU$^ zdiTT0!bkUh^WnYwGs{zx6Z4aA-sm~s8|~^$A`!2x-fnf&pWC-<*Y2`?B|8pP?^ySf zmyhgvW$*rjm8Z+!C^>rYqo3}nIwnYAn(|e-{G``~I9w-BQv${)NLavlLX7ofb-Y}!#K|ZUcdCKc>khmmu^f#&PlfzwJl@J-ncMx=YyMf=P%85cci8--G1l(t%d8CR<4cBU6>zQ zn!fj+fBg547v_KQ@x5Q(pYIr$pPZl1H>LzX7N$hh@2#)g{m(z%xcQ|WuWj47p=d*e zb=`B{d;PiRU)U8m z7Jhm6z3ZR-_owgQn7Va!?EQ|#&;K6%-{;V-2M>O4HtjbL{`dOQFO2m4tNHGJWA0bC zZ%^rG_~3Y9YSRfzg*{qXUQ1RyS^v!5`fWda2|4!0fo zU0J++YjJYw?q`4c!UVG1`10Pp z<#o22<40b%mX;#!hLW8-w!V7WdTjl(Uw`6- zJdleSVoM@7($#T(WU9S29_NzLbVoubLkQUdt6EM4m2gzba!80Z+?0vpY0f%Twb1@9GG5u z?`lunFmgRZLt__52Ku`P2l5kLxxT@n;gRm%kt?%(L!%c9lljrY^xX1dK0k5&&YgwX z$-?C1!nLKv!rYrHi}}IxBMVoqUY?j87wVuDQbZvI5E0bwz&g$`0D$LP> z5n)AtSZ*HaiAj_!Mw6KqiQ*!;Y$_U!Hg|UATAOn{O+911t(_gc1LH%vj^6gp!Tz!Q z`DE8%exN^Ea=H>roFo(*J22QsKwHTq-wGjjYMUcrNbeL4l5cT z6T=i14wC_brwJnHbz>AmqYgMqX~OPwy6q_H!-x>=by;n}02U1ReNHFNks(igU7g+O zuB~yQ0Y^(ZUm#kKBwE|^aLoL z!%#1+B^wiht{SqeMv|H4Y$B%1MzXEDqb+MF$;M<;b4PPZOSLyP>Pob|Bd$k{L{mx( zOPr<}*%nEp6_w|C0vGrYNe4-c4C4WWKuxq*6i2xd#+cg=D#M6m*BHPm1l8zg(M7pUdnTV(2aaD;X8dHX$#i9`-6^|&q zz>A_JX_}^pvZCoSF9?z%$)Y9+0>d#ZNL8H=K`VKN!7<1KawbU{N4;J@Nl`c&Vo22O z@%fMdinu+94}rHI@pxSx*vT%RKY*jodYjAR^&*JJ<*++kZZP#aoNkZ99RwKQ-yui< zLVylVg-DhcsSpKC!AUYmP=q;>I1(fQ5&{q+LJUL=qPPh@P17WpuoQ`d4^XCgi3Dte zi~yTDM00#tkQGIiSelb%MG!baltfYF1Q0-zWr62emZcd$6d2ey<|YWUG-Lon7z7O5 z*p}-N(a}Wqp z<7kFs1qn8jBAS^9f}+asfIG7RvKCQgQHD;K4k0%lC7P;5BC4u_%zzyb0}YtO3|-eX*wuy+F-cP)B4~gU=yFs88&Cj2)Z`7r zh=FP>9y8)e`1T|cu^24HxJW{zM2noy9UX*x)t97qfbFo6XnRf57+6E*QMH>n0N04QJrpg$fv(7^*)=m)2x7L$G%y8b=l)8tyqYnT zV743x7N8bW8OWTQ`X=)i0+%Kap}wHi>0iXatgf#vmoh7tnpt6tMiOuE~oQ+>iR!!Oio@ z)tjfq^4zq=a@f3z{vA3}QgLDrtd|@+P+GFDwCu;g?+c&|=61S>qRqv{#YGhXxa}4l evlCPR^A?pL4KIN9Ye&CsYSv*zuLlB{#q$3R0$=6; literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/examples/data/chimp.png b/venv/Lib/site-packages/pygame/examples/data/chimp.png new file mode 100644 index 0000000000000000000000000000000000000000..9bf37b1a0a9ec3b4a79d6b1b2f2c56d3db71d5b6 GIT binary patch literal 826 zcmV-A1I7G_P)Px#1ZP1_K>z@;j|==^1poj54^T{0MgIT*0000S930%-+)z+ZYSagT00009a7bBm z000ib000ib0l1NC?EnA*v`IukR7l62mf3OOAPhjE0}IlCSQ;Qs10nQZ)9S(oj59k+ zK9caPTY%iU0KmO2f+?lr6(?Evf_<{Jx8OtPdkb*kgqsh1xp^#43?(6$ju;;b085JJ zNfCw}_lN~gS%vu;Lcl~CfGC`S6ovT%3O$UxEHRSJfKl}u$5}kF*3L1^oHK`s{EPHM zJfxMk%Dj+$_CL%?*1`mmFNMV)yme0Mfla;16YuI*UISYCa4oWY-;AF@#q-D;b4!5L zFy8^PKxSU3d`~Xsb3>Bn3iLKxxFkr+yYSxD%EQV%cFqopIDM0^00)lJT?zfjsdZ{H zDa(u>6BICC3MOt21li9wN6YB{^24|}5c>Z2zj5ppsT0qgA8wNOY3BIgnwXr2w&MiX znYTOyH6*C>nuo3)IaQt$T+_<4{6l}D)Tf5aJ>{*3s*cs!>BMJl;Mq97@m~Mq)_?3c z3a{P2%f4~h6|SakZh5Z96o0rIPk-P1yYoCX==aJ|`@Qp@!)b$e&X#u^2R`WkDQ-9* z%G=EwalI0h-#&mvT~N=O{wnn>Vam& z3NY|~7C$)0as-<4>-;Mh)p|s>{G-;YZXz3P?Ye(-54goU53Myjo~~auS0PA!`JtOk zu^FJvN+}G+=_0)D=bP&#M>pn>0*KEe6bL`9LHvU|Hp>1350D-rtRtA`;oxd2 zfOW#6o?*A#+X}4z7Y>q?_u?*_UI{P~J7ho9iS&yi1D*ylh07*qoM6N<$ Eg169#x&QzG literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/examples/data/city.png b/venv/Lib/site-packages/pygame/examples/data/city.png new file mode 100644 index 0000000000000000000000000000000000000000..202da5cf1a069cad472feb9833fb81974f09c2bc GIT binary patch literal 143 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaT3?y&uT)!JgF%}28J29*~C-V}>VGHmHaRt)< z|NmclbN*eBbV-n3FoVOh8)-m}mZytj2*>s0ga#%zg|xhcgarEo2M+viXmtF?%-sB! kpRMheea4Uf_CW>=QPVYSQ|}dS1nOe&boFyt=akR{006};i~s-t literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/examples/data/crimson.pnm b/venv/Lib/site-packages/pygame/examples/data/crimson.pnm new file mode 100644 index 0000000..28501e9 --- /dev/null +++ b/venv/Lib/site-packages/pygame/examples/data/crimson.pnm @@ -0,0 +1,5 @@ +P6 +# CREATOR: GIMP PNM Filter Version 1.1 +32 32 +255 +Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü<Ü< \ No newline at end of file diff --git a/venv/Lib/site-packages/pygame/examples/data/danger.gif b/venv/Lib/site-packages/pygame/examples/data/danger.gif new file mode 100644 index 0000000000000000000000000000000000000000..106d69c0fe6a1e450ae00658748b80a436018ac9 GIT binary patch literal 2761 zcmY*Z2|QG58$YvP5RHAEj4ey{-7U8nTgY`KvQ1-6mSn6&(x4<1ifA7USHfUy$8wEi zNu&5e_|PPSL{voFJH9h~-}n2z=l7iF{h$Byf6wzi=e+MZW^Zd|?uUfg0viC=$h#ML zcOXM|WHJM?Nk&=!s-U>Hf|R?4w40&q$zSE1k71l#4mc994nc}`BxTzK73*xZqlM}g zC7Oq;4w*M;n_gA5?9?%SrDr&zug@~n`DCQEW~|9ERfj5={`Q1vGzj@0Fy9UE$z|f2 zHOz4XY=i(eD>Y>e$AYsI0Dv)#NRUIa0sz>cOFP zAm0U0`?#fd%@i#S0PsBxv^;Qj7-SQ0+T7A0`-rLBHdnV_?4kLTELf^$lHSqN{)G=p=2R(L0CeM^9MqXD0)QbjHq|8~+-t<3HpBoR5$3L@8~|a+z`0eOi_YNO5(L0GXHoM8 zaK3PxBfi%NIFHsv`GWKNAOOx?ULQy<{+00J=zF!hcy^|-f?gY#NY6<|FSVc-mH28b~=BSXDw#~)fqK}1HW7D#MkqiAy?OxPo&^BK0VGiJb~TjFRFs$|p|7T> z>pEK5;h|k^ad)P)Vd!LEZAou7)+$5ZzK;6xj{3<8!ppkSR|R?j{SWQwWdje)q8BG$ z(*Jn#1eYp+ai}jJD*06=*rUJx>Dw~2EcQ{t_s+M^WaT}m=;CMZXue%(V-&pR2wlf8 zU80rYf4zb9E{;rY)amDm>>$?kVQD@!^3r1%Etlu-(Lowf7Kxiy{?Bua|6Kp)hnc{h zE0|-`iM1;}{E7Mj)l9JdMR)vBg0=S63i53YhIq@nGb*g-fd6Nwg>f1yqdj7$v{kNT z1ZCyfH9)FOA@wvUnq2f<*I2*(mKGL>JKfsJCu+nww>j8Q^?E7$Y?mr=sOx)|oTLuL z+3!fAKnEsne@9GL+Jb-YjS>>p3UBWFOVQKAr@(#a#oZ0zKr;9p>3 z9sQb<;|0t}uy|rfDUL*92c1By7&qp4J@>@T;M3SV6L47ys(@G6p7NNKjd{Vik#rfD zwG?esAA}n%8s|iXX?x~IUx{ZuAqkkH1NclO#Z?J{W`lvmCBR-J6b~0M^8Wu)YdQ`~Fs_=P9=<2De7g_@=x= z64QS@TMFN)mLNr6zwC%kO^PH8dV8IsBqOIRaPOao*=P+`t`*B^cc*(g>f-l@B`6ON zwU3JoT~fLlMLbADbr$jZF~)8#wK!ss9s!0k8@}qRo8yLx!Lo~14abM#j zs&5ntzeExa*kPp+E<0!F9Psq%oT`*7u)bL0aGKWW1CdAAflM8otn@E8mAs8VEttB2W7sK)#X4ikXxadK^<(auC_cLyn^)$Gc^YM686X z{b2ay9l~uz)i-U=vV0|D0txal+v|Q(I9wzA+=cua>&l&LCio&+Z#l2^mDT$n!lr`H zdC-K6+I$L>Eb8#lw9;>1{VjTw-zkV!l9%R-#qfiCcgySp6XHD|;#)3grmh7?-511v zMHYiUf4*{t`(Z&dc0qUSd2MP6FcjCs=ra0Uk=9DI20V0o+N%!<5KbVyzqd}rGEX4z zEHBqW%Vd_W7AMH_B*B1UiOF!hhImOteKQsj>S14kzx2M1?0Npr@(8ooEhf(Bdd^m| zgJ0x{0l4$^n)5POuZ38mU>*KFH>4xA_2v7J(gCGB%o<}cR~(OET@Nj1L09I^6kpQE z7d7X|&LsW!mI4}gk0?hW#yRokBOTZ*Mf zLD3?cyQK`~VOc+_$DbQr%>>P0zqU!lc~j$*%Kcg)E=o(hx9>scFyE(>A>`c!gB?JU z9naYzPT7kDCaI~BBTYu8zvo#?mW*V)*K8`ORRhoAuUfS+&P>vmHQH~`yFtQL zz|BLm?gwe7nFkgZGf}Rzby(HGp-U=tZb6%yQn~(Lu`a`ThBmR<`4;?T0wH8DC?U6z z_zD4+|K$Fcp{tY0>K`HvQ_fxgc#}+ghK-J$w=8!U&NRA3GzpcMOp$3$$ud@qOXR%y zfm_skVBQ$MuM_&mXyy*~H{L{o;SUHCLyv{5>lATerdT$z1k@)JU(tE0A7EQQUcFB%Fy?2wjJY&qk|Cy?g*@s}4~E8Xd7HgwouuGV%3O|tDEB8MIgkV#OZSz%^y0EZ#kZH+{qLsxzilI%Je9x5-a3mG5wpC<%Tkxcm+S z@3g?)*Lq*|OD?(0R0o?|6@PtScI>y?P91z1RHyZ0{fiZ^E4D`DKSXB{gg$%uAPc(M z=~WlB2L@W)-?a%h-cQ67=n8I+?f(?;`;@xIlRtvV7jq bDM%{xORmok;7h{xL&$P#fw+yY{8#ei0AweK~AMS_3> zxB=S66%Hw7=S_Bz%1DbDeYUbFSyVbME`O&$B2pA}Ba1 z5l9670seo`|C{vxfSx$fw0(AdZHKAxTX1NLSu9MdcTt2`)b!XXW_>=5o2Ga_sMy8 z;%E1y<2@PDPtn+ySnsj4Nq=wl?o~wHi`(6^HRkTN&F1LXvA7+d(qq2t*!lZ^)Z<@e zKaI`qOHz+3)Z?ji6NCTOENJ@0yZP9nCe6Oz>XtPBy1Ur`HXCL%jQ~v+PV?B5=690c zhl3lxcs5yrn+*$p>rZPoM>l^-?$8YSnBQmx$1MfKw&7})_pm)NB8aL!njWbJ3d{G{c>eT$1R|}-L_+h)7fu7&1YUYfX?aZSb^J@pQnPV~A8Q;wq9hp07_82t>nP0h^M+41fiP;i#t2?&$ z&W_GE5$&&*cbLQ5EGzFlj~g&5hAiO&=2dq-r;Xi>`FvOPl8t`x-*qGA@K@%9@zDtL z=t{FC+-y$xV>ET-kMCYtQb)%2nnzPDFZWu^-`}!|(4}8^=eQ$H%*lsQc;)x|)A6AIcu9EBL3m=5b@&c;k(po&rOkuIE!x z&%YN(I&)sOAOB-0YvjQ(OGmD`y}~k>V;(&A*--uY%b}OAFa9yw@XAs-I(E(cy3#V* zXf{`lnd>?RZ#=u%-LJntc>C?$e{S@Qo8CNqVCiiAJlHb&bo|q&wm0J@i^UQcM0X#Q zh8^jjST{IoC&u^}lU93{rs?qso{t0L|APsf*iD4Z5Um`EjMlzFQZ1zMI9AEuVchYK1wX?6@9f+2@ykET7rVcYgMrhtR1w zq*NS|SgR=x*<`e8`Ec$|d4TWW<$Uh6*s_`FZ`*uDsf!;qtV&jXo3%TC_1m!G;4yQW4uvA8Qx*uP9!QZ{tzma;b63iG_U>v^I5up%cv;P%CxQ9(7$ z!~Dr5DSt&vm_Lgv#LK|T9aBpS#RohZV_Z7iQ=^j?om0Ou=DL)#eT9xC$3tGamJIo# zUiJGoMl~MM#V?+BeHnMLM0y&ujx%-j-p(vX)Y)Qs8yIGB*@^h^Vwm~9U2KWK_~Pu6 z+~=5mU^mc3W*{}N_*&jy`QrTMmK3iX|9iyZJl*@eX-s`_o}*&!aIWLQ`J!yGcK6aC z$9$W$C9Vne#jhQAM#s1JIZXL*%iHs;9-?+`Q+J+zu*teeoD&q9=cuE(QQl?x){TP; zqg%IWizs76t4a>u_PQFKasMTK!hOIO|}ZKwllUDk0WB>ZvJO;0a9 zKq&7>O7g;7y^3=?Y{IRJk+8Q9DO5!nZ7nBXWmDOVe}K#-sm%VyQC>fZJMWJ9KC8?ZPNd?<2H&s!W6iX74} z6T5Iw`6ke|`d?_)e|iJO|8lHo3UcT9<_01lu2rZblTg{K%y?5~n7E3plAdLu zBm?LyvCR%_PPV!vzvXx&qI9J!dTBwF=h3HU(6jPntqXEva;%E$X`snJ4rWvNQq3HD z%&#ON+u6Sc6`oMy5=Dy>b&9(v0X{$74Ce~=mvA$2)`5jkJHnX{r`zgqq2JPjl{F!S)FrU13+eSsK--`(HXeT+mAdrde zZgmiL$rc1D$wlI1;-h2hv~D|WlRVU~5#LT5u1$70BzJml#SP|r^SVef{u-sYeALOs1C8yzDeO6IKWjxx z_S9~z^%`BK;B*Ujmd&qe>Vy_#lM=ES1NaIRXrH1|TPduq$lJ*d&5dp~!Z644QZQU~ zicsabI2AKlVyT`c3PM!j#o39ERSnW+CH|%pp0Nuhwr7X(T$#{_i>K5QmJ+ziLwrv# zIo8oFBI&GKcf{$u*+?q_oYBmx%EYJZldX>`v!D;fhaSr`);aT@<4TfyGi9NZF)w2G zd=(^RPdh~Cfqu&v_0YAe_G^(W>Z1Yi(zS@zTzF$SdcH=d*$X-GQx z36hUlK=>jnUedXUpJ6DF?BYPuf5;2&3P;$f7v=|DW(DBgToE%>0!IjHgT%v$QbJC1CEh${t zGrbJ<*UnwwCF45TJMkm5nKrzZwxqqG*2B*5rp{s9R@!2_SEim6#(`syg|k|9Y7Yt6 zUXqaGD%qm>A%DZO?upIsBJK}F3wM`UZwjtH)xXx zK5#ga%T0o!=GO36%bz=3f7KSerADwOY^1i)bB)+^J}0KWWk|w=;+I)4GH!{$Jug&H zZqA$*cFN|-UKonks@**ql%_-7$E2FCww<0_T?Nl_I-LnmO0lU|g-Z_i66c8!6_l+vAyAMAG3L~6c>CUk|j7TRp0EOz~rDzcpWW}>Sef(ghR!W`Kxz5N3DZe z9Hv=9j&1HvdWY=}3sSr%mR@vqaeM`E?>mpKpZ{EVyFSO~$6iRdP01UzFYr7&+xIK& zek{5URM6m7TCheMZpZAB=YS6xD>n*SujkqV+=iW~ibN_**daY!CgVM1xdxT60uV+k z2~i6tB|}hW5I!S?byB>-gb(Y48!vN?0m5n%QLV>T48vnEcO@fmq2L897*BFiK+uuq zBDs@TT^=8F;Q*$l^wU-eK-e3^#~^iB>c-b$cEO6_U$n zil3^0!fY1~YG?Hu1gwc*=2+!0Sd;;+W<-@LqKD=kR((^g%L-+Y3`Ve30WM)7i3*x( z;&xRExR(J(mh(vmbedEW0G_B=8kXazesSOrR2oX;93X%)lBqe)KSsM`BSl-mk>o(!?!NbRc^-_+C&! z6Au+W^)mbliyP_LhfHwPb1(aP)K3dZNKU*I)D%yYu1QM|Pf9p4Y3u{$r!Q@I&Of5} zF47`DE}MCmOQ-_ylPc^9P$U!;ilk(P66@FH>j3K{N_b3#HrY9B&?-x`Tu*XRs0Vii zfG5j{PbR>Q$#s;bFP9r{c!I6z5?bm6Q0f~vJ85*l1Va*Y-(W|XCT96dT!#kr*tCXGy|4!c)?KQ+lF?gsYTzDZnp}M~;<-E0WO-Byvz%vIc-> z7y$iiaH5+?y3ctY~Q})BG zK&MBCX&z16K^wM*1Jx5By8usW60RBM*`j8x7HaUysA14v4 z{cHd8&=uPKkxF<3pJ?aqCMD8LmkQB7ok?Ic2rrogHXQt-9_=%sS4rEw zXZS^7yvDzj^6@IE~@XAi2(lZSxd_zY2_gIIWr{29$1U7T(XI zZVp(bR$yShf1^VNMM9e;%1T`t5s!U+W^P+acmu~%(I?XwCMXU6ZXoR4){6mnI)Egq zAb)@}lLSNl=C5S}TpK1=O9`W%=d(1m9w6>eyJO3W&(XNtnO|nWcIh(X^b1S1{7Glf zL?H7=2lzJ$H&6w}ZGmQ-hZ+I=8VN^7fN>1y5E@mY=kGgeab~n0=MBUVHM@04IN&U( z_7%NrolrFvwR8JEcJi85{&9Vvie0x#4+iVOE_?106)0hCl1V6rL52*(0u?yR03?{8 z-~)58kMN@v=oT$e3lP7kgbkYoA1aAUe9Y!O{y>C!+x~p~p14tjR_OU9QrL@Ll1JD4 z=jOKFmE4KnmeUu(PYe>vfXk;qOBiTX8+<_-mByf23a!$imMw&aIXo?Zs9*&KQq(WQ zADYm&G6K7XJa$1=oh7QZf`erIVHY?FxG+^QKUoLeEsZWAeOLzcYT!CEP`r*CZxGfo zyd7G!K*kIE7G9=9A6r0T58!c2fmJfd1s(cGK1J9I4KN<30HOCrbhnfjrb0^e4s|4w z#_}_0o|p#bsz7%`bRq?}81dz2i5e}w-UR0V1Fcnp{Up~w+ZL$j6aZ*nLtT&7HA+`_ zZUxc93Lfay!gPK=DSUL3DA&(X^wkxySidsZb1OgbC|9Y4*3sOhQn2k*Rw+Q_(6|SK zRJ`VS=)l$vJcq?s$qLgbEQgDXLAJB|1SgHyQ&McV&B&OON)pNeT3Y~}mmrJ39*?eLnQbwT_e`8yuFk`}o zP551FVt_5aN8%@x*hx~<9g1BtbzU^#-%HW*P=BdzwGkjHq`dbhqWk^4(zLLo1#u3= z>lOG-6SPF-azzh)s&cd+wjlq$pTGJvTJ~?oLlyDBgjcDEE6ST94pMm!H=5A%D!iDD zZ)gFRsz6Qi9uFr;xfH%6KzkShn~6qK@KqCUi59%1=RJ}g%F)G{c|4sCi(+Dob(l^y z{ke%S7>G)PP{)#{;`C!nd5M>iauc>t1sAak7?arduqN9TZTN&cWCd0-Shp9NMZ>fS zXmi{=Zws$NK{Qfm>2v8f%VJ7MY(*`4jhLLJCon|DhSpx8b}} zEi%bjuYm%^ABk~M=G=T4Nh94`4D*bft z!xdEw@v9yW{soR(8kM4jGF8Z!-)V=gvqc+TT42oYled z%);X|^w+&ZA3u>7o;$z1C-z*sqSQ3alC6*RCa6aS!KOa+rwy~Nlf>;K=tF>iHjKx9 zh5kp2_FQnR9O+e@PA{`rUakhtO9^4-oFaPK3q{n>5l8PF{2YZ3v(T>wV&^gTsbQdA zM{M1W>02P^Rb!j)2ZkT2?ZK!54ubZ$4o?F8bIDz~6as#?dwrqRQC?4XOWe~oT z3f9!Ry(`}7ahm9g#O3-4chsDDe{M02_o?s&WaL{GYYVae#aO!)Kzu)AicsvMGx|M) z)SgTzS3OFU{#nAH<$n0mKgkp!`bs8vMS!aZGBN`35Eq(X*57h~pFOunDhY{C|QLU)bP#P|Cj`gTJj6B2q^pDIN=ecbp>Y z^wZa0M+a0PQ$?>ndr;T34$oMk)~dXZ#!u=n4dZmwwJB^N|9DYkDh<&e;4})^rB|fU z5CbB3O?sLZ%AjG~c&%Q?b4Vxj?8O=xeu^FFH4%Tf<3^p8Pia;p+k4P3|1ypz>EnJl zY3%tgtfFnK*3Zq zC+thDY|3>Nb{@co^_Z6tKc3}VV!T_%A{G7oB0Uo9kFKynOD)NTQ7)v54|Sgs{wnqH z?VXjr`^zZ>c0qv~Dfn{%-fQx^L<(z7L=)|OwH7U-*!@!eAq8@b?R$DgsiD!{ap4+G zj~pO}TYb@E@`}q_qXvxX{yz@~Nvh;V^?C1Q^=r>xLBHfK)`~+)!rY5rywZr}CH^tx zyw?gU;?UDOXII@Di8&EmowRk&mLC5#{hQoo|NZtzz}ZI`vwqWTw5GfYCU3Ojg}opn z6))tM+wQ*^T&3H+<;+HGve(Kw)n@BGZ;t<5z0R$r>#XOU^D!l+>m?~|#qNjGp=XB! z@P6;r(b>lM$~$(yrq^9*!2*L)Z6ix{hg*KJGB|~#WQ-}7Jn#Il`TozpO?!Ce)sZJ< zuXF2{tbKHCV`Pd`VR75}6T!QW6+L!e=TzzL<*kvsxc~PF>D+!UuKMT5B3EZ^)sDag n@=_O<{q=|Hyd#B_>|keg>a(ZjegD3H*;Bdx*@90r0L=S;t8kRt literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/examples/data/fist.png b/venv/Lib/site-packages/pygame/examples/data/fist.png new file mode 100644 index 0000000000000000000000000000000000000000..9097629fbe53b9f6bdc518ba1416442a0cb77396 GIT binary patch literal 86196 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 LGM9Il@po?FOYFDmUP?)m;dto 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
GF%EEepky>Z6Jj~4YA^!XKNF4mw28j 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 D5JZXT literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/examples/data/house_lo.ogg b/venv/Lib/site-packages/pygame/examples/data/house_lo.ogg new file mode 100644 index 0000000000000000000000000000000000000000..e050848e3fa587ca0b5b61cab6edafc1e285c0fb GIT binary patch literal 31334 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/examples/data/house_lo.wav b/venv/Lib/site-packages/pygame/examples/data/house_lo.wav new file mode 100644 index 0000000000000000000000000000000000000000..68a96b869380fd9da83e28da23c847bd03ff414e GIT binary patch literal 78464 zcmXWD*Owe;dgj?WXD{}4_ng_C)sZxkrq$hQb&DPZ3GY!rp-=$I+ssPuZA3> z`)klokPJ-{j3BZc$3>%2D$0u-Ckm1zin6T6gqW(O)2Z2JJuT1-8FZN}R-0jZY;1UN zWO8C;Y{un}#`IKaetqZQ@yB0%^WE?M`1|jE_lMv7^0SwZ_EzTW`Gmq!A)nJUF*Y$Z zIXN*kWAg+_MpSd4tbvrj*M^#cFj*81w=Y%Pl<6UhX)78j~*WGA3QkP-`U>U+*n(jpKaGG#at?t zN+=RT_*^dA^vKXa|Bc?8S1(?=a`p0si|5W=xP1A-xeM2B;8Wl19~>STGg@7~5Jhvb zL@J#xl}eT7TxV%zV{32k{=vcC{==tF9z1yZ?9uVj(c$jS&gSyM!eXaguhpydS~VS4 zHJK&DA+N(>H{ym2-@S41+=r(=c=wH;|NO1D-+A|~H{Ut&!KqWH&tL7i(bv~MI6iGO z&dkhMtahizAB?bqASV*ZLcP^&&aZ5&Z*1@1KX`b2bo}Vi(`QegzIgS~>rY-jefkVf z@aXvd_V)J1>eAx!LbF=PW-m>A7(okK@#dlOLRX z@4ffm$J?JebLRBfi&w8)x_q;*x3_O#aBy^LVtjhW=5)D(5t`THsvOT13;9ZGc7ADX zeQjg^aBpXKcmMG4@Zj+1(c>o%kB*KWK6&!E`{UX3Cl4Pzd4&7EzP!9N+o+Wa`CK}Y z&=pYz1M&1M(>SlSFT;}xzTgw(xq!XS1(<zg&p!I()w5^MpW*&JK0J7Eytlr*xY(Jk zm2$a!HX(}w%kgZKA_z(9ZRt-c%AuJv3wfBy32i|0R*2)>c<=`@8#P zV{>bJXLDs~Wo-!yu32w3ib+jVVqBCY!dP%lJC=|e%MS1CaoX%|{A8M*7{^r%+`H4? z-*@xo?K`(`-M-u3cl+MGJ6IXrubvy&ueWb^KmRyFjnU?C;)M`O+<{OaKt!V?8HrHQ zNH`oOND@CG)QM6|%Ph2$#rayUwNcY&7n1Q>U5l3s@j|_rtF>y4`Od=1>e}k^GCut3 z`r0y<^2+Mw*2eDM_SWt$Ldo{}=Faxo>e|xW?A&avn9pU>*rS5L(+EeQ2!(qV4tIZv zP&6G0c-*XP9Wq<*-k7xY^%^E`-WngfaqZ6CzMFlwuU)=*>*}Sxfu5^(26}tPrbj0% z))}ie81Vc2VJbpKy7!0Z{vZilli%m_`@9|maT1Z67Gg13RW&^skHr*Kk!8eiN#c2J zuF8qUydYNV@nl|Oq->gJ;)R5iENApWqgq>7nQO1^talc-_czyeb~o2|_qR8;HdmI{ zmRgNgyHP0@bA?K!l+P6k`9i5!D3nUsxT450fu+JhzaLM`=?nN=Zo3VE$xe&5QJZ(F zf7ERm9UK|BeS2iI|JKCJP`|-7b!W`sGR-)hMx)DPvj+)0oq)^X3Hse0JR_RrIZ=rx z(&=mt@08V(nY13)RXip&ro@veY%H$H@nk~NG*wm*Z>Dq0^`$dNgXyX1!8v z&S5bwZ*9&uJInKRTynWs#AU_fiSAY5h9deP@WkWz7+5ngQQ&BXWf_JJhoVuRJrpA* zN3AZ?=yZg$4~)9Qwh2pwFpZnsZkxs7^_Zs3Zsay!n50;Sm15n6Ch>wC!)NC?AtuKp z8JC8&h&!21XEM2BsZ_?oK_Jc}zNd9roi8NhU~1w;@NrqKcDv1q|8RNz z0R+AX&G9_043CJD5N2aaOp4)}MFv|k7(}WHkx>Q#1v^i}>P#f@S@HZdMT}BnT$PkG z0<@Y+C%XGnq$9K-aC~=n%9i=wce;zYt_bVEKsg11YSkXxro3*irPBvFv?X=7Q%lA+5CtBF*?!53IL zr7*roE|e2OYC3G3r`m}~Fp;#+6jVFI@La-U_eq2gH_Y$N6O@=yvP>{3 z1eu_}7$OvwP~vJl5zq45F|9eD5tMvZ%O&GXnh$3gC5~!HTT7O#dA${hmN}Jj@o5{8 z36(Q^IDpkfsLO43p_Hzv((Gn#b*ZpOXWFS|E7eYx6XkHy%+|tbHj*xd>zbTrl5sxC z(<&E^M~Rpi3`?9q6aF|YOQa_jS1ew2-07VT2qu{b_(UITCKY2aZe&6ud>~}w9f6q6 zIU{aFaCg+?o1{YlYji3=Sv^il^M}NIPW0tOv7J{}s=2x3N-EaLR;uMtrmQJSv7N3} z^{S}S8LvteM3Jas?WAQ@Sz1j7SRPj`>zX$hWeGBeG9%0RDOSh|;RG3qcxWjUqS>aJ zDl@69+*m23Q;AkSRiWbfR7Oh(*|^?~BMCC53aPYD6;y#FilLa0%(4PQvtqQn9Hme~ zix3_uB@5}S8c0xzj|uru=cCjO8Le)s(PI}3A;E2pkapP{356*lM7RuYrxU5g9TnMV zgbqddOp=Qic$%ivNF=VN@X@iHV_K}JXJd6$l{6(K7m^7DF*{WeSgkx4jYP!&8HzHb ze}i&^M&t-W5QDLZAXBmsjj?Vq(A~Y7d3u^~OioxFX3|HJA$Qmtc7X3$Xdo2y1|*KpYFYfHEUWW8GA-hz z9z&wgW4tUO&ofbi6r)U(Ly#oA9+%zY<`JmEpIGse8B)4cMcjzr`b!`tyGq9kRhkV9kLkRUc1p0w2!;Oo-l{BFUDhWEbK%g zrASC>dLofdWsy;l(eipii!(71e=C9{Pjf;P%PJGkpm|VGhw*A$QbZL|KBJ`)oux!n zONtUtJ7>aC`;@_M7&3TWGfpDl3^Qby5u~VqY)nK21yzrpDdn>TB=Bx3Meb8oECEST zVj7-@rlb?9reIyrNMIyp4y@mp*jpC=%zv`qSnP@%ii~tH*^x+~*6C0k_xT_7Xvl-S6=c zxUYJ;RBbfSeYV@JW~JP2p;=pALW8ibF42K^mY_Ux^&TI1qJ!S{TOy3)KlfKC*7r}AiKtxVy48aR@B*LO%P8LdqVzpX9 z$xv^#tI!GJ3hHL$26UG?GHt$?%atmbxTbPgB5YUP(c-d_NOhM`jN>DrAZi_(-DNe| z2+HTCR3YppwKVIt`pB@?Fpco(w^=GRahWIAeKrfEAbpOx!Yk0D7f&PM3EO1SwTq&1q&s*-;K)6 z>yI!9y-1F^YQ2d9Kck^56BSL83$;qAP^ngmX)T$MA}HO$xSUX^+k5)Zg)ovNNV3Qy zK!k~Ig*-ScHMsJsm^Hf9*I$geK-EZ=v; zDcV?H5T^s`Qf{*E?e{K@4O=ZIfBr+y-TsSrPfXZziJgbXo%a0lub!=Z^56dNZ~ypj z|KorB^VgsM+yC|T)?TYni$CbZJ-+D)Zph^mZrPm^aZZ@4&95ewwkijE2VeYte?G8esbc>4^N&PxOchd5*O(mwa0ii?UaT3&ZEx# z=98D34_|-Wx!;*RSQ5*UTfhT15BS{Eleam|K=u)a;hW}ZOYrunYueL&8XJqB9?rJb zc9tH0{^ZN$qc0yrfY|!Y^XkL(-50wbJ-sh6HOYP1pX7pPe|rA<$(z@MH-Gf+FSyUY zd+z7w&%FKqVf{F5O?N&hI}y-fA=oOO0xoLsybfs9?xCJ~A>k zaQnw6PyhVA>sQ}Ab@H#@|J!%o`n$95-|HLb|KPndJ(Ko(6NA&^GyW;Fos4&i&T5#uz&xfZ-4XEFMjI^AD+0}`^HHqw0{om?Dmk=c=i0-KkK=8)!`bs*JrtLb7ah5 z9=<;4r5V4?O<4mrHC?VoiupvleE8&1v0XXbJKo$~-7C&_4%c!}K<5^gRu>AbTCS+q zs`-SURuXoJBSf`XtY}fj8l;s_bmro~y$fUZd-sfnv%Mc&y?FN2ho`PzdgJ`Nm#*Er z^tT_Le*fCV(YtmFIX!*J8Ff=$fe2BIjYEv3R6-TA)mkQ9U!9HD_ntg#9zWbX+rI}DF)zYCBOXc}atdc}MytrL` z*je5C0>atD?SrQeAAG#Oy1jm|554#6Z$3ZRS*TU__L{ZLM@w^Am6qz8+w058%JTMu zz2nvO*@Xgn!$c`vZY5$uk)(5)?y)*Zr!5q4SS^qqub=qf8idw!7v8#cWn}#JVBf{j zp=6{UQ(k&EQgq$3fnvkW%W<=4v&vn zj8nJzZ<$SZ?bd5|hli#O12;}z=(~Emckoi*)TrSWl(c&emu1}2bNNdDsZ%|tKRDZS zeYEfHh0BBe69&f&q(kS_(CDPo;}MjMr17NSS6r(!=4Ko9%Kpd4 z?dJB{=Av3|ZdYZr0IHI0F3&a>A3oW6^7y+?A3a=OJ3d~T-`Lq*s;wSwtj{mZcRH(` zxy9vlC0&fgXf-KEIVltsq7vE)ktTx9>4}-?f#DI?*tLPlDTB#)yZ^R%W_Z*xbnVK- z^zGh(@#)cfW7BSPzsbXp6JEbzbo}D2(a}4D7BNk_Z9#7^EEH&<(k)B_epn(YRnzJ#c~vZSsyY!T z1muel7qWP|Hzg`%JH?gV^}V@rtA>4_Up-h@d;Z|{%NNj>AHI6Fv$DI=Tx{wEJ=v(| zo0W8>SgPkc6-`&s2jQj6Q{(0-qd7oPE9D`#6gEI!R(H@Qp{;=C*4lzzIA%?=nL7x{F9^}+m1frPaA$%5x&FHWiEskhh zLgkW5wTtuf`AnspLp38aUQduxc}_1Ss_oepwAzH4Pv}}GY@V61b>*mtC?r%xiAx*{ zDJ@EboltT-LNcDJ)wAgew8dn=Yw>v!>b}d&*C@7gkK9R31FVs8B&1R`mFV)cpl6W<5AV@}IYB`mZXe}xT zNkxb{LdKaPJh*9mw=uI+9vtuB^3bL$P1BMc9{pQ0qSys*4`w7b7Gzt~*a zYG;xHWHpwgC_0{KwaT>$a^!5QJr8MH&PX1&)g?*_oV#pS8HDvE^9+h>kK1OoJ4lqJ z5{cUe*JIu`oBkv)EZL?zNR_woHVr&Z%rzS>fCDPO`j}%kGPF`FwRQ6H)t6_V zHZ$er`Q^Ee&V(urK@N<2ZACxtwZvprPtAxE$_zw8qw^X9yu~xaM^u3b()0jfa10o% z6PNCu_`o=1c3Q}=oArp{2{I<>PP1l2kctFdoGK>jxyr_DY<-Ss={!k?{o|b3E~K<} z>d|t3eW|mXQ&%drw!*I~rL@YW^7Gk7tDe}Y3p*C&CqB}rTkpFwNkE1VoAv+7pP3JChjln&u=~4d9Yl|>j(l&)MgD*K_*d7 zaK&bR4x#G)+}u&8S}!!)$$TTWw!5~nuyi=LyuDhfS8Ann-YZ&|nTS=1z^dj2HY%e3 zNpn6A;V>D^_EF>y6X&sn!i2}+i4GVi4AznU;UVL+Y0__-iG~E5h^|8Md-*`bDL8pE z?MqM@IW1?C@BtE%Ova+L&tq~pLwtzNrP9?-r`()dsw`C7>58HkbuFJtloG{8s@iVA zX3ptpK_xj4?S_C668)5-a`DvcRxJ|}7=>~>CM{00ow2)2a0*D$=^*?uv`T(+)Petw zuyQhyoh_9Mt;LnCjb@`($yM9)FlchKv-mTt+xBw14*3ZCnY2b+L0>qS5Hi^HnwHl1 zBFCt4M)p%&P!@!Ego=r%)7VIi4H?Z-cSolOCk95xO{3#ho6GGa;7IsGPSWSIdd$Wt ztJQ^KE)+rQMW7fXJwCtN1k)$rfi@G5MHPh7dcF}aWYuyh1;xKym~YLs+Dr3`YkT{f z?NVG6j1Q~?cq67?Zm z6v%_steT*CE=nWh3lSO?Pk_^CB?jqP6_LNaSl2#>$Kmz59X=P_y9n*a0`Xf-0a(($ zP{c1mlMFCtRQ=v=X^!x1(__`n<3@XmIp-);9pNTwrbWECis*$h-%PKz*+5Qq<1 z6cw^-QTogdyD#K{TOK0uvy~KR*dj1FL`agdB1!4|+)|98v&&5}!ls%T7CFpjf`4Z- z*a?ykhgl((#z)IlT1%_*t%dnTNH+8Bxi%t6dA41iFXfV5qmb)*Ts#}`d3|Bzq;NP& z;OZceaABVd4ljIhyWi_|Io;4T2X5ZBh25hgqt2kqI(}=!=x`bg4sS$dqd`*8w1ff? zpjyaR^Ds%8O<0tTYA#pE7D~`oGmyiPhZ>~@Sdqo~#re6VRtptZ28vZ2`i-u|Bvy(L z0guDx#xGu0jZ6)Whk0UVY{tiveykq1+ciBhZU_cKrb&}M6ei(EhY2d+At+f>7y|-Dk8#H0i!fog8CjL_ID!#DqFG6SHl9^=EE!0qjDRbMP_Tob z{=y@JvCT%JG&ma)I&If;hQJFGK@>$54?a_Fly!zpR*NbVqNJ1-u}+(zj*!+#D~UVm z3DQC`mrSSXiyLcei;M7m7iZ@d=9lKmwQ{MDL3N-)LqavFAn%hTyk}_3_zDK0MRm&t zj{06e@q29+1chLbi3H3;V-7zG_;I5v?3)=G7_xf2c!+KiRvgN@WU-La6ZvwnQp=W# zT#SnPl`gAq#xD-PW6g1er zx$=CwTEYh@z^g15P!mBHhlZa?!OKe|Rn#pUY!IlGsdO$^sY5RKjm8A$Q8HdB^a`}STybKeem{vZLH0FMxah0_UsOT?=QT$BpJ=!6m$060PhJ?`&~ z6ffj*5FkE0ZMW0mgq~{mg;_bCE)>czO5oF%x_1m-D{OnX^~1d}CCSK{Qgdl%cWWI0)!zOtsIU8* z%kzzLrQJwHy>5~VjbFQVciM3G;)iFh-njhk&)@jq;?b>TK-p z>>fUT{Nk(M{Q9fUUVrxb)yr3}zxd)8Uw!)W381fCy!Ou8T&;U0A-@Ow*g(&v3m49O zc=Cf&=S~BB0{L{}!!wtz-n`Wd;^p?h@Psvp$`}+8obU>&x_K}`?G|oFrPi8l6!Dl~ zPINWzSd0zYXC_DP-5nen8JU=z7#q4bFgQFqG7Pw@i_G2V?Z=~;8XXuM1*>Fsg%}AI zPa;uV-dcyNa{rUBKRezzdinJ?A3r>N@bvkM$M@Gac8;GuKG*@Y_TWAUlC_P+Mh*yH z1i>x{@tgM9XQoDmh6ej@0E;?(;_bKJdh6Yj0FKU{J$wG*rE53)hek$6?g6#y1GzI{ zcEaX?zKigluR~RUD^N#-pI_eC+S*+2vPO8nCr_U~fBy6#*tqVy9`1oCT3uXNT4=*J zucTv;@IxM#%V{-E;R5g8zIE$X-_7e6&%FQc8-M#ZfAgas|J_?BPQ3lbTkpPi;)63F z<}Lx!x_G&7XyDex)8}rRz4ob*5u=Zl*lvM?E`=tdN^SGuqoex|UVi!Q@BZ-Z*I#}E z!10@Je)GFO{L_E=umAMjFMj#m?|=8*x4-?vAOHA=@4k5X^a&uhqX&;3+y@=h|3jczm#*C&nVOz5!zA-MKsI4_a&o%b#=~CQ z+}`W5R!4_N4<3LOdwA4k`VJ2tJbC`n>o33g_Se7u^)Ekr^~vX7eDeGu^oTFN`SSVw zt=*%C$9pStjdB_GYbK76+$BSxkaxKalrZLraf8h=J}_c(IW0i&rlzN-CdUTv_Fcbx z>B_}3C*Q}Xzi<&aBk;E#ti+xxXFoXc?%Qv_clsho$-ya$16{Wr?m)0hC?Sd<-C`Go zDHg^<5>XvwLot`fyI1S8%UgRpo9jCdUcPvAc>L_;vj=E`XGPU6lg?lIzlWahSIP$W??~yU73tiX#0kAY?8#KKuARu$MRQ3{4nK zGe(Oi4A;=(aylJWFsw$4arka`sZUG*7ei?Bz$x}ROw+hp5QJ_YLM27Ba4q3G!Ep?F zoq*vSHmk!2WLA>kC!tXW$Uz1W^!-qeDA;?&Vyc_R{=d{&DO76tW+C5fudePrK3v;a zSUuXiztc%b&|c~Z6!9JKR$B|;t?uuxEp}EGH|wohwF*Nqohr1-t$BEV*=jDCp#|g( zR879F8L9ID#_zGaXDsfS3FAnAALPlq1O0af?~NLUCkO6;^Xu*DAGmSm?Vr4Lxo4p7 z#^v7g7keix!-K>9W23{yiP4GPG24L2>hLfisE~3~8CezLA`yTRrZO9eV==9M}YiU!lPF$Q<&jB&U*v z1j>j?rO>RDn#C-zoRliX^<24Bt5+)ZY)RMjw2}bS6OFLEl+aVj9E!zqwOq<-nJSE4 zUE#n>Wpm}F&5b%d`*Nk(O0zDj6D}1pwWMZh1xWtYYA#zUHLK;Eiv9#fdAd}aooz16 zF4w^mq| zrfv3#fu8GwcKB|Fi7DJAo6BrAnv5=}f5_k1zVTEFMk6i_uBZ%OG1KaF7M2$QS#B)M z&Mz)4G;0-j)~M5)bBo(sTgxkp5CWUX;^3#U;1Y^+^UJGS%k4rAWGAfHG~sj-yd*?j zHZP5mTZS=7b}iiq5-jj2w>KQ&p@_x0JZOxAXD0BFOMyZKeaP$Z_%skGQSfi1-)6H} zu>VkOfG?1`^%l#-vPIlm_>3St1FQzvm%B4`GD1j<-JModbj00idq z#Y#B?U<$nnur)j>a9%nfn{LU}#Ui`@9SmSe0aAsh3hp-xmKa4I%ww+0oY!aDb=Y{h zJZesja@&Eh!H1-yA~=*fO5J>^UN7f#yr6)4n#z{y^9x{do3$Kd!?;9)00yr>A}RoK zgUYDLkcKr)=mHht0G2RVL7MJfCCXsX8Ige7W;OzhHak24A8Hwk3+-Su=yrB-2Orv< z5a7bD>k9}R7#;Xs+%l2?@5!n#9W%HF*q1;V5cXhDcR{gIbFQ<{=`40X*jx){D{{N4 z<9q2Uwjw$r0FL!;S5(g_Y$O8K7}lsD08LXQ7^?(ue9|#JW%UJTh6DbTC2R4Dx?iOt z=r?)0ZIZHE7)qplY*3za7NRL{DjHMll);F`&#$_K7$4OOYBRsoT6)EotMRN%w{z`h zt#o_4x|B>l-7G98N|}tkX$UhJJyN1Ilg@=on!oN5=uCi<*iA&>1jWf+i&pu=`BLslNIZxve}YBv>%$1r^)IA-Mn-*rSt1IPe}{I4Q?N z4mKQ;i)10iI*PPTrL$zZoJr9>(9KH%2{~2d0)~4YXHZ4iugZyqnw&}38u|9Twy;pC zWwfH)+1XfHn_Jyn-OV>d@ktG};M+YazU3Y9qpYCZ-V8%R7I0ReN$9QQsVetDonSdfq>HyccAW%`xL+~JQ z2rxIYuI3UM37uv!rIj-A0@^G-S1kg-YAh|cJB9heY^h#IC-eaDgQyrwwW~Ec>Wqq| zGE`5WRFruT|3b1N5dJ{2QmQb%cr=?&aY&UAjQjxyEuveIkdLc1PPDJDewIGZ0YhJ8Z#)CkG3fjA8lg_Y<8-kgbNpe2Ae1&YjqD@tOsbCf$^ zu~^*{i|j;`DldX<#jchyHN&yMV{!A4a}p z4N)vA4qA=_`AKKw2zaxUK!BU1!I_%>yfSI+W zrA7x16VL`!7`#HVAeKcfl`Lt%3^j@4(CNq!9NBmm!ayqw7P8y3vK(X}j|tk&#N?0x zwSU-chZYaE+X77{fMzvH(iAHtMdU&mH<6=+07p~7s6XO^uO1flZaD_RHXTpHe$i8j zOrugk0YBeqE;rh<&ABoZTshA10=O_gUXNpu200=KJQ~-G9SDI66A?g@)vTuJ3ap)iQb<0dp(W=q1cOWf(%<6^ z1!1cwyj+Qc7&B7>AGUghd@?*eV#TNO8I55^^cW}2cpff`JqU3m=wtb~DlmY3fZ5S1 zO4DQ#9XmKL{0mrGkHw%Rfocs#&>#a=0(q-vA+7-fq=O{MqOhs2uFU3BN~KXNYJyUz z#zT|i7U%?ynHdbS_#AGZ1gD0@+U0mWnlzGhrd(@Rs?c@-)}y$RWF&A@SD@Y_knbqq zKhQtmta_bRRBpjg0LuXh7bueu!{;ldI1Jg46ydSXxFb<0a5H{J)=*?eXv~sDxOfhF zQK8nHheQmKc5$|ezCWj-fypFQd=>#nr-EWApHLC_z`=1MAg3fkhX&X&9S3s+7mD=T z0VaTU2TtWMnA{=2cQ!lL)XYHtz?jX8LMISndB{TyFUf#DL4U$%gG&cN55`$Mmnl}8 zwR%R6$FS(j_4@4G+)@WQd7%SAvRun#;FHo|mMDs#!T=bN>;oe5PCgL}*lnH&9Vbl=w}@88GOMAHXe_{ z9Ipb|2EwH^}3;qe>zp9ExuYyOoNiO0C&y)?lKd5C==FcKIxH4NMri zYghEf7sN2=ZoDK)!0*17;sEw{FA$Lo(=brgBRpWb2nPSUfEYm$sQle-H<~{P?F{Y# zgntZD;1*&!3dK;jm4jf3c+)K+0p5dv!*^rx6pF&`C#u(K2v#t)Q9I@^kkEYz4gon5 z^g>7kB>=DvuZJZMje~{;i;paHzmKvo6b=QvF6e#;PF_H3-tTq4@9R5EfdDwg2oMU( z?x=()$KhG(HKRmPC8k&~7#Me=V)F3~f=~0?IS+!;YD#ghG@pLmQn|I?9o9mw+anI> z*wb&FFb1Yi_n&y<`~<2OjbbWudk-u1m;dR-r{Da`zx~VNM-Tqn7tQ0x)g}J%QH{1l zh8zHng47lFXn=8-tJXq!=Zme)h38-X_IT}!N1uH9^(Ti*_4e_>N``Zc!?z97=AjRV zZoKuw_ujoc`qPsq2K+aNhhtPWpN}f}onJm*e)RmCuYULYe}4RU_nTk+a{uWDguvxQ zz#j15oj5aa_s+?;Km6I7|J%vD@~CzAC;#zJ$M2lzdF!1w-WcgMdtCR% z_)b|R=#*Y~^78R#E4v5(^p8iMKL7Z$*T4PO|NgK4{rN9m{ma+SKmNz&ar4E_PBj}& zSiMnZvUjBK)`hpvp1yGUgOfl1%Qyb?&)>dq`mJ|PU6>lUVC%a#739Of#ie8=TUp#( zmKRpHwpSOL2kGkir(4T~)fkuE?=%`RlWFQXmU6`$Ou*(a^!8qIPEX!^`|5{3>zz3B z?$tAITz~)4J3l^q>B_aC(?5N?=L$w-EjEWmlDzR~Yw>7ftF+wS`|=mBj(+{+i#sh=KmX@{`S!a%{N`8Ref{d?^It$*U7xM2RI44d>|_}p zD+LjM`p&(P-YciB_n&z49I(P0KRdA}ePyXy@r%#=E@BKG__#p-w|LVP;UjFdZ z`BQKG*&C-%^`3kCgTHz6%DH#1^bOA3x^>U%o(VYp0_|j2Dxpz)tyNB?wQ_#>!Ro?N zwX(FlyRf-hSU*}@+uGdQfBo^t|M^$neD(U9Uw-%5t8aeuFTeTyCkIC#efIGAXWu@3 zvJSR%jF5_)mIN2H2`}tD)N%0~=krDl7Cy*14My+uuzecx(yjjCdp$k3uixl7 zbLMYO{{87wfBV)Oe{<&Y2Ynx&KXa7xVy^MZje&tNi^DKEF*$;gg7E+e zbXw7@5w$s5ndhm4f;CN~O@cHK6?!tV&Hovy8 z-l{GvZm%vLtn92G9BynKF7DS?=U3OOcqpw#6+v#co(E*Eh5fY44RZj_<;<`n0k{Lt@-VhmHlH3F5ll>sW;ab78(`E0&VoW^O;7m z0WK+*huOhke#_(x!r;QdDi4uKpmUkFVzpukd2DxX-!{$|46cdZ+jj;>p*;@_j}BpI z^lIOw8w33=)1WbE@5b%`A;wwK>6*eT@r>PSc2crP1S2LRWD(kGv5exz0FW?4@PG?W zQL#h>LIRI+KN4bdMR+|DGFFm>?Fu(37YTIPE}qe`4BV{$)JpsOmDze?$UE5yjZ0_tF z9c|G8%^p#SM6X zCTNOBA)?Ew6!F=umcY#9?du~3PcY)L8wQ+q7A`qqbq52eZlI`R6cOhqV1@{zD6*uI z(JsKwMnMQ9llfW}c4{12RVfF&FCK%siY@}`DiFW8NTF8OV{WIPj`379?1&IR*U(k* z5TI}a6hIXm+E=J&dAgAG$-M@l-K`8nj+e3%PVPpF|DS_0zQ^ z+S`Px>)BKe9VUoMRD;;#jGWG4ZX{ELEY)Z>G6_+N#<&=V(VeaUzzRW16g58V_s|%w zcg&cktw?zxXBdj2*qy&+V|pwafSnzoMH(LrA{qEFISy?RjwyUfbkY#&BfKU8>;ZPj zM7mSKXf`n3$;Tv);^G)glN1PgI%e0eel3%ponNol<`8UMrUx zCGZv@p%h_?FwMC+DomMmrC3#>oJ+P)Hl6Z2FnE=reVMojA|XZ&5f))$%IUKRGjvKy z#U<2=MPG^yQ*kjxl1X!buvz0iDdB)ZU8#hEId&55V2}be%7;yE%0J=FI>Ve!>d^>f z3Jf^bgG^3ga=ET^onwwcx~xlKzN*j|go?D{5e(6)iDFuwO)RtdKwL3+4~C%%{hI6*LUPnQkz|ib+k+|o=QS8 zB-oHGU~m(nCz6Z7r=a3~g>jice%P&nVGrSSkuxzL!RN!8oliM@^rUUF&tY|s2gd9X zDd@ydo;&1?nnS}dUc8E%lQHuWQ7w*8I?dTd!mly5ltAfhA;j0Sl|mzwY8KDf5<$}JJ zsV$Z;NjkfgMdw&dM9Tsi866UDJ&UPgjJ1U!*2iORUP$r2faVp^Ei)2axFjRxw0kfD+cDWaW@V=flDRjvs98k2Xiq?(n`mSMl5<7HGWzgEaY*ucQJOa?5W zU|fkoI~U|)9OnXp2()T zSU5@eAc4kQq~Id}OhsIB1ay%{NB76P>ybENCyZn#;paFqvH(b;iN=L0*0h#TOdZVjZ(G% zKmof~Q=oug!U&qVmccZejOc|%RhJkh9Mvd-CoroVFRE#v3Jfh_$UlNemcev9dTy{G zn0dui5Ju`Eq!(<5*AYUBCD1=I{$SXLFcpE0k3m`xU|tt4lL1;m1uz7zrZJtT@;pZM zG)09{kjtsvsdWtPVG>+VNjYu7cRB;?c0pv8M5o82f8AgVl)KuIg*l9q%!hl*JXE2)R9~l_7 z6TzvG+he|<*EldRi1iY7%>XCVm=H)q>tbxBPYus zb#z%u#x?jpcmM>3Bw?L&2k0>^jENI4Ya(u*$VkOfj`ez+Tr2{r7~WviWgG|7fCGMT zJ`Ln05(*d2GLZrK2%;pQZV@5I;K?gpmnE66G|_A837j#IiQ_~8*s%!BNYco63MWHG zAq8l>kQ_*l17!gLStII!AsY(V4HGsmLt`%2-(`K^M?oKf3W1?D9s3Lm8`@~LP|oFW zT1X**`9m#}(D5z_9dH_E%s>RDRKWX+*hRZ>KvMww34#>YJ+TA|4zN)aeCb?L3_1No zOpRi+Im!?Lm)Q;p$>{?CWknH-U57n`DO-W#x}ue==($WDBhFooql{z+^BuK!sZv0A z$>uUZcQ6I4=s2MOx-5^kV#p|or4)dJ&q``KBZjS$0Mk5no+rOrSQ)1I@#E5s;IS3edf4Dvn4=C(>9Ukm?2^*==H*6twQ%kuX&I{Q)#M-vhdlAhi16Z)D zY<3wl7Y1Iy1LE=VU3HPhZ-F=BZxaE37em8@I&hKiPkX^lMd-wvg3WDgtt?cNJk--r z&}kUDH#j`lf93S4i+847=-g1Mcc&3LdoRBD;`K)#fA!rz{P8zmee&Y@izi2$^YtPQ zNGP*g9zA{X_`$*EN~cv!z?BZUZN{;|-fQPS zc=zphPoBPT`D*W-Q5d;?LQE84vx31{URvM6kz}u)Ke&&Ub*0nD!`#PvSSE*u28W04 z-2zS4J*MkM|HzclWbFnZwi^rTosB)5MTW!3a30ntuRnhI>=7`Yql3do4>zk)&;tRQ zaE#sV?d`vP{q);!oxV9V+y}Vq#_;6$;H}%EHj<^l6!Tg5^_`{7&k^QXV0BEd-~LeC*OVNo%hdP>Fw*g z)z^0ycXD*v>_XmW1vOQuHrf#A_I5Tv6fWbCCy+)snrdNwz60E@Q9^XYYeIVU!{eSB z9lUercHhk#&^NAK{{KNWaB3HE09*gPq2bXeG)O?QiWI93O2hL1xFX6#Km9anGGZTy*CHUA^3-efxA;a zK@q_}6R~W4b{?ZRi<|c!93SrO?%h9p@c8MoXU|@K`t`TJ``vH9`|kJu=^y_1+i$*n z{n3k;FP=Z{@?;0l2?0eefY{2RVMgr2_OSwVpBNv#(|fajWO`<5xbON^uxw}EfBVh1 z-gyrX_PrA)KRkU3N2R@kJ34;&TtPMEYGg*Y|Lh5UQATxmpjc8PBkmxEV;bO5(F(E4uk`+3%W5EA=hi4ndp*%_io?B z-RtSSb*pqgkFKOl0LLWI!>`-AY?v3Eu$4b$U;|1U}J z*<@#Sp6mSte{z*emJWHuD5l96U}gXea_Vk0I_J1^&N=6tV~5>2M}$Vsm^{N722rF$ zNj}m!Wn1O)N4xyRKE4*%B4-E)=-zw3@4MEs?&rR*r=zXCdw5bRSIDNvh6ecR6*j|; z4ne4EyTPBC93LGWpPb@fgZz0_o()K>rZSft*GfE{#|L zb4pzRw(89$b`Pv4tJocH-nk8p3w+-G-Zqcnim-hwE-mxL|95+1Wnpf1ZXQOLFvpb3 zWdU&jBUEcGHj^SO5{SoKis8XYTyY2|^kEipE4)8EW;^_9 zlLco}n3?Bh8v@XU!M|23Wm4I4ePM02ktBmbH!1Gbjt`D&-4Wcv8nqF_5!^-We_CEO z{}hZgUMgEKc3Olzy;domo|eefIITp3P27z5p>g*qi4aapq!OtD!!ExIrw>1wMJuNc zu=%4Qr(UJTo|?-=%+n(iY6M2*a8Lh~k+!78?C{5PsHyBGRV+kwMDms9JXdOU`|!@4 z!yN!|ycs}_Etb!P7Er`lmNfnaBZ1F^ofao!44-Z`PgDoCPHld^9Ij;A9izYVF{YY3b!jgZGLmMMsh|tH(`ksNpb?# zz^Y6Z)^CzeN^~x93hC<}(ReBMJtmzVQIm?q$<8ZNS^T)^>_(&A&%1$0X)^LSa$)Fi z>&&j#?}NI8LO#UP%5G!=N+zx-QPW5)?4|bNBm|8E?}G4&n)zE;j#5FhoEuk3LfDK( zE$r_8gs5Ab=tae9IU5nOS*p~)zl)oSM{#3yVU|U)iUXBLtWn2CRxCr25NI`Fv8Dv1 z4#Wi)P6)6YJz+j7iaLvyirkJKrISucu2;e`i1O1o z^(Z6-z>xq1KalTFq0G0YWaCqd0XE?bgaXT>$w4!b%5Y`*BAJ0;H_M|ZtYm+A{)9iS z!W-tw^WFgg3a`JHpQxep@wy*OkO4>zXI?Cj6!&(u!|je(9VwsAWi3zU0;Whn7qLi; z(^{iUCwH18oWT8NhsL{VPJ6S8Y^YE*`jk>muCahZVsO|aF=qm5R32nMnh_gW%< zkav)WO~;c*tBEY`t)ywqOk!}x*Yre{FvMo^mMoDhKVBKB230d`_j%K$U;rg^Gg7DX z6R^aQlx>-Kz>~DixI@+uA?(ns)EOBJ1yl{&aKUaYD1o224a%G~fcqxh=l2g4EkOrD zJ`DdR?G8+H6#oQ>P&bgMtMg0j+(ik9jY#Xph$Ac!lRwhCI^{7!3=89Qg)>+^b;I?HwzG9V( zONgAQOC5506IGSlX_OX7EvG9H8r4y=#^!g976^INo1huau(xa>u@9zRt!S4tyK z8;V7q?sz3N2Y;c=I+<(wOWs0!E?CM(aC+sUg?K7jsU++k>dKHeVnrL*^0H{thoio< z$pb$jfW%QuBt03IC+&|bgLYH~<)lSvGx|053FV|_(x5g-u@nW>Iz8tqQSb5md)#uR z2SWheP0UyZTtik|AW0vAP+!a!O8GMRY^@k)1t%Msid67VanK|ntxcho>dBLYp)BFb3*xG%CyT`-1w$&4t|ERENPm@h8l(7pV=lV~F~Amxq$3%K zdYmNVJcd3~+~aZhY$4%jO7RFf)o!&KxyJ7Z1YJRw8{C;N&Tx#te1yoLvl82LV9fM6 zM7a~D6XUdnT?wz(jG>qqm`2K8$N5SisQd{6LU^A=R4NI_C}NMJKcu+gl%VKMtd>Em zpIs3n9jA3(GF3H-2rZq6%i=McL4lBRgDK}W^S#|(AF8m==<$as!3&8{wM@a0$%beN zfHXuG$;Hc=My^IY63+-f)feQ*8iXI_wRsI5ak5UOSaV+U4pZ1SB0voNsZh)vf_Vfn zi)(GrNG2r`4LwJ>QVTi26Qr$X^|~+}8(jw0Rh!@HC1own`#zy5QBt6M;oW4Fgrdel zyjn_^$oB(uOJ!=MMy^;$q-%u++6HGxv5U|W1cyu(L9e%)+1u$cV0|W11uB#?ZV)n{ zIAq5-ZDK`(Yl(*KcAJzG5f;*d4g`IdMT?k)vDb|+kd%`*okUzn6o`%CuL0r~OtF~5 z>C0u1Sn$wPOZ5s2ChWpd(ytCTMC}x6WdKjP$Bi4(>$W%$k5y<@dV^Z5{2Yt%sTfpK zi25$GOrqvvz#n7`psyf1+5jhc5HCHRsGCDM+6ET|zY`)EFh0OlNXGEHI9TJQ3rFl; zpVjLm0%h~N=|A#gFiQ5eg zh7_XC#v7B4j89;*GU{XsBMTR>25ypgj2#_?Gf%vuR-vVa!>a{hqzODAn=azv^jmL z=%l_dgT!*V&?_SJ3vKR5*v&_YPE8qubZ&F86mh==&{CxHN*G$7Ft)}i{4-%>VBV;x52!EP9Iiw> zQ%9r)h@j#+|NGzn z`~UOlpa1lK{^RYVd$Y^2Z=NrwyzXI_a!MYPUmX~Bconshrj{%1t}Ygip8VnV-LJlV z`MX~~xqUF-+`qG1(JQ(}B-1MYMBkfTXHWj()QKy7$B&(rIL`M>Mr`qXLK!WuJiEWM zfA7hiNB6!sxZS#Q@UXdAhQ(X-DJRtvA9a4z-P`ry+aH{I@2BrwJ~wu)`})L{CfL;dHUH`|FL)H_V)A5m1i%jje@bW!{D*^_y6c8Z}q_k z>iF9?-qMV{d+m+)&Rv=8lN&UHlf}cCdMs0`&p-O|%ikSr-TU`H-Tvg@{{07^|LJ%C z^i^}`&gXYmcaE%OA9yMIWV`%&@6=fPiHj#Mz46mug7Jc&_2!iy|M;EGYZuR7x~Lx+ zcEP8EBUj3J67{*-{Ob04dUcQd-|qaqnf04r-`twt%*|{(-E1|2mTV(d^jI`eW5^>n zNN==Vk`4Es{_*jj|KMWxiT5wO@#70`e(?S;&R=P7>p%C#iL2+NqeG+PQ=>MEETE2% zXJ4P+C@&shPwXi^t%`LckZk&-TL&`PY(C)J%99gYv+^0!?ini_x3hly?XTY z04ydT;aRUuYxk+7W0!AC_FTJo>CDyl-#*jbd+aAa`p-YSaP7jW_ka9@x6fRhl#ln{ zkRn$q)dt)6lo~>?(ZenhPL+0>u~Z|sIJ39?U@nzgS=qe3vV9-T^WgsW+Rd9xJXqLW zURz3s3;Ajs&bYV6ZljTqW)7+VoL?JKUX}J7zuNv`?`X%>!M>B7m#SI-ZeneH+wopRH-L~;FwOvwDhDyKW1kCdW`NPTg2Z+3I%XmRQ0{>#mS z=P&NP`s&HES6}`5-~a13fB)qElb4Tv{f8&_U)?%-@)%dm&4b%}n|pir*JfL}m^*HB zCfsrVq~EAlV2xIe4@^vScbvIAeExjbh08ZOKI-cmx_bH4ho>*}_gy{qHa4;k-+AYM ze&bhXP8>UP=G~v2`0(67S7-N!7ltlhxPD_&*3r{%(T?j>b};JsWH29dN6R(%%+^%0 zadW;opN1NHbK~Kix%&^-_5}Rt_Wk?+@cjOR^@k6izIgQ2AOGo_FZPx>-fz@)j<#+s z(8Qi=Z7*zA(pi?sW<6bHL*ZC9+X&1TqOp3!8Oa~xrTsU+6)X(1f{;?BpT{`=#lOLbHajCucN=IM+_*nbZ6Ky>`Qmu06YR~l{lpKx3 zG^t@P9*31-)Qf{BDn}}{RxH+WcFu3F?aVgtge~q?8fz=-Yio16XnfBfY_2vpHurDu z?l0ZmKiGeG@4=&cPi`GPy#M&wtp~Rc=drENw`zq_y187)Kygm_<4Jwo2G;rMr zI6*P;I<+d7>Xeg)X}P{_u(PYTzo+k9+rX8-C%XGa$A|lefRK|<*OIZImtcUlGR2nabedeTR28#zX6gQIf|ctBGyAum z-(A?KwD#v(Yy0;%n%kSZk9Kaa?cI4q(tD+`u~lE2Pp!?SnYCjB<5K*j{bSRhxODI&P|#6YQ+}UKsW*B}Mot^dE};lh8l#Xo zjS7qbMuT*EVnV0I9Vd}7Fv1ex#B8AmqMNLPj_SzIL?O9o)Tvwwc!9E*8)WjH0;lZiQX7^jn zG6K`CNUoR)T2)#zq-I2KD+yOzO%ik;2N17frp!5^(WHP*7MiQ2YB?6mR%U9gwb}W( z`FS9vwMMH!;}qE^O&=KgVL|F3=r6R^n9>u#iQo$u z4LUlIsAS}gNFq_chcI(FEl}yiEDflV5t0U+l5lleI80Df;y~jN7s?A##mvh5^6cy~ zp6LegfyI0xn+xSCGjp@^92FXcQlm!cOyPqAgZGihG-t}BWNS_GmAOP3^~(pdk0=Ik z3yfDDZ=9|s<_{9T8r=0jbp#Hb%ma-+l2cT~s9SJ;)h4yV5x}DZaN8$}s|4p8XmKu2 zEW%Nces?ijZRRuZ#Dks?hb~Sy0Hni#6nP%b)B$%m zyj$?3Z4j>9M*uLIO>AYc$&_ItXuR(2*Seh3P85Pn+;3G{3@MjVs!_Xx6Skpg97f)d z-%X=LrBkURO2vR#IymAjPTGT0S-m7{o-CLx<-u^&W>hGOcySZ0qwvOz?{*TTcWW+G zaGT;@b2MCv&DN8_rJ%3rt6*)LwUr!xYfJ}_&L7ES*P@wXjSS>+vQ|st+Zv1MCp89L zFye{|Sd%AZolkqzK5NX9OWF&C(0n#DyXf25EmZ=F<)E(Ms01Nf1xmhPq2wxgw@RUO zi|<*3RG&^ZsiBv4tL~ZP43xNqu)#zqNMe-29wvI|pLXkt9=&IZMg}CmkQY+P1G2n=XvN2z_ z;+vT*)k~SB;>-fvy%L6&ygh>S*>cu6JL3KDq0-rMsh~|C=8n8q{*) z?N)_e?{ZtcoX?T_<+>@Ve}~(^Fe;;gMg{^NN>G^O5?FgD3x1gYL0>uUr+{IIh#5H~^%Re$jwQ|RLW_^3eJm?%KfIo#i}+!v09+h7RE(g(jm!Li zxERR6aWU#Az=o`Yhb<~%TLQHc@gOvkZ%RgxD53;h5!&n|&(J|c#Eg)n@N#>6F%Gpj zw>g#CdF2q}y^O|!M@|eA!wNDOE;KB_2y(y<>ckQYAg^;+RH$s5g$TaOOsyDpGB+s< zHA*Qn=&kU=T%3b3r(hVOZ^Y~48w9W!BU``}!MvEuMo}HbCr!ZGhpP_%wapn0q70cm zc2-n00DRV*z?nTmN6(2>(~Q+dBN?1hqN+$o#vlR6`#^LMQiVwx@e=n0(27u3B-K{H zyi~7LX4qLl)FUgiljP#S?(pLvYk}ZT<@qELKqCyNK~NFlEj+}uJP9FE5W5}l;DTX~ zW@2a>=8|@5bXp6FY)S@@K|`+DV5HGz29ZZkkaU4C>|t@|8`5(FxLac?QaVj56OBs1 z^3jfY5xBd`kRzgL5{=0aM#Z4WHuFtrL}Ci%0w(Q7nZn}1WT*ndMzl<+lBtM8phaoR7dG z3WgY*6iTKDvw1Lk1Huivaa)tlgK4BQ=$KqX%Z$t#G8otbo+}UiE8KK=q#10$f2bD8 zRdNnwa843XDAro!Kn#+Y8Sxj<*kz_cG{mRrM)USMj2KAV#M>}C$P{$GT)5h&M#iTk zQ0b7P*x$Xlv*O5&EmbH{+GR2m~1q!nTXn5_5}ZgUPU zNY(`NFg1zLqmNv)!R(GE^Ra+cDVc_sZ?frCvayMA8Gt^EL8+LMV7NgvvY1_{ponOG zKes0@8M9I*UoO&nOXjmQ+-nreuwS`bSi6`n#N9<`GJ>y(qA5cRgD#suuVJmT1~D5@ zGl;k!Dvi~mo*u=Npf*DMQch1xwS;N8Ziw*~av!hXFFuk`JWtlK1Y8&unARJ8GMsDR zB0}8IXiIo3@h=hsXN(4SxDN$MIO};DBIMz-F;pZJe!c|J3nf~^CoR(0v|LnhVS*7K zy(LB}a07@(kj24=*$(_953fj%QjFj|rFZIO9ud_N<~QUx!9%0BiuaJGkk8c3)CN9M zjF3V~q@c9GHp2-(=au+@Q$*VNOEC9i*_2RzU5IAl{zM0lg4ki>ytqLL#nh2G8_{$pf?f9;OEf8rHP9u$IC?n!+8F_OLs7tFHwaUgPAhgK(&c65NiSzAk=TE%( zt78{#^!0YNcMeKLjifMm3rjn@xSci*?!Wr-i_cy>eevnnzxnNV-+uG;H{X2o#q&Em zxMFs_Li6T9)14J z7f-nYd?1HAYbyX!78d5{TjCqT0q4+84G;7W_V;vNyUIk)GXUPsTmWEo@!Z)nAAfxM z?3uIt*7>X5xN>kts!U|ESv5F@Fv2aEF3-#|53)MT8`|0+n6|TjlPQ{z6VHXu! z-+%9&x88p5_(^ba*E(+WjY(wEiGdr}yGGUQfzUs#^* z-`QP;2+I~sZ$YP&$si?a1=nk2Xn>on^BM-a4~`47*!%Ci@ylPm_1>{}-}u=NzyCLX z^Zg(E=m+2X>%ac~-@W}IRJ_xt&s}c6(cLZX$L;~TH&_|fCKpD=Vi9a#eune)rgkQ)e$->*&03qpPdyMmHv9F*~xae`s9#I*hK-87;48L1F+VUB+=V0&lJ+ zTw@FbTxBfPiuhVy!mNYKYUk$tr!QZ=c=m*`n~xveKe~CqfXhR^4j`0muB~8(9?b?aXW)Y;CU0Y;5h^+g)7QTt7U#{l%+CFCV{n z_H6&j`UXovYc*Gm&Qxlx+0qQgY&Kk4Ko|w+J1UJb4O)g1WD8kBD0@fO_q zZ;W(bx$wp>KfE%bn;7c-_{#Nujb@;`|9VH?#Ps-hcehjzJxXUJU7)aP)l!*?l@zJj z!rl=j%jK{^1_>F=67_^tM?FZXg%vy+qbbi_fLT05BpL^0VWzcFN0Zn1kloTG(IRJzUw_+C93nyv>SGgWJi*z*xwc zGEN_-pRqU)R`9;5C&$Kz#lQwEK{8&pT4{jlEa|`0ajgfWsEk3D*GFUqvsyCN-964@ zIz2YnH9V#e3z^CWmlMs8#&RSXafciZaOI>nh{@$ri*IN<{A)~uU^iIE;R)CP|7NxVjR(vSt{o;AD)rI{uCfb-0Z zJ=i)8#~8i8DtSKOm)eJZx41 zChQrWQYojp+b;JGtBlyBWQs`zw<=IPt`jIOPlyVIiUObqV|>_~E#UF&wD`I0@U#<7 zrce`pcJ^}7M#ok_zZ63{rxNN=q9F9d_-Q!Cs(I`Leq2YTLfE0ugLXb5Io9gD9gk&&8lJQ9<#Y zna&6hqf|hIr*-$*2JdAelE6#gxWhbvT>#Hij_I1X%ka<&F{BAo5$Z4J4-Vz50wPdM zfsG9Ux*~%gLx4zU>LsE}gx8ifv2jxP3Runzl(u4q=n#dxAXHFd^E0Vasc695(D)}i zNU}jNa$nEjqLI(hmSdNT{Y5ebn$S%8LnDT4Q&kCe1{@jA&^8~`B8(dN^%=bw#&2)K z@FCEu5JuNT#bZM`#s&X3LBWkV89OITydo(GJRTWL< z$}ZQW$>MUtzVS0L4=02R`j#TDp3+1zQzrkIQ#xiClNB}2`WP5S4i;GxpG{`jx0a3{ zMu3HHwla)8Y2+uOjN-fESty4~|E3;h6&lQ5Rk?e9cxVi%U+qYK_tR|NzZ4>3WQpg^s zk60j^?ult4Nu31Rs!L%qkhj%EtWi_gQYDLS@@5PHpANX24vm^Pr&nR@)hHDTmq)3S z5zJD7{AHqvmUY2fm?^kp%q#T6xK32kK6yOpse6MiixM1dA>v6!D}`9Ttji$<)I*JM zG)ELOoo_X(ByT;IOx79;sEuX2ot&kXu^dsa!me}Xun&32Fmi2nQf_X(QJKruOEW9=g~m#2ZFLhgd0B*{;R^=y5iz62 z7;(j&^q!a z%+7?NU97K>L@ig2CcPQtpg8Ps7fL@~0_4!3%bNfJ#WB{CrWwJ^HUgM207mJAC+}wx zS|Uy^-4U>PX(BkOwnbKn>6=!yL2fhHpe%}PA#?qh8j_yJ+h2$<&ZC&B)=8p4Itv0k z0$EUIW?&d|8!S$i{Y)UnULKC+bIc1OA;cg=K37;hNS+1)_af#){{RCR@YR zR#~&r$C_rRQD_O;SPA_MvShvw@mOyl85E&A=9qILgj6a#Bj{78|Ky+;avop`0OLxs z0oL9^H3!kDQo>+Xsg~yO{}v-*CSGtfK)wT!fMTQNXv(dHm)NAGV6}PNgiR?48L^09 zhrNnQg_Z-ZVllYHZ1u)c458KY#_2mK*s^p0UCqo6^mtJ_aF8+eQ5d^OI&zL;&TEiP zLkjcs46J)Hb!@Ih)>)=3l+rbVT{Jp^r0ZDgG0T|MxPFM7Avaoxohg9vTJS|dt~H{! zc&#+_*vGMmbEbA;4YrsBfSetJkuO2U6=pH&u%R-DI)M?3F^?!Nc%Vr1(cwk(XSNKI zBH2A?%Md6S@aqi`pT+7(jsfxok5IhSD5SY@AqW~Z67miT#pKl32=fIAwvoTKk{Wa( zK7>e6GcC8=AanbyTPM&>lbonip79^A*PFG6AO@6 zs9$`641he~5^k*^qo?B-Lz&mi^Dc&-GSpPK+}O`GI=>sMH&kDtoa&a^d}<3s^2?#DGs6U^u!&rHee3|VmyqL{FRD9NTd zJuyBuIYqNt3LP2f1k^E1P6VoXd${|H2rSjI_*uLyp_ftP38y0_Dhhn=F4$YBIRdPP zg;H47kjkMkAoWpNMIyM%LCv`kToJ7ifk4~yjL{+hPr;=LF~n9h8Ze(%DjYU>KDa@I zob)>B$oWucdkCkb61fNX*&x5Lu403Pu}SBSwOg9AVxtIZgc(IyCq~id2qaV7a2dIAk-X@j6fzuF3H!op1LKP0 zj%JRD2b+@`njVi<0x2p@lafzEykVqSv@l_>qY>g@9kE-?tREIW9KH=diUF7C)Iy=- zP8W|P(!02{G42z3#Jn6tY}{ddKOCdtL*kLehejt{nBfpMLF7^?Q?c7ohUsRa`m!u& zs@ul2`w z{_R_i`02cTajBBjxjNLU>r-C$b(=ZJl-HJTeSi1q?rQzfy-%Ody|}Y^^z>k3HtlH4 zw5nE3-@sVklzp)0o%Yjje{||}-{85k9TVQMF=;GNFO)T@+|rAii;q@rA0FNQ@?fdD zHG6ZhUN%p;Vr;_`V`nd&zR_d8boIqh~MvlfPF6;t|fRwD_mv}RJpnc~XJFMj>MKRrD7<3B(C_U_TWJ1_tI^*3KK2Eqk$Pgge{|MBJL`*+K!xkvjuD;dTJyD~22w4qxexiLP{cID&A z{_g9)xODDUT~p^jzJB&t@9EBK$F5!K>6-32d8+4%Nur;2`y6tAda*iNoGmqW zR&Y{1yS2RX*`06h-`{_DYwzgAH(!1B=@)>-pl=9A@fwrq3oH^BZ?c~Mw!E--^=|46-e&g($KmO_QV;v)Xd`NJvMh2C}p-E*b z1;N%EgrncQwbDq;6kDse9(?+szOcM|@M>r8Xur19*qkXXuPxy7U9DAS5{X)VHku2$ z{4*hwT|Qwm_~IVDbd33FDu=GC?dtm%+Bz?`wY~L=H{W{q?8Rdjul8KH)P8Dks;lkF zwJQTxl;gntkT*w_L)|7dy@(;HLS?l;IPy7@)y2KW*3MICXfJ;M?B*vg?~xFG_~@%w z|Lxy?^QUi^3Gw3h|NPZcW*a=Xzqz(PySy}4nw#BYjsgUbLf#j*#e!1-on9u9PRWLc z2B&+wJ8r1EJBO}bxqj`10qmR#hc<$tzAD{Z@^e@hw>OKF#i4*Vr z@S`hj^8U{5Q>QRRNyasr>(|<4nn9gJ#vCmANTpgVMT8d;?|gOT@&5AR%EtcI-CMUF zwO+h<{PfWtMzOnxUq0I1s4g$$Esw}tG zm;<#U2%?~d!;+v)A~UPTl@wtr1xRm+Q>V76JBNF^J1=#1cXsi)bzGSkzSwu+%=z~} zJpCg`YFEy_cj@HGbC>#u+dI$R7#W5JCh6_F-Z`x@YDSqCZ#MaL%-{n&5s3orv4t%V zaZtPBxz_CJa&w{DTED%vyt})&wo%`|{rJJXdz%Ma&p!DMv2yR(oqKog+}Yb*Kipd0 z+*&wXx^wUT5lZ3OMzc~&RTr{xW;9b9m+Yx9>!MLT-D5UQO-x>I9~$bp(RO2Ea@ek$ zH1`jTO;5!($6&Qju(GZ}J~c0;lZ z1(7BTqWzjR_MO8XJ+lIheOC#_BAtZZ0lzzbvlJmQrlrt+mb8=4@kSW$FI*_R`!^ zBU7BOrfR834kP|tqlEmlG*`)`*uw$@J}IT`{y;2OZO%f=23X3DXICpnh6j-IH&$F2h2~-4?Vw_2d zpojspl3Ik?O%#K9*ZEdH<~6BD5iZP(!3kz6AqVzbNQ9sryI6FE_ATiJ!5y$k@sFE>h=-%$A zkPJn9DG;LHYH`5M%5pfMtzF$|E)g#&=4J~ehTuXsCch1nrJ1d9C?~vKqW4v+k^Nz$ zYO%7|AT3;pCrUIqBM};>l#fPNqPn)gtg|SiPK3n`5d!ElM!spSm_+3_U}vYq;L~P0 zR@iCwm?e5=6oWu2LP~}B5(cu@1HsK!Vo@RjL7ndPSn1JO8T-qiO`U-nM^Lg|W}D3s z^u`O7D6S0$vrHr!mJRANVlO`C1z_EvY{anQ^QG|jwdU8iHs{JS3nenqE#yFSIP^7! z78Eih5zECIAGYK}>?04kW<01e$1O2g1bQ%#}k@^LdE zDiG!E!<<3kq%BFh61xWW1QuU`>`)=L3d)(t30Q4n016HQ#5UZb(4~`im7nc0aaRmPH8NjgGJvc+uCT0({5%7F(F&mSJeHL+VJ*cS-bf-76;cp$zKQbklz zd!k}=>NQSBn34}(qsQo!PX^Qyqe`Y5>{U&B$D}^HE-}gMG<(csm@(ZsG@UvWj<@{IQllI}544sxyep;ELN4M;Wh^0otm#V5$5RVw zxJ|*dX;l@B&2f$_MN)P2#;Vs6%c3a|!{_{LP1-Xw9YR^3G3l4mO1ZdkoWqJOL)h6nPrWv<#c9j?o;7 zQ8H4K0eK*bykYXGBq45my)R%18mAb6N)XK!DZpS4YCUPD3g!z8okYC~1R9Y{dM8zj zF9hb|wN$=ZE--dF7!lyPa<$b=CjvR2J5@$Tbh|2Ud)enN#On*;k-Zaxt{P+FSRnDScVzMvsuj_dtlo7QDg#?`cD5b{NC4G%${B}*7DD#>KNKm#D^ z;y!QW!lKE}C&`)7=ZyuDp$fLLu(y&ZMEy3LmfkeFLZAW?)ulE`HFl<26fs5`r}bvP zHz81W2zp5OxdeX0YM!Ud4;Q663)Q>ESqfyp?BN1qc5@MOr0|5mR(YerMkrM*`%BDn z!@i2YO&i1-WK_DbFgwlI5g0n-02*XwII`ZRQDgp?#`Eq#6$ILj6B1d_Bsc4|YK2OU zCj|wA?TAU2M6oe4K;31u3AQBAM64mMgvXoo+r2h%mQA`75p1bsywP2nWz0q8bd=Tw z5=OO>62lSV^U%3cp#a^gDB!OG3^x2iem5uNg(fOT4e=(DERlGvRPiZA8PdlY(h)|Z z^6F{R_yC~;<1jFGO%3J)wg7UGK|{#e#AF*30VAz3xGM~dL(Rli#>$LhU}WcD*+smt zfY=b;8ILF8LIB{D7{<_ohb$4yg!7ngvndjxNN9AEV{n>KsIbB$lAx|J0V7=^l%dLq zI2UbKC$dw7SH&5YE)-reqr-~V3%r%xfLIU?yJJk$uwf^|wnkhyA=(u=Y-MrG)GUN_ zNWiX%87Tm~X<86!!%M`GyjZ9w!a&pfygFQu7AE(YQEg2IbZ8s|(AwhcS^%3wB#LQw z9K8Lss-R}GMRBtsG+_$zd85kU@=YN>((TGbo zJuxZR_+TqkDmlUiA0NQ~FpII1b3L4Requ&ojIy|}nWqMhj!Q_x0=H)=SElVY%ixDx zwU8@iqgi$tUI@2{+iSH0V=&|Schb*Ns<>3(*uC26p`kH+a_9hR#IJFTsPGM$F3Cha zq?xeztYhgY!A(KY6n4BE2nm{kIHjvhk}L^A7#=L#q@sC(qMo3QgC~z>6#E5gG#D#8 ziy^RsI738z79g;2_Z%$bQu)+06P1;)8%&gn{M*fV2`Ba_CY_+*x&2O11(|#`OY)UO z8ZH{B6)+D45s3h15wjWkut@W#`P3t*Ck*KjT(Xdr1c@_Rn6H;ZW~EHRT#qDi61{}B zn#RUO0GFfDFu?}aeJbt`0Jq{Zqgp_Rjiib-v~NPJ7}%&_qI46v34yTVtOMo&ssfWx z1lM3zE9l+%(rmrSD6wpmTPrSz3kXHv_<_@-wP4xOp_H0j0oVa9 zmX{E3cb1w#S~G$8_tm#Mh=>Z6T)Tbhxa99VIDbXWojTskYs)UHe4p@;SJ?>Bk{>|K#H69 zhw3M!J%&o40>T5NN~3v+#qBTuNQ-rhPB_lze1qAu>9AcRz;Rj|m#^*QyT?yo=^hvw z9PAzD>0p#gxwg1-|M?eRe96Ga&p!R+)w4%O`x^^_6NAMOrwGdk@~D@deSyIiYg_xb zA3b3{RE&!WmdsSFVE>1G(QbIIc8eh-QN> z*5}tZHrF@Suqk1cx3!}{x;Js&s@0Dexnax3N!P(W@GE{;pe~mr+@kL@4x->i?6=>hkyF>KmPHz-+lL+-~R5mU%$Gyx6TMm zjIv}EG-9yeaPRd?XFfcB?ASYRz47y({_Xev=0E-CAN=HJKmWxq-gx(eGZ(LP^bAjO zz(N!i4nmAZRQ)xGGh$Q{n z>9cLa*fb`)&mKQvQzr{^8d8_T5ju`@`RV^X%@e+YeuT z{oOa8KRG%)xOwlv!@D=}^$Gq`ixFa+LsD?a^eTy%G6}<~?aJlLmoJ<|bN_)@1V1L&&EP1CsK7UyZV&o;f z^Ukr87uwnd9qr;ZCVGyHO)$I*-5wN^3M;Hdz+!|Nk9$~v1R=TX@+haMvO2$RZ{K_vwC`j zd+WM@-JSXP^hxk?nA?sWJAV8)qalCwcR%^jkAC>0pZxq+@1FSZ!xI?Z-hBK0Qy1H= zU%z(o?3r_yJNri`Byts_B88bWQ$$plonx5k;^NW@&%>Pu%o~0B?Dn& z%TGUj^<2DA@kG6P@$Bj22cXgz8;RQx1|KA;`%z+9Art|LstY-!0=mE z1<-!OeO)&QBnlPj%Eb#81VZi92fS>q;E5BwbnJP@kDvJ9)Y*&B-5`}+xOf?lUQgd3 z2r?yBG8}?7VhB9Mr0=oMvWqj`gyOCt3}wr!>!7>#L0s(};MTl%k2~oxCb(CxUOs=! z$9Z&@$(@HgTbnz3u;^|c>~3wWtuVi}@tP}yp#sK^7>z;^C$xHU@bt1Vl*wgM$@KJV zGaOGaxt9^BXkFLa(7*;pA&-qAQ1aVA&&ppJ=|a|=srTRR}T_z(Z(ZQa5K z$+NMx4!d6X;TD&-Z{5AMIg^bgN^`5LvuT$>Zx5vlGc}KSR?zO)e_l`O=n; z>N=mkF{~2# zU4fmoqiaZJ#ItBpPK{4%oKZCEfEB=**%L`7BOdN;E*9TUz(BbtxH)L4W45LKrd#8S3` zvyo}03mB}bO!%3bt&4q;kBIXYK>`X&ToRl=IC{YpL;{mzN}iZjXsPy$s>$KOQJKld z$$))JE*IcX01k9vL32P&q&v(dve8bbuP$mKF>Mhb7?lHsr@*~ZeDH>-sQ{yhpW-4^ z5Dz+yM2htSi6|Zg-XQp-un>M2TA405F394{I%CceeOvB7akk$<1bGvBaZ|wP|d<9k_rxt zltT2P2h8_-UF6^_6Qd7BdW4FU?kVsS0v|k2%qGJ=#v1|4L7gSOFz;iaELBKuaRMX% zl%f=@S8Jrzvf?z^Op#zvYmH60FB$?iTg;k+HglX(G!w89Jj9cr)~^_&{+5zs&Wtgk zFb4HlSj;Lb2yvs<6JSwlOfWFcmzp4yuwUUto5MbHeKA&xbj;i#1wi~)(x>q|EDQMdXp$K$*-Y?c^3x)NbU_L*T!W)-?;BxVhhF$wrW1?a?cz>wwftsf$-k25ti`QpMXd`B?F{<)Kojj?eEvp`3aEP)2_TbW(-?n z=19P)W4OeO8zTS%+Uz<)GPy=G8O|coV+2Z-8)@k7PCD?_WE8J%gTb}f+Y)6wS;d8P zE}V}x3Ue@VmfdaQ3PGy#%X~Dv>8YKp1H!8hyv(KxFFoO~Uo7Qd9g*ePvH8G*HSll|M zzq$!l5>V%l#hAC3CQ}e{;Dh00Q<`U{CQlY~GV^uDm(;2S#_^RX3T)nl0 zYok7FrZPr?tT4=;VtTCDlCKWa=g0<`#W~mAO z6P6u=La)VwWTdXKF(ts@#I?)p6%xbfOI9$l0MmUggU=cDWzbAnM;V-HBSz?V`qBWW z@lsh>q@u_Vv4n7!^14A_1tBv<0OMO+@WI6Cp8hk-YbcOlcVQlMj=3&=Gfrs6IVAGA zI+G*g{$z-uCairNV`*tIVc2V@KY`y4TqIU!K5MjdTSh3ZI)fdswm@L4ZWS1zzL75wEc-VUdmjx$;Fq0;!(FB+kM?gwq!zyE_lxx`e-I zrdr8Gf)F%AbVZ`RFuXDsV+YbsrM!PqZe}71D0RlYku@Xs}r)hNk!+&8BRmoG|2S;+&GBg zO~Pqov0`??J{6}c6X4Ko$H-G>G;@{zBhx0_Dx8q3v(*`#!xhqvIdSC2TP>gtN%|B> z2n_s$+{#9YWhM>L=-`o z!gDVA26RSEmDh4t64;YNFv{2YdFD0xhHz>!{K));-QEUGg0?IcEPIt2i62~we+TW#3m z#FkFLmAo;eR;#F)&_F<{2Sa|lSw2R_WP(0(fW6vocx{izFT_^oW@KssPgo`v;!GIC z4~dDBM=O#nf;r7mp$HN<=v|TR!viG_*bJveOCiC^V;1D*$0mv}0U;anInP`m;54Ze z+*vw1fd#gAc=gz?1fZYB7UTphlzE;79OrgNB*8!?rkZj=_-2^flsX+R%jKrr<0xX) z>y>yHp^G7QGKXN!rh9FLH?5Q!KiIRkfMp@lX{gN}&@xjLsX zrU*0CTio5eSZtYSJaFU~DWX#-WP(san%5)D52I5@8K_nAm_XHF2mls2 zj?C0g9G%5X&%Z#wh`@4;jwcBK;E2bbB~AqtUi^?WAq<2!FESC4S`mMY;U^QtA;%F> zhY^bpb7~YxN1K}iQn?D$BSMmbTL^8J?18|gA+;M`D{;7wu@H*dl0ZNh-zl~+Y@B2= z#Mn#0V}pyXAX7u$o6!vv<-$uQzVM%k7mmtCkU$vnM2?Q=D?JN>7F=DP^f;-9U<^bv z;!J=507HYR%6Joekvtb@S^TsXoTIGW+&LcpDTZRgW3!`#p$Puv;D`=Ro5De_8W$XY zj56Lv5ihI)@L7_v!C=^050#dc(}_r<6iOzmF-Oj{o>ml`&P7wn6sYeUl>%XGwl?X& zd#A23cx~*&&nAcZE>E26?2tR+vqvkd_g?*Pe|r4l&;RR}fBKLAHSA{j*y|k+=xZLdgP)6 zMaIYW}LAJ$P7Ix@9Zbz$RZW@cmU(Z<}}gT|xv z?Z;o$*5)cNc2>8x>FR1_!`Y%o)%Wg+kA~!O`e)M)%yTTA==t`sQGC7xTkOe@sT643zP)#6?QrkuAHV(0%YXgn7tg-`y z``)LY-+w|@^zP9&fB*c^=le$w4%fH0cXn>>@9f=qdbo9au~k@Nuv)SZQK#_addz{C z8-Iy(x=*3)>zeEZVRX9h`k9YDdiU5n$1Yqr@yj3o^n35T`>S`q_u&U;kH7KWTR;5C z2ba6Y#=7wTDaR&c1k-!^$313~&k^CIP1#T@M9cFFWHfV2Yxh3iIow-VT-$%N`{~{7 z2Vd^rB7c16)uW@Y4|exg5h3p!eEHqK{{3&C?5*zJyt{Vq$;Ng$9?Vo4tMjYW>*yV_xS{)O7Xnjfr=qVPKhyP*b0;pHJoe_X_dhy!q3xsV=g*%1=ofGQ z_=At%K6Ct6@18t;<)ceiFMKTWq*u-#zjWp5pvs_U0GO7BCj-O`fNui&Xqk#`o~CIa zo1dH6p2Pfh>);vVOP@S_@%Yi>Pj~lj?e88Q?mqeEt8c&k>cOpphj;HhzJ0X+{Nb(r z`#ak!8>^LEHA8!(Iyaxq%&<39QgJ6a2eleQi`gGg(p=JM&62S`jiPs`_d?Iulyr2k z?Z(y4p7ZT}?_9dpGc+|ke7=3Wcch>Dy!#q2_7dK`>4D4rXRn@_Xzv=1!SwWnjGy>GDhTw9;Yu7-X9Ko9E=S{7$#3+@h@ zT<8x(1pFZ{7U|sV%G}EA#tOrQYE3kS!Yuxy21+Ogi5i)uY^}1mHs4%m5j$4KFIpdB|=%hn%@TUN? z!Mw8DRFh<6hdbKNUG5t0>Fw$#lRQ0e{lcmCt2f#&T)fbKW4KQu9Y;sg%7(^tv}1Kv z98NB5R8CGV7LD3sPZS!}`Ng@Vt@YK`3|+cdE`@Mef|M5Z&dk*j`4WksHROfeg%1Y` zEFFUwuzaFEglwYFDENbLlf8O-uuy0e&}OpYdQ(>MrW?gtrQWKQV(Bt<2yZx+2%~S; z>&$vz&X$M-&|4IfvlAjuXw=F%0f4UMlpS)Av$VQ$@f0Bb$#JPkPDYQQ%#_?HI?YDZ z4GX1^IiBNC5lM#3cnQ6v_#li39D|dpTt`gUZx&UP7}($y&U>}At7~{ztA~Rw%6%*F z2&U9(%?2g@Bs<{(T9XM-bhO_%&GOMO<`OU=k5QvFyS%=Pj&}Rj%{z}CKDoKJu`xS8 zySlf&zS2bRrJkTRj+Ik1v57Ph?*vx@dnoSHQ$sO@l0I>O424vTA!T#{Fa^deX>_F2 zjH9x#DLFhjD{tMxp(n`DTZO?atnn7|H5`fKu*jKJ3aQFq(1TJn8dcPW2rOEw0U0Wp zVoW797IXhNzA)%4Qh?b|Di`xnyb;mzT$K;Mkg3&5T#R}y2(gB1L2A8D=qy`|L<+?y zDg|Td0-Pr?C_%ch;}t;gqCXgfrh@yPaERT+p)*3jB^`yun~Wk^b$$j_W*?CkQ+Q80+(eOb>*X{XLH*&CmC2I?NY)08oesxMAlpKvMFW{qZg zs^4dl$sH2h_Cpq#+-z2ACi<+(kX&P!o=o)n!gMON@-ba>)Nhj*LprQRaY!d>?~E8q=bZDs04{O{BS?a=$!6!CENK+1TD!`jTz<9Q z@=Mpsp9jO;Ue!|Fz`eitJm-7P=TITHu~J-FFK@lsT&`!}%o5$}B`cJ9$Dx3jV&SS7DC`+^jjdl~O6N?Hz5(yohIZ#iopgw0> zg?KYkuJ3N_+}&KnqFJw(0yn%|FJf(JHkXzw*ro^)7F*SN zC0fo_YbEhr6+8)m?7=yX+Zb9fN5QqNav^|HZG-X-3k7785u;hsj-2iAnYd+L3rd+0 zl9FAb;DL$Pf|5l;C`x)h<4%XOiAu4VkD^6c+;#*`z1IL%9utkvN!Uuo?}#`=2l_g;PXgEgnw$+$xQ1Xnsnjw1CzN!y57mO%VGS!=5lqreY>p#blAB8;(TK za!q8f(VZp!AqqAfJFzy zezOf&f+HO-6?o3r@wJAWI=6uT*g~SM*kO>X$Yjk*#%88ua^glx3$6;lh*Ajwcw{6H zg7yGzAD$JIVcP?NL^f4~lMl^aZ`4vVO1mf{?4o53#ByF>waJdWKC~q|y1?=%$qml?w-G?H_EQZHB+(srOX+}N{ zd<-;mVl-w9AN2=>sg3sxgJE{?$pF?dBOzh@yS$fa)Ip?#$L_Q&Oz6x$n?t=YPLsA8 z;l|)hA>|u=iDJ7(M@G6@?JU>Jm3%u}V7}oArwYYZ4sq1Q@|)QdPT>q!MkoO1JppRY zZWh)qT9j@2_Uze1r>tBWhYg3S+vl<*6rnC*$~ z>Xb)2JEO8?s->`bc6!dlM+)%)%zkWm5d;_?DqaRTm<2(Y`wM!#n>$Qci6HthRiNn> za=Q+-h()JatF=1CHrZsfx_t?l6DFf4S*Rp}Oy8BH%6T1*4o@jq=?Br71Bp_#iZT~X z!&2>VE^B~x#BED7mMAra42W`g6}hN+tm9u5F+M0&geEcTlk!s=O*RXQC9|6*Gc|>) zlNwJf<};9|!SRDuuTm;a9<1^wDqf73Xr0_<7$#1x-C1qtDDnnpgN#K%farNgd}eV7 zc7$RhP7?AE4VEH3%j^>Y3+kLvv!E4|-E`27BI^>>oCv-yd{Wqf5hb~f@DlP7`Gh>h z=?p@H1I~tj5%M5)-ZX8H!DPNj!2nJTrrI{MRSZ={@i+1mRi!bP8Ju|x@)(*U6XAGD zxTxa98z^O}a0xYA9h@UH<)sCpf;L()gXM&XASd$xao=%p`Cf4^>abB%H_(d(&xGMD zlM2>+oH4nSUN$EtS$2qwG*LWBN-_ud(}J|S>#xWyeM;77Mh$ODkjjzxL%OqiW|$dgbNO@$!3@v?duyD8X6si$TUb#q|)pP zP(!=8esKKe`yYS&fj>X~^v&z14-WQrx7HRbm?1UN*@=nCsoB|C%rofR40ACzEUxX| zd-4Jr*>^vD`}W1r-dejRlBvw;>A=9aE}4dcH9R;pJT^s%9*3TD!Yx;>6Y}Y79y|d1 z{p#r>dMF>>+g&9m&8;aeRmIF`ANGrj=T4tFeg49wo?iG|po-XU(GHto=#bCWH|{=t zcBhTWdF$cR$9qe)Mu$qkP89+Tt5b&G)Y;nUE}LifCY>4XyFD;IM-dx7Tm) z7Z2_oi8{M`VGDZ-gbNIXZZ{57n({<_GXQ$qK_uY5j zd-oUbzW>q3!l`rl%9YEPufp*HPQ;xSPP3G(mH_;Tx;f!qqUjNv)!oDWz3rXto!z~? zosH!>-b*iq7uJQrtLHA=npP>tuYUaD+3vBqnW1Z6T)H_4403K_d`6+uGkuuXy2OnU ziRPN?`-l5f)p5vQy~Nt{_S^5FseSe3%NMwj?ucKdQB;`Sa$@>o4E@@avym-&<`j?;XE+d8diD zKfk=aQ41O6a%M9Y<@D(2q?Fpu;oG-v-n!M>b>Zx3=wn^o*Tj*#diC;!GoO8W`a;*O ze$0jagS0NCrtP zU=JVM+1&!qsb*w^$W4#< z;`;6Ze-62R4(~$edybI}{uqs#!pZjJ5!cp(2NYR8IX*rHo%iSgm&3u~A%%lDm^w>K zbSiR1;CvUtH+~3~I#w;*z?tbu@n-^1*T~>N|LvRCuU)=y4zt_Y3zsfmx=8Nx^y$-Q z&tJTJ^;-A!-rnmy-95ed@~|!SoHVRX%*q*v@}R_=Z2&!zPe*WL<7egFhl{bqvwnGL zX?f+u7YI9#kF>Xc=fRU_&z>CJKRJ>B$iyRn4vmZpGuF6pGU6wcNThO*+!~c>no1pkyoKJ2otDhKNHzsA4ad?;+ocMo z`n9!fA~yvX;k9BVR^kc0+N^J`JUZArT-rLg|MKy(2YU}+fAuA0wVT^dpWUN2W36*{ zdv~n~wQO&tUQ5-%z3(hlsMkU4U=`0?ml>m;Tn-FZ{j6k=L8g4-*6o2w`N&Amg-iXT zs?pvvr_WrwF*5eW)mvRCqvJhSrbedKeZzydho)zh<8!mq3jMTVYG`V3iaDrabaIqB zYn7Wf0ec$2NFq$l(J)mP-0~GX7t2~B_`t~ zhK#iev&U+Csl}?GQfe$M)p?B|vtSs-tb?78#_(FZK{T(~Xs_ZC#I01Vv4LCN*lhA{ z^&$9S@uE?YSPA|nKW8q+1B^Fu5)giYltH;foD|Pond(K-n;h^sess}RZF34%tX9Z7 z7~~8ptyD^vA!Y*UJR4OB%Aeh&oapZ#nw*)M7{mOE}Ks3K&QNF?&^&w=j%91H!ooQcAV1iQhS%L=tr^tZDHBQ1-iil;Y* zIlvh#to&rOX!@d)J!VzR3c;SYvuc66YJqwx&Z6MmfWmMD#TUV^B{tWT|3Z@`R^w;R zEu2}{2PkEt8k<2QmEuWgtK5K$2qBZ<-xPEVW}~@6!YdL)e=7QhZfsz`!>IZsi9=as zp|OHnwkk}km>Ww-u&ZmG7H8#8E;7MdqqCFcCpiv&J2pdtvh38^EasU@lU!w9h!2sz z2MvP<3=?`9CFr}POBxRt<}eimAFY zjEYfs1j&T;Kci4lff*M>S3Lg_FRCC{Q;ZqApcskSH-0#=X$R7|vatc1p^lC7#2Y8l zJHi^51Vx8)0@o?P5wQ*opAhPjQP%4IoXZ?RRd%%1@whb}ai(GlC!Yp#j@_wH+NKx~ zs&utUtFEamAqjhvrcgTI&AP%6-y`&?(WscsFY7(b?JLtDy6?9m(L8(}OKBxsD5N@B zSKD6At!(&!4wD46lspk3tCz}7M_yA3yF+{#FiaPtYndfT=EcQgxRh{UT3IfIu=4>$tK5UCAVii zN|(tdca)PhKaHR^M?kBKm|Z%1-jlAn(g|C|os3iy8F#R13I%0py9!{5*Q*bu^ORDi zn*{6XxummJsYMq(rHnrnvEmfVfGF3vu_JgSa4l=a781VMoq%?4Zi|Feyf)nHeqfXXY3 z&RJ{Fq|s{}I+btMtut!e22a8dqBM$b!ImiQmYAb-!`LIVzF;;nEnvCe*=e8G7(DcJ zLfPi#^=TDhS4mHg1sAd{>Pb3q3h7-ItYo-5?N(16(M*ZG4h&4dZsTnks-@|Yi1{;h zN_7@jOB8S)G;=gDw92i`3O8G`1%Ya{n2Y8^C9qr7a$7vZ%I$h(CEtt*=y^O7@Pq2{ zSREwaG)g0xlv&&ZCWFjQAZtN3D>GW~#j)!V@f{PH984Hty+XHOv#D$bqf$AKfooyb zJSB&O?&Iz?nUJe|<|L(fVRtQ@tTnTFaz8Gr9}6LWJdjB648Yh;j?_lKOp=C9?!8Je zUr3_T&;nA&Q7yLAY|;`W?6?yX?B*lvmVlUJn?)>2Is?TtnMCYTiJX_+B(?}Y&?Y^E zER#mqWi4t_by}zhqA<`6C>|$`Sx}$iutNOFu&7ciB5;^tY>7KtK%dxMvX~c`0xz>^ zOT>r0E+n?h029G$B1t-(p%V+1O$%uWLzthX1Y#Q-IHV4f00^ag5l;+>1r;KJb&Kbm z&y%2aktC>iy8A_R9~Th!4qO(5ic|>Nli-&_3TCfP`C}>(qC5vXFyjG;J>YDu>~|bt zu{92ask9}qPYGS7grOVr4RzM2w)AmmA-)-`1jUV73M=sjVPLe8XQXS0Pk7RGh-t`Z z@i++FQc|twPQaw3RSQ%U+gJlJE)K5GnD&(A4kglrd-N}BpK3MHv`w0{U^81}GE`!YphakMG7n?=BM zd7k1CCj~AXKW;R?C(2-m*NM%|ZQ&(1nym7fB0luMIDuT3)x+RZuVnnHq!y4!eKZwv zTi|D)?~}M>OPPfVm#MYOAU%U=o-OFbA?i2KHB44~HFm@X_WVYOp(3pY98RaT1{v7^ z-izgtY^lDmlYjLYz@VBvoP1PL!lfb}98NLYB7?Td<{FPydu5doU#3!}wFp6(#)Azm|!NP-v&*p5Oou-^WmVKpO#S`9&oZTSE0&_igJ?(9%KBAl+o`w zB$Ux|4blj|f(%r~4PC|u%=-)H4mN6JnULSXh)oak4JI9zH>DKO3LKayS2P~Cm=CZ7 zOA?2AZft`5I#>jOBaMMrp}T=~D7nixGFXwYFW639HtOpi+fvei#;!G6d9xI-5z+hZ!JYIudJFV;s281rs z+!nq;I6|U|oE|3{OM9u@YIfMg5n?D|^C{{5BXHGt0X@P1P-VpB`U*hi!{%M7;z8F zJIp+@Uz0oveaTb zi2a>cJAXv}H*-?fL9Z37Bn)dV7N9JVH9FGlEa*VyixF z{-$BLW5*{`zymePW9ComIo^hTVf%UO-~QikzWv=le7Ae26JIp#tT39;4qHZLO21@GdRc2$wCaw0 zbn#x}ptJex?b7|j!=tQ<jw`H+t0qm67~G?+vNve{q*wj-8+@e?vvfk^=f3Xov)bG zaBeE#9*Kl}49F8s}zD?j_i*$=+Bc&2;eM&HDhGdISD^wI?_!YGv{ z2~XudrnyXK_1PbP|EuT!`43-x^N;`A@BjGi@$27y`}ME?>7T!O_UyZ_pYImS$6&l0 zIsB!qVk}{nNM*8liTp~}+5XYqOP~MZ{qD2xefZI-)Bn?d`ryhJ|MAcM-M{-q@5t?Q zpZ>+4e|GNb?9{F6U9ww)TXL#i7wW~e-s`2jOzMjc$`H*@=P8Tqjt3k60O?p5-}Ek zzMOZ4s?GIelMvF{osF%#cV2$;?Ss3G<<9?Zx%g#l@{d{wbEj z%Yis`VLn|9`Uvz#pK6-sxcL#?!tLw*mv0XBe>T|PO$_nM)$4;@XHWf{O4Bbs`|vN% zoV(p~sprajr>@;16E`+-ZQewWw%+Ys&?sY!8zMXa*|}BLmy4bCeT@A1<+Z~X>vs;; zcXl4X+|LDQt+xxq_tB0FwJL|`9zB@kNUM{U~9k%u#t!}kyx$4s9 z(t0xxFD25!gsVgh!)}wC$))%(KFM#~md_}9ZlV@lo$Mc+oH*apb@R+wp?_Wb;*(1s zU%ztd+()O*fBwPgzxw>lxoh1YU%!6y*68$Dch|+6gSe~|Be%w_Iyw%6Al?mvEZ^knP>dZ9IAU z_Vt%f?mWMDZ+q+R&cW{e-NmKN=0SF~(kRB$6?iFZ9pea(BCTL@#&ryodAb>t6GpRi zbb4S!u2aknA;I5N%nr_UU%7hw=D^_XD_u8xZ{EH^al_!yjgRO^xHUR_yXV@a&%1jr zbd8}dO;5`eGc%L(lOPopICmUMmD%R^n<W%X=HG?SpTQHupDI?j1bXMoM1W-fXPw?v+>9n~TNe4i{@H6AUA=R>8qIDGZKf zY$@KPpqO)vax-4I@**fjKp+-!DuDt=5*3$j9$UHJX_Cv4`ebJ195q95O35G3k5hti zV{CYQVpKaNot?XI{^~Wflfj!8&Rw|C)qD9;-|)?0%0uN8=olwaouPmjJk~_ii2(<1 zL^1~RJ=$m`DaXlBcT`N}Dy0}Krsc+Jr`SwqiLbT+o}#&zv!E8*_3eBL;77h$MMNlN z);Oa<20&MIYh|fYVe;I}dy>h@N+}H;nptrwQWOIW7sQ1~ z*lgAz#&(MrS6bCP&7>JV8+dxTZB} zLSm)hmK&`MVvtyPm-CH^WD~+5%%j;1vT3LcNiR;9dIqu*JcU>phg!MZXe~AJA%D6Y zFU9dMctY6(*#r(g#_o82shVw6nyr<3W3@~;dbJ5PcnOY8y;@o7ELDoNPOF)sqlShH zdZI!ko^n};@nDDPIb*JgK{{?XPMf?5k4a^4ieb7?;=}4;vij`?n?YvqxI9KgTW2B_ z^-#9PLe0&7!Axihj4jw#G$qgrNftDjbiJOhlKN>MR2M0+>(tlq1F)!CB_fN>zTKdF zvXx0EDS5-hQICaTx}!G%I-wf%<0I2BSn^wU{20 ziApimg`k0ZD?o?{4sI?6uFt}*&F(Z?u@sSB@|hMCn8-|kTjXq7PtqQG)(k`= zHp+w{$N;iPtz@Bi5=NlIJwcQd`yz65F-hMguCyXSfJ&vn_MJHbDqy6>-puLFMI(#V zvIKxjDr95x6bZR~kfw5ez1N7!U{CE9Nyc25O>mj%@2 zfK6lfF`SPpak~Uki5hIS3~kYrU20~c8o42!Ua;rw#h@drH&l&*rn)SM7w)Es{?TMj z+e~`51es;A(bKzW`dJTWXwO&oxn>mnz*=REtZpSlASzoh-b7!_-7!N3u(pkA&1CU-9 z)r34L`^>n(Lp`i&nC?H1Mz2VO%o9e1OXZfw)WCU69+lgnv-m?+QWHgYE8+|-4h7&rw3;S0gWY@Xr z6D|3{OT?L`&#R4COOxCtA?S)Awz!USsWkFZH4o~I+O}j3#6SWBDw;ed4usb<5FSW< z8CSq)apfB^p9|WcFUYu&5=P`_qr;0#XK*Re=(Pb9KeJP1v7=a8ZSxwnQRnxZ2-4{k zqk6l>X%1-JR0X0fxlCTdm_DOVYEo+T1db!#tj!qkI}?_WlMWX*IbOFfo)q+Nzmeb- z>PRSucZX?D98;4A?pM;63O9?Lb_=e2uF6ZH0LPF=XSz~dgEpVfAheYchO(7%s?Lp` zO*HWCEnp2}1`sr1o(jPNp^n3%Wr=R1W)h~l%ceI;6^28)CC>PGE6RLe{>|6f>Gq9r{+V+6D-CJ_AHJY_;* zCJ7Wz8ry81H4{c5jL$c;6${f zviXhT?8cYq4P#R_fJxj5vdbhZixEJA#pfmztk z+e|c&x&VQ|W+H6{iO6B|XR=9;Ol?BF_8F9ON(uE_GgDHGBnBCNSSSA$`z#|PI*e-A zrqeVr@LnRP$I?B@V2nr@yeN2$A&Mu1K*E@KfSIz<*@(D6VGBg2Y$@$Gkvp()b?Ve4 z?Z<4J|S???dpaTO%rO|ZB(l{empv7XQjfcpiwKd7HTAg zgh&n-P%o+Qd=dInE>C1$6hI(Y;IbjFhEOZaT`@kg;EZ5NBMC|+li8%_Wy_ch3@8AL zs8KmDH#oyl7-F+Vdk_lkoJ?(Y@!mwdz{Xj^cNWd((Xl!2Y@nFGQF}{bl>2}frU(Or z&-YV`j(`I!3r&o~4uL^fbST3v+~Wa*=#aB}<1W?AtjvsdsF@$1)*#1XHzc#3tx^!^ z1#?R04^*Q%g{#87j`tp{91&2U9?YHN*t+3U(Gtna9#0xT57ORy zD~-UXSPoG~!McNw&LII;$2ak#mN5Wk8qICb7jp?dzc^D~isFk3WiYteCBZ@4zRnocwYk>)mK_L( zd?b=wq}Lr9A`du+j-o?61LJsVz_H9LQGeq(tYrIlj*ee_``dr|*MI%zzx(Y^KYsW6 z85Xa_HtdP815P3vMJQ2BJ{d4@vt+8v>s#B~+XwfbJb(4_)yt=k?`#V+QGx4*`%$+r z3z+BjExPx*u3fuwwRdPrsw58T@R1rJb-TGmL*?UV5Tw8|QI@wMd}x>rMJt|MIy*f+ zMDt+xje&t%J=eN!kIU3F(z*iC?9%quVx_!%hfgUkAd=dDKwMKgxc+~plmZ)mv6CB=uc=X`T-u4Dx z0*egq5*I43UNt{*`+9dz*VT(u9G*S>$%h|)0`Te6Pd+()?o#({=zqfOqST9mQc4vH zl|~zz+V+7k-`u|k{^;T3M|hm>V#V2Eh7RVUR!HFVq65Zjl?`6+?Vp;N?7Q^YCugo+ z?>hJCXP0jD_jO&k*gHBen`0A>71PC;LFL|N7z1=FY=s&mL~p^IS;n0{DUeu3Z;n2Q!m8+4%7IJevLN z#2DVfft%fzFJ8KKy_aIi^H*;S4EFV0xzam0I^1{j7CA=A+^k?{X;}Dbp?Jf55*}#o z4QBM%O3Rdn0!3S2r+X2f-rfCOj9Kue4n>>f(Gira!=25wl{JCM;%Ia6@`6clO)~cq zZ9>3kv>cMDv2mDJBisOE+6T3=dvE_u+dVp6`a>{mH41&R)ED?vsyBU%t_I z`$o@=A$m9EcuN-8u7Wl~mB&sdm^83D7-fQr!pgV31&oZV2&WtW1E$yG<6}HzPl1me zJ-}25fDDM+!v}oC4FMq&6f$fQT#U#aSTmpm2}lr6loOn3b56|rqHby}s`vT72vgQG{V_;JADQxq1t?0P43C!i}o$9;CozZUA=W#Ah~N~@0%ot*nw^b}RVM%2hj;ci);9PC z``cVa!jQ-xP6u_Q>$D$Y@rB!u$Az7Gxgx#|Hko|0U4l@;)IH_Uk@QK~rBiZ?%PeO- zU^XeI$LIAf;R3@ggmnr3GqWq4?39iOpA}cnpKPfz@u@kfG8IV*to7ikL{|=#8gjYH z#Kw1Fd_=|`Nj@^JCWALWKC7|Wm~5JyPLpCzPHsTd9HoRSi1=H3dAZ$cLyuctMBd{z zg4s?(vp}Z_?f}(}C!{rja4a&0A~TvR&>>O9@}EXiq`fX(O#9$|F_LG21-}I@vp-eh z99Bs`h#L#X5=$q+S76s7e8#jM36z&u8xsW3u}DTQ0jI+k(TZozfuG?ve?m%@e)tAm9Wt6`qGB8TG&XDhWTFAR=BvyF##V^#Q0 zabTTTI9Wx3Cu7mX?_fdB3WUrZGe*JA6OT+dwPrh^5U*YWQWB;-HDZ88bXqko)pjLU^GI)@Dlq#13o#XY+gac@-Sw{ zB%E@Y0&8(@sUnQPCDHfHSp^hF6>a8EUqsAC$!>}EdRWN}Kw% zviY?%WfY}CELaNK5eUQnq)i^x8GP2ztV3q9Y!H`L)x!~)K5uhmB?%b2E17_0l9*@C z}DBfqhw3Rphg>Le9ZF8budh_zI3E+NGWVkvlX6&ACF<615eV(wT6%O2c5ilCmNfE&9|ck1yfO=_V;u zN++k;0HiaeR-~}HN@qZ%99+)Vqh4LT!9vj&4{fegk`YU^xJkQWItNjW9}f zpb&CKxO>caThO9o5RH|{-hq@sp;36P3&vTs-w!cN!oSK~Z`S;mY%EjE1VR0Sgj@4<33lna$@fr1|@LTt4V;+0SS z(4pkn&eI8&Jz`M~Gcm!Y<*gF89rfA-(b?0$tS4K!RBWe~OAue{YqfT<9M5AZS>_3r zYC`L#cp;hedK@OOT5hMtV)l6GO_xwHV^EuwGc@R!oKl^h;2c{nKvC@Hfg92c5r87? zcj@LZ>RJpIolUBf`lopoR zSYOz_5fJ0yMoKG{su;IaTO|koxHkbTQb8 z@PtD!0Ro06#~Wnh@52g(jSA0<17jQUOE$tu!hdjw@})R-3?b&wYeAM0k-!URNsqDC zM%+)MVqt|p90wU1g_plV6X5~KmeWJD7xRsS9+Fhf&%y+^GbXA3G5m6*I4 zLeMGkbKs=`;*YG zYBxNPom2+h+}zwakqWt7bZN7KwK3_56JN{|HiMWH4#Bzr?JQmqkti=d&Oy{K6uuzO zbPx7BlM~

@5qkJm}w6hmb_^DzV|s266Ej?0?$SstDT?p%*)H&-eg@&XJv}i z2j7hME}KMVvn;s)n4+Rkk%+U>OBE*JGUydSvwUi7W?C{oJ~%KkYXFgI~;fAy5Hy0>T*b5m3E?5<`e#wKPlzOu%lp*((4x9y9k6Rd@u z!d^vZF_LSwjw~hufM7R)Sg>vl5n7HThw{EcL>3M>P*QmPkj6lGQ8t87ZPbEllc`uW z>gYm)>BdPUw@7}7*s>^_M1?}B!m!C97S1mgvDnP`(4r)q`;DXmd23+{L;Vz(v6F?P z_+lI|8hugZK}vHxS%5RqgOI|i4L2>tyQ0fpJSv1eA1w^Ylj1G$DIw5O>Oq9zgt))opZe&g!b_gD7sfAz<&j{fj} z{OxW)d(^yC~DU&g|ef4^BwKX~x= zyQQCAJbv?=?;am4d3Uz&cD(wL5sYZ|iNW`-|MIUte*etno?pIy{-$oCZ`SK7rkk2V zaqs)*dvEt&J^T9Wzo!xL%lkh*+1rSkGi5LDOshgGT~I}Or*DsrT^Jr8RF4hyD28W@ z^OpH~b|0ODh022;zInZN_~p{?4&OfcKkt?w?7x1w^K29JPla7muHlJJT{|~9z-4=* z`c{bP9Do&7g2zj;%rXC5=_ zf8+|MwyNs^&9riIQm*N`a`x=$&rh8{-PL>b#;H#}KlMr1%;-?>7uWR45n@VGWdtCD z+~~>E$h5!Y&$gaCxOeB^`xg)1{O><}eelEH#@*jOy??(`u5RR(GD%m`5VI{9^wPO8 z)#SjfcdmZ+pFZmP=;xO&{p^!J`^C@x;_8`emxr%>a&Dv>u>p3?yfa`-2Uph~uP+x? zN-Gba9zA;d{qyy`KfL|@i?1I2{tv(V^*{W}ufO^J*T4Vfdw5&Vx7XIUO6BO{ayj8w z>!!2|daJbO#*L}o{;Thv{`AaefBo~n{P5J@eE9MC|M9>3_y6I)ztlI>{l%$w-s$QZ zR%*s?4UJ#DFw{RbKQJ_AS3Bnva)aDzEFW&J6gR4k<)fG1KWlDoA0K_U|K#!Ot>;JI z-CKM5{i_#0{r-1PA3QnOdc6B!aidXf-Yb|1snO+}_hXT^2ZPpd6k_${q=M>a+tigy zLeg9o<6$!?iMjdV6^2-0An;yMT!I&IhOZ zy6`)F@@MZ~xuNL0)^qN>Og%22w8k-~`yx7shn1KiMT>gMq_tS>k|V#-Ip$$ z>ppY4>;3Z|e0KiR&o2Jr^yeR5z3~2}v!9>4Ha2tf#)a;In}agNP#3xCS%q3Urkm4Q zwN9zQ7s|#mjaBxc#ZK`K>C~0R+Sa}8`wtH8ZQVP3ez^VetK*}igRg)6FTeibho^5| z{OY^!zkB=D({F@|{OIs5X03K-rL|w)!@X6;-?hZ5Cx$^F!vY~-w1t%{H+kr(Q@-;H9>z z?Tv?9jh&snsh?H|vQa~QmYO54;=n5*mOQD!CGx2n3XH_roSm_0Ko(;Kvk zvGJLy`T6UgbWhA#<=t0q4)=`>%*!c|oSPYix){qrhhps?cO|Q}rCP4FP1_mk{>6=L z7%Q7A>$Eg(-+!{Zn4^bfv6*B^C#r7hL?eJ2KxkiD-`^{QOSB-yHR?dPorjI8WB%?8 zh8a*15n+nm%ooYH6mlV7Bv)%<4rGcM7UfHfd=r^8?@$^AS>i(~GCAEw2ir@pLq`lF zM%cjQXLV4Bv3ZeBnGh?LDyr6pC&$6X>7mL1ua#UMlzL(!rOMXdg@zOoO_@v~@dJgz z=^(^o&>yfQSZj(@UC?HcYt;^jHD**Cz+`5I%Kl`jMi5Fgck0w?V?5(fN*o4SgbY4! zjwOr3ooK8quXHx{?{bZ9ZFaWz?jCG+DxBTM+9rs&_7*dp{q^O=4lM))99AqR2ofa{ z*$CwfEN#5ue5F~-xb*mGyr%i-d81dW=Qpt#97*n9hrWOhjXl#QXp8!D( zIBJweP*p@aThAEIVkWEtWZDF8i`A=*DSHeLkuSw@^!QRl=T=KeC=ZcXz-T1amW_w( zP@-9(!k`XeT?i9AZLcgXwUKK(P4eiAOAJcc&Oq&OnMj*Qe)2g-L9t+fjv3Y3_uP5fb8Kg!eqL{7A&5r5^rF12`z^Z zh67F?VKNk|Sh`3?mGLDbMr?LaiXy}=*T0J-m;{Sjwa`fu6%H?k9maS) zS9B`GVv~%Z$?Qv+oU)rhegdi>O-m}NM=x>BpgwdD01}H2>m(*?!K}7U_|zJ&#A8%@ z)OchJQKx~3l-;`de6_vJTXR2u7qBs?lj)OSauXQ!edIE(FWDV9K%UXxdY* z^{h3aNo>@@4Qr$sZ`8sr4@NVmBOeSc-pdftYCb8hY{p?*h66EA-KWW#<3_jETCfMr z3v3ahX}eVtv&&qLX&Dc%nZB`U)q+N5Rp@T26*-+nVsR&Dy$ktTusv}ZZ)SuBLt%f&`v zJ2Y8xcqA{G2?K=%wo0_tQHa(uH%p;W>staK~Ict>R{E9*4m>9OTbPZ zB_464q8iogtWoE4N>RosUb8H?1BM_dAiFyr1&N3&E9{NB9qB+en)6{EuC_WGD?6Kq zYmK!Pimf~CLW>JML?>U0?VQvFXr5b)5@vR~79V;BXdo%fF@sH}R~oGne7#mQ4Z>zF zC$sIC3#=MYFQ-as2NJh1tKkVr=1%NBqiz~60)QdaE?lrSrCI`x%}Soj=OmYC_xoc$ z9IX*wBo58Hm`US;ig3SC{SpV0RRP4aUTi?gC(+-`6Xs6kQ>A)5Qz^FUi%Xrw-D!Kh-#7k79h}&FP>mO56RoiLlON7|C2#@2%>(h ztq`m;`5J|u37+KS(2@KcUTW+?jMI%t_>RYq6FRf6!YK+MAZw!ctW92%`xz}c~!F7A-uV|)M>(D ztTz~{0b#>+V+xm(`tey|6X#)~)&{akrxypPfjlxNMGdWQ!S1(U+xK%@B=UF*NWWoY zP6oM!@in4x0v=-t;lPLppKLdg)V0L)2RZCt_yqVSD+5oZAJ00NzLxCqe(e z^~HOd-zRL1X`qOBS}Vnp=$I0y`mktPu)}t@CX#OTgcOu5)_x=C6=uyQg94nAQe#jr zOb$&hprC>ts zPMrhw@v@n*;bA~vAeb(kJ9p;H`K!IR`)*M*X7vGbTsvH^w{|hP93OxA=IPOs*DvmF z>^=VS`8}vg`)l=5xgsn%!pH_OMm{|`J3rok3lz{CHV+QI*&blZn*(!F111H;YjbCh z3dl`r?zT79XeHd=rDY5g0;;v2))NR;1ASd*Kg4o%>VpqXef-HMAAR`V2cKQIf{&*Q z=apy~6tE?!l2O0}im2og>1Hjg z!z`?m4B`CgyL|36Cbd(aT*OXx?i!w^TYb|&NqKm}uQS^b#Dma?<7s~WCOEYRM~|OS zo(PZ(2G$At3i$%e)f%phw(uqu1;d8-f?L!Js+E!{yg7rt7d}39>Z6Z8;#++B>1Usw zdhet2s8v_5-@0|HZ)9B1uV7$J%y0o?0OOHJcP|&Y=;~@oZ?=J45 zhmZN1Pu~9OyT{ubdq+?9>)CQ=tsb@*9Vqxb10V^o8OKWupIkzsqx`{ zFmqSCdPI~_K)rgpuMdv(U;g~_%eVWxKL7aqjsEV>-g)nAZ~u*}SFR6D%}tMu&nanA zWR}RBLiE`JI$~y0Y2(^~1hp+pJy@3R9`0`M-g$s!OaQ%hcK7x%{@oRSu({#G6aKP& zEKFM)E6a+K{ zot)>-@aHV8uY8m1*L!+zff}5W$mb`9@omcIC&#AcN*RiVL?>XR^eWRx&GG>TC(I1+XQU0hmP;!@mNzqhx2Z|mXy!ISOBLi2lge02OJB*eGRjvu^w z4J7X2Gm@o`b~@X;2mAYtPH~y$HGrXs95EsrJP(R>c%3K>a(B?Do}MRy0Z;bZ#_V6Vx-x|9=yIg@H$FXJ4T zbW$BIERB*Ef*F?ef(@3n-4%(tlhMjzC*^k$i*?|=Y13^(*>osih{dwu9Jc_auK7|6 zUVC$;S;7C;T3XxP->7ddA%LxHuXT_jRtv2)+*$c0AYTk~lldALkO=+WW!}7@a3&o} zG}>88(6R}aOliiz4Ty`r!ijkSVbz%JN`)H7zm?`1h+VAsS*65yh*&)=w0WH~KsQ+h zXUYh2aE89pd4*JCSWwK*&CkqIK%kiC%W9P7l%KL~hs!LRmf28Xq*ASkcQd;pj7esj zM(^guiSwvUAg{huZ`9hWo#qnNj?^S`=hnE{S61mu;E}W3q7Zlqk~to;bfFHotln;6 zl&g0R?`;<2#bzT*p<1n)ClbPX#s~nPwYH7mB_8iM9n`5Lb20o`49~FL^NnGoVB=sC z$TE)PsDW`fR`>;(O3CngPD;#LsZ`4rq)NDV!MMku(Aiviq%%G6G6{}h9Tq_0Lvsqi z2zEP9AjM5oF7t5bs%zI9>>;R_uhfY$z*<4)6Q(#YzHt_VX%Y=s0r-r<)DANumRnqD zF#OJy!giz0j|bia5`)P%kPJXN(Ef4BBLF7KZL$`C1nc<7ictI62BsjG@zRIt00j$+ zJAxBlLB{AVM#1b6alnh28h(LHCF8@U5^&?Z0rKm!DP>X>_axj%gOxEf&jmkg69*=E z>dT2*@IQsm0PF*^I2JE-M>6?kfG1GB%w$>7;8f$62x}QPJaO7=wVDGU%TfrLJj_Cp z3=iqWR8$0++0OammChpdU~9X(Tb*UhkGN=Ydol@zfq^Q@1BsD2&m}+_z*VuRMFjOs z1S)wR@(<%@rmKP{hn#>TOdxYiG^xnAhKZ}GIGsw3K-Cz5aFHLu0hbV)|d0;psUfr$j!zk?_1R2f!U~f;%RrN z5vsJkoaVGu9hwg<1Y&xXZqlrFXtO@8-s3Q))GBD;cA$XrTN;ULWE5AjcT{bK!Ll$r zql`*ICb=&aTXcu>Zii13ZW=rlBWC_`Uh3>5=tIq>YJN+$nh2)jWkY1ym#fz@2 z5tzX3L}4YFT5iY7crSu4v+3}1F6|200%2O?^8Q(iPIv~wk)l3i?UXt>+D}@!NM*?$ zO$S=V0FEbb#2wGXOCFjd0t zV=I#;!JVXa$1Qry6IQij+H5c@lnR+y!t_UHP|9HHIV}=aP+XlEa&r-{-K<0;GEz&Y zLI<&{^&0R)I(yhD^=qR_kB;e)SLLx6+}UJ`1Yf~bsDxa^z8;rzo=hswwv1j#hnqJV zyBj#p>=T!pwUr$#sm;UH7DnE+dToUQH+T}YMrtWj&DHbGVu70ku6iiK?Sbm<$`5lwc^ zU>r3jLs~Cn;UK#(nj%n`u!o_5<;_LIuu%&~L++TvL#n}NrJ*rOK`B%%?rc(a z4)|>7YfgvgeoXViKv8metYo<`NqYoWk%wVQFdu@kR2<}BF`dTu$&!-FG#jdn58*+8 z3n3tjH#){R{+>CPm8uUuqR|?_eT5s1hpC?DPTYr?5HbKp5T_BNltydSS?MOg-i+Ui z5=&kb#X_6M3UtSOfy6qgyCl5^==sGH5K<2Je3Jg8I8A~0A_H)Gq6q;T!dStR%tbhg zK5h(cK1^k9uR~A!0Z&Q}djQTmczBFCVKVI;y0C{ylMhzCo?I5Me40;Ll9;qke70;l z%yiMNb3T1|S7g$02^EmLz~>;U9&jRU82pLp}I6FFf1 zJ2{d;(P4o3CKVyHNF)@2FAVU2*H=8nZjI(2u0Wdh5*UJ_Vw)czTZSBvD4|RdOJ$4B z>x~Z*<6Vh9VYi?*0(m3A<8}p*Dg!KEc*ny5Ndv;fhesuY7+|tBbrWa}yNGm(=02=} z!V@h@uc=^mIdr zn4dja1^mY~!D#^v2Bb}lqk7h`2b@Dpp|PxZ`LNRp!Fa z$0w{$5$ivOr8YVZvC|{-X&hlMnvA$>!P0UBJyFQ^>|lt=bKKxrB*{q=%_MwI z^A(2pHi5;(#X3X3auFw^s21Q+!c`s(x^P&zZ2Uf!OKdu^u%YYOwKur3!#m%5)ugmtbwdxg=CFx$~+L)I&Lbi zH0=Ar`tA?KQ(PFRJ*;_%gs_godl+CR%D4tgd%rhco%96R50AE;-_=6 z!GOCl@e(H?6$DC6IO~xY`Gja&JRU&CA;$5AI29xfDE;BV!-$ZurU(x3pLkfcArPW| zBJLK*g`={8!G_Z&Ol(*RX`Mi=7T$b9;39_1g~{d5{}Cety8y_F-@(hn&IOHrCa|z! z)^g0m1-_Y5bKz1G7lZgOQIT2Mip~dNi{r9+VtSb>AMyt~%GE zc~4%Ki<;Ie3RVP*n-%4ZrQQgb4L5uH7I>sw``|O{z|=tR|8Ty?I$Pgc3KTXEzj?O% z=70J7KmPsy^Kbw4=&OhS_um~gHyJo}hAv;c{>imVLll}#xQs*UP@&k|4z5(5 z{_ck-zkB@K-@N|j@4s7lbbtTLhq-3R$m`IlnUKtn_Fo=WobG$C>*D*Thq@=GyRS{& z>XT3D=Zou10J*Tb*A|CfW`zH0AP?mS&u35()}8~s;w&S~k5Pd~qO zMX%7@y!esYacye2w|8`AQbO6zw70g?hH+NhJbd-je}4P)!EgWmhwq-he0KcmH^2Jf z`;AWdc(I<{3L0XtG;9j(*x0a4GtiF+*7eT&fAj8{4=?`3yZ_;@{_2-!E}#4SZ+nKv zE=|b>6|x-WX?rBqh84cQmMd($dV1&H)}w>gAU9 zagk`@@!PLn9{u>;lcT@;-T(aCZ;rqF>FrnF{NblJFCM>r{(5I)|K;jddpQ>~MV2x? z$AWy2?l`^d`qZfW|1arGo|{PTFw8ZTOAe`Aa+#W{q_Px~VORz#lQ1w~FlG#1@Pe@L zrp0n=U%Iul)|OiPZpoHyd0!YW7#j?OO_)hCOESq}Du?_#d75x?scfW{THW9G{@(X_ z2Oe}@`t-`3&a>x#bNi7{P?UMh zro`E62Gb0*7B{w^HTO4`j*kEJz%`$ zjiXoJK54J6?QUjVHRZ9-N>p?hJQc z>A3pf(Ln!={;sY8JzHulqtnASmp)`q`anL7iP*G!FtrIHr4yOit=VjI@ARPg;^q3$ zlf$*;r_2BT?$zs^g^h#5)9?Rsba1%0|8#r%`SHoo)0L(6@#aEfAyJCfh~4K3Na1=0L z$D`YKJFi{n8@VxfSBOtP(oLx@((}+0TJ=(Ov0U8PI9O;mo9)BXllH;J-pTHp?_T`( z)jxmu&)ct0zkT!euZM5Hf4;lF^Wu1OXXDLRZ@+nUu)215y1jq+^_S1uv-Q&KT&)tf zvk;3*L7QLj2^KtF&dET4?YMRDf%&m@==0BqdOqvx?(HA`%QFQ5PD#?24z+=7I4Z;(ProoSSII-}mmg&B*8D;o>aVH*||R*t!) z^&G6XrPkpd3FD=`_U_ivo1J~adneDfj!yOtU#uRU{BUyma%X@2=+)m(PLB>>KHFQK z-=dFrdz-XveJewG-d3~LZnb9^0TvgV1@4$Jn^gpHWb-;Er^g0N4(o{SZm-1-4F0iR z-#x1DHR-zghVMV<<_zfW>DKiiQ0g9zXu;7TBVDfp-M4yrZ+7W!_Ydp($9wyFhl~@` z7Kb%JE3ef-aLhZ&a>(g4h`^Xw!2;Pz#!C4t9+s7Sxw+U#XEcQc)Ah<)Wp45GkVx7* zIp>|d{pZK8kGGFrzS(`cGvD4m-dkJQ+@>FD9r)>!)fJ#!E6vs7BGvI#mGmAR!vr50 zJVew`rsSF=pJf@h7#!nz{m9Ux#{;*z?mg5IfWCicpr_~2#5nThqrslRk#4bNAK3#?IFM^MjXr&t^CG_c!O4H`aHbe=)m0 zx3GG!_Wa4}*7EXvz1CW+wrUZzLA(SeMl6mtGuw6G1TlQMp9++`31lR<~ZHEwa6 zElzTTW@pgrM*E-;)J092*W~oUc4h86h07X-j+ycA6l8Y-Yc`MFY_m!MD}QMU%GOZO z4k>nARO%tS+0D4!39&sBoE#PCo3hcO9Fhg65~bWT>{FZb8MRc))j6ul(&kDPT1jI|w9S+lJq%R~URvq<5yOv}9QJzVu)npy&e!W=AtZgnRi4rSCmFnI~HARn`8<;UD zW5p|42*t9bD75BL1uXl}_)Lf{;38KxQ(yA5_laSgnYB>{5mRKZ_$Vr7s9&1xlzAM`H z!sF-5=$4d9#9`Js&3?h;aE}pje@sXeYm`}-n3xv*l-9B$g`z{CwNzn*n@B`6In3(` zO5s576jItW4fGJMthmUD1aM8HyfXmEjm54uh0CaO4GJY=jDp$DAiRTO3pzYdS#T;+ zT?a&?MB2AnY0NMUYY|0d)<}c}q6#J2h=p^EFUfVX>eT#j8HLSohFuJ8UYH1GN>o`9 zd1Q4h zdq@w9PFAaaCv#q+HVi4@yaq&xB2yNV%+XQSh>fWLmJkC)9~2iki1!5u8Q}w^NR8V< zYl-7P0bK(gn&mw2v#t zMnG6sd~sLA=2E;Cg3m>sC_W{4l|a?1NMd%go?migZTSKxOOA^W7m z6h%#OQMzg=LZr*3j7G_l3^`SMxMj*NnW`x^it5tz(oCq*a<%-$r3rfY7E@z+cc`T# zc9dE8zVYZ6^ij%%FG_}XV^Qx;Ce8C1+eoos!!?yjE;PeyQaL+Uc{1O6S}YUAU&+s` zW}d9iVVqk6ncbq%c@`719GVMfY5^(k7AE}D^7L>(C`htl%%euU_9SzbTEJ(E2i1=kfIC6qG@i^3=#jg*>tPZ@Ll2h?0P8!LSVidAh zG+ZbIY_gCd9-2sXQhWpez{3G`iUr1u%N87=9m!y&OwczCixj7^)dv+S=CC?MH`s0;^U!d}O+s z1u~O|+Jo>Ew?vbmr*4Df8|h%+UeiP1v|rA_ox<;OnHD@)-Z zVhp8{Y%L`*t@!ZIg={X-OFJ)l-FNbg8+j%eW})W|z(qn)qEIaW@f>6lH<}a{0U6y7 zt1w55kwu%IAyGRC;*yXAgcrrQLv2E&5KkAeDax^sI}lDqiS&njP?7urXFx`lkrXBe zY+YkP5_jno-r8gwfHr1`SuT=1kcU)Cln{baF_MbWhRGf$uC5z-Y{-NWagyL6NoZ22}V^u9y2i!zfIOpcr#H zY7>%ln0F738*x8EUKsYgj!aVUL|rDQ*F}}AU$mIfs0b87cjAT+M$@9)M^({UqX}MQ z1)mP32x-hR+FAmBIP)7+F?!5{h@YBl0jvxCDD}>r0w0hvy&Q(6b%nbA?mXg{SCshLdDK7rq=kcA;c zg(4aTX-Hsp>9W@%g(l3b+^EBJQAIc03q)CBuBwK2fYh_vzYI&lH z1)hZLgvuxOPR2mWL7yVFuK^OcX>;jeT%ZA~Z~#4ptYlHndOF@+kUOAc8s+m9Z%yaE2nK zjKdla2o}~EJgs06SYo-U!(_hVWaZ(P;l3-HL7PS&QhwQDrBy?ADU?eU?!j5>Dr$ku3iyUkg??yl~Dg#A4|AC`ZiKvd+6#zMs z4;$rH`;3vN;#^)(^ibO{oFbwTW~DY3ISft*jE`spM_?GhuIQoA(&geC4z@#cyLf?4 zkQksZAr#Z#C2X*1eCEB^&QGoNlWP{x4J15HD3(AdS=t3jD;Z#_fu04QgfpMhfg1`z zaIIqtVOK&K z&t184`sf6E=1scKsDg9<2om$!3N`lsM<-=BDPA0J#hd&PAz-C8;S2<(VZJ3hti10V#T^ z>_G8iPZ!4!kK=Ez8uB$5aI`-B*Y`C}ZrAs$aM_qy653lfNbEQuu29)Or~ip%bkRHp zCXNN{S=w?8wIO$oCyPh!1ROhz)PN(=xu5OXF`I@LGJQ&^>bP0l+XkKsf1F+ literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/examples/data/liquid.bmp b/venv/Lib/site-packages/pygame/examples/data/liquid.bmp new file mode 100644 index 0000000000000000000000000000000000000000..c4f12ebb708473ab81cb08621415c366d30a87da GIT binary patch literal 11734 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/examples/data/midikeys.png b/venv/Lib/site-packages/pygame/examples/data/midikeys.png new file mode 100644 index 0000000000000000000000000000000000000000..74ecb86b8c4d75a7cfacfc9361264f317d1122ce GIT binary patch literal 19666 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/examples/data/player1.gif b/venv/Lib/site-packages/pygame/examples/data/player1.gif new file mode 100644 index 0000000000000000000000000000000000000000..6c4eda74e953b1647cf7734737aebdbede177510 GIT binary patch literal 3470 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 H5^VhfMy$yf literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/examples/data/sans.ttf b/venv/Lib/site-packages/pygame/examples/data/sans.ttf new file mode 100644 index 0000000000000000000000000000000000000000..09fac2ff94ae92033266d8e021c22c382bea19b5 GIT binary patch literal 133088 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¬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

`bqx)glFU#MQX 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/libfreetype-6.dll b/venv/Lib/site-packages/pygame/libfreetype-6.dll new file mode 100644 index 0000000000000000000000000000000000000000..16ef77711fd6df62bf4d9134fb126235bcb854d2 GIT binary patch literal 586240 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

6r7fo|(&9N{nDD{=2saEMdEUAY~&ou5L>C%t9 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%0DV|CbwS$1;4tn+_t!32Vl2!Ai)8K{`>=`Q*0 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

  • TT|!6KLpf*{68nhom?S{;s5XCdnaeHpZ6wTO(ZyZ@MOWs z*1UWVbTaj1Hi^Nv^e{Z>tf%1Q`IA*Aub;e&>7f~yFu(bElv?K(6;k}>KETzGL}Bg8 z=Xn$JKFXV$H$QJ_o4a{R!bb}Rtui- z!dlF+YE?O1Z4k;c%Zme8;xEXv&)bscl^6d16&=MCYq?CZRyFih_1QqLl8F3Z#v_mA znp5cAGyg9T7~x2bd=5Q#=!5hx9eJ&J!~bX{Ezd)@^6t* zxP+}kzEJjPcnE@S>+_f8Yv=3do8(*PZ^@UIL%eN$1ss%DUkPxa9#>VbIyUvAI$Y1~ za6J)g)aM`1GtN)U&&w~%ugz}(UYvh8A3UUpv*G4q%CUn$kP2R7{#lCeJ!_%zWk8_RPZ5r7?S!NQU$O6G3RYWETgf38_ z`BA}R0!1o`l(melue9J5W9z$wcl5=_5{0nw)O0+ljliN$EjaZ#X3=GsMQgDX^#I=V z3azeFT>bwMQl|z+b3&%;X4?AH51ooQb-1g&9jwQrANCVbFCb2O40Q#_HMQBb{()F< zs^V1Lsq3e{p{zz*vDL_#b_r3qEK3xS6Ey4z!MeDDO>{h2_pE&z%_OKZsl_zsfDWw4JeYDfJy594k9yF zFe=S(95NScOSB2+kB_y*7K zk)C0YhnT|*g)n7={}b3cA-3kd$6fFQD2oE^JI$_t6fH%kSD)S>LZ^*STQk%8kP`p4 z2gLH5PrIBBKOIlJ7T&uL#q0fDMjz`|2dS`#`ilKcH3Q#+ksbgSs)8R3~Z zX8;BHjz4|*^n=r#r$>tB7cDPJEXpdXg^xF!{#F%51*u>kia0X(P^@AJGx0&EUl)B$ z;2|GWq*gQ;<0w6@;Y&s%q}3{Z`}%?WBE2G)BAEyknG~&8ku`leHZ;DfXTLE3sz6i} zT(k#&%YgeWAMOvsP*jv#RHBN(j8rg~H#8kw`c-=62XqJ(-7ET?a3ln0g}LzSQ4x6c za=Zv<;=_?N8`&*bepLw6N%8vS@GxN_J^@>Hmp85RD>NCbHbX!151Mfg#PjqJO znOy{-j75!SoX)tN@nLBcxzQ*G#*Z0+1pP>o*BEr|Ow5@>Y@Msw5_bvt6#}bCoiv&X z5nrqyw}US_bLGrU*0Qye^sn$zpuJ~)zqJDDP=DojxP&)IQjHO_8e$0Layk0)oRbH)Qs?l`;X>^h|co&Ef* z0TJlIG=#9Wu)c+$c9hCT9#UgBANTaE*V&-65ocqWmy)Q~PheZ0#P;-T#@Q2RPcvn2 zP-V^8vNu99cp+yWl+>4ed4A1#pVDQe24&w?I#tG2o~+tlm0#Ul{q5!W%iq;R)WnF! zpY1vO?A*k2o6h;2i#V5duKe5srsi6LVJgPBp5t*84iXRHxf$m)&Mi8(>YN1zo2y7b zs>_|nH&;eM&U#hI*#KPgoa;Fc%r$E<*W~06a$?83`dmC`y!Su`Yxoc3YDg~t5t+|g z2Z`S>@FdIl=Vg!b36TEQa}DR1quor;G5QZvOxocHQsKGBC0ZrACEg{$a6NGDWeFq zKVoH_2X9-*expFO3t_!F|H=8!3G3A(96-3812zz(ZVpA~ZO=R5uYuVC{0|j##OHT% z+8~pRKOcSm@cD}KgBM&bgk4Cv@aKh>t&oogun~6hHh^zsoj*_Hc~@U?{sdS+*sO}* zkg_7LSm`e~fA##A=kJ||unY=EtWa5=6{D7CrRwsmA`{+RzA*N}^a~$dn0I0M1+xow z%g}{)FH8Z6=Q1Sexm*F#&}F=mE~_H@%cGF}WmbQf&IS3GrRaj&1r95SVo;4MyZGxb z#Bdh>KCs7M$hy$f22o{jI*$H@!V4EJ)Z$*w;*j)Nv>t5JNM9ES)C66ktX{`2{K%;= zuQwE3czmIs(FtlY3ha51zBq-abMfPg3od?f(eC1=i#slcUrfJPb+PHuF4qf~g zf7pwm8$FcBrI_z|QSWUtQYuBS{FsE4JAe{glw9=3l%NMw0zdFaxw!A*0oGLHg{?%3 zWa#42izRPai54;{=lz^<_>eUT=>(#ScP`$ibPl@#j$ZupqLMTTrBEiJXS5+`7sCtG z!$VQ2uyhIGk5c+>DRul4taI=bDE+u}9#vHw?T>PlF!J8FKMzMAew!w;rGK@H1f@x(nWdGb&3L#S zASoXla9w(`6gtrQep`!?)Zyg?GZCROzMNrGurf zE(u`2z|m3}-Gsm4ZBLcH3iXmp zXX($YmyC!Kgk_hmU%GSY&r6+`o|TPVhA#c@((Q7P$jgX-%h9D@F8u~caLPb+QHEPx zrn-sCMs4CU?#?aa_Nrcn$`+L^2Pvr!lvQFmzsEmT*i~jwcDM{u8f`bqFfkUKRv#JwO{3uRbf2;wPWcx0aUe!MBzIXP^hS8DGE&z-1@PDsTm# zmND_aaDE|K=aRApT)`4j{ShM@SN5=ceEGEUrR6r|j^%C@6FPbzX#Yl8S6NTlFsPBQ z6La7Tf4hg_To0v+3^KrCA!n96)s$;+sL9^$;UHALs+{q>zDn>Y+~li}M}Sa@8$kP* zo7ek7)XD?O)5|N$zbpT}{Iv*`hn2^v3NE24g3B~e|CS#sFXE_w_i@#~o<69&w){&K zUG8pLQnBa-DFdg&Shgn+l|L$n+*@ph3^jPp#1}`YYJT@d9O7wLd{VKz!l1&XLR7K4 zBCDdN;zq@H6@3-YDiL1Dp3G*Zvxg|=ODe41CWeP8V(1I|szO@9ILggQoT~(;+iz+=&R9R8k1V^L|Gv>P+(E2Yczh_7?0m)gCWXmqC|*?w3^+6)SZ_S zgi11@s-fzus-LQQtNyK?S-rU0y4s`qc=dS}H|dK})$OV~V)=>|KlzFiSg!=GB!l3c z4JVI5&O=}Mf^(oD0F_*h84-qGIz+wW6 z$3dW$)K!8Q)d*@P($0>1Ad7e_*jOg8yJo8os##ED2r7OGUDnks<7}NMU?VgF-`E3o z1|l=G<`f76FrYMpF`BV8;u?SU%Sp_a_cQj9-(U0%KWkO8sR;Lmrt(5-YHFKmf2#AS zORjHdv}{UiI?;5l`J3jp>#MK#+$g&7ujrkc+cm$`bk_{lPONpQ^{I`kO|Q*nX8bf9 z4^;C<4TR@BgC?DZH3j{m-FfE&MXq^S%g0FPG^WV&rGnZIYUkE2t+m13(osPz*JY@7 zMXi~N4gAdwYy;n^ieXy1AP{Vr)2}F&0yWk~aE4Jn^h~LQQ@1Hu#w1M6Z`lDN3~zpeoKV$dNH1i?}*iE+iL%=eOmjn&Y;ej zQW#69b0yAVNl@IWlnUz9>L%CCu3L&fp1|$zt39eH?bTkD9=-yBMvUs#)L9d(qD>`U zA&4U%juCsHI`6tr+6_@Y2Tnvqb$jaKu(;?$ii`3&ev(8n1kPGb#GMW?)9lr?#dHo z=*qM!^Hd7GIf5tHlX958qJ0H$2H{jff9!R^sA?wop)0OeqKMS7Ln3s=^9tk7|A|Vo zG9~Cr?3Gk*T-{N^ulmZ-E5)i`I6dkMliu>HW)7NHXnlF*XU^)1^+i`Yue?(BclN;n zei|BA25Ck!3DnynR4=HX3T9M@i^oeU|0!ffgEKs6NP5m+Q2$x|s`|C{+p)b(29DOF zpvfnJsD6FD6NLt%Xf%*Uqm4*7wE-1}#tQG(ht?<7r(u(vZhbUf(7O0@_aS)|;J0nXy7%>W(YwMMfw-Op0Dq% zXU_jC!h3#!FKSS0n2eW=mdgBGAbjy5JU^7*@L7XR!$u->v|(j~G0DXUr1ShJ#kt7q zBNPg-9Ths7E#WtKHa-`B2NOT1)hqDBO(bfK|FYws=5-f^5QxS|7l2qP` zYoAWE-r(Yr)qT|MxDu24%1fuO(f}X0V}}7)t{4WawJaHNY>Uwwop+3B+>H_0+dr zW=B}z0J1G!dwT6TH9xxmkX`$?QAi302dRM|ffTq*g(!H}8fPkd$kSFv{-8H;Fe5VX zDyfloWTIm;Wn&vRH;NkXHEB1QHH9?Au?RxsgBraWqZtIz+!(?kP7394sGu>av9$4O z8XgIFyf$O8TZ9W?oDCB~xUFQXnf1dEc9G>-(LrnOC; zN|?l^4NY4yrOM_~s_cGF61+eNO`=I0<-Zxr%_RZi2otdsz?s`k0b`r$np&E^Z|ZDz zYxZq!V%1ABcC@7|#`s^;@0@{-^XE79H*aiqmI#_&HXAovHrqnNT|u*2^StJz&DzT6 zL!d-zey{nXPEZb!c1S`eOI~y_w;tnLo#50*KI?c)_~MMYI@kpVh{qFYZ^xV^9NObB zC|^XRMW+MjCl3tuL8eYZoz#twwr!4WE+EiZjMlW~l;&(&tGS&XZEzM{O_|EHrZ-<~ zuBIRFU?1xZVZXEK5Y*Rvr}-gBW3An!?t095k`!GE<~KjN{?7H8;L;9yQXhqeX7jTU z)cntNK53!;8%PycsDFclH2UCR<>!>%JF%P!SS`&Rn;+?tA^`>uqo%P>k^Lb^GgL%-SrkyI|I4iI>D<3A!G9J&I*-mIIOm zVfFQt>&LGbTras^cm3;S=z8Y$qoBO12IW}7dt>~K_ZVW9M={E|K%{Pbctah7<2+2H<^o#0vGRuD4VxQq zz8wWsBf0$Rm6t02dL>oiU$215@o$9Oh`JHSd^4Z=raJM>q#K#|oB8;g>U6rK{bBqY z7jM+wxWg`V4|buq+_=eE=rQCPK{tN8@t7?wW=r3=0Rl1O{T>jGT7)hB64WxGMZbGQ z!f%=0GN%Qn`kn6+h+5{iETKqdG|kd7Xo9$>cPNtIV$rg`Wh+e!<^yS?DYxSqcy(tB z91KZt!~OKDxdAD>*)b67s)j`@(L4BcFM6S9} zFrv1I3NHA5epRWY2x;bd{?9q@|D5-IIOogfTeoiAy36n0s-%%~7TId#c(OFmobS~_LvLrWJmauP3)?pD7pd3woq{0I)!CXn-FHSo+BWm+ zDjSnu?)swGw&cqt-xy!sI#6v}vTw<6=0v;C9Qm9Q`_eW`+btcN{1a8b3ft0Cmv&Bm zd+SU2_E!DUibkCQHK-8*_S@H^wp&clXna+Ed8rx##W{dotSvncXXL;>GGw&2W(5@OTRO| z#5Hc|M@uaaaQ!y*O_kdY`GMY^srMR3l-nBe8~X3ywotxsGEEgUoY8Pr!-WlA{Xz97 zSmOK2)MUEA_>#&sAzQ=XhN1HQ$Jy-sUfyO=@?{>rPpMUgoeklJ2@Q8P{HcLI^2mZv zpZI`6l$#C9yXA}YCs*EOU)(UK;njvW&00^fuW0yN;@e>Li4SexpV(f--+0H_8kRR~ zNZsX}qF?ep!~g>|)*w+?VRjo8_~`wq?gIJ2ka# z_D!vue_eKtWfVg6qWl%fwygIu%R?{!q5poG<=XSA9spCd(6VvMDibj?F%dA;)y`%2 zE_-O%>}9VmOFehyeq*NOvPdm^df8kvRPQ(2kel}Pt6r&3Pb^!z?4xDdlPl*3MoGO= z@A`dU$@|;#tmSQzdEYnk_Dtn{fBXzJe)$E ze$N{hMt`}`yjQre#J2p=AZH_{!a6ZeoLu6@@FxS4>pXFr=v;Wm9+sfNkPL*%eMNhpwag)O%$ye5{d?Ho&tW@Fq zCOoJntZZ2I>Z-R_ty}f;>dRO6jdzY;8^0+&H(nqASNwzcia_?ttt&rU`PIrFSG8Z& zW7U9FrN-CN?lM0Dc>eXNq8}V*Tlwp%w#g;-+f~_?8qZ0rtD}rtsa2g;ou4}NPpMjc z!>7{B`~2(1+g1%(HPU!Or>FgaANYcSzL3htgpKdyAM7^4zN%`~?W<;(Q8&OEbqBw( zJQHWtJGr+mOQF?&TFq}C@NsKTo7I0w^;&QJ1<(}FQLE>r68jX{R==})=Wc$L zjE~B6T)Mg;@iPkil7zgy_mvDCUwYH`M>{s~1&`)$^{;*u+gAU$#-;D(!GXpnB|E;C zvhVB(+SasN(`)Cxb=h)Bu{u#2x z&x>E0ng_MxZ1F4O1C!CwoQRGB%YDLi6^?juJQAM~e=>F8!{!8<;@KO&(=zSGmQQj2 zE&h<@_?`S+B=LS1ucP&)<263?S{yxfcJj>_+rP|Dd_HjC8$N*lUd?@~CjMo7Z~V8l zuC=GFJ#TH-wO6d|ms*1_PknyF_`xwI&zD8EwRvlgPtKVKQlA`~@x`vxidYtk+TXQQ za8#mJ|4dcq^NA0tiEAs@U9~Q-?!Lz2#)`&hW2|xIhGiSR+wj}Q?2V^vvISbLow4>W zYoA#=ckMsczPWbY+K<=S*X6If;6R$|1i{rWTc?3D4I)({DSQro(d)^$vkb60A} zK3~_>Qbeic{z)DJUuau5Y~3hXj&_;L(S#z~y5e=Wnq8}YXE|C|vu=vH96gv=j(!Mc zt$S?!GwWYkzi|Dw#?Fm5mSnGcdENYV8`tevfA0Fr*VnAS-&_!{+AcqH5wxv)Z(W0# zw$8dp{&L7uQxEcs$L7Pv9P55suhzF&f2w(0C+l$s??3dye{jYj7yg4Y({_K)x3<>z zSA<&NlYj5}U(9=^msksupHq3s z@}tdH|8V%HArE{ne*!MHH(uCyMdJ|jlvA4deQ3*XUf*Tin9BFm%yT`SxKi*JTfP>c z&2Owpyh8dZ)VCam)+M_WHoNv zaQcRGH(b2orVTST%qqIexutPufEwwEULBJ;`pEInK7R&&JWoZrHieXX%DV6Ls}h+BcSNe0byA+jke+HdbxC zGc~y5c7MBX_fCH6Kb2IrhhN&@BE0d*jdN3}#fN7M=_}R7MH|4hXC!Z8?mrN)ZOYknY;wi@)L3c@CjCiG+SGk>ug!xu*KB@d%Ntuy-#TdP zsI5g?qg$tMoxSy$K<*~rrW-en*%aDTwdsRRO`E>jeAMQXQ!zYNU%9nOMsYW$UWVRS z;@EV@rh7L%x`~K4-bp<4^W{rIwoOlLdg+iAV9jT!p0_I{WA!{_V+yZI5Mjhj1ezSNvP z7j5>K)8ZoYkd3M9=?R7Q%_BCC-W)OBpSeRW2%C#Ghvb5=J8?lc^`Rg3mPTz4@fp6U z+T_hsH_u312{gXWrvGZ|BSF{ZXEx8sXSY9w;a3Wlr0^$T)yS1EhDxBwv=uezh%mn>E>AY zlaa8~7`m}sYPX!TCHebjJIzb&Sj*>`T>j)2>)lbyBAuUl<4+#dWxT`JoSb;>urYmo zynW5z{I<;6^5mAk{hNC-e!1n~@85j;O~SkLj2}pIx8hs&c0OCZW#N{ksh&SJ=-9G$ z%eF0hwpdmd2rMh$hKQCrR z!r!?)HGgdGQA-!xP+{A8%hu}D@i(WAe>ZUl^}6|^h>1Tx)SACU|3x*0Y6rUOX z$)CTAdfrn1^M9K9LhYoOFV!x!Tm4&orS_<=)i|m4<*JpIr?qCQ zjdqlluN|!&qaCZY)sEAS*G|ydX(wtYX(wy#wNtcHwLfTX?KJIl?F_Ah)=}%EovC%! z&eG1-&e6JP=W6F^f7DC=pZ0-AJ74Rnmvn*FO}kLLNV}M=OZ1dW_5ZtTm+9=GU9MfB zJEfjdPpIeAm6})UsrAx&Ykjo7`ksE;pVjl~Z>qmGKpUuCrCqHJ(gtfov}-hS7{Mrb3o>$FkY_1X>EjoN7KChcaeK=W$>ZH!i^6=^|jtX8a*Xd&$uZJbuBm1*T# zg%;Ls)goG@R;5*Ist(i`6CSQq^5urh2H$)fMVWFPe*k^kM#?itA}Gt~p?PwK(swo)cxX^(49YtL(QwZCigwKui*v}M|Atx?;ieWC5r{;loN zzR{Ysz1lwQM{U3Mv-YcYkkGK%95$CN+m>s~v$e71+m5ldwHK`rrM_2?y*g`-EW&|`;)EK z_ONZ1?J3){wpVNmY#-VhY-?>>ZJ*e_uzhX&(PpzBWk1D!j=j76a=X{w-#)}X%3f^0 z)m~%2*FMYsto>E{TlOXP_4Y0HPwoGj!alYeX#}$sAj=_%M zjvE~}JH|Q69TOaPIPP{#cRb>F+VPU(7016EZ#zD8ta7Y(eB$`R@vY-W$FGiD=kd2IiGXBl{~CR}WWj*Hx~OF2AeTRpzR4-R_#^s&zf?dd4-^HQ)8FYq4vkYrX4J z*KSv{>nGPimow|=tdp}&&pIpXf~@XY{jx@76=#jlx;v{j>)EW=vleBo&uYrrleIs~ zm3?fsJG)DE_v``LBeDy#CuHA~JuCaE?77*mXTO)dEPH+S$Jt+If0zABwln9boD*}} z=eTn^C z_v_pPx%O81txj*%rPZaa`nDR{>c&>VR*_bBwwl>$cB>a!&2RO7tJSTxw%XZh9}9k) zyp!@e=UtT7JI|L_kXN2JId6L2th~SGy_y%xTamXu@3XwG^A6XZtLZ(H@5z=^^dJ>ZCbZ!-=;&GE^WHC>CvWFoBnME zwHeyx`Zj?!#ch()B58iZxzgsykGB7}=g4~d|74C75Qh?ltBJXjh%mn%V`apcMA+kc zj6FkiNsLK^?bc(gnfN+6OCqel{ac63vM+46GLxn|jwixjacp7MoS?2?p19SAjC}uK%nVk{ zmmaPQvc6#UGD}^jXRTu1p2mEAgt^R1{SgR;h4^0;+<=5lXtIELa>+kw8(XkgY(NJT*oc zeS)P`0ja|nN|s7gh69B`Ra!AASY8~ItfgFJk-O9QIXG`$0b)m1@NXrOmtAVS3o4HOkdDgssNJepY)q~iMdf;EMufiiV#HEk~% zL#I@ijR{67L&fE)sDh#+DjbaHCkvF}Dg)(3M&?MUxP-O_BEj;~;MjyS5(Aa=RH$;C z3YS(_s=^97NR>Pf{C+6l)hy-TUDsED5#9V zDyo>kn9BG|KbI0Z5+{XvqbJf|V@oR{A?YO}sjxc27!^)5>Q_m20?Qn4{e;EU1W~Z8 z!f3Q?>A8~o^ev+@V?z|Lg5^areno-e;$S2J2_9o~rE1KSA_oo@AAb&0uM1C|nt;lrvP7R8%Lz&=_gGKR6FTlZbwOXvUTXYn0J%WdTCJ zoKBT#l$t(8A*v~*(p|;$s4_Q5k?OM2Ky{U>C?-C~F`wl4V42?Ro_$qCq-ZQb zsK?|WBSNl8K;Kyws4T2zWT=sTLW$FmDmAiHB*2UgM#`8_V@fM!8dO&6{TE>kD3;}d zd8*2)RTZm8P!=lHx2i<)l>|!1>QjpfFu#VERIqlD&e9d3<5f{;e28Ef6R8*%EFZ%R zE@CZWZqadM)aO|uD=|2sB6-?Kus9?U#mE^Y2RUC^b!k;7TsqM>E}6HmB0SL;nx00V z_cZ2%-swG)9oy3wmY#YC_cR8hx7pEsjU)S7j_jK}vafOEKqJpUOP+zrJOhn9LyU5- zF|uA`$$CvP>orE!YmBVJjPV>{95KRj#E9e(Ba9=iH}YJcOuxZ6HejR&EXT6QC*nz> zUZPQNHWvq(yR6todeY8XOri@+1}+y;DQUJRu`bxlwL~k+s57TtzZ# zg^{(w$XaPsz1ldU+Hyp7@`!5Vh>1p?iOKXyi7B98E-K3cTt5d`CW?__Trnz2iz=%o zvd9>l$(TuAK#a^i8&v2Ym6V={|*r84>;kW3$w zbh45rH;R%jwNiwVX{AY5mUQJwXPM;5w92GQorC+Cv9iRo#wW*wn<2Sqb0Z+vdVNfi zNxhRRtt!(Az*C1APtjGtl3_00RRJTxH;D1A`0D4U8}_(!g~FMj5!?zzqiUyNoizsVWeeC?PjCRK^AAVMd}{NsSbms)u@svF;nbQol1Zy?%3MZb%oE zgd#<9LD5a6es`CQ1et584dz;MgSnRSGS`w@dfCY>nQO@nneE92a_*$(^eHb>Fu5f) zNNrGqo@?IjyWJy0kt$xrURxcEOwD%=;9=cztU5E6q?~Lyb*>0P5zU%{O$ER&K?>}_^{@*B8|ycS)8_rnKJ4}2~B81=z7!ClCQZ-)EPa6BIwP_57?d_HVKqa{Cd zAE#6aUf2+N`4qeb$H=#s2Rv4_!#^VHR1XAgL)k8!q>t1XpiK97oV(D zGu{gyMf)TVT!i-Hr0>DeegTfEP47VwHy74Z-!I)6L0e= z2ku7s_+}U#zp5Q1;no7iSn|V10*ocT4&FOPspb@0X@v4r=-GsY4>cn_R}w&A1j zA+$sC!&lKRd<@#h5m)$p*bX_~pdVm2l#TboFUlBud^3EjoHYv{gMX=D-r?)u>&PqV z@JrN3@w6{qQ!_fRDmv zv=T2ISIydm55u===v#aYUN(`~!+YUMutn3z8-Ew9()sYO{U-R z`S3P$2|fxhzLWmMd*StH6y6UfBERH;&!7@~Jv<}I+{AlePgH~VL4JczO~!}exT*A^ zcsK*i!q>v0yNE4GhYz8-_&T@>&BMpx#nV{R@Lm`}3-M9ty_>$0bQndOB^}046JB`n zJ;a{mfh*B|d>r<;mv~!1I;@z^e8h+0_oxG2K5%#k^5CQJAo5E3{iGwGq{G28=o7pT z-j7Q0wQxVGlKeC2g9oUepZI2Y{d?3O?}xV{zvO{G zp(4DBacM?XcrToVqWC)4fTrQ&@G~?W-waQBpJBth;rXZ*?}hiES@>G`rw`}{@$hRj z7vBuE51IS;e0T*~fcL_IXd&JQXDy;y_&V5YF>xvBP%R;D@xp(iW_%1j+`zuK$qz4I z#=433!go*yd<=e#Josj~7j?s{Lwr5FW-Vie_rbSO5k3Y#-b4)J zo8Ud0=^uP8+>d7A)fV=nI(!)JLG$p*HlTg@IBfMXeYKGM@K%(EkHX_Wq2KUs zcq8h7_e1q5{e~BIZ(@$%y>Re$<~ZI5SECYq9BxN7_-0u4IrYGYVKthLkHU64Xg}T! z7oger7(DX}?mh4x_!m@h}`dN|`N=9=V(&!TRU4*!WRk^JyO)B_)fL-x== zcpuFFnpnaMA4H?^weV|Hif@LCzoD=2ad_jm#1h^QPj04v@NW1TnuCwQ?cXtv@XfGk zFMWa+_WYhP#{1yaKM)V%;YU9a1Cj?`zMoimm$8Gjs4ZT2%+ItD?}pkhv=N^V*C|c) z!8gGmU#b|555s#<6}}d}fF|SX;qAGanud?U^{5u#1oK;IY8GC&3(dwi!)|;v<9WOn zzJ(UxV{j*0D0yK2HkyjzebAM!sYUpF`1fNq)rhZ$?b>Q;58e%5M*AgQ(vagl%7Oik z(-a?H<~2TbMs4x+@R$=g9`A(BHF(utQ_rC3_`1w1kJ~L;b61??}Im^g?K+KM=^XD{v9pC*TdgX173B|RBN;npASz(al9LPQ6pX$ z?Wn2Ec;Opp8$JeqL``_rNmF*T1D_AuqFs15{OL@_K=O3f)B~s)Ukf{(qp5v(5B#(X z?TpbU@E~fBSLf2V$c@j3N23mSH*9~NraFsR42ABC@?8hi}yMbq%=YTAWr@m^St=HSEd>uZQTd^7wVEtLE| zP32rm{NVFp<#ogcJ__#`#rTSc({Es|;cMZG1g_`P)df>fqJ?evR zg0B=YrzAgoGsv96$KaV`nMZgJd;o>)>3} z7GDp)e1r86-wcPmPo42T_#WzmkHKCaP-jVpk0C$44i5W}vBUded@tjL7ryd6{g1DQ zt(8s9#^=M&vTdp!-wb!=*i?gfcxzD)_$DE0#y7(mc{a5VUkmF{_F~!syR^2cJiG^2tsa7cff+K>0aV+PRwODP|=zRITB>{`e+% zQ+Tvr-K9;`5=fhi2dwdw)jXL0K z;a^c_d_DXKb-_2mf1_^rW_Wb5O|ml-pDT-VM)> zFkW~sJin6I6A$}U5uLwr8$ga+X~ zuo?OA!XIy^ukh*)#`#X0D#5#9jR+rwl~LL*9{z%6Oa3V~b=p+gi1)x7?qbg1{cttf zjE}=V-_4xD*TKSj7!Q0H9=MnKEvKC69E;lF{qQ~10Uv|UJxsgs_0aVQ?ZW57g|ldv zBU5k8gr^&8GhNT6p?n)F1DG51^Tn4xgT5Q?u}O@T#Yo=Xf7{8O8AR z@GI1SZ-&>_v9{y=LbMGpy!;u~H@p}2dY<(e?}L3_WV}}3;Txy}J_hfYOPt}Ouy!8t zj~Dt@6T^}p)}b(7SdVJ(!X9gEYBJsnd!lKQAC{o$_%M71&6ND`9aM{t!Eezld^7w7 z&Bm*^O|?RE@cFO+)#3ec{s#I4AA{d-v8hFpf2&Qc|A@BZo8TWlCRXuoxDWj*c|M`t zqLq{hN1=SYA3lTH;p<_mPi@LAdEiy3Gu{W^{*L~^$6%|yjJ4!}ZZrrloQZt+S~%o; z)&aZ^PD7(59lreoa~~grPyfig#@E442grx_z{xlMceRU_#0}H{0FHUYR1<>^*enc>2Ms%UPXR*Su4A0i}%8b$J<703Ys=~+NMpT1ug7)=ml8eW}g zSJ$IjydRdLIruRA5Y^%1(AC+l=Hm0=XJ^^fe0(!J=WM%*;XUv@)PRq{-G8*JZITCm z>anYR_$Igqsnw*z{bD1m)qqu=pao%EyP{Yu)XtGd>14_pmE3z6qXsIemh6 z!{r0*YBW9$n^6^Bco5a#)m3(NDVmJ;!naTqAA`=T=?8p1>_3=(!293_s16^8+t56G z6D%HLXZ}$)*x?%b0q=p6ZlE9VQMeFo#>e1Rv;*G+o6#=3@Twc>3%n10g_G1g=eJ=UoF}KmTk`DXbZdbGM zKG^mS;z!cq4pfhChK@V!Y5_hUo`)9VJwQvbiamEz-?xNrD!qKQ5-VZmT_V^|^a++PaB^~~RI^fmawC`SG z5-%Jvo!FH;@V*($S$r*AhDPDzuw3(UgW^n z!WU3Bz8>yEdH817_I>6f-VJAJ9_G5R;N0o`=GC54-|Z z;k|Gqs=@o=%}uPO;$hZjj0-*=dOl|?@WPE>P(OSV+=CkM&G6z~^da60$D)^Tr#0(D_*(b` zDw1?~b}NS}!F%9j5k3kxwQ;EF_$JupD9$H&U{1b6&BN!zX=ow77B-&XPz{nFdQWsP zKNutUWqXI(k8g(KI@6X7)E^!^n>ypwISy6oai~iq9S%F6dgA@C@dAhP+<>;>o8W~#9BK#N3m->& z@O5xiPwI@1!+pKz^Np0>+o3ukH{JsuK^^dQumN?$$KjQI9I6N23%d=V|HZ?Z$d9ju zvr#F&4$ehkd_8=8phHzjIy`ti{fk#OIMi!s4n79!Z{`@u54V-j|M(_2{ubJckHR@< z2fhwoRO(Q>@Lu={Qk%#RN0vF11Mi13P#(S(K8o`3b?~pKExsPEMD6f#IJUx}+T+7; zP?#9S``~PJ3BC?KgL>fW;kyxH0w04fO>(GFk`CugqwSI(F1d#>#mC_V_puM}h5x?a zq2}Y8VV4>7HQoceqDILBN7g#jX1pI3&vK|{d>H;6WpCzOaNVP{1>Xek`ZME*uZ43^ zH+&tua5nYFdtvG04%G)AhVP@%_&A*LB;$y$gaWII(6J`CSSlksubp_Nlb@gDdpnvIXa<~*l* z9xq(n#;F!aet7B8)EV!E-yBb!B@f(pHg(3UbDZipl)sHSz%$Qvsf3K+X6t{5RT%Z-&2INuS`A*Qqq*_?Wi9qY*#$q}=cfl!y1gp(r2khn1)uJ_=`` z_V`-3xtEjoFz7@0VjubtUk{JFmT||sVXxs%?xCnBybqP)YvFsS1|JiSq~GvSxE9UA zH^I+P9ljZUkDkY?>zwLzG#BrIy-_{h2X934@qSo4ia5aw-$OBc3|3$7REzLYxCgDo zH^V1K(;j>sY+FDd;@xl|`V}98lLGYHCmaj!Dxx3oweX*)8$Jf@L8t10&xZri0K5j$pbG!jd(A-7H!7+;eBWuz83C7O?XvFT%aBJeAo`{!n@&kv{54Ur9QA5aoYLnXvnK`V{Ylp$XI*ABHcZ9{76rR1JNFuY;#eq_6NE*fhzh zO7OyNw=t*iUf5%@Q%x5Sm)*`4*7yTt3Zl1UL`C>!IN@IU6d#2TqG^&J-f}-}$A{rl4>(mFz7GBaEx^~q;~pY* z@ou3?>ruIN`uhmEso*JsopKKvLlkFSGGsI#O) z^*CdL7tVfybwKjKC+4tDiHGfK4sSti@nP6{9%G8nhyGVs_wd4>kO!~+&YFpONILBD8sm%iz#j8C2JeOaP!-+> zD^U$T3U|KF+{ZV=;2X3TABG!I9li-}{ugs!JnXx`spjE*@YXkpb9@v&_%`v3uZ54H zIKB=Jd53{`g6*MGh?(DUke{X?eTRmj@)?R?Dtt;Bpt?4 z7fFXlf518LZnz3{lXR#)q%ZKo;mC{k!||vOJ__s50K9NL8ia3x$1ZXzAKncIpy7BQ z44_f?Fnkb=#@E7w$d6ZxovIBg!so-ms08nWH={7#56e*%J`8VK%D6~6oYX*k;-j$t z3gQ#*gXgc}I)(Sbd8iIw4^LaoHr@k=q6K(AtVJ=r@Pak0Gk7n24mINI;hS;B1s{Xc z))JqRAMQqK2eARe>sXKQ!ZS89MtBc=U=w|guZ16=0r)sP?qm82?}p<(;kttl!`DCM z9QYV)LUZuK51NQEd>p>=8EwJW!@i%>7Q7E`_=2`be)#g2v_ z+)caiG5G1fX&1f;mVZUOeL;QTvwN6p_i2L;T?Va24u(i;dN*p-Vev4dVCbVhUVjA@CUR2 zuYM*0Ph z6R(bTsXk~n-Un;Y^Y|!y6V1iP;FM!rY9788EqW~(~*Pn3_3!K2%`R9n0oMv)sYeEARb1HK;K;im194o^JI zr3OiU_$V5VuY*6MBD^}?rC#v4R0+NwK7BLgN*=f#&BiyuaRn|l2Oox={4Q08_rQ^8 z9^Mb9p?Z8RoP*}$>tLHPF0}xk4|^BVCwL#cY%KkN_d{nfZO02wMa_6O?1T2>g%2aO zD_iGWd>+0YjxC{o@WN3c`ULNXlaU86Y($sfg_}?xd=uP(2H=Ie&>(!X@D>-ZS+jM{ z97nl$VO<%0g%^HR&N=YH6&17}FYI-zOU=Uj;5<}^7oHkn8!vnqEyN3lRx&T}emD)S z#0%d?alEik6>Y!^YtRn7@ULhOUidrOhZmkz?NYzug(2kFovrgzd>+0DevaDVJ>y;K zBGex5h5e9Qe2q)>MIG?}`|rp-pgC>I*;Vssd08s2SGFh1?+QD8j+iaZTez%8xm{fz zr{58_`)o1I!Dn-)l1`Dj%wu^kHmj@MWApPPaqvD*qIAvb+hnUYU2{D- z{_Jp;&lPjTZB3fpu8dZ4yrwD51FdP+bLZ!T!C8dZdr7OgHDBCi>OlIo)^s>!! zn&U0|$CweFh?OykIVgFpZ4__rGmp3KPwxXMd#a^uv)(4HePb=hdLCh{=Bi`0qYs}Cvah8wGR2|P**b1!pIZCF z>dkrzTUvvpp4-`P<~>qfC6CnW;k5Z-vnhRDZz+b&vW3?AS-tE_ACvU_W-O%VvzBA# zv7XcFC9fIJ5{p9<*CZMLXVb22*8MGcIc`kaapw7~$7CAMmg37ymvXFSSnF=)vFz>(X>G74meWbFa9_tc)nSR`V+LmJ@iDRW*AEdRrrMUX<%$=6X zFxzhJGpTR-8Wu_1|4dCAYbm!^`jsvb=Tj4Fs+>cPPcOHn`pY;)EaN2ODsh&6Zgae) zoM$uCL7&UV9=`7A>6aazE`2X+ft0sBLwS<^L56hmI5Q?Q)iqO^*)P%#>6>1b>xRTc zru#*+&HtTatZQFO*GucVnqHTd#>qPOGSxRzo72Zu`ru(=!;C|HY>qp8Y|>-LIv1_= zkaFZc!P-xzw;m&D);e3gxzAi1t#iYg&zf%aQrGnUw9Y5Jjpt@=qcsN1dRXJYdY*J| zuIrL+dWp$iiME<+OnUvS{g=Matb^GXvYnnL>8wZ7JnYb>vl z^w(R~wZWP{Q$4KbmbO{@x25@fqdKl?f%GI7t{OSTAn%ot!e48V%=xvKhk`+ zw*SBDGp&=--d<_fKWn*WjAp8*IgXjiO>bxVwv5%74A-5O(yixj$(#L`J|^ksmKZSC z4XgjJ9B0O+^ifN5DpS0eb(8a%WmvtnO=eyx|Je+EB>TkX6ryRcC=;>!2o-XD5cVbWSZ_h9e zGJZo7_qdX$SB5-#9Zo*H4lRvWrr41_w%+5XkA3>KHI}4anZ`B!7;`K#^?OVGYmMLZ z@}v&w*K56;6A$kT$!p$Mx706sdWQR3v)(PyoJ+DlQ`;on8kg3-)6e;F=K4OHcpY$5 zwmM4tURhUAt(A+XS$>~-e=*aXI66litzD!Jy{b?b{hR|2Kc}94-Qnrh`etfhOXIJX z_xq8{OCM7y>)8x3o*tii+m1QBZ7tQMrE;xtVQptiW0_uG>$sZl+e#kmy_xh``hDJ! z>VJBM_P5lo^nOWigBhFFbwtwSUfErze@Ao!J6MXCT6+m<7VwA8MiQXv8J`;WgNz27@zd=W!rj9H0#vTIJT5- zZI`u9*6~b_H?z(E)w)W)sTta&kMC)RkFWLIna0|>KU3^WJFM%r#DRXUQ?&G2=<$*1 zdS&eknFC!d?|YbiE%h+(gUqy+`b1x2k3DpaHT%(|wLI(jt?5#Jru9qGx2Ly`c3Y24 zk0HHJGQ6hO(>oqME@nL?X3X|l<0su)+n|^E+2LjC>AxJFo?h4Vcu(J!bDQ-On(L3r zuB=D;xvoC^T-JJ9=X<8uOFwT*v2AU;*;nansf>+z?hn%;U<^8Rej<@!a)m!7s>Lrgk4pKjJK3eN)j#s8@eoOU`2t)qZ!u}s*`&2y*1BgJAK7o7-)u|z`OI=nrnl32 zj!bL6S*}UFof%%6S=;m9jXnMTtjpo|mwI~J!_&>S2(9O}rkmcJ6V`T``?6h!UV}3A z@sZl{L56FLc|P+T*71}y>$+v;NpFLT$4w_ct&t%P)6ZcoGd*V0^P1-rn&(YtdW=}- zu9RoJmy~jj^f?0Qztc1Hlce{`kS^u5)aPal9x0F1)x2kxc37_?EtPAXN7m!5=|}35 zmf9losq3My2oJjlvEH{zIhoex^mC_gTgS)jqjYAverHNEVr)HY{7lEUbiVX?B>BcU=^tyJmdccT)-jZ0%=-@UV-oM3wG=zj zC+X{8OMP;r^h|NCpEJXIkWyzU>)8zbeqydVQTvPIXivWXsBjx!>sYIJ4xj4N`@(FC zbxuhAA5M!|{k$382bS}i^D4dH^z%O5>ag?bWo7vLT1)k}j)m3ho}p|>pPC_E%CcTVW!rkqm;N#D z2dsT1Gf@?UM;m>kDbd8A6v6dA7rSL zb$lhZho;4L`gJ0G+Z^Ncd)p)Rf!T+$4yC_8n<*{*98SK|?s53-VLrcW?i03@o_^ok zQr*(yNAJ%JpT}uqS8cS1v-QskTh~0PLrd>3TgTq4b9%k3YlXQl+wROB>agqgGy0r9 zA^Wg7ox|^7aNnbU-oU)qYbiz~JyWck=d;$++P0R~IJ3^_)bnTf{D9<}N{-y6ST?3??O#PGI_trjX=^SRA%(_^|**bQaVk%QwOLdd7_9p&D zZMNT9Kk??hnUrB(f2B><_v6fCww`M+{qGwb5vd}h7VSVwwZn;n&WHcv0ekyWyC*JHMv#sfI zohgqs%^H&}^+~32wU%LytzP#GuiGT=&_rLDdDG)d>aX9A-J5sV{g_^E3$G32IO|$q z_Jc6}yVSTSB*Xhh%=d$Z9^s&FC1plA?cU$rL8>MmI zWaa3u!?VF+avN@A@W-w^4lQt zJ0S9#CGuM(@;fH-+(LOat2_^^?k=T2TTPxTCeIm@=QqjooaA{;@|-4l=94_@$=iWv zc72ZDj=z&*I+5>E@}HpeXC28i2J5~+q{*{=KY@j^Km*+jn^Pl8-Q1aZy<^denn=+6*|4DJIJU>*P|0K^)QvEo$m;Jky{+uIu zo?>hV$M&Thj*({s$uooG8A9^R8F{{pJXfZfnKy6Z6wb_lIPFJvr6R|Hu6jxd8U;-&q<#3B+tH)XWn?5I2YUU8z}Nj8+pF1JWo`f zFDlPrl;?gme?YlHREu}NPnoE84CP%7QEqSDs}SzlZdAoA~_|`K=iFZ5MeSkvywNo>3&vGLmN!$+LyzSwr$1B6u zvykLjfbs2=kHUAMDV%RA+fmL#J3LUHlOfN|P}w=^ICLhu99@q}(d}p!dKtZq8qrSl z1Io?GQ6166XaFieW#~3E4LyRMM{l6Ts1bdMengJk9CZ{r16_uCp+V?+bPK9M)6rkh z^XPr_G5QUi&?-k=fCeK!x*gqzW}~_2U9=8;gO1M2QJ11Ys0fWmGtkrMRkR4j(Z}dp zbP%1?I!ARz7on@rXjF!x=n?b+dJC;ZJJD~bb(|3ZyuFUmS9 zN1ckgp@ArXD$o@45PA{4g;t>^^drjR+W!Z11-cg9gv!xv=zjD#`Wu>$-bZWDcJw`R zanG8MPC}i~g=hd8j)G_sx);qxbJ06!721h@M)}9&sB=(%bR)VI-HqzdKhRRN1?@rF zu{r8^)CpaL2B4czIl2S=2|bSHp|{aW^bz_RWwj+9kQa?aAv6))k6uKJ(Ps21`X0HC z%Teu+2lYlH(O5JY{RzE*-bWkJF7y*R>UhQpdCFNyCL3LD})R|n9&QfQqb5s{~t~yWsQF+w)sw)pl?xrqO7paTYC0r!BtIJdm zb-B7iU8%gPC(CSamh-+W;r-PBHBeopuI4f^SPkLfw?1{P8mfk=;cA2$sjgF_)b;8H zb)y=sZc;a^0_9f$HAWSxA{A6)Rk12jA$5xyr%F|sDpwUMtZr2iRmr1ItJQclLDi^< zYLdE5O;)$7JJg*js-~!^>Mk`+-L39X_p0eUfb)JegU4q+p#G#DRJB|bA6Ad>NX$po zpVeQ~Z1tFWTs@)Ys3+A^>S9-L=hXA+uj&Q$qMEDzre0Dnt9j}b^>_6TRj*!E zuc?2k`RaA`hWeLUpx#t(skgb*yrbS#@2Qx2UwxoHREyMNwM3PM#*B>wgH;p5!E-M< zuc)+C^&8&1p!eWFxObqiBv>%0qGDWiI4yBVaDtvPuq;p@j*FyV4p*Z9U80*R_Q52DvE*y zBg!MevHIq)UZJYP8k3%AX-jICaqfbig;k;PfvR9ZqH+a2i;4>R1jh!dOREY7R}@v3 z1}iy}o@{LDTjj;2!Gb=au~LhIo>hVJu7;^%01EnrN~N8o>zl)>BEdkJBv9G1K)9fH zMfvz(MB0-|2~V_aCc4$!+qY~?MQKs6+>&EpdB}QvqA|ULq0)Y#8p+qYG*DR?D!e)v zDKF?pu%xGr43vh7Xt$nTp*OKlXnf*eIe$T75cM(Eix^J4Np^j2|I&%!lH}H)(3nUd zqBlX`J9u!x$bdwTk=g89DYBql>PdFoU^>N)j!ZJuQ?Q$18LI8aGHnrU*HLmMR)g+*M65<#6Q{kmYNxWrg|&D|q|k;+hoex(`2sv(y> zsgLgaF{Mh4OL#INwRd27W#XEqXCBCT6PFi#+qkqR%Nn82@j(>A7Ur zph13G8f0>#Z0{AVkMh{x#?hal=WSXlO*$c zbxk-}ZY*PoD`+yodij*ZsL7`FPV@C9CN!*P)4_+Qa@=j(YT*V9;9DP z%>~|Cnl*~egUz&2*Z)85U0mNGyoc?cVLIUDtT` zb`3t5+`Tt!rGWP|PnIECGNo{L_T zmc7z`#cWr(t`Ds8zM4rQ!)#@xIk~5R@2YqN_h|!kqSh^Fv94h+tm zgY6t?l3GiS+ZeL&+2z$PW7#~55P0+OR#d~x-syli&Ls8tG=(m`S0a?>PLHN^lETUk z)Nz0bt>X>E4JUK)6wAgThghq*hK`RZf*AJ<>F&vU2thfE^A4nN^33%lMaUrE2xgCaS zHYr_TRnU$2x07j((r!y=fEsLWF|Ka5ek!tjOju#9hPfL&adu{-;r)~|QI^cB@$@YR zR>|N7GFM2}#y)}pgD4rtj7IXFq34=SCkjI|SxmavsIr2UvsbA8EC4EHF&r7OG`ejKsCHJCgoNQd`nDB)uc)o07Wt{Y4%xB=y3UX!A?zw!3d14leiY<8=G@ zy|{#hmTdgVOfs9qO5%0o4w?u4Q>@c!#YwjK?HXmh!wjZkS6vGIH}A@hxU<6D zOkiPc2Tbw72XOsWJi)JLGW!`JeoV*LpT`sZ-ez(y{=@+-$fx=J{|uL(gk8RpQR@fOpojkxk*5>GENk2kbmT zpCj&*TYB~|gO*NGdx&^)wNy3+G+06tAEq-ml9}w`R_d8FXKzvUAZtI9PHd%jQt_Sj z+;&_iJmurvFFe;%@whHt^K8a5d%W=Bf+&9N*-RZ^$j%DF?>zVHM7-^hH^sGC=u3#d zxf~v@z&d+0iq&RJg>saoag^M@8Qq2W_~^2TZtWf1it;IOZ7rGvtWfoycx5e`+TVT- zpQnz>D_?pbdJxY(yQhoLndo7f&wjwOb(7{!AN9aoz!BoJp55&fJs*k3J-hpu_lYlg zc6B_jh>IR9e{b#JgJ`r2F2ohj?m;~MoOs%^n~h^NeA9CawwJyw#CJWA_7>ggd!9Yn z?~9(j_}+E`R`LVh!%6W&-oul<_z~^VDzwPc9^}NwH$2}uAlZKA!EIT%s)rUNwo*bg zJqJ1#)v~*y?>We3wy}UFUgkaO_m{j!{k}qbSe?S_W7CbYbGppNA!B|7jS-g2q;w?O0Qh=uLhW-kUcJWqTh%~neqAnnaiU6YP_~CQts54kY z_S?t%dmZog(|BKh4RjAz)3%8>{BcwrTt?q<{M*ENojGA}_VMmNj%om;YHT-9uduef z_a&S;z&VmhM~fs{BWYv1%zIh%x`8%nt|f3KS5S$NM1?^HGGuTs+8#lr#8JODa1B)$ z9QAhrl@DLQ?@_e90OU})gckeg_mE{<9nZ;eQ2#;h|M)d0@3MN27VuhwoN*w%1)K>z z9kS9Gs3L;UXkv61(DS3Hz);>ZiV7+w=-+v0&A~e>@jj1xWYGJ0^!5bqnF2k!-vJ*H z-h|C<{M|uI+8jK{4zheM%@Q9Wa`HZO%|+Crtic|g{>h?fl&($Dkz*YvuRV{ul4P`9 z!fy>0L0WXLJhDcC`V}||a3MXXA$JON)kYrl{E-^`_ctBiRl!{&7XBE{K8jATkaHF_ zFsP+7H8X5R%$S)lbu(ugX5K8AMbk7bb6^fl+Z>s8d0d{B=O|P0Rg_AwqE=#+L`ARU zDq1yMjZ|aRL{+cmtA%Q@YE{vxiEq|`1Wc#*qn@c>r&qP4mBOV+DOO69^ir;5l=7uQ zsaP76?9!yPDEZ3%vQiF|gXK_JEoi8Q{X}2y=lU4n0N>vM5vJGl znSN6-17^?+$x%C)I(QzTIW=eI++3jS$6NB1{G~uCSRyP2?RmQZseE1ZXP+fw69Y30 zYzn0?u-1;DYy#&&by&5lQY57jXas?Bq>*UojU3P( zHO7qz5Fc4nYi7+YZ`0TGHY=v5CE7nT1 z@+}kC3*a6D<~HzFfVI&Z^rk%@5Z3!hz*-Dg#}t;Kmi4j; zn-s9cSfx<0EAxs1OEiGVwCby=z`(%R2N?6Tmd7Y9j4;tCG%Q$*I||j(tgsbm^_-`Cg${?3q0a zBN_H47|ls*G5c13&>!|k7~h0!XL=U3VdNuW_Piqdnrj_C*hL6-k&v1sElz3+=ufR{ z^>94`KS;7US*ux_)@9 z29J$E2P2?Afyd5ZLkpD3d3%0%uGWh{BczEDYr)@F;I-tlMT~U>?BmSlj!VUoSsEc0O-p`6B8|ssV5Eg|5u>%r1B}=%k1*;9qT>wlae>i$ z5hMMGk^!I)LZs9x;YvitOS>|vjDg3rG6N=PT`xrhM)a1bj&mJu(5&StB4rtdcg?MbRxZcfw+3y)77Td46}_TntC(0v^2A6v9+BR2Yf9*Vt|II9N|cy zw{nQjd3al~WwtCt>LL7Y)Ec)Yh}koE-~wfk-nOspZ!7IUJJ=2(j%)DBNITX}Afo5s zpZRv7T|{iR;Hks5-5w#zPvEmNMAHT0z0wIF=7&1KR5`~ng`%5a1XYe}24iM72r0q% zsEmriSlArr1V=cvNuxD*j5bF&!Ldz6T+=ZY8iUP}3zk=9DGip*W{Ct#qjnOACq~EW z43LRtoQVR6h-x>1$YOLY&P6lWwde(UL1d!@XCn)-#YRq=BP#`vkyOq@2FDc}K0NP> z;5m*dg7c8damC;~ZgbWVGTS7ORg99wxpr2XqX0F4Jgb%y@MME6+h%(fY{e?)dIP>Z zfH#xn3bt95E!N;nWLIa^IZ9Y52T}gXbM_J8b7BJM12Tul_zo7lX1es3BR{dw`*i6U zfvURV6BaVvl<%>?T>`aWEriISE%P14M;p;&&M{J{2M|L-h?Q=n)DcY#neRr(bB+~w z8{|z2vRtU4vNhxzBNIB%WdG?BA+MYT zxHxGikjlTy+`vUHAhFXLdBmRq<_5F7q74in?B!=O)A0q&0H$p9KAwT8JO?Aor>siz eurcDg2%@$gmr^zgnb=XCV;6I9?r-k_fqw(CN$T$a literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/libjpeg-9.dll b/venv/Lib/site-packages/pygame/libjpeg-9.dll new file mode 100644 index 0000000000000000000000000000000000000000..9a05528eff3bc65d0f67b93f6d24dd82621a298a GIT binary patch literal 244224 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

    sMo^((-hY+?nUdPz0tah zNMe|$=-_FUWKly^R^ceJ4dJuZKlTHC+FYlZ0{cUk!U`PeMOiV*DJwur9k)H5e+UkX zflZDFJ)!M88nbVvj^l&i$iMp-yF+e*Z=4_7vEVzy@mXLPJjS%>(O|w0)91==_p>yOgRXIq0gIL-cu_r6Kt=I&9#{x1R# z-XW^sz&Wlt+M7Gkn+?}Rhxm6W0RT!N2NrbNF6*OK^UM?x*_Vv_^HxNp>$BxqB9-exGt6$@FZZz2O7qwIjD!A`HJElYk$T`+_X^u$=x2SFO$ zSAigBX^voba|QaW)l@(U8TGKxhZaD3UQaB1Oa^S+JPN zjpxYqx#T~?P#^@3F>mKAjp?BQ_DcXic*#GH1Q_ODUGLwKr9+*~cWB=cdG)eS(t>(g zK%hN+Z>zz>WmmE?WH1(A`F(bN8jlb$k`;wdH3GbXw=(@&*ar@#74sX z&Ai&nU-Z{brjTi`Xmk1R)I&ivxoD-=RExKS%IJhb2h#tC$W`NXYD?yyF&W{%94*+Y zRNkuF5HEA|fS%OYZ*@u$0%`a5Xy%WroBhex#k}WZ-g5+<>VCH}syL%a-seq@?%s>w z+u5k2=J=HDvB;yu1cphgvB9h|FQ%vcwethrn7am|*3$gf-bTS9jm4R_GwIN7!xJ=+C~R8^jo~SdCO2r~U#%3@F5ABvV^i*@oA*+j^4i$x!&Cbi6${K|KAe_uk&NI-o=DY2is&tq5$L5B=3twsHBvy@Q-lg{&O5gF zEAO!2N)?791rEZ0F0h@AQkwF8l?^-{o9PftnRCZZa{wkc_6Rnst`qO`GfLe8*{B4X zjo+nC@e{^?p0Ek_L`^r7`GTQeEL^*ff+c>4712zNx2@r9QNH9~Wd?@erT!WN0W)Qu z8In>PX&}2h&yz=3`5K$+iZ{29NluhnXXF!uG8@m z`k#}X8ZO{P@={={F|f&Fw1v%h&NJYpd1t{Zuc-)_{bZj{oMtP8r`9 z9>T61sRNRSoQ|uNZvP}_!-L!ujL_ArkJixf({zVzC{wFA5*?RPuc))#d~9tbk=BqZ zHNV+4!^1E+*)JRT=xs?eZ$HKE_s`&^cm*rLMBHKb`*W1m$XiFsLqBQil6n6jAu9EM zN7^JT0i{7G0cBEcv#)^bpOw@?g^bmXQubV4qVQS-ELMVS9v?=+6yeR#dJL`6gb}Uj zcm|16K^e?+y}i;*SD(F{rmLB#g(o!@Ys@Hs^8aa`G=TEfxbYV}&RAncuw%UjY?o?W|Ca$7MocfSyT(~XY352! z#W^qv9k?IsDoxz$%*6e$EuAn09oJGL4Htbd4VS2>rF~v?)Q-Nt@==#@1@$B%w9~+~ zcT9t$xZ^aMIU0TMB<0nZF#6xW+0dTY-B zHZf2jCM49dIaa8ktv~Ty{))H4-im^ve3$r{p7HQWIGQX@psjqgRD$#f3^@Y$+3@rh zS4(A0rv9LarLvnggOSzoL%=@-1kn^GqF7K6kc`12$k;D%i)#z97RP4cn`sV9Wb$agIRfaLOUv;gH zmG?BERq}UpimnCbBGTfFBODNVMEl`776O(agFV3cI&ixji%xqpfn?rAwGnfpShzkn z^->1SZGWYu+(b@wy}#z$O{vKf3R}rEL=TX)m(RGv%;DT#6_+~`x@a8j%fB+6f-7sz z2~{5ITY33!rZ^s>UQhlglOziH?6^ZM%j`UgD1rSa4lCcfkpDCGN<^iMO?VLxlurDB zVzB-xo@?fak2ujBYreH7-ti`1IJNAF7oBW4(+rb&^{mIX2JkT_D-PYVi)%_nR;%Dej1fVKQ!#P|dy$dp_v_HS0e5pUo zMuYYfp8#wF=kC2;_v8Dck>5J&{{$rFqs}mbkB<*TBllAa$I~zJIakp!kqgINt+{W} z&wuGZPUpoMi+l&=W2h3F@Ve>W7o(3KRR6}pAqI~afb_3%SJ)LRpM%$hIpM-DApVk{ z*!*z=pOgIpeQ6pN4-NiWN0ZK$Z23GuitO9^G>@*6K#$iTRez26OVSY$PVIHFH!8FA zq-~k6VNOJwpDX;?RFx%riEA;ANR&T+B&L;2yMh)FT3A6ET39%a@zD2C^Vh`7iKW^sjT>z?i8;@nK)V!_bxy4^wMaroE8?9SWe}fh?n9F*;={j8_@A{v1 zy&Yz@l3tT^_mXfu|EI_N6$J9^MH@NOKT-Xa$ya3l7D^uBwpT69%si_s`3fh9TE=n< zaZ79FU#*+#5Jd>c0gNoC`{%W`4{G6rH%$4BV{p1BnU(2sBd6PAq zeZ|X`QcCBq$gs4WMlX$Gj}VR6ayBle>BR}-j+`*X_1H{)6?&2d=q`F}sS~59pcGT0 zv+-Dp>c7MIGd6n*vJ9JFaXY`R7QP-(X-}}wh|(Sq!4?CqxOlbsgQ(Ilma4SYn1&1J z=_6~B2;5jP82)R>o{LS{Fw8*hgzZ^!lEIAR*DO}}8#VYb{|6!*R<+7qvr|JA-Tfyx z1DWAGDbFg*sr~tB21ew{{pmSCm*EirTRpBrjNU4Mox z=wa=RV*X7dpa!4OU<&YgH#H5%X9XoDV3F|I-yobb7>jS1+&O0Lspq4RH_^TfC*~y_ zteu}*@`?;r*_^xWgDvIvS|2ywfqd)VG!Dt*3ipE{!ao-8@*aQ)W$2M*L3DU*9*JBe77<%=3 z^zlK_tN9@aJW?U3K8j_~tU;CpG+cIQF|bpY0FoAcm8zb#0T;6yg=VM(y6xFJEJJfmz|gGh0Ou})qdC8Ne(u6Qm$jCsFlTx_|0hnBP z!qnoTI?gPr513SN5y|PTeyd$ik1wsKL+cB@3oR_IsaKh7spqt8p7fqI^)V;+9nuGF zZOttO5#Q~{$2ZoT#4jSR;Ya>jCMv%=Lm;46_-F>psX~Qf0;!TEGc}*AV{M< zUy{;ku$^tw7 zZd1?qq(u-f3U*T|;(qFQi#Ucd7rR}<*u8gL!q|k#j-BIRZA86{kxcDc)#v6mY42K^ zFT>&$Y)|cr8r`%e_{qN21TRw2BMykn`I+k@jx~z4WmUncAshN$ylnC4dQF^Wl?Qo8 z%k#)aRsuKpDA9OFaB)8&HJrA3?+ApHWkd2_RJDqQOS{;gN1l20`M2vhXP>1{$srl< zN9h@f6sWlbMG!nDV-1Xp>t$&@s#PO!GUfVLxNdIhDK0_Izpb*_Y!f`xDygRHF#hWL+;HjW&%p?w)pF?IKrCAY%hS;?ed9 zE_x|=uWt6F}7E$5?3U@*!^E-zEi>(R(p^zo?O= zF0m>D+9{$mVCk>=P<=_e42I@^{xKRC8A$$QL{3gJzGuoSjt8SA{chvm3}11_Dn1?f z+X~vdxeqBSrt2*yjkNVpqf*cg+w&Gr)OI;fqm%0TyN0c|C3(DT#~+~r+UsN`5NH+u zVUOp(ROiYf?E7j`ZtN|p+Pj3xuF!C+=rYPBLde(;3mj>=3HVF~~6t0mz}#qP5VgXk8CZ2N=CH`O8Mnmtekyf)(pwD!zhb zY>L44ItJp0jkKlLdZ)ocvPk2K{*O!ebWxpp_%Uy{>?`L~Ms|4HS5+_FG-Wre)Zke) z=G`7|`^s0{_GjJDhutZAT8w1bR-YS`CLkd9vb`7nGc zwRbqep6ljjT`kn`kNvHD=jA3z7XrNfq{Z6?b)Z`3dMiMqS-l30gvJmmZz1GtMXlSb z1dw9eAw_y((c2Ea#+}K^uprK~v)Aag>V0#g#;b4%6^=OnE5d7BC%E2j&R>(~!8)AH zfPnQ~$)$|3&T|2JubFe7Ef~yRQR#XD5ClK=t&3@tv>0=f78%gxtWlr`!EuK9=NQ#@ zK`p6&)%ZuZ+G$GX3gkJk#+w4EFY>;6Mn(Ga^(-FJT~lvB&U6`}FTaWJ5(i&(BVSON z7sGpTjZv8&o`<6s(R-sWKl=T!@$6lrV)R$Ih`!r2t;@`i62CZV|GC0nb0hV+{`CSE zih@x|n*sv1Df~h9e*{d-@3@ijn5YT=OpGmDY-k%Rtd{#VJ39HKvkejw-`!}szg6VB zI#l-RyWIAssWY1DVU$pG*D-?>-D7?`9WMD&POB$Ufmq~c5Ae}hiw+x={#u#g3RhiW zOj_p_q4E9_^A|SwE6|(V{05)TNWkJW%rC$2?`@nZjmJwPHiq-cV^5Iz*;P|<)Be7G zr^K%(&{b}KoLJb2TsloX)V#YP7I`rB7rc5}&yG*6{*Ab@c;v0s-*x>Cu^-yNxuR5U zmD#T3^r%rUx6rQBX;DcJyrB~IGZty8@3s1Yt3HYne&Hh|(fgR!UgtGUHHY;pM(j^* z7sE@;=ny`59XA5oB@R{Q{|ofpiU6;yANBVRsFy~9b9NKHy8l!grl~wk7rHg=+8Qm$kwiFwH9zOc6E8c;Z>lxnH;jbn zA-7#)=dWEz&mmlK{R{h83$jM0X`}(JKeLKG1!ENDq#9?NzlBsF5HRaGC(y0_)G%i@ zpFkiACdTB|u@&oYZ$HKk;&?Kzqz9jff-$l3D;WDrCSUd}7+;5kqcSlAv5T9V*_*n{ z!f7LT@{6!AVl;}X?^#9X=miaZe~?&S@P)gMF?$tT^+-M8su5{_-d9;K3X)c`k!_5GoSjLH7rEq+s*=;qIs zW*W+pH!RJp7*m$Kjtja$S8<{4@5&&#YuaGcELOZb2I1Jn^cS}k+)ABUGKTW2Rii&f z5}Gr3H?50+Q)4P(ULu5X40m*YoY*MX7b0mNs7~$0BDIDMDApT`XI#;6Wh?;3$yS@v z8z|gJzXg<&9i-(3Fem$Wb;6pRWi-OT=yaggKUjE<*KwVz{7&C2lg#NM`%dAEoe zNE*?qMbU^UZS{k^Ssdcc;s~v9GT)>>d9@HvwR7rJET0xeBXjDhX0e`~jk2@~nj7^u z-pIRXW}T2SlshdH!DR9WdgrWd0uY*z-#ZXcvcmg#WBF^Wpehi2EM@}Zw&w?$q|E#6 zmCjm?ZPagVz(!Tm6iT+jVtMfo7CLdN938Tp7W*$HmvmG~PC{j3khRV};y)e-sMef}Grs^)w)oR$zDy!c)=m zZ-%3hzo&jrMGfjr;D@W6yn_N73`q+?#3_5`O0V!eP^qBT)lNd)<4-=g&QU zOj$vUw;+jnbEa}#%(d3l(@~^if9~VM; z3Eda3YnFg)xR1W*7yVCI3Lj0cII%2s3Rd_Z@_!>qoF!M&x;SpUrYrP7WUc8v^wM67 zYAHa{iQ<88mJR<}vxM}mx9gU(4Lo&V%%xOT6E(k0m)xu z=eow+eFA47Cj#jESNx>)a4c=o>;ym&!9j@*_RzeG7*i~LmjjJGMuRR;z8aVwvrC)5yjiI z`|=={M#LPD+v)sYFl~_0!8WM>M9P{zlv2{RnBppO1W4pYidkS;$K3pM)ND2L_xuc} zYh-rTP64>6b6(cF-cX3V)i)0b97N!f!i#;VKNU ztBZyIiDz5*0)ZY2?RgL6x7xxr4^;S8u7`nKg$WB5h+)*p7R%f+d2(`vdjaPekeJM? z=>#>d5E@1YcNwY>!|HZH`HHYXmdrKU#I`rG@U09l%UCpL6}OY1lH)vcQnxIan@j-B z0~822h13KXqRKpU@kw;gtP8C14KU;Otro9HbAz+-`#%P(JJ@MX$&tm+SsGjHuF?4&`gKg@GcmtuO+j6?J%>1UVHYha7%4>P!=pUjGB z%hy;H(;sHMNZ(RQFRU!4KMZD)USWwwFCG#cA7<4sVQaN?cs+&R?pId&ecG;InZiwB z<3zu)mI!@ls^dl@*2P4906_2@Scs8cGzQ87Q4vXMEWBiNk}eD{F4S>%Sbh~^Cw~rm zDT$Te+il2!JUZ-z^2$Ej(%T^-tUrwZB{#f?GjwjNoa|k^jQOi5EZFG{ zuDZ~8cSHZ}jEU*rm@NkiuiC7|a$%Oa<#jP9_M*;~GCLOM&%O~q7H8b-&%+U7FDL4i z`8aQ4-jZ+~?K3+nOC1e(hR1l)^*Yj28(Gz``iB4$14w`Y)5jji$*ueowB$Op0&rW) z4rt^d#V~$hPSGdaYlxU&72u>LBIpkIPcLySG@tW=Od)OUi(~#4G2)ywp<0SRdyd6g zdgHZJrMd*cOSWff`qynTN{36aeNLS(-JaAu={BW4H^SO5bv#;CsUxIHwHalg{{O;l zoUu0i_QC$YT7@B=EBc=vq3G6s526F5lb%t`yWn8|PkR_e`c$UL{a4vzhN1o9Ez1Df z4tH6FhWp`Quo13G)X%2&X?lQ9L+@)2^PZ7BM0$*7T|b3>S9<+aYWh;G#I`6hf9*Ux zL6>d*5MFWbP9NEditEE`x(isT;%}-d=1nG^&yMJtu7BTIdh>pcIo}suQ`ogdG_tyi z0jP+s`Rj2Di6^-~{r5Y{QumZLwIk*IBjg+Y8nxL!Cn-lZixa+g9W+TBt2S*07AE`^ zRiGknotD+YC)8yw3@-~gotqiRVfaD#Tjt_I5!N=H!M2HwUtG!0!cYgUsNRn|qV2AH zJoq!Yo<<)`Tw|7F_RKwlX8=>i^vvLd#`c96 zkcH|H4v3NYTy;eARV_A`f5osH(aA`XYp*BeeLZYGkJWh^R$D_xdk6& z0^=!y?#t{*cb@ZZq~|jHVFKO1mY^HCUmEJOWyAaI%27c5<38I`;Q-Y1qxjj=oLl*s zG&jjf0&%c8x9BrzoH#c572D{&+tru6fA-Kl`6~l!rU1@gcb5A_gmr-fZJGFSAoUX`B&Tt04sQ+tFh>w|9j z5gjag74^vz=jSF5)1T0Y$=6@3^XNpVI}zEFdfE6ci#)t~hjmi99cQNhllsr0egVW1 zd}p1(nn=*|(~<y$J;<+!&kF4~ z(>x5PKkPW`U<4;>Yf+Q24l|)ee^wqS&kEQwWpQZ@TwuV~an;L^>wjP*5yI%r5TP@m zZDEL!P0y+D0CZ_0(!77u5jO6vHW|_+?`DR^($mZq5h}t2Mg578r|v0_y6spBCBx`f zZJBsP=iGN@`xAd0El>O#r1@dF&LYjjZu`T*=XW7hKaSy+YYGyW2ZNUfb!A54%#WQ0 zFkH5_)JX4m31fm&!IH(pVb1R`7jN)ek{qYUyzQ+-ft&Uqw7pIuBCfTrUzwjmw{Oyl zuk( zI%~y;W(F#f7i9*K)W$OGsaFep%{Ue$z@XlO|2E3wIzP zM|gtG$)z-?@D+ZB<^up@7(Gw#3_or>0AtopJrE!2k*D9xfw8Hp;bTq^4~rrU2bcLf zQ1R-|ZR#~u0ozb@va4K%>m`cNdn<%=)-DEMtgw?cJy>AA>?^e!|Hs&p#a8{U24bwPykKznpRTU6=HNLsPHOpmlEGd zaM&(WtZp0d*BJ1>t8xX)uSiMG$7#_ph9_vK>)&C}0S3n$+A)*N;bW06BAIz_Sfi2I z&3jPr5b6DInFByrqw5zkiC2;P(%R_V>BqN-HG2LF2gMp)d;P&phBw;%$e4gPT68SF zXT==F{PGgJ1atI$n4_Oy959SI`V4y=n4_;<5K3(`VOdRo(&y;(pT|H3<9$B2e#T&D zm-Q3L_+f0Tq0Wu{CL&nVn+nUS^>irdj~OwO^brkRZtSig>97u?DH8+s(R35MU)l_F zz0L=4*wa|%Rjt|XC&bmI4d>u>mccU6z&XgEp%1Wm-JkjpEjds|vQ%H;0{|j#3mt>n zs^-RiLOV~5_d%Y`hre)R!pQP<5@TwI%Mfb&EKFprB{Du zo;Vw{JDcTTyvCu8d2t56vns3fqD56!ahtl<&7J%LVYa8Sx4Q7}mF6sNb~Li`&V|Vt zcvxvey(IbR%pmI{uQ*^KV`dQAb{;nfiH)zI09YWM1`vZ)%x7~HykoJ{@bHd>WZ_{Z zr&C8qi-H%|^r3ipvyK=mxXu)y8*flkD%E4z&k5$S=G!{8r$TQ#bXWu27fce|g(h%f zRu$;xWLr)C`;@=Jy!fPPv$>t9{6}f5I(}^P_nu?&mn;87Fx<($rhb_;Nw<%wka2q3 z@ok&@0q8l^>5OU9tZ@jDoh(X0WwR!lTiKY-D%WktDK`B;n@O)|(3@tJ3$koR>Bn)K zJbRYRcvuf?+Lym((yrjijQ^~$=s!8xCj|2m+$N8kHGx2fPRAe3gg$v{l}Yc~+y_}z zfXryU=T6>xfq9y0zg_$#^Q4mpx@-xdY)Dzf6Gs_D4`acbE zRwi^TD+Eb?4*T zUw6*wCdoM!y6ai$RCg_P&h5h;^3m06#GP>LSefETwOa;6py2+-)GrDPhrx%ldg`0> z1a``*1OYAZA*G!dayCD{X1j=4_W^uJRnHy<@iT>EDPq=9nsgm=4JA7H5+*%8vDrSw zPc~0C*{93KnI~EQ(ZN$%%#*SH%bol-ay9Z@X1~p{nEf^T^lghs=h>&n$C#9@_DNCr z$aji;`t1A7(=_|kjHf5Qon)Vm`-*uw);`^HqpS*+i)?nc=`;>YMBmqZp^1_SJbf9nxFYWp?jNZaaOE#4zS0ML!RKZ&3v%`>d z%Fy53*z;Hq64vvSPVW&-IU8iTG3{BzBmG}B236*KQ-T+#<5oUJy*}LFN4xW~LdARR zAq-K6nYa}#+|bI#x#(gfwUIA3^u~;r;=xrHNv37MWAUSbQaZrY5<$>H1PD#2k`WC!wa@_|W2C!6s>LXEZWp7ONUw|k)Jq>4?mXH@)P zb#4C~i{G3dvLo0L+C4y`%-+z1eX}DKKe)24t-eb8}cYm zHF37nc*#Z?NgweTU5U)EQZL*%FY1llQ781vV!UgMTT2{p*xB$JkYJ;*)Y?4fRl-nqcFS@_c z+3-ssissw_Re@6pf4y-lBNqn?!G%O_L3r_2SPO*Q@-uilPcqW~rxhG#8~uYT}eMS^f#wHtFPxyE<;#)slyAU72mmzd_J({v>jC(4wgE&C>EMiTCIjQ0jUT2Rrno`_cSHG^ zBx=oVHtXb}c3j2`%ty@haXR*KMPIV8oV+D^G)n%ntYqI5*xRCly;~+uNBWmFV49MZ z!1C-;`5i*JnE$gfE(!k^Ra|IwgWp_hob=92ew6mll*-La!mMY$UF?d?{mVx5 z1G>+3s6$FC!}UMo>R8%8y9UD-BFPwhj7Q#)u&3VjFIy~(Y&1F}S6*0HN0xZ#g=nP9 zSuclfY?xLa%hnTJWyCq&E^sd9PwWKyP-2emK7ciL?8FD7gsh(O(2R-Kc|ze5usJv%-fdFe|Kr9iQa^ zbhwZU^dfoYJv5U=;OX6ej7N5?z92qjkJs1Q{;ZY-aKDjxo165Z>M>=rPpY_Hv%$^9 z%4Hpd{Z|~CVrGWNzuBz%rjT=WJs6QK{tUG%W)$bZ7L0O={@Qv)@<|2|c&XV@ExOn6lZy1|TCH1o{{cAUWC#c^UZ z6e?{;KEt7?MrkHJVV1R$g`6bVrS*Ko{AGQh8AZFwHMUpQht)RZ=nR!BDIS-idQ!F? z%5B~lRih5EB$Bo&hbD#_HB4{9{|MSaZ9pOoQNPnp{F^oLQGU|IM>~J9e?=`8xNXth zFCoAqe2Nr4ie-tkNj`p!Et+pD0*NsKeSV3*7dHh+RK3 zf#}=2W__9xz1Q(90Wb?Fk>1dD~v^>lg$8{o~Zq1}sO-t5WV z>{^2=nPo*v&Z0(Fjw0q*dD_{KuSGzm$$SHeC@WZ7C50Hm-=zdwYNM%z_wicoeb;fa zTc92woYuK-dl>UagSR4E=Uz-xJAr?XL}4^pvOrrwRwen98&Adv4rw3cwd$1bKrhySWni%6CEQPcE!URS}Dj)H@x&WN9Il1S#wiE@T7?*9&|*$gO3CUn@Tpe{mF<-}d}LR2_i-rXgVJNbnEn zn`XFwix8v4|H7eM6VCI#5y6DU2ew1d3Cc51 zjVgUF527*xQm6=HI6%;W@IFna2G_stW|K(n4e{AQHYS?u-!@2Wfx@L4S8JfATT*>n1$767iRG-^swQ;Zc=CFCLK6(3_j@cE$svV?bea6t*o{E zmE8j}Of6>BhJLCxXuM%BWsm5Pfa7wqYUnVo z%j@pmFPqCD{oX zzQ-Ku1^X9jH~IJH_hJ03{OYwLd?WJz4O(LJpGHYRe%fpJ-9O}SGx?K?Mm4b@Q@B9z-?FM%%Z5s3NA-zVO4oMmPJlBV(|^6K{6A=d zDJR$(e%};Ac1d<6RquuPT2pLU~-EiPOWZ3Y2elF8vE7KMOr#Xl;l3C^u;X6;TUyQIS?|BVi#_>u^#V zoiXv3uK(GK>1IQ5cgp1tL^tv`Lv~lqx1CNOT-=sJ6q>!(->4(W*&LL_3?tV)_9Ok6tFEXes z(N9q4pFo`}KjhkiUX$STrM#(lcL_em*m%nA|6u4*Gyc+8jZPV$GcyPA>~}5o2)I?t z4~5Igj~{CEdQ*3p#p7J^W_q0dJM4aabbkq+UK*y=;1nP)!PNgN;iCbY{!+4f1GbZ` zA=#)tll7YIvzvp4V%}KDAAHGlP4+LqP%5}^5{ZlS*Q6e{o^kYD$ba6z1O9c&f!t8W zg;3Ao0NoH2zm8O+0IDRZ1?WEmfK1PSGstn~h;pZpIM~09qIU~9v8Ch7bz-5&^vKgM zeV-LcPiKf?UgK1r2CEvgufXb{TEc8@@$bA}vs64qGLt|kH!c)(5Blrv`$Wd5 zVsY46l{_xJlGDaiFEaKD@P>0La|&9OdMR)_-`f;p^l;?>d(9b|)SYtoTu;yS7*ekj zt#X~RB_|CXWd-gzlaodqUyV?D9_{*-Gg}>m4G*zmhUVGXX-1|jjz^v31$Rrs!OB#$ zP?g1|yoR`>wS9+VO|$*1=|6lq=O&I1@Xc-Sqd_t68slmm-!zGFM-ynTbN%}y+eq!@ zP3&_DAQ*+0gl(;h3|zT67{JO@2E0o)5o0&`MRDS8?#oBd%_Tp1O#jiP`K1kQLaMD@K~#1;WH36484 zik9|w-0qif-+a$)BtW8w`{oaLJ0(x({2tv9`ME@2xNqj(ZQp6!H_u#W=x5A#jQ{2b zotE)||K^XNpJRke=oH1g#lsyqFJo_F9IIv|Qq#JOp1jxmj;-Lz+pRBS3vba=Z!Gdx zXJadvPN+reAr&978L&*b|w-XVc|`)2w#HKXJJ zI@`jx-q>%#G!@%+fe@NuT(&y75A(^wP|QeY>?BkRhoVno@7bQ0wF7atU(Np!5w`1B zyo&bHVm2a0{5q7s=VK{#Sf79@2v2lu>0hl4dFH?=2=dF>v*7CDM^bolVn{pYR2E%8 zuX3?V^lvo{2~O6Z*1=#)dsiZt=vkIO8(2zSH#;I=%&7K7O#4=Evra-0x^0NjDfHZz zkUJ8aU|Lu7J~LH+gPu!S^w*3t{^tO@?AH`#)kQ4-k!W9^5#u)BU;nT=wzd7V>iPbH zCpjv*rblchFKXud*E}iaMDH|XqUp2md%E{~7Yf{1%H+(I0a^_km{)l!kaXj6dcbN+*BJ`?)FniXR-aLOKqNi#yFv z$~{07)zQ}WT|7S8+Wz3FxrvXrPI(*!mGHq(S+hU!yHQk&W8Qbo2Hf};GURr9MWox= zxQ_|mgO}@~uUd1E+B>I)7ULrlE0m#wf1~^@{voJ;EEVEoz|^n%M_SvTZf$>v`dd!T zRnLRfEq~VlaMdsX`oAN2m4P339nHTB^6UP$#r)MCd7By4*3dJ+KRkP(kx3Nf$EcxH ze>v^v5fEs9^;P8WefvFi7bM1nzYOvdySMqNpnlyyR;s^6^^^Y)^>@)wAR8`L~F;TDS%5S-PorPOV8?L1K+3w4s{RW?BaG zu`%DP^w+b^WPQ&~iu}b8soAhvLqw`@7N3VaS4#;eeRrK2<*yO3P0qK(fq)ksU3@G& z$q)VSd}nSvn-K%XESt+ z0ilWaF@5n*vU(3dG^$3fZg6c2t_#i8f??z1U?gDAmL66#P8-_>TD?h2vxg$Syu=0k zOW?0+O(SDSl5d(MI1a1oX{;^lX*^M$gMg3qAY@{EW?UsSI?BDqMO{#N(SOyj^S`>l zw~zO*(e8_q5w8?dm0tHF?)|IN6pVW_XS0cFmcMBkR(e+}x{E(=dhpWAJiv2)EuXxM zcv8E@5Y&!){ju%Y@B&xYdk)V#avGGonNQPp#Zc}dPD{*h!J*~mF0_?mUXB+|Qj?YoST~ttl4^g*=nQLJPC4WjNAv<2#o*X?==!pzs&?RYw(%I0wZT3_nXwAhd>aw-#qPcgIfYu8N~DD6DW$gB&C6 zxA9m59o1Rwpw!l8=yr*J1o+9Sdwhv=c}&x+t3uf;=c`e2LqZi|O5#>y~f`lXrLR>}NB*<)Z# zY6}W+J#$VZrgU;ykRrX}xU$scrapWdZXy96r%3TV+W`#V`i*pujzv2{^g-{OI)T=I zLqI>$t7=92eI-KIq7%}PAAo9`?WEC&4gw*W=t8T0V8dSZZ!GekCG`9vr83Bum_ZIu zHf-MY-?Zk6>Ay$qZ}o&VSJdlf)rn+dH&ah-(5H`+49{lz!h7sv_yT(gL`dp0`zxGv zn}HdJkeU5QI2)7PcRUCI=R5z1M<$Y^J9?y+tFs}?!?aiWGd38zfToo8LKJA8(^QQ98}wXRr;Pf!R2)LTmlE8$tr-jk!S68IxgnM&y>+5MUcp* zAm7f0Kk{Yr%w+eWPP&J6peOz7ZZ z{4sIl9)G}+es!U3*o2j2_QWrchxEnF5rxfj~u67oaL ztS!gUB(p)41Q-Dgl|uW~L&jAyD|A6jBm{t*WrgEuQf8nX239!P+2*DV%PxQH z&#+Rly(A%pIZGevo&bvqzcP&=T&P@IX9nt%Uqy4+>5v`^Mf`iI2<`5+>BkmP!(Fk6 zi%n0Bol{B+3}xH&W7C4%rL=Qw+OL<=Y6rPZKQ?Xsu(ThvX+K#?t9|A+{n)f84NEH} z#UYGHc!$IY1=z8Pu;gH)d51w8-P-~+y9z%wXfpP?+G6K1SEvP)h zbk7MzV8O)TJ2xdb`)sm1{|{~N0$xRRF8pVb4Fm{G(5OLEo7UK73koP4iNv}mnF%|P zXb`NR)TY&1rrH)Y5fH?UNtEd@il^FYYg>AH|7>fm8t*-O6Uha8<+cOOVeouiyoJsqtjNAcBs7T-XZkOHB30HTN%~w-&oSF-!g#?m|keKiMiq} zil%Gr>Roslm%w?Hoq=vozeP^l7+QyVf0;;2i>rhe5>5%vNw|sg)k%REbgtH)`69PI;`SP{~q3H6V z{F_5^yR%8-=YrN!NcXBe-?h z=MQM$i{#$+hInlh?_YcT#mS(2Ll^L%)!jsmLz^#Q*Q8s)P!6_2KGe0TO5dmQN4l+} z@<+O-rSmgXgZbq{-HWHP#=6HGl{MDgdueI_ge;{;O+J!x1;Y{TZz4RSJ3*%5eelEo zk}gazJzbc5B-Q?j3_(Qe=#Cv#fQ0@aon6RNI=g%*eS_*oyu19U%<=9i>8wJf(^=&s zc^2JJSvT>O0R&|pRX{4H`;ydX2r*3;BOl2RAv=S`bU#JX;bWi*>Hb5y2%!h*BIF|} z{-gc5ptq}zDj-JamFet40MgmzBl&}Lb}uK|U3zqW2|hJlfKZ!s0rHUyrwWLGiQNY| zt2ev{D)=3OeLNDHo-RN>lHHI~)q#kYv$p&3qYIGW-=zx>nw%~`K9cI5u(?ygn#O?ysbak??de z@{v51ViZ0F`T_$VHpZhq$5hVpk2?!nI+RC$#T)|?Eo&GNmqddgD^fAa_l|o*BE4}7 zd8E_|DF@_AC&8iEw7>V7sC$nrHCSd=Ixogn)}o%cD!2Z0bQ@D8m=6&oaX~3|tj-4< z9YXg#M`XV$@p2VuEytbYzkKoZmYJ%g50vOBIf}8)6Kk--DzE$sF1hC{XHD9USkzCq?PzWH=Sptt#!*dHm}qkvXjNqt8Su*Vsgfra*wdD zzkEK%wyKF$-c?s{=U_~dIiKL=6}!C`mS8BsN{2sBFQQ zSY8xQP^x`;-Y z%@?pQFTQ8r;Yx&SCM@S1d0E;NuX01@tgbX1c31~+C;c*(R@<^+xtaU6qmYf>jXD

    >7qtUWY2Z-+AAC4*;OU`>t7NtvMltot4n(7*Cxec zK{fYZ(%f`IsZGDFm9A7?K6|Oj5Z;FP^6 z4|}La!Or(H(H;uyM1h?suoK7+IX?8TgF1gnm78}aPYl#rnWWDEAU+qIl`DQ|PE_ZE ztK6K;)lN=3|2K=97o+64n|e%dGK=HgtJyATqB>+WHgBGr?ct_JwtcHF?>*lu{aj+I zwa=@=pK#~P2iaU@cTTm|2fzuG0f!y_v0?5WbZYvlN|N>O0QV=OQSR8cgEPq0UZ_*< zi#i4{ZI`M`+Hc}cA%V%(>}W}k-ZYiLW{8%nCIp1TK>Z=#{3YdX!J+ddJ_-CYvTKP( zR(4)~9HbL%pf^s;=OT?*ajE;mMVkRl&Bhf3DUbkDlcYDEP5_tZ$mkml{hEGTHE(h| zM_SA1-X|y`qBpBkoKRKbo?X10kmL!`D_~T#1iJ%q#MzIh!FIlvuD%8vhLG4+yyMQs ztIewhzJK)lXCq0r)!wu338_vsw(4?*upA%WhncaDW_#x8Z29d@*AjIvS~ACzn*~E> z^1hUJ=vU}Wshx2%N?u&`8$3`*Gh8JZn_g`uqHU!ZMiq0Ja7B*XDM$nK`zvrdcYg(^ zqUL9_M@x2wepB|)#z2Xl#uy1d^{_-MyJY3eoBjo^r2P;m<(}#OPFk<}uPW}jeNdic znND4BPeBj#Wp@Zprox0D%MoTZ*vY$zT5qKNC&~HUsCx~w#G&1a?5I0_?Omc?GS@bR z)x$fD2d=pF#=}g9T-mKRPt+Svpe6w)KcGZ!ED8cd2P&s5?h;KKI~%@}1WBqlYq+F{ zBK6&NR;kjfylV&CyW})XmG>Ra^Ct27 z>Mfqt=UBjug$iRbwudM++>558&Tuc9$$(wS;BZg055aOBM^lviqW;vIrcfnmp-f|4 zYbry~lp~FxD9R@9SA3|y+?wg-MM`$mWG*z$8O&{G5V?w!F>Pe=`f5 z%Gn*PKdZ&GQk{!y+Fk9PKY-t&5Dr*9$*DK~j$d~IduWZKSht|^VBH0tDGaS^M5Wf= zlUBSHz{{4R7g*zECCGw$A(dYAjZD;(+PBL2T9tD>^FQo}w@**0irY)XiujMx33sIInkB_1+>bXfVvl-@YU^eg z&VjjJ=tAyl7!mc>X>m#JY&Tt&(i_pf!og(8*j~RIkNL8wB$?LYmC3e=jE9VdgDWE0 z^iEY;H>1k^nyPRIp^CnzqfS&&*Jmd$ACf_D>Z4k9ysL1KskAUD$)+L6m1O>YtC@pjFgzi6tZ#{}&RSUiRBUyK z(^z_Q#fZ`gdSe~fQF^T2h(;r$6i^45>;?+Gr*%y&c|oHKN36Z$JG@fMNQmCrHE5INW7OI;m-}zb=lP?d ziCX)WPQw*`*cigbs<7Arjo>Q@zW!`gc@DJp-1YSmAra2lpJ|5QpQiLbD2*gSx= zB}*QOl0-z2Q6#g;gXu}EKk`$l6

    #m(QcYZOG@2qjx>f3$5T`Sj8bCi0>%`=nI3hZkYrQ7-= z(Us-%`LKYf`K481^^SXCX|0wgM{PM?{rm8paZ{&^n>4IIdqm5Y`?2l+3#h7HP+C)G zSS5Zr^y}mSk9A%aV|hrQFUn_|H_BLki2t8?z?+%>CZu!a*3A46KKnd3|IeEJAJZH! z@3N(_u}~}=g98$;&%5=9_B@n+=m0O<@)|vj{TscF`HjBDQH}n_35|iqnT?^wipFqb zLt~_Id1JJ3bz`hC-q_Z-sWH*GwK3VavoY1Ur!n1lfLC>SO`fLyP2Q&bCSTL2CV$g} zra;rorchHwQ@E+2DblpODcZEUDb^HkYHQlmlxW)8lx*7Blxo`3lx{lEq~dvTPrQHJ z8_$pX;-ljJ_=I>MJ~JMQSH#2dhIk~tJRXg&j>qEhcw2l^JQ3d-PsVq~Q}I3Vbo@YE zHRm;Zn)^3N?Y4#XOcFiX`hF-`Dj;wHicLb{Rc-KW@NV#J e;DS)==l(HYY?Sn~HhrJn-K|2zVp_ literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/libmodplug-1.dll b/venv/Lib/site-packages/pygame/libmodplug-1.dll new file mode 100644 index 0000000000000000000000000000000000000000..7c0512674e8e43019777928ca42aca50081a8795 GIT binary patch literal 252928 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/libmpg123-0.dll b/venv/Lib/site-packages/pygame/libmpg123-0.dll new file mode 100644 index 0000000000000000000000000000000000000000..c7809b163f5e1d305341bba3e65874efac205792 GIT binary patch literal 337408 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

    R*lGkf8duJr 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�LdO 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
    8ct0{sTCmXBG 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

    X+1HK5H555+BEBH?Eec;EzFM|(&zX!Lw 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/libopus-0.dll b/venv/Lib/site-packages/pygame/libopus-0.dll new file mode 100644 index 0000000000000000000000000000000000000000..9ba6c3860c6daa71ae9646f01b43003dac3798f0 GIT binary patch literal 124928 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

    +*%ObQ$CF`z)rK_rUQV66PF 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≀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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/libopusfile-0.dll b/venv/Lib/site-packages/pygame/libopusfile-0.dll new file mode 100644 index 0000000000000000000000000000000000000000..97a88b6108980d2450acd66cb36193e4cfbaa30a GIT binary patch literal 46592 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 z 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 HDe!*)FtIkk literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/libtiff-5.dll b/venv/Lib/site-packages/pygame/libtiff-5.dll new file mode 100644 index 0000000000000000000000000000000000000000..fc8a7c0ca04ebc95ae2549d80f4516f771003731 GIT binary patch literal 432640 zcmeFad3;pm^*=sY2}-zOiKZ?kYN){?5|>H@Y=%tWMg~OL6%h-L)Vd(f0B(?RW)iOB zAQq+Sr>(fu;!^jLXsb@x0$3G-3!trt+r5qpi(&v_e((2r?wuuI+wbT5{qvXCD|7FC zmh+tFJm;L}Jm)$0xuY&w?81D}LyI1AC|{NBrGc=(@*g>PQ8)7rH8skY4j* zp=%up{Ud(^{8!HNBX8P%6e4cyyVE(lPPuE$v;i}&@Lz%FWoO{01O)~%GrM4oYg&B3 zY*p~v^MGs(@`vC$@UU_<1AcYmjfBu}G=B>_sVOo zpYBp)gE4Zkt4lkV8#s(${{O!;1;)PQ%5k~$(3j=r-QVZAbYqonw3=(T;5PEUZWNqw zOCb^qPQ;}J1zrBGdYiEEz_=b-U4H2*pZpEb`h*3jd))Ym6THUSvAXd(p+?#Rw?#{r zUSH^{ibvY#`$AvjRK<6iMThWXy!JcXs8Hudt$+*4MC_U8!Vfy9-1 zG`}y!MUT!bs)`fd>Ei*UD#^C1_3AY>%{l%m;Lrs))Kz_wING-usam)nTTqC2jqOtL z1RIeLtCG=zE_jH<1M~D)=|5gYS7OC~#igwvaZ@3w>oSJ}F=YNuWiG_UJPS!}1?y3Q zoF7RBjv`7;1*?#vM++W3Jzq#tTyN}rnI&{%YjR_#VB~cG$?i#~E>(S0z2Ev>o-46J zj~34a2y@T79KtvT)L)OZDNOs2X~tST^mUP5y=QJOJzB`Ff5U|2MkLMo3eA|y07!2u z=!+`+!);IdwymJdzEj8^gQw2OL<>6R6}nzyzaw!iY#vG`txJ>1q)+SP5l+)1?MCT~ z{n0;TN=3PD+*&cv*sL4ZR1DG$e?_HkyyZ1!RMdElHGwOl1(#ln5!wqZD={MGWnj#D z!!)+(#y)e_`*~=>SgVB}Lt~)>dHx$B@B6PccD5B<1n_7xsYlsFlwhN1M~|WvZxqmh zwZ2O07wU!TQfL9m(L9&Fg!3g~G7qctYqaZWo#TbWP8ea6$@KjWqLjl6v@~=FXH;P9+ii{{r zu*wanvUrs7dY#bAz4E(@o!zk^U zjb5YOYi!h8_y4l~`+eT(c;IFih-tUlZXsS1tvjCpe1ovC;bLQq;xrYS#NBt zYBw*z$e_7FXpQ_G{PI4G3R!y^*?A^e`&OU{{+_2BZ+eYKD;iM1Ydlr4P_AuW5HT(Md;T`D&ESD! zBxS3loQvP!fi9BLEgxkXeNZF813e|>Gr2F7``6{3T2u@F8uwLkpLRX4pzKVe?99Zo z2oL)K37Q9#t_Nn`sNI*S>I;*BsW)o(C%BqutwNiCs)bKN3v(|I9vCAn^y2;9$@7U{vUi*|`lnBoA*K}ztz34+aw0%M!NI9*c4 zNZp}wf3n4kd;FM%uod|zt)MZa+Gzkg6gxO)~d(Z_T$;=5ll;JT76aZ=; pb`gt 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%0A`h6`vddRtstX>9ljm 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�LR^nm>oa{Z6l4*V4!p1bA+ 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/libvorbis-0.dll b/venv/Lib/site-packages/pygame/libvorbis-0.dll new file mode 100644 index 0000000000000000000000000000000000000000..f5ae1bf754671625ec44f9992efb55e0ad5c2dec GIT binary patch literal 251904 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/libvorbisfile-3.dll b/venv/Lib/site-packages/pygame/libvorbisfile-3.dll new file mode 100644 index 0000000000000000000000000000000000000000..d0787368a3e30fd363c1324423c78d7e06add0be GIT binary patch literal 69632 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≷R zSuP3{rYsADrIe_Ne*spy$IZ)K{*3HEVe}h#DEbl%sB!&PE@R1LqdQ=J@K6Su$toT0 zBSc|yCi0ks$f-V5VY?%p2#yTGg5Uu)G(U`70xv^5^U;>S<#1_@l=(Yd%iMN8IEz#l z{F{`BhPLYPuYyS_MrbJVp}GhLex=c@DthUiG zY&|j&i}t_twDh=H>8N=O|8G{Oft9FibE%$kv?j?$8>qB``A+R<-ABoSI*mwSfU1>( zQ8iu^Uf*WC2_uo2Ruso%NxDKNsoS#%fxZ(`XCwKE1S7=mz`;P-hS>qZj~$I$UHC2k z*w5hb)$lcF^mcSb=!A5rUliBq^lvf(bhk*Wbqno78m)*snoV@JhSFgKZPl<6VM1y@ z9WB@a;@EEFJefmFMQrm#D~UEhCC{VTp=KvdCC?)+sms|PQkeN$4hMt7HP+y`juz^w zR4KX{hE9K2X06*>C1p^rEx_M&cl)$x0riCH5g^P#@eA2pkg3fS+gGd_W6f@>zAQ6a zRJ6I#l%THBAM#IOM{NYV9eD?%pHaGsRskgj#<&js4zxK8_kj9sJ`f{0k^OsBK6&9|e;|?XH3yh|0kDid#PI zH=3?!KXJ1RGW5_EqQ1{gv|CnQ9{$N2dHDnlGAEbf-11#?mYjL##Q`~R`T=sZ@J@J5 zK5D?fihK)^qT4u|l$)umTuifY>snJ^P<@Yfa!`Zg&Zxi0-h3$GM5u~8a(Kr(lrRN* zKWe$Jy3h}l8$S0(=13l#`%pKxa=2Q0g?<@!A1x{SE|h_`myFp-?N8zIdptLZXXt!& z1J5CMh$(eHY5CwUf^HBiB2QpqUmp4+Wjj2!=RLNUns4ei{0m@4ajY4ao#XiRggkjD zzE`Ru_xnN8d$VmdT$s-$%7r1Ypz)xegt(x+R< zsTK6NQGal>PJ;|MFym;Idm$a0PI858u5KX>kiDS7hYMD90s| z&n%gPve}tfi${Ojq8|uR$jHu?{j*vA%e^gJ9CO=;ghE&5jtkE>I$cU(PxN_&cMhbV zuF~^49Z$8}CR8Mfl2-q-9*~ka0GsF76kib>H9*G1V!oAgb``-Btz>K4i!xkR!Dg9? z#)Xb^`&!ta8D1%A_;HoGho;MlRu$FvfWo#^O8RRv{m|dHHsWV;8bbW)7#bCHwcAvT z==DUC`1-sV>VnUEsKb0YGyZzM^o2DnKAk0)MZ~HAz4K*&$c0jN*k3=FPvM`>IqK_$ zgb(pjWhOD5vNCbxk;neXMCzkP4He{o`ta`$>TG604T(7*!nD3Duj8hvQ)T>cu9q=`&S?Auo&xaX z{J|TXu%FWlZiYSaX`pLWH;QlLQTA^fXN`{FzP^O%ubX!a zc!q88%a!C-{|gIl>*sxHcgDs3p1k0DB;gR_#eB0c<(Io-tMW5d39AMLs$P*#V80BX zU8vX%*EiMu;{gNTxl+e+p6Y{y?tMysb5rbX+G%q3`qrn5q?Xq#Pn!7zI&?g-g?+K1$BxEXDHTkC& zPYx-Sgx{u z7?y($>5VRQGuZ-QI+H4Dd6D{rZ0?ZUXw+rT&+3%JfWa+6*D(=$cyZW6;ji%ml{cK) z>JD*0iC67CVJb%*GD4RfV@LnQzS9Qz6({wERpbMy2*Y?P9W!efnJXS`_ID^DeKK5e z($1w|Z6`&f2loZP(uqrV=Rp3Eo1TWg!fESf$N-jmAigW)*y%q@u3!iztdSh{bti1& zYnw2)*!0~Aj}RiizI)XC!+kTMwD03by-(tvPhBR=u32J5PB6>6z$$N^E-$^mN6}U= z;S?z{?MnH)2kmh?K_VWUzV4F-TJ7`K6I}Kot8#y?+-9)Rc5rnf{`Gpc~`uBtq{#d7i{U1p5pJ_C8C+xsm%HZs_;xB6as*gU@_i>d59WbJ+ z3sZ8X&VT!k)MM=Z1gaW$VX>}Gk$a=$H=s|T&r<|>;i$4ZG{H=8Jp7)sfVLM!{{$;^XS2RBO zth_!Hc@()7`j8tmnp!S8P)nx4#>C)F$^H%9bJeGf?zt%>8K^Rs^yo}!TX>?CH)ksb zvkxZ}`ACt)TO?7KPLGszB;I4&;kn33b(-2ZGz&LOm{0P)ApHD6tG)`KreNrw+Hyl; z(yDX8gjxudU6}|XKC7W$E^?<>tAL=(}v;nf*iOzqyvGgvXvq z5*0~sK7eoQym#nZscZ~}7o>Bwzqf23U$f2hd7r=e4o7_k3P3SzX`k>FRUx zF2&oz=YvQ5X%{vn-+YRvY`bi`EMA??cW`yGSKn8{wf$j_EpmoT#e(VI`OjBt#@Gep zLTb%=!V~;UtN_iXnWl`eK(Ke{odeS-r|S_A19yzsHWipBl$=otvv$s71YuSdg===^)|&nwi_v=ZB|0<_%B0H$Uft z#?k@$B-G9^L^$>9{yFS7vU`AXY2OJJJ>)|=%mWD7~I2Ya8noa7W2$e4Igf5!51Vp#>2TqPY zN6UA8=KqQ(bO94C<@qn>2E9XDZT_gbZYUbL$)bYo{$;e6=foq4pmf(~0S3h2O+r@t z&5qs6g3-*l3?^LzX?YTRYdTZnqv&W!2 z?!iS|Q1U7=0OFvk)6s|=`c#z3L_3-b)yy93`<_|&B31ZBOG;HE{gYcR+Kz}5$Gx~@ zMkPMP)t}ZxC8DA+Zzh__K84D%+kbj@Zn}I-uqZN^aI$2j3;DUHJ0Tvo{8*@#lEYAb z7(=hp2Pnz7L%!6m&k{m;$-JZHvc2I#@ok)j-pEL83VF zKISYXo$U%POO2cgX7bt07*2Lpe@niuP~kD|W3ZEvE4biTQ(s>vRJl{lH~D3AQu&Cc z&Km`0@^D%la!LASVY}_Ja8X=(UxFv6tMOE!auIgip)u~9M1S8Yoh>_TYJKv#_p?EL zuSV_#`?B_XmliwPk)UaNf)fj_Foy(^33me z%C1QTZ+BYl5vfT8Ialb~W1$7ASzP#)pM~hxBVCCXGMx)O_WYbzn|66}b{5FRFfT3p zs^;IM*Xc$|MEs^VJcnOp%D(`CERJ5hlk%c=L_s#lbLrx!Juh^k9B3C|@Sr=m&>Hb3 zKAw#P*^;Ai{wz(PkSonMIVY1HQ?=5>^aMX+YbW|=#xK3`Z(9Bl{+q(3d8w|=P7>vZ z7a;~Gx8zBk!;6lg3bjQkLUpzr8RHJdt#YetCfz|EY3$7E+Vj5F3=&UuxbjbapBGKH^u zyV?1Aj*hyB*E*hhR%73_Cn_P~MNW6nldj6~UpqIvZv2ako8ZY$enncC^;&R(9za_^ zayy=S-5uP&r%&dPD}UouD0t4DwI2-ZO4?5@gp#eRz2M5vfz2TXe||--167SS-aFyN!>}vY}&U)cd zQf)IFtq3nXlariL!0v$kx6-)ahgpYdP66kJZu>QEZ}9y=dB7DicxRpgCyZoIFH7#E z9WK^Nc_9zHNfI@^QIN%@J99r{F%`$2LmQW(KkE)A`r#O80%k?Tzwb)j-T@g}_Bci8B%>CnQt-ztov9 z+x4}vUmzDvE`W>JZ{@Q_+*VuE58@@Me(NVi~s-K7-(Rr zH2l|0&kp^Gd#I7HUNcTfNhc1m&&ABc7zI_eOPkJZI)A3KAyDhDs_{81N~@{^4Zg3A zkzm7BUf$qqY;;bkcUG1*I&15kRW+qcedjj%%KTMzwT9Dqbyb5uP+Gkp;A^-+CH9p& zE9x4YQ_7u7Zt(jWouz(f=|CO9{d?qck-fyW;0@4o}{B1ZhGfs$@EFj@Q`>F<}k?*Ll)Ex<1E zhL&mB#h<>Zs;%$xab#mK$GgzZ~Rc-;{N zn_H*3B)sROG6h>-y-Pvgi!Tav7I(zW0Y;X2E)aPCx>IX_xqrGR`+nfs)3-gf7dZ2* zPp(g%Yc%&>aKl#DT%%)O+ch(n%{6w+Us}`k=vQ{A&56$J5+}e|dZF zJEwlledj9$qh31L>?U9Jdn&l^t|xZiGyA-U9)9IZhrBr#J@m2rZ;l6N{P?alFC{+t z^(k}fHk45_<)2)e@T*^K{_drp9K9qOfBCF}8I!V)dYW#%cJ^-@SG{?8 zT3|52a9eS4adla-FtB>qWN}5Hw#*pjH9WfEJUE=6IAiAb+_A&w<5+jIZFo4RNQcee z2YkcBQ!9qM>to7Kjd7>X9Uea=#_f!8XU4co?8DO=^~2qXG47NYw=>3l_aBD0@8KAC zM~piqdw6;C=Fa`9GjrbjtFoLkr{zq`cFxG2eqQ$ZGiEq5eaq{84a|VG{!)0c{(TYu z3;cXR4_}OzFZhGW5dYcvp~ct#X(8W|3owS$W)uQ{bdq5tV($PZ@ws^-_7q?-W-9g) zppWxOGqKkLZjT)Gzzoc0?AgGXn5VGk0=Hv2vG)K^_87)C z>`vfam>t+VfTwv4;|1{t-i+zN-VB^M-!NXro(sI^a>F=)y#x5f6^3yPdneF&rD3F= zX;bjLt8rt`1zxs@^w;;-VUy?=K_C^@rXb0hj$ppLWvLjS4;`^jlfB34Wk^p6ZjJh-*Al% z;3cTAv|`T%zKU5RaqcvXvoPzhX9Lg2+%0i{k?+#?*bf4ytYdsh9N+@X2J9ukfB7CX zCjP+Hn5VF>1^(pw&>Qv+;5Y9wjC~Rx_$elW-MHH@9{M3)#ISD!{^rNvY6`Rj+;A`a z3j0Q2*L~0u_8#C}_d_SxJAjw}D|CXr5IFq-@PIuRxc5QYj=dLn<0FPqkG&cA@h@pR zcH>vj#?y$KFqPPQfG6#t zAF(@u=`S0`3b6xk!?a^x3v|5#{bMf#F2i(SZw5ZNms^anZv125c98?omC zMRB_q`&!_$uR*)mdw@TGoj$_e3EcJuI~(E;{1{`GE0f=3?ED_u#-0LPfJw(*0=y10 z5qmxGA&e9IM&KoXfX=ah@%yjCfGr`;NSI;Ewk3}?lIJ95k1iQipHOJ;jO$?^f6ORj z%#2al2_^RW_` zqk8PUaR)yq{pZCUKgJkuJJE>EMdiIE)|b2`e&uLm++W9JCzT}Dk1ib5Y43^aRq<~f zA^w-R>U8;NV{+vv7S9x8x?PiniH38E75%wTei?e!w|YqHpEH|HoUc7~20 z$^VI%{7+0uIPrr^Lcq&X|3>~?HO%1M$b^C)DNqZ#UF--TYf{!jO`OEj+7A_7VEa+#@0*xPok~j zFMLPf5)Gw4t#pF-h8VoZmSLqGJ33+PjHGx?y`2iD(nm8!=p%`HMNHgSybr~T;A4xX zg;@LBL&npVn6a$J$;lSw4RA`^Y01WEl}YfwwBy61J%R%%{|eo2Bhk0i<9=PX;N2s>PwF{`xI_J{{D$Jr@{8>^%U{|y;~(_#NO7c| zvE>L&4fT^aqY{ikj)q(O#EejXy#H7IKAX_HNE)=3E1jjy8QNqP+KkN@5B{=tl(n#t zYpAuLtnXxvDr-<#U&~ri*0Hj-l{KoY^JLvBYdl$B${JbL!?G5XwWq9~W$h?yNm)0_ znp@V_vJRJZxvbM=Z7ge9SsThaR@Q~GK9#lZ1Jvnp%ofb^n7x>{F@2cB7N_0*AL+`B+F1eTIRG4mhlu4tiKv816GHp4B83#Y6-&^gsVAFA>@`f7P`%Yc?x`|!t_6;Vaig|ovC52hD91y zYuK#eIt@2!xJ|=e4UcI!vC_?vWDpzIyF37!dQ*RWZ` zb`9^;utUQ~H2kH8&uF+q!XE(B#ZuK)IdF>73TwQf)?evstU`8PdYqq`q^g#E;N!zA z!Oy7r{4hD`Yg{)%IMNkjRIPFS@nKcvl`0f1M2+u(IwD?z+nVG3kql8jqpaHF!w?b8 zu)5>JM9MSjNAgD~ZXm;N9Uq1SU3Pt4ZS@VpThX#qVs>#;Rc(1)6ViL#(xpm#EnZRw zPU8pNWpyaB)&_j#lFmNp?~`~5gYKmbrKnx{>ct!Re;_|Cch<2Q5IKxJ>I`w1oE`u{!4xIPx??lG;V$1dNUfPibv=wa;Z3SBsxyt`(IH9c!5&-rlz4BWd(PY|^Qp@m)R^;@8^+h-aV5!YlHpDYM-y(c+y_vYpAKJWw~l~lF?-^s%`{XSC>`? ze8x`u=VoFYu9>IU#)%ttGdwQ^mpZ#kUiN?cWSOH6f1 zG>iXsBf$BHyO?6pg7dHra}0vM_vc#X8Rm z;)?^d$}h=Yx}**!Gu~e6uVY{0WV&p1rX|E`&u4{z4r`yd%_gCx{sMeMlIra+0 zv%V^j@LYR^8Y^?`6>2GXnSCiEp>~;J)Y!?YwAu&T!R5Et=)70hYkW0j_4Lguv8fS# zhn-AS(RbPLFcTU-us2pMtz~I#JZOj8lvP6OkBW_U3f(^@_G)$njGv3GwydV!c+cKc z)~Ng#n6f7PZ!iOU8|P-LeT`Jg_^&YJ3vD?>RF~cJ4TQCe@Scq z|7!-{<5Q&79VH$09b$oZ@xSE0%KMt{>v^#E!GjMP>r>V{*JrQKU0=AqWPSbm=JjjW zcdXyIzH@!g`rh>i*BcL|Jmh>R`yrzqT@KQwcVu_W>cG-$x}6=FmJgm^{Qh6U!2baz CE~PU7 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/libwebp-7.dll b/venv/Lib/site-packages/pygame/libwebp-7.dll new file mode 100644 index 0000000000000000000000000000000000000000..fad57b229ea2d91c7767b2a6f10209baebf4f562 GIT binary patch literal 447488 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 luq)H}h+&GiULY0KC;Q|FHgPkuQRO$uuLSE? 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

    mznqHqy;VXk)PnL*1@`Er%SAIYx{Yk}# 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

    3+^8Ld5SAuVF2$L_A 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

    d`cEz@~ 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�kb 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

    c<$_uWu7 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õu2$Z>j ztaB%^>+Wsd$OMh3U%^-k01T#X%N3(Ah|joSq^fNC6-MwG=7PYCP!`U6P<_*`S7o^` zLkF76_(;);t%lUB`x7?-o=Nu937jcfzA7k`WX4XNaKAh~5i-V2hju4F{7B22Q-g&S z@aPfU3h)E3gchJ46)&3#%ejcVs;Oz;U)R7{{b(FCj1mtXo4bzXS9C9RFT=|&5Ka%! z0&^oj^WR|D;>^ADg$p7QXqBYP7-3F!Ka`3q(@2ZOdbn7FQDXN*J3h!`(J$yYE~_7` zgg4XIL9z)JWG>@5iw$cK`&QGe4%s#!q|6js#Rt3PHt&*w*~ zm~QM}>1451m|+EvO+Uj&u)a?|ABlcm^JWdW6%#t{GxnOJ5{0&6;SOwRL@fU4P#Y{F zr4h9mYuaHH!{ZVu5+QesyIzmKCg=TUk$ z%b!Iib$&zzClE9z(F+k8M+NThDR?>W?5KFnKDy+VPf7vz&hC!Aw)HQaXeNr;!%L)l z-GZ`n6Q@(WvYvnh4E}NZ9+}*cna>t{ct2OGDxOG%Pqp1=tM{xLo4Ryx*D>A+sqSfw zq%IFW)!${5Wfmo@>cqck+t_GE=d~?do(2dg4DU0v%iNIJXrKe=?INd%OTPDSbwcz2 z#84NKT<4euOtdf-iMN#UANGLk!ylq#rv6jeojjyZa~Dr3+T5Le-fO}G zO?EciH~G}6mz9V{`!T&z>g~Zpf`X`fBtHJRU=8 z0344{D%0=T41$b4JY2iohxg!vXu>7ZuZ<-$`F6!IP}H3K7)XG1nm9jN{nYA#y6Pue zPDk|dLk2pVE7LcG|D}(d*)oiO)Jg{<_fkV#>f$Z@1ITuz8nSctbz_-iw)?IA&)-J{Q~eBjmDs}vI3BY;)Mu#SsT&N zjyjxZ%(X*1qV7{mr_QPc8nfgKuc%hTSiQA%S5OkEYaF>=$CX{FV?~kf$nWSn49n$3 zahSKbERwPwJ}Qu{Pur-GB-Jl=s6>fCbTc$79KKKKA>p`+KndE~3y8 zacKkhy`tf75GbHo@p|0UXYdtS!}FHfQ==Ch|7-bnw7w{z&vHqtSI%5iwyb3;IYz0P zP-l>h|Lwn0XZ6n3rv=p-s7nn?WoNd&hl;}0yH~K6HmlzHw zrn%PRMVA0TT$!*$5`~9%=}@z-2m;LjZnK7`MrL7=xNk?@>)GhcpPRv5Jq``y^q1LK zO?~);KNrjq7|WA_=N>9bz^}>T68cr;k47G9&~Lhoy@{Q0p)g2#23!cST)TMY)+b9h z-OYDyQ_1-^N1$W$J`yM|tSVdSG(8XRNZOfgloYMrYr9uXvo>|YDVc7&`QnWoFrQb= zu+hX|SeD!FO;xep+F7J$ROdN_H;Okz=G9-bQ*#C(XDOu|jeMfYC}8zBhmZdFiFg~1 zD7MNDzegpLD6N!V2}z4tq%XzXc~}97HEpd6$-Ky#hNi9X&=#Y~o$oK4$w@lPBujtg zrS}ILns$N}-K)xm%a0vCSV!d)S47RLZc`l?W5Z0dTU%l_p{{+Zu#_DrcKCoUA9QC$ zb9LP+taie1Vb0-0YFE06u^qwN5P$X3IoKst2zy_ma|l%RsGD7Yi30vGv{@z&Y218ci?#bMJPMpv1;wtHJn<@b?b zpLK!E=~r*vSlNkid>Gwq6n`3)4fk4rB{&r7u6<>xH>GJjNKhh%8 zh1M5_;x?kWTX-)!JpOwsck$S)LMQVhV&Wx4@chIT!Sl@Pg6G-)#M2sYJIeeU^FBYK z^f#LKD@&ATg?ayCIqzrQV&2zilQ)_aZU}5~ZkILw`YNK&UKSLwP(`c?idd#1+JYih zs)%;p9rq5cZf~M2F5yo1J|Y2)&^ss>vc~7~ zlq1OlA#BqO~`3AhnXGX^S~A4L(cH zFGMC-xp#2lf0M?fzPQ-*b#US&dhc-I)}$3ww-P`2Ea_?S#0yEEd=Jt!n7-FtbHe%^ z_DAA)XP-vWxOZlp2Y$qy)UD-4z2&*Vr%?!i{n0#OqmeTn_3OYyL0IA~ID_caxbP4X zmHsR?5*7&7)-ydu{)2}9#9L}PFV#nwH9+{NUoxELUwz5(f((q`@EXpo#~ge#3AhI) zlU_R#^9Cm_8^HWEN-K#^shPAbG12T_+4kWPU@&=MsQCbQl#M=NuJg{|nO`OA5dD-3 zXEwEIK-_bj)J5ffGl#kiJ3jnW2q4Y}VrY*^f9+%h9OxI>21lxiK{{VX(Y#9oQ@wWv z-4csDnwOj30xv_1{$)&gG@b}XEwZ6bU&E&vT7bp)(OmjjL4v`F*JJ9?G*I5ll|^?f zoL;nVcm&V`Kas1Pgqhzh-I#@669G_8{ny-vSs< z=tq$75r^smQ*ggyP-XPaEuaf1oBmQ#=+xKB2PYoirFqH?Km2Itd;0Q7F5lP ztX`_m!HF{jEVsT!*{(2)gEQCQ#Q!31FXkXgW6HXQ@1TJ>K(KQBSH(t9Rfqaj%0d5B z^)z6-!)53NGDGwG<7%zaK4H?P{eLHO<_QzebiLY1R_7%ybCTbPYQm12V~Pb~znPvVirX*w2bO0&0C3=kck(9@8xFzS-!_Z=_1Jui%lUrUg3V z7*uWIQdrAmQ{RqkeH%=DZ^zuOSm@~AsPFR4xE{eM^abk{oUq<>n%07$*a(KHRlE6;I%W!oOPfbf{MDQ6HOD(zprt51h3t{-z zRd*%k*13HR*LObl9~XQQ$=641?5dfwD70N?ZQHDHUUNyN8T`a)g_|uz#hbcJc;dQx zuf1L8M~Z3Qha@2!uO4W=*J)~KlzrvYjP-W)@n%mdi(f+7txQQ9xRk=9vU8)|HZw0V zF6xbkP07)r-ktF6m~jcw6>h*O$iB=uCiHewLv2qu95RRN)>BmxZKf`(qY6BhS-&}? z6|-iW;5E$nLB5qq4$}wO{XSTK1?UHW6_LR?)w@<)?1XmwM$JNc;8?Z00+GR*Vf+)I_ceR# zC0-dqpd+Spjy}+=a(AYj2wE22rD1nY5$cTYvjcx!lm;-oGoC5)r6>_~*(F zhmRPXIk~|JQjZuN=D(pYJ?t0X-x+gvxC7{HqivhG#%7vELv}b?fdtUV0h32sTF+ti zfFbAhAWcM3hOM;lH;A_FfiH&TE-%k6h#{EQPgV&dhGs$=7>hOjd(5ZYchn7K?ho)! zwtfj3cO7vDsJdZ9)x$MU32JVjwq4oE5N6v&G}E<<;71Qt=DQtb|I)hN;m|ZL3*a< zr%b_ani3DK{8Z==P(op+>+XkhkY(<}D(+r(RrS0CK9@r(PcPW$2mK zyxUuEw1X7%Da~HoP6V@X2tHZ(aytbc7bGW~EFq1$(80wD`_{!1dbXY)1&^rpkL?e%;R{MVa1;?;95xUR&VTYf@UP5b_`zt3av|Oa*Th z)Y6#R63;GoYq?Y~Og${!cqt?kdJm`LXBTo{J{G8AC2_-}D7VIkh@8j$`B*V8UnsT4 zOBW4&tg9exq--+}jg{I`%Dj4LJ`DATa$rl8##1(z%ldCQ!|@7SF8TYV$*)98vK21a8i4YA^o8} zpH_PuwdYayVCZcON4YB^u`wUS-A|bY1x_J1{UueB_MZJt zD2=*ZX{TvUnEiAV&B>v&pg-UXh$Z9V?dR<0(#zzw zy1VOfElOL1Q z7{s0@dkVVcZy^<~*u!SJgk7SPs|Z|23!OUq+bVzkkNLmH4z-@GPgvLaMolNpNAk!i ztD)|v^xy1pz7m^k3`pv5o44rJ@z1H&(?|Q zF4ZRdLuCa?A2^t*S{C<&kRgw1^{Gi=ROKF~qRbDn^Ev6`Kh}gRbj?Ox7P*7M4Ca6i z{VtV}iDFIj-NWgtXxwmnh*likYMvKe7gGh47j_S;Y3XxF%V`o3!5F1DRd`yaT(&NC z?c?cUVuSSg>2UB)`N!A`2+fF*KloyJ%g^9$?Z+HKHud=fENxnFrE>;zwO3Ef4s+Sl;E7r*ZVY2$w;%m@KvMqTn~ zZ$c7nl8$o;wRIt{nY|^bgj*^OMh{re5(w1fC1)jJTfc}FIDCB$zO8Qu_irdW*3@Gp zVNry7(@+AEAf^T#+OX{&cR~kbilS7_Cb*QtSh-BGV(ZvQs)p7l3~KC`^mYNR;CxFv zlncHo$H-4IZB-)0MXOPjs(sQ$35ce|T_@r~@^*)+u^HUDBM>*F#x=10*qgPvY0v#w z8NFVG{JeP~Hvhs%5EjE;}jEvCl z3<#<#6i;1UJaeX%+(18V&Oq*7r@F8C^@=AP4C7FPu#EQDkUV0dVew9}Kj~9|B)Oet zHgR#{U3aDoDNXO4qj}2o{7S_5PiDQk`(^8xJ}}RF>rJ$P3x+=!buW)J;7|pT^o*#x zw8*#Ez|(S#Fbt1qg{hrJ7!RD_^X%kB3cQi#>Q5Jl?+RYc``y|1sAoR!9TD}wi1*DS z-aALU_hsL;aeX#dp9odQL$5Q%&8<+^kpCC~5mj&e(Wo_S3kX8Gn$sg&$6U8Z7q!@c5Z6x~qfxwDb!@I}_^7Lk#NkoJ9Wcu%r3 zQs@2-rDhhwYZk7x%KpK|jYm2h9rFsa;8lp}{Yz`z33Fqq8r00TCeV`Z%xucyN6yE> zDLQ7^i|lLcYw_cNMEA*|{nCAJi)keHjnkVs8OWSh`EY-u9*j58PU=SH=5@z2=hM;V zG09_?HkW}!z7l+mvNrho!oeqMTj8XjZWv;0FsshsP6E%w_GooDDYxHvXzE4=+P(S> zuK?hPUAH5!wIrvBsV{w)i4EZkRS>CdTQzzxuer9?o0fFeXbRREW?jOS{uH~Dy8C<(psR2K7pw_{SSny?0|F zfJb4j3t!pA{bE_U*os++a1UOzoA<_=x>cU=J;Jkh_L6e<<6?{hpLW3wXHfAJyIG0g z5-!8;#F>iJ2TwJ-HD0)k%!kw-6@mh7QgB~tm78&R*IIPD zX+41fF5&VvBck8J140~J|6cS4$+z*-6YC*Y{$Aa<dw;Kk$We=VM5*wg*n5@WwrO1uJJw%&zQHLZW$1o)Ya&;{Mif6SeqVB?g< zPztghY7eW^_PS`Uzpf6$D{F}C%Bjhu&WvI-io?L_+^siTdN1l>u5x*Oe379TG>CuH z^ht5Qj7u7V(L1lDpXCFf?aS33GzB}w)*}~wKD}bZ7$tUUOfq)_h(zbF={nqa<6OL0 z`8TkJ4Ta|nb~ca4z{}3Z74RGe+n{Z~Y8WK`;2DH@;}$BzOl9!KE#Tec^UqR1Y5~R; zAd)!fV`_w_|GvqC4F<~bPcfOyt>wZ~RmxG8f+^c^3&$wnb|p9bvgubtvAOo`FtFH~5r^TN%>ED>KXWr1 zOfppZytvy3C;EybSvg|miSO|d#bxCA@=*~8abX)fl|862 z@ZTP%@_;i1qh&{$PjNP%pR3+2Y^65ma6d5a&|A`6Ka$47Wq`;9SZ^*DHzzgjjjNEe zO}s~SdY{-uFP+q7d)Ue~5hi|*U_=~(H40mG`(X1p-er3vdV>-s#5W@jZ}cY=qh42; zUK2~tt|NEmqu9uU;Zba6q@;%;)opbIchyew& zVnRg1m2oCPyF2KlquezH!cX!|3`?+`D z`|MWn<$vnb$>-GRIFGi#!U#rgahZ*uCJeZyVkw$!*2!h;ruk^ z0$gGQ01eW>vtzI)09J2ai!n4t)3GjSOyafrntDP8V(-A?nCzE%QyAo2f%L)`El?EV zu*mf}f@MLlGO7zt3_ejXjjby<+ds`OoV?jMv765+p&$?$B{BaC-&HSxh0~}fLiSXI zCSK}c-slWQV~fRM9J>Qn;jkC9e{{yvyYA5+Yo6_A!jv3EjKS2c=?sP&XJN)CpPme~OL3g-}8>j-fc<2*epL)g|AwE=c|h45+!af&S=SQf(Oe_Y6IACzn>w8F7bjX&zPY_WQ#U;--n zSQVx=$!U3*L|89zOc7s;h!e$+VldttJ|iwWJn*YJz7ou0debyIXLsGV;k1$vJVfcE z$;7(Z89(sypLqoXL{2wQdNmDDtdXBWX2G4zQAmZ$n^2zB;iu|mI|DaE`4$=(yBcm>Zm-j?CMYAc@^@Sa>yPT03IC!TJgZg3>C zX#5wSSXKNNPMy$62r^bLtEOQl;;|;uhY86I)ZuuJ>Skxo5sVo__8=P&FfLY;xzsfW zBU6-{HW|Xk)R~i!C)#b!rvT9p^!f!=4|Y!Ne+=7pu+wpY_N&l5QKH?6=Q$iJ9^YVA zjN@45)$qg@C=(%_Iv;cOUy?!SlS&>I9)x+7$?Etg@Vio45Q2c!^3-dCGF*$`u7_6zj&AA z9K(2%Q61SL1gyeIS{m-ayVfamtn_52MJN*6zNgXiAcXUnut+hnZFXY)Z`fDDC+=h> zD-6Ku(07NCs~O4}2$93sb2I5$XXTvNCybv7Ke9QmAzCb~L>J!?jJrD=KI1=!h1K_o zlYI9t0F_a};^UW7 zd}3oWqjO45zZ{eKOHONOX7iuF_LE$6o%@;{{EWo^ly~B8M|e z<}Wyz7*Aopw{`wV#A?x<<$6a8ccjOsIN)%y>pJ(B)%BC_&V(7tcxO&^$2LKzliLU- z4gUB~lRJzr1wCwjXY2(9in+=;#EyXs6oEJRJ)hQ5lZg%!Wr$$O`Cf=gVeMcxXRKfv ztHLd;ghv;uF!Qdd^D9iwCVs~6YN0?nH#)77=m%H6qFjb24wpEL*DwHpD4h{BW+)#z z^}P-_MHqguKH_#J9e=@*Gg%Y^>#o{|T?#{qXW>&vSX_?_y!SXAQ;xv}QUYDC0n@aB zx8jN-1>;bm3G*r0Zn&9=4l7{?g9uH=8?0T)#N-#@G6h2rnJI9slhd`4aLt*Zcubvs z;_WBa1D#nl@h+sEI0Xd-FH!hz3lz_0L zpzz@x=`P;%atZ}{*)XniAw2#xhE6`c-6W(jUd0_Lc&a4B@J6O=z6~|m0MrQxHHZ1X zA-JxD_oz_#d`Z1K!l2&W2Of9QSOUKf^>Y2fVfqnLCgTlmlJ^L?kEI)Ur^qwuilkI9TmpvSD&Az3 zpSR>hGDG$SPYnY?Sc-5 z@M=$+XAw#_EZ4@?_DFebu#h2al7}V>jF!SC?Xkt;M`CuBD1M}Zh&3d9948Uh(vzu~ zG6ypMs39|5Xx<>#g$CuZ*=Y|87RcriSZ$<%Z)odTVzBP*ne!@MN`#kls+@O+J;hX; zaA>w`U(ot&XF<=WSNIyui{Wbj*b?1@&YTiP;G9K@hS>xi=s6VX9zJeAj{DNbMv_{5Wye12-pN1m^T`%f#eHm`- z6&_@l>lw=soXmQHl_j_n1gD7D>cZt@=Os+W`rUCy4#^oIv^KajENsdU;ngG!YkTf= zDp3O#up|#1DJRu_NEc+x@O@-qrX*EZw7(ncJMHHb zQRo&-En6b>Tj~HTH;z9pX$KF4emJ4!f}wuc)+HYG6_UV}!a;%(yILhn&!~Sn5+X^7 z6JxXJw#jh{Sc0GE(Gk3gKW=f=BjaDJMf8RI!`|x$O4xD1tNmRgF;U^_vB!jeLO)w} z_>oMXC|>P%B=J^as>?HcKf;xp7xxexK}c`J`Z}`*^{l5ecd%^izsj7b#_F*rg?|_c zdgYUdrL|eYt4m(_xXdS>+UIogVyyqZoE$IW+~zwc$F=dFN$V9%`eFzI6C02>n23i^ zAfBvcrOtjHCoBa9^Duy!yZz3Ww_r8FTWnZ9tz9m4q)NgsAVrw){6Jd#F?-pxSIfX(f#)6*>yM=f5zdo@abxX5ih8)ea0(6l`BbtM1-71zjFaO1SFH;-oE(Gc>eHHO0S z5~QrUZPlwwQ6P#7WhB!J&(*|9LdyP*A|RyE65JFt`$7{&P6{>OV6|UPjpFC3QP5*8 zR5#9dh@7`3XaAH?0aZ-ADpWQ{oiz@&7V?2Rml7|BBwi|5IpFIsN1XLdi1c)9slWMq zfZ8Gd?}6~!qU?iE=GF_Vg}hRiznrgL_!(NxdLgcn5Gj8c$Ii0O`oI@zq;#ti5g9#@ z!Wd`}T*M^`!RIA81tkBENlTRWXKmmjR%hMEq+||{W^+7(K6vniF}Yf}CHRsF+ZYE+ z6eg8EE9us}AZWsn$$h=cWoU}XeZ2|S&rrL%ex%~Y2@VJaCGqB`ONmFZp)E314v&OK z~dMFkM#ukS+vEC?iuNT90Bh0Op_Em`j~SQm zB|NQk>f=TC(s$MMd1C*;#s;V274RSYsNQ~-dO9^LHRJA))bDrDrI(U3nK3Q!*gBzu zHkP?_Gxb%$8#(0{iGm|5c-GMmew}7r2~K^95G3FBeS|tEH97VEZ7;m~IPRs}AJvW3 z-APSFCt!Z};V>3A=GVz_*ewxyyiwpG#v44Ag$ri!!!Jz5!VG+DiDHq z&vX9d%Y&R36MsX%kZPzY@CJaQo}r#*cWRZ!@E6K1=Pb}ZsGWSE!cYKIen<)=0_rO0 zX`KJHodmyOTzE5v-|mivanj51&+YF~$>lhM)7v;@hS2BWdV|Zf!jWDjP~-*w(?`l; zA7qNu2_q43+z{e~6)yQ+ju2-A5Jz5m-eI4^w2-U!(o>U{#8kiez?H0N|6H<;JcU>l z%3L9d9lrIJlIXs7_*Qevl5S~oOOacCT;ekK#4WG8{P<(8}6a=u%Rb<1eC?BbS9 z-Lj5bmUl~Uw^X_1kHs#3U%BOVw>;^Vo7{4VTh4ULv2GddmR;Pksaw`@%kpmN?UpLH z{PDZnU$?yLmKWUekXvqY%O!3((=ErkWwcv%am%J|S;sBQyQQ~Vs@(F&BDeoenLGa^ z{zW^q8Y3H^*^U-cS(KxRCG03N7~MekhjR!J-!*j>ZQ;Q|;l+RKLEyMF8>OusI(3zP zu>33&cCgdQ6bRwx2VW%`U7{OaezB4p3%3&R@Ju5eDcDqa7>_zWaUo3iWG0~H>`2G` zinz`!14SYXW)_2DnV_&jaX?ULptvq5#8A|O0`q<)Z+W#Q#77ub5#HiPpdFz33A23h zSZDa+hf`Rn&j}+h;V>xtY$M>p*P$`!f)Lz-BhWxAD8mn7#>aAmK>H!km6GvZj$q^G zRftW&=gHwKa;N8NXF5Jh8}%i3@w-s|-AA`yf9np*xkrwEuEzhBVp+j(5b5&@gv+PU z{fdRIxkA?wg|54~ulu;=V7DCZmUg$yiSFz|*UJiBZz*&g(b*OL^sX++xuuU=cI)KQ zAMC!)@h3;l{s;MhpQ8dt&R}qk=K0P(SEBxOIC8H4|0ZdMW*CZM@K1P~{>u?IC~iP6 zpXfocKD{D)4(b)@(|y3;KHYtKb&u^{o~ReoePE=|kjU7$!9G#l`wocgg+-b%k==Xw z^o{Nt+qe6Gz9YNG_8k=MzF8iwM-TED7&&lI%m|-eaWQ?Pd;3H=-6&`t1|?#V5H17? z!J;I830Iy5LrCx~A3HITm_nfQoMcD|sUYp-L~;r_9Z|9e=b8Phib2CtM2O*r6ubP( z;gXV25o&bRXbBym$J#X`VIs_gg|HGf!ULZR@*=#kpx=imicXW__~?)?QIaTy?=$%m zrHL~5+)z29JW+wDNK_&!69GgOqAF31s7}-%0*RVLZK4idOheJcu1ACu4e`P9rbGnM zf@npwA=(iguw!%=q8rhJ=tV>keTaU<03w;$J!@MoHS+X^jUM}{km{5K~l5`fp8ya)fGH)>czh) zx8UnN?&IDYG%H=l=kI7KxsUg`y3c>0+IJm!w;hg;xw@~v=PG|Va+QwkT;4we)Vv$_zr8`|otB?}dGqDF+xI-z?&XEy)%QGg zUMxQ6nay(+vBMz;%_E7ccUZU%%%iL|!0&3q<7=+!L!J@|nd7nJYp!SC^6BQ? zcjWru_?%Pd1&r?eU7KCZw!VCI{gh=zFVqh< zNMd3xDWngY`^mfQYUQOVF===E#2%6T{+JiOzt@DtgM1oAghs9D*|3h^bGv_4>9#jB zY?A&B%h={NSY64yIHY9XWdT)+46*lVrtnC0wAG5+^7YHc1gQ6!EBLFTckMQ6kA{}B zMx8il)|uM1`+0up^5u@7FVlT@Tw+EG~n$p&0ER&H`qgX(nm?*E#O-gyTPOAAw zhaOxpQ|twEu`;V0^snY)3m}`9DZ*R(nYg49_hX9bjZqU1Xc~{Mqifo=bztR+0Y@T> zFTF9SefdGP=M~wI_QEDQ?vUKCc2 z$Htx!k}?a)09*Z;O`B>Q_F^ZJ{QcOdtGgNUPC#Yt+RMpiYm2ExN+fx#E?M?*SlgQG zS`4w(+8$i1!;V_3J2zP9=Vy$ab-7rn%@x#|-No)zD!045w&-qA54F$k!15-Govfzy z4e@C(#M5rJpZBAsLjsa@qI+$9r9)~p;fxjfR4;o=TCM7Y2V94G=l%T6w!mtEgZHrh zC0AebE@n$u5G(VUR7zjqiAv z^{-U2sB%PL0~^`eUlumCNpyz_F++@$EXuLkEQ<8f$XeSYkJ|!uvZ$zQ#SCTQ4C)dq z?L29V3aam0tZI>W$#rYjFWF$2=UrdEoV^%XLH;4Bj#gi9ZtLoG>iL%OUD#`7>t$rH zw9^z%&gXRNMrx^)bL<(WX(RGvIfpfytRc}(OmtL_wbxV|T1*bKjqqDlxk%!|1Z(kI z0lmw{$B!x^TGGakn>;VQ+-|$crj5^9s3I?y(-=E)cg5t18pcwKYELysU2CaOR!es9 z6+BzpTDP{_edZ?VUekh`N&m9qCtCed#wnE!20saP`$VT>Q zL+8fYTi5VcZ+X$$S6ZjOw|3Z2hgLT=vSjV4)$5h9&7508@15l6?qQf(E~ri#+57~5N%T#}iziMc z8Tr-m#${mrv^U>gxZL%PJ^oJUHG&cH+z-bGmw}7RzBpbvZP}xGKXqJ9a=EbJn}j_3ECx)I~AI*z8h43Mt7xcHc-%+<5oPZoc9@5ufY%jPVq6JPG+oef)VFaCCi z64B#FktSu^6mQlpRNc7Qa(DKySyB@?TzCpzRw8*Whb2eem>c$BqzT9ns(Xo z2Xwnkx&QUnA*ZgX*QO8qmOFhTcYStbWa75nK6=(0$HV7NW$`9EzaF{jIFAc*G1B*` z)7pp`nU4Dpoyu}O4}3kA>PQz1kY63wTwyp%;y23afIX4i>PUB~ze}^fUcBT;#*NL& z^mj-0em)6P4YWyjmT!Nt#_`-vcK!7I&)rU&uRFZ|a@Cbti<%tEK5)#bOIluky_Mz+ z&gpfo2lrL5jL*MLjo@BBYwxt6)_@a<(;n;m0I?#fuV z=g}s|etS^)scFA%%UbWaX(tCi`Eu&;r=@Uw^}t8puHJBLf^(&stjO4~IZ+9R4 zaZfPN{K>a-XPtR5D(dp51IHcDV8GDzw|A>HI?h5#-pzL0yat8czIOA+Z<+XzHk1`& zZ#b@^$qOYp;>GtruRE19T3!2g`i%2|EFG~dYsFqyfyqnM_j$@!c}jd`m-<07qVMdt zuV2KUCE1?})+McC;-Y(YkB#i*(+BO!$QYpwDI5)=dk%_;iR>Bc(?4>As|`80yU>)3 zjf@$R(=v57Tl)?fJfQoC?mY%XmM404j~4V`a!91l;J!U$<6xjrjt(K3A}HO3@Vgqp z<%wpEg!b{E9{mt6S2T&}xB&xv@M*;cgAkk{Ly!)!gM{n)k+I><1R3JzFBomwx^d%N zbMACND_qdxoeg(Ce`nG~#6%A4?u>S1bgy!QqRQolr=m|J(ljm_0gvpJlgz|l%p+=% z1x+@Kiya(?nDiJFgM7-h>5c%&NLV!Sqza`>ELUOnRKa6+va5e)n_F&h%Vlo)IlV#neclO_;b7EPZ_Y@COtzHm&HPnXY>&y_Efua}>Z%M{ZU)0NZJ)Ag>q z1Yr@It$w0X{w7<=(lyxXfkuyNHGRv3GxZx7Jge5K*RVv{c6A$7sZFh!ZY(`?O2unf&)uITJrG?KMINhtY)2 zjr@HZxm_E7zh|RB$3};aojP~v+O2z!p6K1^-KTHA{sRU^<8?b`NNn8DVZ%p^95s5( z*m3sp6XGW(Oqx6;aq6_`GiJ`3J!kIE^M0BC>w@1FF8Y1(lBLU*uUNV2kJW3|u3Mk9 zVdJLFTefc7zGLUE-Fx=#+kfETp~J~XjvhOH;^e86(`U|}JAdKgrOQ{Y{(0^Cjhm^r z(r(|mdoTU|gNKhEKY5z*?0M#km#P@7lRz`?jrHHgDRvA!+@(wQE-Yv1;Xt z<;#{XS^WE=g}*KMb^b5&ex5sL_NLTasgTR07(Qkh8XtW4H-G;pxNct^EkG||2g|@E@Bk!q{pxrRnGC6c%qcSkn@*s2(BJ7M%zWkqqhfVT5Yv&F#B5{kFkhLHY#`fd~uxi$qt->~CJF`P@XA^sny~;jdzp-*rQBg%vh$uo7C5jWx5-kz!5FHb} z7X1(z#Kpxy;>O}0;-AEaMJGfTM1P9zi5`nyiQbDOVwKn|_7eMv%ZsbSR2y+8aiqAv zc&K=^I6*v3yj1*$c$0XC_^|kd_=5OPai;i<_zNZh$R%2dP2wY|BB?0}lQfXDl5~*t zl=PKMkW7)xk^CxIAz3TgD%mYLE4eJWB}tcLO5RAmVCukd$ymu`$qdN?$r8yL$wtW$ z$tlSt$#uzn$x}&|z>D zuk^U|jP$BBRr*r;PWnws$&@m^%u`lOR!bHlYbcA5b(D3N^^*;jO_WWQ{Ve-Uwo0~M zwq3SY_Coqr`c+EG6f&L6LsnE)6*hR-Xbl^^U?X0ZD4Q!=AX_P0C)+05BReO%B1@Cq zm%Wg^m3@_wa*NzsUP@k0UPE3-USHls-d)~XK3G0fK3+aqK3hItzFEFgen@^?eo=l+ zepmiTo-O|&7b}zsi^5w`N>NVnhdfEXL%vUbLVi~Mr~H=umHfT@yPQ_26b6NtqPU{A zB2>{x(Ol6<(L>Q+@slD!F-%FPAje`ZYmxso+;icvK0!YPU)d6 zsw}IltgNLBQSMb7R-`B{C{h*o6d8(F3Q8$aYL#YXF{PiflCruoLfJ;yRT-%qtQ@Kw zr%X`(rd+CAtK6jAt30esQC?6!R%R;SE59gNm0V>|*;M6KRa8N$FjZ4kD^+JzPt|DE z1l2Uv9M$it6{;lFR@DjBS=FDaTdK#ZOx1hU7gae`fU34CRMkY)Qq@V-Lp2mO5@2IK zZ2SQm$5m%kS5>L1N2=$lcdE}SrCP7{R2Ng1QwOMPt3%c8)m_zn)Y0k@>T&8R>Y3^l z>b2^v>fP$2>J;^5^$m5F`lH&RW;Gg(NmE4Qs|nNuYr-{6HSINBHGMSEnkVWP>JRF# zYLP~vF={+C6*N^fbu_%DnWnX-i>8-mj3!<)T{Bm+ShG^IL9!NFs^zNnsx7Mhsv}65ORA@;m#UAdZz{1`sWu^HDyplggVlA_5$ZNbnMn0m z^+fdy_0Q@h>Q(BE>h0=N>htRB>f7q4>X%5FZ|Yd}NOinAQ9Vz+P`y&UPJK{)Onpv$ zMSVy85GnIkE!Su@HjR&_jHZ&NriRnB(sa=D)b!QFYDOYu5;e;-t2LW7J2lBjnTtr7 zXPVcVY|RgiRI5hHcx$U`gS7RujkRsHowZTg0b09ul6IE%7wt0bYNX6gZHDHR=9A{T zMxs?|%~~&QCD`C#qd9DJgN&(9c_m8mG+bNyVjty z>5A+8byajVbz!;&y3V?ux&gWv-56cGZn|!+E=jjlw@;U>JFB~_yQNFlz1Mxw(R!)g zpttFZ>;3i1b!&86bh~s%bfR4I)_fC*XXVKBKjKoI{NzhCi-^zF8bd3 zf%@_K$@&1#wErz z#*M}!##6>i#_PuW#;3+C<42>vv4XLNv5v8Uv6-=*v5PSVHpauoT-aC+8_C9##*4;l z#&qKo<7?vwqtv7}Sxnw0e^Uih4O1OcYg0#4FH=8LoN1J4qG_sWiD{K-qiMV8kmdxh3T#7tBEu#%sR7&xv06Sxt5tXH#E04cQp4h_cK2*WtiTWKA9-9#H=-&&1KA$ z%r(uNxskcKxr4czd4zeKd5U?a`8V@Y^IG#J^HFn(`Lg+j`GGmZ{Kovrtg;v^UY6pP z@|G%=AWN8~t);Ui$}+$*%reF@$uiyYhb76f!?MqE!gAK~r{$LAmF2zVyM?x@tOl!> zwYc>^&;Ng(|NlJy|Gv-vZo@&tNy9nA4Z|J76T=Hk+7%hqMx)WkSQ0g3Rbx|QD`RJ4 zPh+$();Pu(Z~WD`*tpub!MNLa5H;gD<3r;!<6C34kv2(9I@FA1O_fcxOd+PmrWU9f zyPHOu?50H1EYm{MGSfQKX45g#Y10+cP18fuGt`XPropD6rg5eO(`?gx(^AtProE=a zrWDf!Q>y76YQ|S4u~}(0nLW*=%;n70%(cxC<~HW8=1B8k^H9``3FhC;E6hpet>y!$ z8PB3-d~D7%zc+s|vlcmOMw=zT5@-pvgj-r#+FN>9`dCI=CRnCf=2(8WtU%4U)$+*v z-2Be`+00mE7QMx4DF++1VWSCbbb^ghmhqOUmf4m?mgSc9mMxa!mNS;CmQ>3l%X7;+ z%V&$mYO)rw`dTYmt677sb*=5KU9Ekr(bf^xan>o;nbtMdjn-Y(1J+a4^VaLu+tw`W zN2|li+B7zkt%%Lnw%EGTy1}~5deC~zdd_;q`o#Le`oa3uDzYhTMw^GNimj$C%+|ox z%GSZw)7IBE#ujgzZkuacY+GsDVB2OpZM$f@X}fECW_xYRw*9c_JS-kXJxY00_Nd_z z;!)qDn@5z#Adff?yT>GtSsuT5tn=9HvB%?($7zp?9ydMidSqLESj1MP)nfIwma>+! zhFI%cBdl$#-L1W?gRMiYv#h^ZmsnR>H(PgF4_S{}Z(8qKpITp9v#md@Vw=)d!dBWA zU<j&kml^ zurUTUX2Ql|*f`*M)bp(8WzXB54?HtH-*~cKaxa6I&CA!Tj8_$}nqJMl+In^Kit_r& zYnYeaYm(POuVr5Ayf%C7^GfzQ?RC*B!|RpTC$H~b5^t5a+1tyzl6Q4)&byv>b8k$Y z7ful&va@YiOr~d(nT3pO13XVU2udN-X!&!X*gG~JtSL)W9L&}C>Fjr~S( zW>Jr*+telM1eHu}qmrm))Iw?&H5t7K!>DMgH`SGDLq$*xDUPa5RiP?SWvJqm7iFR} zl#Ie^K`NVkPrf2E$cN+|GL^hao+rv8LJlQk$Y`=3*_-T1b|pKKZE!~5OSKKjdSn>Mk+sPhWEHX!S)MFI`jNh*4_Sot zAT6X3Gv_r}VIU*1I@Ec7C9*NI{wW~4B`>-fVhWQ_qT|f#C75-aS1c=&tg9Q zN#Zz>OdKW-5c`SUn5n;=*g|Y3l5nmi{vcKo%ZR1K@5DmP>Yq={!~Fi)#7truF_oB1 zBw*gZ9p@Ng6fpv80pf@u#81Q^tPbc;^d)*@wE$+UVC6s;tRUz}w8v_KHbhITD~KTQ zJ#DNrXh75_>JnjCdB73DSj1Wjs}ZVWT|yPCP^g5}3gxkGp$t|q_+c$W39M=;iuDcN zSn1$_RSy=de=uStgbr&W)L0#%z&Z)3Gs_udAJ$v^-T56tUlId^6&%>)1aZJBSRkyN za!%pE3Ju}Y+QR3!6u=H9f+;{)y&)WeeLE2B<+zh;AA0UCD2f((`*M2x3QH_LF zreov{(B_!SxnFpYKi7jJ~*sov0-7ujAO(4Oqmcy$tHyjos}52$uc8s!5_23e5%b0t9Itsu$1nL z!cKl$0{>Qo9k0C_ey$7KleiK7ZVjvaa0mR}6LvcM0Q^r5v+X;EFq{fYsdg6OxDYnx z&=rK`df3y5TL{nHustvDBTSFO*3El{aJ>v0QuhtQ_95(=BOBrS2EPb?P%DbB7S8b2 zAQ5j0knsMcWqh+@3O>O@#h)^2c)eD~M=A~c0hx){OD%jKiH+YY@#HC)Hy^6-;fJb= z@r(2&_)V6Q{3dTdet~akzHhm*yic|A{QlsIe6@y^`8lnt@G0G^@oCXD_>-e+@>8bO z=8G(!{KX4Azvg~DzR`zpevh;f|Ju6=pIN0Dzp+tszH-l&{D@JldHcM! ze7#NW`O_&KdGVvpJVA8hw|e&AZ8dxGHQGh-@?m}W+4KAHDZ2*nTW&=2^*;~hr+Wh9*y$`1G^FB}K_i1MG<@{#x&x2?4@7m7c>kXdEKbZ0}pR#-&|7qVZ z{GdPQ^W|Ut%2$*8#!oD^5b3#y|Iqe#-ZW$}KW63<-hcg4-ga^s-|WG1KIO*>r0*&| zp~fHlsn)Cc#zWTd`Z;TPkIn1&$n)#@tjr{&_eTDd|0Z7FU^Bm@&lbMVl&$J-~}U9z=c|=I7K(<~MaY!iy#x z34X2i6!Is9zue(8zkl2r{?4kie6=&@_>|Y@`8mdmuy+ahb(ya= z&!C@6+`uzX#tdskP%7|N8E8{!i%(HhBUMsFu@6OPV@VXs z_FoP+R&b``tKiNb+|BK);no_CDYg#ot>?5qCBe-N+{cw0;qE3b?BHg&y@jiEcq`oB zhOlghA3L}S6L-R&U7Sy&-SBG<_k`HX-MY4yldjnZKlgKs>l}c;2f2kQ2jTZ2?tb0F z@IRRg+MSFr9N~I<9Yr{fa*`3p5SHWIzB9)Wo)es0e-dFj$&GGt3gJ4%O-xKd*iLhE z_nb!f&LDlxAdF|Zmc%)P^BlL|dLCgt&n+l>0pY#CRSmp|Fkj@-f-fQ5m$)z|7FrE(c{ZXu4hxDZtu;+e*YZ>1rwx4HH!ZX>>TkZ*So=R2Ii|1RQvm)r65 zF5-TVYr66t;-Aia?wF1=NaxOL?;{=VbLq$LBP||q_2M2NJsxm|;t!D~54kQE9wJ>H zaaD#rLfSmy)_Xlh`aI??A9;*4dcy7Q`2^|ogo~!1BCVcs^zx@jucur>?F^(@21j4d zK)OBSrVM+|6)^57lE4SI)sc*mtaeTTew&(-Ss9{KT} z>v!!v^5g?IsNo0X%LlH>p%2KL51gXXN94~(Zp(^~$fJ*3u>KSB=@WNo!YAa_C$93F zPsp!qZh4n%W6Oa8M_8f5K@>dQT>x;;;SiWUwct6bX~EOkC4!LToD#HX z3!d2y36V#JVVxvD>m-)U{1~uuAV2F6!2%Spona_wdz~b`JW1rI#wmixkE?qp?|%{O zeUSeY_Gid{6rN>Sc=FTuLPw7I9CJChUHO8o$i)Ru=nGkwOMbrvb)oDjm|4P=y3h$P z;9eeiDyMFt%fC2}%_)SoC!m~x%9&-K8-BM&?sWmrgbVB)k{_oJf@vYJ*!j?2@U){R zB>(xB_&aS1_Fa+6N#DZKWdaFV=qOlvr%x?ddPg1^o=TbVtBp4iK$BkPTTl`r?GCqGb*Lv$rLMi7LMPk zkm4cvAvlAz0CsGCn-2$F@XV_(U8;h0pQLc|5z<@3cIF3;V{KJ_C{*WpOs(OM=KIw2KGVb==bRHi>SUM^AQ{bRjiTp2FN-|=Z()q7|SzP=bNB*`;|Ft9epM61H;Mo`If_%@uQ;qUM zvQi}_lBsC1TuqP?DMbqsZ-v^AQLfSxv^-4;I@4`)T`p_sZ%M`dasgI>vxRq*&?)Jac>L8 zUrSU9YuRhafG&->%4PkE`Iid_Y0`Dz(4TsDir{P4s1_Jhw|VD2F~ed9_3PfQRm1Q` zt=sqLKR6EI;M&*mujdL+*5RCR<;dsB-yPRL#UtMx8bE?9T<6@!8-Rhb(%y7srZUrr z>A-dn^>U?=%Y+{>j@d72A+9cYDDEVBBibfuFG(h@ks8*M4MYd~2hkeQR?%B_CNY!# zLd_Eeiv2`8SSu?Pj}TR$##0^GKgcCaQBh;jK~Y!wHC=`*&SWsHn9)>OrktpwIFcU9 z7|FKGF{%X{!Yrf0M65_ElC#$dCEY+|X1j@YO0H8D_%WYeKqwg#b5C?wJXX?_eL|fR zMY9BDVy3fis4Pm$USOMu&XK#BwPY>21$&X&#cpFZGsoG@jE%}7=91CORd$rxz#vGem=!ePXR> z8^%vR5G%wc$$BQ6y-x2C?~zo%H!~koJ?Z|;pY&;_70ojmdK=ZBW~jsTa%wE?!>oqc zDCQBho3@kRnctWfWEoLBQ%(Gg4I{;LNhVA5QT~M~N3UW!v9qWQ@+|#`d@9OhUyC|2 zpGaD?lYKt;7UTMkbUUMw^(C%ywok)tBf-uVCNMGsP9f zuUWe|QB+1`qAHQ=m?UZd8!M5Cqr_RvT&5Dna|Y6_n7QmM#T?d;@ndhn#BFM_m?W>U zgd|j~5fx#!(^JXvcnzP2m>7_AQg#e&W;7T*enfAew=$!sddyX6ak?qnk&L1mh*mN| ziV*fSU5oupFQRS{kEm$6t|$~UXhYbKR1>zjXc_g2VnyZg;pkvdQ*m3#Tr!x6pf*s6 z%qEg&QrTndWwt(3jebP9C8I$K>)i>*QjuvM9jWHvd79!w2oN6;ha!K@!WiXIC; zLPb*cG960Ypb2(^Xg=A4nMHP|e`Cut6`5}+y(idH%xbC$nN6*sqeO3MEfp=Az$UXv z5`ua~zM`fuhnXH!Q_QsQB$~t2rY2D@$eH3jOh>A$s1Y-iJuBAHM#Q!*^#$Yn!J^$v z8fw37)F*lwRgI~K@%hD~C2T9ExtyTiF}0{`;xy(x5hCx!e!}0wK>#4X* z7GX=V<&c+4;a)SQDI39TqnlGL+15-2>LqHAYuJ29C9d)*@2zqPNGaklMSc@x&$+hy~hloqnTDBZ{|2zmGY*Jh)%Jm z*lc4nC)X z*#M>zTa9@|`jE32mYvV^7WEc|&=({Y_B-YxT%;USL-8HaN9Hb5lDZ=5EqO@JpmtG@ z+3i>%ag_N=jugLTGRP0qVREJ1D1Ofj6?ssB;vk8PYJl|?E$P;5Tl`O;kIVVf|$spZrX=>^(@zKOFq)q^R?l%*%IyYWH3XzD#PjrxPQ zPG3dNRKx6$QKHhK<8)(D1htx6OgE#4FzuNB?0a!%TFd-Q)}?P#6v8%A^nmfF$FbvB zJKc}2z>Fb%MEgXG+1ZkGQqI_syYFcUvw@0Y%ZX}AmZ2;QWg~!|OP_@Osq6yGFImJc zC7)xhNfiBq`HJlozSCk>M$ISh((S1?^c&_4^N#sMeWt%NDfANLf&nfn*ma_9qO-&( z_BLu92Xli=pc5IXNX5RR-cf^ym2?kwIWt2%STq{H7|q2V?0j+wDPkNnR+X?t*+HVm ztd(v<+Nofaqg19Yo5<8-Z;S4-6{sK7awd|TE1JhvV*84ZF~#Uqat2Bw7$GVCdZ4|Qf4WHF z=^_7bre`>3n>Z(*Xmtjo*<$nX^7biOyhO=T{-w*7t5C6WK-FqB0&CT-6a3dhm|l@< zU!&Ci$Zub*(dmsQi`B!^yGYSu zC45Wyl`d1Re8oxuRjO4FtXVtgueO7O^VwJ7>nHzg@CEw}iycN0eQYoKPY1uC{eM3A z`RxCh$;q&-vv8~nj&dHaf;V_}=vC|9jo|fft~BYP zc@$j5>Cjd8{U^bj>faw}*z`JhltEBUbo-a%e_oti_jkC>t#ZrbZaFV_>vB`+s~4`+ zciBu2{t}up0u611Q%IYWz+S*@t(^6|6!F_{_|_Y~ zM>4mB@W_+I%!lYFI!6%Y_Yp9It<4u>f2p~cgC52x3xq zf-rX`2zh$~?qJjL<^*xPDM8$7L=Yt!5X6#t_^c045E>yjIqY{{hahU##+O-Y62!wA z1kt`aK|HRC>na2h5P%Q2S3&h=71?+92g1)f?l8_XbBpEP!I?z0YBgaEIhv%z#Q1tfs+U&Xpebkw>Vq)Af!ZJtR0EYk1yBa~0bfuIcmoe$0S2H2Dj)|EzycEdU{JO} zHuwPEg4f^$cm|$;haer?0k^;nAbc0~GPnTFf)sEP90SSVAlL`?fSq6)*bFv;^3E~_00P3T0iJ^l@B};p4?sG&2kwA0 zkP6U~LR}B8Ug$fgOwmW56gd z5)22!Kpcn#G2kaK2tAbdu!0SE{6KwZFtP!Iw*PzMBo+Mp%~1T{c)P!&`G0iY772r7W`pe!f@N&|mT z3X}xCpadueiUJ={1b72a-~nvF3e3O+jKBc&KnFBH4OBo06hIE7Kmx=-1X#cT8jyeh z4hm%zdL71{RB#jA0K)eZuYo_oRd5Ad2A9A^Z~>eL=fGKT2Al>d;1oCsPJrX! z7&r=!fMjqO90CWy0kGfAKFGab57-TMft_Fn*bcUVtze6r&5)bGMz8@S0pXQ@9a!sT z4diO@2UrDGf)!x7n`Mwo!4j|-{0ff=FvLv^ z=dxakcU1tQ(_g6!$02V{59%}rOxE^azQc5>4ZvIA)E zrX6HkH*FwWyJ-d4(oGA<=58V&o4IKU*~Cp_$VP4&LN;&{4q4w#J;=Ilc*rm}p^yS0 zfO8WJS;tKfWNkOKAO&iIKsPlY1*(H;ZmL37aT5S3P#IKmQxQ_20x0jM9Hc;5P{vJZ zNCAI0evqZyl!O%U1tr`RhZHF0rYNM3n<9_`-fp}g1w4U=8ylp6)r|#Gzzj@ojF18b zH+o0`of|ErfCi}Ds2~NDZWNFLayK$a0jV1aq=49s2vUG`!$1nqZYW3r;b1fzK{64+ z(YAqKTb@;pUyWr7Yho7jJE@Jv3srPTAK`~D@)X_-iOUoQ);o5(jm zIC^gIIp=XZ`0B&2{GR!5T=%nQxy?&*?1j1P=k&`w3&xfyI0n1S|Jdv{_dZxdkoa5X z(oY}c*3Ys1UrSg2&dJccyE*d~OC;y%K?V0hTffOH+f|$F?4}8zIhTAG?CLMtdl;ph zJM*@|PtNWd!z+Yia7Y0++!x+h1E|M$kvy;tP)o?5)?yu>1UfSO7ZD}V!C=6YEgyUt zNlS>K7ECeF5#zs*84O`3Cc>-&YyPJH7he2>?>C7Ukwl~rX+#E*MdT^6izcG=AvlXS zKURY`Z#3|+7Btsk@BgR0H-V3$O4t9-$<7`W1QfJYKu|^-M2(7L0|9~tXxT&uhwhMu zM3QvdNgyanyW^;1bWm|`_J}&habsLtL}g}lj5Ca)GTI_2qp0nU%Z&f;TT4=1>3C=6 ze(vwy|GnhH!}FX|Z=E_@ojO%r=dDp^^Y3i_8GnJAKvhj`>(+Kc-anErKgoBWdXV@1 zj4wXP_nzcyPXlO3{tRSDl_`9qG$ztMN^z9qK*xA!|;*Fuv)OrSn;nx*zLP57q-&u{vCzpif~P z>uIcMovCN*GFG}q^#%H3eU-jm-=gEJi*42$^}g?48B0O`8^3>*zJAtzp8Jw9-s~~Q z2X&Uu?6}smPtI@ieE!gUo_p+{PwjI~-7Dkze8hPzf4fheVf@+ev81fXMVEWucnN^gSZ;-3t4TfM-SR-XoD`4qE`ui;VX#HlyP{dk>8uY3}%W z)&mX!a-*>n{2;*K2Mm6|;0FwTz~BcA9?0&ch~(-zx?(mORv1{=DXJ4|LD^%y!_hR?|<_3(o3(r`nq4;eA`{C*WYvh zgO5J`^s_Jg;pIQS_U7B~zW?DTpMU+`(u*&>{K~7YzV^E7e|6){x7>EeT`O0wU4QpI z_uc=%gAYIY+sB`L`k7~+d*OF~cdyA@~?)Kcj`OcuIT$<_8;z@v*_HiW&LN&E~*%^@xfku z|8eGn7ll67UFX!V z95MB)6Q++C_W0QkoVlUL`^SD+`^Lv}Dt5d$xBk-Zx72*J-aFy>*Ar7l^W! zdp|Vu-K<@;;Rk+SJZ941A>aM_vD%M5^mqR5k#h%h*?Lm9ij&_w?$Uz`j=FKd9~Y%| zU3|t9Ctu#MeED5!)JMCHF#B3;Y{#unANxPv{`}zCHLG)8cikzsTXvWH9`^fFKN;Kq z!yU&T$XO$1zq<<%D65nKB^pi!$kM!{2y}HWkkn!zyK9hG+ zXEnOKJQ}L4^$d!5DuT6q6y8%=9h@KfNiCnN<12Z}~8Iyd*-eNtM zv5wDgs&mLerMvrq_h$ zQSI|c}-&*3A8736ow(33oaYUM+T zgKCEinm^1lX#P--XGky0tO2)y8-UbZ$!_yJ5-opA^3%f& zu5hg@T;U2Q2Bq(>4o(ky-b)WxxWW-vxG|Y-AJ~z8zI$5I!$VyA`(0t5D;#iz8(rZ- zSJ;k6l`)63)eK0Up?uI+{K^zEr#>H9ai>c{U2SGdA)S2%HCdU|nJ zSh@1Q@tt&gkE{RecG)+(!cDGl!WE9Y!p*MZMRuegKjGT0cBXG{a&1qpy4f*W@~)IC z|65$gZ*he;y24)9{za~^dN(~kF<1U$uI=&n)9sZjoOB(3n=4%5PT#e^&vm{mbM3EO z{lnv`zl3Xhk!$~$D_r0T_jQGRuKM!3!ZBBW-0kZBg|7THyYg4!3eR%cm$>q?*Oh+6 zwZG354!FWAT;Ywb@GMt&qpN%kuI)vxaLg56<_agCNgpq^xWe09;TCuJ?ezZF>wY&vJzWuKMx0(oeX;o|WnSCvtOoIB^nd9ogb~&mwn^IzVTt-_>fiu`^Lw8Z(YpWGcYXNJT_66V`?r1D zf4qMGyX)sa>i_@U`TMUveuna=T`d161`1gl1!VEKa2~!E3edt|gZ^mYQTS#UhW5dw zU?kcPp8<-{0eBM_g>HdI;3J|$?BRFt9}z&O;C1+ws6#iy2jYXG0qudyK_fZ>-vL&j z<8U7SD&puucp+GWj={-8Sks3V&h@ZHP;B7Q;0d%J{s1Jp&Q}90k7D@_f4j) z(arF>DXhU24R`jlmKR+JdqFu`cbOgR}CizCk z;VoxUMsy22X%?#((0=&vvneCm3oiqOmy%ET!kLqz`9uqU1!kjJ zcB7Vu=!fVyd>?2)H^T><$M3di4}5wpc4$BR`C`_QqSg8I2e26(gWtG>b*|_ny!A@j zLNxrs)#MZ10>26hS*nzTk6_tTFSHka4fL0I_$x3_mNQ+;J5yi?+5?XV!_aS~?Ej;v>^hvZA4gsIoz_q`k?C2Q02Fyk`!*AV4+0jY(QxHM(nK{)2>cj@_c{A;W z_Q1?PHna^s6+eV)DyHLTKLRo zS#OIDz$a~{F3>)>=6U)aIs&f%ThMX%$rtH2=mb3ACHfxP1K$EtVgo<%GG!4PcwP%@ z7q1{4xa<}Bp=kJGFcRGeKLU!-3HWcohfcx${=^u9_P`T?AMJ-1gIVYpeA%CAFLWdP zD5ygx;19qObP7IjD|ToPd>Xh0?T60?%h56TGjKav{RJDaMr`2Spc$Ql`@G6Ii1xsq z*C?lG_>kAB6VdSNAc;=G=e)uG=m6aPP3i|-2ww=kN5|mTLBW;S!;`kt|IvQ94tUTp zcpVsmZiaV*VdxZG{8z>lv4=fxQHN;Zg`fl-gTDZ?(R^r8eGTeFCpo9zp?<^$E_|1M zj22$Ki}pr0!|#DOIt8Ej9{m~ZgFC%XouCWhGLS$=;9r3)=s4VGH|IXu178KUq8s5; z{>EB)v=4qC>_n&F=Re?FK)1m6eMtSFo8eRT(0`U;5BL9w`ayf(F<>Ct53dG8(9Q54 z!7y|SJm6#MN9^GmFcKYsUjjv91Ah%hq17j>M+QE$555f)qvP=3L5bL;So;l1(GhqJ z@S~gIZ@_f1`4pcDU>4d3-vi3U2G077^ATMLmw^U!1fKFa(+ad7z7#Z~8{uVNQ2(Og zSHMH)B;4<7#uKy$KKmQS3v>V;^F8g2_QM0TR$Z^c2JW7#)j)J1{C2)pqtHqCfNok% z7aKU-Q>!X;1U{mdR+pi@@NjSqnvbifdeDfD!F_sbwH)n%>p)!M;R6rQYK_Fh4})fO z0=}$|R!^WC;R$`UdJ*l1XM(Nh06Z6LLr36RupJ$PF9S(*BfK2!M91OZgWc#Bi35Ak zDLA{IRw;BLJQRF^_QDgvUbG)x0lr7a;kSVL1$6?Se4ti2Xdiqh=!%ZRKY(6nb&ytb zK!0=q{tOJ1`2Jd50*0X*;hX_ljYJp1mw{0d59b`LRk6gwn?NbL1upVvH4E*7mmW%6 zpkwgYhiSD0tq#}fG;j^t55EGIqm%F{_-9*#_Q9S()Hzx>1~#LG9|kSx1pGbNidKWE z6R-{Khi?bl(Q$YyNTQRXkD#7K!*>m#KE(#Uc_?X#hL;?vRRIo`V(?Fop?=Ul_(L!C zfKI_@j?~JB4#587C@)(0oa42MNIdL4L91nG;g7*`bPCQdqK}~q;a`I_=w|qc6ScZm z?BT4Fw0cNv;GC1`Z=&IxQCe*g4dyuM1S26Qw0SsmvNTGeYc|3a;r#0K67 z66gec`$e1==s5fm*otm}hc2aE&|bLn#q@P_Ashr>pd;`muvhHi+Dm8`bPWCq6kN-3 zFV*T8&ddhXb=1*h>Jb^#4VH)oq%t@mGYwF@Z{TR7qlN<2DYOc;SWI)or1r-gT9AW zcT&f9ai0DXdpHIP(ZZ+1>2GKsyc7(Rc=&1HMJM1Nz(}-Osnw~VNbKP&!6AUxR)}cJ@A{q=G+t; z_^Su02eEmGay&}AqlL$TooGLt|69r~@$i`-g$}^4fxYM?Jnb?1_jSa>pMyfQdR(iq zz=QU~H-draIQ%6TA~sLZufQ<07oGvU=m2~t7%BGf_n=7ZpJdzvKCyulpad=Kd5XG1 z3qK5INjyC6Y5EM>55E8^&@J$U1a&C!@C%?p;^E7mp(J_1t;TGo4#ghc z@*L;8*u$4TPu~)Ic*G0TA=(GO1Gb@4u=n@$CA9G5KTvOIKYZRxoC`RGi@|q-Vdyyg z$RF7Uoq%t8mGVkFe8lUN5$%P;Z&DU?1YQGT=w^82U+E8MA3WeK@{IPt-QMP0Ko`P` z!M*4heCj)lS7Hx0fXxyQuLfJt&G51vlndPmm+Yi0Xg@p;q|gz#1?)u&Puj)#emyqu zYoIGS3E%r3eFNPL58uuCg7(3CKcGLL)rVTG0zR>UC-31ph4#Z=ffBL#NUQxnrXJ89 zxZ)Gq5gmcYrzpGF!%u(7IDk&TzuC)JCmMd>ACy-#++Ag<1iBF3qO;VC=oa`OoR;iH zd*Eq#S*qX$`WrkF=O$gzKKMQ0L8st(I6fJOj==AMArcSI!#T<@iHF|$LK&RlDIGK47 z9e^*wAx#T925-Va%@<-1e>*Ts?L~`&n_mv59)3lifgc2;&Npqj07(3+;u!0}W_#vU9}IS?V&0ho1v$&@J$d$7HD{bQ~V)%~Bi12A%|- zK>OiqK?2|ELAM_a1D-*O3@McUNBp1;Db-451>78&6q58yV$_@jH7eT-@c8A7 z31~ljBgk37c?!REBlU$&!kcd*&*&ETp_|DMIsva)K_5mp!^>}>51`}lWw&OjYtW5w z-ECq=8R7EV>Cfm0oLobm(89~^<5;&~5BGh9K8g0gE1t?y5p*0bdVzG%K6uN^LhiDZiGL3m%2iWQ@ApMxtZztDp#-gnQv|aTMAEH{*cOhZcSw_|Yw}w{NzZg%%!yqs9u+ z@EjaBUWN|9yKv;V44r~U;@~lk_QC5x3%VKZe<*oFd*EXZ&sKZTUU)g^dnfG+Zw39) zN!Ww)NDo?g1Q><(!4<%Vj=-0KVss)n2i*d{0t(Pc_#My{oq|6Fg=ldyszEPwA>0%6 zMSI{wL4ULt9u7QcA3PciMEl`0zz}o*4uWCm2z(y!qGRyIU?jQ`z8(~z+Q8M}u;- zA3g(ApaXCaRG}mAc_4z0!54!%bR&E{Xh6r|m0$_F8NOp)wu(tS9LAyR3Uma%wwiMc z-3b2xwxGrF>uk`14#2+!+t3MkU^rVP(O&p@um{}&*W*0)dvpvQkAvA>tH?imI1Xor zp}p|&OQ}z^5AJ#=b%HL0UtL8$(MkA})#OcV;Pv2kbTj-8XhNsp)7Q|S(SEoQY(xt` z2cAH;z1l`vE(23LdC)ln?ENOMoBkhi8E4=l~o7v(ORvaxfd+2q!@RExZs%(iP|! zJRmzq)uBD`!8ti9CK_G@mWd7g09cMrz)N#;R9xcWXkLzL5)EI7GwY3_;S!u%??LAQX0$76f z!DoUPIsg|8BQ10x{5)8OZh^CK{(X(a!=s1is5NLmJQHk02jE^f34a3Zfo}ybqT}%A z$L6T5XmKPy59~ol;OD?zbPK%TxE%Gp#KY@xI$p4z{tW*e^hc``a#T++1nq%~z%aBA zjsh<_20smo&9!=PO3 z;V(gz*yBY0I8Z0{@LOT}2095ZjBt*iWAJe}oo^N!`1^X=7cI`{*EZy+o#9 zyU80|3c8~G@K>N0TAiPxKDvN%p;PeTOUOUk3-`TfE(-jj1xiP*z8@xco}It~vh&Q%o>51#?5&;fWch@fNe zHc*F7!l#eRRSjrAJbZkvT7ve$@ADyzW#|+U922Y?<@KdMfssuU#kLLp(+t7aa9FRf>;Pb#2=oq~J)LgX}?SU)! z@JGR~sZaQUv#2+80v>sGt{R5+!Lz|gbO0{+8TE-Sgr|TKv>%?yM?|KJ4SWrlg>HmD z2LZG?Cs&OFRbmgvKm%I%3$R3NeolRWYtV6cz#QrX?SV&td(l4lT+ob;z;A(#=p;Nl zn5#CU1Mst8E4l^VCJ-CApe$EyM;F2;fF#-nj{`f=es~7hjSj$%fj#I1eB|6*^*!1P zFD%bhUGFFVaIX-34();e2E6DL{F`~XY7{yFpEN&Lm7;y{S}+~m4DSZB#U8G#pgqtL z_+ik1PQV3~)DOB44uEB7;d{VxbThmY+>TDcr=Odv;%Gm78@Lx8ho1!xp;l+6S)#+tAJMt00L^!bQ~_Pi)}*!?YjT1D{u)%S$2D3H%rzo#~5C zz@hW$KWO2Lz$meS*MMTQ@MoYDEnIK`{RdqLKM!W3g*Pst|DY4_cCZ93Jo3U^bs1Xt z1ki}~!Np)XTDSzPK>Oi)!R=__Jr|J=w6J_I=OMK4>6cIsXyKzSWz0bfueywSKsUo( zFK2(W@I_!RTKF?i@Bn3je{)5yDnuvXouDsT_|PkJRe!Yb8sI?-Zv$SmaPBhd8ZA5r z_|U>vffBUv?|>gIeCk!y8`=kt1?A{Q_$E++j>GFf6}lOI^%sm|=pM+>oo{=)zxdE`xi~o||%25Ilqyt_Dw_g~#4ZUqT1q5ZH?T-}0w(vsCT~?bTiL zRo5{E-uysbgwO6KvRe2qN#{J(c|@K!H;@y__Gcw@4!_Cr&Lh88o5_cn5_v5-Nj|zw8u_ZTw^N`XlJCz;ec&X;|x z0vYFWyxD=Qi1u4)$TrFMCRe^Y%FF)vuh)H)`>5Jkj!g9+>5Xyk#j*3bw;GY{%?jv< zQ70W8H&dF-2w$AjAEF;f~+eyOJ$Xg|BYq@Kn&>Zzl=OIvPYf7xD^p=@?~cKth9 z`bE^yFC=eet~PMijh&VpD^r_G{EiHH$W&&#yg!y!rt-M^vh2Sq!!g}x0%$L94AwL>}{Fy@MC4WBtxF<`pwi1KbBTU`ReE#w2$NL3!;Cl{O^3vVXCdhZM&iAcG8BD zPT4=fnbQ1c_s!2z`Ha^_pIBvGXUw`Y$6KQegVOWnu2ZQOFZs;kw_~nUI)~?L)>R}; zXJ;$3hNVmn8+(5#v%pTLATRy6-3wIr5$RVtQ2W_?>}O@E$sIHciEZG zO!L022TQ>VxgaOLty*r>0W{??c)1vN5z*N8?c6uBvYXzZGNOJ?a`yWuLMR z>QVZO^O=A<+|ltmikEtoZJEXz+2*VtyDz)@tlc*I=d1mBpR8L0?+RD2u2<@zTW(ue z>O|;y1n+PA;O&!|MP4%njs(R}F?Vo*k z3Y2GAXVs^nlj>1XV9sxy$C2~2g7=8sb4eNJ4zsQ~PVLFV_zHGQw?6hGsI>5 zhDAR$>^5cSlSZGn+Ek8lSPyj=`}JqP1K6)8>9>16BzAKSP;>Tr)Xd$7s7c!nR>fNe zsFOGLS0kDZQbSi9$Z`A8Mty0cKD5zT?r}5pElJ0H4oaM0KzB8OzS4*K+>iSF(K*W@ z-PIwqSwHOe$G$uEY0pJMXgWw)A(9zR}kFj!*mn9JeRO?Yhc&M~jX7JfD5An!UHHnzp-( zI&B+1?YDGNMH>s$F-`fjd!9Oc8Nbmq@H=b;=eo{ty*#of`OYKXx$0o@)R$xL$FaL{ z?1CMR`?CM+amF5?#_sN^;~YhXOwpOZZ2?)%d*WGw)>=e zAN%_3wC(7eviG(3vDuDyreVj~HumxVneq0R{nasBsOyc?brW^X7|@3?peJKMSH^&} z{#0~;D%zG$+vd@>xwLH#ZOgm0*!RM|2licb&$ee9|IxYQyoN{_j_RR~BJB>Z5purC zbvo1h>VI0izpwId`H7maahUpP(^2ZU6-TmmdZ;?QVTd}Y;t2ZkIqm!MzI{^q->Cz; z|J(f2UetMC>bwtiegJjen>z1Bogdr2&Wn07_I6>s>CCmh6W7ZE`Z9Bn3g(zx16rTQ zb;(m*=->JKSMHqKYNV9-MQ8bY%27x;jJl>A`oGF{`~hnG-cJ8yK6)$tuiDQ% zK+W9ST}|5EO%-qJ%KJ@S)QF9p)zGF+jF|l$aYUsw8QhB<|#)6rb(UoE?&)zQ7yu>Fm9{o2i|cVw7X+hy$6HGN*{{5{6D z5&o~Ze*8P*(Z92gvm6T!RtxqXqRMtNH`+FU>qvjDBL^|29mts0k1?$;V_F}^n*(Ue z(e1~y+5MPb_F#V5o%v-q=9gW6WQ_B)jd8;Y)iBP-4#%KBF$Vp+Y5zN8(UiVw3UkBp z%neUrZa8vF0dvrN=Ae1ZL38O7Im|(sk5@3?XKrYWdH>nE`&ZAyf7RaE&i_-i@m%hd z_Wj6+pVC2mhU=XDY{bpZ=W*_NxN(dD?T^u~v+Aec&*|wc4D^U}_jgNlY3an<9PP%m zo}JA5Yxi&e$L+_t(vx$gkaML6=Sp|Zl|k)~V~mOY*mhj|ZPGr@`^QXSyA7RoGWL~a z7|)Ed4sU-P=e~B`NgA2PL?gf5$Zv)^v-2X{(R|o0gZ*1(N5|VAXk z8J?XVNo!Sx`mmqHIPJz{u*>uex1;wAGS$1g&$+`xyQ`rMC+R~gPSpMMqO5j(&e&eW z_7m7%+kU&9e`h<|ankqg-{1T2%xzgN*L~h^uE=hSH|j56b^pv&e?}j6&tWt4pB{PK z>*jK=%Wp0+PqdG1v)!kh`E#C=&h3{tp6`vZw9F?ip-*+mWnRX*{W2@wxX$gzwW%l9 zrb5oQ9-MF8Ip4Z*zR5h}i1vM5`a-5Qvh!-^QQpI_<7}3FH)ZG_5}&Ex*!$W2%$^t7 z@tIiCx+KFfqz}5EQOo}BzGT;>j7z$x{j*nh`JC;Lsh>Ny+xfMRVYkb_%Tm_EGL+S> zuL9Tm1!7;8!QSWx!{`S`(GQNK9}J}*451$!K|dHwKloYuejs^XWsOstGNkFQSG(*s z8)IqD%;}bquB89Za7T6UW6y<+ZM?g=BSXGB>OV5KO1uA`(LV1|HoGm2cUJnQ|F$lD z$3FMOR{F+N>weUD59NsT_d$#_j!aJ@)9+bEUG{FDAG;q&nO0>etK`9c<|H;_GT7LC zRkoL9*xo6Jx!aX8cZ=xGjA43N+kA9pUo~^fG1-$g9-Up>^pot9R}9M@vFxbqp$$i7 zA6hXKS7gDwc4M`1eOykTJ4(Bc)|ywzw^8N{%@pZtAqGO?c=4~o7_3E zkAH1@dn5e|+s6;xkLRKJJP*y|c_`1S8SD4wS(`iMv@x@zV>`zbvDx8Hh5Xs=CUs?x zSpl@zUy{LI;>To&&op0XPAxX>XC&@4-P=1#SL`yq8!q-vxYKus`*c!$bS$ffw|k&lq^rM6qLcZ)x-;KS z?arTFW}AP^R`TVnGpDV+zu0sXZ?}bQ>n@8OFKM{*>HJOIX!i`yqz>(>4z0+_>PH6J zos*LGROY(&IbgH1JaSyglk<5|=iJ=Rf6B`?u9|+fceJ1EE0E(vIgX@rL)%-ayr-Jm zZEB}%D<)yA2e8ZQt_NqHoZ4L{_Wm~8d2rj=dH#>sc`Q3EVdMAeJe9ML=vxVOMphtz`{)1FtYVn0c*kNbIMPa~d9|McJdiJi|8<6b%W z#=f{QQ-UEWetX@Ur~0aVWBpUf?mWYffUMP)^@Fl@OV)D9+AdkUCB6-o>qf;twfL?UzwxrRQ+!}ICfSb9R`I3bn~U!RSbT(t z4=C}a64=49SsyBXB|I(Y8hk$7t_}Yj3i}wg;&V>?4K}lHA#q+%Q6{J{D-R)AxP z9~1E@mCB~f-?NqqE{wCz5C0D0??HS!i2rW!=bhTcamTYJi!^1eWfSH1g9;D_i34Gv zIF78#6d$(Yzh3-3h%b8aGcIcu#ixY${+2cUvff|T|BG(`@fBdK>py~ZvuN=tAZzhu zy}$Sr5Pt)*PJiP&9OH1UJhb(0j%E8o5Z@f)V?+FAh<^?7FDUChWo@3UtCRJ5vK~*? z;mI03@qHkE2W4$$GwFz5L-Fq|{=3C*M-y@4+c6>K!QZ2-1(h|Rejt8VWes$kZO!CI z{I*7R$S+i&R0uMY(TjBFt{Ddc0(KeD_?$86Y zPlWan-!kHVO8g*-{}vDNJ~&Ri_@Rp*PWv2BzaGrGS?Xg8`DpUAr*;WL^ zuLCEk;k#V?g@~UJ@gX8U7sX$M_=XTa5D{#|mxPC~tYejRt+I|*e9XovS3t^&zjO62 zX`*9r{C&y`l5Cgtjk2y$*42uC6Y*;z>&KJiOMGf>gDcoi{OO8c&6w<)L;vDDk@day z8g5zFy$oCNOWz!#p3dW#a{>L$!*LR@d>291ddeD4S=%XVI%SQv_#z3AR-FBcNFxRc zKwlvKAjL_<9$=@#05b{J4ux zcv;(=A`eYK)^&^j3Gq82ekH`8g!r8he-q-bLi|+7ns8Z5y%GB@AVyuvH#lTHuzY7j z*8Ix13S=F*_<as3f{6qJZZTOWggvF<{tZ9$XCuFU+56Jp&@k<<_ugMzmEwB&Fk}&PKQ~|X1BZc;pctG5s=;D#8E6Ezf_30Y@JFx>>;Yecg1mgy9~=oz1SMb= zmARm8q{5B58 zftg?)h=NPO4PZTZ6g&sEf?Ys$;=KiM1UM0tf;k`pVxSS+3GN3^gBQUYU>Dd6I`eF3 z02m662gSe-&H-T%1HS}!fd{}Q&;tGnJ^_CR-MWwl7y*jGOfU~LfMwtg@Br8ZUIib6 zJf7wE1xJBmFb7nF3&F3zz2Ft_K9Kcc2Y{i#2d07fU@^D`+zB28&w}mXGmzVz`UF1# zCxA(y3S0~B0e=8*gU>)N@1G6@qrq%&9#{tM01tzg!7lIvIH)jR9ScqaKL;0qEKm)i2tOFatAHgp04d~h{UmXmN1!KWfa5ks}7l7-)O7Jjv z9=r)Y0pEijz3Fe@L~s_k0Q?d(fz9A`um^k#x*d?O4gtr4@!%{F0#)E*a2>b<+zTE9 zFMz**w?PVg2fFsjSBHY(U@SNToC7LA6f6N(gFC_f;05p}uoLV7dqLN}louQWMuVB4 z95jGS!A)QTcoMt<-UNGq>POvzL%`ACWKaTTf%%{TTnTOlP2gehEO;4g2OokTz~B5*ZW4ekYxfM>vqU9ho6(|@$e*=R+5jYLZ0_TFI;CiqDJPe)%e*(L~51{wK zyz>c80u#Z{K|Qzv+zeKO-+;%#OW+;wHRyH-#{cy;E&*K@Fm!PAm=qW5ljX@2Q}a_ zupHbEHiI`n3gix=oM1SZ2z~}?z!hL6cmli#c7U%yr@{0AFcM4#3&17dR`46}9C#Ca z4SF9zx?lQv=ZqtzHSRu!vpYP_1DO4LMknmS#Ts!3|H znxg#b3^i3vQ`7mN*i3b%nx)QCXRDv7+3Fnib2Uc=R8W+|b*f%1REt!DTFhs@E>KIJoLSx=dZJu25I1W$G&R z3w5=+h8vMzs_Rsvx?bI&ex;VH8~KdZ&1!|ZMct}yQ@5)-)Sc=s6;~_ODz#dzQESyY zwO%!;yVVADkGfagr+%&OSIz1H^&9n|dPqI29#M~~jq102^6GK*gnCjvrJhy^^^Dr2 zo>iOGbLx5Zg4&{fr+%;gpk7ojsXwZhRf~E>{Ym{1-Z3v0!>S8@kkJl4)iJquW)2HiFJxNd2Q?y^7p{MF; zdb*yWXX-QcEPa+fTmMYY*5~M->p3j+4(c*JSC{LMo~P&Q3SFts)eCf$uGTd=%nu;v z>8P&Nb-G?J)Qfb3UaZg87w9GWLVb~5s$=?MeTlwQU#2hDSLiGCGJTc)g}z!}qp#J! z)Ys`oeZ9Ux|4J{{H|m@8&3c8tMc=A#)3@t8^qu-H9oH-MD!p2-(QEZOyy8AJLEMjrzCxG5xrHLO-dW(ogGzenxN7&+5(kIsLqT zL2uE&)4$h$&@bwj^dI%hx<$XD|D^w{x9Y#>SM_Upn|@utq2JWo^Cg2S`b+(l{#x(V-{^1kclvw%cU@Ik zwkT8<`N;`KmseG(GwOpib(QCbN<#}nRkdoSzi9N_x%JicRl&N@v}xmvi1KsmYwN~W zR@H@~)9Rw3n)!7VMtmevwRmzU7%dIg)>egTjlIWI)=dos%drgAjj5kEFBBD1V$Y0L zvj6BvBvezL7B#-Irn1&Zu+?f}O=Vr0&6$;v(3E;3Zfvk>u8}(<$792_b;fbW2J4QM zUEq-xA7}CL23LgUE|^w1zb05$9}O8XRb<@|;quVLn!0Fk62eR@9GW+;)*lU*1-+() zgl9y`sT3pDjI62(&8;h`tgQ>rj|QvFxX9w+$2Sz&dSruDuPqPi;RpEhvo(AtLltnS`k$tE1k-^icoZHxVo&eCRAh|vbZ*4SDhs% zP4rJYc7$;RbDKnz*G8tM#Z4RSu$Vk<%4A27PT;g9IC8kPdD`4yjmUA;m37m@3qmzU z7RS}h9bFTwT714yNJ3+RHRbk};*jLuD5J4w&0I1njcDf^dq+%L_S?s|mLh$Vo&EG! zyA)<@`oSdRK9C*fI*1W%)>d0e=|>ck_D5^2Hg+>Ryt59*M?<03&Tm(hB;+(I4TmFE zo%y4o^05`saCOk=X{0GJrS;Xp;YMe7L>T>#uzjA77*iFVyTCq%9cx5diKoS#Su)*< zo>mu(rscz^^PW?tA1v2$C~$!06U*xd@Z?ptCEu15Q@ z$&t*|P;F&-eXz=|Wwy$27b>3_tg1Jvn3(AmQTCq{s;dYagD_F8n@h~nnWbnAR7x(b zkkQ#}ZET>-GH6a=bPSo}@Whesh_r^3W@x=cNYWB9wyH8RJy^yi#EvO82Di$Z`F4bv zx7HBDtx+V|dt#WuI}~Neu{Td;zzG}uMz-4(V{esFtBNtx2(x3bE*u@RxGq#XJv{k* zXXLnsNH}VAnu(U##Oii29KgBH#MRher`nx&lAW}>B|%gZM) z6xEPJ`poE>@~I)Cn`GQDXRIV6n`Uwu3`f&L{rF6n^T=N;0q>q?( z8K*8{Y0h27R#{Ek7S%R)X^V5FXYSbAl5IxQ76pyLye-Bt#gWKbD|dFz?C^}5XlNe2 z*D6|lWmS0z)2!-Xjd2E<=JbcE(AaQQI6BEbOj?xHbYt7iiAvk*(@@T;Hj*Y$ne-TG zOCM=Hxy`2Oc(Z*-$NqG#AK5)^Yun!8=-A-gijX6pQcN?B#QCo<)Ma& zH48)0+O~|hUSdlPn`sgHTWhwg(kRX(jESW^?OaW>4@u%uQuX2R6boHG-qTK4IY zt(kX3Pn}>)`#5HL1lWt`Ei_Sjt?pwU1ajZCYR(SaSk9Xio_2uss_n zWv1m!vMty)!F1T9AIf2D&OjWNtp{u~%5coqS*GksvD>Q03_B`xTti(nXwMZ&TSM0U zggLs54>B_e&mS?Z%Bn4in3f(xi>8n5GM8%>YQ;n?0$ zym1t>qb#m23!8VZrR>mlcx!Sgk@i%nv?N$tF}5ODS<^O#v_?q>F|ySf)7m>)6SXfZ z&WLGDRjNY%%7!W2ky)cq>-Mq6DPksT-z<)^=D;%2r*CP0Kq}FZRXc@gTyjHl2{d=- zR0&OphU+7>(g5zb$sx15OX3`IsxgT)jNHSa5y@4<7z~dcQI-}iGJ|$%a??>Mmwq!3 zZ9%(=(qgPZq%Ce*y_sBEOgk$(qFypyJHD#EwxYGt{AQ$c{#PnxYc(*Y2*zZfwOZSv zWMxfaCMpdRqS+(EsmW&Bmk><2( zQe`cV7UmicP^?EH)>8~4)OPz}93&hpXU-C=YMp^j3N8p)x02EhMoUVZ@jzr`T9kQ{ z(iRm8*6^&uxXM^P!XM*buhvnZ6}E_e`_rP zgDk~1Z<9=I+!x8%YgPuzdLA=v+QdnY%Yh?^jd3R{QPQ=zyEX@cvo=8Q@r zrD>u0)u9?QN39{6H(1?jv7pkJ>zw-5MA@_Sm#=v2h>N zy196)d9U6Y;R;$$EX?|K+&HI|yER~x*a{il%+|&R8#6!JVU+na&o&FX?WVR*tu@NAD{)L+Gwhrx!Jte|9kvUCWwlI$Ob4xp%SNm`h&CpZlXzHKNx(F27i~<6jXf5IE6ZhCGbvOZ=FVB- z##HfS+PoW(pmdm;`iRktksvptb)&hC80x?IhB!w3cClwUqnMMA7&$$h7DsxS;zl1k!hIOIH85ja4-{FPUe7YM zX^mmBBR?3JS&A%n2W94MY%C51t-F1*h1x3IoYPxIGF_F@yMokS*bybSSaL*jSK}rm zJ=osf6_b7lDYPR&3AVR)#hhg|kC_KTj_v2A|C(att+F;E*XOpL#fZ}uGd*lfFN{o> zlXQo)i)(IZEv^}~dr`WPBi1Zgy0KmScCk+5bfeZfGWKDj%h+#TWu$nm6WNgc6OoyJ zxxJWcJuf!w%!szan!~i&fyQ&%JI-fg1}i&>Xzg%Dx?BQ{xs*T1?H)gbh!t^WTSRAa zXI~kvv183bx?{(4!^%%UJPNX&8d_->Hwcz4<$m8EtYk88+@A9zmbKx`aCAW^YV10X z2L)zyG+36NOYR}ZFXKTB|;^(&a6*^>g;RX))S(yPn{k+58cZBul4>o~+l zjo{ST@*XQdMc19y4?7Y&b=iq_jW2oI&#fps%V7j zNvj1rGHw4Eky>}g+M?Pws$(0^C+wWH#ikvwExLn4re~V`a&fkr!&y`A4ehh#wn#f( zhK+Vr@v}i?oy@(bMCuqc%*HY21LjXzQbI>KYEB{Dv66~W88Y{fzA3jThEZGCx}rKP ztfOJ#G)Fs337KYoo{HP&vT^@p{|F?9@pA{xaMpTOm@U&T*8D|6E#EK@tqF-&FH(l%1LH(JAlE4p=@aK*QtxOTkt1DrEMW|V!-q#F{;W`6rK+NOhT z*7?$Hk!WzB-jdz#x^dvej{m&B@2d2uDT!7}YguTHb8r6p+fK5Kliv(OrwA@i%4(I4{IYHulgU!PfIu0+XEEjO&^;LolAU8wIv6 zOlBZdmuc2yUy;mtpxvT&tT_>}J9v7md4n^9E3LedWY&7y<;FNBKWbOX%R1)u*obmp z3Czg)g-35$Pk@p~5UwYcE;^m2Qw@X;2Jve<9& z&n=Eve7?n3So}+iS6IBt;tdu*WbsoLZ?U+=;%ycuE&jmbFD(9t#RasZ{OxD)fff(6 z_-KpmHr>~bW_|tty&Y#NUO=f0l`z3!u6d<0e^wl~P@YUG-ZnSG)8yBS3Lb+K_qsA4 z5ZLe4P2p?b^`Youe<&(H{m2jgMq)gxNo7yv!AP(+)LI#Q@gQevT@}Aej<2sVD#5&J z=1c6@U_|bqm@Cxri=gT*alF^Kpgv+7Q(ZhHR=s7*%*tpTui4G0S;SieO3liV$6?Y4 zO5H5ltPX#)GRzy0i`5#5n^D87BeYuixQ4kQ<8ITO^{5AOrd5SP5%qM=^iZ^#ALfkr zi{*zdrJm23UR6sqnb-P1=X98e`ZUMN6pdC#8!Pp>9b;6HQs3vC8RTX+95sKao>F!$ zX5$)IX)$LGZ-Mh(6R%&g+G5U}%5d47dDM|&UB#R^Ob+X7$yrd|HI6FQPR!xwo%wSN zb5={tDGSZ7tf@2JDhxF!RxixKt|qM1WId;nCZ(HItKaH5%qAD8%B(rok&3eC)Ylks zopXX^@|N9!Ic2rHkInCx{d1UB%j{E)%9$5oR$ezxor$b873N zHL~mWoQ3uQW$=`1=l^4zK5pvdaizzOFka0k3%xl0{|i*tE}R>!vyW?MrSk;u98Uve_5+zo-WMw;Amnu()*ltwz}EGvogkmGu8+Q5yN?J0)*e&wp{g zJ1?~mFN}NQ-ncLBj|buv@kqQO9*Z}|;kMWy{KKE0rgYHKOrWL0cc*96u?*2LB{u8FT{UXxhUvL?AE#WKvowVt)!wZ66f zwSl#fwXwC0YvXI1*Cy7stWB;>u}HIUooAhQoo}6gU0_{gU2I+By7;>0b%}K?>yqnI zEa5C%?^*9%?_2L*A6Oq*A6wtJKEA$rePVsf`sDf)3p@*(JWbvvUz5Kn&=hHkH8nQH zo0^*vO)X8yrWDIR3-9*a?Y-M~xBu?I-I2RvcQ@W0zq|SF#N91-C+|+NIJ9tsXM=Zx sZ-akBU_)d>Y(wLQ_=e^U%E!8Qs;@8YQ4~k`&9Emv#Ev2I-~apn01DIzTL1t6 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/locals.py b/venv/Lib/site-packages/pygame/locals.py new file mode 100644 index 0000000..66e6c24 --- /dev/null +++ b/venv/Lib/site-packages/pygame/locals.py @@ -0,0 +1,576 @@ +# pygame - Python Game Library +# Copyright (C) 2000-2003 Pete Shinners +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Library General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Library General Public License for more details. +# +# You should have received a copy of the GNU Library General Public +# License along with this library; if not, write to the Free +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# Pete Shinners +# pete@shinners.org + + +"""Set of functions from PyGame that are handy to have in +the local namespace for your module""" + +from pygame.constants import * # pylint: disable=wildcard-import; lgtm[py/polluting-import] +from pygame.rect import Rect +from pygame import color + +Color = color.Color + + +__all__ = [ + "Rect", + "Color", + "ACTIVEEVENT", + "ANYFORMAT", + "APPACTIVE", + "APPFOCUSMOUSE", + "APPINPUTFOCUS", + "ASYNCBLIT", + "AUDIODEVICEADDED", + "AUDIODEVICEREMOVED", + "AUDIO_ALLOW_ANY_CHANGE", + "AUDIO_ALLOW_CHANNELS_CHANGE", + "AUDIO_ALLOW_FORMAT_CHANGE", + "AUDIO_ALLOW_FREQUENCY_CHANGE", + "AUDIO_S16", + "AUDIO_S16LSB", + "AUDIO_S16MSB", + "AUDIO_S16SYS", + "AUDIO_S8", + "AUDIO_U16", + "AUDIO_U16LSB", + "AUDIO_U16MSB", + "AUDIO_U16SYS", + "AUDIO_U8", + "BIG_ENDIAN", + "BLENDMODE_ADD", + "BLENDMODE_BLEND", + "BLENDMODE_MOD", + "BLENDMODE_NONE", + "BLEND_ADD", + "BLEND_MAX", + "BLEND_MIN", + "BLEND_MULT", + "BLEND_PREMULTIPLIED", + "BLEND_ALPHA_SDL2", + "BLEND_RGBA_ADD", + "BLEND_RGBA_MAX", + "BLEND_RGBA_MIN", + "BLEND_RGBA_MULT", + "BLEND_RGBA_SUB", + "BLEND_RGB_ADD", + "BLEND_RGB_MAX", + "BLEND_RGB_MIN", + "BLEND_RGB_MULT", + "BLEND_RGB_SUB", + "BLEND_SUB", + "BUTTON_LEFT", + "BUTTON_MIDDLE", + "BUTTON_RIGHT", + "BUTTON_WHEELDOWN", + "BUTTON_WHEELUP", + "BUTTON_X1", + "BUTTON_X2", + "CONTROLLERAXISMOTION", + "CONTROLLERBUTTONDOWN", + "CONTROLLERBUTTONUP", + "CONTROLLERDEVICEADDED", + "CONTROLLERDEVICEREMAPPED", + "CONTROLLERDEVICEREMOVED", + "CONTROLLERTOUCHPADDOWN", + "CONTROLLERTOUCHPADMOTION", + "CONTROLLERTOUCHPADUP", + "CONTROLLER_AXIS_INVALID", + "CONTROLLER_AXIS_LEFTX", + "CONTROLLER_AXIS_LEFTY", + "CONTROLLER_AXIS_MAX", + "CONTROLLER_AXIS_RIGHTX", + "CONTROLLER_AXIS_RIGHTY", + "CONTROLLER_AXIS_TRIGGERLEFT", + "CONTROLLER_AXIS_TRIGGERRIGHT", + "CONTROLLER_BUTTON_A", + "CONTROLLER_BUTTON_B", + "CONTROLLER_BUTTON_BACK", + "CONTROLLER_BUTTON_DPAD_DOWN", + "CONTROLLER_BUTTON_DPAD_LEFT", + "CONTROLLER_BUTTON_DPAD_RIGHT", + "CONTROLLER_BUTTON_DPAD_UP", + "CONTROLLER_BUTTON_GUIDE", + "CONTROLLER_BUTTON_INVALID", + "CONTROLLER_BUTTON_LEFTSHOULDER", + "CONTROLLER_BUTTON_LEFTSTICK", + "CONTROLLER_BUTTON_MAX", + "CONTROLLER_BUTTON_RIGHTSHOULDER", + "CONTROLLER_BUTTON_RIGHTSTICK", + "CONTROLLER_BUTTON_START", + "CONTROLLER_BUTTON_X", + "CONTROLLER_BUTTON_Y", + "DOUBLEBUF", + "DROPBEGIN", + "DROPCOMPLETE", + "DROPFILE", + "DROPTEXT", + "FINGERDOWN", + "FINGERMOTION", + "FINGERUP", + "FULLSCREEN", + "GL_ACCELERATED_VISUAL", + "GL_ACCUM_ALPHA_SIZE", + "GL_ACCUM_BLUE_SIZE", + "GL_ACCUM_GREEN_SIZE", + "GL_ACCUM_RED_SIZE", + "GL_ALPHA_SIZE", + "GL_BLUE_SIZE", + "GL_BUFFER_SIZE", + "GL_CONTEXT_DEBUG_FLAG", + "GL_CONTEXT_FLAGS", + "GL_CONTEXT_FORWARD_COMPATIBLE_FLAG", + "GL_CONTEXT_MAJOR_VERSION", + "GL_CONTEXT_MINOR_VERSION", + "GL_CONTEXT_PROFILE_COMPATIBILITY", + "GL_CONTEXT_PROFILE_CORE", + "GL_CONTEXT_PROFILE_ES", + "GL_CONTEXT_PROFILE_MASK", + "GL_CONTEXT_RELEASE_BEHAVIOR", + "GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH", + "GL_CONTEXT_RELEASE_BEHAVIOR_NONE", + "GL_CONTEXT_RESET_ISOLATION_FLAG", + "GL_CONTEXT_ROBUST_ACCESS_FLAG", + "GL_DEPTH_SIZE", + "GL_DOUBLEBUFFER", + "GL_FRAMEBUFFER_SRGB_CAPABLE", + "GL_GREEN_SIZE", + "GL_MULTISAMPLEBUFFERS", + "GL_MULTISAMPLESAMPLES", + "GL_RED_SIZE", + "GL_SHARE_WITH_CURRENT_CONTEXT", + "GL_STENCIL_SIZE", + "GL_STEREO", + "GL_SWAP_CONTROL", + "HAT_CENTERED", + "HAT_DOWN", + "HAT_LEFT", + "HAT_LEFTDOWN", + "HAT_LEFTUP", + "HAT_RIGHT", + "HAT_RIGHTDOWN", + "HAT_RIGHTUP", + "HAT_UP", + "HIDDEN", + "HWACCEL", + "HWPALETTE", + "HWSURFACE", + "JOYAXISMOTION", + "JOYBALLMOTION", + "JOYBUTTONDOWN", + "JOYBUTTONUP", + "JOYHATMOTION", + "JOYDEVICEADDED", + "JOYDEVICEREMOVED", + "KEYDOWN", + "KEYUP", + "KMOD_ALT", + "KMOD_CAPS", + "KMOD_CTRL", + "KMOD_GUI", + "KMOD_LALT", + "KMOD_LCTRL", + "KMOD_LGUI", + "KMOD_LMETA", + "KMOD_LSHIFT", + "KMOD_META", + "KMOD_MODE", + "KMOD_NONE", + "KMOD_NUM", + "KMOD_RALT", + "KMOD_RCTRL", + "KMOD_RGUI", + "KMOD_RMETA", + "KMOD_RSHIFT", + "KMOD_SHIFT", + "KSCAN_0", + "KSCAN_1", + "KSCAN_2", + "KSCAN_3", + "KSCAN_4", + "KSCAN_5", + "KSCAN_6", + "KSCAN_7", + "KSCAN_8", + "KSCAN_9", + "KSCAN_A", + "KSCAN_APOSTROPHE", + "KSCAN_B", + "KSCAN_BACKSLASH", + "KSCAN_BACKSPACE", + "KSCAN_BREAK", + "KSCAN_C", + "KSCAN_CAPSLOCK", + "KSCAN_CLEAR", + "KSCAN_COMMA", + "KSCAN_CURRENCYSUBUNIT", + "KSCAN_CURRENCYUNIT", + "KSCAN_D", + "KSCAN_DELETE", + "KSCAN_DOWN", + "KSCAN_E", + "KSCAN_END", + "KSCAN_EQUALS", + "KSCAN_ESCAPE", + "KSCAN_EURO", + "KSCAN_F", + "KSCAN_F1", + "KSCAN_F10", + "KSCAN_F11", + "KSCAN_F12", + "KSCAN_F13", + "KSCAN_F14", + "KSCAN_F15", + "KSCAN_F2", + "KSCAN_F3", + "KSCAN_F4", + "KSCAN_F5", + "KSCAN_F6", + "KSCAN_F7", + "KSCAN_F8", + "KSCAN_F9", + "KSCAN_G", + "KSCAN_GRAVE", + "KSCAN_H", + "KSCAN_HELP", + "KSCAN_HOME", + "KSCAN_I", + "KSCAN_INSERT", + "KSCAN_INTERNATIONAL1", + "KSCAN_INTERNATIONAL2", + "KSCAN_INTERNATIONAL3", + "KSCAN_INTERNATIONAL4", + "KSCAN_INTERNATIONAL5", + "KSCAN_INTERNATIONAL6", + "KSCAN_INTERNATIONAL7", + "KSCAN_INTERNATIONAL8", + "KSCAN_INTERNATIONAL9", + "KSCAN_J", + "KSCAN_K", + "KSCAN_KP0", + "KSCAN_KP1", + "KSCAN_KP2", + "KSCAN_KP3", + "KSCAN_KP4", + "KSCAN_KP5", + "KSCAN_KP6", + "KSCAN_KP7", + "KSCAN_KP8", + "KSCAN_KP9", + "KSCAN_KP_0", + "KSCAN_KP_1", + "KSCAN_KP_2", + "KSCAN_KP_3", + "KSCAN_KP_4", + "KSCAN_KP_5", + "KSCAN_KP_6", + "KSCAN_KP_7", + "KSCAN_KP_8", + "KSCAN_KP_9", + "KSCAN_KP_DIVIDE", + "KSCAN_KP_ENTER", + "KSCAN_KP_EQUALS", + "KSCAN_KP_MINUS", + "KSCAN_KP_MULTIPLY", + "KSCAN_KP_PERIOD", + "KSCAN_KP_PLUS", + "KSCAN_L", + "KSCAN_LALT", + "KSCAN_LANG1", + "KSCAN_LANG2", + "KSCAN_LANG3", + "KSCAN_LANG4", + "KSCAN_LANG5", + "KSCAN_LANG6", + "KSCAN_LANG7", + "KSCAN_LANG8", + "KSCAN_LANG9", + "KSCAN_LCTRL", + "KSCAN_LEFT", + "KSCAN_LEFTBRACKET", + "KSCAN_LGUI", + "KSCAN_LMETA", + "KSCAN_LSHIFT", + "KSCAN_LSUPER", + "KSCAN_M", + "KSCAN_MENU", + "KSCAN_MINUS", + "KSCAN_MODE", + "KSCAN_N", + "KSCAN_NONUSBACKSLASH", + "KSCAN_NONUSHASH", + "KSCAN_NUMLOCK", + "KSCAN_NUMLOCKCLEAR", + "KSCAN_O", + "KSCAN_P", + "KSCAN_PAGEDOWN", + "KSCAN_PAGEUP", + "KSCAN_PAUSE", + "KSCAN_PERIOD", + "KSCAN_POWER", + "KSCAN_PRINT", + "KSCAN_PRINTSCREEN", + "KSCAN_Q", + "KSCAN_R", + "KSCAN_RALT", + "KSCAN_RCTRL", + "KSCAN_RETURN", + "KSCAN_RGUI", + "KSCAN_RIGHT", + "KSCAN_RIGHTBRACKET", + "KSCAN_RMETA", + "KSCAN_RSHIFT", + "KSCAN_RSUPER", + "KSCAN_S", + "KSCAN_SCROLLLOCK", + "KSCAN_SCROLLOCK", + "KSCAN_SEMICOLON", + "KSCAN_SLASH", + "KSCAN_SPACE", + "KSCAN_SYSREQ", + "KSCAN_T", + "KSCAN_TAB", + "KSCAN_U", + "KSCAN_UNKNOWN", + "KSCAN_UP", + "KSCAN_V", + "KSCAN_W", + "KSCAN_X", + "KSCAN_Y", + "KSCAN_Z", + "K_0", + "K_1", + "K_2", + "K_3", + "K_4", + "K_5", + "K_6", + "K_7", + "K_8", + "K_9", + "K_AC_BACK", + "K_AMPERSAND", + "K_ASTERISK", + "K_AT", + "K_BACKQUOTE", + "K_BACKSLASH", + "K_BACKSPACE", + "K_BREAK", + "K_CAPSLOCK", + "K_CARET", + "K_CLEAR", + "K_COLON", + "K_COMMA", + "K_CURRENCYSUBUNIT", + "K_CURRENCYUNIT", + "K_DELETE", + "K_DOLLAR", + "K_DOWN", + "K_END", + "K_EQUALS", + "K_ESCAPE", + "K_EURO", + "K_EXCLAIM", + "K_F1", + "K_F10", + "K_F11", + "K_F12", + "K_F13", + "K_F14", + "K_F15", + "K_F2", + "K_F3", + "K_F4", + "K_F5", + "K_F6", + "K_F7", + "K_F8", + "K_F9", + "K_GREATER", + "K_HASH", + "K_HELP", + "K_HOME", + "K_INSERT", + "K_KP0", + "K_KP1", + "K_KP2", + "K_KP3", + "K_KP4", + "K_KP5", + "K_KP6", + "K_KP7", + "K_KP8", + "K_KP9", + "K_KP_0", + "K_KP_1", + "K_KP_2", + "K_KP_3", + "K_KP_4", + "K_KP_5", + "K_KP_6", + "K_KP_7", + "K_KP_8", + "K_KP_9", + "K_KP_DIVIDE", + "K_KP_ENTER", + "K_KP_EQUALS", + "K_KP_MINUS", + "K_KP_MULTIPLY", + "K_KP_PERIOD", + "K_KP_PLUS", + "K_LALT", + "K_LCTRL", + "K_LEFT", + "K_LEFTBRACKET", + "K_LEFTPAREN", + "K_LESS", + "K_LGUI", + "K_LMETA", + "K_LSHIFT", + "K_LSUPER", + "K_MENU", + "K_MINUS", + "K_MODE", + "K_NUMLOCK", + "K_NUMLOCKCLEAR", + "K_PAGEDOWN", + "K_PAGEUP", + "K_PAUSE", + "K_PERCENT", + "K_PERIOD", + "K_PLUS", + "K_POWER", + "K_PRINT", + "K_PRINTSCREEN", + "K_QUESTION", + "K_QUOTE", + "K_QUOTEDBL", + "K_RALT", + "K_RCTRL", + "K_RETURN", + "K_RGUI", + "K_RIGHT", + "K_RIGHTBRACKET", + "K_RIGHTPAREN", + "K_RMETA", + "K_RSHIFT", + "K_RSUPER", + "K_SCROLLLOCK", + "K_SCROLLOCK", + "K_SEMICOLON", + "K_SLASH", + "K_SPACE", + "K_SYSREQ", + "K_TAB", + "K_UNDERSCORE", + "K_UNKNOWN", + "K_UP", + "K_a", + "K_b", + "K_c", + "K_d", + "K_e", + "K_f", + "K_g", + "K_h", + "K_i", + "K_j", + "K_k", + "K_l", + "K_m", + "K_n", + "K_o", + "K_p", + "K_q", + "K_r", + "K_s", + "K_t", + "K_u", + "K_v", + "K_w", + "K_x", + "K_y", + "K_z", + "LIL_ENDIAN", + "MIDIIN", + "MIDIOUT", + "MOUSEBUTTONDOWN", + "MOUSEBUTTONUP", + "MOUSEMOTION", + "MOUSEWHEEL", + "MULTIGESTURE", + "NOEVENT", + "NOFRAME", + "NUMEVENTS", + "OPENGL", + "OPENGLBLIT", + "PREALLOC", + "QUIT", + "RESIZABLE", + "RLEACCEL", + "RLEACCELOK", + "SCALED", + "SCRAP_BMP", + "SCRAP_CLIPBOARD", + "SCRAP_PBM", + "SCRAP_PPM", + "SCRAP_SELECTION", + "SCRAP_TEXT", + "SHOWN", + "SRCALPHA", + "SRCCOLORKEY", + "SWSURFACE", + "SYSTEM_CURSOR_ARROW", + "SYSTEM_CURSOR_CROSSHAIR", + "SYSTEM_CURSOR_HAND", + "SYSTEM_CURSOR_IBEAM", + "SYSTEM_CURSOR_NO", + "SYSTEM_CURSOR_SIZEALL", + "SYSTEM_CURSOR_SIZENESW", + "SYSTEM_CURSOR_SIZENS", + "SYSTEM_CURSOR_SIZENWSE", + "SYSTEM_CURSOR_SIZEWE", + "SYSTEM_CURSOR_WAIT", + "SYSTEM_CURSOR_WAITARROW", + "SYSWMEVENT", + "TEXTEDITING", + "TEXTINPUT", + "TIMER_RESOLUTION", + "USEREVENT", + "USEREVENT_DROPFILE", + "VIDEOEXPOSE", + "VIDEORESIZE", + "WINDOWSHOWN", + "WINDOWHIDDEN", + "WINDOWEXPOSED", + "WINDOWMOVED", + "WINDOWRESIZED", + "WINDOWSIZECHANGED", + "WINDOWMINIMIZED", + "WINDOWMAXIMIZED", + "WINDOWRESTORED", + "WINDOWENTER", + "WINDOWLEAVE", + "WINDOWFOCUSGAINED", + "WINDOWFOCUSLOST", + "WINDOWCLOSE", + "WINDOWTAKEFOCUS", + "WINDOWHITTEST", +] diff --git a/venv/Lib/site-packages/pygame/macosx.py b/venv/Lib/site-packages/pygame/macosx.py new file mode 100644 index 0000000..fca8e21 --- /dev/null +++ b/venv/Lib/site-packages/pygame/macosx.py @@ -0,0 +1,15 @@ +import platform +import os +import sys +from pygame.pkgdata import getResource +from pygame import sdlmain_osx + +__all__ = ["Video_AutoInit"] + + +def Video_AutoInit(): + """Called from the base.c just before display module is initialized.""" + if "Darwin" in platform.platform(): + if (os.getcwd() == "/") and len(sys.argv) > 1: + os.chdir(os.path.dirname(sys.argv[0])) + return True diff --git a/venv/Lib/site-packages/pygame/mask.cp39-win_amd64.pyd b/venv/Lib/site-packages/pygame/mask.cp39-win_amd64.pyd new file mode 100644 index 0000000000000000000000000000000000000000..fb6d539157dc2c40b9f85c2f6fc4566e03ab059b GIT binary patch literal 56832 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/mask.pyi b/venv/Lib/site-packages/pygame/mask.pyi new file mode 100644 index 0000000..726d3bf --- /dev/null +++ b/venv/Lib/site-packages/pygame/mask.pyi @@ -0,0 +1,58 @@ +from typing import Any, List, Optional, Sequence, Tuple, TypeVar, Union + +from pygame.rect import Rect +from pygame.surface import Surface + +from ._common import _ColorValue, _Coordinate, _RectValue + +_Offset = TypeVar("_Offset", Tuple[int, int], Sequence[int]) + +def from_surface(surface: Surface, threshold: int = 127) -> Mask: ... +def from_threshold( + surface: Surface, + color: _ColorValue, + threshold: _ColorValue = (0, 0, 0, 255), + other_surface: Optional[Surface] = None, + palette_colors: int = 1, +) -> Mask: ... + +class Mask: + def __init__(self, size: _Coordinate, fill: bool = False) -> None: ... + def copy(self) -> Mask: ... + def get_size(self) -> Tuple[int, int]: ... + def get_rect(self, **kwargs: Any) -> Rect: ... # Dict type needs to be completed + def get_at(self, pos: _Coordinate) -> int: ... + def set_at(self, pos: _Coordinate, value: int = 1) -> None: ... + def overlap(self, other: Mask, offset: _Offset) -> Union[Tuple[int, int], None]: ... + def overlap_area(self, other: Mask, offset: _Coordinate) -> int: ... + def overlap_mask(self, other: Mask, offset: _Coordinate) -> Mask: ... + def fill(self) -> None: ... + def clear(self) -> None: ... + def invert(self) -> None: ... + def scale(self, size: _Coordinate) -> Mask: ... + def draw(self, other: Mask, offset: _Coordinate) -> None: ... + def erase(self, other: Mask, offset: _Coordinate) -> None: ... + def count(self) -> int: ... + def centroid(self) -> Tuple[int, int]: ... + def angle(self) -> float: ... + def outline(self, every: int = 1) -> List[Tuple[int, int]]: ... + def convolve( + self, + other: Mask, + output: Optional[Mask] = None, + offset: _Coordinate = (0, 0), + ) -> Mask: ... + def connected_component( + self, pos: Union[List[int], Tuple[int, int]] = ... + ) -> Mask: ... + def connected_components(self, minimum: int = 0) -> List[Mask]: ... + def get_bounding_rects(self) -> Rect: ... + def to_surface( + self, + surface: Optional[Surface] = None, + setsurface: Optional[Surface] = None, + unsetsurface: Optional[Surface] = None, + setcolor: _ColorValue = (255, 255, 255, 255), + unsetcolor: _ColorValue = (0, 0, 0, 255), + dest: Union[_RectValue, _Coordinate] = (0, 0), + ) -> Surface: ... diff --git a/venv/Lib/site-packages/pygame/math.cp39-win_amd64.pyd b/venv/Lib/site-packages/pygame/math.cp39-win_amd64.pyd new file mode 100644 index 0000000000000000000000000000000000000000..2ea3471e8066ff8d14ae13b802a5f56c25c8e48f GIT binary patch literal 67584 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 Vector2: ... + def __radd__( + self, other: Union[float, Vector2, _VectorElementwiseProxy2] + ) -> Vector2: ... + def __sub__( + self, other: Union[float, Vector2, _VectorElementwiseProxy2] + ) -> Vector2: ... + def __rsub__( + self, other: Union[float, Vector2, _VectorElementwiseProxy2] + ) -> Vector2: ... + def __mul__( + self, other: Union[float, Vector2, _VectorElementwiseProxy2] + ) -> Vector2: ... + def __rmul__( + self, other: Union[float, Vector2, _VectorElementwiseProxy2] + ) -> Vector2: ... + def __truediv__( + self, other: Union[float, Vector2, _VectorElementwiseProxy2] + ) -> Vector2: ... + def __rtruediv__( + self, other: Union[float, Vector2, _VectorElementwiseProxy2] + ) -> Vector2: ... + def __floordiv__( + self, other: Union[float, Vector2, _VectorElementwiseProxy2] + ) -> Vector2: ... + def __rfloordiv__( + self, other: Union[float, Vector2, _VectorElementwiseProxy2] + ) -> Vector2: ... + def __mod__( + self, other: Union[float, Vector2, _VectorElementwiseProxy2] + ) -> Vector2: ... + def __rmod__( + self, other: Union[float, Vector2, _VectorElementwiseProxy2] + ) -> Vector2: ... + def __pow__( + self, power: Union[float, Vector2, _VectorElementwiseProxy2] + ) -> Vector2: ... + def __rpow__( + self, power: Union[float, Vector2, _VectorElementwiseProxy2] + ) -> Vector2: ... + +class _VectorElementwiseProxy3: + def __add__( + self, other: Union[float, Vector3, _VectorElementwiseProxy3] + ) -> Vector3: ... + def __radd__( + self, other: Union[float, Vector3, _VectorElementwiseProxy3] + ) -> Vector3: ... + def __sub__( + self, other: Union[float, Vector3, _VectorElementwiseProxy3] + ) -> Vector3: ... + def __rsub__( + self, other: Union[float, Vector3, _VectorElementwiseProxy3] + ) -> Vector3: ... + def __mul__( + self, other: Union[float, Vector3, _VectorElementwiseProxy3] + ) -> Vector3: ... + def __rmul__( + self, other: Union[float, Vector3, _VectorElementwiseProxy3] + ) -> Vector3: ... + def __truediv__( + self, other: Union[float, Vector3, _VectorElementwiseProxy3] + ) -> Vector3: ... + def __rtruediv__( + self, other: Union[float, Vector3, _VectorElementwiseProxy3] + ) -> Vector3: ... + def __floordiv__( + self, other: Union[float, Vector3, _VectorElementwiseProxy3] + ) -> Vector3: ... + def __rfloordiv__( + self, other: Union[float, Vector3, _VectorElementwiseProxy3] + ) -> Vector3: ... + def __mod__( + self, other: Union[float, Vector3, _VectorElementwiseProxy3] + ) -> Vector3: ... + def __rmod__( + self, other: Union[float, Vector3, _VectorElementwiseProxy3] + ) -> Vector3: ... + def __pow__( + self, power: Union[float, Vector3, _VectorElementwiseProxy3] + ) -> Vector3: ... + def __rpow__( + self, power: Union[float, Vector3, _VectorElementwiseProxy3] + ) -> Vector3: ... + +class Vector2: + x: float + y: float + xx: Vector2 + xy: Vector2 + yx: Vector2 + yy: Vector2 + __hash__: None # type: ignore + @overload + def __init__( + self, + x: Union[float, Tuple[float, float], List[float], Vector2] = 0, + ) -> None: ... + @overload + def __init__(self, x: float, y: float) -> None: ... + def __setitem__(self, key: int, value: float) -> None: ... + @overload + def __getitem__(self, i: int) -> float: ... + @overload + def __getitem__(self, s: slice) -> List[float]: ... + def __add__(self, other: Vector2) -> Vector2: ... + def __sub__(self, other: Vector2) -> Vector2: ... + @overload + def __mul__(self, other: Vector2) -> float: ... + @overload + def __mul__(self, other: float) -> Vector2: ... + def __rmul__(self, other: float) -> Vector2: ... + def __truediv__(self, other: float) -> Vector2: ... + def __floordiv__(self, other: float) -> Vector2: ... + def __neg__(self) -> Vector2: ... + def __pos__(self) -> Vector2: ... + def __bool__(self) -> bool: ... + def __iadd__(self, other: Vector2) -> Vector2: ... + def __isub__(self, other: Vector2) -> Vector2: ... + @overload + def __imul__(self, other: Vector2) -> float: ... + @overload + def __imul__(self, other: float) -> Vector2: ... + def dot(self, other: Vector2) -> float: ... + def cross(self, other: Vector2) -> Vector2: ... + def magnitude(self) -> float: ... + def magnitude_squared(self) -> float: ... + def length(self) -> float: ... + def length_squared(self) -> float: ... + def normalize(self) -> Vector2: ... + def normalize_ip(self) -> None: ... + def is_normalized(self) -> bool: ... + def scale_to_length(self, value: float) -> None: ... + def reflect(self, other: Vector2) -> Vector2: ... + def reflect_ip(self, other: Vector2) -> None: ... + def distance_to(self, other: Union[Vector2, Sequence[float]]) -> float: ... + def distance_squared_to(self, other: Vector2) -> float: ... + def lerp(self, other: Vector2, value: float) -> Vector2: ... + def slerp(self, other: Vector2, value: float) -> Vector2: ... + def elementwise(self) -> _VectorElementwiseProxy2: ... + def rotate(self, angle: float) -> Vector2: ... + def rotate_rad(self, angle: float) -> Vector2: ... + def rotate_ip(self, angle: float) -> None: ... + def rotate_rad_ip(self, angle: float) -> None: ... + def rotate_ip_rad(self, angle: float) -> None: ... + def angle_to(self, other: Vector2) -> float: ... + def as_polar(self) -> Tuple[float, float]: ... + def from_polar( + self, polar_value: Union[List[float], Tuple[float, float]] + ) -> None: ... + def copy(self) -> Vector2: ... + def update( + self, + x: Union[float, Vector2, Tuple[float, float], List[float]] = 0, + y: float = 0, + ) -> None: ... + +class Vector3: + x: float + y: float + z: float + xx: Vector2 + xy: Vector2 + xz: Vector2 + yx: Vector2 + yy: Vector2 + yz: Vector2 + zx: Vector2 + zy: Vector2 + zz: Vector2 + xxx: Vector3 + xxy: Vector3 + xxz: Vector3 + xyx: Vector3 + xyy: Vector3 + xyz: Vector3 + xzx: Vector3 + xzy: Vector3 + xzz: Vector3 + yxx: Vector3 + yxy: Vector3 + yxz: Vector3 + yyx: Vector3 + yyy: Vector3 + yyz: Vector3 + yzx: Vector3 + yzy: Vector3 + yzz: Vector3 + zxx: Vector3 + zxy: Vector3 + zxz: Vector3 + zyx: Vector3 + zyy: Vector3 + zyz: Vector3 + zzx: Vector3 + zzy: Vector3 + zzz: Vector3 + __hash__: None # type: ignore + @overload + def __init__( + self, + xyz: Union[float, Tuple[float, float, float], List[float], Vector3] = 0, + ) -> None: ... + @overload + def __init__(self, x: float, y: float, z: float) -> None: ... + def __setitem__(self, key: int, value: float) -> None: ... + @overload + def __getitem__(self, i: int) -> float: ... + @overload + def __getitem__(self, s: slice) -> List[float]: ... + def __add__(self, other: Vector3) -> Vector3: ... + def __sub__(self, other: Vector3) -> Vector3: ... + @overload + def __mul__(self, other: Vector3) -> float: ... + @overload + def __mul__(self, other: float) -> Vector3: ... + def __rmul__(self, other: float) -> Vector3: ... + def __truediv__(self, other: float) -> Vector3: ... + def __floordiv__(self, other: float) -> Vector3: ... + def __neg__(self) -> Vector3: ... + def __pos__(self) -> Vector3: ... + def __bool__(self) -> bool: ... + def __iadd__(self, other: Vector3) -> Vector3: ... + def __isub__(self, other: Vector3) -> Vector3: ... + @overload + def __imul__(self, other: Vector3) -> float: ... + @overload + def __imul__(self, other: float) -> Vector3: ... + def dot(self, other: Vector3) -> float: ... + def cross(self, other: Vector3) -> Vector3: ... + def magnitude(self) -> float: ... + def magnitude_squared(self) -> float: ... + def length(self) -> float: ... + def length_squared(self) -> float: ... + def normalize(self) -> Vector3: ... + def normalize_ip(self) -> None: ... + def is_normalized(self) -> bool: ... + def scale_to_length(self, value: float) -> None: ... + def reflect(self, other: Vector3) -> Vector3: ... + def reflect_ip(self, other: Vector3) -> None: ... + def distance_to(self, other: Vector3) -> float: ... + def distance_squared_to(self, other: Vector3) -> float: ... + def lerp(self, other: Vector3, value: float) -> Vector3: ... + def slerp(self, other: Vector3, value: float) -> Vector3: ... + def elementwise(self) -> _VectorElementwiseProxy3: ... + def rotate(self, angle: float, axis: Vector3) -> Vector3: ... + def rotate_rad(self, angle: float, axis: Vector3) -> Vector3: ... + def rotate_ip(self, angle: float, axis: Vector3) -> None: ... + def rotate_rad_ip(self, angle: float, axis: Vector3) -> None: ... + def rotate_ip_rad(self, angle: float, axis: Vector3) -> None: ... + def rotate_x(self, angle: float) -> Vector3: ... + def rotate_x_rad(self, angle: float) -> Vector3: ... + def rotate_x_ip(self, angle: float) -> None: ... + def rotate_x_rad_ip(self, angle: float) -> None: ... + def rotate_x_ip_rad(self, angle: float) -> None: ... + def rotate_y(self, angle: float) -> Vector3: ... + def rotate_y_rad(self, angle: float) -> Vector3: ... + def rotate_y_ip(self, angle: float) -> None: ... + def rotate_y_rad_ip(self, angle: float) -> None: ... + def rotate_y_ip_rad(self, angle: float) -> None: ... + def rotate_z(self, angle: float) -> Vector3: ... + def rotate_z_rad(self, angle: float) -> Vector3: ... + def rotate_z_ip(self, angle: float) -> None: ... + def rotate_z_rad_ip(self, angle: float) -> None: ... + def rotate_z_ip_rad(self, angle: float) -> None: ... + def angle_to(self, other: Vector3) -> float: ... + def as_spherical(self) -> Tuple[float, float, float]: ... + def from_spherical(self, spherical: Tuple[float, float, float]) -> None: ... + def copy(self) -> Vector3: ... + @overload + def update( + self, + xyz: Union[float, Tuple[float, float, float], List[float], Vector3] = 0, + ) -> None: ... + @overload + def update(self, x: int, y: int, z: int) -> None: ... diff --git a/venv/Lib/site-packages/pygame/midi.py b/venv/Lib/site-packages/pygame/midi.py new file mode 100644 index 0000000..bcf8d6b --- /dev/null +++ b/venv/Lib/site-packages/pygame/midi.py @@ -0,0 +1,718 @@ +"""pygame.midi +pygame module for interacting with midi input and output. + +The midi module can send output to midi devices, and get input +from midi devices. It can also list midi devices on the system. + +Including real midi devices, and virtual ones. + +It uses the portmidi library. Is portable to which ever platforms +portmidi supports (currently windows, OSX, and linux). + +This uses pyportmidi for now, but may use its own bindings at some +point in the future. The pyportmidi bindings are included with pygame. + +New in pygame 1.9.0. +""" + +# TODO: finish writing tests. +# - likely as interactive tests... so you'd need to plug in +# a midi device. +# TODO: create a background thread version for input threads. +# - that can automatically inject input into the event queue +# once the input object is running. Like joysticks. + +import math +import atexit + +import pygame +import pygame.locals + +import pygame.pypm as _pypm + +# For backward compatibility. +MIDIIN = pygame.locals.MIDIIN +MIDIOUT = pygame.locals.MIDIOUT + +__all__ = [ + "Input", + "MIDIIN", + "MIDIOUT", + "MidiException", + "Output", + "get_count", + "get_default_input_id", + "get_default_output_id", + "get_device_info", + "init", + "midis2events", + "quit", + "get_init", + "time", + "frequency_to_midi", + "midi_to_frequency", + "midi_to_ansi_note", +] + +__theclasses__ = ["Input", "Output"] + + +def _module_init(state=None): + # this is a sneaky dodge to store module level state in a non-public + # function. Helps us dodge using globals. + if state is not None: + _module_init.value = state + return state + + try: + _module_init.value + except AttributeError: + return False + else: + return _module_init.value + + +def init(): + """initialize the midi module + pygame.midi.init(): return None + + Call the initialisation function before using the midi module. + + It is safe to call this more than once. + """ + if not _module_init(): + _pypm.Initialize() + _module_init(True) + atexit.register(quit) + + +def quit(): # pylint: disable=redefined-builtin + """uninitialize the midi module + pygame.midi.quit(): return None + + + Called automatically atexit if you don't call it. + + It is safe to call this function more than once. + """ + if _module_init(): + # TODO: find all Input and Output classes and close them first? + _pypm.Terminate() + _module_init(False) + + +def get_init(): + """returns True if the midi module is currently initialized + pygame.midi.get_init(): return bool + + Returns True if the pygame.midi module is currently initialized. + + New in pygame 1.9.5. + """ + return _module_init() + + +def _check_init(): + if not _module_init(): + raise RuntimeError("pygame.midi not initialised.") + + +def get_count(): + """gets the number of devices. + pygame.midi.get_count(): return num_devices + + + Device ids range from 0 to get_count() -1 + """ + _check_init() + return _pypm.CountDevices() + + +def get_default_input_id(): + """gets default input device number + pygame.midi.get_default_input_id(): return default_id + + + Return the default device ID or -1 if there are no devices. + The result can be passed to the Input()/Output() class. + + On the PC, the user can specify a default device by + setting an environment variable. For example, to use device #1. + + set PM_RECOMMENDED_INPUT_DEVICE=1 + + The user should first determine the available device ID by using + the supplied application "testin" or "testout". + + In general, the registry is a better place for this kind of info, + and with USB devices that can come and go, using integers is not + very reliable for device identification. Under Windows, if + PM_RECOMMENDED_OUTPUT_DEVICE (or PM_RECOMMENDED_INPUT_DEVICE) is + *NOT* found in the environment, then the default device is obtained + by looking for a string in the registry under: + HKEY_LOCAL_MACHINE/SOFTWARE/PortMidi/Recommended_Input_Device + and HKEY_LOCAL_MACHINE/SOFTWARE/PortMidi/Recommended_Output_Device + for a string. The number of the first device with a substring that + matches the string exactly is returned. For example, if the string + in the registry is "USB", and device 1 is named + "In USB MidiSport 1x1", then that will be the default + input because it contains the string "USB". + + In addition to the name, get_device_info() returns "interf", which + is the interface name. (The "interface" is the underlying software + system or API used by PortMidi to access devices. Examples are + MMSystem, DirectX (not implemented), ALSA, OSS (not implemented), etc.) + At present, the only Win32 interface is "MMSystem", the only Linux + interface is "ALSA", and the only Max OS X interface is "CoreMIDI". + To specify both the interface and the device name in the registry, + separate the two with a comma and a space, e.g.: + MMSystem, In USB MidiSport 1x1 + In this case, the string before the comma must be a substring of + the "interf" string, and the string after the space must be a + substring of the "name" name string in order to match the device. + + Note: in the current release, the default is simply the first device + (the input or output device with the lowest PmDeviceID). + """ + _check_init() + return _pypm.GetDefaultInputDeviceID() + + +def get_default_output_id(): + """gets default output device number + pygame.midi.get_default_output_id(): return default_id + + + Return the default device ID or -1 if there are no devices. + The result can be passed to the Input()/Output() class. + + On the PC, the user can specify a default device by + setting an environment variable. For example, to use device #1. + + set PM_RECOMMENDED_OUTPUT_DEVICE=1 + + The user should first determine the available device ID by using + the supplied application "testin" or "testout". + + In general, the registry is a better place for this kind of info, + and with USB devices that can come and go, using integers is not + very reliable for device identification. Under Windows, if + PM_RECOMMENDED_OUTPUT_DEVICE (or PM_RECOMMENDED_INPUT_DEVICE) is + *NOT* found in the environment, then the default device is obtained + by looking for a string in the registry under: + HKEY_LOCAL_MACHINE/SOFTWARE/PortMidi/Recommended_Input_Device + and HKEY_LOCAL_MACHINE/SOFTWARE/PortMidi/Recommended_Output_Device + for a string. The number of the first device with a substring that + matches the string exactly is returned. For example, if the string + in the registry is "USB", and device 1 is named + "In USB MidiSport 1x1", then that will be the default + input because it contains the string "USB". + + In addition to the name, get_device_info() returns "interf", which + is the interface name. (The "interface" is the underlying software + system or API used by PortMidi to access devices. Examples are + MMSystem, DirectX (not implemented), ALSA, OSS (not implemented), etc.) + At present, the only Win32 interface is "MMSystem", the only Linux + interface is "ALSA", and the only Max OS X interface is "CoreMIDI". + To specify both the interface and the device name in the registry, + separate the two with a comma and a space, e.g.: + MMSystem, In USB MidiSport 1x1 + In this case, the string before the comma must be a substring of + the "interf" string, and the string after the space must be a + substring of the "name" name string in order to match the device. + + Note: in the current release, the default is simply the first device + (the input or output device with the lowest PmDeviceID). + """ + _check_init() + return _pypm.GetDefaultOutputDeviceID() + + +def get_device_info(an_id): + """returns information about a midi device + pygame.midi.get_device_info(an_id): return (interf, name, + input, output, + opened) + + interf - a text string describing the device interface, eg 'ALSA'. + name - a text string for the name of the device, eg 'Midi Through Port-0' + input - 0, or 1 if the device is an input device. + output - 0, or 1 if the device is an output device. + opened - 0, or 1 if the device is opened. + + If the id is out of range, the function returns None. + """ + _check_init() + return _pypm.GetDeviceInfo(an_id) + + +class Input(object): + """Input is used to get midi input from midi devices. + Input(device_id) + Input(device_id, buffer_size) + + buffer_size - the number of input events to be buffered waiting to + be read using Input.read() + """ + + def __init__(self, device_id, buffer_size=4096): + """ + The buffer_size specifies the number of input events to be buffered + waiting to be read using Input.read(). + """ + _check_init() + + if device_id == -1: + raise MidiException( + "Device id is -1, not a valid output id. " + "-1 usually means there were no default " + "Output devices." + ) + + try: + result = get_device_info(device_id) + except TypeError: + raise TypeError("an integer is required") + except OverflowError: + raise OverflowError("long int too large to convert to int") + + # and now some nasty looking error checking, to provide nice error + # messages to the kind, lovely, midi using people of wherever. + if result: + _, _, is_input, is_output, _ = result + if is_input: + try: + self._input = _pypm.Input(device_id, buffer_size) + except TypeError: + raise TypeError("an integer is required") + self.device_id = device_id + + elif is_output: + raise MidiException( + "Device id given is not a valid" " input id, it is an output id." + ) + else: + raise MidiException("Device id given is not a valid input id.") + else: + raise MidiException("Device id invalid, out of range.") + + def _check_open(self): + if self._input is None: + raise MidiException("midi not open.") + + def close(self): + """closes a midi stream, flushing any pending buffers. + Input.close(): return None + + PortMidi attempts to close open streams when the application + exits -- this is particularly difficult under Windows. + """ + _check_init() + if self._input is not None: + self._input.Close() + self._input = None + + def read(self, num_events): + """reads num_events midi events from the buffer. + Input.read(num_events): return midi_event_list + + Reads from the Input buffer and gives back midi events. + [[[status,data1,data2,data3],timestamp], + [[status,data1,data2,data3],timestamp],...] + """ + _check_init() + self._check_open() + return self._input.Read(num_events) + + def poll(self): + """returns true if there's data, or false if not. + Input.poll(): return Bool + + raises a MidiException on error. + """ + _check_init() + self._check_open() + + result = self._input.Poll() + if result == _pypm.TRUE: + return True + + if result == _pypm.FALSE: + return False + + err_text = _pypm.GetErrorText(result) + raise MidiException((result, err_text)) + + +class Output(object): + """Output is used to send midi to an output device + Output(device_id) + Output(device_id, latency = 0) + Output(device_id, buffer_size = 4096) + Output(device_id, latency, buffer_size) + + The buffer_size specifies the number of output events to be + buffered waiting for output. (In some cases -- see below -- + PortMidi does not buffer output at all and merely passes data + to a lower-level API, in which case buffersize is ignored.) + + latency is the delay in milliseconds applied to timestamps to determine + when the output should actually occur. (If latency is < 0, 0 is + assumed.) + + If latency is zero, timestamps are ignored and all output is delivered + immediately. If latency is greater than zero, output is delayed until + the message timestamp plus the latency. (NOTE: time is measured + relative to the time source indicated by time_proc. Timestamps are + absolute, not relative delays or offsets.) In some cases, PortMidi + can obtain better timing than your application by passing timestamps + along to the device driver or hardware. Latency may also help you + to synchronize midi data to audio data by matching midi latency to + the audio buffer latency. + + """ + + def __init__(self, device_id, latency=0, buffer_size=256): + """Output(device_id) + Output(device_id, latency = 0) + Output(device_id, buffer_size = 4096) + Output(device_id, latency, buffer_size) + + The buffer_size specifies the number of output events to be + buffered waiting for output. (In some cases -- see below -- + PortMidi does not buffer output at all and merely passes data + to a lower-level API, in which case buffersize is ignored.) + + latency is the delay in milliseconds applied to timestamps to determine + when the output should actually occur. (If latency is < 0, 0 is + assumed.) + + If latency is zero, timestamps are ignored and all output is delivered + immediately. If latency is greater than zero, output is delayed until + the message timestamp plus the latency. (NOTE: time is measured + relative to the time source indicated by time_proc. Timestamps are + absolute, not relative delays or offsets.) In some cases, PortMidi + can obtain better timing than your application by passing timestamps + along to the device driver or hardware. Latency may also help you + to synchronize midi data to audio data by matching midi latency to + the audio buffer latency. + """ + + _check_init() + self._aborted = 0 + + if device_id == -1: + raise MidiException( + "Device id is -1, not a valid output id." + " -1 usually means there were no default " + "Output devices." + ) + + try: + result = get_device_info(device_id) + except TypeError: + raise TypeError("an integer is required") + except OverflowError: + raise OverflowError("long int too large to convert to int") + + # and now some nasty looking error checking, to provide nice error + # messages to the kind, lovely, midi using people of wherever. + if result: + _, _, is_input, is_output, _ = result + if is_output: + try: + self._output = _pypm.Output(device_id, latency, buffer_size) + except TypeError: + raise TypeError("an integer is required") + self.device_id = device_id + + elif is_input: + raise MidiException( + "Device id given is not a valid output " "id, it is an input id." + ) + else: + raise MidiException("Device id given is not a" " valid output id.") + else: + raise MidiException("Device id invalid, out of range.") + + def _check_open(self): + if self._output is None: + raise MidiException("midi not open.") + + if self._aborted: + raise MidiException("midi aborted.") + + def close(self): + """closes a midi stream, flushing any pending buffers. + Output.close(): return None + + PortMidi attempts to close open streams when the application + exits -- this is particularly difficult under Windows. + """ + _check_init() + if self._output is not None: + self._output.Close() + self._output = None + + def abort(self): + """terminates outgoing messages immediately + Output.abort(): return None + + The caller should immediately close the output port; + this call may result in transmission of a partial midi message. + There is no abort for Midi input because the user can simply + ignore messages in the buffer and close an input device at + any time. + """ + + _check_init() + if self._output: + self._output.Abort() + self._aborted = 1 + + def write(self, data): + """writes a list of midi data to the Output + Output.write(data) + + writes series of MIDI information in the form of a list: + write([[[status <,data1><,data2><,data3>],timestamp], + [[status <,data1><,data2><,data3>],timestamp],...]) + fields are optional + example: choose program change 1 at time 20000 and + send note 65 with velocity 100 500 ms later. + write([[[0xc0,0,0],20000],[[0x90,60,100],20500]]) + notes: + 1. timestamps will be ignored if latency = 0. + 2. To get a note to play immediately, send MIDI info with + timestamp read from function Time. + 3. understanding optional data fields: + write([[[0xc0,0,0],20000]]) is equivalent to + write([[[0xc0],20000]]) + + Can send up to 1024 elements in your data list, otherwise an + IndexError exception is raised. + """ + _check_init() + self._check_open() + + self._output.Write(data) + + def write_short(self, status, data1=0, data2=0): + """write_short(status <, data1><, data2>) + Output.write_short(status) + Output.write_short(status, data1 = 0, data2 = 0) + + output MIDI information of 3 bytes or less. + data fields are optional + status byte could be: + 0xc0 = program change + 0x90 = note on + etc. + data bytes are optional and assumed 0 if omitted + example: note 65 on with velocity 100 + write_short(0x90,65,100) + """ + _check_init() + self._check_open() + self._output.WriteShort(status, data1, data2) + + def write_sys_ex(self, when, msg): + """writes a timestamped system-exclusive midi message. + Output.write_sys_ex(when, msg) + + msg - can be a *list* or a *string* + when - a timestamp in miliseconds + example: + (assuming o is an onput MIDI stream) + o.write_sys_ex(0,'\\xF0\\x7D\\x10\\x11\\x12\\x13\\xF7') + is equivalent to + o.write_sys_ex(pygame.midi.time(), + [0xF0,0x7D,0x10,0x11,0x12,0x13,0xF7]) + """ + _check_init() + self._check_open() + self._output.WriteSysEx(when, msg) + + def note_on(self, note, velocity, channel=0): + """turns a midi note on. Note must be off. + Output.note_on(note, velocity, channel=0) + + note is an integer from 0 to 127 + velocity is an integer from 0 to 127 + channel is an integer from 0 to 15 + + Turn a note on in the output stream. The note must already + be off for this to work correctly. + """ + if not 0 <= channel <= 15: + raise ValueError("Channel not between 0 and 15.") + + self.write_short(0x90 + channel, note, velocity) + + def note_off(self, note, velocity=0, channel=0): + """turns a midi note off. Note must be on. + Output.note_off(note, velocity=0, channel=0) + + note is an integer from 0 to 127 + velocity is an integer from 0 to 127 (release velocity) + channel is an integer from 0 to 15 + + Turn a note off in the output stream. The note must already + be on for this to work correctly. + """ + if not 0 <= channel <= 15: + raise ValueError("Channel not between 0 and 15.") + + self.write_short(0x80 + channel, note, velocity) + + def set_instrument(self, instrument_id, channel=0): + """select an instrument for a channel, with a value between 0 and 127 + Output.set_instrument(instrument_id, channel=0) + + Also called "patch change" or "program change". + """ + if not 0 <= instrument_id <= 127: + raise ValueError(f"Undefined instrument id: {instrument_id}") + + if not 0 <= channel <= 15: + raise ValueError("Channel not between 0 and 15.") + + self.write_short(0xC0 + channel, instrument_id) + + def pitch_bend(self, value=0, channel=0): + """modify the pitch of a channel. + Output.pitch_bend(value=0, channel=0) + + Adjust the pitch of a channel. The value is a signed integer + from -8192 to +8191. For example, 0 means "no change", +4096 is + typically a semitone higher, and -8192 is 1 whole tone lower (though + the musical range corresponding to the pitch bend range can also be + changed in some synthesizers). + + If no value is given, the pitch bend is returned to "no change". + """ + if not 0 <= channel <= 15: + raise ValueError("Channel not between 0 and 15.") + + if not -8192 <= value <= 8191: + raise ValueError( + f"Pitch bend value must be between -8192 and +8191, not {value}." + ) + + # "The 14 bit value of the pitch bend is defined so that a value of + # 0x2000 is the center corresponding to the normal pitch of the note + # (no pitch change)." so value=0 should send 0x2000 + value = value + 0x2000 + lsb = value & 0x7F # keep least 7 bits + msb = value >> 7 + self.write_short(0xE0 + channel, lsb, msb) + + +# MIDI commands +# +# 0x80 Note Off (note_off) +# 0x90 Note On (note_on) +# 0xA0 Aftertouch +# 0xB0 Continuous controller +# 0xC0 Patch change (set_instrument?) +# 0xD0 Channel Pressure +# 0xE0 Pitch bend +# 0xF0 (non-musical commands) + + +def time(): + """returns the current time in ms of the PortMidi timer + pygame.midi.time(): return time + + The time is reset to 0, when the module is inited. + """ + _check_init() + return _pypm.Time() + + +def midis2events(midis, device_id): + """converts midi events to pygame events + pygame.midi.midis2events(midis, device_id): return [Event, ...] + + Takes a sequence of midi events and returns list of pygame events. + """ + evs = [] + for midi in midis: + ((status, data1, data2, data3), timestamp) = midi + + event = pygame.event.Event( + MIDIIN, + status=status, + data1=data1, + data2=data2, + data3=data3, + timestamp=timestamp, + vice_id=device_id, + ) + evs.append(event) + + return evs + + +class MidiException(Exception): + """exception that pygame.midi functions and classes can raise + MidiException(errno) + """ + + def __init__(self, value): + super(MidiException, self).__init__(value) + self.parameter = value + + def __str__(self): + return repr(self.parameter) + + +def frequency_to_midi(frequency): + """converts a frequency into a MIDI note. + + Rounds to the closest midi note. + + ::Examples:: + + >>> frequency_to_midi(27.5) + 21 + >>> frequency_to_midi(36.7) + 26 + >>> frequency_to_midi(4186.0) + 108 + """ + return int(round(69 + (12 * math.log(frequency / 440.0)) / math.log(2))) + + +def midi_to_frequency(midi_note): + """Converts a midi note to a frequency. + + ::Examples:: + + >>> midi_to_frequency(21) + 27.5 + >>> midi_to_frequency(26) + 36.7 + >>> midi_to_frequency(108) + 4186.0 + """ + return round(440.0 * 2 ** ((midi_note - 69) * (1.0 / 12.0)), 1) + + +def midi_to_ansi_note(midi_note): + """returns the Ansi Note name for a midi number. + + ::Examples:: + + >>> midi_to_ansi_note(21) + 'A0' + >>> midi_to_ansi_note(102) + 'F#7' + >>> midi_to_ansi_note(108) + 'C8' + """ + notes = ["A", "A#", "B", "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#"] + num_notes = 12 + note_name = notes[int(((midi_note - 21) % num_notes))] + note_number = (midi_note - 12) // num_notes + return f"{note_name}{note_number}" diff --git a/venv/Lib/site-packages/pygame/midi.pyi b/venv/Lib/site-packages/pygame/midi.pyi new file mode 100644 index 0000000..90cd4a6 --- /dev/null +++ b/venv/Lib/site-packages/pygame/midi.pyi @@ -0,0 +1,49 @@ +from typing import List, Sequence, Tuple, Union + +from pygame.event import Event + +MIDIIN: int +MIDIOUT: int + +class MidiException(Exception): + def __init__(self, errno: str) -> None: ... + +def init() -> None: ... +def quit() -> None: ... +def get_init() -> bool: ... +def get_count() -> int: ... +def get_default_input_id() -> int: ... +def get_default_output_id() -> int: ... +def get_device_info(an_id: int) -> Tuple[str, str, int, int, int]: ... +def midis2events( + midi_events: Sequence[Sequence[Union[Sequence[int], int]]], device_id: int +) -> List[Event]: ... +def time() -> int: ... +def frequency_to_midi(frequency: float) -> int: ... +def midi_to_frequency(midi_note: int) -> float: ... +def midi_to_ansi_note(midi_note: int) -> str: ... + +class Input: + device_id: int + def __init__(self, device_id: int, buffer_size: int = 4096) -> None: ... + def close(self) -> None: ... + def pool(self) -> bool: ... + def read(self, num_events: int) -> List[List[Union[List[int], int]]]: ... + +class Output: + device_id: int + def __init__( + self, + device_id: int, + latency: int = 0, + buffersize: int = 4096, + ) -> None: ... + def abort(self) -> None: ... + def close(self) -> None: ... + def note_off(self, note: int, velocity: int = 0, channel: int = 0) -> None: ... + def note_on(self, note: int, velocity: int = 0, channel: int = 0) -> None: ... + def set_instrument(self, instrument_id: int, channel: int = 0) -> None: ... + def pitch_bend(self, value: int = 0, channel: int = 0) -> None: ... + def write(self, data: List[List[Union[List[int], int]]]) -> None: ... + def write_short(self, status: int, data1: int = 0, data2: int = 0) -> None: ... + def write_sys_ex(self, msg: Union[List[int], str], when: int) -> None: ... diff --git a/venv/Lib/site-packages/pygame/mixer.cp39-win_amd64.pyd b/venv/Lib/site-packages/pygame/mixer.cp39-win_amd64.pyd new file mode 100644 index 0000000000000000000000000000000000000000..4c49c04fb361eb0cc64e6e714947769a33d998e7 GIT binary patch literal 37376 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 None: ... +def pre_init( + frequency: int = 44100, + size: int = -16, + channels: int = 2, + buffer: int = 512, + devicename: Optional[str] = None, + allowedchanges: int = 5, +) -> None: ... +def quit() -> None: ... +def get_init() -> Tuple[int, int, int]: ... +def stop() -> None: ... +def pause() -> None: ... +def unpause() -> None: ... +def fadeout(time: int) -> None: ... +def set_num_channels(count: int) -> None: ... +def get_num_channels() -> int: ... +def set_reserved(count: int) -> int: ... +def find_channel(force: bool = False) -> Channel: ... +def get_busy() -> bool: ... +def get_sdl_mixer_version(linked: bool = True) -> Tuple[int, int, int]: ... + +class Sound: + @overload + def __init__(self, file: _FileArg) -> None: ... + @overload + def __init__( + self, buffer: Any + ) -> None: ... # Buffer protocol is still not implemented in typing + @overload + def __init__( + self, array: numpy.ndarray + ) -> None: ... # Buffer protocol is still not implemented in typing + def play( + self, + loops: int = 0, + maxtime: int = 0, + fade_ms: int = 0, + ) -> Channel: ... + def stop(self) -> None: ... + def fadeout(self, time: int) -> None: ... + def set_volume(self, value: float) -> None: ... + def get_volume(self) -> float: ... + def get_num_channels(self) -> int: ... + def get_length(self) -> float: ... + def get_raw(self) -> bytes: ... + +class Channel: + def __init__(self, id: int) -> None: ... + def play( + self, + sound: Sound, + loops: int = 0, + maxtime: int = 0, + fade_ms: int = 0, + ) -> None: ... + def stop(self) -> None: ... + def pause(self) -> None: ... + def unpause(self) -> None: ... + def fadeout(self, time: int) -> None: ... + @overload + def set_volume(self, value: float) -> None: ... + @overload + def set_volume(self, left: float, right: float) -> None: ... + def get_volume(self) -> float: ... + def get_busy(self) -> bool: ... + def get_sound(self) -> Sound: ... + def get_queue(self) -> Sound: ... + def set_endevent(self, type: Union[int, Event] = 0) -> None: ... + def get_endevent(self) -> int: ... diff --git a/venv/Lib/site-packages/pygame/mixer_music.cp39-win_amd64.pyd b/venv/Lib/site-packages/pygame/mixer_music.cp39-win_amd64.pyd new file mode 100644 index 0000000000000000000000000000000000000000..de406d30d31ec64341d6fe7e254d7fa50811483c GIT binary patch literal 20992 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 Np1*4^|DWyr{{mwAZ)gAj literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/mouse.pyi b/venv/Lib/site-packages/pygame/mouse.pyi new file mode 100644 index 0000000..84b77ed --- /dev/null +++ b/venv/Lib/site-packages/pygame/mouse.pyi @@ -0,0 +1,34 @@ +from typing import List, Sequence, Tuple, Union, overload + +from pygame.cursors import Cursor +from pygame.surface import Surface + +def get_pressed( + num_buttons: int = 3, +) -> Union[Tuple[bool, bool, bool], Tuple[bool, bool, bool, bool, bool]]: ... +def get_pos() -> Tuple[int, int]: ... +def get_rel() -> Tuple[int, int]: ... +@overload +def set_pos(pos: Union[List[float], Tuple[float, float]]) -> None: ... +@overload +def set_pos(x: float, y: float) -> None: ... +def set_visible(value: bool) -> int: ... +def get_visible() -> bool: ... +def get_focused() -> bool: ... +@overload +def set_cursor(cursor: Cursor) -> None: ... +@overload +def set_cursor(constant: int) -> None: ... +@overload +def set_cursor( + size: Union[Tuple[int, int], List[int]], + hotspot: Union[Tuple[int, int], List[int]], + xormasks: Sequence[int], + andmasks: Sequence[int], +) -> None: ... +@overload +def set_cursor( + hotspot: Union[Tuple[int, int], List[int]], surface: Surface +) -> None: ... +def get_cursor() -> Cursor: ... +def set_system_cursor(cursor: int) -> None: ... diff --git a/venv/Lib/site-packages/pygame/music.pyi b/venv/Lib/site-packages/pygame/music.pyi new file mode 100644 index 0000000..91a6f55 --- /dev/null +++ b/venv/Lib/site-packages/pygame/music.pyi @@ -0,0 +1,20 @@ +from typing import Optional + +from ._common import _FileArg + +def load(filename: _FileArg, namehint: Optional[str] = "") -> None: ... +def unload() -> None: ... +def play(loops: int = 0, start: float = 0.0, fade_ms: int = 0) -> None: ... +def rewind() -> None: ... +def stop() -> None: ... +def pause() -> None: ... +def unpause() -> None: ... +def fadeout(time: int) -> None: ... +def set_volume(volume: float) -> None: ... +def get_volume() -> float: ... +def get_busy() -> bool: ... +def set_pos(pos: float) -> None: ... +def get_pos() -> int: ... +def queue(filename: _FileArg, namehint: str = "", loops: int = 0) -> None: ... +def set_endevent(event_type: int) -> None: ... +def get_endevent() -> int: ... diff --git a/venv/Lib/site-packages/pygame/newbuffer.cp39-win_amd64.pyd b/venv/Lib/site-packages/pygame/newbuffer.cp39-win_amd64.pyd new file mode 100644 index 0000000000000000000000000000000000000000..1f7ee6167a1deceb1fc5f86b2a654eb4c005d5d6 GIT binary patch literal 22016 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 Bx#j=> literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/pixelarray.cp39-win_amd64.pyd b/venv/Lib/site-packages/pygame/pixelarray.cp39-win_amd64.pyd new file mode 100644 index 0000000000000000000000000000000000000000..de2a5b0b1780e7ee52be9d4bbe8d0c325df16329 GIT binary patch literal 44544 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�^%3c~&&<~(*f#?#h}+*-9E+$5y^>2MbQ13G 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 None: ... + def make_surface(self) -> Surface: ... + def replace( + self, + color: _ColorValue, + repcolor: _ColorValue, + distance: float = 0, + weights: Sequence[float] = (0.299, 0.587, 0.114), + ) -> None: ... + def extract( + self, + color: _ColorValue, + distance: float = 0, + weights: Sequence[float] = (0.299, 0.587, 0.114), + ) -> PixelArray: ... + def compare( + self, + array: PixelArray, + distance: float = 0, + weights: Sequence[float] = (0.299, 0.587, 0.114), + ) -> PixelArray: ... + def transpose(self) -> PixelArray: ... + def close(self) -> PixelArray: ... diff --git a/venv/Lib/site-packages/pygame/pixelcopy.cp39-win_amd64.pyd b/venv/Lib/site-packages/pygame/pixelcopy.cp39-win_amd64.pyd new file mode 100644 index 0000000000000000000000000000000000000000..56811d59a2890f412f2ef4ffa4d44666fb2901ac GIT binary patch literal 26112 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 R$Fd&Fe(W#Wa{n!q|4)}DCQ<+Z literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/pixelcopy.pyi b/venv/Lib/site-packages/pygame/pixelcopy.pyi new file mode 100644 index 0000000..3734ddf --- /dev/null +++ b/venv/Lib/site-packages/pygame/pixelcopy.pyi @@ -0,0 +1,19 @@ +import numpy +from typing_extensions import Literal + +from pygame.surface import Surface + +_kind = Literal["P", "p", "R", "r", "G", "g", "B", "b", "A", "a", "C", "c"] + +def surface_to_array( + array: numpy.ndarray, + surface: Surface, + kind: _kind = "P", + opaque: int = 255, + clear: int = 0, +) -> None: ... +def array_to_surface(surface: Surface, array: numpy.ndarray) -> None: ... +def map_to_array( + array1: numpy.ndarray, array2: numpy.ndarray, surface: Surface +) -> None: ... +def make_surface(array: numpy.ndarray) -> Surface: ... diff --git a/venv/Lib/site-packages/pygame/pkgdata.py b/venv/Lib/site-packages/pygame/pkgdata.py new file mode 100644 index 0000000..1d89028 --- /dev/null +++ b/venv/Lib/site-packages/pygame/pkgdata.py @@ -0,0 +1,79 @@ +""" +pkgdata is a simple, extensible way for a package to acquire data file +resources. + +The getResource function is equivalent to the standard idioms, such as +the following minimal implementation: + + import sys, os + + def getResource(identifier, pkgname=__name__): + pkgpath = os.path.dirname(sys.modules[pkgname].__file__) + path = os.path.join(pkgpath, identifier) + return file(os.path.normpath(path), mode='rb') + +When a __loader__ is present on the module given by __name__, it will defer +getResource to its get_data implementation and return it as a file-like +object (such as StringIO). +""" + +__all__ = ["getResource"] +import sys +import os + +from io import BytesIO + +try: + from pkg_resources import resource_stream, resource_exists +except ImportError: + + def resource_exists(_package_or_requirement, _resource_name): + """ + A stub for when we fail to import this function. + + :return: Always returns False + """ + return False + + def resource_stream(_package_of_requirement, _resource_name): + """ + A stub for when we fail to import this function. + + Always raises a NotImplementedError when called. + """ + raise NotImplementedError + + +def getResource(identifier, pkgname=__name__): + """ + Acquire a readable object for a given package name and identifier. + An IOError will be raised if the resource can not be found. + + For example: + mydata = getResource('mypkgdata.jpg').read() + + Note that the package name must be fully qualified, if given, such + that it would be found in sys.modules. + + In some cases, getResource will return a real file object. In that + case, it may be useful to use its name attribute to get the path + rather than use it as a file-like object. For example, you may + be handing data off to a C API. + """ + + # When pyinstaller (or similar tools) are used, resource_exists may raise + # NotImplemented error + try: + if resource_exists(pkgname, identifier): + return resource_stream(pkgname, identifier) + except NotImplementedError: + pass + + mod = sys.modules[pkgname] + path_to_file = getattr(mod, "__file__", None) + if path_to_file is None: + raise IOError(f"{repr(mod)} has no __file__!") + path = os.path.join(os.path.dirname(path_to_file), identifier) + + # pylint: disable=consider-using-with + return open(os.path.normpath(path), "rb") diff --git a/venv/Lib/site-packages/pygame/portmidi.dll b/venv/Lib/site-packages/pygame/portmidi.dll new file mode 100644 index 0000000000000000000000000000000000000000..cc4361c30b2d5abd24c7ff5edf3fb5e070d55616 GIT binary patch literal 41984 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 ToQMc9iAO07f{vlS_CNgxsX4?^ literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/pygame_icon.icns b/venv/Lib/site-packages/pygame/pygame_icon.icns new file mode 100644 index 0000000000000000000000000000000000000000..44a67bbdf93d265b58a8d385db24acde4e6cff88 GIT binary patch literal 264148 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�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ⅈh}K2#CB98MZeq__d^qmn_C==>Kh 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 z z3V|IU7zFV^Fg*wZLIi)vLjwcRx0#rNIcfQ^52{^I27TJNcbElZR58M7EkeDJ7eEikN@ zk>uUsVJqG8B;H#`Z9X>s*@wdTHP1qiw+e349k}l2*DYKB@)me_Odxu%$JmDg2T0aa z6$9Tm7|kGh;O>VvZCZejZ3V5GUHAtYWG%oce>|yV*c~YM6$a6(iUGc24Gc#O`$f7? z%a3FYfa6nP>_HGd==hnkhL7+&FZKlF@&LH&MWL{K@t`RJ7ZQ;1>;s=;=?v=;m~7?K zIEp>ir4+AO69u5(2!81&{mla)^~z8@mtw#6hpoV47t0vi;L6fd?CXGy_{=Pj^`wA4 zry}6xMiNg`5%ekAMZ={%yZGHeu^rv5zBLVifoBJn8<2K@ieMLoK&Z3$y?8NT7r}1@ zzF7RSDDa6945HeI0SmIGY;*qEVAQwFyLKD|Ooz|5zySn>IZT~gzww4m)a2QCn0(eX z$uW4;lNQ+4#7J_MMx|6xk9d%z^~O`o)?p|9kyE(Q6T=d{%BL zZmA@?w2E=$ZSd1gbM*MMY!o#690tC9aM4|*cU?*J*N!JD-axyZ6P`gM{kS+b6!tkp z5Xkj#;;fvudIY8x{zhx+x1o@AbqpBZ>lolWR?xdC0Er9r>}!C&wfI#m=pDbZ{L6U= z?0HcfoaHaqQ_LSTAp;e%3WIw-%XfueW&#Gz3O`PJ3?%Lf=;6V&1Z1O*+ZmZ3#8=^~ zw6VZH#XMF!t+#QJTOw!0;O;kyfK;f5Pv7U+q+xO?0HYvf7{^*F4PHs#V&wUKUc>Hg zARR8%A*CaV;0FU{kfV0dpX>Ox!%K&jfg`K^y9_|92<-1-zb{!MbVu3|v&>)5sLEPgAJRt_AR8#li8%5Kk2%qfjxZQvBA{SkfgS9hda|rE$flT7fSH>3AErQvy^> zvEiC$ZzJ+;fA8As*X8$miM>-`G6fI|e9@#vWkxed*}4Czm~8>*smwPRS)V>{&^xu* zQz_|=B=KBSI;wPBTc#)iBH-P?P_d>g>0;T7rtAim>1m0}Uo3oa`Ab|}_u|qQ&p@Ap}Dw@ zf7iOj4DcJxfFcmYtNWec7t7yLXUU5I*FY%0A!7x)@HH`HT-*wNXW3f|-SJ7`i#DIL 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 J%s<~J{|k(bh%NvC literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/pygame_icon_mac.bmp b/venv/Lib/site-packages/pygame/pygame_icon_mac.bmp new file mode 100644 index 0000000000000000000000000000000000000000..7b58bb1039a85e13f3766f2308718668c5f83351 GIT binary patch literal 262282 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/rect.cp39-win_amd64.pyd b/venv/Lib/site-packages/pygame/rect.cp39-win_amd64.pyd new file mode 100644 index 0000000000000000000000000000000000000000..af03aa2b3406ca7e5efa202ab62d454d751ceaef GIT binary patch literal 36864 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 None: ... + @overload + def __init__( + self, + left_top: Union[List[float], Tuple[float, float], Vector2], + width_height: Union[List[float], Tuple[float, float], Vector2], + ) -> None: ... + @overload + def __init__( + self, + left_top_width_height: Union[ + Rect, Tuple[float, float, float, float], List[float] + ], + ) -> None: ... + @overload + def __getitem__(self, i: int) -> int: ... + @overload + def __getitem__(self, s: slice) -> List[int]: ... + def copy(self) -> Rect: ... + @overload + def move(self, x: float, y: float) -> Rect: ... + @overload + def move(self, move_by: _Coordinate) -> Rect: ... + @overload + def move_ip(self, x: float, y: float) -> None: ... + @overload + def move_ip(self, move_by: _Coordinate) -> None: ... + @overload + def inflate(self, x: float, y: float) -> Rect: ... + @overload + def inflate(self, inflate_by: _Coordinate) -> Rect: ... + @overload + def inflate_ip(self, x: float, y: float) -> None: ... + @overload + def inflate_ip(self, inflate_by: _Coordinate) -> None: ... + @overload + def update(self, left: float, top: float, width: float, height: float) -> None: ... + @overload + def update( + self, + left_top: Union[List[float], Tuple[float, float], Vector2], + width_height: Union[List[float], Tuple[float, float], Vector2], + ) -> None: ... + @overload + def update( + self, + left_top_width_height: Union[ + Rect, Tuple[float, float, float, float], List[float] + ], + ) -> None: ... + @overload + def clamp(self, rect: Union[_CanBeRect, Rect]) -> Rect: ... + @overload + def clamp( + self, + left_top: Union[List[float], Tuple[float, float], Vector2], + width_height: Union[List[float], Tuple[float, float], Vector2], + ) -> Rect: ... + @overload + def clamp(self, left: float, top: float, width: float, height: float) -> Rect: ... + @overload + def clamp_ip(self, rect: Union[_CanBeRect, Rect]) -> None: ... + @overload + def clamp_ip( + self, + left_top: Union[List[float], Tuple[float, float], Vector2], + width_height: Union[List[float], Tuple[float, float], Vector2], + ) -> None: ... + @overload + def clamp_ip( + self, left: float, top: float, width: float, height: float + ) -> None: ... + @overload + def clip(self, rect: Union[_CanBeRect, Rect]) -> Rect: ... + @overload + def clip( + self, + left_top: Union[List[float], Tuple[float, float], Vector2], + width_height: Union[List[float], Tuple[float, float], Vector2], + ) -> Rect: ... + @overload + def clip(self, left: float, top: float, width: float, height: float) -> Rect: ... + @overload + def clipline( + self, x1: float, x2: float, x3: float, x4: float + ) -> Union[Tuple[Tuple[int, int], Tuple[int, int]], Tuple[()]]: ... + @overload + def clipline( + self, first_coordinate: _Coordinate, second_coordinate: _Coordinate + ) -> Union[Tuple[Tuple[int, int], Tuple[int, int]], Tuple[()]]: ... + @overload + def clipline( + self, values: Union[Tuple[float, float, float, float], List[float]] + ) -> Union[Tuple[Tuple[int, int], Tuple[int, int]], Tuple[()]]: ... + @overload + def clipline( + self, coordinates: Union[Tuple[_Coordinate, _Coordinate], List[_Coordinate]] + ) -> Union[Tuple[Tuple[int, int], Tuple[int, int]], Tuple[()]]: ... + @overload + def union(self, rect: Union[_CanBeRect, Rect]) -> Rect: ... + @overload + def union( + self, + left_top: Union[List[float], Tuple[float, float], Vector2], + width_height: Union[List[float], Tuple[float, float], Vector2], + ) -> Rect: ... + @overload + def union(self, left: float, top: float, width: float, height: float) -> Rect: ... + @overload + def union_ip(self, rect: Union[_CanBeRect, Rect]) -> None: ... + @overload + def union_ip( + self, + left_top: Union[List[float], Tuple[float, float], Vector2], + width_height: Union[List[float], Tuple[float, float], Vector2], + ) -> None: ... + @overload + def union_ip( + self, left: float, top: float, width: float, height: float + ) -> None: ... + def unionall(self, rect: Sequence[Union[_CanBeRect, Rect]]) -> Rect: ... + def unionall_ip(self, rect_sequence: Sequence[Union[_CanBeRect, Rect]]) -> None: ... + @overload + def fit(self, rect: Union[_CanBeRect, Rect]) -> Rect: ... + @overload + def fit( + self, + left_top: Union[List[float], Tuple[float, float], Vector2], + width_height: Union[List[float], Tuple[float, float], Vector2], + ) -> Rect: ... + @overload + def fit(self, left: float, top: float, width: float, height: float) -> Rect: ... + def normalize(self) -> None: ... + @overload + def __contains__(self, rect: Union[_CanBeRect, Rect, int]) -> bool: ... + @overload + def __contains__( + self, + left_top: Union[List[float], Tuple[float, float], Vector2], + width_height: Union[List[float], Tuple[float, float], Vector2], + ) -> bool: ... + @overload + def __contains__(self, left: float, top: float, width: float, height: float) -> bool: ... + @overload + def contains(self, rect: Union[_CanBeRect, Rect]) -> bool: ... + @overload + def contains( + self, + left_top: Union[List[float], Tuple[float, float], Vector2], + width_height: Union[List[float], Tuple[float, float], Vector2], + ) -> bool: ... + @overload + def contains( + self, left: float, top: float, width: float, height: float + ) -> bool: ... + @overload + def collidepoint(self, x: float, y: float) -> bool: ... + @overload + def collidepoint(self, x_y: Union[List[float], Tuple[float, float]]) -> bool: ... + @overload + def colliderect(self, rect: Union[_CanBeRect, Rect]) -> bool: ... + @overload + def colliderect( + self, + left_top: Union[List[float], Tuple[float, float], Vector2], + width_height: Union[List[float], Tuple[float, float], Vector2], + ) -> bool: ... + @overload + def colliderect( + self, left: float, top: float, width: float, height: float + ) -> bool: ... + def collidelist(self, rect_list: Sequence[Union[Rect, _CanBeRect]]) -> int: ... + def collidelistall( + self, rect_list: Sequence[Union[Rect, _CanBeRect]] + ) -> List[int]: ... + # Also undocumented: the dict collision methods take a 'values' argument + # that defaults to False. If it is False, the keys in rect_dict must be + # Rect-like; otherwise, the values must be Rects. + @overload + def collidedict( + self, rect_dict: Dict[_CanBeRect, _V], values: bool = ... + ) -> Tuple[_CanBeRect, _V]: ... + @overload + def collidedict( + self, rect_dict: Dict[_K, "Rect"], values: bool + ) -> Tuple[_K, "Rect"]: ... + @overload + def collidedictall( + self, rect_dict: Dict[_CanBeRect, _V], values: bool = ... + ) -> List[Tuple[_CanBeRect, _V]]: ... + @overload + def collidedictall( + self, rect_dict: Dict[_K, "Rect"], values: bool + ) -> List[Tuple[_K, "Rect"]]: ... diff --git a/venv/Lib/site-packages/pygame/rwobject.cp39-win_amd64.pyd b/venv/Lib/site-packages/pygame/rwobject.cp39-win_amd64.pyd new file mode 100644 index 0000000000000000000000000000000000000000..7766d8a166e2ba17ba9b8d9f8ba31897fb1ef009 GIT binary patch literal 19456 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 E1(7$mZ2$lO literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/scrap.cp39-win_amd64.pyd b/venv/Lib/site-packages/pygame/scrap.cp39-win_amd64.pyd new file mode 100644 index 0000000000000000000000000000000000000000..31e5d8f17fe177d02aeb122dc7891740e4d7ffe0 GIT binary patch literal 18944 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/scrap.pyi b/venv/Lib/site-packages/pygame/scrap.pyi new file mode 100644 index 0000000..7905ce6 --- /dev/null +++ b/venv/Lib/site-packages/pygame/scrap.pyi @@ -0,0 +1,10 @@ +from typing import AnyStr, List + +def init() -> None: ... +def get_init() -> bool: ... +def get(data_type: str) -> AnyStr: ... +def get_types() -> List[str]: ... +def put(data_type: str, data: AnyStr) -> None: ... +def contains(data_type: str) -> bool: ... +def lost() -> bool: ... +def set_mode(mode: int) -> None: ... diff --git a/venv/Lib/site-packages/pygame/sndarray.py b/venv/Lib/site-packages/pygame/sndarray.py new file mode 100644 index 0000000..99ac4c7 --- /dev/null +++ b/venv/Lib/site-packages/pygame/sndarray.py @@ -0,0 +1,139 @@ +## pygame - Python Game Library +## Copyright (C) 2008 Marcus von Appen +## +## This library is free software; you can redistribute it and/or +## modify it under the terms of the GNU Library General Public +## License as published by the Free Software Foundation; either +## version 2 of the License, or (at your option) any later version. +## +## This library is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## Library General Public License for more details. +## +## You should have received a copy of the GNU Library General Public +## License along with this library; if not, write to the Free +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +## +## Marcus von Appen +## mva@sysfault.org + +"""pygame module for accessing sound sample data + +Functions to convert between NumPy arrays and Sound objects. This module +will only be functional when pygame can use the external NumPy package. +If NumPy can't be imported, surfarray becomes a MissingModule object. + +Sound data is made of thousands of samples per second, and each sample +is the amplitude of the wave at a particular moment in time. For +example, in 22-kHz format, element number 5 of the array is the +amplitude of the wave after 5/22000 seconds. + +Each sample is an 8-bit or 16-bit integer, depending on the data format. +A stereo sound file has two values per sample, while a mono sound file +only has one. + +Sounds with 16-bit data will be treated as unsigned integers, +if the sound sample type requests this. +""" + +from pygame import mixer +import numpy + +import warnings + + +__all__ = [ + "array", + "samples", + "make_sound", + "use_arraytype", + "get_arraytype", + "get_arraytypes", +] + + +def array(sound): + """pygame.sndarray.array(Sound): return array + + Copy Sound samples into an array. + + Creates a new array for the sound data and copies the samples. The + array will always be in the format returned from + pygame.mixer.get_init(). + """ + + return numpy.array(sound, copy=True) + + +def samples(sound): + """pygame.sndarray.samples(Sound): return array + + Reference Sound samples into an array. + + Creates a new array that directly references the samples in a Sound + object. Modifying the array will change the Sound. The array will + always be in the format returned from pygame.mixer.get_init(). + """ + + return numpy.array(sound, copy=False) + + +def make_sound(array): + """pygame.sndarray.make_sound(array): return Sound + + Convert an array into a Sound object. + + Create a new playable Sound object from an array. The mixer module + must be initialized and the array format must be similar to the mixer + audio format. + """ + + return mixer.Sound(array=array) + + +def use_arraytype(arraytype): + """pygame.sndarray.use_arraytype(arraytype): return None + + DEPRECATED - only numpy arrays are now supported. + """ + warnings.warn( + DeprecationWarning( + "only numpy arrays are now supported, " + "this function will be removed in a " + "future version of the module" + ) + ) + arraytype = arraytype.lower() + if arraytype != "numpy": + raise ValueError("invalid array type") + + +def get_arraytype(): + """pygame.sndarray.get_arraytype(): return str + + DEPRECATED - only numpy arrays are now supported. + """ + warnings.warn( + DeprecationWarning( + "only numpy arrays are now supported, " + "this function will be removed in a " + "future version of the module" + ) + ) + return "numpy" + + +def get_arraytypes(): + """pygame.sndarray.get_arraytypes(): return tuple + + DEPRECATED - only numpy arrays are now supported. + """ + warnings.warn( + DeprecationWarning( + "only numpy arrays are now supported, " + "this function will be removed in a " + "future version of the module" + ) + ) + return ("numpy",) diff --git a/venv/Lib/site-packages/pygame/sndarray.pyi b/venv/Lib/site-packages/pygame/sndarray.pyi new file mode 100644 index 0000000..8b0dd65 --- /dev/null +++ b/venv/Lib/site-packages/pygame/sndarray.pyi @@ -0,0 +1,12 @@ +from typing import Tuple + +import numpy + +from pygame.mixer import Sound + +def array(sound: Sound) -> numpy.ndarray: ... +def samples(sound: Sound) -> numpy.ndarray: ... +def make_sound(array: numpy.ndarray) -> Sound: ... +def use_arraytype(arraytype: str) -> Sound: ... +def get_arraytype() -> str: ... +def get_arraytypes() -> Tuple[str]: ... diff --git a/venv/Lib/site-packages/pygame/sprite.py b/venv/Lib/site-packages/pygame/sprite.py new file mode 100644 index 0000000..553ccfb --- /dev/null +++ b/venv/Lib/site-packages/pygame/sprite.py @@ -0,0 +1,1782 @@ +# pygame - Python Game Library +# Copyright (C) 2000-2003, 2007 Pete Shinners +# (C) 2004 Joe Wreschnig +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Library General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Library General Public License for more details. +# +# You should have received a copy of the GNU Library General Public +# License along with this library; if not, write to the Free +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# Pete Shinners +# pete@shinners.org + +"""pygame module with basic game object classes + +This module contains several simple classes to be used within games. There +are the main Sprite class and several Group classes that contain Sprites. +The use of these classes is entirely optional when using Pygame. The classes +are fairly lightweight and only provide a starting place for the code +that is common to most games. + +The Sprite class is intended to be used as a base class for the different +types of objects in the game. There is also a base Group class that simply +stores sprites. A game could create new types of Group classes that operate +on specially customized Sprite instances they contain. + +The basic Sprite class can draw the Sprites it contains to a Surface. The +Group.draw() method requires that each Sprite have a Surface.image attribute +and a Surface.rect. The Group.clear() method requires these same attributes +and can be used to erase all the Sprites with background. There are also +more advanced Groups: pygame.sprite.RenderUpdates() and +pygame.sprite.OrderedUpdates(). + +Lastly, this module contains several collision functions. These help find +sprites inside multiple groups that have intersecting bounding rectangles. +To find the collisions, the Sprites are required to have a Surface.rect +attribute assigned. + +The groups are designed for high efficiency in removing and adding Sprites +to them. They also allow cheap testing to see if a Sprite already exists in +a Group. A given Sprite can exist in any number of groups. A game could use +some groups to control object rendering, and a completely separate set of +groups to control interaction or player movement. Instead of adding type +attributes or bools to a derived Sprite class, consider keeping the +Sprites inside organized Groups. This will allow for easier lookup later +in the game. + +Sprites and Groups manage their relationships with the add() and remove() +methods. These methods can accept a single or multiple group arguments for +membership. The default initializers for these classes also take a +single group or list of groups as arguments for initial membership. It is safe +to repeatedly add and remove the same Sprite from a Group. + +While it is possible to design sprite and group classes that don't derive +from the Sprite and AbstractGroup classes below, it is strongly recommended +that you extend those when you create a new Sprite or Group class. + +Sprites are not thread safe, so lock them yourself if using threads. + +""" + +# TODO: a group that holds only the 'n' most recent elements. +# sort of like the GroupSingle class, but holding more +# than one sprite +# +# drawing groups that can 'automatically' store the area +# underneath so they can "clear" without needing a background +# function. obviously a little slower than normal, but nice +# to use in many situations. (also remember it must "clear" +# in the reverse order that it draws :]) +# +# the drawing groups should also be able to take a background +# function, instead of just a background surface. the function +# would take a surface and a rectangle on that surface to erase. +# +# perhaps more types of collision functions? the current two +# should handle just about every need, but perhaps more optimized +# specific ones that aren't quite so general but fit into common +# specialized cases. + +from operator import truth +from warnings import warn + +import pygame + +from pygame.rect import Rect +from pygame.time import get_ticks +from pygame.mask import from_surface + + +class Sprite(object): + """simple base class for visible game objects + + pygame.sprite.Sprite(*groups): return Sprite + + The base class for visible game objects. Derived classes will want to + override the Sprite.update() method and assign Sprite.image and Sprite.rect + attributes. The initializer can accept any number of Group instances that + the Sprite will become a member of. + + When subclassing the Sprite class, be sure to call the base initializer + before adding the Sprite to Groups. + + """ + + def __init__(self, *groups): + self.__g = {} # The groups the sprite is in + if groups: + self.add(*groups) + + def add(self, *groups): + """add the sprite to groups + + Sprite.add(*groups): return None + + Any number of Group instances can be passed as arguments. The + Sprite will be added to the Groups it is not already a member of. + + """ + has = self.__g.__contains__ + for group in groups: + if hasattr(group, "_spritegroup"): + if not has(group): + group.add_internal(self) + self.add_internal(group) + else: + self.add(*group) + + def remove(self, *groups): + """remove the sprite from groups + + Sprite.remove(*groups): return None + + Any number of Group instances can be passed as arguments. The Sprite + will be removed from the Groups it is currently a member of. + + """ + has = self.__g.__contains__ + for group in groups: + if hasattr(group, "_spritegroup"): + if has(group): + group.remove_internal(self) + self.remove_internal(group) + else: + self.remove(*group) + + def add_internal(self, group): + """ + For adding this sprite to a group internally. + + :param group: The group we are adding to. + """ + self.__g[group] = 0 + + def remove_internal(self, group): + """ + For removing this sprite from a group internally. + + :param group: The group we are removing from. + """ + del self.__g[group] + + def update(self, *args, **kwargs): + """method to control sprite behavior + + Sprite.update(*args, **kwargs): + + The default implementation of this method does nothing; it's just a + convenient "hook" that you can override. This method is called by + Group.update() with whatever arguments you give it. + + There is no need to use this method if not using the convenience + method by the same name in the Group class. + + """ + + def kill(self): + """remove the Sprite from all Groups + + Sprite.kill(): return None + + The Sprite is removed from all the Groups that contain it. This won't + change anything about the state of the Sprite. It is possible to + continue to use the Sprite after this method has been called, including + adding it to Groups. + + """ + for group in self.__g: + group.remove_internal(self) + self.__g.clear() + + def groups(self): + """list of Groups that contain this Sprite + + Sprite.groups(): return group_list + + Returns a list of all the Groups that contain this Sprite. + + """ + return list(self.__g) + + def alive(self): + """does the sprite belong to any groups + + Sprite.alive(): return bool + + Returns True when the Sprite belongs to one or more Groups. + """ + return truth(self.__g) + + def __repr__(self): + return f"<{self.__class__.__name__} Sprite(in {len(self.__g)} groups)>" + + @property + def layer(self): + """ + Dynamic, read only property for protected _layer attribute. + This will get the _layer variable if it exists. + + If you try to get it before it is set it will raise an attribute error. + + Layer property can only be set before the sprite is added to a group, + after that it is read only and a sprite's layer in a group should be + set via the group's change_layer() method. + + :return: layer as an int, or raise AttributeError. + """ + return getattr(self, "_layer") + + @layer.setter + def layer(self, value): + if not self.alive(): + setattr(self, "_layer", value) + else: + raise AttributeError( + "Can't set layer directly after " + "adding to group. Use " + "group.change_layer(sprite, new_layer) " + "instead." + ) + + +class DirtySprite(Sprite): + """a more featureful subclass of Sprite with more attributes + + pygame.sprite.DirtySprite(*groups): return DirtySprite + + Extra DirtySprite attributes with their default values: + + dirty = 1 + If set to 1, it is repainted and then set to 0 again. + If set to 2, it is always dirty (repainted each frame; + flag is not reset). + If set to 0, it is not dirty and therefore not repainted again. + + blendmode = 0 + It's the special_flags argument of Surface.blit; see the blendmodes in + the Surface.blit documentation + + source_rect = None + This is the source rect to use. Remember that it is relative to the top + left corner (0, 0) of self.image. + + visible = 1 + Normally this is 1. If set to 0, it will not be repainted. (If you + change visible to 1, you must set dirty to 1 for it to be erased from + the screen.) + + _layer = 0 + 0 is the default value but this is able to be set differently + when subclassing. + + """ + + def __init__(self, *groups): + + self.dirty = 1 + + # referred to as special_flags in the documentation of Surface.blit + self.blendmode = 0 + self._visible = 1 + + # Default 0 unless initialized differently. + self._layer = getattr(self, "_layer", 0) + self.source_rect = None + Sprite.__init__(self, *groups) + + def _set_visible(self, val): + """set the visible value (0 or 1) and makes the sprite dirty""" + self._visible = val + if self.dirty < 2: + self.dirty = 1 + + def _get_visible(self): + """return the visible value of that sprite""" + return self._visible + + @property + def visible(self): + """ + You can make this sprite disappear without removing it from the group + assign 0 for invisible and 1 for visible + """ + return self._get_visible() + + @visible.setter + def visible(self, value): + self._set_visible(value) + + @property + def layer(self): + """ + Layer property can only be set before the sprite is added to a group, + after that it is read only and a sprite's layer in a group should be + set via the group's change_layer() method. + + Overwrites dynamic property from sprite class for speed. + """ + return self._layer + + @layer.setter + def layer(self, value): + if not self.alive(): + self._layer = value + else: + raise AttributeError( + "Can't set layer directly after " + "adding to group. Use " + "group.change_layer(sprite, new_layer) " + "instead." + ) + + def __repr__(self): + return ( + f"<{self.__class__.__name__} DirtySprite(in {len(self.groups())} groups)>" + ) + + +class AbstractGroup(object): + """base class for containers of sprites + + AbstractGroup does everything needed to behave as a normal group. You can + easily subclass a new group class from this or the other groups below if + you want to add more features. + + Any AbstractGroup-derived sprite groups act like sequences and support + iteration, len, and so on. + + """ + + # dummy val to identify sprite groups, and avoid infinite recursion + _spritegroup = True + + def __init__(self): + self.spritedict = {} + self.lostsprites = [] + + def sprites(self): + """get a list of sprites in the group + + Group.sprite(): return list + + Returns an object that can be looped over with a 'for' loop. (For now, + it is always a list, but this could change in a future version of + pygame.) Alternatively, you can get the same information by iterating + directly over the sprite group, e.g. 'for sprite in group'. + + """ + return list(self.spritedict) + + def add_internal( + self, + sprite, + layer=None, # noqa pylint: disable=unused-argument; supporting legacy derived classes that override in non-pythonic way + ): + """ + For adding a sprite to this group internally. + + :param sprite: The sprite we are adding. + :param layer: the layer to add to, if the group type supports layers + """ + self.spritedict[sprite] = None + + def remove_internal(self, sprite): + """ + For removing a sprite from this group internally. + + :param sprite: The sprite we are removing. + """ + lost_rect = self.spritedict[sprite] + if lost_rect: + self.lostsprites.append(lost_rect) + del self.spritedict[sprite] + + def has_internal(self, sprite): + """ + For checking if a sprite is in this group internally. + + :param sprite: The sprite we are checking. + """ + return sprite in self.spritedict + + def copy(self): + """copy a group with all the same sprites + + Group.copy(): return Group + + Returns a copy of the group that is an instance of the same class + and has the same sprites in it. + + """ + return self.__class__( # noqa pylint: disable=too-many-function-args + self.sprites() # Needed because copy() won't work on AbstractGroup + ) + + def __iter__(self): + return iter(self.sprites()) + + def __contains__(self, sprite): + return self.has(sprite) + + def add(self, *sprites): + """add sprite(s) to group + + Group.add(sprite, list, group, ...): return None + + Adds a sprite or sequence of sprites to a group. + + """ + for sprite in sprites: + # It's possible that some sprite is also an iterator. + # If this is the case, we should add the sprite itself, + # and not the iterator object. + if isinstance(sprite, Sprite): + if not self.has_internal(sprite): + self.add_internal(sprite) + sprite.add_internal(self) + else: + try: + # See if sprite is an iterator, like a list or sprite + # group. + self.add(*sprite) + except (TypeError, AttributeError): + # Not iterable. This is probably a sprite that is not an + # instance of the Sprite class or is not an instance of a + # subclass of the Sprite class. Alternately, it could be an + # old-style sprite group. + if hasattr(sprite, "_spritegroup"): + for spr in sprite.sprites(): + if not self.has_internal(spr): + self.add_internal(spr) + spr.add_internal(self) + elif not self.has_internal(sprite): + self.add_internal(sprite) + sprite.add_internal(self) + + def remove(self, *sprites): + """remove sprite(s) from group + + Group.remove(sprite, list, or group, ...): return None + + Removes a sprite or sequence of sprites from a group. + + """ + # This function behaves essentially the same as Group.add. It first + # tries to handle each argument as an instance of the Sprite class. If + # that fails, then it tries to handle the argument as an iterable + # object. If that fails, then it tries to handle the argument as an + # old-style sprite group. Lastly, if that fails, it assumes that the + # normal Sprite methods should be used. + for sprite in sprites: + if isinstance(sprite, Sprite): + if self.has_internal(sprite): + self.remove_internal(sprite) + sprite.remove_internal(self) + else: + try: + self.remove(*sprite) + except (TypeError, AttributeError): + if hasattr(sprite, "_spritegroup"): + for spr in sprite.sprites(): + if self.has_internal(spr): + self.remove_internal(spr) + spr.remove_internal(self) + elif self.has_internal(sprite): + self.remove_internal(sprite) + sprite.remove_internal(self) + + def has(self, *sprites): + """ask if group has a sprite or sprites + + Group.has(sprite or group, ...): return bool + + Returns True if the given sprite or sprites are contained in the + group. Alternatively, you can get the same information using the + 'in' operator, e.g. 'sprite in group', 'subgroup in group'. + + """ + if not sprites: + return False # return False if no sprites passed in + + for sprite in sprites: + if isinstance(sprite, Sprite): + # Check for Sprite instance's membership in this group + if not self.has_internal(sprite): + return False + else: + try: + if not self.has(*sprite): + return False + except (TypeError, AttributeError): + if hasattr(sprite, "_spritegroup"): + for spr in sprite.sprites(): + if not self.has_internal(spr): + return False + else: + if not self.has_internal(sprite): + return False + + return True + + def update(self, *args, **kwargs): + """call the update method of every member sprite + + Group.update(*args, **kwargs): return None + + Calls the update method of every member sprite. All arguments that + were passed to this method are passed to the Sprite update function. + + """ + for sprite in self.sprites(): + sprite.update(*args, **kwargs) + + def draw(self, surface): + """draw all sprites onto the surface + + Group.draw(surface): return Rect_list + + Draws all of the member sprites onto the given surface. + + """ + sprites = self.sprites() + if hasattr(surface, "blits"): + self.spritedict.update( + zip(sprites, surface.blits((spr.image, spr.rect) for spr in sprites)) + ) + else: + for spr in sprites: + self.spritedict[spr] = surface.blit(spr.image, spr.rect) + self.lostsprites = [] + dirty = self.lostsprites + + return dirty + + def clear(self, surface, bgd): + """erase the previous position of all sprites + + Group.clear(surface, bgd): return None + + Clears the area under every drawn sprite in the group. The bgd + argument should be Surface which is the same dimensions as the + screen surface. The bgd could also be a function which accepts + the given surface and the area to be cleared as arguments. + + """ + if callable(bgd): + for lost_clear_rect in self.lostsprites: + bgd(surface, lost_clear_rect) + for clear_rect in self.spritedict.values(): + if clear_rect: + bgd(surface, clear_rect) + else: + surface_blit = surface.blit + for lost_clear_rect in self.lostsprites: + surface_blit(bgd, lost_clear_rect, lost_clear_rect) + for clear_rect in self.spritedict.values(): + if clear_rect: + surface_blit(bgd, clear_rect, clear_rect) + + def empty(self): + """remove all sprites + + Group.empty(): return None + + Removes all the sprites from the group. + + """ + for sprite in self.sprites(): + self.remove_internal(sprite) + sprite.remove_internal(self) + + def __nonzero__(self): + return truth(self.sprites()) + + __bool__ = __nonzero__ + + def __len__(self): + """return number of sprites in group + + Group.len(group): return int + + Returns the number of sprites contained in the group. + + """ + return len(self.sprites()) + + def __repr__(self): + return f"<{self.__class__.__name__}({len(self)} sprites)>" + + +class Group(AbstractGroup): + """container class for many Sprites + + pygame.sprite.Group(*sprites): return Group + + A simple container for Sprite objects. This class can be subclassed to + create containers with more specific behaviors. The constructor takes any + number of Sprite arguments to add to the Group. The group supports the + following standard Python operations: + + in test if a Sprite is contained + len the number of Sprites contained + bool test if any Sprites are contained + iter iterate through all the Sprites + + The Sprites in the Group are not ordered, so the Sprites are drawn and + iterated over in no particular order. + + """ + + def __init__(self, *sprites): + AbstractGroup.__init__(self) + self.add(*sprites) + + +RenderPlain = Group +RenderClear = Group + + +class RenderUpdates(Group): + """Group class that tracks dirty updates + + pygame.sprite.RenderUpdates(*sprites): return RenderUpdates + + This class is derived from pygame.sprite.Group(). It has an enhanced draw + method that tracks the changed areas of the screen. + + """ + + def draw(self, surface): + surface_blit = surface.blit + dirty = self.lostsprites + self.lostsprites = [] + dirty_append = dirty.append + for sprite in self.sprites(): + old_rect = self.spritedict[sprite] + new_rect = surface_blit(sprite.image, sprite.rect) + if old_rect: + if new_rect.colliderect(old_rect): + dirty_append(new_rect.union(old_rect)) + else: + dirty_append(new_rect) + dirty_append(old_rect) + else: + dirty_append(new_rect) + self.spritedict[sprite] = new_rect + return dirty + + +class OrderedUpdates(RenderUpdates): + """RenderUpdates class that draws Sprites in order of addition + + pygame.sprite.OrderedUpdates(*spites): return OrderedUpdates + + This class derives from pygame.sprite.RenderUpdates(). It maintains + the order in which the Sprites were added to the Group for rendering. + This makes adding and removing Sprites from the Group a little + slower than regular Groups. + + """ + + def __init__(self, *sprites): + self._spritelist = [] + RenderUpdates.__init__(self, *sprites) + + def sprites(self): + return list(self._spritelist) + + def add_internal(self, sprite, layer=None): + RenderUpdates.add_internal(self, sprite) + self._spritelist.append(sprite) + + def remove_internal(self, sprite): + RenderUpdates.remove_internal(self, sprite) + self._spritelist.remove(sprite) + + +class LayeredUpdates(AbstractGroup): + """LayeredUpdates Group handles layers, which are drawn like OrderedUpdates + + pygame.sprite.LayeredUpdates(*spites, **kwargs): return LayeredUpdates + + This group is fully compatible with pygame.sprite.Sprite. + New in pygame 1.8.0 + + """ + + _init_rect = Rect(0, 0, 0, 0) + + def __init__(self, *sprites, **kwargs): + """initialize an instance of LayeredUpdates with the given attributes + + You can set the default layer through kwargs using 'default_layer' + and an integer for the layer. The default layer is 0. + + If the sprite you add has an attribute _layer, then that layer will be + used. If **kwarg contains 'layer', then the passed sprites will be + added to that layer (overriding the sprite._layer attribute). If + neither the sprite nor **kwarg has a 'layer', then the default layer is + used to add the sprites. + + """ + self._spritelayers = {} + self._spritelist = [] + AbstractGroup.__init__(self) + self._default_layer = kwargs.get("default_layer", 0) + + self.add(*sprites, **kwargs) + + def add_internal(self, sprite, layer=None): + """Do not use this method directly. + + It is used by the group to add a sprite internally. + + """ + self.spritedict[sprite] = self._init_rect + + if layer is None: + try: + layer = sprite.layer + except AttributeError: + layer = self._default_layer + setattr(sprite, "_layer", layer) + elif hasattr(sprite, "_layer"): + setattr(sprite, "_layer", layer) + + sprites = self._spritelist # speedup + sprites_layers = self._spritelayers + sprites_layers[sprite] = layer + + # add the sprite at the right position + # bisect algorithmus + leng = len(sprites) + low = mid = 0 + high = leng - 1 + while low <= high: + mid = low + (high - low) // 2 + if sprites_layers[sprites[mid]] <= layer: + low = mid + 1 + else: + high = mid - 1 + # linear search to find final position + while mid < leng and sprites_layers[sprites[mid]] <= layer: + mid += 1 + sprites.insert(mid, sprite) + + def add(self, *sprites, **kwargs): + """add a sprite or sequence of sprites to a group + + LayeredUpdates.add(*sprites, **kwargs): return None + + If the sprite you add has an attribute _layer, then that layer will be + used. If **kwarg contains 'layer', then the passed sprites will be + added to that layer (overriding the sprite._layer attribute). If + neither the sprite nor **kwarg has a 'layer', then the default layer is + used to add the sprites. + + """ + + if not sprites: + return + layer = kwargs["layer"] if "layer" in kwargs else None + for sprite in sprites: + # It's possible that some sprite is also an iterator. + # If this is the case, we should add the sprite itself, + # and not the iterator object. + if isinstance(sprite, Sprite): + if not self.has_internal(sprite): + self.add_internal(sprite, layer) + sprite.add_internal(self) + else: + try: + # See if sprite is an iterator, like a list or sprite + # group. + self.add(*sprite, **kwargs) + except (TypeError, AttributeError): + # Not iterable. This is probably a sprite that is not an + # instance of the Sprite class or is not an instance of a + # subclass of the Sprite class. Alternately, it could be an + # old-style sprite group. + if hasattr(sprite, "_spritegroup"): + for spr in sprite.sprites(): + if not self.has_internal(spr): + self.add_internal(spr, layer) + spr.add_internal(self) + elif not self.has_internal(sprite): + self.add_internal(sprite, layer) + sprite.add_internal(self) + + def remove_internal(self, sprite): + """Do not use this method directly. + + The group uses it to add a sprite. + + """ + self._spritelist.remove(sprite) + # these dirty rects are suboptimal for one frame + old_rect = self.spritedict[sprite] + if old_rect is not self._init_rect: + self.lostsprites.append(old_rect) # dirty rect + if hasattr(sprite, "rect"): + self.lostsprites.append(sprite.rect) # dirty rect + + del self.spritedict[sprite] + del self._spritelayers[sprite] + + def sprites(self): + """return a ordered list of sprites (first back, last top). + + LayeredUpdates.sprites(): return sprites + + """ + return list(self._spritelist) + + def draw(self, surface): + """draw all sprites in the right order onto the passed surface + + LayeredUpdates.draw(surface): return Rect_list + + """ + spritedict = self.spritedict + surface_blit = surface.blit + dirty = self.lostsprites + self.lostsprites = [] + dirty_append = dirty.append + init_rect = self._init_rect + for spr in self.sprites(): + rec = spritedict[spr] + newrect = surface_blit(spr.image, spr.rect) + if rec is init_rect: + dirty_append(newrect) + else: + if newrect.colliderect(rec): + dirty_append(newrect.union(rec)) + else: + dirty_append(newrect) + dirty_append(rec) + spritedict[spr] = newrect + return dirty + + def get_sprites_at(self, pos): + """return a list with all sprites at that position + + LayeredUpdates.get_sprites_at(pos): return colliding_sprites + + Bottom sprites are listed first; the top ones are listed last. + + """ + _sprites = self._spritelist + rect = Rect(pos, (1, 1)) + colliding_idx = rect.collidelistall(_sprites) + return [_sprites[i] for i in colliding_idx] + + def get_sprite(self, idx): + """return the sprite at the index idx from the groups sprites + + LayeredUpdates.get_sprite(idx): return sprite + + Raises IndexOutOfBounds if the idx is not within range. + + """ + return self._spritelist[idx] + + def remove_sprites_of_layer(self, layer_nr): + """remove all sprites from a layer and return them as a list + + LayeredUpdates.remove_sprites_of_layer(layer_nr): return sprites + + """ + sprites = self.get_sprites_from_layer(layer_nr) + self.remove(*sprites) + return sprites + + # layer methods + def layers(self): + """return a list of unique defined layers defined. + + LayeredUpdates.layers(): return layers + + """ + return sorted(set(self._spritelayers.values())) + + def change_layer(self, sprite, new_layer): + """change the layer of the sprite + + LayeredUpdates.change_layer(sprite, new_layer): return None + + The sprite must have been added to the renderer already. This is not + checked. + + """ + sprites = self._spritelist # speedup + sprites_layers = self._spritelayers # speedup + + sprites.remove(sprite) + sprites_layers.pop(sprite) + + # add the sprite at the right position + # bisect algorithmus + leng = len(sprites) + low = mid = 0 + high = leng - 1 + while low <= high: + mid = low + (high - low) // 2 + if sprites_layers[sprites[mid]] <= new_layer: + low = mid + 1 + else: + high = mid - 1 + # linear search to find final position + while mid < leng and sprites_layers[sprites[mid]] <= new_layer: + mid += 1 + sprites.insert(mid, sprite) + if hasattr(sprite, "_layer"): + setattr(sprite, "_layer", new_layer) + + # add layer info + sprites_layers[sprite] = new_layer + + def get_layer_of_sprite(self, sprite): + """return the layer that sprite is currently in + + If the sprite is not found, then it will return the default layer. + + """ + return self._spritelayers.get(sprite, self._default_layer) + + def get_top_layer(self): + """return the top layer + + LayeredUpdates.get_top_layer(): return layer + + """ + return self._spritelayers[self._spritelist[-1]] + + def get_bottom_layer(self): + """return the bottom layer + + LayeredUpdates.get_bottom_layer(): return layer + + """ + return self._spritelayers[self._spritelist[0]] + + def move_to_front(self, sprite): + """bring the sprite to front layer + + LayeredUpdates.move_to_front(sprite): return None + + Brings the sprite to front by changing the sprite layer to the top-most + layer. The sprite is added at the end of the list of sprites in that + top-most layer. + + """ + self.change_layer(sprite, self.get_top_layer()) + + def move_to_back(self, sprite): + """move the sprite to the bottom layer + + LayeredUpdates.move_to_back(sprite): return None + + Moves the sprite to the bottom layer by moving it to a new layer below + the current bottom layer. + + """ + self.change_layer(sprite, self.get_bottom_layer() - 1) + + def get_top_sprite(self): + """return the topmost sprite + + LayeredUpdates.get_top_sprite(): return Sprite + + """ + return self._spritelist[-1] + + def get_sprites_from_layer(self, layer): + """return all sprites from a layer ordered as they where added + + LayeredUpdates.get_sprites_from_layer(layer): return sprites + + Returns all sprites from a layer. The sprites are ordered in the + sequence that they where added. (The sprites are not removed from the + layer. + + """ + sprites = [] + sprites_append = sprites.append + sprite_layers = self._spritelayers + for spr in self._spritelist: + if sprite_layers[spr] == layer: + sprites_append(spr) + elif sprite_layers[spr] > layer: + # break after because no other will + # follow with same layer + break + return sprites + + def switch_layer(self, layer1_nr, layer2_nr): + """switch the sprites from layer1_nr to layer2_nr + + LayeredUpdates.switch_layer(layer1_nr, layer2_nr): return None + + The layers number must exist. This method does not check for the + existence of the given layers. + + """ + sprites1 = self.remove_sprites_of_layer(layer1_nr) + for spr in self.get_sprites_from_layer(layer2_nr): + self.change_layer(spr, layer1_nr) + self.add(layer=layer2_nr, *sprites1) + + +class LayeredDirty(LayeredUpdates): + """LayeredDirty Group is for DirtySprites; subclasses LayeredUpdates + + pygame.sprite.LayeredDirty(*spites, **kwargs): return LayeredDirty + + This group requires pygame.sprite.DirtySprite or any sprite that + has the following attributes: + image, rect, dirty, visible, blendmode (see doc of DirtySprite). + + It uses the dirty flag technique and is therefore faster than + pygame.sprite.RenderUpdates if you have many static sprites. It + also switches automatically between dirty rect updating and full + screen drawing, so you do no have to worry which would be faster. + + As with the pygame.sprite.Group, you can specify some additional attributes + through kwargs: + _use_update: True/False (default is False) + _default_layer: default layer where the sprites without a layer are + added + _time_threshold: threshold time for switching between dirty rect mode + and fullscreen mode; defaults to updating at 80 frames per second, + which is equal to 1000.0 / 80.0 + + New in pygame 1.8.0 + + """ + + def __init__(self, *sprites, **kwargs): + """initialize group. + + pygame.sprite.LayeredDirty(*spites, **kwargs): return LayeredDirty + + You can specify some additional attributes through kwargs: + _use_update: True/False (default is False) + _default_layer: default layer where the sprites without a layer are + added + _time_threshold: threshold time for switching between dirty rect + mode and fullscreen mode; defaults to updating at 80 frames per + second, which is equal to 1000.0 / 80.0 + + """ + LayeredUpdates.__init__(self, *sprites, **kwargs) + self._clip = None + + self._use_update = False + + self._time_threshold = 1000.0 / 80.0 # 1000.0 / fps + + self._bgd = None + for key, val in kwargs.items(): + if key in ["_use_update", "_time_threshold", "_default_layer"] and hasattr( + self, key + ): + setattr(self, key, val) + + def add_internal(self, sprite, layer=None): + """Do not use this method directly. + + It is used by the group to add a sprite internally. + + """ + # check if all needed attributes are set + if not hasattr(sprite, "dirty"): + raise AttributeError() + if not hasattr(sprite, "visible"): + raise AttributeError() + if not hasattr(sprite, "blendmode"): + raise AttributeError() + + if not isinstance(sprite, DirtySprite): + raise TypeError() + + if sprite.dirty == 0: # set it dirty if it is not + sprite.dirty = 1 + + LayeredUpdates.add_internal(self, sprite, layer) + + def draw( + self, surface, bgd=None + ): # noqa pylint: disable=arguments-differ; unable to change public interface + """draw all sprites in the right order onto the given surface + + LayeredDirty.draw(surface, bgd=None): return Rect_list + + You can pass the background too. If a self.bgd is already set to some + value that is not None, then the bgd argument has no effect. + + """ + # functions and classes assigned locally to speed up loops + orig_clip = surface.get_clip() + latest_clip = self._clip + if latest_clip is None: + latest_clip = orig_clip + + local_sprites = self._spritelist + local_old_rect = self.spritedict + local_update = self.lostsprites + rect_type = Rect + + surf_blit_func = surface.blit + if bgd is not None: + self._bgd = bgd + local_bgd = self._bgd + + surface.set_clip(latest_clip) + # ------- + # 0. decide whether to render with update or flip + start_time = get_ticks() + if self._use_update: # dirty rects mode + # 1. find dirty area on screen and put the rects into + # self.lostsprites still not happy with that part + self._find_dirty_area( + latest_clip, + local_old_rect, + rect_type, + local_sprites, + local_update, + local_update.append, + self._init_rect, + ) + # can it be done better? because that is an O(n**2) algorithm in + # worst case + + # clear using background + if local_bgd is not None: + for rec in local_update: + surf_blit_func(local_bgd, rec, rec) + + # 2. draw + self._draw_dirty_internal( + local_old_rect, rect_type, local_sprites, surf_blit_func, local_update + ) + local_ret = list(local_update) + else: # flip, full screen mode + if local_bgd is not None: + surf_blit_func(local_bgd, (0, 0)) + for spr in local_sprites: + if spr.visible: + local_old_rect[spr] = surf_blit_func( + spr.image, spr.rect, spr.source_rect, spr.blendmode + ) + # return only the part of the screen changed + local_ret = [rect_type(latest_clip)] + + # timing for switching modes + # How may a good threshold be found? It depends on the hardware. + end_time = get_ticks() + if end_time - start_time > self._time_threshold: + self._use_update = False + else: + self._use_update = True + + # emtpy dirty rects list + local_update[:] = [] + + # ------- + # restore original clip + surface.set_clip(orig_clip) + return local_ret + + @staticmethod + def _draw_dirty_internal(_old_rect, _rect, _sprites, _surf_blit, _update): + for spr in _sprites: + if spr.dirty < 1 and spr.visible: + # sprite not dirty; blit only the intersecting part + if spr.source_rect is not None: + # For possible future speed up, source_rect's data + # can be pre-fetched outside of this loop. + _spr_rect = _rect(spr.rect.topleft, spr.source_rect.size) + rect_offset_x = spr.source_rect[0] - _spr_rect[0] + rect_offset_y = spr.source_rect[1] - _spr_rect[1] + else: + _spr_rect = spr.rect + rect_offset_x = -_spr_rect[0] + rect_offset_y = -_spr_rect[1] + + _spr_rect_clip = _spr_rect.clip + + for idx in _spr_rect.collidelistall(_update): + # clip + clip = _spr_rect_clip(_update[idx]) + _surf_blit( + spr.image, + clip, + ( + clip[0] + rect_offset_x, + clip[1] + rect_offset_y, + clip[2], + clip[3], + ), + spr.blendmode, + ) + else: # dirty sprite + if spr.visible: + _old_rect[spr] = _surf_blit( + spr.image, spr.rect, spr.source_rect, spr.blendmode + ) + if spr.dirty == 1: + spr.dirty = 0 + + @staticmethod + def _find_dirty_area( + _clip, _old_rect, _rect, _sprites, _update, _update_append, init_rect + ): + for spr in _sprites: + if spr.dirty > 0: + # chose the right rect + if spr.source_rect: + _union_rect = _rect(spr.rect.topleft, spr.source_rect.size) + else: + _union_rect = _rect(spr.rect) + + _union_rect_collidelist = _union_rect.collidelist + _union_rect_union_ip = _union_rect.union_ip + i = _union_rect_collidelist(_update) + while i > -1: + _union_rect_union_ip(_update[i]) + del _update[i] + i = _union_rect_collidelist(_update) + _update_append(_union_rect.clip(_clip)) + + if _old_rect[spr] is not init_rect: + _union_rect = _rect(_old_rect[spr]) + _union_rect_collidelist = _union_rect.collidelist + _union_rect_union_ip = _union_rect.union_ip + i = _union_rect_collidelist(_update) + while i > -1: + _union_rect_union_ip(_update[i]) + del _update[i] + i = _union_rect_collidelist(_update) + _update_append(_union_rect.clip(_clip)) + + def clear(self, surface, bgd): + """use to set background + + Group.clear(surface, bgd): return None + + """ + self._bgd = bgd + + def repaint_rect(self, screen_rect): + """repaint the given area + + LayeredDirty.repaint_rect(screen_rect): return None + + screen_rect is in screen coordinates. + + """ + if self._clip: + self.lostsprites.append(screen_rect.clip(self._clip)) + else: + self.lostsprites.append(Rect(screen_rect)) + + def set_clip(self, screen_rect=None): + """clip the area where to draw; pass None (default) to reset the clip + + LayeredDirty.set_clip(screen_rect=None): return None + + """ + if screen_rect is None: + self._clip = pygame.display.get_surface().get_rect() + else: + self._clip = screen_rect + self._use_update = False + + def get_clip(self): + """get the area where drawing will occur + + LayeredDirty.get_clip(): return Rect + + """ + return self._clip + + def change_layer(self, sprite, new_layer): + """change the layer of the sprite + + LayeredUpdates.change_layer(sprite, new_layer): return None + + The sprite must have been added to the renderer already. This is not + checked. + + """ + LayeredUpdates.change_layer(self, sprite, new_layer) + if sprite.dirty == 0: + sprite.dirty = 1 + + def set_timing_treshold(self, time_ms): + """set the threshold in milliseconds + + set_timing_treshold(time_ms): return None + + Defaults to 1000.0 / 80.0. This means that the screen will be painted + using the flip method rather than the update method if the update + method is taking so long to update the screen that the frame rate falls + below 80 frames per second. + + Raises TypeError if time_ms is not int or float. + + """ + warn( + "This function will be removed, use set_timing_threshold function instead", + DeprecationWarning, + ) + self.set_timing_threshold(time_ms) + + def set_timing_threshold(self, time_ms): + """set the threshold in milliseconds + + set_timing_threshold(time_ms): return None + + Defaults to 1000.0 / 80.0. This means that the screen will be painted + using the flip method rather than the update method if the update + method is taking so long to update the screen that the frame rate falls + below 80 frames per second. + + Raises TypeError if time_ms is not int or float. + + """ + if isinstance(time_ms, (int, float)): + self._time_threshold = time_ms + else: + raise TypeError( + f"Expected numeric value, got {time_ms.__class__.__name__} instead" + ) + + +class GroupSingle(AbstractGroup): + """A group container that holds a single most recent item. + + This class works just like a regular group, but it only keeps a single + sprite in the group. Whatever sprite has been added to the group last will + be the only sprite in the group. + + You can access its one sprite as the .sprite attribute. Assigning to this + attribute will properly remove the old sprite and then add the new one. + + """ + + def __init__(self, sprite=None): + AbstractGroup.__init__(self) + self.__sprite = None + if sprite is not None: + self.add(sprite) + + def copy(self): + return GroupSingle(self.__sprite) + + def sprites(self): + if self.__sprite is not None: + return [self.__sprite] + return [] + + def add_internal(self, sprite, _=None): + if self.__sprite is not None: + self.__sprite.remove_internal(self) + self.remove_internal(self.__sprite) + self.__sprite = sprite + + def __nonzero__(self): + return self.__sprite is not None + + __bool__ = __nonzero__ + + def _get_sprite(self): + return self.__sprite + + def _set_sprite(self, sprite): + self.add_internal(sprite) + sprite.add_internal(self) + return sprite + + @property + def sprite(self): + """ + Property for the single sprite contained in this group + + :return: The sprite. + """ + return self._get_sprite() + + @sprite.setter + def sprite(self, sprite_to_set): + self._set_sprite(sprite_to_set) + + def remove_internal(self, sprite): + if sprite is self.__sprite: + self.__sprite = None + if sprite in self.spritedict: + AbstractGroup.remove_internal(self, sprite) + + def has_internal(self, sprite): + return self.__sprite is sprite + + # Optimizations... + def __contains__(self, sprite): + return self.__sprite is sprite + + +# Some different collision detection functions that could be used. +def collide_rect(left, right): + """collision detection between two sprites, using rects. + + pygame.sprite.collide_rect(left, right): return bool + + Tests for collision between two sprites. Uses the pygame.Rect colliderect + function to calculate the collision. It is intended to be passed as a + collided callback function to the *collide functions. Sprites must have + "rect" attributes. + + New in pygame 1.8.0 + + """ + return left.rect.colliderect(right.rect) + + +class collide_rect_ratio: # noqa pylint: disable=invalid-name; this is a function-like class + """A callable class that checks for collisions using scaled rects + + The class checks for collisions between two sprites using a scaled version + of the sprites' rects. Is created with a ratio; the instance is then + intended to be passed as a collided callback function to the *collide + functions. + + New in pygame 1.8.1 + + """ + + def __init__(self, ratio): + """create a new collide_rect_ratio callable + + Ratio is expected to be a floating point value used to scale + the underlying sprite rect before checking for collisions. + + """ + self.ratio = ratio + + def __repr__(self): + """ + Turn the class into a string. + """ + # pylint: disable=consider-using-f-string + return "<{klass} @{id:x} {attrs}>".format( + klass=self.__class__.__name__, + id=id(self) & 0xFFFFFF, + attrs=" ".join("{}={!r}".format(k, v) for k, v in self.__dict__.items()), + ) + + def __call__(self, left, right): + """detect collision between two sprites using scaled rects + + pygame.sprite.collide_rect_ratio(ratio)(left, right): return bool + + Tests for collision between two sprites. Uses the pygame.Rect + colliderect function to calculate the collision after scaling the rects + by the stored ratio. Sprites must have "rect" attributes. + + """ + + ratio = self.ratio + + leftrect = left.rect + width = leftrect.width + height = leftrect.height + leftrect = leftrect.inflate(width * ratio - width, height * ratio - height) + + rightrect = right.rect + width = rightrect.width + height = rightrect.height + rightrect = rightrect.inflate(width * ratio - width, height * ratio - height) + + return leftrect.colliderect(rightrect) + + +def collide_circle(left, right): + """detect collision between two sprites using circles + + pygame.sprite.collide_circle(left, right): return bool + + Tests for collision between two sprites by testing whether two circles + centered on the sprites overlap. If the sprites have a "radius" attribute, + then that radius is used to create the circle; otherwise, a circle is + created that is big enough to completely enclose the sprite's rect as + given by the "rect" attribute. This function is intended to be passed as + a collided callback function to the *collide functions. Sprites must have a + "rect" and an optional "radius" attribute. + + New in pygame 1.8.0 + + """ + + xdistance = left.rect.centerx - right.rect.centerx + ydistance = left.rect.centery - right.rect.centery + distancesquared = xdistance ** 2 + ydistance ** 2 + + try: + leftradius = left.radius + except AttributeError: + leftrect = left.rect + # approximating the radius of a square by using half of the diagonal, + # might give false positives (especially if its a long small rect) + leftradius = 0.5 * ((leftrect.width ** 2 + leftrect.height ** 2) ** 0.5) + # store the radius on the sprite for next time + left.radius = leftradius + + try: + rightradius = right.radius + except AttributeError: + rightrect = right.rect + # approximating the radius of a square by using half of the diagonal + # might give false positives (especially if its a long small rect) + rightradius = 0.5 * ((rightrect.width ** 2 + rightrect.height ** 2) ** 0.5) + # store the radius on the sprite for next time + right.radius = rightradius + return distancesquared <= (leftradius + rightradius) ** 2 + + +class collide_circle_ratio( + object +): # noqa pylint: disable=invalid-name; this is a function-like class + """detect collision between two sprites using scaled circles + + This callable class checks for collisions between two sprites using a + scaled version of a sprite's radius. It is created with a ratio as the + argument to the constructor. The instance is then intended to be passed as + a collided callback function to the *collide functions. + + New in pygame 1.8.1 + + """ + + def __init__(self, ratio): + """creates a new collide_circle_ratio callable instance + + The given ratio is expected to be a floating point value used to scale + the underlying sprite radius before checking for collisions. + + When the ratio is ratio=1.0, then it behaves exactly like the + collide_circle method. + + """ + self.ratio = ratio + + def __repr__(self): + """ + Turn the class into a string. + """ + # pylint: disable=consider-using-f-string + return "<{klass} @{id:x} {attrs}>".format( + klass=self.__class__.__name__, + id=id(self) & 0xFFFFFF, + attrs=" ".join("{}={!r}".format(k, v) for k, v in self.__dict__.items()), + ) + + def __call__(self, left, right): + """detect collision between two sprites using scaled circles + + pygame.sprite.collide_circle_radio(ratio)(left, right): return bool + + Tests for collision between two sprites by testing whether two circles + centered on the sprites overlap after scaling the circle's radius by + the stored ratio. If the sprites have a "radius" attribute, that is + used to create the circle; otherwise, a circle is created that is big + enough to completely enclose the sprite's rect as given by the "rect" + attribute. Intended to be passed as a collided callback function to the + *collide functions. Sprites must have a "rect" and an optional "radius" + attribute. + + """ + + ratio = self.ratio + xdistance = left.rect.centerx - right.rect.centerx + ydistance = left.rect.centery - right.rect.centery + distancesquared = xdistance ** 2 + ydistance ** 2 + + try: + leftradius = left.radius + except AttributeError: + leftrect = left.rect + leftradius = 0.5 * ((leftrect.width ** 2 + leftrect.height ** 2) ** 0.5) + # store the radius on the sprite for next time + left.radius = leftradius + leftradius *= ratio + + try: + rightradius = right.radius + except AttributeError: + rightrect = right.rect + rightradius = 0.5 * ((rightrect.width ** 2 + rightrect.height ** 2) ** 0.5) + # store the radius on the sprite for next time + right.radius = rightradius + rightradius *= ratio + + return distancesquared <= (leftradius + rightradius) ** 2 + + +def collide_mask(left, right): + """collision detection between two sprites, using masks. + + pygame.sprite.collide_mask(SpriteLeft, SpriteRight): bool + + Tests for collision between two sprites by testing if their bitmasks + overlap. If the sprites have a "mask" attribute, that is used as the mask; + otherwise, a mask is created from the sprite image. Intended to be passed + as a collided callback function to the *collide functions. Sprites must + have a "rect" and an optional "mask" attribute. + + New in pygame 1.8.0 + + """ + xoffset = right.rect[0] - left.rect[0] + yoffset = right.rect[1] - left.rect[1] + try: + leftmask = left.mask + except AttributeError: + leftmask = from_surface(left.image) + try: + rightmask = right.mask + except AttributeError: + rightmask = from_surface(right.image) + return leftmask.overlap(rightmask, (xoffset, yoffset)) + + +def spritecollide(sprite, group, dokill, collided=None): + """find Sprites in a Group that intersect another Sprite + + pygame.sprite.spritecollide(sprite, group, dokill, collided=None): + return Sprite_list + + Return a list containing all Sprites in a Group that intersect with another + Sprite. Intersection is determined by comparing the Sprite.rect attribute + of each Sprite. + + The dokill argument is a bool. If set to True, all Sprites that collide + will be removed from the Group. + + The collided argument is a callback function used to calculate if two + sprites are colliding. it should take two sprites as values, and return a + bool value indicating if they are colliding. If collided is not passed, all + sprites must have a "rect" value, which is a rectangle of the sprite area, + which will be used to calculate the collision. + + """ + # pull the default collision function in as a local variable outside + # the loop as this makes the loop run faster + default_sprite_collide_func = sprite.rect.colliderect + + if dokill: + + crashed = [] + append = crashed.append + + for group_sprite in group.sprites(): + if collided: + if collided(sprite, group_sprite): + group_sprite.kill() + append(group_sprite) + else: + if default_sprite_collide_func(group_sprite.rect): + group_sprite.kill() + append(group_sprite) + + return crashed + + if collided: + return [ + group_sprite for group_sprite in group if collided(sprite, group_sprite) + ] + + return [ + group_sprite + for group_sprite in group + if default_sprite_collide_func(group_sprite.rect) + ] + + +def groupcollide(groupa, groupb, dokilla, dokillb, collided=None): + """detect collision between a group and another group + + pygame.sprite.groupcollide(groupa, groupb, dokilla, dokillb): + return dict + + Given two groups, this will find the intersections between all sprites in + each group. It returns a dictionary of all sprites in the first group that + collide. The value for each item in the dictionary is a list of the sprites + in the second group it collides with. The two dokill arguments control if + the sprites from either group will be automatically removed from all + groups. Collided is a callback function used to calculate if two sprites + are colliding. it should take two sprites as values, and return a bool + value indicating if they are colliding. If collided is not passed, all + sprites must have a "rect" value, which is a rectangle of the sprite area + that will be used to calculate the collision. + + """ + crashed = {} + # pull the collision function in as a local variable outside + # the loop as this makes the loop run faster + sprite_collide_func = spritecollide + if dokilla: + for group_a_sprite in groupa.sprites(): + collision = sprite_collide_func(group_a_sprite, groupb, dokillb, collided) + if collision: + crashed[group_a_sprite] = collision + group_a_sprite.kill() + else: + for group_a_sprite in groupa: + collision = sprite_collide_func(group_a_sprite, groupb, dokillb, collided) + if collision: + crashed[group_a_sprite] = collision + return crashed + + +def spritecollideany(sprite, group, collided=None): + """finds any sprites in a group that collide with the given sprite + + pygame.sprite.spritecollideany(sprite, group): return sprite + + Given a sprite and a group of sprites, this will return return any single + sprite that collides with with the given sprite. If there are no + collisions, then this returns None. + + If you don't need all the features of the spritecollide function, this + function will be a bit quicker. + + Collided is a callback function used to calculate if two sprites are + colliding. It should take two sprites as values and return a bool value + indicating if they are colliding. If collided is not passed, then all + sprites must have a "rect" value, which is a rectangle of the sprite area, + which will be used to calculate the collision. + + + """ + # pull the default collision function in as a local variable outside + # the loop as this makes the loop run faster + default_sprite_collide_func = sprite.rect.colliderect + + if collided is not None: + for group_sprite in group: + if collided(sprite, group_sprite): + return group_sprite + else: + # Special case old behaviour for speed. + for group_sprite in group: + if default_sprite_collide_func(group_sprite.rect): + return group_sprite + return None diff --git a/venv/Lib/site-packages/pygame/sprite.pyi b/venv/Lib/site-packages/pygame/sprite.pyi new file mode 100644 index 0000000..4e2f0fd --- /dev/null +++ b/venv/Lib/site-packages/pygame/sprite.pyi @@ -0,0 +1,152 @@ +from typing import ( + Any, + Callable, + Dict, + Iterable, + Iterator, + List, + Optional, + Sequence, + SupportsFloat, + Tuple, + Union, +) + +from pygame.rect import Rect +from pygame.surface import Surface + +from ._common import _CanBeRect + +# Some functions violate Liskov substitution principle so mypy will throw errors for this file, but this are the +# best type hints I could do + +class Sprite: + image: Optional[Surface] = None + rect: Optional[Rect] = None + def __init__(self, *groups: AbstractGroup) -> None: ... + def update(self, *args: Any, **kwargs: Any) -> None: ... + def add(self, *groups: AbstractGroup) -> None: ... + def remove(self, *groups: AbstractGroup) -> None: ... + def kill(self) -> None: ... + def alive(self) -> bool: ... + def groups(self) -> List[AbstractGroup]: ... + +class DirtySprite(Sprite): + dirty: int + blendmode: int + source_rect: Rect + visible: int + _layer: int + def _set_visible(self, value: int) -> None: ... + def _get_visible(self) -> int: ... + +class AbstractGroup: + spritedict: Dict[Sprite, Rect] + lostsprites: List[int] # I think + def __init__(self) -> None: ... + def __len__(self) -> int: ... + def __iter__(self) -> Iterator[Sprite]: ... + def copy(self) -> AbstractGroup: ... + def sprites(self) -> List[Sprite]: ... + def add( + self, + *sprites: Union[Sprite, AbstractGroup, Iterable[Union[Sprite, AbstractGroup]]] + ) -> None: ... + def remove(self, *sprites: Sprite) -> None: ... + def has(self, *sprites: Sprite) -> bool: ... + def update(self, *args: Any, **kwargs: Any) -> None: ... + def draw(self, surface: Surface) -> List[Rect]: ... + def clear(self, surface_dest: Surface, background: Surface) -> None: ... + def empty(self) -> None: ... + +class Group(AbstractGroup): + def __init__(self, *sprites: Union[Sprite, Sequence[Sprite]]) -> None: ... + def copy(self) -> Group: ... + +class RenderPlain(Group): + def copy(self) -> RenderPlain: ... + +class RenderClear(Group): + def copy(self) -> RenderClear: ... + +class RenderUpdates(Group): + def copy(self) -> RenderUpdates: ... + def draw(self, surface: Surface) -> List[Rect]: ... + +class OrderedUpdates(RenderUpdates): + def copy(self) -> OrderedUpdates: ... + +class LayeredUpdates(AbstractGroup): + def __init__(self, *sprites: Sprite, **kwargs: Any) -> None: ... + def copy(self) -> LayeredUpdates: ... + def add(self, *sprites: Sprite, **kwargs: Any) -> None: ... + def draw(self, surface: Surface) -> List[Rect]: ... + def get_sprites_at( + self, pos: Union[Tuple[int, int], List[int]] + ) -> List[Sprite]: ... + def get_sprite(self, idx: int) -> Sprite: ... + def remove_sprites_of_layer(self, layer_nr: int) -> List[Sprite]: ... + def layers(self) -> List[int]: ... + def change_layer(self, sprite: Sprite, new_layer: int) -> None: ... + def get_layer_of_sprite(self, sprite: Sprite) -> int: ... + def get_top_layer(self) -> int: ... + def get_bottom_layer(self) -> int: ... + def move_to_front(self, sprite: Sprite) -> None: ... + def move_to_back(self, sprite: Sprite) -> None: ... + def get_top_sprite(self) -> Sprite: ... + def get_sprites_from_layer(self, layer: int) -> List[Sprite]: ... + def switch_layer(self, layer1_nr: int, layer2_nr: int) -> None: ... + +class LayeredDirty(LayeredUpdates): + def __init__(self, *sprites: DirtySprite, **kwargs: Any) -> None: ... + def copy(self) -> LayeredDirty: ... + def draw(self, surface: Surface, bgd: Optional[Surface] = None) -> List[Rect]: ... + def clear(self, surface: Surface, bgd: Surface) -> None: ... + def repaint_rect(self, screen_rect: _CanBeRect) -> None: ... + def set_clip(self, screen_rect: Optional[_CanBeRect] = None) -> None: ... + def get_clip(self) -> Rect: ... + def set_timing_treshold( + self, time_ms: SupportsFloat + ) -> None: ... # This actually accept any value + def set_timing_threshold( + self, time_ms: SupportsFloat + ) -> None: ... # This actually accept any value + +class GroupSingle(AbstractGroup): + sprite: Sprite + def __init__(self, sprite: Optional[Sprite] = None) -> None: ... + def copy(self) -> GroupSingle: ... + +def spritecollide( + sprite: Sprite, + group: AbstractGroup, + dokill: bool, + collided: Optional[Callable[[Sprite, Sprite], bool]] = None, +) -> List[Sprite]: ... +def collide_rect(left: Sprite, right: Sprite) -> bool: ... + +class collide_rect_ratio: + ratio: float + def __init__(self, ratio: float) -> None: ... + def __call__(self, left: Sprite, right: Sprite) -> bool: ... + +def collide_circle(left: Sprite, right: Sprite) -> bool: ... + +class collide_circle_ratio: + ratio: float + def __init__(self, ratio: float) -> None: ... + def __call__(self, left: Sprite, right: Sprite) -> bool: ... + +def collide_mask(sprite1: Sprite, sprite2: Sprite) -> Tuple[int, int]: ... +def groupcollide( + group1: AbstractGroup, + group2: AbstractGroup, + dokill: bool, + dokill2: bool, + collided: Optional[Callable[[Sprite, Sprite], bool]] = None, +) -> Dict[Sprite, Sprite]: ... +def spritecollideany( + sprite: Sprite, + group: AbstractGroup, + collided: Optional[Callable[[Sprite, Sprite], bool]] = None, +) -> Sprite: ... diff --git a/venv/Lib/site-packages/pygame/surface.cp39-win_amd64.pyd b/venv/Lib/site-packages/pygame/surface.cp39-win_amd64.pyd new file mode 100644 index 0000000000000000000000000000000000000000..569b82fdcf511adafa918f2d192e4581c46bf6cd GIT binary patch literal 220672 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 iDu# None: ... + @overload + def __init__( + self, + size: _Coordinate, + flags: int = ..., + surface: Surface = ..., + ) -> None: ... + def blit( + self, + source: Surface, + dest: Union[_Coordinate, _CanBeRect], + area: Optional[_CanBeRect] = ..., + special_flags: int = ..., + ) -> Rect: ... + def blits( + self, + blit_sequence: Sequence[ + Union[ + Tuple[Surface, Union[_Coordinate, _CanBeRect]], + Tuple[Surface, Union[_Coordinate, _CanBeRect], Union[_CanBeRect, int]], + Tuple[Surface, Union[_Coordinate, _CanBeRect], _CanBeRect, int], + ] + ], + doreturn: Union[int, bool] = 1, + ) -> Union[List[Rect], None]: ... + @overload + def convert(self, surface: Surface) -> Surface: ... + @overload + def convert(self, depth: int, flags: int = ...) -> Surface: ... + @overload + def convert(self, masks: _ColorValue, flags: int = ...) -> Surface: ... + @overload + def convert(self) -> Surface: ... + @overload + def convert_alpha(self, surface: Surface) -> Surface: ... + @overload + def convert_alpha(self) -> Surface: ... + def copy(self) -> Surface: ... + def fill( + self, + color: _ColorValue, + rect: Optional[_CanBeRect] = ..., + special_flags: int = ..., + ) -> Rect: ... + def scroll(self, dx: int = ..., dy: int = ...) -> None: ... + @overload + def set_colorkey(self, color: _ColorValue, flags: int = ...) -> None: ... + @overload + def set_colorkey(self, color: None) -> None: ... + def get_colorkey(self) -> Optional[_RgbaOutput]: ... + @overload + def set_alpha(self, value: int, flags: int = ...) -> None: ... + @overload + def set_alpha(self, value: None) -> None: ... + def get_alpha(self) -> Optional[int]: ... + def lock(self) -> None: ... + def unlock(self) -> None: ... + def mustlock(self) -> bool: ... + def get_locked(self) -> bool: ... + def get_locks(self) -> Tuple[Any, ...]: ... + def get_at(self, x_y: Sequence[int]) -> _RgbaOutput: ... + def set_at(self, x_y: Sequence[int], color: _ColorValue) -> None: ... + def get_at_mapped(self, x_y: Sequence[int]) -> int: ... + def get_palette(self) -> List[_RgbaOutput]: ... + def get_palette_at(self, index: int) -> _RgbaOutput: ... + def set_palette(self, palette: List[_ColorValue]) -> None: ... + def set_palette_at(self, index: int, color: _ColorValue) -> None: ... + def map_rgb(self, color: _ColorValue) -> int: ... + def unmap_rgb(self, mapped_int: int) -> _RgbaOutput: ... + def set_clip(self, rect: Optional[_CanBeRect]) -> None: ... + def get_clip(self) -> Rect: ... + @overload + def subsurface(self, rect: Union[_CanBeRect, Rect]) -> Surface: ... + @overload + def subsurface( + self, + left_top: Union[List[float], Tuple[float, float], Vector2], + width_height: Union[List[float], Tuple[float, float], Vector2], + ) -> Surface: ... + @overload + def subsurface( + self, left: float, top: float, width: float, height: float + ) -> Surface: ... + def get_parent(self) -> Surface: ... + def get_abs_parent(self) -> Surface: ... + def get_offset(self) -> Tuple[int, int]: ... + def get_abs_offset(self) -> Tuple[int, int]: ... + def get_size(self) -> Tuple[int, int]: ... + def get_width(self) -> int: ... + def get_height(self) -> int: ... + def get_rect(self, **kwargs: Any) -> Rect: ... + def get_bitsize(self) -> int: ... + def get_bytesize(self) -> int: ... + def get_flags(self) -> int: ... + def get_pitch(self) -> int: ... + def get_masks(self) -> _RgbaOutput: ... + def set_masks(self, color: _ColorValue) -> None: ... + def get_shifts(self) -> _RgbaOutput: ... + def set_shifts(self, color: _ColorValue) -> None: ... + def get_losses(self) -> _RgbaOutput: ... + def get_bounding_rect(self, min_alpha: int = ...) -> Rect: ... + def get_view(self, kind: Text = ...) -> BufferProxy: ... + def get_buffer(self) -> BufferProxy: ... diff --git a/venv/Lib/site-packages/pygame/surfarray.py b/venv/Lib/site-packages/pygame/surfarray.py new file mode 100644 index 0000000..70653fd --- /dev/null +++ b/venv/Lib/site-packages/pygame/surfarray.py @@ -0,0 +1,447 @@ +## pygame - Python Game Library +## Copyright (C) 2007 Marcus von Appen +## +## This library is free software; you can redistribute it and/or +## modify it under the terms of the GNU Library General Public +## License as published by the Free Software Foundation; either +## version 2 of the License, or (at your option) any later version. +## +## This library is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## Library General Public License for more details. +## +## You should have received a copy of the GNU Library General Public +## License along with this library; if not, write to the Free +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +## +## Marcus von Appen +## mva@sysfault.org + +"""pygame module for accessing surface pixel data using array interfaces + +Functions to convert between NumPy arrays and Surface objects. This module +will only be functional when pygame can use the external NumPy package. +If NumPy can't be imported, surfarray becomes a MissingModule object. + +Every pixel is stored as a single integer value to represent the red, +green, and blue colors. The 8bit images use a value that looks into a +colormap. Pixels with higher depth use a bit packing process to place +three or four values into a single number. + +The arrays are indexed by the X axis first, followed by the Y +axis. Arrays that treat the pixels as a single integer are referred to +as 2D arrays. This module can also separate the red, green, and blue +color values into separate indices. These types of arrays are referred +to as 3D arrays, and the last index is 0 for red, 1 for green, and 2 for +blue. +""" + + +from pygame.pixelcopy import ( + array_to_surface, + surface_to_array, + map_array as pix_map_array, + make_surface as pix_make_surface, +) +import numpy +from numpy import ( + array as numpy_array, + empty as numpy_empty, + uint32 as numpy_uint32, + ndarray as numpy_ndarray, +) + +import warnings # will be removed in the future + + +# float96 not available on all numpy versions. +numpy_floats = [] +for type_name in "float32 float64 float96".split(): + if hasattr(numpy, type_name): + numpy_floats.append(getattr(numpy, type_name)) +# Added below due to deprecation of numpy.float. See issue #2814 +numpy_floats.append(float) + +# Pixel sizes corresponding to NumPy supported integer sizes, and therefore +# permissible for 2D reference arrays. +_pixel2d_bitdepths = {8, 16, 32} + + +__all__ = [ + "array2d", + "array3d", + "array_alpha", + "array_blue", + "array_colorkey", + "array_green", + "array_red", + "array_to_surface", + "blit_array", + "get_arraytype", + "get_arraytypes", + "make_surface", + "map_array", + "pixels2d", + "pixels3d", + "pixels_alpha", + "pixels_blue", + "pixels_green", + "pixels_red", + "surface_to_array", + "use_arraytype", +] + + +def blit_array(surface, array): + """pygame.surfarray.blit_array(Surface, array): return None + + Blit directly from a array values. + + Directly copy values from an array into a Surface. This is faster than + converting the array into a Surface and blitting. The array must be the + same dimensions as the Surface and will completely replace all pixel + values. Only integer, ascii character and record arrays are accepted. + + This function will temporarily lock the Surface as the new values are + copied. + """ + if isinstance(array, numpy_ndarray) and array.dtype in numpy_floats: + array = array.round(0).astype(numpy_uint32) + return array_to_surface(surface, array) + + +def make_surface(array): + """pygame.surfarray.make_surface (array): return Surface + + Copy an array to a new surface. + + Create a new Surface that best resembles the data and format on the + array. The array can be 2D or 3D with any sized integer values. + """ + if isinstance(array, numpy_ndarray) and array.dtype in numpy_floats: + array = array.round(0).astype(numpy_uint32) + return pix_make_surface(array) + + +def array2d(surface): + """pygame.surfarray.array2d(Surface): return array + + copy pixels into a 2d array + + Copy the pixels from a Surface into a 2D array. The bit depth of the + surface will control the size of the integer values, and will work + for any type of pixel format. + + This function will temporarily lock the Surface as pixels are copied + (see the Surface.lock - lock the Surface memory for pixel access + method). + """ + bpp = surface.get_bytesize() + try: + dtype = (numpy.uint8, numpy.uint16, numpy.int32, numpy.int32)[bpp - 1] + except IndexError: + raise ValueError(f"unsupported bit depth {bpp * 8} for 2D array") + size = surface.get_size() + array = numpy.empty(size, dtype) + surface_to_array(array, surface) + return array + + +def pixels2d(surface): + """pygame.surfarray.pixels2d(Surface): return array + + reference pixels into a 2d array + + Create a new 2D array that directly references the pixel values in a + Surface. Any changes to the array will affect the pixels in the + Surface. This is a fast operation since no data is copied. + + Pixels from a 24-bit Surface cannot be referenced, but all other + Surface bit depths can. + + The Surface this references will remain locked for the lifetime of + the array (see the Surface.lock - lock the Surface memory for pixel + access method). + """ + if surface.get_bitsize() not in _pixel2d_bitdepths: + raise ValueError("unsupport bit depth for 2D reference array") + try: + return numpy_array(surface.get_view("2"), copy=False) + except (ValueError, TypeError): + raise ValueError( + f"bit depth {surface.get_bitsize()} unsupported for 2D reference array" + ) + + +def array3d(surface): + """pygame.surfarray.array3d(Surface): return array + + copy pixels into a 3d array + + Copy the pixels from a Surface into a 3D array. The bit depth of the + surface will control the size of the integer values, and will work + for any type of pixel format. + + This function will temporarily lock the Surface as pixels are copied + (see the Surface.lock - lock the Surface memory for pixel access + method). + """ + width, height = surface.get_size() + array = numpy.empty((width, height, 3), numpy.uint8) + surface_to_array(array, surface) + return array + + +def pixels3d(surface): + """pygame.surfarray.pixels3d(Surface): return array + + reference pixels into a 3d array + + Create a new 3D array that directly references the pixel values in a + Surface. Any changes to the array will affect the pixels in the + Surface. This is a fast operation since no data is copied. + + This will only work on Surfaces that have 24-bit or 32-bit + formats. Lower pixel formats cannot be referenced. + + The Surface this references will remain locked for the lifetime of + the array (see the Surface.lock - lock the Surface memory for pixel + access method). + """ + return numpy_array(surface.get_view("3"), copy=False) + + +def array_alpha(surface): + """pygame.surfarray.array_alpha(Surface): return array + + copy pixel alphas into a 2d array + + Copy the pixel alpha values (degree of transparency) from a Surface + into a 2D array. This will work for any type of Surface + format. Surfaces without a pixel alpha will return an array with all + opaque values. + + This function will temporarily lock the Surface as pixels are copied + (see the Surface.lock - lock the Surface memory for pixel access + method). + """ + size = surface.get_size() + array = numpy.empty(size, numpy.uint8) + surface_to_array(array, surface, "A") + return array + + +def pixels_alpha(surface): + """pygame.surfarray.pixels_alpha(Surface): return array + + reference pixel alphas into a 2d array + + Create a new 2D array that directly references the alpha values + (degree of transparency) in a Surface. Any changes to the array will + affect the pixels in the Surface. This is a fast operation since no + data is copied. + + This can only work on 32-bit Surfaces with a per-pixel alpha value. + + The Surface this array references will remain locked for the + lifetime of the array. + """ + return numpy.array(surface.get_view("A"), copy=False) + + +def pixels_red(surface): + """pygame.surfarray.pixels_red(Surface): return array + + Reference pixel red into a 2d array. + + Create a new 2D array that directly references the red values + in a Surface. Any changes to the array will affect the pixels + in the Surface. This is a fast operation since no data is copied. + + This can only work on 24-bit or 32-bit Surfaces. + + The Surface this array references will remain locked for the + lifetime of the array. + """ + return numpy.array(surface.get_view("R"), copy=False) + + +def array_red(surface): + """pygame.surfarray.array_red(Surface): return array + + copy pixel red into a 2d array + + Copy the pixel red values from a Surface into a 2D array. This will work + for any type of Surface format. + + This function will temporarily lock the Surface as pixels are copied + (see the Surface.lock - lock the Surface memory for pixel access + method). + """ + size = surface.get_size() + array = numpy.empty(size, numpy.uint8) + surface_to_array(array, surface, "R") + return array + + +def pixels_green(surface): + """pygame.surfarray.pixels_green(Surface): return array + + Reference pixel green into a 2d array. + + Create a new 2D array that directly references the green values + in a Surface. Any changes to the array will affect the pixels + in the Surface. This is a fast operation since no data is copied. + + This can only work on 24-bit or 32-bit Surfaces. + + The Surface this array references will remain locked for the + lifetime of the array. + """ + return numpy.array(surface.get_view("G"), copy=False) + + +def array_green(surface): + """pygame.surfarray.array_green(Surface): return array + + copy pixel green into a 2d array + + Copy the pixel green values from a Surface into a 2D array. This will work + for any type of Surface format. + + This function will temporarily lock the Surface as pixels are copied + (see the Surface.lock - lock the Surface memory for pixel access + method). + """ + size = surface.get_size() + array = numpy.empty(size, numpy.uint8) + surface_to_array(array, surface, "G") + return array + + +def pixels_blue(surface): + """pygame.surfarray.pixels_blue(Surface): return array + + Reference pixel blue into a 2d array. + + Create a new 2D array that directly references the blue values + in a Surface. Any changes to the array will affect the pixels + in the Surface. This is a fast operation since no data is copied. + + This can only work on 24-bit or 32-bit Surfaces. + + The Surface this array references will remain locked for the + lifetime of the array. + """ + return numpy.array(surface.get_view("B"), copy=False) + + +def array_blue(surface): + """pygame.surfarray.array_blue(Surface): return array + + copy pixel blue into a 2d array + + Copy the pixel blue values from a Surface into a 2D array. This will work + for any type of Surface format. + + This function will temporarily lock the Surface as pixels are copied + (see the Surface.lock - lock the Surface memory for pixel access + method). + """ + size = surface.get_size() + array = numpy.empty(size, numpy.uint8) + surface_to_array(array, surface, "B") + return array + + +def array_colorkey(surface): + """pygame.surfarray.array_colorkey(Surface): return array + + copy the colorkey values into a 2d array + + Create a new array with the colorkey transparency value from each + pixel. If the pixel matches the colorkey it will be fully + tranparent; otherwise it will be fully opaque. + + This will work on any type of Surface format. If the image has no + colorkey a solid opaque array will be returned. + + This function will temporarily lock the Surface as pixels are + copied. + """ + size = surface.get_size() + array = numpy.empty(size, numpy.uint8) + surface_to_array(array, surface, "C") + return array + + +def map_array(surface, array): + """pygame.surfarray.map_array(Surface, array3d): return array2d + + map a 3d array into a 2d array + + Convert a 3D array into a 2D array. This will use the given Surface + format to control the conversion. + + Note: arrays do not need to be 3D, as long as the minor axis has + three elements giving the component colours, any array shape can be + used (for example, a single colour can be mapped, or an array of + colours). The array shape is limited to eleven dimensions maximum, + including the three element minor axis. + """ + if array.ndim == 0: + raise ValueError("array must have at least 1 dimension") + shape = array.shape + if shape[-1] != 3: + raise ValueError("array must be a 3d array of 3-value color data") + target = numpy_empty(shape[:-1], numpy.int32) + pix_map_array(target, array, surface) + return target + + +def use_arraytype(arraytype): + """pygame.surfarray.use_arraytype(arraytype): return None + + DEPRECATED - only numpy arrays are now supported. + """ + warnings.warn( + DeprecationWarning( + "only numpy arrays are now supported, " + "this function will be removed in a " + "future version of the module" + ) + ) + arraytype = arraytype.lower() + if arraytype != "numpy": + raise ValueError("invalid array type") + + +def get_arraytype(): + """pygame.surfarray.get_arraytype(): return str + + DEPRECATED - only numpy arrays are now supported. + """ + warnings.warn( + DeprecationWarning( + "only numpy arrays are now supported, " + "this function will be removed in a " + "future version of the module" + ) + ) + return "numpy" + + +def get_arraytypes(): + """pygame.surfarray.get_arraytypes(): return tuple + + DEPRECATED - only numpy arrays are now supported. + """ + warnings.warn( + DeprecationWarning( + "only numpy arrays are now supported, " + "this function will be removed in a " + "future version of the module" + ) + ) + return ("numpy",) diff --git a/venv/Lib/site-packages/pygame/surfarray.pyi b/venv/Lib/site-packages/pygame/surfarray.pyi new file mode 100644 index 0000000..33d7dbb --- /dev/null +++ b/venv/Lib/site-packages/pygame/surfarray.pyi @@ -0,0 +1,25 @@ +from typing import Tuple + +import numpy + +from pygame.surface import Surface + +def array2d(surface: Surface) -> numpy.ndarray: ... +def pixels2d(surface: Surface) -> numpy.ndarray: ... +def array3d(surface: Surface) -> numpy.ndarray: ... +def pixels3d(surface: Surface) -> numpy.ndarray: ... +def array_alpha(surface: Surface) -> numpy.ndarray: ... +def pixels_alpha(surface: Surface) -> numpy.ndarray: ... +def array_red(surface: Surface) -> numpy.ndarray: ... +def pixels_red(surface: Surface) -> numpy.ndarray: ... +def array_green(surface: Surface) -> numpy.ndarray: ... +def pixels_green(surface: Surface) -> numpy.ndarray: ... +def array_blue(surface: Surface) -> numpy.ndarray: ... +def pixels_blue(surface: Surface) -> numpy.ndarray: ... +def array_colorkey(surface: Surface) -> numpy.ndarray: ... +def make_surface(array: numpy.ndarray) -> Surface: ... +def blit_array(surface: Surface, array: numpy.ndarray) -> None: ... +def map_array(surface: Surface, array3d: numpy.ndarray) -> numpy.ndarray: ... +def use_arraytype(arraytype: str) -> None: ... +def get_arraytype() -> str: ... +def get_arraytypes() -> Tuple[str]: ... diff --git a/venv/Lib/site-packages/pygame/surflock.cp39-win_amd64.pyd b/venv/Lib/site-packages/pygame/surflock.cp39-win_amd64.pyd new file mode 100644 index 0000000000000000000000000000000000000000..9e4d48e2fd45fe408006df4b20d20c4436b359a5 GIT binary patch literal 13824 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 RZr5(l?tg19{mTyi{{V=AlCb~) literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/sysfont.py b/venv/Lib/site-packages/pygame/sysfont.py new file mode 100644 index 0000000..588a5b5 --- /dev/null +++ b/venv/Lib/site-packages/pygame/sysfont.py @@ -0,0 +1,529 @@ +# coding: ascii +# pygame - Python Game Library +# Copyright (C) 2000-2003 Pete Shinners +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Library General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Library General Public License for more details. +# +# You should have received a copy of the GNU Library General Public +# License along with this library; if not, write to the Free +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# Pete Shinners +# pete@shinners.org +"""sysfont, used in the font module to find system fonts""" + +import os +import sys +from os.path import basename, dirname, exists, join, splitext + +from pygame.font import Font + + +OpenType_extensions = frozenset((".ttf", ".ttc", ".otf")) +Sysfonts = {} +Sysalias = {} + +# Python 3 compatibility + + +def toascii(raw): + """convert bytes to ASCII-only string""" + return raw.decode("ascii", "ignore") + + +if os.name == "nt": + import winreg as _winreg +else: + import subprocess + + +def _simplename(name): + """create simple version of the font name""" + # return alphanumeric characters of a string (converted to lowercase) + return "".join(c.lower() for c in name if c.isalnum()) + + +def _addfont(name, bold, italic, font, fontdict): + """insert a font and style into the font dictionary""" + if name not in fontdict: + fontdict[name] = {} + fontdict[name][bold, italic] = font + + +def initsysfonts_win32(): + """initialize fonts dictionary on Windows""" + + fontdir = join(os.environ.get("WINDIR", "C:\\Windows"), "Fonts") + + fonts = {} + + # add fonts entered in the registry + + # find valid registry keys containing font information. + # http://docs.python.org/lib/module-sys.html + # 0 (VER_PLATFORM_WIN32s) Win32s on Windows 3.1 + # 1 (VER_PLATFORM_WIN32_WINDOWS) Windows 95/98/ME + # 2 (VER_PLATFORM_WIN32_NT) Windows NT/2000/XP + # 3 (VER_PLATFORM_WIN32_CE) Windows CE + if sys.getwindowsversion()[0] == 1: + key_name = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Fonts" + else: + key_name = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts" + key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, key_name) + + for i in range(_winreg.QueryInfoKey(key)[1]): + try: + # name is the font's name e.g. Times New Roman (TrueType) + # font is the font's filename e.g. times.ttf + name, font = _winreg.EnumValue(key, i)[0:2] + except EnvironmentError: + break + + # try to handle windows unicode strings for file names with + # international characters + + # here are two documents with some information about it: + # http://www.python.org/peps/pep-0277.html + # https://www.microsoft.com/technet/archive/interopmigration/linux/mvc/lintowin.mspx#ECAA + try: + font = str(font) + except UnicodeEncodeError: + # MBCS is the windows encoding for unicode file names. + try: + font = font.encode("MBCS") + except UnicodeEncodeError: + # no success with str or MBCS encoding... skip this font. + continue + + if splitext(font)[1].lower() not in OpenType_extensions: + continue + if not dirname(font): + font = join(fontdir, font) + + # Some are named A & B, both names should be processed separately + # Ex: the main Cambria file is marked as "Cambria & Cambria Math" + for name in name.split("&"): + _parse_font_entry_win(name, font, fonts) + + return fonts + + +def _parse_font_entry_win(name, font, fonts): + """ + Parse out a simpler name and the font style from the initial file name. + + :param name: The font name + :param font: The font file path + :param fonts: The pygame font dictionary + + :return: Tuple of (bold, italic, name) + """ + true_type_suffix = "(TrueType)" + mods = ("demibold", "narrow", "light", "unicode", "bt", "mt") + if name.endswith(true_type_suffix): + name = name.rstrip(true_type_suffix).rstrip() + name = name.lower().split() + bold = italic = False + for mod in mods: + if mod in name: + name.remove(mod) + if "bold" in name: + name.remove("bold") + bold = True + if "italic" in name: + name.remove("italic") + italic = True + name = "".join(name) + name = _simplename(name) + + _addfont(name, bold, italic, font, fonts) + + +def _parse_font_entry_darwin(name, filepath, fonts): + """ + Parses a font entry for macOS + + :param name: The filepath without extensions or directories + :param filepath: The full path to the font + :param fonts: The pygame font dictionary to add the parsed font data to. + """ + + name = _simplename(name) + + mods = ("regular",) + + for mod in mods: + if mod in name: + name = name.replace(mod, "") + + bold = italic = False + if "bold" in name: + name = name.replace("bold", "") + bold = True + if "italic" in name: + name = name.replace("italic", "") + italic = True + + _addfont(name, bold, italic, filepath, fonts) + + +def _font_finder_darwin(): + locations = [ + "/Library/Fonts", + "/Network/Library/Fonts", + "/System/Library/Fonts", + "/System/Library/Fonts/Supplemental", + ] + + username = os.getenv("USER") + if username: + locations.append("/Users/" + username + "/Library/Fonts") + + strange_root = "/System/Library/Assets/com_apple_MobileAsset_Font3" + if exists(strange_root): + strange_locations = os.listdir(strange_root) + for loc in strange_locations: + locations.append(strange_root + "/" + loc + "/AssetData") + + fonts = {} + + for location in locations: + if not exists(location): + continue + + files = os.listdir(location) + for file in files: + name, extension = splitext(file) + if extension in OpenType_extensions: + _parse_font_entry_darwin(name, join(location, file), fonts) + + return fonts + + +def initsysfonts_darwin(): + """Read the fonts on MacOS, and OS X.""" + # if the X11 binary exists... try and use that. + # Not likely to be there on pre 10.4.x ... or MacOS 10.10+ + if exists("/usr/X11/bin/fc-list"): + fonts = initsysfonts_unix("/usr/X11/bin/fc-list") + # This fc-list path will work with the X11 from the OS X 10.3 installation + # disc + elif exists("/usr/X11R6/bin/fc-list"): + fonts = initsysfonts_unix("/usr/X11R6/bin/fc-list") + else: + # eventually this should probably be the preferred solution + fonts = _font_finder_darwin() + + return fonts + + +# read the fonts on unix +def initsysfonts_unix(path="fc-list"): + """use the fc-list from fontconfig to get a list of fonts""" + fonts = {} + + try: + # pylint: disable=consider-using-with + # subprocess.Popen is not a context manager in all of + # pygame's supported python versions. + + # note, we capture stderr so if fc-list isn't there to stop stderr + # printing. + flout, _ = subprocess.Popen( + f"{path} : file family style", + shell=True, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + close_fds=True, + ).communicate() + except (OSError, ValueError): + return fonts + + entries = toascii(flout) + try: + for entry in entries.split("\n"): + + try: + _parse_font_entry_unix(entry, fonts) + except ValueError: + # try the next one. + pass + + except ValueError: + pass + + return fonts + + +def _parse_font_entry_unix(entry, fonts): + """ + Parses an entry in the unix font data to add to the pygame font + dictionary. + + :param entry: A entry from the unix font list. + :param fonts: The pygame font dictionary to add the parsed font data to. + + """ + filename, family, style = entry.split(":", 2) + if splitext(filename)[1].lower() in OpenType_extensions: + bold = "Bold" in style + italic = "Italic" in style + oblique = "Oblique" in style + for name in family.strip().split(","): + if name: + break + else: + name = splitext(basename(filename))[0] + + _addfont(_simplename(name), bold, italic or oblique, filename, fonts) + + +def create_aliases(): + """Map common fonts that are absent from the system to similar fonts + that are installed in the system + """ + alias_groups = ( + ( + "monospace", + "misc-fixed", + "courier", + "couriernew", + "console", + "fixed", + "mono", + "freemono", + "bitstreamverasansmono", + "verasansmono", + "monotype", + "lucidaconsole", + "consolas", + "dejavusansmono", + "liberationmono", + ), + ( + "sans", + "arial", + "helvetica", + "swiss", + "freesans", + "bitstreamverasans", + "verasans", + "verdana", + "tahoma", + "calibri", + "gillsans", + "segoeui", + "trebuchetms", + "ubuntu", + "dejavusans", + "liberationsans", + ), + ( + "serif", + "times", + "freeserif", + "bitstreamveraserif", + "roman", + "timesroman", + "timesnewroman", + "dutch", + "veraserif", + "georgia", + "cambria", + "constantia", + "dejavuserif", + "liberationserif", + ), + ("wingdings", "wingbats"), + ("comicsansms", "comicsans"), + ) + for alias_set in alias_groups: + for name in alias_set: + if name in Sysfonts: + found = Sysfonts[name] + break + else: + continue + for name in alias_set: + if name not in Sysfonts: + Sysalias[name] = found + + +def initsysfonts(): + """ + Initialise the sysfont module, called once. Locates the installed fonts + and creates some aliases for common font categories. + + Has different initialisation functions for different platforms. + """ + if sys.platform == "win32": + fonts = initsysfonts_win32() + elif sys.platform == "darwin": + fonts = initsysfonts_darwin() + else: + fonts = initsysfonts_unix() + Sysfonts.update(fonts) + create_aliases() + if not Sysfonts: # dummy so we don't try to reinit + Sysfonts[None] = None + + +def font_constructor(fontpath, size, bold, italic): + """ + pygame.font specific declarations + + :param fontpath: path to a font. + :param size: size of a font. + :param bold: bold style, True or False. + :param italic: italic style, True or False. + + :return: A font.Font object. + """ + + font = Font(fontpath, size) + if bold: + font.set_bold(True) + if italic: + font.set_italic(True) + + return font + + +# the exported functions + + +def SysFont(name, size, bold=False, italic=False, constructor=None): + """pygame.font.SysFont(name, size, bold=False, italic=False, constructor=None) -> Font + Create a pygame Font from system font resources. + + This will search the system fonts for the given font + name. You can also enable bold or italic styles, and + the appropriate system font will be selected if available. + + This will always return a valid Font object, and will + fallback on the builtin pygame font if the given font + is not found. + + Name can also be an iterable of font names, a string of + comma-separated font names, or a bytes of comma-separated + font names, in which case the set of names will be searched + in order. Pygame uses a small set of common font aliases. If the + specific font you ask for is not available, a reasonable + alternative may be used. + + If optional constructor is provided, it must be a function with + signature constructor(fontpath, size, bold, italic) which returns + a Font instance. If None, a pygame.font.Font object is created. + """ + if constructor is None: + constructor = font_constructor + + if not Sysfonts: + initsysfonts() + + gotbold = gotitalic = False + fontname = None + if name: + if isinstance(name, (str, bytes)): + name = name.split(b"," if isinstance(name, bytes) else ",") + for single_name in name: + if isinstance(single_name, bytes): + single_name = single_name.decode() + + single_name = _simplename(single_name) + styles = Sysfonts.get(single_name) + if not styles: + styles = Sysalias.get(single_name) + if styles: + plainname = styles.get((False, False)) + fontname = styles.get((bold, italic)) + if not (fontname or plainname): + # Neither requested style, nor plain font exists, so + # return a font with the name requested, but an + # arbitrary style. + (style, fontname) = list(styles.items())[0] + # Attempt to style it as requested. This can't + # unbold or unitalicize anything, but it can + # fake bold and/or fake italicize. + if bold and style[0]: + gotbold = True + if italic and style[1]: + gotitalic = True + elif not fontname: + fontname = plainname + elif plainname != fontname: + gotbold = bold + gotitalic = italic + if fontname: + break + + set_bold = set_italic = False + if bold and not gotbold: + set_bold = True + if italic and not gotitalic: + set_italic = True + + return constructor(fontname, size, set_bold, set_italic) + + +def get_fonts(): + """pygame.font.get_fonts() -> list + get a list of system font names + + Returns the list of all found system fonts. Note that + the names of the fonts will be all lowercase with spaces + removed. This is how pygame internally stores the font + names for matching. + """ + if not Sysfonts: + initsysfonts() + return list(Sysfonts) + + +def match_font(name, bold=0, italic=0): + """pygame.font.match_font(name, bold=0, italic=0) -> name + find the filename for the named system font + + This performs the same font search as the SysFont() + function, only it returns the path to the TTF file + that would be loaded. The font name can also be an + iterable of font names or a string/bytes of comma-separated + font names to try. + + If no match is found, None is returned. + """ + if not Sysfonts: + initsysfonts() + + fontname = None + if isinstance(name, (str, bytes)): + name = name.split(b"," if isinstance(name, bytes) else ",") + + for single_name in name: + if isinstance(single_name, bytes): + single_name = single_name.decode() + + single_name = _simplename(single_name) + styles = Sysfonts.get(single_name) + if not styles: + styles = Sysalias.get(single_name) + if styles: + while not fontname: + fontname = styles.get((bold, italic)) + if italic: + italic = 0 + elif bold: + bold = 0 + elif not fontname: + fontname = list(styles.values())[0] + if fontname: + break + return fontname diff --git a/venv/Lib/site-packages/pygame/tests/__init__.py b/venv/Lib/site-packages/pygame/tests/__init__.py new file mode 100644 index 0000000..dd26586 --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/__init__.py @@ -0,0 +1,40 @@ +"""Pygame unit test suite package + +Exports function run() + +A quick way to run the test suite package from the command line +is by importing the go submodule: + +python -m "import pygame.tests" [] + +Command line option --help displays a usage message. Available options +correspond to the pygame.tests.run arguments. + +The xxxx_test submodules of the tests package are unit test suites for +individual parts of Pygame. Each can also be run as a main program. This is +useful if the test, such as cdrom_test, is interactive. + +For Pygame development the test suite can be run from a Pygame distribution +root directory using run_tests.py. Alternately, test/__main__.py can be run +directly. + +""" + +if __name__ == "pygame.tests": + from pygame.tests.test_utils.run_tests import run +elif __name__ == "__main__": + import os + import sys + + pkg_dir = os.path.split(os.path.abspath(__file__))[0] + parent_dir, pkg_name = os.path.split(pkg_dir) + is_pygame_pkg = pkg_name == "tests" and os.path.split(parent_dir)[1] == "pygame" + if not is_pygame_pkg: + sys.path.insert(0, parent_dir) + + if is_pygame_pkg: + import pygame.tests.__main__ + else: + import test.__main__ +else: + from test.test_utils.run_tests import run diff --git a/venv/Lib/site-packages/pygame/tests/__main__.py b/venv/Lib/site-packages/pygame/tests/__main__.py new file mode 100644 index 0000000..abdd92e --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/__main__.py @@ -0,0 +1,144 @@ +"""Load and run the Pygame test suite + +python -c "import pygame.tests.go" [] + +or + +python test/go.py [] + +Command line option --help displays a command line usage message. + +run_tests.py in the main distribution directory is an alternative to test.go + +""" + +import sys + +if __name__ == "__main__": + import os + + pkg_dir = os.path.split(os.path.abspath(__file__))[0] + parent_dir, pkg_name = os.path.split(pkg_dir) + is_pygame_pkg = pkg_name == "tests" and os.path.split(parent_dir)[1] == "pygame" + if not is_pygame_pkg: + sys.path.insert(0, parent_dir) +else: + is_pygame_pkg = __name__.startswith("pygame.tests.") + +if is_pygame_pkg: + from pygame.tests.test_utils.run_tests import run_and_exit + from pygame.tests.test_utils.test_runner import opt_parser +else: + from test.test_utils.run_tests import run_and_exit + from test.test_utils.test_runner import opt_parser + +if is_pygame_pkg: + test_pkg_name = "pygame.tests" +else: + test_pkg_name = "test" +program_name = sys.argv[0] +if program_name == "-c": + program_name = 'python -c "import %s.go"' % test_pkg_name + +########################################################################### +# Set additional command line options +# +# Defined in test_runner.py as it shares options, added to here + +opt_parser.set_usage( + """ + +Runs all or some of the %(pkg)s.xxxx_test tests. + +$ %(exec)s sprite threads -sd + +Runs the sprite and threads module tests isolated in subprocesses, dumping +all failing tests info in the form of a dict. + +""" + % {"pkg": test_pkg_name, "exec": program_name} +) + +opt_parser.add_option( + "-d", "--dump", action="store_true", help="dump results as dict ready to eval" +) + +opt_parser.add_option("-F", "--file", help="dump results to a file") + +opt_parser.add_option( + "-m", + "--multi_thread", + metavar="THREADS", + type="int", + help="run subprocessed tests in x THREADS", +) + +opt_parser.add_option( + "-t", + "--time_out", + metavar="SECONDS", + type="int", + help="kill stalled subprocessed tests after SECONDS", +) + +opt_parser.add_option( + "-f", "--fake", metavar="DIR", help="run fake tests in run_tests__tests/$DIR" +) + +opt_parser.add_option( + "-p", + "--python", + metavar="PYTHON", + help="path to python excutable to run subproccesed tests\n" + "default (sys.executable): %s" % sys.executable, +) + +opt_parser.add_option( + "-I", + "--interactive", + action="store_true", + help="include tests requiring user input", +) + +opt_parser.add_option("-S", "--seed", type="int", help="Randomisation seed") + +########################################################################### +# Set run() keyword arguements according to command line arguemnts. +# args will be the test module list, passed as positional argumemts. + +options, args = opt_parser.parse_args() +kwds = {} +if options.incomplete: + kwds["incomplete"] = True +if options.usesubprocess: + kwds["usesubprocess"] = True +else: + kwds["usesubprocess"] = False +if options.dump: + kwds["dump"] = True +if options.file: + kwds["file"] = options.file +if options.exclude: + kwds["exclude"] = options.exclude +if options.unbuffered: + kwds["unbuffered"] = True +if options.randomize: + kwds["randomize"] = True +if options.seed is not None: + kwds["seed"] = options.seed +if options.multi_thread is not None: + kwds["multi_thread"] = options.multi_thread +if options.time_out is not None: + kwds["time_out"] = options.time_out +if options.fake: + kwds["fake"] = options.fake +if options.python: + kwds["python"] = options.python +if options.interactive: + kwds["interactive"] = True +kwds["verbosity"] = options.verbosity if options.verbosity is not None else 1 + + +########################################################################### +# Run the test suite. +run_and_exit(*args, **kwds) diff --git a/venv/Lib/site-packages/pygame/tests/__pycache__/__init__.cpython-39.pyc b/venv/Lib/site-packages/pygame/tests/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..068cbe6d946fe87ab0b0e4da60ddd2eb48089906 GIT binary patch literal 1372 zcmZuxO^@3)5S3*4Bi!{iZIYr}F%@ycvqk=On`GPx|@tT^dF2{AT|e z>xW7hkUY4j2r9+=r=u%_-vbGb1{dX#TfG(@kAV4CUGR@_H{t` zAiMeEZFu@H`$!++(@5RwIq~uL(a8<=dlE(8wQE)h+Gy#h6W}N`(g|9#a?93&kf$$e zV;#^{qe~}^rnb@dPY5}uFB(~H=>==4Gu}$wM*L3-y0WGU?@CiuOmnKF7DNJFwp3O= zyVUF8ur`RktPF3Ict}Xyx(x!JRrFr(N9#a#;d#P6`s1TO*wmgEJpPH0CwmCAx6`w; zjZih^5^BX-po}(vmC;Iozc1+dj!DIqN(>P|N@J~n+8|df&6l+gyzsR$yKX9>9V`fW zh7K?BDhB$_P2d!z#T*z@a%@Q8dWx=8Y9}ni-tGj}@|Cdz zDCJ@&l&O7{*JTXT;h791LU-A9j09)pvhf`u))uX-*oqM|9YmE zG@FhApP$@IyWh?j##g9Jerlk+3P174G7M_?1~sV_nZC&^S{YbeYQ5rDSY_XSIHhHk z)sD?$lbXwhUmxN1W3yxV)4szTY7eaR-4Q+wc2mm+tqv^z1Un)A$4rRRpeCC>woD^& znDwwpAs(*s4`H`@G!xJIvnFOT9nHn_{yf+%>6L|vm6PQPczs44e=)J?34alypVE1? zSc^6w|1W8iEw&85#pWNLrZa32@YxTomT_#F2AkhsqH}bfF3^*7@qs-;PSF-UO_v^2 zM*1>6Ls#fox=PPIm>OZvQJ0GSjoWVPHfCh)7&gFQDV z_S~W`K(s&5KbF1^&m0@T=Zb$eH2hVzvVZOalYc^AWUKT~+Xm>*f&PE3|9RU;>hv$L z0#C5w!pawV<*!;l5Bk@Dp9hP-X=DwM?*Lf?-?Q>1*7eQ}n{bjAMQ!6(C zy9!?G;I*yMOC$6(KraFMibgMw(0>4W8PMw*-2m@>KsEsRyGGi8{1=cmAg^lVc|hLN zyWY_Hl~JUR!0Jk3(J8Qe4OV6uu)XL-IJWpJ?$K1Dv zeG)TQG9g`&hmtu?Hk5m5;(A?oEsV32OE=R-n`k69`{|nduWjv+W-?3@asA(plkz8y zxU|(zH?!e0>~5xUjQdAn!rao|^}Ib6WiAax7LlQFiQApD$_42&H)aC=HysC356Vs z$Zg}G7g;sd(H?It|#ay zAa;1Ph@_7V;*{o5*>nN)q!E#fB9$WF&3M`cs+qXz(mc+>r0-x_JrY98`sMCm+DpgO z_fj5Xwgf2eN=U42sR|^mY|IWSr$yECFqU!zG=v3`=d4&m#N|xnk%Y>H_6D8MA@+wI zkO%@*Nf*1RY&;kW+63nNyve&G)u#6`Sq@&G-$u71%)wh3?9W)zK)jK$p^#~B= zZiu1S#O{?I?Q8D307h>YP0s`B7{{(0Ko7&D8|8GIEocA9Lyo5;hkF1-W;vex9js9> zMvH}ea0=5n6mSjUiXsM;%#JI$uN(-N##zK9Q%wl+l)*QYt&fn6O;$Ci1~*ntp6uqm z9^;IvXZsVL&CnhRV(+7<2rXrNX_El920-APVBvgP8 zoDd0&N>Hs-C>!ZjQ!ueYscK|bXdP@Yzaa2ya03FELCS%tz!IsS>j+{HzZr_491{Uv zm1>v(V-hb2;Zhuia?d|MIY#vC4PdfGV)My~;8QrGF8rPy_A~(FgmGR)%Vk8K8OdMy z_0oj1-_*)DcV!daKkyqcDEgelx*jzxm<;rwRt}*wC?~seo*p7igkS+U3soDvIdm)_ zb8tunpT~2sfZ`;IMHHt{v{0Nzv4mn7#TgVUD9)l-MR5+qrv`r!pHY0@zj>|m4iGCk zBuR+q++t!N)2suj@3Vm%214dEB%K?#gTu67gWxcvQF=J+9I)h|^H#Xqfs??zjC2R^ z>Jgoi=`Ex~Y>i(S@Saok?Q*1E$G3)f1j3%FTXnN;EtzxXS<^P>EXT6VhB;$3%mzGF z;pdoOQL|0UseflZwr6a!{zc8 Ud_ryXT!%cIC%+Oe*Un7+46F!VRsaA1 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/tests/__pycache__/base_test.cpython-39.pyc b/venv/Lib/site-packages/pygame/tests/__pycache__/base_test.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8ee1ffe482a5f37ce24f88a3dbdb4e9803db788e GIT binary patch literal 16434 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 H^B(^{x43bE literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/tests/__pycache__/bufferproxy_test.cpython-39.pyc b/venv/Lib/site-packages/pygame/tests/__pycache__/bufferproxy_test.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2c94c39ce745503714d4cfc734a93e877edaa923 GIT binary patch literal 12852 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/tests/__pycache__/controller_test.cpython-39.pyc b/venv/Lib/site-packages/pygame/tests/__pycache__/controller_test.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2ecc1e30b2fe66022e513064af7446205e66b90c GIT binary patch literal 10079 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 r)rF3lS***BgFihyv=o%O6Ib;JX+nltBj&$;J* z%(?SB8!jzX2weYmU)xzdPsm>p9KQ?zH{llF0l^5P9pd9t>(H*|Ycy}uef|4{>CE_; zFe4%@<3RV#$YN$&<8Mb~VjmLlq+7(ZrVxj0cr>f-#t&tmM?o)?_nX*y{L%p2gj-w$ z5fPs<;%kgD?PKEW`AELOOlAQ#nGKPh>bS;q^#eGwj&{%6nYwrEWpHS|~rO7gL^7-6@)sL-@tfZ1Z*T@>g zP$Qkfk&^0MUjtuw4GSBd{?xf!haX&^sjFTeIv|5ytl}n!p`F`Zg_Q8EylLLz z8AAi2)rXqvf>sA<-i60qPxEe1e~q#5Ju5N&^O2Urzn9@3%kU3n_`5RvZ5jRs;Phuj zn}wPZYH-x1KPg$KYi0Om8UFJKPXB~j5o-Dw!c#|9zF2}&fh+pGUdm;}p4LS>?)Bni&z11eb3@^ZNCw~uU&GfuHx@4TEd0G%Rt<%S zxZDh55s9qw=iC|i;D<7PVqul+zs4#SCTF^_ZW z!+zMwY!-`NCmdu(oWwFSyJ=rUS!F(#%#73+I&{yRJ~-igGXtle86Wmz>Dhpy&aPiY z%WMf(O6Y0{UGr;UQ^M%M&Ok;13uTyD`P4HSJt6#?u!~RI>u)vQhXsp9m?WWSd^Zwp znf4kzp0=X49Kd?|EDjs*yc_JN!>AqX$E=g?4;l}mo;FZLCWmwFCP2dq5<{2<(r~ zkIk8fF*4EPb9A?ToPs`Q<;ShS%A{kCtyx41s0k=^gijzvH9jpUsxhpAA5hdtpApjy zAST*c9DD|}WCJZ-UnPqpQAcqZg<^^;s9gmC40#P6ekD(>T{wNdgA+lG zUq_RZn}S{6LPN02-@@MCK!GWri*JFJEvfV=W(Q5e1wj@a>d<9g`r873xT z4SrQj#8+OBh)0o1nTUCg*{F)EpQ}u4(TOHW3rd?Yg+c{#uVo_MgDFV+n(U&#&I%`$@ z(MxbV*5JORtwQT*XkVo(+G#rc(hCku-n`*inG*yFkZTZRl_2Pt&Gcd|YgJ;f-eBy6o)hDn@b6_(ZedQ5(M9w+%zut&8;s5{u literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/tests/__pycache__/display_test.cpython-39.pyc b/venv/Lib/site-packages/pygame/tests/__pycache__/display_test.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0a928e3e1bc4dc0ef5b459f0a3030a39f880a4b4 GIT binary patch literal 22466 zcmcJ1d2k$8dS732U~muw!9%2u5p@w-3Lz+h(B zJs`wc(B7C@A4wF+@!F|meE^EfHWMGajz&lc^M!7 zcTqT+qgORsee1R^_l9lAw`rU5ZOOM$O|7Qww9d9>)m+Wk8C^T4IhK=pTXRybww%3X z+5@ObI~mku!kQdvvd#c%2HYH44B|fL4B~z;Y%%0&o5QZYJhHjV8QRjF;T6Lf*)q^> zmotiXqpIC4-5y2VZf6X2V`1Oj?wGS@#qfR$W9-?|Fgtxtn;5@?wP}UhdXT-g=K9S_ zy*8l-8K>ems-+tXe3<-;LGppFX|6^v00cUgZ8+xJnr*2?+9|a(JFOOEXVgOMtUIuo za|f4)Hiwf7P}9e>N7SV4UCth79OI2Td!2pw-tFvn4&ZytxyLz(?>!vHIpo~CWjOaa z_rI;7@3`}TlgG2Y&V$ZjeD9Ms4>i8r^}dJE=Mm>o>9gN?%sGO#2fF4pab0sBN4t+X zN2T38&J)fg+8uPBbdKTskaOI53g7oSPdm@x`#$Gc=Q(`e?|hr{JiZ@rUT|K-ci#E9 za{}KFI-hV}!uR2>_Yi?6@t&8RQ}UjN`aFNdIW5m0mgkSSk1jvvoVjHTY0eaSpLNd3 z(<9ES&NSXK;k@R265o$IGtPN@f6OU37w~=5x#+x(?Uk92fNQG5;xy7~1=&8e?1fI{Lw zUK{wF#>XE*(bP6|Awq3VyR8={49`MsU{z|BCWz7U-Rk0P&Ep3BVCD3SS1$Rk=U*w+ zY9;^58P{KF)*DwEUVYhJY2GOM%{8Y|x^il|xL$9$E5-GSQ?0MxxN_aCUB5C@xq8K~ zG~Fi}rG=GJ+4ZleX+GJ+oc$+5N-y$mvT-9w`EK)4V>jo?32S<5|F)G*N}G?qKrfAf zZbwVJwpM9+S=7ktR56I#Alr0H-kJJ(Z5(&e+YfGkd(^CB0w($pgaY9!xM*t2`lhj^ z-PAX;wEwj6!S(6#U`rS7Cv+A+5Dn?^^EjPx+W9=uCAa_0bJ6IS8Qhxof~-1#hC z<&8zfL^en(@CrU{Yr3{r4@OEp(AO-~n^V`;N>zJcVa@a0TC=#+zFZHofNF8I?zq9A zYA=l^Om6_A2WF+V7^M9L&vk3vfEyt4ihR|6H1$VNXnIZ`(MQZ7`EDKR1;wyW2N;QS z;zq#uWn3tr09d*Lq}*Fu+Lo^KS!y%Ap#yv&V7s2`n;8;0K%T{ufi3;rgVIai#0a|f z1|)=qf459stBoGl{KhfV^53WN`A#D4qxJjgWIsWWSpaSv%-=hNV#2)h3a{@)apzf9 z0nBIckpRqb6~5#57R$#SnXTV2G?FCiEI^1m+-gMcNSt z66BrYGpQFs?`kJR-5x`(qz5-j=V*=v(oePSCAZ5rm)v|A6kA$oR<67G#kCqP>b0}C zjml?1MU_9mMCS_=nFOE-KyM$4AlL5cWmrob^kfRVgtptwpF=}`6oqEx^f5qiNFT#h zPH#QfhsN7|gI#lHW{Q`m&rDr7Gdq2GYBoqYYpbg_TF-bcxRU4kvZ}5|`DQ(T)y|nFVu+S`H9j z*Ny=GIcYz*1>K1|%t-DCiF!9QPGY`R{)RLfTu>b1(^4ewFRMs~rUerEjV&i!HQ z?UQE<6GI8K2>qvANQ-8WTBw2v2br*Qkn&2kGB!Z7vg$%MR9&|bSdF#ShTzeA3}Zuf z35U{)-L${I3wOnE)K}3}b5$up5PtPnrNP zHd=>wSXaABUINE(`-nwu}4K6P<^`a+>6^HVTM3{t|V zJ~^bOTY$=_KCbtLOrl!{WIDDQi93P}VIh!6qFf*mii9-+^-tdYqQbeQR{J9A5^D=t z`Nvt?#mdJ8!y!0|Yc)`_<5tknr+yJ=w2OWvxTTBtA7 zOE6~2C0H!rhYQWO?5w(2yy`uUnb|pa6-r2@(R6EeYVj&~jBS?76+5+5s;sQpnUy84 zUaR|ddS%sjFs4;2EkNU`FD@$G#m+SF&bo)!H2j8bUaP%j4|pZNaTTKUhMn=RmpL;# zwN_cFGz0T`xoT&wSFV?8P1nw>mu^(iJ;*2>8?WI7o8#MS+U8rwk3-~e*V!Ut91p_D zv$LUeuZa-%D2f#Wd0-HeDkL6Sopq7jeJvwdYRfV zw#=Jm(^wW(e$yhi+psnw?L4(%;aNIVLh*!ZXPXD&K8t%%Qm@^AZJ(0{`_HtVjbO^T z1G?1osL?1TAXL%wjxzJ|VS`B!%L|zM9j->CYR4M6He&N>eEd9$4H58M+jop$AL|>& zqH&qxJ$DVRlQ~UHBOx?k$(TGA=<9*L1Pd@zb!+A3lCOwR?4yAbWw++O)$m^0#K`{x zAFcK54)}Eb&%L9Wma$LAHZ-VHK*R1YT@py|z#!?ISd{%p&?rT&ZAbRn zm5IUfOW;q{P?L;^hgKcb$0jyrrB=>EvSC+R2^DM>FY+jILuJal#ELHYbAP-m!*v(M zTr6VXB8L12=%VxutiE;Z?u60Vy#orQ;g~C(z)dJ$Xp(`7o3itku!H{|?PhC3r{-}> zhcQS?+C-}ib|?84RV}0N5(&v30|%>Due)bGxJj1J-AS>);;wg z$U(H!Kri5Ic6QNM4Bs9AEw2=5Y$(=WU$+O>E31vmaF4L%;9`4h0U`ubx#}(0+4WU5 zL|{3kCWYMMRoh&07VKev$*oo+4xnVmz)~foYsZsc?NRHb-R7pT#D0fp*yqnXtRPFT5x=>X51A=S2?CuJ_#464-F9 zEcM+)(cTQotF+(rA!8v8H^fS_QE#l-7JV@7Lkf zS}awnB7q=iD6Sh7*ceWJwR8i*rVeA!%fn;ZMBi2agC{OD+}gPr2%*rd665KK!(u%h z&UYDD9h65^D%OPxpg~feql3SL=5Fd`YC{HeUCM%#aDAoqCF?SwPMoaE_NaqHLNvx? zyIhaD!5(#RKX2ruC-N8Najy1hN>_Nh97=YGOdIdkIs zjPiQL_t~!J1CE$f@$+2Q{b1MqP}lvilcL;?`;T!AM3i`)75^w z>wa(7J+uSP2O4+=8n_91qdu{n-ja0@y(Q}+dP~+t^p>oP=q*_n(Oa@EqPJvSL~qHu zh~AQQ5xphrB6>^KMf8@ei|8#`7tvd?E~2+&T|{rmx`^HmH1FAf14J~w$(t!ijDyhV zQm|7EmMg}4RwEbIn5u^R?LG6_AEE7`=Do0c?hWZCX<+IyD&@;2*dfWCGr z-Kr??>LQB^EU4Nk>u}6#KawkX-c?BRxQ`mKSDm~sZfB>?TsnXL(-Ze~D_ZFb7pDs6 zW`cC70siUOqvdLmEV|T$E`N0m2GH=inc}ILi?5z4&Q04>a(ia#;{2=Xb{C$`%}*6h zPve`dDN{Pf(Z^A~5P zUb%Gk?9}X>-Bqm~&LPAn^O>ExAT2PHshO$SQ}dY1<>|Rgr)KN}XmR>NVSegU^TqS0 zUb`?`gja43?u5=K(}l#7(L|rKGpEkY+4~bU7iTY=ot~M(Xmg*m@8bksJvBR3d}A6w zI(=z&cB%lEg?giX2#?Rso;n|{qc}Hv?iKnoPQ5ZSCBUZ(A_l(qB#0w0p_hA94#kKJ z2Ig-x+$lPNC(>;vu)VA9RmznbWVyHseLKgYqHE$*T?cxlTcGb%T3#3Ce;aS~e+7j$ zFk)H8I2L+!8fVsHPL+343WT zhhii_JkZ`Gued$EV=RudIEo@LvDM(~#2&Q=Po18J&wuJNIDl=Hp;E)2O^=B^aO&bk z_0Zn+#&qG#g*VPm7pBjHfu2!2{jYGmGKz4I(=uIHaDCq%Qqhm1IM1Q7OXRn>3Uz%I zman7gy{Du3bno>c+3O+gERqrrqp6k}GR9!TS$Z~%-yz1q&8}zZEl1R&b$<^^WehMJ zs)MMwcVeRA_{x?OpJ5_w!~lgLjcE}^>zT+q!Z?reIFY#N4-%IXC|gAuSOce1wJNTr z(2+iZ*Qmgbu*x&MrB>e!02LkM5TE1f#gA%cvCh8nFt+{3%aag0=rME%Czf~Oqb_e1 ze*X%{P*yJM^u=~3L_f+3_b3!&)-bojvEGT-3YQ_)`ba-)cJ%64HJKryB@FSu;DUQ_ z*?^&>Et?KpYVVlj3XZvAdanWkRx^b={T}TWoNJMztjX9d>QsF*BZ_!CY_59$*tgO< zYI{p>rkdFesCT!-0Uyl{GwYn&A4fet%G`vXqza;E-8K=tqvI$@EmliqU+Gff&?0Q$ z#iGkWYJ*(0g1tc}4D9l=mu6<>PE+?$3}k`LR!}g+-t@kmox_M$O1gB@ta1alhx|OT z$xxD}j{~3M`T^`x`Nq|lT=jJdw@2x~u8F~7>|VuXbFA|;P*x1`5qM} zK){D-4|KzXhMU|2>L&1Rs@|j%-s6*c#|rs$y5KSE!y^clCi^phWK4xtDwu%jTZ{ZqQEMS7&;8Q#=?D&&}9hn7U;^1u94S*rMcK!HU*sVXX zp2tuM1R;QQ0O%P22;o18qlgGywl=^Ln9=c$q3l_b)@`fMUj2kF3kS!Km)l;Y*TQSO z>nuLQqRUaI;-2AL;jF4wRqW%7TrIU1W@m7%P>Vk78};1Y|1W3R-gja`JFGKE&z(Ls z16kN>sfxWtQ}rPST<0rXCb@mI%)Sh+vtP&ZFh*NyQPP7^ATF|ONHDh@)iV@3n6T_& z<&-|>xe)4J8*R|!p>NmLR*R1E<@-HFQK)x!HT@;7g$za8L38cu(|;Z05|Q-9dbW$D z=X;AKx{kL?UM5n-lJ|BP&J@Wj3d>!DE_?qfSI1qg89Rtvw(P&A!-+NRxVD$Sm9<5p zG9NDzV%NKcclAV`B15)qOW9xJ;zXm^S;}_yYTZ|GUB}PUW7&+-J*c|(h~1G*)0ul3 zAHSPT!-HfnhP$CdAkpiAQXSM z4dtewKVic9QtTzU7a|MSRyi)#M+N!UgyWG1eb=5Ht28I@=RT-UD7 zGZ%n+%pRa^Bu&GhXpojW-}`HL+|B1kM7N2%{00F|R;XEwg-SFu-$%8HJ9Q8igK9BA z8@N%dT*d9=vzL#QMJv z7wrNS-_MG;K*jf>qWr+;{_E>sx&L<}xPSd5B6+$O=;c7aI`92;j;11D-rr#VzscfV z7Voj>5*>;Q#n34hn`=-$f4>v5BQOX0+R@#8gOPR(Vk3>#u>uI2{(b+3-$XQD{P;^H z&si^dFtwE7nisUg)4$s29mN%zrx;A4sA)DWrZwFH-BZDM8&OzBb#EF@O70A~Q)Vm_ zQX&qKU3gf%H^C3nGFDtqWv8|e^_lJUvKP|y<((xIS=@m;Kte(eX0Ye;Cjt$RO+=Yj}qt#h~z(vTL+N9aOM?gaIF>dFRo#^}^jK zyhtEUwu7+o7~lF_z0XH8^?oS6l1UEo_HU#3ztO}Ht7>a5-0FeFH!CywZ?QR1=uuQe z^w~+8_F%=Ii`*F9pim6Ald}GpR7&+x8ykW;hxAi;lq@L0edT{={|=sIkwZng)p%Tq5uZCsHhMLlC6et>XziK?L(=wcWeeerJGzm#g#lwQ@0PF zGSe;Ydk7Bo&i02iazoib@Xf@a^ZqVo*LqI5Fp$IUG?()JQhlxJsO-mBBG(rsOEQc> ztCk{>TF-}_m)uHusriw5tEL@UqNG*tvncFcRNO+JikK3VQQka?P&(NbXMwaJL~DDP z8eJGw+Nnj19>y4&p4M|8rp+AHaNW?2Z&<11)x#g&9ph@q4vhCCT&3#K`rQ(*nLr<^ ztCHbe)M;lfBko=Ip6W@aZ3!V{dR;Z$AJgg1k|EirW7_E7*0*2AjgTY^MSM%-6~qz7G0X$kzm6~O$59kI%#@f=lp#;L=$V6BV1!`)$MjOBVtUHmLPlQ~|!u;9f`t7}BJOEgI zy{POM3n{~nEq}a08fD@?==1oC&!ohAq4p@h?WPx z%7!Y-NLbi$l&|+3i=gp1S{3&r!K5s6Kb; zTkF~PahcKZ`?@nSu9caX+7C8r2EW*Il#hZt)&I|u{e}2Pmm)VLl?~$fsyyP zD0ySxpBApkA6VY6A4O?NIU;4Ye=c5vL8x%r(KvC4(TA>dq3}FLd>W$zk6eDtJN^ha ziWw)Es)cAFi?tXplf*ZUQM=dTyQ~{; z>ljm*JCaU$lBs4NQ?p2IAvquMw67t731>V|A|AI$N2I=tG#Pv&IR+kC^SUM}bi*5_ zN=B(20EZdw?4{CM9R_PMt%J1SC2y-)FP9OlX!{&h^i6FD*$LMGl=+E~gw7!@qr<57 zNI~{)HAcd3nK+_TW{Ux(mq9~RN!CheNNU7L>*;SAW?IjFXnn)VAWE)}e%M!} zZyUZaaXiQti#22>7K=enawCytjq9Oek*D_56Yn{$Pk78OUfsju5f(>K1X-L4fSB`} zII4%3<@91;)cqiXbC?yR#e2(a_za70W5L8q?-MLuVKK#m3WWCtiz16f7E3H@Eb1)i z81ZhfxXI$XSo~EM-_7D}7N2AB4vQZ^5oDH1KJyq7NdG&0_yra}!s16+Y_iy5@%K@{ z8H6Pi#c2E)R<^C-w#k{o1JaLAI|2@EBa1wN>|l00J7&TDGrnn9xzTJYo5km`Y#QOq zUDXe)YoFY944elxsTklJo6kw(JLP1YEWXo9{NiB1pfiN~ zEY1jz;Cn!w*S2%vY3;%AwDwSVT6@^pk8OD%J|ldofs|7@BfP+AM1Q>ImOPD*cwuEX z;~10#!4Ygl@}&d6ub5kiO}Sop)($Sag(|$=@Q4x<5JTkPwsj5WeF9736EN}QExajm zVn^p`+jE+X4!(CVQcjG0WpXd#BJ%A@CLThJTTr2jbiY|ttweuiPNuL*w84=!VVcbU zHQ}eZ^Jf^*`^Ok4NL{VsC~}l%oU$5ecz^{ryeEkRJO-mT`UrM>thV(j$qzASWCu{|iT*D?fswb!1wdj!^bS zUK)}@j~qLi$N%HUR55Xq2S3}Wq$4V@X7NrHkWH`2j_^oep_~W|?>IhB*@pLY7n%cQ z$E!ZYXu6*x_{H0VEN2)d@h7(06WAB)rfYx>awj2h6A3X;#q5t5L52L_1JTrp7`X!) z6bj4Rkhq*~pNMu4eg6W|On+1*%4dO|f!6bqJ)~x;K;0;L&3x!{al*qWWuObEd~OJ5 z5L8Zj{{)j(YVILk{WuHS&mZjXgR>9xlZD#@U0Cw|Df^L3y?@4{z5j@-h|{Fxojan* zN9s3|-#69QytPk#W>fk4Z3-ft3ZK27K zP(x_64tJ8E@P7$Au$wTElee?ol-Q35dokqDN=X3jO9U8Y1^}jn!r{;g+W|=Zfiu|? zIFxVzQxY`Fy(j)J?_Z*m?90}{5CCtydSPZNpX8n=3*Oh*tcQ3Dl#@MPRFMwpuO!#S zY_Qn5-gjNnZ`;yhF+`2F7v4n_8C%x2B`WMAbb{XkctXuiv8sqYt@%7gLeq^i&X*WX zCC3Pv6!}x@XeUXuB}pVhI;2T|7%B5Kgb`o&%Six@5kPlAJUeZJ4$&dIq9xFw{|R>E zVSxpA1rIIKn+xc`el)G5{kYx#!oK;aFZ@^5`>5&Bv)bYJAQ7cnk9+b{698e`de5&f zf&W)(jWq~yM(x&NU6dz<>jYNGcNTfPOyt17#{AV4Z{ZF(%!;38(GCv@tM5gD2a|%c zQd_9wcS{!FSOmzv7Q-1yipS_ajnZfP5MpQd{t!Qdxrt?+NKVAL{cp)?4>jq1G3?Zj zvP{A~TKAB@mkfi`d{Iz&h*y1K(Y+g)kn!&c1nwlwq*3}2_9A-~V1EBB-}Q4Wex8NN zf=Z~UmfkP%>Yuat7c72_#jmsYS1kSwi+{_aEk5K*H2!~t2kV>{t#E|lO_)?>c2{-; zpN#w)@YrSnpN>ED(O$;Kr?aSSBJszq$~ufAWh6nn0bQnpdpp?ablW_kFQRq!mGJP` zI*1czx5*8V$V+kpuc+s}wHoUkY)pL}Pn9v% zj%zB4?}9;WSCQO0(H&%pMW?<1=K@>~O=K??i;4o;?`z}p-(e!Z$Cr}MXkw=gk9Ga= zcNkCG_yg`lTZQ48_<1tmFca(xao9C;?>9I+m4oPyve?8&pnV+|5*Gp!JVE&v{kRFQ z;N&8sgVg~sLH8-t1#I4s`5`4Vz8-+J!qcPdl~XoKbI{2kTY%?Bhm`%&9$nnP*}?}I z3W%qkJr<0|enFh>VAgi=;)OYQGnuw11w6(-$!jrWSm38=-ov-B!&W{NKw-?1nbV*G z4?3L>caP_uY&{URh{T#SNi>)k_I`om|3emSW-9zdtlB&uJcz=U-*#eu<&C91tq@Lt zMxL@T8JewVIt5uAmu=K*`01!NS%{W+k8ovrO*te^p~f5LPe>=+_nKsi=U9sVgM=Jh z$ESk35I)&=zz!-P0n)i5R6s-FZd3rwZleR`V`*mTV^JXuWQPnONS!-@ANr&JrQ?~2 zpaoCgnVSPh=0U2@mg#+uq8afo3`_RN&wz49Ksh`|HngD*Jhb~D$0QQIu}@-G!TT+& z!26FZej5d-MFeJCbSxckg^2HyN-`d%k|feIeuBexqD_JV60A6nhpm@-@4YrEBm<{! z@`$49AH+x%?T7I$PWvxq#)gT}IpeeQtw%cd%vHE?%3gg9jJru9M5X}Z3n%ZoFT~Nq zeUV5;5wVL`sk9VuOj_fz59|SsDuA#DYdBwwQ&miq ziP4^*$utgU5syYOnrY!X%U`20;<#qt{n19scCPOICTH-wEX2Foo{LF;HH#0G5h_Q-t+Zf?cyMs@g_Vt5-t#JhJAW3`nm zxq?p*-$<2{;3$3{PbHBs)-R@>+4^?;sK}aEqdMQt{y-p~!qw+5A2JC;4t?X@I1ZA_ zhkqNCaW95^^r(-B_0c*`IF_p$aTD)R%&7C{!i0wkt(5TWEfo|;n1g! zA3u%r^-DXW?>UU$jXn{)j7W)f(i4r!87rU`{?URZ=oy%9>nfUs3pTPKccxO6t2>Ay;RtMO~ zW0>X{2uUQ(NZ743r0q8gS-bL(|4t;6{FF$p_{=%sp{sh*nKS*H;%EJHLgD^P61X40 z7uictu8xaX&%vq)`Ul@svQrXr<(#?Tw>Rq_QR$pB>B`?an|BAewJC zcFV+!izI8Lk`ra>gsz0;pfi{wm}UzEM$AY~-_xAEXOJ@iFMLnqrGVM>!`O(dOyW#P z@M{NUrHWP!xZSE22XU@;aA!w|JWdNCG=|Vv9h`8C%JwfUe-qt@jZcT82hl5|w29)P zh)uMs%)BnEsM6(3&Fh6QbtBU_dNLNr!DU}np7(}+%NU8#b-Ee(oC8wXk!S3qec4`D3@qc@{XLbcl3mu)2~pcEnorHF5GB! z>&FJ*swcWp0n@!N_7=@fU`clKOX^0XpBZos>;_+hur;>)<-5gR-ndc$(g0nz6+8lE z`D;yPv}QAowH$ECr303BO7}09l0QkYT%whfc^((?1{`R+f-puM>Qe^8q0UEtu+F;IU+t_5 zrWo$iijn}fud)QU+2+3eDEr^FdzWI|!{{wLPQStx) literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/tests/__pycache__/draw_test.cpython-39.pyc b/venv/Lib/site-packages/pygame/tests/__pycache__/draw_test.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0c4a6770ecbd0d1f965838b76c09cfaaaaeb346c GIT binary patch literal 142718 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
    v!p_i2})hVAxKk~rhto#WU@Ih)0Qrv>b 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/tests/__pycache__/font_test.cpython-39.pyc b/venv/Lib/site-packages/pygame/tests/__pycache__/font_test.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5337cfcdd15894ff2d57bdfb90149305f33b0f64 GIT binary patch literal 19021 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 P=p(Vs{_{i6WQ_j@uWhVK literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/tests/__pycache__/ftfont_tags.cpython-39.pyc b/venv/Lib/site-packages/pygame/tests/__pycache__/ftfont_tags.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..80cab24cea0b32fda5d1a76d2eda83a73255c05f GIT binary patch literal 382 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 O;tnQ%5%)niz<&dFM}KGl literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/tests/__pycache__/image_tags.cpython-39.pyc b/venv/Lib/site-packages/pygame/tests/__pycache__/image_tags.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..251eeb820f6ff59b5b06b475219d60ee48b368bf GIT binary patch literal 329 zcmYjLO-sZu5KYor%icEXzWVw3NB&pf$&GJ3_mB}zG|{x6oKBN*rWvqZ(9z}$ z$Xlp`cS`-mh9u#aSCFUuQ9Wd;gq0~(1_>J@lU23>evEBeH+Bn%a$Y3|JeJa_45j4J zEE@wHa6BxnZVSLMf)@vs{vb`{%_sOacbDQBp+TXlN};$1%$==;H{U_-28piKMv2=8 z+1owjvNyW0{UAE1I`L>yfyTi_t+u&Oh+=-cc7P7oQ|c+xsvgGpY7TNu{dbH#ge;~p GThL$6r(m7{ literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/tests/__pycache__/image_test.cpython-39.pyc b/venv/Lib/site-packages/pygame/tests/__pycache__/image_test.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..029a5115b631e37dae857188bea097b79ab8535e GIT binary patch literal 25278 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 X@E}Lm&zZD$x&H9PN37o8Y2W_eP#*F& literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/tests/__pycache__/imageext_tags.cpython-39.pyc b/venv/Lib/site-packages/pygame/tests/__pycache__/imageext_tags.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..24c78dd68dddc952b9e05a30cdd872a0395d9b47 GIT binary patch literal 335 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 E0gynX*Z=?k literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/tests/__pycache__/key_test.cpython-39.pyc b/venv/Lib/site-packages/pygame/tests/__pycache__/key_test.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..490c80e67bfff7a799cd5aa747656310bad4ce71 GIT binary patch literal 3557 zcma)8Pj4H?72nxEq#*;S-4fh4=_g27_N87WIr zyY$S`Dp~7fUyJ%9P)A?-5&A*)R`jHMP6dkg_hw0nlqs|%_U+r5H*enG-%MC8dj@|0 zu6%f~yu5RjgNyNgAlcX1Cc0>C?`7J5-9Y ztjK1=?BAL2Z1qy;|94VSZmOoF^2qGx-6)j>u-d7EnyNWzgop#upYP6#R zvPi~Kx(v%@F7sIb=A_A5YQj_s??hQprM8VzP*jxFpXZ5Cl_;%5$DKr`UrDN?T9sv9 zp21b*4y9u&(LU5>Uk&FhB{s-c-^JQdFjpom8@z5jXTB#L=*q9#0{T$1m)!2bj@5n4v!K4mYBf%TG|F=l|XU$WFWGm(Tsvp8@$ z#<|(D-Z1$9D`o~BR+uk=0qFU!xqZY=O&V{`(%1@VEpg{BwBBfz2XnkYdNn^kOzq{a z7kgpfh1>!yc|%JUnv1+Rw)0Iry2RaAY{U5e&Z(8&8Y~kYjO%~?ck%{W^e)4>Y1WPO z+Y>3PGR7s#rsng+MY3e4QW%*q-2>)lglB*To~14nKAUs=qE7w;Qym};&;p8kKt zLq%NmYX1D*#!m2TYh&}2FW|(SQ9_^={s<77ERurIt8M8eJv0KMRNuGJPDjmGBqxk1e$ot2B%o zBD116&CEn)MIcZllQ^@mT9%>Q_u3JP@;Ko_WiFaRv%dHE>CVpH`tIgtEpr5bEA{o{ zkqi%fyVE`HWM00_zU;!}MjJ?x*)cHFFGh_djt+a7Bg6Oz7@9^vQb)Cg=*U^@nU(UT zyJ4iTt0SaLWVIl1fC2eOK9z?}9w-DwWh}^8l$nj=t6jCA`(-Q|6{u04gBZ4l#xI$R zrUwWpux0Rign6cCmY8SZVI{U;Vg}qCIHLWZOliom4JLYx5QAV;_gV$as6s})hHrZX zCnfcnt_icIk)!J5AhCiqc{V#zAdNg5W^?m-H*EXG?O=E7$?x`o);c}~s96_IbiHcuJ!hImcuzJz5w>p_sZ9vnFmh zXFv#@d8Z~CeoEv+kj#4)w!31J zI!As+qlEW486Dkd>ye5*Oy;Mdj?1#yf9C)nlfFJWFQ6x{Z&3J~pCWq1Iine!?F$Kg z9w0*Yn1qhcg#@8@;kU*#O~aXC*W}lM;$@-acm&*1{>=6_-);o!`@1_jhWTwl&$xQ# z(a!$V7~Rr!Lzst?HJ}F9izrrfD>MKFOC}!t`#+mfNmp0C6SoUo*oC&sN;w;%0oBLA zraSgz=V0EZk$ir51`RuKw02leKm}@7P0s0(cs>t;(O=Q%7sNYP3(F%c9G7(Pr63^08_vu& z=-zuQ(jO8o$umhgk#q@_H$XDCi~As%hZ|Qb>d2qd%qK*CLFAW2=oFB@CUV&xnxh_( z1l`0ax{SHZ#DPGM>$(Np7^|-BI&RUO(Q;(-aTvuxQ1#?{kk2gDQ}TUq@*xq*wWQ$t p?mmoK4{;#V2J%ag%%-)|jL6(C^8oyY@~8;n>ApJrTZ`Of{{^MkMiu}7 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/tests/__pycache__/mask_test.cpython-39.pyc b/venv/Lib/site-packages/pygame/tests/__pycache__/mask_test.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b834562550413f1c2f0794a769643d620e83322b GIT binary patch literal 163209 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/tests/__pycache__/mixer_music_tags.cpython-39.pyc b/venv/Lib/site-packages/pygame/tests/__pycache__/mixer_music_tags.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3062ba2e96ea26c77a169b91835e1ffe10493237 GIT binary patch literal 341 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 H*@FH8@xx%^ literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/tests/__pycache__/mixer_test.cpython-39.pyc b/venv/Lib/site-packages/pygame/tests/__pycache__/mixer_test.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7aaae4cddaaecaba20b0fb02103ef6a2076dacf6 GIT binary patch literal 30281 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 ZJ2i*lJp6H^`+reV#Sd=c<3=@S{$Gp-MEL*! literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/tests/__pycache__/pixelcopy_test.cpython-39.pyc b/venv/Lib/site-packages/pygame/tests/__pycache__/pixelcopy_test.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f9546dcf382addc4dac38e2bc89f9c0a23f14230 GIT binary patch literal 18170 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 I-g;pFUnI%x>i_@% literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/tests/__pycache__/rect_test.cpython-39.pyc b/venv/Lib/site-packages/pygame/tests/__pycache__/rect_test.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7908fe5f30ddc4c7db4d07d7d7b0e415c988ec30 GIT binary patch literal 66131 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­wegQld2E9y#Y@>@E=~ui_Pc5xlg(wz7zL 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 YZB4A-rSMY!c|a<+O7>!7@v3Y77h?vul>h($ literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/tests/__pycache__/scrap_tags.cpython-39.pyc b/venv/Lib/site-packages/pygame/tests/__pycache__/scrap_tags.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4b3594fb1adf59aaa92673751e2b0a92ce3b2192 GIT binary patch literal 238 zcmYjKv1$TA6nuAqAQB7zz)G-C`w&8cHUUW!(i{(#cejsab9%e%+w-{mOzQlSZ9XBL zAh?<)12ZrKGee`%5E4$4Y5A1{{9Md`qzs-Co7j?QE1e{dapC9&0(@cBh`?vrcP zS-o{#k9%(RxUnUQjXd{M)nr)E_l9=7j4V->QU&tY*M;v7gNL2d?Uo<2^!}R&XM@N` Ak^lez literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/tests/__pycache__/scrap_test.cpython-39.pyc b/venv/Lib/site-packages/pygame/tests/__pycache__/scrap_test.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1fe308470e6f473e76350325e0fe1d0f846d229c GIT binary patch literal 9669 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 Hj|BJ+?ACCt literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/tests/__pycache__/sndarray_test.cpython-39.pyc b/venv/Lib/site-packages/pygame/tests/__pycache__/sndarray_test.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2a26136801cdea490e6d0be06c6d4af6a633df91 GIT binary patch literal 5569 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/tests/__pycache__/sprite_test.cpython-39.pyc b/venv/Lib/site-packages/pygame/tests/__pycache__/sprite_test.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..da4fdea50afcabe179763497d29ac1fd571b2ad8 GIT binary patch literal 36482 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/tests/__pycache__/surface_test.cpython-39.pyc b/venv/Lib/site-packages/pygame/tests/__pycache__/surface_test.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b1864ad85b352678841bd0a411edf2904e021f14 GIT binary patch literal 98920 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
    Ew1?m0-;64k;C*4nhMYp&A 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Ǟ$WgkI%ci4aqp{9R=t9AfGI^09|1$FPH_TQ9=rG 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 TUVu#3K|nl0aNGITCVTh?VtRJ* literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/tests/__pycache__/surfarray_test.cpython-39.pyc b/venv/Lib/site-packages/pygame/tests/__pycache__/surfarray_test.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..80b96d3c39800a1e526bc52930aed1d3bb43a010 GIT binary patch literal 18845 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/tests/__pycache__/surflock_test.cpython-39.pyc b/venv/Lib/site-packages/pygame/tests/__pycache__/surflock_test.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..631da5579554afea6d2380facdacd89b8d47c713 GIT binary patch literal 2852 zcmbUjO>g5wbY}b!Cr#PX4O%UqJs_k=uq$yy2<@t{s8Ur`v>euou$<1gxN#ga<7}HK zWe+X?BR%#HaO7ujm@B9L1tcWi8^>|lO-mO?d44nV{JuXXTwQGtc>dY=tb4Lf$X~cv zd>mLjgTML-04JO##4p~|r)JH3X5N->aVFT*z92p3JAzDI;c)AMeNVW}opZur@2GZW zol)Ntb?)|<^nt2zK`8LuBkkH1$RIn~-W~0Z#*ea5Hri0VINRu@gX44~3gcub#Q_p6 zJ`5Jm;IBRhAPA}jDpAhP38-Xo8{VJ*cj4{u8u#Gs@;V4?=m&d48HER8dvMU(7b-uX zz@vPSG1|WgfAu?noJ=XF7xa`)=#-(}6Ed{`2b(#&VDq(eK_)b!X6GK1KwErGr|!ME z-lPOiFUsdOt~uEwm(I>5yFx>x3t<1nCAeC<+2}Cr3tgLeK-&rUK(B;K37LQQ%P>rI z<51)QZVRsKC9bqPOmVZ#w5>!EX{I7sL-q*%PBy>l{0KZ$Crr~&b-op=o(!&u(g1XAKwV~llj-z0&fEobd?GGpO6OE0}r95 zr)<7wO)N+PhN%t#K%CBSGPQGZ+J76jlJdWKm9`c(p^cRV#>SZi6{qU_?JRs7oyvm0)xP_9tE9ok z(5~%BYzuAs3frE12;d5vo^0VRlV%se{tHvv?G@?aaUFo)P{S^kBXm#S?j~`rn?>*V zA&iw!+7VI?q{Q(e-$Af~0IO840%+Uv0pe=_dyj?sGaNOVoIoORW+k6pu1TtE5?@vgV(@ZVIgCUc;Lih9xkizvK2y`O|`U5^p5N`$nUJQy83HL=JA0fc8D?dUozXuc;mas(U zV;fM|JfIdIdfQ&h?4p={7^gwdUh%zQ8s}($w$w;zFH6Ea8pyuMH~n5V%6}fDLEO(0 z(HChR=J6o)Yg>E4?#tbmzKb`-t;qNGfx~797Z4OHKL(&}l(9@T?R{O?_6>G9g$8*P Qe#~P{t3g|@iR00K0k|oT00000 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/tests/__pycache__/sysfont_test.cpython-39.pyc b/venv/Lib/site-packages/pygame/tests/__pycache__/sysfont_test.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..904f6139cf41e1feb43dbe651a826eeb19d4891b GIT binary patch literal 2040 zcmbtV-D(?06rP#g)vnjFW6NopmNvLQ2~i;mq)XN zS(Qkx><5u9{RDlNx$Tu-q0rKEW@U9{TM)>?o;@>j&dm3npINc75fga+*?sit&w!A> za8P}G7<><}`3i(2l4c|+zcisg63L`@PNb*E2|M!=Px;dCGW|@EX)q%c><>sYxCCFa z-$7Y@;JkA0b5ImXs3ZxKRI+oDc+!(Te0>#6Ycf#bG@OxBDr++)Lm8cuGnzzlO~zoe zwq!#FzsmKwJ&|>=-;kTmK6Z9jYgFEWwJo{r*4AYMknY&+gRwd4=f%%`In30dGDU}0 zFf-6GBzy3dApy`Cc|%{*6FOx`*=e5B$kZ11saN) z^cqfL=t{AH%i9iLH8VJEaFdeN%Lg-PNPqy~^#coe@c1LR0bkjj=HP_GK zgaubJr3C|q-qd#tS*5hRva~L-uP=g<>4IO$`3@}IO7H#+dR#iBJK$k3XoN*<^2J+l zoI5TN!r(8G_caU_gsycDUMn;9hP^I32&rNZv8(=R`X$LEc&<~CT|S1rnqjg&?+NxXlP1Yr2`S#!Yx3$yt)ES%qdvu-2KbGUjrw=w5Ecj1Fx z=lu7f$jTMHiKwB!)bU=X#9O( z1DN|DA{vEJtwG};3VnKyvVWN$2My}15L{2BIp=U&eS*H9f=Hr60I&yt0B58hz?}8b Y?zZD>^li!NJN(zUf`v1^#*>Kt2eNecH2?qr literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/tests/__pycache__/test_test_.cpython-39.pyc b/venv/Lib/site-packages/pygame/tests/__pycache__/test_test_.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..624b5fa966cbfaffa32f839741ab6656d60abc2f GIT binary patch literal 200 zcmYe~<>g`kg1-uCNuogdF^Gc>9DoAFY(S!rA%!8BL6gyMB|{M-kdGjKWjb5Mgche3 z6~`pz$CqcOPO2Tq L3B^o6f`JhL>o+$z literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/tests/__pycache__/threads_test.cpython-39.pyc b/venv/Lib/site-packages/pygame/tests/__pycache__/threads_test.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fd3693a19886be6fe04c449f4c556be502012302 GIT binary patch literal 7008 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/tests/__pycache__/time_test.cpython-39.pyc b/venv/Lib/site-packages/pygame/tests/__pycache__/time_test.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a233702c947775e345fd6308a53243ddd4fc2c5a GIT binary patch literal 7840 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 I-gNc<1yXZm-2eap literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/tests/__pycache__/touch_test.cpython-39.pyc b/venv/Lib/site-packages/pygame/tests/__pycache__/touch_test.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..de96604e1d366a63e1ed763e920dbbef24229b5e GIT binary patch literal 3458 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 vQ{XH;>Vv|+6RrDM7`poDjs~YP8uI+iS0Pw=?S` zw$>7obLZZZeeA!(aju;FFCd}vX6+8==4S z&-$?7=UZ6vdms!k93gM{#UAFUXUt4yFq4tF>5)f>SSY5 zJ4YDKAE3Is09~lzSyBWvP)-;J(U9?RiKe5DKj7QlKntvoOE&$}I>Fnd2Ur z*adGDyi@RY!MmB2*;D+-?~_tq+C$HJlX4DvAZTZ~otLM0QpqdgEOYY8%w^6T17hT0 z1tebN&ZWeQYZ7Ko3W;X!UP?5tNs#BwUm%eL=G4R}-uxWNKOaDf^!yc8j%KCY$Z@aC z@cU?PtPrz6oHc|Lh`U4>f@qf-LWk`oR?f*X>Wfz}#-A__(d8|9_vs`0)6S1in)K*l z^I-o;1E9}-dvNc|XLswbN$ofOht$)Z!`&a=qHCeuSQtR+6=g50OXylshTzHxl0h0q zT-lQQBIqiTq&!xov_rexXIv;Vj5B3*L^4cO#g~$c?BVmFA9*(1D;^H&RYfF^+J#OJ z4tD9l?&w<2m;EeBTd7ETyq}Gz%!VxVTRZ#oG#T?gJq=luoQ_&2JU(eX4v$+h z%=o?35Bh$G%hobH_cLe^d4H8Rs{gjrk-DWB3X!?k2$EQaGUIVDDuFjrHzp!ggJ3;f zql)z`W4D+DZ@l*1##=DQcaE;wa{E7Q1nYgM6G~teefTjj>wO4yYh=1g$rLkF*KJXg zWLc9!pIewf>Xy)s7pW8P0H@4|$DVnx_qc9|t;;PP>muOdT`ja(I4N0l5s5mWQfo!H zYK(8cai2BO22`O-X$)^1rK(KnAYsEu^HoZ9U9EQ9VH{@Kj%Q1FsP@~+NTecA6kTP9 zvJEvWHo%~GPm^1kTzOe=+Et-%sh=yU>&}I&Y`ike@&^U3{TTRROliF&YOpUp)Z`-| tiu95&E)00?A$YOtLzQV|;&!pE&%Mo{a=%_)=o_7^l~vc=G`H@!_+Lbttor}} literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/tests/__pycache__/video_test.cpython-39.pyc b/venv/Lib/site-packages/pygame/tests/__pycache__/video_test.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9d191c7121e16ed236e3a684c3df190823f26116 GIT binary patch literal 1098 zcmZ`&U5gVj6iqVeblRPDcST=(ah`+`t-6AUh$!m^E9)ZbC&NIfCwj^r1P5eyLCZ&Gz78*5meMZq7OI;gb&d5a^t0g zd{T&ECZ9`Vr|W}BhxcVPR=Fs~nfHr`qUrhT+tH!2(X;z|(RS-<>)MUz4L1?bBW27` zw%T|_l+)zH+<|GHLa?ZdXQ&Ih1o=dcG34G13-1#?230e{sIAR?QG=f^>I-`8&B(ky z^A;GR8Q1|?V}V4lAYe-av^S^zxX?Y*iiwIqrg{yR5|grKmCa;HjhagE%&!g-lau## zgidaPFztkD$dC>o#I!2>UEPnH8URt^zgjv`ZU}kAhnZzUlh8=ZMoNwcg|_7yH%4mv;O&rSN!VH0iYZ8z*^zdxm4W_^O*No= zM*0+#zp0&D=?efbDbI6m()-f%Y%xd&y6DQDoiJmELhfTi-o#Bj zz4%Wjwf+yVA2-T?u^jr0v9ifnf7ySq4jFUSR6Du>6lE~Xm33H&Z+dF5dsKR6V#<1- zzjJo$O?YYP&Pv#DHP^cCewR`MObG><") if is_lil_endian else (">", "<") + buftools = self.buftools + Importer = buftools.Importer + a = BufferProxy( + {"typestr": "|u4", "shape": (10, 2), "data": (9, False)} + ) # 9? No data accesses. + b = Importer(a, buftools.PyBUF_SIMPLE) + self.assertEqual(b.ndim, 0) + self.assertTrue(b.format is None) + self.assertEqual(b.len, a.length) + self.assertEqual(b.itemsize, 4) + self.assertTrue(b.shape is None) + self.assertTrue(b.strides is None) + self.assertTrue(b.suboffsets is None) + self.assertFalse(b.readonly) + self.assertEqual(b.buf, 9) + b = Importer(a, buftools.PyBUF_WRITABLE) + self.assertEqual(b.ndim, 0) + self.assertTrue(b.format is None) + self.assertEqual(b.len, a.length) + self.assertEqual(b.itemsize, 4) + self.assertTrue(b.shape is None) + self.assertTrue(b.strides is None) + self.assertTrue(b.suboffsets is None) + self.assertFalse(b.readonly) + self.assertEqual(b.buf, 9) + b = Importer(a, buftools.PyBUF_ND) + self.assertEqual(b.ndim, 2) + self.assertTrue(b.format is None) + self.assertEqual(b.len, a.length) + self.assertEqual(b.itemsize, 4) + self.assertEqual(b.shape, (10, 2)) + self.assertTrue(b.strides is None) + self.assertTrue(b.suboffsets is None) + self.assertFalse(b.readonly) + self.assertEqual(b.buf, 9) + a = BufferProxy( + { + "typestr": fsys + "i2", + "shape": (5, 10), + "strides": (24, 2), + "data": (42, False), + } + ) # 42? No data accesses. + b = Importer(a, buftools.PyBUF_STRIDES) + self.assertEqual(b.ndim, 2) + self.assertTrue(b.format is None) + self.assertEqual(b.len, 100) + self.assertEqual(b.itemsize, 2) + self.assertEqual(b.shape, (5, 10)) + self.assertEqual(b.strides, (24, 2)) + self.assertTrue(b.suboffsets is None) + self.assertFalse(b.readonly) + self.assertEqual(b.buf, 42) + b = Importer(a, buftools.PyBUF_FULL_RO) + self.assertEqual(b.ndim, 2) + self.assertEqual(b.format, "=h") + self.assertEqual(b.len, 100) + self.assertEqual(b.itemsize, 2) + self.assertEqual(b.shape, (5, 10)) + self.assertEqual(b.strides, (24, 2)) + self.assertTrue(b.suboffsets is None) + self.assertFalse(b.readonly) + self.assertEqual(b.buf, 42) + self.assertRaises(BufferError, Importer, a, buftools.PyBUF_SIMPLE) + self.assertRaises(BufferError, Importer, a, buftools.PyBUF_ND) + self.assertRaises(BufferError, Importer, a, buftools.PyBUF_C_CONTIGUOUS) + self.assertRaises(BufferError, Importer, a, buftools.PyBUF_F_CONTIGUOUS) + self.assertRaises(BufferError, Importer, a, buftools.PyBUF_ANY_CONTIGUOUS) + self.assertRaises(BufferError, Importer, a, buftools.PyBUF_CONTIG) + self.assertRaises(BufferError, Importer, a, buftools.PyBUF_SIMPLE) + self.assertRaises(BufferError, Importer, a, buftools.PyBUF_ND) + self.assertRaises(BufferError, Importer, a, buftools.PyBUF_C_CONTIGUOUS) + self.assertRaises(BufferError, Importer, a, buftools.PyBUF_F_CONTIGUOUS) + self.assertRaises(BufferError, Importer, a, buftools.PyBUF_ANY_CONTIGUOUS) + self.assertRaises(BufferError, Importer, a, buftools.PyBUF_CONTIG) + a = BufferProxy( + { + "typestr": frev + "i2", + "shape": (3, 5, 10), + "strides": (120, 24, 2), + "data": (1000000, True), + } + ) # 1000000? No data accesses. + b = Importer(a, buftools.PyBUF_FULL_RO) + self.assertEqual(b.ndim, 3) + self.assertEqual(b.format, frev + "h") + self.assertEqual(b.len, 300) + self.assertEqual(b.itemsize, 2) + self.assertEqual(b.shape, (3, 5, 10)) + self.assertEqual(b.strides, (120, 24, 2)) + self.assertTrue(b.suboffsets is None) + self.assertTrue(b.readonly) + self.assertEqual(b.buf, 1000000) + self.assertRaises(BufferError, Importer, a, buftools.PyBUF_FULL) + + @unittest.skipIf(IS_PYPY or (not pygame.HAVE_NEWBUF), "newbuf with ctypes") + def test_PgObject_AsBuffer_PyBUF_flags(self): + from pygame.bufferproxy import BufferProxy + import ctypes + + is_lil_endian = pygame.get_sdl_byteorder() == pygame.LIL_ENDIAN + fsys, frev = ("<", ">") if is_lil_endian else (">", "<") + buftools = self.buftools + Importer = buftools.Importer + e = arrinter.Exporter( + (10, 2), typekind="f", itemsize=ctypes.sizeof(ctypes.c_double) + ) + a = BufferProxy(e) + b = Importer(a, buftools.PyBUF_SIMPLE) + self.assertEqual(b.ndim, 0) + self.assertTrue(b.format is None) + self.assertEqual(b.len, e.len) + self.assertEqual(b.itemsize, e.itemsize) + self.assertTrue(b.shape is None) + self.assertTrue(b.strides is None) + self.assertTrue(b.suboffsets is None) + self.assertFalse(b.readonly) + self.assertEqual(b.buf, e.data) + b = Importer(a, buftools.PyBUF_WRITABLE) + self.assertEqual(b.ndim, 0) + self.assertTrue(b.format is None) + self.assertEqual(b.len, e.len) + self.assertEqual(b.itemsize, e.itemsize) + self.assertTrue(b.shape is None) + self.assertTrue(b.strides is None) + self.assertTrue(b.suboffsets is None) + self.assertFalse(b.readonly) + self.assertEqual(b.buf, e.data) + b = Importer(a, buftools.PyBUF_ND) + self.assertEqual(b.ndim, e.nd) + self.assertTrue(b.format is None) + self.assertEqual(b.len, a.length) + self.assertEqual(b.itemsize, e.itemsize) + self.assertEqual(b.shape, e.shape) + self.assertTrue(b.strides is None) + self.assertTrue(b.suboffsets is None) + self.assertFalse(b.readonly) + self.assertEqual(b.buf, e.data) + e = arrinter.Exporter((5, 10), typekind="i", itemsize=2, strides=(24, 2)) + a = BufferProxy(e) + b = Importer(a, buftools.PyBUF_STRIDES) + self.assertEqual(b.ndim, e.nd) + self.assertTrue(b.format is None) + self.assertEqual(b.len, e.len) + self.assertEqual(b.itemsize, e.itemsize) + self.assertEqual(b.shape, e.shape) + self.assertEqual(b.strides, e.strides) + self.assertTrue(b.suboffsets is None) + self.assertFalse(b.readonly) + self.assertEqual(b.buf, e.data) + b = Importer(a, buftools.PyBUF_FULL_RO) + self.assertEqual(b.ndim, e.nd) + self.assertEqual(b.format, "=h") + self.assertEqual(b.len, e.len) + self.assertEqual(b.itemsize, e.itemsize) + self.assertEqual(b.shape, e.shape) + self.assertEqual(b.strides, e.strides) + self.assertTrue(b.suboffsets is None) + self.assertFalse(b.readonly) + self.assertEqual(b.buf, e.data) + self.assertRaises(BufferError, Importer, a, buftools.PyBUF_SIMPLE) + self.assertRaises(BufferError, Importer, a, buftools.PyBUF_WRITABLE) + self.assertRaises(BufferError, Importer, a, buftools.PyBUF_WRITABLE) + self.assertRaises(BufferError, Importer, a, buftools.PyBUF_ND) + self.assertRaises(BufferError, Importer, a, buftools.PyBUF_C_CONTIGUOUS) + self.assertRaises(BufferError, Importer, a, buftools.PyBUF_F_CONTIGUOUS) + self.assertRaises(BufferError, Importer, a, buftools.PyBUF_ANY_CONTIGUOUS) + self.assertRaises(BufferError, Importer, a, buftools.PyBUF_CONTIG) + self.assertRaises(BufferError, Importer, a, buftools.PyBUF_SIMPLE) + self.assertRaises(BufferError, Importer, a, buftools.PyBUF_ND) + self.assertRaises(BufferError, Importer, a, buftools.PyBUF_C_CONTIGUOUS) + self.assertRaises(BufferError, Importer, a, buftools.PyBUF_F_CONTIGUOUS) + self.assertRaises(BufferError, Importer, a, buftools.PyBUF_ANY_CONTIGUOUS) + self.assertRaises(BufferError, Importer, a, buftools.PyBUF_CONTIG) + e = arrinter.Exporter( + (3, 5, 10), + typekind="i", + itemsize=2, + strides=(120, 24, 2), + flags=arrinter.PAI_ALIGNED, + ) + a = BufferProxy(e) + b = Importer(a, buftools.PyBUF_FULL_RO) + self.assertEqual(b.ndim, e.nd) + self.assertEqual(b.format, frev + "h") + self.assertEqual(b.len, e.len) + self.assertEqual(b.itemsize, e.itemsize) + self.assertEqual(b.shape, e.shape) + self.assertEqual(b.strides, e.strides) + self.assertTrue(b.suboffsets is None) + self.assertTrue(b.readonly) + self.assertEqual(b.buf, e.data) + self.assertRaises(BufferError, Importer, a, buftools.PyBUF_FULL) + + def test_PgObject_GetBuffer_exception(self): + # For consistency with surfarray + from pygame.bufferproxy import BufferProxy + + bp = BufferProxy(1) + self.assertRaises(ValueError, getattr, bp, "length") + + def not_init_assertions(self): + self.assertFalse(pygame.get_init(), "pygame shouldn't be initialized") + self.assertFalse(pygame.display.get_init(), "display shouldn't be initialized") + + if "pygame.mixer" in sys.modules: + self.assertFalse(pygame.mixer.get_init(), "mixer shouldn't be initialized") + + if "pygame.font" in sys.modules: + self.assertFalse(pygame.font.get_init(), "init shouldn't be initialized") + + ## !!! TODO : Remove when scrap works for OS X + import platform + + if platform.system().startswith("Darwin"): + return + + try: + self.assertRaises(pygame.error, pygame.scrap.get) + except NotImplementedError: + # Scrap is optional. + pass + + # pygame.cdrom + # pygame.joystick + + def init_assertions(self): + self.assertTrue(pygame.get_init()) + self.assertTrue(pygame.display.get_init()) + + if "pygame.mixer" in sys.modules: + self.assertTrue(pygame.mixer.get_init()) + + if "pygame.font" in sys.modules: + self.assertTrue(pygame.font.get_init()) + + def test_quit__and_init(self): + # __doc__ (as of 2008-06-25) for pygame.base.quit: + + # pygame.quit(): return None + # uninitialize all pygame modules + + # Make sure everything is not init + self.not_init_assertions() + + # Initiate it + pygame.init() + + # Check + self.init_assertions() + + # Quit + pygame.quit() + + # All modules have quit + self.not_init_assertions() + + def test_register_quit(self): + """Ensure that a registered function is called on quit()""" + self.assertEqual(quit_count, 0) + + pygame.init() + pygame.register_quit(quit_hook) + pygame.quit() + + self.assertEqual(quit_count, 1) + + def test_get_error(self): + + # __doc__ (as of 2008-08-02) for pygame.base.get_error: + + # pygame.get_error(): return errorstr + # get the current error message + # + # SDL maintains an internal error message. This message will usually + # be given to you when pygame.error is raised. You will rarely need to + # call this function. + # + + # The first error could be all sorts of nonsense or empty. + e = pygame.get_error() + pygame.set_error("hi") + self.assertEqual(pygame.get_error(), "hi") + pygame.set_error("") + self.assertEqual(pygame.get_error(), "") + + def test_set_error(self): + + # The first error could be all sorts of nonsense or empty. + e = pygame.get_error() + pygame.set_error("hi") + self.assertEqual(pygame.get_error(), "hi") + pygame.set_error("") + self.assertEqual(pygame.get_error(), "") + + def test_unicode_error(self): + pygame.set_error("你好") + self.assertEqual("你好", pygame.get_error()) + + def test_init(self): + """Ensures init() works properly.""" + # Make sure nothing initialized. + self.not_init_assertions() + + # display and joystick must init, at minimum + expected_min_passes = 2 + + # All modules should pass. + expected_fails = 0 + + passes, fails = pygame.init() + + self.init_assertions() + self.assertGreaterEqual(passes, expected_min_passes) + self.assertEqual(fails, expected_fails) + + def test_get_init(self): + # Test if get_init() gets the init state. + self.assertFalse(pygame.get_init()) + + def test_get_init__after_init(self): + # Test if get_init() gets the init state after pygame.init() called. + pygame.init() + + self.assertTrue(pygame.get_init()) + + def test_get_init__after_quit(self): + # Test if get_init() gets the init state after pygame.quit() called. + pygame.init() + pygame.quit() + + self.assertFalse(pygame.get_init()) + + def todo_test_segfault(self): + + # __doc__ (as of 2008-08-02) for pygame.base.segfault: + + # crash + + self.fail() + + +if __name__ == "__main__": + unittest.main() diff --git a/venv/Lib/site-packages/pygame/tests/blit_test.py b/venv/Lib/site-packages/pygame/tests/blit_test.py new file mode 100644 index 0000000..906e7c4 --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/blit_test.py @@ -0,0 +1,155 @@ +import unittest + +import pygame +from pygame.locals import * + + +class BlitTest(unittest.TestCase): + def test_SRCALPHA(self): + """SRCALPHA tests.""" + # blend(s, 0, d) = d + s = pygame.Surface((1, 1), SRCALPHA, 32) + s.fill((255, 255, 255, 0)) + + d = pygame.Surface((1, 1), SRCALPHA, 32) + d.fill((0, 0, 255, 255)) + + s.blit(d, (0, 0)) + self.assertEqual(s.get_at((0, 0)), d.get_at((0, 0))) + + # blend(s, 255, d) = s + s = pygame.Surface((1, 1), SRCALPHA, 32) + s.fill((123, 0, 0, 255)) + s1 = pygame.Surface((1, 1), SRCALPHA, 32) + s1.fill((123, 0, 0, 255)) + d = pygame.Surface((1, 1), SRCALPHA, 32) + d.fill((10, 0, 0, 0)) + s.blit(d, (0, 0)) + self.assertEqual(s.get_at((0, 0)), s1.get_at((0, 0))) + + # TODO: these should be true too. + # blend(0, sA, 0) = 0 + # blend(255, sA, 255) = 255 + # blend(s, sA, d) <= 255 + + def test_BLEND(self): + """BLEND_ tests.""" + + # test that it doesn't overflow, and that it is saturated. + s = pygame.Surface((1, 1), SRCALPHA, 32) + s.fill((255, 255, 255, 0)) + + d = pygame.Surface((1, 1), SRCALPHA, 32) + d.fill((0, 0, 255, 255)) + + s.blit(d, (0, 0), None, BLEND_ADD) + + # print "d %s" % (d.get_at((0,0)),) + # print s.get_at((0,0)) + # self.assertEqual(s.get_at((0,0))[2], 255 ) + # self.assertEqual(s.get_at((0,0))[3], 0 ) + + s.blit(d, (0, 0), None, BLEND_RGBA_ADD) + # print s.get_at((0,0)) + self.assertEqual(s.get_at((0, 0))[3], 255) + + # test adding works. + s.fill((20, 255, 255, 0)) + d.fill((10, 0, 255, 255)) + s.blit(d, (0, 0), None, BLEND_ADD) + self.assertEqual(s.get_at((0, 0))[2], 255) + + # test subbing works. + s.fill((20, 255, 255, 0)) + d.fill((10, 0, 255, 255)) + s.blit(d, (0, 0), None, BLEND_SUB) + self.assertEqual(s.get_at((0, 0))[0], 10) + + # no overflow in sub blend. + s.fill((20, 255, 255, 0)) + d.fill((30, 0, 255, 255)) + s.blit(d, (0, 0), None, BLEND_SUB) + self.assertEqual(s.get_at((0, 0))[0], 0) + + def make_blit_list(self, num_surfs): + + blit_list = [] + for i in range(num_surfs): + dest = (i * 10, 0) + surf = pygame.Surface((10, 10), SRCALPHA, 32) + color = (i * 1, i * 1, i * 1) + surf.fill(color) + blit_list.append((surf, dest)) + return blit_list + + def test_blits(self): + + NUM_SURFS = 255 + PRINT_TIMING = 0 + dst = pygame.Surface((NUM_SURFS * 10, 10), SRCALPHA, 32) + dst.fill((230, 230, 230)) + blit_list = self.make_blit_list(NUM_SURFS) + + def blits(blit_list): + for surface, dest in blit_list: + dst.blit(surface, dest) + + from time import time + + t0 = time() + results = blits(blit_list) + t1 = time() + if PRINT_TIMING: + print("python blits: %s" % (t1 - t0)) + + dst.fill((230, 230, 230)) + t0 = time() + results = dst.blits(blit_list) + t1 = time() + if PRINT_TIMING: + print("Surface.blits :%s" % (t1 - t0)) + + # check if we blit all the different colors in the correct spots. + for i in range(NUM_SURFS): + color = (i * 1, i * 1, i * 1) + self.assertEqual(dst.get_at((i * 10, 0)), color) + self.assertEqual(dst.get_at(((i * 10) + 5, 5)), color) + + self.assertEqual(len(results), NUM_SURFS) + + t0 = time() + results = dst.blits(blit_list, doreturn=0) + t1 = time() + if PRINT_TIMING: + print("Surface.blits doreturn=0: %s" % (t1 - t0)) + self.assertEqual(results, None) + + t0 = time() + results = dst.blits(((surf, dest) for surf, dest in blit_list)) + t1 = time() + if PRINT_TIMING: + print("Surface.blits generator: %s" % (t1 - t0)) + + def test_blits_not_sequence(self): + dst = pygame.Surface((100, 10), SRCALPHA, 32) + self.assertRaises(ValueError, dst.blits, None) + + def test_blits_wrong_length(self): + dst = pygame.Surface((100, 10), SRCALPHA, 32) + self.assertRaises( + ValueError, dst.blits, [pygame.Surface((10, 10), SRCALPHA, 32)] + ) + + def test_blits_bad_surf_args(self): + dst = pygame.Surface((100, 10), SRCALPHA, 32) + self.assertRaises(TypeError, dst.blits, [(None, None)]) + + def test_blits_bad_dest(self): + dst = pygame.Surface((100, 10), SRCALPHA, 32) + self.assertRaises( + TypeError, dst.blits, [(pygame.Surface((10, 10), SRCALPHA, 32), None)] + ) + + +if __name__ == "__main__": + unittest.main() diff --git a/venv/Lib/site-packages/pygame/tests/bufferproxy_test.py b/venv/Lib/site-packages/pygame/tests/bufferproxy_test.py new file mode 100644 index 0000000..3d9c0b3 --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/bufferproxy_test.py @@ -0,0 +1,507 @@ +import re +import weakref +import gc +import ctypes +import unittest + +import pygame +from pygame.bufferproxy import BufferProxy + + +try: + BufferError +except NameError: + from pygame import BufferError + + +class BufferProxyTest(unittest.TestCase): + view_keywords = { + "shape": (5, 4, 3), + "typestr": "|u1", + "data": (0, True), + "strides": (4, 20, 1), + } + + def test_module_name(self): + self.assertEqual(pygame.bufferproxy.__name__, "pygame.bufferproxy") + + def test_class_name(self): + self.assertEqual(BufferProxy.__name__, "BufferProxy") + + def test___array_struct___property(self): + kwds = self.view_keywords + v = BufferProxy(kwds) + d = pygame.get_array_interface(v) + self.assertEqual(len(d), 5) + self.assertEqual(d["version"], 3) + self.assertEqual(d["shape"], kwds["shape"]) + self.assertEqual(d["typestr"], kwds["typestr"]) + self.assertEqual(d["data"], kwds["data"]) + self.assertEqual(d["strides"], kwds["strides"]) + + def test___array_interface___property(self): + kwds = self.view_keywords + v = BufferProxy(kwds) + d = v.__array_interface__ + self.assertEqual(len(d), 5) + self.assertEqual(d["version"], 3) + self.assertEqual(d["shape"], kwds["shape"]) + self.assertEqual(d["typestr"], kwds["typestr"]) + self.assertEqual(d["data"], kwds["data"]) + self.assertEqual(d["strides"], kwds["strides"]) + + def test_parent_property(self): + kwds = dict(self.view_keywords) + p = [] + kwds["parent"] = p + v = BufferProxy(kwds) + + self.assertIs(v.parent, p) + + def test_before(self): + def callback(parent): + success.append(parent is p) + + class MyException(Exception): + pass + + def raise_exception(parent): + raise MyException("Just a test.") + + kwds = dict(self.view_keywords) + p = [] + kwds["parent"] = p + + # For array interface + success = [] + kwds["before"] = callback + v = BufferProxy(kwds) + self.assertEqual(len(success), 0) + d = v.__array_interface__ + self.assertEqual(len(success), 1) + self.assertTrue(success[0]) + d = v.__array_interface__ + self.assertEqual(len(success), 1) + d = v = None + gc.collect() + self.assertEqual(len(success), 1) + + # For array struct + success = [] + kwds["before"] = callback + v = BufferProxy(kwds) + self.assertEqual(len(success), 0) + c = v.__array_struct__ + self.assertEqual(len(success), 1) + self.assertTrue(success[0]) + c = v.__array_struct__ + self.assertEqual(len(success), 1) + c = v = None + gc.collect() + self.assertEqual(len(success), 1) + + # Callback raises an exception + kwds["before"] = raise_exception + v = BufferProxy(kwds) + self.assertRaises(MyException, lambda: v.__array_struct__) + + def test_after(self): + def callback(parent): + success.append(parent is p) + + kwds = dict(self.view_keywords) + p = [] + kwds["parent"] = p + + # For array interface + success = [] + kwds["after"] = callback + v = BufferProxy(kwds) + self.assertEqual(len(success), 0) + d = v.__array_interface__ + self.assertEqual(len(success), 0) + d = v.__array_interface__ + self.assertEqual(len(success), 0) + d = v = None + gc.collect() + self.assertEqual(len(success), 1) + self.assertTrue(success[0]) + + # For array struct + success = [] + kwds["after"] = callback + v = BufferProxy(kwds) + self.assertEqual(len(success), 0) + c = v.__array_struct__ + self.assertEqual(len(success), 0) + c = v.__array_struct__ + self.assertEqual(len(success), 0) + c = v = None + gc.collect() + self.assertEqual(len(success), 1) + self.assertTrue(success[0]) + + def test_attribute(self): + v = BufferProxy(self.view_keywords) + self.assertRaises(AttributeError, getattr, v, "undefined") + v.undefined = 12 + self.assertEqual(v.undefined, 12) + del v.undefined + self.assertRaises(AttributeError, getattr, v, "undefined") + + def test_weakref(self): + v = BufferProxy(self.view_keywords) + weak_v = weakref.ref(v) + + self.assertIs(weak_v(), v) + + v = None + gc.collect() + + self.assertIsNone(weak_v()) + + def test_gc(self): + """refcount agnostic check that contained objects are freed""" + + def before_callback(parent): + return r[0] + + def after_callback(parent): + return r[1] + + class Obj(object): + pass + + p = Obj() + a = Obj() + r = [Obj(), Obj()] + weak_p = weakref.ref(p) + weak_a = weakref.ref(a) + weak_r0 = weakref.ref(r[0]) + weak_r1 = weakref.ref(r[1]) + weak_before = weakref.ref(before_callback) + weak_after = weakref.ref(after_callback) + kwds = dict(self.view_keywords) + kwds["parent"] = p + kwds["before"] = before_callback + kwds["after"] = after_callback + v = BufferProxy(kwds) + v.some_attribute = a + weak_v = weakref.ref(v) + kwds = p = a = before_callback = after_callback = None + gc.collect() + self.assertTrue(weak_p() is not None) + self.assertTrue(weak_a() is not None) + self.assertTrue(weak_before() is not None) + self.assertTrue(weak_after() is not None) + v = None + [gc.collect() for x in range(4)] + self.assertTrue(weak_v() is None) + self.assertTrue(weak_p() is None) + self.assertTrue(weak_a() is None) + self.assertTrue(weak_before() is None) + self.assertTrue(weak_after() is None) + self.assertTrue(weak_r0() is not None) + self.assertTrue(weak_r1() is not None) + r = None + gc.collect() + self.assertTrue(weak_r0() is None) + self.assertTrue(weak_r1() is None) + + # Cycle removal + kwds = dict(self.view_keywords) + kwds["parent"] = [] + v = BufferProxy(kwds) + v.some_attribute = v + tracked = True + for o in gc.get_objects(): + if o is v: + break + else: + tracked = False + self.assertTrue(tracked) + kwds["parent"].append(v) + kwds = None + gc.collect() + n1 = len(gc.garbage) + v = None + gc.collect() + n2 = len(gc.garbage) + self.assertEqual(n2, n1) + + def test_c_api(self): + api = pygame.bufferproxy._PYGAME_C_API + api_type = type(pygame.base._PYGAME_C_API) + + self.assertIsInstance(api, api_type) + + def test_repr(self): + v = BufferProxy(self.view_keywords) + cname = BufferProxy.__name__ + oname, ovalue = re.findall(r"<([^)]+)\(([^)]+)\)>", repr(v))[0] + self.assertEqual(oname, cname) + self.assertEqual(v.length, int(ovalue)) + + def test_subclassing(self): + class MyBufferProxy(BufferProxy): + def __repr__(self): + return "*%s*" % (BufferProxy.__repr__(self),) + + kwds = dict(self.view_keywords) + kwds["parent"] = 0 + v = MyBufferProxy(kwds) + self.assertEqual(v.parent, 0) + r = repr(v) + self.assertEqual(r[:2], "*<") + self.assertEqual(r[-2:], ">*") + + @unittest.skipIf(not pygame.HAVE_NEWBUF, "newbuf not implemented") + def NEWBUF_test_newbuf(self): + from ctypes import string_at + + from pygame.tests.test_utils import buftools + + Exporter = buftools.Exporter + Importer = buftools.Importer + exp = Exporter((10,), "B", readonly=True) + b = BufferProxy(exp) + self.assertEqual(b.length, exp.len) + self.assertEqual(b.raw, string_at(exp.buf, exp.len)) + d = b.__array_interface__ + try: + self.assertEqual(d["typestr"], "|u1") + self.assertEqual(d["shape"], exp.shape) + self.assertEqual(d["strides"], exp.strides) + self.assertEqual(d["data"], (exp.buf, True)) + finally: + d = None + exp = Exporter((3,), "=h") + b = BufferProxy(exp) + self.assertEqual(b.length, exp.len) + self.assertEqual(b.raw, string_at(exp.buf, exp.len)) + d = b.__array_interface__ + try: + lil_endian = pygame.get_sdl_byteorder() == pygame.LIL_ENDIAN + f = "{}i{}".format("<" if lil_endian else ">", exp.itemsize) + self.assertEqual(d["typestr"], f) + self.assertEqual(d["shape"], exp.shape) + self.assertEqual(d["strides"], exp.strides) + self.assertEqual(d["data"], (exp.buf, False)) + finally: + d = None + + exp = Exporter((10, 2), "=i") + b = BufferProxy(exp) + imp = Importer(b, buftools.PyBUF_RECORDS) + self.assertTrue(imp.obj is b) + self.assertEqual(imp.buf, exp.buf) + self.assertEqual(imp.ndim, exp.ndim) + self.assertEqual(imp.format, exp.format) + self.assertEqual(imp.readonly, exp.readonly) + self.assertEqual(imp.itemsize, exp.itemsize) + self.assertEqual(imp.len, exp.len) + self.assertEqual(imp.shape, exp.shape) + self.assertEqual(imp.strides, exp.strides) + self.assertTrue(imp.suboffsets is None) + + d = { + "typestr": "|u1", + "shape": (10,), + "strides": (1,), + "data": (9, True), + } # 9? Will not reading the data anyway. + b = BufferProxy(d) + imp = Importer(b, buftools.PyBUF_SIMPLE) + self.assertTrue(imp.obj is b) + self.assertEqual(imp.buf, 9) + self.assertEqual(imp.len, 10) + self.assertEqual(imp.format, None) + self.assertEqual(imp.itemsize, 1) + self.assertEqual(imp.ndim, 0) + self.assertTrue(imp.readonly) + self.assertTrue(imp.shape is None) + self.assertTrue(imp.strides is None) + self.assertTrue(imp.suboffsets is None) + + try: + pygame.bufferproxy.get_segcount + except AttributeError: + pass + else: + + def test_oldbuf_arg(self): + self.OLDBUF_test_oldbuf_arg() + + def OLDBUF_test_oldbuf_arg(self): + from pygame.bufferproxy import get_segcount, get_read_buffer, get_write_buffer + + content = b"\x01\x00\x00\x02" * 12 + memory = ctypes.create_string_buffer(content) + memaddr = ctypes.addressof(memory) + + def raise_exception(o): + raise ValueError("An exception") + + bf = BufferProxy( + { + "shape": (len(content),), + "typestr": "|u1", + "data": (memaddr, False), + "strides": (1,), + } + ) + seglen, segaddr = get_read_buffer(bf, 0) + self.assertEqual(segaddr, 0) + self.assertEqual(seglen, 0) + seglen, segaddr = get_write_buffer(bf, 0) + self.assertEqual(segaddr, 0) + self.assertEqual(seglen, 0) + segcount, buflen = get_segcount(bf) + self.assertEqual(segcount, 1) + self.assertEqual(buflen, len(content)) + seglen, segaddr = get_read_buffer(bf, 0) + self.assertEqual(segaddr, memaddr) + self.assertEqual(seglen, len(content)) + seglen, segaddr = get_write_buffer(bf, 0) + self.assertEqual(segaddr, memaddr) + self.assertEqual(seglen, len(content)) + + bf = BufferProxy( + { + "shape": (len(content),), + "typestr": "|u1", + "data": (memaddr, True), + "strides": (1,), + } + ) + segcount, buflen = get_segcount(bf) + self.assertEqual(segcount, 1) + self.assertEqual(buflen, len(content)) + seglen, segaddr = get_read_buffer(bf, 0) + self.assertEqual(segaddr, memaddr) + self.assertEqual(seglen, len(content)) + self.assertRaises(ValueError, get_write_buffer, bf, 0) + + bf = BufferProxy( + { + "shape": (len(content),), + "typestr": "|u1", + "data": (memaddr, True), + "strides": (1,), + "before": raise_exception, + } + ) + segcount, buflen = get_segcount(bf) + self.assertEqual(segcount, 0) + self.assertEqual(buflen, 0) + + bf = BufferProxy( + { + "shape": (3, 4), + "typestr": "|u4", + "data": (memaddr, True), + "strides": (12, 4), + } + ) + segcount, buflen = get_segcount(bf) + self.assertEqual(segcount, 3 * 4) + self.assertEqual(buflen, 3 * 4 * 4) + for i in range(0, 4): + seglen, segaddr = get_read_buffer(bf, i) + self.assertEqual(segaddr, memaddr + i * 4) + self.assertEqual(seglen, 4) + + +class BufferProxyLegacyTest(unittest.TestCase): + content = b"\x01\x00\x00\x02" * 12 + buffer = ctypes.create_string_buffer(content) + data = (ctypes.addressof(buffer), True) + + def test_length(self): + + # __doc__ (as of 2008-08-02) for pygame.bufferproxy.BufferProxy.length: + + # The size of the buffer data in bytes. + bf = BufferProxy( + {"shape": (3, 4), "typestr": "|u4", "data": self.data, "strides": (12, 4)} + ) + self.assertEqual(bf.length, len(self.content)) + bf = BufferProxy( + {"shape": (3, 3), "typestr": "|u4", "data": self.data, "strides": (12, 4)} + ) + self.assertEqual(bf.length, 3 * 3 * 4) + + def test_raw(self): + + # __doc__ (as of 2008-08-02) for pygame.bufferproxy.BufferProxy.raw: + + # The raw buffer data as string. The string may contain NUL bytes. + + bf = BufferProxy( + {"shape": (len(self.content),), "typestr": "|u1", "data": self.data} + ) + self.assertEqual(bf.raw, self.content) + bf = BufferProxy( + {"shape": (3, 4), "typestr": "|u4", "data": self.data, "strides": (4, 12)} + ) + self.assertEqual(bf.raw, self.content) + bf = BufferProxy( + {"shape": (3, 4), "typestr": "|u1", "data": self.data, "strides": (16, 4)} + ) + self.assertRaises(ValueError, getattr, bf, "raw") + + def test_write(self): + + # __doc__ (as of 2008-08-02) for pygame.bufferproxy.BufferProxy.write: + + # B.write (bufferproxy, buffer, offset) -> None + # + # Writes raw data to the bufferproxy. + # + # Writes the raw data from buffer to the BufferProxy object, starting + # at the specified offset within the BufferProxy. + # If the length of the passed buffer exceeds the length of the + # BufferProxy (reduced by the offset), an IndexError will be raised. + from ctypes import c_byte, sizeof, addressof, string_at, memset + + nullbyte = "\x00".encode("latin_1") + Buf = c_byte * 10 + data_buf = Buf(*range(1, 3 * sizeof(Buf) + 1, 3)) + data = string_at(data_buf, sizeof(data_buf)) + buf = Buf() + bp = BufferProxy( + {"typestr": "|u1", "shape": (sizeof(buf),), "data": (addressof(buf), False)} + ) + try: + self.assertEqual(bp.raw, nullbyte * sizeof(Buf)) + bp.write(data) + self.assertEqual(bp.raw, data) + memset(buf, 0, sizeof(buf)) + bp.write(data[:3], 2) + raw = bp.raw + self.assertEqual(raw[:2], nullbyte * 2) + self.assertEqual(raw[2:5], data[:3]) + self.assertEqual(raw[5:], nullbyte * (sizeof(Buf) - 5)) + bp.write(data[:3], bp.length - 3) + raw = bp.raw + self.assertEqual(raw[-3:], data[:3]) + self.assertRaises(IndexError, bp.write, data, 1) + self.assertRaises(IndexError, bp.write, data[:5], -1) + self.assertRaises(IndexError, bp.write, data[:5], bp.length) + self.assertRaises(TypeError, bp.write, 12) + bp = BufferProxy( + { + "typestr": "|u1", + "shape": (sizeof(buf),), + "data": (addressof(buf), True), + } + ) + self.assertRaises(pygame.BufferError, bp.write, "123".encode("latin_1")) + finally: + # Make sure bp is garbage collected before buf + bp = None + gc.collect() + + +if __name__ == "__main__": + unittest.main() diff --git a/venv/Lib/site-packages/pygame/tests/camera_test.py b/venv/Lib/site-packages/pygame/tests/camera_test.py new file mode 100644 index 0000000..79cf0f9 --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/camera_test.py @@ -0,0 +1,5 @@ +import unittest + + +class CameraModuleTest(unittest.TestCase): + pass diff --git a/venv/Lib/site-packages/pygame/tests/color_test.py b/venv/Lib/site-packages/pygame/tests/color_test.py new file mode 100644 index 0000000..16eefd1 --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/color_test.py @@ -0,0 +1,1302 @@ +import unittest +import math +import operator +import platform + +import pygame +from pygame.colordict import THECOLORS + + +IS_PYPY = "PyPy" == platform.python_implementation() +################################### CONSTANTS ################################## + +rgba_vals = [0, 1, 62, 63, 126, 127, 255] + +rgba_combinations = [ + (r, g, b, a) + for r in rgba_vals + for g in rgba_vals + for b in rgba_vals + for a in rgba_vals +] + +################################################################################ + + +def rgba_combos_Color_generator(): + for rgba in rgba_combinations: + yield pygame.Color(*rgba) + + +# Python gamma correct +def gamma_correct(rgba_0_255, gamma): + corrected = round(255.0 * math.pow(rgba_0_255 / 255.0, gamma)) + return max(min(int(corrected), 255), 0) + + +################################################################################ + +# TODO: add tests for +# correct_gamma() -- test against statically defined verified correct values +# coerce () -- ?? + + +def _assignr(x, y): + x.r = y + + +def _assigng(x, y): + x.g = y + + +def _assignb(x, y): + x.b = y + + +def _assigna(x, y): + x.a = y + + +def _assign_item(x, p, y): + x[p] = y + + +class ColorTypeTest(unittest.TestCase): + def test_new(self): + c = pygame.Color.__new__(pygame.Color) + self.assertEqual(c, pygame.Color(0, 0, 0, 255)) + self.assertEqual(len(c), 4) + + def test_init(self): + c = pygame.Color(10, 20, 30, 200) + self.assertEqual(c, (10, 20, 30, 200)) + c.set_length(3) + self.assertEqual(len(c), 3) + c.__init__(100, 110, 120, 128) + self.assertEqual(len(c), 4) + self.assertEqual(c, (100, 110, 120, 128)) + + def test_invalid_html_hex_codes(self): + # This was a problem with the way 2 digit hex numbers were + # calculated. The test_hex_digits test is related to the fix. + Color = pygame.color.Color + self.assertRaises(ValueError, lambda: Color("# f000000")) + self.assertRaises(ValueError, lambda: Color("#f 000000")) + self.assertRaises(ValueError, lambda: Color("#-f000000")) + + def test_hex_digits(self): + # This is an implementation specific test. + # Two digit hex numbers are calculated using table lookups + # for the upper and lower digits. + Color = pygame.color.Color + self.assertEqual(Color("#00000000").r, 0x00) + self.assertEqual(Color("#10000000").r, 0x10) + self.assertEqual(Color("#20000000").r, 0x20) + self.assertEqual(Color("#30000000").r, 0x30) + self.assertEqual(Color("#40000000").r, 0x40) + self.assertEqual(Color("#50000000").r, 0x50) + self.assertEqual(Color("#60000000").r, 0x60) + self.assertEqual(Color("#70000000").r, 0x70) + self.assertEqual(Color("#80000000").r, 0x80) + self.assertEqual(Color("#90000000").r, 0x90) + self.assertEqual(Color("#A0000000").r, 0xA0) + self.assertEqual(Color("#B0000000").r, 0xB0) + self.assertEqual(Color("#C0000000").r, 0xC0) + self.assertEqual(Color("#D0000000").r, 0xD0) + self.assertEqual(Color("#E0000000").r, 0xE0) + self.assertEqual(Color("#F0000000").r, 0xF0) + self.assertEqual(Color("#01000000").r, 0x01) + self.assertEqual(Color("#02000000").r, 0x02) + self.assertEqual(Color("#03000000").r, 0x03) + self.assertEqual(Color("#04000000").r, 0x04) + self.assertEqual(Color("#05000000").r, 0x05) + self.assertEqual(Color("#06000000").r, 0x06) + self.assertEqual(Color("#07000000").r, 0x07) + self.assertEqual(Color("#08000000").r, 0x08) + self.assertEqual(Color("#09000000").r, 0x09) + self.assertEqual(Color("#0A000000").r, 0x0A) + self.assertEqual(Color("#0B000000").r, 0x0B) + self.assertEqual(Color("#0C000000").r, 0x0C) + self.assertEqual(Color("#0D000000").r, 0x0D) + self.assertEqual(Color("#0E000000").r, 0x0E) + self.assertEqual(Color("#0F000000").r, 0x0F) + + def test_comparison(self): + Color = pygame.color.Color + + # Check valid comparisons + self.assertTrue(Color(255, 0, 0, 0) == Color(255, 0, 0, 0)) + self.assertTrue(Color(0, 255, 0, 0) == Color(0, 255, 0, 0)) + self.assertTrue(Color(0, 0, 255, 0) == Color(0, 0, 255, 0)) + self.assertTrue(Color(0, 0, 0, 255) == Color(0, 0, 0, 255)) + self.assertFalse(Color(0, 0, 0, 0) == Color(255, 0, 0, 0)) + self.assertFalse(Color(0, 0, 0, 0) == Color(0, 255, 0, 0)) + self.assertFalse(Color(0, 0, 0, 0) == Color(0, 0, 255, 0)) + self.assertFalse(Color(0, 0, 0, 0) == Color(0, 0, 0, 255)) + self.assertTrue(Color(0, 0, 0, 0) != Color(255, 0, 0, 0)) + self.assertTrue(Color(0, 0, 0, 0) != Color(0, 255, 0, 0)) + self.assertTrue(Color(0, 0, 0, 0) != Color(0, 0, 255, 0)) + self.assertTrue(Color(0, 0, 0, 0) != Color(0, 0, 0, 255)) + self.assertFalse(Color(255, 0, 0, 0) != Color(255, 0, 0, 0)) + self.assertFalse(Color(0, 255, 0, 0) != Color(0, 255, 0, 0)) + self.assertFalse(Color(0, 0, 255, 0) != Color(0, 0, 255, 0)) + self.assertFalse(Color(0, 0, 0, 255) != Color(0, 0, 0, 255)) + + self.assertTrue(Color(255, 0, 0, 0) == (255, 0, 0, 0)) + self.assertTrue(Color(0, 255, 0, 0) == (0, 255, 0, 0)) + self.assertTrue(Color(0, 0, 255, 0) == (0, 0, 255, 0)) + self.assertTrue(Color(0, 0, 0, 255) == (0, 0, 0, 255)) + self.assertFalse(Color(0, 0, 0, 0) == (255, 0, 0, 0)) + self.assertFalse(Color(0, 0, 0, 0) == (0, 255, 0, 0)) + self.assertFalse(Color(0, 0, 0, 0) == (0, 0, 255, 0)) + self.assertFalse(Color(0, 0, 0, 0) == (0, 0, 0, 255)) + self.assertTrue(Color(0, 0, 0, 0) != (255, 0, 0, 0)) + self.assertTrue(Color(0, 0, 0, 0) != (0, 255, 0, 0)) + self.assertTrue(Color(0, 0, 0, 0) != (0, 0, 255, 0)) + self.assertTrue(Color(0, 0, 0, 0) != (0, 0, 0, 255)) + self.assertFalse(Color(255, 0, 0, 0) != (255, 0, 0, 0)) + self.assertFalse(Color(0, 255, 0, 0) != (0, 255, 0, 0)) + self.assertFalse(Color(0, 0, 255, 0) != (0, 0, 255, 0)) + self.assertFalse(Color(0, 0, 0, 255) != (0, 0, 0, 255)) + + self.assertTrue((255, 0, 0, 0) == Color(255, 0, 0, 0)) + self.assertTrue((0, 255, 0, 0) == Color(0, 255, 0, 0)) + self.assertTrue((0, 0, 255, 0) == Color(0, 0, 255, 0)) + self.assertTrue((0, 0, 0, 255) == Color(0, 0, 0, 255)) + self.assertFalse((0, 0, 0, 0) == Color(255, 0, 0, 0)) + self.assertFalse((0, 0, 0, 0) == Color(0, 255, 0, 0)) + self.assertFalse((0, 0, 0, 0) == Color(0, 0, 255, 0)) + self.assertFalse((0, 0, 0, 0) == Color(0, 0, 0, 255)) + self.assertTrue((0, 0, 0, 0) != Color(255, 0, 0, 0)) + self.assertTrue((0, 0, 0, 0) != Color(0, 255, 0, 0)) + self.assertTrue((0, 0, 0, 0) != Color(0, 0, 255, 0)) + self.assertTrue((0, 0, 0, 0) != Color(0, 0, 0, 255)) + self.assertFalse((255, 0, 0, 0) != Color(255, 0, 0, 0)) + self.assertFalse((0, 255, 0, 0) != Color(0, 255, 0, 0)) + self.assertFalse((0, 0, 255, 0) != Color(0, 0, 255, 0)) + self.assertFalse((0, 0, 0, 255) != Color(0, 0, 0, 255)) + + class TupleSubclass(tuple): + pass + + self.assertTrue(Color(255, 0, 0, 0) == TupleSubclass((255, 0, 0, 0))) + self.assertTrue(TupleSubclass((255, 0, 0, 0)) == Color(255, 0, 0, 0)) + self.assertFalse(Color(255, 0, 0, 0) != TupleSubclass((255, 0, 0, 0))) + self.assertFalse(TupleSubclass((255, 0, 0, 0)) != Color(255, 0, 0, 0)) + + # These are not supported so will be unequal. + self.assertFalse(Color(255, 0, 0, 0) == "#ff000000") + self.assertTrue(Color(255, 0, 0, 0) != "#ff000000") + + self.assertFalse("#ff000000" == Color(255, 0, 0, 0)) + self.assertTrue("#ff000000" != Color(255, 0, 0, 0)) + + self.assertFalse(Color(255, 0, 0, 0) == 0xFF000000) + self.assertTrue(Color(255, 0, 0, 0) != 0xFF000000) + + self.assertFalse(0xFF000000 == Color(255, 0, 0, 0)) + self.assertTrue(0xFF000000 != Color(255, 0, 0, 0)) + + self.assertFalse(Color(255, 0, 0, 0) == [255, 0, 0, 0]) + self.assertTrue(Color(255, 0, 0, 0) != [255, 0, 0, 0]) + + self.assertFalse([255, 0, 0, 0] == Color(255, 0, 0, 0)) + self.assertTrue([255, 0, 0, 0] != Color(255, 0, 0, 0)) + + # Comparison is not implemented for invalid color values. + class Test(object): + def __eq__(self, other): + return -1 + + def __ne__(self, other): + return -2 + + class TestTuple(tuple): + def __eq__(self, other): + return -1 + + def __ne__(self, other): + return -2 + + t = Test() + t_tuple = TestTuple(("a", 0, 0, 0)) + black = Color("black") + self.assertEqual(black == t, -1) + self.assertEqual(t == black, -1) + self.assertEqual(black != t, -2) + self.assertEqual(t != black, -2) + self.assertEqual(black == t_tuple, -1) + self.assertEqual(black != t_tuple, -2) + self.assertEqual(t_tuple == black, -1) + self.assertEqual(t_tuple != black, -2) + + def test_ignore_whitespace(self): + self.assertEqual(pygame.color.Color("red"), pygame.color.Color(" r e d ")) + + def test_slice(self): + # """|tags: python3_ignore|""" + + # slicing a color gives you back a tuple. + # do all sorts of slice combinations. + c = pygame.Color(1, 2, 3, 4) + + self.assertEqual((1, 2, 3, 4), c[:]) + self.assertEqual((1, 2, 3), c[:-1]) + + self.assertEqual((), c[:-5]) + + self.assertEqual((1, 2, 3, 4), c[:4]) + self.assertEqual((1, 2, 3, 4), c[:5]) + self.assertEqual((1, 2), c[:2]) + self.assertEqual((1,), c[:1]) + self.assertEqual((), c[:0]) + + self.assertEqual((2,), c[1:-2]) + self.assertEqual((3, 4), c[-2:]) + self.assertEqual((4,), c[-1:]) + + # NOTE: assigning to a slice is currently unsupported. + + def test_unpack(self): + # should be able to unpack to r,g,b,a and r,g,b + c = pygame.Color(1, 2, 3, 4) + r, g, b, a = c + self.assertEqual((1, 2, 3, 4), (r, g, b, a)) + self.assertEqual(c, (r, g, b, a)) + + c.set_length(3) + r, g, b = c + self.assertEqual((1, 2, 3), (r, g, b)) + + def test_length(self): + # should be able to unpack to r,g,b,a and r,g,b + c = pygame.Color(1, 2, 3, 4) + self.assertEqual(len(c), 4) + + c.set_length(3) + self.assertEqual(len(c), 3) + + # it keeps the old alpha anyway... + self.assertEqual(c.a, 4) + + # however you can't get the alpha in this way: + self.assertRaises(IndexError, lambda x: c[x], 4) + + c.set_length(4) + self.assertEqual(len(c), 4) + self.assertEqual(len(c), 4) + + self.assertRaises(ValueError, c.set_length, 5) + self.assertRaises(ValueError, c.set_length, -1) + self.assertRaises(ValueError, c.set_length, 0) + self.assertRaises(ValueError, c.set_length, pow(2, 33)) + + def test_case_insensitivity_of_string_args(self): + self.assertEqual(pygame.color.Color("red"), pygame.color.Color("Red")) + + def test_color(self): + """Ensures Color objects can be created.""" + color = pygame.Color(0, 0, 0, 0) + + self.assertIsInstance(color, pygame.Color) + + def test_color__rgba_int_args(self): + """Ensures Color objects can be created using ints.""" + color = pygame.Color(10, 20, 30, 40) + + self.assertEqual(color.r, 10) + self.assertEqual(color.g, 20) + self.assertEqual(color.b, 30) + self.assertEqual(color.a, 40) + + def test_color__rgba_int_args_without_alpha(self): + """Ensures Color objects can be created without providing alpha.""" + color = pygame.Color(10, 20, 30) + + self.assertEqual(color.r, 10) + self.assertEqual(color.g, 20) + self.assertEqual(color.b, 30) + self.assertEqual(color.a, 255) + + def test_color__rgba_int_args_invalid_value(self): + """Ensures invalid values are detected when creating Color objects.""" + self.assertRaises(ValueError, pygame.Color, 257, 10, 105, 44) + self.assertRaises(ValueError, pygame.Color, 10, 257, 105, 44) + self.assertRaises(ValueError, pygame.Color, 10, 105, 257, 44) + self.assertRaises(ValueError, pygame.Color, 10, 105, 44, 257) + + def test_color__rgba_int_args_invalid_value_without_alpha(self): + """Ensures invalid values are detected when creating Color objects + without providing an alpha. + """ + self.assertRaises(ValueError, pygame.Color, 256, 10, 105) + self.assertRaises(ValueError, pygame.Color, 10, 256, 105) + self.assertRaises(ValueError, pygame.Color, 10, 105, 256) + + def test_color__color_object_arg(self): + """Ensures Color objects can be created using Color objects.""" + color_args = (10, 20, 30, 40) + color_obj = pygame.Color(*color_args) + + new_color_obj = pygame.Color(color_obj) + + self.assertIsInstance(new_color_obj, pygame.Color) + self.assertEqual(new_color_obj, color_obj) + self.assertEqual(new_color_obj.r, color_args[0]) + self.assertEqual(new_color_obj.g, color_args[1]) + self.assertEqual(new_color_obj.b, color_args[2]) + self.assertEqual(new_color_obj.a, color_args[3]) + + def test_color__name_str_arg(self): + """Ensures Color objects can be created using str names.""" + for name in ("aquamarine3", "AQUAMARINE3", "AqUAmArIne3"): + color = pygame.Color(name) + + self.assertEqual(color.r, 102) + self.assertEqual(color.g, 205) + self.assertEqual(color.b, 170) + self.assertEqual(color.a, 255) + + def test_color__name_str_arg_from_colordict(self): + """Ensures Color objects can be created using str names + from the THECOLORS dict.""" + for name, values in THECOLORS.items(): + color = pygame.Color(name) + + self.assertEqual(color.r, values[0]) + self.assertEqual(color.g, values[1]) + self.assertEqual(color.b, values[2]) + self.assertEqual(color.a, values[3]) + + def test_color__html_str_arg(self): + """Ensures Color objects can be created using html strings.""" + # See test_webstyle() for related tests. + color = pygame.Color("#a1B2c3D4") + + self.assertEqual(color.r, 0xA1) + self.assertEqual(color.g, 0xB2) + self.assertEqual(color.b, 0xC3) + self.assertEqual(color.a, 0xD4) + + def test_color__hex_str_arg(self): + """Ensures Color objects can be created using hex strings.""" + # See test_webstyle() for related tests. + color = pygame.Color("0x1a2B3c4D") + + self.assertEqual(color.r, 0x1A) + self.assertEqual(color.g, 0x2B) + self.assertEqual(color.b, 0x3C) + self.assertEqual(color.a, 0x4D) + + def test_color__int_arg(self): + """Ensures Color objects can be created using one int value.""" + for value in (0x0, 0xFFFFFFFF, 0xAABBCCDD): + color = pygame.Color(value) + + self.assertEqual(color.r, (value >> 24) & 0xFF) + self.assertEqual(color.g, (value >> 16) & 0xFF) + self.assertEqual(color.b, (value >> 8) & 0xFF) + self.assertEqual(color.a, value & 0xFF) + + def test_color__int_arg_invalid(self): + """Ensures invalid int values are detected when creating Color objects.""" + with self.assertRaises(ValueError): + color = pygame.Color(0x1FFFFFFFF) + + def test_color__sequence_arg(self): + """Ensures Color objects can be created using tuples/lists.""" + color_values = (33, 44, 55, 66) + for seq_type in (tuple, list): + color = pygame.Color(seq_type(color_values)) + + self.assertEqual(color.r, color_values[0]) + self.assertEqual(color.g, color_values[1]) + self.assertEqual(color.b, color_values[2]) + self.assertEqual(color.a, color_values[3]) + + def test_color__sequence_arg_without_alpha(self): + """Ensures Color objects can be created using tuples/lists + without providing an alpha value. + """ + color_values = (33, 44, 55) + for seq_type in (tuple, list): + color = pygame.Color(seq_type(color_values)) + + self.assertEqual(color.r, color_values[0]) + self.assertEqual(color.g, color_values[1]) + self.assertEqual(color.b, color_values[2]) + self.assertEqual(color.a, 255) + + def test_color__sequence_arg_invalid_value(self): + """Ensures invalid sequences are detected when creating Color objects.""" + cls = pygame.Color + for seq_type in (tuple, list): + self.assertRaises(ValueError, cls, seq_type((256, 90, 80, 70))) + self.assertRaises(ValueError, cls, seq_type((100, 256, 80, 70))) + self.assertRaises(ValueError, cls, seq_type((100, 90, 256, 70))) + self.assertRaises(ValueError, cls, seq_type((100, 90, 80, 256))) + + def test_color__sequence_arg_invalid_value_without_alpha(self): + """Ensures invalid sequences are detected when creating Color objects + without providing an alpha. + """ + cls = pygame.Color + for seq_type in (tuple, list): + self.assertRaises(ValueError, cls, seq_type((256, 90, 80))) + self.assertRaises(ValueError, cls, seq_type((100, 256, 80))) + self.assertRaises(ValueError, cls, seq_type((100, 90, 256))) + + def test_color__sequence_arg_invalid_format(self): + """Ensures invalid sequences are detected when creating Color objects + with the wrong number of values. + """ + cls = pygame.Color + for seq_type in (tuple, list): + self.assertRaises(ValueError, cls, seq_type((100,))) + self.assertRaises(ValueError, cls, seq_type((100, 90))) + self.assertRaises(ValueError, cls, seq_type((100, 90, 80, 70, 60))) + + def test_rgba(self): + c = pygame.Color(0) + self.assertEqual(c.r, 0) + self.assertEqual(c.g, 0) + self.assertEqual(c.b, 0) + self.assertEqual(c.a, 0) + + # Test simple assignments + c.r = 123 + self.assertEqual(c.r, 123) + self.assertRaises(ValueError, _assignr, c, 537) + self.assertEqual(c.r, 123) + self.assertRaises(ValueError, _assignr, c, -3) + self.assertEqual(c.r, 123) + + c.g = 55 + self.assertEqual(c.g, 55) + self.assertRaises(ValueError, _assigng, c, 348) + self.assertEqual(c.g, 55) + self.assertRaises(ValueError, _assigng, c, -44) + self.assertEqual(c.g, 55) + + c.b = 77 + self.assertEqual(c.b, 77) + self.assertRaises(ValueError, _assignb, c, 256) + self.assertEqual(c.b, 77) + self.assertRaises(ValueError, _assignb, c, -12) + self.assertEqual(c.b, 77) + + c.a = 255 + self.assertEqual(c.a, 255) + self.assertRaises(ValueError, _assigna, c, 312) + self.assertEqual(c.a, 255) + self.assertRaises(ValueError, _assigna, c, -10) + self.assertEqual(c.a, 255) + + def test_repr(self): + c = pygame.Color(68, 38, 26, 69) + t = "(68, 38, 26, 69)" + self.assertEqual(repr(c), t) + + def test_add(self): + c1 = pygame.Color(0) + self.assertEqual(c1.r, 0) + self.assertEqual(c1.g, 0) + self.assertEqual(c1.b, 0) + self.assertEqual(c1.a, 0) + + c2 = pygame.Color(20, 33, 82, 193) + self.assertEqual(c2.r, 20) + self.assertEqual(c2.g, 33) + self.assertEqual(c2.b, 82) + self.assertEqual(c2.a, 193) + + c3 = c1 + c2 + self.assertEqual(c3.r, 20) + self.assertEqual(c3.g, 33) + self.assertEqual(c3.b, 82) + self.assertEqual(c3.a, 193) + + c3 = c3 + c2 + self.assertEqual(c3.r, 40) + self.assertEqual(c3.g, 66) + self.assertEqual(c3.b, 164) + self.assertEqual(c3.a, 255) + + # Issue #286: Is type checking done for Python 3.x? + self.assertRaises(TypeError, operator.add, c1, None) + self.assertRaises(TypeError, operator.add, None, c1) + + def test_sub(self): + c1 = pygame.Color(0xFFFFFFFF) + self.assertEqual(c1.r, 255) + self.assertEqual(c1.g, 255) + self.assertEqual(c1.b, 255) + self.assertEqual(c1.a, 255) + + c2 = pygame.Color(20, 33, 82, 193) + self.assertEqual(c2.r, 20) + self.assertEqual(c2.g, 33) + self.assertEqual(c2.b, 82) + self.assertEqual(c2.a, 193) + + c3 = c1 - c2 + self.assertEqual(c3.r, 235) + self.assertEqual(c3.g, 222) + self.assertEqual(c3.b, 173) + self.assertEqual(c3.a, 62) + + c3 = c3 - c2 + self.assertEqual(c3.r, 215) + self.assertEqual(c3.g, 189) + self.assertEqual(c3.b, 91) + self.assertEqual(c3.a, 0) + + # Issue #286: Is type checking done for Python 3.x? + self.assertRaises(TypeError, operator.sub, c1, None) + self.assertRaises(TypeError, operator.sub, None, c1) + + def test_mul(self): + c1 = pygame.Color(0x01010101) + self.assertEqual(c1.r, 1) + self.assertEqual(c1.g, 1) + self.assertEqual(c1.b, 1) + self.assertEqual(c1.a, 1) + + c2 = pygame.Color(2, 5, 3, 22) + self.assertEqual(c2.r, 2) + self.assertEqual(c2.g, 5) + self.assertEqual(c2.b, 3) + self.assertEqual(c2.a, 22) + + c3 = c1 * c2 + self.assertEqual(c3.r, 2) + self.assertEqual(c3.g, 5) + self.assertEqual(c3.b, 3) + self.assertEqual(c3.a, 22) + + c3 = c3 * c2 + self.assertEqual(c3.r, 4) + self.assertEqual(c3.g, 25) + self.assertEqual(c3.b, 9) + self.assertEqual(c3.a, 255) + + # Issue #286: Is type checking done for Python 3.x? + self.assertRaises(TypeError, operator.mul, c1, None) + self.assertRaises(TypeError, operator.mul, None, c1) + + def test_div(self): + c1 = pygame.Color(0x80808080) + self.assertEqual(c1.r, 128) + self.assertEqual(c1.g, 128) + self.assertEqual(c1.b, 128) + self.assertEqual(c1.a, 128) + + c2 = pygame.Color(2, 4, 8, 16) + self.assertEqual(c2.r, 2) + self.assertEqual(c2.g, 4) + self.assertEqual(c2.b, 8) + self.assertEqual(c2.a, 16) + + c3 = c1 // c2 + self.assertEqual(c3.r, 64) + self.assertEqual(c3.g, 32) + self.assertEqual(c3.b, 16) + self.assertEqual(c3.a, 8) + + c3 = c3 // c2 + self.assertEqual(c3.r, 32) + self.assertEqual(c3.g, 8) + self.assertEqual(c3.b, 2) + self.assertEqual(c3.a, 0) + + # Issue #286: Is type checking done for Python 3.x? + self.assertRaises(TypeError, operator.floordiv, c1, None) + self.assertRaises(TypeError, operator.floordiv, None, c1) + + # Division by zero check + dividend = pygame.Color(255, 255, 255, 255) + for i in range(4): + divisor = pygame.Color(64, 64, 64, 64) + divisor[i] = 0 + quotient = pygame.Color(3, 3, 3, 3) + quotient[i] = 0 + self.assertEqual(dividend // divisor, quotient) + + def test_mod(self): + c1 = pygame.Color(0xFFFFFFFF) + self.assertEqual(c1.r, 255) + self.assertEqual(c1.g, 255) + self.assertEqual(c1.b, 255) + self.assertEqual(c1.a, 255) + + c2 = pygame.Color(2, 4, 8, 16) + self.assertEqual(c2.r, 2) + self.assertEqual(c2.g, 4) + self.assertEqual(c2.b, 8) + self.assertEqual(c2.a, 16) + + c3 = c1 % c2 + self.assertEqual(c3.r, 1) + self.assertEqual(c3.g, 3) + self.assertEqual(c3.b, 7) + self.assertEqual(c3.a, 15) + + # Issue #286: Is type checking done for Python 3.x? + self.assertRaises(TypeError, operator.mod, c1, None) + self.assertRaises(TypeError, operator.mod, None, c1) + + # Division by zero check + dividend = pygame.Color(255, 255, 255, 255) + for i in range(4): + divisor = pygame.Color(64, 64, 64, 64) + divisor[i] = 0 + quotient = pygame.Color(63, 63, 63, 63) + quotient[i] = 0 + self.assertEqual(dividend % divisor, quotient) + + def test_float(self): + c = pygame.Color(0xCC00CC00) + self.assertEqual(c.r, 204) + self.assertEqual(c.g, 0) + self.assertEqual(c.b, 204) + self.assertEqual(c.a, 0) + self.assertEqual(float(c), float(0xCC00CC00)) + + c = pygame.Color(0x33727592) + self.assertEqual(c.r, 51) + self.assertEqual(c.g, 114) + self.assertEqual(c.b, 117) + self.assertEqual(c.a, 146) + self.assertEqual(float(c), float(0x33727592)) + + def test_oct(self): + c = pygame.Color(0xCC00CC00) + self.assertEqual(c.r, 204) + self.assertEqual(c.g, 0) + self.assertEqual(c.b, 204) + self.assertEqual(c.a, 0) + self.assertEqual(oct(c), oct(0xCC00CC00)) + + c = pygame.Color(0x33727592) + self.assertEqual(c.r, 51) + self.assertEqual(c.g, 114) + self.assertEqual(c.b, 117) + self.assertEqual(c.a, 146) + self.assertEqual(oct(c), oct(0x33727592)) + + def test_hex(self): + c = pygame.Color(0xCC00CC00) + self.assertEqual(c.r, 204) + self.assertEqual(c.g, 0) + self.assertEqual(c.b, 204) + self.assertEqual(c.a, 0) + self.assertEqual(hex(c), hex(0xCC00CC00)) + + c = pygame.Color(0x33727592) + self.assertEqual(c.r, 51) + self.assertEqual(c.g, 114) + self.assertEqual(c.b, 117) + self.assertEqual(c.a, 146) + self.assertEqual(hex(c), hex(0x33727592)) + + def test_webstyle(self): + c = pygame.Color("#CC00CC11") + self.assertEqual(c.r, 204) + self.assertEqual(c.g, 0) + self.assertEqual(c.b, 204) + self.assertEqual(c.a, 17) + self.assertEqual(hex(c), hex(0xCC00CC11)) + + c = pygame.Color("#CC00CC") + self.assertEqual(c.r, 204) + self.assertEqual(c.g, 0) + self.assertEqual(c.b, 204) + self.assertEqual(c.a, 255) + self.assertEqual(hex(c), hex(0xCC00CCFF)) + + c = pygame.Color("0xCC00CC11") + self.assertEqual(c.r, 204) + self.assertEqual(c.g, 0) + self.assertEqual(c.b, 204) + self.assertEqual(c.a, 17) + self.assertEqual(hex(c), hex(0xCC00CC11)) + + c = pygame.Color("0xCC00CC") + self.assertEqual(c.r, 204) + self.assertEqual(c.g, 0) + self.assertEqual(c.b, 204) + self.assertEqual(c.a, 255) + self.assertEqual(hex(c), hex(0xCC00CCFF)) + + self.assertRaises(ValueError, pygame.Color, "#cc00qq") + self.assertRaises(ValueError, pygame.Color, "0xcc00qq") + self.assertRaises(ValueError, pygame.Color, "09abcdef") + self.assertRaises(ValueError, pygame.Color, "09abcde") + self.assertRaises(ValueError, pygame.Color, "quarky") + + def test_int(self): + # This will be a long + c = pygame.Color(0xCC00CC00) + self.assertEqual(c.r, 204) + self.assertEqual(c.g, 0) + self.assertEqual(c.b, 204) + self.assertEqual(c.a, 0) + self.assertEqual(int(c), int(0xCC00CC00)) + + # This will be an int + c = pygame.Color(0x33727592) + self.assertEqual(c.r, 51) + self.assertEqual(c.g, 114) + self.assertEqual(c.b, 117) + self.assertEqual(c.a, 146) + self.assertEqual(int(c), int(0x33727592)) + + def test_long(self): + # This will be a long + c = pygame.Color(0xCC00CC00) + self.assertEqual(c.r, 204) + self.assertEqual(c.g, 0) + self.assertEqual(c.b, 204) + self.assertEqual(c.a, 0) + self.assertEqual(int(c), int(0xCC00CC00)) + + # This will be an int + c = pygame.Color(0x33727592) + self.assertEqual(c.r, 51) + self.assertEqual(c.g, 114) + self.assertEqual(c.b, 117) + self.assertEqual(c.a, 146) + self.assertEqual(int(c), int(0x33727592)) + + def test_normalize(self): + c = pygame.Color(204, 38, 194, 55) + self.assertEqual(c.r, 204) + self.assertEqual(c.g, 38) + self.assertEqual(c.b, 194) + self.assertEqual(c.a, 55) + + t = c.normalize() + + self.assertAlmostEqual(t[0], 0.800000, 5) + self.assertAlmostEqual(t[1], 0.149016, 5) + self.assertAlmostEqual(t[2], 0.760784, 5) + self.assertAlmostEqual(t[3], 0.215686, 5) + + def test_len(self): + c = pygame.Color(204, 38, 194, 55) + self.assertEqual(len(c), 4) + + def test_get_item(self): + c = pygame.Color(204, 38, 194, 55) + self.assertEqual(c[0], 204) + self.assertEqual(c[1], 38) + self.assertEqual(c[2], 194) + self.assertEqual(c[3], 55) + + def test_set_item(self): + c = pygame.Color(204, 38, 194, 55) + self.assertEqual(c[0], 204) + self.assertEqual(c[1], 38) + self.assertEqual(c[2], 194) + self.assertEqual(c[3], 55) + + c[0] = 33 + self.assertEqual(c[0], 33) + c[1] = 48 + self.assertEqual(c[1], 48) + c[2] = 173 + self.assertEqual(c[2], 173) + c[3] = 213 + self.assertEqual(c[3], 213) + + # Now try some 'invalid' ones + self.assertRaises(TypeError, _assign_item, c, 0, 95.485) + self.assertEqual(c[0], 33) + self.assertRaises(ValueError, _assign_item, c, 1, -83) + self.assertEqual(c[1], 48) + self.assertRaises(TypeError, _assign_item, c, 2, "Hello") + self.assertEqual(c[2], 173) + + def test_Color_type_works_for_Surface_get_and_set_colorkey(self): + s = pygame.Surface((32, 32)) + + c = pygame.Color(33, 22, 11, 255) + s.set_colorkey(c) + + get_r, get_g, get_b, get_a = s.get_colorkey() + + self.assertTrue(get_r == c.r) + self.assertTrue(get_g == c.g) + self.assertTrue(get_b == c.b) + self.assertTrue(get_a == c.a) + + ########## HSLA, HSVA, CMY, I1I2I3 ALL ELEMENTS WITHIN SPECIFIED RANGE ######### + + def test_hsla__all_elements_within_limits(self): + for c in rgba_combos_Color_generator(): + h, s, l, a = c.hsla + self.assertTrue(0 <= h <= 360) + self.assertTrue(0 <= s <= 100) + self.assertTrue(0 <= l <= 100) + self.assertTrue(0 <= a <= 100) + + def test_hsva__all_elements_within_limits(self): + for c in rgba_combos_Color_generator(): + h, s, v, a = c.hsva + self.assertTrue(0 <= h <= 360) + self.assertTrue(0 <= s <= 100) + self.assertTrue(0 <= v <= 100) + self.assertTrue(0 <= a <= 100) + + def test_cmy__all_elements_within_limits(self): + for c in rgba_combos_Color_generator(): + c, m, y = c.cmy + self.assertTrue(0 <= c <= 1) + self.assertTrue(0 <= m <= 1) + self.assertTrue(0 <= y <= 1) + + def test_i1i2i3__all_elements_within_limits(self): + for c in rgba_combos_Color_generator(): + i1, i2, i3 = c.i1i2i3 + self.assertTrue(0 <= i1 <= 1) + self.assertTrue(-0.5 <= i2 <= 0.5) + self.assertTrue(-0.5 <= i3 <= 0.5) + + def test_issue_269(self): + """PyColor OverflowError on HSVA with hue value of 360 + + >>> c = pygame.Color(0) + >>> c.hsva = (360,0,0,0) + Traceback (most recent call last): + File "", line 1, in + OverflowError: this is not allowed to happen ever + >>> pygame.ver + '1.9.1release' + >>> + + """ + + c = pygame.Color(0) + c.hsva = 360, 0, 0, 0 + self.assertEqual(c.hsva, (0, 0, 0, 0)) + c.hsva = 360, 100, 100, 100 + self.assertEqual(c.hsva, (0, 100, 100, 100)) + self.assertEqual(c, (255, 0, 0, 255)) + + ####################### COLORSPACE PROPERTY SANITY TESTS ####################### + + def colorspaces_converted_should_not_raise(self, prop): + fails = 0 + + x = 0 + for c in rgba_combos_Color_generator(): + x += 1 + + other = pygame.Color(0) + + try: + setattr(other, prop, getattr(c, prop)) + # eg other.hsla = c.hsla + + except ValueError: + fails += 1 + + self.assertTrue(x > 0, "x is combination counter, 0 means no tests!") + self.assertTrue((fails, x) == (0, x)) + + def test_hsla__sanity_testing_converted_should_not_raise(self): + self.colorspaces_converted_should_not_raise("hsla") + + def test_hsva__sanity_testing_converted_should_not_raise(self): + self.colorspaces_converted_should_not_raise("hsva") + + def test_cmy__sanity_testing_converted_should_not_raise(self): + self.colorspaces_converted_should_not_raise("cmy") + + def test_i1i2i3__sanity_testing_converted_should_not_raise(self): + self.colorspaces_converted_should_not_raise("i1i2i3") + + ################################################################################ + + def colorspaces_converted_should_equate_bar_rounding(self, prop): + for c in rgba_combos_Color_generator(): + other = pygame.Color(0) + + try: + setattr(other, prop, getattr(c, prop)) + # eg other.hsla = c.hsla + + self.assertTrue(abs(other.r - c.r) <= 1) + self.assertTrue(abs(other.b - c.b) <= 1) + self.assertTrue(abs(other.g - c.g) <= 1) + # CMY and I1I2I3 do not care about the alpha + if not prop in ("cmy", "i1i2i3"): + self.assertTrue(abs(other.a - c.a) <= 1) + + except ValueError: + pass # other tests will notify, this tests equation + + def test_hsla__sanity_testing_converted_should_equate_bar_rounding(self): + self.colorspaces_converted_should_equate_bar_rounding("hsla") + + def test_hsva__sanity_testing_converted_should_equate_bar_rounding(self): + self.colorspaces_converted_should_equate_bar_rounding("hsva") + + def test_cmy__sanity_testing_converted_should_equate_bar_rounding(self): + self.colorspaces_converted_should_equate_bar_rounding("cmy") + + def test_i1i2i3__sanity_testing_converted_should_equate_bar_rounding(self): + self.colorspaces_converted_should_equate_bar_rounding("i1i2i3") + + ################################################################################ + + def test_correct_gamma__verified_against_python_implementation(self): + "|tags:slow|" + # gamma_correct defined at top of page + + gammas = [i / 10.0 for i in range(1, 31)] # [0.1 ... 3.0] + gammas_len = len(gammas) + + for i, c in enumerate(rgba_combos_Color_generator()): + gamma = gammas[i % gammas_len] + + corrected = pygame.Color(*[gamma_correct(x, gamma) for x in tuple(c)]) + lib_corrected = c.correct_gamma(gamma) + + self.assertTrue(corrected.r == lib_corrected.r) + self.assertTrue(corrected.g == lib_corrected.g) + self.assertTrue(corrected.b == lib_corrected.b) + self.assertTrue(corrected.a == lib_corrected.a) + + # TODO: test against statically defined verified _correct_ values + # assert corrected.r == 125 etc. + + def test_pickle(self): + import pickle + + c1 = pygame.Color(1, 2, 3, 4) + # c2 = pygame.Color(255,254,253,252) + pickle_string = pickle.dumps(c1) + c1_frompickle = pickle.loads(pickle_string) + self.assertEqual(c1, c1_frompickle) + + ################################################################################ + # only available if ctypes module is also available + + @unittest.skipIf(IS_PYPY, "PyPy has no ctypes") + def test_arraystruct(self): + + import pygame.tests.test_utils.arrinter as ai + import ctypes as ct + + c_byte_p = ct.POINTER(ct.c_byte) + c = pygame.Color(5, 7, 13, 23) + flags = ai.PAI_CONTIGUOUS | ai.PAI_FORTRAN | ai.PAI_ALIGNED | ai.PAI_NOTSWAPPED + for i in range(1, 5): + c.set_length(i) + inter = ai.ArrayInterface(c) + self.assertEqual(inter.two, 2) + self.assertEqual(inter.nd, 1) + self.assertEqual(inter.typekind, "u") + self.assertEqual(inter.itemsize, 1) + self.assertEqual(inter.flags, flags) + self.assertEqual(inter.shape[0], i) + self.assertEqual(inter.strides[0], 1) + data = ct.cast(inter.data, c_byte_p) + for j in range(i): + self.assertEqual(data[j], c[j]) + + @unittest.skipIf(not pygame.HAVE_NEWBUF, "newbuf not implemented") + def test_newbuf(self): + from pygame.tests.test_utils import buftools + from ctypes import cast, POINTER, c_uint8 + + class ColorImporter(buftools.Importer): + def __init__(self, color, flags): + super(ColorImporter, self).__init__(color, flags) + self.items = cast(self.buf, POINTER(c_uint8)) + + def __getitem__(self, index): + if 0 <= index < 4: + return self.items[index] + raise IndexError( + "valid index values are between 0 and 3: " "got {}".format(index) + ) + + def __setitem__(self, index, value): + if 0 <= index < 4: + self.items[index] = value + else: + raise IndexError( + "valid index values are between 0 and 3: " + "got {}".format(index) + ) + + c = pygame.Color(50, 100, 150, 200) + imp = ColorImporter(c, buftools.PyBUF_SIMPLE) + self.assertTrue(imp.obj is c) + self.assertEqual(imp.ndim, 0) + self.assertEqual(imp.itemsize, 1) + self.assertEqual(imp.len, 4) + self.assertTrue(imp.readonly) + self.assertTrue(imp.format is None) + self.assertTrue(imp.shape is None) + self.assertTrue(imp.strides is None) + self.assertTrue(imp.suboffsets is None) + for i in range(4): + self.assertEqual(c[i], imp[i]) + imp[0] = 60 + self.assertEqual(c.r, 60) + imp[1] = 110 + self.assertEqual(c.g, 110) + imp[2] = 160 + self.assertEqual(c.b, 160) + imp[3] = 210 + self.assertEqual(c.a, 210) + imp = ColorImporter(c, buftools.PyBUF_FORMAT) + self.assertEqual(imp.ndim, 0) + self.assertEqual(imp.itemsize, 1) + self.assertEqual(imp.len, 4) + self.assertEqual(imp.format, "B") + self.assertEqual(imp.ndim, 0) + self.assertEqual(imp.itemsize, 1) + self.assertEqual(imp.len, 4) + imp = ColorImporter(c, buftools.PyBUF_ND) + self.assertEqual(imp.ndim, 1) + self.assertEqual(imp.itemsize, 1) + self.assertEqual(imp.len, 4) + self.assertTrue(imp.format is None) + self.assertEqual(imp.shape, (4,)) + self.assertEqual(imp.strides, None) + imp = ColorImporter(c, buftools.PyBUF_STRIDES) + self.assertEqual(imp.ndim, 1) + self.assertTrue(imp.format is None) + self.assertEqual(imp.shape, (4,)) + self.assertEqual(imp.strides, (1,)) + imp = ColorImporter(c, buftools.PyBUF_C_CONTIGUOUS) + self.assertEqual(imp.ndim, 1) + imp = ColorImporter(c, buftools.PyBUF_F_CONTIGUOUS) + self.assertEqual(imp.ndim, 1) + imp = ColorImporter(c, buftools.PyBUF_ANY_CONTIGUOUS) + self.assertEqual(imp.ndim, 1) + for i in range(1, 5): + c.set_length(i) + imp = ColorImporter(c, buftools.PyBUF_ND) + self.assertEqual(imp.ndim, 1) + self.assertEqual(imp.len, i) + self.assertEqual(imp.shape, (i,)) + self.assertRaises(BufferError, ColorImporter, c, buftools.PyBUF_WRITABLE) + + def test_lerp(self): + # setup + Color = pygame.color.Color + + color0 = Color(0, 0, 0, 0) + color128 = Color(128, 128, 128, 128) + color255 = Color(255, 255, 255, 255) + color100 = Color(100, 100, 100, 100) + + # type checking + self.assertTrue(isinstance(color0.lerp(color128, 0.5), Color)) + + # common value testing + self.assertEqual(color0.lerp(color128, 0.5), Color(64, 64, 64, 64)) + self.assertEqual(color0.lerp(color128, 0.5), Color(64, 64, 64, 64)) + self.assertEqual(color128.lerp(color255, 0.5), Color(192, 192, 192, 192)) + self.assertEqual(color0.lerp(color255, 0.5), Color(128, 128, 128, 128)) + + # testing extremes + self.assertEqual(color0.lerp(color100, 0), color0) + self.assertEqual(color0.lerp(color100, 0.01), Color(1, 1, 1, 1)) + self.assertEqual(color0.lerp(color100, 0.99), Color(99, 99, 99, 99)) + self.assertEqual(color0.lerp(color100, 1), color100) + + # kwarg testing + self.assertEqual(color0.lerp(color=color100, amount=0.5), Color(50, 50, 50, 50)) + self.assertEqual(color0.lerp(amount=0.5, color=color100), Color(50, 50, 50, 50)) + + # invalid input testing + self.assertRaises(ValueError, lambda: color0.lerp(color128, 2.5)) + self.assertRaises(ValueError, lambda: color0.lerp(color128, -0.5)) + self.assertRaises(ValueError, lambda: color0.lerp((256, 0, 0, 0), 0.5)) + self.assertRaises(ValueError, lambda: color0.lerp((0, 256, 0, 0), 0.5)) + self.assertRaises(ValueError, lambda: color0.lerp((0, 0, 256, 0), 0.5)) + self.assertRaises(ValueError, lambda: color0.lerp((0, 0, 0, 256), 0.5)) + self.assertRaises(TypeError, lambda: color0.lerp(0.2, 0.5)) + + def test_premul_alpha(self): + # setup + Color = pygame.color.Color + + color0 = Color(0, 0, 0, 0) + alpha0 = Color(255, 255, 255, 0) + alpha49 = Color(255, 0, 0, 49) + alpha67 = Color(0, 255, 0, 67) + alpha73 = Color(0, 0, 255, 73) + alpha128 = Color(255, 255, 255, 128) + alpha199 = Color(255, 255, 255, 199) + alpha255 = Color(128, 128, 128, 255) + + # type checking + self.assertTrue(isinstance(color0.premul_alpha(), Color)) + + # hand crafted value testing + self.assertEqual(alpha0.premul_alpha(), Color(0, 0, 0, 0)) + self.assertEqual(alpha49.premul_alpha(), Color(49, 0, 0, 49)) + self.assertEqual(alpha67.premul_alpha(), Color(0, 67, 0, 67)) + self.assertEqual(alpha73.premul_alpha(), Color(0, 0, 73, 73)) + self.assertEqual(alpha128.premul_alpha(), Color(128, 128, 128, 128)) + self.assertEqual(alpha199.premul_alpha(), Color(199, 199, 199, 199)) + self.assertEqual(alpha255.premul_alpha(), Color(128, 128, 128, 255)) + + # full range of alpha auto sub-testing + test_colors = [ + (200, 30, 74), + (76, 83, 24), + (184, 21, 6), + (74, 4, 74), + (76, 83, 24), + (184, 21, 234), + (160, 30, 74), + (96, 147, 204), + (198, 201, 60), + (132, 89, 74), + (245, 9, 224), + (184, 112, 6), + ] + + for r, g, b in test_colors: + for a in range(255): + with self.subTest(r=r, g=g, b=b, a=a): + alpha = a / 255.0 + self.assertEqual( + Color(r, g, b, a).premul_alpha(), + Color( + ((r + 1) * a) >> 8, + ((g + 1) * a) >> 8, + ((b + 1) * a) >> 8, + a, + ), + ) + + def test_update(self): + c = pygame.color.Color(0, 0, 0) + c.update(1, 2, 3, 4) + + self.assertEqual(c.r, 1) + self.assertEqual(c.g, 2) + self.assertEqual(c.b, 3) + self.assertEqual(c.a, 4) + + c = pygame.color.Color(0, 0, 0) + c.update([1, 2, 3, 4]) + + self.assertEqual(c.r, 1) + self.assertEqual(c.g, 2) + self.assertEqual(c.b, 3) + self.assertEqual(c.a, 4) + + c = pygame.color.Color(0, 0, 0) + c2 = pygame.color.Color(1, 2, 3, 4) + c.update(c2) + + self.assertEqual(c.r, 1) + self.assertEqual(c.g, 2) + self.assertEqual(c.b, 3) + self.assertEqual(c.a, 4) + + c = pygame.color.Color(1, 1, 1) + c.update("black") + + self.assertEqual(c.r, 0) + self.assertEqual(c.g, 0) + self.assertEqual(c.b, 0) + self.assertEqual(c.a, 255) + + c = pygame.color.Color(0, 0, 0, 120) + c.set_length(3) + c.update(1, 2, 3) + self.assertEqual(len(c), 3) + c.set_length(4) + self.assertEqual(c[3], 120) + + c.set_length(3) + c.update(1, 2, 3, 4) + self.assertEqual(len(c), 4) + + +class SubclassTest(unittest.TestCase): + class MyColor(pygame.Color): + def __init__(self, *args, **kwds): + super(SubclassTest.MyColor, self).__init__(*args, **kwds) + self.an_attribute = True + + def test_add(self): + mc1 = self.MyColor(128, 128, 128, 255) + self.assertTrue(mc1.an_attribute) + c2 = pygame.Color(64, 64, 64, 255) + mc2 = mc1 + c2 + self.assertTrue(isinstance(mc2, self.MyColor)) + self.assertRaises(AttributeError, getattr, mc2, "an_attribute") + c3 = c2 + mc1 + self.assertTrue(type(c3) is pygame.Color) + + def test_sub(self): + mc1 = self.MyColor(128, 128, 128, 255) + self.assertTrue(mc1.an_attribute) + c2 = pygame.Color(64, 64, 64, 255) + mc2 = mc1 - c2 + self.assertTrue(isinstance(mc2, self.MyColor)) + self.assertRaises(AttributeError, getattr, mc2, "an_attribute") + c3 = c2 - mc1 + self.assertTrue(type(c3) is pygame.Color) + + def test_mul(self): + mc1 = self.MyColor(128, 128, 128, 255) + self.assertTrue(mc1.an_attribute) + c2 = pygame.Color(64, 64, 64, 255) + mc2 = mc1 * c2 + self.assertTrue(isinstance(mc2, self.MyColor)) + self.assertRaises(AttributeError, getattr, mc2, "an_attribute") + c3 = c2 * mc1 + self.assertTrue(type(c3) is pygame.Color) + + def test_div(self): + mc1 = self.MyColor(128, 128, 128, 255) + self.assertTrue(mc1.an_attribute) + c2 = pygame.Color(64, 64, 64, 255) + mc2 = mc1 // c2 + self.assertTrue(isinstance(mc2, self.MyColor)) + self.assertRaises(AttributeError, getattr, mc2, "an_attribute") + c3 = c2 // mc1 + self.assertTrue(type(c3) is pygame.Color) + + def test_mod(self): + mc1 = self.MyColor(128, 128, 128, 255) + self.assertTrue(mc1.an_attribute) + c2 = pygame.Color(64, 64, 64, 255) + mc2 = mc1 % c2 + self.assertTrue(isinstance(mc2, self.MyColor)) + self.assertRaises(AttributeError, getattr, mc2, "an_attribute") + c3 = c2 % mc1 + self.assertTrue(type(c3) is pygame.Color) + + def test_inv(self): + mc1 = self.MyColor(64, 64, 64, 64) + self.assertTrue(mc1.an_attribute) + mc2 = ~mc1 + self.assertTrue(isinstance(mc2, self.MyColor)) + self.assertRaises(AttributeError, getattr, mc2, "an_attribute") + + def test_correct_gamma(self): + mc1 = self.MyColor(64, 70, 75, 255) + self.assertTrue(mc1.an_attribute) + mc2 = mc1.correct_gamma(0.03) + self.assertTrue(isinstance(mc2, self.MyColor)) + self.assertRaises(AttributeError, getattr, mc2, "an_attribute") + + +################################################################################ + +if __name__ == "__main__": + unittest.main() diff --git a/venv/Lib/site-packages/pygame/tests/constants_test.py b/venv/Lib/site-packages/pygame/tests/constants_test.py new file mode 100644 index 0000000..452a8fe --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/constants_test.py @@ -0,0 +1,437 @@ +import unittest +import pygame.constants + + +# K_* and KSCAN_* common names. +K_AND_KSCAN_COMMON_NAMES = ( + "UNKNOWN", + "BACKSPACE", + "TAB", + "CLEAR", + "RETURN", + "PAUSE", + "ESCAPE", + "SPACE", + "COMMA", + "MINUS", + "PERIOD", + "SLASH", + "0", + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + "SEMICOLON", + "EQUALS", + "LEFTBRACKET", + "BACKSLASH", + "RIGHTBRACKET", + "DELETE", + "KP0", + "KP1", + "KP2", + "KP3", + "KP4", + "KP5", + "KP6", + "KP7", + "KP8", + "KP9", + "KP_PERIOD", + "KP_DIVIDE", + "KP_MULTIPLY", + "KP_MINUS", + "KP_PLUS", + "KP_ENTER", + "KP_EQUALS", + "UP", + "DOWN", + "RIGHT", + "LEFT", + "INSERT", + "HOME", + "END", + "PAGEUP", + "PAGEDOWN", + "F1", + "F2", + "F3", + "F4", + "F5", + "F6", + "F7", + "F8", + "F9", + "F10", + "F11", + "F12", + "F13", + "F14", + "F15", + "NUMLOCK", + "CAPSLOCK", + "SCROLLOCK", + "RSHIFT", + "LSHIFT", + "RCTRL", + "LCTRL", + "RALT", + "LALT", + "RMETA", + "LMETA", + "LSUPER", + "RSUPER", + "MODE", + "HELP", + "PRINT", + "SYSREQ", + "BREAK", + "MENU", + "POWER", + "EURO", + "KP_0", + "KP_1", + "KP_2", + "KP_3", + "KP_4", + "KP_5", + "KP_6", + "KP_7", + "KP_8", + "KP_9", + "NUMLOCKCLEAR", + "SCROLLLOCK", + "RGUI", + "LGUI", + "PRINTSCREEN", + "CURRENCYUNIT", + "CURRENCYSUBUNIT", +) + +# Constants that have the same value. +K_AND_KSCAN_COMMON_OVERLAPS = ( + ("KP0", "KP_0"), + ("KP1", "KP_1"), + ("KP2", "KP_2"), + ("KP3", "KP_3"), + ("KP4", "KP_4"), + ("KP5", "KP_5"), + ("KP6", "KP_6"), + ("KP7", "KP_7"), + ("KP8", "KP_8"), + ("KP9", "KP_9"), + ("NUMLOCK", "NUMLOCKCLEAR"), + ("SCROLLOCK", "SCROLLLOCK"), + ("LSUPER", "LMETA", "LGUI"), + ("RSUPER", "RMETA", "RGUI"), + ("PRINT", "PRINTSCREEN"), + ("BREAK", "PAUSE"), + ("EURO", "CURRENCYUNIT"), +) + + +def create_overlap_set(constant_names): + """Helper function to find overlapping constant values/names. + + Returns a set of fronzensets: + set(frozenset(names of overlapping constants), ...) + """ + # Create an overlap dict. + overlap_dict = {} + + for name in constant_names: + value = getattr(pygame.constants, name) + overlap_dict.setdefault(value, set()).add(name) + + # Get all entries with more than 1 value. + overlaps = set() + + for overlap_names in overlap_dict.values(): + if len(overlap_names) > 1: + overlaps.add(frozenset(overlap_names)) + + return overlaps + + +class KConstantsTests(unittest.TestCase): + """Test K_* (key) constants.""" + + # K_* specific names. + K_SPECIFIC_NAMES = ( + "a", + "b", + "c", + "d", + "e", + "f", + "g", + "h", + "i", + "j", + "k", + "l", + "m", + "n", + "o", + "p", + "q", + "r", + "s", + "t", + "u", + "v", + "w", + "x", + "y", + "z", + "QUOTE", + "BACKQUOTE", + "EXCLAIM", + "QUOTEDBL", + "HASH", + "DOLLAR", + "AMPERSAND", + "LEFTPAREN", + "RIGHTPAREN", + "ASTERISK", + "PLUS", + "COLON", + "LESS", + "GREATER", + "QUESTION", + "AT", + "CARET", + "UNDERSCORE", + "PERCENT", + ) + + # Create a sequence of all the K_* constant names. + K_NAMES = tuple("K_" + n for n in K_AND_KSCAN_COMMON_NAMES + K_SPECIFIC_NAMES) + + def test_k__existence(self): + """Ensures K constants exist.""" + for name in self.K_NAMES: + self.assertTrue( + hasattr(pygame.constants, name), "missing constant {}".format(name) + ) + + def test_k__type(self): + """Ensures K constants are the correct type.""" + for name in self.K_NAMES: + value = getattr(pygame.constants, name) + + self.assertIs(type(value), int) + + def test_k__value_overlap(self): + """Ensures no unexpected K constant values overlap.""" + EXPECTED_OVERLAPS = set( + [ + frozenset(["K_" + n for n in item]) + for item in K_AND_KSCAN_COMMON_OVERLAPS + ] + ) + + overlaps = create_overlap_set(self.K_NAMES) + + self.assertSetEqual(overlaps, EXPECTED_OVERLAPS) + + +class KscanConstantsTests(unittest.TestCase): + """Test KSCAN_* (scancode) constants.""" + + # KSCAN_* specific names. + KSCAN_SPECIFIC_NAMES = ( + "A", + "B", + "C", + "D", + "E", + "F", + "G", + "H", + "I", + "J", + "K", + "L", + "M", + "N", + "O", + "P", + "Q", + "R", + "S", + "T", + "U", + "V", + "W", + "X", + "Y", + "Z", + "APOSTROPHE", + "GRAVE", + "INTERNATIONAL1", + "INTERNATIONAL2", + "INTERNATIONAL3", + "INTERNATIONAL4", + "INTERNATIONAL5", + "INTERNATIONAL6", + "INTERNATIONAL7", + "INTERNATIONAL8", + "INTERNATIONAL9", + "LANG1", + "LANG2", + "LANG3", + "LANG4", + "LANG5", + "LANG6", + "LANG7", + "LANG8", + "LANG9", + "NONUSBACKSLASH", + "NONUSHASH", + ) + + # Create a sequence of all the KSCAN_* constant names. + KSCAN_NAMES = tuple( + "KSCAN_" + n for n in K_AND_KSCAN_COMMON_NAMES + KSCAN_SPECIFIC_NAMES + ) + + def test_kscan__existence(self): + """Ensures KSCAN constants exist.""" + for name in self.KSCAN_NAMES: + self.assertTrue( + hasattr(pygame.constants, name), "missing constant {}".format(name) + ) + + def test_kscan__type(self): + """Ensures KSCAN constants are the correct type.""" + for name in self.KSCAN_NAMES: + value = getattr(pygame.constants, name) + + self.assertIs(type(value), int) + + def test_kscan__value_overlap(self): + """Ensures no unexpected KSCAN constant values overlap.""" + EXPECTED_OVERLAPS = set( + [ + frozenset(["KSCAN_" + n for n in item]) + for item in K_AND_KSCAN_COMMON_OVERLAPS + ] + ) + + overlaps = create_overlap_set(self.KSCAN_NAMES) + + self.assertSetEqual(overlaps, EXPECTED_OVERLAPS) + + +class KmodConstantsTests(unittest.TestCase): + """Test KMOD_* (key modifier) constants.""" + + # KMOD_* constant names. + KMOD_CONSTANTS = ( + "KMOD_NONE", + "KMOD_LSHIFT", + "KMOD_RSHIFT", + "KMOD_SHIFT", + "KMOD_LCTRL", + "KMOD_RCTRL", + "KMOD_CTRL", + "KMOD_LALT", + "KMOD_RALT", + "KMOD_ALT", + "KMOD_LMETA", + "KMOD_RMETA", + "KMOD_META", + "KMOD_NUM", + "KMOD_CAPS", + "KMOD_MODE", + "KMOD_LGUI", + "KMOD_RGUI", + "KMOD_GUI", + ) + + def test_kmod__existence(self): + """Ensures KMOD constants exist.""" + for name in self.KMOD_CONSTANTS: + self.assertTrue( + hasattr(pygame.constants, name), "missing constant {}".format(name) + ) + + def test_kmod__type(self): + """Ensures KMOD constants are the correct type.""" + for name in self.KMOD_CONSTANTS: + value = getattr(pygame.constants, name) + + self.assertIs(type(value), int) + + def test_kmod__value_overlap(self): + """Ensures no unexpected KMOD constant values overlap.""" + # KMODs that have the same values. + EXPECTED_OVERLAPS = { + frozenset(["KMOD_LGUI", "KMOD_LMETA"]), + frozenset(["KMOD_RGUI", "KMOD_RMETA"]), + frozenset(["KMOD_GUI", "KMOD_META"]), + } + + overlaps = create_overlap_set(self.KMOD_CONSTANTS) + + self.assertSetEqual(overlaps, EXPECTED_OVERLAPS) + + def test_kmod__no_bitwise_overlap(self): + """Ensures certain KMOD constants have no overlapping bits.""" + NO_BITWISE_OVERLAP = ( + "KMOD_NONE", + "KMOD_LSHIFT", + "KMOD_RSHIFT", + "KMOD_LCTRL", + "KMOD_RCTRL", + "KMOD_LALT", + "KMOD_RALT", + "KMOD_LMETA", + "KMOD_RMETA", + "KMOD_NUM", + "KMOD_CAPS", + "KMOD_MODE", + ) + + kmods = 0 + + for name in NO_BITWISE_OVERLAP: + value = getattr(pygame.constants, name) + + self.assertFalse(kmods & value) + + kmods |= value + + def test_kmod__bitwise_overlap(self): + """Ensures certain KMOD constants have overlapping bits.""" + # KMODS that are comprised of other KMODs. + KMOD_COMPRISED_DICT = { + "KMOD_SHIFT": ("KMOD_LSHIFT", "KMOD_RSHIFT"), + "KMOD_CTRL": ("KMOD_LCTRL", "KMOD_RCTRL"), + "KMOD_ALT": ("KMOD_LALT", "KMOD_RALT"), + "KMOD_META": ("KMOD_LMETA", "KMOD_RMETA"), + "KMOD_GUI": ("KMOD_LGUI", "KMOD_RGUI"), + } + + for base_name, seq_names in KMOD_COMPRISED_DICT.items(): + expected_value = 0 # Reset. + + for name in seq_names: + expected_value |= getattr(pygame.constants, name) + + value = getattr(pygame.constants, base_name) + + self.assertEqual(value, expected_value) + + +################################################################################ + + +if __name__ == "__main__": + unittest.main() diff --git a/venv/Lib/site-packages/pygame/tests/controller_test.py b/venv/Lib/site-packages/pygame/tests/controller_test.py new file mode 100644 index 0000000..f05c00c --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/controller_test.py @@ -0,0 +1,357 @@ +import unittest +import pygame +import pygame._sdl2.controller as controller +from pygame.tests.test_utils import prompt, question + + +class ControllerModuleTest(unittest.TestCase): + def setUp(self): + controller.init() + + def tearDown(self): + controller.quit() + + def test_init(self): + controller.quit() + controller.init() + self.assertTrue(controller.get_init()) + + def test_init__multiple(self): + controller.init() + controller.init() + self.assertTrue(controller.get_init()) + + def test_quit(self): + controller.quit() + self.assertFalse(controller.get_init()) + + def test_quit__multiple(self): + controller.quit() + controller.quit() + self.assertFalse(controller.get_init()) + + def test_get_init(self): + self.assertTrue(controller.get_init()) + + def test_get_eventstate(self): + controller.set_eventstate(True) + self.assertTrue(controller.get_eventstate()) + + controller.set_eventstate(False) + self.assertFalse(controller.get_eventstate()) + + controller.set_eventstate(True) + + def test_get_count(self): + self.assertGreaterEqual(controller.get_count(), 0) + + def test_is_controller(self): + for i in range(controller.get_count()): + if controller.is_controller(i): + c = controller.Controller(i) + self.assertIsInstance(c, controller.Controller) + c.quit() + else: + with self.assertRaises(pygame._sdl2.sdl2.error): + c = controller.Controller(i) + + with self.assertRaises(TypeError): + controller.is_controller("Test") + + def test_name_forindex(self): + self.assertIsNone(controller.name_forindex(-1)) + + +class ControllerTypeTest(unittest.TestCase): + def setUp(self): + controller.init() + + def tearDown(self): + controller.quit() + + def _get_first_controller(self): + for i in range(controller.get_count()): + if controller.is_controller(i): + return controller.Controller(i) + + def test_construction(self): + c = self._get_first_controller() + if c: + self.assertIsInstance(c, controller.Controller) + else: + self.skipTest("No controller connected") + + def test__auto_init(self): + c = self._get_first_controller() + if c: + self.assertTrue(c.get_init()) + else: + self.skipTest("No controller connected") + + def test_get_init(self): + c = self._get_first_controller() + if c: + self.assertTrue(c.get_init()) + c.quit() + self.assertFalse(c.get_init()) + else: + self.skipTest("No controller connected") + + def test_from_joystick(self): + for i in range(controller.get_count()): + if controller.is_controller(i): + joy = pygame.joystick.Joystick(i) + break + else: + self.skipTest("No controller connected") + + c = controller.Controller.from_joystick(joy) + self.assertIsInstance(c, controller.Controller) + + def test_as_joystick(self): + c = self._get_first_controller() + if c: + joy = c.as_joystick() + self.assertIsInstance(joy, type(pygame.joystick.Joystick(0))) + else: + self.skipTest("No controller connected") + + def test_get_mapping(self): + c = self._get_first_controller() + if c: + mapping = c.get_mapping() + self.assertIsInstance(mapping, dict) + self.assertIsNotNone(mapping["a"]) + else: + self.skipTest("No controller connected") + + def test_set_mapping(self): + c = self._get_first_controller() + if c: + mapping = c.get_mapping() + mapping["a"] = "b3" + mapping["y"] = "b0" + c.set_mapping(mapping) + new_mapping = c.get_mapping() + + self.assertEqual(len(mapping), len(new_mapping)) + for i in mapping: + if mapping[i] not in ("a", "y"): + self.assertEqual(mapping[i], new_mapping[i]) + else: + if i == "a": + self.assertEqual(new_mapping[i], mapping["y"]) + else: + self.assertEqual(new_mapping[i], mapping["a"]) + else: + self.skipTest("No controller connected") + + +class ControllerInteractiveTest(unittest.TestCase): + __tags__ = ["interactive"] + + def _get_first_controller(self): + for i in range(controller.get_count()): + if controller.is_controller(i): + return controller.Controller(i) + + def setUp(self): + controller.init() + + def tearDown(self): + controller.quit() + + def test__get_count_interactive(self): + prompt( + "Please connect at least one controller " + "before the test for controller.get_count() starts" + ) + + # Reset the number of joysticks counted + controller.quit() + controller.init() + + joystick_num = controller.get_count() + ans = question( + "get_count() thinks there are {} joysticks " + "connected. Is that correct?".format(joystick_num) + ) + + self.assertTrue(ans) + + def test_set_eventstate_on_interactive(self): + c = self._get_first_controller() + if not c: + self.skipTest("No controller connected") + + pygame.display.init() + pygame.font.init() + + screen = pygame.display.set_mode((400, 400)) + font = pygame.font.Font(None, 20) + running = True + + screen.fill((255, 255, 255)) + screen.blit( + font.render("Press button 'x' (on ps4) or 'a' (on xbox).", True, (0, 0, 0)), + (0, 0), + ) + pygame.display.update() + + controller.set_eventstate(True) + + while running: + for event in pygame.event.get(): + if event.type == pygame.QUIT: + running = False + + if event.type == pygame.CONTROLLERBUTTONDOWN: + running = False + + pygame.display.quit() + pygame.font.quit() + + def test_set_eventstate_off_interactive(self): + c = self._get_first_controller() + if not c: + self.skipTest("No controller connected") + + pygame.display.init() + pygame.font.init() + + screen = pygame.display.set_mode((400, 400)) + font = pygame.font.Font(None, 20) + running = True + + screen.fill((255, 255, 255)) + screen.blit( + font.render("Press button 'x' (on ps4) or 'a' (on xbox).", True, (0, 0, 0)), + (0, 0), + ) + pygame.display.update() + + controller.set_eventstate(False) + + while running: + for event in pygame.event.get(pygame.QUIT): + if event: + running = False + + if c.get_button(pygame.CONTROLLER_BUTTON_A): + if pygame.event.peek(pygame.CONTROLLERBUTTONDOWN): + pygame.display.quit() + pygame.font.quit() + self.fail() + else: + running = False + + pygame.display.quit() + pygame.font.quit() + + def test_get_button_interactive(self): + c = self._get_first_controller() + if not c: + self.skipTest("No controller connected") + + pygame.display.init() + pygame.font.init() + + screen = pygame.display.set_mode((400, 400)) + font = pygame.font.Font(None, 20) + running = True + + label1 = font.render( + "Press button 'x' (on ps4) or 'a' (on xbox).", True, (0, 0, 0) + ) + + label2 = font.render( + 'The two values should match up. Press "y" or "n" to confirm.', + True, + (0, 0, 0), + ) + + is_pressed = [False, False] # event, get_button() + while running: + for event in pygame.event.get(): + if event.type == pygame.QUIT: + running = False + if event.type == pygame.CONTROLLERBUTTONDOWN and event.button == 0: + is_pressed[0] = True + if event.type == pygame.CONTROLLERBUTTONUP and event.button == 0: + is_pressed[0] = False + + if event.type == pygame.KEYDOWN: + if event.key == pygame.K_y: + running = False + if event.key == pygame.K_n: + running = False + pygame.display.quit() + pygame.font.quit() + self.fail() + + is_pressed[1] = c.get_button(pygame.CONTROLLER_BUTTON_A) + + screen.fill((255, 255, 255)) + screen.blit(label1, (0, 0)) + screen.blit(label2, (0, 20)) + screen.blit(font.render(str(is_pressed), True, (0, 0, 0)), (0, 40)) + pygame.display.update() + + pygame.display.quit() + pygame.font.quit() + + def test_get_axis_interactive(self): + c = self._get_first_controller() + if not c: + self.skipTest("No controller connected") + + pygame.display.init() + pygame.font.init() + + screen = pygame.display.set_mode((400, 400)) + font = pygame.font.Font(None, 20) + running = True + + label1 = font.render( + "Press down the right trigger. The value on-screen should", True, (0, 0, 0) + ) + + label2 = font.render( + "indicate how far the trigger is pressed down. This value should", + True, + (0, 0, 0), + ) + + label3 = font.render( + 'be in the range of 0-32767. Press "y" or "n" to confirm.', True, (0, 0, 0) + ) + + while running: + for event in pygame.event.get(): + if event.type == pygame.QUIT: + running = False + + if event.type == pygame.KEYDOWN: + if event.key == pygame.K_y: + running = False + if event.key == pygame.K_n: + running = False + pygame.display.quit() + pygame.font.quit() + self.fail() + + right_trigger = c.get_axis(pygame.CONTROLLER_AXIS_TRIGGERRIGHT) + + screen.fill((255, 255, 255)) + screen.blit(label1, (0, 0)) + screen.blit(label2, (0, 20)) + screen.blit(label3, (0, 40)) + screen.blit(font.render(str(right_trigger), True, (0, 0, 0)), (0, 60)) + pygame.display.update() + + pygame.display.quit() + pygame.font.quit() + + +if __name__ == "__main__": + unittest.main() diff --git a/venv/Lib/site-packages/pygame/tests/cursors_test.py b/venv/Lib/site-packages/pygame/tests/cursors_test.py new file mode 100644 index 0000000..bb8f766 --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/cursors_test.py @@ -0,0 +1,291 @@ +import unittest +from pygame.tests.test_utils import fixture_path +import pygame + + +class CursorsModuleTest(unittest.TestCase): + def test_compile(self): + + # __doc__ (as of 2008-06-25) for pygame.cursors.compile: + + # pygame.cursors.compile(strings, black, white,xor) -> data, mask + # compile cursor strings into cursor data + # + # This takes a set of strings with equal length and computes + # the binary data for that cursor. The string widths must be + # divisible by 8. + # + # The black and white arguments are single letter strings that + # tells which characters will represent black pixels, and which + # characters represent white pixels. All other characters are + # considered clear. + # + # This returns a tuple containing the cursor data and cursor mask + # data. Both these arguments are used when setting a cursor with + # pygame.mouse.set_cursor(). + + # Various types of input strings + test_cursor1 = ("X.X.XXXX", "XXXXXX..", " XXXX ") + + test_cursor2 = ( + "X.X.XXXX", + "XXXXXX..", + "XXXXXX ", + "XXXXXX..", + "XXXXXX..", + "XXXXXX", + "XXXXXX..", + "XXXXXX..", + ) + test_cursor3 = (".XX.", " ", ".. ", "X.. X") + + # Test such that total number of strings is not divisible by 8 + with self.assertRaises(ValueError): + pygame.cursors.compile(test_cursor1) + + # Test such that size of individual string is not divisible by 8 + with self.assertRaises(ValueError): + pygame.cursors.compile(test_cursor2) + + # Test such that neither size of individual string nor total number of strings is divisible by 8 + with self.assertRaises(ValueError): + pygame.cursors.compile(test_cursor3) + + # Test that checks whether the byte data from compile funtion is equal to actual byte data + actual_byte_data = ( + 192, + 0, + 0, + 224, + 0, + 0, + 240, + 0, + 0, + 216, + 0, + 0, + 204, + 0, + 0, + 198, + 0, + 0, + 195, + 0, + 0, + 193, + 128, + 0, + 192, + 192, + 0, + 192, + 96, + 0, + 192, + 48, + 0, + 192, + 56, + 0, + 192, + 248, + 0, + 220, + 192, + 0, + 246, + 96, + 0, + 198, + 96, + 0, + 6, + 96, + 0, + 3, + 48, + 0, + 3, + 48, + 0, + 1, + 224, + 0, + 1, + 128, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + ), ( + 192, + 0, + 0, + 224, + 0, + 0, + 240, + 0, + 0, + 248, + 0, + 0, + 252, + 0, + 0, + 254, + 0, + 0, + 255, + 0, + 0, + 255, + 128, + 0, + 255, + 192, + 0, + 255, + 224, + 0, + 255, + 240, + 0, + 255, + 248, + 0, + 255, + 248, + 0, + 255, + 192, + 0, + 247, + 224, + 0, + 199, + 224, + 0, + 7, + 224, + 0, + 3, + 240, + 0, + 3, + 240, + 0, + 1, + 224, + 0, + 1, + 128, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + ) + + cursor = pygame.cursors.compile(pygame.cursors.thickarrow_strings) + self.assertEqual(cursor, actual_byte_data) + + # Test such that cursor byte data obtained from compile function is valid in pygame.mouse.set_cursor() + pygame.display.init() + try: + pygame.mouse.set_cursor((24, 24), (0, 0), *cursor) + except pygame.error as e: + if "not currently supported" in str(e): + unittest.skip("skipping test as set_cursor() is not supported") + finally: + pygame.display.quit() + + ################################################################################ + + def test_load_xbm(self): + # __doc__ (as of 2008-06-25) for pygame.cursors.load_xbm: + + # pygame.cursors.load_xbm(cursorfile, maskfile) -> cursor_args + # reads a pair of XBM files into set_cursor arguments + # + # Arguments can either be filenames or filelike objects + # with the readlines method. Not largely tested, but + # should work with typical XBM files. + + # Test that load_xbm will take filenames as arguments + cursorfile = fixture_path(r"xbm_cursors/white_sizing.xbm") + maskfile = fixture_path(r"xbm_cursors/white_sizing_mask.xbm") + cursor = pygame.cursors.load_xbm(cursorfile, maskfile) + + # Test that load_xbm will take file objects as arguments + with open(cursorfile) as cursor_f, open(maskfile) as mask_f: + cursor = pygame.cursors.load_xbm(cursor_f, mask_f) + + # Can it load using pathlib.Path? + import pathlib + + cursor = pygame.cursors.load_xbm( + pathlib.Path(cursorfile), pathlib.Path(maskfile) + ) + + # Is it in a format that mouse.set_cursor won't blow up on? + pygame.display.init() + try: + pygame.mouse.set_cursor(*cursor) + except pygame.error as e: + if "not currently supported" in str(e): + unittest.skip("skipping test as set_cursor() is not supported") + finally: + pygame.display.quit() + + def test_Cursor(self): + """Ensure that the cursor object parses information properly""" + + c1 = pygame.cursors.Cursor(pygame.SYSTEM_CURSOR_CROSSHAIR) + + self.assertEqual(c1.data, (pygame.SYSTEM_CURSOR_CROSSHAIR,)) + self.assertEqual(c1.type, "system") + + c2 = pygame.cursors.Cursor(c1) + + self.assertEqual(c1, c2) + + with self.assertRaises(TypeError): + pygame.cursors.Cursor(-34002) + with self.assertRaises(TypeError): + pygame.cursors.Cursor("a", "b", "c", "d") + with self.assertRaises(TypeError): + pygame.cursors.Cursor((2,)) + + c3 = pygame.cursors.Cursor((0, 0), pygame.Surface((20, 20))) + + self.assertEqual(c3.data[0], (0, 0)) + self.assertEqual(c3.data[1].get_size(), (20, 20)) + self.assertEqual(c3.type, "color") + + xormask, andmask = pygame.cursors.compile(pygame.cursors.thickarrow_strings) + c4 = pygame.cursors.Cursor((24, 24), (0, 0), xormask, andmask) + + self.assertEqual(c4.data, ((24, 24), (0, 0), xormask, andmask)) + self.assertEqual(c4.type, "bitmap") + + +################################################################################ + +if __name__ == "__main__": + unittest.main() + +################################################################################ diff --git a/venv/Lib/site-packages/pygame/tests/display_test.py b/venv/Lib/site-packages/pygame/tests/display_test.py new file mode 100644 index 0000000..a44ff15 --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/display_test.py @@ -0,0 +1,811 @@ +# -*- coding: utf-8 -*- + +import unittest +import os +import time + +import pygame, pygame.transform + +from pygame.tests.test_utils import question + +from pygame import display + + +class DisplayModuleTest(unittest.TestCase): + default_caption = "pygame window" + + def setUp(self): + display.init() + + def tearDown(self): + display.quit() + + def test_Info(self): + inf = pygame.display.Info() + self.assertNotEqual(inf.current_h, -1) + self.assertNotEqual(inf.current_w, -1) + # probably have an older SDL than 1.2.10 if -1. + + screen = pygame.display.set_mode((128, 128)) + inf = pygame.display.Info() + self.assertEqual(inf.current_h, 128) + self.assertEqual(inf.current_w, 128) + + def test_flip(self): + screen = pygame.display.set_mode((100, 100)) + + # test without a change + self.assertIsNone(pygame.display.flip()) + + # test with a change + pygame.Surface.fill(screen, (66, 66, 53)) + self.assertIsNone(pygame.display.flip()) + + # test without display init + pygame.display.quit() + with self.assertRaises(pygame.error): + (pygame.display.flip()) + + # test without window + del screen + with self.assertRaises(pygame.error): + (pygame.display.flip()) + + def test_get_active(self): + """Test the get_active function""" + + # Initially, the display is not active + pygame.display.quit() + self.assertEqual(pygame.display.get_active(), False) + + # get_active defaults to true after a set_mode + pygame.display.init() + pygame.display.set_mode((640, 480)) + self.assertEqual(pygame.display.get_active(), True) + + # get_active after init/quit should be False + # since no display is visible + pygame.display.quit() + pygame.display.init() + self.assertEqual(pygame.display.get_active(), False) + + @unittest.skipIf( + os.environ.get("SDL_VIDEODRIVER") == "dummy", + "requires the SDL_VIDEODRIVER to be a non dummy value", + ) + def test_get_active_iconify(self): + """Test the get_active function after an iconify""" + + # According to the docs, get_active should return + # false if the display is iconified + pygame.display.set_mode((640, 480)) + + pygame.event.clear() + pygame.display.iconify() + + for _ in range(100): + time.sleep(0.01) + pygame.event.pump() + + self.assertEqual(pygame.display.get_active(), False) + + def test_get_caption(self): + screen = display.set_mode((100, 100)) + + self.assertEqual(display.get_caption()[0], self.default_caption) + + def test_set_caption(self): + TEST_CAPTION = "test" + screen = display.set_mode((100, 100)) + + self.assertIsNone(display.set_caption(TEST_CAPTION)) + self.assertEqual(display.get_caption()[0], TEST_CAPTION) + self.assertEqual(display.get_caption()[1], TEST_CAPTION) + + def test_caption_unicode(self): + TEST_CAPTION = "å°" + display.set_caption(TEST_CAPTION) + self.assertEqual(display.get_caption()[0], TEST_CAPTION) + + def test_get_driver(self): + drivers = [ + "aalib", + "android", + "arm", + "cocoa", + "dga", + "directx", + "directfb", + "dummy", + "emscripten", + "fbcon", + "ggi", + "haiku", + "khronos", + "kmsdrm", + "nacl", + "offscreen", + "pandora", + "psp", + "qnx", + "raspberry", + "svgalib", + "uikit", + "vgl", + "vivante", + "wayland", + "windows", + "windib", + "winrt", + "x11", + ] + driver = display.get_driver() + self.assertIn(driver, drivers) + + display.quit() + with self.assertRaises(pygame.error): + driver = display.get_driver() + + def test_get_init(self): + """Ensures the module's initialization state can be retrieved.""" + # display.init() already called in setUp() + self.assertTrue(display.get_init()) + + # This test can be uncommented when issues #991 and #993 are resolved. + @unittest.skipIf(True, "SDL2 issues") + def test_get_surface(self): + """Ensures get_surface gets the current display surface.""" + lengths = (1, 5, 100) + + for expected_size in ((w, h) for w in lengths for h in lengths): + for expected_depth in (8, 16, 24, 32): + expected_surface = display.set_mode(expected_size, 0, expected_depth) + + surface = pygame.display.get_surface() + + self.assertEqual(surface, expected_surface) + self.assertIsInstance(surface, pygame.Surface) + self.assertEqual(surface.get_size(), expected_size) + self.assertEqual(surface.get_bitsize(), expected_depth) + + def test_get_surface__mode_not_set(self): + """Ensures get_surface handles the display mode not being set.""" + surface = pygame.display.get_surface() + + self.assertIsNone(surface) + + def test_get_wm_info(self): + wm_info = display.get_wm_info() + # Assert function returns a dictionary type + self.assertIsInstance(wm_info, dict) + + wm_info_potential_keys = { + "colorbuffer", + "connection", + "data", + "dfb", + "display", + "framebuffer", + "fswindow", + "hdc", + "hglrc", + "hinstance", + "lock_func", + "resolveFramebuffer", + "shell_surface", + "surface", + "taskHandle", + "unlock_func", + "wimpVersion", + "window", + "wmwindow", + } + + # If any unexpected dict keys are present, they + # will be stored in set wm_info_remaining_keys + wm_info_remaining_keys = set(wm_info.keys()).difference(wm_info_potential_keys) + + # Assert set is empty (& therefore does not + # contain unexpected dict keys) + self.assertFalse(wm_info_remaining_keys) + + @unittest.skipIf( + ( + "skipping for all because some failures on rasppi and maybe other platforms" + or os.environ.get("SDL_VIDEODRIVER") == "dummy" + ), + 'OpenGL requires a non-"dummy" SDL_VIDEODRIVER', + ) + def test_gl_get_attribute(self): + + screen = display.set_mode((0, 0), pygame.OPENGL) + + # We create a list where we store the original values of the + # flags before setting them with a different value. + original_values = [] + + original_values.append(pygame.display.gl_get_attribute(pygame.GL_ALPHA_SIZE)) + original_values.append(pygame.display.gl_get_attribute(pygame.GL_DEPTH_SIZE)) + original_values.append(pygame.display.gl_get_attribute(pygame.GL_STENCIL_SIZE)) + original_values.append( + pygame.display.gl_get_attribute(pygame.GL_ACCUM_RED_SIZE) + ) + original_values.append( + pygame.display.gl_get_attribute(pygame.GL_ACCUM_GREEN_SIZE) + ) + original_values.append( + pygame.display.gl_get_attribute(pygame.GL_ACCUM_BLUE_SIZE) + ) + original_values.append( + pygame.display.gl_get_attribute(pygame.GL_ACCUM_ALPHA_SIZE) + ) + original_values.append( + pygame.display.gl_get_attribute(pygame.GL_MULTISAMPLEBUFFERS) + ) + original_values.append( + pygame.display.gl_get_attribute(pygame.GL_MULTISAMPLESAMPLES) + ) + original_values.append(pygame.display.gl_get_attribute(pygame.GL_STEREO)) + + original_values.append( + pygame.display.gl_get_attribute(pygame.GL_ACCELERATED_VISUAL) + ) + original_values.append( + pygame.display.gl_get_attribute(pygame.GL_CONTEXT_MAJOR_VERSION) + ) + original_values.append( + pygame.display.gl_get_attribute(pygame.GL_CONTEXT_MINOR_VERSION) + ) + original_values.append(pygame.display.gl_get_attribute(pygame.GL_CONTEXT_FLAGS)) + original_values.append( + pygame.display.gl_get_attribute(pygame.GL_CONTEXT_PROFILE_MASK) + ) + original_values.append( + pygame.display.gl_get_attribute(pygame.GL_SHARE_WITH_CURRENT_CONTEXT) + ) + original_values.append( + pygame.display.gl_get_attribute(pygame.GL_FRAMEBUFFER_SRGB_CAPABLE) + ) + + # Setting the flags with values supposedly different from the original values + + # assign SDL1-supported values with gl_set_attribute + pygame.display.gl_set_attribute(pygame.GL_ALPHA_SIZE, 8) + pygame.display.gl_set_attribute(pygame.GL_DEPTH_SIZE, 24) + pygame.display.gl_set_attribute(pygame.GL_STENCIL_SIZE, 8) + pygame.display.gl_set_attribute(pygame.GL_ACCUM_RED_SIZE, 16) + pygame.display.gl_set_attribute(pygame.GL_ACCUM_GREEN_SIZE, 16) + pygame.display.gl_set_attribute(pygame.GL_ACCUM_BLUE_SIZE, 16) + pygame.display.gl_set_attribute(pygame.GL_ACCUM_ALPHA_SIZE, 16) + pygame.display.gl_set_attribute(pygame.GL_MULTISAMPLEBUFFERS, 1) + pygame.display.gl_set_attribute(pygame.GL_MULTISAMPLESAMPLES, 1) + pygame.display.gl_set_attribute(pygame.GL_STEREO, 0) + pygame.display.gl_set_attribute(pygame.GL_ACCELERATED_VISUAL, 0) + pygame.display.gl_set_attribute(pygame.GL_CONTEXT_MAJOR_VERSION, 1) + pygame.display.gl_set_attribute(pygame.GL_CONTEXT_MINOR_VERSION, 1) + pygame.display.gl_set_attribute(pygame.GL_CONTEXT_FLAGS, 0) + pygame.display.gl_set_attribute(pygame.GL_CONTEXT_PROFILE_MASK, 0) + pygame.display.gl_set_attribute(pygame.GL_SHARE_WITH_CURRENT_CONTEXT, 0) + pygame.display.gl_set_attribute(pygame.GL_FRAMEBUFFER_SRGB_CAPABLE, 0) + + # We create a list where we store the values that we set each flag to + set_values = [8, 24, 8, 16, 16, 16, 16, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0] + + # We create a list where we store the values after getting them + get_values = [] + + get_values.append(pygame.display.gl_get_attribute(pygame.GL_ALPHA_SIZE)) + get_values.append(pygame.display.gl_get_attribute(pygame.GL_DEPTH_SIZE)) + get_values.append(pygame.display.gl_get_attribute(pygame.GL_STENCIL_SIZE)) + get_values.append(pygame.display.gl_get_attribute(pygame.GL_ACCUM_RED_SIZE)) + get_values.append(pygame.display.gl_get_attribute(pygame.GL_ACCUM_GREEN_SIZE)) + get_values.append(pygame.display.gl_get_attribute(pygame.GL_ACCUM_BLUE_SIZE)) + get_values.append(pygame.display.gl_get_attribute(pygame.GL_ACCUM_ALPHA_SIZE)) + get_values.append(pygame.display.gl_get_attribute(pygame.GL_MULTISAMPLEBUFFERS)) + get_values.append(pygame.display.gl_get_attribute(pygame.GL_MULTISAMPLESAMPLES)) + get_values.append(pygame.display.gl_get_attribute(pygame.GL_STEREO)) + get_values.append(pygame.display.gl_get_attribute(pygame.GL_ACCELERATED_VISUAL)) + get_values.append( + pygame.display.gl_get_attribute(pygame.GL_CONTEXT_MAJOR_VERSION) + ) + get_values.append( + pygame.display.gl_get_attribute(pygame.GL_CONTEXT_MINOR_VERSION) + ) + get_values.append(pygame.display.gl_get_attribute(pygame.GL_CONTEXT_FLAGS)) + get_values.append( + pygame.display.gl_get_attribute(pygame.GL_CONTEXT_PROFILE_MASK) + ) + get_values.append( + pygame.display.gl_get_attribute(pygame.GL_SHARE_WITH_CURRENT_CONTEXT) + ) + get_values.append( + pygame.display.gl_get_attribute(pygame.GL_FRAMEBUFFER_SRGB_CAPABLE) + ) + + # We check to see if the values that we get correspond to the values that we set + # them to or to the original values. + for i in range(len(original_values)): + self.assertTrue( + (get_values[i] == original_values[i]) + or (get_values[i] == set_values[i]) + ) + + # test using non-flag argument + with self.assertRaises(TypeError): + pygame.display.gl_get_attribute("DUMMY") + + def todo_test_gl_set_attribute(self): + + # __doc__ (as of 2008-08-02) for pygame.display.gl_set_attribute: + + # pygame.display.gl_set_attribute(flag, value): return None + # request an opengl display attribute for the display mode + # + # When calling pygame.display.set_mode() with the pygame.OPENGL flag, + # Pygame automatically handles setting the OpenGL attributes like + # color and doublebuffering. OpenGL offers several other attributes + # you may want control over. Pass one of these attributes as the flag, + # and its appropriate value. This must be called before + # pygame.display.set_mode() + # + # The OPENGL flags are; + # GL_ALPHA_SIZE, GL_DEPTH_SIZE, GL_STENCIL_SIZE, GL_ACCUM_RED_SIZE, + # GL_ACCUM_GREEN_SIZE, GL_ACCUM_BLUE_SIZE, GL_ACCUM_ALPHA_SIZE, + # GL_MULTISAMPLEBUFFERS, GL_MULTISAMPLESAMPLES, GL_STEREO + + self.fail() + + @unittest.skipIf( + os.environ.get("SDL_VIDEODRIVER") in ["dummy", "android"], + "iconify is only supported on some video drivers/platforms", + ) + def test_iconify(self): + pygame.display.set_mode((640, 480)) + + self.assertEqual(pygame.display.get_active(), True) + + success = pygame.display.iconify() + + if success: + active_event = window_minimized_event = False + # make sure we cycle the event loop enough to get the display + # hidden. Test that both ACTIVEEVENT and WINDOWMINIMISED event appears + for _ in range(50): + time.sleep(0.01) + for event in pygame.event.get(): + if event.type == pygame.ACTIVEEVENT: + if not event.gain and event.state == pygame.APPACTIVE: + active_event = True + if event.type == pygame.WINDOWMINIMIZED: + window_minimized_event = True + + self.assertTrue(window_minimized_event) + self.assertTrue(active_event) + self.assertFalse(pygame.display.get_active()) + + else: + self.fail("Iconify not supported on this platform, please skip") + + def test_init(self): + """Ensures the module is initialized after init called.""" + # display.init() already called in setUp(), so quit and re-init + display.quit() + display.init() + + self.assertTrue(display.get_init()) + + def test_init__multiple(self): + """Ensures the module is initialized after multiple init calls.""" + display.init() + display.init() + + self.assertTrue(display.get_init()) + + def test_list_modes(self): + modes = pygame.display.list_modes(depth=0, flags=pygame.FULLSCREEN, display=0) + # modes == -1 means any mode is supported. + if modes != -1: + self.assertEqual(len(modes[0]), 2) + self.assertEqual(type(modes[0][0]), int) + + modes = pygame.display.list_modes() + if modes != -1: + self.assertEqual(len(modes[0]), 2) + self.assertEqual(type(modes[0][0]), int) + self.assertEqual(len(modes), len(set(modes))) + + modes = pygame.display.list_modes(depth=0, flags=0, display=0) + if modes != -1: + self.assertEqual(len(modes[0]), 2) + self.assertEqual(type(modes[0][0]), int) + + def test_mode_ok(self): + pygame.display.mode_ok((128, 128)) + modes = pygame.display.list_modes() + if modes != -1: + size = modes[0] + self.assertNotEqual(pygame.display.mode_ok(size), 0) + + pygame.display.mode_ok((128, 128), 0, 32) + pygame.display.mode_ok((128, 128), flags=0, depth=32, display=0) + + def test_mode_ok_fullscreen(self): + modes = pygame.display.list_modes() + if modes != -1: + size = modes[0] + self.assertNotEqual( + pygame.display.mode_ok(size, flags=pygame.FULLSCREEN), 0 + ) + + def test_mode_ok_scaled(self): + modes = pygame.display.list_modes() + if modes != -1: + size = modes[0] + self.assertNotEqual(pygame.display.mode_ok(size, flags=pygame.SCALED), 0) + + def test_get_num_displays(self): + self.assertGreater(pygame.display.get_num_displays(), 0) + + def test_quit(self): + """Ensures the module is not initialized after quit called.""" + display.quit() + + self.assertFalse(display.get_init()) + + def test_quit__multiple(self): + """Ensures the module is not initialized after multiple quit calls.""" + display.quit() + display.quit() + + self.assertFalse(display.get_init()) + + @unittest.skipIf( + os.environ.get("SDL_VIDEODRIVER") == "dummy", "Needs a not dummy videodriver" + ) + def test_set_gamma(self): + pygame.display.set_mode((1, 1)) + + gammas = [0.25, 0.5, 0.88, 1.0] + for gamma in gammas: + with self.subTest(gamma=gamma): + self.assertEqual(pygame.display.set_gamma(gamma), True) + + @unittest.skipIf( + os.environ.get("SDL_VIDEODRIVER") == "dummy", "Needs a not dummy videodriver" + ) + def test_set_gamma__tuple(self): + pygame.display.set_mode((1, 1)) + + gammas = [(0.5, 0.5, 0.5), (1.0, 1.0, 1.0), (0.25, 0.33, 0.44)] + for r, g, b in gammas: + with self.subTest(r=r, g=g, b=b): + self.assertEqual(pygame.display.set_gamma(r, g, b), True) + + @unittest.skipIf( + not hasattr(pygame.display, "set_gamma_ramp"), + "Not all systems and hardware support gamma ramps", + ) + def test_set_gamma_ramp(self): + + # __doc__ (as of 2008-08-02) for pygame.display.set_gamma_ramp: + + # change the hardware gamma ramps with a custom lookup + # pygame.display.set_gamma_ramp(red, green, blue): return bool + # set_gamma_ramp(red, green, blue): return bool + # + # Set the red, green, and blue gamma ramps with an explicit lookup + # table. Each argument should be sequence of 256 integers. The + # integers should range between 0 and 0xffff. Not all systems and + # hardware support gamma ramps, if the function succeeds it will + # return True. + # + pygame.display.set_mode((5, 5)) + r = list(range(256)) + g = [number + 256 for number in r] + b = [number + 256 for number in g] + isSupported = pygame.display.set_gamma_ramp(r, g, b) + if isSupported: + self.assertTrue(pygame.display.set_gamma_ramp(r, g, b)) + else: + self.assertFalse(pygame.display.set_gamma_ramp(r, g, b)) + + def test_set_mode_kwargs(self): + + pygame.display.set_mode(size=(1, 1), flags=0, depth=0, display=0) + + def test_set_mode_scaled(self): + surf = pygame.display.set_mode( + size=(1, 1), flags=pygame.SCALED, depth=0, display=0 + ) + winsize = pygame.display.get_window_size() + self.assertEqual( + winsize[0] % surf.get_size()[0], + 0, + "window width should be a multiple of the surface width", + ) + self.assertEqual( + winsize[1] % surf.get_size()[1], + 0, + "window height should be a multiple of the surface height", + ) + self.assertEqual( + winsize[0] / surf.get_size()[0], winsize[1] / surf.get_size()[1] + ) + + def test_set_mode_vector2(self): + pygame.display.set_mode(pygame.Vector2(1, 1)) + + def test_set_mode_unscaled(self): + """Ensures a window created with SCALED can become smaller.""" + # see https://github.com/pygame/pygame/issues/2327 + + screen = pygame.display.set_mode((300, 300), pygame.SCALED) + self.assertEqual(screen.get_size(), (300, 300)) + + screen = pygame.display.set_mode((200, 200)) + self.assertEqual(screen.get_size(), (200, 200)) + + def test_screensaver_support(self): + pygame.display.set_allow_screensaver(True) + self.assertTrue(pygame.display.get_allow_screensaver()) + pygame.display.set_allow_screensaver(False) + self.assertFalse(pygame.display.get_allow_screensaver()) + pygame.display.set_allow_screensaver() + self.assertTrue(pygame.display.get_allow_screensaver()) + + # the following test fails always with SDL2 + @unittest.skipIf(True, "set_palette() not supported in SDL2") + def test_set_palette(self): + with self.assertRaises(pygame.error): + palette = [1, 2, 3] + pygame.display.set_palette(palette) + pygame.display.set_mode((1024, 768), 0, 8) + palette = [] + self.assertIsNone(pygame.display.set_palette(palette)) + + with self.assertRaises(ValueError): + palette = 12 + pygame.display.set_palette(palette) + with self.assertRaises(TypeError): + palette = [[1, 2], [1, 2]] + pygame.display.set_palette(palette) + with self.assertRaises(TypeError): + palette = [[0, 0, 0, 0, 0]] + [[x, x, x, x, x] for x in range(1, 255)] + pygame.display.set_palette(palette) + with self.assertRaises(TypeError): + palette = "qwerty" + pygame.display.set_palette(palette) + with self.assertRaises(TypeError): + palette = [[123, 123, 123] * 10000] + pygame.display.set_palette(palette) + with self.assertRaises(TypeError): + palette = [1, 2, 3] + pygame.display.set_palette(palette) + + skip_list = ["dummy", "android"] + + @unittest.skipIf( + os.environ.get("SDL_VIDEODRIVER") in skip_list, + "requires the SDL_VIDEODRIVER to be non dummy", + ) + def test_toggle_fullscreen(self): + """Test for toggle fullscreen""" + + # try to toggle fullscreen with no active display + # this should result in an error + pygame.display.quit() + with self.assertRaises(pygame.error): + pygame.display.toggle_fullscreen() + + pygame.display.init() + width_height = (640, 480) + test_surf = pygame.display.set_mode(width_height) + + # try to toggle fullscreen + try: + pygame.display.toggle_fullscreen() + + except pygame.error: + self.fail() + + else: + # if toggle success, the width/height should be a + # value found in list_modes + if pygame.display.toggle_fullscreen() == 1: + boolean = ( + test_surf.get_width(), + test_surf.get_height(), + ) in pygame.display.list_modes( + depth=0, flags=pygame.FULLSCREEN, display=0 + ) + + self.assertEqual(boolean, True) + + # if not original width/height should be preserved + else: + self.assertEqual( + (test_surf.get_width(), test_surf.get_height()), width_height + ) + + +class DisplayUpdateTest(unittest.TestCase): + def question(self, qstr): + """this is used in the interactive subclass.""" + + def setUp(self): + display.init() + self.screen = pygame.display.set_mode((500, 500)) + self.screen.fill("black") + pygame.display.flip() + pygame.event.pump() # so mac updates + + def tearDown(self): + display.quit() + + def test_update_negative(self): + """takes rects with negative values.""" + self.screen.fill("green") + + r1 = pygame.Rect(0, 0, 100, 100) + pygame.display.update(r1) + + r2 = pygame.Rect(-10, 0, 100, 100) + pygame.display.update(r2) + + r3 = pygame.Rect(-10, 0, -100, -100) + pygame.display.update(r3) + + self.question("Is the screen green in (0, 0, 100, 100)?") + + def test_update_sequence(self): + """only updates the part of the display given by the rects.""" + self.screen.fill("green") + rects = [ + pygame.Rect(0, 0, 100, 100), + pygame.Rect(100, 0, 100, 100), + pygame.Rect(200, 0, 100, 100), + pygame.Rect(300, 300, 100, 100), + ] + pygame.display.update(rects) + pygame.event.pump() # so mac updates + + self.question(f"Is the screen green in {rects}?") + + def test_update_none_skipped(self): + """None is skipped inside sequences.""" + self.screen.fill("green") + rects = ( + None, + pygame.Rect(100, 0, 100, 100), + None, + pygame.Rect(200, 0, 100, 100), + pygame.Rect(300, 300, 100, 100), + ) + pygame.display.update(rects) + pygame.event.pump() # so mac updates + + self.question(f"Is the screen green in {rects}?") + + def test_update_none(self): + """does NOT update the display.""" + self.screen.fill("green") + pygame.display.update(None) + pygame.event.pump() # so mac updates + self.question(f"Is the screen black and NOT green?") + + def test_update_no_args(self): + """does NOT update the display.""" + self.screen.fill("green") + pygame.display.update() + pygame.event.pump() # so mac updates + self.question(f"Is the WHOLE screen green?") + + def test_update_args(self): + """updates the display using the args as a rect.""" + self.screen.fill("green") + pygame.display.update(100, 100, 100, 100) + pygame.event.pump() # so mac updates + self.question("Is the screen green in (100, 100, 100, 100)?") + + def test_update_incorrect_args(self): + """raises a ValueError when inputs are wrong.""" + + with self.assertRaises(ValueError): + pygame.display.update(100, "asdf", 100, 100) + + with self.assertRaises(ValueError): + pygame.display.update([100, "asdf", 100, 100]) + + def test_update_no_init(self): + """raises a pygame.error.""" + + pygame.display.quit() + with self.assertRaises(pygame.error): + pygame.display.update() + + +class DisplayUpdateInteractiveTest(DisplayUpdateTest): + """Because we want these tests to run as interactive and not interactive.""" + + __tags__ = ["interactive"] + + def question(self, qstr): + """since this is the interactive sublcass we ask a question.""" + question(qstr) + + +class DisplayInteractiveTest(unittest.TestCase): + + __tags__ = ["interactive"] + + def test_set_icon_interactive(self): + + os.environ["SDL_VIDEO_WINDOW_POS"] = "100,250" + pygame.display.quit() + pygame.display.init() + + test_icon = pygame.Surface((32, 32)) + test_icon.fill((255, 0, 0)) + + pygame.display.set_icon(test_icon) + screen = pygame.display.set_mode((400, 100)) + pygame.display.set_caption("Is the window icon a red square?") + + response = question("Is the display icon red square?") + + self.assertTrue(response) + pygame.display.quit() + + def test_set_gamma_ramp(self): + + os.environ["SDL_VIDEO_WINDOW_POS"] = "100,250" + pygame.display.quit() + pygame.display.init() + + screen = pygame.display.set_mode((400, 100)) + screen.fill((100, 100, 100)) + + blue_ramp = [x * 256 for x in range(0, 256)] + blue_ramp[100] = 150 * 256 # Can't tint too far or gamma ramps fail + normal_ramp = [x * 256 for x in range(0, 256)] + # test to see if this platform supports gamma ramps + gamma_success = False + if pygame.display.set_gamma_ramp(normal_ramp, normal_ramp, blue_ramp): + pygame.display.update() + gamma_success = True + + if gamma_success: + response = question("Is the window background tinted blue?") + self.assertTrue(response) + # restore normal ramp + pygame.display.set_gamma_ramp(normal_ramp, normal_ramp, normal_ramp) + + pygame.display.quit() + + +@unittest.skipIf( + os.environ.get("SDL_VIDEODRIVER") == "dummy", + 'OpenGL requires a non-"dummy" SDL_VIDEODRIVER', +) +class DisplayOpenGLTest(unittest.TestCase): + def test_screen_size_opengl(self): + """returns a surface with the same size requested. + |tags:display,slow,opengl| + """ + pygame.display.init() + screen = pygame.display.set_mode((640, 480), pygame.OPENGL) + self.assertEqual((640, 480), screen.get_size()) + + +class X11CrashTest(unittest.TestCase): + def test_x11_set_mode_crash_gh1654(self): + # Test for https://github.com/pygame/pygame/issues/1654 + # If unfixed, this will trip a segmentation fault + pygame.display.init() + pygame.display.quit() + screen = pygame.display.set_mode((640, 480), 0) + self.assertEqual((640, 480), screen.get_size()) + + +if __name__ == "__main__": + unittest.main() diff --git a/venv/Lib/site-packages/pygame/tests/docs_test.py b/venv/Lib/site-packages/pygame/tests/docs_test.py new file mode 100644 index 0000000..de021a8 --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/docs_test.py @@ -0,0 +1,35 @@ +import os +import subprocess +import sys +import unittest + + +class DocsIncludedTest(unittest.TestCase): + def test_doc_import_works(self): + from pygame.docs.__main__ import has_local_docs, open_docs + + @unittest.skipIf("CI" not in os.environ, "Docs not required for local builds") + def test_docs_included(self): + from pygame.docs.__main__ import has_local_docs + + self.assertTrue(has_local_docs()) + + @unittest.skipIf("CI" not in os.environ, "Docs not required for local builds") + def test_docs_command(self): + try: + subprocess.run( + [sys.executable, "-m", "pygame.docs"], + timeout=5, + # check ensures an exception is raised when the process fails + check=True, + # pipe stdout/stderr so that they don't clutter main stdout + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + ) + except subprocess.TimeoutExpired: + # timeout errors are not an issue + pass + + +if __name__ == "__main__": + unittest.main() diff --git a/venv/Lib/site-packages/pygame/tests/draw_test.py b/venv/Lib/site-packages/pygame/tests/draw_test.py new file mode 100644 index 0000000..d876060 --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/draw_test.py @@ -0,0 +1,6563 @@ +import math +import unittest +import sys +import warnings + +import pygame +from pygame import draw +from pygame import draw_py +from pygame.locals import SRCALPHA +from pygame.tests import test_utils +from pygame.math import Vector2 + + +RED = BG_RED = pygame.Color("red") +GREEN = FG_GREEN = pygame.Color("green") + +# Clockwise from the top left corner and ending with the center point. +RECT_POSITION_ATTRIBUTES = ( + "topleft", + "midtop", + "topright", + "midright", + "bottomright", + "midbottom", + "bottomleft", + "midleft", + "center", +) + + +def get_border_values(surface, width, height): + """Returns a list containing lists with the values of the surface's + borders. + """ + border_top = [surface.get_at((x, 0)) for x in range(width)] + border_left = [surface.get_at((0, y)) for y in range(height)] + border_right = [surface.get_at((width - 1, y)) for y in range(height)] + border_bottom = [surface.get_at((x, height - 1)) for x in range(width)] + + return [border_top, border_left, border_right, border_bottom] + + +def corners(surface): + """Returns a tuple with the corner positions of the given surface. + + Clockwise from the top left corner. + """ + width, height = surface.get_size() + return ((0, 0), (width - 1, 0), (width - 1, height - 1), (0, height - 1)) + + +def rect_corners_mids_and_center(rect): + """Returns a tuple with each corner, mid, and the center for a given rect. + + Clockwise from the top left corner and ending with the center point. + """ + return ( + rect.topleft, + rect.midtop, + rect.topright, + rect.midright, + rect.bottomright, + rect.midbottom, + rect.bottomleft, + rect.midleft, + rect.center, + ) + + +def border_pos_and_color(surface): + """Yields each border position and its color for a given surface. + + Clockwise from the top left corner. + """ + width, height = surface.get_size() + right, bottom = width - 1, height - 1 + + # Top edge. + for x in range(width): + pos = (x, 0) + yield pos, surface.get_at(pos) + + # Right edge. + # Top right done in top edge loop. + for y in range(1, height): + pos = (right, y) + yield pos, surface.get_at(pos) + + # Bottom edge. + # Bottom right done in right edge loop. + for x in range(right - 1, -1, -1): + pos = (x, bottom) + yield pos, surface.get_at(pos) + + # Left edge. + # Bottom left done in bottom edge loop. Top left done in top edge loop. + for y in range(bottom - 1, 0, -1): + pos = (0, y) + yield pos, surface.get_at(pos) + + +def get_color_points(surface, color, bounds_rect=None, match_color=True): + """Get all the points of a given color on the surface within the given + bounds. + + If bounds_rect is None the full surface is checked. + If match_color is True, all points matching the color are returned, + otherwise all points not matching the color are returned. + """ + get_at = surface.get_at # For possible speed up. + + if bounds_rect is None: + x_range = range(surface.get_width()) + y_range = range(surface.get_height()) + else: + x_range = range(bounds_rect.left, bounds_rect.right) + y_range = range(bounds_rect.top, bounds_rect.bottom) + + surface.lock() # For possible speed up. + + if match_color: + pts = [(x, y) for x in x_range for y in y_range if get_at((x, y)) == color] + else: + pts = [(x, y) for x in x_range for y in y_range if get_at((x, y)) != color] + + surface.unlock() + return pts + + +def create_bounding_rect(surface, surf_color, default_pos): + """Create a rect to bound all the pixels that don't match surf_color. + + The default_pos parameter is used to position the bounding rect for the + case where all pixels match the surf_color. + """ + width, height = surface.get_clip().size + xmin, ymin = width, height + xmax, ymax = -1, -1 + get_at = surface.get_at # For possible speed up. + + surface.lock() # For possible speed up. + + for y in range(height): + for x in range(width): + if get_at((x, y)) != surf_color: + xmin = min(x, xmin) + xmax = max(x, xmax) + ymin = min(y, ymin) + ymax = max(y, ymax) + + surface.unlock() + + if -1 == xmax: + # No points means a 0 sized rect positioned at default_pos. + return pygame.Rect(default_pos, (0, 0)) + return pygame.Rect((xmin, ymin), (xmax - xmin + 1, ymax - ymin + 1)) + + +class InvalidBool(object): + """To help test invalid bool values.""" + + __nonzero__ = None + __bool__ = None + + +class DrawTestCase(unittest.TestCase): + """Base class to test draw module functions.""" + + draw_rect = staticmethod(draw.rect) + draw_polygon = staticmethod(draw.polygon) + draw_circle = staticmethod(draw.circle) + draw_ellipse = staticmethod(draw.ellipse) + draw_arc = staticmethod(draw.arc) + draw_line = staticmethod(draw.line) + draw_lines = staticmethod(draw.lines) + draw_aaline = staticmethod(draw.aaline) + draw_aalines = staticmethod(draw.aalines) + + +class PythonDrawTestCase(unittest.TestCase): + """Base class to test draw_py module functions.""" + + # draw_py is currently missing some functions. + # draw_rect = staticmethod(draw_py.draw_rect) + draw_polygon = staticmethod(draw_py.draw_polygon) + # draw_circle = staticmethod(draw_py.draw_circle) + # draw_ellipse = staticmethod(draw_py.draw_ellipse) + # draw_arc = staticmethod(draw_py.draw_arc) + draw_line = staticmethod(draw_py.draw_line) + draw_lines = staticmethod(draw_py.draw_lines) + draw_aaline = staticmethod(draw_py.draw_aaline) + draw_aalines = staticmethod(draw_py.draw_aalines) + + +### Ellipse Testing ########################################################### + + +class DrawEllipseMixin(object): + """Mixin tests for drawing ellipses. + + This class contains all the general ellipse drawing tests. + """ + + def test_ellipse__args(self): + """Ensures draw ellipse accepts the correct args.""" + bounds_rect = self.draw_ellipse( + pygame.Surface((3, 3)), (0, 10, 0, 50), pygame.Rect((0, 0), (3, 2)), 1 + ) + + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_ellipse__args_without_width(self): + """Ensures draw ellipse accepts the args without a width.""" + bounds_rect = self.draw_ellipse( + pygame.Surface((2, 2)), (1, 1, 1, 99), pygame.Rect((1, 1), (1, 1)) + ) + + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_ellipse__args_with_negative_width(self): + """Ensures draw ellipse accepts the args with negative width.""" + bounds_rect = self.draw_ellipse( + pygame.Surface((3, 3)), (0, 10, 0, 50), pygame.Rect((2, 3), (3, 2)), -1 + ) + + self.assertIsInstance(bounds_rect, pygame.Rect) + self.assertEqual(bounds_rect, pygame.Rect(2, 3, 0, 0)) + + def test_ellipse__args_with_width_gt_radius(self): + """Ensures draw ellipse accepts the args with + width > rect.w // 2 and width > rect.h // 2. + """ + rect = pygame.Rect((0, 0), (4, 4)) + bounds_rect = self.draw_ellipse( + pygame.Surface((3, 3)), (0, 10, 0, 50), rect, rect.w // 2 + 1 + ) + + self.assertIsInstance(bounds_rect, pygame.Rect) + + bounds_rect = self.draw_ellipse( + pygame.Surface((3, 3)), (0, 10, 0, 50), rect, rect.h // 2 + 1 + ) + + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_ellipse__kwargs(self): + """Ensures draw ellipse accepts the correct kwargs + with and without a width arg. + """ + kwargs_list = [ + { + "surface": pygame.Surface((4, 4)), + "color": pygame.Color("yellow"), + "rect": pygame.Rect((0, 0), (3, 2)), + "width": 1, + }, + { + "surface": pygame.Surface((2, 1)), + "color": (0, 10, 20), + "rect": (0, 0, 1, 1), + }, + ] + + for kwargs in kwargs_list: + bounds_rect = self.draw_ellipse(**kwargs) + + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_ellipse__kwargs_order_independent(self): + """Ensures draw ellipse's kwargs are not order dependent.""" + bounds_rect = self.draw_ellipse( + color=(1, 2, 3), + surface=pygame.Surface((3, 2)), + width=0, + rect=pygame.Rect((1, 0), (1, 1)), + ) + + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_ellipse__args_missing(self): + """Ensures draw ellipse detects any missing required args.""" + surface = pygame.Surface((1, 1)) + + with self.assertRaises(TypeError): + bounds_rect = self.draw_ellipse(surface, pygame.Color("red")) + + with self.assertRaises(TypeError): + bounds_rect = self.draw_ellipse(surface) + + with self.assertRaises(TypeError): + bounds_rect = self.draw_ellipse() + + def test_ellipse__kwargs_missing(self): + """Ensures draw ellipse detects any missing required kwargs.""" + kwargs = { + "surface": pygame.Surface((1, 2)), + "color": pygame.Color("red"), + "rect": pygame.Rect((1, 0), (2, 2)), + "width": 2, + } + + for name in ("rect", "color", "surface"): + invalid_kwargs = dict(kwargs) + invalid_kwargs.pop(name) # Pop from a copy. + + with self.assertRaises(TypeError): + bounds_rect = self.draw_ellipse(**invalid_kwargs) + + def test_ellipse__arg_invalid_types(self): + """Ensures draw ellipse detects invalid arg types.""" + surface = pygame.Surface((2, 2)) + color = pygame.Color("blue") + rect = pygame.Rect((1, 1), (1, 1)) + + with self.assertRaises(TypeError): + # Invalid width. + bounds_rect = self.draw_ellipse(surface, color, rect, "1") + + with self.assertRaises(TypeError): + # Invalid rect. + bounds_rect = self.draw_ellipse(surface, color, (1, 2, 3, 4, 5), 1) + + with self.assertRaises(TypeError): + # Invalid color. + bounds_rect = self.draw_ellipse(surface, 2.3, rect, 0) + + with self.assertRaises(TypeError): + # Invalid surface. + bounds_rect = self.draw_ellipse(rect, color, rect, 2) + + def test_ellipse__kwarg_invalid_types(self): + """Ensures draw ellipse detects invalid kwarg types.""" + surface = pygame.Surface((3, 3)) + color = pygame.Color("green") + rect = pygame.Rect((0, 1), (1, 1)) + kwargs_list = [ + { + "surface": pygame.Surface, # Invalid surface. + "color": color, + "rect": rect, + "width": 1, + }, + { + "surface": surface, + "color": 2.3, # Invalid color. + "rect": rect, + "width": 1, + }, + { + "surface": surface, + "color": color, + "rect": (0, 0, 0), # Invalid rect. + "width": 1, + }, + {"surface": surface, "color": color, "rect": rect, "width": 1.1}, + ] # Invalid width. + + for kwargs in kwargs_list: + with self.assertRaises(TypeError): + bounds_rect = self.draw_ellipse(**kwargs) + + def test_ellipse__kwarg_invalid_name(self): + """Ensures draw ellipse detects invalid kwarg names.""" + surface = pygame.Surface((2, 3)) + color = pygame.Color("cyan") + rect = pygame.Rect((0, 1), (2, 2)) + kwargs_list = [ + { + "surface": surface, + "color": color, + "rect": rect, + "width": 1, + "invalid": 1, + }, + {"surface": surface, "color": color, "rect": rect, "invalid": 1}, + ] + + for kwargs in kwargs_list: + with self.assertRaises(TypeError): + bounds_rect = self.draw_ellipse(**kwargs) + + def test_ellipse__args_and_kwargs(self): + """Ensures draw ellipse accepts a combination of args/kwargs""" + surface = pygame.Surface((3, 1)) + color = (255, 255, 0, 0) + rect = pygame.Rect((1, 0), (2, 1)) + width = 0 + kwargs = {"surface": surface, "color": color, "rect": rect, "width": width} + + for name in ("surface", "color", "rect", "width"): + kwargs.pop(name) + + if "surface" == name: + bounds_rect = self.draw_ellipse(surface, **kwargs) + elif "color" == name: + bounds_rect = self.draw_ellipse(surface, color, **kwargs) + elif "rect" == name: + bounds_rect = self.draw_ellipse(surface, color, rect, **kwargs) + else: + bounds_rect = self.draw_ellipse(surface, color, rect, width, **kwargs) + + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_ellipse__valid_width_values(self): + """Ensures draw ellipse accepts different width values.""" + pos = (1, 1) + surface_color = pygame.Color("white") + surface = pygame.Surface((3, 4)) + color = (10, 20, 30, 255) + kwargs = { + "surface": surface, + "color": color, + "rect": pygame.Rect(pos, (3, 2)), + "width": None, + } + + for width in (-1000, -10, -1, 0, 1, 10, 1000): + surface.fill(surface_color) # Clear for each test. + kwargs["width"] = width + expected_color = color if width >= 0 else surface_color + + bounds_rect = self.draw_ellipse(**kwargs) + + self.assertEqual(surface.get_at(pos), expected_color) + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_ellipse__valid_rect_formats(self): + """Ensures draw ellipse accepts different rect formats.""" + pos = (1, 1) + expected_color = pygame.Color("red") + surface_color = pygame.Color("black") + surface = pygame.Surface((4, 4)) + kwargs = {"surface": surface, "color": expected_color, "rect": None, "width": 0} + rects = (pygame.Rect(pos, (1, 3)), (pos, (2, 1)), (pos[0], pos[1], 1, 1)) + + for rect in rects: + surface.fill(surface_color) # Clear for each test. + kwargs["rect"] = rect + + bounds_rect = self.draw_ellipse(**kwargs) + + self.assertEqual(surface.get_at(pos), expected_color) + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_ellipse__valid_color_formats(self): + """Ensures draw ellipse accepts different color formats.""" + pos = (1, 1) + green_color = pygame.Color("green") + surface_color = pygame.Color("black") + surface = pygame.Surface((3, 4)) + kwargs = { + "surface": surface, + "color": None, + "rect": pygame.Rect(pos, (1, 2)), + "width": 0, + } + reds = ( + (0, 255, 0), + (0, 255, 0, 255), + surface.map_rgb(green_color), + green_color, + ) + + for color in reds: + surface.fill(surface_color) # Clear for each test. + kwargs["color"] = color + + if isinstance(color, int): + expected_color = surface.unmap_rgb(color) + else: + expected_color = green_color + + bounds_rect = self.draw_ellipse(**kwargs) + + self.assertEqual(surface.get_at(pos), expected_color) + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_ellipse__invalid_color_formats(self): + """Ensures draw ellipse handles invalid color formats correctly.""" + pos = (1, 1) + surface = pygame.Surface((4, 3)) + kwargs = { + "surface": surface, + "color": None, + "rect": pygame.Rect(pos, (2, 2)), + "width": 1, + } + + for expected_color in (2.3, surface): + kwargs["color"] = expected_color + + with self.assertRaises(TypeError): + bounds_rect = self.draw_ellipse(**kwargs) + + def test_ellipse(self): + """Tests ellipses of differing sizes on surfaces of differing sizes. + + Checks if the number of sides touching the border of the surface is + correct. + """ + left_top = [(0, 0), (1, 0), (0, 1), (1, 1)] + sizes = [(4, 4), (5, 4), (4, 5), (5, 5)] + color = (1, 13, 24, 255) + + def same_size(width, height, border_width): + """Test for ellipses with the same size as the surface.""" + surface = pygame.Surface((width, height)) + + self.draw_ellipse(surface, color, (0, 0, width, height), border_width) + + # For each of the four borders check if it contains the color + borders = get_border_values(surface, width, height) + for border in borders: + self.assertTrue(color in border) + + def not_same_size(width, height, border_width, left, top): + """Test for ellipses that aren't the same size as the surface.""" + surface = pygame.Surface((width, height)) + + self.draw_ellipse( + surface, color, (left, top, width - 1, height - 1), border_width + ) + + borders = get_border_values(surface, width, height) + + # Check if two sides of the ellipse are touching the border + sides_touching = [color in border for border in borders].count(True) + self.assertEqual(sides_touching, 2) + + for width, height in sizes: + for border_width in (0, 1): + same_size(width, height, border_width) + for left, top in left_top: + not_same_size(width, height, border_width, left, top) + + def test_ellipse__big_ellipse(self): + """Test for big ellipse that could overflow in algorithm""" + width = 1025 + height = 1025 + border = 1 + x_value_test = int(0.4 * height) + y_value_test = int(0.4 * height) + surface = pygame.Surface((width, height)) + + self.draw_ellipse(surface, (255, 0, 0), (0, 0, width, height), border) + colored_pixels = 0 + for y in range(height): + if surface.get_at((x_value_test, y)) == (255, 0, 0): + colored_pixels += 1 + for x in range(width): + if surface.get_at((x, y_value_test)) == (255, 0, 0): + colored_pixels += 1 + self.assertEqual(colored_pixels, border * 4) + + def test_ellipse__thick_line(self): + """Ensures a thick lined ellipse is drawn correctly.""" + ellipse_color = pygame.Color("yellow") + surface_color = pygame.Color("black") + surface = pygame.Surface((40, 40)) + rect = pygame.Rect((0, 0), (31, 23)) + rect.center = surface.get_rect().center + + # As the lines get thicker the internals of the ellipse are not + # cleanly defined. So only test up to a few thicknesses before the + # maximum thickness. + for thickness in range(1, min(*rect.size) // 2 - 2): + surface.fill(surface_color) # Clear for each test. + + self.draw_ellipse(surface, ellipse_color, rect, thickness) + + surface.lock() # For possible speed up. + + # Check vertical thickness on the ellipse's top. + x = rect.centerx + y_start = rect.top + y_end = rect.top + thickness - 1 + + for y in range(y_start, y_end + 1): + self.assertEqual(surface.get_at((x, y)), ellipse_color, thickness) + + # Check pixels above and below this line. + self.assertEqual(surface.get_at((x, y_start - 1)), surface_color, thickness) + self.assertEqual(surface.get_at((x, y_end + 1)), surface_color, thickness) + + # Check vertical thickness on the ellipse's bottom. + x = rect.centerx + y_start = rect.bottom - thickness + y_end = rect.bottom - 1 + + for y in range(y_start, y_end + 1): + self.assertEqual(surface.get_at((x, y)), ellipse_color, thickness) + + # Check pixels above and below this line. + self.assertEqual(surface.get_at((x, y_start - 1)), surface_color, thickness) + self.assertEqual(surface.get_at((x, y_end + 1)), surface_color, thickness) + + # Check horizontal thickness on the ellipse's left. + x_start = rect.left + x_end = rect.left + thickness - 1 + y = rect.centery + + for x in range(x_start, x_end + 1): + self.assertEqual(surface.get_at((x, y)), ellipse_color, thickness) + + # Check pixels to the left and right of this line. + self.assertEqual(surface.get_at((x_start - 1, y)), surface_color, thickness) + self.assertEqual(surface.get_at((x_end + 1, y)), surface_color, thickness) + + # Check horizontal thickness on the ellipse's right. + x_start = rect.right - thickness + x_end = rect.right - 1 + y = rect.centery + + for x in range(x_start, x_end + 1): + self.assertEqual(surface.get_at((x, y)), ellipse_color, thickness) + + # Check pixels to the left and right of this line. + self.assertEqual(surface.get_at((x_start - 1, y)), surface_color, thickness) + self.assertEqual(surface.get_at((x_end + 1, y)), surface_color, thickness) + + surface.unlock() + + def test_ellipse__no_holes(self): + width = 80 + height = 70 + surface = pygame.Surface((width + 1, height)) + rect = pygame.Rect(0, 0, width, height) + for thickness in range(1, 37, 5): + surface.fill("BLACK") + self.draw_ellipse(surface, "RED", rect, thickness) + for y in range(height): + number_of_changes = 0 + drawn_pixel = False + for x in range(width + 1): + if ( + not drawn_pixel + and surface.get_at((x, y)) == pygame.Color("RED") + or drawn_pixel + and surface.get_at((x, y)) == pygame.Color("BLACK") + ): + drawn_pixel = not drawn_pixel + number_of_changes += 1 + if y < thickness or y > height - thickness - 1: + self.assertEqual(number_of_changes, 2) + else: + self.assertEqual(number_of_changes, 4) + + def test_ellipse__max_width(self): + """Ensures an ellipse with max width (and greater) is drawn correctly.""" + ellipse_color = pygame.Color("yellow") + surface_color = pygame.Color("black") + surface = pygame.Surface((40, 40)) + rect = pygame.Rect((0, 0), (31, 21)) + rect.center = surface.get_rect().center + max_thickness = (min(*rect.size) + 1) // 2 + + for thickness in range(max_thickness, max_thickness + 3): + surface.fill(surface_color) # Clear for each test. + + self.draw_ellipse(surface, ellipse_color, rect, thickness) + + surface.lock() # For possible speed up. + + # Check vertical thickness. + for y in range(rect.top, rect.bottom): + self.assertEqual(surface.get_at((rect.centerx, y)), ellipse_color) + + # Check horizontal thickness. + for x in range(rect.left, rect.right): + self.assertEqual(surface.get_at((x, rect.centery)), ellipse_color) + + # Check pixels above and below ellipse. + self.assertEqual( + surface.get_at((rect.centerx, rect.top - 1)), surface_color + ) + self.assertEqual( + surface.get_at((rect.centerx, rect.bottom + 1)), surface_color + ) + + # Check pixels to the left and right of the ellipse. + self.assertEqual( + surface.get_at((rect.left - 1, rect.centery)), surface_color + ) + self.assertEqual( + surface.get_at((rect.right + 1, rect.centery)), surface_color + ) + + surface.unlock() + + def _check_1_pixel_sized_ellipse( + self, surface, collide_rect, surface_color, ellipse_color + ): + # Helper method to check the surface for 1 pixel wide and/or high + # ellipses. + surf_w, surf_h = surface.get_size() + + surface.lock() # For possible speed up. + + for pos in ((x, y) for y in range(surf_h) for x in range(surf_w)): + # Since the ellipse is just a line we can use a rect to help find + # where it is expected to be drawn. + if collide_rect.collidepoint(pos): + expected_color = ellipse_color + else: + expected_color = surface_color + + self.assertEqual( + surface.get_at(pos), + expected_color, + "collide_rect={}, pos={}".format(collide_rect, pos), + ) + + surface.unlock() + + def test_ellipse__1_pixel_width(self): + """Ensures an ellipse with a width of 1 is drawn correctly. + + An ellipse with a width of 1 pixel is a vertical line. + """ + ellipse_color = pygame.Color("red") + surface_color = pygame.Color("black") + surf_w, surf_h = 10, 20 + + surface = pygame.Surface((surf_w, surf_h)) + rect = pygame.Rect((0, 0), (1, 0)) + collide_rect = rect.copy() + + # Calculate some positions. + off_left = -1 + off_right = surf_w + off_bottom = surf_h + center_x = surf_w // 2 + center_y = surf_h // 2 + + # Test some even and odd heights. + for ellipse_h in range(6, 10): + collide_rect.h = ellipse_h + rect.h = ellipse_h + + # Calculate some variable positions. + off_top = -(ellipse_h + 1) + half_off_top = -(ellipse_h // 2) + half_off_bottom = surf_h - (ellipse_h // 2) + + # Draw the ellipse in different positions: fully on-surface, + # partially off-surface, and fully off-surface. + positions = ( + (off_left, off_top), + (off_left, half_off_top), + (off_left, center_y), + (off_left, half_off_bottom), + (off_left, off_bottom), + (center_x, off_top), + (center_x, half_off_top), + (center_x, center_y), + (center_x, half_off_bottom), + (center_x, off_bottom), + (off_right, off_top), + (off_right, half_off_top), + (off_right, center_y), + (off_right, half_off_bottom), + (off_right, off_bottom), + ) + + for rect_pos in positions: + surface.fill(surface_color) # Clear before each draw. + rect.topleft = rect_pos + collide_rect.topleft = rect_pos + + self.draw_ellipse(surface, ellipse_color, rect) + + self._check_1_pixel_sized_ellipse( + surface, collide_rect, surface_color, ellipse_color + ) + + def test_ellipse__1_pixel_width_spanning_surface(self): + """Ensures an ellipse with a width of 1 is drawn correctly + when spanning the height of the surface. + + An ellipse with a width of 1 pixel is a vertical line. + """ + ellipse_color = pygame.Color("red") + surface_color = pygame.Color("black") + surf_w, surf_h = 10, 20 + + surface = pygame.Surface((surf_w, surf_h)) + rect = pygame.Rect((0, 0), (1, surf_h + 2)) # Longer than the surface. + + # Draw the ellipse in different positions: on-surface and off-surface. + positions = ( + (-1, -1), # (off_left, off_top) + (0, -1), # (left_edge, off_top) + (surf_w // 2, -1), # (center_x, off_top) + (surf_w - 1, -1), # (right_edge, off_top) + (surf_w, -1), + ) # (off_right, off_top) + + for rect_pos in positions: + surface.fill(surface_color) # Clear before each draw. + rect.topleft = rect_pos + + self.draw_ellipse(surface, ellipse_color, rect) + + self._check_1_pixel_sized_ellipse( + surface, rect, surface_color, ellipse_color + ) + + def test_ellipse__1_pixel_height(self): + """Ensures an ellipse with a height of 1 is drawn correctly. + + An ellipse with a height of 1 pixel is a horizontal line. + """ + ellipse_color = pygame.Color("red") + surface_color = pygame.Color("black") + surf_w, surf_h = 20, 10 + + surface = pygame.Surface((surf_w, surf_h)) + rect = pygame.Rect((0, 0), (0, 1)) + collide_rect = rect.copy() + + # Calculate some positions. + off_right = surf_w + off_top = -1 + off_bottom = surf_h + center_x = surf_w // 2 + center_y = surf_h // 2 + + # Test some even and odd widths. + for ellipse_w in range(6, 10): + collide_rect.w = ellipse_w + rect.w = ellipse_w + + # Calculate some variable positions. + off_left = -(ellipse_w + 1) + half_off_left = -(ellipse_w // 2) + half_off_right = surf_w - (ellipse_w // 2) + + # Draw the ellipse in different positions: fully on-surface, + # partially off-surface, and fully off-surface. + positions = ( + (off_left, off_top), + (half_off_left, off_top), + (center_x, off_top), + (half_off_right, off_top), + (off_right, off_top), + (off_left, center_y), + (half_off_left, center_y), + (center_x, center_y), + (half_off_right, center_y), + (off_right, center_y), + (off_left, off_bottom), + (half_off_left, off_bottom), + (center_x, off_bottom), + (half_off_right, off_bottom), + (off_right, off_bottom), + ) + + for rect_pos in positions: + surface.fill(surface_color) # Clear before each draw. + rect.topleft = rect_pos + collide_rect.topleft = rect_pos + + self.draw_ellipse(surface, ellipse_color, rect) + + self._check_1_pixel_sized_ellipse( + surface, collide_rect, surface_color, ellipse_color + ) + + def test_ellipse__1_pixel_height_spanning_surface(self): + """Ensures an ellipse with a height of 1 is drawn correctly + when spanning the width of the surface. + + An ellipse with a height of 1 pixel is a horizontal line. + """ + ellipse_color = pygame.Color("red") + surface_color = pygame.Color("black") + surf_w, surf_h = 20, 10 + + surface = pygame.Surface((surf_w, surf_h)) + rect = pygame.Rect((0, 0), (surf_w + 2, 1)) # Wider than the surface. + + # Draw the ellipse in different positions: on-surface and off-surface. + positions = ( + (-1, -1), # (off_left, off_top) + (-1, 0), # (off_left, top_edge) + (-1, surf_h // 2), # (off_left, center_y) + (-1, surf_h - 1), # (off_left, bottom_edge) + (-1, surf_h), + ) # (off_left, off_bottom) + + for rect_pos in positions: + surface.fill(surface_color) # Clear before each draw. + rect.topleft = rect_pos + + self.draw_ellipse(surface, ellipse_color, rect) + + self._check_1_pixel_sized_ellipse( + surface, rect, surface_color, ellipse_color + ) + + def test_ellipse__1_pixel_width_and_height(self): + """Ensures an ellipse with a width and height of 1 is drawn correctly. + + An ellipse with a width and height of 1 pixel is a single pixel. + """ + ellipse_color = pygame.Color("red") + surface_color = pygame.Color("black") + surf_w, surf_h = 10, 10 + + surface = pygame.Surface((surf_w, surf_h)) + rect = pygame.Rect((0, 0), (1, 1)) + + # Calculate some positions. + off_left = -1 + off_right = surf_w + off_top = -1 + off_bottom = surf_h + left_edge = 0 + right_edge = surf_w - 1 + top_edge = 0 + bottom_edge = surf_h - 1 + center_x = surf_w // 2 + center_y = surf_h // 2 + + # Draw the ellipse in different positions: center surface, + # top/bottom/left/right edges, and off-surface. + positions = ( + (off_left, off_top), + (off_left, top_edge), + (off_left, center_y), + (off_left, bottom_edge), + (off_left, off_bottom), + (left_edge, off_top), + (left_edge, top_edge), + (left_edge, center_y), + (left_edge, bottom_edge), + (left_edge, off_bottom), + (center_x, off_top), + (center_x, top_edge), + (center_x, center_y), + (center_x, bottom_edge), + (center_x, off_bottom), + (right_edge, off_top), + (right_edge, top_edge), + (right_edge, center_y), + (right_edge, bottom_edge), + (right_edge, off_bottom), + (off_right, off_top), + (off_right, top_edge), + (off_right, center_y), + (off_right, bottom_edge), + (off_right, off_bottom), + ) + + for rect_pos in positions: + surface.fill(surface_color) # Clear before each draw. + rect.topleft = rect_pos + + self.draw_ellipse(surface, ellipse_color, rect) + + self._check_1_pixel_sized_ellipse( + surface, rect, surface_color, ellipse_color + ) + + def test_ellipse__bounding_rect(self): + """Ensures draw ellipse returns the correct bounding rect. + + Tests ellipses on and off the surface and a range of width/thickness + values. + """ + ellipse_color = pygame.Color("red") + surf_color = pygame.Color("black") + min_width = min_height = 5 + max_width = max_height = 7 + sizes = ((min_width, min_height), (max_width, max_height)) + surface = pygame.Surface((20, 20), 0, 32) + surf_rect = surface.get_rect() + # Make a rect that is bigger than the surface to help test drawing + # ellipses off and partially off the surface. + big_rect = surf_rect.inflate(min_width * 2 + 1, min_height * 2 + 1) + + for pos in rect_corners_mids_and_center( + surf_rect + ) + rect_corners_mids_and_center(big_rect): + # Each of the ellipse's rect position attributes will be set to + # the pos value. + for attr in RECT_POSITION_ATTRIBUTES: + # Test using different rect sizes and thickness values. + for width, height in sizes: + ellipse_rect = pygame.Rect((0, 0), (width, height)) + setattr(ellipse_rect, attr, pos) + + for thickness in (0, 1, 2, 3, min(width, height)): + surface.fill(surf_color) # Clear for each test. + + bounding_rect = self.draw_ellipse( + surface, ellipse_color, ellipse_rect, thickness + ) + + # Calculating the expected_rect after the ellipse + # is drawn (it uses what is actually drawn). + expected_rect = create_bounding_rect( + surface, surf_color, ellipse_rect.topleft + ) + + self.assertEqual(bounding_rect, expected_rect) + + def test_ellipse__surface_clip(self): + """Ensures draw ellipse respects a surface's clip area. + + Tests drawing the ellipse filled and unfilled. + """ + surfw = surfh = 30 + ellipse_color = pygame.Color("red") + surface_color = pygame.Color("green") + surface = pygame.Surface((surfw, surfh)) + surface.fill(surface_color) + + clip_rect = pygame.Rect((0, 0), (11, 11)) + clip_rect.center = surface.get_rect().center + pos_rect = clip_rect.copy() # Manages the ellipse's pos. + + for width in (0, 1): # Filled and unfilled. + # Test centering the ellipse along the clip rect's edge. + for center in rect_corners_mids_and_center(clip_rect): + # Get the expected points by drawing the ellipse without the + # clip area set. + pos_rect.center = center + surface.set_clip(None) + surface.fill(surface_color) + self.draw_ellipse(surface, ellipse_color, pos_rect, width) + expected_pts = get_color_points(surface, ellipse_color, clip_rect) + + # Clear the surface and set the clip area. Redraw the ellipse + # and check that only the clip area is modified. + surface.fill(surface_color) + surface.set_clip(clip_rect) + + self.draw_ellipse(surface, ellipse_color, pos_rect, width) + + surface.lock() # For possible speed up. + + # Check all the surface points to ensure only the expected_pts + # are the ellipse_color. + for pt in ((x, y) for x in range(surfw) for y in range(surfh)): + if pt in expected_pts: + expected_color = ellipse_color + else: + expected_color = surface_color + + self.assertEqual(surface.get_at(pt), expected_color, pt) + + surface.unlock() + + +class DrawEllipseTest(DrawEllipseMixin, DrawTestCase): + """Test draw module function ellipse. + + This class inherits the general tests from DrawEllipseMixin. It is also + the class to add any draw.ellipse specific tests to. + """ + + +# Commented out to avoid cluttering the test output. Add back in if draw_py +# ever properly supports drawing ellipses. +# @unittest.skip('draw_py.draw_ellipse not supported yet') +# class PythonDrawEllipseTest(DrawEllipseMixin, PythonDrawTestCase): +# """Test draw_py module function draw_ellipse. +# +# This class inherits the general tests from DrawEllipseMixin. It is also +# the class to add any draw_py.draw_ellipse specific tests to. +# """ + + +### Line/Lines/AALine/AALines Testing ######################################### + + +class BaseLineMixin(object): + """Mixin base for drawing various lines. + + This class contains general helper methods and setup for testing the + different types of lines. + """ + + COLORS = ( + (0, 0, 0), + (255, 0, 0), + (0, 255, 0), + (0, 0, 255), + (255, 255, 0), + (255, 0, 255), + (0, 255, 255), + (255, 255, 255), + ) + + @staticmethod + def _create_surfaces(): + # Create some surfaces with different sizes, depths, and flags. + surfaces = [] + for size in ((49, 49), (50, 50)): + for depth in (8, 16, 24, 32): + for flags in (0, SRCALPHA): + surface = pygame.display.set_mode(size, flags, depth) + surfaces.append(surface) + surfaces.append(surface.convert_alpha()) + return surfaces + + @staticmethod + def _rect_lines(rect): + # Yields pairs of end points and their reverse (to test symmetry). + # Uses a rect with the points radiating from its midleft. + for pt in rect_corners_mids_and_center(rect): + if pt in [rect.midleft, rect.center]: + # Don't bother with these points. + continue + yield (rect.midleft, pt) + yield (pt, rect.midleft) + + +### Line Testing ############################################################## + + +class LineMixin(BaseLineMixin): + """Mixin test for drawing a single line. + + This class contains all the general single line drawing tests. + """ + + def test_line__args(self): + """Ensures draw line accepts the correct args.""" + bounds_rect = self.draw_line( + pygame.Surface((3, 3)), (0, 10, 0, 50), (0, 0), (1, 1), 1 + ) + + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_line__args_without_width(self): + """Ensures draw line accepts the args without a width.""" + bounds_rect = self.draw_line( + pygame.Surface((2, 2)), (0, 0, 0, 50), (0, 0), (2, 2) + ) + + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_line__kwargs(self): + """Ensures draw line accepts the correct kwargs + with and without a width arg. + """ + surface = pygame.Surface((4, 4)) + color = pygame.Color("yellow") + start_pos = (1, 1) + end_pos = (2, 2) + kwargs_list = [ + { + "surface": surface, + "color": color, + "start_pos": start_pos, + "end_pos": end_pos, + "width": 1, + }, + { + "surface": surface, + "color": color, + "start_pos": start_pos, + "end_pos": end_pos, + }, + ] + + for kwargs in kwargs_list: + bounds_rect = self.draw_line(**kwargs) + + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_line__kwargs_order_independent(self): + """Ensures draw line's kwargs are not order dependent.""" + bounds_rect = self.draw_line( + start_pos=(1, 2), + end_pos=(2, 1), + width=2, + color=(10, 20, 30), + surface=pygame.Surface((3, 2)), + ) + + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_line__args_missing(self): + """Ensures draw line detects any missing required args.""" + surface = pygame.Surface((1, 1)) + color = pygame.Color("blue") + + with self.assertRaises(TypeError): + bounds_rect = self.draw_line(surface, color, (0, 0)) + + with self.assertRaises(TypeError): + bounds_rect = self.draw_line(surface, color) + + with self.assertRaises(TypeError): + bounds_rect = self.draw_line(surface) + + with self.assertRaises(TypeError): + bounds_rect = self.draw_line() + + def test_line__kwargs_missing(self): + """Ensures draw line detects any missing required kwargs.""" + kwargs = { + "surface": pygame.Surface((3, 2)), + "color": pygame.Color("red"), + "start_pos": (2, 1), + "end_pos": (2, 2), + "width": 1, + } + + for name in ("end_pos", "start_pos", "color", "surface"): + invalid_kwargs = dict(kwargs) + invalid_kwargs.pop(name) # Pop from a copy. + + with self.assertRaises(TypeError): + bounds_rect = self.draw_line(**invalid_kwargs) + + def test_line__arg_invalid_types(self): + """Ensures draw line detects invalid arg types.""" + surface = pygame.Surface((2, 2)) + color = pygame.Color("blue") + start_pos = (0, 1) + end_pos = (1, 2) + + with self.assertRaises(TypeError): + # Invalid width. + bounds_rect = self.draw_line(surface, color, start_pos, end_pos, "1") + + with self.assertRaises(TypeError): + # Invalid end_pos. + bounds_rect = self.draw_line(surface, color, start_pos, (1, 2, 3)) + + with self.assertRaises(TypeError): + # Invalid start_pos. + bounds_rect = self.draw_line(surface, color, (1,), end_pos) + + with self.assertRaises(TypeError): + # Invalid color. + bounds_rect = self.draw_line(surface, 2.3, start_pos, end_pos) + + with self.assertRaises(TypeError): + # Invalid surface. + bounds_rect = self.draw_line((1, 2, 3, 4), color, start_pos, end_pos) + + def test_line__kwarg_invalid_types(self): + """Ensures draw line detects invalid kwarg types.""" + surface = pygame.Surface((3, 3)) + color = pygame.Color("green") + start_pos = (1, 0) + end_pos = (2, 0) + width = 1 + kwargs_list = [ + { + "surface": pygame.Surface, # Invalid surface. + "color": color, + "start_pos": start_pos, + "end_pos": end_pos, + "width": width, + }, + { + "surface": surface, + "color": 2.3, # Invalid color. + "start_pos": start_pos, + "end_pos": end_pos, + "width": width, + }, + { + "surface": surface, + "color": color, + "start_pos": (0, 0, 0), # Invalid start_pos. + "end_pos": end_pos, + "width": width, + }, + { + "surface": surface, + "color": color, + "start_pos": start_pos, + "end_pos": (0,), # Invalid end_pos. + "width": width, + }, + { + "surface": surface, + "color": color, + "start_pos": start_pos, + "end_pos": end_pos, + "width": 1.2, + }, + ] # Invalid width. + + for kwargs in kwargs_list: + with self.assertRaises(TypeError): + bounds_rect = self.draw_line(**kwargs) + + def test_line__kwarg_invalid_name(self): + """Ensures draw line detects invalid kwarg names.""" + surface = pygame.Surface((2, 3)) + color = pygame.Color("cyan") + start_pos = (1, 1) + end_pos = (2, 0) + kwargs_list = [ + { + "surface": surface, + "color": color, + "start_pos": start_pos, + "end_pos": end_pos, + "width": 1, + "invalid": 1, + }, + { + "surface": surface, + "color": color, + "start_pos": start_pos, + "end_pos": end_pos, + "invalid": 1, + }, + ] + + for kwargs in kwargs_list: + with self.assertRaises(TypeError): + bounds_rect = self.draw_line(**kwargs) + + def test_line__args_and_kwargs(self): + """Ensures draw line accepts a combination of args/kwargs""" + surface = pygame.Surface((3, 2)) + color = (255, 255, 0, 0) + start_pos = (0, 1) + end_pos = (1, 2) + width = 0 + kwargs = { + "surface": surface, + "color": color, + "start_pos": start_pos, + "end_pos": end_pos, + "width": width, + } + + for name in ("surface", "color", "start_pos", "end_pos", "width"): + kwargs.pop(name) + + if "surface" == name: + bounds_rect = self.draw_line(surface, **kwargs) + elif "color" == name: + bounds_rect = self.draw_line(surface, color, **kwargs) + elif "start_pos" == name: + bounds_rect = self.draw_line(surface, color, start_pos, **kwargs) + elif "end_pos" == name: + bounds_rect = self.draw_line( + surface, color, start_pos, end_pos, **kwargs + ) + else: + bounds_rect = self.draw_line( + surface, color, start_pos, end_pos, width, **kwargs + ) + + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_line__valid_width_values(self): + """Ensures draw line accepts different width values.""" + line_color = pygame.Color("yellow") + surface_color = pygame.Color("white") + surface = pygame.Surface((3, 4)) + pos = (2, 1) + kwargs = { + "surface": surface, + "color": line_color, + "start_pos": pos, + "end_pos": (2, 2), + "width": None, + } + + for width in (-100, -10, -1, 0, 1, 10, 100): + surface.fill(surface_color) # Clear for each test. + kwargs["width"] = width + expected_color = line_color if width > 0 else surface_color + + bounds_rect = self.draw_line(**kwargs) + + self.assertEqual(surface.get_at(pos), expected_color) + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_line__valid_start_pos_formats(self): + """Ensures draw line accepts different start_pos formats.""" + expected_color = pygame.Color("red") + surface_color = pygame.Color("black") + surface = pygame.Surface((4, 4)) + kwargs = { + "surface": surface, + "color": expected_color, + "start_pos": None, + "end_pos": (2, 2), + "width": 2, + } + x, y = 2, 1 # start position + + # The point values can be ints or floats. + for start_pos in ((x, y), (x + 0.1, y), (x, y + 0.1), (x + 0.1, y + 0.1)): + # The point type can be a tuple/list/Vector2. + for seq_type in (tuple, list, Vector2): + surface.fill(surface_color) # Clear for each test. + kwargs["start_pos"] = seq_type(start_pos) + + bounds_rect = self.draw_line(**kwargs) + + self.assertEqual(surface.get_at((x, y)), expected_color) + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_line__valid_end_pos_formats(self): + """Ensures draw line accepts different end_pos formats.""" + expected_color = pygame.Color("red") + surface_color = pygame.Color("black") + surface = pygame.Surface((4, 4)) + kwargs = { + "surface": surface, + "color": expected_color, + "start_pos": (2, 1), + "end_pos": None, + "width": 2, + } + x, y = 2, 2 # end position + + # The point values can be ints or floats. + for end_pos in ((x, y), (x + 0.2, y), (x, y + 0.2), (x + 0.2, y + 0.2)): + # The point type can be a tuple/list/Vector2. + for seq_type in (tuple, list, Vector2): + surface.fill(surface_color) # Clear for each test. + kwargs["end_pos"] = seq_type(end_pos) + + bounds_rect = self.draw_line(**kwargs) + + self.assertEqual(surface.get_at((x, y)), expected_color) + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_line__invalid_start_pos_formats(self): + """Ensures draw line handles invalid start_pos formats correctly.""" + kwargs = { + "surface": pygame.Surface((4, 4)), + "color": pygame.Color("red"), + "start_pos": None, + "end_pos": (2, 2), + "width": 1, + } + + start_pos_fmts = ( + (2,), # Too few coords. + (2, 1, 0), # Too many coords. + (2, "1"), # Wrong type. + set([2, 1]), # Wrong type. + dict(((2, 1),)), + ) # Wrong type. + + for start_pos in start_pos_fmts: + kwargs["start_pos"] = start_pos + + with self.assertRaises(TypeError): + bounds_rect = self.draw_line(**kwargs) + + def test_line__invalid_end_pos_formats(self): + """Ensures draw line handles invalid end_pos formats correctly.""" + kwargs = { + "surface": pygame.Surface((4, 4)), + "color": pygame.Color("red"), + "start_pos": (2, 2), + "end_pos": None, + "width": 1, + } + + end_pos_fmts = ( + (2,), # Too few coords. + (2, 1, 0), # Too many coords. + (2, "1"), # Wrong type. + set([2, 1]), # Wrong type. + dict(((2, 1),)), + ) # Wrong type. + + for end_pos in end_pos_fmts: + kwargs["end_pos"] = end_pos + + with self.assertRaises(TypeError): + bounds_rect = self.draw_line(**kwargs) + + def test_line__valid_color_formats(self): + """Ensures draw line accepts different color formats.""" + green_color = pygame.Color("green") + surface_color = pygame.Color("black") + surface = pygame.Surface((3, 4)) + pos = (1, 1) + kwargs = { + "surface": surface, + "color": None, + "start_pos": pos, + "end_pos": (2, 1), + "width": 3, + } + greens = ( + (0, 255, 0), + (0, 255, 0, 255), + surface.map_rgb(green_color), + green_color, + ) + + for color in greens: + surface.fill(surface_color) # Clear for each test. + kwargs["color"] = color + + if isinstance(color, int): + expected_color = surface.unmap_rgb(color) + else: + expected_color = green_color + + bounds_rect = self.draw_line(**kwargs) + + self.assertEqual(surface.get_at(pos), expected_color) + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_line__invalid_color_formats(self): + """Ensures draw line handles invalid color formats correctly.""" + kwargs = { + "surface": pygame.Surface((4, 3)), + "color": None, + "start_pos": (1, 1), + "end_pos": (2, 1), + "width": 1, + } + + for expected_color in (2.3, self): + kwargs["color"] = expected_color + + with self.assertRaises(TypeError): + bounds_rect = self.draw_line(**kwargs) + + def test_line__color(self): + """Tests if the line drawn is the correct color.""" + pos = (0, 0) + for surface in self._create_surfaces(): + for expected_color in self.COLORS: + self.draw_line(surface, expected_color, pos, (1, 0)) + + self.assertEqual( + surface.get_at(pos), expected_color, "pos={}".format(pos) + ) + + def test_line__color_with_thickness(self): + """Ensures a thick line is drawn using the correct color.""" + from_x = 5 + to_x = 10 + y = 5 + for surface in self._create_surfaces(): + for expected_color in self.COLORS: + self.draw_line(surface, expected_color, (from_x, y), (to_x, y), 5) + for pos in ((x, y + i) for i in (-2, 0, 2) for x in (from_x, to_x)): + self.assertEqual( + surface.get_at(pos), expected_color, "pos={}".format(pos) + ) + + def test_line__gaps(self): + """Tests if the line drawn contains any gaps.""" + expected_color = (255, 255, 255) + for surface in self._create_surfaces(): + width = surface.get_width() + self.draw_line(surface, expected_color, (0, 0), (width - 1, 0)) + + for x in range(width): + pos = (x, 0) + self.assertEqual( + surface.get_at(pos), expected_color, "pos={}".format(pos) + ) + + def test_line__gaps_with_thickness(self): + """Ensures a thick line is drawn without any gaps.""" + expected_color = (255, 255, 255) + thickness = 5 + for surface in self._create_surfaces(): + width = surface.get_width() - 1 + h = width // 5 + w = h * 5 + self.draw_line(surface, expected_color, (0, 5), (w, 5 + h), thickness) + + for x in range(w + 1): + for y in range(3, 8): + pos = (x, y + ((x + 2) // 5)) + self.assertEqual( + surface.get_at(pos), expected_color, "pos={}".format(pos) + ) + + def test_line__bounding_rect(self): + """Ensures draw line returns the correct bounding rect. + + Tests lines with endpoints on and off the surface and a range of + width/thickness values. + """ + if isinstance(self, PythonDrawTestCase): + self.skipTest("bounding rects not supported in draw_py.draw_line") + + line_color = pygame.Color("red") + surf_color = pygame.Color("black") + width = height = 30 + # Using a rect to help manage where the lines are drawn. + helper_rect = pygame.Rect((0, 0), (width, height)) + + # Testing surfaces of different sizes. One larger than the helper_rect + # and one smaller (to test lines that span the surface). + for size in ((width + 5, height + 5), (width - 5, height - 5)): + surface = pygame.Surface(size, 0, 32) + surf_rect = surface.get_rect() + + # Move the helper rect to different positions to test line + # endpoints on and off the surface. + for pos in rect_corners_mids_and_center(surf_rect): + helper_rect.center = pos + + # Draw using different thicknesses. + for thickness in range(-1, 5): + for start, end in self._rect_lines(helper_rect): + surface.fill(surf_color) # Clear for each test. + + bounding_rect = self.draw_line( + surface, line_color, start, end, thickness + ) + + if 0 < thickness: + # Calculating the expected_rect after the line is + # drawn (it uses what is actually drawn). + expected_rect = create_bounding_rect( + surface, surf_color, start + ) + else: + # Nothing drawn. + expected_rect = pygame.Rect(start, (0, 0)) + + self.assertEqual( + bounding_rect, + expected_rect, + "start={}, end={}, size={}, thickness={}".format( + start, end, size, thickness + ), + ) + + def test_line__surface_clip(self): + """Ensures draw line respects a surface's clip area.""" + surfw = surfh = 30 + line_color = pygame.Color("red") + surface_color = pygame.Color("green") + surface = pygame.Surface((surfw, surfh)) + surface.fill(surface_color) + + clip_rect = pygame.Rect((0, 0), (11, 11)) + clip_rect.center = surface.get_rect().center + pos_rect = clip_rect.copy() # Manages the line's pos. + + for thickness in (1, 3): # Test different line widths. + # Test centering the line along the clip rect's edge. + for center in rect_corners_mids_and_center(clip_rect): + # Get the expected points by drawing the line without the + # clip area set. + pos_rect.center = center + surface.set_clip(None) + surface.fill(surface_color) + self.draw_line( + surface, line_color, pos_rect.midtop, pos_rect.midbottom, thickness + ) + expected_pts = get_color_points(surface, line_color, clip_rect) + + # Clear the surface and set the clip area. Redraw the line + # and check that only the clip area is modified. + surface.fill(surface_color) + surface.set_clip(clip_rect) + + self.draw_line( + surface, line_color, pos_rect.midtop, pos_rect.midbottom, thickness + ) + + surface.lock() # For possible speed up. + + # Check all the surface points to ensure only the expected_pts + # are the line_color. + for pt in ((x, y) for x in range(surfw) for y in range(surfh)): + if pt in expected_pts: + expected_color = line_color + else: + expected_color = surface_color + + self.assertEqual(surface.get_at(pt), expected_color, pt) + + surface.unlock() + + +# Commented out to avoid cluttering the test output. Add back in if draw_py +# ever fully supports drawing single lines. +# @unittest.skip('draw_py.draw_line not fully supported yet') +# class PythonDrawLineTest(LineMixin, PythonDrawTestCase): +# """Test draw_py module function line. +# +# This class inherits the general tests from LineMixin. It is also the class +# to add any draw_py.draw_line specific tests to. +# """ + + +class DrawLineTest(LineMixin, DrawTestCase): + """Test draw module function line. + + This class inherits the general tests from LineMixin. It is also the class + to add any draw.line specific tests to. + """ + + def test_line_endianness(self): + """test color component order""" + for depth in (24, 32): + surface = pygame.Surface((5, 3), 0, depth) + surface.fill(pygame.Color(0, 0, 0)) + self.draw_line(surface, pygame.Color(255, 0, 0), (0, 1), (2, 1), 1) + + self.assertGreater(surface.get_at((1, 1)).r, 0, "there should be red here") + + surface.fill(pygame.Color(0, 0, 0)) + self.draw_line(surface, pygame.Color(0, 0, 255), (0, 1), (2, 1), 1) + + self.assertGreater(surface.get_at((1, 1)).b, 0, "there should be blue here") + + def test_line(self): + # (l, t), (l, t) + self.surf_size = (320, 200) + self.surf = pygame.Surface(self.surf_size, pygame.SRCALPHA) + self.color = (1, 13, 24, 205) + + drawn = draw.line(self.surf, self.color, (1, 0), (200, 0)) + self.assertEqual( + drawn.right, 201, "end point arg should be (or at least was) inclusive" + ) + + # Should be colored where it's supposed to be + for pt in test_utils.rect_area_pts(drawn): + self.assertEqual(self.surf.get_at(pt), self.color) + + # And not where it shouldn't + for pt in test_utils.rect_outer_bounds(drawn): + self.assertNotEqual(self.surf.get_at(pt), self.color) + + # Line width greater that 1 + line_width = 2 + offset = 5 + a = (offset, offset) + b = (self.surf_size[0] - offset, a[1]) + c = (a[0], self.surf_size[1] - offset) + d = (b[0], c[1]) + e = (a[0] + offset, c[1]) + f = (b[0], c[0] + 5) + lines = [ + (a, d), + (b, c), + (c, b), + (d, a), + (a, b), + (b, a), + (a, c), + (c, a), + (a, e), + (e, a), + (a, f), + (f, a), + (a, a), + ] + + for p1, p2 in lines: + msg = "%s - %s" % (p1, p2) + if p1[0] <= p2[0]: + plow = p1 + phigh = p2 + else: + plow = p2 + phigh = p1 + + self.surf.fill((0, 0, 0)) + rec = draw.line(self.surf, (255, 255, 255), p1, p2, line_width) + xinc = yinc = 0 + + if abs(p1[0] - p2[0]) > abs(p1[1] - p2[1]): + yinc = 1 + else: + xinc = 1 + + for i in range(line_width): + p = (p1[0] + xinc * i, p1[1] + yinc * i) + self.assertEqual(self.surf.get_at(p), (255, 255, 255), msg) + + p = (p2[0] + xinc * i, p2[1] + yinc * i) + self.assertEqual(self.surf.get_at(p), (255, 255, 255), msg) + + p = (plow[0] - 1, plow[1]) + self.assertEqual(self.surf.get_at(p), (0, 0, 0), msg) + + p = (plow[0] + xinc * line_width, plow[1] + yinc * line_width) + self.assertEqual(self.surf.get_at(p), (0, 0, 0), msg) + + p = (phigh[0] + xinc * line_width, phigh[1] + yinc * line_width) + self.assertEqual(self.surf.get_at(p), (0, 0, 0), msg) + + if p1[0] < p2[0]: + rx = p1[0] + else: + rx = p2[0] + + if p1[1] < p2[1]: + ry = p1[1] + else: + ry = p2[1] + + w = abs(p2[0] - p1[0]) + 1 + xinc * (line_width - 1) + h = abs(p2[1] - p1[1]) + 1 + yinc * (line_width - 1) + msg += ", %s" % (rec,) + + self.assertEqual(rec, (rx, ry, w, h), msg) + + def test_line_for_gaps(self): + # This checks bug Thick Line Bug #448 + + width = 200 + height = 200 + surf = pygame.Surface((width, height), pygame.SRCALPHA) + + def white_surrounded_pixels(x, y): + offsets = [(1, 0), (0, 1), (-1, 0), (0, -1)] + WHITE = (255, 255, 255, 255) + return len( + [1 for dx, dy in offsets if surf.get_at((x + dx, y + dy)) == WHITE] + ) + + def check_white_line(start, end): + surf.fill((0, 0, 0)) + pygame.draw.line(surf, (255, 255, 255), start, end, 30) + + BLACK = (0, 0, 0, 255) + for x in range(1, width - 1): + for y in range(1, height - 1): + if surf.get_at((x, y)) == BLACK: + self.assertTrue(white_surrounded_pixels(x, y) < 3) + + check_white_line((50, 50), (140, 0)) + check_white_line((50, 50), (0, 120)) + check_white_line((50, 50), (199, 198)) + + +### Lines Testing ############################################################# + + +class LinesMixin(BaseLineMixin): + """Mixin test for drawing lines. + + This class contains all the general lines drawing tests. + """ + + def test_lines__args(self): + """Ensures draw lines accepts the correct args.""" + bounds_rect = self.draw_lines( + pygame.Surface((3, 3)), (0, 10, 0, 50), False, ((0, 0), (1, 1)), 1 + ) + + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_lines__args_without_width(self): + """Ensures draw lines accepts the args without a width.""" + bounds_rect = self.draw_lines( + pygame.Surface((2, 2)), (0, 0, 0, 50), False, ((0, 0), (1, 1)) + ) + + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_lines__kwargs(self): + """Ensures draw lines accepts the correct kwargs + with and without a width arg. + """ + surface = pygame.Surface((4, 4)) + color = pygame.Color("yellow") + points = ((0, 0), (1, 1), (2, 2)) + kwargs_list = [ + { + "surface": surface, + "color": color, + "closed": False, + "points": points, + "width": 1, + }, + {"surface": surface, "color": color, "closed": False, "points": points}, + ] + + for kwargs in kwargs_list: + bounds_rect = self.draw_lines(**kwargs) + + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_lines__kwargs_order_independent(self): + """Ensures draw lines's kwargs are not order dependent.""" + bounds_rect = self.draw_lines( + closed=1, + points=((0, 0), (1, 1), (2, 2)), + width=2, + color=(10, 20, 30), + surface=pygame.Surface((3, 2)), + ) + + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_lines__args_missing(self): + """Ensures draw lines detects any missing required args.""" + surface = pygame.Surface((1, 1)) + color = pygame.Color("blue") + + with self.assertRaises(TypeError): + bounds_rect = self.draw_lines(surface, color, 0) + + with self.assertRaises(TypeError): + bounds_rect = self.draw_lines(surface, color) + + with self.assertRaises(TypeError): + bounds_rect = self.draw_lines(surface) + + with self.assertRaises(TypeError): + bounds_rect = self.draw_lines() + + def test_lines__kwargs_missing(self): + """Ensures draw lines detects any missing required kwargs.""" + kwargs = { + "surface": pygame.Surface((3, 2)), + "color": pygame.Color("red"), + "closed": 1, + "points": ((2, 2), (1, 1)), + "width": 1, + } + + for name in ("points", "closed", "color", "surface"): + invalid_kwargs = dict(kwargs) + invalid_kwargs.pop(name) # Pop from a copy. + + with self.assertRaises(TypeError): + bounds_rect = self.draw_lines(**invalid_kwargs) + + def test_lines__arg_invalid_types(self): + """Ensures draw lines detects invalid arg types.""" + surface = pygame.Surface((2, 2)) + color = pygame.Color("blue") + closed = 0 + points = ((1, 2), (2, 1)) + + with self.assertRaises(TypeError): + # Invalid width. + bounds_rect = self.draw_lines(surface, color, closed, points, "1") + + with self.assertRaises(TypeError): + # Invalid points. + bounds_rect = self.draw_lines(surface, color, closed, (1, 2, 3)) + + with self.assertRaises(TypeError): + # Invalid closed. + bounds_rect = self.draw_lines(surface, color, InvalidBool(), points) + + with self.assertRaises(TypeError): + # Invalid color. + bounds_rect = self.draw_lines(surface, 2.3, closed, points) + + with self.assertRaises(TypeError): + # Invalid surface. + bounds_rect = self.draw_lines((1, 2, 3, 4), color, closed, points) + + def test_lines__kwarg_invalid_types(self): + """Ensures draw lines detects invalid kwarg types.""" + valid_kwargs = { + "surface": pygame.Surface((3, 3)), + "color": pygame.Color("green"), + "closed": False, + "points": ((1, 2), (2, 1)), + "width": 1, + } + + invalid_kwargs = { + "surface": pygame.Surface, + "color": 2.3, + "closed": InvalidBool(), + "points": (0, 0, 0), + "width": 1.2, + } + + for kwarg in ("surface", "color", "closed", "points", "width"): + kwargs = dict(valid_kwargs) + kwargs[kwarg] = invalid_kwargs[kwarg] + + with self.assertRaises(TypeError): + bounds_rect = self.draw_lines(**kwargs) + + def test_lines__kwarg_invalid_name(self): + """Ensures draw lines detects invalid kwarg names.""" + surface = pygame.Surface((2, 3)) + color = pygame.Color("cyan") + closed = 1 + points = ((1, 2), (2, 1)) + kwargs_list = [ + { + "surface": surface, + "color": color, + "closed": closed, + "points": points, + "width": 1, + "invalid": 1, + }, + { + "surface": surface, + "color": color, + "closed": closed, + "points": points, + "invalid": 1, + }, + ] + + for kwargs in kwargs_list: + with self.assertRaises(TypeError): + bounds_rect = self.draw_lines(**kwargs) + + def test_lines__args_and_kwargs(self): + """Ensures draw lines accepts a combination of args/kwargs""" + surface = pygame.Surface((3, 2)) + color = (255, 255, 0, 0) + closed = 0 + points = ((1, 2), (2, 1)) + width = 1 + kwargs = { + "surface": surface, + "color": color, + "closed": closed, + "points": points, + "width": width, + } + + for name in ("surface", "color", "closed", "points", "width"): + kwargs.pop(name) + + if "surface" == name: + bounds_rect = self.draw_lines(surface, **kwargs) + elif "color" == name: + bounds_rect = self.draw_lines(surface, color, **kwargs) + elif "closed" == name: + bounds_rect = self.draw_lines(surface, color, closed, **kwargs) + elif "points" == name: + bounds_rect = self.draw_lines(surface, color, closed, points, **kwargs) + else: + bounds_rect = self.draw_lines( + surface, color, closed, points, width, **kwargs + ) + + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_lines__valid_width_values(self): + """Ensures draw lines accepts different width values.""" + line_color = pygame.Color("yellow") + surface_color = pygame.Color("white") + surface = pygame.Surface((3, 4)) + pos = (1, 1) + kwargs = { + "surface": surface, + "color": line_color, + "closed": False, + "points": (pos, (2, 1)), + "width": None, + } + + for width in (-100, -10, -1, 0, 1, 10, 100): + surface.fill(surface_color) # Clear for each test. + kwargs["width"] = width + expected_color = line_color if width > 0 else surface_color + + bounds_rect = self.draw_lines(**kwargs) + + self.assertEqual(surface.get_at(pos), expected_color) + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_lines__valid_points_format(self): + """Ensures draw lines accepts different points formats.""" + expected_color = (10, 20, 30, 255) + surface_color = pygame.Color("white") + surface = pygame.Surface((3, 4)) + kwargs = { + "surface": surface, + "color": expected_color, + "closed": False, + "points": None, + "width": 1, + } + + # The point type can be a tuple/list/Vector2. + point_types = ( + (tuple, tuple, tuple, tuple), # all tuples + (list, list, list, list), # all lists + (Vector2, Vector2, Vector2, Vector2), # all Vector2s + (list, Vector2, tuple, Vector2), + ) # mix + + # The point values can be ints or floats. + point_values = ( + ((1, 1), (2, 1), (2, 2), (1, 2)), + ((1, 1), (2.2, 1), (2.1, 2.2), (1, 2.1)), + ) + + # Each sequence of points can be a tuple or a list. + seq_types = (tuple, list) + + for point_type in point_types: + for values in point_values: + check_pos = values[0] + points = [point_type[i](pt) for i, pt in enumerate(values)] + + for seq_type in seq_types: + surface.fill(surface_color) # Clear for each test. + kwargs["points"] = seq_type(points) + + bounds_rect = self.draw_lines(**kwargs) + + self.assertEqual(surface.get_at(check_pos), expected_color) + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_lines__invalid_points_formats(self): + """Ensures draw lines handles invalid points formats correctly.""" + kwargs = { + "surface": pygame.Surface((4, 4)), + "color": pygame.Color("red"), + "closed": False, + "points": None, + "width": 1, + } + + points_fmts = ( + ((1, 1), (2,)), # Too few coords. + ((1, 1), (2, 2, 2)), # Too many coords. + ((1, 1), (2, "2")), # Wrong type. + ((1, 1), set([2, 3])), # Wrong type. + ((1, 1), dict(((2, 2), (3, 3)))), # Wrong type. + set(((1, 1), (1, 2))), # Wrong type. + dict(((1, 1), (4, 4))), + ) # Wrong type. + + for points in points_fmts: + kwargs["points"] = points + + with self.assertRaises(TypeError): + bounds_rect = self.draw_lines(**kwargs) + + def test_lines__invalid_points_values(self): + """Ensures draw lines handles invalid points values correctly.""" + kwargs = { + "surface": pygame.Surface((4, 4)), + "color": pygame.Color("red"), + "closed": False, + "points": None, + "width": 1, + } + + for points in ([], ((1, 1),)): # Too few points. + for seq_type in (tuple, list): # Test as tuples and lists. + kwargs["points"] = seq_type(points) + + with self.assertRaises(ValueError): + bounds_rect = self.draw_lines(**kwargs) + + def test_lines__valid_closed_values(self): + """Ensures draw lines accepts different closed values.""" + line_color = pygame.Color("blue") + surface_color = pygame.Color("white") + surface = pygame.Surface((3, 4)) + pos = (1, 2) + kwargs = { + "surface": surface, + "color": line_color, + "closed": None, + "points": ((1, 1), (3, 1), (3, 3), (1, 3)), + "width": 1, + } + + true_values = (-7, 1, 10, "2", 3.1, (4,), [5], True) + false_values = (None, "", 0, (), [], False) + + for closed in true_values + false_values: + surface.fill(surface_color) # Clear for each test. + kwargs["closed"] = closed + expected_color = line_color if closed else surface_color + + bounds_rect = self.draw_lines(**kwargs) + + self.assertEqual(surface.get_at(pos), expected_color) + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_lines__valid_color_formats(self): + """Ensures draw lines accepts different color formats.""" + green_color = pygame.Color("green") + surface_color = pygame.Color("black") + surface = pygame.Surface((3, 4)) + pos = (1, 1) + kwargs = { + "surface": surface, + "color": None, + "closed": False, + "points": (pos, (2, 1)), + "width": 3, + } + greens = ( + (0, 255, 0), + (0, 255, 0, 255), + surface.map_rgb(green_color), + green_color, + ) + + for color in greens: + surface.fill(surface_color) # Clear for each test. + kwargs["color"] = color + + if isinstance(color, int): + expected_color = surface.unmap_rgb(color) + else: + expected_color = green_color + + bounds_rect = self.draw_lines(**kwargs) + + self.assertEqual(surface.get_at(pos), expected_color) + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_lines__invalid_color_formats(self): + """Ensures draw lines handles invalid color formats correctly.""" + kwargs = { + "surface": pygame.Surface((4, 3)), + "color": None, + "closed": False, + "points": ((1, 1), (1, 2)), + "width": 1, + } + + for expected_color in (2.3, self): + kwargs["color"] = expected_color + + with self.assertRaises(TypeError): + bounds_rect = self.draw_lines(**kwargs) + + def test_lines__color(self): + """Tests if the lines drawn are the correct color. + + Draws lines around the border of the given surface and checks if all + borders of the surface only contain the given color. + """ + for surface in self._create_surfaces(): + for expected_color in self.COLORS: + self.draw_lines(surface, expected_color, True, corners(surface)) + + for pos, color in border_pos_and_color(surface): + self.assertEqual(color, expected_color, "pos={}".format(pos)) + + def test_lines__color_with_thickness(self): + """Ensures thick lines are drawn using the correct color.""" + x_left = y_top = 5 + for surface in self._create_surfaces(): + x_right = surface.get_width() - 5 + y_bottom = surface.get_height() - 5 + endpoints = ( + (x_left, y_top), + (x_right, y_top), + (x_right, y_bottom), + (x_left, y_bottom), + ) + for expected_color in self.COLORS: + self.draw_lines(surface, expected_color, True, endpoints, 3) + + for t in (-1, 0, 1): + for x in range(x_left, x_right + 1): + for y in (y_top, y_bottom): + pos = (x, y + t) + self.assertEqual( + surface.get_at(pos), + expected_color, + "pos={}".format(pos), + ) + for y in range(y_top, y_bottom + 1): + for x in (x_left, x_right): + pos = (x + t, y) + self.assertEqual( + surface.get_at(pos), + expected_color, + "pos={}".format(pos), + ) + + def test_lines__gaps(self): + """Tests if the lines drawn contain any gaps. + + Draws lines around the border of the given surface and checks if + all borders of the surface contain any gaps. + """ + expected_color = (255, 255, 255) + for surface in self._create_surfaces(): + self.draw_lines(surface, expected_color, True, corners(surface)) + + for pos, color in border_pos_and_color(surface): + self.assertEqual(color, expected_color, "pos={}".format(pos)) + + def test_lines__gaps_with_thickness(self): + """Ensures thick lines are drawn without any gaps.""" + expected_color = (255, 255, 255) + x_left = y_top = 5 + for surface in self._create_surfaces(): + h = (surface.get_width() - 11) // 5 + w = h * 5 + x_right = x_left + w + y_bottom = y_top + h + endpoints = ((x_left, y_top), (x_right, y_top), (x_right, y_bottom)) + self.draw_lines(surface, expected_color, True, endpoints, 3) + + for x in range(x_left, x_right + 1): + for t in (-1, 0, 1): + pos = (x, y_top + t) + self.assertEqual( + surface.get_at(pos), expected_color, "pos={}".format(pos) + ) + pos = (x, y_top + t + ((x - 3) // 5)) + self.assertEqual( + surface.get_at(pos), expected_color, "pos={}".format(pos) + ) + for y in range(y_top, y_bottom + 1): + for t in (-1, 0, 1): + pos = (x_right + t, y) + self.assertEqual( + surface.get_at(pos), expected_color, "pos={}".format(pos) + ) + + def test_lines__bounding_rect(self): + """Ensures draw lines returns the correct bounding rect. + + Tests lines with endpoints on and off the surface and a range of + width/thickness values. + """ + line_color = pygame.Color("red") + surf_color = pygame.Color("black") + width = height = 30 + # Using a rect to help manage where the lines are drawn. + pos_rect = pygame.Rect((0, 0), (width, height)) + + # Testing surfaces of different sizes. One larger than the pos_rect + # and one smaller (to test lines that span the surface). + for size in ((width + 5, height + 5), (width - 5, height - 5)): + surface = pygame.Surface(size, 0, 32) + surf_rect = surface.get_rect() + + # Move pos_rect to different positions to test line endpoints on + # and off the surface. + for pos in rect_corners_mids_and_center(surf_rect): + pos_rect.center = pos + # Shape: Triangle (if closed), ^ caret (if not closed). + pts = (pos_rect.midleft, pos_rect.midtop, pos_rect.midright) + pos = pts[0] # Rect position if nothing drawn. + + # Draw using different thickness and closed values. + for thickness in range(-1, 5): + for closed in (True, False): + surface.fill(surf_color) # Clear for each test. + + bounding_rect = self.draw_lines( + surface, line_color, closed, pts, thickness + ) + + if 0 < thickness: + # Calculating the expected_rect after the lines are + # drawn (it uses what is actually drawn). + expected_rect = create_bounding_rect( + surface, surf_color, pos + ) + else: + # Nothing drawn. + expected_rect = pygame.Rect(pos, (0, 0)) + + self.assertEqual(bounding_rect, expected_rect) + + def test_lines__surface_clip(self): + """Ensures draw lines respects a surface's clip area.""" + surfw = surfh = 30 + line_color = pygame.Color("red") + surface_color = pygame.Color("green") + surface = pygame.Surface((surfw, surfh)) + surface.fill(surface_color) + + clip_rect = pygame.Rect((0, 0), (11, 11)) + clip_rect.center = surface.get_rect().center + pos_rect = clip_rect.copy() # Manages the lines's pos. + + # Test centering the pos_rect along the clip rect's edge to allow for + # drawing the lines over the clip_rect's bounds. + for center in rect_corners_mids_and_center(clip_rect): + pos_rect.center = center + pts = (pos_rect.midtop, pos_rect.center, pos_rect.midbottom) + + for closed in (True, False): # Test closed and not closed. + for thickness in (1, 3): # Test different line widths. + # Get the expected points by drawing the lines without the + # clip area set. + surface.set_clip(None) + surface.fill(surface_color) + self.draw_lines(surface, line_color, closed, pts, thickness) + expected_pts = get_color_points(surface, line_color, clip_rect) + + # Clear the surface and set the clip area. Redraw the lines + # and check that only the clip area is modified. + surface.fill(surface_color) + surface.set_clip(clip_rect) + + self.draw_lines(surface, line_color, closed, pts, thickness) + + surface.lock() # For possible speed up. + + # Check all the surface points to ensure only the + # expected_pts are the line_color. + for pt in ((x, y) for x in range(surfw) for y in range(surfh)): + if pt in expected_pts: + expected_color = line_color + else: + expected_color = surface_color + + self.assertEqual(surface.get_at(pt), expected_color, pt) + + surface.unlock() + + +# Commented out to avoid cluttering the test output. Add back in if draw_py +# ever fully supports drawing lines. +# class PythonDrawLinesTest(LinesMixin, PythonDrawTestCase): +# """Test draw_py module function lines. +# +# This class inherits the general tests from LinesMixin. It is also the +# class to add any draw_py.draw_lines specific tests to. +# """ + + +class DrawLinesTest(LinesMixin, DrawTestCase): + """Test draw module function lines. + + This class inherits the general tests from LinesMixin. It is also the class + to add any draw.lines specific tests to. + """ + + +### AALine Testing ############################################################ + + +class AALineMixin(BaseLineMixin): + """Mixin test for drawing a single aaline. + + This class contains all the general single aaline drawing tests. + """ + + def test_aaline__args(self): + """Ensures draw aaline accepts the correct args.""" + bounds_rect = self.draw_aaline( + pygame.Surface((3, 3)), (0, 10, 0, 50), (0, 0), (1, 1), 1 + ) + + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_aaline__args_without_blend(self): + """Ensures draw aaline accepts the args without a blend.""" + bounds_rect = self.draw_aaline( + pygame.Surface((2, 2)), (0, 0, 0, 50), (0, 0), (2, 2) + ) + + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_aaline__blend_warning(self): + """From pygame 2, blend=False should raise DeprecationWarning.""" + with warnings.catch_warnings(record=True) as w: + # Cause all warnings to always be triggered. + warnings.simplefilter("always") + # Trigger DeprecationWarning. + self.draw_aaline( + pygame.Surface((2, 2)), (0, 0, 0, 50), (0, 0), (2, 2), False + ) + # Check if there is only one warning and is a DeprecationWarning. + self.assertEqual(len(w), 1) + self.assertTrue(issubclass(w[-1].category, DeprecationWarning)) + + def test_aaline__kwargs(self): + """Ensures draw aaline accepts the correct kwargs + with and without a blend arg. + """ + surface = pygame.Surface((4, 4)) + color = pygame.Color("yellow") + start_pos = (1, 1) + end_pos = (2, 2) + kwargs_list = [ + { + "surface": surface, + "color": color, + "start_pos": start_pos, + "end_pos": end_pos, + "blend": 1, + }, + { + "surface": surface, + "color": color, + "start_pos": start_pos, + "end_pos": end_pos, + }, + ] + + for kwargs in kwargs_list: + bounds_rect = self.draw_aaline(**kwargs) + + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_aaline__kwargs_order_independent(self): + """Ensures draw aaline's kwargs are not order dependent.""" + bounds_rect = self.draw_aaline( + start_pos=(1, 2), + end_pos=(2, 1), + blend=1, + color=(10, 20, 30), + surface=pygame.Surface((3, 2)), + ) + + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_aaline__args_missing(self): + """Ensures draw aaline detects any missing required args.""" + surface = pygame.Surface((1, 1)) + color = pygame.Color("blue") + + with self.assertRaises(TypeError): + bounds_rect = self.draw_aaline(surface, color, (0, 0)) + + with self.assertRaises(TypeError): + bounds_rect = self.draw_aaline(surface, color) + + with self.assertRaises(TypeError): + bounds_rect = self.draw_aaline(surface) + + with self.assertRaises(TypeError): + bounds_rect = self.draw_aaline() + + def test_aaline__kwargs_missing(self): + """Ensures draw aaline detects any missing required kwargs.""" + kwargs = { + "surface": pygame.Surface((3, 2)), + "color": pygame.Color("red"), + "start_pos": (2, 1), + "end_pos": (2, 2), + "blend": 1, + } + + for name in ("end_pos", "start_pos", "color", "surface"): + invalid_kwargs = dict(kwargs) + invalid_kwargs.pop(name) # Pop from a copy. + + with self.assertRaises(TypeError): + bounds_rect = self.draw_aaline(**invalid_kwargs) + + def test_aaline__arg_invalid_types(self): + """Ensures draw aaline detects invalid arg types.""" + surface = pygame.Surface((2, 2)) + color = pygame.Color("blue") + start_pos = (0, 1) + end_pos = (1, 2) + + with self.assertRaises(TypeError): + # Invalid blend. + bounds_rect = self.draw_aaline(surface, color, start_pos, end_pos, "1") + + with self.assertRaises(TypeError): + # Invalid end_pos. + bounds_rect = self.draw_aaline(surface, color, start_pos, (1, 2, 3)) + + with self.assertRaises(TypeError): + # Invalid start_pos. + bounds_rect = self.draw_aaline(surface, color, (1,), end_pos) + + with self.assertRaises(ValueError): + # Invalid color. + bounds_rect = self.draw_aaline(surface, "invalid-color", start_pos, end_pos) + + with self.assertRaises(TypeError): + # Invalid surface. + bounds_rect = self.draw_aaline((1, 2, 3, 4), color, start_pos, end_pos) + + def test_aaline__kwarg_invalid_types(self): + """Ensures draw aaline detects invalid kwarg types.""" + surface = pygame.Surface((3, 3)) + color = pygame.Color("green") + start_pos = (1, 0) + end_pos = (2, 0) + blend = 1 + kwargs_list = [ + { + "surface": pygame.Surface, # Invalid surface. + "color": color, + "start_pos": start_pos, + "end_pos": end_pos, + "blend": blend, + }, + { + "surface": surface, + "color": 2.3, # Invalid color. + "start_pos": start_pos, + "end_pos": end_pos, + "blend": blend, + }, + { + "surface": surface, + "color": color, + "start_pos": (0, 0, 0), # Invalid start_pos. + "end_pos": end_pos, + "blend": blend, + }, + { + "surface": surface, + "color": color, + "start_pos": start_pos, + "end_pos": (0,), # Invalid end_pos. + "blend": blend, + }, + { + "surface": surface, + "color": color, + "start_pos": start_pos, + "end_pos": end_pos, + "blend": 1.2, + }, + ] # Invalid blend. + + for kwargs in kwargs_list: + with self.assertRaises(TypeError): + bounds_rect = self.draw_aaline(**kwargs) + + def test_aaline__kwarg_invalid_name(self): + """Ensures draw aaline detects invalid kwarg names.""" + surface = pygame.Surface((2, 3)) + color = pygame.Color("cyan") + start_pos = (1, 1) + end_pos = (2, 0) + kwargs_list = [ + { + "surface": surface, + "color": color, + "start_pos": start_pos, + "end_pos": end_pos, + "blend": 1, + "invalid": 1, + }, + { + "surface": surface, + "color": color, + "start_pos": start_pos, + "end_pos": end_pos, + "invalid": 1, + }, + ] + + for kwargs in kwargs_list: + with self.assertRaises(TypeError): + bounds_rect = self.draw_aaline(**kwargs) + + def test_aaline__args_and_kwargs(self): + """Ensures draw aaline accepts a combination of args/kwargs""" + surface = pygame.Surface((3, 2)) + color = (255, 255, 0, 0) + start_pos = (0, 1) + end_pos = (1, 2) + blend = 0 + kwargs = { + "surface": surface, + "color": color, + "start_pos": start_pos, + "end_pos": end_pos, + "blend": blend, + } + + for name in ("surface", "color", "start_pos", "end_pos", "blend"): + kwargs.pop(name) + + if "surface" == name: + bounds_rect = self.draw_aaline(surface, **kwargs) + elif "color" == name: + bounds_rect = self.draw_aaline(surface, color, **kwargs) + elif "start_pos" == name: + bounds_rect = self.draw_aaline(surface, color, start_pos, **kwargs) + elif "end_pos" == name: + bounds_rect = self.draw_aaline( + surface, color, start_pos, end_pos, **kwargs + ) + else: + bounds_rect = self.draw_aaline( + surface, color, start_pos, end_pos, blend, **kwargs + ) + + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_aaline__valid_blend_values(self): + """Ensures draw aaline accepts different blend values.""" + expected_color = pygame.Color("yellow") + surface_color = pygame.Color("white") + surface = pygame.Surface((3, 4)) + pos = (2, 1) + kwargs = { + "surface": surface, + "color": expected_color, + "start_pos": pos, + "end_pos": (2, 2), + "blend": None, + } + + for blend in (-10, -2, -1, 0, 1, 2, 10): + surface.fill(surface_color) # Clear for each test. + kwargs["blend"] = blend + + bounds_rect = self.draw_aaline(**kwargs) + + self.assertEqual(surface.get_at(pos), expected_color) + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_aaline__valid_start_pos_formats(self): + """Ensures draw aaline accepts different start_pos formats.""" + expected_color = pygame.Color("red") + surface_color = pygame.Color("black") + surface = pygame.Surface((4, 4)) + kwargs = { + "surface": surface, + "color": expected_color, + "start_pos": None, + "end_pos": (2, 2), + "blend": 0, + } + x, y = 2, 1 # start position + positions = ((x, y), (x + 0.01, y), (x, y + 0.01), (x + 0.01, y + 0.01)) + + for start_pos in positions: + for seq_type in (tuple, list, Vector2): + surface.fill(surface_color) # Clear for each test. + kwargs["start_pos"] = seq_type(start_pos) + + bounds_rect = self.draw_aaline(**kwargs) + + color = surface.get_at((x, y)) + for i, sub_color in enumerate(expected_color): + # The color could be slightly off the expected color due to + # any fractional position arguments. + self.assertGreaterEqual(color[i] + 6, sub_color, start_pos) + self.assertIsInstance(bounds_rect, pygame.Rect, start_pos) + + def test_aaline__valid_end_pos_formats(self): + """Ensures draw aaline accepts different end_pos formats.""" + expected_color = pygame.Color("red") + surface_color = pygame.Color("black") + surface = pygame.Surface((4, 4)) + kwargs = { + "surface": surface, + "color": expected_color, + "start_pos": (2, 1), + "end_pos": None, + "blend": 0, + } + x, y = 2, 2 # end position + positions = ((x, y), (x + 0.02, y), (x, y + 0.02), (x + 0.02, y + 0.02)) + + for end_pos in positions: + for seq_type in (tuple, list, Vector2): + surface.fill(surface_color) # Clear for each test. + kwargs["end_pos"] = seq_type(end_pos) + + bounds_rect = self.draw_aaline(**kwargs) + + color = surface.get_at((x, y)) + for i, sub_color in enumerate(expected_color): + # The color could be slightly off the expected color due to + # any fractional position arguments. + self.assertGreaterEqual(color[i] + 15, sub_color, end_pos) + self.assertIsInstance(bounds_rect, pygame.Rect, end_pos) + + def test_aaline__invalid_start_pos_formats(self): + """Ensures draw aaline handles invalid start_pos formats correctly.""" + kwargs = { + "surface": pygame.Surface((4, 4)), + "color": pygame.Color("red"), + "start_pos": None, + "end_pos": (2, 2), + "blend": 0, + } + + start_pos_fmts = ( + (2,), # Too few coords. + (2, 1, 0), # Too many coords. + (2, "1"), # Wrong type. + set([2, 1]), # Wrong type. + dict(((2, 1),)), + ) # Wrong type. + + for start_pos in start_pos_fmts: + kwargs["start_pos"] = start_pos + + with self.assertRaises(TypeError): + bounds_rect = self.draw_aaline(**kwargs) + + def test_aaline__invalid_end_pos_formats(self): + """Ensures draw aaline handles invalid end_pos formats correctly.""" + kwargs = { + "surface": pygame.Surface((4, 4)), + "color": pygame.Color("red"), + "start_pos": (2, 2), + "end_pos": None, + "blend": 0, + } + + end_pos_fmts = ( + (2,), # Too few coords. + (2, 1, 0), # Too many coords. + (2, "1"), # Wrong type. + set([2, 1]), # Wrong type. + dict(((2, 1),)), + ) # Wrong type. + + for end_pos in end_pos_fmts: + kwargs["end_pos"] = end_pos + + with self.assertRaises(TypeError): + bounds_rect = self.draw_aaline(**kwargs) + + def test_aaline__valid_color_formats(self): + """Ensures draw aaline accepts different color formats.""" + green_color = pygame.Color("green") + surface_color = pygame.Color("black") + surface = pygame.Surface((3, 4)) + pos = (1, 1) + kwargs = { + "surface": surface, + "color": None, + "start_pos": pos, + "end_pos": (2, 1), + "blend": 0, + } + greens = ( + (0, 255, 0), + (0, 255, 0, 255), + surface.map_rgb(green_color), + green_color, + ) + + for color in greens: + surface.fill(surface_color) # Clear for each test. + kwargs["color"] = color + + if isinstance(color, int): + expected_color = surface.unmap_rgb(color) + else: + expected_color = green_color + + bounds_rect = self.draw_aaline(**kwargs) + + self.assertEqual(surface.get_at(pos), expected_color) + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_aaline__invalid_color_formats(self): + """Ensures draw aaline handles invalid color formats correctly.""" + kwargs = { + "surface": pygame.Surface((4, 3)), + "color": None, + "start_pos": (1, 1), + "end_pos": (2, 1), + "blend": 0, + } + + for expected_color in (2.3, self): + kwargs["color"] = expected_color + + with self.assertRaises(TypeError): + bounds_rect = self.draw_aaline(**kwargs) + + def test_aaline__color(self): + """Tests if the aaline drawn is the correct color.""" + pos = (0, 0) + for surface in self._create_surfaces(): + for expected_color in self.COLORS: + self.draw_aaline(surface, expected_color, pos, (1, 0)) + + self.assertEqual( + surface.get_at(pos), expected_color, "pos={}".format(pos) + ) + + def test_aaline__gaps(self): + """Tests if the aaline drawn contains any gaps. + + See: #512 + """ + expected_color = (255, 255, 255) + for surface in self._create_surfaces(): + width = surface.get_width() + self.draw_aaline(surface, expected_color, (0, 0), (width - 1, 0)) + + for x in range(width): + pos = (x, 0) + self.assertEqual( + surface.get_at(pos), expected_color, "pos={}".format(pos) + ) + + def test_aaline__bounding_rect(self): + """Ensures draw aaline returns the correct bounding rect. + + Tests lines with endpoints on and off the surface and blending + enabled and disabled. + """ + line_color = pygame.Color("red") + surf_color = pygame.Color("blue") + width = height = 30 + # Using a rect to help manage where the lines are drawn. + helper_rect = pygame.Rect((0, 0), (width, height)) + + # Testing surfaces of different sizes. One larger than the helper_rect + # and one smaller (to test lines that span the surface). + for size in ((width + 5, height + 5), (width - 5, height - 5)): + surface = pygame.Surface(size, 0, 32) + surf_rect = surface.get_rect() + + # Move the helper rect to different positions to test line + # endpoints on and off the surface. + for pos in rect_corners_mids_and_center(surf_rect): + helper_rect.center = pos + + for blend in (False, True): # Test non-blending and blending. + for start, end in self._rect_lines(helper_rect): + surface.fill(surf_color) # Clear for each test. + + bounding_rect = self.draw_aaline( + surface, line_color, start, end, blend + ) + + # Calculating the expected_rect after the line is + # drawn (it uses what is actually drawn). + expected_rect = create_bounding_rect(surface, surf_color, start) + + self.assertEqual(bounding_rect, expected_rect) + + def test_aaline__surface_clip(self): + """Ensures draw aaline respects a surface's clip area.""" + surfw = surfh = 30 + aaline_color = pygame.Color("red") + surface_color = pygame.Color("green") + surface = pygame.Surface((surfw, surfh)) + surface.fill(surface_color) + + clip_rect = pygame.Rect((0, 0), (11, 11)) + clip_rect.center = surface.get_rect().center + pos_rect = clip_rect.copy() # Manages the aaline's pos. + + # Test centering the pos_rect along the clip rect's edge to allow for + # drawing the aaline over the clip_rect's bounds. + for center in rect_corners_mids_and_center(clip_rect): + pos_rect.center = center + + for blend in (0, 1): # Test non-blending and blending. + # Get the expected points by drawing the aaline without the + # clip area set. + surface.set_clip(None) + surface.fill(surface_color) + self.draw_aaline( + surface, aaline_color, pos_rect.midtop, pos_rect.midbottom, blend + ) + + # Need to get the points that are NOT surface_color due to the + # way blend=0 uses the color black to antialias. + expected_pts = get_color_points( + surface, surface_color, clip_rect, False + ) + + # Clear the surface and set the clip area. Redraw the aaline + # and check that only the clip area is modified. + surface.fill(surface_color) + surface.set_clip(clip_rect) + + self.draw_aaline( + surface, aaline_color, pos_rect.midtop, pos_rect.midbottom, blend + ) + + surface.lock() # For possible speed up. + + # Check all the surface points to ensure the expected_pts + # are not surface_color. + for pt in ((x, y) for x in range(surfw) for y in range(surfh)): + if pt in expected_pts: + self.assertNotEqual(surface.get_at(pt), surface_color, pt) + else: + self.assertEqual(surface.get_at(pt), surface_color, pt) + + surface.unlock() + + +# Commented out to avoid cluttering the test output. Add back in if draw_py +# ever fully supports drawing single aalines. +# class PythonDrawAALineTest(AALineMixin, PythonDrawTestCase): +# """Test draw_py module function aaline. +# +# This class inherits the general tests from AALineMixin. It is also the +# class to add any draw_py.draw_aaline specific tests to. +# """ + + +class DrawAALineTest(AALineMixin, DrawTestCase): + """Test draw module function aaline. + + This class inherits the general tests from AALineMixin. It is also the + class to add any draw.aaline specific tests to. + """ + + def test_aaline_endianness(self): + """test color component order""" + for depth in (24, 32): + surface = pygame.Surface((5, 3), 0, depth) + surface.fill(pygame.Color(0, 0, 0)) + self.draw_aaline(surface, pygame.Color(255, 0, 0), (0, 1), (2, 1), 1) + + self.assertGreater(surface.get_at((1, 1)).r, 0, "there should be red here") + + surface.fill(pygame.Color(0, 0, 0)) + self.draw_aaline(surface, pygame.Color(0, 0, 255), (0, 1), (2, 1), 1) + + self.assertGreater(surface.get_at((1, 1)).b, 0, "there should be blue here") + + def _check_antialiasing( + self, from_point, to_point, should, check_points, set_endpoints=True + ): + """Draw a line between two points and check colors of check_points.""" + if set_endpoints: + should[from_point] = should[to_point] = FG_GREEN + + def check_one_direction(from_point, to_point, should): + self.draw_aaline(self.surface, FG_GREEN, from_point, to_point, True) + + for pt in check_points: + color = should.get(pt, BG_RED) + with self.subTest(from_pt=from_point, pt=pt, to=to_point): + self.assertEqual(self.surface.get_at(pt), color) + + # reset + draw.rect(self.surface, BG_RED, (0, 0, 10, 10), 0) + + # it is important to test also opposite direction, the algorithm + # is (#512) or was not symmetric + check_one_direction(from_point, to_point, should) + if from_point != to_point: + check_one_direction(to_point, from_point, should) + + def test_short_non_antialiased_lines(self): + """test very short not anti aliased lines in all directions.""" + + # Horizontal, vertical and diagonal lines should not be anti-aliased, + # even with draw.aaline ... + self.surface = pygame.Surface((10, 10)) + draw.rect(self.surface, BG_RED, (0, 0, 10, 10), 0) + + check_points = [(i, j) for i in range(3, 8) for j in range(3, 8)] + + def check_both_directions(from_pt, to_pt, other_points): + should = {pt: FG_GREEN for pt in other_points} + self._check_antialiasing(from_pt, to_pt, should, check_points) + + # 0. one point + check_both_directions((5, 5), (5, 5), []) + # 1. horizontal + check_both_directions((4, 7), (5, 7), []) + check_both_directions((5, 4), (7, 4), [(6, 4)]) + + # 2. vertical + check_both_directions((5, 5), (5, 6), []) + check_both_directions((6, 4), (6, 6), [(6, 5)]) + # 3. diagonals + check_both_directions((5, 5), (6, 6), []) + check_both_directions((5, 5), (7, 7), [(6, 6)]) + check_both_directions((5, 6), (6, 5), []) + check_both_directions((6, 4), (4, 6), [(5, 5)]) + + def test_short_line_anti_aliasing(self): + + self.surface = pygame.Surface((10, 10)) + draw.rect(self.surface, BG_RED, (0, 0, 10, 10), 0) + + check_points = [(i, j) for i in range(3, 8) for j in range(3, 8)] + + def check_both_directions(from_pt, to_pt, should): + self._check_antialiasing(from_pt, to_pt, should, check_points) + + brown = (127, 127, 0) + reddish = (191, 63, 0) + greenish = (63, 191, 0) + + # lets say dx = abs(x0 - x1) ; dy = abs(y0 - y1) + + # dy / dx = 0.5 + check_both_directions((4, 4), (6, 5), {(5, 4): brown, (5, 5): brown}) + check_both_directions((4, 5), (6, 4), {(5, 4): brown, (5, 5): brown}) + + # dy / dx = 2 + check_both_directions((4, 4), (5, 6), {(4, 5): brown, (5, 5): brown}) + check_both_directions((5, 4), (4, 6), {(4, 5): brown, (5, 5): brown}) + + # some little longer lines; so we need to check more points: + check_points = [(i, j) for i in range(2, 9) for j in range(2, 9)] + # dy / dx = 0.25 + should = { + (4, 3): greenish, + (5, 3): brown, + (6, 3): reddish, + (4, 4): reddish, + (5, 4): brown, + (6, 4): greenish, + } + check_both_directions((3, 3), (7, 4), should) + + should = { + (4, 3): reddish, + (5, 3): brown, + (6, 3): greenish, + (4, 4): greenish, + (5, 4): brown, + (6, 4): reddish, + } + check_both_directions((3, 4), (7, 3), should) + + # dy / dx = 4 + should = { + (4, 4): greenish, + (4, 5): brown, + (4, 6): reddish, + (5, 4): reddish, + (5, 5): brown, + (5, 6): greenish, + } + check_both_directions((4, 3), (5, 7), should) + + should = { + (4, 4): reddish, + (4, 5): brown, + (4, 6): greenish, + (5, 4): greenish, + (5, 5): brown, + (5, 6): reddish, + } + check_both_directions((5, 3), (4, 7), should) + + def test_anti_aliasing_float_coordinates(self): + """Float coordinates should be blended smoothly.""" + + self.surface = pygame.Surface((10, 10)) + draw.rect(self.surface, BG_RED, (0, 0, 10, 10), 0) + + check_points = [(i, j) for i in range(5) for j in range(5)] + brown = (127, 127, 0) + reddish = (191, 63, 0) + greenish = (63, 191, 0) + + # 0. identical point : current implementation does no smoothing... + expected = {(2, 2): FG_GREEN} + self._check_antialiasing( + (1.5, 2), (1.5, 2), expected, check_points, set_endpoints=False + ) + expected = {(2, 3): FG_GREEN} + self._check_antialiasing( + (2.49, 2.7), (2.49, 2.7), expected, check_points, set_endpoints=False + ) + + # 1. horizontal lines + # a) blend endpoints + expected = {(1, 2): brown, (2, 2): FG_GREEN} + self._check_antialiasing( + (1.5, 2), (2, 2), expected, check_points, set_endpoints=False + ) + expected = {(1, 2): brown, (2, 2): FG_GREEN, (3, 2): brown} + self._check_antialiasing( + (1.5, 2), (2.5, 2), expected, check_points, set_endpoints=False + ) + expected = {(2, 2): brown, (1, 2): FG_GREEN} + self._check_antialiasing( + (1, 2), (1.5, 2), expected, check_points, set_endpoints=False + ) + expected = {(1, 2): brown, (2, 2): greenish} + self._check_antialiasing( + (1.5, 2), (1.75, 2), expected, check_points, set_endpoints=False + ) + + # b) blend y-coordinate + expected = {(x, y): brown for x in range(2, 5) for y in (1, 2)} + self._check_antialiasing( + (2, 1.5), (4, 1.5), expected, check_points, set_endpoints=False + ) + + # 2. vertical lines + # a) blend endpoints + expected = {(2, 1): brown, (2, 2): FG_GREEN, (2, 3): brown} + self._check_antialiasing( + (2, 1.5), (2, 2.5), expected, check_points, set_endpoints=False + ) + expected = {(2, 1): brown, (2, 2): greenish} + self._check_antialiasing( + (2, 1.5), (2, 1.75), expected, check_points, set_endpoints=False + ) + # b) blend x-coordinate + expected = {(x, y): brown for x in (1, 2) for y in range(2, 5)} + self._check_antialiasing( + (1.5, 2), (1.5, 4), expected, check_points, set_endpoints=False + ) + # 3. diagonal lines + # a) blend endpoints + expected = {(1, 1): brown, (2, 2): FG_GREEN, (3, 3): brown} + self._check_antialiasing( + (1.5, 1.5), (2.5, 2.5), expected, check_points, set_endpoints=False + ) + expected = {(3, 1): brown, (2, 2): FG_GREEN, (1, 3): brown} + self._check_antialiasing( + (2.5, 1.5), (1.5, 2.5), expected, check_points, set_endpoints=False + ) + # b) blend sidewards + expected = {(2, 1): brown, (2, 2): brown, (3, 2): brown, (3, 3): brown} + self._check_antialiasing( + (2, 1.5), (3, 2.5), expected, check_points, set_endpoints=False + ) + + expected = { + (2, 1): greenish, + (2, 2): reddish, + (3, 2): greenish, + (3, 3): reddish, + (4, 3): greenish, + (4, 4): reddish, + } + + self._check_antialiasing( + (2, 1.25), (4, 3.25), expected, check_points, set_endpoints=False + ) + + def test_anti_aliasing_at_and_outside_the_border(self): + """Ensures antialiasing works correct at a surface's borders.""" + + self.surface = pygame.Surface((10, 10)) + draw.rect(self.surface, BG_RED, (0, 0, 10, 10), 0) + + check_points = [(i, j) for i in range(10) for j in range(10)] + + reddish = (191, 63, 0) + brown = (127, 127, 0) + greenish = (63, 191, 0) + from_point, to_point = (3, 3), (7, 4) + should = { + (4, 3): greenish, + (5, 3): brown, + (6, 3): reddish, + (4, 4): reddish, + (5, 4): brown, + (6, 4): greenish, + } + + for dx, dy in ( + (-4, 0), + (4, 0), # moved to left and right borders + (0, -5), + (0, -4), + (0, -3), # upper border + (0, 5), + (0, 6), + (0, 7), # lower border + (-4, -4), + (-4, -3), + (-3, -4), + ): # upper left corner + first = from_point[0] + dx, from_point[1] + dy + second = to_point[0] + dx, to_point[1] + dy + expected = {(x + dx, y + dy): color for (x, y), color in should.items()} + + self._check_antialiasing(first, second, expected, check_points) + + +### AALines Testing ########################################################### + + +class AALinesMixin(BaseLineMixin): + """Mixin test for drawing aalines. + + This class contains all the general aalines drawing tests. + """ + + def test_aalines__args(self): + """Ensures draw aalines accepts the correct args.""" + bounds_rect = self.draw_aalines( + pygame.Surface((3, 3)), (0, 10, 0, 50), False, ((0, 0), (1, 1)), 1 + ) + + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_aalines__args_without_blend(self): + """Ensures draw aalines accepts the args without a blend.""" + bounds_rect = self.draw_aalines( + pygame.Surface((2, 2)), (0, 0, 0, 50), False, ((0, 0), (1, 1)) + ) + + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_aalines__blend_warning(self): + """From pygame 2, blend=False should raise DeprecationWarning.""" + with warnings.catch_warnings(record=True) as w: + # Cause all warnings to always be triggered. + warnings.simplefilter("always") + # Trigger DeprecationWarning. + self.draw_aalines( + pygame.Surface((2, 2)), (0, 0, 0, 50), False, ((0, 0), (1, 1)), False + ) + # Check if there is only one warning and is a DeprecationWarning. + self.assertEqual(len(w), 1) + self.assertTrue(issubclass(w[-1].category, DeprecationWarning)) + + def test_aalines__kwargs(self): + """Ensures draw aalines accepts the correct kwargs + with and without a blend arg. + """ + surface = pygame.Surface((4, 4)) + color = pygame.Color("yellow") + points = ((0, 0), (1, 1), (2, 2)) + kwargs_list = [ + { + "surface": surface, + "color": color, + "closed": False, + "points": points, + "blend": 1, + }, + {"surface": surface, "color": color, "closed": False, "points": points}, + ] + + for kwargs in kwargs_list: + bounds_rect = self.draw_aalines(**kwargs) + + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_aalines__kwargs_order_independent(self): + """Ensures draw aalines's kwargs are not order dependent.""" + bounds_rect = self.draw_aalines( + closed=1, + points=((0, 0), (1, 1), (2, 2)), + blend=1, + color=(10, 20, 30), + surface=pygame.Surface((3, 2)), + ) + + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_aalines__args_missing(self): + """Ensures draw aalines detects any missing required args.""" + surface = pygame.Surface((1, 1)) + color = pygame.Color("blue") + + with self.assertRaises(TypeError): + bounds_rect = self.draw_aalines(surface, color, 0) + + with self.assertRaises(TypeError): + bounds_rect = self.draw_aalines(surface, color) + + with self.assertRaises(TypeError): + bounds_rect = self.draw_aalines(surface) + + with self.assertRaises(TypeError): + bounds_rect = self.draw_aalines() + + def test_aalines__kwargs_missing(self): + """Ensures draw aalines detects any missing required kwargs.""" + kwargs = { + "surface": pygame.Surface((3, 2)), + "color": pygame.Color("red"), + "closed": 1, + "points": ((2, 2), (1, 1)), + "blend": 1, + } + + for name in ("points", "closed", "color", "surface"): + invalid_kwargs = dict(kwargs) + invalid_kwargs.pop(name) # Pop from a copy. + + with self.assertRaises(TypeError): + bounds_rect = self.draw_aalines(**invalid_kwargs) + + def test_aalines__arg_invalid_types(self): + """Ensures draw aalines detects invalid arg types.""" + surface = pygame.Surface((2, 2)) + color = pygame.Color("blue") + closed = 0 + points = ((1, 2), (2, 1)) + + with self.assertRaises(TypeError): + # Invalid blend. + bounds_rect = self.draw_aalines(surface, color, closed, points, "1") + + with self.assertRaises(TypeError): + # Invalid points. + bounds_rect = self.draw_aalines(surface, color, closed, (1, 2, 3)) + + with self.assertRaises(TypeError): + # Invalid closed. + bounds_rect = self.draw_aalines(surface, color, InvalidBool(), points) + + with self.assertRaises(TypeError): + # Invalid color. + bounds_rect = self.draw_aalines(surface, 2.3, closed, points) + + with self.assertRaises(TypeError): + # Invalid surface. + bounds_rect = self.draw_aalines((1, 2, 3, 4), color, closed, points) + + def test_aalines__kwarg_invalid_types(self): + """Ensures draw aalines detects invalid kwarg types.""" + valid_kwargs = { + "surface": pygame.Surface((3, 3)), + "color": pygame.Color("green"), + "closed": False, + "points": ((1, 2), (2, 1)), + "blend": 1, + } + + invalid_kwargs = { + "surface": pygame.Surface, + "color": 2.3, + "closed": InvalidBool(), + "points": (0, 0, 0), + "blend": 1.2, + } + + for kwarg in ("surface", "color", "closed", "points", "blend"): + kwargs = dict(valid_kwargs) + kwargs[kwarg] = invalid_kwargs[kwarg] + + with self.assertRaises(TypeError): + bounds_rect = self.draw_aalines(**kwargs) + + def test_aalines__kwarg_invalid_name(self): + """Ensures draw aalines detects invalid kwarg names.""" + surface = pygame.Surface((2, 3)) + color = pygame.Color("cyan") + closed = 1 + points = ((1, 2), (2, 1)) + kwargs_list = [ + { + "surface": surface, + "color": color, + "closed": closed, + "points": points, + "blend": 1, + "invalid": 1, + }, + { + "surface": surface, + "color": color, + "closed": closed, + "points": points, + "invalid": 1, + }, + ] + + for kwargs in kwargs_list: + with self.assertRaises(TypeError): + bounds_rect = self.draw_aalines(**kwargs) + + def test_aalines__args_and_kwargs(self): + """Ensures draw aalines accepts a combination of args/kwargs""" + surface = pygame.Surface((3, 2)) + color = (255, 255, 0, 0) + closed = 0 + points = ((1, 2), (2, 1)) + blend = 1 + kwargs = { + "surface": surface, + "color": color, + "closed": closed, + "points": points, + "blend": blend, + } + + for name in ("surface", "color", "closed", "points", "blend"): + kwargs.pop(name) + + if "surface" == name: + bounds_rect = self.draw_aalines(surface, **kwargs) + elif "color" == name: + bounds_rect = self.draw_aalines(surface, color, **kwargs) + elif "closed" == name: + bounds_rect = self.draw_aalines(surface, color, closed, **kwargs) + elif "points" == name: + bounds_rect = self.draw_aalines( + surface, color, closed, points, **kwargs + ) + else: + bounds_rect = self.draw_aalines( + surface, color, closed, points, blend, **kwargs + ) + + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_aalines__valid_blend_values(self): + """Ensures draw aalines accepts different blend values.""" + expected_color = pygame.Color("yellow") + surface_color = pygame.Color("white") + surface = pygame.Surface((3, 4)) + pos = (1, 1) + kwargs = { + "surface": surface, + "color": expected_color, + "closed": False, + "points": (pos, (1, 3)), + "blend": None, + } + + for blend in (-10, -2, -1, 0, 1, 2, 10): + surface.fill(surface_color) # Clear for each test. + kwargs["blend"] = blend + + bounds_rect = self.draw_aalines(**kwargs) + + self.assertEqual(surface.get_at(pos), expected_color, blend) + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_aalines__valid_points_format(self): + """Ensures draw aalines accepts different points formats.""" + expected_color = (10, 20, 30, 255) + surface_color = pygame.Color("white") + surface = pygame.Surface((3, 4)) + kwargs = { + "surface": surface, + "color": expected_color, + "closed": False, + "points": None, + "blend": 0, + } + + # The point type can be a tuple/list/Vector2. + point_types = ( + (tuple, tuple, tuple, tuple), # all tuples + (list, list, list, list), # all lists + (Vector2, Vector2, Vector2, Vector2), # all Vector2s + (list, Vector2, tuple, Vector2), + ) # mix + + # The point values can be ints or floats. + point_values = ( + ((1, 1), (2, 1), (2, 2), (1, 2)), + ((1, 1), (2.2, 1), (2.1, 2.2), (1, 2.1)), + ) + + # Each sequence of points can be a tuple or a list. + seq_types = (tuple, list) + + for point_type in point_types: + for values in point_values: + check_pos = values[0] + points = [point_type[i](pt) for i, pt in enumerate(values)] + + for seq_type in seq_types: + surface.fill(surface_color) # Clear for each test. + kwargs["points"] = seq_type(points) + + bounds_rect = self.draw_aalines(**kwargs) + + self.assertEqual(surface.get_at(check_pos), expected_color) + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_aalines__invalid_points_formats(self): + """Ensures draw aalines handles invalid points formats correctly.""" + kwargs = { + "surface": pygame.Surface((4, 4)), + "color": pygame.Color("red"), + "closed": False, + "points": None, + "blend": 1, + } + + points_fmts = ( + ((1, 1), (2,)), # Too few coords. + ((1, 1), (2, 2, 2)), # Too many coords. + ((1, 1), (2, "2")), # Wrong type. + ((1, 1), set([2, 3])), # Wrong type. + ((1, 1), dict(((2, 2), (3, 3)))), # Wrong type. + set(((1, 1), (1, 2))), # Wrong type. + dict(((1, 1), (4, 4))), + ) # Wrong type. + + for points in points_fmts: + kwargs["points"] = points + + with self.assertRaises(TypeError): + bounds_rect = self.draw_aalines(**kwargs) + + def test_aalines__invalid_points_values(self): + """Ensures draw aalines handles invalid points values correctly.""" + kwargs = { + "surface": pygame.Surface((4, 4)), + "color": pygame.Color("red"), + "closed": False, + "points": None, + "blend": 1, + } + + for points in ([], ((1, 1),)): # Too few points. + for seq_type in (tuple, list): # Test as tuples and lists. + kwargs["points"] = seq_type(points) + + with self.assertRaises(ValueError): + bounds_rect = self.draw_aalines(**kwargs) + + def test_aalines__valid_closed_values(self): + """Ensures draw aalines accepts different closed values.""" + line_color = pygame.Color("blue") + surface_color = pygame.Color("white") + surface = pygame.Surface((5, 5)) + pos = (1, 3) + kwargs = { + "surface": surface, + "color": line_color, + "closed": None, + "points": ((1, 1), (4, 1), (4, 4), (1, 4)), + "blend": 0, + } + + true_values = (-7, 1, 10, "2", 3.1, (4,), [5], True) + false_values = (None, "", 0, (), [], False) + + for closed in true_values + false_values: + surface.fill(surface_color) # Clear for each test. + kwargs["closed"] = closed + expected_color = line_color if closed else surface_color + + bounds_rect = self.draw_aalines(**kwargs) + + self.assertEqual(surface.get_at(pos), expected_color) + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_aalines__valid_color_formats(self): + """Ensures draw aalines accepts different color formats.""" + green_color = pygame.Color("green") + surface_color = pygame.Color("black") + surface = pygame.Surface((3, 4)) + pos = (1, 1) + kwargs = { + "surface": surface, + "color": None, + "closed": False, + "points": (pos, (2, 1)), + "blend": 0, + } + greens = ( + (0, 255, 0), + (0, 255, 0, 255), + surface.map_rgb(green_color), + green_color, + ) + + for color in greens: + surface.fill(surface_color) # Clear for each test. + kwargs["color"] = color + + if isinstance(color, int): + expected_color = surface.unmap_rgb(color) + else: + expected_color = green_color + + bounds_rect = self.draw_aalines(**kwargs) + + self.assertEqual(surface.get_at(pos), expected_color) + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_aalines__invalid_color_formats(self): + """Ensures draw aalines handles invalid color formats correctly.""" + kwargs = { + "surface": pygame.Surface((4, 3)), + "color": None, + "closed": False, + "points": ((1, 1), (1, 2)), + "blend": 0, + } + + for expected_color in (2.3, self): + kwargs["color"] = expected_color + + with self.assertRaises(TypeError): + bounds_rect = self.draw_aalines(**kwargs) + + def test_aalines__color(self): + """Tests if the aalines drawn are the correct color. + + Draws aalines around the border of the given surface and checks if all + borders of the surface only contain the given color. + """ + for surface in self._create_surfaces(): + for expected_color in self.COLORS: + self.draw_aalines(surface, expected_color, True, corners(surface)) + + for pos, color in border_pos_and_color(surface): + self.assertEqual(color, expected_color, "pos={}".format(pos)) + + def test_aalines__gaps(self): + """Tests if the aalines drawn contain any gaps. + + Draws aalines around the border of the given surface and checks if + all borders of the surface contain any gaps. + + See: #512 + """ + expected_color = (255, 255, 255) + for surface in self._create_surfaces(): + self.draw_aalines(surface, expected_color, True, corners(surface)) + + for pos, color in border_pos_and_color(surface): + self.assertEqual(color, expected_color, "pos={}".format(pos)) + + def test_aalines__bounding_rect(self): + """Ensures draw aalines returns the correct bounding rect. + + Tests lines with endpoints on and off the surface and blending + enabled and disabled. + """ + line_color = pygame.Color("red") + surf_color = pygame.Color("blue") + width = height = 30 + # Using a rect to help manage where the lines are drawn. + pos_rect = pygame.Rect((0, 0), (width, height)) + + # Testing surfaces of different sizes. One larger than the pos_rect + # and one smaller (to test lines that span the surface). + for size in ((width + 5, height + 5), (width - 5, height - 5)): + surface = pygame.Surface(size, 0, 32) + surf_rect = surface.get_rect() + + # Move pos_rect to different positions to test line endpoints on + # and off the surface. + for pos in rect_corners_mids_and_center(surf_rect): + pos_rect.center = pos + # Shape: Triangle (if closed), ^ caret (if not closed). + pts = (pos_rect.midleft, pos_rect.midtop, pos_rect.midright) + pos = pts[0] # Rect position if nothing drawn. + + for blend in (False, True): # Test non-blending and blending. + for closed in (True, False): + surface.fill(surf_color) # Clear for each test. + + bounding_rect = self.draw_aalines( + surface, line_color, closed, pts, blend + ) + + # Calculating the expected_rect after the lines are + # drawn (it uses what is actually drawn). + expected_rect = create_bounding_rect(surface, surf_color, pos) + + self.assertEqual(bounding_rect, expected_rect) + + def test_aalines__surface_clip(self): + """Ensures draw aalines respects a surface's clip area.""" + surfw = surfh = 30 + aaline_color = pygame.Color("red") + surface_color = pygame.Color("green") + surface = pygame.Surface((surfw, surfh)) + surface.fill(surface_color) + + clip_rect = pygame.Rect((0, 0), (11, 11)) + clip_rect.center = surface.get_rect().center + pos_rect = clip_rect.copy() # Manages the aalines's pos. + + # Test centering the pos_rect along the clip rect's edge to allow for + # drawing the aalines over the clip_rect's bounds. + for center in rect_corners_mids_and_center(clip_rect): + pos_rect.center = center + pts = (pos_rect.midtop, pos_rect.center, pos_rect.midbottom) + + for closed in (True, False): # Test closed and not closed. + for blend in (0, 1): # Test non-blending and blending. + # Get the expected points by drawing the aalines without + # the clip area set. + surface.set_clip(None) + surface.fill(surface_color) + self.draw_aalines(surface, aaline_color, closed, pts, blend) + + # Need to get the points that are NOT surface_color due to + # the way blend=0 uses the color black to antialias. + expected_pts = get_color_points( + surface, surface_color, clip_rect, False + ) + + # Clear the surface and set the clip area. Redraw the + # aalines and check that only the clip area is modified. + surface.fill(surface_color) + surface.set_clip(clip_rect) + + self.draw_aalines(surface, aaline_color, closed, pts, blend) + + surface.lock() # For possible speed up. + + # Check all the surface points to ensure the expected_pts + # are not surface_color. + for pt in ((x, y) for x in range(surfw) for y in range(surfh)): + if pt in expected_pts: + self.assertNotEqual(surface.get_at(pt), surface_color, pt) + else: + self.assertEqual(surface.get_at(pt), surface_color, pt) + + surface.unlock() + + +# Commented out to avoid cluttering the test output. Add back in if draw_py +# ever fully supports drawing aalines. +# class PythonDrawAALinesTest(AALinesMixin, PythonDrawTestCase): +# """Test draw_py module function aalines. +# +# This class inherits the general tests from AALinesMixin. It is also the +# class to add any draw_py.draw_aalines specific tests to. +# """ + + +class DrawAALinesTest(AALinesMixin, DrawTestCase): + """Test draw module function aalines. + + This class inherits the general tests from AALinesMixin. It is also the + class to add any draw.aalines specific tests to. + """ + + +### Polygon Testing ########################################################### + +SQUARE = ([0, 0], [3, 0], [3, 3], [0, 3]) +DIAMOND = [(1, 3), (3, 5), (5, 3), (3, 1)] +CROSS = ( + [2, 0], + [4, 0], + [4, 2], + [6, 2], + [6, 4], + [4, 4], + [4, 6], + [2, 6], + [2, 4], + [0, 4], + [0, 2], + [2, 2], +) + + +class DrawPolygonMixin(object): + """Mixin tests for drawing polygons. + + This class contains all the general polygon drawing tests. + """ + + def setUp(self): + self.surface = pygame.Surface((20, 20)) + + def test_polygon__args(self): + """Ensures draw polygon accepts the correct args.""" + bounds_rect = self.draw_polygon( + pygame.Surface((3, 3)), (0, 10, 0, 50), ((0, 0), (1, 1), (2, 2)), 1 + ) + + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_polygon__args_without_width(self): + """Ensures draw polygon accepts the args without a width.""" + bounds_rect = self.draw_polygon( + pygame.Surface((2, 2)), (0, 0, 0, 50), ((0, 0), (1, 1), (2, 2)) + ) + + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_polygon__kwargs(self): + """Ensures draw polygon accepts the correct kwargs + with and without a width arg. + """ + surface = pygame.Surface((4, 4)) + color = pygame.Color("yellow") + points = ((0, 0), (1, 1), (2, 2)) + kwargs_list = [ + {"surface": surface, "color": color, "points": points, "width": 1}, + {"surface": surface, "color": color, "points": points}, + ] + + for kwargs in kwargs_list: + bounds_rect = self.draw_polygon(**kwargs) + + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_polygon__kwargs_order_independent(self): + """Ensures draw polygon's kwargs are not order dependent.""" + bounds_rect = self.draw_polygon( + color=(10, 20, 30), + surface=pygame.Surface((3, 2)), + width=0, + points=((0, 1), (1, 2), (2, 3)), + ) + + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_polygon__args_missing(self): + """Ensures draw polygon detects any missing required args.""" + surface = pygame.Surface((1, 1)) + color = pygame.Color("blue") + + with self.assertRaises(TypeError): + bounds_rect = self.draw_polygon(surface, color) + + with self.assertRaises(TypeError): + bounds_rect = self.draw_polygon(surface) + + with self.assertRaises(TypeError): + bounds_rect = self.draw_polygon() + + def test_polygon__kwargs_missing(self): + """Ensures draw polygon detects any missing required kwargs.""" + kwargs = { + "surface": pygame.Surface((1, 2)), + "color": pygame.Color("red"), + "points": ((2, 1), (2, 2), (2, 3)), + "width": 1, + } + + for name in ("points", "color", "surface"): + invalid_kwargs = dict(kwargs) + invalid_kwargs.pop(name) # Pop from a copy. + + with self.assertRaises(TypeError): + bounds_rect = self.draw_polygon(**invalid_kwargs) + + def test_polygon__arg_invalid_types(self): + """Ensures draw polygon detects invalid arg types.""" + surface = pygame.Surface((2, 2)) + color = pygame.Color("blue") + points = ((0, 1), (1, 2), (1, 3)) + + with self.assertRaises(TypeError): + # Invalid width. + bounds_rect = self.draw_polygon(surface, color, points, "1") + + with self.assertRaises(TypeError): + # Invalid points. + bounds_rect = self.draw_polygon(surface, color, (1, 2, 3)) + + with self.assertRaises(TypeError): + # Invalid color. + bounds_rect = self.draw_polygon(surface, 2.3, points) + + with self.assertRaises(TypeError): + # Invalid surface. + bounds_rect = self.draw_polygon((1, 2, 3, 4), color, points) + + def test_polygon__kwarg_invalid_types(self): + """Ensures draw polygon detects invalid kwarg types.""" + surface = pygame.Surface((3, 3)) + color = pygame.Color("green") + points = ((0, 0), (1, 0), (2, 0)) + width = 1 + kwargs_list = [ + { + "surface": pygame.Surface, # Invalid surface. + "color": color, + "points": points, + "width": width, + }, + { + "surface": surface, + "color": 2.3, # Invalid color. + "points": points, + "width": width, + }, + { + "surface": surface, + "color": color, + "points": ((1,), (1,), (1,)), # Invalid points. + "width": width, + }, + {"surface": surface, "color": color, "points": points, "width": 1.2}, + ] # Invalid width. + + for kwargs in kwargs_list: + with self.assertRaises(TypeError): + bounds_rect = self.draw_polygon(**kwargs) + + def test_polygon__kwarg_invalid_name(self): + """Ensures draw polygon detects invalid kwarg names.""" + surface = pygame.Surface((2, 3)) + color = pygame.Color("cyan") + points = ((1, 1), (1, 2), (1, 3)) + kwargs_list = [ + { + "surface": surface, + "color": color, + "points": points, + "width": 1, + "invalid": 1, + }, + {"surface": surface, "color": color, "points": points, "invalid": 1}, + ] + + for kwargs in kwargs_list: + with self.assertRaises(TypeError): + bounds_rect = self.draw_polygon(**kwargs) + + def test_polygon__args_and_kwargs(self): + """Ensures draw polygon accepts a combination of args/kwargs""" + surface = pygame.Surface((3, 1)) + color = (255, 255, 0, 0) + points = ((0, 1), (1, 2), (2, 3)) + width = 0 + kwargs = {"surface": surface, "color": color, "points": points, "width": width} + + for name in ("surface", "color", "points", "width"): + kwargs.pop(name) + + if "surface" == name: + bounds_rect = self.draw_polygon(surface, **kwargs) + elif "color" == name: + bounds_rect = self.draw_polygon(surface, color, **kwargs) + elif "points" == name: + bounds_rect = self.draw_polygon(surface, color, points, **kwargs) + else: + bounds_rect = self.draw_polygon(surface, color, points, width, **kwargs) + + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_polygon__valid_width_values(self): + """Ensures draw polygon accepts different width values.""" + surface_color = pygame.Color("white") + surface = pygame.Surface((3, 4)) + color = (10, 20, 30, 255) + kwargs = { + "surface": surface, + "color": color, + "points": ((1, 1), (2, 1), (2, 2), (1, 2)), + "width": None, + } + pos = kwargs["points"][0] + + for width in (-100, -10, -1, 0, 1, 10, 100): + surface.fill(surface_color) # Clear for each test. + kwargs["width"] = width + expected_color = color if width >= 0 else surface_color + + bounds_rect = self.draw_polygon(**kwargs) + + self.assertEqual(surface.get_at(pos), expected_color) + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_polygon__valid_points_format(self): + """Ensures draw polygon accepts different points formats.""" + expected_color = (10, 20, 30, 255) + surface_color = pygame.Color("white") + surface = pygame.Surface((3, 4)) + kwargs = { + "surface": surface, + "color": expected_color, + "points": None, + "width": 0, + } + + # The point type can be a tuple/list/Vector2. + point_types = ( + (tuple, tuple, tuple, tuple), # all tuples + (list, list, list, list), # all lists + (Vector2, Vector2, Vector2, Vector2), # all Vector2s + (list, Vector2, tuple, Vector2), + ) # mix + + # The point values can be ints or floats. + point_values = ( + ((1, 1), (2, 1), (2, 2), (1, 2)), + ((1, 1), (2.2, 1), (2.1, 2.2), (1, 2.1)), + ) + + # Each sequence of points can be a tuple or a list. + seq_types = (tuple, list) + + for point_type in point_types: + for values in point_values: + check_pos = values[0] + points = [point_type[i](pt) for i, pt in enumerate(values)] + + for seq_type in seq_types: + surface.fill(surface_color) # Clear for each test. + kwargs["points"] = seq_type(points) + + bounds_rect = self.draw_polygon(**kwargs) + + self.assertEqual(surface.get_at(check_pos), expected_color) + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_polygon__invalid_points_formats(self): + """Ensures draw polygon handles invalid points formats correctly.""" + kwargs = { + "surface": pygame.Surface((4, 4)), + "color": pygame.Color("red"), + "points": None, + "width": 0, + } + + points_fmts = ( + ((1, 1), (2, 1), (2,)), # Too few coords. + ((1, 1), (2, 1), (2, 2, 2)), # Too many coords. + ((1, 1), (2, 1), (2, "2")), # Wrong type. + ((1, 1), (2, 1), set([2, 3])), # Wrong type. + ((1, 1), (2, 1), dict(((2, 2), (3, 3)))), # Wrong type. + set(((1, 1), (2, 1), (2, 2), (1, 2))), # Wrong type. + dict(((1, 1), (2, 2), (3, 3), (4, 4))), + ) # Wrong type. + + for points in points_fmts: + kwargs["points"] = points + + with self.assertRaises(TypeError): + bounds_rect = self.draw_polygon(**kwargs) + + def test_polygon__invalid_points_values(self): + """Ensures draw polygon handles invalid points values correctly.""" + kwargs = { + "surface": pygame.Surface((4, 4)), + "color": pygame.Color("red"), + "points": None, + "width": 0, + } + + points_fmts = ( + tuple(), # Too few points. + ((1, 1),), # Too few points. + ((1, 1), (2, 1)), + ) # Too few points. + + for points in points_fmts: + for seq_type in (tuple, list): # Test as tuples and lists. + kwargs["points"] = seq_type(points) + + with self.assertRaises(ValueError): + bounds_rect = self.draw_polygon(**kwargs) + + def test_polygon__valid_color_formats(self): + """Ensures draw polygon accepts different color formats.""" + green_color = pygame.Color("green") + surface_color = pygame.Color("black") + surface = pygame.Surface((3, 4)) + kwargs = { + "surface": surface, + "color": None, + "points": ((1, 1), (2, 1), (2, 2), (1, 2)), + "width": 0, + } + pos = kwargs["points"][0] + greens = ( + (0, 255, 0), + (0, 255, 0, 255), + surface.map_rgb(green_color), + green_color, + ) + + for color in greens: + surface.fill(surface_color) # Clear for each test. + kwargs["color"] = color + + if isinstance(color, int): + expected_color = surface.unmap_rgb(color) + else: + expected_color = green_color + + bounds_rect = self.draw_polygon(**kwargs) + + self.assertEqual(surface.get_at(pos), expected_color) + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_polygon__invalid_color_formats(self): + """Ensures draw polygon handles invalid color formats correctly.""" + kwargs = { + "surface": pygame.Surface((4, 3)), + "color": None, + "points": ((1, 1), (2, 1), (2, 2), (1, 2)), + "width": 0, + } + + for expected_color in (2.3, self): + kwargs["color"] = expected_color + + with self.assertRaises(TypeError): + bounds_rect = self.draw_polygon(**kwargs) + + def test_draw_square(self): + self.draw_polygon(self.surface, RED, SQUARE, 0) + # note : there is a discussion (#234) if draw.polygon should include or + # not the right or lower border; here we stick with current behavior, + # eg include those borders ... + for x in range(4): + for y in range(4): + self.assertEqual(self.surface.get_at((x, y)), RED) + + def test_draw_diamond(self): + pygame.draw.rect(self.surface, RED, (0, 0, 10, 10), 0) + self.draw_polygon(self.surface, GREEN, DIAMOND, 0) + # this diamond shape is equivalent to its four corners, plus inner square + for x, y in DIAMOND: + self.assertEqual(self.surface.get_at((x, y)), GREEN, msg=str((x, y))) + for x in range(2, 5): + for y in range(2, 5): + self.assertEqual(self.surface.get_at((x, y)), GREEN) + + def test_1_pixel_high_or_wide_shapes(self): + # 1. one-pixel-high, filled + pygame.draw.rect(self.surface, RED, (0, 0, 10, 10), 0) + self.draw_polygon(self.surface, GREEN, [(x, 2) for x, _y in CROSS], 0) + cross_size = 6 # the maximum x or y coordinate of the cross + for x in range(cross_size + 1): + self.assertEqual(self.surface.get_at((x, 1)), RED) + self.assertEqual(self.surface.get_at((x, 2)), GREEN) + self.assertEqual(self.surface.get_at((x, 3)), RED) + pygame.draw.rect(self.surface, RED, (0, 0, 10, 10), 0) + # 2. one-pixel-high, not filled + self.draw_polygon(self.surface, GREEN, [(x, 5) for x, _y in CROSS], 1) + for x in range(cross_size + 1): + self.assertEqual(self.surface.get_at((x, 4)), RED) + self.assertEqual(self.surface.get_at((x, 5)), GREEN) + self.assertEqual(self.surface.get_at((x, 6)), RED) + pygame.draw.rect(self.surface, RED, (0, 0, 10, 10), 0) + # 3. one-pixel-wide, filled + self.draw_polygon(self.surface, GREEN, [(3, y) for _x, y in CROSS], 0) + for y in range(cross_size + 1): + self.assertEqual(self.surface.get_at((2, y)), RED) + self.assertEqual(self.surface.get_at((3, y)), GREEN) + self.assertEqual(self.surface.get_at((4, y)), RED) + pygame.draw.rect(self.surface, RED, (0, 0, 10, 10), 0) + # 4. one-pixel-wide, not filled + self.draw_polygon(self.surface, GREEN, [(4, y) for _x, y in CROSS], 1) + for y in range(cross_size + 1): + self.assertEqual(self.surface.get_at((3, y)), RED) + self.assertEqual(self.surface.get_at((4, y)), GREEN) + self.assertEqual(self.surface.get_at((5, y)), RED) + + def test_draw_symetric_cross(self): + """non-regression on issue #234 : x and y where handled inconsistently. + + Also, the result is/was different whether we fill or not the polygon. + """ + # 1. case width = 1 (not filled: `polygon` calls internally the `lines` function) + pygame.draw.rect(self.surface, RED, (0, 0, 10, 10), 0) + self.draw_polygon(self.surface, GREEN, CROSS, 1) + inside = [(x, 3) for x in range(1, 6)] + [(3, y) for y in range(1, 6)] + for x in range(10): + for y in range(10): + if (x, y) in inside: + self.assertEqual(self.surface.get_at((x, y)), RED) + elif (x in range(2, 5) and y < 7) or (y in range(2, 5) and x < 7): + # we are on the border of the cross: + self.assertEqual(self.surface.get_at((x, y)), GREEN) + else: + # we are outside + self.assertEqual(self.surface.get_at((x, y)), RED) + + # 2. case width = 0 (filled; this is the example from #234) + pygame.draw.rect(self.surface, RED, (0, 0, 10, 10), 0) + self.draw_polygon(self.surface, GREEN, CROSS, 0) + inside = [(x, 3) for x in range(1, 6)] + [(3, y) for y in range(1, 6)] + for x in range(10): + for y in range(10): + if (x in range(2, 5) and y < 7) or (y in range(2, 5) and x < 7): + # we are on the border of the cross: + self.assertEqual( + self.surface.get_at((x, y)), GREEN, msg=str((x, y)) + ) + else: + # we are outside + self.assertEqual(self.surface.get_at((x, y)), RED) + + def test_illumine_shape(self): + """non-regression on issue #313""" + rect = pygame.Rect((0, 0, 20, 20)) + path_data = [ + (0, 0), + (rect.width - 1, 0), # upper border + (rect.width - 5, 5 - 1), + (5 - 1, 5 - 1), # upper inner + (5 - 1, rect.height - 5), + (0, rect.height - 1), + ] # lower diagonal + # The shape looks like this (the numbers are the indices of path_data) + + # 0**********************1 <-- upper border + # *********************** + # ********************** + # ********************* + # ****3**************2 <-- upper inner border + # ***** + # ***** (more lines here) + # ***** + # ****4 + # **** + # *** + # ** + # 5 + # + + # the current bug is that the "upper inner" line is not drawn, but only + # if 4 or some lower corner exists + pygame.draw.rect(self.surface, RED, (0, 0, 20, 20), 0) + + # 1. First without the corners 4 & 5 + self.draw_polygon(self.surface, GREEN, path_data[:4], 0) + for x in range(20): + self.assertEqual(self.surface.get_at((x, 0)), GREEN) # upper border + for x in range(4, rect.width - 5 + 1): + self.assertEqual(self.surface.get_at((x, 4)), GREEN) # upper inner + + # 2. with the corners 4 & 5 + pygame.draw.rect(self.surface, RED, (0, 0, 20, 20), 0) + self.draw_polygon(self.surface, GREEN, path_data, 0) + for x in range(4, rect.width - 5 + 1): + self.assertEqual(self.surface.get_at((x, 4)), GREEN) # upper inner + + def test_invalid_points(self): + self.assertRaises( + TypeError, + lambda: self.draw_polygon( + self.surface, RED, ((0, 0), (0, 20), (20, 20), 20), 0 + ), + ) + + def test_polygon__bounding_rect(self): + """Ensures draw polygon returns the correct bounding rect. + + Tests polygons on and off the surface and a range of width/thickness + values. + """ + polygon_color = pygame.Color("red") + surf_color = pygame.Color("black") + min_width = min_height = 5 + max_width = max_height = 7 + sizes = ((min_width, min_height), (max_width, max_height)) + surface = pygame.Surface((20, 20), 0, 32) + surf_rect = surface.get_rect() + # Make a rect that is bigger than the surface to help test drawing + # polygons off and partially off the surface. + big_rect = surf_rect.inflate(min_width * 2 + 1, min_height * 2 + 1) + + for pos in rect_corners_mids_and_center( + surf_rect + ) + rect_corners_mids_and_center(big_rect): + # A rect (pos_rect) is used to help create and position the + # polygon. Each of this rect's position attributes will be set to + # the pos value. + for attr in RECT_POSITION_ATTRIBUTES: + # Test using different rect sizes and thickness values. + for width, height in sizes: + pos_rect = pygame.Rect((0, 0), (width, height)) + setattr(pos_rect, attr, pos) + # Points form a triangle with no fully + # horizontal/vertical lines. + vertices = ( + pos_rect.midleft, + pos_rect.midtop, + pos_rect.bottomright, + ) + + for thickness in range(4): + surface.fill(surf_color) # Clear for each test. + + bounding_rect = self.draw_polygon( + surface, polygon_color, vertices, thickness + ) + + # Calculating the expected_rect after the polygon + # is drawn (it uses what is actually drawn). + expected_rect = create_bounding_rect( + surface, surf_color, vertices[0] + ) + + self.assertEqual( + bounding_rect, + expected_rect, + "thickness={}".format(thickness), + ) + + def test_polygon__surface_clip(self): + """Ensures draw polygon respects a surface's clip area. + + Tests drawing the polygon filled and unfilled. + """ + surfw = surfh = 30 + polygon_color = pygame.Color("red") + surface_color = pygame.Color("green") + surface = pygame.Surface((surfw, surfh)) + surface.fill(surface_color) + + clip_rect = pygame.Rect((0, 0), (8, 10)) + clip_rect.center = surface.get_rect().center + pos_rect = clip_rect.copy() # Manages the polygon's pos. + + for width in (0, 1): # Filled and unfilled. + # Test centering the polygon along the clip rect's edge. + for center in rect_corners_mids_and_center(clip_rect): + # Get the expected points by drawing the polygon without the + # clip area set. + pos_rect.center = center + vertices = ( + pos_rect.topleft, + pos_rect.topright, + pos_rect.bottomright, + pos_rect.bottomleft, + ) + surface.set_clip(None) + surface.fill(surface_color) + self.draw_polygon(surface, polygon_color, vertices, width) + expected_pts = get_color_points(surface, polygon_color, clip_rect) + + # Clear the surface and set the clip area. Redraw the polygon + # and check that only the clip area is modified. + surface.fill(surface_color) + surface.set_clip(clip_rect) + + self.draw_polygon(surface, polygon_color, vertices, width) + + surface.lock() # For possible speed up. + + # Check all the surface points to ensure only the expected_pts + # are the polygon_color. + for pt in ((x, y) for x in range(surfw) for y in range(surfh)): + if pt in expected_pts: + expected_color = polygon_color + else: + expected_color = surface_color + + self.assertEqual(surface.get_at(pt), expected_color, pt) + + surface.unlock() + + +class DrawPolygonTest(DrawPolygonMixin, DrawTestCase): + """Test draw module function polygon. + + This class inherits the general tests from DrawPolygonMixin. It is also + the class to add any draw.polygon specific tests to. + """ + + +# Commented out to avoid cluttering the test output. Add back in if draw_py +# ever fully supports drawing polygons. +# @unittest.skip('draw_py.draw_polygon not fully supported yet') +# class PythonDrawPolygonTest(DrawPolygonMixin, PythonDrawTestCase): +# """Test draw_py module function draw_polygon. +# +# This class inherits the general tests from DrawPolygonMixin. It is also +# the class to add any draw_py.draw_polygon specific tests to. +# """ + + +### Rect Testing ############################################################## + + +class DrawRectMixin(object): + """Mixin tests for drawing rects. + + This class contains all the general rect drawing tests. + """ + + def test_rect__args(self): + """Ensures draw rect accepts the correct args.""" + bounds_rect = self.draw_rect( + pygame.Surface((2, 2)), + (20, 10, 20, 150), + pygame.Rect((0, 0), (1, 1)), + 2, + 1, + 2, + 3, + 4, + 5, + ) + + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_rect__args_without_width(self): + """Ensures draw rect accepts the args without a width and borders.""" + bounds_rect = self.draw_rect( + pygame.Surface((3, 5)), (0, 0, 0, 255), pygame.Rect((0, 0), (1, 1)) + ) + + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_rect__kwargs(self): + """Ensures draw rect accepts the correct kwargs + with and without a width and border_radius arg. + """ + kwargs_list = [ + { + "surface": pygame.Surface((5, 5)), + "color": pygame.Color("red"), + "rect": pygame.Rect((0, 0), (1, 2)), + "width": 1, + "border_radius": 10, + "border_top_left_radius": 5, + "border_top_right_radius": 20, + "border_bottom_left_radius": 15, + "border_bottom_right_radius": 0, + }, + { + "surface": pygame.Surface((1, 2)), + "color": (0, 100, 200), + "rect": (0, 0, 1, 1), + }, + ] + + for kwargs in kwargs_list: + bounds_rect = self.draw_rect(**kwargs) + + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_rect__kwargs_order_independent(self): + """Ensures draw rect's kwargs are not order dependent.""" + bounds_rect = self.draw_rect( + color=(0, 1, 2), + border_radius=10, + surface=pygame.Surface((2, 3)), + border_top_left_radius=5, + width=-2, + border_top_right_radius=20, + border_bottom_right_radius=0, + rect=pygame.Rect((0, 0), (0, 0)), + border_bottom_left_radius=15, + ) + + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_rect__args_missing(self): + """Ensures draw rect detects any missing required args.""" + surface = pygame.Surface((1, 1)) + + with self.assertRaises(TypeError): + bounds_rect = self.draw_rect(surface, pygame.Color("white")) + + with self.assertRaises(TypeError): + bounds_rect = self.draw_rect(surface) + + with self.assertRaises(TypeError): + bounds_rect = self.draw_rect() + + def test_rect__kwargs_missing(self): + """Ensures draw rect detects any missing required kwargs.""" + kwargs = { + "surface": pygame.Surface((1, 3)), + "color": pygame.Color("red"), + "rect": pygame.Rect((0, 0), (2, 2)), + "width": 5, + "border_radius": 10, + "border_top_left_radius": 5, + "border_top_right_radius": 20, + "border_bottom_left_radius": 15, + "border_bottom_right_radius": 0, + } + + for name in ("rect", "color", "surface"): + invalid_kwargs = dict(kwargs) + invalid_kwargs.pop(name) # Pop from a copy. + + with self.assertRaises(TypeError): + bounds_rect = self.draw_rect(**invalid_kwargs) + + def test_rect__arg_invalid_types(self): + """Ensures draw rect detects invalid arg types.""" + surface = pygame.Surface((3, 3)) + color = pygame.Color("white") + rect = pygame.Rect((1, 1), (1, 1)) + + with self.assertRaises(TypeError): + # Invalid border_bottom_right_radius. + bounds_rect = self.draw_rect( + surface, color, rect, 2, border_bottom_right_radius="rad" + ) + + with self.assertRaises(TypeError): + # Invalid border_bottom_left_radius. + bounds_rect = self.draw_rect( + surface, color, rect, 2, border_bottom_left_radius="rad" + ) + + with self.assertRaises(TypeError): + # Invalid border_top_right_radius. + bounds_rect = self.draw_rect( + surface, color, rect, 2, border_top_right_radius="rad" + ) + + with self.assertRaises(TypeError): + # Invalid border_top_left_radius. + bounds_rect = self.draw_rect( + surface, color, rect, 2, border_top_left_radius="draw" + ) + + with self.assertRaises(TypeError): + # Invalid border_radius. + bounds_rect = self.draw_rect(surface, color, rect, 2, "rad") + + with self.assertRaises(TypeError): + # Invalid width. + bounds_rect = self.draw_rect(surface, color, rect, "2", 4) + + with self.assertRaises(TypeError): + # Invalid rect. + bounds_rect = self.draw_rect(surface, color, (1, 2, 3), 2, 6) + + with self.assertRaises(TypeError): + # Invalid color. + bounds_rect = self.draw_rect(surface, 2.3, rect, 3, 8) + + with self.assertRaises(TypeError): + # Invalid surface. + bounds_rect = self.draw_rect(rect, color, rect, 4, 10) + + def test_rect__kwarg_invalid_types(self): + """Ensures draw rect detects invalid kwarg types.""" + surface = pygame.Surface((2, 3)) + color = pygame.Color("red") + rect = pygame.Rect((0, 0), (1, 1)) + kwargs_list = [ + { + "surface": pygame.Surface, # Invalid surface. + "color": color, + "rect": rect, + "width": 1, + "border_radius": 10, + "border_top_left_radius": 5, + "border_top_right_radius": 20, + "border_bottom_left_radius": 15, + "border_bottom_right_radius": 0, + }, + { + "surface": surface, + "color": 2.3, # Invalid color. + "rect": rect, + "width": 1, + "border_radius": 10, + "border_top_left_radius": 5, + "border_top_right_radius": 20, + "border_bottom_left_radius": 15, + "border_bottom_right_radius": 0, + }, + { + "surface": surface, + "color": color, + "rect": (1, 1, 2), # Invalid rect. + "width": 1, + "border_radius": 10, + "border_top_left_radius": 5, + "border_top_right_radius": 20, + "border_bottom_left_radius": 15, + "border_bottom_right_radius": 0, + }, + { + "surface": surface, + "color": color, + "rect": rect, + "width": 1.1, # Invalid width. + "border_radius": 10, + "border_top_left_radius": 5, + "border_top_right_radius": 20, + "border_bottom_left_radius": 15, + "border_bottom_right_radius": 0, + }, + { + "surface": surface, + "color": color, + "rect": rect, + "width": 1, + "border_radius": 10.5, # Invalid border_radius. + "border_top_left_radius": 5, + "border_top_right_radius": 20, + "border_bottom_left_radius": 15, + "border_bottom_right_radius": 0, + }, + { + "surface": surface, + "color": color, + "rect": rect, + "width": 1, + "border_radius": 10, + "border_top_left_radius": 5.5, # Invalid top_left_radius. + "border_top_right_radius": 20, + "border_bottom_left_radius": 15, + "border_bottom_right_radius": 0, + }, + { + "surface": surface, + "color": color, + "rect": rect, + "width": 1, + "border_radius": 10, + "border_top_left_radius": 5, + "border_top_right_radius": "a", # Invalid top_right_radius. + "border_bottom_left_radius": 15, + "border_bottom_right_radius": 0, + }, + { + "surface": surface, + "color": color, + "rect": rect, + "width": 1, + "border_radius": 10, + "border_top_left_radius": 5, + "border_top_right_radius": 20, + "border_bottom_left_radius": "c", # Invalid bottom_left_radius + "border_bottom_right_radius": 0, + }, + { + "surface": surface, + "color": color, + "rect": rect, + "width": 1, + "border_radius": 10, + "border_top_left_radius": 5, + "border_top_right_radius": 20, + "border_bottom_left_radius": 15, + "border_bottom_right_radius": "d", # Invalid bottom_right. + }, + ] + + for kwargs in kwargs_list: + with self.assertRaises(TypeError): + bounds_rect = self.draw_rect(**kwargs) + + def test_rect__kwarg_invalid_name(self): + """Ensures draw rect detects invalid kwarg names.""" + surface = pygame.Surface((2, 1)) + color = pygame.Color("green") + rect = pygame.Rect((0, 0), (3, 3)) + kwargs_list = [ + { + "surface": surface, + "color": color, + "rect": rect, + "width": 1, + "border_radius": 10, + "border_top_left_radius": 5, + "border_top_right_radius": 20, + "border_bottom_left_radius": 15, + "border_bottom_right_radius": 0, + "invalid": 1, + }, + {"surface": surface, "color": color, "rect": rect, "invalid": 1}, + ] + + for kwargs in kwargs_list: + with self.assertRaises(TypeError): + bounds_rect = self.draw_rect(**kwargs) + + def test_rect__args_and_kwargs(self): + """Ensures draw rect accepts a combination of args/kwargs""" + surface = pygame.Surface((3, 1)) + color = (255, 255, 255, 0) + rect = pygame.Rect((1, 0), (2, 5)) + width = 0 + kwargs = {"surface": surface, "color": color, "rect": rect, "width": width} + + for name in ("surface", "color", "rect", "width"): + kwargs.pop(name) + + if "surface" == name: + bounds_rect = self.draw_rect(surface, **kwargs) + elif "color" == name: + bounds_rect = self.draw_rect(surface, color, **kwargs) + elif "rect" == name: + bounds_rect = self.draw_rect(surface, color, rect, **kwargs) + else: + bounds_rect = self.draw_rect(surface, color, rect, width, **kwargs) + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_rect__valid_width_values(self): + """Ensures draw rect accepts different width values.""" + pos = (1, 1) + surface_color = pygame.Color("black") + surface = pygame.Surface((3, 4)) + color = (1, 2, 3, 255) + kwargs = { + "surface": surface, + "color": color, + "rect": pygame.Rect(pos, (2, 2)), + "width": None, + } + + for width in (-1000, -10, -1, 0, 1, 10, 1000): + surface.fill(surface_color) # Clear for each test. + kwargs["width"] = width + expected_color = color if width >= 0 else surface_color + + bounds_rect = self.draw_rect(**kwargs) + + self.assertEqual(surface.get_at(pos), expected_color) + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_rect__valid_rect_formats(self): + """Ensures draw rect accepts different rect formats.""" + pos = (1, 1) + expected_color = pygame.Color("yellow") + surface_color = pygame.Color("black") + surface = pygame.Surface((3, 4)) + kwargs = {"surface": surface, "color": expected_color, "rect": None, "width": 0} + rects = ( + pygame.Rect(pos, (1, 1)), + (pos, (2, 2)), + (pos[0], pos[1], 3, 3), + [pos, (2.1, 2.2)], + ) + + for rect in rects: + surface.fill(surface_color) # Clear for each test. + kwargs["rect"] = rect + + bounds_rect = self.draw_rect(**kwargs) + + self.assertEqual(surface.get_at(pos), expected_color) + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_rect__invalid_rect_formats(self): + """Ensures draw rect handles invalid rect formats correctly.""" + kwargs = { + "surface": pygame.Surface((4, 4)), + "color": pygame.Color("red"), + "rect": None, + "width": 0, + } + + invalid_fmts = ( + [], + [1], + [1, 2], + [1, 2, 3], + [1, 2, 3, 4, 5], + set([1, 2, 3, 4]), + [1, 2, 3, "4"], + ) + + for rect in invalid_fmts: + kwargs["rect"] = rect + + with self.assertRaises(TypeError): + bounds_rect = self.draw_rect(**kwargs) + + def test_rect__valid_color_formats(self): + """Ensures draw rect accepts different color formats.""" + pos = (1, 1) + red_color = pygame.Color("red") + surface_color = pygame.Color("black") + surface = pygame.Surface((3, 4)) + kwargs = { + "surface": surface, + "color": None, + "rect": pygame.Rect(pos, (1, 1)), + "width": 3, + } + reds = ((255, 0, 0), (255, 0, 0, 255), surface.map_rgb(red_color), red_color) + + for color in reds: + surface.fill(surface_color) # Clear for each test. + kwargs["color"] = color + + if isinstance(color, int): + expected_color = surface.unmap_rgb(color) + else: + expected_color = red_color + + bounds_rect = self.draw_rect(**kwargs) + + self.assertEqual(surface.get_at(pos), expected_color) + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_rect__invalid_color_formats(self): + """Ensures draw rect handles invalid color formats correctly.""" + pos = (1, 1) + surface = pygame.Surface((3, 4)) + kwargs = { + "surface": surface, + "color": None, + "rect": pygame.Rect(pos, (1, 1)), + "width": 1, + } + + for expected_color in (2.3, self): + kwargs["color"] = expected_color + + with self.assertRaises(TypeError): + bounds_rect = self.draw_rect(**kwargs) + + def test_rect__fill(self): + self.surf_w, self.surf_h = self.surf_size = (320, 200) + self.surf = pygame.Surface(self.surf_size, pygame.SRCALPHA) + self.color = (1, 13, 24, 205) + rect = pygame.Rect(10, 10, 25, 20) + drawn = self.draw_rect(self.surf, self.color, rect, 0) + + self.assertEqual(drawn, rect) + + # Should be colored where it's supposed to be + for pt in test_utils.rect_area_pts(rect): + color_at_pt = self.surf.get_at(pt) + + self.assertEqual(color_at_pt, self.color) + + # And not where it shouldn't + for pt in test_utils.rect_outer_bounds(rect): + color_at_pt = self.surf.get_at(pt) + + self.assertNotEqual(color_at_pt, self.color) + + # Issue #310: Cannot draw rectangles that are 1 pixel high + bgcolor = pygame.Color("black") + self.surf.fill(bgcolor) + hrect = pygame.Rect(1, 1, self.surf_w - 2, 1) + vrect = pygame.Rect(1, 3, 1, self.surf_h - 4) + + drawn = self.draw_rect(self.surf, self.color, hrect, 0) + + self.assertEqual(drawn, hrect) + + x, y = hrect.topleft + w, h = hrect.size + + self.assertEqual(self.surf.get_at((x - 1, y)), bgcolor) + self.assertEqual(self.surf.get_at((x + w, y)), bgcolor) + for i in range(x, x + w): + self.assertEqual(self.surf.get_at((i, y)), self.color) + + drawn = self.draw_rect(self.surf, self.color, vrect, 0) + + self.assertEqual(drawn, vrect) + + x, y = vrect.topleft + w, h = vrect.size + + self.assertEqual(self.surf.get_at((x, y - 1)), bgcolor) + self.assertEqual(self.surf.get_at((x, y + h)), bgcolor) + for i in range(y, y + h): + self.assertEqual(self.surf.get_at((x, i)), self.color) + + def test_rect__one_pixel_lines(self): + self.surf = pygame.Surface((320, 200), pygame.SRCALPHA) + self.color = (1, 13, 24, 205) + + rect = pygame.Rect(10, 10, 56, 20) + + drawn = self.draw_rect(self.surf, self.color, rect, 1) + + self.assertEqual(drawn, rect) + + # Should be colored where it's supposed to be + for pt in test_utils.rect_perimeter_pts(drawn): + color_at_pt = self.surf.get_at(pt) + + self.assertEqual(color_at_pt, self.color) + + # And not where it shouldn't + for pt in test_utils.rect_outer_bounds(drawn): + color_at_pt = self.surf.get_at(pt) + + self.assertNotEqual(color_at_pt, self.color) + + def test_rect__draw_line_width(self): + surface = pygame.Surface((100, 100)) + surface.fill("black") + color = pygame.Color(255, 255, 255) + rect_width = 80 + rect_height = 50 + line_width = 10 + pygame.draw.rect( + surface, color, pygame.Rect(0, 0, rect_width, rect_height), line_width + ) + for i in range(line_width): + self.assertEqual(surface.get_at((i, i)), color) + self.assertEqual(surface.get_at((rect_width - i - 1, i)), color) + self.assertEqual(surface.get_at((i, rect_height - i - 1)), color) + self.assertEqual( + surface.get_at((rect_width - i - 1, rect_height - i - 1)), color + ) + self.assertEqual(surface.get_at((line_width, line_width)), (0, 0, 0)) + self.assertEqual( + surface.get_at((rect_width - line_width - 1, line_width)), (0, 0, 0) + ) + self.assertEqual( + surface.get_at((line_width, rect_height - line_width - 1)), (0, 0, 0) + ) + self.assertEqual( + surface.get_at((rect_width - line_width - 1, rect_height - line_width - 1)), + (0, 0, 0), + ) + + def test_rect__bounding_rect(self): + """Ensures draw rect returns the correct bounding rect. + + Tests rects on and off the surface and a range of width/thickness + values. + """ + rect_color = pygame.Color("red") + surf_color = pygame.Color("black") + min_width = min_height = 5 + max_width = max_height = 7 + sizes = ((min_width, min_height), (max_width, max_height)) + surface = pygame.Surface((20, 20), 0, 32) + surf_rect = surface.get_rect() + # Make a rect that is bigger than the surface to help test drawing + # rects off and partially off the surface. + big_rect = surf_rect.inflate(min_width * 2 + 1, min_height * 2 + 1) + + for pos in rect_corners_mids_and_center( + surf_rect + ) + rect_corners_mids_and_center(big_rect): + # Each of the rect's position attributes will be set to the pos + # value. + for attr in RECT_POSITION_ATTRIBUTES: + # Test using different rect sizes and thickness values. + for width, height in sizes: + rect = pygame.Rect((0, 0), (width, height)) + setattr(rect, attr, pos) + + for thickness in range(4): + surface.fill(surf_color) # Clear for each test. + + bounding_rect = self.draw_rect( + surface, rect_color, rect, thickness + ) + + # Calculating the expected_rect after the rect is + # drawn (it uses what is actually drawn). + expected_rect = create_bounding_rect( + surface, surf_color, rect.topleft + ) + + self.assertEqual( + bounding_rect, + expected_rect, + "thickness={}".format(thickness), + ) + + def test_rect__surface_clip(self): + """Ensures draw rect respects a surface's clip area. + + Tests drawing the rect filled and unfilled. + """ + surfw = surfh = 30 + rect_color = pygame.Color("red") + surface_color = pygame.Color("green") + surface = pygame.Surface((surfw, surfh)) + surface.fill(surface_color) + + clip_rect = pygame.Rect((0, 0), (8, 10)) + clip_rect.center = surface.get_rect().center + test_rect = clip_rect.copy() # Manages the rect's pos. + + for width in (0, 1): # Filled and unfilled. + # Test centering the rect along the clip rect's edge. + for center in rect_corners_mids_and_center(clip_rect): + # Get the expected points by drawing the rect without the + # clip area set. + test_rect.center = center + surface.set_clip(None) + surface.fill(surface_color) + self.draw_rect(surface, rect_color, test_rect, width) + expected_pts = get_color_points(surface, rect_color, clip_rect) + + # Clear the surface and set the clip area. Redraw the rect + # and check that only the clip area is modified. + surface.fill(surface_color) + surface.set_clip(clip_rect) + + self.draw_rect(surface, rect_color, test_rect, width) + + surface.lock() # For possible speed up. + + # Check all the surface points to ensure only the expected_pts + # are the rect_color. + for pt in ((x, y) for x in range(surfw) for y in range(surfh)): + if pt in expected_pts: + expected_color = rect_color + else: + expected_color = surface_color + + self.assertEqual(surface.get_at(pt), expected_color, pt) + + surface.unlock() + + +class DrawRectTest(DrawRectMixin, DrawTestCase): + """Test draw module function rect. + + This class inherits the general tests from DrawRectMixin. It is also the + class to add any draw.rect specific tests to. + """ + + +# Commented out to avoid cluttering the test output. Add back in if draw_py +# ever properly supports drawing rects. +# @unittest.skip('draw_py.draw_rect not supported yet') +# class PythonDrawRectTest(DrawRectMixin, PythonDrawTestCase): +# """Test draw_py module function draw_rect. +# +# This class inherits the general tests from DrawRectMixin. It is also the +# class to add any draw_py.draw_rect specific tests to. +# """ + + +### Circle Testing ############################################################ + + +class DrawCircleMixin(object): + """Mixin tests for drawing circles. + + This class contains all the general circle drawing tests. + """ + + def test_circle__args(self): + """Ensures draw circle accepts the correct args.""" + bounds_rect = self.draw_circle( + pygame.Surface((3, 3)), (0, 10, 0, 50), (0, 0), 3, 1, 1, 0, 1, 1 + ) + + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_circle__args_without_width(self): + """Ensures draw circle accepts the args without a width and + quadrants.""" + bounds_rect = self.draw_circle(pygame.Surface((2, 2)), (0, 0, 0, 50), (1, 1), 1) + + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_circle__args_with_negative_width(self): + """Ensures draw circle accepts the args with negative width.""" + bounds_rect = self.draw_circle( + pygame.Surface((2, 2)), (0, 0, 0, 50), (1, 1), 1, -1 + ) + + self.assertIsInstance(bounds_rect, pygame.Rect) + self.assertEqual(bounds_rect, pygame.Rect(1, 1, 0, 0)) + + def test_circle__args_with_width_gt_radius(self): + """Ensures draw circle accepts the args with width > radius.""" + bounds_rect = self.draw_circle( + pygame.Surface((2, 2)), (0, 0, 0, 50), (1, 1), 2, 3, 0, 0, 0, 0 + ) + + self.assertIsInstance(bounds_rect, pygame.Rect) + self.assertEqual(bounds_rect, pygame.Rect(0, 0, 2, 2)) + + def test_circle__kwargs(self): + """Ensures draw circle accepts the correct kwargs + with and without a width and quadrant arguments. + """ + kwargs_list = [ + { + "surface": pygame.Surface((4, 4)), + "color": pygame.Color("yellow"), + "center": (2, 2), + "radius": 2, + "width": 1, + "draw_top_right": True, + "draw_top_left": True, + "draw_bottom_left": False, + "draw_bottom_right": True, + }, + { + "surface": pygame.Surface((2, 1)), + "color": (0, 10, 20), + "center": (1, 1), + "radius": 1, + }, + ] + + for kwargs in kwargs_list: + bounds_rect = self.draw_circle(**kwargs) + + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_circle__kwargs_order_independent(self): + """Ensures draw circle's kwargs are not order dependent.""" + bounds_rect = self.draw_circle( + draw_top_right=False, + color=(10, 20, 30), + surface=pygame.Surface((3, 2)), + width=0, + draw_bottom_left=False, + center=(1, 0), + draw_bottom_right=False, + radius=2, + draw_top_left=True, + ) + + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_circle__args_missing(self): + """Ensures draw circle detects any missing required args.""" + surface = pygame.Surface((1, 1)) + color = pygame.Color("blue") + + with self.assertRaises(TypeError): + bounds_rect = self.draw_circle(surface, color, (0, 0)) + + with self.assertRaises(TypeError): + bounds_rect = self.draw_circle(surface, color) + + with self.assertRaises(TypeError): + bounds_rect = self.draw_circle(surface) + + with self.assertRaises(TypeError): + bounds_rect = self.draw_circle() + + def test_circle__kwargs_missing(self): + """Ensures draw circle detects any missing required kwargs.""" + kwargs = { + "surface": pygame.Surface((1, 2)), + "color": pygame.Color("red"), + "center": (1, 0), + "radius": 2, + "width": 1, + "draw_top_right": False, + "draw_top_left": False, + "draw_bottom_left": False, + "draw_bottom_right": True, + } + + for name in ("radius", "center", "color", "surface"): + invalid_kwargs = dict(kwargs) + invalid_kwargs.pop(name) # Pop from a copy. + + with self.assertRaises(TypeError): + bounds_rect = self.draw_circle(**invalid_kwargs) + + def test_circle__arg_invalid_types(self): + """Ensures draw circle detects invalid arg types.""" + surface = pygame.Surface((2, 2)) + color = pygame.Color("blue") + center = (1, 1) + radius = 1 + + with self.assertRaises(TypeError): + # Invalid draw_top_right. + bounds_rect = self.draw_circle( + surface, color, center, radius, 1, "a", 1, 1, 1 + ) + + with self.assertRaises(TypeError): + # Invalid draw_top_left. + bounds_rect = self.draw_circle( + surface, color, center, radius, 1, 1, "b", 1, 1 + ) + + with self.assertRaises(TypeError): + # Invalid draw_bottom_left. + bounds_rect = self.draw_circle( + surface, color, center, radius, 1, 1, 1, "c", 1 + ) + + with self.assertRaises(TypeError): + # Invalid draw_bottom_right. + bounds_rect = self.draw_circle( + surface, color, center, radius, 1, 1, 1, 1, "d" + ) + + with self.assertRaises(TypeError): + # Invalid width. + bounds_rect = self.draw_circle(surface, color, center, radius, "1") + + with self.assertRaises(TypeError): + # Invalid radius. + bounds_rect = self.draw_circle(surface, color, center, "2") + + with self.assertRaises(TypeError): + # Invalid center. + bounds_rect = self.draw_circle(surface, color, (1, 2, 3), radius) + + with self.assertRaises(TypeError): + # Invalid color. + bounds_rect = self.draw_circle(surface, 2.3, center, radius) + + with self.assertRaises(TypeError): + # Invalid surface. + bounds_rect = self.draw_circle((1, 2, 3, 4), color, center, radius) + + def test_circle__kwarg_invalid_types(self): + """Ensures draw circle detects invalid kwarg types.""" + surface = pygame.Surface((3, 3)) + color = pygame.Color("green") + center = (0, 1) + radius = 1 + width = 1 + quadrant = 1 + kwargs_list = [ + { + "surface": pygame.Surface, # Invalid surface. + "color": color, + "center": center, + "radius": radius, + "width": width, + "draw_top_right": True, + "draw_top_left": True, + "draw_bottom_left": True, + "draw_bottom_right": True, + }, + { + "surface": surface, + "color": 2.3, # Invalid color. + "center": center, + "radius": radius, + "width": width, + "draw_top_right": True, + "draw_top_left": True, + "draw_bottom_left": True, + "draw_bottom_right": True, + }, + { + "surface": surface, + "color": color, + "center": (1, 1, 1), # Invalid center. + "radius": radius, + "width": width, + "draw_top_right": True, + "draw_top_left": True, + "draw_bottom_left": True, + "draw_bottom_right": True, + }, + { + "surface": surface, + "color": color, + "center": center, + "radius": "1", # Invalid radius. + "width": width, + "draw_top_right": True, + "draw_top_left": True, + "draw_bottom_left": True, + "draw_bottom_right": True, + }, + { + "surface": surface, + "color": color, + "center": center, + "radius": radius, + "width": 1.2, # Invalid width. + "draw_top_right": True, + "draw_top_left": True, + "draw_bottom_left": True, + "draw_bottom_right": True, + }, + { + "surface": surface, + "color": color, + "center": center, + "radius": radius, + "width": width, + "draw_top_right": "True", # Invalid draw_top_right + "draw_top_left": True, + "draw_bottom_left": True, + "draw_bottom_right": True, + }, + { + "surface": surface, + "color": color, + "center": center, + "radius": radius, + "width": width, + "draw_top_right": True, + "draw_top_left": "True", # Invalid draw_top_left + "draw_bottom_left": True, + "draw_bottom_right": True, + }, + { + "surface": surface, + "color": color, + "center": center, + "radius": radius, + "width": width, + "draw_top_right": True, + "draw_top_left": True, + "draw_bottom_left": 3.14, # Invalid draw_bottom_left + "draw_bottom_right": True, + }, + { + "surface": surface, + "color": color, + "center": center, + "radius": radius, + "width": width, + "draw_top_right": True, + "draw_top_left": True, + "draw_bottom_left": True, + "draw_bottom_right": "quadrant", # Invalid draw_bottom_right + }, + ] + + for kwargs in kwargs_list: + with self.assertRaises(TypeError): + bounds_rect = self.draw_circle(**kwargs) + + def test_circle__kwarg_invalid_name(self): + """Ensures draw circle detects invalid kwarg names.""" + surface = pygame.Surface((2, 3)) + color = pygame.Color("cyan") + center = (0, 0) + radius = 2 + kwargs_list = [ + { + "surface": surface, + "color": color, + "center": center, + "radius": radius, + "width": 1, + "quadrant": 1, + "draw_top_right": True, + "draw_top_left": True, + "draw_bottom_left": True, + "draw_bottom_right": True, + }, + { + "surface": surface, + "color": color, + "center": center, + "radius": radius, + "invalid": 1, + }, + ] + + for kwargs in kwargs_list: + with self.assertRaises(TypeError): + bounds_rect = self.draw_circle(**kwargs) + + def test_circle__args_and_kwargs(self): + """Ensures draw circle accepts a combination of args/kwargs""" + surface = pygame.Surface((3, 1)) + color = (255, 255, 0, 0) + center = (1, 0) + radius = 2 + width = 0 + draw_top_right = True + draw_top_left = False + draw_bottom_left = False + draw_bottom_right = True + kwargs = { + "surface": surface, + "color": color, + "center": center, + "radius": radius, + "width": width, + "draw_top_right": True, + "draw_top_left": True, + "draw_bottom_left": True, + "draw_bottom_right": True, + } + + for name in ( + "surface", + "color", + "center", + "radius", + "width", + "draw_top_right", + "draw_top_left", + "draw_bottom_left", + "draw_bottom_right", + ): + kwargs.pop(name) + + if "surface" == name: + bounds_rect = self.draw_circle(surface, **kwargs) + elif "color" == name: + bounds_rect = self.draw_circle(surface, color, **kwargs) + elif "center" == name: + bounds_rect = self.draw_circle(surface, color, center, **kwargs) + elif "radius" == name: + bounds_rect = self.draw_circle(surface, color, center, radius, **kwargs) + elif "width" == name: + bounds_rect = self.draw_circle( + surface, color, center, radius, width, **kwargs + ) + elif "draw_top_right" == name: + bounds_rect = self.draw_circle( + surface, color, center, radius, width, draw_top_right, **kwargs + ) + elif "draw_top_left" == name: + bounds_rect = self.draw_circle( + surface, + color, + center, + radius, + width, + draw_top_right, + draw_top_left, + **kwargs + ) + elif "draw_bottom_left" == name: + bounds_rect = self.draw_circle( + surface, + color, + center, + radius, + width, + draw_top_right, + draw_top_left, + draw_bottom_left, + **kwargs + ) + else: + bounds_rect = self.draw_circle( + surface, + color, + center, + radius, + width, + draw_top_right, + draw_top_left, + draw_bottom_left, + draw_bottom_right, + **kwargs + ) + + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_circle__valid_width_values(self): + """Ensures draw circle accepts different width values.""" + center = (2, 2) + radius = 1 + pos = (center[0] - radius, center[1]) + surface_color = pygame.Color("white") + surface = pygame.Surface((3, 4)) + color = (10, 20, 30, 255) + kwargs = { + "surface": surface, + "color": color, + "center": center, + "radius": radius, + "width": None, + "draw_top_right": True, + "draw_top_left": True, + "draw_bottom_left": True, + "draw_bottom_right": True, + } + + for width in (-100, -10, -1, 0, 1, 10, 100): + surface.fill(surface_color) # Clear for each test. + kwargs["width"] = width + expected_color = color if width >= 0 else surface_color + + bounds_rect = self.draw_circle(**kwargs) + + self.assertEqual(surface.get_at(pos), expected_color) + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_circle__valid_radius_values(self): + """Ensures draw circle accepts different radius values.""" + pos = center = (2, 2) + surface_color = pygame.Color("white") + surface = pygame.Surface((3, 4)) + color = (10, 20, 30, 255) + kwargs = { + "surface": surface, + "color": color, + "center": center, + "radius": None, + "width": 0, + "draw_top_right": True, + "draw_top_left": True, + "draw_bottom_left": True, + "draw_bottom_right": True, + } + + for radius in (-10, -1, 0, 1, 10): + surface.fill(surface_color) # Clear for each test. + kwargs["radius"] = radius + expected_color = color if radius > 0 else surface_color + + bounds_rect = self.draw_circle(**kwargs) + + self.assertEqual(surface.get_at(pos), expected_color) + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_circle__valid_center_formats(self): + """Ensures draw circle accepts different center formats.""" + expected_color = pygame.Color("red") + surface_color = pygame.Color("black") + surface = pygame.Surface((4, 4)) + kwargs = { + "surface": surface, + "color": expected_color, + "center": None, + "radius": 1, + "width": 0, + "draw_top_right": True, + "draw_top_left": True, + "draw_bottom_left": True, + "draw_bottom_right": True, + } + x, y = 2, 2 # center position + + # The center values can be ints or floats. + for center in ((x, y), (x + 0.1, y), (x, y + 0.1), (x + 0.1, y + 0.1)): + # The center type can be a tuple/list/Vector2. + for seq_type in (tuple, list, Vector2): + surface.fill(surface_color) # Clear for each test. + kwargs["center"] = seq_type(center) + + bounds_rect = self.draw_circle(**kwargs) + + self.assertEqual(surface.get_at((x, y)), expected_color) + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_circle__valid_color_formats(self): + """Ensures draw circle accepts different color formats.""" + center = (2, 2) + radius = 1 + pos = (center[0] - radius, center[1]) + green_color = pygame.Color("green") + surface_color = pygame.Color("black") + surface = pygame.Surface((3, 4)) + kwargs = { + "surface": surface, + "color": None, + "center": center, + "radius": radius, + "width": 0, + "draw_top_right": True, + "draw_top_left": True, + "draw_bottom_left": True, + "draw_bottom_right": True, + } + greens = ( + (0, 255, 0), + (0, 255, 0, 255), + surface.map_rgb(green_color), + green_color, + ) + + for color in greens: + surface.fill(surface_color) # Clear for each test. + kwargs["color"] = color + + if isinstance(color, int): + expected_color = surface.unmap_rgb(color) + else: + expected_color = green_color + + bounds_rect = self.draw_circle(**kwargs) + + self.assertEqual(surface.get_at(pos), expected_color) + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_circle__invalid_color_formats(self): + """Ensures draw circle handles invalid color formats correctly.""" + kwargs = { + "surface": pygame.Surface((4, 3)), + "color": None, + "center": (1, 2), + "radius": 1, + "width": 0, + "draw_top_right": True, + "draw_top_left": True, + "draw_bottom_left": True, + "draw_bottom_right": True, + } + + for expected_color in (2.3, self): + kwargs["color"] = expected_color + + with self.assertRaises(TypeError): + bounds_rect = self.draw_circle(**kwargs) + + def test_circle__floats(self): + """Ensure that floats are accepted.""" + draw.circle( + surface=pygame.Surface((4, 4)), + color=(255, 255, 127), + center=(1.5, 1.5), + radius=1.3, + width=0, + draw_top_right=True, + draw_top_left=True, + draw_bottom_left=True, + draw_bottom_right=True, + ) + + draw.circle( + surface=pygame.Surface((4, 4)), + color=(255, 255, 127), + center=Vector2(1.5, 1.5), + radius=1.3, + width=0, + draw_top_right=True, + draw_top_left=True, + draw_bottom_left=True, + draw_bottom_right=True, + ) + + draw.circle(pygame.Surface((2, 2)), (0, 0, 0, 50), (1.3, 1.3), 1.2) + + # def test_circle_clip(self): + # """ maybe useful to help work out circle clip algorithm.""" + # MAX = max + # MIN = min + # posx=30 + # posy=15 + # radius=1 + # l=29 + # t=14 + # r=30 + # b=16 + # clip_rect_x=0 + # clip_rect_y=0 + # clip_rect_w=30 + # clip_rect_h=30 + + # l = MAX(posx - radius, clip_rect_x) + # t = MAX(posy - radius, clip_rect_y) + # r = MIN(posx + radius, clip_rect_x + clip_rect_w) + # b = MIN(posy + radius, clip_rect_y + clip_rect_h) + + # l, t, MAX(r - l, 0), MAX(b - t, 0) + + def test_circle__bounding_rect(self): + """Ensures draw circle returns the correct bounding rect. + + Tests circles on and off the surface and a range of width/thickness + values. + """ + circle_color = pygame.Color("red") + surf_color = pygame.Color("black") + max_radius = 3 + surface = pygame.Surface((30, 30), 0, 32) + surf_rect = surface.get_rect() + # Make a rect that is bigger than the surface to help test drawing + # circles off and partially off the surface. Make this rect such that + # when centering the test circle on one of its corners, the circle is + # drawn fully off the test surface, but a rect bounding the circle + # would still overlap with the test surface. + big_rect = surf_rect.inflate(max_radius * 2 - 1, max_radius * 2 - 1) + + for pos in rect_corners_mids_and_center( + surf_rect + ) + rect_corners_mids_and_center(big_rect): + # Test using different radius and thickness values. + for radius in range(max_radius + 1): + for thickness in range(radius + 1): + surface.fill(surf_color) # Clear for each test. + + bounding_rect = self.draw_circle( + surface, circle_color, pos, radius, thickness + ) + + # Calculating the expected_rect after the circle is + # drawn (it uses what is actually drawn). + expected_rect = create_bounding_rect(surface, surf_color, pos) + # print("pos:%s:, radius:%s:, thickness:%s:" % (pos, radius, thickness)) + self.assertEqual(bounding_rect, expected_rect) + + def test_circle_negative_radius(self): + """Ensures negative radius circles return zero sized bounding rect.""" + surf = pygame.Surface((200, 200)) + color = (0, 0, 0, 50) + center = surf.get_height() // 2, surf.get_height() // 2 + + bounding_rect = self.draw_circle(surf, color, center, radius=-1, width=1) + self.assertEqual(bounding_rect.size, (0, 0)) + + def test_circle_zero_radius(self): + """Ensures zero radius circles does not draw a center pixel. + + NOTE: This is backwards incompatible behaviour with 1.9.x. + """ + surf = pygame.Surface((200, 200)) + circle_color = pygame.Color("red") + surf_color = pygame.Color("black") + surf.fill((0, 0, 0)) + center = (100, 100) + radius = 0 + width = 1 + + bounding_rect = self.draw_circle(surf, circle_color, center, radius, width) + expected_rect = create_bounding_rect(surf, surf_color, center) + self.assertEqual(bounding_rect, expected_rect) + self.assertEqual(bounding_rect, pygame.Rect(100, 100, 0, 0)) + + def test_circle__surface_clip(self): + """Ensures draw circle respects a surface's clip area. + + Tests drawing the circle filled and unfilled. + """ + surfw = surfh = 25 + circle_color = pygame.Color("red") + surface_color = pygame.Color("green") + surface = pygame.Surface((surfw, surfh)) + surface.fill(surface_color) + + clip_rect = pygame.Rect((0, 0), (10, 10)) + clip_rect.center = surface.get_rect().center + radius = clip_rect.w // 2 + 1 + + for width in (0, 1): # Filled and unfilled. + # Test centering the circle along the clip rect's edge. + for center in rect_corners_mids_and_center(clip_rect): + # Get the expected points by drawing the circle without the + # clip area set. + surface.set_clip(None) + surface.fill(surface_color) + self.draw_circle(surface, circle_color, center, radius, width) + expected_pts = get_color_points(surface, circle_color, clip_rect) + + # Clear the surface and set the clip area. Redraw the circle + # and check that only the clip area is modified. + surface.fill(surface_color) + surface.set_clip(clip_rect) + + self.draw_circle(surface, circle_color, center, radius, width) + + surface.lock() # For possible speed up. + + # Check all the surface points to ensure only the expected_pts + # are the circle_color. + for pt in ((x, y) for x in range(surfw) for y in range(surfh)): + if pt in expected_pts: + expected_color = circle_color + else: + expected_color = surface_color + + self.assertEqual(surface.get_at(pt), expected_color, pt) + + surface.unlock() + + def test_circle_shape(self): + """Ensures there are no holes in the circle, and no overdrawing. + + Tests drawing a thick circle. + Measures the distance of the drawn pixels from the circle center. + """ + surfw = surfh = 100 + circle_color = pygame.Color("red") + surface_color = pygame.Color("green") + surface = pygame.Surface((surfw, surfh)) + surface.fill(surface_color) + + (cx, cy) = center = (50, 50) + radius = 45 + width = 25 + + dest_rect = self.draw_circle(surface, circle_color, center, radius, width) + + for pt in test_utils.rect_area_pts(dest_rect): + x, y = pt + sqr_distance = (x - cx) ** 2 + (y - cy) ** 2 + if (radius - width + 1) ** 2 < sqr_distance < (radius - 1) ** 2: + self.assertEqual(surface.get_at(pt), circle_color) + if ( + sqr_distance < (radius - width - 1) ** 2 + or sqr_distance > (radius + 1) ** 2 + ): + self.assertEqual(surface.get_at(pt), surface_color) + + def test_circle__diameter(self): + """Ensures draw circle is twice size of radius high and wide.""" + surf = pygame.Surface((200, 200)) + color = (0, 0, 0, 50) + center = surf.get_height() // 2, surf.get_height() // 2 + width = 1 + radius = 6 + for radius in range(1, 65): + bounding_rect = self.draw_circle(surf, color, center, radius, width) + self.assertEqual(bounding_rect.width, radius * 2) + self.assertEqual(bounding_rect.height, radius * 2) + + +class DrawCircleTest(DrawCircleMixin, DrawTestCase): + """Test draw module function circle. + + This class inherits the general tests from DrawCircleMixin. It is also + the class to add any draw.circle specific tests to. + """ + + +# Commented out to avoid cluttering the test output. Add back in if draw_py +# ever properly supports drawing circles. +# @unittest.skip('draw_py.draw_circle not supported yet') +# class PythonDrawCircleTest(DrawCircleMixin, PythonDrawTestCase): +# """Test draw_py module function draw_circle." +# +# This class inherits the general tests from DrawCircleMixin. It is also +# the class to add any draw_py.draw_circle specific tests to. +# """ + + +### Arc Testing ############################################################### + + +class DrawArcMixin(object): + """Mixin tests for drawing arcs. + + This class contains all the general arc drawing tests. + """ + + def test_arc__args(self): + """Ensures draw arc accepts the correct args.""" + bounds_rect = self.draw_arc( + pygame.Surface((3, 3)), (0, 10, 0, 50), (1, 1, 2, 2), 0, 1, 1 + ) + + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_arc__args_without_width(self): + """Ensures draw arc accepts the args without a width.""" + bounds_rect = self.draw_arc( + pygame.Surface((2, 2)), (1, 1, 1, 99), pygame.Rect((0, 0), (2, 2)), 1.1, 2.1 + ) + + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_arc__args_with_negative_width(self): + """Ensures draw arc accepts the args with negative width.""" + bounds_rect = self.draw_arc( + pygame.Surface((3, 3)), (10, 10, 50, 50), (1, 1, 2, 2), 0, 1, -1 + ) + + self.assertIsInstance(bounds_rect, pygame.Rect) + self.assertEqual(bounds_rect, pygame.Rect(1, 1, 0, 0)) + + def test_arc__args_with_width_gt_radius(self): + """Ensures draw arc accepts the args with + width > rect.w // 2 and width > rect.h // 2. + """ + rect = pygame.Rect((0, 0), (4, 4)) + bounds_rect = self.draw_arc( + pygame.Surface((3, 3)), (10, 10, 50, 50), rect, 0, 45, rect.w // 2 + 1 + ) + + self.assertIsInstance(bounds_rect, pygame.Rect) + + bounds_rect = self.draw_arc( + pygame.Surface((3, 3)), (10, 10, 50, 50), rect, 0, 45, rect.h // 2 + 1 + ) + + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_arc__kwargs(self): + """Ensures draw arc accepts the correct kwargs + with and without a width arg. + """ + kwargs_list = [ + { + "surface": pygame.Surface((4, 4)), + "color": pygame.Color("yellow"), + "rect": pygame.Rect((0, 0), (3, 2)), + "start_angle": 0.5, + "stop_angle": 3, + "width": 1, + }, + { + "surface": pygame.Surface((2, 1)), + "color": (0, 10, 20), + "rect": (0, 0, 2, 2), + "start_angle": 1, + "stop_angle": 3.1, + }, + ] + + for kwargs in kwargs_list: + bounds_rect = self.draw_arc(**kwargs) + + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_arc__kwargs_order_independent(self): + """Ensures draw arc's kwargs are not order dependent.""" + bounds_rect = self.draw_arc( + stop_angle=1, + start_angle=2.2, + color=(1, 2, 3), + surface=pygame.Surface((3, 2)), + width=1, + rect=pygame.Rect((1, 0), (2, 3)), + ) + + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_arc__args_missing(self): + """Ensures draw arc detects any missing required args.""" + surface = pygame.Surface((1, 1)) + color = pygame.Color("red") + rect = pygame.Rect((0, 0), (2, 2)) + + with self.assertRaises(TypeError): + bounds_rect = self.draw_arc(surface, color, rect, 0.1) + + with self.assertRaises(TypeError): + bounds_rect = self.draw_arc(surface, color, rect) + + with self.assertRaises(TypeError): + bounds_rect = self.draw_arc(surface, color) + + with self.assertRaises(TypeError): + bounds_rect = self.draw_arc(surface) + + with self.assertRaises(TypeError): + bounds_rect = self.draw_arc() + + def test_arc__kwargs_missing(self): + """Ensures draw arc detects any missing required kwargs.""" + kwargs = { + "surface": pygame.Surface((1, 2)), + "color": pygame.Color("red"), + "rect": pygame.Rect((1, 0), (2, 2)), + "start_angle": 0.1, + "stop_angle": 2, + "width": 1, + } + + for name in ("stop_angle", "start_angle", "rect", "color", "surface"): + invalid_kwargs = dict(kwargs) + invalid_kwargs.pop(name) # Pop from a copy. + + with self.assertRaises(TypeError): + bounds_rect = self.draw_arc(**invalid_kwargs) + + def test_arc__arg_invalid_types(self): + """Ensures draw arc detects invalid arg types.""" + surface = pygame.Surface((2, 2)) + color = pygame.Color("blue") + rect = pygame.Rect((1, 1), (3, 3)) + + with self.assertRaises(TypeError): + # Invalid width. + bounds_rect = self.draw_arc(surface, color, rect, 0, 1, "1") + + with self.assertRaises(TypeError): + # Invalid stop_angle. + bounds_rect = self.draw_arc(surface, color, rect, 0, "1", 1) + + with self.assertRaises(TypeError): + # Invalid start_angle. + bounds_rect = self.draw_arc(surface, color, rect, "1", 0, 1) + + with self.assertRaises(TypeError): + # Invalid rect. + bounds_rect = self.draw_arc(surface, color, (1, 2, 3, 4, 5), 0, 1, 1) + + with self.assertRaises(TypeError): + # Invalid color. + bounds_rect = self.draw_arc(surface, 2.3, rect, 0, 1, 1) + + with self.assertRaises(TypeError): + # Invalid surface. + bounds_rect = self.draw_arc(rect, color, rect, 0, 1, 1) + + def test_arc__kwarg_invalid_types(self): + """Ensures draw arc detects invalid kwarg types.""" + surface = pygame.Surface((3, 3)) + color = pygame.Color("green") + rect = pygame.Rect((0, 1), (4, 2)) + start = 3 + stop = 4 + kwargs_list = [ + { + "surface": pygame.Surface, # Invalid surface. + "color": color, + "rect": rect, + "start_angle": start, + "stop_angle": stop, + "width": 1, + }, + { + "surface": surface, + "color": 2.3, # Invalid color. + "rect": rect, + "start_angle": start, + "stop_angle": stop, + "width": 1, + }, + { + "surface": surface, + "color": color, + "rect": (0, 0, 0), # Invalid rect. + "start_angle": start, + "stop_angle": stop, + "width": 1, + }, + { + "surface": surface, + "color": color, + "rect": rect, + "start_angle": "1", # Invalid start_angle. + "stop_angle": stop, + "width": 1, + }, + { + "surface": surface, + "color": color, + "rect": rect, + "start_angle": start, + "stop_angle": "1", # Invalid stop_angle. + "width": 1, + }, + { + "surface": surface, + "color": color, + "rect": rect, + "start_angle": start, + "stop_angle": stop, + "width": 1.1, + }, + ] # Invalid width. + + for kwargs in kwargs_list: + with self.assertRaises(TypeError): + bounds_rect = self.draw_arc(**kwargs) + + def test_arc__kwarg_invalid_name(self): + """Ensures draw arc detects invalid kwarg names.""" + surface = pygame.Surface((2, 3)) + color = pygame.Color("cyan") + rect = pygame.Rect((0, 1), (2, 2)) + start = 0.9 + stop = 2.3 + kwargs_list = [ + { + "surface": surface, + "color": color, + "rect": rect, + "start_angle": start, + "stop_angle": stop, + "width": 1, + "invalid": 1, + }, + { + "surface": surface, + "color": color, + "rect": rect, + "start_angle": start, + "stop_angle": stop, + "invalid": 1, + }, + ] + + for kwargs in kwargs_list: + with self.assertRaises(TypeError): + bounds_rect = self.draw_arc(**kwargs) + + def test_arc__args_and_kwargs(self): + """Ensures draw arc accepts a combination of args/kwargs""" + surface = pygame.Surface((3, 1)) + color = (255, 255, 0, 0) + rect = pygame.Rect((1, 0), (2, 3)) + start = 0.6 + stop = 2 + width = 1 + kwargs = { + "surface": surface, + "color": color, + "rect": rect, + "start_angle": start, + "stop_angle": stop, + "width": width, + } + + for name in ("surface", "color", "rect", "start_angle", "stop_angle"): + kwargs.pop(name) + + if "surface" == name: + bounds_rect = self.draw_arc(surface, **kwargs) + elif "color" == name: + bounds_rect = self.draw_arc(surface, color, **kwargs) + elif "rect" == name: + bounds_rect = self.draw_arc(surface, color, rect, **kwargs) + elif "start_angle" == name: + bounds_rect = self.draw_arc(surface, color, rect, start, **kwargs) + elif "stop_angle" == name: + bounds_rect = self.draw_arc(surface, color, rect, start, stop, **kwargs) + else: + bounds_rect = self.draw_arc( + surface, color, rect, start, stop, width, **kwargs + ) + + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_arc__valid_width_values(self): + """Ensures draw arc accepts different width values.""" + arc_color = pygame.Color("yellow") + surface_color = pygame.Color("white") + surface = pygame.Surface((6, 6)) + rect = pygame.Rect((0, 0), (4, 4)) + rect.center = surface.get_rect().center + pos = rect.centerx + 1, rect.centery + 1 + kwargs = { + "surface": surface, + "color": arc_color, + "rect": rect, + "start_angle": 0, + "stop_angle": 7, + "width": None, + } + + for width in (-50, -10, -3, -2, -1, 0, 1, 2, 3, 10, 50): + msg = "width={}".format(width) + surface.fill(surface_color) # Clear for each test. + kwargs["width"] = width + expected_color = arc_color if width > 0 else surface_color + + bounds_rect = self.draw_arc(**kwargs) + + self.assertEqual(surface.get_at(pos), expected_color, msg) + self.assertIsInstance(bounds_rect, pygame.Rect, msg) + + def test_arc__valid_stop_angle_values(self): + """Ensures draw arc accepts different stop_angle values.""" + expected_color = pygame.Color("blue") + surface_color = pygame.Color("white") + surface = pygame.Surface((6, 6)) + rect = pygame.Rect((0, 0), (4, 4)) + rect.center = surface.get_rect().center + pos = rect.centerx, rect.centery + 1 + kwargs = { + "surface": surface, + "color": expected_color, + "rect": rect, + "start_angle": -17, + "stop_angle": None, + "width": 1, + } + + for stop_angle in (-10, -5.5, -1, 0, 1, 5.5, 10): + msg = "stop_angle={}".format(stop_angle) + surface.fill(surface_color) # Clear for each test. + kwargs["stop_angle"] = stop_angle + + bounds_rect = self.draw_arc(**kwargs) + + self.assertEqual(surface.get_at(pos), expected_color, msg) + self.assertIsInstance(bounds_rect, pygame.Rect, msg) + + def test_arc__valid_start_angle_values(self): + """Ensures draw arc accepts different start_angle values.""" + expected_color = pygame.Color("blue") + surface_color = pygame.Color("white") + surface = pygame.Surface((6, 6)) + rect = pygame.Rect((0, 0), (4, 4)) + rect.center = surface.get_rect().center + pos = rect.centerx + 1, rect.centery + 1 + kwargs = { + "surface": surface, + "color": expected_color, + "rect": rect, + "start_angle": None, + "stop_angle": 17, + "width": 1, + } + + for start_angle in (-10.0, -5.5, -1, 0, 1, 5.5, 10.0): + msg = "start_angle={}".format(start_angle) + surface.fill(surface_color) # Clear for each test. + kwargs["start_angle"] = start_angle + + bounds_rect = self.draw_arc(**kwargs) + + self.assertEqual(surface.get_at(pos), expected_color, msg) + self.assertIsInstance(bounds_rect, pygame.Rect, msg) + + def test_arc__valid_rect_formats(self): + """Ensures draw arc accepts different rect formats.""" + expected_color = pygame.Color("red") + surface_color = pygame.Color("black") + surface = pygame.Surface((6, 6)) + rect = pygame.Rect((0, 0), (4, 4)) + rect.center = surface.get_rect().center + pos = rect.centerx + 1, rect.centery + 1 + kwargs = { + "surface": surface, + "color": expected_color, + "rect": None, + "start_angle": 0, + "stop_angle": 7, + "width": 1, + } + rects = (rect, (rect.topleft, rect.size), (rect.x, rect.y, rect.w, rect.h)) + + for rect in rects: + surface.fill(surface_color) # Clear for each test. + kwargs["rect"] = rect + + bounds_rect = self.draw_arc(**kwargs) + + self.assertEqual(surface.get_at(pos), expected_color) + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_arc__valid_color_formats(self): + """Ensures draw arc accepts different color formats.""" + green_color = pygame.Color("green") + surface_color = pygame.Color("black") + surface = pygame.Surface((6, 6)) + rect = pygame.Rect((0, 0), (4, 4)) + rect.center = surface.get_rect().center + pos = rect.centerx + 1, rect.centery + 1 + kwargs = { + "surface": surface, + "color": None, + "rect": rect, + "start_angle": 0, + "stop_angle": 7, + "width": 1, + } + greens = ( + (0, 255, 0), + (0, 255, 0, 255), + surface.map_rgb(green_color), + green_color, + ) + + for color in greens: + surface.fill(surface_color) # Clear for each test. + kwargs["color"] = color + + if isinstance(color, int): + expected_color = surface.unmap_rgb(color) + else: + expected_color = green_color + + bounds_rect = self.draw_arc(**kwargs) + + self.assertEqual(surface.get_at(pos), expected_color) + self.assertIsInstance(bounds_rect, pygame.Rect) + + def test_arc__invalid_color_formats(self): + """Ensures draw arc handles invalid color formats correctly.""" + pos = (1, 1) + surface = pygame.Surface((4, 3)) + kwargs = { + "surface": surface, + "color": None, + "rect": pygame.Rect(pos, (2, 2)), + "start_angle": 5, + "stop_angle": 6.1, + "width": 1, + } + + for expected_color in (2.3, self): + kwargs["color"] = expected_color + + with self.assertRaises(TypeError): + bounds_rect = self.draw_arc(**kwargs) + + def todo_test_arc(self): + """Ensure draw arc works correctly.""" + self.fail() + + def test_arc__bounding_rect(self): + """Ensures draw arc returns the correct bounding rect. + + Tests arcs on and off the surface and a range of width/thickness + values. + """ + arc_color = pygame.Color("red") + surf_color = pygame.Color("black") + min_width = min_height = 5 + max_width = max_height = 7 + sizes = ((min_width, min_height), (max_width, max_height)) + surface = pygame.Surface((20, 20), 0, 32) + surf_rect = surface.get_rect() + # Make a rect that is bigger than the surface to help test drawing + # arcs off and partially off the surface. + big_rect = surf_rect.inflate(min_width * 2 + 1, min_height * 2 + 1) + + # Max angle allows for a full circle to be drawn. + start_angle = 0 + stop_angles = (0, 2, 3, 5, math.ceil(2 * math.pi)) + + for pos in rect_corners_mids_and_center( + surf_rect + ) + rect_corners_mids_and_center(big_rect): + # Each of the arc's rect position attributes will be set to the pos + # value. + for attr in RECT_POSITION_ATTRIBUTES: + # Test using different rect sizes, thickness values and stop + # angles. + for width, height in sizes: + arc_rect = pygame.Rect((0, 0), (width, height)) + setattr(arc_rect, attr, pos) + + for thickness in (0, 1, 2, 3, min(width, height)): + for stop_angle in stop_angles: + surface.fill(surf_color) # Clear for each test. + + bounding_rect = self.draw_arc( + surface, + arc_color, + arc_rect, + start_angle, + stop_angle, + thickness, + ) + + # Calculating the expected_rect after the arc + # is drawn (it uses what is actually drawn). + expected_rect = create_bounding_rect( + surface, surf_color, arc_rect.topleft + ) + + self.assertEqual( + bounding_rect, + expected_rect, + "thickness={}".format(thickness), + ) + + def test_arc__surface_clip(self): + """Ensures draw arc respects a surface's clip area.""" + surfw = surfh = 30 + start = 0.1 + end = 0 # end < start so a full circle will be drawn + arc_color = pygame.Color("red") + surface_color = pygame.Color("green") + surface = pygame.Surface((surfw, surfh)) + surface.fill(surface_color) + + clip_rect = pygame.Rect((0, 0), (11, 11)) + clip_rect.center = surface.get_rect().center + pos_rect = clip_rect.copy() # Manages the arc's pos. + + for thickness in (1, 3): # Different line widths. + # Test centering the arc along the clip rect's edge. + for center in rect_corners_mids_and_center(clip_rect): + # Get the expected points by drawing the arc without the + # clip area set. + pos_rect.center = center + surface.set_clip(None) + surface.fill(surface_color) + self.draw_arc(surface, arc_color, pos_rect, start, end, thickness) + expected_pts = get_color_points(surface, arc_color, clip_rect) + + # Clear the surface and set the clip area. Redraw the arc + # and check that only the clip area is modified. + surface.fill(surface_color) + surface.set_clip(clip_rect) + + self.draw_arc(surface, arc_color, pos_rect, start, end, thickness) + + surface.lock() # For possible speed up. + + # Check all the surface points to ensure only the expected_pts + # are the arc_color. + for pt in ((x, y) for x in range(surfw) for y in range(surfh)): + if pt in expected_pts: + expected_color = arc_color + else: + expected_color = surface_color + + self.assertEqual(surface.get_at(pt), expected_color, pt) + + surface.unlock() + + +class DrawArcTest(DrawArcMixin, DrawTestCase): + """Test draw module function arc. + + This class inherits the general tests from DrawArcMixin. It is also the + class to add any draw.arc specific tests to. + """ + + +# Commented out to avoid cluttering the test output. Add back in if draw_py +# ever properly supports drawing arcs. +# @unittest.skip('draw_py.draw_arc not supported yet') +# class PythonDrawArcTest(DrawArcMixin, PythonDrawTestCase): +# """Test draw_py module function draw_arc. +# +# This class inherits the general tests from DrawArcMixin. It is also the +# class to add any draw_py.draw_arc specific tests to. +# """ + + +### Draw Module Testing ####################################################### + + +class DrawModuleTest(unittest.TestCase): + """General draw module tests.""" + + def test_path_data_validation(self): + """Test validation of multi-point drawing methods. + + See bug #521 + """ + surf = pygame.Surface((5, 5)) + rect = pygame.Rect(0, 0, 5, 5) + bad_values = ( + "text", + b"bytes", + 1 + 1j, # string, bytes, complex, + object(), + (lambda x: x), + ) # object, function + bad_points = list(bad_values) + [(1,), (1, 2, 3)] # wrong tuple length + bad_points.extend((1, v) for v in bad_values) # one wrong value + good_path = [(1, 1), (1, 3), (3, 3), (3, 1)] + # A) draw.lines + check_pts = [(x, y) for x in range(5) for y in range(5)] + + for method, is_polgon in ( + (draw.lines, 0), + (draw.aalines, 0), + (draw.polygon, 1), + ): + for val in bad_values: + # 1. at the beginning + draw.rect(surf, RED, rect, 0) + with self.assertRaises(TypeError): + if is_polgon: + method(surf, GREEN, [val] + good_path, 0) + else: + method(surf, GREEN, True, [val] + good_path) + + # make sure, nothing was drawn : + self.assertTrue(all(surf.get_at(pt) == RED for pt in check_pts)) + + # 2. not at the beginning (was not checked) + draw.rect(surf, RED, rect, 0) + with self.assertRaises(TypeError): + path = good_path[:2] + [val] + good_path[2:] + if is_polgon: + method(surf, GREEN, path, 0) + else: + method(surf, GREEN, True, path) + + # make sure, nothing was drawn : + self.assertTrue(all(surf.get_at(pt) == RED for pt in check_pts)) + + def test_color_validation(self): + surf = pygame.Surface((10, 10)) + colors = 123456, (1, 10, 100), RED, "#ab12df", "red" + points = ((0, 0), (1, 1), (1, 0)) + + # 1. valid colors + for col in colors: + draw.line(surf, col, (0, 0), (1, 1)) + draw.aaline(surf, col, (0, 0), (1, 1)) + draw.aalines(surf, col, True, points) + draw.lines(surf, col, True, points) + draw.arc(surf, col, pygame.Rect(0, 0, 3, 3), 15, 150) + draw.ellipse(surf, col, pygame.Rect(0, 0, 3, 6), 1) + draw.circle(surf, col, (7, 3), 2) + draw.polygon(surf, col, points, 0) + + # 2. invalid colors + for col in (1.256, object(), None): + with self.assertRaises(TypeError): + draw.line(surf, col, (0, 0), (1, 1)) + + with self.assertRaises(TypeError): + draw.aaline(surf, col, (0, 0), (1, 1)) + + with self.assertRaises(TypeError): + draw.aalines(surf, col, True, points) + + with self.assertRaises(TypeError): + draw.lines(surf, col, True, points) + + with self.assertRaises(TypeError): + draw.arc(surf, col, pygame.Rect(0, 0, 3, 3), 15, 150) + + with self.assertRaises(TypeError): + draw.ellipse(surf, col, pygame.Rect(0, 0, 3, 6), 1) + + with self.assertRaises(TypeError): + draw.circle(surf, col, (7, 3), 2) + + with self.assertRaises(TypeError): + draw.polygon(surf, col, points, 0) + + +############################################################################### + + +if __name__ == "__main__": + unittest.main() diff --git a/venv/Lib/site-packages/pygame/tests/event_test.py b/venv/Lib/site-packages/pygame/tests/event_test.py new file mode 100644 index 0000000..8d7dfe0 --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/event_test.py @@ -0,0 +1,840 @@ +import os +import sys +import unittest +import collections + +import pygame + + +EVENT_TYPES = ( + # pygame.NOEVENT, + # pygame.ACTIVEEVENT, + pygame.KEYDOWN, + pygame.KEYUP, + pygame.MOUSEMOTION, + pygame.MOUSEBUTTONDOWN, + pygame.MOUSEBUTTONUP, + pygame.JOYAXISMOTION, + pygame.JOYBALLMOTION, + pygame.JOYHATMOTION, + pygame.JOYBUTTONDOWN, + pygame.JOYBUTTONUP, + pygame.VIDEORESIZE, + pygame.VIDEOEXPOSE, + pygame.QUIT, + pygame.SYSWMEVENT, + pygame.USEREVENT, + # pygame.NUMEVENTS, +) + +EVENT_TEST_PARAMS = collections.defaultdict(dict) +EVENT_TEST_PARAMS.update( + { + pygame.KEYDOWN: {"key": pygame.K_SPACE}, + pygame.KEYUP: {"key": pygame.K_SPACE}, + pygame.MOUSEMOTION: dict(), + pygame.MOUSEBUTTONDOWN: dict(button=1), + pygame.MOUSEBUTTONUP: dict(button=1), + } +) + + +NAMES_AND_EVENTS = ( + ("NoEvent", pygame.NOEVENT), + ("ActiveEvent", pygame.ACTIVEEVENT), + ("KeyDown", pygame.KEYDOWN), + ("KeyUp", pygame.KEYUP), + ("MouseMotion", pygame.MOUSEMOTION), + ("MouseButtonDown", pygame.MOUSEBUTTONDOWN), + ("MouseButtonUp", pygame.MOUSEBUTTONUP), + ("JoyAxisMotion", pygame.JOYAXISMOTION), + ("JoyBallMotion", pygame.JOYBALLMOTION), + ("JoyHatMotion", pygame.JOYHATMOTION), + ("JoyButtonDown", pygame.JOYBUTTONDOWN), + ("JoyButtonUp", pygame.JOYBUTTONUP), + ("VideoResize", pygame.VIDEORESIZE), + ("VideoExpose", pygame.VIDEOEXPOSE), + ("Quit", pygame.QUIT), + ("SysWMEvent", pygame.SYSWMEVENT), + ("MidiIn", pygame.MIDIIN), + ("MidiOut", pygame.MIDIOUT), + ("UserEvent", pygame.USEREVENT), + ("Unknown", 0xFFFF), + ("FingerMotion", pygame.FINGERMOTION), + ("FingerDown", pygame.FINGERDOWN), + ("FingerUp", pygame.FINGERUP), + ("MultiGesture", pygame.MULTIGESTURE), + ("MouseWheel", pygame.MOUSEWHEEL), + ("TextInput", pygame.TEXTINPUT), + ("TextEditing", pygame.TEXTEDITING), + ("ControllerAxisMotion", pygame.CONTROLLERAXISMOTION), + ("ControllerButtonDown", pygame.CONTROLLERBUTTONDOWN), + ("ControllerButtonUp", pygame.CONTROLLERBUTTONUP), + ("ControllerDeviceAdded", pygame.CONTROLLERDEVICEADDED), + ("ControllerDeviceRemoved", pygame.CONTROLLERDEVICEREMOVED), + ("ControllerDeviceMapped", pygame.CONTROLLERDEVICEREMAPPED), + ("DropFile", pygame.DROPFILE), +) + +# Add in any SDL 2.0.4 specific events. +if pygame.get_sdl_version() >= (2, 0, 4): + NAMES_AND_EVENTS += ( + ("AudioDeviceAdded", pygame.AUDIODEVICEADDED), + ("AudioDeviceRemoved", pygame.AUDIODEVICEREMOVED), + ) + +# Add in any SDL 2.0.5 specific events. +if pygame.get_sdl_version() >= (2, 0, 5): + NAMES_AND_EVENTS += ( + ("DropText", pygame.DROPTEXT), + ("DropBegin", pygame.DROPBEGIN), + ("DropComplete", pygame.DROPCOMPLETE), + ) + + +class EventTypeTest(unittest.TestCase): + def test_Event(self): + """Ensure an Event object can be created.""" + e = pygame.event.Event(pygame.USEREVENT, some_attr=1, other_attr="1") + + self.assertEqual(e.some_attr, 1) + self.assertEqual(e.other_attr, "1") + + # Event now uses tp_dictoffset and tp_members: request 62 + # on Motherhamster Bugzilla. + self.assertEqual(e.type, pygame.USEREVENT) + self.assertIs(e.dict, e.__dict__) + + e.some_attr = 12 + + self.assertEqual(e.some_attr, 12) + + e.new_attr = 15 + + self.assertEqual(e.new_attr, 15) + + self.assertRaises(AttributeError, setattr, e, "type", 0) + self.assertRaises(AttributeError, setattr, e, "dict", None) + + # Ensure attributes are visible to dir(), part of the original + # posted request. + d = dir(e) + attrs = ("type", "dict", "__dict__", "some_attr", "other_attr", "new_attr") + + for attr in attrs: + self.assertIn(attr, d) + + def test_as_str(self): + # Bug reported on Pygame mailing list July 24, 2011: + # For Python 3.x str(event) to raises an UnicodeEncodeError when + # an event attribute is a string with a non-ascii character. + try: + str(pygame.event.Event(EVENT_TYPES[0], a="\xed")) + except UnicodeEncodeError: + self.fail("Event object raised exception for non-ascii character") + # Passed. + + +race_condition_notification = """ +This test is dependent on timing. The event queue is cleared in preparation for +tests. There is a small window where outside events from the OS may have effected +results. Try running the test again. +""" + + +class EventModuleArgsTest(unittest.TestCase): + def setUp(self): + pygame.display.init() + pygame.event.clear() + + def tearDown(self): + pygame.display.quit() + + def test_get(self): + pygame.event.get() + pygame.event.get(None) + pygame.event.get(None, True) + + pygame.event.get(pump=False) + pygame.event.get(pump=True) + pygame.event.get(eventtype=None) + pygame.event.get(eventtype=[pygame.KEYUP, pygame.KEYDOWN]) + pygame.event.get(eventtype=pygame.USEREVENT, pump=False) + + def test_clear(self): + pygame.event.clear() + pygame.event.clear(None) + pygame.event.clear(None, True) + + pygame.event.clear(pump=False) + pygame.event.clear(pump=True) + pygame.event.clear(eventtype=None) + pygame.event.clear(eventtype=[pygame.KEYUP, pygame.KEYDOWN]) + pygame.event.clear(eventtype=pygame.USEREVENT, pump=False) + + def test_peek(self): + pygame.event.peek() + pygame.event.peek(None) + pygame.event.peek(None, True) + + pygame.event.peek(pump=False) + pygame.event.peek(pump=True) + pygame.event.peek(eventtype=None) + pygame.event.peek(eventtype=[pygame.KEYUP, pygame.KEYDOWN]) + pygame.event.peek(eventtype=pygame.USEREVENT, pump=False) + + +class EventCustomTypeTest(unittest.TestCase): + """Those tests are special in that they need the _custom_event counter to + be reset before and/or after being run.""" + + def setUp(self): + pygame.quit() + pygame.init() + pygame.display.init() + + def tearDown(self): + pygame.quit() + + def test_custom_type(self): + self.assertEqual(pygame.event.custom_type(), pygame.USEREVENT + 1) + atype = pygame.event.custom_type() + atype2 = pygame.event.custom_type() + + self.assertEqual(atype, atype2 - 1) + + ev = pygame.event.Event(atype) + pygame.event.post(ev) + queue = pygame.event.get(atype) + self.assertEqual(len(queue), 1) + self.assertEqual(queue[0].type, atype) + + def test_custom_type__end_boundary(self): + """Ensure custom_type() raises error when no more custom types. + + The last allowed custom type number should be (pygame.NUMEVENTS - 1). + """ + start = pygame.event.custom_type() + 1 + for i in range(start, pygame.NUMEVENTS): + last = pygame.event.custom_type() + self.assertEqual(last, pygame.NUMEVENTS - 1) + with self.assertRaises(pygame.error): + pygame.event.custom_type() + + def test_custom_type__reset(self): + """Ensure custom events get 'deregistered' by quit().""" + before = pygame.event.custom_type() + self.assertEqual(before, pygame.event.custom_type() - 1) + pygame.quit() + pygame.init() + pygame.display.init() + self.assertEqual(before, pygame.event.custom_type()) + + +class EventModuleTest(unittest.TestCase): + def _assertCountEqual(self, *args, **kwargs): + # Handle method name differences between Python versions. + # Is this still needed? + self.assertCountEqual(*args, **kwargs) + + def _assertExpectedEvents(self, expected, got): + """Find events like expected events, raise on unexpected or missing, + ignore additional event properties if expected properties are present.""" + + # This does greedy matching, don't encode an NP-hard problem + # into your input data, *please* + items_left = got[:] + for expected_element in expected: + for item in items_left: + for key in expected_element.__dict__: + if item.__dict__[key] != expected_element.__dict__[key]: + break + else: + # found item! + items_left.remove(item) + break + else: + raise AssertionError( + "Expected " + + str(expected_element) + + " among remaining events " + + str(items_left) + + " out of " + + str(got) + ) + if len(items_left) > 0: + raise AssertionError("Unexpected Events: " + str(items_left)) + + def setUp(self): + pygame.display.init() + pygame.event.clear() # flush events + + def tearDown(self): + pygame.event.clear() # flush events + pygame.display.quit() + + def test_event_numevents(self): + """Ensures NUMEVENTS does not exceed the maximum SDL number of events.""" + # Ref: https://www.libsdl.org/tmp/SDL/include/SDL_events.h + MAX_SDL_EVENTS = 0xFFFF # SDL_LASTEVENT = 0xFFFF + + self.assertLessEqual(pygame.NUMEVENTS, MAX_SDL_EVENTS) + + def test_event_attribute(self): + e1 = pygame.event.Event(pygame.USEREVENT, attr1="attr1") + self.assertEqual(e1.attr1, "attr1") + + def test_set_blocked(self): + """Ensure events can be blocked from the queue.""" + event = EVENT_TYPES[0] + pygame.event.set_blocked(event) + + self.assertTrue(pygame.event.get_blocked(event)) + + pygame.event.post( + pygame.event.Event(event, **EVENT_TEST_PARAMS[EVENT_TYPES[0]]) + ) + ret = pygame.event.get() + should_be_blocked = [e for e in ret if e.type == event] + + self.assertEqual(should_be_blocked, []) + + def test_set_blocked__event_sequence(self): + """Ensure a sequence of event types can be blocked.""" + event_types = [ + pygame.KEYDOWN, + pygame.KEYUP, + pygame.MOUSEMOTION, + pygame.MOUSEBUTTONDOWN, + pygame.MOUSEBUTTONUP, + ] + + pygame.event.set_blocked(event_types) + + for etype in event_types: + self.assertTrue(pygame.event.get_blocked(etype)) + + def test_set_blocked_all(self): + """Ensure all events can be unblocked at once.""" + pygame.event.set_blocked(None) + + for e in EVENT_TYPES: + self.assertTrue(pygame.event.get_blocked(e)) + + def test_post__and_poll(self): + """Ensure events can be posted to the queue.""" + e1 = pygame.event.Event(pygame.USEREVENT, attr1="attr1") + pygame.event.post(e1) + posted_event = pygame.event.poll() + + self.assertEqual(e1.attr1, posted_event.attr1, race_condition_notification) + + # fuzzing event types + for i in range(1, 13): + pygame.event.post( + pygame.event.Event(EVENT_TYPES[i], **EVENT_TEST_PARAMS[EVENT_TYPES[i]]) + ) + + self.assertEqual( + pygame.event.poll().type, EVENT_TYPES[i], race_condition_notification + ) + + def test_post_and_get_keydown(self): + """Ensure keydown events can be posted to the queue.""" + activemodkeys = pygame.key.get_mods() + + events = [ + pygame.event.Event(pygame.KEYDOWN, key=pygame.K_p), + pygame.event.Event(pygame.KEYDOWN, key=pygame.K_y, mod=activemodkeys), + pygame.event.Event(pygame.KEYDOWN, key=pygame.K_g, unicode="g"), + pygame.event.Event(pygame.KEYDOWN, key=pygame.K_a, unicode=None), + pygame.event.Event(pygame.KEYDOWN, key=pygame.K_m, mod=None, window=None), + pygame.event.Event( + pygame.KEYDOWN, key=pygame.K_e, mod=activemodkeys, unicode="e" + ), + ] + + for e in events: + pygame.event.post(e) + posted_event = pygame.event.poll() + self.assertEqual(e, posted_event, race_condition_notification) + + def test_post_large_user_event(self): + pygame.event.post(pygame.event.Event(pygame.USEREVENT, {"a": "a" * 1024})) + e = pygame.event.poll() + + self.assertEqual(e.type, pygame.USEREVENT) + self.assertEqual(e.a, "a" * 1024) + + def test_post_blocked(self): + """ + Test blocked events are not posted. Also test whether post() + returns a boolean correctly + """ + pygame.event.set_blocked(pygame.USEREVENT) + self.assertFalse(pygame.event.post(pygame.event.Event(pygame.USEREVENT))) + self.assertFalse(pygame.event.poll()) + pygame.event.set_allowed(pygame.USEREVENT) + self.assertTrue(pygame.event.post(pygame.event.Event(pygame.USEREVENT))) + self.assertEqual(pygame.event.poll(), pygame.event.Event(pygame.USEREVENT)) + + def test_get(self): + """Ensure get() retrieves all the events on the queue.""" + event_cnt = 10 + for _ in range(event_cnt): + pygame.event.post(pygame.event.Event(pygame.USEREVENT)) + + queue = pygame.event.get() + + self.assertEqual(len(queue), event_cnt) + self.assertTrue(all(e.type == pygame.USEREVENT for e in queue)) + + def test_get_type(self): + ev = pygame.event.Event(pygame.USEREVENT) + pygame.event.post(ev) + queue = pygame.event.get(pygame.USEREVENT) + self.assertEqual(len(queue), 1) + self.assertEqual(queue[0].type, pygame.USEREVENT) + + TESTEVENTS = 10 + for _ in range(TESTEVENTS): + pygame.event.post(ev) + q = pygame.event.get([pygame.USEREVENT]) + self.assertEqual(len(q), TESTEVENTS) + for event in q: + self.assertEqual(event, ev) + + def test_get_exclude_throw(self): + self.assertRaises( + pygame.error, pygame.event.get, pygame.KEYDOWN, False, pygame.KEYUP + ) + + def test_get_exclude(self): + pygame.event.post(pygame.event.Event(pygame.USEREVENT)) + pygame.event.post(pygame.event.Event(pygame.KEYDOWN)) + + queue = pygame.event.get(exclude=pygame.KEYDOWN) + self.assertEqual(len(queue), 1) + self.assertEqual(queue[0].type, pygame.USEREVENT) + + pygame.event.post(pygame.event.Event(pygame.KEYUP)) + pygame.event.post(pygame.event.Event(pygame.USEREVENT)) + queue = pygame.event.get(exclude=(pygame.KEYDOWN, pygame.KEYUP)) + self.assertEqual(len(queue), 1) + self.assertEqual(queue[0].type, pygame.USEREVENT) + + queue = pygame.event.get() + self.assertEqual(len(queue), 2) + + def test_get__empty_queue(self): + """Ensure get() works correctly on an empty queue.""" + expected_events = [] + pygame.event.clear() + + # Ensure all events can be checked. + retrieved_events = pygame.event.get() + + self.assertListEqual(retrieved_events, expected_events) + + # Ensure events can be checked individually. + for event_type in EVENT_TYPES: + retrieved_events = pygame.event.get(event_type) + + self.assertListEqual(retrieved_events, expected_events) + + # Ensure events can be checked as a sequence. + retrieved_events = pygame.event.get(EVENT_TYPES) + + self.assertListEqual(retrieved_events, expected_events) + + def test_get__event_sequence(self): + """Ensure get() can handle a sequence of event types.""" + event_types = [pygame.KEYDOWN, pygame.KEYUP, pygame.MOUSEMOTION] + other_event_type = pygame.MOUSEBUTTONUP + + # Test when no events in the queue. + expected_events = [] + pygame.event.clear() + retrieved_events = pygame.event.get(event_types) + + # don't use self._assertCountEqual here. This checks for + # expected properties in events, and ignores unexpected ones, for + # forward compatibility with SDL2. + self._assertExpectedEvents(expected=expected_events, got=retrieved_events) + + # Test when an event type not in the list is in the queue. + expected_events = [] + pygame.event.clear() + pygame.event.post( + pygame.event.Event(other_event_type, **EVENT_TEST_PARAMS[other_event_type]) + ) + + retrieved_events = pygame.event.get(event_types) + + self._assertExpectedEvents(expected=expected_events, got=retrieved_events) + + # Test when 1 event type in the list is in the queue. + expected_events = [ + pygame.event.Event(event_types[0], **EVENT_TEST_PARAMS[event_types[0]]) + ] + pygame.event.clear() + pygame.event.post(expected_events[0]) + + retrieved_events = pygame.event.get(event_types) + + self._assertExpectedEvents(expected=expected_events, got=retrieved_events) + + # Test all events in the list are in the queue. + pygame.event.clear() + expected_events = [] + + for etype in event_types: + expected_events.append( + pygame.event.Event(etype, **EVENT_TEST_PARAMS[etype]) + ) + pygame.event.post(expected_events[-1]) + + retrieved_events = pygame.event.get(event_types) + + self._assertExpectedEvents(expected=expected_events, got=retrieved_events) + + def test_clear(self): + """Ensure clear() removes all the events on the queue.""" + for e in EVENT_TYPES: + pygame.event.post(pygame.event.Event(e, **EVENT_TEST_PARAMS[e])) + poll_event = pygame.event.poll() + + self.assertNotEqual(poll_event.type, pygame.NOEVENT) + + pygame.event.clear() + poll_event = pygame.event.poll() + + self.assertEqual(poll_event.type, pygame.NOEVENT, race_condition_notification) + + def test_clear__empty_queue(self): + """Ensure clear() works correctly on an empty queue.""" + expected_events = [] + pygame.event.clear() + + # Test calling clear() on an already empty queue. + pygame.event.clear() + + retrieved_events = pygame.event.get() + + self.assertListEqual(retrieved_events, expected_events) + + def test_clear__event_sequence(self): + """Ensure a sequence of event types can be cleared from the queue.""" + cleared_event_types = EVENT_TYPES[:5] + expected_event_types = EVENT_TYPES[5:10] + expected_events = [] + + # Add the events to the queue. + for etype in cleared_event_types: + pygame.event.post(pygame.event.Event(etype, **EVENT_TEST_PARAMS[etype])) + + for etype in expected_events: + expected_events.append( + pygame.event.Event(etype, **EVENT_TEST_PARAMS[etype]) + ) + pygame.event.post(expected_events[-1]) + + # Clear the cleared_events from the queue. + pygame.event.clear(cleared_event_types) + + # Check the rest of the events in the queue. + remaining_events = pygame.event.get() + + self._assertCountEqual(remaining_events, expected_events) + + def test_event_name(self): + """Ensure event_name() returns the correct event name.""" + for expected_name, event in NAMES_AND_EVENTS: + self.assertEqual( + pygame.event.event_name(event), expected_name, "0x{:X}".format(event) + ) + + def test_event_name__userevent_range(self): + """Ensures event_name() returns the correct name for user events. + + Tests the full range of user events. + """ + expected_name = "UserEvent" + + for event in range(pygame.USEREVENT, pygame.NUMEVENTS): + self.assertEqual( + pygame.event.event_name(event), expected_name, "0x{:X}".format(event) + ) + + def test_event_name__userevent_boundary(self): + """Ensures event_name() does not return 'UserEvent' for events + just outside the user event range. + """ + unexpected_name = "UserEvent" + + for event in (pygame.USEREVENT - 1, pygame.NUMEVENTS): + self.assertNotEqual( + pygame.event.event_name(event), unexpected_name, "0x{:X}".format(event) + ) + + def test_wait(self): + """Ensure wait() waits for an event on the queue.""" + # Test case without timeout. + event = pygame.event.Event(EVENT_TYPES[0], **EVENT_TEST_PARAMS[EVENT_TYPES[0]]) + pygame.event.post(event) + wait_event = pygame.event.wait() + + self.assertEqual(wait_event.type, event.type) + + # Test case with timeout and no event in the queue. + wait_event = pygame.event.wait(250) + self.assertEqual(wait_event.type, pygame.NOEVENT) + + # Test case with timeout and an event in the queue. + event = pygame.event.Event(EVENT_TYPES[0], **EVENT_TEST_PARAMS[EVENT_TYPES[0]]) + pygame.event.post(event) + wait_event = pygame.event.wait(250) + + self.assertEqual(wait_event.type, event.type) + + def test_peek(self): + """Ensure queued events can be peeked at.""" + event_types = [pygame.KEYDOWN, pygame.KEYUP, pygame.MOUSEMOTION] + + for event_type in event_types: + pygame.event.post( + pygame.event.Event(event_type, **EVENT_TEST_PARAMS[event_type]) + ) + + # Ensure events can be checked individually. + for event_type in event_types: + self.assertTrue(pygame.event.peek(event_type)) + + # Ensure events can be checked as a sequence. + self.assertTrue(pygame.event.peek(event_types)) + + def test_peek__event_sequence(self): + """Ensure peek() can handle a sequence of event types.""" + event_types = [pygame.KEYDOWN, pygame.KEYUP, pygame.MOUSEMOTION] + other_event_type = pygame.MOUSEBUTTONUP + + # Test when no events in the queue. + pygame.event.clear() + peeked = pygame.event.peek(event_types) + + self.assertFalse(peeked) + + # Test when an event type not in the list is in the queue. + pygame.event.clear() + pygame.event.post( + pygame.event.Event(other_event_type, **EVENT_TEST_PARAMS[other_event_type]) + ) + + peeked = pygame.event.peek(event_types) + + self.assertFalse(peeked) + + # Test when 1 event type in the list is in the queue. + pygame.event.clear() + pygame.event.post( + pygame.event.Event(event_types[0], **EVENT_TEST_PARAMS[event_types[0]]) + ) + + peeked = pygame.event.peek(event_types) + + self.assertTrue(peeked) + + # Test all events in the list are in the queue. + pygame.event.clear() + for etype in event_types: + pygame.event.post(pygame.event.Event(etype, **EVENT_TEST_PARAMS[etype])) + + peeked = pygame.event.peek(event_types) + + self.assertTrue(peeked) + + def test_peek__empty_queue(self): + """Ensure peek() works correctly on an empty queue.""" + pygame.event.clear() + + # Ensure all events can be checked. + peeked = pygame.event.peek() + + self.assertFalse(peeked) + + # Ensure events can be checked individually. + for event_type in EVENT_TYPES: + peeked = pygame.event.peek(event_type) + self.assertFalse(peeked) + + # Ensure events can be checked as a sequence. + peeked = pygame.event.peek(EVENT_TYPES) + + self.assertFalse(peeked) + + def test_set_allowed(self): + """Ensure a blocked event type can be unblocked/allowed.""" + event = EVENT_TYPES[0] + pygame.event.set_blocked(event) + + self.assertTrue(pygame.event.get_blocked(event)) + + pygame.event.set_allowed(event) + + self.assertFalse(pygame.event.get_blocked(event)) + + def test_set_allowed__event_sequence(self): + """Ensure a sequence of blocked event types can be unblocked/allowed.""" + event_types = [ + pygame.KEYDOWN, + pygame.KEYUP, + pygame.MOUSEMOTION, + pygame.MOUSEBUTTONDOWN, + pygame.MOUSEBUTTONUP, + ] + pygame.event.set_blocked(event_types) + + pygame.event.set_allowed(event_types) + + for etype in event_types: + self.assertFalse(pygame.event.get_blocked(etype)) + + def test_set_allowed_all(self): + """Ensure all events can be unblocked/allowed at once.""" + pygame.event.set_blocked(None) + + for e in EVENT_TYPES: + self.assertTrue(pygame.event.get_blocked(e)) + + pygame.event.set_allowed(None) + + for e in EVENT_TYPES: + self.assertFalse(pygame.event.get_blocked(e)) + + def test_pump(self): + """Ensure pump() functions properly.""" + pygame.event.pump() + + # @unittest.skipIf( + # os.environ.get("SDL_VIDEODRIVER") == "dummy", + # 'requires the SDL_VIDEODRIVER to be a non "dummy" value', + # ) + # Fails on SDL 2.0.18 + @unittest.skip("flaky test, and broken on 2.0.18 windows") + def test_set_grab__and_get_symmetric(self): + """Ensure event grabbing can be enabled and disabled. + + WARNING: Moving the mouse off the display during this test can cause it + to fail. + """ + surf = pygame.display.set_mode((10, 10)) + pygame.event.set_grab(True) + + self.assertTrue(pygame.event.get_grab()) + + pygame.event.set_grab(False) + + self.assertFalse(pygame.event.get_grab()) + + def test_event_equality(self): + """Ensure an events can be compared correctly.""" + a = pygame.event.Event(EVENT_TYPES[0], a=1) + b = pygame.event.Event(EVENT_TYPES[0], a=1) + c = pygame.event.Event(EVENT_TYPES[1], a=1) + d = pygame.event.Event(EVENT_TYPES[0], a=2) + + self.assertTrue(a == a) + self.assertFalse(a != a) + self.assertTrue(a == b) + self.assertFalse(a != b) + self.assertTrue(a != c) + self.assertFalse(a == c) + self.assertTrue(a != d) + self.assertFalse(a == d) + + def test_get_blocked(self): + """Ensure an event's blocked state can be retrieved.""" + # Test each event is not blocked. + pygame.event.set_allowed(None) + + for etype in EVENT_TYPES: + blocked = pygame.event.get_blocked(etype) + + self.assertFalse(blocked) + + # Test each event type is blocked. + pygame.event.set_blocked(None) + + for etype in EVENT_TYPES: + blocked = pygame.event.get_blocked(etype) + + self.assertTrue(blocked) + + def test_get_blocked__event_sequence(self): + """Ensure get_blocked() can handle a sequence of event types.""" + event_types = [ + pygame.KEYDOWN, + pygame.KEYUP, + pygame.MOUSEMOTION, + pygame.MOUSEBUTTONDOWN, + pygame.MOUSEBUTTONUP, + ] + + # Test no event types in the list are blocked. + blocked = pygame.event.get_blocked(event_types) + + self.assertFalse(blocked) + + # Test when 1 event type in the list is blocked. + pygame.event.set_blocked(event_types[2]) + + blocked = pygame.event.get_blocked(event_types) + + self.assertTrue(blocked) + + # Test all event types in the list are blocked. + pygame.event.set_blocked(event_types) + + blocked = pygame.event.get_blocked(event_types) + + self.assertTrue(blocked) + + # @unittest.skipIf( + # os.environ.get("SDL_VIDEODRIVER") == "dummy", + # 'requires the SDL_VIDEODRIVER to be a non "dummy" value', + # ) + # Fails on SDL 2.0.18 + @unittest.skip("flaky test, and broken on 2.0.18 windows") + def test_get_grab(self): + """Ensure get_grab() works as expected""" + surf = pygame.display.set_mode((10, 10)) + # Test 5 times + for i in range(5): + pygame.event.set_grab(i % 2) + self.assertEqual(pygame.event.get_grab(), i % 2) + + def test_poll(self): + """Ensure poll() works as expected""" + pygame.event.clear() + ev = pygame.event.poll() + # poll() on empty queue should return NOEVENT + self.assertEqual(ev.type, pygame.NOEVENT) + + # test poll returns stuff in same order + e1 = pygame.event.Event(pygame.USEREVENT) + e2 = pygame.event.Event(pygame.KEYDOWN, key=pygame.K_a) + e3 = pygame.event.Event(pygame.KEYUP, key=pygame.K_a) + pygame.event.post(e1) + pygame.event.post(e2) + pygame.event.post(e3) + + self.assertEqual(pygame.event.poll().type, e1.type) + self.assertEqual(pygame.event.poll().type, e2.type) + self.assertEqual(pygame.event.poll().type, e3.type) + self.assertEqual(pygame.event.poll().type, pygame.NOEVENT) + + +################################################################################ + +if __name__ == "__main__": + unittest.main() diff --git a/venv/Lib/site-packages/pygame/tests/fixtures/fonts/A_PyGameMono-8.png b/venv/Lib/site-packages/pygame/tests/fixtures/fonts/A_PyGameMono-8.png new file mode 100644 index 0000000000000000000000000000000000000000..b15961f08bce5b630952beb840bda9dab3db338f GIT binary patch literal 92 zcmeAS@N?(olHy`uVBq!ia0vp^Y(UJ;$P6R}d3f?JBJrD{mt%$ z63MDmssD6G@6DUv`;S+s69Z4K2k_?fnr^ zdYp)UUtjC5d&0H)QKF0%j9>TpS{mCAuKf~`3-;t`*ii4Il~e@#R*XwFKfb(TOGnsG z#A+~p=Gm@5xAK!1p@cTa=-G z1ca`9{nnECy{f4PFm{q6Q9ST5ktZ#C)rw^4EDlS|BMk$a`VspSl2bXPoW;1`>e>5L z&Xfgih3pIF9NA|HB+}Gg-$n^qFNCUzN_x`FXy%q$bv@>9<;|oKb0re~G7YC>M(K1r zB_j#TPRS~ju;){r_Wk3Q~Y#;BA=yHrfO3$0!UmYGQs0Vbn%Fu!>TIx~SA_ z8tsB6MxF5R0S`l#eUv)juTce+kr#alEMjQgR87m#+Ecc&w`|K0yB*eH_{Hc!qPl1> z5DT_x+xBSwU^ozM)BK@uTTd(+=_)NP)pmtqotiHaj`wdsRE<^5 zkE+eZ)v!j5%5kcefqTI#z{_Qge}2Bznl%GWPC={I%2zHc_b#jOmc#Pyp;J>f9f-b) zIY+T=A#*_*lE^f2!)4Q85RCSOB4N$zEidzWy+G!Nz3V=puH*?(L8TxYs3lc_-;z~h z;wtJ`;x@cjoN4sTJco5cU`+CS5Q#*}4_ASSt~9w7J0+Ukdhj|BBj(*>l9`v;=ML6< z>;Fz>id@P6^OKst_y(%zE*rwghTUf@V_q@i%3`!E>87NICBL8~3)JMjwtg4W_31OW z^U^$Y*6kt6^3a=$JXGwlExCtm(#1iK(buSBNBIixnyUZd@tarW^JaG;-&P<~@GEeSI=5Upda5vL=Ve$koRC(ca7LqoO&j^ZrGAL-> zLpDK2?ukg&EwLj)B%l>Pg~DPw6c!ed+6df)E>mXkzwnYE-;o~+ z`uO4Pg5JpZrY`vb@JB!0Z#*+%Jd)tOV}g4B@B*+KOM9I>Y6SjlJb@P2X!I87LM$2? zeqD%obLR!4*O{q*z`uW;Bcgx%Zy9$@Bwx6t@~yllcl;k0c|MxEskYW|HyQaxe$mD8 zg2PFc`yN-`;vO_*Q%#MbY%)A(%3JRhBtM?X%hfOL9@+W5_EX^#`p@*l=+V=sPQG&D zw0=o{XFtz3M*G`w#J^G_#Q3!#NFMC;l^;H$JB9c`?Iuj`K;^g)VxZMns*gWCX83iZ zMmPMOM&0Ud&g3~e-_rla2RbLroGZycaRs~ofSP=mE4fCwv5?=#%h492FDc}T&L3?2 zXS4H|{m@|lA^lj(`$iSdGZyPk<2j?xr~>uzUBG$@`8u8FeKN+=o!{wm6#EVLV@9Fw z%;Z}ykMh>h%Zy*(t!mCBzaZ;My#3+xf*t}B<9Wvft)62NGZp{FEECgMx|zNvW-(v| zhIg@`jr@wB?Y~I~TI;M3)W51G#Uv(v1+Dlw6c!tR*1~$E)?^a1d=aX^C|>+Gqgv3x zAzuhZ9~whJjD*gC4-RcOKf#L)h35&;A3FCgYJF$}w!V4D2mamA*cKzpSnABYy+23K z-Sx`!8QreC(l4i9KK}B+;Bf!T<1W|LjERB6Ctp2!&b3h9k@9xW1m($(2X1uS$mZQH zzXI|%Na`g)w%f_>oXrayoO0O7;oO_o_hMd+3EsK)Xv35#?elnlJ!!L3nse{OQ*Jl8 zvr!V_rijl{lBU?CnsCJ3@pW-=N#gNEZd#P>p6t6h$zd_WW*jqxQgPFWf5_fp!>Xp# z*sL%~F+EuoUqK!0-PyvKb;)i|;=cHr^EbpVXUVisCkv;hdJ=2MLzVdHm}Ci-P!lW8 zpBG5&a8m{nb#EV7{ekcpZh@#pb$t0 fodB6R-u`w(`p}i$zz(zTd+wP06Sn?_B|`KsxgTC( literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/tests/fixtures/fonts/test_fixed.otf b/venv/Lib/site-packages/pygame/tests/fixtures/fonts/test_fixed.otf new file mode 100644 index 0000000000000000000000000000000000000000..348889828d894b9b57fb6435497d5c034448cb1b GIT binary patch literal 58464 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/tests/fixtures/fonts/u13079_PyGameMono-8.png b/venv/Lib/site-packages/pygame/tests/fixtures/fonts/u13079_PyGameMono-8.png new file mode 100644 index 0000000000000000000000000000000000000000..911da8a6cf8238dccacdddce217744446e508b6a GIT binary patch literal 89 zcmeAS@N?(olHy`uVBq!ia0vp^Y(UJy$P6T>pSlAi8Q21RLR^9L|NsA&-kg6I$l~*K kaSY*@nVgaSf$dNk1KSM7rD8`d`az04UHx3vIVCg!0CbKQWB>pF literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/tests/fixtures/xbm_cursors/white_sizing.xbm b/venv/Lib/site-packages/pygame/tests/fixtures/xbm_cursors/white_sizing.xbm new file mode 100644 index 0000000..d334d8d --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/fixtures/xbm_cursors/white_sizing.xbm @@ -0,0 +1,8 @@ +#define resize_white_width 16 +#define resize_white_height 16 +#define resize_white_x_hot 7 +#define resize_white_y_hot 7 +static unsigned char resize_white_bits[] = { + 0xff, 0x03, 0x01, 0x02, 0xfd, 0x03, 0x05, 0x00, 0xf5, 0x0f, 0x15, 0x08, + 0xd5, 0xeb, 0x55, 0xaa, 0x55, 0xaa, 0xd7, 0xab, 0x10, 0xa8, 0xf0, 0xb7, + 0x00, 0xa8, 0xc0, 0x9f, 0x40, 0x80, 0xc0, 0xff}; diff --git a/venv/Lib/site-packages/pygame/tests/fixtures/xbm_cursors/white_sizing_mask.xbm b/venv/Lib/site-packages/pygame/tests/fixtures/xbm_cursors/white_sizing_mask.xbm new file mode 100644 index 0000000..f00bc46 --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/fixtures/xbm_cursors/white_sizing_mask.xbm @@ -0,0 +1,8 @@ +#define resize_white_mask_width 16 +#define resize_white_mask_height 16 +#define resize_white_mask_x_hot 7 +#define resize_white_mask_y_hot 7 +static unsigned char resize_white_mask_bits[] = { + 0xff, 0x03, 0xff, 0x03, 0xff, 0x03, 0x07, 0x00, 0xf7, 0x0f, 0xf7, 0x0f, + 0xf7, 0xef, 0x77, 0xee, 0x77, 0xee, 0xf7, 0xef, 0xf0, 0xef, 0xf0, 0xff, + 0x00, 0xf8, 0xc0, 0xff, 0xc0, 0xff, 0xc0, 0xff}; diff --git a/venv/Lib/site-packages/pygame/tests/font_test.py b/venv/Lib/site-packages/pygame/tests/font_test.py new file mode 100644 index 0000000..e7bbf67 --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/font_test.py @@ -0,0 +1,633 @@ +# -*- coding: utf-8 -*- + +import sys +import os +import unittest +import pathlib +import platform + +import pygame +from pygame import font as pygame_font # So font can be replaced with ftfont + + +FONTDIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "fixtures", "fonts") + +UCS_4 = sys.maxunicode > 0xFFFF + + +def equal_images(s1, s2): + size = s1.get_size() + if s2.get_size() != size: + return False + w, h = size + for x in range(w): + for y in range(h): + if s1.get_at((x, y)) != s2.get_at((x, y)): + return False + return True + + +IS_PYPY = "PyPy" == platform.python_implementation() + + +@unittest.skipIf(IS_PYPY, "pypy skip known failure") # TODO +class FontModuleTest(unittest.TestCase): + def setUp(self): + pygame_font.init() + + def tearDown(self): + pygame_font.quit() + + def test_SysFont(self): + # Can only check that a font object is returned. + fonts = pygame_font.get_fonts() + if "arial" in fonts: + # Try to use arial font if it is there, rather than a random font + # which can be different depending on installed fonts on the system. + font_name = "arial" + else: + font_name = sorted(fonts)[0] + o = pygame_font.SysFont(font_name, 20) + self.assertTrue(isinstance(o, pygame_font.FontType)) + o = pygame_font.SysFont(font_name, 20, italic=True) + self.assertTrue(isinstance(o, pygame_font.FontType)) + o = pygame_font.SysFont(font_name, 20, bold=True) + self.assertTrue(isinstance(o, pygame_font.FontType)) + o = pygame_font.SysFont("thisisnotafont", 20) + self.assertTrue(isinstance(o, pygame_font.FontType)) + + def test_get_default_font(self): + self.assertEqual(pygame_font.get_default_font(), "freesansbold.ttf") + + def test_get_fonts_returns_something(self): + fnts = pygame_font.get_fonts() + self.assertTrue(fnts) + + # to test if some files exist... + # def XXtest_has_file_osx_10_5_sdk(self): + # import os + # f = "/Developer/SDKs/MacOSX10.5.sdk/usr/X11/include/ft2build.h" + # self.assertEqual(os.path.exists(f), True) + + # def XXtest_has_file_osx_10_4_sdk(self): + # import os + # f = "/Developer/SDKs/MacOSX10.4u.sdk/usr/X11R6/include/ft2build.h" + # self.assertEqual(os.path.exists(f), True) + + def test_get_fonts(self): + fnts = pygame_font.get_fonts() + + self.assertTrue(fnts, msg=repr(fnts)) + + for name in fnts: + # note, on ubuntu 2.6 they are all unicode strings. + + self.assertTrue(isinstance(name, str), name) + # Font names can be comprised of only numeric characters, so + # just checking name.islower() will not work as expected here. + self.assertFalse(any(c.isupper() for c in name)) + self.assertTrue(name.isalnum(), name) + + def test_get_init(self): + self.assertTrue(pygame_font.get_init()) + pygame_font.quit() + self.assertFalse(pygame_font.get_init()) + + def test_init(self): + pygame_font.init() + + def test_match_font_all_exist(self): + fonts = pygame_font.get_fonts() + + # Ensure all listed fonts are in fact available, and the returned file + # name is a full path. + for font in fonts: + path = pygame_font.match_font(font) + self.assertFalse(path is None) + self.assertTrue(os.path.isabs(path)) + + def test_match_font_name(self): + """That match_font accepts names of various types""" + font = pygame_font.get_fonts()[0] + font_path = pygame_font.match_font(font) + self.assertIsNotNone(font_path) + font_b = font.encode() + not_a_font = "thisisnotafont" + not_a_font_b = b"thisisnotafont" + good_font_names = [ + # Check single name bytes. + font_b, + # Check string of comma-separated names. + ",".join([not_a_font, font, not_a_font]), + # Check list of names. + [not_a_font, font, not_a_font], + # Check generator: + (name for name in [not_a_font, font, not_a_font]), + # Check comma-separated bytes. + b",".join([not_a_font_b, font_b, not_a_font_b]), + # Check list of bytes. + [not_a_font_b, font_b, not_a_font_b], + # Check mixed list of bytes and string. + [font, not_a_font, font_b, not_a_font_b], + ] + for font_name in good_font_names: + self.assertEqual(pygame_font.match_font(font_name), font_path, font_name) + + def test_not_match_font_name(self): + """match_font return None when names of various types do not exist""" + not_a_font = "thisisnotafont" + not_a_font_b = b"thisisnotafont" + bad_font_names = [ + not_a_font, + ",".join([not_a_font, not_a_font, not_a_font]), + [not_a_font, not_a_font, not_a_font], + (name for name in [not_a_font, not_a_font, not_a_font]), + not_a_font_b, + b",".join([not_a_font_b, not_a_font_b, not_a_font_b]), + [not_a_font_b, not_a_font_b, not_a_font_b], + [not_a_font, not_a_font_b, not_a_font], + ] + for font_name in bad_font_names: + self.assertIsNone(pygame_font.match_font(font_name), font_name) + + def test_match_font_bold(self): + fonts = pygame_font.get_fonts() + + # Look for a bold font. + self.assertTrue(any(pygame_font.match_font(font, bold=True) for font in fonts)) + + def test_match_font_italic(self): + fonts = pygame_font.get_fonts() + + # Look for an italic font. + self.assertTrue( + any(pygame_font.match_font(font, italic=True) for font in fonts) + ) + + def test_issue_742(self): + """that the font background does not crash.""" + surf = pygame.Surface((320, 240)) + font = pygame_font.Font(None, 24) + image = font.render("Test", 0, (255, 255, 255), (0, 0, 0)) + self.assertIsNone(image.get_colorkey()) + image.set_alpha(255) + surf.blit(image, (0, 0)) + + def test_issue_font_alphablit(self): + """Check that blitting anti-aliased text doesn't + change the background blue""" + pygame.display.set_mode((600, 400)) + + font = pygame_font.Font(None, 24) + + (color, text, center, pos) = ((160, 200, 250), "Music", (190, 170), "midright") + img1 = font.render(text, True, color) + + img = pygame.Surface(img1.get_size(), depth=32) + pre_blit_corner_pixel = img.get_at((0, 0)) + img.blit(img1, (0, 0)) + post_blit_corner_pixel = img.get_at((0, 0)) + + self.assertEqual(pre_blit_corner_pixel, post_blit_corner_pixel) + + def test_segfault_after_reinit(self): + """Reinitialization of font module should not cause + segmentation fault""" + import gc + + font = pygame_font.Font(None, 20) + pygame_font.quit() + pygame_font.init() + del font + gc.collect() + + def test_quit(self): + pygame_font.quit() + + +@unittest.skipIf(IS_PYPY, "pypy skip known failure") # TODO +class FontTest(unittest.TestCase): + def setUp(self): + pygame_font.init() + + def tearDown(self): + pygame_font.quit() + + def test_render_args(self): + screen = pygame.display.set_mode((600, 400)) + rect = screen.get_rect() + f = pygame_font.Font(None, 20) + screen.fill((10, 10, 10)) + font_surface = f.render(" bar", True, (0, 0, 0), (255, 255, 255)) + font_rect = font_surface.get_rect() + font_rect.topleft = rect.topleft + self.assertTrue(font_surface) + screen.blit(font_surface, font_rect, font_rect) + pygame.display.update() + self.assertEqual(tuple(screen.get_at((0, 0)))[:3], (255, 255, 255)) + self.assertEqual(tuple(screen.get_at(font_rect.topleft))[:3], (255, 255, 255)) + + # If we don't have a real display, don't do this test. + # Transparent background doesn't seem to work without a read video card. + if os.environ.get("SDL_VIDEODRIVER") != "dummy": + screen.fill((10, 10, 10)) + font_surface = f.render(" bar", True, (0, 0, 0), None) + font_rect = font_surface.get_rect() + font_rect.topleft = rect.topleft + self.assertTrue(font_surface) + screen.blit(font_surface, font_rect, font_rect) + pygame.display.update() + self.assertEqual(tuple(screen.get_at((0, 0)))[:3], (10, 10, 10)) + self.assertEqual(tuple(screen.get_at(font_rect.topleft))[:3], (10, 10, 10)) + + screen.fill((10, 10, 10)) + font_surface = f.render(" bar", True, (0, 0, 0)) + font_rect = font_surface.get_rect() + font_rect.topleft = rect.topleft + self.assertTrue(font_surface) + screen.blit(font_surface, font_rect, font_rect) + pygame.display.update(rect) + self.assertEqual(tuple(screen.get_at((0, 0)))[:3], (10, 10, 10)) + self.assertEqual(tuple(screen.get_at(font_rect.topleft))[:3], (10, 10, 10)) + + +@unittest.skipIf(IS_PYPY, "pypy skip known failure") # TODO +class FontTypeTest(unittest.TestCase): + def setUp(self): + pygame_font.init() + + def tearDown(self): + pygame_font.quit() + + def test_get_ascent(self): + # Ckecking ascent would need a custom test font to do properly. + f = pygame_font.Font(None, 20) + ascent = f.get_ascent() + self.assertTrue(isinstance(ascent, int)) + self.assertTrue(ascent > 0) + s = f.render("X", False, (255, 255, 255)) + self.assertTrue(s.get_size()[1] > ascent) + + def test_get_descent(self): + # Ckecking descent would need a custom test font to do properly. + f = pygame_font.Font(None, 20) + descent = f.get_descent() + self.assertTrue(isinstance(descent, int)) + self.assertTrue(descent < 0) + + def test_get_height(self): + # Ckecking height would need a custom test font to do properly. + f = pygame_font.Font(None, 20) + height = f.get_height() + self.assertTrue(isinstance(height, int)) + self.assertTrue(height > 0) + s = f.render("X", False, (255, 255, 255)) + self.assertTrue(s.get_size()[1] == height) + + def test_get_linesize(self): + # Ckecking linesize would need a custom test font to do properly. + # Questions: How do linesize, height and descent relate? + f = pygame_font.Font(None, 20) + linesize = f.get_linesize() + self.assertTrue(isinstance(linesize, int)) + self.assertTrue(linesize > 0) + + def test_metrics(self): + # Ensure bytes decoding works correctly. Can only compare results + # with unicode for now. + f = pygame_font.Font(None, 20) + um = f.metrics(".") + bm = f.metrics(b".") + + self.assertEqual(len(um), 1) + self.assertEqual(len(bm), 1) + self.assertIsNotNone(um[0]) + self.assertEqual(um, bm) + + u = "\u212A" + b = u.encode("UTF-16")[2:] # Keep byte order consistent. [2:] skips BOM + bm = f.metrics(b) + + self.assertEqual(len(bm), 2) + + try: # FIXME why do we do this try/except ? + um = f.metrics(u) + except pygame.error: + pass + else: + self.assertEqual(len(um), 1) + self.assertNotEqual(bm[0], um[0]) + self.assertNotEqual(bm[1], um[0]) + + if UCS_4: + u = u"\U00013000" + bm = f.metrics(u) + + self.assertEqual(len(bm), 1) + self.assertIsNone(bm[0]) + + return # unfinished + # The documentation is useless here. How large a list? + # How do list positions relate to character codes? + # What about unicode characters? + + # __doc__ (as of 2008-08-02) for pygame_font.Font.metrics: + + # Font.metrics(text): return list + # Gets the metrics for each character in the pased string. + # + # The list contains tuples for each character, which contain the + # minimum X offset, the maximum X offset, the minimum Y offset, the + # maximum Y offset and the advance offset (bearing plus width) of the + # character. [(minx, maxx, miny, maxy, advance), (minx, maxx, miny, + # maxy, advance), ...] + + self.fail() + + def test_render(self): + f = pygame_font.Font(None, 20) + s = f.render("foo", True, [0, 0, 0], [255, 255, 255]) + s = f.render("xxx", True, [0, 0, 0], [255, 255, 255]) + s = f.render("", True, [0, 0, 0], [255, 255, 255]) + s = f.render("foo", False, [0, 0, 0], [255, 255, 255]) + s = f.render("xxx", False, [0, 0, 0], [255, 255, 255]) + s = f.render("xxx", False, [0, 0, 0]) + s = f.render(" ", False, [0, 0, 0]) + s = f.render(" ", False, [0, 0, 0], [255, 255, 255]) + # null text should be 0 pixel wide. + s = f.render("", False, [0, 0, 0], [255, 255, 255]) + self.assertEqual(s.get_size()[0], 0) + # None text should be 0 pixel wide. + s = f.render(None, False, [0, 0, 0], [255, 255, 255]) + self.assertEqual(s.get_size()[0], 0) + # Non-text should raise a TypeError. + self.assertRaises(TypeError, f.render, [], False, [0, 0, 0], [255, 255, 255]) + self.assertRaises(TypeError, f.render, 1, False, [0, 0, 0], [255, 255, 255]) + # is background transparent for antialiasing? + s = f.render(".", True, [255, 255, 255]) + self.assertEqual(s.get_at((0, 0))[3], 0) + # is Unicode and bytes encoding correct? + # Cannot really test if the correct characters are rendered, but + # at least can assert the encodings differ. + su = f.render(".", False, [0, 0, 0], [255, 255, 255]) + sb = f.render(b".", False, [0, 0, 0], [255, 255, 255]) + self.assertTrue(equal_images(su, sb)) + u = "\u212A" + b = u.encode("UTF-16")[2:] # Keep byte order consistent. [2:] skips BOM + sb = f.render(b, False, [0, 0, 0], [255, 255, 255]) + try: # FIXME why do we do this try/except ? + su = f.render(u, False, [0, 0, 0], [255, 255, 255]) + except pygame.error: + pass + else: + self.assertFalse(equal_images(su, sb)) + + b = b"ab\x00cd" + self.assertRaises(ValueError, f.render, b, 0, [0, 0, 0]) + u = "ab\x00cd" + self.assertRaises(ValueError, f.render, b, 0, [0, 0, 0]) + + def test_render_ucs2_ucs4(self): + """that it renders without raising if there is a new enough SDL_ttf.""" + f = pygame_font.Font(None, 20) + # If the font module is SDL_ttf < 2.0.15 based, then it only supports UCS-2 + # it will raise an exception for an out-of-range UCS-4 code point. + if UCS_4 and hasattr(pygame_font, "UCS_4"): + ucs_2 = "\uFFEE" + s = f.render(ucs_2, False, [0, 0, 0], [255, 255, 255]) + ucs_4 = "\U00010000" + s = f.render(ucs_4, False, [0, 0, 0], [255, 255, 255]) + + def test_set_bold(self): + f = pygame_font.Font(None, 20) + self.assertFalse(f.get_bold()) + f.set_bold(True) + self.assertTrue(f.get_bold()) + f.set_bold(False) + self.assertFalse(f.get_bold()) + + def test_set_italic(self): + f = pygame_font.Font(None, 20) + self.assertFalse(f.get_italic()) + f.set_italic(True) + self.assertTrue(f.get_italic()) + f.set_italic(False) + self.assertFalse(f.get_italic()) + + def test_set_underline(self): + f = pygame_font.Font(None, 20) + self.assertFalse(f.get_underline()) + f.set_underline(True) + self.assertTrue(f.get_underline()) + f.set_underline(False) + self.assertFalse(f.get_underline()) + + def test_bold_attr(self): + f = pygame_font.Font(None, 20) + self.assertFalse(f.bold) + f.bold = True + self.assertTrue(f.bold) + f.bold = False + self.assertFalse(f.bold) + + def test_set_italic_property(self): + f = pygame_font.Font(None, 20) + self.assertFalse(f.italic) + f.italic = True + self.assertTrue(f.italic) + f.italic = False + self.assertFalse(f.italic) + + def test_set_underline_property(self): + f = pygame_font.Font(None, 20) + self.assertFalse(f.underline) + f.underline = True + self.assertTrue(f.underline) + f.underline = False + self.assertFalse(f.underline) + + def test_size(self): + f = pygame_font.Font(None, 20) + text = "Xg" + size = f.size(text) + w, h = size + s = f.render(text, False, (255, 255, 255)) + btext = text.encode("ascii") + + self.assertIsInstance(w, int) + self.assertIsInstance(h, int) + self.assertEqual(s.get_size(), size) + self.assertEqual(f.size(btext), size) + + text = "\u212A" + btext = text.encode("UTF-16")[2:] # Keep the byte order consistent. + bsize = f.size(btext) + size = f.size(text) + + self.assertNotEqual(size, bsize) + + def test_font_file_not_found(self): + # A per BUG reported by Bo Jangeborg on pygame-user mailing list, + # http://www.mail-archive.com/pygame-users@seul.org/msg11675.html + + pygame_font.init() + self.assertRaises( + FileNotFoundError, pygame_font.Font, str("some-fictional-font.ttf"), 20 + ) + + def test_load_from_file(self): + font_name = pygame_font.get_default_font() + font_path = os.path.join( + os.path.split(pygame.__file__)[0], pygame_font.get_default_font() + ) + f = pygame_font.Font(font_path, 20) + + def test_load_from_pathlib(self): + font_name = pygame_font.get_default_font() + font_path = os.path.join( + os.path.split(pygame.__file__)[0], pygame_font.get_default_font() + ) + f = pygame_font.Font(pathlib.Path(font_path), 20) + + def test_load_from_file_obj(self): + font_name = pygame_font.get_default_font() + font_path = os.path.join( + os.path.split(pygame.__file__)[0], pygame_font.get_default_font() + ) + with open(font_path, "rb") as f: + font = pygame_font.Font(f, 20) + + def test_load_default_font_filename(self): + # In font_init, a special case is when the filename argument is + # identical to the default font file name. + f = pygame_font.Font(pygame_font.get_default_font(), 20) + + def _load_unicode(self, path): + import shutil + + fdir = str(FONTDIR) + temp = os.path.join(fdir, path) + pgfont = os.path.join(fdir, u"test_sans.ttf") + shutil.copy(pgfont, temp) + try: + with open(temp, "rb") as f: + pass + except FileNotFoundError: + raise unittest.SkipTest("the path cannot be opened") + try: + pygame_font.Font(temp, 20) + finally: + os.remove(temp) + + def test_load_from_file_unicode_0(self): + """ASCII string as a unicode object""" + self._load_unicode(u"temp_file.ttf") + + def test_load_from_file_unicode_1(self): + self._load_unicode(u"你好.ttf") + + def test_load_from_file_bytes(self): + font_path = os.path.join( + os.path.split(pygame.__file__)[0], pygame_font.get_default_font() + ) + filesystem_encoding = sys.getfilesystemencoding() + filesystem_errors = "replace" if sys.platform == "win32" else "surrogateescape" + try: # FIXME why do we do this try/except ? + font_path = font_path.decode(filesystem_encoding, filesystem_errors) + except AttributeError: + pass + bfont_path = font_path.encode(filesystem_encoding, filesystem_errors) + f = pygame_font.Font(bfont_path, 20) + + +@unittest.skipIf(IS_PYPY, "pypy skip known failure") # TODO +class VisualTests(unittest.TestCase): + + __tags__ = ["interactive"] + + screen = None + aborted = False + + def setUp(self): + if self.screen is None: + pygame.init() + self.screen = pygame.display.set_mode((600, 200)) + self.screen.fill((255, 255, 255)) + pygame.display.flip() + self.f = pygame_font.Font(None, 32) + + def abort(self): + if self.screen is not None: + pygame.quit() + self.aborted = True + + def query(self, bold=False, italic=False, underline=False, antialiase=False): + if self.aborted: + return False + spacing = 10 + offset = 20 + y = spacing + f = self.f + screen = self.screen + screen.fill((255, 255, 255)) + pygame.display.flip() + if not (bold or italic or underline or antialiase): + text = "normal" + else: + modes = [] + if bold: + modes.append("bold") + if italic: + modes.append("italic") + if underline: + modes.append("underlined") + if antialiase: + modes.append("antialiased") + text = "%s (y/n):" % ("-".join(modes),) + f.set_bold(bold) + f.set_italic(italic) + f.set_underline(underline) + s = f.render(text, antialiase, (0, 0, 0)) + screen.blit(s, (offset, y)) + y += s.get_size()[1] + spacing + f.set_bold(False) + f.set_italic(False) + f.set_underline(False) + s = f.render("(some comparison text)", False, (0, 0, 0)) + screen.blit(s, (offset, y)) + pygame.display.flip() + while 1: + for evt in pygame.event.get(): + if evt.type == pygame.KEYDOWN: + if evt.key == pygame.K_ESCAPE: + self.abort() + return False + if evt.key == pygame.K_y: + return True + if evt.key == pygame.K_n: + return False + if evt.type == pygame.QUIT: + self.abort() + return False + + def test_bold(self): + self.assertTrue(self.query(bold=True)) + + def test_italic(self): + self.assertTrue(self.query(italic=True)) + + def test_underline(self): + self.assertTrue(self.query(underline=True)) + + def test_antialiase(self): + self.assertTrue(self.query(antialiase=True)) + + def test_bold_antialiase(self): + self.assertTrue(self.query(bold=True, antialiase=True)) + + def test_italic_underline(self): + self.assertTrue(self.query(italic=True, underline=True)) + + +if __name__ == "__main__": + unittest.main() diff --git a/venv/Lib/site-packages/pygame/tests/freetype_tags.py b/venv/Lib/site-packages/pygame/tests/freetype_tags.py new file mode 100644 index 0000000..d84cbb7 --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/freetype_tags.py @@ -0,0 +1,11 @@ +__tags__ = ["development"] + +exclude = False + +try: + import pygame.freetype +except ImportError: + exclude = True + +if exclude: + __tags__.extend(["ignore", "subprocess_ignore"]) diff --git a/venv/Lib/site-packages/pygame/tests/freetype_test.py b/venv/Lib/site-packages/pygame/tests/freetype_test.py new file mode 100644 index 0000000..815dfe3 --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/freetype_test.py @@ -0,0 +1,1799 @@ +import os + +if os.environ.get("SDL_VIDEODRIVER") == "dummy": + __tags__ = ("ignore", "subprocess_ignore") + +import unittest +import ctypes +import weakref +import gc +import pathlib +import platform + +IS_PYPY = "PyPy" == platform.python_implementation() + + +try: + from pygame.tests.test_utils import arrinter +except NameError: + pass + +import pygame + +try: + import pygame.freetype as ft +except ImportError: + ft = None + + +FONTDIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "fixtures", "fonts") + + +def nullfont(): + """return an uninitialized font instance""" + return ft.Font.__new__(ft.Font) + + +max_point_size_FX6 = 0x7FFFFFFF +max_point_size = max_point_size_FX6 >> 6 +max_point_size_f = max_point_size_FX6 * 0.015625 + + +def surf_same_image(a, b): + """Return True if a's pixel buffer is identical to b's""" + + a_sz = a.get_height() * a.get_pitch() + b_sz = b.get_height() * b.get_pitch() + if a_sz != b_sz: + return False + a_bytes = ctypes.string_at(a._pixels_address, a_sz) + b_bytes = ctypes.string_at(b._pixels_address, b_sz) + return a_bytes == b_bytes + + +class FreeTypeFontTest(unittest.TestCase): + + _fixed_path = os.path.join(FONTDIR, "test_fixed.otf") + _sans_path = os.path.join(FONTDIR, "test_sans.ttf") + _mono_path = os.path.join(FONTDIR, "PyGameMono.otf") + _bmp_8_75dpi_path = os.path.join(FONTDIR, "PyGameMono-8.bdf") + _bmp_18_75dpi_path = os.path.join(FONTDIR, "PyGameMono-18-75dpi.bdf") + _bmp_18_100dpi_path = os.path.join(FONTDIR, "PyGameMono-18-100dpi.bdf") + _TEST_FONTS = {} + + @classmethod + def setUpClass(cls): + ft.init() + + # Setup the test fonts. + + # Inconsolata is an open-source font designed by Raph Levien. + # Licensed under the Open Font License. + # http://www.levien.com/type/myfonts/inconsolata.html + cls._TEST_FONTS["fixed"] = ft.Font(cls._fixed_path) + + # Liberation Sans is an open-source font designed by Steve Matteson. + # Licensed under the GNU GPL. + # https://fedorahosted.org/liberation-fonts/ + cls._TEST_FONTS["sans"] = ft.Font(cls._sans_path) + + # A scalable mono test font made for pygame. It contains only + # a few glyphs: '\0', 'A', 'B', 'C', and U+13079. + # It also contains two bitmap sizes: 8.0 X 8.0 and 19.0 X 19.0. + cls._TEST_FONTS["mono"] = ft.Font(cls._mono_path) + + # A fixed size bitmap mono test font made for pygame. + # It contains only a few glyphs: '\0', 'A', 'B', 'C', and U+13079. + # The size is 8.0 X 8.0. + cls._TEST_FONTS["bmp-8-75dpi"] = ft.Font(cls._bmp_8_75dpi_path) + + # A fixed size bitmap mono test font made for pygame. + # It contains only a few glyphs: '\0', 'A', 'B', 'C', and U+13079. + # The size is 8.0 X 8.0. + cls._TEST_FONTS["bmp-18-75dpi"] = ft.Font(cls._bmp_18_75dpi_path) + + # A fixed size bitmap mono test font made for pygame. + # It contains only a few glyphs: '\0', 'A', 'B', 'C', and U+13079. + # The size is 8.0 X 8.0. + cls._TEST_FONTS["bmp-18-100dpi"] = ft.Font(cls._bmp_18_100dpi_path) + + @classmethod + def tearDownClass(cls): + ft.quit() + + def test_freetype_defaultfont(self): + font = ft.Font(None) + self.assertEqual(font.name, "FreeSans") + + def test_freetype_Font_init(self): + + self.assertRaises( + FileNotFoundError, ft.Font, os.path.join(FONTDIR, "nonexistent.ttf") + ) + + f = self._TEST_FONTS["sans"] + self.assertIsInstance(f, ft.Font) + + f = self._TEST_FONTS["fixed"] + self.assertIsInstance(f, ft.Font) + + # Test keyword arguments + f = ft.Font(size=22, file=None) + self.assertEqual(f.size, 22) + f = ft.Font(font_index=0, file=None) + self.assertNotEqual(ft.get_default_resolution(), 100) + f = ft.Font(resolution=100, file=None) + self.assertEqual(f.resolution, 100) + f = ft.Font(ucs4=True, file=None) + self.assertTrue(f.ucs4) + self.assertRaises(OverflowError, ft.Font, file=None, size=(max_point_size + 1)) + self.assertRaises(OverflowError, ft.Font, file=None, size=-1) + + f = ft.Font(None, size=24) + self.assertTrue(f.height > 0) + self.assertRaises( + FileNotFoundError, f.__init__, os.path.join(FONTDIR, "nonexistent.ttf") + ) + + # Test attribute preservation during reinitalization + f = ft.Font(self._sans_path, size=24, ucs4=True) + self.assertEqual(f.name, "Liberation Sans") + self.assertTrue(f.scalable) + self.assertFalse(f.fixed_width) + self.assertTrue(f.antialiased) + self.assertFalse(f.oblique) + self.assertTrue(f.ucs4) + f.antialiased = False + f.oblique = True + f.__init__(self._mono_path) + self.assertEqual(f.name, "PyGameMono") + self.assertTrue(f.scalable) + self.assertTrue(f.fixed_width) + self.assertFalse(f.antialiased) + self.assertTrue(f.oblique) + self.assertTrue(f.ucs4) + + # For a bitmap font, the size is automatically set to the first + # size in the available sizes list. + f = ft.Font(self._bmp_8_75dpi_path) + sizes = f.get_sizes() + self.assertEqual(len(sizes), 1) + size_pt, width_px, height_px, x_ppem, y_ppem = sizes[0] + self.assertEqual(f.size, (x_ppem, y_ppem)) + f.__init__(self._bmp_8_75dpi_path, size=12) + self.assertEqual(f.size, 12.0) + + @unittest.skipIf(IS_PYPY, "PyPy doesn't use refcounting") + def test_freetype_Font_dealloc(self): + import sys + + handle = open(self._sans_path, "rb") + + def load_font(): + tempFont = ft.Font(handle) + + try: + load_font() + + self.assertEqual(sys.getrefcount(handle), 2) + finally: + # Ensures file is closed even if test fails. + handle.close() + + def test_freetype_Font_kerning(self): + """Ensures get/set works with the kerning property.""" + ft_font = self._TEST_FONTS["sans"] + + # Test default is disabled. + self.assertFalse(ft_font.kerning) + + # Test setting to True. + ft_font.kerning = True + + self.assertTrue(ft_font.kerning) + + # Test setting to False. + ft_font.kerning = False + + self.assertFalse(ft_font.kerning) + + def test_freetype_Font_kerning__enabled(self): + """Ensures exceptions are not raised when calling freetype methods + while kerning is enabled. + + Note: This does not test what changes occur to a rendered font by + having kerning enabled. + + Related to issue #367. + """ + surface = pygame.Surface((10, 10), 0, 32) + TEST_TEXT = "Freetype Font" + ft_font = self._TEST_FONTS["bmp-8-75dpi"] + + ft_font.kerning = True + + # Call different methods to ensure they don't raise an exception. + metrics = ft_font.get_metrics(TEST_TEXT) + self.assertIsInstance(metrics, list) + + rect = ft_font.get_rect(TEST_TEXT) + self.assertIsInstance(rect, pygame.Rect) + + font_surf, rect = ft_font.render(TEST_TEXT) + self.assertIsInstance(font_surf, pygame.Surface) + self.assertIsInstance(rect, pygame.Rect) + + rect = ft_font.render_to(surface, (0, 0), TEST_TEXT) + self.assertIsInstance(rect, pygame.Rect) + + buf, size = ft_font.render_raw(TEST_TEXT) + self.assertIsInstance(buf, bytes) + self.assertIsInstance(size, tuple) + + rect = ft_font.render_raw_to(surface.get_view("2"), TEST_TEXT) + self.assertIsInstance(rect, pygame.Rect) + + def test_freetype_Font_scalable(self): + + f = self._TEST_FONTS["sans"] + self.assertTrue(f.scalable) + + self.assertRaises(RuntimeError, lambda: nullfont().scalable) + + def test_freetype_Font_fixed_width(self): + + f = self._TEST_FONTS["sans"] + self.assertFalse(f.fixed_width) + + f = self._TEST_FONTS["mono"] + self.assertTrue(f.fixed_width) + + self.assertRaises(RuntimeError, lambda: nullfont().fixed_width) + + def test_freetype_Font_fixed_sizes(self): + + f = self._TEST_FONTS["sans"] + self.assertEqual(f.fixed_sizes, 0) + f = self._TEST_FONTS["bmp-8-75dpi"] + self.assertEqual(f.fixed_sizes, 1) + f = self._TEST_FONTS["mono"] + self.assertEqual(f.fixed_sizes, 2) + + def test_freetype_Font_get_sizes(self): + f = self._TEST_FONTS["sans"] + szlist = f.get_sizes() + self.assertIsInstance(szlist, list) + self.assertEqual(len(szlist), 0) + + f = self._TEST_FONTS["bmp-8-75dpi"] + szlist = f.get_sizes() + self.assertIsInstance(szlist, list) + self.assertEqual(len(szlist), 1) + + size8 = szlist[0] + self.assertIsInstance(size8[0], int) + self.assertEqual(size8[0], 8) + self.assertIsInstance(size8[1], int) + self.assertIsInstance(size8[2], int) + self.assertIsInstance(size8[3], float) + self.assertEqual(int(size8[3] * 64.0 + 0.5), 8 * 64) + self.assertIsInstance(size8[4], float) + self.assertEqual(int(size8[4] * 64.0 + 0.5), 8 * 64) + + f = self._TEST_FONTS["mono"] + szlist = f.get_sizes() + self.assertIsInstance(szlist, list) + self.assertEqual(len(szlist), 2) + + size8 = szlist[0] + self.assertEqual(size8[3], 8) + self.assertEqual(int(size8[3] * 64.0 + 0.5), 8 * 64) + self.assertEqual(int(size8[4] * 64.0 + 0.5), 8 * 64) + + size19 = szlist[1] + self.assertEqual(size19[3], 19) + self.assertEqual(int(size19[3] * 64.0 + 0.5), 19 * 64) + self.assertEqual(int(size19[4] * 64.0 + 0.5), 19 * 64) + + def test_freetype_Font_use_bitmap_strikes(self): + f = self._TEST_FONTS["mono"] + try: + # use_bitmap_strikes == True + # + self.assertTrue(f.use_bitmap_strikes) + + # bitmap compatible properties + s_strike, sz = f.render_raw("A", size=19) + try: + f.vertical = True + s_strike_vert, sz = f.render_raw("A", size=19) + finally: + f.vertical = False + try: + f.wide = True + s_strike_wide, sz = f.render_raw("A", size=19) + finally: + f.wide = False + try: + f.underline = True + s_strike_underline, sz = f.render_raw("A", size=19) + finally: + f.underline = False + + # bitmap incompatible properties + s_strike_rot45, sz = f.render_raw("A", size=19, rotation=45) + try: + f.strong = True + s_strike_strong, sz = f.render_raw("A", size=19) + finally: + f.strong = False + try: + f.oblique = True + s_strike_oblique, sz = f.render_raw("A", size=19) + finally: + f.oblique = False + + # compare with use_bitmap_strikes == False + # + f.use_bitmap_strikes = False + self.assertFalse(f.use_bitmap_strikes) + + # bitmap compatible properties + s_outline, sz = f.render_raw("A", size=19) + self.assertNotEqual(s_outline, s_strike) + try: + f.vertical = True + s_outline, sz = f.render_raw("A", size=19) + self.assertNotEqual(s_outline, s_strike_vert) + finally: + f.vertical = False + try: + f.wide = True + s_outline, sz = f.render_raw("A", size=19) + self.assertNotEqual(s_outline, s_strike_wide) + finally: + f.wide = False + try: + f.underline = True + s_outline, sz = f.render_raw("A", size=19) + self.assertNotEqual(s_outline, s_strike_underline) + finally: + f.underline = False + + # bitmap incompatible properties + s_outline, sz = f.render_raw("A", size=19, rotation=45) + self.assertEqual(s_outline, s_strike_rot45) + try: + f.strong = True + s_outline, sz = f.render_raw("A", size=19) + self.assertEqual(s_outline, s_strike_strong) + finally: + f.strong = False + try: + f.oblique = True + s_outline, sz = f.render_raw("A", size=19) + self.assertEqual(s_outline, s_strike_oblique) + finally: + f.oblique = False + finally: + f.use_bitmap_strikes = True + + def test_freetype_Font_bitmap_files(self): + """Ensure bitmap file restrictions are caught""" + f = self._TEST_FONTS["bmp-8-75dpi"] + f_null = nullfont() + s = pygame.Surface((10, 10), 0, 32) + a = s.get_view("3") + + exception = AttributeError + self.assertRaises(exception, setattr, f, "strong", True) + self.assertRaises(exception, setattr, f, "oblique", True) + self.assertRaises(exception, setattr, f, "style", ft.STYLE_STRONG) + self.assertRaises(exception, setattr, f, "style", ft.STYLE_OBLIQUE) + exception = RuntimeError + self.assertRaises(exception, setattr, f_null, "strong", True) + self.assertRaises(exception, setattr, f_null, "oblique", True) + self.assertRaises(exception, setattr, f_null, "style", ft.STYLE_STRONG) + self.assertRaises(exception, setattr, f_null, "style", ft.STYLE_OBLIQUE) + exception = ValueError + self.assertRaises(exception, f.render, "A", (0, 0, 0), size=8, rotation=1) + self.assertRaises( + exception, f.render, "A", (0, 0, 0), size=8, style=ft.STYLE_OBLIQUE + ) + self.assertRaises( + exception, f.render, "A", (0, 0, 0), size=8, style=ft.STYLE_STRONG + ) + self.assertRaises(exception, f.render_raw, "A", size=8, rotation=1) + self.assertRaises(exception, f.render_raw, "A", size=8, style=ft.STYLE_OBLIQUE) + self.assertRaises(exception, f.render_raw, "A", size=8, style=ft.STYLE_STRONG) + self.assertRaises( + exception, f.render_to, s, (0, 0), "A", (0, 0, 0), size=8, rotation=1 + ) + self.assertRaises( + exception, + f.render_to, + s, + (0, 0), + "A", + (0, 0, 0), + size=8, + style=ft.STYLE_OBLIQUE, + ) + self.assertRaises( + exception, + f.render_to, + s, + (0, 0), + "A", + (0, 0, 0), + size=8, + style=ft.STYLE_STRONG, + ) + self.assertRaises(exception, f.render_raw_to, a, "A", size=8, rotation=1) + self.assertRaises( + exception, f.render_raw_to, a, "A", size=8, style=ft.STYLE_OBLIQUE + ) + self.assertRaises( + exception, f.render_raw_to, a, "A", size=8, style=ft.STYLE_STRONG + ) + self.assertRaises(exception, f.get_rect, "A", size=8, rotation=1) + self.assertRaises(exception, f.get_rect, "A", size=8, style=ft.STYLE_OBLIQUE) + self.assertRaises(exception, f.get_rect, "A", size=8, style=ft.STYLE_STRONG) + + # Unsupported point size + exception = pygame.error + self.assertRaises(exception, f.get_rect, "A", size=42) + self.assertRaises(exception, f.get_metrics, "A", size=42) + self.assertRaises(exception, f.get_sized_ascender, 42) + self.assertRaises(exception, f.get_sized_descender, 42) + self.assertRaises(exception, f.get_sized_height, 42) + self.assertRaises(exception, f.get_sized_glyph_height, 42) + + def test_freetype_Font_get_metrics(self): + + font = self._TEST_FONTS["sans"] + + metrics = font.get_metrics("ABCD", size=24) + self.assertEqual(len(metrics), len("ABCD")) + self.assertIsInstance(metrics, list) + + for metrics_tuple in metrics: + self.assertIsInstance(metrics_tuple, tuple, metrics_tuple) + self.assertEqual(len(metrics_tuple), 6) + + for m in metrics_tuple[:4]: + self.assertIsInstance(m, int) + + for m in metrics_tuple[4:]: + self.assertIsInstance(m, float) + + # test for empty string + metrics = font.get_metrics("", size=24) + self.assertEqual(metrics, []) + + # test for invalid string + self.assertRaises(TypeError, font.get_metrics, 24, 24) + + # raises exception when uninitalized + self.assertRaises(RuntimeError, nullfont().get_metrics, "a", size=24) + + def test_freetype_Font_get_rect(self): + + font = self._TEST_FONTS["sans"] + + def test_rect(r): + self.assertIsInstance(r, pygame.Rect) + + rect_default = font.get_rect("ABCDabcd", size=24) + test_rect(rect_default) + self.assertTrue(rect_default.size > (0, 0)) + self.assertTrue(rect_default.width > rect_default.height) + + rect_bigger = font.get_rect("ABCDabcd", size=32) + test_rect(rect_bigger) + self.assertTrue(rect_bigger.size > rect_default.size) + + rect_strong = font.get_rect("ABCDabcd", size=24, style=ft.STYLE_STRONG) + test_rect(rect_strong) + self.assertTrue(rect_strong.size > rect_default.size) + + font.vertical = True + rect_vert = font.get_rect("ABCDabcd", size=24) + test_rect(rect_vert) + self.assertTrue(rect_vert.width < rect_vert.height) + font.vertical = False + + rect_oblique = font.get_rect("ABCDabcd", size=24, style=ft.STYLE_OBLIQUE) + test_rect(rect_oblique) + self.assertTrue(rect_oblique.width > rect_default.width) + self.assertTrue(rect_oblique.height == rect_default.height) + + rect_under = font.get_rect("ABCDabcd", size=24, style=ft.STYLE_UNDERLINE) + test_rect(rect_under) + self.assertTrue(rect_under.width == rect_default.width) + self.assertTrue(rect_under.height > rect_default.height) + + # Rect size should change if UTF surrogate pairs are treated as + # one code point or two. + ufont = self._TEST_FONTS["mono"] + rect_utf32 = ufont.get_rect("\U00013079", size=24) + rect_utf16 = ufont.get_rect("\uD80C\uDC79", size=24) + self.assertEqual(rect_utf16, rect_utf32) + ufont.ucs4 = True + try: + rect_utf16 = ufont.get_rect("\uD80C\uDC79", size=24) + finally: + ufont.ucs4 = False + self.assertNotEqual(rect_utf16, rect_utf32) + + self.assertRaises(RuntimeError, nullfont().get_rect, "a", size=24) + + # text stretching + rect12 = font.get_rect("A", size=12.0) + rect24 = font.get_rect("A", size=24.0) + rect_x = font.get_rect("A", size=(24.0, 12.0)) + self.assertEqual(rect_x.width, rect24.width) + self.assertEqual(rect_x.height, rect12.height) + rect_y = font.get_rect("A", size=(12.0, 24.0)) + self.assertEqual(rect_y.width, rect12.width) + self.assertEqual(rect_y.height, rect24.height) + + def test_freetype_Font_height(self): + + f = self._TEST_FONTS["sans"] + self.assertEqual(f.height, 2355) + + f = self._TEST_FONTS["fixed"] + self.assertEqual(f.height, 1100) + + self.assertRaises(RuntimeError, lambda: nullfont().height) + + def test_freetype_Font_name(self): + + f = self._TEST_FONTS["sans"] + self.assertEqual(f.name, "Liberation Sans") + + f = self._TEST_FONTS["fixed"] + self.assertEqual(f.name, "Inconsolata") + + nf = nullfont() + self.assertEqual(nf.name, repr(nf)) + + def test_freetype_Font_size(self): + + f = ft.Font(None, size=12) + self.assertEqual(f.size, 12) + f.size = 22 + self.assertEqual(f.size, 22) + f.size = 0 + self.assertEqual(f.size, 0) + f.size = max_point_size + self.assertEqual(f.size, max_point_size) + f.size = 6.5 + self.assertEqual(f.size, 6.5) + f.size = max_point_size_f + self.assertEqual(f.size, max_point_size_f) + self.assertRaises(OverflowError, setattr, f, "size", -1) + self.assertRaises(OverflowError, setattr, f, "size", (max_point_size + 1)) + + f.size = 24.0, 0 + size = f.size + self.assertIsInstance(size, float) + self.assertEqual(size, 24.0) + + f.size = 16, 16 + size = f.size + self.assertIsInstance(size, tuple) + self.assertEqual(len(size), 2) + + x, y = size + self.assertIsInstance(x, float) + self.assertEqual(x, 16.0) + self.assertIsInstance(y, float) + self.assertEqual(y, 16.0) + + f.size = 20.5, 22.25 + x, y = f.size + self.assertEqual(x, 20.5) + self.assertEqual(y, 22.25) + + f.size = 0, 0 + size = f.size + self.assertIsInstance(size, float) + self.assertEqual(size, 0.0) + self.assertRaises(ValueError, setattr, f, "size", (0, 24.0)) + self.assertRaises(TypeError, setattr, f, "size", (24.0,)) + self.assertRaises(TypeError, setattr, f, "size", (24.0, 0, 0)) + self.assertRaises(TypeError, setattr, f, "size", (24.0j, 24.0)) + self.assertRaises(TypeError, setattr, f, "size", (24.0, 24.0j)) + self.assertRaises(OverflowError, setattr, f, "size", (-1, 16)) + self.assertRaises(OverflowError, setattr, f, "size", (max_point_size + 1, 16)) + self.assertRaises(OverflowError, setattr, f, "size", (16, -1)) + self.assertRaises(OverflowError, setattr, f, "size", (16, max_point_size + 1)) + + # bitmap files with identical point size but differing ppems. + f75 = self._TEST_FONTS["bmp-18-75dpi"] + sizes = f75.get_sizes() + self.assertEqual(len(sizes), 1) + size_pt, width_px, height_px, x_ppem, y_ppem = sizes[0] + self.assertEqual(size_pt, 18) + self.assertEqual(x_ppem, 19.0) + self.assertEqual(y_ppem, 19.0) + rect = f75.get_rect("A", size=18) + rect = f75.get_rect("A", size=19) + rect = f75.get_rect("A", size=(19.0, 19.0)) + self.assertRaises(pygame.error, f75.get_rect, "A", size=17) + f100 = self._TEST_FONTS["bmp-18-100dpi"] + sizes = f100.get_sizes() + self.assertEqual(len(sizes), 1) + size_pt, width_px, height_px, x_ppem, y_ppem = sizes[0] + self.assertEqual(size_pt, 18) + self.assertEqual(x_ppem, 25.0) + self.assertEqual(y_ppem, 25.0) + rect = f100.get_rect("A", size=18) + rect = f100.get_rect("A", size=25) + rect = f100.get_rect("A", size=(25.0, 25.0)) + self.assertRaises(pygame.error, f100.get_rect, "A", size=17) + + def test_freetype_Font_rotation(self): + + test_angles = [ + (30, 30), + (360, 0), + (390, 30), + (720, 0), + (764, 44), + (-30, 330), + (-360, 0), + (-390, 330), + (-720, 0), + (-764, 316), + ] + + f = ft.Font(None) + self.assertEqual(f.rotation, 0) + for r, r_reduced in test_angles: + f.rotation = r + self.assertEqual( + f.rotation, + r_reduced, + "for angle %d: %d != %d" % (r, f.rotation, r_reduced), + ) + self.assertRaises(TypeError, setattr, f, "rotation", "12") + + def test_freetype_Font_render_to(self): + # Rendering to an existing target surface is equivalent to + # blitting a surface returned by Font.render with the target. + font = self._TEST_FONTS["sans"] + + surf = pygame.Surface((800, 600)) + color = pygame.Color(0, 0, 0) + + rrect = font.render_to(surf, (32, 32), "FoobarBaz", color, None, size=24) + self.assertIsInstance(rrect, pygame.Rect) + self.assertEqual(rrect.topleft, (32, 32)) + self.assertNotEqual(rrect.bottomright, (32, 32)) + + rcopy = rrect.copy() + rcopy.topleft = (32, 32) + self.assertTrue(surf.get_rect().contains(rcopy)) + + rect = pygame.Rect(20, 20, 2, 2) + rrect = font.render_to(surf, rect, "FoobarBax", color, None, size=24) + self.assertEqual(rect.topleft, rrect.topleft) + self.assertNotEqual(rrect.size, rect.size) + rrect = font.render_to(surf, (20.1, 18.9), "FoobarBax", color, None, size=24) + + rrect = font.render_to(surf, rect, "", color, None, size=24) + self.assertFalse(rrect) + self.assertEqual(rrect.height, font.get_sized_height(24)) + + # invalid surf test + self.assertRaises(TypeError, font.render_to, "not a surface", "text", color) + self.assertRaises(TypeError, font.render_to, pygame.Surface, "text", color) + + # invalid dest test + for dest in [ + None, + 0, + "a", + "ab", + (), + (1,), + ("a", 2), + (1, "a"), + (1 + 2j, 2), + (1, 1 + 2j), + (1, int), + (int, 1), + ]: + self.assertRaises( + TypeError, font.render_to, surf, dest, "foobar", color, size=24 + ) + + # misc parameter test + self.assertRaises(ValueError, font.render_to, surf, (0, 0), "foobar", color) + self.assertRaises( + TypeError, font.render_to, surf, (0, 0), "foobar", color, 2.3, size=24 + ) + self.assertRaises( + ValueError, + font.render_to, + surf, + (0, 0), + "foobar", + color, + None, + style=42, + size=24, + ) + self.assertRaises( + TypeError, + font.render_to, + surf, + (0, 0), + "foobar", + color, + None, + style=None, + size=24, + ) + self.assertRaises( + ValueError, + font.render_to, + surf, + (0, 0), + "foobar", + color, + None, + style=97, + size=24, + ) + + def test_freetype_Font_render(self): + + font = self._TEST_FONTS["sans"] + + surf = pygame.Surface((800, 600)) + color = pygame.Color(0, 0, 0) + + rend = font.render("FoobarBaz", pygame.Color(0, 0, 0), None, size=24) + self.assertIsInstance(rend, tuple) + self.assertEqual(len(rend), 2) + self.assertIsInstance(rend[0], pygame.Surface) + self.assertIsInstance(rend[1], pygame.Rect) + self.assertEqual(rend[0].get_rect().size, rend[1].size) + + s, r = font.render("", pygame.Color(0, 0, 0), None, size=24) + self.assertEqual(r.width, 0) + self.assertEqual(r.height, font.get_sized_height(24)) + self.assertEqual(s.get_size(), r.size) + self.assertEqual(s.get_bitsize(), 32) + + # misc parameter test + self.assertRaises(ValueError, font.render, "foobar", color) + self.assertRaises(TypeError, font.render, "foobar", color, 2.3, size=24) + self.assertRaises( + ValueError, font.render, "foobar", color, None, style=42, size=24 + ) + self.assertRaises( + TypeError, font.render, "foobar", color, None, style=None, size=24 + ) + self.assertRaises( + ValueError, font.render, "foobar", color, None, style=97, size=24 + ) + + # valid surrogate pairs + font2 = self._TEST_FONTS["mono"] + ucs4 = font2.ucs4 + try: + font2.ucs4 = False + rend1 = font2.render("\uD80C\uDC79", color, size=24) + rend2 = font2.render("\U00013079", color, size=24) + self.assertEqual(rend1[1], rend2[1]) + font2.ucs4 = True + rend1 = font2.render("\uD80C\uDC79", color, size=24) + self.assertNotEqual(rend1[1], rend2[1]) + finally: + font2.ucs4 = ucs4 + + # malformed surrogate pairs + self.assertRaises(UnicodeEncodeError, font.render, "\uD80C", color, size=24) + self.assertRaises(UnicodeEncodeError, font.render, "\uDCA7", color, size=24) + self.assertRaises( + UnicodeEncodeError, font.render, "\uD7FF\uDCA7", color, size=24 + ) + self.assertRaises( + UnicodeEncodeError, font.render, "\uDC00\uDCA7", color, size=24 + ) + self.assertRaises( + UnicodeEncodeError, font.render, "\uD80C\uDBFF", color, size=24 + ) + self.assertRaises( + UnicodeEncodeError, font.render, "\uD80C\uE000", color, size=24 + ) + + # raises exception when uninitalized + self.assertRaises(RuntimeError, nullfont().render, "a", (0, 0, 0), size=24) + + # Confirm the correct glpyhs are returned for a couple of + # unicode code points, 'A' and '\U00023079'. For each code point + # the rendered glyph is compared with an image of glyph bitmap + # as exported by FontForge. + path = os.path.join(FONTDIR, "A_PyGameMono-8.png") + A = pygame.image.load(path) + path = os.path.join(FONTDIR, "u13079_PyGameMono-8.png") + u13079 = pygame.image.load(path) + + font = self._TEST_FONTS["mono"] + font.ucs4 = False + A_rendered, r = font.render("A", bgcolor=pygame.Color("white"), size=8) + u13079_rendered, r = font.render( + "\U00013079", bgcolor=pygame.Color("white"), size=8 + ) + + # before comparing the surfaces, make sure they are the same + # pixel format. Use 32-bit SRCALPHA to avoid row padding and + # undefined bytes (the alpha byte will be set to 255.) + bitmap = pygame.Surface(A.get_size(), pygame.SRCALPHA, 32) + bitmap.blit(A, (0, 0)) + rendering = pygame.Surface(A_rendered.get_size(), pygame.SRCALPHA, 32) + rendering.blit(A_rendered, (0, 0)) + self.assertTrue(surf_same_image(rendering, bitmap)) + bitmap = pygame.Surface(u13079.get_size(), pygame.SRCALPHA, 32) + bitmap.blit(u13079, (0, 0)) + rendering = pygame.Surface(u13079_rendered.get_size(), pygame.SRCALPHA, 32) + rendering.blit(u13079_rendered, (0, 0)) + self.assertTrue(surf_same_image(rendering, bitmap)) + + def test_freetype_Font_render_mono(self): + font = self._TEST_FONTS["sans"] + color = pygame.Color("black") + colorkey = pygame.Color("white") + text = "." + + save_antialiased = font.antialiased + font.antialiased = False + try: + surf, r = font.render(text, color, size=24) + self.assertEqual(surf.get_bitsize(), 8) + flags = surf.get_flags() + self.assertTrue(flags & pygame.SRCCOLORKEY) + self.assertFalse(flags & (pygame.SRCALPHA | pygame.HWSURFACE)) + self.assertEqual(surf.get_colorkey(), colorkey) + self.assertIsNone(surf.get_alpha()) + + translucent_color = pygame.Color(*color) + translucent_color.a = 55 + surf, r = font.render(text, translucent_color, size=24) + self.assertEqual(surf.get_bitsize(), 8) + flags = surf.get_flags() + self.assertTrue(flags & (pygame.SRCCOLORKEY | pygame.SRCALPHA)) + self.assertFalse(flags & pygame.HWSURFACE) + self.assertEqual(surf.get_colorkey(), colorkey) + self.assertEqual(surf.get_alpha(), translucent_color.a) + + surf, r = font.render(text, color, colorkey, size=24) + self.assertEqual(surf.get_bitsize(), 32) + finally: + font.antialiased = save_antialiased + + def test_freetype_Font_render_to_mono(self): + # Blitting is done in two stages. First the target is alpha filled + # with the background color, if any. Second, the foreground + # color is alpha blitted to the background. + font = self._TEST_FONTS["sans"] + text = " ." + rect = font.get_rect(text, size=24) + size = rect.size + fg = pygame.Surface((1, 1), pygame.SRCALPHA, 32) + bg = pygame.Surface((1, 1), pygame.SRCALPHA, 32) + surrogate = pygame.Surface((1, 1), pygame.SRCALPHA, 32) + surfaces = [ + pygame.Surface(size, 0, 8), + pygame.Surface(size, 0, 16), + pygame.Surface(size, pygame.SRCALPHA, 16), + pygame.Surface(size, 0, 24), + pygame.Surface(size, 0, 32), + pygame.Surface(size, pygame.SRCALPHA, 32), + ] + fg_colors = [ + surfaces[0].get_palette_at(2), + surfaces[1].unmap_rgb(surfaces[1].map_rgb((128, 64, 200))), + surfaces[2].unmap_rgb(surfaces[2].map_rgb((99, 0, 100, 64))), + (128, 97, 213), + (128, 97, 213), + (128, 97, 213, 60), + ] + fg_colors = [pygame.Color(*c) for c in fg_colors] + self.assertEqual(len(surfaces), len(fg_colors)) # integrity check + bg_colors = [ + surfaces[0].get_palette_at(4), + surfaces[1].unmap_rgb(surfaces[1].map_rgb((220, 20, 99))), + surfaces[2].unmap_rgb(surfaces[2].map_rgb((55, 200, 0, 86))), + (255, 120, 13), + (255, 120, 13), + (255, 120, 13, 180), + ] + bg_colors = [pygame.Color(*c) for c in bg_colors] + self.assertEqual(len(surfaces), len(bg_colors)) # integrity check + + save_antialiased = font.antialiased + font.antialiased = False + try: + fill_color = pygame.Color("black") + for i, surf in enumerate(surfaces): + surf.fill(fill_color) + fg_color = fg_colors[i] + fg.set_at((0, 0), fg_color) + surf.blit(fg, (0, 0)) + r_fg_color = surf.get_at((0, 0)) + surf.set_at((0, 0), fill_color) + rrect = font.render_to(surf, (0, 0), text, fg_color, size=24) + bottomleft = 0, rrect.height - 1 + self.assertEqual( + surf.get_at(bottomleft), + fill_color, + "Position: {}. Depth: {}." + " fg_color: {}.".format(bottomleft, surf.get_bitsize(), fg_color), + ) + bottomright = rrect.width - 1, rrect.height - 1 + self.assertEqual( + surf.get_at(bottomright), + r_fg_color, + "Position: {}. Depth: {}." + " fg_color: {}.".format(bottomright, surf.get_bitsize(), fg_color), + ) + for i, surf in enumerate(surfaces): + surf.fill(fill_color) + fg_color = fg_colors[i] + bg_color = bg_colors[i] + bg.set_at((0, 0), bg_color) + fg.set_at((0, 0), fg_color) + if surf.get_bitsize() == 24: + # For a 24 bit target surface test against Pygame's alpha + # blit as there appears to be a problem with SDL's alpha + # blit: + # + # self.assertEqual(surf.get_at(bottomright), r_fg_color) + # + # raises + # + # AssertionError: (128, 97, 213, 255) != (129, 98, 213, 255) + # + surrogate.set_at((0, 0), fill_color) + surrogate.blit(bg, (0, 0)) + r_bg_color = surrogate.get_at((0, 0)) + surrogate.blit(fg, (0, 0)) + r_fg_color = surrogate.get_at((0, 0)) + else: + # Surface blit values for comparison. + surf.blit(bg, (0, 0)) + r_bg_color = surf.get_at((0, 0)) + surf.blit(fg, (0, 0)) + r_fg_color = surf.get_at((0, 0)) + surf.set_at((0, 0), fill_color) + rrect = font.render_to(surf, (0, 0), text, fg_color, bg_color, size=24) + bottomleft = 0, rrect.height - 1 + self.assertEqual(surf.get_at(bottomleft), r_bg_color) + bottomright = rrect.width - 1, rrect.height - 1 + self.assertEqual(surf.get_at(bottomright), r_fg_color) + finally: + font.antialiased = save_antialiased + + def test_freetype_Font_render_raw(self): + + font = self._TEST_FONTS["sans"] + + text = "abc" + size = font.get_rect(text, size=24).size + rend = font.render_raw(text, size=24) + self.assertIsInstance(rend, tuple) + self.assertEqual(len(rend), 2) + + r, s = rend + self.assertIsInstance(r, bytes) + self.assertIsInstance(s, tuple) + self.assertTrue(len(s), 2) + + w, h = s + self.assertIsInstance(w, int) + self.assertIsInstance(h, int) + self.assertEqual(s, size) + self.assertEqual(len(r), w * h) + + r, (w, h) = font.render_raw("", size=24) + self.assertEqual(w, 0) + self.assertEqual(h, font.height) + self.assertEqual(len(r), 0) + + # bug with decenders: this would crash + rend = font.render_raw("render_raw", size=24) + + # bug with non-printable characters: this would cause a crash + # because the text length was not adjusted for skipped characters. + text = "".join([chr(i) for i in range(31, 64)]) + rend = font.render_raw(text, size=10) + + def test_freetype_Font_render_raw_to(self): + + # This only checks that blits do not crash. It needs to check: + # - int values + # - invert option + # + + font = self._TEST_FONTS["sans"] + text = "abc" + + # No frills antialiased render to int1 (__render_glyph_INT) + srect = font.get_rect(text, size=24) + surf = pygame.Surface(srect.size, 0, 8) + rrect = font.render_raw_to(surf.get_view("2"), text, size=24) + self.assertEqual(rrect, srect) + + for bpp in [24, 32]: + surf = pygame.Surface(srect.size, 0, bpp) + rrect = font.render_raw_to(surf.get_view("r"), text, size=24) + self.assertEqual(rrect, srect) + + # Underlining to int1 (__fill_glyph_INT) + srect = font.get_rect(text, size=24, style=ft.STYLE_UNDERLINE) + surf = pygame.Surface(srect.size, 0, 8) + rrect = font.render_raw_to( + surf.get_view("2"), text, size=24, style=ft.STYLE_UNDERLINE + ) + self.assertEqual(rrect, srect) + + for bpp in [24, 32]: + surf = pygame.Surface(srect.size, 0, bpp) + rrect = font.render_raw_to( + surf.get_view("r"), text, size=24, style=ft.STYLE_UNDERLINE + ) + self.assertEqual(rrect, srect) + + # Unaliased (mono) rendering to int1 (__render_glyph_MONO_as_INT) + font.antialiased = False + try: + srect = font.get_rect(text, size=24) + surf = pygame.Surface(srect.size, 0, 8) + rrect = font.render_raw_to(surf.get_view("2"), text, size=24) + self.assertEqual(rrect, srect) + + for bpp in [24, 32]: + surf = pygame.Surface(srect.size, 0, bpp) + rrect = font.render_raw_to(surf.get_view("r"), text, size=24) + self.assertEqual(rrect, srect) + finally: + font.antialiased = True + + # Antialiased render to ints sized greater than 1 byte + # (__render_glyph_INT) + srect = font.get_rect(text, size=24) + + for bpp in [16, 24, 32]: + surf = pygame.Surface(srect.size, 0, bpp) + rrect = font.render_raw_to(surf.get_view("2"), text, size=24) + self.assertEqual(rrect, srect) + + # Underline render to ints sized greater than 1 byte + # (__fill_glyph_INT) + srect = font.get_rect(text, size=24, style=ft.STYLE_UNDERLINE) + + for bpp in [16, 24, 32]: + surf = pygame.Surface(srect.size, 0, bpp) + rrect = font.render_raw_to( + surf.get_view("2"), text, size=24, style=ft.STYLE_UNDERLINE + ) + self.assertEqual(rrect, srect) + + # Unaliased (mono) rendering to ints greater than 1 byte + # (__render_glyph_MONO_as_INT) + font.antialiased = False + try: + srect = font.get_rect(text, size=24) + + for bpp in [16, 24, 32]: + surf = pygame.Surface(srect.size, 0, bpp) + rrect = font.render_raw_to(surf.get_view("2"), text, size=24) + self.assertEqual(rrect, srect) + finally: + font.antialiased = True + + # Invalid dest parameter test. + srect = font.get_rect(text, size=24) + surf_buf = pygame.Surface(srect.size, 0, 32).get_view("2") + + for dest in [ + 0, + "a", + "ab", + (), + (1,), + ("a", 2), + (1, "a"), + (1 + 2j, 2), + (1, 1 + 2j), + (1, int), + (int, 1), + ]: + self.assertRaises( + TypeError, font.render_raw_to, surf_buf, text, dest, size=24 + ) + + def test_freetype_Font_text_is_None(self): + f = ft.Font(self._sans_path, 36) + f.style = ft.STYLE_NORMAL + f.rotation = 0 + text = "ABCD" + + # reference values + get_rect = f.get_rect(text) + f.vertical = True + get_rect_vert = f.get_rect(text) + + self.assertTrue(get_rect_vert.width < get_rect.width) + self.assertTrue(get_rect_vert.height > get_rect.height) + f.vertical = False + render_to_surf = pygame.Surface(get_rect.size, pygame.SRCALPHA, 32) + + if IS_PYPY: + return + + arr = arrinter.Array(get_rect.size, "u", 1) + render = f.render(text, (0, 0, 0)) + render_to = f.render_to(render_to_surf, (0, 0), text, (0, 0, 0)) + render_raw = f.render_raw(text) + render_raw_to = f.render_raw_to(arr, text) + + # comparisons + surf = pygame.Surface(get_rect.size, pygame.SRCALPHA, 32) + self.assertEqual(f.get_rect(None), get_rect) + s, r = f.render(None, (0, 0, 0)) + self.assertEqual(r, render[1]) + self.assertTrue(surf_same_image(s, render[0])) + r = f.render_to(surf, (0, 0), None, (0, 0, 0)) + self.assertEqual(r, render_to) + self.assertTrue(surf_same_image(surf, render_to_surf)) + px, sz = f.render_raw(None) + self.assertEqual(sz, render_raw[1]) + self.assertEqual(px, render_raw[0]) + sz = f.render_raw_to(arr, None) + self.assertEqual(sz, render_raw_to) + + def test_freetype_Font_text_is_None(self): + f = ft.Font(self._sans_path, 36) + f.style = ft.STYLE_NORMAL + f.rotation = 0 + text = "ABCD" + + # reference values + get_rect = f.get_rect(text) + f.vertical = True + get_rect_vert = f.get_rect(text) + + # vertical: trigger glyph positioning. + f.vertical = True + r = f.get_rect(None) + self.assertEqual(r, get_rect_vert) + f.vertical = False + + # wide style: trigger glyph reload + r = f.get_rect(None, style=ft.STYLE_WIDE) + self.assertEqual(r.height, get_rect.height) + self.assertTrue(r.width > get_rect.width) + r = f.get_rect(None) + self.assertEqual(r, get_rect) + + # rotated: trigger glyph reload + r = f.get_rect(None, rotation=90) + self.assertEqual(r.width, get_rect.height) + self.assertEqual(r.height, get_rect.width) + + # this method will not support None text + self.assertRaises(TypeError, f.get_metrics, None) + + def test_freetype_Font_fgcolor(self): + f = ft.Font(self._bmp_8_75dpi_path) + notdef = "\0" # the PyGameMono .notdef glyph has a pixel at (0, 0) + f.origin = False + f.pad = False + black = pygame.Color("black") # initial color + green = pygame.Color("green") + alpha128 = pygame.Color(10, 20, 30, 128) + + c = f.fgcolor + self.assertIsInstance(c, pygame.Color) + self.assertEqual(c, black) + + s, r = f.render(notdef) + self.assertEqual(s.get_at((0, 0)), black) + + f.fgcolor = green + self.assertEqual(f.fgcolor, green) + + s, r = f.render(notdef) + self.assertEqual(s.get_at((0, 0)), green) + + f.fgcolor = alpha128 + s, r = f.render(notdef) + self.assertEqual(s.get_at((0, 0)), alpha128) + + surf = pygame.Surface(f.get_rect(notdef).size, pygame.SRCALPHA, 32) + f.render_to(surf, (0, 0), None) + self.assertEqual(surf.get_at((0, 0)), alpha128) + + self.assertRaises(AttributeError, setattr, f, "fgcolor", None) + + def test_freetype_Font_bgcolor(self): + f = ft.Font(None, 32) + zero = "0" # the default font 0 glyph does not have a pixel at (0, 0) + f.origin = False + f.pad = False + + transparent_black = pygame.Color(0, 0, 0, 0) # initial color + green = pygame.Color("green") + alpha128 = pygame.Color(10, 20, 30, 128) + + c = f.bgcolor + self.assertIsInstance(c, pygame.Color) + self.assertEqual(c, transparent_black) + + s, r = f.render(zero, pygame.Color(255, 255, 255)) + self.assertEqual(s.get_at((0, 0)), transparent_black) + + f.bgcolor = green + self.assertEqual(f.bgcolor, green) + + s, r = f.render(zero) + self.assertEqual(s.get_at((0, 0)), green) + + f.bgcolor = alpha128 + s, r = f.render(zero) + self.assertEqual(s.get_at((0, 0)), alpha128) + + surf = pygame.Surface(f.get_rect(zero).size, pygame.SRCALPHA, 32) + f.render_to(surf, (0, 0), None) + self.assertEqual(surf.get_at((0, 0)), alpha128) + + self.assertRaises(AttributeError, setattr, f, "bgcolor", None) + + @unittest.skipIf(not pygame.HAVE_NEWBUF, "newbuf not implemented") + @unittest.skipIf(IS_PYPY, "pypy no likey") + def test_newbuf(self): + from pygame.tests.test_utils import buftools + + Exporter = buftools.Exporter + font = self._TEST_FONTS["sans"] + srect = font.get_rect("Hi", size=12) + for format in [ + "b", + "B", + "h", + "H", + "i", + "I", + "l", + "L", + "q", + "Q", + "x", + "1x", + "2x", + "3x", + "4x", + "5x", + "6x", + "7x", + "8x", + "9x", + "h", + "=h", + "@h", + "!h", + "1h", + "=1h", + ]: + newbuf = Exporter(srect.size, format=format) + rrect = font.render_raw_to(newbuf, "Hi", size=12) + self.assertEqual(rrect, srect) + # Some unsupported formats + for format in ["f", "d", "2h", "?", "hh"]: + newbuf = Exporter(srect.size, format=format, itemsize=4) + self.assertRaises(ValueError, font.render_raw_to, newbuf, "Hi", size=12) + + def test_freetype_Font_style(self): + + font = self._TEST_FONTS["sans"] + + # make sure STYLE_NORMAL is the default value + self.assertEqual(ft.STYLE_NORMAL, font.style) + + # make sure we check for style type + with self.assertRaises(TypeError): + font.style = "None" + with self.assertRaises(TypeError): + font.style = None + + # make sure we only accept valid constants + with self.assertRaises(ValueError): + font.style = 112 + + # make assure no assignments happened + self.assertEqual(ft.STYLE_NORMAL, font.style) + + # test assignement + font.style = ft.STYLE_UNDERLINE + self.assertEqual(ft.STYLE_UNDERLINE, font.style) + + # test complex styles + st = ft.STYLE_STRONG | ft.STYLE_UNDERLINE | ft.STYLE_OBLIQUE + + font.style = st + self.assertEqual(st, font.style) + + # and that STYLE_DEFAULT has no effect (continued from above) + self.assertNotEqual(st, ft.STYLE_DEFAULT) + font.style = ft.STYLE_DEFAULT + self.assertEqual(st, font.style) + + # revert changes + font.style = ft.STYLE_NORMAL + self.assertEqual(ft.STYLE_NORMAL, font.style) + + def test_freetype_Font_resolution(self): + text = "|" # Differs in width and height + resolution = ft.get_default_resolution() + new_font = ft.Font(self._sans_path, resolution=2 * resolution) + self.assertEqual(new_font.resolution, 2 * resolution) + size_normal = self._TEST_FONTS["sans"].get_rect(text, size=24).size + size_scaled = new_font.get_rect(text, size=24).size + size_by_2 = size_normal[0] * 2 + self.assertTrue( + size_by_2 + 2 >= size_scaled[0] >= size_by_2 - 2, + "%i not equal %i" % (size_scaled[1], size_by_2), + ) + size_by_2 = size_normal[1] * 2 + self.assertTrue( + size_by_2 + 2 >= size_scaled[1] >= size_by_2 - 2, + "%i not equal %i" % (size_scaled[1], size_by_2), + ) + new_resolution = resolution + 10 + ft.set_default_resolution(new_resolution) + try: + new_font = ft.Font(self._sans_path, resolution=0) + self.assertEqual(new_font.resolution, new_resolution) + finally: + ft.set_default_resolution() + + def test_freetype_Font_path(self): + self.assertEqual(self._TEST_FONTS["sans"].path, self._sans_path) + self.assertRaises(AttributeError, getattr, nullfont(), "path") + + # This Font cache test is conditional on freetype being built by a debug + # version of Python or with the C macro PGFT_DEBUG_CACHE defined. + def test_freetype_Font_cache(self): + glyphs = "abcde" + glen = len(glyphs) + other_glyphs = "123" + oglen = len(other_glyphs) + uempty = str("") + ## many_glyphs = (uempty.join([chr(i) for i in range(32,127)] + + ## [chr(i) for i in range(161,172)] + + ## [chr(i) for i in range(174,239)])) + many_glyphs = uempty.join([chr(i) for i in range(32, 127)]) + mglen = len(many_glyphs) + + count = 0 + access = 0 + hit = 0 + miss = 0 + + f = ft.Font(None, size=24, font_index=0, resolution=72, ucs4=False) + f.style = ft.STYLE_NORMAL + f.antialiased = True + + # Ensure debug counters are zero + self.assertEqual(f._debug_cache_stats, (0, 0, 0, 0, 0)) + # Load some basic glyphs + count = access = miss = glen + f.render_raw(glyphs) + self.assertEqual(f._debug_cache_stats, (count, 0, access, hit, miss)) + # Vertical should not affect the cache + access += glen + hit += glen + f.vertical = True + f.render_raw(glyphs) + f.vertical = False + self.assertEqual(f._debug_cache_stats, (count, 0, access, hit, miss)) + # New glyphs will + count += oglen + access += oglen + miss += oglen + f.render_raw(other_glyphs) + self.assertEqual(f._debug_cache_stats, (count, 0, access, hit, miss)) + # Point size does + count += glen + access += glen + miss += glen + f.render_raw(glyphs, size=12) + self.assertEqual(f._debug_cache_stats, (count, 0, access, hit, miss)) + # Underline style does not + access += oglen + hit += oglen + f.underline = True + f.render_raw(other_glyphs) + f.underline = False + self.assertEqual(f._debug_cache_stats, (count, 0, access, hit, miss)) + # Oblique style does + count += glen + access += glen + miss += glen + f.oblique = True + f.render_raw(glyphs) + f.oblique = False + self.assertEqual(f._debug_cache_stats, (count, 0, access, hit, miss)) + # Strong style does; by this point cache clears can happen + count += glen + access += glen + miss += glen + f.strong = True + f.render_raw(glyphs) + f.strong = False + ccount, cdelete_count, caccess, chit, cmiss = f._debug_cache_stats + self.assertEqual( + (ccount + cdelete_count, caccess, chit, cmiss), (count, access, hit, miss) + ) + # Rotation does + count += glen + access += glen + miss += glen + f.render_raw(glyphs, rotation=10) + ccount, cdelete_count, caccess, chit, cmiss = f._debug_cache_stats + self.assertEqual( + (ccount + cdelete_count, caccess, chit, cmiss), (count, access, hit, miss) + ) + # aliased (mono) glyphs do + count += oglen + access += oglen + miss += oglen + f.antialiased = False + f.render_raw(other_glyphs) + f.antialiased = True + ccount, cdelete_count, caccess, chit, cmiss = f._debug_cache_stats + self.assertEqual( + (ccount + cdelete_count, caccess, chit, cmiss), (count, access, hit, miss) + ) + # Trigger a cleanup for sure. + count += 2 * mglen + access += 2 * mglen + miss += 2 * mglen + f.get_metrics(many_glyphs, size=8) + f.get_metrics(many_glyphs, size=10) + ccount, cdelete_count, caccess, chit, cmiss = f._debug_cache_stats + self.assertTrue(ccount < count) + self.assertEqual( + (ccount + cdelete_count, caccess, chit, cmiss), (count, access, hit, miss) + ) + + try: + ft.Font._debug_cache_stats + except AttributeError: + del test_freetype_Font_cache + + def test_undefined_character_code(self): + # To be consistent with pygame.font.Font, undefined codes + # are rendered as the undefined character, and has metrics + # of None. + font = self._TEST_FONTS["sans"] + + img, size1 = font.render(chr(1), (0, 0, 0), size=24) + img, size0 = font.render("", (0, 0, 0), size=24) + self.assertTrue(size1.width > size0.width) + + metrics = font.get_metrics(chr(1) + chr(48), size=24) + self.assertEqual(len(metrics), 2) + self.assertIsNone(metrics[0]) + self.assertIsInstance(metrics[1], tuple) + + def test_issue_242(self): + """Issue #242: get_rect() uses 0 as default style""" + + # Issue #242: freetype.Font.get_rect() ignores style defaults when + # the style argument is not given + # + # The text boundary rectangle returned by freetype.Font.get_rect() + # should match the boundary of the same text rendered directly to a + # surface. This permits accurate text positioning. To work properly, + # get_rect() should calculate the text boundary to reflect text style, + # such as underline. Instead, it ignores the style settings for the + # Font object when the style argument is omitted. + # + # When the style argument is not given, freetype.get_rect() uses + # unstyled text when calculating the boundary rectangle. This is + # because _ftfont_getrect(), in _freetype.c, set the default + # style to 0 rather than FT_STYLE_DEFAULT. + # + font = self._TEST_FONTS["sans"] + + # Try wide style on a wide character. + prev_style = font.wide + font.wide = True + try: + rect = font.get_rect("M", size=64) + surf, rrect = font.render(None, size=64) + self.assertEqual(rect, rrect) + finally: + font.wide = prev_style + + # Try strong style on several wide characters. + prev_style = font.strong + font.strong = True + try: + rect = font.get_rect("Mm_", size=64) + surf, rrect = font.render(None, size=64) + self.assertEqual(rect, rrect) + finally: + font.strong = prev_style + + # Try oblique style on a tall, narrow character. + prev_style = font.oblique + font.oblique = True + try: + rect = font.get_rect("|", size=64) + surf, rrect = font.render(None, size=64) + self.assertEqual(rect, rrect) + finally: + font.oblique = prev_style + + # Try underline style on a glyphless character. + prev_style = font.underline + font.underline = True + try: + rect = font.get_rect(" ", size=64) + surf, rrect = font.render(None, size=64) + self.assertEqual(rect, rrect) + finally: + font.underline = prev_style + + def test_issue_237(self): + """Issue #237: Memory overrun when rendered with underlining""" + + # Issue #237: Memory overrun when text without descenders is rendered + # with underlining + # + # The bug crashes the Python interpreter. The bug is caught with C + # assertions in ft_render_cb.c when the Pygame module is compiled + # for debugging. So far it is only known to affect Times New Roman. + # + name = "Times New Roman" + font = ft.SysFont(name, 19) + if font.name != name: + # The font is unavailable, so skip the test. + return + font.underline = True + s, r = font.render("Amazon", size=19) + + # Some other checks to make sure nothing else broke. + for adj in [-2, -1.9, -1, 0, 1.9, 2]: + font.underline_adjustment = adj + s, r = font.render("Amazon", size=19) + + def test_issue_243(self): + """Issue Y: trailing space ignored in boundary calculation""" + + # Issue #243: For a string with trailing spaces, freetype ignores the + # last space in boundary calculations + # + font = self._TEST_FONTS["fixed"] + r1 = font.get_rect(" ", size=64) + self.assertTrue(r1.width > 1) + r2 = font.get_rect(" ", size=64) + self.assertEqual(r2.width, 2 * r1.width) + + def test_garbage_collection(self): + """Check reference counting on returned new references""" + + def ref_items(seq): + return [weakref.ref(o) for o in seq] + + font = self._TEST_FONTS["bmp-8-75dpi"] + font.size = font.get_sizes()[0][0] + text = "A" + rect = font.get_rect(text) + surf = pygame.Surface(rect.size, pygame.SRCALPHA, 32) + refs = [] + refs.extend(ref_items(font.render(text, (0, 0, 0)))) + refs.append(weakref.ref(font.render_to(surf, (0, 0), text, (0, 0, 0)))) + refs.append(weakref.ref(font.get_rect(text))) + + n = len(refs) + self.assertTrue(n > 0) + + # for pypy we garbage collection twice. + for i in range(2): + gc.collect() + + for i in range(n): + self.assertIsNone(refs[i](), "ref %d not collected" % i) + + try: + from sys import getrefcount + except ImportError: + pass + else: + array = arrinter.Array(rect.size, "u", 1) + o = font.render_raw(text) + self.assertEqual(getrefcount(o), 2) + self.assertEqual(getrefcount(o[0]), 2) + self.assertEqual(getrefcount(o[1]), 2) + self.assertEqual(getrefcount(font.render_raw_to(array, text)), 1) + o = font.get_metrics("AB") + self.assertEqual(getrefcount(o), 2) + for i in range(len(o)): + self.assertEqual(getrefcount(o[i]), 2, "refcount fail for item %d" % i) + o = font.get_sizes() + self.assertEqual(getrefcount(o), 2) + for i in range(len(o)): + self.assertEqual(getrefcount(o[i]), 2, "refcount fail for item %d" % i) + + def test_display_surface_quit(self): + """Font.render_to() on a closed display surface""" + + # The Font.render_to() method checks that PySurfaceObject.surf is NULL + # and raise a exception if it is. This fixes a bug in Pygame revision + # 0600ea4f1cfb and earlier where Pygame segfaults instead. + null_surface = pygame.Surface.__new__(pygame.Surface) + f = self._TEST_FONTS["sans"] + self.assertRaises( + pygame.error, f.render_to, null_surface, (0, 0), "Crash!", size=12 + ) + + def test_issue_565(self): + """get_metrics supporting rotation/styles/size""" + + tests = [ + {"method": "size", "value": 36, "msg": "metrics same for size"}, + {"method": "rotation", "value": 90, "msg": "metrics same for rotation"}, + {"method": "oblique", "value": True, "msg": "metrics same for oblique"}, + ] + text = "|" + + def run_test(method, value, msg): + font = ft.Font(self._sans_path, size=24) + before = font.get_metrics(text) + font.__setattr__(method, value) + after = font.get_metrics(text) + self.assertNotEqual(before, after, msg) + + for test in tests: + run_test(test["method"], test["value"], test["msg"]) + + def test_freetype_SysFont_name(self): + """that SysFont accepts names of various types""" + fonts = pygame.font.get_fonts() + size = 12 + + # Check single name string: + font_name = ft.SysFont(fonts[0], size).name + self.assertFalse(font_name is None) + + # Check string of comma-separated names. + names = ",".join(fonts) + font_name_2 = ft.SysFont(names, size).name + self.assertEqual(font_name_2, font_name) + + # Check list of names. + font_name_2 = ft.SysFont(fonts, size).name + self.assertEqual(font_name_2, font_name) + + # Check generator: + names = (name for name in fonts) + font_name_2 = ft.SysFont(names, size).name + self.assertEqual(font_name_2, font_name) + + fonts_b = [f.encode() for f in fonts] + + # Check single name bytes. + font_name_2 = ft.SysFont(fonts_b[0], size).name + self.assertEqual(font_name_2, font_name) + + # Check comma-separated bytes. + names = b",".join(fonts_b) + font_name_2 = ft.SysFont(names, size).name + self.assertEqual(font_name_2, font_name) + + # Check list of bytes. + font_name_2 = ft.SysFont(fonts_b, size).name + self.assertEqual(font_name_2, font_name) + + # Check mixed list of bytes and string. + names = [fonts[0], fonts_b[1], fonts[2], fonts_b[3]] + font_name_2 = ft.SysFont(names, size).name + self.assertEqual(font_name_2, font_name) + + def test_pathlib(self): + f = ft.Font(pathlib.Path(self._fixed_path), 20) + + +class FreeTypeTest(unittest.TestCase): + def setUp(self): + ft.init() + + def tearDown(self): + ft.quit() + + def test_resolution(self): + try: + ft.set_default_resolution() + resolution = ft.get_default_resolution() + self.assertEqual(resolution, 72) + new_resolution = resolution + 10 + ft.set_default_resolution(new_resolution) + self.assertEqual(ft.get_default_resolution(), new_resolution) + ft.init(resolution=resolution + 20) + self.assertEqual(ft.get_default_resolution(), new_resolution) + finally: + ft.set_default_resolution() + + def test_autoinit_and_autoquit(self): + pygame.init() + self.assertTrue(ft.get_init()) + pygame.quit() + self.assertFalse(ft.get_init()) + + # Ensure autoquit is replaced at init time + pygame.init() + self.assertTrue(ft.get_init()) + pygame.quit() + self.assertFalse(ft.get_init()) + + def test_init(self): + # Test if module initialized after calling init(). + ft.quit() + ft.init() + + self.assertTrue(ft.get_init()) + + def test_init__multiple(self): + # Test if module initialized after multiple init() calls. + ft.init() + ft.init() + + self.assertTrue(ft.get_init()) + + def test_quit(self): + # Test if module uninitialized after calling quit(). + ft.quit() + + self.assertFalse(ft.get_init()) + + def test_quit__multiple(self): + # Test if module initialized after multiple quit() calls. + ft.quit() + ft.quit() + + self.assertFalse(ft.get_init()) + + def test_get_init(self): + # Test if get_init() gets the init state. + self.assertTrue(ft.get_init()) + + def test_cache_size(self): + DEFAULT_CACHE_SIZE = 64 + self.assertEqual(ft.get_cache_size(), DEFAULT_CACHE_SIZE) + ft.quit() + self.assertEqual(ft.get_cache_size(), 0) + new_cache_size = DEFAULT_CACHE_SIZE * 2 + ft.init(cache_size=new_cache_size) + self.assertEqual(ft.get_cache_size(), new_cache_size) + + def test_get_error(self): + """Ensures get_error() is initially empty (None).""" + error_msg = ft.get_error() + + self.assertIsNone(error_msg) + + +if __name__ == "__main__": + unittest.main() diff --git a/venv/Lib/site-packages/pygame/tests/ftfont_tags.py b/venv/Lib/site-packages/pygame/tests/ftfont_tags.py new file mode 100644 index 0000000..0d538f4 --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/ftfont_tags.py @@ -0,0 +1,11 @@ +__tags__ = ["development"] + +exclude = False + +try: + import pygame.ftfont +except ImportError: + exclude = True + +if exclude: + __tags__.extend(["ignore", "subprocess_ignore"]) diff --git a/venv/Lib/site-packages/pygame/tests/ftfont_test.py b/venv/Lib/site-packages/pygame/tests/ftfont_test.py new file mode 100644 index 0000000..1f71204 --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/ftfont_test.py @@ -0,0 +1,19 @@ +import sys +import os +import unittest +from pygame.tests import font_test + +import pygame.ftfont + +font_test.pygame_font = pygame.ftfont +# Disable UCS-4 specific tests as this "Font" type does accept UCS-4 codes. +font_test.UCS_4 = False + +for name in dir(font_test): + obj = getattr(font_test, name) + if isinstance(obj, type) and issubclass(obj, unittest.TestCase): # conditional and + new_name = "Ft%s" % name + globals()[new_name] = type(new_name, (obj,), {}) + +if __name__ == "__main__": + unittest.main() diff --git a/venv/Lib/site-packages/pygame/tests/gfxdraw_test.py b/venv/Lib/site-packages/pygame/tests/gfxdraw_test.py new file mode 100644 index 0000000..293cef3 --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/gfxdraw_test.py @@ -0,0 +1,877 @@ +import unittest +import pygame +import pygame.gfxdraw +from pygame.locals import * +from pygame.tests.test_utils import SurfaceSubclass + + +def intensity(c, i): + """Return color c changed by intensity i + + For 0 <= i <= 127 the color is a shade, with 0 being black, 127 being the + unaltered color. + + For 128 <= i <= 255 the color is a tint, with 255 being white, 128 the + unaltered color. + + """ + r, g, b = c[0:3] + if 0 <= i <= 127: + # Darken + return ((r * i) // 127, (g * i) // 127, (b * i) // 127) + # Lighten + return ( + r + ((255 - r) * (255 - i)) // 127, + g + ((255 - g) * (255 - i)) // 127, + b + ((255 - b) * (255 - i)) // 127, + ) + + +class GfxdrawDefaultTest(unittest.TestCase): + + is_started = False + + foreground_color = (128, 64, 8) + background_color = (255, 255, 255) + + def make_palette(base_color): + """Return color palette that is various intensities of base_color""" + # Need this function for Python 3.x so the base_color + # is within the scope of the list comprehension. + return [intensity(base_color, i) for i in range(0, 256)] + + default_palette = make_palette(foreground_color) + + default_size = (100, 100) + + def check_at(self, surf, posn, color): + sc = surf.get_at(posn) + fail_msg = "%s != %s at %s, bitsize: %i, flags: %i, masks: %s" % ( + sc, + color, + posn, + surf.get_bitsize(), + surf.get_flags(), + surf.get_masks(), + ) + self.assertEqual(sc, color, fail_msg) + + def check_not_at(self, surf, posn, color): + sc = surf.get_at(posn) + fail_msg = "%s != %s at %s, bitsize: %i, flags: %i, masks: %s" % ( + sc, + color, + posn, + surf.get_bitsize(), + surf.get_flags(), + surf.get_masks(), + ) + self.assertNotEqual(sc, color, fail_msg) + + @classmethod + def setUpClass(cls): + # Necessary for Surface.set_palette. + pygame.init() + pygame.display.set_mode((1, 1)) + + @classmethod + def tearDownClass(cls): + pygame.quit() + + def setUp(self): + # This makes sure pygame is always initialized before each test (in + # case a test calls pygame.quit()). + if not pygame.get_init(): + pygame.init() + + Surface = pygame.Surface + size = self.default_size + palette = self.default_palette + if not self.is_started: + # Create test surfaces + self.surfaces = [ + Surface(size, 0, 8), + Surface(size, SRCALPHA, 16), + Surface(size, SRCALPHA, 32), + ] + self.surfaces[0].set_palette(palette) + nonpalette_fmts = ( + # (8, (0xe0, 0x1c, 0x3, 0x0)), + (12, (0xF00, 0xF0, 0xF, 0x0)), + (15, (0x7C00, 0x3E0, 0x1F, 0x0)), + (15, (0x1F, 0x3E0, 0x7C00, 0x0)), + (16, (0xF00, 0xF0, 0xF, 0xF000)), + (16, (0xF000, 0xF00, 0xF0, 0xF)), + (16, (0xF, 0xF0, 0xF00, 0xF000)), + (16, (0xF0, 0xF00, 0xF000, 0xF)), + (16, (0x7C00, 0x3E0, 0x1F, 0x8000)), + (16, (0xF800, 0x7C0, 0x3E, 0x1)), + (16, (0x1F, 0x3E0, 0x7C00, 0x8000)), + (16, (0x3E, 0x7C0, 0xF800, 0x1)), + (16, (0xF800, 0x7E0, 0x1F, 0x0)), + (16, (0x1F, 0x7E0, 0xF800, 0x0)), + (24, (0xFF, 0xFF00, 0xFF0000, 0x0)), + (24, (0xFF0000, 0xFF00, 0xFF, 0x0)), + (32, (0xFF0000, 0xFF00, 0xFF, 0x0)), + (32, (0xFF000000, 0xFF0000, 0xFF00, 0x0)), + (32, (0xFF, 0xFF00, 0xFF0000, 0x0)), + (32, (0xFF00, 0xFF0000, 0xFF000000, 0x0)), + (32, (0xFF0000, 0xFF00, 0xFF, 0xFF000000)), + (32, (0xFF000000, 0xFF0000, 0xFF00, 0xFF)), + (32, (0xFF, 0xFF00, 0xFF0000, 0xFF000000)), + (32, (0xFF00, 0xFF0000, 0xFF000000, 0xFF)), + ) + for bitsize, masks in nonpalette_fmts: + self.surfaces.append(Surface(size, 0, bitsize, masks)) + for surf in self.surfaces: + surf.fill(self.background_color) + + def test_gfxdraw__subclassed_surface(self): + """Ensure pygame.gfxdraw works on subclassed surfaces.""" + surface = SurfaceSubclass((11, 13), SRCALPHA, 32) + surface.fill(pygame.Color("blue")) + expected_color = pygame.Color("red") + x, y = 1, 2 + + pygame.gfxdraw.pixel(surface, x, y, expected_color) + + self.assertEqual(surface.get_at((x, y)), expected_color) + + def test_pixel(self): + """pixel(surface, x, y, color): return None""" + fg = self.foreground_color + bg = self.background_color + for surf in self.surfaces: + fg_adjusted = surf.unmap_rgb(surf.map_rgb(fg)) + bg_adjusted = surf.unmap_rgb(surf.map_rgb(bg)) + pygame.gfxdraw.pixel(surf, 2, 2, fg) + for x in range(1, 4): + for y in range(1, 4): + if x == 2 and y == 2: + self.check_at(surf, (x, y), fg_adjusted) + else: + self.check_at(surf, (x, y), bg_adjusted) + + def test_hline(self): + """hline(surface, x1, x2, y, color): return None""" + fg = self.foreground_color + bg = self.background_color + startx = 10 + stopx = 80 + y = 50 + fg_test_points = [(startx, y), (stopx, y), ((stopx - startx) // 2, y)] + bg_test_points = [ + (startx - 1, y), + (stopx + 1, y), + (startx, y - 1), + (startx, y + 1), + (stopx, y - 1), + (stopx, y + 1), + ] + for surf in self.surfaces: + fg_adjusted = surf.unmap_rgb(surf.map_rgb(fg)) + bg_adjusted = surf.unmap_rgb(surf.map_rgb(bg)) + pygame.gfxdraw.hline(surf, startx, stopx, y, fg) + for posn in fg_test_points: + self.check_at(surf, posn, fg_adjusted) + for posn in bg_test_points: + self.check_at(surf, posn, bg_adjusted) + + def test_vline(self): + """vline(surface, x, y1, y2, color): return None""" + fg = self.foreground_color + bg = self.background_color + x = 50 + starty = 10 + stopy = 80 + fg_test_points = [(x, starty), (x, stopy), (x, (stopy - starty) // 2)] + bg_test_points = [ + (x, starty - 1), + (x, stopy + 1), + (x - 1, starty), + (x + 1, starty), + (x - 1, stopy), + (x + 1, stopy), + ] + for surf in self.surfaces: + fg_adjusted = surf.unmap_rgb(surf.map_rgb(fg)) + bg_adjusted = surf.unmap_rgb(surf.map_rgb(bg)) + pygame.gfxdraw.vline(surf, x, starty, stopy, fg) + for posn in fg_test_points: + self.check_at(surf, posn, fg_adjusted) + for posn in bg_test_points: + self.check_at(surf, posn, bg_adjusted) + + def test_rectangle(self): + """rectangle(surface, rect, color): return None""" + fg = self.foreground_color + bg = self.background_color + rect = pygame.Rect(10, 15, 55, 62) + rect_tuple = tuple(rect) + fg_test_points = [ + rect.topleft, + (rect.right - 1, rect.top), + (rect.left, rect.bottom - 1), + (rect.right - 1, rect.bottom - 1), + ] + bg_test_points = [ + (rect.left - 1, rect.top - 1), + (rect.left + 1, rect.top + 1), + (rect.right, rect.top - 1), + (rect.right - 2, rect.top + 1), + (rect.left - 1, rect.bottom), + (rect.left + 1, rect.bottom - 2), + (rect.right, rect.bottom), + (rect.right - 2, rect.bottom - 2), + ] + for surf in self.surfaces: + fg_adjusted = surf.unmap_rgb(surf.map_rgb(fg)) + bg_adjusted = surf.unmap_rgb(surf.map_rgb(bg)) + pygame.gfxdraw.rectangle(surf, rect, fg) + for posn in fg_test_points: + self.check_at(surf, posn, fg_adjusted) + for posn in bg_test_points: + self.check_at(surf, posn, bg_adjusted) + surf.fill(bg) + pygame.gfxdraw.rectangle(surf, rect_tuple, fg) + for posn in fg_test_points: + self.check_at(surf, posn, fg_adjusted) + for posn in bg_test_points: + self.check_at(surf, posn, bg_adjusted) + + def test_box(self): + """box(surface, rect, color): return None""" + fg = self.foreground_color + bg = self.background_color + rect = pygame.Rect(10, 15, 55, 62) + rect_tuple = tuple(rect) + fg_test_points = [ + rect.topleft, + (rect.left + 1, rect.top + 1), + (rect.right - 1, rect.top), + (rect.right - 2, rect.top + 1), + (rect.left, rect.bottom - 1), + (rect.left + 1, rect.bottom - 2), + (rect.right - 1, rect.bottom - 1), + (rect.right - 2, rect.bottom - 2), + ] + bg_test_points = [ + (rect.left - 1, rect.top - 1), + (rect.right, rect.top - 1), + (rect.left - 1, rect.bottom), + (rect.right, rect.bottom), + ] + for surf in self.surfaces: + fg_adjusted = surf.unmap_rgb(surf.map_rgb(fg)) + bg_adjusted = surf.unmap_rgb(surf.map_rgb(bg)) + pygame.gfxdraw.box(surf, rect, fg) + for posn in fg_test_points: + self.check_at(surf, posn, fg_adjusted) + for posn in bg_test_points: + self.check_at(surf, posn, bg_adjusted) + surf.fill(bg) + pygame.gfxdraw.box(surf, rect_tuple, fg) + for posn in fg_test_points: + self.check_at(surf, posn, fg_adjusted) + for posn in bg_test_points: + self.check_at(surf, posn, bg_adjusted) + + def test_line(self): + """line(surface, x1, y1, x2, y2, color): return None""" + fg = self.foreground_color + bg = self.background_color + x1 = 10 + y1 = 15 + x2 = 92 + y2 = 77 + fg_test_points = [(x1, y1), (x2, y2)] + bg_test_points = [ + (x1 - 1, y1), + (x1, y1 - 1), + (x1 - 1, y1 - 1), + (x2 + 1, y2), + (x2, y2 + 1), + (x2 + 1, y2 + 1), + ] + for surf in self.surfaces: + fg_adjusted = surf.unmap_rgb(surf.map_rgb(fg)) + bg_adjusted = surf.unmap_rgb(surf.map_rgb(bg)) + pygame.gfxdraw.line(surf, x1, y1, x2, y2, fg) + for posn in fg_test_points: + self.check_at(surf, posn, fg_adjusted) + for posn in bg_test_points: + self.check_at(surf, posn, bg_adjusted) + + def test_circle(self): + """circle(surface, x, y, r, color): return None""" + fg = self.foreground_color + bg = self.background_color + x = 45 + y = 40 + r = 30 + fg_test_points = [(x, y - r), (x, y + r), (x - r, y), (x + r, y)] + bg_test_points = [ + (x, y), + (x, y - r + 1), + (x, y - r - 1), + (x, y + r + 1), + (x, y + r - 1), + (x - r - 1, y), + (x - r + 1, y), + (x + r + 1, y), + (x + r - 1, y), + ] + for surf in self.surfaces: + fg_adjusted = surf.unmap_rgb(surf.map_rgb(fg)) + bg_adjusted = surf.unmap_rgb(surf.map_rgb(bg)) + pygame.gfxdraw.circle(surf, x, y, r, fg) + for posn in fg_test_points: + self.check_at(surf, posn, fg_adjusted) + for posn in bg_test_points: + self.check_at(surf, posn, bg_adjusted) + + def test_arc(self): + """arc(surface, x, y, r, start, end, color): return None""" + fg = self.foreground_color + bg = self.background_color + x = 45 + y = 40 + r = 30 + start = 0 # +x direction, but not (x + r, y) (?) + end = 90 # -y direction, including (x, y + r) + fg_test_points = [(x, y + r), (x + r, y + 1)] + bg_test_points = [ + (x, y), + (x, y - r), + (x - r, y), + (x, y + r + 1), + (x, y + r - 1), + (x - 1, y + r), + (x + r + 1, y), + (x + r - 1, y), + (x + r, y), + ] + for surf in self.surfaces: + fg_adjusted = surf.unmap_rgb(surf.map_rgb(fg)) + bg_adjusted = surf.unmap_rgb(surf.map_rgb(bg)) + pygame.gfxdraw.arc(surf, x, y, r, start, end, fg) + for posn in fg_test_points: + self.check_at(surf, posn, fg_adjusted) + for posn in bg_test_points: + self.check_at(surf, posn, bg_adjusted) + + def test_aacircle(self): + """aacircle(surface, x, y, r, color): return None""" + fg = self.foreground_color + bg = self.background_color + x = 45 + y = 40 + r = 30 + fg_test_points = [(x, y - r), (x, y + r), (x - r, y), (x + r, y)] + bg_test_points = [ + (x, y), + (x, y - r + 1), + (x, y - r - 1), + (x, y + r + 1), + (x, y + r - 1), + (x - r - 1, y), + (x - r + 1, y), + (x + r + 1, y), + (x + r - 1, y), + ] + for surf in self.surfaces: + fg_adjusted = surf.unmap_rgb(surf.map_rgb(fg)) + bg_adjusted = surf.unmap_rgb(surf.map_rgb(bg)) + pygame.gfxdraw.aacircle(surf, x, y, r, fg) + for posn in fg_test_points: + self.check_not_at(surf, posn, bg_adjusted) + for posn in bg_test_points: + self.check_at(surf, posn, bg_adjusted) + + def test_filled_circle(self): + """filled_circle(surface, x, y, r, color): return None""" + fg = self.foreground_color + bg = self.background_color + x = 45 + y = 40 + r = 30 + fg_test_points = [ + (x, y - r), + (x, y - r + 1), + (x, y + r), + (x, y + r - 1), + (x - r, y), + (x - r + 1, y), + (x + r, y), + (x + r - 1, y), + (x, y), + ] + bg_test_points = [ + (x, y - r - 1), + (x, y + r + 1), + (x - r - 1, y), + (x + r + 1, y), + ] + for surf in self.surfaces: + fg_adjusted = surf.unmap_rgb(surf.map_rgb(fg)) + bg_adjusted = surf.unmap_rgb(surf.map_rgb(bg)) + pygame.gfxdraw.filled_circle(surf, x, y, r, fg) + for posn in fg_test_points: + self.check_at(surf, posn, fg_adjusted) + for posn in bg_test_points: + self.check_at(surf, posn, bg_adjusted) + + def test_ellipse(self): + """ellipse(surface, x, y, rx, ry, color): return None""" + fg = self.foreground_color + bg = self.background_color + x = 45 + y = 40 + rx = 30 + ry = 35 + fg_test_points = [(x, y - ry), (x, y + ry), (x - rx, y), (x + rx, y)] + bg_test_points = [ + (x, y), + (x, y - ry + 1), + (x, y - ry - 1), + (x, y + ry + 1), + (x, y + ry - 1), + (x - rx - 1, y), + (x - rx + 1, y), + (x + rx + 1, y), + (x + rx - 1, y), + ] + for surf in self.surfaces: + fg_adjusted = surf.unmap_rgb(surf.map_rgb(fg)) + bg_adjusted = surf.unmap_rgb(surf.map_rgb(bg)) + pygame.gfxdraw.ellipse(surf, x, y, rx, ry, fg) + for posn in fg_test_points: + self.check_at(surf, posn, fg_adjusted) + for posn in bg_test_points: + self.check_at(surf, posn, bg_adjusted) + + def test_aaellipse(self): + """aaellipse(surface, x, y, rx, ry, color): return None""" + fg = self.foreground_color + bg = self.background_color + x = 45 + y = 40 + rx = 30 + ry = 35 + fg_test_points = [(x, y - ry), (x, y + ry), (x - rx, y), (x + rx, y)] + bg_test_points = [ + (x, y), + (x, y - ry + 1), + (x, y - ry - 1), + (x, y + ry + 1), + (x, y + ry - 1), + (x - rx - 1, y), + (x - rx + 1, y), + (x + rx + 1, y), + (x + rx - 1, y), + ] + for surf in self.surfaces: + fg_adjusted = surf.unmap_rgb(surf.map_rgb(fg)) + bg_adjusted = surf.unmap_rgb(surf.map_rgb(bg)) + pygame.gfxdraw.aaellipse(surf, x, y, rx, ry, fg) + for posn in fg_test_points: + self.check_not_at(surf, posn, bg_adjusted) + for posn in bg_test_points: + self.check_at(surf, posn, bg_adjusted) + + def test_filled_ellipse(self): + """filled_ellipse(surface, x, y, rx, ry, color): return None""" + fg = self.foreground_color + bg = self.background_color + x = 45 + y = 40 + rx = 30 + ry = 35 + fg_test_points = [ + (x, y - ry), + (x, y - ry + 1), + (x, y + ry), + (x, y + ry - 1), + (x - rx, y), + (x - rx + 1, y), + (x + rx, y), + (x + rx - 1, y), + (x, y), + ] + bg_test_points = [ + (x, y - ry - 1), + (x, y + ry + 1), + (x - rx - 1, y), + (x + rx + 1, y), + ] + for surf in self.surfaces: + fg_adjusted = surf.unmap_rgb(surf.map_rgb(fg)) + bg_adjusted = surf.unmap_rgb(surf.map_rgb(bg)) + pygame.gfxdraw.filled_ellipse(surf, x, y, rx, ry, fg) + for posn in fg_test_points: + self.check_at(surf, posn, fg_adjusted) + for posn in bg_test_points: + self.check_at(surf, posn, bg_adjusted) + + def test_pie(self): + """pie(surface, x, y, r, start, end, color): return None""" + fg = self.foreground_color + bg = self.background_color + x = 45 + y = 40 + r = 30 + start = 0 # +x direction, including (x + r, y) + end = 90 # -y direction, but not (x, y + r) (?) + fg_test_points = [(x, y), (x + 1, y), (x, y + 1), (x + r, y)] + bg_test_points = [ + (x - 1, y), + (x, y - 1), + (x - 1, y - 1), + (x + 1, y + 1), + (x + r + 1, y), + (x + r, y - 1), + (x, y + r + 1), + ] + for surf in self.surfaces: + fg_adjusted = surf.unmap_rgb(surf.map_rgb(fg)) + bg_adjusted = surf.unmap_rgb(surf.map_rgb(bg)) + pygame.gfxdraw.pie(surf, x, y, r, start, end, fg) + for posn in fg_test_points: + self.check_at(surf, posn, fg_adjusted) + for posn in bg_test_points: + self.check_at(surf, posn, bg_adjusted) + + def test_trigon(self): + """trigon(surface, x1, y1, x2, y2, x3, y3, color): return None""" + fg = self.foreground_color + bg = self.background_color + x1 = 10 + y1 = 15 + x2 = 92 + y2 = 77 + x3 = 20 + y3 = 60 + fg_test_points = [(x1, y1), (x2, y2), (x3, y3)] + bg_test_points = [ + (x1 - 1, y1 - 1), + (x2 + 1, y2 + 1), + (x3 - 1, y3 + 1), + (x1 + 10, y1 + 30), + ] + for surf in self.surfaces: + fg_adjusted = surf.unmap_rgb(surf.map_rgb(fg)) + bg_adjusted = surf.unmap_rgb(surf.map_rgb(bg)) + pygame.gfxdraw.trigon(surf, x1, y1, x2, y2, x3, y3, fg) + for posn in fg_test_points: + self.check_at(surf, posn, fg_adjusted) + for posn in bg_test_points: + self.check_at(surf, posn, bg_adjusted) + + def test_aatrigon(self): + """aatrigon(surface, x1, y1, x2, y2, x3, y3, color): return None""" + fg = self.foreground_color + bg = self.background_color + x1 = 10 + y1 = 15 + x2 = 92 + y2 = 77 + x3 = 20 + y3 = 60 + fg_test_points = [(x1, y1), (x2, y2), (x3, y3)] + bg_test_points = [ + (x1 - 1, y1 - 1), + (x2 + 1, y2 + 1), + (x3 - 1, y3 + 1), + (x1 + 10, y1 + 30), + ] + for surf in self.surfaces: + fg_adjusted = surf.unmap_rgb(surf.map_rgb(fg)) + bg_adjusted = surf.unmap_rgb(surf.map_rgb(bg)) + pygame.gfxdraw.aatrigon(surf, x1, y1, x2, y2, x3, y3, fg) + for posn in fg_test_points: + self.check_not_at(surf, posn, bg_adjusted) + for posn in bg_test_points: + self.check_at(surf, posn, bg_adjusted) + + def test_aatrigon__with_horizontal_edge(self): + """Ensure aatrigon draws horizontal edges correctly. + + This test creates 2 surfaces and draws an aatrigon on each. The pixels + on each surface are compared to ensure they are the same. The only + difference between the 2 aatrigons is the order the points are drawn. + The order of the points should have no impact on the final drawing. + + Related to issue #622. + """ + bg_color = pygame.Color("white") + line_color = pygame.Color("black") + width, height = 11, 10 + expected_surface = pygame.Surface((width, height), 0, 32) + expected_surface.fill(bg_color) + surface = pygame.Surface((width, height), 0, 32) + surface.fill(bg_color) + + x1, y1 = width - 1, 0 + x2, y2 = (width - 1) // 2, height - 1 + x3, y3 = 0, 0 + + # The points in this order draw as expected. + pygame.gfxdraw.aatrigon(expected_surface, x1, y1, x2, y2, x3, y3, line_color) + + # The points in reverse order fail to draw the horizontal edge along + # the top. + pygame.gfxdraw.aatrigon(surface, x3, y3, x2, y2, x1, y1, line_color) + + # The surfaces are locked for a possible speed up of pixel access. + expected_surface.lock() + surface.lock() + for x in range(width): + for y in range(height): + self.assertEqual( + expected_surface.get_at((x, y)), + surface.get_at((x, y)), + "pos=({}, {})".format(x, y), + ) + + surface.unlock() + expected_surface.unlock() + + def test_filled_trigon(self): + """filled_trigon(surface, x1, y1, x2, y2, x3, y3, color): return None""" + fg = self.foreground_color + bg = self.background_color + x1 = 10 + y1 = 15 + x2 = 92 + y2 = 77 + x3 = 20 + y3 = 60 + fg_test_points = [(x1, y1), (x2, y2), (x3, y3), (x1 + 10, y1 + 30)] + bg_test_points = [(x1 - 1, y1 - 1), (x2 + 1, y2 + 1), (x3 - 1, y3 + 1)] + for surf in self.surfaces: + fg_adjusted = surf.unmap_rgb(surf.map_rgb(fg)) + bg_adjusted = surf.unmap_rgb(surf.map_rgb(bg)) + pygame.gfxdraw.filled_trigon(surf, x1, y1, x2, y2, x3, y3, fg) + for posn in fg_test_points: + self.check_at(surf, posn, fg_adjusted) + for posn in bg_test_points: + self.check_at(surf, posn, bg_adjusted) + + def test_polygon(self): + """polygon(surface, points, color): return None""" + fg = self.foreground_color + bg = self.background_color + points = [(10, 80), (10, 15), (92, 25), (92, 80)] + fg_test_points = points + [ + (points[0][0], points[0][1] - 1), + (points[0][0] + 1, points[0][1]), + (points[3][0] - 1, points[3][1]), + (points[3][0], points[3][1] - 1), + (points[2][0], points[2][1] + 1), + ] + bg_test_points = [ + (points[0][0] - 1, points[0][1]), + (points[0][0], points[0][1] + 1), + (points[0][0] - 1, points[0][1] + 1), + (points[0][0] + 1, points[0][1] - 1), + (points[3][0] + 1, points[3][1]), + (points[3][0], points[3][1] + 1), + (points[3][0] + 1, points[3][1] + 1), + (points[3][0] - 1, points[3][1] - 1), + (points[2][0] + 1, points[2][1]), + (points[2][0] - 1, points[2][1] + 1), + (points[1][0] - 1, points[1][1]), + (points[1][0], points[1][1] - 1), + (points[1][0] - 1, points[1][1] - 1), + ] + for surf in self.surfaces: + fg_adjusted = surf.unmap_rgb(surf.map_rgb(fg)) + bg_adjusted = surf.unmap_rgb(surf.map_rgb(bg)) + pygame.gfxdraw.polygon(surf, points, fg) + for posn in fg_test_points: + self.check_at(surf, posn, fg_adjusted) + for posn in bg_test_points: + self.check_at(surf, posn, bg_adjusted) + + def test_aapolygon(self): + """aapolygon(surface, points, color): return None""" + fg = self.foreground_color + bg = self.background_color + points = [(10, 80), (10, 15), (92, 25), (92, 80)] + fg_test_points = points + bg_test_points = [ + (points[0][0] - 1, points[0][1]), + (points[0][0], points[0][1] + 1), + (points[0][0] - 1, points[0][1] + 1), + (points[0][0] + 1, points[0][1] - 1), + (points[3][0] + 1, points[3][1]), + (points[3][0], points[3][1] + 1), + (points[3][0] + 1, points[3][1] + 1), + (points[3][0] - 1, points[3][1] - 1), + (points[2][0] + 1, points[2][1]), + (points[2][0] - 1, points[2][1] + 1), + (points[1][0] - 1, points[1][1]), + (points[1][0], points[1][1] - 1), + (points[1][0] - 1, points[1][1] - 1), + ] + for surf in self.surfaces: + fg_adjusted = surf.unmap_rgb(surf.map_rgb(fg)) + bg_adjusted = surf.unmap_rgb(surf.map_rgb(bg)) + pygame.gfxdraw.aapolygon(surf, points, fg) + for posn in fg_test_points: + self.check_at(surf, posn, fg_adjusted) + for posn in bg_test_points: + self.check_not_at(surf, posn, fg_adjusted) + for posn in bg_test_points: + self.check_at(surf, posn, bg_adjusted) + + def test_aapolygon__with_horizontal_edge(self): + """Ensure aapolygon draws horizontal edges correctly. + + This test creates 2 surfaces and draws a polygon on each. The pixels + on each surface are compared to ensure they are the same. The only + difference between the 2 polygons is that one is drawn using + aapolygon() and the other using multiple line() calls. They should + produce the same final drawing. + + Related to issue #622. + """ + bg_color = pygame.Color("white") + line_color = pygame.Color("black") + width, height = 11, 10 + expected_surface = pygame.Surface((width, height), 0, 32) + expected_surface.fill(bg_color) + surface = pygame.Surface((width, height), 0, 32) + surface.fill(bg_color) + + points = ((0, 0), (0, height - 1), (width - 1, height - 1), (width - 1, 0)) + + # The points are used to draw the expected aapolygon using the line() + # function. + for (x1, y1), (x2, y2) in zip(points, points[1:] + points[:1]): + pygame.gfxdraw.line(expected_surface, x1, y1, x2, y2, line_color) + + # The points in this order fail to draw the horizontal edge along + # the top. + pygame.gfxdraw.aapolygon(surface, points, line_color) + + # The surfaces are locked for a possible speed up of pixel access. + expected_surface.lock() + surface.lock() + for x in range(width): + for y in range(height): + self.assertEqual( + expected_surface.get_at((x, y)), + surface.get_at((x, y)), + "pos=({}, {})".format(x, y), + ) + + surface.unlock() + expected_surface.unlock() + + def test_filled_polygon(self): + """filled_polygon(surface, points, color): return None""" + fg = self.foreground_color + bg = self.background_color + points = [(10, 80), (10, 15), (92, 25), (92, 80)] + fg_test_points = points + [ + (points[0][0], points[0][1] - 1), + (points[0][0] + 1, points[0][1]), + (points[0][0] + 1, points[0][1] - 1), + (points[3][0] - 1, points[3][1]), + (points[3][0], points[3][1] - 1), + (points[3][0] - 1, points[3][1] - 1), + (points[2][0], points[2][1] + 1), + (points[2][0] - 1, points[2][1] + 1), + ] + bg_test_points = [ + (points[0][0] - 1, points[0][1]), + (points[0][0], points[0][1] + 1), + (points[0][0] - 1, points[0][1] + 1), + (points[3][0] + 1, points[3][1]), + (points[3][0], points[3][1] + 1), + (points[3][0] + 1, points[3][1] + 1), + (points[2][0] + 1, points[2][1]), + (points[1][0] - 1, points[1][1]), + (points[1][0], points[1][1] - 1), + (points[1][0] - 1, points[1][1] - 1), + ] + for surf in self.surfaces: + fg_adjusted = surf.unmap_rgb(surf.map_rgb(fg)) + bg_adjusted = surf.unmap_rgb(surf.map_rgb(bg)) + pygame.gfxdraw.filled_polygon(surf, points, fg) + for posn in fg_test_points: + self.check_at(surf, posn, fg_adjusted) + for posn in bg_test_points: + self.check_at(surf, posn, bg_adjusted) + + def test_textured_polygon(self): + """textured_polygon(surface, points, texture, tx, ty): return None""" + w, h = self.default_size + fg = self.foreground_color + bg = self.background_color + tx = 0 + ty = 0 + texture = pygame.Surface((w + tx, h + ty), 0, 24) + texture.fill(fg, (0, 0, w, h)) + points = [(10, 80), (10, 15), (92, 25), (92, 80)] + # Don't know how to really check this as boarder points may + # or may not be included in the textured polygon. + fg_test_points = [(points[1][0] + 30, points[1][1] + 40)] + bg_test_points = [ + (points[0][0] - 1, points[0][1]), + (points[0][0], points[0][1] + 1), + (points[0][0] - 1, points[0][1] + 1), + (points[3][0] + 1, points[3][1]), + (points[3][0], points[3][1] + 1), + (points[3][0] + 1, points[3][1] + 1), + (points[2][0] + 1, points[2][1]), + (points[1][0] - 1, points[1][1]), + (points[1][0], points[1][1] - 1), + (points[1][0] - 1, points[1][1] - 1), + ] + for surf in self.surfaces[1:]: + fg_adjusted = surf.unmap_rgb(surf.map_rgb(fg)) + bg_adjusted = surf.unmap_rgb(surf.map_rgb(bg)) + pygame.gfxdraw.textured_polygon(surf, points, texture, -tx, -ty) + for posn in fg_test_points: + self.check_at(surf, posn, fg_adjusted) + for posn in bg_test_points: + self.check_at(surf, posn, bg_adjusted) + + # Alpha blit to 8 bits-per-pixel surface forbidden. + texture = pygame.Surface(self.default_size, SRCALPHA, 32) + self.assertRaises( + ValueError, + pygame.gfxdraw.textured_polygon, + self.surfaces[0], + points, + texture, + 0, + 0, + ) + + def test_bezier(self): + """bezier(surface, points, steps, color): return None""" + fg = self.foreground_color + bg = self.background_color + points = [(10, 50), (25, 15), (60, 80), (92, 30)] + fg_test_points = [points[0], points[3]] + bg_test_points = [ + (points[0][0] - 1, points[0][1]), + (points[3][0] + 1, points[3][1]), + (points[1][0], points[1][1] + 3), + (points[2][0], points[2][1] - 3), + ] + for surf in self.surfaces: + fg_adjusted = surf.unmap_rgb(surf.map_rgb(fg)) + bg_adjusted = surf.unmap_rgb(surf.map_rgb(bg)) + pygame.gfxdraw.bezier(surf, points, 30, fg) + for posn in fg_test_points: + self.check_at(surf, posn, fg_adjusted) + for posn in bg_test_points: + self.check_at(surf, posn, bg_adjusted) + + +if __name__ == "__main__": + unittest.main() diff --git a/venv/Lib/site-packages/pygame/tests/image__save_gl_surface_test.py b/venv/Lib/site-packages/pygame/tests/image__save_gl_surface_test.py new file mode 100644 index 0000000..2932f42 --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/image__save_gl_surface_test.py @@ -0,0 +1,46 @@ +import os +import unittest + +from pygame.tests import test_utils +import pygame +from pygame.locals import * + + +@unittest.skipIf( + os.environ.get("SDL_VIDEODRIVER") == "dummy", + 'OpenGL requires a non-"dummy" SDL_VIDEODRIVER', +) +class GL_ImageSave(unittest.TestCase): + def test_image_save_works_with_opengl_surfaces(self): + """ + |tags:display,slow,opengl| + """ + + pygame.display.init() + screen = pygame.display.set_mode((640, 480), OPENGL | DOUBLEBUF) + pygame.display.flip() + + tmp_dir = test_utils.get_tmp_dir() + # Try the imageext module. + tmp_file = os.path.join(tmp_dir, "opengl_save_surface_test.png") + pygame.image.save(screen, tmp_file) + + self.assertTrue(os.path.exists(tmp_file)) + + os.remove(tmp_file) + + # Only test the image module. + tmp_file = os.path.join(tmp_dir, "opengl_save_surface_test.bmp") + pygame.image.save(screen, tmp_file) + + self.assertTrue(os.path.exists(tmp_file)) + + os.remove(tmp_file) + + # stops tonnes of tmp dirs building up in trunk dir + os.rmdir(tmp_dir) + pygame.display.quit() + + +if __name__ == "__main__": + unittest.main() diff --git a/venv/Lib/site-packages/pygame/tests/image_tags.py b/venv/Lib/site-packages/pygame/tests/image_tags.py new file mode 100644 index 0000000..d847903 --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/image_tags.py @@ -0,0 +1,7 @@ +__tags__ = [] + +import pygame +import sys + +if "pygame.image" not in sys.modules: + __tags__.extend(("ignore", "subprocess_ignore")) diff --git a/venv/Lib/site-packages/pygame/tests/image_test.py b/venv/Lib/site-packages/pygame/tests/image_test.py new file mode 100644 index 0000000..a3522fb --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/image_test.py @@ -0,0 +1,1115 @@ +# -*- coding: utf-8 -*- + +import array +import binascii +import io +import os +import tempfile +import unittest +import glob +import pathlib + +from pygame.tests.test_utils import example_path, png, tostring +import pygame, pygame.image, pygame.pkgdata + + +def test_magic(f, magic_hexes): + """Tests a given file to see if the magic hex matches.""" + data = f.read(len(magic_hexes)) + if len(data) != len(magic_hexes): + return 0 + for i, magic_hex in enumerate(magic_hexes): + if magic_hex != data[i]: + return 0 + return 1 + + +class ImageModuleTest(unittest.TestCase): + def testLoadIcon(self): + """see if we can load the pygame icon.""" + f = pygame.pkgdata.getResource("pygame_icon.bmp") + self.assertEqual(f.mode, "rb") + + surf = pygame.image.load_basic(f) + + self.assertEqual(surf.get_at((0, 0)), (5, 4, 5, 255)) + self.assertEqual(surf.get_height(), 32) + self.assertEqual(surf.get_width(), 32) + + def testLoadPNG(self): + """see if we can load a png with color values in the proper channels.""" + # Create a PNG file with known colors + reddish_pixel = (210, 0, 0, 255) + greenish_pixel = (0, 220, 0, 255) + bluish_pixel = (0, 0, 230, 255) + greyish_pixel = (110, 120, 130, 140) + pixel_array = [reddish_pixel + greenish_pixel, bluish_pixel + greyish_pixel] + + f_descriptor, f_path = tempfile.mkstemp(suffix=".png") + + with os.fdopen(f_descriptor, "wb") as f: + w = png.Writer(2, 2, alpha=True) + w.write(f, pixel_array) + + # Read the PNG file and verify that pygame interprets it correctly + surf = pygame.image.load(f_path) + + self.assertEqual(surf.get_at((0, 0)), reddish_pixel) + self.assertEqual(surf.get_at((1, 0)), greenish_pixel) + self.assertEqual(surf.get_at((0, 1)), bluish_pixel) + self.assertEqual(surf.get_at((1, 1)), greyish_pixel) + + # Read the PNG file obj. and verify that pygame interprets it correctly + with open(f_path, "rb") as f: + surf = pygame.image.load(f) + + self.assertEqual(surf.get_at((0, 0)), reddish_pixel) + self.assertEqual(surf.get_at((1, 0)), greenish_pixel) + self.assertEqual(surf.get_at((0, 1)), bluish_pixel) + self.assertEqual(surf.get_at((1, 1)), greyish_pixel) + + os.remove(f_path) + + def testLoadJPG(self): + """to see if we can load a jpg.""" + f = example_path("data/alien1.jpg") + surf = pygame.image.load(f) + + with open(f, "rb") as f: + surf = pygame.image.load(f) + + def testLoadBytesIO(self): + """to see if we can load images with BytesIO.""" + files = [ + "data/alien1.png", + "data/alien1.jpg", + "data/alien1.gif", + "data/asprite.bmp", + ] + + for fname in files: + with self.subTest(fname=fname): + with open(example_path(fname), "rb") as f: + img_bytes = f.read() + img_file = io.BytesIO(img_bytes) + image = pygame.image.load(img_file) + + def testSaveJPG(self): + """JPG equivalent to issue #211 - color channel swapping + + Make sure the SDL surface color masks represent the rgb memory format + required by the JPG library. The masks are machine endian dependent + """ + + from pygame import Color, Rect + + # The source image is a 2 by 2 square of four colors. Since JPEG is + # lossy, there can be color bleed. Make each color square 16 by 16, + # to avoid the significantly color value distorts found at color + # boundaries due to the compression value set by Pygame. + square_len = 16 + sz = 2 * square_len, 2 * square_len + + # +---------------------------------+ + # | red | green | + # |----------------+----------------| + # | blue | (255, 128, 64) | + # +---------------------------------+ + # + # as (rect, color) pairs. + def as_rect(square_x, square_y): + return Rect( + square_x * square_len, square_y * square_len, square_len, square_len + ) + + squares = [ + (as_rect(0, 0), Color("red")), + (as_rect(1, 0), Color("green")), + (as_rect(0, 1), Color("blue")), + (as_rect(1, 1), Color(255, 128, 64)), + ] + + # A surface format which is not directly usable with libjpeg. + surf = pygame.Surface(sz, 0, 32) + for rect, color in squares: + surf.fill(color, rect) + + # Assume pygame.image.Load works correctly as it is handled by the + # third party SDL_image library. + f_path = tempfile.mktemp(suffix=".jpg") + pygame.image.save(surf, f_path) + jpg_surf = pygame.image.load(f_path) + + # Allow for small differences in the restored colors. + def approx(c): + mask = 0xFC + return pygame.Color(c.r & mask, c.g & mask, c.b & mask) + + offset = square_len // 2 + for rect, color in squares: + posn = rect.move((offset, offset)).topleft + self.assertEqual(approx(jpg_surf.get_at(posn)), approx(color)) + + os.remove(f_path) + + def testSavePNG32(self): + """see if we can save a png with color values in the proper channels.""" + # Create a PNG file with known colors + reddish_pixel = (215, 0, 0, 255) + greenish_pixel = (0, 225, 0, 255) + bluish_pixel = (0, 0, 235, 255) + greyish_pixel = (115, 125, 135, 145) + + surf = pygame.Surface((1, 4), pygame.SRCALPHA, 32) + surf.set_at((0, 0), reddish_pixel) + surf.set_at((0, 1), greenish_pixel) + surf.set_at((0, 2), bluish_pixel) + surf.set_at((0, 3), greyish_pixel) + + f_path = tempfile.mktemp(suffix=".png") + pygame.image.save(surf, f_path) + + try: + # Read the PNG file and verify that pygame saved it correctly + reader = png.Reader(filename=f_path) + width, height, pixels, metadata = reader.asRGBA8() + + # pixels is a generator + self.assertEqual(tuple(next(pixels)), reddish_pixel) + self.assertEqual(tuple(next(pixels)), greenish_pixel) + self.assertEqual(tuple(next(pixels)), bluish_pixel) + self.assertEqual(tuple(next(pixels)), greyish_pixel) + + finally: + # Ensures proper clean up. + if not reader.file.closed: + reader.file.close() + del reader + os.remove(f_path) + + def testSavePNG24(self): + """see if we can save a png with color values in the proper channels.""" + # Create a PNG file with known colors + reddish_pixel = (215, 0, 0) + greenish_pixel = (0, 225, 0) + bluish_pixel = (0, 0, 235) + greyish_pixel = (115, 125, 135) + + surf = pygame.Surface((1, 4), 0, 24) + surf.set_at((0, 0), reddish_pixel) + surf.set_at((0, 1), greenish_pixel) + surf.set_at((0, 2), bluish_pixel) + surf.set_at((0, 3), greyish_pixel) + + f_path = tempfile.mktemp(suffix=".png") + pygame.image.save(surf, f_path) + + try: + # Read the PNG file and verify that pygame saved it correctly + reader = png.Reader(filename=f_path) + width, height, pixels, metadata = reader.asRGB8() + + # pixels is a generator + self.assertEqual(tuple(next(pixels)), reddish_pixel) + self.assertEqual(tuple(next(pixels)), greenish_pixel) + self.assertEqual(tuple(next(pixels)), bluish_pixel) + self.assertEqual(tuple(next(pixels)), greyish_pixel) + + finally: + # Ensures proper clean up. + if not reader.file.closed: + reader.file.close() + del reader + os.remove(f_path) + + def test_save(self): + + s = pygame.Surface((10, 10)) + s.fill((23, 23, 23)) + magic_hex = {} + magic_hex["jpg"] = [0xFF, 0xD8, 0xFF, 0xE0] + magic_hex["png"] = [0x89, 0x50, 0x4E, 0x47] + # magic_hex['tga'] = [0x0, 0x0, 0xa] + magic_hex["bmp"] = [0x42, 0x4D] + + formats = ["jpg", "png", "bmp"] + # uppercase too... JPG + formats = formats + [x.upper() for x in formats] + + for fmt in formats: + try: + temp_filename = "%s.%s" % ("tmpimg", fmt) + pygame.image.save(s, temp_filename) + + # Using 'with' ensures the file is closed even if test fails. + with open(temp_filename, "rb") as handle: + # Test the magic numbers at the start of the file to ensure + # they are saved as the correct file type. + self.assertEqual( + (1, fmt), (test_magic(handle, magic_hex[fmt.lower()]), fmt) + ) + + # load the file to make sure it was saved correctly. + # Note load can load a jpg saved with a .png file name. + s2 = pygame.image.load(temp_filename) + # compare contents, might only work reliably for png... + # but because it's all one color it seems to work with jpg. + self.assertEqual(s2.get_at((0, 0)), s.get_at((0, 0))) + finally: + # clean up the temp file, comment out to leave tmp file after run. + os.remove(temp_filename) + + def test_save_to_fileobject(self): + s = pygame.Surface((1, 1)) + s.fill((23, 23, 23)) + bytes_stream = io.BytesIO() + + pygame.image.save(s, bytes_stream) + bytes_stream.seek(0) + s2 = pygame.image.load(bytes_stream, "tga") + self.assertEqual(s.get_at((0, 0)), s2.get_at((0, 0))) + + def test_save_tga(self): + s = pygame.Surface((1, 1)) + s.fill((23, 23, 23)) + with tempfile.NamedTemporaryFile(suffix=".tga", delete=False) as f: + temp_filename = f.name + + try: + pygame.image.save(s, temp_filename) + s2 = pygame.image.load(temp_filename) + self.assertEqual(s2.get_at((0, 0)), s.get_at((0, 0))) + finally: + # clean up the temp file, even if test fails + os.remove(temp_filename) + + def test_save_pathlib(self): + surf = pygame.Surface((1, 1)) + surf.fill((23, 23, 23)) + with tempfile.NamedTemporaryFile(suffix=".tga", delete=False) as f: + temp_filename = f.name + + path = pathlib.Path(temp_filename) + try: + pygame.image.save(surf, path) + s2 = pygame.image.load(path) + self.assertEqual(s2.get_at((0, 0)), surf.get_at((0, 0))) + finally: + os.remove(temp_filename) + + def test_save__to_fileobject_w_namehint_argument(self): + s = pygame.Surface((10, 10)) + s.fill((23, 23, 23)) + magic_hex = {} + magic_hex["jpg"] = [0xFF, 0xD8, 0xFF, 0xE0] + magic_hex["png"] = [0x89, 0x50, 0x4E, 0x47] + magic_hex["bmp"] = [0x42, 0x4D] + + formats = ["tga", "jpg", "bmp", "png"] + # uppercase too... JPG + formats = formats + [x.upper() for x in formats] + + SDL_Im_version = pygame.image.get_sdl_image_version() + # We assume here that minor version and patch level of SDL_Image + # never goes above 99 + isAtLeastSDL_image_2_0_2 = (SDL_Im_version is not None) and ( + SDL_Im_version[0] * 10000 + SDL_Im_version[1] * 100 + SDL_Im_version[2] + ) >= 20002 + for fmt in formats: + tmp_file, tmp_filename = tempfile.mkstemp(suffix=".%s" % fmt) + if not isAtLeastSDL_image_2_0_2 and fmt.lower() == "jpg": + with os.fdopen(tmp_file, "wb") as handle: + with self.assertRaises(pygame.error): + pygame.image.save(s, handle, tmp_filename) + else: + with os.fdopen(tmp_file, "r+b") as handle: + pygame.image.save(s, handle, tmp_filename) + + if fmt.lower() in magic_hex: + # Test the magic numbers at the start of the file to + # ensure they are saved as the correct file type. + handle.seek(0) + self.assertEqual( + (1, fmt), (test_magic(handle, magic_hex[fmt.lower()]), fmt) + ) + # load the file to make sure it was saved correctly. + handle.flush() + handle.seek(0) + s2 = pygame.image.load(handle, tmp_filename) + self.assertEqual(s2.get_at((0, 0)), s.get_at((0, 0))) + os.remove(tmp_filename) + + def test_save_colorkey(self): + """make sure the color key is not changed when saving.""" + s = pygame.Surface((10, 10), pygame.SRCALPHA, 32) + s.fill((23, 23, 23)) + s.set_colorkey((0, 0, 0)) + colorkey1 = s.get_colorkey() + p1 = s.get_at((0, 0)) + + temp_filename = "tmpimg.png" + try: + pygame.image.save(s, temp_filename) + s2 = pygame.image.load(temp_filename) + finally: + os.remove(temp_filename) + + colorkey2 = s.get_colorkey() + # check that the pixel and the colorkey is correct. + self.assertEqual(colorkey1, colorkey2) + self.assertEqual(p1, s2.get_at((0, 0))) + + def test_load_unicode_path(self): + import shutil + + orig = example_path("data/asprite.bmp") + temp = os.path.join(example_path("data"), u"你好.bmp") + shutil.copy(orig, temp) + try: + im = pygame.image.load(temp) + finally: + os.remove(temp) + + def _unicode_save(self, temp_file): + im = pygame.Surface((10, 10), 0, 32) + try: + with open(temp_file, "w") as f: + pass + os.remove(temp_file) + except IOError: + raise unittest.SkipTest("the path cannot be opened") + + self.assertFalse(os.path.exists(temp_file)) + + try: + pygame.image.save(im, temp_file) + + self.assertGreater(os.path.getsize(temp_file), 10) + finally: + try: + os.remove(temp_file) + except EnvironmentError: + pass + + def test_save_unicode_path(self): + """save unicode object with non-ASCII chars""" + self._unicode_save(u"你好.bmp") + + def assertPremultipliedAreEqual(self, string1, string2, source_string): + self.assertEqual(len(string1), len(string2)) + block_size = 20 + if string1 != string2: + for block_start in range(0, len(string1), block_size): + block_end = min(block_start + block_size, len(string1)) + block1 = string1[block_start:block_end] + block2 = string2[block_start:block_end] + if block1 != block2: + source_block = source_string[block_start:block_end] + msg = ( + "string difference in %d to %d of %d:\n%s\n%s\nsource:\n%s" + % ( + block_start, + block_end, + len(string1), + binascii.hexlify(block1), + binascii.hexlify(block2), + binascii.hexlify(source_block), + ) + ) + self.fail(msg) + + def test_to_string__premultiplied(self): + """test to make sure we can export a surface to a premultiplied alpha string""" + + def convertRGBAtoPremultiplied(surface_to_modify): + for x in range(surface_to_modify.get_width()): + for y in range(surface_to_modify.get_height()): + color = surface_to_modify.get_at((x, y)) + premult_color = ( + color[0] * color[3] / 255, + color[1] * color[3] / 255, + color[2] * color[3] / 255, + color[3], + ) + surface_to_modify.set_at((x, y), premult_color) + + test_surface = pygame.Surface((256, 256), pygame.SRCALPHA, 32) + for x in range(test_surface.get_width()): + for y in range(test_surface.get_height()): + i = x + y * test_surface.get_width() + test_surface.set_at( + (x, y), ((i * 7) % 256, (i * 13) % 256, (i * 27) % 256, y) + ) + premultiplied_copy = test_surface.copy() + convertRGBAtoPremultiplied(premultiplied_copy) + self.assertPremultipliedAreEqual( + pygame.image.tostring(test_surface, "RGBA_PREMULT"), + pygame.image.tostring(premultiplied_copy, "RGBA"), + pygame.image.tostring(test_surface, "RGBA"), + ) + self.assertPremultipliedAreEqual( + pygame.image.tostring(test_surface, "ARGB_PREMULT"), + pygame.image.tostring(premultiplied_copy, "ARGB"), + pygame.image.tostring(test_surface, "ARGB"), + ) + + no_alpha_surface = pygame.Surface((256, 256), 0, 24) + self.assertRaises( + ValueError, pygame.image.tostring, no_alpha_surface, "RGBA_PREMULT" + ) + + # Custom assert method to check for identical surfaces. + def _assertSurfaceEqual(self, surf_a, surf_b, msg=None): + a_width, a_height = surf_a.get_width(), surf_a.get_height() + + # Check a few things to see if the surfaces are equal. + self.assertEqual(a_width, surf_b.get_width(), msg) + self.assertEqual(a_height, surf_b.get_height(), msg) + self.assertEqual(surf_a.get_size(), surf_b.get_size(), msg) + self.assertEqual(surf_a.get_rect(), surf_b.get_rect(), msg) + self.assertEqual(surf_a.get_colorkey(), surf_b.get_colorkey(), msg) + self.assertEqual(surf_a.get_alpha(), surf_b.get_alpha(), msg) + self.assertEqual(surf_a.get_flags(), surf_b.get_flags(), msg) + self.assertEqual(surf_a.get_bitsize(), surf_b.get_bitsize(), msg) + self.assertEqual(surf_a.get_bytesize(), surf_b.get_bytesize(), msg) + # Anything else? + + # Making the method lookups local for a possible speed up. + surf_a_get_at = surf_a.get_at + surf_b_get_at = surf_b.get_at + for y in range(a_height): + for x in range(a_width): + self.assertEqual( + surf_a_get_at((x, y)), + surf_b_get_at((x, y)), + "%s (pixel: %d, %d)" % (msg, x, y), + ) + + def test_fromstring__and_tostring(self): + """Ensure methods tostring() and fromstring() are symmetric.""" + + #################################################################### + def RotateRGBAtoARGB(str_buf): + byte_buf = array.array("B", str_buf) + num_quads = len(byte_buf) // 4 + for i in range(num_quads): + alpha = byte_buf[i * 4 + 3] + byte_buf[i * 4 + 3] = byte_buf[i * 4 + 2] + byte_buf[i * 4 + 2] = byte_buf[i * 4 + 1] + byte_buf[i * 4 + 1] = byte_buf[i * 4 + 0] + byte_buf[i * 4 + 0] = alpha + return tostring(byte_buf) + + #################################################################### + def RotateARGBtoRGBA(str_buf): + byte_buf = array.array("B", str_buf) + num_quads = len(byte_buf) // 4 + for i in range(num_quads): + alpha = byte_buf[i * 4 + 0] + byte_buf[i * 4 + 0] = byte_buf[i * 4 + 1] + byte_buf[i * 4 + 1] = byte_buf[i * 4 + 2] + byte_buf[i * 4 + 2] = byte_buf[i * 4 + 3] + byte_buf[i * 4 + 3] = alpha + return tostring(byte_buf) + + #################################################################### + test_surface = pygame.Surface((64, 256), flags=pygame.SRCALPHA, depth=32) + for i in range(256): + for j in range(16): + intensity = j * 16 + 15 + test_surface.set_at((j + 0, i), (intensity, i, i, i)) + test_surface.set_at((j + 16, i), (i, intensity, i, i)) + test_surface.set_at((j + 32, i), (i, i, intensity, i)) + test_surface.set_at((j + 32, i), (i, i, i, intensity)) + + self._assertSurfaceEqual( + test_surface, test_surface, "failing with identical surfaces" + ) + + rgba_buf = pygame.image.tostring(test_surface, "RGBA") + rgba_buf = RotateARGBtoRGBA(RotateRGBAtoARGB(rgba_buf)) + test_rotate_functions = pygame.image.fromstring( + rgba_buf, test_surface.get_size(), "RGBA" + ) + + self._assertSurfaceEqual( + test_surface, test_rotate_functions, "rotate functions are not symmetric" + ) + + rgba_buf = pygame.image.tostring(test_surface, "RGBA") + argb_buf = RotateRGBAtoARGB(rgba_buf) + test_from_argb_string = pygame.image.fromstring( + argb_buf, test_surface.get_size(), "ARGB" + ) + + self._assertSurfaceEqual( + test_surface, test_from_argb_string, '"RGBA" rotated to "ARGB" failed' + ) + + argb_buf = pygame.image.tostring(test_surface, "ARGB") + rgba_buf = RotateARGBtoRGBA(argb_buf) + test_to_argb_string = pygame.image.fromstring( + rgba_buf, test_surface.get_size(), "RGBA" + ) + + self._assertSurfaceEqual( + test_surface, test_to_argb_string, '"ARGB" rotated to "RGBA" failed' + ) + + for fmt in ("ARGB", "RGBA"): + fmt_buf = pygame.image.tostring(test_surface, fmt) + test_to_from_fmt_string = pygame.image.fromstring( + fmt_buf, test_surface.get_size(), fmt + ) + + self._assertSurfaceEqual( + test_surface, + test_to_from_fmt_string, + "tostring/fromstring functions are not " + 'symmetric with "{}" format'.format(fmt), + ) + + def test_tostring_depth_24(self): + test_surface = pygame.Surface((64, 256), depth=24) + for i in range(256): + for j in range(16): + intensity = j * 16 + 15 + test_surface.set_at((j + 0, i), (intensity, i, i, i)) + test_surface.set_at((j + 16, i), (i, intensity, i, i)) + test_surface.set_at((j + 32, i), (i, i, intensity, i)) + test_surface.set_at((j + 32, i), (i, i, i, intensity)) + + fmt = "RGB" + fmt_buf = pygame.image.tostring(test_surface, fmt) + test_to_from_fmt_string = pygame.image.fromstring( + fmt_buf, test_surface.get_size(), fmt + ) + + self._assertSurfaceEqual( + test_surface, + test_to_from_fmt_string, + "tostring/fromstring functions are not " + 'symmetric with "{}" format'.format(fmt), + ) + + def test_frombuffer_8bit(self): + """test reading pixel data from a bytes buffer""" + pygame.display.init() + eight_bit_palette_buffer = bytearray( + [0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3] + ) + + eight_bit_surf = pygame.image.frombuffer(eight_bit_palette_buffer, (4, 4), "P") + eight_bit_surf.set_palette( + [(255, 10, 20), (255, 255, 255), (0, 0, 0), (50, 200, 20)] + ) + self.assertEqual(eight_bit_surf.get_at((0, 0)), pygame.Color(255, 10, 20)) + self.assertEqual(eight_bit_surf.get_at((1, 1)), pygame.Color(255, 255, 255)) + self.assertEqual(eight_bit_surf.get_at((2, 2)), pygame.Color(0, 0, 0)) + self.assertEqual(eight_bit_surf.get_at((3, 3)), pygame.Color(50, 200, 20)) + + def test_frombuffer_RGB(self): + rgb_buffer = bytearray( + [ + 255, + 10, + 20, + 255, + 10, + 20, + 255, + 10, + 20, + 255, + 10, + 20, + 255, + 255, + 255, + 255, + 255, + 255, + 255, + 255, + 255, + 255, + 255, + 255, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 50, + 200, + 20, + 50, + 200, + 20, + 50, + 200, + 20, + 50, + 200, + 20, + ] + ) + + rgb_surf = pygame.image.frombuffer(rgb_buffer, (4, 4), "RGB") + self.assertEqual(rgb_surf.get_at((0, 0)), pygame.Color(255, 10, 20)) + self.assertEqual(rgb_surf.get_at((1, 1)), pygame.Color(255, 255, 255)) + self.assertEqual(rgb_surf.get_at((2, 2)), pygame.Color(0, 0, 0)) + self.assertEqual(rgb_surf.get_at((3, 3)), pygame.Color(50, 200, 20)) + + def test_frombuffer_BGR(self): + bgr_buffer = bytearray( + [ + 20, + 10, + 255, + 20, + 10, + 255, + 20, + 10, + 255, + 20, + 10, + 255, + 255, + 255, + 255, + 255, + 255, + 255, + 255, + 255, + 255, + 255, + 255, + 255, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 20, + 200, + 50, + 20, + 200, + 50, + 20, + 200, + 50, + 20, + 200, + 50, + ] + ) + + bgr_surf = pygame.image.frombuffer(bgr_buffer, (4, 4), "BGR") + self.assertEqual(bgr_surf.get_at((0, 0)), pygame.Color(255, 10, 20)) + self.assertEqual(bgr_surf.get_at((1, 1)), pygame.Color(255, 255, 255)) + self.assertEqual(bgr_surf.get_at((2, 2)), pygame.Color(0, 0, 0)) + self.assertEqual(bgr_surf.get_at((3, 3)), pygame.Color(50, 200, 20)) + + def test_frombuffer_RGBX(self): + rgbx_buffer = bytearray( + [ + 255, + 10, + 20, + 255, + 255, + 10, + 20, + 255, + 255, + 10, + 20, + 255, + 255, + 10, + 20, + 255, + 255, + 255, + 255, + 255, + 255, + 255, + 255, + 255, + 255, + 255, + 255, + 255, + 255, + 255, + 255, + 255, + 0, + 0, + 0, + 255, + 0, + 0, + 0, + 255, + 0, + 0, + 0, + 255, + 0, + 0, + 0, + 255, + 50, + 200, + 20, + 255, + 50, + 200, + 20, + 255, + 50, + 200, + 20, + 255, + 50, + 200, + 20, + 255, + ] + ) + + rgbx_surf = pygame.image.frombuffer(rgbx_buffer, (4, 4), "RGBX") + self.assertEqual(rgbx_surf.get_at((0, 0)), pygame.Color(255, 10, 20, 255)) + self.assertEqual(rgbx_surf.get_at((1, 1)), pygame.Color(255, 255, 255, 255)) + self.assertEqual(rgbx_surf.get_at((2, 2)), pygame.Color(0, 0, 0, 255)) + self.assertEqual(rgbx_surf.get_at((3, 3)), pygame.Color(50, 200, 20, 255)) + + def test_frombuffer_RGBA(self): + rgba_buffer = bytearray( + [ + 255, + 10, + 20, + 200, + 255, + 10, + 20, + 200, + 255, + 10, + 20, + 200, + 255, + 10, + 20, + 200, + 255, + 255, + 255, + 127, + 255, + 255, + 255, + 127, + 255, + 255, + 255, + 127, + 255, + 255, + 255, + 127, + 0, + 0, + 0, + 79, + 0, + 0, + 0, + 79, + 0, + 0, + 0, + 79, + 0, + 0, + 0, + 79, + 50, + 200, + 20, + 255, + 50, + 200, + 20, + 255, + 50, + 200, + 20, + 255, + 50, + 200, + 20, + 255, + ] + ) + + rgba_surf = pygame.image.frombuffer(rgba_buffer, (4, 4), "RGBA") + self.assertEqual(rgba_surf.get_at((0, 0)), pygame.Color(255, 10, 20, 200)) + self.assertEqual(rgba_surf.get_at((1, 1)), pygame.Color(255, 255, 255, 127)) + self.assertEqual(rgba_surf.get_at((2, 2)), pygame.Color(0, 0, 0, 79)) + self.assertEqual(rgba_surf.get_at((3, 3)), pygame.Color(50, 200, 20, 255)) + + def test_frombuffer_ARGB(self): + argb_buffer = bytearray( + [ + 200, + 255, + 10, + 20, + 200, + 255, + 10, + 20, + 200, + 255, + 10, + 20, + 200, + 255, + 10, + 20, + 127, + 255, + 255, + 255, + 127, + 255, + 255, + 255, + 127, + 255, + 255, + 255, + 127, + 255, + 255, + 255, + 79, + 0, + 0, + 0, + 79, + 0, + 0, + 0, + 79, + 0, + 0, + 0, + 79, + 0, + 0, + 0, + 255, + 50, + 200, + 20, + 255, + 50, + 200, + 20, + 255, + 50, + 200, + 20, + 255, + 50, + 200, + 20, + ] + ) + + argb_surf = pygame.image.frombuffer(argb_buffer, (4, 4), "ARGB") + self.assertEqual(argb_surf.get_at((0, 0)), pygame.Color(255, 10, 20, 200)) + self.assertEqual(argb_surf.get_at((1, 1)), pygame.Color(255, 255, 255, 127)) + self.assertEqual(argb_surf.get_at((2, 2)), pygame.Color(0, 0, 0, 79)) + self.assertEqual(argb_surf.get_at((3, 3)), pygame.Color(50, 200, 20, 255)) + + def test_get_extended(self): + # Create a png file and try to load it. If it cannot, get_extended() should return False + raw_image = [] + raw_image.append((200, 200, 200, 255, 100, 100, 100, 255)) + + f_descriptor, f_path = tempfile.mkstemp(suffix=".png") + + with os.fdopen(f_descriptor, "wb") as file: + w = png.Writer(2, 1, alpha=True) + w.write(file, raw_image) + + try: + surf = pygame.image.load(f_path) + loaded = True + except pygame.error: + loaded = False + + self.assertEqual(pygame.image.get_extended(), loaded) + os.remove(f_path) + + def test_get_sdl_image_version(self): + # If get_extended() returns False then get_sdl_image_version() should + # return None + if not pygame.image.get_extended(): + self.assertIsNone(pygame.image.get_sdl_image_version()) + else: + expected_length = 3 + expected_type = tuple + expected_item_type = int + + version = pygame.image.get_sdl_image_version() + + self.assertIsInstance(version, expected_type) + self.assertEqual(len(version), expected_length) + + for item in version: + self.assertIsInstance(item, expected_item_type) + + def test_load_basic(self): + """to see if we can load bmp from files and/or file-like objects in memory""" + + # pygame.image.load(filename): return Surface + + # test loading from a file + s = pygame.image.load_basic(example_path("data/asprite.bmp")) + self.assertEqual(s.get_at((0, 0)), (255, 255, 255, 255)) + + # test loading from io.BufferedReader + f = pygame.pkgdata.getResource("pygame_icon.bmp") + self.assertEqual(f.mode, "rb") + + surf = pygame.image.load_basic(f) + + self.assertEqual(surf.get_at((0, 0)), (5, 4, 5, 255)) + self.assertEqual(surf.get_height(), 32) + self.assertEqual(surf.get_width(), 32) + + f.close() + + def test_load_extended(self): + """can load different format images. + + We test loading the following file types: + bmp, png, jpg, gif (non-animated), pcx, tga (uncompressed), tif, xpm, ppm, pgm + Following file types are tested when using SDL 2 + svg, pnm, webp + All the loaded images are smaller than 32 x 32 pixels. + """ + + filename_expected_color = [ + ("asprite.bmp", (255, 255, 255, 255)), + ("laplacian.png", (10, 10, 70, 255)), + ("red.jpg", (254, 0, 0, 255)), + ("blue.gif", (0, 0, 255, 255)), + ("green.pcx", (0, 255, 0, 255)), + ("yellow.tga", (255, 255, 0, 255)), + ("turquoise.tif", (0, 255, 255, 255)), + ("purple.xpm", (255, 0, 255, 255)), + ("black.ppm", (0, 0, 0, 255)), + ("grey.pgm", (120, 120, 120, 255)), + ("teal.svg", (0, 128, 128, 255)), + ("crimson.pnm", (220, 20, 60, 255)), + ("scarlet.webp", (252, 14, 53, 255)), + ] + + for filename, expected_color in filename_expected_color: + with self.subTest( + "Test loading a " + filename.split(".")[-1], + filename="examples/data/" + filename, + expected_color=expected_color, + ): + surf = pygame.image.load_extended(example_path("data/" + filename)) + self.assertEqual(surf.get_at((0, 0)), expected_color) + + def test_load_pathlib(self): + """works loading using a Path argument.""" + path = pathlib.Path(example_path("data/asprite.bmp")) + surf = pygame.image.load_extended(path) + self.assertEqual(surf.get_at((0, 0)), (255, 255, 255, 255)) + + def test_save_extended(self): + surf = pygame.Surface((5, 5)) + surf.fill((23, 23, 23)) + + passing_formats = ["jpg", "png"] + passing_formats += [fmt.upper() for fmt in passing_formats] + + magic_hex = {} + magic_hex["jpg"] = [0xFF, 0xD8, 0xFF, 0xE0] + magic_hex["png"] = [0x89, 0x50, 0x4E, 0x47] + + failing_formats = ["bmp", "tga"] + failing_formats += [fmt.upper() for fmt in failing_formats] + + # check that .jpg and .png save + for fmt in passing_formats: + temp_file_name = "temp_file.%s" % fmt + # save image as .jpg and .png + pygame.image.save_extended(surf, temp_file_name) + with open(temp_file_name, "rb") as file: + # Test the magic numbers at the start of the file to ensure + # they are saved as the correct file type. + self.assertEqual(1, (test_magic(file, magic_hex[fmt.lower()]))) + # load the file to make sure it was saved correctly + loaded_file = pygame.image.load(temp_file_name) + self.assertEqual(loaded_file.get_at((0, 0)), surf.get_at((0, 0))) + # clean up the temp file + os.remove(temp_file_name) + # check that .bmp and .tga do not save + for fmt in failing_formats: + self.assertRaises( + pygame.error, pygame.image.save_extended, surf, "temp_file.%s" % fmt + ) + + def threads_load(self, images): + import pygame.threads + + for i in range(10): + surfs = pygame.threads.tmap(pygame.image.load, images) + for s in surfs: + self.assertIsInstance(s, pygame.Surface) + + def test_load_png_threads(self): + self.threads_load(glob.glob(example_path("data/*.png"))) + + def test_load_jpg_threads(self): + self.threads_load(glob.glob(example_path("data/*.jpg"))) + + def test_load_bmp_threads(self): + self.threads_load(glob.glob(example_path("data/*.bmp"))) + + def test_load_gif_threads(self): + self.threads_load(glob.glob(example_path("data/*.gif"))) + + +if __name__ == "__main__": + unittest.main() diff --git a/venv/Lib/site-packages/pygame/tests/imageext_tags.py b/venv/Lib/site-packages/pygame/tests/imageext_tags.py new file mode 100644 index 0000000..25cff74 --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/imageext_tags.py @@ -0,0 +1,7 @@ +__tags__ = [] + +import pygame +import sys + +if "pygame.imageext" not in sys.modules: + __tags__.extend(("ignore", "subprocess_ignore")) diff --git a/venv/Lib/site-packages/pygame/tests/imageext_test.py b/venv/Lib/site-packages/pygame/tests/imageext_test.py new file mode 100644 index 0000000..19faf83 --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/imageext_test.py @@ -0,0 +1,94 @@ +# -*- coding: utf8 -*- +import os +import os.path +import sys +import unittest + +from pygame.tests.test_utils import example_path +import pygame, pygame.image, pygame.pkgdata + + +imageext = sys.modules["pygame.imageext"] + + +class ImageextModuleTest(unittest.TestCase): + # Most of the testing is done indirectly through image_test.py + # This just confirms file path encoding and error handling. + def test_save_non_string_file(self): + im = pygame.Surface((10, 10), 0, 32) + self.assertRaises(TypeError, imageext.save_extended, im, []) + + def test_load_non_string_file(self): + self.assertRaises(TypeError, imageext.load_extended, []) + + @unittest.skip("SDL silently removes invalid characters") + def test_save_bad_filename(self): + im = pygame.Surface((10, 10), 0, 32) + u = u"a\x00b\x00c.png" + self.assertRaises(pygame.error, imageext.save_extended, im, u) + + @unittest.skip("SDL silently removes invalid characters") + def test_load_bad_filename(self): + u = u"a\x00b\x00c.png" + self.assertRaises(pygame.error, imageext.load_extended, u) + + def test_save_unknown_extension(self): + im = pygame.Surface((10, 10), 0, 32) + s = "foo.bar" + self.assertRaises(pygame.error, imageext.save_extended, im, s) + + def test_load_unknown_extension(self): + s = "foo.bar" + self.assertRaises(FileNotFoundError, imageext.load_extended, s) + + def test_load_unknown_file(self): + s = "nonexistent.png" + self.assertRaises(FileNotFoundError, imageext.load_extended, s) + + def test_load_unicode_path_0(self): + u = example_path("data/alien1.png") + im = imageext.load_extended(u) + + def test_load_unicode_path_1(self): + """non-ASCII unicode""" + import shutil + + orig = example_path("data/alien1.png") + temp = os.path.join(example_path("data"), u"你好.png") + shutil.copy(orig, temp) + try: + im = imageext.load_extended(temp) + finally: + os.remove(temp) + + def _unicode_save(self, temp_file): + im = pygame.Surface((10, 10), 0, 32) + try: + with open(temp_file, "w") as f: + pass + os.remove(temp_file) + except IOError: + raise unittest.SkipTest("the path cannot be opened") + + self.assertFalse(os.path.exists(temp_file)) + + try: + imageext.save_extended(im, temp_file) + + self.assertGreater(os.path.getsize(temp_file), 10) + finally: + try: + os.remove(temp_file) + except EnvironmentError: + pass + + def test_save_unicode_path_0(self): + """unicode object with ASCII chars""" + self._unicode_save(u"temp_file.png") + + def test_save_unicode_path_1(self): + self._unicode_save(u"你好.png") + + +if __name__ == "__main__": + unittest.main() diff --git a/venv/Lib/site-packages/pygame/tests/joystick_test.py b/venv/Lib/site-packages/pygame/tests/joystick_test.py new file mode 100644 index 0000000..e8cea2d --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/joystick_test.py @@ -0,0 +1,172 @@ +import unittest +from pygame.tests.test_utils import question, prompt + +import pygame +import pygame._sdl2.controller + + +class JoystickTypeTest(unittest.TestCase): + def todo_test_Joystick(self): + + # __doc__ (as of 2008-08-02) for pygame.joystick.Joystick: + + # pygame.joystick.Joystick(id): return Joystick + # create a new Joystick object + # + # Create a new joystick to access a physical device. The id argument + # must be a value from 0 to pygame.joystick.get_count()-1. + # + # To access most of the Joystick methods, you'll need to init() the + # Joystick. This is separate from making sure the joystick module is + # initialized. When multiple Joysticks objects are created for the + # same physical joystick device (i.e., they have the same ID number), + # the state and values for those Joystick objects will be shared. + # + # The Joystick object allows you to get information about the types of + # controls on a joystick device. Once the device is initialized the + # Pygame event queue will start receiving events about its input. + # + # You can call the Joystick.get_name() and Joystick.get_id() functions + # without initializing the Joystick object. + # + + self.fail() + + +class JoystickModuleTest(unittest.TestCase): + def test_get_init(self): + # Check that get_init() matches what is actually happening + def error_check_get_init(): + try: + pygame.joystick.get_count() + except pygame.error: + return False + return True + + # Start uninitialised + self.assertEqual(pygame.joystick.get_init(), False) + + pygame.joystick.init() + self.assertEqual(pygame.joystick.get_init(), error_check_get_init()) # True + pygame.joystick.quit() + self.assertEqual(pygame.joystick.get_init(), error_check_get_init()) # False + + pygame.joystick.init() + pygame.joystick.init() + self.assertEqual(pygame.joystick.get_init(), error_check_get_init()) # True + pygame.joystick.quit() + self.assertEqual(pygame.joystick.get_init(), error_check_get_init()) # False + + pygame.joystick.quit() + self.assertEqual(pygame.joystick.get_init(), error_check_get_init()) # False + + for i in range(100): + pygame.joystick.init() + self.assertEqual(pygame.joystick.get_init(), error_check_get_init()) # True + pygame.joystick.quit() + self.assertEqual(pygame.joystick.get_init(), error_check_get_init()) # False + + for i in range(100): + pygame.joystick.quit() + self.assertEqual(pygame.joystick.get_init(), error_check_get_init()) # False + + def test_init(self): + """ + This unit test is for joystick.init() + It was written to help reduce maintenance costs + and to help test against changes to the code or + different platforms. + """ + pygame.quit() + # test that pygame.init automatically calls joystick.init + pygame.init() + self.assertEqual(pygame.joystick.get_init(), True) + + # Controller module interferes with the joystick module. + pygame._sdl2.controller.quit() + + # test that get_count doesn't work w/o joystick init + # this is done before and after an init to test + # that init activates the joystick functions + pygame.joystick.quit() + with self.assertRaises(pygame.error): + pygame.joystick.get_count() + + # test explicit call(s) to joystick.init. + # Also test that get_count works once init is called + iterations = 20 + for i in range(iterations): + pygame.joystick.init() + self.assertEqual(pygame.joystick.get_init(), True) + self.assertIsNotNone(pygame.joystick.get_count()) + + def test_quit(self): + """Test if joystick.quit works.""" + + pygame.joystick.init() + + self.assertIsNotNone(pygame.joystick.get_count()) # Is not None before quit + + pygame.joystick.quit() + + with self.assertRaises(pygame.error): # Raises error if quit worked + pygame.joystick.get_count() + + def test_get_count(self): + # Test that get_count correctly returns a non-negative number of joysticks + pygame.joystick.init() + + try: + count = pygame.joystick.get_count() + self.assertGreaterEqual( + count, 0, ("joystick.get_count() must " "return a value >= 0") + ) + finally: + pygame.joystick.quit() + + +class JoystickInteractiveTest(unittest.TestCase): + + __tags__ = ["interactive"] + + def test_get_count_interactive(self): + # Test get_count correctly identifies number of connected joysticks + prompt( + ( + "Please connect any joysticks/controllers now before starting the " + "joystick.get_count() test." + ) + ) + + pygame.joystick.init() + # pygame.joystick.get_count(): return count + # number of joysticks on the system, 0 means no joysticks connected + count = pygame.joystick.get_count() + + response = question( + ( + "NOTE: Having Steam open may add an extra virtual controller for " + "each joystick/controller physically plugged in.\n" + "joystick.get_count() thinks there is [{}] joystick(s)/controller(s)" + "connected to this system. Is this correct?".format(count) + ) + ) + + self.assertTrue(response) + + # When you create Joystick objects using Joystick(id), you pass an + # integer that must be lower than this count. + # Test Joystick(id) for each connected joystick + if count != 0: + for x in range(count): + pygame.joystick.Joystick(x) + with self.assertRaises(pygame.error): + pygame.joystick.Joystick(count) + + pygame.joystick.quit() + + +################################################################################ + +if __name__ == "__main__": + unittest.main() diff --git a/venv/Lib/site-packages/pygame/tests/key_test.py b/venv/Lib/site-packages/pygame/tests/key_test.py new file mode 100644 index 0000000..a15199f --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/key_test.py @@ -0,0 +1,110 @@ +import os +import sys +import time +import unittest +import pygame +import pygame.key + + +class KeyModuleTest(unittest.TestCase): + @classmethod + def setUpClass(cls): + pygame.init() + + @classmethod + def tearDownClass(cls): + pygame.quit() + + def setUp(cls): + # This makes sure pygame is always initialized before each test (in + # case a test calls pygame.quit()). + if not pygame.get_init(): + pygame.init() + if not pygame.display.get_init(): + pygame.display.init() + + def test_import(self): + """does it import?""" + import pygame.key + + # fixme: test_get_focused failing systematically in some linux + # fixme: test_get_focused failing on SDL 2.0.18 on Windows + @unittest.skip("flaky test, and broken on 2.0.18 windows") + def test_get_focused(self): + # This test fails in SDL2 in some linux + # This test was skipped in SDL1. + focused = pygame.key.get_focused() + self.assertFalse(focused) # No window to focus + self.assertIsInstance(focused, int) + # Dummy video driver never gets keyboard focus. + if os.environ.get("SDL_VIDEODRIVER") != "dummy": + # Positive test, fullscreen with events grabbed + display_sizes = pygame.display.list_modes() + if display_sizes == -1: + display_sizes = [(500, 500)] + pygame.display.set_mode(size=display_sizes[-1], flags=pygame.FULLSCREEN) + pygame.event.set_grab(True) + # Pump event queue to get window focus on macos + pygame.event.pump() + focused = pygame.key.get_focused() + self.assertIsInstance(focused, int) + self.assertTrue(focused) + # Now test negative, iconify takes away focus + pygame.event.clear() + # TODO: iconify test fails in windows + if os.name != "nt": + pygame.display.iconify() + # Apparent need to pump event queue in order to make sure iconify + # happens. See display_test.py's test_get_active_iconify + for _ in range(50): + time.sleep(0.01) + pygame.event.pump() + self.assertFalse(pygame.key.get_focused()) + # Test if focus is returned when iconify is gone + pygame.display.set_mode(size=display_sizes[-1], flags=pygame.FULLSCREEN) + for i in range(50): + time.sleep(0.01) + pygame.event.pump() + self.assertTrue(pygame.key.get_focused()) + # Test if a quit display raises an error: + pygame.display.quit() + with self.assertRaises(pygame.error) as cm: + pygame.key.get_focused() + + def test_get_pressed(self): + states = pygame.key.get_pressed() + self.assertEqual(states[pygame.K_RIGHT], 0) + + def test_name(self): + self.assertEqual(pygame.key.name(pygame.K_RETURN), "return") + self.assertEqual(pygame.key.name(pygame.K_0), "0") + self.assertEqual(pygame.key.name(pygame.K_SPACE), "space") + + def test_key_code(self): + self.assertEqual(pygame.key.key_code("return"), pygame.K_RETURN) + self.assertEqual(pygame.key.key_code("0"), pygame.K_0) + self.assertEqual(pygame.key.key_code("space"), pygame.K_SPACE) + + self.assertRaises(ValueError, pygame.key.key_code, "fizzbuzz") + + def test_set_and_get_mods(self): + pygame.key.set_mods(pygame.KMOD_CTRL) + self.assertEqual(pygame.key.get_mods(), pygame.KMOD_CTRL) + + pygame.key.set_mods(pygame.KMOD_ALT) + self.assertEqual(pygame.key.get_mods(), pygame.KMOD_ALT) + pygame.key.set_mods(pygame.KMOD_CTRL | pygame.KMOD_ALT) + self.assertEqual(pygame.key.get_mods(), pygame.KMOD_CTRL | pygame.KMOD_ALT) + + def test_set_and_get_repeat(self): + self.assertEqual(pygame.key.get_repeat(), (0, 0)) + + pygame.key.set_repeat(10, 15) + self.assertEqual(pygame.key.get_repeat(), (10, 15)) + + pygame.key.set_repeat() + self.assertEqual(pygame.key.get_repeat(), (0, 0)) + + +if __name__ == "__main__": + unittest.main() diff --git a/venv/Lib/site-packages/pygame/tests/mask_test.py b/venv/Lib/site-packages/pygame/tests/mask_test.py new file mode 100644 index 0000000..56c0917 --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/mask_test.py @@ -0,0 +1,6440 @@ +from collections import OrderedDict +import copy +import platform +import random +import unittest +import sys + +import pygame +from pygame.locals import * +from pygame.math import Vector2 +from pygame.tests.test_utils import AssertRaisesRegexMixin + + +IS_PYPY = "PyPy" == platform.python_implementation() + + +def random_mask(size=(100, 100)): + """random_mask(size=(100,100)): return Mask + Create a mask of the given size, with roughly half the bits set at random.""" + m = pygame.Mask(size) + for i in range(size[0] * size[1] // 2): + x, y = random.randint(0, size[0] - 1), random.randint(0, size[1] - 1) + m.set_at((x, y)) + return m + + +def maskFromSurface(surface, threshold=127): + mask = pygame.Mask(surface.get_size()) + key = surface.get_colorkey() + if key: + for y in range(surface.get_height()): + for x in range(surface.get_width()): + if surface.get_at((x + 0.1, y + 0.1)) != key: + mask.set_at((x, y), 1) + else: + for y in range(surface.get_height()): + for x in range(surface.get_width()): + if surface.get_at((x, y))[3] > threshold: + mask.set_at((x, y), 1) + return mask + + +def create_bounding_rect(points): + """Creates a bounding rect from the given points.""" + xmin = xmax = points[0][0] + ymin = ymax = points[0][1] + + for x, y in points[1:]: + xmin = min(x, xmin) + xmax = max(x, xmax) + ymin = min(y, ymin) + ymax = max(y, ymax) + + return pygame.Rect((xmin, ymin), (xmax - xmin + 1, ymax - ymin + 1)) + + +def zero_size_pairs(width, height): + """Creates a generator which yields pairs of sizes. + + For each pair of sizes at least one of the sizes will have a 0 in it. + """ + sizes = ((width, height), (width, 0), (0, height), (0, 0)) + + return ((a, b) for a in sizes for b in sizes if 0 in a or 0 in b) + + +def corners(mask): + """Returns a tuple with the corner positions of the given mask. + + Clockwise from the top left corner. + """ + width, height = mask.get_size() + return ((0, 0), (width - 1, 0), (width - 1, height - 1), (0, height - 1)) + + +def off_corners(rect): + """Returns a tuple with the positions off of the corners of the given rect. + + Clockwise from the top left corner. + """ + return ( + (rect.left - 1, rect.top), + (rect.left - 1, rect.top - 1), + (rect.left, rect.top - 1), + (rect.right - 1, rect.top - 1), + (rect.right, rect.top - 1), + (rect.right, rect.top), + (rect.right, rect.bottom - 1), + (rect.right, rect.bottom), + (rect.right - 1, rect.bottom), + (rect.left, rect.bottom), + (rect.left - 1, rect.bottom), + (rect.left - 1, rect.bottom - 1), + ) + + +def assertSurfaceFilled(testcase, surface, expected_color, area_rect=None): + """Checks to see if the given surface is filled with the given color. + + If an area_rect is provided, only check that area of the surface. + """ + if area_rect is None: + x_range = range(surface.get_width()) + y_range = range(surface.get_height()) + else: + area_rect.normalize() + area_rect = area_rect.clip(surface.get_rect()) + x_range = range(area_rect.left, area_rect.right) + y_range = range(area_rect.top, area_rect.bottom) + + surface.lock() # Lock for possible speed up. + for pos in ((x, y) for y in y_range for x in x_range): + testcase.assertEqual(surface.get_at(pos), expected_color, pos) + surface.unlock() + + +def assertSurfaceFilledIgnoreArea(testcase, surface, expected_color, ignore_rect): + """Checks if the surface is filled with the given color. The + ignore_rect area is not checked. + """ + x_range = range(surface.get_width()) + y_range = range(surface.get_height()) + ignore_rect.normalize() + + surface.lock() # Lock for possible speed up. + for pos in ((x, y) for y in y_range for x in x_range): + if not ignore_rect.collidepoint(pos): + testcase.assertEqual(surface.get_at(pos), expected_color, pos) + surface.unlock() + + +def assertMaskEqual(testcase, m1, m2, msg=None): + """Checks to see if the 2 given masks are equal.""" + m1_count = m1.count() + + testcase.assertEqual(m1.get_size(), m2.get_size(), msg=msg) + testcase.assertEqual(m1_count, m2.count(), msg=msg) + testcase.assertEqual(m1_count, m1.overlap_area(m2, (0, 0)), msg=msg) + + # This can be used to help debug exact locations. + ##for i in range(m1.get_size()[0]): + ## for j in range(m1.get_size()[1]): + ## testcase.assertEqual(m1.get_at((i, j)), m2.get_at((i, j))) + + +# @unittest.skipIf(IS_PYPY, "pypy has lots of mask failures") # TODO +class MaskTypeTest(AssertRaisesRegexMixin, unittest.TestCase): + ORIGIN_OFFSETS = ( + (0, 0), + (0, 1), + (1, 1), + (1, 0), + (1, -1), + (0, -1), + (-1, -1), + (-1, 0), + (-1, 1), + ) + + @unittest.skipIf(IS_PYPY, "Segfaults on pypy") + def test_mask(self): + """Ensure masks are created correctly without fill parameter.""" + expected_count = 0 + expected_size = (11, 23) + + mask1 = pygame.mask.Mask(expected_size) + mask2 = pygame.mask.Mask(size=expected_size) + + self.assertIsInstance(mask1, pygame.mask.Mask) + self.assertEqual(mask1.count(), expected_count) + self.assertEqual(mask1.get_size(), expected_size) + + self.assertIsInstance(mask2, pygame.mask.Mask) + self.assertEqual(mask2.count(), expected_count) + self.assertEqual(mask2.get_size(), expected_size) + + def test_mask__negative_size(self): + """Ensure the mask constructor handles negative sizes correctly.""" + for size in ((1, -1), (-1, 1), (-1, -1)): + with self.assertRaises(ValueError): + mask = pygame.Mask(size) + + def test_mask__fill_kwarg(self): + """Ensure masks are created correctly using the fill keyword.""" + width, height = 37, 47 + expected_size = (width, height) + fill_counts = {True: width * height, False: 0} + + for fill, expected_count in fill_counts.items(): + msg = "fill={}".format(fill) + + mask = pygame.mask.Mask(expected_size, fill=fill) + + self.assertIsInstance(mask, pygame.mask.Mask, msg) + self.assertEqual(mask.count(), expected_count, msg) + self.assertEqual(mask.get_size(), expected_size, msg) + + @unittest.skipIf(IS_PYPY, "Segfaults on pypy") + def test_mask__fill_kwarg_bit_boundaries(self): + """Ensures masks are created correctly using the fill keyword + over a range of sizes. + + Tests masks of different sizes, including: + -masks 31 to 33 bits wide (32 bit boundaries) + -masks 63 to 65 bits wide (64 bit boundaries) + """ + for height in range(1, 4): + for width in range(1, 66): + expected_count = width * height + expected_size = (width, height) + msg = "size={}".format(expected_size) + + mask = pygame.mask.Mask(expected_size, fill=True) + + self.assertIsInstance(mask, pygame.mask.Mask, msg) + self.assertEqual(mask.count(), expected_count, msg) + self.assertEqual(mask.get_size(), expected_size, msg) + + def test_mask__fill_arg(self): + """Ensure masks are created correctly using a fill arg.""" + width, height = 59, 71 + expected_size = (width, height) + fill_counts = {True: width * height, False: 0} + + for fill, expected_count in fill_counts.items(): + msg = "fill={}".format(fill) + + mask = pygame.mask.Mask(expected_size, fill) + + self.assertIsInstance(mask, pygame.mask.Mask, msg) + self.assertEqual(mask.count(), expected_count, msg) + self.assertEqual(mask.get_size(), expected_size, msg) + + def test_mask__size_kwarg(self): + """Ensure masks are created correctly using the size keyword.""" + width, height = 73, 83 + expected_size = (width, height) + fill_counts = {True: width * height, False: 0} + + for fill, expected_count in fill_counts.items(): + msg = "fill={}".format(fill) + + mask1 = pygame.mask.Mask(fill=fill, size=expected_size) + mask2 = pygame.mask.Mask(size=expected_size, fill=fill) + + self.assertIsInstance(mask1, pygame.mask.Mask, msg) + self.assertIsInstance(mask2, pygame.mask.Mask, msg) + self.assertEqual(mask1.count(), expected_count, msg) + self.assertEqual(mask2.count(), expected_count, msg) + self.assertEqual(mask1.get_size(), expected_size, msg) + self.assertEqual(mask2.get_size(), expected_size, msg) + + def test_copy(self): + """Ensures copy works correctly with some bits set and unset.""" + # Test different widths and heights. + for width in (31, 32, 33, 63, 64, 65): + for height in (31, 32, 33, 63, 64, 65): + mask = pygame.mask.Mask((width, height)) + + # Create a checkerboard pattern of set/unset bits. + for x in range(width): + for y in range(x & 1, height, 2): + mask.set_at((x, y)) + + # Test both the copy() and __copy__() methods. + for mask_copy in (mask.copy(), copy.copy(mask)): + self.assertIsInstance(mask_copy, pygame.mask.Mask) + self.assertIsNot(mask_copy, mask) + assertMaskEqual(self, mask_copy, mask) + + def test_copy__full(self): + """Ensures copy works correctly on a filled masked.""" + # Test different widths and heights. + for width in (31, 32, 33, 63, 64, 65): + for height in (31, 32, 33, 63, 64, 65): + mask = pygame.mask.Mask((width, height), fill=True) + + # Test both the copy() and __copy__() methods. + for mask_copy in (mask.copy(), copy.copy(mask)): + self.assertIsInstance(mask_copy, pygame.mask.Mask) + self.assertIsNot(mask_copy, mask) + assertMaskEqual(self, mask_copy, mask) + + def test_copy__empty(self): + """Ensures copy works correctly on an empty mask.""" + for width in (31, 32, 33, 63, 64, 65): + for height in (31, 32, 33, 63, 64, 65): + mask = pygame.mask.Mask((width, height)) + + # Test both the copy() and __copy__() methods. + for mask_copy in (mask.copy(), copy.copy(mask)): + self.assertIsInstance(mask_copy, pygame.mask.Mask) + self.assertIsNot(mask_copy, mask) + assertMaskEqual(self, mask_copy, mask) + + def test_copy__independent(self): + """Ensures copy makes an independent copy of the mask.""" + mask_set_pos = (64, 1) + mask_copy_set_pos = (64, 2) + mask = pygame.mask.Mask((65, 3)) + + # Test both the copy() and __copy__() methods. + mask_copies = (mask.copy(), copy.copy(mask)) + mask.set_at(mask_set_pos) + + for mask_copy in mask_copies: + mask_copy.set_at(mask_copy_set_pos) + + self.assertIsNot(mask_copy, mask) + self.assertNotEqual( + mask_copy.get_at(mask_set_pos), mask.get_at(mask_set_pos) + ) + self.assertNotEqual( + mask_copy.get_at(mask_copy_set_pos), mask.get_at(mask_copy_set_pos) + ) + + def test_get_size(self): + """Ensure a mask's size is correctly retrieved.""" + expected_size = (93, 101) + mask = pygame.mask.Mask(expected_size) + + self.assertEqual(mask.get_size(), expected_size) + + def test_get_rect(self): + """Ensures get_rect works correctly.""" + expected_rect = pygame.Rect((0, 0), (11, 13)) + + # Test on full and empty masks. + for fill in (True, False): + mask = pygame.mask.Mask(expected_rect.size, fill=fill) + + rect = mask.get_rect() + + self.assertEqual(rect, expected_rect) + + @unittest.skipIf(IS_PYPY, "Segfaults on pypy") + def test_get_rect__one_kwarg(self): + """Ensures get_rect supports a single rect attribute kwarg. + + Tests all the rect attributes. + """ + # Rect attributes that take a single value. + RECT_SINGLE_VALUE_ATTRIBUTES = ( + "x", + "y", + "top", + "left", + "bottom", + "right", + "centerx", + "centery", + "width", + "height", + "w", + "h", + ) + + # Rect attributes that take 2 values. + RECT_DOUBLE_VALUE_ATTRIBUTES = ( + "topleft", + "bottomleft", + "topright", + "bottomright", + "midtop", + "midleft", + "midbottom", + "midright", + "center", + "size", + ) + + # Testing ints/floats and tuples/lists/Vector2s. + # {attribute_names : attribute_values} + rect_attributes = { + RECT_SINGLE_VALUE_ATTRIBUTES: (3, 5.1), + RECT_DOUBLE_VALUE_ATTRIBUTES: ((1, 2.2), [2.3, 3], Vector2(0, 1)), + } + + size = (7, 3) + mask = pygame.mask.Mask(size) + + for attributes, values in rect_attributes.items(): + for attribute in attributes: + for value in values: + expected_rect = pygame.Rect((0, 0), size) + setattr(expected_rect, attribute, value) + + rect = mask.get_rect(**{attribute: value}) + + self.assertEqual(rect, expected_rect) + + def test_get_rect__multiple_kwargs(self): + """Ensures get_rect supports multiple rect attribute kwargs.""" + mask = pygame.mask.Mask((5, 4)) + expected_rect = pygame.Rect((0, 0), (0, 0)) + kwargs = {"x": 7.1, "top": -1, "size": Vector2(2, 3.2)} + + for attrib, value in kwargs.items(): + setattr(expected_rect, attrib, value) + + rect = mask.get_rect(**kwargs) + + self.assertEqual(rect, expected_rect) + + def test_get_rect__no_arg_support(self): + """Ensures get_rect only supports kwargs.""" + mask = pygame.mask.Mask((4, 5)) + + with self.assertRaises(TypeError): + rect = mask.get_rect(3) + + with self.assertRaises(TypeError): + rect = mask.get_rect((1, 2)) + + @unittest.skipIf(IS_PYPY, "Segfaults on pypy") + def test_get_rect__invalid_kwarg_name(self): + """Ensures get_rect detects invalid kwargs.""" + mask = pygame.mask.Mask((1, 2)) + + with self.assertRaises(AttributeError): + rect = mask.get_rect(righte=11) + + with self.assertRaises(AttributeError): + rect = mask.get_rect(toplef=(1, 1)) + + with self.assertRaises(AttributeError): + rect = mask.get_rect(move=(3, 2)) + + def test_get_rect__invalid_kwarg_format(self): + """Ensures get_rect detects invalid kwarg formats.""" + mask = pygame.mask.Mask((3, 11)) + + with self.assertRaises(TypeError): + rect = mask.get_rect(right="1") # Wrong type. + + with self.assertRaises(TypeError): + rect = mask.get_rect(bottom=(1,)) # Wrong type. + + with self.assertRaises(TypeError): + rect = mask.get_rect(centerx=(1, 1)) # Wrong type. + + with self.assertRaises(TypeError): + rect = mask.get_rect(midleft=(1, "1")) # Wrong type. + + with self.assertRaises(TypeError): + rect = mask.get_rect(topright=(1,)) # Too few. + + with self.assertRaises(TypeError): + rect = mask.get_rect(bottomleft=(1, 2, 3)) # Too many. + + with self.assertRaises(TypeError): + rect = mask.get_rect(midbottom=1) # Wrong type. + + def test_get_at(self): + """Ensure individual mask bits are correctly retrieved.""" + width, height = 5, 7 + mask0 = pygame.mask.Mask((width, height)) + mask1 = pygame.mask.Mask((width, height), fill=True) + mask0_expected_bit = 0 + mask1_expected_bit = 1 + pos = (width - 1, height - 1) + + # Check twice to make sure bits aren't toggled. + self.assertEqual(mask0.get_at(pos), mask0_expected_bit) + self.assertEqual(mask0.get_at(pos=pos), mask0_expected_bit) + self.assertEqual(mask1.get_at(Vector2(pos)), mask1_expected_bit) + self.assertEqual(mask1.get_at(pos=Vector2(pos)), mask1_expected_bit) + + def test_get_at__out_of_bounds(self): + """Ensure get_at() checks bounds.""" + width, height = 11, 3 + mask = pygame.mask.Mask((width, height)) + + with self.assertRaises(IndexError): + mask.get_at((width, 0)) + + with self.assertRaises(IndexError): + mask.get_at((0, height)) + + with self.assertRaises(IndexError): + mask.get_at((-1, 0)) + + with self.assertRaises(IndexError): + mask.get_at((0, -1)) + + def test_set_at(self): + """Ensure individual mask bits are set to 1.""" + width, height = 13, 17 + mask0 = pygame.mask.Mask((width, height)) + mask1 = pygame.mask.Mask((width, height), fill=True) + mask0_expected_count = 1 + mask1_expected_count = mask1.count() + expected_bit = 1 + pos = (width - 1, height - 1) + + mask0.set_at(pos, expected_bit) # set 0 to 1 + mask1.set_at(pos=Vector2(pos), value=expected_bit) # set 1 to 1 + + self.assertEqual(mask0.get_at(pos), expected_bit) + self.assertEqual(mask0.count(), mask0_expected_count) + self.assertEqual(mask1.get_at(pos), expected_bit) + self.assertEqual(mask1.count(), mask1_expected_count) + + def test_set_at__to_0(self): + """Ensure individual mask bits are set to 0.""" + width, height = 11, 7 + mask0 = pygame.mask.Mask((width, height)) + mask1 = pygame.mask.Mask((width, height), fill=True) + mask0_expected_count = 0 + mask1_expected_count = mask1.count() - 1 + expected_bit = 0 + pos = (width - 1, height - 1) + + mask0.set_at(pos, expected_bit) # set 0 to 0 + mask1.set_at(pos, expected_bit) # set 1 to 0 + + self.assertEqual(mask0.get_at(pos), expected_bit) + self.assertEqual(mask0.count(), mask0_expected_count) + self.assertEqual(mask1.get_at(pos), expected_bit) + self.assertEqual(mask1.count(), mask1_expected_count) + + def test_set_at__default_value(self): + """Ensure individual mask bits are set using the default value.""" + width, height = 3, 21 + mask0 = pygame.mask.Mask((width, height)) + mask1 = pygame.mask.Mask((width, height), fill=True) + mask0_expected_count = 1 + mask1_expected_count = mask1.count() + expected_bit = 1 + pos = (width - 1, height - 1) + + mask0.set_at(pos) # set 0 to 1 + mask1.set_at(pos) # set 1 to 1 + + self.assertEqual(mask0.get_at(pos), expected_bit) + self.assertEqual(mask0.count(), mask0_expected_count) + self.assertEqual(mask1.get_at(pos), expected_bit) + self.assertEqual(mask1.count(), mask1_expected_count) + + def test_set_at__out_of_bounds(self): + """Ensure set_at() checks bounds.""" + width, height = 11, 3 + mask = pygame.mask.Mask((width, height)) + + with self.assertRaises(IndexError): + mask.set_at((width, 0)) + + with self.assertRaises(IndexError): + mask.set_at((0, height)) + + with self.assertRaises(IndexError): + mask.set_at((-1, 0)) + + with self.assertRaises(IndexError): + mask.set_at((0, -1)) + + def test_overlap(self): + """Ensure the overlap intersection is correctly calculated. + + Testing the different combinations of full/empty masks: + (mask1-filled) 1 overlap 1 (mask2-filled) + (mask1-empty) 0 overlap 1 (mask2-filled) + (mask1-filled) 1 overlap 0 (mask2-empty) + (mask1-empty) 0 overlap 0 (mask2-empty) + """ + expected_size = (4, 4) + offset = (0, 0) + expected_default = None + expected_overlaps = {(True, True): offset} + + for fill2 in (True, False): + mask2 = pygame.mask.Mask(expected_size, fill=fill2) + mask2_count = mask2.count() + + for fill1 in (True, False): + key = (fill1, fill2) + msg = "key={}".format(key) + mask1 = pygame.mask.Mask(expected_size, fill=fill1) + mask1_count = mask1.count() + expected_pos = expected_overlaps.get(key, expected_default) + + overlap_pos = mask1.overlap(mask2, offset) + + self.assertEqual(overlap_pos, expected_pos, msg) + + # Ensure mask1/mask2 unchanged. + self.assertEqual(mask1.count(), mask1_count, msg) + self.assertEqual(mask2.count(), mask2_count, msg) + self.assertEqual(mask1.get_size(), expected_size, msg) + self.assertEqual(mask2.get_size(), expected_size, msg) + + def test_overlap__offset(self): + """Ensure an offset overlap intersection is correctly calculated.""" + mask1 = pygame.mask.Mask((65, 3), fill=True) + mask2 = pygame.mask.Mask((66, 4), fill=True) + mask1_count = mask1.count() + mask2_count = mask2.count() + mask1_size = mask1.get_size() + mask2_size = mask2.get_size() + + for offset in self.ORIGIN_OFFSETS: + msg = "offset={}".format(offset) + expected_pos = (max(offset[0], 0), max(offset[1], 0)) + + overlap_pos = mask1.overlap(other=mask2, offset=offset) + + self.assertEqual(overlap_pos, expected_pos, msg) + + # Ensure mask1/mask2 unchanged. + self.assertEqual(mask1.count(), mask1_count, msg) + self.assertEqual(mask2.count(), mask2_count, msg) + self.assertEqual(mask1.get_size(), mask1_size, msg) + self.assertEqual(mask2.get_size(), mask2_size, msg) + + def test_overlap__offset_with_unset_bits(self): + """Ensure an offset overlap intersection is correctly calculated + when (0, 0) bits not set.""" + mask1 = pygame.mask.Mask((65, 3), fill=True) + mask2 = pygame.mask.Mask((66, 4), fill=True) + unset_pos = (0, 0) + mask1.set_at(unset_pos, 0) + mask2.set_at(unset_pos, 0) + mask1_count = mask1.count() + mask2_count = mask2.count() + mask1_size = mask1.get_size() + mask2_size = mask2.get_size() + + for offset in self.ORIGIN_OFFSETS: + msg = "offset={}".format(offset) + x, y = offset + expected_y = max(y, 0) + if 0 == y: + expected_x = max(x + 1, 1) + elif 0 < y: + expected_x = max(x + 1, 0) + else: + expected_x = max(x, 1) + + overlap_pos = mask1.overlap(mask2, Vector2(offset)) + + self.assertEqual(overlap_pos, (expected_x, expected_y), msg) + + # Ensure mask1/mask2 unchanged. + self.assertEqual(mask1.count(), mask1_count, msg) + self.assertEqual(mask2.count(), mask2_count, msg) + self.assertEqual(mask1.get_size(), mask1_size, msg) + self.assertEqual(mask2.get_size(), mask2_size, msg) + self.assertEqual(mask1.get_at(unset_pos), 0, msg) + self.assertEqual(mask2.get_at(unset_pos), 0, msg) + + def test_overlap__no_overlap(self): + """Ensure an offset overlap intersection is correctly calculated + when there is no overlap.""" + mask1 = pygame.mask.Mask((65, 3), fill=True) + mask1_count = mask1.count() + mask1_size = mask1.get_size() + + mask2_w, mask2_h = 67, 5 + mask2_size = (mask2_w, mask2_h) + mask2 = pygame.mask.Mask(mask2_size) + set_pos = (mask2_w - 1, mask2_h - 1) + mask2.set_at(set_pos) + mask2_count = 1 + + for offset in self.ORIGIN_OFFSETS: + msg = "offset={}".format(offset) + + overlap_pos = mask1.overlap(mask2, offset) + + self.assertIsNone(overlap_pos, msg) + + # Ensure mask1/mask2 unchanged. + self.assertEqual(mask1.count(), mask1_count, msg) + self.assertEqual(mask2.count(), mask2_count, msg) + self.assertEqual(mask1.get_size(), mask1_size, msg) + self.assertEqual(mask2.get_size(), mask2_size, msg) + self.assertEqual(mask2.get_at(set_pos), 1, msg) + + def test_overlap__offset_boundary(self): + """Ensures overlap handles offsets and boundaries correctly.""" + mask1 = pygame.mask.Mask((13, 3), fill=True) + mask2 = pygame.mask.Mask((7, 5), fill=True) + mask1_count = mask1.count() + mask2_count = mask2.count() + mask1_size = mask1.get_size() + mask2_size = mask2.get_size() + + # Check the 4 boundaries. + offsets = ( + (mask1_size[0], 0), # off right + (0, mask1_size[1]), # off bottom + (-mask2_size[0], 0), # off left + (0, -mask2_size[1]), + ) # off top + + for offset in offsets: + msg = "offset={}".format(offset) + + overlap_pos = mask1.overlap(mask2, offset) + + self.assertIsNone(overlap_pos, msg) + + # Ensure mask1/mask2 unchanged. + self.assertEqual(mask1.count(), mask1_count, msg) + self.assertEqual(mask2.count(), mask2_count, msg) + self.assertEqual(mask1.get_size(), mask1_size, msg) + self.assertEqual(mask2.get_size(), mask2_size, msg) + + @unittest.skipIf(IS_PYPY, "Segfaults on pypy") + def test_overlap__bit_boundaries(self): + """Ensures overlap handles masks of different sizes correctly. + + Tests masks of different sizes, including: + -masks 31 to 33 bits wide (32 bit boundaries) + -masks 63 to 65 bits wide (64 bit boundaries) + """ + for height in range(2, 4): + for width in range(2, 66): + mask_size = (width, height) + mask_count = width * height + mask1 = pygame.mask.Mask(mask_size, fill=True) + mask2 = pygame.mask.Mask(mask_size, fill=True) + + # Testing masks offset from each other. + for offset in self.ORIGIN_OFFSETS: + msg = "size={}, offset={}".format(mask_size, offset) + expected_pos = (max(offset[0], 0), max(offset[1], 0)) + + overlap_pos = mask1.overlap(mask2, offset) + + self.assertEqual(overlap_pos, expected_pos, msg) + + # Ensure mask1/mask2 unchanged. + self.assertEqual(mask1.count(), mask_count, msg) + self.assertEqual(mask2.count(), mask_count, msg) + self.assertEqual(mask1.get_size(), mask_size, msg) + self.assertEqual(mask2.get_size(), mask_size, msg) + + @unittest.skipIf(IS_PYPY, "Segfaults on pypy") + def test_overlap__invalid_mask_arg(self): + """Ensure overlap handles invalid mask arguments correctly.""" + size = (5, 3) + offset = (0, 0) + mask = pygame.mask.Mask(size) + invalid_mask = pygame.Surface(size) + + with self.assertRaises(TypeError): + overlap_pos = mask.overlap(invalid_mask, offset) + + def test_overlap__invalid_offset_arg(self): + """Ensure overlap handles invalid offset arguments correctly.""" + size = (2, 7) + offset = "(0, 0)" + mask1 = pygame.mask.Mask(size) + mask2 = pygame.mask.Mask(size) + + with self.assertRaises(TypeError): + overlap_pos = mask1.overlap(mask2, offset) + + @unittest.skipIf(IS_PYPY, "Segfaults on pypy") + def test_overlap_area(self): + """Ensure the overlap_area is correctly calculated. + + Testing the different combinations of full/empty masks: + (mask1-filled) 1 overlap_area 1 (mask2-filled) + (mask1-empty) 0 overlap_area 1 (mask2-filled) + (mask1-filled) 1 overlap_area 0 (mask2-empty) + (mask1-empty) 0 overlap_area 0 (mask2-empty) + """ + expected_size = width, height = (4, 4) + offset = (0, 0) + expected_default = 0 + expected_counts = {(True, True): width * height} + + for fill2 in (True, False): + mask2 = pygame.mask.Mask(expected_size, fill=fill2) + mask2_count = mask2.count() + + for fill1 in (True, False): + key = (fill1, fill2) + msg = "key={}".format(key) + mask1 = pygame.mask.Mask(expected_size, fill=fill1) + mask1_count = mask1.count() + expected_count = expected_counts.get(key, expected_default) + + overlap_count = mask1.overlap_area(mask2, offset) + + self.assertEqual(overlap_count, expected_count, msg) + + # Ensure mask1/mask2 unchanged. + self.assertEqual(mask1.count(), mask1_count, msg) + self.assertEqual(mask2.count(), mask2_count, msg) + self.assertEqual(mask1.get_size(), expected_size, msg) + self.assertEqual(mask2.get_size(), expected_size, msg) + + @unittest.skipIf(IS_PYPY, "Segfaults on pypy") + def test_overlap_area__offset(self): + """Ensure an offset overlap_area is correctly calculated.""" + mask1 = pygame.mask.Mask((65, 3), fill=True) + mask2 = pygame.mask.Mask((66, 4), fill=True) + mask1_count = mask1.count() + mask2_count = mask2.count() + mask1_size = mask1.get_size() + mask2_size = mask2.get_size() + + # Using rects to help determine the overlapping area. + rect1 = mask1.get_rect() + rect2 = mask2.get_rect() + + for offset in self.ORIGIN_OFFSETS: + msg = "offset={}".format(offset) + rect2.topleft = offset + overlap_rect = rect1.clip(rect2) + expected_count = overlap_rect.w * overlap_rect.h + + overlap_count = mask1.overlap_area(other=mask2, offset=offset) + + self.assertEqual(overlap_count, expected_count, msg) + + # Ensure mask1/mask2 unchanged. + self.assertEqual(mask1.count(), mask1_count, msg) + self.assertEqual(mask2.count(), mask2_count, msg) + self.assertEqual(mask1.get_size(), mask1_size, msg) + self.assertEqual(mask2.get_size(), mask2_size, msg) + + def test_overlap_area__offset_boundary(self): + """Ensures overlap_area handles offsets and boundaries correctly.""" + mask1 = pygame.mask.Mask((11, 3), fill=True) + mask2 = pygame.mask.Mask((5, 7), fill=True) + mask1_count = mask1.count() + mask2_count = mask2.count() + mask1_size = mask1.get_size() + mask2_size = mask2.get_size() + expected_count = 0 + + # Check the 4 boundaries. + offsets = ( + (mask1_size[0], 0), # off right + (0, mask1_size[1]), # off bottom + (-mask2_size[0], 0), # off left + (0, -mask2_size[1]), + ) # off top + + for offset in offsets: + msg = "offset={}".format(offset) + + overlap_count = mask1.overlap_area(mask2, Vector2(offset)) + + self.assertEqual(overlap_count, expected_count, msg) + + # Ensure mask1/mask2 unchanged. + self.assertEqual(mask1.count(), mask1_count, msg) + self.assertEqual(mask2.count(), mask2_count, msg) + self.assertEqual(mask1.get_size(), mask1_size, msg) + self.assertEqual(mask2.get_size(), mask2_size, msg) + + @unittest.skipIf(IS_PYPY, "Segfaults on pypy") + def test_overlap_area__bit_boundaries(self): + """Ensures overlap_area handles masks of different sizes correctly. + + Tests masks of different sizes, including: + -masks 31 to 33 bits wide (32 bit boundaries) + -masks 63 to 65 bits wide (64 bit boundaries) + """ + for height in range(2, 4): + for width in range(2, 66): + mask_size = (width, height) + mask_count = width * height + mask1 = pygame.mask.Mask(mask_size, fill=True) + mask2 = pygame.mask.Mask(mask_size, fill=True) + + # Using rects to help determine the overlapping area. + rect1 = mask1.get_rect() + rect2 = mask2.get_rect() + + # Testing masks offset from each other. + for offset in self.ORIGIN_OFFSETS: + msg = "size={}, offset={}".format(mask_size, offset) + rect2.topleft = offset + overlap_rect = rect1.clip(rect2) + expected_overlap_count = overlap_rect.w * overlap_rect.h + + overlap_count = mask1.overlap_area(mask2, offset) + + self.assertEqual(overlap_count, expected_overlap_count, msg) + + # Ensure mask1/mask2 unchanged. + self.assertEqual(mask1.count(), mask_count, msg) + self.assertEqual(mask2.count(), mask_count, msg) + self.assertEqual(mask1.get_size(), mask_size, msg) + self.assertEqual(mask2.get_size(), mask_size, msg) + + def test_overlap_area__invalid_mask_arg(self): + """Ensure overlap_area handles invalid mask arguments correctly.""" + size = (3, 5) + offset = (0, 0) + mask = pygame.mask.Mask(size) + invalid_mask = pygame.Surface(size) + + with self.assertRaises(TypeError): + overlap_count = mask.overlap_area(invalid_mask, offset) + + def test_overlap_area__invalid_offset_arg(self): + """Ensure overlap_area handles invalid offset arguments correctly.""" + size = (7, 2) + offset = "(0, 0)" + mask1 = pygame.mask.Mask(size) + mask2 = pygame.mask.Mask(size) + + with self.assertRaises(TypeError): + overlap_count = mask1.overlap_area(mask2, offset) + + def test_overlap_mask(self): + """Ensure overlap_mask's mask has correct bits set. + + Testing the different combinations of full/empty masks: + (mask1-filled) 1 overlap_mask 1 (mask2-filled) + (mask1-empty) 0 overlap_mask 1 (mask2-filled) + (mask1-filled) 1 overlap_mask 0 (mask2-empty) + (mask1-empty) 0 overlap_mask 0 (mask2-empty) + """ + expected_size = (4, 4) + offset = (0, 0) + expected_default = pygame.mask.Mask(expected_size) + expected_masks = {(True, True): pygame.mask.Mask(expected_size, fill=True)} + + for fill2 in (True, False): + mask2 = pygame.mask.Mask(expected_size, fill=fill2) + mask2_count = mask2.count() + + for fill1 in (True, False): + key = (fill1, fill2) + msg = "key={}".format(key) + mask1 = pygame.mask.Mask(expected_size, fill=fill1) + mask1_count = mask1.count() + expected_mask = expected_masks.get(key, expected_default) + + overlap_mask = mask1.overlap_mask(other=mask2, offset=offset) + + self.assertIsInstance(overlap_mask, pygame.mask.Mask, msg) + assertMaskEqual(self, overlap_mask, expected_mask, msg) + + # Ensure mask1/mask2 unchanged. + self.assertEqual(mask1.count(), mask1_count, msg) + self.assertEqual(mask2.count(), mask2_count, msg) + self.assertEqual(mask1.get_size(), expected_size, msg) + self.assertEqual(mask2.get_size(), expected_size, msg) + + @unittest.skipIf(IS_PYPY, "Segfaults on pypy") + def test_overlap_mask__bits_set(self): + """Ensure overlap_mask's mask has correct bits set.""" + mask1 = pygame.mask.Mask((50, 50), fill=True) + mask2 = pygame.mask.Mask((300, 10), fill=True) + mask1_count = mask1.count() + mask2_count = mask2.count() + mask1_size = mask1.get_size() + mask2_size = mask2.get_size() + + mask3 = mask1.overlap_mask(mask2, (-1, 0)) + + for i in range(50): + for j in range(10): + self.assertEqual(mask3.get_at((i, j)), 1, "({}, {})".format(i, j)) + + for i in range(50): + for j in range(11, 50): + self.assertEqual(mask3.get_at((i, j)), 0, "({}, {})".format(i, j)) + + # Ensure mask1/mask2 unchanged. + self.assertEqual(mask1.count(), mask1_count) + self.assertEqual(mask2.count(), mask2_count) + self.assertEqual(mask1.get_size(), mask1_size) + self.assertEqual(mask2.get_size(), mask2_size) + + def test_overlap_mask__offset(self): + """Ensure an offset overlap_mask's mask is correctly calculated.""" + mask1 = pygame.mask.Mask((65, 3), fill=True) + mask2 = pygame.mask.Mask((66, 4), fill=True) + mask1_count = mask1.count() + mask2_count = mask2.count() + mask1_size = mask1.get_size() + mask2_size = mask2.get_size() + expected_mask = pygame.Mask(mask1_size) + + # Using rects to help determine the overlapping area. + rect1 = mask1.get_rect() + rect2 = mask2.get_rect() + + for offset in self.ORIGIN_OFFSETS: + msg = "offset={}".format(offset) + rect2.topleft = offset + overlap_rect = rect1.clip(rect2) + expected_mask.clear() + expected_mask.draw( + pygame.Mask(overlap_rect.size, fill=True), overlap_rect.topleft + ) + + overlap_mask = mask1.overlap_mask(mask2, offset) + + self.assertIsInstance(overlap_mask, pygame.mask.Mask, msg) + assertMaskEqual(self, overlap_mask, expected_mask, msg) + + # Ensure mask1/mask2 unchanged. + self.assertEqual(mask1.count(), mask1_count, msg) + self.assertEqual(mask2.count(), mask2_count, msg) + self.assertEqual(mask1.get_size(), mask1_size, msg) + self.assertEqual(mask2.get_size(), mask2_size, msg) + + @unittest.skipIf(IS_PYPY, "Segfaults on pypy") + def test_overlap_mask__specific_offsets(self): + """Ensure an offset overlap_mask's mask is correctly calculated. + + Testing the specific case of: + -both masks are wider than 32 bits + -a positive offset is used + -the mask calling overlap_mask() is wider than the mask passed in + """ + mask1 = pygame.mask.Mask((65, 5), fill=True) + mask2 = pygame.mask.Mask((33, 3), fill=True) + expected_mask = pygame.Mask(mask1.get_size()) + + # Using rects to help determine the overlapping area. + rect1 = mask1.get_rect() + rect2 = mask2.get_rect() + + # This rect's corners are used to move rect2 around the inside of + # rect1. + corner_rect = rect1.inflate(-2, -2) + + for corner in ("topleft", "topright", "bottomright", "bottomleft"): + setattr(rect2, corner, getattr(corner_rect, corner)) + offset = rect2.topleft + msg = "offset={}".format(offset) + overlap_rect = rect1.clip(rect2) + expected_mask.clear() + expected_mask.draw( + pygame.Mask(overlap_rect.size, fill=True), overlap_rect.topleft + ) + + overlap_mask = mask1.overlap_mask(mask2, offset) + + self.assertIsInstance(overlap_mask, pygame.mask.Mask, msg) + assertMaskEqual(self, overlap_mask, expected_mask, msg) + + def test_overlap_mask__offset_boundary(self): + """Ensures overlap_mask handles offsets and boundaries correctly.""" + mask1 = pygame.mask.Mask((9, 3), fill=True) + mask2 = pygame.mask.Mask((11, 5), fill=True) + mask1_count = mask1.count() + mask2_count = mask2.count() + mask1_size = mask1.get_size() + mask2_size = mask2.get_size() + expected_count = 0 + expected_size = mask1_size + + # Check the 4 boundaries. + offsets = ( + (mask1_size[0], 0), # off right + (0, mask1_size[1]), # off bottom + (-mask2_size[0], 0), # off left + (0, -mask2_size[1]), + ) # off top + + for offset in offsets: + msg = "offset={}".format(offset) + + overlap_mask = mask1.overlap_mask(mask2, offset) + + self.assertIsInstance(overlap_mask, pygame.mask.Mask, msg) + self.assertEqual(overlap_mask.count(), expected_count, msg) + self.assertEqual(overlap_mask.get_size(), expected_size, msg) + + # Ensure mask1/mask2 unchanged. + self.assertEqual(mask1.count(), mask1_count, msg) + self.assertEqual(mask2.count(), mask2_count, msg) + self.assertEqual(mask1.get_size(), mask1_size, msg) + self.assertEqual(mask2.get_size(), mask2_size, msg) + + @unittest.skipIf(IS_PYPY, "Segfaults on pypy") + def test_overlap_mask__bit_boundaries(self): + """Ensures overlap_mask handles masks of different sizes correctly. + + Tests masks of different sizes, including: + -masks 31 to 33 bits wide (32 bit boundaries) + -masks 63 to 65 bits wide (64 bit boundaries) + """ + for height in range(2, 4): + for width in range(2, 66): + mask_size = (width, height) + mask_count = width * height + mask1 = pygame.mask.Mask(mask_size, fill=True) + mask2 = pygame.mask.Mask(mask_size, fill=True) + expected_mask = pygame.Mask(mask_size) + + # Using rects to help determine the overlapping area. + rect1 = mask1.get_rect() + rect2 = mask2.get_rect() + + # Testing masks offset from each other. + for offset in self.ORIGIN_OFFSETS: + msg = "size={}, offset={}".format(mask_size, offset) + rect2.topleft = offset + overlap_rect = rect1.clip(rect2) + expected_mask.clear() + expected_mask.draw( + pygame.Mask(overlap_rect.size, fill=True), overlap_rect.topleft + ) + + overlap_mask = mask1.overlap_mask(mask2, offset) + + self.assertIsInstance(overlap_mask, pygame.mask.Mask, msg) + assertMaskEqual(self, overlap_mask, expected_mask, msg) + + # Ensure mask1/mask2 unchanged. + self.assertEqual(mask1.count(), mask_count, msg) + self.assertEqual(mask2.count(), mask_count, msg) + self.assertEqual(mask1.get_size(), mask_size, msg) + self.assertEqual(mask2.get_size(), mask_size, msg) + + def test_overlap_mask__invalid_mask_arg(self): + """Ensure overlap_mask handles invalid mask arguments correctly.""" + size = (3, 2) + offset = (0, 0) + mask = pygame.mask.Mask(size) + invalid_mask = pygame.Surface(size) + + with self.assertRaises(TypeError): + overlap_mask = mask.overlap_mask(invalid_mask, offset) + + def test_overlap_mask__invalid_offset_arg(self): + """Ensure overlap_mask handles invalid offset arguments correctly.""" + size = (5, 2) + offset = "(0, 0)" + mask1 = pygame.mask.Mask(size) + mask2 = pygame.mask.Mask(size) + + with self.assertRaises(TypeError): + overlap_mask = mask1.overlap_mask(mask2, offset) + + def test_mask_access(self): + """do the set_at, and get_at parts work correctly?""" + m = pygame.Mask((10, 10)) + m.set_at((0, 0), 1) + self.assertEqual(m.get_at((0, 0)), 1) + m.set_at((9, 0), 1) + self.assertEqual(m.get_at((9, 0)), 1) + + # s = pygame.Surface((10,10)) + # s.set_at((1,0), (0, 0, 1, 255)) + # self.assertEqual(s.get_at((1,0)), (0, 0, 1, 255)) + # s.set_at((-1,0), (0, 0, 1, 255)) + + # out of bounds, should get IndexError + self.assertRaises(IndexError, lambda: m.get_at((-1, 0))) + self.assertRaises(IndexError, lambda: m.set_at((-1, 0), 1)) + self.assertRaises(IndexError, lambda: m.set_at((10, 0), 1)) + self.assertRaises(IndexError, lambda: m.set_at((0, 10), 1)) + + def test_fill(self): + """Ensure a mask can be filled.""" + width, height = 11, 23 + expected_count = width * height + expected_size = (width, height) + mask = pygame.mask.Mask(expected_size) + + mask.fill() + + self.assertEqual(mask.count(), expected_count) + self.assertEqual(mask.get_size(), expected_size) + + @unittest.skipIf(IS_PYPY, "Segfaults on pypy") + def test_fill__bit_boundaries(self): + """Ensures masks of different sizes are filled correctly. + + Tests masks of different sizes, including: + -masks 31 to 33 bits wide (32 bit boundaries) + -masks 63 to 65 bits wide (64 bit boundaries) + """ + for height in range(1, 4): + for width in range(1, 66): + mask = pygame.mask.Mask((width, height)) + expected_count = width * height + + mask.fill() + + self.assertEqual( + mask.count(), expected_count, "size=({}, {})".format(width, height) + ) + + def test_clear(self): + """Ensure a mask can be cleared.""" + expected_count = 0 + expected_size = (13, 27) + mask = pygame.mask.Mask(expected_size, fill=True) + + mask.clear() + + self.assertEqual(mask.count(), expected_count) + self.assertEqual(mask.get_size(), expected_size) + + def test_clear__bit_boundaries(self): + """Ensures masks of different sizes are cleared correctly. + + Tests masks of different sizes, including: + -masks 31 to 33 bits wide (32 bit boundaries) + -masks 63 to 65 bits wide (64 bit boundaries) + """ + expected_count = 0 + + for height in range(1, 4): + for width in range(1, 66): + mask = pygame.mask.Mask((width, height), fill=True) + + mask.clear() + + self.assertEqual( + mask.count(), expected_count, "size=({}, {})".format(width, height) + ) + + @unittest.skipIf(IS_PYPY, "Segfaults on pypy") + def test_invert(self): + """Ensure a mask can be inverted.""" + side = 73 + expected_size = (side, side) + mask1 = pygame.mask.Mask(expected_size) + mask2 = pygame.mask.Mask(expected_size, fill=True) + expected_count1 = side * side + expected_count2 = 0 + + for i in range(side): + expected_count1 -= 1 + expected_count2 += 1 + pos = (i, i) + mask1.set_at(pos) + mask2.set_at(pos, 0) + + mask1.invert() + mask2.invert() + + self.assertEqual(mask1.count(), expected_count1) + self.assertEqual(mask2.count(), expected_count2) + self.assertEqual(mask1.get_size(), expected_size) + self.assertEqual(mask2.get_size(), expected_size) + + for i in range(side): + pos = (i, i) + msg = "pos={}".format(pos) + + self.assertEqual(mask1.get_at(pos), 0, msg) + self.assertEqual(mask2.get_at(pos), 1, msg) + + def test_invert__full(self): + """Ensure a full mask can be inverted.""" + expected_count = 0 + expected_size = (43, 97) + mask = pygame.mask.Mask(expected_size, fill=True) + + mask.invert() + + self.assertEqual(mask.count(), expected_count) + self.assertEqual(mask.get_size(), expected_size) + + def test_invert__empty(self): + """Ensure an empty mask can be inverted.""" + width, height = 43, 97 + expected_size = (width, height) + expected_count = width * height + mask = pygame.mask.Mask(expected_size) + + mask.invert() + + self.assertEqual(mask.count(), expected_count) + self.assertEqual(mask.get_size(), expected_size) + + @unittest.skipIf(IS_PYPY, "Segfaults on pypy") + def test_invert__bit_boundaries(self): + """Ensures masks of different sizes are inverted correctly. + + Tests masks of different sizes, including: + -masks 31 to 33 bits wide (32 bit boundaries) + -masks 63 to 65 bits wide (64 bit boundaries) + """ + for fill in (True, False): + for height in range(1, 4): + for width in range(1, 66): + mask = pygame.mask.Mask((width, height), fill=fill) + expected_count = 0 if fill else width * height + + mask.invert() + + self.assertEqual( + mask.count(), + expected_count, + "fill={}, size=({}, {})".format(fill, width, height), + ) + + @unittest.skipIf(IS_PYPY, "Segfaults on pypy") + def test_scale(self): + """Ensure a mask can be scaled.""" + width, height = 43, 61 + original_size = (width, height) + + for fill in (True, False): + original_mask = pygame.mask.Mask(original_size, fill=fill) + original_count = width * height if fill else 0 + + # Test a range of sizes. Also tests scaling to 'same' + # size when new_w, new_h = width, height + for new_w in range(width - 10, width + 10): + for new_h in range(height - 10, height + 10): + expected_size = (new_w, new_h) + expected_count = new_w * new_h if fill else 0 + msg = "size={}".format(expected_size) + + mask = original_mask.scale(scale=expected_size) + + self.assertIsInstance(mask, pygame.mask.Mask, msg) + self.assertEqual(mask.count(), expected_count, msg) + self.assertEqual(mask.get_size(), expected_size) + + # Ensure the original mask is unchanged. + self.assertEqual(original_mask.count(), original_count, msg) + self.assertEqual(original_mask.get_size(), original_size, msg) + + def test_scale__negative_size(self): + """Ensure scale handles negative sizes correctly.""" + mask = pygame.Mask((100, 100)) + + with self.assertRaises(ValueError): + mask.scale((-1, -1)) + + with self.assertRaises(ValueError): + mask.scale(Vector2(-1, 10)) + + with self.assertRaises(ValueError): + mask.scale((10, -1)) + + def test_draw(self): + """Ensure a mask can be drawn onto another mask. + + Testing the different combinations of full/empty masks: + (mask1-filled) 1 draw 1 (mask2-filled) + (mask1-empty) 0 draw 1 (mask2-filled) + (mask1-filled) 1 draw 0 (mask2-empty) + (mask1-empty) 0 draw 0 (mask2-empty) + """ + expected_size = (4, 4) + offset = (0, 0) + expected_default = pygame.mask.Mask(expected_size, fill=True) + expected_masks = {(False, False): pygame.mask.Mask(expected_size)} + + for fill2 in (True, False): + mask2 = pygame.mask.Mask(expected_size, fill=fill2) + mask2_count = mask2.count() + + for fill1 in (True, False): + key = (fill1, fill2) + msg = "key={}".format(key) + mask1 = pygame.mask.Mask(expected_size, fill=fill1) + expected_mask = expected_masks.get(key, expected_default) + + mask1.draw(mask2, offset) + + assertMaskEqual(self, mask1, expected_mask, msg) + + # Ensure mask2 unchanged. + self.assertEqual(mask2.count(), mask2_count, msg) + self.assertEqual(mask2.get_size(), expected_size, msg) + + def test_draw__offset(self): + """Ensure an offset mask can be drawn onto another mask.""" + mask1 = pygame.mask.Mask((65, 3)) + mask2 = pygame.mask.Mask((66, 4), fill=True) + mask2_count = mask2.count() + mask2_size = mask2.get_size() + expected_mask = pygame.Mask(mask1.get_size()) + + # Using rects to help determine the overlapping area. + rect1 = mask1.get_rect() + rect2 = mask2.get_rect() + + for offset in self.ORIGIN_OFFSETS: + msg = "offset={}".format(offset) + rect2.topleft = offset + overlap_rect = rect1.clip(rect2) + expected_mask.clear() + + # Normally draw() could be used to set these bits, but the draw() + # method is being tested here, so a loop is used instead. + for x in range(overlap_rect.left, overlap_rect.right): + for y in range(overlap_rect.top, overlap_rect.bottom): + expected_mask.set_at((x, y)) + mask1.clear() # Ensure it's empty for testing each offset. + + mask1.draw(other=mask2, offset=offset) + + assertMaskEqual(self, mask1, expected_mask, msg) + + # Ensure mask2 unchanged. + self.assertEqual(mask2.count(), mask2_count, msg) + self.assertEqual(mask2.get_size(), mask2_size, msg) + + def test_draw__specific_offsets(self): + """Ensure an offset mask can be drawn onto another mask. + + Testing the specific case of: + -both masks are wider than 32 bits + -a positive offset is used + -the mask calling draw() is wider than the mask passed in + """ + mask1 = pygame.mask.Mask((65, 5)) + mask2 = pygame.mask.Mask((33, 3), fill=True) + expected_mask = pygame.Mask(mask1.get_size()) + + # Using rects to help determine the overlapping area. + rect1 = mask1.get_rect() + rect2 = mask2.get_rect() + + # This rect's corners are used to move rect2 around the inside of + # rect1. + corner_rect = rect1.inflate(-2, -2) + + for corner in ("topleft", "topright", "bottomright", "bottomleft"): + setattr(rect2, corner, getattr(corner_rect, corner)) + offset = rect2.topleft + msg = "offset={}".format(offset) + overlap_rect = rect1.clip(rect2) + expected_mask.clear() + + # Normally draw() could be used to set these bits, but the draw() + # method is being tested here, so a loop is used instead. + for x in range(overlap_rect.left, overlap_rect.right): + for y in range(overlap_rect.top, overlap_rect.bottom): + expected_mask.set_at((x, y)) + mask1.clear() # Ensure it's empty for testing each offset. + + mask1.draw(mask2, offset) + + assertMaskEqual(self, mask1, expected_mask, msg) + + def test_draw__offset_boundary(self): + """Ensures draw handles offsets and boundaries correctly.""" + mask1 = pygame.mask.Mask((13, 5)) + mask2 = pygame.mask.Mask((7, 3), fill=True) + mask1_count = mask1.count() + mask2_count = mask2.count() + mask1_size = mask1.get_size() + mask2_size = mask2.get_size() + + # Check the 4 boundaries. + offsets = ( + (mask1_size[0], 0), # off right + (0, mask1_size[1]), # off bottom + (-mask2_size[0], 0), # off left + (0, -mask2_size[1]), + ) # off top + + for offset in offsets: + msg = "offset={}".format(offset) + + mask1.draw(mask2, offset) + + # Ensure mask1/mask2 unchanged. + self.assertEqual(mask1.count(), mask1_count, msg) + self.assertEqual(mask2.count(), mask2_count, msg) + self.assertEqual(mask1.get_size(), mask1_size, msg) + self.assertEqual(mask2.get_size(), mask2_size, msg) + + @unittest.skipIf(IS_PYPY, "Segfaults on pypy") + def test_draw__bit_boundaries(self): + """Ensures draw handles masks of different sizes correctly. + + Tests masks of different sizes, including: + -masks 31 to 33 bits wide (32 bit boundaries) + -masks 63 to 65 bits wide (64 bit boundaries) + """ + for height in range(2, 4): + for width in range(2, 66): + mask_size = (width, height) + mask_count = width * height + mask1 = pygame.mask.Mask(mask_size) + mask2 = pygame.mask.Mask(mask_size, fill=True) + expected_mask = pygame.Mask(mask_size) + + # Using rects to help determine the overlapping area. + rect1 = mask1.get_rect() + rect2 = mask2.get_rect() + + # Testing masks offset from each other. + for offset in self.ORIGIN_OFFSETS: + msg = "size={}, offset={}".format(mask_size, offset) + rect2.topleft = offset + overlap_rect = rect1.clip(rect2) + expected_mask.clear() + + # Normally draw() could be used to set these bits, but the + # draw() method is being tested here, so a loop is used + # instead. + for x in range(overlap_rect.left, overlap_rect.right): + for y in range(overlap_rect.top, overlap_rect.bottom): + expected_mask.set_at((x, y)) + mask1.clear() # Ensure it's empty for each test. + + mask1.draw(mask2, offset) + + assertMaskEqual(self, mask1, expected_mask, msg) + + # Ensure mask2 unchanged. + self.assertEqual(mask2.count(), mask_count, msg) + self.assertEqual(mask2.get_size(), mask_size, msg) + + def test_draw__invalid_mask_arg(self): + """Ensure draw handles invalid mask arguments correctly.""" + size = (7, 3) + offset = (0, 0) + mask = pygame.mask.Mask(size) + invalid_mask = pygame.Surface(size) + + with self.assertRaises(TypeError): + mask.draw(invalid_mask, offset) + + def test_draw__invalid_offset_arg(self): + """Ensure draw handles invalid offset arguments correctly.""" + size = (5, 7) + offset = "(0, 0)" + mask1 = pygame.mask.Mask(size) + mask2 = pygame.mask.Mask(size) + + with self.assertRaises(TypeError): + mask1.draw(mask2, offset) + + def test_erase(self): + """Ensure a mask can erase another mask. + + Testing the different combinations of full/empty masks: + (mask1-filled) 1 erase 1 (mask2-filled) + (mask1-empty) 0 erase 1 (mask2-filled) + (mask1-filled) 1 erase 0 (mask2-empty) + (mask1-empty) 0 erase 0 (mask2-empty) + """ + expected_size = (4, 4) + offset = (0, 0) + expected_default = pygame.mask.Mask(expected_size) + expected_masks = {(True, False): pygame.mask.Mask(expected_size, fill=True)} + + for fill2 in (True, False): + mask2 = pygame.mask.Mask(expected_size, fill=fill2) + mask2_count = mask2.count() + + for fill1 in (True, False): + key = (fill1, fill2) + msg = "key={}".format(key) + mask1 = pygame.mask.Mask(expected_size, fill=fill1) + expected_mask = expected_masks.get(key, expected_default) + + mask1.erase(mask2, offset) + + assertMaskEqual(self, mask1, expected_mask, msg) + + # Ensure mask2 unchanged. + self.assertEqual(mask2.count(), mask2_count, msg) + self.assertEqual(mask2.get_size(), expected_size, msg) + + def test_erase__offset(self): + """Ensure an offset mask can erase another mask.""" + mask1 = pygame.mask.Mask((65, 3)) + mask2 = pygame.mask.Mask((66, 4), fill=True) + mask2_count = mask2.count() + mask2_size = mask2.get_size() + expected_mask = pygame.Mask(mask1.get_size()) + + # Using rects to help determine the overlapping area. + rect1 = mask1.get_rect() + rect2 = mask2.get_rect() + + for offset in self.ORIGIN_OFFSETS: + msg = "offset={}".format(offset) + rect2.topleft = offset + overlap_rect = rect1.clip(rect2) + expected_mask.fill() + + # Normally erase() could be used to clear these bits, but the + # erase() method is being tested here, so a loop is used instead. + for x in range(overlap_rect.left, overlap_rect.right): + for y in range(overlap_rect.top, overlap_rect.bottom): + expected_mask.set_at((x, y), 0) + mask1.fill() # Ensure it's filled for testing each offset. + + mask1.erase(other=mask2, offset=offset) + + assertMaskEqual(self, mask1, expected_mask, msg) + + # Ensure mask2 unchanged. + self.assertEqual(mask2.count(), mask2_count, msg) + self.assertEqual(mask2.get_size(), mask2_size, msg) + + def test_erase__specific_offsets(self): + """Ensure an offset mask can erase another mask. + + Testing the specific case of: + -both masks are wider than 32 bits + -a positive offset is used + -the mask calling erase() is wider than the mask passed in + """ + mask1 = pygame.mask.Mask((65, 5)) + mask2 = pygame.mask.Mask((33, 3), fill=True) + expected_mask = pygame.Mask(mask1.get_size()) + + # Using rects to help determine the overlapping area. + rect1 = mask1.get_rect() + rect2 = mask2.get_rect() + + # This rect's corners are used to move rect2 around the inside of + # rect1. + corner_rect = rect1.inflate(-2, -2) + + for corner in ("topleft", "topright", "bottomright", "bottomleft"): + setattr(rect2, corner, getattr(corner_rect, corner)) + offset = rect2.topleft + msg = "offset={}".format(offset) + overlap_rect = rect1.clip(rect2) + expected_mask.fill() + + # Normally erase() could be used to clear these bits, but the + # erase() method is being tested here, so a loop is used instead. + for x in range(overlap_rect.left, overlap_rect.right): + for y in range(overlap_rect.top, overlap_rect.bottom): + expected_mask.set_at((x, y), 0) + mask1.fill() # Ensure it's filled for testing each offset. + + mask1.erase(mask2, Vector2(offset)) + + assertMaskEqual(self, mask1, expected_mask, msg) + + def test_erase__offset_boundary(self): + """Ensures erase handles offsets and boundaries correctly.""" + mask1 = pygame.mask.Mask((7, 11), fill=True) + mask2 = pygame.mask.Mask((3, 13), fill=True) + mask1_count = mask1.count() + mask2_count = mask2.count() + mask1_size = mask1.get_size() + mask2_size = mask2.get_size() + + # Check the 4 boundaries. + offsets = ( + (mask1_size[0], 0), # off right + (0, mask1_size[1]), # off bottom + (-mask2_size[0], 0), # off left + (0, -mask2_size[1]), + ) # off top + + for offset in offsets: + msg = "offset={}".format(offset) + + mask1.erase(mask2, offset) + + # Ensure mask1/mask2 unchanged. + self.assertEqual(mask1.count(), mask1_count, msg) + self.assertEqual(mask2.count(), mask2_count, msg) + self.assertEqual(mask1.get_size(), mask1_size, msg) + self.assertEqual(mask2.get_size(), mask2_size, msg) + + @unittest.skipIf(IS_PYPY, "Segfaults on pypy") + def test_erase__bit_boundaries(self): + """Ensures erase handles masks of different sizes correctly. + + Tests masks of different sizes, including: + -masks 31 to 33 bits wide (32 bit boundaries) + -masks 63 to 65 bits wide (64 bit boundaries) + """ + for height in range(2, 4): + for width in range(2, 66): + mask_size = (width, height) + mask_count = width * height + mask1 = pygame.mask.Mask(mask_size) + mask2 = pygame.mask.Mask(mask_size, fill=True) + expected_mask = pygame.Mask(mask_size) + + # Using rects to help determine the overlapping area. + rect1 = mask1.get_rect() + rect2 = mask2.get_rect() + + # Testing masks offset from each other. + for offset in self.ORIGIN_OFFSETS: + msg = "size={}, offset={}".format(mask_size, offset) + rect2.topleft = offset + overlap_rect = rect1.clip(rect2) + expected_mask.fill() + + # Normally erase() could be used to clear these bits, but + # the erase() method is being tested here, so a loop is + # used instead. + for x in range(overlap_rect.left, overlap_rect.right): + for y in range(overlap_rect.top, overlap_rect.bottom): + expected_mask.set_at((x, y), 0) + mask1.fill() # Ensure it's filled for each test. + + mask1.erase(mask2, offset) + + assertMaskEqual(self, mask1, expected_mask, msg) + + # Ensure mask2 unchanged. + self.assertEqual(mask2.count(), mask_count, msg) + self.assertEqual(mask2.get_size(), mask_size, msg) + + def test_erase__invalid_mask_arg(self): + """Ensure erase handles invalid mask arguments correctly.""" + size = (3, 7) + offset = (0, 0) + mask = pygame.mask.Mask(size) + invalid_mask = pygame.Surface(size) + + with self.assertRaises(TypeError): + mask.erase(invalid_mask, offset) + + def test_erase__invalid_offset_arg(self): + """Ensure erase handles invalid offset arguments correctly.""" + size = (7, 5) + offset = "(0, 0)" + mask1 = pygame.mask.Mask(size) + mask2 = pygame.mask.Mask(size) + + with self.assertRaises(TypeError): + mask1.erase(mask2, offset) + + def test_count(self): + """Ensure a mask's set bits are correctly counted.""" + side = 67 + expected_size = (side, side) + expected_count = 0 + mask = pygame.mask.Mask(expected_size) + + for i in range(side): + expected_count += 1 + mask.set_at((i, i)) + + count = mask.count() + + self.assertEqual(count, expected_count) + self.assertEqual(mask.get_size(), expected_size) + + @unittest.skipIf(IS_PYPY, "Segfaults on pypy") + def test_count__bit_boundaries(self): + """Ensures the set bits of different sized masks are counted correctly. + + Tests masks of different sizes, including: + -masks 31 to 33 bits wide (32 bit boundaries) + -masks 63 to 65 bits wide (64 bit boundaries) + """ + for fill in (True, False): + for height in range(1, 4): + for width in range(1, 66): + mask = pygame.mask.Mask((width, height), fill=fill) + expected_count = width * height if fill else 0 + + # Test toggling each bit. + for pos in ((x, y) for y in range(height) for x in range(width)): + if fill: + mask.set_at(pos, 0) + expected_count -= 1 + else: + mask.set_at(pos, 1) + expected_count += 1 + + count = mask.count() + + self.assertEqual( + count, + expected_count, + "fill={}, size=({}, {}), pos={}".format( + fill, width, height, pos + ), + ) + + def test_count__full_mask(self): + """Ensure a full mask's set bits are correctly counted.""" + width, height = 17, 97 + expected_size = (width, height) + expected_count = width * height + mask = pygame.mask.Mask(expected_size, fill=True) + + count = mask.count() + + self.assertEqual(count, expected_count) + self.assertEqual(mask.get_size(), expected_size) + + def test_count__empty_mask(self): + """Ensure an empty mask's set bits are correctly counted.""" + expected_count = 0 + expected_size = (13, 27) + mask = pygame.mask.Mask(expected_size) + + count = mask.count() + + self.assertEqual(count, expected_count) + self.assertEqual(mask.get_size(), expected_size) + + def test_centroid(self): + """Ensure a filled mask's centroid is correctly calculated.""" + mask = pygame.mask.Mask((5, 7), fill=True) + expected_centroid = mask.get_rect().center + + centroid = mask.centroid() + + self.assertEqual(centroid, expected_centroid) + + def test_centroid__empty_mask(self): + """Ensure an empty mask's centroid is correctly calculated.""" + expected_centroid = (0, 0) + expected_size = (101, 103) + mask = pygame.mask.Mask(expected_size) + + centroid = mask.centroid() + + self.assertEqual(centroid, expected_centroid) + self.assertEqual(mask.get_size(), expected_size) + + def test_centroid__single_row(self): + """Ensure a mask's centroid is correctly calculated + when setting points along a single row.""" + width, height = (5, 7) + mask = pygame.mask.Mask((width, height)) + + for y in range(height): + mask.clear() # Clear for each row. + + for x in range(width): + mask.set_at((x, y)) + expected_centroid = (x // 2, y) + + centroid = mask.centroid() + + self.assertEqual(centroid, expected_centroid) + + def test_centroid__two_rows(self): + """Ensure a mask's centroid is correctly calculated + when setting points along two rows.""" + width, height = (5, 7) + mask = pygame.mask.Mask((width, height)) + + # The first row is tested with each of the other rows. + for y in range(1, height): + mask.clear() # Clear for each set of rows. + + for x in range(width): + mask.set_at((x, 0)) + mask.set_at((x, y)) + expected_centroid = (x // 2, y // 2) + + centroid = mask.centroid() + + self.assertEqual(centroid, expected_centroid) + + def test_centroid__single_column(self): + """Ensure a mask's centroid is correctly calculated + when setting points along a single column.""" + width, height = (5, 7) + mask = pygame.mask.Mask((width, height)) + + for x in range(width): + mask.clear() # Clear for each column. + + for y in range(height): + mask.set_at((x, y)) + expected_centroid = (x, y // 2) + + centroid = mask.centroid() + + self.assertEqual(centroid, expected_centroid) + + def test_centroid__two_columns(self): + """Ensure a mask's centroid is correctly calculated + when setting points along two columns.""" + width, height = (5, 7) + mask = pygame.mask.Mask((width, height)) + + # The first column is tested with each of the other columns. + for x in range(1, width): + mask.clear() # Clear for each set of columns. + + for y in range(height): + mask.set_at((0, y)) + mask.set_at((x, y)) + expected_centroid = (x // 2, y // 2) + + centroid = mask.centroid() + + self.assertEqual(centroid, expected_centroid) + + def test_centroid__all_corners(self): + """Ensure a mask's centroid is correctly calculated + when its corners are set.""" + mask = pygame.mask.Mask((5, 7)) + expected_centroid = mask.get_rect().center + + for corner in corners(mask): + mask.set_at(corner) + + centroid = mask.centroid() + + self.assertEqual(centroid, expected_centroid) + + def test_centroid__two_corners(self): + """Ensure a mask's centroid is correctly calculated + when only two corners are set.""" + mask = pygame.mask.Mask((5, 7)) + mask_rect = mask.get_rect() + mask_corners = corners(mask) + + for i, corner1 in enumerate(mask_corners): + for corner2 in mask_corners[i + 1 :]: + mask.clear() # Clear for each pair of corners. + mask.set_at(corner1) + mask.set_at(corner2) + + if corner1[0] == corner2[0]: + expected_centroid = (corner1[0], abs(corner1[1] - corner2[1]) // 2) + elif corner1[1] == corner2[1]: + expected_centroid = (abs(corner1[0] - corner2[0]) // 2, corner1[1]) + else: + expected_centroid = mask_rect.center + + centroid = mask.centroid() + + self.assertEqual(centroid, expected_centroid) + + def todo_test_angle(self): + """Ensure a mask's orientation angle is correctly calculated.""" + self.fail() + + def test_angle__empty_mask(self): + """Ensure an empty mask's angle is correctly calculated.""" + expected_angle = 0.0 + expected_size = (107, 43) + mask = pygame.mask.Mask(expected_size) + + angle = mask.angle() + + self.assertIsInstance(angle, float) + self.assertAlmostEqual(angle, expected_angle) + self.assertEqual(mask.get_size(), expected_size) + + def test_drawing(self): + """Test fill, clear, invert, draw, erase""" + m = pygame.Mask((100, 100)) + self.assertEqual(m.count(), 0) + + m.fill() + self.assertEqual(m.count(), 10000) + + m2 = pygame.Mask((10, 10), fill=True) + m.erase(m2, (50, 50)) + self.assertEqual(m.count(), 9900) + + m.invert() + self.assertEqual(m.count(), 100) + + m.draw(m2, (0, 0)) + self.assertEqual(m.count(), 200) + + m.clear() + self.assertEqual(m.count(), 0) + + def test_outline(self): + """ """ + + m = pygame.Mask((20, 20)) + self.assertEqual(m.outline(), []) + + m.set_at((10, 10), 1) + self.assertEqual(m.outline(), [(10, 10)]) + + m.set_at((10, 12), 1) + self.assertEqual(m.outline(10), [(10, 10)]) + + m.set_at((11, 11), 1) + self.assertEqual( + m.outline(), [(10, 10), (11, 11), (10, 12), (11, 11), (10, 10)] + ) + self.assertEqual(m.outline(every=2), [(10, 10), (10, 12), (10, 10)]) + + # TODO: Test more corner case outlines. + + def test_convolve__size(self): + sizes = [(1, 1), (31, 31), (32, 32), (100, 100)] + for s1 in sizes: + m1 = pygame.Mask(s1) + for s2 in sizes: + m2 = pygame.Mask(s2) + o = m1.convolve(m2) + + self.assertIsInstance(o, pygame.mask.Mask) + + for i in (0, 1): + self.assertEqual( + o.get_size()[i], m1.get_size()[i] + m2.get_size()[i] - 1 + ) + + def test_convolve__point_identities(self): + """Convolving with a single point is the identity, while convolving a point with something flips it.""" + m = random_mask((100, 100)) + k = pygame.Mask((1, 1)) + k.set_at((0, 0)) + + convolve_mask = m.convolve(k) + + self.assertIsInstance(convolve_mask, pygame.mask.Mask) + assertMaskEqual(self, m, convolve_mask) + + convolve_mask = k.convolve(k.convolve(m)) + + self.assertIsInstance(convolve_mask, pygame.mask.Mask) + assertMaskEqual(self, m, convolve_mask) + + def test_convolve__with_output(self): + """checks that convolution modifies only the correct portion of the output""" + + m = random_mask((10, 10)) + k = pygame.Mask((2, 2)) + k.set_at((0, 0)) + + o = pygame.Mask((50, 50)) + test = pygame.Mask((50, 50)) + + m.convolve(k, o) + test.draw(m, (1, 1)) + + self.assertIsInstance(o, pygame.mask.Mask) + assertMaskEqual(self, o, test) + + o.clear() + test.clear() + + m.convolve(other=k, output=o, offset=Vector2(10, 10)) + test.draw(m, (11, 11)) + + self.assertIsInstance(o, pygame.mask.Mask) + assertMaskEqual(self, o, test) + + def test_convolve__out_of_range(self): + full = pygame.Mask((2, 2), fill=True) + # Tuple of points (out of range) and the expected count for each. + pts_data = (((0, 3), 0), ((0, 2), 3), ((-2, -2), 1), ((-3, -3), 0)) + + for pt, expected_count in pts_data: + convolve_mask = full.convolve(full, None, pt) + + self.assertIsInstance(convolve_mask, pygame.mask.Mask) + self.assertEqual(convolve_mask.count(), expected_count) + + @unittest.skipIf(IS_PYPY, "Segfaults on pypy") + def test_convolve(self): + """Tests the definition of convolution""" + m1 = random_mask((100, 100)) + m2 = random_mask((100, 100)) + conv = m1.convolve(m2) + + self.assertIsInstance(conv, pygame.mask.Mask) + for i in range(conv.get_size()[0]): + for j in range(conv.get_size()[1]): + self.assertEqual( + conv.get_at((i, j)) == 0, m1.overlap(m2, (i - 99, j - 99)) is None + ) + + def _draw_component_pattern_box(self, mask, size, pos, inverse=False): + # Helper method to create/draw a 'box' pattern for testing. + # + # 111 + # 101 3x3 example pattern + # 111 + pattern = pygame.mask.Mask((size, size), fill=True) + pattern.set_at((size // 2, size // 2), 0) + + if inverse: + mask.erase(pattern, pos) + pattern.invert() + else: + mask.draw(pattern, pos) + + return pattern + + def _draw_component_pattern_x(self, mask, size, pos, inverse=False): + # Helper method to create/draw an 'X' pattern for testing. + # + # 101 + # 010 3x3 example pattern + # 101 + pattern = pygame.mask.Mask((size, size)) + + ymax = size - 1 + for y in range(size): + for x in range(size): + if x in [y, ymax - y]: + pattern.set_at((x, y)) + + if inverse: + mask.erase(pattern, pos) + pattern.invert() + else: + mask.draw(pattern, pos) + + return pattern + + def _draw_component_pattern_plus(self, mask, size, pos, inverse=False): + # Helper method to create/draw a '+' pattern for testing. + # + # 010 + # 111 3x3 example pattern + # 010 + pattern = pygame.mask.Mask((size, size)) + + xmid = ymid = size // 2 + for y in range(size): + for x in range(size): + if x == xmid or y == ymid: + pattern.set_at((x, y)) + + if inverse: + mask.erase(pattern, pos) + pattern.invert() + else: + mask.draw(pattern, pos) + + return pattern + + def test_connected_component(self): + """Ensure a mask's connected component is correctly calculated.""" + width, height = 41, 27 + expected_size = (width, height) + original_mask = pygame.mask.Mask(expected_size) + patterns = [] # Patterns and offsets. + + # Draw some connected patterns on the original mask. + offset = (0, 0) + pattern = self._draw_component_pattern_x(original_mask, 3, offset) + patterns.append((pattern, offset)) + + size = 4 + offset = (width - size, 0) + pattern = self._draw_component_pattern_plus(original_mask, size, offset) + patterns.append((pattern, offset)) + + # Make this one the largest connected component. + offset = (width // 2, height // 2) + pattern = self._draw_component_pattern_box(original_mask, 7, offset) + patterns.append((pattern, offset)) + + expected_pattern, expected_offset = patterns[-1] + expected_count = expected_pattern.count() + original_count = sum(p.count() for p, _ in patterns) + + mask = original_mask.connected_component() + + self.assertIsInstance(mask, pygame.mask.Mask) + self.assertEqual(mask.count(), expected_count) + self.assertEqual(mask.get_size(), expected_size) + self.assertEqual( + mask.overlap_area(expected_pattern, expected_offset), expected_count + ) + + # Ensure the original mask is unchanged. + self.assertEqual(original_mask.count(), original_count) + self.assertEqual(original_mask.get_size(), expected_size) + + for pattern, offset in patterns: + self.assertEqual( + original_mask.overlap_area(pattern, offset), pattern.count() + ) + + def test_connected_component__full_mask(self): + """Ensure a mask's connected component is correctly calculated + when the mask is full. + """ + expected_size = (23, 31) + original_mask = pygame.mask.Mask(expected_size, fill=True) + expected_count = original_mask.count() + + mask = original_mask.connected_component() + + self.assertIsInstance(mask, pygame.mask.Mask) + self.assertEqual(mask.count(), expected_count) + self.assertEqual(mask.get_size(), expected_size) + + # Ensure the original mask is unchanged. + self.assertEqual(original_mask.count(), expected_count) + self.assertEqual(original_mask.get_size(), expected_size) + + def test_connected_component__empty_mask(self): + """Ensure a mask's connected component is correctly calculated + when the mask is empty. + """ + expected_size = (37, 43) + original_mask = pygame.mask.Mask(expected_size) + original_count = original_mask.count() + expected_count = 0 + + mask = original_mask.connected_component() + + self.assertIsInstance(mask, pygame.mask.Mask) + self.assertEqual(mask.count(), expected_count) + self.assertEqual(mask.get_size(), expected_size) + + # Ensure the original mask is unchanged. + self.assertEqual(original_mask.count(), original_count) + self.assertEqual(original_mask.get_size(), expected_size) + + def test_connected_component__one_set_bit(self): + """Ensure a mask's connected component is correctly calculated + when the coordinate's bit is set with a connected component of 1 bit. + """ + width, height = 71, 67 + expected_size = (width, height) + original_mask = pygame.mask.Mask(expected_size, fill=True) + xset, yset = width // 2, height // 2 + set_pos = (xset, yset) + expected_offset = (xset - 1, yset - 1) + + # This isolates the bit at set_pos from all the other bits. + expected_pattern = self._draw_component_pattern_box( + original_mask, 3, expected_offset, inverse=True + ) + expected_count = 1 + original_count = original_mask.count() + + mask = original_mask.connected_component(set_pos) + + self.assertIsInstance(mask, pygame.mask.Mask) + self.assertEqual(mask.count(), expected_count) + self.assertEqual(mask.get_size(), expected_size) + self.assertEqual( + mask.overlap_area(expected_pattern, expected_offset), expected_count + ) + + # Ensure the original mask is unchanged. + self.assertEqual(original_mask.count(), original_count) + self.assertEqual(original_mask.get_size(), expected_size) + self.assertEqual( + original_mask.overlap_area(expected_pattern, expected_offset), + expected_count, + ) + + def test_connected_component__multi_set_bits(self): + """Ensure a mask's connected component is correctly calculated + when the coordinate's bit is set with a connected component of > 1 bit. + """ + expected_size = (113, 67) + original_mask = pygame.mask.Mask(expected_size) + p_width, p_height = 11, 13 + set_pos = xset, yset = 11, 21 + expected_offset = (xset - 1, yset - 1) + expected_pattern = pygame.mask.Mask((p_width, p_height), fill=True) + + # Make an unsymmetrical pattern. All the set bits need to be connected + # in the resulting pattern for this to work properly. + for y in range(3, p_height): + for x in range(1, p_width): + if x in [y, y - 3, p_width - 4]: + expected_pattern.set_at((x, y), 0) + + expected_count = expected_pattern.count() + original_mask.draw(expected_pattern, expected_offset) + + mask = original_mask.connected_component(set_pos) + + self.assertIsInstance(mask, pygame.mask.Mask) + self.assertEqual(mask.count(), expected_count) + self.assertEqual(mask.get_size(), expected_size) + self.assertEqual( + mask.overlap_area(expected_pattern, expected_offset), expected_count + ) + + # Ensure the original mask is unchanged. + self.assertEqual(original_mask.count(), expected_count) + self.assertEqual(original_mask.get_size(), expected_size) + self.assertEqual( + original_mask.overlap_area(expected_pattern, expected_offset), + expected_count, + ) + + def test_connected_component__unset_bit(self): + """Ensure a mask's connected component is correctly calculated + when the coordinate's bit is unset. + """ + width, height = 109, 101 + expected_size = (width, height) + original_mask = pygame.mask.Mask(expected_size, fill=True) + unset_pos = (width // 2, height // 2) + original_mask.set_at(unset_pos, 0) + original_count = original_mask.count() + expected_count = 0 + + mask = original_mask.connected_component(unset_pos) + + self.assertIsInstance(mask, pygame.mask.Mask) + self.assertEqual(mask.count(), expected_count) + self.assertEqual(mask.get_size(), expected_size) + + # Ensure the original mask is unchanged. + self.assertEqual(original_mask.count(), original_count) + self.assertEqual(original_mask.get_size(), expected_size) + self.assertEqual(original_mask.get_at(unset_pos), 0) + + def test_connected_component__out_of_bounds(self): + """Ensure connected_component() checks bounds.""" + width, height = 19, 11 + original_size = (width, height) + original_mask = pygame.mask.Mask(original_size, fill=True) + original_count = original_mask.count() + + for pos in ((0, -1), (-1, 0), (0, height + 1), (width + 1, 0)): + with self.assertRaises(IndexError): + mask = original_mask.connected_component(pos) + + # Ensure the original mask is unchanged. + self.assertEqual(original_mask.count(), original_count) + self.assertEqual(original_mask.get_size(), original_size) + + def test_connected_components(self): + """ """ + m = pygame.Mask((10, 10)) + + self.assertListEqual(m.connected_components(), []) + + comp = m.connected_component() + + self.assertEqual(m.count(), comp.count()) + + m.set_at((0, 0), 1) + m.set_at((1, 1), 1) + comp = m.connected_component() + comps = m.connected_components() + comps1 = m.connected_components(1) + comps2 = m.connected_components(2) + comps3 = m.connected_components(3) + + self.assertEqual(comp.count(), comps[0].count()) + self.assertEqual(comps1[0].count(), 2) + self.assertEqual(comps2[0].count(), 2) + self.assertListEqual(comps3, []) + + m.set_at((9, 9), 1) + comp = m.connected_component() + comp1 = m.connected_component((1, 1)) + comp2 = m.connected_component((2, 2)) + comps = m.connected_components() + comps1 = m.connected_components(1) + comps2 = m.connected_components(minimum=2) + comps3 = m.connected_components(3) + + self.assertEqual(comp.count(), 2) + self.assertEqual(comp1.count(), 2) + self.assertEqual(comp2.count(), 0) + self.assertEqual(len(comps), 2) + self.assertEqual(len(comps1), 2) + self.assertEqual(len(comps2), 1) + self.assertEqual(len(comps3), 0) + + for mask in comps: + self.assertIsInstance(mask, pygame.mask.Mask) + + def test_connected_components__negative_min_with_empty_mask(self): + """Ensures connected_components() properly handles negative min values + when the mask is empty. + + Negative and zero values for the min parameter (minimum number of bits + per connected component) equate to setting it to one. + """ + expected_comps = [] + mask_count = 0 + mask_size = (65, 13) + mask = pygame.mask.Mask(mask_size) + + connected_comps = mask.connected_components(-1) + + self.assertListEqual(connected_comps, expected_comps) + + # Ensure the original mask is unchanged. + self.assertEqual(mask.count(), mask_count) + self.assertEqual(mask.get_size(), mask_size) + + def test_connected_components__negative_min_with_full_mask(self): + """Ensures connected_components() properly handles negative min values + when the mask is full. + + Negative and zero values for the min parameter (minimum number of bits + per connected component) equate to setting it to one. + """ + mask_size = (64, 11) + mask = pygame.mask.Mask(mask_size, fill=True) + mask_count = mask.count() + expected_len = 1 + + connected_comps = mask.connected_components(-2) + + self.assertEqual(len(connected_comps), expected_len) + assertMaskEqual(self, connected_comps[0], mask) + + # Ensure the original mask is unchanged. + self.assertEqual(mask.count(), mask_count) + self.assertEqual(mask.get_size(), mask_size) + + def test_connected_components__negative_min_with_some_bits_set(self): + """Ensures connected_components() properly handles negative min values + when the mask has some bits set. + + Negative and zero values for the min parameter (minimum number of bits + per connected component) equate to setting it to one. + """ + mask_size = (64, 12) + mask = pygame.mask.Mask(mask_size) + expected_comps = {} + + # Set the corners and the center positions. A new expected component + # mask is created for each point. + for corner in corners(mask): + mask.set_at(corner) + + new_mask = pygame.mask.Mask(mask_size) + new_mask.set_at(corner) + expected_comps[corner] = new_mask + + center = (mask_size[0] // 2, mask_size[1] // 2) + mask.set_at(center) + + new_mask = pygame.mask.Mask(mask_size) + new_mask.set_at(center) + expected_comps[center] = new_mask + mask_count = mask.count() + + connected_comps = mask.connected_components(-3) + + self.assertEqual(len(connected_comps), len(expected_comps)) + + for comp in connected_comps: + # Since the masks in the connected component list can be in any + # order, loop the expected components to find its match. + found = False + + for pt in tuple(expected_comps.keys()): + if comp.get_at(pt): + found = True + assertMaskEqual(self, comp, expected_comps[pt]) + del expected_comps[pt] # Entry removed so it isn't reused. + break + + self.assertTrue(found, "missing component for pt={}".format(pt)) + + # Ensure the original mask is unchanged. + self.assertEqual(mask.count(), mask_count) + self.assertEqual(mask.get_size(), mask_size) + + @unittest.skipIf(IS_PYPY, "Segfaults on pypy") + def test_get_bounding_rects(self): + """Ensures get_bounding_rects works correctly.""" + # Create masks with different set point groups. Each group of + # connected set points will be contained in its own bounding rect. + # Diagonal points are considered connected. + mask_data = [] # [((size), ((rect1_pts), ...)), ...] + + # Mask 1: + # |0123456789 + # -+---------- + # 0|1100000000 + # 1|1000000000 + # 2|0000000000 + # 3|1001000000 + # 4|0000000000 + # 5|0000000000 + # 6|0000000000 + # 7|0000000000 + # 8|0000000000 + # 9|0000000000 + mask_data.append( + ( + (10, 10), # size + # Points to set for the 3 bounding rects. + (((0, 0), (1, 0), (0, 1)), ((0, 3),), ((3, 3),)), # rect1 # rect2 + ) + ) # rect3 + + # Mask 2: + # |0123 + # -+---- + # 0|1100 + # 1|1111 + mask_data.append( + ( + (4, 2), # size + # Points to set for the 1 bounding rect. + (((0, 0), (1, 0), (0, 1), (1, 1), (2, 1), (3, 1)),), + ) + ) + + # Mask 3: + # |01234 + # -+----- + # 0|00100 + # 1|01110 + # 2|00100 + mask_data.append( + ( + (5, 3), # size + # Points to set for the 1 bounding rect. + (((2, 0), (1, 1), (2, 1), (3, 1), (2, 2)),), + ) + ) + + # Mask 4: + # |01234 + # -+----- + # 0|00010 + # 1|00100 + # 2|01000 + mask_data.append( + ( + (5, 3), # size + # Points to set for the 1 bounding rect. + (((3, 0), (2, 1), (1, 2)),), + ) + ) + + # Mask 5: + # |01234 + # -+----- + # 0|00011 + # 1|11111 + mask_data.append( + ( + (5, 2), # size + # Points to set for the 1 bounding rect. + (((3, 0), (4, 0), (0, 1), (1, 1), (2, 1), (3, 1)),), + ) + ) + + # Mask 6: + # |01234 + # -+----- + # 0|10001 + # 1|00100 + # 2|10001 + mask_data.append( + ( + (5, 3), # size + # Points to set for the 5 bounding rects. + ( + ((0, 0),), # rect1 + ((4, 0),), # rect2 + ((2, 1),), # rect3 + ((0, 2),), # rect4 + ((4, 2),), + ), + ) + ) # rect5 + + for size, rect_point_tuples in mask_data: + rects = [] + mask = pygame.Mask(size) + + for rect_points in rect_point_tuples: + rects.append(create_bounding_rect(rect_points)) + for pt in rect_points: + mask.set_at(pt) + + expected_rects = sorted(rects, key=tuple) + + rects = mask.get_bounding_rects() + + self.assertListEqual( + sorted(mask.get_bounding_rects(), key=tuple), + expected_rects, + "size={}".format(size), + ) + + @unittest.skipIf(IS_PYPY, "Segfaults on pypy") + def test_to_surface(self): + """Ensures empty and full masks can be drawn onto surfaces.""" + expected_ref_count = 3 + size = (33, 65) + surface = pygame.Surface(size, SRCALPHA, 32) + surface_color = pygame.Color("red") + test_fills = ((pygame.Color("white"), True), (pygame.Color("black"), False)) + + for expected_color, fill in test_fills: + surface.fill(surface_color) + mask = pygame.mask.Mask(size, fill=fill) + + to_surface = mask.to_surface(surface) + + self.assertIs(to_surface, surface) + if not IS_PYPY: + self.assertEqual(sys.getrefcount(to_surface), expected_ref_count) + self.assertEqual(to_surface.get_size(), size) + assertSurfaceFilled(self, to_surface, expected_color) + + def test_to_surface__create_surface(self): + """Ensures empty and full masks can be drawn onto a created surface.""" + expected_ref_count = 2 + expected_flag = SRCALPHA + expected_depth = 32 + size = (33, 65) + test_fills = ((pygame.Color("white"), True), (pygame.Color("black"), False)) + + for expected_color, fill in test_fills: + mask = pygame.mask.Mask(size, fill=fill) + + for use_arg in (True, False): + if use_arg: + to_surface = mask.to_surface(None) + else: + to_surface = mask.to_surface() + + self.assertIsInstance(to_surface, pygame.Surface) + if not IS_PYPY: + self.assertEqual(sys.getrefcount(to_surface), expected_ref_count) + self.assertTrue(to_surface.get_flags() & expected_flag) + self.assertEqual(to_surface.get_bitsize(), expected_depth) + self.assertEqual(to_surface.get_size(), size) + assertSurfaceFilled(self, to_surface, expected_color) + + def test_to_surface__surface_param(self): + """Ensures to_surface accepts a surface arg/kwarg.""" + expected_ref_count = 4 + expected_color = pygame.Color("white") + surface_color = pygame.Color("red") + size = (5, 3) + mask = pygame.mask.Mask(size, fill=True) + surface = pygame.Surface(size) + kwargs = {"surface": surface} + + for use_kwargs in (True, False): + surface.fill(surface_color) + + if use_kwargs: + to_surface = mask.to_surface(**kwargs) + else: + to_surface = mask.to_surface(kwargs["surface"]) + + self.assertIs(to_surface, surface) + if not IS_PYPY: + self.assertEqual(sys.getrefcount(to_surface), expected_ref_count) + self.assertEqual(to_surface.get_size(), size) + assertSurfaceFilled(self, to_surface, expected_color) + + def test_to_surface__setsurface_param(self): + """Ensures to_surface accepts a setsurface arg/kwarg.""" + expected_ref_count = 2 + expected_flag = SRCALPHA + expected_depth = 32 + expected_color = pygame.Color("red") + size = (5, 3) + mask = pygame.mask.Mask(size, fill=True) + setsurface = pygame.Surface(size, expected_flag, expected_depth) + setsurface.fill(expected_color) + kwargs = {"setsurface": setsurface} + + for use_kwargs in (True, False): + if use_kwargs: + to_surface = mask.to_surface(**kwargs) + else: + to_surface = mask.to_surface(None, kwargs["setsurface"]) + + self.assertIsInstance(to_surface, pygame.Surface) + + if not IS_PYPY: + self.assertEqual(sys.getrefcount(to_surface), expected_ref_count) + self.assertTrue(to_surface.get_flags() & expected_flag) + self.assertEqual(to_surface.get_bitsize(), expected_depth) + self.assertEqual(to_surface.get_size(), size) + assertSurfaceFilled(self, to_surface, expected_color) + + def test_to_surface__unsetsurface_param(self): + """Ensures to_surface accepts a unsetsurface arg/kwarg.""" + expected_ref_count = 2 + expected_flag = SRCALPHA + expected_depth = 32 + expected_color = pygame.Color("red") + size = (5, 3) + mask = pygame.mask.Mask(size) + unsetsurface = pygame.Surface(size, expected_flag, expected_depth) + unsetsurface.fill(expected_color) + kwargs = {"unsetsurface": unsetsurface} + + for use_kwargs in (True, False): + if use_kwargs: + to_surface = mask.to_surface(**kwargs) + else: + to_surface = mask.to_surface(None, None, kwargs["unsetsurface"]) + + self.assertIsInstance(to_surface, pygame.Surface) + if not IS_PYPY: + self.assertEqual(sys.getrefcount(to_surface), expected_ref_count) + self.assertTrue(to_surface.get_flags() & expected_flag) + self.assertEqual(to_surface.get_bitsize(), expected_depth) + self.assertEqual(to_surface.get_size(), size) + assertSurfaceFilled(self, to_surface, expected_color) + + def test_to_surface__setcolor_param(self): + """Ensures to_surface accepts a setcolor arg/kwarg.""" + expected_ref_count = 2 + expected_flag = SRCALPHA + expected_depth = 32 + expected_color = pygame.Color("red") + size = (5, 3) + mask = pygame.mask.Mask(size, fill=True) + kwargs = {"setcolor": expected_color} + + for use_kwargs in (True, False): + if use_kwargs: + to_surface = mask.to_surface(**kwargs) + else: + to_surface = mask.to_surface(None, None, None, kwargs["setcolor"]) + + self.assertIsInstance(to_surface, pygame.Surface) + if not IS_PYPY: + self.assertEqual(sys.getrefcount(to_surface), expected_ref_count) + self.assertTrue(to_surface.get_flags() & expected_flag) + self.assertEqual(to_surface.get_bitsize(), expected_depth) + self.assertEqual(to_surface.get_size(), size) + assertSurfaceFilled(self, to_surface, expected_color) + + def test_to_surface__setcolor_default(self): + """Ensures the default setcolor is correct.""" + expected_color = pygame.Color("white") + size = (3, 7) + mask = pygame.mask.Mask(size, fill=True) + + to_surface = mask.to_surface( + surface=None, setsurface=None, unsetsurface=None, unsetcolor=None + ) + + self.assertEqual(to_surface.get_size(), size) + assertSurfaceFilled(self, to_surface, expected_color) + + def test_to_surface__unsetcolor_param(self): + """Ensures to_surface accepts a unsetcolor arg/kwarg.""" + expected_ref_count = 2 + expected_flag = SRCALPHA + expected_depth = 32 + expected_color = pygame.Color("red") + size = (5, 3) + mask = pygame.mask.Mask(size) + kwargs = {"unsetcolor": expected_color} + + for use_kwargs in (True, False): + if use_kwargs: + to_surface = mask.to_surface(**kwargs) + else: + to_surface = mask.to_surface( + None, None, None, None, kwargs["unsetcolor"] + ) + + self.assertIsInstance(to_surface, pygame.Surface) + if not IS_PYPY: + self.assertEqual(sys.getrefcount(to_surface), expected_ref_count) + self.assertTrue(to_surface.get_flags() & expected_flag) + self.assertEqual(to_surface.get_bitsize(), expected_depth) + self.assertEqual(to_surface.get_size(), size) + assertSurfaceFilled(self, to_surface, expected_color) + + def test_to_surface__unsetcolor_default(self): + """Ensures the default unsetcolor is correct.""" + expected_color = pygame.Color("black") + size = (3, 7) + mask = pygame.mask.Mask(size) + + to_surface = mask.to_surface( + surface=None, setsurface=None, unsetsurface=None, setcolor=None + ) + + self.assertEqual(to_surface.get_size(), size) + assertSurfaceFilled(self, to_surface, expected_color) + + def test_to_surface__dest_param(self): + """Ensures to_surface accepts a dest arg/kwarg.""" + expected_ref_count = 2 + expected_flag = SRCALPHA + expected_depth = 32 + default_surface_color = (0, 0, 0, 0) + default_unsetcolor = pygame.Color("black") + dest = (0, 0) + size = (5, 3) + mask = pygame.mask.Mask(size) + kwargs = {"dest": dest} + + for use_kwargs in (True, False): + if use_kwargs: + expected_color = default_unsetcolor + + to_surface = mask.to_surface(**kwargs) + else: + expected_color = default_surface_color + + to_surface = mask.to_surface( + None, None, None, None, None, kwargs["dest"] + ) + + self.assertIsInstance(to_surface, pygame.Surface) + if not IS_PYPY: + self.assertEqual(sys.getrefcount(to_surface), expected_ref_count) + self.assertTrue(to_surface.get_flags() & expected_flag) + self.assertEqual(to_surface.get_bitsize(), expected_depth) + self.assertEqual(to_surface.get_size(), size) + assertSurfaceFilled(self, to_surface, expected_color) + + def test_to_surface__dest_default(self): + """Ensures the default dest is correct.""" + expected_color = pygame.Color("white") + surface_color = pygame.Color("red") + + mask_size = (3, 2) + mask = pygame.mask.Mask(mask_size, fill=True) + mask_rect = mask.get_rect() + + # Make the surface bigger than the mask. + surf_size = (mask_size[0] + 2, mask_size[1] + 1) + surface = pygame.Surface(surf_size, SRCALPHA, 32) + surface.fill(surface_color) + + to_surface = mask.to_surface( + surface, setsurface=None, unsetsurface=None, unsetcolor=None + ) + + self.assertIs(to_surface, surface) + self.assertEqual(to_surface.get_size(), surf_size) + assertSurfaceFilled(self, to_surface, expected_color, mask_rect) + assertSurfaceFilledIgnoreArea(self, to_surface, surface_color, mask_rect) + + @unittest.expectedFailure + def test_to_surface__area_param(self): + """Ensures to_surface accepts an area arg/kwarg.""" + expected_ref_count = 2 + expected_flag = SRCALPHA + expected_depth = 32 + default_surface_color = (0, 0, 0, 0) + default_unsetcolor = pygame.Color("black") + size = (5, 3) + mask = pygame.mask.Mask(size) + kwargs = {"area": mask.get_rect()} + + for use_kwargs in (True, False): + if use_kwargs: + expected_color = default_unsetcolor + + to_surface = mask.to_surface(**kwargs) + else: + expected_color = default_surface_color + + to_surface = mask.to_surface( + None, None, None, None, None, (0, 0), kwargs["area"] + ) + + self.assertIsInstance(to_surface, pygame.Surface) + if not IS_PYPY: + self.assertEqual(sys.getrefcount(to_surface), expected_ref_count) + self.assertTrue(to_surface.get_flags() & expected_flag) + self.assertEqual(to_surface.get_bitsize(), expected_depth) + self.assertEqual(to_surface.get_size(), size) + assertSurfaceFilled(self, to_surface, expected_color) + + def test_to_surface__area_default(self): + """Ensures the default area is correct.""" + expected_color = pygame.Color("white") + surface_color = pygame.Color("red") + + mask_size = (3, 2) + mask = pygame.mask.Mask(mask_size, fill=True) + mask_rect = mask.get_rect() + + # Make the surface bigger than the mask. The default area is the full + # area of the mask. + surf_size = (mask_size[0] + 2, mask_size[1] + 1) + surface = pygame.Surface(surf_size, SRCALPHA, 32) + surface.fill(surface_color) + + to_surface = mask.to_surface( + surface, setsurface=None, unsetsurface=None, unsetcolor=None + ) + + self.assertIs(to_surface, surface) + self.assertEqual(to_surface.get_size(), surf_size) + assertSurfaceFilled(self, to_surface, expected_color, mask_rect) + assertSurfaceFilledIgnoreArea(self, to_surface, surface_color, mask_rect) + + def test_to_surface__kwargs(self): + """Ensures to_surface accepts the correct kwargs.""" + expected_color = pygame.Color("white") + size = (5, 3) + mask = pygame.mask.Mask(size, fill=True) + surface = pygame.Surface(size) + surface_color = pygame.Color("red") + setsurface = surface.copy() + setsurface.fill(expected_color) + + test_data = ( + (None, None), # None entry allows loop to test all kwargs on first pass. + ("dest", (0, 0)), + ("unsetcolor", pygame.Color("yellow")), + ("setcolor", expected_color), + ("unsetsurface", surface.copy()), + ("setsurface", setsurface), + ("surface", surface), + ) + + kwargs = dict(test_data) + + for name, _ in test_data: + kwargs.pop(name) + surface.fill(surface_color) # Clear for each test. + + to_surface = mask.to_surface(**kwargs) + + self.assertEqual(to_surface.get_size(), size) + assertSurfaceFilled(self, to_surface, expected_color) + + def test_to_surface__kwargs_create_surface(self): + """Ensures to_surface accepts the correct kwargs + when creating a surface. + """ + expected_color = pygame.Color("black") + size = (5, 3) + mask = pygame.mask.Mask(size) + setsurface = pygame.Surface(size, SRCALPHA, 32) + setsurface_color = pygame.Color("red") + setsurface.fill(setsurface_color) + unsetsurface = setsurface.copy() + unsetsurface.fill(expected_color) + + test_data = ( + (None, None), # None entry allows loop to test all kwargs on first pass. + ("dest", (0, 0)), + ("unsetcolor", expected_color), + ("setcolor", pygame.Color("yellow")), + ("unsetsurface", unsetsurface), + ("setsurface", setsurface), + ("surface", None), + ) + kwargs = dict(test_data) + + for name, _ in test_data: + kwargs.pop(name) + + to_surface = mask.to_surface(**kwargs) + + self.assertIsInstance(to_surface, pygame.Surface) + self.assertEqual(to_surface.get_size(), size) + assertSurfaceFilled(self, to_surface, expected_color) + + def test_to_surface__kwargs_order_independent(self): + """Ensures to_surface kwargs are not order dependent.""" + expected_color = pygame.Color("blue") + size = (3, 2) + mask = pygame.mask.Mask(size, fill=True) + surface = pygame.Surface(size) + + to_surface = mask.to_surface( + dest=(0, 0), + setcolor=expected_color, + unsetcolor=None, + surface=surface, + unsetsurface=pygame.Surface(size), + setsurface=None, + ) + + self.assertIs(to_surface, surface) + self.assertEqual(to_surface.get_size(), size) + assertSurfaceFilled(self, to_surface, expected_color) + + def test_to_surface__args_invalid_types(self): + """Ensures to_surface detects invalid kwarg types.""" + size = (3, 2) + mask = pygame.mask.Mask(size, fill=True) + invalid_surf = pygame.Color("green") + invalid_color = pygame.Surface(size) + + with self.assertRaises(TypeError): + # Invalid dest. + mask.to_surface(None, None, None, None, None, (0,)) + + with self.assertRaises(TypeError): + # Invalid unsetcolor. + mask.to_surface(None, None, None, None, invalid_color) + + with self.assertRaises(TypeError): + # Invalid setcolor. + mask.to_surface(None, None, None, invalid_color, None) + + with self.assertRaises(TypeError): + # Invalid unsetsurface. + mask.to_surface(None, None, invalid_surf, None, None) + + with self.assertRaises(TypeError): + # Invalid setsurface. + mask.to_surface(None, invalid_surf, None, None, None) + + with self.assertRaises(TypeError): + # Invalid surface. + mask.to_surface(invalid_surf, None, None, None, None) + + def test_to_surface__kwargs_invalid_types(self): + """Ensures to_surface detects invalid kwarg types.""" + size = (3, 2) + mask = pygame.mask.Mask(size) + + valid_kwargs = { + "surface": pygame.Surface(size), + "setsurface": pygame.Surface(size), + "unsetsurface": pygame.Surface(size), + "setcolor": pygame.Color("green"), + "unsetcolor": pygame.Color("green"), + "dest": (0, 0), + } + + invalid_kwargs = { + "surface": (1, 2, 3, 4), + "setsurface": pygame.Color("green"), + "unsetsurface": ((1, 2), (2, 1)), + "setcolor": pygame.Mask((1, 2)), + "unsetcolor": pygame.Surface((2, 2)), + "dest": (0, 0, 0), + } + + kwarg_order = ( + "surface", + "setsurface", + "unsetsurface", + "setcolor", + "unsetcolor", + "dest", + ) + + for kwarg in kwarg_order: + kwargs = dict(valid_kwargs) + kwargs[kwarg] = invalid_kwargs[kwarg] + + with self.assertRaises(TypeError): + mask.to_surface(**kwargs) + + def test_to_surface__kwargs_invalid_name(self): + """Ensures to_surface detects invalid kwarg names.""" + mask = pygame.mask.Mask((3, 2)) + kwargs = {"setcolour": pygame.Color("red")} + + with self.assertRaises(TypeError): + mask.to_surface(**kwargs) + + def test_to_surface__args_and_kwargs(self): + """Ensures to_surface accepts a combination of args/kwargs""" + size = (5, 3) + + surface_color = pygame.Color("red") + setsurface_color = pygame.Color("yellow") + unsetsurface_color = pygame.Color("blue") + setcolor = pygame.Color("green") + unsetcolor = pygame.Color("cyan") + + surface = pygame.Surface(size, SRCALPHA, 32) + setsurface = surface.copy() + unsetsurface = surface.copy() + + setsurface.fill(setsurface_color) + unsetsurface.fill(unsetsurface_color) + + mask = pygame.mask.Mask(size, fill=True) + expected_color = setsurface_color + + test_data = ( + (None, None), # None entry allows loop to test all kwargs on first pass. + ("surface", surface), + ("setsurface", setsurface), + ("unsetsurface", unsetsurface), + ("setcolor", setcolor), + ("unsetcolor", unsetcolor), + ("dest", (0, 0)), + ) + + args = [] + kwargs = dict(test_data) + + # Loop gradually moves the kwargs to args. + for name, value in test_data: + if name is not None: + args.append(value) + kwargs.pop(name) + + surface.fill(surface_color) + + to_surface = mask.to_surface(*args, **kwargs) + + assertSurfaceFilled(self, to_surface, expected_color) + + def test_to_surface__valid_setcolor_formats(self): + """Ensures to_surface handles valid setcolor formats correctly.""" + size = (5, 3) + mask = pygame.mask.Mask(size, fill=True) + surface = pygame.Surface(size, SRCALPHA, 32) + expected_color = pygame.Color("green") + test_colors = ( + (0, 255, 0), + (0, 255, 0, 255), + surface.map_rgb(expected_color), + expected_color, + "green", + "#00FF00FF", + "0x00FF00FF", + ) + + for setcolor in test_colors: + to_surface = mask.to_surface(setcolor=setcolor) + + assertSurfaceFilled(self, to_surface, expected_color) + + def test_to_surface__valid_unsetcolor_formats(self): + """Ensures to_surface handles valid unsetcolor formats correctly.""" + size = (5, 3) + mask = pygame.mask.Mask(size) + surface = pygame.Surface(size, SRCALPHA, 32) + expected_color = pygame.Color("green") + test_colors = ( + (0, 255, 0), + (0, 255, 0, 255), + surface.map_rgb(expected_color), + expected_color, + "green", + "#00FF00FF", + "0x00FF00FF", + ) + + for unsetcolor in test_colors: + to_surface = mask.to_surface(unsetcolor=unsetcolor) + + assertSurfaceFilled(self, to_surface, expected_color) + + def test_to_surface__invalid_setcolor_formats(self): + """Ensures to_surface handles invalid setcolor formats correctly.""" + mask = pygame.mask.Mask((5, 3)) + + for setcolor in ("green color", "#00FF00FF0", "0x00FF00FF0", (1, 2)): + with self.assertRaises(ValueError): + mask.to_surface(setcolor=setcolor) + + for setcolor in (pygame.Surface((1, 2)), pygame.Mask((2, 1)), 1.1): + with self.assertRaises(TypeError): + mask.to_surface(setcolor=setcolor) + + def test_to_surface__invalid_unsetcolor_formats(self): + """Ensures to_surface handles invalid unsetcolor formats correctly.""" + mask = pygame.mask.Mask((5, 3)) + + for unsetcolor in ("green color", "#00FF00FF0", "0x00FF00FF0", (1, 2)): + with self.assertRaises(ValueError): + mask.to_surface(unsetcolor=unsetcolor) + + for unsetcolor in (pygame.Surface((1, 2)), pygame.Mask((2, 1)), 1.1): + with self.assertRaises(TypeError): + mask.to_surface(unsetcolor=unsetcolor) + + def test_to_surface__valid_dest_formats(self): + """Ensures to_surface handles valid dest formats correctly.""" + expected_color = pygame.Color("white") + mask = pygame.mask.Mask((3, 5), fill=True) + dests = ( + (0, 0), + [0, 0], + Vector2(0, 0), + (0, 0, 100, 100), + pygame.Rect((0, 0), (10, 10)), + ) + + for dest in dests: + to_surface = mask.to_surface(dest=dest) + + assertSurfaceFilled(self, to_surface, expected_color) + + def test_to_surface__invalid_dest_formats(self): + """Ensures to_surface handles invalid dest formats correctly.""" + mask = pygame.mask.Mask((3, 5)) + invalid_dests = ( + (0,), # Incorrect size. + (0, 0, 0), # Incorrect size. + set([0, 1]), # Incorrect type. + {0: 1}, # Incorrect type. + Rect, + ) # Incorrect type. + + for dest in invalid_dests: + with self.assertRaises(TypeError): + mask.to_surface(dest=dest) + + def test_to_surface__negative_sized_dest_rect(self): + """Ensures to_surface correctly handles negative sized dest rects.""" + expected_color = pygame.Color("white") + mask = pygame.mask.Mask((3, 5), fill=True) + dests = ( + pygame.Rect((0, 0), (10, -10)), + pygame.Rect((0, 0), (-10, 10)), + pygame.Rect((0, 0), (-10, -10)), + ) + + for dest in dests: + to_surface = mask.to_surface(dest=dest) + + assertSurfaceFilled(self, to_surface, expected_color) + + def test_to_surface__zero_sized_dest_rect(self): + """Ensures to_surface correctly handles zero sized dest rects.""" + expected_color = pygame.Color("white") + mask = pygame.mask.Mask((3, 5), fill=True) + dests = ( + pygame.Rect((0, 0), (0, 10)), + pygame.Rect((0, 0), (10, 0)), + pygame.Rect((0, 0), (0, 0)), + ) + + for dest in dests: + to_surface = mask.to_surface(dest=dest) + + assertSurfaceFilled(self, to_surface, expected_color) + + @unittest.expectedFailure + def test_to_surface__valid_area_formats(self): + """Ensures to_surface handles valid area formats correctly.""" + size = (3, 5) + surface_color = pygame.Color("red") + expected_color = pygame.Color("white") + surface = pygame.Surface(size) + mask = pygame.mask.Mask(size, fill=True) + area_pos = (0, 0) + area_size = (2, 1) + areas = ( + (area_pos[0], area_pos[1], area_size[0], area_size[1]), + (area_pos, area_size), + (area_pos, list(area_size)), + (list(area_pos), area_size), + (list(area_pos), list(area_size)), + [area_pos[0], area_pos[1], area_size[0], area_size[1]], + [area_pos, area_size], + [area_pos, list(area_size)], + [list(area_pos), area_size], + [list(area_pos), list(area_size)], + pygame.Rect(area_pos, area_size), + ) + + for area in areas: + surface.fill(surface_color) + area_rect = pygame.Rect(area) + + to_surface = mask.to_surface(surface, area=area) + + assertSurfaceFilled(self, to_surface, expected_color, area_rect) + assertSurfaceFilledIgnoreArea(self, to_surface, surface_color, area_rect) + + @unittest.expectedFailure + def test_to_surface__invalid_area_formats(self): + """Ensures to_surface handles invalid area formats correctly.""" + mask = pygame.mask.Mask((3, 5)) + invalid_areas = ( + (0,), # Incorrect size. + (0, 0), # Incorrect size. + (0, 0, 1), # Incorrect size. + ((0, 0), (1,)), # Incorrect size. + ((0,), (1, 1)), # Incorrect size. + set([0, 1, 2, 3]), # Incorrect type. + {0: 1, 2: 3}, # Incorrect type. + Rect, # Incorrect type. + ) + + for area in invalid_areas: + with self.assertRaisesRegex(TypeError, "invalid area argument"): + unused_to_surface = mask.to_surface(area=area) + + @unittest.expectedFailure + def test_to_surface__negative_sized_area_rect(self): + """Ensures to_surface correctly handles negative sized area rects.""" + size = (3, 5) + surface_color = pygame.Color("red") + expected_color = pygame.Color("white") + surface = pygame.Surface(size) + mask = pygame.mask.Mask(size) + mask.set_at((0, 0)) + + # These rects should cause position (0, 0) of the mask to be drawn. + areas = ( + pygame.Rect((0, 1), (1, -1)), + pygame.Rect((1, 0), (-1, 1)), + pygame.Rect((1, 1), (-1, -1)), + ) + + for area in areas: + surface.fill(surface_color) + + to_surface = mask.to_surface(surface, area=area) + + assertSurfaceFilled(self, to_surface, expected_color, area) + assertSurfaceFilledIgnoreArea(self, to_surface, surface_color, area) + + @unittest.expectedFailure + def test_to_surface__zero_sized_area_rect(self): + """Ensures to_surface correctly handles zero sized area rects.""" + size = (3, 5) + expected_color = pygame.Color("red") + surface = pygame.Surface(size) + mask = pygame.mask.Mask(size, fill=True) + + # Zero sized rect areas should cause none of the mask to be drawn. + areas = ( + pygame.Rect((0, 0), (0, 1)), + pygame.Rect((0, 0), (1, 0)), + pygame.Rect((0, 0), (0, 0)), + ) + + for area in areas: + surface.fill(expected_color) + + to_surface = mask.to_surface(surface, area=area) + + assertSurfaceFilled(self, to_surface, expected_color) + + def test_to_surface__default_surface_with_param_combinations(self): + """Ensures to_surface works with a default surface value + and combinations of other parameters. + + This tests many different parameter combinations with full and empty + masks. + """ + expected_ref_count = 2 + expected_flag = SRCALPHA + expected_depth = 32 + size = (5, 3) + dest = (0, 0) + + default_surface_color = (0, 0, 0, 0) + setsurface_color = pygame.Color("yellow") + unsetsurface_color = pygame.Color("blue") + setcolor = pygame.Color("green") + unsetcolor = pygame.Color("cyan") + + setsurface = pygame.Surface(size, expected_flag, expected_depth) + unsetsurface = setsurface.copy() + + setsurface.fill(setsurface_color) + unsetsurface.fill(unsetsurface_color) + + kwargs = { + "setsurface": None, + "unsetsurface": None, + "setcolor": None, + "unsetcolor": None, + "dest": None, + } + + for fill in (True, False): + mask = pygame.mask.Mask(size, fill=fill) + + # Test different combinations of parameters. + for setsurface_param in (setsurface, None): + kwargs["setsurface"] = setsurface_param + + for unsetsurface_param in (unsetsurface, None): + kwargs["unsetsurface"] = unsetsurface_param + + for setcolor_param in (setcolor, None): + kwargs["setcolor"] = setcolor_param + + for unsetcolor_param in (unsetcolor, None): + kwargs["unsetcolor"] = unsetcolor_param + + for dest_param in (dest, None): + if dest_param is None: + kwargs.pop("dest", None) + else: + kwargs["dest"] = dest_param + + if fill: + if setsurface_param is not None: + expected_color = setsurface_color + elif setcolor_param is not None: + expected_color = setcolor + else: + expected_color = default_surface_color + else: + if unsetsurface_param is not None: + expected_color = unsetsurface_color + elif unsetcolor_param is not None: + expected_color = unsetcolor + else: + expected_color = default_surface_color + + to_surface = mask.to_surface(**kwargs) + + self.assertIsInstance(to_surface, pygame.Surface) + if not IS_PYPY: + self.assertEqual( + sys.getrefcount(to_surface), expected_ref_count + ) + self.assertTrue(to_surface.get_flags() & expected_flag) + self.assertEqual( + to_surface.get_bitsize(), expected_depth + ) + self.assertEqual(to_surface.get_size(), size) + assertSurfaceFilled(self, to_surface, expected_color) + + def test_to_surface__surface_with_param_combinations(self): + """Ensures to_surface works with a surface value + and combinations of other parameters. + + This tests many different parameter combinations with full and empty + masks. + """ + expected_ref_count = 4 + expected_flag = SRCALPHA + expected_depth = 32 + size = (5, 3) + dest = (0, 0) + + surface_color = pygame.Color("red") + setsurface_color = pygame.Color("yellow") + unsetsurface_color = pygame.Color("blue") + setcolor = pygame.Color("green") + unsetcolor = pygame.Color("cyan") + + surface = pygame.Surface(size, expected_flag, expected_depth) + setsurface = surface.copy() + unsetsurface = surface.copy() + + setsurface.fill(setsurface_color) + unsetsurface.fill(unsetsurface_color) + + kwargs = { + "surface": surface, + "setsurface": None, + "unsetsurface": None, + "setcolor": None, + "unsetcolor": None, + "dest": None, + } + + for fill in (True, False): + mask = pygame.mask.Mask(size, fill=fill) + + # Test different combinations of parameters. + for setsurface_param in (setsurface, None): + kwargs["setsurface"] = setsurface_param + + for unsetsurface_param in (unsetsurface, None): + kwargs["unsetsurface"] = unsetsurface_param + + for setcolor_param in (setcolor, None): + kwargs["setcolor"] = setcolor_param + + for unsetcolor_param in (unsetcolor, None): + kwargs["unsetcolor"] = unsetcolor_param + surface.fill(surface_color) # Clear for each test. + + for dest_param in (dest, None): + if dest_param is None: + kwargs.pop("dest", None) + else: + kwargs["dest"] = dest_param + + if fill: + if setsurface_param is not None: + expected_color = setsurface_color + elif setcolor_param is not None: + expected_color = setcolor + else: + expected_color = surface_color + else: + if unsetsurface_param is not None: + expected_color = unsetsurface_color + elif unsetcolor_param is not None: + expected_color = unsetcolor + else: + expected_color = surface_color + + to_surface = mask.to_surface(**kwargs) + + self.assertIs(to_surface, surface) + if not IS_PYPY: + self.assertEqual( + sys.getrefcount(to_surface), expected_ref_count + ) + self.assertTrue(to_surface.get_flags() & expected_flag) + self.assertEqual( + to_surface.get_bitsize(), expected_depth + ) + self.assertEqual(to_surface.get_size(), size) + assertSurfaceFilled(self, to_surface, expected_color) + + def test_to_surface__set_and_unset_bits(self): + """Ensures that to_surface works correctly with with set/unset bits + when using the defaults for setcolor and unsetcolor. + """ + default_setcolor = pygame.Color("white") + default_unsetcolor = pygame.Color("black") + width, height = size = (10, 20) + mask = pygame.mask.Mask(size) + mask_rect = mask.get_rect() + + surface = pygame.Surface(size) + surface_color = pygame.Color("red") + + # Create a checkerboard pattern of set/unset bits. + for pos in ((x, y) for x in range(width) for y in range(x & 1, height, 2)): + mask.set_at(pos) + + # Test different dest values. + for dest in self.ORIGIN_OFFSETS: + mask_rect.topleft = dest + surface.fill(surface_color) + + to_surface = mask.to_surface(surface, dest=dest) + + to_surface.lock() # Lock for possible speed up. + for pos in ((x, y) for x in range(width) for y in range(height)): + mask_pos = (pos[0] - dest[0], pos[1] - dest[1]) + if not mask_rect.collidepoint(pos): + expected_color = surface_color + elif mask.get_at(mask_pos): + expected_color = default_setcolor + else: + expected_color = default_unsetcolor + + self.assertEqual(to_surface.get_at(pos), expected_color, (dest, pos)) + to_surface.unlock() + + def test_to_surface__set_and_unset_bits_with_setsurface_unsetsurface(self): + """Ensures that to_surface works correctly with with set/unset bits + when using setsurface and unsetsurface. + """ + width, height = size = (10, 20) + mask = pygame.mask.Mask(size) + mask_rect = mask.get_rect() + + surface = pygame.Surface(size) + surface_color = pygame.Color("red") + + setsurface = surface.copy() + setsurface_color = pygame.Color("green") + setsurface.fill(setsurface_color) + + unsetsurface = surface.copy() + unsetsurface_color = pygame.Color("blue") + unsetsurface.fill(unsetsurface_color) + + # Create a checkerboard pattern of set/unset bits. + for pos in ((x, y) for x in range(width) for y in range(x & 1, height, 2)): + mask.set_at(pos) + + # Test different dest values. + for dest in self.ORIGIN_OFFSETS: + mask_rect.topleft = dest + + # Tests the color parameters set to None and also as their + # default values. Should have no effect as they are not being + # used, but this exercises different to_surface() code. + for disable_color_params in (True, False): + surface.fill(surface_color) # Clear for each test. + + if disable_color_params: + to_surface = mask.to_surface( + surface, + dest=dest, + setsurface=setsurface, + unsetsurface=unsetsurface, + setcolor=None, + unsetcolor=None, + ) + else: + to_surface = mask.to_surface( + surface, + dest=dest, + setsurface=setsurface, + unsetsurface=unsetsurface, + ) + + to_surface.lock() # Lock for possible speed up. + + for pos in ((x, y) for x in range(width) for y in range(height)): + mask_pos = (pos[0] - dest[0], pos[1] - dest[1]) + + if not mask_rect.collidepoint(pos): + expected_color = surface_color + elif mask.get_at(mask_pos): + expected_color = setsurface_color + else: + expected_color = unsetsurface_color + + self.assertEqual(to_surface.get_at(pos), expected_color) + to_surface.unlock() + + def test_to_surface__surface_narrower_than_mask(self): + """Ensures that surfaces narrower than the mask work correctly. + + For this test the surface's width is less than the mask's width. + """ + default_setcolor = pygame.Color("white") + default_unsetcolor = pygame.Color("black") + mask_size = (10, 20) + narrow_size = (6, 20) + + surface = pygame.Surface(narrow_size) + surface_color = pygame.Color("red") + + for fill in (True, False): + mask = pygame.mask.Mask(mask_size, fill=fill) + surface.fill(surface_color) # Clear for each test. + expected_color = default_setcolor if fill else default_unsetcolor + + to_surface = mask.to_surface(surface) + + self.assertIs(to_surface, surface) + self.assertEqual(to_surface.get_size(), narrow_size) + assertSurfaceFilled(self, to_surface, expected_color) + + def test_to_surface__setsurface_narrower_than_mask(self): + """Ensures that setsurfaces narrower than the mask work correctly. + + For this test the setsurface's width is less than the mask's width. + """ + default_setcolor = pygame.Color("white") + default_unsetcolor = pygame.Color("black") + mask_size = (10, 20) + narrow_size = (6, 20) + + setsurface = pygame.Surface(narrow_size, SRCALPHA, 32) + setsurface_color = pygame.Color("red") + setsurface.fill(setsurface_color) + setsurface_rect = setsurface.get_rect() + + for fill in (True, False): + mask = pygame.mask.Mask(mask_size, fill=fill) + + to_surface = mask.to_surface(setsurface=setsurface) + + self.assertIsInstance(to_surface, pygame.Surface) + self.assertEqual(to_surface.get_size(), mask_size) + + # Different checks depending on if the mask was filled or not. + if fill: + assertSurfaceFilled(self, to_surface, setsurface_color, setsurface_rect) + assertSurfaceFilledIgnoreArea( + self, to_surface, default_setcolor, setsurface_rect + ) + else: + assertSurfaceFilled(self, to_surface, default_unsetcolor) + + def test_to_surface__unsetsurface_narrower_than_mask(self): + """Ensures that unsetsurfaces narrower than the mask work correctly. + + For this test the unsetsurface's width is less than the mask's width. + """ + default_setcolor = pygame.Color("white") + default_unsetcolor = pygame.Color("black") + mask_size = (10, 20) + narrow_size = (6, 20) + + unsetsurface = pygame.Surface(narrow_size, SRCALPHA, 32) + unsetsurface_color = pygame.Color("red") + unsetsurface.fill(unsetsurface_color) + unsetsurface_rect = unsetsurface.get_rect() + + for fill in (True, False): + mask = pygame.mask.Mask(mask_size, fill=fill) + + to_surface = mask.to_surface(unsetsurface=unsetsurface) + + self.assertIsInstance(to_surface, pygame.Surface) + self.assertEqual(to_surface.get_size(), mask_size) + + # Different checks depending on if the mask was filled or not. + if fill: + assertSurfaceFilled(self, to_surface, default_setcolor) + else: + assertSurfaceFilled( + self, to_surface, unsetsurface_color, unsetsurface_rect + ) + assertSurfaceFilledIgnoreArea( + self, to_surface, default_unsetcolor, unsetsurface_rect + ) + + def test_to_surface__setsurface_narrower_than_mask_and_colors_none(self): + """Ensures that setsurfaces narrower than the mask work correctly + when setcolor and unsetcolor are set to None. + + For this test the setsurface's width is less than the mask's width. + """ + default_surface_color = (0, 0, 0, 0) + mask_size = (10, 20) + narrow_size = (6, 20) + + setsurface = pygame.Surface(narrow_size, SRCALPHA, 32) + setsurface_color = pygame.Color("red") + setsurface.fill(setsurface_color) + setsurface_rect = setsurface.get_rect() + + for fill in (True, False): + mask = pygame.mask.Mask(mask_size, fill=fill) + + to_surface = mask.to_surface( + setsurface=setsurface, setcolor=None, unsetcolor=None + ) + + self.assertIsInstance(to_surface, pygame.Surface) + self.assertEqual(to_surface.get_size(), mask_size) + + # Different checks depending on if the mask was filled or not. + if fill: + assertSurfaceFilled(self, to_surface, setsurface_color, setsurface_rect) + assertSurfaceFilledIgnoreArea( + self, to_surface, default_surface_color, setsurface_rect + ) + else: + assertSurfaceFilled(self, to_surface, default_surface_color) + + def test_to_surface__unsetsurface_narrower_than_mask_and_colors_none(self): + """Ensures that unsetsurfaces narrower than the mask work correctly + when setcolor and unsetcolor are set to None. + + For this test the unsetsurface's width is less than the mask's width. + """ + default_surface_color = (0, 0, 0, 0) + mask_size = (10, 20) + narrow_size = (6, 20) + + unsetsurface = pygame.Surface(narrow_size, SRCALPHA, 32) + unsetsurface_color = pygame.Color("red") + unsetsurface.fill(unsetsurface_color) + unsetsurface_rect = unsetsurface.get_rect() + + for fill in (True, False): + mask = pygame.mask.Mask(mask_size, fill=fill) + + to_surface = mask.to_surface( + unsetsurface=unsetsurface, setcolor=None, unsetcolor=None + ) + + self.assertIsInstance(to_surface, pygame.Surface) + self.assertEqual(to_surface.get_size(), mask_size) + + # Different checks depending on if the mask was filled or not. + if fill: + assertSurfaceFilled(self, to_surface, default_surface_color) + else: + assertSurfaceFilled( + self, to_surface, unsetsurface_color, unsetsurface_rect + ) + assertSurfaceFilledIgnoreArea( + self, to_surface, default_surface_color, unsetsurface_rect + ) + + def test_to_surface__surface_wider_than_mask(self): + """Ensures that surfaces wider than the mask work correctly. + + For this test the surface's width is greater than the mask's width. + """ + default_setcolor = pygame.Color("white") + default_unsetcolor = pygame.Color("black") + mask_size = (6, 15) + wide_size = (11, 15) + + surface = pygame.Surface(wide_size) + surface_color = pygame.Color("red") + + for fill in (True, False): + mask = pygame.mask.Mask(mask_size, fill=fill) + mask_rect = mask.get_rect() + surface.fill(surface_color) # Clear for each test. + expected_color = default_setcolor if fill else default_unsetcolor + + to_surface = mask.to_surface(surface) + + self.assertIs(to_surface, surface) + self.assertEqual(to_surface.get_size(), wide_size) + assertSurfaceFilled(self, to_surface, expected_color, mask_rect) + assertSurfaceFilledIgnoreArea(self, to_surface, surface_color, mask_rect) + + def test_to_surface__setsurface_wider_than_mask(self): + """Ensures that setsurfaces wider than the mask work correctly. + + For this test the setsurface's width is greater than the mask's width. + """ + default_unsetcolor = pygame.Color("black") + mask_size = (6, 15) + wide_size = (11, 15) + + setsurface = pygame.Surface(wide_size, SRCALPHA, 32) + setsurface_color = pygame.Color("red") + setsurface.fill(setsurface_color) + + for fill in (True, False): + mask = pygame.mask.Mask(mask_size, fill=fill) + expected_color = setsurface_color if fill else default_unsetcolor + + to_surface = mask.to_surface(setsurface=setsurface) + + self.assertIsInstance(to_surface, pygame.Surface) + self.assertEqual(to_surface.get_size(), mask_size) + assertSurfaceFilled(self, to_surface, expected_color) + + def test_to_surface__unsetsurface_wider_than_mask(self): + """Ensures that unsetsurfaces wider than the mask work correctly. + + For this test the unsetsurface's width is greater than the mask's + width. + """ + default_setcolor = pygame.Color("white") + mask_size = (6, 15) + wide_size = (11, 15) + + unsetsurface = pygame.Surface(wide_size, SRCALPHA, 32) + unsetsurface_color = pygame.Color("red") + unsetsurface.fill(unsetsurface_color) + + for fill in (True, False): + mask = pygame.mask.Mask(mask_size, fill=fill) + expected_color = default_setcolor if fill else unsetsurface_color + + to_surface = mask.to_surface(unsetsurface=unsetsurface) + + self.assertIsInstance(to_surface, pygame.Surface) + self.assertEqual(to_surface.get_size(), mask_size) + assertSurfaceFilled(self, to_surface, expected_color) + + def test_to_surface__surface_shorter_than_mask(self): + """Ensures that surfaces shorter than the mask work correctly. + + For this test the surface's height is less than the mask's height. + """ + default_setcolor = pygame.Color("white") + default_unsetcolor = pygame.Color("black") + mask_size = (10, 11) + short_size = (10, 6) + + surface = pygame.Surface(short_size) + surface_color = pygame.Color("red") + + for fill in (True, False): + mask = pygame.mask.Mask(mask_size, fill=fill) + surface.fill(surface_color) # Clear for each test. + expected_color = default_setcolor if fill else default_unsetcolor + + to_surface = mask.to_surface(surface) + + self.assertIs(to_surface, surface) + self.assertEqual(to_surface.get_size(), short_size) + assertSurfaceFilled(self, to_surface, expected_color) + + def test_to_surface__setsurface_shorter_than_mask(self): + """Ensures that setsurfaces shorter than the mask work correctly. + + For this test the setsurface's height is less than the mask's height. + """ + default_setcolor = pygame.Color("white") + default_unsetcolor = pygame.Color("black") + mask_size = (10, 11) + short_size = (10, 6) + + setsurface = pygame.Surface(short_size, SRCALPHA, 32) + setsurface_color = pygame.Color("red") + setsurface.fill(setsurface_color) + setsurface_rect = setsurface.get_rect() + + for fill in (True, False): + mask = pygame.mask.Mask(mask_size, fill=fill) + + to_surface = mask.to_surface(setsurface=setsurface) + + self.assertIsInstance(to_surface, pygame.Surface) + self.assertEqual(to_surface.get_size(), mask_size) + + # Different checks depending on if the mask was filled or not. + if fill: + assertSurfaceFilled(self, to_surface, setsurface_color, setsurface_rect) + assertSurfaceFilledIgnoreArea( + self, to_surface, default_setcolor, setsurface_rect + ) + else: + assertSurfaceFilled(self, to_surface, default_unsetcolor) + + def test_to_surface__unsetsurface_shorter_than_mask(self): + """Ensures that unsetsurfaces shorter than the mask work correctly. + + For this test the unsetsurface's height is less than the mask's height. + """ + default_setcolor = pygame.Color("white") + default_unsetcolor = pygame.Color("black") + mask_size = (10, 11) + short_size = (10, 6) + + unsetsurface = pygame.Surface(short_size, SRCALPHA, 32) + unsetsurface_color = pygame.Color("red") + unsetsurface.fill(unsetsurface_color) + unsetsurface_rect = unsetsurface.get_rect() + + for fill in (True, False): + mask = pygame.mask.Mask(mask_size, fill=fill) + + to_surface = mask.to_surface(unsetsurface=unsetsurface) + + self.assertIsInstance(to_surface, pygame.Surface) + self.assertEqual(to_surface.get_size(), mask_size) + + # Different checks depending on if the mask was filled or not. + if fill: + assertSurfaceFilled(self, to_surface, default_setcolor) + else: + assertSurfaceFilled( + self, to_surface, unsetsurface_color, unsetsurface_rect + ) + assertSurfaceFilledIgnoreArea( + self, to_surface, default_unsetcolor, unsetsurface_rect + ) + + def test_to_surface__setsurface_shorter_than_mask_and_colors_none(self): + """Ensures that setsurfaces shorter than the mask work correctly + when setcolor and unsetcolor are set to None. + + For this test the setsurface's height is less than the mask's height. + """ + default_surface_color = (0, 0, 0, 0) + mask_size = (10, 11) + short_size = (10, 6) + + setsurface = pygame.Surface(short_size, SRCALPHA, 32) + setsurface_color = pygame.Color("red") + setsurface.fill(setsurface_color) + setsurface_rect = setsurface.get_rect() + + for fill in (True, False): + mask = pygame.mask.Mask(mask_size, fill=fill) + + to_surface = mask.to_surface( + setsurface=setsurface, setcolor=None, unsetcolor=None + ) + + self.assertIsInstance(to_surface, pygame.Surface) + self.assertEqual(to_surface.get_size(), mask_size) + + # Different checks depending on if the mask was filled or not. + if fill: + assertSurfaceFilled(self, to_surface, setsurface_color, setsurface_rect) + assertSurfaceFilledIgnoreArea( + self, to_surface, default_surface_color, setsurface_rect + ) + else: + assertSurfaceFilled(self, to_surface, default_surface_color) + + def test_to_surface__unsetsurface_shorter_than_mask_and_colors_none(self): + """Ensures that unsetsurfaces shorter than the mask work correctly + when setcolor and unsetcolor are set to None. + + For this test the unsetsurface's height is less than the mask's height. + """ + default_surface_color = (0, 0, 0, 0) + mask_size = (10, 11) + short_size = (10, 6) + + unsetsurface = pygame.Surface(short_size, SRCALPHA, 32) + unsetsurface_color = pygame.Color("red") + unsetsurface.fill(unsetsurface_color) + unsetsurface_rect = unsetsurface.get_rect() + + for fill in (True, False): + mask = pygame.mask.Mask(mask_size, fill=fill) + + to_surface = mask.to_surface( + unsetsurface=unsetsurface, setcolor=None, unsetcolor=None + ) + + self.assertIsInstance(to_surface, pygame.Surface) + self.assertEqual(to_surface.get_size(), mask_size) + + # Different checks depending on if the mask was filled or not. + if fill: + assertSurfaceFilled(self, to_surface, default_surface_color) + else: + assertSurfaceFilled( + self, to_surface, unsetsurface_color, unsetsurface_rect + ) + assertSurfaceFilledIgnoreArea( + self, to_surface, default_surface_color, unsetsurface_rect + ) + + def test_to_surface__surface_taller_than_mask(self): + """Ensures that surfaces taller than the mask work correctly. + + For this test the surface's height is greater than the mask's height. + """ + default_setcolor = pygame.Color("white") + default_unsetcolor = pygame.Color("black") + mask_size = (10, 6) + tall_size = (10, 11) + + surface = pygame.Surface(tall_size) + surface_color = pygame.Color("red") + + for fill in (True, False): + mask = pygame.mask.Mask(mask_size, fill=fill) + mask_rect = mask.get_rect() + surface.fill(surface_color) # Clear for each test. + expected_color = default_setcolor if fill else default_unsetcolor + + to_surface = mask.to_surface(surface) + + self.assertIs(to_surface, surface) + self.assertEqual(to_surface.get_size(), tall_size) + assertSurfaceFilled(self, to_surface, expected_color, mask_rect) + assertSurfaceFilledIgnoreArea(self, to_surface, surface_color, mask_rect) + + def test_to_surface__setsurface_taller_than_mask(self): + """Ensures that setsurfaces taller than the mask work correctly. + + For this test the setsurface's height is greater than the mask's + height. + """ + default_unsetcolor = pygame.Color("black") + mask_size = (10, 6) + tall_size = (10, 11) + + setsurface = pygame.Surface(tall_size, SRCALPHA, 32) + setsurface_color = pygame.Color("red") + setsurface.fill(setsurface_color) + + for fill in (True, False): + mask = pygame.mask.Mask(mask_size, fill=fill) + expected_color = setsurface_color if fill else default_unsetcolor + + to_surface = mask.to_surface(setsurface=setsurface) + + self.assertIsInstance(to_surface, pygame.Surface) + self.assertEqual(to_surface.get_size(), mask_size) + assertSurfaceFilled(self, to_surface, expected_color) + + def test_to_surface__unsetsurface_taller_than_mask(self): + """Ensures that unsetsurfaces taller than the mask work correctly. + + For this test the unsetsurface's height is greater than the mask's + height. + """ + default_setcolor = pygame.Color("white") + mask_size = (10, 6) + tall_size = (10, 11) + + unsetsurface = pygame.Surface(tall_size, SRCALPHA, 32) + unsetsurface_color = pygame.Color("red") + unsetsurface.fill(unsetsurface_color) + + for fill in (True, False): + mask = pygame.mask.Mask(mask_size, fill=fill) + expected_color = default_setcolor if fill else unsetsurface_color + + to_surface = mask.to_surface(unsetsurface=unsetsurface) + + self.assertIsInstance(to_surface, pygame.Surface) + self.assertEqual(to_surface.get_size(), mask_size) + assertSurfaceFilled(self, to_surface, expected_color) + + def test_to_surface__surface_wider_and_taller_than_mask(self): + """Ensures that surfaces wider and taller than the mask work correctly. + + For this test the surface's width is greater than the mask's width and + the surface's height is greater than the mask's height. + """ + default_setcolor = pygame.Color("white") + default_unsetcolor = pygame.Color("black") + mask_size = (6, 8) + wide_tall_size = (11, 15) + + surface = pygame.Surface(wide_tall_size) + surface_color = pygame.Color("red") + + for fill in (True, False): + mask = pygame.mask.Mask(mask_size, fill=fill) + mask_rect = mask.get_rect() + surface.fill(surface_color) # Clear for each test. + expected_color = default_setcolor if fill else default_unsetcolor + + to_surface = mask.to_surface(surface) + + self.assertIs(to_surface, surface) + self.assertEqual(to_surface.get_size(), wide_tall_size) + assertSurfaceFilled(self, to_surface, expected_color, mask_rect) + assertSurfaceFilledIgnoreArea(self, to_surface, surface_color, mask_rect) + + def test_to_surface__setsurface_wider_and_taller_than_mask(self): + """Ensures that setsurfaces wider and taller than the mask work + correctly. + + For this test the setsurface's width is greater than the mask's width + and the setsurface's height is greater than the mask's height. + """ + default_unsetcolor = pygame.Color("black") + mask_size = (6, 8) + wide_tall_size = (11, 15) + + setsurface = pygame.Surface(wide_tall_size, SRCALPHA, 32) + setsurface_color = pygame.Color("red") + setsurface.fill(setsurface_color) + + for fill in (True, False): + mask = pygame.mask.Mask(mask_size, fill=fill) + expected_color = setsurface_color if fill else default_unsetcolor + + to_surface = mask.to_surface(setsurface=setsurface) + + self.assertIsInstance(to_surface, pygame.Surface) + self.assertEqual(to_surface.get_size(), mask_size) + assertSurfaceFilled(self, to_surface, expected_color) + + def test_to_surface__unsetsurface_wider_and_taller_than_mask(self): + """Ensures that unsetsurfaces wider and taller than the mask work + correctly. + + For this test the unsetsurface's width is greater than the mask's width + and the unsetsurface's height is greater than the mask's height. + """ + default_setcolor = pygame.Color("white") + mask_size = (6, 8) + wide_tall_size = (11, 15) + + unsetsurface = pygame.Surface(wide_tall_size, SRCALPHA, 32) + unsetsurface_color = pygame.Color("red") + unsetsurface.fill(unsetsurface_color) + + for fill in (True, False): + mask = pygame.mask.Mask(mask_size, fill=fill) + expected_color = default_setcolor if fill else unsetsurface_color + + to_surface = mask.to_surface(unsetsurface=unsetsurface) + + self.assertIsInstance(to_surface, pygame.Surface) + self.assertEqual(to_surface.get_size(), mask_size) + assertSurfaceFilled(self, to_surface, expected_color) + + def test_to_surface__surface_wider_and_shorter_than_mask(self): + """Ensures that surfaces wider and shorter than the mask work + correctly. + + For this test the surface's width is greater than the mask's width and + the surface's height is less than the mask's height. + """ + default_setcolor = pygame.Color("white") + default_unsetcolor = pygame.Color("black") + mask_size = (7, 11) + wide_short_size = (13, 6) + + surface = pygame.Surface(wide_short_size) + surface_color = pygame.Color("red") + + for fill in (True, False): + mask = pygame.mask.Mask(mask_size, fill=fill) + mask_rect = mask.get_rect() + surface.fill(surface_color) # Clear for each test. + expected_color = default_setcolor if fill else default_unsetcolor + + to_surface = mask.to_surface(surface) + + self.assertIs(to_surface, surface) + self.assertEqual(to_surface.get_size(), wide_short_size) + assertSurfaceFilled(self, to_surface, expected_color, mask_rect) + assertSurfaceFilledIgnoreArea(self, to_surface, surface_color, mask_rect) + + def test_to_surface__setsurface_wider_and_shorter_than_mask(self): + """Ensures that setsurfaces wider and shorter than the mask work + correctly. + + For this test the setsurface's width is greater than the mask's width + and the setsurface's height is less than the mask's height. + """ + default_setcolor = pygame.Color("white") + default_unsetcolor = pygame.Color("black") + mask_size = (7, 11) + wide_short_size = (10, 6) + + setsurface = pygame.Surface(wide_short_size, SRCALPHA, 32) + setsurface_color = pygame.Color("red") + setsurface.fill(setsurface_color) + setsurface_rect = setsurface.get_rect() + + for fill in (True, False): + mask = pygame.mask.Mask(mask_size, fill=fill) + + to_surface = mask.to_surface(setsurface=setsurface) + + self.assertIsInstance(to_surface, pygame.Surface) + self.assertEqual(to_surface.get_size(), mask_size) + + # Different checks depending on if the mask was filled or not. + if fill: + assertSurfaceFilled(self, to_surface, setsurface_color, setsurface_rect) + assertSurfaceFilledIgnoreArea( + self, to_surface, default_setcolor, setsurface_rect + ) + else: + assertSurfaceFilled(self, to_surface, default_unsetcolor) + + def test_to_surface__unsetsurface_wider_and_shorter_than_mask(self): + """Ensures that unsetsurfaces wider and shorter than the mask work + correctly. + + For this test the unsetsurface's width is greater than the mask's width + and the unsetsurface's height is less than the mask's height. + """ + default_setcolor = pygame.Color("white") + default_unsetcolor = pygame.Color("black") + mask_size = (7, 11) + wide_short_size = (10, 6) + + unsetsurface = pygame.Surface(wide_short_size, SRCALPHA, 32) + unsetsurface_color = pygame.Color("red") + unsetsurface.fill(unsetsurface_color) + unsetsurface_rect = unsetsurface.get_rect() + + for fill in (True, False): + mask = pygame.mask.Mask(mask_size, fill=fill) + + to_surface = mask.to_surface(unsetsurface=unsetsurface) + + self.assertIsInstance(to_surface, pygame.Surface) + self.assertEqual(to_surface.get_size(), mask_size) + + # Different checks depending on if the mask was filled or not. + if fill: + assertSurfaceFilled(self, to_surface, default_setcolor) + else: + assertSurfaceFilled( + self, to_surface, unsetsurface_color, unsetsurface_rect + ) + assertSurfaceFilledIgnoreArea( + self, to_surface, default_unsetcolor, unsetsurface_rect + ) + + def test_to_surface__surface_narrower_and_taller_than_mask(self): + """Ensures that surfaces narrower and taller than the mask work + correctly. + + For this test the surface's width is less than the mask's width and + the surface's height is greater than the mask's height. + """ + default_setcolor = pygame.Color("white") + default_unsetcolor = pygame.Color("black") + mask_size = (10, 8) + narrow_tall_size = (6, 15) + + surface = pygame.Surface(narrow_tall_size) + surface_color = pygame.Color("red") + + for fill in (True, False): + mask = pygame.mask.Mask(mask_size, fill=fill) + mask_rect = mask.get_rect() + surface.fill(surface_color) # Clear for each test. + expected_color = default_setcolor if fill else default_unsetcolor + + to_surface = mask.to_surface(surface) + + self.assertIs(to_surface, surface) + self.assertEqual(to_surface.get_size(), narrow_tall_size) + assertSurfaceFilled(self, to_surface, expected_color, mask_rect) + assertSurfaceFilledIgnoreArea(self, to_surface, surface_color, mask_rect) + + def test_to_surface__setsurface_narrower_and_taller_than_mask(self): + """Ensures that setsurfaces narrower and taller than the mask work + correctly. + + For this test the setsurface's width is less than the mask's width + and the setsurface's height is greater than the mask's height. + """ + default_setcolor = pygame.Color("white") + default_unsetcolor = pygame.Color("black") + mask_size = (10, 8) + narrow_tall_size = (6, 15) + + setsurface = pygame.Surface(narrow_tall_size, SRCALPHA, 32) + setsurface_color = pygame.Color("red") + setsurface.fill(setsurface_color) + setsurface_rect = setsurface.get_rect() + + for fill in (True, False): + mask = pygame.mask.Mask(mask_size, fill=fill) + + to_surface = mask.to_surface(setsurface=setsurface) + + self.assertIsInstance(to_surface, pygame.Surface) + self.assertEqual(to_surface.get_size(), mask_size) + + # Different checks depending on if the mask was filled or not. + if fill: + assertSurfaceFilled(self, to_surface, setsurface_color, setsurface_rect) + assertSurfaceFilledIgnoreArea( + self, to_surface, default_setcolor, setsurface_rect + ) + else: + assertSurfaceFilled(self, to_surface, default_unsetcolor) + + def test_to_surface__unsetsurface_narrower_and_taller_than_mask(self): + """Ensures that unsetsurfaces narrower and taller than the mask work + correctly. + + For this test the unsetsurface's width is less than the mask's width + and the unsetsurface's height is greater than the mask's height. + """ + default_setcolor = pygame.Color("white") + default_unsetcolor = pygame.Color("black") + mask_size = (10, 8) + narrow_tall_size = (6, 15) + + unsetsurface = pygame.Surface(narrow_tall_size, SRCALPHA, 32) + unsetsurface_color = pygame.Color("red") + unsetsurface.fill(unsetsurface_color) + unsetsurface_rect = unsetsurface.get_rect() + + for fill in (True, False): + mask = pygame.mask.Mask(mask_size, fill=fill) + + to_surface = mask.to_surface(unsetsurface=unsetsurface) + + self.assertIsInstance(to_surface, pygame.Surface) + self.assertEqual(to_surface.get_size(), mask_size) + + # Different checks depending on if the mask was filled or not. + if fill: + assertSurfaceFilled(self, to_surface, default_setcolor) + else: + assertSurfaceFilled( + self, to_surface, unsetsurface_color, unsetsurface_rect + ) + assertSurfaceFilledIgnoreArea( + self, to_surface, default_unsetcolor, unsetsurface_rect + ) + + def test_to_surface__surface_narrower_and_shorter_than_mask(self): + """Ensures that surfaces narrower and shorter than the mask work + correctly. + + For this test the surface's width is less than the mask's width and + the surface's height is less than the mask's height. + """ + default_setcolor = pygame.Color("white") + default_unsetcolor = pygame.Color("black") + mask_size = (10, 18) + narrow_short_size = (6, 15) + + surface = pygame.Surface(narrow_short_size) + surface_color = pygame.Color("red") + + for fill in (True, False): + mask = pygame.mask.Mask(mask_size, fill=fill) + mask_rect = mask.get_rect() + surface.fill(surface_color) # Clear for each test. + expected_color = default_setcolor if fill else default_unsetcolor + + to_surface = mask.to_surface(surface) + + self.assertIs(to_surface, surface) + self.assertEqual(to_surface.get_size(), narrow_short_size) + assertSurfaceFilled(self, to_surface, expected_color, mask_rect) + assertSurfaceFilledIgnoreArea(self, to_surface, surface_color, mask_rect) + + def test_to_surface__setsurface_narrower_and_shorter_than_mask(self): + """Ensures that setsurfaces narrower and shorter than the mask work + correctly. + + For this test the setsurface's width is less than the mask's width + and the setsurface's height is less than the mask's height. + """ + default_setcolor = pygame.Color("white") + default_unsetcolor = pygame.Color("black") + mask_size = (10, 18) + narrow_short_size = (6, 15) + + setsurface = pygame.Surface(narrow_short_size, SRCALPHA, 32) + setsurface_color = pygame.Color("red") + setsurface.fill(setsurface_color) + setsurface_rect = setsurface.get_rect() + + for fill in (True, False): + mask = pygame.mask.Mask(mask_size, fill=fill) + + to_surface = mask.to_surface(setsurface=setsurface) + + self.assertIsInstance(to_surface, pygame.Surface) + self.assertEqual(to_surface.get_size(), mask_size) + + # Different checks depending on if the mask was filled or not. + if fill: + assertSurfaceFilled(self, to_surface, setsurface_color, setsurface_rect) + assertSurfaceFilledIgnoreArea( + self, to_surface, default_setcolor, setsurface_rect + ) + else: + assertSurfaceFilled(self, to_surface, default_unsetcolor) + + def test_to_surface__unsetsurface_narrower_and_shorter_than_mask(self): + """Ensures that unsetsurfaces narrower and shorter than the mask work + correctly. + + For this test the unsetsurface's width is less than the mask's width + and the unsetsurface's height is less than the mask's height. + """ + default_setcolor = pygame.Color("white") + default_unsetcolor = pygame.Color("black") + mask_size = (10, 18) + narrow_short_size = (6, 15) + + unsetsurface = pygame.Surface(narrow_short_size, SRCALPHA, 32) + unsetsurface_color = pygame.Color("red") + unsetsurface.fill(unsetsurface_color) + unsetsurface_rect = unsetsurface.get_rect() + + for fill in (True, False): + mask = pygame.mask.Mask(mask_size, fill=fill) + + to_surface = mask.to_surface(unsetsurface=unsetsurface) + + self.assertIsInstance(to_surface, pygame.Surface) + self.assertEqual(to_surface.get_size(), mask_size) + + # Different checks depending on if the mask was filled or not. + if fill: + assertSurfaceFilled(self, to_surface, default_setcolor) + else: + assertSurfaceFilled( + self, to_surface, unsetsurface_color, unsetsurface_rect + ) + assertSurfaceFilledIgnoreArea( + self, to_surface, default_unsetcolor, unsetsurface_rect + ) + + @unittest.skipIf(IS_PYPY, "Segfaults on pypy") + def test_to_surface__all_surfaces_different_sizes_than_mask(self): + """Ensures that all the surface parameters can be of different sizes.""" + default_setcolor = pygame.Color("white") + default_unsetcolor = pygame.Color("black") + surface_color = pygame.Color("red") + setsurface_color = pygame.Color("green") + unsetsurface_color = pygame.Color("blue") + + mask_size = (10, 15) + surface_size = (11, 14) + setsurface_size = (9, 8) + unsetsurface_size = (12, 16) + + surface = pygame.Surface(surface_size) + setsurface = pygame.Surface(setsurface_size) + unsetsurface = pygame.Surface(unsetsurface_size) + + surface.fill(surface_color) + setsurface.fill(setsurface_color) + unsetsurface.fill(unsetsurface_color) + + surface_rect = surface.get_rect() + setsurface_rect = setsurface.get_rect() + unsetsurface_rect = unsetsurface.get_rect() + + # Create a mask that is filled except for a rect in the center. + mask = pygame.mask.Mask(mask_size, fill=True) + mask_rect = mask.get_rect() + unfilled_rect = pygame.Rect((0, 0), (4, 5)) + unfilled_rect.center = mask_rect.center + + for pos in ( + (x, y) + for x in range(unfilled_rect.x, unfilled_rect.w) + for y in range(unfilled_rect.y, unfilled_rect.h) + ): + mask.set_at(pos, 0) + + to_surface = mask.to_surface(surface, setsurface, unsetsurface) + + self.assertIs(to_surface, surface) + self.assertEqual(to_surface.get_size(), surface_size) + + # Check each surface pixel for the correct color. + to_surface.lock() # Lock for possible speed up. + + for pos in ( + (x, y) for x in range(surface_rect.w) for y in range(surface_rect.h) + ): + if not mask_rect.collidepoint(pos): + expected_color = surface_color + elif mask.get_at(pos): + # Checking set bit colors. + if setsurface_rect.collidepoint(pos): + expected_color = setsurface_color + else: + expected_color = default_setcolor + else: + # Checking unset bit colors. + if unsetsurface_rect.collidepoint(pos): + expected_color = unsetsurface_color + else: + expected_color = default_unsetcolor + + self.assertEqual(to_surface.get_at(pos), expected_color) + + to_surface.unlock() + + def test_to_surface__dest_locations(self): + """Ensures dest values can be different locations on/off the surface.""" + SIDE = 7 + surface = pygame.Surface((SIDE, SIDE)) + surface_rect = surface.get_rect() + dest_rect = surface_rect.copy() + + surface_color = pygame.Color("red") + default_setcolor = pygame.Color("white") + default_unsetcolor = pygame.Color("black") + + directions = ( + ((s, 0) for s in range(-SIDE, SIDE + 1)), # left to right + ((0, s) for s in range(-SIDE, SIDE + 1)), # top to bottom + ((s, s) for s in range(-SIDE, SIDE + 1)), # topleft to bottomright diag + ((-s, s) for s in range(-SIDE, SIDE + 1)), # topright to bottomleft diag + ) + + for fill in (True, False): + mask = pygame.mask.Mask((SIDE, SIDE), fill=fill) + expected_color = default_setcolor if fill else default_unsetcolor + + for direction in directions: + for pos in direction: + dest_rect.topleft = pos + overlap_rect = dest_rect.clip(surface_rect) + surface.fill(surface_color) + + to_surface = mask.to_surface(surface, dest=dest_rect) + + assertSurfaceFilled(self, to_surface, expected_color, overlap_rect) + assertSurfaceFilledIgnoreArea( + self, to_surface, surface_color, overlap_rect + ) + + @unittest.expectedFailure + @unittest.skipIf(IS_PYPY, "Segfaults on pypy") + def test_to_surface__area_locations(self): + """Ensures area rects can be different locations on/off the mask.""" + SIDE = 7 + surface = pygame.Surface((SIDE, SIDE)) + + surface_color = pygame.Color("red") + default_setcolor = pygame.Color("white") + default_unsetcolor = pygame.Color("black") + + directions = ( + ((s, 0) for s in range(-SIDE, SIDE + 1)), # left to right + ((0, s) for s in range(-SIDE, SIDE + 1)), # top to bottom + ((s, s) for s in range(-SIDE, SIDE + 1)), # topleft to bottomright diag + ((-s, s) for s in range(-SIDE, SIDE + 1)), # topright to bottomleft diag + ) + + for fill in (True, False): + mask = pygame.mask.Mask((SIDE, SIDE), fill=fill) + mask_rect = mask.get_rect() + area_rect = mask_rect.copy() + expected_color = default_setcolor if fill else default_unsetcolor + + for direction in directions: + for pos in direction: + area_rect.topleft = pos + overlap_rect = area_rect.clip(mask_rect) + overlap_rect.topleft = (0, 0) + surface.fill(surface_color) + + to_surface = mask.to_surface(surface, area=area_rect) + + assertSurfaceFilled(self, to_surface, expected_color, overlap_rect) + assertSurfaceFilledIgnoreArea( + self, to_surface, surface_color, overlap_rect + ) + + @unittest.expectedFailure + def test_to_surface__dest_and_area_locations(self): + """Ensures dest/area values can be different locations on/off the + surface/mask. + """ + SIDE = 5 + surface = pygame.Surface((SIDE, SIDE)) + surface_rect = surface.get_rect() + dest_rect = surface_rect.copy() + + surface_color = pygame.Color("red") + default_setcolor = pygame.Color("white") + default_unsetcolor = pygame.Color("black") + + dest_directions = ( + ((s, 0) for s in range(-SIDE, SIDE + 1)), # left to right + ((0, s) for s in range(-SIDE, SIDE + 1)), # top to bottom + ((s, s) for s in range(-SIDE, SIDE + 1)), # topleft to bottomright diag + ((-s, s) for s in range(-SIDE, SIDE + 1)), # topright to bottomleft diag + ) + + # Using only the topleft to bottomright diagonal to test the area (to + # reduce the number of loop iterations). + area_positions = list(dest_directions[2]) + + for fill in (True, False): + mask = pygame.mask.Mask((SIDE, SIDE), fill=fill) + mask_rect = mask.get_rect() + area_rect = mask_rect.copy() + expected_color = default_setcolor if fill else default_unsetcolor + + for dest_direction in dest_directions: + for dest_pos in dest_direction: + dest_rect.topleft = dest_pos + + for area_pos in area_positions: + area_rect.topleft = area_pos + area_overlap_rect = area_rect.clip(mask_rect) + area_overlap_rect.topleft = dest_rect.topleft + dest_overlap_rect = dest_rect.clip(area_overlap_rect) + + surface.fill(surface_color) + + to_surface = mask.to_surface( + surface, dest=dest_rect, area=area_rect + ) + + assertSurfaceFilled( + self, to_surface, expected_color, dest_overlap_rect + ) + assertSurfaceFilledIgnoreArea( + self, to_surface, surface_color, dest_overlap_rect + ) + + @unittest.expectedFailure + def test_to_surface__area_sizes(self): + """Ensures area rects can be different sizes.""" + SIDE = 7 + SIZES = ( + (0, 0), + (0, 1), + (1, 0), + (1, 1), + (SIDE - 1, SIDE - 1), + (SIDE - 1, SIDE), + (SIDE, SIDE - 1), + (SIDE, SIDE), + (SIDE + 1, SIDE), + (SIDE, SIDE + 1), + (SIDE + 1, SIDE + 1), + ) + + surface = pygame.Surface((SIDE, SIDE)) + surface_color = pygame.Color("red") + default_setcolor = pygame.Color("white") + default_unsetcolor = pygame.Color("black") + + for fill in (True, False): + mask = pygame.mask.Mask((SIDE, SIDE), fill=fill) + mask_rect = mask.get_rect() + expected_color = default_setcolor if fill else default_unsetcolor + + for size in SIZES: + area_rect = pygame.Rect((0, 0), size) + + for pos in self.ORIGIN_OFFSETS: + area_rect.topleft = pos + overlap_rect = area_rect.clip(mask_rect) + overlap_rect.topleft = (0, 0) + surface.fill(surface_color) + + to_surface = mask.to_surface(surface, area=area_rect) + + assertSurfaceFilled(self, to_surface, expected_color, overlap_rect) + assertSurfaceFilledIgnoreArea( + self, to_surface, surface_color, overlap_rect + ) + + def test_to_surface__surface_color_alphas(self): + """Ensures the setsurface/unsetsurface color alpha values are respected.""" + size = (13, 17) + setsurface_color = pygame.Color("green") + setsurface_color.a = 53 + unsetsurface_color = pygame.Color("blue") + unsetsurface_color.a = 109 + + setsurface = pygame.Surface(size, flags=SRCALPHA, depth=32) + unsetsurface = pygame.Surface(size, flags=SRCALPHA, depth=32) + + setsurface.fill(setsurface_color) + unsetsurface.fill(unsetsurface_color) + + for fill in (True, False): + mask = pygame.mask.Mask(size, fill=fill) + expected_color = setsurface_color if fill else unsetsurface_color + + to_surface = mask.to_surface( + setsurface=setsurface, unsetsurface=unsetsurface + ) + + self.assertIsInstance(to_surface, pygame.Surface) + self.assertEqual(to_surface.get_size(), size) + assertSurfaceFilled(self, to_surface, expected_color) + + def test_to_surface__color_alphas(self): + """Ensures the setcolor/unsetcolor alpha values are respected.""" + size = (13, 17) + setcolor = pygame.Color("green") + setcolor.a = 35 + unsetcolor = pygame.Color("blue") + unsetcolor.a = 213 + + for fill in (True, False): + mask = pygame.mask.Mask(size, fill=fill) + expected_color = setcolor if fill else unsetcolor + + to_surface = mask.to_surface(setcolor=setcolor, unsetcolor=unsetcolor) + + self.assertIsInstance(to_surface, pygame.Surface) + self.assertEqual(to_surface.get_size(), size) + assertSurfaceFilled(self, to_surface, expected_color) + + def test_to_surface__depths(self): + """Ensures to_surface works correctly with supported surface depths.""" + size = (13, 17) + surface_color = pygame.Color("red") + setsurface_color = pygame.Color("green") + unsetsurface_color = pygame.Color("blue") + + for depth in (8, 16, 24, 32): + surface = pygame.Surface(size, depth=depth) + setsurface = pygame.Surface(size, depth=depth) + unsetsurface = pygame.Surface(size, depth=depth) + + surface.fill(surface_color) + setsurface.fill(setsurface_color) + unsetsurface.fill(unsetsurface_color) + + for fill in (True, False): + mask = pygame.mask.Mask(size, fill=fill) + + # For non-32 bit depths, the actual color can be different from + # what was filled. + expected_color = ( + setsurface.get_at((0, 0)) if fill else unsetsurface.get_at((0, 0)) + ) + + to_surface = mask.to_surface(surface, setsurface, unsetsurface) + + self.assertIsInstance(to_surface, pygame.Surface) + self.assertEqual(to_surface.get_size(), size) + assertSurfaceFilled(self, to_surface, expected_color) + + def test_to_surface__different_depths(self): + """Ensures an exception is raised when surfaces have different depths.""" + size = (13, 17) + surface_color = pygame.Color("red") + setsurface_color = pygame.Color("green") + unsetsurface_color = pygame.Color("blue") + mask = pygame.mask.Mask(size) + + # Test different combinations of depths. + test_depths = ( + (8, 8, 16), # surface/setsurface/unsetsurface + (8, 8, 24), + (8, 8, 32), + (16, 16, 24), + (16, 16, 32), + (24, 16, 8), + (32, 16, 16), + (32, 32, 16), + (32, 24, 32), + ) + + for depths in test_depths: + surface = pygame.Surface(size, depth=depths[0]) + setsurface = pygame.Surface(size, depth=depths[1]) + unsetsurface = pygame.Surface(size, depth=depths[2]) + + surface.fill(surface_color) + setsurface.fill(setsurface_color) + unsetsurface.fill(unsetsurface_color) + + with self.assertRaises(ValueError): + mask.to_surface(surface, setsurface, unsetsurface) + + def test_to_surface__different_depths_with_created_surfaces(self): + """Ensures an exception is raised when surfaces have different depths + than the created surface. + """ + size = (13, 17) + setsurface_color = pygame.Color("green") + unsetsurface_color = pygame.Color("blue") + mask = pygame.mask.Mask(size) + + # Test different combinations of depths. The created surface always has + # a depth of 32. + test_depths = ( + (8, 8), # setsurface/unsetsurface + (16, 16), + (24, 24), + (24, 16), + (32, 8), + (32, 16), + (32, 24), + (16, 32), + ) + + for set_depth, unset_depth in test_depths: + setsurface = pygame.Surface(size, depth=set_depth) + unsetsurface = pygame.Surface(size, depth=unset_depth) + + setsurface.fill(setsurface_color) + unsetsurface.fill(unsetsurface_color) + + with self.assertRaises(ValueError): + mask.to_surface(setsurface=setsurface, unsetsurface=unsetsurface) + + def test_to_surface__same_srcalphas(self): + """Ensures to_surface works correctly when the SRCALPHA flag is set or not.""" + size = (13, 17) + surface_color = pygame.Color("red") + setsurface_color = pygame.Color("green") + unsetsurface_color = pygame.Color("blue") + + for depth in (16, 32): + for flags in (0, SRCALPHA): + surface = pygame.Surface(size, flags=flags, depth=depth) + setsurface = pygame.Surface(size, flags=flags, depth=depth) + unsetsurface = pygame.Surface(size, flags=flags, depth=depth) + + surface.fill(surface_color) + setsurface.fill(setsurface_color) + unsetsurface.fill(unsetsurface_color) + + for fill in (True, False): + mask = pygame.mask.Mask(size, fill=fill) + expected_color = setsurface_color if fill else unsetsurface_color + + to_surface = mask.to_surface(surface, setsurface, unsetsurface) + + self.assertIsInstance(to_surface, pygame.Surface) + self.assertEqual(to_surface.get_size(), size) + assertSurfaceFilled(self, to_surface, expected_color) + if flags: + self.assertTrue(to_surface.get_flags() & flags) + + def test_to_surface__same_srcalphas_with_created_surfaces(self): + """Ensures to_surface works correctly when it creates a surface + and the SRCALPHA flag is set on both setsurface and unsetsurface. + """ + size = (13, 17) + setsurface_color = pygame.Color("green") + unsetsurface_color = pygame.Color("blue") + # The created surface always has a depth of 32 and the SRCALPHA flag set. + expected_flags = SRCALPHA + + setsurface = pygame.Surface(size, flags=expected_flags, depth=32) + unsetsurface = pygame.Surface(size, flags=expected_flags, depth=32) + + setsurface.fill(setsurface_color) + unsetsurface.fill(unsetsurface_color) + + for fill in (True, False): + mask = pygame.mask.Mask(size, fill=fill) + expected_color = setsurface_color if fill else unsetsurface_color + + to_surface = mask.to_surface( + setsurface=setsurface, unsetsurface=unsetsurface + ) + + self.assertIsInstance(to_surface, pygame.Surface) + self.assertEqual(to_surface.get_size(), size) + assertSurfaceFilled(self, to_surface, expected_color) + self.assertTrue(to_surface.get_flags() & expected_flags) + + def test_to_surface__different_srcalphas(self): + """Ensures an exception is raised when surfaces have different SRCALPHA + flag settings. + """ + size = (13, 17) + surface_color = pygame.Color("red") + setsurface_color = pygame.Color("green") + unsetsurface_color = pygame.Color("blue") + mask = pygame.mask.Mask(size) + + # Test different combinations of SRCALPHA flags. + test_flags = ( + (SRCALPHA, 0, 0), # surface/setsurface/unsetsurface + (SRCALPHA, SRCALPHA, 0), + (0, SRCALPHA, SRCALPHA), + (0, 0, SRCALPHA), + ) + + for depth in (16, 32): + for flags in test_flags: + surface = pygame.Surface(size, flags=flags[0], depth=depth) + setsurface = pygame.Surface(size, flags=flags[1], depth=depth) + unsetsurface = pygame.Surface(size, flags=flags[2], depth=depth) + + surface.fill(surface_color) + setsurface.fill(setsurface_color) + unsetsurface.fill(unsetsurface_color) + + with self.assertRaises(ValueError): + mask.to_surface(surface, setsurface, unsetsurface) + + def test_to_surface__different_srcalphas_with_created_surfaces(self): + """Ensures an exception is raised when surfaces have different SRCALPHA + flag settings than the created surface. + """ + size = (13, 17) + setsurface_color = pygame.Color("green") + unsetsurface_color = pygame.Color("blue") + mask = pygame.mask.Mask(size) + + for depth in (16, 32): + # Test different combinations of SRCALPHA flags. The created + # surface always has the SRCALPHA flag set. + for flags in ((0, 0), (SRCALPHA, 0), (0, SRCALPHA)): + setsurface = pygame.Surface(size, flags=flags[0], depth=depth) + unsetsurface = pygame.Surface(size, flags=flags[1], depth=depth) + + setsurface.fill(setsurface_color) + unsetsurface.fill(unsetsurface_color) + + with self.assertRaises(ValueError): + mask.to_surface(setsurface=setsurface, unsetsurface=unsetsurface) + + def test_to_surface__dest_on_surface(self): + """Ensures dest values on the surface work correctly + when using the defaults for setcolor and unsetcolor. + """ + default_setcolor = pygame.Color("white") + default_unsetcolor = pygame.Color("black") + width, height = size = (5, 9) + surface = pygame.Surface(size, SRCALPHA, 32) + surface_color = pygame.Color("red") + + for fill in (True, False): + mask = pygame.mask.Mask(size, fill=fill) + mask_rect = mask.get_rect() + expected_color = default_setcolor if fill else default_unsetcolor + + # Test the dest parameter at different locations on the surface. + for dest in ((x, y) for y in range(height) for x in range(width)): + surface.fill(surface_color) # Clear for each test. + mask_rect.topleft = dest + + to_surface = mask.to_surface(surface, dest=dest) + + self.assertIs(to_surface, surface) + self.assertEqual(to_surface.get_size(), size) + assertSurfaceFilled(self, to_surface, expected_color, mask_rect) + assertSurfaceFilledIgnoreArea( + self, to_surface, surface_color, mask_rect + ) + + def test_to_surface__dest_on_surface_with_setsurface_unsetsurface(self): + """Ensures dest values on the surface work correctly + when using setsurface and unsetsurface. + """ + width, height = size = (5, 9) + surface = pygame.Surface(size, SRCALPHA, 32) + surface_color = pygame.Color("red") + + setsurface = surface.copy() + setsurface_color = pygame.Color("green") + setsurface.fill(setsurface_color) + + unsetsurface = surface.copy() + unsetsurface_color = pygame.Color("blue") + unsetsurface.fill(unsetsurface_color) + + # Using different kwargs to exercise different to_surface() code. + # Should not have any impact on the resulting drawn surfaces. + kwargs = { + "surface": surface, + "setsurface": setsurface, + "unsetsurface": unsetsurface, + "dest": None, + } + + color_kwargs = dict(kwargs) + color_kwargs.update((("setcolor", None), ("unsetcolor", None))) + + for fill in (True, False): + mask = pygame.mask.Mask(size, fill=fill) + mask_rect = mask.get_rect() + expected_color = setsurface_color if fill else unsetsurface_color + + # Test the dest parameter at different locations on the surface. + for dest in ((x, y) for y in range(height) for x in range(width)): + mask_rect.topleft = dest + + for use_color_params in (True, False): + surface.fill(surface_color) # Clear for each test. + + test_kwargs = color_kwargs if use_color_params else kwargs + test_kwargs["dest"] = dest + to_surface = mask.to_surface(**test_kwargs) + + self.assertIs(to_surface, surface) + self.assertEqual(to_surface.get_size(), size) + assertSurfaceFilled(self, to_surface, expected_color, mask_rect) + assertSurfaceFilledIgnoreArea( + self, to_surface, surface_color, mask_rect + ) + + def test_to_surface__dest_off_surface(self): + """Ensures dest values off the surface work correctly + when using the defaults for setcolor and unsetcolor. + """ + default_setcolor = pygame.Color("white") + default_unsetcolor = pygame.Color("black") + width, height = size = (5, 7) + surface = pygame.Surface(size, SRCALPHA, 32) + surface_color = pygame.Color("red") + + # Test different dests off the surface. + dests = [(-width, -height), (-width, 0), (0, -height)] + dests.extend(off_corners(surface.get_rect())) + + for fill in (True, False): + mask = pygame.mask.Mask(size, fill=fill) + mask_rect = mask.get_rect() + expected_color = default_setcolor if fill else default_unsetcolor + + for dest in dests: + surface.fill(surface_color) # Clear for each test. + mask_rect.topleft = dest + + to_surface = mask.to_surface(surface, dest=dest) + + self.assertIs(to_surface, surface) + self.assertEqual(to_surface.get_size(), size) + assertSurfaceFilled(self, to_surface, expected_color, mask_rect) + assertSurfaceFilledIgnoreArea( + self, to_surface, surface_color, mask_rect + ) + + def test_to_surface__dest_off_surface_with_setsurface_unsetsurface(self): + """Ensures dest values off the surface work correctly + when using setsurface and unsetsurface. + """ + width, height = size = (5, 7) + surface = pygame.Surface(size, SRCALPHA, 32) + surface_color = pygame.Color("red") + + setsurface = surface.copy() + setsurface_color = pygame.Color("green") + setsurface.fill(setsurface_color) + + unsetsurface = surface.copy() + unsetsurface_color = pygame.Color("blue") + unsetsurface.fill(unsetsurface_color) + + # Test different dests off the surface. + dests = [(-width, -height), (-width, 0), (0, -height)] + dests.extend(off_corners(surface.get_rect())) + + # Using different kwargs to exercise different to_surface() code. + # Should not have any impact on the resulting drawn surfaces. + kwargs = { + "surface": surface, + "setsurface": setsurface, + "unsetsurface": unsetsurface, + "dest": None, + } + + color_kwargs = dict(kwargs) + color_kwargs.update((("setcolor", None), ("unsetcolor", None))) + + for fill in (True, False): + mask = pygame.mask.Mask(size, fill=fill) + mask_rect = mask.get_rect() + expected_color = setsurface_color if fill else unsetsurface_color + + for dest in dests: + mask_rect.topleft = dest + + for use_color_params in (True, False): + surface.fill(surface_color) # Clear for each test. + test_kwargs = color_kwargs if use_color_params else kwargs + test_kwargs["dest"] = dest + to_surface = mask.to_surface(**test_kwargs) + + self.assertIs(to_surface, surface) + self.assertEqual(to_surface.get_size(), size) + assertSurfaceFilled(self, to_surface, expected_color, mask_rect) + assertSurfaceFilledIgnoreArea( + self, to_surface, surface_color, mask_rect + ) + + @unittest.expectedFailure + @unittest.skipIf(IS_PYPY, "Segfaults on pypy") + def test_to_surface__area_on_mask(self): + """Ensures area values on the mask work correctly + when using the defaults for setcolor and unsetcolor. + """ + default_setcolor = pygame.Color("white") + default_unsetcolor = pygame.Color("black") + width, height = size = (5, 9) + surface = pygame.Surface(size, SRCALPHA, 32) + surface_color = pygame.Color("red") + + for fill in (True, False): + mask = pygame.mask.Mask(size, fill=fill) + mask_rect = mask.get_rect() + area_rect = mask_rect.copy() + expected_color = default_setcolor if fill else default_unsetcolor + + # Testing the area parameter at different locations on the mask. + for pos in ((x, y) for y in range(height) for x in range(width)): + surface.fill(surface_color) # Clear for each test. + area_rect.topleft = pos + overlap_rect = mask_rect.clip(area_rect) + overlap_rect.topleft = (0, 0) + + to_surface = mask.to_surface(surface, area=area_rect) + + self.assertIs(to_surface, surface) + self.assertEqual(to_surface.get_size(), size) + assertSurfaceFilled(self, to_surface, expected_color, overlap_rect) + assertSurfaceFilledIgnoreArea( + self, to_surface, surface_color, overlap_rect + ) + + @unittest.expectedFailure + def test_to_surface__area_on_mask_with_setsurface_unsetsurface(self): + """Ensures area values on the mask work correctly + when using setsurface and unsetsurface. + """ + width, height = size = (5, 9) + surface = pygame.Surface(size, SRCALPHA, 32) + surface_color = pygame.Color("red") + + setsurface = surface.copy() + setsurface_color = pygame.Color("green") + setsurface.fill(setsurface_color) + + unsetsurface = surface.copy() + unsetsurface_color = pygame.Color("blue") + unsetsurface.fill(unsetsurface_color) + + # Using the values in kwargs vs color_kwargs tests different to_surface + # code. Should not have any impact on the resulting drawn surfaces. + kwargs = { + "surface": surface, + "setsurface": setsurface, + "unsetsurface": unsetsurface, + "area": pygame.Rect((0, 0), size), + } + + color_kwargs = dict(kwargs) + color_kwargs.update((("setcolor", None), ("unsetcolor", None))) + + for fill in (True, False): + mask = pygame.mask.Mask(size, fill=fill) + mask_rect = mask.get_rect() + area_rect = mask_rect.copy() + expected_color = setsurface_color if fill else unsetsurface_color + + # Testing the area parameter at different locations on the mask. + for pos in ((x, y) for y in range(height) for x in range(width)): + area_rect.topleft = pos + overlap_rect = mask_rect.clip(area_rect) + overlap_rect.topleft = (0, 0) + + for use_color_params in (True, False): + surface.fill(surface_color) # Clear for each test. + test_kwargs = color_kwargs if use_color_params else kwargs + test_kwargs["area"].topleft = pos + overlap_rect = mask_rect.clip(test_kwargs["area"]) + overlap_rect.topleft = (0, 0) + + to_surface = mask.to_surface(**test_kwargs) + + self.assertIs(to_surface, surface) + self.assertEqual(to_surface.get_size(), size) + assertSurfaceFilled(self, to_surface, expected_color, overlap_rect) + assertSurfaceFilledIgnoreArea( + self, to_surface, surface_color, overlap_rect + ) + + @unittest.expectedFailure + @unittest.skipIf(IS_PYPY, "Segfaults on pypy") + def test_to_surface__area_off_mask(self): + """Ensures area values off the mask work correctly + when using the defaults for setcolor and unsetcolor. + """ + default_setcolor = pygame.Color("white") + default_unsetcolor = pygame.Color("black") + width, height = size = (5, 7) + surface = pygame.Surface(size, SRCALPHA, 32) + surface_color = pygame.Color("red") + + # Testing positions off the mask. + positions = [(-width, -height), (-width, 0), (0, -height)] + positions.extend(off_corners(pygame.Rect((0, 0), (width, height)))) + + for fill in (True, False): + mask = pygame.mask.Mask(size, fill=fill) + mask_rect = mask.get_rect() + area_rect = mask_rect.copy() + expected_color = default_setcolor if fill else default_unsetcolor + + for pos in positions: + surface.fill(surface_color) # Clear for each test. + area_rect.topleft = pos + overlap_rect = mask_rect.clip(area_rect) + overlap_rect.topleft = (0, 0) + + to_surface = mask.to_surface(surface, area=area_rect) + + self.assertIs(to_surface, surface) + self.assertEqual(to_surface.get_size(), size) + assertSurfaceFilled(self, to_surface, expected_color, overlap_rect) + assertSurfaceFilledIgnoreArea( + self, to_surface, surface_color, overlap_rect + ) + + @unittest.expectedFailure + @unittest.skipIf(IS_PYPY, "Segfaults on pypy") + def test_to_surface__area_off_mask_with_setsurface_unsetsurface(self): + """Ensures area values off the mask work correctly + when using setsurface and unsetsurface. + """ + width, height = size = (5, 7) + surface = pygame.Surface(size, SRCALPHA, 32) + surface_color = pygame.Color("red") + + setsurface = surface.copy() + setsurface_color = pygame.Color("green") + setsurface.fill(setsurface_color) + + unsetsurface = surface.copy() + unsetsurface_color = pygame.Color("blue") + unsetsurface.fill(unsetsurface_color) + + # Testing positions off the mask. + positions = [(-width, -height), (-width, 0), (0, -height)] + positions.extend(off_corners(pygame.Rect((0, 0), (width, height)))) + + # Using the values in kwargs vs color_kwargs tests different to_surface + # code. Should not have any impact on the resulting drawn surfaces. + kwargs = { + "surface": surface, + "setsurface": setsurface, + "unsetsurface": unsetsurface, + "area": pygame.Rect((0, 0), size), + } + + color_kwargs = dict(kwargs) + color_kwargs.update((("setcolor", None), ("unsetcolor", None))) + + for fill in (True, False): + mask = pygame.mask.Mask(size, fill=fill) + mask_rect = mask.get_rect() + expected_color = setsurface_color if fill else unsetsurface_color + + for pos in positions: + for use_color_params in (True, False): + surface.fill(surface_color) # Clear for each test. + test_kwargs = color_kwargs if use_color_params else kwargs + test_kwargs["area"].topleft = pos + overlap_rect = mask_rect.clip(test_kwargs["area"]) + overlap_rect.topleft = (0, 0) + + to_surface = mask.to_surface(**test_kwargs) + + self.assertIs(to_surface, surface) + self.assertEqual(to_surface.get_size(), size) + assertSurfaceFilled(self, to_surface, expected_color, overlap_rect) + assertSurfaceFilledIgnoreArea( + self, to_surface, surface_color, overlap_rect + ) + + def test_to_surface__surface_with_zero_size(self): + """Ensures zero sized surfaces are handled correctly.""" + expected_ref_count = 3 + size = (0, 0) + surface = pygame.Surface(size) + mask = pygame.mask.Mask((3, 4), fill=True) + + to_surface = mask.to_surface(surface) + + self.assertIs(to_surface, surface) + if not IS_PYPY: + self.assertEqual(sys.getrefcount(to_surface), expected_ref_count) + self.assertEqual(to_surface.get_size(), size) + + def test_to_surface__setsurface_with_zero_size(self): + """Ensures zero sized setsurfaces are handled correctly.""" + expected_ref_count = 2 + expected_flag = SRCALPHA + expected_depth = 32 + expected_color = pygame.Color("white") # Default setcolor. + mask_size = (2, 4) + mask = pygame.mask.Mask(mask_size, fill=True) + setsurface = pygame.Surface((0, 0), expected_flag, expected_depth) + + to_surface = mask.to_surface(setsurface=setsurface) + + self.assertIsInstance(to_surface, pygame.Surface) + if not IS_PYPY: + self.assertEqual(sys.getrefcount(to_surface), expected_ref_count) + self.assertTrue(to_surface.get_flags() & expected_flag) + self.assertEqual(to_surface.get_bitsize(), expected_depth) + self.assertEqual(to_surface.get_size(), mask_size) + assertSurfaceFilled(self, to_surface, expected_color) + + def test_to_surface__unsetsurface_with_zero_size(self): + """Ensures zero sized unsetsurfaces are handled correctly.""" + expected_ref_count = 2 + expected_flag = SRCALPHA + expected_depth = 32 + expected_color = pygame.Color("black") # Default unsetcolor. + mask_size = (4, 2) + mask = pygame.mask.Mask(mask_size) + unsetsurface = pygame.Surface((0, 0), expected_flag, expected_depth) + + to_surface = mask.to_surface(unsetsurface=unsetsurface) + + self.assertIsInstance(to_surface, pygame.Surface) + if not IS_PYPY: + self.assertEqual(sys.getrefcount(to_surface), expected_ref_count) + self.assertTrue(to_surface.get_flags() & expected_flag) + self.assertEqual(to_surface.get_bitsize(), expected_depth) + self.assertEqual(to_surface.get_size(), mask_size) + assertSurfaceFilled(self, to_surface, expected_color) + + def test_zero_mask(self): + """Ensures masks can be created with zero sizes.""" + for size in ((100, 0), (0, 100), (0, 0)): + for fill in (True, False): + msg = "size={}, fill={}".format(size, fill) + + mask = pygame.mask.Mask(size, fill=fill) + + self.assertIsInstance(mask, pygame.mask.Mask, msg) + self.assertEqual(mask.get_size(), size, msg) + + def test_zero_mask_copy(self): + """Ensures copy correctly handles zero sized masks.""" + for expected_size in ((11, 0), (0, 11), (0, 0)): + mask = pygame.mask.Mask(expected_size) + + mask_copy = mask.copy() + + self.assertIsInstance(mask_copy, pygame.mask.Mask) + self.assertIsNot(mask_copy, mask) + assertMaskEqual(self, mask_copy, mask) + + def test_zero_mask_get_size(self): + """Ensures get_size correctly handles zero sized masks.""" + for expected_size in ((41, 0), (0, 40), (0, 0)): + mask = pygame.mask.Mask(expected_size) + + size = mask.get_size() + + self.assertEqual(size, expected_size) + + def test_zero_mask_get_rect(self): + """Ensures get_rect correctly handles zero sized masks.""" + for expected_size in ((4, 0), (0, 4), (0, 0)): + expected_rect = pygame.Rect((0, 0), expected_size) + mask = pygame.mask.Mask(expected_size) + + rect = mask.get_rect() + + self.assertEqual(rect, expected_rect) + + def test_zero_mask_get_at(self): + """Ensures get_at correctly handles zero sized masks.""" + for size in ((51, 0), (0, 50), (0, 0)): + mask = pygame.mask.Mask(size) + + with self.assertRaises(IndexError): + value = mask.get_at((0, 0)) + + def test_zero_mask_set_at(self): + """Ensures set_at correctly handles zero sized masks.""" + for size in ((31, 0), (0, 30), (0, 0)): + mask = pygame.mask.Mask(size) + + with self.assertRaises(IndexError): + mask.set_at((0, 0)) + + def test_zero_mask_overlap(self): + """Ensures overlap correctly handles zero sized masks. + + Tests combinations of sized and zero sized masks. + """ + offset = (0, 0) + + for size1, size2 in zero_size_pairs(51, 42): + msg = "size1={}, size2={}".format(size1, size2) + mask1 = pygame.mask.Mask(size1, fill=True) + mask2 = pygame.mask.Mask(size2, fill=True) + + overlap_pos = mask1.overlap(mask2, offset) + + self.assertIsNone(overlap_pos, msg) + + def test_zero_mask_overlap_area(self): + """Ensures overlap_area correctly handles zero sized masks. + + Tests combinations of sized and zero sized masks. + """ + offset = (0, 0) + expected_count = 0 + + for size1, size2 in zero_size_pairs(41, 52): + msg = "size1={}, size2={}".format(size1, size2) + mask1 = pygame.mask.Mask(size1, fill=True) + mask2 = pygame.mask.Mask(size2, fill=True) + + overlap_count = mask1.overlap_area(mask2, offset) + + self.assertEqual(overlap_count, expected_count, msg) + + def test_zero_mask_overlap_mask(self): + """Ensures overlap_mask correctly handles zero sized masks. + + Tests combinations of sized and zero sized masks. + """ + offset = (0, 0) + expected_count = 0 + + for size1, size2 in zero_size_pairs(43, 53): + msg = "size1={}, size2={}".format(size1, size2) + mask1 = pygame.mask.Mask(size1, fill=True) + mask2 = pygame.mask.Mask(size2, fill=True) + + overlap_mask = mask1.overlap_mask(mask2, offset) + + self.assertIsInstance(overlap_mask, pygame.mask.Mask, msg) + self.assertEqual(overlap_mask.count(), expected_count, msg) + self.assertEqual(overlap_mask.get_size(), size1, msg) + + def test_zero_mask_fill(self): + """Ensures fill correctly handles zero sized masks.""" + expected_count = 0 + + for size in ((100, 0), (0, 100), (0, 0)): + mask = pygame.mask.Mask(size) + + mask.fill() + + self.assertEqual(mask.count(), expected_count, "size={}".format(size)) + + def test_zero_mask_clear(self): + sizes = ((100, 0), (0, 100), (0, 0)) + + for size in sizes: + mask = pygame.mask.Mask(size) + mask.clear() + self.assertEqual(mask.count(), 0) + + def test_zero_mask_flip(self): + sizes = ((100, 0), (0, 100), (0, 0)) + + for size in sizes: + mask = pygame.mask.Mask(size) + mask.invert() + self.assertEqual(mask.count(), 0) + + def test_zero_mask_scale(self): + sizes = ((100, 0), (0, 100), (0, 0)) + + for size in sizes: + mask = pygame.mask.Mask(size) + mask2 = mask.scale((2, 3)) + + self.assertIsInstance(mask2, pygame.mask.Mask) + self.assertEqual(mask2.get_size(), (2, 3)) + + def test_zero_mask_draw(self): + """Ensures draw correctly handles zero sized masks. + + Tests combinations of sized and zero sized masks. + """ + offset = (0, 0) + + for size1, size2 in zero_size_pairs(31, 37): + msg = "size1={}, size2={}".format(size1, size2) + mask1 = pygame.mask.Mask(size1, fill=True) + mask2 = pygame.mask.Mask(size2, fill=True) + expected_count = mask1.count() + + mask1.draw(mask2, offset) + + self.assertEqual(mask1.count(), expected_count, msg) + self.assertEqual(mask1.get_size(), size1, msg) + + def test_zero_mask_erase(self): + """Ensures erase correctly handles zero sized masks. + + Tests combinations of sized and zero sized masks. + """ + offset = (0, 0) + + for size1, size2 in zero_size_pairs(29, 23): + msg = "size1={}, size2={}".format(size1, size2) + mask1 = pygame.mask.Mask(size1, fill=True) + mask2 = pygame.mask.Mask(size2, fill=True) + expected_count = mask1.count() + + mask1.erase(mask2, offset) + + self.assertEqual(mask1.count(), expected_count, msg) + self.assertEqual(mask1.get_size(), size1, msg) + + def test_zero_mask_count(self): + sizes = ((100, 0), (0, 100), (0, 0)) + + for size in sizes: + mask = pygame.mask.Mask(size, fill=True) + self.assertEqual(mask.count(), 0) + + def test_zero_mask_centroid(self): + sizes = ((100, 0), (0, 100), (0, 0)) + + for size in sizes: + mask = pygame.mask.Mask(size) + self.assertEqual(mask.centroid(), (0, 0)) + + def test_zero_mask_angle(self): + sizes = ((100, 0), (0, 100), (0, 0)) + + for size in sizes: + mask = pygame.mask.Mask(size) + self.assertEqual(mask.angle(), 0.0) + + def test_zero_mask_outline(self): + """Ensures outline correctly handles zero sized masks.""" + expected_points = [] + + for size in ((61, 0), (0, 60), (0, 0)): + mask = pygame.mask.Mask(size) + + points = mask.outline() + + self.assertListEqual(points, expected_points, "size={}".format(size)) + + def test_zero_mask_outline__with_arg(self): + """Ensures outline correctly handles zero sized masks + when using the skip pixels argument.""" + expected_points = [] + + for size in ((66, 0), (0, 65), (0, 0)): + mask = pygame.mask.Mask(size) + + points = mask.outline(10) + + self.assertListEqual(points, expected_points, "size={}".format(size)) + + def test_zero_mask_convolve(self): + """Ensures convolve correctly handles zero sized masks. + + Tests the different combinations of sized and zero sized masks. + """ + for size1 in ((17, 13), (71, 0), (0, 70), (0, 0)): + mask1 = pygame.mask.Mask(size1, fill=True) + + for size2 in ((11, 7), (81, 0), (0, 60), (0, 0)): + msg = "sizes={}, {}".format(size1, size2) + mask2 = pygame.mask.Mask(size2, fill=True) + expected_size = ( + max(0, size1[0] + size2[0] - 1), + max(0, size1[1] + size2[1] - 1), + ) + + mask = mask1.convolve(mask2) + + self.assertIsInstance(mask, pygame.mask.Mask, msg) + self.assertIsNot(mask, mask2, msg) + self.assertEqual(mask.get_size(), expected_size, msg) + + def test_zero_mask_convolve__with_output_mask(self): + """Ensures convolve correctly handles zero sized masks + when using an output mask argument. + + Tests the different combinations of sized and zero sized masks. + """ + for size1 in ((11, 17), (91, 0), (0, 90), (0, 0)): + mask1 = pygame.mask.Mask(size1, fill=True) + + for size2 in ((13, 11), (83, 0), (0, 62), (0, 0)): + mask2 = pygame.mask.Mask(size2, fill=True) + + for output_size in ((7, 5), (71, 0), (0, 70), (0, 0)): + msg = "sizes={}, {}, {}".format(size1, size2, output_size) + output_mask = pygame.mask.Mask(output_size) + + mask = mask1.convolve(mask2, output_mask) + + self.assertIsInstance(mask, pygame.mask.Mask, msg) + self.assertIs(mask, output_mask, msg) + self.assertEqual(mask.get_size(), output_size, msg) + + def test_zero_mask_connected_component(self): + """Ensures connected_component correctly handles zero sized masks.""" + expected_count = 0 + + for size in ((81, 0), (0, 80), (0, 0)): + msg = "size={}".format(size) + mask = pygame.mask.Mask(size) + + cc_mask = mask.connected_component() + + self.assertIsInstance(cc_mask, pygame.mask.Mask, msg) + self.assertEqual(cc_mask.get_size(), size) + self.assertEqual(cc_mask.count(), expected_count, msg) + + def test_zero_mask_connected_component__indexed(self): + """Ensures connected_component correctly handles zero sized masks + when using an index argument.""" + for size in ((91, 0), (0, 90), (0, 0)): + mask = pygame.mask.Mask(size) + + with self.assertRaises(IndexError): + cc_mask = mask.connected_component((0, 0)) + + def test_zero_mask_connected_components(self): + """Ensures connected_components correctly handles zero sized masks.""" + expected_cc_masks = [] + + for size in ((11, 0), (0, 10), (0, 0)): + mask = pygame.mask.Mask(size) + + cc_masks = mask.connected_components() + + self.assertListEqual(cc_masks, expected_cc_masks, "size={}".format(size)) + + def test_zero_mask_get_bounding_rects(self): + """Ensures get_bounding_rects correctly handles zero sized masks.""" + expected_bounding_rects = [] + + for size in ((21, 0), (0, 20), (0, 0)): + mask = pygame.mask.Mask(size) + + bounding_rects = mask.get_bounding_rects() + + self.assertListEqual( + bounding_rects, expected_bounding_rects, "size={}".format(size) + ) + + def test_zero_mask_to_surface(self): + """Ensures to_surface correctly handles zero sized masks and surfaces.""" + mask_color = pygame.Color("blue") + surf_color = pygame.Color("red") + + for surf_size in ((7, 3), (7, 0), (0, 7), (0, 0)): + surface = pygame.Surface(surf_size, SRCALPHA, 32) + surface.fill(surf_color) + + for mask_size in ((5, 0), (0, 5), (0, 0)): + mask = pygame.mask.Mask(mask_size, fill=True) + + to_surface = mask.to_surface(surface, setcolor=mask_color) + + self.assertIs(to_surface, surface) + self.assertEqual(to_surface.get_size(), surf_size) + + if 0 not in surf_size: + assertSurfaceFilled(self, to_surface, surf_color) + + def test_zero_mask_to_surface__create_surface(self): + """Ensures to_surface correctly handles zero sized masks and surfaces + when it has to create a default surface. + """ + mask_color = pygame.Color("blue") + + for mask_size in ((3, 0), (0, 3), (0, 0)): + mask = pygame.mask.Mask(mask_size, fill=True) + + to_surface = mask.to_surface(setcolor=mask_color) + + self.assertIsInstance(to_surface, pygame.Surface) + self.assertEqual(to_surface.get_size(), mask_size) + + +class SubMask(pygame.mask.Mask): + """Subclass of the Mask class to help test subclassing.""" + + def __init__(self, *args, **kwargs): + super(SubMask, self).__init__(*args, **kwargs) + self.test_attribute = True + + +class SubMaskCopy(SubMask): + """Subclass of the Mask class to help test copying subclasses.""" + + def copy(self): + mask_copy = super(SubMaskCopy, self).copy() + mask_copy.test_attribute = self.test_attribute + return mask_copy + + +class SubMaskDunderCopy(SubMask): + """Subclass of the Mask class to help test copying subclasses.""" + + def __copy__(self): + mask_copy = super(SubMaskDunderCopy, self).__copy__() + mask_copy.test_attribute = self.test_attribute + return mask_copy + + +class SubMaskCopyAndDunderCopy(SubMaskDunderCopy): + """Subclass of the Mask class to help test copying subclasses.""" + + def copy(self): + return super(SubMaskCopyAndDunderCopy, self).copy() + + +class MaskSubclassTest(unittest.TestCase): + """Test subclassed Masks.""" + + def test_subclass_mask(self): + """Ensures the Mask class can be subclassed.""" + mask = SubMask((5, 3), fill=True) + + self.assertIsInstance(mask, pygame.mask.Mask) + self.assertIsInstance(mask, SubMask) + self.assertTrue(mask.test_attribute) + + def test_subclass_copy(self): + """Ensures copy works for subclassed Masks.""" + mask = SubMask((65, 2), fill=True) + + # Test both the copy() and __copy__() methods. + for mask_copy in (mask.copy(), copy.copy(mask)): + self.assertIsInstance(mask_copy, pygame.mask.Mask) + self.assertIsInstance(mask_copy, SubMask) + self.assertIsNot(mask_copy, mask) + assertMaskEqual(self, mask_copy, mask) + # No subclass attributes because copy()/__copy__() not overridden. + self.assertFalse(hasattr(mask_copy, "test_attribute")) + + def test_subclass_copy__override_copy(self): + """Ensures copy works for subclassed Masks overriding copy.""" + mask = SubMaskCopy((65, 2), fill=True) + + # Test both the copy() and __copy__() methods. + for i, mask_copy in enumerate((mask.copy(), copy.copy(mask))): + self.assertIsInstance(mask_copy, pygame.mask.Mask) + self.assertIsInstance(mask_copy, SubMaskCopy) + self.assertIsNot(mask_copy, mask) + assertMaskEqual(self, mask_copy, mask) + + if 1 == i: + # No subclass attributes because __copy__() not overridden. + self.assertFalse(hasattr(mask_copy, "test_attribute")) + else: + self.assertTrue(mask_copy.test_attribute) + + def test_subclass_copy__override_dunder_copy(self): + """Ensures copy works for subclassed Masks overriding __copy__.""" + mask = SubMaskDunderCopy((65, 2), fill=True) + + # Test both the copy() and __copy__() methods. + for mask_copy in (mask.copy(), copy.copy(mask)): + self.assertIsInstance(mask_copy, pygame.mask.Mask) + self.assertIsInstance(mask_copy, SubMaskDunderCopy) + self.assertIsNot(mask_copy, mask) + assertMaskEqual(self, mask_copy, mask) + # Calls to copy() eventually call __copy__() internally so the + # attributes will be copied. + self.assertTrue(mask_copy.test_attribute) + + def test_subclass_copy__override_both_copy_methods(self): + """Ensures copy works for subclassed Masks overriding copy/__copy__.""" + mask = SubMaskCopyAndDunderCopy((65, 2), fill=True) + + # Test both the copy() and __copy__() methods. + for mask_copy in (mask.copy(), copy.copy(mask)): + self.assertIsInstance(mask_copy, pygame.mask.Mask) + self.assertIsInstance(mask_copy, SubMaskCopyAndDunderCopy) + self.assertIsNot(mask_copy, mask) + assertMaskEqual(self, mask_copy, mask) + self.assertTrue(mask_copy.test_attribute) + + def test_subclass_get_size(self): + """Ensures get_size works for subclassed Masks.""" + expected_size = (2, 3) + mask = SubMask(expected_size) + + size = mask.get_size() + + self.assertEqual(size, expected_size) + + def test_subclass_mask_get_rect(self): + """Ensures get_rect works for subclassed Masks.""" + expected_rect = pygame.Rect((0, 0), (65, 33)) + mask = SubMask(expected_rect.size, fill=True) + + rect = mask.get_rect() + + self.assertEqual(rect, expected_rect) + + def test_subclass_get_at(self): + """Ensures get_at works for subclassed Masks.""" + expected_bit = 1 + mask = SubMask((3, 2), fill=True) + + bit = mask.get_at((0, 0)) + + self.assertEqual(bit, expected_bit) + + def test_subclass_set_at(self): + """Ensures set_at works for subclassed Masks.""" + expected_bit = 1 + expected_count = 1 + pos = (0, 0) + mask = SubMask(fill=False, size=(4, 2)) + + mask.set_at(pos) + + self.assertEqual(mask.get_at(pos), expected_bit) + self.assertEqual(mask.count(), expected_count) + + def test_subclass_overlap(self): + """Ensures overlap works for subclassed Masks.""" + expected_pos = (0, 0) + mask_size = (2, 3) + masks = (pygame.mask.Mask(fill=True, size=mask_size), SubMask(mask_size, True)) + arg_masks = ( + pygame.mask.Mask(fill=True, size=mask_size), + SubMask(mask_size, True), + ) + + # Test different combinations of subclassed and non-subclassed Masks. + for mask in masks: + for arg_mask in arg_masks: + overlap_pos = mask.overlap(arg_mask, (0, 0)) + + self.assertEqual(overlap_pos, expected_pos) + + def test_subclass_overlap_area(self): + """Ensures overlap_area works for subclassed Masks.""" + mask_size = (3, 2) + expected_count = mask_size[0] * mask_size[1] + masks = (pygame.mask.Mask(fill=True, size=mask_size), SubMask(mask_size, True)) + arg_masks = ( + pygame.mask.Mask(fill=True, size=mask_size), + SubMask(mask_size, True), + ) + + # Test different combinations of subclassed and non-subclassed Masks. + for mask in masks: + for arg_mask in arg_masks: + overlap_count = mask.overlap_area(arg_mask, (0, 0)) + + self.assertEqual(overlap_count, expected_count) + + def test_subclass_overlap_mask(self): + """Ensures overlap_mask works for subclassed Masks.""" + expected_size = (4, 5) + expected_count = expected_size[0] * expected_size[1] + masks = ( + pygame.mask.Mask(fill=True, size=expected_size), + SubMask(expected_size, True), + ) + arg_masks = ( + pygame.mask.Mask(fill=True, size=expected_size), + SubMask(expected_size, True), + ) + + # Test different combinations of subclassed and non-subclassed Masks. + for mask in masks: + for arg_mask in arg_masks: + overlap_mask = mask.overlap_mask(arg_mask, (0, 0)) + + self.assertIsInstance(overlap_mask, pygame.mask.Mask) + self.assertNotIsInstance(overlap_mask, SubMask) + self.assertEqual(overlap_mask.count(), expected_count) + self.assertEqual(overlap_mask.get_size(), expected_size) + + def test_subclass_fill(self): + """Ensures fill works for subclassed Masks.""" + mask_size = (2, 4) + expected_count = mask_size[0] * mask_size[1] + mask = SubMask(fill=False, size=mask_size) + + mask.fill() + + self.assertEqual(mask.count(), expected_count) + + def test_subclass_clear(self): + """Ensures clear works for subclassed Masks.""" + mask_size = (4, 3) + expected_count = 0 + mask = SubMask(mask_size, True) + + mask.clear() + + self.assertEqual(mask.count(), expected_count) + + def test_subclass_invert(self): + """Ensures invert works for subclassed Masks.""" + mask_size = (1, 4) + expected_count = mask_size[0] * mask_size[1] + mask = SubMask(fill=False, size=mask_size) + + mask.invert() + + self.assertEqual(mask.count(), expected_count) + + def test_subclass_scale(self): + """Ensures scale works for subclassed Masks.""" + expected_size = (5, 2) + mask = SubMask((1, 4)) + + scaled_mask = mask.scale(expected_size) + + self.assertIsInstance(scaled_mask, pygame.mask.Mask) + self.assertNotIsInstance(scaled_mask, SubMask) + self.assertEqual(scaled_mask.get_size(), expected_size) + + def test_subclass_draw(self): + """Ensures draw works for subclassed Masks.""" + mask_size = (5, 4) + expected_count = mask_size[0] * mask_size[1] + arg_masks = ( + pygame.mask.Mask(fill=True, size=mask_size), + SubMask(mask_size, True), + ) + + # Test different combinations of subclassed and non-subclassed Masks. + for mask in (pygame.mask.Mask(mask_size), SubMask(mask_size)): + for arg_mask in arg_masks: + mask.clear() # Clear for each test. + + mask.draw(arg_mask, (0, 0)) + + self.assertEqual(mask.count(), expected_count) + + def test_subclass_erase(self): + """Ensures erase works for subclassed Masks.""" + mask_size = (3, 4) + expected_count = 0 + masks = (pygame.mask.Mask(mask_size, True), SubMask(mask_size, True)) + arg_masks = (pygame.mask.Mask(mask_size, True), SubMask(mask_size, True)) + + # Test different combinations of subclassed and non-subclassed Masks. + for mask in masks: + for arg_mask in arg_masks: + mask.fill() # Fill for each test. + + mask.erase(arg_mask, (0, 0)) + + self.assertEqual(mask.count(), expected_count) + + def test_subclass_count(self): + """Ensures count works for subclassed Masks.""" + mask_size = (5, 2) + expected_count = mask_size[0] * mask_size[1] - 1 + mask = SubMask(fill=True, size=mask_size) + mask.set_at((1, 1), 0) + + count = mask.count() + + self.assertEqual(count, expected_count) + + def test_subclass_centroid(self): + """Ensures centroid works for subclassed Masks.""" + expected_centroid = (0, 0) + mask_size = (3, 2) + mask = SubMask((3, 2)) + + centroid = mask.centroid() + + self.assertEqual(centroid, expected_centroid) + + def test_subclass_angle(self): + """Ensures angle works for subclassed Masks.""" + expected_angle = 0.0 + mask = SubMask(size=(5, 4)) + + angle = mask.angle() + + self.assertAlmostEqual(angle, expected_angle) + + def test_subclass_outline(self): + """Ensures outline works for subclassed Masks.""" + expected_outline = [] + mask = SubMask((3, 4)) + + outline = mask.outline() + + self.assertListEqual(outline, expected_outline) + + def test_subclass_convolve(self): + """Ensures convolve works for subclassed Masks.""" + width, height = 7, 5 + mask_size = (width, height) + expected_count = 0 + expected_size = (max(0, width * 2 - 1), max(0, height * 2 - 1)) + + arg_masks = (pygame.mask.Mask(mask_size), SubMask(mask_size)) + output_masks = (pygame.mask.Mask(mask_size), SubMask(mask_size)) + + # Test different combinations of subclassed and non-subclassed Masks. + for mask in (pygame.mask.Mask(mask_size), SubMask(mask_size)): + for arg_mask in arg_masks: + convolve_mask = mask.convolve(arg_mask) + + self.assertIsInstance(convolve_mask, pygame.mask.Mask) + self.assertNotIsInstance(convolve_mask, SubMask) + self.assertEqual(convolve_mask.count(), expected_count) + self.assertEqual(convolve_mask.get_size(), expected_size) + + # Test subclassed masks for the output_mask as well. + for output_mask in output_masks: + convolve_mask = mask.convolve(arg_mask, output_mask) + + self.assertIsInstance(convolve_mask, pygame.mask.Mask) + self.assertEqual(convolve_mask.count(), expected_count) + self.assertEqual(convolve_mask.get_size(), mask_size) + + if isinstance(output_mask, SubMask): + self.assertIsInstance(convolve_mask, SubMask) + else: + self.assertNotIsInstance(convolve_mask, SubMask) + + def test_subclass_connected_component(self): + """Ensures connected_component works for subclassed Masks.""" + expected_count = 0 + expected_size = (3, 4) + mask = SubMask(expected_size) + + cc_mask = mask.connected_component() + + self.assertIsInstance(cc_mask, pygame.mask.Mask) + self.assertNotIsInstance(cc_mask, SubMask) + self.assertEqual(cc_mask.count(), expected_count) + self.assertEqual(cc_mask.get_size(), expected_size) + + def test_subclass_connected_components(self): + """Ensures connected_components works for subclassed Masks.""" + expected_ccs = [] + mask = SubMask((5, 4)) + + ccs = mask.connected_components() + + self.assertListEqual(ccs, expected_ccs) + + def test_subclass_get_bounding_rects(self): + """Ensures get_bounding_rects works for subclassed Masks.""" + expected_bounding_rects = [] + mask = SubMask((3, 2)) + + bounding_rects = mask.get_bounding_rects() + + self.assertListEqual(bounding_rects, expected_bounding_rects) + + def test_subclass_to_surface(self): + """Ensures to_surface works for subclassed Masks.""" + expected_color = pygame.Color("blue") + size = (5, 3) + mask = SubMask(size, fill=True) + surface = pygame.Surface(size, SRCALPHA, 32) + surface.fill(pygame.Color("red")) + + to_surface = mask.to_surface(surface, setcolor=expected_color) + + self.assertIs(to_surface, surface) + self.assertEqual(to_surface.get_size(), size) + assertSurfaceFilled(self, to_surface, expected_color) + + +@unittest.skipIf(IS_PYPY, "pypy has lots of mask failures") # TODO +class MaskModuleTest(unittest.TestCase): + def test_from_surface(self): + """Ensures from_surface creates a mask with the correct bits set. + + This test checks the masks created by the from_surface function using + 16 and 32 bit surfaces. Each alpha value (0-255) is tested against + several different threshold values. + Note: On 16 bit surface the requested alpha value can differ from what + is actually set. This test uses the value read from the surface. + """ + threshold_count = 256 + surface_color = [55, 155, 255, 0] + expected_size = (11, 9) + all_set_count = expected_size[0] * expected_size[1] + none_set_count = 0 + + for depth in (16, 32): + surface = pygame.Surface(expected_size, SRCALPHA, depth) + + for alpha in range(threshold_count): + surface_color[3] = alpha + surface.fill(surface_color) + + if depth < 32: + # On surfaces with depths < 32 the requested alpha can be + # different than what gets set. Use the value read from the + # surface. + alpha = surface.get_at((0, 0))[3] + + # Test the mask created at threshold values low, high and + # around alpha. + threshold_test_values = set( + [-1, 0, alpha - 1, alpha, alpha + 1, 255, 256] + ) + + for threshold in threshold_test_values: + msg = "depth={}, alpha={}, threshold={}".format( + depth, alpha, threshold + ) + + if alpha > threshold: + expected_count = all_set_count + else: + expected_count = none_set_count + + mask = pygame.mask.from_surface( + surface=surface, threshold=threshold + ) + + self.assertIsInstance(mask, pygame.mask.Mask, msg) + self.assertEqual(mask.get_size(), expected_size, msg) + self.assertEqual(mask.count(), expected_count, msg) + + def test_from_surface__different_alphas_32bit(self): + """Ensures from_surface creates a mask with the correct bits set + when pixels have different alpha values (32 bits surfaces). + + This test checks the masks created by the from_surface function using + a 32 bit surface. The surface is created with each pixel having a + different alpha value (0-255). This surface is tested over a range + of threshold values (0-255). + """ + offset = (0, 0) + threshold_count = 256 + surface_color = [10, 20, 30, 0] + expected_size = (threshold_count, 1) + expected_mask = pygame.Mask(expected_size, fill=True) + surface = pygame.Surface(expected_size, SRCALPHA, 32) + + # Give each pixel a different alpha. + surface.lock() # Lock for possible speed up. + for a in range(threshold_count): + surface_color[3] = a + surface.set_at((a, 0), surface_color) + surface.unlock() + + # Test the mask created for each different alpha threshold. + for threshold in range(threshold_count): + msg = "threshold={}".format(threshold) + expected_mask.set_at((threshold, 0), 0) + expected_count = expected_mask.count() + + mask = pygame.mask.from_surface(surface, threshold) + + self.assertIsInstance(mask, pygame.mask.Mask, msg) + self.assertEqual(mask.get_size(), expected_size, msg) + self.assertEqual(mask.count(), expected_count, msg) + self.assertEqual( + mask.overlap_area(expected_mask, offset), expected_count, msg + ) + + def test_from_surface__different_alphas_16bit(self): + """Ensures from_surface creates a mask with the correct bits set + when pixels have different alpha values (16 bit surfaces). + + This test checks the masks created by the from_surface function using + a 16 bit surface. Each pixel of the surface is set with a different + alpha value (0-255), but since this is a 16 bit surface the requested + alpha value can differ from what is actually set. The resulting surface + will have groups of alpha values which complicates the test as the + alpha groups will all be set/unset at a given threshold. The setup + calculates these groups and an expected mask for each. This test data + is then used to test each alpha grouping over a range of threshold + values. + """ + threshold_count = 256 + surface_color = [110, 120, 130, 0] + expected_size = (threshold_count, 1) + surface = pygame.Surface(expected_size, SRCALPHA, 16) + + # Give each pixel a different alpha. + surface.lock() # Lock for possible speed up. + for a in range(threshold_count): + surface_color[3] = a + surface.set_at((a, 0), surface_color) + surface.unlock() + + alpha_thresholds = OrderedDict() + special_thresholds = set() + + # Create the threshold ranges and identify any thresholds that need + # special handling. + for threshold in range(threshold_count): + # On surfaces with depths < 32 the requested alpha can be different + # than what gets set. Use the value read from the surface. + alpha = surface.get_at((threshold, 0))[3] + + if alpha not in alpha_thresholds: + alpha_thresholds[alpha] = [threshold] + else: + alpha_thresholds[alpha].append(threshold) + + if threshold < alpha: + special_thresholds.add(threshold) + + # Use each threshold group to create an expected mask. + test_data = [] # [(from_threshold, to_threshold, expected_mask), ...] + offset = (0, 0) + erase_mask = pygame.Mask(expected_size) + exp_mask = pygame.Mask(expected_size, fill=True) + + for thresholds in alpha_thresholds.values(): + for threshold in thresholds: + if threshold in special_thresholds: + # Any special thresholds just reuse previous exp_mask. + test_data.append((threshold, threshold + 1, exp_mask)) + else: + to_threshold = thresholds[-1] + 1 + + # Make the expected mask by erasing the unset bits. + for thres in range(to_threshold): + erase_mask.set_at((thres, 0), 1) + + exp_mask = pygame.Mask(expected_size, fill=True) + exp_mask.erase(erase_mask, offset) + test_data.append((threshold, to_threshold, exp_mask)) + break + + # All the setup is done. Now test the masks created over the threshold + # ranges. + for from_threshold, to_threshold, expected_mask in test_data: + expected_count = expected_mask.count() + + for threshold in range(from_threshold, to_threshold): + msg = "threshold={}".format(threshold) + + mask = pygame.mask.from_surface(surface, threshold) + + self.assertIsInstance(mask, pygame.mask.Mask, msg) + self.assertEqual(mask.get_size(), expected_size, msg) + self.assertEqual(mask.count(), expected_count, msg) + self.assertEqual( + mask.overlap_area(expected_mask, offset), expected_count, msg + ) + + def test_from_surface__with_colorkey_mask_cleared(self): + """Ensures from_surface creates a mask with the correct bits set + when the surface uses a colorkey. + + The surface is filled with the colorkey color so the resulting masks + are expected to have no bits set. + """ + colorkeys = ((0, 0, 0), (1, 2, 3), (50, 100, 200), (255, 255, 255)) + expected_size = (7, 11) + expected_count = 0 + + for depth in (8, 16, 24, 32): + msg = "depth={}".format(depth) + surface = pygame.Surface(expected_size, 0, depth) + + for colorkey in colorkeys: + surface.set_colorkey(colorkey) + # With some depths (i.e. 8 and 16) the actual colorkey can be + # different than what was requested via the set. + surface.fill(surface.get_colorkey()) + + mask = pygame.mask.from_surface(surface) + + self.assertIsInstance(mask, pygame.mask.Mask, msg) + self.assertEqual(mask.get_size(), expected_size, msg) + self.assertEqual(mask.count(), expected_count, msg) + + def test_from_surface__with_colorkey_mask_filled(self): + """Ensures from_surface creates a mask with the correct bits set + when the surface uses a colorkey. + + The surface is filled with a color that is not the colorkey color so + the resulting masks are expected to have all bits set. + """ + colorkeys = ((0, 0, 0), (1, 2, 3), (10, 100, 200), (255, 255, 255)) + surface_color = (50, 100, 200) + expected_size = (11, 7) + expected_count = expected_size[0] * expected_size[1] + + for depth in (8, 16, 24, 32): + msg = "depth={}".format(depth) + surface = pygame.Surface(expected_size, 0, depth) + surface.fill(surface_color) + + for colorkey in colorkeys: + surface.set_colorkey(colorkey) + + mask = pygame.mask.from_surface(surface) + + self.assertIsInstance(mask, pygame.mask.Mask, msg) + self.assertEqual(mask.get_size(), expected_size, msg) + self.assertEqual(mask.count(), expected_count, msg) + + def test_from_surface__with_colorkey_mask_pattern(self): + """Ensures from_surface creates a mask with the correct bits set + when the surface uses a colorkey. + + The surface is filled with alternating pixels of colorkey and + non-colorkey colors, so the resulting masks are expected to have + alternating bits set. + """ + + def alternate(func, set_value, unset_value, width, height): + # Helper function to set alternating values. + setbit = False + for pos in ((x, y) for x in range(width) for y in range(height)): + func(pos, set_value if setbit else unset_value) + setbit = not setbit + + surface_color = (5, 10, 20) + colorkey = (50, 60, 70) + expected_size = (11, 2) + expected_mask = pygame.mask.Mask(expected_size) + alternate(expected_mask.set_at, 1, 0, *expected_size) + expected_count = expected_mask.count() + offset = (0, 0) + + for depth in (8, 16, 24, 32): + msg = "depth={}".format(depth) + surface = pygame.Surface(expected_size, 0, depth) + # Fill the surface with alternating colors. + alternate(surface.set_at, surface_color, colorkey, *expected_size) + surface.set_colorkey(colorkey) + + mask = pygame.mask.from_surface(surface) + + self.assertIsInstance(mask, pygame.mask.Mask, msg) + self.assertEqual(mask.get_size(), expected_size, msg) + self.assertEqual(mask.count(), expected_count, msg) + self.assertEqual( + mask.overlap_area(expected_mask, offset), expected_count, msg + ) + + def test_from_threshold(self): + """Does mask.from_threshold() work correctly?""" + + a = [16, 24, 32] + + for i in a: + surf = pygame.surface.Surface((70, 70), 0, i) + surf.fill((100, 50, 200), (20, 20, 20, 20)) + mask = pygame.mask.from_threshold( + surf, (100, 50, 200, 255), (10, 10, 10, 255) + ) + + rects = mask.get_bounding_rects() + + self.assertEqual(mask.count(), 400) + self.assertEqual(mask.get_bounding_rects(), [pygame.Rect((20, 20, 20, 20))]) + + for i in a: + surf = pygame.surface.Surface((70, 70), 0, i) + surf2 = pygame.surface.Surface((70, 70), 0, i) + surf.fill((100, 100, 100)) + surf2.fill((150, 150, 150)) + surf2.fill((100, 100, 100), (40, 40, 10, 10)) + mask = pygame.mask.from_threshold( + surface=surf, + color=(0, 0, 0, 0), + threshold=(10, 10, 10, 255), + othersurface=surf2, + ) + + self.assertIsInstance(mask, pygame.mask.Mask) + self.assertEqual(mask.count(), 100) + self.assertEqual(mask.get_bounding_rects(), [pygame.Rect((40, 40, 10, 10))]) + + def test_zero_size_from_surface(self): + """Ensures from_surface can create masks from zero sized surfaces.""" + for size in ((100, 0), (0, 100), (0, 0)): + mask = pygame.mask.from_surface(pygame.Surface(size)) + + self.assertIsInstance(mask, pygame.mask.MaskType, "size={}".format(size)) + self.assertEqual(mask.get_size(), size) + + def test_zero_size_from_threshold(self): + a = [16, 24, 32] + sizes = ((100, 0), (0, 100), (0, 0)) + + for size in sizes: + for i in a: + surf = pygame.surface.Surface(size, 0, i) + surf.fill((100, 50, 200), (20, 20, 20, 20)) + mask = pygame.mask.from_threshold( + surf, (100, 50, 200, 255), (10, 10, 10, 255) + ) + + self.assertEqual(mask.count(), 0) + + rects = mask.get_bounding_rects() + self.assertEqual(rects, []) + + for i in a: + surf = pygame.surface.Surface(size, 0, i) + surf2 = pygame.surface.Surface(size, 0, i) + surf.fill((100, 100, 100)) + surf2.fill((150, 150, 150)) + surf2.fill((100, 100, 100), (40, 40, 10, 10)) + mask = pygame.mask.from_threshold( + surf, (0, 0, 0, 0), (10, 10, 10, 255), surf2 + ) + + self.assertIsInstance(mask, pygame.mask.Mask) + self.assertEqual(mask.count(), 0) + + rects = mask.get_bounding_rects() + self.assertEqual(rects, []) + + def test_buffer_interface(self): + size = (1000, 100) + pixels_set = ((0, 1), (100, 10), (173, 90)) + pixels_unset = ((0, 0), (101, 10), (173, 91)) + + mask = pygame.Mask(size) + for point in pixels_set: + mask.set_at(point, 1) + + view = memoryview(mask) + intwidth = 8 * view.strides[1] + + for point in pixels_set: + x, y = point + col = x // intwidth + self.assertEqual( + (view[col, y] >> (x % intwidth)) & 1, + 1, + "the pixel at {} is not set to 1".format(point), + ) + + for point in pixels_unset: + x, y = point + col = x // intwidth + self.assertEqual( + (view[col, y] >> (x % intwidth)) & 1, + 0, + "the pixel at {} is not set to 0".format(point), + ) + + +if __name__ == "__main__": + unittest.main() diff --git a/venv/Lib/site-packages/pygame/tests/math_test.py b/venv/Lib/site-packages/pygame/tests/math_test.py new file mode 100644 index 0000000..1d8cd63 --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/math_test.py @@ -0,0 +1,2326 @@ +# -*- coding: utf-8 -*- +import sys +import unittest +import math +import platform + +import pygame.math +from pygame.math import Vector2, Vector3 + +IS_PYPY = "PyPy" == platform.python_implementation() + + +class Vector2TypeTest(unittest.TestCase): + def setUp(self): + self.zeroVec = Vector2() + self.e1 = Vector2(1, 0) + self.e2 = Vector2(0, 1) + self.t1 = (1.2, 3.4) + self.l1 = list(self.t1) + self.v1 = Vector2(self.t1) + self.t2 = (5.6, 7.8) + self.l2 = list(self.t2) + self.v2 = Vector2(self.t2) + self.s1 = 5.6 + self.s2 = 7.8 + + def testConstructionDefault(self): + v = Vector2() + self.assertEqual(v.x, 0.0) + self.assertEqual(v.y, 0.0) + + def testConstructionScalar(self): + v = Vector2(1) + self.assertEqual(v.x, 1.0) + self.assertEqual(v.y, 1.0) + + def testConstructionScalarKeywords(self): + v = Vector2(x=1) + self.assertEqual(v.x, 1.0) + self.assertEqual(v.y, 1.0) + + def testConstructionKeywords(self): + v = Vector2(x=1, y=2) + self.assertEqual(v.x, 1.0) + self.assertEqual(v.y, 2.0) + + def testConstructionXY(self): + v = Vector2(1.2, 3.4) + self.assertEqual(v.x, 1.2) + self.assertEqual(v.y, 3.4) + + def testConstructionTuple(self): + v = Vector2((1.2, 3.4)) + self.assertEqual(v.x, 1.2) + self.assertEqual(v.y, 3.4) + + def testConstructionList(self): + v = Vector2([1.2, 3.4]) + self.assertEqual(v.x, 1.2) + self.assertEqual(v.y, 3.4) + + def testConstructionVector2(self): + v = Vector2(Vector2(1.2, 3.4)) + self.assertEqual(v.x, 1.2) + self.assertEqual(v.y, 3.4) + + def testAttributeAccess(self): + tmp = self.v1.x + self.assertEqual(tmp, self.v1.x) + self.assertEqual(tmp, self.v1[0]) + tmp = self.v1.y + self.assertEqual(tmp, self.v1.y) + self.assertEqual(tmp, self.v1[1]) + self.v1.x = 3.141 + self.assertEqual(self.v1.x, 3.141) + self.v1.y = 3.141 + self.assertEqual(self.v1.y, 3.141) + + def assign_nonfloat(): + v = Vector2() + v.x = "spam" + + self.assertRaises(TypeError, assign_nonfloat) + + def testCopy(self): + v_copy0 = Vector2(2004.0, 2022.0) + v_copy1 = v_copy0.copy() + self.assertEqual(v_copy0.x, v_copy1.x) + self.assertEqual(v_copy0.y, v_copy1.y) + + def testSequence(self): + v = Vector2(1.2, 3.4) + Vector2()[:] + self.assertEqual(len(v), 2) + self.assertEqual(v[0], 1.2) + self.assertEqual(v[1], 3.4) + self.assertRaises(IndexError, lambda: v[2]) + self.assertEqual(v[-1], 3.4) + self.assertEqual(v[-2], 1.2) + self.assertRaises(IndexError, lambda: v[-3]) + self.assertEqual(v[:], [1.2, 3.4]) + self.assertEqual(v[1:], [3.4]) + self.assertEqual(v[:1], [1.2]) + self.assertEqual(list(v), [1.2, 3.4]) + self.assertEqual(tuple(v), (1.2, 3.4)) + v[0] = 5.6 + v[1] = 7.8 + self.assertEqual(v.x, 5.6) + self.assertEqual(v.y, 7.8) + v[:] = [9.1, 11.12] + self.assertEqual(v.x, 9.1) + self.assertEqual(v.y, 11.12) + + def overpopulate(): + v = Vector2() + v[:] = [1, 2, 3] + + self.assertRaises(ValueError, overpopulate) + + def underpopulate(): + v = Vector2() + v[:] = [1] + + self.assertRaises(ValueError, underpopulate) + + def assign_nonfloat(): + v = Vector2() + v[0] = "spam" + + self.assertRaises(TypeError, assign_nonfloat) + + def testExtendedSlicing(self): + # deletion + def delSlice(vec, start=None, stop=None, step=None): + if start is not None and stop is not None and step is not None: + del vec[start:stop:step] + elif start is not None and stop is None and step is not None: + del vec[start::step] + elif start is None and stop is None and step is not None: + del vec[::step] + + v = Vector2(self.v1) + self.assertRaises(TypeError, delSlice, v, None, None, 2) + self.assertRaises(TypeError, delSlice, v, 1, None, 2) + self.assertRaises(TypeError, delSlice, v, 1, 2, 1) + + # assignment + v = Vector2(self.v1) + v[::2] = [-1] + self.assertEqual(v, [-1, self.v1.y]) + v = Vector2(self.v1) + v[::-2] = [10] + self.assertEqual(v, [self.v1.x, 10]) + v = Vector2(self.v1) + v[::-1] = v + self.assertEqual(v, [self.v1.y, self.v1.x]) + a = Vector2(self.v1) + b = Vector2(self.v1) + c = Vector2(self.v1) + a[1:2] = [2.2] + b[slice(1, 2)] = [2.2] + c[1:2:] = (2.2,) + self.assertEqual(a, b) + self.assertEqual(a, c) + self.assertEqual(type(a), type(self.v1)) + self.assertEqual(type(b), type(self.v1)) + self.assertEqual(type(c), type(self.v1)) + + def testAdd(self): + v3 = self.v1 + self.v2 + self.assertTrue(isinstance(v3, type(self.v1))) + self.assertEqual(v3.x, self.v1.x + self.v2.x) + self.assertEqual(v3.y, self.v1.y + self.v2.y) + v3 = self.v1 + self.t2 + self.assertTrue(isinstance(v3, type(self.v1))) + self.assertEqual(v3.x, self.v1.x + self.t2[0]) + self.assertEqual(v3.y, self.v1.y + self.t2[1]) + v3 = self.v1 + self.l2 + self.assertTrue(isinstance(v3, type(self.v1))) + self.assertEqual(v3.x, self.v1.x + self.l2[0]) + self.assertEqual(v3.y, self.v1.y + self.l2[1]) + v3 = self.t1 + self.v2 + self.assertTrue(isinstance(v3, type(self.v1))) + self.assertEqual(v3.x, self.t1[0] + self.v2.x) + self.assertEqual(v3.y, self.t1[1] + self.v2.y) + v3 = self.l1 + self.v2 + self.assertTrue(isinstance(v3, type(self.v1))) + self.assertEqual(v3.x, self.l1[0] + self.v2.x) + self.assertEqual(v3.y, self.l1[1] + self.v2.y) + + def testSub(self): + v3 = self.v1 - self.v2 + self.assertTrue(isinstance(v3, type(self.v1))) + self.assertEqual(v3.x, self.v1.x - self.v2.x) + self.assertEqual(v3.y, self.v1.y - self.v2.y) + v3 = self.v1 - self.t2 + self.assertTrue(isinstance(v3, type(self.v1))) + self.assertEqual(v3.x, self.v1.x - self.t2[0]) + self.assertEqual(v3.y, self.v1.y - self.t2[1]) + v3 = self.v1 - self.l2 + self.assertTrue(isinstance(v3, type(self.v1))) + self.assertEqual(v3.x, self.v1.x - self.l2[0]) + self.assertEqual(v3.y, self.v1.y - self.l2[1]) + v3 = self.t1 - self.v2 + self.assertTrue(isinstance(v3, type(self.v1))) + self.assertEqual(v3.x, self.t1[0] - self.v2.x) + self.assertEqual(v3.y, self.t1[1] - self.v2.y) + v3 = self.l1 - self.v2 + self.assertTrue(isinstance(v3, type(self.v1))) + self.assertEqual(v3.x, self.l1[0] - self.v2.x) + self.assertEqual(v3.y, self.l1[1] - self.v2.y) + + def testScalarMultiplication(self): + v = self.s1 * self.v1 + self.assertTrue(isinstance(v, type(self.v1))) + self.assertEqual(v.x, self.s1 * self.v1.x) + self.assertEqual(v.y, self.s1 * self.v1.y) + v = self.v1 * self.s2 + self.assertEqual(v.x, self.v1.x * self.s2) + self.assertEqual(v.y, self.v1.y * self.s2) + + def testScalarDivision(self): + v = self.v1 / self.s1 + self.assertTrue(isinstance(v, type(self.v1))) + self.assertAlmostEqual(v.x, self.v1.x / self.s1) + self.assertAlmostEqual(v.y, self.v1.y / self.s1) + v = self.v1 // self.s2 + self.assertTrue(isinstance(v, type(self.v1))) + self.assertEqual(v.x, self.v1.x // self.s2) + self.assertEqual(v.y, self.v1.y // self.s2) + + def testBool(self): + self.assertEqual(bool(self.zeroVec), False) + self.assertEqual(bool(self.v1), True) + self.assertTrue(not self.zeroVec) + self.assertTrue(self.v1) + + def testUnary(self): + v = +self.v1 + self.assertTrue(isinstance(v, type(self.v1))) + self.assertEqual(v.x, self.v1.x) + self.assertEqual(v.y, self.v1.y) + self.assertNotEqual(id(v), id(self.v1)) + v = -self.v1 + self.assertTrue(isinstance(v, type(self.v1))) + self.assertEqual(v.x, -self.v1.x) + self.assertEqual(v.y, -self.v1.y) + self.assertNotEqual(id(v), id(self.v1)) + + def testCompare(self): + int_vec = Vector2(3, -2) + flt_vec = Vector2(3.0, -2.0) + zero_vec = Vector2(0, 0) + self.assertEqual(int_vec == flt_vec, True) + self.assertEqual(int_vec != flt_vec, False) + self.assertEqual(int_vec != zero_vec, True) + self.assertEqual(flt_vec == zero_vec, False) + self.assertEqual(int_vec == (3, -2), True) + self.assertEqual(int_vec != (3, -2), False) + self.assertEqual(int_vec != [0, 0], True) + self.assertEqual(int_vec == [0, 0], False) + self.assertEqual(int_vec != 5, True) + self.assertEqual(int_vec == 5, False) + self.assertEqual(int_vec != [3, -2, 0], True) + self.assertEqual(int_vec == [3, -2, 0], False) + + def testStr(self): + v = Vector2(1.2, 3.4) + self.assertEqual(str(v), "[1.2, 3.4]") + + def testRepr(self): + v = Vector2(1.2, 3.4) + self.assertEqual(v.__repr__(), "") + self.assertEqual(v, Vector2(v.__repr__())) + + def testIter(self): + it = self.v1.__iter__() + next_ = it.__next__ + self.assertEqual(next_(), self.v1[0]) + self.assertEqual(next_(), self.v1[1]) + self.assertRaises(StopIteration, lambda: next_()) + it1 = self.v1.__iter__() + it2 = self.v1.__iter__() + self.assertNotEqual(id(it1), id(it2)) + self.assertEqual(id(it1), id(it1.__iter__())) + self.assertEqual(list(it1), list(it2)) + self.assertEqual(list(self.v1.__iter__()), self.l1) + idx = 0 + for val in self.v1: + self.assertEqual(val, self.v1[idx]) + idx += 1 + + def test_rotate(self): + v1 = Vector2(1, 0) + v2 = v1.rotate(90) + v3 = v1.rotate(90 + 360) + self.assertEqual(v1.x, 1) + self.assertEqual(v1.y, 0) + self.assertEqual(v2.x, 0) + self.assertEqual(v2.y, 1) + self.assertEqual(v3.x, v2.x) + self.assertEqual(v3.y, v2.y) + v1 = Vector2(-1, -1) + v2 = v1.rotate(-90) + self.assertEqual(v2.x, -1) + self.assertEqual(v2.y, 1) + v2 = v1.rotate(360) + self.assertEqual(v1.x, v2.x) + self.assertEqual(v1.y, v2.y) + v2 = v1.rotate(0) + self.assertEqual(v1.x, v2.x) + self.assertEqual(v1.y, v2.y) + # issue 214 + self.assertEqual(Vector2(0, 1).rotate(359.99999999), Vector2(0, 1)) + + def test_rotate_rad(self): + tests = ( + ((1, 0), math.pi), + ((1, 0), math.pi / 2), + ((1, 0), -math.pi / 2), + ((1, 0), math.pi / 4), + ) + for initialVec, radians in tests: + self.assertEqual( + Vector2(initialVec).rotate_rad(radians), + (math.cos(radians), math.sin(radians)), + ) + + def test_rotate_ip(self): + v = Vector2(1, 0) + self.assertEqual(v.rotate_ip(90), None) + self.assertEqual(v.x, 0) + self.assertEqual(v.y, 1) + v = Vector2(-1, -1) + v.rotate_ip(-90) + self.assertEqual(v.x, -1) + self.assertEqual(v.y, 1) + + def test_rotate_rad_ip(self): + tests = ( + ((1, 0), math.pi), + ((1, 0), math.pi / 2), + ((1, 0), -math.pi / 2), + ((1, 0), math.pi / 4), + ) + for initialVec, radians in tests: + vec = Vector2(initialVec) + vec.rotate_rad_ip(radians) + self.assertEqual(vec, (math.cos(radians), math.sin(radians))) + + def test_normalize(self): + v = self.v1.normalize() + # length is 1 + self.assertAlmostEqual(v.x * v.x + v.y * v.y, 1.0) + # v1 is unchanged + self.assertEqual(self.v1.x, self.l1[0]) + self.assertEqual(self.v1.y, self.l1[1]) + # v2 is parallel to v1 + self.assertAlmostEqual(self.v1.x * v.y - self.v1.y * v.x, 0.0) + self.assertRaises(ValueError, lambda: self.zeroVec.normalize()) + + def test_normalize_ip(self): + v = +self.v1 + # v has length != 1 before normalizing + self.assertNotEqual(v.x * v.x + v.y * v.y, 1.0) + # inplace operations should return None + self.assertEqual(v.normalize_ip(), None) + # length is 1 + self.assertAlmostEqual(v.x * v.x + v.y * v.y, 1.0) + # v2 is parallel to v1 + self.assertAlmostEqual(self.v1.x * v.y - self.v1.y * v.x, 0.0) + self.assertRaises(ValueError, lambda: self.zeroVec.normalize_ip()) + + def test_is_normalized(self): + self.assertEqual(self.v1.is_normalized(), False) + v = self.v1.normalize() + self.assertEqual(v.is_normalized(), True) + self.assertEqual(self.e2.is_normalized(), True) + self.assertEqual(self.zeroVec.is_normalized(), False) + + def test_cross(self): + self.assertEqual( + self.v1.cross(self.v2), self.v1.x * self.v2.y - self.v1.y * self.v2.x + ) + self.assertEqual( + self.v1.cross(self.l2), self.v1.x * self.l2[1] - self.v1.y * self.l2[0] + ) + self.assertEqual( + self.v1.cross(self.t2), self.v1.x * self.t2[1] - self.v1.y * self.t2[0] + ) + self.assertEqual(self.v1.cross(self.v2), -self.v2.cross(self.v1)) + self.assertEqual(self.v1.cross(self.v1), 0) + + def test_dot(self): + self.assertAlmostEqual( + self.v1.dot(self.v2), self.v1.x * self.v2.x + self.v1.y * self.v2.y + ) + self.assertAlmostEqual( + self.v1.dot(self.l2), self.v1.x * self.l2[0] + self.v1.y * self.l2[1] + ) + self.assertAlmostEqual( + self.v1.dot(self.t2), self.v1.x * self.t2[0] + self.v1.y * self.t2[1] + ) + self.assertEqual(self.v1.dot(self.v2), self.v2.dot(self.v1)) + self.assertEqual(self.v1.dot(self.v2), self.v1 * self.v2) + + def test_angle_to(self): + self.assertEqual( + self.v1.rotate(self.v1.angle_to(self.v2)).normalize(), self.v2.normalize() + ) + self.assertEqual(Vector2(1, 1).angle_to((-1, 1)), 90) + self.assertEqual(Vector2(1, 0).angle_to((0, -1)), -90) + self.assertEqual(Vector2(1, 0).angle_to((-1, 1)), 135) + self.assertEqual(abs(Vector2(1, 0).angle_to((-1, 0))), 180) + + def test_scale_to_length(self): + v = Vector2(1, 1) + v.scale_to_length(2.5) + self.assertEqual(v, Vector2(2.5, 2.5) / math.sqrt(2)) + self.assertRaises(ValueError, lambda: self.zeroVec.scale_to_length(1)) + self.assertEqual(v.scale_to_length(0), None) + self.assertEqual(v, self.zeroVec) + + def test_length(self): + self.assertEqual(Vector2(3, 4).length(), 5) + self.assertEqual(Vector2(-3, 4).length(), 5) + self.assertEqual(self.zeroVec.length(), 0) + + def test_length_squared(self): + self.assertEqual(Vector2(3, 4).length_squared(), 25) + self.assertEqual(Vector2(-3, 4).length_squared(), 25) + self.assertEqual(self.zeroVec.length_squared(), 0) + + def test_reflect(self): + v = Vector2(1, -1) + n = Vector2(0, 1) + self.assertEqual(v.reflect(n), Vector2(1, 1)) + self.assertEqual(v.reflect(3 * n), v.reflect(n)) + self.assertEqual(v.reflect(-v), -v) + self.assertRaises(ValueError, lambda: v.reflect(self.zeroVec)) + + def test_reflect_ip(self): + v1 = Vector2(1, -1) + v2 = Vector2(v1) + n = Vector2(0, 1) + self.assertEqual(v2.reflect_ip(n), None) + self.assertEqual(v2, Vector2(1, 1)) + v2 = Vector2(v1) + v2.reflect_ip(3 * n) + self.assertEqual(v2, v1.reflect(n)) + v2 = Vector2(v1) + v2.reflect_ip(-v1) + self.assertEqual(v2, -v1) + self.assertRaises(ValueError, lambda: v2.reflect_ip(Vector2())) + + def test_distance_to(self): + diff = self.v1 - self.v2 + self.assertEqual(self.e1.distance_to(self.e2), math.sqrt(2)) + self.assertAlmostEqual( + self.v1.distance_to(self.v2), math.sqrt(diff.x * diff.x + diff.y * diff.y) + ) + self.assertEqual(self.v1.distance_to(self.v1), 0) + self.assertEqual(self.v1.distance_to(self.v2), self.v2.distance_to(self.v1)) + + def test_distance_squared_to(self): + diff = self.v1 - self.v2 + self.assertEqual(self.e1.distance_squared_to(self.e2), 2) + self.assertAlmostEqual( + self.v1.distance_squared_to(self.v2), diff.x * diff.x + diff.y * diff.y + ) + self.assertEqual(self.v1.distance_squared_to(self.v1), 0) + self.assertEqual( + self.v1.distance_squared_to(self.v2), self.v2.distance_squared_to(self.v1) + ) + + def test_update(self): + v = Vector2(3, 4) + v.update(0) + self.assertEqual(v, Vector2((0, 0))) + v.update(5, 1) + self.assertEqual(v, Vector2(5, 1)) + v.update((4, 1)) + self.assertNotEqual(v, Vector2((5, 1))) + + def test_swizzle(self): + self.assertEqual(self.v1.yx, (self.v1.y, self.v1.x)) + self.assertEqual( + self.v1.xxyyxy, + (self.v1.x, self.v1.x, self.v1.y, self.v1.y, self.v1.x, self.v1.y), + ) + self.v1.xy = self.t2 + self.assertEqual(self.v1, self.t2) + self.v1.yx = self.t2 + self.assertEqual(self.v1, (self.t2[1], self.t2[0])) + self.assertEqual(type(self.v1), Vector2) + + def invalidSwizzleX(): + Vector2().xx = (1, 2) + + def invalidSwizzleY(): + Vector2().yy = (1, 2) + + self.assertRaises(AttributeError, invalidSwizzleX) + self.assertRaises(AttributeError, invalidSwizzleY) + + def invalidAssignment(): + Vector2().xy = 3 + + self.assertRaises(TypeError, invalidAssignment) + + def unicodeAttribute(): + getattr(Vector2(), "ä") + + self.assertRaises(AttributeError, unicodeAttribute) + + def test_swizzle_return_types(self): + self.assertEqual(type(self.v1.x), float) + self.assertEqual(type(self.v1.xy), Vector2) + self.assertEqual(type(self.v1.xyx), Vector3) + # but we don't have vector4 or above... so tuple. + self.assertEqual(type(self.v1.xyxy), tuple) + self.assertEqual(type(self.v1.xyxyx), tuple) + + def test_elementwise(self): + # behaviour for "elementwise op scalar" + self.assertEqual( + self.v1.elementwise() + self.s1, (self.v1.x + self.s1, self.v1.y + self.s1) + ) + self.assertEqual( + self.v1.elementwise() - self.s1, (self.v1.x - self.s1, self.v1.y - self.s1) + ) + self.assertEqual( + self.v1.elementwise() * self.s2, (self.v1.x * self.s2, self.v1.y * self.s2) + ) + self.assertEqual( + self.v1.elementwise() / self.s2, (self.v1.x / self.s2, self.v1.y / self.s2) + ) + self.assertEqual( + self.v1.elementwise() // self.s1, + (self.v1.x // self.s1, self.v1.y // self.s1), + ) + self.assertEqual( + self.v1.elementwise() ** self.s1, + (self.v1.x ** self.s1, self.v1.y ** self.s1), + ) + self.assertEqual( + self.v1.elementwise() % self.s1, (self.v1.x % self.s1, self.v1.y % self.s1) + ) + self.assertEqual( + self.v1.elementwise() > self.s1, self.v1.x > self.s1 and self.v1.y > self.s1 + ) + self.assertEqual( + self.v1.elementwise() < self.s1, self.v1.x < self.s1 and self.v1.y < self.s1 + ) + self.assertEqual( + self.v1.elementwise() == self.s1, + self.v1.x == self.s1 and self.v1.y == self.s1, + ) + self.assertEqual( + self.v1.elementwise() != self.s1, + self.v1.x != self.s1 and self.v1.y != self.s1, + ) + self.assertEqual( + self.v1.elementwise() >= self.s1, + self.v1.x >= self.s1 and self.v1.y >= self.s1, + ) + self.assertEqual( + self.v1.elementwise() <= self.s1, + self.v1.x <= self.s1 and self.v1.y <= self.s1, + ) + self.assertEqual( + self.v1.elementwise() != self.s1, + self.v1.x != self.s1 and self.v1.y != self.s1, + ) + # behaviour for "scalar op elementwise" + self.assertEqual(5 + self.v1.elementwise(), Vector2(5, 5) + self.v1) + self.assertEqual(3.5 - self.v1.elementwise(), Vector2(3.5, 3.5) - self.v1) + self.assertEqual(7.5 * self.v1.elementwise(), 7.5 * self.v1) + self.assertEqual( + -3.5 / self.v1.elementwise(), (-3.5 / self.v1.x, -3.5 / self.v1.y) + ) + self.assertEqual( + -3.5 // self.v1.elementwise(), (-3.5 // self.v1.x, -3.5 // self.v1.y) + ) + self.assertEqual( + -(3.5 ** self.v1.elementwise()), (-(3.5 ** self.v1.x), -(3.5 ** self.v1.y)) + ) + self.assertEqual(3 % self.v1.elementwise(), (3 % self.v1.x, 3 % self.v1.y)) + self.assertEqual(2 < self.v1.elementwise(), 2 < self.v1.x and 2 < self.v1.y) + self.assertEqual(2 > self.v1.elementwise(), 2 > self.v1.x and 2 > self.v1.y) + self.assertEqual(1 == self.v1.elementwise(), 1 == self.v1.x and 1 == self.v1.y) + self.assertEqual(1 != self.v1.elementwise(), 1 != self.v1.x and 1 != self.v1.y) + self.assertEqual(2 <= self.v1.elementwise(), 2 <= self.v1.x and 2 <= self.v1.y) + self.assertEqual( + -7 >= self.v1.elementwise(), -7 >= self.v1.x and -7 >= self.v1.y + ) + self.assertEqual( + -7 != self.v1.elementwise(), -7 != self.v1.x and -7 != self.v1.y + ) + + # behaviour for "elementwise op vector" + self.assertEqual(type(self.v1.elementwise() * self.v2), type(self.v1)) + self.assertEqual(self.v1.elementwise() + self.v2, self.v1 + self.v2) + self.assertEqual(self.v1.elementwise() + self.v2, self.v1 + self.v2) + self.assertEqual(self.v1.elementwise() - self.v2, self.v1 - self.v2) + self.assertEqual( + self.v1.elementwise() * self.v2, + (self.v1.x * self.v2.x, self.v1.y * self.v2.y), + ) + self.assertEqual( + self.v1.elementwise() / self.v2, + (self.v1.x / self.v2.x, self.v1.y / self.v2.y), + ) + self.assertEqual( + self.v1.elementwise() // self.v2, + (self.v1.x // self.v2.x, self.v1.y // self.v2.y), + ) + self.assertEqual( + self.v1.elementwise() ** self.v2, + (self.v1.x ** self.v2.x, self.v1.y ** self.v2.y), + ) + self.assertEqual( + self.v1.elementwise() % self.v2, + (self.v1.x % self.v2.x, self.v1.y % self.v2.y), + ) + self.assertEqual( + self.v1.elementwise() > self.v2, + self.v1.x > self.v2.x and self.v1.y > self.v2.y, + ) + self.assertEqual( + self.v1.elementwise() < self.v2, + self.v1.x < self.v2.x and self.v1.y < self.v2.y, + ) + self.assertEqual( + self.v1.elementwise() >= self.v2, + self.v1.x >= self.v2.x and self.v1.y >= self.v2.y, + ) + self.assertEqual( + self.v1.elementwise() <= self.v2, + self.v1.x <= self.v2.x and self.v1.y <= self.v2.y, + ) + self.assertEqual( + self.v1.elementwise() == self.v2, + self.v1.x == self.v2.x and self.v1.y == self.v2.y, + ) + self.assertEqual( + self.v1.elementwise() != self.v2, + self.v1.x != self.v2.x and self.v1.y != self.v2.y, + ) + # behaviour for "vector op elementwise" + self.assertEqual(self.v2 + self.v1.elementwise(), self.v2 + self.v1) + self.assertEqual(self.v2 - self.v1.elementwise(), self.v2 - self.v1) + self.assertEqual( + self.v2 * self.v1.elementwise(), + (self.v2.x * self.v1.x, self.v2.y * self.v1.y), + ) + self.assertEqual( + self.v2 / self.v1.elementwise(), + (self.v2.x / self.v1.x, self.v2.y / self.v1.y), + ) + self.assertEqual( + self.v2 // self.v1.elementwise(), + (self.v2.x // self.v1.x, self.v2.y // self.v1.y), + ) + self.assertEqual( + self.v2 ** self.v1.elementwise(), + (self.v2.x ** self.v1.x, self.v2.y ** self.v1.y), + ) + self.assertEqual( + self.v2 % self.v1.elementwise(), + (self.v2.x % self.v1.x, self.v2.y % self.v1.y), + ) + self.assertEqual( + self.v2 < self.v1.elementwise(), + self.v2.x < self.v1.x and self.v2.y < self.v1.y, + ) + self.assertEqual( + self.v2 > self.v1.elementwise(), + self.v2.x > self.v1.x and self.v2.y > self.v1.y, + ) + self.assertEqual( + self.v2 <= self.v1.elementwise(), + self.v2.x <= self.v1.x and self.v2.y <= self.v1.y, + ) + self.assertEqual( + self.v2 >= self.v1.elementwise(), + self.v2.x >= self.v1.x and self.v2.y >= self.v1.y, + ) + self.assertEqual( + self.v2 == self.v1.elementwise(), + self.v2.x == self.v1.x and self.v2.y == self.v1.y, + ) + self.assertEqual( + self.v2 != self.v1.elementwise(), + self.v2.x != self.v1.x and self.v2.y != self.v1.y, + ) + + # behaviour for "elementwise op elementwise" + self.assertEqual( + self.v2.elementwise() + self.v1.elementwise(), self.v2 + self.v1 + ) + self.assertEqual( + self.v2.elementwise() - self.v1.elementwise(), self.v2 - self.v1 + ) + self.assertEqual( + self.v2.elementwise() * self.v1.elementwise(), + (self.v2.x * self.v1.x, self.v2.y * self.v1.y), + ) + self.assertEqual( + self.v2.elementwise() / self.v1.elementwise(), + (self.v2.x / self.v1.x, self.v2.y / self.v1.y), + ) + self.assertEqual( + self.v2.elementwise() // self.v1.elementwise(), + (self.v2.x // self.v1.x, self.v2.y // self.v1.y), + ) + self.assertEqual( + self.v2.elementwise() ** self.v1.elementwise(), + (self.v2.x ** self.v1.x, self.v2.y ** self.v1.y), + ) + self.assertEqual( + self.v2.elementwise() % self.v1.elementwise(), + (self.v2.x % self.v1.x, self.v2.y % self.v1.y), + ) + self.assertEqual( + self.v2.elementwise() < self.v1.elementwise(), + self.v2.x < self.v1.x and self.v2.y < self.v1.y, + ) + self.assertEqual( + self.v2.elementwise() > self.v1.elementwise(), + self.v2.x > self.v1.x and self.v2.y > self.v1.y, + ) + self.assertEqual( + self.v2.elementwise() <= self.v1.elementwise(), + self.v2.x <= self.v1.x and self.v2.y <= self.v1.y, + ) + self.assertEqual( + self.v2.elementwise() >= self.v1.elementwise(), + self.v2.x >= self.v1.x and self.v2.y >= self.v1.y, + ) + self.assertEqual( + self.v2.elementwise() == self.v1.elementwise(), + self.v2.x == self.v1.x and self.v2.y == self.v1.y, + ) + self.assertEqual( + self.v2.elementwise() != self.v1.elementwise(), + self.v2.x != self.v1.x and self.v2.y != self.v1.y, + ) + + # other behaviour + self.assertEqual(abs(self.v1.elementwise()), (abs(self.v1.x), abs(self.v1.y))) + self.assertEqual(-self.v1.elementwise(), -self.v1) + self.assertEqual(+self.v1.elementwise(), +self.v1) + self.assertEqual(bool(self.v1.elementwise()), bool(self.v1)) + self.assertEqual(bool(Vector2().elementwise()), bool(Vector2())) + self.assertEqual(self.zeroVec.elementwise() ** 0, (1, 1)) + self.assertRaises(ValueError, lambda: pow(Vector2(-1, 0).elementwise(), 1.2)) + self.assertRaises(ZeroDivisionError, lambda: self.zeroVec.elementwise() ** -1) + + def test_elementwise(self): + v1 = self.v1 + v2 = self.v2 + s1 = self.s1 + s2 = self.s2 + # behaviour for "elementwise op scalar" + self.assertEqual(v1.elementwise() + s1, (v1.x + s1, v1.y + s1)) + self.assertEqual(v1.elementwise() - s1, (v1.x - s1, v1.y - s1)) + self.assertEqual(v1.elementwise() * s2, (v1.x * s2, v1.y * s2)) + self.assertEqual(v1.elementwise() / s2, (v1.x / s2, v1.y / s2)) + self.assertEqual(v1.elementwise() // s1, (v1.x // s1, v1.y // s1)) + self.assertEqual(v1.elementwise() ** s1, (v1.x ** s1, v1.y ** s1)) + self.assertEqual(v1.elementwise() % s1, (v1.x % s1, v1.y % s1)) + self.assertEqual(v1.elementwise() > s1, v1.x > s1 and v1.y > s1) + self.assertEqual(v1.elementwise() < s1, v1.x < s1 and v1.y < s1) + self.assertEqual(v1.elementwise() == s1, v1.x == s1 and v1.y == s1) + self.assertEqual(v1.elementwise() != s1, s1 not in [v1.x, v1.y]) + self.assertEqual(v1.elementwise() >= s1, v1.x >= s1 and v1.y >= s1) + self.assertEqual(v1.elementwise() <= s1, v1.x <= s1 and v1.y <= s1) + self.assertEqual(v1.elementwise() != s1, s1 not in [v1.x, v1.y]) + # behaviour for "scalar op elementwise" + self.assertEqual(s1 + v1.elementwise(), (s1 + v1.x, s1 + v1.y)) + self.assertEqual(s1 - v1.elementwise(), (s1 - v1.x, s1 - v1.y)) + self.assertEqual(s1 * v1.elementwise(), (s1 * v1.x, s1 * v1.y)) + self.assertEqual(s1 / v1.elementwise(), (s1 / v1.x, s1 / v1.y)) + self.assertEqual(s1 // v1.elementwise(), (s1 // v1.x, s1 // v1.y)) + self.assertEqual(s1 ** v1.elementwise(), (s1 ** v1.x, s1 ** v1.y)) + self.assertEqual(s1 % v1.elementwise(), (s1 % v1.x, s1 % v1.y)) + self.assertEqual(s1 < v1.elementwise(), s1 < v1.x and s1 < v1.y) + self.assertEqual(s1 > v1.elementwise(), s1 > v1.x and s1 > v1.y) + self.assertEqual(s1 == v1.elementwise(), s1 == v1.x and s1 == v1.y) + self.assertEqual(s1 != v1.elementwise(), s1 not in [v1.x, v1.y]) + self.assertEqual(s1 <= v1.elementwise(), s1 <= v1.x and s1 <= v1.y) + self.assertEqual(s1 >= v1.elementwise(), s1 >= v1.x and s1 >= v1.y) + self.assertEqual(s1 != v1.elementwise(), s1 not in [v1.x, v1.y]) + + # behaviour for "elementwise op vector" + self.assertEqual(type(v1.elementwise() * v2), type(v1)) + self.assertEqual(v1.elementwise() + v2, v1 + v2) + self.assertEqual(v1.elementwise() - v2, v1 - v2) + self.assertEqual(v1.elementwise() * v2, (v1.x * v2.x, v1.y * v2.y)) + self.assertEqual(v1.elementwise() / v2, (v1.x / v2.x, v1.y / v2.y)) + self.assertEqual(v1.elementwise() // v2, (v1.x // v2.x, v1.y // v2.y)) + self.assertEqual(v1.elementwise() ** v2, (v1.x ** v2.x, v1.y ** v2.y)) + self.assertEqual(v1.elementwise() % v2, (v1.x % v2.x, v1.y % v2.y)) + self.assertEqual(v1.elementwise() > v2, v1.x > v2.x and v1.y > v2.y) + self.assertEqual(v1.elementwise() < v2, v1.x < v2.x and v1.y < v2.y) + self.assertEqual(v1.elementwise() >= v2, v1.x >= v2.x and v1.y >= v2.y) + self.assertEqual(v1.elementwise() <= v2, v1.x <= v2.x and v1.y <= v2.y) + self.assertEqual(v1.elementwise() == v2, v1.x == v2.x and v1.y == v2.y) + self.assertEqual(v1.elementwise() != v2, v1.x != v2.x and v1.y != v2.y) + # behaviour for "vector op elementwise" + self.assertEqual(v2 + v1.elementwise(), v2 + v1) + self.assertEqual(v2 - v1.elementwise(), v2 - v1) + self.assertEqual(v2 * v1.elementwise(), (v2.x * v1.x, v2.y * v1.y)) + self.assertEqual(v2 / v1.elementwise(), (v2.x / v1.x, v2.y / v1.y)) + self.assertEqual(v2 // v1.elementwise(), (v2.x // v1.x, v2.y // v1.y)) + self.assertEqual(v2 ** v1.elementwise(), (v2.x ** v1.x, v2.y ** v1.y)) + self.assertEqual(v2 % v1.elementwise(), (v2.x % v1.x, v2.y % v1.y)) + self.assertEqual(v2 < v1.elementwise(), v2.x < v1.x and v2.y < v1.y) + self.assertEqual(v2 > v1.elementwise(), v2.x > v1.x and v2.y > v1.y) + self.assertEqual(v2 <= v1.elementwise(), v2.x <= v1.x and v2.y <= v1.y) + self.assertEqual(v2 >= v1.elementwise(), v2.x >= v1.x and v2.y >= v1.y) + self.assertEqual(v2 == v1.elementwise(), v2.x == v1.x and v2.y == v1.y) + self.assertEqual(v2 != v1.elementwise(), v2.x != v1.x and v2.y != v1.y) + + # behaviour for "elementwise op elementwise" + self.assertEqual(v2.elementwise() + v1.elementwise(), v2 + v1) + self.assertEqual(v2.elementwise() - v1.elementwise(), v2 - v1) + self.assertEqual( + v2.elementwise() * v1.elementwise(), (v2.x * v1.x, v2.y * v1.y) + ) + self.assertEqual( + v2.elementwise() / v1.elementwise(), (v2.x / v1.x, v2.y / v1.y) + ) + self.assertEqual( + v2.elementwise() // v1.elementwise(), (v2.x // v1.x, v2.y // v1.y) + ) + self.assertEqual( + v2.elementwise() ** v1.elementwise(), (v2.x ** v1.x, v2.y ** v1.y) + ) + self.assertEqual( + v2.elementwise() % v1.elementwise(), (v2.x % v1.x, v2.y % v1.y) + ) + self.assertEqual( + v2.elementwise() < v1.elementwise(), v2.x < v1.x and v2.y < v1.y + ) + self.assertEqual( + v2.elementwise() > v1.elementwise(), v2.x > v1.x and v2.y > v1.y + ) + self.assertEqual( + v2.elementwise() <= v1.elementwise(), v2.x <= v1.x and v2.y <= v1.y + ) + self.assertEqual( + v2.elementwise() >= v1.elementwise(), v2.x >= v1.x and v2.y >= v1.y + ) + self.assertEqual( + v2.elementwise() == v1.elementwise(), v2.x == v1.x and v2.y == v1.y + ) + self.assertEqual( + v2.elementwise() != v1.elementwise(), v2.x != v1.x and v2.y != v1.y + ) + + # other behaviour + self.assertEqual(abs(v1.elementwise()), (abs(v1.x), abs(v1.y))) + self.assertEqual(-v1.elementwise(), -v1) + self.assertEqual(+v1.elementwise(), +v1) + self.assertEqual(bool(v1.elementwise()), bool(v1)) + self.assertEqual(bool(Vector2().elementwise()), bool(Vector2())) + self.assertEqual(self.zeroVec.elementwise() ** 0, (1, 1)) + self.assertRaises(ValueError, lambda: pow(Vector2(-1, 0).elementwise(), 1.2)) + self.assertRaises(ZeroDivisionError, lambda: self.zeroVec.elementwise() ** -1) + self.assertRaises(ZeroDivisionError, lambda: self.zeroVec.elementwise() ** -1) + self.assertRaises(ZeroDivisionError, lambda: Vector2(1, 1).elementwise() / 0) + self.assertRaises(ZeroDivisionError, lambda: Vector2(1, 1).elementwise() // 0) + self.assertRaises(ZeroDivisionError, lambda: Vector2(1, 1).elementwise() % 0) + self.assertRaises( + ZeroDivisionError, lambda: Vector2(1, 1).elementwise() / self.zeroVec + ) + self.assertRaises( + ZeroDivisionError, lambda: Vector2(1, 1).elementwise() // self.zeroVec + ) + self.assertRaises( + ZeroDivisionError, lambda: Vector2(1, 1).elementwise() % self.zeroVec + ) + self.assertRaises(ZeroDivisionError, lambda: 2 / self.zeroVec.elementwise()) + self.assertRaises(ZeroDivisionError, lambda: 2 // self.zeroVec.elementwise()) + self.assertRaises(ZeroDivisionError, lambda: 2 % self.zeroVec.elementwise()) + + def test_slerp(self): + self.assertRaises(ValueError, lambda: self.zeroVec.slerp(self.v1, 0.5)) + self.assertRaises(ValueError, lambda: self.v1.slerp(self.zeroVec, 0.5)) + self.assertRaises(ValueError, lambda: self.zeroVec.slerp(self.zeroVec, 0.5)) + v1 = Vector2(1, 0) + v2 = Vector2(0, 1) + steps = 10 + angle_step = v1.angle_to(v2) / steps + for i, u in ((i, v1.slerp(v2, i / float(steps))) for i in range(steps + 1)): + self.assertAlmostEqual(u.length(), 1) + self.assertAlmostEqual(v1.angle_to(u), i * angle_step) + self.assertEqual(u, v2) + + v1 = Vector2(100, 0) + v2 = Vector2(0, 10) + radial_factor = v2.length() / v1.length() + for i, u in ((i, v1.slerp(v2, -i / float(steps))) for i in range(steps + 1)): + self.assertAlmostEqual( + u.length(), + (v2.length() - v1.length()) * (float(i) / steps) + v1.length(), + ) + self.assertEqual(u, v2) + self.assertEqual(v1.slerp(v1, 0.5), v1) + self.assertEqual(v2.slerp(v2, 0.5), v2) + self.assertRaises(ValueError, lambda: v1.slerp(-v1, 0.5)) + + def test_lerp(self): + v1 = Vector2(0, 0) + v2 = Vector2(10, 10) + self.assertEqual(v1.lerp(v2, 0.5), (5, 5)) + self.assertRaises(ValueError, lambda: v1.lerp(v2, 2.5)) + + v1 = Vector2(-10, -5) + v2 = Vector2(10, 10) + self.assertEqual(v1.lerp(v2, 0.5), (0, 2.5)) + + def test_polar(self): + v = Vector2() + v.from_polar(self.v1.as_polar()) + self.assertEqual(self.v1, v) + self.assertEqual(self.e1.as_polar(), (1, 0)) + self.assertEqual(self.e2.as_polar(), (1, 90)) + self.assertEqual((2 * self.e2).as_polar(), (2, 90)) + self.assertRaises(TypeError, lambda: v.from_polar((None, None))) + self.assertRaises(TypeError, lambda: v.from_polar("ab")) + self.assertRaises(TypeError, lambda: v.from_polar((None, 1))) + self.assertRaises(TypeError, lambda: v.from_polar((1, 2, 3))) + self.assertRaises(TypeError, lambda: v.from_polar((1,))) + self.assertRaises(TypeError, lambda: v.from_polar(1, 2)) + v.from_polar((0.5, 90)) + self.assertEqual(v, 0.5 * self.e2) + v.from_polar((1, 0)) + self.assertEqual(v, self.e1) + + def test_subclass_operation(self): + class Vector(pygame.math.Vector2): + pass + + vec = Vector() + + vec_a = Vector(2, 0) + vec_b = Vector(0, 1) + + vec_a + vec_b + vec_a *= 2 + + def test_project_v2_onto_x_axis(self): + """Project onto x-axis, e.g. get the component pointing in the x-axis direction.""" + # arrange + v = Vector2(2, 2) + x_axis = Vector2(10, 0) + + # act + actual = v.project(x_axis) + + # assert + self.assertEqual(v.x, actual.x) + self.assertEqual(0, actual.y) + + def test_project_v2_onto_y_axis(self): + """Project onto y-axis, e.g. get the component pointing in the y-axis direction.""" + # arrange + v = Vector2(2, 2) + y_axis = Vector2(0, 100) + + # act + actual = v.project(y_axis) + + # assert + self.assertEqual(0, actual.x) + self.assertEqual(v.y, actual.y) + + def test_project_v2_onto_other(self): + """Project onto other vector.""" + # arrange + v = Vector2(2, 3) + other = Vector2(3, 5) + + # act + actual = v.project(other) + + # assert + expected = v.dot(other) / other.dot(other) * other + self.assertEqual(expected.x, actual.x) + self.assertEqual(expected.y, actual.y) + + def test_project_v2_raises_if_other_has_zero_length(self): + """Check if exception is raise when projected on vector has zero length.""" + # arrange + v = Vector2(2, 3) + other = Vector2(0, 0) + + # act / assert + self.assertRaises(ValueError, v.project, other) + + def test_project_v2_onto_other_as_tuple(self): + """Project onto other tuple as vector.""" + # arrange + v = Vector2(2, 3) + other = Vector2(3, 5) + + # act + actual = v.project(tuple(other)) + + # assert + expected = v.dot(other) / other.dot(other) * other + self.assertEqual(expected.x, actual.x) + self.assertEqual(expected.y, actual.y) + + def test_project_v2_onto_other_as_list(self): + """Project onto other list as vector.""" + # arrange + v = Vector2(2, 3) + other = Vector2(3, 5) + + # act + actual = v.project(list(other)) + + # assert + expected = v.dot(other) / other.dot(other) * other + self.assertEqual(expected.x, actual.x) + self.assertEqual(expected.y, actual.y) + + def test_project_v2_raises_if_other_has_zero_length(self): + """Check if exception is raise when projected on vector has zero length.""" + # arrange + v = Vector2(2, 3) + other = Vector2(0, 0) + + # act / assert + self.assertRaises(ValueError, v.project, other) + + def test_project_v2_raises_if_other_is_not_iterable(self): + """Check if exception is raise when projected on vector is not iterable.""" + # arrange + v = Vector2(2, 3) + other = 10 + + # act / assert + self.assertRaises(TypeError, v.project, other) + + +class Vector3TypeTest(unittest.TestCase): + def setUp(self): + self.zeroVec = Vector3() + self.e1 = Vector3(1, 0, 0) + self.e2 = Vector3(0, 1, 0) + self.e3 = Vector3(0, 0, 1) + self.t1 = (1.2, 3.4, 9.6) + self.l1 = list(self.t1) + self.v1 = Vector3(self.t1) + self.t2 = (5.6, 7.8, 2.1) + self.l2 = list(self.t2) + self.v2 = Vector3(self.t2) + self.s1 = 5.6 + self.s2 = 7.8 + + def testConstructionDefault(self): + v = Vector3() + self.assertEqual(v.x, 0.0) + self.assertEqual(v.y, 0.0) + self.assertEqual(v.z, 0.0) + + def testConstructionXYZ(self): + v = Vector3(1.2, 3.4, 9.6) + self.assertEqual(v.x, 1.2) + self.assertEqual(v.y, 3.4) + self.assertEqual(v.z, 9.6) + + def testConstructionTuple(self): + v = Vector3((1.2, 3.4, 9.6)) + self.assertEqual(v.x, 1.2) + self.assertEqual(v.y, 3.4) + self.assertEqual(v.z, 9.6) + + def testConstructionList(self): + v = Vector3([1.2, 3.4, -9.6]) + self.assertEqual(v.x, 1.2) + self.assertEqual(v.y, 3.4) + self.assertEqual(v.z, -9.6) + + def testConstructionVector3(self): + v = Vector3(Vector3(1.2, 3.4, -9.6)) + self.assertEqual(v.x, 1.2) + self.assertEqual(v.y, 3.4) + self.assertEqual(v.z, -9.6) + + def testConstructionScalar(self): + v = Vector3(1) + self.assertEqual(v.x, 1.0) + self.assertEqual(v.y, 1.0) + self.assertEqual(v.z, 1.0) + + def testConstructionScalarKeywords(self): + v = Vector3(x=1) + self.assertEqual(v.x, 1.0) + self.assertEqual(v.y, 1.0) + self.assertEqual(v.z, 1.0) + + def testConstructionKeywords(self): + v = Vector3(x=1, y=2, z=3) + self.assertEqual(v.x, 1.0) + self.assertEqual(v.y, 2.0) + self.assertEqual(v.z, 3.0) + + def testConstructionMissing(self): + def assign_missing_value(): + v = Vector3(1, 2) + + self.assertRaises(ValueError, assign_missing_value) + + def assign_missing_value(): + v = Vector3(x=1, y=2) + + self.assertRaises(ValueError, assign_missing_value) + + def testAttributeAccess(self): + tmp = self.v1.x + self.assertEqual(tmp, self.v1.x) + self.assertEqual(tmp, self.v1[0]) + tmp = self.v1.y + self.assertEqual(tmp, self.v1.y) + self.assertEqual(tmp, self.v1[1]) + tmp = self.v1.z + self.assertEqual(tmp, self.v1.z) + self.assertEqual(tmp, self.v1[2]) + self.v1.x = 3.141 + self.assertEqual(self.v1.x, 3.141) + self.v1.y = 3.141 + self.assertEqual(self.v1.y, 3.141) + self.v1.z = 3.141 + self.assertEqual(self.v1.z, 3.141) + + def assign_nonfloat(): + v = Vector2() + v.x = "spam" + + self.assertRaises(TypeError, assign_nonfloat) + + def testSequence(self): + v = Vector3(1.2, 3.4, -9.6) + self.assertEqual(len(v), 3) + self.assertEqual(v[0], 1.2) + self.assertEqual(v[1], 3.4) + self.assertEqual(v[2], -9.6) + self.assertRaises(IndexError, lambda: v[3]) + self.assertEqual(v[-1], -9.6) + self.assertEqual(v[-2], 3.4) + self.assertEqual(v[-3], 1.2) + self.assertRaises(IndexError, lambda: v[-4]) + self.assertEqual(v[:], [1.2, 3.4, -9.6]) + self.assertEqual(v[1:], [3.4, -9.6]) + self.assertEqual(v[:1], [1.2]) + self.assertEqual(v[:-1], [1.2, 3.4]) + self.assertEqual(v[1:2], [3.4]) + self.assertEqual(list(v), [1.2, 3.4, -9.6]) + self.assertEqual(tuple(v), (1.2, 3.4, -9.6)) + v[0] = 5.6 + v[1] = 7.8 + v[2] = -2.1 + self.assertEqual(v.x, 5.6) + self.assertEqual(v.y, 7.8) + self.assertEqual(v.z, -2.1) + v[:] = [9.1, 11.12, -13.41] + self.assertEqual(v.x, 9.1) + self.assertEqual(v.y, 11.12) + self.assertEqual(v.z, -13.41) + + def overpopulate(): + v = Vector3() + v[:] = [1, 2, 3, 4] + + self.assertRaises(ValueError, overpopulate) + + def underpopulate(): + v = Vector3() + v[:] = [1] + + self.assertRaises(ValueError, underpopulate) + + def assign_nonfloat(): + v = Vector2() + v[0] = "spam" + + self.assertRaises(TypeError, assign_nonfloat) + + def testExtendedSlicing(self): + # deletion + def delSlice(vec, start=None, stop=None, step=None): + if start is not None and stop is not None and step is not None: + del vec[start:stop:step] + elif start is not None and stop is None and step is not None: + del vec[start::step] + elif start is None and stop is None and step is not None: + del vec[::step] + + v = Vector3(self.v1) + self.assertRaises(TypeError, delSlice, v, None, None, 2) + self.assertRaises(TypeError, delSlice, v, 1, None, 2) + self.assertRaises(TypeError, delSlice, v, 1, 2, 1) + + # assignment + v = Vector3(self.v1) + v[::2] = [-1.1, -2.2] + self.assertEqual(v, [-1.1, self.v1.y, -2.2]) + v = Vector3(self.v1) + v[::-2] = [10, 20] + self.assertEqual(v, [20, self.v1.y, 10]) + v = Vector3(self.v1) + v[::-1] = v + self.assertEqual(v, [self.v1.z, self.v1.y, self.v1.x]) + a = Vector3(self.v1) + b = Vector3(self.v1) + c = Vector3(self.v1) + a[1:2] = [2.2] + b[slice(1, 2)] = [2.2] + c[1:2:] = (2.2,) + self.assertEqual(a, b) + self.assertEqual(a, c) + self.assertEqual(type(a), type(self.v1)) + self.assertEqual(type(b), type(self.v1)) + self.assertEqual(type(c), type(self.v1)) + + def testAdd(self): + v3 = self.v1 + self.v2 + self.assertTrue(isinstance(v3, type(self.v1))) + self.assertEqual(v3.x, self.v1.x + self.v2.x) + self.assertEqual(v3.y, self.v1.y + self.v2.y) + self.assertEqual(v3.z, self.v1.z + self.v2.z) + v3 = self.v1 + self.t2 + self.assertTrue(isinstance(v3, type(self.v1))) + self.assertEqual(v3.x, self.v1.x + self.t2[0]) + self.assertEqual(v3.y, self.v1.y + self.t2[1]) + self.assertEqual(v3.z, self.v1.z + self.t2[2]) + v3 = self.v1 + self.l2 + self.assertTrue(isinstance(v3, type(self.v1))) + self.assertEqual(v3.x, self.v1.x + self.l2[0]) + self.assertEqual(v3.y, self.v1.y + self.l2[1]) + self.assertEqual(v3.z, self.v1.z + self.l2[2]) + v3 = self.t1 + self.v2 + self.assertTrue(isinstance(v3, type(self.v1))) + self.assertEqual(v3.x, self.t1[0] + self.v2.x) + self.assertEqual(v3.y, self.t1[1] + self.v2.y) + self.assertEqual(v3.z, self.t1[2] + self.v2.z) + v3 = self.l1 + self.v2 + self.assertTrue(isinstance(v3, type(self.v1))) + self.assertEqual(v3.x, self.l1[0] + self.v2.x) + self.assertEqual(v3.y, self.l1[1] + self.v2.y) + self.assertEqual(v3.z, self.l1[2] + self.v2.z) + + def testSub(self): + v3 = self.v1 - self.v2 + self.assertTrue(isinstance(v3, type(self.v1))) + self.assertEqual(v3.x, self.v1.x - self.v2.x) + self.assertEqual(v3.y, self.v1.y - self.v2.y) + self.assertEqual(v3.z, self.v1.z - self.v2.z) + v3 = self.v1 - self.t2 + self.assertTrue(isinstance(v3, type(self.v1))) + self.assertEqual(v3.x, self.v1.x - self.t2[0]) + self.assertEqual(v3.y, self.v1.y - self.t2[1]) + self.assertEqual(v3.z, self.v1.z - self.t2[2]) + v3 = self.v1 - self.l2 + self.assertTrue(isinstance(v3, type(self.v1))) + self.assertEqual(v3.x, self.v1.x - self.l2[0]) + self.assertEqual(v3.y, self.v1.y - self.l2[1]) + self.assertEqual(v3.z, self.v1.z - self.l2[2]) + v3 = self.t1 - self.v2 + self.assertTrue(isinstance(v3, type(self.v1))) + self.assertEqual(v3.x, self.t1[0] - self.v2.x) + self.assertEqual(v3.y, self.t1[1] - self.v2.y) + self.assertEqual(v3.z, self.t1[2] - self.v2.z) + v3 = self.l1 - self.v2 + self.assertTrue(isinstance(v3, type(self.v1))) + self.assertEqual(v3.x, self.l1[0] - self.v2.x) + self.assertEqual(v3.y, self.l1[1] - self.v2.y) + self.assertEqual(v3.z, self.l1[2] - self.v2.z) + + def testScalarMultiplication(self): + v = self.s1 * self.v1 + self.assertTrue(isinstance(v, type(self.v1))) + self.assertEqual(v.x, self.s1 * self.v1.x) + self.assertEqual(v.y, self.s1 * self.v1.y) + self.assertEqual(v.z, self.s1 * self.v1.z) + v = self.v1 * self.s2 + self.assertEqual(v.x, self.v1.x * self.s2) + self.assertEqual(v.y, self.v1.y * self.s2) + self.assertEqual(v.z, self.v1.z * self.s2) + + def testScalarDivision(self): + v = self.v1 / self.s1 + self.assertTrue(isinstance(v, type(self.v1))) + self.assertAlmostEqual(v.x, self.v1.x / self.s1) + self.assertAlmostEqual(v.y, self.v1.y / self.s1) + self.assertAlmostEqual(v.z, self.v1.z / self.s1) + v = self.v1 // self.s2 + self.assertTrue(isinstance(v, type(self.v1))) + self.assertEqual(v.x, self.v1.x // self.s2) + self.assertEqual(v.y, self.v1.y // self.s2) + self.assertEqual(v.z, self.v1.z // self.s2) + + def testBool(self): + self.assertEqual(bool(self.zeroVec), False) + self.assertEqual(bool(self.v1), True) + self.assertTrue(not self.zeroVec) + self.assertTrue(self.v1) + + def testUnary(self): + v = +self.v1 + self.assertTrue(isinstance(v, type(self.v1))) + self.assertEqual(v.x, self.v1.x) + self.assertEqual(v.y, self.v1.y) + self.assertEqual(v.z, self.v1.z) + self.assertNotEqual(id(v), id(self.v1)) + v = -self.v1 + self.assertTrue(isinstance(v, type(self.v1))) + self.assertEqual(v.x, -self.v1.x) + self.assertEqual(v.y, -self.v1.y) + self.assertEqual(v.z, -self.v1.z) + self.assertNotEqual(id(v), id(self.v1)) + + def testCompare(self): + int_vec = Vector3(3, -2, 13) + flt_vec = Vector3(3.0, -2.0, 13.0) + zero_vec = Vector3(0, 0, 0) + self.assertEqual(int_vec == flt_vec, True) + self.assertEqual(int_vec != flt_vec, False) + self.assertEqual(int_vec != zero_vec, True) + self.assertEqual(flt_vec == zero_vec, False) + self.assertEqual(int_vec == (3, -2, 13), True) + self.assertEqual(int_vec != (3, -2, 13), False) + self.assertEqual(int_vec != [0, 0], True) + self.assertEqual(int_vec == [0, 0], False) + self.assertEqual(int_vec != 5, True) + self.assertEqual(int_vec == 5, False) + self.assertEqual(int_vec != [3, -2, 0, 1], True) + self.assertEqual(int_vec == [3, -2, 0, 1], False) + + def testStr(self): + v = Vector3(1.2, 3.4, 5.6) + self.assertEqual(str(v), "[1.2, 3.4, 5.6]") + + def testRepr(self): + v = Vector3(1.2, 3.4, -9.6) + self.assertEqual(v.__repr__(), "") + self.assertEqual(v, Vector3(v.__repr__())) + + def testIter(self): + it = self.v1.__iter__() + next_ = it.__next__ + self.assertEqual(next_(), self.v1[0]) + self.assertEqual(next_(), self.v1[1]) + self.assertEqual(next_(), self.v1[2]) + self.assertRaises(StopIteration, lambda: next_()) + it1 = self.v1.__iter__() + it2 = self.v1.__iter__() + self.assertNotEqual(id(it1), id(it2)) + self.assertEqual(id(it1), id(it1.__iter__())) + self.assertEqual(list(it1), list(it2)) + self.assertEqual(list(self.v1.__iter__()), self.l1) + idx = 0 + for val in self.v1: + self.assertEqual(val, self.v1[idx]) + idx += 1 + + def test_rotate(self): + v1 = Vector3(1, 0, 0) + axis = Vector3(0, 1, 0) + v2 = v1.rotate(90, axis) + v3 = v1.rotate(90 + 360, axis) + self.assertEqual(v1.x, 1) + self.assertEqual(v1.y, 0) + self.assertEqual(v1.z, 0) + self.assertEqual(v2.x, 0) + self.assertEqual(v2.y, 0) + self.assertEqual(v2.z, -1) + self.assertEqual(v3.x, v2.x) + self.assertEqual(v3.y, v2.y) + self.assertEqual(v3.z, v2.z) + v1 = Vector3(-1, -1, -1) + v2 = v1.rotate(-90, axis) + self.assertEqual(v2.x, 1) + self.assertEqual(v2.y, -1) + self.assertEqual(v2.z, -1) + v2 = v1.rotate(360, axis) + self.assertEqual(v1.x, v2.x) + self.assertEqual(v1.y, v2.y) + self.assertEqual(v1.z, v2.z) + v2 = v1.rotate(0, axis) + self.assertEqual(v1.x, v2.x) + self.assertEqual(v1.y, v2.y) + self.assertEqual(v1.z, v2.z) + # issue 214 + self.assertEqual( + Vector3(0, 1, 0).rotate(359.9999999, Vector3(0, 0, 1)), Vector3(0, 1, 0) + ) + + def test_rotate_rad(self): + axis = Vector3(0, 0, 1) + tests = ( + ((1, 0, 0), math.pi), + ((1, 0, 0), math.pi / 2), + ((1, 0, 0), -math.pi / 2), + ((1, 0, 0), math.pi / 4), + ) + for initialVec, radians in tests: + vec = Vector3(initialVec).rotate_rad(radians, axis) + self.assertEqual(vec, (math.cos(radians), math.sin(radians), 0)) + + def test_rotate_ip(self): + v = Vector3(1, 0, 0) + axis = Vector3(0, 1, 0) + self.assertEqual(v.rotate_ip(90, axis), None) + self.assertEqual(v.x, 0) + self.assertEqual(v.y, 0) + self.assertEqual(v.z, -1) + v = Vector3(-1, -1, 1) + v.rotate_ip(-90, axis) + self.assertEqual(v.x, -1) + self.assertEqual(v.y, -1) + self.assertEqual(v.z, -1) + + def test_rotate_rad_ip(self): + axis = Vector3(0, 0, 1) + tests = ( + ((1, 0, 0), math.pi), + ((1, 0, 0), math.pi / 2), + ((1, 0, 0), -math.pi / 2), + ((1, 0, 0), math.pi / 4), + ) + for initialVec, radians in tests: + vec = Vector3(initialVec) + vec.rotate_rad_ip(radians, axis) + self.assertEqual(vec, (math.cos(radians), math.sin(radians), 0)) + + def test_rotate_x(self): + v1 = Vector3(1, 0, 0) + v2 = v1.rotate_x(90) + v3 = v1.rotate_x(90 + 360) + self.assertEqual(v1.x, 1) + self.assertEqual(v1.y, 0) + self.assertEqual(v1.z, 0) + self.assertEqual(v2.x, 1) + self.assertEqual(v2.y, 0) + self.assertEqual(v2.z, 0) + self.assertEqual(v3.x, v2.x) + self.assertEqual(v3.y, v2.y) + self.assertEqual(v3.z, v2.z) + v1 = Vector3(-1, -1, -1) + v2 = v1.rotate_x(-90) + self.assertEqual(v2.x, -1) + self.assertAlmostEqual(v2.y, -1) + self.assertAlmostEqual(v2.z, 1) + v2 = v1.rotate_x(360) + self.assertAlmostEqual(v1.x, v2.x) + self.assertAlmostEqual(v1.y, v2.y) + self.assertAlmostEqual(v1.z, v2.z) + v2 = v1.rotate_x(0) + self.assertEqual(v1.x, v2.x) + self.assertAlmostEqual(v1.y, v2.y) + self.assertAlmostEqual(v1.z, v2.z) + + def test_rotate_x_rad(self): + vec = Vector3(0, 1, 0) + result = vec.rotate_x_rad(math.pi / 2) + self.assertEqual(result, (0, 0, 1)) + + def test_rotate_x_ip(self): + v = Vector3(1, 0, 0) + self.assertEqual(v.rotate_x_ip(90), None) + self.assertEqual(v.x, 1) + self.assertEqual(v.y, 0) + self.assertEqual(v.z, 0) + v = Vector3(-1, -1, 1) + v.rotate_x_ip(-90) + self.assertEqual(v.x, -1) + self.assertAlmostEqual(v.y, 1) + self.assertAlmostEqual(v.z, 1) + + def test_rotate_x_rad_ip(self): + vec = Vector3(0, 1, 0) + vec.rotate_x_rad_ip(math.pi / 2) + self.assertEqual(vec, (0, 0, 1)) + + def test_rotate_y(self): + v1 = Vector3(1, 0, 0) + v2 = v1.rotate_y(90) + v3 = v1.rotate_y(90 + 360) + self.assertEqual(v1.x, 1) + self.assertEqual(v1.y, 0) + self.assertEqual(v1.z, 0) + self.assertAlmostEqual(v2.x, 0) + self.assertEqual(v2.y, 0) + self.assertAlmostEqual(v2.z, -1) + self.assertAlmostEqual(v3.x, v2.x) + self.assertEqual(v3.y, v2.y) + self.assertAlmostEqual(v3.z, v2.z) + v1 = Vector3(-1, -1, -1) + v2 = v1.rotate_y(-90) + self.assertAlmostEqual(v2.x, 1) + self.assertEqual(v2.y, -1) + self.assertAlmostEqual(v2.z, -1) + v2 = v1.rotate_y(360) + self.assertAlmostEqual(v1.x, v2.x) + self.assertEqual(v1.y, v2.y) + self.assertAlmostEqual(v1.z, v2.z) + v2 = v1.rotate_y(0) + self.assertEqual(v1.x, v2.x) + self.assertEqual(v1.y, v2.y) + self.assertEqual(v1.z, v2.z) + + def test_rotate_y_rad(self): + vec = Vector3(1, 0, 0) + result = vec.rotate_y_rad(math.pi / 2) + self.assertEqual(result, (0, 0, -1)) + + def test_rotate_y_ip(self): + v = Vector3(1, 0, 0) + self.assertEqual(v.rotate_y_ip(90), None) + self.assertAlmostEqual(v.x, 0) + self.assertEqual(v.y, 0) + self.assertAlmostEqual(v.z, -1) + v = Vector3(-1, -1, 1) + v.rotate_y_ip(-90) + self.assertAlmostEqual(v.x, -1) + self.assertEqual(v.y, -1) + self.assertAlmostEqual(v.z, -1) + + def test_rotate_y_rad_ip(self): + vec = Vector3(1, 0, 0) + vec.rotate_y_rad_ip(math.pi / 2) + self.assertEqual(vec, (0, 0, -1)) + + def test_rotate_z(self): + v1 = Vector3(1, 0, 0) + v2 = v1.rotate_z(90) + v3 = v1.rotate_z(90 + 360) + self.assertEqual(v1.x, 1) + self.assertEqual(v1.y, 0) + self.assertEqual(v1.z, 0) + self.assertAlmostEqual(v2.x, 0) + self.assertAlmostEqual(v2.y, 1) + self.assertEqual(v2.z, 0) + self.assertAlmostEqual(v3.x, v2.x) + self.assertAlmostEqual(v3.y, v2.y) + self.assertEqual(v3.z, v2.z) + v1 = Vector3(-1, -1, -1) + v2 = v1.rotate_z(-90) + self.assertAlmostEqual(v2.x, -1) + self.assertAlmostEqual(v2.y, 1) + self.assertEqual(v2.z, -1) + v2 = v1.rotate_z(360) + self.assertAlmostEqual(v1.x, v2.x) + self.assertAlmostEqual(v1.y, v2.y) + self.assertEqual(v1.z, v2.z) + v2 = v1.rotate_z(0) + self.assertAlmostEqual(v1.x, v2.x) + self.assertAlmostEqual(v1.y, v2.y) + self.assertEqual(v1.z, v2.z) + + def test_rotate_z_rad(self): + vec = Vector3(1, 0, 0) + result = vec.rotate_z_rad(math.pi / 2) + self.assertEqual(result, (0, 1, 0)) + + def test_rotate_z_ip(self): + v = Vector3(1, 0, 0) + self.assertEqual(v.rotate_z_ip(90), None) + self.assertAlmostEqual(v.x, 0) + self.assertAlmostEqual(v.y, 1) + self.assertEqual(v.z, 0) + v = Vector3(-1, -1, 1) + v.rotate_z_ip(-90) + self.assertAlmostEqual(v.x, -1) + self.assertAlmostEqual(v.y, 1) + self.assertEqual(v.z, 1) + + def test_rotate_z_rad_ip(self): + vec = Vector3(1, 0, 0) + vec.rotate_z_rad_ip(math.pi / 2) + self.assertEqual(vec, (0, 1, 0)) + + def test_normalize(self): + v = self.v1.normalize() + # length is 1 + self.assertAlmostEqual(v.x * v.x + v.y * v.y + v.z * v.z, 1.0) + # v1 is unchanged + self.assertEqual(self.v1.x, self.l1[0]) + self.assertEqual(self.v1.y, self.l1[1]) + self.assertEqual(self.v1.z, self.l1[2]) + # v2 is parallel to v1 (tested via cross product) + cross = ( + (self.v1.y * v.z - self.v1.z * v.y) ** 2 + + (self.v1.z * v.x - self.v1.x * v.z) ** 2 + + (self.v1.x * v.y - self.v1.y * v.x) ** 2 + ) + self.assertAlmostEqual(cross, 0.0) + self.assertRaises(ValueError, lambda: self.zeroVec.normalize()) + + def test_normalize_ip(self): + v = +self.v1 + # v has length != 1 before normalizing + self.assertNotEqual(v.x * v.x + v.y * v.y + v.z * v.z, 1.0) + # inplace operations should return None + self.assertEqual(v.normalize_ip(), None) + # length is 1 + self.assertAlmostEqual(v.x * v.x + v.y * v.y + v.z * v.z, 1.0) + # v2 is parallel to v1 (tested via cross product) + cross = ( + (self.v1.y * v.z - self.v1.z * v.y) ** 2 + + (self.v1.z * v.x - self.v1.x * v.z) ** 2 + + (self.v1.x * v.y - self.v1.y * v.x) ** 2 + ) + self.assertAlmostEqual(cross, 0.0) + self.assertRaises(ValueError, lambda: self.zeroVec.normalize_ip()) + + def test_is_normalized(self): + self.assertEqual(self.v1.is_normalized(), False) + v = self.v1.normalize() + self.assertEqual(v.is_normalized(), True) + self.assertEqual(self.e2.is_normalized(), True) + self.assertEqual(self.zeroVec.is_normalized(), False) + + def test_cross(self): + def cross(a, b): + return Vector3( + a[1] * b[2] - a[2] * b[1], + a[2] * b[0] - a[0] * b[2], + a[0] * b[1] - a[1] * b[0], + ) + + self.assertEqual(self.v1.cross(self.v2), cross(self.v1, self.v2)) + self.assertEqual(self.v1.cross(self.l2), cross(self.v1, self.l2)) + self.assertEqual(self.v1.cross(self.t2), cross(self.v1, self.t2)) + self.assertEqual(self.v1.cross(self.v2), -self.v2.cross(self.v1)) + self.assertEqual(self.v1.cross(self.v1), self.zeroVec) + + def test_dot(self): + self.assertAlmostEqual( + self.v1.dot(self.v2), + self.v1.x * self.v2.x + self.v1.y * self.v2.y + self.v1.z * self.v2.z, + ) + self.assertAlmostEqual( + self.v1.dot(self.l2), + self.v1.x * self.l2[0] + self.v1.y * self.l2[1] + self.v1.z * self.l2[2], + ) + self.assertAlmostEqual( + self.v1.dot(self.t2), + self.v1.x * self.t2[0] + self.v1.y * self.t2[1] + self.v1.z * self.t2[2], + ) + self.assertAlmostEqual(self.v1.dot(self.v2), self.v2.dot(self.v1)) + self.assertAlmostEqual(self.v1.dot(self.v2), self.v1 * self.v2) + + def test_angle_to(self): + self.assertEqual(Vector3(1, 1, 0).angle_to((-1, 1, 0)), 90) + self.assertEqual(Vector3(1, 0, 0).angle_to((0, 0, -1)), 90) + self.assertEqual(Vector3(1, 0, 0).angle_to((-1, 0, 1)), 135) + self.assertEqual(abs(Vector3(1, 0, 1).angle_to((-1, 0, -1))), 180) + # if we rotate v1 by the angle_to v2 around their cross product + # we should look in the same direction + self.assertEqual( + self.v1.rotate( + self.v1.angle_to(self.v2), self.v1.cross(self.v2) + ).normalize(), + self.v2.normalize(), + ) + + def test_scale_to_length(self): + v = Vector3(1, 1, 1) + v.scale_to_length(2.5) + self.assertEqual(v, Vector3(2.5, 2.5, 2.5) / math.sqrt(3)) + self.assertRaises(ValueError, lambda: self.zeroVec.scale_to_length(1)) + self.assertEqual(v.scale_to_length(0), None) + self.assertEqual(v, self.zeroVec) + + def test_length(self): + self.assertEqual(Vector3(3, 4, 5).length(), math.sqrt(3 * 3 + 4 * 4 + 5 * 5)) + self.assertEqual(Vector3(-3, 4, 5).length(), math.sqrt(-3 * -3 + 4 * 4 + 5 * 5)) + self.assertEqual(self.zeroVec.length(), 0) + + def test_length_squared(self): + self.assertEqual(Vector3(3, 4, 5).length_squared(), 3 * 3 + 4 * 4 + 5 * 5) + self.assertEqual(Vector3(-3, 4, 5).length_squared(), -3 * -3 + 4 * 4 + 5 * 5) + self.assertEqual(self.zeroVec.length_squared(), 0) + + def test_reflect(self): + v = Vector3(1, -1, 1) + n = Vector3(0, 1, 0) + self.assertEqual(v.reflect(n), Vector3(1, 1, 1)) + self.assertEqual(v.reflect(3 * n), v.reflect(n)) + self.assertEqual(v.reflect(-v), -v) + self.assertRaises(ValueError, lambda: v.reflect(self.zeroVec)) + + def test_reflect_ip(self): + v1 = Vector3(1, -1, 1) + v2 = Vector3(v1) + n = Vector3(0, 1, 0) + self.assertEqual(v2.reflect_ip(n), None) + self.assertEqual(v2, Vector3(1, 1, 1)) + v2 = Vector3(v1) + v2.reflect_ip(3 * n) + self.assertEqual(v2, v1.reflect(n)) + v2 = Vector3(v1) + v2.reflect_ip(-v1) + self.assertEqual(v2, -v1) + self.assertRaises(ValueError, lambda: v2.reflect_ip(self.zeroVec)) + + def test_distance_to(self): + diff = self.v1 - self.v2 + self.assertEqual(self.e1.distance_to(self.e2), math.sqrt(2)) + self.assertEqual( + self.v1.distance_to(self.v2), + math.sqrt(diff.x * diff.x + diff.y * diff.y + diff.z * diff.z), + ) + self.assertEqual(self.v1.distance_to(self.v1), 0) + self.assertEqual(self.v1.distance_to(self.v2), self.v2.distance_to(self.v1)) + + def test_distance_squared_to(self): + diff = self.v1 - self.v2 + self.assertEqual(self.e1.distance_squared_to(self.e2), 2) + self.assertAlmostEqual( + self.v1.distance_squared_to(self.v2), + diff.x * diff.x + diff.y * diff.y + diff.z * diff.z, + ) + self.assertEqual(self.v1.distance_squared_to(self.v1), 0) + self.assertEqual( + self.v1.distance_squared_to(self.v2), self.v2.distance_squared_to(self.v1) + ) + + def test_swizzle(self): + self.assertEqual(self.v1.yxz, (self.v1.y, self.v1.x, self.v1.z)) + self.assertEqual( + self.v1.xxyyzzxyz, + ( + self.v1.x, + self.v1.x, + self.v1.y, + self.v1.y, + self.v1.z, + self.v1.z, + self.v1.x, + self.v1.y, + self.v1.z, + ), + ) + self.v1.xyz = self.t2 + self.assertEqual(self.v1, self.t2) + self.v1.zxy = self.t2 + self.assertEqual(self.v1, (self.t2[1], self.t2[2], self.t2[0])) + self.v1.yz = self.t2[:2] + self.assertEqual(self.v1, (self.t2[1], self.t2[0], self.t2[1])) + self.assertEqual(type(self.v1), Vector3) + + @unittest.skipIf(IS_PYPY, "known pypy failure") + def test_invalid_swizzle(self): + def invalidSwizzleX(): + Vector3().xx = (1, 2) + + def invalidSwizzleY(): + Vector3().yy = (1, 2) + + def invalidSwizzleZ(): + Vector3().zz = (1, 2) + + def invalidSwizzleW(): + Vector3().ww = (1, 2) + + self.assertRaises(AttributeError, invalidSwizzleX) + self.assertRaises(AttributeError, invalidSwizzleY) + self.assertRaises(AttributeError, invalidSwizzleZ) + self.assertRaises(AttributeError, invalidSwizzleW) + + def invalidAssignment(): + Vector3().xy = 3 + + self.assertRaises(TypeError, invalidAssignment) + + def test_swizzle_return_types(self): + self.assertEqual(type(self.v1.x), float) + self.assertEqual(type(self.v1.xy), Vector2) + self.assertEqual(type(self.v1.xyz), Vector3) + # but we don't have vector4 or above... so tuple. + self.assertEqual(type(self.v1.xyxy), tuple) + self.assertEqual(type(self.v1.xyxyx), tuple) + + def test_dir_works(self): + # not every single one of the attributes... + attributes = set( + ["lerp", "normalize", "normalize_ip", "reflect", "slerp", "x", "y"] + ) + # check if this selection of attributes are all there. + self.assertTrue(attributes.issubset(set(dir(self.v1)))) + + def test_elementwise(self): + # behaviour for "elementwise op scalar" + self.assertEqual( + self.v1.elementwise() + self.s1, + (self.v1.x + self.s1, self.v1.y + self.s1, self.v1.z + self.s1), + ) + self.assertEqual( + self.v1.elementwise() - self.s1, + (self.v1.x - self.s1, self.v1.y - self.s1, self.v1.z - self.s1), + ) + self.assertEqual( + self.v1.elementwise() * self.s2, + (self.v1.x * self.s2, self.v1.y * self.s2, self.v1.z * self.s2), + ) + self.assertEqual( + self.v1.elementwise() / self.s2, + (self.v1.x / self.s2, self.v1.y / self.s2, self.v1.z / self.s2), + ) + self.assertEqual( + self.v1.elementwise() // self.s1, + (self.v1.x // self.s1, self.v1.y // self.s1, self.v1.z // self.s1), + ) + self.assertEqual( + self.v1.elementwise() ** self.s1, + (self.v1.x ** self.s1, self.v1.y ** self.s1, self.v1.z ** self.s1), + ) + self.assertEqual( + self.v1.elementwise() % self.s1, + (self.v1.x % self.s1, self.v1.y % self.s1, self.v1.z % self.s1), + ) + self.assertEqual( + self.v1.elementwise() > self.s1, + self.v1.x > self.s1 and self.v1.y > self.s1 and self.v1.z > self.s1, + ) + self.assertEqual( + self.v1.elementwise() < self.s1, + self.v1.x < self.s1 and self.v1.y < self.s1 and self.v1.z < self.s1, + ) + self.assertEqual( + self.v1.elementwise() == self.s1, + self.v1.x == self.s1 and self.v1.y == self.s1 and self.v1.z == self.s1, + ) + self.assertEqual( + self.v1.elementwise() != self.s1, + self.v1.x != self.s1 and self.v1.y != self.s1 and self.v1.z != self.s1, + ) + self.assertEqual( + self.v1.elementwise() >= self.s1, + self.v1.x >= self.s1 and self.v1.y >= self.s1 and self.v1.z >= self.s1, + ) + self.assertEqual( + self.v1.elementwise() <= self.s1, + self.v1.x <= self.s1 and self.v1.y <= self.s1 and self.v1.z <= self.s1, + ) + # behaviour for "scalar op elementwise" + self.assertEqual(5 + self.v1.elementwise(), Vector3(5, 5, 5) + self.v1) + self.assertEqual(3.5 - self.v1.elementwise(), Vector3(3.5, 3.5, 3.5) - self.v1) + self.assertEqual(7.5 * self.v1.elementwise(), 7.5 * self.v1) + self.assertEqual( + -3.5 / self.v1.elementwise(), + (-3.5 / self.v1.x, -3.5 / self.v1.y, -3.5 / self.v1.z), + ) + self.assertEqual( + -3.5 // self.v1.elementwise(), + (-3.5 // self.v1.x, -3.5 // self.v1.y, -3.5 // self.v1.z), + ) + self.assertEqual( + -(3.5 ** self.v1.elementwise()), + (-(3.5 ** self.v1.x), -(3.5 ** self.v1.y), -(3.5 ** self.v1.z)), + ) + self.assertEqual( + 3 % self.v1.elementwise(), (3 % self.v1.x, 3 % self.v1.y, 3 % self.v1.z) + ) + self.assertEqual( + 2 < self.v1.elementwise(), 2 < self.v1.x and 2 < self.v1.y and 2 < self.v1.z + ) + self.assertEqual( + 2 > self.v1.elementwise(), 2 > self.v1.x and 2 > self.v1.y and 2 > self.v1.z + ) + self.assertEqual( + 1 == self.v1.elementwise(), + 1 == self.v1.x and 1 == self.v1.y and 1 == self.v1.z, + ) + self.assertEqual( + 1 != self.v1.elementwise(), + 1 != self.v1.x and 1 != self.v1.y and 1 != self.v1.z, + ) + self.assertEqual( + 2 <= self.v1.elementwise(), + 2 <= self.v1.x and 2 <= self.v1.y and 2 <= self.v1.z, + ) + self.assertEqual( + -7 >= self.v1.elementwise(), + -7 >= self.v1.x and -7 >= self.v1.y and -7 >= self.v1.z, + ) + self.assertEqual( + -7 != self.v1.elementwise(), + -7 != self.v1.x and -7 != self.v1.y and -7 != self.v1.z, + ) + + # behaviour for "elementwise op vector" + self.assertEqual(type(self.v1.elementwise() * self.v2), type(self.v1)) + self.assertEqual(self.v1.elementwise() + self.v2, self.v1 + self.v2) + self.assertEqual(self.v1.elementwise() + self.v2, self.v1 + self.v2) + self.assertEqual(self.v1.elementwise() - self.v2, self.v1 - self.v2) + self.assertEqual( + self.v1.elementwise() * self.v2, + (self.v1.x * self.v2.x, self.v1.y * self.v2.y, self.v1.z * self.v2.z), + ) + self.assertEqual( + self.v1.elementwise() / self.v2, + (self.v1.x / self.v2.x, self.v1.y / self.v2.y, self.v1.z / self.v2.z), + ) + self.assertEqual( + self.v1.elementwise() // self.v2, + (self.v1.x // self.v2.x, self.v1.y // self.v2.y, self.v1.z // self.v2.z), + ) + self.assertEqual( + self.v1.elementwise() ** self.v2, + (self.v1.x ** self.v2.x, self.v1.y ** self.v2.y, self.v1.z ** self.v2.z), + ) + self.assertEqual( + self.v1.elementwise() % self.v2, + (self.v1.x % self.v2.x, self.v1.y % self.v2.y, self.v1.z % self.v2.z), + ) + self.assertEqual( + self.v1.elementwise() > self.v2, + self.v1.x > self.v2.x and self.v1.y > self.v2.y and self.v1.z > self.v2.z, + ) + self.assertEqual( + self.v1.elementwise() < self.v2, + self.v1.x < self.v2.x and self.v1.y < self.v2.y and self.v1.z < self.v2.z, + ) + self.assertEqual( + self.v1.elementwise() >= self.v2, + self.v1.x >= self.v2.x + and self.v1.y >= self.v2.y + and self.v1.z >= self.v2.z, + ) + self.assertEqual( + self.v1.elementwise() <= self.v2, + self.v1.x <= self.v2.x + and self.v1.y <= self.v2.y + and self.v1.z <= self.v2.z, + ) + self.assertEqual( + self.v1.elementwise() == self.v2, + self.v1.x == self.v2.x + and self.v1.y == self.v2.y + and self.v1.z == self.v2.z, + ) + self.assertEqual( + self.v1.elementwise() != self.v2, + self.v1.x != self.v2.x + and self.v1.y != self.v2.y + and self.v1.z != self.v2.z, + ) + # behaviour for "vector op elementwise" + self.assertEqual(self.v2 + self.v1.elementwise(), self.v2 + self.v1) + self.assertEqual(self.v2 - self.v1.elementwise(), self.v2 - self.v1) + self.assertEqual( + self.v2 * self.v1.elementwise(), + (self.v2.x * self.v1.x, self.v2.y * self.v1.y, self.v2.z * self.v1.z), + ) + self.assertEqual( + self.v2 / self.v1.elementwise(), + (self.v2.x / self.v1.x, self.v2.y / self.v1.y, self.v2.z / self.v1.z), + ) + self.assertEqual( + self.v2 // self.v1.elementwise(), + (self.v2.x // self.v1.x, self.v2.y // self.v1.y, self.v2.z // self.v1.z), + ) + self.assertEqual( + self.v2 ** self.v1.elementwise(), + (self.v2.x ** self.v1.x, self.v2.y ** self.v1.y, self.v2.z ** self.v1.z), + ) + self.assertEqual( + self.v2 % self.v1.elementwise(), + (self.v2.x % self.v1.x, self.v2.y % self.v1.y, self.v2.z % self.v1.z), + ) + self.assertEqual( + self.v2 < self.v1.elementwise(), + self.v2.x < self.v1.x and self.v2.y < self.v1.y and self.v2.z < self.v1.z, + ) + self.assertEqual( + self.v2 > self.v1.elementwise(), + self.v2.x > self.v1.x and self.v2.y > self.v1.y and self.v2.z > self.v1.z, + ) + self.assertEqual( + self.v2 <= self.v1.elementwise(), + self.v2.x <= self.v1.x + and self.v2.y <= self.v1.y + and self.v2.z <= self.v1.z, + ) + self.assertEqual( + self.v2 >= self.v1.elementwise(), + self.v2.x >= self.v1.x + and self.v2.y >= self.v1.y + and self.v2.z >= self.v1.z, + ) + self.assertEqual( + self.v2 == self.v1.elementwise(), + self.v2.x == self.v1.x + and self.v2.y == self.v1.y + and self.v2.z == self.v1.z, + ) + self.assertEqual( + self.v2 != self.v1.elementwise(), + self.v2.x != self.v1.x + and self.v2.y != self.v1.y + and self.v2.z != self.v1.z, + ) + + # behaviour for "elementwise op elementwise" + self.assertEqual( + self.v2.elementwise() + self.v1.elementwise(), self.v2 + self.v1 + ) + self.assertEqual( + self.v2.elementwise() - self.v1.elementwise(), self.v2 - self.v1 + ) + self.assertEqual( + self.v2.elementwise() * self.v1.elementwise(), + (self.v2.x * self.v1.x, self.v2.y * self.v1.y, self.v2.z * self.v1.z), + ) + self.assertEqual( + self.v2.elementwise() / self.v1.elementwise(), + (self.v2.x / self.v1.x, self.v2.y / self.v1.y, self.v2.z / self.v1.z), + ) + self.assertEqual( + self.v2.elementwise() // self.v1.elementwise(), + (self.v2.x // self.v1.x, self.v2.y // self.v1.y, self.v2.z // self.v1.z), + ) + self.assertEqual( + self.v2.elementwise() ** self.v1.elementwise(), + (self.v2.x ** self.v1.x, self.v2.y ** self.v1.y, self.v2.z ** self.v1.z), + ) + self.assertEqual( + self.v2.elementwise() % self.v1.elementwise(), + (self.v2.x % self.v1.x, self.v2.y % self.v1.y, self.v2.z % self.v1.z), + ) + self.assertEqual( + self.v2.elementwise() < self.v1.elementwise(), + self.v2.x < self.v1.x and self.v2.y < self.v1.y and self.v2.z < self.v1.z, + ) + self.assertEqual( + self.v2.elementwise() > self.v1.elementwise(), + self.v2.x > self.v1.x and self.v2.y > self.v1.y and self.v2.z > self.v1.z, + ) + self.assertEqual( + self.v2.elementwise() <= self.v1.elementwise(), + self.v2.x <= self.v1.x + and self.v2.y <= self.v1.y + and self.v2.z <= self.v1.z, + ) + self.assertEqual( + self.v2.elementwise() >= self.v1.elementwise(), + self.v2.x >= self.v1.x + and self.v2.y >= self.v1.y + and self.v2.z >= self.v1.z, + ) + self.assertEqual( + self.v2.elementwise() == self.v1.elementwise(), + self.v2.x == self.v1.x + and self.v2.y == self.v1.y + and self.v2.z == self.v1.z, + ) + self.assertEqual( + self.v2.elementwise() != self.v1.elementwise(), + self.v2.x != self.v1.x + and self.v2.y != self.v1.y + and self.v2.z != self.v1.z, + ) + + # other behaviour + self.assertEqual( + abs(self.v1.elementwise()), (abs(self.v1.x), abs(self.v1.y), abs(self.v1.z)) + ) + self.assertEqual(-self.v1.elementwise(), -self.v1) + self.assertEqual(+self.v1.elementwise(), +self.v1) + self.assertEqual(bool(self.v1.elementwise()), bool(self.v1)) + self.assertEqual(bool(Vector3().elementwise()), bool(Vector3())) + self.assertEqual(self.zeroVec.elementwise() ** 0, (1, 1, 1)) + self.assertRaises(ValueError, lambda: pow(Vector3(-1, 0, 0).elementwise(), 1.2)) + self.assertRaises(ZeroDivisionError, lambda: self.zeroVec.elementwise() ** -1) + self.assertRaises(ZeroDivisionError, lambda: Vector3(1, 1, 1).elementwise() / 0) + self.assertRaises( + ZeroDivisionError, lambda: Vector3(1, 1, 1).elementwise() // 0 + ) + self.assertRaises(ZeroDivisionError, lambda: Vector3(1, 1, 1).elementwise() % 0) + self.assertRaises( + ZeroDivisionError, lambda: Vector3(1, 1, 1).elementwise() / self.zeroVec + ) + self.assertRaises( + ZeroDivisionError, lambda: Vector3(1, 1, 1).elementwise() // self.zeroVec + ) + self.assertRaises( + ZeroDivisionError, lambda: Vector3(1, 1, 1).elementwise() % self.zeroVec + ) + self.assertRaises(ZeroDivisionError, lambda: 2 / self.zeroVec.elementwise()) + self.assertRaises(ZeroDivisionError, lambda: 2 // self.zeroVec.elementwise()) + self.assertRaises(ZeroDivisionError, lambda: 2 % self.zeroVec.elementwise()) + + def test_slerp(self): + self.assertRaises(ValueError, lambda: self.zeroVec.slerp(self.v1, 0.5)) + self.assertRaises(ValueError, lambda: self.v1.slerp(self.zeroVec, 0.5)) + self.assertRaises(ValueError, lambda: self.zeroVec.slerp(self.zeroVec, 0.5)) + steps = 10 + angle_step = self.e1.angle_to(self.e2) / steps + for i, u in ( + (i, self.e1.slerp(self.e2, i / float(steps))) for i in range(steps + 1) + ): + self.assertAlmostEqual(u.length(), 1) + self.assertAlmostEqual(self.e1.angle_to(u), i * angle_step) + self.assertEqual(u, self.e2) + + v1 = Vector3(100, 0, 0) + v2 = Vector3(0, 10, 7) + radial_factor = v2.length() / v1.length() + for i, u in ((i, v1.slerp(v2, -i / float(steps))) for i in range(steps + 1)): + self.assertAlmostEqual( + u.length(), + (v2.length() - v1.length()) * (float(i) / steps) + v1.length(), + ) + self.assertEqual(u, v2) + self.assertEqual(v1.slerp(v1, 0.5), v1) + self.assertEqual(v2.slerp(v2, 0.5), v2) + self.assertRaises(ValueError, lambda: v1.slerp(-v1, 0.5)) + + def test_lerp(self): + v1 = Vector3(0, 0, 0) + v2 = Vector3(10, 10, 10) + self.assertEqual(v1.lerp(v2, 0.5), (5, 5, 5)) + self.assertRaises(ValueError, lambda: v1.lerp(v2, 2.5)) + + v1 = Vector3(-10, -5, -20) + v2 = Vector3(10, 10, -20) + self.assertEqual(v1.lerp(v2, 0.5), (0, 2.5, -20)) + + def test_spherical(self): + v = Vector3() + v.from_spherical(self.v1.as_spherical()) + self.assertEqual(self.v1, v) + self.assertEqual(self.e1.as_spherical(), (1, 90, 0)) + self.assertEqual(self.e2.as_spherical(), (1, 90, 90)) + self.assertEqual(self.e3.as_spherical(), (1, 0, 0)) + self.assertEqual((2 * self.e2).as_spherical(), (2, 90, 90)) + self.assertRaises(TypeError, lambda: v.from_spherical((None, None, None))) + self.assertRaises(TypeError, lambda: v.from_spherical("abc")) + self.assertRaises(TypeError, lambda: v.from_spherical((None, 1, 2))) + self.assertRaises(TypeError, lambda: v.from_spherical((1, 2, 3, 4))) + self.assertRaises(TypeError, lambda: v.from_spherical((1, 2))) + self.assertRaises(TypeError, lambda: v.from_spherical(1, 2, 3)) + v.from_spherical((0.5, 90, 90)) + self.assertEqual(v, 0.5 * self.e2) + + def test_inplace_operators(self): + + v = Vector3(1, 1, 1) + v *= 2 + self.assertEqual(v, (2.0, 2.0, 2.0)) + + v = Vector3(4, 4, 4) + v /= 2 + self.assertEqual(v, (2.0, 2.0, 2.0)) + + v = Vector3(3.0, 3.0, 3.0) + v -= (1, 1, 1) + self.assertEqual(v, (2.0, 2.0, 2.0)) + + v = Vector3(3.0, 3.0, 3.0) + v += (1, 1, 1) + self.assertEqual(v, (4.0, 4.0, 4.0)) + + def test_pickle(self): + import pickle + + v2 = Vector2(1, 2) + v3 = Vector3(1, 2, 3) + self.assertEqual(pickle.loads(pickle.dumps(v2)), v2) + self.assertEqual(pickle.loads(pickle.dumps(v3)), v3) + + def test_subclass_operation(self): + class Vector(pygame.math.Vector3): + pass + + v = Vector(2.0, 2.0, 2.0) + v *= 2 + self.assertEqual(v, (4.0, 4.0, 4.0)) + + def test_swizzle_constants(self): + """We can get constant values from a swizzle.""" + v = Vector2(7, 6) + self.assertEqual( + v.xy1, + (7.0, 6.0, 1.0), + ) + + def test_swizzle_four_constants(self): + """We can get 4 constant values from a swizzle.""" + v = Vector2(7, 6) + self.assertEqual( + v.xy01, + (7.0, 6.0, 0.0, 1.0), + ) + + def test_swizzle_oob(self): + """An out-of-bounds swizzle raises an AttributeError.""" + v = Vector2(7, 6) + with self.assertRaises(AttributeError): + v.xyz + + @unittest.skipIf(IS_PYPY, "known pypy failure") + def test_swizzle_set_oob(self): + """An out-of-bounds swizzle set raises an AttributeError.""" + v = Vector2(7, 6) + with self.assertRaises(AttributeError): + v.xz = (1, 1) + + def test_project_v3_onto_x_axis(self): + """Project onto x-axis, e.g. get the component pointing in the x-axis direction.""" + # arrange + v = Vector3(2, 3, 4) + x_axis = Vector3(10, 0, 0) + + # act + actual = v.project(x_axis) + + # assert + self.assertEqual(v.x, actual.x) + self.assertEqual(0, actual.y) + self.assertEqual(0, actual.z) + + def test_project_v3_onto_y_axis(self): + """Project onto y-axis, e.g. get the component pointing in the y-axis direction.""" + # arrange + v = Vector3(2, 3, 4) + y_axis = Vector3(0, 100, 0) + + # act + actual = v.project(y_axis) + + # assert + self.assertEqual(0, actual.x) + self.assertEqual(v.y, actual.y) + self.assertEqual(0, actual.z) + + def test_project_v3_onto_z_axis(self): + """Project onto z-axis, e.g. get the component pointing in the z-axis direction.""" + # arrange + v = Vector3(2, 3, 4) + y_axis = Vector3(0, 0, 77) + + # act + actual = v.project(y_axis) + + # assert + self.assertEqual(0, actual.x) + self.assertEqual(0, actual.y) + self.assertEqual(v.z, actual.z) + + def test_project_v3_onto_other(self): + """Project onto other vector.""" + # arrange + v = Vector3(2, 3, 4) + other = Vector3(3, 5, 7) + + # act + actual = v.project(other) + + # assert + expected = v.dot(other) / other.dot(other) * other + self.assertAlmostEqual(expected.x, actual.x) + self.assertAlmostEqual(expected.y, actual.y) + self.assertAlmostEqual(expected.z, actual.z) + + def test_project_v3_onto_other_as_tuple(self): + """Project onto other tuple as vector.""" + # arrange + v = Vector3(2, 3, 4) + other = Vector3(3, 5, 7) + + # act + actual = v.project(tuple(other)) + + # assert + expected = v.dot(other) / other.dot(other) * other + self.assertAlmostEqual(expected.x, actual.x) + self.assertAlmostEqual(expected.y, actual.y) + self.assertAlmostEqual(expected.z, actual.z) + + def test_project_v3_onto_other_as_list(self): + """Project onto other list as vector.""" + # arrange + v = Vector3(2, 3, 4) + other = Vector3(3, 5, 7) + + # act + actual = v.project(list(other)) + + # assert + expected = v.dot(other) / other.dot(other) * other + self.assertAlmostEqual(expected.x, actual.x) + self.assertAlmostEqual(expected.y, actual.y) + self.assertAlmostEqual(expected.z, actual.z) + + def test_project_v3_raises_if_other_has_zero_length(self): + """Check if exception is raise when projected on vector has zero length.""" + # arrange + v = Vector3(2, 3, 4) + other = Vector3(0, 0, 0) + + # act / assert + self.assertRaises(ValueError, v.project, other) + + def test_project_v3_raises_if_other_is_not_iterable(self): + """Check if exception is raise when projected on vector is not iterable.""" + # arrange + v = Vector3(2, 3, 4) + other = 10 + + # act / assert + self.assertRaises(TypeError, v.project, other) + + +if __name__ == "__main__": + unittest.main() diff --git a/venv/Lib/site-packages/pygame/tests/midi_test.py b/venv/Lib/site-packages/pygame/tests/midi_test.py new file mode 100644 index 0000000..ffbe8ff --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/midi_test.py @@ -0,0 +1,472 @@ +import unittest + + +import pygame + + +class MidiInputTest(unittest.TestCase): + __tags__ = ["interactive"] + + def setUp(self): + import pygame.midi + + pygame.midi.init() + in_id = pygame.midi.get_default_input_id() + if in_id != -1: + self.midi_input = pygame.midi.Input(in_id) + else: + self.midi_input = None + + def tearDown(self): + if self.midi_input: + self.midi_input.close() + pygame.midi.quit() + + def test_Input(self): + i = pygame.midi.get_default_input_id() + if self.midi_input: + self.assertEqual(self.midi_input.device_id, i) + + # try feeding it an input id. + i = pygame.midi.get_default_output_id() + + # can handle some invalid input too. + self.assertRaises(pygame.midi.MidiException, pygame.midi.Input, i) + self.assertRaises(pygame.midi.MidiException, pygame.midi.Input, 9009) + self.assertRaises(pygame.midi.MidiException, pygame.midi.Input, -1) + self.assertRaises(TypeError, pygame.midi.Input, "1234") + self.assertRaises(OverflowError, pygame.midi.Input, pow(2, 99)) + + def test_poll(self): + + if not self.midi_input: + self.skipTest("No midi Input device") + + self.assertFalse(self.midi_input.poll()) + # TODO fake some incoming data + + pygame.midi.quit() + self.assertRaises(RuntimeError, self.midi_input.poll) + # set midi_input to None to avoid error in tearDown + self.midi_input = None + + def test_read(self): + + if not self.midi_input: + self.skipTest("No midi Input device") + + read = self.midi_input.read(5) + self.assertEqual(read, []) + # TODO fake some incoming data + + pygame.midi.quit() + self.assertRaises(RuntimeError, self.midi_input.read, 52) + # set midi_input to None to avoid error in tearDown + self.midi_input = None + + def test_close(self): + if not self.midi_input: + self.skipTest("No midi Input device") + + self.assertIsNotNone(self.midi_input._input) + self.midi_input.close() + self.assertIsNone(self.midi_input._input) + + +class MidiOutputTest(unittest.TestCase): + __tags__ = ["interactive"] + + def setUp(self): + import pygame.midi + + pygame.midi.init() + m_out_id = pygame.midi.get_default_output_id() + if m_out_id != -1: + self.midi_output = pygame.midi.Output(m_out_id) + else: + self.midi_output = None + + def tearDown(self): + if self.midi_output: + self.midi_output.close() + pygame.midi.quit() + + def test_Output(self): + i = pygame.midi.get_default_output_id() + if self.midi_output: + self.assertEqual(self.midi_output.device_id, i) + + # try feeding it an input id. + i = pygame.midi.get_default_input_id() + + # can handle some invalid input too. + self.assertRaises(pygame.midi.MidiException, pygame.midi.Output, i) + self.assertRaises(pygame.midi.MidiException, pygame.midi.Output, 9009) + self.assertRaises(pygame.midi.MidiException, pygame.midi.Output, -1) + self.assertRaises(TypeError, pygame.midi.Output, "1234") + self.assertRaises(OverflowError, pygame.midi.Output, pow(2, 99)) + + def test_note_off(self): + if self.midi_output: + out = self.midi_output + out.note_on(5, 30, 0) + out.note_off(5, 30, 0) + with self.assertRaises(ValueError) as cm: + out.note_off(5, 30, 25) + self.assertEqual(str(cm.exception), "Channel not between 0 and 15.") + with self.assertRaises(ValueError) as cm: + out.note_off(5, 30, -1) + self.assertEqual(str(cm.exception), "Channel not between 0 and 15.") + + def test_note_on(self): + if self.midi_output: + out = self.midi_output + out.note_on(5, 30, 0) + out.note_on(5, 42, 10) + with self.assertRaises(ValueError) as cm: + out.note_on(5, 30, 25) + self.assertEqual(str(cm.exception), "Channel not between 0 and 15.") + with self.assertRaises(ValueError) as cm: + out.note_on(5, 30, -1) + self.assertEqual(str(cm.exception), "Channel not between 0 and 15.") + + def test_set_instrument(self): + + if not self.midi_output: + self.skipTest("No midi device") + out = self.midi_output + out.set_instrument(5) + out.set_instrument(42, channel=2) + with self.assertRaises(ValueError) as cm: + out.set_instrument(-6) + self.assertEqual(str(cm.exception), "Undefined instrument id: -6") + with self.assertRaises(ValueError) as cm: + out.set_instrument(156) + self.assertEqual(str(cm.exception), "Undefined instrument id: 156") + with self.assertRaises(ValueError) as cm: + out.set_instrument(5, -1) + self.assertEqual(str(cm.exception), "Channel not between 0 and 15.") + with self.assertRaises(ValueError) as cm: + out.set_instrument(5, 16) + self.assertEqual(str(cm.exception), "Channel not between 0 and 15.") + + def test_write(self): + if not self.midi_output: + self.skipTest("No midi device") + + out = self.midi_output + out.write([[[0xC0, 0, 0], 20000]]) + # is equivalent to + out.write([[[0xC0], 20000]]) + # example from the docstring : + # 1. choose program change 1 at time 20000 and + # 2. send note 65 with velocity 100 500 ms later + out.write([[[0xC0, 0, 0], 20000], [[0x90, 60, 100], 20500]]) + + out.write([]) + verrry_long = [[[0x90, 60, i % 100], 20000 + 100 * i] for i in range(1024)] + out.write(verrry_long) + + too_long = [[[0x90, 60, i % 100], 20000 + 100 * i] for i in range(1025)] + self.assertRaises(IndexError, out.write, too_long) + # test wrong data + with self.assertRaises(TypeError) as cm: + out.write("Non sens ?") + error_msg = "unsupported operand type(s) for &: 'str' and 'int'" + self.assertEqual(str(cm.exception), error_msg) + + with self.assertRaises(TypeError) as cm: + out.write(["Hey what's that?"]) + self.assertEqual(str(cm.exception), error_msg) + + def test_write_short(self): + if not self.midi_output: + self.skipTest("No midi device") + + out = self.midi_output + # program change + out.write_short(0xC0) + # put a note on, then off. + out.write_short(0x90, 65, 100) + out.write_short(0x80, 65, 100) + out.write_short(0x90) + + def test_write_sys_ex(self): + if not self.midi_output: + self.skipTest("No midi device") + + out = self.midi_output + out.write_sys_ex(pygame.midi.time(), [0xF0, 0x7D, 0x10, 0x11, 0x12, 0x13, 0xF7]) + + def test_pitch_bend(self): + # FIXME : pitch_bend in the code, but not in documentation + if not self.midi_output: + self.skipTest("No midi device") + + out = self.midi_output + with self.assertRaises(ValueError) as cm: + out.pitch_bend(5, channel=-1) + self.assertEqual(str(cm.exception), "Channel not between 0 and 15.") + with self.assertRaises(ValueError) as cm: + out.pitch_bend(5, channel=16) + with self.assertRaises(ValueError) as cm: + out.pitch_bend(-10001, 1) + self.assertEqual( + str(cm.exception), + "Pitch bend value must be between " "-8192 and +8191, not -10001.", + ) + with self.assertRaises(ValueError) as cm: + out.pitch_bend(10665, 2) + + def test_close(self): + if not self.midi_output: + self.skipTest("No midi device") + self.assertIsNotNone(self.midi_output._output) + self.midi_output.close() + self.assertIsNone(self.midi_output._output) + + def test_abort(self): + if not self.midi_output: + self.skipTest("No midi device") + self.assertEqual(self.midi_output._aborted, 0) + self.midi_output.abort() + self.assertEqual(self.midi_output._aborted, 1) + + +class MidiModuleTest(unittest.TestCase): + """Midi module tests that require midi hardware or midi.init(). + + See MidiModuleNonInteractiveTest for non-interactive module tests. + """ + + __tags__ = ["interactive"] + + def setUp(self): + import pygame.midi + + pygame.midi.init() + + def tearDown(self): + pygame.midi.quit() + + def test_get_count(self): + c = pygame.midi.get_count() + self.assertIsInstance(c, int) + self.assertTrue(c >= 0) + + def test_get_default_input_id(self): + + midin_id = pygame.midi.get_default_input_id() + # if there is a not None return make sure it is an int. + self.assertIsInstance(midin_id, int) + self.assertTrue(midin_id >= -1) + pygame.midi.quit() + self.assertRaises(RuntimeError, pygame.midi.get_default_output_id) + + def test_get_default_output_id(self): + + c = pygame.midi.get_default_output_id() + self.assertIsInstance(c, int) + self.assertTrue(c >= -1) + pygame.midi.quit() + self.assertRaises(RuntimeError, pygame.midi.get_default_output_id) + + def test_get_device_info(self): + + an_id = pygame.midi.get_default_output_id() + if an_id != -1: + interf, name, input, output, opened = pygame.midi.get_device_info(an_id) + self.assertEqual(output, 1) + self.assertEqual(input, 0) + self.assertEqual(opened, 0) + + an_in_id = pygame.midi.get_default_input_id() + if an_in_id != -1: + r = pygame.midi.get_device_info(an_in_id) + # if r is None, it means that the id is out of range. + interf, name, input, output, opened = r + + self.assertEqual(output, 0) + self.assertEqual(input, 1) + self.assertEqual(opened, 0) + out_of_range = pygame.midi.get_count() + for num in range(out_of_range): + self.assertIsNotNone(pygame.midi.get_device_info(num)) + info = pygame.midi.get_device_info(out_of_range) + self.assertIsNone(info) + + def test_init(self): + + pygame.midi.quit() + self.assertRaises(RuntimeError, pygame.midi.get_count) + # initialising many times should be fine. + pygame.midi.init() + pygame.midi.init() + pygame.midi.init() + pygame.midi.init() + + self.assertTrue(pygame.midi.get_init()) + + def test_quit(self): + + # It is safe to call this more than once. + pygame.midi.quit() + pygame.midi.init() + pygame.midi.quit() + pygame.midi.quit() + pygame.midi.init() + pygame.midi.init() + pygame.midi.quit() + + self.assertFalse(pygame.midi.get_init()) + + def test_get_init(self): + # Already initialized as pygame.midi.init() was called in setUp(). + self.assertTrue(pygame.midi.get_init()) + + def test_time(self): + + mtime = pygame.midi.time() + self.assertIsInstance(mtime, int) + # should be close to 2-3... since the timer is just init'd. + self.assertTrue(0 <= mtime < 100) + + +class MidiModuleNonInteractiveTest(unittest.TestCase): + """Midi module tests that do not require midi hardware or midi.init(). + + See MidiModuleTest for interactive module tests. + """ + + def setUp(self): + import pygame.midi + + def test_midiin(self): + """Ensures the MIDIIN event id exists in the midi module. + + The MIDIIN event id can be accessed via the midi module for backward + compatibility. + """ + self.assertEqual(pygame.midi.MIDIIN, pygame.MIDIIN) + self.assertEqual(pygame.midi.MIDIIN, pygame.locals.MIDIIN) + + self.assertNotEqual(pygame.midi.MIDIIN, pygame.MIDIOUT) + self.assertNotEqual(pygame.midi.MIDIIN, pygame.locals.MIDIOUT) + + def test_midiout(self): + """Ensures the MIDIOUT event id exists in the midi module. + + The MIDIOUT event id can be accessed via the midi module for backward + compatibility. + """ + self.assertEqual(pygame.midi.MIDIOUT, pygame.MIDIOUT) + self.assertEqual(pygame.midi.MIDIOUT, pygame.locals.MIDIOUT) + + self.assertNotEqual(pygame.midi.MIDIOUT, pygame.MIDIIN) + self.assertNotEqual(pygame.midi.MIDIOUT, pygame.locals.MIDIIN) + + def test_MidiException(self): + """Ensures the MidiException is raised as expected.""" + + def raiseit(): + raise pygame.midi.MidiException("Hello Midi param") + + with self.assertRaises(pygame.midi.MidiException) as cm: + raiseit() + + self.assertEqual(cm.exception.parameter, "Hello Midi param") + + def test_midis2events(self): + """Ensures midi events are properly converted to pygame events.""" + # List/tuple indexes. + MIDI_DATA = 0 + MD_STATUS = 0 + MD_DATA1 = 1 + MD_DATA2 = 2 + MD_DATA3 = 3 + + TIMESTAMP = 1 + + # Midi events take the form of: + # ((status, data1, data2, data3), timestamp) + midi_events = ( + ((0xC0, 0, 1, 2), 20000), + ((0x90, 60, 1000, "string_data"), 20001), + (("0", "1", "2", "3"), "4"), + ) + expected_num_events = len(midi_events) + + # Test different device ids. + for device_id in range(3): + pg_events = pygame.midi.midis2events(midi_events, device_id) + + self.assertEqual(len(pg_events), expected_num_events) + + for i, pg_event in enumerate(pg_events): + # Get the original midi data for comparison. + midi_event = midi_events[i] + midi_event_data = midi_event[MIDI_DATA] + + # Can't directly check event instance as pygame.event.Event is + # a function. + # self.assertIsInstance(pg_event, pygame.event.Event) + self.assertEqual(pg_event.__class__.__name__, "Event") + self.assertEqual(pg_event.type, pygame.MIDIIN) + self.assertEqual(pg_event.status, midi_event_data[MD_STATUS]) + self.assertEqual(pg_event.data1, midi_event_data[MD_DATA1]) + self.assertEqual(pg_event.data2, midi_event_data[MD_DATA2]) + self.assertEqual(pg_event.data3, midi_event_data[MD_DATA3]) + self.assertEqual(pg_event.timestamp, midi_event[TIMESTAMP]) + self.assertEqual(pg_event.vice_id, device_id) + + def test_midis2events__missing_event_data(self): + """Ensures midi events with missing values are handled properly.""" + midi_event_missing_data = ((0xC0, 0, 1), 20000) + midi_event_missing_timestamp = ((0xC0, 0, 1, 2),) + + for midi_event in (midi_event_missing_data, midi_event_missing_timestamp): + with self.assertRaises(ValueError): + events = pygame.midi.midis2events([midi_event], 0) + + def test_midis2events__extra_event_data(self): + """Ensures midi events with extra values are handled properly.""" + midi_event_extra_data = ((0xC0, 0, 1, 2, "extra"), 20000) + midi_event_extra_timestamp = ((0xC0, 0, 1, 2), 20000, "extra") + + for midi_event in (midi_event_extra_data, midi_event_extra_timestamp): + with self.assertRaises(ValueError): + events = pygame.midi.midis2events([midi_event], 0) + + def test_midis2events__extra_event_data_missing_timestamp(self): + """Ensures midi events with extra data and no timestamps are handled + properly. + """ + midi_event_extra_data_no_timestamp = ((0xC0, 0, 1, 2, "extra"),) + + with self.assertRaises(ValueError): + events = pygame.midi.midis2events([midi_event_extra_data_no_timestamp], 0) + + def test_conversions(self): + """of frequencies to midi note numbers and ansi note names.""" + from pygame.midi import frequency_to_midi, midi_to_frequency, midi_to_ansi_note + + self.assertEqual(frequency_to_midi(27.5), 21) + self.assertEqual(frequency_to_midi(36.7), 26) + self.assertEqual(frequency_to_midi(4186.0), 108) + self.assertEqual(midi_to_frequency(21), 27.5) + self.assertEqual(midi_to_frequency(26), 36.7) + self.assertEqual(midi_to_frequency(108), 4186.0) + self.assertEqual(midi_to_ansi_note(21), "A0") + self.assertEqual(midi_to_ansi_note(71), "B4") + self.assertEqual(midi_to_ansi_note(82), "A#5") + self.assertEqual(midi_to_ansi_note(83), "B5") + self.assertEqual(midi_to_ansi_note(93), "A6") + self.assertEqual(midi_to_ansi_note(94), "A#6") + self.assertEqual(midi_to_ansi_note(95), "B6") + self.assertEqual(midi_to_ansi_note(96), "C7") + self.assertEqual(midi_to_ansi_note(102), "F#7") + self.assertEqual(midi_to_ansi_note(108), "C8") + + +if __name__ == "__main__": + unittest.main() diff --git a/venv/Lib/site-packages/pygame/tests/mixer_music_tags.py b/venv/Lib/site-packages/pygame/tests/mixer_music_tags.py new file mode 100644 index 0000000..30f6893 --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/mixer_music_tags.py @@ -0,0 +1,7 @@ +__tags__ = [] + +import pygame +import sys + +if "pygame.mixer_music" not in sys.modules: + __tags__.extend(("ignore", "subprocess_ignore")) diff --git a/venv/Lib/site-packages/pygame/tests/mixer_music_test.py b/venv/Lib/site-packages/pygame/tests/mixer_music_test.py new file mode 100644 index 0000000..3d1c1f7 --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/mixer_music_test.py @@ -0,0 +1,415 @@ +# -*- coding: utf-8 -*- + +import os +import sys +import platform +import unittest +import time + +from pygame.tests.test_utils import example_path +import pygame + + +class MixerMusicModuleTest(unittest.TestCase): + @classmethod + def setUpClass(cls): + # Initializing the mixer is slow, so minimize the times it is called. + pygame.mixer.init() + + @classmethod + def tearDownClass(cls): + pygame.mixer.quit() + + def setUp(cls): + # This makes sure the mixer is always initialized before each test (in + # case a test calls pygame.mixer.quit()). + if pygame.mixer.get_init() is None: + pygame.mixer.init() + + def test_load_mp3(self): + "|tags:music|" + self.music_load("mp3") + + def test_load_ogg(self): + "|tags:music|" + self.music_load("ogg") + + def test_load_wav(self): + "|tags:music|" + self.music_load("wav") + + def music_load(self, format): + data_fname = example_path("data") + + path = os.path.join(data_fname, "house_lo.%s" % format) + if os.sep == "\\": + path = path.replace("\\", "\\\\") + umusfn = str(path) + bmusfn = umusfn.encode() + + pygame.mixer.music.load(umusfn) + pygame.mixer.music.load(bmusfn) + + def test_load_object(self): + """test loading music from file-like objects.""" + formats = ["ogg", "wav"] + data_fname = example_path("data") + for f in formats: + path = os.path.join(data_fname, "house_lo.%s" % f) + if os.sep == "\\": + path = path.replace("\\", "\\\\") + bmusfn = path.encode() + + with open(bmusfn, "rb") as musf: + pygame.mixer.music.load(musf) + + def test_object_namehint(self): + """test loading & queuing music from file-like objects with namehint argument.""" + formats = ["wav", "ogg"] + data_fname = example_path("data") + for f in formats: + path = os.path.join(data_fname, "house_lo.%s" % f) + if os.sep == "\\": + path = path.replace("\\", "\\\\") + bmusfn = path.encode() + + # these two "with open" blocks need to be separate, which is kinda weird + with open(bmusfn, "rb") as musf: + pygame.mixer.music.load(musf, f) + + with open(bmusfn, "rb") as musf: + pygame.mixer.music.queue(musf, f) + + with open(bmusfn, "rb") as musf: + pygame.mixer.music.load(musf, namehint=f) + + with open(bmusfn, "rb") as musf: + pygame.mixer.music.queue(musf, namehint=f) + + def test_load_unicode(self): + """test non-ASCII unicode path""" + import shutil + + ep = example_path("data") + temp_file = os.path.join(ep, u"你好.wav") + org_file = os.path.join(ep, u"house_lo.wav") + try: + with open(temp_file, "w") as f: + pass + os.remove(temp_file) + except IOError: + raise unittest.SkipTest("the path cannot be opened") + shutil.copy(org_file, temp_file) + try: + pygame.mixer.music.load(temp_file) + pygame.mixer.music.load(org_file) # unload + finally: + os.remove(temp_file) + + def test_unload(self): + import shutil + import tempfile + + ep = example_path("data") + org_file = os.path.join(ep, u"house_lo.wav") + tmpfd, tmppath = tempfile.mkstemp(".wav") + os.close(tmpfd) + shutil.copy(org_file, tmppath) + try: + pygame.mixer.music.load(tmppath) + pygame.mixer.music.unload() + finally: + os.remove(tmppath) + + def test_queue_mp3(self): + """Ensures queue() accepts mp3 files. + + |tags:music| + """ + filename = example_path(os.path.join("data", "house_lo.mp3")) + pygame.mixer.music.queue(filename) + + def test_queue_ogg(self): + """Ensures queue() accepts ogg files. + + |tags:music| + """ + filename = example_path(os.path.join("data", "house_lo.ogg")) + pygame.mixer.music.queue(filename) + + def test_queue_wav(self): + """Ensures queue() accepts wav files. + + |tags:music| + """ + filename = example_path(os.path.join("data", "house_lo.wav")) + pygame.mixer.music.queue(filename) + + def test_queue__multiple_calls(self): + """Ensures queue() can be called multiple times.""" + ogg_file = example_path(os.path.join("data", "house_lo.ogg")) + wav_file = example_path(os.path.join("data", "house_lo.wav")) + + pygame.mixer.music.queue(ogg_file) + pygame.mixer.music.queue(wav_file) + + def test_queue__arguments(self): + """Ensures queue() can be called with proper arguments.""" + wav_file = example_path(os.path.join("data", "house_lo.wav")) + + pygame.mixer.music.queue(wav_file, loops=2) + pygame.mixer.music.queue(wav_file, namehint="") + pygame.mixer.music.queue(wav_file, "") + pygame.mixer.music.queue(wav_file, "", 2) + + def test_queue__no_file(self): + """Ensures queue() correctly handles missing the file argument.""" + with self.assertRaises(TypeError): + pygame.mixer.music.queue() + + def test_queue__invalid_sound_type(self): + """Ensures queue() correctly handles invalid file types.""" + not_a_sound_file = example_path(os.path.join("data", "city.png")) + + with self.assertRaises(pygame.error): + pygame.mixer.music.queue(not_a_sound_file) + + def test_queue__invalid_filename(self): + """Ensures queue() correctly handles invalid filenames.""" + with self.assertRaises(pygame.error): + pygame.mixer.music.queue("") + + def test_music_pause__unpause(self): + """Ensure music has the correct position immediately after unpausing + + |tags:music| + """ + filename = example_path(os.path.join("data", "house_lo.mp3")) + pygame.mixer.music.load(filename) + pygame.mixer.music.play() + + # Wait 0.05s, then pause + time.sleep(0.05) + pygame.mixer.music.pause() + # Wait 0.05s, get position, unpause, then get position again + time.sleep(0.05) + before_unpause = pygame.mixer.music.get_pos() + pygame.mixer.music.unpause() + after_unpause = pygame.mixer.music.get_pos() + + self.assertEqual(before_unpause, after_unpause) + + def todo_test_stop(self): + + # __doc__ (as of 2008-08-02) for pygame.mixer_music.stop: + + # Stops the music playback if it is currently playing. + + self.fail() + + def todo_test_rewind(self): + + # __doc__ (as of 2008-08-02) for pygame.mixer_music.rewind: + + # Resets playback of the current music to the beginning. + + self.fail() + + def todo_test_get_pos(self): + + # __doc__ (as of 2008-08-02) for pygame.mixer_music.get_pos: + + # This gets the number of milliseconds that the music has been playing + # for. The returned time only represents how long the music has been + # playing; it does not take into account any starting position + # offsets. + # + + self.fail() + + def todo_test_fadeout(self): + + # __doc__ (as of 2008-08-02) for pygame.mixer_music.fadeout: + + # This will stop the music playback after it has been faded out over + # the specified time (measured in milliseconds). + # + # Note, that this function blocks until the music has faded out. + + self.fail() + + @unittest.skipIf( + os.environ.get("SDL_AUDIODRIVER") == "disk", + 'disk audio driver "playback" writing to disk is slow', + ) + def test_play__start_time(self): + + pygame.display.init() + + # music file is 7 seconds long + filename = example_path(os.path.join("data", "house_lo.ogg")) + pygame.mixer.music.load(filename) + start_time_in_seconds = 6.0 # 6 seconds + + music_finished = False + clock = pygame.time.Clock() + start_time_in_ms = clock.tick() + # should play the last 1 second + pygame.mixer.music.play(0, start=start_time_in_seconds) + running = True + while running: + pygame.event.pump() + + if not (pygame.mixer.music.get_busy() or music_finished): + music_finished = True + time_to_finish = (clock.tick() - start_time_in_ms) // 1000 + self.assertEqual(time_to_finish, 1) + running = False + + def todo_test_play(self): + + # __doc__ (as of 2008-08-02) for pygame.mixer_music.play: + + # This will play the loaded music stream. If the music is already + # playing it will be restarted. + # + # The loops argument controls the number of repeats a music will play. + # play(5) will cause the music to played once, then repeated five + # times, for a total of six. If the loops is -1 then the music will + # repeat indefinitely. + # + # The starting position argument controls where in the music the song + # starts playing. The starting position is dependent on the format of + # music playing. MP3 and OGG use the position as time (in seconds). + # MOD music it is the pattern order number. Passing a startpos will + # raise a NotImplementedError if it cannot set the start position + # + + self.fail() + + def todo_test_load(self): + + # __doc__ (as of 2008-08-02) for pygame.mixer_music.load: + + # This will load a music file and prepare it for playback. If a music + # stream is already playing it will be stopped. This does not start + # the music playing. + # + # Music can only be loaded from filenames, not python file objects + # like the other pygame loading functions. + # + + self.fail() + + def todo_test_get_volume(self): + + # __doc__ (as of 2008-08-02) for pygame.mixer_music.get_volume: + + # Returns the current volume for the mixer. The value will be between + # 0.0 and 1.0. + # + + self.fail() + + def todo_test_set_endevent(self): + + # __doc__ (as of 2008-08-02) for pygame.mixer_music.set_endevent: + + # This causes Pygame to signal (by means of the event queue) when the + # music is done playing. The argument determines the type of event + # that will be queued. + # + # The event will be queued every time the music finishes, not just the + # first time. To stop the event from being queued, call this method + # with no argument. + # + + self.fail() + + def todo_test_pause(self): + + # __doc__ (as of 2008-08-02) for pygame.mixer_music.pause: + + # Temporarily stop playback of the music stream. It can be resumed + # with the pygame.mixer.music.unpause() function. + # + + self.fail() + + def test_get_busy(self): + + # __doc__ (as of 2008-08-02) for pygame.mixer_music.get_busy: + + # Returns True when the music stream is actively playing. When the + # music is idle this returns False. + # + + self.music_load("ogg") + self.assertFalse(pygame.mixer.music.get_busy()) + pygame.mixer.music.play() + self.assertTrue(pygame.mixer.music.get_busy()) + pygame.mixer.music.pause() + self.assertFalse(pygame.mixer.music.get_busy()) + + def todo_test_get_endevent(self): + + # __doc__ (as of 2008-08-02) for pygame.mixer_music.get_endevent: + + # Returns the event type to be sent every time the music finishes + # playback. If there is no endevent the function returns + # pygame.NOEVENT. + # + + self.fail() + + def todo_test_unpause(self): + + # __doc__ (as of 2008-08-02) for pygame.mixer_music.unpause: + + # This will resume the playback of a music stream after it has been paused. + + self.fail() + + def todo_test_set_volume(self): + + # __doc__ (as of 2008-08-02) for pygame.mixer_music.set_volume: + + # Set the volume of the music playback. The value argument is between + # 0.0 and 1.0. When new music is loaded the volume is reset. + # + + self.fail() + + def todo_test_set_pos(self): + + # __doc__ (as of 2010-24-05) for pygame.mixer_music.set_pos: + + # This sets the position in the music file where playback will start. The + # meaning of "pos", a float (or a number that can be converted to a float), + # depends on the music format. Newer versions of SDL_mixer have better + # positioning support than earlier. An SDLError is raised if a particular + # format does not support positioning. + # + + self.fail() + + def test_init(self): + """issue #955. unload music whenever mixer.quit() is called""" + import tempfile + import shutil + + testfile = example_path(os.path.join("data", "house_lo.wav")) + tempcopy = os.path.join(tempfile.gettempdir(), "tempfile.wav") + + for i in range(10): + pygame.mixer.init() + try: + shutil.copy2(testfile, tempcopy) + pygame.mixer.music.load(tempcopy) + pygame.mixer.quit() + finally: + os.remove(tempcopy) + + +if __name__ == "__main__": + unittest.main() diff --git a/venv/Lib/site-packages/pygame/tests/mixer_tags.py b/venv/Lib/site-packages/pygame/tests/mixer_tags.py new file mode 100644 index 0000000..06a9de2 --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/mixer_tags.py @@ -0,0 +1,7 @@ +__tags__ = [] + +import pygame +import sys + +if "pygame.mixer" not in sys.modules: + __tags__.extend(("ignore", "subprocess_ignore")) diff --git a/venv/Lib/site-packages/pygame/tests/mixer_test.py b/venv/Lib/site-packages/pygame/tests/mixer_test.py new file mode 100644 index 0000000..0d5985d --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/mixer_test.py @@ -0,0 +1,1193 @@ +# -*- coding: utf8 -*- + +import sys +import os +import unittest +import pathlib +import platform + +from pygame.tests.test_utils import example_path, AssertRaisesRegexMixin + +import pygame +from pygame import mixer + +IS_PYPY = "PyPy" == platform.python_implementation() + +################################### CONSTANTS ################################## + +FREQUENCIES = [11025, 22050, 44100, 48000] +SIZES = [-16, -8, 8, 16] # fixme +# size 32 failed in test_get_init__returns_exact_values_used_for_init +CHANNELS = [1, 2] +BUFFERS = [3024] + +CONFIGS = [ + {"frequency": f, "size": s, "channels": c} + for f in FREQUENCIES + for s in SIZES + for c in CHANNELS +] +# Using all CONFIGS fails on a Mac; probably older SDL_mixer; we could do: +# if platform.system() == 'Darwin': +# But using all CONFIGS is very slow (> 10 sec for example) +# And probably, we don't need to be so exhaustive, hence: + +CONFIG = {"frequency": 44100, "size": 32, "channels": 2, "allowedchanges": 0} + + +class InvalidBool(object): + """To help test invalid bool values.""" + + __nonzero__ = None + __bool__ = None + + +############################## MODULE LEVEL TESTS ############################# + + +class MixerModuleTest(unittest.TestCase): + def tearDown(self): + mixer.quit() + mixer.pre_init(0, 0, 0, 0) + + def test_init__keyword_args(self): + # note: this test used to loop over all CONFIGS, but it's very slow.. + mixer.init(**CONFIG) + mixer_conf = mixer.get_init() + + self.assertEqual(mixer_conf[0], CONFIG["frequency"]) + # Not all "sizes" are supported on all systems, hence "abs". + self.assertEqual(abs(mixer_conf[1]), abs(CONFIG["size"])) + self.assertGreaterEqual(mixer_conf[2], CONFIG["channels"]) + + def test_pre_init__keyword_args(self): + # note: this test used to loop over all CONFIGS, but it's very slow.. + mixer.pre_init(**CONFIG) + mixer.init() + + mixer_conf = mixer.get_init() + + self.assertEqual(mixer_conf[0], CONFIG["frequency"]) + # Not all "sizes" are supported on all systems, hence "abs". + self.assertEqual(abs(mixer_conf[1]), abs(CONFIG["size"])) + self.assertGreaterEqual(mixer_conf[2], CONFIG["channels"]) + + def test_pre_init__zero_values(self): + # Ensure that argument values of 0 are replaced with + # default values. No way to check buffer size though. + mixer.pre_init(22050, -8, 1) # Non default values + mixer.pre_init(0, 0, 0) # Should reset to default values + mixer.init(allowedchanges=0) + self.assertEqual(mixer.get_init()[0], 44100) + self.assertEqual(mixer.get_init()[1], -16) + self.assertGreaterEqual(mixer.get_init()[2], 2) + + def test_init__zero_values(self): + # Ensure that argument values of 0 are replaced with + # preset values. No way to check buffer size though. + mixer.pre_init(44100, 8, 1, allowedchanges=0) # None default values + mixer.init(0, 0, 0) + self.assertEqual(mixer.get_init(), (44100, 8, 1)) + + def test_get_init__returns_exact_values_used_for_init(self): + # TODO: size 32 fails in this test (maybe SDL_mixer bug) + + for init_conf in CONFIGS: + frequency, size, channels = init_conf.values() + if (frequency, size) == (22050, 16): + continue + mixer.init(frequency, size, channels) + + mixer_conf = mixer.get_init() + + self.assertEqual(tuple(init_conf.values()), mixer_conf) + mixer.quit() + + def test_get_init__returns_None_if_mixer_not_initialized(self): + self.assertIsNone(mixer.get_init()) + + def test_get_num_channels__defaults_eight_after_init(self): + mixer.init() + self.assertEqual(mixer.get_num_channels(), 8) + + def test_set_num_channels(self): + mixer.init() + + default_num_channels = mixer.get_num_channels() + for i in range(1, default_num_channels + 1): + mixer.set_num_channels(i) + self.assertEqual(mixer.get_num_channels(), i) + + def test_quit(self): + """get_num_channels() Should throw pygame.error if uninitialized + after mixer.quit()""" + mixer.init() + mixer.quit() + self.assertRaises(pygame.error, mixer.get_num_channels) + + # TODO: FIXME: appveyor and pypy (on linux) fails here sometimes. + @unittest.skipIf(sys.platform.startswith("win"), "See github issue 892.") + @unittest.skipIf(IS_PYPY, "random errors here with pypy") + def test_sound_args(self): + def get_bytes(snd): + return snd.get_raw() + + mixer.init() + + sample = b"\x00\xff" * 24 + wave_path = example_path(os.path.join("data", "house_lo.wav")) + uwave_path = str(wave_path) + bwave_path = uwave_path.encode(sys.getfilesystemencoding()) + snd = mixer.Sound(file=wave_path) + self.assertTrue(snd.get_length() > 0.5) + snd_bytes = get_bytes(snd) + self.assertTrue(len(snd_bytes) > 1000) + + self.assertEqual(get_bytes(mixer.Sound(wave_path)), snd_bytes) + + self.assertEqual(get_bytes(mixer.Sound(file=uwave_path)), snd_bytes) + self.assertEqual(get_bytes(mixer.Sound(uwave_path)), snd_bytes) + arg_emsg = "Sound takes either 1 positional or 1 keyword argument" + + with self.assertRaises(TypeError) as cm: + mixer.Sound() + self.assertEqual(str(cm.exception), arg_emsg) + with self.assertRaises(TypeError) as cm: + mixer.Sound(wave_path, buffer=sample) + self.assertEqual(str(cm.exception), arg_emsg) + with self.assertRaises(TypeError) as cm: + mixer.Sound(sample, file=wave_path) + self.assertEqual(str(cm.exception), arg_emsg) + with self.assertRaises(TypeError) as cm: + mixer.Sound(buffer=sample, file=wave_path) + self.assertEqual(str(cm.exception), arg_emsg) + + with self.assertRaises(TypeError) as cm: + mixer.Sound(foobar=sample) + self.assertEqual(str(cm.exception), "Unrecognized keyword argument 'foobar'") + + snd = mixer.Sound(wave_path, **{}) + self.assertEqual(get_bytes(snd), snd_bytes) + snd = mixer.Sound(*[], **{"file": wave_path}) + + with self.assertRaises(TypeError) as cm: + mixer.Sound([]) + self.assertEqual(str(cm.exception), "Unrecognized argument (type list)") + + with self.assertRaises(TypeError) as cm: + snd = mixer.Sound(buffer=[]) + emsg = "Expected object with buffer interface: got a list" + self.assertEqual(str(cm.exception), emsg) + + ufake_path = str("12345678") + self.assertRaises(IOError, mixer.Sound, ufake_path) + self.assertRaises(IOError, mixer.Sound, "12345678") + + with self.assertRaises(TypeError) as cm: + mixer.Sound(buffer=str("something")) + emsg = "Unicode object not allowed as buffer object" + self.assertEqual(str(cm.exception), emsg) + self.assertEqual(get_bytes(mixer.Sound(buffer=sample)), sample) + if type(sample) != str: + somebytes = get_bytes(mixer.Sound(sample)) + # on python 2 we do not allow using string except as file name. + self.assertEqual(somebytes, sample) + self.assertEqual(get_bytes(mixer.Sound(file=bwave_path)), snd_bytes) + self.assertEqual(get_bytes(mixer.Sound(bwave_path)), snd_bytes) + + snd = mixer.Sound(wave_path) + with self.assertRaises(TypeError) as cm: + mixer.Sound(wave_path, array=snd) + self.assertEqual(str(cm.exception), arg_emsg) + with self.assertRaises(TypeError) as cm: + mixer.Sound(buffer=sample, array=snd) + self.assertEqual(str(cm.exception), arg_emsg) + snd2 = mixer.Sound(array=snd) + self.assertEqual(snd.get_raw(), snd2.get_raw()) + + def test_sound_unicode(self): + """test non-ASCII unicode path""" + mixer.init() + import shutil + + ep = example_path("data") + temp_file = os.path.join(ep, u"你好.wav") + org_file = os.path.join(ep, u"house_lo.wav") + shutil.copy(org_file, temp_file) + try: + with open(temp_file, "rb") as f: + pass + except IOError: + raise unittest.SkipTest("the path cannot be opened") + + try: + sound = mixer.Sound(temp_file) + del sound + finally: + os.remove(temp_file) + + @unittest.skipIf( + os.environ.get("SDL_AUDIODRIVER") == "disk", + "this test fails without real sound card", + ) + def test_array_keyword(self): + try: + from numpy import ( + array, + arange, + zeros, + int8, + uint8, + int16, + uint16, + int32, + uint32, + ) + except ImportError: + self.skipTest("requires numpy") + + freq = 22050 + format_list = [-8, 8, -16, 16] + channels_list = [1, 2] + + a_lists = dict((f, []) for f in format_list) + a32u_mono = arange(0, 256, 1, uint32) + a16u_mono = a32u_mono.astype(uint16) + a8u_mono = a32u_mono.astype(uint8) + au_list_mono = [(1, a) for a in [a8u_mono, a16u_mono, a32u_mono]] + for format in format_list: + if format > 0: + a_lists[format].extend(au_list_mono) + a32s_mono = arange(-128, 128, 1, int32) + a16s_mono = a32s_mono.astype(int16) + a8s_mono = a32s_mono.astype(int8) + as_list_mono = [(1, a) for a in [a8s_mono, a16s_mono, a32s_mono]] + for format in format_list: + if format < 0: + a_lists[format].extend(as_list_mono) + a32u_stereo = zeros([a32u_mono.shape[0], 2], uint32) + a32u_stereo[:, 0] = a32u_mono + a32u_stereo[:, 1] = 255 - a32u_mono + a16u_stereo = a32u_stereo.astype(uint16) + a8u_stereo = a32u_stereo.astype(uint8) + au_list_stereo = [(2, a) for a in [a8u_stereo, a16u_stereo, a32u_stereo]] + for format in format_list: + if format > 0: + a_lists[format].extend(au_list_stereo) + a32s_stereo = zeros([a32s_mono.shape[0], 2], int32) + a32s_stereo[:, 0] = a32s_mono + a32s_stereo[:, 1] = -1 - a32s_mono + a16s_stereo = a32s_stereo.astype(int16) + a8s_stereo = a32s_stereo.astype(int8) + as_list_stereo = [(2, a) for a in [a8s_stereo, a16s_stereo, a32s_stereo]] + for format in format_list: + if format < 0: + a_lists[format].extend(as_list_stereo) + + for format in format_list: + for channels in channels_list: + try: + mixer.init(freq, format, channels) + except pygame.error: + # Some formats (e.g. 16) may not be supported. + continue + try: + __, f, c = mixer.get_init() + if f != format or c != channels: + # Some formats (e.g. -8) may not be supported. + continue + for c, a in a_lists[format]: + self._test_array_argument(format, a, c == channels) + finally: + mixer.quit() + + def _test_array_argument(self, format, a, test_pass): + from numpy import array, all as all_ + + try: + snd = mixer.Sound(array=a) + except ValueError: + if not test_pass: + return + self.fail("Raised ValueError: Format %i, dtype %s" % (format, a.dtype)) + if not test_pass: + self.fail( + "Did not raise ValueError: Format %i, dtype %s" % (format, a.dtype) + ) + a2 = array(snd) + a3 = a.astype(a2.dtype) + lshift = abs(format) - 8 * a.itemsize + if lshift >= 0: + # This is asymmetric with respect to downcasting. + a3 <<= lshift + self.assertTrue(all_(a2 == a3), "Format %i, dtype %s" % (format, a.dtype)) + + def _test_array_interface_fail(self, a): + self.assertRaises(ValueError, mixer.Sound, array=a) + + def test_array_interface(self): + mixer.init(22050, -16, 1, allowedchanges=0) + snd = mixer.Sound(buffer=b"\x00\x7f" * 20) + d = snd.__array_interface__ + self.assertTrue(isinstance(d, dict)) + if pygame.get_sdl_byteorder() == pygame.LIL_ENDIAN: + typestr = "") if is_lil_endian else (">", "<") + shape = (10, channels)[:ndim] + strides = (channels * itemsize, itemsize)[2 - ndim :] + exp = Exporter(shape, format=frev + "i") + snd = mixer.Sound(array=exp) + buflen = len(exp) * itemsize * channels + imp = Importer(snd, buftools.PyBUF_SIMPLE) + self.assertEqual(imp.ndim, 0) + self.assertTrue(imp.format is None) + self.assertEqual(imp.len, buflen) + self.assertEqual(imp.itemsize, itemsize) + self.assertTrue(imp.shape is None) + self.assertTrue(imp.strides is None) + self.assertTrue(imp.suboffsets is None) + self.assertFalse(imp.readonly) + self.assertEqual(imp.buf, snd._samples_address) + imp = Importer(snd, buftools.PyBUF_WRITABLE) + self.assertEqual(imp.ndim, 0) + self.assertTrue(imp.format is None) + self.assertEqual(imp.len, buflen) + self.assertEqual(imp.itemsize, itemsize) + self.assertTrue(imp.shape is None) + self.assertTrue(imp.strides is None) + self.assertTrue(imp.suboffsets is None) + self.assertFalse(imp.readonly) + self.assertEqual(imp.buf, snd._samples_address) + imp = Importer(snd, buftools.PyBUF_FORMAT) + self.assertEqual(imp.ndim, 0) + self.assertEqual(imp.format, format) + self.assertEqual(imp.len, buflen) + self.assertEqual(imp.itemsize, itemsize) + self.assertTrue(imp.shape is None) + self.assertTrue(imp.strides is None) + self.assertTrue(imp.suboffsets is None) + self.assertFalse(imp.readonly) + self.assertEqual(imp.buf, snd._samples_address) + imp = Importer(snd, buftools.PyBUF_ND) + self.assertEqual(imp.ndim, ndim) + self.assertTrue(imp.format is None) + self.assertEqual(imp.len, buflen) + self.assertEqual(imp.itemsize, itemsize) + self.assertEqual(imp.shape, shape) + self.assertTrue(imp.strides is None) + self.assertTrue(imp.suboffsets is None) + self.assertFalse(imp.readonly) + self.assertEqual(imp.buf, snd._samples_address) + imp = Importer(snd, buftools.PyBUF_STRIDES) + self.assertEqual(imp.ndim, ndim) + self.assertTrue(imp.format is None) + self.assertEqual(imp.len, buflen) + self.assertEqual(imp.itemsize, itemsize) + self.assertEqual(imp.shape, shape) + self.assertEqual(imp.strides, strides) + self.assertTrue(imp.suboffsets is None) + self.assertFalse(imp.readonly) + self.assertEqual(imp.buf, snd._samples_address) + imp = Importer(snd, buftools.PyBUF_FULL_RO) + self.assertEqual(imp.ndim, ndim) + self.assertEqual(imp.format, format) + self.assertEqual(imp.len, buflen) + self.assertEqual(imp.itemsize, 2) + self.assertEqual(imp.shape, shape) + self.assertEqual(imp.strides, strides) + self.assertTrue(imp.suboffsets is None) + self.assertFalse(imp.readonly) + self.assertEqual(imp.buf, snd._samples_address) + imp = Importer(snd, buftools.PyBUF_FULL_RO) + self.assertEqual(imp.ndim, ndim) + self.assertEqual(imp.format, format) + self.assertEqual(imp.len, buflen) + self.assertEqual(imp.itemsize, itemsize) + self.assertEqual(imp.shape, exp.shape) + self.assertEqual(imp.strides, strides) + self.assertTrue(imp.suboffsets is None) + self.assertFalse(imp.readonly) + self.assertEqual(imp.buf, snd._samples_address) + imp = Importer(snd, buftools.PyBUF_C_CONTIGUOUS) + self.assertEqual(imp.ndim, ndim) + self.assertTrue(imp.format is None) + self.assertEqual(imp.strides, strides) + imp = Importer(snd, buftools.PyBUF_ANY_CONTIGUOUS) + self.assertEqual(imp.ndim, ndim) + self.assertTrue(imp.format is None) + self.assertEqual(imp.strides, strides) + if ndim == 1: + imp = Importer(snd, buftools.PyBUF_F_CONTIGUOUS) + self.assertEqual(imp.ndim, 1) + self.assertTrue(imp.format is None) + self.assertEqual(imp.strides, strides) + else: + self.assertRaises(BufferError, Importer, snd, buftools.PyBUF_F_CONTIGUOUS) + + def todo_test_fadeout(self): + + # __doc__ (as of 2008-08-02) for pygame.mixer.fadeout: + + # pygame.mixer.fadeout(time): return None + # fade out the volume on all sounds before stopping + # + # This will fade out the volume on all active channels over the time + # argument in milliseconds. After the sound is muted the playback will + # stop. + # + + self.fail() + + def test_find_channel(self): + # __doc__ (as of 2008-08-02) for pygame.mixer.find_channel: + + # pygame.mixer.find_channel(force=False): return Channel + # find an unused channel + mixer.init() + + filename = example_path(os.path.join("data", "house_lo.wav")) + sound = mixer.Sound(file=filename) + + num_channels = mixer.get_num_channels() + + if num_channels > 0: + found_channel = mixer.find_channel() + self.assertIsNotNone(found_channel) + + # try playing on all channels + channels = [] + for channel_id in range(0, num_channels): + channel = mixer.Channel(channel_id) + channel.play(sound) + channels.append(channel) + + # should fail without being forceful + found_channel = mixer.find_channel() + self.assertIsNone(found_channel) + + # try forcing without keyword + found_channel = mixer.find_channel(True) + self.assertIsNotNone(found_channel) + + # try forcing with keyword + found_channel = mixer.find_channel(force=True) + self.assertIsNotNone(found_channel) + + for channel in channels: + channel.stop() + found_channel = mixer.find_channel() + self.assertIsNotNone(found_channel) + + def todo_test_get_busy(self): + + # __doc__ (as of 2008-08-02) for pygame.mixer.get_busy: + + # pygame.mixer.get_busy(): return bool + # test if any sound is being mixed + # + # Returns True if the mixer is busy mixing any channels. If the mixer + # is idle then this return False. + # + + self.fail() + + def todo_test_pause(self): + + # __doc__ (as of 2008-08-02) for pygame.mixer.pause: + + # pygame.mixer.pause(): return None + # temporarily stop playback of all sound channels + # + # This will temporarily stop all playback on the active mixer + # channels. The playback can later be resumed with + # pygame.mixer.unpause() + # + + self.fail() + + def test_set_reserved(self): + + # __doc__ (as of 2008-08-02) for pygame.mixer.set_reserved: + + # pygame.mixer.set_reserved(count): return count + mixer.init() + default_num_channels = mixer.get_num_channels() + + # try reserving all the channels + result = mixer.set_reserved(default_num_channels) + self.assertEqual(result, default_num_channels) + + # try reserving all the channels + 1 + result = mixer.set_reserved(default_num_channels + 1) + # should still be default + self.assertEqual(result, default_num_channels) + + # try unreserving all + result = mixer.set_reserved(0) + # should still be default + self.assertEqual(result, 0) + + # try reserving half + result = mixer.set_reserved(int(default_num_channels / 2)) + # should still be default + self.assertEqual(result, int(default_num_channels / 2)) + + def todo_test_stop(self): + + # __doc__ (as of 2008-08-02) for pygame.mixer.stop: + + # pygame.mixer.stop(): return None + # stop playback of all sound channels + # + # This will stop all playback of all active mixer channels. + + self.fail() + + def todo_test_unpause(self): + + # __doc__ (as of 2008-08-02) for pygame.mixer.unpause: + + # pygame.mixer.unpause(): return None + # resume paused playback of sound channels + # + # This will resume all active sound channels after they have been paused. + + self.fail() + + def test_get_sdl_mixer_version(self): + """Ensures get_sdl_mixer_version works correctly with no args.""" + expected_length = 3 + expected_type = tuple + expected_item_type = int + + version = pygame.mixer.get_sdl_mixer_version() + + self.assertIsInstance(version, expected_type) + self.assertEqual(len(version), expected_length) + + for item in version: + self.assertIsInstance(item, expected_item_type) + + def test_get_sdl_mixer_version__args(self): + """Ensures get_sdl_mixer_version works correctly using args.""" + expected_length = 3 + expected_type = tuple + expected_item_type = int + + for value in (True, False): + version = pygame.mixer.get_sdl_mixer_version(value) + + self.assertIsInstance(version, expected_type) + self.assertEqual(len(version), expected_length) + + for item in version: + self.assertIsInstance(item, expected_item_type) + + def test_get_sdl_mixer_version__kwargs(self): + """Ensures get_sdl_mixer_version works correctly using kwargs.""" + expected_length = 3 + expected_type = tuple + expected_item_type = int + + for value in (True, False): + version = pygame.mixer.get_sdl_mixer_version(linked=value) + + self.assertIsInstance(version, expected_type) + self.assertEqual(len(version), expected_length) + + for item in version: + self.assertIsInstance(item, expected_item_type) + + def test_get_sdl_mixer_version__invalid_args_kwargs(self): + """Ensures get_sdl_mixer_version handles invalid args and kwargs.""" + invalid_bool = InvalidBool() + + with self.assertRaises(TypeError): + version = pygame.mixer.get_sdl_mixer_version(invalid_bool) + + with self.assertRaises(TypeError): + version = pygame.mixer.get_sdl_mixer_version(linked=invalid_bool) + + def test_get_sdl_mixer_version__linked_equals_compiled(self): + """Ensures get_sdl_mixer_version's linked/compiled versions are equal.""" + linked_version = pygame.mixer.get_sdl_mixer_version(linked=True) + complied_version = pygame.mixer.get_sdl_mixer_version(linked=False) + + self.assertTupleEqual(linked_version, complied_version) + + +############################## CHANNEL CLASS TESTS ############################# + + +class ChannelTypeTest(AssertRaisesRegexMixin, unittest.TestCase): + @classmethod + def setUpClass(cls): + # Initializing the mixer is slow, so minimize the times it is called. + mixer.init() + + @classmethod + def tearDownClass(cls): + mixer.quit() + + def setUp(cls): + # This makes sure the mixer is always initialized before each test (in + # case a test calls pygame.mixer.quit()). + if mixer.get_init() is None: + mixer.init() + + def test_channel(self): + """Ensure Channel() creation works.""" + channel = mixer.Channel(0) + + self.assertIsInstance(channel, mixer.ChannelType) + self.assertEqual(channel.__class__.__name__, "Channel") + + def test_channel__without_arg(self): + """Ensure exception for Channel() creation with no argument.""" + with self.assertRaises(TypeError): + mixer.Channel() + + def test_channel__invalid_id(self): + """Ensure exception for Channel() creation with an invalid id.""" + with self.assertRaises(IndexError): + mixer.Channel(-1) + + def test_channel__before_init(self): + """Ensure exception for Channel() creation with non-init mixer.""" + mixer.quit() + + with self.assertRaisesRegex(pygame.error, "mixer not initialized"): + mixer.Channel(0) + + def todo_test_fadeout(self): + + # __doc__ (as of 2008-08-02) for pygame.mixer.Channel.fadeout: + + # Channel.fadeout(time): return None + # stop playback after fading channel out + # + # Stop playback of a channel after fading out the sound over the given + # time argument in milliseconds. + # + + self.fail() + + def test_get_busy(self): + """Ensure an idle channel's busy state is correct.""" + expected_busy = False + channel = mixer.Channel(0) + + busy = channel.get_busy() + + self.assertEqual(busy, expected_busy) + + def todo_test_get_busy__active(self): + """Ensure an active channel's busy state is correct.""" + self.fail() + + def todo_test_get_endevent(self): + + # __doc__ (as of 2008-08-02) for pygame.mixer.Channel.get_endevent: + + # Channel.get_endevent(): return type + # get the event a channel sends when playback stops + # + # Returns the event type to be sent every time the Channel finishes + # playback of a Sound. If there is no endevent the function returns + # pygame.NOEVENT. + # + + self.fail() + + def todo_test_get_queue(self): + + # __doc__ (as of 2008-08-02) for pygame.mixer.Channel.get_queue: + + # Channel.get_queue(): return Sound + # return any Sound that is queued + # + # If a Sound is already queued on this channel it will be returned. + # Once the queued sound begins playback it will no longer be on the + # queue. + # + + self.fail() + + def todo_test_get_sound(self): + + # __doc__ (as of 2008-08-02) for pygame.mixer.Channel.get_sound: + + # Channel.get_sound(): return Sound + # get the currently playing Sound + # + # Return the actual Sound object currently playing on this channel. If + # the channel is idle None is returned. + # + + self.fail() + + def test_get_volume(self): + """Ensure a channel's volume can be retrieved.""" + expected_volume = 1.0 # default + channel = mixer.Channel(0) + + volume = channel.get_volume() + + self.assertAlmostEqual(volume, expected_volume) + + def todo_test_get_volume__while_playing(self): + """Ensure a channel's volume can be retrieved while playing.""" + self.fail() + + def todo_test_pause(self): + + # __doc__ (as of 2008-08-02) for pygame.mixer.Channel.pause: + + # Channel.pause(): return None + # temporarily stop playback of a channel + # + # Temporarily stop the playback of sound on a channel. It can be + # resumed at a later time with Channel.unpause() + # + + self.fail() + + def todo_test_play(self): + + # __doc__ (as of 2008-08-02) for pygame.mixer.Channel.play: + + # Channel.play(Sound, loops=0, maxtime=0, fade_ms=0): return None + # play a Sound on a specific Channel + # + # This will begin playback of a Sound on a specific Channel. If the + # Channel is currently playing any other Sound it will be stopped. + # + # The loops argument has the same meaning as in Sound.play(): it is + # the number of times to repeat the sound after the first time. If it + # is 3, the sound will be played 4 times (the first time, then three + # more). If loops is -1 then the playback will repeat indefinitely. + # + # As in Sound.play(), the maxtime argument can be used to stop + # playback of the Sound after a given number of milliseconds. + # + # As in Sound.play(), the fade_ms argument can be used fade in the sound. + + self.fail() + + def todo_test_queue(self): + + # __doc__ (as of 2008-08-02) for pygame.mixer.Channel.queue: + + # Channel.queue(Sound): return None + # queue a Sound object to follow the current + # + # When a Sound is queued on a Channel, it will begin playing + # immediately after the current Sound is finished. Each channel can + # only have a single Sound queued at a time. The queued Sound will + # only play if the current playback finished automatically. It is + # cleared on any other call to Channel.stop() or Channel.play(). + # + # If there is no sound actively playing on the Channel then the Sound + # will begin playing immediately. + # + + self.fail() + + def todo_test_set_endevent(self): + + # __doc__ (as of 2008-08-02) for pygame.mixer.Channel.set_endevent: + + # Channel.set_endevent(): return None + # Channel.set_endevent(type): return None + # have the channel send an event when playback stops + # + # When an endevent is set for a channel, it will send an event to the + # pygame queue every time a sound finishes playing on that channel + # (not just the first time). Use pygame.event.get() to retrieve the + # endevent once it's sent. + # + # Note that if you called Sound.play(n) or Channel.play(sound,n), the + # end event is sent only once: after the sound has been played "n+1" + # times (see the documentation of Sound.play). + # + # If Channel.stop() or Channel.play() is called while the sound was + # still playing, the event will be posted immediately. + # + # The type argument will be the event id sent to the queue. This can + # be any valid event type, but a good choice would be a value between + # pygame.locals.USEREVENT and pygame.locals.NUMEVENTS. If no type + # argument is given then the Channel will stop sending endevents. + # + + self.fail() + + def todo_test_set_volume(self): + + # __doc__ (as of 2008-08-02) for pygame.mixer.Channel.set_volume: + + # Channel.set_volume(value): return None + # Channel.set_volume(left, right): return None + # set the volume of a playing channel + # + # Set the volume (loudness) of a playing sound. When a channel starts + # to play its volume value is reset. This only affects the current + # sound. The value argument is between 0.0 and 1.0. + # + # If one argument is passed, it will be the volume of both speakers. + # If two arguments are passed and the mixer is in stereo mode, the + # first argument will be the volume of the left speaker and the second + # will be the volume of the right speaker. (If the second argument is + # None, the first argument will be the volume of both speakers.) + # + # If the channel is playing a Sound on which set_volume() has also + # been called, both calls are taken into account. For example: + # + # sound = pygame.mixer.Sound("s.wav") + # channel = s.play() # Sound plays at full volume by default + # sound.set_volume(0.9) # Now plays at 90% of full volume. + # sound.set_volume(0.6) # Now plays at 60% (previous value replaced). + # channel.set_volume(0.5) # Now plays at 30% (0.6 * 0.5). + + self.fail() + + def todo_test_stop(self): + + # __doc__ (as of 2008-08-02) for pygame.mixer.Channel.stop: + + # Channel.stop(): return None + # stop playback on a Channel + # + # Stop sound playback on a channel. After playback is stopped the + # channel becomes available for new Sounds to play on it. + # + + self.fail() + + def todo_test_unpause(self): + + # __doc__ (as of 2008-08-02) for pygame.mixer.Channel.unpause: + + # Channel.unpause(): return None + # resume pause playback of a channel + # + # Resume the playback on a paused channel. + + self.fail() + + +############################### SOUND CLASS TESTS ############################## + + +class SoundTypeTest(AssertRaisesRegexMixin, unittest.TestCase): + @classmethod + def tearDownClass(cls): + mixer.quit() + + def setUp(cls): + # This makes sure the mixer is always initialized before each test (in + # case a test calls pygame.mixer.quit()). + if mixer.get_init() is None: + mixer.init() + + # See MixerModuleTest's methods test_sound_args(), test_sound_unicode(), + # and test_array_keyword() for additional testing of Sound() creation. + def test_sound(self): + """Ensure Sound() creation with a filename works.""" + filename = example_path(os.path.join("data", "house_lo.wav")) + sound1 = mixer.Sound(filename) + sound2 = mixer.Sound(file=filename) + + self.assertIsInstance(sound1, mixer.Sound) + self.assertIsInstance(sound2, mixer.Sound) + + def test_sound__from_file_object(self): + """Ensure Sound() creation with a file object works.""" + filename = example_path(os.path.join("data", "house_lo.wav")) + + # Using 'with' ensures the file is closed even if test fails. + with open(filename, "rb") as file_obj: + sound = mixer.Sound(file_obj) + + self.assertIsInstance(sound, mixer.Sound) + + def test_sound__from_sound_object(self): + """Ensure Sound() creation with a Sound() object works.""" + filename = example_path(os.path.join("data", "house_lo.wav")) + sound_obj = mixer.Sound(file=filename) + + sound = mixer.Sound(sound_obj) + + self.assertIsInstance(sound, mixer.Sound) + + def test_sound__from_pathlib(self): + """Ensure Sound() creation with a pathlib.Path object works.""" + path = pathlib.Path(example_path(os.path.join("data", "house_lo.wav"))) + sound1 = mixer.Sound(path) + sound2 = mixer.Sound(file=path) + self.assertIsInstance(sound1, mixer.Sound) + self.assertIsInstance(sound2, mixer.Sound) + + def todo_test_sound__from_buffer(self): + """Ensure Sound() creation with a buffer works.""" + self.fail() + + def todo_test_sound__from_array(self): + """Ensure Sound() creation with an array works.""" + self.fail() + + def test_sound__without_arg(self): + """Ensure exception raised for Sound() creation with no argument.""" + with self.assertRaises(TypeError): + mixer.Sound() + + def test_sound__before_init(self): + """Ensure exception raised for Sound() creation with non-init mixer.""" + mixer.quit() + filename = example_path(os.path.join("data", "house_lo.wav")) + + with self.assertRaisesRegex(pygame.error, "mixer not initialized"): + mixer.Sound(file=filename) + + @unittest.skipIf(IS_PYPY, "pypy skip") + def test_samples_address(self): + """Test the _samples_address getter.""" + try: + from ctypes import pythonapi, c_void_p, py_object + + Bytes_FromString = pythonapi.PyBytes_FromString + + Bytes_FromString.restype = c_void_p + Bytes_FromString.argtypes = [py_object] + samples = b"abcdefgh" # keep byte size a multiple of 4 + sample_bytes = Bytes_FromString(samples) + + snd = mixer.Sound(buffer=samples) + + self.assertNotEqual(snd._samples_address, sample_bytes) + finally: + pygame.mixer.quit() + with self.assertRaisesRegex(pygame.error, "mixer not initialized"): + snd._samples_address + + def todo_test_fadeout(self): + + # __doc__ (as of 2008-08-02) for pygame.mixer.Sound.fadeout: + + # Sound.fadeout(time): return None + # stop sound playback after fading out + # + # This will stop playback of the sound after fading it out over the + # time argument in milliseconds. The Sound will fade and stop on all + # actively playing channels. + # + + self.fail() + + def test_get_length(self): + """Tests if get_length returns a correct length.""" + try: + for size in SIZES: + pygame.mixer.quit() + pygame.mixer.init(size=size) + filename = example_path(os.path.join("data", "punch.wav")) + sound = mixer.Sound(file=filename) + # The sound data is in the mixer output format. So dividing the + # length of the raw sound data by the mixer settings gives + # the expected length of the sound. + sound_bytes = sound.get_raw() + mix_freq, mix_bits, mix_channels = pygame.mixer.get_init() + mix_bytes = abs(mix_bits) / 8 + expected_length = ( + float(len(sound_bytes)) / mix_freq / mix_bytes / mix_channels + ) + self.assertAlmostEqual(expected_length, sound.get_length()) + finally: + pygame.mixer.quit() + with self.assertRaisesRegex(pygame.error, "mixer not initialized"): + sound.get_length() + + def test_get_num_channels(self): + """ + Tests if Sound.get_num_channels returns the correct number + of channels playing a specific sound. + """ + try: + filename = example_path(os.path.join("data", "house_lo.wav")) + sound = mixer.Sound(file=filename) + + self.assertEqual(sound.get_num_channels(), 0) + sound.play() + self.assertEqual(sound.get_num_channels(), 1) + sound.play() + self.assertEqual(sound.get_num_channels(), 2) + sound.stop() + self.assertEqual(sound.get_num_channels(), 0) + finally: + pygame.mixer.quit() + with self.assertRaisesRegex(pygame.error, "mixer not initialized"): + sound.get_num_channels() + + def test_get_volume(self): + """Ensure a sound's volume can be retrieved.""" + try: + expected_volume = 1.0 # default + filename = example_path(os.path.join("data", "house_lo.wav")) + sound = mixer.Sound(file=filename) + + volume = sound.get_volume() + + self.assertAlmostEqual(volume, expected_volume) + finally: + pygame.mixer.quit() + with self.assertRaisesRegex(pygame.error, "mixer not initialized"): + sound.get_volume() + + def todo_test_get_volume__while_playing(self): + """Ensure a sound's volume can be retrieved while playing.""" + self.fail() + + def todo_test_play(self): + + # __doc__ (as of 2008-08-02) for pygame.mixer.Sound.play: + + # Sound.play(loops=0, maxtime=0, fade_ms=0): return Channel + # begin sound playback + # + # Begin playback of the Sound (i.e., on the computer's speakers) on an + # available Channel. This will forcibly select a Channel, so playback + # may cut off a currently playing sound if necessary. + # + # The loops argument controls how many times the sample will be + # repeated after being played the first time. A value of 5 means that + # the sound will be played once, then repeated five times, and so is + # played a total of six times. The default value (zero) means the + # Sound is not repeated, and so is only played once. If loops is set + # to -1 the Sound will loop indefinitely (though you can still call + # stop() to stop it). + # + # The maxtime argument can be used to stop playback after a given + # number of milliseconds. + # + # The fade_ms argument will make the sound start playing at 0 volume + # and fade up to full volume over the time given. The sample may end + # before the fade-in is complete. + # + # This returns the Channel object for the channel that was selected. + + self.fail() + + def test_set_volume(self): + """Ensure a sound's volume can be set.""" + try: + float_delta = 1.0 / 128 # SDL volume range is 0 to 128 + filename = example_path(os.path.join("data", "house_lo.wav")) + sound = mixer.Sound(file=filename) + current_volume = sound.get_volume() + + # (volume_set_value : expected_volume) + volumes = ( + (-1, current_volume), # value < 0 won't change volume + (0, 0.0), + (0.01, 0.01), + (0.1, 0.1), + (0.5, 0.5), + (0.9, 0.9), + (0.99, 0.99), + (1, 1.0), + (1.1, 1.0), + (2.0, 1.0), + ) + + for volume_set_value, expected_volume in volumes: + sound.set_volume(volume_set_value) + + self.assertAlmostEqual( + sound.get_volume(), expected_volume, delta=float_delta + ) + finally: + pygame.mixer.quit() + with self.assertRaisesRegex(pygame.error, "mixer not initialized"): + sound.set_volume(1) + + def todo_test_set_volume__while_playing(self): + """Ensure a sound's volume can be set while playing.""" + self.fail() + + def test_stop(self): + """Ensure stop can be called while not playing a sound.""" + try: + expected_channels = 0 + filename = example_path(os.path.join("data", "house_lo.wav")) + sound = mixer.Sound(file=filename) + + sound.stop() + + self.assertEqual(sound.get_num_channels(), expected_channels) + finally: + pygame.mixer.quit() + with self.assertRaisesRegex(pygame.error, "mixer not initialized"): + sound.stop() + + def todo_test_stop__while_playing(self): + """Ensure stop stops a playing sound.""" + self.fail() + + def test_get_raw(self): + """Ensure get_raw returns the correct bytestring.""" + try: + samples = b"abcdefgh" # keep byte size a multiple of 4 + snd = mixer.Sound(buffer=samples) + + raw = snd.get_raw() + + self.assertIsInstance(raw, bytes) + self.assertEqual(raw, samples) + finally: + pygame.mixer.quit() + with self.assertRaisesRegex(pygame.error, "mixer not initialized"): + snd.get_raw() + + +##################################### MAIN ##################################### + +if __name__ == "__main__": + unittest.main() diff --git a/venv/Lib/site-packages/pygame/tests/mouse_test.py b/venv/Lib/site-packages/pygame/tests/mouse_test.py new file mode 100644 index 0000000..c23035f --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/mouse_test.py @@ -0,0 +1,350 @@ +import unittest +import os +import platform +import warnings +import pygame + + +DARWIN = "Darwin" in platform.platform() + + +class MouseTests(unittest.TestCase): + @classmethod + def setUpClass(cls): + # The display needs to be initialized for mouse functions. + pygame.display.init() + + @classmethod + def tearDownClass(cls): + pygame.display.quit() + + +class MouseModuleInteractiveTest(MouseTests): + + __tags__ = ["interactive"] + + def test_set_pos(self): + """Ensures set_pos works correctly. + Requires tester to move the mouse to be on the window. + """ + pygame.display.set_mode((500, 500)) + pygame.event.get() # Pump event queue to make window get focus on macos. + + if not pygame.mouse.get_focused(): + # The window needs to be focused for the mouse.set_pos to work on macos. + return + clock = pygame.time.Clock() + + expected_pos = ((10, 0), (0, 0), (499, 0), (499, 499), (341, 143), (94, 49)) + + for x, y in expected_pos: + pygame.mouse.set_pos(x, y) + pygame.event.get() + found_pos = pygame.mouse.get_pos() + + clock.tick() + time_passed = 0.0 + ready_to_test = False + + while not ready_to_test and time_passed <= 1000.0: # Avoid endless loop + time_passed += clock.tick() + for event in pygame.event.get(): + if event.type == pygame.MOUSEMOTION: + ready_to_test = True + + self.assertEqual(found_pos, (x, y)) + + +class MouseModuleTest(MouseTests): + @unittest.skipIf( + os.environ.get("SDL_VIDEODRIVER", "") == "dummy", + "Cursors not supported on headless test machines", + ) + def test_get_cursor(self): + """Ensures get_cursor works correctly.""" + + # error should be raised when the display is unintialized + with self.assertRaises(pygame.error): + pygame.display.quit() + pygame.mouse.get_cursor() + + pygame.display.init() + + size = (8, 8) + hotspot = (0, 0) + xormask = (0, 96, 120, 126, 112, 96, 0, 0) + andmask = (224, 240, 254, 255, 254, 240, 96, 0) + + expected_length = 4 + expected_cursor = pygame.cursors.Cursor(size, hotspot, xormask, andmask) + pygame.mouse.set_cursor(expected_cursor) + + try: + cursor = pygame.mouse.get_cursor() + + self.assertIsInstance(cursor, pygame.cursors.Cursor) + self.assertEqual(len(cursor), expected_length) + + for info in cursor: + self.assertIsInstance(info, tuple) + + pygame.mouse.set_cursor(size, hotspot, xormask, andmask) + self.assertEqual(pygame.mouse.get_cursor(), expected_cursor) + + # SDLError should be raised when the mouse cursor is NULL + except pygame.error: + with self.assertRaises(pygame.error): + pygame.mouse.get_cursor() + + @unittest.skipIf( + os.environ.get("SDL_VIDEODRIVER", "") == "dummy", + "mouse.set_system_cursor only available in SDL2", + ) + def test_set_system_cursor(self): + """Ensures set_system_cursor works correctly.""" + + with warnings.catch_warnings(record=True) as w: + """From Pygame 2.0.1, set_system_cursor() should raise a deprecation warning""" + # Cause all warnings to always be triggered. + warnings.simplefilter("always") + + # Error should be raised when the display is uninitialized + with self.assertRaises(pygame.error): + pygame.display.quit() + pygame.mouse.set_system_cursor(pygame.SYSTEM_CURSOR_HAND) + + pygame.display.init() + + # TypeError raised when PyArg_ParseTuple fails to parse parameters + with self.assertRaises(TypeError): + pygame.mouse.set_system_cursor("b") + with self.assertRaises(TypeError): + pygame.mouse.set_system_cursor(None) + with self.assertRaises(TypeError): + pygame.mouse.set_system_cursor((8, 8), (0, 0)) + + # Right type, invalid value + with self.assertRaises(pygame.error): + pygame.mouse.set_system_cursor(2000) + + # Working as intended + self.assertEqual( + pygame.mouse.set_system_cursor(pygame.SYSTEM_CURSOR_ARROW), None + ) + + # Making sure the warnings are working properly + self.assertEqual(len(w), 6) + self.assertTrue( + all([issubclass(warn.category, DeprecationWarning) for warn in w]) + ) + + @unittest.skipIf( + os.environ.get("SDL_VIDEODRIVER", "") == "dummy", + "Cursors not supported on headless test machines", + ) + def test_set_cursor(self): + """Ensures set_cursor works correctly.""" + + # Bitmap cursor information + size = (8, 8) + hotspot = (0, 0) + xormask = (0, 126, 64, 64, 32, 16, 0, 0) + andmask = (254, 255, 254, 112, 56, 28, 12, 0) + bitmap_cursor = pygame.cursors.Cursor(size, hotspot, xormask, andmask) + + # System cursor information + constant = pygame.SYSTEM_CURSOR_ARROW + system_cursor = pygame.cursors.Cursor(constant) + + # Color cursor information (also uses hotspot variable from Bitmap cursor info) + surface = pygame.Surface((10, 10)) + color_cursor = pygame.cursors.Cursor(hotspot, surface) + + pygame.display.quit() + + # Bitmap: Error should be raised when the display is uninitialized + with self.assertRaises(pygame.error): + pygame.mouse.set_cursor(bitmap_cursor) + + # System: Error should be raised when the display is uninitialized + with self.assertRaises(pygame.error): + pygame.mouse.set_cursor(system_cursor) + + # Color: Error should be raised when the display is uninitialized + with self.assertRaises(pygame.error): + pygame.mouse.set_cursor(color_cursor) + + pygame.display.init() + + # Bitmap: TypeError raised when PyArg_ParseTuple fails to parse parameters + with self.assertRaises(TypeError): + pygame.mouse.set_cursor(("w", "h"), hotspot, xormask, andmask) + with self.assertRaises(TypeError): + pygame.mouse.set_cursor(size, ("0", "0"), xormask, andmask) + with self.assertRaises(TypeError): + pygame.mouse.set_cursor(size, ("x", "y", "z"), xormask, andmask) + + # Bitmap: TypeError raised when either mask is not a sequence + with self.assertRaises(TypeError): + pygame.mouse.set_cursor(size, hotspot, 12345678, andmask) + with self.assertRaises(TypeError): + pygame.mouse.set_cursor(size, hotspot, xormask, 12345678) + + # Bitmap: TypeError raised when element of mask is not an integer + with self.assertRaises(TypeError): + pygame.mouse.set_cursor(size, hotspot, "00000000", andmask) + with self.assertRaises(TypeError): + pygame.mouse.set_cursor(size, hotspot, xormask, (2, [0], 4, 0, 0, 8, 0, 1)) + + # Bitmap: ValueError raised when width not divisible by 8 + with self.assertRaises(ValueError): + pygame.mouse.set_cursor((3, 8), hotspot, xormask, andmask) + + # Bitmap: ValueError raised when length of either mask != width * height / 8 + with self.assertRaises(ValueError): + pygame.mouse.set_cursor((16, 2), hotspot, (128, 64, 32), andmask) + with self.assertRaises(ValueError): + pygame.mouse.set_cursor((16, 2), hotspot, xormask, (192, 96, 48, 0, 1)) + + # Bitmap: Working as intended + self.assertEqual( + pygame.mouse.set_cursor((16, 1), hotspot, (8, 0), (0, 192)), None + ) + pygame.mouse.set_cursor(size, hotspot, xormask, andmask) + self.assertEqual(pygame.mouse.get_cursor(), bitmap_cursor) + + # Bitmap: Working as intended + lists + masks with no references + pygame.mouse.set_cursor(size, hotspot, list(xormask), list(andmask)) + self.assertEqual(pygame.mouse.get_cursor(), bitmap_cursor) + + # System: TypeError raised when constant is invalid + with self.assertRaises(TypeError): + pygame.mouse.set_cursor(-50021232) + with self.assertRaises(TypeError): + pygame.mouse.set_cursor("yellow") + + # System: Working as intended + self.assertEqual(pygame.mouse.set_cursor(constant), None) + pygame.mouse.set_cursor(constant) + self.assertEqual(pygame.mouse.get_cursor(), system_cursor) + pygame.mouse.set_cursor(system_cursor) + self.assertEqual(pygame.mouse.get_cursor(), system_cursor) + + # Color: TypeError raised with invalid parameters + with self.assertRaises(TypeError): + pygame.mouse.set_cursor(("x", "y"), surface) + with self.assertRaises(TypeError): + pygame.mouse.set_cursor(hotspot, "not_a_surface") + + # Color: Working as intended + self.assertEqual(pygame.mouse.set_cursor(hotspot, surface), None) + pygame.mouse.set_cursor(hotspot, surface) + self.assertEqual(pygame.mouse.get_cursor(), color_cursor) + pygame.mouse.set_cursor(color_cursor) + self.assertEqual(pygame.mouse.get_cursor(), color_cursor) + + # Color: Working as intended + Surface with no references is returned okay + pygame.mouse.set_cursor((0, 0), pygame.Surface((20, 20))) + cursor = pygame.mouse.get_cursor() + self.assertEqual(cursor.type, "color") + self.assertEqual(cursor.data[0], (0, 0)) + self.assertEqual(cursor.data[1].get_size(), (20, 20)) + + def test_get_focused(self): + """Ensures get_focused returns the correct type.""" + focused = pygame.mouse.get_focused() + + self.assertIsInstance(focused, int) + + def test_get_pressed(self): + """Ensures get_pressed returns the correct types.""" + expected_length = 3 + buttons_pressed = pygame.mouse.get_pressed() + self.assertIsInstance(buttons_pressed, tuple) + self.assertEqual(len(buttons_pressed), expected_length) + for value in buttons_pressed: + self.assertIsInstance(value, bool) + + expected_length = 5 + buttons_pressed = pygame.mouse.get_pressed(num_buttons=5) + self.assertIsInstance(buttons_pressed, tuple) + self.assertEqual(len(buttons_pressed), expected_length) + for value in buttons_pressed: + self.assertIsInstance(value, bool) + + expected_length = 3 + buttons_pressed = pygame.mouse.get_pressed(3) + self.assertIsInstance(buttons_pressed, tuple) + self.assertEqual(len(buttons_pressed), expected_length) + for value in buttons_pressed: + self.assertIsInstance(value, bool) + + expected_length = 5 + buttons_pressed = pygame.mouse.get_pressed(5) + self.assertIsInstance(buttons_pressed, tuple) + self.assertEqual(len(buttons_pressed), expected_length) + for value in buttons_pressed: + self.assertIsInstance(value, bool) + + with self.assertRaises(ValueError): + pygame.mouse.get_pressed(4) + + def test_get_pos(self): + """Ensures get_pos returns the correct types.""" + expected_length = 2 + + pos = pygame.mouse.get_pos() + + self.assertIsInstance(pos, tuple) + self.assertEqual(len(pos), expected_length) + for value in pos: + self.assertIsInstance(value, int) + + def test_set_pos__invalid_pos(self): + """Ensures set_pos handles invalid positions correctly.""" + for invalid_pos in ((1,), [1, 2, 3], 1, "1", (1, "1"), []): + + with self.assertRaises(TypeError): + pygame.mouse.set_pos(invalid_pos) + + def test_get_rel(self): + """Ensures get_rel returns the correct types.""" + expected_length = 2 + + rel = pygame.mouse.get_rel() + + self.assertIsInstance(rel, tuple) + self.assertEqual(len(rel), expected_length) + for value in rel: + self.assertIsInstance(value, int) + + def test_get_visible(self): + """Ensures get_visible works correctly.""" + for expected_value in (False, True): + pygame.mouse.set_visible(expected_value) + + visible = pygame.mouse.get_visible() + + self.assertEqual(visible, expected_value) + + def test_set_visible(self): + """Ensures set_visible returns the correct values.""" + # Set to a known state. + pygame.mouse.set_visible(True) + + for expected_visible in (False, True): + prev_visible = pygame.mouse.set_visible(expected_visible) + + self.assertEqual(prev_visible, not expected_visible) + + def test_set_visible__invalid_value(self): + """Ensures set_visible handles invalid positions correctly.""" + for invalid_value in ((1,), [1, 2, 3], 1.1, "1", (1, "1"), []): + with self.assertRaises(TypeError): + prev_visible = pygame.mouse.set_visible(invalid_value) + + +################################################################################ + +if __name__ == "__main__": + unittest.main() diff --git a/venv/Lib/site-packages/pygame/tests/pixelarray_test.py b/venv/Lib/site-packages/pygame/tests/pixelarray_test.py new file mode 100644 index 0000000..c93f36a --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/pixelarray_test.py @@ -0,0 +1,1660 @@ +import sys +import platform + +try: + reduce +except NameError: + from functools import reduce +import operator +import weakref +import gc +import unittest + +from pygame.tests.test_utils import SurfaceSubclass + +try: + from pygame.tests.test_utils import arrinter +except NameError: + pass + +import pygame + + +IS_PYPY = "PyPy" == platform.python_implementation() + + +class TestMixin(object): + def assert_surfaces_equal(self, s1, s2, msg=None): + """Checks if two surfaces are equal in size and color.""" + w, h = s1.get_size() + + self.assertTupleEqual((w, h), s2.get_size(), msg) + + msg = "" if msg is None else "{}, ".format(msg) + msg += "size: ({}, {})".format(w, h) + + for x in range(w): + for y in range(h): + self.assertEqual( + s1.get_at((x, y)), + s2.get_at((x, y)), + "{}, position: ({}, {})".format(msg, x, y), + ) + + def assert_surface_filled(self, surface, expected_color, msg=None): + """Checks if the surface is filled with the given color.""" + width, height = surface.get_size() + + surface.lock() # Lock for possible speed up. + for pos in ((x, y) for y in range(height) for x in range(width)): + self.assertEqual(surface.get_at(pos), expected_color, msg) + surface.unlock() + + +@unittest.skipIf(IS_PYPY, "pypy having issues") +class PixelArrayTypeTest(unittest.TestCase, TestMixin): + def test_compare(self): + # __doc__ (as of 2008-06-25) for pygame.pixelarray.PixelArray.compare: + + # PixelArray.compare (array, distance=0, weights=(0.299, 0.587, 0.114)): Return PixelArray + # Compares the PixelArray with another one. + + w = 10 + h = 20 + size = w, h + sf = pygame.Surface(size, 0, 32) + ar = pygame.PixelArray(sf) + sf2 = pygame.Surface(size, 0, 32) + self.assertRaises(TypeError, ar.compare, sf2) + ar2 = pygame.PixelArray(sf2) + ar3 = ar.compare(ar2) + self.assertTrue(isinstance(ar3, pygame.PixelArray)) + self.assertEqual(ar3.shape, size) + sf2.fill(pygame.Color("white")) + self.assert_surfaces_equal(sf2, ar3.surface) + del ar3 + r = pygame.Rect(2, 5, 6, 13) + sf.fill(pygame.Color("blue"), r) + sf2.fill(pygame.Color("red")) + sf2.fill(pygame.Color("blue"), r) + ar3 = ar.compare(ar2) + sf.fill(pygame.Color("white"), r) + self.assert_surfaces_equal(sf, ar3.surface) + + # FINISH ME! + # Test other bit depths, slices, and distance != 0. + + def test_compare__same_colors_within_distance(self): + """Ensures compare works correctly with same colored surfaces.""" + size = (3, 5) + pixelarray_result_color = pygame.Color("white") + surface_color = (127, 127, 127, 255) + + for depth in (8, 16, 24, 32): + expected_pixelarray_surface = pygame.Surface(size, depth=depth) + expected_pixelarray_surface.fill(pixelarray_result_color) + + # Copy the surface to ensure same dimensions/formatting. + surf_a = expected_pixelarray_surface.copy() + surf_a.fill(surface_color) + # For non-32 bit depths, the actual color can be different from what + # was filled. + expected_surface_color = surf_a.get_at((0, 0)) + + pixelarray_a = pygame.PixelArray(surf_a) + pixelarray_b = pygame.PixelArray(surf_a.copy()) + + for distance in (0.0, 0.01, 0.1, 1.0): + pixelarray_result = pixelarray_a.compare( + pixelarray_b, distance=distance + ) + + # Ensure the resulting pixelarray is correct and that the original + # surfaces were not changed. + self.assert_surfaces_equal( + pixelarray_result.surface, + expected_pixelarray_surface, + (depth, distance), + ) + self.assert_surface_filled( + pixelarray_a.surface, expected_surface_color, (depth, distance) + ) + self.assert_surface_filled( + pixelarray_b.surface, expected_surface_color, (depth, distance) + ) + + pixelarray_a.close() + pixelarray_b.close() + pixelarray_result.close() + + def test_compare__different_colors_within_distance(self): + """Ensures compare works correctly with different colored surfaces + and the color difference is within the given distance. + """ + size = (3, 5) + pixelarray_result_color = pygame.Color("white") + surface_a_color = (127, 127, 127, 255) + surface_b_color = (128, 127, 127, 255) + + for depth in (8, 16, 24, 32): + expected_pixelarray_surface = pygame.Surface(size, depth=depth) + expected_pixelarray_surface.fill(pixelarray_result_color) + + # Copy the surface to ensure same dimensions/formatting. + surf_a = expected_pixelarray_surface.copy() + surf_a.fill(surface_a_color) + # For non-32 bit depths, the actual color can be different from what + # was filled. + expected_surface_a_color = surf_a.get_at((0, 0)) + pixelarray_a = pygame.PixelArray(surf_a) + + surf_b = expected_pixelarray_surface.copy() + surf_b.fill(surface_b_color) + # For non-32 bit depths, the actual color can be different from what + # was filled. + expected_surface_b_color = surf_b.get_at((0, 0)) + pixelarray_b = pygame.PixelArray(surf_b) + + for distance in (0.2, 0.3, 0.5, 1.0): + pixelarray_result = pixelarray_a.compare( + pixelarray_b, distance=distance + ) + + # Ensure the resulting pixelarray is correct and that the original + # surfaces were not changed. + self.assert_surfaces_equal( + pixelarray_result.surface, + expected_pixelarray_surface, + (depth, distance), + ) + self.assert_surface_filled( + pixelarray_a.surface, expected_surface_a_color, (depth, distance) + ) + self.assert_surface_filled( + pixelarray_b.surface, expected_surface_b_color, (depth, distance) + ) + + pixelarray_a.close() + pixelarray_b.close() + pixelarray_result.close() + + def test_compare__different_colors_not_within_distance(self): + """Ensures compare works correctly with different colored surfaces + and the color difference is not within the given distance. + """ + size = (3, 5) + pixelarray_result_color = pygame.Color("black") + surface_a_color = (127, 127, 127, 255) + surface_b_color = (128, 127, 127, 255) + + for depth in (8, 16, 24, 32): + expected_pixelarray_surface = pygame.Surface(size, depth=depth) + expected_pixelarray_surface.fill(pixelarray_result_color) + + # Copy the surface to ensure same dimensions/formatting. + surf_a = expected_pixelarray_surface.copy() + surf_a.fill(surface_a_color) + # For non-32 bit depths, the actual color can be different from what + # was filled. + expected_surface_a_color = surf_a.get_at((0, 0)) + pixelarray_a = pygame.PixelArray(surf_a) + + surf_b = expected_pixelarray_surface.copy() + surf_b.fill(surface_b_color) + # For non-32 bit depths, the actual color can be different from what + # was filled. + expected_surface_b_color = surf_b.get_at((0, 0)) + pixelarray_b = pygame.PixelArray(surf_b) + + for distance in (0.0, 0.00001, 0.0001, 0.001): + pixelarray_result = pixelarray_a.compare( + pixelarray_b, distance=distance + ) + + # Ensure the resulting pixelarray is correct and that the original + # surfaces were not changed. + self.assert_surfaces_equal( + pixelarray_result.surface, + expected_pixelarray_surface, + (depth, distance), + ) + self.assert_surface_filled( + pixelarray_a.surface, expected_surface_a_color, (depth, distance) + ) + self.assert_surface_filled( + pixelarray_b.surface, expected_surface_b_color, (depth, distance) + ) + + pixelarray_a.close() + pixelarray_b.close() + pixelarray_result.close() + + def test_close(self): + """does not crash when it is deleted.""" + s = pygame.Surface((10, 10)) + a = pygame.PixelArray(s) + a.close() + del a + + def test_close_raises(self): + """when you try to do an operation after it is closed.""" + s = pygame.Surface((10, 10)) + a = pygame.PixelArray(s) + a.close() + + def do_operation(): + a[:] + + self.assertRaises(ValueError, do_operation) + + def do_operation2(): + a[:] = 1 + + self.assertRaises(ValueError, do_operation2) + + def do_operation3(): + a.make_surface() + + self.assertRaises(ValueError, do_operation3) + + def do_operation4(): + for x in a: + pass + + self.assertRaises(ValueError, do_operation4) + + def test_context_manager(self): + """closes properly.""" + s = pygame.Surface((10, 10)) + with pygame.PixelArray(s) as a: + a[:] + + def test_pixel_array(self): + for bpp in (8, 16, 24, 32): + sf = pygame.Surface((10, 20), 0, bpp) + sf.fill((0, 0, 0)) + ar = pygame.PixelArray(sf) + + self.assertEqual(ar._pixels_address, sf._pixels_address) + + if sf.mustlock(): + self.assertTrue(sf.get_locked()) + + self.assertEqual(len(ar), 10) + + del ar + if sf.mustlock(): + self.assertFalse(sf.get_locked()) + + def test_as_class(self): + # Check general new-style class freatures. + sf = pygame.Surface((2, 3), 0, 32) + ar = pygame.PixelArray(sf) + self.assertRaises(AttributeError, getattr, ar, "nonnative") + ar.nonnative = "value" + self.assertEqual(ar.nonnative, "value") + r = weakref.ref(ar) + self.assertTrue(r() is ar) + del ar + gc.collect() + self.assertTrue(r() is None) + + class C(pygame.PixelArray): + def __str__(self): + return "string (%i, %i)" % self.shape + + ar = C(sf) + self.assertEqual(str(ar), "string (2, 3)") + r = weakref.ref(ar) + self.assertTrue(r() is ar) + del ar + gc.collect() + self.assertTrue(r() is None) + + def test_pixelarray__subclassed_surface(self): + """Ensure the PixelArray constructor accepts subclassed surfaces.""" + surface = SurfaceSubclass((3, 5), 0, 32) + pixelarray = pygame.PixelArray(surface) + + self.assertIsInstance(pixelarray, pygame.PixelArray) + + # Sequence interfaces + def test_get_column(self): + for bpp in (8, 16, 24, 32): + sf = pygame.Surface((6, 8), 0, bpp) + sf.fill((0, 0, 255)) + val = sf.map_rgb((0, 0, 255)) + ar = pygame.PixelArray(sf) + + ar2 = ar.__getitem__(1) + self.assertEqual(len(ar2), 8) + self.assertEqual(ar2.__getitem__(0), val) + self.assertEqual(ar2.__getitem__(1), val) + self.assertEqual(ar2.__getitem__(2), val) + + ar2 = ar.__getitem__(-1) + self.assertEqual(len(ar2), 8) + self.assertEqual(ar2.__getitem__(0), val) + self.assertEqual(ar2.__getitem__(1), val) + self.assertEqual(ar2.__getitem__(2), val) + + @unittest.skipIf(IS_PYPY, "pypy malloc abort") + def test_get_pixel(self): + w = 10 + h = 20 + size = w, h + bg_color = (0, 0, 255) + fg_color_y = (0, 0, 128) + fg_color_x = (0, 0, 11) + for bpp in (8, 16, 24, 32): + sf = pygame.Surface(size, 0, bpp) + mapped_bg_color = sf.map_rgb(bg_color) + mapped_fg_color_y = sf.map_rgb(fg_color_y) + mapped_fg_color_x = sf.map_rgb(fg_color_x) + self.assertNotEqual( + mapped_fg_color_y, + mapped_bg_color, + "Unusable test colors for bpp %i" % (bpp,), + ) + self.assertNotEqual( + mapped_fg_color_x, + mapped_bg_color, + "Unusable test colors for bpp %i" % (bpp,), + ) + self.assertNotEqual( + mapped_fg_color_y, + mapped_fg_color_x, + "Unusable test colors for bpp %i" % (bpp,), + ) + sf.fill(bg_color) + + ar = pygame.PixelArray(sf) + + ar_y = ar.__getitem__(1) + for y in range(h): + ar2 = ar_y.__getitem__(y) + self.assertEqual( + ar2, + mapped_bg_color, + "ar[1][%i] == %i, mapped_bg_color == %i" + % (y, ar2, mapped_bg_color), + ) + + sf.set_at((1, y), fg_color_y) + ar2 = ar_y.__getitem__(y) + self.assertEqual( + ar2, + mapped_fg_color_y, + "ar[1][%i] == %i, mapped_fg_color_y == %i" + % (y, ar2, mapped_fg_color_y), + ) + + sf.set_at((1, 1), bg_color) + for x in range(w): + ar2 = ar.__getitem__(x).__getitem__(1) + self.assertEqual( + ar2, + mapped_bg_color, + "ar[%i][1] = %i, mapped_bg_color = %i" % (x, ar2, mapped_bg_color), + ) + sf.set_at((x, 1), fg_color_x) + ar2 = ar.__getitem__(x).__getitem__(1) + self.assertEqual( + ar2, + mapped_fg_color_x, + "ar[%i][1] = %i, mapped_fg_color_x = %i" + % (x, ar2, mapped_fg_color_x), + ) + + ar2 = ar.__getitem__(0).__getitem__(0) + self.assertEqual(ar2, mapped_bg_color, "bpp = %i" % (bpp,)) + + ar2 = ar.__getitem__(1).__getitem__(0) + self.assertEqual(ar2, mapped_fg_color_y, "bpp = %i" % (bpp,)) + + ar2 = ar.__getitem__(-4).__getitem__(1) + self.assertEqual(ar2, mapped_fg_color_x, "bpp = %i" % (bpp,)) + + ar2 = ar.__getitem__(-4).__getitem__(5) + self.assertEqual(ar2, mapped_bg_color, "bpp = %i" % (bpp,)) + + ar2 = ar.__getitem__(-4).__getitem__(0) + self.assertEqual(ar2, mapped_bg_color, "bpp = %i" % (bpp,)) + + ar2 = ar.__getitem__(-w + 1).__getitem__(0) + self.assertEqual(ar2, mapped_fg_color_y, "bpp = %i" % (bpp,)) + + ar2 = ar.__getitem__(-w).__getitem__(0) + self.assertEqual(ar2, mapped_bg_color, "bpp = %i" % (bpp,)) + + ar2 = ar.__getitem__(5).__getitem__(-4) + self.assertEqual(ar2, mapped_bg_color, "bpp = %i" % (bpp,)) + + ar2 = ar.__getitem__(5).__getitem__(-h + 1) + self.assertEqual(ar2, mapped_fg_color_x, "bpp = %i" % (bpp,)) + + ar2 = ar.__getitem__(5).__getitem__(-h) + self.assertEqual(ar2, mapped_bg_color, "bpp = %i" % (bpp,)) + + ar2 = ar.__getitem__(0).__getitem__(-h + 1) + self.assertEqual(ar2, mapped_fg_color_x, "bpp = %i" % (bpp,)) + + ar2 = ar.__getitem__(0).__getitem__(-h) + self.assertEqual(ar2, mapped_bg_color, "bpp = %i" % (bpp,)) + + def test_set_pixel(self): + for bpp in (8, 16, 24, 32): + sf = pygame.Surface((10, 20), 0, bpp) + sf.fill((0, 0, 0)) + ar = pygame.PixelArray(sf) + + ar.__getitem__(0).__setitem__(0, (0, 255, 0)) + self.assertEqual(ar[0][0], sf.map_rgb((0, 255, 0))) + + ar.__getitem__(1).__setitem__(1, (128, 128, 128)) + self.assertEqual(ar[1][1], sf.map_rgb((128, 128, 128))) + + ar.__getitem__(-1).__setitem__(-1, (128, 128, 128)) + self.assertEqual(ar[9][19], sf.map_rgb((128, 128, 128))) + + ar.__getitem__(-2).__setitem__(-2, (128, 128, 128)) + self.assertEqual(ar[8][-2], sf.map_rgb((128, 128, 128))) + + def test_set_column(self): + for bpp in (8, 16, 24, 32): + sf = pygame.Surface((6, 8), 0, bpp) + sf.fill((0, 0, 0)) + ar = pygame.PixelArray(sf) + + sf2 = pygame.Surface((6, 8), 0, bpp) + sf2.fill((0, 255, 255)) + ar2 = pygame.PixelArray(sf2) + + # Test single value assignment + ar.__setitem__(2, (128, 128, 128)) + self.assertEqual(ar[2][0], sf.map_rgb((128, 128, 128))) + self.assertEqual(ar[2][1], sf.map_rgb((128, 128, 128))) + + ar.__setitem__(-1, (0, 255, 255)) + self.assertEqual(ar[5][0], sf.map_rgb((0, 255, 255))) + self.assertEqual(ar[-1][1], sf.map_rgb((0, 255, 255))) + + ar.__setitem__(-2, (255, 255, 0)) + self.assertEqual(ar[4][0], sf.map_rgb((255, 255, 0))) + self.assertEqual(ar[-2][1], sf.map_rgb((255, 255, 0))) + + # Test list assignment. + ar.__setitem__(0, [(255, 255, 255)] * 8) + self.assertEqual(ar[0][0], sf.map_rgb((255, 255, 255))) + self.assertEqual(ar[0][1], sf.map_rgb((255, 255, 255))) + + # Test tuple assignment. + # Changed in Pygame 1.9.2 - Raises an exception. + self.assertRaises( + ValueError, + ar.__setitem__, + 1, + ( + (204, 0, 204), + (17, 17, 17), + (204, 0, 204), + (17, 17, 17), + (204, 0, 204), + (17, 17, 17), + (204, 0, 204), + (17, 17, 17), + ), + ) + + # Test pixel array assignment. + ar.__setitem__(1, ar2.__getitem__(3)) + self.assertEqual(ar[1][0], sf.map_rgb((0, 255, 255))) + self.assertEqual(ar[1][1], sf.map_rgb((0, 255, 255))) + + def test_get_slice(self): + for bpp in (8, 16, 24, 32): + sf = pygame.Surface((10, 20), 0, bpp) + sf.fill((0, 0, 0)) + ar = pygame.PixelArray(sf) + + self.assertEqual(len(ar[0:2]), 2) + self.assertEqual(len(ar[3:7][3]), 20) + + self.assertEqual(ar[0:0], None) + self.assertEqual(ar[5:5], None) + self.assertEqual(ar[9:9], None) + + # Has to resolve to ar[7:8] + self.assertEqual(len(ar[-3:-2]), 1) # 2D + self.assertEqual(len(ar[-3:-2][0]), 20) # 1D + + # Try assignments. + + # 2D assignment. + ar[2:5] = (255, 255, 255) + + # 1D assignment + ar[3][3:7] = (10, 10, 10) + self.assertEqual(ar[3][5], sf.map_rgb((10, 10, 10))) + self.assertEqual(ar[3][6], sf.map_rgb((10, 10, 10))) + + @unittest.skipIf(IS_PYPY, "skipping for PyPy (segfaults on mac pypy3 6.0.0)") + def test_contains(self): + for bpp in (8, 16, 24, 32): + sf = pygame.Surface((10, 20), 0, bpp) + sf.fill((0, 0, 0)) + sf.set_at((8, 8), (255, 255, 255)) + + ar = pygame.PixelArray(sf) + self.assertTrue((0, 0, 0) in ar) + self.assertTrue((255, 255, 255) in ar) + self.assertFalse((255, 255, 0) in ar) + self.assertFalse(0x0000FF in ar) + + # Test sliced array + self.assertTrue((0, 0, 0) in ar[8]) + self.assertTrue((255, 255, 255) in ar[8]) + self.assertFalse((255, 255, 0) in ar[8]) + self.assertFalse(0x0000FF in ar[8]) + + def test_get_surface(self): + for bpp in (8, 16, 24, 32): + sf = pygame.Surface((10, 20), 0, bpp) + sf.fill((0, 0, 0)) + ar = pygame.PixelArray(sf) + self.assertTrue(ar.surface is sf) + + def test_get_surface__subclassed_surface(self): + """Ensure the surface attribute can handle subclassed surfaces.""" + expected_surface = SurfaceSubclass((5, 3), 0, 32) + pixelarray = pygame.PixelArray(expected_surface) + + surface = pixelarray.surface + + self.assertIs(surface, expected_surface) + self.assertIsInstance(surface, pygame.Surface) + self.assertIsInstance(surface, SurfaceSubclass) + + def test_set_slice(self): + for bpp in (8, 16, 24, 32): + sf = pygame.Surface((6, 8), 0, bpp) + sf.fill((0, 0, 0)) + ar = pygame.PixelArray(sf) + + # Test single value assignment + val = sf.map_rgb((128, 128, 128)) + ar[0:2] = val + self.assertEqual(ar[0][0], val) + self.assertEqual(ar[0][1], val) + self.assertEqual(ar[1][0], val) + self.assertEqual(ar[1][1], val) + + val = sf.map_rgb((0, 255, 255)) + ar[-3:-1] = val + self.assertEqual(ar[3][0], val) + self.assertEqual(ar[-2][1], val) + + val = sf.map_rgb((255, 255, 255)) + ar[-3:] = (255, 255, 255) + self.assertEqual(ar[4][0], val) + self.assertEqual(ar[-1][1], val) + + # Test array size mismatch. + # Changed in ver. 1.9.2 + # (was "Test list assignment, this is a vertical assignment.") + val = sf.map_rgb((0, 255, 0)) + self.assertRaises(ValueError, ar.__setitem__, slice(2, 4), [val] * 8) + + # And the horizontal assignment. + val = sf.map_rgb((255, 0, 0)) + val2 = sf.map_rgb((128, 0, 255)) + ar[0:2] = [val, val2] + self.assertEqual(ar[0][0], val) + self.assertEqual(ar[1][0], val2) + self.assertEqual(ar[0][1], val) + self.assertEqual(ar[1][1], val2) + self.assertEqual(ar[0][4], val) + self.assertEqual(ar[1][4], val2) + self.assertEqual(ar[0][5], val) + self.assertEqual(ar[1][5], val2) + + # Test pixelarray assignment. + ar[:] = (0, 0, 0) + sf2 = pygame.Surface((6, 8), 0, bpp) + sf2.fill((255, 0, 255)) + + val = sf.map_rgb((255, 0, 255)) + ar2 = pygame.PixelArray(sf2) + + ar[:] = ar2[:] + self.assertEqual(ar[0][0], val) + self.assertEqual(ar[5][7], val) + + # Ensure p1 ... pn are freed for array[...] = [p1, ..., pn] + # Bug fix: reference counting. + if hasattr(sys, "getrefcount"): + + class Int(int): + """Unique int instances""" + + pass + + sf = pygame.Surface((5, 2), 0, 32) + ar = pygame.PixelArray(sf) + pixel_list = [Int(i) for i in range(ar.shape[0])] + refcnts_before = [sys.getrefcount(i) for i in pixel_list] + ar[...] = pixel_list + refcnts_after = [sys.getrefcount(i) for i in pixel_list] + gc.collect() + self.assertEqual(refcnts_after, refcnts_before) + + def test_subscript(self): + # By default we do not need to work with any special __***__ + # methods as map subscripts are the first looked up by the + # object system. + for bpp in (8, 16, 24, 32): + sf = pygame.Surface((6, 8), 0, bpp) + sf.set_at((1, 3), (0, 255, 0)) + sf.set_at((0, 0), (0, 255, 0)) + sf.set_at((4, 4), (0, 255, 0)) + val = sf.map_rgb((0, 255, 0)) + + ar = pygame.PixelArray(sf) + + # Test single value requests. + self.assertEqual(ar[1, 3], val) + self.assertEqual(ar[0, 0], val) + self.assertEqual(ar[4, 4], val) + self.assertEqual(ar[1][3], val) + self.assertEqual(ar[0][0], val) + self.assertEqual(ar[4][4], val) + + # Test ellipse working. + self.assertEqual(len(ar[..., ...]), 6) + self.assertEqual(len(ar[1, ...]), 8) + self.assertEqual(len(ar[..., 3]), 6) + + # Test simple slicing + self.assertEqual(len(ar[:, :]), 6) + self.assertEqual( + len( + ar[ + :, + ] + ), + 6, + ) + self.assertEqual(len(ar[1, :]), 8) + self.assertEqual(len(ar[:, 2]), 6) + # Empty slices + self.assertEqual( + ar[ + 4:4, + ], + None, + ) + self.assertEqual(ar[4:4, ...], None) + self.assertEqual(ar[4:4, 2:2], None) + self.assertEqual(ar[4:4, 1:4], None) + self.assertEqual( + ar[ + 4:4:2, + ], + None, + ) + self.assertEqual( + ar[ + 4:4:-2, + ], + None, + ) + self.assertEqual(ar[4:4:1, ...], None) + self.assertEqual(ar[4:4:-1, ...], None) + self.assertEqual(ar[4:4:1, 2:2], None) + self.assertEqual(ar[4:4:-1, 1:4], None) + self.assertEqual(ar[..., 4:4], None) + self.assertEqual(ar[1:4, 4:4], None) + self.assertEqual(ar[..., 4:4:1], None) + self.assertEqual(ar[..., 4:4:-1], None) + self.assertEqual(ar[2:2, 4:4:1], None) + self.assertEqual(ar[1:4, 4:4:-1], None) + + # Test advanced slicing + ar[0] = 0 + ar[1] = 1 + ar[2] = 2 + ar[3] = 3 + ar[4] = 4 + ar[5] = 5 + + # We should receive something like [0,2,4] + self.assertEqual(ar[::2, 1][0], 0) + self.assertEqual(ar[::2, 1][1], 2) + self.assertEqual(ar[::2, 1][2], 4) + # We should receive something like [2,2,2] + self.assertEqual(ar[2, ::2][0], 2) + self.assertEqual(ar[2, ::2][1], 2) + self.assertEqual(ar[2, ::2][2], 2) + + # Should create a 3x3 array of [0,2,4] + ar2 = ar[::2, ::2] + self.assertEqual(len(ar2), 3) + self.assertEqual(ar2[0][0], 0) + self.assertEqual(ar2[0][1], 0) + self.assertEqual(ar2[0][2], 0) + self.assertEqual(ar2[2][0], 4) + self.assertEqual(ar2[2][1], 4) + self.assertEqual(ar2[2][2], 4) + self.assertEqual(ar2[1][0], 2) + self.assertEqual(ar2[2][0], 4) + self.assertEqual(ar2[1][1], 2) + + # Should create a reversed 3x8 array over X of [1,2,3] -> [3,2,1] + ar2 = ar[3:0:-1] + self.assertEqual(len(ar2), 3) + self.assertEqual(ar2[0][0], 3) + self.assertEqual(ar2[0][1], 3) + self.assertEqual(ar2[0][2], 3) + self.assertEqual(ar2[0][7], 3) + self.assertEqual(ar2[2][0], 1) + self.assertEqual(ar2[2][1], 1) + self.assertEqual(ar2[2][2], 1) + self.assertEqual(ar2[2][7], 1) + self.assertEqual(ar2[1][0], 2) + self.assertEqual(ar2[1][1], 2) + # Should completely reverse the array over X -> [5,4,3,2,1,0] + ar2 = ar[::-1] + self.assertEqual(len(ar2), 6) + self.assertEqual(ar2[0][0], 5) + self.assertEqual(ar2[0][1], 5) + self.assertEqual(ar2[0][3], 5) + self.assertEqual(ar2[0][-1], 5) + self.assertEqual(ar2[1][0], 4) + self.assertEqual(ar2[1][1], 4) + self.assertEqual(ar2[1][3], 4) + self.assertEqual(ar2[1][-1], 4) + self.assertEqual(ar2[-1][-1], 0) + self.assertEqual(ar2[-2][-2], 1) + self.assertEqual(ar2[-3][-1], 2) + + # Test advanced slicing + ar[:] = 0 + ar2 = ar[:, 1] + ar2[:] = [99] * len(ar2) + self.assertEqual(ar2[0], 99) + self.assertEqual(ar2[-1], 99) + self.assertEqual(ar2[-2], 99) + self.assertEqual(ar2[2], 99) + self.assertEqual(ar[0, 1], 99) + self.assertEqual(ar[1, 1], 99) + self.assertEqual(ar[2, 1], 99) + self.assertEqual(ar[-1, 1], 99) + self.assertEqual(ar[-2, 1], 99) + + # Cases where a 2d array should have a dimension of length 1. + ar2 = ar[1:2, :] + self.assertEqual(ar2.shape, (1, ar.shape[1])) + ar2 = ar[:, 1:2] + self.assertEqual(ar2.shape, (ar.shape[0], 1)) + sf2 = pygame.Surface((1, 5), 0, 32) + ar2 = pygame.PixelArray(sf2) + self.assertEqual(ar2.shape, sf2.get_size()) + sf2 = pygame.Surface((7, 1), 0, 32) + ar2 = pygame.PixelArray(sf2) + self.assertEqual(ar2.shape, sf2.get_size()) + + # Array has a single ellipsis subscript: the identity operator + ar2 = ar[...] + self.assertTrue(ar2 is ar) + + # Ensure x and y are freed for p = array[x, y] + # Bug fix: reference counting + if hasattr(sys, "getrefcount"): + + class Int(int): + """Unique int instances""" + + pass + + sf = pygame.Surface((2, 2), 0, 32) + ar = pygame.PixelArray(sf) + x, y = Int(0), Int(1) + rx_before, ry_before = sys.getrefcount(x), sys.getrefcount(y) + p = ar[x, y] + rx_after, ry_after = sys.getrefcount(x), sys.getrefcount(y) + self.assertEqual(rx_after, rx_before) + self.assertEqual(ry_after, ry_before) + + def test_ass_subscript(self): + for bpp in (8, 16, 24, 32): + sf = pygame.Surface((6, 8), 0, bpp) + sf.fill((255, 255, 255)) + ar = pygame.PixelArray(sf) + + # Test ellipse working + ar[..., ...] = (0, 0, 0) + self.assertEqual(ar[0, 0], 0) + self.assertEqual(ar[1, 0], 0) + self.assertEqual(ar[-1, -1], 0) + ar[ + ..., + ] = (0, 0, 255) + self.assertEqual(ar[0, 0], sf.map_rgb((0, 0, 255))) + self.assertEqual(ar[1, 0], sf.map_rgb((0, 0, 255))) + self.assertEqual(ar[-1, -1], sf.map_rgb((0, 0, 255))) + ar[:, ...] = (255, 0, 0) + self.assertEqual(ar[0, 0], sf.map_rgb((255, 0, 0))) + self.assertEqual(ar[1, 0], sf.map_rgb((255, 0, 0))) + self.assertEqual(ar[-1, -1], sf.map_rgb((255, 0, 0))) + ar[...] = (0, 255, 0) + self.assertEqual(ar[0, 0], sf.map_rgb((0, 255, 0))) + self.assertEqual(ar[1, 0], sf.map_rgb((0, 255, 0))) + self.assertEqual(ar[-1, -1], sf.map_rgb((0, 255, 0))) + + # Ensure x and y are freed for array[x, y] = p + # Bug fix: reference counting + if hasattr(sys, "getrefcount"): + + class Int(int): + """Unique int instances""" + + pass + + sf = pygame.Surface((2, 2), 0, 32) + ar = pygame.PixelArray(sf) + x, y = Int(0), Int(1) + rx_before, ry_before = sys.getrefcount(x), sys.getrefcount(y) + ar[x, y] = 0 + rx_after, ry_after = sys.getrefcount(x), sys.getrefcount(y) + self.assertEqual(rx_after, rx_before) + self.assertEqual(ry_after, ry_before) + + def test_pixels_field(self): + for bpp in [1, 2, 3, 4]: + sf = pygame.Surface((11, 7), 0, bpp * 8) + ar = pygame.PixelArray(sf) + ar2 = ar[1:, :] + self.assertEqual(ar2._pixels_address - ar._pixels_address, ar.itemsize) + ar2 = ar[:, 1:] + self.assertEqual(ar2._pixels_address - ar._pixels_address, ar.strides[1]) + ar2 = ar[::-1, :] + self.assertEqual( + ar2._pixels_address - ar._pixels_address, + (ar.shape[0] - 1) * ar.itemsize, + ) + ar2 = ar[::-2, :] + self.assertEqual( + ar2._pixels_address - ar._pixels_address, + (ar.shape[0] - 1) * ar.itemsize, + ) + ar2 = ar[:, ::-1] + self.assertEqual( + ar2._pixels_address - ar._pixels_address, + (ar.shape[1] - 1) * ar.strides[1], + ) + ar3 = ar2[::-1, :] + self.assertEqual( + ar3._pixels_address - ar._pixels_address, + (ar.shape[0] - 1) * ar.strides[0] + (ar.shape[1] - 1) * ar.strides[1], + ) + ar2 = ar[:, ::-2] + self.assertEqual( + ar2._pixels_address - ar._pixels_address, + (ar.shape[1] - 1) * ar.strides[1], + ) + ar2 = ar[2::, 3::] + self.assertEqual( + ar2._pixels_address - ar._pixels_address, + ar.strides[0] * 2 + ar.strides[1] * 3, + ) + ar2 = ar[2::2, 3::4] + self.assertEqual( + ar2._pixels_address - ar._pixels_address, + ar.strides[0] * 2 + ar.strides[1] * 3, + ) + ar2 = ar[9:2:-1, :] + self.assertEqual( + ar2._pixels_address - ar._pixels_address, ar.strides[0] * 9 + ) + ar2 = ar[:, 5:2:-1] + self.assertEqual( + ar2._pixels_address - ar._pixels_address, ar.strides[1] * 5 + ) + ##? ar2 = ar[:,9:2:-1] + + def test_make_surface(self): + bg_color = pygame.Color(255, 255, 255) + fg_color = pygame.Color(128, 100, 0) + for bpp in (8, 16, 24, 32): + sf = pygame.Surface((10, 20), 0, bpp) + bg_color_adj = sf.unmap_rgb(sf.map_rgb(bg_color)) + fg_color_adj = sf.unmap_rgb(sf.map_rgb(fg_color)) + sf.fill(bg_color_adj) + sf.fill(fg_color_adj, (2, 5, 4, 11)) + ar = pygame.PixelArray(sf) + newsf = ar[::2, ::2].make_surface() + rect = newsf.get_rect() + self.assertEqual(rect.width, 5) + self.assertEqual(rect.height, 10) + for p in [ + (0, 2), + (0, 3), + (1, 2), + (2, 2), + (3, 2), + (3, 3), + (0, 7), + (0, 8), + (1, 8), + (2, 8), + (3, 8), + (3, 7), + ]: + self.assertEqual(newsf.get_at(p), bg_color_adj) + for p in [(1, 3), (2, 3), (1, 5), (2, 5), (1, 7), (2, 7)]: + self.assertEqual(newsf.get_at(p), fg_color_adj) + + # Bug when array width is not a multiple of the slice step. + w = 17 + lst = list(range(w)) + w_slice = len(lst[::2]) + h = 3 + sf = pygame.Surface((w, h), 0, 32) + ar = pygame.PixelArray(sf) + ar2 = ar[::2, :] + sf2 = ar2.make_surface() + w2, h2 = sf2.get_size() + self.assertEqual(w2, w_slice) + self.assertEqual(h2, h) + + # Bug when array height is not a multiple of the slice step. + # This can hang the Python interpreter. + h = 17 + lst = list(range(h)) + h_slice = len(lst[::2]) + w = 3 + sf = pygame.Surface((w, h), 0, 32) + ar = pygame.PixelArray(sf) + ar2 = ar[:, ::2] + sf2 = ar2.make_surface() # Hangs here. + w2, h2 = sf2.get_size() + self.assertEqual(w2, w) + self.assertEqual(h2, h_slice) + + def test_make_surface__subclassed_surface(self): + """Ensure make_surface can handle subclassed surfaces.""" + expected_size = (3, 5) + expected_flags = 0 + expected_depth = 32 + original_surface = SurfaceSubclass( + expected_size, expected_flags, expected_depth + ) + pixelarray = pygame.PixelArray(original_surface) + + surface = pixelarray.make_surface() + + self.assertIsNot(surface, original_surface) + self.assertIsInstance(surface, pygame.Surface) + self.assertNotIsInstance(surface, SurfaceSubclass) + self.assertEqual(surface.get_size(), expected_size) + self.assertEqual(surface.get_flags(), expected_flags) + self.assertEqual(surface.get_bitsize(), expected_depth) + + def test_iter(self): + for bpp in (8, 16, 24, 32): + sf = pygame.Surface((5, 10), 0, bpp) + ar = pygame.PixelArray(sf) + iterations = 0 + for col in ar: + self.assertEqual(len(col), 10) + iterations += 1 + self.assertEqual(iterations, 5) + + def test_replace(self): + # print "replace start" + for bpp in (8, 16, 24, 32): + sf = pygame.Surface((10, 10), 0, bpp) + sf.fill((255, 0, 0)) + rval = sf.map_rgb((0, 0, 255)) + oval = sf.map_rgb((255, 0, 0)) + ar = pygame.PixelArray(sf) + ar[::2].replace((255, 0, 0), (0, 0, 255)) + self.assertEqual(ar[0][0], rval) + self.assertEqual(ar[1][0], oval) + self.assertEqual(ar[2][3], rval) + self.assertEqual(ar[3][6], oval) + self.assertEqual(ar[8][9], rval) + self.assertEqual(ar[9][9], oval) + + ar[::2].replace((0, 0, 255), (255, 0, 0), weights=(10, 20, 50)) + self.assertEqual(ar[0][0], oval) + self.assertEqual(ar[2][3], oval) + self.assertEqual(ar[3][6], oval) + self.assertEqual(ar[8][9], oval) + self.assertEqual(ar[9][9], oval) + # print "replace end" + + def test_extract(self): + # print "extract start" + for bpp in (8, 16, 24, 32): + sf = pygame.Surface((10, 10), 0, bpp) + sf.fill((0, 0, 255)) + sf.fill((255, 0, 0), (2, 2, 6, 6)) + + white = sf.map_rgb((255, 255, 255)) + black = sf.map_rgb((0, 0, 0)) + + ar = pygame.PixelArray(sf) + newar = ar.extract((255, 0, 0)) + + self.assertEqual(newar[0][0], black) + self.assertEqual(newar[1][0], black) + self.assertEqual(newar[2][3], white) + self.assertEqual(newar[3][6], white) + self.assertEqual(newar[8][9], black) + self.assertEqual(newar[9][9], black) + + newar = ar.extract((255, 0, 0), weights=(10, 0.1, 50)) + self.assertEqual(newar[0][0], black) + self.assertEqual(newar[1][0], black) + self.assertEqual(newar[2][3], white) + self.assertEqual(newar[3][6], white) + self.assertEqual(newar[8][9], black) + self.assertEqual(newar[9][9], black) + # print "extract end" + + def test_2dslice_assignment(self): + w = 2 * 5 * 8 + h = 3 * 5 * 9 + sf = pygame.Surface((w, h), 0, 32) + ar = pygame.PixelArray(sf) + size = (w, h) + strides = (1, w) + offset = 0 + self._test_assignment(sf, ar, size, strides, offset) + xslice = slice(None, None, 2) + yslice = slice(None, None, 3) + ar, size, strides, offset = self._array_slice( + ar, size, (xslice, yslice), strides, offset + ) + self._test_assignment(sf, ar, size, strides, offset) + xslice = slice(5, None, 5) + yslice = slice(5, None, 5) + ar, size, strides, offset = self._array_slice( + ar, size, (xslice, yslice), strides, offset + ) + self._test_assignment(sf, ar, size, strides, offset) + + def _test_assignment(self, sf, ar, ar_size, ar_strides, ar_offset): + self.assertEqual(ar.shape, ar_size) + ar_w, ar_h = ar_size + ar_xstride, ar_ystride = ar_strides + sf_w, sf_h = sf.get_size() + black = pygame.Color("black") + color = pygame.Color(0, 0, 12) + pxcolor = sf.map_rgb(color) + sf.fill(black) + for ar_x, ar_y in [ + (0, 0), + (0, ar_h - 4), + (ar_w - 3, 0), + (0, ar_h - 1), + (ar_w - 1, 0), + (ar_w - 1, ar_h - 1), + ]: + sf_offset = ar_offset + ar_x * ar_xstride + ar_y * ar_ystride + sf_y = sf_offset // sf_w + sf_x = sf_offset - sf_y * sf_w + sf_posn = (sf_x, sf_y) + sf_pix = sf.get_at(sf_posn) + self.assertEqual( + sf_pix, + black, + "at pixarr posn (%i, %i) (surf posn (%i, %i)): " + "%s != %s" % (ar_x, ar_y, sf_x, sf_y, sf_pix, black), + ) + ar[ar_x, ar_y] = pxcolor + sf_pix = sf.get_at(sf_posn) + self.assertEqual( + sf_pix, + color, + "at pixarr posn (%i, %i) (surf posn (%i, %i)): " + "%s != %s" % (ar_x, ar_y, sf_x, sf_y, sf_pix, color), + ) + + def _array_slice(self, ar, size, slices, strides, offset): + ar = ar[slices] + xslice, yslice = slices + w, h = size + xstart, xstop, xstep = xslice.indices(w) + ystart, ystop, ystep = yslice.indices(h) + w = (xstop - xstart + xstep - 1) // xstep + h = (ystop - ystart + ystep - 1) // ystep + xstride, ystride = strides + offset += xstart * xstride + ystart * ystride + xstride *= xstep + ystride *= ystep + return ar, (w, h), (xstride, ystride), offset + + def test_array_properties(self): + # itemsize, ndim, shape, and strides. + for bpp in [1, 2, 3, 4]: + sf = pygame.Surface((2, 2), 0, bpp * 8) + ar = pygame.PixelArray(sf) + self.assertEqual(ar.itemsize, bpp) + + for shape in [(4, 16), (5, 13)]: + w, h = shape + sf = pygame.Surface(shape, 0, 32) + bpp = sf.get_bytesize() + pitch = sf.get_pitch() + ar = pygame.PixelArray(sf) + self.assertEqual(ar.ndim, 2) + self.assertEqual(ar.shape, shape) + self.assertEqual(ar.strides, (bpp, pitch)) + ar2 = ar[::2, :] + w2 = len(([0] * w)[::2]) + self.assertEqual(ar2.ndim, 2) + self.assertEqual(ar2.shape, (w2, h)) + self.assertEqual(ar2.strides, (2 * bpp, pitch)) + ar2 = ar[:, ::2] + h2 = len(([0] * h)[::2]) + self.assertEqual(ar2.ndim, 2) + self.assertEqual(ar2.shape, (w, h2)) + self.assertEqual(ar2.strides, (bpp, 2 * pitch)) + ar2 = ar[1] + self.assertEqual(ar2.ndim, 1) + self.assertEqual(ar2.shape, (h,)) + self.assertEqual(ar2.strides, (pitch,)) + ar2 = ar[:, 1] + self.assertEqual(ar2.ndim, 1) + self.assertEqual(ar2.shape, (w,)) + self.assertEqual(ar2.strides, (bpp,)) + + def test_self_assign(self): + # This differs from NumPy arrays. + w = 10 + max_x = w - 1 + h = 20 + max_y = h - 1 + for bpp in [1, 2, 3, 4]: + sf = pygame.Surface((w, h), 0, bpp * 8) + ar = pygame.PixelArray(sf) + for i in range(w * h): + ar[i % w, i // w] = i + ar[:, :] = ar[::-1, :] + for i in range(w * h): + self.assertEqual(ar[max_x - i % w, i // w], i) + ar = pygame.PixelArray(sf) + for i in range(w * h): + ar[i % w, i // w] = i + ar[:, :] = ar[:, ::-1] + for i in range(w * h): + self.assertEqual(ar[i % w, max_y - i // w], i) + ar = pygame.PixelArray(sf) + for i in range(w * h): + ar[i % w, i // w] = i + ar[:, :] = ar[::-1, ::-1] + for i in range(w * h): + self.assertEqual(ar[max_x - i % w, max_y - i // w], i) + + def test_color_value(self): + # Confirm that a PixelArray slice assignment distinguishes between + # pygame.Color and tuple objects as single (r, g, b[, a]) colors + # and other sequences as sequences of colors to be treated as + # slices. + sf = pygame.Surface((5, 5), 0, 32) + ar = pygame.PixelArray(sf) + index = slice(None, None, 1) + ar.__setitem__(index, (1, 2, 3)) + self.assertEqual(ar[0, 0], sf.map_rgb((1, 2, 3))) + ar.__setitem__(index, pygame.Color(10, 11, 12)) + self.assertEqual(ar[0, 0], sf.map_rgb((10, 11, 12))) + self.assertRaises(ValueError, ar.__setitem__, index, (1, 2, 3, 4, 5)) + self.assertRaises(ValueError, ar.__setitem__, (index, index), (1, 2, 3, 4, 5)) + self.assertRaises(ValueError, ar.__setitem__, index, [1, 2, 3]) + self.assertRaises(ValueError, ar.__setitem__, (index, index), [1, 2, 3]) + sf = pygame.Surface((3, 3), 0, 32) + ar = pygame.PixelArray(sf) + ar[:] = (20, 30, 40) + self.assertEqual(ar[0, 0], sf.map_rgb((20, 30, 40))) + ar[:] = [20, 30, 40] + self.assertEqual(ar[0, 0], 20) + self.assertEqual(ar[1, 0], 30) + self.assertEqual(ar[2, 0], 40) + + def test_transpose(self): + # PixelArray.transpose(): swap axis on a 2D array, add a length + # 1 x axis to a 1D array. + sf = pygame.Surface((3, 7), 0, 32) + ar = pygame.PixelArray(sf) + w, h = ar.shape + dx, dy = ar.strides + for i in range(w * h): + x = i % w + y = i // w + ar[x, y] = i + ar_t = ar.transpose() + self.assertEqual(ar_t.shape, (h, w)) + self.assertEqual(ar_t.strides, (dy, dx)) + for i in range(w * h): + x = i % w + y = i // w + self.assertEqual(ar_t[y, x], ar[x, y]) + ar1D = ar[0] + ar2D = ar1D.transpose() + self.assertEqual(ar2D.shape, (1, h)) + for y in range(h): + self.assertEqual(ar1D[y], ar2D[0, y]) + ar1D = ar[:, 0] + ar2D = ar1D.transpose() + self.assertEqual(ar2D.shape, (1, w)) + for x in range(2): + self.assertEqual(ar1D[x], ar2D[0, x]) + + def test_length_1_dimension_broadcast(self): + w = 5 + sf = pygame.Surface((w, w), 0, 32) + ar = pygame.PixelArray(sf) + # y-axis broadcast. + sf_x = pygame.Surface((w, 1), 0, 32) + ar_x = pygame.PixelArray(sf_x) + for i in range(w): + ar_x[i, 0] = (w + 1) * 10 + ar[...] = ar_x + for y in range(w): + for x in range(w): + self.assertEqual(ar[x, y], ar_x[x, 0]) + # x-axis broadcast. + ar[...] = 0 + sf_y = pygame.Surface((1, w), 0, 32) + ar_y = pygame.PixelArray(sf_y) + for i in range(w): + ar_y[0, i] = (w + 1) * 10 + ar[...] = ar_y + for x in range(w): + for y in range(w): + self.assertEqual(ar[x, y], ar_y[0, y]) + # (1, 1) array broadcast. + ar[...] = 0 + sf_1px = pygame.Surface((1, 1), 0, 32) + ar_1px = pygame.PixelArray(sf_1px) + ar_1px[0, 0] = 42 # Well it had to show up somewhere. + ar[...] = ar_1px + for y in range(w): + for x in range(w): + self.assertEqual(ar[x, y], 42) + + def test_assign_size_mismatch(self): + sf = pygame.Surface((7, 11), 0, 32) + ar = pygame.PixelArray(sf) + self.assertRaises(ValueError, ar.__setitem__, Ellipsis, ar[:, 0:2]) + self.assertRaises(ValueError, ar.__setitem__, Ellipsis, ar[0:2, :]) + + def test_repr(self): + # Python 3.x bug: the tp_repr slot function returned NULL instead + # of a Unicode string, triggering an exception. + sf = pygame.Surface((3, 1), pygame.SRCALPHA, 16) + ar = pygame.PixelArray(sf) + ar[...] = 42 + pixel = sf.get_at_mapped((0, 0)) + self.assertEqual(repr(ar), type(ar).__name__ + "([\n [42, 42, 42]]\n)") + + +@unittest.skipIf(IS_PYPY, "pypy having issues") +class PixelArrayArrayInterfaceTest(unittest.TestCase, TestMixin): + @unittest.skipIf(IS_PYPY, "skipping for PyPy (why?)") + def test_basic(self): + # Check unchanging fields. + sf = pygame.Surface((2, 2), 0, 32) + ar = pygame.PixelArray(sf) + + ai = arrinter.ArrayInterface(ar) + self.assertEqual(ai.two, 2) + self.assertEqual(ai.typekind, "u") + self.assertEqual(ai.nd, 2) + self.assertEqual(ai.data, ar._pixels_address) + + @unittest.skipIf(IS_PYPY, "skipping for PyPy (why?)") + def test_shape(self): + + for shape in [[4, 16], [5, 13]]: + w, h = shape + sf = pygame.Surface(shape, 0, 32) + ar = pygame.PixelArray(sf) + ai = arrinter.ArrayInterface(ar) + ai_shape = [ai.shape[i] for i in range(ai.nd)] + self.assertEqual(ai_shape, shape) + ar2 = ar[::2, :] + ai2 = arrinter.ArrayInterface(ar2) + w2 = len(([0] * w)[::2]) + ai_shape = [ai2.shape[i] for i in range(ai2.nd)] + self.assertEqual(ai_shape, [w2, h]) + ar2 = ar[:, ::2] + ai2 = arrinter.ArrayInterface(ar2) + h2 = len(([0] * h)[::2]) + ai_shape = [ai2.shape[i] for i in range(ai2.nd)] + self.assertEqual(ai_shape, [w, h2]) + + @unittest.skipIf(IS_PYPY, "skipping for PyPy (why?)") + def test_itemsize(self): + for bytes_per_pixel in range(1, 5): + bits_per_pixel = 8 * bytes_per_pixel + sf = pygame.Surface((2, 2), 0, bits_per_pixel) + ar = pygame.PixelArray(sf) + ai = arrinter.ArrayInterface(ar) + self.assertEqual(ai.itemsize, bytes_per_pixel) + + @unittest.skipIf(IS_PYPY, "skipping for PyPy (why?)") + def test_flags(self): + aim = arrinter + common_flags = aim.PAI_NOTSWAPPED | aim.PAI_WRITEABLE | aim.PAI_ALIGNED + s = pygame.Surface((10, 2), 0, 32) + ar = pygame.PixelArray(s) + ai = aim.ArrayInterface(ar) + self.assertEqual(ai.flags, common_flags | aim.PAI_FORTRAN) + + ar2 = ar[::2, :] + ai = aim.ArrayInterface(ar2) + self.assertEqual(ai.flags, common_flags) + + s = pygame.Surface((8, 2), 0, 24) + ar = pygame.PixelArray(s) + ai = aim.ArrayInterface(ar) + self.assertEqual(ai.flags, common_flags | aim.PAI_FORTRAN) + + s = pygame.Surface((7, 2), 0, 24) + ar = pygame.PixelArray(s) + ai = aim.ArrayInterface(ar) + self.assertEqual(ai.flags, common_flags) + + def test_slicing(self): + # This will implicitly test data and strides fields. + # + # Need an 8 bit test surfaces because pixelcopy.make_surface + # returns an 8 bit surface for a 2d array. + + factors = [7, 3, 11] + + w = reduce(operator.mul, factors, 1) + h = 13 + sf = pygame.Surface((w, h), 0, 8) + color = sf.map_rgb((1, 17, 128)) + ar = pygame.PixelArray(sf) + for f in factors[:-1]: + w = w // f + sf.fill((0, 0, 0)) + ar = ar[f : f + w, :] + ar[0][0] = color + ar[-1][-2] = color + ar[0][-3] = color + sf2 = ar.make_surface() + sf3 = pygame.pixelcopy.make_surface(ar) + self.assert_surfaces_equal(sf3, sf2) + + h = reduce(operator.mul, factors, 1) + w = 13 + sf = pygame.Surface((w, h), 0, 8) + color = sf.map_rgb((1, 17, 128)) + ar = pygame.PixelArray(sf) + for f in factors[:-1]: + h = h // f + sf.fill((0, 0, 0)) + ar = ar[:, f : f + h] + ar[0][0] = color + ar[-1][-2] = color + ar[0][-3] = color + sf2 = ar.make_surface() + sf3 = pygame.pixelcopy.make_surface(ar) + self.assert_surfaces_equal(sf3, sf2) + + w = 20 + h = 10 + sf = pygame.Surface((w, h), 0, 8) + color = sf.map_rgb((1, 17, 128)) + ar = pygame.PixelArray(sf) + for slices in [ + (slice(w), slice(h)), + (slice(0, w, 2), slice(h)), + (slice(0, w, 3), slice(h)), + (slice(w), slice(0, h, 2)), + (slice(w), slice(0, h, 3)), + (slice(0, w, 2), slice(0, h, 2)), + (slice(0, w, 3), slice(0, h, 3)), + ]: + sf.fill((0, 0, 0)) + ar2 = ar[slices] + ar2[0][0] = color + ar2[-1][-2] = color + ar2[0][-3] = color + sf2 = ar2.make_surface() + sf3 = pygame.pixelcopy.make_surface(ar2) + self.assert_surfaces_equal(sf3, sf2) + + +@unittest.skipIf(not pygame.HAVE_NEWBUF, "newbuf not implemented") +@unittest.skipIf(IS_PYPY, "pypy having issues") +class PixelArrayNewBufferTest(unittest.TestCase, TestMixin): + + if pygame.HAVE_NEWBUF: + from pygame.tests.test_utils import buftools + + bitsize_to_format = {8: "B", 16: "=H", 24: "3x", 32: "=I"} + + def test_newbuf_2D(self): + buftools = self.buftools + Importer = buftools.Importer + + for bit_size in [8, 16, 24, 32]: + s = pygame.Surface((10, 2), 0, bit_size) + ar = pygame.PixelArray(s) + format = self.bitsize_to_format[bit_size] + itemsize = ar.itemsize + shape = ar.shape + w, h = shape + strides = ar.strides + length = w * h * itemsize + imp = Importer(ar, buftools.PyBUF_FULL) + self.assertTrue(imp.obj, ar) + self.assertEqual(imp.len, length) + self.assertEqual(imp.ndim, 2) + self.assertEqual(imp.itemsize, itemsize) + self.assertEqual(imp.format, format) + self.assertFalse(imp.readonly) + self.assertEqual(imp.shape, shape) + self.assertEqual(imp.strides, strides) + self.assertTrue(imp.suboffsets is None) + self.assertEqual(imp.buf, s._pixels_address) + + s = pygame.Surface((8, 16), 0, 32) + ar = pygame.PixelArray(s) + format = self.bitsize_to_format[s.get_bitsize()] + itemsize = ar.itemsize + shape = ar.shape + w, h = shape + strides = ar.strides + length = w * h * itemsize + imp = Importer(ar, buftools.PyBUF_SIMPLE) + self.assertTrue(imp.obj, ar) + self.assertEqual(imp.len, length) + self.assertEqual(imp.ndim, 0) + self.assertEqual(imp.itemsize, itemsize) + self.assertTrue(imp.format is None) + self.assertFalse(imp.readonly) + self.assertTrue(imp.shape is None) + self.assertTrue(imp.strides is None) + self.assertTrue(imp.suboffsets is None) + self.assertEqual(imp.buf, s._pixels_address) + imp = Importer(ar, buftools.PyBUF_FORMAT) + self.assertEqual(imp.ndim, 0) + self.assertEqual(imp.format, format) + imp = Importer(ar, buftools.PyBUF_WRITABLE) + self.assertEqual(imp.ndim, 0) + self.assertTrue(imp.format is None) + imp = Importer(ar, buftools.PyBUF_F_CONTIGUOUS) + self.assertEqual(imp.ndim, 2) + self.assertTrue(imp.format is None) + self.assertEqual(imp.shape, shape) + self.assertEqual(imp.strides, strides) + imp = Importer(ar, buftools.PyBUF_ANY_CONTIGUOUS) + self.assertEqual(imp.ndim, 2) + self.assertTrue(imp.format is None) + self.assertEqual(imp.shape, shape) + self.assertEqual(imp.strides, strides) + self.assertRaises(BufferError, Importer, ar, buftools.PyBUF_C_CONTIGUOUS) + self.assertRaises(BufferError, Importer, ar, buftools.PyBUF_ND) + + ar_sliced = ar[:, ::2] + format = self.bitsize_to_format[s.get_bitsize()] + itemsize = ar_sliced.itemsize + shape = ar_sliced.shape + w, h = shape + strides = ar_sliced.strides + length = w * h * itemsize + imp = Importer(ar_sliced, buftools.PyBUF_STRIDED) + self.assertEqual(imp.len, length) + self.assertEqual(imp.ndim, 2) + self.assertEqual(imp.itemsize, itemsize) + self.assertTrue(imp.format is None) + self.assertFalse(imp.readonly) + self.assertEqual(imp.shape, shape) + self.assertEqual(imp.strides, strides) + self.assertEqual(imp.buf, s._pixels_address) + self.assertRaises(BufferError, Importer, ar_sliced, buftools.PyBUF_SIMPLE) + self.assertRaises(BufferError, Importer, ar_sliced, buftools.PyBUF_ND) + self.assertRaises(BufferError, Importer, ar_sliced, buftools.PyBUF_C_CONTIGUOUS) + self.assertRaises(BufferError, Importer, ar_sliced, buftools.PyBUF_F_CONTIGUOUS) + self.assertRaises( + BufferError, Importer, ar_sliced, buftools.PyBUF_ANY_CONTIGUOUS + ) + + ar_sliced = ar[::2, :] + format = self.bitsize_to_format[s.get_bitsize()] + itemsize = ar_sliced.itemsize + shape = ar_sliced.shape + w, h = shape + strides = ar_sliced.strides + length = w * h * itemsize + imp = Importer(ar_sliced, buftools.PyBUF_STRIDED) + self.assertEqual(imp.len, length) + self.assertEqual(imp.ndim, 2) + self.assertEqual(imp.itemsize, itemsize) + self.assertTrue(imp.format is None) + self.assertFalse(imp.readonly) + self.assertEqual(imp.shape, shape) + self.assertEqual(imp.strides, strides) + self.assertEqual(imp.buf, s._pixels_address) + self.assertRaises(BufferError, Importer, ar_sliced, buftools.PyBUF_SIMPLE) + self.assertRaises(BufferError, Importer, ar_sliced, buftools.PyBUF_ND) + self.assertRaises(BufferError, Importer, ar_sliced, buftools.PyBUF_C_CONTIGUOUS) + self.assertRaises(BufferError, Importer, ar_sliced, buftools.PyBUF_F_CONTIGUOUS) + self.assertRaises( + BufferError, Importer, ar_sliced, buftools.PyBUF_ANY_CONTIGUOUS + ) + + s2 = s.subsurface((2, 3, 5, 7)) + ar = pygame.PixelArray(s2) + format = self.bitsize_to_format[s.get_bitsize()] + itemsize = ar.itemsize + shape = ar.shape + w, h = shape + strides = ar.strides + length = w * h * itemsize + imp = Importer(ar, buftools.PyBUF_STRIDES) + self.assertTrue(imp.obj, ar) + self.assertEqual(imp.len, length) + self.assertEqual(imp.ndim, 2) + self.assertEqual(imp.itemsize, itemsize) + self.assertTrue(imp.format is None) + self.assertFalse(imp.readonly) + self.assertEqual(imp.shape, shape) + self.assertEqual(imp.strides, strides) + self.assertTrue(imp.suboffsets is None) + self.assertEqual(imp.buf, s2._pixels_address) + self.assertRaises(BufferError, Importer, ar, buftools.PyBUF_SIMPLE) + self.assertRaises(BufferError, Importer, ar, buftools.PyBUF_FORMAT) + self.assertRaises(BufferError, Importer, ar, buftools.PyBUF_WRITABLE) + self.assertRaises(BufferError, Importer, ar, buftools.PyBUF_ND) + self.assertRaises(BufferError, Importer, ar, buftools.PyBUF_C_CONTIGUOUS) + self.assertRaises(BufferError, Importer, ar, buftools.PyBUF_F_CONTIGUOUS) + self.assertRaises(BufferError, Importer, ar, buftools.PyBUF_ANY_CONTIGUOUS) + + def test_newbuf_1D(self): + buftools = self.buftools + Importer = buftools.Importer + + s = pygame.Surface((2, 16), 0, 32) + ar_2D = pygame.PixelArray(s) + x = 0 + ar = ar_2D[x] + format = self.bitsize_to_format[s.get_bitsize()] + itemsize = ar.itemsize + shape = ar.shape + h = shape[0] + strides = ar.strides + length = h * itemsize + buf = s._pixels_address + x * itemsize + imp = Importer(ar, buftools.PyBUF_STRIDES) + self.assertTrue(imp.obj, ar) + self.assertEqual(imp.len, length) + self.assertEqual(imp.ndim, 1) + self.assertEqual(imp.itemsize, itemsize) + self.assertTrue(imp.format is None) + self.assertFalse(imp.readonly) + self.assertEqual(imp.shape, shape) + self.assertEqual(imp.strides, strides) + self.assertTrue(imp.suboffsets is None) + self.assertEqual(imp.buf, buf) + imp = Importer(ar, buftools.PyBUF_FULL) + self.assertEqual(imp.ndim, 1) + self.assertEqual(imp.format, format) + self.assertRaises(BufferError, Importer, ar, buftools.PyBUF_SIMPLE) + self.assertRaises(BufferError, Importer, ar, buftools.PyBUF_FORMAT) + self.assertRaises(BufferError, Importer, ar, buftools.PyBUF_WRITABLE) + self.assertRaises(BufferError, Importer, ar, buftools.PyBUF_ND) + self.assertRaises(BufferError, Importer, ar, buftools.PyBUF_C_CONTIGUOUS) + self.assertRaises(BufferError, Importer, ar, buftools.PyBUF_F_CONTIGUOUS) + self.assertRaises(BufferError, Importer, ar, buftools.PyBUF_ANY_CONTIGUOUS) + y = 10 + ar = ar_2D[:, y] + shape = ar.shape + w = shape[0] + strides = ar.strides + length = w * itemsize + buf = s._pixels_address + y * s.get_pitch() + imp = Importer(ar, buftools.PyBUF_FULL) + self.assertEqual(imp.len, length) + self.assertEqual(imp.ndim, 1) + self.assertEqual(imp.itemsize, itemsize) + self.assertEqual(imp.format, format) + self.assertFalse(imp.readonly) + self.assertEqual(imp.shape, shape) + self.assertEqual(imp.strides, strides) + self.assertEqual(imp.buf, buf) + self.assertTrue(imp.suboffsets is None) + imp = Importer(ar, buftools.PyBUF_SIMPLE) + self.assertEqual(imp.len, length) + self.assertEqual(imp.ndim, 0) + self.assertEqual(imp.itemsize, itemsize) + self.assertTrue(imp.format is None) + self.assertFalse(imp.readonly) + self.assertTrue(imp.shape is None) + self.assertTrue(imp.strides is None) + imp = Importer(ar, buftools.PyBUF_ND) + self.assertEqual(imp.len, length) + self.assertEqual(imp.ndim, 1) + self.assertEqual(imp.itemsize, itemsize) + self.assertTrue(imp.format is None) + self.assertFalse(imp.readonly) + self.assertEqual(imp.shape, shape) + self.assertTrue(imp.strides is None) + imp = Importer(ar, buftools.PyBUF_C_CONTIGUOUS) + self.assertEqual(imp.ndim, 1) + imp = Importer(ar, buftools.PyBUF_F_CONTIGUOUS) + self.assertEqual(imp.ndim, 1) + imp = Importer(ar, buftools.PyBUF_ANY_CONTIGUOUS) + self.assertEqual(imp.ndim, 1) + + +if __name__ == "__main__": + unittest.main() diff --git a/venv/Lib/site-packages/pygame/tests/pixelcopy_test.py b/venv/Lib/site-packages/pygame/tests/pixelcopy_test.py new file mode 100644 index 0000000..f89c665 --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/pixelcopy_test.py @@ -0,0 +1,712 @@ +import platform +import unittest + +try: + from pygame.tests.test_utils import arrinter +except NameError: + pass +import pygame +from pygame.locals import * +from pygame.pixelcopy import surface_to_array, map_array, array_to_surface, make_surface + +IS_PYPY = "PyPy" == platform.python_implementation() + + +def unsigned32(i): + """cast signed 32 bit integer to an unsigned integer""" + return i & 0xFFFFFFFF + + +@unittest.skipIf(IS_PYPY, "pypy having illegal instruction on mac") +class PixelcopyModuleTest(unittest.TestCase): + + bitsizes = [8, 16, 32] + + test_palette = [ + (0, 0, 0, 255), + (10, 30, 60, 255), + (25, 75, 100, 255), + (100, 150, 200, 255), + (0, 100, 200, 255), + ] + + surf_size = (10, 12) + test_points = [ + ((0, 0), 1), + ((4, 5), 1), + ((9, 0), 2), + ((5, 5), 2), + ((0, 11), 3), + ((4, 6), 3), + ((9, 11), 4), + ((5, 6), 4), + ] + + def __init__(self, *args, **kwds): + pygame.display.init() + try: + unittest.TestCase.__init__(self, *args, **kwds) + self.sources = [ + self._make_src_surface(8), + self._make_src_surface(16), + self._make_src_surface(16, srcalpha=True), + self._make_src_surface(24), + self._make_src_surface(32), + self._make_src_surface(32, srcalpha=True), + ] + finally: + pygame.display.quit() + + def _make_surface(self, bitsize, srcalpha=False, palette=None): + if palette is None: + palette = self.test_palette + flags = 0 + if srcalpha: + flags |= SRCALPHA + surf = pygame.Surface(self.surf_size, flags, bitsize) + if bitsize == 8: + surf.set_palette([c[:3] for c in palette]) + return surf + + def _fill_surface(self, surf, palette=None): + if palette is None: + palette = self.test_palette + surf.fill(palette[1], (0, 0, 5, 6)) + surf.fill(palette[2], (5, 0, 5, 6)) + surf.fill(palette[3], (0, 6, 5, 6)) + surf.fill(palette[4], (5, 6, 5, 6)) + + def _make_src_surface(self, bitsize, srcalpha=False, palette=None): + surf = self._make_surface(bitsize, srcalpha, palette) + self._fill_surface(surf, palette) + return surf + + def setUp(self): + pygame.display.init() + + def tearDown(self): + pygame.display.quit() + + def test_surface_to_array_2d(self): + alpha_color = (0, 0, 0, 128) + + for surf in self.sources: + src_bitsize = surf.get_bitsize() + for dst_bitsize in self.bitsizes: + # dst in a surface standing in for a 2 dimensional array + # of unsigned integers. The byte order is system dependent. + dst = pygame.Surface(surf.get_size(), 0, dst_bitsize) + dst.fill((0, 0, 0, 0)) + view = dst.get_view("2") + self.assertFalse(surf.get_locked()) + if dst_bitsize < src_bitsize: + self.assertRaises(ValueError, surface_to_array, view, surf) + self.assertFalse(surf.get_locked()) + continue + surface_to_array(view, surf) + self.assertFalse(surf.get_locked()) + for posn, i in self.test_points: + sp = surf.get_at_mapped(posn) + dp = dst.get_at_mapped(posn) + self.assertEqual( + dp, + sp, + "%s != %s: flags: %i" + ", bpp: %i, posn: %s" + % (dp, sp, surf.get_flags(), surf.get_bitsize(), posn), + ) + del view + + if surf.get_masks()[3]: + dst.fill((0, 0, 0, 0)) + view = dst.get_view("2") + posn = (2, 1) + surf.set_at(posn, alpha_color) + self.assertFalse(surf.get_locked()) + surface_to_array(view, surf) + self.assertFalse(surf.get_locked()) + sp = surf.get_at_mapped(posn) + dp = dst.get_at_mapped(posn) + self.assertEqual( + dp, sp, "%s != %s: bpp: %i" % (dp, sp, surf.get_bitsize()) + ) + + if IS_PYPY: + return + # Swapped endian destination array + pai_flags = arrinter.PAI_ALIGNED | arrinter.PAI_WRITEABLE + for surf in self.sources: + for itemsize in [1, 2, 4, 8]: + if itemsize < surf.get_bytesize(): + continue + a = arrinter.Array(surf.get_size(), "u", itemsize, flags=pai_flags) + surface_to_array(a, surf) + for posn, i in self.test_points: + sp = unsigned32(surf.get_at_mapped(posn)) + dp = a[posn] + self.assertEqual( + dp, + sp, + "%s != %s: itemsize: %i, flags: %i" + ", bpp: %i, posn: %s" + % ( + dp, + sp, + itemsize, + surf.get_flags(), + surf.get_bitsize(), + posn, + ), + ) + + def test_surface_to_array_3d(self): + self.iter_surface_to_array_3d((0xFF, 0xFF00, 0xFF0000, 0)) + self.iter_surface_to_array_3d((0xFF0000, 0xFF00, 0xFF, 0)) + + def iter_surface_to_array_3d(self, rgba_masks): + dst = pygame.Surface(self.surf_size, 0, 24, masks=rgba_masks) + + for surf in self.sources: + dst.fill((0, 0, 0, 0)) + src_bitsize = surf.get_bitsize() + view = dst.get_view("3") + self.assertFalse(surf.get_locked()) + surface_to_array(view, surf) + self.assertFalse(surf.get_locked()) + for posn, i in self.test_points: + sc = surf.get_at(posn)[0:3] + dc = dst.get_at(posn)[0:3] + self.assertEqual( + dc, + sc, + "%s != %s: flags: %i" + ", bpp: %i, posn: %s" + % (dc, sc, surf.get_flags(), surf.get_bitsize(), posn), + ) + view = None + + def test_map_array(self): + targets = [ + self._make_surface(8), + self._make_surface(16), + self._make_surface(16, srcalpha=True), + self._make_surface(24), + self._make_surface(32), + self._make_surface(32, srcalpha=True), + ] + source = pygame.Surface( + self.surf_size, 0, 24, masks=[0xFF, 0xFF00, 0xFF0000, 0] + ) + self._fill_surface(source) + source_view = source.get_view("3") # (w, h, 3) + for t in targets: + map_array(t.get_view("2"), source_view, t) + for posn, i in self.test_points: + sc = t.map_rgb(source.get_at(posn)) + dc = t.get_at_mapped(posn) + self.assertEqual( + dc, + sc, + "%s != %s: flags: %i" + ", bpp: %i, posn: %s" + % (dc, sc, t.get_flags(), t.get_bitsize(), posn), + ) + + color = pygame.Color("salmon") + color.set_length(3) + for t in targets: + map_array(t.get_view("2"), color, t) + sc = t.map_rgb(color) + for posn, i in self.test_points: + dc = t.get_at_mapped(posn) + self.assertEqual( + dc, + sc, + "%s != %s: flags: %i" + ", bpp: %i, posn: %s" + % (dc, sc, t.get_flags(), t.get_bitsize(), posn), + ) + + # mismatched shapes + w, h = source.get_size() + target = pygame.Surface((w, h + 1), 0, 32) + self.assertRaises(ValueError, map_array, target, source, target) + target = pygame.Surface((w - 1, h), 0, 32) + self.assertRaises(ValueError, map_array, target, source, target) + + def test_array_to_surface_broadcasting(self): + # target surfaces + targets = [ + self._make_surface(8), + self._make_surface(16), + self._make_surface(16, srcalpha=True), + self._make_surface(24), + self._make_surface(32), + self._make_surface(32, srcalpha=True), + ] + + w, h = self.surf_size + + # broadcast column + column = pygame.Surface((1, h), 0, 32) + for target in targets: + source = pygame.Surface((1, h), 0, target) + for y in range(h): + source.set_at((0, y), pygame.Color(y + 1, y + h + 1, y + 2 * h + 1)) + pygame.pixelcopy.surface_to_array(column.get_view("2"), source) + pygame.pixelcopy.array_to_surface(target, column.get_view("2")) + for x in range(w): + for y in range(h): + self.assertEqual( + target.get_at_mapped((x, y)), column.get_at_mapped((0, y)) + ) + + # broadcast row + row = pygame.Surface((w, 1), 0, 32) + for target in targets: + source = pygame.Surface((w, 1), 0, target) + for x in range(w): + source.set_at((x, 0), pygame.Color(x + 1, x + w + 1, x + 2 * w + 1)) + pygame.pixelcopy.surface_to_array(row.get_view("2"), source) + pygame.pixelcopy.array_to_surface(target, row.get_view("2")) + for x in range(w): + for y in range(h): + self.assertEqual( + target.get_at_mapped((x, y)), row.get_at_mapped((x, 0)) + ) + + # broadcast pixel + pixel = pygame.Surface((1, 1), 0, 32) + for target in targets: + source = pygame.Surface((1, 1), 0, target) + source.set_at((0, 0), pygame.Color(13, 47, 101)) + pygame.pixelcopy.surface_to_array(pixel.get_view("2"), source) + pygame.pixelcopy.array_to_surface(target, pixel.get_view("2")) + p = pixel.get_at_mapped((0, 0)) + for x in range(w): + for y in range(h): + self.assertEqual(target.get_at_mapped((x, y)), p) + + +@unittest.skipIf(IS_PYPY, "pypy having illegal instruction on mac") +class PixelCopyTestWithArray(unittest.TestCase): + try: + import numpy + except ImportError: + __tags__ = ["ignore", "subprocess_ignore"] + else: + pygame.surfarray.use_arraytype("numpy") + + bitsizes = [8, 16, 32] + + test_palette = [ + (0, 0, 0, 255), + (10, 30, 60, 255), + (25, 75, 100, 255), + (100, 150, 200, 255), + (0, 100, 200, 255), + ] + + surf_size = (10, 12) + test_points = [ + ((0, 0), 1), + ((4, 5), 1), + ((9, 0), 2), + ((5, 5), 2), + ((0, 11), 3), + ((4, 6), 3), + ((9, 11), 4), + ((5, 6), 4), + ] + + pixels2d = set([8, 16, 32]) + pixels3d = set([24, 32]) + array2d = set([8, 16, 24, 32]) + array3d = set([24, 32]) + + def __init__(self, *args, **kwds): + import numpy + + self.dst_types = [numpy.uint8, numpy.uint16, numpy.uint32] + try: + self.dst_types.append(numpy.uint64) + except AttributeError: + pass + pygame.display.init() + try: + unittest.TestCase.__init__(self, *args, **kwds) + self.sources = [ + self._make_src_surface(8), + self._make_src_surface(16), + self._make_src_surface(16, srcalpha=True), + self._make_src_surface(24), + self._make_src_surface(32), + self._make_src_surface(32, srcalpha=True), + ] + finally: + pygame.display.quit() + + def _make_surface(self, bitsize, srcalpha=False, palette=None): + if palette is None: + palette = self.test_palette + flags = 0 + if srcalpha: + flags |= SRCALPHA + surf = pygame.Surface(self.surf_size, flags, bitsize) + if bitsize == 8: + surf.set_palette([c[:3] for c in palette]) + return surf + + def _fill_surface(self, surf, palette=None): + if palette is None: + palette = self.test_palette + surf.fill(palette[1], (0, 0, 5, 6)) + surf.fill(palette[2], (5, 0, 5, 6)) + surf.fill(palette[3], (0, 6, 5, 6)) + surf.fill(palette[4], (5, 6, 5, 6)) + + def _make_src_surface(self, bitsize, srcalpha=False, palette=None): + surf = self._make_surface(bitsize, srcalpha, palette) + self._fill_surface(surf, palette) + return surf + + def setUp(self): + pygame.display.init() + + def tearDown(self): + pygame.display.quit() + + def test_surface_to_array_2d(self): + try: + from numpy import empty, dtype + except ImportError: + return + + palette = self.test_palette + alpha_color = (0, 0, 0, 128) + + dst_dims = self.surf_size + destinations = [empty(dst_dims, t) for t in self.dst_types] + if pygame.get_sdl_byteorder() == pygame.LIL_ENDIAN: + swapped_dst = empty(dst_dims, dtype(">u4")) + else: + swapped_dst = empty(dst_dims, dtype("u4")) + else: + swapped_dst = empty(dst_dims, dtype("i", + "!i", + "1i", + "=1i", + "@q", + "q", + "4x", + "8x", + ]: + surface.fill((255, 254, 253)) + exp = Exporter(shape, format=format) + exp._buf[:] = [42] * exp.buflen + array_to_surface(surface, exp) + for x in range(w): + for y in range(h): + self.assertEqual(surface.get_at((x, y)), (42, 42, 42, 255)) + # Some unsupported formats for array_to_surface and a 32 bit surface + for format in ["f", "d", "?", "x", "1x", "2x", "3x", "5x", "6x", "7x", "9x"]: + exp = Exporter(shape, format=format) + self.assertRaises(ValueError, array_to_surface, surface, exp) + + +if __name__ == "__main__": + unittest.main() diff --git a/venv/Lib/site-packages/pygame/tests/rect_test.py b/venv/Lib/site-packages/pygame/tests/rect_test.py new file mode 100644 index 0000000..0d635c8 --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/rect_test.py @@ -0,0 +1,2152 @@ +import math +import sys +import unittest +import platform + +from pygame import Rect, Vector2 +from pygame.tests import test_utils + + +IS_PYPY = "PyPy" == platform.python_implementation() + + +class RectTypeTest(unittest.TestCase): + def _assertCountEqual(self, *args, **kwargs): + self.assertCountEqual(*args, **kwargs) + + def testConstructionXYWidthHeight(self): + r = Rect(1, 2, 3, 4) + self.assertEqual(1, r.left) + self.assertEqual(2, r.top) + self.assertEqual(3, r.width) + self.assertEqual(4, r.height) + + def testConstructionTopLeftSize(self): + r = Rect((1, 2), (3, 4)) + self.assertEqual(1, r.left) + self.assertEqual(2, r.top) + self.assertEqual(3, r.width) + self.assertEqual(4, r.height) + + def testCalculatedAttributes(self): + r = Rect(1, 2, 3, 4) + + self.assertEqual(r.left + r.width, r.right) + self.assertEqual(r.top + r.height, r.bottom) + self.assertEqual((r.width, r.height), r.size) + self.assertEqual((r.left, r.top), r.topleft) + self.assertEqual((r.right, r.top), r.topright) + self.assertEqual((r.left, r.bottom), r.bottomleft) + self.assertEqual((r.right, r.bottom), r.bottomright) + + midx = r.left + r.width // 2 + midy = r.top + r.height // 2 + + self.assertEqual(midx, r.centerx) + self.assertEqual(midy, r.centery) + self.assertEqual((r.centerx, r.centery), r.center) + self.assertEqual((r.centerx, r.top), r.midtop) + self.assertEqual((r.centerx, r.bottom), r.midbottom) + self.assertEqual((r.left, r.centery), r.midleft) + self.assertEqual((r.right, r.centery), r.midright) + + def test_normalize(self): + """Ensures normalize works when width and height are both negative.""" + test_rect = Rect((1, 2), (-3, -6)) + expected_normalized_rect = ( + (test_rect.x + test_rect.w, test_rect.y + test_rect.h), + (-test_rect.w, -test_rect.h), + ) + + test_rect.normalize() + + self.assertEqual(test_rect, expected_normalized_rect) + + @unittest.skipIf(IS_PYPY, "fails on pypy sometimes") + def test_normalize__positive_height(self): + """Ensures normalize works with a negative width and a positive height.""" + test_rect = Rect((1, 2), (-3, 6)) + expected_normalized_rect = ( + (test_rect.x + test_rect.w, test_rect.y), + (-test_rect.w, test_rect.h), + ) + + test_rect.normalize() + + self.assertEqual(test_rect, expected_normalized_rect) + + @unittest.skipIf(IS_PYPY, "fails on pypy sometimes") + def test_normalize__positive_width(self): + """Ensures normalize works with a positive width and a negative height.""" + test_rect = Rect((1, 2), (3, -6)) + expected_normalized_rect = ( + (test_rect.x, test_rect.y + test_rect.h), + (test_rect.w, -test_rect.h), + ) + + test_rect.normalize() + + self.assertEqual(test_rect, expected_normalized_rect) + + @unittest.skipIf(IS_PYPY, "fails on pypy sometimes") + def test_normalize__zero_height(self): + """Ensures normalize works with a negative width and a zero height.""" + test_rect = Rect((1, 2), (-3, 0)) + expected_normalized_rect = ( + (test_rect.x + test_rect.w, test_rect.y), + (-test_rect.w, test_rect.h), + ) + + test_rect.normalize() + + self.assertEqual(test_rect, expected_normalized_rect) + + @unittest.skipIf(IS_PYPY, "fails on pypy sometimes") + def test_normalize__zero_width(self): + """Ensures normalize works with a zero width and a negative height.""" + test_rect = Rect((1, 2), (0, -6)) + expected_normalized_rect = ( + (test_rect.x, test_rect.y + test_rect.h), + (test_rect.w, -test_rect.h), + ) + + test_rect.normalize() + + self.assertEqual(test_rect, expected_normalized_rect) + + @unittest.skipIf(IS_PYPY, "fails on pypy") + def test_normalize__non_negative(self): + """Ensures normalize works when width and height are both non-negative. + + Tests combinations of positive and zero values for width and height. + The normalize method has no impact when both width and height are + non-negative. + """ + for size in ((3, 6), (3, 0), (0, 6), (0, 0)): + test_rect = Rect((1, 2), size) + expected_normalized_rect = Rect(test_rect) + + test_rect.normalize() + + self.assertEqual(test_rect, expected_normalized_rect) + + def test_x(self): + """Ensures changing the x attribute moves the rect and does not change + the rect's size. + """ + expected_x = 10 + expected_y = 2 + expected_size = (3, 4) + r = Rect((1, expected_y), expected_size) + + r.x = expected_x + + self.assertEqual(r.x, expected_x) + self.assertEqual(r.x, r.left) + self.assertEqual(r.y, expected_y) + self.assertEqual(r.size, expected_size) + + def test_x__invalid_value(self): + """Ensures the x attribute handles invalid values correctly.""" + r = Rect(0, 0, 1, 1) + + for value in (None, [], "1", (1,), [1, 2, 3]): + with self.assertRaises(TypeError): + r.x = value + + def test_x__del(self): + """Ensures the x attribute can't be deleted.""" + r = Rect(0, 0, 1, 1) + + with self.assertRaises(AttributeError): + del r.x + + def test_y(self): + """Ensures changing the y attribute moves the rect and does not change + the rect's size. + """ + expected_x = 1 + expected_y = 20 + expected_size = (3, 4) + r = Rect((expected_x, 2), expected_size) + + r.y = expected_y + + self.assertEqual(r.y, expected_y) + self.assertEqual(r.y, r.top) + self.assertEqual(r.x, expected_x) + self.assertEqual(r.size, expected_size) + + def test_y__invalid_value(self): + """Ensures the y attribute handles invalid values correctly.""" + r = Rect(0, 0, 1, 1) + + for value in (None, [], "1", (1,), [1, 2, 3]): + with self.assertRaises(TypeError): + r.y = value + + def test_y__del(self): + """Ensures the y attribute can't be deleted.""" + r = Rect(0, 0, 1, 1) + + with self.assertRaises(AttributeError): + del r.y + + def test_left(self): + """Changing the left attribute moves the rect and does not change + the rect's width + """ + r = Rect(1, 2, 3, 4) + new_left = 10 + + r.left = new_left + self.assertEqual(new_left, r.left) + self.assertEqual(Rect(new_left, 2, 3, 4), r) + + def test_left__invalid_value(self): + """Ensures the left attribute handles invalid values correctly.""" + r = Rect(0, 0, 1, 1) + + for value in (None, [], "1", (1,), [1, 2, 3]): + with self.assertRaises(TypeError): + r.left = value + + def test_left__del(self): + """Ensures the left attribute can't be deleted.""" + r = Rect(0, 0, 1, 1) + + with self.assertRaises(AttributeError): + del r.left + + def test_right(self): + """Changing the right attribute moves the rect and does not change + the rect's width + """ + r = Rect(1, 2, 3, 4) + new_right = r.right + 20 + expected_left = r.left + 20 + old_width = r.width + + r.right = new_right + self.assertEqual(new_right, r.right) + self.assertEqual(expected_left, r.left) + self.assertEqual(old_width, r.width) + + def test_right__invalid_value(self): + """Ensures the right attribute handles invalid values correctly.""" + r = Rect(0, 0, 1, 1) + + for value in (None, [], "1", (1,), [1, 2, 3]): + with self.assertRaises(TypeError): + r.right = value + + def test_right__del(self): + """Ensures the right attribute can't be deleted.""" + r = Rect(0, 0, 1, 1) + + with self.assertRaises(AttributeError): + del r.right + + def test_top(self): + """Changing the top attribute moves the rect and does not change + the rect's width + """ + r = Rect(1, 2, 3, 4) + new_top = 10 + + r.top = new_top + self.assertEqual(Rect(1, new_top, 3, 4), r) + self.assertEqual(new_top, r.top) + + def test_top__invalid_value(self): + """Ensures the top attribute handles invalid values correctly.""" + r = Rect(0, 0, 1, 1) + + for value in (None, [], "1", (1,), [1, 2, 3]): + with self.assertRaises(TypeError): + r.top = value + + def test_top__del(self): + """Ensures the top attribute can't be deleted.""" + r = Rect(0, 0, 1, 1) + + with self.assertRaises(AttributeError): + del r.top + + def test_bottom(self): + """Changing the bottom attribute moves the rect and does not change + the rect's height + """ + r = Rect(1, 2, 3, 4) + new_bottom = r.bottom + 20 + expected_top = r.top + 20 + old_height = r.height + + r.bottom = new_bottom + self.assertEqual(new_bottom, r.bottom) + self.assertEqual(expected_top, r.top) + self.assertEqual(old_height, r.height) + + def test_bottom__invalid_value(self): + """Ensures the bottom attribute handles invalid values correctly.""" + r = Rect(0, 0, 1, 1) + + for value in (None, [], "1", (1,), [1, 2, 3]): + with self.assertRaises(TypeError): + r.bottom = value + + def test_bottom__del(self): + """Ensures the bottom attribute can't be deleted.""" + r = Rect(0, 0, 1, 1) + + with self.assertRaises(AttributeError): + del r.bottom + + def test_centerx(self): + """Changing the centerx attribute moves the rect and does not change + the rect's width + """ + r = Rect(1, 2, 3, 4) + new_centerx = r.centerx + 20 + expected_left = r.left + 20 + old_width = r.width + + r.centerx = new_centerx + self.assertEqual(new_centerx, r.centerx) + self.assertEqual(expected_left, r.left) + self.assertEqual(old_width, r.width) + + def test_centerx__invalid_value(self): + """Ensures the centerx attribute handles invalid values correctly.""" + r = Rect(0, 0, 1, 1) + + for value in (None, [], "1", (1,), [1, 2, 3]): + with self.assertRaises(TypeError): + r.centerx = value + + def test_centerx__del(self): + """Ensures the centerx attribute can't be deleted.""" + r = Rect(0, 0, 1, 1) + + with self.assertRaises(AttributeError): + del r.centerx + + def test_centery(self): + """Changing the centery attribute moves the rect and does not change + the rect's width + """ + r = Rect(1, 2, 3, 4) + new_centery = r.centery + 20 + expected_top = r.top + 20 + old_height = r.height + + r.centery = new_centery + self.assertEqual(new_centery, r.centery) + self.assertEqual(expected_top, r.top) + self.assertEqual(old_height, r.height) + + def test_centery__invalid_value(self): + """Ensures the centery attribute handles invalid values correctly.""" + r = Rect(0, 0, 1, 1) + + for value in (None, [], "1", (1,), [1, 2, 3]): + with self.assertRaises(TypeError): + r.centery = value + + def test_centery__del(self): + """Ensures the centery attribute can't be deleted.""" + r = Rect(0, 0, 1, 1) + + with self.assertRaises(AttributeError): + del r.centery + + def test_topleft(self): + """Changing the topleft attribute moves the rect and does not change + the rect's size + """ + r = Rect(1, 2, 3, 4) + new_topleft = (r.left + 20, r.top + 30) + old_size = r.size + + r.topleft = new_topleft + self.assertEqual(new_topleft, r.topleft) + self.assertEqual(old_size, r.size) + + def test_topleft__invalid_value(self): + """Ensures the topleft attribute handles invalid values correctly.""" + r = Rect(0, 0, 1, 1) + + for value in (None, [], "1", 1, (1,), [1, 2, 3]): + with self.assertRaises(TypeError): + r.topleft = value + + def test_topleft__del(self): + """Ensures the topleft attribute can't be deleted.""" + r = Rect(0, 0, 1, 1) + + with self.assertRaises(AttributeError): + del r.topleft + + def test_bottomleft(self): + """Changing the bottomleft attribute moves the rect and does not change + the rect's size + """ + r = Rect(1, 2, 3, 4) + new_bottomleft = (r.left + 20, r.bottom + 30) + expected_topleft = (r.left + 20, r.top + 30) + old_size = r.size + + r.bottomleft = new_bottomleft + self.assertEqual(new_bottomleft, r.bottomleft) + self.assertEqual(expected_topleft, r.topleft) + self.assertEqual(old_size, r.size) + + def test_bottomleft__invalid_value(self): + """Ensures the bottomleft attribute handles invalid values correctly.""" + r = Rect(0, 0, 1, 1) + + for value in (None, [], "1", 1, (1,), [1, 2, 3]): + with self.assertRaises(TypeError): + r.bottomleft = value + + def test_bottomleft__del(self): + """Ensures the bottomleft attribute can't be deleted.""" + r = Rect(0, 0, 1, 1) + + with self.assertRaises(AttributeError): + del r.bottomleft + + def test_topright(self): + """Changing the topright attribute moves the rect and does not change + the rect's size + """ + r = Rect(1, 2, 3, 4) + new_topright = (r.right + 20, r.top + 30) + expected_topleft = (r.left + 20, r.top + 30) + old_size = r.size + + r.topright = new_topright + self.assertEqual(new_topright, r.topright) + self.assertEqual(expected_topleft, r.topleft) + self.assertEqual(old_size, r.size) + + def test_topright__invalid_value(self): + """Ensures the topright attribute handles invalid values correctly.""" + r = Rect(0, 0, 1, 1) + + for value in (None, [], "1", 1, (1,), [1, 2, 3]): + with self.assertRaises(TypeError): + r.topright = value + + def test_topright__del(self): + """Ensures the topright attribute can't be deleted.""" + r = Rect(0, 0, 1, 1) + + with self.assertRaises(AttributeError): + del r.topright + + def test_bottomright(self): + """Changing the bottomright attribute moves the rect and does not change + the rect's size + """ + r = Rect(1, 2, 3, 4) + new_bottomright = (r.right + 20, r.bottom + 30) + expected_topleft = (r.left + 20, r.top + 30) + old_size = r.size + + r.bottomright = new_bottomright + self.assertEqual(new_bottomright, r.bottomright) + self.assertEqual(expected_topleft, r.topleft) + self.assertEqual(old_size, r.size) + + def test_bottomright__invalid_value(self): + """Ensures the bottomright attribute handles invalid values correctly.""" + r = Rect(0, 0, 1, 1) + + for value in (None, [], "1", 1, (1,), [1, 2, 3]): + with self.assertRaises(TypeError): + r.bottomright = value + + def test_bottomright__del(self): + """Ensures the bottomright attribute can't be deleted.""" + r = Rect(0, 0, 1, 1) + + with self.assertRaises(AttributeError): + del r.bottomright + + def test_center(self): + """Changing the center attribute moves the rect and does not change + the rect's size + """ + r = Rect(1, 2, 3, 4) + new_center = (r.centerx + 20, r.centery + 30) + expected_topleft = (r.left + 20, r.top + 30) + old_size = r.size + + r.center = new_center + self.assertEqual(new_center, r.center) + self.assertEqual(expected_topleft, r.topleft) + self.assertEqual(old_size, r.size) + + def test_center__invalid_value(self): + """Ensures the center attribute handles invalid values correctly.""" + r = Rect(0, 0, 1, 1) + + for value in (None, [], "1", 1, (1,), [1, 2, 3]): + with self.assertRaises(TypeError): + r.center = value + + def test_center__del(self): + """Ensures the center attribute can't be deleted.""" + r = Rect(0, 0, 1, 1) + + with self.assertRaises(AttributeError): + del r.center + + def test_midleft(self): + """Changing the midleft attribute moves the rect and does not change + the rect's size + """ + r = Rect(1, 2, 3, 4) + new_midleft = (r.left + 20, r.centery + 30) + expected_topleft = (r.left + 20, r.top + 30) + old_size = r.size + + r.midleft = new_midleft + self.assertEqual(new_midleft, r.midleft) + self.assertEqual(expected_topleft, r.topleft) + self.assertEqual(old_size, r.size) + + def test_midleft__invalid_value(self): + """Ensures the midleft attribute handles invalid values correctly.""" + r = Rect(0, 0, 1, 1) + + for value in (None, [], "1", 1, (1,), [1, 2, 3]): + with self.assertRaises(TypeError): + r.midleft = value + + def test_midleft__del(self): + """Ensures the midleft attribute can't be deleted.""" + r = Rect(0, 0, 1, 1) + + with self.assertRaises(AttributeError): + del r.midleft + + def test_midright(self): + """Changing the midright attribute moves the rect and does not change + the rect's size + """ + r = Rect(1, 2, 3, 4) + new_midright = (r.right + 20, r.centery + 30) + expected_topleft = (r.left + 20, r.top + 30) + old_size = r.size + + r.midright = new_midright + self.assertEqual(new_midright, r.midright) + self.assertEqual(expected_topleft, r.topleft) + self.assertEqual(old_size, r.size) + + def test_midright__invalid_value(self): + """Ensures the midright attribute handles invalid values correctly.""" + r = Rect(0, 0, 1, 1) + + for value in (None, [], "1", 1, (1,), [1, 2, 3]): + with self.assertRaises(TypeError): + r.midright = value + + def test_midright__del(self): + """Ensures the midright attribute can't be deleted.""" + r = Rect(0, 0, 1, 1) + + with self.assertRaises(AttributeError): + del r.midright + + def test_midtop(self): + """Changing the midtop attribute moves the rect and does not change + the rect's size + """ + r = Rect(1, 2, 3, 4) + new_midtop = (r.centerx + 20, r.top + 30) + expected_topleft = (r.left + 20, r.top + 30) + old_size = r.size + + r.midtop = new_midtop + self.assertEqual(new_midtop, r.midtop) + self.assertEqual(expected_topleft, r.topleft) + self.assertEqual(old_size, r.size) + + def test_midtop__invalid_value(self): + """Ensures the midtop attribute handles invalid values correctly.""" + r = Rect(0, 0, 1, 1) + + for value in (None, [], "1", 1, (1,), [1, 2, 3]): + with self.assertRaises(TypeError): + r.midtop = value + + def test_midtop__del(self): + """Ensures the midtop attribute can't be deleted.""" + r = Rect(0, 0, 1, 1) + + with self.assertRaises(AttributeError): + del r.midtop + + def test_midbottom(self): + """Changing the midbottom attribute moves the rect and does not change + the rect's size + """ + r = Rect(1, 2, 3, 4) + new_midbottom = (r.centerx + 20, r.bottom + 30) + expected_topleft = (r.left + 20, r.top + 30) + old_size = r.size + + r.midbottom = new_midbottom + self.assertEqual(new_midbottom, r.midbottom) + self.assertEqual(expected_topleft, r.topleft) + self.assertEqual(old_size, r.size) + + def test_midbottom__invalid_value(self): + """Ensures the midbottom attribute handles invalid values correctly.""" + r = Rect(0, 0, 1, 1) + + for value in (None, [], "1", 1, (1,), [1, 2, 3]): + with self.assertRaises(TypeError): + r.midbottom = value + + def test_midbottom__del(self): + """Ensures the midbottom attribute can't be deleted.""" + r = Rect(0, 0, 1, 1) + + with self.assertRaises(AttributeError): + del r.midbottom + + def test_width(self): + """Changing the width resizes the rect from the top-left corner""" + r = Rect(1, 2, 3, 4) + new_width = 10 + old_topleft = r.topleft + old_height = r.height + + r.width = new_width + self.assertEqual(new_width, r.width) + self.assertEqual(old_height, r.height) + self.assertEqual(old_topleft, r.topleft) + + def test_width__invalid_value(self): + """Ensures the width attribute handles invalid values correctly.""" + r = Rect(0, 0, 1, 1) + + for value in (None, [], "1", (1,), [1, 2, 3]): + with self.assertRaises(TypeError): + r.width = value + + def test_width__del(self): + """Ensures the width attribute can't be deleted.""" + r = Rect(0, 0, 1, 1) + + with self.assertRaises(AttributeError): + del r.width + + def test_height(self): + """Changing the height resizes the rect from the top-left corner""" + r = Rect(1, 2, 3, 4) + new_height = 10 + old_topleft = r.topleft + old_width = r.width + + r.height = new_height + self.assertEqual(new_height, r.height) + self.assertEqual(old_width, r.width) + self.assertEqual(old_topleft, r.topleft) + + def test_height__invalid_value(self): + """Ensures the height attribute handles invalid values correctly.""" + r = Rect(0, 0, 1, 1) + + for value in (None, [], "1", (1,), [1, 2, 3]): + with self.assertRaises(TypeError): + r.height = value + + def test_height__del(self): + """Ensures the height attribute can't be deleted.""" + r = Rect(0, 0, 1, 1) + + with self.assertRaises(AttributeError): + del r.height + + def test_size(self): + """Changing the size resizes the rect from the top-left corner""" + r = Rect(1, 2, 3, 4) + new_size = (10, 20) + old_topleft = r.topleft + + r.size = new_size + self.assertEqual(new_size, r.size) + self.assertEqual(old_topleft, r.topleft) + + def test_size__invalid_value(self): + """Ensures the size attribute handles invalid values correctly.""" + r = Rect(0, 0, 1, 1) + + for value in (None, [], "1", 1, (1,), [1, 2, 3]): + with self.assertRaises(TypeError): + r.size = value + + def test_size__del(self): + """Ensures the size attribute can't be deleted.""" + r = Rect(0, 0, 1, 1) + + with self.assertRaises(AttributeError): + del r.size + + def test_contains(self): + r = Rect(1, 2, 3, 4) + + self.assertTrue( + r.contains(Rect(2, 3, 1, 1)), "r does not contain Rect(2, 3, 1, 1)" + ) + self.assertTrue(Rect(2, 3, 1, 1) in r, "r does not contain Rect(2, 3, 1, 1) 2") + self.assertTrue( + r.contains(Rect(r)), "r does not contain the same rect as itself" + ) + self.assertTrue(r in Rect(r), "r does not contain the same rect as itself") + self.assertTrue( + r.contains(Rect(2, 3, 0, 0)), + "r does not contain an empty rect within its bounds", + ) + self.assertTrue( + Rect(2, 3, 0, 0) in r, + "r does not contain an empty rect within its bounds", + ) + self.assertFalse(r.contains(Rect(0, 0, 1, 2)), "r contains Rect(0, 0, 1, 2)") + self.assertFalse(r.contains(Rect(4, 6, 1, 1)), "r contains Rect(4, 6, 1, 1)") + self.assertFalse(r.contains(Rect(4, 6, 0, 0)), "r contains Rect(4, 6, 0, 0)") + self.assertFalse(Rect(0, 0, 1, 2) in r, "r contains Rect(0, 0, 1, 2)") + self.assertFalse(Rect(4, 6, 1, 1) in r, "r contains Rect(4, 6, 1, 1)") + self.assertFalse(Rect(4, 6, 0, 0) in r, "r contains Rect(4, 6, 0, 0)") + self.assertTrue(2 in Rect(0, 0, 1, 2), "r does not contain 2") + self.assertFalse(3 in Rect(0, 0, 1, 2), "r contains 3") + + def test_collidepoint(self): + r = Rect(1, 2, 3, 4) + + self.assertTrue( + r.collidepoint(r.left, r.top), "r does not collide with point (left, top)" + ) + self.assertFalse( + r.collidepoint(r.left - 1, r.top), "r collides with point (left - 1, top)" + ) + self.assertFalse( + r.collidepoint(r.left, r.top - 1), "r collides with point (left, top - 1)" + ) + self.assertFalse( + r.collidepoint(r.left - 1, r.top - 1), + "r collides with point (left - 1, top - 1)", + ) + + self.assertTrue( + r.collidepoint(r.right - 1, r.bottom - 1), + "r does not collide with point (right - 1, bottom - 1)", + ) + self.assertFalse( + r.collidepoint(r.right, r.bottom), "r collides with point (right, bottom)" + ) + self.assertFalse( + r.collidepoint(r.right - 1, r.bottom), + "r collides with point (right - 1, bottom)", + ) + self.assertFalse( + r.collidepoint(r.right, r.bottom - 1), + "r collides with point (right, bottom - 1)", + ) + + def test_inflate__larger(self): + """The inflate method inflates around the center of the rectangle""" + r = Rect(2, 4, 6, 8) + r2 = r.inflate(4, 6) + + self.assertEqual(r.center, r2.center) + self.assertEqual(r.left - 2, r2.left) + self.assertEqual(r.top - 3, r2.top) + self.assertEqual(r.right + 2, r2.right) + self.assertEqual(r.bottom + 3, r2.bottom) + self.assertEqual(r.width + 4, r2.width) + self.assertEqual(r.height + 6, r2.height) + + def test_inflate__smaller(self): + """The inflate method inflates around the center of the rectangle""" + r = Rect(2, 4, 6, 8) + r2 = r.inflate(-4, -6) + + self.assertEqual(r.center, r2.center) + self.assertEqual(r.left + 2, r2.left) + self.assertEqual(r.top + 3, r2.top) + self.assertEqual(r.right - 2, r2.right) + self.assertEqual(r.bottom - 3, r2.bottom) + self.assertEqual(r.width - 4, r2.width) + self.assertEqual(r.height - 6, r2.height) + + def test_inflate_ip__larger(self): + """The inflate_ip method inflates around the center of the rectangle""" + r = Rect(2, 4, 6, 8) + r2 = Rect(r) + r2.inflate_ip(-4, -6) + + self.assertEqual(r.center, r2.center) + self.assertEqual(r.left + 2, r2.left) + self.assertEqual(r.top + 3, r2.top) + self.assertEqual(r.right - 2, r2.right) + self.assertEqual(r.bottom - 3, r2.bottom) + self.assertEqual(r.width - 4, r2.width) + self.assertEqual(r.height - 6, r2.height) + + def test_inflate_ip__smaller(self): + """The inflate method inflates around the center of the rectangle""" + r = Rect(2, 4, 6, 8) + r2 = Rect(r) + r2.inflate_ip(-4, -6) + + self.assertEqual(r.center, r2.center) + self.assertEqual(r.left + 2, r2.left) + self.assertEqual(r.top + 3, r2.top) + self.assertEqual(r.right - 2, r2.right) + self.assertEqual(r.bottom - 3, r2.bottom) + self.assertEqual(r.width - 4, r2.width) + self.assertEqual(r.height - 6, r2.height) + + def test_clamp(self): + r = Rect(10, 10, 10, 10) + c = Rect(19, 12, 5, 5).clamp(r) + self.assertEqual(c.right, r.right) + self.assertEqual(c.top, 12) + c = Rect(1, 2, 3, 4).clamp(r) + self.assertEqual(c.topleft, r.topleft) + c = Rect(5, 500, 22, 33).clamp(r) + self.assertEqual(c.center, r.center) + + def test_clamp_ip(self): + r = Rect(10, 10, 10, 10) + c = Rect(19, 12, 5, 5) + c.clamp_ip(r) + self.assertEqual(c.right, r.right) + self.assertEqual(c.top, 12) + c = Rect(1, 2, 3, 4) + c.clamp_ip(r) + self.assertEqual(c.topleft, r.topleft) + c = Rect(5, 500, 22, 33) + c.clamp_ip(r) + self.assertEqual(c.center, r.center) + + def test_clip(self): + r1 = Rect(1, 2, 3, 4) + self.assertEqual(Rect(1, 2, 2, 2), r1.clip(Rect(0, 0, 3, 4))) + self.assertEqual(Rect(2, 2, 2, 4), r1.clip(Rect(2, 2, 10, 20))) + self.assertEqual(Rect(2, 3, 1, 2), r1.clip(Rect(2, 3, 1, 2))) + self.assertEqual((0, 0), r1.clip(20, 30, 5, 6).size) + self.assertEqual( + r1, r1.clip(Rect(r1)), "r1 does not clip an identical rect to itself" + ) + + def test_clipline(self): + """Ensures clipline handles four int parameters. + + Tests the clipline(x1, y1, x2, y2) format. + """ + rect = Rect((1, 2), (35, 40)) + x1 = 5 + y1 = 6 + x2 = 11 + y2 = 19 + expected_line = ((x1, y1), (x2, y2)) + + clipped_line = rect.clipline(x1, y1, x2, y2) + + self.assertIsInstance(clipped_line, tuple) + self.assertTupleEqual(clipped_line, expected_line) + + def test_clipline__two_sequences(self): + """Ensures clipline handles a sequence of two sequences. + + Tests the clipline((x1, y1), (x2, y2)) format. + Tests the sequences as different types. + """ + rect = Rect((1, 2), (35, 40)) + pt1 = (5, 6) + pt2 = (11, 19) + + INNER_SEQUENCES = (list, tuple, Vector2) + expected_line = (pt1, pt2) + + for inner_seq1 in INNER_SEQUENCES: + endpt1 = inner_seq1(pt1) + + for inner_seq2 in INNER_SEQUENCES: + clipped_line = rect.clipline((endpt1, inner_seq2(pt2))) + + self.assertIsInstance(clipped_line, tuple) + self.assertTupleEqual(clipped_line, expected_line) + + def test_clipline__sequence_of_four_ints(self): + """Ensures clipline handles a sequence of four ints. + + Tests the clipline((x1, y1, x2, y2)) format. + Tests the sequence as different types. + """ + rect = Rect((1, 2), (35, 40)) + line = (5, 6, 11, 19) + expected_line = ((line[0], line[1]), (line[2], line[3])) + + for outer_seq in (list, tuple): + clipped_line = rect.clipline(outer_seq(line)) + + self.assertIsInstance(clipped_line, tuple) + self.assertTupleEqual(clipped_line, expected_line) + + def test_clipline__sequence_of_two_sequences(self): + """Ensures clipline handles a sequence of two sequences. + + Tests the clipline(((x1, y1), (x2, y2))) format. + Tests the sequences as different types. + """ + rect = Rect((1, 2), (35, 40)) + pt1 = (5, 6) + pt2 = (11, 19) + + INNER_SEQUENCES = (list, tuple, Vector2) + expected_line = (pt1, pt2) + + for inner_seq1 in INNER_SEQUENCES: + endpt1 = inner_seq1(pt1) + + for inner_seq2 in INNER_SEQUENCES: + endpt2 = inner_seq2(pt2) + + for outer_seq in (list, tuple): + clipped_line = rect.clipline(outer_seq((endpt1, endpt2))) + + self.assertIsInstance(clipped_line, tuple) + self.assertTupleEqual(clipped_line, expected_line) + + def test_clipline__floats(self): + """Ensures clipline handles float parameters.""" + rect = Rect((1, 2), (35, 40)) + x1 = 5.9 + y1 = 6.9 + x2 = 11.9 + y2 = 19.9 + + # Floats are truncated. + expected_line = ( + (math.floor(x1), math.floor(y1)), + (math.floor(x2), math.floor(y2)), + ) + + clipped_line = rect.clipline(x1, y1, x2, y2) + + self.assertIsInstance(clipped_line, tuple) + self.assertTupleEqual(clipped_line, expected_line) + + def test_clipline__no_overlap(self): + """Ensures lines that do not overlap the rect are not clipped.""" + rect = Rect((10, 25), (15, 20)) + # Use a bigger rect to help create test lines. + big_rect = rect.inflate(2, 2) + lines = ( + (big_rect.bottomleft, big_rect.topleft), # Left edge. + (big_rect.topleft, big_rect.topright), # Top edge. + (big_rect.topright, big_rect.bottomright), # Right edge. + (big_rect.bottomright, big_rect.bottomleft), + ) # Bottom edge. + expected_line = () + + # Test lines outside rect. + for line in lines: + clipped_line = rect.clipline(line) + + self.assertTupleEqual(clipped_line, expected_line) + + def test_clipline__both_endpoints_outside(self): + """Ensures lines that overlap the rect are clipped. + + Testing lines with both endpoints outside the rect. + """ + rect = Rect((0, 0), (20, 20)) + # Use a bigger rect to help create test lines. + big_rect = rect.inflate(2, 2) + + # Create a dict of lines and expected results. + line_dict = { + (big_rect.midleft, big_rect.midright): ( + rect.midleft, + (rect.midright[0] - 1, rect.midright[1]), + ), + (big_rect.midtop, big_rect.midbottom): ( + rect.midtop, + (rect.midbottom[0], rect.midbottom[1] - 1), + ), + # Diagonals. + (big_rect.topleft, big_rect.bottomright): ( + rect.topleft, + (rect.bottomright[0] - 1, rect.bottomright[1] - 1), + ), + # This line needs a small adjustment to make sure it intersects + # the rect correctly. + ( + (big_rect.topright[0] - 1, big_rect.topright[1]), + (big_rect.bottomleft[0], big_rect.bottomleft[1] - 1), + ): ( + (rect.topright[0] - 1, rect.topright[1]), + (rect.bottomleft[0], rect.bottomleft[1] - 1), + ), + } + + for line, expected_line in line_dict.items(): + clipped_line = rect.clipline(line) + + self.assertTupleEqual(clipped_line, expected_line) + + # Swap endpoints to test for symmetry. + expected_line = (expected_line[1], expected_line[0]) + + clipped_line = rect.clipline((line[1], line[0])) + + self.assertTupleEqual(clipped_line, expected_line) + + def test_clipline__both_endpoints_inside(self): + """Ensures lines that overlap the rect are clipped. + + Testing lines with both endpoints inside the rect. + """ + rect = Rect((-10, -5), (20, 20)) + # Use a smaller rect to help create test lines. + small_rect = rect.inflate(-2, -2) + + lines = ( + (small_rect.midleft, small_rect.midright), + (small_rect.midtop, small_rect.midbottom), + # Diagonals. + (small_rect.topleft, small_rect.bottomright), + (small_rect.topright, small_rect.bottomleft), + ) + + for line in lines: + expected_line = line + + clipped_line = rect.clipline(line) + + self.assertTupleEqual(clipped_line, expected_line) + + # Swap endpoints to test for symmetry. + expected_line = (expected_line[1], expected_line[0]) + + clipped_line = rect.clipline((line[1], line[0])) + + self.assertTupleEqual(clipped_line, expected_line) + + def test_clipline__endpoints_inside_and_outside(self): + """Ensures lines that overlap the rect are clipped. + + Testing lines with one endpoint outside the rect and the other is + inside the rect. + """ + rect = Rect((0, 0), (21, 21)) + # Use a bigger rect to help create test lines. + big_rect = rect.inflate(2, 2) + + # Create a dict of lines and expected results. + line_dict = { + (big_rect.midleft, rect.center): (rect.midleft, rect.center), + (big_rect.midtop, rect.center): (rect.midtop, rect.center), + (big_rect.midright, rect.center): ( + (rect.midright[0] - 1, rect.midright[1]), + rect.center, + ), + (big_rect.midbottom, rect.center): ( + (rect.midbottom[0], rect.midbottom[1] - 1), + rect.center, + ), + # Diagonals. + (big_rect.topleft, rect.center): (rect.topleft, rect.center), + (big_rect.topright, rect.center): ( + (rect.topright[0] - 1, rect.topright[1]), + rect.center, + ), + (big_rect.bottomright, rect.center): ( + (rect.bottomright[0] - 1, rect.bottomright[1] - 1), + rect.center, + ), + # This line needs a small adjustment to make sure it intersects + # the rect correctly. + ((big_rect.bottomleft[0], big_rect.bottomleft[1] - 1), rect.center): ( + (rect.bottomleft[0], rect.bottomleft[1] - 1), + rect.center, + ), + } + + for line, expected_line in line_dict.items(): + clipped_line = rect.clipline(line) + + self.assertTupleEqual(clipped_line, expected_line) + + # Swap endpoints to test for symmetry. + expected_line = (expected_line[1], expected_line[0]) + + clipped_line = rect.clipline((line[1], line[0])) + + self.assertTupleEqual(clipped_line, expected_line) + + def test_clipline__edges(self): + """Ensures clipline properly clips line that are along the rect edges.""" + rect = Rect((10, 25), (15, 20)) + + # Create a dict of edges and expected results. + edge_dict = { + # Left edge. + (rect.bottomleft, rect.topleft): ( + (rect.bottomleft[0], rect.bottomleft[1] - 1), + rect.topleft, + ), + # Top edge. + (rect.topleft, rect.topright): ( + rect.topleft, + (rect.topright[0] - 1, rect.topright[1]), + ), + # Right edge. + (rect.topright, rect.bottomright): (), + # Bottom edge. + (rect.bottomright, rect.bottomleft): (), + } + + for edge, expected_line in edge_dict.items(): + clipped_line = rect.clipline(edge) + + self.assertTupleEqual(clipped_line, expected_line) + + # Swap endpoints to test for symmetry. + if expected_line: + expected_line = (expected_line[1], expected_line[0]) + + clipped_line = rect.clipline((edge[1], edge[0])) + + self.assertTupleEqual(clipped_line, expected_line) + + def test_clipline__equal_endpoints_with_overlap(self): + """Ensures clipline handles lines with both endpoints the same. + + Testing lines that overlap the rect. + """ + rect = Rect((10, 25), (15, 20)) + + # Test all the points in and on a rect. + pts = ( + (x, y) + for x in range(rect.left, rect.right) + for y in range(rect.top, rect.bottom) + ) + + for pt in pts: + expected_line = (pt, pt) + + clipped_line = rect.clipline((pt, pt)) + + self.assertTupleEqual(clipped_line, expected_line) + + def test_clipline__equal_endpoints_no_overlap(self): + """Ensures clipline handles lines with both endpoints the same. + + Testing lines that do not overlap the rect. + """ + expected_line = () + rect = Rect((10, 25), (15, 20)) + + # Test points outside rect. + for pt in test_utils.rect_perimeter_pts(rect.inflate(2, 2)): + clipped_line = rect.clipline((pt, pt)) + + self.assertTupleEqual(clipped_line, expected_line) + + def test_clipline__zero_size_rect(self): + """Ensures clipline handles zero sized rects correctly.""" + expected_line = () + + for size in ((0, 15), (15, 0), (0, 0)): + rect = Rect((10, 25), size) + + clipped_line = rect.clipline(rect.topleft, rect.topleft) + + self.assertTupleEqual(clipped_line, expected_line) + + def test_clipline__negative_size_rect(self): + """Ensures clipline handles negative sized rects correctly.""" + expected_line = () + + for size in ((-15, 20), (15, -20), (-15, -20)): + rect = Rect((10, 25), size) + norm_rect = rect.copy() + norm_rect.normalize() + # Use a bigger rect to help create test lines. + big_rect = norm_rect.inflate(2, 2) + + # Create a dict of lines and expected results. Some line have both + # endpoints outside the rect and some have one inside and one + # outside. + line_dict = { + (big_rect.midleft, big_rect.midright): ( + norm_rect.midleft, + (norm_rect.midright[0] - 1, norm_rect.midright[1]), + ), + (big_rect.midtop, big_rect.midbottom): ( + norm_rect.midtop, + (norm_rect.midbottom[0], norm_rect.midbottom[1] - 1), + ), + (big_rect.midleft, norm_rect.center): ( + norm_rect.midleft, + norm_rect.center, + ), + (big_rect.midtop, norm_rect.center): ( + norm_rect.midtop, + norm_rect.center, + ), + (big_rect.midright, norm_rect.center): ( + (norm_rect.midright[0] - 1, norm_rect.midright[1]), + norm_rect.center, + ), + (big_rect.midbottom, norm_rect.center): ( + (norm_rect.midbottom[0], norm_rect.midbottom[1] - 1), + norm_rect.center, + ), + } + + for line, expected_line in line_dict.items(): + clipped_line = rect.clipline(line) + + # Make sure rect wasn't normalized. + self.assertNotEqual(rect, norm_rect) + self.assertTupleEqual(clipped_line, expected_line) + + # Swap endpoints to test for symmetry. + expected_line = (expected_line[1], expected_line[0]) + + clipped_line = rect.clipline((line[1], line[0])) + + self.assertTupleEqual(clipped_line, expected_line) + + def test_clipline__invalid_line(self): + """Ensures clipline handles invalid lines correctly.""" + rect = Rect((0, 0), (10, 20)) + invalid_lines = ( + (), + (1,), + (1, 2), + (1, 2, 3), + (1, 2, 3, 4, 5), + ((1, 2),), + ((1, 2), (3,)), + ((1, 2), 3), + ((1, 2, 5), (3, 4)), + ((1, 2), (3, 4, 5)), + ((1, 2), (3, 4), (5, 6)), + ) + + for line in invalid_lines: + with self.assertRaises(TypeError): + clipped_line = rect.clipline(line) + + with self.assertRaises(TypeError): + clipped_line = rect.clipline(*line) + + @unittest.skipIf(IS_PYPY, "fails on pypy sometimes") + def test_move(self): + r = Rect(1, 2, 3, 4) + move_x = 10 + move_y = 20 + r2 = r.move(move_x, move_y) + expected_r2 = Rect(r.left + move_x, r.top + move_y, r.width, r.height) + self.assertEqual(expected_r2, r2) + + @unittest.skipIf(IS_PYPY, "fails on pypy sometimes") + def test_move_ip(self): + r = Rect(1, 2, 3, 4) + r2 = Rect(r) + move_x = 10 + move_y = 20 + r2.move_ip(move_x, move_y) + expected_r2 = Rect(r.left + move_x, r.top + move_y, r.width, r.height) + self.assertEqual(expected_r2, r2) + + def test_update_XYWidthHeight(self): + """Test update with 4 int values(x, y, w, h)""" + rect = Rect(0, 0, 1, 1) + rect.update(1, 2, 3, 4) + + self.assertEqual(1, rect.left) + self.assertEqual(2, rect.top) + self.assertEqual(3, rect.width) + self.assertEqual(4, rect.height) + + def test_update__TopLeftSize(self): + """Test update with 2 tuples((x, y), (w, h))""" + rect = Rect(0, 0, 1, 1) + rect.update((1, 2), (3, 4)) + + self.assertEqual(1, rect.left) + self.assertEqual(2, rect.top) + self.assertEqual(3, rect.width) + self.assertEqual(4, rect.height) + + def test_update__List(self): + """Test update with list""" + rect = Rect(0, 0, 1, 1) + rect2 = [1, 2, 3, 4] + rect.update(rect2) + + self.assertEqual(1, rect.left) + self.assertEqual(2, rect.top) + self.assertEqual(3, rect.width) + self.assertEqual(4, rect.height) + + def test_update__RectObject(self): + """Test update with other rect object""" + rect = Rect(0, 0, 1, 1) + rect2 = Rect(1, 2, 3, 4) + rect.update(rect2) + + self.assertEqual(1, rect.left) + self.assertEqual(2, rect.top) + self.assertEqual(3, rect.width) + self.assertEqual(4, rect.height) + + def test_union(self): + r1 = Rect(1, 1, 1, 2) + r2 = Rect(-2, -2, 1, 2) + self.assertEqual(Rect(-2, -2, 4, 5), r1.union(r2)) + + def test_union__with_identical_Rect(self): + r1 = Rect(1, 2, 3, 4) + self.assertEqual(r1, r1.union(Rect(r1))) + + def test_union_ip(self): + r1 = Rect(1, 1, 1, 2) + r2 = Rect(-2, -2, 1, 2) + r1.union_ip(r2) + self.assertEqual(Rect(-2, -2, 4, 5), r1) + + def test_unionall(self): + r1 = Rect(0, 0, 1, 1) + r2 = Rect(-2, -2, 1, 1) + r3 = Rect(2, 2, 1, 1) + + r4 = r1.unionall([r2, r3]) + self.assertEqual(Rect(-2, -2, 5, 5), r4) + + def test_unionall__invalid_rect_format(self): + """Ensures unionall correctly handles invalid rect parameters.""" + numbers = [0, 1.2, 2, 3.3] + strs = ["a", "b", "c"] + nones = [None, None] + + for invalid_rects in (numbers, strs, nones): + with self.assertRaises(TypeError): + Rect(0, 0, 1, 1).unionall(invalid_rects) + + def test_unionall_ip(self): + r1 = Rect(0, 0, 1, 1) + r2 = Rect(-2, -2, 1, 1) + r3 = Rect(2, 2, 1, 1) + + r1.unionall_ip([r2, r3]) + self.assertEqual(Rect(-2, -2, 5, 5), r1) + + # Bug for an empty list. Would return a Rect instead of None. + self.assertTrue(r1.unionall_ip([]) is None) + + def test_unionall__invalid_rect_format(self): + """Ensures unionall_ip correctly handles invalid rect parameters.""" + numbers = [0, 1.2, 2, 3.3] + strs = ["a", "b", "c"] + nones = [None, None] + + for invalid_rects in (numbers, strs, nones): + with self.assertRaises(TypeError): + Rect(0, 0, 1, 1).unionall_ip(invalid_rects) + + def test_colliderect(self): + r1 = Rect(1, 2, 3, 4) + self.assertTrue( + r1.colliderect(Rect(0, 0, 2, 3)), + "r1 does not collide with Rect(0, 0, 2, 3)", + ) + self.assertFalse( + r1.colliderect(Rect(0, 0, 1, 2)), "r1 collides with Rect(0, 0, 1, 2)" + ) + self.assertFalse( + r1.colliderect(Rect(r1.right, r1.bottom, 2, 2)), + "r1 collides with Rect(r1.right, r1.bottom, 2, 2)", + ) + self.assertTrue( + r1.colliderect(Rect(r1.left + 1, r1.top + 1, r1.width - 2, r1.height - 2)), + "r1 does not collide with Rect(r1.left + 1, r1.top + 1, " + + "r1.width - 2, r1.height - 2)", + ) + self.assertTrue( + r1.colliderect(Rect(r1.left - 1, r1.top - 1, r1.width + 2, r1.height + 2)), + "r1 does not collide with Rect(r1.left - 1, r1.top - 1, " + + "r1.width + 2, r1.height + 2)", + ) + self.assertTrue( + r1.colliderect(Rect(r1)), "r1 does not collide with an identical rect" + ) + self.assertFalse( + r1.colliderect(Rect(r1.right, r1.bottom, 0, 0)), + "r1 collides with Rect(r1.right, r1.bottom, 0, 0)", + ) + self.assertFalse( + r1.colliderect(Rect(r1.right, r1.bottom, 1, 1)), + "r1 collides with Rect(r1.right, r1.bottom, 1, 1)", + ) + + @unittest.skipIf(IS_PYPY, "fails on pypy3 sometimes") + def testEquals(self): + """check to see how the rect uses __eq__""" + r1 = Rect(1, 2, 3, 4) + r2 = Rect(10, 20, 30, 40) + r3 = (10, 20, 30, 40) + r4 = Rect(10, 20, 30, 40) + + class foo(Rect): + def __eq__(self, other): + return id(self) == id(other) + + def __ne__(self, other): + return id(self) != id(other) + + class foo2(Rect): + pass + + r5 = foo(10, 20, 30, 40) + r6 = foo2(10, 20, 30, 40) + + self.assertNotEqual(r5, r2) + + # because we define equality differently for this subclass. + self.assertEqual(r6, r2) + + rect_list = [r1, r2, r3, r4, r6] + + # see if we can remove 4 of these. + rect_list.remove(r2) + rect_list.remove(r2) + rect_list.remove(r2) + rect_list.remove(r2) + self.assertRaises(ValueError, rect_list.remove, r2) + + def test_collidedict(self): + """Ensures collidedict detects collisions.""" + rect = Rect(1, 1, 10, 10) + + collide_item1 = ("collide 1", rect.copy()) + collide_item2 = ("collide 2", Rect(5, 5, 10, 10)) + no_collide_item1 = ("no collide 1", Rect(60, 60, 10, 10)) + no_collide_item2 = ("no collide 2", Rect(70, 70, 10, 10)) + + # Dict to check collisions with values. + rect_values = dict( + (collide_item1, collide_item2, no_collide_item1, no_collide_item2) + ) + value_collide_items = (collide_item1, collide_item2) + + # Dict to check collisions with keys. + rect_keys = {tuple(v): k for k, v in rect_values.items()} + key_collide_items = tuple((tuple(v), k) for k, v in value_collide_items) + + for use_values in (True, False): + if use_values: + expected_items = value_collide_items + d = rect_values + else: + expected_items = key_collide_items + d = rect_keys + + collide_item = rect.collidedict(d, use_values) + + # The detected collision could be any of the possible items. + self.assertIn(collide_item, expected_items) + + def test_collidedict__no_collision(self): + """Ensures collidedict returns None when no collisions.""" + rect = Rect(1, 1, 10, 10) + + no_collide_item1 = ("no collide 1", Rect(50, 50, 10, 10)) + no_collide_item2 = ("no collide 2", Rect(60, 60, 10, 10)) + no_collide_item3 = ("no collide 3", Rect(70, 70, 10, 10)) + + # Dict to check collisions with values. + rect_values = dict((no_collide_item1, no_collide_item2, no_collide_item3)) + + # Dict to check collisions with keys. + rect_keys = {tuple(v): k for k, v in rect_values.items()} + + for use_values in (True, False): + d = rect_values if use_values else rect_keys + + collide_item = rect.collidedict(d, use_values) + + self.assertIsNone(collide_item) + + def test_collidedict__barely_touching(self): + """Ensures collidedict works correctly for rects that barely touch.""" + rect = Rect(1, 1, 10, 10) + # Small rect to test barely touching collisions. + collide_rect = Rect(0, 0, 1, 1) + + collide_item1 = ("collide 1", collide_rect) + no_collide_item1 = ("no collide 1", Rect(50, 50, 10, 10)) + no_collide_item2 = ("no collide 2", Rect(60, 60, 10, 10)) + no_collide_item3 = ("no collide 3", Rect(70, 70, 10, 10)) + + # Dict to check collisions with values. + no_collide_rect_values = dict( + (no_collide_item1, no_collide_item2, no_collide_item3) + ) + + # Dict to check collisions with keys. + no_collide_rect_keys = {tuple(v): k for k, v in no_collide_rect_values.items()} + + # Tests the collide_rect on each of the rect's corners. + for attr in ("topleft", "topright", "bottomright", "bottomleft"): + setattr(collide_rect, attr, getattr(rect, attr)) + + for use_values in (True, False): + if use_values: + expected_item = collide_item1 + d = dict(no_collide_rect_values) + else: + expected_item = (tuple(collide_item1[1]), collide_item1[0]) + d = dict(no_collide_rect_keys) + + d.update((expected_item,)) # Add in the expected item. + + collide_item = rect.collidedict(d, use_values) + + self.assertTupleEqual(collide_item, expected_item) + + def test_collidedict__zero_sized_rects(self): + """Ensures collidedict works correctly with zero sized rects. + + There should be no collisions with zero sized rects. + """ + zero_rect1 = Rect(1, 1, 0, 0) + zero_rect2 = Rect(1, 1, 1, 0) + zero_rect3 = Rect(1, 1, 0, 1) + zero_rect4 = Rect(1, 1, -1, 0) + zero_rect5 = Rect(1, 1, 0, -1) + + no_collide_item1 = ("no collide 1", zero_rect1.copy()) + no_collide_item2 = ("no collide 2", zero_rect2.copy()) + no_collide_item3 = ("no collide 3", zero_rect3.copy()) + no_collide_item4 = ("no collide 4", zero_rect4.copy()) + no_collide_item5 = ("no collide 5", zero_rect5.copy()) + no_collide_item6 = ("no collide 6", Rect(0, 0, 10, 10)) + no_collide_item7 = ("no collide 7", Rect(0, 0, 2, 2)) + + # Dict to check collisions with values. + rect_values = dict( + ( + no_collide_item1, + no_collide_item2, + no_collide_item3, + no_collide_item4, + no_collide_item5, + no_collide_item6, + no_collide_item7, + ) + ) + + # Dict to check collisions with keys. + rect_keys = {tuple(v): k for k, v in rect_values.items()} + + for use_values in (True, False): + d = rect_values if use_values else rect_keys + + for zero_rect in ( + zero_rect1, + zero_rect2, + zero_rect3, + zero_rect4, + zero_rect5, + ): + collide_item = zero_rect.collidedict(d, use_values) + + self.assertIsNone(collide_item) + + def test_collidedict__zero_sized_rects_as_args(self): + """Ensures collidedict works correctly with zero sized rects as args. + + There should be no collisions with zero sized rects. + """ + rect = Rect(0, 0, 10, 10) + + no_collide_item1 = ("no collide 1", Rect(1, 1, 0, 0)) + no_collide_item2 = ("no collide 2", Rect(1, 1, 1, 0)) + no_collide_item3 = ("no collide 3", Rect(1, 1, 0, 1)) + + # Dict to check collisions with values. + rect_values = dict((no_collide_item1, no_collide_item2, no_collide_item3)) + + # Dict to check collisions with keys. + rect_keys = {tuple(v): k for k, v in rect_values.items()} + + for use_values in (True, False): + d = rect_values if use_values else rect_keys + + collide_item = rect.collidedict(d, use_values) + + self.assertIsNone(collide_item) + + def test_collidedict__negative_sized_rects(self): + """Ensures collidedict works correctly with negative sized rects.""" + neg_rect = Rect(1, 1, -1, -1) + + collide_item1 = ("collide 1", neg_rect.copy()) + collide_item2 = ("collide 2", Rect(0, 0, 10, 10)) + no_collide_item1 = ("no collide 1", Rect(1, 1, 10, 10)) + + # Dict to check collisions with values. + rect_values = dict((collide_item1, collide_item2, no_collide_item1)) + value_collide_items = (collide_item1, collide_item2) + + # Dict to check collisions with keys. + rect_keys = {tuple(v): k for k, v in rect_values.items()} + key_collide_items = tuple((tuple(v), k) for k, v in value_collide_items) + + for use_values in (True, False): + if use_values: + collide_items = value_collide_items + d = rect_values + else: + collide_items = key_collide_items + d = rect_keys + + collide_item = neg_rect.collidedict(d, use_values) + + # The detected collision could be any of the possible items. + self.assertIn(collide_item, collide_items) + + def test_collidedict__negative_sized_rects_as_args(self): + """Ensures collidedict works correctly with negative sized rect args.""" + rect = Rect(0, 0, 10, 10) + + collide_item1 = ("collide 1", Rect(1, 1, -1, -1)) + no_collide_item1 = ("no collide 1", Rect(1, 1, -1, 0)) + no_collide_item2 = ("no collide 2", Rect(1, 1, 0, -1)) + + # Dict to check collisions with values. + rect_values = dict((collide_item1, no_collide_item1, no_collide_item2)) + + # Dict to check collisions with keys. + rect_keys = {tuple(v): k for k, v in rect_values.items()} + + for use_values in (True, False): + if use_values: + expected_item = collide_item1 + d = rect_values + else: + expected_item = (tuple(collide_item1[1]), collide_item1[0]) + d = rect_keys + + collide_item = rect.collidedict(d, use_values) + + self.assertTupleEqual(collide_item, expected_item) + + def test_collidedict__invalid_dict_format(self): + """Ensures collidedict correctly handles invalid dict parameters.""" + rect = Rect(0, 0, 10, 10) + + invalid_value_dict = ("collide", rect.copy()) + invalid_key_dict = tuple(invalid_value_dict[1]), invalid_value_dict[0] + + for use_values in (True, False): + d = invalid_value_dict if use_values else invalid_key_dict + + with self.assertRaises(TypeError): + collide_item = rect.collidedict(d, use_values) + + def test_collidedict__invalid_dict_value_format(self): + """Ensures collidedict correctly handles dicts with invalid values.""" + rect = Rect(0, 0, 10, 10) + rect_keys = {tuple(rect): "collide"} + + with self.assertRaises(TypeError): + collide_item = rect.collidedict(rect_keys, 1) + + def test_collidedict__invalid_dict_key_format(self): + """Ensures collidedict correctly handles dicts with invalid keys.""" + rect = Rect(0, 0, 10, 10) + rect_values = {"collide": rect.copy()} + + with self.assertRaises(TypeError): + collide_item = rect.collidedict(rect_values) + + def test_collidedict__invalid_use_values_format(self): + """Ensures collidedict correctly handles invalid use_values parameters.""" + rect = Rect(0, 0, 1, 1) + d = {} + + for invalid_param in (None, d, 1.1): + with self.assertRaises(TypeError): + collide_item = rect.collidedict(d, invalid_param) + + def test_collidedictall(self): + """Ensures collidedictall detects collisions.""" + rect = Rect(1, 1, 10, 10) + + collide_item1 = ("collide 1", rect.copy()) + collide_item2 = ("collide 2", Rect(5, 5, 10, 10)) + no_collide_item1 = ("no collide 1", Rect(60, 60, 20, 20)) + no_collide_item2 = ("no collide 2", Rect(70, 70, 20, 20)) + + # Dict to check collisions with values. + rect_values = dict( + (collide_item1, collide_item2, no_collide_item1, no_collide_item2) + ) + value_collide_items = [collide_item1, collide_item2] + + # Dict to check collisions with keys. + rect_keys = {tuple(v): k for k, v in rect_values.items()} + key_collide_items = [(tuple(v), k) for k, v in value_collide_items] + + for use_values in (True, False): + if use_values: + expected_items = value_collide_items + d = rect_values + else: + expected_items = key_collide_items + d = rect_keys + + collide_items = rect.collidedictall(d, use_values) + + self._assertCountEqual(collide_items, expected_items) + + def test_collidedictall__no_collision(self): + """Ensures collidedictall returns an empty list when no collisions.""" + rect = Rect(1, 1, 10, 10) + + no_collide_item1 = ("no collide 1", Rect(50, 50, 20, 20)) + no_collide_item2 = ("no collide 2", Rect(60, 60, 20, 20)) + no_collide_item3 = ("no collide 3", Rect(70, 70, 20, 20)) + + # Dict to check collisions with values. + rect_values = dict((no_collide_item1, no_collide_item2, no_collide_item3)) + + # Dict to check collisions with keys. + rect_keys = {tuple(v): k for k, v in rect_values.items()} + + expected_items = [] + + for use_values in (True, False): + d = rect_values if use_values else rect_keys + + collide_items = rect.collidedictall(d, use_values) + + self._assertCountEqual(collide_items, expected_items) + + def test_collidedictall__barely_touching(self): + """Ensures collidedictall works correctly for rects that barely touch.""" + rect = Rect(1, 1, 10, 10) + # Small rect to test barely touching collisions. + collide_rect = Rect(0, 0, 1, 1) + + collide_item1 = ("collide 1", collide_rect) + no_collide_item1 = ("no collide 1", Rect(50, 50, 20, 20)) + no_collide_item2 = ("no collide 2", Rect(60, 60, 20, 20)) + no_collide_item3 = ("no collide 3", Rect(70, 70, 20, 20)) + + # Dict to check collisions with values. + no_collide_rect_values = dict( + (no_collide_item1, no_collide_item2, no_collide_item3) + ) + + # Dict to check collisions with keys. + no_collide_rect_keys = {tuple(v): k for k, v in no_collide_rect_values.items()} + + # Tests the collide_rect on each of the rect's corners. + for attr in ("topleft", "topright", "bottomright", "bottomleft"): + setattr(collide_rect, attr, getattr(rect, attr)) + + for use_values in (True, False): + if use_values: + expected_items = [collide_item1] + d = dict(no_collide_rect_values) + else: + expected_items = [(tuple(collide_item1[1]), collide_item1[0])] + d = dict(no_collide_rect_keys) + + d.update(expected_items) # Add in the expected items. + + collide_items = rect.collidedictall(d, use_values) + + self._assertCountEqual(collide_items, expected_items) + + def test_collidedictall__zero_sized_rects(self): + """Ensures collidedictall works correctly with zero sized rects. + + There should be no collisions with zero sized rects. + """ + zero_rect1 = Rect(2, 2, 0, 0) + zero_rect2 = Rect(2, 2, 2, 0) + zero_rect3 = Rect(2, 2, 0, 2) + zero_rect4 = Rect(2, 2, -2, 0) + zero_rect5 = Rect(2, 2, 0, -2) + + no_collide_item1 = ("no collide 1", zero_rect1.copy()) + no_collide_item2 = ("no collide 2", zero_rect2.copy()) + no_collide_item3 = ("no collide 3", zero_rect3.copy()) + no_collide_item4 = ("no collide 4", zero_rect4.copy()) + no_collide_item5 = ("no collide 5", zero_rect5.copy()) + no_collide_item6 = ("no collide 6", Rect(0, 0, 10, 10)) + no_collide_item7 = ("no collide 7", Rect(0, 0, 2, 2)) + + # Dict to check collisions with values. + rect_values = dict( + ( + no_collide_item1, + no_collide_item2, + no_collide_item3, + no_collide_item4, + no_collide_item5, + no_collide_item6, + no_collide_item7, + ) + ) + + # Dict to check collisions with keys. + rect_keys = {tuple(v): k for k, v in rect_values.items()} + + expected_items = [] + + for use_values in (True, False): + d = rect_values if use_values else rect_keys + + for zero_rect in ( + zero_rect1, + zero_rect2, + zero_rect3, + zero_rect4, + zero_rect5, + ): + collide_items = zero_rect.collidedictall(d, use_values) + + self._assertCountEqual(collide_items, expected_items) + + def test_collidedictall__zero_sized_rects_as_args(self): + """Ensures collidedictall works correctly with zero sized rects + as args. + + There should be no collisions with zero sized rects. + """ + rect = Rect(0, 0, 20, 20) + + no_collide_item1 = ("no collide 1", Rect(2, 2, 0, 0)) + no_collide_item2 = ("no collide 2", Rect(2, 2, 2, 0)) + no_collide_item3 = ("no collide 3", Rect(2, 2, 0, 2)) + + # Dict to check collisions with values. + rect_values = dict((no_collide_item1, no_collide_item2, no_collide_item3)) + + # Dict to check collisions with keys. + rect_keys = {tuple(v): k for k, v in rect_values.items()} + + expected_items = [] + + for use_values in (True, False): + d = rect_values if use_values else rect_keys + + collide_items = rect.collidedictall(d, use_values) + + self._assertCountEqual(collide_items, expected_items) + + def test_collidedictall__negative_sized_rects(self): + """Ensures collidedictall works correctly with negative sized rects.""" + neg_rect = Rect(2, 2, -2, -2) + + collide_item1 = ("collide 1", neg_rect.copy()) + collide_item2 = ("collide 2", Rect(0, 0, 20, 20)) + no_collide_item1 = ("no collide 1", Rect(2, 2, 20, 20)) + + # Dict to check collisions with values. + rect_values = dict((collide_item1, collide_item2, no_collide_item1)) + value_collide_items = [collide_item1, collide_item2] + + # Dict to check collisions with keys. + rect_keys = {tuple(v): k for k, v in rect_values.items()} + key_collide_items = [(tuple(v), k) for k, v in value_collide_items] + + for use_values in (True, False): + if use_values: + expected_items = value_collide_items + d = rect_values + else: + expected_items = key_collide_items + d = rect_keys + + collide_items = neg_rect.collidedictall(d, use_values) + + self._assertCountEqual(collide_items, expected_items) + + def test_collidedictall__negative_sized_rects_as_args(self): + """Ensures collidedictall works correctly with negative sized rect + args. + """ + rect = Rect(0, 0, 10, 10) + + collide_item1 = ("collide 1", Rect(1, 1, -1, -1)) + no_collide_item1 = ("no collide 1", Rect(1, 1, -1, 0)) + no_collide_item2 = ("no collide 2", Rect(1, 1, 0, -1)) + + # Dict to check collisions with values. + rect_values = dict((collide_item1, no_collide_item1, no_collide_item2)) + value_collide_items = [collide_item1] + + # Dict to check collisions with keys. + rect_keys = {tuple(v): k for k, v in rect_values.items()} + key_collide_items = [(tuple(v), k) for k, v in value_collide_items] + + for use_values in (True, False): + if use_values: + expected_items = value_collide_items + d = rect_values + else: + expected_items = key_collide_items + d = rect_keys + + collide_items = rect.collidedictall(d, use_values) + + self._assertCountEqual(collide_items, expected_items) + + def test_collidedictall__invalid_dict_format(self): + """Ensures collidedictall correctly handles invalid dict parameters.""" + rect = Rect(0, 0, 10, 10) + + invalid_value_dict = ("collide", rect.copy()) + invalid_key_dict = tuple(invalid_value_dict[1]), invalid_value_dict[0] + + for use_values in (True, False): + d = invalid_value_dict if use_values else invalid_key_dict + + with self.assertRaises(TypeError): + collide_item = rect.collidedictall(d, use_values) + + def test_collidedictall__invalid_dict_value_format(self): + """Ensures collidedictall correctly handles dicts with invalid values.""" + rect = Rect(0, 0, 10, 10) + rect_keys = {tuple(rect): "collide"} + + with self.assertRaises(TypeError): + collide_items = rect.collidedictall(rect_keys, 1) + + def test_collidedictall__invalid_dict_key_format(self): + """Ensures collidedictall correctly handles dicts with invalid keys.""" + rect = Rect(0, 0, 10, 10) + rect_values = {"collide": rect.copy()} + + with self.assertRaises(TypeError): + collide_items = rect.collidedictall(rect_values) + + def test_collidedictall__invalid_use_values_format(self): + """Ensures collidedictall correctly handles invalid use_values + parameters. + """ + rect = Rect(0, 0, 1, 1) + d = {} + + for invalid_param in (None, d, 1.1): + with self.assertRaises(TypeError): + collide_items = rect.collidedictall(d, invalid_param) + + def test_collidelist(self): + + # __doc__ (as of 2008-08-02) for pygame.rect.Rect.collidelist: + + # Rect.collidelist(list): return index + # test if one rectangle in a list intersects + # + # Test whether the rectangle collides with any in a sequence of + # rectangles. The index of the first collision found is returned. If + # no collisions are found an index of -1 is returned. + + r = Rect(1, 1, 10, 10) + l = [Rect(50, 50, 1, 1), Rect(5, 5, 10, 10), Rect(15, 15, 1, 1)] + + self.assertEqual(r.collidelist(l), 1) + + f = [Rect(50, 50, 1, 1), (100, 100, 4, 4)] + self.assertEqual(r.collidelist(f), -1) + + def test_collidelistall(self): + + # __doc__ (as of 2008-08-02) for pygame.rect.Rect.collidelistall: + + # Rect.collidelistall(list): return indices + # test if all rectangles in a list intersect + # + # Returns a list of all the indices that contain rectangles that + # collide with the Rect. If no intersecting rectangles are found, an + # empty list is returned. + + r = Rect(1, 1, 10, 10) + + l = [ + Rect(1, 1, 10, 10), + Rect(5, 5, 10, 10), + Rect(15, 15, 1, 1), + Rect(2, 2, 1, 1), + ] + self.assertEqual(r.collidelistall(l), [0, 1, 3]) + + f = [Rect(50, 50, 1, 1), Rect(20, 20, 5, 5)] + self.assertFalse(r.collidelistall(f)) + + def test_fit(self): + + # __doc__ (as of 2008-08-02) for pygame.rect.Rect.fit: + + # Rect.fit(Rect): return Rect + # resize and move a rectangle with aspect ratio + # + # Returns a new rectangle that is moved and resized to fit another. + # The aspect ratio of the original Rect is preserved, so the new + # rectangle may be smaller than the target in either width or height. + + r = Rect(10, 10, 30, 30) + + r2 = Rect(30, 30, 15, 10) + + f = r.fit(r2) + self.assertTrue(r2.contains(f)) + + f2 = r2.fit(r) + self.assertTrue(r.contains(f2)) + + def test_copy(self): + r = Rect(1, 2, 10, 20) + c = r.copy() + self.assertEqual(c, r) + + def test_subscript(self): + r = Rect(1, 2, 3, 4) + self.assertEqual(r[0], 1) + self.assertEqual(r[1], 2) + self.assertEqual(r[2], 3) + self.assertEqual(r[3], 4) + self.assertEqual(r[-1], 4) + self.assertEqual(r[-2], 3) + self.assertEqual(r[-4], 1) + self.assertRaises(IndexError, r.__getitem__, 5) + self.assertRaises(IndexError, r.__getitem__, -5) + self.assertEqual(r[0:2], [1, 2]) + self.assertEqual(r[0:4], [1, 2, 3, 4]) + self.assertEqual(r[0:-1], [1, 2, 3]) + self.assertEqual(r[:], [1, 2, 3, 4]) + self.assertEqual(r[...], [1, 2, 3, 4]) + self.assertEqual(r[0:4:2], [1, 3]) + self.assertEqual(r[0:4:3], [1, 4]) + self.assertEqual(r[3::-1], [4, 3, 2, 1]) + self.assertRaises(TypeError, r.__getitem__, None) + + def test_ass_subscript(self): + r = Rect(0, 0, 0, 0) + r[...] = 1, 2, 3, 4 + self.assertEqual(r, [1, 2, 3, 4]) + self.assertRaises(TypeError, r.__setitem__, None, 0) + self.assertEqual(r, [1, 2, 3, 4]) + self.assertRaises(TypeError, r.__setitem__, 0, "") + self.assertEqual(r, [1, 2, 3, 4]) + self.assertRaises(IndexError, r.__setitem__, 4, 0) + self.assertEqual(r, [1, 2, 3, 4]) + self.assertRaises(IndexError, r.__setitem__, -5, 0) + self.assertEqual(r, [1, 2, 3, 4]) + r[0] = 10 + self.assertEqual(r, [10, 2, 3, 4]) + r[3] = 40 + self.assertEqual(r, [10, 2, 3, 40]) + r[-1] = 400 + self.assertEqual(r, [10, 2, 3, 400]) + r[-4] = 100 + self.assertEqual(r, [100, 2, 3, 400]) + r[1:3] = 0 + self.assertEqual(r, [100, 0, 0, 400]) + r[...] = 0 + self.assertEqual(r, [0, 0, 0, 0]) + r[:] = 9 + self.assertEqual(r, [9, 9, 9, 9]) + r[:] = 11, 12, 13, 14 + self.assertEqual(r, [11, 12, 13, 14]) + r[::-1] = r + self.assertEqual(r, [14, 13, 12, 11]) + + +@unittest.skipIf(IS_PYPY, "fails on pypy") +class SubclassTest(unittest.TestCase): + class MyRect(Rect): + def __init__(self, *args, **kwds): + super(SubclassTest.MyRect, self).__init__(*args, **kwds) + self.an_attribute = True + + def test_copy(self): + mr1 = self.MyRect(1, 2, 10, 20) + self.assertTrue(mr1.an_attribute) + mr2 = mr1.copy() + self.assertTrue(isinstance(mr2, self.MyRect)) + self.assertRaises(AttributeError, getattr, mr2, "an_attribute") + + def test_move(self): + mr1 = self.MyRect(1, 2, 10, 20) + self.assertTrue(mr1.an_attribute) + mr2 = mr1.move(1, 2) + self.assertTrue(isinstance(mr2, self.MyRect)) + self.assertRaises(AttributeError, getattr, mr2, "an_attribute") + + def test_inflate(self): + mr1 = self.MyRect(1, 2, 10, 20) + self.assertTrue(mr1.an_attribute) + mr2 = mr1.inflate(2, 4) + self.assertTrue(isinstance(mr2, self.MyRect)) + self.assertRaises(AttributeError, getattr, mr2, "an_attribute") + + def test_clamp(self): + mr1 = self.MyRect(19, 12, 5, 5) + self.assertTrue(mr1.an_attribute) + mr2 = mr1.clamp(Rect(10, 10, 10, 10)) + self.assertTrue(isinstance(mr2, self.MyRect)) + self.assertRaises(AttributeError, getattr, mr2, "an_attribute") + + def test_clip(self): + mr1 = self.MyRect(1, 2, 3, 4) + self.assertTrue(mr1.an_attribute) + mr2 = mr1.clip(Rect(0, 0, 3, 4)) + self.assertTrue(isinstance(mr2, self.MyRect)) + self.assertRaises(AttributeError, getattr, mr2, "an_attribute") + + def test_union(self): + mr1 = self.MyRect(1, 1, 1, 2) + self.assertTrue(mr1.an_attribute) + mr2 = mr1.union(Rect(-2, -2, 1, 2)) + self.assertTrue(isinstance(mr2, self.MyRect)) + self.assertRaises(AttributeError, getattr, mr2, "an_attribute") + + def test_unionall(self): + mr1 = self.MyRect(0, 0, 1, 1) + self.assertTrue(mr1.an_attribute) + mr2 = mr1.unionall([Rect(-2, -2, 1, 1), Rect(2, 2, 1, 1)]) + self.assertTrue(isinstance(mr2, self.MyRect)) + self.assertRaises(AttributeError, getattr, mr2, "an_attribute") + + def test_fit(self): + mr1 = self.MyRect(10, 10, 30, 30) + self.assertTrue(mr1.an_attribute) + mr2 = mr1.fit(Rect(30, 30, 15, 10)) + self.assertTrue(isinstance(mr2, self.MyRect)) + self.assertRaises(AttributeError, getattr, mr2, "an_attribute") + + +if __name__ == "__main__": + unittest.main() diff --git a/venv/Lib/site-packages/pygame/tests/run_tests__tests/__init__.py b/venv/Lib/site-packages/pygame/tests/run_tests__tests/__init__.py new file mode 100644 index 0000000..1bb8bf6 --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/run_tests__tests/__init__.py @@ -0,0 +1 @@ +# empty diff --git a/venv/Lib/site-packages/pygame/tests/run_tests__tests/__pycache__/__init__.cpython-39.pyc b/venv/Lib/site-packages/pygame/tests/run_tests__tests/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..824cc7b93a8d4c23a7e5d964118a2b6cd9a2e0ac GIT binary patch literal 211 zcmYjLI|{-;5Z!=95ON1A!9vrEh@y=kHexq0Y|J2Q%0i&xZlEGv!CEE2%F)oueI^gYV4H)?DR#t;b(2Fga?Kwl)anhn!r8G0=%nZ+*IX~Z_ zJ3ek{@chfZRr|-Jru`k6vriV7UqX`)sHQQE5npqXkvK&0)S+tB9bJuvV=(HZnC_&R z!BTHDC&O;BG|Rjpj>$|;_r|)KW3jP>YVUB%$ucY9WWcfsC0=tn$g$jz5RH?)@xg@Z z&*3W5X0;(1!uhkBGpXj!tA2`4vhg7u66XS&VCUYzn}caSIV7vvF>x-kNp>FenPF4x z0*sf~G`k4nWso_`X4s{s?p)zl*kv}`q?a`3D$uh{0@O8rrKzzi-yuE6G-sY&b*}S^ ztJ=%&9h;l{Dz|YTzi>>Q8^B*X!!Phpc!uBL3k`ZqE7ZB^Eb^OtabE`s*WVJ+;I|m; zZ;%<#k!ZmTpJ#KwfHPoz{{1|k;WkP+*1;axw?zI)y*&lHuH$5Dw>P7{& zzzbdNEtTnCY2T7F`h7Aw`6i#|MSk&^u(?ZGgC;itjTUj8k+PP*{R2kTdY<--qU;9o zxED0Mz>9d*55snz!ovKP8`w(~b~kTFTt?FN61GyrIoX@R^~%co#hv2L&W?mPFF*Et zZZ8z?e7*GB-z`@v#g}(0#r9!-p*NPSR8|)11Qi%PI*e&(kD$r>&_x>f@=k>wks}(B zK4IjT3cFAG;FBZml@ZZ_4jk=kLmm0P26v*p`#~sLuJ84@&Adi~3m(+Dyl2Z!eb;uS z9eFJ;XxcR%9dI7lVJB*LqS&lf>#pxtt9c{Nu5WBTfB0<8DQ%VG%&sflC=xLhJl18W zme=F7;IiXKj&*vJh_iyXeYehAJc$0R3C!RhfB)z~<%Q%zR@@+PWo4Di{U~f#+9KTJ z`_W-lMjht4m4|E9gRsZ6qpB5e;04n2hi z=4OP^KctRmpAL+nCccRPRQg)Nodj8w?$f=@z#M|3z6A#*G&sjt-v;xhWyHYhYUD!1 zdi{XKQ=P!;f~8!)8t?<(3%Km17Nxx?^JB3EW(S*r8)cl@4BI@2jm@>qQk*VtuWr29 zj*SD?i{eyUctI48m0s6*JMzLnjKd9LLvWXY*YtXe#k9_117#@>B^}~vJf_@_D_4P) zGtg}xVZIVy}Dg0ZHvZP?)2t12IC#{I~J1ZaAJv=6)p z(!!1o!h+AEhzq+OGXB7_YyaMOzRsX%iTi!bJIF39K9P=Dcv7wy0->?q%PdL-4NhhR zZoLbx1USOfkQh;rUmH&$BQs4uthv67^(K!*3XT;R|FDvh9Y7#RRe(&N3xtN)K-Bs8 zlIIi2)i4;rjeG)oCE8yjlYlolBJKkHfrs$s*wofrK=k3G;N`U=3iqX5O-^HJV}Lb4 z8%V!0)ZO&;UJeV-&wic+dQ3N-Duwd8Ve^#Fh$V9A3P{74Ipya7}cllx)?MPpVx?p+1fE7wA{x7x1oB!okvt@Q&| z<=)JH+p+Pqw~R&A_iDuiOqTM+L;_z*Vgw8A2&*~EKd@r0SN!0+Vs!4(drY@mfH+u} zIh2LG-MchGx<<$M55Z0X3bq?@ChnnPQ`VwfK2c8EZ3w(x&MNHMjZoN#!+ElvUl!-_ zvUAWu(LR&{lP=DTbQcS_hy z?L)Q6xHXBeAa3BKiQubP8(3#70(a~yc*tP(15P;SFmI~L>bM|PKB#yT=)u_HuX()_ zxiz0VX3dqn3I$8dqPPqg3ppo;R;q%T6qm-!a~Y>GKEOUIit;GSfEOU0TW;GKN6p|q ziF+LNNq{VDP+1-usGyTh{26CP?u4R?*Ho1_siUa_0a)OS;m4th!&vuua3)sq<3gxn zYJLGO?fCpF%x<{{-I4)y)HJi!d5cUy9fg|ulaZY#Gc--jcWKManrYL@sZWy}g}u}S m*qEeKFs5NNq4MIYsVXvsahgoOqd(!#%;E>l1k9QAGW|DGnStd1 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/tests/run_tests__tests/all_ok/__init__.py b/venv/Lib/site-packages/pygame/tests/run_tests__tests/all_ok/__init__.py new file mode 100644 index 0000000..1bb8bf6 --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/run_tests__tests/all_ok/__init__.py @@ -0,0 +1 @@ +# empty diff --git a/venv/Lib/site-packages/pygame/tests/run_tests__tests/all_ok/__pycache__/__init__.cpython-39.pyc b/venv/Lib/site-packages/pygame/tests/run_tests__tests/all_ok/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..dec15cbd6facb28bc173e641375ab3fe3b6a73b8 GIT binary patch literal 218 zcmYjLy9&ZE6ivZF1pmQFaM11|qUa)si@065M0+VQH3_|GOI`dPf63KPa1#Vm9rVC? zPDggT9TD*A_4n=I_onfgM7`C0XO|xd}1_DhCn07$gfmPy&CNwl8gn(UEE>P2EC)N4=LwG=y`Ggd@G9`7?_yOtgNH z-l#oB7zwhA)|7cPZiqS2g4z)t$eGW**K+ta5&cMZK}XNX zm=@E99YNdh>v@0=XoLj#3AvzMbU}8y7dUsh)>36%)t3<2T1NX9NX-HL`^W94{yP}d zK96Ir{TEV)S(5sxN{(ch4VljRBH;e>S8R}+%8(5L5ha76emZYlQ{D^t zfz*EKN~dt8qxvx`TCA)(Jc?KncJ_HF*^{DgBOT^#!(j(9WBW<3ucf$UvM~-KeEQ(8 zVL%Bj2y^d`jN?S;JJ2=NaPI~UhBre2S3aal!j6gMiiVqf zm{4aZqgnV6!y#X(tbg|!4-9993zr+9;T#xaA66E>ZUd&g846e^GB*<|nM$6mRV3WM zCjTquPWfsWLm10lct48!3hfqS@B2I|N0bLMDsxZOf`PVyMFUF)%#EyoIhCpgUnrF6jCqHth~Yu`to`Zn};KJb;ebu2SIj7oqil-#whA^0k=6YjL6(JZ)Qb)kxg;4 noXygXXXd%ms{oJ)c1Rts{UU_?w5>K?!8UFampInaZ3q7bZF`0A literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/tests/run_tests__tests/all_ok/__pycache__/fake_3_test.cpython-39.pyc b/venv/Lib/site-packages/pygame/tests/run_tests__tests/all_ok/__pycache__/fake_3_test.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8e9c8a387163fc0fea53476358066e36e778e680 GIT binary patch literal 1651 zcmb_cO>fgM7`C0XO|xd}1_DhCn07$gf%U)*O=xIH2m!mST&zfzS9@EQED3hHsuL%+ z1806gd)$BE!0*VF)BXYyAFq>^1+g8F>L`!>+K=q#ef+^a&qYvvtUlU1vk>}bf@*0( zum!*V3Lud{AyJPlCCmKf%r6IeQ9f>G>BG-?T$o4SPpk9seWXb9&V2}gQI^Jf-am}vbX zy-|CNFcM@Jtv7Rrv11;@j9o%LXeX~_QfK-SLqO~4@PHr7Q?INyilL33Ayx~4U<-b| z2_O;JfG9CS&JneQC2Xi|Q4@8jYo#n&7fs%uh<|tl_47hB1#5B|3t6(`VZfZ&!hjN55a!+=8OMpxcc5#k;oc1z3~z=4u6#(9gdG#h6%9A} zFrm&+MzioChC{wmS^w@e9vIFH7cMtI!#OaXFEb1GF0zzk{= zIoPqLUoo=2sLW-_Ej`pZNpxWr&Q4}$EFI{i4vj8W9-0&a6)7?HVc-pq>pBAeo7 nIh&;&&&+eBR{ahQei literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/tests/run_tests__tests/all_ok/__pycache__/fake_4_test.cpython-39.pyc b/venv/Lib/site-packages/pygame/tests/run_tests__tests/all_ok/__pycache__/fake_4_test.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a9bd985d1f15a204581eb5d30f86ca02148655f7 GIT binary patch literal 1651 zcmb_cO>fgM7`C0XO|xd}1_DhCn07$gf%U=(O=xIH2m!mST&zfzS9@EQED3hHsuL%+ z1806gd)$BE!0*VF)BXYyAFq>^1+g8F>L`!>+K=q#ef+^a&qYvvtUlU1vk>}bf@*0( zum!*V3Lud{AyJPlCCmKf%r6IeQ9f>G>BG-?T$o4SPpk9seWXb9&V2}gQI^Jf-am}vbX zy-|CNFcM@Jtv7Rrv11;@j9o%LXeX~_QfK-SLqO~4@PHr7Q?INyilL33Ayx~4U<-b| z2_O;JfG9CS&JneQC2Xi|Q4@8jYo#n&7fs%uh<|tl_47hB1#5B|3t6(`VZfZ&!hjN55a!+=8OMpxcc5#k;oc1z3~z=4u6#(9gdG#h6%9A} zFrm&+MzioChC{wmS^w@e9vIFH7cMtI!#OaXFEb1GF0zzk{= zIoPqLUoo=2sLW-_Ej`pZNpxWr&Q4}$EFI{i4vj8W9-0&a6)7?HVc-pq>pBAeo7 nIh&;&&&+eBR{b+v`^ literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/tests/run_tests__tests/all_ok/__pycache__/fake_5_test.cpython-39.pyc b/venv/Lib/site-packages/pygame/tests/run_tests__tests/all_ok/__pycache__/fake_5_test.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b73dbf4d1321d0a2d553cb8465756b9d7f398a90 GIT binary patch literal 1651 zcmb_cO>fgM7`C0XO|xd}1_DhCn07$gf%U`%O=xIH2m!mST&zfzS9@EQED3hHsuL%+ z1806gd)$BE!0*VF)BXYyAFq>^1+g8F>L`!>+K=q#ef+^a&qYvvtUlU1vk>}bf@*0( zum!*V3Lud{AyJPlCCmKf%r6IeQ9f>G>BG-?T$o4SPpk9seWXb9&V2}gQI^Jf-am}vbX zy-|CNFcM@Jtv7Rrv11;@j9o%LXeX~_QfK-SLqO~4@PHr7Q?INyilL33Ayx~4U<-b| z2_O;JfG9CS&JneQC2Xi|Q4@8jYo#n&7fs%uh<|tl_47hB1#5B|3t6(`VZfZ&!hjN55a!+=8OMpxcc5#k;oc1z3~z=4u6#(9gdG#h6%9A} zFrm&+MzioChC{wmS^w@e9vIFH7cMtI!#OaXFEb1GF0zzk{= zIoPqLUoo=2sLW-_Ej`pZNpxWr&Q4}$EFI{i4vj8W9-0&a6)7?HVc-pq>pBAeo7 nIh&;&&&+eBR{dD4aR literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/tests/run_tests__tests/all_ok/__pycache__/fake_6_test.cpython-39.pyc b/venv/Lib/site-packages/pygame/tests/run_tests__tests/all_ok/__pycache__/fake_6_test.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6ae1085eccec175ab4bded215a355ca39d077aba GIT binary patch literal 1651 zcmb_cO>fgM7`C0XO|xd}1_DhCn07$gf%V1#O=xIH2m!mST&zfzS9@EQED3hHsuL%+ z1806gd)$BE!0*VF)BXYyAFq>^1+g8F>L`!>+K=q#ef+^a&qYvvtUlU1vk>}bf@*0( zum!*V3Lud{AyJPlCCmKf%r6IeQ9f>G>BG-?T$o4SPpk9seWXb9&V2}gQI^Jf-am}vbX zy-|CNFcM@Jtv7Rrv11;@j9o%LXeX~_QfK-SLqO~4@PHr7Q?INyilL33Ayx~4U<-b| z2_O;JfG9CS&JneQC2Xi|Q4@8jYo#n&7fs%uh<|tl_47hB1#5B|3t6(`VZfZ&!hjN55a!+=8OMpxcc5#k;oc1z3~z=4u6#(9gdG#h6%9A} zFrm&+MzioChC{wmS^w@e9vIFH7cMtI!#OaXFEb1GF0zzk{= zIoPqLUoo=2sLW-_Ej`pZNpxWr&Q4}$EFI{i4vj8W9-0&a6)7?HVc-pq>pBAeo7 nIh&;&&&+eBR{eeZ?z literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/tests/run_tests__tests/all_ok/__pycache__/no_assertions__ret_code_of_1__test.cpython-39.pyc b/venv/Lib/site-packages/pygame/tests/run_tests__tests/all_ok/__pycache__/no_assertions__ret_code_of_1__test.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b67ac97266bc9e9053a9b4bb8b422708401611d9 GIT binary patch literal 1604 zcmbtUPfrvv6mL7TyWN3-1&xLXN;sHskd0SE3cb5V>=63u5$3~ z%^Q2^~u~qCowxygOh&bc?9Qr{UwoximnsW>WYZilDaiEUFTCP+}D?JxDJ_s0VFwH7} zLO=sz#1(Ram?u5ygY;!XHbFM(vRG5LWdL?dPRL1+REAK_lnvjg!Mj}cQ?&(k^jsOE z;dD3GVHzJmqD^#$H_ia8Z&bRYTi~tW$CveI(R-t`iA0tO6TMU>Df1#KbiS{Wa==a5 zm$8Umyyi#wu}b(+EYtjG5FM)QFnSwrMsCt!D5L#trrBmm06|yik zyuPO#e6|^9?k?KEltP#0C@%LH?Pqc6h+=dLa9u!zE7JPz5xlMkOIK?;p1ZflECN6y bn35)5`b`M=<$E1GkA2)B0ioXPU5ftz0vCJ* literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/tests/run_tests__tests/all_ok/__pycache__/zero_tests_test.cpython-39.pyc b/venv/Lib/site-packages/pygame/tests/run_tests__tests/all_ok/__pycache__/zero_tests_test.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..213aa883b35a2119443cc764fb9da058cfe79715 GIT binary patch literal 774 zcmZWny^a$x5VpOW#96Wst~-h1pg>AN(j$Zp9TGyoH5`q#lI5ID&e^@)J=?h`X+emZ zCrC=(fr967OLeb+#Lsv)5|J3o-^_SMb%^$n^>&%PEzSs|tgreq%1LE*=M=KzLnJ#n zVTnrY7lonzEr}J~5{$}3q0K--ZI(10q%3`bWKYtMNK%!~Z-0o`on5crRJs{%5k``{ zMWeo_oL>rEa()AR(5de@Wu3jj;IMAJnu$xbPFp>0LgVw0xGy317`7b%Cu!N$V`vk6TLSPR#zgmc*jeJEWjJbiIpH3cU@2oO56J;rE z_FUQARdrUIYOZp(;?^ys7TL3xd|9nk&X-yi)pC_xtMWQ~t*4pQPCcr{c`jzkW-XUV z!)0O?C2uU=s);BHUgeXuGSw~+!sB{nI?&NUU`| ztqbjZPfTs&1LgO+0LrXa=QA#~@kuR=DqUmKa2S}gR9oKm$KlL(bqU0sPplKh*`;E{4_k2Jp!N@7U|*#e+VJJ<7kNQ;TR7| KLTGdlQ~Vdqr`8z& literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/tests/run_tests__tests/all_ok/fake_2_test.py b/venv/Lib/site-packages/pygame/tests/run_tests__tests/all_ok/fake_2_test.py new file mode 100644 index 0000000..3be92e1 --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/run_tests__tests/all_ok/fake_2_test.py @@ -0,0 +1,39 @@ +if __name__ == "__main__": + import sys + import os + + pkg_dir = os.path.split( + os.path.split(os.path.split(os.path.abspath(__file__))[0])[0] + )[0] + parent_dir, pkg_name = os.path.split(pkg_dir) + is_pygame_pkg = pkg_name == "tests" and os.path.split(parent_dir)[1] == "pygame" + if not is_pygame_pkg: + sys.path.insert(0, parent_dir) +else: + is_pygame_pkg = __name__.startswith("pygame.tests.") + +import unittest + + +class KeyModuleTest(unittest.TestCase): + def test_get_focused(self): + self.assertTrue(True) + + def test_get_mods(self): + self.assertTrue(True) + + def test_get_pressed(self): + self.assertTrue(True) + + def test_name(self): + self.assertTrue(True) + + def test_set_mods(self): + self.assertTrue(True) + + def test_set_repeat(self): + self.assertTrue(True) + + +if __name__ == "__main__": + unittest.main() diff --git a/venv/Lib/site-packages/pygame/tests/run_tests__tests/all_ok/fake_3_test.py b/venv/Lib/site-packages/pygame/tests/run_tests__tests/all_ok/fake_3_test.py new file mode 100644 index 0000000..3be92e1 --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/run_tests__tests/all_ok/fake_3_test.py @@ -0,0 +1,39 @@ +if __name__ == "__main__": + import sys + import os + + pkg_dir = os.path.split( + os.path.split(os.path.split(os.path.abspath(__file__))[0])[0] + )[0] + parent_dir, pkg_name = os.path.split(pkg_dir) + is_pygame_pkg = pkg_name == "tests" and os.path.split(parent_dir)[1] == "pygame" + if not is_pygame_pkg: + sys.path.insert(0, parent_dir) +else: + is_pygame_pkg = __name__.startswith("pygame.tests.") + +import unittest + + +class KeyModuleTest(unittest.TestCase): + def test_get_focused(self): + self.assertTrue(True) + + def test_get_mods(self): + self.assertTrue(True) + + def test_get_pressed(self): + self.assertTrue(True) + + def test_name(self): + self.assertTrue(True) + + def test_set_mods(self): + self.assertTrue(True) + + def test_set_repeat(self): + self.assertTrue(True) + + +if __name__ == "__main__": + unittest.main() diff --git a/venv/Lib/site-packages/pygame/tests/run_tests__tests/all_ok/fake_4_test.py b/venv/Lib/site-packages/pygame/tests/run_tests__tests/all_ok/fake_4_test.py new file mode 100644 index 0000000..3be92e1 --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/run_tests__tests/all_ok/fake_4_test.py @@ -0,0 +1,39 @@ +if __name__ == "__main__": + import sys + import os + + pkg_dir = os.path.split( + os.path.split(os.path.split(os.path.abspath(__file__))[0])[0] + )[0] + parent_dir, pkg_name = os.path.split(pkg_dir) + is_pygame_pkg = pkg_name == "tests" and os.path.split(parent_dir)[1] == "pygame" + if not is_pygame_pkg: + sys.path.insert(0, parent_dir) +else: + is_pygame_pkg = __name__.startswith("pygame.tests.") + +import unittest + + +class KeyModuleTest(unittest.TestCase): + def test_get_focused(self): + self.assertTrue(True) + + def test_get_mods(self): + self.assertTrue(True) + + def test_get_pressed(self): + self.assertTrue(True) + + def test_name(self): + self.assertTrue(True) + + def test_set_mods(self): + self.assertTrue(True) + + def test_set_repeat(self): + self.assertTrue(True) + + +if __name__ == "__main__": + unittest.main() diff --git a/venv/Lib/site-packages/pygame/tests/run_tests__tests/all_ok/fake_5_test.py b/venv/Lib/site-packages/pygame/tests/run_tests__tests/all_ok/fake_5_test.py new file mode 100644 index 0000000..3be92e1 --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/run_tests__tests/all_ok/fake_5_test.py @@ -0,0 +1,39 @@ +if __name__ == "__main__": + import sys + import os + + pkg_dir = os.path.split( + os.path.split(os.path.split(os.path.abspath(__file__))[0])[0] + )[0] + parent_dir, pkg_name = os.path.split(pkg_dir) + is_pygame_pkg = pkg_name == "tests" and os.path.split(parent_dir)[1] == "pygame" + if not is_pygame_pkg: + sys.path.insert(0, parent_dir) +else: + is_pygame_pkg = __name__.startswith("pygame.tests.") + +import unittest + + +class KeyModuleTest(unittest.TestCase): + def test_get_focused(self): + self.assertTrue(True) + + def test_get_mods(self): + self.assertTrue(True) + + def test_get_pressed(self): + self.assertTrue(True) + + def test_name(self): + self.assertTrue(True) + + def test_set_mods(self): + self.assertTrue(True) + + def test_set_repeat(self): + self.assertTrue(True) + + +if __name__ == "__main__": + unittest.main() diff --git a/venv/Lib/site-packages/pygame/tests/run_tests__tests/all_ok/fake_6_test.py b/venv/Lib/site-packages/pygame/tests/run_tests__tests/all_ok/fake_6_test.py new file mode 100644 index 0000000..3be92e1 --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/run_tests__tests/all_ok/fake_6_test.py @@ -0,0 +1,39 @@ +if __name__ == "__main__": + import sys + import os + + pkg_dir = os.path.split( + os.path.split(os.path.split(os.path.abspath(__file__))[0])[0] + )[0] + parent_dir, pkg_name = os.path.split(pkg_dir) + is_pygame_pkg = pkg_name == "tests" and os.path.split(parent_dir)[1] == "pygame" + if not is_pygame_pkg: + sys.path.insert(0, parent_dir) +else: + is_pygame_pkg = __name__.startswith("pygame.tests.") + +import unittest + + +class KeyModuleTest(unittest.TestCase): + def test_get_focused(self): + self.assertTrue(True) + + def test_get_mods(self): + self.assertTrue(True) + + def test_get_pressed(self): + self.assertTrue(True) + + def test_name(self): + self.assertTrue(True) + + def test_set_mods(self): + self.assertTrue(True) + + def test_set_repeat(self): + self.assertTrue(True) + + +if __name__ == "__main__": + unittest.main() diff --git a/venv/Lib/site-packages/pygame/tests/run_tests__tests/all_ok/no_assertions__ret_code_of_1__test.py b/venv/Lib/site-packages/pygame/tests/run_tests__tests/all_ok/no_assertions__ret_code_of_1__test.py new file mode 100644 index 0000000..0ba0e94 --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/run_tests__tests/all_ok/no_assertions__ret_code_of_1__test.py @@ -0,0 +1,39 @@ +if __name__ == "__main__": + import sys + import os + + pkg_dir = os.path.split( + os.path.split(os.path.split(os.path.abspath(__file__))[0])[0] + )[0] + parent_dir, pkg_name = os.path.split(pkg_dir) + is_pygame_pkg = pkg_name == "tests" and os.path.split(parent_dir)[1] == "pygame" + if not is_pygame_pkg: + sys.path.insert(0, parent_dir) +else: + is_pygame_pkg = __name__.startswith("pygame.tests.") + +import unittest + + +class KeyModuleTest(unittest.TestCase): + def test_get_focused(self): + pass + + def test_get_mods(self): + pass + + def test_get_pressed(self): + pass + + def test_name(self): + pass + + def test_set_mods(self): + pass + + def test_set_repeat(self): + pass + + +if __name__ == "__main__": + unittest.main() diff --git a/venv/Lib/site-packages/pygame/tests/run_tests__tests/all_ok/zero_tests_test.py b/venv/Lib/site-packages/pygame/tests/run_tests__tests/all_ok/zero_tests_test.py new file mode 100644 index 0000000..649055a --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/run_tests__tests/all_ok/zero_tests_test.py @@ -0,0 +1,23 @@ +if __name__ == "__main__": + import sys + import os + + pkg_dir = os.path.split( + os.path.split(os.path.split(os.path.abspath(__file__))[0])[0] + )[0] + parent_dir, pkg_name = os.path.split(pkg_dir) + is_pygame_pkg = pkg_name == "tests" and os.path.split(parent_dir)[1] == "pygame" + if not is_pygame_pkg: + sys.path.insert(0, parent_dir) +else: + is_pygame_pkg = __name__.startswith("pygame.tests.") + +import unittest + + +class KeyModuleTest(unittest.TestCase): + pass + + +if __name__ == "__main__": + unittest.main() diff --git a/venv/Lib/site-packages/pygame/tests/run_tests__tests/everything/__init__.py b/venv/Lib/site-packages/pygame/tests/run_tests__tests/everything/__init__.py new file mode 100644 index 0000000..1bb8bf6 --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/run_tests__tests/everything/__init__.py @@ -0,0 +1 @@ +# empty diff --git a/venv/Lib/site-packages/pygame/tests/run_tests__tests/everything/__pycache__/__init__.cpython-39.pyc b/venv/Lib/site-packages/pygame/tests/run_tests__tests/everything/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..06f843dafa7fc8104593c5ef94526960f62105f2 GIT binary patch literal 222 zcmYjLyNbd<6rF&DEaV@o7A$tti-?Oh!m`a`ci}RcOB@qthPji3vGr^GC0jqiP7s`E zp$E>hIxvAcedVngnV^Dvve_d zgunTM07Q|L>5qykHlUnVHRBA}o_FN`gDq%J=mc4dq=~#UWp*YsW<20s=qfK|xt{h1 z$o3bBYNd>a5SmXwasC-aA(${qvJlA8tiri@SSg5j^pvQM3f>bHK(sga&g1h_t)C$} z>P-kGioGItyJaB6zDzP9zF|IOqik6))_kKF@OClo%Y8VE>UyObTG@8QW?>jS!r!bR z06`lFXHLj_!ae0FA8TK=R2%D7EsM8RSA`gN)QpJ<80CkMicz8l`Dh#;Kz0znNVZ~=Sh!cn?Ns)` z#I-A{l`E@yn2D+->S`4ZK#%QilJ!@2WD4Sb)xT1V%bw$jK3K7nZx0Qq%Pu45BB6)3 z{xYDlyh;5ZM|2x!)Ex)z)K(_cFpFUs{gJVsD{~dQPBdIUM}y;Cpny{!3JthxYO$f= zJRhdi3zX5Ve8}*i-)O9V?Fe5H^AUIaK_$lEPmDoobWDCzk-L|)yDX(=#-?PsDg8p)-LhqhL1N2}+%i>+kJ?T$Kxw>Fql3kB{H1I(s%D>Lw=P_ pb+dxC+Kz|r$udg_mn~{z(Ohs=#K6v$HLfjVuON}hQ>J@5dd+kM$>GYY zK(1bBeFw?eV9q$x;w5{~uOp?7vb<301MY|I)Ex)b*$*58*{x=y>Yn?oYD zi@@L!R{IbE7}~(3AR(`r40NDFY(w4AU2HpzEZNn49b??nOL`gGNGB*~rA~f^*^5$7 zC$Nh;h9qNAsE;SYwz1k3gx}a1)95Geg}r3wVrTc9*KuYo7`JPtfKg~+vVYFZ64L+r zef!7s7o4Unolyy^`XX)c->ZCk{u{z21q&%6W$50%n&-1<1 z<_>+Kp&_P zIJI96rxx^0+8Wu(`02O*aKd}vrv4vmOcz%)Jp#JE-i-#9F|3nI8AqkIU*XU~!=3-o zK)h=daQo5~zr)G^o}pfE3Auko$il@o{~87Ly(0zQ{kts@UtbYHhew=i{NuGRPFTDa z&Hq>KGpwpU~J}R_fPj zHfd%|f-4$IWV1>zAhZh-Q>u literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/tests/run_tests__tests/everything/__pycache__/magic_tag_test.cpython-39.pyc b/venv/Lib/site-packages/pygame/tests/run_tests__tests/everything/__pycache__/magic_tag_test.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9c9bcc1f365ea1a87c37ab6111d425e547f4d54f GIT binary patch literal 1535 zcmb_czi$&U6t;br%jMdnX#qi1Q~?802bzTmAyiZ(gn%wBi#f@1V>i7fxjSs9Ar%{4 zSeO}`vHu1Ge}q@2{tHO_c)n}l5bc0eNB*9l{dE4`=l8;!%?QExe(Ub`YY(BX&Z&+D zIBPKV7XX2Jm?DViYl^Q7jNB0@)rS>IqNyV0}>&0oa&3KPgAbrCsOxKmdClu_GI5om^LGk@c8jFHqH)YpN$hS$i|a+U#9!< zi)1_2iIMkm-tF_A)N!dsr%q*0Q zvhGMram^*=1Vs2?`7aF$wX323BZ{iS7ggxM)pnsn2~BWq^EZuQCiD&1I^(c(0S6a% zi3I-WkShrfCzdK4F4EyN^b%<_3LR3Y@#V_>*U!!Nm$epG#+plthGIz%z(1unGNF}Q{)04f)y#(=g1J%Ju`p@HJS zwT&HD(nozJdJS*=_^|sZd5du-Ny{=d$ulrH#w3*ClA|%o0npx>bmZbe*pVc5>5aB literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/tests/run_tests__tests/everything/fake_2_test.py b/venv/Lib/site-packages/pygame/tests/run_tests__tests/everything/fake_2_test.py new file mode 100644 index 0000000..3be92e1 --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/run_tests__tests/everything/fake_2_test.py @@ -0,0 +1,39 @@ +if __name__ == "__main__": + import sys + import os + + pkg_dir = os.path.split( + os.path.split(os.path.split(os.path.abspath(__file__))[0])[0] + )[0] + parent_dir, pkg_name = os.path.split(pkg_dir) + is_pygame_pkg = pkg_name == "tests" and os.path.split(parent_dir)[1] == "pygame" + if not is_pygame_pkg: + sys.path.insert(0, parent_dir) +else: + is_pygame_pkg = __name__.startswith("pygame.tests.") + +import unittest + + +class KeyModuleTest(unittest.TestCase): + def test_get_focused(self): + self.assertTrue(True) + + def test_get_mods(self): + self.assertTrue(True) + + def test_get_pressed(self): + self.assertTrue(True) + + def test_name(self): + self.assertTrue(True) + + def test_set_mods(self): + self.assertTrue(True) + + def test_set_repeat(self): + self.assertTrue(True) + + +if __name__ == "__main__": + unittest.main() diff --git a/venv/Lib/site-packages/pygame/tests/run_tests__tests/everything/incomplete_todo_test.py b/venv/Lib/site-packages/pygame/tests/run_tests__tests/everything/incomplete_todo_test.py new file mode 100644 index 0000000..bdd8a3b --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/run_tests__tests/everything/incomplete_todo_test.py @@ -0,0 +1,39 @@ +if __name__ == "__main__": + import sys + import os + + pkg_dir = os.path.split( + os.path.split(os.path.split(os.path.abspath(__file__))[0])[0] + )[0] + parent_dir, pkg_name = os.path.split(pkg_dir) + is_pygame_pkg = pkg_name == "tests" and os.path.split(parent_dir)[1] == "pygame" + if not is_pygame_pkg: + sys.path.insert(0, parent_dir) +else: + is_pygame_pkg = __name__.startswith("pygame.tests.") + +import unittest + + +class KeyModuleTest(unittest.TestCase): + def test_get_focused(self): + self.assertTrue(True) + + def test_get_mods(self): + self.assertTrue(True) + + def todo_test_get_pressed(self): + self.assertTrue(True) + + def test_name(self): + self.assertTrue(True) + + def todo_test_set_mods(self): + self.assertTrue(True) + + def test_set_repeat(self): + self.assertTrue(True) + + +if __name__ == "__main__": + unittest.main() diff --git a/venv/Lib/site-packages/pygame/tests/run_tests__tests/everything/magic_tag_test.py b/venv/Lib/site-packages/pygame/tests/run_tests__tests/everything/magic_tag_test.py new file mode 100644 index 0000000..126bc2b --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/run_tests__tests/everything/magic_tag_test.py @@ -0,0 +1,38 @@ +__tags__ = ["magic"] + +if __name__ == "__main__": + import sys + import os + + pkg_dir = os.path.split( + os.path.split(os.path.split(os.path.abspath(__file__))[0])[0] + )[0] + parent_dir, pkg_name = os.path.split(pkg_dir) + is_pygame_pkg = pkg_name == "tests" and os.path.split(parent_dir)[1] == "pygame" + if not is_pygame_pkg: + sys.path.insert(0, parent_dir) +else: + is_pygame_pkg = __name__.startswith("pygame.tests.") + +import unittest + + +class KeyModuleTest(unittest.TestCase): + def test_get_focused(self): + self.assertTrue(True) + + def test_get_mods(self): + self.assertTrue(True) + + def test_get_pressed(self): + self.assertTrue(True) + + def test_name(self): + self.assertTrue(True) + + def test_set_mods(self): + self.assertTrue(True) + + +if __name__ == "__main__": + unittest.main() diff --git a/venv/Lib/site-packages/pygame/tests/run_tests__tests/everything/sleep_test.py b/venv/Lib/site-packages/pygame/tests/run_tests__tests/everything/sleep_test.py new file mode 100644 index 0000000..468c75f --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/run_tests__tests/everything/sleep_test.py @@ -0,0 +1,29 @@ +if __name__ == "__main__": + import sys + import os + + pkg_dir = os.path.split( + os.path.split(os.path.split(os.path.abspath(__file__))[0])[0] + )[0] + parent_dir, pkg_name = os.path.split(pkg_dir) + is_pygame_pkg = pkg_name == "tests" and os.path.split(parent_dir)[1] == "pygame" + if not is_pygame_pkg: + sys.path.insert(0, parent_dir) +else: + is_pygame_pkg = __name__.startswith("pygame.tests.") + +import unittest + +import time + + +class KeyModuleTest(unittest.TestCase): + def test_get_focused(self): + stop_time = time.time() + 10.0 + while time.time() < stop_time: + time.sleep(1) + self.assertTrue(True) + + +if __name__ == "__main__": + unittest.main() diff --git a/venv/Lib/site-packages/pygame/tests/run_tests__tests/exclude/__init__.py b/venv/Lib/site-packages/pygame/tests/run_tests__tests/exclude/__init__.py new file mode 100644 index 0000000..1bb8bf6 --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/run_tests__tests/exclude/__init__.py @@ -0,0 +1 @@ +# empty diff --git a/venv/Lib/site-packages/pygame/tests/run_tests__tests/exclude/__pycache__/__init__.cpython-39.pyc b/venv/Lib/site-packages/pygame/tests/run_tests__tests/exclude/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..38aefa9370ba4727e99a782a0d0c73b948f6fbec GIT binary patch literal 219 zcmYjLy9&ZE6pi3e1pmQFaM11|qUa)si@065M01hYnuOl8wNCzyzvSvCxCw%(4tn4` zrz6|#mI!!ty4xuDy)OS~gfa=_W)LOTqSshmMOM#0d0u8i*f3=b(iq7wCr-R|;4*ul z#8=2ZS6ae!fu%iDf~8ieEh{L<6tL7=VC|{z>^qdnrlRkvt#v?@<&Tt9mRiZ|PyKwkg= literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/tests/run_tests__tests/exclude/__pycache__/fake_2_test.cpython-39.pyc b/venv/Lib/site-packages/pygame/tests/run_tests__tests/exclude/__pycache__/fake_2_test.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1f558086aa34648be70c90b1853bae216f80eaa3 GIT binary patch literal 1652 zcmb_cO-~dt7;ZbWyR!oW3mOd(m2fcOAS50QF&IpYQMs^Qnn{|neSu+?nX#P(mw1DN zXMe%&k^kVq-!WHD`~?#~-p+uG5e_DFGEe)qPuk~w`XPhBCs=+gJlZ;T2>E7%dTC>@ zhQIlW07Q|P=}(F()~B47HRBA}o-=a)!3H$Pbd0PyQb*o8XST*PWZdIzXe%dXsXp)b zknPS9)rcAQ!8f0Q;`|eef;VQABtDSQq{6wmUn&TA@RF#O@=l2IAlREacKGzU)-Mo@ zI%7hKVw+^CU3fz5%P0}z4D%ryMI#53n=^_5Z)U?CxerG{RWFxA%RNi17ly$a{$>>c z2--k6vqDY?ca)=CtX`M+vuLs!k5N?&bxX57`X=e+owcNApQIC`qS_o4w_IV zi8SF0Fmaw{VW!hPi1VQ^`9MW7eEv!trbiHq!$|eh!(n&;$wBxg+6qmS!{bc$Vz~n* ztXx?sU0KnCM3gO2RV(nJ*B>ZY*_JVgCuQeyHY_@pBz7Pd+i7oLK;5$GSPKa~dhl2F zrQdbx|Jb3MIHPV^ut&CZpn^#Zi{Oup{ZyGd*ma@d-ZdI5?*;{2`jBbBEmLzf4cGZ_ zPQ5`H?b3$?Px*Xp{kvCqU^zFqaJ2yj&w(}eVQulNHsFGHg94_@% zk9y9xJqdrRGtt{RVD$<3YNexL} zwmsWv74jf5qPoKZ`-*0i*q5X5O)hnA4x@aRdxIp(tx??TBCbnhSdoQmAI+NlGMn;d nd8?Hj&+L0;77#EI>aiwW{KXji={g-cPhHw!KJ%Q}+aCQ5`HY5X literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/tests/run_tests__tests/exclude/__pycache__/invisible_tag_test.cpython-39.pyc b/venv/Lib/site-packages/pygame/tests/run_tests__tests/exclude/__pycache__/invisible_tag_test.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8f4ea0ad1e99ae28d36e4ec1d475d201e4e344d2 GIT binary patch literal 1688 zcmb_c&u`>36t$3oBTykb0oKqZL|IB!qxowp^@8mOJltHk~vHwx`{x zxUnY=oVg%%j{P?{@JHmzY5xTzemrN|-5|OLq&mv?{Ol+Dd!PNRvn*xQ{`}yh!(Rf% ze)mqlCFDGz-~L7bY{n%+4ty@mPaq&Dg%q6)WPrhOcro}7MmSvY6$f#T^-;!Gk@1S> zLMAfB6vDZvpI?n96g{}dAesv~!jb(M1+BjU0+W^CtV)qzWI$`nQO95`$6qjrA$h?d z!SV6t4}qLqas3s?7k5^SGYFot?Nla3bz0csu*5c2>O>cnQZFe%w%-mMT4!H!a%9vj zXZi%sv$fsnrgo-2u-^nZPw2Og36Mz+j8vhFUoaU!03q2B1`v@Qzz|}x5hRe39l{7U z$i|QnvvHe!h0AYhSd@4`Jf@z;b@P2XBDP1r9TR-dE*Oxsloor+F2(-AC2v!0EgE-V z7D!%bu{^qDW<=qC{J8f?{w+<~TvwI0`R8cou5R+i)W_0Ni~gwQ_pa&FwVH zcH(2z44pcvrwfblw$I8d$@uw$e~Hk^-Vgmhs+fpYG(!*mDtAJxVT0T@dqv}<2Kz1z zU30kq1`a;%774u8p)p7&2lsm%-lW4-=q=JnIvpyy><@bTzjK2IKIRrTULSy^d*Frr zu($b52XGyCiv%{i%>BX!8`SPmkHY&m?H7hZjVtHl=r@t6S=CDD~Y!m+Kjm z(Tc{`tJ(B0@o>k(mIq&%J@B{E3<&PhZ@m}uIJo}0ne8n}+fp%ErOaCt(FS&DTT$CK zY_xmU4s25vt{v(_+xZlIRFp(g4x9N*L1Ego(FQBm^c|^cu^J3OD5w3!aYq9o^BiZSG1Q%mseL~@#D2HpZW*PJ|u_)CB%@(T zBWI57asLJf{s><=?O#CR$8*v_5ZeK1uKYbe`zik3=l9B+O%K8Ne&^oq8w;VY#wm{) zIGZrl7XX3!m?DV<9+2dtAi^3FN^)yaOIio^wDJ!+vO2>vEXXn{BX#GI?hN~c)~F{v zVGl@jG~cg5bY&R{XFzCO*3~CT;QI|hWNk(;3O$LZO#$Dg^_)SAww@v3irNVhHQ72? zcyH16oa<-Vnl8=|M#9=b>z=NRct7ZAm$4BKLdMP@Ikc@SsZ^;t!{AUSp7i-h9ybfS zksodJOkjBsa5iD82LKXLED$IH*`6S32}{^uZBY>p*ovqM7px;{!UJ0sbzsxb%@=a= zDiYaHcH#b>x&C~ZH9QO2f~i^n@6Z$pkP}itJLr^bcTchQxKc7nyGbU&vy~j~ouZ@x z;om-NJ@jA0q4Ieca^*jjYLG^;A1Bd)9HbMb(o6*0fAXA-qhmQ><3J3f@x(ur;i3OB z*!5MA%KI_z4R~KFzfhx-tIyFvng zbchoPuO?PX94^yg9(si|YPk*}6!>cC{+kzQU}CQD;^F}m)PWK9Zt3!i9^gD~d)+n7 zYPc|_J!sp!U0~f{>}|$}#Ytj1Bv~-fHn3=5$$;sF5|~;@9DwUEl_?Y#yH@eb_t%#w z+y@1$7)!3fxwh0qX%Z=I$2{HF6%`MIR9E?~%6*953x>dsR^vgRi6GHl%o7==`Pwy` zh9qqUiWN=7U{5dSES}2o1t_O+5T6Alxt8mr)ljmhNgbkBpkXlQIIdSTZ1?$X# zQePtbJXR8>3oOi;QY=)QnWBUf=@Tr~7Fc=eS-DGPLJYP{^X9|#!tepMSH2T b+z}5VM5UES?A!9z7#&TVXEd(9Jp#oWUuQuB literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/tests/run_tests__tests/failures1/__pycache__/fake_2_test.cpython-39.pyc b/venv/Lib/site-packages/pygame/tests/run_tests__tests/failures1/__pycache__/fake_2_test.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b3625316761b2695cc990985d3de5ab205076988 GIT binary patch literal 1654 zcmb_cO>fgM7`C0XO|xd}1_DhCm^dKqz$Q4N2@MSiAz+u4ixtW8YOl+ZCBaTtb>g-m zapo7a$NdKm{El2X?Jpql@j7W)5ZeK%j`G;A{m6da#~chQL3!!f&sFo%K zTkz|z01^ol67@-7K_X0XQ4>leIkZOhKUkCXF&+bJ8C8)sCd|ed`-D2QDVxFyNunnG z4zTTIBx)g{u5|ThiDCXZfu%Dh7{#tcqn3cVsaq)UsP__yhH%c1aHMxQe`?W%iPkUD z8@0y>BSCi2S~GVTJK{mi*ahT+cJf*#b*3*c1hk$Gd;CbAcxAm_46Sz!v04ZOTkz{m z0Exf`M2Qh{hNvYhVMA?;ny5ovD`nBTXbKnNhL{sAs2$;focY{)Er)Lt(T`*Ybaai3 zX)$fs5ws1zo(K4VMo564kPF&H=VYgIj&ql5EmhW0eF>4RWwd{e)Ev;if82iRzk@;T z^El?(e<5|4C8?jP?pAKQfLIp>ILgRKuNXG#K6t1zh@&f=%GVaz(>+ zK1`@Hl+i4Fh~b>CRMx+Jg$IT+!-dNY&~OfnvG*&BU$p^K-V6mS6q%cel}shi9#kaU zy(0fh=1%!=7(*D#U3fx@D+}!wWAFPsDo2zDGb(dc)q;VxfkgvL2F#_bfH{?_24DuY zi5%=$)2|p=TU6$<fgM7`C0XO|xd}1_DhCm^dKqz$U~EO=xIH2m!mST&zfzS9@KSED3hHsuQ;j zi8H^TJ?=kn;CJN8X@3EUkJm}dg4hm7b(F_`?ML?WKK|gI=OQRSRv+%2S_pkJLA5j? z*n(ew1&~Ofkf=`r3ld?9i<(d($)Po}|G}E9kMS5-%czR9F<~~w*eBGXP1zJyND?*a zcYtj#BT)+pb)~C6OAPbR2`rs4!6P2EC)N4=LwG=y`8gd@Gf`BRH7OtgNH z-l#oB7zwhA)|$D)*bxt6#x5Wqw3F8|sWW|nA)xhi*yBg?#4GFdVracPv`hEu;N&q~?JB{p0pi{~Zi! zpT{xR{tKzYEJ^)TC5JN1hD>LD5pe(cD>g_@WXJ}Ah?2q3KbG;a|0dY;b&$zNDes27 zC$(R?vQfCQq53f^TCA)#_IVKXmDG=+6-xG`=w45UdE3xfPiAaC>Gri0H%vmtM1)W7 z{gr>=c$NA;hNwEss2T>$p)EWpp#@>?{gH8$2z?8>rW)>CqrvcIDB#kE6l?+?mMa>r z^I<}rp^RqXLk#D9rLz9*D?Biq87^FIfQEBmjJ;o3{HhI@@@6Ptp~&1!tYj*A_Mjr+ z?iKl8GIz>{!x+L??!psNTv=$h7<=F6Q8}VKm{FOlsum2i4J;a1GGH!c1awwjV?wjW*J-$3&oVH|0vk zS(*fM(z%U|n+dP{U`9(Ix o&2lzNJD!;rORoYzBG@5y{NNWMcL%Qn zLjFKwzIDNP2%mckV2CCev%hJo*^mnAdnTA+N5N^hfGyLW(kXbYk$DuInP+E86DGLm znywBqR@m7*2k&r==vKx=WFq&wp|JmwriM=$C3$4X>9U5sMdTU8B7Q=2NAp)ia}yt} z{1S-O8P_)^KJ85jC7SJ!jc(1QJXUEg{4pZs|7kt%jCp>#mN#?&u}G3_aH|&{?VDXJ-6E zp+`fr3q1Ca#(Bdr+z8o*&#eIbL{5nYJs}pdL(W)#_l(w&a?aRl*NzNWp)2PF?yAPwx$glnMW;w2V=q3+LCHITH zku&-;3A|465zR0w@lG~^{^QBYPH}A3pQeL>v8g+}n$bsLO3)32S(_tul`u2c1z!J< zDgPo&*9((F;@_G(|K=s4pwGg=n5JG3R9REUpOT-UB0vn*f86MQ^>sMN3Y7WI#mT|s zvgIToU|8&wlfapc+!v5j-fqfML8W<&PsZY*uUx zJ6bGUyNZAbW3M4xN5B%D160qp0C3Tv#VHSFzm{LwxMs0*>cEX%%?ekCrK%3=mMe#8 zRd>|Dc^h81{d5S_M5oLSq)u%emCBmD@?(yZ$WX+olTA%an5)}qjxR|axk}l}out*F z;G;aPP$<@jHb=GN1%8EtgJz( literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/tests/run_tests__tests/incomplete/__pycache__/fake_2_test.cpython-39.pyc b/venv/Lib/site-packages/pygame/tests/run_tests__tests/incomplete/__pycache__/fake_2_test.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7642ff0e36abaac90946dba1ffbef41f80fe5407 GIT binary patch literal 1672 zcmbVM!EO{c7`8pLyR(x_vIJ-q0c}L3N*tO<91*IhQmI1FTnHCyB+FTQ!(=8iQ`<|l z5x1hM=RQI9n0M%*&oS4Ycm*U%|KF3qkPV>LqxtOL{$zjt{M#}~VglvO#>xM^7qF-Mb2p3~OZR}=!?uV?%6P#-64z3GQG$4KlJ z2EhaP?R@}Ezy`t@3VBI*paK;_9jcz{L)~j-@xB_W7~+9iQp-?BDgikwP4Y<3ey-HC z(7T{xj55v(w&6s`HvD!4-~~A$3jBn!vD`=?@RZQFW|yag?c|I+~@=b@@Dfob9DH zbNahlj&r%MZQ8oBq5*je0#LU< z5}Xu|#3vUX2;DiQJe z@i#jnzPum;&ki{Y3xCuIvkKFh5yEBXu=d^u3ps%%f8AMsJgGta=A< zVxwy<-R+K!TNiYo5AT^f?Nfrr2+_pwsQ60^?PVc;naZLaF$ubWm)BfDSVO?{H`fsG znsxv)%Jcw`W-*Fr6r6v46uoD&XB(tKu*8=*QepcdZ(!|zDFu|Sv46r~L~qiNj#$j1VC`B&{{?jok_7+& literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/tests/run_tests__tests/incomplete/__pycache__/fake_3_test.cpython-39.pyc b/venv/Lib/site-packages/pygame/tests/run_tests__tests/incomplete/__pycache__/fake_3_test.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b01dc65dff5c6dc74a3dbdf4da7b95e91c502c82 GIT binary patch literal 1655 zcmb_cO-~dt7;ZbWyR!oW>qj(1RKmf8gK+R>jKN@HjLHSPG?O%C`vSu(Gh^G8Eb#_0 zp8W;vk^kVq-!WHD`~?#~-p+uG5e_DFGEe)qPuk~w`XQqzBv^jTJ=i$#2>IrMX6a(E zjKBGc07Q|L=}(F(HlUnVHRBA}j(6n$gDq%}=@?lvq=~$9%Iu73%y_`N&{bZ_a(&t# zAlsiIs+BSxLTEk%#rY=`g<#Am$wDAUlM3hNVWlAA(F>wFDmWx6fM{pxz~j@WTE9Sa z)Eg5@6k8(;-7*kjS0t zAZP>O%n3Op+*6+NvG!FV987BSA}(~k1F0PeV}~k{@w1m=FW-k$>?LZD?~UU3kiCyzCmXRzEIce^Kb2cx z;@Xv^%9SNO%tX}^b+wda{d~6=fQ6+^nSyv!^)D8qvgdeW3#{18`$GfjhRevgNa+5( zzYM4>Z&Lrq5#7cab;p4_wUr4qOk!9@e`M_D%G|=PGYxkx(cpMjDB#?OLIduanrUdb z%!gCz70T#VK4f^%XB+F^zQ6;=xx$6(4KR2PoU!*Ci(j+>XS^#EFkNNtCe~1ZwDS!K zcQ45QoVi-R9L^9S$`Id>>ds<&Qiyj$IjBc;gfnV)SM{`mo`Y)+t~+qIvH|W?>K1|< zG%gBg;GKQd$ig-4E=%c|kttbjO23eHyKI?akl3;#H%t}dqqdn0P#W(P>6TE5F2h1< z$ZXXPT&GjWqr`~%8Vl?z+ezjgk1{k?YHRiqyUl}PmRM&L57rS^Br=@H(s%D>Lw=P_ pb+dvewH;60lV#=*FcBKCHl6>)82jmaJvvK$+G8OLyz4gu`WqJ0hqC|x literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/tests/run_tests__tests/incomplete/fake_2_test.py b/venv/Lib/site-packages/pygame/tests/run_tests__tests/incomplete/fake_2_test.py new file mode 100644 index 0000000..b88f1ae --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/run_tests__tests/incomplete/fake_2_test.py @@ -0,0 +1,39 @@ +if __name__ == "__main__": + import sys + import os + + pkg_dir = os.path.split( + os.path.split(os.path.split(os.path.abspath(__file__))[0])[0] + )[0] + parent_dir, pkg_name = os.path.split(pkg_dir) + is_pygame_pkg = pkg_name == "tests" and os.path.split(parent_dir)[1] == "pygame" + if not is_pygame_pkg: + sys.path.insert(0, parent_dir) +else: + is_pygame_pkg = __name__.startswith("pygame.tests.") + +import unittest + + +class KeyModuleTest(unittest.TestCase): + def test_get_focused(self): + self.assertTrue(True) + + def test_get_mods(self): + self.assertTrue(True) + + def todo_test_get_pressed(self): + self.fail() + + def test_name(self): + self.assertTrue(True) + + def todo_test_set_mods(self): + self.fail() + + def test_set_repeat(self): + self.assertTrue(True) + + +if __name__ == "__main__": + unittest.main() diff --git a/venv/Lib/site-packages/pygame/tests/run_tests__tests/incomplete/fake_3_test.py b/venv/Lib/site-packages/pygame/tests/run_tests__tests/incomplete/fake_3_test.py new file mode 100644 index 0000000..3be92e1 --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/run_tests__tests/incomplete/fake_3_test.py @@ -0,0 +1,39 @@ +if __name__ == "__main__": + import sys + import os + + pkg_dir = os.path.split( + os.path.split(os.path.split(os.path.abspath(__file__))[0])[0] + )[0] + parent_dir, pkg_name = os.path.split(pkg_dir) + is_pygame_pkg = pkg_name == "tests" and os.path.split(parent_dir)[1] == "pygame" + if not is_pygame_pkg: + sys.path.insert(0, parent_dir) +else: + is_pygame_pkg = __name__.startswith("pygame.tests.") + +import unittest + + +class KeyModuleTest(unittest.TestCase): + def test_get_focused(self): + self.assertTrue(True) + + def test_get_mods(self): + self.assertTrue(True) + + def test_get_pressed(self): + self.assertTrue(True) + + def test_name(self): + self.assertTrue(True) + + def test_set_mods(self): + self.assertTrue(True) + + def test_set_repeat(self): + self.assertTrue(True) + + +if __name__ == "__main__": + unittest.main() diff --git a/venv/Lib/site-packages/pygame/tests/run_tests__tests/incomplete_todo/__init__.py b/venv/Lib/site-packages/pygame/tests/run_tests__tests/incomplete_todo/__init__.py new file mode 100644 index 0000000..1bb8bf6 --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/run_tests__tests/incomplete_todo/__init__.py @@ -0,0 +1 @@ +# empty diff --git a/venv/Lib/site-packages/pygame/tests/run_tests__tests/incomplete_todo/__pycache__/__init__.cpython-39.pyc b/venv/Lib/site-packages/pygame/tests/run_tests__tests/incomplete_todo/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9b187380edc6aad50744abb09edf8073b9837fa2 GIT binary patch literal 227 zcmYjLJ8Hu~5M6-_VbC318C*E(LkJFb69{gCyMbZl9mGb`?xGn<$S3esd?mLzLOO#X ztE5OCyl?e%md#bfeX%Uk=$}*hk0h2&B+sH4^{!UQ{-WAx{*&8z`v?c7mO(qG8Fs{# z_yD2xA5_VRES<3$US4tVC#rC;ruM@KJ-HsY)VOHRE>A|ar zv0o|aw=pJ<@N>T)05hx<_NC!Q%(&zs3MoJwN9XZBZ~((4Um|Oh^-+#4nWH7og-qla z#wIF7Z7;_YWXGG#3`!wWNZn7sas3s;Az2E}subAys=>8o8WdzQ`;wWFNnS9MKz6+L zLnPNPwf+p*`DDpBGvW!mH*OQ9PIOTz^&0oX_S%65=iO_Li5xbIBYgsASr@m%)b^B! z{U$JZgr9qW01RzlQjm}rOhzU$F~-;o%n;+ClO=~{Y*NfeX2q;xOiYGy*4pfASbSTX z`3&|^$CPATHR|JuuwDGz8p8MNoEh{J_rjjA3$eFpg)yMpxJ ze%$>${|+ZzuB%GB{0nfUubaHF^)Zxwp`4$aLg$aaQm6G9leJ2wdK|vJ+g{vGYoWp6bF*QBCWUW(FRVuT8yks7p}y!{m0eXeUHgN8r_A zJ)Ju+@6fi$O2*GV{+kQI_dfOi*kXscq8$;?)eTN`u!?D$y^(QJ8}~jAU1|96KQs{U z1_iuF<^)&54jT)2erB^Lg|Hi*TLF3>^h4=n;Ps9h;M9|?8=LY|H$%g{IHu)ZOMbqj)(M?xh(|T2v5Y2-}zGr@kbm@_-!8Z NiAY5fZM>WCzW^fJl0Eqj(1RKmf8gK+R>jKN@HjLHSPG?O%C`vSu(Gh^G8Eb#^h z6L0?^+b8YwKK+nU6cQ{y<{oSuc!Yd&L9=u* zSjOLcMF65m%JfG?6&p}atD12JY{xtD|G^ft$8?OW8PY`FIc0XnG-f>DUFa$=Ww}1> z50LH85YQ*oQ>|Yh zI_ixHC5o+)g>D%Lu`82Ih!f0*td=bc#+nm~0dE(hEx8N(QC%-qLyLV!Y!-&WGXCZX z0uZ!;aOQ*@67DHa`B?j^rP^4xYFWIkx+=uDqbAfO)`5yp&Quw_g3+5?4F|A}I{Hq= zS#fRL5we26nL_wLj)+1(F&DB%j@jz^F)c%B3~0Nqhk%i9V6b^i^aRqse_DAQzr{fl z%Pf;7ehwzJc@Y;n-+|PQgt0@F$oSbyv6t^dD)tgJ$oEF^d&u6$uak|~Bo-bPvY*N= zFmdh5Qsv5$9%iCyiMm=!vVOi>48Vf0xyqL|WeVa^HMm%e%AO;OEwExU?+*>A8!jzp zC87KG{&J!6y-EEaTXY*|)Ex)z=vGeDFo|Iq{gJVoD{~9G&NSS)M1$j9p@4HA3Jth* zYNny#G9ON`1<)9wX5zeUHh1JszdJe8RxbDDR%?7wr zsaptc(6}g|fp_**BMaBGyDX(=My6!BDg8p)?XqQxL1N2}+%Q#)FWY7^Kxw>Fq+3EI zx(o}cA+uFGaGg#ej}jy5yDYG;Y$us}LCVlrsjb;d>^2XESz?`0JXl9uk;rf&OW!@7 t4f$0z)y)c?)OI{|@0OWEz(i=k+I0RGW9+Bz_2?}1X^(|0@UGts=x@mjiOm22 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/tests/run_tests__tests/incomplete_todo/fake_2_test.py b/venv/Lib/site-packages/pygame/tests/run_tests__tests/incomplete_todo/fake_2_test.py new file mode 100644 index 0000000..bdd8a3b --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/run_tests__tests/incomplete_todo/fake_2_test.py @@ -0,0 +1,39 @@ +if __name__ == "__main__": + import sys + import os + + pkg_dir = os.path.split( + os.path.split(os.path.split(os.path.abspath(__file__))[0])[0] + )[0] + parent_dir, pkg_name = os.path.split(pkg_dir) + is_pygame_pkg = pkg_name == "tests" and os.path.split(parent_dir)[1] == "pygame" + if not is_pygame_pkg: + sys.path.insert(0, parent_dir) +else: + is_pygame_pkg = __name__.startswith("pygame.tests.") + +import unittest + + +class KeyModuleTest(unittest.TestCase): + def test_get_focused(self): + self.assertTrue(True) + + def test_get_mods(self): + self.assertTrue(True) + + def todo_test_get_pressed(self): + self.assertTrue(True) + + def test_name(self): + self.assertTrue(True) + + def todo_test_set_mods(self): + self.assertTrue(True) + + def test_set_repeat(self): + self.assertTrue(True) + + +if __name__ == "__main__": + unittest.main() diff --git a/venv/Lib/site-packages/pygame/tests/run_tests__tests/incomplete_todo/fake_3_test.py b/venv/Lib/site-packages/pygame/tests/run_tests__tests/incomplete_todo/fake_3_test.py new file mode 100644 index 0000000..3be92e1 --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/run_tests__tests/incomplete_todo/fake_3_test.py @@ -0,0 +1,39 @@ +if __name__ == "__main__": + import sys + import os + + pkg_dir = os.path.split( + os.path.split(os.path.split(os.path.abspath(__file__))[0])[0] + )[0] + parent_dir, pkg_name = os.path.split(pkg_dir) + is_pygame_pkg = pkg_name == "tests" and os.path.split(parent_dir)[1] == "pygame" + if not is_pygame_pkg: + sys.path.insert(0, parent_dir) +else: + is_pygame_pkg = __name__.startswith("pygame.tests.") + +import unittest + + +class KeyModuleTest(unittest.TestCase): + def test_get_focused(self): + self.assertTrue(True) + + def test_get_mods(self): + self.assertTrue(True) + + def test_get_pressed(self): + self.assertTrue(True) + + def test_name(self): + self.assertTrue(True) + + def test_set_mods(self): + self.assertTrue(True) + + def test_set_repeat(self): + self.assertTrue(True) + + +if __name__ == "__main__": + unittest.main() diff --git a/venv/Lib/site-packages/pygame/tests/run_tests__tests/infinite_loop/__init__.py b/venv/Lib/site-packages/pygame/tests/run_tests__tests/infinite_loop/__init__.py new file mode 100644 index 0000000..1bb8bf6 --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/run_tests__tests/infinite_loop/__init__.py @@ -0,0 +1 @@ +# empty diff --git a/venv/Lib/site-packages/pygame/tests/run_tests__tests/infinite_loop/__pycache__/__init__.cpython-39.pyc b/venv/Lib/site-packages/pygame/tests/run_tests__tests/infinite_loop/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d2be196caf6de83c58e8e10221e6edf6d1f9b490 GIT binary patch literal 225 zcmYk0F$%&!5Jgw85WzcG2^N}OL=Go!+-RX6 z{{QoaDMofWZ4vb9_I9n%_Zt4y2rv!iW{6m9M8C1VilScs;(3{mV9Qi6NUbHqf;e@? zf-TIEQsH7b>;oJx?H8W$7ti&9k5Vt>5>)XIrIdLZJP9=jZL;BSQW} zXSVghc?_TX1jZ0e3TEGHs@aGN8hR#}Vf)cZe8F~1cS@&#xZQ<^csMc?#w zRItjP&2vDOOe7|8e;5k;FKBA`lu=S9hMX*F*jprlK`PQ`ME5j*M>IF-{?gk> zET3`xXws9xlu)ACOS0PcT*?ELmr{O)e8{HnG{!aVGX+O<>&dP39vQ#d6YFyD&bynMI-xSS6x@N3%l|6YbkE&x+$fI13s-sDEXv)Lvw|qNu zd1HR5)lQ*yjmuh9)`KeRc3jFZl5Mx1m&3dSyc|_ky*^Zhk@v&WT0QXtgvwph$YHfJ zc1B;tq)^nxh(uOLbn2Cst{t8_EuZ1K3ZBb2}{g7N9M;0Kj<*I}xS z%#MHhPGrPg2>U;^u*k&r(99!no_%c%luQ5kjl=h|KZ9N(jegLfgcE*iCjJj|G(gNH z25t-Bp!z86otfbC3h)(oi3FBI=D4vnwNcHz849=NM#Y<|J(G1XBL9>D;oW*m4r_y%7;G#p1Qy%dcKKO-|)hiaSh>zUFc~&_e z*Q(j`9aoR?#`n~=3qHJN!+ZqPM6WJ(rOvHSYGqB?gfYiSWGK?y$@czAnDgDd#8<;7 zu2HseM|ra+_!zD)3MKd!*bM~;BfgM7`C0XO|xd}1_DhCn07$gfmPy&CNwl8gn(UEE>}bf^w-t zumivT3Lud{AyFR%7Nn0U&TB%6BuCcR{s$|vI>8fQt)ep0+LT$FV4qNj)@5B-A&J$r z-vPG0ibN$O)RnIOEHTW#Ah2{M1f$56XxtDmH+6Fb9`#-#Q4`KN5{~qa7SAlYG}Zb= zdgJBc4|Q z?ei$&+J7N+n8t~psQ5^R>4@ocAOh|`f5nFJsSMdL5dC;K@=s)R;=c(Fd>y3nal$(x z?@8?!uC#JjT51rnyv2&D6-3=20zT`KUi5%=$vo9anTvjGoGE0wiMq-`W2~Q8Ricb1Ln$`G$&SQAjxS2%`QfB~(Y>c8#8*rBc!-&jm^K_Qv r=ex->%h@jMcxGNLy$%2y!49e7jbDV2pSIP+YuLt3;u6PNx$WTJ5_O35 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/tests/run_tests__tests/infinite_loop/fake_1_test.py b/venv/Lib/site-packages/pygame/tests/run_tests__tests/infinite_loop/fake_1_test.py new file mode 100644 index 0000000..3e9e936 --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/run_tests__tests/infinite_loop/fake_1_test.py @@ -0,0 +1,40 @@ +if __name__ == "__main__": + import sys + import os + + pkg_dir = os.path.split( + os.path.split(os.path.split(os.path.abspath(__file__))[0])[0] + )[0] + parent_dir, pkg_name = os.path.split(pkg_dir) + is_pygame_pkg = pkg_name == "tests" and os.path.split(parent_dir)[1] == "pygame" + if not is_pygame_pkg: + sys.path.insert(0, parent_dir) +else: + is_pygame_pkg = __name__.startswith("pygame.tests.") + +import unittest + + +class KeyModuleTest(unittest.TestCase): + def test_get_focused(self): + self.assertTrue(True) + + def test_get_mods(self): + while True: + pass + + def test_get_pressed(self): + self.assertTrue(True) + + def test_name(self): + self.assertTrue(True) + + def test_set_mods(self): + self.assertTrue(True) + + def test_set_repeat(self): + self.assertTrue(True) + + +if __name__ == "__main__": + unittest.main() diff --git a/venv/Lib/site-packages/pygame/tests/run_tests__tests/infinite_loop/fake_2_test.py b/venv/Lib/site-packages/pygame/tests/run_tests__tests/infinite_loop/fake_2_test.py new file mode 100644 index 0000000..3be92e1 --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/run_tests__tests/infinite_loop/fake_2_test.py @@ -0,0 +1,39 @@ +if __name__ == "__main__": + import sys + import os + + pkg_dir = os.path.split( + os.path.split(os.path.split(os.path.abspath(__file__))[0])[0] + )[0] + parent_dir, pkg_name = os.path.split(pkg_dir) + is_pygame_pkg = pkg_name == "tests" and os.path.split(parent_dir)[1] == "pygame" + if not is_pygame_pkg: + sys.path.insert(0, parent_dir) +else: + is_pygame_pkg = __name__.startswith("pygame.tests.") + +import unittest + + +class KeyModuleTest(unittest.TestCase): + def test_get_focused(self): + self.assertTrue(True) + + def test_get_mods(self): + self.assertTrue(True) + + def test_get_pressed(self): + self.assertTrue(True) + + def test_name(self): + self.assertTrue(True) + + def test_set_mods(self): + self.assertTrue(True) + + def test_set_repeat(self): + self.assertTrue(True) + + +if __name__ == "__main__": + unittest.main() diff --git a/venv/Lib/site-packages/pygame/tests/run_tests__tests/print_stderr/__init__.py b/venv/Lib/site-packages/pygame/tests/run_tests__tests/print_stderr/__init__.py new file mode 100644 index 0000000..1bb8bf6 --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/run_tests__tests/print_stderr/__init__.py @@ -0,0 +1 @@ +# empty diff --git a/venv/Lib/site-packages/pygame/tests/run_tests__tests/print_stderr/__pycache__/__init__.cpython-39.pyc b/venv/Lib/site-packages/pygame/tests/run_tests__tests/print_stderr/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5148ae3363efa98527828cc2678870bb9b8dbcf0 GIT binary patch literal 224 zcmYjLy$ZrG5RTwb1mD3)aM11|qUa)si?|&e(Hs(MlaNa-b@yR>C08H8O%P0V&=0=f z;W*iDw?xFN)7>V~?{)b{BbG@dH=`)A7QM#mDttZv#gWGKdyh!*20gSwng9R* literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/tests/run_tests__tests/print_stderr/__pycache__/fake_2_test.cpython-39.pyc b/venv/Lib/site-packages/pygame/tests/run_tests__tests/print_stderr/__pycache__/fake_2_test.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..93e3950827b50d5fda9596e61704c7d428bcd9cd GIT binary patch literal 1657 zcmb_c%}(4f5VoD{ZZ>RSp;aqX+9D2>I25EFD^yWYsjAv?VSBM6Sq2*jS(4Pwf)@1# z2hM$h-6QYNL!Tqpo_K{y{h3Liq$(UL;V7Ryo{{~{XOCqN_ypRI`6rvl4k6#rsJAv4 ztMJ>e0GcQgGjpn_VtvYK*)z^G+jBA@*gI2yqVikoBUGYn$713I=ax!yUP=kAkXSDqTxk7+7x%j8*vU z3V~E@z7dD%k&eY-r26UMFg(!7LHI7(3~iL_r5kSc_++XDJ&NU5pevIv3mN*1&3Y2XjIl z2|arBmjtEg_0a#(#57?=(?Y;|Tgp&D2h1Y)Lt{Tx_8v@Ka(Hk92aLN#0#`a@M#H(O z*&2tNbhrq;MH=l=hXk(rTy6jR*Jyw-x43b202b~63j4UW`E>_y8Fz~WrpnB5VWTrG z^Mx9Phu7qP6}eu$9Vmzpg%7VtS+y|k2=Q?s`<2H8u%f|gHB$&(glU8s1gy&%;H@+b z0CZZkJnA`@U+Gz#Hdri$V~4h2sV&@0=DS71X8kBHT5{8tHau(FQ6H%BRu=CF6`8`% zq|s24IQDQ78S)^qqAFwob44>s@cAfwn@f}1!zkb7-XMu`6pDL2z%>aGNV0J8<*d;! qvneafTdCxDfsdA*2Y^JV$C`BE7h~+F>vZWHb!nIR%yVY$dh|Cg%!s4_ literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/tests/run_tests__tests/print_stderr/__pycache__/fake_3_test.cpython-39.pyc b/venv/Lib/site-packages/pygame/tests/run_tests__tests/print_stderr/__pycache__/fake_3_test.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..19ee82eca56789210c78b88e87b35541d569958d GIT binary patch literal 1721 zcmb_c&2Aev5GJ`RiCSxIwP_k8X$rL{3g}S#&|47{DIByY+WHdbLM*VLOj=&8yt^f- z2oiE@4mtM;q@!P<$f3`{YfpKF0{xlUl@kTAfffh_e&mp&*>64$DdRXI(Eb{HKKd;n z~6DGLm z>aGfMR+`N^2k-DUQLUVbNJsWpO(6b`BATxmB}Js^s;3~fh-wD0h`%GMqxdtTxQ-{g zzXW1$!|{cVSN%1i!2A&zc3(mkPh+N!G}usdo;^ z-2Z%j_*L>4Hfvcf?~rHwf_mAOv8tatXSh3}(hI@T^d zEl*}vs}C?I)REBT$8Shbi@xppe>5>|h-f+pShuwd4fMeD@hckVrLwnR>5{|UYdE0a zJ0$R0hstO;H+5%=!*x1rT(75rK^&RT6%-*>2h>TR*kzpzgQMl$Nj4g3li9PuIeym; z+*wwP?O;|#-ws0`*oF1&=InfHZs6Drhp1Po*sWD8;G*0^_8|bFJ-WPgg@)*LJ@L1T z`ad0@g*w86`2;_|DWaZ0eiI?>BOMjgOuk0B{DWur~el XAI8|CWM{7 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/tests/run_tests__tests/print_stderr/__pycache__/fake_4_test.cpython-39.pyc b/venv/Lib/site-packages/pygame/tests/run_tests__tests/print_stderr/__pycache__/fake_4_test.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..07a9e27568b01b28e0119bed1b6c34312c467b9d GIT binary patch literal 1671 zcmbVMPj4eN6t_K-#F=*5>>@3ySfD}(sR!B%r`2k;sAv%j}S8&zxVTd)^Qv$Y`<@RH2NuE z>{l|DTOW<5__<#YfEktx`^s=5#ysJ^7l{CI7F>oa*n#ex&(Uj(Eo0JKc=qNz6^Tsx z&^JLYO1qes=pAk`)5%2=LF9e}j{C0}4stFyDjw8uBF`XB;?J4s8TpbK3Gvy+ z4?(iI;QBMfmxDRu%!mWF({H3w=Q=BtdX4e0VbiI>)$TP%Bk5Mt6MYV|xb1iS((VyC zE;oV3Q~cax1YjrwO9T;l$&$bXCd5889n;0W)6z=1rf(v&duGk7V=qmNbT*p!OPGFL zn#mXrk;f6yxNbDY8)5tSxebKx*d;TlC&t1K*p(O_UhyW<&Vj8D?F7&Y9gL5!m|a8n z-(KxMO25HHm+GR>F8vH#UYAu`+42nXda7JKF_}(3{X$)oGsx9NX2#{kG<^ZZi}b5( zl)9{jk1KtY>l1KktID2NWzS9u{ioeK%VLZYIR&5 zO&plFC??X8@!5NSlfa9LcL}p_UE%c) z$?`A4^t~_z=KjN_^WVNj6!KX)m@?H1LMj{Xx@|6y9}f~ z)lE;2oVW3jJI=;PE$LPHi87gOqDou90;RE}Nn)79nNw|9E1YY(SwW9U6S-R3+FfMz zX(A^@R+CVPJVe~r=s_f#klxWH`aT+8XYz3?#}i5nw~c^-a4EX{gFl53e}ut+Kja}F Mh)Brb{sYPX0*NY*FaQ7m literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/tests/run_tests__tests/print_stderr/fake_2_test.py b/venv/Lib/site-packages/pygame/tests/run_tests__tests/print_stderr/fake_2_test.py new file mode 100644 index 0000000..3be92e1 --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/run_tests__tests/print_stderr/fake_2_test.py @@ -0,0 +1,39 @@ +if __name__ == "__main__": + import sys + import os + + pkg_dir = os.path.split( + os.path.split(os.path.split(os.path.abspath(__file__))[0])[0] + )[0] + parent_dir, pkg_name = os.path.split(pkg_dir) + is_pygame_pkg = pkg_name == "tests" and os.path.split(parent_dir)[1] == "pygame" + if not is_pygame_pkg: + sys.path.insert(0, parent_dir) +else: + is_pygame_pkg = __name__.startswith("pygame.tests.") + +import unittest + + +class KeyModuleTest(unittest.TestCase): + def test_get_focused(self): + self.assertTrue(True) + + def test_get_mods(self): + self.assertTrue(True) + + def test_get_pressed(self): + self.assertTrue(True) + + def test_name(self): + self.assertTrue(True) + + def test_set_mods(self): + self.assertTrue(True) + + def test_set_repeat(self): + self.assertTrue(True) + + +if __name__ == "__main__": + unittest.main() diff --git a/venv/Lib/site-packages/pygame/tests/run_tests__tests/print_stderr/fake_3_test.py b/venv/Lib/site-packages/pygame/tests/run_tests__tests/print_stderr/fake_3_test.py new file mode 100644 index 0000000..f59ad40 --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/run_tests__tests/print_stderr/fake_3_test.py @@ -0,0 +1,41 @@ +import sys + +if __name__ == "__main__": + import os + + pkg_dir = os.path.split( + os.path.split(os.path.split(os.path.abspath(__file__))[0])[0] + )[0] + parent_dir, pkg_name = os.path.split(pkg_dir) + is_pygame_pkg = pkg_name == "tests" and os.path.split(parent_dir)[1] == "pygame" + if not is_pygame_pkg: + sys.path.insert(0, parent_dir) +else: + is_pygame_pkg = __name__.startswith("pygame.tests.") + +import unittest + + +class KeyModuleTest(unittest.TestCase): + def test_get_focused(self): + self.assertTrue(True) + + def test_get_mods(self): + self.assertTrue(True) + + def test_get_pressed(self): + self.assertTrue(True) + + def test_name(self): + sys.stderr.write("jibberish messes things up\n") + self.assertTrue(False) + + def test_set_mods(self): + self.assertTrue(True) + + def test_set_repeat(self): + self.assertTrue(True) + + +if __name__ == "__main__": + unittest.main() diff --git a/venv/Lib/site-packages/pygame/tests/run_tests__tests/print_stderr/fake_4_test.py b/venv/Lib/site-packages/pygame/tests/run_tests__tests/print_stderr/fake_4_test.py new file mode 100644 index 0000000..1e75fea --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/run_tests__tests/print_stderr/fake_4_test.py @@ -0,0 +1,41 @@ +if __name__ == "__main__": + import sys + import os + + pkg_dir = os.path.split( + os.path.split(os.path.split(os.path.abspath(__file__))[0])[0] + )[0] + parent_dir, pkg_name = os.path.split(pkg_dir) + is_pygame_pkg = pkg_name == "tests" and os.path.split(parent_dir)[1] == "pygame" + if not is_pygame_pkg: + sys.path.insert(0, parent_dir) +else: + is_pygame_pkg = __name__.startswith("pygame.tests.") + +import unittest + + +class KeyModuleTest(unittest.TestCase): + def test_get_focused(self): + self.assertTrue(True) + + def test_get_mods(self): + self.assertTrue(True) + + def test_get_pressed(self): + self.assertTrue(False, "Some Jibberish") + + def test_name(self): + self.assertTrue(True) + + def test_set_mods(self): + if 1: + if 1: + assert False + + def test_set_repeat(self): + self.assertTrue(True) + + +if __name__ == "__main__": + unittest.main() diff --git a/venv/Lib/site-packages/pygame/tests/run_tests__tests/print_stdout/__init__.py b/venv/Lib/site-packages/pygame/tests/run_tests__tests/print_stdout/__init__.py new file mode 100644 index 0000000..1bb8bf6 --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/run_tests__tests/print_stdout/__init__.py @@ -0,0 +1 @@ +# empty diff --git a/venv/Lib/site-packages/pygame/tests/run_tests__tests/print_stdout/__pycache__/__init__.cpython-39.pyc b/venv/Lib/site-packages/pygame/tests/run_tests__tests/print_stdout/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4f38bfd2af9ea244ba3f272ae86e71f06b6bc993 GIT binary patch literal 224 zcmYjLy@~=c5RPE62)=`rV4>R|awyseVk33~Lo|cLb(4^pby<5K##gfS5$uG6%ia}t zAAG;XFuLFGsf4e=aGxcAw&g!Msmv0&o5ZNC8g({z72Ekw-nYdE?3f~hc1|-ai3{-o zLi8spq(PR-SPkDUENh)%5rly zA3(IfNK`9jJk+86ped|Bqo@w1jFK$WWYSZxHV-QX5s#h{)ltDaq5>Tq%)a&b+!@!8 zI-2ySgc8NJ$ZEF?ggBH*Cd3!WhisNDr>(PJC>Xq5jQ8ZBK8fmnt#YmHU|_Q`Fdo5g z9{^|qG7!#?$UDM4Omi<22dA_QrM23)ff;GAe5;4Mr^L)a_}BLv_v2UK zw6V-GY2zo_rYEtNAZhfJGP0_cMG|b z$~|r4T9x%mm31@9L^Tq1w_cbebFie!M{a#rrdr&qJZr_c>|>J0q*r70d~B zB=qFg9}-leH$(qN6VrwjO$Pz*Z6!kuJuu7Y7mdSQ*=sO$&f&&CIAGi*68Nn{VKkhZ zT5NFmmkwv4mq?>q>5#!yUux`s{Q?az<`Orq55U4bKw)n;Hoxcq&f_kTz+9C%E^Kt6 zrCVuGxOqYTzauy6w*v(cq72~`sj3#nJt1C?w2V?BJ@Ac^t^=Y4lEbtbt2J|Ov|A?~y literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/tests/run_tests__tests/print_stdout/__pycache__/fake_3_test.cpython-39.pyc b/venv/Lib/site-packages/pygame/tests/run_tests__tests/print_stdout/__pycache__/fake_3_test.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..118e1660b2e3de342cb5b7e4b7c21d12fd4abd33 GIT binary patch literal 1764 zcmb_c&yU+g6rLG7iQ|oT1N4VVOBGcDX%FlkxS>YWo3Ki;#mG*vee2*&a^^JbpM-}~OolR@A!Y`+ga8vW`p z_6r%?t&7GJe9g}YiYY#4Ap@>ND)fum7NGz!b5`zK*n;+&ueoCP*fxfpjb~@gBN2LG z7rM$xMXopV9(ud?m};dW^uaeTf#Lppih;KloMk@nRZrpGpnRbI5L064!f@~3U*p~aeOY5ERL&|1!K)Cj?-bgSWe|RTn0^lR4*Nk z>67gy(0GEcd5i!o!~jE~P?F~?bd;l9>|NDTZR}eOt+1`S%167S_EZmhPX$P4zY4yF z<+r&i=P*PbW1?~0Xp9+QC-|Cugdf-nqgZo{g*{_e;&gb$D_&;i8FTmPr$R4kopE5fwV0L28$=v8766^z^HEkzYa@FA_D+7t81ZvWw`O zWE7di!pDUir*aA=YE(I{RXNsW7T2S=>5dDXWEQtnd1;R)GKKh)dgZ8CR(MHzcS<-*){sn&>v}s5=C7ZfhAD=%HB!f73Y6mAQ*k*BtKe;6Q%6 z3A~RxST^G;%s!eVV%oAI6>@3ySfD}(sR!B%r`2k;sAv%j2prANe)fy~dq2Ntm8J=S_WSlnqn{!| zenn%s^}%=wpZf*C5KRhZUumk@mYE-hR+!#Wn#$Xx`w?)5*VZ+{ha8Y<}ZonCOzBu zArhMlu0Nafaxf>9Xm&t$`VE)zT;-*duOS{XY&zaJ?_N_dM7N%vsB<$*+kQ7J?H-}y za${gTh0i?(Fa%^Ef+3NYL_|8$G4!$S=q~h~mX_%1zD~gI={3C$J=ZDF*=W))&GhR^ zPsZjDcpM>(>xN^v5wZ`T+W`2EToMg>LM-HfT(RNd6>SpboU#7UP7GMFGvnhcV%Na^ zw^#d*vTtC~WvVQd%RV!%@Kv4FwmLI~pGxN^I#=1JU&xDUW(s+c>v454&0d)DMfO!b z%3SWv$F({t)QNFftIA$bWzSAZ8Ah`0_G+7#9=6og#P1!e!pKj;%5FVv2IwhIjF-pN z(Zm`37RH1+5;}YDZxRI2mtFshCbkPZ+8zStZIGdbbugRshQ@iN-2<4q=J3uP9MErt zKn#Bjmok7sdnuY>V&b*zM8jvZjf3jkY(LLOBV%)SdN-pt!qnElMe403Qg;cna9!c` z56SW`!t{eMCFK6YrSspuMHKW|IT$lF2!bkW>iBc=Jro6q!G_OT{qMdG2U&qKzkhRb zG`sCOuKiX{|NmichOlvCYigtXhc^`H?A=>}f8#l9UlLS9$|iv~CDbsC*QNY+qQ>ot zO<_liwQDyKFk$RHg!>3srAvV7*$x0MI)l1} zPX(WpxksS{KLp%Y;DIEY7~jz)`XQQ7XZ&$1#}iBpw+#S+P|mvagFhK#f5g#%KBO@n Mu!QmG{sT_`0?03qKL7v# literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/tests/run_tests__tests/print_stdout/fake_2_test.py b/venv/Lib/site-packages/pygame/tests/run_tests__tests/print_stdout/fake_2_test.py new file mode 100644 index 0000000..3be92e1 --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/run_tests__tests/print_stdout/fake_2_test.py @@ -0,0 +1,39 @@ +if __name__ == "__main__": + import sys + import os + + pkg_dir = os.path.split( + os.path.split(os.path.split(os.path.abspath(__file__))[0])[0] + )[0] + parent_dir, pkg_name = os.path.split(pkg_dir) + is_pygame_pkg = pkg_name == "tests" and os.path.split(parent_dir)[1] == "pygame" + if not is_pygame_pkg: + sys.path.insert(0, parent_dir) +else: + is_pygame_pkg = __name__.startswith("pygame.tests.") + +import unittest + + +class KeyModuleTest(unittest.TestCase): + def test_get_focused(self): + self.assertTrue(True) + + def test_get_mods(self): + self.assertTrue(True) + + def test_get_pressed(self): + self.assertTrue(True) + + def test_name(self): + self.assertTrue(True) + + def test_set_mods(self): + self.assertTrue(True) + + def test_set_repeat(self): + self.assertTrue(True) + + +if __name__ == "__main__": + unittest.main() diff --git a/venv/Lib/site-packages/pygame/tests/run_tests__tests/print_stdout/fake_3_test.py b/venv/Lib/site-packages/pygame/tests/run_tests__tests/print_stdout/fake_3_test.py new file mode 100644 index 0000000..467c725 --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/run_tests__tests/print_stdout/fake_3_test.py @@ -0,0 +1,42 @@ +import sys + +if __name__ == "__main__": + import os + + pkg_dir = os.path.split( + os.path.split(os.path.split(os.path.abspath(__file__))[0])[0] + )[0] + parent_dir, pkg_name = os.path.split(pkg_dir) + is_pygame_pkg = pkg_name == "tests" and os.path.split(parent_dir)[1] == "pygame" + if not is_pygame_pkg: + sys.path.insert(0, parent_dir) +else: + is_pygame_pkg = __name__.startswith("pygame.tests.") + +import unittest + + +class KeyModuleTest(unittest.TestCase): + def test_get_focused(self): + self.assertTrue(True) + + def test_get_mods(self): + self.assertTrue(True) + + def test_get_pressed(self): + sys.stdout.write("jibberish ruins everything\n") + self.assertTrue(False) + + def test_name(self): + sys.stdout.write("forgot to remove debug crap\n") + self.assertTrue(True) + + def test_set_mods(self): + self.assertTrue(True) + + def test_set_repeat(self): + self.assertTrue(True) + + +if __name__ == "__main__": + unittest.main() diff --git a/venv/Lib/site-packages/pygame/tests/run_tests__tests/print_stdout/fake_4_test.py b/venv/Lib/site-packages/pygame/tests/run_tests__tests/print_stdout/fake_4_test.py new file mode 100644 index 0000000..1e75fea --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/run_tests__tests/print_stdout/fake_4_test.py @@ -0,0 +1,41 @@ +if __name__ == "__main__": + import sys + import os + + pkg_dir = os.path.split( + os.path.split(os.path.split(os.path.abspath(__file__))[0])[0] + )[0] + parent_dir, pkg_name = os.path.split(pkg_dir) + is_pygame_pkg = pkg_name == "tests" and os.path.split(parent_dir)[1] == "pygame" + if not is_pygame_pkg: + sys.path.insert(0, parent_dir) +else: + is_pygame_pkg = __name__.startswith("pygame.tests.") + +import unittest + + +class KeyModuleTest(unittest.TestCase): + def test_get_focused(self): + self.assertTrue(True) + + def test_get_mods(self): + self.assertTrue(True) + + def test_get_pressed(self): + self.assertTrue(False, "Some Jibberish") + + def test_name(self): + self.assertTrue(True) + + def test_set_mods(self): + if 1: + if 1: + assert False + + def test_set_repeat(self): + self.assertTrue(True) + + +if __name__ == "__main__": + unittest.main() diff --git a/venv/Lib/site-packages/pygame/tests/run_tests__tests/run_tests__test.py b/venv/Lib/site-packages/pygame/tests/run_tests__tests/run_tests__test.py new file mode 100644 index 0000000..533f7a0 --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/run_tests__tests/run_tests__test.py @@ -0,0 +1,145 @@ +################################################################################ + +import subprocess, os, sys, re, difflib + +################################################################################ + +IGNORE = (".svn", "infinite_loop") +NORMALIZERS = ( + (r"Ran (\d+) tests in (\d+\.\d+)s", "Ran \\1 tests in X.XXXs"), + (r'File ".*?([^/\\.]+\.py)"', 'File "\\1"'), +) + +################################################################################ + + +def norm_result(result): + "normalize differences, such as timing between output" + for normalizer, replacement in NORMALIZERS: + if hasattr(normalizer, "__call__"): + result = normalizer(result) + else: + result = re.sub(normalizer, replacement, result) + + return result + + +def call_proc(cmd, cd=None): + proc = subprocess.Popen( + cmd, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + cwd=cd, + universal_newlines=True, + ) + if proc.wait(): + print("%s %s" % (cmd, proc.wait())) + raise Exception(proc.stdout.read()) + + return proc.stdout.read() + + +################################################################################ + +unnormed_diff = "-u" in sys.argv +verbose = "-v" in sys.argv or unnormed_diff +if "-h" in sys.argv or "--help" in sys.argv: + sys.exit( + "\nCOMPARES OUTPUT OF SINGLE VS SUBPROCESS MODE OF RUN_TESTS.PY\n\n" + "-v, to output diffs even on success\n" + "-u, to output diffs of unnormalized tests\n\n" + "Each line of a Differ delta begins with a two-letter code:\n\n" + " '- ' line unique to sequence 1\n" + " '+ ' line unique to sequence 2\n" + " ' ' line common to both sequences\n" + " '? ' line not present in either input sequence\n" + ) + +main_dir = os.path.split(os.path.abspath(sys.argv[0]))[0] +trunk_dir = os.path.normpath(os.path.join(main_dir, "../../")) + +test_suite_dirs = [ + x + for x in os.listdir(main_dir) + if os.path.isdir(os.path.join(main_dir, x)) and x not in IGNORE +] + + +################################################################################ + + +def assert_on_results(suite, single, sub): + test = globals().get("%s_test" % suite) + if hasattr(test, "__call_"): + test(suite, single, sub) + print("assertions on %s OK" % (suite,)) + + +# Don't modify tests in suites below. These assertions are in place to make sure +# that tests are actually being ran + + +def all_ok_test(uite, *args): + for results in args: + assert "Ran 36 tests" in results # some tests are runing + assert "OK" in results # OK + + +def failures1_test(suite, *args): + for results in args: + assert "FAILED (failures=2)" in results + assert "Ran 18 tests" in results + + +################################################################################ +# Test that output is the same in single process and subprocess modes +# + +base_cmd = [sys.executable, "run_tests.py", "-i"] + +cmd = base_cmd + ["-n", "-f"] +sub_cmd = base_cmd + ["-f"] +time_out_cmd = base_cmd + ["-t", "4", "-f", "infinite_loop"] + +passes = 0 +failed = False + +for suite in test_suite_dirs: + single = call_proc(cmd + [suite], trunk_dir) + subs = call_proc(sub_cmd + [suite], trunk_dir) + + normed_single, normed_subs = map(norm_result, (single, subs)) + + failed = normed_single != normed_subs + if failed: + print("%s suite comparison FAILED\n" % (suite,)) + else: + passes += 1 + print("%s suite comparison OK" % (suite,)) + + assert_on_results(suite, single, subs) + + if verbose or failed: + print("difflib.Differ().compare(single, suprocessed):\n") + print( + "".join( + list( + difflib.Differ().compare( + (unnormed_diff and single or normed_single).splitlines(1), + (unnormed_diff and subs or normed_subs).splitlines(1), + ) + ) + ) + ) + +sys.stdout.write("infinite_loop suite (subprocess mode timeout) ") +loop_test = call_proc(time_out_cmd, trunk_dir) +assert "successfully terminated" in loop_test +passes += 1 +print("OK") + +print("\n%s/%s suites pass" % (passes, len(test_suite_dirs) + 1)) + +print("\n-h for help") + +################################################################################ diff --git a/venv/Lib/site-packages/pygame/tests/run_tests__tests/timeout/__init__.py b/venv/Lib/site-packages/pygame/tests/run_tests__tests/timeout/__init__.py new file mode 100644 index 0000000..1bb8bf6 --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/run_tests__tests/timeout/__init__.py @@ -0,0 +1 @@ +# empty diff --git a/venv/Lib/site-packages/pygame/tests/run_tests__tests/timeout/__pycache__/__init__.cpython-39.pyc b/venv/Lib/site-packages/pygame/tests/run_tests__tests/timeout/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7d87f293176a03e6f4a7eb396213d9ad7a2ef997 GIT binary patch literal 219 zcmYjLI|{-;5M9AS1n*!aSZI0?QM3`nM(hTL)eK>c*fgM7`C0XO|xd}1_DhCm^dKqz$$S>6B-&4LclI77b}wG&EA%!O@i&N>cnk3 zaOM}Z$NdKm{El2X?Jpql@j7W)5ZeK1j`G;A{m6da#~(Zhd<5mk>f_y02cd5^sFo%K zoAB$e01^ol6ZJ`8L3)_tq9&9`a^#HNf3PO&6FdRdGO8kNOqq=d4hi*WQ#OSYlT=On zJz%@bNYr9Ned+7Z62ts+0!wc~FiL!h#w`JJQ@>CU(BKsk4dI<3;mP1={?wrhQ>|ZQ zFm6u}MuP01wPx-y*5^^e*ahT+w)2{i+UN@m0j+1F1KyV>L0PXCL+g8%SSTm9l7EG=&dwL(GX5)Sd`H&U_xck)wC181!TpbnICf zvtrw@BWMeLJrD2^jgbI9As4iR&dGN79OpjQS}N030|}9BO{+=d@tq) zQir80ox+ul8YHY}v9juzs4vrj>Fo1ZvZqDodN#`2mc$OEVf*RcKudAUreiHc_~gM~ z*%y9SssCe#s>6(`VZk2R!hsT65az)j8U0k~JJ2=LaPJxomUn{!E`7+9ge?=x6%E(< zFs0t0jAr3O0;hbXvi{vGJg}S_T)5l-4d=ib`>?Y3RU0tl-JpPlB6B;jl9}Y@QANW2 zEAqc&ZkNx7HH5L;hX+|eVQlT_z!#?4_~(^)Svd4uojB8C@jKk9)r+Q{MqCL)#l8CNnf zMccETRv`@{&B{B>pf9gSiG4Y8UmLEB9!BPndV?e~)+p+A0k=3XtjOH8k7h-Fkxg;4 nyp7V1=k~qQs{oJ)_DCH+`b7x&={jw^f?eDuKJlET+aCT6an^>0 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/tests/run_tests__tests/timeout/__pycache__/sleep_test.cpython-39.pyc b/venv/Lib/site-packages/pygame/tests/run_tests__tests/timeout/__pycache__/sleep_test.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..692e3488497f79750b021afd9a7d4710f41cfb06 GIT binary patch literal 1024 zcmZWnPiqu06i+gbZU5g?G5h+F3gI(|_B9#gvYA>#rFc7Ajbe+z0W}0NWY^fLR z!Ly%W=jiwF;K5IjtEYYi!9OoE6;^y9?_XZtd-=V@VHhBwpLg#ad?N^bcg8C9!PteZ zzXFp;pp>YO0t=F1h8sy3k>to*`v38c?AEx3s7iIxKaxmnP35VEk5>umiQ5gXZ z$Z&bRMi>e58jbpva()~qIp>$~F0^kuMrxxkF&L~{E@ttuJPTX7(;V$gUEnGKTrD&= zK#>UGK#aIXE)esC2W5O4zL1Mog{U$)f&5dK{x7-f9_&5X`T;P5mZ(Mo-$L(jtDoZ( zscq09X^k;D8Jwdf5uVcpas~Eha1m&GSNR|&BhUIKIhMAgGbu|O#9B*bCaRJnVtp;M zL)+J;D7lOJjMN(3`tg46Ve|&#bQI@#tfQw=rw|jBsyLFVS#WJCk;KuH=X_qA$&}9% zkrnerbSm@H=w)&c>BPwUWjsyenbc8>+ql7Ptg4(h8gIqeRW2$sZaQpyJLSR-T@0T| z!w-vTrKPwDooNaT;elJ^?9M-6He*@6un%~{SaTR1=Qe-=H^75F;QXYDv-U)Vkg|FA z3L7|I2bi0scB7%Vu}2$f9W3kVg|?*7)-Pl87T_(j#MoYZpc@{tGt~?79&0Bal_-r@H-F$4IO{|QbC+01qRh}4!hU!9PMkk=|#SrHDv%dSb uE1kOmD%ZZHkJ<-6cE3z-0izfe>Ef;5gpgmpH^jHGkB1~6lu&P@Pw^iuND&YK literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/tests/run_tests__tests/timeout/fake_2_test.py b/venv/Lib/site-packages/pygame/tests/run_tests__tests/timeout/fake_2_test.py new file mode 100644 index 0000000..3be92e1 --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/run_tests__tests/timeout/fake_2_test.py @@ -0,0 +1,39 @@ +if __name__ == "__main__": + import sys + import os + + pkg_dir = os.path.split( + os.path.split(os.path.split(os.path.abspath(__file__))[0])[0] + )[0] + parent_dir, pkg_name = os.path.split(pkg_dir) + is_pygame_pkg = pkg_name == "tests" and os.path.split(parent_dir)[1] == "pygame" + if not is_pygame_pkg: + sys.path.insert(0, parent_dir) +else: + is_pygame_pkg = __name__.startswith("pygame.tests.") + +import unittest + + +class KeyModuleTest(unittest.TestCase): + def test_get_focused(self): + self.assertTrue(True) + + def test_get_mods(self): + self.assertTrue(True) + + def test_get_pressed(self): + self.assertTrue(True) + + def test_name(self): + self.assertTrue(True) + + def test_set_mods(self): + self.assertTrue(True) + + def test_set_repeat(self): + self.assertTrue(True) + + +if __name__ == "__main__": + unittest.main() diff --git a/venv/Lib/site-packages/pygame/tests/run_tests__tests/timeout/sleep_test.py b/venv/Lib/site-packages/pygame/tests/run_tests__tests/timeout/sleep_test.py new file mode 100644 index 0000000..bab528a --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/run_tests__tests/timeout/sleep_test.py @@ -0,0 +1,30 @@ +if __name__ == "__main__": + import sys + import os + + pkg_dir = os.path.split( + os.path.split(os.path.split(os.path.abspath(__file__))[0])[0] + )[0] + parent_dir, pkg_name = os.path.split(pkg_dir) + is_pygame_pkg = pkg_name == "tests" and os.path.split(parent_dir)[1] == "pygame" + if not is_pygame_pkg: + sys.path.insert(0, parent_dir) +else: + is_pygame_pkg = __name__.startswith("pygame.tests.") + +import unittest + +import time + + +class KeyModuleTest(unittest.TestCase): + def test_get_focused(self): + stop_time = time.time() + 10.0 + while time.time() < stop_time: + time.sleep(1) + + self.assertTrue(True) + + +if __name__ == "__main__": + unittest.main() diff --git a/venv/Lib/site-packages/pygame/tests/rwobject_test.py b/venv/Lib/site-packages/pygame/tests/rwobject_test.py new file mode 100644 index 0000000..31723ae --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/rwobject_test.py @@ -0,0 +1,139 @@ +import pathlib +import unittest + +from pygame import encode_string, encode_file_path + + +class RWopsEncodeStringTest(unittest.TestCase): + global getrefcount + + def test_obj_None(self): + encoded_string = encode_string(None) + + self.assertIsNone(encoded_string) + + def test_returns_bytes(self): + u = "Hello" + encoded_string = encode_string(u) + + self.assertIsInstance(encoded_string, bytes) + + def test_obj_bytes(self): + b = b"encyclop\xE6dia" + encoded_string = encode_string(b, "ascii", "strict") + + self.assertIs(encoded_string, b) + + def test_encode_unicode(self): + u = "\u00DEe Olde Komp\u00FCter Shoppe" + b = u.encode("utf-8") + self.assertEqual(encode_string(u, "utf-8"), b) + + def test_error_fowarding(self): + self.assertRaises(SyntaxError, encode_string) + + def test_errors(self): + u = "abc\u0109defg\u011Dh\u0125ij\u0135klmnoprs\u015Dtu\u016Dvz" + b = u.encode("ascii", "ignore") + self.assertEqual(encode_string(u, "ascii", "ignore"), b) + + def test_encoding_error(self): + u = "a\x80b" + encoded_string = encode_string(u, "ascii", "strict") + + self.assertIsNone(encoded_string) + + def test_check_defaults(self): + u = "a\u01F7b" + b = u.encode("unicode_escape", "backslashreplace") + encoded_string = encode_string(u) + + self.assertEqual(encoded_string, b) + + def test_etype(self): + u = "a\x80b" + self.assertRaises(SyntaxError, encode_string, u, "ascii", "strict", SyntaxError) + + def test_etype__invalid(self): + """Ensures invalid etypes are properly handled.""" + + for etype in ("SyntaxError", self): + self.assertRaises(TypeError, encode_string, "test", etype=etype) + + def test_string_with_null_bytes(self): + b = b"a\x00b\x00c" + encoded_string = encode_string(b, etype=SyntaxError) + encoded_decode_string = encode_string(b.decode(), "ascii", "strict") + + self.assertIs(encoded_string, b) + self.assertEqual(encoded_decode_string, b) + + try: + from sys import getrefcount as _g + + getrefcount = _g # This nonsense is for Python 3.x + except ImportError: + pass + else: + + def test_refcount(self): + bpath = b" This is a string that is not cached."[1:] + upath = bpath.decode("ascii") + before = getrefcount(bpath) + bpath = encode_string(bpath) + self.assertEqual(getrefcount(bpath), before) + bpath = encode_string(upath) + self.assertEqual(getrefcount(bpath), before) + + def test_smp(self): + utf_8 = b"a\xF0\x93\x82\xA7b" + u = "a\U000130A7b" + b = encode_string(u, "utf-8", "strict", AssertionError) + self.assertEqual(b, utf_8) + + def test_pathlib_obj(self): + """Test loading string representation of pathlib object""" + """ + We do this because pygame functions internally use pg_EncodeString + to decode the filenames passed to them. So if we test that here, we + can safely assume that all those functions do not have any issues + with pathlib objects + """ + encoded = encode_string(pathlib.PurePath("foo"), "utf-8") + self.assertEqual(encoded, b"foo") + + encoded = encode_string(pathlib.Path("baz")) + self.assertEqual(encoded, b"baz") + + +class RWopsEncodeFilePathTest(unittest.TestCase): + # Most tests can be skipped since RWopsEncodeFilePath wraps + # RWopsEncodeString + def test_encoding(self): + u = "Hello" + encoded_file_path = encode_file_path(u) + + self.assertIsInstance(encoded_file_path, bytes) + + def test_error_fowarding(self): + self.assertRaises(SyntaxError, encode_file_path) + + def test_path_with_null_bytes(self): + b = b"a\x00b\x00c" + encoded_file_path = encode_file_path(b) + + self.assertIsNone(encoded_file_path) + + def test_etype(self): + b = b"a\x00b\x00c" + self.assertRaises(TypeError, encode_file_path, b, TypeError) + + def test_etype__invalid(self): + """Ensures invalid etypes are properly handled.""" + + for etype in ("SyntaxError", self): + self.assertRaises(TypeError, encode_file_path, "test", etype) + + +if __name__ == "__main__": + unittest.main() diff --git a/venv/Lib/site-packages/pygame/tests/scrap_tags.py b/venv/Lib/site-packages/pygame/tests/scrap_tags.py new file mode 100644 index 0000000..17a82ff --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/scrap_tags.py @@ -0,0 +1,26 @@ +__tags__ = ["ignore", "subprocess_ignore"] + +# TODO: make scrap_test.py work +# This test used to work only on linux and windows. +# Currently it only work in windows, and in linux it throws: +# `pygame.error: content could not be placed in clipboard.` +# The old test and tags kept here for reference when fixing. + +# import sys +# +# exclude = False +# +# if sys.platform == "win32" or sys.platform.startswith("linux"): +# try: +# import pygame +# +# pygame.scrap._NOT_IMPLEMENTED_ +# except AttributeError: +# pass +# else: +# exclude = True +# else: +# exclude = True +# +# if exclude: +# __tags__.extend(["ignore", "subprocess_ignore"]) diff --git a/venv/Lib/site-packages/pygame/tests/scrap_test.py b/venv/Lib/site-packages/pygame/tests/scrap_test.py new file mode 100644 index 0000000..6b7f6fa --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/scrap_test.py @@ -0,0 +1,301 @@ +import os +import sys + +if os.environ.get("SDL_VIDEODRIVER") == "dummy": + __tags__ = ("ignore", "subprocess_ignore") +import unittest +from pygame.tests.test_utils import trunk_relative_path + +import pygame +from pygame import scrap + + +class ScrapModuleTest(unittest.TestCase): + @classmethod + def setUpClass(cls): + pygame.display.init() + pygame.display.set_mode((1, 1)) + scrap.init() + + @classmethod + def tearDownClass(cls): + # scrap.quit() # Does not exist! + pygame.display.quit() + + def test_init(self): + """Ensures scrap module still initialized after multiple init calls.""" + scrap.init() + scrap.init() + + self.assertTrue(scrap.get_init()) + + def test_init__reinit(self): + """Ensures reinitializing the scrap module doesn't clear its data.""" + data_type = pygame.SCRAP_TEXT + expected_data = b"test_init__reinit" + scrap.put(data_type, expected_data) + + scrap.init() + + self.assertEqual(scrap.get(data_type), expected_data) + + def test_get_init(self): + """Ensures get_init gets the init state.""" + self.assertTrue(scrap.get_init()) + + def todo_test_contains(self): + """Ensures contains works as expected.""" + self.fail() + + def todo_test_get(self): + """Ensures get works as expected.""" + self.fail() + + def test_get__owned_empty_type(self): + """Ensures get works when there is no data of the requested type + in the clipboard and the clipboard is owned by the pygame application. + """ + # Use a unique data type identifier to ensure there is no preexisting + # data. + DATA_TYPE = "test_get__owned_empty_type" + + if scrap.lost(): + # Try to acquire the clipboard. + scrap.put(pygame.SCRAP_TEXT, b"text to clipboard") + + if scrap.lost(): + self.skipTest("requires the pygame application to own the clipboard") + + data = scrap.get(DATA_TYPE) + + self.assertIsNone(data) + + def todo_test_get_types(self): + """Ensures get_types works as expected.""" + self.fail() + + def todo_test_lost(self): + """Ensures lost works as expected.""" + self.fail() + + def test_set_mode(self): + """Ensures set_mode works as expected.""" + scrap.set_mode(pygame.SCRAP_SELECTION) + scrap.set_mode(pygame.SCRAP_CLIPBOARD) + + self.assertRaises(ValueError, scrap.set_mode, 1099) + + def test_put__text(self): + """Ensures put can place text into the clipboard.""" + scrap.put(pygame.SCRAP_TEXT, b"Hello world") + + self.assertEqual(scrap.get(pygame.SCRAP_TEXT), b"Hello world") + + scrap.put(pygame.SCRAP_TEXT, b"Another String") + + self.assertEqual(scrap.get(pygame.SCRAP_TEXT), b"Another String") + + @unittest.skipIf("pygame.image" not in sys.modules, "requires pygame.image module") + def test_put__bmp_image(self): + """Ensures put can place a BMP image into the clipboard.""" + sf = pygame.image.load(trunk_relative_path("examples/data/asprite.bmp")) + expected_string = pygame.image.tostring(sf, "RGBA") + scrap.put(pygame.SCRAP_BMP, expected_string) + + self.assertEqual(scrap.get(pygame.SCRAP_BMP), expected_string) + + def test_put(self): + """Ensures put can place data into the clipboard + when using a user defined type identifier. + """ + DATA_TYPE = "arbitrary buffer" + + scrap.put(DATA_TYPE, b"buf") + r = scrap.get(DATA_TYPE) + + self.assertEqual(r, b"buf") + + +class ScrapModuleClipboardNotOwnedTest(unittest.TestCase): + """Test the scrap module's functionality when the pygame application is + not the current owner of the clipboard. + + A separate class is used to prevent tests that acquire the clipboard from + interfering with these tests. + """ + + @classmethod + def setUpClass(cls): + pygame.display.init() + pygame.display.set_mode((1, 1)) + scrap.init() + + @classmethod + def tearDownClass(cls): + # scrap.quit() # Does not exist! + pygame.quit() + pygame.display.quit() + + def _skip_if_clipboard_owned(self): + # Skip test if the pygame application owns the clipboard. Currently, + # there is no way to give up ownership. + if not scrap.lost(): + self.skipTest("requires the pygame application to not own the clipboard") + + def test_get__not_owned(self): + """Ensures get works when there is no data of the requested type + in the clipboard and the clipboard is not owned by the pygame + application. + """ + self._skip_if_clipboard_owned() + + # Use a unique data type identifier to ensure there is no preexisting + # data. + DATA_TYPE = "test_get__not_owned" + + data = scrap.get(DATA_TYPE) + + self.assertIsNone(data) + + def test_get_types__not_owned(self): + """Ensures get_types works when the clipboard is not owned + by the pygame application. + """ + self._skip_if_clipboard_owned() + + data_types = scrap.get_types() + + self.assertIsInstance(data_types, list) + + def test_contains__not_owned(self): + """Ensures contains works when the clipboard is not owned + by the pygame application. + """ + self._skip_if_clipboard_owned() + + # Use a unique data type identifier to ensure there is no preexisting + # data. + DATA_TYPE = "test_contains__not_owned" + + contains = scrap.contains(DATA_TYPE) + + self.assertFalse(contains) + + def test_lost__not_owned(self): + """Ensures lost works when the clipboard is not owned + by the pygame application. + """ + self._skip_if_clipboard_owned() + + lost = scrap.lost() + + self.assertTrue(lost) + + +class X11InteractiveTest(unittest.TestCase): + __tags__ = ["ignore", "subprocess_ignore"] + try: + pygame.display.init() + except Exception: + pass + else: + if pygame.display.get_driver() == "x11": + __tags__ = ["interactive"] + pygame.display.quit() + + def test_issue_208(self): + """PATCH: pygame.scrap on X11, fix copying into PRIMARY selection + + Copying into theX11 PRIMARY selection (mouse copy/paste) would not + work due to a confusion between content type and clipboard type. + + """ + + from pygame import display, event, freetype + from pygame.locals import SCRAP_SELECTION, SCRAP_TEXT + from pygame.locals import KEYDOWN, K_y, QUIT + + success = False + freetype.init() + font = freetype.Font(None, 24) + display.init() + display.set_caption("Interactive X11 Paste Test") + screen = display.set_mode((600, 200)) + screen.fill(pygame.Color("white")) + text = "Scrap put() succeeded." + msg = ( + "Some text has been placed into the X11 clipboard." + " Please click the center mouse button in an open" + " text window to retrieve it." + '\n\nDid you get "{}"? (y/n)' + ).format(text) + word_wrap(screen, msg, font, 6) + display.flip() + event.pump() + scrap.init() + scrap.set_mode(SCRAP_SELECTION) + scrap.put(SCRAP_TEXT, text.encode("UTF-8")) + while True: + e = event.wait() + if e.type == QUIT: + break + if e.type == KEYDOWN: + success = e.key == K_y + break + pygame.display.quit() + self.assertTrue(success) + + +def word_wrap(surf, text, font, margin=0, color=(0, 0, 0)): + font.origin = True + surf_width, surf_height = surf.get_size() + width = surf_width - 2 * margin + height = surf_height - 2 * margin + line_spacing = int(1.25 * font.get_sized_height()) + x, y = margin, margin + line_spacing + space = font.get_rect(" ") + for word in iwords(text): + if word == "\n": + x, y = margin, y + line_spacing + else: + bounds = font.get_rect(word) + if x + bounds.width + bounds.x >= width: + x, y = margin, y + line_spacing + if x + bounds.width + bounds.x >= width: + raise ValueError("word too wide for the surface") + if y + bounds.height - bounds.y >= height: + raise ValueError("text to long for the surface") + font.render_to(surf, (x, y), None, color) + x += bounds.width + space.width + return x, y + + +def iwords(text): + # r"\n|[^ ]+" + # + head = 0 + tail = head + end = len(text) + while head < end: + if text[head] == " ": + head += 1 + tail = head + 1 + elif text[head] == "\n": + head += 1 + yield "\n" + tail = head + 1 + elif tail == end: + yield text[head:] + head = end + elif text[tail] == "\n": + yield text[head:tail] + head = tail + elif text[tail] == " ": + yield text[head:tail] + head = tail + else: + tail += 1 + + +if __name__ == "__main__": + unittest.main() diff --git a/venv/Lib/site-packages/pygame/tests/sndarray_tags.py b/venv/Lib/site-packages/pygame/tests/sndarray_tags.py new file mode 100644 index 0000000..68fa7a5 --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/sndarray_tags.py @@ -0,0 +1,12 @@ +__tags__ = ["array"] + +exclude = False + +try: + import pygame.mixer + import numpy +except ImportError: + exclude = True + +if exclude: + __tags__.extend(("ignore", "subprocess_ignore")) diff --git a/venv/Lib/site-packages/pygame/tests/sndarray_test.py b/venv/Lib/site-packages/pygame/tests/sndarray_test.py new file mode 100644 index 0000000..afa94ec --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/sndarray_test.py @@ -0,0 +1,155 @@ +import unittest + +from numpy import int8, int16, uint8, uint16, float32, array, alltrue + +import pygame +import pygame.sndarray + + +class SndarrayTest(unittest.TestCase): + array_dtypes = {8: uint8, -8: int8, 16: uint16, -16: int16, 32: float32} + + def _assert_compatible(self, arr, size): + dtype = self.array_dtypes[size] + self.assertEqual(arr.dtype, dtype) + + def test_array(self): + def check_array(size, channels, test_data): + try: + pygame.mixer.init(22050, size, channels, allowedchanges=0) + except pygame.error: + # Not all sizes are supported on all systems. + return + try: + __, sz, __ = pygame.mixer.get_init() + if sz == size: + srcarr = array(test_data, self.array_dtypes[size]) + snd = pygame.sndarray.make_sound(srcarr) + arr = pygame.sndarray.array(snd) + self._assert_compatible(arr, size) + self.assertTrue( + alltrue(arr == srcarr), + "size: %i\n%s\n%s" % (size, arr, test_data), + ) + finally: + pygame.mixer.quit() + + check_array(8, 1, [0, 0x0F, 0xF0, 0xFF]) + check_array(8, 2, [[0, 0x80], [0x2D, 0x41], [0x64, 0xA1], [0xFF, 0x40]]) + check_array(16, 1, [0, 0x00FF, 0xFF00, 0xFFFF]) + check_array( + 16, 2, [[0, 0xFFFF], [0xFFFF, 0], [0x00FF, 0xFF00], [0x0F0F, 0xF0F0]] + ) + check_array(-8, 1, [0, -0x80, 0x7F, 0x64]) + check_array(-8, 2, [[0, -0x80], [-0x64, 0x64], [0x25, -0x50], [0xFF, 0]]) + check_array(-16, 1, [0, 0x7FFF, -0x7FFF, -1]) + check_array(-16, 2, [[0, -0x7FFF], [-0x7FFF, 0], [0x7FFF, 0], [0, 0x7FFF]]) + + def test_get_arraytype(self): + array_type = pygame.sndarray.get_arraytype() + + self.assertEqual(array_type, "numpy", "unknown array type %s" % array_type) + + def test_get_arraytypes(self): + arraytypes = pygame.sndarray.get_arraytypes() + self.assertIn("numpy", arraytypes) + + for atype in arraytypes: + self.assertEqual(atype, "numpy", "unknown array type %s" % atype) + + def test_make_sound(self): + def check_sound(size, channels, test_data): + try: + pygame.mixer.init(22050, size, channels, allowedchanges=0) + except pygame.error: + # Not all sizes are supported on all systems. + return + try: + __, sz, __ = pygame.mixer.get_init() + if sz == size: + srcarr = array(test_data, self.array_dtypes[size]) + snd = pygame.sndarray.make_sound(srcarr) + arr = pygame.sndarray.samples(snd) + self.assertTrue( + alltrue(arr == srcarr), + "size: %i\n%s\n%s" % (size, arr, test_data), + ) + finally: + pygame.mixer.quit() + + check_sound(8, 1, [0, 0x0F, 0xF0, 0xFF]) + check_sound(8, 2, [[0, 0x80], [0x2D, 0x41], [0x64, 0xA1], [0xFF, 0x40]]) + check_sound(16, 1, [0, 0x00FF, 0xFF00, 0xFFFF]) + check_sound( + 16, 2, [[0, 0xFFFF], [0xFFFF, 0], [0x00FF, 0xFF00], [0x0F0F, 0xF0F0]] + ) + check_sound(-8, 1, [0, -0x80, 0x7F, 0x64]) + check_sound(-8, 2, [[0, -0x80], [-0x64, 0x64], [0x25, -0x50], [0xFF, 0]]) + check_sound(-16, 1, [0, 0x7FFF, -0x7FFF, -1]) + check_sound(-16, 2, [[0, -0x7FFF], [-0x7FFF, 0], [0x7FFF, 0], [0, 0x7FFF]]) + check_sound(32, 2, [[0.0, -1.0], [-1.0, 0], [1.0, 0], [0, 1.0]]) + + def test_samples(self): + + null_byte = b"\x00" + + def check_sample(size, channels, test_data): + try: + pygame.mixer.init(22050, size, channels, allowedchanges=0) + except pygame.error: + # Not all sizes are supported on all systems. + return + try: + __, sz, __ = pygame.mixer.get_init() + if sz == size: + zeroed = null_byte * ((abs(size) // 8) * len(test_data) * channels) + snd = pygame.mixer.Sound(buffer=zeroed) + samples = pygame.sndarray.samples(snd) + self._assert_compatible(samples, size) + ##print ('X %s' % (samples.shape,)) + ##print ('Y %s' % (test_data,)) + samples[...] = test_data + arr = pygame.sndarray.array(snd) + self.assertTrue( + alltrue(samples == arr), + "size: %i\n%s\n%s" % (size, arr, test_data), + ) + finally: + pygame.mixer.quit() + + check_sample(8, 1, [0, 0x0F, 0xF0, 0xFF]) + check_sample(8, 2, [[0, 0x80], [0x2D, 0x41], [0x64, 0xA1], [0xFF, 0x40]]) + check_sample(16, 1, [0, 0x00FF, 0xFF00, 0xFFFF]) + check_sample( + 16, 2, [[0, 0xFFFF], [0xFFFF, 0], [0x00FF, 0xFF00], [0x0F0F, 0xF0F0]] + ) + check_sample(-8, 1, [0, -0x80, 0x7F, 0x64]) + check_sample(-8, 2, [[0, -0x80], [-0x64, 0x64], [0x25, -0x50], [0xFF, 0]]) + check_sample(-16, 1, [0, 0x7FFF, -0x7FFF, -1]) + check_sample(-16, 2, [[0, -0x7FFF], [-0x7FFF, 0], [0x7FFF, 0], [0, 0x7FFF]]) + check_sample(32, 2, [[0.0, -1.0], [-1.0, 0], [1.0, 0], [0, 1.0]]) + + def test_use_arraytype(self): + def do_use_arraytype(atype): + pygame.sndarray.use_arraytype(atype) + + pygame.sndarray.use_arraytype("numpy") + self.assertEqual(pygame.sndarray.get_arraytype(), "numpy") + + self.assertRaises(ValueError, do_use_arraytype, "not an option") + + def test_float32(self): + """sized arrays work with Sounds and 32bit float arrays.""" + try: + pygame.mixer.init(22050, 32, 2, allowedchanges=0) + except pygame.error: + # Not all sizes are supported on all systems. + self.skipTest("unsupported mixer configuration") + + arr = array([[0.0, -1.0], [-1.0, 0], [1.0, 0], [0, 1.0]], float32) + newsound = pygame.mixer.Sound(array=arr) + pygame.mixer.quit() + + +if __name__ == "__main__": + unittest.main() diff --git a/venv/Lib/site-packages/pygame/tests/sprite_test.py b/venv/Lib/site-packages/pygame/tests/sprite_test.py new file mode 100644 index 0000000..b0b099a --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/sprite_test.py @@ -0,0 +1,1403 @@ +#################################### IMPORTS ################################### +# -*- encoding: utf-8 -*- + + +import unittest + +import pygame +from pygame import sprite + + +################################# MODULE LEVEL ################################# + + +class SpriteModuleTest(unittest.TestCase): + pass + + +######################### SPRITECOLLIDE FUNCTIONS TEST ######################### + + +class SpriteCollideTest(unittest.TestCase): + def setUp(self): + self.ag = sprite.AbstractGroup() + self.ag2 = sprite.AbstractGroup() + self.s1 = sprite.Sprite(self.ag) + self.s2 = sprite.Sprite(self.ag2) + self.s3 = sprite.Sprite(self.ag2) + + self.s1.image = pygame.Surface((50, 10), pygame.SRCALPHA, 32) + self.s2.image = pygame.Surface((10, 10), pygame.SRCALPHA, 32) + self.s3.image = pygame.Surface((10, 10), pygame.SRCALPHA, 32) + + self.s1.rect = self.s1.image.get_rect() + self.s2.rect = self.s2.image.get_rect() + self.s3.rect = self.s3.image.get_rect() + self.s2.rect.move_ip(40, 0) + self.s3.rect.move_ip(100, 100) + + def test_spritecollide__works_if_collided_cb_is_None(self): + # Test that sprites collide without collided function. + self.assertEqual( + sprite.spritecollide(self.s1, self.ag2, dokill=False, collided=None), + [self.s2], + ) + + def test_spritecollide__works_if_collided_cb_not_passed(self): + # Should also work when collided function isn't passed at all. + self.assertEqual( + sprite.spritecollide(self.s1, self.ag2, dokill=False), [self.s2] + ) + + def test_spritecollide__collided_must_be_a_callable(self): + # Need to pass a callable. + self.assertRaises( + TypeError, sprite.spritecollide, self.s1, self.ag2, dokill=False, collided=1 + ) + + def test_spritecollide__collided_defaults_to_collide_rect(self): + # collide_rect should behave the same as default. + self.assertEqual( + sprite.spritecollide( + self.s1, self.ag2, dokill=False, collided=sprite.collide_rect + ), + [self.s2], + ) + + def test_collide_rect_ratio__ratio_of_one_like_default(self): + # collide_rect_ratio should behave the same as default at a 1.0 ratio. + self.assertEqual( + sprite.spritecollide( + self.s1, self.ag2, dokill=False, collided=sprite.collide_rect_ratio(1.0) + ), + [self.s2], + ) + + def test_collide_rect_ratio__collides_all_at_ratio_of_twenty(self): + # collide_rect_ratio should collide all at a 20.0 ratio. + collided_func = sprite.collide_rect_ratio(20.0) + expected_sprites = sorted(self.ag2.sprites(), key=id) + + collided_sprites = sorted( + sprite.spritecollide( + self.s1, self.ag2, dokill=False, collided=collided_func + ), + key=id, + ) + + self.assertListEqual(collided_sprites, expected_sprites) + + def test_collide_circle__no_radius_set(self): + # collide_circle with no radius set. + self.assertEqual( + sprite.spritecollide( + self.s1, self.ag2, dokill=False, collided=sprite.collide_circle + ), + [self.s2], + ) + + def test_collide_circle_ratio__no_radius_and_ratio_of_one(self): + # collide_circle_ratio with no radius set, at a 1.0 ratio. + self.assertEqual( + sprite.spritecollide( + self.s1, + self.ag2, + dokill=False, + collided=sprite.collide_circle_ratio(1.0), + ), + [self.s2], + ) + + def test_collide_circle_ratio__no_radius_and_ratio_of_twenty(self): + # collide_circle_ratio with no radius set, at a 20.0 ratio. + collided_func = sprite.collide_circle_ratio(20.0) + expected_sprites = sorted(self.ag2.sprites(), key=id) + + collided_sprites = sorted( + sprite.spritecollide( + self.s1, self.ag2, dokill=False, collided=collided_func + ), + key=id, + ) + + self.assertListEqual(expected_sprites, collided_sprites) + + def test_collide_circle__radius_set_by_collide_circle_ratio(self): + # Call collide_circle_ratio with no radius set, at a 20.0 ratio. + # That should return group ag2 AND set the radius attribute of the + # sprites in such a way that collide_circle would give same result as + # if it had been called without the radius being set. + collided_func = sprite.collide_circle_ratio(20.0) + + sprite.spritecollide(self.s1, self.ag2, dokill=False, collided=collided_func) + + self.assertEqual( + sprite.spritecollide( + self.s1, self.ag2, dokill=False, collided=sprite.collide_circle + ), + [self.s2], + ) + + def test_collide_circle_ratio__no_radius_and_ratio_of_two_twice(self): + # collide_circle_ratio with no radius set, at a 2.0 ratio, + # called twice to check if the bug where the calculated radius + # is not stored correctly in the radius attribute of each sprite. + collided_func = sprite.collide_circle_ratio(2.0) + + # Calling collide_circle_ratio will set the radius attribute of the + # sprites. If an incorrect value is stored then we will not get the + # same result next time it is called: + expected_sprites = sorted( + sprite.spritecollide( + self.s1, self.ag2, dokill=False, collided=collided_func + ), + key=id, + ) + collided_sprites = sorted( + sprite.spritecollide( + self.s1, self.ag2, dokill=False, collided=collided_func + ), + key=id, + ) + + self.assertListEqual(expected_sprites, collided_sprites) + + def test_collide_circle__with_radii_set(self): + # collide_circle with a radius set. + self.s1.radius = 50 + self.s2.radius = 10 + self.s3.radius = 400 + collided_func = sprite.collide_circle + expected_sprites = sorted(self.ag2.sprites(), key=id) + + collided_sprites = sorted( + sprite.spritecollide( + self.s1, self.ag2, dokill=False, collided=collided_func + ), + key=id, + ) + + self.assertListEqual(expected_sprites, collided_sprites) + + def test_collide_circle_ratio__with_radii_set(self): + # collide_circle_ratio with a radius set. + self.s1.radius = 50 + self.s2.radius = 10 + self.s3.radius = 400 + collided_func = sprite.collide_circle_ratio(0.5) + expected_sprites = sorted(self.ag2.sprites(), key=id) + + collided_sprites = sorted( + sprite.spritecollide( + self.s1, self.ag2, dokill=False, collided=collided_func + ), + key=id, + ) + + self.assertListEqual(expected_sprites, collided_sprites) + + def test_collide_mask__opaque(self): + # make some fully opaque sprites that will collide with masks. + self.s1.image.fill((255, 255, 255, 255)) + self.s2.image.fill((255, 255, 255, 255)) + self.s3.image.fill((255, 255, 255, 255)) + + # masks should be autogenerated from image if they don't exist. + self.assertEqual( + sprite.spritecollide( + self.s1, self.ag2, dokill=False, collided=sprite.collide_mask + ), + [self.s2], + ) + + self.s1.mask = pygame.mask.from_surface(self.s1.image) + self.s2.mask = pygame.mask.from_surface(self.s2.image) + self.s3.mask = pygame.mask.from_surface(self.s3.image) + + # with set masks. + self.assertEqual( + sprite.spritecollide( + self.s1, self.ag2, dokill=False, collided=sprite.collide_mask + ), + [self.s2], + ) + + def test_collide_mask__transparent(self): + # make some sprites that are fully transparent, so they won't collide. + self.s1.image.fill((255, 255, 255, 0)) + self.s2.image.fill((255, 255, 255, 0)) + self.s3.image.fill((255, 255, 255, 0)) + + self.s1.mask = pygame.mask.from_surface(self.s1.image, 255) + self.s2.mask = pygame.mask.from_surface(self.s2.image, 255) + self.s3.mask = pygame.mask.from_surface(self.s3.image, 255) + + self.assertFalse( + sprite.spritecollide( + self.s1, self.ag2, dokill=False, collided=sprite.collide_mask + ) + ) + + def test_spritecollideany__without_collided_callback(self): + + # pygame.sprite.spritecollideany(sprite, group) -> sprite + # finds any sprites that collide + + # if collided is not passed, all + # sprites must have a "rect" value, which is a + # rectangle of the sprite area, which will be used + # to calculate the collision. + + # s2 in, s3 out + expected_sprite = self.s2 + collided_sprite = sprite.spritecollideany(self.s1, self.ag2) + + self.assertEqual(collided_sprite, expected_sprite) + + # s2 and s3 out + self.s2.rect.move_ip(0, 10) + collided_sprite = sprite.spritecollideany(self.s1, self.ag2) + + self.assertIsNone(collided_sprite) + + # s2 out, s3 in + self.s3.rect.move_ip(-105, -105) + expected_sprite = self.s3 + collided_sprite = sprite.spritecollideany(self.s1, self.ag2) + + self.assertEqual(collided_sprite, expected_sprite) + + # s2 and s3 in + self.s2.rect.move_ip(0, -10) + expected_sprite_choices = self.ag2.sprites() + collided_sprite = sprite.spritecollideany(self.s1, self.ag2) + + self.assertIn(collided_sprite, expected_sprite_choices) + + def test_spritecollideany__with_collided_callback(self): + + # pygame.sprite.spritecollideany(sprite, group) -> sprite + # finds any sprites that collide + + # collided is a callback function used to calculate if + # two sprites are colliding. it should take two sprites + # as values, and return a bool value indicating if + # they are colliding. + + # This collision test can be faster than pygame.sprite.spritecollide() + # since it has less work to do. + + arg_dict_a = {} + arg_dict_b = {} + return_container = [True] + + # This function is configurable using the mutable default arguments! + def collided_callback( + spr_a, + spr_b, + arg_dict_a=arg_dict_a, + arg_dict_b=arg_dict_b, + return_container=return_container, + ): + + count = arg_dict_a.get(spr_a, 0) + arg_dict_a[spr_a] = 1 + count + + count = arg_dict_b.get(spr_b, 0) + arg_dict_b[spr_b] = 1 + count + + return return_container[0] + + # This should return a sprite from self.ag2 because the callback + # function (collided_callback()) currently returns True. + expected_sprite_choices = self.ag2.sprites() + collided_sprite = sprite.spritecollideany(self.s1, self.ag2, collided_callback) + + self.assertIn(collided_sprite, expected_sprite_choices) + + # The callback function should have been called only once, so self.s1 + # should have only been passed as an argument once + self.assertEqual(len(arg_dict_a), 1) + self.assertEqual(arg_dict_a[self.s1], 1) + + # The callback function should have been called only once, so self.s2 + # exclusive-or self.s3 should have only been passed as an argument + # once + self.assertEqual(len(arg_dict_b), 1) + self.assertEqual(list(arg_dict_b.values())[0], 1) + self.assertTrue(self.s2 in arg_dict_b or self.s3 in arg_dict_b) + + arg_dict_a.clear() + arg_dict_b.clear() + return_container[0] = False + + # This should return None because the callback function + # (collided_callback()) currently returns False. + collided_sprite = sprite.spritecollideany(self.s1, self.ag2, collided_callback) + + self.assertIsNone(collided_sprite) + + # The callback function should have been called as many times as + # there are sprites in self.ag2 + self.assertEqual(len(arg_dict_a), 1) + self.assertEqual(arg_dict_a[self.s1], len(self.ag2)) + self.assertEqual(len(arg_dict_b), len(self.ag2)) + + # Each sprite in self.ag2 should be called once. + for s in self.ag2: + self.assertEqual(arg_dict_b[s], 1) + + def test_groupcollide__without_collided_callback(self): + + # pygame.sprite.groupcollide(groupa, groupb, dokilla, dokillb) -> dict + # collision detection between group and group + + # test no kill + expected_dict = {self.s1: [self.s2]} + crashed = pygame.sprite.groupcollide(self.ag, self.ag2, False, False) + + self.assertDictEqual(expected_dict, crashed) + + crashed = pygame.sprite.groupcollide(self.ag, self.ag2, False, False) + + self.assertDictEqual(expected_dict, crashed) + + # Test dokill2=True (kill colliding sprites in second group). + crashed = pygame.sprite.groupcollide(self.ag, self.ag2, False, True) + + self.assertDictEqual(expected_dict, crashed) + + expected_dict = {} + crashed = pygame.sprite.groupcollide(self.ag, self.ag2, False, False) + + self.assertDictEqual(expected_dict, crashed) + + # Test dokill1=True (kill colliding sprites in first group). + self.s3.rect.move_ip(-100, -100) + expected_dict = {self.s1: [self.s3]} + crashed = pygame.sprite.groupcollide(self.ag, self.ag2, True, False) + + self.assertDictEqual(expected_dict, crashed) + + expected_dict = {} + crashed = pygame.sprite.groupcollide(self.ag, self.ag2, False, False) + + self.assertDictEqual(expected_dict, crashed) + + def test_groupcollide__with_collided_callback(self): + + collided_callback_true = lambda spr_a, spr_b: True + collided_callback_false = lambda spr_a, spr_b: False + + # test no kill + expected_dict = {} + crashed = pygame.sprite.groupcollide( + self.ag, self.ag2, False, False, collided_callback_false + ) + + self.assertDictEqual(expected_dict, crashed) + + expected_dict = {self.s1: sorted(self.ag2.sprites(), key=id)} + crashed = pygame.sprite.groupcollide( + self.ag, self.ag2, False, False, collided_callback_true + ) + for value in crashed.values(): + value.sort(key=id) + + self.assertDictEqual(expected_dict, crashed) + + # expected_dict is the same again for this collide + crashed = pygame.sprite.groupcollide( + self.ag, self.ag2, False, False, collided_callback_true + ) + for value in crashed.values(): + value.sort(key=id) + + self.assertDictEqual(expected_dict, crashed) + + # Test dokill2=True (kill colliding sprites in second group). + expected_dict = {} + crashed = pygame.sprite.groupcollide( + self.ag, self.ag2, False, True, collided_callback_false + ) + + self.assertDictEqual(expected_dict, crashed) + + expected_dict = {self.s1: sorted(self.ag2.sprites(), key=id)} + crashed = pygame.sprite.groupcollide( + self.ag, self.ag2, False, True, collided_callback_true + ) + for value in crashed.values(): + value.sort(key=id) + + self.assertDictEqual(expected_dict, crashed) + + expected_dict = {} + crashed = pygame.sprite.groupcollide( + self.ag, self.ag2, False, True, collided_callback_true + ) + + self.assertDictEqual(expected_dict, crashed) + + # Test dokill1=True (kill colliding sprites in first group). + self.ag.add(self.s2) + self.ag2.add(self.s3) + expected_dict = {} + crashed = pygame.sprite.groupcollide( + self.ag, self.ag2, True, False, collided_callback_false + ) + + self.assertDictEqual(expected_dict, crashed) + + expected_dict = {self.s1: [self.s3], self.s2: [self.s3]} + crashed = pygame.sprite.groupcollide( + self.ag, self.ag2, True, False, collided_callback_true + ) + + self.assertDictEqual(expected_dict, crashed) + + expected_dict = {} + crashed = pygame.sprite.groupcollide( + self.ag, self.ag2, True, False, collided_callback_true + ) + + self.assertDictEqual(expected_dict, crashed) + + def test_collide_rect(self): + # Test colliding - some edges touching + self.assertTrue(pygame.sprite.collide_rect(self.s1, self.s2)) + self.assertTrue(pygame.sprite.collide_rect(self.s2, self.s1)) + + # Test colliding - all edges touching + self.s2.rect.center = self.s3.rect.center + + self.assertTrue(pygame.sprite.collide_rect(self.s2, self.s3)) + self.assertTrue(pygame.sprite.collide_rect(self.s3, self.s2)) + + # Test colliding - no edges touching + self.s2.rect.inflate_ip(10, 10) + + self.assertTrue(pygame.sprite.collide_rect(self.s2, self.s3)) + self.assertTrue(pygame.sprite.collide_rect(self.s3, self.s2)) + + # Test colliding - some edges intersecting + self.s2.rect.center = (self.s1.rect.right, self.s1.rect.bottom) + + self.assertTrue(pygame.sprite.collide_rect(self.s1, self.s2)) + self.assertTrue(pygame.sprite.collide_rect(self.s2, self.s1)) + + # Test not colliding + self.assertFalse(pygame.sprite.collide_rect(self.s1, self.s3)) + self.assertFalse(pygame.sprite.collide_rect(self.s3, self.s1)) + + +################################################################################ + + +class AbstractGroupTypeTest(unittest.TestCase): + def setUp(self): + self.ag = sprite.AbstractGroup() + self.ag2 = sprite.AbstractGroup() + self.s1 = sprite.Sprite(self.ag) + self.s2 = sprite.Sprite(self.ag) + self.s3 = sprite.Sprite(self.ag2) + self.s4 = sprite.Sprite(self.ag2) + + self.s1.image = pygame.Surface((10, 10)) + self.s1.image.fill(pygame.Color("red")) + self.s1.rect = self.s1.image.get_rect() + + self.s2.image = pygame.Surface((10, 10)) + self.s2.image.fill(pygame.Color("green")) + self.s2.rect = self.s2.image.get_rect() + self.s2.rect.left = 10 + + self.s3.image = pygame.Surface((10, 10)) + self.s3.image.fill(pygame.Color("blue")) + self.s3.rect = self.s3.image.get_rect() + self.s3.rect.top = 10 + + self.s4.image = pygame.Surface((10, 10)) + self.s4.image.fill(pygame.Color("white")) + self.s4.rect = self.s4.image.get_rect() + self.s4.rect.left = 10 + self.s4.rect.top = 10 + + self.bg = pygame.Surface((20, 20)) + self.scr = pygame.Surface((20, 20)) + self.scr.fill(pygame.Color("grey")) + + def test_has(self): + "See if AbstractGroup.has() works as expected." + + self.assertEqual(True, self.s1 in self.ag) + + self.assertEqual(True, self.ag.has(self.s1)) + + self.assertEqual(True, self.ag.has([self.s1, self.s2])) + + # see if one of them not being in there. + self.assertNotEqual(True, self.ag.has([self.s1, self.s2, self.s3])) + self.assertNotEqual(True, self.ag.has(self.s1, self.s2, self.s3)) + self.assertNotEqual(True, self.ag.has(self.s1, sprite.Group(self.s2, self.s3))) + self.assertNotEqual(True, self.ag.has(self.s1, [self.s2, self.s3])) + + # test empty list processing + self.assertFalse(self.ag.has(*[])) + self.assertFalse(self.ag.has([])) + self.assertFalse(self.ag.has([[]])) + + # see if a second AbstractGroup works. + self.assertEqual(True, self.ag2.has(self.s3)) + + def test_add(self): + ag3 = sprite.AbstractGroup() + sprites = (self.s1, self.s2, self.s3, self.s4) + + for s in sprites: + self.assertNotIn(s, ag3) + + ag3.add(self.s1, [self.s2], self.ag2) + + for s in sprites: + self.assertIn(s, ag3) + + def test_add_internal(self): + self.assertNotIn(self.s1, self.ag2) + + self.ag2.add_internal(self.s1) + + self.assertIn(self.s1, self.ag2) + + def test_clear(self): + + self.ag.draw(self.scr) + self.ag.clear(self.scr, self.bg) + self.assertEqual((0, 0, 0, 255), self.scr.get_at((5, 5))) + self.assertEqual((0, 0, 0, 255), self.scr.get_at((15, 5))) + + def test_draw(self): + + self.ag.draw(self.scr) + self.assertEqual((255, 0, 0, 255), self.scr.get_at((5, 5))) + self.assertEqual((0, 255, 0, 255), self.scr.get_at((15, 5))) + + self.assertEqual(self.ag.spritedict[self.s1], pygame.Rect(0, 0, 10, 10)) + self.assertEqual(self.ag.spritedict[self.s2], pygame.Rect(10, 0, 10, 10)) + + def test_empty(self): + + self.ag.empty() + self.assertFalse(self.s1 in self.ag) + self.assertFalse(self.s2 in self.ag) + + def test_has_internal(self): + self.assertTrue(self.ag.has_internal(self.s1)) + self.assertFalse(self.ag.has_internal(self.s3)) + + def test_remove(self): + + # Test removal of 1 sprite + self.ag.remove(self.s1) + self.assertFalse(self.ag in self.s1.groups()) + self.assertFalse(self.ag.has(self.s1)) + + # Test removal of 2 sprites as 2 arguments + self.ag2.remove(self.s3, self.s4) + self.assertFalse(self.ag2 in self.s3.groups()) + self.assertFalse(self.ag2 in self.s4.groups()) + self.assertFalse(self.ag2.has(self.s3, self.s4)) + + # Test removal of 4 sprites as a list containing a sprite and a group + # containing a sprite and another group containing 2 sprites. + self.ag.add(self.s1, self.s3, self.s4) + self.ag2.add(self.s3, self.s4) + g = sprite.Group(self.s2) + self.ag.remove([self.s1, g], self.ag2) + self.assertFalse(self.ag in self.s1.groups()) + self.assertFalse(self.ag in self.s2.groups()) + self.assertFalse(self.ag in self.s3.groups()) + self.assertFalse(self.ag in self.s4.groups()) + self.assertFalse(self.ag.has(self.s1, self.s2, self.s3, self.s4)) + + def test_remove_internal(self): + + self.ag.remove_internal(self.s1) + self.assertFalse(self.ag.has_internal(self.s1)) + + def test_sprites(self): + expected_sprites = sorted((self.s1, self.s2), key=id) + sprite_list = sorted(self.ag.sprites(), key=id) + + self.assertListEqual(sprite_list, expected_sprites) + + def test_update(self): + class test_sprite(pygame.sprite.Sprite): + sink = [] + + def __init__(self, *groups): + pygame.sprite.Sprite.__init__(self, *groups) + + def update(self, *args): + self.sink += args + + s = test_sprite(self.ag) + self.ag.update(1, 2, 3) + + self.assertEqual(test_sprite.sink, [1, 2, 3]) + + def test_update_with_kwargs(self): + class test_sprite(pygame.sprite.Sprite): + sink = [] + sink_kwargs = {} + + def __init__(self, *groups): + pygame.sprite.Sprite.__init__(self, *groups) + + def update(self, *args, **kwargs): + self.sink += args + self.sink_kwargs.update(kwargs) + + s = test_sprite(self.ag) + self.ag.update(1, 2, 3, foo=4, bar=5) + + self.assertEqual(test_sprite.sink, [1, 2, 3]) + self.assertEqual(test_sprite.sink_kwargs, {"foo": 4, "bar": 5}) + + +################################################################################ + +# A base class to share tests between similar classes + + +class LayeredGroupBase: + def test_get_layer_of_sprite(self): + expected_layer = 666 + spr = self.sprite() + self.LG.add(spr, layer=expected_layer) + layer = self.LG.get_layer_of_sprite(spr) + + self.assertEqual(len(self.LG._spritelist), 1) + self.assertEqual(layer, self.LG.get_layer_of_sprite(spr)) + self.assertEqual(layer, expected_layer) + self.assertEqual(layer, self.LG._spritelayers[spr]) + + def test_add(self): + expected_layer = self.LG._default_layer + spr = self.sprite() + self.LG.add(spr) + layer = self.LG.get_layer_of_sprite(spr) + + self.assertEqual(len(self.LG._spritelist), 1) + self.assertEqual(layer, expected_layer) + + def test_add__sprite_with_layer_attribute(self): + expected_layer = 100 + spr = self.sprite() + spr._layer = expected_layer + self.LG.add(spr) + layer = self.LG.get_layer_of_sprite(spr) + + self.assertEqual(len(self.LG._spritelist), 1) + self.assertEqual(layer, expected_layer) + + def test_add__passing_layer_keyword(self): + expected_layer = 100 + spr = self.sprite() + self.LG.add(spr, layer=expected_layer) + layer = self.LG.get_layer_of_sprite(spr) + + self.assertEqual(len(self.LG._spritelist), 1) + self.assertEqual(layer, expected_layer) + + def test_add__overriding_sprite_layer_attr(self): + expected_layer = 200 + spr = self.sprite() + spr._layer = 100 + self.LG.add(spr, layer=expected_layer) + layer = self.LG.get_layer_of_sprite(spr) + + self.assertEqual(len(self.LG._spritelist), 1) + self.assertEqual(layer, expected_layer) + + def test_add__adding_sprite_on_init(self): + spr = self.sprite() + lrg2 = sprite.LayeredUpdates(spr) + expected_layer = lrg2._default_layer + layer = lrg2._spritelayers[spr] + + self.assertEqual(len(lrg2._spritelist), 1) + self.assertEqual(layer, expected_layer) + + def test_add__sprite_init_layer_attr(self): + expected_layer = 20 + spr = self.sprite() + spr._layer = expected_layer + lrg2 = sprite.LayeredUpdates(spr) + layer = lrg2._spritelayers[spr] + + self.assertEqual(len(lrg2._spritelist), 1) + self.assertEqual(layer, expected_layer) + + def test_add__sprite_init_passing_layer(self): + expected_layer = 33 + spr = self.sprite() + lrg2 = sprite.LayeredUpdates(spr, layer=expected_layer) + layer = lrg2._spritelayers[spr] + + self.assertEqual(len(lrg2._spritelist), 1) + self.assertEqual(layer, expected_layer) + + def test_add__sprite_init_overiding_layer(self): + expected_layer = 33 + spr = self.sprite() + spr._layer = 55 + lrg2 = sprite.LayeredUpdates(spr, layer=expected_layer) + layer = lrg2._spritelayers[spr] + + self.assertEqual(len(lrg2._spritelist), 1) + self.assertEqual(layer, expected_layer) + + def test_add__spritelist(self): + expected_layer = self.LG._default_layer + sprite_count = 10 + sprites = [self.sprite() for _ in range(sprite_count)] + + self.LG.add(sprites) + + self.assertEqual(len(self.LG._spritelist), sprite_count) + + for i in range(sprite_count): + layer = self.LG.get_layer_of_sprite(sprites[i]) + + self.assertEqual(layer, expected_layer) + + def test_add__spritelist_with_layer_attr(self): + sprites = [] + sprite_and_layer_count = 10 + for i in range(sprite_and_layer_count): + sprites.append(self.sprite()) + sprites[-1]._layer = i + + self.LG.add(sprites) + + self.assertEqual(len(self.LG._spritelist), sprite_and_layer_count) + + for i in range(sprite_and_layer_count): + layer = self.LG.get_layer_of_sprite(sprites[i]) + + self.assertEqual(layer, i) + + def test_add__spritelist_passing_layer(self): + expected_layer = 33 + sprite_count = 10 + sprites = [self.sprite() for _ in range(sprite_count)] + + self.LG.add(sprites, layer=expected_layer) + + self.assertEqual(len(self.LG._spritelist), sprite_count) + + for i in range(sprite_count): + layer = self.LG.get_layer_of_sprite(sprites[i]) + + self.assertEqual(layer, expected_layer) + + def test_add__spritelist_overriding_layer(self): + expected_layer = 33 + sprites = [] + sprite_and_layer_count = 10 + for i in range(sprite_and_layer_count): + sprites.append(self.sprite()) + sprites[-1].layer = i + + self.LG.add(sprites, layer=expected_layer) + + self.assertEqual(len(self.LG._spritelist), sprite_and_layer_count) + + for i in range(sprite_and_layer_count): + layer = self.LG.get_layer_of_sprite(sprites[i]) + + self.assertEqual(layer, expected_layer) + + def test_add__spritelist_init(self): + sprite_count = 10 + sprites = [self.sprite() for _ in range(sprite_count)] + + lrg2 = sprite.LayeredUpdates(sprites) + expected_layer = lrg2._default_layer + + self.assertEqual(len(lrg2._spritelist), sprite_count) + + for i in range(sprite_count): + layer = lrg2.get_layer_of_sprite(sprites[i]) + + self.assertEqual(layer, expected_layer) + + def test_remove__sprite(self): + sprites = [] + sprite_count = 10 + for i in range(sprite_count): + sprites.append(self.sprite()) + sprites[-1].rect = pygame.Rect((0, 0, 0, 0)) + + self.LG.add(sprites) + + self.assertEqual(len(self.LG._spritelist), sprite_count) + + for i in range(sprite_count): + self.LG.remove(sprites[i]) + + self.assertEqual(len(self.LG._spritelist), 0) + + def test_sprites(self): + sprites = [] + sprite_and_layer_count = 10 + for i in range(sprite_and_layer_count, 0, -1): + sprites.append(self.sprite()) + sprites[-1]._layer = i + + self.LG.add(sprites) + + self.assertEqual(len(self.LG._spritelist), sprite_and_layer_count) + + # Sprites should be ordered based on their layer (bottom to top), + # which is the reverse order of the sprites list. + expected_sprites = list(reversed(sprites)) + actual_sprites = self.LG.sprites() + + self.assertListEqual(actual_sprites, expected_sprites) + + def test_layers(self): + sprites = [] + expected_layers = [] + layer_count = 10 + for i in range(layer_count): + expected_layers.append(i) + for j in range(5): + sprites.append(self.sprite()) + sprites[-1]._layer = i + self.LG.add(sprites) + + layers = self.LG.layers() + + self.assertListEqual(layers, expected_layers) + + def test_add__layers_are_correct(self): + layers = [1, 4, 6, 8, 3, 6, 2, 6, 4, 5, 6, 1, 0, 9, 7, 6, 54, 8, 2, 43, 6, 1] + for lay in layers: + self.LG.add(self.sprite(), layer=lay) + layers.sort() + + for idx, spr in enumerate(self.LG.sprites()): + layer = self.LG.get_layer_of_sprite(spr) + + self.assertEqual(layer, layers[idx]) + + def test_change_layer(self): + expected_layer = 99 + spr = self.sprite() + self.LG.add(spr, layer=expected_layer) + + self.assertEqual(self.LG._spritelayers[spr], expected_layer) + + expected_layer = 44 + self.LG.change_layer(spr, expected_layer) + + self.assertEqual(self.LG._spritelayers[spr], expected_layer) + + expected_layer = 77 + spr2 = self.sprite() + spr2.layer = 55 + self.LG.add(spr2) + self.LG.change_layer(spr2, expected_layer) + + self.assertEqual(spr2.layer, expected_layer) + + def test_get_sprites_at(self): + sprites = [] + expected_sprites = [] + for i in range(3): + spr = self.sprite() + spr.rect = pygame.Rect(i * 50, i * 50, 100, 100) + sprites.append(spr) + if i < 2: + expected_sprites.append(spr) + self.LG.add(sprites) + result = self.LG.get_sprites_at((50, 50)) + self.assertEqual(result, expected_sprites) + + def test_get_top_layer(self): + layers = [1, 5, 2, 8, 4, 5, 3, 88, 23, 0] + for i in layers: + self.LG.add(self.sprite(), layer=i) + top_layer = self.LG.get_top_layer() + + self.assertEqual(top_layer, self.LG.get_top_layer()) + self.assertEqual(top_layer, max(layers)) + self.assertEqual(top_layer, max(self.LG._spritelayers.values())) + self.assertEqual(top_layer, self.LG._spritelayers[self.LG._spritelist[-1]]) + + def test_get_bottom_layer(self): + layers = [1, 5, 2, 8, 4, 5, 3, 88, 23, 0] + for i in layers: + self.LG.add(self.sprite(), layer=i) + bottom_layer = self.LG.get_bottom_layer() + + self.assertEqual(bottom_layer, self.LG.get_bottom_layer()) + self.assertEqual(bottom_layer, min(layers)) + self.assertEqual(bottom_layer, min(self.LG._spritelayers.values())) + self.assertEqual(bottom_layer, self.LG._spritelayers[self.LG._spritelist[0]]) + + def test_move_to_front(self): + layers = [1, 5, 2, 8, 4, 5, 3, 88, 23, 0] + for i in layers: + self.LG.add(self.sprite(), layer=i) + spr = self.sprite() + self.LG.add(spr, layer=3) + + self.assertNotEqual(spr, self.LG._spritelist[-1]) + + self.LG.move_to_front(spr) + + self.assertEqual(spr, self.LG._spritelist[-1]) + + def test_move_to_back(self): + layers = [1, 5, 2, 8, 4, 5, 3, 88, 23, 0] + for i in layers: + self.LG.add(self.sprite(), layer=i) + spr = self.sprite() + self.LG.add(spr, layer=55) + + self.assertNotEqual(spr, self.LG._spritelist[0]) + + self.LG.move_to_back(spr) + + self.assertEqual(spr, self.LG._spritelist[0]) + + def test_get_top_sprite(self): + layers = [1, 5, 2, 8, 4, 5, 3, 88, 23, 0] + for i in layers: + self.LG.add(self.sprite(), layer=i) + expected_layer = self.LG.get_top_layer() + layer = self.LG.get_layer_of_sprite(self.LG.get_top_sprite()) + + self.assertEqual(layer, expected_layer) + + def test_get_sprites_from_layer(self): + sprites = {} + layers = [ + 1, + 4, + 5, + 6, + 3, + 7, + 8, + 2, + 1, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 0, + 1, + 6, + 5, + 4, + 3, + 2, + ] + for lay in layers: + spr = self.sprite() + spr._layer = lay + self.LG.add(spr) + if lay not in sprites: + sprites[lay] = [] + sprites[lay].append(spr) + + for lay in self.LG.layers(): + for spr in self.LG.get_sprites_from_layer(lay): + self.assertIn(spr, sprites[lay]) + + sprites[lay].remove(spr) + if len(sprites[lay]) == 0: + del sprites[lay] + + self.assertEqual(len(sprites.values()), 0) + + def test_switch_layer(self): + sprites1 = [] + sprites2 = [] + layers = [3, 2, 3, 2, 3, 3, 2, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 3, 2, 2, 3, 2, 3] + for lay in layers: + spr = self.sprite() + spr._layer = lay + self.LG.add(spr) + if lay == 2: + sprites1.append(spr) + else: + sprites2.append(spr) + + sprites1.sort(key=id) + sprites2.sort(key=id) + layer2_sprites = sorted(self.LG.get_sprites_from_layer(2), key=id) + layer3_sprites = sorted(self.LG.get_sprites_from_layer(3), key=id) + + self.assertListEqual(sprites1, layer2_sprites) + self.assertListEqual(sprites2, layer3_sprites) + self.assertEqual(len(self.LG), len(sprites1) + len(sprites2)) + + self.LG.switch_layer(2, 3) + layer2_sprites = sorted(self.LG.get_sprites_from_layer(2), key=id) + layer3_sprites = sorted(self.LG.get_sprites_from_layer(3), key=id) + + self.assertListEqual(sprites1, layer3_sprites) + self.assertListEqual(sprites2, layer2_sprites) + self.assertEqual(len(self.LG), len(sprites1) + len(sprites2)) + + def test_copy(self): + self.LG.add(self.sprite()) + spr = self.LG.sprites()[0] + lg_copy = self.LG.copy() + + self.assertIsInstance(lg_copy, type(self.LG)) + self.assertIn(spr, lg_copy) + self.assertIn(lg_copy, spr.groups()) + + +########################## LAYERED RENDER GROUP TESTS ########################## + + +class LayeredUpdatesTypeTest__SpriteTest(LayeredGroupBase, unittest.TestCase): + sprite = sprite.Sprite + + def setUp(self): + self.LG = sprite.LayeredUpdates() + + +class LayeredUpdatesTypeTest__DirtySprite(LayeredGroupBase, unittest.TestCase): + sprite = sprite.DirtySprite + + def setUp(self): + self.LG = sprite.LayeredUpdates() + + +class LayeredDirtyTypeTest__DirtySprite(LayeredGroupBase, unittest.TestCase): + sprite = sprite.DirtySprite + + def setUp(self): + self.LG = sprite.LayeredDirty() + + def test_repaint_rect(self): + group = self.LG + surface = pygame.Surface((100, 100)) + + group.repaint_rect(pygame.Rect(0, 0, 100, 100)) + group.draw(surface) + + def test_repaint_rect_with_clip(self): + group = self.LG + surface = pygame.Surface((100, 100)) + + group.set_clip(pygame.Rect(0, 0, 100, 100)) + group.repaint_rect(pygame.Rect(0, 0, 100, 100)) + group.draw(surface) + + def _nondirty_intersections_redrawn(self, use_source_rect=False): + # Helper method to ensure non-dirty sprites are redrawn correctly. + # + # Parameters: + # use_source_rect - allows non-dirty sprites to be tested + # with (True) and without (False) a source_rect + # + # This test was written to reproduce the behavior seen in issue #898. + # A non-dirty sprite (using source_rect) was being redrawn incorrectly + # after a dirty sprite intersected with it. + # + # This test does the following. + # 1. Creates a surface filled with white. Also creates an image_source + # with a default fill color of yellow and adds 2 images to it + # (red and blue rectangles). + # 2. Creates 2 DirtySprites (red_sprite and blue_sprite) using the + # image_source and adds them to a LayeredDirty group. + # 3. Moves the red_sprite and calls LayeredDirty.draw(surface) a few + # times. + # 4. Checks to make sure the sprites were redrawn correctly. + RED = pygame.Color("red") + BLUE = pygame.Color("blue") + WHITE = pygame.Color("white") + YELLOW = pygame.Color("yellow") + + surface = pygame.Surface((60, 80)) + surface.fill(WHITE) + start_pos = (10, 10) + + # These rects define each sprite's image area in the image_source. + red_sprite_source = pygame.Rect((45, 0), (5, 4)) + blue_sprite_source = pygame.Rect((0, 40), (20, 10)) + + # Create a source image/surface. + image_source = pygame.Surface((50, 50)) + image_source.fill(YELLOW) + image_source.fill(RED, red_sprite_source) + image_source.fill(BLUE, blue_sprite_source) + + # The blue_sprite is stationary and will not reset its dirty flag. It + # will be the non-dirty sprite in this test. Its values are dependent + # on the use_source_rect flag. + blue_sprite = pygame.sprite.DirtySprite(self.LG) + + if use_source_rect: + blue_sprite.image = image_source + # The rect is a bit smaller than the source_rect to make sure + # LayeredDirty.draw() is using the correct dimensions. + blue_sprite.rect = pygame.Rect( + start_pos, (blue_sprite_source.w - 7, blue_sprite_source.h - 7) + ) + blue_sprite.source_rect = blue_sprite_source + start_x, start_y = blue_sprite.rect.topleft + end_x = start_x + blue_sprite.source_rect.w + end_y = start_y + blue_sprite.source_rect.h + else: + blue_sprite.image = image_source.subsurface(blue_sprite_source) + blue_sprite.rect = pygame.Rect(start_pos, blue_sprite_source.size) + start_x, start_y = blue_sprite.rect.topleft + end_x, end_y = blue_sprite.rect.bottomright + + # The red_sprite is moving and will always be dirty. + red_sprite = pygame.sprite.DirtySprite(self.LG) + red_sprite.image = image_source + red_sprite.rect = pygame.Rect(start_pos, red_sprite_source.size) + red_sprite.source_rect = red_sprite_source + red_sprite.dirty = 2 + + # Draw the red_sprite as it moves a few steps. + for _ in range(4): + red_sprite.rect.move_ip(2, 1) + + # This is the method being tested. + self.LG.draw(surface) + + # Check colors where the blue_sprite is drawn. We expect red where the + # red_sprite is drawn over the blue_sprite, but the rest should be + # blue. + surface.lock() # Lock surface for possible speed up. + try: + for y in range(start_y, end_y): + for x in range(start_x, end_x): + if red_sprite.rect.collidepoint(x, y): + expected_color = RED + else: + expected_color = BLUE + + color = surface.get_at((x, y)) + + self.assertEqual(color, expected_color, "pos=({}, {})".format(x, y)) + finally: + surface.unlock() + + def test_nondirty_intersections_redrawn(self): + """Ensure non-dirty sprites are correctly redrawn + when dirty sprites intersect with them. + """ + self._nondirty_intersections_redrawn() + + def test_nondirty_intersections_redrawn__with_source_rect(self): + """Ensure non-dirty sprites using source_rects are correctly redrawn + when dirty sprites intersect with them. + + Related to issue #898. + """ + self._nondirty_intersections_redrawn(True) + + +############################### SPRITE BASE CLASS ############################## +# +# tests common between sprite classes + + +class SpriteBase: + def setUp(self): + self.groups = [] + for Group in self.Groups: + self.groups.append(Group()) + + self.sprite = self.Sprite() + + def test_add_internal(self): + + for g in self.groups: + self.sprite.add_internal(g) + + for g in self.groups: + self.assertIn(g, self.sprite.groups()) + + def test_remove_internal(self): + + for g in self.groups: + self.sprite.add_internal(g) + + for g in self.groups: + self.sprite.remove_internal(g) + + for g in self.groups: + self.assertFalse(g in self.sprite.groups()) + + def test_update(self): + class test_sprite(pygame.sprite.Sprite): + sink = [] + + def __init__(self, *groups): + pygame.sprite.Sprite.__init__(self, *groups) + + def update(self, *args): + self.sink += args + + s = test_sprite() + s.update(1, 2, 3) + + self.assertEqual(test_sprite.sink, [1, 2, 3]) + + def test_update_with_kwargs(self): + class test_sprite(pygame.sprite.Sprite): + sink = [] + sink_dict = {} + + def __init__(self, *groups): + pygame.sprite.Sprite.__init__(self, *groups) + + def update(self, *args, **kwargs): + self.sink += args + self.sink_dict.update(kwargs) + + s = test_sprite() + s.update(1, 2, 3, foo=4, bar=5) + + self.assertEqual(test_sprite.sink, [1, 2, 3]) + self.assertEqual(test_sprite.sink_dict, {"foo": 4, "bar": 5}) + + def test___init____added_to_groups_passed(self): + expected_groups = sorted(self.groups, key=id) + sprite = self.Sprite(self.groups) + groups = sorted(sprite.groups(), key=id) + + self.assertListEqual(groups, expected_groups) + + def test_add(self): + expected_groups = sorted(self.groups, key=id) + self.sprite.add(self.groups) + groups = sorted(self.sprite.groups(), key=id) + + self.assertListEqual(groups, expected_groups) + + def test_alive(self): + self.assertFalse( + self.sprite.alive(), "Sprite should not be alive if in no groups" + ) + + self.sprite.add(self.groups) + + self.assertTrue(self.sprite.alive()) + + def test_groups(self): + for i, g in enumerate(self.groups): + expected_groups = sorted(self.groups[: i + 1], key=id) + self.sprite.add(g) + groups = sorted(self.sprite.groups(), key=id) + + self.assertListEqual(groups, expected_groups) + + def test_kill(self): + self.sprite.add(self.groups) + + self.assertTrue(self.sprite.alive()) + + self.sprite.kill() + + self.assertListEqual(self.sprite.groups(), []) + self.assertFalse(self.sprite.alive()) + + def test_remove(self): + self.sprite.add(self.groups) + self.sprite.remove(self.groups) + + self.assertListEqual(self.sprite.groups(), []) + + +############################## SPRITE CLASS TESTS ############################## + + +class SpriteTypeTest(SpriteBase, unittest.TestCase): + Sprite = sprite.Sprite + + Groups = [ + sprite.Group, + sprite.LayeredUpdates, + sprite.RenderUpdates, + sprite.OrderedUpdates, + ] + + +class DirtySpriteTypeTest(SpriteBase, unittest.TestCase): + Sprite = sprite.DirtySprite + + Groups = [ + sprite.Group, + sprite.LayeredUpdates, + sprite.RenderUpdates, + sprite.OrderedUpdates, + sprite.LayeredDirty, + ] + + +############################## BUG TESTS ####################################### + + +class SingleGroupBugsTest(unittest.TestCase): + def test_memoryleak_bug(self): + # For memoryleak bug posted to mailing list by Tobias Steinrücken on 16/11/10. + # Fixed in revision 2953. + + import weakref + import gc + + class MySprite(sprite.Sprite): + def __init__(self, *args, **kwargs): + sprite.Sprite.__init__(self, *args, **kwargs) + self.image = pygame.Surface((2, 4), 0, 24) + self.rect = self.image.get_rect() + + g = sprite.GroupSingle() + screen = pygame.Surface((4, 8), 0, 24) + s = MySprite() + r = weakref.ref(s) + g.sprite = s + del s + gc.collect() + + self.assertIsNotNone(r()) + + g.update() + g.draw(screen) + g.sprite = MySprite() + gc.collect() + + self.assertIsNone(r()) + + +################################################################################ + +if __name__ == "__main__": + unittest.main() diff --git a/venv/Lib/site-packages/pygame/tests/surface_test.py b/venv/Lib/site-packages/pygame/tests/surface_test.py new file mode 100644 index 0000000..ab9b0e6 --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/surface_test.py @@ -0,0 +1,4015 @@ +import os +import unittest +from pygame.tests import test_utils +from pygame.tests.test_utils import ( + example_path, + AssertRaisesRegexMixin, + SurfaceSubclass, +) + +try: + from pygame.tests.test_utils.arrinter import * +except (ImportError, NameError): + pass +import pygame +from pygame.locals import * +from pygame.bufferproxy import BufferProxy + +import platform +import gc +import weakref +import ctypes + +IS_PYPY = "PyPy" == platform.python_implementation() + + +class SurfaceTypeTest(AssertRaisesRegexMixin, unittest.TestCase): + def test_surface__pixel_format_as_surface_subclass(self): + """Ensure a subclassed surface can be used for pixel format + when creating a new surface.""" + expected_depth = 16 + expected_flags = SRCALPHA + expected_size = (13, 37) + depth_surface = SurfaceSubclass((11, 21), expected_flags, expected_depth) + + surface = pygame.Surface(expected_size, expected_flags, depth_surface) + + self.assertIsNot(surface, depth_surface) + self.assertIsInstance(surface, pygame.Surface) + self.assertNotIsInstance(surface, SurfaceSubclass) + self.assertEqual(surface.get_size(), expected_size) + self.assertEqual(surface.get_flags(), expected_flags) + self.assertEqual(surface.get_bitsize(), expected_depth) + + def test_set_clip(self): + """see if surface.set_clip(None) works correctly.""" + s = pygame.Surface((800, 600)) + r = pygame.Rect(10, 10, 10, 10) + s.set_clip(r) + r.move_ip(10, 0) + s.set_clip(None) + res = s.get_clip() + # this was garbled before. + self.assertEqual(res[0], 0) + self.assertEqual(res[2], 800) + + def test_print(self): + surf = pygame.Surface((70, 70), 0, 32) + self.assertEqual(repr(surf), "") + + def test_keyword_arguments(self): + surf = pygame.Surface((70, 70), flags=SRCALPHA, depth=32) + self.assertEqual(surf.get_flags() & SRCALPHA, SRCALPHA) + self.assertEqual(surf.get_bitsize(), 32) + + # sanity check to make sure the check below is valid + surf_16 = pygame.Surface((70, 70), 0, 16) + self.assertEqual(surf_16.get_bytesize(), 2) + + # try again with an argument list + surf_16 = pygame.Surface((70, 70), depth=16) + self.assertEqual(surf_16.get_bytesize(), 2) + + def test_set_at(self): + + # 24bit surfaces + s = pygame.Surface((100, 100), 0, 24) + s.fill((0, 0, 0)) + + # set it with a tuple. + s.set_at((0, 0), (10, 10, 10, 255)) + r = s.get_at((0, 0)) + self.assertIsInstance(r, pygame.Color) + self.assertEqual(r, (10, 10, 10, 255)) + + # try setting a color with a single integer. + s.fill((0, 0, 0, 255)) + s.set_at((10, 1), 0x0000FF) + r = s.get_at((10, 1)) + self.assertEqual(r, (0, 0, 255, 255)) + + def test_set_at__big_endian(self): + """png files are loaded in big endian format (BGR rather than RGB)""" + pygame.display.init() + try: + image = pygame.image.load(example_path(os.path.join("data", "BGR.png"))) + # Check they start red, green and blue + self.assertEqual(image.get_at((10, 10)), pygame.Color(255, 0, 0)) + self.assertEqual(image.get_at((10, 20)), pygame.Color(0, 255, 0)) + self.assertEqual(image.get_at((10, 40)), pygame.Color(0, 0, 255)) + # Set three pixels that are already red, green, blue + # to red, green and, blue with set_at: + image.set_at((10, 10), pygame.Color(255, 0, 0)) + image.set_at((10, 20), pygame.Color(0, 255, 0)) + image.set_at((10, 40), pygame.Color(0, 0, 255)) + + # Check they still are + self.assertEqual(image.get_at((10, 10)), pygame.Color(255, 0, 0)) + self.assertEqual(image.get_at((10, 20)), pygame.Color(0, 255, 0)) + self.assertEqual(image.get_at((10, 40)), pygame.Color(0, 0, 255)) + + finally: + pygame.display.quit() + + def test_SRCALPHA(self): + # has the flag been passed in ok? + surf = pygame.Surface((70, 70), SRCALPHA, 32) + self.assertEqual(surf.get_flags() & SRCALPHA, SRCALPHA) + + # 24bit surfaces can not have SRCALPHA. + self.assertRaises(ValueError, pygame.Surface, (100, 100), pygame.SRCALPHA, 24) + + # if we have a 32 bit surface, the SRCALPHA should have worked too. + surf2 = pygame.Surface((70, 70), SRCALPHA) + if surf2.get_bitsize() == 32: + self.assertEqual(surf2.get_flags() & SRCALPHA, SRCALPHA) + + def test_flags_default0_nodisplay(self): + """is set to zero, and SRCALPH is not set by default with no display initialized.""" + pygame.display.quit() + surf = pygame.Surface((70, 70)) + self.assertEqual(surf.get_flags() & SRCALPHA, 0) + + def test_flags_default0_display(self): + """is set to zero, and SRCALPH is not set by default even when the display is initialized.""" + pygame.display.set_mode((320, 200)) + try: + surf = pygame.Surface((70, 70)) + self.assertEqual(surf.get_flags() & SRCALPHA, 0) + finally: + pygame.display.quit() + + def test_masks(self): + def make_surf(bpp, flags, masks): + pygame.Surface((10, 10), flags, bpp, masks) + + # With some masks SDL_CreateRGBSurface does not work properly. + masks = (0xFF000000, 0xFF0000, 0xFF00, 0) + self.assertEqual(make_surf(32, 0, masks), None) + # For 24 and 32 bit surfaces Pygame assumes no losses. + masks = (0x7F0000, 0xFF00, 0xFF, 0) + self.assertRaises(ValueError, make_surf, 24, 0, masks) + self.assertRaises(ValueError, make_surf, 32, 0, masks) + # What contiguous bits in a mask. + masks = (0x6F0000, 0xFF00, 0xFF, 0) + self.assertRaises(ValueError, make_surf, 32, 0, masks) + + def test_get_bounding_rect(self): + surf = pygame.Surface((70, 70), SRCALPHA, 32) + surf.fill((0, 0, 0, 0)) + bound_rect = surf.get_bounding_rect() + self.assertEqual(bound_rect.width, 0) + self.assertEqual(bound_rect.height, 0) + surf.set_at((30, 30), (255, 255, 255, 1)) + bound_rect = surf.get_bounding_rect() + self.assertEqual(bound_rect.left, 30) + self.assertEqual(bound_rect.top, 30) + self.assertEqual(bound_rect.width, 1) + self.assertEqual(bound_rect.height, 1) + surf.set_at((29, 29), (255, 255, 255, 1)) + bound_rect = surf.get_bounding_rect() + self.assertEqual(bound_rect.left, 29) + self.assertEqual(bound_rect.top, 29) + self.assertEqual(bound_rect.width, 2) + self.assertEqual(bound_rect.height, 2) + + surf = pygame.Surface((70, 70), 0, 24) + surf.fill((0, 0, 0)) + bound_rect = surf.get_bounding_rect() + self.assertEqual(bound_rect.width, surf.get_width()) + self.assertEqual(bound_rect.height, surf.get_height()) + + surf.set_colorkey((0, 0, 0)) + bound_rect = surf.get_bounding_rect() + self.assertEqual(bound_rect.width, 0) + self.assertEqual(bound_rect.height, 0) + surf.set_at((30, 30), (255, 255, 255)) + bound_rect = surf.get_bounding_rect() + self.assertEqual(bound_rect.left, 30) + self.assertEqual(bound_rect.top, 30) + self.assertEqual(bound_rect.width, 1) + self.assertEqual(bound_rect.height, 1) + surf.set_at((60, 60), (255, 255, 255)) + bound_rect = surf.get_bounding_rect() + self.assertEqual(bound_rect.left, 30) + self.assertEqual(bound_rect.top, 30) + self.assertEqual(bound_rect.width, 31) + self.assertEqual(bound_rect.height, 31) + + # Issue #180 + pygame.display.init() + try: + surf = pygame.Surface((4, 1), 0, 8) + surf.fill((255, 255, 255)) + surf.get_bounding_rect() # Segfault. + finally: + pygame.display.quit() + + def test_copy(self): + """Ensure a surface can be copied.""" + color = (25, 25, 25, 25) + s1 = pygame.Surface((32, 32), pygame.SRCALPHA, 32) + s1.fill(color) + + s2 = s1.copy() + + s1rect = s1.get_rect() + s2rect = s2.get_rect() + + self.assertEqual(s1rect.size, s2rect.size) + self.assertEqual(s2.get_at((10, 10)), color) + + def test_fill(self): + """Ensure a surface can be filled.""" + color = (25, 25, 25, 25) + fill_rect = pygame.Rect(0, 0, 16, 16) + s1 = pygame.Surface((32, 32), pygame.SRCALPHA, 32) + s1.fill(color, fill_rect) + + for pt in test_utils.rect_area_pts(fill_rect): + self.assertEqual(s1.get_at(pt), color) + + for pt in test_utils.rect_outer_bounds(fill_rect): + self.assertNotEqual(s1.get_at(pt), color) + + def test_fill_rle(self): + """Test RLEACCEL flag with fill()""" + color = (250, 25, 25, 255) + + surf = pygame.Surface((32, 32)) + blit_surf = pygame.Surface((32, 32)) + + blit_surf.set_colorkey((255, 0, 255), pygame.RLEACCEL) + self.assertTrue(blit_surf.get_flags() & pygame.RLEACCELOK) + surf.blit(blit_surf, (0, 0)) + blit_surf.fill(color) + self.assertEqual( + blit_surf.mustlock(), (blit_surf.get_flags() & pygame.RLEACCEL) != 0 + ) + self.assertTrue(blit_surf.get_flags() & pygame.RLEACCEL) + + def test_mustlock_rle(self): + """Test RLEACCEL flag with mustlock()""" + surf = pygame.Surface((100, 100)) + blit_surf = pygame.Surface((100, 100)) + blit_surf.set_colorkey((0, 0, 255), pygame.RLEACCEL) + self.assertTrue(blit_surf.get_flags() & pygame.RLEACCELOK) + surf.blit(blit_surf, (0, 0)) + self.assertTrue(blit_surf.get_flags() & pygame.RLEACCEL) + self.assertTrue(blit_surf.mustlock()) + + def test_mustlock_surf_alpha_rle(self): + """Test RLEACCEL flag with mustlock() on a surface + with per pixel alpha - new feature in SDL2""" + surf = pygame.Surface((100, 100)) + blit_surf = pygame.Surface((100, 100), depth=32, flags=pygame.SRCALPHA) + blit_surf.set_colorkey((192, 191, 192, 255), pygame.RLEACCEL) + self.assertTrue(blit_surf.get_flags() & pygame.RLEACCELOK) + surf.blit(blit_surf, (0, 0)) + self.assertTrue(blit_surf.get_flags() & pygame.RLEACCEL) + self.assertTrue(blit_surf.get_flags() & pygame.SRCALPHA) + self.assertTrue(blit_surf.mustlock()) + + def test_copy_rle(self): + """Test copying a surface set to use run length encoding""" + s1 = pygame.Surface((32, 32), 24) + s1.set_colorkey((255, 0, 255), pygame.RLEACCEL) + self.assertTrue(s1.get_flags() & pygame.RLEACCELOK) + + newsurf = s1.copy() + self.assertTrue(s1.get_flags() & pygame.RLEACCELOK) + self.assertTrue(newsurf.get_flags() & pygame.RLEACCELOK) + + def test_subsurface_rle(self): + """Ensure an RLE sub-surface works independently of its parent.""" + color = (250, 25, 25, 255) + color2 = (200, 200, 250, 255) + sub_rect = pygame.Rect(16, 16, 16, 16) + s0 = pygame.Surface((32, 32), 24) + s1 = pygame.Surface((32, 32), 24) + s1.set_colorkey((255, 0, 255), pygame.RLEACCEL) + s1.fill(color) + s2 = s1.subsurface(sub_rect) + s2.fill(color2) + s0.blit(s1, (0, 0)) + self.assertTrue(s1.get_flags() & pygame.RLEACCEL) + self.assertTrue(not s2.get_flags() & pygame.RLEACCEL) + + def test_subsurface_rle2(self): + """Ensure an RLE sub-surface works independently of its parent.""" + color = (250, 25, 25, 255) + color2 = (200, 200, 250, 255) + sub_rect = pygame.Rect(16, 16, 16, 16) + + s0 = pygame.Surface((32, 32), 24) + s1 = pygame.Surface((32, 32), 24) + s1.set_colorkey((255, 0, 255), pygame.RLEACCEL) + s1.fill(color) + s2 = s1.subsurface(sub_rect) + s2.fill(color2) + s0.blit(s2, (0, 0)) + self.assertTrue(s1.get_flags() & pygame.RLEACCELOK) + self.assertTrue(not s2.get_flags() & pygame.RLEACCELOK) + + def test_solarwolf_rle_usage(self): + """Test for error/crash when calling set_colorkey() followed + by convert twice in succession. Code originally taken + from solarwolf.""" + + def optimize(img): + clear = img.get_colorkey() + img.set_colorkey(clear, RLEACCEL) + self.assertEqual(img.get_colorkey(), clear) + return img.convert() + + pygame.display.init() + try: + pygame.display.set_mode((640, 480)) + + image = pygame.image.load(example_path(os.path.join("data", "alien1.png"))) + image = image.convert() + orig_colorkey = image.get_colorkey() + + image = optimize(image) + image = optimize(image) + self.assertTrue(image.get_flags() & pygame.RLEACCELOK) + self.assertTrue(not image.get_flags() & pygame.RLEACCEL) + self.assertEqual(image.get_colorkey(), orig_colorkey) + self.assertTrue(isinstance(image, pygame.Surface)) + finally: + pygame.display.quit() + + def test_solarwolf_rle_usage_2(self): + """Test for RLE status after setting alpha""" + + pygame.display.init() + try: + pygame.display.set_mode((640, 480), depth=32) + blit_to_surf = pygame.Surface((100, 100)) + + image = pygame.image.load(example_path(os.path.join("data", "alien1.png"))) + image = image.convert() + orig_colorkey = image.get_colorkey() + + # set the colorkey with RLEACCEL, should add the RLEACCELOK flag + image.set_colorkey(orig_colorkey, RLEACCEL) + self.assertTrue(image.get_flags() & pygame.RLEACCELOK) + self.assertTrue(not image.get_flags() & pygame.RLEACCEL) + + # now blit the surface - should add the RLEACCEL flag + blit_to_surf.blit(image, (0, 0)) + self.assertTrue(image.get_flags() & pygame.RLEACCELOK) + self.assertTrue(image.get_flags() & pygame.RLEACCEL) + + # Now set the alpha, without RLE acceleration - should strip all + # RLE flags + image.set_alpha(90) + self.assertTrue(not image.get_flags() & pygame.RLEACCELOK) + self.assertTrue(not image.get_flags() & pygame.RLEACCEL) + + finally: + pygame.display.quit() + + def test_set_alpha__set_colorkey_rle(self): + pygame.display.init() + try: + pygame.display.set_mode((640, 480)) + blit_to_surf = pygame.Surface((80, 71)) + blit_to_surf.fill((255, 255, 255)) + + image = pygame.image.load(example_path(os.path.join("data", "alien1.png"))) + image = image.convert() + orig_colorkey = image.get_colorkey() + + # Add the RLE flag while setting alpha for the whole surface + image.set_alpha(90, RLEACCEL) + blit_to_surf.blit(image, (0, 0)) + sample_pixel_rle = blit_to_surf.get_at((50, 50)) + + # Now reset the colorkey to the original value with RLE + self.assertEqual(image.get_colorkey(), orig_colorkey) + image.set_colorkey(orig_colorkey, RLEACCEL) + blit_to_surf.fill((255, 255, 255)) + blit_to_surf.blit(image, (0, 0)) + sample_pixel_no_rle = blit_to_surf.get_at((50, 50)) + + self.assertAlmostEqual(sample_pixel_rle.r, sample_pixel_no_rle.r, delta=2) + self.assertAlmostEqual(sample_pixel_rle.g, sample_pixel_no_rle.g, delta=2) + self.assertAlmostEqual(sample_pixel_rle.b, sample_pixel_no_rle.b, delta=2) + + finally: + pygame.display.quit() + + def test_fill_negative_coordinates(self): + + # negative coordinates should be clipped by fill, and not draw outside the surface. + color = (25, 25, 25, 25) + color2 = (20, 20, 20, 25) + fill_rect = pygame.Rect(-10, -10, 16, 16) + + s1 = pygame.Surface((32, 32), pygame.SRCALPHA, 32) + r1 = s1.fill(color, fill_rect) + c = s1.get_at((0, 0)) + self.assertEqual(c, color) + + # make subsurface in the middle to test it doesn't over write. + s2 = s1.subsurface((5, 5, 5, 5)) + r2 = s2.fill(color2, (-3, -3, 5, 5)) + c2 = s1.get_at((4, 4)) + self.assertEqual(c, color) + + # rect returns the area we actually fill. + r3 = s2.fill(color2, (-30, -30, 5, 5)) + # since we are using negative coords, it should be an zero sized rect. + self.assertEqual(tuple(r3), (0, 0, 0, 0)) + + def test_fill_keyword_args(self): + """Ensure fill() accepts keyword arguments.""" + color = (1, 2, 3, 255) + area = (1, 1, 2, 2) + s1 = pygame.Surface((4, 4), 0, 32) + s1.fill(special_flags=pygame.BLEND_ADD, color=color, rect=area) + + self.assertEqual(s1.get_at((0, 0)), (0, 0, 0, 255)) + self.assertEqual(s1.get_at((1, 1)), color) + + ######################################################################## + + def test_get_alpha(self): + """Ensure a surface's alpha value can be retrieved.""" + s1 = pygame.Surface((32, 32), pygame.SRCALPHA, 32) + + self.assertEqual(s1.get_alpha(), 255) + + for alpha in (0, 32, 127, 255): + s1.set_alpha(alpha) + for t in range(4): + s1.set_alpha(s1.get_alpha()) + + self.assertEqual(s1.get_alpha(), alpha) + + ######################################################################## + + def test_get_bytesize(self): + """Ensure a surface's bit and byte sizes can be retrieved.""" + pygame.display.init() + try: + depth = 32 + depth_bytes = 4 + s1 = pygame.Surface((32, 32), pygame.SRCALPHA, depth) + + self.assertEqual(s1.get_bytesize(), depth_bytes) + self.assertEqual(s1.get_bitsize(), depth) + + depth = 15 + depth_bytes = 2 + s1 = pygame.Surface((32, 32), 0, depth) + + self.assertEqual(s1.get_bytesize(), depth_bytes) + self.assertEqual(s1.get_bitsize(), depth) + + depth = 12 + depth_bytes = 2 + s1 = pygame.Surface((32, 32), 0, depth) + + self.assertEqual(s1.get_bytesize(), depth_bytes) + self.assertEqual(s1.get_bitsize(), depth) + + with self.assertRaises(pygame.error): + surface = pygame.display.set_mode() + pygame.display.quit() + surface.get_bytesize() + finally: + pygame.display.quit() + + ######################################################################## + + def test_get_flags(self): + """Ensure a surface's flags can be retrieved.""" + s1 = pygame.Surface((32, 32), pygame.SRCALPHA, 32) + + self.assertEqual(s1.get_flags(), pygame.SRCALPHA) + + @unittest.skipIf( + os.environ.get("SDL_VIDEODRIVER") == "dummy", + 'requires a non-"dummy" SDL_VIDEODRIVER', + ) + def test_get_flags__display_surf(self): + pygame.display.init() + try: + # FULLSCREEN + screen_surf = pygame.display.set_mode((600, 400), flags=0) + self.assertFalse(screen_surf.get_flags() & pygame.FULLSCREEN) + + screen_surf = pygame.display.set_mode((600, 400), flags=pygame.FULLSCREEN) + self.assertTrue(screen_surf.get_flags() & pygame.FULLSCREEN) + + # NOFRAME + screen_surf = pygame.display.set_mode((600, 400), flags=0) + self.assertFalse(screen_surf.get_flags() & pygame.NOFRAME) + + screen_surf = pygame.display.set_mode((600, 400), flags=pygame.NOFRAME) + self.assertTrue(screen_surf.get_flags() & pygame.NOFRAME) + + # RESIZABLE + screen_surf = pygame.display.set_mode((600, 400), flags=0) + self.assertFalse(screen_surf.get_flags() & pygame.RESIZABLE) + + screen_surf = pygame.display.set_mode((600, 400), flags=pygame.RESIZABLE) + self.assertTrue(screen_surf.get_flags() & pygame.RESIZABLE) + + # OPENGL + screen_surf = pygame.display.set_mode((600, 400), flags=0) + # it can have an OPENGL flag by default on Macos? + if not (screen_surf.get_flags() & pygame.OPENGL): + self.assertFalse(screen_surf.get_flags() & pygame.OPENGL) + + try: + pygame.display.set_mode((200, 200), pygame.OPENGL, 32) + except pygame.error: + pass # If we can't create OPENGL surface don't try this test + else: + self.assertTrue(screen_surf.get_flags() & pygame.OPENGL) + finally: + pygame.display.quit() + + ######################################################################## + + def test_get_parent(self): + """Ensure a surface's parent can be retrieved.""" + pygame.display.init() + try: + parent = pygame.Surface((16, 16)) + child = parent.subsurface((0, 0, 5, 5)) + + self.assertIs(child.get_parent(), parent) + + with self.assertRaises(pygame.error): + surface = pygame.display.set_mode() + pygame.display.quit() + surface.get_parent() + finally: + pygame.display.quit() + + ######################################################################## + + def test_get_rect(self): + """Ensure a surface's rect can be retrieved.""" + size = (16, 16) + surf = pygame.Surface(size) + rect = surf.get_rect() + + self.assertEqual(rect.size, size) + + ######################################################################## + + def test_get_width__size_and_height(self): + """Ensure a surface's size, width and height can be retrieved.""" + for w in range(0, 255, 32): + for h in range(0, 127, 15): + s = pygame.Surface((w, h)) + self.assertEqual(s.get_width(), w) + self.assertEqual(s.get_height(), h) + self.assertEqual(s.get_size(), (w, h)) + + def test_get_view(self): + """Ensure a buffer view of the surface's pixels can be retrieved.""" + # Check that BufferProxys are returned when array depth is supported, + # ValueErrors returned otherwise. + Error = ValueError + s = pygame.Surface((5, 7), 0, 8) + v2 = s.get_view("2") + + self.assertRaises(Error, s.get_view, "0") + self.assertRaises(Error, s.get_view, "1") + self.assertIsInstance(v2, BufferProxy) + self.assertRaises(Error, s.get_view, "3") + + s = pygame.Surface((8, 7), 0, 8) + length = s.get_bytesize() * s.get_width() * s.get_height() + v0 = s.get_view("0") + v1 = s.get_view("1") + + self.assertIsInstance(v0, BufferProxy) + self.assertEqual(v0.length, length) + self.assertIsInstance(v1, BufferProxy) + self.assertEqual(v1.length, length) + + s = pygame.Surface((5, 7), 0, 16) + v2 = s.get_view("2") + + self.assertRaises(Error, s.get_view, "0") + self.assertRaises(Error, s.get_view, "1") + self.assertIsInstance(v2, BufferProxy) + self.assertRaises(Error, s.get_view, "3") + + s = pygame.Surface((8, 7), 0, 16) + length = s.get_bytesize() * s.get_width() * s.get_height() + v0 = s.get_view("0") + v1 = s.get_view("1") + + self.assertIsInstance(v0, BufferProxy) + self.assertEqual(v0.length, length) + self.assertIsInstance(v1, BufferProxy) + self.assertEqual(v1.length, length) + + s = pygame.Surface((5, 7), pygame.SRCALPHA, 16) + v2 = s.get_view("2") + + self.assertIsInstance(v2, BufferProxy) + self.assertRaises(Error, s.get_view, "3") + + s = pygame.Surface((5, 7), 0, 24) + v2 = s.get_view("2") + v3 = s.get_view("3") + + self.assertRaises(Error, s.get_view, "0") + self.assertRaises(Error, s.get_view, "1") + self.assertIsInstance(v2, BufferProxy) + self.assertIsInstance(v3, BufferProxy) + + s = pygame.Surface((8, 7), 0, 24) + length = s.get_bytesize() * s.get_width() * s.get_height() + v0 = s.get_view("0") + v1 = s.get_view("1") + + self.assertIsInstance(v0, BufferProxy) + self.assertEqual(v0.length, length) + self.assertIsInstance(v1, BufferProxy) + self.assertEqual(v1.length, length) + + s = pygame.Surface((5, 7), 0, 32) + length = s.get_bytesize() * s.get_width() * s.get_height() + v0 = s.get_view("0") + v1 = s.get_view("1") + v2 = s.get_view("2") + v3 = s.get_view("3") + + self.assertIsInstance(v0, BufferProxy) + self.assertEqual(v0.length, length) + self.assertIsInstance(v1, BufferProxy) + self.assertEqual(v1.length, length) + self.assertIsInstance(v2, BufferProxy) + self.assertIsInstance(v3, BufferProxy) + + s2 = s.subsurface((0, 0, 4, 7)) + + self.assertRaises(Error, s2.get_view, "0") + self.assertRaises(Error, s2.get_view, "1") + + s2 = None + s = pygame.Surface((5, 7), pygame.SRCALPHA, 32) + + for kind in ("2", "3", "a", "A", "r", "R", "g", "G", "b", "B"): + self.assertIsInstance(s.get_view(kind), BufferProxy) + + # Check default argument value: '2' + s = pygame.Surface((2, 4), 0, 32) + v = s.get_view() + if not IS_PYPY: + ai = ArrayInterface(v) + self.assertEqual(ai.nd, 2) + + # Check locking. + s = pygame.Surface((2, 4), 0, 32) + + self.assertFalse(s.get_locked()) + + v = s.get_view("2") + + self.assertFalse(s.get_locked()) + + c = v.__array_interface__ + + self.assertTrue(s.get_locked()) + + c = None + gc.collect() + + self.assertTrue(s.get_locked()) + + v = None + gc.collect() + + self.assertFalse(s.get_locked()) + + # Check invalid view kind values. + s = pygame.Surface((2, 4), pygame.SRCALPHA, 32) + self.assertRaises(TypeError, s.get_view, "") + self.assertRaises(TypeError, s.get_view, "9") + self.assertRaises(TypeError, s.get_view, "RGBA") + self.assertRaises(TypeError, s.get_view, 2) + + # Both unicode and bytes strings are allowed for kind. + s = pygame.Surface((2, 4), 0, 32) + s.get_view("2") + s.get_view(b"2") + + # Garbage collection + s = pygame.Surface((2, 4), 0, 32) + weak_s = weakref.ref(s) + v = s.get_view("3") + weak_v = weakref.ref(v) + gc.collect() + self.assertTrue(weak_s() is s) + self.assertTrue(weak_v() is v) + del v + gc.collect() + self.assertTrue(weak_s() is s) + self.assertTrue(weak_v() is None) + del s + gc.collect() + self.assertTrue(weak_s() is None) + + def test_get_buffer(self): + # Check that get_buffer works for all pixel sizes and for a subsurface. + + # Check for all pixel sizes + for bitsize in [8, 16, 24, 32]: + s = pygame.Surface((5, 7), 0, bitsize) + length = s.get_pitch() * s.get_height() + v = s.get_buffer() + + self.assertIsInstance(v, BufferProxy) + self.assertEqual(v.length, length) + self.assertEqual(repr(v), "") + + # Check for a subsurface (not contiguous) + s = pygame.Surface((7, 10), 0, 32) + s2 = s.subsurface((1, 2, 5, 7)) + length = s2.get_pitch() * s2.get_height() + v = s2.get_buffer() + + self.assertIsInstance(v, BufferProxy) + self.assertEqual(v.length, length) + + # Check locking. + s = pygame.Surface((2, 4), 0, 32) + v = s.get_buffer() + self.assertTrue(s.get_locked()) + v = None + gc.collect() + self.assertFalse(s.get_locked()) + + OLDBUF = hasattr(pygame.bufferproxy, "get_segcount") + + @unittest.skipIf(not OLDBUF, "old buffer not available") + def test_get_buffer_oldbuf(self): + from pygame.bufferproxy import get_segcount, get_write_buffer + + s = pygame.Surface((2, 4), pygame.SRCALPHA, 32) + v = s.get_buffer() + segcount, buflen = get_segcount(v) + self.assertEqual(segcount, 1) + self.assertEqual(buflen, s.get_pitch() * s.get_height()) + seglen, segaddr = get_write_buffer(v, 0) + self.assertEqual(segaddr, s._pixels_address) + self.assertEqual(seglen, buflen) + + @unittest.skipIf(not OLDBUF, "old buffer not available") + def test_get_view_oldbuf(self): + from pygame.bufferproxy import get_segcount, get_write_buffer + + s = pygame.Surface((2, 4), pygame.SRCALPHA, 32) + v = s.get_view("1") + segcount, buflen = get_segcount(v) + self.assertEqual(segcount, 8) + self.assertEqual(buflen, s.get_pitch() * s.get_height()) + seglen, segaddr = get_write_buffer(v, 7) + self.assertEqual(segaddr, s._pixels_address + s.get_bytesize() * 7) + self.assertEqual(seglen, s.get_bytesize()) + + def test_set_colorkey(self): + + # __doc__ (as of 2008-06-25) for pygame.surface.Surface.set_colorkey: + + # Surface.set_colorkey(Color, flags=0): return None + # Surface.set_colorkey(None): return None + # Set the transparent colorkey + + s = pygame.Surface((16, 16), pygame.SRCALPHA, 32) + + colorkeys = ((20, 189, 20, 255), (128, 50, 50, 255), (23, 21, 255, 255)) + + for colorkey in colorkeys: + s.set_colorkey(colorkey) + + for t in range(4): + s.set_colorkey(s.get_colorkey()) + + self.assertEqual(s.get_colorkey(), colorkey) + + def test_set_masks(self): + s = pygame.Surface((32, 32)) + r, g, b, a = s.get_masks() + self.assertRaises(TypeError, s.set_masks, (b, g, r, a)) + + def test_set_shifts(self): + s = pygame.Surface((32, 32)) + r, g, b, a = s.get_shifts() + self.assertRaises(TypeError, s.set_shifts, (b, g, r, a)) + + def test_blit_keyword_args(self): + color = (1, 2, 3, 255) + s1 = pygame.Surface((4, 4), 0, 32) + s2 = pygame.Surface((2, 2), 0, 32) + s2.fill((1, 2, 3)) + s1.blit(special_flags=BLEND_ADD, source=s2, dest=(1, 1), area=s2.get_rect()) + self.assertEqual(s1.get_at((0, 0)), (0, 0, 0, 255)) + self.assertEqual(s1.get_at((1, 1)), color) + + def test_blit_big_rects(self): + """SDL2 can have more than 16 bits for x, y, width, height.""" + big_surf = pygame.Surface((100, 68000), 0, 32) + big_surf_color = (255, 0, 0) + big_surf.fill(big_surf_color) + + background = pygame.Surface((500, 500), 0, 32) + background_color = (0, 255, 0) + background.fill(background_color) + + # copy parts of the big_surf using more than 16bit parts. + background.blit(big_surf, (100, 100), area=(0, 16000, 100, 100)) + background.blit(big_surf, (200, 200), area=(0, 32000, 100, 100)) + background.blit(big_surf, (300, 300), area=(0, 66000, 100, 100)) + + # check that all three areas are drawn. + self.assertEqual(background.get_at((101, 101)), big_surf_color) + self.assertEqual(background.get_at((201, 201)), big_surf_color) + self.assertEqual(background.get_at((301, 301)), big_surf_color) + + # areas outside the 3 blitted areas not covered by those blits. + self.assertEqual(background.get_at((400, 301)), background_color) + self.assertEqual(background.get_at((400, 201)), background_color) + self.assertEqual(background.get_at((100, 201)), background_color) + self.assertEqual(background.get_at((99, 99)), background_color) + self.assertEqual(background.get_at((450, 450)), background_color) + + +class TestSurfaceBlit(unittest.TestCase): + """Tests basic blitting functionality and options.""" + + # __doc__ (as of 2008-08-02) for pygame.surface.Surface.blit: + + # Surface.blit(source, dest, area=None, special_flags = 0): return Rect + # draw one image onto another + # + # Draws a source Surface onto this Surface. The draw can be positioned + # with the dest argument. Dest can either be pair of coordinates + # representing the upper left corner of the source. A Rect can also be + # passed as the destination and the topleft corner of the rectangle + # will be used as the position for the blit. The size of the + # destination rectangle does not effect the blit. + # + # An optional area rectangle can be passed as well. This represents a + # smaller portion of the source Surface to draw. + # + # An optional special flags is for passing in new in 1.8.0: BLEND_ADD, + # BLEND_SUB, BLEND_MULT, BLEND_MIN, BLEND_MAX new in 1.8.1: + # BLEND_RGBA_ADD, BLEND_RGBA_SUB, BLEND_RGBA_MULT, BLEND_RGBA_MIN, + # BLEND_RGBA_MAX BLEND_RGB_ADD, BLEND_RGB_SUB, BLEND_RGB_MULT, + # BLEND_RGB_MIN, BLEND_RGB_MAX With other special blitting flags + # perhaps added in the future. + # + # The return rectangle is the area of the affected pixels, excluding + # any pixels outside the destination Surface, or outside the clipping + # area. + # + # Pixel alphas will be ignored when blitting to an 8 bit Surface. + # special_flags new in pygame 1.8. + + def setUp(self): + """Resets starting surfaces.""" + self.src_surface = pygame.Surface((256, 256), 32) + self.src_surface.fill(pygame.Color(255, 255, 255)) + self.dst_surface = pygame.Surface((64, 64), 32) + self.dst_surface.fill(pygame.Color(0, 0, 0)) + + def test_blit_overflow_coord(self): + """Full coverage w/ overflow, specified with Coordinate""" + result = self.dst_surface.blit(self.src_surface, (0, 0)) + self.assertIsInstance(result, pygame.Rect) + self.assertEqual(result.size, (64, 64)) + for k in [(x, x) for x in range(64)]: + self.assertEqual(self.dst_surface.get_at(k), (255, 255, 255)) + + def test_blit_overflow_rect(self): + """Full coverage w/ overflow, specified with a Rect""" + result = self.dst_surface.blit(self.src_surface, pygame.Rect(-1, -1, 300, 300)) + self.assertIsInstance(result, pygame.Rect) + self.assertEqual(result.size, (64, 64)) + for k in [(x, x) for x in range(64)]: + self.assertEqual(self.dst_surface.get_at(k), (255, 255, 255)) + + def test_blit_overflow_nonorigin(self): + """Test Rectange Dest, with overflow but with starting rect with top-left at (1,1)""" + result = self.dst_surface.blit(self.src_surface, dest=pygame.Rect((1, 1, 1, 1))) + self.assertIsInstance(result, pygame.Rect) + self.assertEqual(result.size, (63, 63)) + self.assertEqual(self.dst_surface.get_at((0, 0)), (0, 0, 0)) + self.assertEqual(self.dst_surface.get_at((63, 0)), (0, 0, 0)) + self.assertEqual(self.dst_surface.get_at((0, 63)), (0, 0, 0)) + self.assertEqual(self.dst_surface.get_at((1, 1)), (255, 255, 255)) + self.assertEqual(self.dst_surface.get_at((63, 63)), (255, 255, 255)) + + def test_blit_area_contraint(self): + """Testing area constraint""" + result = self.dst_surface.blit( + self.src_surface, + dest=pygame.Rect((1, 1, 1, 1)), + area=pygame.Rect((2, 2, 2, 2)), + ) + self.assertIsInstance(result, pygame.Rect) + self.assertEqual(result.size, (2, 2)) + self.assertEqual(self.dst_surface.get_at((0, 0)), (0, 0, 0)) # Corners + self.assertEqual(self.dst_surface.get_at((63, 0)), (0, 0, 0)) + self.assertEqual(self.dst_surface.get_at((0, 63)), (0, 0, 0)) + self.assertEqual(self.dst_surface.get_at((63, 63)), (0, 0, 0)) + self.assertEqual( + self.dst_surface.get_at((1, 1)), (255, 255, 255) + ) # Blitted Area + self.assertEqual(self.dst_surface.get_at((2, 2)), (255, 255, 255)) + self.assertEqual(self.dst_surface.get_at((3, 3)), (0, 0, 0)) + # Should stop short of filling in (3,3) + + def test_blit_zero_overlap(self): + """Testing zero-overlap condition.""" + result = self.dst_surface.blit( + self.src_surface, + dest=pygame.Rect((-256, -256, 1, 1)), + area=pygame.Rect((2, 2, 256, 256)), + ) + self.assertIsInstance(result, pygame.Rect) + self.assertEqual(result.size, (0, 0)) # No blitting expected + for k in [(x, x) for x in range(64)]: + self.assertEqual(self.dst_surface.get_at(k), (0, 0, 0)) # Diagonal + self.assertEqual( + self.dst_surface.get_at((63, 0)), (0, 0, 0) + ) # Remaining corners + self.assertEqual(self.dst_surface.get_at((0, 63)), (0, 0, 0)) + + def test_blit__SRCALPHA_opaque_source(self): + src = pygame.Surface((256, 256), SRCALPHA, 32) + dst = src.copy() + + for i, j in test_utils.rect_area_pts(src.get_rect()): + dst.set_at((i, j), (i, 0, 0, j)) + src.set_at((i, j), (0, i, 0, 255)) + + dst.blit(src, (0, 0)) + + for pt in test_utils.rect_area_pts(src.get_rect()): + self.assertEqual(dst.get_at(pt)[1], src.get_at(pt)[1]) + + def test_blit__blit_to_self(self): + """Test that blit operation works on self, alpha value is + correct, and that no RGB distortion occurs.""" + test_surface = pygame.Surface((128, 128), SRCALPHA, 32) + area = test_surface.get_rect() + + for pt, test_color in test_utils.gradient(area.width, area.height): + test_surface.set_at(pt, test_color) + + reference_surface = test_surface.copy() + + test_surface.blit(test_surface, (0, 0)) + + for x in range(area.width): + for y in range(area.height): + (r, g, b, a) = reference_color = reference_surface.get_at((x, y)) + expected_color = (r, g, b, (a + (a * ((256 - a) // 256)))) + self.assertEqual(reference_color, expected_color) + + self.assertEqual(reference_surface.get_rect(), test_surface.get_rect()) + + def test_blit__SRCALPHA_to_SRCALPHA_non_zero(self): + """Tests blitting a nonzero alpha surface to another nonzero alpha surface + both straight alpha compositing method. Test is fuzzy (+/- 1/256) to account for + different implementations in SDL1 and SDL2. + """ + + size = (32, 32) + + def check_color_diff(color1, color2): + """Returns True if two colors are within (1, 1, 1, 1) of each other.""" + for val in color1 - color2: + if abs(val) > 1: + return False + return True + + def high_a_onto_low(high, low): + """Tests straight alpha case. Source is low alpha, destination is high alpha""" + high_alpha_surface = pygame.Surface(size, pygame.SRCALPHA, 32) + low_alpha_surface = high_alpha_surface.copy() + high_alpha_color = Color( + (high, high, low, high) + ) # Injecting some RGB variance. + low_alpha_color = Color((high, low, low, low)) + high_alpha_surface.fill(high_alpha_color) + low_alpha_surface.fill(low_alpha_color) + + high_alpha_surface.blit(low_alpha_surface, (0, 0)) + + expected_color = low_alpha_color + Color( + tuple( + ((x * (255 - low_alpha_color.a)) // 255) for x in high_alpha_color + ) + ) + self.assertTrue( + check_color_diff(high_alpha_surface.get_at((0, 0)), expected_color) + ) + + def low_a_onto_high(high, low): + """Tests straight alpha case. Source is high alpha, destination is low alpha""" + high_alpha_surface = pygame.Surface(size, pygame.SRCALPHA, 32) + low_alpha_surface = high_alpha_surface.copy() + high_alpha_color = Color( + (high, high, low, high) + ) # Injecting some RGB variance. + low_alpha_color = Color((high, low, low, low)) + high_alpha_surface.fill(high_alpha_color) + low_alpha_surface.fill(low_alpha_color) + + low_alpha_surface.blit(high_alpha_surface, (0, 0)) + + expected_color = high_alpha_color + Color( + tuple( + ((x * (255 - high_alpha_color.a)) // 255) for x in low_alpha_color + ) + ) + self.assertTrue( + check_color_diff(low_alpha_surface.get_at((0, 0)), expected_color) + ) + + for low_a in range(0, 128): + for high_a in range(128, 256): + high_a_onto_low(high_a, low_a) + low_a_onto_high(high_a, low_a) + + def test_blit__SRCALPHA32_to_8(self): + # Bug: fatal + # SDL_DisplayConvert segfaults when video is uninitialized. + target = pygame.Surface((11, 8), 0, 8) + test_color = target.get_palette_at(2) + source = pygame.Surface((1, 1), pygame.SRCALPHA, 32) + source.set_at((0, 0), test_color) + target.blit(source, (0, 0)) + + +class GeneralSurfaceTests(AssertRaisesRegexMixin, unittest.TestCase): + @unittest.skipIf( + os.environ.get("SDL_VIDEODRIVER") == "dummy", + 'requires a non-"dummy" SDL_VIDEODRIVER', + ) + def test_image_convert_bug_131(self): + # Bitbucket bug #131: Unable to Surface.convert(32) some 1-bit images. + # https://bitbucket.org/pygame/pygame/issue/131/unable-to-surfaceconvert-32-some-1-bit + + pygame.display.init() + try: + pygame.display.set_mode((640, 480)) + + im = pygame.image.load(example_path(os.path.join("data", "city.png"))) + im2 = pygame.image.load(example_path(os.path.join("data", "brick.png"))) + + self.assertEqual(im.get_palette(), ((0, 0, 0, 255), (255, 255, 255, 255))) + self.assertEqual(im2.get_palette(), ((0, 0, 0, 255), (0, 0, 0, 255))) + + self.assertEqual(repr(im.convert(32)), "") + self.assertEqual(repr(im2.convert(32)), "") + + # Ensure a palette format to palette format works. + im3 = im.convert(8) + self.assertEqual(repr(im3), "") + self.assertEqual(im3.get_palette(), im.get_palette()) + + finally: + pygame.display.quit() + + def test_convert_init(self): + """Ensure initialization exceptions are raised + for surf.convert().""" + pygame.display.quit() + surf = pygame.Surface((1, 1)) + + self.assertRaisesRegex(pygame.error, "display initialized", surf.convert) + + pygame.display.init() + try: + if os.environ.get("SDL_VIDEODRIVER") != "dummy": + try: + surf.convert(32) + surf.convert(pygame.Surface((1, 1))) + except pygame.error: + self.fail("convert() should not raise an exception here.") + + self.assertRaisesRegex(pygame.error, "No video mode", surf.convert) + + pygame.display.set_mode((640, 480)) + try: + surf.convert() + except pygame.error: + self.fail("convert() should not raise an exception here.") + finally: + pygame.display.quit() + + def test_convert_alpha_init(self): + """Ensure initialization exceptions are raised + for surf.convert_alpha().""" + pygame.display.quit() + surf = pygame.Surface((1, 1)) + + self.assertRaisesRegex(pygame.error, "display initialized", surf.convert_alpha) + + pygame.display.init() + try: + self.assertRaisesRegex(pygame.error, "No video mode", surf.convert_alpha) + + pygame.display.set_mode((640, 480)) + try: + surf.convert_alpha() + except pygame.error: + self.fail("convert_alpha() should not raise an exception here.") + finally: + pygame.display.quit() + + def test_convert_alpha_SRCALPHA(self): + """Ensure that the surface returned by surf.convert_alpha() + has alpha blending enabled""" + pygame.display.init() + try: + pygame.display.set_mode((640, 480)) + + s1 = pygame.Surface((100, 100), 0, 32) + # s2=pygame.Surface((100,100), pygame.SRCALPHA, 32) + s1_alpha = s1.convert_alpha() + self.assertEqual(s1_alpha.get_flags() & SRCALPHA, SRCALPHA) + self.assertEqual(s1_alpha.get_alpha(), 255) + finally: + pygame.display.quit() + + def test_src_alpha_issue_1289(self): + """blit should be white.""" + surf1 = pygame.Surface((1, 1), pygame.SRCALPHA, 32) + surf1.fill((255, 255, 255, 100)) + + surf2 = pygame.Surface((1, 1), pygame.SRCALPHA, 32) + self.assertEqual(surf2.get_at((0, 0)), (0, 0, 0, 0)) + surf2.blit(surf1, (0, 0)) + + self.assertEqual(surf1.get_at((0, 0)), (255, 255, 255, 100)) + self.assertEqual(surf2.get_at((0, 0)), (255, 255, 255, 100)) + + def test_src_alpha_compatible(self): + """ "What pygame 1.9.x did". Is the alpha blitter as before?""" + + # The table below was generated with the SDL1 blit. + # def print_table(): + # nums = [0, 1, 65, 126, 127, 199, 254, 255] + # results = {} + # for dest_r, dest_b, dest_a in zip(nums, reversed(nums), reversed(nums)): + # for src_r, src_b, src_a in zip(nums, reversed(nums), nums): + # src_surf = pygame.Surface((66, 66), pygame.SRCALPHA, 32) + # src_surf.fill((src_r, 255, src_b, src_a)) + # dest_surf = pygame.Surface((66, 66), pygame.SRCALPHA, 32) + # dest_surf.fill((dest_r, 255, dest_b, dest_a)) + # dest_surf.blit(src_surf, (0, 0)) + # key = ((dest_r, dest_b, dest_a), (src_r, src_b, src_a)) + # results[key] = dest_surf.get_at((65, 33)) + # print("(dest_r, dest_b, dest_a), (src_r, src_b, src_a): color") + # pprint(results) + + results_expected = { + ((0, 255, 255), (0, 255, 0)): (0, 255, 255, 255), + ((0, 255, 255), (1, 254, 1)): (0, 255, 255, 255), + ((0, 255, 255), (65, 199, 65)): (16, 255, 241, 255), + ((0, 255, 255), (126, 127, 126)): (62, 255, 192, 255), + ((0, 255, 255), (127, 126, 127)): (63, 255, 191, 255), + ((0, 255, 255), (199, 65, 199)): (155, 255, 107, 255), + ((0, 255, 255), (254, 1, 254)): (253, 255, 2, 255), + ((0, 255, 255), (255, 0, 255)): (255, 255, 0, 255), + ((1, 254, 254), (0, 255, 0)): (1, 255, 254, 254), + ((1, 254, 254), (1, 254, 1)): (1, 255, 254, 255), + ((1, 254, 254), (65, 199, 65)): (17, 255, 240, 255), + ((1, 254, 254), (126, 127, 126)): (63, 255, 191, 255), + ((1, 254, 254), (127, 126, 127)): (64, 255, 190, 255), + ((1, 254, 254), (199, 65, 199)): (155, 255, 107, 255), + ((1, 254, 254), (254, 1, 254)): (253, 255, 2, 255), + ((1, 254, 254), (255, 0, 255)): (255, 255, 0, 255), + ((65, 199, 199), (0, 255, 0)): (65, 255, 199, 199), + ((65, 199, 199), (1, 254, 1)): (64, 255, 200, 200), + ((65, 199, 199), (65, 199, 65)): (65, 255, 199, 214), + ((65, 199, 199), (126, 127, 126)): (95, 255, 164, 227), + ((65, 199, 199), (127, 126, 127)): (96, 255, 163, 227), + ((65, 199, 199), (199, 65, 199)): (169, 255, 95, 243), + ((65, 199, 199), (254, 1, 254)): (253, 255, 2, 255), + ((65, 199, 199), (255, 0, 255)): (255, 255, 0, 255), + ((126, 127, 127), (0, 255, 0)): (126, 255, 127, 127), + ((126, 127, 127), (1, 254, 1)): (125, 255, 128, 128), + ((126, 127, 127), (65, 199, 65)): (110, 255, 146, 160), + ((126, 127, 127), (126, 127, 126)): (126, 255, 127, 191), + ((126, 127, 127), (127, 126, 127)): (126, 255, 126, 191), + ((126, 127, 127), (199, 65, 199)): (183, 255, 79, 227), + ((126, 127, 127), (254, 1, 254)): (253, 255, 1, 255), + ((126, 127, 127), (255, 0, 255)): (255, 255, 0, 255), + ((127, 126, 126), (0, 255, 0)): (127, 255, 126, 126), + ((127, 126, 126), (1, 254, 1)): (126, 255, 127, 127), + ((127, 126, 126), (65, 199, 65)): (111, 255, 145, 159), + ((127, 126, 126), (126, 127, 126)): (127, 255, 126, 190), + ((127, 126, 126), (127, 126, 127)): (127, 255, 126, 191), + ((127, 126, 126), (199, 65, 199)): (183, 255, 78, 227), + ((127, 126, 126), (254, 1, 254)): (254, 255, 1, 255), + ((127, 126, 126), (255, 0, 255)): (255, 255, 0, 255), + ((199, 65, 65), (0, 255, 0)): (199, 255, 65, 65), + ((199, 65, 65), (1, 254, 1)): (198, 255, 66, 66), + ((199, 65, 65), (65, 199, 65)): (165, 255, 99, 114), + ((199, 65, 65), (126, 127, 126)): (163, 255, 96, 159), + ((199, 65, 65), (127, 126, 127)): (163, 255, 95, 160), + ((199, 65, 65), (199, 65, 199)): (199, 255, 65, 214), + ((199, 65, 65), (254, 1, 254)): (254, 255, 1, 255), + ((199, 65, 65), (255, 0, 255)): (255, 255, 0, 255), + ((254, 1, 1), (0, 255, 0)): (254, 255, 1, 1), + ((254, 1, 1), (1, 254, 1)): (253, 255, 2, 2), + ((254, 1, 1), (65, 199, 65)): (206, 255, 52, 66), + ((254, 1, 1), (126, 127, 126)): (191, 255, 63, 127), + ((254, 1, 1), (127, 126, 127)): (191, 255, 63, 128), + ((254, 1, 1), (199, 65, 199)): (212, 255, 51, 200), + ((254, 1, 1), (254, 1, 254)): (254, 255, 1, 255), + ((254, 1, 1), (255, 0, 255)): (255, 255, 0, 255), + ((255, 0, 0), (0, 255, 0)): (0, 255, 255, 0), + ((255, 0, 0), (1, 254, 1)): (1, 255, 254, 1), + ((255, 0, 0), (65, 199, 65)): (65, 255, 199, 65), + ((255, 0, 0), (126, 127, 126)): (126, 255, 127, 126), + ((255, 0, 0), (127, 126, 127)): (127, 255, 126, 127), + ((255, 0, 0), (199, 65, 199)): (199, 255, 65, 199), + ((255, 0, 0), (254, 1, 254)): (254, 255, 1, 254), + ((255, 0, 0), (255, 0, 255)): (255, 255, 0, 255), + } + + # chosen because they contain edge cases. + nums = [0, 1, 65, 126, 127, 199, 254, 255] + results = {} + for dst_r, dst_b, dst_a in zip(nums, reversed(nums), reversed(nums)): + for src_r, src_b, src_a in zip(nums, reversed(nums), nums): + with self.subTest( + src_r=src_r, + src_b=src_b, + src_a=src_a, + dest_r=dst_r, + dest_b=dst_b, + dest_a=dst_a, + ): + src_surf = pygame.Surface((66, 66), pygame.SRCALPHA, 32) + src_surf.fill((src_r, 255, src_b, src_a)) + dest_surf = pygame.Surface((66, 66), pygame.SRCALPHA, 32) + dest_surf.fill((dst_r, 255, dst_b, dst_a)) + + dest_surf.blit(src_surf, (0, 0)) + key = ((dst_r, dst_b, dst_a), (src_r, src_b, src_a)) + results[key] = dest_surf.get_at((65, 33)) + self.assertEqual(results[key], results_expected[key]) + + self.assertEqual(results, results_expected) + + def test_src_alpha_compatible_16bit(self): + """ "What pygame 1.9.x did". Is the alpha blitter as before?""" + + # The table below was generated with the SDL1 blit. + # def print_table(): + # nums = [0, 1, 65, 126, 127, 199, 254, 255] + # results = {} + # for dest_r, dest_b, dest_a in zip(nums, reversed(nums), reversed(nums)): + # for src_r, src_b, src_a in zip(nums, reversed(nums), nums): + # src_surf = pygame.Surface((66, 66), pygame.SRCALPHA, 16) + # src_surf.fill((src_r, 255, src_b, src_a)) + # dest_surf = pygame.Surface((66, 66), pygame.SRCALPHA, 16) + # dest_surf.fill((dest_r, 255, dest_b, dest_a)) + # dest_surf.blit(src_surf, (0, 0)) + # key = ((dest_r, dest_b, dest_a), (src_r, src_b, src_a)) + # results[key] = dest_surf.get_at((65, 33)) + # print("(dest_r, dest_b, dest_a), (src_r, src_b, src_a): color") + # pprint(results) + + results_expected = { + ((0, 255, 255), (0, 255, 0)): (0, 255, 255, 255), + ((0, 255, 255), (1, 254, 1)): (0, 255, 255, 255), + ((0, 255, 255), (65, 199, 65)): (17, 255, 255, 255), + ((0, 255, 255), (126, 127, 126)): (51, 255, 204, 255), + ((0, 255, 255), (127, 126, 127)): (51, 255, 204, 255), + ((0, 255, 255), (199, 65, 199)): (170, 255, 102, 255), + ((0, 255, 255), (254, 1, 254)): (255, 255, 0, 255), + ((0, 255, 255), (255, 0, 255)): (255, 255, 0, 255), + ((1, 254, 254), (0, 255, 0)): (0, 255, 255, 255), + ((1, 254, 254), (1, 254, 1)): (0, 255, 255, 255), + ((1, 254, 254), (65, 199, 65)): (17, 255, 255, 255), + ((1, 254, 254), (126, 127, 126)): (51, 255, 204, 255), + ((1, 254, 254), (127, 126, 127)): (51, 255, 204, 255), + ((1, 254, 254), (199, 65, 199)): (170, 255, 102, 255), + ((1, 254, 254), (254, 1, 254)): (255, 255, 0, 255), + ((1, 254, 254), (255, 0, 255)): (255, 255, 0, 255), + ((65, 199, 199), (0, 255, 0)): (68, 255, 204, 204), + ((65, 199, 199), (1, 254, 1)): (68, 255, 204, 204), + ((65, 199, 199), (65, 199, 65)): (68, 255, 204, 221), + ((65, 199, 199), (126, 127, 126)): (85, 255, 170, 238), + ((65, 199, 199), (127, 126, 127)): (85, 255, 170, 238), + ((65, 199, 199), (199, 65, 199)): (187, 255, 85, 255), + ((65, 199, 199), (254, 1, 254)): (255, 255, 0, 255), + ((65, 199, 199), (255, 0, 255)): (255, 255, 0, 255), + ((126, 127, 127), (0, 255, 0)): (119, 255, 119, 119), + ((126, 127, 127), (1, 254, 1)): (119, 255, 119, 119), + ((126, 127, 127), (65, 199, 65)): (102, 255, 136, 153), + ((126, 127, 127), (126, 127, 126)): (119, 255, 119, 187), + ((126, 127, 127), (127, 126, 127)): (119, 255, 119, 187), + ((126, 127, 127), (199, 65, 199)): (187, 255, 68, 238), + ((126, 127, 127), (254, 1, 254)): (255, 255, 0, 255), + ((126, 127, 127), (255, 0, 255)): (255, 255, 0, 255), + ((127, 126, 126), (0, 255, 0)): (119, 255, 119, 119), + ((127, 126, 126), (1, 254, 1)): (119, 255, 119, 119), + ((127, 126, 126), (65, 199, 65)): (102, 255, 136, 153), + ((127, 126, 126), (126, 127, 126)): (119, 255, 119, 187), + ((127, 126, 126), (127, 126, 127)): (119, 255, 119, 187), + ((127, 126, 126), (199, 65, 199)): (187, 255, 68, 238), + ((127, 126, 126), (254, 1, 254)): (255, 255, 0, 255), + ((127, 126, 126), (255, 0, 255)): (255, 255, 0, 255), + ((199, 65, 65), (0, 255, 0)): (204, 255, 68, 68), + ((199, 65, 65), (1, 254, 1)): (204, 255, 68, 68), + ((199, 65, 65), (65, 199, 65)): (170, 255, 102, 119), + ((199, 65, 65), (126, 127, 126)): (170, 255, 85, 153), + ((199, 65, 65), (127, 126, 127)): (170, 255, 85, 153), + ((199, 65, 65), (199, 65, 199)): (204, 255, 68, 221), + ((199, 65, 65), (254, 1, 254)): (255, 255, 0, 255), + ((199, 65, 65), (255, 0, 255)): (255, 255, 0, 255), + ((254, 1, 1), (0, 255, 0)): (0, 255, 255, 0), + ((254, 1, 1), (1, 254, 1)): (0, 255, 255, 0), + ((254, 1, 1), (65, 199, 65)): (68, 255, 204, 68), + ((254, 1, 1), (126, 127, 126)): (119, 255, 119, 119), + ((254, 1, 1), (127, 126, 127)): (119, 255, 119, 119), + ((254, 1, 1), (199, 65, 199)): (204, 255, 68, 204), + ((254, 1, 1), (254, 1, 254)): (255, 255, 0, 255), + ((254, 1, 1), (255, 0, 255)): (255, 255, 0, 255), + ((255, 0, 0), (0, 255, 0)): (0, 255, 255, 0), + ((255, 0, 0), (1, 254, 1)): (0, 255, 255, 0), + ((255, 0, 0), (65, 199, 65)): (68, 255, 204, 68), + ((255, 0, 0), (126, 127, 126)): (119, 255, 119, 119), + ((255, 0, 0), (127, 126, 127)): (119, 255, 119, 119), + ((255, 0, 0), (199, 65, 199)): (204, 255, 68, 204), + ((255, 0, 0), (254, 1, 254)): (255, 255, 0, 255), + ((255, 0, 0), (255, 0, 255)): (255, 255, 0, 255), + } + + # chosen because they contain edge cases. + nums = [0, 1, 65, 126, 127, 199, 254, 255] + results = {} + for dst_r, dst_b, dst_a in zip(nums, reversed(nums), reversed(nums)): + for src_r, src_b, src_a in zip(nums, reversed(nums), nums): + with self.subTest( + src_r=src_r, + src_b=src_b, + src_a=src_a, + dest_r=dst_r, + dest_b=dst_b, + dest_a=dst_a, + ): + src_surf = pygame.Surface((66, 66), pygame.SRCALPHA, 16) + src_surf.fill((src_r, 255, src_b, src_a)) + dest_surf = pygame.Surface((66, 66), pygame.SRCALPHA, 16) + dest_surf.fill((dst_r, 255, dst_b, dst_a)) + + dest_surf.blit(src_surf, (0, 0)) + key = ((dst_r, dst_b, dst_a), (src_r, src_b, src_a)) + results[key] = dest_surf.get_at((65, 33)) + self.assertEqual(results[key], results_expected[key]) + + self.assertEqual(results, results_expected) + + def test_sdl1_mimic_blitter_with_set_alpha(self): + """does the SDL 1 style blitter in pygame 2 work with set_alpha(), + this feature only exists in pygame 2/SDL2 SDL1 did not support + combining surface and pixel alpha""" + + results_expected = { + ((0, 255, 255), (0, 255, 0)): (0, 255, 255, 255), + ((0, 255, 255), (1, 254, 1)): (0, 255, 255, 255), + ((0, 255, 255), (65, 199, 65)): (16, 255, 241, 255), + ((0, 255, 255), (126, 127, 126)): (62, 255, 192, 255), + ((0, 255, 255), (127, 126, 127)): (63, 255, 191, 255), + ((0, 255, 255), (199, 65, 199)): (155, 255, 107, 255), + ((0, 255, 255), (254, 1, 254)): (253, 255, 2, 255), + ((0, 255, 255), (255, 0, 255)): (255, 255, 0, 255), + ((1, 254, 254), (0, 255, 0)): (1, 255, 254, 254), + ((1, 254, 254), (1, 254, 1)): (1, 255, 254, 255), + ((1, 254, 254), (65, 199, 65)): (17, 255, 240, 255), + ((1, 254, 254), (126, 127, 126)): (63, 255, 191, 255), + ((1, 254, 254), (127, 126, 127)): (64, 255, 190, 255), + ((1, 254, 254), (199, 65, 199)): (155, 255, 107, 255), + ((1, 254, 254), (254, 1, 254)): (253, 255, 2, 255), + ((1, 254, 254), (255, 0, 255)): (255, 255, 0, 255), + ((65, 199, 199), (0, 255, 0)): (65, 255, 199, 199), + ((65, 199, 199), (1, 254, 1)): (64, 255, 200, 200), + ((65, 199, 199), (65, 199, 65)): (65, 255, 199, 214), + ((65, 199, 199), (126, 127, 126)): (95, 255, 164, 227), + ((65, 199, 199), (127, 126, 127)): (96, 255, 163, 227), + ((65, 199, 199), (199, 65, 199)): (169, 255, 95, 243), + ((65, 199, 199), (254, 1, 254)): (253, 255, 2, 255), + ((65, 199, 199), (255, 0, 255)): (255, 255, 0, 255), + ((126, 127, 127), (0, 255, 0)): (126, 255, 127, 127), + ((126, 127, 127), (1, 254, 1)): (125, 255, 128, 128), + ((126, 127, 127), (65, 199, 65)): (110, 255, 146, 160), + ((126, 127, 127), (126, 127, 126)): (126, 255, 127, 191), + ((126, 127, 127), (127, 126, 127)): (126, 255, 126, 191), + ((126, 127, 127), (199, 65, 199)): (183, 255, 79, 227), + ((126, 127, 127), (254, 1, 254)): (253, 255, 1, 255), + ((126, 127, 127), (255, 0, 255)): (255, 255, 0, 255), + ((127, 126, 126), (0, 255, 0)): (127, 255, 126, 126), + ((127, 126, 126), (1, 254, 1)): (126, 255, 127, 127), + ((127, 126, 126), (65, 199, 65)): (111, 255, 145, 159), + ((127, 126, 126), (126, 127, 126)): (127, 255, 126, 190), + ((127, 126, 126), (127, 126, 127)): (127, 255, 126, 191), + ((127, 126, 126), (199, 65, 199)): (183, 255, 78, 227), + ((127, 126, 126), (254, 1, 254)): (254, 255, 1, 255), + ((127, 126, 126), (255, 0, 255)): (255, 255, 0, 255), + ((199, 65, 65), (0, 255, 0)): (199, 255, 65, 65), + ((199, 65, 65), (1, 254, 1)): (198, 255, 66, 66), + ((199, 65, 65), (65, 199, 65)): (165, 255, 99, 114), + ((199, 65, 65), (126, 127, 126)): (163, 255, 96, 159), + ((199, 65, 65), (127, 126, 127)): (163, 255, 95, 160), + ((199, 65, 65), (199, 65, 199)): (199, 255, 65, 214), + ((199, 65, 65), (254, 1, 254)): (254, 255, 1, 255), + ((199, 65, 65), (255, 0, 255)): (255, 255, 0, 255), + ((254, 1, 1), (0, 255, 0)): (254, 255, 1, 1), + ((254, 1, 1), (1, 254, 1)): (253, 255, 2, 2), + ((254, 1, 1), (65, 199, 65)): (206, 255, 52, 66), + ((254, 1, 1), (126, 127, 126)): (191, 255, 63, 127), + ((254, 1, 1), (127, 126, 127)): (191, 255, 63, 128), + ((254, 1, 1), (199, 65, 199)): (212, 255, 51, 200), + ((254, 1, 1), (254, 1, 254)): (254, 255, 1, 255), + ((254, 1, 1), (255, 0, 255)): (255, 255, 0, 255), + ((255, 0, 0), (0, 255, 0)): (0, 255, 255, 0), + ((255, 0, 0), (1, 254, 1)): (1, 255, 254, 1), + ((255, 0, 0), (65, 199, 65)): (65, 255, 199, 65), + ((255, 0, 0), (126, 127, 126)): (126, 255, 127, 126), + ((255, 0, 0), (127, 126, 127)): (127, 255, 126, 127), + ((255, 0, 0), (199, 65, 199)): (199, 255, 65, 199), + ((255, 0, 0), (254, 1, 254)): (254, 255, 1, 254), + ((255, 0, 0), (255, 0, 255)): (255, 255, 0, 255), + } + + # chosen because they contain edge cases. + nums = [0, 1, 65, 126, 127, 199, 254, 255] + results = {} + for dst_r, dst_b, dst_a in zip(nums, reversed(nums), reversed(nums)): + for src_r, src_b, src_a in zip(nums, reversed(nums), nums): + with self.subTest( + src_r=src_r, + src_b=src_b, + src_a=src_a, + dest_r=dst_r, + dest_b=dst_b, + dest_a=dst_a, + ): + src_surf = pygame.Surface((66, 66), pygame.SRCALPHA, 32) + src_surf.fill((src_r, 255, src_b, 255)) + src_surf.set_alpha(src_a) + dest_surf = pygame.Surface((66, 66), pygame.SRCALPHA, 32) + dest_surf.fill((dst_r, 255, dst_b, dst_a)) + + dest_surf.blit(src_surf, (0, 0)) + key = ((dst_r, dst_b, dst_a), (src_r, src_b, src_a)) + results[key] = dest_surf.get_at((65, 33)) + self.assertEqual(results[key], results_expected[key]) + + self.assertEqual(results, results_expected) + + @unittest.skipIf( + "arm" in platform.machine() or "aarch64" in platform.machine(), + "sdl2 blitter produces different results on arm", + ) + def test_src_alpha_sdl2_blitter(self): + """Checking that the BLEND_ALPHA_SDL2 flag works - this feature + only exists when using SDL2""" + + results_expected = { + ((0, 255, 255), (0, 255, 0)): (0, 255, 255, 255), + ((0, 255, 255), (1, 254, 1)): (0, 253, 253, 253), + ((0, 255, 255), (65, 199, 65)): (16, 253, 239, 253), + ((0, 255, 255), (126, 127, 126)): (62, 253, 190, 253), + ((0, 255, 255), (127, 126, 127)): (63, 253, 189, 253), + ((0, 255, 255), (199, 65, 199)): (154, 253, 105, 253), + ((0, 255, 255), (254, 1, 254)): (252, 253, 0, 253), + ((0, 255, 255), (255, 0, 255)): (255, 255, 0, 255), + ((1, 254, 254), (0, 255, 0)): (1, 255, 254, 254), + ((1, 254, 254), (1, 254, 1)): (0, 253, 252, 252), + ((1, 254, 254), (65, 199, 65)): (16, 253, 238, 252), + ((1, 254, 254), (126, 127, 126)): (62, 253, 189, 252), + ((1, 254, 254), (127, 126, 127)): (63, 253, 189, 253), + ((1, 254, 254), (199, 65, 199)): (154, 253, 105, 253), + ((1, 254, 254), (254, 1, 254)): (252, 253, 0, 253), + ((1, 254, 254), (255, 0, 255)): (255, 255, 0, 255), + ((65, 199, 199), (0, 255, 0)): (65, 255, 199, 199), + ((65, 199, 199), (1, 254, 1)): (64, 253, 197, 197), + ((65, 199, 199), (65, 199, 65)): (64, 253, 197, 211), + ((65, 199, 199), (126, 127, 126)): (94, 253, 162, 225), + ((65, 199, 199), (127, 126, 127)): (95, 253, 161, 225), + ((65, 199, 199), (199, 65, 199)): (168, 253, 93, 241), + ((65, 199, 199), (254, 1, 254)): (252, 253, 0, 253), + ((65, 199, 199), (255, 0, 255)): (255, 255, 0, 255), + ((126, 127, 127), (0, 255, 0)): (126, 255, 127, 127), + ((126, 127, 127), (1, 254, 1)): (125, 253, 126, 126), + ((126, 127, 127), (65, 199, 65)): (109, 253, 144, 158), + ((126, 127, 127), (126, 127, 126)): (125, 253, 125, 188), + ((126, 127, 127), (127, 126, 127)): (126, 253, 125, 189), + ((126, 127, 127), (199, 65, 199)): (181, 253, 77, 225), + ((126, 127, 127), (254, 1, 254)): (252, 253, 0, 253), + ((126, 127, 127), (255, 0, 255)): (255, 255, 0, 255), + ((127, 126, 126), (0, 255, 0)): (127, 255, 126, 126), + ((127, 126, 126), (1, 254, 1)): (126, 253, 125, 125), + ((127, 126, 126), (65, 199, 65)): (110, 253, 143, 157), + ((127, 126, 126), (126, 127, 126)): (125, 253, 125, 188), + ((127, 126, 126), (127, 126, 127)): (126, 253, 125, 189), + ((127, 126, 126), (199, 65, 199)): (181, 253, 77, 225), + ((127, 126, 126), (254, 1, 254)): (252, 253, 0, 253), + ((127, 126, 126), (255, 0, 255)): (255, 255, 0, 255), + ((199, 65, 65), (0, 255, 0)): (199, 255, 65, 65), + ((199, 65, 65), (1, 254, 1)): (197, 253, 64, 64), + ((199, 65, 65), (65, 199, 65)): (163, 253, 98, 112), + ((199, 65, 65), (126, 127, 126)): (162, 253, 94, 157), + ((199, 65, 65), (127, 126, 127)): (162, 253, 94, 158), + ((199, 65, 65), (199, 65, 199)): (197, 253, 64, 212), + ((199, 65, 65), (254, 1, 254)): (252, 253, 0, 253), + ((199, 65, 65), (255, 0, 255)): (255, 255, 0, 255), + ((254, 1, 1), (0, 255, 0)): (254, 255, 1, 1), + ((254, 1, 1), (1, 254, 1)): (252, 253, 0, 0), + ((254, 1, 1), (65, 199, 65)): (204, 253, 50, 64), + ((254, 1, 1), (126, 127, 126)): (189, 253, 62, 125), + ((254, 1, 1), (127, 126, 127)): (190, 253, 62, 126), + ((254, 1, 1), (199, 65, 199)): (209, 253, 50, 198), + ((254, 1, 1), (254, 1, 254)): (252, 253, 0, 253), + ((254, 1, 1), (255, 0, 255)): (255, 255, 0, 255), + ((255, 0, 0), (0, 255, 0)): (255, 255, 0, 0), + ((255, 0, 0), (1, 254, 1)): (253, 253, 0, 0), + ((255, 0, 0), (65, 199, 65)): (205, 253, 50, 64), + ((255, 0, 0), (126, 127, 126)): (190, 253, 62, 125), + ((255, 0, 0), (127, 126, 127)): (190, 253, 62, 126), + ((255, 0, 0), (199, 65, 199)): (209, 253, 50, 198), + ((255, 0, 0), (254, 1, 254)): (252, 253, 0, 253), + ((255, 0, 0), (255, 0, 255)): (255, 255, 0, 255), + } + + # chosen because they contain edge cases. + nums = [0, 1, 65, 126, 127, 199, 254, 255] + results = {} + for dst_r, dst_b, dst_a in zip(nums, reversed(nums), reversed(nums)): + for src_r, src_b, src_a in zip(nums, reversed(nums), nums): + with self.subTest( + src_r=src_r, + src_b=src_b, + src_a=src_a, + dest_r=dst_r, + dest_b=dst_b, + dest_a=dst_a, + ): + src_surf = pygame.Surface((66, 66), pygame.SRCALPHA, 32) + src_surf.fill((src_r, 255, src_b, src_a)) + dest_surf = pygame.Surface((66, 66), pygame.SRCALPHA, 32) + dest_surf.fill((dst_r, 255, dst_b, dst_a)) + + dest_surf.blit( + src_surf, (0, 0), special_flags=pygame.BLEND_ALPHA_SDL2 + ) + key = ((dst_r, dst_b, dst_a), (src_r, src_b, src_a)) + results[key] = dest_surf.get_at((65, 33)) + self.assertEqual(results[key], results_expected[key]) + + # print("(dest_r, dest_b, dest_a), (src_r, src_b, src_a): color") + # pprint(results) + self.assertEqual(results, results_expected) + + def test_opaque_destination_blit_with_set_alpha(self): + # no set_alpha() + src_surf = pygame.Surface((32, 32), pygame.SRCALPHA, 32) + src_surf.fill((255, 255, 255, 200)) + dest_surf = pygame.Surface((32, 32)) + dest_surf.fill((100, 100, 100)) + + dest_surf.blit(src_surf, (0, 0)) + + no_surf_alpha_col = dest_surf.get_at((0, 0)) + + dest_surf.fill((100, 100, 100)) + dest_surf.set_alpha(200) + dest_surf.blit(src_surf, (0, 0)) + + surf_alpha_col = dest_surf.get_at((0, 0)) + + self.assertEqual(no_surf_alpha_col, surf_alpha_col) + + def todo_test_convert(self): + + # __doc__ (as of 2008-08-02) for pygame.surface.Surface.convert: + + # Surface.convert(Surface): return Surface + # Surface.convert(depth, flags=0): return Surface + # Surface.convert(masks, flags=0): return Surface + # Surface.convert(): return Surface + # change the pixel format of an image + # + # Creates a new copy of the Surface with the pixel format changed. The + # new pixel format can be determined from another existing Surface. + # Otherwise depth, flags, and masks arguments can be used, similar to + # the pygame.Surface() call. + # + # If no arguments are passed the new Surface will have the same pixel + # format as the display Surface. This is always the fastest format for + # blitting. It is a good idea to convert all Surfaces before they are + # blitted many times. + # + # The converted Surface will have no pixel alphas. They will be + # stripped if the original had them. See Surface.convert_alpha() for + # preserving or creating per-pixel alphas. + # + + self.fail() + + def test_convert__pixel_format_as_surface_subclass(self): + """Ensure convert accepts a Surface subclass argument.""" + expected_size = (23, 17) + convert_surface = SurfaceSubclass(expected_size, 0, 32) + depth_surface = SurfaceSubclass((31, 61), 0, 32) + + pygame.display.init() + try: + surface = convert_surface.convert(depth_surface) + + self.assertIsNot(surface, depth_surface) + self.assertIsNot(surface, convert_surface) + self.assertIsInstance(surface, pygame.Surface) + self.assertIsInstance(surface, SurfaceSubclass) + self.assertEqual(surface.get_size(), expected_size) + finally: + pygame.display.quit() + + def test_convert_alpha(self): + """Ensure the surface returned by surf.convert_alpha + has alpha values added""" + pygame.display.init() + try: + pygame.display.set_mode((640, 480)) + + s1 = pygame.Surface((100, 100), 0, 32) + s1_alpha = pygame.Surface.convert_alpha(s1) + + s2 = pygame.Surface((100, 100), 0, 32) + s2_alpha = s2.convert_alpha() + + s3 = pygame.Surface((100, 100), 0, 8) + s3_alpha = s3.convert_alpha() + + s4 = pygame.Surface((100, 100), 0, 12) + s4_alpha = s4.convert_alpha() + + s5 = pygame.Surface((100, 100), 0, 15) + s5_alpha = s5.convert_alpha() + + s6 = pygame.Surface((100, 100), 0, 16) + s6_alpha = s6.convert_alpha() + + s7 = pygame.Surface((100, 100), 0, 24) + s7_alpha = s7.convert_alpha() + + self.assertEqual(s1_alpha.get_alpha(), 255) + self.assertEqual(s2_alpha.get_alpha(), 255) + self.assertEqual(s3_alpha.get_alpha(), 255) + self.assertEqual(s4_alpha.get_alpha(), 255) + self.assertEqual(s5_alpha.get_alpha(), 255) + self.assertEqual(s6_alpha.get_alpha(), 255) + self.assertEqual(s7_alpha.get_alpha(), 255) + + self.assertEqual(s1_alpha.get_bitsize(), 32) + self.assertEqual(s2_alpha.get_bitsize(), 32) + self.assertEqual(s3_alpha.get_bitsize(), 32) + self.assertEqual(s4_alpha.get_bitsize(), 32) + self.assertEqual(s5_alpha.get_bitsize(), 32) + self.assertEqual(s6_alpha.get_bitsize(), 32) + self.assertEqual(s6_alpha.get_bitsize(), 32) + + with self.assertRaises(pygame.error): + surface = pygame.display.set_mode() + pygame.display.quit() + surface.convert_alpha() + + finally: + pygame.display.quit() + + def test_convert_alpha__pixel_format_as_surface_subclass(self): + """Ensure convert_alpha accepts a Surface subclass argument.""" + expected_size = (23, 17) + convert_surface = SurfaceSubclass(expected_size, SRCALPHA, 32) + depth_surface = SurfaceSubclass((31, 57), SRCALPHA, 32) + + pygame.display.init() + try: + pygame.display.set_mode((60, 60)) + + # This is accepted as an argument, but its values are ignored. + # See issue #599. + surface = convert_surface.convert_alpha(depth_surface) + + self.assertIsNot(surface, depth_surface) + self.assertIsNot(surface, convert_surface) + self.assertIsInstance(surface, pygame.Surface) + self.assertIsInstance(surface, SurfaceSubclass) + self.assertEqual(surface.get_size(), expected_size) + finally: + pygame.display.quit() + + def test_get_abs_offset(self): + pygame.display.init() + try: + parent = pygame.Surface((64, 64), SRCALPHA, 32) + + # Stack bunch of subsurfaces + sub_level_1 = parent.subsurface((2, 2), (34, 37)) + sub_level_2 = sub_level_1.subsurface((0, 0), (30, 29)) + sub_level_3 = sub_level_2.subsurface((3, 7), (20, 21)) + sub_level_4 = sub_level_3.subsurface((6, 1), (14, 14)) + sub_level_5 = sub_level_4.subsurface((5, 6), (3, 4)) + + # Parent is always (0, 0) + self.assertEqual(parent.get_abs_offset(), (0, 0)) + # Total offset: (0+2, 0+2) = (2, 2) + self.assertEqual(sub_level_1.get_abs_offset(), (2, 2)) + # Total offset: (0+2+0, 0+2+0) = (2, 2) + self.assertEqual(sub_level_2.get_abs_offset(), (2, 2)) + # Total offset: (0+2+0+3, 0+2+0+7) = (5, 9) + self.assertEqual(sub_level_3.get_abs_offset(), (5, 9)) + # Total offset: (0+2+0+3+6, 0+2+0+7+1) = (11, 10) + self.assertEqual(sub_level_4.get_abs_offset(), (11, 10)) + # Total offset: (0+2+0+3+6+5, 0+2+0+7+1+6) = (16, 16) + self.assertEqual(sub_level_5.get_abs_offset(), (16, 16)) + + with self.assertRaises(pygame.error): + surface = pygame.display.set_mode() + pygame.display.quit() + surface.get_abs_offset() + finally: + pygame.display.quit() + + def test_get_abs_parent(self): + pygame.display.init() + try: + parent = pygame.Surface((32, 32), SRCALPHA, 32) + + # Stack bunch of subsurfaces + sub_level_1 = parent.subsurface((1, 1), (15, 15)) + sub_level_2 = sub_level_1.subsurface((1, 1), (12, 12)) + sub_level_3 = sub_level_2.subsurface((1, 1), (9, 9)) + sub_level_4 = sub_level_3.subsurface((1, 1), (8, 8)) + sub_level_5 = sub_level_4.subsurface((2, 2), (3, 4)) + sub_level_6 = sub_level_5.subsurface((0, 0), (2, 1)) + + # Can't have subsurfaces bigger than parents + self.assertRaises(ValueError, parent.subsurface, (5, 5), (100, 100)) + self.assertRaises(ValueError, sub_level_3.subsurface, (0, 0), (11, 5)) + self.assertRaises(ValueError, sub_level_6.subsurface, (0, 0), (5, 5)) + + # Calling get_abs_parent on parent should return itself + self.assertEqual(parent.get_abs_parent(), parent) + + # On subclass "depth" of 1, get_abs_parent and get_parent should return the same + self.assertEqual(sub_level_1.get_abs_parent(), sub_level_1.get_parent()) + self.assertEqual(sub_level_2.get_abs_parent(), parent) + self.assertEqual(sub_level_3.get_abs_parent(), parent) + self.assertEqual(sub_level_4.get_abs_parent(), parent) + self.assertEqual(sub_level_5.get_abs_parent(), parent) + self.assertEqual( + sub_level_6.get_abs_parent(), sub_level_6.get_parent().get_abs_parent() + ) + + with self.assertRaises(pygame.error): + surface = pygame.display.set_mode() + pygame.display.quit() + surface.get_abs_parent() + finally: + pygame.display.quit() + + def test_get_at(self): + surf = pygame.Surface((2, 2), 0, 24) + c00 = pygame.Color(1, 2, 3) + c01 = pygame.Color(5, 10, 15) + c10 = pygame.Color(100, 50, 0) + c11 = pygame.Color(4, 5, 6) + surf.set_at((0, 0), c00) + surf.set_at((0, 1), c01) + surf.set_at((1, 0), c10) + surf.set_at((1, 1), c11) + c = surf.get_at((0, 0)) + self.assertIsInstance(c, pygame.Color) + self.assertEqual(c, c00) + self.assertEqual(surf.get_at((0, 1)), c01) + self.assertEqual(surf.get_at((1, 0)), c10) + self.assertEqual(surf.get_at((1, 1)), c11) + for p in [(-1, 0), (0, -1), (2, 0), (0, 2)]: + self.assertRaises(IndexError, surf.get_at, p) + + def test_get_at_mapped(self): + color = pygame.Color(10, 20, 30) + for bitsize in [8, 16, 24, 32]: + surf = pygame.Surface((2, 2), 0, bitsize) + surf.fill(color) + pixel = surf.get_at_mapped((0, 0)) + self.assertEqual( + pixel, + surf.map_rgb(color), + "%i != %i, bitsize: %i" % (pixel, surf.map_rgb(color), bitsize), + ) + + def test_get_bitsize(self): + pygame.display.init() + try: + expected_size = (11, 21) + + # Check that get_bitsize returns passed depth + expected_depth = 32 + surface = pygame.Surface(expected_size, pygame.SRCALPHA, expected_depth) + self.assertEqual(surface.get_size(), expected_size) + self.assertEqual(surface.get_bitsize(), expected_depth) + + expected_depth = 16 + surface = pygame.Surface(expected_size, pygame.SRCALPHA, expected_depth) + self.assertEqual(surface.get_size(), expected_size) + self.assertEqual(surface.get_bitsize(), expected_depth) + + expected_depth = 15 + surface = pygame.Surface(expected_size, 0, expected_depth) + self.assertEqual(surface.get_size(), expected_size) + self.assertEqual(surface.get_bitsize(), expected_depth) + # Check for invalid depths + expected_depth = -1 + self.assertRaises( + ValueError, pygame.Surface, expected_size, 0, expected_depth + ) + expected_depth = 11 + self.assertRaises( + ValueError, pygame.Surface, expected_size, 0, expected_depth + ) + expected_depth = 1024 + self.assertRaises( + ValueError, pygame.Surface, expected_size, 0, expected_depth + ) + + with self.assertRaises(pygame.error): + surface = pygame.display.set_mode() + pygame.display.quit() + surface.get_bitsize() + finally: + pygame.display.quit() + + def test_get_clip(self): + s = pygame.Surface((800, 600)) + rectangle = s.get_clip() + self.assertEqual(rectangle, (0, 0, 800, 600)) + + def test_get_colorkey(self): + pygame.display.init() + try: + # if set_colorkey is not used + s = pygame.Surface((800, 600), 0, 32) + self.assertIsNone(s.get_colorkey()) + + # if set_colorkey is used + s.set_colorkey(None) + self.assertIsNone(s.get_colorkey()) + + # setting up remainder of tests... + r, g, b, a = 20, 40, 60, 12 + colorkey = pygame.Color(r, g, b) + s.set_colorkey(colorkey) + + # test for ideal case + self.assertEqual(s.get_colorkey(), (r, g, b, 255)) + + # test for if the color_key is set using pygame.RLEACCEL + s.set_colorkey(colorkey, pygame.RLEACCEL) + self.assertEqual(s.get_colorkey(), (r, g, b, 255)) + + # test for if the color key is not what's expected + s.set_colorkey(pygame.Color(r + 1, g + 1, b + 1)) + self.assertNotEqual(s.get_colorkey(), (r, g, b, 255)) + + s.set_colorkey(pygame.Color(r, g, b, a)) + # regardless of whether alpha is not 255 + # colorkey returned from surface is always 255 + self.assertEqual(s.get_colorkey(), (r, g, b, 255)) + finally: + # test for using method after display.quit() is called... + s = pygame.display.set_mode((200, 200), 0, 32) + pygame.display.quit() + with self.assertRaises(pygame.error): + s.get_colorkey() + + def test_get_height(self): + sizes = ((1, 1), (119, 10), (10, 119), (1, 1000), (1000, 1), (1000, 1000)) + for width, height in sizes: + surf = pygame.Surface((width, height)) + found_height = surf.get_height() + self.assertEqual(height, found_height) + + def test_get_locked(self): + def blit_locked_test(surface): + newSurf = pygame.Surface((10, 10)) + try: + newSurf.blit(surface, (0, 0)) + except pygame.error: + return True + else: + return False + + surf = pygame.Surface((100, 100)) + + self.assertIs(surf.get_locked(), blit_locked_test(surf)) # Unlocked + # Surface should lock + surf.lock() + self.assertIs(surf.get_locked(), blit_locked_test(surf)) # Locked + # Surface should unlock + surf.unlock() + self.assertIs(surf.get_locked(), blit_locked_test(surf)) # Unlocked + + # Check multiple locks + surf = pygame.Surface((100, 100)) + surf.lock() + surf.lock() + self.assertIs(surf.get_locked(), blit_locked_test(surf)) # Locked + surf.unlock() + self.assertIs(surf.get_locked(), blit_locked_test(surf)) # Locked + surf.unlock() + self.assertIs(surf.get_locked(), blit_locked_test(surf)) # Unlocked + + # Check many locks + surf = pygame.Surface((100, 100)) + for i in range(1000): + surf.lock() + self.assertIs(surf.get_locked(), blit_locked_test(surf)) # Locked + for i in range(1000): + surf.unlock() + self.assertFalse(surf.get_locked()) # Unlocked + + # Unlocking an unlocked surface + surf = pygame.Surface((100, 100)) + surf.unlock() + self.assertIs(surf.get_locked(), blit_locked_test(surf)) # Unlocked + surf.unlock() + self.assertIs(surf.get_locked(), blit_locked_test(surf)) # Unlocked + + def test_get_locks(self): + + # __doc__ (as of 2008-08-02) for pygame.surface.Surface.get_locks: + + # Surface.get_locks(): return tuple + # Gets the locks for the Surface + # + # Returns the currently existing locks for the Surface. + + # test on a surface that is not initially locked + surface = pygame.Surface((100, 100)) + self.assertEqual(surface.get_locks(), ()) + + # test on the same surface after it has been locked + surface.lock() + self.assertEqual(surface.get_locks(), (surface,)) + + # test on the same surface after it has been unlocked + surface.unlock() + self.assertEqual(surface.get_locks(), ()) + + # test with PixelArray initialization: locks surface + pxarray = pygame.PixelArray(surface) + self.assertNotEqual(surface.get_locks(), ()) + + # closing the PixelArray releases the surface lock + pxarray.close() + self.assertEqual(surface.get_locks(), ()) + + # AttributeError raised when called on invalid object type (i.e. not a pygame.Surface object) + with self.assertRaises(AttributeError): + "DUMMY".get_locks() + + # test multiple locks and unlocks on the same surface + surface.lock() + surface.lock() + surface.lock() + self.assertEqual(surface.get_locks(), (surface, surface, surface)) + + surface.unlock() + surface.unlock() + self.assertEqual(surface.get_locks(), (surface,)) + surface.unlock() + self.assertEqual(surface.get_locks(), ()) + + def test_get_losses(self): + """Ensure a surface's losses can be retrieved""" + pygame.display.init() + try: + # Masks for different color component configurations + mask8 = (224, 28, 3, 0) + mask15 = (31744, 992, 31, 0) + mask16 = (63488, 2016, 31, 0) + mask24 = (4278190080, 16711680, 65280, 0) + mask32 = (4278190080, 16711680, 65280, 255) + + # Surfaces with standard depths and masks + display_surf = pygame.display.set_mode((100, 100)) + surf = pygame.Surface((100, 100)) + surf_8bit = pygame.Surface((100, 100), depth=8, masks=mask8) + surf_15bit = pygame.Surface((100, 100), depth=15, masks=mask15) + surf_16bit = pygame.Surface((100, 100), depth=16, masks=mask16) + surf_24bit = pygame.Surface((100, 100), depth=24, masks=mask24) + surf_32bit = pygame.Surface((100, 100), depth=32, masks=mask32) + + # Test output is correct type, length, and value range + losses = surf.get_losses() + self.assertIsInstance(losses, tuple) + self.assertEqual(len(losses), 4) + for loss in losses: + self.assertIsInstance(loss, int) + self.assertGreaterEqual(loss, 0) + self.assertLessEqual(loss, 8) + + # Test each surface for correct losses + # Display surface losses gives idea of default surface losses + if display_surf.get_losses() == (0, 0, 0, 8): + self.assertEqual(losses, (0, 0, 0, 8)) + elif display_surf.get_losses() == (8, 8, 8, 8): + self.assertEqual(losses, (8, 8, 8, 8)) + + self.assertEqual(surf_8bit.get_losses(), (5, 5, 6, 8)) + self.assertEqual(surf_15bit.get_losses(), (3, 3, 3, 8)) + self.assertEqual(surf_16bit.get_losses(), (3, 2, 3, 8)) + self.assertEqual(surf_24bit.get_losses(), (0, 0, 0, 8)) + self.assertEqual(surf_32bit.get_losses(), (0, 0, 0, 0)) + + # Method should fail when display is not initialized + with self.assertRaises(pygame.error): + surface = pygame.display.set_mode((100, 100)) + pygame.display.quit() + surface.get_losses() + finally: + pygame.display.quit() + + def test_get_masks__rgba(self): + """ + Ensure that get_mask can return RGBA mask. + """ + masks = [ + (0x0F00, 0x00F0, 0x000F, 0xF000), + (0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000), + ] + depths = [16, 32] + for expected, depth in list(zip(masks, depths)): + surface = pygame.Surface((10, 10), pygame.SRCALPHA, depth) + self.assertEqual(expected, surface.get_masks()) + + def test_get_masks__rgb(self): + """ + Ensure that get_mask can return RGB mask. + """ + masks = [ + (0x60, 0x1C, 0x03, 0x00), + (0xF00, 0x0F0, 0x00F, 0x000), + (0x7C00, 0x03E0, 0x001F, 0x0000), + (0xF800, 0x07E0, 0x001F, 0x0000), + (0xFF0000, 0x00FF00, 0x0000FF, 0x000000), + (0xFF0000, 0x00FF00, 0x0000FF, 0x000000), + ] + depths = [8, 12, 15, 16, 24, 32] + for expected, depth in list(zip(masks, depths)): + surface = pygame.Surface((10, 10), 0, depth) + if depth == 8: + expected = (0x00, 0x00, 0x00, 0x00) + self.assertEqual(expected, surface.get_masks()) + + def test_get_masks__no_surface(self): + """ + Ensure that after display.quit, calling get_masks raises pygame.error. + """ + with self.assertRaises(pygame.error): + surface = pygame.display.set_mode((10, 10)) + pygame.display.quit() + surface.get_masks() + + def test_get_offset(self): + """get_offset returns the (0,0) if surface is not a child + returns the position of child subsurface inside of parent + """ + pygame.display.init() + try: + surf = pygame.Surface((100, 100)) + self.assertEqual(surf.get_offset(), (0, 0)) + + # subsurface offset test + subsurf = surf.subsurface(1, 1, 10, 10) + self.assertEqual(subsurf.get_offset(), (1, 1)) + + with self.assertRaises(pygame.error): + surface = pygame.display.set_mode() + pygame.display.quit() + surface.get_offset() + finally: + pygame.display.quit() + + def test_get_palette(self): + pygame.display.init() + try: + palette = [Color(i, i, i) for i in range(256)] + pygame.display.set_mode((100, 50)) + surf = pygame.Surface((2, 2), 0, 8) + surf.set_palette(palette) + palette2 = surf.get_palette() + r, g, b = palette2[0] + + self.assertEqual(len(palette2), len(palette)) + for c2, c in zip(palette2, palette): + self.assertEqual(c2, c) + for c in palette2: + self.assertIsInstance(c, pygame.Color) + finally: + pygame.display.quit() + + def test_get_palette_at(self): + # See also test_get_palette + pygame.display.init() + try: + pygame.display.set_mode((100, 50)) + surf = pygame.Surface((2, 2), 0, 8) + color = pygame.Color(1, 2, 3, 255) + surf.set_palette_at(0, color) + color2 = surf.get_palette_at(0) + self.assertIsInstance(color2, pygame.Color) + self.assertEqual(color2, color) + self.assertRaises(IndexError, surf.get_palette_at, -1) + self.assertRaises(IndexError, surf.get_palette_at, 256) + finally: + pygame.display.quit() + + def test_get_pitch(self): + # Test get_pitch() on several surfaces of varying size/depth + sizes = ((2, 2), (7, 33), (33, 7), (2, 734), (734, 2), (734, 734)) + depths = [8, 24, 32] + for width, height in sizes: + for depth in depths: + # Test get_pitch() on parent surface + surf = pygame.Surface((width, height), depth=depth) + buff = surf.get_buffer() + pitch = buff.length / surf.get_height() + test_pitch = surf.get_pitch() + self.assertEqual(pitch, test_pitch) + # Test get_pitch() on subsurface with same rect as parent + rect1 = surf.get_rect() + subsurf1 = surf.subsurface(rect1) + sub_buff1 = subsurf1.get_buffer() + sub_pitch1 = sub_buff1.length / subsurf1.get_height() + test_sub_pitch1 = subsurf1.get_pitch() + self.assertEqual(sub_pitch1, test_sub_pitch1) + # Test get_pitch on subsurface with modified rect + rect2 = rect1.inflate(-width / 2, -height / 2) + subsurf2 = surf.subsurface(rect2) + sub_buff2 = subsurf2.get_buffer() + sub_pitch2 = sub_buff2.length / float(subsurf2.get_height()) + test_sub_pitch2 = subsurf2.get_pitch() + self.assertEqual(sub_pitch2, test_sub_pitch2) + + def test_get_shifts(self): + """ + Tests whether Surface.get_shifts returns proper + RGBA shifts under various conditions. + """ + # __doc__ (as of 2008-08-02) for pygame.surface.Surface.get_shifts: + # Surface.get_shifts(): return (R, G, B, A) + # the bit shifts needed to convert between color and mapped integer. + # Returns the pixel shifts need to convert between each color and a + # mapped integer. + # This value is not needed for normal Pygame usage. + + # Test for SDL2 on surfaces with various depths and alpha on/off + depths = [8, 24, 32] + alpha = 128 + off = None + for bit_depth in depths: + surface = pygame.Surface((32, 32), depth=bit_depth) + surface.set_alpha(alpha) + r1, g1, b1, a1 = surface.get_shifts() + surface.set_alpha(off) + r2, g2, b2, a2 = surface.get_shifts() + self.assertEqual((r1, g1, b1, a1), (r2, g2, b2, a2)) + + def test_get_size(self): + sizes = ((1, 1), (119, 10), (1000, 1000), (1, 5000), (1221, 1), (99, 999)) + for width, height in sizes: + surf = pygame.Surface((width, height)) + found_size = surf.get_size() + self.assertEqual((width, height), found_size) + + def test_lock(self): + + # __doc__ (as of 2008-08-02) for pygame.surface.Surface.lock: + + # Surface.lock(): return None + # lock the Surface memory for pixel access + # + # Lock the pixel data of a Surface for access. On accelerated + # Surfaces, the pixel data may be stored in volatile video memory or + # nonlinear compressed forms. When a Surface is locked the pixel + # memory becomes available to access by regular software. Code that + # reads or writes pixel values will need the Surface to be locked. + # + # Surfaces should not remain locked for more than necessary. A locked + # Surface can often not be displayed or managed by Pygame. + # + # Not all Surfaces require locking. The Surface.mustlock() method can + # determine if it is actually required. There is no performance + # penalty for locking and unlocking a Surface that does not need it. + # + # All pygame functions will automatically lock and unlock the Surface + # data as needed. If a section of code is going to make calls that + # will repeatedly lock and unlock the Surface many times, it can be + # helpful to wrap the block inside a lock and unlock pair. + # + # It is safe to nest locking and unlocking calls. The surface will + # only be unlocked after the final lock is released. + # + + # Basic + surf = pygame.Surface((100, 100)) + surf.lock() + self.assertTrue(surf.get_locked()) + + # Nested + surf = pygame.Surface((100, 100)) + surf.lock() + surf.lock() + surf.unlock() + self.assertTrue(surf.get_locked()) + surf.unlock() + surf.lock() + surf.lock() + self.assertTrue(surf.get_locked()) + surf.unlock() + self.assertTrue(surf.get_locked()) + surf.unlock() + self.assertFalse(surf.get_locked()) + + # Already Locked + surf = pygame.Surface((100, 100)) + surf.lock() + surf.lock() + self.assertTrue(surf.get_locked()) + surf.unlock() + self.assertTrue(surf.get_locked()) + surf.unlock() + self.assertFalse(surf.get_locked()) + + def test_map_rgb(self): + color = Color(0, 128, 255, 64) + surf = pygame.Surface((5, 5), SRCALPHA, 32) + c = surf.map_rgb(color) + self.assertEqual(surf.unmap_rgb(c), color) + + self.assertEqual(surf.get_at((0, 0)), (0, 0, 0, 0)) + surf.fill(c) + self.assertEqual(surf.get_at((0, 0)), color) + + surf.fill((0, 0, 0, 0)) + self.assertEqual(surf.get_at((0, 0)), (0, 0, 0, 0)) + surf.set_at((0, 0), c) + self.assertEqual(surf.get_at((0, 0)), color) + + def test_mustlock(self): + # Test that subsurfaces mustlock + surf = pygame.Surface((1024, 1024)) + subsurf = surf.subsurface((0, 0, 1024, 1024)) + self.assertTrue(subsurf.mustlock()) + self.assertFalse(surf.mustlock()) + # Tests nested subsurfaces + rects = ((0, 0, 512, 512), (0, 0, 256, 256), (0, 0, 128, 128)) + surf_stack = [] + surf_stack.append(surf) + surf_stack.append(subsurf) + for rect in rects: + surf_stack.append(surf_stack[-1].subsurface(rect)) + self.assertTrue(surf_stack[-1].mustlock()) + self.assertTrue(surf_stack[-2].mustlock()) + + def test_set_alpha_none(self): + """surf.set_alpha(None) disables blending""" + s = pygame.Surface((1, 1), SRCALPHA, 32) + s.fill((0, 255, 0, 128)) + s.set_alpha(None) + self.assertEqual(None, s.get_alpha()) + + s2 = pygame.Surface((1, 1), SRCALPHA, 32) + s2.fill((255, 0, 0, 255)) + s2.blit(s, (0, 0)) + self.assertEqual(s2.get_at((0, 0))[0], 0, "the red component should be 0") + + def test_set_alpha_value(self): + """surf.set_alpha(x), where x != None, enables blending""" + s = pygame.Surface((1, 1), SRCALPHA, 32) + s.fill((0, 255, 0, 128)) + s.set_alpha(255) + + s2 = pygame.Surface((1, 1), SRCALPHA, 32) + s2.fill((255, 0, 0, 255)) + s2.blit(s, (0, 0)) + self.assertGreater( + s2.get_at((0, 0))[0], 0, "the red component should be above 0" + ) + + def test_palette_colorkey(self): + """test bug discovered by robertpfeiffer + https://github.com/pygame/pygame/issues/721 + """ + surf = pygame.image.load(example_path(os.path.join("data", "alien2.png"))) + key = surf.get_colorkey() + self.assertEqual(surf.get_palette()[surf.map_rgb(key)], key) + + def test_palette_colorkey_set_px(self): + surf = pygame.image.load(example_path(os.path.join("data", "alien2.png"))) + key = surf.get_colorkey() + surf.set_at((0, 0), key) + self.assertEqual(surf.get_at((0, 0)), key) + + def test_palette_colorkey_fill(self): + surf = pygame.image.load(example_path(os.path.join("data", "alien2.png"))) + key = surf.get_colorkey() + surf.fill(key) + self.assertEqual(surf.get_at((0, 0)), key) + + def test_set_palette(self): + palette = [pygame.Color(i, i, i) for i in range(256)] + palette[10] = tuple(palette[10]) # 4 element tuple + palette[11] = tuple(palette[11])[0:3] # 3 element tuple + + surf = pygame.Surface((2, 2), 0, 8) + pygame.display.init() + try: + pygame.display.set_mode((100, 50)) + surf.set_palette(palette) + for i in range(256): + self.assertEqual(surf.map_rgb(palette[i]), i, "palette color %i" % (i,)) + c = palette[i] + surf.fill(c) + self.assertEqual(surf.get_at((0, 0)), c, "palette color %i" % (i,)) + for i in range(10): + palette[i] = pygame.Color(255 - i, 0, 0) + surf.set_palette(palette[0:10]) + for i in range(256): + self.assertEqual(surf.map_rgb(palette[i]), i, "palette color %i" % (i,)) + c = palette[i] + surf.fill(c) + self.assertEqual(surf.get_at((0, 0)), c, "palette color %i" % (i,)) + self.assertRaises(ValueError, surf.set_palette, [Color(1, 2, 3, 254)]) + self.assertRaises(ValueError, surf.set_palette, (1, 2, 3, 254)) + finally: + pygame.display.quit() + + def test_set_palette__fail(self): + pygame.init() + palette = 256 * [(10, 20, 30)] + surf = pygame.Surface((2, 2), 0, 32) + self.assertRaises(pygame.error, surf.set_palette, palette) + pygame.quit() + + def test_set_palette_at(self): + pygame.display.init() + try: + pygame.display.set_mode((100, 50)) + surf = pygame.Surface((2, 2), 0, 8) + original = surf.get_palette_at(10) + replacement = Color(1, 1, 1, 255) + if replacement == original: + replacement = Color(2, 2, 2, 255) + surf.set_palette_at(10, replacement) + self.assertEqual(surf.get_palette_at(10), replacement) + next = tuple(original) + surf.set_palette_at(10, next) + self.assertEqual(surf.get_palette_at(10), next) + next = tuple(original)[0:3] + surf.set_palette_at(10, next) + self.assertEqual(surf.get_palette_at(10), next) + self.assertRaises(IndexError, surf.set_palette_at, 256, replacement) + self.assertRaises(IndexError, surf.set_palette_at, -1, replacement) + finally: + pygame.display.quit() + + def test_subsurface(self): + + # __doc__ (as of 2008-08-02) for pygame.surface.Surface.subsurface: + + # Surface.subsurface(Rect): return Surface + # create a new surface that references its parent + # + # Returns a new Surface that shares its pixels with its new parent. + # The new Surface is considered a child of the original. Modifications + # to either Surface pixels will effect each other. Surface information + # like clipping area and color keys are unique to each Surface. + # + # The new Surface will inherit the palette, color key, and alpha + # settings from its parent. + # + # It is possible to have any number of subsurfaces and subsubsurfaces + # on the parent. It is also possible to subsurface the display Surface + # if the display mode is not hardware accelerated. + # + # See the Surface.get_offset(), Surface.get_parent() to learn more + # about the state of a subsurface. + # + + surf = pygame.Surface((16, 16)) + s = surf.subsurface(0, 0, 1, 1) + s = surf.subsurface((0, 0, 1, 1)) + + # s = surf.subsurface((0,0,1,1), 1) + # This form is not acceptable. + # s = surf.subsurface(0,0,10,10, 1) + + self.assertRaises(ValueError, surf.subsurface, (0, 0, 1, 1, 666)) + + self.assertEqual(s.get_shifts(), surf.get_shifts()) + self.assertEqual(s.get_masks(), surf.get_masks()) + self.assertEqual(s.get_losses(), surf.get_losses()) + + # Issue 2 at Bitbucket.org/pygame/pygame + surf = pygame.Surface.__new__(pygame.Surface) + self.assertRaises(pygame.error, surf.subsurface, (0, 0, 0, 0)) + + def test_unlock(self): + # Basic + surf = pygame.Surface((100, 100)) + surf.lock() + surf.unlock() + self.assertFalse(surf.get_locked()) + + # Nested + surf = pygame.Surface((100, 100)) + surf.lock() + surf.lock() + surf.unlock() + self.assertTrue(surf.get_locked()) + surf.unlock() + self.assertFalse(surf.get_locked()) + + # Already Unlocked + surf = pygame.Surface((100, 100)) + surf.unlock() + self.assertFalse(surf.get_locked()) + surf.unlock() + self.assertFalse(surf.get_locked()) + + # Surface can be relocked + surf = pygame.Surface((100, 100)) + surf.lock() + surf.unlock() + self.assertFalse(surf.get_locked()) + surf.lock() + surf.unlock() + self.assertFalse(surf.get_locked()) + + def test_unmap_rgb(self): + # Special case, 8 bit-per-pixel surface (has a palette). + surf = pygame.Surface((2, 2), 0, 8) + c = (1, 1, 1) # Unlikely to be in a default palette. + i = 67 + pygame.display.init() + try: + pygame.display.set_mode((100, 50)) + surf.set_palette_at(i, c) + unmapped_c = surf.unmap_rgb(i) + self.assertEqual(unmapped_c, c) + # Confirm it is a Color instance + self.assertIsInstance(unmapped_c, pygame.Color) + finally: + pygame.display.quit() + + # Remaining, non-pallete, cases. + c = (128, 64, 12, 255) + formats = [(0, 16), (0, 24), (0, 32), (SRCALPHA, 16), (SRCALPHA, 32)] + for flags, bitsize in formats: + surf = pygame.Surface((2, 2), flags, bitsize) + unmapped_c = surf.unmap_rgb(surf.map_rgb(c)) + surf.fill(c) + comparison_c = surf.get_at((0, 0)) + self.assertEqual( + unmapped_c, + comparison_c, + "%s != %s, flags: %i, bitsize: %i" + % (unmapped_c, comparison_c, flags, bitsize), + ) + # Confirm it is a Color instance + self.assertIsInstance(unmapped_c, pygame.Color) + + def test_scroll(self): + scrolls = [ + (8, 2, 3), + (16, 2, 3), + (24, 2, 3), + (32, 2, 3), + (32, -1, -3), + (32, 0, 0), + (32, 11, 0), + (32, 0, 11), + (32, -11, 0), + (32, 0, -11), + (32, -11, 2), + (32, 2, -11), + ] + for bitsize, dx, dy in scrolls: + surf = pygame.Surface((10, 10), 0, bitsize) + surf.fill((255, 0, 0)) + surf.fill((0, 255, 0), (2, 2, 2, 2)) + comp = surf.copy() + comp.blit(surf, (dx, dy)) + surf.scroll(dx, dy) + w, h = surf.get_size() + for x in range(w): + for y in range(h): + with self.subTest(x=x, y=y): + self.assertEqual( + surf.get_at((x, y)), + comp.get_at((x, y)), + "%s != %s, bpp:, %i, x: %i, y: %i" + % ( + surf.get_at((x, y)), + comp.get_at((x, y)), + bitsize, + dx, + dy, + ), + ) + # Confirm clip rect containment + surf = pygame.Surface((20, 13), 0, 32) + surf.fill((255, 0, 0)) + surf.fill((0, 255, 0), (7, 1, 6, 6)) + comp = surf.copy() + clip = Rect(3, 1, 8, 14) + surf.set_clip(clip) + comp.set_clip(clip) + comp.blit(surf, (clip.x + 2, clip.y + 3), surf.get_clip()) + surf.scroll(2, 3) + w, h = surf.get_size() + for x in range(w): + for y in range(h): + self.assertEqual(surf.get_at((x, y)), comp.get_at((x, y))) + # Confirm keyword arguments and per-pixel alpha + spot_color = (0, 255, 0, 128) + surf = pygame.Surface((4, 4), pygame.SRCALPHA, 32) + surf.fill((255, 0, 0, 255)) + surf.set_at((1, 1), spot_color) + surf.scroll(dx=1) + self.assertEqual(surf.get_at((2, 1)), spot_color) + surf.scroll(dy=1) + self.assertEqual(surf.get_at((2, 2)), spot_color) + surf.scroll(dy=1, dx=1) + self.assertEqual(surf.get_at((3, 3)), spot_color) + surf.scroll(dx=-3, dy=-3) + self.assertEqual(surf.get_at((0, 0)), spot_color) + + +class SurfaceSubtypeTest(unittest.TestCase): + """Issue #280: Methods that return a new Surface preserve subclasses""" + + def setUp(self): + pygame.display.init() + + def tearDown(self): + pygame.display.quit() + + def test_copy(self): + """Ensure method copy() preserves the surface's class + + When Surface is subclassed, the inherited copy() method will return + instances of the subclass. Non Surface fields are uncopied, however. + This includes instance attributes. + """ + expected_size = (32, 32) + ms1 = SurfaceSubclass(expected_size, SRCALPHA, 32) + ms2 = ms1.copy() + + self.assertIsNot(ms1, ms2) + self.assertIsInstance(ms1, pygame.Surface) + self.assertIsInstance(ms2, pygame.Surface) + self.assertIsInstance(ms1, SurfaceSubclass) + self.assertIsInstance(ms2, SurfaceSubclass) + self.assertTrue(ms1.test_attribute) + self.assertRaises(AttributeError, getattr, ms2, "test_attribute") + self.assertEqual(ms2.get_size(), expected_size) + + def test_convert(self): + """Ensure method convert() preserves the surface's class + + When Surface is subclassed, the inherited convert() method will return + instances of the subclass. Non Surface fields are omitted, however. + This includes instance attributes. + """ + expected_size = (32, 32) + ms1 = SurfaceSubclass(expected_size, 0, 24) + ms2 = ms1.convert(24) + + self.assertIsNot(ms1, ms2) + self.assertIsInstance(ms1, pygame.Surface) + self.assertIsInstance(ms2, pygame.Surface) + self.assertIsInstance(ms1, SurfaceSubclass) + self.assertIsInstance(ms2, SurfaceSubclass) + self.assertTrue(ms1.test_attribute) + self.assertRaises(AttributeError, getattr, ms2, "test_attribute") + self.assertEqual(ms2.get_size(), expected_size) + + def test_convert_alpha(self): + """Ensure method convert_alpha() preserves the surface's class + + When Surface is subclassed, the inherited convert_alpha() method will + return instances of the subclass. Non Surface fields are omitted, + however. This includes instance attributes. + """ + pygame.display.set_mode((40, 40)) + expected_size = (32, 32) + s = pygame.Surface(expected_size, SRCALPHA, 16) + ms1 = SurfaceSubclass(expected_size, SRCALPHA, 32) + ms2 = ms1.convert_alpha(s) + + self.assertIsNot(ms1, ms2) + self.assertIsInstance(ms1, pygame.Surface) + self.assertIsInstance(ms2, pygame.Surface) + self.assertIsInstance(ms1, SurfaceSubclass) + self.assertIsInstance(ms2, SurfaceSubclass) + self.assertTrue(ms1.test_attribute) + self.assertRaises(AttributeError, getattr, ms2, "test_attribute") + self.assertEqual(ms2.get_size(), expected_size) + + def test_subsurface(self): + """Ensure method subsurface() preserves the surface's class + + When Surface is subclassed, the inherited subsurface() method will + return instances of the subclass. Non Surface fields are uncopied, + however. This includes instance attributes. + """ + expected_size = (10, 12) + ms1 = SurfaceSubclass((32, 32), SRCALPHA, 32) + ms2 = ms1.subsurface((4, 5), expected_size) + + self.assertIsNot(ms1, ms2) + self.assertIsInstance(ms1, pygame.Surface) + self.assertIsInstance(ms2, pygame.Surface) + self.assertIsInstance(ms1, SurfaceSubclass) + self.assertIsInstance(ms2, SurfaceSubclass) + self.assertTrue(ms1.test_attribute) + self.assertRaises(AttributeError, getattr, ms2, "test_attribute") + self.assertEqual(ms2.get_size(), expected_size) + + +class SurfaceGetBufferTest(unittest.TestCase): + # These tests requires ctypes. They are disabled if ctypes + # is not installed. + try: + ArrayInterface + except NameError: + __tags__ = ("ignore", "subprocess_ignore") + + lilendian = pygame.get_sdl_byteorder() == pygame.LIL_ENDIAN + + def _check_interface_2D(self, s): + s_w, s_h = s.get_size() + s_bytesize = s.get_bytesize() + s_pitch = s.get_pitch() + s_pixels = s._pixels_address + + # check the array interface structure fields. + v = s.get_view("2") + if not IS_PYPY: + flags = PAI_ALIGNED | PAI_NOTSWAPPED | PAI_WRITEABLE + if s.get_pitch() == s_w * s_bytesize: + flags |= PAI_FORTRAN + + inter = ArrayInterface(v) + + self.assertEqual(inter.two, 2) + self.assertEqual(inter.nd, 2) + self.assertEqual(inter.typekind, "u") + self.assertEqual(inter.itemsize, s_bytesize) + self.assertEqual(inter.shape[0], s_w) + self.assertEqual(inter.shape[1], s_h) + self.assertEqual(inter.strides[0], s_bytesize) + self.assertEqual(inter.strides[1], s_pitch) + self.assertEqual(inter.flags, flags) + self.assertEqual(inter.data, s_pixels) + + def _check_interface_3D(self, s): + s_w, s_h = s.get_size() + s_bytesize = s.get_bytesize() + s_pitch = s.get_pitch() + s_pixels = s._pixels_address + s_shifts = list(s.get_shifts()) + + # Check for RGB or BGR surface. + if s_shifts[0:3] == [0, 8, 16]: + if self.lilendian: + # RGB + offset = 0 + step = 1 + else: + # BGR + offset = s_bytesize - 1 + step = -1 + elif s_shifts[0:3] == [8, 16, 24]: + if self.lilendian: + # xRGB + offset = 1 + step = 1 + else: + # BGRx + offset = s_bytesize - 2 + step = -1 + elif s_shifts[0:3] == [16, 8, 0]: + if self.lilendian: + # BGR + offset = 2 + step = -1 + else: + # RGB + offset = s_bytesize - 3 + step = 1 + elif s_shifts[0:3] == [24, 16, 8]: + if self.lilendian: + # BGRx + offset = 2 + step = -1 + else: + # RGBx + offset = s_bytesize - 4 + step = -1 + else: + return + + # check the array interface structure fields. + v = s.get_view("3") + if not IS_PYPY: + inter = ArrayInterface(v) + flags = PAI_ALIGNED | PAI_NOTSWAPPED | PAI_WRITEABLE + self.assertEqual(inter.two, 2) + self.assertEqual(inter.nd, 3) + self.assertEqual(inter.typekind, "u") + self.assertEqual(inter.itemsize, 1) + self.assertEqual(inter.shape[0], s_w) + self.assertEqual(inter.shape[1], s_h) + self.assertEqual(inter.shape[2], 3) + self.assertEqual(inter.strides[0], s_bytesize) + self.assertEqual(inter.strides[1], s_pitch) + self.assertEqual(inter.strides[2], step) + self.assertEqual(inter.flags, flags) + self.assertEqual(inter.data, s_pixels + offset) + + def _check_interface_rgba(self, s, plane): + s_w, s_h = s.get_size() + s_bytesize = s.get_bytesize() + s_pitch = s.get_pitch() + s_pixels = s._pixels_address + s_shifts = s.get_shifts() + s_masks = s.get_masks() + + # Find the color plane position within the pixel. + if not s_masks[plane]: + return + alpha_shift = s_shifts[plane] + offset = alpha_shift // 8 + if not self.lilendian: + offset = s_bytesize - offset - 1 + + # check the array interface structure fields. + v = s.get_view("rgba"[plane]) + if not IS_PYPY: + inter = ArrayInterface(v) + flags = PAI_ALIGNED | PAI_NOTSWAPPED | PAI_WRITEABLE + self.assertEqual(inter.two, 2) + self.assertEqual(inter.nd, 2) + self.assertEqual(inter.typekind, "u") + self.assertEqual(inter.itemsize, 1) + self.assertEqual(inter.shape[0], s_w) + self.assertEqual(inter.shape[1], s_h) + self.assertEqual(inter.strides[0], s_bytesize) + self.assertEqual(inter.strides[1], s_pitch) + self.assertEqual(inter.flags, flags) + self.assertEqual(inter.data, s_pixels + offset) + + def test_array_interface(self): + self._check_interface_2D(pygame.Surface((5, 7), 0, 8)) + self._check_interface_2D(pygame.Surface((5, 7), 0, 16)) + self._check_interface_2D(pygame.Surface((5, 7), pygame.SRCALPHA, 16)) + self._check_interface_3D(pygame.Surface((5, 7), 0, 24)) + self._check_interface_3D(pygame.Surface((8, 4), 0, 24)) # No gaps + self._check_interface_2D(pygame.Surface((5, 7), 0, 32)) + self._check_interface_3D(pygame.Surface((5, 7), 0, 32)) + self._check_interface_2D(pygame.Surface((5, 7), pygame.SRCALPHA, 32)) + self._check_interface_3D(pygame.Surface((5, 7), pygame.SRCALPHA, 32)) + + def test_array_interface_masks(self): + """Test non-default color byte orders on 3D views""" + + sz = (5, 7) + # Reversed RGB byte order + s = pygame.Surface(sz, 0, 32) + s_masks = list(s.get_masks()) + masks = [0xFF, 0xFF00, 0xFF0000] + if s_masks[0:3] == masks or s_masks[0:3] == masks[::-1]: + masks = s_masks[2::-1] + s_masks[3:4] + self._check_interface_3D(pygame.Surface(sz, 0, 32, masks)) + s = pygame.Surface(sz, 0, 24) + s_masks = list(s.get_masks()) + masks = [0xFF, 0xFF00, 0xFF0000] + if s_masks[0:3] == masks or s_masks[0:3] == masks[::-1]: + masks = s_masks[2::-1] + s_masks[3:4] + self._check_interface_3D(pygame.Surface(sz, 0, 24, masks)) + + masks = [0xFF00, 0xFF0000, 0xFF000000, 0] + self._check_interface_3D(pygame.Surface(sz, 0, 32, masks)) + + def test_array_interface_alpha(self): + for shifts in [[0, 8, 16, 24], [8, 16, 24, 0], [24, 16, 8, 0], [16, 8, 0, 24]]: + masks = [0xFF << s for s in shifts] + s = pygame.Surface((4, 2), pygame.SRCALPHA, 32, masks) + self._check_interface_rgba(s, 3) + + def test_array_interface_rgb(self): + for shifts in [[0, 8, 16, 24], [8, 16, 24, 0], [24, 16, 8, 0], [16, 8, 0, 24]]: + masks = [0xFF << s for s in shifts] + masks[3] = 0 + for plane in range(3): + s = pygame.Surface((4, 2), 0, 24) + self._check_interface_rgba(s, plane) + s = pygame.Surface((4, 2), 0, 32) + self._check_interface_rgba(s, plane) + + @unittest.skipIf(not pygame.HAVE_NEWBUF, "newbuf not implemented") + def test_newbuf_PyBUF_flags_bytes(self): + from pygame.tests.test_utils import buftools + + Importer = buftools.Importer + s = pygame.Surface((10, 6), 0, 32) + a = s.get_buffer() + b = Importer(a, buftools.PyBUF_SIMPLE) + self.assertEqual(b.ndim, 0) + self.assertTrue(b.format is None) + self.assertEqual(b.len, a.length) + self.assertEqual(b.itemsize, 1) + self.assertTrue(b.shape is None) + self.assertTrue(b.strides is None) + self.assertTrue(b.suboffsets is None) + self.assertFalse(b.readonly) + self.assertEqual(b.buf, s._pixels_address) + b = Importer(a, buftools.PyBUF_WRITABLE) + self.assertEqual(b.ndim, 0) + self.assertTrue(b.format is None) + self.assertFalse(b.readonly) + b = Importer(a, buftools.PyBUF_FORMAT) + self.assertEqual(b.ndim, 0) + self.assertEqual(b.format, "B") + b = Importer(a, buftools.PyBUF_ND) + self.assertEqual(b.ndim, 1) + self.assertTrue(b.format is None) + self.assertEqual(b.len, a.length) + self.assertEqual(b.itemsize, 1) + self.assertEqual(b.shape, (a.length,)) + self.assertTrue(b.strides is None) + self.assertTrue(b.suboffsets is None) + self.assertFalse(b.readonly) + self.assertEqual(b.buf, s._pixels_address) + b = Importer(a, buftools.PyBUF_STRIDES) + self.assertEqual(b.ndim, 1) + self.assertTrue(b.format is None) + self.assertEqual(b.strides, (1,)) + s2 = s.subsurface((1, 1, 7, 4)) # Not contiguous + a = s2.get_buffer() + b = Importer(a, buftools.PyBUF_SIMPLE) + self.assertEqual(b.ndim, 0) + self.assertTrue(b.format is None) + self.assertEqual(b.len, a.length) + self.assertEqual(b.itemsize, 1) + self.assertTrue(b.shape is None) + self.assertTrue(b.strides is None) + self.assertTrue(b.suboffsets is None) + self.assertFalse(b.readonly) + self.assertEqual(b.buf, s2._pixels_address) + b = Importer(a, buftools.PyBUF_C_CONTIGUOUS) + self.assertEqual(b.ndim, 1) + self.assertEqual(b.strides, (1,)) + b = Importer(a, buftools.PyBUF_F_CONTIGUOUS) + self.assertEqual(b.ndim, 1) + self.assertEqual(b.strides, (1,)) + b = Importer(a, buftools.PyBUF_ANY_CONTIGUOUS) + self.assertEqual(b.ndim, 1) + self.assertEqual(b.strides, (1,)) + + @unittest.skipIf(not pygame.HAVE_NEWBUF, "newbuf not implemented") + def test_newbuf_PyBUF_flags_0D(self): + # This is the same handler as used by get_buffer(), so just + # confirm that it succeeds for one case. + from pygame.tests.test_utils import buftools + + Importer = buftools.Importer + s = pygame.Surface((10, 6), 0, 32) + a = s.get_view("0") + b = Importer(a, buftools.PyBUF_SIMPLE) + self.assertEqual(b.ndim, 0) + self.assertTrue(b.format is None) + self.assertEqual(b.len, a.length) + self.assertEqual(b.itemsize, 1) + self.assertTrue(b.shape is None) + self.assertTrue(b.strides is None) + self.assertTrue(b.suboffsets is None) + self.assertFalse(b.readonly) + self.assertEqual(b.buf, s._pixels_address) + + @unittest.skipIf(not pygame.HAVE_NEWBUF, "newbuf not implemented") + def test_newbuf_PyBUF_flags_1D(self): + from pygame.tests.test_utils import buftools + + Importer = buftools.Importer + s = pygame.Surface((10, 6), 0, 32) + a = s.get_view("1") + b = Importer(a, buftools.PyBUF_SIMPLE) + self.assertEqual(b.ndim, 0) + self.assertTrue(b.format is None) + self.assertEqual(b.len, a.length) + self.assertEqual(b.itemsize, s.get_bytesize()) + self.assertTrue(b.shape is None) + self.assertTrue(b.strides is None) + self.assertTrue(b.suboffsets is None) + self.assertFalse(b.readonly) + self.assertEqual(b.buf, s._pixels_address) + b = Importer(a, buftools.PyBUF_WRITABLE) + self.assertEqual(b.ndim, 0) + self.assertTrue(b.format is None) + self.assertFalse(b.readonly) + b = Importer(a, buftools.PyBUF_FORMAT) + self.assertEqual(b.ndim, 0) + self.assertEqual(b.format, "=I") + b = Importer(a, buftools.PyBUF_ND) + self.assertEqual(b.ndim, 1) + self.assertTrue(b.format is None) + self.assertEqual(b.len, a.length) + self.assertEqual(b.itemsize, s.get_bytesize()) + self.assertEqual(b.shape, (s.get_width() * s.get_height(),)) + self.assertTrue(b.strides is None) + self.assertTrue(b.suboffsets is None) + self.assertFalse(b.readonly) + self.assertEqual(b.buf, s._pixels_address) + b = Importer(a, buftools.PyBUF_STRIDES) + self.assertEqual(b.ndim, 1) + self.assertTrue(b.format is None) + self.assertEqual(b.strides, (s.get_bytesize(),)) + + @unittest.skipIf(not pygame.HAVE_NEWBUF, "newbuf not implemented") + def test_newbuf_PyBUF_flags_2D(self): + from pygame.tests.test_utils import buftools + + Importer = buftools.Importer + s = pygame.Surface((10, 6), 0, 32) + a = s.get_view("2") + # Non dimensional requests, no PyDEF_ND, are handled by the + # 1D surface buffer code, so only need to confirm a success. + b = Importer(a, buftools.PyBUF_SIMPLE) + self.assertEqual(b.ndim, 0) + self.assertTrue(b.format is None) + self.assertEqual(b.len, a.length) + self.assertEqual(b.itemsize, s.get_bytesize()) + self.assertTrue(b.shape is None) + self.assertTrue(b.strides is None) + self.assertTrue(b.suboffsets is None) + self.assertFalse(b.readonly) + self.assertEqual(b.buf, s._pixels_address) + # Uniquely 2D + b = Importer(a, buftools.PyBUF_STRIDES) + self.assertEqual(b.ndim, 2) + self.assertTrue(b.format is None) + self.assertEqual(b.len, a.length) + self.assertEqual(b.itemsize, s.get_bytesize()) + self.assertEqual(b.shape, s.get_size()) + self.assertEqual(b.strides, (s.get_bytesize(), s.get_pitch())) + self.assertTrue(b.suboffsets is None) + self.assertFalse(b.readonly) + self.assertEqual(b.buf, s._pixels_address) + b = Importer(a, buftools.PyBUF_RECORDS_RO) + self.assertEqual(b.ndim, 2) + self.assertEqual(b.format, "=I") + self.assertEqual(b.strides, (s.get_bytesize(), s.get_pitch())) + b = Importer(a, buftools.PyBUF_RECORDS) + self.assertEqual(b.ndim, 2) + self.assertEqual(b.format, "=I") + self.assertEqual(b.strides, (s.get_bytesize(), s.get_pitch())) + b = Importer(a, buftools.PyBUF_F_CONTIGUOUS) + self.assertEqual(b.ndim, 2) + self.assertEqual(b.format, None) + self.assertEqual(b.strides, (s.get_bytesize(), s.get_pitch())) + b = Importer(a, buftools.PyBUF_ANY_CONTIGUOUS) + self.assertEqual(b.ndim, 2) + self.assertEqual(b.format, None) + self.assertEqual(b.strides, (s.get_bytesize(), s.get_pitch())) + self.assertRaises(BufferError, Importer, a, buftools.PyBUF_ND) + self.assertRaises(BufferError, Importer, a, buftools.PyBUF_C_CONTIGUOUS) + s2 = s.subsurface((1, 1, 7, 4)) # Not contiguous + a = s2.get_view("2") + b = Importer(a, buftools.PyBUF_STRIDES) + self.assertEqual(b.ndim, 2) + self.assertTrue(b.format is None) + self.assertEqual(b.len, a.length) + self.assertEqual(b.itemsize, s2.get_bytesize()) + self.assertEqual(b.shape, s2.get_size()) + self.assertEqual(b.strides, (s2.get_bytesize(), s.get_pitch())) + self.assertTrue(b.suboffsets is None) + self.assertFalse(b.readonly) + self.assertEqual(b.buf, s2._pixels_address) + b = Importer(a, buftools.PyBUF_RECORDS) + self.assertEqual(b.ndim, 2) + self.assertEqual(b.format, "=I") + self.assertRaises(BufferError, Importer, a, buftools.PyBUF_SIMPLE) + self.assertRaises(BufferError, Importer, a, buftools.PyBUF_FORMAT) + self.assertRaises(BufferError, Importer, a, buftools.PyBUF_WRITABLE) + self.assertRaises(BufferError, Importer, a, buftools.PyBUF_ND) + self.assertRaises(BufferError, Importer, a, buftools.PyBUF_C_CONTIGUOUS) + self.assertRaises(BufferError, Importer, a, buftools.PyBUF_F_CONTIGUOUS) + self.assertRaises(BufferError, Importer, a, buftools.PyBUF_ANY_CONTIGUOUS) + + @unittest.skipIf(not pygame.HAVE_NEWBUF, "newbuf not implemented") + def test_newbuf_PyBUF_flags_3D(self): + from pygame.tests.test_utils import buftools + + Importer = buftools.Importer + s = pygame.Surface((12, 6), 0, 24) + rmask, gmask, bmask, amask = s.get_masks() + if self.lilendian: + if rmask == 0x0000FF: + color_step = 1 + addr_offset = 0 + else: + color_step = -1 + addr_offset = 2 + else: + if rmask == 0xFF0000: + color_step = 1 + addr_offset = 0 + else: + color_step = -1 + addr_offset = 2 + a = s.get_view("3") + b = Importer(a, buftools.PyBUF_STRIDES) + w, h = s.get_size() + shape = w, h, 3 + strides = 3, s.get_pitch(), color_step + self.assertEqual(b.ndim, 3) + self.assertTrue(b.format is None) + self.assertEqual(b.len, a.length) + self.assertEqual(b.itemsize, 1) + self.assertEqual(b.shape, shape) + self.assertEqual(b.strides, strides) + self.assertTrue(b.suboffsets is None) + self.assertFalse(b.readonly) + self.assertEqual(b.buf, s._pixels_address + addr_offset) + b = Importer(a, buftools.PyBUF_RECORDS_RO) + self.assertEqual(b.ndim, 3) + self.assertEqual(b.format, "B") + self.assertEqual(b.strides, strides) + b = Importer(a, buftools.PyBUF_RECORDS) + self.assertEqual(b.ndim, 3) + self.assertEqual(b.format, "B") + self.assertEqual(b.strides, strides) + self.assertRaises(BufferError, Importer, a, buftools.PyBUF_SIMPLE) + self.assertRaises(BufferError, Importer, a, buftools.PyBUF_FORMAT) + self.assertRaises(BufferError, Importer, a, buftools.PyBUF_WRITABLE) + self.assertRaises(BufferError, Importer, a, buftools.PyBUF_ND) + self.assertRaises(BufferError, Importer, a, buftools.PyBUF_C_CONTIGUOUS) + self.assertRaises(BufferError, Importer, a, buftools.PyBUF_F_CONTIGUOUS) + self.assertRaises(BufferError, Importer, a, buftools.PyBUF_ANY_CONTIGUOUS) + + @unittest.skipIf(not pygame.HAVE_NEWBUF, "newbuf not implemented") + def test_newbuf_PyBUF_flags_rgba(self): + # All color plane views are handled by the same routine, + # so only one plane need be checked. + from pygame.tests.test_utils import buftools + + Importer = buftools.Importer + s = pygame.Surface((12, 6), 0, 24) + rmask, gmask, bmask, amask = s.get_masks() + if self.lilendian: + if rmask == 0x0000FF: + addr_offset = 0 + else: + addr_offset = 2 + else: + if rmask == 0xFF0000: + addr_offset = 0 + else: + addr_offset = 2 + a = s.get_view("R") + b = Importer(a, buftools.PyBUF_STRIDES) + w, h = s.get_size() + shape = w, h + strides = s.get_bytesize(), s.get_pitch() + self.assertEqual(b.ndim, 2) + self.assertTrue(b.format is None) + self.assertEqual(b.len, a.length) + self.assertEqual(b.itemsize, 1) + self.assertEqual(b.shape, shape) + self.assertEqual(b.strides, strides) + self.assertTrue(b.suboffsets is None) + self.assertFalse(b.readonly) + self.assertEqual(b.buf, s._pixels_address + addr_offset) + b = Importer(a, buftools.PyBUF_RECORDS_RO) + self.assertEqual(b.ndim, 2) + self.assertEqual(b.format, "B") + self.assertEqual(b.strides, strides) + b = Importer(a, buftools.PyBUF_RECORDS) + self.assertEqual(b.ndim, 2) + self.assertEqual(b.format, "B") + self.assertEqual(b.strides, strides) + self.assertRaises(BufferError, Importer, a, buftools.PyBUF_SIMPLE) + self.assertRaises(BufferError, Importer, a, buftools.PyBUF_FORMAT) + self.assertRaises(BufferError, Importer, a, buftools.PyBUF_WRITABLE) + self.assertRaises(BufferError, Importer, a, buftools.PyBUF_ND) + self.assertRaises(BufferError, Importer, a, buftools.PyBUF_C_CONTIGUOUS) + self.assertRaises(BufferError, Importer, a, buftools.PyBUF_F_CONTIGUOUS) + self.assertRaises(BufferError, Importer, a, buftools.PyBUF_ANY_CONTIGUOUS) + + +class SurfaceBlendTest(unittest.TestCase): + def setUp(self): + # Needed for 8 bits-per-pixel color palette surface tests. + pygame.display.init() + + def tearDown(self): + pygame.display.quit() + + _test_palette = [ + (0, 0, 0, 255), + (10, 30, 60, 0), + (25, 75, 100, 128), + (200, 150, 100, 200), + (0, 100, 200, 255), + ] + surf_size = (10, 12) + _test_points = [ + ((0, 0), 1), + ((4, 5), 1), + ((9, 0), 2), + ((5, 5), 2), + ((0, 11), 3), + ((4, 6), 3), + ((9, 11), 4), + ((5, 6), 4), + ] + + def _make_surface(self, bitsize, srcalpha=False, palette=None): + if palette is None: + palette = self._test_palette + flags = 0 + if srcalpha: + flags |= SRCALPHA + surf = pygame.Surface(self.surf_size, flags, bitsize) + if bitsize == 8: + surf.set_palette([c[:3] for c in palette]) + return surf + + def _fill_surface(self, surf, palette=None): + if palette is None: + palette = self._test_palette + surf.fill(palette[1], (0, 0, 5, 6)) + surf.fill(palette[2], (5, 0, 5, 6)) + surf.fill(palette[3], (0, 6, 5, 6)) + surf.fill(palette[4], (5, 6, 5, 6)) + + def _make_src_surface(self, bitsize, srcalpha=False, palette=None): + surf = self._make_surface(bitsize, srcalpha, palette) + self._fill_surface(surf, palette) + return surf + + def _assert_surface(self, surf, palette=None, msg=""): + if palette is None: + palette = self._test_palette + if surf.get_bitsize() == 16: + palette = [surf.unmap_rgb(surf.map_rgb(c)) for c in palette] + for posn, i in self._test_points: + self.assertEqual( + surf.get_at(posn), + palette[i], + "%s != %s: flags: %i, bpp: %i, posn: %s%s" + % ( + surf.get_at(posn), + palette[i], + surf.get_flags(), + surf.get_bitsize(), + posn, + msg, + ), + ) + + def test_blit_blend(self): + sources = [ + self._make_src_surface(8), + self._make_src_surface(16), + self._make_src_surface(16, srcalpha=True), + self._make_src_surface(24), + self._make_src_surface(32), + self._make_src_surface(32, srcalpha=True), + ] + destinations = [ + self._make_surface(8), + self._make_surface(16), + self._make_surface(16, srcalpha=True), + self._make_surface(24), + self._make_surface(32), + self._make_surface(32, srcalpha=True), + ] + blend = [ + ("BLEND_ADD", (0, 25, 100, 255), lambda a, b: min(a + b, 255)), + ("BLEND_SUB", (100, 25, 0, 100), lambda a, b: max(a - b, 0)), + ("BLEND_MULT", (100, 200, 0, 0), lambda a, b: (a * b) // 256), + ("BLEND_MIN", (255, 0, 0, 255), min), + ("BLEND_MAX", (0, 255, 0, 255), max), + ] + + for src in sources: + src_palette = [src.unmap_rgb(src.map_rgb(c)) for c in self._test_palette] + for dst in destinations: + for blend_name, dst_color, op in blend: + dc = dst.unmap_rgb(dst.map_rgb(dst_color)) + p = [] + for sc in src_palette: + c = [op(dc[i], sc[i]) for i in range(3)] + if dst.get_masks()[3]: + c.append(dc[3]) + else: + c.append(255) + c = dst.unmap_rgb(dst.map_rgb(c)) + p.append(c) + dst.fill(dst_color) + dst.blit(src, (0, 0), special_flags=getattr(pygame, blend_name)) + self._assert_surface( + dst, + p, + ( + ", op: %s, src bpp: %i" + ", src flags: %i" + % (blend_name, src.get_bitsize(), src.get_flags()) + ), + ) + + src = self._make_src_surface(32) + masks = src.get_masks() + dst = pygame.Surface( + src.get_size(), 0, 32, [masks[2], masks[1], masks[0], masks[3]] + ) + for blend_name, dst_color, op in blend: + p = [] + for src_color in self._test_palette: + c = [op(dst_color[i], src_color[i]) for i in range(3)] + c.append(255) + p.append(tuple(c)) + dst.fill(dst_color) + dst.blit(src, (0, 0), special_flags=getattr(pygame, blend_name)) + self._assert_surface(dst, p, ", %s" % blend_name) + + # Blend blits are special cased for 32 to 32 bit surfaces. + # + # Confirm that it works when the rgb bytes are not the + # least significant bytes. + pat = self._make_src_surface(32) + masks = pat.get_masks() + if min(masks) == 0xFF000000: + masks = [m >> 8 for m in masks] + else: + masks = [m << 8 for m in masks] + src = pygame.Surface(pat.get_size(), 0, 32, masks) + self._fill_surface(src) + dst = pygame.Surface(src.get_size(), 0, 32, masks) + for blend_name, dst_color, op in blend: + p = [] + for src_color in self._test_palette: + c = [op(dst_color[i], src_color[i]) for i in range(3)] + c.append(255) + p.append(tuple(c)) + dst.fill(dst_color) + dst.blit(src, (0, 0), special_flags=getattr(pygame, blend_name)) + self._assert_surface(dst, p, ", %s" % blend_name) + + def test_blit_blend_rgba(self): + sources = [ + self._make_src_surface(8), + self._make_src_surface(16), + self._make_src_surface(16, srcalpha=True), + self._make_src_surface(24), + self._make_src_surface(32), + self._make_src_surface(32, srcalpha=True), + ] + destinations = [ + self._make_surface(8), + self._make_surface(16), + self._make_surface(16, srcalpha=True), + self._make_surface(24), + self._make_surface(32), + self._make_surface(32, srcalpha=True), + ] + blend = [ + ("BLEND_RGBA_ADD", (0, 25, 100, 255), lambda a, b: min(a + b, 255)), + ("BLEND_RGBA_SUB", (0, 25, 100, 255), lambda a, b: max(a - b, 0)), + ("BLEND_RGBA_MULT", (0, 7, 100, 255), lambda a, b: (a * b) // 256), + ("BLEND_RGBA_MIN", (0, 255, 0, 255), min), + ("BLEND_RGBA_MAX", (0, 255, 0, 255), max), + ] + + for src in sources: + src_palette = [src.unmap_rgb(src.map_rgb(c)) for c in self._test_palette] + for dst in destinations: + for blend_name, dst_color, op in blend: + dc = dst.unmap_rgb(dst.map_rgb(dst_color)) + p = [] + for sc in src_palette: + c = [op(dc[i], sc[i]) for i in range(4)] + if not dst.get_masks()[3]: + c[3] = 255 + c = dst.unmap_rgb(dst.map_rgb(c)) + p.append(c) + dst.fill(dst_color) + dst.blit(src, (0, 0), special_flags=getattr(pygame, blend_name)) + self._assert_surface( + dst, + p, + ( + ", op: %s, src bpp: %i" + ", src flags: %i" + % (blend_name, src.get_bitsize(), src.get_flags()) + ), + ) + + # Blend blits are special cased for 32 to 32 bit surfaces + # with per-pixel alpha. + # + # Confirm the general case is used instead when the formats differ. + src = self._make_src_surface(32, srcalpha=True) + masks = src.get_masks() + dst = pygame.Surface( + src.get_size(), SRCALPHA, 32, (masks[2], masks[1], masks[0], masks[3]) + ) + for blend_name, dst_color, op in blend: + p = [ + tuple([op(dst_color[i], src_color[i]) for i in range(4)]) + for src_color in self._test_palette + ] + dst.fill(dst_color) + dst.blit(src, (0, 0), special_flags=getattr(pygame, blend_name)) + self._assert_surface(dst, p, ", %s" % blend_name) + + # Confirm this special case handles subsurfaces. + src = pygame.Surface((8, 10), SRCALPHA, 32) + dst = pygame.Surface((8, 10), SRCALPHA, 32) + tst = pygame.Surface((8, 10), SRCALPHA, 32) + src.fill((1, 2, 3, 4)) + dst.fill((40, 30, 20, 10)) + subsrc = src.subsurface((2, 3, 4, 4)) + subdst = dst.subsurface((2, 3, 4, 4)) + subdst.blit(subsrc, (0, 0), special_flags=BLEND_RGBA_ADD) + tst.fill((40, 30, 20, 10)) + tst.fill((41, 32, 23, 14), (2, 3, 4, 4)) + for x in range(8): + for y in range(10): + self.assertEqual( + dst.get_at((x, y)), + tst.get_at((x, y)), + "%s != %s at (%i, %i)" + % (dst.get_at((x, y)), tst.get_at((x, y)), x, y), + ) + + def test_blit_blend_premultiplied(self): + def test_premul_surf( + src_col, + dst_col, + src_size=(16, 16), + dst_size=(16, 16), + src_bit_depth=32, + dst_bit_depth=32, + src_has_alpha=True, + dst_has_alpha=True, + ): + if src_bit_depth == 8: + src = pygame.Surface(src_size, 0, src_bit_depth) + palette = [src_col, dst_col] + src.set_palette(palette) + src.fill(palette[0]) + elif src_has_alpha: + src = pygame.Surface(src_size, SRCALPHA, src_bit_depth) + src.fill(src_col) + else: + src = pygame.Surface(src_size, 0, src_bit_depth) + src.fill(src_col) + + if dst_bit_depth == 8: + dst = pygame.Surface(dst_size, 0, dst_bit_depth) + palette = [src_col, dst_col] + dst.set_palette(palette) + dst.fill(palette[1]) + elif dst_has_alpha: + dst = pygame.Surface(dst_size, SRCALPHA, dst_bit_depth) + dst.fill(dst_col) + else: + dst = pygame.Surface(dst_size, 0, dst_bit_depth) + dst.fill(dst_col) + + dst.blit(src, (0, 0), special_flags=BLEND_PREMULTIPLIED) + + actual_col = dst.get_at( + (int(float(src_size[0] / 2.0)), int(float(src_size[0] / 2.0))) + ) + + # This is the blend pre-multiplied formula + if src_col.a == 0: + expected_col = dst_col + elif src_col.a == 255: + expected_col = src_col + else: + # sC + dC - (((dC + 1) * sA >> 8) + expected_col = pygame.Color( + (src_col.r + dst_col.r - ((dst_col.r + 1) * src_col.a >> 8)), + (src_col.g + dst_col.g - ((dst_col.g + 1) * src_col.a >> 8)), + (src_col.b + dst_col.b - ((dst_col.b + 1) * src_col.a >> 8)), + (src_col.a + dst_col.a - ((dst_col.a + 1) * src_col.a >> 8)), + ) + if not dst_has_alpha: + expected_col.a = 255 + + return (expected_col, actual_col) + + # # Colour Tests + self.assertEqual( + *test_premul_surf(pygame.Color(40, 20, 0, 51), pygame.Color(40, 20, 0, 51)) + ) + + self.assertEqual( + *test_premul_surf(pygame.Color(0, 0, 0, 0), pygame.Color(40, 20, 0, 51)) + ) + + self.assertEqual( + *test_premul_surf(pygame.Color(40, 20, 0, 51), pygame.Color(0, 0, 0, 0)) + ) + + self.assertEqual( + *test_premul_surf(pygame.Color(0, 0, 0, 0), pygame.Color(0, 0, 0, 0)) + ) + + self.assertEqual( + *test_premul_surf(pygame.Color(2, 2, 2, 2), pygame.Color(40, 20, 0, 51)) + ) + + self.assertEqual( + *test_premul_surf(pygame.Color(40, 20, 0, 51), pygame.Color(2, 2, 2, 2)) + ) + + self.assertEqual( + *test_premul_surf(pygame.Color(2, 2, 2, 2), pygame.Color(2, 2, 2, 2)) + ) + + self.assertEqual( + *test_premul_surf(pygame.Color(9, 9, 9, 9), pygame.Color(40, 20, 0, 51)) + ) + + self.assertEqual( + *test_premul_surf(pygame.Color(40, 20, 0, 51), pygame.Color(9, 9, 9, 9)) + ) + + self.assertEqual( + *test_premul_surf(pygame.Color(9, 9, 9, 9), pygame.Color(9, 9, 9, 9)) + ) + + self.assertEqual( + *test_premul_surf( + pygame.Color(127, 127, 127, 127), pygame.Color(40, 20, 0, 51) + ) + ) + + self.assertEqual( + *test_premul_surf( + pygame.Color(40, 20, 0, 51), pygame.Color(127, 127, 127, 127) + ) + ) + + self.assertEqual( + *test_premul_surf( + pygame.Color(127, 127, 127, 127), pygame.Color(127, 127, 127, 127) + ) + ) + + self.assertEqual( + *test_premul_surf( + pygame.Color(200, 200, 200, 200), pygame.Color(40, 20, 0, 51) + ) + ) + + self.assertEqual( + *test_premul_surf( + pygame.Color(40, 20, 0, 51), pygame.Color(200, 200, 200, 200) + ) + ) + + self.assertEqual( + *test_premul_surf( + pygame.Color(200, 200, 200, 200), pygame.Color(200, 200, 200, 200) + ) + ) + + self.assertEqual( + *test_premul_surf( + pygame.Color(255, 255, 255, 255), pygame.Color(40, 20, 0, 51) + ) + ) + + self.assertEqual( + *test_premul_surf( + pygame.Color(40, 20, 0, 51), pygame.Color(255, 255, 255, 255) + ) + ) + + self.assertEqual( + *test_premul_surf( + pygame.Color(255, 255, 255, 255), pygame.Color(255, 255, 255, 255) + ) + ) + + # Surface format tests + self.assertRaises( + IndexError, + test_premul_surf, + pygame.Color(255, 255, 255, 255), + pygame.Color(255, 255, 255, 255), + src_size=(0, 0), + dst_size=(0, 0), + ) + + self.assertEqual( + *test_premul_surf( + pygame.Color(40, 20, 0, 51), + pygame.Color(30, 20, 0, 51), + src_size=(4, 4), + dst_size=(9, 9), + ) + ) + + self.assertEqual( + *test_premul_surf( + pygame.Color(30, 20, 0, 51), + pygame.Color(40, 20, 0, 51), + src_size=(17, 67), + dst_size=(69, 69), + ) + ) + + self.assertEqual( + *test_premul_surf( + pygame.Color(30, 20, 0, 255), + pygame.Color(40, 20, 0, 51), + src_size=(17, 67), + dst_size=(69, 69), + src_has_alpha=True, + ) + ) + self.assertEqual( + *test_premul_surf( + pygame.Color(30, 20, 0, 51), + pygame.Color(40, 20, 0, 255), + src_size=(17, 67), + dst_size=(69, 69), + dst_has_alpha=False, + ) + ) + + self.assertEqual( + *test_premul_surf( + pygame.Color(30, 20, 0, 255), + pygame.Color(40, 20, 0, 255), + src_size=(17, 67), + dst_size=(69, 69), + src_has_alpha=False, + dst_has_alpha=False, + ) + ) + + self.assertEqual( + *test_premul_surf( + pygame.Color(30, 20, 0, 255), + pygame.Color(40, 20, 0, 255), + src_size=(17, 67), + dst_size=(69, 69), + dst_bit_depth=24, + src_has_alpha=True, + dst_has_alpha=False, + ) + ) + + self.assertEqual( + *test_premul_surf( + pygame.Color(30, 20, 0, 255), + pygame.Color(40, 20, 0, 255), + src_size=(17, 67), + dst_size=(69, 69), + src_bit_depth=24, + src_has_alpha=False, + dst_has_alpha=True, + ) + ) + + self.assertEqual( + *test_premul_surf( + pygame.Color(30, 20, 0, 255), + pygame.Color(40, 20, 0, 255), + src_size=(17, 67), + dst_size=(69, 69), + src_bit_depth=24, + dst_bit_depth=24, + src_has_alpha=False, + dst_has_alpha=False, + ) + ) + + self.assertEqual( + *test_premul_surf( + pygame.Color(30, 20, 0, 255), + pygame.Color(40, 20, 0, 255), + src_size=(17, 67), + dst_size=(69, 69), + src_bit_depth=8, + ) + ) + + self.assertEqual( + *test_premul_surf( + pygame.Color(30, 20, 0, 255), + pygame.Color(40, 20, 0, 255), + src_size=(17, 67), + dst_size=(69, 69), + dst_bit_depth=8, + ) + ) + + self.assertEqual( + *test_premul_surf( + pygame.Color(30, 20, 0, 255), + pygame.Color(40, 20, 0, 255), + src_size=(17, 67), + dst_size=(69, 69), + src_bit_depth=8, + dst_bit_depth=8, + ) + ) + + def test_blit_blend_big_rect(self): + """test that an oversized rect works ok.""" + color = (1, 2, 3, 255) + area = (1, 1, 30, 30) + s1 = pygame.Surface((4, 4), 0, 32) + r = s1.fill(special_flags=pygame.BLEND_ADD, color=color, rect=area) + + self.assertEqual(pygame.Rect((1, 1, 3, 3)), r) + self.assertEqual(s1.get_at((0, 0)), (0, 0, 0, 255)) + self.assertEqual(s1.get_at((1, 1)), color) + + black = pygame.Color("black") + red = pygame.Color("red") + self.assertNotEqual(black, red) + + surf = pygame.Surface((10, 10), 0, 32) + surf.fill(black) + subsurf = surf.subsurface(pygame.Rect(0, 1, 10, 8)) + self.assertEqual(surf.get_at((0, 0)), black) + self.assertEqual(surf.get_at((0, 9)), black) + + subsurf.fill(red, (0, -1, 10, 1), pygame.BLEND_RGB_ADD) + self.assertEqual(surf.get_at((0, 0)), black) + self.assertEqual(surf.get_at((0, 9)), black) + + subsurf.fill(red, (0, 8, 10, 1), pygame.BLEND_RGB_ADD) + self.assertEqual(surf.get_at((0, 0)), black) + self.assertEqual(surf.get_at((0, 9)), black) + + def test_GET_PIXELVALS(self): + # surface.h GET_PIXELVALS bug regarding whether of not + # a surface has per-pixel alpha. Looking at the Amask + # is not enough. The surface's SRCALPHA flag must also + # be considered. Fix rev. 1923. + src = self._make_surface(32, srcalpha=True) + src.fill((0, 0, 0, 128)) + src.set_alpha(None) # Clear SRCALPHA flag. + dst = self._make_surface(32, srcalpha=True) + dst.blit(src, (0, 0), special_flags=BLEND_RGBA_ADD) + self.assertEqual(dst.get_at((0, 0)), (0, 0, 0, 255)) + + def test_fill_blend(self): + destinations = [ + self._make_surface(8), + self._make_surface(16), + self._make_surface(16, srcalpha=True), + self._make_surface(24), + self._make_surface(32), + self._make_surface(32, srcalpha=True), + ] + blend = [ + ("BLEND_ADD", (0, 25, 100, 255), lambda a, b: min(a + b, 255)), + ("BLEND_SUB", (0, 25, 100, 255), lambda a, b: max(a - b, 0)), + ("BLEND_MULT", (0, 7, 100, 255), lambda a, b: (a * b) // 256), + ("BLEND_MIN", (0, 255, 0, 255), min), + ("BLEND_MAX", (0, 255, 0, 255), max), + ] + + for dst in destinations: + dst_palette = [dst.unmap_rgb(dst.map_rgb(c)) for c in self._test_palette] + for blend_name, fill_color, op in blend: + fc = dst.unmap_rgb(dst.map_rgb(fill_color)) + self._fill_surface(dst) + p = [] + for dc in dst_palette: + c = [op(dc[i], fc[i]) for i in range(3)] + if dst.get_masks()[3]: + c.append(dc[3]) + else: + c.append(255) + c = dst.unmap_rgb(dst.map_rgb(c)) + p.append(c) + dst.fill(fill_color, special_flags=getattr(pygame, blend_name)) + self._assert_surface(dst, p, ", %s" % blend_name) + + def test_fill_blend_rgba(self): + destinations = [ + self._make_surface(8), + self._make_surface(16), + self._make_surface(16, srcalpha=True), + self._make_surface(24), + self._make_surface(32), + self._make_surface(32, srcalpha=True), + ] + blend = [ + ("BLEND_RGBA_ADD", (0, 25, 100, 255), lambda a, b: min(a + b, 255)), + ("BLEND_RGBA_SUB", (0, 25, 100, 255), lambda a, b: max(a - b, 0)), + ("BLEND_RGBA_MULT", (0, 7, 100, 255), lambda a, b: (a * b) // 256), + ("BLEND_RGBA_MIN", (0, 255, 0, 255), min), + ("BLEND_RGBA_MAX", (0, 255, 0, 255), max), + ] + + for dst in destinations: + dst_palette = [dst.unmap_rgb(dst.map_rgb(c)) for c in self._test_palette] + for blend_name, fill_color, op in blend: + fc = dst.unmap_rgb(dst.map_rgb(fill_color)) + self._fill_surface(dst) + p = [] + for dc in dst_palette: + c = [op(dc[i], fc[i]) for i in range(4)] + if not dst.get_masks()[3]: + c[3] = 255 + c = dst.unmap_rgb(dst.map_rgb(c)) + p.append(c) + dst.fill(fill_color, special_flags=getattr(pygame, blend_name)) + self._assert_surface(dst, p, ", %s" % blend_name) + + +class SurfaceSelfBlitTest(unittest.TestCase): + """Blit to self tests. + + This test case is in response to MotherHamster Bugzilla Bug 19. + """ + + def setUp(self): + # Needed for 8 bits-per-pixel color palette surface tests. + pygame.display.init() + + def tearDown(self): + pygame.display.quit() + + _test_palette = [(0, 0, 0, 255), (255, 0, 0, 0), (0, 255, 0, 255)] + surf_size = (9, 6) + + def _fill_surface(self, surf, palette=None): + if palette is None: + palette = self._test_palette + surf.fill(palette[1]) + surf.fill(palette[2], (1, 2, 1, 2)) + + def _make_surface(self, bitsize, srcalpha=False, palette=None): + if palette is None: + palette = self._test_palette + flags = 0 + if srcalpha: + flags |= SRCALPHA + surf = pygame.Surface(self.surf_size, flags, bitsize) + if bitsize == 8: + surf.set_palette([c[:3] for c in palette]) + self._fill_surface(surf, palette) + return surf + + def _assert_same(self, a, b): + w, h = a.get_size() + for x in range(w): + for y in range(h): + self.assertEqual( + a.get_at((x, y)), + b.get_at((x, y)), + ( + "%s != %s, bpp: %i" + % (a.get_at((x, y)), b.get_at((x, y)), a.get_bitsize()) + ), + ) + + def test_overlap_check(self): + # Ensure overlapping blits are properly detected. There are two + # places where this is done, within SoftBlitPyGame() in alphablit.c + # and PySurface_Blit() in surface.c. SoftBlitPyGame should catch the + # per-pixel alpha surface, PySurface_Blit the colorkey and blanket + # alpha surface. per-pixel alpha and blanket alpha self blits are + # not properly handled by SDL 1.2.13, so Pygame does them. + bgc = (0, 0, 0, 255) + rectc_left = (128, 64, 32, 255) + rectc_right = (255, 255, 255, 255) + colors = [(255, 255, 255, 255), (128, 64, 32, 255)] + overlaps = [ + (0, 0, 1, 0, (50, 0)), + (0, 0, 49, 1, (98, 2)), + (0, 0, 49, 49, (98, 98)), + (49, 0, 0, 1, (0, 2)), + (49, 0, 0, 49, (0, 98)), + ] + surfs = [pygame.Surface((100, 100), SRCALPHA, 32)] + surf = pygame.Surface((100, 100), 0, 32) + surf.set_alpha(255) + surfs.append(surf) + surf = pygame.Surface((100, 100), 0, 32) + surf.set_colorkey((0, 1, 0)) + surfs.append(surf) + for surf in surfs: + for s_x, s_y, d_x, d_y, test_posn in overlaps: + surf.fill(bgc) + surf.fill(rectc_right, (25, 0, 25, 50)) + surf.fill(rectc_left, (0, 0, 25, 50)) + surf.blit(surf, (d_x, d_y), (s_x, s_y, 50, 50)) + self.assertEqual(surf.get_at(test_posn), rectc_right) + + # https://github.com/pygame/pygame/issues/370#issuecomment-364625291 + @unittest.skipIf("ppc64le" in platform.uname(), "known ppc64le issue") + def test_colorkey(self): + # Check a workaround for an SDL 1.2.13 surface self-blit problem + # (MotherHamster Bugzilla bug 19). + pygame.display.set_mode((100, 50)) # Needed for 8bit surface + bitsizes = [8, 16, 24, 32] + for bitsize in bitsizes: + surf = self._make_surface(bitsize) + surf.set_colorkey(self._test_palette[1]) + surf.blit(surf, (3, 0)) + p = [] + for c in self._test_palette: + c = surf.unmap_rgb(surf.map_rgb(c)) + p.append(c) + p[1] = (p[1][0], p[1][1], p[1][2], 0) + tmp = self._make_surface(32, srcalpha=True, palette=p) + tmp.blit(tmp, (3, 0)) + tmp.set_alpha(None) + comp = self._make_surface(bitsize) + comp.blit(tmp, (0, 0)) + self._assert_same(surf, comp) + + # https://github.com/pygame/pygame/issues/370#issuecomment-364625291 + @unittest.skipIf("ppc64le" in platform.uname(), "known ppc64le issue") + def test_blanket_alpha(self): + # Check a workaround for an SDL 1.2.13 surface self-blit problem + # (MotherHamster Bugzilla bug 19). + pygame.display.set_mode((100, 50)) # Needed for 8bit surface + bitsizes = [8, 16, 24, 32] + for bitsize in bitsizes: + surf = self._make_surface(bitsize) + surf.set_alpha(128) + surf.blit(surf, (3, 0)) + p = [] + for c in self._test_palette: + c = surf.unmap_rgb(surf.map_rgb(c)) + p.append((c[0], c[1], c[2], 128)) + tmp = self._make_surface(32, srcalpha=True, palette=p) + tmp.blit(tmp, (3, 0)) + tmp.set_alpha(None) + comp = self._make_surface(bitsize) + comp.blit(tmp, (0, 0)) + self._assert_same(surf, comp) + + def test_pixel_alpha(self): + bitsizes = [16, 32] + for bitsize in bitsizes: + surf = self._make_surface(bitsize, srcalpha=True) + comp = self._make_surface(bitsize, srcalpha=True) + comp.blit(surf, (3, 0)) + surf.blit(surf, (3, 0)) + self._assert_same(surf, comp) + + def test_blend(self): + bitsizes = [8, 16, 24, 32] + blends = ["BLEND_ADD", "BLEND_SUB", "BLEND_MULT", "BLEND_MIN", "BLEND_MAX"] + for bitsize in bitsizes: + surf = self._make_surface(bitsize) + comp = self._make_surface(bitsize) + for blend in blends: + self._fill_surface(surf) + self._fill_surface(comp) + comp.blit(surf, (3, 0), special_flags=getattr(pygame, blend)) + surf.blit(surf, (3, 0), special_flags=getattr(pygame, blend)) + self._assert_same(surf, comp) + + def test_blend_rgba(self): + bitsizes = [16, 32] + blends = [ + "BLEND_RGBA_ADD", + "BLEND_RGBA_SUB", + "BLEND_RGBA_MULT", + "BLEND_RGBA_MIN", + "BLEND_RGBA_MAX", + ] + for bitsize in bitsizes: + surf = self._make_surface(bitsize, srcalpha=True) + comp = self._make_surface(bitsize, srcalpha=True) + for blend in blends: + self._fill_surface(surf) + self._fill_surface(comp) + comp.blit(surf, (3, 0), special_flags=getattr(pygame, blend)) + surf.blit(surf, (3, 0), special_flags=getattr(pygame, blend)) + self._assert_same(surf, comp) + + def test_subsurface(self): + # Blitting a surface to its subsurface is allowed. + surf = self._make_surface(32, srcalpha=True) + comp = surf.copy() + comp.blit(surf, (3, 0)) + sub = surf.subsurface((3, 0, 6, 6)) + sub.blit(surf, (0, 0)) + del sub + self._assert_same(surf, comp) + + # Blitting a subsurface to its owner is forbidden because of + # lock conficts. This limitation allows the overlap check + # in PySurface_Blit of alphablit.c to be simplified. + def do_blit(d, s): + d.blit(s, (0, 0)) + + sub = surf.subsurface((1, 1, 2, 2)) + self.assertRaises(pygame.error, do_blit, surf, sub) + + def test_copy_alpha(self): + """issue 581: alpha of surface copy with SRCALPHA is set to 0.""" + surf = pygame.Surface((16, 16), pygame.SRCALPHA, 32) + self.assertEqual(surf.get_alpha(), 255) + surf2 = surf.copy() + self.assertEqual(surf2.get_alpha(), 255) + + +class SurfaceFillTest(unittest.TestCase): + def setUp(self): + pygame.display.init() + + def tearDown(self): + pygame.display.quit() + + def test_fill(self): + screen = pygame.display.set_mode((640, 480)) + + # Green and blue test pattern + screen.fill((0, 255, 0), (0, 0, 320, 240)) + screen.fill((0, 255, 0), (320, 240, 320, 240)) + screen.fill((0, 0, 255), (320, 0, 320, 240)) + screen.fill((0, 0, 255), (0, 240, 320, 240)) + + # Now apply a clip rect, such that only the left side of the + # screen should be effected by blit operations. + screen.set_clip((0, 0, 320, 480)) + + # Test fills with each special flag, and additionally without any. + screen.fill((255, 0, 0, 127), (160, 0, 320, 30), 0) + screen.fill((255, 0, 0, 127), (160, 30, 320, 30), pygame.BLEND_ADD) + screen.fill((0, 127, 127, 127), (160, 60, 320, 30), pygame.BLEND_SUB) + screen.fill((0, 63, 63, 127), (160, 90, 320, 30), pygame.BLEND_MULT) + screen.fill((0, 127, 127, 127), (160, 120, 320, 30), pygame.BLEND_MIN) + screen.fill((127, 0, 0, 127), (160, 150, 320, 30), pygame.BLEND_MAX) + screen.fill((255, 0, 0, 127), (160, 180, 320, 30), pygame.BLEND_RGBA_ADD) + screen.fill((0, 127, 127, 127), (160, 210, 320, 30), pygame.BLEND_RGBA_SUB) + screen.fill((0, 63, 63, 127), (160, 240, 320, 30), pygame.BLEND_RGBA_MULT) + screen.fill((0, 127, 127, 127), (160, 270, 320, 30), pygame.BLEND_RGBA_MIN) + screen.fill((127, 0, 0, 127), (160, 300, 320, 30), pygame.BLEND_RGBA_MAX) + screen.fill((255, 0, 0, 127), (160, 330, 320, 30), pygame.BLEND_RGB_ADD) + screen.fill((0, 127, 127, 127), (160, 360, 320, 30), pygame.BLEND_RGB_SUB) + screen.fill((0, 63, 63, 127), (160, 390, 320, 30), pygame.BLEND_RGB_MULT) + screen.fill((0, 127, 127, 127), (160, 420, 320, 30), pygame.BLEND_RGB_MIN) + screen.fill((255, 0, 0, 127), (160, 450, 320, 30), pygame.BLEND_RGB_MAX) + + # Update the display so we can see the results + pygame.display.flip() + + # Compare colors on both sides of window + for y in range(5, 480, 10): + self.assertEqual(screen.get_at((10, y)), screen.get_at((330, 480 - y))) + + +if __name__ == "__main__": + unittest.main() diff --git a/venv/Lib/site-packages/pygame/tests/surfarray_tags.py b/venv/Lib/site-packages/pygame/tests/surfarray_tags.py new file mode 100644 index 0000000..baa535c --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/surfarray_tags.py @@ -0,0 +1,16 @@ +__tags__ = ["array"] + +exclude = False + +try: + import numpy +except ImportError: + exclude = True +else: + try: + import pygame.pixelcopy + except ImportError: + exclude = True + +if exclude: + __tags__.extend(("ignore", "subprocess_ignore")) diff --git a/venv/Lib/site-packages/pygame/tests/surfarray_test.py b/venv/Lib/site-packages/pygame/tests/surfarray_test.py new file mode 100644 index 0000000..246da82 --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/surfarray_test.py @@ -0,0 +1,754 @@ +import unittest +import platform + +from numpy import ( + uint8, + uint16, + uint32, + uint64, + zeros, + float32, + float64, + alltrue, + rint, + arange, +) + +import pygame +from pygame.locals import * + +import pygame.surfarray + + +IS_PYPY = "PyPy" == platform.python_implementation() + + +@unittest.skipIf(IS_PYPY, "pypy skip known failure") # TODO +class SurfarrayModuleTest(unittest.TestCase): + pixels2d = {8: True, 16: True, 24: False, 32: True} + pixels3d = {8: False, 16: False, 24: True, 32: True} + array2d = {8: True, 16: True, 24: True, 32: True} + array3d = {8: False, 16: False, 24: True, 32: True} + + test_palette = [ + (0, 0, 0, 255), + (10, 30, 60, 255), + (25, 75, 100, 255), + (100, 150, 200, 255), + (0, 100, 200, 255), + ] + surf_size = (10, 12) + test_points = [ + ((0, 0), 1), + ((4, 5), 1), + ((9, 0), 2), + ((5, 5), 2), + ((0, 11), 3), + ((4, 6), 3), + ((9, 11), 4), + ((5, 6), 4), + ] + + @classmethod + def setUpClass(cls): + # Needed for 8 bits-per-pixel color palette surface tests. + pygame.init() + + @classmethod + def tearDownClass(cls): + pygame.quit() + + def setUp(cls): + # This makes sure pygame is always initialized before each test (in + # case a test calls pygame.quit()). + if not pygame.get_init(): + pygame.init() + + def _make_surface(self, bitsize, srcalpha=False, palette=None): + if palette is None: + palette = self.test_palette + flags = 0 + if srcalpha: + flags |= SRCALPHA + surf = pygame.Surface(self.surf_size, flags, bitsize) + if bitsize == 8: + surf.set_palette([c[:3] for c in palette]) + return surf + + def _fill_surface(self, surf, palette=None): + if palette is None: + palette = self.test_palette + surf.fill(palette[1], (0, 0, 5, 6)) + surf.fill(palette[2], (5, 0, 5, 6)) + surf.fill(palette[3], (0, 6, 5, 6)) + surf.fill(palette[4], (5, 6, 5, 6)) + + def _make_src_surface(self, bitsize, srcalpha=False, palette=None): + surf = self._make_surface(bitsize, srcalpha, palette) + self._fill_surface(surf, palette) + return surf + + def _assert_surface(self, surf, palette=None, msg=""): + if palette is None: + palette = self.test_palette + if surf.get_bitsize() == 16: + palette = [surf.unmap_rgb(surf.map_rgb(c)) for c in palette] + for posn, i in self.test_points: + self.assertEqual( + surf.get_at(posn), + palette[i], + "%s != %s: flags: %i, bpp: %i, posn: %s%s" + % ( + surf.get_at(posn), + palette[i], + surf.get_flags(), + surf.get_bitsize(), + posn, + msg, + ), + ) + + def _make_array3d(self, dtype): + return zeros((self.surf_size[0], self.surf_size[1], 3), dtype) + + def _fill_array2d(self, arr, surf): + palette = self.test_palette + arr[:5, :6] = surf.map_rgb(palette[1]) + arr[5:, :6] = surf.map_rgb(palette[2]) + arr[:5, 6:] = surf.map_rgb(palette[3]) + arr[5:, 6:] = surf.map_rgb(palette[4]) + + def _fill_array3d(self, arr): + palette = self.test_palette + arr[:5, :6] = palette[1][:3] + arr[5:, :6] = palette[2][:3] + arr[:5, 6:] = palette[3][:3] + arr[5:, 6:] = palette[4][:3] + + def _make_src_array3d(self, dtype): + arr = self._make_array3d(dtype) + self._fill_array3d(arr) + return arr + + def _make_array2d(self, dtype): + return zeros(self.surf_size, dtype) + + def test_array2d(self): + + sources = [ + self._make_src_surface(8), + self._make_src_surface(16), + self._make_src_surface(16, srcalpha=True), + self._make_src_surface(24), + self._make_src_surface(32), + self._make_src_surface(32, srcalpha=True), + ] + palette = self.test_palette + alpha_color = (0, 0, 0, 128) + + for surf in sources: + arr = pygame.surfarray.array2d(surf) + for posn, i in self.test_points: + self.assertEqual( + arr[posn], + surf.get_at_mapped(posn), + "%s != %s: flags: %i, bpp: %i, posn: %s" + % ( + arr[posn], + surf.get_at_mapped(posn), + surf.get_flags(), + surf.get_bitsize(), + posn, + ), + ) + + if surf.get_masks()[3]: + surf.fill(alpha_color) + arr = pygame.surfarray.array2d(surf) + posn = (0, 0) + self.assertEqual( + arr[posn], + surf.get_at_mapped(posn), + "%s != %s: bpp: %i" + % (arr[posn], surf.get_at_mapped(posn), surf.get_bitsize()), + ) + + def test_array3d(self): + + sources = [ + self._make_src_surface(16), + self._make_src_surface(16, srcalpha=True), + self._make_src_surface(24), + self._make_src_surface(32), + self._make_src_surface(32, srcalpha=True), + ] + palette = self.test_palette + + for surf in sources: + arr = pygame.surfarray.array3d(surf) + + def same_color(ac, sc): + return ac[0] == sc[0] and ac[1] == sc[1] and ac[2] == sc[2] + + for posn, i in self.test_points: + self.assertTrue( + same_color(arr[posn], surf.get_at(posn)), + "%s != %s: flags: %i, bpp: %i, posn: %s" + % ( + tuple(arr[posn]), + surf.get_at(posn), + surf.get_flags(), + surf.get_bitsize(), + posn, + ), + ) + + def test_array_alpha(self): + + palette = [ + (0, 0, 0, 0), + (10, 50, 100, 255), + (60, 120, 240, 130), + (64, 128, 255, 0), + (255, 128, 0, 65), + ] + targets = [ + self._make_src_surface(8, palette=palette), + self._make_src_surface(16, palette=palette), + self._make_src_surface(16, palette=palette, srcalpha=True), + self._make_src_surface(24, palette=palette), + self._make_src_surface(32, palette=palette), + self._make_src_surface(32, palette=palette, srcalpha=True), + ] + + for surf in targets: + p = palette + if surf.get_bitsize() == 16: + p = [surf.unmap_rgb(surf.map_rgb(c)) for c in p] + arr = pygame.surfarray.array_alpha(surf) + if surf.get_masks()[3]: + for (x, y), i in self.test_points: + self.assertEqual( + arr[x, y], + p[i][3], + ( + "%i != %i, posn: (%i, %i), " + "bitsize: %i" + % (arr[x, y], p[i][3], x, y, surf.get_bitsize()) + ), + ) + else: + self.assertTrue(alltrue(arr == 255)) + + # No per-pixel alpha when blanket alpha is None. + for surf in targets: + blanket_alpha = surf.get_alpha() + surf.set_alpha(None) + arr = pygame.surfarray.array_alpha(surf) + self.assertTrue( + alltrue(arr == 255), + "All alpha values should be 255 when" + " surf.set_alpha(None) has been set." + " bitsize: %i, flags: %i" % (surf.get_bitsize(), surf.get_flags()), + ) + surf.set_alpha(blanket_alpha) + + # Bug for per-pixel alpha surface when blanket alpha 0. + for surf in targets: + blanket_alpha = surf.get_alpha() + surf.set_alpha(0) + arr = pygame.surfarray.array_alpha(surf) + if surf.get_masks()[3]: + self.assertFalse( + alltrue(arr == 255), + "bitsize: %i, flags: %i" % (surf.get_bitsize(), surf.get_flags()), + ) + else: + self.assertTrue( + alltrue(arr == 255), + "bitsize: %i, flags: %i" % (surf.get_bitsize(), surf.get_flags()), + ) + surf.set_alpha(blanket_alpha) + + def test_array_colorkey(self): + + palette = [ + (0, 0, 0, 0), + (10, 50, 100, 255), + (60, 120, 240, 130), + (64, 128, 255, 0), + (255, 128, 0, 65), + ] + targets = [ + self._make_src_surface(8, palette=palette), + self._make_src_surface(16, palette=palette), + self._make_src_surface(16, palette=palette, srcalpha=True), + self._make_src_surface(24, palette=palette), + self._make_src_surface(32, palette=palette), + self._make_src_surface(32, palette=palette, srcalpha=True), + ] + + for surf in targets: + p = palette + if surf.get_bitsize() == 16: + p = [surf.unmap_rgb(surf.map_rgb(c)) for c in p] + surf.set_colorkey(None) + arr = pygame.surfarray.array_colorkey(surf) + self.assertTrue(alltrue(arr == 255)) + + for i in range(1, len(palette)): + surf.set_colorkey(p[i]) + alphas = [255] * len(p) + alphas[i] = 0 + arr = pygame.surfarray.array_colorkey(surf) + for (x, y), j in self.test_points: + self.assertEqual( + arr[x, y], + alphas[j], + ( + "%i != %i, posn: (%i, %i), " + "bitsize: %i" + % (arr[x, y], alphas[j], x, y, surf.get_bitsize()) + ), + ) + + def test_array_red(self): + self._test_array_rgb("red", 0) + + def test_array_green(self): + self._test_array_rgb("green", 1) + + def test_array_blue(self): + self._test_array_rgb("blue", 2) + + def _test_array_rgb(self, operation, mask_posn): + method_name = "array_" + operation + + array_rgb = getattr(pygame.surfarray, method_name) + palette = [ + (0, 0, 0, 255), + (5, 13, 23, 255), + (29, 31, 37, 255), + (131, 157, 167, 255), + (179, 191, 251, 255), + ] + plane = [c[mask_posn] for c in palette] + + targets = [ + self._make_src_surface(24, palette=palette), + self._make_src_surface(32, palette=palette), + self._make_src_surface(32, palette=palette, srcalpha=True), + ] + + for surf in targets: + self.assertFalse(surf.get_locked()) + for (x, y), i in self.test_points: + surf.fill(palette[i]) + arr = array_rgb(surf) + self.assertEqual(arr[x, y], plane[i]) + surf.fill((100, 100, 100, 250)) + self.assertEqual(arr[x, y], plane[i]) + self.assertFalse(surf.get_locked()) + del arr + + def test_blit_array(self): + + s = pygame.Surface((10, 10), 0, 24) + a = pygame.surfarray.array3d(s) + pygame.surfarray.blit_array(s, a) + + # target surfaces + targets = [ + self._make_surface(8), + self._make_surface(16), + self._make_surface(16, srcalpha=True), + self._make_surface(24), + self._make_surface(32), + self._make_surface(32, srcalpha=True), + ] + + # source arrays + arrays3d = [] + dtypes = [(8, uint8), (16, uint16), (32, uint32)] + try: + dtypes.append((64, uint64)) + except NameError: + pass + arrays3d = [(self._make_src_array3d(dtype), None) for __, dtype in dtypes] + for bitsize in [8, 16, 24, 32]: + palette = None + if bitsize == 16: + s = pygame.Surface((1, 1), 0, 16) + palette = [s.unmap_rgb(s.map_rgb(c)) for c in self.test_palette] + if self.pixels3d[bitsize]: + surf = self._make_src_surface(bitsize) + arr = pygame.surfarray.pixels3d(surf) + arrays3d.append((arr, palette)) + if self.array3d[bitsize]: + surf = self._make_src_surface(bitsize) + arr = pygame.surfarray.array3d(surf) + arrays3d.append((arr, palette)) + for sz, dtype in dtypes: + arrays3d.append((arr.astype(dtype), palette)) + + # tests on arrays + def do_blit(surf, arr): + pygame.surfarray.blit_array(surf, arr) + + for surf in targets: + bitsize = surf.get_bitsize() + for arr, palette in arrays3d: + surf.fill((0, 0, 0, 0)) + if bitsize == 8: + self.assertRaises(ValueError, do_blit, surf, arr) + else: + pygame.surfarray.blit_array(surf, arr) + self._assert_surface(surf, palette) + + if self.pixels2d[bitsize]: + surf.fill((0, 0, 0, 0)) + s = self._make_src_surface(bitsize, surf.get_flags() & SRCALPHA) + arr = pygame.surfarray.pixels2d(s) + pygame.surfarray.blit_array(surf, arr) + self._assert_surface(surf) + + if self.array2d[bitsize]: + s = self._make_src_surface(bitsize, surf.get_flags() & SRCALPHA) + arr = pygame.surfarray.array2d(s) + for sz, dtype in dtypes: + surf.fill((0, 0, 0, 0)) + if sz >= bitsize: + pygame.surfarray.blit_array(surf, arr.astype(dtype)) + self._assert_surface(surf) + else: + self.assertRaises( + ValueError, do_blit, surf, self._make_array2d(dtype) + ) + + # Check alpha for 2D arrays + surf = self._make_surface(16, srcalpha=True) + arr = zeros(surf.get_size(), uint16) + arr[...] = surf.map_rgb((0, 128, 255, 64)) + color = surf.unmap_rgb(arr[0, 0]) + pygame.surfarray.blit_array(surf, arr) + self.assertEqual(surf.get_at((5, 5)), color) + + surf = self._make_surface(32, srcalpha=True) + arr = zeros(surf.get_size(), uint32) + color = (0, 111, 255, 63) + arr[...] = surf.map_rgb(color) + pygame.surfarray.blit_array(surf, arr) + self.assertEqual(surf.get_at((5, 5)), color) + + # Check shifts + arr3d = self._make_src_array3d(uint8) + + shift_tests = [ + (16, [12, 0, 8, 4], [0xF000, 0xF, 0xF00, 0xF0]), + (24, [16, 0, 8, 0], [0xFF0000, 0xFF, 0xFF00, 0]), + (32, [0, 16, 24, 8], [0xFF, 0xFF0000, 0xFF000000, 0xFF00]), + ] + + for bitsize, shifts, masks in shift_tests: + surf = self._make_surface(bitsize, srcalpha=(shifts[3] != 0)) + palette = None + if bitsize == 16: + palette = [surf.unmap_rgb(surf.map_rgb(c)) for c in self.test_palette] + + self.assertRaises(TypeError, surf.set_shifts, shifts) + self.assertRaises(TypeError, surf.set_masks, masks) + + # Invalid arrays + surf = pygame.Surface((1, 1), 0, 32) + t = "abcd" + self.assertRaises(ValueError, do_blit, surf, t) + + surf_size = self.surf_size + surf = pygame.Surface(surf_size, 0, 32) + arr = zeros([surf_size[0], surf_size[1] + 1, 3], uint32) + self.assertRaises(ValueError, do_blit, surf, arr) + arr = zeros([surf_size[0] + 1, surf_size[1], 3], uint32) + self.assertRaises(ValueError, do_blit, surf, arr) + + surf = pygame.Surface((1, 4), 0, 32) + arr = zeros((4,), uint32) + self.assertRaises(ValueError, do_blit, surf, arr) + arr.shape = (1, 1, 1, 4) + self.assertRaises(ValueError, do_blit, surf, arr) + + # Issue #81: round from float to int + try: + rint + except NameError: + pass + else: + surf = pygame.Surface((10, 10), pygame.SRCALPHA, 32) + w, h = surf.get_size() + length = w * h + for dtype in [float32, float64]: + surf.fill((255, 255, 255, 0)) + farr = arange(0, length, dtype=dtype) + farr.shape = w, h + pygame.surfarray.blit_array(surf, farr) + for x in range(w): + for y in range(h): + self.assertEqual( + surf.get_at_mapped((x, y)), int(rint(farr[x, y])) + ) + + # this test should be removed soon, when the function is deleted + def test_get_arraytype(self): + array_type = pygame.surfarray.get_arraytype() + + self.assertEqual(array_type, "numpy", "unknown array type %s" % array_type) + + # this test should be removed soon, when the function is deleted + def test_get_arraytypes(self): + + arraytypes = pygame.surfarray.get_arraytypes() + self.assertIn("numpy", arraytypes) + + for atype in arraytypes: + self.assertEqual(atype, "numpy", "unknown array type %s" % atype) + + def test_make_surface(self): + + # How does one properly test this with 2d arrays. It makes no sense + # since the pixel format is not entirely dependent on element size. + # Just make sure the surface pixel size is at least as large as the + # array element size I guess. + # + for bitsize, dtype in [(8, uint8), (16, uint16), (24, uint32)]: + ## Even this simple assertion fails for 2d arrays. Where's the problem? + ## surf = pygame.surfarray.make_surface(self._make_array2d(dtype)) + ## self.assertGreaterEqual(surf.get_bitsize(), bitsize, + ## "not %i >= %i)" % (surf.get_bitsize(), bitsize)) + ## + surf = pygame.surfarray.make_surface(self._make_src_array3d(dtype)) + self._assert_surface(surf) + + # Issue #81: round from float to int + try: + rint + except NameError: + pass + else: + w = 9 + h = 11 + length = w * h + for dtype in [float32, float64]: + farr = arange(0, length, dtype=dtype) + farr.shape = w, h + surf = pygame.surfarray.make_surface(farr) + for x in range(w): + for y in range(h): + self.assertEqual( + surf.get_at_mapped((x, y)), int(rint(farr[x, y])) + ) + + def test_map_array(self): + + arr3d = self._make_src_array3d(uint8) + targets = [ + self._make_surface(8), + self._make_surface(16), + self._make_surface(16, srcalpha=True), + self._make_surface(24), + self._make_surface(32), + self._make_surface(32, srcalpha=True), + ] + palette = self.test_palette + + for surf in targets: + arr2d = pygame.surfarray.map_array(surf, arr3d) + for posn, i in self.test_points: + self.assertEqual( + arr2d[posn], + surf.map_rgb(palette[i]), + "%i != %i, bitsize: %i, flags: %i" + % ( + arr2d[posn], + surf.map_rgb(palette[i]), + surf.get_bitsize(), + surf.get_flags(), + ), + ) + + # Exception checks + self.assertRaises( + ValueError, + pygame.surfarray.map_array, + self._make_surface(32), + self._make_array2d(uint8), + ) + + def test_pixels2d(self): + + sources = [ + self._make_surface(8), + self._make_surface(16, srcalpha=True), + self._make_surface(32, srcalpha=True), + ] + + for surf in sources: + self.assertFalse(surf.get_locked()) + arr = pygame.surfarray.pixels2d(surf) + self.assertTrue(surf.get_locked()) + self._fill_array2d(arr, surf) + surf.unlock() + self.assertTrue(surf.get_locked()) + del arr + self.assertFalse(surf.get_locked()) + self.assertEqual(surf.get_locks(), ()) + self._assert_surface(surf) + + # Error checks + self.assertRaises(ValueError, pygame.surfarray.pixels2d, self._make_surface(24)) + + def test_pixels3d(self): + + sources = [self._make_surface(24), self._make_surface(32)] + + for surf in sources: + self.assertFalse(surf.get_locked()) + arr = pygame.surfarray.pixels3d(surf) + self.assertTrue(surf.get_locked()) + self._fill_array3d(arr) + surf.unlock() + self.assertTrue(surf.get_locked()) + del arr + self.assertFalse(surf.get_locked()) + self.assertEqual(surf.get_locks(), ()) + self._assert_surface(surf) + + # Alpha check + color = (1, 2, 3, 0) + surf = self._make_surface(32, srcalpha=True) + arr = pygame.surfarray.pixels3d(surf) + arr[0, 0] = color[:3] + self.assertEqual(surf.get_at((0, 0)), color) + + # Error checks + def do_pixels3d(surf): + pygame.surfarray.pixels3d(surf) + + self.assertRaises(ValueError, do_pixels3d, self._make_surface(8)) + self.assertRaises(ValueError, do_pixels3d, self._make_surface(16)) + + def test_pixels_alpha(self): + + palette = [ + (0, 0, 0, 0), + (127, 127, 127, 0), + (127, 127, 127, 85), + (127, 127, 127, 170), + (127, 127, 127, 255), + ] + alphas = [0, 45, 86, 99, 180] + + surf = self._make_src_surface(32, srcalpha=True, palette=palette) + + self.assertFalse(surf.get_locked()) + arr = pygame.surfarray.pixels_alpha(surf) + self.assertTrue(surf.get_locked()) + surf.unlock() + self.assertTrue(surf.get_locked()) + + for (x, y), i in self.test_points: + self.assertEqual(arr[x, y], palette[i][3]) + + for (x, y), i in self.test_points: + alpha = alphas[i] + arr[x, y] = alpha + color = (127, 127, 127, alpha) + self.assertEqual(surf.get_at((x, y)), color, "posn: (%i, %i)" % (x, y)) + + del arr + self.assertFalse(surf.get_locked()) + self.assertEqual(surf.get_locks(), ()) + + # Check exceptions. + def do_pixels_alpha(surf): + pygame.surfarray.pixels_alpha(surf) + + targets = [(8, False), (16, False), (16, True), (24, False), (32, False)] + + for bitsize, srcalpha in targets: + self.assertRaises( + ValueError, do_pixels_alpha, self._make_surface(bitsize, srcalpha) + ) + + def test_pixels_red(self): + self._test_pixels_rgb("red", 0) + + def test_pixels_green(self): + self._test_pixels_rgb("green", 1) + + def test_pixels_blue(self): + self._test_pixels_rgb("blue", 2) + + def _test_pixels_rgb(self, operation, mask_posn): + method_name = "pixels_" + operation + + pixels_rgb = getattr(pygame.surfarray, method_name) + palette = [ + (0, 0, 0, 255), + (5, 13, 23, 255), + (29, 31, 37, 255), + (131, 157, 167, 255), + (179, 191, 251, 255), + ] + plane = [c[mask_posn] for c in palette] + + surf24 = self._make_src_surface(24, srcalpha=False, palette=palette) + surf32 = self._make_src_surface(32, srcalpha=False, palette=palette) + surf32a = self._make_src_surface(32, srcalpha=True, palette=palette) + + for surf in [surf24, surf32, surf32a]: + self.assertFalse(surf.get_locked()) + arr = pixels_rgb(surf) + self.assertTrue(surf.get_locked()) + surf.unlock() + self.assertTrue(surf.get_locked()) + + for (x, y), i in self.test_points: + self.assertEqual(arr[x, y], plane[i]) + + del arr + self.assertFalse(surf.get_locked()) + self.assertEqual(surf.get_locks(), ()) + + # Check exceptions. + targets = [(8, False), (16, False), (16, True)] + + for bitsize, srcalpha in targets: + self.assertRaises( + ValueError, pixels_rgb, self._make_surface(bitsize, srcalpha) + ) + + def test_use_arraytype(self): + def do_use_arraytype(atype): + pygame.surfarray.use_arraytype(atype) + + pygame.surfarray.use_arraytype("numpy") + self.assertEqual(pygame.surfarray.get_arraytype(), "numpy") + self.assertRaises(ValueError, do_use_arraytype, "not an option") + + def test_surf_lock(self): + sf = pygame.Surface((5, 5), 0, 32) + for atype in pygame.surfarray.get_arraytypes(): + pygame.surfarray.use_arraytype(atype) + + ar = pygame.surfarray.pixels2d(sf) + self.assertTrue(sf.get_locked()) + + sf.unlock() + self.assertTrue(sf.get_locked()) + + del ar + self.assertFalse(sf.get_locked()) + self.assertEqual(sf.get_locks(), ()) + + +if __name__ == "__main__": + unittest.main() diff --git a/venv/Lib/site-packages/pygame/tests/surflock_test.py b/venv/Lib/site-packages/pygame/tests/surflock_test.py new file mode 100644 index 0000000..19f354b --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/surflock_test.py @@ -0,0 +1,144 @@ +import unittest +import sys +import platform + +import pygame + +IS_PYPY = "PyPy" == platform.python_implementation() + + +@unittest.skipIf(IS_PYPY, "pypy skip known failure") # TODO +class SurfaceLockTest(unittest.TestCase): + def test_lock(self): + sf = pygame.Surface((5, 5)) + + sf.lock() + self.assertEqual(sf.get_locked(), True) + self.assertEqual(sf.get_locks(), (sf,)) + + sf.lock() + self.assertEqual(sf.get_locked(), True) + self.assertEqual(sf.get_locks(), (sf, sf)) + + sf.unlock() + self.assertEqual(sf.get_locked(), True) + self.assertEqual(sf.get_locks(), (sf,)) + + sf.unlock() + self.assertEqual(sf.get_locked(), False) + self.assertEqual(sf.get_locks(), ()) + + def test_subsurface_lock(self): + sf = pygame.Surface((5, 5)) + subsf = sf.subsurface((1, 1, 2, 2)) + sf2 = pygame.Surface((5, 5)) + + # Simple blits, nothing should happen here. + sf2.blit(subsf, (0, 0)) + sf2.blit(sf, (0, 0)) + + # Test blitting on self: + self.assertRaises(pygame.error, sf.blit, subsf, (0, 0)) + # self.assertRaises(pygame.error, subsf.blit, sf, (0, 0)) + # ^ Fails although it should not in my opinion. If I cannot + # blit the subsurface to the surface, it should not be allowed + # the other way around as well. + + # Test additional locks. + sf.lock() + sf2.blit(subsf, (0, 0)) + self.assertRaises(pygame.error, sf2.blit, sf, (0, 0)) + + subsf.lock() + self.assertRaises(pygame.error, sf2.blit, subsf, (0, 0)) + self.assertRaises(pygame.error, sf2.blit, sf, (0, 0)) + + # sf and subsf are now explicitly locked. Unlock sf, so we can + # (assume) to blit it. + # It will fail though as the subsurface still has a lock around, + # which is okay and correct behaviour. + sf.unlock() + self.assertRaises(pygame.error, sf2.blit, subsf, (0, 0)) + self.assertRaises(pygame.error, sf2.blit, sf, (0, 0)) + + # Run a second unlock on the surface. This should ideally have + # no effect as the subsurface is the locking reason! + sf.unlock() + self.assertRaises(pygame.error, sf2.blit, sf, (0, 0)) + self.assertRaises(pygame.error, sf2.blit, subsf, (0, 0)) + subsf.unlock() + + sf.lock() + self.assertEqual(sf.get_locked(), True) + self.assertEqual(sf.get_locks(), (sf,)) + self.assertEqual(subsf.get_locked(), False) + self.assertEqual(subsf.get_locks(), ()) + + subsf.lock() + self.assertEqual(sf.get_locked(), True) + self.assertEqual(sf.get_locks(), (sf, subsf)) + self.assertEqual(subsf.get_locked(), True) + self.assertEqual(subsf.get_locks(), (subsf,)) + + sf.unlock() + self.assertEqual(sf.get_locked(), True) + self.assertEqual(sf.get_locks(), (subsf,)) + self.assertEqual(subsf.get_locked(), True) + self.assertEqual(subsf.get_locks(), (subsf,)) + + subsf.unlock() + self.assertEqual(sf.get_locked(), False) + self.assertEqual(sf.get_locks(), ()) + self.assertEqual(subsf.get_locked(), False) + self.assertEqual(subsf.get_locks(), ()) + + subsf.lock() + self.assertEqual(sf.get_locked(), True) + self.assertEqual(sf.get_locks(), (subsf,)) + self.assertEqual(subsf.get_locked(), True) + self.assertEqual(subsf.get_locks(), (subsf,)) + + subsf.lock() + self.assertEqual(sf.get_locked(), True) + self.assertEqual(sf.get_locks(), (subsf, subsf)) + self.assertEqual(subsf.get_locked(), True) + self.assertEqual(subsf.get_locks(), (subsf, subsf)) + + def test_pxarray_ref(self): + sf = pygame.Surface((5, 5)) + ar = pygame.PixelArray(sf) + ar2 = pygame.PixelArray(sf) + + self.assertEqual(sf.get_locked(), True) + self.assertEqual(sf.get_locks(), (ar, ar2)) + + del ar + self.assertEqual(sf.get_locked(), True) + self.assertEqual(sf.get_locks(), (ar2,)) + + ar = ar2[:] + self.assertEqual(sf.get_locked(), True) + self.assertEqual(sf.get_locks(), (ar2,)) + + del ar + self.assertEqual(sf.get_locked(), True) + self.assertEqual(len(sf.get_locks()), 1) + + def test_buffer(self): + sf = pygame.Surface((5, 5)) + buf = sf.get_buffer() + + self.assertEqual(sf.get_locked(), True) + self.assertEqual(sf.get_locks(), (buf,)) + + sf.unlock() + self.assertEqual(sf.get_locked(), True) + self.assertEqual(sf.get_locks(), (buf,)) + + del buf + self.assertEqual(sf.get_locked(), False) + self.assertEqual(sf.get_locks(), ()) + + +if __name__ == "__main__": + unittest.main() diff --git a/venv/Lib/site-packages/pygame/tests/sysfont_test.py b/venv/Lib/site-packages/pygame/tests/sysfont_test.py new file mode 100644 index 0000000..0ae380a --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/sysfont_test.py @@ -0,0 +1,51 @@ +import unittest +import platform + + +class SysfontModuleTest(unittest.TestCase): + def test_create_aliases(self): + import pygame.sysfont + + pygame.sysfont.initsysfonts() + pygame.sysfont.create_aliases() + self.assertTrue(len(pygame.sysfont.Sysalias) > 0) + + def test_initsysfonts(self): + import pygame.sysfont + + pygame.sysfont.initsysfonts() + self.assertTrue(len(pygame.sysfont.get_fonts()) > 0) + + @unittest.skipIf("Darwin" not in platform.platform(), "Not mac we skip.") + def test_initsysfonts_darwin(self): + import pygame.sysfont + + self.assertTrue(len(pygame.sysfont.get_fonts()) > 10) + + def test_sysfont(self): + import pygame.font + + pygame.font.init() + arial = pygame.font.SysFont("Arial", 40) + self.assertTrue(isinstance(arial, pygame.font.Font)) + + @unittest.skipIf( + ("Darwin" in platform.platform() or "Windows" in platform.platform()), + "Not unix we skip.", + ) + def test_initsysfonts_unix(self): + import pygame.sysfont + + self.assertTrue(len(pygame.sysfont.get_fonts()) > 0) + + @unittest.skipIf("Windows" not in platform.platform(), "Not windows we skip.") + def test_initsysfonts_win32(self): + import pygame.sysfont + + self.assertTrue(len(pygame.sysfont.get_fonts()) > 10) + + +############################################################################### + +if __name__ == "__main__": + unittest.main() diff --git a/venv/Lib/site-packages/pygame/tests/test_test_.py b/venv/Lib/site-packages/pygame/tests/test_test_.py new file mode 100644 index 0000000..0880e7e --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/test_test_.py @@ -0,0 +1,2 @@ +while True: + pass diff --git a/venv/Lib/site-packages/pygame/tests/test_utils/__init__.py b/venv/Lib/site-packages/pygame/tests/test_utils/__init__.py new file mode 100644 index 0000000..f8013ca --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/test_utils/__init__.py @@ -0,0 +1,227 @@ +import os +import pygame +import sys +import tempfile +import time + +is_pygame_pkg = __name__.startswith("pygame.tests.") + +############################################################################### + + +def tostring(row): + """Convert row of bytes to string. Expects `row` to be an + ``array``. + """ + return row.tobytes() + + +def geterror(): + return sys.exc_info()[1] + + +class AssertRaisesRegexMixin(object): + """Provides a way to prevent DeprecationWarnings in python >= 3.2. + + For this mixin to override correctly it needs to be before the + unittest.TestCase in the multiple inheritance hierarchy. + e.g. class TestClass(AssertRaisesRegexMixin, unittest.TestCase) + + This class/mixin and its usage can be removed when pygame no longer + supports python < 3.2. + """ + + def assertRaisesRegex(self, *args, **kwargs): + try: + return super(AssertRaisesRegexMixin, self).assertRaisesRegex( + *args, **kwargs + ) + except AttributeError: + try: + return super(AssertRaisesRegexMixin, self).assertRaisesRegexp( + *args, **kwargs + ) + except AttributeError: + self.skipTest("No assertRaisesRegex/assertRaisesRegexp method") + + +############################################################################### + +this_dir = os.path.dirname(os.path.abspath(__file__)) +trunk_dir = os.path.split(os.path.split(this_dir)[0])[0] +if is_pygame_pkg: + test_module = "tests" +else: + test_module = "test" + + +def trunk_relative_path(relative): + return os.path.normpath(os.path.join(trunk_dir, relative)) + + +def fixture_path(path): + return trunk_relative_path(os.path.join(test_module, "fixtures", path)) + + +def example_path(path): + return trunk_relative_path(os.path.join("examples", path)) + + +sys.path.insert(0, trunk_relative_path(".")) + + +################################## TEMP FILES ################################# + + +def get_tmp_dir(): + return tempfile.mkdtemp() + + +############################################################################### + + +def question(q): + return input("\n%s (y/n): " % q.rstrip(" ")).lower().strip() == "y" + + +def prompt(p): + return input("\n%s (press enter to continue): " % p.rstrip(" ")) + + +#################################### HELPERS ################################## + + +def rgba_between(value, minimum=0, maximum=255): + if value < minimum: + return minimum + elif value > maximum: + return maximum + else: + return value + + +def combinations(seqs): + """ + + Recipe 496807 from ActiveState Python CookBook + + Non recursive technique for getting all possible combinations of a sequence + of sequences. + + """ + + r = [[]] + for x in seqs: + r = [i + [y] for y in x for i in r] + return r + + +def gradient(width, height): + """ + + Yields a pt and corresponding RGBA tuple, for every (width, height) combo. + Useful for generating gradients. + + Actual gradient may be changed, no tests rely on specific values. + + Used in transform.rotate lossless tests to generate a fixture. + + """ + + for l in range(width): + for t in range(height): + yield (l, t), tuple(map(rgba_between, (l, t, l, l + t))) + + +def rect_area_pts(rect): + for l in range(rect.left, rect.right): + for t in range(rect.top, rect.bottom): + yield l, t + + +def rect_perimeter_pts(rect): + """ + + Returns pts ((L, T) tuples) encompassing the perimeter of a rect. + + The order is clockwise: + + topleft to topright + topright to bottomright + bottomright to bottomleft + bottomleft to topleft + + Duplicate pts are not returned + + """ + clock_wise_from_top_left = ( + [(l, rect.top) for l in range(rect.left, rect.right)], + [(rect.right - 1, t) for t in range(rect.top + 1, rect.bottom)], + [(l, rect.bottom - 1) for l in range(rect.right - 2, rect.left - 1, -1)], + [(rect.left, t) for t in range(rect.bottom - 2, rect.top, -1)], + ) + + for line in clock_wise_from_top_left: + for pt in line: + yield pt + + +def rect_outer_bounds(rect): + """ + + Returns topleft outerbound if possible and then the other pts, that are + "exclusive" bounds of the rect + + ?------O + |RECT| ?|0)uterbound + |----| + O O + + """ + return ([(rect.left - 1, rect.top)] if rect.left else []) + [ + rect.topright, + rect.bottomleft, + rect.bottomright, + ] + + +def import_submodule(module): + m = __import__(module) + for n in module.split(".")[1:]: + m = getattr(m, n) + return m + + +class SurfaceSubclass(pygame.Surface): + """A subclassed Surface to test inheritance.""" + + def __init__(self, *args, **kwargs): + super(SurfaceSubclass, self).__init__(*args, **kwargs) + self.test_attribute = True + + +def test(): + """ + + Lightweight test for helpers + + """ + + r = pygame.Rect(0, 0, 10, 10) + assert rect_outer_bounds(r) == [(10, 0), (0, 10), (10, 10)] # tr # bl # br + + assert len(list(rect_area_pts(r))) == 100 + + r = pygame.Rect(0, 0, 3, 3) + assert list(rect_perimeter_pts(r)) == [ + (0, 0), + (1, 0), + (2, 0), # tl -> tr + (2, 1), + (2, 2), # tr -> br + (1, 2), + (0, 2), # br -> bl + (0, 1), # bl -> tl + ] + + print("Tests: OK") diff --git a/venv/Lib/site-packages/pygame/tests/test_utils/__pycache__/__init__.cpython-39.pyc b/venv/Lib/site-packages/pygame/tests/test_utils/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c1ac907f671f75be55933023a8d31d6f4769cff8 GIT binary patch literal 6644 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/tests/test_utils/__pycache__/async_sub.cpython-39.pyc b/venv/Lib/site-packages/pygame/tests/test_utils/__pycache__/async_sub.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..21b008516766c2c287885609fbb709a729f78269 GIT binary patch literal 7152 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 Ymf`k$@b)mz>% literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/tests/test_utils/__pycache__/buftools.cpython-39.pyc b/venv/Lib/site-packages/pygame/tests/test_utils/__pycache__/buftools.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f0e2dd5209d164a2b6e27102df7a709b2ce9a047 GIT binary patch literal 17204 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/tests/test_utils/__pycache__/endian.cpython-39.pyc b/venv/Lib/site-packages/pygame/tests/test_utils/__pycache__/endian.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fa0b318d70793519b413635de02e87b66cfcc951 GIT binary patch literal 681 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�eu#TPqB}P=i_h6WC^j3Hp!6g*xlAqc3;%~FgDxqTvEqz=9l5v>|Fz7=zVGdq z_a@`(SMw;=5LV@w;=zpIhDSTCQ?=Z+g9Rt-kX0<|uobb}+fJ{O+-*+snO!$>dtg zl^4%%TmW9CRKxo94fgU#zC54s`fu|~p3V1_6VH}s5&D0(I$fRde|cJ{|4--Xw_iE& zle=HtouAB8aKEzm?3uEEM|IKu*|PtJ>Q4K6W&e%UUG~paZ>sKg-l?yia^9P(xA?A6 z_TO5)&Hnka|Mu!0`xnaoJF0iuzoYEGtNI4}7t8*;t9|=#DEr@7y~qBYW&fM1_u7AB z_083{xX+2No^YS{RrmVtuCjk$^?v(rs=l@QfPUOveOqhSc}b`Q@U z?j4>xJagDMJb!rM@Q%Zahi^E%^YD#_cOAaz@b1GmSHI!+z4<41zPjVO#Qj(He)44X zk*}WgiIDorxo6)}eS7sCuK3of{p{NgPkipg&zxL5mjBDAlZPiB_t={>6>%D`R?+~ zY2W-q-?-lOzml_;|L5GlanPtf_}t0g;=Z3dRo|x?)K@S6yJl(Gxze)phbMn#=lVAs zzU45z*qQHKJ#qNdU&#W;O(AE`GdR9zU|q2o_$C4p^u#Sp|?Ey z&VvhwCl23v_>RMO`gQl@iJ#f|V)x(<*Cga_M9HdA9EU)h~>%_~Kf% z|D}cJRPP@=G25SCebUZT9)4Lp^~}Nj<;*Qo57}D?^;5O;jOatV8_(1Joxa+5OlWz? zyY;y3MUT4E52e&lr>}odm z?HriTgYuly!xML(IP}cZyHC9J#0wf*c_uSD->ql)iet;mb4=fwKKz_dH&0#v;^JU& zyPlNCOg|pd%(y=JiH+vJ=OxE=efTYH&Wgx0oy&8-zh-e%T4=S~mR6!gPc7dV*{`2m z?3jUisLN`(tK4>Zi>U=OTRgJSs&9FvR@JB6(z3{=(y}}c{%gzCadmjNek|8==4$o_8$mGfIeJu@{+`1aq4arl?S0nN|8?*S#Yii8x zN2Rc?JSF_#gopYfo4bjK>f{G)my`7MoyG6<`(kM0nY{bizbBic2QwEMI$smX!Q$%E zvme}O*}Gqoc&?XYZ<(w$)d=M`MwzToOn7RD>4-z1<8#|&^M;K!JpRPv?Z-FT@lCJL zjvW7L+p_q{ZB}*uWt-8RytZa^Uu`ooByZRnlEtx>+_^m%wd@nuJ2 zYg&Hf@mBNNMmt_{T5`fmkH?C|9iDvaa^);uzA(2VF8;-h)_n6T5lK1YrJHla z=-!IE92cFhK)zc|TRf?02d|}R<&0?vcJ<1Bp5|WI-h1sV+1}2I?d8elhwD!d9I?U0 zo*5lm?B~a~+Ol}dc1!A2zq)j*_v}Vf zUV7CZ9e+z(+^wFwj7}91b#l7_$Ar?kG9Nc)i>H2k{tKw)fbF?0x95o4b!b_V8sJKRo)O?0x9b%cmaw za6W(hQ|)ZJmrs5CQ?2IZ-S5rk@6G4$EuSBL^iz(1*yh9EGrWB2!{5{DT|RaB!AC!N zdH0i-9-LO;n!}pH&{k_kgKRo^X?!l>p(}#PG zIPZuv?>KSTcy8zLRMz2hCtonDU;N=Oe)RA(E&I%kD{DjY`qgV!Sc^|TIleaAzxNAI zU3+T!#Nw$h%n3FL^=TD9g_7_imsor_|>W|Kz z+#fF%<1g11XAY_Li)cfOZZ>}|n`dn9JF^Jqs1>1a%ifP<6P0N32W{@Vu$X4Q%I2!g z&9lpxmuP9&nT&Uub zooHfF5D#~rJN4|D%8b|e%Y4_Ie&E@?!@b2j*T?KR=G?&vn9RAuv)Gn1^8et(vuD5f z&cicib!S{2`;cMJYdymmh8iX?iw};cPwY>h7+rc<7SLav#wCv}1fEm8LK6(7~cyUmlwQ$UId~JU++rK_LfIO_PamiBr!2Xw>xazK7 zy87gk4twVMZ2#)P{Z<8Ir>hMai z*;ZsHvZ9sk#9~^y?5^1IrE)!zH_A%D?(Zbk%1Xr z_B*{XzgpGvip!eLSP97w3`6>(eHZ>#E$=xK^OMff-1$joentv2>B-JGInVhZk6!q$ zR4aRRUYbKMk|iJd^Maa0wSbKj!|4xv$`Z_tPt`e)Ec8o^hiD*LSvy4(NAmCy`}a{Va^ z4H)9vh8po<;~L;KNqYGv6ew~SKy=S&0%W$M48oec1^@g)ktof=E+aT;V zV=h@8lGKXtI)cahEPtP3n?j5=2T;op|3b|Y!vs7Fp4-b_)+z;Yp|bk*J6EcLn)0Sk zs=S9nUVVsR(h2n~T&;Crq3T~Q*Gl;^`3!efsj5;$GR(^D_8Bvanzp?0-)&gk!W3p^3AY{N9Hhq36OF=V8oM~x9P6(dj&8Nr@T z*v^5}lYIZiDW0O>!wIg3Pgg@7u&r9E))k)X(xfvt>6}jky7CnVZ~2xiN65BLESGXC z8*KoZblyx8N;`O|a9eb2<Lx{=qN^$EJS;)LHa^SpUKS-in$gJN z6@z>xDUa06*Zeg-_$vB^wK7K;9w`x0w*aj0l%Q5P4xuZo&XsCwIrSnh%~`h+0CSjs zr4p>#HSf-B)z^8p%15~gksfO$sx`k@t$1pNXMWBzUr;=xh;Z>^6mbfRB0-U&7@*ik z!M~!d_EQW~9H1DXI7o4b;xNS#iW3x1QxKqA*2V`pRq%S$t%OUrEMdr%Xk0q3eSAUX zF_@2@&u3OjJ%d}@0X6hZ`Oflf^)6yr z{Ky>ucq6iHJcw+Y4o#s^W%o$P5LqLv&@3tdvmK;VS474TeC6^8me4HX*82qm=Xmg6?avnsspD%4WxmB1s z?H*Oo2KMg6;+Ye$G<4SCee+7o`9iT$p^eV-J&(k z)+*(!p4%<$^kl5rg^QOiE(MQp+W89hYCAQRhgGaA%t)~9bK{9H8#4_pO2=C9cP?MN zcBy4un!P-C=~^p(adwf1S7vU!Ju|;U{h*Fw>8?`!=vx(_dhe%b=@{hvrnwn|g`-VC z6n+9<>gz-eR%pSOQ>9Ti4q8V24vvB+^qu6|chXHeouf%!sg`Tgdrm@}CHnp{i6Lq* zv={Ky=$(kZE~oJwqh;yE+BKIGow>ZoRg?T%xef(r8x~ogNk^~Gq$BI29ZtPQ!P&iA z=(CQDm4gS{(U#lvoBeztue_GIcqZMa{tNffvbhv|=&iVL!Lo!cd-ko@wYB~!SMO z9?Jk0$)jP5*p|uY$^=-^e47$!4V%XidkvyIjJkIGl`G0kn&L>@Ip;g{O;j ze*(ce0%$124L911Hp~Kobb%n-?bDv_9s0A0?f3&kqz#Kln>B=GNr2t1ifKvgxk=$!o<}Thb8{I~@NdO;t0>aUR_NFI4D7yaIy~bY10WTgbYT@d;-+-GMMsOESE-kmfsEBvnMN3DdF;Wn;>`Yvz}({b zD>Crn+!cnM^wYK~XhZ+WB^I8ZWIGvVaS?4j=ee*a-eegF!%9c$b0$FeM-(_!2AR{gt-~Dhz%j@RkTC!DAYB z_PBAjSEq14ftef#PSh*;4?%H|`+)wa97>A!zgn%sazc|rs6URugOi=Mx|ZApj3Y=5 zAI!!YHamDV{Bq@_tlqdMAs+I4v~aS@YKH5`#S%&^-7h!TvXqAD37!>mN2F^dik=L| zf?F&UeGS)Lii{8rI)W?G>gztNf9J8?o@ypqTP~|J9QpzUm$4Q1s~h=>dW99TmgiaO z1?0Z*05G%qu5_yL_ht$z>e()q;-Pq z+G@Prqk+_IGYRNSjtU^V`@q|N7oOtKK^#}W&$;_qYD5vNAB7Kzk$hv_Y}f^Gu-`V8 zBA>{$H~$i6K(zp9hw&C12#&rZTXk~ILf*$CB78p6_8U&>K#s4I)}AU$L(m*`kx%M1 z3Mx~Og07Cc`oAP}O}g++&Fq_7ntAu?g_-%;?9BY)rI}10m@!=p&Mlrvim!o=N$roY zBpwM1p~r#Jwd;%X*WO*6#XFJIK4CJ5PLI30nB0YQOnt;T-lO=0g8UQQil4Jgu+S`S zH~5!0SX>6Vxo@BeV$^!AL@H1HkUhRnA^O>U;rk?hqsw}Snn^w-0{xSSi+UHgqA_FC zK;&guqNQ*w9wJ_fhZ-t+dc;syuzEZELB5uZi9`#3jDqL{FicHrPTn=CW8~Xu1QGq1 zQYIzVE+dX$nN(J%_ua5JHSVtN?OMMM6Wi_O+B=SIH_<-cG18C1k@_&wkHV35_e{2X z%K4<**FNS*Za*|H6?`HV>O!@`y+lq9gh#nd+EW4w&3-sA%yrp5mLs9+a7zLBSHu== zhf~|H*Dv3=GJDp!id+Fm5?JdGV3qO5AKJD`0S@ai1dYYIXkC9B zYp?Z~mPutOZcyNPN7V1(IW2%!`2)TT;>3#oYP8~i}xkr~{wGqO zlzO<*>;3mlmGb+2a0cSY4-lmr3E=r4cmu@vcktZr8=L>*^1Y6)??d}Bf2a|Mn{8f= z`1|nqoABsAp_cY&IMKBLUw ztslfF+y0?O(tQiMlxn254+}v*&>U>;YYzEGup2kri+cy!bl<3)@*hR(#XIKBcyoV~ z?S`8N8pH0_HjL&7zL#!eU$1}Ez3N{3wTS;1*6jKn?6hl+27`^!?XkuI_-O~Zt`^StN_wB|3|MAA?9b+{NlirO~%u|uZLH7-4{2~9i%wz<6TI1_a;73;3 zf3oq&{b=nhj>oyi>rdh5g!>M5wH{{O{V1Ny2urdGM=<*%?u~Hvk2a4sA8U>^#@u%| zqG)*+v&b~Y!XOR1X;)2NbJdiyf94-^-$Pi!^}u-CZM$lPZ4YlxVCOPc>p|3rR8oz@ z+iC7(e!$(dc#i3t!HnSGQeB4&%qHb4D^)Nw+Mx>x%&xQFi<2RA(P$vcn0iad&c&Sa z@@gTl#%rotaDx34&Z{?{Y+PTOKkGD>^0&{X)p6Y+0qFI>_5_dWrtgIpd*69a!UKBa z?+50T3X)S(^kt_&WWU}@dVW>qfoAo5a9|15Ok*LnCY}Twh;+1-z;CAJ>LtHr!I#Aq zTCuf!sfMA7LI2d0WK6(Y=Y#PT49i`_VH$;%GMpwZCT84R`Ai!9{9s^e%2&AxoKc0i zpQHjN(X!~YRtjo?ZpgFcoZ676t3!Z?Ji0US#M08-+ROB7NiPSogHc^~{O;-SQs|cp5>r!}!u}hqbnv*8+a!I@%Qtec)7;mmQPU~Jy zDYunZ=sL&eBV8qp5Xe^6FZGjiyLz6d8cI(l9Rk@0^`(wHwX5Gu=Zf-3zv7DeaqE?8 z&-KktPsxVpRQ`@jb{!PyiTiUqeKfVjEKDZ8aQ^bOtH=iGH%Ar|?;p7cu(0GRq=BYkd2VsMQ~im5TPtI6%w+#JqjYe62jsc%mxJ3MN`b)dqboJY)`v99LH931QTh0|Lz3fA-j6aJrtv=$c(_6^5IhsImCdR$A z#LtMmJ29s5-M6w+xmE0S>Q+Zx0KVZo48z@99>EI`&ZA#;>@W8> z%>T9ecF+D$RPTsN_3V&}A=FNS>>(i}1QBQ+3ltH_o{=c{{fC2nB!ot=MuYf3K1`xd zXVuV?AC3@1x{|E_2v%7q`iI%h9QuMG{E(^mOj>qU@FbfJqM#+x#sYBgRXpePtLic} z=6ybM#BGtx!P*u~cK#%>+7p?r`^A!{xFJHxJ_Y_(iFysgYVJbbpzpFS3(-nsvq-sQ zvzpWRL)QNT#bXqYQ#?f>tX-NVd0$SmbdKUP4*UvBmnhz#khkfNSh6YpgQ5>2)5qN^ zvUyI$SqUc`$#IlgX0fVrJX(fmA(daQ39J*hH3pPfs#ACrO^A$r4Yz$E2PFDc)_qR# zuM|WPjT&ScH3kS82-{Jh8^ zkx7xdmmWu#wd_5sN6<9`J-sHRd|KqN$Y(@;Gs4e5TJ8IM+Wto5y8Tpg(LQMppnQv} I&;2d`5BC5vqyPW_ literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/tests/test_utils/__pycache__/run_tests.cpython-39.pyc b/venv/Lib/site-packages/pygame/tests/test_utils/__pycache__/run_tests.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..613a01349464031d9e370abee28ae18a7c99b130 GIT binary patch literal 8810 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 U0%~u@>{++TI?m>~uG78v6MprVmjD0& literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/tests/test_utils/__pycache__/test_runner.cpython-39.pyc b/venv/Lib/site-packages/pygame/tests/test_utils/__pycache__/test_runner.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c15d72f666c620aa3d7f5a9b36ca442820db6c4a GIT binary patch literal 6962 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 Zz5j9FCu6Y@sBMGF(7DmjY}`Yh{vVeLQ~>}0 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/tests/test_utils/arrinter.py b/venv/Lib/site-packages/pygame/tests/test_utils/arrinter.py new file mode 100644 index 0000000..3883b45 --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/test_utils/arrinter.py @@ -0,0 +1,441 @@ +import sys +import ctypes +from ctypes import * +import unittest + +__all__ = [ + "PAI_CONTIGUOUS", + "PAI_FORTRAN", + "PAI_ALIGNED", + "PAI_NOTSWAPPED", + "PAI_WRITEABLE", + "PAI_ARR_HAS_DESCR", + "ArrayInterface", +] + +try: + c_ssize_t # Undefined in early Python versions +except NameError: + if sizeof(c_uint) == sizeof(c_void_p): + c_size_t = c_uint + c_ssize_t = c_int + elif sizeof(c_ulong) == sizeof(c_void_p): + c_size_t = c_ulong + c_ssize_t = c_long + elif sizeof(c_ulonglong) == sizeof(c_void_p): + c_size_t = c_ulonglong + c_ssize_t = c_longlong + + +SIZEOF_VOID_P = sizeof(c_void_p) +if SIZEOF_VOID_P <= sizeof(c_int): + Py_intptr_t = c_int +elif SIZEOF_VOID_P <= sizeof(c_long): + Py_intptr_t = c_long +elif "c_longlong" in globals() and SIZEOF_VOID_P <= sizeof(c_longlong): + Py_intptr_t = c_longlong +else: + raise RuntimeError("Unrecognized pointer size %i" % (pointer_size,)) + + +class PyArrayInterface(Structure): + _fields_ = [ + ("two", c_int), + ("nd", c_int), + ("typekind", c_char), + ("itemsize", c_int), + ("flags", c_int), + ("shape", POINTER(Py_intptr_t)), + ("strides", POINTER(Py_intptr_t)), + ("data", c_void_p), + ("descr", py_object), + ] + + +PAI_Ptr = POINTER(PyArrayInterface) + +try: + PyCObject_AsVoidPtr = pythonapi.PyCObject_AsVoidPtr +except AttributeError: + + def PyCObject_AsVoidPtr(o): + raise TypeError("Not available") + +else: + PyCObject_AsVoidPtr.restype = c_void_p + PyCObject_AsVoidPtr.argtypes = [py_object] + PyCObject_GetDesc = pythonapi.PyCObject_GetDesc + PyCObject_GetDesc.restype = c_void_p + PyCObject_GetDesc.argtypes = [py_object] + +try: + PyCapsule_IsValid = pythonapi.PyCapsule_IsValid +except AttributeError: + + def PyCapsule_IsValid(capsule, name): + return 0 + +else: + PyCapsule_IsValid.restype = c_int + PyCapsule_IsValid.argtypes = [py_object, c_char_p] + PyCapsule_GetPointer = pythonapi.PyCapsule_GetPointer + PyCapsule_GetPointer.restype = c_void_p + PyCapsule_GetPointer.argtypes = [py_object, c_char_p] + PyCapsule_GetContext = pythonapi.PyCapsule_GetContext + PyCapsule_GetContext.restype = c_void_p + PyCapsule_GetContext.argtypes = [py_object] + +PyCapsule_Destructor = CFUNCTYPE(None, py_object) +PyCapsule_New = pythonapi.PyCapsule_New +PyCapsule_New.restype = py_object +PyCapsule_New.argtypes = [c_void_p, c_char_p, POINTER(PyCapsule_Destructor)] + + +def capsule_new(p): + return PyCapsule_New(addressof(p), None, None) + + +PAI_CONTIGUOUS = 0x01 +PAI_FORTRAN = 0x02 +PAI_ALIGNED = 0x100 +PAI_NOTSWAPPED = 0x200 +PAI_WRITEABLE = 0x400 +PAI_ARR_HAS_DESCR = 0x800 + + +class ArrayInterface(object): + def __init__(self, arr): + try: + self._cobj = arr.__array_struct__ + except AttributeError: + raise TypeError("The array object lacks an array structure") + if not self._cobj: + raise TypeError("The array object has a NULL array structure value") + try: + vp = PyCObject_AsVoidPtr(self._cobj) + except TypeError: + if PyCapsule_IsValid(self._cobj, None): + vp = PyCapsule_GetPointer(self._cobj, None) + else: + raise TypeError("The array object has an invalid array structure") + self.desc = PyCapsule_GetContext(self._cobj) + else: + self.desc = PyCObject_GetDesc(self._cobj) + self._inter = cast(vp, PAI_Ptr)[0] + + def __getattr__(self, name): + if name == "typekind": + return self._inter.typekind.decode("latin-1") + return getattr(self._inter, name) + + def __str__(self): + if isinstance(self.desc, tuple): + ver = self.desc[0] + else: + ver = "N/A" + return ( + "nd: %i\n" + "typekind: %s\n" + "itemsize: %i\n" + "flags: %s\n" + "shape: %s\n" + "strides: %s\n" + "ver: %s\n" + % ( + self.nd, + self.typekind, + self.itemsize, + format_flags(self.flags), + format_shape(self.nd, self.shape), + format_strides(self.nd, self.strides), + ver, + ) + ) + + +def format_flags(flags): + names = [] + for flag, name in [ + (PAI_CONTIGUOUS, "CONTIGUOUS"), + (PAI_FORTRAN, "FORTRAN"), + (PAI_ALIGNED, "ALIGNED"), + (PAI_NOTSWAPPED, "NOTSWAPPED"), + (PAI_WRITEABLE, "WRITEABLE"), + (PAI_ARR_HAS_DESCR, "ARR_HAS_DESCR"), + ]: + if flag & flags: + names.append(name) + return ", ".join(names) + + +def format_shape(nd, shape): + return ", ".join([str(shape[i]) for i in range(nd)]) + + +def format_strides(nd, strides): + return ", ".join([str(strides[i]) for i in range(nd)]) + + +class Exporter(object): + def __init__( + self, shape, typekind=None, itemsize=None, strides=None, descr=None, flags=None + ): + if typekind is None: + typekind = "u" + if itemsize is None: + itemsize = 1 + if flags is None: + flags = PAI_WRITEABLE | PAI_ALIGNED | PAI_NOTSWAPPED + if descr is not None: + flags |= PAI_ARR_HAS_DESCR + if len(typekind) != 1: + raise ValueError("Argument 'typekind' must be length 1 string") + nd = len(shape) + self.typekind = typekind + self.itemsize = itemsize + self.nd = nd + self.shape = tuple(shape) + self._shape = (c_ssize_t * self.nd)(*self.shape) + if strides is None: + self._strides = (c_ssize_t * self.nd)() + self._strides[self.nd - 1] = self.itemsize + for i in range(self.nd - 1, 0, -1): + self._strides[i - 1] = self.shape[i] * self._strides[i] + strides = tuple(self._strides) + self.strides = strides + elif len(strides) == nd: + self.strides = tuple(strides) + self._strides = (c_ssize_t * self.nd)(*self.strides) + else: + raise ValueError("Mismatch in length of strides and shape") + self.descr = descr + if self.is_contiguous("C"): + flags |= PAI_CONTIGUOUS + if self.is_contiguous("F"): + flags |= PAI_FORTRAN + self.flags = flags + sz = max(shape[i] * strides[i] for i in range(nd)) + self._data = (c_ubyte * sz)() + self.data = addressof(self._data) + self._inter = PyArrayInterface( + 2, + nd, + typekind.encode("latin_1"), + itemsize, + flags, + self._shape, + self._strides, + self.data, + descr, + ) + self.len = itemsize + for i in range(nd): + self.len *= self.shape[i] + + __array_struct__ = property(lambda self: capsule_new(self._inter)) + + def is_contiguous(self, fortran): + if fortran in "CA": + if self.strides[-1] == self.itemsize: + for i in range(self.nd - 1, 0, -1): + if self.strides[i - 1] != self.shape[i] * self.strides[i]: + break + else: + return True + if fortran in "FA": + if self.strides[0] == self.itemsize: + for i in range(0, self.nd - 1): + if self.strides[i + 1] != self.shape[i] * self.strides[i]: + break + else: + return True + return False + + +class Array(Exporter): + _ctypes = { + ("u", 1): c_uint8, + ("u", 2): c_uint16, + ("u", 4): c_uint32, + ("u", 8): c_uint64, + ("i", 1): c_int8, + ("i", 2): c_int16, + ("i", 4): c_int32, + ("i", 8): c_int64, + } + + def __init__(self, *args, **kwds): + super(Array, self).__init__(*args, **kwds) + try: + if self.flags & PAI_NOTSWAPPED: + ct = self._ctypes[self.typekind, self.itemsize] + elif c_int.__ctype_le__ is c_int: + ct = self._ctypes[self.typekind, self.itemsize].__ctype_be__ + else: + ct = self._ctypes[self.typekind, self.itemsize].__ctype_le__ + except KeyError: + ct = c_uint8 * self.itemsize + self._ctype = ct + self._ctype_p = POINTER(ct) + + def __getitem__(self, key): + return cast(self._addr_at(key), self._ctype_p)[0] + + def __setitem__(self, key, value): + cast(self._addr_at(key), self._ctype_p)[0] = value + + def _addr_at(self, key): + if not isinstance(key, tuple): + key = (key,) + if len(key) != self.nd: + raise ValueError("wrong number of indexes") + for i in range(self.nd): + if not (0 <= key[i] < self.shape[i]): + raise IndexError("index {} out of range".format(i)) + return self.data + sum(i * s for i, s in zip(key, self.strides)) + + +class ExporterTest(unittest.TestCase): + def test_strides(self): + self.check_args(0, (10,), "u", (2,), 20, 20, 2) + self.check_args(0, (5, 3), "u", (6, 2), 30, 30, 2) + self.check_args(0, (7, 3, 5), "u", (30, 10, 2), 210, 210, 2) + self.check_args(0, (13, 5, 11, 3), "u", (330, 66, 6, 2), 4290, 4290, 2) + self.check_args(3, (7, 3, 5), "i", (2, 14, 42), 210, 210, 2) + self.check_args(3, (7, 3, 5), "x", (2, 16, 48), 210, 240, 2) + self.check_args(3, (13, 5, 11, 3), "%", (440, 88, 8, 2), 4290, 5720, 2) + self.check_args(3, (7, 5), "-", (15, 3), 105, 105, 3) + self.check_args(3, (7, 5), "*", (3, 21), 105, 105, 3) + self.check_args(3, (7, 5), " ", (3, 24), 105, 120, 3) + + def test_is_contiguous(self): + a = Exporter((10,), itemsize=2) + self.assertTrue(a.is_contiguous("C")) + self.assertTrue(a.is_contiguous("F")) + self.assertTrue(a.is_contiguous("A")) + a = Exporter((10, 4), itemsize=2) + self.assertTrue(a.is_contiguous("C")) + self.assertTrue(a.is_contiguous("A")) + self.assertFalse(a.is_contiguous("F")) + a = Exporter((13, 5, 11, 3), itemsize=2, strides=(330, 66, 6, 2)) + self.assertTrue(a.is_contiguous("C")) + self.assertTrue(a.is_contiguous("A")) + self.assertFalse(a.is_contiguous("F")) + a = Exporter((10, 4), itemsize=2, strides=(2, 20)) + self.assertTrue(a.is_contiguous("F")) + self.assertTrue(a.is_contiguous("A")) + self.assertFalse(a.is_contiguous("C")) + a = Exporter((13, 5, 11, 3), itemsize=2, strides=(2, 26, 130, 1430)) + self.assertTrue(a.is_contiguous("F")) + self.assertTrue(a.is_contiguous("A")) + self.assertFalse(a.is_contiguous("C")) + a = Exporter((2, 11, 6, 4), itemsize=2, strides=(576, 48, 8, 2)) + self.assertFalse(a.is_contiguous("A")) + a = Exporter((2, 11, 6, 4), itemsize=2, strides=(2, 4, 48, 288)) + self.assertFalse(a.is_contiguous("A")) + a = Exporter((3, 2, 2), itemsize=2, strides=(16, 8, 4)) + self.assertFalse(a.is_contiguous("A")) + a = Exporter((3, 2, 2), itemsize=2, strides=(4, 12, 24)) + self.assertFalse(a.is_contiguous("A")) + + def check_args( + self, call_flags, shape, typekind, strides, length, bufsize, itemsize, offset=0 + ): + if call_flags & 1: + typekind_arg = typekind + else: + typekind_arg = None + if call_flags & 2: + strides_arg = strides + else: + strides_arg = None + a = Exporter(shape, itemsize=itemsize, strides=strides_arg) + self.assertEqual(sizeof(a._data), bufsize) + self.assertEqual(a.data, ctypes.addressof(a._data) + offset) + m = ArrayInterface(a) + self.assertEqual(m.data, a.data) + self.assertEqual(m.itemsize, itemsize) + self.assertEqual(tuple(m.shape[0 : m.nd]), shape) + self.assertEqual(tuple(m.strides[0 : m.nd]), strides) + + +class ArrayTest(unittest.TestCase): + def __init__(self, *args, **kwds): + unittest.TestCase.__init__(self, *args, **kwds) + self.a = Array((20, 15), "i", 4) + + def setUp(self): + # Every test starts with a zeroed array. + memset(self.a.data, 0, sizeof(self.a._data)) + + def test__addr_at(self): + a = self.a + self.assertEqual(a._addr_at((0, 0)), a.data) + self.assertEqual(a._addr_at((0, 1)), a.data + 4) + self.assertEqual(a._addr_at((1, 0)), a.data + 60) + self.assertEqual(a._addr_at((1, 1)), a.data + 64) + + def test_indices(self): + a = self.a + self.assertEqual(a[0, 0], 0) + self.assertEqual(a[19, 0], 0) + self.assertEqual(a[0, 14], 0) + self.assertEqual(a[19, 14], 0) + self.assertEqual(a[5, 8], 0) + a[0, 0] = 12 + a[5, 8] = 99 + self.assertEqual(a[0, 0], 12) + self.assertEqual(a[5, 8], 99) + self.assertRaises(IndexError, a.__getitem__, (-1, 0)) + self.assertRaises(IndexError, a.__getitem__, (0, -1)) + self.assertRaises(IndexError, a.__getitem__, (20, 0)) + self.assertRaises(IndexError, a.__getitem__, (0, 15)) + self.assertRaises(ValueError, a.__getitem__, 0) + self.assertRaises(ValueError, a.__getitem__, (0, 0, 0)) + a = Array((3,), "i", 4) + a[1] = 333 + self.assertEqual(a[1], 333) + + def test_typekind(self): + a = Array((1,), "i", 4) + self.assertTrue(a._ctype is c_int32) + self.assertTrue(a._ctype_p is POINTER(c_int32)) + a = Array((1,), "u", 4) + self.assertTrue(a._ctype is c_uint32) + self.assertTrue(a._ctype_p is POINTER(c_uint32)) + a = Array((1,), "f", 4) # float types unsupported: size system dependent + ct = a._ctype + self.assertTrue(issubclass(ct, ctypes.Array)) + self.assertEqual(sizeof(ct), 4) + + def test_itemsize(self): + for size in [1, 2, 4, 8]: + a = Array((1,), "i", size) + ct = a._ctype + self.assertTrue(issubclass(ct, ctypes._SimpleCData)) + self.assertEqual(sizeof(ct), size) + + def test_oddball_itemsize(self): + for size in [3, 5, 6, 7, 9]: + a = Array((1,), "i", size) + ct = a._ctype + self.assertTrue(issubclass(ct, ctypes.Array)) + self.assertEqual(sizeof(ct), size) + + def test_byteswapped(self): + a = Array((1,), "u", 4, flags=(PAI_ALIGNED | PAI_WRITEABLE)) + ct = a._ctype + self.assertTrue(ct is not c_uint32) + if sys.byteorder == "little": + self.assertTrue(ct is c_uint32.__ctype_be__) + else: + self.assertTrue(ct is c_uint32.__ctype_le__) + i = 0xA0B0C0D + n = c_uint32(i) + a[0] = i + self.assertEqual(a[0], i) + self.assertEqual(a._data[0:4], cast(addressof(n), POINTER(c_uint8))[3:-1:-1]) + + +if __name__ == "__main__": + unittest.main() diff --git a/venv/Lib/site-packages/pygame/tests/test_utils/async_sub.py b/venv/Lib/site-packages/pygame/tests/test_utils/async_sub.py new file mode 100644 index 0000000..4adc760 --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/test_utils/async_sub.py @@ -0,0 +1,301 @@ +################################################################################ +""" + +Modification of http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/440554 + +""" + +#################################### IMPORTS ################################### + +import os +import platform +import subprocess +import errno +import time +import sys +import unittest +import tempfile + + +def geterror(): + return sys.exc_info()[1] + + +null_byte = "\x00".encode("ascii") + +if platform.system() == "Windows": + + def encode(s): + return s.encode("ascii") + + def decode(b): + return b.decode("ascii") + + try: + import ctypes + from ctypes.wintypes import DWORD + + kernel32 = ctypes.windll.kernel32 + TerminateProcess = ctypes.windll.kernel32.TerminateProcess + + def WriteFile(handle, data, ol=None): + c_written = DWORD() + success = ctypes.windll.kernel32.WriteFile( + handle, + ctypes.create_string_buffer(encode(data)), + len(data), + ctypes.byref(c_written), + ol, + ) + return ctypes.windll.kernel32.GetLastError(), c_written.value + + def ReadFile(handle, desired_bytes, ol=None): + c_read = DWORD() + buffer = ctypes.create_string_buffer(desired_bytes + 1) + success = ctypes.windll.kernel32.ReadFile( + handle, buffer, desired_bytes, ctypes.byref(c_read), ol + ) + buffer[c_read.value] = null_byte + return ctypes.windll.kernel32.GetLastError(), decode(buffer.value) + + def PeekNamedPipe(handle, desired_bytes): + c_avail = DWORD() + c_message = DWORD() + if desired_bytes > 0: + c_read = DWORD() + buffer = ctypes.create_string_buffer(desired_bytes + 1) + success = ctypes.windll.kernel32.PeekNamedPipe( + handle, + buffer, + desired_bytes, + ctypes.byref(c_read), + ctypes.byref(c_avail), + ctypes.byref(c_message), + ) + buffer[c_read.value] = null_byte + return decode(buffer.value), c_avail.value, c_message.value + else: + success = ctypes.windll.kernel32.PeekNamedPipe( + handle, + None, + desired_bytes, + None, + ctypes.byref(c_avail), + ctypes.byref(c_message), + ) + return "", c_avail.value, c_message.value + + except ImportError: + from win32file import ReadFile, WriteFile + from win32pipe import PeekNamedPipe + from win32api import TerminateProcess + import msvcrt + +else: + from signal import SIGINT, SIGTERM, SIGKILL + import select + import fcntl + +################################### CONSTANTS ################################## + +PIPE = subprocess.PIPE + +################################################################################ + + +class Popen(subprocess.Popen): + def recv(self, maxsize=None): + return self._recv("stdout", maxsize) + + def recv_err(self, maxsize=None): + return self._recv("stderr", maxsize) + + def send_recv(self, input="", maxsize=None): + return self.send(input), self.recv(maxsize), self.recv_err(maxsize) + + def read_async(self, wait=0.1, e=1, tr=5, stderr=0): + if tr < 1: + tr = 1 + x = time.time() + wait + y = [] + r = "" + pr = self.recv + if stderr: + pr = self.recv_err + while time.time() < x or r: + r = pr() + if r is None: + if e: + raise Exception("Other end disconnected!") + else: + break + elif r: + y.append(r) + else: + time.sleep(max((x - time.time()) / tr, 0)) + return "".join(y) + + def send_all(self, data): + while len(data): + sent = self.send(data) + if sent is None: + raise Exception("Other end disconnected!") + data = buffer(data, sent) + + def get_conn_maxsize(self, which, maxsize): + if maxsize is None: + maxsize = 1024 + elif maxsize < 1: + maxsize = 1 + return getattr(self, which), maxsize + + def _close(self, which): + getattr(self, which).close() + setattr(self, which, None) + + if platform.system() == "Windows": + + def kill(self): + # Recipes + # http://me.in-berlin.de/doc/python/faq/windows.html#how-do-i-emulate-os-kill-in-windows + # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/347462 + + """kill function for Win32""" + TerminateProcess(int(self._handle), 0) # returns None + + def send(self, input): + if not self.stdin: + return None + + try: + x = msvcrt.get_osfhandle(self.stdin.fileno()) + (errCode, written) = WriteFile(x, input) + except ValueError: + return self._close("stdin") + except (subprocess.pywintypes.error, Exception): + if geterror()[0] in (109, errno.ESHUTDOWN): + return self._close("stdin") + raise + + return written + + def _recv(self, which, maxsize): + conn, maxsize = self.get_conn_maxsize(which, maxsize) + if conn is None: + return None + + try: + x = msvcrt.get_osfhandle(conn.fileno()) + (read, nAvail, nMessage) = PeekNamedPipe(x, 0) + if maxsize < nAvail: + nAvail = maxsize + if nAvail > 0: + (errCode, read) = ReadFile(x, nAvail, None) + except ValueError: + return self._close(which) + except (subprocess.pywintypes.error, Exception): + if geterror()[0] in (109, errno.ESHUTDOWN): + return self._close(which) + raise + + if self.universal_newlines: + # Translate newlines. For Python 3.x assume read is text. + # If bytes then another solution is needed. + read = read.replace("\r\n", "\n").replace("\r", "\n") + return read + + else: + + def kill(self): + for i, sig in enumerate([SIGTERM, SIGKILL] * 2): + if i % 2 == 0: + os.kill(self.pid, sig) + time.sleep((i * (i % 2) / 5.0) + 0.01) + + killed_pid, stat = os.waitpid(self.pid, os.WNOHANG) + if killed_pid != 0: + return + + def send(self, input): + if not self.stdin: + return None + + if not select.select([], [self.stdin], [], 0)[1]: + return 0 + + try: + written = os.write(self.stdin.fileno(), input) + except OSError: + if geterror()[0] == errno.EPIPE: # broken pipe + return self._close("stdin") + raise + + return written + + def _recv(self, which, maxsize): + conn, maxsize = self.get_conn_maxsize(which, maxsize) + if conn is None: + return None + + if not select.select([conn], [], [], 0)[0]: + return "" + + r = conn.read(maxsize) + if not r: + return self._close(which) + + if self.universal_newlines: + r = r.replace("\r\n", "\n").replace("\r", "\n") + return r + + +################################################################################ + + +def proc_in_time_or_kill(cmd, time_out, wd=None, env=None): + proc = Popen( + cmd, + cwd=wd, + env=env, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + universal_newlines=1, + ) + + ret_code = None + response = [] + + t = time.time() + while ret_code is None and ((time.time() - t) < time_out): + ret_code = proc.poll() + response += [proc.read_async(wait=0.1, e=0)] + + if ret_code is None: + ret_code = '"Process timed out (time_out = %s secs) ' % time_out + try: + proc.kill() + ret_code += 'and was successfully terminated"' + except Exception: + ret_code += 'and termination failed (exception: %s)"' % (geterror(),) + + return ret_code, "".join(response) + + +################################################################################ + + +class AsyncTest(unittest.TestCase): + def test_proc_in_time_or_kill(self): + ret_code, response = proc_in_time_or_kill( + [sys.executable, "-c", "while 1: pass"], time_out=1 + ) + + self.assertIn("rocess timed out", ret_code) + self.assertIn("successfully terminated", ret_code) + + +################################################################################ + +if __name__ == "__main__": + unittest.main() diff --git a/venv/Lib/site-packages/pygame/tests/test_utils/buftools.py b/venv/Lib/site-packages/pygame/tests/test_utils/buftools.py new file mode 100644 index 0000000..2d2112a --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/test_utils/buftools.py @@ -0,0 +1,613 @@ +"""Module pygame.tests.test_utils.array + +Export the Exporter and Importer classes. + +Class Exporter has configurable shape and strides. Exporter objects +provide a convient target for unit tests on Pygame objects and functions that +import a new buffer interface. + +Class Importer imports a buffer interface with the given PyBUF_* flags. +It returns NULL Py_buffer fields as None. The shape, strides, and suboffsets +arrays are returned as tuples of ints. All Py_buffer field properties are +read-only. This class is useful in comparing exported buffer interfaces +with the actual request. The simular Python builtin memoryview currently +does not support configurable PyBUF_* flags. + +This module contains its own unit tests. When Pygame is installed, these tests +can be run with the following command line statement: + +python -m pygame.tests.test_utils.array + +""" +import pygame + +if not pygame.HAVE_NEWBUF: + emsg = "This Pygame build does not support the new buffer protocol" + raise ImportError(emsg) +import pygame.newbuffer +from pygame.newbuffer import ( + PyBUF_SIMPLE, + PyBUF_FORMAT, + PyBUF_ND, + PyBUF_WRITABLE, + PyBUF_STRIDES, + PyBUF_C_CONTIGUOUS, + PyBUF_F_CONTIGUOUS, + PyBUF_ANY_CONTIGUOUS, + PyBUF_INDIRECT, + PyBUF_STRIDED, + PyBUF_STRIDED_RO, + PyBUF_RECORDS, + PyBUF_RECORDS_RO, + PyBUF_FULL, + PyBUF_FULL_RO, + PyBUF_CONTIG, + PyBUF_CONTIG_RO, +) + +import unittest +import sys +import ctypes +import operator + +try: + reduce +except NameError: + from functools import reduce + +__all__ = ["Exporter", "Importer"] + +try: + ctypes.c_ssize_t +except AttributeError: + void_p_sz = ctypes.sizeof(ctypes.c_void_p) + if ctypes.sizeof(ctypes.c_short) == void_p_sz: + ctypes.c_ssize_t = ctypes.c_short + elif ctypes.sizeof(ctypes.c_int) == void_p_sz: + ctypes.c_ssize_t = ctypes.c_int + elif ctypes.sizeof(ctypes.c_long) == void_p_sz: + ctypes.c_ssize_t = ctypes.c_long + elif ctypes.sizeof(ctypes.c_longlong) == void_p_sz: + ctypes.c_ssize_t = ctypes.c_longlong + else: + raise RuntimeError("Cannot set c_ssize_t: sizeof(void *) is %i" % void_p_sz) + + +def _prop_get(fn): + return property(fn) + + +class Exporter(pygame.newbuffer.BufferMixin): + """An object that exports a multi-dimension new buffer interface + + The only array operation this type supports is to export a buffer. + """ + + prefixes = { + "@": "", + "=": "=", + "<": "=", + ">": "=", + "!": "=", + "2": "2", + "3": "3", + "4": "4", + "5": "5", + "6": "6", + "7": "7", + "8": "8", + "9": "9", + } + types = { + "c": ctypes.c_char, + "b": ctypes.c_byte, + "B": ctypes.c_ubyte, + "=c": ctypes.c_int8, + "=b": ctypes.c_int8, + "=B": ctypes.c_uint8, + "?": ctypes.c_bool, + "=?": ctypes.c_int8, + "h": ctypes.c_short, + "H": ctypes.c_ushort, + "=h": ctypes.c_int16, + "=H": ctypes.c_uint16, + "i": ctypes.c_int, + "I": ctypes.c_uint, + "=i": ctypes.c_int32, + "=I": ctypes.c_uint32, + "l": ctypes.c_long, + "L": ctypes.c_ulong, + "=l": ctypes.c_int32, + "=L": ctypes.c_uint32, + "q": ctypes.c_longlong, + "Q": ctypes.c_ulonglong, + "=q": ctypes.c_int64, + "=Q": ctypes.c_uint64, + "f": ctypes.c_float, + "d": ctypes.c_double, + "P": ctypes.c_void_p, + "x": ctypes.c_ubyte * 1, + "2x": ctypes.c_ubyte * 2, + "3x": ctypes.c_ubyte * 3, + "4x": ctypes.c_ubyte * 4, + "5x": ctypes.c_ubyte * 5, + "6x": ctypes.c_ubyte * 6, + "7x": ctypes.c_ubyte * 7, + "8x": ctypes.c_ubyte * 8, + "9x": ctypes.c_ubyte * 9, + } + + def __init__(self, shape, format=None, strides=None, readonly=None, itemsize=None): + if format is None: + format = "B" + if readonly is None: + readonly = False + prefix = "" + typecode = "" + i = 0 + if i < len(format): + try: + prefix = self.prefixes[format[i]] + i += 1 + except LookupError: + pass + if i < len(format) and format[i] == "1": + i += 1 + if i == len(format) - 1: + typecode = format[i] + if itemsize is None: + try: + itemsize = ctypes.sizeof(self.types[prefix + typecode]) + except KeyError: + raise ValueError("Unknown item format '" + format + "'") + self.readonly = bool(readonly) + self.format = format + self._format = ctypes.create_string_buffer(format.encode("latin_1")) + self.ndim = len(shape) + self.itemsize = itemsize + self.len = reduce(operator.mul, shape, 1) * self.itemsize + self.shape = tuple(shape) + self._shape = (ctypes.c_ssize_t * self.ndim)(*self.shape) + if strides is None: + self._strides = (ctypes.c_ssize_t * self.ndim)() + self._strides[self.ndim - 1] = itemsize + for i in range(self.ndim - 1, 0, -1): + self._strides[i - 1] = self.shape[i] * self._strides[i] + self.strides = tuple(self._strides) + elif len(strides) == self.ndim: + self.strides = tuple(strides) + self._strides = (ctypes.c_ssize_t * self.ndim)(*self.strides) + else: + raise ValueError("Mismatch in length of strides and shape") + buflen = max(d * abs(s) for d, s in zip(self.shape, self.strides)) + self.buflen = buflen + self._buf = (ctypes.c_ubyte * buflen)() + offset = sum( + (d - 1) * abs(s) for d, s in zip(self.shape, self.strides) if s < 0 + ) + self.buf = ctypes.addressof(self._buf) + offset + + def buffer_info(self): + return (addressof(self.buffer), self.shape[0]) + + def tobytes(self): + return cast(self.buffer, POINTER(c_char))[0 : self._len] + + def __len__(self): + return self.shape[0] + + def _get_buffer(self, view, flags): + from ctypes import addressof + + if (flags & PyBUF_WRITABLE) == PyBUF_WRITABLE and self.readonly: + raise BufferError("buffer is read-only") + if ( + flags & PyBUF_C_CONTIGUOUS + ) == PyBUF_C_CONTIGUOUS and not self.is_contiguous("C"): + raise BufferError("data is not C contiguous") + if ( + flags & PyBUF_F_CONTIGUOUS + ) == PyBUF_F_CONTIGUOUS and not self.is_contiguous("F"): + raise BufferError("data is not F contiguous") + if ( + flags & PyBUF_ANY_CONTIGUOUS + ) == PyBUF_ANY_CONTIGUOUS and not self.is_contiguous("A"): + raise BufferError("data is not contiguous") + view.buf = self.buf + view.readonly = self.readonly + view.len = self.len + if flags | PyBUF_WRITABLE == PyBUF_WRITABLE: + view.ndim = 0 + else: + view.ndim = self.ndim + view.itemsize = self.itemsize + if (flags & PyBUF_FORMAT) == PyBUF_FORMAT: + view.format = addressof(self._format) + else: + view.format = None + if (flags & PyBUF_ND) == PyBUF_ND: + view.shape = addressof(self._shape) + elif self.is_contiguous("C"): + view.shape = None + else: + raise BufferError( + "shape required for {} dimensional data".format(self.ndim) + ) + if (flags & PyBUF_STRIDES) == PyBUF_STRIDES: + view.strides = ctypes.addressof(self._strides) + elif view.shape is None or self.is_contiguous("C"): + view.strides = None + else: + raise BufferError("strides required for none C contiguous data") + view.suboffsets = None + view.internal = None + view.obj = self + + def is_contiguous(self, fortran): + if fortran in "CA": + if self.strides[-1] == self.itemsize: + for i in range(self.ndim - 1, 0, -1): + if self.strides[i - 1] != self.shape[i] * self.strides[i]: + break + else: + return True + if fortran in "FA": + if self.strides[0] == self.itemsize: + for i in range(0, self.ndim - 1): + if self.strides[i + 1] != self.shape[i] * self.strides[i]: + break + else: + return True + return False + + +class Importer(object): + """An object that imports a new buffer interface + + The fields of the Py_buffer C struct are exposed by identically + named Importer read-only properties. + """ + + def __init__(self, obj, flags): + self._view = pygame.newbuffer.Py_buffer() + self._view.get_buffer(obj, flags) + + @property + def obj(self): + """return object or None for NULL field""" + return self._view.obj + + @property + def buf(self): + """return int or None for NULL field""" + return self._view.buf + + @property + def len(self): + """return int""" + return self._view.len + + @property + def readonly(self): + """return bool""" + return self._view.readonly + + @property + def format(self): + """return bytes or None for NULL field""" + format_addr = self._view.format + if format_addr is None: + return None + return ctypes.cast(format_addr, ctypes.c_char_p).value.decode("ascii") + + @property + def itemsize(self): + """return int""" + return self._view.itemsize + + @property + def ndim(self): + """return int""" + return self._view.ndim + + @property + def shape(self): + """return int tuple or None for NULL field""" + return self._to_ssize_tuple(self._view.shape) + + @property + def strides(self): + """return int tuple or None for NULL field""" + return self._to_ssize_tuple(self._view.strides) + + @property + def suboffsets(self): + """return int tuple or None for NULL field""" + return self._to_ssize_tuple(self._view.suboffsets) + + @property + def internal(self): + """return int or None for NULL field""" + return self._view.internal + + def _to_ssize_tuple(self, addr): + from ctypes import cast, POINTER, c_ssize_t + + if addr is None: + return None + return tuple(cast(addr, POINTER(c_ssize_t))[0 : self._view.ndim]) + + +class ExporterTest(unittest.TestCase): + """Class Exporter unit tests""" + + def test_formats(self): + char_sz = ctypes.sizeof(ctypes.c_char) + short_sz = ctypes.sizeof(ctypes.c_short) + int_sz = ctypes.sizeof(ctypes.c_int) + long_sz = ctypes.sizeof(ctypes.c_long) + longlong_sz = ctypes.sizeof(ctypes.c_longlong) + float_sz = ctypes.sizeof(ctypes.c_float) + double_sz = ctypes.sizeof(ctypes.c_double) + voidp_sz = ctypes.sizeof(ctypes.c_void_p) + bool_sz = ctypes.sizeof(ctypes.c_bool) + + self.check_args(0, (1,), "B", (1,), 1, 1, 1) + self.check_args(1, (1,), "b", (1,), 1, 1, 1) + self.check_args(1, (1,), "B", (1,), 1, 1, 1) + self.check_args(1, (1,), "c", (char_sz,), char_sz, char_sz, char_sz) + self.check_args(1, (1,), "h", (short_sz,), short_sz, short_sz, short_sz) + self.check_args(1, (1,), "H", (short_sz,), short_sz, short_sz, short_sz) + self.check_args(1, (1,), "i", (int_sz,), int_sz, int_sz, int_sz) + self.check_args(1, (1,), "I", (int_sz,), int_sz, int_sz, int_sz) + self.check_args(1, (1,), "l", (long_sz,), long_sz, long_sz, long_sz) + self.check_args(1, (1,), "L", (long_sz,), long_sz, long_sz, long_sz) + self.check_args( + 1, (1,), "q", (longlong_sz,), longlong_sz, longlong_sz, longlong_sz + ) + self.check_args( + 1, (1,), "Q", (longlong_sz,), longlong_sz, longlong_sz, longlong_sz + ) + self.check_args(1, (1,), "f", (float_sz,), float_sz, float_sz, float_sz) + self.check_args(1, (1,), "d", (double_sz,), double_sz, double_sz, double_sz) + self.check_args(1, (1,), "x", (1,), 1, 1, 1) + self.check_args(1, (1,), "P", (voidp_sz,), voidp_sz, voidp_sz, voidp_sz) + self.check_args(1, (1,), "?", (bool_sz,), bool_sz, bool_sz, bool_sz) + self.check_args(1, (1,), "@b", (1,), 1, 1, 1) + self.check_args(1, (1,), "@B", (1,), 1, 1, 1) + self.check_args(1, (1,), "@c", (char_sz,), char_sz, char_sz, char_sz) + self.check_args(1, (1,), "@h", (short_sz,), short_sz, short_sz, short_sz) + self.check_args(1, (1,), "@H", (short_sz,), short_sz, short_sz, short_sz) + self.check_args(1, (1,), "@i", (int_sz,), int_sz, int_sz, int_sz) + self.check_args(1, (1,), "@I", (int_sz,), int_sz, int_sz, int_sz) + self.check_args(1, (1,), "@l", (long_sz,), long_sz, long_sz, long_sz) + self.check_args(1, (1,), "@L", (long_sz,), long_sz, long_sz, long_sz) + self.check_args( + 1, (1,), "@q", (longlong_sz,), longlong_sz, longlong_sz, longlong_sz + ) + self.check_args( + 1, (1,), "@Q", (longlong_sz,), longlong_sz, longlong_sz, longlong_sz + ) + self.check_args(1, (1,), "@f", (float_sz,), float_sz, float_sz, float_sz) + self.check_args(1, (1,), "@d", (double_sz,), double_sz, double_sz, double_sz) + self.check_args(1, (1,), "@?", (bool_sz,), bool_sz, bool_sz, bool_sz) + self.check_args(1, (1,), "=b", (1,), 1, 1, 1) + self.check_args(1, (1,), "=B", (1,), 1, 1, 1) + self.check_args(1, (1,), "=c", (1,), 1, 1, 1) + self.check_args(1, (1,), "=h", (2,), 2, 2, 2) + self.check_args(1, (1,), "=H", (2,), 2, 2, 2) + self.check_args(1, (1,), "=i", (4,), 4, 4, 4) + self.check_args(1, (1,), "=I", (4,), 4, 4, 4) + self.check_args(1, (1,), "=l", (4,), 4, 4, 4) + self.check_args(1, (1,), "=L", (4,), 4, 4, 4) + self.check_args(1, (1,), "=q", (8,), 8, 8, 8) + self.check_args(1, (1,), "=Q", (8,), 8, 8, 8) + self.check_args(1, (1,), "=?", (1,), 1, 1, 1) + self.check_args(1, (1,), "h", (2,), 2, 2, 2) + self.check_args(1, (1,), "!h", (2,), 2, 2, 2) + self.check_args(1, (1,), "q", (8,), 8, 8, 8) + self.check_args(1, (1,), "!q", (8,), 8, 8, 8) + self.check_args(1, (1,), "1x", (1,), 1, 1, 1) + self.check_args(1, (1,), "2x", (2,), 2, 2, 2) + self.check_args(1, (1,), "3x", (3,), 3, 3, 3) + self.check_args(1, (1,), "4x", (4,), 4, 4, 4) + self.check_args(1, (1,), "5x", (5,), 5, 5, 5) + self.check_args(1, (1,), "6x", (6,), 6, 6, 6) + self.check_args(1, (1,), "7x", (7,), 7, 7, 7) + self.check_args(1, (1,), "8x", (8,), 8, 8, 8) + self.check_args(1, (1,), "9x", (9,), 9, 9, 9) + self.check_args(1, (1,), "1h", (2,), 2, 2, 2) + self.check_args(1, (1,), "=1h", (2,), 2, 2, 2) + self.assertRaises(ValueError, Exporter, (2, 1), "") + self.assertRaises(ValueError, Exporter, (2, 1), "W") + self.assertRaises(ValueError, Exporter, (2, 1), "^Q") + self.assertRaises(ValueError, Exporter, (2, 1), "=W") + self.assertRaises(ValueError, Exporter, (2, 1), "=f") + self.assertRaises(ValueError, Exporter, (2, 1), "=d") + self.assertRaises(ValueError, Exporter, (2, 1), "f") + self.assertRaises(ValueError, Exporter, (2, 1), ">d") + self.assertRaises(ValueError, Exporter, (2, 1), "!f") + self.assertRaises(ValueError, Exporter, (2, 1), "!d") + self.assertRaises(ValueError, Exporter, (2, 1), "0x") + self.assertRaises(ValueError, Exporter, (2, 1), "11x") + self.assertRaises(ValueError, Exporter, (2, 1), "BB") + + def test_strides(self): + self.check_args(1, (10,), "=h", (2,), 20, 20, 2) + self.check_args(1, (5, 3), "=h", (6, 2), 30, 30, 2) + self.check_args(1, (7, 3, 5), "=h", (30, 10, 2), 210, 210, 2) + self.check_args(1, (13, 5, 11, 3), "=h", (330, 66, 6, 2), 4290, 4290, 2) + self.check_args(3, (7, 3, 5), "=h", (2, 14, 42), 210, 210, 2) + self.check_args(3, (7, 3, 5), "=h", (2, 16, 48), 210, 240, 2) + self.check_args(3, (13, 5, 11, 3), "=h", (440, 88, 8, 2), 4290, 5720, 2) + self.check_args(3, (7, 5), "3x", (15, 3), 105, 105, 3) + self.check_args(3, (7, 5), "3x", (3, 21), 105, 105, 3) + self.check_args(3, (7, 5), "3x", (3, 24), 105, 120, 3) + + def test_readonly(self): + a = Exporter((2,), "h", readonly=True) + self.assertTrue(a.readonly) + b = Importer(a, PyBUF_STRIDED_RO) + self.assertRaises(BufferError, Importer, a, PyBUF_STRIDED) + b = Importer(a, PyBUF_STRIDED_RO) + + def test_is_contiguous(self): + a = Exporter((10,), "=h") + self.assertTrue(a.is_contiguous("C")) + self.assertTrue(a.is_contiguous("F")) + self.assertTrue(a.is_contiguous("A")) + a = Exporter((10, 4), "=h") + self.assertTrue(a.is_contiguous("C")) + self.assertTrue(a.is_contiguous("A")) + self.assertFalse(a.is_contiguous("F")) + a = Exporter((13, 5, 11, 3), "=h", (330, 66, 6, 2)) + self.assertTrue(a.is_contiguous("C")) + self.assertTrue(a.is_contiguous("A")) + self.assertFalse(a.is_contiguous("F")) + a = Exporter((10, 4), "=h", (2, 20)) + self.assertTrue(a.is_contiguous("F")) + self.assertTrue(a.is_contiguous("A")) + self.assertFalse(a.is_contiguous("C")) + a = Exporter((13, 5, 11, 3), "=h", (2, 26, 130, 1430)) + self.assertTrue(a.is_contiguous("F")) + self.assertTrue(a.is_contiguous("A")) + self.assertFalse(a.is_contiguous("C")) + a = Exporter((2, 11, 6, 4), "=h", (576, 48, 8, 2)) + self.assertFalse(a.is_contiguous("A")) + a = Exporter((2, 11, 6, 4), "=h", (2, 4, 48, 288)) + self.assertFalse(a.is_contiguous("A")) + a = Exporter((3, 2, 2), "=h", (16, 8, 4)) + self.assertFalse(a.is_contiguous("A")) + a = Exporter((3, 2, 2), "=h", (4, 12, 24)) + self.assertFalse(a.is_contiguous("A")) + + def test_PyBUF_flags(self): + a = Exporter((10, 2), "d") + b = Importer(a, PyBUF_SIMPLE) + self.assertTrue(b.obj is a) + self.assertTrue(b.format is None) + self.assertEqual(b.len, a.len) + self.assertEqual(b.itemsize, a.itemsize) + self.assertTrue(b.shape is None) + self.assertTrue(b.strides is None) + self.assertTrue(b.suboffsets is None) + self.assertTrue(b.internal is None) + self.assertFalse(b.readonly) + b = Importer(a, PyBUF_WRITABLE) + self.assertTrue(b.obj is a) + self.assertTrue(b.format is None) + self.assertEqual(b.len, a.len) + self.assertEqual(b.itemsize, a.itemsize) + self.assertTrue(b.shape is None) + self.assertTrue(b.strides is None) + self.assertTrue(b.suboffsets is None) + self.assertTrue(b.internal is None) + self.assertFalse(b.readonly) + b = Importer(a, PyBUF_ND) + self.assertTrue(b.obj is a) + self.assertTrue(b.format is None) + self.assertEqual(b.len, a.len) + self.assertEqual(b.itemsize, a.itemsize) + self.assertEqual(b.shape, a.shape) + self.assertTrue(b.strides is None) + self.assertTrue(b.suboffsets is None) + self.assertTrue(b.internal is None) + self.assertFalse(b.readonly) + a = Exporter((5, 10), "=h", (24, 2)) + b = Importer(a, PyBUF_STRIDES) + self.assertTrue(b.obj is a) + self.assertTrue(b.format is None) + self.assertEqual(b.len, a.len) + self.assertEqual(b.itemsize, a.itemsize) + self.assertEqual(b.shape, a.shape) + self.assertEqual(b.strides, a.strides) + self.assertTrue(b.suboffsets is None) + self.assertTrue(b.internal is None) + self.assertFalse(b.readonly) + b = Importer(a, PyBUF_FULL) + self.assertTrue(b.obj is a) + self.assertEqual(b.format, "=h") + self.assertEqual(b.len, a.len) + self.assertEqual(b.itemsize, a.itemsize) + self.assertEqual(b.shape, a.shape) + self.assertEqual(b.strides, a.strides) + self.assertTrue(b.suboffsets is None) + self.assertTrue(b.internal is None) + self.assertFalse(b.readonly) + self.assertRaises(BufferError, Importer, a, PyBUF_SIMPLE) + self.assertRaises(BufferError, Importer, a, PyBUF_WRITABLE) + self.assertRaises(BufferError, Importer, a, PyBUF_ND) + self.assertRaises(BufferError, Importer, a, PyBUF_C_CONTIGUOUS) + self.assertRaises(BufferError, Importer, a, PyBUF_F_CONTIGUOUS) + self.assertRaises(BufferError, Importer, a, PyBUF_ANY_CONTIGUOUS) + self.assertRaises(BufferError, Importer, a, PyBUF_CONTIG) + + def test_negative_strides(self): + self.check_args(3, (3, 5, 4), "B", (20, 4, -1), 60, 60, 1, 3) + self.check_args(3, (3, 5, 3), "B", (20, 4, -1), 45, 60, 1, 2) + self.check_args(3, (3, 5, 4), "B", (20, -4, 1), 60, 60, 1, 16) + self.check_args(3, (3, 5, 4), "B", (-20, -4, -1), 60, 60, 1, 59) + self.check_args(3, (3, 5, 3), "B", (-20, -4, -1), 45, 60, 1, 58) + + def test_attributes(self): + a = Exporter((13, 5, 11, 3), "=h", (440, 88, 8, 2)) + self.assertEqual(a.ndim, 4) + self.assertEqual(a.itemsize, 2) + self.assertFalse(a.readonly) + self.assertEqual(a.shape, (13, 5, 11, 3)) + self.assertEqual(a.format, "=h") + self.assertEqual(a.strides, (440, 88, 8, 2)) + self.assertEqual(a.len, 4290) + self.assertEqual(a.buflen, 5720) + self.assertEqual(a.buf, ctypes.addressof(a._buf)) + a = Exporter((8,)) + self.assertEqual(a.ndim, 1) + self.assertEqual(a.itemsize, 1) + self.assertFalse(a.readonly) + self.assertEqual(a.shape, (8,)) + self.assertEqual(a.format, "B") + self.assertTrue(isinstance(a.strides, tuple)) + self.assertEqual(a.strides, (1,)) + self.assertEqual(a.len, 8) + self.assertEqual(a.buflen, 8) + a = Exporter([13, 5, 11, 3], "=h", [440, 88, 8, 2]) + self.assertTrue(isinstance(a.shape, tuple)) + self.assertTrue(isinstance(a.strides, tuple)) + self.assertEqual(a.shape, (13, 5, 11, 3)) + self.assertEqual(a.strides, (440, 88, 8, 2)) + + def test_itemsize(self): + exp = Exporter((4, 5), format="B", itemsize=8) + imp = Importer(exp, PyBUF_RECORDS) + self.assertEqual(imp.itemsize, 8) + self.assertEqual(imp.format, "B") + self.assertEqual(imp.strides, (40, 8)) + exp = Exporter((4, 5), format="weird", itemsize=5) + imp = Importer(exp, PyBUF_RECORDS) + self.assertEqual(imp.itemsize, 5) + self.assertEqual(imp.format, "weird") + self.assertEqual(imp.strides, (25, 5)) + + def check_args( + self, call_flags, shape, format, strides, length, bufsize, itemsize, offset=0 + ): + format_arg = format if call_flags & 1 else None + strides_arg = strides if call_flags & 2 else None + a = Exporter(shape, format_arg, strides_arg) + self.assertEqual(a.buflen, bufsize) + self.assertEqual(a.buf, ctypes.addressof(a._buf) + offset) + m = Importer(a, PyBUF_RECORDS_RO) + self.assertEqual(m.buf, a.buf) + self.assertEqual(m.len, length) + self.assertEqual(m.format, format) + self.assertEqual(m.itemsize, itemsize) + self.assertEqual(m.shape, shape) + self.assertEqual(m.strides, strides) + + +if __name__ == "__main__": + unittest.main() diff --git a/venv/Lib/site-packages/pygame/tests/test_utils/endian.py b/venv/Lib/site-packages/pygame/tests/test_utils/endian.py new file mode 100644 index 0000000..64ba1b3 --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/test_utils/endian.py @@ -0,0 +1,20 @@ +# Module pygame.tests.test_utils.endian +# +# Machine independent conversion to little-endian and big-endian Python +# integer values. + +import struct + + +def little_endian_uint32(i): + """Return the 32 bit unsigned integer little-endian representation of i""" + + s = struct.pack("I", i) + return struct.unpack("=I", s)[0] diff --git a/venv/Lib/site-packages/pygame/tests/test_utils/png.py b/venv/Lib/site-packages/pygame/tests/test_utils/png.py new file mode 100644 index 0000000..74df9fd --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/test_utils/png.py @@ -0,0 +1,4001 @@ +#!/usr/bin/env python + +# $URL: http://pypng.googlecode.com/svn/trunk/code/png.py $ +# $Rev: 228 $ + +# png.py - PNG encoder/decoder in pure Python +# +# Modified for Pygame in Oct., 2012 to work with Python 3.x. +# +# Copyright (C) 2006 Johann C. Rocholl +# Portions Copyright (C) 2009 David Jones +# And probably portions Copyright (C) 2006 Nicko van Someren +# +# Original concept by Johann C. Rocholl. +# +# LICENSE (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. +# +# Changelog (recent first): +# 2009-03-11 David: interlaced bit depth < 8 (writing). +# 2009-03-10 David: interlaced bit depth < 8 (reading). +# 2009-03-04 David: Flat and Boxed pixel formats. +# 2009-02-26 David: Palette support (writing). +# 2009-02-23 David: Bit-depths < 8; better PNM support. +# 2006-06-17 Nicko: Reworked into a class, faster interlacing. +# 2006-06-17 Johann: Very simple prototype PNG decoder. +# 2006-06-17 Nicko: Test suite with various image generators. +# 2006-06-17 Nicko: Alpha-channel, grey-scale, 16-bit/plane support. +# 2006-06-15 Johann: Scanline iterator interface for large input files. +# 2006-06-09 Johann: Very simple prototype PNG encoder. + +# Incorporated into Bangai-O Development Tools by drj on 2009-02-11 from +# http://trac.browsershots.org/browser/trunk/pypng/lib/png.py?rev=2885 + +# Incorporated into pypng by drj on 2009-03-12 from +# //depot/prj/bangaio/master/code/png.py#67 + + +""" +Pure Python PNG Reader/Writer + +This Python module implements support for PNG images (see PNG +specification at http://www.w3.org/TR/2003/REC-PNG-20031110/ ). It reads +and writes PNG files with all allowable bit depths (1/2/4/8/16/24/32/48/64 +bits per pixel) and colour combinations: greyscale (1/2/4/8/16 bit); RGB, +RGBA, LA (greyscale with alpha) with 8/16 bits per channel; colour mapped +images (1/2/4/8 bit). Adam7 interlacing is supported for reading and +writing. A number of optional chunks can be specified (when writing) +and understood (when reading): ``tRNS``, ``bKGD``, ``gAMA``. + +For help, type ``import png; help(png)`` in your python interpreter. + +A good place to start is the :class:`Reader` and :class:`Writer` classes. + +This file can also be used as a command-line utility to convert +`Netpbm `_ PNM files to PNG, and the reverse conversion from PNG to +PNM. The interface is similar to that of the ``pnmtopng`` program from +Netpbm. Type ``python png.py --help`` at the shell prompt +for usage and a list of options. + +A note on spelling and terminology +---------------------------------- + +Generally British English spelling is used in the documentation. So +that's "greyscale" and "colour". This not only matches the author's +native language, it's also used by the PNG specification. + +The major colour models supported by PNG (and hence by PyPNG) are: +greyscale, RGB, greyscale--alpha, RGB--alpha. These are sometimes +referred to using the abbreviations: L, RGB, LA, RGBA. In this case +each letter abbreviates a single channel: *L* is for Luminance or Luma or +Lightness which is the channel used in greyscale images; *R*, *G*, *B* stand +for Red, Green, Blue, the components of a colour image; *A* stands for +Alpha, the opacity channel (used for transparency effects, but higher +values are more opaque, so it makes sense to call it opacity). + +A note on formats +----------------- + +When getting pixel data out of this module (reading) and presenting +data to this module (writing) there are a number of ways the data could +be represented as a Python value. Generally this module uses one of +three formats called "flat row flat pixel", "boxed row flat pixel", and +"boxed row boxed pixel". Basically the concern is whether each pixel +and each row comes in its own little tuple (box), or not. + +Consider an image that is 3 pixels wide by 2 pixels high, and each pixel +has RGB components: + +Boxed row flat pixel:: + + list([R,G,B, R,G,B, R,G,B], + [R,G,B, R,G,B, R,G,B]) + +Each row appears as its own list, but the pixels are flattened so that +three values for one pixel simply follow the three values for the previous +pixel. This is the most common format used, because it provides a good +compromise between space and convenience. PyPNG regards itself as +at liberty to replace any sequence type with any sufficiently compatible +other sequence type; in practice each row is an array (from the array +module), and the outer list is sometimes an iterator rather than an +explicit list (so that streaming is possible). + +Flat row flat pixel:: + + [R,G,B, R,G,B, R,G,B, + R,G,B, R,G,B, R,G,B] + +The entire image is one single giant sequence of colour values. +Generally an array will be used (to save space), not a list. + +Boxed row boxed pixel:: + + list([ (R,G,B), (R,G,B), (R,G,B) ], + [ (R,G,B), (R,G,B), (R,G,B) ]) + +Each row appears in its own list, but each pixel also appears in its own +tuple. A serious memory burn in Python. + +In all cases the top row comes first, and for each row the pixels are +ordered from left-to-right. Within a pixel the values appear in the +order, R-G-B-A (or L-A for greyscale--alpha). + +There is a fourth format, mentioned because it is used internally, +is close to what lies inside a PNG file itself, and has some support +from the public API. This format is called packed. When packed, +each row is a sequence of bytes (integers from 0 to 255), just as +it is before PNG scanline filtering is applied. When the bit depth +is 8 this is essentially the same as boxed row flat pixel; when the +bit depth is less than 8, several pixels are packed into each byte; +when the bit depth is 16 (the only value more than 8 that is supported +by the PNG image format) each pixel value is decomposed into 2 bytes +(and `packed` is a misnomer). This format is used by the +:meth:`Writer.write_packed` method. It isn't usually a convenient +format, but may be just right if the source data for the PNG image +comes from something that uses a similar format (for example, 1-bit +BMPs, or another PNG file). + +And now, my famous members +-------------------------- +""" + +__version__ = "$URL: http://pypng.googlecode.com/svn/trunk/code/png.py $ $Rev: 228 $" + +from array import array +from pygame.tests.test_utils import tostring +import itertools +import math +import operator +import struct +import sys +import zlib +import warnings + +__all__ = ["Image", "Reader", "Writer", "write_chunks", "from_array"] + + +# The PNG signature. +# http://www.w3.org/TR/PNG/#5PNG-file-signature +_signature = struct.pack("8B", 137, 80, 78, 71, 13, 10, 26, 10) + +_adam7 = ( + (0, 0, 8, 8), + (4, 0, 8, 8), + (0, 4, 4, 8), + (2, 0, 4, 4), + (0, 2, 2, 4), + (1, 0, 2, 2), + (0, 1, 1, 2), +) + + +def group(s, n): + # See + # http://www.python.org/doc/2.6/library/functions.html#zip + return zip(*[iter(s)] * n) + + +def isarray(x): + """Same as ``isinstance(x, array)``.""" + return isinstance(x, array) + + +# Conditionally convert to bytes. Works on Python 2 and Python 3. +try: + bytes("", "ascii") + + def strtobytes(x): + return bytes(x, "iso8859-1") + + def bytestostr(x): + return str(x, "iso8859-1") + +except: + strtobytes = str + bytestostr = str + + +def interleave_planes(ipixels, apixels, ipsize, apsize): + """ + Interleave (colour) planes, e.g. RGB + A = RGBA. + + Return an array of pixels consisting of the `ipsize` elements of data + from each pixel in `ipixels` followed by the `apsize` elements of data + from each pixel in `apixels`. Conventionally `ipixels` and + `apixels` are byte arrays so the sizes are bytes, but it actually + works with any arrays of the same type. The returned array is the + same type as the input arrays which should be the same type as each other. + """ + + itotal = len(ipixels) + atotal = len(apixels) + newtotal = itotal + atotal + newpsize = ipsize + apsize + # Set up the output buffer + # See http://www.python.org/doc/2.4.4/lib/module-array.html#l2h-1356 + out = array(ipixels.typecode) + # It's annoying that there is no cheap way to set the array size :-( + out.extend(ipixels) + out.extend(apixels) + # Interleave in the pixel data + for i in range(ipsize): + out[i:newtotal:newpsize] = ipixels[i:itotal:ipsize] + for i in range(apsize): + out[i + ipsize : newtotal : newpsize] = apixels[i:atotal:apsize] + return out + + +def check_palette(palette): + """Check a palette argument (to the :class:`Writer` class) for validity. + Returns the palette as a list if okay; raises an exception otherwise. + """ + + # None is the default and is allowed. + if palette is None: + return None + + p = list(palette) + if not (0 < len(p) <= 256): + raise ValueError("a palette must have between 1 and 256 entries") + seen_triple = False + for i, t in enumerate(p): + if len(t) not in (3, 4): + raise ValueError("palette entry %d: entries must be 3- or 4-tuples." % i) + if len(t) == 3: + seen_triple = True + if seen_triple and len(t) == 4: + raise ValueError( + "palette entry %d: all 4-tuples must precede all 3-tuples" % i + ) + for x in t: + if int(x) != x or not (0 <= x <= 255): + raise ValueError( + "palette entry %d: values must be integer: 0 <= x <= 255" % i + ) + return p + + +class Error(Exception): + prefix = "Error" + + def __str__(self): + return self.prefix + ": " + " ".join(self.args) + + +class FormatError(Error): + """Problem with input file format. In other words, PNG file does + not conform to the specification in some way and is invalid. + """ + + prefix = "FormatError" + + +class ChunkError(FormatError): + prefix = "ChunkError" + + +class Writer: + """ + PNG encoder in pure Python. + """ + + def __init__( + self, + width=None, + height=None, + size=None, + greyscale=False, + alpha=False, + bitdepth=8, + palette=None, + transparent=None, + background=None, + gamma=None, + compression=None, + interlace=False, + bytes_per_sample=None, # deprecated + planes=None, + colormap=None, + maxval=None, + chunk_limit=2 ** 20, + ): + """ + Create a PNG encoder object. + + Arguments: + + width, height + Image size in pixels, as two separate arguments. + size + Image size (w,h) in pixels, as single argument. + greyscale + Input data is greyscale, not RGB. + alpha + Input data has alpha channel (RGBA or LA). + bitdepth + Bit depth: from 1 to 16. + palette + Create a palette for a colour mapped image (colour type 3). + transparent + Specify a transparent colour (create a ``tRNS`` chunk). + background + Specify a default background colour (create a ``bKGD`` chunk). + gamma + Specify a gamma value (create a ``gAMA`` chunk). + compression + zlib compression level (1-9). + interlace + Create an interlaced image. + chunk_limit + Write multiple ``IDAT`` chunks to save memory. + + The image size (in pixels) can be specified either by using the + `width` and `height` arguments, or with the single `size` + argument. If `size` is used it should be a pair (*width*, + *height*). + + `greyscale` and `alpha` are booleans that specify whether + an image is greyscale (or colour), and whether it has an + alpha channel (or not). + + `bitdepth` specifies the bit depth of the source pixel values. + Each source pixel value must be an integer between 0 and + ``2**bitdepth-1``. For example, 8-bit images have values + between 0 and 255. PNG only stores images with bit depths of + 1,2,4,8, or 16. When `bitdepth` is not one of these values, + the next highest valid bit depth is selected, and an ``sBIT`` + (significant bits) chunk is generated that specifies the original + precision of the source image. In this case the supplied pixel + values will be rescaled to fit the range of the selected bit depth. + + The details of which bit depth / colour model combinations the + PNG file format supports directly, are somewhat arcane + (refer to the PNG specification for full details). Briefly: + "small" bit depths (1,2,4) are only allowed with greyscale and + colour mapped images; colour mapped images cannot have bit depth + 16. + + For colour mapped images (in other words, when the `palette` + argument is specified) the `bitdepth` argument must match one of + the valid PNG bit depths: 1, 2, 4, or 8. (It is valid to have a + PNG image with a palette and an ``sBIT`` chunk, but the meaning + is slightly different; it would be awkward to press the + `bitdepth` argument into service for this.) + + The `palette` option, when specified, causes a colour mapped image + to be created: the PNG colour type is set to 3; greyscale + must not be set; alpha must not be set; transparent must + not be set; the bit depth must be 1,2,4, or 8. When a colour + mapped image is created, the pixel values are palette indexes + and the `bitdepth` argument specifies the size of these indexes + (not the size of the colour values in the palette). + + The palette argument value should be a sequence of 3- or + 4-tuples. 3-tuples specify RGB palette entries; 4-tuples + specify RGBA palette entries. If both 4-tuples and 3-tuples + appear in the sequence then all the 4-tuples must come + before all the 3-tuples. A ``PLTE`` chunk is created; if there + are 4-tuples then a ``tRNS`` chunk is created as well. The + ``PLTE`` chunk will contain all the RGB triples in the same + sequence; the ``tRNS`` chunk will contain the alpha channel for + all the 4-tuples, in the same sequence. Palette entries + are always 8-bit. + + If specified, the `transparent` and `background` parameters must + be a tuple with three integer values for red, green, blue, or + a simple integer (or singleton tuple) for a greyscale image. + + If specified, the `gamma` parameter must be a positive number + (generally, a float). A ``gAMA`` chunk will be created. Note that + this will not change the values of the pixels as they appear in + the PNG file, they are assumed to have already been converted + appropriately for the gamma specified. + + The `compression` argument specifies the compression level + to be used by the ``zlib`` module. Higher values are likely + to compress better, but will be slower to compress. The + default for this argument is ``None``; this does not mean + no compression, rather it means that the default from the + ``zlib`` module is used (which is generally acceptable). + + If `interlace` is true then an interlaced image is created + (using PNG's so far only interlace method, *Adam7*). This does not + affect how the pixels should be presented to the encoder, rather + it changes how they are arranged into the PNG file. On slow + connexions interlaced images can be partially decoded by the + browser to give a rough view of the image that is successively + refined as more image data appears. + + .. note :: + + Enabling the `interlace` option requires the entire image + to be processed in working memory. + + `chunk_limit` is used to limit the amount of memory used whilst + compressing the image. In order to avoid using large amounts of + memory, multiple ``IDAT`` chunks may be created. + """ + + # At the moment the `planes` argument is ignored; + # its purpose is to act as a dummy so that + # ``Writer(x, y, **info)`` works, where `info` is a dictionary + # returned by Reader.read and friends. + # Ditto for `colormap`. + + # A couple of helper functions come first. Best skipped if you + # are reading through. + + def isinteger(x): + try: + return int(x) == x + except: + return False + + def check_color(c, which): + """Checks that a colour argument for transparent or + background options is the right form. Also "corrects" bare + integers to 1-tuples. + """ + + if c is None: + return c + if greyscale: + try: + l = len(c) + except TypeError: + c = (c,) + if len(c) != 1: + raise ValueError("%s for greyscale must be 1-tuple" % which) + if not isinteger(c[0]): + raise ValueError("%s colour for greyscale must be integer" % which) + else: + if not ( + len(c) == 3 + and isinteger(c[0]) + and isinteger(c[1]) + and isinteger(c[2]) + ): + raise ValueError("%s colour must be a triple of integers" % which) + return c + + if size: + if len(size) != 2: + raise ValueError("size argument should be a pair (width, height)") + if width is not None and width != size[0]: + raise ValueError( + "size[0] (%r) and width (%r) should match when both are used." + % (size[0], width) + ) + if height is not None and height != size[1]: + raise ValueError( + "size[1] (%r) and height (%r) should match when both are used." + % (size[1], height) + ) + width, height = size + del size + + if width <= 0 or height <= 0: + raise ValueError("width and height must be greater than zero") + if not isinteger(width) or not isinteger(height): + raise ValueError("width and height must be integers") + # http://www.w3.org/TR/PNG/#7Integers-and-byte-order + if width > 2 ** 32 - 1 or height > 2 ** 32 - 1: + raise ValueError("width and height cannot exceed 2**32-1") + + if alpha and transparent is not None: + raise ValueError("transparent colour not allowed with alpha channel") + + if bytes_per_sample is not None: + warnings.warn( + "please use bitdepth instead of bytes_per_sample", DeprecationWarning + ) + if bytes_per_sample not in (0.125, 0.25, 0.5, 1, 2): + raise ValueError("bytes per sample must be .125, .25, .5, 1, or 2") + bitdepth = int(8 * bytes_per_sample) + del bytes_per_sample + if not isinteger(bitdepth) or bitdepth < 1 or 16 < bitdepth: + raise ValueError( + "bitdepth (%r) must be a positive integer <= 16" % bitdepth + ) + + self.rescale = None + if palette: + if bitdepth not in (1, 2, 4, 8): + raise ValueError("with palette, bitdepth must be 1, 2, 4, or 8") + if transparent is not None: + raise ValueError("transparent and palette not compatible") + if alpha: + raise ValueError("alpha and palette not compatible") + if greyscale: + raise ValueError("greyscale and palette not compatible") + else: + # No palette, check for sBIT chunk generation. + if alpha or not greyscale: + if bitdepth not in (8, 16): + targetbitdepth = (8, 16)[bitdepth > 8] + self.rescale = (bitdepth, targetbitdepth) + bitdepth = targetbitdepth + del targetbitdepth + else: + assert greyscale + assert not alpha + if bitdepth not in (1, 2, 4, 8, 16): + if bitdepth > 8: + targetbitdepth = 16 + elif bitdepth == 3: + targetbitdepth = 4 + else: + assert bitdepth in (5, 6, 7) + targetbitdepth = 8 + self.rescale = (bitdepth, targetbitdepth) + bitdepth = targetbitdepth + del targetbitdepth + + if bitdepth < 8 and (alpha or not greyscale and not palette): + raise ValueError("bitdepth < 8 only permitted with greyscale or palette") + if bitdepth > 8 and palette: + raise ValueError("bit depth must be 8 or less for images with palette") + + transparent = check_color(transparent, "transparent") + background = check_color(background, "background") + + # It's important that the true boolean values (greyscale, alpha, + # colormap, interlace) are converted to bool because Iverson's + # convention is relied upon later on. + self.width = width + self.height = height + self.transparent = transparent + self.background = background + self.gamma = gamma + self.greyscale = bool(greyscale) + self.alpha = bool(alpha) + self.colormap = bool(palette) + self.bitdepth = int(bitdepth) + self.compression = compression + self.chunk_limit = chunk_limit + self.interlace = bool(interlace) + self.palette = check_palette(palette) + + self.color_type = 4 * self.alpha + 2 * (not greyscale) + 1 * self.colormap + assert self.color_type in (0, 2, 3, 4, 6) + + self.color_planes = (3, 1)[self.greyscale or self.colormap] + self.planes = self.color_planes + self.alpha + # :todo: fix for bitdepth < 8 + self.psize = (self.bitdepth / 8) * self.planes + + def make_palette(self): + """Create the byte sequences for a ``PLTE`` and if necessary a + ``tRNS`` chunk. Returned as a pair (*p*, *t*). *t* will be + ``None`` if no ``tRNS`` chunk is necessary. + """ + + p = array("B") + t = array("B") + + for x in self.palette: + p.extend(x[0:3]) + if len(x) > 3: + t.append(x[3]) + p = tostring(p) + t = tostring(t) + if t: + return p, t + return p, None + + def write(self, outfile, rows): + """Write a PNG image to the output file. `rows` should be + an iterable that yields each row in boxed row flat pixel format. + The rows should be the rows of the original image, so there + should be ``self.height`` rows of ``self.width * self.planes`` values. + If `interlace` is specified (when creating the instance), then + an interlaced PNG file will be written. Supply the rows in the + normal image order; the interlacing is carried out internally. + + .. note :: + + Interlacing will require the entire image to be in working memory. + """ + + if self.interlace: + fmt = "BH"[self.bitdepth > 8] + a = array(fmt, itertools.chain(*rows)) + return self.write_array(outfile, a) + else: + nrows = self.write_passes(outfile, rows) + if nrows != self.height: + raise ValueError( + "rows supplied (%d) does not match height (%d)" + % (nrows, self.height) + ) + + def write_passes(self, outfile, rows, packed=False): + """ + Write a PNG image to the output file. + + Most users are expected to find the :meth:`write` or + :meth:`write_array` method more convenient. + + The rows should be given to this method in the order that + they appear in the output file. For straightlaced images, + this is the usual top to bottom ordering, but for interlaced + images the rows should have already been interlaced before + passing them to this function. + + `rows` should be an iterable that yields each row. When + `packed` is ``False`` the rows should be in boxed row flat pixel + format; when `packed` is ``True`` each row should be a packed + sequence of bytes. + + """ + + # http://www.w3.org/TR/PNG/#5PNG-file-signature + outfile.write(_signature) + + # http://www.w3.org/TR/PNG/#11IHDR + write_chunk( + outfile, + "IHDR", + struct.pack( + "!2I5B", + self.width, + self.height, + self.bitdepth, + self.color_type, + 0, + 0, + self.interlace, + ), + ) + + # See :chunk:order + # http://www.w3.org/TR/PNG/#11gAMA + if self.gamma is not None: + write_chunk( + outfile, "gAMA", struct.pack("!L", int(round(self.gamma * 1e5))) + ) + + # See :chunk:order + # http://www.w3.org/TR/PNG/#11sBIT + if self.rescale: + write_chunk( + outfile, + "sBIT", + struct.pack("%dB" % self.planes, *[self.rescale[0]] * self.planes), + ) + + # :chunk:order: Without a palette (PLTE chunk), ordering is + # relatively relaxed. With one, gAMA chunk must precede PLTE + # chunk which must precede tRNS and bKGD. + # See http://www.w3.org/TR/PNG/#5ChunkOrdering + if self.palette: + p, t = self.make_palette() + write_chunk(outfile, "PLTE", p) + if t: + # tRNS chunk is optional. Only needed if palette entries + # have alpha. + write_chunk(outfile, "tRNS", t) + + # http://www.w3.org/TR/PNG/#11tRNS + if self.transparent is not None: + if self.greyscale: + write_chunk(outfile, "tRNS", struct.pack("!1H", *self.transparent)) + else: + write_chunk(outfile, "tRNS", struct.pack("!3H", *self.transparent)) + + # http://www.w3.org/TR/PNG/#11bKGD + if self.background is not None: + if self.greyscale: + write_chunk(outfile, "bKGD", struct.pack("!1H", *self.background)) + else: + write_chunk(outfile, "bKGD", struct.pack("!3H", *self.background)) + + # http://www.w3.org/TR/PNG/#11IDAT + if self.compression is not None: + compressor = zlib.compressobj(self.compression) + else: + compressor = zlib.compressobj() + + # Choose an extend function based on the bitdepth. The extend + # function packs/decomposes the pixel values into bytes and + # stuffs them onto the data array. + data = array("B") + if self.bitdepth == 8 or packed: + extend = data.extend + elif self.bitdepth == 16: + # Decompose into bytes + def extend(sl): + fmt = "!%dH" % len(sl) + data.extend(array("B", struct.pack(fmt, *sl))) + + else: + # Pack into bytes + assert self.bitdepth < 8 + # samples per byte + spb = int(8 / self.bitdepth) + + def extend(sl): + a = array("B", sl) + # Adding padding bytes so we can group into a whole + # number of spb-tuples. + l = float(len(a)) + extra = math.ceil(l / float(spb)) * spb - l + a.extend([0] * int(extra)) + # Pack into bytes + l = group(a, spb) + l = map(lambda e: reduce(lambda x, y: (x << self.bitdepth) + y, e), l) + data.extend(l) + + if self.rescale: + oldextend = extend + factor = float(2 ** self.rescale[1] - 1) / float(2 ** self.rescale[0] - 1) + + def extend(sl): + oldextend(map(lambda x: int(round(factor * x)), sl)) + + # Build the first row, testing mostly to see if we need to + # changed the extend function to cope with NumPy integer types + # (they cause our ordinary definition of extend to fail, so we + # wrap it). See + # http://code.google.com/p/pypng/issues/detail?id=44 + enumrows = enumerate(rows) + del rows + + # First row's filter type. + data.append(0) + # :todo: Certain exceptions in the call to ``.next()`` or the + # following try would indicate no row data supplied. + # Should catch. + i, row = next(enumrows) + try: + # If this fails... + extend(row) + except: + # ... try a version that converts the values to int first. + # Not only does this work for the (slightly broken) NumPy + # types, there are probably lots of other, unknown, "nearly" + # int types it works for. + def wrapmapint(f): + return lambda sl: f(map(int, sl)) + + extend = wrapmapint(extend) + del wrapmapint + extend(row) + + for i, row in enumrows: + # Add "None" filter type. Currently, it's essential that + # this filter type be used for every scanline as we do not + # mark the first row of a reduced pass image; that means we + # could accidentally compute the wrong filtered scanline if + # we used "up", "average", or "paeth" on such a line. + data.append(0) + extend(row) + if len(data) > self.chunk_limit: + compressed = compressor.compress(tostring(data)) + if len(compressed): + # print >> sys.stderr, len(data), len(compressed) + write_chunk(outfile, "IDAT", compressed) + # Because of our very witty definition of ``extend``, + # above, we must re-use the same ``data`` object. Hence + # we use ``del`` to empty this one, rather than create a + # fresh one (which would be my natural FP instinct). + del data[:] + if len(data): + compressed = compressor.compress(tostring(data)) + else: + compressed = "" + flushed = compressor.flush() + if len(compressed) or len(flushed): + # print >> sys.stderr, len(data), len(compressed), len(flushed) + write_chunk(outfile, "IDAT", compressed + flushed) + # http://www.w3.org/TR/PNG/#11IEND + write_chunk(outfile, "IEND") + return i + 1 + + def write_array(self, outfile, pixels): + """ + Write an array in flat row flat pixel format as a PNG file on + the output file. See also :meth:`write` method. + """ + + if self.interlace: + self.write_passes(outfile, self.array_scanlines_interlace(pixels)) + else: + self.write_passes(outfile, self.array_scanlines(pixels)) + + def write_packed(self, outfile, rows): + """ + Write PNG file to `outfile`. The pixel data comes from `rows` + which should be in boxed row packed format. Each row should be + a sequence of packed bytes. + + Technically, this method does work for interlaced images but it + is best avoided. For interlaced images, the rows should be + presented in the order that they appear in the file. + + This method should not be used when the source image bit depth + is not one naturally supported by PNG; the bit depth should be + 1, 2, 4, 8, or 16. + """ + + if self.rescale: + raise Error( + "write_packed method not suitable for bit depth %d" % self.rescale[0] + ) + return self.write_passes(outfile, rows, packed=True) + + def convert_pnm(self, infile, outfile): + """ + Convert a PNM file containing raw pixel data into a PNG file + with the parameters set in the writer object. Works for + (binary) PGM, PPM, and PAM formats. + """ + + if self.interlace: + pixels = array("B") + pixels.fromfile( + infile, + (self.bitdepth / 8) * self.color_planes * self.width * self.height, + ) + self.write_passes(outfile, self.array_scanlines_interlace(pixels)) + else: + self.write_passes(outfile, self.file_scanlines(infile)) + + def convert_ppm_and_pgm(self, ppmfile, pgmfile, outfile): + """ + Convert a PPM and PGM file containing raw pixel data into a + PNG outfile with the parameters set in the writer object. + """ + pixels = array("B") + pixels.fromfile( + ppmfile, (self.bitdepth / 8) * self.color_planes * self.width * self.height + ) + apixels = array("B") + apixels.fromfile(pgmfile, (self.bitdepth / 8) * self.width * self.height) + pixels = interleave_planes( + pixels, + apixels, + (self.bitdepth / 8) * self.color_planes, + (self.bitdepth / 8), + ) + if self.interlace: + self.write_passes(outfile, self.array_scanlines_interlace(pixels)) + else: + self.write_passes(outfile, self.array_scanlines(pixels)) + + def file_scanlines(self, infile): + """ + Generates boxed rows in flat pixel format, from the input file + `infile`. It assumes that the input file is in a "Netpbm-like" + binary format, and is positioned at the beginning of the first + pixel. The number of pixels to read is taken from the image + dimensions (`width`, `height`, `planes`) and the number of bytes + per value is implied by the image `bitdepth`. + """ + + # Values per row + vpr = self.width * self.planes + row_bytes = vpr + if self.bitdepth > 8: + assert self.bitdepth == 16 + row_bytes *= 2 + fmt = ">%dH" % vpr + + def line(): + return array("H", struct.unpack(fmt, infile.read(row_bytes))) + + else: + + def line(): + scanline = array("B", infile.read(row_bytes)) + return scanline + + for y in range(self.height): + yield line() + + def array_scanlines(self, pixels): + """ + Generates boxed rows (flat pixels) from flat rows (flat pixels) + in an array. + """ + + # Values per row + vpr = self.width * self.planes + stop = 0 + for y in range(self.height): + start = stop + stop = start + vpr + yield pixels[start:stop] + + def array_scanlines_interlace(self, pixels): + """ + Generator for interlaced scanlines from an array. `pixels` is + the full source image in flat row flat pixel format. The + generator yields each scanline of the reduced passes in turn, in + boxed row flat pixel format. + """ + + # http://www.w3.org/TR/PNG/#8InterlaceMethods + # Array type. + fmt = "BH"[self.bitdepth > 8] + # Value per row + vpr = self.width * self.planes + for xstart, ystart, xstep, ystep in _adam7: + if xstart >= self.width: + continue + # Pixels per row (of reduced image) + ppr = int(math.ceil((self.width - xstart) / float(xstep))) + # number of values in reduced image row. + row_len = ppr * self.planes + for y in range(ystart, self.height, ystep): + if xstep == 1: + offset = y * vpr + yield pixels[offset : offset + vpr] + else: + row = array(fmt) + # There's no easier way to set the length of an array + row.extend(pixels[0:row_len]) + offset = y * vpr + xstart * self.planes + end_offset = (y + 1) * vpr + skip = self.planes * xstep + for i in range(self.planes): + row[i :: self.planes] = pixels[offset + i : end_offset : skip] + yield row + + +def write_chunk(outfile, tag, data=strtobytes("")): + """ + Write a PNG chunk to the output file, including length and + checksum. + """ + + # http://www.w3.org/TR/PNG/#5Chunk-layout + outfile.write(struct.pack("!I", len(data))) + tag = strtobytes(tag) + outfile.write(tag) + outfile.write(data) + checksum = zlib.crc32(tag) + checksum = zlib.crc32(data, checksum) + checksum &= 2 ** 32 - 1 + outfile.write(struct.pack("!I", checksum)) + + +def write_chunks(out, chunks): + """Create a PNG file by writing out the chunks.""" + + out.write(_signature) + for chunk in chunks: + write_chunk(out, *chunk) + + +def filter_scanline(type, line, fo, prev=None): + """Apply a scanline filter to a scanline. `type` specifies the + filter type (0 to 4); `line` specifies the current (unfiltered) + scanline as a sequence of bytes; `prev` specifies the previous + (unfiltered) scanline as a sequence of bytes. `fo` specifies the + filter offset; normally this is size of a pixel in bytes (the number + of bytes per sample times the number of channels), but when this is + < 1 (for bit depths < 8) then the filter offset is 1. + """ + + assert 0 <= type < 5 + + # The output array. Which, pathetically, we extend one-byte at a + # time (fortunately this is linear). + out = array("B", [type]) + + def sub(): + ai = -fo + for x in line: + if ai >= 0: + x = (x - line[ai]) & 0xFF + out.append(x) + ai += 1 + + def up(): + for i, x in enumerate(line): + x = (x - prev[i]) & 0xFF + out.append(x) + + def average(): + ai = -fo + for i, x in enumerate(line): + if ai >= 0: + x = (x - ((line[ai] + prev[i]) >> 1)) & 0xFF + else: + x = (x - (prev[i] >> 1)) & 0xFF + out.append(x) + ai += 1 + + def paeth(): + # http://www.w3.org/TR/PNG/#9Filter-type-4-Paeth + ai = -fo # also used for ci + for i, x in enumerate(line): + a = 0 + b = prev[i] + c = 0 + + if ai >= 0: + a = line[ai] + c = prev[ai] + p = a + b - c + pa = abs(p - a) + pb = abs(p - b) + pc = abs(p - c) + if pa <= pb and pa <= pc: + Pr = a + elif pb <= pc: + Pr = b + else: + Pr = c + + x = (x - Pr) & 0xFF + out.append(x) + ai += 1 + + if not prev: + # We're on the first line. Some of the filters can be reduced + # to simpler cases which makes handling the line "off the top" + # of the image simpler. "up" becomes "none"; "paeth" becomes + # "left" (non-trivial, but true). "average" needs to be handled + # specially. + if type == 2: # "up" + return line # type = 0 + elif type == 3: + prev = [0] * len(line) + elif type == 4: # "paeth" + type = 1 + if type == 0: + out.extend(line) + elif type == 1: + sub() + elif type == 2: + up() + elif type == 3: + average() + else: # type == 4 + paeth() + return out + + +def from_array(a, mode=None, info={}): + """Create a PNG :class:`Image` object from a 2- or 3-dimensional array. + One application of this function is easy PIL-style saving: + ``png.from_array(pixels, 'L').save('foo.png')``. + + .. note : + + The use of the term *3-dimensional* is for marketing purposes + only. It doesn't actually work. Please bear with us. Meanwhile + enjoy the complimentary snacks (on request) and please use a + 2-dimensional array. + + Unless they are specified using the *info* parameter, the PNG's + height and width are taken from the array size. For a 3 dimensional + array the first axis is the height; the second axis is the width; + and the third axis is the channel number. Thus an RGB image that is + 16 pixels high and 8 wide will use an array that is 16x8x3. For 2 + dimensional arrays the first axis is the height, but the second axis + is ``width*channels``, so an RGB image that is 16 pixels high and 8 + wide will use a 2-dimensional array that is 16x24 (each row will be + 8*3==24 sample values). + + *mode* is a string that specifies the image colour format in a + PIL-style mode. It can be: + + ``'L'`` + greyscale (1 channel) + ``'LA'`` + greyscale with alpha (2 channel) + ``'RGB'`` + colour image (3 channel) + ``'RGBA'`` + colour image with alpha (4 channel) + + The mode string can also specify the bit depth (overriding how this + function normally derives the bit depth, see below). Appending + ``';16'`` to the mode will cause the PNG to be 16 bits per channel; + any decimal from 1 to 16 can be used to specify the bit depth. + + When a 2-dimensional array is used *mode* determines how many + channels the image has, and so allows the width to be derived from + the second array dimension. + + The array is expected to be a ``numpy`` array, but it can be any + suitable Python sequence. For example, a list of lists can be used: + ``png.from_array([[0, 255, 0], [255, 0, 255]], 'L')``. The exact + rules are: ``len(a)`` gives the first dimension, height; + ``len(a[0])`` gives the second dimension; ``len(a[0][0])`` gives the + third dimension, unless an exception is raised in which case a + 2-dimensional array is assumed. It's slightly more complicated than + that because an iterator of rows can be used, and it all still + works. Using an iterator allows data to be streamed efficiently. + + The bit depth of the PNG is normally taken from the array element's + datatype (but if *mode* specifies a bitdepth then that is used + instead). The array element's datatype is determined in a way which + is supposed to work both for ``numpy`` arrays and for Python + ``array.array`` objects. A 1 byte datatype will give a bit depth of + 8, a 2 byte datatype will give a bit depth of 16. If the datatype + does not have an implicit size, for example it is a plain Python + list of lists, as above, then a default of 8 is used. + + The *info* parameter is a dictionary that can be used to specify + metadata (in the same style as the arguments to the + :class:``png.Writer`` class). For this function the keys that are + useful are: + + height + overrides the height derived from the array dimensions and allows + *a* to be an iterable. + width + overrides the width derived from the array dimensions. + bitdepth + overrides the bit depth derived from the element datatype (but + must match *mode* if that also specifies a bit depth). + + Generally anything specified in the + *info* dictionary will override any implicit choices that this + function would otherwise make, but must match any explicit ones. + For example, if the *info* dictionary has a ``greyscale`` key then + this must be true when mode is ``'L'`` or ``'LA'`` and false when + mode is ``'RGB'`` or ``'RGBA'``. + """ + + # We abuse the *info* parameter by modifying it. Take a copy here. + # (Also typechecks *info* to some extent). + info = dict(info) + + # Syntax check mode string. + bitdepth = None + try: + mode = mode.split(";") + if len(mode) not in (1, 2): + raise Error() + if mode[0] not in ("L", "LA", "RGB", "RGBA"): + raise Error() + if len(mode) == 2: + try: + bitdepth = int(mode[1]) + except: + raise Error() + except Error: + raise Error("mode string should be 'RGB' or 'L;16' or similar.") + mode = mode[0] + + # Get bitdepth from *mode* if possible. + if bitdepth: + if info.get("bitdepth") and bitdepth != info["bitdepth"]: + raise Error( + "mode bitdepth (%d) should match info bitdepth (%d)." + % (bitdepth, info["bitdepth"]) + ) + info["bitdepth"] = bitdepth + + # Fill in and/or check entries in *info*. + # Dimensions. + if "size" in info: + # Check width, height, size all match where used. + for dimension, axis in [("width", 0), ("height", 1)]: + if dimension in info: + if info[dimension] != info["size"][axis]: + raise Error( + "info[%r] should match info['size'][%r]." % (dimension, axis) + ) + info["width"], info["height"] = info["size"] + if "height" not in info: + try: + l = len(a) + except: + raise Error("len(a) does not work, supply info['height'] instead.") + info["height"] = l + # Colour format. + if "greyscale" in info: + if bool(info["greyscale"]) != ("L" in mode): + raise Error("info['greyscale'] should match mode.") + info["greyscale"] = "L" in mode + if "alpha" in info: + if bool(info["alpha"]) != ("A" in mode): + raise Error("info['alpha'] should match mode.") + info["alpha"] = "A" in mode + + planes = len(mode) + if "planes" in info: + if info["planes"] != planes: + raise Error("info['planes'] should match mode.") + + # In order to work out whether we the array is 2D or 3D we need its + # first row, which requires that we take a copy of its iterator. + # We may also need the first row to derive width and bitdepth. + a, t = itertools.tee(a) + row = next(t) + del t + try: + row[0][0] + threed = True + testelement = row[0] + except: + threed = False + testelement = row + if "width" not in info: + if threed: + width = len(row) + else: + width = len(row) // planes + info["width"] = width + + # Not implemented yet + assert not threed + + if "bitdepth" not in info: + try: + dtype = testelement.dtype + # goto the "else:" clause. Sorry. + except: + try: + # Try a Python array.array. + bitdepth = 8 * testelement.itemsize + except: + # We can't determine it from the array element's + # datatype, use a default of 8. + bitdepth = 8 + else: + # If we got here without exception, we now assume that + # the array is a numpy array. + if dtype.kind == "b": + bitdepth = 1 + else: + bitdepth = 8 * dtype.itemsize + info["bitdepth"] = bitdepth + + for thing in "width height bitdepth greyscale alpha".split(): + assert thing in info + return Image(a, info) + + +# So that refugee's from PIL feel more at home. Not documented. +fromarray = from_array + + +class Image: + """A PNG image. + You can create an :class:`Image` object from an array of pixels by calling + :meth:`png.from_array`. It can be saved to disk with the + :meth:`save` method.""" + + def __init__(self, rows, info): + """ + .. note :: + + The constructor is not public. Please do not call it. + """ + + self.rows = rows + self.info = info + + def save(self, file): + """Save the image to *file*. If *file* looks like an open file + descriptor then it is used, otherwise it is treated as a + filename and a fresh file is opened. + + In general, you can only call this method once; after it has + been called the first time and the PNG image has been saved, the + source data will have been streamed, and cannot be streamed + again. + """ + + w = Writer(**self.info) + + try: + file.write + + def close(): + pass + + except: + file = open(file, "wb") + + def close(): + file.close() + + try: + w.write(file, self.rows) + finally: + close() + + +class _readable: + """ + A simple file-like interface for strings and arrays. + """ + + def __init__(self, buf): + self.buf = buf + self.offset = 0 + + def read(self, n): + r = self.buf[self.offset : self.offset + n] + if isarray(r): + r = tostring(r) + self.offset += n + return r + + +class Reader: + """ + PNG decoder in pure Python. + """ + + def __init__(self, _guess=None, **kw): + """ + Create a PNG decoder object. + + The constructor expects exactly one keyword argument. If you + supply a positional argument instead, it will guess the input + type. You can choose among the following keyword arguments: + + filename + Name of input file (a PNG file). + file + A file-like object (object with a read() method). + bytes + ``array`` or ``string`` with PNG data. + + """ + if (_guess is not None and len(kw) != 0) or (_guess is None and len(kw) != 1): + raise TypeError("Reader() takes exactly 1 argument") + + # Will be the first 8 bytes, later on. See validate_signature. + self.signature = None + self.transparent = None + # A pair of (len,type) if a chunk has been read but its data and + # checksum have not (in other words the file position is just + # past the 4 bytes that specify the chunk type). See preamble + # method for how this is used. + self.atchunk = None + + if _guess is not None: + if isarray(_guess): + kw["bytes"] = _guess + elif isinstance(_guess, str): + kw["filename"] = _guess + elif isinstance(_guess, file): + kw["file"] = _guess + + if "filename" in kw: + self.file = open(kw["filename"], "rb") + elif "file" in kw: + self.file = kw["file"] + elif "bytes" in kw: + self.file = _readable(kw["bytes"]) + else: + raise TypeError("expecting filename, file or bytes array") + + def chunk(self, seek=None): + """ + Read the next PNG chunk from the input file; returns a + (*type*,*data*) tuple. *type* is the chunk's type as a string + (all PNG chunk types are 4 characters long). *data* is the + chunk's data content, as a string. + + If the optional `seek` argument is + specified then it will keep reading chunks until it either runs + out of file or finds the type specified by the argument. Note + that in general the order of chunks in PNGs is unspecified, so + using `seek` can cause you to miss chunks. + """ + + self.validate_signature() + + while True: + # http://www.w3.org/TR/PNG/#5Chunk-layout + if not self.atchunk: + self.atchunk = self.chunklentype() + length, type = self.atchunk + self.atchunk = None + data = self.file.read(length) + if len(data) != length: + raise ChunkError( + "Chunk %s too short for required %i octets." % (type, length) + ) + checksum = self.file.read(4) + if len(checksum) != 4: + raise ValueError("Chunk %s too short for checksum.", tag) + if seek and type != seek: + continue + verify = zlib.crc32(strtobytes(type)) + verify = zlib.crc32(data, verify) + # Whether the output from zlib.crc32 is signed or not varies + # according to hideous implementation details, see + # http://bugs.python.org/issue1202 . + # We coerce it to be positive here (in a way which works on + # Python 2.3 and older). + verify &= 2 ** 32 - 1 + verify = struct.pack("!I", verify) + if checksum != verify: + # print repr(checksum) + (a,) = struct.unpack("!I", checksum) + (b,) = struct.unpack("!I", verify) + raise ChunkError( + "Checksum error in %s chunk: 0x%08X != 0x%08X." % (type, a, b) + ) + return type, data + + def chunks(self): + """Return an iterator that will yield each chunk as a + (*chunktype*, *content*) pair. + """ + + while True: + t, v = self.chunk() + yield t, v + if t == "IEND": + break + + def undo_filter(self, filter_type, scanline, previous): + """Undo the filter for a scanline. `scanline` is a sequence of + bytes that does not include the initial filter type byte. + `previous` is decoded previous scanline (for straightlaced + images this is the previous pixel row, but for interlaced + images, it is the previous scanline in the reduced image, which + in general is not the previous pixel row in the final image). + When there is no previous scanline (the first row of a + straightlaced image, or the first row in one of the passes in an + interlaced image), then this argument should be ``None``. + + The scanline will have the effects of filtering removed, and the + result will be returned as a fresh sequence of bytes. + """ + + # :todo: Would it be better to update scanline in place? + + # Create the result byte array. It seems that the best way to + # create the array to be the right size is to copy from an + # existing sequence. *sigh* + # If we fill the result with scanline, then this allows a + # micro-optimisation in the "null" and "sub" cases. + result = array("B", scanline) + + if filter_type == 0: + # And here, we _rely_ on filling the result with scanline, + # above. + return result + + if filter_type not in (1, 2, 3, 4): + raise FormatError( + "Invalid PNG Filter Type." + " See http://www.w3.org/TR/2003/REC-PNG-20031110/#9Filters ." + ) + + # Filter unit. The stride from one pixel to the corresponding + # byte from the previous previous. Normally this is the pixel + # size in bytes, but when this is smaller than 1, the previous + # byte is used instead. + fu = max(1, self.psize) + + # For the first line of a pass, synthesize a dummy previous + # line. An alternative approach would be to observe that on the + # first line 'up' is the same as 'null', 'paeth' is the same + # as 'sub', with only 'average' requiring any special case. + if not previous: + previous = array("B", [0] * len(scanline)) + + def sub(): + """Undo sub filter.""" + + ai = 0 + # Loops starts at index fu. Observe that the initial part + # of the result is already filled in correctly with + # scanline. + for i in range(fu, len(result)): + x = scanline[i] + a = result[ai] + result[i] = (x + a) & 0xFF + ai += 1 + + def up(): + """Undo up filter.""" + for i in range(len(result)): # pylint: disable=consider-using-enumerate + x = scanline[i] + b = previous[i] + result[i] = (x + b) & 0xFF + + def average(): + """Undo average filter.""" + + ai = -fu + for i in range(len(result)): # pylint: disable=consider-using-enumerate + x = scanline[i] + if ai < 0: + a = 0 + else: + a = result[ai] + b = previous[i] + result[i] = (x + ((a + b) >> 1)) & 0xFF + ai += 1 + + def paeth(): + """Undo Paeth filter.""" + + # Also used for ci. + ai = -fu + for i in range(len(result)): # pylint: disable=consider-using-enumerate + x = scanline[i] + if ai < 0: + a = c = 0 + else: + a = result[ai] + c = previous[ai] + b = previous[i] + p = a + b - c + pa = abs(p - a) + pb = abs(p - b) + pc = abs(p - c) + if pa <= pb and pa <= pc: + pr = a + elif pb <= pc: + pr = b + else: + pr = c + result[i] = (x + pr) & 0xFF + ai += 1 + + # Call appropriate filter algorithm. Note that 0 has already + # been dealt with. + (None, sub, up, average, paeth)[filter_type]() + return result + + def deinterlace(self, raw): + """ + Read raw pixel data, undo filters, deinterlace, and flatten. + Return in flat row flat pixel format. + """ + + # print >> sys.stderr, ("Reading interlaced, w=%s, r=%s, planes=%s," + + # " bpp=%s") % (self.width, self.height, self.planes, self.bps) + # Values per row (of the target image) + vpr = self.width * self.planes + + # Make a result array, and make it big enough. Interleaving + # writes to the output array randomly (well, not quite), so the + # entire output array must be in memory. + fmt = "BH"[self.bitdepth > 8] + a = array(fmt, [0] * vpr * self.height) + source_offset = 0 + + for xstart, ystart, xstep, ystep in _adam7: + # print >> sys.stderr, "Adam7: start=%s,%s step=%s,%s" % ( + # xstart, ystart, xstep, ystep) + if xstart >= self.width: + continue + # The previous (reconstructed) scanline. None at the + # beginning of a pass to indicate that there is no previous + # line. + recon = None + # Pixels per row (reduced pass image) + ppr = int(math.ceil((self.width - xstart) / float(xstep))) + # Row size in bytes for this pass. + row_size = int(math.ceil(self.psize * ppr)) + for y in range(ystart, self.height, ystep): + filter_type = raw[source_offset] + source_offset += 1 + scanline = raw[source_offset : source_offset + row_size] + source_offset += row_size + recon = self.undo_filter(filter_type, scanline, recon) + # Convert so that there is one element per pixel value + flat = self.serialtoflat(recon, ppr) + if xstep == 1: + assert xstart == 0 + offset = y * vpr + a[offset : offset + vpr] = flat + else: + offset = y * vpr + xstart * self.planes + end_offset = (y + 1) * vpr + skip = self.planes * xstep + for i in range(self.planes): + a[offset + i : end_offset : skip] = flat[i :: self.planes] + return a + + def iterboxed(self, rows): + """Iterator that yields each scanline in boxed row flat pixel + format. `rows` should be an iterator that yields the bytes of + each row in turn. + """ + + def asvalues(raw): + """Convert a row of raw bytes into a flat row. Result may + or may not share with argument""" + + if self.bitdepth == 8: + return raw + if self.bitdepth == 16: + raw = tostring(raw) + return array("H", struct.unpack("!%dH" % (len(raw) // 2), raw)) + assert self.bitdepth < 8 + width = self.width + # Samples per byte + spb = 8 // self.bitdepth + out = array("B") + mask = 2 ** self.bitdepth - 1 + shifts = map(self.bitdepth.__mul__, reversed(range(spb))) + for o in raw: + out.extend(map(lambda i: mask & (o >> i), shifts)) + return out[:width] + + return map(asvalues, rows) + + def serialtoflat(self, bytes, width=None): + """Convert serial format (byte stream) pixel data to flat row + flat pixel. + """ + + if self.bitdepth == 8: + return bytes + if self.bitdepth == 16: + bytes = tostring(bytes) + return array("H", struct.unpack("!%dH" % (len(bytes) // 2), bytes)) + assert self.bitdepth < 8 + if width is None: + width = self.width + # Samples per byte + spb = 8 // self.bitdepth + out = array("B") + mask = 2 ** self.bitdepth - 1 + shifts = map(self.bitdepth.__mul__, reversed(range(spb))) + l = width + for o in bytes: + out.extend([(mask & (o >> s)) for s in shifts][:l]) + l -= spb + if l <= 0: + l = width + return out + + def iterstraight(self, raw): + """Iterator that undoes the effect of filtering, and yields each + row in serialised format (as a sequence of bytes). Assumes input + is straightlaced. `raw` should be an iterable that yields the + raw bytes in chunks of arbitrary size.""" + + # length of row, in bytes + rb = self.row_bytes + a = array("B") + # The previous (reconstructed) scanline. None indicates first + # line of image. + recon = None + for some in raw: + a.extend(some) + while len(a) >= rb + 1: + filter_type = a[0] + scanline = a[1 : rb + 1] + del a[: rb + 1] + recon = self.undo_filter(filter_type, scanline, recon) + yield recon + if len(a) != 0: + # :file:format We get here with a file format error: when the + # available bytes (after decompressing) do not pack into exact + # rows. + raise FormatError("Wrong size for decompressed IDAT chunk.") + assert len(a) == 0 + + def validate_signature(self): + """If signature (header) has not been read then read and + validate it; otherwise do nothing. + """ + + if self.signature: + return + self.signature = self.file.read(8) + if self.signature != _signature: + raise FormatError("PNG file has invalid signature.") + + def preamble(self): + """ + Extract the image metadata by reading the initial part of the PNG + file up to the start of the ``IDAT`` chunk. All the chunks that + precede the ``IDAT`` chunk are read and either processed for + metadata or discarded. + """ + + self.validate_signature() + + while True: + if not self.atchunk: + self.atchunk = self.chunklentype() + if self.atchunk is None: + raise FormatError("This PNG file has no IDAT chunks.") + if self.atchunk[1] == "IDAT": + return + self.process_chunk() + + def chunklentype(self): + """Reads just enough of the input to determine the next + chunk's length and type, returned as a (*length*, *type*) pair + where *type* is a string. If there are no more chunks, ``None`` + is returned. + """ + + x = self.file.read(8) + if not x: + return None + if len(x) != 8: + raise FormatError("End of file whilst reading chunk length and type.") + length, type = struct.unpack("!I4s", x) + type = bytestostr(type) + if length > 2 ** 31 - 1: + raise FormatError("Chunk %s is too large: %d." % (type, length)) + return length, type + + def process_chunk(self): + """Process the next chunk and its data. This only processes the + following chunk types, all others are ignored: ``IHDR``, + ``PLTE``, ``bKGD``, ``tRNS``, ``gAMA``, ``sBIT``. + """ + + type, data = self.chunk() + if type == "IHDR": + # http://www.w3.org/TR/PNG/#11IHDR + if len(data) != 13: + raise FormatError("IHDR chunk has incorrect length.") + ( + self.width, + self.height, + self.bitdepth, + self.color_type, + self.compression, + self.filter, + self.interlace, + ) = struct.unpack("!2I5B", data) + + # Check that the header specifies only valid combinations. + if self.bitdepth not in (1, 2, 4, 8, 16): + raise Error("invalid bit depth %d" % self.bitdepth) + if self.color_type not in (0, 2, 3, 4, 6): + raise Error("invalid colour type %d" % self.color_type) + # Check indexed (palettized) images have 8 or fewer bits + # per pixel; check only indexed or greyscale images have + # fewer than 8 bits per pixel. + if (self.color_type & 1 and self.bitdepth > 8) or ( + self.bitdepth < 8 and self.color_type not in (0, 3) + ): + raise FormatError( + "Illegal combination of bit depth (%d)" + " and colour type (%d)." + " See http://www.w3.org/TR/2003/REC-PNG-20031110/#table111 ." + % (self.bitdepth, self.color_type) + ) + if self.compression != 0: + raise Error("unknown compression method %d" % self.compression) + if self.filter != 0: + raise FormatError( + "Unknown filter method %d," + " see http://www.w3.org/TR/2003/REC-PNG-20031110/#9Filters ." + % self.filter + ) + if self.interlace not in (0, 1): + raise FormatError( + "Unknown interlace method %d," + " see http://www.w3.org/TR/2003/REC-PNG-20031110/#8InterlaceMethods ." + % self.interlace + ) + + # Derived values + # http://www.w3.org/TR/PNG/#6Colour-values + colormap = bool(self.color_type & 1) + greyscale = not (self.color_type & 2) + alpha = bool(self.color_type & 4) + color_planes = (3, 1)[greyscale or colormap] + planes = color_planes + alpha + + self.colormap = colormap + self.greyscale = greyscale + self.alpha = alpha + self.color_planes = color_planes + self.planes = planes + self.psize = float(self.bitdepth) / float(8) * planes + if int(self.psize) == self.psize: + self.psize = int(self.psize) + self.row_bytes = int(math.ceil(self.width * self.psize)) + # Stores PLTE chunk if present, and is used to check + # chunk ordering constraints. + self.plte = None + # Stores tRNS chunk if present, and is used to check chunk + # ordering constraints. + self.trns = None + # Stores sbit chunk if present. + self.sbit = None + elif type == "PLTE": + # http://www.w3.org/TR/PNG/#11PLTE + if self.plte: + warnings.warn("Multiple PLTE chunks present.") + self.plte = data + if len(data) % 3 != 0: + raise FormatError("PLTE chunk's length should be a multiple of 3.") + if len(data) > (2 ** self.bitdepth) * 3: + raise FormatError("PLTE chunk is too long.") + if len(data) == 0: + raise FormatError("Empty PLTE is not allowed.") + elif type == "bKGD": + try: + if self.colormap: + if not self.plte: + warnings.warn("PLTE chunk is required before bKGD chunk.") + self.background = struct.unpack("B", data) + else: + self.background = struct.unpack("!%dH" % self.color_planes, data) + except struct.error: + raise FormatError("bKGD chunk has incorrect length.") + elif type == "tRNS": + # http://www.w3.org/TR/PNG/#11tRNS + self.trns = data + if self.colormap: + if not self.plte: + warnings.warn("PLTE chunk is required before tRNS chunk.") + else: + if len(data) > len(self.plte) / 3: + # Was warning, but promoted to Error as it + # would otherwise cause pain later on. + raise FormatError("tRNS chunk is too long.") + else: + if self.alpha: + raise FormatError( + "tRNS chunk is not valid with colour type %d." % self.color_type + ) + try: + self.transparent = struct.unpack("!%dH" % self.color_planes, data) + except struct.error: + raise FormatError("tRNS chunk has incorrect length.") + elif type == "gAMA": + try: + self.gamma = struct.unpack("!L", data)[0] / 100000.0 + except struct.error: + raise FormatError("gAMA chunk has incorrect length.") + elif type == "sBIT": + self.sbit = data + if ( + self.colormap + and len(data) != 3 + or not self.colormap + and len(data) != self.planes + ): + raise FormatError("sBIT chunk has incorrect length.") + + def read(self): + """ + Read the PNG file and decode it. Returns (`width`, `height`, + `pixels`, `metadata`). + + May use excessive memory. + + `pixels` are returned in boxed row flat pixel format. + """ + + def iteridat(): + """Iterator that yields all the ``IDAT`` chunks as strings.""" + while True: + try: + type, data = self.chunk() + except ValueError as e: + raise ChunkError(e.args[0]) + if type == "IEND": + # http://www.w3.org/TR/PNG/#11IEND + break + if type != "IDAT": + continue + # type == 'IDAT' + # http://www.w3.org/TR/PNG/#11IDAT + if self.colormap and not self.plte: + warnings.warn("PLTE chunk is required before IDAT chunk") + yield data + + def iterdecomp(idat): + """Iterator that yields decompressed strings. `idat` should + be an iterator that yields the ``IDAT`` chunk data. + """ + + # Currently, with no max_length parameter to decompress, this + # routine will do one yield per IDAT chunk. So not very + # incremental. + d = zlib.decompressobj() + # Each IDAT chunk is passed to the decompressor, then any + # remaining state is decompressed out. + for data in idat: + # :todo: add a max_length argument here to limit output + # size. + yield array("B", d.decompress(data)) + yield array("B", d.flush()) + + self.preamble() + raw = iterdecomp(iteridat()) + + if self.interlace: + raw = array("B", itertools.chain(*raw)) + arraycode = "BH"[self.bitdepth > 8] + # Like :meth:`group` but producing an array.array object for + # each row. + pixels = map( + lambda *row: array(arraycode, row), + *[iter(self.deinterlace(raw))] * self.width * self.planes + ) + else: + pixels = self.iterboxed(self.iterstraight(raw)) + meta = dict() + for attr in "greyscale alpha planes bitdepth interlace".split(): + meta[attr] = getattr(self, attr) + meta["size"] = (self.width, self.height) + for attr in "gamma transparent background".split(): + a = getattr(self, attr, None) + if a is not None: + meta[attr] = a + return self.width, self.height, pixels, meta + + def read_flat(self): + """ + Read a PNG file and decode it into flat row flat pixel format. + Returns (*width*, *height*, *pixels*, *metadata*). + + May use excessive memory. + + `pixels` are returned in flat row flat pixel format. + + See also the :meth:`read` method which returns pixels in the + more stream-friendly boxed row flat pixel format. + """ + + x, y, pixel, meta = self.read() + arraycode = "BH"[meta["bitdepth"] > 8] + pixel = array(arraycode, itertools.chain(*pixel)) + return x, y, pixel, meta + + def palette(self, alpha="natural"): + """Returns a palette that is a sequence of 3-tuples or 4-tuples, + synthesizing it from the ``PLTE`` and ``tRNS`` chunks. These + chunks should have already been processed (for example, by + calling the :meth:`preamble` method). All the tuples are the + same size: 3-tuples if there is no ``tRNS`` chunk, 4-tuples when + there is a ``tRNS`` chunk. Assumes that the image is colour type + 3 and therefore a ``PLTE`` chunk is required. + + If the `alpha` argument is ``'force'`` then an alpha channel is + always added, forcing the result to be a sequence of 4-tuples. + """ + + if not self.plte: + raise FormatError("Required PLTE chunk is missing in colour type 3 image.") + plte = group(array("B", self.plte), 3) + if self.trns or alpha == "force": + trns = array("B", self.trns or "") + trns.extend([255] * (len(plte) - len(trns))) + plte = map(operator.add, plte, group(trns, 1)) + return plte + + def asDirect(self): + """Returns the image data as a direct representation of an + ``x * y * planes`` array. This method is intended to remove the + need for callers to deal with palettes and transparency + themselves. Images with a palette (colour type 3) + are converted to RGB or RGBA; images with transparency (a + ``tRNS`` chunk) are converted to LA or RGBA as appropriate. + When returned in this format the pixel values represent the + colour value directly without needing to refer to palettes or + transparency information. + + Like the :meth:`read` method this method returns a 4-tuple: + + (*width*, *height*, *pixels*, *meta*) + + This method normally returns pixel values with the bit depth + they have in the source image, but when the source PNG has an + ``sBIT`` chunk it is inspected and can reduce the bit depth of + the result pixels; pixel values will be reduced according to + the bit depth specified in the ``sBIT`` chunk (PNG nerds should + note a single result bit depth is used for all channels; the + maximum of the ones specified in the ``sBIT`` chunk. An RGB565 + image will be rescaled to 6-bit RGB666). + + The *meta* dictionary that is returned reflects the `direct` + format and not the original source image. For example, an RGB + source image with a ``tRNS`` chunk to represent a transparent + colour, will have ``planes=3`` and ``alpha=False`` for the + source image, but the *meta* dictionary returned by this method + will have ``planes=4`` and ``alpha=True`` because an alpha + channel is synthesized and added. + + *pixels* is the pixel data in boxed row flat pixel format (just + like the :meth:`read` method). + + All the other aspects of the image data are not changed. + """ + + self.preamble() + + # Simple case, no conversion necessary. + if not self.colormap and not self.trns and not self.sbit: + return self.read() + + x, y, pixels, meta = self.read() + + if self.colormap: + meta["colormap"] = False + meta["alpha"] = bool(self.trns) + meta["bitdepth"] = 8 + meta["planes"] = 3 + bool(self.trns) + plte = self.palette() + + def iterpal(pixels): + for row in pixels: + row = map(plte.__getitem__, row) + yield array("B", itertools.chain(*row)) + + pixels = iterpal(pixels) + elif self.trns: + # It would be nice if there was some reasonable way of doing + # this without generating a whole load of intermediate tuples. + # But tuples does seem like the easiest way, with no other way + # clearly much simpler or much faster. (Actually, the L to LA + # conversion could perhaps go faster (all those 1-tuples!), but + # I still wonder whether the code proliferation is worth it) + it = self.transparent + maxval = 2 ** meta["bitdepth"] - 1 + planes = meta["planes"] + meta["alpha"] = True + meta["planes"] += 1 + typecode = "BH"[meta["bitdepth"] > 8] + + def itertrns(pixels): + for row in pixels: + # For each row we group it into pixels, then form a + # characterisation vector that says whether each pixel + # is opaque or not. Then we convert True/False to + # 0/maxval (by multiplication), and add it as the extra + # channel. + row = group(row, planes) + opa = map(it.__ne__, row) + opa = map(maxval.__mul__, opa) + opa = zip(opa) # convert to 1-tuples + yield array(typecode, itertools.chain(*map(operator.add, row, opa))) + + pixels = itertrns(pixels) + targetbitdepth = None + if self.sbit: + sbit = struct.unpack("%dB" % len(self.sbit), self.sbit) + targetbitdepth = max(sbit) + if targetbitdepth > meta["bitdepth"]: + raise Error("sBIT chunk %r exceeds bitdepth %d" % (sbit, self.bitdepth)) + if min(sbit) <= 0: + raise Error("sBIT chunk %r has a 0-entry" % sbit) + if targetbitdepth == meta["bitdepth"]: + targetbitdepth = None + if targetbitdepth: + shift = meta["bitdepth"] - targetbitdepth + meta["bitdepth"] = targetbitdepth + + def itershift(pixels): + for row in pixels: + yield map(shift.__rrshift__, row) + + pixels = itershift(pixels) + return x, y, pixels, meta + + def asFloat(self, maxval=1.0): + """Return image pixels as per :meth:`asDirect` method, but scale + all pixel values to be floating point values between 0.0 and + *maxval*. + """ + + x, y, pixels, info = self.asDirect() + sourcemaxval = 2 ** info["bitdepth"] - 1 + del info["bitdepth"] + info["maxval"] = float(maxval) + factor = float(maxval) / float(sourcemaxval) + + def iterfloat(): + for row in pixels: + yield map(factor.__mul__, row) + + return x, y, iterfloat(), info + + def _as_rescale(self, get, targetbitdepth): + """Helper used by :meth:`asRGB8` and :meth:`asRGBA8`.""" + + width, height, pixels, meta = get() + maxval = 2 ** meta["bitdepth"] - 1 + targetmaxval = 2 ** targetbitdepth - 1 + factor = float(targetmaxval) / float(maxval) + meta["bitdepth"] = targetbitdepth + + def iterscale(): + for row in pixels: + yield map(lambda x: int(round(x * factor)), row) + + return width, height, iterscale(), meta + + def asRGB8(self): + """Return the image data as an RGB pixels with 8-bits per + sample. This is like the :meth:`asRGB` method except that + this method additionally rescales the values so that they + are all between 0 and 255 (8-bit). In the case where the + source image has a bit depth < 8 the transformation preserves + all the information; where the source image has bit depth + > 8, then rescaling to 8-bit values loses precision. No + dithering is performed. Like :meth:`asRGB`, an alpha channel + in the source image will raise an exception. + + This function returns a 4-tuple: + (*width*, *height*, *pixels*, *metadata*). + *width*, *height*, *metadata* are as per the :meth:`read` method. + + *pixels* is the pixel data in boxed row flat pixel format. + """ + + return self._as_rescale(self.asRGB, 8) + + def asRGBA8(self): + """Return the image data as RGBA pixels with 8-bits per + sample. This method is similar to :meth:`asRGB8` and + :meth:`asRGBA`: The result pixels have an alpha channel, *and* + values are rescaled to the range 0 to 255. The alpha channel is + synthesized if necessary (with a small speed penalty). + """ + + return self._as_rescale(self.asRGBA, 8) + + def asRGB(self): + """Return image as RGB pixels. RGB colour images are passed + through unchanged; greyscales are expanded into RGB + triplets (there is a small speed overhead for doing this). + + An alpha channel in the source image will raise an + exception. + + The return values are as for the :meth:`read` method + except that the *metadata* reflect the returned pixels, not the + source image. In particular, for this method + ``metadata['greyscale']`` will be ``False``. + """ + + width, height, pixels, meta = self.asDirect() + if meta["alpha"]: + raise Error("will not convert image with alpha channel to RGB") + if not meta["greyscale"]: + return width, height, pixels, meta + meta["greyscale"] = False + typecode = "BH"[meta["bitdepth"] > 8] + + def iterrgb(): + for row in pixels: + a = array(typecode, [0]) * 3 * width + for i in range(3): + a[i::3] = row + yield a + + return width, height, iterrgb(), meta + + def asRGBA(self): + """Return image as RGBA pixels. Greyscales are expanded into + RGB triplets; an alpha channel is synthesized if necessary. + The return values are as for the :meth:`read` method + except that the *metadata* reflect the returned pixels, not the + source image. In particular, for this method + ``metadata['greyscale']`` will be ``False``, and + ``metadata['alpha']`` will be ``True``. + """ + + width, height, pixels, meta = self.asDirect() + if meta["alpha"] and not meta["greyscale"]: + return width, height, pixels, meta + typecode = "BH"[meta["bitdepth"] > 8] + maxval = 2 ** meta["bitdepth"] - 1 + + def newarray(): + return array(typecode, [0]) * 4 * width + + if meta["alpha"] and meta["greyscale"]: + # LA to RGBA + def convert(): + for row in pixels: + # Create a fresh target row, then copy L channel + # into first three target channels, and A channel + # into fourth channel. + a = newarray() + for i in range(3): + a[i::4] = row[0::2] + a[3::4] = row[1::2] + yield a + + elif meta["greyscale"]: + # L to RGBA + def convert(): + for row in pixels: + a = newarray() + for i in range(3): + a[i::4] = row + a[3::4] = array(typecode, [maxval]) * width + yield a + + else: + assert not meta["alpha"] and not meta["greyscale"] + # RGB to RGBA + def convert(): + for row in pixels: + a = newarray() + for i in range(3): + a[i::4] = row[i::3] + a[3::4] = array(typecode, [maxval]) * width + yield a + + meta["alpha"] = True + meta["greyscale"] = False + return width, height, convert(), meta + + +# === Internal Test Support === + +# This section comprises the tests that are internally validated (as +# opposed to tests which produce output files that are externally +# validated). Primarily they are unittests. + +# Note that it is difficult to internally validate the results of +# writing a PNG file. The only thing we can do is read it back in +# again, which merely checks consistency, not that the PNG file we +# produce is valid. + +# Run the tests from the command line: +# python -c 'import png;png.test()' + +# (For an in-memory binary file IO object) We use BytesIO where +# available, otherwise we use StringIO, but name it BytesIO. +try: + from io import BytesIO +except: + from StringIO import StringIO as BytesIO +import tempfile +import unittest + + +def test(): + unittest.main(__name__) + + +def topngbytes(name, rows, x, y, **k): + """Convenience function for creating a PNG file "in memory" as a + string. Creates a :class:`Writer` instance using the keyword arguments, + then passes `rows` to its :meth:`Writer.write` method. The resulting + PNG file is returned as a string. `name` is used to identify the file for + debugging. + """ + + import os + + print(name) + f = BytesIO() + w = Writer(x, y, **k) + w.write(f, rows) + if os.environ.get("PYPNG_TEST_TMP"): + w = open(name, "wb") + w.write(f.getvalue()) + w.close() + return f.getvalue() + + +def testWithIO(inp, out, f): + """Calls the function `f` with ``sys.stdin`` changed to `inp` + and ``sys.stdout`` changed to `out`. They are restored when `f` + returns. This function returns whatever `f` returns. + """ + + import os + + try: + oldin, sys.stdin = sys.stdin, inp + oldout, sys.stdout = sys.stdout, out + x = f() + finally: + sys.stdin = oldin + sys.stdout = oldout + if os.environ.get("PYPNG_TEST_TMP") and hasattr(out, "getvalue"): + name = mycallersname() + if name: + w = open(name + ".png", "wb") + w.write(out.getvalue()) + w.close() + return x + + +def mycallersname(): + """Returns the name of the caller of the caller of this function + (hence the name of the caller of the function in which + "mycallersname()" textually appears). Returns None if this cannot + be determined.""" + + # http://docs.python.org/library/inspect.html#the-interpreter-stack + import inspect + + frame = inspect.currentframe() + if not frame: + return None + frame_, filename_, lineno_, funname, linelist_, listi_ = inspect.getouterframes( + frame + )[2] + return funname + + +def seqtobytes(s): + """Convert a sequence of integers to a *bytes* instance. Good for + plastering over Python 2 / Python 3 cracks. + """ + + return strtobytes("".join(chr(x) for x in s)) + + +class Test(unittest.TestCase): + # This member is used by the superclass. If we don't define a new + # class here then when we use self.assertRaises() and the PyPNG code + # raises an assertion then we get no proper traceback. I can't work + # out why, but defining a new class here means we get a proper + # traceback. + class failureException(Exception): + pass + + def helperLN(self, n): + mask = (1 << n) - 1 + # Use small chunk_limit so that multiple chunk writing is + # tested. Making it a test for Issue 20. + w = Writer(15, 17, greyscale=True, bitdepth=n, chunk_limit=99) + f = BytesIO() + w.write_array(f, array("B", map(mask.__and__, range(1, 256)))) + r = Reader(bytes=f.getvalue()) + x, y, pixels, meta = r.read() + self.assertEqual(x, 15) + self.assertEqual(y, 17) + self.assertEqual( + list(itertools.chain(*pixels)), map(mask.__and__, range(1, 256)) + ) + + def testL8(self): + return self.helperLN(8) + + def testL4(self): + return self.helperLN(4) + + def testL2(self): + "Also tests asRGB8." + w = Writer(1, 4, greyscale=True, bitdepth=2) + f = BytesIO() + w.write_array(f, array("B", range(4))) + r = Reader(bytes=f.getvalue()) + x, y, pixels, meta = r.asRGB8() + self.assertEqual(x, 1) + self.assertEqual(y, 4) + for i, row in enumerate(pixels): + self.assertEqual(len(row), 3) + self.assertEqual(list(row), [0x55 * i] * 3) + + def testP2(self): + "2-bit palette." + a = (255, 255, 255) + b = (200, 120, 120) + c = (50, 99, 50) + w = Writer(1, 4, bitdepth=2, palette=[a, b, c]) + f = BytesIO() + w.write_array(f, array("B", (0, 1, 1, 2))) + r = Reader(bytes=f.getvalue()) + x, y, pixels, meta = r.asRGB8() + self.assertEqual(x, 1) + self.assertEqual(y, 4) + self.assertEqual(list(pixels), map(list, [a, b, b, c])) + + def testPtrns(self): + "Test colour type 3 and tRNS chunk (and 4-bit palette)." + a = (50, 99, 50, 50) + b = (200, 120, 120, 80) + c = (255, 255, 255) + d = (200, 120, 120) + e = (50, 99, 50) + w = Writer(3, 3, bitdepth=4, palette=[a, b, c, d, e]) + f = BytesIO() + w.write_array(f, array("B", (4, 3, 2, 3, 2, 0, 2, 0, 1))) + r = Reader(bytes=f.getvalue()) + x, y, pixels, meta = r.asRGBA8() + self.assertEqual(x, 3) + self.assertEqual(y, 3) + c = c + (255,) + d = d + (255,) + e = e + (255,) + boxed = [(e, d, c), (d, c, a), (c, a, b)] + flat = map(lambda row: itertools.chain(*row), boxed) + self.assertEqual(map(list, pixels), map(list, flat)) + + def testRGBtoRGBA(self): + "asRGBA8() on colour type 2 source." "" + # Test for Issue 26 + r = Reader(bytes=_pngsuite["basn2c08"]) + x, y, pixels, meta = r.asRGBA8() + # Test the pixels at row 9 columns 0 and 1. + row9 = list(pixels)[9] + self.assertEqual(row9[0:8], [0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xDE, 0xFF, 0xFF]) + + def testLtoRGBA(self): + "asRGBA() on grey source." "" + # Test for Issue 60 + r = Reader(bytes=_pngsuite["basi0g08"]) + x, y, pixels, meta = r.asRGBA() + row9 = list(list(pixels)[9]) + self.assertEqual(row9[0:8], [222, 222, 222, 255, 221, 221, 221, 255]) + + def testCtrns(self): + "Test colour type 2 and tRNS chunk." + # Test for Issue 25 + r = Reader(bytes=_pngsuite["tbrn2c08"]) + x, y, pixels, meta = r.asRGBA8() + # I just happen to know that the first pixel is transparent. + # In particular it should be #7f7f7f00 + row0 = list(pixels)[0] + self.assertEqual(tuple(row0[0:4]), (0x7F, 0x7F, 0x7F, 0x00)) + + def testAdam7read(self): + """Adam7 interlace reading. + Specifically, test that for images in the PngSuite that + have both an interlaced and straightlaced pair that both + images from the pair produce the same array of pixels.""" + for candidate in _pngsuite: + if not candidate.startswith("basn"): + continue + candi = candidate.replace("n", "i") + if candi not in _pngsuite: + continue + print("adam7 read %s" % (candidate,)) + straight = Reader(bytes=_pngsuite[candidate]) + adam7 = Reader(bytes=_pngsuite[candi]) + # Just compare the pixels. Ignore x,y (because they're + # likely to be correct?); metadata is ignored because the + # "interlace" member differs. Lame. + straight = straight.read()[2] + adam7 = adam7.read()[2] + self.assertEqual(map(list, straight), map(list, adam7)) + + def testAdam7write(self): + """Adam7 interlace writing. + For each test image in the PngSuite, write an interlaced + and a straightlaced version. Decode both, and compare results. + """ + # Not such a great test, because the only way we can check what + # we have written is to read it back again. + + for name, bytes in _pngsuite.items(): + # Only certain colour types supported for this test. + if name[3:5] not in ["n0", "n2", "n4", "n6"]: + continue + it = Reader(bytes=bytes) + x, y, pixels, meta = it.read() + pngi = topngbytes( + "adam7wn" + name + ".png", + pixels, + x=x, + y=y, + bitdepth=it.bitdepth, + greyscale=it.greyscale, + alpha=it.alpha, + transparent=it.transparent, + interlace=False, + ) + x, y, ps, meta = Reader(bytes=pngi).read() + it = Reader(bytes=bytes) + x, y, pixels, meta = it.read() + pngs = topngbytes( + "adam7wi" + name + ".png", + pixels, + x=x, + y=y, + bitdepth=it.bitdepth, + greyscale=it.greyscale, + alpha=it.alpha, + transparent=it.transparent, + interlace=True, + ) + x, y, pi, meta = Reader(bytes=pngs).read() + self.assertEqual(map(list, ps), map(list, pi)) + + def testPGMin(self): + """Test that the command line tool can read PGM files.""" + + def do(): + return _main(["testPGMin"]) + + s = BytesIO() + s.write(strtobytes("P5 2 2 3\n")) + s.write(strtobytes("\x00\x01\x02\x03")) + s.flush() + s.seek(0) + o = BytesIO() + testWithIO(s, o, do) + r = Reader(bytes=o.getvalue()) + x, y, pixels, meta = r.read() + self.assertTrue(r.greyscale) + self.assertEqual(r.bitdepth, 2) + + def testPAMin(self): + """Test that the command line tool can read PAM file.""" + + def do(): + return _main(["testPAMin"]) + + s = BytesIO() + s.write( + strtobytes( + "P7\nWIDTH 3\nHEIGHT 1\nDEPTH 4\nMAXVAL 255\n" + "TUPLTYPE RGB_ALPHA\nENDHDR\n" + ) + ) + # The pixels in flat row flat pixel format + flat = [255, 0, 0, 255, 0, 255, 0, 120, 0, 0, 255, 30] + asbytes = seqtobytes(flat) + s.write(asbytes) + s.flush() + s.seek(0) + o = BytesIO() + testWithIO(s, o, do) + r = Reader(bytes=o.getvalue()) + x, y, pixels, meta = r.read() + self.assertTrue(r.alpha) + self.assertTrue(not r.greyscale) + self.assertEqual(list(itertools.chain(*pixels)), flat) + + def testLA4(self): + """Create an LA image with bitdepth 4.""" + bytes = topngbytes( + "la4.png", [[5, 12]], 1, 1, greyscale=True, alpha=True, bitdepth=4 + ) + sbit = Reader(bytes=bytes).chunk("sBIT")[1] + self.assertEqual(sbit, strtobytes("\x04\x04")) + + def testPNMsbit(self): + """Test that PNM files can generates sBIT chunk.""" + + def do(): + return _main(["testPNMsbit"]) + + s = BytesIO() + s.write(strtobytes("P6 8 1 1\n")) + for pixel in range(8): + s.write(struct.pack(" 255: + a = array("H") + else: + a = array("B") + fw = float(width) + fh = float(height) + pfun = test_patterns[pattern] + for y in range(height): + fy = float(y) / fh + for x in range(width): + a.append(int(round(pfun(float(x) / fw, fy) * maxval))) + return a + + def test_rgba(size=256, bitdepth=8, red="GTB", green="GLR", blue="RTL", alpha=None): + """ + Create a test image. Each channel is generated from the + specified pattern; any channel apart from red can be set to + None, which will cause it not to be in the image. It + is possible to create all PNG channel types (L, RGB, LA, RGBA), + as well as non PNG channel types (RGA, and so on). + """ + + i = test_pattern(size, size, bitdepth, red) + psize = 1 + for channel in (green, blue, alpha): + if channel: + c = test_pattern(size, size, bitdepth, channel) + i = interleave_planes(i, c, psize, 1) + psize += 1 + return i + + def pngsuite_image(name): + """ + Create a test image by reading an internal copy of the files + from the PngSuite. Returned in flat row flat pixel format. + """ + + if name not in _pngsuite: + raise NotImplementedError( + "cannot find PngSuite file %s (use -L for a list)" % name + ) + r = Reader(bytes=_pngsuite[name]) + w, h, pixels, meta = r.asDirect() + assert w == h + # LAn for n < 8 is a special case for which we need to rescale + # the data. + if meta["greyscale"] and meta["alpha"] and meta["bitdepth"] < 8: + factor = 255 // (2 ** meta["bitdepth"] - 1) + + def rescale(data): + for row in data: + yield map(factor.__mul__, row) + + pixels = rescale(pixels) + meta["bitdepth"] = 8 + arraycode = "BH"[meta["bitdepth"] > 8] + return w, array(arraycode, itertools.chain(*pixels)), meta + + # The body of test_suite() + size = 256 + if options.test_size: + size = options.test_size + options.bitdepth = options.test_depth + options.greyscale = bool(options.test_black) + + kwargs = {} + if options.test_red: + kwargs["red"] = options.test_red + if options.test_green: + kwargs["green"] = options.test_green + if options.test_blue: + kwargs["blue"] = options.test_blue + if options.test_alpha: + kwargs["alpha"] = options.test_alpha + if options.greyscale: + if options.test_red or options.test_green or options.test_blue: + raise ValueError( + "cannot specify colours (R, G, B) when greyscale image (black channel, K) is specified" + ) + kwargs["red"] = options.test_black + kwargs["green"] = None + kwargs["blue"] = None + options.alpha = bool(options.test_alpha) + if not args: + pixels = test_rgba(size, options.bitdepth, **kwargs) + else: + size, pixels, meta = pngsuite_image(args[0]) + for k in ["bitdepth", "alpha", "greyscale"]: + setattr(options, k, meta[k]) + + writer = Writer( + size, + size, + bitdepth=options.bitdepth, + transparent=options.transparent, + background=options.background, + gamma=options.gamma, + greyscale=options.greyscale, + alpha=options.alpha, + compression=options.compression, + interlace=options.interlace, + ) + writer.write_array(sys.stdout, pixels) + + +def read_pam_header(infile): + """ + Read (the rest of a) PAM header. `infile` should be positioned + immediately after the initial 'P7' line (at the beginning of the + second line). Returns are as for `read_pnm_header`. + """ + + # Unlike PBM, PGM, and PPM, we can read the header a line at a time. + header = dict() + while True: + l = infile.readline().strip() + if l == strtobytes("ENDHDR"): + break + if not l: + raise EOFError("PAM ended prematurely") + if l[0] == strtobytes("#"): + continue + l = l.split(None, 1) + if l[0] not in header: + header[l[0]] = l[1] + else: + header[l[0]] += strtobytes(" ") + l[1] + + required = ["WIDTH", "HEIGHT", "DEPTH", "MAXVAL"] + required = [strtobytes(x) for x in required] + WIDTH, HEIGHT, DEPTH, MAXVAL = required + present = [x for x in required if x in header] + if len(present) != len(required): + raise Error("PAM file must specify WIDTH, HEIGHT, DEPTH, and MAXVAL") + width = int(header[WIDTH]) + height = int(header[HEIGHT]) + depth = int(header[DEPTH]) + maxval = int(header[MAXVAL]) + if width <= 0 or height <= 0 or depth <= 0 or maxval <= 0: + raise Error("WIDTH, HEIGHT, DEPTH, MAXVAL must all be positive integers") + return "P7", width, height, depth, maxval + + +def read_pnm_header(infile, supported=("P5", "P6")): + """ + Read a PNM header, returning (format,width,height,depth,maxval). + `width` and `height` are in pixels. `depth` is the number of + channels in the image; for PBM and PGM it is synthesized as 1, for + PPM as 3; for PAM images it is read from the header. `maxval` is + synthesized (as 1) for PBM images. + """ + + # Generally, see http://netpbm.sourceforge.net/doc/ppm.html + # and http://netpbm.sourceforge.net/doc/pam.html + + supported = [strtobytes(x) for x in supported] + + # Technically 'P7' must be followed by a newline, so by using + # rstrip() we are being liberal in what we accept. I think this + # is acceptable. + type = infile.read(3).rstrip() + if type not in supported: + raise NotImplementedError("file format %s not supported" % type) + if type == strtobytes("P7"): + # PAM header parsing is completely different. + return read_pam_header(infile) + # Expected number of tokens in header (3 for P4, 4 for P6) + expected = 4 + pbm = ("P1", "P4") + if type in pbm: + expected = 3 + header = [type] + + # We have to read the rest of the header byte by byte because the + # final whitespace character (immediately following the MAXVAL in + # the case of P6) may not be a newline. Of course all PNM files in + # the wild use a newline at this point, so it's tempting to use + # readline; but it would be wrong. + def getc(): + c = infile.read(1) + if not c: + raise Error("premature EOF reading PNM header") + return c + + c = getc() + while True: + # Skip whitespace that precedes a token. + while c.isspace(): + c = getc() + # Skip comments. + while c == "#": + while c not in "\n\r": + c = getc() + if not c.isdigit(): + raise Error("unexpected character %s found in header" % c) + # According to the specification it is legal to have comments + # that appear in the middle of a token. + # This is bonkers; I've never seen it; and it's a bit awkward to + # code good lexers in Python (no goto). So we break on such + # cases. + token = strtobytes("") + while c.isdigit(): + token += c + c = getc() + # Slight hack. All "tokens" are decimal integers, so convert + # them here. + header.append(int(token)) + if len(header) == expected: + break + # Skip comments (again) + while c == "#": + while c not in "\n\r": + c = getc() + if not c.isspace(): + raise Error("expected header to end with whitespace, not %s" % c) + + if type in pbm: + # synthesize a MAXVAL + header.append(1) + depth = (1, 3)[type == strtobytes("P6")] + return header[0], header[1], header[2], depth, header[3] + + +def write_pnm(file, width, height, pixels, meta): + """Write a Netpbm PNM/PAM file.""" + + bitdepth = meta["bitdepth"] + maxval = 2 ** bitdepth - 1 + # Rudely, the number of image planes can be used to determine + # whether we are L (PGM), LA (PAM), RGB (PPM), or RGBA (PAM). + planes = meta["planes"] + # Can be an assert as long as we assume that pixels and meta came + # from a PNG file. + assert planes in (1, 2, 3, 4) + if planes in (1, 3): + if 1 == planes: + # PGM + # Could generate PBM if maxval is 1, but we don't (for one + # thing, we'd have to convert the data, not just blat it + # out). + fmt = "P5" + else: + # PPM + fmt = "P6" + file.write("%s %d %d %d\n" % (fmt, width, height, maxval)) + if planes in (2, 4): + # PAM + # See http://netpbm.sourceforge.net/doc/pam.html + if 2 == planes: + tupltype = "GRAYSCALE_ALPHA" + else: + tupltype = "RGB_ALPHA" + file.write( + "P7\nWIDTH %d\nHEIGHT %d\nDEPTH %d\nMAXVAL %d\n" + "TUPLTYPE %s\nENDHDR\n" % (width, height, planes, maxval, tupltype) + ) + # Values per row + vpr = planes * width + # struct format + fmt = ">%d" % vpr + if maxval > 0xFF: + fmt = fmt + "H" + else: + fmt = fmt + "B" + for row in pixels: + file.write(struct.pack(fmt, *row)) + file.flush() + + +def color_triple(color): + """ + Convert a command line colour value to a RGB triple of integers. + FIXME: Somewhere we need support for greyscale backgrounds etc. + """ + if color.startswith("#") and len(color) == 4: + return (int(color[1], 16), int(color[2], 16), int(color[3], 16)) + if color.startswith("#") and len(color) == 7: + return (int(color[1:3], 16), int(color[3:5], 16), int(color[5:7], 16)) + elif color.startswith("#") and len(color) == 13: + return (int(color[1:5], 16), int(color[5:9], 16), int(color[9:13], 16)) + + +def _main(argv): + """ + Run the PNG encoder with options from the command line. + """ + + # Parse command line arguments + from optparse import OptionParser + import re + + version = "%prog " + re.sub(r"( ?\$|URL: |Rev:)", "", __version__) + parser = OptionParser(version=version) + parser.set_usage("%prog [options] [imagefile]") + parser.add_option( + "-r", + "--read-png", + default=False, + action="store_true", + help="Read PNG, write PNM", + ) + parser.add_option( + "-i", + "--interlace", + default=False, + action="store_true", + help="create an interlaced PNG file (Adam7)", + ) + parser.add_option( + "-t", + "--transparent", + action="store", + type="string", + metavar="color", + help="mark the specified colour (#RRGGBB) as transparent", + ) + parser.add_option( + "-b", + "--background", + action="store", + type="string", + metavar="color", + help="save the specified background colour", + ) + parser.add_option( + "-a", + "--alpha", + action="store", + type="string", + metavar="pgmfile", + help="alpha channel transparency (RGBA)", + ) + parser.add_option( + "-g", + "--gamma", + action="store", + type="float", + metavar="value", + help="save the specified gamma value", + ) + parser.add_option( + "-c", + "--compression", + action="store", + type="int", + metavar="level", + help="zlib compression level (0-9)", + ) + parser.add_option( + "-T", + "--test", + default=False, + action="store_true", + help="create a test image (a named PngSuite image if an argument is supplied)", + ) + parser.add_option( + "-L", + "--list", + default=False, + action="store_true", + help="print list of named test images", + ) + parser.add_option( + "-R", + "--test-red", + action="store", + type="string", + metavar="pattern", + help="test pattern for the red image layer", + ) + parser.add_option( + "-G", + "--test-green", + action="store", + type="string", + metavar="pattern", + help="test pattern for the green image layer", + ) + parser.add_option( + "-B", + "--test-blue", + action="store", + type="string", + metavar="pattern", + help="test pattern for the blue image layer", + ) + parser.add_option( + "-A", + "--test-alpha", + action="store", + type="string", + metavar="pattern", + help="test pattern for the alpha image layer", + ) + parser.add_option( + "-K", + "--test-black", + action="store", + type="string", + metavar="pattern", + help="test pattern for greyscale image", + ) + parser.add_option( + "-d", + "--test-depth", + default=8, + action="store", + type="int", + metavar="NBITS", + help="create test PNGs that are NBITS bits per channel", + ) + parser.add_option( + "-S", + "--test-size", + action="store", + type="int", + metavar="size", + help="width and height of the test image", + ) + (options, args) = parser.parse_args(args=argv[1:]) + + # Convert options + if options.transparent is not None: + options.transparent = color_triple(options.transparent) + if options.background is not None: + options.background = color_triple(options.background) + + if options.list: + names = list(_pngsuite) + names.sort() + for name in names: + print(name) + return + + # Run regression tests + if options.test: + return test_suite(options, args) + + # Prepare input and output files + if len(args) == 0: + infilename = "-" + infile = sys.stdin + elif len(args) == 1: + infilename = args[0] + infile = open(infilename, "rb") + else: + parser.error("more than one input file") + outfile = sys.stdout + + if options.read_png: + # Encode PNG to PPM + png = Reader(file=infile) + width, height, pixels, meta = png.asDirect() + write_pnm(outfile, width, height, pixels, meta) + else: + # Encode PNM to PNG + format, width, height, depth, maxval = read_pnm_header( + infile, ("P5", "P6", "P7") + ) + # When it comes to the variety of input formats, we do something + # rather rude. Observe that L, LA, RGB, RGBA are the 4 colour + # types supported by PNG and that they correspond to 1, 2, 3, 4 + # channels respectively. So we use the number of channels in + # the source image to determine which one we have. We do not + # care about TUPLTYPE. + greyscale = depth <= 2 + pamalpha = depth in (2, 4) + supported = map(lambda x: 2 ** x - 1, range(1, 17)) + try: + mi = supported.index(maxval) + except ValueError: + raise NotImplementedError( + "your maxval (%s) not in supported list %s" % (maxval, str(supported)) + ) + bitdepth = mi + 1 + writer = Writer( + width, + height, + greyscale=greyscale, + bitdepth=bitdepth, + interlace=options.interlace, + transparent=options.transparent, + background=options.background, + alpha=bool(pamalpha or options.alpha), + gamma=options.gamma, + compression=options.compression, + ) + if options.alpha: + pgmfile = open(options.alpha, "rb") + format, awidth, aheight, adepth, amaxval = read_pnm_header(pgmfile, "P5") + if amaxval != "255": + raise NotImplementedError( + "maxval %s not supported for alpha channel" % amaxval + ) + if (awidth, aheight) != (width, height): + raise ValueError( + "alpha channel image size mismatch" + " (%s has %sx%s but %s has %sx%s)" + % (infilename, width, height, options.alpha, awidth, aheight) + ) + writer.convert_ppm_and_pgm(infile, pgmfile, outfile) + else: + writer.convert_pnm(infile, outfile) + + +if __name__ == "__main__": + try: + _main(sys.argv) + except Error as e: + sys.stderr.write("%s\n" % (e,)) diff --git a/venv/Lib/site-packages/pygame/tests/test_utils/run_tests.py b/venv/Lib/site-packages/pygame/tests/test_utils/run_tests.py new file mode 100644 index 0000000..a193e23 --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/test_utils/run_tests.py @@ -0,0 +1,350 @@ +import sys + +if __name__ == "__main__": + sys.exit("This module is for import only") + +test_pkg_name = ".".join(__name__.split(".")[0:-2]) +is_pygame_pkg = test_pkg_name == "pygame.tests" +test_runner_mod = test_pkg_name + ".test_utils.test_runner" + +if is_pygame_pkg: + from pygame.tests.test_utils import import_submodule + from pygame.tests.test_utils.test_runner import ( + prepare_test_env, + run_test, + combine_results, + get_test_results, + TEST_RESULTS_START, + ) +else: + from test.test_utils import import_submodule + from test.test_utils.test_runner import ( + prepare_test_env, + run_test, + combine_results, + get_test_results, + TEST_RESULTS_START, + ) +import pygame +import pygame.threads + +import os +import re +import shutil +import tempfile +import time +import random +from pprint import pformat + +was_run = False + + +def run(*args, **kwds): + """Run the Pygame unit test suite and return (total tests run, fails dict) + + Positional arguments (optional): + The names of tests to include. If omitted then all tests are run. Test + names need not include the trailing '_test'. + + Keyword arguments: + incomplete - fail incomplete tests (default False) + usesubprocess - run all test suites in the current process + (default False, use separate subprocesses) + dump - dump failures/errors as dict ready to eval (default False) + file - if provided, the name of a file into which to dump failures/errors + timings - if provided, the number of times to run each individual test to + get an average run time (default is run each test once) + exclude - A list of TAG names to exclude from the run. The items may be + comma or space separated. + show_output - show silenced stderr/stdout on errors (default False) + all - dump all results, not just errors (default False) + randomize - randomize order of tests (default False) + seed - if provided, a seed randomizer integer + multi_thread - if provided, the number of THREADS in which to run + subprocessed tests + time_out - if subprocess is True then the time limit in seconds before + killing a test (default 30) + fake - if provided, the name of the fake tests package in the + run_tests__tests subpackage to run instead of the normal + Pygame tests + python - the path to a python executable to run subprocessed tests + (default sys.executable) + interative - allow tests tagged 'interative'. + + Return value: + A tuple of total number of tests run, dictionary of error information. The + dictionary is empty if no errors were recorded. + + By default individual test modules are run in separate subprocesses. This + recreates normal Pygame usage where pygame.init() and pygame.quit() are + called only once per program execution, and avoids unfortunate + interactions between test modules. Also, a time limit is placed on test + execution, so frozen tests are killed when there time allotment expired. + Use the single process option if threading is not working properly or if + tests are taking too long. It is not guaranteed that all tests will pass + in single process mode. + + Tests are run in a randomized order if the randomize argument is True or a + seed argument is provided. If no seed integer is provided then the system + time is used. + + Individual test modules may have a corresponding *_tags.py module, + defining a __tags__ attribute, a list of tag strings used to selectively + omit modules from a run. By default only the 'interactive', 'ignore', and + 'subprocess_ignore' tags are ignored. 'interactive' is for modules that + take user input, like cdrom_test.py. 'ignore' and 'subprocess_ignore' for + for disabling modules for foreground and subprocess modes respectively. + These are for disabling tests on optional modules or for experimental + modules with known problems. These modules can be run from the console as + a Python program. + + This function can only be called once per Python session. It is not + reentrant. + + """ + + global was_run + + if was_run: + raise RuntimeError("run() was already called this session") + was_run = True + + options = kwds.copy() + option_usesubprocess = options.get("usesubprocess", False) + option_dump = options.pop("dump", False) + option_file = options.pop("file", None) + option_randomize = options.get("randomize", False) + option_seed = options.get("seed", None) + option_multi_thread = options.pop("multi_thread", 1) + option_time_out = options.pop("time_out", 120) + option_fake = options.pop("fake", None) + option_python = options.pop("python", sys.executable) + option_exclude = options.pop("exclude", ()) + option_interactive = options.pop("interactive", False) + + if not option_interactive and "interactive" not in option_exclude: + option_exclude += ("interactive",) + if option_usesubprocess and "subprocess_ignore" not in option_exclude: + option_exclude += ("subprocess_ignore",) + elif "ignore" not in option_exclude: + option_exclude += ("ignore",) + + option_exclude += ("python3_ignore",) + option_exclude += ("SDL2_ignore",) + + main_dir, test_subdir, fake_test_subdir = prepare_test_env() + + ########################################################################### + # Compile a list of test modules. If fake, then compile list of fake + # xxxx_test.py from run_tests__tests + + TEST_MODULE_RE = re.compile(r"^(.+_test)\.py$") + + test_mods_pkg_name = test_pkg_name + + working_dir_temp = tempfile.mkdtemp() + + if option_fake is not None: + test_mods_pkg_name = ".".join( + [test_mods_pkg_name, "run_tests__tests", option_fake] + ) + test_subdir = os.path.join(fake_test_subdir, option_fake) + working_dir = test_subdir + else: + working_dir = working_dir_temp + + # Added in because some machines will need os.environ else there will be + # false failures in subprocess mode. Same issue as python2.6. Needs some + # env vars. + + test_env = os.environ + + fmt1 = "%s.%%s" % test_mods_pkg_name + fmt2 = "%s.%%s_test" % test_mods_pkg_name + if args: + test_modules = [m.endswith("_test") and (fmt1 % m) or (fmt2 % m) for m in args] + else: + test_modules = [] + for f in sorted(os.listdir(test_subdir)): + for match in TEST_MODULE_RE.findall(f): + test_modules.append(fmt1 % (match,)) + + ########################################################################### + # Remove modules to be excluded. + + tmp = test_modules + test_modules = [] + for name in tmp: + tag_module_name = "%s_tags" % (name[0:-5],) + try: + tag_module = import_submodule(tag_module_name) + except ImportError: + test_modules.append(name) + else: + try: + tags = tag_module.__tags__ + except AttributeError: + print("%s has no tags: ignoring" % (tag_module_name,)) + test_modules.append(name) + else: + for tag in tags: + if tag in option_exclude: + print("skipping %s (tag '%s')" % (name, tag)) + break + else: + test_modules.append(name) + del tmp, tag_module_name, name + + ########################################################################### + # Meta results + + results = {} + meta_results = {"__meta__": {}} + meta = meta_results["__meta__"] + + ########################################################################### + # Randomization + + if option_randomize or option_seed is not None: + if option_seed is None: + option_seed = time.time() + meta["random_seed"] = option_seed + print("\nRANDOM SEED USED: %s\n" % option_seed) + random.seed(option_seed) + random.shuffle(test_modules) + + ########################################################################### + # Single process mode + + if not option_usesubprocess: + options["exclude"] = option_exclude + t = time.time() + for module in test_modules: + results.update(run_test(module, **options)) + t = time.time() - t + + ########################################################################### + # Subprocess mode + # + + else: + if is_pygame_pkg: + from pygame.tests.test_utils.async_sub import proc_in_time_or_kill + else: + from test.test_utils.async_sub import proc_in_time_or_kill + + pass_on_args = ["--exclude", ",".join(option_exclude)] + for field in ["randomize", "incomplete", "unbuffered", "verbosity"]: + if kwds.get(field, False): + pass_on_args.append("--" + field) + + def sub_test(module): + print("loading %s" % module) + + cmd = [option_python, "-m", test_runner_mod, module] + pass_on_args + + return ( + module, + (cmd, test_env, working_dir), + proc_in_time_or_kill( + cmd, option_time_out, env=test_env, wd=working_dir + ), + ) + + if option_multi_thread > 1: + + def tmap(f, args): + return pygame.threads.tmap( + f, args, stop_on_error=False, num_workers=option_multi_thread + ) + + else: + tmap = map + + t = time.time() + + for module, cmd, (return_code, raw_return) in tmap(sub_test, test_modules): + test_file = "%s.py" % os.path.join(test_subdir, module) + cmd, test_env, working_dir = cmd + + test_results = get_test_results(raw_return) + if test_results: + results.update(test_results) + else: + results[module] = {} + + results[module].update( + dict( + return_code=return_code, + raw_return=raw_return, + cmd=cmd, + test_file=test_file, + test_env=test_env, + working_dir=working_dir, + module=module, + ) + ) + + t = time.time() - t + + ########################################################################### + # Output Results + # + + untrusty_total, combined = combine_results(results, t) + total, n_errors, n_failures = count_results(results) + + meta["total_tests"] = total + meta["combined"] = combined + meta["total_errors"] = n_errors + meta["total_failures"] = n_failures + results.update(meta_results) + + if not option_usesubprocess and total != untrusty_total: + raise AssertionError( + "Something went wrong in the Test Machinery:\n" + "total: %d != untrusty_total: %d" % (total, untrusty_total) + ) + + if not option_dump: + print(combined) + else: + print(TEST_RESULTS_START) + print(pformat(results)) + + if option_file is not None: + results_file = open(option_file, "w") + try: + results_file.write(pformat(results)) + finally: + results_file.close() + + shutil.rmtree(working_dir_temp) + + return total, n_errors + n_failures + + +def count_results(results): + total = errors = failures = 0 + for result in results.values(): + if result.get("return_code", 0): + total += 1 + errors += 1 + else: + total += result["num_tests"] + errors += result["num_errors"] + failures += result["num_failures"] + + return total, errors, failures + + +def run_and_exit(*args, **kwargs): + """Run the tests, and if there are failures, exit with a return code of 1. + + This is needed for various buildbots to recognise that the tests have + failed. + """ + total, fails = run(*args, **kwargs) + if fails: + sys.exit(1) + sys.exit(0) diff --git a/venv/Lib/site-packages/pygame/tests/test_utils/test_machinery.py b/venv/Lib/site-packages/pygame/tests/test_utils/test_machinery.py new file mode 100644 index 0000000..114c281 --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/test_utils/test_machinery.py @@ -0,0 +1,89 @@ +import inspect +import random +import re +import unittest + +try: + from StringIO import StringIO +except ImportError: + from io import StringIO + +from . import import_submodule + + +class PygameTestLoader(unittest.TestLoader): + def __init__( + self, randomize_tests=False, include_incomplete=False, exclude=("interactive",) + ): + super(PygameTestLoader, self).__init__() + self.randomize_tests = randomize_tests + + if exclude is None: + self.exclude = set() + else: + self.exclude = set(exclude) + + if include_incomplete: + self.testMethodPrefix = ("test", "todo_") + + def getTestCaseNames(self, testCaseClass): + res = [] + for name in super(PygameTestLoader, self).getTestCaseNames(testCaseClass): + tags = get_tags(testCaseClass, getattr(testCaseClass, name)) + if self.exclude.isdisjoint(tags): + res.append(name) + + if self.randomize_tests: + random.shuffle(res) + + return res + + +# Exclude by tags: + +TAGS_RE = re.compile(r"\|[tT]ags:(-?[ a-zA-Z,0-9_\n]+)\|", re.M) + + +class TestTags: + def __init__(self): + self.memoized = {} + self.parent_modules = {} + + def get_parent_module(self, class_): + if class_ not in self.parent_modules: + self.parent_modules[class_] = import_submodule(class_.__module__) + return self.parent_modules[class_] + + def __call__(self, parent_class, meth): + key = (parent_class, meth.__name__) + if key not in self.memoized: + parent_module = self.get_parent_module(parent_class) + + module_tags = getattr(parent_module, "__tags__", []) + class_tags = getattr(parent_class, "__tags__", []) + + tags = TAGS_RE.search(inspect.getdoc(meth) or "") + if tags: + test_tags = [t.strip() for t in tags.group(1).split(",")] + else: + test_tags = [] + + combined = set() + for tags in (module_tags, class_tags, test_tags): + if not tags: + continue + + add = set([t for t in tags if not t.startswith("-")]) + remove = set([t[1:] for t in tags if t not in add]) + + if add: + combined.update(add) + if remove: + combined.difference_update(remove) + + self.memoized[key] = combined + + return self.memoized[key] + + +get_tags = TestTags() diff --git a/venv/Lib/site-packages/pygame/tests/test_utils/test_runner.py b/venv/Lib/site-packages/pygame/tests/test_utils/test_runner.py new file mode 100644 index 0000000..4c35221 --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/test_utils/test_runner.py @@ -0,0 +1,330 @@ +import sys +import os + +if __name__ == "__main__": + pkg_dir = os.path.split(os.path.split(os.path.abspath(__file__))[0])[0] + parent_dir, pkg_name = os.path.split(pkg_dir) + is_pygame_pkg = pkg_name == "tests" and os.path.split(parent_dir)[1] == "pygame" + if not is_pygame_pkg: + sys.path.insert(0, parent_dir) +else: + is_pygame_pkg = __name__.startswith("pygame.tests.") + +import unittest +from .test_machinery import PygameTestLoader + +import re + +try: + import StringIO +except ImportError: + import io as StringIO + +import optparse +from pprint import pformat + + +def prepare_test_env(): + test_subdir = os.path.split(os.path.split(os.path.abspath(__file__))[0])[0] + main_dir = os.path.split(test_subdir)[0] + sys.path.insert(0, test_subdir) + fake_test_subdir = os.path.join(test_subdir, "run_tests__tests") + return main_dir, test_subdir, fake_test_subdir + + +main_dir, test_subdir, fake_test_subdir = prepare_test_env() + +################################################################################ +# Set the command line options +# +# options are shared with run_tests.py so make sure not to conflict +# in time more will be added here + +TAG_PAT = r"-?[a-zA-Z0-9_]+" +TAG_RE = re.compile(TAG_PAT) +EXCLUDE_RE = re.compile(r"(%s,?\s*)+$" % (TAG_PAT,)) + + +def exclude_callback(option, opt, value, parser): + if EXCLUDE_RE.match(value) is None: + raise optparse.OptionValueError("%s argument has invalid value" % (opt,)) + parser.values.exclude = TAG_RE.findall(value) + + +opt_parser = optparse.OptionParser() + +opt_parser.add_option( + "-i", "--incomplete", action="store_true", help="fail incomplete tests" +) + +opt_parser.add_option( + "-s", + "--usesubprocess", + action="store_true", + help="run everything in a single process " " (default: use no subprocesses)", +) + +opt_parser.add_option( + "-e", + "--exclude", + action="callback", + type="string", + help="exclude tests containing any of TAGS", + callback=exclude_callback, +) + +opt_parser.add_option( + "-u", + "--unbuffered", + action="store_true", + help="Show stdout/stderr as tests run, rather than storing it and showing on failures", +) + +opt_parser.add_option( + "-v", + "--verbose", + dest="verbosity", + action="store_const", + const=2, + help="Verbose output", +) +opt_parser.add_option( + "-q", + "--quiet", + dest="verbosity", + action="store_const", + const=0, + help="Quiet output", +) + +opt_parser.add_option( + "-r", "--randomize", action="store_true", help="randomize order of tests" +) + +################################################################################ +# If an xxxx_test.py takes longer than TIME_OUT seconds it will be killed +# This is only the default, can be over-ridden on command line + +TIME_OUT = 30 + +# DEFAULTS + +################################################################################ +# Human readable output +# + +COMPLETE_FAILURE_TEMPLATE = """ +====================================================================== +ERROR: all_tests_for (%(module)s.AllTestCases) +---------------------------------------------------------------------- +Traceback (most recent call last): + File "test/%(module)s.py", line 1, in all_tests_for +subprocess completely failed with return code of %(return_code)s +cmd: %(cmd)s +test_env: %(test_env)s +working_dir: %(working_dir)s +return (first 10 and last 10 lines): +%(raw_return)s + +""" # Leave that last empty line else build page regex won't match +# Text also needs to be vertically compressed + + +RAN_TESTS_DIV = (70 * "-") + "\nRan" + +DOTS = re.compile("^([FE.sux]*)$", re.MULTILINE) + + +def extract_tracebacks(output): + """from test runner output return the tracebacks.""" + verbose_mode = " ..." in output + + if verbose_mode: + if "ERROR" in output or "FAILURE" in output: + return "\n\n==".join(output.split("\n\n==")[1:]) + else: + dots = DOTS.search(output).group(1) + if "E" in dots or "F" in dots: + return output[len(dots) + 1 :].split(RAN_TESTS_DIV)[0] + return "" + + +def output_into_dots(output): + """convert the test runner output into dots.""" + # verbose_mode = ") ..." in output + verbose_mode = " ..." in output + + if verbose_mode: + # a map from the verbose output to the dots output. + reasons = { + "... ERROR": "E", + "... unexpected success": "u", + "... skipped": "s", + "... expected failure": "x", + "... ok": ".", + "... FAIL": "F", + } + results = output.split("\n\n==")[0] + lines = [l for l in results.split("\n") if l and "..." in l] + dotlist = [] + for l in lines: + found = False + for reason in reasons: + if reason in l: + dotlist.append(reasons[reason]) + found = True + break + if not found: + raise ValueError("Not sure what this is. Add to reasons. :%s" % l) + + return "".join(dotlist) + dots = DOTS.search(output).group(1) + return dots + + +def combine_results(all_results, t): + """ + + Return pieced together results in a form fit for human consumption. Don't + rely on results if piecing together subprocessed results (single process + mode is fine). Was originally meant for that purpose but was found to be + unreliable. See the dump option for reliable results. + + """ + + all_dots = "" + failures = [] + + for module, results in sorted(all_results.items()): + output, return_code, raw_return = map( + results.get, ("output", "return_code", "raw_return") + ) + + if not output or (return_code and RAN_TESTS_DIV not in output): + # would this effect the original dict? TODO + output_lines = raw_return.splitlines() + if len(output_lines) > 20: + results["raw_return"] = "\n".join( + output_lines[:10] + ["..."] + output_lines[-10:] + ) + failures.append(COMPLETE_FAILURE_TEMPLATE % results) + all_dots += "E" + continue + + dots = output_into_dots(output) + all_dots += dots + tracebacks = extract_tracebacks(output) + if tracebacks: + failures.append(tracebacks) + + total_fails, total_errors = map(all_dots.count, "FE") + total_tests = len(all_dots) + + combined = [all_dots] + if failures: + combined += ["".join(failures).lstrip("\n")[:-1]] + combined += ["%s %s tests in %.3fs\n" % (RAN_TESTS_DIV, total_tests, t)] + + if failures: + infos = (["failures=%s" % total_fails] if total_fails else []) + ( + ["errors=%s" % total_errors] if total_errors else [] + ) + combined += ["FAILED (%s)\n" % ", ".join(infos)] + else: + combined += ["OK\n"] + + return total_tests, "\n".join(combined) + + +################################################################################ + +TEST_RESULTS_START = "<--!! TEST RESULTS START HERE !!-->" +TEST_RESULTS_END = "<--!! TEST RESULTS END HERE !!-->" +_test_re_str = "%s\n(.*)%s" % (TEST_RESULTS_START, TEST_RESULTS_END) +TEST_RESULTS_RE = re.compile(_test_re_str, re.DOTALL | re.M) + + +def get_test_results(raw_return): + test_results = TEST_RESULTS_RE.search(raw_return) + if test_results: + try: + return eval(test_results.group(1)) + except: + print("BUGGY TEST RESULTS EVAL:\n %s" % test_results.group(1)) + raise + + +################################################################################ + + +def run_test( + module, + incomplete=False, + usesubprocess=True, + randomize=False, + exclude=("interactive",), + buffer=True, + unbuffered=None, + verbosity=1, +): + """Run a unit test module""" + suite = unittest.TestSuite() + + if verbosity is None: + verbosity = 1 + + if verbosity: + print("loading %s" % module) + + loader = PygameTestLoader( + randomize_tests=randomize, include_incomplete=incomplete, exclude=exclude + ) + suite.addTest(loader.loadTestsFromName(module)) + + output = StringIO.StringIO() + runner = unittest.TextTestRunner(stream=output, buffer=buffer, verbosity=verbosity) + results = runner.run(suite) + + if verbosity == 2: + output.seek(0) + print(output.read()) + output.seek(0) + + results = { + module: { + "output": output.getvalue(), + "num_tests": results.testsRun, + "num_errors": len(results.errors), + "num_failures": len(results.failures), + } + } + + if usesubprocess: + print(TEST_RESULTS_START) + print(pformat(results)) + print(TEST_RESULTS_END) + else: + return results + + +################################################################################ + +if __name__ == "__main__": + options, args = opt_parser.parse_args() + if not args: + + if is_pygame_pkg: + run_from = "pygame.tests.go" + else: + run_from = os.path.join(main_dir, "run_tests.py") + sys.exit("No test module provided; consider using %s instead" % run_from) + run_test( + args[0], + incomplete=options.incomplete, + usesubprocess=options.usesubprocess, + randomize=options.randomize, + exclude=options.exclude, + buffer=(not options.unbuffered), + ) + +################################################################################ diff --git a/venv/Lib/site-packages/pygame/tests/threads_test.py b/venv/Lib/site-packages/pygame/tests/threads_test.py new file mode 100644 index 0000000..5f55eac --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/threads_test.py @@ -0,0 +1,240 @@ +import unittest +from pygame.threads import FuncResult, tmap, WorkerQueue, Empty, STOP +from pygame import threads, Surface, transform + + +import time + + +class WorkerQueueTypeTest(unittest.TestCase): + def test_usage_with_different_functions(self): + def f(x): + return x + 1 + + def f2(x): + return x + 2 + + wq = WorkerQueue() + fr = FuncResult(f) + fr2 = FuncResult(f2) + wq.do(fr, 1) + wq.do(fr2, 1) + wq.wait() + wq.stop() + + self.assertEqual(fr.result, 2) + self.assertEqual(fr2.result, 3) + + def test_do(self): + """Tests function placement on queue and execution after blocking function completion.""" + # __doc__ (as of 2008-06-28) for pygame.threads.WorkerQueue.do: + + # puts a function on a queue for running _later_. + + # TODO: This tests needs refactoring to avoid sleep. + # sleep is slow and unreliable (especially on VMs). + + # def sleep_test(): + # time.sleep(0.5) + + # def calc_test(x): + # return x + 1 + + # worker_queue = WorkerQueue(num_workers=1) + # sleep_return = FuncResult(sleep_test) + # calc_return = FuncResult(calc_test) + # init_time = time.time() + # worker_queue.do(sleep_return) + # worker_queue.do(calc_return, 1) + # worker_queue.wait() + # worker_queue.stop() + # time_diff = time.time() - init_time + + # self.assertEqual(sleep_return.result, None) + # self.assertEqual(calc_return.result, 2) + # self.assertGreaterEqual(time_diff, 0.5) + + def test_stop(self): + """Ensure stop() stops the worker queue""" + wq = WorkerQueue() + + self.assertGreater(len(wq.pool), 0) + + for t in wq.pool: + self.assertTrue(t.is_alive()) + + for i in range(200): + wq.do(lambda x: x + 1, i) + + wq.stop() + + for t in wq.pool: + self.assertFalse(t.is_alive()) + + self.assertIs(wq.queue.get(), STOP) + + def test_threadloop(self): + + # __doc__ (as of 2008-06-28) for pygame.threads.WorkerQueue.threadloop: + + # Loops until all of the tasks are finished. + + # Make a worker queue with only one thread + wq = WorkerQueue(1) + + # Ocuppy the one worker with the threadloop + # wq threads are just threadloop, so this makes an embedded threadloop + wq.do(wq.threadloop) + + # Make sure wq can still do work + # If wq can still do work, threadloop works + l = [] + wq.do(l.append, 1) + # Wait won't work because the primary thread is in an infinite loop + time.sleep(0.5) + self.assertEqual(l[0], 1) + + # Kill the embedded threadloop by sending stop onto the stack + # Threadloop puts STOP back onto the queue when it STOPs so this kills both loops + wq.stop() + + # Make sure wq has stopped + self.assertFalse(wq.pool[0].is_alive()) + + def test_wait(self): + + # __doc__ (as of 2008-06-28) for pygame.threads.WorkerQueue.wait: + + # waits until all tasks are complete. + + wq = WorkerQueue() + + for i in range(2000): + wq.do(lambda x: x + 1, i) + wq.wait() + + self.assertRaises(Empty, wq.queue.get_nowait) + + wq.stop() + + +class ThreadsModuleTest(unittest.TestCase): + def test_benchmark_workers(self): + """Ensure benchmark_workers performance measure functions properly with both default and specified inputs""" + "tags:long_running" + + # __doc__ (as of 2008-06-28) for pygame.threads.benchmark_workers: + + # does a little test to see if workers are at all faster. + # Returns the number of workers which works best. + # Takes a little bit of time to run, so you should only really call + # it once. + # You can pass in benchmark data, and functions if you want. + # a_bench_func - f(data) + # the_data - data to work on. + optimal_workers = threads.benchmark_workers() + self.assertIsInstance(optimal_workers, int) + self.assertTrue(0 <= optimal_workers < 64) + + # Test passing benchmark data and function explicitly + def smooth_scale_bench(data): + transform.smoothscale(data, (128, 128)) + + surf_data = [Surface((x, x), 0, 32) for x in range(12, 64, 12)] + best_num_workers = threads.benchmark_workers(smooth_scale_bench, surf_data) + self.assertIsInstance(best_num_workers, int) + + def test_init(self): + """Ensure init() sets up the worker queue""" + threads.init(8) + + self.assertIsInstance(threads._wq, WorkerQueue) + + threads.quit() + + def test_quit(self): + """Ensure quit() cleans up the worker queue""" + threads.init(8) + threads.quit() + + self.assertIsNone(threads._wq) + + def test_tmap(self): + # __doc__ (as of 2008-06-28) for pygame.threads.tmap: + + # like map, but uses a thread pool to execute. + # num_workers - the number of worker threads that will be used. If pool + # is passed in, then the num_workers arg is ignored. + # worker_queue - you can optionally pass in an existing WorkerQueue. + # wait - True means that the results are returned when everything is finished. + # False means that we return the [worker_queue, results] right away instead. + # results, is returned as a list of FuncResult instances. + # stop_on_error - + + ## test that the outcomes of map and tmap are the same + func, data = lambda x: x + 1, range(100) + + tmapped = list(tmap(func, data)) + mapped = list(map(func, data)) + + self.assertEqual(tmapped, mapped) + + ## Test that setting tmap to not stop on errors produces the expected result + data2 = range(100) + always_excepts = lambda x: 1 / 0 + + tmapped2 = list(tmap(always_excepts, data2, stop_on_error=False)) + + # Use list comprehension to check all entries are None as all function + # calls made by tmap will have thrown an exception (ZeroDivisionError) + # Condense to single bool with `all`, which will return true if all + # entries are true + self.assertTrue(all([x is None for x in tmapped2])) + + def todo_test_tmap__None_func_and_multiple_sequences(self): + """Using a None as func and multiple sequences""" + self.fail() + + res = tmap(None, [1, 2, 3, 4]) + res2 = tmap(None, [1, 2, 3, 4], [22, 33, 44, 55]) + res3 = tmap(None, [1, 2, 3, 4], [22, 33, 44, 55, 66]) + res4 = tmap(None, [1, 2, 3, 4, 5], [22, 33, 44, 55]) + + self.assertEqual([1, 2, 3, 4], res) + self.assertEqual([(1, 22), (2, 33), (3, 44), (4, 55)], res2) + self.assertEqual([(1, 22), (2, 33), (3, 44), (4, 55), (None, 66)], res3) + self.assertEqual([(1, 22), (2, 33), (3, 44), (4, 55), (5, None)], res4) + + def test_tmap__wait(self): + r = range(1000) + wq, results = tmap(lambda x: x, r, num_workers=5, wait=False) + wq.wait() + r2 = map(lambda x: x.result, results) + self.assertEqual(list(r), list(r2)) + + def test_FuncResult(self): + """Ensure FuncResult sets its result and exception attributes""" + # Results are stored in result attribute + fr = FuncResult(lambda x: x + 1) + fr(2) + + self.assertEqual(fr.result, 3) + + # Exceptions are store in exception attribute + self.assertIsNone(fr.exception, "no exception should be raised") + + exception = ValueError("rast") + + def x(sdf): + raise exception + + fr = FuncResult(x) + fr(None) + + self.assertIs(fr.exception, exception) + + +################################################################################ + +if __name__ == "__main__": + unittest.main() diff --git a/venv/Lib/site-packages/pygame/tests/time_test.py b/venv/Lib/site-packages/pygame/tests/time_test.py new file mode 100644 index 0000000..e428508 --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/time_test.py @@ -0,0 +1,392 @@ +import unittest +import pygame +import time + +Clock = pygame.time.Clock + + +class ClockTypeTest(unittest.TestCase): + __tags__ = ["timing"] + + def test_construction(self): + """Ensure a Clock object can be created""" + c = Clock() + + self.assertTrue(c, "Clock cannot be constructed") + + def test_get_fps(self): + """test_get_fps tests pygame.time.get_fps()""" + # Initialization check, first call should return 0 fps + c = Clock() + self.assertEqual(c.get_fps(), 0) + # Type check get_fps should return float + self.assertTrue(type(c.get_fps()) == float) + # Allowable margin of error in percentage + delta = 0.30 + # Test fps correctness for 100, 60 and 30 fps + self._fps_test(c, 100, delta) + self._fps_test(c, 60, delta) + self._fps_test(c, 30, delta) + + def _fps_test(self, clock, fps, delta): + """ticks fps times each second, hence get_fps() should return fps""" + delay_per_frame = 1.0 / fps + for f in range(fps): # For one second tick and sleep + clock.tick() + time.sleep(delay_per_frame) + # We should get around fps (+- fps*delta -- delta % of fps) + self.assertAlmostEqual(clock.get_fps(), fps, delta=fps * delta) + + def test_get_rawtime(self): + + iterations = 10 + delay = 0.1 + delay_miliseconds = delay * (10 ** 3) # actual time difference between ticks + framerate_limit = 5 + delta = 50 # allowable error in milliseconds + + # Testing Clock Initialization + c = Clock() + self.assertEqual(c.get_rawtime(), 0) + + # Testing Raw Time with Frame Delay + for f in range(iterations): + time.sleep(delay) + c.tick(framerate_limit) + c1 = c.get_rawtime() + self.assertAlmostEqual(delay_miliseconds, c1, delta=delta) + + # Testing get_rawtime() = get_time() + for f in range(iterations): + time.sleep(delay) + c.tick() + c1 = c.get_rawtime() + c2 = c.get_time() + self.assertAlmostEqual(c1, c2, delta=delta) + + def test_get_time(self): + # Testing parameters + delay = 0.1 # seconds + delay_miliseconds = delay * (10 ** 3) + iterations = 10 + delta = 50 # milliseconds + + # Testing Clock Initialization + c = Clock() + self.assertEqual(c.get_time(), 0) + + # Testing within delay parameter range + for i in range(iterations): + time.sleep(delay) + c.tick() + c1 = c.get_time() + self.assertAlmostEqual(delay_miliseconds, c1, delta=delta) + + # Comparing get_time() results with the 'time' module + for i in range(iterations): + t0 = time.time() + time.sleep(delay) + c.tick() + t1 = time.time() + c1 = c.get_time() # elapsed time in milliseconds + d0 = (t1 - t0) * ( + 10 ** 3 + ) #'time' module elapsed time converted to milliseconds + self.assertAlmostEqual(d0, c1, delta=delta) + + def test_tick(self): + """Tests time.Clock.tick()""" + """ + Loops with a set delay a few times then checks what tick reports to + verify its accuracy. Then calls tick with a desired frame-rate and + verifies it is not faster than the desired frame-rate nor is it taking + a dramatically long time to complete + """ + + # Adjust this value to increase the acceptable sleep jitter + epsilon = 1.5 + # Adjust this value to increase the acceptable locked frame-rate jitter + epsilon2 = 0.3 + # adjust this value to increase the acceptable frame-rate margin + epsilon3 = 20 + testing_framerate = 60 + milliseconds = 5.0 + + collection = [] + c = Clock() + + # verify time.Clock.tick() will measure the time correctly + c.tick() + for i in range(100): + time.sleep(milliseconds / 1000) # convert to seconds + collection.append(c.tick()) + + # removes the first highest and lowest value + for outlier in [min(collection), max(collection)]: + if outlier != milliseconds: + collection.remove(outlier) + + average_time = float(sum(collection)) / len(collection) + + # assert the deviation from the intended frame-rate is within the + # acceptable amount (the delay is not taking a dramatically long time) + self.assertAlmostEqual(average_time, milliseconds, delta=epsilon) + + # verify tick will control the frame-rate + + c = Clock() + collection = [] + + start = time.time() + + for i in range(testing_framerate): + collection.append(c.tick(testing_framerate)) + + # remove the highest and lowest outliers + for outlier in [min(collection), max(collection)]: + if outlier != round(1000 / testing_framerate): + collection.remove(outlier) + + end = time.time() + + # Since calling tick with a desired fps will prevent the program from + # running at greater than the given fps, 100 iterations at 100 fps + # should last no less than 1 second + self.assertAlmostEqual(end - start, 1, delta=epsilon2) + + average_tick_time = float(sum(collection)) / len(collection) + self.assertAlmostEqual( + 1000 / average_tick_time, testing_framerate, delta=epsilon3 + ) + + def test_tick_busy_loop(self): + """Test tick_busy_loop""" + + c = Clock() + + # Test whether the return value of tick_busy_loop is equal to + # (FPS is accurate) or greater than (slower than the set FPS) + # with a small margin for error based on differences in how this + # test runs in practise - it either sometimes runs slightly fast + # or seems to based on a rounding error. + second_length = 1000 + shortfall_tolerance = 1 # (ms) The amount of time a tick is allowed to run short of, to account for underlying rounding errors + sample_fps = 40 + + self.assertGreaterEqual( + c.tick_busy_loop(sample_fps), + (second_length / sample_fps) - shortfall_tolerance, + ) + pygame.time.wait(10) # incur delay between ticks that's faster than sample_fps + self.assertGreaterEqual( + c.tick_busy_loop(sample_fps), + (second_length / sample_fps) - shortfall_tolerance, + ) + pygame.time.wait(200) # incur delay between ticks that's slower than sample_fps + self.assertGreaterEqual( + c.tick_busy_loop(sample_fps), + (second_length / sample_fps) - shortfall_tolerance, + ) + + high_fps = 500 + self.assertGreaterEqual( + c.tick_busy_loop(high_fps), (second_length / high_fps) - shortfall_tolerance + ) + + low_fps = 1 + self.assertGreaterEqual( + c.tick_busy_loop(low_fps), (second_length / low_fps) - shortfall_tolerance + ) + + low_non_factor_fps = 35 # 1000/35 makes 28.5714285714 + frame_length_without_decimal_places = int( + second_length / low_non_factor_fps + ) # Same result as math.floor + self.assertGreaterEqual( + c.tick_busy_loop(low_non_factor_fps), + frame_length_without_decimal_places - shortfall_tolerance, + ) + + high_non_factor_fps = 750 # 1000/750 makes 1.3333... + frame_length_without_decimal_places_2 = int( + second_length / high_non_factor_fps + ) # Same result as math.floor + self.assertGreaterEqual( + c.tick_busy_loop(high_non_factor_fps), + frame_length_without_decimal_places_2 - shortfall_tolerance, + ) + + zero_fps = 0 + self.assertEqual(c.tick_busy_loop(zero_fps), 0) + + # Check behaviour of unexpected values + + negative_fps = -1 + self.assertEqual(c.tick_busy_loop(negative_fps), 0) + + fractional_fps = 32.75 + frame_length_without_decimal_places_3 = int(second_length / fractional_fps) + self.assertGreaterEqual( + c.tick_busy_loop(fractional_fps), + frame_length_without_decimal_places_3 - shortfall_tolerance, + ) + + bool_fps = True + self.assertGreaterEqual( + c.tick_busy_loop(bool_fps), (second_length / bool_fps) - shortfall_tolerance + ) + + +class TimeModuleTest(unittest.TestCase): + __tags__ = ["timing"] + + def test_delay(self): + """Tests time.delay() function.""" + millis = 50 # millisecond to wait on each iteration + iterations = 20 # number of iterations + delta = 150 # Represents acceptable margin of error for wait in ms + # Call checking function + self._wait_delay_check(pygame.time.delay, millis, iterations, delta) + # After timing behaviour, check argument type exceptions + self._type_error_checks(pygame.time.delay) + + def test_get_ticks(self): + """Tests time.get_ticks()""" + """ + Iterates and delays for arbitrary amount of time for each iteration, + check get_ticks to equal correct gap time + """ + iterations = 20 + millis = 50 + delta = 15 # Acceptable margin of error in ms + # Assert return type to be int + self.assertTrue(type(pygame.time.get_ticks()) == int) + for i in range(iterations): + curr_ticks = pygame.time.get_ticks() # Save current tick count + curr_time = time.time() # Save current time + pygame.time.delay(millis) # Delay for millis + # Time and Ticks difference from start of the iteration + time_diff = round((time.time() - curr_time) * 1000) + ticks_diff = pygame.time.get_ticks() - curr_ticks + # Assert almost equality of the ticking time and time difference + self.assertAlmostEqual(ticks_diff, time_diff, delta=delta) + + def test_set_timer(self): + """Tests time.set_timer()""" + """ + Tests if a timer will post the correct amount of eventid events in + the specified delay. Test is posting event objects work. + Also tests if setting milliseconds to 0 stops the timer and if + the once argument and repeat arguments work. + """ + pygame.init() + TIMER_EVENT_TYPE = pygame.event.custom_type() + timer_event = pygame.event.Event(TIMER_EVENT_TYPE) + delta = 50 + timer_delay = 100 + test_number = 8 # Number of events to read for the test + events = 0 # Events read + + pygame.event.clear() + pygame.time.set_timer(TIMER_EVENT_TYPE, timer_delay) + + # Test that 'test_number' events are posted in the right amount of time + t1 = pygame.time.get_ticks() + max_test_time = t1 + timer_delay * test_number + delta + while events < test_number: + for event in pygame.event.get(): + if event == timer_event: + events += 1 + + # The test takes too much time + if pygame.time.get_ticks() > max_test_time: + break + + pygame.time.set_timer(TIMER_EVENT_TYPE, 0) + t2 = pygame.time.get_ticks() + # Is the number ef events and the timing right? + self.assertEqual(events, test_number) + self.assertAlmostEqual(timer_delay * test_number, t2 - t1, delta=delta) + + # Test that the timer stopped when set with 0ms delay. + pygame.time.delay(200) + self.assertNotIn(timer_event, pygame.event.get()) + + # Test that the old timer for an event is deleted when a new timer is set + pygame.time.set_timer(TIMER_EVENT_TYPE, timer_delay) + pygame.time.delay(int(timer_delay * 3.5)) + self.assertEqual(pygame.event.get().count(timer_event), 3) + pygame.time.set_timer(TIMER_EVENT_TYPE, timer_delay * 10) # long wait time + pygame.time.delay(timer_delay * 5) + self.assertNotIn(timer_event, pygame.event.get()) + pygame.time.set_timer(TIMER_EVENT_TYPE, timer_delay * 3) + pygame.time.delay(timer_delay * 7) + self.assertEqual(pygame.event.get().count(timer_event), 2) + pygame.time.set_timer(TIMER_EVENT_TYPE, timer_delay) + pygame.time.delay(int(timer_delay * 5.5)) + self.assertEqual(pygame.event.get().count(timer_event), 5) + + # Test that the loops=True works + pygame.time.set_timer(TIMER_EVENT_TYPE, 10, True) + pygame.time.delay(40) + self.assertEqual(pygame.event.get().count(timer_event), 1) + + # Test a variety of event objects, test loops argument + events_to_test = [ + pygame.event.Event(TIMER_EVENT_TYPE), + pygame.event.Event( + TIMER_EVENT_TYPE, foo="9gwz5", baz=12, lol=[124, (34, "")] + ), + pygame.event.Event(pygame.KEYDOWN, key=pygame.K_a, unicode="a"), + ] + repeat = 3 + millis = 50 + for e in events_to_test: + pygame.time.set_timer(e, millis, loops=repeat) + pygame.time.delay(2 * millis * repeat) + self.assertEqual(pygame.event.get().count(e), repeat) + pygame.quit() + + def test_wait(self): + """Tests time.wait() function.""" + millis = 100 # millisecond to wait on each iteration + iterations = 10 # number of iterations + delta = 50 # Represents acceptable margin of error for wait in ms + # Call checking function + self._wait_delay_check(pygame.time.wait, millis, iterations, delta) + # After timing behaviour, check argument type exceptions + self._type_error_checks(pygame.time.wait) + + def _wait_delay_check(self, func_to_check, millis, iterations, delta): + """ " + call func_to_check(millis) "iterations" times and check each time if + function "waited" for given millisecond (+- delta). At the end, take + average time for each call (whole_duration/iterations), which should + be equal to millis (+- delta - acceptable margin of error). + *Created to avoid code duplication during delay and wait tests + """ + # take starting time for duration calculation + start_time = time.time() + for i in range(iterations): + wait_time = func_to_check(millis) + # Check equality of wait_time and millis with margin of error delta + self.assertAlmostEqual(wait_time, millis, delta=delta) + stop_time = time.time() + # Cycle duration in millisecond + duration = round((stop_time - start_time) * 1000) + # Duration/Iterations should be (almost) equal to predefined millis + self.assertAlmostEqual(duration / iterations, millis, delta=delta) + + def _type_error_checks(self, func_to_check): + """Checks 3 TypeError (float, tuple, string) for the func_to_check""" + """Intended for time.delay and time.wait functions""" + # Those methods throw no exceptions on negative integers + self.assertRaises(TypeError, func_to_check, 0.1) # check float + self.assertRaises(TypeError, pygame.time.delay, (0, 1)) # check tuple + self.assertRaises(TypeError, pygame.time.delay, "10") # check string + + +############################################################################### + +if __name__ == "__main__": + unittest.main() diff --git a/venv/Lib/site-packages/pygame/tests/touch_test.py b/venv/Lib/site-packages/pygame/tests/touch_test.py new file mode 100644 index 0000000..3f63cae --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/touch_test.py @@ -0,0 +1,98 @@ +import unittest +import os +import pygame +from pygame._sdl2 import touch +from pygame.tests.test_utils import question + + +has_touchdevice = touch.get_num_devices() > 0 + + +class TouchTest(unittest.TestCase): + @classmethod + def setUpClass(cls): + pygame.display.init() + + @classmethod + def tearDownClass(cls): + pygame.display.quit() + + def test_num_devices(self): + touch.get_num_devices() + + @unittest.skipIf(not has_touchdevice, "no touch devices found") + def test_get_device(self): + touch.get_device(0) + + def test_num_fingers__invalid(self): + self.assertRaises(pygame.error, touch.get_device, -1234) + self.assertRaises(TypeError, touch.get_device, "test") + + @unittest.skipIf(not has_touchdevice, "no touch devices found") + def test_num_fingers(self): + touch.get_num_fingers(touch.get_device(0)) + + def test_num_fingers__invalid(self): + self.assertRaises(TypeError, touch.get_num_fingers, "test") + self.assertRaises(pygame.error, touch.get_num_fingers, -1234) + + +class TouchInteractiveTest(unittest.TestCase): + + __tags__ = ["interactive"] + + @unittest.skipIf(not has_touchdevice, "no touch devices found") + def test_get_finger(self): + """ask for touch input and check the dict""" + + pygame.display.init() + pygame.font.init() + + os.environ["SDL_VIDEO_WINDOW_POS"] = "50,50" + screen = pygame.display.set_mode((800, 600)) + screen.fill((255, 255, 255)) + + font = pygame.font.Font(None, 32) + instructions_str_1 = "Please place some fingers on your touch device" + instructions_str_2 = ( + "Close the window when finished, " "and answer the question" + ) + inst_1_render = font.render(instructions_str_1, True, pygame.Color("#000000")) + inst_2_render = font.render(instructions_str_2, True, pygame.Color("#000000")) + + running = True + while running: + for event in pygame.event.get(): + if event.type == pygame.QUIT: + running = False + + finger_data_renders = [] + num_devices = pygame._sdl2.touch.get_num_devices() + if num_devices > 0: + first_device = pygame._sdl2.touch.get_device(0) + num_fingers = pygame._sdl2.touch.get_num_fingers(first_device) + if num_fingers > 0: + for finger_index in range(0, num_fingers): + data = pygame._sdl2.touch.get_finger(first_device, finger_index) + render = font.render( + "finger - " + str(data), True, pygame.Color("#000000") + ) + + finger_data_renders.append(render) + + screen.fill((255, 255, 255)) + screen.blit(inst_1_render, (5, 5)) + screen.blit(inst_2_render, (5, 40)) + for index, finger in enumerate(finger_data_renders): + screen.blit(finger, (5, 80 + (index * 40))) + + pygame.display.update() + + response = question("Does the finger data seem correct?") + self.assertTrue(response) + + pygame.display.quit() + + +if __name__ == "__main__": + unittest.main() diff --git a/venv/Lib/site-packages/pygame/tests/transform_test.py b/venv/Lib/site-packages/pygame/tests/transform_test.py new file mode 100644 index 0000000..1484817 --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/transform_test.py @@ -0,0 +1,1316 @@ +import unittest +import os +import platform + +from pygame.tests import test_utils +from pygame.tests.test_utils import example_path + +import pygame +import pygame.transform +from pygame.locals import * + + +def show_image(s, images=[]): + # pygame.display.init() + size = s.get_rect()[2:] + screen = pygame.display.set_mode(size) + screen.blit(s, (0, 0)) + pygame.display.flip() + pygame.event.pump() + going = True + idx = 0 + while going: + events = pygame.event.get() + for e in events: + if e.type == QUIT: + going = False + if e.type == KEYDOWN: + if e.key in [K_s, K_a]: + if e.key == K_s: + idx += 1 + if e.key == K_a: + idx -= 1 + s = images[idx] + screen.blit(s, (0, 0)) + pygame.display.flip() + pygame.event.pump() + elif e.key in [K_ESCAPE]: + going = False + pygame.display.quit() + pygame.display.init() + + +def threshold( + return_surf, + surf, + color, + threshold=(0, 0, 0), + diff_color=(0, 0, 0), + change_return=True, +): + """given the color it makes return_surf only have areas with the given colour.""" + + width, height = surf.get_width(), surf.get_height() + + if change_return: + return_surf.fill(diff_color) + + try: + r, g, b = color + except ValueError: + r, g, b, a = color + + try: + tr, tg, tb = color + except ValueError: + tr, tg, tb, ta = color + + similar = 0 + for y in range(height): + for x in range(width): + c1 = surf.get_at((x, y)) + + if (abs(c1[0] - r) < tr) & (abs(c1[1] - g) < tg) & (abs(c1[2] - b) < tb): + # this pixel is within the threshold. + if change_return: + return_surf.set_at((x, y), c1) + similar += 1 + # else: + # print c1, c2 + + return similar + + +class TransformModuleTest(unittest.TestCase): + def test_scale__alpha(self): + """see if set_alpha information is kept.""" + + s = pygame.Surface((32, 32)) + s.set_alpha(55) + self.assertEqual(s.get_alpha(), 55) + + s = pygame.Surface((32, 32)) + s.set_alpha(55) + s2 = pygame.transform.scale(s, (64, 64)) + s3 = s.copy() + self.assertEqual(s.get_alpha(), s3.get_alpha()) + self.assertEqual(s.get_alpha(), s2.get_alpha()) + + def test_scale__destination(self): + """see if the destination surface can be passed in to use.""" + + s = pygame.Surface((32, 32)) + s2 = pygame.transform.scale(s, (64, 64)) + s3 = s2.copy() + + # Also validate keyword arguments + s3 = pygame.transform.scale(surface=s, size=(64, 64), dest_surface=s3) + pygame.transform.scale(s, (64, 64), s2) + + # the wrong size surface is past in. Should raise an error. + self.assertRaises(ValueError, pygame.transform.scale, s, (33, 64), s3) + + s = pygame.Surface((32, 32)) + s2 = pygame.transform.smoothscale(s, (64, 64)) + s3 = s2.copy() + + # Also validate keyword arguments + s3 = pygame.transform.smoothscale(surface=s, size=(64, 64), dest_surface=s3) + + # the wrong size surface is past in. Should raise an error. + self.assertRaises(ValueError, pygame.transform.smoothscale, s, (33, 64), s3) + + def test_scale__vector2(self): + s = pygame.Surface((32, 32)) + s2 = pygame.transform.scale(s, pygame.Vector2(64, 64)) + s3 = pygame.transform.smoothscale(s, pygame.Vector2(64, 64)) + + self.assertEqual((64, 64), s2.get_size()) + self.assertEqual((64, 64), s3.get_size()) + + def test_scale__zero_surface_transform(self): + tmp_surface = pygame.transform.scale(pygame.Surface((128, 128)), (0, 0)) + self.assertEqual(tmp_surface.get_size(), (0, 0)) + tmp_surface = pygame.transform.scale(tmp_surface, (128, 128)) + self.assertEqual(tmp_surface.get_size(), (128, 128)) + + def test_threshold__honors_third_surface(self): + # __doc__ for threshold as of Tue 07/15/2008 + + # pygame.transform.threshold(DestSurface, Surface, color, threshold = + # (0,0,0,0), diff_color = (0,0,0,0), change_return = True, Surface = + # None): return num_threshold_pixels + + # When given the optional third + # surface, it would use the colors in that rather than the "color" + # specified in the function to check against. + + # New in pygame 1.8 + + ################################################################ + # Sizes + (w, h) = size = (32, 32) + + # the original_color is within the threshold of the threshold_color + threshold = (20, 20, 20, 20) + + original_color = (25, 25, 25, 25) + threshold_color = (10, 10, 10, 10) + + # Surfaces + original_surface = pygame.Surface(size, pygame.SRCALPHA, 32) + dest_surface = pygame.Surface(size, pygame.SRCALPHA, 32) + + # Third surface is used in lieu of 3rd position arg color + third_surface = pygame.Surface(size, pygame.SRCALPHA, 32) + + # Color filling + original_surface.fill(original_color) + third_surface.fill(threshold_color) + + ################################################################ + # All pixels for color should be within threshold + # + pixels_within_threshold = pygame.transform.threshold( + dest_surface=None, + surface=original_surface, + search_color=threshold_color, + threshold=threshold, + set_color=None, + set_behavior=0, + ) + + self.assertEqual(w * h, pixels_within_threshold) + + ################################################################ + # This should respect third_surface colors in place of 3rd arg + # color Should be the same as: surface.fill(threshold_color) + # all within threshold + + pixels_within_threshold = pygame.transform.threshold( + dest_surface=None, + surface=original_surface, + search_color=None, + threshold=threshold, + set_color=None, + set_behavior=0, + search_surf=third_surface, + ) + self.assertEqual(w * h, pixels_within_threshold) + + def test_threshold_dest_surf_not_change(self): + """the pixels within the threshold. + + All pixels not within threshold are changed to set_color. + So there should be none changed in this test. + """ + (w, h) = size = (32, 32) + threshold = (20, 20, 20, 20) + original_color = (25, 25, 25, 25) + original_dest_color = (65, 65, 65, 55) + threshold_color = (10, 10, 10, 10) + set_color = (255, 10, 10, 10) + + surf = pygame.Surface(size, pygame.SRCALPHA, 32) + dest_surf = pygame.Surface(size, pygame.SRCALPHA, 32) + search_surf = pygame.Surface(size, pygame.SRCALPHA, 32) + + surf.fill(original_color) + search_surf.fill(threshold_color) + dest_surf.fill(original_dest_color) + + # set_behavior=1, set dest_surface from set_color. + # all within threshold of third_surface, so no color is set. + + THRESHOLD_BEHAVIOR_FROM_SEARCH_COLOR = 1 + pixels_within_threshold = pygame.transform.threshold( + dest_surface=dest_surf, + surface=surf, + search_color=None, + threshold=threshold, + set_color=set_color, + set_behavior=THRESHOLD_BEHAVIOR_FROM_SEARCH_COLOR, + search_surf=search_surf, + ) + + # # Return, of pixels within threshold is correct + self.assertEqual(w * h, pixels_within_threshold) + + # # Size of dest surface is correct + dest_rect = dest_surf.get_rect() + dest_size = dest_rect.size + self.assertEqual(size, dest_size) + + # The color is not the change_color specified for every pixel As all + # pixels are within threshold + + for pt in test_utils.rect_area_pts(dest_rect): + self.assertNotEqual(dest_surf.get_at(pt), set_color) + self.assertEqual(dest_surf.get_at(pt), original_dest_color) + + def test_threshold_dest_surf_all_changed(self): + """Lowering the threshold, expecting changed surface""" + + (w, h) = size = (32, 32) + threshold = (20, 20, 20, 20) + original_color = (25, 25, 25, 25) + original_dest_color = (65, 65, 65, 55) + threshold_color = (10, 10, 10, 10) + set_color = (255, 10, 10, 10) + + surf = pygame.Surface(size, pygame.SRCALPHA, 32) + dest_surf = pygame.Surface(size, pygame.SRCALPHA, 32) + search_surf = pygame.Surface(size, pygame.SRCALPHA, 32) + + surf.fill(original_color) + search_surf.fill(threshold_color) + dest_surf.fill(original_dest_color) + + THRESHOLD_BEHAVIOR_FROM_SEARCH_COLOR = 1 + pixels_within_threshold = pygame.transform.threshold( + dest_surf, + surf, + search_color=None, + set_color=set_color, + set_behavior=THRESHOLD_BEHAVIOR_FROM_SEARCH_COLOR, + search_surf=search_surf, + ) + + self.assertEqual(0, pixels_within_threshold) + + dest_rect = dest_surf.get_rect() + dest_size = dest_rect.size + self.assertEqual(size, dest_size) + + # The color is the set_color specified for every pixel As all + # pixels are not within threshold + for pt in test_utils.rect_area_pts(dest_rect): + self.assertEqual(dest_surf.get_at(pt), set_color) + + def test_threshold_count(self): + """counts the colors, and not changes them.""" + surf_size = (32, 32) + surf = pygame.Surface(surf_size, pygame.SRCALPHA, 32) + search_surf = pygame.Surface(surf_size, pygame.SRCALPHA, 32) + search_color = (55, 55, 55, 255) + original_color = (10, 10, 10, 255) + + surf.fill(original_color) + # set 2 pixels to the color we are searching for. + surf.set_at((0, 0), search_color) + surf.set_at((12, 5), search_color) + + # There is no destination surface, but we ask to change it. + # This should be an error. + self.assertRaises( + TypeError, pygame.transform.threshold, None, surf, search_color + ) + # from pygame.transform import THRESHOLD_BEHAVIOR_COUNT + THRESHOLD_BEHAVIOR_FROM_SEARCH_SURF = 2 + self.assertRaises( + TypeError, + pygame.transform.threshold, + None, + surf, + search_color, + set_behavior=THRESHOLD_BEHAVIOR_FROM_SEARCH_SURF, + ) + + THRESHOLD_BEHAVIOR_COUNT = 0 + num_threshold_pixels = pygame.transform.threshold( + dest_surface=None, + surface=surf, + search_color=search_color, + set_behavior=THRESHOLD_BEHAVIOR_COUNT, + ) + self.assertEqual(num_threshold_pixels, 2) + + def test_threshold_search_surf(self): + surf_size = (32, 32) + surf = pygame.Surface(surf_size, pygame.SRCALPHA, 32) + search_surf = pygame.Surface(surf_size, pygame.SRCALPHA, 32) + dest_surf = pygame.Surface(surf_size, pygame.SRCALPHA, 32) + + original_color = (10, 10, 10, 255) + search_color = (55, 55, 55, 255) + + surf.fill(original_color) + dest_surf.fill(original_color) + # set 2 pixels to the color we are searching for. + surf.set_at((0, 0), search_color) + surf.set_at((12, 5), search_color) + + search_surf.fill(search_color) + + # We look in the other surface for matching colors. + # Change it in dest_surf + THRESHOLD_BEHAVIOR_FROM_SEARCH_SURF = 2 + + # TypeError: if search_surf is used, search_color should be None + self.assertRaises( + TypeError, + pygame.transform.threshold, + dest_surf, + surf, + search_color, + set_behavior=THRESHOLD_BEHAVIOR_FROM_SEARCH_SURF, + search_surf=search_surf, + ) + + # surf, dest_surf, and search_surf should all be the same size. + # Check surface sizes are the same size. + different_sized_surf = pygame.Surface((22, 33), pygame.SRCALPHA, 32) + self.assertRaises( + TypeError, + pygame.transform.threshold, + different_sized_surf, + surf, + search_color=None, + set_color=None, + set_behavior=THRESHOLD_BEHAVIOR_FROM_SEARCH_SURF, + search_surf=search_surf, + ) + + self.assertRaises( + TypeError, + pygame.transform.threshold, + dest_surf, + surf, + search_color=None, + set_color=None, + set_behavior=THRESHOLD_BEHAVIOR_FROM_SEARCH_SURF, + search_surf=different_sized_surf, + ) + + # We look to see if colors in search_surf are in surf. + num_threshold_pixels = pygame.transform.threshold( + dest_surface=dest_surf, + surface=surf, + search_color=None, + set_color=None, + set_behavior=THRESHOLD_BEHAVIOR_FROM_SEARCH_SURF, + search_surf=search_surf, + ) + + num_pixels_within = 2 + self.assertEqual(num_threshold_pixels, num_pixels_within) + + dest_surf.fill(original_color) + num_threshold_pixels = pygame.transform.threshold( + dest_surf, + surf, + search_color=None, + set_color=None, + set_behavior=THRESHOLD_BEHAVIOR_FROM_SEARCH_SURF, + search_surf=search_surf, + inverse_set=True, + ) + + self.assertEqual(num_threshold_pixels, 2) + + def test_threshold_inverse_set(self): + """changes the pixels within the threshold, and not outside.""" + surf_size = (32, 32) + _dest_surf = pygame.Surface(surf_size, pygame.SRCALPHA, 32) + _surf = pygame.Surface(surf_size, pygame.SRCALPHA, 32) + + dest_surf = _dest_surf # surface we are changing. + surf = _surf # surface we are looking at + search_color = (55, 55, 55, 255) # color we are searching for. + threshold = (0, 0, 0, 0) # within this distance from search_color. + set_color = (245, 245, 245, 255) # color we set. + inverse_set = 1 # pixels within threshold are changed to 'set_color' + + original_color = (10, 10, 10, 255) + surf.fill(original_color) + # set 2 pixels to the color we are searching for. + surf.set_at((0, 0), search_color) + surf.set_at((12, 5), search_color) + + dest_surf.fill(original_color) + # set 2 pixels to the color we are searching for. + dest_surf.set_at((0, 0), search_color) + dest_surf.set_at((12, 5), search_color) + + THRESHOLD_BEHAVIOR_FROM_SEARCH_COLOR = 1 + num_threshold_pixels = pygame.transform.threshold( + dest_surf, + surf, + search_color=search_color, + threshold=threshold, + set_color=set_color, + set_behavior=THRESHOLD_BEHAVIOR_FROM_SEARCH_COLOR, + inverse_set=1, + ) + + self.assertEqual(num_threshold_pixels, 2) + # only two pixels changed to diff_color. + self.assertEqual(dest_surf.get_at((0, 0)), set_color) + self.assertEqual(dest_surf.get_at((12, 5)), set_color) + + # other pixels should be the same as they were before. + # We just check one other pixel, not all of them. + self.assertEqual(dest_surf.get_at((2, 2)), original_color) + + # XXX + def test_threshold_non_src_alpha(self): + + result = pygame.Surface((10, 10)) + s1 = pygame.Surface((10, 10)) + s2 = pygame.Surface((10, 10)) + s3 = pygame.Surface((10, 10)) + s4 = pygame.Surface((10, 10)) + + x = s1.fill((0, 0, 0)) + s1.set_at((0, 0), (32, 20, 0)) + + x = s2.fill((0, 20, 0)) + x = s3.fill((0, 0, 0)) + x = s4.fill((0, 0, 0)) + s2.set_at((0, 0), (33, 21, 0)) + s2.set_at((3, 0), (63, 61, 0)) + s3.set_at((0, 0), (112, 31, 0)) + s4.set_at((0, 0), (11, 31, 0)) + s4.set_at((1, 1), (12, 31, 0)) + + self.assertEqual(s1.get_at((0, 0)), (32, 20, 0, 255)) + self.assertEqual(s2.get_at((0, 0)), (33, 21, 0, 255)) + self.assertEqual((0, 0), (s1.get_flags(), s2.get_flags())) + + similar_color = (255, 255, 255, 255) + diff_color = (222, 0, 0, 255) + threshold_color = (20, 20, 20, 255) + + THRESHOLD_BEHAVIOR_FROM_SEARCH_COLOR = 1 + num_threshold_pixels = pygame.transform.threshold( + dest_surface=result, + surface=s1, + search_color=similar_color, + threshold=threshold_color, + set_color=diff_color, + set_behavior=THRESHOLD_BEHAVIOR_FROM_SEARCH_COLOR, + ) + self.assertEqual(num_threshold_pixels, 0) + + num_threshold_pixels = pygame.transform.threshold( + dest_surface=result, + surface=s1, + search_color=(40, 40, 0), + threshold=threshold_color, + set_color=diff_color, + set_behavior=THRESHOLD_BEHAVIOR_FROM_SEARCH_COLOR, + ) + self.assertEqual(num_threshold_pixels, 1) + + self.assertEqual(result.get_at((0, 0)), diff_color) + + def test_threshold__uneven_colors(self): + (w, h) = size = (16, 16) + + original_surface = pygame.Surface(size, pygame.SRCALPHA, 32) + dest_surface = pygame.Surface(size, pygame.SRCALPHA, 32) + + original_surface.fill(0) + + threshold_color_template = [5, 5, 5, 5] + threshold_template = [6, 6, 6, 6] + + ################################################################ + + for pos in range(len("rgb")): + threshold_color = threshold_color_template[:] + threshold = threshold_template[:] + + threshold_color[pos] = 45 + threshold[pos] = 50 + + pixels_within_threshold = pygame.transform.threshold( + None, + original_surface, + threshold_color, + threshold, + set_color=None, + set_behavior=0, + ) + + self.assertEqual(w * h, pixels_within_threshold) + + ################################################################ + + def test_threshold_set_behavior2(self): + """raises an error when set_behavior=2 and set_color is not None.""" + from pygame.transform import threshold + + s1 = pygame.Surface((32, 32), SRCALPHA, 32) + s2 = pygame.Surface((32, 32), SRCALPHA, 32) + THRESHOLD_BEHAVIOR_FROM_SEARCH_SURF = 2 + self.assertRaises( + TypeError, + threshold, + dest_surface=s2, + surface=s1, + search_color=(30, 30, 30), + threshold=(11, 11, 11), + set_color=(255, 0, 0), + set_behavior=THRESHOLD_BEHAVIOR_FROM_SEARCH_SURF, + ) + + def test_threshold_set_behavior0(self): + """raises an error when set_behavior=1 + and set_color is not None, + and dest_surf is not None. + """ + from pygame.transform import threshold + + s1 = pygame.Surface((32, 32), SRCALPHA, 32) + s2 = pygame.Surface((32, 32), SRCALPHA, 32) + THRESHOLD_BEHAVIOR_COUNT = 0 + + self.assertRaises( + TypeError, + threshold, + dest_surface=None, + surface=s2, + search_color=(30, 30, 30), + threshold=(11, 11, 11), + set_color=(0, 0, 0), + set_behavior=THRESHOLD_BEHAVIOR_COUNT, + ) + + self.assertRaises( + TypeError, + threshold, + dest_surface=s1, + surface=s2, + search_color=(30, 30, 30), + threshold=(11, 11, 11), + set_color=None, + set_behavior=THRESHOLD_BEHAVIOR_COUNT, + ) + + threshold( + dest_surface=None, + surface=s2, + search_color=(30, 30, 30), + threshold=(11, 11, 11), + set_color=None, + set_behavior=THRESHOLD_BEHAVIOR_COUNT, + ) + + def test_threshold_from_surface(self): + """Set similar pixels in 'dest_surf' to color in the 'surf'.""" + from pygame.transform import threshold + + surf = pygame.Surface((32, 32), SRCALPHA, 32) + dest_surf = pygame.Surface((32, 32), SRCALPHA, 32) + surf_color = (40, 40, 40, 255) + dest_color = (255, 255, 255) + surf.fill(surf_color) + dest_surf.fill(dest_color) + THRESHOLD_BEHAVIOR_FROM_SEARCH_SURF = 2 + + num_threshold_pixels = threshold( + dest_surface=dest_surf, + surface=surf, + search_color=(30, 30, 30), + threshold=(11, 11, 11), + set_color=None, + set_behavior=THRESHOLD_BEHAVIOR_FROM_SEARCH_SURF, + inverse_set=1, + ) + + self.assertEqual( + num_threshold_pixels, dest_surf.get_height() * dest_surf.get_width() + ) + self.assertEqual(dest_surf.get_at((0, 0)), surf_color) + + def test_threshold__surface(self): + """ """ + from pygame.transform import threshold + + s1 = pygame.Surface((32, 32), SRCALPHA, 32) + s2 = pygame.Surface((32, 32), SRCALPHA, 32) + s3 = pygame.Surface((1, 1), SRCALPHA, 32) + THRESHOLD_BEHAVIOR_FROM_SEARCH_SURF = 2 + + # # only one pixel should not be changed. + # s1.fill((40,40,40)) + # s2.fill((255,255,255)) + # s1.set_at( (0,0), (170, 170, 170) ) + # # set the similar pixels in destination surface to the color + # # in the first surface. + # num_threshold_pixels = threshold( + # dest_surface=s2, + # surface=s1, + # search_color=(30,30,30), + # threshold=(11,11,11), + # set_color=None, + # set_behavior=THRESHOLD_BEHAVIOR_FROM_SEARCH_SURF) + + # #num_threshold_pixels = threshold(s2, s1, (30,30,30)) + # self.assertEqual(num_threshold_pixels, (s1.get_height() * s1.get_width()) -1) + # self.assertEqual(s2.get_at((0,0)), (0,0,0, 255)) + # self.assertEqual(s2.get_at((0,1)), (40, 40, 40, 255)) + # self.assertEqual(s2.get_at((17,1)), (40, 40, 40, 255)) + + # # abs(40 - 255) < 100 + # #(abs(c1[0] - r) < tr) + + # s1.fill((160,160,160)) + # s2.fill((255,255,255)) + # num_threshold_pixels = threshold(s2, s1, (255,255,255), (100,100,100), (0,0,0), True) + + # self.assertEqual(num_threshold_pixels, (s1.get_height() * s1.get_width())) + + # only one pixel should not be changed. + s1.fill((40, 40, 40)) + s1.set_at((0, 0), (170, 170, 170)) + THRESHOLD_BEHAVIOR_COUNT = 0 + + num_threshold_pixels = threshold( + dest_surface=None, + surface=s1, + search_color=(30, 30, 30), + threshold=(11, 11, 11), + set_color=None, + set_behavior=THRESHOLD_BEHAVIOR_COUNT, + ) + + # num_threshold_pixels = threshold(s2, s1, (30,30,30)) + self.assertEqual(num_threshold_pixels, (s1.get_height() * s1.get_width()) - 1) + + # test end markers. 0, and 255 + + # the pixels are different by 1. + s1.fill((254, 254, 254)) + s2.fill((255, 255, 255)) + s3.fill((255, 255, 255)) + s1.set_at((0, 0), (170, 170, 170)) + num_threshold_pixels = threshold( + None, s1, (254, 254, 254), (1, 1, 1), None, THRESHOLD_BEHAVIOR_COUNT + ) + self.assertEqual(num_threshold_pixels, (s1.get_height() * s1.get_width()) - 1) + + # compare the two surfaces. Should be all but one matching. + num_threshold_pixels = threshold( + None, s1, None, (1, 1, 1), None, THRESHOLD_BEHAVIOR_COUNT, s2 + ) + self.assertEqual(num_threshold_pixels, (s1.get_height() * s1.get_width()) - 1) + + # within (0,0,0) threshold? Should match no pixels. + num_threshold_pixels = threshold( + None, s1, (253, 253, 253), (0, 0, 0), None, THRESHOLD_BEHAVIOR_COUNT + ) + self.assertEqual(num_threshold_pixels, 0) + + # other surface within (0,0,0) threshold? Should match no pixels. + num_threshold_pixels = threshold( + None, s1, None, (0, 0, 0), None, THRESHOLD_BEHAVIOR_COUNT, s2 + ) + self.assertEqual(num_threshold_pixels, 0) + + def test_threshold__subclassed_surface(self): + """Ensure threshold accepts subclassed surfaces.""" + expected_size = (13, 11) + expected_flags = 0 + expected_depth = 32 + expected_color = (90, 80, 70, 255) + expected_count = 0 + surface = test_utils.SurfaceSubclass( + expected_size, expected_flags, expected_depth + ) + dest_surface = test_utils.SurfaceSubclass( + expected_size, expected_flags, expected_depth + ) + search_surface = test_utils.SurfaceSubclass( + expected_size, expected_flags, expected_depth + ) + surface.fill((10, 10, 10)) + dest_surface.fill((255, 255, 255)) + search_surface.fill((20, 20, 20)) + + count = pygame.transform.threshold( + dest_surface=dest_surface, + surface=surface, + threshold=(1, 1, 1), + set_color=expected_color, + search_color=None, + search_surf=search_surface, + ) + + self.assertIsInstance(dest_surface, pygame.Surface) + self.assertIsInstance(dest_surface, test_utils.SurfaceSubclass) + self.assertEqual(count, expected_count) + self.assertEqual(dest_surface.get_at((0, 0)), expected_color) + self.assertEqual(dest_surface.get_bitsize(), expected_depth) + self.assertEqual(dest_surface.get_size(), expected_size) + self.assertEqual(dest_surface.get_flags(), expected_flags) + + def test_laplacian(self): + """ """ + + SIZE = 32 + s1 = pygame.Surface((SIZE, SIZE)) + s2 = pygame.Surface((SIZE, SIZE)) + s1.fill((10, 10, 70)) + pygame.draw.line(s1, (255, 0, 0), (3, 10), (20, 20)) + + # a line at the last row of the image. + pygame.draw.line(s1, (255, 0, 0), (0, 31), (31, 31)) + + pygame.transform.laplacian(s1, s2) + + # show_image(s1) + # show_image(s2) + + self.assertEqual(s2.get_at((0, 0)), (0, 0, 0, 255)) + self.assertEqual(s2.get_at((3, 10)), (255, 0, 0, 255)) + self.assertEqual(s2.get_at((0, 31)), (255, 0, 0, 255)) + self.assertEqual(s2.get_at((31, 31)), (255, 0, 0, 255)) + + # here we create the return surface. + s2 = pygame.transform.laplacian(s1) + + self.assertEqual(s2.get_at((0, 0)), (0, 0, 0, 255)) + self.assertEqual(s2.get_at((3, 10)), (255, 0, 0, 255)) + self.assertEqual(s2.get_at((0, 31)), (255, 0, 0, 255)) + self.assertEqual(s2.get_at((31, 31)), (255, 0, 0, 255)) + + def test_laplacian__24_big_endian(self): + """ """ + pygame.display.init() + try: + surf_1 = pygame.image.load( + example_path(os.path.join("data", "laplacian.png")) + ) + SIZE = 32 + surf_2 = pygame.Surface((SIZE, SIZE), 0, 24) + # s1.fill((10, 10, 70)) + # pygame.draw.line(s1, (255, 0, 0), (3, 10), (20, 20)) + + # a line at the last row of the image. + # pygame.draw.line(s1, (255, 0, 0), (0, 31), (31, 31)) + + # Also validate keyword arguments + pygame.transform.laplacian(surface=surf_1, dest_surface=surf_2) + + # show_image(s1) + # show_image(s2) + + self.assertEqual(surf_2.get_at((0, 0)), (0, 0, 0, 255)) + self.assertEqual(surf_2.get_at((3, 10)), (255, 0, 0, 255)) + self.assertEqual(surf_2.get_at((0, 31)), (255, 0, 0, 255)) + self.assertEqual(surf_2.get_at((31, 31)), (255, 0, 0, 255)) + + # here we create the return surface. + surf_2 = pygame.transform.laplacian(surf_1) + + self.assertEqual(surf_2.get_at((0, 0)), (0, 0, 0, 255)) + self.assertEqual(surf_2.get_at((3, 10)), (255, 0, 0, 255)) + self.assertEqual(surf_2.get_at((0, 31)), (255, 0, 0, 255)) + self.assertEqual(surf_2.get_at((31, 31)), (255, 0, 0, 255)) + finally: + pygame.display.quit() + + def test_average_surfaces(self): + """ """ + + SIZE = 32 + s1 = pygame.Surface((SIZE, SIZE)) + s2 = pygame.Surface((SIZE, SIZE)) + s3 = pygame.Surface((SIZE, SIZE)) + s1.fill((10, 10, 70)) + s2.fill((10, 20, 70)) + s3.fill((10, 130, 10)) + + surfaces = [s1, s2, s3] + surfaces = [s1, s2] + sr = pygame.transform.average_surfaces(surfaces) + + self.assertEqual(sr.get_at((0, 0)), (10, 15, 70, 255)) + + self.assertRaises(TypeError, pygame.transform.average_surfaces, 1) + self.assertRaises(TypeError, pygame.transform.average_surfaces, []) + + self.assertRaises(TypeError, pygame.transform.average_surfaces, [1]) + self.assertRaises(TypeError, pygame.transform.average_surfaces, [s1, 1]) + self.assertRaises(TypeError, pygame.transform.average_surfaces, [1, s1]) + self.assertRaises(TypeError, pygame.transform.average_surfaces, [s1, s2, 1]) + + self.assertRaises( + TypeError, pygame.transform.average_surfaces, (s for s in [s1, s2, s3]) + ) + + def test_average_surfaces__24(self): + + SIZE = 32 + depth = 24 + s1 = pygame.Surface((SIZE, SIZE), 0, depth) + s2 = pygame.Surface((SIZE, SIZE), 0, depth) + s3 = pygame.Surface((SIZE, SIZE), 0, depth) + s1.fill((10, 10, 70, 255)) + s2.fill((10, 20, 70, 255)) + s3.fill((10, 130, 10, 255)) + + surfaces = [s1, s2, s3] + sr = pygame.transform.average_surfaces(surfaces) + self.assertEqual(sr.get_masks(), s1.get_masks()) + self.assertEqual(sr.get_flags(), s1.get_flags()) + self.assertEqual(sr.get_losses(), s1.get_losses()) + + if 0: + print(sr, s1) + print(sr.get_masks(), s1.get_masks()) + print(sr.get_flags(), s1.get_flags()) + print(sr.get_losses(), s1.get_losses()) + print(sr.get_shifts(), s1.get_shifts()) + + self.assertEqual(sr.get_at((0, 0)), (10, 53, 50, 255)) + + def test_average_surfaces__24_big_endian(self): + pygame.display.init() + try: + surf_1 = pygame.image.load(example_path(os.path.join("data", "BGR.png"))) + + surf_2 = surf_1.copy() + + surfaces = [surf_1, surf_2] + self.assertEqual(surf_1.get_at((0, 0)), (255, 0, 0, 255)) + self.assertEqual(surf_2.get_at((0, 0)), (255, 0, 0, 255)) + + surf_av = pygame.transform.average_surfaces(surfaces) + self.assertEqual(surf_av.get_masks(), surf_1.get_masks()) + self.assertEqual(surf_av.get_flags(), surf_1.get_flags()) + self.assertEqual(surf_av.get_losses(), surf_1.get_losses()) + + self.assertEqual(surf_av.get_at((0, 0)), (255, 0, 0, 255)) + finally: + pygame.display.quit() + + def test_average_surfaces__subclassed_surfaces(self): + """Ensure average_surfaces accepts subclassed surfaces.""" + expected_size = (23, 17) + expected_flags = 0 + expected_depth = 32 + expected_color = (50, 50, 50, 255) + surfaces = [] + + for color in ((40, 60, 40), (60, 40, 60)): + s = test_utils.SurfaceSubclass( + expected_size, expected_flags, expected_depth + ) + s.fill(color) + surfaces.append(s) + + surface = pygame.transform.average_surfaces(surfaces) + + self.assertIsInstance(surface, pygame.Surface) + self.assertNotIsInstance(surface, test_utils.SurfaceSubclass) + self.assertEqual(surface.get_at((0, 0)), expected_color) + self.assertEqual(surface.get_bitsize(), expected_depth) + self.assertEqual(surface.get_size(), expected_size) + self.assertEqual(surface.get_flags(), expected_flags) + + def test_average_surfaces__subclassed_destination_surface(self): + """Ensure average_surfaces accepts a destination subclassed surface.""" + expected_size = (13, 27) + expected_flags = 0 + expected_depth = 32 + expected_color = (15, 15, 15, 255) + surfaces = [] + + for color in ((10, 10, 20), (20, 20, 10), (30, 30, 30)): + s = test_utils.SurfaceSubclass( + expected_size, expected_flags, expected_depth + ) + s.fill(color) + surfaces.append(s) + expected_dest_surface = surfaces.pop() + + # Also validate keyword arguments + dest_surface = pygame.transform.average_surfaces( + surfaces=surfaces, dest_surface=expected_dest_surface + ) + + self.assertIsInstance(dest_surface, pygame.Surface) + self.assertIsInstance(dest_surface, test_utils.SurfaceSubclass) + self.assertIs(dest_surface, expected_dest_surface) + self.assertEqual(dest_surface.get_at((0, 0)), expected_color) + self.assertEqual(dest_surface.get_bitsize(), expected_depth) + self.assertEqual(dest_surface.get_size(), expected_size) + self.assertEqual(dest_surface.get_flags(), expected_flags) + + def test_average_color(self): + """ """ + for i in (24, 32): + with self.subTest(f"Testing {i}-bit surface"): + s = pygame.Surface((32, 32), 0, i) + s.fill((0, 100, 200)) + s.fill((10, 50, 100), (0, 0, 16, 32)) + + self.assertEqual(pygame.transform.average_color(s), (5, 75, 150, 0)) + + # Also validate keyword arguments + avg_color = pygame.transform.average_color( + surface=s, rect=(16, 0, 16, 32) + ) + self.assertEqual(avg_color, (0, 100, 200, 0)) + + def test_rotate(self): + # setting colors and canvas + blue = (0, 0, 255, 255) + red = (255, 0, 0, 255) + black = (0, 0, 0) + canvas = pygame.Surface((3, 3)) + rotation = 0 + + canvas.set_at((2, 0), blue) + canvas.set_at((0, 2), red) + + self.assertEqual(canvas.get_at((0, 0)), black) + self.assertEqual(canvas.get_at((2, 0)), blue) + self.assertEqual(canvas.get_at((0, 2)), red) + + for i in range(0, 4): + if i % 2 == 0: + self.assertEqual(canvas.get_at((0, 0)), black) + elif i == 1: + self.assertEqual(canvas.get_at((0, 0)), blue) + elif i == 3: + self.assertEqual(canvas.get_at((0, 0)), red) + + rotation += 90 + # Also validate keyword arguments + canvas = pygame.transform.rotate(surface=canvas, angle=90) + + self.assertEqual(canvas.get_at((0, 0)), black) + + def test_rotate_of_0_sized_surface(self): + # This function just tests possible Segmentation Fault + canvas1 = pygame.Surface((0, 1)) + canvas2 = pygame.Surface((1, 0)) + pygame.transform.rotate(canvas1, 42) + pygame.transform.rotate(canvas2, 42) + + def test_rotate__lossless_at_90_degrees(self): + w, h = 32, 32 + s = pygame.Surface((w, h), pygame.SRCALPHA) + + gradient = list(test_utils.gradient(w, h)) + + for pt, color in gradient: + s.set_at(pt, color) + + for rotation in (90, -90): + s = pygame.transform.rotate(s, rotation) + + for pt, color in gradient: + self.assertTrue(s.get_at(pt) == color) + + def test_scale2x(self): + + # __doc__ (as of 2008-06-25) for pygame.transform.scale2x: + + # pygame.transform.scale2x(Surface, DestSurface = None): Surface + # specialized image doubler + + w, h = 32, 32 + s = pygame.Surface((w, h), pygame.SRCALPHA, 32) + + # s.set_at((0,0), (20, 20, 20, 255)) + + s1 = pygame.transform.scale2x(s) + # Also validate keyword arguments + s2 = pygame.transform.scale2x(surface=s) + self.assertEqual(s1.get_rect().size, (64, 64)) + self.assertEqual(s2.get_rect().size, (64, 64)) + + def test_scale2xraw(self): + w, h = 32, 32 + s = pygame.Surface((w, h), pygame.SRCALPHA, 32) + s.fill((0, 0, 0)) + pygame.draw.circle(s, (255, 0, 0), (w // 2, h // 2), (w // 3)) + + s2 = pygame.transform.scale(s, (w * 2, h * 2)) + s2_2 = pygame.transform.scale(s2, (w * 4, h * 4)) + s4 = pygame.transform.scale(s, (w * 4, h * 4)) + + self.assertEqual(s2_2.get_rect().size, (128, 128)) + + for pt in test_utils.rect_area_pts(s2_2.get_rect()): + self.assertEqual(s2_2.get_at(pt), s4.get_at(pt)) + + def test_get_smoothscale_backend(self): + filter_type = pygame.transform.get_smoothscale_backend() + self.assertTrue(filter_type in ["GENERIC", "MMX", "SSE"]) + # It would be nice to test if a non-generic type corresponds to an x86 + # processor. But there is no simple test for this. platform.machine() + # returns process version specific information, like 'i686'. + + def test_set_smoothscale_backend(self): + # All machines should allow 'GENERIC'. + original_type = pygame.transform.get_smoothscale_backend() + pygame.transform.set_smoothscale_backend("GENERIC") + filter_type = pygame.transform.get_smoothscale_backend() + self.assertEqual(filter_type, "GENERIC") + # All machines should allow returning to original value. + # Also check that keyword argument works. + pygame.transform.set_smoothscale_backend(backend=original_type) + # Something invalid. + def change(): + pygame.transform.set_smoothscale_backend("mmx") + + self.assertRaises(ValueError, change) + # Invalid argument keyword. + def change(): + pygame.transform.set_smoothscale_backend(t="GENERIC") + + self.assertRaises(TypeError, change) + # Invalid argument type. + def change(): + pygame.transform.set_smoothscale_backend(1) + + self.assertRaises(TypeError, change) + # Unsupported type, if possible. + if original_type != "SSE": + + def change(): + pygame.transform.set_smoothscale_backend("SSE") + + self.assertRaises(ValueError, change) + # Should be back where we started. + filter_type = pygame.transform.get_smoothscale_backend() + self.assertEqual(filter_type, original_type) + + def test_chop(self): + original_surface = pygame.Surface((20, 20)) + pygame.draw.rect(original_surface, (255, 0, 0), (0, 0, 10, 10)) + pygame.draw.rect(original_surface, (0, 255, 0), (0, 10, 10, 10)) + pygame.draw.rect(original_surface, (0, 0, 255), (10, 0, 10, 10)) + pygame.draw.rect(original_surface, (255, 255, 0), (10, 10, 10, 10)) + # Test chopping the corner of image + rect = pygame.Rect(0, 0, 5, 15) + test_surface = pygame.transform.chop(original_surface, rect) + # Check the size of chopped image + self.assertEqual(test_surface.get_size(), (15, 5)) + # Check if the colors of the chopped image are correct + for x in range(15): + for y in range(5): + if x < 5: + self.assertEqual(test_surface.get_at((x, y)), (0, 255, 0)) + else: + self.assertEqual(test_surface.get_at((x, y)), (255, 255, 0)) + # Check if the original image stayed the same + self.assertEqual(original_surface.get_size(), (20, 20)) + for x in range(20): + for y in range(20): + if x < 10 and y < 10: + self.assertEqual(original_surface.get_at((x, y)), (255, 0, 0)) + if x < 10 < y: + self.assertEqual(original_surface.get_at((x, y)), (0, 255, 0)) + if x > 10 > y: + self.assertEqual(original_surface.get_at((x, y)), (0, 0, 255)) + if x > 10 and y > 10: + self.assertEqual(original_surface.get_at((x, y)), (255, 255, 0)) + # Test chopping the center of the surface: + rect = pygame.Rect(0, 0, 10, 10) + rect.center = original_surface.get_rect().center + # Also validate keyword arguments + test_surface = pygame.transform.chop(surface=original_surface, rect=rect) + self.assertEqual(test_surface.get_size(), (10, 10)) + for x in range(10): + for y in range(10): + if x < 5 and y < 5: + self.assertEqual(test_surface.get_at((x, y)), (255, 0, 0)) + if x < 5 < y: + self.assertEqual(test_surface.get_at((x, y)), (0, 255, 0)) + if x > 5 > y: + self.assertEqual(test_surface.get_at((x, y)), (0, 0, 255)) + if x > 5 and y > 5: + self.assertEqual(test_surface.get_at((x, y)), (255, 255, 0)) + # Test chopping with the empty rect + rect = pygame.Rect(10, 10, 0, 0) + test_surface = pygame.transform.chop(original_surface, rect) + self.assertEqual(test_surface.get_size(), (20, 20)) + # Test chopping the entire surface + rect = pygame.Rect(0, 0, 20, 20) + test_surface = pygame.transform.chop(original_surface, rect) + self.assertEqual(test_surface.get_size(), (0, 0)) + # Test chopping outside of surface + rect = pygame.Rect(5, 15, 20, 20) + test_surface = pygame.transform.chop(original_surface, rect) + self.assertEqual(test_surface.get_size(), (5, 15)) + rect = pygame.Rect(400, 400, 10, 10) + test_surface = pygame.transform.chop(original_surface, rect) + self.assertEqual(test_surface.get_size(), (20, 20)) + + def test_rotozoom(self): + + # __doc__ (as of 2008-08-02) for pygame.transform.rotozoom: + + # pygame.transform.rotozoom(Surface, angle, scale): return Surface + # filtered scale and rotation + # + # This is a combined scale and rotation transform. The resulting + # Surface will be a filtered 32-bit Surface. The scale argument is a + # floating point value that will be multiplied by the current + # resolution. The angle argument is a floating point value that + # represents the counterclockwise degrees to rotate. A negative + # rotation angle will rotate clockwise. + + s = pygame.Surface((10, 0)) + pygame.transform.scale(s, (10, 2)) + s1 = pygame.transform.rotozoom(s, 30, 1) + # Also validate keyword arguments + s2 = pygame.transform.rotozoom(surface=s, angle=30, scale=1) + + self.assertEqual(s1.get_rect(), pygame.Rect(0, 0, 0, 0)) + self.assertEqual(s2.get_rect(), pygame.Rect(0, 0, 0, 0)) + + def test_smoothscale(self): + """Tests the stated boundaries, sizing, and color blending of smoothscale function""" + # __doc__ (as of 2008-08-02) for pygame.transform.smoothscale: + + # pygame.transform.smoothscale(Surface, (width, height), DestSurface = + # None): return Surface + # + # scale a surface to an arbitrary size smoothly + # + # Uses one of two different algorithms for scaling each dimension of + # the input surface as required. For shrinkage, the output pixels are + # area averages of the colors they cover. For expansion, a bilinear + # filter is used. For the amd64 and i686 architectures, optimized MMX + # routines are included and will run much faster than other machine + # types. The size is a 2 number sequence for (width, height). This + # function only works for 24-bit or 32-bit surfaces. An exception + # will be thrown if the input surface bit depth is less than 24. + # + # New in pygame 1.8 + + # check stated exceptions + def smoothscale_low_bpp(): + starting_surface = pygame.Surface((20, 20), depth=12) + smoothscaled_surface = pygame.transform.smoothscale( + starting_surface, (10, 10) + ) + + self.assertRaises(ValueError, smoothscale_low_bpp) + + def smoothscale_high_bpp(): + starting_surface = pygame.Surface((20, 20), depth=48) + smoothscaled_surface = pygame.transform.smoothscale( + starting_surface, (10, 10) + ) + + self.assertRaises(ValueError, smoothscale_high_bpp) + + def smoothscale_invalid_scale(): + starting_surface = pygame.Surface((20, 20), depth=32) + smoothscaled_surface = pygame.transform.smoothscale( + starting_surface, (-1, -1) + ) + + self.assertRaises(ValueError, smoothscale_invalid_scale) + + # Test Color Blending Scaling-Up + two_pixel_surface = pygame.Surface((2, 1), depth=32) + two_pixel_surface.fill(pygame.Color(0, 0, 0), pygame.Rect(0, 0, 1, 1)) + two_pixel_surface.fill(pygame.Color(255, 255, 255), pygame.Rect(1, 0, 1, 1)) + for k in [2 ** x for x in range(5, 8)]: # Enlarge to targets 32, 64...256 + bigger_surface = pygame.transform.smoothscale(two_pixel_surface, (k, 1)) + self.assertEqual( + bigger_surface.get_at((k // 2, 0)), pygame.Color(127, 127, 127) + ) + self.assertEqual(bigger_surface.get_size(), (k, 1)) + # Test Color Blending Scaling-Down + two_five_six_surf = pygame.Surface((256, 1), depth=32) + two_five_six_surf.fill(pygame.Color(0, 0, 0), pygame.Rect(0, 0, 128, 1)) + two_five_six_surf.fill(pygame.Color(255, 255, 255), pygame.Rect(128, 0, 128, 1)) + for k in range(3, 11, 2): # Shrink to targets 3, 5...11 pixels wide + smaller_surface = pygame.transform.smoothscale(two_five_six_surf, (k, 1)) + self.assertEqual( + smaller_surface.get_at(((k // 2), 0)), pygame.Color(127, 127, 127) + ) + self.assertEqual(smaller_surface.get_size(), (k, 1)) + + +class TransformDisplayModuleTest(unittest.TestCase): + def setUp(self): + pygame.display.init() + pygame.display.set_mode((320, 200)) + + def tearDown(self): + pygame.display.quit() + + def test_flip(self): + """honors the set_color key on the returned surface from flip.""" + image_loaded = pygame.image.load(example_path("data/chimp.png")) + + image = pygame.Surface(image_loaded.get_size(), 0, 32) + image.blit(image_loaded, (0, 0)) + + image_converted = image_loaded.convert() + + self.assertFalse(image.get_flags() & pygame.SRCALPHA) + self.assertFalse(image_converted.get_flags() & pygame.SRCALPHA) + + surf = pygame.Surface(image.get_size(), 0, 32) + surf2 = pygame.Surface(image.get_size(), 0, 32) + + surf.fill((255, 255, 255)) + surf2.fill((255, 255, 255)) + + colorkey = image.get_at((0, 0)) + image.set_colorkey(colorkey, RLEACCEL) + timage = pygame.transform.flip(image, 1, 0) + + colorkey = image_converted.get_at((0, 0)) + image_converted.set_colorkey(colorkey, RLEACCEL) + # Also validate keyword arguments + timage_converted = pygame.transform.flip( + surface=image_converted, flip_x=1, flip_y=0 + ) + + # blit the flipped surface, and non flipped surface. + surf.blit(timage, (0, 0)) + surf2.blit(image, (0, 0)) + + # the results should be the same. + self.assertEqual(surf.get_at((0, 0)), surf2.get_at((0, 0))) + self.assertEqual(surf2.get_at((0, 0)), (255, 255, 255, 255)) + + # now we test the convert() ed image also works. + surf.fill((255, 255, 255)) + surf2.fill((255, 255, 255)) + surf.blit(timage_converted, (0, 0)) + surf2.blit(image_converted, (0, 0)) + self.assertEqual(surf.get_at((0, 0)), surf2.get_at((0, 0))) + + def test_flip_alpha(self): + """returns a surface with the same properties as the input.""" + image_loaded = pygame.image.load(example_path("data/chimp.png")) + + image_alpha = pygame.Surface(image_loaded.get_size(), pygame.SRCALPHA, 32) + image_alpha.blit(image_loaded, (0, 0)) + + surf = pygame.Surface(image_loaded.get_size(), 0, 32) + surf2 = pygame.Surface(image_loaded.get_size(), 0, 32) + + colorkey = image_alpha.get_at((0, 0)) + image_alpha.set_colorkey(colorkey, RLEACCEL) + timage_alpha = pygame.transform.flip(image_alpha, 1, 0) + + self.assertTrue(image_alpha.get_flags() & pygame.SRCALPHA) + self.assertTrue(timage_alpha.get_flags() & pygame.SRCALPHA) + + # now we test the alpha image works. + surf.fill((255, 255, 255)) + surf2.fill((255, 255, 255)) + surf.blit(timage_alpha, (0, 0)) + surf2.blit(image_alpha, (0, 0)) + self.assertEqual(surf.get_at((0, 0)), surf2.get_at((0, 0))) + self.assertEqual(surf2.get_at((0, 0)), (255, 0, 0, 255)) + + +if __name__ == "__main__": + unittest.main() diff --git a/venv/Lib/site-packages/pygame/tests/version_test.py b/venv/Lib/site-packages/pygame/tests/version_test.py new file mode 100644 index 0000000..ba0bb3d --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/version_test.py @@ -0,0 +1,48 @@ +import os +import unittest + + +pg_header = os.path.join("src_c", "include", "_pygame.h") + + +class VersionTest(unittest.TestCase): + @unittest.skipIf( + not os.path.isfile(pg_header), "Skipping because we cannot find _pygame.h" + ) + def test_pg_version_consistency(self): + from pygame import version + + pgh_major = -1 + pgh_minor = -1 + pgh_patch = -1 + import re + + major_exp_search = re.compile(r"define\s+PG_MAJOR_VERSION\s+([0-9]+)").search + minor_exp_search = re.compile(r"define\s+PG_MINOR_VERSION\s+([0-9]+)").search + patch_exp_search = re.compile(r"define\s+PG_PATCH_VERSION\s+([0-9]+)").search + with open(pg_header) as f: + for line in f: + if pgh_major == -1: + m = major_exp_search(line) + if m: + pgh_major = int(m.group(1)) + if pgh_minor == -1: + m = minor_exp_search(line) + if m: + pgh_minor = int(m.group(1)) + if pgh_patch == -1: + m = patch_exp_search(line) + if m: + pgh_patch = int(m.group(1)) + self.assertEqual(pgh_major, version.vernum[0]) + self.assertEqual(pgh_minor, version.vernum[1]) + self.assertEqual(pgh_patch, version.vernum[2]) + + def test_sdl_version(self): + from pygame import version + + self.assertEqual(len(version.SDL), 3) + + +if __name__ == "__main__": + unittest.main() diff --git a/venv/Lib/site-packages/pygame/tests/video_test.py b/venv/Lib/site-packages/pygame/tests/video_test.py new file mode 100644 index 0000000..a6a6473 --- /dev/null +++ b/venv/Lib/site-packages/pygame/tests/video_test.py @@ -0,0 +1,26 @@ +import unittest +import sys +import pygame + +from pygame._sdl2 import video + + +class VideoModuleTest(unittest.TestCase): + default_caption = "pygame window" + + @unittest.skipIf( + not (sys.maxsize > 2 ** 32), + "32 bit SDL 2.0.16 has an issue.", + ) + def test_renderer_set_viewport(self): + """works.""" + window = video.Window(title=self.default_caption, size=(800, 600)) + renderer = video.Renderer(window=window) + renderer.logical_size = (1920, 1080) + rect = pygame.Rect(0, 0, 1920, 1080) + renderer.set_viewport(rect) + self.assertEqual(renderer.get_viewport(), (0, 0, 1920, 1080)) + + +if __name__ == "__main__": + unittest.main() diff --git a/venv/Lib/site-packages/pygame/threads/__init__.py b/venv/Lib/site-packages/pygame/threads/__init__.py new file mode 100644 index 0000000..89db392 --- /dev/null +++ b/venv/Lib/site-packages/pygame/threads/__init__.py @@ -0,0 +1,272 @@ +""" +* Experimental * + +Like the map function, but can use a pool of threads. + +Really easy to use threads. eg. tmap(f, alist) + +If you know how to use the map function, you can use threads. +""" + +__author__ = "Rene Dudfield" +__version__ = "0.3.0" +__license__ = "Python license" + +from queue import Queue, Empty +import threading + + +Thread = threading.Thread + +STOP = object() +FINISH = object() + +# DONE_ONE = object() +# DONE_TWO = object() + +# a default worker queue. +_wq = None + +# if we are using threads or not. This is the number of workers. +_use_workers = 0 + +# Set this to the maximum for the amount of Cores/CPUs +# Note, that the tests early out. +# So it should only test the best number of workers +2 +MAX_WORKERS_TO_TEST = 64 + + +def init(number_of_workers=0): + """Does a little test to see if threading is worth it. + Sets up a global worker queue if it's worth it. + + Calling init() is not required, but is generally better to do. + """ + global _wq, _use_workers + + if number_of_workers: + _use_workers = number_of_workers + else: + _use_workers = benchmark_workers() + + # if it is best to use zero workers, then use that. + _wq = WorkerQueue(_use_workers) + + +def quit(): + """cleans up everything.""" + global _wq, _use_workers + _wq.stop() + _wq = None + _use_workers = False + + +def benchmark_workers(a_bench_func=None, the_data=None): + """does a little test to see if workers are at all faster. + Returns the number of workers which works best. + Takes a little bit of time to run, so you should only really call + it once. + You can pass in benchmark data, and functions if you want. + a_bench_func - f(data) + the_data - data to work on. + """ + # TODO: try and make this scale better with slower/faster cpus. + # first find some variables so that using 0 workers takes about 1.0 seconds. + # then go from there. + + # note, this will only work with pygame 1.8rc3+ + # replace the doit() and the_data with something that releases the GIL + + import pygame + import pygame.transform + import time + + if not a_bench_func: + + def doit(x): + return pygame.transform.scale(x, (544, 576)) + + else: + doit = a_bench_func + + if not the_data: + thedata = [pygame.Surface((155, 155), 0, 32) for x in range(10)] + else: + thedata = the_data + + best = time.time() + 100000000 + best_number = 0 + # last_best = -1 + + for num_workers in range(0, MAX_WORKERS_TO_TEST): + + wq = WorkerQueue(num_workers) + t1 = time.time() + for _ in range(20): + print(f"active count:{threading.activeCount()}") + tmap(doit, thedata, worker_queue=wq) + t2 = time.time() + + wq.stop() + + total_time = t2 - t1 + print(f"total time num_workers:{num_workers}: time:{total_time}:") + + if total_time < best: + # last_best = best_number + best_number = num_workers + best = total_time + + if num_workers - best_number > 1: + # We tried to add more, but it didn't like it. + # so we stop with testing at this number. + break + + return best_number + + +class WorkerQueue(object): + def __init__(self, num_workers=20): + self.queue = Queue() + self.pool = [] + self._setup_workers(num_workers) + + def _setup_workers(self, num_workers): + """Sets up the worker threads + NOTE: undefined behaviour if you call this again. + """ + self.pool = [] + + for _ in range(num_workers): + self.pool.append(Thread(target=self.threadloop)) + + for a_thread in self.pool: + a_thread.setDaemon(True) + a_thread.start() + + def do(self, f, *args, **kwArgs): + """puts a function on a queue for running later.""" + self.queue.put((f, args, kwArgs)) + + def stop(self): + """Stops the WorkerQueue, waits for all of the threads to finish up.""" + self.queue.put(STOP) + for thread in self.pool: + thread.join() + + def threadloop(self): # , finish=False): + """Loops until all of the tasks are finished.""" + while True: + args = self.queue.get() + if args is STOP: + self.queue.put(STOP) + self.queue.task_done() + break + try: + args[0](*args[1], **args[2]) + finally: + # clean up the queue, raise the exception. + self.queue.task_done() + # raise + + def wait(self): + """waits until all tasks are complete.""" + self.queue.join() + + +class FuncResult: + """Used for wrapping up a function call so that the results are stored + inside the instances result attribute. + """ + + def __init__(self, f, callback=None, errback=None): + """f - is the function we that we call + callback(result) - this is called when the function(f) returns + errback(exception) - this is called when the function(f) raises + an exception. + """ + self.f = f + self.exception = None + self.result = None + self.callback = callback + self.errback = errback + + def __call__(self, *args, **kwargs): + # we try to call the function here. If it fails we store the exception. + try: + self.result = self.f(*args, **kwargs) + if self.callback: + self.callback(self.result) + except Exception as e: + self.exception = e + if self.errback: + self.errback(self.exception) + + +def tmap(f, seq_args, num_workers=20, worker_queue=None, wait=True, stop_on_error=True): + """like map, but uses a thread pool to execute. + num_workers - the number of worker threads that will be used. If pool + is passed in, then the num_workers arg is ignored. + worker_queue - you can optionally pass in an existing WorkerQueue. + wait - True means that the results are returned when everything is finished. + False means that we return the [worker_queue, results] right away instead. + results, is returned as a list of FuncResult instances. + stop_on_error - + """ + + if worker_queue: + wq = worker_queue + else: + # see if we have a global queue to work with. + if _wq: + wq = _wq + else: + if num_workers == 0: + return map(f, seq_args) + + wq = WorkerQueue(num_workers) + + # we short cut it here if the number of workers is 0. + # normal map should be faster in this case. + if len(wq.pool) == 0: + return map(f, seq_args) + + # print ("queue size:%s" % wq.queue.qsize()) + + # TODO: divide the data (seq_args) into even chunks and + # then pass each thread a map(f, equal_part(seq_args)) + # That way there should be less locking, and overhead. + + results = [] + for sa in seq_args: + results.append(FuncResult(f)) + wq.do(results[-1], sa) + + # wq.stop() + + if wait: + # print ("wait") + wq.wait() + # print ("after wait") + # print ("queue size:%s" % wq.queue.qsize()) + if wq.queue.qsize(): + raise Exception("buggy threadmap") + # if we created a worker queue, we need to stop it. + if not worker_queue and not _wq: + # print ("stoping") + wq.stop() + if wq.queue.qsize(): + um = wq.queue.get() + if not um is STOP: + raise Exception("buggy threadmap") + + # see if there were any errors. If so raise the first one. This matches map behaviour. + # TODO: the traceback doesn't show up nicely. + # NOTE: TODO: we might want to return the results anyway? This should be an option. + if stop_on_error: + error_ones = list(filter(lambda x: x.exception, results)) + if error_ones: + raise error_ones[0].exception + + return map(lambda x: x.result, results) + return [wq, results] diff --git a/venv/Lib/site-packages/pygame/threads/__pycache__/__init__.cpython-39.pyc b/venv/Lib/site-packages/pygame/threads/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..958b7a4fd397070225a9ed9797f93a8a413910c2 GIT binary patch literal 6542 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 b*9f>cfV1^I*Qq~DfeE$Ccs!>+a literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/time.cp39-win_amd64.pyd b/venv/Lib/site-packages/pygame/time.cp39-win_amd64.pyd new file mode 100644 index 0000000000000000000000000000000000000000..8a632235aa8064ae4cd71b94c5f40f27904505b8 GIT binary patch literal 18944 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 H4UGRk-2G3U literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/time.pyi b/venv/Lib/site-packages/pygame/time.pyi new file mode 100644 index 0000000..f938442 --- /dev/null +++ b/venv/Lib/site-packages/pygame/time.pyi @@ -0,0 +1,15 @@ +from typing import Union + +from pygame.event import Event + +def get_ticks() -> int: ... +def wait(milliseconds: int) -> int: ... +def delay(milliseconds: int) -> int: ... +def set_timer(event: Union[int, Event], millis: int, loops: int = 0) -> None: ... + +class Clock: + def tick(self, framerate: int = 0) -> int: ... + def tick_busy_loop(self, framerate: int = 0) -> int: ... + def get_time(self) -> int: ... + def get_rawtime(self) -> int: ... + def get_fps(self) -> float: ... diff --git a/venv/Lib/site-packages/pygame/transform.cp39-win_amd64.pyd b/venv/Lib/site-packages/pygame/transform.cp39-win_amd64.pyd new file mode 100644 index 0000000000000000000000000000000000000000..cb646b301353456f8468594c9a10c7c409800ac7 GIT binary patch literal 52224 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 i%MNExX1!TGJDr`)&SmGb3)#i& Surface: ... +def scale( + surface: Surface, + size: _Coordinate, + dest_surface: Optional[Surface] = None, +) -> Surface: ... +def rotate(surface: Surface, angle: float) -> Surface: ... +def rotozoom(surface: Surface, angle: float, scale: float) -> Surface: ... +def scale2x(surface: Surface, dest_surface: Optional[Surface] = None) -> Surface: ... +def smoothscale( + surface: Surface, + size: _Coordinate, + dest_surface: Optional[Surface] = None, +) -> Surface: ... +def get_smoothscale_backend() -> str: ... +def set_smoothscale_backend(backend: str) -> None: ... +def chop(surface: Surface, rect: _RectValue) -> Surface: ... +def laplacian(surface: Surface, dest_surface: Optional[Surface] = None) -> Surface: ... +def average_surfaces( + surfaces: Sequence[Surface], + dest_surface: Optional[Surface] = None, + palette_colors: Union[bool, int] = 1, +) -> Surface: ... +def average_color(surface: Surface, rect: Optional[_RectValue] = None) -> Color: ... +def threshold( + dest_surface: Optional[Surface], + surface: Surface, + search_color: Optional[_ColorValue], + threshold: Optional[_ColorValue] = (0, 0, 0, 0), + set_color: Optional[_ColorValue] = (0, 0, 0, 0), + set_behavior: Optional[int] = 1, + search_surf: Optional[Surface] = None, + inverse_set: Optional[bool] = False, +) -> int: ... diff --git a/venv/Lib/site-packages/pygame/version.py b/venv/Lib/site-packages/pygame/version.py new file mode 100644 index 0000000..b287dba --- /dev/null +++ b/venv/Lib/site-packages/pygame/version.py @@ -0,0 +1,72 @@ +## pygame - Python Game Library +## Copyright (C) 2000-2003 Pete Shinners +## +## This library is free software; you can redistribute it and/or +## modify it under the terms of the GNU Library General Public +## License as published by the Free Software Foundation; either +## version 2 of the License, or (at your option) any later version. +## +## This library is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## Library General Public License for more details. +## +## You should have received a copy of the GNU Library General Public +## License along with this library; if not, write to the Free +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +## +## Pete Shinners +## pete@shinners.org + +"""Simply the current installed pygame version. The version information is +stored in the regular pygame module as 'pygame.ver'. Keeping the version +information also available in a separate module allows you to test the +pygame version without importing the main pygame module. + +The python version information should always compare greater than any previous +releases. (hmm, until we get to versions > 10) +""" +from pygame.base import get_sdl_version + +############### +# This file is generated with version.py.in +## + +class SoftwareVersion(tuple): + """ + A class for storing data about software versions. + """ + __slots__ = () + fields = "major", "minor", "patch" + + def __new__(cls, major, minor, patch): + return tuple.__new__(cls, (major, minor, patch)) + + def __repr__(self): + fields = (f"{fld}={val}" for fld, val in zip(self.fields, self)) + return f"{str(self.__class__.__name__)}({', '.join(fields)})" + + def __str__(self): + return f"{self.major}.{self.minor}.{self.patch}" + + major = property(lambda self: self[0]) + minor = property(lambda self: self[1]) + patch = property(lambda self: self[2]) + +class PygameVersion(SoftwareVersion): + """ + Pygame Version class. + """ + +class SDLVersion(SoftwareVersion): + """ + SDL Version class. + """ + +_sdl_tuple = get_sdl_version() +SDL = SDLVersion(_sdl_tuple[0], _sdl_tuple[1], _sdl_tuple[2]) +ver = "2.1.2" # pylint: disable=invalid-name +vernum = PygameVersion(2, 1, 2) +rev = "" # pylint: disable=invalid-name + +__all__ = ["SDL", "ver", "vernum", "rev"] diff --git a/venv/Lib/site-packages/pygame/version.pyi b/venv/Lib/site-packages/pygame/version.pyi new file mode 100644 index 0000000..41f2132 --- /dev/null +++ b/venv/Lib/site-packages/pygame/version.pyi @@ -0,0 +1,17 @@ +from typing import Tuple + +class SoftwareVersion(Tuple[int, int, int]): + def __new__(cls, major: int, minor: int, patch: int) -> PygameVersion: ... + def __repr__(self) -> str: ... + def __str__(self) -> str: ... + major: int + minor: int + patch: int + +class PygameVersion(SoftwareVersion): ... +class SDLVersion(SoftwareVersion): ... + +SDL: SDLVersion +ver: str +vernum: PygameVersion +rev: str diff --git a/venv/Lib/site-packages/pygame/zlib1.dll b/venv/Lib/site-packages/pygame/zlib1.dll new file mode 100644 index 0000000000000000000000000000000000000000..e7493de315264b254bdf914737274034e9017598 GIT binary patch literal 108544 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools-60.9.3.dist-info/INSTALLER b/venv/Lib/site-packages/setuptools-60.9.3.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/venv/Lib/site-packages/setuptools-60.9.3.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/venv/Lib/site-packages/setuptools-60.9.3.dist-info/LICENSE b/venv/Lib/site-packages/setuptools-60.9.3.dist-info/LICENSE new file mode 100644 index 0000000..353924b --- /dev/null +++ b/venv/Lib/site-packages/setuptools-60.9.3.dist-info/LICENSE @@ -0,0 +1,19 @@ +Copyright Jason R. Coombs + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. diff --git a/venv/Lib/site-packages/setuptools-60.9.3.dist-info/METADATA b/venv/Lib/site-packages/setuptools-60.9.3.dist-info/METADATA new file mode 100644 index 0000000..394db51 --- /dev/null +++ b/venv/Lib/site-packages/setuptools-60.9.3.dist-info/METADATA @@ -0,0 +1,142 @@ +Metadata-Version: 2.1 +Name: setuptools +Version: 60.9.3 +Summary: Easily download, build, install, upgrade, and uninstall Python packages +Home-page: https://github.com/pypa/setuptools +Author: Python Packaging Authority +Author-email: distutils-sig@python.org +License: UNKNOWN +Project-URL: Documentation, https://setuptools.pypa.io/ +Keywords: CPAN PyPI distutils eggs package management +Platform: UNKNOWN +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: MIT License +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3 :: Only +Classifier: Topic :: Software Development :: Libraries :: Python Modules +Classifier: Topic :: System :: Archiving :: Packaging +Classifier: Topic :: System :: Systems Administration +Classifier: Topic :: Utilities +Requires-Python: >=3.7 +License-File: LICENSE +Provides-Extra: certs +Provides-Extra: docs +Requires-Dist: sphinx ; extra == 'docs' +Requires-Dist: jaraco.packaging (>=9) ; extra == 'docs' +Requires-Dist: rst.linker (>=1.9) ; extra == 'docs' +Requires-Dist: jaraco.tidelift (>=1.4) ; extra == 'docs' +Requires-Dist: pygments-github-lexers (==0.0.5) ; extra == 'docs' +Requires-Dist: sphinx-favicon ; extra == 'docs' +Requires-Dist: sphinx-inline-tabs ; extra == 'docs' +Requires-Dist: sphinxcontrib-towncrier ; extra == 'docs' +Requires-Dist: furo ; extra == 'docs' +Provides-Extra: ssl +Provides-Extra: testing +Requires-Dist: pytest (>=6) ; extra == 'testing' +Requires-Dist: pytest-checkdocs (>=2.4) ; extra == 'testing' +Requires-Dist: pytest-flake8 ; extra == 'testing' +Requires-Dist: pytest-enabler (>=1.0.1) ; extra == 'testing' +Requires-Dist: pytest-perf ; extra == 'testing' +Requires-Dist: mock ; extra == 'testing' +Requires-Dist: flake8-2020 ; extra == 'testing' +Requires-Dist: virtualenv (>=13.0.0) ; extra == 'testing' +Requires-Dist: wheel ; extra == 'testing' +Requires-Dist: pip (>=19.1) ; extra == 'testing' +Requires-Dist: jaraco.envs (>=2.2) ; extra == 'testing' +Requires-Dist: pytest-xdist ; extra == 'testing' +Requires-Dist: sphinx (>=4.3.2) ; extra == 'testing' +Requires-Dist: jaraco.path (>=3.2.0) ; extra == 'testing' +Requires-Dist: build[virtualenv] ; extra == 'testing' +Requires-Dist: filelock (>=3.4.0) ; extra == 'testing' +Requires-Dist: pip-run (>=8.8) ; extra == 'testing' +Provides-Extra: testing-integration +Requires-Dist: pytest ; extra == 'testing-integration' +Requires-Dist: pytest-xdist ; extra == 'testing-integration' +Requires-Dist: pytest-enabler ; extra == 'testing-integration' +Requires-Dist: virtualenv (>=13.0.0) ; extra == 'testing-integration' +Requires-Dist: tomli ; extra == 'testing-integration' +Requires-Dist: wheel ; extra == 'testing-integration' +Requires-Dist: jaraco.path (>=3.2.0) ; extra == 'testing-integration' +Requires-Dist: jaraco.envs (>=2.2) ; extra == 'testing-integration' +Requires-Dist: build[virtualenv] ; extra == 'testing-integration' +Requires-Dist: filelock (>=3.4.0) ; extra == 'testing-integration' +Requires-Dist: pytest-black (>=0.3.7) ; (platform_python_implementation != "PyPy") and extra == 'testing' +Requires-Dist: pytest-cov ; (platform_python_implementation != "PyPy") and extra == 'testing' +Requires-Dist: pytest-mypy (>=0.9.1) ; (platform_python_implementation != "PyPy") and extra == 'testing' + +.. image:: https://raw.githubusercontent.com/pypa/setuptools/main/docs/images/banner-640x320.svg + :align: center + +| + +.. image:: https://img.shields.io/pypi/v/setuptools.svg + :target: `PyPI link`_ + +.. image:: https://img.shields.io/pypi/pyversions/setuptools.svg + :target: `PyPI link`_ + +.. _PyPI link: https://pypi.org/project/setuptools + +.. image:: https://github.com/pypa/setuptools/workflows/tests/badge.svg + :target: https://github.com/pypa/setuptools/actions?query=workflow%3A%22tests%22 + :alt: tests + +.. image:: https://img.shields.io/badge/code%20style-black-000000.svg + :target: https://github.com/psf/black + :alt: Code style: Black + +.. image:: https://img.shields.io/readthedocs/setuptools/latest.svg + :target: https://setuptools.pypa.io + +.. image:: https://img.shields.io/badge/skeleton-2022-informational + :target: https://blog.jaraco.com/skeleton + +.. image:: https://img.shields.io/codecov/c/github/pypa/setuptools/master.svg?logo=codecov&logoColor=white + :target: https://codecov.io/gh/pypa/setuptools + +.. image:: https://tidelift.com/badges/github/pypa/setuptools?style=flat + :target: https://tidelift.com/subscription/pkg/pypi-setuptools?utm_source=pypi-setuptools&utm_medium=readme + +.. image:: https://img.shields.io/discord/803025117553754132 + :target: https://discord.com/channels/803025117553754132/815945031150993468 + :alt: Discord + +See the `Installation Instructions +`_ in the Python Packaging +User's Guide for instructions on installing, upgrading, and uninstalling +Setuptools. + +Questions and comments should be directed to `GitHub Discussions +`_. +Bug reports and especially tested patches may be +submitted directly to the `bug tracker +`_. + + +Code of Conduct +=============== + +Everyone interacting in the setuptools project's codebases, issue trackers, +chat rooms, and fora is expected to follow the +`PSF Code of Conduct `_. + + +For Enterprise +============== + +Available as part of the Tidelift Subscription. + +Setuptools and the maintainers of thousands of other packages are working with Tidelift to deliver one enterprise subscription that covers all of the open source you use. + +`Learn more `_. + + +Security Contact +================ + +To report a security vulnerability, please use the +`Tidelift security contact `_. +Tidelift will coordinate the fix and disclosure. + + diff --git a/venv/Lib/site-packages/setuptools-60.9.3.dist-info/RECORD b/venv/Lib/site-packages/setuptools-60.9.3.dist-info/RECORD new file mode 100644 index 0000000..f48ee7a --- /dev/null +++ b/venv/Lib/site-packages/setuptools-60.9.3.dist-info/RECORD @@ -0,0 +1,389 @@ +_distutils_hack/__init__.py,sha256=Am1CVQftk_MHAKvfJQVpQMwVx3lrAbKGPhKIUgwawDY,5298 +_distutils_hack/__pycache__/__init__.cpython-39.pyc,, +_distutils_hack/__pycache__/override.cpython-39.pyc,, +_distutils_hack/override.py,sha256=Eu_s-NF6VIZ4Cqd0tbbA5wtWky2IZPNd8et6GLt1mzo,44 +distutils-precedence.pth,sha256=JjjOniUA5XKl4N5_rtZmHrVp0baW_LoHsN0iPaX10iQ,151 +pkg_resources/__init__.py,sha256=NssS5SQg4XHYfyygmvKvSjlzq9hhdwvr66DL0I5-bO8,107935 +pkg_resources/__pycache__/__init__.cpython-39.pyc,, +pkg_resources/_vendor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pkg_resources/_vendor/__pycache__/__init__.cpython-39.pyc,, +pkg_resources/_vendor/__pycache__/appdirs.cpython-39.pyc,, +pkg_resources/_vendor/__pycache__/pyparsing.cpython-39.pyc,, +pkg_resources/_vendor/__pycache__/zipp.cpython-39.pyc,, +pkg_resources/_vendor/appdirs.py,sha256=MievUEuv3l_mQISH5SF0shDk_BNhHHzYiAPrT3ITN4I,24701 +pkg_resources/_vendor/importlib_resources/__init__.py,sha256=evPm12kLgYqTm-pbzm60bOuumumT8IpBNWFp0uMyrzE,506 +pkg_resources/_vendor/importlib_resources/__pycache__/__init__.cpython-39.pyc,, +pkg_resources/_vendor/importlib_resources/__pycache__/_adapters.cpython-39.pyc,, +pkg_resources/_vendor/importlib_resources/__pycache__/_common.cpython-39.pyc,, +pkg_resources/_vendor/importlib_resources/__pycache__/_compat.cpython-39.pyc,, +pkg_resources/_vendor/importlib_resources/__pycache__/_itertools.cpython-39.pyc,, +pkg_resources/_vendor/importlib_resources/__pycache__/_legacy.cpython-39.pyc,, +pkg_resources/_vendor/importlib_resources/__pycache__/abc.cpython-39.pyc,, +pkg_resources/_vendor/importlib_resources/__pycache__/readers.cpython-39.pyc,, +pkg_resources/_vendor/importlib_resources/__pycache__/simple.cpython-39.pyc,, +pkg_resources/_vendor/importlib_resources/_adapters.py,sha256=o51tP2hpVtohP33gSYyAkGNpLfYDBqxxYsadyiRZi1E,4504 +pkg_resources/_vendor/importlib_resources/_common.py,sha256=iIxAaQhotSh6TLLUEfL_ynU2fzEeyHMz9JcL46mUhLg,2741 +pkg_resources/_vendor/importlib_resources/_compat.py,sha256=nFBCGMvImglrqgYkb9aPgOj68-h6xbw-ca94XOv1-zs,2706 +pkg_resources/_vendor/importlib_resources/_itertools.py,sha256=WCdJ1Gs_kNFwKENyIG7TO0Y434IWCu0zjVVSsSbZwU8,884 +pkg_resources/_vendor/importlib_resources/_legacy.py,sha256=TMLkx6aEM6U8xIREPXqGZrMbUhTiPUuPl6ESD7RdYj4,3494 +pkg_resources/_vendor/importlib_resources/abc.py,sha256=MvTJJXajbl74s36Gyeesf76egtbFnh-TMtzQMVhFWXo,3886 +pkg_resources/_vendor/importlib_resources/readers.py,sha256=_9QLGQ5AzrED3PY8S2Zf8V6yLR0-nqqYqtQmgleDJzY,3566 +pkg_resources/_vendor/importlib_resources/simple.py,sha256=xt0qhXbwt3bZ86zuaaKbTiE9A0mDbwu0saRjUq_pcY0,2836 +pkg_resources/_vendor/jaraco/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +pkg_resources/_vendor/jaraco/__pycache__/__init__.cpython-39.pyc,, +pkg_resources/_vendor/jaraco/__pycache__/context.cpython-39.pyc,, +pkg_resources/_vendor/jaraco/__pycache__/functools.cpython-39.pyc,, +pkg_resources/_vendor/jaraco/context.py,sha256=7X1tpCLc5EN45iWGzGcsH0Unx62REIkvtRvglj0SiUA,5420 +pkg_resources/_vendor/jaraco/functools.py,sha256=eLwPh8FWY7rQ_cj1YxCekUkibTuerwyoJ_41H7Q7oWM,13515 +pkg_resources/_vendor/jaraco/text/__init__.py,sha256=cN55bFcceW4wTHG5ruv5IuEDRarP-4hBYX8zl94_c30,15526 +pkg_resources/_vendor/jaraco/text/__pycache__/__init__.cpython-39.pyc,, +pkg_resources/_vendor/more_itertools/__init__.py,sha256=ZQYu_9H6stSG7viUgT32TFqslqcZwq82kWRZooKiI8Y,83 +pkg_resources/_vendor/more_itertools/__pycache__/__init__.cpython-39.pyc,, +pkg_resources/_vendor/more_itertools/__pycache__/more.cpython-39.pyc,, +pkg_resources/_vendor/more_itertools/__pycache__/recipes.cpython-39.pyc,, +pkg_resources/_vendor/more_itertools/more.py,sha256=oave_26jctLsuF30e1SOWMgW0bEuwS-t08wkaLUwvXc,132569 +pkg_resources/_vendor/more_itertools/recipes.py,sha256=N6aCDwoIPvE-aiqpGU-nbFwqiM3X8MKRcxBM84naW88,18410 +pkg_resources/_vendor/packaging/__about__.py,sha256=ugASIO2w1oUyH8_COqQ2X_s0rDhjbhQC3yJocD03h2c,661 +pkg_resources/_vendor/packaging/__init__.py,sha256=b9Kk5MF7KxhhLgcDmiUWukN-LatWFxPdNug0joPhHSk,497 +pkg_resources/_vendor/packaging/__pycache__/__about__.cpython-39.pyc,, +pkg_resources/_vendor/packaging/__pycache__/__init__.cpython-39.pyc,, +pkg_resources/_vendor/packaging/__pycache__/_manylinux.cpython-39.pyc,, +pkg_resources/_vendor/packaging/__pycache__/_musllinux.cpython-39.pyc,, +pkg_resources/_vendor/packaging/__pycache__/_structures.cpython-39.pyc,, +pkg_resources/_vendor/packaging/__pycache__/markers.cpython-39.pyc,, +pkg_resources/_vendor/packaging/__pycache__/requirements.cpython-39.pyc,, +pkg_resources/_vendor/packaging/__pycache__/specifiers.cpython-39.pyc,, +pkg_resources/_vendor/packaging/__pycache__/tags.cpython-39.pyc,, +pkg_resources/_vendor/packaging/__pycache__/utils.cpython-39.pyc,, +pkg_resources/_vendor/packaging/__pycache__/version.cpython-39.pyc,, +pkg_resources/_vendor/packaging/_manylinux.py,sha256=XcbiXB-qcjv3bcohp6N98TMpOP4_j3m-iOA8ptK2GWY,11488 +pkg_resources/_vendor/packaging/_musllinux.py,sha256=_KGgY_qc7vhMGpoqss25n2hiLCNKRtvz9mCrS7gkqyc,4378 +pkg_resources/_vendor/packaging/_structures.py,sha256=q3eVNmbWJGG_S0Dit_S3Ao8qQqz_5PYTXFAKBZe5yr4,1431 +pkg_resources/_vendor/packaging/markers.py,sha256=gFSKoBTb0sKDw1v_apJy15lPr0v2mEvuEkfooTtcWx4,8496 +pkg_resources/_vendor/packaging/requirements.py,sha256=uJ4cjwm3_nrfHJLCcGU9mT5aw8SXfw8v1aBUD7OFuVs,4706 +pkg_resources/_vendor/packaging/specifiers.py,sha256=LRQ0kFsHrl5qfcFNEEJrIFYsnIHQUJXY9fIsakTrrqE,30110 +pkg_resources/_vendor/packaging/tags.py,sha256=lmsnGNiJ8C4D_Pf9PbM0qgbZvD9kmB9lpZBQUZa3R_Y,15699 +pkg_resources/_vendor/packaging/utils.py,sha256=dJjeat3BS-TYn1RrUFVwufUMasbtzLfYRoy_HXENeFQ,4200 +pkg_resources/_vendor/packaging/version.py,sha256=_fLRNrFrxYcHVfyo8vk9j8s6JM8N_xsSxVFr6RJyco8,14665 +pkg_resources/_vendor/pyparsing.py,sha256=tmrp-lu-qO1i75ZzIN5A12nKRRD1Cm4Vpk-5LR9rims,232055 +pkg_resources/_vendor/zipp.py,sha256=ajztOH-9I7KA_4wqDYygtHa6xUBVZgFpmZ8FE74HHHI,8425 +pkg_resources/extern/__init__.py,sha256=inFoCK9jn_yRFqkbNSOxOYyZD0aB3awch_xtbwIW_-Y,2426 +pkg_resources/extern/__pycache__/__init__.cpython-39.pyc,, +setuptools-60.9.3.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +setuptools-60.9.3.dist-info/LICENSE,sha256=2z8CRrH5J48VhFuZ_sR4uLUG63ZIeZNyL4xuJUKF-vg,1050 +setuptools-60.9.3.dist-info/METADATA,sha256=YdoPvPFkCgYd185e5NKDeC7wKoAYULKUuzTS_klv8ws,5979 +setuptools-60.9.3.dist-info/RECORD,, +setuptools-60.9.3.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92 +setuptools-60.9.3.dist-info/entry_points.txt,sha256=wGnbIm7sqODfIXBH1z7YfkG4xXIks1fD-hFCtQrVaE4,2635 +setuptools-60.9.3.dist-info/top_level.txt,sha256=d9yL39v_W7qmKDDSH6sT4bE0j_Ls1M3P161OGgdsm4g,41 +setuptools/__init__.py,sha256=84lf54h_UbIkYxMn3ZqKyiaC9R86vnmIZUdTT-wxqeg,7461 +setuptools/__pycache__/__init__.cpython-39.pyc,, +setuptools/__pycache__/_deprecation_warning.cpython-39.pyc,, +setuptools/__pycache__/_entry_points.cpython-39.pyc,, +setuptools/__pycache__/_imp.cpython-39.pyc,, +setuptools/__pycache__/_importlib.cpython-39.pyc,, +setuptools/__pycache__/_itertools.cpython-39.pyc,, +setuptools/__pycache__/_path.cpython-39.pyc,, +setuptools/__pycache__/_reqs.cpython-39.pyc,, +setuptools/__pycache__/archive_util.cpython-39.pyc,, +setuptools/__pycache__/build_meta.cpython-39.pyc,, +setuptools/__pycache__/config.cpython-39.pyc,, +setuptools/__pycache__/dep_util.cpython-39.pyc,, +setuptools/__pycache__/depends.cpython-39.pyc,, +setuptools/__pycache__/dist.cpython-39.pyc,, +setuptools/__pycache__/errors.cpython-39.pyc,, +setuptools/__pycache__/extension.cpython-39.pyc,, +setuptools/__pycache__/glob.cpython-39.pyc,, +setuptools/__pycache__/installer.cpython-39.pyc,, +setuptools/__pycache__/launch.cpython-39.pyc,, +setuptools/__pycache__/logging.cpython-39.pyc,, +setuptools/__pycache__/monkey.cpython-39.pyc,, +setuptools/__pycache__/msvc.cpython-39.pyc,, +setuptools/__pycache__/namespaces.cpython-39.pyc,, +setuptools/__pycache__/package_index.cpython-39.pyc,, +setuptools/__pycache__/py34compat.cpython-39.pyc,, +setuptools/__pycache__/sandbox.cpython-39.pyc,, +setuptools/__pycache__/unicode_utils.cpython-39.pyc,, +setuptools/__pycache__/version.cpython-39.pyc,, +setuptools/__pycache__/wheel.cpython-39.pyc,, +setuptools/__pycache__/windows_support.cpython-39.pyc,, +setuptools/_deprecation_warning.py,sha256=jU9-dtfv6cKmtQJOXN8nP1mm7gONw5kKEtiPtbwnZyI,218 +setuptools/_distutils/__init__.py,sha256=3YtkfadGoU57VMEQFk2TNyMZVud1kDkakWQLhWg2Fm8,536 +setuptools/_distutils/__pycache__/__init__.cpython-39.pyc,, +setuptools/_distutils/__pycache__/_collections.cpython-39.pyc,, +setuptools/_distutils/__pycache__/_msvccompiler.cpython-39.pyc,, +setuptools/_distutils/__pycache__/archive_util.cpython-39.pyc,, +setuptools/_distutils/__pycache__/bcppcompiler.cpython-39.pyc,, +setuptools/_distutils/__pycache__/ccompiler.cpython-39.pyc,, +setuptools/_distutils/__pycache__/cmd.cpython-39.pyc,, +setuptools/_distutils/__pycache__/config.cpython-39.pyc,, +setuptools/_distutils/__pycache__/core.cpython-39.pyc,, +setuptools/_distutils/__pycache__/cygwinccompiler.cpython-39.pyc,, +setuptools/_distutils/__pycache__/debug.cpython-39.pyc,, +setuptools/_distutils/__pycache__/dep_util.cpython-39.pyc,, +setuptools/_distutils/__pycache__/dir_util.cpython-39.pyc,, +setuptools/_distutils/__pycache__/dist.cpython-39.pyc,, +setuptools/_distutils/__pycache__/errors.cpython-39.pyc,, +setuptools/_distutils/__pycache__/extension.cpython-39.pyc,, +setuptools/_distutils/__pycache__/fancy_getopt.cpython-39.pyc,, +setuptools/_distutils/__pycache__/file_util.cpython-39.pyc,, +setuptools/_distutils/__pycache__/filelist.cpython-39.pyc,, +setuptools/_distutils/__pycache__/log.cpython-39.pyc,, +setuptools/_distutils/__pycache__/msvc9compiler.cpython-39.pyc,, +setuptools/_distutils/__pycache__/msvccompiler.cpython-39.pyc,, +setuptools/_distutils/__pycache__/py35compat.cpython-39.pyc,, +setuptools/_distutils/__pycache__/py38compat.cpython-39.pyc,, +setuptools/_distutils/__pycache__/spawn.cpython-39.pyc,, +setuptools/_distutils/__pycache__/sysconfig.cpython-39.pyc,, +setuptools/_distutils/__pycache__/text_file.cpython-39.pyc,, +setuptools/_distutils/__pycache__/unixccompiler.cpython-39.pyc,, +setuptools/_distutils/__pycache__/util.cpython-39.pyc,, +setuptools/_distutils/__pycache__/version.cpython-39.pyc,, +setuptools/_distutils/__pycache__/versionpredicate.cpython-39.pyc,, +setuptools/_distutils/_collections.py,sha256=s7zkSh7QUyJWEYSt5n10ouAZNDYvux8YCHnnY3k0wmQ,1330 +setuptools/_distutils/_msvccompiler.py,sha256=i8vRyUE3jqX5BLzVa3ZeLheyEoKN6KGJDJ44Tlz69ww,20809 +setuptools/_distutils/archive_util.py,sha256=qW-uiGwYexTvK5e-iSel_31Dshx-CqTanNPK6snwf98,8572 +setuptools/_distutils/bcppcompiler.py,sha256=gJqtPboJZl1llfCtjo_SVCE1DdjgK1H2rd0Vngz18QI,14885 +setuptools/_distutils/ccompiler.py,sha256=YbernlpGZZqKnfzZSfJ814fINca8cicZiUlBjyUPyaM,47644 +setuptools/_distutils/cmd.py,sha256=eco6LAGUtobLuPafuhmgKgkwRRL_WY8KJ4YeDCHpcls,18079 +setuptools/_distutils/command/__init__.py,sha256=2TA-rlNDlzeI-csbWHXFjGD8uOYqALMfyWOhT49nC6g,799 +setuptools/_distutils/command/__pycache__/__init__.cpython-39.pyc,, +setuptools/_distutils/command/__pycache__/bdist.cpython-39.pyc,, +setuptools/_distutils/command/__pycache__/bdist_dumb.cpython-39.pyc,, +setuptools/_distutils/command/__pycache__/bdist_msi.cpython-39.pyc,, +setuptools/_distutils/command/__pycache__/bdist_rpm.cpython-39.pyc,, +setuptools/_distutils/command/__pycache__/bdist_wininst.cpython-39.pyc,, +setuptools/_distutils/command/__pycache__/build.cpython-39.pyc,, +setuptools/_distutils/command/__pycache__/build_clib.cpython-39.pyc,, +setuptools/_distutils/command/__pycache__/build_ext.cpython-39.pyc,, +setuptools/_distutils/command/__pycache__/build_py.cpython-39.pyc,, +setuptools/_distutils/command/__pycache__/build_scripts.cpython-39.pyc,, +setuptools/_distutils/command/__pycache__/check.cpython-39.pyc,, +setuptools/_distutils/command/__pycache__/clean.cpython-39.pyc,, +setuptools/_distutils/command/__pycache__/config.cpython-39.pyc,, +setuptools/_distutils/command/__pycache__/install.cpython-39.pyc,, +setuptools/_distutils/command/__pycache__/install_data.cpython-39.pyc,, +setuptools/_distutils/command/__pycache__/install_egg_info.cpython-39.pyc,, +setuptools/_distutils/command/__pycache__/install_headers.cpython-39.pyc,, +setuptools/_distutils/command/__pycache__/install_lib.cpython-39.pyc,, +setuptools/_distutils/command/__pycache__/install_scripts.cpython-39.pyc,, +setuptools/_distutils/command/__pycache__/py37compat.cpython-39.pyc,, +setuptools/_distutils/command/__pycache__/register.cpython-39.pyc,, +setuptools/_distutils/command/__pycache__/sdist.cpython-39.pyc,, +setuptools/_distutils/command/__pycache__/upload.cpython-39.pyc,, +setuptools/_distutils/command/bdist.py,sha256=2z4eudRl_n7m3lG9leL0IYqes4bsm8c0fxfZuiafjMg,5562 +setuptools/_distutils/command/bdist_dumb.py,sha256=BTur9jcIppyP7Piavjfsk7YjElqvxeYO2npUyPPOekc,4913 +setuptools/_distutils/command/bdist_msi.py,sha256=9Q1f4Pw4PRsg54fqHVgH8FZb78-yN4D5VlDC2KugX0A,35574 +setuptools/_distutils/command/bdist_rpm.py,sha256=gjOw22GhDSbcq0bdq25cTb-n6HWWm0bShLQad_mkJ4k,21537 +setuptools/_distutils/command/bdist_wininst.py,sha256=iGlaI-VfElHOneeczKHWnSN5a10-7IMcJaXuR1mdS3c,16030 +setuptools/_distutils/command/build.py,sha256=1AF-dxN_NlOEyoydBz19AwpeWYPSYCZvOLJSN_PdatY,5773 +setuptools/_distutils/command/build_clib.py,sha256=bgVTHh28eLQA2Gkw68amApd_j7qQBX4MTI-zTvAK_J4,8022 +setuptools/_distutils/command/build_ext.py,sha256=KgxpopuD6sqep0LsumMH15joWih0VdbnXpYm-ETNjoE,31612 +setuptools/_distutils/command/build_py.py,sha256=hXesMrH_epNj6K8SUtJdipgEis3EdICKeZ8VWe_ndck,16495 +setuptools/_distutils/command/build_scripts.py,sha256=urdn6wPxPMW5dLqpqFkZ8dqaFG1tf9TiAao6U9LCoEI,5963 +setuptools/_distutils/command/check.py,sha256=brOziX0PqvmfGYSUQlSA93m8b7T350uQwrOowwgNxqE,5630 +setuptools/_distutils/command/clean.py,sha256=2TCt47ru4hZZM0RfVfUYj5bbpicpGLP4Qhw5jBtvp9k,2776 +setuptools/_distutils/command/config.py,sha256=2aTjww3PwjMB8-ZibCe4P7B-qG1hM1gn_rJXYyxRz6c,13117 +setuptools/_distutils/command/install.py,sha256=dsCo4g_FG6SMsX_TIJQ-qaHWbgdjupBBie4-dfm793o,30075 +setuptools/_distutils/command/install_data.py,sha256=YhGOAwh3gJPqF7em5XA0rmpR42z1bLh80ooElzDyUvk,2822 +setuptools/_distutils/command/install_egg_info.py,sha256=WijZ7cHMAkNMMCwrZ--KoqV9M2RtLouU4-qSbiCwv70,2753 +setuptools/_distutils/command/install_headers.py,sha256=XQ6idkbIDfr1ljXCOznuVUMvOFpHBn6cK0Wz9gIM2b4,1298 +setuptools/_distutils/command/install_lib.py,sha256=9AofR-MO9lAtjwwuukCptepOaJEKMZW2VHiyR5hU7HA,8397 +setuptools/_distutils/command/install_scripts.py,sha256=_CLUeQwGJRcY2kik7azPMn5IdtDCrjWdUvZ1khlG6ck,2017 +setuptools/_distutils/command/py37compat.py,sha256=qzRhhvTihqx_PZZt2ZYECxh1X3Oj255VqatzelYFAKw,671 +setuptools/_distutils/command/register.py,sha256=2jaq9968rt2puRVDBx1HbNiXv27uOk8idE_4lPf_3VM,11712 +setuptools/_distutils/command/sdist.py,sha256=qotJjAOzyhJjq2-oDImjNFrOtaSneEFDJTB-sEk1wnU,19005 +setuptools/_distutils/command/upload.py,sha256=BLO1w7eSAqsCjCLXtf_CRVSjwF1WmyOByGVGNdcQ8oY,7597 +setuptools/_distutils/config.py,sha256=dtHgblx9JhfyrKx1-J7Jlxw_f7s8ZbPFQii2UWMTZpY,4827 +setuptools/_distutils/core.py,sha256=0v7Emh9y0AW9o4AEjfVMhDxKzTFWFxUQn46spFSL56g,9282 +setuptools/_distutils/cygwinccompiler.py,sha256=eOMXcoZ_Reto4VQR_lWK-IylR1Lsi_RW0MMwCqhlvtU,14521 +setuptools/_distutils/debug.py,sha256=N6MrTAqK6l9SVk6tWweR108PM8Ol7qNlfyV-nHcLhsY,139 +setuptools/_distutils/dep_util.py,sha256=GuR9Iw_jzZRkyemJ5HX8rB_wRGxkIBcBm1qh54r7zhk,3491 +setuptools/_distutils/dir_util.py,sha256=UwhBOUTcV65GTwce4SPuTXR8Z8q3LYEcmttqcGb0bYo,7778 +setuptools/_distutils/dist.py,sha256=Biuf6ca8uiFfMScRFsYUKtb5neMPtxKxRtXn50_1f3U,50421 +setuptools/_distutils/errors.py,sha256=Yr6tKZGdzBoNi53vBtiq0UJ__X05CmxSdQJqOWaw6SY,3577 +setuptools/_distutils/extension.py,sha256=bTb3Q0CoevGKYv5dX1ls--Ln8tlB0-UEOsi9BwzlZ-s,10515 +setuptools/_distutils/fancy_getopt.py,sha256=OPxp2CxHi1Yp_d1D8JxW4Ueq9fC71tegQFaafh58GGU,17784 +setuptools/_distutils/file_util.py,sha256=0hUqfItN_x2DVihR0MHdA4KCMVCOO8VoByaFp_a6MDg,8148 +setuptools/_distutils/filelist.py,sha256=Z9f5hvepZnpniZ2IFmCnWIjdviWozs8sbARBhWajwoM,13407 +setuptools/_distutils/log.py,sha256=gZ0wCQvSMzrS_6ccOhtvceqigM77oT_GKB_nnooRIXo,1973 +setuptools/_distutils/msvc9compiler.py,sha256=XXs85TZO4quRKOdWUk6ylcD-1f_QAm4ceiHbiW5tH-k,30474 +setuptools/_distutils/msvccompiler.py,sha256=E-Fm6eLWnRr-sSRpHGOq6ezJ7YCnDuM3MV7_i9wiTRg,23531 +setuptools/_distutils/py35compat.py,sha256=-sk1vBIsOgH-AobjIYbK_OEjdJF_54Ul_D1EiE9XM_c,455 +setuptools/_distutils/py38compat.py,sha256=II7ddBxOijC7uNN4z_46HYUjwYTJYMNiLJoGTormZm0,212 +setuptools/_distutils/spawn.py,sha256=rbPiTTUGLIo0QtzS-n04HuzXh15ztDcUDJ94vXfheFY,3474 +setuptools/_distutils/sysconfig.py,sha256=MJ2B3ARCEVi0TqHjTTQVxIfKLsQ1BUF__cfT9nCjTb4,21103 +setuptools/_distutils/text_file.py,sha256=PsuAJeWdKJoLSV_6N6IpB5-0Pa84KzLUucJMFRazw3I,12483 +setuptools/_distutils/unixccompiler.py,sha256=u2Sfs6LRmqQux4nZW08GwDtoFMded6wYnkiaO2TvKC4,14538 +setuptools/_distutils/util.py,sha256=2WMXovrYPE-Uc06ckbV-mHgm9IKsaQ4nUdSGiK-9w_I,18537 +setuptools/_distutils/version.py,sha256=syRvPxuMQxnftpuIKeRE-2ELQ_ZMCwMJ-o8ie-lxdZo,13015 +setuptools/_distutils/versionpredicate.py,sha256=vx4ND3BtMgxFR9iZ4_t3WFa-NdIKxO8vtOd0twBppxc,5277 +setuptools/_entry_points.py,sha256=5rRyEuiC0tdEsoCRJ6NWii5RET134mtDtjoSTFdLCwA,1972 +setuptools/_imp.py,sha256=HmF91IbitRfsD5z-g4_wmcuH-RahyIONbPgiCOFgtzA,2392 +setuptools/_importlib.py,sha256=VItIWibvlzNI2QEko84WAmLh0b0_iVFd8TtjY0AekjY,891 +setuptools/_itertools.py,sha256=pZAgXNz6tRPUFnHAaKJ90xAgD0gLPemcE1396Zgz73o,675 +setuptools/_path.py,sha256=nMzHs8z0MXh_MsQG3ndRrWsQS1q2u_E_-0QxeVqXfkk,176 +setuptools/_reqs.py,sha256=ApdTOmDFyK7hbHDnAH8VwhtVD5kvnOthyMNTmrUeFXs,501 +setuptools/_vendor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +setuptools/_vendor/__pycache__/__init__.cpython-39.pyc,, +setuptools/_vendor/__pycache__/ordered_set.cpython-39.pyc,, +setuptools/_vendor/__pycache__/pyparsing.cpython-39.pyc,, +setuptools/_vendor/__pycache__/typing_extensions.cpython-39.pyc,, +setuptools/_vendor/__pycache__/zipp.cpython-39.pyc,, +setuptools/_vendor/importlib_metadata/__init__.py,sha256=xRXwTtvg4EAYuBotYeGawbjraQD4GFIvKgMClxApCDY,30130 +setuptools/_vendor/importlib_metadata/__pycache__/__init__.cpython-39.pyc,, +setuptools/_vendor/importlib_metadata/__pycache__/_adapters.cpython-39.pyc,, +setuptools/_vendor/importlib_metadata/__pycache__/_collections.cpython-39.pyc,, +setuptools/_vendor/importlib_metadata/__pycache__/_compat.cpython-39.pyc,, +setuptools/_vendor/importlib_metadata/__pycache__/_functools.cpython-39.pyc,, +setuptools/_vendor/importlib_metadata/__pycache__/_itertools.cpython-39.pyc,, +setuptools/_vendor/importlib_metadata/__pycache__/_meta.cpython-39.pyc,, +setuptools/_vendor/importlib_metadata/__pycache__/_text.cpython-39.pyc,, +setuptools/_vendor/importlib_metadata/_adapters.py,sha256=B6fCi5-8mLVDFUZj3krI5nAo-mKp1dH_qIavyIyFrJs,1862 +setuptools/_vendor/importlib_metadata/_collections.py,sha256=CJ0OTCHIjWA0ZIVS4voORAsn2R4R2cQBEtPsZEJpASY,743 +setuptools/_vendor/importlib_metadata/_compat.py,sha256=cotBaMUB-2pIRZboQnWp9fEqm6Dwlypndn-EEn0bj5M,1828 +setuptools/_vendor/importlib_metadata/_functools.py,sha256=PsY2-4rrKX4RVeRC1oGp1lB1pmC9eKN88_f-bD9uOoA,2895 +setuptools/_vendor/importlib_metadata/_itertools.py,sha256=cvr_2v8BRbxcIl5x5ldfqdHjhI8Yi8s8yk50G_nm6jQ,2068 +setuptools/_vendor/importlib_metadata/_meta.py,sha256=_F48Hu_jFxkfKWz5wcYS8vO23qEygbVdF9r-6qh-hjE,1154 +setuptools/_vendor/importlib_metadata/_text.py,sha256=HCsFksZpJLeTP3NEk_ngrAeXVRRtTrtyh9eOABoRP4A,2166 +setuptools/_vendor/importlib_resources/__init__.py,sha256=evPm12kLgYqTm-pbzm60bOuumumT8IpBNWFp0uMyrzE,506 +setuptools/_vendor/importlib_resources/__pycache__/__init__.cpython-39.pyc,, +setuptools/_vendor/importlib_resources/__pycache__/_adapters.cpython-39.pyc,, +setuptools/_vendor/importlib_resources/__pycache__/_common.cpython-39.pyc,, +setuptools/_vendor/importlib_resources/__pycache__/_compat.cpython-39.pyc,, +setuptools/_vendor/importlib_resources/__pycache__/_itertools.cpython-39.pyc,, +setuptools/_vendor/importlib_resources/__pycache__/_legacy.cpython-39.pyc,, +setuptools/_vendor/importlib_resources/__pycache__/abc.cpython-39.pyc,, +setuptools/_vendor/importlib_resources/__pycache__/readers.cpython-39.pyc,, +setuptools/_vendor/importlib_resources/__pycache__/simple.cpython-39.pyc,, +setuptools/_vendor/importlib_resources/_adapters.py,sha256=o51tP2hpVtohP33gSYyAkGNpLfYDBqxxYsadyiRZi1E,4504 +setuptools/_vendor/importlib_resources/_common.py,sha256=iIxAaQhotSh6TLLUEfL_ynU2fzEeyHMz9JcL46mUhLg,2741 +setuptools/_vendor/importlib_resources/_compat.py,sha256=nFBCGMvImglrqgYkb9aPgOj68-h6xbw-ca94XOv1-zs,2706 +setuptools/_vendor/importlib_resources/_itertools.py,sha256=WCdJ1Gs_kNFwKENyIG7TO0Y434IWCu0zjVVSsSbZwU8,884 +setuptools/_vendor/importlib_resources/_legacy.py,sha256=TMLkx6aEM6U8xIREPXqGZrMbUhTiPUuPl6ESD7RdYj4,3494 +setuptools/_vendor/importlib_resources/abc.py,sha256=MvTJJXajbl74s36Gyeesf76egtbFnh-TMtzQMVhFWXo,3886 +setuptools/_vendor/importlib_resources/readers.py,sha256=_9QLGQ5AzrED3PY8S2Zf8V6yLR0-nqqYqtQmgleDJzY,3566 +setuptools/_vendor/importlib_resources/simple.py,sha256=xt0qhXbwt3bZ86zuaaKbTiE9A0mDbwu0saRjUq_pcY0,2836 +setuptools/_vendor/jaraco/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +setuptools/_vendor/jaraco/__pycache__/__init__.cpython-39.pyc,, +setuptools/_vendor/jaraco/__pycache__/context.cpython-39.pyc,, +setuptools/_vendor/jaraco/__pycache__/functools.cpython-39.pyc,, +setuptools/_vendor/jaraco/context.py,sha256=7X1tpCLc5EN45iWGzGcsH0Unx62REIkvtRvglj0SiUA,5420 +setuptools/_vendor/jaraco/functools.py,sha256=ap1qoXaNABOx897366NTMEd2objrqAoSO1zuxZPjcmM,13512 +setuptools/_vendor/jaraco/text/__init__.py,sha256=KfFGMerrkN_0V0rgtJVx-9dHt3tW7i_uJypjwEcLtC0,15517 +setuptools/_vendor/jaraco/text/__pycache__/__init__.cpython-39.pyc,, +setuptools/_vendor/more_itertools/__init__.py,sha256=C7sXffHTXM3P-iaLPPfqfmDoxOflQMJLcM7ed9p3jak,82 +setuptools/_vendor/more_itertools/__pycache__/__init__.cpython-39.pyc,, +setuptools/_vendor/more_itertools/__pycache__/more.cpython-39.pyc,, +setuptools/_vendor/more_itertools/__pycache__/recipes.cpython-39.pyc,, +setuptools/_vendor/more_itertools/more.py,sha256=0rB_mibFR51sq33UlAI_bWfaNdsYNnJr1v6S0CaW7QA,117959 +setuptools/_vendor/more_itertools/recipes.py,sha256=UkNkrsZyqiwgLHANBTmvMhCvaNSvSNYhyOpz_Jc55DY,16256 +setuptools/_vendor/ordered_set.py,sha256=dbaCcs27dyN9gnMWGF5nA_BrVn6Q-NrjKYJpV9_fgBs,15130 +setuptools/_vendor/packaging/__about__.py,sha256=ugASIO2w1oUyH8_COqQ2X_s0rDhjbhQC3yJocD03h2c,661 +setuptools/_vendor/packaging/__init__.py,sha256=b9Kk5MF7KxhhLgcDmiUWukN-LatWFxPdNug0joPhHSk,497 +setuptools/_vendor/packaging/__pycache__/__about__.cpython-39.pyc,, +setuptools/_vendor/packaging/__pycache__/__init__.cpython-39.pyc,, +setuptools/_vendor/packaging/__pycache__/_manylinux.cpython-39.pyc,, +setuptools/_vendor/packaging/__pycache__/_musllinux.cpython-39.pyc,, +setuptools/_vendor/packaging/__pycache__/_structures.cpython-39.pyc,, +setuptools/_vendor/packaging/__pycache__/markers.cpython-39.pyc,, +setuptools/_vendor/packaging/__pycache__/requirements.cpython-39.pyc,, +setuptools/_vendor/packaging/__pycache__/specifiers.cpython-39.pyc,, +setuptools/_vendor/packaging/__pycache__/tags.cpython-39.pyc,, +setuptools/_vendor/packaging/__pycache__/utils.cpython-39.pyc,, +setuptools/_vendor/packaging/__pycache__/version.cpython-39.pyc,, +setuptools/_vendor/packaging/_manylinux.py,sha256=XcbiXB-qcjv3bcohp6N98TMpOP4_j3m-iOA8ptK2GWY,11488 +setuptools/_vendor/packaging/_musllinux.py,sha256=_KGgY_qc7vhMGpoqss25n2hiLCNKRtvz9mCrS7gkqyc,4378 +setuptools/_vendor/packaging/_structures.py,sha256=q3eVNmbWJGG_S0Dit_S3Ao8qQqz_5PYTXFAKBZe5yr4,1431 +setuptools/_vendor/packaging/markers.py,sha256=lihRgqpZjLM-JW-vxlLPqU3kmVe79g9vypy1kxmTRuQ,8493 +setuptools/_vendor/packaging/requirements.py,sha256=Opd0FjqgdEiWkzBLyo1oLU0Dj01uIFwTAnAJQrr6j2A,4700 +setuptools/_vendor/packaging/specifiers.py,sha256=LRQ0kFsHrl5qfcFNEEJrIFYsnIHQUJXY9fIsakTrrqE,30110 +setuptools/_vendor/packaging/tags.py,sha256=lmsnGNiJ8C4D_Pf9PbM0qgbZvD9kmB9lpZBQUZa3R_Y,15699 +setuptools/_vendor/packaging/utils.py,sha256=dJjeat3BS-TYn1RrUFVwufUMasbtzLfYRoy_HXENeFQ,4200 +setuptools/_vendor/packaging/version.py,sha256=_fLRNrFrxYcHVfyo8vk9j8s6JM8N_xsSxVFr6RJyco8,14665 +setuptools/_vendor/pyparsing.py,sha256=tmrp-lu-qO1i75ZzIN5A12nKRRD1Cm4Vpk-5LR9rims,232055 +setuptools/_vendor/typing_extensions.py,sha256=1uqi_RSlI7gos4eJB_NEV3d5wQwzTUQHd3_jrkbTo8Q,87149 +setuptools/_vendor/zipp.py,sha256=ajztOH-9I7KA_4wqDYygtHa6xUBVZgFpmZ8FE74HHHI,8425 +setuptools/archive_util.py,sha256=ji0lQ5itrhtfagixEsIJiTwWfl-KKD9cLX2nGMk9ggw,7070 +setuptools/build_meta.py,sha256=Rp40H4rz20WB0GUz7sGshN9mPx3M18zo7aW5hwejie0,10902 +setuptools/cli-32.exe,sha256=dfEuovMNnA2HLa3jRfMPVi5tk4R7alCbpTvuxtCyw0Y,65536 +setuptools/cli-64.exe,sha256=KLABu5pyrnokJCv6skjXZ6GsXeyYHGcqOUT3oHI3Xpo,74752 +setuptools/cli-arm64.exe,sha256=o9amxowudZ98NvNWh_a2DRY8LhoIRqTAekxABqltiMc,137216 +setuptools/cli.exe,sha256=dfEuovMNnA2HLa3jRfMPVi5tk4R7alCbpTvuxtCyw0Y,65536 +setuptools/command/__init__.py,sha256=e-8TJOikUe3St0fw2b2p9u5EDdSxl5zHUBJJKifbcQ8,217 +setuptools/command/__pycache__/__init__.cpython-39.pyc,, +setuptools/command/__pycache__/alias.cpython-39.pyc,, +setuptools/command/__pycache__/bdist_egg.cpython-39.pyc,, +setuptools/command/__pycache__/bdist_rpm.cpython-39.pyc,, +setuptools/command/__pycache__/build_clib.cpython-39.pyc,, +setuptools/command/__pycache__/build_ext.cpython-39.pyc,, +setuptools/command/__pycache__/build_py.cpython-39.pyc,, +setuptools/command/__pycache__/develop.cpython-39.pyc,, +setuptools/command/__pycache__/dist_info.cpython-39.pyc,, +setuptools/command/__pycache__/easy_install.cpython-39.pyc,, +setuptools/command/__pycache__/egg_info.cpython-39.pyc,, +setuptools/command/__pycache__/install.cpython-39.pyc,, +setuptools/command/__pycache__/install_egg_info.cpython-39.pyc,, +setuptools/command/__pycache__/install_lib.cpython-39.pyc,, +setuptools/command/__pycache__/install_scripts.cpython-39.pyc,, +setuptools/command/__pycache__/py36compat.cpython-39.pyc,, +setuptools/command/__pycache__/register.cpython-39.pyc,, +setuptools/command/__pycache__/rotate.cpython-39.pyc,, +setuptools/command/__pycache__/saveopts.cpython-39.pyc,, +setuptools/command/__pycache__/sdist.cpython-39.pyc,, +setuptools/command/__pycache__/setopt.cpython-39.pyc,, +setuptools/command/__pycache__/test.cpython-39.pyc,, +setuptools/command/__pycache__/upload.cpython-39.pyc,, +setuptools/command/__pycache__/upload_docs.cpython-39.pyc,, +setuptools/command/alias.py,sha256=1sLQxZcNh6dDQpDmm4G7UGGTol83nY1NTPmNBbm2siI,2381 +setuptools/command/bdist_egg.py,sha256=QEIu1AkgS02j6ejonJY7kwGp6LNxfMeYZ3sxkd55ftA,16623 +setuptools/command/bdist_rpm.py,sha256=PxrgoHPNaw2Pw2qNjjHDPC-Ay_IaDbCqP3d_5N-cj2A,1182 +setuptools/command/build_clib.py,sha256=fWHSFGkk10VCddBWCszvNhowbG9Z9CZXVjQ2uSInoOs,4415 +setuptools/command/build_ext.py,sha256=SNK042HfB2ezlDQbSVRGFqI1IM5A4AsjU1wpV3fgskE,13212 +setuptools/command/build_py.py,sha256=c90V1nVPEtYkdye-xvo-B48V5RLvSgD8JBMfPtUbtYw,8751 +setuptools/command/develop.py,sha256=5_Ss7ENd1_B_jVMY1tF5UV_y1Xu6jbVzAPG8oKeluGA,7012 +setuptools/command/dist_info.py,sha256=5t6kOfrdgALT-P3ogss6PF9k-Leyesueycuk3dUyZnI,960 +setuptools/command/easy_install.py,sha256=JvgOS1I6PjMdBl8XRGlom1y3B9GOiwzsGd5IU7OHW9k,86193 +setuptools/command/egg_info.py,sha256=KePN5k9NfkdmMhi-0cZMVbs-bnDdO--j7-1x-NavVlU,25703 +setuptools/command/install.py,sha256=UynjFBgRyyHrDZRVAmXrXG0vChJAMx-sxnOO3JoAzVo,4906 +setuptools/command/install_egg_info.py,sha256=pgZ64m_-kmtx3QISHN_kRtMiZC_Y8x1Nr1j38jXEbXQ,2226 +setuptools/command/install_lib.py,sha256=Uz42McsyHZAjrB6cw9E7Bz0xsaTbzxnM1PI9CBhiPtE,3875 +setuptools/command/install_scripts.py,sha256=APFFpt_lYUEo-viMtpXr-Hkwycwq8knTxSTNUu_TwHo,2612 +setuptools/command/launcher manifest.xml,sha256=xlLbjWrB01tKC0-hlVkOKkiSPbzMml2eOPtJ_ucCnbE,628 +setuptools/command/py36compat.py,sha256=7yLWzQj179Enx3pJ8V1cDDCzeLMFMd9XJXlK-iZTq5Y,4946 +setuptools/command/register.py,sha256=kk3DxXCb5lXTvqnhfwx2g6q7iwbUmgTyXUCaBooBOUk,468 +setuptools/command/rotate.py,sha256=SvsQPasezIojPjvMnfkqzh8P0U0tCj0daczF8uc3NQM,2128 +setuptools/command/saveopts.py,sha256=za7QCBcQimKKriWcoCcbhxPjUz30gSB74zuTL47xpP4,658 +setuptools/command/sdist.py,sha256=kTpUQpmT9XSE6wR3ClCNCH7eD7eNAeywIISYIRIYOpU,6422 +setuptools/command/setopt.py,sha256=okxhqD1NM1nQlbSVDCNv6P7Y7g680sc2r-tUW7wPH1Y,5086 +setuptools/command/test.py,sha256=j3NeJ3_ADgkCvWHfuvMrZmSFoTQFngp9Lg3XYNkyZlg,8133 +setuptools/command/upload.py,sha256=XT3YFVfYPAmA5qhGg0euluU98ftxRUW-PzKcODMLxUs,462 +setuptools/command/upload_docs.py,sha256=idT7bhLNblM_I9STmIF_psXRIooDN43gq0QIxt2GDpA,7220 +setuptools/config.py,sha256=O-T_28163qkEeaX8bLgqJLuOLYur15cC2_xpA0RENfM,23153 +setuptools/dep_util.py,sha256=BDx1BkzNQntvAB4alypHbW5UVBzjqths000PrUL4Zqc,949 +setuptools/depends.py,sha256=QYQIadr5DwLxPzkErhNt5hmRhvGhWxoXZMRXCm_jcQ0,5499 +setuptools/dist.py,sha256=TdhjsMb1QrRXkmgGiQAc5PSOrDZg0G45A67s4OFxMeU,44087 +setuptools/errors.py,sha256=t4Rm85eXm71Ti0-PO1gAQMRK3V7NN3x1tcbcw0-xGSI,1555 +setuptools/extension.py,sha256=wOWVz6qk-B3qx-O3vNp2gUZ2ItDEoB4MXIDNU_HCdiU,1675 +setuptools/extern/__init__.py,sha256=a3PZqKDn2rmMHybkWEtO0i8eGtGNoAu1HkULZlZRXdg,2503 +setuptools/extern/__pycache__/__init__.cpython-39.pyc,, +setuptools/glob.py,sha256=1oZjbfjAHSXbgdhSuR6YGU8jKob9L8NtEmBYqcPTLYk,4873 +setuptools/gui-32.exe,sha256=XBr0bHMA6Hpz2s9s9Bzjl-PwXfa9nH4ie0rFn4V2kWA,65536 +setuptools/gui-64.exe,sha256=aYKMhX1IJLn4ULHgWX0sE0yREUt6B3TEHf_jOw6yNyE,75264 +setuptools/gui-arm64.exe,sha256=TEFnOKDi-mq3ZszxqbCoCXTnM_lhUWjdIqBpr6fVs40,137728 +setuptools/gui.exe,sha256=XBr0bHMA6Hpz2s9s9Bzjl-PwXfa9nH4ie0rFn4V2kWA,65536 +setuptools/installer.py,sha256=s6DQfsoICBJxbUqbduhOJtl1oG0S4yegRCg3EAs0i3M,3824 +setuptools/launch.py,sha256=TyPT-Ic1T2EnYvGO26gfNRP4ysBlrhpbRjQxWsiO414,812 +setuptools/logging.py,sha256=npS_AaQd7a-4CVqxC8CKKkwQqLNvSH__pPO94BOB8TY,1148 +setuptools/monkey.py,sha256=0e3HdVKXHL415O7np-AUqhEFXPPuDdJKbI47chQ_DE4,5217 +setuptools/msvc.py,sha256=3LLt938e6OR7wWPzIvCQu7LCWZSIKqoKV6w3r8jV3kY,50561 +setuptools/namespaces.py,sha256=PMqGVPXPYQgjUTvEg9bGccRAkIODrQ6NmsDg_fwErwI,3093 +setuptools/package_index.py,sha256=iajBWGn6Kh6ti4xaiy5fmvG6_SlqLxJ1jV-RK9wnCHs,40055 +setuptools/py34compat.py,sha256=KYOd6ybRxjBW8NJmYD8t_UyyVmysppFXqHpFLdslGXU,245 +setuptools/sandbox.py,sha256=mR83i-mu-ZUU_7TaMgYCeRSyzkqv8loJ_GR9xhS2DDw,14348 +setuptools/script (dev).tmpl,sha256=RUzQzCQUaXtwdLtYHWYbIQmOaES5Brqq1FvUA_tu-5I,218 +setuptools/script.tmpl,sha256=WGTt5piezO27c-Dbx6l5Q4T3Ff20A5z7872hv3aAhYY,138 +setuptools/unicode_utils.py,sha256=aOOFo4JGwAsiBttGYDsqFS7YqWQeZ2j6DWiCuctR_00,941 +setuptools/version.py,sha256=og_cuZQb0QI6ukKZFfZWPlr1HgJBPPn2vO2m_bI9ZTE,144 +setuptools/wheel.py,sha256=4yoNrbyYshwcbLyV5hKksVJNnIXWV2pde_4sUYaxAcY,8274 +setuptools/windows_support.py,sha256=5GrfqSP2-dLGJoZTq2g6dCKkyQxxa2n5IQiXlJCoYEE,714 diff --git a/venv/Lib/site-packages/setuptools-60.9.3.dist-info/WHEEL b/venv/Lib/site-packages/setuptools-60.9.3.dist-info/WHEEL new file mode 100644 index 0000000..becc9a6 --- /dev/null +++ b/venv/Lib/site-packages/setuptools-60.9.3.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.37.1) +Root-Is-Purelib: true +Tag: py3-none-any + diff --git a/venv/Lib/site-packages/setuptools-60.9.3.dist-info/entry_points.txt b/venv/Lib/site-packages/setuptools-60.9.3.dist-info/entry_points.txt new file mode 100644 index 0000000..18041f6 --- /dev/null +++ b/venv/Lib/site-packages/setuptools-60.9.3.dist-info/entry_points.txt @@ -0,0 +1,55 @@ +[distutils.commands] +alias = setuptools.command.alias:alias +bdist_egg = setuptools.command.bdist_egg:bdist_egg +bdist_rpm = setuptools.command.bdist_rpm:bdist_rpm +build_clib = setuptools.command.build_clib:build_clib +build_ext = setuptools.command.build_ext:build_ext +build_py = setuptools.command.build_py:build_py +develop = setuptools.command.develop:develop +dist_info = setuptools.command.dist_info:dist_info +easy_install = setuptools.command.easy_install:easy_install +egg_info = setuptools.command.egg_info:egg_info +install = setuptools.command.install:install +install_egg_info = setuptools.command.install_egg_info:install_egg_info +install_lib = setuptools.command.install_lib:install_lib +install_scripts = setuptools.command.install_scripts:install_scripts +rotate = setuptools.command.rotate:rotate +saveopts = setuptools.command.saveopts:saveopts +sdist = setuptools.command.sdist:sdist +setopt = setuptools.command.setopt:setopt +test = setuptools.command.test:test +upload_docs = setuptools.command.upload_docs:upload_docs + +[distutils.setup_keywords] +dependency_links = setuptools.dist:assert_string_list +eager_resources = setuptools.dist:assert_string_list +entry_points = setuptools.dist:check_entry_points +exclude_package_data = setuptools.dist:check_package_data +extras_require = setuptools.dist:check_extras +include_package_data = setuptools.dist:assert_bool +install_requires = setuptools.dist:check_requirements +namespace_packages = setuptools.dist:check_nsp +package_data = setuptools.dist:check_package_data +packages = setuptools.dist:check_packages +python_requires = setuptools.dist:check_specifier +setup_requires = setuptools.dist:check_requirements +test_loader = setuptools.dist:check_importable +test_runner = setuptools.dist:check_importable +test_suite = setuptools.dist:check_test_suite +tests_require = setuptools.dist:check_requirements +use_2to3 = setuptools.dist:invalid_unless_false +zip_safe = setuptools.dist:assert_bool + +[egg_info.writers] +PKG-INFO = setuptools.command.egg_info:write_pkg_info +dependency_links.txt = setuptools.command.egg_info:overwrite_arg +depends.txt = setuptools.command.egg_info:warn_depends_obsolete +eager_resources.txt = setuptools.command.egg_info:overwrite_arg +entry_points.txt = setuptools.command.egg_info:write_entries +namespace_packages.txt = setuptools.command.egg_info:overwrite_arg +requires.txt = setuptools.command.egg_info:write_requirements +top_level.txt = setuptools.command.egg_info:write_toplevel_names + +[setuptools.finalize_distribution_options] +keywords = setuptools.dist:Distribution._finalize_setup_keywords +parent_finalize = setuptools.dist:_Distribution.finalize_options diff --git a/venv/Lib/site-packages/setuptools-60.9.3.dist-info/top_level.txt b/venv/Lib/site-packages/setuptools-60.9.3.dist-info/top_level.txt new file mode 100644 index 0000000..b5ac107 --- /dev/null +++ b/venv/Lib/site-packages/setuptools-60.9.3.dist-info/top_level.txt @@ -0,0 +1,3 @@ +_distutils_hack +pkg_resources +setuptools diff --git a/venv/Lib/site-packages/setuptools/__init__.py b/venv/Lib/site-packages/setuptools/__init__.py new file mode 100644 index 0000000..06991b6 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/__init__.py @@ -0,0 +1,244 @@ +"""Extensions to the 'distutils' for large or complex distributions""" + +from fnmatch import fnmatchcase +import functools +import os +import re + +import _distutils_hack.override # noqa: F401 + +import distutils.core +from distutils.errors import DistutilsOptionError +from distutils.util import convert_path + +from ._deprecation_warning import SetuptoolsDeprecationWarning + +import setuptools.version +from setuptools.extension import Extension +from setuptools.dist import Distribution +from setuptools.depends import Require +from . import monkey +from . import logging + + +__all__ = [ + 'setup', + 'Distribution', + 'Command', + 'Extension', + 'Require', + 'SetuptoolsDeprecationWarning', + 'find_packages', + 'find_namespace_packages', +] + +__version__ = setuptools.version.__version__ + +bootstrap_install_from = None + + +class PackageFinder: + """ + Generate a list of all Python packages found within a directory + """ + + @classmethod + def find(cls, where='.', exclude=(), include=('*',)): + """Return a list all Python packages found within directory 'where' + + 'where' is the root directory which will be searched for packages. It + should be supplied as a "cross-platform" (i.e. URL-style) path; it will + be converted to the appropriate local path syntax. + + 'exclude' is a sequence of package names to exclude; '*' can be used + as a wildcard in the names, such that 'foo.*' will exclude all + subpackages of 'foo' (but not 'foo' itself). + + 'include' is a sequence of package names to include. If it's + specified, only the named packages will be included. If it's not + specified, all found packages will be included. 'include' can contain + shell style wildcard patterns just like 'exclude'. + """ + + return list( + cls._find_packages_iter( + convert_path(where), + cls._build_filter('ez_setup', '*__pycache__', *exclude), + cls._build_filter(*include), + ) + ) + + @classmethod + def _find_packages_iter(cls, where, exclude, include): + """ + All the packages found in 'where' that pass the 'include' filter, but + not the 'exclude' filter. + """ + for root, dirs, files in os.walk(where, followlinks=True): + # Copy dirs to iterate over it, then empty dirs. + all_dirs = dirs[:] + dirs[:] = [] + + for dir in all_dirs: + full_path = os.path.join(root, dir) + rel_path = os.path.relpath(full_path, where) + package = rel_path.replace(os.path.sep, '.') + + # Skip directory trees that are not valid packages + if '.' in dir or not cls._looks_like_package(full_path): + continue + + # Should this package be included? + if include(package) and not exclude(package): + yield package + + # Keep searching subdirectories, as there may be more packages + # down there, even if the parent was excluded. + dirs.append(dir) + + @staticmethod + def _looks_like_package(path): + """Does a directory look like a package?""" + return os.path.isfile(os.path.join(path, '__init__.py')) + + @staticmethod + def _build_filter(*patterns): + """ + Given a list of patterns, return a callable that will be true only if + the input matches at least one of the patterns. + """ + return lambda name: any(fnmatchcase(name, pat=pat) for pat in patterns) + + +class PEP420PackageFinder(PackageFinder): + @staticmethod + def _looks_like_package(path): + return True + + +find_packages = PackageFinder.find +find_namespace_packages = PEP420PackageFinder.find + + +def _install_setup_requires(attrs): + # Note: do not use `setuptools.Distribution` directly, as + # our PEP 517 backend patch `distutils.core.Distribution`. + class MinimalDistribution(distutils.core.Distribution): + """ + A minimal version of a distribution for supporting the + fetch_build_eggs interface. + """ + + def __init__(self, attrs): + _incl = 'dependency_links', 'setup_requires' + filtered = {k: attrs[k] for k in set(_incl) & set(attrs)} + super().__init__(filtered) + + def finalize_options(self): + """ + Disable finalize_options to avoid building the working set. + Ref #2158. + """ + + dist = MinimalDistribution(attrs) + + # Honor setup.cfg's options. + dist.parse_config_files(ignore_option_errors=True) + if dist.setup_requires: + dist.fetch_build_eggs(dist.setup_requires) + + +def setup(**attrs): + # Make sure we have any requirements needed to interpret 'attrs'. + logging.configure() + _install_setup_requires(attrs) + return distutils.core.setup(**attrs) + + +setup.__doc__ = distutils.core.setup.__doc__ + + +_Command = monkey.get_unpatched(distutils.core.Command) + + +class Command(_Command): + __doc__ = _Command.__doc__ + + command_consumes_arguments = False + + def __init__(self, dist, **kw): + """ + Construct the command for dist, updating + vars(self) with any keyword parameters. + """ + super().__init__(dist) + vars(self).update(kw) + + def _ensure_stringlike(self, option, what, default=None): + val = getattr(self, option) + if val is None: + setattr(self, option, default) + return default + elif not isinstance(val, str): + raise DistutilsOptionError( + "'%s' must be a %s (got `%s`)" % (option, what, val) + ) + return val + + def ensure_string_list(self, option): + r"""Ensure that 'option' is a list of strings. If 'option' is + currently a string, we split it either on /,\s*/ or /\s+/, so + "foo bar baz", "foo,bar,baz", and "foo, bar baz" all become + ["foo", "bar", "baz"]. + """ + val = getattr(self, option) + if val is None: + return + elif isinstance(val, str): + setattr(self, option, re.split(r',\s*|\s+', val)) + else: + if isinstance(val, list): + ok = all(isinstance(v, str) for v in val) + else: + ok = False + if not ok: + raise DistutilsOptionError( + "'%s' must be a list of strings (got %r)" % (option, val) + ) + + def reinitialize_command(self, command, reinit_subcommands=0, **kw): + cmd = _Command.reinitialize_command(self, command, reinit_subcommands) + vars(cmd).update(kw) + return cmd + + +def _find_all_simple(path): + """ + Find all files under 'path' + """ + results = ( + os.path.join(base, file) + for base, dirs, files in os.walk(path, followlinks=True) + for file in files + ) + return filter(os.path.isfile, results) + + +def findall(dir=os.curdir): + """ + Find all files under 'dir' and return the list of full filenames. + Unless dir is '.', return full filenames with dir prepended. + """ + files = _find_all_simple(dir) + if dir == os.curdir: + make_rel = functools.partial(os.path.relpath, start=dir) + files = map(make_rel, files) + return list(files) + + +class sic(str): + """Treat this string as-is (https://en.wikipedia.org/wiki/Sic)""" + + +# Apply monkey patches +monkey.patch_all() diff --git a/venv/Lib/site-packages/setuptools/__pycache__/__init__.cpython-39.pyc b/venv/Lib/site-packages/setuptools/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..129e0351631c4446e286d3c5b18ef35e7dc492de GIT binary patch literal 8622 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/__pycache__/_deprecation_warning.cpython-39.pyc b/venv/Lib/site-packages/setuptools/__pycache__/_deprecation_warning.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e863a0186f2550197a49400de8d0bc7ecf9a4e76 GIT binary patch literal 545 zcmZWlO-lnY5Y4v5mSVw!N5Pzgf-Q(Q5vd>GMS5vPC=1!?CbiMsB<}3C)Tdxz+H0JOfu=c5)^x>jyzcz zuy!@1${+J6>k)8=oMP0+MiuFes>}X-Z=ll5rPfAxrCg#yNVPS0kQi<5pWmCD>;h2n zFaktAu?e3qi(Ibzk!!<)0Dor%L9?U|ry5sO3XDyOmFSt0e3IChDE}V~fv4zJtpX{}xq(J{SY&pF4L2Dfl-wgvcMN*!fPoPG%g0k4kptQ>CKLQ3en5<23fy w`}$%-4Y5+F>lR6&e*vtJYj|beZ&&jAO5*Zj{i9`6r{27Ay4>WfpnnnA50(y?^8f$< literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/__pycache__/_entry_points.cpython-39.pyc b/venv/Lib/site-packages/setuptools/__pycache__/_entry_points.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c5a5b67c885d1a0baac860b15dbc3459de90efaf GIT binary patch literal 2984 zcmZ`*J8v6D5Wd|zQm50ydOz$WzQloLCNks1K#D*XVpxV7M+odBKxi7ok-L(PzL$5G zwkS}QRHSi}HZeez?(;)ZUz^HxIu~|k=JcYZkhs0s_slon%v>-w=2`Ij?dtXBUqhDl z4|Y!fO3?Wp9{o2o!V)a9YQ>w?81;FL3oh))j-8srERdb36qjpdl1tH0?ABb8%h7P` z)jX1iqLFyCHVU#UhWD-7nDE31yvN0;7=!mE>9!}t_@7K%5)=DQZBkn8DKROg_N_fu zo0il48995v#I%^9kvSTf7i^D-SuwY79dKsJ^6@G2VqxEboeN@7T!!-(1$%5&uDk`S zto64H+6v1@x}l6jBMK9#p*x%fS~rq3k5=#G+&P7*%v;N(y%g^^gc z@Svj~%J|%aMILoxGD>bkt*@yz_hliG`tR)l;yTjfquhsF0(h58i9M?{d(`a`p;S_T@R8Z z(Dl1nwg#5eAEvD!s{bV8te%D0%}$a9t!Gl)e7PlMbo1*@(0+N_#C0uACo^dp>3TyZ zMs*um8YV_pvu-|m2*rya3dJZ|%Av7JY7E*I$=HXVbNCP(UqHtIAbV_=3)W+Q0B>H~ z!tS#kKVb9Lu5EbR?mIpE0R80bY>I%rf6kBHc+`W(t zihD1EU@XH7H+Ii5j$p6&9^YdOGy&J}ogWC>`xFubp!XmQ`u2gf2CO__yUaMI)Gzly-a`)BJ9h^-xE5-N$!5odX;LMw9frj+ zMy}|z$#s_WcSx;x`d>29jLWB3%9{&aM#d9tIXSE0mDg{R>cFwD} z$n^?2bQX)@l}(w*?M$uS!lNnhc=^N5JW{W^5@FQq)#~x8%1}NWLNcKc&r7YXAWZTx zqBjl)%}C}YkYY`EQZT3~)Q78&;gy%kwfd|c4&L`As^CInl}35_y=$uq$OAxNl0@&4 zPv$^Cy7jqXZQcjU9UOUp?fgz2SY2K9Wwz|!@$rHiOHVNSrjcyumI^bYpVpI&G`-Ud z)KcZthAL@E150OiES+A4>?~HnDFZVUk9uI{{l^Iom!9vAYrlaZ?1VYq0)bcr3LH&A_?HvtxL_fsV2IOcWFcfQ{3$ zdO-hIz_Dcakg&C5DfMhZ0vqi{b`yyhMyQib-NQ6euFS3ZC#s`M83 z*bMhLf3I%C*nm6G#m5;4Q@&t*{A#lIf%RAsk3o0V&qIy*3%Nm1`yc?+3%gK3+ZMnK zV7CF}*Y+XAn78@S*rf-N(`kTlB>u9eH|K?!Jm(^!@upi U?uhG5xDN9?mw96|HfK}bf85`hdjJ3c literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/__pycache__/_imp.cpython-39.pyc b/venv/Lib/site-packages/setuptools/__pycache__/_imp.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fe0d7e7adb67ace01265cc16b6134f230e0c3f48 GIT binary patch literal 2080 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/__pycache__/archive_util.cpython-39.pyc b/venv/Lib/site-packages/setuptools/__pycache__/archive_util.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3a36ffe9b5e9f5b7efa983d456dd0478dfc2aea3 GIT binary patch literal 5806 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/__pycache__/config.cpython-39.pyc b/venv/Lib/site-packages/setuptools/__pycache__/config.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5fe67eb37cd6cf6fa7d3f3182c0bde4462fc93c3 GIT binary patch literal 20848 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 ZA4A~QWbs*y`dsnY^f!%f8nxN#{{c3CNvQw; literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/__pycache__/dep_util.cpython-39.pyc b/venv/Lib/site-packages/setuptools/__pycache__/dep_util.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bac0d4b757a1924b791006d3bd720a4b7a640a0a GIT binary patch literal 852 zcmY*X!H&}~5Ve!E3*GIiS|PNY@QH4uwh|yN2qDleH^c!JkgA}{ji+t4j$>>`6|3xp za^N%I$OrH2g>Auab6tiVj>Cd+kP^=_qwPNk=)c7eu`f~+Z8x~5Ct z96Kt|`%LHL%0u;?*HoZen2dHCSRVlMUHw0R}ch zakI_5W>$kdU_8c&&8!SFSPm&yE{Sc8g_HU_+@FN~QGI^-sDEvApK&Evzd^Nqmgd&6 zDKv;Y1tvkw-6Cw2K6+*69hW)0FeWo)%WyRZQ@v{0=30XiVQYMN4c?Y}8|d<;nru>) zyFI1J4`TKa;?Mc%pYApq((X}@djEnTpaJdCBYH@C tp6O!dRp^&T0w1eFvZF0#ecigC-g?IzU{iVHNt%gV!c&Tot*AL@{|Cn0_aFcO literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/__pycache__/depends.cpython-39.pyc b/venv/Lib/site-packages/setuptools/__pycache__/depends.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..55af65551f2de4cd4808fed08b77af329e617c60 GIT binary patch literal 5270 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/__pycache__/dist.cpython-39.pyc b/venv/Lib/site-packages/setuptools/__pycache__/dist.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d70ad219a22afb4971be3a71f24d42ffd798d740 GIT binary patch literal 38025 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/__pycache__/errors.cpython-39.pyc b/venv/Lib/site-packages/setuptools/__pycache__/errors.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c0cd0188727286f0216a6d44bc01dfbbc51bbca1 GIT binary patch literal 1497 zcmaJ>OK;RV6i(*VnRKQMZF#@UMM6}fBO!KxuDDDAAr+|F%f=chNvqpT88aq z!B5~X+`r^4EB*p2j^k;PVS%H3I>*Q7%Xv9uFbF(YUvJ%=ZFD^EyH)C|4a!q^^)~?O zVUPN>A^f<3o4%Esq7}Ds+xK32v_;!rJlbY$*7>i6S6K5y7xw@I900E3KHvZk0N3z2 zz#%>lxQ;gfH}NLm1$+VUBEAH88D9asimw4)$JYUG;G2NAFao@dZv(dRU$k@JZLNGB zYnJ6{mLx)tm{N(-L9nNi6Hb{%>{G>+{e8HtWjmMnkdF&yN& z;44aK!%>9WlJmprgU}BMOxvuMVua9b@{oefokSTwVPam;)e5nk@u)Dr*=m_?7)lbe zFf>6Jx}JjE55tc+5ev&o7}6vP!~Z?igN_yObASA3@=i0QCqzo3C;z1B4#~)5H;IUt z{LA8WlJayrmnr1T==SLmV`BS3PClGI%;HH^|4EUw9;I{D0(N_`bOWI47y6s6JE{w+ z>6Lv^){M`G9OtWfQ&;EWcGaj>Idx5>#JpTL>iyTF-5-anIGKO9$nv13PE15ARi6|KGU`aLI zT|Qe-?{azU#Ld$8b#Ysr=W0zc)seTwU3ZSFb)|}6Pml~QUhH@VOR71yr&y|zh%G8o zE7O7f%Q&Z?l545iaRKf{2L?;38NQRpGC7rHO>plS(Ti@D1L;Q7PLJt6afAG~{n6-q R0Ihc4?>E=`9siF{^B31U;Bx=~ literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/__pycache__/extension.cpython-39.pyc b/venv/Lib/site-packages/setuptools/__pycache__/extension.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1124d7528f856aa60b12f8c67357075a7ee94b17 GIT binary patch literal 1971 zcmaJ?Uys{F5Z_%piIdA+Po*GK6K^D-2rH7c=iMaEIkwqd z_byTH=_(Zo!Dna@Fa1g@-gxR);E5SKajycg*3AB!-TC*MwbvMoE0iR`HUnHO%sJdj2spdufHGO`F!-yC~Za} z%Y+$yT@-hP6{GukEYi_|nir!YDfTcr@sW~y$5W-!y^l&UJO0GZM+STe(B!yv;@gfzm;`tbsi^a)$Bi`sn z{VgC2;RPTw1h(>@LiQzl##SVvmYtEAx1uXHVJq)<`aMZN;t%>8pg|I_$lG^2#Ue_R zc>-yTM3LMZ_|7ZxLigb|*D__HvDc+1m@C&Yd8uP%oGMZ}P zP+Wt)4)xj{ew^4T$C&d5FNWKkzp`(qid*no+2)>9WRp@%)XQT-elSf8pR0H(vc$}} zNYnh-@J3RUP++>gy)24!(Ogz&wHN2vBZU>$s6H$$S^}G6r2#prwsUP+U6|<7z9UO7 zzHwve596X(vSGYzp+{E-y$aGU*qGp2U=bv_J1(=hsuI^Jgtm!D9n;ErraW{$RaoDTFfOW6mg5^5zP4eB9XzfP?21IL9Bb!Hf`Z^pi2sYAgGoSY8 zCAv$O*Uq8ie+~~ih)u*|6yduv&t;k7xF1D7l_Fj5bfQS+F#r-_s1b*5dyUdqrRfH# zmBp{4NQK!g7`+W-;NL(3>a%`Z8e*l`B1~>o! literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/__pycache__/glob.cpython-39.pyc b/venv/Lib/site-packages/setuptools/__pycache__/glob.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ba065c80f45e4572a01d0d210a25ca7431a395e2 GIT binary patch literal 3689 zcmeHKPj4H?72la%k}HaqCB>2L#BHXIYniOAN_GnrL69_%ZP-Do8nv4uG7W0AGZI%? z?$R?u%M_NEIt6-YgPeLRAO*en+7HqXu-BgY6?)3=4XMAq^wd+Anm4m=-p;%~zxQSo zUAR#9@ci+Eo10Vbc-}wh<@Dp@<(FvYTM+53dy+|>vUTQqzRq3mulw7c^uJ^4fqY+9 zWc6#dUXj;iO@;{?XB13v}~XcM60E=9`;Iwk-xWNfSF<62Hog zO@|^9ao!(_d`oPQ%!b&~c~3kU+HRhSdrLoGs@GS$QMRp&NU}H`NcB-&w8X|RQK@vo z8zRc2c=F)My_My=VxzSowCd%rlw2agM~Rdw6I)Qkh)64u#EAcQC~fbIZaO<8duO((abD}^(-sA0?z(3f5TufkA}?iexvL_XRs?xj3vAJ zk?k7Mi)`E_2SkqHoPrsvbOsXzo@ZS}Q^bMv5Pr#Qlw`sry?&~M>8donW9$&)y(E=! zq$Mm8Y2?1%%G?f1;!(b*UMYQB46-!YRbn!6+qrLUkUP6ijS+6OEZ#^BN`}dR8kJ`UAN}G0+Wszxr*6-hsY}EcDkE68xO!fNhe$u}) z$of&dtK^-%u2Sipl|i(#chC0P2BGfTJWoxVaI@4OYC;Kt!#LE2qITJ$)Hm&S({}~2_XRagvnS~eiHOqJWgFv!FHuAD6y^Xy68OskU6txlmotG^H zo~;faGI)-8+W^E@@ZGX!YX^v8!46R+-tx7w^4ZhX$B&y+Wj!%ThH{_9s;q1dtumUb zQ&~lECY!4&i*u>qN%)Z%wO>DdpmmPHb3EVCfGXx8p>{I6 z4KL`6__$ed_USo{^<^RpM6S{lcLwP9iE%EzSHO$VOala3BdQ@^Kx8$|oY9wJNG(P) zcR?tAz1ZKFe{1-4|6PWRxW1xNI(tjC-!kABv zj43?b1xN{cC>e)5gOMX2MFAziC3`TLMG2TByM6fuIY55^rJ8m9BXs&Y5dx+DkjM=p zKL#l)ihwu{B?VCb1Ox#l7-~8>^=%>)>XHr5`-+5zXokek0&&Kb*eY8f?~&Yo?bh?w zr_WzB4OQ96_>4;lr4;p5G*<-Z)OPM%Kz{lzKUr3{!O=v9-;Es)N;<%u1?%l z@ovYZWLY&T(s8$(J~ah!%wV&!;%;5%t$PK5w<4!Lim&<}i6)4TA4q&@gbjVQw8>nhkNhciM3UDt|?)dv3K5(~l5#jQ9d|T~C zI*L)Ia08{gprH+)w^v^52Sl6UNm(fC?r4!3cheIC^-u9Z>Em9hS1^L@1ckCP7CToi zXz{JNa^y@SA`S3<~ PA)F1vaIVhkKKk1CY3NrP literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/__pycache__/installer.cpython-39.pyc b/venv/Lib/site-packages/setuptools/__pycache__/installer.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..cfeac79663298c36399cc031eadc0d9926730ab4 GIT binary patch literal 2994 zcmZ`*&2JmW6`vU{spaxRv?AM)<2qZ{b)&*d+bEg_X%aNGWXFZ8DE_G0g$ioP8IemZ zch@sR$s(3LST4{@QK844sAJLpp?^hBbL}a&o^mMKrtb|UMJUiEI3I6j-h1;tes7{i z!z1wh?%mtne>4gCJ5DZs3?@H;zj^}=C!8iEocA=OcFsa(`%+l4y%RdNFNbC5SyCA- zgbNhUloEGT4Xbuc6EF0D<|MUIJ*)$*%qvM_)C`+2Uf}K<5-##8_n>d_8m~itiPL9f zweclrLN->ZDJ5ASy5?G}^jOD;|!$WK69Kil<{mOxPL)w1zo6{ku^X-}9E&`nw8 zNvus7^iG6v@CaPQL*5zxX=*h zQI{@JiIg6O$Jy6{K@I-adRO8m}DD*OV{l`mnK2Gs)fgXjxKADyaGF+5@ zE6TGLj!<{terbl$@YV?dohopvxT%OkK+U24)UpuBRhsdFz!|Sl?kNR6^O*{pjxG{UT@Nf*C zcpp4*W9T2#Lqo|F5^-`(*I;-32=*8C*K7;?0rsl@rk;Xru)jyZJKxqfXE&`izEf2B zl@rj2UtJ;KvBoL2QZ#0_z)Eb|gwc14CQ1Z5-7cD^JDU7$ILD@o5DVWMzE?DhMZWTT zHidZDA`GNDkd8+swA+1h%+&LHHd-)303 zPB>&(+w*+*AWM8mg}XKbe4Y8bc_0eds?Qh`D4R z^E2uT6qRP$kM^TDiMokso4Sb9Vds=fSc{S*JLn8DrPbsM4d-_(C9ss8Gt4<hz5zPxaoc39nfyxIBU#pCtoVGW1BSbzG{&!4S_4V*mQSX=*P z=f%?}8>R}#AYOIGGLdD-d0B^M!h(@00sF~2LBL~$`UeO<`v6dYgh6j0dV7;<5TscE z232t2V6qSdU{0YYwIHxe17JF-2f;T;Iw^m@eK1HQ;`78^fAlDLyz%gJKty*Wbi@Jh zR#%OCFh_J{9306CY&MO2uiueEWna!*LJh^*!a4;*`1mT)J_lvxnzek`-pA|wBoEghNP9Yyhfq`wmGQ(Y(Hm>@im607YGq33K!kPUsc|=#8CVH+T1SB% zNn(~BKr8s>e92Z=i8azV{UqxeXPCvQaZ&9w8i}xZ8djZ1;ayC96R!62Q!knNMQfYJ zuFOVIV-kT!S6jxx%b5~Hq;bHs%9L$n$R&_xBP>KgYHpfSE2C*F+4?oC=uwWAEA>WT zVXT#g3W=r3G?05Ify#)U59iaf0J7zD-oP`6m_-W@9SaY5k*h#dDKx}!C}Zs3PKD7X z{Fa&PU`2GBHGVlZkb>-oWTd4^Hm1M8z3o(_W*~wQCB2C_941u z1-SL3(rN4q#8*8(1C(7AvFVAUaeCnQ=eOBtWWN+*mD3G_$E)09aGbBMA>2 z8>5xEUaM5T5BvVdW%4@EI`CJR`DCF5&akxAC3zPJ@&-0{u)(LDyp7FeXiOCY!#*JA z>E1e@w*|f^mCbFdTiE*M$pnxDk13lB;d1A!KtO19PLaq$kVOIOMyt#PrSSnLZLql? cjWRw?#3u-F3Y`k^bpET`$bq)xy6$KH1rM)PyZ`_I literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/__pycache__/launch.cpython-39.pyc b/venv/Lib/site-packages/setuptools/__pycache__/launch.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e832b0c79e3fe64e0376e042a7d6ca796ba40a84 GIT binary patch literal 896 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�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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/__pycache__/namespaces.cpython-39.pyc b/venv/Lib/site-packages/setuptools/__pycache__/namespaces.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ded41f30390689fc3f6bf427b54204db3dadf7ae GIT binary patch literal 3595 zcmai1O^+M586M7zq>=W+8^?A~*GLAjU1{32P$Ov#B=OdT(t-x>2QI7oyn!dYBmbx|XnyH%kNYnj?w`7Y z7QPz1iLa(;oqB_Svu~WJ^&jYRb|YrItUMUf$LizZ;{l3#gi1IA#+`x7*}&s2_g*>! zpZmOl7K(WbZIcIs7H>m&hp*wg&DZ$`+7933m(Z?>b-u;ldFh<8!3MvK4ZLgGzb%wb zvP{TH=T4!jX9xXC9}XE-JbRjW2~ZxQsDGlGIy2{$bHb)fZE@!tN3$b$=AqYr<-B5h z?umQiP2H(;)VSxIP}`ifrtT}o939NsoZ%gK=?)}oQ+Dc}_;_2FTyISMQ;f1YH>WOl zPu;&?KWR)GvrAK-=KmQoAHP$NImOmpNB!;R4zs_%pr(0|w>#OGpD8U4!rRKYFLbnJ zuEYmI$2e(RsJKdo&yoWHS*eU)CHl|=s>)I=zSCySj?{_71k<*d#MIv^$GRG8WtvG< ziGoWPSQtMoMy2ucq%xNsaag#}7Z*`;!txYA{rsXbamVU$q)>eyUPYYN26?hU$X zTGU|y^YOdFI&7VOZqr4NyUr#z7R>3tso)%eh{t3;mOx+OMLS1q24c*-Ibj%R!axEa zgke_Nn6g()^(_@ZACQJw(m1n#B=gI5cPDFKi@bbZUv<=$L{{0NiYP1FRFPquruYtb zpzNhdI-hAunkgbrUZGLfsCthoI(S|E7;omvxOnq`A3&nuCxB3mjSqAt?=LZV+oW@- zkcm;TsL-}?eh~OIBY)7W>Gzt|dpo})d#WyGC}N<)CRdlsu5dSMPp+nURZ1PIW3?UX z<4T|@)#T=3qT+m{!uurYKL@AMvWSVv;ZE55XgmBxG`UqlT!JC6j{Z@Z7QNd&S(ZA2 zj-TG{!AnFkntWWZkfl#C`b=$7@Gy>RNgVgOi!uGNPP1+_x%2-==E?97HX@HP{2%!R z<+SU(HsL)uy%meL~mzxHI|@BiNJ`Vp?;Y`0KyFDI;fR?UTX0iV88ur_&8O zq{#*hgqHeBjHg6p8um&q;3h9&6XZnICMt(*!b3ON7JPJvO@4F^z13KB?n(*I28wk( zAzsM!9I>i%K{oh2^7G+f3H1h#dK z5i)%Wi!Y18<%Mh+dz-Z?(;8*qrYIyG$aG=~pLTfU)`0owQ5RvL{r?d~5g8l`NGs0Q zQtLvje**yz^M<6Mhl+9`SWG^Tohrl zJop(D+u?C4G9Kzf5e`fE-~x802rqq@=*9dwaQ)7rXJ==p)&_sDa+eE8dflY|v_I@d z=VrjVdo^O=eYkXdJ?SRh?T`k~8_d~XPI@HAVxd9a!ufX*1_=kbjSB26E1=(}_XaWi z4fyXt^cY2vJvyBZ_=hXF^0qziMw=#x?Ulwc?l-QzB;MEK_}g)k(bnVGhG}^N+9Uq6o99ze^ zn#TV?zEQ8wj9nBd=d-siN*ErkEPCVZi`H4oZq$&UVzB&-s{2&Yrt2GBrZUT0`W2)j z6l==?3p`0Z^K8zv$&*mxP$zGujo2b>B1;}JfrH(!k)67er}!uHOInN|w`x}KTdZh; V&uS9x5Gsli!~pySCA`i3{{mlIm$U!? literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/__pycache__/package_index.cpython-39.pyc b/venv/Lib/site-packages/setuptools/__pycache__/package_index.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c80df47fc3f4405d4d3e5e528e74fda71481f66d GIT binary patch literal 32862 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 gvjbZXPZqWV@esorGrZA^A_COdgc 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 QP1z0o5BBX(rH~W*f7l!vwg3PC literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/__pycache__/py34compat.cpython-39.pyc b/venv/Lib/site-packages/setuptools/__pycache__/py34compat.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8d614586c8a9219b4b65fe850474fb1a328f37be GIT binary patch literal 475 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 E0Pt{guK)l5 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/__pycache__/unicode_utils.cpython-39.pyc b/venv/Lib/site-packages/setuptools/__pycache__/unicode_utils.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f5c0c176a906ef87a43110333bb22f0a40741779 GIT binary patch literal 1109 zcmZ9LL2uJA6o73f&9bhmrcF%T@Bu1ST49I_LI{D@a+(5SOrurMWMX#+5v{CMril(0r#a3|oal$yxLCF47-gvzp5?R&0^vGtU{cB^tURpN!TJwe z7YwT~OSm6kaSgX=!B~)Ul-=cchNqb0A(@dW>7tK2GiS14flr+|K0*X=9w2~Q8^2w` zJ#Y2Vd21IYhw`+YNxx2E^rX&}pyrer5Q3h>UxcKV5{)&jX!4!XHFy*BC@_#zrc`{* zL}Ub~CFoe5(2G=^>C#czjtknJf^J00<^)9>>*CIdFvB nP^xK#ZLTuWa_d$s+xw~{=06{$JWs?6d#THCKK5O|;cxu~X#@t$ literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/__pycache__/version.cpython-39.pyc b/venv/Lib/site-packages/setuptools/__pycache__/version.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..86ae401d2451d523e85a27736656b441b717ed0e GIT binary patch literal 319 zcmYjNO-sZu5S_G@?XDJj^6E|4Ll;F)BBH1_@v@3o0wvoFYqxC@n#6Ve1s?qgdh{>l z>dC+0$y65f4fFBf4R08hBqQ*6+1Z`F`u^FI|A;*~^{Eei;lN1)IXtHbZ-fW$WD(@y z9f<7+Fj`Fr^ufbCyay5NdG!>=(U;$ZYd6wptTIwI+6}CzgKls!6SCMA2y3(Jr;!Dp?dRxUnnCASTp5bvY=kHkSh IQnE#U03E+u-v9sr literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/__pycache__/wheel.cpython-39.pyc b/venv/Lib/site-packages/setuptools/__pycache__/wheel.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..19b57ca8bebbd1609428dd9901491d8a239173ac GIT binary patch literal 7260 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/__pycache__/windows_support.cpython-39.pyc b/venv/Lib/site-packages/setuptools/__pycache__/windows_support.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b6417b0cd7f38972d131a72b4b1119ff2b44e948 GIT binary patch literal 1018 zcmZWoO>fgc5Z$#M$4OHaDv&rJ@ClJa6Sa|$sH%##N!3bGikeiBLL}GmZio|qvAZUu zN-wkrB>qHui_F(Zx-~_tD z*T6W@*@FdB8_f~iHd->@^&=8bxd(Z_P2E;34lHhfBPtuWzM!%u4VS&;(wt1y&Q#l( z`|)OPvwy-V<9#=ZT;AVFlDaG0elzympx>ck(og(kEsYY_n^3Yg9Z?#rt*7pIS`%TP zQ;{YjjsxDGE?RPUnj|q3m1HKZt-uWj#NEzAz3;Hl*^}F}I0|N!tw5FG+W;1c(5aOK zt{BEFlqR2XLBleZ#xRY%KV35usATCbRSqItg%K`c3$qfSzw}jtsAp&THUS9G_5x!h z@K_t`W8)kH%8kv;=ZD%HJ647ZfQm#rhsYewwF~WBpX>ZU;H#x;^br$XeUr1#MH{S5 zg)K(Z9{GgO$aaNb{vZ|9j^SVr{QwZNiO;AfVm7N3vs?Qt4(*W;$!4|61qdC#r)(I+ z(~1{|)psf7!jB_fU4QvvV`IHmt1hmcCaxHr+F{CtJ)pLrA4DbNJ6rL@ETOyt3T5C% z%|@$Sl10byL-lzaN1BTyX(}CqKw1;ZA{x{-daLk^edu-Pwte1})-9Jbo3Fd=&auqZ zyGO@$X~9HgMWnHNbkvl22JJ$1X?6Xm!C1`7hBQ>Gz5D<1%7^=h&4#nn=^P*Ko^%?{ z!C}4LXi1$>@$dI8fT+|_8ZN a)1QrywH3xB4d}M|Z@2}{!j^8C8vY3iod%fz literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/_deprecation_warning.py b/venv/Lib/site-packages/setuptools/_deprecation_warning.py new file mode 100644 index 0000000..086b64d --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_deprecation_warning.py @@ -0,0 +1,7 @@ +class SetuptoolsDeprecationWarning(Warning): + """ + Base class for warning deprecations in ``setuptools`` + + This class is not derived from ``DeprecationWarning``, and as such is + visible by default. + """ diff --git a/venv/Lib/site-packages/setuptools/_distutils/__init__.py b/venv/Lib/site-packages/setuptools/_distutils/__init__.py new file mode 100644 index 0000000..8fd493b --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_distutils/__init__.py @@ -0,0 +1,24 @@ +"""distutils + +The main package for the Python Module Distribution Utilities. Normally +used from a setup script as + + from distutils.core import setup + + setup (...) +""" + +import sys +import importlib + +__version__ = sys.version[:sys.version.index(' ')] + + +try: + # Allow Debian and pkgsrc (only) to customize system + # behavior. Ref pypa/distutils#2 and pypa/distutils#16. + # This hook is deprecated and no other environments + # should use it. + importlib.import_module('_distutils_system_mod') +except ImportError: + pass diff --git a/venv/Lib/site-packages/setuptools/_distutils/__pycache__/__init__.cpython-39.pyc b/venv/Lib/site-packages/setuptools/_distutils/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..161156ac7eac5c15b6b9a7c2cd257e260e3acb50 GIT binary patch literal 553 zcmYjNL2DE-6i%|c?l|l2p`g^0If;ANLGdOc73;yGrC^IV1VVO_x~Z8YBpK`UF8DLr zg9rc8Ts`?0dh+dzR1@-r_ws%3eJ^4@&k?Ne4<4>}2|~ZN!T&3RU=L0_0+6Ug5=&xm ziTj(BMB%fM?D29eM_2e8xsS@p#X^zGTXKAbG5Ub)&KRj_dw|h)e?*o%Mv}Zo%gMzL zsbgxAHZjkSH;UFmTk1viS$tCT)CHO#dDNzjv-F*ljZt(T6hW^+1i2HC>ZDaHC_Qwc z7RI!B6P2W=!PQjIs8Zu;tb+E53g|-V@O0C-s9aD~*WQIR(0kG#d{h+0GXD+3qr+=V z%e(wW$736ls(J0?GV7+COILB;jUe6K9?BWL?xtTt=6y7q3Hb;U@|+=-R_IfAx%=L@30BwIZ^Y-tUVf*jrZ#!;V$$nb&^R*zMOTxjNq{ zWmZobad!SR)vTW-IcFmK=bv$|txlX5zU{K-gM}9udd3C7IL~lK?v2P~f$!iy6(*>E literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/_distutils/__pycache__/_collections.cpython-39.pyc b/venv/Lib/site-packages/setuptools/_distutils/__pycache__/_collections.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..079a56cc8311ee17ac13f46932bd9e9ab21563ae GIT binary patch literal 2052 zcma)7&2J+$6t`z4$u!+AP-)99NH83rGgTUGTLcI-(XO_L1JFws4%t+eGj`j_PG+XI z)6y!v&>r|R+T&jNbA08*nHwjbJx!XVRKkg0{PEt;zxQE>E-lp&wBJAdqPJN==ub15 zZm@=4K$mME7-Bd@o$?oV@b`#0%)LU)M!SGt_Yy?zkmV$73F=T%k^dSNpY&&#J5jvjyg}1^BJAI$$sAg`Ff;dy2+y=^ubt z51_paq*(~^gMh(ql4n#TTn6fhs-VY@=m|_He1nsOp9XmbJGtaD$_Ex)4MgM;qY}|Ql(GS6I>(y?a@w;Qdy&%a-2G(NYVT_^t z$IaY{D)d*-We7r{Ydk_X_yQ|OxytKTuB!|)=L(JR4!XoQ_!2&F6WrZw!;v<@5dg(yq0}DrcDF<&o$n{17n3ATA5ZRWm#fkFy$cI}$%nH=q){ihes2#=f-B$h`odWIZG#2z|cR^A9S zeuEcq4+(=5RkSbo2?U=rU4cNRTr9%6C8qr!_}O50)zIAMbZ=5k)KDWDB%6nj|k*FQ;-HpNaU2HD>*!*Vveu)7*6;Sy0pQ?=PT0;??7gX-Q1u#iYE3W zxF6;1C}Zks7aqtmj!R$?VM}C=fvyn(YJ_|}#o~i$7It?R{(GSEGCJUd=sF>ToDEYm z24|0lG`-ycG?vGN*vyF!0n-xDRR|5wnD)%0Y`qqrm`!u_ri87=@v9(BS^C)f%=i3i s)$v_ncA~0yYK-19!WPLhGy2E~vp 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

    wzoPMh}`9!is5|~Md8de`>JfUT3U08I7V}@ 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 G<^Kcuu@vwC literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/_distutils/__pycache__/archive_util.cpython-39.pyc b/venv/Lib/site-packages/setuptools/_distutils/__pycache__/archive_util.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1662aab856c07534029d6d02be216b3363e4106e GIT binary patch literal 6640 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 ddF)Vrwf@abwuY3`y)Dzg3{NGA@+lT-F literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/_distutils/__pycache__/config.cpython-39.pyc b/venv/Lib/site-packages/setuptools/_distutils/__pycache__/config.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..98dbb2efac0f69040095e0825db76ef057db0c91 GIT binary patch literal 3582 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 qXz{6S{k3iNq^XAQa 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/_distutils/__pycache__/dist.cpython-39.pyc b/venv/Lib/site-packages/setuptools/_distutils/__pycache__/dist.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f1b26007378d60c83bdad78860d6061b8237821b GIT binary patch literal 34440 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 BKVtv@ literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/_distutils/__pycache__/errors.cpython-39.pyc b/venv/Lib/site-packages/setuptools/_distutils/__pycache__/errors.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fc11e86e8ca9bcfa8741a324c5d4469a283cd8c9 GIT binary patch literal 5305 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 f`l3ku}rB literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/_distutils/__pycache__/file_util.cpython-39.pyc b/venv/Lib/site-packages/setuptools/_distutils/__pycache__/file_util.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..aa2661974e1dc7fc31a3a1b54b5e37ab6ef81838 GIT binary patch literal 6036 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 SFlYWu>)6NU&dfCIr~VfPLjH#U literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/_distutils/__pycache__/log.cpython-39.pyc b/venv/Lib/site-packages/setuptools/_distutils/__pycache__/log.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5be105301fabf95771f0181bcbe5ae55d0186da0 GIT binary patch literal 2368 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 G>i-`|P{Dfu literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/_distutils/__pycache__/msvccompiler.cpython-39.pyc b/venv/Lib/site-packages/setuptools/_distutils/__pycache__/msvccompiler.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6036e83cf207222aa622a3b649e2708a1bc0dc08 GIT binary patch literal 14793 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/_distutils/__pycache__/py38compat.cpython-39.pyc b/venv/Lib/site-packages/setuptools/_distutils/__pycache__/py38compat.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..247b5a96d407ea18bc7d0d7f3b4903160b7ce9f1 GIT binary patch literal 420 zcmYjNu}T9$5S_gX@r;+o!q&zJS6onHAtItg3qjIE5oIB)w;MdYyIpqoj0tCF;b&;+ z|5#mXWo>8WY(&T`Z)V;MZFYM3@jA2Tq>h8n`!v$WMGM z{aXW*0MSR79dxr*PB>)nGji?>U5 zH|g1&8evOirOXT+@zmJTrkJW}Z#R*-Vz#TM+Fgbq=2rvak$|*FNSb8c8AN|^zRrSM SMnxU$=aQG1IB@!J1pES-n`AZs literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/_distutils/__pycache__/spawn.cpython-39.pyc b/venv/Lib/site-packages/setuptools/_distutils/__pycache__/spawn.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..613c9250434618049a68f856b805e03588ae0fa1 GIT binary patch literal 2863 zcmZWr&u<&Y6`t8$lFKFa!%CbsK!FU9Iy4JOa1x*g+X$@4MjarP4asp5g$6O&8A>bf z4`yao6oq9DN)9=sXwh>H(y{+U&;1+b+LMd^1wGVxZ%9gPy}-`y&b;@{n|a^+X8F=m zMBw`Iy$=rlxLDNHQS?+5Cy9`n znIp+MuJd-c!v7~; zDF=w7BtK+4F92Mzp(+j)&sdTJs4fpSpd*%AZ$?|GE^v4ul0lM-zC4w2Y4|}ZF(#N@ zORnN07weFlBR3IehslY|qibW9^Gt3=uV639PM6xXhx1iG0>DQ~6$*N546l~)fdd#jiJTYn8aO*V~Hl!lo(+M&3!ZZFwP?1Y|Nhzs(#RT0W6;%&Rts=sE z7wu|QP0$khD%W?PRDt{cybAKr)J@|!1gpR_k0ar~^whcVAf2tOJ*j6)6G&;*_?}F{ zDpcoHSOr!6J~?B?KVGg7srDyt(yW>nE0+W;o5!n@=u4764v4ui{ud>a7A0qQ%$olD zG#-fhEl~&0*74h-@h%y7??8-I>)iX2d<{gJw7zTQ(e!zT+#yx;7pj)Q|Gx|VA^1mA z&vPIq5UR=l>=CkCLPGyH$Lnmy3Mm-ZknXt1G7bz%Arq_zbUK zk?Z(u0M+K$+(#yNT*#`F>^2528`sN^;jF3bu_z1aTv2|aFsAh(v%%YR%+OC zh!pE*aS!e>SA?TP%k|kVIgAW98T@codCFtM92_7_d*%hW$ry$#)VL3ua24*l13}Yy zhFu`Q1_oFqPt!4?gUf8)yBs25Zx$p=256O|U?AK)bpsA!<*1U6F$?z`E!?b1no{Mg z$U#ivDSfhU@J8H^!LbfjmtNY=V$r*}Z84WV%9Kw?UE* z3LAmq&4_N>IQS88HBEA9SN>1yY#@@@Sg+8w0nsENzt#s1*l;eocKKSzQO#8Y=20O| zR(o0uWp0BJPmGPGTZB>B#*;m#e9A{#C|d{&7OuN(>q8{AwZKN(fXz54GAs3;jUD62!ZT}5ud((jaj?XD*K1HSq zpM;Ny7j5WY0-vA?9+DRyOloe{Wjuudz3#qhRUKmZxvG1Bvq!%D8GXC;Gy6;>_$x4z zkIuE;K*8s(E=8hbYzk+GEC#iKk&e@_S&45kU_RC{j^lIDN6R5s9NiAatW)Ss^n}jN zy}9V&{I0%Xa7O=cI#0KrJ?^{!5!!V{Kb3c=#9=Cp1hGpcp7{)phMgh@(H?+kgA^BK zE~a8`Yaj+6e{>dX!lHI;fPl8Kz1PQ=?uxnrnFQKGFgDb~G%@njsJEa~y^SOFMB^k1 ziDi9|3)_f`d;klz%UcGPdr%tb>dQvYd0Nii8zAHk6KDyTwlQ0+4UP-YriOYCXXqj* z?SuB58e4NFmJTf)xPqBBzeU3pXdc6@Z$m@st8@)W+y-)oj>t&oRj*w`x+B?_X&cDy zyt;wHpBpEQu7Ure9Vq=qzb}fo-=8iOH$lPwDY2_prL`&Xe@RajW97PA$b<6GiHU7q q^*X_GHREPoh#yN|;Ua8!KPyC;%1=*3xZIn;7y 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/_distutils/__pycache__/unixccompiler.cpython-39.pyc b/venv/Lib/site-packages/setuptools/_distutils/__pycache__/unixccompiler.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8b84e374f1ac8043933ba3dcc5124052e34325c1 GIT binary patch literal 6842 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/_distutils/__pycache__/versionpredicate.cpython-39.pyc b/venv/Lib/site-packages/setuptools/_distutils/__pycache__/versionpredicate.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e03315127778d2fe8bfbb2fdca2308aa63aabf32 GIT binary patch literal 5313 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 stack = DictStack([dict(a=1, c=2), dict(b=2, a=2)]) + >>> stack['a'] + 2 + >>> stack['b'] + 2 + >>> stack['c'] + 2 + >>> len(stack) + 3 + >>> stack.push(dict(a=3)) + >>> stack['a'] + 3 + >>> set(stack.keys()) == set(['a', 'b', 'c']) + True + >>> set(stack.items()) == set([('a', 3), ('b', 2), ('c', 2)]) + True + >>> dict(**stack) == dict(stack) == dict(a=3, c=2, b=2) + True + >>> d = stack.pop() + >>> stack['a'] + 2 + >>> d = stack.pop() + >>> stack['a'] + 1 + >>> stack.get('b', None) + >>> 'c' in stack + True + """ + + def __iter__(self): + dicts = list.__iter__(self) + return iter(set(itertools.chain.from_iterable(c.keys() for c in dicts))) + + def __getitem__(self, key): + for scope in reversed(tuple(list.__iter__(self))): + if key in scope: + return scope[key] + raise KeyError(key) + + push = list.append + + def __contains__(self, other): + return collections.abc.Mapping.__contains__(self, other) + + def __len__(self): + return len(list(iter(self))) diff --git a/venv/Lib/site-packages/setuptools/_distutils/_msvccompiler.py b/venv/Lib/site-packages/setuptools/_distutils/_msvccompiler.py new file mode 100644 index 0000000..f2f801c --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_distutils/_msvccompiler.py @@ -0,0 +1,561 @@ +"""distutils._msvccompiler + +Contains MSVCCompiler, an implementation of the abstract CCompiler class +for Microsoft Visual Studio 2015. + +The module is compatible with VS 2015 and later. You can find legacy support +for older versions in distutils.msvc9compiler and distutils.msvccompiler. +""" + +# Written by Perry Stoll +# hacked by Robin Becker and Thomas Heller to do a better job of +# finding DevStudio (through the registry) +# ported to VS 2005 and VS 2008 by Christian Heimes +# ported to VS 2015 by Steve Dower + +import os +import subprocess +import contextlib +import warnings +import unittest.mock +with contextlib.suppress(ImportError): + import winreg + +from distutils.errors import DistutilsExecError, DistutilsPlatformError, \ + CompileError, LibError, LinkError +from distutils.ccompiler import CCompiler, gen_lib_options +from distutils import log +from distutils.util import get_platform + +from itertools import count + +def _find_vc2015(): + try: + key = winreg.OpenKeyEx( + winreg.HKEY_LOCAL_MACHINE, + r"Software\Microsoft\VisualStudio\SxS\VC7", + access=winreg.KEY_READ | winreg.KEY_WOW64_32KEY + ) + except OSError: + log.debug("Visual C++ is not registered") + return None, None + + best_version = 0 + best_dir = None + with key: + for i in count(): + try: + v, vc_dir, vt = winreg.EnumValue(key, i) + except OSError: + break + if v and vt == winreg.REG_SZ and os.path.isdir(vc_dir): + try: + version = int(float(v)) + except (ValueError, TypeError): + continue + if version >= 14 and version > best_version: + best_version, best_dir = version, vc_dir + return best_version, best_dir + +def _find_vc2017(): + """Returns "15, path" based on the result of invoking vswhere.exe + If no install is found, returns "None, None" + + The version is returned to avoid unnecessarily changing the function + result. It may be ignored when the path is not None. + + If vswhere.exe is not available, by definition, VS 2017 is not + installed. + """ + root = os.environ.get("ProgramFiles(x86)") or os.environ.get("ProgramFiles") + if not root: + return None, None + + try: + path = subprocess.check_output([ + os.path.join(root, "Microsoft Visual Studio", "Installer", "vswhere.exe"), + "-latest", + "-prerelease", + "-requires", "Microsoft.VisualStudio.Component.VC.Tools.x86.x64", + "-property", "installationPath", + "-products", "*", + ], encoding="mbcs", errors="strict").strip() + except (subprocess.CalledProcessError, OSError, UnicodeDecodeError): + return None, None + + path = os.path.join(path, "VC", "Auxiliary", "Build") + if os.path.isdir(path): + return 15, path + + return None, None + +PLAT_SPEC_TO_RUNTIME = { + 'x86' : 'x86', + 'x86_amd64' : 'x64', + 'x86_arm' : 'arm', + 'x86_arm64' : 'arm64' +} + +def _find_vcvarsall(plat_spec): + # bpo-38597: Removed vcruntime return value + _, best_dir = _find_vc2017() + + if not best_dir: + best_version, best_dir = _find_vc2015() + + if not best_dir: + log.debug("No suitable Visual C++ version found") + return None, None + + vcvarsall = os.path.join(best_dir, "vcvarsall.bat") + if not os.path.isfile(vcvarsall): + log.debug("%s cannot be found", vcvarsall) + return None, None + + return vcvarsall, None + +def _get_vc_env(plat_spec): + if os.getenv("DISTUTILS_USE_SDK"): + return { + key.lower(): value + for key, value in os.environ.items() + } + + vcvarsall, _ = _find_vcvarsall(plat_spec) + if not vcvarsall: + raise DistutilsPlatformError("Unable to find vcvarsall.bat") + + try: + out = subprocess.check_output( + 'cmd /u /c "{}" {} && set'.format(vcvarsall, plat_spec), + stderr=subprocess.STDOUT, + ).decode('utf-16le', errors='replace') + except subprocess.CalledProcessError as exc: + log.error(exc.output) + raise DistutilsPlatformError("Error executing {}" + .format(exc.cmd)) + + env = { + key.lower(): value + for key, _, value in + (line.partition('=') for line in out.splitlines()) + if key and value + } + + return env + +def _find_exe(exe, paths=None): + """Return path to an MSVC executable program. + + Tries to find the program in several places: first, one of the + MSVC program search paths from the registry; next, the directories + in the PATH environment variable. If any of those work, return an + absolute path that is known to exist. If none of them work, just + return the original program name, 'exe'. + """ + if not paths: + paths = os.getenv('path').split(os.pathsep) + for p in paths: + fn = os.path.join(os.path.abspath(p), exe) + if os.path.isfile(fn): + return fn + return exe + +# A map keyed by get_platform() return values to values accepted by +# 'vcvarsall.bat'. Always cross-compile from x86 to work with the +# lighter-weight MSVC installs that do not include native 64-bit tools. +PLAT_TO_VCVARS = { + 'win32' : 'x86', + 'win-amd64' : 'x86_amd64', + 'win-arm32' : 'x86_arm', + 'win-arm64' : 'x86_arm64' +} + +class MSVCCompiler(CCompiler) : + """Concrete class that implements an interface to Microsoft Visual C++, + as defined by the CCompiler abstract class.""" + + compiler_type = 'msvc' + + # Just set this so CCompiler's constructor doesn't barf. We currently + # don't use the 'set_executables()' bureaucracy provided by CCompiler, + # as it really isn't necessary for this sort of single-compiler class. + # Would be nice to have a consistent interface with UnixCCompiler, + # though, so it's worth thinking about. + executables = {} + + # Private class data (need to distinguish C from C++ source for compiler) + _c_extensions = ['.c'] + _cpp_extensions = ['.cc', '.cpp', '.cxx'] + _rc_extensions = ['.rc'] + _mc_extensions = ['.mc'] + + # Needed for the filename generation methods provided by the + # base class, CCompiler. + src_extensions = (_c_extensions + _cpp_extensions + + _rc_extensions + _mc_extensions) + res_extension = '.res' + obj_extension = '.obj' + static_lib_extension = '.lib' + shared_lib_extension = '.dll' + static_lib_format = shared_lib_format = '%s%s' + exe_extension = '.exe' + + + def __init__(self, verbose=0, dry_run=0, force=0): + super().__init__(verbose, dry_run, force) + # target platform (.plat_name is consistent with 'bdist') + self.plat_name = None + self.initialized = False + + def initialize(self, plat_name=None): + # multi-init means we would need to check platform same each time... + assert not self.initialized, "don't init multiple times" + if plat_name is None: + plat_name = get_platform() + # sanity check for platforms to prevent obscure errors later. + if plat_name not in PLAT_TO_VCVARS: + raise DistutilsPlatformError("--plat-name must be one of {}" + .format(tuple(PLAT_TO_VCVARS))) + + # Get the vcvarsall.bat spec for the requested platform. + plat_spec = PLAT_TO_VCVARS[plat_name] + + vc_env = _get_vc_env(plat_spec) + if not vc_env: + raise DistutilsPlatformError("Unable to find a compatible " + "Visual Studio installation.") + + self._paths = vc_env.get('path', '') + paths = self._paths.split(os.pathsep) + self.cc = _find_exe("cl.exe", paths) + self.linker = _find_exe("link.exe", paths) + self.lib = _find_exe("lib.exe", paths) + self.rc = _find_exe("rc.exe", paths) # resource compiler + self.mc = _find_exe("mc.exe", paths) # message compiler + self.mt = _find_exe("mt.exe", paths) # message compiler + + for dir in vc_env.get('include', '').split(os.pathsep): + if dir: + self.add_include_dir(dir.rstrip(os.sep)) + + for dir in vc_env.get('lib', '').split(os.pathsep): + if dir: + self.add_library_dir(dir.rstrip(os.sep)) + + self.preprocess_options = None + # bpo-38597: Always compile with dynamic linking + # Future releases of Python 3.x will include all past + # versions of vcruntime*.dll for compatibility. + self.compile_options = [ + '/nologo', '/O2', '/W3', '/GL', '/DNDEBUG', '/MD' + ] + + self.compile_options_debug = [ + '/nologo', '/Od', '/MDd', '/Zi', '/W3', '/D_DEBUG' + ] + + ldflags = [ + '/nologo', '/INCREMENTAL:NO', '/LTCG' + ] + + ldflags_debug = [ + '/nologo', '/INCREMENTAL:NO', '/LTCG', '/DEBUG:FULL' + ] + + self.ldflags_exe = [*ldflags, '/MANIFEST:EMBED,ID=1'] + self.ldflags_exe_debug = [*ldflags_debug, '/MANIFEST:EMBED,ID=1'] + self.ldflags_shared = [*ldflags, '/DLL', '/MANIFEST:EMBED,ID=2', '/MANIFESTUAC:NO'] + self.ldflags_shared_debug = [*ldflags_debug, '/DLL', '/MANIFEST:EMBED,ID=2', '/MANIFESTUAC:NO'] + self.ldflags_static = [*ldflags] + self.ldflags_static_debug = [*ldflags_debug] + + self._ldflags = { + (CCompiler.EXECUTABLE, None): self.ldflags_exe, + (CCompiler.EXECUTABLE, False): self.ldflags_exe, + (CCompiler.EXECUTABLE, True): self.ldflags_exe_debug, + (CCompiler.SHARED_OBJECT, None): self.ldflags_shared, + (CCompiler.SHARED_OBJECT, False): self.ldflags_shared, + (CCompiler.SHARED_OBJECT, True): self.ldflags_shared_debug, + (CCompiler.SHARED_LIBRARY, None): self.ldflags_static, + (CCompiler.SHARED_LIBRARY, False): self.ldflags_static, + (CCompiler.SHARED_LIBRARY, True): self.ldflags_static_debug, + } + + self.initialized = True + + # -- Worker methods ------------------------------------------------ + + def object_filenames(self, + source_filenames, + strip_dir=0, + output_dir=''): + ext_map = { + **{ext: self.obj_extension for ext in self.src_extensions}, + **{ext: self.res_extension for ext in self._rc_extensions + self._mc_extensions}, + } + + output_dir = output_dir or '' + + def make_out_path(p): + base, ext = os.path.splitext(p) + if strip_dir: + base = os.path.basename(base) + else: + _, base = os.path.splitdrive(base) + if base.startswith((os.path.sep, os.path.altsep)): + base = base[1:] + try: + # XXX: This may produce absurdly long paths. We should check + # the length of the result and trim base until we fit within + # 260 characters. + return os.path.join(output_dir, base + ext_map[ext]) + except LookupError: + # Better to raise an exception instead of silently continuing + # and later complain about sources and targets having + # different lengths + raise CompileError("Don't know how to compile {}".format(p)) + + return list(map(make_out_path, source_filenames)) + + + def compile(self, sources, + output_dir=None, macros=None, include_dirs=None, debug=0, + extra_preargs=None, extra_postargs=None, depends=None): + + if not self.initialized: + self.initialize() + compile_info = self._setup_compile(output_dir, macros, include_dirs, + sources, depends, extra_postargs) + macros, objects, extra_postargs, pp_opts, build = compile_info + + compile_opts = extra_preargs or [] + compile_opts.append('/c') + if debug: + compile_opts.extend(self.compile_options_debug) + else: + compile_opts.extend(self.compile_options) + + + add_cpp_opts = False + + for obj in objects: + try: + src, ext = build[obj] + except KeyError: + continue + if debug: + # pass the full pathname to MSVC in debug mode, + # this allows the debugger to find the source file + # without asking the user to browse for it + src = os.path.abspath(src) + + if ext in self._c_extensions: + input_opt = "/Tc" + src + elif ext in self._cpp_extensions: + input_opt = "/Tp" + src + add_cpp_opts = True + elif ext in self._rc_extensions: + # compile .RC to .RES file + input_opt = src + output_opt = "/fo" + obj + try: + self.spawn([self.rc] + pp_opts + [output_opt, input_opt]) + except DistutilsExecError as msg: + raise CompileError(msg) + continue + elif ext in self._mc_extensions: + # Compile .MC to .RC file to .RES file. + # * '-h dir' specifies the directory for the + # generated include file + # * '-r dir' specifies the target directory of the + # generated RC file and the binary message resource + # it includes + # + # For now (since there are no options to change this), + # we use the source-directory for the include file and + # the build directory for the RC file and message + # resources. This works at least for win32all. + h_dir = os.path.dirname(src) + rc_dir = os.path.dirname(obj) + try: + # first compile .MC to .RC and .H file + self.spawn([self.mc, '-h', h_dir, '-r', rc_dir, src]) + base, _ = os.path.splitext(os.path.basename (src)) + rc_file = os.path.join(rc_dir, base + '.rc') + # then compile .RC to .RES file + self.spawn([self.rc, "/fo" + obj, rc_file]) + + except DistutilsExecError as msg: + raise CompileError(msg) + continue + else: + # how to handle this file? + raise CompileError("Don't know how to compile {} to {}" + .format(src, obj)) + + args = [self.cc] + compile_opts + pp_opts + if add_cpp_opts: + args.append('/EHsc') + args.append(input_opt) + args.append("/Fo" + obj) + args.extend(extra_postargs) + + try: + self.spawn(args) + except DistutilsExecError as msg: + raise CompileError(msg) + + return objects + + + def create_static_lib(self, + objects, + output_libname, + output_dir=None, + debug=0, + target_lang=None): + + if not self.initialized: + self.initialize() + objects, output_dir = self._fix_object_args(objects, output_dir) + output_filename = self.library_filename(output_libname, + output_dir=output_dir) + + if self._need_link(objects, output_filename): + lib_args = objects + ['/OUT:' + output_filename] + if debug: + pass # XXX what goes here? + try: + log.debug('Executing "%s" %s', self.lib, ' '.join(lib_args)) + self.spawn([self.lib] + lib_args) + except DistutilsExecError as msg: + raise LibError(msg) + else: + log.debug("skipping %s (up-to-date)", output_filename) + + + def link(self, + target_desc, + objects, + output_filename, + output_dir=None, + libraries=None, + library_dirs=None, + runtime_library_dirs=None, + export_symbols=None, + debug=0, + extra_preargs=None, + extra_postargs=None, + build_temp=None, + target_lang=None): + + if not self.initialized: + self.initialize() + objects, output_dir = self._fix_object_args(objects, output_dir) + fixed_args = self._fix_lib_args(libraries, library_dirs, + runtime_library_dirs) + libraries, library_dirs, runtime_library_dirs = fixed_args + + if runtime_library_dirs: + self.warn("I don't know what to do with 'runtime_library_dirs': " + + str(runtime_library_dirs)) + + lib_opts = gen_lib_options(self, + library_dirs, runtime_library_dirs, + libraries) + if output_dir is not None: + output_filename = os.path.join(output_dir, output_filename) + + if self._need_link(objects, output_filename): + ldflags = self._ldflags[target_desc, debug] + + export_opts = ["/EXPORT:" + sym for sym in (export_symbols or [])] + + ld_args = (ldflags + lib_opts + export_opts + + objects + ['/OUT:' + output_filename]) + + # The MSVC linker generates .lib and .exp files, which cannot be + # suppressed by any linker switches. The .lib files may even be + # needed! Make sure they are generated in the temporary build + # directory. Since they have different names for debug and release + # builds, they can go into the same directory. + build_temp = os.path.dirname(objects[0]) + if export_symbols is not None: + (dll_name, dll_ext) = os.path.splitext( + os.path.basename(output_filename)) + implib_file = os.path.join( + build_temp, + self.library_filename(dll_name)) + ld_args.append ('/IMPLIB:' + implib_file) + + if extra_preargs: + ld_args[:0] = extra_preargs + if extra_postargs: + ld_args.extend(extra_postargs) + + output_dir = os.path.dirname(os.path.abspath(output_filename)) + self.mkpath(output_dir) + try: + log.debug('Executing "%s" %s', self.linker, ' '.join(ld_args)) + self.spawn([self.linker] + ld_args) + except DistutilsExecError as msg: + raise LinkError(msg) + else: + log.debug("skipping %s (up-to-date)", output_filename) + + def spawn(self, cmd): + env = dict(os.environ, PATH=self._paths) + with self._fallback_spawn(cmd, env) as fallback: + return super().spawn(cmd, env=env) + return fallback.value + + @contextlib.contextmanager + def _fallback_spawn(self, cmd, env): + """ + Discovered in pypa/distutils#15, some tools monkeypatch the compiler, + so the 'env' kwarg causes a TypeError. Detect this condition and + restore the legacy, unsafe behavior. + """ + bag = type('Bag', (), {})() + try: + yield bag + except TypeError as exc: + if "unexpected keyword argument 'env'" not in str(exc): + raise + else: + return + warnings.warn( + "Fallback spawn triggered. Please update distutils monkeypatch.") + with unittest.mock.patch.dict('os.environ', env): + bag.value = super().spawn(cmd) + + # -- Miscellaneous methods ----------------------------------------- + # These are all used by the 'gen_lib_options() function, in + # ccompiler.py. + + def library_dir_option(self, dir): + return "/LIBPATH:" + dir + + def runtime_library_dir_option(self, dir): + raise DistutilsPlatformError( + "don't know how to set runtime library search path for MSVC") + + def library_option(self, lib): + return self.library_filename(lib) + + def find_library_file(self, dirs, lib, debug=0): + # Prefer a debugging library if found (and requested), but deal + # with it if we don't have one. + if debug: + try_names = [lib + "_d", lib] + else: + try_names = [lib] + for dir in dirs: + for name in try_names: + libfile = os.path.join(dir, self.library_filename(name)) + if os.path.isfile(libfile): + return libfile + else: + # Oops, didn't find it in *any* of 'dirs' + return None diff --git a/venv/Lib/site-packages/setuptools/_distutils/archive_util.py b/venv/Lib/site-packages/setuptools/_distutils/archive_util.py new file mode 100644 index 0000000..565a311 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_distutils/archive_util.py @@ -0,0 +1,256 @@ +"""distutils.archive_util + +Utility functions for creating archive files (tarballs, zip files, +that sort of thing).""" + +import os +from warnings import warn +import sys + +try: + import zipfile +except ImportError: + zipfile = None + + +from distutils.errors import DistutilsExecError +from distutils.spawn import spawn +from distutils.dir_util import mkpath +from distutils import log + +try: + from pwd import getpwnam +except ImportError: + getpwnam = None + +try: + from grp import getgrnam +except ImportError: + getgrnam = None + +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): + """Create a (possibly compressed) tar file from all the files under + 'base_dir'. + + 'compress' must be "gzip" (the default), "bzip2", "xz", "compress", or + None. ("compress" will be deprecated in Python 3.2) + + '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_dir' + ".tar", possibly plus + the appropriate compression extension (".gz", ".bz2", ".xz" or ".Z"). + + Returns the output filename. + """ + tar_compression = {'gzip': 'gz', 'bzip2': 'bz2', 'xz': 'xz', None: '', + 'compress': ''} + compress_ext = {'gzip': '.gz', 'bzip2': '.bz2', 'xz': '.xz', + 'compress': '.Z'} + + # flags for compression program, each element of list will be an argument + if compress is not None and compress not in compress_ext.keys(): + raise ValueError( + "bad value for 'compress': must be None, 'gzip', 'bzip2', " + "'xz' or 'compress'") + + archive_name = base_name + '.tar' + if compress != 'compress': + archive_name += compress_ext.get(compress, '') + + mkpath(os.path.dirname(archive_name), dry_run=dry_run) + + # creating the tarball + import tarfile # late import so Python build itself doesn't break + + log.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[compress]) + try: + tar.add(base_dir, filter=_set_uid_gid) + finally: + tar.close() + + # compression using `compress` + if compress == 'compress': + warn("'compress' will be deprecated.", PendingDeprecationWarning) + # the option varies depending on the platform + compressed_name = archive_name + compress_ext[compress] + if sys.platform == 'win32': + cmd = [compress, archive_name, compressed_name] + else: + cmd = [compress, '-f', archive_name] + spawn(cmd, dry_run=dry_run) + return compressed_name + + return archive_name + +def make_zipfile(base_name, base_dir, verbose=0, dry_run=0): + """Create a zip file from all the files under 'base_dir'. + + The output zip file will be named 'base_name' + ".zip". Uses either the + "zipfile" Python module (if available) or the InfoZIP "zip" utility + (if installed and found on the default search path). If neither tool is + available, raises DistutilsExecError. Returns the name of the output zip + file. + """ + zip_filename = base_name + ".zip" + mkpath(os.path.dirname(zip_filename), dry_run=dry_run) + + # If zipfile module is not available, try spawning an external + # 'zip' command. + if zipfile is None: + if verbose: + zipoptions = "-r" + else: + zipoptions = "-rq" + + try: + spawn(["zip", zipoptions, zip_filename, base_dir], + dry_run=dry_run) + except DistutilsExecError: + # XXX really should distinguish between "couldn't find + # external 'zip' command" and "zip failed". + raise DistutilsExecError(("unable to create zip file '%s': " + "could neither import the 'zipfile' module nor " + "find a standalone zip utility") % zip_filename) + + else: + log.info("creating '%s' and adding '%s' to it", + zip_filename, base_dir) + + if not dry_run: + try: + zip = zipfile.ZipFile(zip_filename, "w", + compression=zipfile.ZIP_DEFLATED) + except RuntimeError: + zip = zipfile.ZipFile(zip_filename, "w", + compression=zipfile.ZIP_STORED) + + with zip: + if base_dir != os.curdir: + path = os.path.normpath(os.path.join(base_dir, '')) + zip.write(path, path) + log.info("adding '%s'", path) + for dirpath, dirnames, filenames in os.walk(base_dir): + for name in dirnames: + path = os.path.normpath(os.path.join(dirpath, name, '')) + zip.write(path, path) + log.info("adding '%s'", path) + for name in filenames: + path = os.path.normpath(os.path.join(dirpath, name)) + if os.path.isfile(path): + zip.write(path, path) + log.info("adding '%s'", path) + + return zip_filename + +ARCHIVE_FORMATS = { + 'gztar': (make_tarball, [('compress', 'gzip')], "gzip'ed tar-file"), + 'bztar': (make_tarball, [('compress', 'bzip2')], "bzip2'ed tar-file"), + 'xztar': (make_tarball, [('compress', 'xz')], "xz'ed tar-file"), + 'ztar': (make_tarball, [('compress', 'compress')], "compressed tar file"), + 'tar': (make_tarball, [('compress', None)], "uncompressed tar file"), + 'zip': (make_zipfile, [],"ZIP file") + } + +def check_archive_formats(formats): + """Returns the first format from the 'format' list that is unknown. + + If all formats are known, returns None + """ + for format in formats: + if format not in ARCHIVE_FORMATS: + return format + return None + +def make_archive(base_name, format, root_dir=None, base_dir=None, verbose=0, + dry_run=0, owner=None, group=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", "xztar", or "ztar". + + '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: + log.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} + + try: + format_info = ARCHIVE_FORMATS[format] + except KeyError: + raise ValueError("unknown archive format '%s'" % format) + + 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: + log.debug("changing back to '%s'", save_cwd) + os.chdir(save_cwd) + + return filename diff --git a/venv/Lib/site-packages/setuptools/_distutils/bcppcompiler.py b/venv/Lib/site-packages/setuptools/_distutils/bcppcompiler.py new file mode 100644 index 0000000..2eb6d2e --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_distutils/bcppcompiler.py @@ -0,0 +1,393 @@ +"""distutils.bcppcompiler + +Contains BorlandCCompiler, an implementation of the abstract CCompiler class +for the Borland C++ compiler. +""" + +# This implementation by Lyle Johnson, based on the original msvccompiler.py +# module and using the directions originally published by Gordon Williams. + +# XXX looks like there's a LOT of overlap between these two classes: +# someone should sit down and factor out the common code as +# WindowsCCompiler! --GPW + + +import os +from distutils.errors import \ + DistutilsExecError, \ + CompileError, LibError, LinkError, UnknownFileError +from distutils.ccompiler import \ + CCompiler, gen_preprocess_options +from distutils.file_util import write_file +from distutils.dep_util import newer +from distutils import log + +class BCPPCompiler(CCompiler) : + """Concrete class that implements an interface to the Borland C/C++ + compiler, as defined by the CCompiler abstract class. + """ + + compiler_type = 'bcpp' + + # Just set this so CCompiler's constructor doesn't barf. We currently + # don't use the 'set_executables()' bureaucracy provided by CCompiler, + # as it really isn't necessary for this sort of single-compiler class. + # Would be nice to have a consistent interface with UnixCCompiler, + # though, so it's worth thinking about. + executables = {} + + # Private class data (need to distinguish C from C++ source for compiler) + _c_extensions = ['.c'] + _cpp_extensions = ['.cc', '.cpp', '.cxx'] + + # Needed for the filename generation methods provided by the + # base class, CCompiler. + src_extensions = _c_extensions + _cpp_extensions + obj_extension = '.obj' + static_lib_extension = '.lib' + shared_lib_extension = '.dll' + static_lib_format = shared_lib_format = '%s%s' + exe_extension = '.exe' + + + def __init__ (self, + verbose=0, + dry_run=0, + force=0): + + super().__init__(verbose, dry_run, force) + + # These executables are assumed to all be in the path. + # Borland doesn't seem to use any special registry settings to + # indicate their installation locations. + + self.cc = "bcc32.exe" + self.linker = "ilink32.exe" + self.lib = "tlib.exe" + + self.preprocess_options = None + self.compile_options = ['/tWM', '/O2', '/q', '/g0'] + self.compile_options_debug = ['/tWM', '/Od', '/q', '/g0'] + + self.ldflags_shared = ['/Tpd', '/Gn', '/q', '/x'] + self.ldflags_shared_debug = ['/Tpd', '/Gn', '/q', '/x'] + self.ldflags_static = [] + self.ldflags_exe = ['/Gn', '/q', '/x'] + self.ldflags_exe_debug = ['/Gn', '/q', '/x','/r'] + + + # -- Worker methods ------------------------------------------------ + + def compile(self, sources, + output_dir=None, macros=None, include_dirs=None, debug=0, + extra_preargs=None, extra_postargs=None, depends=None): + + macros, objects, extra_postargs, pp_opts, build = \ + self._setup_compile(output_dir, macros, include_dirs, sources, + depends, extra_postargs) + compile_opts = extra_preargs or [] + compile_opts.append ('-c') + if debug: + compile_opts.extend (self.compile_options_debug) + else: + compile_opts.extend (self.compile_options) + + for obj in objects: + try: + src, ext = build[obj] + except KeyError: + continue + # XXX why do the normpath here? + src = os.path.normpath(src) + obj = os.path.normpath(obj) + # XXX _setup_compile() did a mkpath() too but before the normpath. + # Is it possible to skip the normpath? + self.mkpath(os.path.dirname(obj)) + + if ext == '.res': + # This is already a binary file -- skip it. + continue # the 'for' loop + if ext == '.rc': + # This needs to be compiled to a .res file -- do it now. + try: + self.spawn (["brcc32", "-fo", obj, src]) + except DistutilsExecError as msg: + raise CompileError(msg) + continue # the 'for' loop + + # The next two are both for the real compiler. + if ext in self._c_extensions: + input_opt = "" + elif ext in self._cpp_extensions: + input_opt = "-P" + else: + # Unknown file type -- no extra options. The compiler + # will probably fail, but let it just in case this is a + # file the compiler recognizes even if we don't. + input_opt = "" + + output_opt = "-o" + obj + + # Compiler command line syntax is: "bcc32 [options] file(s)". + # Note that the source file names must appear at the end of + # the command line. + try: + self.spawn ([self.cc] + compile_opts + pp_opts + + [input_opt, output_opt] + + extra_postargs + [src]) + except DistutilsExecError as msg: + raise CompileError(msg) + + return objects + + # compile () + + + def create_static_lib (self, + objects, + output_libname, + output_dir=None, + debug=0, + target_lang=None): + + (objects, output_dir) = self._fix_object_args (objects, output_dir) + output_filename = \ + self.library_filename (output_libname, output_dir=output_dir) + + if self._need_link (objects, output_filename): + lib_args = [output_filename, '/u'] + objects + if debug: + pass # XXX what goes here? + try: + self.spawn ([self.lib] + lib_args) + except DistutilsExecError as msg: + raise LibError(msg) + else: + log.debug("skipping %s (up-to-date)", output_filename) + + # create_static_lib () + + + def link (self, + target_desc, + objects, + output_filename, + output_dir=None, + libraries=None, + library_dirs=None, + runtime_library_dirs=None, + export_symbols=None, + debug=0, + extra_preargs=None, + extra_postargs=None, + build_temp=None, + target_lang=None): + + # XXX this ignores 'build_temp'! should follow the lead of + # msvccompiler.py + + (objects, output_dir) = self._fix_object_args (objects, output_dir) + (libraries, library_dirs, runtime_library_dirs) = \ + self._fix_lib_args (libraries, library_dirs, runtime_library_dirs) + + if runtime_library_dirs: + log.warn("I don't know what to do with 'runtime_library_dirs': %s", + str(runtime_library_dirs)) + + if output_dir is not None: + output_filename = os.path.join (output_dir, output_filename) + + if self._need_link (objects, output_filename): + + # Figure out linker args based on type of target. + if target_desc == CCompiler.EXECUTABLE: + startup_obj = 'c0w32' + if debug: + ld_args = self.ldflags_exe_debug[:] + else: + ld_args = self.ldflags_exe[:] + else: + startup_obj = 'c0d32' + if debug: + ld_args = self.ldflags_shared_debug[:] + else: + ld_args = self.ldflags_shared[:] + + + # Create a temporary exports file for use by the linker + if export_symbols is None: + def_file = '' + else: + head, tail = os.path.split (output_filename) + modname, ext = os.path.splitext (tail) + temp_dir = os.path.dirname(objects[0]) # preserve tree structure + def_file = os.path.join (temp_dir, '%s.def' % modname) + contents = ['EXPORTS'] + for sym in (export_symbols or []): + contents.append(' %s=_%s' % (sym, sym)) + self.execute(write_file, (def_file, contents), + "writing %s" % def_file) + + # Borland C++ has problems with '/' in paths + objects2 = map(os.path.normpath, objects) + # split objects in .obj and .res files + # Borland C++ needs them at different positions in the command line + objects = [startup_obj] + resources = [] + for file in objects2: + (base, ext) = os.path.splitext(os.path.normcase(file)) + if ext == '.res': + resources.append(file) + else: + objects.append(file) + + + for l in library_dirs: + ld_args.append("/L%s" % os.path.normpath(l)) + ld_args.append("/L.") # we sometimes use relative paths + + # list of object files + ld_args.extend(objects) + + # XXX the command-line syntax for Borland C++ is a bit wonky; + # certain filenames are jammed together in one big string, but + # comma-delimited. This doesn't mesh too well with the + # Unix-centric attitude (with a DOS/Windows quoting hack) of + # 'spawn()', so constructing the argument list is a bit + # awkward. Note that doing the obvious thing and jamming all + # the filenames and commas into one argument would be wrong, + # because 'spawn()' would quote any filenames with spaces in + # them. Arghghh!. Apparently it works fine as coded... + + # name of dll/exe file + ld_args.extend([',',output_filename]) + # no map file and start libraries + ld_args.append(',,') + + for lib in libraries: + # see if we find it and if there is a bcpp specific lib + # (xxx_bcpp.lib) + libfile = self.find_library_file(library_dirs, lib, debug) + if libfile is None: + ld_args.append(lib) + # probably a BCPP internal library -- don't warn + else: + # full name which prefers bcpp_xxx.lib over xxx.lib + ld_args.append(libfile) + + # some default libraries + ld_args.append ('import32') + ld_args.append ('cw32mt') + + # def file for export symbols + ld_args.extend([',',def_file]) + # add resource files + ld_args.append(',') + ld_args.extend(resources) + + + if extra_preargs: + ld_args[:0] = extra_preargs + if extra_postargs: + ld_args.extend(extra_postargs) + + self.mkpath (os.path.dirname (output_filename)) + try: + self.spawn ([self.linker] + ld_args) + except DistutilsExecError as msg: + raise LinkError(msg) + + else: + log.debug("skipping %s (up-to-date)", output_filename) + + # link () + + # -- Miscellaneous methods ----------------------------------------- + + + def find_library_file (self, dirs, lib, debug=0): + # List of effective library names to try, in order of preference: + # xxx_bcpp.lib is better than xxx.lib + # and xxx_d.lib is better than xxx.lib if debug is set + # + # The "_bcpp" suffix is to handle a Python installation for people + # with multiple compilers (primarily Distutils hackers, I suspect + # ;-). The idea is they'd have one static library for each + # compiler they care about, since (almost?) every Windows compiler + # seems to have a different format for static libraries. + if debug: + dlib = (lib + "_d") + try_names = (dlib + "_bcpp", lib + "_bcpp", dlib, lib) + else: + try_names = (lib + "_bcpp", lib) + + for dir in dirs: + for name in try_names: + libfile = os.path.join(dir, self.library_filename(name)) + if os.path.exists(libfile): + return libfile + else: + # Oops, didn't find it in *any* of 'dirs' + return None + + # overwrite the one from CCompiler to support rc and res-files + def object_filenames (self, + source_filenames, + strip_dir=0, + output_dir=''): + if output_dir is None: output_dir = '' + obj_names = [] + for src_name in source_filenames: + # use normcase to make sure '.rc' is really '.rc' and not '.RC' + (base, ext) = os.path.splitext (os.path.normcase(src_name)) + if ext not in (self.src_extensions + ['.rc','.res']): + raise UnknownFileError("unknown file type '%s' (from '%s')" % \ + (ext, src_name)) + if strip_dir: + base = os.path.basename (base) + if ext == '.res': + # these can go unchanged + obj_names.append (os.path.join (output_dir, base + ext)) + elif ext == '.rc': + # these need to be compiled to .res-files + obj_names.append (os.path.join (output_dir, base + '.res')) + else: + obj_names.append (os.path.join (output_dir, + base + self.obj_extension)) + return obj_names + + # object_filenames () + + def preprocess (self, + source, + output_file=None, + macros=None, + include_dirs=None, + extra_preargs=None, + extra_postargs=None): + + (_, macros, include_dirs) = \ + self._fix_compile_args(None, macros, include_dirs) + pp_opts = gen_preprocess_options(macros, include_dirs) + pp_args = ['cpp32.exe'] + pp_opts + if output_file is not None: + pp_args.append('-o' + output_file) + if extra_preargs: + pp_args[:0] = extra_preargs + if extra_postargs: + pp_args.extend(extra_postargs) + pp_args.append(source) + + # We need to preprocess: either we're being forced to, or the + # source file is newer than the target (or the target doesn't + # exist). + if self.force or output_file is None or newer(source, output_file): + if output_file: + self.mkpath(os.path.dirname(output_file)) + try: + self.spawn(pp_args) + except DistutilsExecError as msg: + print(msg) + raise CompileError(msg) + + # preprocess() diff --git a/venv/Lib/site-packages/setuptools/_distutils/ccompiler.py b/venv/Lib/site-packages/setuptools/_distutils/ccompiler.py new file mode 100644 index 0000000..777fc66 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_distutils/ccompiler.py @@ -0,0 +1,1123 @@ +"""distutils.ccompiler + +Contains CCompiler, an abstract base class that defines the interface +for the Distutils compiler abstraction model.""" + +import sys, os, re +from distutils.errors import * +from distutils.spawn import spawn +from distutils.file_util import move_file +from distutils.dir_util import mkpath +from distutils.dep_util import newer_group +from distutils.util import split_quoted, execute +from distutils import log + +class CCompiler: + """Abstract base class to define the interface that must be implemented + by real compiler classes. Also has some utility methods used by + several compiler classes. + + The basic idea behind a compiler abstraction class is that each + instance can be used for all the compile/link steps in building a + single project. Thus, attributes common to all of those compile and + link steps -- include directories, macros to define, libraries to link + against, etc. -- are attributes of the compiler instance. To allow for + variability in how individual files are treated, most of those + attributes may be varied on a per-compilation or per-link basis. + """ + + # 'compiler_type' is a class attribute that identifies this class. It + # keeps code that wants to know what kind of compiler it's dealing with + # from having to import all possible compiler classes just to do an + # 'isinstance'. In concrete CCompiler subclasses, 'compiler_type' + # should really, really be one of the keys of the 'compiler_class' + # dictionary (see below -- used by the 'new_compiler()' factory + # function) -- authors of new compiler interface classes are + # responsible for updating 'compiler_class'! + compiler_type = None + + # XXX things not handled by this compiler abstraction model: + # * client can't provide additional options for a compiler, + # e.g. warning, optimization, debugging flags. Perhaps this + # should be the domain of concrete compiler abstraction classes + # (UnixCCompiler, MSVCCompiler, etc.) -- or perhaps the base + # class should have methods for the common ones. + # * can't completely override the include or library searchg + # path, ie. no "cc -I -Idir1 -Idir2" or "cc -L -Ldir1 -Ldir2". + # I'm not sure how widely supported this is even by Unix + # compilers, much less on other platforms. And I'm even less + # sure how useful it is; maybe for cross-compiling, but + # support for that is a ways off. (And anyways, cross + # compilers probably have a dedicated binary with the + # right paths compiled in. I hope.) + # * can't do really freaky things with the library list/library + # dirs, e.g. "-Ldir1 -lfoo -Ldir2 -lfoo" to link against + # different versions of libfoo.a in different locations. I + # think this is useless without the ability to null out the + # library search path anyways. + + + # Subclasses that rely on the standard filename generation methods + # implemented below should override these; see the comment near + # those methods ('object_filenames()' et. al.) for details: + src_extensions = None # list of strings + obj_extension = None # string + static_lib_extension = None + shared_lib_extension = None # string + static_lib_format = None # format string + shared_lib_format = None # prob. same as static_lib_format + exe_extension = None # string + + # Default language settings. language_map is used to detect a source + # file or Extension target language, checking source filenames. + # language_order is used to detect the language precedence, when deciding + # what language to use when mixing source types. For example, if some + # extension has two files with ".c" extension, and one with ".cpp", it + # is still linked as c++. + language_map = {".c" : "c", + ".cc" : "c++", + ".cpp" : "c++", + ".cxx" : "c++", + ".m" : "objc", + } + language_order = ["c++", "objc", "c"] + + def __init__(self, verbose=0, dry_run=0, force=0): + self.dry_run = dry_run + self.force = force + self.verbose = verbose + + # 'output_dir': a common output directory for object, library, + # shared object, and shared library files + self.output_dir = None + + # 'macros': a list of macro definitions (or undefinitions). A + # macro definition is a 2-tuple (name, value), where the value is + # either a string or None (no explicit value). A macro + # undefinition is a 1-tuple (name,). + self.macros = [] + + # 'include_dirs': a list of directories to search for include files + self.include_dirs = [] + + # 'libraries': a list of libraries to include in any link + # (library names, not filenames: eg. "foo" not "libfoo.a") + self.libraries = [] + + # 'library_dirs': a list of directories to search for libraries + self.library_dirs = [] + + # 'runtime_library_dirs': a list of directories to search for + # shared libraries/objects at runtime + self.runtime_library_dirs = [] + + # 'objects': a list of object files (or similar, such as explicitly + # named library files) to include on any link + self.objects = [] + + for key in self.executables.keys(): + self.set_executable(key, self.executables[key]) + + def set_executables(self, **kwargs): + """Define the executables (and options for them) that will be run + to perform the various stages of compilation. The exact set of + executables that may be specified here depends on the compiler + class (via the 'executables' class attribute), but most will have: + compiler the C/C++ compiler + linker_so linker used to create shared objects and libraries + linker_exe linker used to create binary executables + archiver static library creator + + On platforms with a command-line (Unix, DOS/Windows), each of these + is a string that will be split into executable name and (optional) + list of arguments. (Splitting the string is done similarly to how + Unix shells operate: words are delimited by spaces, but quotes and + backslashes can override this. See + 'distutils.util.split_quoted()'.) + """ + + # Note that some CCompiler implementation classes will define class + # attributes 'cpp', 'cc', etc. with hard-coded executable names; + # this is appropriate when a compiler class is for exactly one + # compiler/OS combination (eg. MSVCCompiler). Other compiler + # classes (UnixCCompiler, in particular) are driven by information + # discovered at run-time, since there are many different ways to do + # basically the same things with Unix C compilers. + + for key in kwargs: + if key not in self.executables: + raise ValueError("unknown executable '%s' for class %s" % + (key, self.__class__.__name__)) + self.set_executable(key, kwargs[key]) + + def set_executable(self, key, value): + if isinstance(value, str): + setattr(self, key, split_quoted(value)) + else: + setattr(self, key, value) + + def _find_macro(self, name): + i = 0 + for defn in self.macros: + if defn[0] == name: + return i + i += 1 + return None + + def _check_macro_definitions(self, definitions): + """Ensures that every element of 'definitions' is a valid macro + definition, ie. either (name,value) 2-tuple or a (name,) tuple. Do + nothing if all definitions are OK, raise TypeError otherwise. + """ + for defn in definitions: + if not (isinstance(defn, tuple) and + (len(defn) in (1, 2) and + (isinstance (defn[1], str) or defn[1] is None)) and + isinstance (defn[0], str)): + raise TypeError(("invalid macro definition '%s': " % defn) + \ + "must be tuple (string,), (string, string), or " + \ + "(string, None)") + + + # -- Bookkeeping methods ------------------------------------------- + + def define_macro(self, name, value=None): + """Define a preprocessor macro for all compilations driven by this + compiler object. The optional parameter 'value' should be a + string; if it is not supplied, then the macro will be defined + without an explicit value and the exact outcome depends on the + compiler used (XXX true? does ANSI say anything about this?) + """ + # Delete from the list of macro definitions/undefinitions if + # already there (so that this one will take precedence). + i = self._find_macro (name) + if i is not None: + del self.macros[i] + + self.macros.append((name, value)) + + def undefine_macro(self, name): + """Undefine a preprocessor macro for all compilations driven by + this compiler object. If the same macro is defined by + 'define_macro()' and undefined by 'undefine_macro()' the last call + takes precedence (including multiple redefinitions or + undefinitions). If the macro is redefined/undefined on a + per-compilation basis (ie. in the call to 'compile()'), then that + takes precedence. + """ + # Delete from the list of macro definitions/undefinitions if + # already there (so that this one will take precedence). + i = self._find_macro (name) + if i is not None: + del self.macros[i] + + undefn = (name,) + self.macros.append(undefn) + + def add_include_dir(self, dir): + """Add 'dir' to the list of directories that will be searched for + header files. The compiler is instructed to search directories in + the order in which they are supplied by successive calls to + 'add_include_dir()'. + """ + self.include_dirs.append(dir) + + def set_include_dirs(self, dirs): + """Set the list of directories that will be searched to 'dirs' (a + list of strings). Overrides any preceding calls to + 'add_include_dir()'; subsequence calls to 'add_include_dir()' add + to the list passed to 'set_include_dirs()'. This does not affect + any list of standard include directories that the compiler may + search by default. + """ + self.include_dirs = dirs[:] + + def add_library(self, libname): + """Add 'libname' to the list of libraries that will be included in + all links driven by this compiler object. Note that 'libname' + should *not* be the name of a file containing a library, but the + name of the library itself: the actual filename will be inferred by + the linker, the compiler, or the compiler class (depending on the + platform). + + The linker will be instructed to link against libraries in the + order they were supplied to 'add_library()' and/or + 'set_libraries()'. It is perfectly valid to duplicate library + names; the linker will be instructed to link against libraries as + many times as they are mentioned. + """ + self.libraries.append(libname) + + def set_libraries(self, libnames): + """Set the list of libraries to be included in all links driven by + this compiler object to 'libnames' (a list of strings). This does + not affect any standard system libraries that the linker may + include by default. + """ + self.libraries = libnames[:] + + def add_library_dir(self, dir): + """Add 'dir' to the list of directories that will be searched for + libraries specified to 'add_library()' and 'set_libraries()'. The + linker will be instructed to search for libraries in the order they + are supplied to 'add_library_dir()' and/or 'set_library_dirs()'. + """ + self.library_dirs.append(dir) + + def set_library_dirs(self, dirs): + """Set the list of library search directories to 'dirs' (a list of + strings). This does not affect any standard library search path + that the linker may search by default. + """ + self.library_dirs = dirs[:] + + def add_runtime_library_dir(self, dir): + """Add 'dir' to the list of directories that will be searched for + shared libraries at runtime. + """ + self.runtime_library_dirs.append(dir) + + def set_runtime_library_dirs(self, dirs): + """Set the list of directories to search for shared libraries at + runtime to 'dirs' (a list of strings). This does not affect any + standard search path that the runtime linker may search by + default. + """ + self.runtime_library_dirs = dirs[:] + + def add_link_object(self, object): + """Add 'object' to the list of object files (or analogues, such as + explicitly named library files or the output of "resource + compilers") to be included in every link driven by this compiler + object. + """ + self.objects.append(object) + + def set_link_objects(self, objects): + """Set the list of object files (or analogues) to be included in + every link to 'objects'. This does not affect any standard object + files that the linker may include by default (such as system + libraries). + """ + self.objects = objects[:] + + + # -- Private utility methods -------------------------------------- + # (here for the convenience of subclasses) + + # Helper method to prep compiler in subclass compile() methods + + def _setup_compile(self, outdir, macros, incdirs, sources, depends, + extra): + """Process arguments and decide which source files to compile.""" + if outdir is None: + outdir = self.output_dir + elif not isinstance(outdir, str): + raise TypeError("'output_dir' must be a string or None") + + if macros is None: + macros = self.macros + elif isinstance(macros, list): + macros = macros + (self.macros or []) + else: + raise TypeError("'macros' (if supplied) must be a list of tuples") + + if incdirs is None: + incdirs = self.include_dirs + elif isinstance(incdirs, (list, tuple)): + incdirs = list(incdirs) + (self.include_dirs or []) + else: + raise TypeError( + "'include_dirs' (if supplied) must be a list of strings") + + if extra is None: + extra = [] + + # Get the list of expected output (object) files + objects = self.object_filenames(sources, strip_dir=0, + output_dir=outdir) + assert len(objects) == len(sources) + + pp_opts = gen_preprocess_options(macros, incdirs) + + build = {} + for i in range(len(sources)): + src = sources[i] + obj = objects[i] + ext = os.path.splitext(src)[1] + self.mkpath(os.path.dirname(obj)) + build[obj] = (src, ext) + + return macros, objects, extra, pp_opts, build + + def _get_cc_args(self, pp_opts, debug, before): + # works for unixccompiler, cygwinccompiler + cc_args = pp_opts + ['-c'] + if debug: + cc_args[:0] = ['-g'] + if before: + cc_args[:0] = before + return cc_args + + def _fix_compile_args(self, output_dir, macros, include_dirs): + """Typecheck and fix-up some of the arguments to the 'compile()' + method, and return fixed-up values. Specifically: if 'output_dir' + is None, replaces it with 'self.output_dir'; ensures that 'macros' + is a list, and augments it with 'self.macros'; ensures that + 'include_dirs' is a list, and augments it with 'self.include_dirs'. + Guarantees that the returned values are of the correct type, + i.e. for 'output_dir' either string or None, and for 'macros' and + 'include_dirs' either list or None. + """ + if output_dir is None: + output_dir = self.output_dir + elif not isinstance(output_dir, str): + raise TypeError("'output_dir' must be a string or None") + + if macros is None: + macros = self.macros + elif isinstance(macros, list): + macros = macros + (self.macros or []) + else: + raise TypeError("'macros' (if supplied) must be a list of tuples") + + if include_dirs is None: + include_dirs = self.include_dirs + elif isinstance(include_dirs, (list, tuple)): + include_dirs = list(include_dirs) + (self.include_dirs or []) + else: + raise TypeError( + "'include_dirs' (if supplied) must be a list of strings") + + return output_dir, macros, include_dirs + + def _prep_compile(self, sources, output_dir, depends=None): + """Decide which source files must be recompiled. + + Determine the list of object files corresponding to 'sources', + and figure out which ones really need to be recompiled. + Return a list of all object files and a dictionary telling + which source files can be skipped. + """ + # Get the list of expected output (object) files + objects = self.object_filenames(sources, output_dir=output_dir) + assert len(objects) == len(sources) + + # Return an empty dict for the "which source files can be skipped" + # return value to preserve API compatibility. + return objects, {} + + def _fix_object_args(self, objects, output_dir): + """Typecheck and fix up some arguments supplied to various methods. + Specifically: ensure that 'objects' is a list; if output_dir is + None, replace with self.output_dir. Return fixed versions of + 'objects' and 'output_dir'. + """ + if not isinstance(objects, (list, tuple)): + raise TypeError("'objects' must be a list or tuple of strings") + objects = list(objects) + + if output_dir is None: + output_dir = self.output_dir + elif not isinstance(output_dir, str): + raise TypeError("'output_dir' must be a string or None") + + return (objects, output_dir) + + def _fix_lib_args(self, libraries, library_dirs, runtime_library_dirs): + """Typecheck and fix up some of the arguments supplied to the + 'link_*' methods. Specifically: ensure that all arguments are + lists, and augment them with their permanent versions + (eg. 'self.libraries' augments 'libraries'). Return a tuple with + fixed versions of all arguments. + """ + if libraries is None: + libraries = self.libraries + elif isinstance(libraries, (list, tuple)): + libraries = list (libraries) + (self.libraries or []) + else: + raise TypeError( + "'libraries' (if supplied) must be a list of strings") + + if library_dirs is None: + library_dirs = self.library_dirs + elif isinstance(library_dirs, (list, tuple)): + library_dirs = list (library_dirs) + (self.library_dirs or []) + else: + raise TypeError( + "'library_dirs' (if supplied) must be a list of strings") + + if runtime_library_dirs is None: + runtime_library_dirs = self.runtime_library_dirs + elif isinstance(runtime_library_dirs, (list, tuple)): + runtime_library_dirs = (list(runtime_library_dirs) + + (self.runtime_library_dirs or [])) + else: + raise TypeError("'runtime_library_dirs' (if supplied) " + "must be a list of strings") + + return (libraries, library_dirs, runtime_library_dirs) + + def _need_link(self, objects, output_file): + """Return true if we need to relink the files listed in 'objects' + to recreate 'output_file'. + """ + if self.force: + return True + else: + if self.dry_run: + newer = newer_group (objects, output_file, missing='newer') + else: + newer = newer_group (objects, output_file) + return newer + + def detect_language(self, sources): + """Detect the language of a given file, or list of files. Uses + language_map, and language_order to do the job. + """ + if not isinstance(sources, list): + sources = [sources] + lang = None + index = len(self.language_order) + for source in sources: + base, ext = os.path.splitext(source) + extlang = self.language_map.get(ext) + try: + extindex = self.language_order.index(extlang) + if extindex < index: + lang = extlang + index = extindex + except ValueError: + pass + return lang + + + # -- Worker methods ------------------------------------------------ + # (must be implemented by subclasses) + + def preprocess(self, source, output_file=None, macros=None, + include_dirs=None, extra_preargs=None, extra_postargs=None): + """Preprocess a single C/C++ source file, named in 'source'. + Output will be written to file named 'output_file', or stdout if + 'output_file' not supplied. 'macros' is a list of macro + definitions as for 'compile()', which will augment the macros set + with 'define_macro()' and 'undefine_macro()'. 'include_dirs' is a + list of directory names that will be added to the default list. + + Raises PreprocessError on failure. + """ + pass + + def compile(self, sources, output_dir=None, macros=None, + include_dirs=None, debug=0, extra_preargs=None, + extra_postargs=None, depends=None): + """Compile one or more source files. + + 'sources' must be a list of filenames, most likely C/C++ + files, but in reality anything that can be handled by a + particular compiler and compiler class (eg. MSVCCompiler can + handle resource files in 'sources'). Return a list of object + filenames, one per source filename in 'sources'. Depending on + the implementation, not all source files will necessarily be + compiled, but all corresponding object filenames will be + returned. + + If 'output_dir' is given, object files will be put under it, while + retaining their original path component. That is, "foo/bar.c" + normally compiles to "foo/bar.o" (for a Unix implementation); if + 'output_dir' is "build", then it would compile to + "build/foo/bar.o". + + 'macros', if given, must be a list of macro definitions. A macro + definition is either a (name, value) 2-tuple or a (name,) 1-tuple. + The former defines a macro; if the value is None, the macro is + defined without an explicit value. The 1-tuple case undefines a + macro. Later definitions/redefinitions/ undefinitions take + precedence. + + 'include_dirs', if given, must be a list of strings, the + directories to add to the default include file search path for this + compilation only. + + 'debug' is a boolean; if true, the compiler will be instructed to + output debug symbols in (or alongside) the object file(s). + + 'extra_preargs' and 'extra_postargs' are implementation- dependent. + On platforms that have the notion of a command-line (e.g. Unix, + DOS/Windows), they are most likely lists of strings: extra + command-line arguments to prepend/append to the compiler command + line. On other platforms, consult the implementation class + documentation. In any event, they are intended as an escape hatch + for those occasions when the abstract compiler framework doesn't + cut the mustard. + + 'depends', if given, is a list of filenames that all targets + depend on. If a source file is older than any file in + depends, then the source file will be recompiled. This + supports dependency tracking, but only at a coarse + granularity. + + Raises CompileError on failure. + """ + # A concrete compiler class can either override this method + # entirely or implement _compile(). + macros, objects, extra_postargs, pp_opts, build = \ + self._setup_compile(output_dir, macros, include_dirs, sources, + depends, extra_postargs) + cc_args = self._get_cc_args(pp_opts, debug, extra_preargs) + + for obj in objects: + try: + src, ext = build[obj] + except KeyError: + continue + self._compile(obj, src, ext, cc_args, extra_postargs, pp_opts) + + # Return *all* object filenames, not just the ones we just built. + return objects + + def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts): + """Compile 'src' to product 'obj'.""" + # A concrete compiler class that does not override compile() + # should implement _compile(). + pass + + def create_static_lib(self, objects, output_libname, output_dir=None, + debug=0, target_lang=None): + """Link a bunch of stuff together to create a static library file. + The "bunch of stuff" consists of the list of object files supplied + as 'objects', the extra object files supplied to + 'add_link_object()' and/or 'set_link_objects()', the libraries + supplied to 'add_library()' and/or 'set_libraries()', and the + libraries supplied as 'libraries' (if any). + + 'output_libname' should be a library name, not a filename; the + filename will be inferred from the library name. 'output_dir' is + the directory where the library file will be put. + + 'debug' is a boolean; if true, debugging information will be + included in the library (note that on most platforms, it is the + compile step where this matters: the 'debug' flag is included here + just for consistency). + + 'target_lang' is the target language for which the given objects + are being compiled. This allows specific linkage time treatment of + certain languages. + + Raises LibError on failure. + """ + pass + + + # values for target_desc parameter in link() + SHARED_OBJECT = "shared_object" + SHARED_LIBRARY = "shared_library" + EXECUTABLE = "executable" + + def link(self, + target_desc, + objects, + output_filename, + output_dir=None, + libraries=None, + library_dirs=None, + runtime_library_dirs=None, + export_symbols=None, + debug=0, + extra_preargs=None, + extra_postargs=None, + build_temp=None, + target_lang=None): + """Link a bunch of stuff together to create an executable or + shared library file. + + The "bunch of stuff" consists of the list of object files supplied + as 'objects'. 'output_filename' should be a filename. If + 'output_dir' is supplied, 'output_filename' is relative to it + (i.e. 'output_filename' can provide directory components if + needed). + + 'libraries' is a list of libraries to link against. These are + library names, not filenames, since they're translated into + filenames in a platform-specific way (eg. "foo" becomes "libfoo.a" + on Unix and "foo.lib" on DOS/Windows). However, they can include a + directory component, which means the linker will look in that + specific directory rather than searching all the normal locations. + + 'library_dirs', if supplied, should be a list of directories to + search for libraries that were specified as bare library names + (ie. no directory component). These are on top of the system + default and those supplied to 'add_library_dir()' and/or + 'set_library_dirs()'. 'runtime_library_dirs' is a list of + directories that will be embedded into the shared library and used + to search for other shared libraries that *it* depends on at + run-time. (This may only be relevant on Unix.) + + 'export_symbols' is a list of symbols that the shared library will + export. (This appears to be relevant only on Windows.) + + 'debug' is as for 'compile()' and 'create_static_lib()', with the + slight distinction that it actually matters on most platforms (as + opposed to 'create_static_lib()', which includes a 'debug' flag + mostly for form's sake). + + 'extra_preargs' and 'extra_postargs' are as for 'compile()' (except + of course that they supply command-line arguments for the + particular linker being used). + + 'target_lang' is the target language for which the given objects + are being compiled. This allows specific linkage time treatment of + certain languages. + + Raises LinkError on failure. + """ + raise NotImplementedError + + + # Old 'link_*()' methods, rewritten to use the new 'link()' method. + + def link_shared_lib(self, + objects, + output_libname, + output_dir=None, + libraries=None, + library_dirs=None, + runtime_library_dirs=None, + export_symbols=None, + debug=0, + extra_preargs=None, + extra_postargs=None, + build_temp=None, + target_lang=None): + self.link(CCompiler.SHARED_LIBRARY, objects, + self.library_filename(output_libname, lib_type='shared'), + output_dir, + libraries, library_dirs, runtime_library_dirs, + export_symbols, debug, + extra_preargs, extra_postargs, build_temp, target_lang) + + + def link_shared_object(self, + objects, + output_filename, + output_dir=None, + libraries=None, + library_dirs=None, + runtime_library_dirs=None, + export_symbols=None, + debug=0, + extra_preargs=None, + extra_postargs=None, + build_temp=None, + target_lang=None): + self.link(CCompiler.SHARED_OBJECT, objects, + output_filename, output_dir, + libraries, library_dirs, runtime_library_dirs, + export_symbols, debug, + extra_preargs, extra_postargs, build_temp, target_lang) + + + def link_executable(self, + objects, + output_progname, + output_dir=None, + libraries=None, + library_dirs=None, + runtime_library_dirs=None, + debug=0, + extra_preargs=None, + extra_postargs=None, + target_lang=None): + self.link(CCompiler.EXECUTABLE, objects, + self.executable_filename(output_progname), output_dir, + libraries, library_dirs, runtime_library_dirs, None, + debug, extra_preargs, extra_postargs, None, target_lang) + + + # -- Miscellaneous methods ----------------------------------------- + # These are all used by the 'gen_lib_options() function; there is + # no appropriate default implementation so subclasses should + # implement all of these. + + def library_dir_option(self, dir): + """Return the compiler option to add 'dir' to the list of + directories searched for libraries. + """ + raise NotImplementedError + + def runtime_library_dir_option(self, dir): + """Return the compiler option to add 'dir' to the list of + directories searched for runtime libraries. + """ + raise NotImplementedError + + def library_option(self, lib): + """Return the compiler option to add 'lib' to the list of libraries + linked into the shared library or executable. + """ + raise NotImplementedError + + def has_function(self, funcname, includes=None, include_dirs=None, + libraries=None, library_dirs=None): + """Return a boolean indicating whether funcname is supported on + the current platform. The optional arguments can be used to + augment the compilation environment. + """ + # this can't be included at module scope because it tries to + # import math which might not be available at that point - maybe + # the necessary logic should just be inlined? + import tempfile + if includes is None: + includes = [] + if include_dirs is None: + include_dirs = [] + if libraries is None: + libraries = [] + if library_dirs is None: + library_dirs = [] + fd, fname = tempfile.mkstemp(".c", funcname, text=True) + f = os.fdopen(fd, "w") + try: + for incl in includes: + f.write("""#include "%s"\n""" % incl) + f.write("""\ +int main (int argc, char **argv) { + %s(); + return 0; +} +""" % funcname) + finally: + f.close() + try: + objects = self.compile([fname], include_dirs=include_dirs) + except CompileError: + return False + finally: + os.remove(fname) + + try: + self.link_executable(objects, "a.out", + libraries=libraries, + library_dirs=library_dirs) + except (LinkError, TypeError): + return False + else: + os.remove(os.path.join(self.output_dir or '', "a.out")) + finally: + for fn in objects: + os.remove(fn) + return True + + def find_library_file (self, dirs, lib, debug=0): + """Search the specified list of directories for a static or shared + library file 'lib' and return the full path to that file. If + 'debug' true, look for a debugging version (if that makes sense on + the current platform). Return None if 'lib' wasn't found in any of + the specified directories. + """ + raise NotImplementedError + + # -- Filename generation methods ----------------------------------- + + # The default implementation of the filename generating methods are + # prejudiced towards the Unix/DOS/Windows view of the world: + # * object files are named by replacing the source file extension + # (eg. .c/.cpp -> .o/.obj) + # * library files (shared or static) are named by plugging the + # library name and extension into a format string, eg. + # "lib%s.%s" % (lib_name, ".a") for Unix static libraries + # * executables are named by appending an extension (possibly + # empty) to the program name: eg. progname + ".exe" for + # Windows + # + # To reduce redundant code, these methods expect to find + # several attributes in the current object (presumably defined + # as class attributes): + # * src_extensions - + # list of C/C++ source file extensions, eg. ['.c', '.cpp'] + # * obj_extension - + # object file extension, eg. '.o' or '.obj' + # * static_lib_extension - + # extension for static library files, eg. '.a' or '.lib' + # * shared_lib_extension - + # extension for shared library/object files, eg. '.so', '.dll' + # * static_lib_format - + # format string for generating static library filenames, + # eg. 'lib%s.%s' or '%s.%s' + # * shared_lib_format + # format string for generating shared library filenames + # (probably same as static_lib_format, since the extension + # is one of the intended parameters to the format string) + # * exe_extension - + # extension for executable files, eg. '' or '.exe' + + def object_filenames(self, source_filenames, strip_dir=0, output_dir=''): + if output_dir is None: + output_dir = '' + obj_names = [] + for src_name in source_filenames: + base, ext = os.path.splitext(src_name) + base = os.path.splitdrive(base)[1] # Chop off the drive + base = base[os.path.isabs(base):] # If abs, chop off leading / + if ext not in self.src_extensions: + raise UnknownFileError( + "unknown file type '%s' (from '%s')" % (ext, src_name)) + if strip_dir: + base = os.path.basename(base) + obj_names.append(os.path.join(output_dir, + base + self.obj_extension)) + return obj_names + + def shared_object_filename(self, basename, strip_dir=0, output_dir=''): + assert output_dir is not None + if strip_dir: + basename = os.path.basename(basename) + return os.path.join(output_dir, basename + self.shared_lib_extension) + + def executable_filename(self, basename, strip_dir=0, output_dir=''): + assert output_dir is not None + if strip_dir: + basename = os.path.basename(basename) + return os.path.join(output_dir, basename + (self.exe_extension or '')) + + def library_filename(self, libname, lib_type='static', # or 'shared' + strip_dir=0, output_dir=''): + assert output_dir is not None + if lib_type not in ("static", "shared", "dylib", "xcode_stub"): + raise ValueError( + "'lib_type' must be \"static\", \"shared\", \"dylib\", or \"xcode_stub\"") + fmt = getattr(self, lib_type + "_lib_format") + ext = getattr(self, lib_type + "_lib_extension") + + dir, base = os.path.split(libname) + filename = fmt % (base, ext) + if strip_dir: + dir = '' + + return os.path.join(output_dir, dir, filename) + + + # -- Utility methods ----------------------------------------------- + + def announce(self, msg, level=1): + log.debug(msg) + + def debug_print(self, msg): + from distutils.debug import DEBUG + if DEBUG: + print(msg) + + def warn(self, msg): + sys.stderr.write("warning: %s\n" % msg) + + def execute(self, func, args, msg=None, level=1): + execute(func, args, msg, self.dry_run) + + def spawn(self, cmd, **kwargs): + spawn(cmd, dry_run=self.dry_run, **kwargs) + + def move_file(self, src, dst): + return move_file(src, dst, dry_run=self.dry_run) + + def mkpath (self, name, mode=0o777): + mkpath(name, mode, dry_run=self.dry_run) + + +# Map a sys.platform/os.name ('posix', 'nt') to the default compiler +# type for that platform. Keys are interpreted as re match +# patterns. Order is important; platform mappings are preferred over +# OS names. +_default_compilers = ( + + # Platform string mappings + + # on a cygwin built python we can use gcc like an ordinary UNIXish + # compiler + ('cygwin.*', 'unix'), + + # OS name mappings + ('posix', 'unix'), + ('nt', 'msvc'), + + ) + +def get_default_compiler(osname=None, platform=None): + """Determine the default compiler to use for the given platform. + + osname should be one of the standard Python OS names (i.e. the + ones returned by os.name) and platform the common value + returned by sys.platform for the platform in question. + + The default values are os.name and sys.platform in case the + parameters are not given. + """ + if osname is None: + osname = os.name + if platform is None: + platform = sys.platform + for pattern, compiler in _default_compilers: + if re.match(pattern, platform) is not None or \ + re.match(pattern, osname) is not None: + return compiler + # Default to Unix compiler + return 'unix' + +# Map compiler types to (module_name, class_name) pairs -- ie. where to +# find the code that implements an interface to this compiler. (The module +# is assumed to be in the 'distutils' package.) +compiler_class = { 'unix': ('unixccompiler', 'UnixCCompiler', + "standard UNIX-style compiler"), + 'msvc': ('_msvccompiler', 'MSVCCompiler', + "Microsoft Visual C++"), + 'cygwin': ('cygwinccompiler', 'CygwinCCompiler', + "Cygwin port of GNU C Compiler for Win32"), + 'mingw32': ('cygwinccompiler', 'Mingw32CCompiler', + "Mingw32 port of GNU C Compiler for Win32"), + 'bcpp': ('bcppcompiler', 'BCPPCompiler', + "Borland C++ Compiler"), + } + +def show_compilers(): + """Print list of available compilers (used by the "--help-compiler" + options to "build", "build_ext", "build_clib"). + """ + # XXX this "knows" that the compiler option it's describing is + # "--compiler", which just happens to be the case for the three + # commands that use it. + from distutils.fancy_getopt import FancyGetopt + compilers = [] + for compiler in compiler_class.keys(): + compilers.append(("compiler="+compiler, None, + compiler_class[compiler][2])) + compilers.sort() + pretty_printer = FancyGetopt(compilers) + pretty_printer.print_help("List of available compilers:") + + +def new_compiler(plat=None, compiler=None, verbose=0, dry_run=0, force=0): + """Generate an instance of some CCompiler subclass for the supplied + platform/compiler combination. 'plat' defaults to 'os.name' + (eg. 'posix', 'nt'), and 'compiler' defaults to the default compiler + for that platform. Currently only 'posix' and 'nt' are supported, and + the default compilers are "traditional Unix interface" (UnixCCompiler + class) and Visual C++ (MSVCCompiler class). Note that it's perfectly + possible to ask for a Unix compiler object under Windows, and a + Microsoft compiler object under Unix -- if you supply a value for + 'compiler', 'plat' is ignored. + """ + if plat is None: + plat = os.name + + try: + if compiler is None: + compiler = get_default_compiler(plat) + + (module_name, class_name, long_description) = compiler_class[compiler] + except KeyError: + msg = "don't know how to compile C/C++ code on platform '%s'" % plat + if compiler is not None: + msg = msg + " with '%s' compiler" % compiler + raise DistutilsPlatformError(msg) + + try: + module_name = "distutils." + module_name + __import__ (module_name) + module = sys.modules[module_name] + klass = vars(module)[class_name] + except ImportError: + raise DistutilsModuleError( + "can't compile C/C++ code: unable to load module '%s'" % \ + module_name) + except KeyError: + raise DistutilsModuleError( + "can't compile C/C++ code: unable to find class '%s' " + "in module '%s'" % (class_name, module_name)) + + # XXX The None is necessary to preserve backwards compatibility + # with classes that expect verbose to be the first positional + # argument. + return klass(None, dry_run, force) + + +def gen_preprocess_options(macros, include_dirs): + """Generate C pre-processor options (-D, -U, -I) as used by at least + two types of compilers: the typical Unix compiler and Visual C++. + 'macros' is the usual thing, a list of 1- or 2-tuples, where (name,) + means undefine (-U) macro 'name', and (name,value) means define (-D) + macro 'name' to 'value'. 'include_dirs' is just a list of directory + names to be added to the header file search path (-I). Returns a list + of command-line options suitable for either Unix compilers or Visual + C++. + """ + # XXX it would be nice (mainly aesthetic, and so we don't generate + # stupid-looking command lines) to go over 'macros' and eliminate + # redundant definitions/undefinitions (ie. ensure that only the + # latest mention of a particular macro winds up on the command + # line). I don't think it's essential, though, since most (all?) + # Unix C compilers only pay attention to the latest -D or -U + # mention of a macro on their command line. Similar situation for + # 'include_dirs'. I'm punting on both for now. Anyways, weeding out + # redundancies like this should probably be the province of + # CCompiler, since the data structures used are inherited from it + # and therefore common to all CCompiler classes. + pp_opts = [] + for macro in macros: + if not (isinstance(macro, tuple) and 1 <= len(macro) <= 2): + raise TypeError( + "bad macro definition '%s': " + "each element of 'macros' list must be a 1- or 2-tuple" + % macro) + + if len(macro) == 1: # undefine this macro + pp_opts.append("-U%s" % macro[0]) + elif len(macro) == 2: + if macro[1] is None: # define with no explicit value + pp_opts.append("-D%s" % macro[0]) + else: + # XXX *don't* need to be clever about quoting the + # macro value here, because we're going to avoid the + # shell at all costs when we spawn the command! + pp_opts.append("-D%s=%s" % macro) + + for dir in include_dirs: + pp_opts.append("-I%s" % dir) + return pp_opts + + +def gen_lib_options (compiler, library_dirs, runtime_library_dirs, libraries): + """Generate linker options for searching library directories and + linking with specific libraries. 'libraries' and 'library_dirs' are, + respectively, lists of library names (not filenames!) and search + directories. Returns a list of command-line options suitable for use + with some compiler (depending on the two format strings passed in). + """ + lib_opts = [] + + for dir in library_dirs: + lib_opts.append(compiler.library_dir_option(dir)) + + for dir in runtime_library_dirs: + opt = compiler.runtime_library_dir_option(dir) + if isinstance(opt, list): + lib_opts = lib_opts + opt + else: + lib_opts.append(opt) + + # XXX it's important that we *not* remove redundant library mentions! + # sometimes you really do have to say "-lfoo -lbar -lfoo" in order to + # resolve all symbols. I just hope we never have to say "-lfoo obj.o + # -lbar" to get things to work -- that's certainly a possibility, but a + # pretty nasty way to arrange your C code. + + for lib in libraries: + (lib_dir, lib_name) = os.path.split(lib) + if lib_dir: + lib_file = compiler.find_library_file([lib_dir], lib_name) + if lib_file: + lib_opts.append(lib_file) + else: + compiler.warn("no library file corresponding to " + "'%s' found (skipping)" % lib) + else: + lib_opts.append(compiler.library_option (lib)) + return lib_opts diff --git a/venv/Lib/site-packages/setuptools/_distutils/cmd.py b/venv/Lib/site-packages/setuptools/_distutils/cmd.py new file mode 100644 index 0000000..dba3191 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_distutils/cmd.py @@ -0,0 +1,403 @@ +"""distutils.cmd + +Provides the Command class, the base class for the command classes +in the distutils.command package. +""" + +import sys, os, re +from distutils.errors import DistutilsOptionError +from distutils import util, dir_util, file_util, archive_util, dep_util +from distutils import log + +class Command: + """Abstract base class for defining command classes, the "worker bees" + of the Distutils. A useful analogy for command classes is to think of + them as subroutines with local variables called "options". The options + are "declared" in 'initialize_options()' and "defined" (given their + final values, aka "finalized") in 'finalize_options()', both of which + must be defined by every command class. The distinction between the + two is necessary because option values might come from the outside + world (command line, config file, ...), and any options dependent on + other options must be computed *after* these outside influences have + been processed -- hence 'finalize_options()'. The "body" of the + subroutine, where it does all its work based on the values of its + options, is the 'run()' method, which must also be implemented by every + command class. + """ + + # 'sub_commands' formalizes the notion of a "family" of commands, + # eg. "install" as the parent with sub-commands "install_lib", + # "install_headers", etc. The parent of a family of commands + # defines 'sub_commands' as a class attribute; it's a list of + # (command_name : string, predicate : unbound_method | string | None) + # tuples, where 'predicate' is a method of the parent command that + # determines whether the corresponding command is applicable in the + # current situation. (Eg. we "install_headers" is only applicable if + # we have any C header files to install.) If 'predicate' is None, + # that command is always applicable. + # + # 'sub_commands' is usually defined at the *end* of a class, because + # predicates can be unbound methods, so they must already have been + # defined. The canonical example is the "install" command. + sub_commands = [] + + + # -- Creation/initialization methods ------------------------------- + + def __init__(self, dist): + """Create and initialize a new Command object. Most importantly, + invokes the 'initialize_options()' method, which is the real + initializer and depends on the actual command being + instantiated. + """ + # late import because of mutual dependence between these classes + from distutils.dist import Distribution + + if not isinstance(dist, Distribution): + raise TypeError("dist must be a Distribution instance") + if self.__class__ is Command: + raise RuntimeError("Command is an abstract class") + + self.distribution = dist + self.initialize_options() + + # Per-command versions of the global flags, so that the user can + # customize Distutils' behaviour command-by-command and let some + # commands fall back on the Distribution's behaviour. None means + # "not defined, check self.distribution's copy", while 0 or 1 mean + # false and true (duh). Note that this means figuring out the real + # value of each flag is a touch complicated -- hence "self._dry_run" + # will be handled by __getattr__, below. + # XXX This needs to be fixed. + self._dry_run = None + + # verbose is largely ignored, but needs to be set for + # backwards compatibility (I think)? + self.verbose = dist.verbose + + # Some commands define a 'self.force' option to ignore file + # timestamps, but methods defined *here* assume that + # 'self.force' exists for all commands. So define it here + # just to be safe. + self.force = None + + # The 'help' flag is just used for command-line parsing, so + # none of that complicated bureaucracy is needed. + self.help = 0 + + # 'finalized' records whether or not 'finalize_options()' has been + # called. 'finalize_options()' itself should not pay attention to + # this flag: it is the business of 'ensure_finalized()', which + # always calls 'finalize_options()', to respect/update it. + self.finalized = 0 + + # XXX A more explicit way to customize dry_run would be better. + def __getattr__(self, attr): + if attr == 'dry_run': + myval = getattr(self, "_" + attr) + if myval is None: + return getattr(self.distribution, attr) + else: + return myval + else: + raise AttributeError(attr) + + def ensure_finalized(self): + if not self.finalized: + self.finalize_options() + self.finalized = 1 + + # Subclasses must define: + # initialize_options() + # provide default values for all options; may be customized by + # setup script, by options from config file(s), or by command-line + # options + # finalize_options() + # decide on the final values for all options; this is called + # after all possible intervention from the outside world + # (command-line, option file, etc.) has been processed + # run() + # run the command: do whatever it is we're here to do, + # controlled by the command's various option values + + def initialize_options(self): + """Set default values for all the options that this command + supports. Note that these defaults may be overridden by other + commands, by the setup script, by config files, or by the + command-line. Thus, this is not the place to code dependencies + between options; generally, 'initialize_options()' implementations + are just a bunch of "self.foo = None" assignments. + + This method must be implemented by all command classes. + """ + raise RuntimeError("abstract method -- subclass %s must override" + % self.__class__) + + def finalize_options(self): + """Set final values for all the options that this command supports. + This is always called as late as possible, ie. after any option + assignments from the command-line or from other commands have been + done. Thus, this is the place to code option dependencies: if + 'foo' depends on 'bar', then it is safe to set 'foo' from 'bar' as + long as 'foo' still has the same value it was assigned in + 'initialize_options()'. + + This method must be implemented by all command classes. + """ + raise RuntimeError("abstract method -- subclass %s must override" + % self.__class__) + + + def dump_options(self, header=None, indent=""): + from distutils.fancy_getopt import longopt_xlate + if header is None: + header = "command options for '%s':" % self.get_command_name() + self.announce(indent + header, level=log.INFO) + indent = indent + " " + for (option, _, _) in self.user_options: + option = option.translate(longopt_xlate) + if option[-1] == "=": + option = option[:-1] + value = getattr(self, option) + self.announce(indent + "%s = %s" % (option, value), + level=log.INFO) + + def run(self): + """A command's raison d'etre: carry out the action it exists to + perform, controlled by the options initialized in + 'initialize_options()', customized by other commands, the setup + script, the command-line, and config files, and finalized in + 'finalize_options()'. All terminal output and filesystem + interaction should be done by 'run()'. + + This method must be implemented by all command classes. + """ + raise RuntimeError("abstract method -- subclass %s must override" + % self.__class__) + + def announce(self, msg, level=1): + """If the current verbosity level is of greater than or equal to + 'level' print 'msg' to stdout. + """ + log.log(level, msg) + + def debug_print(self, msg): + """Print 'msg' to stdout if the global DEBUG (taken from the + DISTUTILS_DEBUG environment variable) flag is true. + """ + from distutils.debug import DEBUG + if DEBUG: + print(msg) + sys.stdout.flush() + + + # -- Option validation methods ------------------------------------- + # (these are very handy in writing the 'finalize_options()' method) + # + # NB. the general philosophy here is to ensure that a particular option + # value meets certain type and value constraints. If not, we try to + # force it into conformance (eg. if we expect a list but have a string, + # split the string on comma and/or whitespace). If we can't force the + # option into conformance, raise DistutilsOptionError. Thus, command + # classes need do nothing more than (eg.) + # self.ensure_string_list('foo') + # and they can be guaranteed that thereafter, self.foo will be + # a list of strings. + + def _ensure_stringlike(self, option, what, default=None): + val = getattr(self, option) + if val is None: + setattr(self, option, default) + return default + elif not isinstance(val, str): + raise DistutilsOptionError("'%s' must be a %s (got `%s`)" + % (option, what, val)) + return val + + def ensure_string(self, option, default=None): + """Ensure that 'option' is a string; if not defined, set it to + 'default'. + """ + self._ensure_stringlike(option, "string", default) + + def ensure_string_list(self, option): + r"""Ensure that 'option' is a list of strings. If 'option' is + currently a string, we split it either on /,\s*/ or /\s+/, so + "foo bar baz", "foo,bar,baz", and "foo, bar baz" all become + ["foo", "bar", "baz"]. + """ + val = getattr(self, option) + if val is None: + return + elif isinstance(val, str): + setattr(self, option, re.split(r',\s*|\s+', val)) + else: + if isinstance(val, list): + ok = all(isinstance(v, str) for v in val) + else: + ok = False + if not ok: + raise DistutilsOptionError( + "'%s' must be a list of strings (got %r)" + % (option, val)) + + def _ensure_tested_string(self, option, tester, what, error_fmt, + default=None): + val = self._ensure_stringlike(option, what, default) + if val is not None and not tester(val): + raise DistutilsOptionError(("error in '%s' option: " + error_fmt) + % (option, val)) + + def ensure_filename(self, option): + """Ensure that 'option' is the name of an existing file.""" + self._ensure_tested_string(option, os.path.isfile, + "filename", + "'%s' does not exist or is not a file") + + def ensure_dirname(self, option): + self._ensure_tested_string(option, os.path.isdir, + "directory name", + "'%s' does not exist or is not a directory") + + + # -- Convenience methods for commands ------------------------------ + + def get_command_name(self): + if hasattr(self, 'command_name'): + return self.command_name + else: + return self.__class__.__name__ + + def set_undefined_options(self, src_cmd, *option_pairs): + """Set the values of any "undefined" options from corresponding + option values in some other command object. "Undefined" here means + "is None", which is the convention used to indicate that an option + has not been changed between 'initialize_options()' and + 'finalize_options()'. Usually called from 'finalize_options()' for + options that depend on some other command rather than another + option of the same command. 'src_cmd' is the other command from + which option values will be taken (a command object will be created + for it if necessary); the remaining arguments are + '(src_option,dst_option)' tuples which mean "take the value of + 'src_option' in the 'src_cmd' command object, and copy it to + 'dst_option' in the current command object". + """ + # Option_pairs: list of (src_option, dst_option) tuples + src_cmd_obj = self.distribution.get_command_obj(src_cmd) + src_cmd_obj.ensure_finalized() + for (src_option, dst_option) in option_pairs: + if getattr(self, dst_option) is None: + setattr(self, dst_option, getattr(src_cmd_obj, src_option)) + + def get_finalized_command(self, command, create=1): + """Wrapper around Distribution's 'get_command_obj()' method: find + (create if necessary and 'create' is true) the command object for + 'command', call its 'ensure_finalized()' method, and return the + finalized command object. + """ + cmd_obj = self.distribution.get_command_obj(command, create) + cmd_obj.ensure_finalized() + return cmd_obj + + # XXX rename to 'get_reinitialized_command()'? (should do the + # same in dist.py, if so) + def reinitialize_command(self, command, reinit_subcommands=0): + return self.distribution.reinitialize_command(command, + reinit_subcommands) + + def run_command(self, command): + """Run some other command: uses the 'run_command()' method of + Distribution, which creates and finalizes the command object if + necessary and then invokes its 'run()' method. + """ + self.distribution.run_command(command) + + def get_sub_commands(self): + """Determine the sub-commands that are relevant in the current + distribution (ie., that need to be run). This is based on the + 'sub_commands' class attribute: each tuple in that list may include + a method that we call to determine if the subcommand needs to be + run for the current distribution. Return a list of command names. + """ + commands = [] + for (cmd_name, method) in self.sub_commands: + if method is None or method(self): + commands.append(cmd_name) + return commands + + + # -- External world manipulation ----------------------------------- + + def warn(self, msg): + log.warn("warning: %s: %s\n", self.get_command_name(), msg) + + def execute(self, func, args, msg=None, level=1): + util.execute(func, args, msg, dry_run=self.dry_run) + + def mkpath(self, name, mode=0o777): + dir_util.mkpath(name, mode, dry_run=self.dry_run) + + def copy_file(self, infile, outfile, preserve_mode=1, preserve_times=1, + link=None, level=1): + """Copy a file respecting verbose, dry-run and force flags. (The + former two default to whatever is in the Distribution object, and + the latter defaults to false for commands that don't define it.)""" + return file_util.copy_file(infile, outfile, preserve_mode, + preserve_times, not self.force, link, + dry_run=self.dry_run) + + def copy_tree(self, infile, outfile, preserve_mode=1, preserve_times=1, + preserve_symlinks=0, level=1): + """Copy an entire directory tree respecting verbose, dry-run, + and force flags. + """ + return dir_util.copy_tree(infile, outfile, preserve_mode, + preserve_times, preserve_symlinks, + not self.force, dry_run=self.dry_run) + + def move_file (self, src, dst, level=1): + """Move a file respecting dry-run flag.""" + return file_util.move_file(src, dst, dry_run=self.dry_run) + + def spawn(self, cmd, search_path=1, level=1): + """Spawn an external command respecting dry-run flag.""" + from distutils.spawn import spawn + spawn(cmd, search_path, dry_run=self.dry_run) + + def make_archive(self, base_name, format, root_dir=None, base_dir=None, + owner=None, group=None): + return archive_util.make_archive(base_name, format, root_dir, base_dir, + dry_run=self.dry_run, + owner=owner, group=group) + + def make_file(self, infiles, outfile, func, args, + exec_msg=None, skip_msg=None, level=1): + """Special case of 'execute()' for operations that process one or + more input files and generate one output file. Works just like + 'execute()', except the operation is skipped and a different + message printed if 'outfile' already exists and is newer than all + files listed in 'infiles'. If the command defined 'self.force', + and it is true, then the command is unconditionally run -- does no + timestamp checks. + """ + if skip_msg is None: + skip_msg = "skipping %s (inputs unchanged)" % outfile + + # Allow 'infiles' to be a single string + if isinstance(infiles, str): + infiles = (infiles,) + elif not isinstance(infiles, (list, tuple)): + raise TypeError( + "'infiles' must be a string, or a list or tuple of strings") + + if exec_msg is None: + exec_msg = "generating %s from %s" % (outfile, ', '.join(infiles)) + + # If 'outfile' must be regenerated (either because it doesn't + # exist, is out-of-date, or the 'force' flag is true) then + # perform the action that presumably regenerates it + if self.force or dep_util.newer_group(infiles, outfile): + self.execute(func, args, exec_msg, level) + # Otherwise, print the "skip" message + else: + log.debug(skip_msg) diff --git a/venv/Lib/site-packages/setuptools/_distutils/command/__init__.py b/venv/Lib/site-packages/setuptools/_distutils/command/__init__.py new file mode 100644 index 0000000..481eea9 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_distutils/command/__init__.py @@ -0,0 +1,31 @@ +"""distutils.command + +Package containing implementation of all the standard Distutils +commands.""" + +__all__ = ['build', + 'build_py', + 'build_ext', + 'build_clib', + 'build_scripts', + 'clean', + 'install', + 'install_lib', + 'install_headers', + 'install_scripts', + 'install_data', + 'sdist', + 'register', + 'bdist', + 'bdist_dumb', + 'bdist_rpm', + 'bdist_wininst', + 'check', + 'upload', + # These two are reserved for future use: + #'bdist_sdux', + #'bdist_pkgtool', + # Note: + # bdist_packager is not included because it only provides + # an abstract base class + ] diff --git a/venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/__init__.cpython-39.pyc b/venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6b6547253a2212d62607c2ab5ca9f4afd03b78d4 GIT binary patch literal 528 zcmYjO%}N6?5Z<<~*43gQcy&)g4=so{5mD?>L{Kjh2x&5IWAn!*OVuavIlTEwx%w8K zoNQZkAenE5ncWJ=rHtf9< zA$@3qRDR5@*35{axMO_IDk!-%fk`7xRZ8s?Xuvo~YfAfEGNsBegVG1=VYMhH>p{h8 zkRJ~ZVm@u860zSp>fYk^62WVT#S(HQr*W{vp4ZX^A9JpNnYbkl&Q~h#tN=~5d+T5Z zOhE1b66^Neb%kJo#oVVQW50$9J=935O%$!8qR~^Nl~S~J8mY8!kv7M+oX>#I<7VTO zW#V?&ja!ro%PCC&$x-^1)rTl=`~6hcXXMc%Ey9dpo?JOMK^El3a;C@wXh)oMqsBOt z8N_HY15l%rhP^CKgC-tA`{&wsms+i4Tb3=yZCKZiv?(OJX;2hSTsVyz*Jz@+ty`mv41&8eT2bbb z^pGoA#Oe~IK>mipDD2*H>7nSU=l&JE_LO5!1$=RTZ^)Haj!)%+!#6W;-n{SkHk_Y# z8J@4-ey9J>^NjtQCbN%;$!)y(uP|`tGp=zx)_e_LBi2WTZ)mh;#^wY1TCp{kd8)S!Z-S~4y%$l|crPUUDoSks4uZsGkHZ+;&G1k+lb zZcOwGjGI`sCi)8F)(YD;UT7M7vOHlE?MOQ`CdPA{+qA|_D49w-})%a?u13S z^=Uc?aPV00_5B?o;`JYo!`=O#6r-(N6yvN&(>UJ>jwRY^7~WE1 zY-9&jC*Mi;gNCIJ?#=0PW^^=DbG44vdFAMiCeLE+l!Fiw#m#NJ`PUc(LqsrN=bCSD zog3WbmN1XlG8};-fntEW!bkU0;Uv$A_WBfc#2+>44YV+C6kvfMbUZ^ zj)+KBelQIxkCwb5^~9(zxECefP$WVkXt}o?#e%ls=v-`v?>iX8&iNI`|j3rwzapbUqAh$B1QhrD2CT;Beiz*-~Y z914KPCMRkQy&{xKDKnf5#!?~?dcc?9sI-SN9cLgnEI+zS;QvQXQF$bn$x%8KoK0%U zH_NM}%X}sqozi?`5~Q29@|!?rqskhVV7)TRDC_B!m8E&~w9=EJ*Y*wU%S*ThnL{C2 zPu0h)PvDr}+K-YbLB4(qXudJZqn<8Th_l7t-v8{hyXuu&U(3g%ez`crjjK@PRB;wofORz* zTmx(>*ixg-8S;R>SyzVERA&_8RhuF+ps$i*oy&%HG9juYs$yfVo~y+wHq zDv_%+PUkP$t(?kjTPfr!sfbD5=hhBp*u=P>Yld1B&YaPvbWg9N)uC6U%uH$FE(qFlztCh>OI$tMs%7LhEQ1Md^^e+I^ zsgd!~seO2;mlx5i(Og$Onzq8I8+*u}xG=SGaHlb~35U_AhJNDSz~uhJo+zSs{DX2Ss}AJyT$Jn~+E6%Ef9S1V%U4ytlhmp9y2^-h4zQ#~ zM*b8-wRCK=&sEb{ThfwYG8C180$eRgF%y?fgH$ahY2yZs(c}Wr?9s4>!EZknA`7Tl zsOIE2nYv%kR(?=94WV3}tF#C!Bd!vU-^$1R0JGQq!~mT=(9S7|Go2bRUAqWJSTfGS zImj_O2Ao85%q6%@S!dG?oa!xBPN0YfLFER)DCOf=0PY0AlW`c6BV#tlMLv*`QbZj? z9V)C-x2zWW=odwpOczw!SE&MdymSk!$@giX_OI6Tj|lo14Zon_#QhaS$x`)X7Xhe$ zQI2lvI^?U}TQ@MN-~X6PwqYu#H*M2I0KBqIhrTC29q@ncd8h4MR#bcKsucu09Rz{A zfg7qWrHknwD=8$U)oSr%QBW}FvuK2@^q~Y+RNo{-<$PEx_UBZaa&j`$a#Y~LE}j1Y D38@Y+ literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/bdist_dumb.cpython-39.pyc b/venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/bdist_dumb.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..533cea4d969ca44560277bbd5e9285a4ea71f774 GIT binary patch literal 3641 zcmbVP&2QYs73bG-x!l!9*0%f=$E;!5+QL%f6h#5I2^`o#&<`j9lA`E#3xc~dyQ0J; z*%{K3h*b|&4!s!YAJBu;Td%qFf8n*Kpx2%PBq zNN!D%`8S~x@i~t(>18|Id)`d;9$w6P=+!H|jfvnv#=XG1N6YVd z<2;Nqm*k0Xj9rr0+uZcRExz^0+s$R>1+f>1$xir!ds*U*xtGUjFxle_4CBJPp9($= z54=RU_xS;z_*Hwb^%cydZ4dOa{j5?OY;VRhKaGNHnuz(pD7%8slNa321n1=nk7X{n zFE}P(Kg`#E4ANJN4zryk_Fr%zp(A?DD49)Yi_5M?;-{RgI&FWn?>%c6k6`L#+@0U6&9%p=>CL$1rm?-!pOTfV}o)Q+uGv(0B zG76V$w;2a>4hd=Ti^h~5b&-Ggd<@Tou{Yx}7w|OmreVZsSb7_bPlG(lo_OnW0Daoz zg&>2dY4Jhh&_nM=_Z}2)c1-{sih8(N}jW1 zGmK>xMC4gOjQkB)C4i6@Of$gfd(YgU5Bhe<7Rr2rLbV{aHXGDU^9*N=gQ&vvE5?^F z2~>3DUYKqYIFuTRAY7@Ynthk1xy-c(A+jq4&pg_f2vk z5b+-7i$9UL8BCc%+^qQUV`6`pI3)%0#1gD4R*0;Elr81_(k$R;qim=c{p&L%oW zn;-E8$}<%C1cYe|&95lJ5Ih1A)Kt8sXiN3jif=3GFb%gmI`vdf}BIx@BxTYIoVgfsnu7;#wo}$$Q+jB(ez)M@UX?#;j<^B-@%M>6vS~L zM<1r?^B@aGzfC4VH2NH99;Luclk_&>9Ug5y&V$|kpJwxshG?6#r9-(2SwTb0L(($h2?Wi zJXmNaxS&q;UE@g4%w6lGwZOG?YLIU*3%18BR`kKQG49+XPuaiMV$agD&f!?s=)(ES%BAx|0NHV&i+_#4C%0sl7fLz3=l@@rUG3S`c2_~A!FB%)k<-gx#?K#(R?{ny}qpKd|yiT!GyLbJQ1 z**X#Locst}x!P#gOnx7|@*aq$yLwMwHC)}$```?G)|qkUTDIbiZ;IQO0P(t>1zP4p_br-*T4R8S-^%QhHnVB$)SwlBk#VZS&298K zC!JH0;!ces&cUkWxPN?9!MDV5Sp={Up)mJJJ;SnM@ z1)(qVag8gfa#XQePo%^Tbg#>zwJx_%eKrXQ`tx89SDp7gaHni9xJTH;ON%MwR}J*C za5}{(68*-yd{kZ9xPX#GB|32jE*9^Alx7eg3VQn>yS14(^hF*IJQW*wV&(C9C|s>h zQ757LAXV^KB)4?-0})di6_ig(D~zW}*`v(XJP)fk+%%6OijpcIACM*wiEI#20jq9~ zm7PHP{2=q^3Cklc%U*3QUqxeMJM|=_9`Q)+DtIbHi`X8S&#$jn6|EP?7KHIqyE`A0wXjcLGF8JYUElVjtCm8mt2TG$DnPJ##W>rRMo>0S1dRV_e zUyp1PX8r^l$ZZhH=B}}$ipw(quPDH3~8eu}KvPTbw zCiRpnW87Ojh?@>Ez#KuzNNf@Lh=}(pp)975My~@&-h!q$j8&&A!&D!7RQ+G;mP03{ zb99}4h0&F=?fWd5_`V?EApJJ!6@PF97j&Cl?xg=dmHz#UnSiLT29%o>R#q=YIpu9x yUb*OzhjNm{({NUyMm;6fpDG1(rP!O!S~|b1p!)&k0ZE{?YzMAEu7-0_8~+EjP$?_` literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/bdist_msi.cpython-39.pyc b/venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/bdist_msi.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3f892e2d9b2f5a55abab1db5ffbeb51a53efa556 GIT binary patch literal 19829 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 a?8Sdaq{1yD^hpX1EQcBn_E^01^#29zk`~4Q literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/bdist_rpm.cpython-39.pyc b/venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/bdist_rpm.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b5b313b9933ff45e3f6801068f62e1719ec95b20 GIT binary patch literal 12278 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�ygiZ*)eeiR1OGRO?#RYdUh`WSEfEj&& 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/build.cpython-39.pyc b/venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/build.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..59650a33a1ae726b578ee1bfd3134368902c5eaf GIT binary patch literal 3930 zcmbVP&2QYs73YxL757tXS(dHDj+wNUyg*lJ6Eq2uI7n;v3kX!8acgv;g5~bauBdQH zW;l$qgaQ;*3iQyTMuFa~+;Zu$e@YL$_E6+sC{U=sH(ah(w$Ouj!8c!T-kW(JznSqn zou+}`A8+rB{=8)v|Dwj~&qm`zeCb0FZVV01xEZn`)1^5yQCgujvxhdLF*~fy>chIO z*TS`#Gjvd|^R+LHVdEzTcX;DVgExeIVhx+z{MhI>^B?jcRhbIHbZ;EbW`4x?Mp+Q@ zX7gvWBos3dsnk`6!hKNjxx1QS*RA-!!Rn0tJ}cJlml9CjT(bW>Q9&I2NXl5EzdaSo zOF~~wVmTYr#OlXTG4b8Um%EZN$Z#QHTWy6Iv3*uyH4AQUp~ zo5j_Y%~bue4sKbaDTZ`V{D@((_W$9{P5P|T8pBuEBX zl=$OM1Rp#;6e1jaFY}Kczo}*isZd#>;y6qXyrsT_g)t7aZT6D6R@;KQl)PxLHq$*9 zwoC(Ud>`UVzXA~kd~1+jhZZ-v#cf_A|B>f-6Mi$cjETityv;kj%h#vvVU73rm8m(b z^9_ELZ;G{vJ!M0OU*lWkb$*@SK-uKm{3Vnv{xZLbvdwStS5S8NZSJD%@>lt5DA)P7 zM0;ZLZ;KA-9nl5d5$h9kY7cw-D$KuI)btkf*L2~E&xD+-!yuZvkq}&PSH*4+rOFS( zzLmE$*I?wQ;$FcSxKO-k3`CFCkT;wDUI|4A)}#DZl+8x4LOgM+{)N(`cm!`1H7-Wkv|!Wxy@e!Ke6B>4k~dwz zk_#(gbAd?R$FQiY`KJ_jK}2BUlix`Y8e>tgN&W`af>Bu6V|6q2z-{{3o`lOUof11l<|42qSIi4>sN71nfD+Y#B{mp!Dj+yKct zhayY{m3j8_8zBPK^*{52kdzRNmH;*;T&sQ;;P4~#a&~NZfIv`S1gNR0rKzoHP1Cxj zYnnRT1ZP9no0_&N5T&C>BWb@~lp*d>ZWbNA2X7Im%Vrs-MWY;rFRDotbrshlI18uR zQ_-MM^C-;DEmAbkOCwqjbdcQ!m(YG3CQ!#_MmR2fU7!nLtwGX%p=hUppngIHpopSHRRuE4(4_unvKuvpzLX`f38SzmQs2cze3|rm^4>7 z8msHyDm7jK@5X|62jd%AQQckK^(g+Cpd1LQRI=I94?(lEO#YGR74i)1>l43HB zGpKe3$-D#{i$d9^AkI6B@GYn2x2ni=anHy??v4a-NGJVN$o{sx3E7fP_ri?R!q!1< zQPWE2Y0<{PNZ{oWJQZt)e(EbFCEaWao6w@LkK!Pb*GS5BA{5a@d-WJA)-lZk4tleg zXQ4>tHZi_LJT_ z^4Xm0X{=kxxSwKD`T)dWP1dY6naRvE+rEjKgKvX+S^cbDr?P1}_M&aJ(e9nqtxeW5 zyO`BuU6yZ^+4-!J=W>&5t8`ireQ;~6gjiBf+BXe==Q4qfGit=?vN33hwvzp%6m&`dCj@W+Bq zu@Lz-n$Wa|qUe$H2uGLRyN&K=Y%SkM-=FZM6spG3IM2>~p%v)x8GFl*YFEqWwj57A;!%B9kxG{Q>m;ZAJH$^ZhQ*FWu!O z^XiZr6G|-3J}gjYVE;yiYSfBs@T?g&Tvu(g6!fv}k8|d{k#y zu|C36LikbDp`Qswo3L%!^(vMt-y-rJ5egYeZYvE;8!FnXfxi-CI>_lDl@zITD@lJ0 z;+VE&mOowE$W8mqJTt3a)BLx6%du?TYuB8f^N!PYEd93^C+>f>%zmp_^E@7pJx}&Y z(Jn~QT|SNQu9QNSKz!Z_(1~R#HD0dp(o0lZseHESOUikkE;my+@0W=90VQKfk0{&j L;gN;E<<$NMjhHPC literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/build_clib.cpython-39.pyc b/venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/build_clib.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..dd4f9bcc02ac70a5932dbf9c7e098afb64c5164c GIT binary patch literal 4853 zcmb7I&2uA16`ya7#3Q?|bx-&Ey{}fXxfxlw z{`lOByB3bKCwh3-3zx93FiZ=y)pfVNVS=mG}8zDVl+x}anPHjndtVj zv=>D`9gQ+&&jNjeQw#-%(_4;EU3pl zR3!R$yWG;p#lyv%y6u!VRuor%OEn;^0vckeCLUj=ci%Yrm6l2$C3&9cqj$&Sdx=So zeqQvG?C8E6jgQ9Zcz=?Qlm5q2>_0q~GTVQ3lAJvJt{EL^X(nS+6q!EiF1~j(SNG8p zf`joHfBPHwrY5to?3T@(wS7~^!l(v#krs@}>NvvgxI;@gf3-WFaD_K?I==8lAR00l zctg7bBN9!RQ79s@LFOb{ViV6uY>8`lZisF11fDH%UEIKPQ#>hd;<+UP=y9ivmTR5f zsZ3+E)yElD7q)PTpq0W{@cXdWnEC(8> z8UxLAZ*AasVq)ql$V%t7+dJDIE7)b<=(bz>LiQ%Z(jHEqpTitKOwDo3>|vS@VakI- zjS{k5lE+J5miA!!8c}I4tLK%cQekg2-EC#JT0>UyHeFqz$~w)d1}%mBR4O`q<8&2@bz^xmL1rEiyuAt zH~r?)_6{B&`It^ZOu~WT7{tuF*e4F@2b7~;fs9MkBb)o6sfne2 z!cyM&-jFou86WSS2`(HZh`MZ;@TB>O^ay#lNaL{dd7W)X-N1)gku^;W&`%Mc8qkbB zHK54|xM@e_O@xdtYZST_wR+0dYJ^o!VgO?0vFv}`okwUq5rS`0N0jO`he75rV;9WQ z*W)ZTrBmp#F;2{}mSgoaeUn1m3NG8ga}AYy=-1Dpv4X&M>fgV;Mg(M9PGoN(OiiCz z!RP7>Yv}lxh;BybZy=yaOGl(X4&e64IVTLD)e}O*!|ejc{I<1 zKfoe3!LjI#(e>v3VVA93F7rs+WjM=*P-k5=$tw`I7#~G;s9vOoao;71k){aFNOiUe z>{X{yl*|x>*|WN%q^}A^Iia&vn?%JduT?r<_-5Nzw`f}WUg_n@2!45*WD`89S*}3s zVznPaRzHu1e9m)Q)Y{%xp&K!>k+WrQ+Yx?S&U9-9V+`$6_N}iqSpN*J0fffBaP)P9 z%yeP@-k#Y|^Yq+7k7Hc)yl%XibAhb=v8!H(6o7@41HjyK4^po2A@x3bJn9kt%ssVq zZi17B@G<6hL=g{^BZ8SD8c$n07Rh3?XF`nLK~G4W2Rot(7mbpS5HsJ)^#qZd3mOW_ z9BYfgywagWhB61LOT|GH#q;Z}wvWmolX@>kNx|#InwhhhDgpa;?fwM$UX=i0 zQG)_8x^LPmTX;W7^-2Nw0aYgNDcDz>4mdj@QXplLZn(~46`*=ML3T8KNhbZ{SXPB<3@lb>;Gs!8*T?j5 zfZStNg?TVfM@8vlL;0&zol@Ga0Oyi6CXKbfwC_yc>?L9j{~2@R-52!k8}TT?YheIu zZW2trEIbfE6P2KN(Oh3nf1xFW#Q(c0f(XfvDwo^rUtEf`50Qpr=%w^XS>=s;Xt}~) zVpjURVN}L4SKorH`Zf)4v9Qu(RvBPuom1Sm5GbzCqRNu$+S2NrbLj>Gam(hQLly0H1 zP;z*VSEaOPSHj(6L)Lb*7W_JxhAIy1!=`o5_e8<(?fIVEON7KnHZl&^8TxJGB3z-q z7&r)7KQn=FW=<8zX7*)co{@HV|L$Sg(8UDhss0j)cFor3F{h3PY{Komcy}(p8`myK z(F^B6KBd*XrCV0wT-UNb+aVi9rF9poV9Qi@uu=6YHLsv411|Q(JPDOeDvNozdYxn# z393-9!m&-dtv=bMG5T`|X-b!L{vj-)%KRMXD;T4HrP#PSdMzta`lXvq?K2RZgZ{LD z0VT%@412}~49HCk1G3W+2II_-gOHW{%Rsm=NE8t>7iFb~@yJV{d{9)LG)}@9l@iUF zKcn|Z1fTln4er^PHBf?BCoSeTKJ`#&RHb8hs8~5~Vv*CEY;_4j?V?NiE@Q`cU9?LL?!8QCJ>k6PPiGm*wNQy(cyM@D|{;aPS^^sRY!)6veE5|qTlUSF@0QBqOH zEVq|TNjY4v{+*%EG_uhk9V!a7Wpg3RpjZEK5Rm_CwPpBLrM$Q4c&W*XyzLM$(cN-F F|Gx_M1g8K1 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/build_ext.cpython-39.pyc b/venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/build_ext.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8e0e039416d3d6947a6fa32dd8d2ee3b3d6b6fca GIT binary patch literal 16218 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/build_scripts.cpython-39.pyc b/venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/build_scripts.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b65c624c48234596e6b4c5e77961952125e71a12 GIT binary patch literal 4013 zcma)9&2!tv6$cg|2tp+F;Sbqz;y|($k*=lM?ex1%omfulX)AYZ=ZlexLfoYU2?XHX zWn?knCCZ_<>e%Ut?9Kl}k3DyK-fK^}bUKq;XBzjt1*s1^(XsFRLs7Xm|woLsdEdp;Vwz_u9HgV35OI@es zXu1@ayKc+Xv=djlUdz*TIiBiPTUAZFz+Y?CG)>}qtIo)9npQ?;Yvw(JdUWawgHAE` z&}z+6^2lgb`wwX(WKTx1SZk-{FmUHvC%YD`O)Lx*ALe30a+0TqMat4XdB1x7ApZ+O4vT*KvZG&Q^sYGg>nb_ zR-A5&*Fe#4uPv_K$PVOAntXC=^+#(@ZZtmeD^J#LG=F}*jVqo05$N23N4yISGXPfu zF>P7f1|@$sTQ;?}%~pxpwDg71a;QVg@GeuAR^aUx2(>D-N^8*fXdN(`R<$#Z_8UvO zzvPc0@*C|mJMaNIzY{&{W&X8AKaLXCY+6mL?`h^$8u6bgllHFy!P+wA2fj@Gi6*U~ z2_sEQl{zVJGi7%Aw~>mr;samn@EHIEKt##5--x!8lrvZ`X1j z47Xwi3$p$Vk+F8vIRMrqjC~56K*%Uf{3wx(XPiOnBkUZ5w{1c*`5}#%-i1djK|_t) z2#OZ41)AvA(ydL6N5*q=qghgw0y1z`mB%n??aDhbPq}GNq66Z&scgaG&U1sGheiG! z-~I9C`+{+?874_6Hs8*&^-zYJze?L-y!n`Qv&}5ZR(nYnw)Yra-QQs>UcKE5clW<5 zyPJZ^UMABt7MsCwcyErwbF;8)Y}8tIpyr|^l2I5(eHNq{A|tM%zxpVf&iLOiHeqru z)?O8Q1vv+_Xyi~`ZVdHlrxvwGaJqA2*W4uqf)Hh;4OP;XH3@fto!6lO8ja8m&@)J5 z15t7ToD6yiWw5P`PV81y^p{6laH7+MPouybHVA9cTmVYV=wLYI@G^{wDl`VTOYr|6 z+wNaIi`C0QuQ-h1q8&!h!9fTIUIVge{tr{O!4Z-6Am#%d3^zeQV9*)n%Lcs6`icR^ zv3e22(E#CLOak`i$beh%*dU?}!doXhm~81cB4zPj@@=#TT|#hdvp;(l7T`Ez2m)S# zM7xs{g=2~bnRDkZ>2OylW7zb(#l{ew~q+F4t8ClXeD}X!Rq9c2h&GHoR^n( z7miHP0FEnzYSJitmzRgH(W#M1tD35fO#QBp%nkty$e=3i;p=%7*00j(ygF~>Q}YI$ znKuTtem$=ZuhLnx6TDvn@838w5B^m6FMT>UT+Bh^q4~K92#{MwA(5BI64%EPe>;{q zhY~PPPGkV#5&A2*~~=H`k3PzZ*;gdVnUE8t;qw zG;${EfKdZzQ#LOfbpDPpn8|18rFRN?HlNLB_AHQUX{pQkbUu^M;ysT z^!)MfH#(nBbbv5c7Vjs~Gk-rk@Ee_o3#oG`NXzyP6aI=G3ox$+oUPnERu!=|ACe!3 z@?<}fJO0w~CVU!4esVEt1~eR#476_czw>KkR#jqss!u z${*Z&_~`zF4Q1W?=$^h$uPuIsD!qOQ((dXH`)iNEJF&yILM$jgTjYZ#8idwU)=nvw z5PpZJUBBRe`~T)g*or{#Spu5S*v4lA@P2{j+L}6hA#bObUuon|yZG0ApkLTu+qP%UI4BSN zz)fC|7v4#q*k426u7b`r(C>{U>!hkR)yW*J>%oiz+Gj|A;cWS!cVK*NZZxNq8w9u$ zL7==K0B?IS($ye%+6&|H%oLRI`uhy3JXP&MseD`kPH#cs%fe(bz_AqK3)o!2=5=fk zuu~xF>JSSplLe@cmtT=Mq~Uvl+{5~IWD-1 z5U(Hi;rkLe@e5eZoeWZz1^D^N@ieMa+Q)TX@|G9Jg(Zfs?;$dE~$OPeqde literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/check.cpython-39.pyc b/venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/check.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3758e601c35813e2b8a6d0d3992e6c89bf0b7683 GIT binary patch literal 4995 zcmbtYUvt~W5x)aK5F#mxwiP8#odj`{*v#0f)3iy(lSz}2oj6mEoUxp^!Kj0Qct;U3 z2rze`ZJ|^j>P*w=OgjAleULhR@wez>KLcL-0{bu|5|y;eNXi*rG1HZ&~1c#~c>aaJWX< z-iQ+%V7BPG;uu}lBHfGQvaaMPiF&d}S2TNwUO=%?^m$a1dhsOIK%O)stll3quHD zBJazjYz(4gM!Py!G8&dOA-Bfcr6YoO(VVe$!K&f%A?JjSuaX9@5te3a}pkcMdpbxwT_YtZhEA|ITkS^syah!q37;{$@>_fAGI>+^MzRwaQv0 zIVay8$!<-xFk$INqY*Sn)#;Q*9_3$T|&3|3GvitonCJcCql`zbniWg z)V5YrZw*6VpqUoO2Q1m%e0_G4hVWH-R zwoGjc8*+9EA1JGRA^Xud$^H9LGM3thwWwL1RtA_r?^B#z zKjxK%9Jhe-G$C0WC2=9c>5NxsXQW{aNI<{hr3xvYWqsykv<-7ILUn>r)dW##HqASy z;8 zy_StFr0CnJq0JTi5&r`r zXieQfT^H6pN8LcXP3^+LIcvqK+vBt{!9Ub_QNFS4Eq2>hur`mo(pN+Ct1M#Z@= z5*cY2WTuqt<^C@G+KhR1z3UmxF5Bijnb8^8=q{1*KVzSdFS(+8)bEO;Ys5( z_MmK>xDxF1bi!8S^j9Rt)2NsYIED^7yn)(tI=on@gbJ=>G9{stCo(eqGYCkB?eIOm z&GukY*Vu2*@7Xzddi#;3F6MSc>CVL3cP2LZsc%55n~-@;Si;_SC)NR9Vbn9>J9Q;c zd-{*2-}trkJX#ji1a)KDUL)?bVR&4kMIATdMF{HH^;83-=w6^^5x_*rZ^kiT%a^lo z4BB`IZU&tYaR7{PKMjMMKAzjNQTxMTT++MC(i~4_E;swt5e1!$s9`Ks{f`gtV@2eKI56|0t8>Ec6`B~N$k?BsoEbp z2H7|f{+2vs@evvoU;UT)jt+Qi&ZFl4G4H+S%q!tIAiw`l(9b!@dbe4&D8N(k77RQ~ zD?6lpW)|=YDNZ(N1E+W(qvFmafR}s>T zAtgg9HeS433ag_lorfmcvB7383O=3UztS@c>$k9OV21ow|qQcQpL-0K-w;nN|sJ-Ll7V{O$s`mdSc?2w*}7$PrOK_#)1*h!urRE`!eAkfw!#Oo$Ol1tBuDVReTnR+Cw0(P z{odTS$siQve2Tnm(4Gn;1cV?>H75z$Rcbm*RfBWKzr$mhYn7gP6k*Um3qcb{mEklm zu8rsqfwKJxFo+OJUZ*JpvC9CkYbJS=qPMa_+ zXwPE8RTCL1Qs`j$u(1+9!eJ-|sbXMmnEq5UN@;GrQl|H4<%R1Hd(x<>+0pZkQ+gj( diSb92Ea;a|IZg{s!Lm@(&+4>2-m)9ke*l~CIx_$O literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/clean.cpython-39.pyc b/venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/clean.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..09c1b9d76b4b264e4b1ac77faeb98bb03d2f5977 GIT binary patch literal 2135 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 E{}FCy7XSbN literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/install_egg_info.cpython-39.pyc b/venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/install_egg_info.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..93115c25931e957c7b0ea694008192bb9152f421 GIT binary patch literal 3297 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/install_scripts.cpython-39.pyc b/venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/install_scripts.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..196d8e094a26a99134766985e9a8e0ba01b68f24 GIT binary patch literal 2186 zcmZ`)-EZ7P5Z|?ZXP@tq3uytBB5IJ*#1e^w-~sWaK!PYz2}mt3r$d%=yLWNoukNl% zW2HPmANVs8-tsT)8{&z7p%Q|bJv&LS!PbsvXLojIe)HjYX~`$>{C@BL{+})(f8pf% zk$dPx?+h`l}b{%H7T+z&e>LyOBJVSBqt&%mGu2@vohrw&y@_+0S|UtjbMFY>w3_f z@qREZM9{1z`ON>}L>&})&>Xq-H#k7{LaN=J`K7?xX)!~|qsP&A-|v1s!7bMx3ntqz zqmgjs*kk;81}%&bv|by)W~8G*OVgRjea%!jYX`fLE-9$R9|@b%dc z5LnT}1t;pYM$lRtY&6z`O9cQRjuXkl&|F{g6a!j9wp_bxoWSzjS~~f`Q1|SQVI`X6_|h%3Z#9IN91>4$hUzoa!Mk| zGN2Fvpq8OFBY>v0Cr}}DbiYLv95YAjp1CZ7xi;2BW`04nBY8T#AYuhHU*tQVjDM6| z$Z?$Ku^fL{mbw>-kEdb_} zoS9-hx9FUQRK+wscc4fSICoEX3?8ASm*zk z6w&K|LsaFAPm`Rp)-kb+TM*_sc?~$d0$W~k|6Pzuyp+%ZxNqV6Pu=EP+ZDDJ)m{R? z2JK4#euc>?IV5rgV1QnAP7Mea$ZQzSIdD-&bq`%;9a-WR*yWv*UGmd|XOLxwJ@HWa zXMJX$QiSixN2+@^0G_I)JA^r35!Trz&n&a2drD8ObLfJwXW8&Zqk&l521|6OEM)Su zzBM_B^BERNRxlnE(_l>|8Dwwr?~suC&JD|0lWRpdG$`x7sPd@EEZv(FLj=O$hz zKH4iPWhzixh15>Fb3M!JdY(7*Y_l5n zv>QdNm_(7l_N$jK+Zz0^1s4dd?p+E^DhaG%lSA`vaaHn{S8MOHxwBtj)Fp!KxE@qI Gy!L;Xyh8{8 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/py37compat.cpython-39.pyc b/venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/py37compat.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..89360c4e45c3d4bb13192359f0d80e29c4af488f GIT binary patch literal 1029 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/_distutils/command/bdist.py b/venv/Lib/site-packages/setuptools/_distutils/command/bdist.py new file mode 100644 index 0000000..014871d --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_distutils/command/bdist.py @@ -0,0 +1,143 @@ +"""distutils.command.bdist + +Implements the Distutils 'bdist' command (create a built [binary] +distribution).""" + +import os +from distutils.core import Command +from distutils.errors import * +from distutils.util import get_platform + + +def show_formats(): + """Print list of available formats (arguments to "--format" option). + """ + from distutils.fancy_getopt import FancyGetopt + formats = [] + for format in bdist.format_commands: + formats.append(("formats=" + format, None, + bdist.format_command[format][1])) + pretty_printer = FancyGetopt(formats) + pretty_printer.print_help("List of available distribution formats:") + + +class bdist(Command): + + description = "create a built (binary) distribution" + + user_options = [('bdist-base=', 'b', + "temporary directory for creating built distributions"), + ('plat-name=', 'p', + "platform name to embed in generated filenames " + "(default: %s)" % get_platform()), + ('formats=', None, + "formats for distribution (comma-separated list)"), + ('dist-dir=', 'd', + "directory to put final built distributions in " + "[default: dist]"), + ('skip-build', None, + "skip rebuilding everything (for testing/debugging)"), + ('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]"), + ] + + boolean_options = ['skip-build'] + + help_options = [ + ('help-formats', None, + "lists available distribution formats", show_formats), + ] + + # The following commands do not take a format option from bdist + no_format_option = ('bdist_rpm',) + + # This won't do in reality: will need to distinguish RPM-ish Linux, + # Debian-ish Linux, Solaris, FreeBSD, ..., Windows, Mac OS. + default_format = {'posix': 'gztar', + 'nt': 'zip'} + + # Establish the preferred order (for the --help-formats option). + format_commands = ['rpm', 'gztar', 'bztar', 'xztar', 'ztar', 'tar', + 'wininst', 'zip', 'msi'] + + # And the real information. + format_command = {'rpm': ('bdist_rpm', "RPM distribution"), + 'gztar': ('bdist_dumb', "gzip'ed tar file"), + 'bztar': ('bdist_dumb', "bzip2'ed tar file"), + 'xztar': ('bdist_dumb', "xz'ed tar file"), + 'ztar': ('bdist_dumb', "compressed tar file"), + 'tar': ('bdist_dumb', "tar file"), + 'wininst': ('bdist_wininst', + "Windows executable installer"), + 'zip': ('bdist_dumb', "ZIP file"), + 'msi': ('bdist_msi', "Microsoft Installer") + } + + + def initialize_options(self): + self.bdist_base = None + self.plat_name = None + self.formats = None + self.dist_dir = None + self.skip_build = 0 + self.group = None + self.owner = None + + def finalize_options(self): + # have to finalize 'plat_name' before 'bdist_base' + if self.plat_name is None: + if self.skip_build: + self.plat_name = get_platform() + else: + self.plat_name = self.get_finalized_command('build').plat_name + + # 'bdist_base' -- parent of per-built-distribution-format + # temporary directories (eg. we'll probably have + # "build/bdist./dumb", "build/bdist./rpm", etc.) + if self.bdist_base is None: + build_base = self.get_finalized_command('build').build_base + self.bdist_base = os.path.join(build_base, + 'bdist.' + self.plat_name) + + self.ensure_string_list('formats') + if self.formats is None: + try: + self.formats = [self.default_format[os.name]] + except KeyError: + raise DistutilsPlatformError( + "don't know how to create built distributions " + "on platform %s" % os.name) + + if self.dist_dir is None: + self.dist_dir = "dist" + + def run(self): + # Figure out which sub-commands we need to run. + commands = [] + for format in self.formats: + try: + commands.append(self.format_command[format][0]) + except KeyError: + raise DistutilsOptionError("invalid format '%s'" % format) + + # Reinitialize and run each command. + for i in range(len(self.formats)): + cmd_name = commands[i] + sub_cmd = self.reinitialize_command(cmd_name) + if cmd_name not in self.no_format_option: + sub_cmd.format = self.formats[i] + + # passing the owner and group names for tar archiving + if cmd_name == 'bdist_dumb': + sub_cmd.owner = self.owner + sub_cmd.group = self.group + + # If we're going to need to run this command again, tell it to + # keep its temporary files around so subsequent runs go faster. + if cmd_name in commands[i+1:]: + sub_cmd.keep_temp = 1 + self.run_command(cmd_name) diff --git a/venv/Lib/site-packages/setuptools/_distutils/command/bdist_dumb.py b/venv/Lib/site-packages/setuptools/_distutils/command/bdist_dumb.py new file mode 100644 index 0000000..f0d6b5b --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_distutils/command/bdist_dumb.py @@ -0,0 +1,123 @@ +"""distutils.command.bdist_dumb + +Implements the Distutils 'bdist_dumb' command (create a "dumb" built +distribution -- i.e., just an archive to be unpacked under $prefix or +$exec_prefix).""" + +import os +from distutils.core import Command +from distutils.util import get_platform +from distutils.dir_util import remove_tree, ensure_relative +from distutils.errors import * +from distutils.sysconfig import get_python_version +from distutils import log + +class bdist_dumb(Command): + + description = "create a \"dumb\" built distribution" + + user_options = [('bdist-dir=', 'd', + "temporary directory for creating the distribution"), + ('plat-name=', 'p', + "platform name to embed in generated filenames " + "(default: %s)" % get_platform()), + ('format=', 'f', + "archive format to create (tar, gztar, bztar, xztar, " + "ztar, zip)"), + ('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]"), + ] + + boolean_options = ['keep-temp', 'skip-build', 'relative'] + + default_format = { 'posix': 'gztar', + 'nt': 'zip' } + + def initialize_options(self): + self.bdist_dir = None + self.plat_name = None + self.format = None + self.keep_temp = 0 + self.dist_dir = None + self.skip_build = None + self.relative = 0 + self.owner = None + self.group = None + + 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, 'dumb') + + if self.format is None: + try: + self.format = self.default_format[os.name] + except KeyError: + raise DistutilsPlatformError( + "don't know how to create dumb built distributions " + "on platform %s" % os.name) + + self.set_undefined_options('bdist', + ('dist_dir', 'dist_dir'), + ('plat_name', 'plat_name'), + ('skip_build', 'skip_build')) + + def run(self): + if not self.skip_build: + self.run_command('build') + + install = self.reinitialize_command('install', reinit_subcommands=1) + install.root = self.bdist_dir + install.skip_build = self.skip_build + install.warn_dir = 0 + + log.info("installing to %s", self.bdist_dir) + self.run_command('install') + + # And make an archive relative to the root of the + # pseudo-installation tree. + archive_basename = "%s.%s" % (self.distribution.get_fullname(), + self.plat_name) + + pseudoinstall_root = os.path.join(self.dist_dir, archive_basename) + if not self.relative: + archive_root = self.bdist_dir + else: + if (self.distribution.has_ext_modules() and + (install.install_base != install.install_platbase)): + raise DistutilsPlatformError( + "can't make a dumb built distribution where " + "base and platbase are different (%s, %s)" + % (repr(install.install_base), + repr(install.install_platbase))) + else: + archive_root = os.path.join(self.bdist_dir, + ensure_relative(install.install_base)) + + # Make the archive + filename = self.make_archive(pseudoinstall_root, + self.format, root_dir=archive_root, + owner=self.owner, group=self.group) + if self.distribution.has_ext_modules(): + pyversion = get_python_version() + else: + pyversion = 'any' + self.distribution.dist_files.append(('bdist_dumb', pyversion, + filename)) + + if not self.keep_temp: + remove_tree(self.bdist_dir, dry_run=self.dry_run) diff --git a/venv/Lib/site-packages/setuptools/_distutils/command/bdist_msi.py b/venv/Lib/site-packages/setuptools/_distutils/command/bdist_msi.py new file mode 100644 index 0000000..1525953 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_distutils/command/bdist_msi.py @@ -0,0 +1,749 @@ +# Copyright (C) 2005, 2006 Martin von Löwis +# Licensed to PSF under a Contributor Agreement. +# The bdist_wininst command proper +# based on bdist_wininst +""" +Implements the bdist_msi command. +""" + +import os +import sys +import warnings +from distutils.core import Command +from distutils.dir_util import remove_tree +from distutils.sysconfig import get_python_version +from distutils.version import StrictVersion +from distutils.errors import DistutilsOptionError +from distutils.util import get_platform +from distutils import log +import msilib +from msilib import schema, sequence, text +from msilib import Directory, Feature, Dialog, add_data + +class PyDialog(Dialog): + """Dialog class with a fixed layout: controls at the top, then a ruler, + then a list of buttons: back, next, cancel. Optionally a bitmap at the + left.""" + def __init__(self, *args, **kw): + """Dialog(database, name, x, y, w, h, attributes, title, first, + default, cancel, bitmap=true)""" + super().__init__(*args) + ruler = self.h - 36 + bmwidth = 152*ruler/328 + #if kw.get("bitmap", True): + # self.bitmap("Bitmap", 0, 0, bmwidth, ruler, "PythonWin") + self.line("BottomLine", 0, ruler, self.w, 0) + + def title(self, title): + "Set the title text of the dialog at the top." + # name, x, y, w, h, flags=Visible|Enabled|Transparent|NoPrefix, + # text, in VerdanaBold10 + self.text("Title", 15, 10, 320, 60, 0x30003, + r"{\VerdanaBold10}%s" % title) + + def back(self, title, next, name = "Back", active = 1): + """Add a back button with a given title, the tab-next button, + its name in the Control table, possibly initially disabled. + + Return the button, so that events can be associated""" + if active: + flags = 3 # Visible|Enabled + else: + flags = 1 # Visible + return self.pushbutton(name, 180, self.h-27 , 56, 17, flags, title, next) + + def cancel(self, title, next, name = "Cancel", active = 1): + """Add a cancel button with a given title, the tab-next button, + its name in the Control table, possibly initially disabled. + + Return the button, so that events can be associated""" + if active: + flags = 3 # Visible|Enabled + else: + flags = 1 # Visible + return self.pushbutton(name, 304, self.h-27, 56, 17, flags, title, next) + + def next(self, title, next, name = "Next", active = 1): + """Add a Next button with a given title, the tab-next button, + its name in the Control table, possibly initially disabled. + + Return the button, so that events can be associated""" + if active: + flags = 3 # Visible|Enabled + else: + flags = 1 # Visible + return self.pushbutton(name, 236, self.h-27, 56, 17, flags, title, next) + + def xbutton(self, name, title, next, xpos): + """Add a button with a given title, the tab-next button, + its name in the Control table, giving its x position; the + y-position is aligned with the other buttons. + + Return the button, so that events can be associated""" + return self.pushbutton(name, int(self.w*xpos - 28), self.h-27, 56, 17, 3, title, next) + +class bdist_msi(Command): + + description = "create a Microsoft Installer (.msi) binary distribution" + + user_options = [('bdist-dir=', None, + "temporary directory for creating the distribution"), + ('plat-name=', 'p', + "platform name to embed in generated filenames " + "(default: %s)" % get_platform()), + ('keep-temp', 'k', + "keep the pseudo-installation tree around after " + + "creating the distribution archive"), + ('target-version=', None, + "require a specific python version" + + " on the target system"), + ('no-target-compile', 'c', + "do not compile .py to .pyc on the target system"), + ('no-target-optimize', 'o', + "do not compile .py to .pyo (optimized) " + "on the target system"), + ('dist-dir=', 'd', + "directory to put final built distributions in"), + ('skip-build', None, + "skip rebuilding everything (for testing/debugging)"), + ('install-script=', None, + "basename of installation script to be run after " + "installation or before deinstallation"), + ('pre-install-script=', None, + "Fully qualified filename of a script to be run before " + "any files are installed. This script need not be in the " + "distribution"), + ] + + boolean_options = ['keep-temp', 'no-target-compile', 'no-target-optimize', + 'skip-build'] + + all_versions = ['2.0', '2.1', '2.2', '2.3', '2.4', + '2.5', '2.6', '2.7', '2.8', '2.9', + '3.0', '3.1', '3.2', '3.3', '3.4', + '3.5', '3.6', '3.7', '3.8', '3.9'] + other_version = 'X' + + def __init__(self, *args, **kw): + super().__init__(*args, **kw) + warnings.warn("bdist_msi command is deprecated since Python 3.9, " + "use bdist_wheel (wheel packages) instead", + DeprecationWarning, 2) + + def initialize_options(self): + self.bdist_dir = None + self.plat_name = None + self.keep_temp = 0 + self.no_target_compile = 0 + self.no_target_optimize = 0 + self.target_version = None + self.dist_dir = None + self.skip_build = None + self.install_script = None + self.pre_install_script = None + self.versions = None + + def finalize_options(self): + self.set_undefined_options('bdist', ('skip_build', 'skip_build')) + + if self.bdist_dir is None: + bdist_base = self.get_finalized_command('bdist').bdist_base + self.bdist_dir = os.path.join(bdist_base, 'msi') + + short_version = get_python_version() + if (not self.target_version) and self.distribution.has_ext_modules(): + self.target_version = short_version + + if self.target_version: + self.versions = [self.target_version] + if not self.skip_build and self.distribution.has_ext_modules()\ + and self.target_version != short_version: + raise DistutilsOptionError( + "target version can only be %s, or the '--skip-build'" + " option must be specified" % (short_version,)) + else: + self.versions = list(self.all_versions) + + self.set_undefined_options('bdist', + ('dist_dir', 'dist_dir'), + ('plat_name', 'plat_name'), + ) + + if self.pre_install_script: + raise DistutilsOptionError( + "the pre-install-script feature is not yet implemented") + + if self.install_script: + for script in self.distribution.scripts: + if self.install_script == os.path.basename(script): + break + else: + raise DistutilsOptionError( + "install_script '%s' not found in scripts" + % self.install_script) + self.install_script_key = None + + def run(self): + if not self.skip_build: + self.run_command('build') + + install = self.reinitialize_command('install', reinit_subcommands=1) + install.prefix = self.bdist_dir + install.skip_build = self.skip_build + install.warn_dir = 0 + + install_lib = self.reinitialize_command('install_lib') + # we do not want to include pyc or pyo files + install_lib.compile = 0 + install_lib.optimize = 0 + + if self.distribution.has_ext_modules(): + # If we are building an installer for a Python version other + # than the one we are currently running, then we need to ensure + # our build_lib reflects the other Python version rather than ours. + # Note that for target_version!=sys.version, we must have skipped the + # build step, so there is no issue with enforcing the build of this + # version. + target_version = self.target_version + if not target_version: + assert self.skip_build, "Should have already checked this" + target_version = '%d.%d' % sys.version_info[:2] + plat_specifier = ".%s-%s" % (self.plat_name, target_version) + build = self.get_finalized_command('build') + build.build_lib = os.path.join(build.build_base, + 'lib' + plat_specifier) + + log.info("installing to %s", self.bdist_dir) + install.ensure_finalized() + + # avoid warning of 'install_lib' about installing + # into a directory not in sys.path + sys.path.insert(0, os.path.join(self.bdist_dir, 'PURELIB')) + + install.run() + + del sys.path[0] + + self.mkpath(self.dist_dir) + fullname = self.distribution.get_fullname() + installer_name = self.get_installer_filename(fullname) + installer_name = os.path.abspath(installer_name) + if os.path.exists(installer_name): os.unlink(installer_name) + + metadata = self.distribution.metadata + author = metadata.author + if not author: + author = metadata.maintainer + if not author: + author = "UNKNOWN" + version = metadata.get_version() + # ProductVersion must be strictly numeric + # XXX need to deal with prerelease versions + sversion = "%d.%d.%d" % StrictVersion(version).version + # Prefix ProductName with Python x.y, so that + # it sorts together with the other Python packages + # in Add-Remove-Programs (APR) + fullname = self.distribution.get_fullname() + if self.target_version: + product_name = "Python %s %s" % (self.target_version, fullname) + else: + product_name = "Python %s" % (fullname) + self.db = msilib.init_database(installer_name, schema, + product_name, msilib.gen_uuid(), + sversion, author) + msilib.add_tables(self.db, sequence) + props = [('DistVersion', version)] + email = metadata.author_email or metadata.maintainer_email + if email: + props.append(("ARPCONTACT", email)) + if metadata.url: + props.append(("ARPURLINFOABOUT", metadata.url)) + if props: + add_data(self.db, 'Property', props) + + self.add_find_python() + self.add_files() + self.add_scripts() + self.add_ui() + self.db.Commit() + + if hasattr(self.distribution, 'dist_files'): + tup = 'bdist_msi', self.target_version or 'any', fullname + self.distribution.dist_files.append(tup) + + if not self.keep_temp: + remove_tree(self.bdist_dir, dry_run=self.dry_run) + + def add_files(self): + db = self.db + cab = msilib.CAB("distfiles") + rootdir = os.path.abspath(self.bdist_dir) + + root = Directory(db, cab, None, rootdir, "TARGETDIR", "SourceDir") + f = Feature(db, "Python", "Python", "Everything", + 0, 1, directory="TARGETDIR") + + items = [(f, root, '')] + for version in self.versions + [self.other_version]: + target = "TARGETDIR" + version + name = default = "Python" + version + desc = "Everything" + if version is self.other_version: + title = "Python from another location" + level = 2 + else: + title = "Python %s from registry" % version + level = 1 + f = Feature(db, name, title, desc, 1, level, directory=target) + dir = Directory(db, cab, root, rootdir, target, default) + items.append((f, dir, version)) + db.Commit() + + seen = {} + for feature, dir, version in items: + todo = [dir] + while todo: + dir = todo.pop() + for file in os.listdir(dir.absolute): + afile = os.path.join(dir.absolute, file) + if os.path.isdir(afile): + short = "%s|%s" % (dir.make_short(file), file) + default = file + version + newdir = Directory(db, cab, dir, file, default, short) + todo.append(newdir) + else: + if not dir.component: + dir.start_component(dir.logical, feature, 0) + if afile not in seen: + key = seen[afile] = dir.add_file(file) + if file==self.install_script: + if self.install_script_key: + raise DistutilsOptionError( + "Multiple files with name %s" % file) + self.install_script_key = '[#%s]' % key + else: + key = seen[afile] + add_data(self.db, "DuplicateFile", + [(key + version, dir.component, key, None, dir.logical)]) + db.Commit() + cab.commit(db) + + def add_find_python(self): + """Adds code to the installer to compute the location of Python. + + Properties PYTHON.MACHINE.X.Y and PYTHON.USER.X.Y will be set from the + registry for each version of Python. + + Properties TARGETDIRX.Y will be set from PYTHON.USER.X.Y if defined, + else from PYTHON.MACHINE.X.Y. + + Properties PYTHONX.Y will be set to TARGETDIRX.Y\\python.exe""" + + start = 402 + for ver in self.versions: + install_path = r"SOFTWARE\Python\PythonCore\%s\InstallPath" % ver + machine_reg = "python.machine." + ver + user_reg = "python.user." + ver + machine_prop = "PYTHON.MACHINE." + ver + user_prop = "PYTHON.USER." + ver + machine_action = "PythonFromMachine" + ver + user_action = "PythonFromUser" + ver + exe_action = "PythonExe" + ver + target_dir_prop = "TARGETDIR" + ver + exe_prop = "PYTHON" + ver + if msilib.Win64: + # type: msidbLocatorTypeRawValue + msidbLocatorType64bit + Type = 2+16 + else: + Type = 2 + add_data(self.db, "RegLocator", + [(machine_reg, 2, install_path, None, Type), + (user_reg, 1, install_path, None, Type)]) + add_data(self.db, "AppSearch", + [(machine_prop, machine_reg), + (user_prop, user_reg)]) + add_data(self.db, "CustomAction", + [(machine_action, 51+256, target_dir_prop, "[" + machine_prop + "]"), + (user_action, 51+256, target_dir_prop, "[" + user_prop + "]"), + (exe_action, 51+256, exe_prop, "[" + target_dir_prop + "]\\python.exe"), + ]) + add_data(self.db, "InstallExecuteSequence", + [(machine_action, machine_prop, start), + (user_action, user_prop, start + 1), + (exe_action, None, start + 2), + ]) + add_data(self.db, "InstallUISequence", + [(machine_action, machine_prop, start), + (user_action, user_prop, start + 1), + (exe_action, None, start + 2), + ]) + add_data(self.db, "Condition", + [("Python" + ver, 0, "NOT TARGETDIR" + ver)]) + start += 4 + assert start < 500 + + def add_scripts(self): + if self.install_script: + start = 6800 + for ver in self.versions + [self.other_version]: + install_action = "install_script." + ver + exe_prop = "PYTHON" + ver + add_data(self.db, "CustomAction", + [(install_action, 50, exe_prop, self.install_script_key)]) + add_data(self.db, "InstallExecuteSequence", + [(install_action, "&Python%s=3" % ver, start)]) + start += 1 + # XXX pre-install scripts are currently refused in finalize_options() + # but if this feature is completed, it will also need to add + # entries for each version as the above code does + if self.pre_install_script: + scriptfn = os.path.join(self.bdist_dir, "preinstall.bat") + with open(scriptfn, "w") as f: + # The batch file will be executed with [PYTHON], so that %1 + # is the path to the Python interpreter; %0 will be the path + # of the batch file. + # rem =""" + # %1 %0 + # exit + # """ + # + f.write('rem ="""\n%1 %0\nexit\n"""\n') + with open(self.pre_install_script) as fin: + f.write(fin.read()) + add_data(self.db, "Binary", + [("PreInstall", msilib.Binary(scriptfn)) + ]) + add_data(self.db, "CustomAction", + [("PreInstall", 2, "PreInstall", None) + ]) + add_data(self.db, "InstallExecuteSequence", + [("PreInstall", "NOT Installed", 450)]) + + + def add_ui(self): + db = self.db + x = y = 50 + w = 370 + h = 300 + title = "[ProductName] Setup" + + # see "Dialog Style Bits" + modal = 3 # visible | modal + modeless = 1 # visible + track_disk_space = 32 + + # UI customization properties + add_data(db, "Property", + # See "DefaultUIFont Property" + [("DefaultUIFont", "DlgFont8"), + # See "ErrorDialog Style Bit" + ("ErrorDialog", "ErrorDlg"), + ("Progress1", "Install"), # modified in maintenance type dlg + ("Progress2", "installs"), + ("MaintenanceForm_Action", "Repair"), + # possible values: ALL, JUSTME + ("WhichUsers", "ALL") + ]) + + # Fonts, see "TextStyle Table" + add_data(db, "TextStyle", + [("DlgFont8", "Tahoma", 9, None, 0), + ("DlgFontBold8", "Tahoma", 8, None, 1), #bold + ("VerdanaBold10", "Verdana", 10, None, 1), + ("VerdanaRed9", "Verdana", 9, 255, 0), + ]) + + # UI Sequences, see "InstallUISequence Table", "Using a Sequence Table" + # Numbers indicate sequence; see sequence.py for how these action integrate + add_data(db, "InstallUISequence", + [("PrepareDlg", "Not Privileged or Windows9x or Installed", 140), + ("WhichUsersDlg", "Privileged and not Windows9x and not Installed", 141), + # In the user interface, assume all-users installation if privileged. + ("SelectFeaturesDlg", "Not Installed", 1230), + # XXX no support for resume installations yet + #("ResumeDlg", "Installed AND (RESUME OR Preselected)", 1240), + ("MaintenanceTypeDlg", "Installed AND NOT RESUME AND NOT Preselected", 1250), + ("ProgressDlg", None, 1280)]) + + add_data(db, 'ActionText', text.ActionText) + add_data(db, 'UIText', text.UIText) + ##################################################################### + # Standard dialogs: FatalError, UserExit, ExitDialog + fatal=PyDialog(db, "FatalError", x, y, w, h, modal, title, + "Finish", "Finish", "Finish") + fatal.title("[ProductName] Installer ended prematurely") + fatal.back("< Back", "Finish", active = 0) + fatal.cancel("Cancel", "Back", active = 0) + fatal.text("Description1", 15, 70, 320, 80, 0x30003, + "[ProductName] setup ended prematurely because of an error. Your system has not been modified. To install this program at a later time, please run the installation again.") + fatal.text("Description2", 15, 155, 320, 20, 0x30003, + "Click the Finish button to exit the Installer.") + c=fatal.next("Finish", "Cancel", name="Finish") + c.event("EndDialog", "Exit") + + user_exit=PyDialog(db, "UserExit", x, y, w, h, modal, title, + "Finish", "Finish", "Finish") + user_exit.title("[ProductName] Installer was interrupted") + user_exit.back("< Back", "Finish", active = 0) + user_exit.cancel("Cancel", "Back", active = 0) + user_exit.text("Description1", 15, 70, 320, 80, 0x30003, + "[ProductName] setup was interrupted. Your system has not been modified. " + "To install this program at a later time, please run the installation again.") + user_exit.text("Description2", 15, 155, 320, 20, 0x30003, + "Click the Finish button to exit the Installer.") + c = user_exit.next("Finish", "Cancel", name="Finish") + c.event("EndDialog", "Exit") + + exit_dialog = PyDialog(db, "ExitDialog", x, y, w, h, modal, title, + "Finish", "Finish", "Finish") + exit_dialog.title("Completing the [ProductName] Installer") + exit_dialog.back("< Back", "Finish", active = 0) + exit_dialog.cancel("Cancel", "Back", active = 0) + exit_dialog.text("Description", 15, 235, 320, 20, 0x30003, + "Click the Finish button to exit the Installer.") + c = exit_dialog.next("Finish", "Cancel", name="Finish") + c.event("EndDialog", "Return") + + ##################################################################### + # Required dialog: FilesInUse, ErrorDlg + inuse = PyDialog(db, "FilesInUse", + x, y, w, h, + 19, # KeepModeless|Modal|Visible + title, + "Retry", "Retry", "Retry", bitmap=False) + inuse.text("Title", 15, 6, 200, 15, 0x30003, + r"{\DlgFontBold8}Files in Use") + inuse.text("Description", 20, 23, 280, 20, 0x30003, + "Some files that need to be updated are currently in use.") + inuse.text("Text", 20, 55, 330, 50, 3, + "The following applications are using files that need to be updated by this setup. Close these applications and then click Retry to continue the installation or Cancel to exit it.") + inuse.control("List", "ListBox", 20, 107, 330, 130, 7, "FileInUseProcess", + None, None, None) + c=inuse.back("Exit", "Ignore", name="Exit") + c.event("EndDialog", "Exit") + c=inuse.next("Ignore", "Retry", name="Ignore") + c.event("EndDialog", "Ignore") + c=inuse.cancel("Retry", "Exit", name="Retry") + c.event("EndDialog","Retry") + + # See "Error Dialog". See "ICE20" for the required names of the controls. + error = Dialog(db, "ErrorDlg", + 50, 10, 330, 101, + 65543, # Error|Minimize|Modal|Visible + title, + "ErrorText", None, None) + error.text("ErrorText", 50,9,280,48,3, "") + #error.control("ErrorIcon", "Icon", 15, 9, 24, 24, 5242881, None, "py.ico", None, None) + error.pushbutton("N",120,72,81,21,3,"No",None).event("EndDialog","ErrorNo") + error.pushbutton("Y",240,72,81,21,3,"Yes",None).event("EndDialog","ErrorYes") + error.pushbutton("A",0,72,81,21,3,"Abort",None).event("EndDialog","ErrorAbort") + error.pushbutton("C",42,72,81,21,3,"Cancel",None).event("EndDialog","ErrorCancel") + error.pushbutton("I",81,72,81,21,3,"Ignore",None).event("EndDialog","ErrorIgnore") + error.pushbutton("O",159,72,81,21,3,"Ok",None).event("EndDialog","ErrorOk") + error.pushbutton("R",198,72,81,21,3,"Retry",None).event("EndDialog","ErrorRetry") + + ##################################################################### + # Global "Query Cancel" dialog + cancel = Dialog(db, "CancelDlg", 50, 10, 260, 85, 3, title, + "No", "No", "No") + cancel.text("Text", 48, 15, 194, 30, 3, + "Are you sure you want to cancel [ProductName] installation?") + #cancel.control("Icon", "Icon", 15, 15, 24, 24, 5242881, None, + # "py.ico", None, None) + c=cancel.pushbutton("Yes", 72, 57, 56, 17, 3, "Yes", "No") + c.event("EndDialog", "Exit") + + c=cancel.pushbutton("No", 132, 57, 56, 17, 3, "No", "Yes") + c.event("EndDialog", "Return") + + ##################################################################### + # Global "Wait for costing" dialog + costing = Dialog(db, "WaitForCostingDlg", 50, 10, 260, 85, modal, title, + "Return", "Return", "Return") + costing.text("Text", 48, 15, 194, 30, 3, + "Please wait while the installer finishes determining your disk space requirements.") + c = costing.pushbutton("Return", 102, 57, 56, 17, 3, "Return", None) + c.event("EndDialog", "Exit") + + ##################################################################### + # Preparation dialog: no user input except cancellation + prep = PyDialog(db, "PrepareDlg", x, y, w, h, modeless, title, + "Cancel", "Cancel", "Cancel") + prep.text("Description", 15, 70, 320, 40, 0x30003, + "Please wait while the Installer prepares to guide you through the installation.") + prep.title("Welcome to the [ProductName] Installer") + c=prep.text("ActionText", 15, 110, 320, 20, 0x30003, "Pondering...") + c.mapping("ActionText", "Text") + c=prep.text("ActionData", 15, 135, 320, 30, 0x30003, None) + c.mapping("ActionData", "Text") + prep.back("Back", None, active=0) + prep.next("Next", None, active=0) + c=prep.cancel("Cancel", None) + c.event("SpawnDialog", "CancelDlg") + + ##################################################################### + # Feature (Python directory) selection + seldlg = PyDialog(db, "SelectFeaturesDlg", x, y, w, h, modal, title, + "Next", "Next", "Cancel") + seldlg.title("Select Python Installations") + + seldlg.text("Hint", 15, 30, 300, 20, 3, + "Select the Python locations where %s should be installed." + % self.distribution.get_fullname()) + + seldlg.back("< Back", None, active=0) + c = seldlg.next("Next >", "Cancel") + order = 1 + c.event("[TARGETDIR]", "[SourceDir]", ordering=order) + for version in self.versions + [self.other_version]: + order += 1 + c.event("[TARGETDIR]", "[TARGETDIR%s]" % version, + "FEATURE_SELECTED AND &Python%s=3" % version, + ordering=order) + c.event("SpawnWaitDialog", "WaitForCostingDlg", ordering=order + 1) + c.event("EndDialog", "Return", ordering=order + 2) + c = seldlg.cancel("Cancel", "Features") + c.event("SpawnDialog", "CancelDlg") + + c = seldlg.control("Features", "SelectionTree", 15, 60, 300, 120, 3, + "FEATURE", None, "PathEdit", None) + c.event("[FEATURE_SELECTED]", "1") + ver = self.other_version + install_other_cond = "FEATURE_SELECTED AND &Python%s=3" % ver + dont_install_other_cond = "FEATURE_SELECTED AND &Python%s<>3" % ver + + c = seldlg.text("Other", 15, 200, 300, 15, 3, + "Provide an alternate Python location") + c.condition("Enable", install_other_cond) + c.condition("Show", install_other_cond) + c.condition("Disable", dont_install_other_cond) + c.condition("Hide", dont_install_other_cond) + + c = seldlg.control("PathEdit", "PathEdit", 15, 215, 300, 16, 1, + "TARGETDIR" + ver, None, "Next", None) + c.condition("Enable", install_other_cond) + c.condition("Show", install_other_cond) + c.condition("Disable", dont_install_other_cond) + c.condition("Hide", dont_install_other_cond) + + ##################################################################### + # Disk cost + cost = PyDialog(db, "DiskCostDlg", x, y, w, h, modal, title, + "OK", "OK", "OK", bitmap=False) + cost.text("Title", 15, 6, 200, 15, 0x30003, + r"{\DlgFontBold8}Disk Space Requirements") + cost.text("Description", 20, 20, 280, 20, 0x30003, + "The disk space required for the installation of the selected features.") + cost.text("Text", 20, 53, 330, 60, 3, + "The highlighted volumes (if any) do not have enough disk space " + "available for the currently selected features. You can either " + "remove some files from the highlighted volumes, or choose to " + "install less features onto local drive(s), or select different " + "destination drive(s).") + cost.control("VolumeList", "VolumeCostList", 20, 100, 330, 150, 393223, + None, "{120}{70}{70}{70}{70}", None, None) + cost.xbutton("OK", "Ok", None, 0.5).event("EndDialog", "Return") + + ##################################################################### + # WhichUsers Dialog. Only available on NT, and for privileged users. + # This must be run before FindRelatedProducts, because that will + # take into account whether the previous installation was per-user + # or per-machine. We currently don't support going back to this + # dialog after "Next" was selected; to support this, we would need to + # find how to reset the ALLUSERS property, and how to re-run + # FindRelatedProducts. + # On Windows9x, the ALLUSERS property is ignored on the command line + # and in the Property table, but installer fails according to the documentation + # if a dialog attempts to set ALLUSERS. + whichusers = PyDialog(db, "WhichUsersDlg", x, y, w, h, modal, title, + "AdminInstall", "Next", "Cancel") + whichusers.title("Select whether to install [ProductName] for all users of this computer.") + # A radio group with two options: allusers, justme + g = whichusers.radiogroup("AdminInstall", 15, 60, 260, 50, 3, + "WhichUsers", "", "Next") + g.add("ALL", 0, 5, 150, 20, "Install for all users") + g.add("JUSTME", 0, 25, 150, 20, "Install just for me") + + whichusers.back("Back", None, active=0) + + c = whichusers.next("Next >", "Cancel") + c.event("[ALLUSERS]", "1", 'WhichUsers="ALL"', 1) + c.event("EndDialog", "Return", ordering = 2) + + c = whichusers.cancel("Cancel", "AdminInstall") + c.event("SpawnDialog", "CancelDlg") + + ##################################################################### + # Installation Progress dialog (modeless) + progress = PyDialog(db, "ProgressDlg", x, y, w, h, modeless, title, + "Cancel", "Cancel", "Cancel", bitmap=False) + progress.text("Title", 20, 15, 200, 15, 0x30003, + r"{\DlgFontBold8}[Progress1] [ProductName]") + progress.text("Text", 35, 65, 300, 30, 3, + "Please wait while the Installer [Progress2] [ProductName]. " + "This may take several minutes.") + progress.text("StatusLabel", 35, 100, 35, 20, 3, "Status:") + + c=progress.text("ActionText", 70, 100, w-70, 20, 3, "Pondering...") + c.mapping("ActionText", "Text") + + #c=progress.text("ActionData", 35, 140, 300, 20, 3, None) + #c.mapping("ActionData", "Text") + + c=progress.control("ProgressBar", "ProgressBar", 35, 120, 300, 10, 65537, + None, "Progress done", None, None) + c.mapping("SetProgress", "Progress") + + progress.back("< Back", "Next", active=False) + progress.next("Next >", "Cancel", active=False) + progress.cancel("Cancel", "Back").event("SpawnDialog", "CancelDlg") + + ################################################################### + # Maintenance type: repair/uninstall + maint = PyDialog(db, "MaintenanceTypeDlg", x, y, w, h, modal, title, + "Next", "Next", "Cancel") + maint.title("Welcome to the [ProductName] Setup Wizard") + maint.text("BodyText", 15, 63, 330, 42, 3, + "Select whether you want to repair or remove [ProductName].") + g=maint.radiogroup("RepairRadioGroup", 15, 108, 330, 60, 3, + "MaintenanceForm_Action", "", "Next") + #g.add("Change", 0, 0, 200, 17, "&Change [ProductName]") + g.add("Repair", 0, 18, 200, 17, "&Repair [ProductName]") + g.add("Remove", 0, 36, 200, 17, "Re&move [ProductName]") + + maint.back("< Back", None, active=False) + c=maint.next("Finish", "Cancel") + # Change installation: Change progress dialog to "Change", then ask + # for feature selection + #c.event("[Progress1]", "Change", 'MaintenanceForm_Action="Change"', 1) + #c.event("[Progress2]", "changes", 'MaintenanceForm_Action="Change"', 2) + + # Reinstall: Change progress dialog to "Repair", then invoke reinstall + # Also set list of reinstalled features to "ALL" + c.event("[REINSTALL]", "ALL", 'MaintenanceForm_Action="Repair"', 5) + c.event("[Progress1]", "Repairing", 'MaintenanceForm_Action="Repair"', 6) + c.event("[Progress2]", "repairs", 'MaintenanceForm_Action="Repair"', 7) + c.event("Reinstall", "ALL", 'MaintenanceForm_Action="Repair"', 8) + + # Uninstall: Change progress to "Remove", then invoke uninstall + # Also set list of removed features to "ALL" + c.event("[REMOVE]", "ALL", 'MaintenanceForm_Action="Remove"', 11) + c.event("[Progress1]", "Removing", 'MaintenanceForm_Action="Remove"', 12) + c.event("[Progress2]", "removes", 'MaintenanceForm_Action="Remove"', 13) + c.event("Remove", "ALL", 'MaintenanceForm_Action="Remove"', 14) + + # Close dialog when maintenance action scheduled + c.event("EndDialog", "Return", 'MaintenanceForm_Action<>"Change"', 20) + #c.event("NewDialog", "SelectFeaturesDlg", 'MaintenanceForm_Action="Change"', 21) + + maint.cancel("Cancel", "RepairRadioGroup").event("SpawnDialog", "CancelDlg") + + def get_installer_filename(self, fullname): + # Factored out to allow overriding in subclasses + if self.target_version: + base_name = "%s.%s-py%s.msi" % (fullname, self.plat_name, + self.target_version) + else: + base_name = "%s.%s.msi" % (fullname, self.plat_name) + installer_name = os.path.join(self.dist_dir, base_name) + return installer_name diff --git a/venv/Lib/site-packages/setuptools/_distutils/command/bdist_rpm.py b/venv/Lib/site-packages/setuptools/_distutils/command/bdist_rpm.py new file mode 100644 index 0000000..550cbfa --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_distutils/command/bdist_rpm.py @@ -0,0 +1,579 @@ +"""distutils.command.bdist_rpm + +Implements the Distutils 'bdist_rpm' command (create RPM source and binary +distributions).""" + +import subprocess, sys, os +from distutils.core import Command +from distutils.debug import DEBUG +from distutils.file_util import write_file +from distutils.errors import * +from distutils.sysconfig import get_python_version +from distutils import log + +class bdist_rpm(Command): + + description = "create an RPM distribution" + + user_options = [ + ('bdist-base=', None, + "base directory for creating built distributions"), + ('rpm-base=', None, + "base directory for creating RPMs (defaults to \"rpm\" under " + "--bdist-base; must be specified for RPM 2)"), + ('dist-dir=', 'd', + "directory to put final RPM files in " + "(and .spec files if --spec-only)"), + ('python=', None, + "path to Python interpreter to hard-code in the .spec file " + "(default: \"python\")"), + ('fix-python', None, + "hard-code the exact path to the current Python interpreter in " + "the .spec file"), + ('spec-only', None, + "only regenerate spec file"), + ('source-only', None, + "only generate source RPM"), + ('binary-only', None, + "only generate binary RPM"), + ('use-bzip2', None, + "use bzip2 instead of gzip to create source distribution"), + + # More meta-data: too RPM-specific to put in the setup script, + # but needs to go in the .spec file -- so we make these options + # to "bdist_rpm". The idea is that packagers would put this + # info in setup.cfg, although they are of course free to + # supply it on the command line. + ('distribution-name=', None, + "name of the (Linux) distribution to which this " + "RPM applies (*not* the name of the module distribution!)"), + ('group=', None, + "package classification [default: \"Development/Libraries\"]"), + ('release=', None, + "RPM release number"), + ('serial=', None, + "RPM serial number"), + ('vendor=', None, + "RPM \"vendor\" (eg. \"Joe Blow \") " + "[default: maintainer or author from setup script]"), + ('packager=', None, + "RPM packager (eg. \"Jane Doe \") " + "[default: vendor]"), + ('doc-files=', None, + "list of documentation files (space or comma-separated)"), + ('changelog=', None, + "RPM changelog"), + ('icon=', None, + "name of icon file"), + ('provides=', None, + "capabilities provided by this package"), + ('requires=', None, + "capabilities required by this package"), + ('conflicts=', None, + "capabilities which conflict with this package"), + ('build-requires=', None, + "capabilities required to build this package"), + ('obsoletes=', None, + "capabilities made obsolete by this package"), + ('no-autoreq', None, + "do not automatically calculate dependencies"), + + # Actions to take when building RPM + ('keep-temp', 'k', + "don't clean up RPM build directory"), + ('no-keep-temp', None, + "clean up RPM build directory [default]"), + ('use-rpm-opt-flags', None, + "compile with RPM_OPT_FLAGS when building from source RPM"), + ('no-rpm-opt-flags', None, + "do not pass any RPM CFLAGS to compiler"), + ('rpm3-mode', None, + "RPM 3 compatibility mode (default)"), + ('rpm2-mode', None, + "RPM 2 compatibility mode"), + + # Add the hooks necessary for specifying custom scripts + ('prep-script=', None, + "Specify a script for the PREP phase of RPM building"), + ('build-script=', None, + "Specify a script for the BUILD phase of RPM building"), + + ('pre-install=', None, + "Specify a script for the pre-INSTALL phase of RPM building"), + ('install-script=', None, + "Specify a script for the INSTALL phase of RPM building"), + ('post-install=', None, + "Specify a script for the post-INSTALL phase of RPM building"), + + ('pre-uninstall=', None, + "Specify a script for the pre-UNINSTALL phase of RPM building"), + ('post-uninstall=', None, + "Specify a script for the post-UNINSTALL phase of RPM building"), + + ('clean-script=', None, + "Specify a script for the CLEAN phase of RPM building"), + + ('verify-script=', None, + "Specify a script for the VERIFY phase of the RPM build"), + + # Allow a packager to explicitly force an architecture + ('force-arch=', None, + "Force an architecture onto the RPM build process"), + + ('quiet', 'q', + "Run the INSTALL phase of RPM building in quiet mode"), + ] + + boolean_options = ['keep-temp', 'use-rpm-opt-flags', 'rpm3-mode', + 'no-autoreq', 'quiet'] + + negative_opt = {'no-keep-temp': 'keep-temp', + 'no-rpm-opt-flags': 'use-rpm-opt-flags', + 'rpm2-mode': 'rpm3-mode'} + + + def initialize_options(self): + self.bdist_base = None + self.rpm_base = None + self.dist_dir = None + self.python = None + self.fix_python = None + self.spec_only = None + self.binary_only = None + self.source_only = None + self.use_bzip2 = None + + self.distribution_name = None + self.group = None + self.release = None + self.serial = None + self.vendor = None + self.packager = None + self.doc_files = None + self.changelog = None + self.icon = None + + self.prep_script = None + self.build_script = None + self.install_script = None + self.clean_script = None + self.verify_script = None + self.pre_install = None + self.post_install = None + self.pre_uninstall = None + self.post_uninstall = None + self.prep = None + self.provides = None + self.requires = None + self.conflicts = None + self.build_requires = None + self.obsoletes = None + + self.keep_temp = 0 + self.use_rpm_opt_flags = 1 + self.rpm3_mode = 1 + self.no_autoreq = 0 + + self.force_arch = None + self.quiet = 0 + + def finalize_options(self): + self.set_undefined_options('bdist', ('bdist_base', 'bdist_base')) + if self.rpm_base is None: + if not self.rpm3_mode: + raise DistutilsOptionError( + "you must specify --rpm-base in RPM 2 mode") + self.rpm_base = os.path.join(self.bdist_base, "rpm") + + if self.python is None: + if self.fix_python: + self.python = sys.executable + else: + self.python = "python3" + elif self.fix_python: + raise DistutilsOptionError( + "--python and --fix-python are mutually exclusive options") + + if os.name != 'posix': + raise DistutilsPlatformError("don't know how to create RPM " + "distributions on platform %s" % os.name) + if self.binary_only and self.source_only: + raise DistutilsOptionError( + "cannot supply both '--source-only' and '--binary-only'") + + # don't pass CFLAGS to pure python distributions + if not self.distribution.has_ext_modules(): + self.use_rpm_opt_flags = 0 + + self.set_undefined_options('bdist', ('dist_dir', 'dist_dir')) + self.finalize_package_data() + + def finalize_package_data(self): + self.ensure_string('group', "Development/Libraries") + self.ensure_string('vendor', + "%s <%s>" % (self.distribution.get_contact(), + self.distribution.get_contact_email())) + self.ensure_string('packager') + self.ensure_string_list('doc_files') + if isinstance(self.doc_files, list): + for readme in ('README', 'README.txt'): + if os.path.exists(readme) and readme not in self.doc_files: + self.doc_files.append(readme) + + self.ensure_string('release', "1") + self.ensure_string('serial') # should it be an int? + + self.ensure_string('distribution_name') + + self.ensure_string('changelog') + # Format changelog correctly + self.changelog = self._format_changelog(self.changelog) + + self.ensure_filename('icon') + + self.ensure_filename('prep_script') + self.ensure_filename('build_script') + self.ensure_filename('install_script') + self.ensure_filename('clean_script') + self.ensure_filename('verify_script') + self.ensure_filename('pre_install') + self.ensure_filename('post_install') + self.ensure_filename('pre_uninstall') + self.ensure_filename('post_uninstall') + + # XXX don't forget we punted on summaries and descriptions -- they + # should be handled here eventually! + + # Now *this* is some meta-data that belongs in the setup script... + self.ensure_string_list('provides') + self.ensure_string_list('requires') + self.ensure_string_list('conflicts') + self.ensure_string_list('build_requires') + self.ensure_string_list('obsoletes') + + self.ensure_string('force_arch') + + def run(self): + if DEBUG: + print("before _get_package_data():") + print("vendor =", self.vendor) + print("packager =", self.packager) + print("doc_files =", self.doc_files) + print("changelog =", self.changelog) + + # make directories + if self.spec_only: + spec_dir = self.dist_dir + self.mkpath(spec_dir) + else: + rpm_dir = {} + for d in ('SOURCES', 'SPECS', 'BUILD', 'RPMS', 'SRPMS'): + rpm_dir[d] = os.path.join(self.rpm_base, d) + self.mkpath(rpm_dir[d]) + spec_dir = rpm_dir['SPECS'] + + # Spec file goes into 'dist_dir' if '--spec-only specified', + # build/rpm. otherwise. + spec_path = os.path.join(spec_dir, + "%s.spec" % self.distribution.get_name()) + self.execute(write_file, + (spec_path, + self._make_spec_file()), + "writing '%s'" % spec_path) + + if self.spec_only: # stop if requested + return + + # Make a source distribution and copy to SOURCES directory with + # optional icon. + saved_dist_files = self.distribution.dist_files[:] + sdist = self.reinitialize_command('sdist') + if self.use_bzip2: + sdist.formats = ['bztar'] + else: + sdist.formats = ['gztar'] + self.run_command('sdist') + self.distribution.dist_files = saved_dist_files + + source = sdist.get_archive_files()[0] + source_dir = rpm_dir['SOURCES'] + self.copy_file(source, source_dir) + + if self.icon: + if os.path.exists(self.icon): + self.copy_file(self.icon, source_dir) + else: + raise DistutilsFileError( + "icon file '%s' does not exist" % self.icon) + + # build package + log.info("building RPMs") + rpm_cmd = ['rpmbuild'] + + if self.source_only: # what kind of RPMs? + rpm_cmd.append('-bs') + elif self.binary_only: + rpm_cmd.append('-bb') + else: + rpm_cmd.append('-ba') + rpm_cmd.extend(['--define', '__python %s' % self.python]) + if self.rpm3_mode: + rpm_cmd.extend(['--define', + '_topdir %s' % os.path.abspath(self.rpm_base)]) + if not self.keep_temp: + rpm_cmd.append('--clean') + + if self.quiet: + rpm_cmd.append('--quiet') + + rpm_cmd.append(spec_path) + # Determine the binary rpm names that should be built out of this spec + # file + # Note that some of these may not be really built (if the file + # list is empty) + nvr_string = "%{name}-%{version}-%{release}" + src_rpm = nvr_string + ".src.rpm" + non_src_rpm = "%{arch}/" + nvr_string + ".%{arch}.rpm" + q_cmd = r"rpm -q --qf '%s %s\n' --specfile '%s'" % ( + src_rpm, non_src_rpm, spec_path) + + out = os.popen(q_cmd) + try: + binary_rpms = [] + source_rpm = None + while True: + line = out.readline() + if not line: + break + l = line.strip().split() + assert(len(l) == 2) + binary_rpms.append(l[1]) + # The source rpm is named after the first entry in the spec file + if source_rpm is None: + source_rpm = l[0] + + status = out.close() + if status: + raise DistutilsExecError("Failed to execute: %s" % repr(q_cmd)) + + finally: + out.close() + + self.spawn(rpm_cmd) + + if not self.dry_run: + if self.distribution.has_ext_modules(): + pyversion = get_python_version() + else: + pyversion = 'any' + + if not self.binary_only: + srpm = os.path.join(rpm_dir['SRPMS'], source_rpm) + assert(os.path.exists(srpm)) + self.move_file(srpm, self.dist_dir) + filename = os.path.join(self.dist_dir, source_rpm) + self.distribution.dist_files.append( + ('bdist_rpm', pyversion, filename)) + + if not self.source_only: + for rpm in binary_rpms: + rpm = os.path.join(rpm_dir['RPMS'], rpm) + if os.path.exists(rpm): + self.move_file(rpm, self.dist_dir) + filename = os.path.join(self.dist_dir, + os.path.basename(rpm)) + self.distribution.dist_files.append( + ('bdist_rpm', pyversion, filename)) + + def _dist_path(self, path): + return os.path.join(self.dist_dir, os.path.basename(path)) + + def _make_spec_file(self): + """Generate the text of an RPM spec file and return it as a + list of strings (one per line). + """ + # definitions and headers + spec_file = [ + '%define name ' + self.distribution.get_name(), + '%define version ' + self.distribution.get_version().replace('-','_'), + '%define unmangled_version ' + self.distribution.get_version(), + '%define release ' + self.release.replace('-','_'), + '', + 'Summary: ' + self.distribution.get_description(), + ] + + # Workaround for #14443 which affects some RPM based systems such as + # RHEL6 (and probably derivatives) + vendor_hook = subprocess.getoutput('rpm --eval %{__os_install_post}') + # Generate a potential replacement value for __os_install_post (whilst + # normalizing the whitespace to simplify the test for whether the + # invocation of brp-python-bytecompile passes in __python): + vendor_hook = '\n'.join([' %s \\' % line.strip() + for line in vendor_hook.splitlines()]) + problem = "brp-python-bytecompile \\\n" + fixed = "brp-python-bytecompile %{__python} \\\n" + fixed_hook = vendor_hook.replace(problem, fixed) + if fixed_hook != vendor_hook: + spec_file.append('# Workaround for http://bugs.python.org/issue14443') + spec_file.append('%define __os_install_post ' + fixed_hook + '\n') + + # put locale summaries into spec file + # XXX not supported for now (hard to put a dictionary + # in a config file -- arg!) + #for locale in self.summaries.keys(): + # spec_file.append('Summary(%s): %s' % (locale, + # self.summaries[locale])) + + spec_file.extend([ + 'Name: %{name}', + 'Version: %{version}', + 'Release: %{release}',]) + + # XXX yuck! this filename is available from the "sdist" command, + # but only after it has run: and we create the spec file before + # running "sdist", in case of --spec-only. + if self.use_bzip2: + spec_file.append('Source0: %{name}-%{unmangled_version}.tar.bz2') + else: + spec_file.append('Source0: %{name}-%{unmangled_version}.tar.gz') + + spec_file.extend([ + 'License: ' + self.distribution.get_license(), + 'Group: ' + self.group, + 'BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-buildroot', + 'Prefix: %{_prefix}', ]) + + if not self.force_arch: + # noarch if no extension modules + if not self.distribution.has_ext_modules(): + spec_file.append('BuildArch: noarch') + else: + spec_file.append( 'BuildArch: %s' % self.force_arch ) + + for field in ('Vendor', + 'Packager', + 'Provides', + 'Requires', + 'Conflicts', + 'Obsoletes', + ): + val = getattr(self, field.lower()) + if isinstance(val, list): + spec_file.append('%s: %s' % (field, ' '.join(val))) + elif val is not None: + spec_file.append('%s: %s' % (field, val)) + + + if self.distribution.get_url() != 'UNKNOWN': + spec_file.append('Url: ' + self.distribution.get_url()) + + if self.distribution_name: + spec_file.append('Distribution: ' + self.distribution_name) + + if self.build_requires: + spec_file.append('BuildRequires: ' + + ' '.join(self.build_requires)) + + if self.icon: + spec_file.append('Icon: ' + os.path.basename(self.icon)) + + if self.no_autoreq: + spec_file.append('AutoReq: 0') + + spec_file.extend([ + '', + '%description', + self.distribution.get_long_description() + ]) + + # put locale descriptions into spec file + # XXX again, suppressed because config file syntax doesn't + # easily support this ;-( + #for locale in self.descriptions.keys(): + # spec_file.extend([ + # '', + # '%description -l ' + locale, + # self.descriptions[locale], + # ]) + + # rpm scripts + # figure out default build script + def_setup_call = "%s %s" % (self.python,os.path.basename(sys.argv[0])) + def_build = "%s build" % def_setup_call + if self.use_rpm_opt_flags: + def_build = 'env CFLAGS="$RPM_OPT_FLAGS" ' + def_build + + # insert contents of files + + # XXX this is kind of misleading: user-supplied options are files + # that we open and interpolate into the spec file, but the defaults + # are just text that we drop in as-is. Hmmm. + + install_cmd = ('%s install -O1 --root=$RPM_BUILD_ROOT ' + '--record=INSTALLED_FILES') % def_setup_call + + script_options = [ + ('prep', 'prep_script', "%setup -n %{name}-%{unmangled_version}"), + ('build', 'build_script', def_build), + ('install', 'install_script', install_cmd), + ('clean', 'clean_script', "rm -rf $RPM_BUILD_ROOT"), + ('verifyscript', 'verify_script', None), + ('pre', 'pre_install', None), + ('post', 'post_install', None), + ('preun', 'pre_uninstall', None), + ('postun', 'post_uninstall', None), + ] + + for (rpm_opt, attr, default) in script_options: + # Insert contents of file referred to, if no file is referred to + # use 'default' as contents of script + val = getattr(self, attr) + if val or default: + spec_file.extend([ + '', + '%' + rpm_opt,]) + if val: + with open(val) as f: + spec_file.extend(f.read().split('\n')) + else: + spec_file.append(default) + + + # files section + spec_file.extend([ + '', + '%files -f INSTALLED_FILES', + '%defattr(-,root,root)', + ]) + + if self.doc_files: + spec_file.append('%doc ' + ' '.join(self.doc_files)) + + if self.changelog: + spec_file.extend([ + '', + '%changelog',]) + spec_file.extend(self.changelog) + + return spec_file + + def _format_changelog(self, changelog): + """Format the changelog correctly and convert it to a list of strings + """ + if not changelog: + return changelog + new_changelog = [] + for line in changelog.strip().split('\n'): + line = line.strip() + if line[0] == '*': + new_changelog.extend(['', line]) + elif line[0] == '-': + new_changelog.append(line) + else: + new_changelog.append(' ' + line) + + # strip trailing newline inserted by first changelog entry + if not new_changelog[0]: + del new_changelog[0] + + return new_changelog diff --git a/venv/Lib/site-packages/setuptools/_distutils/command/bdist_wininst.py b/venv/Lib/site-packages/setuptools/_distutils/command/bdist_wininst.py new file mode 100644 index 0000000..0e9ddaa --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_distutils/command/bdist_wininst.py @@ -0,0 +1,377 @@ +"""distutils.command.bdist_wininst + +Implements the Distutils 'bdist_wininst' command: create a windows installer +exe-program.""" + +import os +import sys +import warnings +from distutils.core import Command +from distutils.util import get_platform +from distutils.dir_util import remove_tree +from distutils.errors import * +from distutils.sysconfig import get_python_version +from distutils import log + +class bdist_wininst(Command): + + description = "create an executable installer for MS Windows" + + user_options = [('bdist-dir=', None, + "temporary directory for creating the distribution"), + ('plat-name=', 'p', + "platform name to embed in generated filenames " + "(default: %s)" % get_platform()), + ('keep-temp', 'k', + "keep the pseudo-installation tree around after " + + "creating the distribution archive"), + ('target-version=', None, + "require a specific python version" + + " on the target system"), + ('no-target-compile', 'c', + "do not compile .py to .pyc on the target system"), + ('no-target-optimize', 'o', + "do not compile .py to .pyo (optimized) " + "on the target system"), + ('dist-dir=', 'd', + "directory to put final built distributions in"), + ('bitmap=', 'b', + "bitmap to use for the installer instead of python-powered logo"), + ('title=', 't', + "title to display on the installer background instead of default"), + ('skip-build', None, + "skip rebuilding everything (for testing/debugging)"), + ('install-script=', None, + "basename of installation script to be run after " + "installation or before deinstallation"), + ('pre-install-script=', None, + "Fully qualified filename of a script to be run before " + "any files are installed. This script need not be in the " + "distribution"), + ('user-access-control=', None, + "specify Vista's UAC handling - 'none'/default=no " + "handling, 'auto'=use UAC if target Python installed for " + "all users, 'force'=always use UAC"), + ] + + boolean_options = ['keep-temp', 'no-target-compile', 'no-target-optimize', + 'skip-build'] + + # bpo-10945: bdist_wininst requires mbcs encoding only available on Windows + _unsupported = (sys.platform != "win32") + + def __init__(self, *args, **kw): + super().__init__(*args, **kw) + warnings.warn("bdist_wininst command is deprecated since Python 3.8, " + "use bdist_wheel (wheel packages) instead", + DeprecationWarning, 2) + + def initialize_options(self): + self.bdist_dir = None + self.plat_name = None + self.keep_temp = 0 + self.no_target_compile = 0 + self.no_target_optimize = 0 + self.target_version = None + self.dist_dir = None + self.bitmap = None + self.title = None + self.skip_build = None + self.install_script = None + self.pre_install_script = None + self.user_access_control = None + + + def finalize_options(self): + self.set_undefined_options('bdist', ('skip_build', 'skip_build')) + + if self.bdist_dir is None: + if self.skip_build and self.plat_name: + # If build is skipped and plat_name is overridden, bdist will + # not see the correct 'plat_name' - so set that up manually. + bdist = self.distribution.get_command_obj('bdist') + bdist.plat_name = self.plat_name + # next the command will be initialized using that name + bdist_base = self.get_finalized_command('bdist').bdist_base + self.bdist_dir = os.path.join(bdist_base, 'wininst') + + if not self.target_version: + self.target_version = "" + + if not self.skip_build and self.distribution.has_ext_modules(): + short_version = get_python_version() + if self.target_version and self.target_version != short_version: + raise DistutilsOptionError( + "target version can only be %s, or the '--skip-build'" \ + " option must be specified" % (short_version,)) + self.target_version = short_version + + self.set_undefined_options('bdist', + ('dist_dir', 'dist_dir'), + ('plat_name', 'plat_name'), + ) + + if self.install_script: + for script in self.distribution.scripts: + if self.install_script == os.path.basename(script): + break + else: + raise DistutilsOptionError( + "install_script '%s' not found in scripts" + % self.install_script) + + def run(self): + if (sys.platform != "win32" and + (self.distribution.has_ext_modules() or + self.distribution.has_c_libraries())): + raise DistutilsPlatformError \ + ("distribution contains extensions and/or C libraries; " + "must be compiled on a Windows 32 platform") + + if not self.skip_build: + self.run_command('build') + + install = self.reinitialize_command('install', reinit_subcommands=1) + install.root = self.bdist_dir + install.skip_build = self.skip_build + install.warn_dir = 0 + install.plat_name = self.plat_name + + install_lib = self.reinitialize_command('install_lib') + # we do not want to include pyc or pyo files + install_lib.compile = 0 + install_lib.optimize = 0 + + if self.distribution.has_ext_modules(): + # If we are building an installer for a Python version other + # than the one we are currently running, then we need to ensure + # our build_lib reflects the other Python version rather than ours. + # Note that for target_version!=sys.version, we must have skipped the + # build step, so there is no issue with enforcing the build of this + # version. + target_version = self.target_version + if not target_version: + assert self.skip_build, "Should have already checked this" + target_version = '%d.%d' % sys.version_info[:2] + plat_specifier = ".%s-%s" % (self.plat_name, target_version) + build = self.get_finalized_command('build') + build.build_lib = os.path.join(build.build_base, + 'lib' + plat_specifier) + + # Use a custom scheme for the zip-file, because we have to decide + # at installation time which scheme to use. + for key in ('purelib', 'platlib', 'headers', 'scripts', 'data'): + value = key.upper() + if key == 'headers': + value = value + '/Include/$dist_name' + setattr(install, + 'install_' + key, + value) + + log.info("installing to %s", self.bdist_dir) + install.ensure_finalized() + + # avoid warning of 'install_lib' about installing + # into a directory not in sys.path + sys.path.insert(0, os.path.join(self.bdist_dir, 'PURELIB')) + + install.run() + + del sys.path[0] + + # And make an archive relative to the root of the + # pseudo-installation tree. + from tempfile import mktemp + archive_basename = mktemp() + fullname = self.distribution.get_fullname() + arcname = self.make_archive(archive_basename, "zip", + root_dir=self.bdist_dir) + # create an exe containing the zip-file + self.create_exe(arcname, fullname, self.bitmap) + if self.distribution.has_ext_modules(): + pyversion = get_python_version() + else: + pyversion = 'any' + self.distribution.dist_files.append(('bdist_wininst', pyversion, + self.get_installer_filename(fullname))) + # remove the zip-file again + log.debug("removing temporary file '%s'", arcname) + os.remove(arcname) + + if not self.keep_temp: + remove_tree(self.bdist_dir, dry_run=self.dry_run) + + def get_inidata(self): + # Return data describing the installation. + lines = [] + metadata = self.distribution.metadata + + # Write the [metadata] section. + lines.append("[metadata]") + + # 'info' will be displayed in the installer's dialog box, + # describing the items to be installed. + info = (metadata.long_description or '') + '\n' + + # Escape newline characters + def escape(s): + return s.replace("\n", "\\n") + + for name in ["author", "author_email", "description", "maintainer", + "maintainer_email", "name", "url", "version"]: + data = getattr(metadata, name, "") + if data: + info = info + ("\n %s: %s" % \ + (name.capitalize(), escape(data))) + lines.append("%s=%s" % (name, escape(data))) + + # The [setup] section contains entries controlling + # the installer runtime. + lines.append("\n[Setup]") + if self.install_script: + lines.append("install_script=%s" % self.install_script) + lines.append("info=%s" % escape(info)) + lines.append("target_compile=%d" % (not self.no_target_compile)) + lines.append("target_optimize=%d" % (not self.no_target_optimize)) + if self.target_version: + lines.append("target_version=%s" % self.target_version) + if self.user_access_control: + lines.append("user_access_control=%s" % self.user_access_control) + + title = self.title or self.distribution.get_fullname() + lines.append("title=%s" % escape(title)) + import time + import distutils + build_info = "Built %s with distutils-%s" % \ + (time.ctime(time.time()), distutils.__version__) + lines.append("build_info=%s" % build_info) + return "\n".join(lines) + + def create_exe(self, arcname, fullname, bitmap=None): + import struct + + self.mkpath(self.dist_dir) + + cfgdata = self.get_inidata() + + installer_name = self.get_installer_filename(fullname) + self.announce("creating %s" % installer_name) + + if bitmap: + with open(bitmap, "rb") as f: + bitmapdata = f.read() + bitmaplen = len(bitmapdata) + else: + bitmaplen = 0 + + with open(installer_name, "wb") as file: + file.write(self.get_exe_bytes()) + if bitmap: + file.write(bitmapdata) + + # Convert cfgdata from unicode to ascii, mbcs encoded + if isinstance(cfgdata, str): + cfgdata = cfgdata.encode("mbcs") + + # Append the pre-install script + cfgdata = cfgdata + b"\0" + if self.pre_install_script: + # We need to normalize newlines, so we open in text mode and + # convert back to bytes. "latin-1" simply avoids any possible + # failures. + with open(self.pre_install_script, "r", + encoding="latin-1") as script: + script_data = script.read().encode("latin-1") + cfgdata = cfgdata + script_data + b"\n\0" + else: + # empty pre-install script + cfgdata = cfgdata + b"\0" + file.write(cfgdata) + + # The 'magic number' 0x1234567B is used to make sure that the + # binary layout of 'cfgdata' is what the wininst.exe binary + # expects. If the layout changes, increment that number, make + # the corresponding changes to the wininst.exe sources, and + # recompile them. + header = struct.pack("' under the base build directory. We only use one of + # them for a given distribution, though -- + if self.build_purelib is None: + self.build_purelib = os.path.join(self.build_base, 'lib') + if self.build_platlib is None: + self.build_platlib = os.path.join(self.build_base, + 'lib' + plat_specifier) + + # 'build_lib' is the actual directory that we will use for this + # particular module distribution -- if user didn't supply it, pick + # one of 'build_purelib' or 'build_platlib'. + if self.build_lib is None: + if self.distribution.has_ext_modules(): + self.build_lib = self.build_platlib + else: + self.build_lib = self.build_purelib + + # 'build_temp' -- temporary directory for compiler turds, + # "build/temp." + if self.build_temp is None: + self.build_temp = os.path.join(self.build_base, + 'temp' + plat_specifier) + if self.build_scripts is None: + self.build_scripts = os.path.join(self.build_base, + 'scripts-%d.%d' % sys.version_info[:2]) + + if self.executable is None and sys.executable: + self.executable = os.path.normpath(sys.executable) + + if isinstance(self.parallel, str): + try: + self.parallel = int(self.parallel) + except ValueError: + raise DistutilsOptionError("parallel should be an integer") + + def run(self): + # Run all relevant sub-commands. This will be some subset of: + # - build_py - pure Python modules + # - build_clib - standalone C libraries + # - build_ext - Python extensions + # - build_scripts - (Python) scripts + for cmd_name in self.get_sub_commands(): + self.run_command(cmd_name) + + + # -- Predicates for the sub-command list --------------------------- + + def has_pure_modules(self): + return self.distribution.has_pure_modules() + + def has_c_libraries(self): + return self.distribution.has_c_libraries() + + def has_ext_modules(self): + return self.distribution.has_ext_modules() + + def has_scripts(self): + return self.distribution.has_scripts() + + + sub_commands = [('build_py', has_pure_modules), + ('build_clib', has_c_libraries), + ('build_ext', has_ext_modules), + ('build_scripts', has_scripts), + ] diff --git a/venv/Lib/site-packages/setuptools/_distutils/command/build_clib.py b/venv/Lib/site-packages/setuptools/_distutils/command/build_clib.py new file mode 100644 index 0000000..3e20ef2 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_distutils/command/build_clib.py @@ -0,0 +1,209 @@ +"""distutils.command.build_clib + +Implements the Distutils 'build_clib' command, to build a C/C++ library +that is included in the module distribution and needed by an extension +module.""" + + +# XXX this module has *lots* of code ripped-off quite transparently from +# build_ext.py -- not surprisingly really, as the work required to build +# a static library from a collection of C source files is not really all +# that different from what's required to build a shared object file from +# a collection of C source files. Nevertheless, I haven't done the +# necessary refactoring to account for the overlap in code between the +# two modules, mainly because a number of subtle details changed in the +# cut 'n paste. Sigh. + +import os +from distutils.core import Command +from distutils.errors import * +from distutils.sysconfig import customize_compiler +from distutils import log + +def show_compilers(): + from distutils.ccompiler import show_compilers + show_compilers() + + +class build_clib(Command): + + description = "build C/C++ libraries used by Python extensions" + + user_options = [ + ('build-clib=', 'b', + "directory to build C/C++ libraries to"), + ('build-temp=', 't', + "directory to put temporary build by-products"), + ('debug', 'g', + "compile with debugging information"), + ('force', 'f', + "forcibly build everything (ignore file timestamps)"), + ('compiler=', 'c', + "specify the compiler type"), + ] + + boolean_options = ['debug', 'force'] + + help_options = [ + ('help-compiler', None, + "list available compilers", show_compilers), + ] + + def initialize_options(self): + self.build_clib = None + self.build_temp = None + + # List of libraries to build + self.libraries = None + + # Compilation options for all libraries + self.include_dirs = None + self.define = None + self.undef = None + self.debug = None + self.force = 0 + self.compiler = None + + + def finalize_options(self): + # This might be confusing: both build-clib and build-temp default + # to build-temp as defined by the "build" command. This is because + # I think that C libraries are really just temporary build + # by-products, at least from the point of view of building Python + # extensions -- but I want to keep my options open. + self.set_undefined_options('build', + ('build_temp', 'build_clib'), + ('build_temp', 'build_temp'), + ('compiler', 'compiler'), + ('debug', 'debug'), + ('force', 'force')) + + self.libraries = self.distribution.libraries + if self.libraries: + self.check_library_list(self.libraries) + + if self.include_dirs is None: + self.include_dirs = self.distribution.include_dirs or [] + if isinstance(self.include_dirs, str): + self.include_dirs = self.include_dirs.split(os.pathsep) + + # XXX same as for build_ext -- what about 'self.define' and + # 'self.undef' ? + + + def run(self): + if not self.libraries: + return + + # Yech -- this is cut 'n pasted from build_ext.py! + from distutils.ccompiler import new_compiler + self.compiler = new_compiler(compiler=self.compiler, + dry_run=self.dry_run, + force=self.force) + customize_compiler(self.compiler) + + if self.include_dirs is not None: + self.compiler.set_include_dirs(self.include_dirs) + if self.define is not None: + # 'define' option is a list of (name,value) tuples + for (name,value) in self.define: + self.compiler.define_macro(name, value) + if self.undef is not None: + for macro in self.undef: + self.compiler.undefine_macro(macro) + + self.build_libraries(self.libraries) + + + def check_library_list(self, libraries): + """Ensure that the list of libraries is valid. + + `library` is presumably provided as a command option 'libraries'. + This method checks that it is a list of 2-tuples, where the tuples + are (library_name, build_info_dict). + + Raise DistutilsSetupError if the structure is invalid anywhere; + just returns otherwise. + """ + if not isinstance(libraries, list): + raise DistutilsSetupError( + "'libraries' option must be a list of tuples") + + for lib in libraries: + if not isinstance(lib, tuple) and len(lib) != 2: + raise DistutilsSetupError( + "each element of 'libraries' must a 2-tuple") + + name, build_info = lib + + if not isinstance(name, str): + raise DistutilsSetupError( + "first element of each tuple in 'libraries' " + "must be a string (the library name)") + + if '/' in name or (os.sep != '/' and os.sep in name): + raise DistutilsSetupError("bad library name '%s': " + "may not contain directory separators" % lib[0]) + + if not isinstance(build_info, dict): + raise DistutilsSetupError( + "second element of each tuple in 'libraries' " + "must be a dictionary (build info)") + + + def get_library_names(self): + # Assume the library list is valid -- 'check_library_list()' is + # called from 'finalize_options()', so it should be! + if not self.libraries: + return None + + lib_names = [] + for (lib_name, build_info) in self.libraries: + lib_names.append(lib_name) + return lib_names + + + def get_source_files(self): + self.check_library_list(self.libraries) + filenames = [] + for (lib_name, build_info) in self.libraries: + sources = build_info.get('sources') + if sources is None or not isinstance(sources, (list, tuple)): + raise DistutilsSetupError( + "in 'libraries' option (library '%s'), " + "'sources' must be present and must be " + "a list of source filenames" % lib_name) + + filenames.extend(sources) + return filenames + + + def build_libraries(self, libraries): + for (lib_name, build_info) in libraries: + sources = build_info.get('sources') + if sources is None or not isinstance(sources, (list, tuple)): + raise DistutilsSetupError( + "in 'libraries' option (library '%s'), " + "'sources' must be present and must be " + "a list of source filenames" % lib_name) + sources = list(sources) + + log.info("building '%s' library", lib_name) + + # First, compile the source code to object files in the library + # directory. (This should probably change to putting object + # files in a temporary build directory.) + macros = build_info.get('macros') + include_dirs = build_info.get('include_dirs') + objects = self.compiler.compile(sources, + output_dir=self.build_temp, + macros=macros, + include_dirs=include_dirs, + debug=self.debug) + + # Now "link" the object files together into a static library. + # (On Unix at least, this isn't really linking -- it just + # builds an archive. Whatever.) + self.compiler.create_static_lib(objects, lib_name, + output_dir=self.build_clib, + debug=self.debug) diff --git a/venv/Lib/site-packages/setuptools/_distutils/command/build_ext.py b/venv/Lib/site-packages/setuptools/_distutils/command/build_ext.py new file mode 100644 index 0000000..181671b --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_distutils/command/build_ext.py @@ -0,0 +1,755 @@ +"""distutils.command.build_ext + +Implements the Distutils 'build_ext' command, for building extension +modules (currently limited to C extensions, should accommodate C++ +extensions ASAP).""" + +import contextlib +import os +import re +import sys +from distutils.core import Command +from distutils.errors import * +from distutils.sysconfig import customize_compiler, get_python_version +from distutils.sysconfig import get_config_h_filename +from distutils.dep_util import newer_group +from distutils.extension import Extension +from distutils.util import get_platform +from distutils import log +from . import py37compat + +from site import USER_BASE + +# An extension name is just a dot-separated list of Python NAMEs (ie. +# the same as a fully-qualified module name). +extension_name_re = re.compile \ + (r'^[a-zA-Z_][a-zA-Z_0-9]*(\.[a-zA-Z_][a-zA-Z_0-9]*)*$') + + +def show_compilers (): + from distutils.ccompiler import show_compilers + show_compilers() + + +class build_ext(Command): + + description = "build C/C++ extensions (compile/link to build directory)" + + # XXX thoughts on how to deal with complex command-line options like + # these, i.e. how to make it so fancy_getopt can suck them off the + # command line and make it look like setup.py defined the appropriate + # lists of tuples of what-have-you. + # - each command needs a callback to process its command-line options + # - Command.__init__() needs access to its share of the whole + # command line (must ultimately come from + # Distribution.parse_command_line()) + # - it then calls the current command class' option-parsing + # callback to deal with weird options like -D, which have to + # parse the option text and churn out some custom data + # structure + # - that data structure (in this case, a list of 2-tuples) + # will then be present in the command object by the time + # we get to finalize_options() (i.e. the constructor + # takes care of both command-line and client options + # in between initialize_options() and finalize_options()) + + sep_by = " (separated by '%s')" % os.pathsep + user_options = [ + ('build-lib=', 'b', + "directory for compiled extension modules"), + ('build-temp=', 't', + "directory for temporary files (build by-products)"), + ('plat-name=', 'p', + "platform name to cross-compile for, if supported " + "(default: %s)" % get_platform()), + ('inplace', 'i', + "ignore build-lib and put compiled extensions into the source " + + "directory alongside your pure Python modules"), + ('include-dirs=', 'I', + "list of directories to search for header files" + sep_by), + ('define=', 'D', + "C preprocessor macros to define"), + ('undef=', 'U', + "C preprocessor macros to undefine"), + ('libraries=', 'l', + "external C libraries to link with"), + ('library-dirs=', 'L', + "directories to search for external C libraries" + sep_by), + ('rpath=', 'R', + "directories to search for shared C libraries at runtime"), + ('link-objects=', 'O', + "extra explicit link objects to include in the link"), + ('debug', 'g', + "compile/link with debugging information"), + ('force', 'f', + "forcibly build everything (ignore file timestamps)"), + ('compiler=', 'c', + "specify the compiler type"), + ('parallel=', 'j', + "number of parallel build jobs"), + ('swig-cpp', None, + "make SWIG create C++ files (default is C)"), + ('swig-opts=', None, + "list of SWIG command line options"), + ('swig=', None, + "path to the SWIG executable"), + ('user', None, + "add user include, library and rpath") + ] + + boolean_options = ['inplace', 'debug', 'force', 'swig-cpp', 'user'] + + help_options = [ + ('help-compiler', None, + "list available compilers", show_compilers), + ] + + def initialize_options(self): + self.extensions = None + self.build_lib = None + self.plat_name = None + self.build_temp = None + self.inplace = 0 + self.package = None + + self.include_dirs = None + self.define = None + self.undef = None + self.libraries = None + self.library_dirs = None + self.rpath = None + self.link_objects = None + self.debug = None + self.force = None + self.compiler = None + self.swig = None + self.swig_cpp = None + self.swig_opts = None + self.user = None + self.parallel = None + + def finalize_options(self): + from distutils import sysconfig + + self.set_undefined_options('build', + ('build_lib', 'build_lib'), + ('build_temp', 'build_temp'), + ('compiler', 'compiler'), + ('debug', 'debug'), + ('force', 'force'), + ('parallel', 'parallel'), + ('plat_name', 'plat_name'), + ) + + if self.package is None: + self.package = self.distribution.ext_package + + self.extensions = self.distribution.ext_modules + + # Make sure Python's include directories (for Python.h, pyconfig.h, + # etc.) are in the include search path. + py_include = sysconfig.get_python_inc() + plat_py_include = sysconfig.get_python_inc(plat_specific=1) + if self.include_dirs is None: + self.include_dirs = self.distribution.include_dirs or [] + if isinstance(self.include_dirs, str): + self.include_dirs = self.include_dirs.split(os.pathsep) + + # If in a virtualenv, add its include directory + # Issue 16116 + if sys.exec_prefix != sys.base_exec_prefix: + self.include_dirs.append(os.path.join(sys.exec_prefix, 'include')) + + # Put the Python "system" include dir at the end, so that + # any local include dirs take precedence. + self.include_dirs.extend(py_include.split(os.path.pathsep)) + if plat_py_include != py_include: + self.include_dirs.extend( + plat_py_include.split(os.path.pathsep)) + + self.ensure_string_list('libraries') + self.ensure_string_list('link_objects') + + # Life is easier if we're not forever checking for None, so + # simplify these options to empty lists if unset + if self.libraries is None: + self.libraries = [] + if self.library_dirs is None: + self.library_dirs = [] + elif isinstance(self.library_dirs, str): + self.library_dirs = self.library_dirs.split(os.pathsep) + + if self.rpath is None: + self.rpath = [] + elif isinstance(self.rpath, str): + self.rpath = self.rpath.split(os.pathsep) + + # for extensions under windows use different directories + # for Release and Debug builds. + # also Python's library directory must be appended to library_dirs + if os.name == 'nt': + # the 'libs' directory is for binary installs - we assume that + # must be the *native* platform. But we don't really support + # cross-compiling via a binary install anyway, so we let it go. + self.library_dirs.append(os.path.join(sys.exec_prefix, 'libs')) + if sys.base_exec_prefix != sys.prefix: # Issue 16116 + self.library_dirs.append(os.path.join(sys.base_exec_prefix, 'libs')) + if self.debug: + self.build_temp = os.path.join(self.build_temp, "Debug") + else: + self.build_temp = os.path.join(self.build_temp, "Release") + + # Append the source distribution include and library directories, + # this allows distutils on windows to work in the source tree + self.include_dirs.append(os.path.dirname(get_config_h_filename())) + self.library_dirs.append(sys.base_exec_prefix) + + # Use the .lib files for the correct architecture + if self.plat_name == 'win32': + suffix = 'win32' + else: + # win-amd64 + suffix = self.plat_name[4:] + new_lib = os.path.join(sys.exec_prefix, 'PCbuild') + if suffix: + new_lib = os.path.join(new_lib, suffix) + self.library_dirs.append(new_lib) + + # For extensions under Cygwin, Python's library directory must be + # appended to library_dirs + if sys.platform[:6] == 'cygwin': + if not sysconfig.python_build: + # building third party extensions + self.library_dirs.append(os.path.join(sys.prefix, "lib", + "python" + get_python_version(), + "config")) + else: + # building python standard extensions + self.library_dirs.append('.') + + # For building extensions with a shared Python library, + # Python's library directory must be appended to library_dirs + # See Issues: #1600860, #4366 + if (sysconfig.get_config_var('Py_ENABLE_SHARED')): + if not sysconfig.python_build: + # building third party extensions + self.library_dirs.append(sysconfig.get_config_var('LIBDIR')) + else: + # building python standard extensions + self.library_dirs.append('.') + + # The argument parsing will result in self.define being a string, but + # it has to be a list of 2-tuples. All the preprocessor symbols + # specified by the 'define' option will be set to '1'. Multiple + # symbols can be separated with commas. + + if self.define: + defines = self.define.split(',') + self.define = [(symbol, '1') for symbol in defines] + + # The option for macros to undefine is also a string from the + # option parsing, but has to be a list. Multiple symbols can also + # be separated with commas here. + if self.undef: + self.undef = self.undef.split(',') + + if self.swig_opts is None: + self.swig_opts = [] + else: + self.swig_opts = self.swig_opts.split(' ') + + # Finally add the user include and library directories if requested + if self.user: + user_include = os.path.join(USER_BASE, "include") + user_lib = os.path.join(USER_BASE, "lib") + if os.path.isdir(user_include): + self.include_dirs.append(user_include) + if os.path.isdir(user_lib): + self.library_dirs.append(user_lib) + self.rpath.append(user_lib) + + if isinstance(self.parallel, str): + try: + self.parallel = int(self.parallel) + except ValueError: + raise DistutilsOptionError("parallel should be an integer") + + def run(self): + from distutils.ccompiler import new_compiler + + # 'self.extensions', as supplied by setup.py, is a list of + # Extension instances. See the documentation for Extension (in + # distutils.extension) for details. + # + # For backwards compatibility with Distutils 0.8.2 and earlier, we + # also allow the 'extensions' list to be a list of tuples: + # (ext_name, build_info) + # where build_info is a dictionary containing everything that + # Extension instances do except the name, with a few things being + # differently named. We convert these 2-tuples to Extension + # instances as needed. + + if not self.extensions: + return + + # If we were asked to build any C/C++ libraries, make sure that the + # directory where we put them is in the library search path for + # linking extensions. + if self.distribution.has_c_libraries(): + build_clib = self.get_finalized_command('build_clib') + self.libraries.extend(build_clib.get_library_names() or []) + self.library_dirs.append(build_clib.build_clib) + + # Setup the CCompiler object that we'll use to do all the + # compiling and linking + self.compiler = new_compiler(compiler=self.compiler, + verbose=self.verbose, + dry_run=self.dry_run, + force=self.force) + customize_compiler(self.compiler) + # If we are cross-compiling, init the compiler now (if we are not + # cross-compiling, init would not hurt, but people may rely on + # late initialization of compiler even if they shouldn't...) + if os.name == 'nt' and self.plat_name != get_platform(): + self.compiler.initialize(self.plat_name) + + # And make sure that any compile/link-related options (which might + # come from the command-line or from the setup script) are set in + # that CCompiler object -- that way, they automatically apply to + # all compiling and linking done here. + if self.include_dirs is not None: + self.compiler.set_include_dirs(self.include_dirs) + if self.define is not None: + # 'define' option is a list of (name,value) tuples + for (name, value) in self.define: + self.compiler.define_macro(name, value) + if self.undef is not None: + for macro in self.undef: + self.compiler.undefine_macro(macro) + if self.libraries is not None: + self.compiler.set_libraries(self.libraries) + if self.library_dirs is not None: + self.compiler.set_library_dirs(self.library_dirs) + if self.rpath is not None: + self.compiler.set_runtime_library_dirs(self.rpath) + if self.link_objects is not None: + self.compiler.set_link_objects(self.link_objects) + + # Now actually compile and link everything. + self.build_extensions() + + def check_extensions_list(self, extensions): + """Ensure that the list of extensions (presumably provided as a + command option 'extensions') is valid, i.e. it is a list of + Extension objects. We also support the old-style list of 2-tuples, + where the tuples are (ext_name, build_info), which are converted to + Extension instances here. + + Raise DistutilsSetupError if the structure is invalid anywhere; + just returns otherwise. + """ + if not isinstance(extensions, list): + raise DistutilsSetupError( + "'ext_modules' option must be a list of Extension instances") + + for i, ext in enumerate(extensions): + if isinstance(ext, Extension): + continue # OK! (assume type-checking done + # by Extension constructor) + + if not isinstance(ext, tuple) or len(ext) != 2: + raise DistutilsSetupError( + "each element of 'ext_modules' option must be an " + "Extension instance or 2-tuple") + + ext_name, build_info = ext + + log.warn("old-style (ext_name, build_info) tuple found in " + "ext_modules for extension '%s' " + "-- please convert to Extension instance", ext_name) + + if not (isinstance(ext_name, str) and + extension_name_re.match(ext_name)): + raise DistutilsSetupError( + "first element of each tuple in 'ext_modules' " + "must be the extension name (a string)") + + if not isinstance(build_info, dict): + raise DistutilsSetupError( + "second element of each tuple in 'ext_modules' " + "must be a dictionary (build info)") + + # OK, the (ext_name, build_info) dict is type-safe: convert it + # to an Extension instance. + ext = Extension(ext_name, build_info['sources']) + + # Easy stuff: one-to-one mapping from dict elements to + # instance attributes. + for key in ('include_dirs', 'library_dirs', 'libraries', + 'extra_objects', 'extra_compile_args', + 'extra_link_args'): + val = build_info.get(key) + if val is not None: + setattr(ext, key, val) + + # Medium-easy stuff: same syntax/semantics, different names. + ext.runtime_library_dirs = build_info.get('rpath') + if 'def_file' in build_info: + log.warn("'def_file' element of build info dict " + "no longer supported") + + # Non-trivial stuff: 'macros' split into 'define_macros' + # and 'undef_macros'. + macros = build_info.get('macros') + if macros: + ext.define_macros = [] + ext.undef_macros = [] + for macro in macros: + if not (isinstance(macro, tuple) and len(macro) in (1, 2)): + raise DistutilsSetupError( + "'macros' element of build info dict " + "must be 1- or 2-tuple") + if len(macro) == 1: + ext.undef_macros.append(macro[0]) + elif len(macro) == 2: + ext.define_macros.append(macro) + + extensions[i] = ext + + def get_source_files(self): + self.check_extensions_list(self.extensions) + filenames = [] + + # Wouldn't it be neat if we knew the names of header files too... + for ext in self.extensions: + filenames.extend(ext.sources) + return filenames + + def get_outputs(self): + # Sanity check the 'extensions' list -- can't assume this is being + # done in the same run as a 'build_extensions()' call (in fact, we + # can probably assume that it *isn't*!). + self.check_extensions_list(self.extensions) + + # And build the list of output (built) filenames. Note that this + # ignores the 'inplace' flag, and assumes everything goes in the + # "build" tree. + outputs = [] + for ext in self.extensions: + outputs.append(self.get_ext_fullpath(ext.name)) + return outputs + + def build_extensions(self): + # First, sanity-check the 'extensions' list + self.check_extensions_list(self.extensions) + if self.parallel: + self._build_extensions_parallel() + else: + self._build_extensions_serial() + + def _build_extensions_parallel(self): + workers = self.parallel + if self.parallel is True: + workers = os.cpu_count() # may return None + try: + from concurrent.futures import ThreadPoolExecutor + except ImportError: + workers = None + + if workers is None: + self._build_extensions_serial() + return + + with ThreadPoolExecutor(max_workers=workers) as executor: + futures = [executor.submit(self.build_extension, ext) + for ext in self.extensions] + for ext, fut in zip(self.extensions, futures): + with self._filter_build_errors(ext): + fut.result() + + def _build_extensions_serial(self): + for ext in self.extensions: + with self._filter_build_errors(ext): + self.build_extension(ext) + + @contextlib.contextmanager + def _filter_build_errors(self, ext): + try: + yield + except (CCompilerError, DistutilsError, CompileError) as e: + if not ext.optional: + raise + self.warn('building extension "%s" failed: %s' % + (ext.name, e)) + + def build_extension(self, ext): + sources = ext.sources + if sources is None or not isinstance(sources, (list, tuple)): + raise DistutilsSetupError( + "in 'ext_modules' option (extension '%s'), " + "'sources' must be present and must be " + "a list of source filenames" % ext.name) + # sort to make the resulting .so file build reproducible + sources = sorted(sources) + + ext_path = self.get_ext_fullpath(ext.name) + depends = sources + ext.depends + if not (self.force or newer_group(depends, ext_path, 'newer')): + log.debug("skipping '%s' extension (up-to-date)", ext.name) + return + else: + log.info("building '%s' extension", ext.name) + + # First, scan the sources for SWIG definition files (.i), run + # SWIG on 'em to create .c files, and modify the sources list + # accordingly. + sources = self.swig_sources(sources, ext) + + # Next, compile the source code to object files. + + # XXX not honouring 'define_macros' or 'undef_macros' -- the + # CCompiler API needs to change to accommodate this, and I + # want to do one thing at a time! + + # Two possible sources for extra compiler arguments: + # - 'extra_compile_args' in Extension object + # - CFLAGS environment variable (not particularly + # elegant, but people seem to expect it and I + # guess it's useful) + # The environment variable should take precedence, and + # any sensible compiler will give precedence to later + # command line args. Hence we combine them in order: + extra_args = ext.extra_compile_args or [] + + macros = ext.define_macros[:] + for undef in ext.undef_macros: + macros.append((undef,)) + + objects = self.compiler.compile(sources, + output_dir=self.build_temp, + macros=macros, + include_dirs=ext.include_dirs, + debug=self.debug, + extra_postargs=extra_args, + depends=ext.depends) + + # XXX outdated variable, kept here in case third-part code + # needs it. + self._built_objects = objects[:] + + # Now link the object files together into a "shared object" -- + # of course, first we have to figure out all the other things + # that go into the mix. + if ext.extra_objects: + objects.extend(ext.extra_objects) + extra_args = ext.extra_link_args or [] + + # Detect target language, if not provided + language = ext.language or self.compiler.detect_language(sources) + + self.compiler.link_shared_object( + objects, ext_path, + libraries=self.get_libraries(ext), + library_dirs=ext.library_dirs, + runtime_library_dirs=ext.runtime_library_dirs, + extra_postargs=extra_args, + export_symbols=self.get_export_symbols(ext), + debug=self.debug, + build_temp=self.build_temp, + target_lang=language) + + def swig_sources(self, sources, extension): + """Walk the list of source files in 'sources', looking for SWIG + interface (.i) files. Run SWIG on all that are found, and + return a modified 'sources' list with SWIG source files replaced + by the generated C (or C++) files. + """ + new_sources = [] + swig_sources = [] + swig_targets = {} + + # XXX this drops generated C/C++ files into the source tree, which + # is fine for developers who want to distribute the generated + # source -- but there should be an option to put SWIG output in + # the temp dir. + + if self.swig_cpp: + log.warn("--swig-cpp is deprecated - use --swig-opts=-c++") + + if self.swig_cpp or ('-c++' in self.swig_opts) or \ + ('-c++' in extension.swig_opts): + target_ext = '.cpp' + else: + target_ext = '.c' + + for source in sources: + (base, ext) = os.path.splitext(source) + if ext == ".i": # SWIG interface file + new_sources.append(base + '_wrap' + target_ext) + swig_sources.append(source) + swig_targets[source] = new_sources[-1] + else: + new_sources.append(source) + + if not swig_sources: + return new_sources + + swig = self.swig or self.find_swig() + swig_cmd = [swig, "-python"] + swig_cmd.extend(self.swig_opts) + if self.swig_cpp: + swig_cmd.append("-c++") + + # Do not override commandline arguments + if not self.swig_opts: + for o in extension.swig_opts: + swig_cmd.append(o) + + for source in swig_sources: + target = swig_targets[source] + log.info("swigging %s to %s", source, target) + self.spawn(swig_cmd + ["-o", target, source]) + + return new_sources + + def find_swig(self): + """Return the name of the SWIG executable. On Unix, this is + just "swig" -- it should be in the PATH. Tries a bit harder on + Windows. + """ + if os.name == "posix": + return "swig" + elif os.name == "nt": + # Look for SWIG in its standard installation directory on + # Windows (or so I presume!). If we find it there, great; + # if not, act like Unix and assume it's in the PATH. + for vers in ("1.3", "1.2", "1.1"): + fn = os.path.join("c:\\swig%s" % vers, "swig.exe") + if os.path.isfile(fn): + return fn + else: + return "swig.exe" + else: + raise DistutilsPlatformError( + "I don't know how to find (much less run) SWIG " + "on platform '%s'" % os.name) + + # -- Name generators ----------------------------------------------- + # (extension names, filenames, whatever) + def get_ext_fullpath(self, ext_name): + """Returns the path of the filename for a given extension. + + The file is located in `build_lib` or directly in the package + (inplace option). + """ + fullname = self.get_ext_fullname(ext_name) + modpath = fullname.split('.') + filename = self.get_ext_filename(modpath[-1]) + + if not self.inplace: + # no further work needed + # returning : + # build_dir/package/path/filename + filename = os.path.join(*modpath[:-1]+[filename]) + return os.path.join(self.build_lib, filename) + + # the inplace option requires to find the package directory + # using the build_py command for that + package = '.'.join(modpath[0:-1]) + build_py = self.get_finalized_command('build_py') + package_dir = os.path.abspath(build_py.get_package_dir(package)) + + # returning + # package_dir/filename + return os.path.join(package_dir, filename) + + def get_ext_fullname(self, ext_name): + """Returns the fullname of a given extension name. + + Adds the `package.` prefix""" + if self.package is None: + return ext_name + else: + return self.package + '.' + ext_name + + def get_ext_filename(self, ext_name): + r"""Convert the name of an extension (eg. "foo.bar") into the name + of the file from which it will be loaded (eg. "foo/bar.so", or + "foo\bar.pyd"). + """ + from distutils.sysconfig import get_config_var + ext_path = ext_name.split('.') + ext_suffix = get_config_var('EXT_SUFFIX') + return os.path.join(*ext_path) + ext_suffix + + def get_export_symbols(self, ext): + """Return the list of symbols that a shared extension has to + export. This either uses 'ext.export_symbols' or, if it's not + provided, "PyInit_" + module_name. Only relevant on Windows, where + the .pyd file (DLL) must export the module "PyInit_" function. + """ + name = ext.name.split('.')[-1] + try: + # Unicode module name support as defined in PEP-489 + # https://www.python.org/dev/peps/pep-0489/#export-hook-name + name.encode('ascii') + except UnicodeEncodeError: + suffix = 'U_' + name.encode('punycode').replace(b'-', b'_').decode('ascii') + else: + suffix = "_" + name + + initfunc_name = "PyInit" + suffix + if initfunc_name not in ext.export_symbols: + ext.export_symbols.append(initfunc_name) + return ext.export_symbols + + def get_libraries(self, ext): + """Return the list of libraries to link against when building a + shared extension. On most platforms, this is just 'ext.libraries'; + on Windows, we add the Python library (eg. python20.dll). + """ + # The python library is always needed on Windows. For MSVC, this + # is redundant, since the library is mentioned in a pragma in + # pyconfig.h that MSVC groks. The other Windows compilers all seem + # to need it mentioned explicitly, though, so that's what we do. + # Append '_d' to the python import library on debug builds. + if sys.platform == "win32": + from distutils._msvccompiler import MSVCCompiler + if not isinstance(self.compiler, MSVCCompiler): + template = "python%d%d" + if self.debug: + template = template + '_d' + pythonlib = (template % + (sys.hexversion >> 24, (sys.hexversion >> 16) & 0xff)) + # don't extend ext.libraries, it may be shared with other + # extensions, it is a reference to the original list + return ext.libraries + [pythonlib] + else: + # On Android only the main executable and LD_PRELOADs are considered + # to be RTLD_GLOBAL, all the dependencies of the main executable + # remain RTLD_LOCAL and so the shared libraries must be linked with + # libpython when python is built with a shared python library (issue + # bpo-21536). + # On Cygwin (and if required, other POSIX-like platforms based on + # Windows like MinGW) it is simply necessary that all symbols in + # shared libraries are resolved at link time. + from distutils.sysconfig import get_config_var + link_libpython = False + if get_config_var('Py_ENABLE_SHARED'): + # A native build on an Android device or on Cygwin + if hasattr(sys, 'getandroidapilevel'): + link_libpython = True + elif sys.platform == 'cygwin': + link_libpython = True + elif '_PYTHON_HOST_PLATFORM' in os.environ: + # We are cross-compiling for one of the relevant platforms + if get_config_var('ANDROID_API_LEVEL') != 0: + link_libpython = True + elif get_config_var('MACHDEP') == 'cygwin': + link_libpython = True + + if link_libpython: + ldversion = get_config_var('LDVERSION') + return ext.libraries + ['python' + ldversion] + + return ext.libraries + py37compat.pythonlib() diff --git a/venv/Lib/site-packages/setuptools/_distutils/command/build_py.py b/venv/Lib/site-packages/setuptools/_distutils/command/build_py.py new file mode 100644 index 0000000..7ef9bce --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_distutils/command/build_py.py @@ -0,0 +1,392 @@ +"""distutils.command.build_py + +Implements the Distutils 'build_py' command.""" + +import os +import importlib.util +import sys +import glob + +from distutils.core import Command +from distutils.errors import * +from distutils.util import convert_path +from distutils import log + +class build_py (Command): + + description = "\"build\" pure Python modules (copy to build directory)" + + user_options = [ + ('build-lib=', 'd', "directory to \"build\" (copy) to"), + ('compile', 'c', "compile .py to .pyc"), + ('no-compile', None, "don't compile .py files [default]"), + ('optimize=', 'O', + "also compile with optimization: -O1 for \"python -O\", " + "-O2 for \"python -OO\", and -O0 to disable [default: -O0]"), + ('force', 'f', "forcibly build everything (ignore file timestamps)"), + ] + + boolean_options = ['compile', 'force'] + negative_opt = {'no-compile' : 'compile'} + + def initialize_options(self): + self.build_lib = None + self.py_modules = None + self.package = None + self.package_data = None + self.package_dir = None + self.compile = 0 + self.optimize = 0 + self.force = None + + def finalize_options(self): + self.set_undefined_options('build', + ('build_lib', 'build_lib'), + ('force', 'force')) + + # Get the distribution options that are aliases for build_py + # options -- list of packages and list of modules. + self.packages = self.distribution.packages + self.py_modules = self.distribution.py_modules + self.package_data = self.distribution.package_data + self.package_dir = {} + if self.distribution.package_dir: + for name, path in self.distribution.package_dir.items(): + self.package_dir[name] = convert_path(path) + self.data_files = self.get_data_files() + + # Ick, copied straight from install_lib.py (fancy_getopt needs a + # type system! Hell, *everything* needs a type system!!!) + if not isinstance(self.optimize, int): + try: + self.optimize = int(self.optimize) + assert 0 <= self.optimize <= 2 + except (ValueError, AssertionError): + raise DistutilsOptionError("optimize must be 0, 1, or 2") + + def run(self): + # XXX copy_file by default preserves atime and mtime. IMHO this is + # the right thing to do, but perhaps it should be an option -- in + # particular, a site administrator might want installed files to + # reflect the time of installation rather than the last + # modification time before the installed release. + + # XXX copy_file by default preserves mode, which appears to be the + # wrong thing to do: if a file is read-only in the working + # directory, we want it to be installed read/write so that the next + # installation of the same module distribution can overwrite it + # without problems. (This might be a Unix-specific issue.) Thus + # we turn off 'preserve_mode' when copying to the build directory, + # since the build directory is supposed to be exactly what the + # installation will look like (ie. we preserve mode when + # installing). + + # Two options control which modules will be installed: 'packages' + # and 'py_modules'. The former lets us work with whole packages, not + # specifying individual modules at all; the latter is for + # specifying modules one-at-a-time. + + if self.py_modules: + self.build_modules() + if self.packages: + self.build_packages() + self.build_package_data() + + self.byte_compile(self.get_outputs(include_bytecode=0)) + + def get_data_files(self): + """Generate list of '(package,src_dir,build_dir,filenames)' tuples""" + data = [] + if not self.packages: + return data + for package in self.packages: + # Locate package source directory + src_dir = self.get_package_dir(package) + + # Compute package build directory + build_dir = os.path.join(*([self.build_lib] + package.split('.'))) + + # Length of path to strip from found files + plen = 0 + if src_dir: + plen = len(src_dir)+1 + + # Strip directory from globbed filenames + filenames = [ + file[plen:] for file in self.find_data_files(package, src_dir) + ] + data.append((package, src_dir, build_dir, filenames)) + return data + + def find_data_files(self, package, src_dir): + """Return filenames for package's data files in 'src_dir'""" + globs = (self.package_data.get('', []) + + self.package_data.get(package, [])) + files = [] + for pattern in globs: + # Each pattern has to be converted to a platform-specific path + filelist = glob.glob(os.path.join(glob.escape(src_dir), convert_path(pattern))) + # Files that match more than one pattern are only added once + files.extend([fn for fn in filelist if fn not in files + and os.path.isfile(fn)]) + return files + + def build_package_data(self): + """Copy data files into build directory""" + lastdir = None + for package, src_dir, build_dir, filenames in self.data_files: + for filename in filenames: + target = os.path.join(build_dir, filename) + self.mkpath(os.path.dirname(target)) + self.copy_file(os.path.join(src_dir, filename), target, + preserve_mode=False) + + def get_package_dir(self, package): + """Return the directory, relative to the top of the source + distribution, where package 'package' should be found + (at least according to the 'package_dir' option, if any).""" + path = package.split('.') + + if not self.package_dir: + if path: + return os.path.join(*path) + else: + return '' + else: + tail = [] + while path: + try: + pdir = self.package_dir['.'.join(path)] + except KeyError: + tail.insert(0, path[-1]) + del path[-1] + else: + tail.insert(0, pdir) + return os.path.join(*tail) + else: + # Oops, got all the way through 'path' without finding a + # match in package_dir. If package_dir defines a directory + # for the root (nameless) package, then fallback on it; + # otherwise, we might as well have not consulted + # package_dir at all, as we just use the directory implied + # by 'tail' (which should be the same as the original value + # of 'path' at this point). + pdir = self.package_dir.get('') + if pdir is not None: + tail.insert(0, pdir) + + if tail: + return os.path.join(*tail) + else: + return '' + + def check_package(self, package, package_dir): + # Empty dir name means current directory, which we can probably + # assume exists. Also, os.path.exists and isdir don't know about + # my "empty string means current dir" convention, so we have to + # circumvent them. + if package_dir != "": + if not os.path.exists(package_dir): + raise DistutilsFileError( + "package directory '%s' does not exist" % package_dir) + if not os.path.isdir(package_dir): + raise DistutilsFileError( + "supposed package directory '%s' exists, " + "but is not a directory" % package_dir) + + # Require __init__.py for all but the "root package" + if package: + init_py = os.path.join(package_dir, "__init__.py") + if os.path.isfile(init_py): + return init_py + else: + log.warn(("package init file '%s' not found " + + "(or not a regular file)"), init_py) + + # Either not in a package at all (__init__.py not expected), or + # __init__.py doesn't exist -- so don't return the filename. + return None + + def check_module(self, module, module_file): + if not os.path.isfile(module_file): + log.warn("file %s (for module %s) not found", module_file, module) + return False + else: + return True + + def find_package_modules(self, package, package_dir): + self.check_package(package, package_dir) + module_files = glob.glob(os.path.join(glob.escape(package_dir), "*.py")) + modules = [] + setup_script = os.path.abspath(self.distribution.script_name) + + for f in module_files: + abs_f = os.path.abspath(f) + if abs_f != setup_script: + module = os.path.splitext(os.path.basename(f))[0] + modules.append((package, module, f)) + else: + self.debug_print("excluding %s" % setup_script) + return modules + + def find_modules(self): + """Finds individually-specified Python modules, ie. those listed by + module name in 'self.py_modules'. Returns a list of tuples (package, + module_base, filename): 'package' is a tuple of the path through + package-space to the module; 'module_base' is the bare (no + packages, no dots) module name, and 'filename' is the path to the + ".py" file (relative to the distribution root) that implements the + module. + """ + # Map package names to tuples of useful info about the package: + # (package_dir, checked) + # package_dir - the directory where we'll find source files for + # this package + # checked - true if we have checked that the package directory + # is valid (exists, contains __init__.py, ... ?) + packages = {} + + # List of (package, module, filename) tuples to return + modules = [] + + # We treat modules-in-packages almost the same as toplevel modules, + # just the "package" for a toplevel is empty (either an empty + # string or empty list, depending on context). Differences: + # - don't check for __init__.py in directory for empty package + for module in self.py_modules: + path = module.split('.') + package = '.'.join(path[0:-1]) + module_base = path[-1] + + try: + (package_dir, checked) = packages[package] + except KeyError: + package_dir = self.get_package_dir(package) + checked = 0 + + if not checked: + init_py = self.check_package(package, package_dir) + packages[package] = (package_dir, 1) + if init_py: + modules.append((package, "__init__", init_py)) + + # XXX perhaps we should also check for just .pyc files + # (so greedy closed-source bastards can distribute Python + # modules too) + module_file = os.path.join(package_dir, module_base + ".py") + if not self.check_module(module, module_file): + continue + + modules.append((package, module_base, module_file)) + + return modules + + def find_all_modules(self): + """Compute the list of all modules that will be built, whether + they are specified one-module-at-a-time ('self.py_modules') or + by whole packages ('self.packages'). Return a list of tuples + (package, module, module_file), just like 'find_modules()' and + 'find_package_modules()' do.""" + modules = [] + if self.py_modules: + modules.extend(self.find_modules()) + if self.packages: + for package in self.packages: + package_dir = self.get_package_dir(package) + m = self.find_package_modules(package, package_dir) + modules.extend(m) + return modules + + def get_source_files(self): + return [module[-1] for module in self.find_all_modules()] + + def get_module_outfile(self, build_dir, package, module): + outfile_path = [build_dir] + list(package) + [module + ".py"] + return os.path.join(*outfile_path) + + def get_outputs(self, include_bytecode=1): + modules = self.find_all_modules() + outputs = [] + for (package, module, module_file) in modules: + package = package.split('.') + filename = self.get_module_outfile(self.build_lib, package, module) + outputs.append(filename) + if include_bytecode: + if self.compile: + outputs.append(importlib.util.cache_from_source( + filename, optimization='')) + if self.optimize > 0: + outputs.append(importlib.util.cache_from_source( + filename, optimization=self.optimize)) + + outputs += [ + os.path.join(build_dir, filename) + for package, src_dir, build_dir, filenames in self.data_files + for filename in filenames + ] + + return outputs + + def build_module(self, module, module_file, package): + if isinstance(package, str): + package = package.split('.') + elif not isinstance(package, (list, tuple)): + raise TypeError( + "'package' must be a string (dot-separated), list, or tuple") + + # Now put the module source file into the "build" area -- this is + # easy, we just copy it somewhere under self.build_lib (the build + # directory for Python source). + outfile = self.get_module_outfile(self.build_lib, package, module) + dir = os.path.dirname(outfile) + self.mkpath(dir) + return self.copy_file(module_file, outfile, preserve_mode=0) + + def build_modules(self): + modules = self.find_modules() + for (package, module, module_file) in modules: + # Now "build" the module -- ie. copy the source file to + # self.build_lib (the build directory for Python source). + # (Actually, it gets copied to the directory for this package + # under self.build_lib.) + self.build_module(module, module_file, package) + + def build_packages(self): + for package in self.packages: + # Get list of (package, module, module_file) tuples based on + # scanning the package directory. 'package' is only included + # in the tuple so that 'find_modules()' and + # 'find_package_tuples()' have a consistent interface; it's + # ignored here (apart from a sanity check). Also, 'module' is + # the *unqualified* module name (ie. no dots, no package -- we + # already know its package!), and 'module_file' is the path to + # the .py file, relative to the current directory + # (ie. including 'package_dir'). + package_dir = self.get_package_dir(package) + modules = self.find_package_modules(package, package_dir) + + # Now loop over the modules we found, "building" each one (just + # copy it to self.build_lib). + for (package_, module, module_file) in modules: + assert package == package_ + self.build_module(module, module_file, package) + + def byte_compile(self, files): + if sys.dont_write_bytecode: + self.warn('byte-compiling is disabled, skipping.') + return + + from distutils.util import byte_compile + prefix = self.build_lib + if prefix[-1] != os.sep: + prefix = prefix + os.sep + + # XXX this code is essentially the same as the 'byte_compile() + # method of the "install_lib" command, except for the determination + # of the 'prefix' string. Hmmm. + if self.compile: + byte_compile(files, optimize=0, + force=self.force, prefix=prefix, dry_run=self.dry_run) + if self.optimize > 0: + byte_compile(files, optimize=self.optimize, + force=self.force, prefix=prefix, dry_run=self.dry_run) diff --git a/venv/Lib/site-packages/setuptools/_distutils/command/build_scripts.py b/venv/Lib/site-packages/setuptools/_distutils/command/build_scripts.py new file mode 100644 index 0000000..e3312cf --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_distutils/command/build_scripts.py @@ -0,0 +1,152 @@ +"""distutils.command.build_scripts + +Implements the Distutils 'build_scripts' command.""" + +import os, re +from stat import ST_MODE +from distutils import sysconfig +from distutils.core import Command +from distutils.dep_util import newer +from distutils.util import convert_path +from distutils import log +import tokenize + +# check if Python is called on the first line with this expression +first_line_re = re.compile(b'^#!.*python[0-9.]*([ \t].*)?$') + +class build_scripts(Command): + + description = "\"build\" scripts (copy and fixup #! line)" + + user_options = [ + ('build-dir=', 'd', "directory to \"build\" (copy) to"), + ('force', 'f', "forcibly build everything (ignore file timestamps"), + ('executable=', 'e', "specify final destination interpreter path"), + ] + + boolean_options = ['force'] + + + def initialize_options(self): + self.build_dir = None + self.scripts = None + self.force = None + self.executable = None + self.outfiles = None + + def finalize_options(self): + self.set_undefined_options('build', + ('build_scripts', 'build_dir'), + ('force', 'force'), + ('executable', 'executable')) + self.scripts = self.distribution.scripts + + def get_source_files(self): + return self.scripts + + def run(self): + if not self.scripts: + return + self.copy_scripts() + + + def copy_scripts(self): + r"""Copy each script listed in 'self.scripts'; if it's marked as a + Python script in the Unix way (first line matches 'first_line_re', + ie. starts with "\#!" and contains "python"), then adjust the first + line to refer to the current Python interpreter as we copy. + """ + self.mkpath(self.build_dir) + outfiles = [] + updated_files = [] + for script in self.scripts: + adjust = False + script = convert_path(script) + outfile = os.path.join(self.build_dir, os.path.basename(script)) + outfiles.append(outfile) + + if not self.force and not newer(script, outfile): + log.debug("not copying %s (up-to-date)", script) + continue + + # Always open the file, but ignore failures in dry-run mode -- + # that way, we'll get accurate feedback if we can read the + # script. + try: + f = open(script, "rb") + except OSError: + if not self.dry_run: + raise + f = None + else: + encoding, lines = tokenize.detect_encoding(f.readline) + f.seek(0) + first_line = f.readline() + if not first_line: + self.warn("%s is an empty file (skipping)" % script) + continue + + match = first_line_re.match(first_line) + if match: + adjust = True + post_interp = match.group(1) or b'' + + if adjust: + log.info("copying and adjusting %s -> %s", script, + self.build_dir) + updated_files.append(outfile) + if not self.dry_run: + if not sysconfig.python_build: + executable = self.executable + else: + executable = os.path.join( + sysconfig.get_config_var("BINDIR"), + "python%s%s" % (sysconfig.get_config_var("VERSION"), + sysconfig.get_config_var("EXE"))) + executable = os.fsencode(executable) + shebang = b"#!" + executable + post_interp + b"\n" + # Python parser starts to read a script using UTF-8 until + # it gets a #coding:xxx cookie. The shebang has to be the + # first line of a file, the #coding:xxx cookie cannot be + # written before. So the shebang has to be decodable from + # UTF-8. + try: + shebang.decode('utf-8') + except UnicodeDecodeError: + raise ValueError( + "The shebang ({!r}) is not decodable " + "from utf-8".format(shebang)) + # If the script is encoded to a custom encoding (use a + # #coding:xxx cookie), the shebang has to be decodable from + # the script encoding too. + try: + shebang.decode(encoding) + except UnicodeDecodeError: + raise ValueError( + "The shebang ({!r}) is not decodable " + "from the script encoding ({})" + .format(shebang, encoding)) + with open(outfile, "wb") as outf: + outf.write(shebang) + outf.writelines(f.readlines()) + if f: + f.close() + else: + if f: + f.close() + updated_files.append(outfile) + self.copy_file(script, outfile) + + if os.name == 'posix': + for file in outfiles: + if self.dry_run: + log.info("changing mode of %s", file) + else: + oldmode = os.stat(file)[ST_MODE] & 0o7777 + newmode = (oldmode | 0o555) & 0o7777 + if newmode != oldmode: + log.info("changing mode of %s from %o to %o", + file, oldmode, newmode) + os.chmod(file, newmode) + # XXX should we modify self.outfiles? + return outfiles, updated_files diff --git a/venv/Lib/site-packages/setuptools/_distutils/command/check.py b/venv/Lib/site-packages/setuptools/_distutils/command/check.py new file mode 100644 index 0000000..525540b --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_distutils/command/check.py @@ -0,0 +1,148 @@ +"""distutils.command.check + +Implements the Distutils 'check' command. +""" +from distutils.core import Command +from distutils.errors import DistutilsSetupError + +try: + # docutils is installed + from docutils.utils import Reporter + from docutils.parsers.rst import Parser + from docutils import frontend + from docutils import nodes + + class SilentReporter(Reporter): + + def __init__(self, source, report_level, halt_level, stream=None, + debug=0, encoding='ascii', error_handler='replace'): + self.messages = [] + super().__init__(source, report_level, halt_level, stream, + debug, encoding, error_handler) + + def system_message(self, level, message, *children, **kwargs): + self.messages.append((level, message, children, kwargs)) + return nodes.system_message(message, level=level, + type=self.levels[level], + *children, **kwargs) + + HAS_DOCUTILS = True +except Exception: + # Catch all exceptions because exceptions besides ImportError probably + # indicate that docutils is not ported to Py3k. + HAS_DOCUTILS = False + +class check(Command): + """This command checks the meta-data of the package. + """ + description = ("perform some checks on the package") + user_options = [('metadata', 'm', 'Verify meta-data'), + ('restructuredtext', 'r', + ('Checks if long string meta-data syntax ' + 'are reStructuredText-compliant')), + ('strict', 's', + 'Will exit with an error if a check fails')] + + boolean_options = ['metadata', 'restructuredtext', 'strict'] + + def initialize_options(self): + """Sets default values for options.""" + self.restructuredtext = 0 + self.metadata = 1 + self.strict = 0 + self._warnings = 0 + + def finalize_options(self): + pass + + def warn(self, msg): + """Counts the number of warnings that occurs.""" + self._warnings += 1 + return Command.warn(self, msg) + + def run(self): + """Runs the command.""" + # perform the various tests + if self.metadata: + self.check_metadata() + if self.restructuredtext: + if HAS_DOCUTILS: + self.check_restructuredtext() + elif self.strict: + raise DistutilsSetupError('The docutils package is needed.') + + # let's raise an error in strict mode, if we have at least + # one warning + if self.strict and self._warnings > 0: + raise DistutilsSetupError('Please correct your package.') + + def check_metadata(self): + """Ensures that all required elements of meta-data are supplied. + + Required fields: + name, version, URL + + Recommended fields: + (author and author_email) or (maintainer and maintainer_email)) + + Warns if any are missing. + """ + metadata = self.distribution.metadata + + missing = [] + for attr in ('name', 'version', 'url'): + if not (hasattr(metadata, attr) and getattr(metadata, attr)): + missing.append(attr) + + if missing: + self.warn("missing required meta-data: %s" % ', '.join(missing)) + if metadata.author: + if not metadata.author_email: + self.warn("missing meta-data: if 'author' supplied, " + + "'author_email' should be supplied too") + elif metadata.maintainer: + if not metadata.maintainer_email: + self.warn("missing meta-data: if 'maintainer' supplied, " + + "'maintainer_email' should be supplied too") + else: + self.warn("missing meta-data: either (author and author_email) " + + "or (maintainer and maintainer_email) " + + "should be supplied") + + def check_restructuredtext(self): + """Checks if the long string fields are reST-compliant.""" + data = self.distribution.get_long_description() + for warning in self._check_rst_data(data): + line = warning[-1].get('line') + if line is None: + warning = warning[1] + else: + warning = '%s (line %s)' % (warning[1], line) + self.warn(warning) + + def _check_rst_data(self, data): + """Returns warnings when the provided data doesn't compile.""" + # the include and csv_table directives need this to be a path + source_path = self.distribution.script_name or 'setup.py' + parser = Parser() + settings = frontend.OptionParser(components=(Parser,)).get_default_values() + settings.tab_width = 4 + settings.pep_references = None + settings.rfc_references = None + reporter = SilentReporter(source_path, + settings.report_level, + settings.halt_level, + stream=settings.warning_stream, + debug=settings.debug, + encoding=settings.error_encoding, + error_handler=settings.error_encoding_error_handler) + + document = nodes.document(settings, reporter, source=source_path) + document.note_source(source_path, -1) + try: + parser.parse(data, document) + except AttributeError as e: + reporter.messages.append( + (-1, 'Could not finish the parsing: %s.' % e, '', {})) + + return reporter.messages diff --git a/venv/Lib/site-packages/setuptools/_distutils/command/clean.py b/venv/Lib/site-packages/setuptools/_distutils/command/clean.py new file mode 100644 index 0000000..0cb2701 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_distutils/command/clean.py @@ -0,0 +1,76 @@ +"""distutils.command.clean + +Implements the Distutils 'clean' command.""" + +# contributed by Bastian Kleineidam , added 2000-03-18 + +import os +from distutils.core import Command +from distutils.dir_util import remove_tree +from distutils import log + +class clean(Command): + + description = "clean up temporary files from 'build' command" + user_options = [ + ('build-base=', 'b', + "base build directory (default: 'build.build-base')"), + ('build-lib=', None, + "build directory for all modules (default: 'build.build-lib')"), + ('build-temp=', 't', + "temporary build directory (default: 'build.build-temp')"), + ('build-scripts=', None, + "build directory for scripts (default: 'build.build-scripts')"), + ('bdist-base=', None, + "temporary directory for built distributions"), + ('all', 'a', + "remove all build output, not just temporary by-products") + ] + + boolean_options = ['all'] + + def initialize_options(self): + self.build_base = None + self.build_lib = None + self.build_temp = None + self.build_scripts = None + self.bdist_base = None + self.all = None + + def finalize_options(self): + self.set_undefined_options('build', + ('build_base', 'build_base'), + ('build_lib', 'build_lib'), + ('build_scripts', 'build_scripts'), + ('build_temp', 'build_temp')) + self.set_undefined_options('bdist', + ('bdist_base', 'bdist_base')) + + def run(self): + # remove the build/temp. directory (unless it's already + # gone) + if os.path.exists(self.build_temp): + remove_tree(self.build_temp, dry_run=self.dry_run) + else: + log.debug("'%s' does not exist -- can't clean it", + self.build_temp) + + if self.all: + # remove build directories + for directory in (self.build_lib, + self.bdist_base, + self.build_scripts): + if os.path.exists(directory): + remove_tree(directory, dry_run=self.dry_run) + else: + log.warn("'%s' does not exist -- can't clean it", + directory) + + # just for the heck of it, try to remove the base build directory: + # we might have emptied it right now, but if not we don't care + if not self.dry_run: + try: + os.rmdir(self.build_base) + log.info("removing '%s'", self.build_base) + except OSError: + pass diff --git a/venv/Lib/site-packages/setuptools/_distutils/command/config.py b/venv/Lib/site-packages/setuptools/_distutils/command/config.py new file mode 100644 index 0000000..aeda408 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_distutils/command/config.py @@ -0,0 +1,344 @@ +"""distutils.command.config + +Implements the Distutils 'config' command, a (mostly) empty command class +that exists mainly to be sub-classed by specific module distributions and +applications. The idea is that while every "config" command is different, +at least they're all named the same, and users always see "config" in the +list of standard commands. Also, this is a good place to put common +configure-like tasks: "try to compile this C code", or "figure out where +this header file lives". +""" + +import os, re + +from distutils.core import Command +from distutils.errors import DistutilsExecError +from distutils.sysconfig import customize_compiler +from distutils import log + +LANG_EXT = {"c": ".c", "c++": ".cxx"} + +class config(Command): + + description = "prepare to build" + + user_options = [ + ('compiler=', None, + "specify the compiler type"), + ('cc=', None, + "specify the compiler executable"), + ('include-dirs=', 'I', + "list of directories to search for header files"), + ('define=', 'D', + "C preprocessor macros to define"), + ('undef=', 'U', + "C preprocessor macros to undefine"), + ('libraries=', 'l', + "external C libraries to link with"), + ('library-dirs=', 'L', + "directories to search for external C libraries"), + + ('noisy', None, + "show every action (compile, link, run, ...) taken"), + ('dump-source', None, + "dump generated source files before attempting to compile them"), + ] + + + # The three standard command methods: since the "config" command + # does nothing by default, these are empty. + + def initialize_options(self): + self.compiler = None + self.cc = None + self.include_dirs = None + self.libraries = None + self.library_dirs = None + + # maximal output for now + self.noisy = 1 + self.dump_source = 1 + + # list of temporary files generated along-the-way that we have + # to clean at some point + self.temp_files = [] + + def finalize_options(self): + if self.include_dirs is None: + self.include_dirs = self.distribution.include_dirs or [] + elif isinstance(self.include_dirs, str): + self.include_dirs = self.include_dirs.split(os.pathsep) + + if self.libraries is None: + self.libraries = [] + elif isinstance(self.libraries, str): + self.libraries = [self.libraries] + + if self.library_dirs is None: + self.library_dirs = [] + elif isinstance(self.library_dirs, str): + self.library_dirs = self.library_dirs.split(os.pathsep) + + def run(self): + pass + + # Utility methods for actual "config" commands. The interfaces are + # loosely based on Autoconf macros of similar names. Sub-classes + # may use these freely. + + def _check_compiler(self): + """Check that 'self.compiler' really is a CCompiler object; + if not, make it one. + """ + # We do this late, and only on-demand, because this is an expensive + # import. + from distutils.ccompiler import CCompiler, new_compiler + if not isinstance(self.compiler, CCompiler): + self.compiler = new_compiler(compiler=self.compiler, + dry_run=self.dry_run, force=1) + customize_compiler(self.compiler) + if self.include_dirs: + self.compiler.set_include_dirs(self.include_dirs) + if self.libraries: + self.compiler.set_libraries(self.libraries) + if self.library_dirs: + self.compiler.set_library_dirs(self.library_dirs) + + def _gen_temp_sourcefile(self, body, headers, lang): + filename = "_configtest" + LANG_EXT[lang] + with open(filename, "w") as file: + if headers: + for header in headers: + file.write("#include <%s>\n" % header) + file.write("\n") + file.write(body) + if body[-1] != "\n": + file.write("\n") + return filename + + def _preprocess(self, body, headers, include_dirs, lang): + src = self._gen_temp_sourcefile(body, headers, lang) + out = "_configtest.i" + self.temp_files.extend([src, out]) + self.compiler.preprocess(src, out, include_dirs=include_dirs) + return (src, out) + + def _compile(self, body, headers, include_dirs, lang): + src = self._gen_temp_sourcefile(body, headers, lang) + if self.dump_source: + dump_file(src, "compiling '%s':" % src) + (obj,) = self.compiler.object_filenames([src]) + self.temp_files.extend([src, obj]) + self.compiler.compile([src], include_dirs=include_dirs) + return (src, obj) + + def _link(self, body, headers, include_dirs, libraries, library_dirs, + lang): + (src, obj) = self._compile(body, headers, include_dirs, lang) + prog = os.path.splitext(os.path.basename(src))[0] + self.compiler.link_executable([obj], prog, + libraries=libraries, + library_dirs=library_dirs, + target_lang=lang) + + if self.compiler.exe_extension is not None: + prog = prog + self.compiler.exe_extension + self.temp_files.append(prog) + + return (src, obj, prog) + + def _clean(self, *filenames): + if not filenames: + filenames = self.temp_files + self.temp_files = [] + log.info("removing: %s", ' '.join(filenames)) + for filename in filenames: + try: + os.remove(filename) + except OSError: + pass + + + # XXX these ignore the dry-run flag: what to do, what to do? even if + # you want a dry-run build, you still need some sort of configuration + # info. My inclination is to make it up to the real config command to + # consult 'dry_run', and assume a default (minimal) configuration if + # true. The problem with trying to do it here is that you'd have to + # return either true or false from all the 'try' methods, neither of + # which is correct. + + # XXX need access to the header search path and maybe default macros. + + def try_cpp(self, body=None, headers=None, include_dirs=None, lang="c"): + """Construct a source file from 'body' (a string containing lines + of C/C++ code) and 'headers' (a list of header files to include) + and run it through the preprocessor. Return true if the + preprocessor succeeded, false if there were any errors. + ('body' probably isn't of much use, but what the heck.) + """ + from distutils.ccompiler import CompileError + self._check_compiler() + ok = True + try: + self._preprocess(body, headers, include_dirs, lang) + except CompileError: + ok = False + + self._clean() + return ok + + def search_cpp(self, pattern, body=None, headers=None, include_dirs=None, + lang="c"): + """Construct a source file (just like 'try_cpp()'), run it through + the preprocessor, and return true if any line of the output matches + 'pattern'. 'pattern' should either be a compiled regex object or a + string containing a regex. If both 'body' and 'headers' are None, + preprocesses an empty file -- which can be useful to determine the + symbols the preprocessor and compiler set by default. + """ + self._check_compiler() + src, out = self._preprocess(body, headers, include_dirs, lang) + + if isinstance(pattern, str): + pattern = re.compile(pattern) + + with open(out) as file: + match = False + while True: + line = file.readline() + if line == '': + break + if pattern.search(line): + match = True + break + + self._clean() + return match + + def try_compile(self, body, headers=None, include_dirs=None, lang="c"): + """Try to compile a source file built from 'body' and 'headers'. + Return true on success, false otherwise. + """ + from distutils.ccompiler import CompileError + self._check_compiler() + try: + self._compile(body, headers, include_dirs, lang) + ok = True + except CompileError: + ok = False + + log.info(ok and "success!" or "failure.") + self._clean() + return ok + + def try_link(self, body, headers=None, include_dirs=None, libraries=None, + library_dirs=None, lang="c"): + """Try to compile and link a source file, built from 'body' and + 'headers', to executable form. Return true on success, false + otherwise. + """ + from distutils.ccompiler import CompileError, LinkError + self._check_compiler() + try: + self._link(body, headers, include_dirs, + libraries, library_dirs, lang) + ok = True + except (CompileError, LinkError): + ok = False + + log.info(ok and "success!" or "failure.") + self._clean() + return ok + + def try_run(self, body, headers=None, include_dirs=None, libraries=None, + library_dirs=None, lang="c"): + """Try to compile, link to an executable, and run a program + built from 'body' and 'headers'. Return true on success, false + otherwise. + """ + from distutils.ccompiler import CompileError, LinkError + self._check_compiler() + try: + src, obj, exe = self._link(body, headers, include_dirs, + libraries, library_dirs, lang) + self.spawn([exe]) + ok = True + except (CompileError, LinkError, DistutilsExecError): + ok = False + + log.info(ok and "success!" or "failure.") + self._clean() + return ok + + + # -- High-level methods -------------------------------------------- + # (these are the ones that are actually likely to be useful + # when implementing a real-world config command!) + + def check_func(self, func, headers=None, include_dirs=None, + libraries=None, library_dirs=None, decl=0, call=0): + """Determine if function 'func' is available by constructing a + source file that refers to 'func', and compiles and links it. + If everything succeeds, returns true; otherwise returns false. + + The constructed source file starts out by including the header + files listed in 'headers'. If 'decl' is true, it then declares + 'func' (as "int func()"); you probably shouldn't supply 'headers' + and set 'decl' true in the same call, or you might get errors about + a conflicting declarations for 'func'. Finally, the constructed + 'main()' function either references 'func' or (if 'call' is true) + calls it. 'libraries' and 'library_dirs' are used when + linking. + """ + self._check_compiler() + body = [] + if decl: + body.append("int %s ();" % func) + body.append("int main () {") + if call: + body.append(" %s();" % func) + else: + body.append(" %s;" % func) + body.append("}") + body = "\n".join(body) + "\n" + + return self.try_link(body, headers, include_dirs, + libraries, library_dirs) + + def check_lib(self, library, library_dirs=None, headers=None, + include_dirs=None, other_libraries=[]): + """Determine if 'library' is available to be linked against, + without actually checking that any particular symbols are provided + by it. 'headers' will be used in constructing the source file to + be compiled, but the only effect of this is to check if all the + header files listed are available. Any libraries listed in + 'other_libraries' will be included in the link, in case 'library' + has symbols that depend on other libraries. + """ + self._check_compiler() + return self.try_link("int main (void) { }", headers, include_dirs, + [library] + other_libraries, library_dirs) + + def check_header(self, header, include_dirs=None, library_dirs=None, + lang="c"): + """Determine if the system header file named by 'header_file' + exists and can be found by the preprocessor; return true if so, + false otherwise. + """ + return self.try_cpp(body="/* No body */", headers=[header], + include_dirs=include_dirs) + +def dump_file(filename, head=None): + """Dumps a file content into log.info. + + If head is not None, will be dumped before the file content. + """ + if head is None: + log.info('%s', filename) + else: + log.info(head) + file = open(filename) + try: + log.info(file.read()) + finally: + file.close() diff --git a/venv/Lib/site-packages/setuptools/_distutils/command/install.py b/venv/Lib/site-packages/setuptools/_distutils/command/install.py new file mode 100644 index 0000000..41c17d8 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_distutils/command/install.py @@ -0,0 +1,781 @@ +"""distutils.command.install + +Implements the Distutils 'install' command.""" + +import sys +import os +import contextlib +import sysconfig +import itertools + +from distutils import log +from distutils.core import Command +from distutils.debug import DEBUG +from distutils.sysconfig import get_config_vars +from distutils.errors import DistutilsPlatformError +from distutils.file_util import write_file +from distutils.util import convert_path, subst_vars, change_root +from distutils.util import get_platform +from distutils.errors import DistutilsOptionError +from .. import _collections + +from site import USER_BASE +from site import USER_SITE +HAS_USER_SITE = True + +WINDOWS_SCHEME = { + 'purelib': '{base}/Lib/site-packages', + 'platlib': '{base}/Lib/site-packages', + 'headers': '{base}/Include/{dist_name}', + 'scripts': '{base}/Scripts', + 'data' : '{base}', +} + +INSTALL_SCHEMES = { + 'posix_prefix': { + 'purelib': '{base}/lib/{implementation_lower}{py_version_short}/site-packages', + 'platlib': '{platbase}/{platlibdir}/{implementation_lower}{py_version_short}/site-packages', + 'headers': '{base}/include/{implementation_lower}{py_version_short}{abiflags}/{dist_name}', + 'scripts': '{base}/bin', + 'data' : '{base}', + }, + 'posix_home': { + 'purelib': '{base}/lib/{implementation_lower}', + 'platlib': '{base}/{platlibdir}/{implementation_lower}', + 'headers': '{base}/include/{implementation_lower}/{dist_name}', + 'scripts': '{base}/bin', + 'data' : '{base}', + }, + 'nt': WINDOWS_SCHEME, + 'pypy': { + 'purelib': '{base}/site-packages', + 'platlib': '{base}/site-packages', + 'headers': '{base}/include/{dist_name}', + 'scripts': '{base}/bin', + 'data' : '{base}', + }, + 'pypy_nt': { + 'purelib': '{base}/site-packages', + 'platlib': '{base}/site-packages', + 'headers': '{base}/include/{dist_name}', + 'scripts': '{base}/Scripts', + 'data' : '{base}', + }, + } + +# user site schemes +if HAS_USER_SITE: + INSTALL_SCHEMES['nt_user'] = { + 'purelib': '{usersite}', + 'platlib': '{usersite}', + 'headers': '{userbase}/{implementation}{py_version_nodot_plat}/Include/{dist_name}', + 'scripts': '{userbase}/{implementation}{py_version_nodot_plat}/Scripts', + 'data' : '{userbase}', + } + + INSTALL_SCHEMES['posix_user'] = { + 'purelib': '{usersite}', + 'platlib': '{usersite}', + 'headers': + '{userbase}/include/{implementation_lower}{py_version_short}{abiflags}/{dist_name}', + 'scripts': '{userbase}/bin', + 'data' : '{userbase}', + } + +# The keys to an installation scheme; if any new types of files are to be +# installed, be sure to add an entry to every installation scheme above, +# and to SCHEME_KEYS here. +SCHEME_KEYS = ('purelib', 'platlib', 'headers', 'scripts', 'data') + + +def _load_sysconfig_schemes(): + with contextlib.suppress(AttributeError): + return { + scheme: sysconfig.get_paths(scheme, expand=False) + for scheme in sysconfig.get_scheme_names() + } + + +def _load_schemes(): + """ + Extend default schemes with schemes from sysconfig. + """ + + sysconfig_schemes = _load_sysconfig_schemes() or {} + + return { + scheme: { + **INSTALL_SCHEMES.get(scheme, {}), + **sysconfig_schemes.get(scheme, {}), + } + for scheme in set(itertools.chain(INSTALL_SCHEMES, sysconfig_schemes)) + } + + +def _get_implementation(): + if hasattr(sys, 'pypy_version_info'): + return 'PyPy' + else: + return 'Python' + + +def _select_scheme(ob, name): + scheme = _inject_headers(name, _load_scheme(_resolve_scheme(name))) + vars(ob).update(_remove_set(ob, _scheme_attrs(scheme))) + + +def _remove_set(ob, attrs): + """ + Include only attrs that are None in ob. + """ + return { + key: value + for key, value in attrs.items() + if getattr(ob, key) is None + } + + +def _resolve_scheme(name): + os_name, sep, key = name.partition('_') + try: + resolved = sysconfig.get_preferred_scheme(key) + except Exception: + resolved = _pypy_hack(name) + return resolved + + +def _load_scheme(name): + return _load_schemes()[name] + + +def _inject_headers(name, scheme): + """ + Given a scheme name and the resolved scheme, + if the scheme does not include headers, resolve + the fallback scheme for the name and use headers + from it. pypa/distutils#88 + """ + # Bypass the preferred scheme, which may not + # have defined headers. + fallback = _load_scheme(_pypy_hack(name)) + scheme.setdefault('headers', fallback['headers']) + return scheme + + +def _scheme_attrs(scheme): + """Resolve install directories by applying the install schemes.""" + return { + f'install_{key}': scheme[key] + for key in SCHEME_KEYS + } + + +def _pypy_hack(name): + PY37 = sys.version_info < (3, 8) + old_pypy = hasattr(sys, 'pypy_version_info') and PY37 + prefix = not name.endswith(('_user', '_home')) + pypy_name = 'pypy' + '_nt' * (os.name == 'nt') + return pypy_name if old_pypy and prefix else name + + +class install(Command): + + description = "install everything from build directory" + + user_options = [ + # Select installation scheme and set base director(y|ies) + ('prefix=', None, + "installation prefix"), + ('exec-prefix=', None, + "(Unix only) prefix for platform-specific files"), + ('home=', None, + "(Unix only) home directory to install under"), + + # Or, just set the base director(y|ies) + ('install-base=', None, + "base installation directory (instead of --prefix or --home)"), + ('install-platbase=', None, + "base installation directory for platform-specific files " + + "(instead of --exec-prefix or --home)"), + ('root=', None, + "install everything relative to this alternate root directory"), + + # Or, explicitly set the installation scheme + ('install-purelib=', None, + "installation directory for pure Python module distributions"), + ('install-platlib=', None, + "installation directory for non-pure module distributions"), + ('install-lib=', None, + "installation directory for all module distributions " + + "(overrides --install-purelib and --install-platlib)"), + + ('install-headers=', None, + "installation directory for C/C++ headers"), + ('install-scripts=', None, + "installation directory for Python scripts"), + ('install-data=', None, + "installation directory for data files"), + + # Byte-compilation options -- see install_lib.py for details, as + # these are duplicated from there (but only install_lib does + # anything with them). + ('compile', 'c', "compile .py to .pyc [default]"), + ('no-compile', None, "don't compile .py files"), + ('optimize=', 'O', + "also compile with optimization: -O1 for \"python -O\", " + "-O2 for \"python -OO\", and -O0 to disable [default: -O0]"), + + # Miscellaneous control options + ('force', 'f', + "force installation (overwrite any existing files)"), + ('skip-build', None, + "skip rebuilding everything (for testing/debugging)"), + + # Where to install documentation (eventually!) + #('doc-format=', None, "format of documentation to generate"), + #('install-man=', None, "directory for Unix man pages"), + #('install-html=', None, "directory for HTML documentation"), + #('install-info=', None, "directory for GNU info files"), + + ('record=', None, + "filename in which to record list of installed files"), + ] + + boolean_options = ['compile', 'force', 'skip-build'] + + if HAS_USER_SITE: + user_options.append(('user', None, + "install in user site-package '%s'" % USER_SITE)) + boolean_options.append('user') + + negative_opt = {'no-compile' : 'compile'} + + + def initialize_options(self): + """Initializes options.""" + # High-level options: these select both an installation base + # and scheme. + self.prefix = None + self.exec_prefix = None + self.home = None + self.user = 0 + + # These select only the installation base; it's up to the user to + # specify the installation scheme (currently, that means supplying + # the --install-{platlib,purelib,scripts,data} options). + self.install_base = None + self.install_platbase = None + self.root = None + + # These options are the actual installation directories; if not + # supplied by the user, they are filled in using the installation + # scheme implied by prefix/exec-prefix/home and the contents of + # that installation scheme. + self.install_purelib = None # for pure module distributions + self.install_platlib = None # non-pure (dists w/ extensions) + self.install_headers = None # for C/C++ headers + self.install_lib = None # set to either purelib or platlib + self.install_scripts = None + self.install_data = None + self.install_userbase = USER_BASE + self.install_usersite = USER_SITE + + self.compile = None + self.optimize = None + + # Deprecated + # These two are for putting non-packagized distributions into their + # own directory and creating a .pth file if it makes sense. + # 'extra_path' comes from the setup file; 'install_path_file' can + # be turned off if it makes no sense to install a .pth file. (But + # better to install it uselessly than to guess wrong and not + # install it when it's necessary and would be used!) Currently, + # 'install_path_file' is always true unless some outsider meddles + # with it. + self.extra_path = None + self.install_path_file = 1 + + # 'force' forces installation, even if target files are not + # out-of-date. 'skip_build' skips running the "build" command, + # handy if you know it's not necessary. 'warn_dir' (which is *not* + # a user option, it's just there so the bdist_* commands can turn + # it off) determines whether we warn about installing to a + # directory not in sys.path. + self.force = 0 + self.skip_build = 0 + self.warn_dir = 1 + + # These are only here as a conduit from the 'build' command to the + # 'install_*' commands that do the real work. ('build_base' isn't + # actually used anywhere, but it might be useful in future.) They + # are not user options, because if the user told the install + # command where the build directory is, that wouldn't affect the + # build command. + self.build_base = None + self.build_lib = None + + # Not defined yet because we don't know anything about + # documentation yet. + #self.install_man = None + #self.install_html = None + #self.install_info = None + + self.record = None + + + # -- Option finalizing methods ------------------------------------- + # (This is rather more involved than for most commands, + # because this is where the policy for installing third- + # party Python modules on various platforms given a wide + # array of user input is decided. Yes, it's quite complex!) + + def finalize_options(self): + """Finalizes options.""" + # This method (and its helpers, like 'finalize_unix()', + # 'finalize_other()', and 'select_scheme()') is where the default + # installation directories for modules, extension modules, and + # anything else we care to install from a Python module + # distribution. Thus, this code makes a pretty important policy + # statement about how third-party stuff is added to a Python + # installation! Note that the actual work of installation is done + # by the relatively simple 'install_*' commands; they just take + # their orders from the installation directory options determined + # here. + + # Check for errors/inconsistencies in the options; first, stuff + # that's wrong on any platform. + + if ((self.prefix or self.exec_prefix or self.home) and + (self.install_base or self.install_platbase)): + raise DistutilsOptionError( + "must supply either prefix/exec-prefix/home or " + + "install-base/install-platbase -- not both") + + if self.home and (self.prefix or self.exec_prefix): + raise DistutilsOptionError( + "must supply either home or prefix/exec-prefix -- not both") + + if self.user and (self.prefix or self.exec_prefix or self.home or + self.install_base or self.install_platbase): + raise DistutilsOptionError("can't combine user with prefix, " + "exec_prefix/home, or install_(plat)base") + + # Next, stuff that's wrong (or dubious) only on certain platforms. + if os.name != "posix": + if self.exec_prefix: + self.warn("exec-prefix option ignored on this platform") + self.exec_prefix = None + + # Now the interesting logic -- so interesting that we farm it out + # to other methods. The goal of these methods is to set the final + # values for the install_{lib,scripts,data,...} options, using as + # input a heady brew of prefix, exec_prefix, home, install_base, + # install_platbase, user-supplied versions of + # install_{purelib,platlib,lib,scripts,data,...}, and the + # install schemes. Phew! + + self.dump_dirs("pre-finalize_{unix,other}") + + if os.name == 'posix': + self.finalize_unix() + else: + self.finalize_other() + + self.dump_dirs("post-finalize_{unix,other}()") + + # Expand configuration variables, tilde, etc. in self.install_base + # and self.install_platbase -- that way, we can use $base or + # $platbase in the other installation directories and not worry + # about needing recursive variable expansion (shudder). + + py_version = sys.version.split()[0] + (prefix, exec_prefix) = get_config_vars('prefix', 'exec_prefix') + try: + abiflags = sys.abiflags + except AttributeError: + # sys.abiflags may not be defined on all platforms. + abiflags = '' + local_vars = { + 'dist_name': self.distribution.get_name(), + 'dist_version': self.distribution.get_version(), + 'dist_fullname': self.distribution.get_fullname(), + 'py_version': py_version, + 'py_version_short': '%d.%d' % sys.version_info[:2], + 'py_version_nodot': '%d%d' % sys.version_info[:2], + 'sys_prefix': prefix, + 'prefix': prefix, + 'sys_exec_prefix': exec_prefix, + 'exec_prefix': exec_prefix, + 'abiflags': abiflags, + 'platlibdir': getattr(sys, 'platlibdir', 'lib'), + 'implementation_lower': _get_implementation().lower(), + 'implementation': _get_implementation(), + } + + # vars for compatibility on older Pythons + compat_vars = dict( + # Python 3.9 and earlier + py_version_nodot_plat=getattr(sys, 'winver', '').replace('.', ''), + ) + + if HAS_USER_SITE: + local_vars['userbase'] = self.install_userbase + local_vars['usersite'] = self.install_usersite + + self.config_vars = _collections.DictStack( + [compat_vars, sysconfig.get_config_vars(), local_vars]) + + self.expand_basedirs() + + self.dump_dirs("post-expand_basedirs()") + + # Now define config vars for the base directories so we can expand + # everything else. + local_vars['base'] = self.install_base + local_vars['platbase'] = self.install_platbase + + if DEBUG: + from pprint import pprint + print("config vars:") + pprint(dict(self.config_vars)) + + # Expand "~" and configuration variables in the installation + # directories. + self.expand_dirs() + + self.dump_dirs("post-expand_dirs()") + + # Create directories in the home dir: + if self.user: + self.create_home_path() + + # Pick the actual directory to install all modules to: either + # install_purelib or install_platlib, depending on whether this + # module distribution is pure or not. Of course, if the user + # already specified install_lib, use their selection. + if self.install_lib is None: + if self.distribution.has_ext_modules(): # has extensions: non-pure + self.install_lib = self.install_platlib + else: + self.install_lib = self.install_purelib + + + # Convert directories from Unix /-separated syntax to the local + # convention. + self.convert_paths('lib', 'purelib', 'platlib', + 'scripts', 'data', 'headers', + 'userbase', 'usersite') + + # Deprecated + # Well, we're not actually fully completely finalized yet: we still + # have to deal with 'extra_path', which is the hack for allowing + # non-packagized module distributions (hello, Numerical Python!) to + # get their own directories. + self.handle_extra_path() + self.install_libbase = self.install_lib # needed for .pth file + self.install_lib = os.path.join(self.install_lib, self.extra_dirs) + + # If a new root directory was supplied, make all the installation + # dirs relative to it. + if self.root is not None: + self.change_roots('libbase', 'lib', 'purelib', 'platlib', + 'scripts', 'data', 'headers') + + self.dump_dirs("after prepending root") + + # Find out the build directories, ie. where to install from. + self.set_undefined_options('build', + ('build_base', 'build_base'), + ('build_lib', 'build_lib')) + + # Punt on doc directories for now -- after all, we're punting on + # documentation completely! + + def dump_dirs(self, msg): + """Dumps the list of user options.""" + if not DEBUG: + return + from distutils.fancy_getopt import longopt_xlate + log.debug(msg + ":") + for opt in self.user_options: + opt_name = opt[0] + if opt_name[-1] == "=": + opt_name = opt_name[0:-1] + if opt_name in self.negative_opt: + opt_name = self.negative_opt[opt_name] + opt_name = opt_name.translate(longopt_xlate) + val = not getattr(self, opt_name) + else: + opt_name = opt_name.translate(longopt_xlate) + val = getattr(self, opt_name) + log.debug(" %s: %s", opt_name, val) + + def finalize_unix(self): + """Finalizes options for posix platforms.""" + if self.install_base is not None or self.install_platbase is not None: + incomplete_scheme = ( + ( + self.install_lib is None and + self.install_purelib is None and + self.install_platlib is None + ) or + self.install_headers is None or + self.install_scripts is None or + self.install_data is None + ) + if incomplete_scheme: + raise DistutilsOptionError( + "install-base or install-platbase supplied, but " + "installation scheme is incomplete") + return + + if self.user: + if self.install_userbase is None: + raise DistutilsPlatformError( + "User base directory is not specified") + self.install_base = self.install_platbase = self.install_userbase + self.select_scheme("posix_user") + elif self.home is not None: + self.install_base = self.install_platbase = self.home + self.select_scheme("posix_home") + else: + if self.prefix is None: + if self.exec_prefix is not None: + raise DistutilsOptionError( + "must not supply exec-prefix without prefix") + + # Allow Fedora to add components to the prefix + _prefix_addition = getattr(sysconfig, '_prefix_addition', "") + + self.prefix = ( + os.path.normpath(sys.prefix) + _prefix_addition) + self.exec_prefix = ( + os.path.normpath(sys.exec_prefix) + _prefix_addition) + + else: + if self.exec_prefix is None: + self.exec_prefix = self.prefix + + self.install_base = self.prefix + self.install_platbase = self.exec_prefix + self.select_scheme("posix_prefix") + + def finalize_other(self): + """Finalizes options for non-posix platforms""" + if self.user: + if self.install_userbase is None: + raise DistutilsPlatformError( + "User base directory is not specified") + self.install_base = self.install_platbase = self.install_userbase + self.select_scheme(os.name + "_user") + elif self.home is not None: + self.install_base = self.install_platbase = self.home + self.select_scheme("posix_home") + else: + if self.prefix is None: + self.prefix = os.path.normpath(sys.prefix) + + self.install_base = self.install_platbase = self.prefix + try: + self.select_scheme(os.name) + except KeyError: + raise DistutilsPlatformError( + "I don't know how to install stuff on '%s'" % os.name) + + def select_scheme(self, name): + _select_scheme(self, name) + + def _expand_attrs(self, attrs): + for attr in attrs: + val = getattr(self, attr) + if val is not None: + if os.name == 'posix' or os.name == 'nt': + val = os.path.expanduser(val) + val = subst_vars(val, self.config_vars) + setattr(self, attr, val) + + def expand_basedirs(self): + """Calls `os.path.expanduser` on install_base, install_platbase and + root.""" + self._expand_attrs(['install_base', 'install_platbase', 'root']) + + def expand_dirs(self): + """Calls `os.path.expanduser` on install dirs.""" + self._expand_attrs(['install_purelib', 'install_platlib', + 'install_lib', 'install_headers', + 'install_scripts', 'install_data',]) + + def convert_paths(self, *names): + """Call `convert_path` over `names`.""" + for name in names: + attr = "install_" + name + setattr(self, attr, convert_path(getattr(self, attr))) + + def handle_extra_path(self): + """Set `path_file` and `extra_dirs` using `extra_path`.""" + if self.extra_path is None: + self.extra_path = self.distribution.extra_path + + if self.extra_path is not None: + log.warn( + "Distribution option extra_path is deprecated. " + "See issue27919 for details." + ) + if isinstance(self.extra_path, str): + self.extra_path = self.extra_path.split(',') + + if len(self.extra_path) == 1: + path_file = extra_dirs = self.extra_path[0] + elif len(self.extra_path) == 2: + path_file, extra_dirs = self.extra_path + else: + raise DistutilsOptionError( + "'extra_path' option must be a list, tuple, or " + "comma-separated string with 1 or 2 elements") + + # convert to local form in case Unix notation used (as it + # should be in setup scripts) + extra_dirs = convert_path(extra_dirs) + else: + path_file = None + extra_dirs = '' + + # XXX should we warn if path_file and not extra_dirs? (in which + # case the path file would be harmless but pointless) + self.path_file = path_file + self.extra_dirs = extra_dirs + + def change_roots(self, *names): + """Change the install directories pointed by name using root.""" + for name in names: + attr = "install_" + name + setattr(self, attr, change_root(self.root, getattr(self, attr))) + + def create_home_path(self): + """Create directories under ~.""" + if not self.user: + return + home = convert_path(os.path.expanduser("~")) + for name, path in self.config_vars.items(): + if str(path).startswith(home) and not os.path.isdir(path): + self.debug_print("os.makedirs('%s', 0o700)" % path) + os.makedirs(path, 0o700) + + # -- Command execution methods ------------------------------------- + + def run(self): + """Runs the command.""" + # Obviously have to build before we can install + if not self.skip_build: + self.run_command('build') + # If we built for any other platform, we can't install. + build_plat = self.distribution.get_command_obj('build').plat_name + # check warn_dir - it is a clue that the 'install' is happening + # internally, and not to sys.path, so we don't check the platform + # matches what we are running. + if self.warn_dir and build_plat != get_platform(): + raise DistutilsPlatformError("Can't install when " + "cross-compiling") + + # Run all sub-commands (at least those that need to be run) + for cmd_name in self.get_sub_commands(): + self.run_command(cmd_name) + + if self.path_file: + self.create_path_file() + + # write list of installed files, if requested. + if self.record: + outputs = self.get_outputs() + if self.root: # strip any package prefix + root_len = len(self.root) + for counter in range(len(outputs)): + outputs[counter] = outputs[counter][root_len:] + self.execute(write_file, + (self.record, outputs), + "writing list of installed files to '%s'" % + self.record) + + sys_path = map(os.path.normpath, sys.path) + sys_path = map(os.path.normcase, sys_path) + install_lib = os.path.normcase(os.path.normpath(self.install_lib)) + if (self.warn_dir and + not (self.path_file and self.install_path_file) and + install_lib not in sys_path): + log.debug(("modules installed to '%s', which is not in " + "Python's module search path (sys.path) -- " + "you'll have to change the search path yourself"), + self.install_lib) + + def create_path_file(self): + """Creates the .pth file""" + filename = os.path.join(self.install_libbase, + self.path_file + ".pth") + if self.install_path_file: + self.execute(write_file, + (filename, [self.extra_dirs]), + "creating %s" % filename) + else: + self.warn("path file '%s' not created" % filename) + + + # -- Reporting methods --------------------------------------------- + + def get_outputs(self): + """Assembles the outputs of all the sub-commands.""" + outputs = [] + for cmd_name in self.get_sub_commands(): + cmd = self.get_finalized_command(cmd_name) + # Add the contents of cmd.get_outputs(), ensuring + # that outputs doesn't contain duplicate entries + for filename in cmd.get_outputs(): + if filename not in outputs: + outputs.append(filename) + + if self.path_file and self.install_path_file: + outputs.append(os.path.join(self.install_libbase, + self.path_file + ".pth")) + + return outputs + + def get_inputs(self): + """Returns the inputs of all the sub-commands""" + # XXX gee, this looks familiar ;-( + inputs = [] + for cmd_name in self.get_sub_commands(): + cmd = self.get_finalized_command(cmd_name) + inputs.extend(cmd.get_inputs()) + + return inputs + + # -- Predicates for sub-command list ------------------------------- + + def has_lib(self): + """Returns true if the current distribution has any Python + modules to install.""" + return (self.distribution.has_pure_modules() or + self.distribution.has_ext_modules()) + + def has_headers(self): + """Returns true if the current distribution has any headers to + install.""" + return self.distribution.has_headers() + + def has_scripts(self): + """Returns true if the current distribution has any scripts to. + install.""" + return self.distribution.has_scripts() + + def has_data(self): + """Returns true if the current distribution has any data to. + install.""" + return self.distribution.has_data_files() + + # 'sub_commands': a list of commands this command might have to run to + # get its work done. See cmd.py for more info. + sub_commands = [('install_lib', has_lib), + ('install_headers', has_headers), + ('install_scripts', has_scripts), + ('install_data', has_data), + ('install_egg_info', lambda self:True), + ] diff --git a/venv/Lib/site-packages/setuptools/_distutils/command/install_data.py b/venv/Lib/site-packages/setuptools/_distutils/command/install_data.py new file mode 100644 index 0000000..947cd76 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_distutils/command/install_data.py @@ -0,0 +1,79 @@ +"""distutils.command.install_data + +Implements the Distutils 'install_data' command, for installing +platform-independent data files.""" + +# contributed by Bastian Kleineidam + +import os +from distutils.core import Command +from distutils.util import change_root, convert_path + +class install_data(Command): + + description = "install data files" + + user_options = [ + ('install-dir=', 'd', + "base directory for installing data files " + "(default: installation base dir)"), + ('root=', None, + "install everything relative to this alternate root directory"), + ('force', 'f', "force installation (overwrite existing files)"), + ] + + boolean_options = ['force'] + + def initialize_options(self): + self.install_dir = None + self.outfiles = [] + self.root = None + self.force = 0 + self.data_files = self.distribution.data_files + self.warn_dir = 1 + + def finalize_options(self): + self.set_undefined_options('install', + ('install_data', 'install_dir'), + ('root', 'root'), + ('force', 'force'), + ) + + def run(self): + self.mkpath(self.install_dir) + for f in self.data_files: + if isinstance(f, str): + # it's a simple file, so copy it + f = convert_path(f) + if self.warn_dir: + self.warn("setup script did not provide a directory for " + "'%s' -- installing right in '%s'" % + (f, self.install_dir)) + (out, _) = self.copy_file(f, self.install_dir) + self.outfiles.append(out) + else: + # it's a tuple with path to install to and a list of files + dir = convert_path(f[0]) + if not os.path.isabs(dir): + dir = os.path.join(self.install_dir, dir) + elif self.root: + dir = change_root(self.root, dir) + self.mkpath(dir) + + if f[1] == []: + # If there are no files listed, the user must be + # trying to create an empty directory, so add the + # directory to the list of output files. + self.outfiles.append(dir) + else: + # Copy files, adding them to the list of output files. + for data in f[1]: + data = convert_path(data) + (out, _) = self.copy_file(data, dir) + self.outfiles.append(out) + + def get_inputs(self): + return self.data_files or [] + + def get_outputs(self): + return self.outfiles diff --git a/venv/Lib/site-packages/setuptools/_distutils/command/install_egg_info.py b/venv/Lib/site-packages/setuptools/_distutils/command/install_egg_info.py new file mode 100644 index 0000000..adc0323 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_distutils/command/install_egg_info.py @@ -0,0 +1,84 @@ +"""distutils.command.install_egg_info + +Implements the Distutils 'install_egg_info' command, for installing +a package's PKG-INFO metadata.""" + + +from distutils.cmd import Command +from distutils import log, dir_util +import os, sys, re + +class install_egg_info(Command): + """Install an .egg-info file for the package""" + + description = "Install package's PKG-INFO metadata as an .egg-info file" + user_options = [ + ('install-dir=', 'd', "directory to install to"), + ] + + def initialize_options(self): + self.install_dir = None + + @property + def basename(self): + """ + Allow basename to be overridden by child class. + Ref pypa/distutils#2. + """ + return "%s-%s-py%d.%d.egg-info" % ( + to_filename(safe_name(self.distribution.get_name())), + to_filename(safe_version(self.distribution.get_version())), + *sys.version_info[:2] + ) + + def finalize_options(self): + self.set_undefined_options('install_lib',('install_dir','install_dir')) + self.target = os.path.join(self.install_dir, self.basename) + self.outputs = [self.target] + + def run(self): + target = self.target + if os.path.isdir(target) and not os.path.islink(target): + dir_util.remove_tree(target, dry_run=self.dry_run) + elif os.path.exists(target): + self.execute(os.unlink,(self.target,),"Removing "+target) + elif not os.path.isdir(self.install_dir): + self.execute(os.makedirs, (self.install_dir,), + "Creating "+self.install_dir) + log.info("Writing %s", target) + if not self.dry_run: + with open(target, 'w', encoding='UTF-8') as f: + self.distribution.metadata.write_pkg_file(f) + + def get_outputs(self): + return self.outputs + + +# The following routines are taken from setuptools' pkg_resources module and +# can be replaced by importing them from pkg_resources once it is included +# in the stdlib. + +def safe_name(name): + """Convert an arbitrary string to a standard distribution name + + Any runs of non-alphanumeric/. characters are replaced with a single '-'. + """ + return re.sub('[^A-Za-z0-9.]+', '-', name) + + +def safe_version(version): + """Convert an arbitrary string to a standard version string + + Spaces become dots, and all other non-alphanumeric characters become + dashes, with runs of multiple dashes condensed to a single dash. + """ + version = version.replace(' ','.') + return re.sub('[^A-Za-z0-9.]+', '-', version) + + +def to_filename(name): + """Convert a project or version name to its filename-escaped form + + Any '-' characters are currently replaced with '_'. + """ + return name.replace('-','_') diff --git a/venv/Lib/site-packages/setuptools/_distutils/command/install_headers.py b/venv/Lib/site-packages/setuptools/_distutils/command/install_headers.py new file mode 100644 index 0000000..9bb0b18 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_distutils/command/install_headers.py @@ -0,0 +1,47 @@ +"""distutils.command.install_headers + +Implements the Distutils 'install_headers' command, to install C/C++ header +files to the Python include directory.""" + +from distutils.core import Command + + +# XXX force is never used +class install_headers(Command): + + description = "install C/C++ header files" + + user_options = [('install-dir=', 'd', + "directory to install header files to"), + ('force', 'f', + "force installation (overwrite existing files)"), + ] + + boolean_options = ['force'] + + def initialize_options(self): + self.install_dir = None + self.force = 0 + self.outfiles = [] + + def finalize_options(self): + self.set_undefined_options('install', + ('install_headers', 'install_dir'), + ('force', 'force')) + + + def run(self): + headers = self.distribution.headers + if not headers: + return + + self.mkpath(self.install_dir) + for header in headers: + (out, _) = self.copy_file(header, self.install_dir) + self.outfiles.append(out) + + def get_inputs(self): + return self.distribution.headers or [] + + def get_outputs(self): + return self.outfiles diff --git a/venv/Lib/site-packages/setuptools/_distutils/command/install_lib.py b/venv/Lib/site-packages/setuptools/_distutils/command/install_lib.py new file mode 100644 index 0000000..6154cf0 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_distutils/command/install_lib.py @@ -0,0 +1,217 @@ +"""distutils.command.install_lib + +Implements the Distutils 'install_lib' command +(install all Python modules).""" + +import os +import importlib.util +import sys + +from distutils.core import Command +from distutils.errors import DistutilsOptionError + + +# Extension for Python source files. +PYTHON_SOURCE_EXTENSION = ".py" + +class install_lib(Command): + + description = "install all Python modules (extensions and pure Python)" + + # The byte-compilation options are a tad confusing. Here are the + # possible scenarios: + # 1) no compilation at all (--no-compile --no-optimize) + # 2) compile .pyc only (--compile --no-optimize; default) + # 3) compile .pyc and "opt-1" .pyc (--compile --optimize) + # 4) compile "opt-1" .pyc only (--no-compile --optimize) + # 5) compile .pyc and "opt-2" .pyc (--compile --optimize-more) + # 6) compile "opt-2" .pyc only (--no-compile --optimize-more) + # + # The UI for this is two options, 'compile' and 'optimize'. + # 'compile' is strictly boolean, and only decides whether to + # generate .pyc files. 'optimize' is three-way (0, 1, or 2), and + # decides both whether to generate .pyc files and what level of + # optimization to use. + + user_options = [ + ('install-dir=', 'd', "directory to install to"), + ('build-dir=','b', "build directory (where to install from)"), + ('force', 'f', "force installation (overwrite existing files)"), + ('compile', 'c', "compile .py to .pyc [default]"), + ('no-compile', None, "don't compile .py files"), + ('optimize=', 'O', + "also compile with optimization: -O1 for \"python -O\", " + "-O2 for \"python -OO\", and -O0 to disable [default: -O0]"), + ('skip-build', None, "skip the build steps"), + ] + + boolean_options = ['force', 'compile', 'skip-build'] + negative_opt = {'no-compile' : 'compile'} + + def initialize_options(self): + # let the 'install' command dictate our installation directory + self.install_dir = None + self.build_dir = None + self.force = 0 + self.compile = None + self.optimize = None + self.skip_build = None + + def finalize_options(self): + # Get all the information we need to install pure Python modules + # from the umbrella 'install' command -- build (source) directory, + # install (target) directory, and whether to compile .py files. + self.set_undefined_options('install', + ('build_lib', 'build_dir'), + ('install_lib', 'install_dir'), + ('force', 'force'), + ('compile', 'compile'), + ('optimize', 'optimize'), + ('skip_build', 'skip_build'), + ) + + if self.compile is None: + self.compile = True + if self.optimize is None: + self.optimize = False + + if not isinstance(self.optimize, int): + try: + self.optimize = int(self.optimize) + if self.optimize not in (0, 1, 2): + raise AssertionError + except (ValueError, AssertionError): + raise DistutilsOptionError("optimize must be 0, 1, or 2") + + def run(self): + # Make sure we have built everything we need first + self.build() + + # Install everything: simply dump the entire contents of the build + # directory to the installation directory (that's the beauty of + # having a build directory!) + outfiles = self.install() + + # (Optionally) compile .py to .pyc + if outfiles is not None and self.distribution.has_pure_modules(): + self.byte_compile(outfiles) + + # -- Top-level worker functions ------------------------------------ + # (called from 'run()') + + def build(self): + if not self.skip_build: + if self.distribution.has_pure_modules(): + self.run_command('build_py') + if self.distribution.has_ext_modules(): + self.run_command('build_ext') + + def install(self): + if os.path.isdir(self.build_dir): + outfiles = self.copy_tree(self.build_dir, self.install_dir) + else: + self.warn("'%s' does not exist -- no Python modules to install" % + self.build_dir) + return + return outfiles + + def byte_compile(self, files): + if sys.dont_write_bytecode: + self.warn('byte-compiling is disabled, skipping.') + return + + from distutils.util import byte_compile + + # Get the "--root" directory supplied to the "install" command, + # and use it as a prefix to strip off the purported filename + # encoded in bytecode files. This is far from complete, but it + # should at least generate usable bytecode in RPM distributions. + install_root = self.get_finalized_command('install').root + + if self.compile: + byte_compile(files, optimize=0, + force=self.force, prefix=install_root, + dry_run=self.dry_run) + if self.optimize > 0: + byte_compile(files, optimize=self.optimize, + force=self.force, prefix=install_root, + verbose=self.verbose, dry_run=self.dry_run) + + + # -- Utility methods ----------------------------------------------- + + def _mutate_outputs(self, has_any, build_cmd, cmd_option, output_dir): + if not has_any: + return [] + + build_cmd = self.get_finalized_command(build_cmd) + build_files = build_cmd.get_outputs() + build_dir = getattr(build_cmd, cmd_option) + + prefix_len = len(build_dir) + len(os.sep) + outputs = [] + for file in build_files: + outputs.append(os.path.join(output_dir, file[prefix_len:])) + + return outputs + + def _bytecode_filenames(self, py_filenames): + bytecode_files = [] + for py_file in py_filenames: + # Since build_py handles package data installation, the + # list of outputs can contain more than just .py files. + # Make sure we only report bytecode for the .py files. + ext = os.path.splitext(os.path.normcase(py_file))[1] + if ext != PYTHON_SOURCE_EXTENSION: + continue + if self.compile: + bytecode_files.append(importlib.util.cache_from_source( + py_file, optimization='')) + if self.optimize > 0: + bytecode_files.append(importlib.util.cache_from_source( + py_file, optimization=self.optimize)) + + return bytecode_files + + + # -- External interface -------------------------------------------- + # (called by outsiders) + + def get_outputs(self): + """Return the list of files that would be installed if this command + were actually run. Not affected by the "dry-run" flag or whether + modules have actually been built yet. + """ + pure_outputs = \ + self._mutate_outputs(self.distribution.has_pure_modules(), + 'build_py', 'build_lib', + self.install_dir) + if self.compile: + bytecode_outputs = self._bytecode_filenames(pure_outputs) + else: + bytecode_outputs = [] + + ext_outputs = \ + self._mutate_outputs(self.distribution.has_ext_modules(), + 'build_ext', 'build_lib', + self.install_dir) + + return pure_outputs + bytecode_outputs + ext_outputs + + def get_inputs(self): + """Get the list of files that are input to this command, ie. the + files that get installed as they are named in the build tree. + The files in this list correspond one-to-one to the output + filenames returned by 'get_outputs()'. + """ + inputs = [] + + if self.distribution.has_pure_modules(): + build_py = self.get_finalized_command('build_py') + inputs.extend(build_py.get_outputs()) + + if self.distribution.has_ext_modules(): + build_ext = self.get_finalized_command('build_ext') + inputs.extend(build_ext.get_outputs()) + + return inputs diff --git a/venv/Lib/site-packages/setuptools/_distutils/command/install_scripts.py b/venv/Lib/site-packages/setuptools/_distutils/command/install_scripts.py new file mode 100644 index 0000000..31a1130 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_distutils/command/install_scripts.py @@ -0,0 +1,60 @@ +"""distutils.command.install_scripts + +Implements the Distutils 'install_scripts' command, for installing +Python scripts.""" + +# contributed by Bastian Kleineidam + +import os +from distutils.core import Command +from distutils import log +from stat import ST_MODE + + +class install_scripts(Command): + + description = "install scripts (Python or otherwise)" + + user_options = [ + ('install-dir=', 'd', "directory to install scripts to"), + ('build-dir=','b', "build directory (where to install from)"), + ('force', 'f', "force installation (overwrite existing files)"), + ('skip-build', None, "skip the build steps"), + ] + + boolean_options = ['force', 'skip-build'] + + def initialize_options(self): + self.install_dir = None + self.force = 0 + self.build_dir = None + self.skip_build = None + + def finalize_options(self): + self.set_undefined_options('build', ('build_scripts', 'build_dir')) + self.set_undefined_options('install', + ('install_scripts', 'install_dir'), + ('force', 'force'), + ('skip_build', 'skip_build'), + ) + + def run(self): + if not self.skip_build: + self.run_command('build_scripts') + self.outfiles = self.copy_tree(self.build_dir, self.install_dir) + if os.name == 'posix': + # Set the executable bits (owner, group, and world) on + # all the scripts we just installed. + for file in self.get_outputs(): + if self.dry_run: + log.info("changing mode of %s", file) + else: + mode = ((os.stat(file)[ST_MODE]) | 0o555) & 0o7777 + log.info("changing mode of %s to %o", file, mode) + os.chmod(file, mode) + + def get_inputs(self): + return self.distribution.scripts or [] + + def get_outputs(self): + return self.outfiles or [] diff --git a/venv/Lib/site-packages/setuptools/_distutils/command/py37compat.py b/venv/Lib/site-packages/setuptools/_distutils/command/py37compat.py new file mode 100644 index 0000000..754715a --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_distutils/command/py37compat.py @@ -0,0 +1,30 @@ +import sys + + +def _pythonlib_compat(): + """ + On Python 3.7 and earlier, distutils would include the Python + library. See pypa/distutils#9. + """ + from distutils import sysconfig + if not sysconfig.get_config_var('Py_ENABLED_SHARED'): + return + + yield 'python{}.{}{}'.format( + sys.hexversion >> 24, + (sys.hexversion >> 16) & 0xff, + sysconfig.get_config_var('ABIFLAGS'), + ) + + +def compose(f1, f2): + return lambda *args, **kwargs: f1(f2(*args, **kwargs)) + + +pythonlib = ( + compose(list, _pythonlib_compat) + if sys.version_info < (3, 8) + and sys.platform != 'darwin' + and sys.platform[:3] != 'aix' + else list +) diff --git a/venv/Lib/site-packages/setuptools/_distutils/command/register.py b/venv/Lib/site-packages/setuptools/_distutils/command/register.py new file mode 100644 index 0000000..0fac94e --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_distutils/command/register.py @@ -0,0 +1,304 @@ +"""distutils.command.register + +Implements the Distutils 'register' command (register with the repository). +""" + +# created 2002/10/21, Richard Jones + +import getpass +import io +import urllib.parse, urllib.request +from warnings import warn + +from distutils.core import PyPIRCCommand +from distutils.errors import * +from distutils import log + +class register(PyPIRCCommand): + + description = ("register the distribution with the Python package index") + user_options = PyPIRCCommand.user_options + [ + ('list-classifiers', None, + 'list the valid Trove classifiers'), + ('strict', None , + 'Will stop the registering if the meta-data are not fully compliant') + ] + boolean_options = PyPIRCCommand.boolean_options + [ + 'verify', 'list-classifiers', 'strict'] + + sub_commands = [('check', lambda self: True)] + + def initialize_options(self): + PyPIRCCommand.initialize_options(self) + self.list_classifiers = 0 + self.strict = 0 + + def finalize_options(self): + PyPIRCCommand.finalize_options(self) + # setting options for the `check` subcommand + check_options = {'strict': ('register', self.strict), + 'restructuredtext': ('register', 1)} + self.distribution.command_options['check'] = check_options + + def run(self): + self.finalize_options() + self._set_config() + + # Run sub commands + for cmd_name in self.get_sub_commands(): + self.run_command(cmd_name) + + if self.dry_run: + self.verify_metadata() + elif self.list_classifiers: + self.classifiers() + else: + self.send_metadata() + + def check_metadata(self): + """Deprecated API.""" + warn("distutils.command.register.check_metadata is deprecated, \ + use the check command instead", PendingDeprecationWarning) + check = self.distribution.get_command_obj('check') + check.ensure_finalized() + check.strict = self.strict + check.restructuredtext = 1 + check.run() + + def _set_config(self): + ''' Reads the configuration file and set attributes. + ''' + config = self._read_pypirc() + if config != {}: + self.username = config['username'] + self.password = config['password'] + self.repository = config['repository'] + self.realm = config['realm'] + self.has_config = True + else: + if self.repository not in ('pypi', self.DEFAULT_REPOSITORY): + raise ValueError('%s not found in .pypirc' % self.repository) + if self.repository == 'pypi': + self.repository = self.DEFAULT_REPOSITORY + self.has_config = False + + def classifiers(self): + ''' Fetch the list of classifiers from the server. + ''' + url = self.repository+'?:action=list_classifiers' + response = urllib.request.urlopen(url) + log.info(self._read_pypi_response(response)) + + def verify_metadata(self): + ''' Send the metadata to the package index server to be checked. + ''' + # send the info to the server and report the result + (code, result) = self.post_to_server(self.build_post_data('verify')) + log.info('Server response (%s): %s', code, result) + + def send_metadata(self): + ''' Send the metadata to the package index server. + + Well, do the following: + 1. figure who the user is, and then + 2. send the data as a Basic auth'ed POST. + + First we try to read the username/password from $HOME/.pypirc, + which is a ConfigParser-formatted file with a section + [distutils] containing username and password entries (both + in clear text). Eg: + + [distutils] + index-servers = + pypi + + [pypi] + username: fred + password: sekrit + + Otherwise, to figure who the user is, we offer the user three + choices: + + 1. use existing login, + 2. register as a new user, or + 3. set the password to a random string and email the user. + + ''' + # see if we can short-cut and get the username/password from the + # config + if self.has_config: + choice = '1' + username = self.username + password = self.password + else: + choice = 'x' + username = password = '' + + # get the user's login info + choices = '1 2 3 4'.split() + while choice not in choices: + self.announce('''\ +We need to know who you are, so please choose either: + 1. use your existing login, + 2. register as a new user, + 3. have the server generate a new password for you (and email it to you), or + 4. quit +Your selection [default 1]: ''', log.INFO) + choice = input() + if not choice: + choice = '1' + elif choice not in choices: + print('Please choose one of the four options!') + + if choice == '1': + # get the username and password + while not username: + username = input('Username: ') + while not password: + password = getpass.getpass('Password: ') + + # set up the authentication + auth = urllib.request.HTTPPasswordMgr() + host = urllib.parse.urlparse(self.repository)[1] + auth.add_password(self.realm, host, username, password) + # send the info to the server and report the result + code, result = self.post_to_server(self.build_post_data('submit'), + auth) + self.announce('Server response (%s): %s' % (code, result), + log.INFO) + + # possibly save the login + if code == 200: + if self.has_config: + # sharing the password in the distribution instance + # so the upload command can reuse it + self.distribution.password = password + else: + self.announce(('I can store your PyPI login so future ' + 'submissions will be faster.'), log.INFO) + self.announce('(the login will be stored in %s)' % \ + self._get_rc_file(), log.INFO) + choice = 'X' + while choice.lower() not in 'yn': + choice = input('Save your login (y/N)?') + if not choice: + choice = 'n' + if choice.lower() == 'y': + self._store_pypirc(username, password) + + elif choice == '2': + data = {':action': 'user'} + data['name'] = data['password'] = data['email'] = '' + data['confirm'] = None + while not data['name']: + data['name'] = input('Username: ') + while data['password'] != data['confirm']: + while not data['password']: + data['password'] = getpass.getpass('Password: ') + while not data['confirm']: + data['confirm'] = getpass.getpass(' Confirm: ') + if data['password'] != data['confirm']: + data['password'] = '' + data['confirm'] = None + print("Password and confirm don't match!") + while not data['email']: + data['email'] = input(' EMail: ') + code, result = self.post_to_server(data) + if code != 200: + log.info('Server response (%s): %s', code, result) + else: + log.info('You will receive an email shortly.') + log.info(('Follow the instructions in it to ' + 'complete registration.')) + elif choice == '3': + data = {':action': 'password_reset'} + data['email'] = '' + while not data['email']: + data['email'] = input('Your email address: ') + code, result = self.post_to_server(data) + log.info('Server response (%s): %s', code, result) + + def build_post_data(self, action): + # figure the data to send - the metadata plus some additional + # information used by the package server + meta = self.distribution.metadata + data = { + ':action': action, + 'metadata_version' : '1.0', + 'name': meta.get_name(), + 'version': meta.get_version(), + 'summary': meta.get_description(), + 'home_page': meta.get_url(), + 'author': meta.get_contact(), + 'author_email': meta.get_contact_email(), + 'license': meta.get_licence(), + 'description': meta.get_long_description(), + 'keywords': meta.get_keywords(), + 'platform': meta.get_platforms(), + 'classifiers': meta.get_classifiers(), + 'download_url': meta.get_download_url(), + # PEP 314 + 'provides': meta.get_provides(), + 'requires': meta.get_requires(), + 'obsoletes': meta.get_obsoletes(), + } + if data['provides'] or data['requires'] or data['obsoletes']: + data['metadata_version'] = '1.1' + return data + + def post_to_server(self, data, auth=None): + ''' Post a query to the server, and return a string response. + ''' + if 'name' in data: + self.announce('Registering %s to %s' % (data['name'], + self.repository), + log.INFO) + # Build up the MIME payload for the urllib2 POST data + boundary = '--------------GHSKFJDLGDS7543FJKLFHRE75642756743254' + sep_boundary = '\n--' + boundary + end_boundary = sep_boundary + '--' + body = io.StringIO() + for key, value in data.items(): + # handle multiple entries for the same name + if type(value) not in (type([]), type( () )): + value = [value] + for value in value: + value = str(value) + body.write(sep_boundary) + body.write('\nContent-Disposition: form-data; name="%s"'%key) + body.write("\n\n") + body.write(value) + if value and value[-1] == '\r': + body.write('\n') # write an extra newline (lurve Macs) + body.write(end_boundary) + body.write("\n") + body = body.getvalue().encode("utf-8") + + # build the Request + headers = { + 'Content-type': 'multipart/form-data; boundary=%s; charset=utf-8'%boundary, + 'Content-length': str(len(body)) + } + req = urllib.request.Request(self.repository, body, headers) + + # handle HTTP and include the Basic Auth handler + opener = urllib.request.build_opener( + urllib.request.HTTPBasicAuthHandler(password_mgr=auth) + ) + data = '' + try: + result = opener.open(req) + except urllib.error.HTTPError as e: + if self.show_response: + data = e.fp.read() + result = e.code, e.msg + except urllib.error.URLError as e: + result = 500, str(e) + else: + if self.show_response: + data = self._read_pypi_response(result) + result = 200, 'OK' + if self.show_response: + msg = '\n'.join(('-' * 75, data, '-' * 75)) + self.announce(msg, log.INFO) + return result diff --git a/venv/Lib/site-packages/setuptools/_distutils/command/sdist.py b/venv/Lib/site-packages/setuptools/_distutils/command/sdist.py new file mode 100644 index 0000000..b4996fc --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_distutils/command/sdist.py @@ -0,0 +1,494 @@ +"""distutils.command.sdist + +Implements the Distutils 'sdist' command (create a source distribution).""" + +import os +import sys +from glob import glob +from warnings import warn + +from distutils.core import Command +from distutils import dir_util +from distutils import file_util +from distutils import archive_util +from distutils.text_file import TextFile +from distutils.filelist import FileList +from distutils import log +from distutils.util import convert_path +from distutils.errors import DistutilsTemplateError, DistutilsOptionError + + +def show_formats(): + """Print all possible values for the 'formats' option (used by + the "--help-formats" command-line option). + """ + from distutils.fancy_getopt import FancyGetopt + from distutils.archive_util import ARCHIVE_FORMATS + formats = [] + for format in ARCHIVE_FORMATS.keys(): + formats.append(("formats=" + format, None, + ARCHIVE_FORMATS[format][2])) + formats.sort() + FancyGetopt(formats).print_help( + "List of available source distribution formats:") + + +class sdist(Command): + + description = "create a source distribution (tarball, zip file, etc.)" + + def checking_metadata(self): + """Callable used for the check sub-command. + + Placed here so user_options can view it""" + return self.metadata_check + + user_options = [ + ('template=', 't', + "name of manifest template file [default: MANIFEST.in]"), + ('manifest=', 'm', + "name of manifest file [default: MANIFEST]"), + ('use-defaults', None, + "include the default file set in the manifest " + "[default; disable with --no-defaults]"), + ('no-defaults', None, + "don't include the default file set"), + ('prune', None, + "specifically exclude files/directories that should not be " + "distributed (build tree, RCS/CVS dirs, etc.) " + "[default; disable with --no-prune]"), + ('no-prune', None, + "don't automatically exclude anything"), + ('manifest-only', 'o', + "just regenerate the manifest and then stop " + "(implies --force-manifest)"), + ('force-manifest', 'f', + "forcibly regenerate the manifest and carry on as usual. " + "Deprecated: now the manifest is always regenerated."), + ('formats=', None, + "formats for source distribution (comma-separated list)"), + ('keep-temp', 'k', + "keep the distribution tree around after creating " + + "archive file(s)"), + ('dist-dir=', 'd', + "directory to put the source distribution archive(s) in " + "[default: dist]"), + ('metadata-check', None, + "Ensure that all required elements of meta-data " + "are supplied. Warn if any missing. [default]"), + ('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]"), + ] + + boolean_options = ['use-defaults', 'prune', + 'manifest-only', 'force-manifest', + 'keep-temp', 'metadata-check'] + + help_options = [ + ('help-formats', None, + "list available distribution formats", show_formats), + ] + + negative_opt = {'no-defaults': 'use-defaults', + 'no-prune': 'prune' } + + sub_commands = [('check', checking_metadata)] + + READMES = ('README', 'README.txt', 'README.rst') + + def initialize_options(self): + # 'template' and 'manifest' are, respectively, the names of + # the manifest template and manifest file. + self.template = None + self.manifest = None + + # 'use_defaults': if true, we will include the default file set + # in the manifest + self.use_defaults = 1 + self.prune = 1 + + self.manifest_only = 0 + self.force_manifest = 0 + + self.formats = ['gztar'] + self.keep_temp = 0 + self.dist_dir = None + + self.archive_files = None + self.metadata_check = 1 + self.owner = None + self.group = None + + def finalize_options(self): + if self.manifest is None: + self.manifest = "MANIFEST" + if self.template is None: + self.template = "MANIFEST.in" + + self.ensure_string_list('formats') + + bad_format = archive_util.check_archive_formats(self.formats) + if bad_format: + raise DistutilsOptionError( + "unknown archive format '%s'" % bad_format) + + if self.dist_dir is None: + self.dist_dir = "dist" + + def run(self): + # 'filelist' contains the list of files that will make up the + # manifest + self.filelist = FileList() + + # Run sub commands + for cmd_name in self.get_sub_commands(): + self.run_command(cmd_name) + + # Do whatever it takes to get the list of files to process + # (process the manifest template, read an existing manifest, + # whatever). File list is accumulated in 'self.filelist'. + self.get_file_list() + + # If user just wanted us to regenerate the manifest, stop now. + if self.manifest_only: + return + + # Otherwise, go ahead and create the source distribution tarball, + # or zipfile, or whatever. + self.make_distribution() + + def check_metadata(self): + """Deprecated API.""" + warn("distutils.command.sdist.check_metadata is deprecated, \ + use the check command instead", PendingDeprecationWarning) + check = self.distribution.get_command_obj('check') + check.ensure_finalized() + check.run() + + def get_file_list(self): + """Figure out the list of files to include in the source + distribution, and put it in 'self.filelist'. This might involve + reading the manifest template (and writing the manifest), or just + reading the manifest, or just using the default file set -- it all + depends on the user's options. + """ + # new behavior when using a template: + # the file list is recalculated every time because + # even if MANIFEST.in or setup.py are not changed + # the user might have added some files in the tree that + # need to be included. + # + # This makes --force the default and only behavior with templates. + template_exists = os.path.isfile(self.template) + if not template_exists and self._manifest_is_not_generated(): + self.read_manifest() + self.filelist.sort() + self.filelist.remove_duplicates() + return + + if not template_exists: + self.warn(("manifest template '%s' does not exist " + + "(using default file list)") % + self.template) + self.filelist.findall() + + if self.use_defaults: + self.add_defaults() + + if template_exists: + self.read_template() + + if self.prune: + self.prune_file_list() + + self.filelist.sort() + self.filelist.remove_duplicates() + self.write_manifest() + + def add_defaults(self): + """Add all the default files to self.filelist: + - README or README.txt + - setup.py + - test/test*.py + - all pure Python modules mentioned in setup script + - all files pointed by package_data (build_py) + - all files defined in data_files. + - all files defined as scripts. + - all C sources listed as part of extensions or C libraries + in the setup script (doesn't catch C headers!) + Warns if (README or README.txt) or setup.py are missing; everything + else is optional. + """ + self._add_defaults_standards() + self._add_defaults_optional() + self._add_defaults_python() + self._add_defaults_data_files() + self._add_defaults_ext() + self._add_defaults_c_libs() + self._add_defaults_scripts() + + @staticmethod + def _cs_path_exists(fspath): + """ + Case-sensitive path existence check + + >>> sdist._cs_path_exists(__file__) + True + >>> sdist._cs_path_exists(__file__.upper()) + False + """ + if not os.path.exists(fspath): + return False + # make absolute so we always have a directory + abspath = os.path.abspath(fspath) + directory, filename = os.path.split(abspath) + return filename in os.listdir(directory) + + def _add_defaults_standards(self): + standards = [self.READMES, self.distribution.script_name] + for fn in standards: + if isinstance(fn, tuple): + alts = fn + got_it = False + for fn in alts: + if self._cs_path_exists(fn): + got_it = True + self.filelist.append(fn) + break + + if not got_it: + self.warn("standard file not found: should have one of " + + ', '.join(alts)) + else: + if self._cs_path_exists(fn): + self.filelist.append(fn) + else: + self.warn("standard file '%s' not found" % fn) + + def _add_defaults_optional(self): + optional = ['test/test*.py', 'setup.cfg'] + for pattern in optional: + files = filter(os.path.isfile, glob(pattern)) + self.filelist.extend(files) + + def _add_defaults_python(self): + # build_py is used to get: + # - python modules + # - files defined in package_data + build_py = self.get_finalized_command('build_py') + + # getting python files + if self.distribution.has_pure_modules(): + self.filelist.extend(build_py.get_source_files()) + + # getting package_data files + # (computed in build_py.data_files by build_py.finalize_options) + for pkg, src_dir, build_dir, filenames in build_py.data_files: + for filename in filenames: + self.filelist.append(os.path.join(src_dir, filename)) + + def _add_defaults_data_files(self): + # getting distribution.data_files + if self.distribution.has_data_files(): + for item in self.distribution.data_files: + if isinstance(item, str): + # plain file + item = convert_path(item) + if os.path.isfile(item): + self.filelist.append(item) + else: + # a (dirname, filenames) tuple + dirname, filenames = item + for f in filenames: + f = convert_path(f) + if os.path.isfile(f): + self.filelist.append(f) + + def _add_defaults_ext(self): + if self.distribution.has_ext_modules(): + build_ext = self.get_finalized_command('build_ext') + self.filelist.extend(build_ext.get_source_files()) + + def _add_defaults_c_libs(self): + if self.distribution.has_c_libraries(): + build_clib = self.get_finalized_command('build_clib') + self.filelist.extend(build_clib.get_source_files()) + + def _add_defaults_scripts(self): + if self.distribution.has_scripts(): + build_scripts = self.get_finalized_command('build_scripts') + self.filelist.extend(build_scripts.get_source_files()) + + def read_template(self): + """Read and parse manifest template file named by self.template. + + (usually "MANIFEST.in") The parsing and processing is done by + 'self.filelist', which updates itself accordingly. + """ + log.info("reading manifest template '%s'", self.template) + template = TextFile(self.template, strip_comments=1, skip_blanks=1, + join_lines=1, lstrip_ws=1, rstrip_ws=1, + collapse_join=1) + + try: + while True: + line = template.readline() + if line is None: # end of file + break + + try: + self.filelist.process_template_line(line) + # the call above can raise a DistutilsTemplateError for + # malformed lines, or a ValueError from the lower-level + # convert_path function + except (DistutilsTemplateError, ValueError) as msg: + self.warn("%s, line %d: %s" % (template.filename, + template.current_line, + msg)) + finally: + template.close() + + def prune_file_list(self): + """Prune off branches that might slip into the file list as created + by 'read_template()', but really don't belong there: + * the build tree (typically "build") + * the release tree itself (only an issue if we ran "sdist" + previously with --keep-temp, or it aborted) + * any RCS, CVS, .svn, .hg, .git, .bzr, _darcs directories + """ + build = self.get_finalized_command('build') + base_dir = self.distribution.get_fullname() + + self.filelist.exclude_pattern(None, prefix=build.build_base) + self.filelist.exclude_pattern(None, prefix=base_dir) + + if sys.platform == 'win32': + seps = r'/|\\' + else: + seps = '/' + + vcs_dirs = ['RCS', 'CVS', r'\.svn', r'\.hg', r'\.git', r'\.bzr', + '_darcs'] + vcs_ptrn = r'(^|%s)(%s)(%s).*' % (seps, '|'.join(vcs_dirs), seps) + self.filelist.exclude_pattern(vcs_ptrn, is_regex=1) + + def write_manifest(self): + """Write the file list in 'self.filelist' (presumably as filled in + by 'add_defaults()' and 'read_template()') to the manifest file + named by 'self.manifest'. + """ + if self._manifest_is_not_generated(): + log.info("not writing to manually maintained " + "manifest file '%s'" % self.manifest) + return + + content = self.filelist.files[:] + content.insert(0, '# file GENERATED by distutils, do NOT edit') + self.execute(file_util.write_file, (self.manifest, content), + "writing manifest file '%s'" % self.manifest) + + def _manifest_is_not_generated(self): + # check for special comment used in 3.1.3 and higher + if not os.path.isfile(self.manifest): + return False + + fp = open(self.manifest) + try: + first_line = fp.readline() + finally: + fp.close() + return first_line != '# file GENERATED by distutils, do NOT edit\n' + + def read_manifest(self): + """Read the manifest file (named by 'self.manifest') and use it to + fill in 'self.filelist', the list of files to include in the source + distribution. + """ + log.info("reading manifest file '%s'", self.manifest) + with open(self.manifest) as manifest: + for line in manifest: + # ignore comments and blank lines + line = line.strip() + if line.startswith('#') or not line: + continue + self.filelist.append(line) + + def make_release_tree(self, base_dir, files): + """Create the directory tree that will become the source + distribution archive. All directories implied by the filenames in + 'files' are created under 'base_dir', and then we hard link or copy + (if hard linking is unavailable) those files into place. + Essentially, this duplicates the developer's source tree, but in a + directory named after the distribution, containing only the files + to be distributed. + """ + # Create all the directories under 'base_dir' necessary to + # put 'files' there; the 'mkpath()' is just so we don't die + # if the manifest happens to be empty. + self.mkpath(base_dir) + dir_util.create_tree(base_dir, files, dry_run=self.dry_run) + + # And walk over the list of files, either making a hard link (if + # os.link exists) to each one that doesn't already exist in its + # corresponding location under 'base_dir', or copying each file + # that's out-of-date in 'base_dir'. (Usually, all files will be + # out-of-date, because by default we blow away 'base_dir' when + # we're done making the distribution archives.) + + if hasattr(os, 'link'): # can make hard links on this system + link = 'hard' + msg = "making hard links in %s..." % base_dir + else: # nope, have to copy + link = None + msg = "copying files to %s..." % base_dir + + if not files: + log.warn("no files to distribute -- empty manifest?") + else: + log.info(msg) + for file in files: + if not os.path.isfile(file): + log.warn("'%s' not a regular file -- skipping", file) + else: + dest = os.path.join(base_dir, file) + self.copy_file(file, dest, link=link) + + self.distribution.metadata.write_pkg_info(base_dir) + + def make_distribution(self): + """Create the source distribution(s). First, we create the release + tree with 'make_release_tree()'; then, we create all required + archive files (according to 'self.formats') from the release tree. + Finally, we clean up by blowing away the release tree (unless + 'self.keep_temp' is true). The list of archive files created is + stored so it can be retrieved later by 'get_archive_files()'. + """ + # Don't warn about missing meta-data here -- should be (and is!) + # done elsewhere. + base_dir = self.distribution.get_fullname() + base_name = os.path.join(self.dist_dir, base_dir) + + self.make_release_tree(base_dir, self.filelist.files) + archive_files = [] # remember names of files we create + # tar archive must be created last to avoid overwrite and remove + if 'tar' in self.formats: + self.formats.append(self.formats.pop(self.formats.index('tar'))) + + for fmt in self.formats: + file = self.make_archive(base_name, fmt, base_dir=base_dir, + owner=self.owner, group=self.group) + archive_files.append(file) + self.distribution.dist_files.append(('sdist', '', file)) + + self.archive_files = archive_files + + if not self.keep_temp: + dir_util.remove_tree(base_dir, dry_run=self.dry_run) + + def get_archive_files(self): + """Return the list of archive files created when the command + was run, or None if the command hasn't run yet. + """ + return self.archive_files diff --git a/venv/Lib/site-packages/setuptools/_distutils/command/upload.py b/venv/Lib/site-packages/setuptools/_distutils/command/upload.py new file mode 100644 index 0000000..95e9fda --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_distutils/command/upload.py @@ -0,0 +1,214 @@ +""" +distutils.command.upload + +Implements the Distutils 'upload' subcommand (upload package to a package +index). +""" + +import os +import io +import hashlib +from base64 import standard_b64encode +from urllib.request import urlopen, Request, HTTPError +from urllib.parse import urlparse +from distutils.errors import DistutilsError, DistutilsOptionError +from distutils.core import PyPIRCCommand +from distutils.spawn import spawn +from distutils import log + + +# PyPI Warehouse supports MD5, SHA256, and Blake2 (blake2-256) +# https://bugs.python.org/issue40698 +_FILE_CONTENT_DIGESTS = { + "md5_digest": getattr(hashlib, "md5", None), + "sha256_digest": getattr(hashlib, "sha256", None), + "blake2_256_digest": getattr(hashlib, "blake2b", None), +} + + +class upload(PyPIRCCommand): + + description = "upload binary package to PyPI" + + user_options = PyPIRCCommand.user_options + [ + ('sign', 's', + 'sign files to upload using gpg'), + ('identity=', 'i', 'GPG identity used to sign files'), + ] + + boolean_options = PyPIRCCommand.boolean_options + ['sign'] + + def initialize_options(self): + PyPIRCCommand.initialize_options(self) + self.username = '' + self.password = '' + self.show_response = 0 + self.sign = False + self.identity = None + + def finalize_options(self): + PyPIRCCommand.finalize_options(self) + if self.identity and not self.sign: + raise DistutilsOptionError( + "Must use --sign for --identity to have meaning" + ) + config = self._read_pypirc() + if config != {}: + self.username = config['username'] + self.password = config['password'] + self.repository = config['repository'] + self.realm = config['realm'] + + # getting the password from the distribution + # if previously set by the register command + if not self.password and self.distribution.password: + self.password = self.distribution.password + + def run(self): + if not self.distribution.dist_files: + msg = ("Must create and upload files in one command " + "(e.g. setup.py sdist upload)") + raise DistutilsOptionError(msg) + for command, pyversion, filename in self.distribution.dist_files: + self.upload_file(command, pyversion, filename) + + def upload_file(self, command, pyversion, filename): + # Makes sure the repository URL is compliant + schema, netloc, url, params, query, fragments = \ + urlparse(self.repository) + if params or query or fragments: + raise AssertionError("Incompatible url %s" % self.repository) + + if schema not in ('http', 'https'): + raise AssertionError("unsupported schema " + schema) + + # Sign if requested + if self.sign: + gpg_args = ["gpg", "--detach-sign", "-a", filename] + if self.identity: + gpg_args[2:2] = ["--local-user", self.identity] + spawn(gpg_args, + dry_run=self.dry_run) + + # Fill in the data - send all the meta-data in case we need to + # register a new release + f = open(filename,'rb') + try: + content = f.read() + finally: + f.close() + + meta = self.distribution.metadata + data = { + # action + ':action': 'file_upload', + 'protocol_version': '1', + + # identify release + 'name': meta.get_name(), + 'version': meta.get_version(), + + # file content + 'content': (os.path.basename(filename),content), + 'filetype': command, + 'pyversion': pyversion, + + # additional meta-data + 'metadata_version': '1.0', + 'summary': meta.get_description(), + 'home_page': meta.get_url(), + 'author': meta.get_contact(), + 'author_email': meta.get_contact_email(), + 'license': meta.get_licence(), + 'description': meta.get_long_description(), + 'keywords': meta.get_keywords(), + 'platform': meta.get_platforms(), + 'classifiers': meta.get_classifiers(), + 'download_url': meta.get_download_url(), + # PEP 314 + 'provides': meta.get_provides(), + 'requires': meta.get_requires(), + 'obsoletes': meta.get_obsoletes(), + } + + data['comment'] = '' + + # file content digests + for digest_name, digest_cons in _FILE_CONTENT_DIGESTS.items(): + if digest_cons is None: + continue + try: + data[digest_name] = digest_cons(content).hexdigest() + except ValueError: + # hash digest not available or blocked by security policy + pass + + if self.sign: + with open(filename + ".asc", "rb") as f: + data['gpg_signature'] = (os.path.basename(filename) + ".asc", + f.read()) + + # set up the authentication + user_pass = (self.username + ":" + self.password).encode('ascii') + # The exact encoding of the authentication string is debated. + # Anyway PyPI only accepts ascii for both username or password. + auth = "Basic " + standard_b64encode(user_pass).decode('ascii') + + # Build up the MIME payload for the POST data + boundary = '--------------GHSKFJDLGDS7543FJKLFHRE75642756743254' + sep_boundary = b'\r\n--' + boundary.encode('ascii') + end_boundary = sep_boundary + b'--\r\n' + body = io.BytesIO() + for key, value in data.items(): + title = '\r\nContent-Disposition: form-data; name="%s"' % key + # handle multiple entries for the same name + if not isinstance(value, list): + value = [value] + for value in value: + if type(value) is tuple: + title += '; filename="%s"' % value[0] + value = value[1] + else: + value = str(value).encode('utf-8') + body.write(sep_boundary) + body.write(title.encode('utf-8')) + body.write(b"\r\n\r\n") + body.write(value) + body.write(end_boundary) + body = body.getvalue() + + msg = "Submitting %s to %s" % (filename, self.repository) + self.announce(msg, log.INFO) + + # build the Request + headers = { + 'Content-type': 'multipart/form-data; boundary=%s' % boundary, + 'Content-length': str(len(body)), + 'Authorization': auth, + } + + request = Request(self.repository, data=body, + headers=headers) + # send the data + try: + result = urlopen(request) + status = result.getcode() + reason = result.msg + except HTTPError as e: + status = e.code + reason = e.msg + except OSError as e: + self.announce(str(e), log.ERROR) + raise + + if status == 200: + self.announce('Server response (%s): %s' % (status, reason), + log.INFO) + if self.show_response: + text = self._read_pypi_response(result) + msg = '\n'.join(('-' * 75, text, '-' * 75)) + self.announce(msg, log.INFO) + else: + msg = 'Upload failed (%s): %s' % (status, reason) + self.announce(msg, log.ERROR) + raise DistutilsError(msg) diff --git a/venv/Lib/site-packages/setuptools/_distutils/config.py b/venv/Lib/site-packages/setuptools/_distutils/config.py new file mode 100644 index 0000000..2171abd --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_distutils/config.py @@ -0,0 +1,130 @@ +"""distutils.pypirc + +Provides the PyPIRCCommand class, the base class for the command classes +that uses .pypirc in the distutils.command package. +""" +import os +from configparser import RawConfigParser + +from distutils.cmd import Command + +DEFAULT_PYPIRC = """\ +[distutils] +index-servers = + pypi + +[pypi] +username:%s +password:%s +""" + +class PyPIRCCommand(Command): + """Base command that knows how to handle the .pypirc file + """ + DEFAULT_REPOSITORY = 'https://upload.pypi.org/legacy/' + DEFAULT_REALM = 'pypi' + repository = None + realm = None + + user_options = [ + ('repository=', 'r', + "url of repository [default: %s]" % \ + DEFAULT_REPOSITORY), + ('show-response', None, + 'display full response text from server')] + + boolean_options = ['show-response'] + + def _get_rc_file(self): + """Returns rc file path.""" + return os.path.join(os.path.expanduser('~'), '.pypirc') + + def _store_pypirc(self, username, password): + """Creates a default .pypirc file.""" + rc = self._get_rc_file() + with os.fdopen(os.open(rc, os.O_CREAT | os.O_WRONLY, 0o600), 'w') as f: + f.write(DEFAULT_PYPIRC % (username, password)) + + def _read_pypirc(self): + """Reads the .pypirc file.""" + rc = self._get_rc_file() + if os.path.exists(rc): + self.announce('Using PyPI login from %s' % rc) + repository = self.repository or self.DEFAULT_REPOSITORY + + config = RawConfigParser() + config.read(rc) + sections = config.sections() + if 'distutils' in sections: + # let's get the list of servers + index_servers = config.get('distutils', 'index-servers') + _servers = [server.strip() for server in + index_servers.split('\n') + if server.strip() != ''] + if _servers == []: + # nothing set, let's try to get the default pypi + if 'pypi' in sections: + _servers = ['pypi'] + else: + # the file is not properly defined, returning + # an empty dict + return {} + for server in _servers: + current = {'server': server} + current['username'] = config.get(server, 'username') + + # optional params + for key, default in (('repository', + self.DEFAULT_REPOSITORY), + ('realm', self.DEFAULT_REALM), + ('password', None)): + if config.has_option(server, key): + current[key] = config.get(server, key) + else: + current[key] = default + + # work around people having "repository" for the "pypi" + # section of their config set to the HTTP (rather than + # HTTPS) URL + if (server == 'pypi' and + repository in (self.DEFAULT_REPOSITORY, 'pypi')): + current['repository'] = self.DEFAULT_REPOSITORY + return current + + if (current['server'] == repository or + current['repository'] == repository): + return current + elif 'server-login' in sections: + # old format + server = 'server-login' + if config.has_option(server, 'repository'): + repository = config.get(server, 'repository') + else: + repository = self.DEFAULT_REPOSITORY + return {'username': config.get(server, 'username'), + 'password': config.get(server, 'password'), + 'repository': repository, + 'server': server, + 'realm': self.DEFAULT_REALM} + + return {} + + def _read_pypi_response(self, response): + """Read and decode a PyPI HTTP response.""" + import cgi + content_type = response.getheader('content-type', 'text/plain') + encoding = cgi.parse_header(content_type)[1].get('charset', 'ascii') + return response.read().decode(encoding) + + def initialize_options(self): + """Initialize options.""" + self.repository = None + self.realm = None + self.show_response = 0 + + def finalize_options(self): + """Finalizes options.""" + if self.repository is None: + self.repository = self.DEFAULT_REPOSITORY + if self.realm is None: + self.realm = self.DEFAULT_REALM diff --git a/venv/Lib/site-packages/setuptools/_distutils/core.py b/venv/Lib/site-packages/setuptools/_distutils/core.py new file mode 100644 index 0000000..f43888e --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_distutils/core.py @@ -0,0 +1,249 @@ +"""distutils.core + +The only module that needs to be imported to use the Distutils; provides +the 'setup' function (which is to be called from the setup script). Also +indirectly provides the Distribution and Command classes, although they are +really defined in distutils.dist and distutils.cmd. +""" + +import os +import sys +import tokenize + +from distutils.debug import DEBUG +from distutils.errors import * + +# Mainly import these so setup scripts can "from distutils.core import" them. +from distutils.dist import Distribution +from distutils.cmd import Command +from distutils.config import PyPIRCCommand +from distutils.extension import Extension + +# This is a barebones help message generated displayed when the user +# runs the setup script with no arguments at all. More useful help +# is generated with various --help options: global help, list commands, +# and per-command help. +USAGE = """\ +usage: %(script)s [global_opts] cmd1 [cmd1_opts] [cmd2 [cmd2_opts] ...] + or: %(script)s --help [cmd1 cmd2 ...] + or: %(script)s --help-commands + or: %(script)s cmd --help +""" + +def gen_usage (script_name): + script = os.path.basename(script_name) + return USAGE % vars() + + +# Some mild magic to control the behaviour of 'setup()' from 'run_setup()'. +_setup_stop_after = None +_setup_distribution = None + +# Legal keyword arguments for the setup() function +setup_keywords = ('distclass', 'script_name', 'script_args', 'options', + 'name', 'version', 'author', 'author_email', + 'maintainer', 'maintainer_email', 'url', 'license', + 'description', 'long_description', 'keywords', + 'platforms', 'classifiers', 'download_url', + 'requires', 'provides', 'obsoletes', + ) + +# Legal keyword arguments for the Extension constructor +extension_keywords = ('name', 'sources', 'include_dirs', + 'define_macros', 'undef_macros', + 'library_dirs', 'libraries', 'runtime_library_dirs', + 'extra_objects', 'extra_compile_args', 'extra_link_args', + 'swig_opts', 'export_symbols', 'depends', 'language') + +def setup (**attrs): + """The gateway to the Distutils: do everything your setup script needs + to do, in a highly flexible and user-driven way. Briefly: create a + Distribution instance; find and parse config files; parse the command + line; run each Distutils command found there, customized by the options + supplied to 'setup()' (as keyword arguments), in config files, and on + the command line. + + The Distribution instance might be an instance of a class supplied via + the 'distclass' keyword argument to 'setup'; if no such class is + supplied, then the Distribution class (in dist.py) is instantiated. + All other arguments to 'setup' (except for 'cmdclass') are used to set + attributes of the Distribution instance. + + The 'cmdclass' argument, if supplied, is a dictionary mapping command + names to command classes. Each command encountered on the command line + will be turned into a command class, which is in turn instantiated; any + class found in 'cmdclass' is used in place of the default, which is + (for command 'foo_bar') class 'foo_bar' in module + 'distutils.command.foo_bar'. The command class must provide a + 'user_options' attribute which is a list of option specifiers for + 'distutils.fancy_getopt'. Any command-line options between the current + and the next command are used to set attributes of the current command + object. + + When the entire command-line has been successfully parsed, calls the + 'run()' method on each command object in turn. This method will be + driven entirely by the Distribution object (which each command object + has a reference to, thanks to its constructor), and the + command-specific options that became attributes of each command + object. + """ + + global _setup_stop_after, _setup_distribution + + # Determine the distribution class -- either caller-supplied or + # our Distribution (see below). + klass = attrs.get('distclass') + if klass: + del attrs['distclass'] + else: + klass = Distribution + + if 'script_name' not in attrs: + attrs['script_name'] = os.path.basename(sys.argv[0]) + if 'script_args' not in attrs: + attrs['script_args'] = sys.argv[1:] + + # Create the Distribution instance, using the remaining arguments + # (ie. everything except distclass) to initialize it + try: + _setup_distribution = dist = klass(attrs) + except DistutilsSetupError as msg: + if 'name' not in attrs: + raise SystemExit("error in setup command: %s" % msg) + else: + raise SystemExit("error in %s setup command: %s" % \ + (attrs['name'], msg)) + + if _setup_stop_after == "init": + return dist + + # Find and parse the config file(s): they will override options from + # the setup script, but be overridden by the command line. + dist.parse_config_files() + + if DEBUG: + print("options (after parsing config files):") + dist.dump_option_dicts() + + if _setup_stop_after == "config": + return dist + + # Parse the command line and override config files; any + # command-line errors are the end user's fault, so turn them into + # SystemExit to suppress tracebacks. + try: + ok = dist.parse_command_line() + except DistutilsArgError as msg: + raise SystemExit(gen_usage(dist.script_name) + "\nerror: %s" % msg) + + if DEBUG: + print("options (after parsing command line):") + dist.dump_option_dicts() + + if _setup_stop_after == "commandline": + return dist + + # And finally, run all the commands found on the command line. + if ok: + return run_commands(dist) + + return dist + +# setup () + + +def run_commands (dist): + """Given a Distribution object run all the commands, + raising ``SystemExit`` errors in the case of failure. + + This function assumes that either ``sys.argv`` or ``dist.script_args`` + is already set accordingly. + """ + try: + dist.run_commands() + except KeyboardInterrupt: + raise SystemExit("interrupted") + except OSError as exc: + if DEBUG: + sys.stderr.write("error: %s\n" % (exc,)) + raise + else: + raise SystemExit("error: %s" % (exc,)) + + except (DistutilsError, + CCompilerError) as msg: + if DEBUG: + raise + else: + raise SystemExit("error: " + str(msg)) + + return dist + + +def run_setup (script_name, script_args=None, stop_after="run"): + """Run a setup script in a somewhat controlled environment, and + return the Distribution instance that drives things. This is useful + if you need to find out the distribution meta-data (passed as + keyword args from 'script' to 'setup()', or the contents of the + config files or command-line. + + 'script_name' is a file that will be read and run with 'exec()'; + 'sys.argv[0]' will be replaced with 'script' for the duration of the + call. 'script_args' is a list of strings; if supplied, + 'sys.argv[1:]' will be replaced by 'script_args' for the duration of + the call. + + 'stop_after' tells 'setup()' when to stop processing; possible + values: + init + stop after the Distribution instance has been created and + populated with the keyword arguments to 'setup()' + config + stop after config files have been parsed (and their data + stored in the Distribution instance) + commandline + stop after the command-line ('sys.argv[1:]' or 'script_args') + have been parsed (and the data stored in the Distribution) + run [default] + stop after all commands have been run (the same as if 'setup()' + had been called in the usual way + + Returns the Distribution instance, which provides all information + used to drive the Distutils. + """ + if stop_after not in ('init', 'config', 'commandline', 'run'): + raise ValueError("invalid value for 'stop_after': %r" % (stop_after,)) + + global _setup_stop_after, _setup_distribution + _setup_stop_after = stop_after + + save_argv = sys.argv.copy() + g = {'__file__': script_name, '__name__': '__main__'} + try: + try: + sys.argv[0] = script_name + if script_args is not None: + sys.argv[1:] = script_args + # tokenize.open supports automatic encoding detection + with tokenize.open(script_name) as f: + code = f.read().replace(r'\r\n', r'\n') + exec(code, g) + finally: + sys.argv = save_argv + _setup_stop_after = None + except SystemExit: + # Hmm, should we do something if exiting with a non-zero code + # (ie. error)? + pass + + if _setup_distribution is None: + raise RuntimeError(("'distutils.core.setup()' was never called -- " + "perhaps '%s' is not a Distutils setup script?") % \ + script_name) + + # I wonder if the setup script's namespace -- g and l -- would be of + # any interest to callers? + #print "_setup_distribution:", _setup_distribution + return _setup_distribution + +# run_setup () diff --git a/venv/Lib/site-packages/setuptools/_distutils/cygwinccompiler.py b/venv/Lib/site-packages/setuptools/_distutils/cygwinccompiler.py new file mode 100644 index 0000000..c5c86d8 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_distutils/cygwinccompiler.py @@ -0,0 +1,362 @@ +"""distutils.cygwinccompiler + +Provides the CygwinCCompiler class, a subclass of UnixCCompiler that +handles the Cygwin port of the GNU C compiler to Windows. It also contains +the Mingw32CCompiler class which handles the mingw32 port of GCC (same as +cygwin in no-cygwin mode). +""" + +# problems: +# +# * if you use a msvc compiled python version (1.5.2) +# 1. you have to insert a __GNUC__ section in its config.h +# 2. you have to generate an import library for its dll +# - create a def-file for python??.dll +# - create an import library using +# dlltool --dllname python15.dll --def python15.def \ +# --output-lib libpython15.a +# +# see also http://starship.python.net/crew/kernr/mingw32/Notes.html +# +# * We put export_symbols in a def-file, and don't use +# --export-all-symbols because it doesn't worked reliable in some +# tested configurations. And because other windows compilers also +# need their symbols specified this no serious problem. +# +# tested configurations: +# +# * cygwin gcc 2.91.57/ld 2.9.4/dllwrap 0.2.4 works +# (after patching python's config.h and for C++ some other include files) +# see also http://starship.python.net/crew/kernr/mingw32/Notes.html +# * mingw32 gcc 2.95.2/ld 2.9.4/dllwrap 0.2.4 works +# (ld doesn't support -shared, so we use dllwrap) +# * cygwin gcc 2.95.2/ld 2.10.90/dllwrap 2.10.90 works now +# - its dllwrap doesn't work, there is a bug in binutils 2.10.90 +# see also http://sources.redhat.com/ml/cygwin/2000-06/msg01274.html +# - using gcc -mdll instead dllwrap doesn't work without -static because +# it tries to link against dlls instead their import libraries. (If +# it finds the dll first.) +# By specifying -static we force ld to link against the import libraries, +# this is windows standard and there are normally not the necessary symbols +# in the dlls. +# *** only the version of June 2000 shows these problems +# * cygwin gcc 3.2/ld 2.13.90 works +# (ld supports -shared) +# * mingw gcc 3.2/ld 2.13 works +# (ld supports -shared) +# * llvm-mingw with Clang 11 works +# (lld supports -shared) + +import os +import sys +import copy +import shlex +import warnings +from subprocess import check_output + +from distutils.unixccompiler import UnixCCompiler +from distutils.file_util import write_file +from distutils.errors import (DistutilsExecError, CCompilerError, + CompileError, UnknownFileError) +from distutils.version import LooseVersion, suppress_known_deprecation + +def get_msvcr(): + """Include the appropriate MSVC runtime library if Python was built + with MSVC 7.0 or later. + """ + msc_pos = sys.version.find('MSC v.') + if msc_pos != -1: + msc_ver = sys.version[msc_pos+6:msc_pos+10] + if msc_ver == '1300': + # MSVC 7.0 + return ['msvcr70'] + elif msc_ver == '1310': + # MSVC 7.1 + return ['msvcr71'] + elif msc_ver == '1400': + # VS2005 / MSVC 8.0 + return ['msvcr80'] + elif msc_ver == '1500': + # VS2008 / MSVC 9.0 + return ['msvcr90'] + elif msc_ver == '1600': + # VS2010 / MSVC 10.0 + return ['msvcr100'] + elif msc_ver == '1700': + # VS2012 / MSVC 11.0 + return ['msvcr110'] + elif msc_ver == '1800': + # VS2013 / MSVC 12.0 + return ['msvcr120'] + elif 1900 <= int(msc_ver) < 2000: + # VS2015 / MSVC 14.0 + return ['ucrt', 'vcruntime140'] + else: + raise ValueError("Unknown MS Compiler version %s " % msc_ver) + + +class CygwinCCompiler(UnixCCompiler): + """ Handles the Cygwin port of the GNU C compiler to Windows. + """ + compiler_type = 'cygwin' + obj_extension = ".o" + static_lib_extension = ".a" + shared_lib_extension = ".dll" + static_lib_format = "lib%s%s" + shared_lib_format = "%s%s" + exe_extension = ".exe" + + def __init__(self, verbose=0, dry_run=0, force=0): + + super().__init__(verbose, dry_run, force) + + status, details = check_config_h() + self.debug_print("Python's GCC status: %s (details: %s)" % + (status, details)) + if status is not CONFIG_H_OK: + self.warn( + "Python's pyconfig.h doesn't seem to support your compiler. " + "Reason: %s. " + "Compiling may fail because of undefined preprocessor macros." + % details) + + self.cc = os.environ.get('CC', 'gcc') + self.cxx = os.environ.get('CXX', 'g++') + + self.linker_dll = self.cc + shared_option = "-shared" + + self.set_executables(compiler='%s -mcygwin -O -Wall' % self.cc, + compiler_so='%s -mcygwin -mdll -O -Wall' % self.cc, + compiler_cxx='%s -mcygwin -O -Wall' % self.cxx, + linker_exe='%s -mcygwin' % self.cc, + linker_so=('%s -mcygwin %s' % + (self.linker_dll, shared_option))) + + # Include the appropriate MSVC runtime library if Python was built + # with MSVC 7.0 or later. + self.dll_libraries = get_msvcr() + + @property + def gcc_version(self): + # Older numpy dependend on this existing to check for ancient + # gcc versions. This doesn't make much sense with clang etc so + # just hardcode to something recent. + # https://github.com/numpy/numpy/pull/20333 + warnings.warn( + "gcc_version attribute of CygwinCCompiler is deprecated. " + "Instead of returning actual gcc version a fixed value 11.2.0 is returned.", + DeprecationWarning, + stacklevel=2, + ) + with suppress_known_deprecation(): + return LooseVersion("11.2.0") + + def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts): + """Compiles the source by spawning GCC and windres if needed.""" + if ext == '.rc' or ext == '.res': + # gcc needs '.res' and '.rc' compiled to object files !!! + try: + self.spawn(["windres", "-i", src, "-o", obj]) + except DistutilsExecError as msg: + raise CompileError(msg) + else: # for other files use the C-compiler + try: + self.spawn(self.compiler_so + cc_args + [src, '-o', obj] + + extra_postargs) + except DistutilsExecError as msg: + raise CompileError(msg) + + def link(self, target_desc, objects, output_filename, output_dir=None, + libraries=None, library_dirs=None, runtime_library_dirs=None, + export_symbols=None, debug=0, extra_preargs=None, + extra_postargs=None, build_temp=None, target_lang=None): + """Link the objects.""" + # use separate copies, so we can modify the lists + extra_preargs = copy.copy(extra_preargs or []) + libraries = copy.copy(libraries or []) + objects = copy.copy(objects or []) + + # Additional libraries + libraries.extend(self.dll_libraries) + + # handle export symbols by creating a def-file + # with executables this only works with gcc/ld as linker + if ((export_symbols is not None) and + (target_desc != self.EXECUTABLE or self.linker_dll == "gcc")): + # (The linker doesn't do anything if output is up-to-date. + # So it would probably better to check if we really need this, + # but for this we had to insert some unchanged parts of + # UnixCCompiler, and this is not what we want.) + + # we want to put some files in the same directory as the + # object files are, build_temp doesn't help much + # where are the object files + temp_dir = os.path.dirname(objects[0]) + # name of dll to give the helper files the same base name + (dll_name, dll_extension) = os.path.splitext( + os.path.basename(output_filename)) + + # generate the filenames for these files + def_file = os.path.join(temp_dir, dll_name + ".def") + lib_file = os.path.join(temp_dir, 'lib' + dll_name + ".a") + + # Generate .def file + contents = [ + "LIBRARY %s" % os.path.basename(output_filename), + "EXPORTS"] + for sym in export_symbols: + contents.append(sym) + self.execute(write_file, (def_file, contents), + "writing %s" % def_file) + + # next add options for def-file and to creating import libraries + + # doesn't work: bfd_close build\...\libfoo.a: Invalid operation + #extra_preargs.extend(["-Wl,--out-implib,%s" % lib_file]) + # for gcc/ld the def-file is specified as any object files + objects.append(def_file) + + #end: if ((export_symbols is not None) and + # (target_desc != self.EXECUTABLE or self.linker_dll == "gcc")): + + # who wants symbols and a many times larger output file + # should explicitly switch the debug mode on + # otherwise we let ld strip the output file + # (On my machine: 10KiB < stripped_file < ??100KiB + # unstripped_file = stripped_file + XXX KiB + # ( XXX=254 for a typical python extension)) + if not debug: + extra_preargs.append("-s") + + UnixCCompiler.link(self, target_desc, objects, output_filename, + output_dir, libraries, library_dirs, + runtime_library_dirs, + None, # export_symbols, we do this in our def-file + debug, extra_preargs, extra_postargs, build_temp, + target_lang) + + # -- Miscellaneous methods ----------------------------------------- + + def object_filenames(self, source_filenames, strip_dir=0, output_dir=''): + """Adds supports for rc and res files.""" + if output_dir is None: + output_dir = '' + obj_names = [] + for src_name in source_filenames: + # use normcase to make sure '.rc' is really '.rc' and not '.RC' + base, ext = os.path.splitext(os.path.normcase(src_name)) + if ext not in (self.src_extensions + ['.rc','.res']): + raise UnknownFileError("unknown file type '%s' (from '%s')" % \ + (ext, src_name)) + if strip_dir: + base = os.path.basename (base) + if ext in ('.res', '.rc'): + # these need to be compiled to object files + obj_names.append (os.path.join(output_dir, + base + ext + self.obj_extension)) + else: + obj_names.append (os.path.join(output_dir, + base + self.obj_extension)) + return obj_names + +# the same as cygwin plus some additional parameters +class Mingw32CCompiler(CygwinCCompiler): + """ Handles the Mingw32 port of the GNU C compiler to Windows. + """ + compiler_type = 'mingw32' + + def __init__(self, verbose=0, dry_run=0, force=0): + + super().__init__ (verbose, dry_run, force) + + shared_option = "-shared" + + if is_cygwincc(self.cc): + raise CCompilerError( + 'Cygwin gcc cannot be used with --compiler=mingw32') + + self.set_executables(compiler='%s -O -Wall' % self.cc, + compiler_so='%s -mdll -O -Wall' % self.cc, + compiler_cxx='%s -O -Wall' % self.cxx, + linker_exe='%s' % self.cc, + linker_so='%s %s' + % (self.linker_dll, shared_option)) + + # Maybe we should also append -mthreads, but then the finished + # dlls need another dll (mingwm10.dll see Mingw32 docs) + # (-mthreads: Support thread-safe exception handling on `Mingw32') + + # no additional libraries needed + self.dll_libraries=[] + + # Include the appropriate MSVC runtime library if Python was built + # with MSVC 7.0 or later. + self.dll_libraries = get_msvcr() + +# Because these compilers aren't configured in Python's pyconfig.h file by +# default, we should at least warn the user if he is using an unmodified +# version. + +CONFIG_H_OK = "ok" +CONFIG_H_NOTOK = "not ok" +CONFIG_H_UNCERTAIN = "uncertain" + +def check_config_h(): + """Check if the current Python installation appears amenable to building + extensions with GCC. + + Returns a tuple (status, details), where 'status' is one of the following + constants: + + - CONFIG_H_OK: all is well, go ahead and compile + - CONFIG_H_NOTOK: doesn't look good + - CONFIG_H_UNCERTAIN: not sure -- unable to read pyconfig.h + + 'details' is a human-readable string explaining the situation. + + Note there are two ways to conclude "OK": either 'sys.version' contains + the string "GCC" (implying that this Python was built with GCC), or the + installed "pyconfig.h" contains the string "__GNUC__". + """ + + # XXX since this function also checks sys.version, it's not strictly a + # "pyconfig.h" check -- should probably be renamed... + + from distutils import sysconfig + + # if sys.version contains GCC then python was compiled with GCC, and the + # pyconfig.h file should be OK + if "GCC" in sys.version: + return CONFIG_H_OK, "sys.version mentions 'GCC'" + + # Clang would also work + if "Clang" in sys.version: + return CONFIG_H_OK, "sys.version mentions 'Clang'" + + # let's see if __GNUC__ is mentioned in python.h + fn = sysconfig.get_config_h_filename() + try: + config_h = open(fn) + try: + if "__GNUC__" in config_h.read(): + return CONFIG_H_OK, "'%s' mentions '__GNUC__'" % fn + else: + return CONFIG_H_NOTOK, "'%s' does not mention '__GNUC__'" % fn + finally: + config_h.close() + except OSError as exc: + return (CONFIG_H_UNCERTAIN, + "couldn't read '%s': %s" % (fn, exc.strerror)) + +def is_cygwincc(cc): + '''Try to determine if the compiler that would be used is from cygwin.''' + out_string = check_output(shlex.split(cc) + ['-dumpmachine']) + return out_string.strip().endswith(b'cygwin') + + +get_versions = None +""" +A stand-in for the previous get_versions() function to prevent failures +when monkeypatched. See pypa/setuptools#2969. +""" diff --git a/venv/Lib/site-packages/setuptools/_distutils/debug.py b/venv/Lib/site-packages/setuptools/_distutils/debug.py new file mode 100644 index 0000000..daf1660 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_distutils/debug.py @@ -0,0 +1,5 @@ +import os + +# If DISTUTILS_DEBUG is anything other than the empty string, we run in +# debug mode. +DEBUG = os.environ.get('DISTUTILS_DEBUG') diff --git a/venv/Lib/site-packages/setuptools/_distutils/dep_util.py b/venv/Lib/site-packages/setuptools/_distutils/dep_util.py new file mode 100644 index 0000000..d74f5e4 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_distutils/dep_util.py @@ -0,0 +1,92 @@ +"""distutils.dep_util + +Utility functions for simple, timestamp-based dependency of files +and groups of files; also, function based entirely on such +timestamp dependency analysis.""" + +import os +from distutils.errors import DistutilsFileError + + +def newer (source, target): + """Return true if 'source' exists and is more recently modified than + 'target', or if 'source' exists and 'target' doesn't. Return false if + both exist and 'target' is the same age or younger than 'source'. + Raise DistutilsFileError if 'source' does not exist. + """ + if not os.path.exists(source): + raise DistutilsFileError("file '%s' does not exist" % + os.path.abspath(source)) + if not os.path.exists(target): + return 1 + + from stat import ST_MTIME + mtime1 = os.stat(source)[ST_MTIME] + mtime2 = os.stat(target)[ST_MTIME] + + return mtime1 > mtime2 + +# newer () + + +def newer_pairwise (sources, targets): + """Walk two filename lists in parallel, testing if each source is newer + than its corresponding target. Return a pair of lists (sources, + targets) where source is newer than target, according to the semantics + of 'newer()'. + """ + if len(sources) != len(targets): + raise ValueError("'sources' and 'targets' must be same length") + + # build a pair of lists (sources, targets) where source is newer + n_sources = [] + n_targets = [] + for i in range(len(sources)): + if newer(sources[i], targets[i]): + n_sources.append(sources[i]) + n_targets.append(targets[i]) + + return (n_sources, n_targets) + +# newer_pairwise () + + +def newer_group (sources, target, missing='error'): + """Return true if 'target' is out-of-date with respect to any file + listed in 'sources'. In other words, if 'target' exists and is newer + than every file in 'sources', return false; otherwise return true. + 'missing' controls what we do when a source file is missing; the + default ("error") is to blow up with an OSError from inside 'stat()'; + if it is "ignore", we silently drop any missing source files; if it is + "newer", any missing source files make us assume that 'target' is + out-of-date (this is handy in "dry-run" mode: it'll make you pretend to + carry out commands that wouldn't work because inputs are missing, but + that doesn't matter because you're not actually going to run the + commands). + """ + # If the target doesn't even exist, then it's definitely out-of-date. + if not os.path.exists(target): + return 1 + + # Otherwise we have to find out the hard way: if *any* source file + # is more recent than 'target', then 'target' is out-of-date and + # we can immediately return true. If we fall through to the end + # of the loop, then 'target' is up-to-date and we return false. + from stat import ST_MTIME + target_mtime = os.stat(target)[ST_MTIME] + for source in sources: + if not os.path.exists(source): + if missing == 'error': # blow up when we stat() the file + pass + elif missing == 'ignore': # missing source dropped from + continue # target's dependency list + elif missing == 'newer': # missing source means target is + return 1 # out-of-date + + source_mtime = os.stat(source)[ST_MTIME] + if source_mtime > target_mtime: + return 1 + else: + return 0 + +# newer_group () diff --git a/venv/Lib/site-packages/setuptools/_distutils/dir_util.py b/venv/Lib/site-packages/setuptools/_distutils/dir_util.py new file mode 100644 index 0000000..d5cd8e3 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_distutils/dir_util.py @@ -0,0 +1,210 @@ +"""distutils.dir_util + +Utility functions for manipulating directories and directory trees.""" + +import os +import errno +from distutils.errors import DistutilsFileError, DistutilsInternalError +from distutils import log + +# cache for by mkpath() -- in addition to cheapening redundant calls, +# eliminates redundant "creating /foo/bar/baz" messages in dry-run mode +_path_created = {} + +# I don't use os.makedirs because a) it's new to Python 1.5.2, and +# b) it blows up if the directory already exists (I want to silently +# succeed in that case). +def mkpath(name, mode=0o777, verbose=1, dry_run=0): + """Create a directory and any missing ancestor directories. + + If the directory already exists (or if 'name' is the empty string, which + means the current directory, which of course exists), then do nothing. + Raise DistutilsFileError if unable to create some directory along the way + (eg. some sub-path exists, but is a file rather than a directory). + If 'verbose' is true, print a one-line summary of each mkdir to stdout. + Return the list of directories actually created. + """ + + global _path_created + + # Detect a common bug -- name is None + if not isinstance(name, str): + raise DistutilsInternalError( + "mkpath: 'name' must be a string (got %r)" % (name,)) + + # XXX what's the better way to handle verbosity? print as we create + # each directory in the path (the current behaviour), or only announce + # the creation of the whole path? (quite easy to do the latter since + # we're not using a recursive algorithm) + + name = os.path.normpath(name) + created_dirs = [] + if os.path.isdir(name) or name == '': + return created_dirs + if _path_created.get(os.path.abspath(name)): + return created_dirs + + (head, tail) = os.path.split(name) + tails = [tail] # stack of lone dirs to create + + while head and tail and not os.path.isdir(head): + (head, tail) = os.path.split(head) + tails.insert(0, tail) # push next higher dir onto stack + + # now 'head' contains the deepest directory that already exists + # (that is, the child of 'head' in 'name' is the highest directory + # that does *not* exist) + for d in tails: + #print "head = %s, d = %s: " % (head, d), + head = os.path.join(head, d) + abs_head = os.path.abspath(head) + + if _path_created.get(abs_head): + continue + + if verbose >= 1: + log.info("creating %s", head) + + if not dry_run: + try: + os.mkdir(head, mode) + except OSError as exc: + if not (exc.errno == errno.EEXIST and os.path.isdir(head)): + raise DistutilsFileError( + "could not create '%s': %s" % (head, exc.args[-1])) + created_dirs.append(head) + + _path_created[abs_head] = 1 + return created_dirs + +def create_tree(base_dir, files, mode=0o777, verbose=1, dry_run=0): + """Create all the empty directories under 'base_dir' needed to put 'files' + there. + + 'base_dir' is just the name of a directory which doesn't necessarily + exist yet; 'files' is a list of filenames to be interpreted relative to + 'base_dir'. 'base_dir' + the directory portion of every file in 'files' + will be created if it doesn't already exist. 'mode', 'verbose' and + 'dry_run' flags are as for 'mkpath()'. + """ + # First get the list of directories to create + need_dir = set() + for file in files: + need_dir.add(os.path.join(base_dir, os.path.dirname(file))) + + # Now create them + for dir in sorted(need_dir): + mkpath(dir, mode, verbose=verbose, dry_run=dry_run) + +def copy_tree(src, dst, preserve_mode=1, preserve_times=1, + preserve_symlinks=0, update=0, verbose=1, dry_run=0): + """Copy an entire directory tree 'src' to a new location 'dst'. + + Both 'src' and 'dst' must be directory names. If 'src' is not a + directory, raise DistutilsFileError. If 'dst' does not exist, it is + created with 'mkpath()'. The end result of the copy is that every + file in 'src' is copied to 'dst', and directories under 'src' are + recursively copied to 'dst'. Return the list of files that were + copied or might have been copied, using their output name. The + return value is unaffected by 'update' or 'dry_run': it is simply + the list of all files under 'src', with the names changed to be + under 'dst'. + + 'preserve_mode' and 'preserve_times' are the same as for + 'copy_file'; note that they only apply to regular files, not to + directories. If 'preserve_symlinks' is true, symlinks will be + copied as symlinks (on platforms that support them!); otherwise + (the default), the destination of the symlink will be copied. + 'update' and 'verbose' are the same as for 'copy_file'. + """ + from distutils.file_util import copy_file + + if not dry_run and not os.path.isdir(src): + raise DistutilsFileError( + "cannot copy tree '%s': not a directory" % src) + try: + names = os.listdir(src) + except OSError as e: + if dry_run: + names = [] + else: + raise DistutilsFileError( + "error listing files in '%s': %s" % (src, e.strerror)) + + if not dry_run: + mkpath(dst, verbose=verbose) + + outputs = [] + + for n in names: + src_name = os.path.join(src, n) + dst_name = os.path.join(dst, n) + + if n.startswith('.nfs'): + # skip NFS rename files + continue + + if preserve_symlinks and os.path.islink(src_name): + link_dest = os.readlink(src_name) + if verbose >= 1: + log.info("linking %s -> %s", dst_name, link_dest) + if not dry_run: + os.symlink(link_dest, dst_name) + outputs.append(dst_name) + + elif os.path.isdir(src_name): + outputs.extend( + copy_tree(src_name, dst_name, preserve_mode, + preserve_times, preserve_symlinks, update, + verbose=verbose, dry_run=dry_run)) + else: + copy_file(src_name, dst_name, preserve_mode, + preserve_times, update, verbose=verbose, + dry_run=dry_run) + outputs.append(dst_name) + + return outputs + +def _build_cmdtuple(path, cmdtuples): + """Helper for remove_tree().""" + for f in os.listdir(path): + real_f = os.path.join(path,f) + if os.path.isdir(real_f) and not os.path.islink(real_f): + _build_cmdtuple(real_f, cmdtuples) + else: + cmdtuples.append((os.remove, real_f)) + cmdtuples.append((os.rmdir, path)) + +def remove_tree(directory, verbose=1, dry_run=0): + """Recursively remove an entire directory tree. + + Any errors are ignored (apart from being reported to stdout if 'verbose' + is true). + """ + global _path_created + + if verbose >= 1: + log.info("removing '%s' (and everything under it)", directory) + if dry_run: + return + cmdtuples = [] + _build_cmdtuple(directory, cmdtuples) + for cmd in cmdtuples: + try: + cmd[0](cmd[1]) + # remove dir from cache if it's already there + abspath = os.path.abspath(cmd[1]) + if abspath in _path_created: + del _path_created[abspath] + except OSError as exc: + log.warn("error removing %s: %s", directory, exc) + +def ensure_relative(path): + """Take the full path 'path', and make it a relative path. + + This is useful to make 'path' the second argument to os.path.join(). + """ + drive, path = os.path.splitdrive(path) + if path[0:1] == os.sep: + path = drive + path[1:] + return path diff --git a/venv/Lib/site-packages/setuptools/_distutils/dist.py b/venv/Lib/site-packages/setuptools/_distutils/dist.py new file mode 100644 index 0000000..37db4d6 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_distutils/dist.py @@ -0,0 +1,1257 @@ +"""distutils.dist + +Provides the Distribution class, which represents the module distribution +being built/installed/distributed. +""" + +import sys +import os +import re +from email import message_from_file + +try: + import warnings +except ImportError: + warnings = None + +from distutils.errors import * +from distutils.fancy_getopt import FancyGetopt, translate_longopt +from distutils.util import check_environ, strtobool, rfc822_escape +from distutils import log +from distutils.debug import DEBUG + +# Regex to define acceptable Distutils command names. This is not *quite* +# the same as a Python NAME -- I don't allow leading underscores. The fact +# that they're very similar is no coincidence; the default naming scheme is +# to look for a Python module named after the command. +command_re = re.compile(r'^[a-zA-Z]([a-zA-Z0-9_]*)$') + + +def _ensure_list(value, fieldname): + if isinstance(value, str): + # a string containing comma separated values is okay. It will + # be converted to a list by Distribution.finalize_options(). + pass + elif not isinstance(value, list): + # passing a tuple or an iterator perhaps, warn and convert + typename = type(value).__name__ + msg = "Warning: '{fieldname}' should be a list, got type '{typename}'" + msg = msg.format(**locals()) + log.log(log.WARN, msg) + value = list(value) + return value + + +class Distribution: + """The core of the Distutils. Most of the work hiding behind 'setup' + is really done within a Distribution instance, which farms the work out + to the Distutils commands specified on the command line. + + Setup scripts will almost never instantiate Distribution directly, + unless the 'setup()' function is totally inadequate to their needs. + However, it is conceivable that a setup script might wish to subclass + Distribution for some specialized purpose, and then pass the subclass + to 'setup()' as the 'distclass' keyword argument. If so, it is + necessary to respect the expectations that 'setup' has of Distribution. + See the code for 'setup()', in core.py, for details. + """ + + # 'global_options' describes the command-line options that may be + # supplied to the setup script prior to any actual commands. + # Eg. "./setup.py -n" or "./setup.py --quiet" both take advantage of + # these global options. This list should be kept to a bare minimum, + # since every global option is also valid as a command option -- and we + # don't want to pollute the commands with too many options that they + # have minimal control over. + # The fourth entry for verbose means that it can be repeated. + global_options = [ + ('verbose', 'v', "run verbosely (default)", 1), + ('quiet', 'q', "run quietly (turns verbosity off)"), + ('dry-run', 'n', "don't actually do anything"), + ('help', 'h', "show detailed help message"), + ('no-user-cfg', None, + 'ignore pydistutils.cfg in your home directory'), + ] + + # 'common_usage' is a short (2-3 line) string describing the common + # usage of the setup script. + common_usage = """\ +Common commands: (see '--help-commands' for more) + + setup.py build will build the package underneath 'build/' + setup.py install will install the package +""" + + # options that are not propagated to the commands + display_options = [ + ('help-commands', None, + "list all available commands"), + ('name', None, + "print package name"), + ('version', 'V', + "print package version"), + ('fullname', None, + "print -"), + ('author', None, + "print the author's name"), + ('author-email', None, + "print the author's email address"), + ('maintainer', None, + "print the maintainer's name"), + ('maintainer-email', None, + "print the maintainer's email address"), + ('contact', None, + "print the maintainer's name if known, else the author's"), + ('contact-email', None, + "print the maintainer's email address if known, else the author's"), + ('url', None, + "print the URL for this package"), + ('license', None, + "print the license of the package"), + ('licence', None, + "alias for --license"), + ('description', None, + "print the package description"), + ('long-description', None, + "print the long package description"), + ('platforms', None, + "print the list of platforms"), + ('classifiers', None, + "print the list of classifiers"), + ('keywords', None, + "print the list of keywords"), + ('provides', None, + "print the list of packages/modules provided"), + ('requires', None, + "print the list of packages/modules required"), + ('obsoletes', None, + "print the list of packages/modules made obsolete") + ] + display_option_names = [translate_longopt(x[0]) for x in display_options] + + # negative options are options that exclude other options + negative_opt = {'quiet': 'verbose'} + + # -- Creation/initialization methods ------------------------------- + + def __init__(self, attrs=None): + """Construct a new Distribution instance: initialize all the + attributes of a Distribution, and then use 'attrs' (a dictionary + mapping attribute names to values) to assign some of those + attributes their "real" values. (Any attributes not mentioned in + 'attrs' will be assigned to some null value: 0, None, an empty list + or dictionary, etc.) Most importantly, initialize the + 'command_obj' attribute to the empty dictionary; this will be + filled in with real command objects by 'parse_command_line()'. + """ + + # Default values for our command-line options + self.verbose = 1 + self.dry_run = 0 + self.help = 0 + for attr in self.display_option_names: + setattr(self, attr, 0) + + # Store the distribution meta-data (name, version, author, and so + # forth) in a separate object -- we're getting to have enough + # information here (and enough command-line options) that it's + # worth it. Also delegate 'get_XXX()' methods to the 'metadata' + # object in a sneaky and underhanded (but efficient!) way. + self.metadata = DistributionMetadata() + for basename in self.metadata._METHOD_BASENAMES: + method_name = "get_" + basename + setattr(self, method_name, getattr(self.metadata, method_name)) + + # 'cmdclass' maps command names to class objects, so we + # can 1) quickly figure out which class to instantiate when + # we need to create a new command object, and 2) have a way + # for the setup script to override command classes + self.cmdclass = {} + + # 'command_packages' is a list of packages in which commands + # are searched for. The factory for command 'foo' is expected + # to be named 'foo' in the module 'foo' in one of the packages + # named here. This list is searched from the left; an error + # is raised if no named package provides the command being + # searched for. (Always access using get_command_packages().) + self.command_packages = None + + # 'script_name' and 'script_args' are usually set to sys.argv[0] + # and sys.argv[1:], but they can be overridden when the caller is + # not necessarily a setup script run from the command-line. + self.script_name = None + self.script_args = None + + # 'command_options' is where we store command options between + # parsing them (from config files, the command-line, etc.) and when + # they are actually needed -- ie. when the command in question is + # instantiated. It is a dictionary of dictionaries of 2-tuples: + # command_options = { command_name : { option : (source, value) } } + self.command_options = {} + + # 'dist_files' is the list of (command, pyversion, file) that + # have been created by any dist commands run so far. This is + # filled regardless of whether the run is dry or not. pyversion + # gives sysconfig.get_python_version() if the dist file is + # specific to a Python version, 'any' if it is good for all + # Python versions on the target platform, and '' for a source + # file. pyversion should not be used to specify minimum or + # maximum required Python versions; use the metainfo for that + # instead. + self.dist_files = [] + + # These options are really the business of various commands, rather + # than of the Distribution itself. We provide aliases for them in + # Distribution as a convenience to the developer. + self.packages = None + self.package_data = {} + self.package_dir = None + self.py_modules = None + self.libraries = None + self.headers = None + self.ext_modules = None + self.ext_package = None + self.include_dirs = None + self.extra_path = None + self.scripts = None + self.data_files = None + self.password = '' + + # And now initialize bookkeeping stuff that can't be supplied by + # the caller at all. 'command_obj' maps command names to + # Command instances -- that's how we enforce that every command + # class is a singleton. + self.command_obj = {} + + # 'have_run' maps command names to boolean values; it keeps track + # of whether we have actually run a particular command, to make it + # cheap to "run" a command whenever we think we might need to -- if + # it's already been done, no need for expensive filesystem + # operations, we just check the 'have_run' dictionary and carry on. + # It's only safe to query 'have_run' for a command class that has + # been instantiated -- a false value will be inserted when the + # command object is created, and replaced with a true value when + # the command is successfully run. Thus it's probably best to use + # '.get()' rather than a straight lookup. + self.have_run = {} + + # Now we'll use the attrs dictionary (ultimately, keyword args from + # the setup script) to possibly override any or all of these + # distribution options. + + if attrs: + # Pull out the set of command options and work on them + # specifically. Note that this order guarantees that aliased + # command options will override any supplied redundantly + # through the general options dictionary. + options = attrs.get('options') + if options is not None: + del attrs['options'] + for (command, cmd_options) in options.items(): + opt_dict = self.get_option_dict(command) + for (opt, val) in cmd_options.items(): + opt_dict[opt] = ("setup script", val) + + if 'licence' in attrs: + attrs['license'] = attrs['licence'] + del attrs['licence'] + msg = "'licence' distribution option is deprecated; use 'license'" + if warnings is not None: + warnings.warn(msg) + else: + sys.stderr.write(msg + "\n") + + # Now work on the rest of the attributes. Any attribute that's + # not already defined is invalid! + for (key, val) in attrs.items(): + if hasattr(self.metadata, "set_" + key): + getattr(self.metadata, "set_" + key)(val) + elif hasattr(self.metadata, key): + setattr(self.metadata, key, val) + elif hasattr(self, key): + setattr(self, key, val) + else: + msg = "Unknown distribution option: %s" % repr(key) + warnings.warn(msg) + + # no-user-cfg is handled before other command line args + # because other args override the config files, and this + # one is needed before we can load the config files. + # If attrs['script_args'] wasn't passed, assume false. + # + # This also make sure we just look at the global options + self.want_user_cfg = True + + if self.script_args is not None: + for arg in self.script_args: + if not arg.startswith('-'): + break + if arg == '--no-user-cfg': + self.want_user_cfg = False + break + + self.finalize_options() + + def get_option_dict(self, command): + """Get the option dictionary for a given command. If that + command's option dictionary hasn't been created yet, then create it + and return the new dictionary; otherwise, return the existing + option dictionary. + """ + dict = self.command_options.get(command) + if dict is None: + dict = self.command_options[command] = {} + return dict + + def dump_option_dicts(self, header=None, commands=None, indent=""): + from pprint import pformat + + if commands is None: # dump all command option dicts + commands = sorted(self.command_options.keys()) + + if header is not None: + self.announce(indent + header) + indent = indent + " " + + if not commands: + self.announce(indent + "no commands known yet") + return + + for cmd_name in commands: + opt_dict = self.command_options.get(cmd_name) + if opt_dict is None: + self.announce(indent + + "no option dict for '%s' command" % cmd_name) + else: + self.announce(indent + + "option dict for '%s' command:" % cmd_name) + out = pformat(opt_dict) + for line in out.split('\n'): + self.announce(indent + " " + line) + + # -- Config file finding/parsing methods --------------------------- + + def find_config_files(self): + """Find as many configuration files as should be processed for this + platform, and return a list of filenames in the order in which they + should be parsed. The filenames returned are guaranteed to exist + (modulo nasty race conditions). + + There are three possible config files: distutils.cfg in the + Distutils installation directory (ie. where the top-level + Distutils __inst__.py file lives), a file in the user's home + directory named .pydistutils.cfg on Unix and pydistutils.cfg + on Windows/Mac; and setup.cfg in the current directory. + + The file in the user's home directory can be disabled with the + --no-user-cfg option. + """ + files = [] + check_environ() + + # Where to look for the system-wide Distutils config file + sys_dir = os.path.dirname(sys.modules['distutils'].__file__) + + # Look for the system config file + sys_file = os.path.join(sys_dir, "distutils.cfg") + if os.path.isfile(sys_file): + files.append(sys_file) + + # What to call the per-user config file + if os.name == 'posix': + user_filename = ".pydistutils.cfg" + else: + user_filename = "pydistutils.cfg" + + # And look for the user config file + if self.want_user_cfg: + user_file = os.path.join(os.path.expanduser('~'), user_filename) + if os.path.isfile(user_file): + files.append(user_file) + + # All platforms support local setup.cfg + local_file = "setup.cfg" + if os.path.isfile(local_file): + files.append(local_file) + + if DEBUG: + self.announce("using config files: %s" % ', '.join(files)) + + return files + + def parse_config_files(self, filenames=None): + from configparser import ConfigParser + + # Ignore install directory options if we have a venv + if sys.prefix != sys.base_prefix: + ignore_options = [ + 'install-base', 'install-platbase', 'install-lib', + 'install-platlib', 'install-purelib', 'install-headers', + 'install-scripts', 'install-data', 'prefix', 'exec-prefix', + 'home', 'user', 'root'] + else: + ignore_options = [] + + ignore_options = frozenset(ignore_options) + + if filenames is None: + filenames = self.find_config_files() + + if DEBUG: + self.announce("Distribution.parse_config_files():") + + parser = ConfigParser() + for filename in filenames: + if DEBUG: + self.announce(" reading %s" % filename) + parser.read(filename) + for section in parser.sections(): + options = parser.options(section) + opt_dict = self.get_option_dict(section) + + for opt in options: + if opt != '__name__' and opt not in ignore_options: + val = parser.get(section,opt) + opt = opt.replace('-', '_') + opt_dict[opt] = (filename, val) + + # Make the ConfigParser forget everything (so we retain + # the original filenames that options come from) + parser.__init__() + + # If there was a "global" section in the config file, use it + # to set Distribution options. + + if 'global' in self.command_options: + for (opt, (src, val)) in self.command_options['global'].items(): + alias = self.negative_opt.get(opt) + try: + if alias: + setattr(self, alias, not strtobool(val)) + elif opt in ('verbose', 'dry_run'): # ugh! + setattr(self, opt, strtobool(val)) + else: + setattr(self, opt, val) + except ValueError as msg: + raise DistutilsOptionError(msg) + + # -- Command-line parsing methods ---------------------------------- + + def parse_command_line(self): + """Parse the setup script's command line, taken from the + 'script_args' instance attribute (which defaults to 'sys.argv[1:]' + -- see 'setup()' in core.py). This list is first processed for + "global options" -- options that set attributes of the Distribution + instance. Then, it is alternately scanned for Distutils commands + and options for that command. Each new command terminates the + options for the previous command. The allowed options for a + command are determined by the 'user_options' attribute of the + command class -- thus, we have to be able to load command classes + in order to parse the command line. Any error in that 'options' + attribute raises DistutilsGetoptError; any error on the + command-line raises DistutilsArgError. If no Distutils commands + were found on the command line, raises DistutilsArgError. Return + true if command-line was successfully parsed and we should carry + on with executing commands; false if no errors but we shouldn't + execute commands (currently, this only happens if user asks for + help). + """ + # + # We now have enough information to show the Macintosh dialog + # that allows the user to interactively specify the "command line". + # + toplevel_options = self._get_toplevel_options() + + # We have to parse the command line a bit at a time -- global + # options, then the first command, then its options, and so on -- + # because each command will be handled by a different class, and + # the options that are valid for a particular class aren't known + # until we have loaded the command class, which doesn't happen + # until we know what the command is. + + self.commands = [] + parser = FancyGetopt(toplevel_options + self.display_options) + parser.set_negative_aliases(self.negative_opt) + parser.set_aliases({'licence': 'license'}) + args = parser.getopt(args=self.script_args, object=self) + option_order = parser.get_option_order() + log.set_verbosity(self.verbose) + + # for display options we return immediately + if self.handle_display_options(option_order): + return + while args: + args = self._parse_command_opts(parser, args) + if args is None: # user asked for help (and got it) + return + + # Handle the cases of --help as a "global" option, ie. + # "setup.py --help" and "setup.py --help command ...". For the + # former, we show global options (--verbose, --dry-run, etc.) + # and display-only options (--name, --version, etc.); for the + # latter, we omit the display-only options and show help for + # each command listed on the command line. + if self.help: + self._show_help(parser, + display_options=len(self.commands) == 0, + commands=self.commands) + return + + # Oops, no commands found -- an end-user error + if not self.commands: + raise DistutilsArgError("no commands supplied") + + # All is well: return true + return True + + def _get_toplevel_options(self): + """Return the non-display options recognized at the top level. + + This includes options that are recognized *only* at the top + level as well as options recognized for commands. + """ + return self.global_options + [ + ("command-packages=", None, + "list of packages that provide distutils commands"), + ] + + def _parse_command_opts(self, parser, args): + """Parse the command-line options for a single command. + 'parser' must be a FancyGetopt instance; 'args' must be the list + of arguments, starting with the current command (whose options + we are about to parse). Returns a new version of 'args' with + the next command at the front of the list; will be the empty + list if there are no more commands on the command line. Returns + None if the user asked for help on this command. + """ + # late import because of mutual dependence between these modules + from distutils.cmd import Command + + # Pull the current command from the head of the command line + command = args[0] + if not command_re.match(command): + raise SystemExit("invalid command name '%s'" % command) + self.commands.append(command) + + # Dig up the command class that implements this command, so we + # 1) know that it's a valid command, and 2) know which options + # it takes. + try: + cmd_class = self.get_command_class(command) + except DistutilsModuleError as msg: + raise DistutilsArgError(msg) + + # Require that the command class be derived from Command -- want + # to be sure that the basic "command" interface is implemented. + if not issubclass(cmd_class, Command): + raise DistutilsClassError( + "command class %s must subclass Command" % cmd_class) + + # Also make sure that the command object provides a list of its + # known options. + if not (hasattr(cmd_class, 'user_options') and + isinstance(cmd_class.user_options, list)): + msg = ("command class %s must provide " + "'user_options' attribute (a list of tuples)") + raise DistutilsClassError(msg % cmd_class) + + # If the command class has a list of negative alias options, + # merge it in with the global negative aliases. + negative_opt = self.negative_opt + if hasattr(cmd_class, 'negative_opt'): + negative_opt = negative_opt.copy() + negative_opt.update(cmd_class.negative_opt) + + # Check for help_options in command class. They have a different + # format (tuple of four) so we need to preprocess them here. + if (hasattr(cmd_class, 'help_options') and + isinstance(cmd_class.help_options, list)): + help_options = fix_help_options(cmd_class.help_options) + else: + help_options = [] + + # All commands support the global options too, just by adding + # in 'global_options'. + parser.set_option_table(self.global_options + + cmd_class.user_options + + help_options) + parser.set_negative_aliases(negative_opt) + (args, opts) = parser.getopt(args[1:]) + if hasattr(opts, 'help') and opts.help: + self._show_help(parser, display_options=0, commands=[cmd_class]) + return + + if (hasattr(cmd_class, 'help_options') and + isinstance(cmd_class.help_options, list)): + help_option_found=0 + for (help_option, short, desc, func) in cmd_class.help_options: + if hasattr(opts, parser.get_attr_name(help_option)): + help_option_found=1 + if callable(func): + func() + else: + raise DistutilsClassError( + "invalid help function %r for help option '%s': " + "must be a callable object (function, etc.)" + % (func, help_option)) + + if help_option_found: + return + + # Put the options from the command-line into their official + # holding pen, the 'command_options' dictionary. + opt_dict = self.get_option_dict(command) + for (name, value) in vars(opts).items(): + opt_dict[name] = ("command line", value) + + return args + + def finalize_options(self): + """Set final values for all the options on the Distribution + instance, analogous to the .finalize_options() method of Command + objects. + """ + for attr in ('keywords', 'platforms'): + value = getattr(self.metadata, attr) + if value is None: + continue + if isinstance(value, str): + value = [elm.strip() for elm in value.split(',')] + setattr(self.metadata, attr, value) + + def _show_help(self, parser, global_options=1, display_options=1, + commands=[]): + """Show help for the setup script command-line in the form of + several lists of command-line options. 'parser' should be a + FancyGetopt instance; do not expect it to be returned in the + same state, as its option table will be reset to make it + generate the correct help text. + + If 'global_options' is true, lists the global options: + --verbose, --dry-run, etc. If 'display_options' is true, lists + the "display-only" options: --name, --version, etc. Finally, + lists per-command help for every command name or command class + in 'commands'. + """ + # late import because of mutual dependence between these modules + from distutils.core import gen_usage + from distutils.cmd import Command + + if global_options: + if display_options: + options = self._get_toplevel_options() + else: + options = self.global_options + parser.set_option_table(options) + parser.print_help(self.common_usage + "\nGlobal options:") + print('') + + if display_options: + parser.set_option_table(self.display_options) + parser.print_help( + "Information display options (just display " + + "information, ignore any commands)") + print('') + + for command in self.commands: + if isinstance(command, type) and issubclass(command, Command): + klass = command + else: + klass = self.get_command_class(command) + if (hasattr(klass, 'help_options') and + isinstance(klass.help_options, list)): + parser.set_option_table(klass.user_options + + fix_help_options(klass.help_options)) + else: + parser.set_option_table(klass.user_options) + parser.print_help("Options for '%s' command:" % klass.__name__) + print('') + + print(gen_usage(self.script_name)) + + def handle_display_options(self, option_order): + """If there were any non-global "display-only" options + (--help-commands or the metadata display options) on the command + line, display the requested info and return true; else return + false. + """ + from distutils.core import gen_usage + + # User just wants a list of commands -- we'll print it out and stop + # processing now (ie. if they ran "setup --help-commands foo bar", + # we ignore "foo bar"). + if self.help_commands: + self.print_commands() + print('') + print(gen_usage(self.script_name)) + return 1 + + # If user supplied any of the "display metadata" options, then + # display that metadata in the order in which the user supplied the + # metadata options. + any_display_options = 0 + is_display_option = {} + for option in self.display_options: + is_display_option[option[0]] = 1 + + for (opt, val) in option_order: + if val and is_display_option.get(opt): + opt = translate_longopt(opt) + value = getattr(self.metadata, "get_"+opt)() + if opt in ['keywords', 'platforms']: + print(','.join(value)) + elif opt in ('classifiers', 'provides', 'requires', + 'obsoletes'): + print('\n'.join(value)) + else: + print(value) + any_display_options = 1 + + return any_display_options + + def print_command_list(self, commands, header, max_length): + """Print a subset of the list of all commands -- used by + 'print_commands()'. + """ + print(header + ":") + + for cmd in commands: + klass = self.cmdclass.get(cmd) + if not klass: + klass = self.get_command_class(cmd) + try: + description = klass.description + except AttributeError: + description = "(no description available)" + + print(" %-*s %s" % (max_length, cmd, description)) + + def print_commands(self): + """Print out a help message listing all available commands with a + description of each. The list is divided into "standard commands" + (listed in distutils.command.__all__) and "extra commands" + (mentioned in self.cmdclass, but not a standard command). The + descriptions come from the command class attribute + 'description'. + """ + import distutils.command + std_commands = distutils.command.__all__ + is_std = {} + for cmd in std_commands: + is_std[cmd] = 1 + + extra_commands = [] + for cmd in self.cmdclass.keys(): + if not is_std.get(cmd): + extra_commands.append(cmd) + + max_length = 0 + for cmd in (std_commands + extra_commands): + if len(cmd) > max_length: + max_length = len(cmd) + + self.print_command_list(std_commands, + "Standard commands", + max_length) + if extra_commands: + print() + self.print_command_list(extra_commands, + "Extra commands", + max_length) + + def get_command_list(self): + """Get a list of (command, description) tuples. + The list is divided into "standard commands" (listed in + distutils.command.__all__) and "extra commands" (mentioned in + self.cmdclass, but not a standard command). The descriptions come + from the command class attribute 'description'. + """ + # Currently this is only used on Mac OS, for the Mac-only GUI + # Distutils interface (by Jack Jansen) + import distutils.command + std_commands = distutils.command.__all__ + is_std = {} + for cmd in std_commands: + is_std[cmd] = 1 + + extra_commands = [] + for cmd in self.cmdclass.keys(): + if not is_std.get(cmd): + extra_commands.append(cmd) + + rv = [] + for cmd in (std_commands + extra_commands): + klass = self.cmdclass.get(cmd) + if not klass: + klass = self.get_command_class(cmd) + try: + description = klass.description + except AttributeError: + description = "(no description available)" + rv.append((cmd, description)) + return rv + + # -- Command class/object methods ---------------------------------- + + def get_command_packages(self): + """Return a list of packages from which commands are loaded.""" + pkgs = self.command_packages + if not isinstance(pkgs, list): + if pkgs is None: + pkgs = '' + pkgs = [pkg.strip() for pkg in pkgs.split(',') if pkg != ''] + if "distutils.command" not in pkgs: + pkgs.insert(0, "distutils.command") + self.command_packages = pkgs + return pkgs + + def get_command_class(self, command): + """Return the class that implements the Distutils command named by + 'command'. First we check the 'cmdclass' dictionary; if the + command is mentioned there, we fetch the class object from the + dictionary and return it. Otherwise we load the command module + ("distutils.command." + command) and fetch the command class from + the module. The loaded class is also stored in 'cmdclass' + to speed future calls to 'get_command_class()'. + + Raises DistutilsModuleError if the expected module could not be + found, or if that module does not define the expected class. + """ + klass = self.cmdclass.get(command) + if klass: + return klass + + for pkgname in self.get_command_packages(): + module_name = "%s.%s" % (pkgname, command) + klass_name = command + + try: + __import__(module_name) + module = sys.modules[module_name] + except ImportError: + continue + + try: + klass = getattr(module, klass_name) + except AttributeError: + raise DistutilsModuleError( + "invalid command '%s' (no class '%s' in module '%s')" + % (command, klass_name, module_name)) + + self.cmdclass[command] = klass + return klass + + raise DistutilsModuleError("invalid command '%s'" % command) + + def get_command_obj(self, command, create=1): + """Return the command object for 'command'. Normally this object + is cached on a previous call to 'get_command_obj()'; if no command + object for 'command' is in the cache, then we either create and + return it (if 'create' is true) or return None. + """ + cmd_obj = self.command_obj.get(command) + if not cmd_obj and create: + if DEBUG: + self.announce("Distribution.get_command_obj(): " + "creating '%s' command object" % command) + + klass = self.get_command_class(command) + cmd_obj = self.command_obj[command] = klass(self) + self.have_run[command] = 0 + + # Set any options that were supplied in config files + # or on the command line. (NB. support for error + # reporting is lame here: any errors aren't reported + # until 'finalize_options()' is called, which means + # we won't report the source of the error.) + options = self.command_options.get(command) + if options: + self._set_command_options(cmd_obj, options) + + return cmd_obj + + def _set_command_options(self, command_obj, option_dict=None): + """Set the options for 'command_obj' from 'option_dict'. Basically + this means copying elements of a dictionary ('option_dict') to + attributes of an instance ('command'). + + 'command_obj' must be a Command instance. If 'option_dict' is not + supplied, uses the standard option dictionary for this command + (from 'self.command_options'). + """ + command_name = command_obj.get_command_name() + if option_dict is None: + option_dict = self.get_option_dict(command_name) + + if DEBUG: + self.announce(" setting options for '%s' command:" % command_name) + for (option, (source, value)) in option_dict.items(): + if DEBUG: + self.announce(" %s = %s (from %s)" % (option, value, + source)) + try: + bool_opts = [translate_longopt(o) + for o in command_obj.boolean_options] + except AttributeError: + bool_opts = [] + try: + neg_opt = command_obj.negative_opt + except AttributeError: + neg_opt = {} + + try: + is_string = isinstance(value, str) + if option in neg_opt and is_string: + setattr(command_obj, neg_opt[option], not strtobool(value)) + elif option in bool_opts and is_string: + setattr(command_obj, option, strtobool(value)) + elif hasattr(command_obj, option): + setattr(command_obj, option, value) + else: + raise DistutilsOptionError( + "error in %s: command '%s' has no such option '%s'" + % (source, command_name, option)) + except ValueError as msg: + raise DistutilsOptionError(msg) + + def reinitialize_command(self, command, reinit_subcommands=0): + """Reinitializes a command to the state it was in when first + returned by 'get_command_obj()': ie., initialized but not yet + finalized. This provides the opportunity to sneak option + values in programmatically, overriding or supplementing + user-supplied values from the config files and command line. + You'll have to re-finalize the command object (by calling + 'finalize_options()' or 'ensure_finalized()') before using it for + real. + + 'command' should be a command name (string) or command object. If + 'reinit_subcommands' is true, also reinitializes the command's + sub-commands, as declared by the 'sub_commands' class attribute (if + it has one). See the "install" command for an example. Only + reinitializes the sub-commands that actually matter, ie. those + whose test predicates return true. + + Returns the reinitialized command object. + """ + from distutils.cmd import Command + if not isinstance(command, Command): + command_name = command + command = self.get_command_obj(command_name) + else: + command_name = command.get_command_name() + + if not command.finalized: + return command + command.initialize_options() + command.finalized = 0 + self.have_run[command_name] = 0 + self._set_command_options(command) + + if reinit_subcommands: + for sub in command.get_sub_commands(): + self.reinitialize_command(sub, reinit_subcommands) + + return command + + # -- Methods that operate on the Distribution ---------------------- + + def announce(self, msg, level=log.INFO): + log.log(level, msg) + + def run_commands(self): + """Run each command that was seen on the setup script command line. + Uses the list of commands found and cache of command objects + created by 'get_command_obj()'. + """ + for cmd in self.commands: + self.run_command(cmd) + + # -- Methods that operate on its Commands -------------------------- + + def run_command(self, command): + """Do whatever it takes to run a command (including nothing at all, + if the command has already been run). Specifically: if we have + already created and run the command named by 'command', return + silently without doing anything. If the command named by 'command' + doesn't even have a command object yet, create one. Then invoke + 'run()' on that command object (or an existing one). + """ + # Already been here, done that? then return silently. + if self.have_run.get(command): + return + + log.info("running %s", command) + cmd_obj = self.get_command_obj(command) + cmd_obj.ensure_finalized() + cmd_obj.run() + self.have_run[command] = 1 + + # -- Distribution query methods ------------------------------------ + + def has_pure_modules(self): + return len(self.packages or self.py_modules or []) > 0 + + def has_ext_modules(self): + return self.ext_modules and len(self.ext_modules) > 0 + + def has_c_libraries(self): + return self.libraries and len(self.libraries) > 0 + + def has_modules(self): + return self.has_pure_modules() or self.has_ext_modules() + + def has_headers(self): + return self.headers and len(self.headers) > 0 + + def has_scripts(self): + return self.scripts and len(self.scripts) > 0 + + def has_data_files(self): + return self.data_files and len(self.data_files) > 0 + + def is_pure(self): + return (self.has_pure_modules() and + not self.has_ext_modules() and + not self.has_c_libraries()) + + # -- Metadata query methods ---------------------------------------- + + # If you're looking for 'get_name()', 'get_version()', and so forth, + # they are defined in a sneaky way: the constructor binds self.get_XXX + # to self.metadata.get_XXX. The actual code is in the + # DistributionMetadata class, below. + +class DistributionMetadata: + """Dummy class to hold the distribution meta-data: name, version, + author, and so forth. + """ + + _METHOD_BASENAMES = ("name", "version", "author", "author_email", + "maintainer", "maintainer_email", "url", + "license", "description", "long_description", + "keywords", "platforms", "fullname", "contact", + "contact_email", "classifiers", "download_url", + # PEP 314 + "provides", "requires", "obsoletes", + ) + + def __init__(self, path=None): + if path is not None: + self.read_pkg_file(open(path)) + else: + self.name = None + self.version = None + self.author = None + self.author_email = None + self.maintainer = None + self.maintainer_email = None + self.url = None + self.license = None + self.description = None + self.long_description = None + self.keywords = None + self.platforms = None + self.classifiers = None + self.download_url = None + # PEP 314 + self.provides = None + self.requires = None + self.obsoletes = None + + def read_pkg_file(self, file): + """Reads the metadata values from a file object.""" + msg = message_from_file(file) + + def _read_field(name): + value = msg[name] + if value == 'UNKNOWN': + return None + return value + + def _read_list(name): + values = msg.get_all(name, None) + if values == []: + return None + return values + + metadata_version = msg['metadata-version'] + self.name = _read_field('name') + self.version = _read_field('version') + self.description = _read_field('summary') + # we are filling author only. + self.author = _read_field('author') + self.maintainer = None + self.author_email = _read_field('author-email') + self.maintainer_email = None + self.url = _read_field('home-page') + self.license = _read_field('license') + + if 'download-url' in msg: + self.download_url = _read_field('download-url') + else: + self.download_url = None + + self.long_description = _read_field('description') + self.description = _read_field('summary') + + if 'keywords' in msg: + self.keywords = _read_field('keywords').split(',') + + self.platforms = _read_list('platform') + self.classifiers = _read_list('classifier') + + # PEP 314 - these fields only exist in 1.1 + if metadata_version == '1.1': + self.requires = _read_list('requires') + self.provides = _read_list('provides') + self.obsoletes = _read_list('obsoletes') + else: + self.requires = None + self.provides = None + self.obsoletes = None + + def write_pkg_info(self, base_dir): + """Write the PKG-INFO file into the release tree. + """ + with open(os.path.join(base_dir, 'PKG-INFO'), 'w', + encoding='UTF-8') as pkg_info: + self.write_pkg_file(pkg_info) + + def write_pkg_file(self, file): + """Write the PKG-INFO format data to a file object. + """ + version = '1.0' + if (self.provides or self.requires or self.obsoletes or + self.classifiers or self.download_url): + version = '1.1' + + file.write('Metadata-Version: %s\n' % version) + file.write('Name: %s\n' % self.get_name()) + file.write('Version: %s\n' % self.get_version()) + file.write('Summary: %s\n' % self.get_description()) + file.write('Home-page: %s\n' % self.get_url()) + file.write('Author: %s\n' % self.get_contact()) + file.write('Author-email: %s\n' % self.get_contact_email()) + file.write('License: %s\n' % self.get_license()) + if self.download_url: + file.write('Download-URL: %s\n' % self.download_url) + + long_desc = rfc822_escape(self.get_long_description()) + file.write('Description: %s\n' % long_desc) + + keywords = ','.join(self.get_keywords()) + if keywords: + file.write('Keywords: %s\n' % keywords) + + self._write_list(file, 'Platform', self.get_platforms()) + self._write_list(file, 'Classifier', self.get_classifiers()) + + # PEP 314 + self._write_list(file, 'Requires', self.get_requires()) + self._write_list(file, 'Provides', self.get_provides()) + self._write_list(file, 'Obsoletes', self.get_obsoletes()) + + def _write_list(self, file, name, values): + for value in values: + file.write('%s: %s\n' % (name, value)) + + # -- Metadata query methods ---------------------------------------- + + def get_name(self): + return self.name or "UNKNOWN" + + def get_version(self): + return self.version or "0.0.0" + + def get_fullname(self): + return "%s-%s" % (self.get_name(), self.get_version()) + + def get_author(self): + return self.author or "UNKNOWN" + + def get_author_email(self): + return self.author_email or "UNKNOWN" + + def get_maintainer(self): + return self.maintainer or "UNKNOWN" + + def get_maintainer_email(self): + return self.maintainer_email or "UNKNOWN" + + def get_contact(self): + return self.maintainer or self.author or "UNKNOWN" + + def get_contact_email(self): + return self.maintainer_email or self.author_email or "UNKNOWN" + + def get_url(self): + return self.url or "UNKNOWN" + + def get_license(self): + return self.license or "UNKNOWN" + get_licence = get_license + + def get_description(self): + return self.description or "UNKNOWN" + + def get_long_description(self): + return self.long_description or "UNKNOWN" + + def get_keywords(self): + return self.keywords or [] + + def set_keywords(self, value): + self.keywords = _ensure_list(value, 'keywords') + + def get_platforms(self): + return self.platforms or ["UNKNOWN"] + + def set_platforms(self, value): + self.platforms = _ensure_list(value, 'platforms') + + def get_classifiers(self): + return self.classifiers or [] + + def set_classifiers(self, value): + self.classifiers = _ensure_list(value, 'classifiers') + + def get_download_url(self): + return self.download_url or "UNKNOWN" + + # PEP 314 + def get_requires(self): + return self.requires or [] + + def set_requires(self, value): + import distutils.versionpredicate + for v in value: + distutils.versionpredicate.VersionPredicate(v) + self.requires = list(value) + + def get_provides(self): + return self.provides or [] + + def set_provides(self, value): + value = [v.strip() for v in value] + for v in value: + import distutils.versionpredicate + distutils.versionpredicate.split_provision(v) + self.provides = value + + def get_obsoletes(self): + return self.obsoletes or [] + + def set_obsoletes(self, value): + import distutils.versionpredicate + for v in value: + distutils.versionpredicate.VersionPredicate(v) + self.obsoletes = list(value) + +def fix_help_options(options): + """Convert a 4-tuple 'help_options' list as found in various command + classes to the 3-tuple form required by FancyGetopt. + """ + new_options = [] + for help_tuple in options: + new_options.append(help_tuple[0:3]) + return new_options diff --git a/venv/Lib/site-packages/setuptools/_distutils/errors.py b/venv/Lib/site-packages/setuptools/_distutils/errors.py new file mode 100644 index 0000000..8b93059 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_distutils/errors.py @@ -0,0 +1,97 @@ +"""distutils.errors + +Provides exceptions used by the Distutils modules. Note that Distutils +modules may raise standard exceptions; in particular, SystemExit is +usually raised for errors that are obviously the end-user's fault +(eg. bad command-line arguments). + +This module is safe to use in "from ... import *" mode; it only exports +symbols whose names start with "Distutils" and end with "Error".""" + +class DistutilsError (Exception): + """The root of all Distutils evil.""" + pass + +class DistutilsModuleError (DistutilsError): + """Unable to load an expected module, or to find an expected class + within some module (in particular, command modules and classes).""" + pass + +class DistutilsClassError (DistutilsError): + """Some command class (or possibly distribution class, if anyone + feels a need to subclass Distribution) is found not to be holding + up its end of the bargain, ie. implementing some part of the + "command "interface.""" + pass + +class DistutilsGetoptError (DistutilsError): + """The option table provided to 'fancy_getopt()' is bogus.""" + pass + +class DistutilsArgError (DistutilsError): + """Raised by fancy_getopt in response to getopt.error -- ie. an + error in the command line usage.""" + pass + +class DistutilsFileError (DistutilsError): + """Any problems in the filesystem: expected file not found, etc. + Typically this is for problems that we detect before OSError + could be raised.""" + pass + +class DistutilsOptionError (DistutilsError): + """Syntactic/semantic errors in command options, such as use of + mutually conflicting options, or inconsistent options, + badly-spelled values, etc. No distinction is made between option + values originating in the setup script, the command line, config + files, or what-have-you -- but if we *know* something originated in + the setup script, we'll raise DistutilsSetupError instead.""" + pass + +class DistutilsSetupError (DistutilsError): + """For errors that can be definitely blamed on the setup script, + such as invalid keyword arguments to 'setup()'.""" + pass + +class DistutilsPlatformError (DistutilsError): + """We don't know how to do something on the current platform (but + we do know how to do it on some platform) -- eg. trying to compile + C files on a platform not supported by a CCompiler subclass.""" + pass + +class DistutilsExecError (DistutilsError): + """Any problems executing an external program (such as the C + compiler, when compiling C files).""" + pass + +class DistutilsInternalError (DistutilsError): + """Internal inconsistencies or impossibilities (obviously, this + should never be seen if the code is working!).""" + pass + +class DistutilsTemplateError (DistutilsError): + """Syntax error in a file list template.""" + +class DistutilsByteCompileError(DistutilsError): + """Byte compile error.""" + +# Exception classes used by the CCompiler implementation classes +class CCompilerError (Exception): + """Some compile/link operation failed.""" + +class PreprocessError (CCompilerError): + """Failure to preprocess one or more C/C++ files.""" + +class CompileError (CCompilerError): + """Failure to compile one or more C/C++ source files.""" + +class LibError (CCompilerError): + """Failure to create a static library from one or more C/C++ object + files.""" + +class LinkError (CCompilerError): + """Failure to link one or more C/C++ object files into an executable + or shared library file.""" + +class UnknownFileError (CCompilerError): + """Attempt to process an unknown file type.""" diff --git a/venv/Lib/site-packages/setuptools/_distutils/extension.py b/venv/Lib/site-packages/setuptools/_distutils/extension.py new file mode 100644 index 0000000..c507da3 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_distutils/extension.py @@ -0,0 +1,240 @@ +"""distutils.extension + +Provides the Extension class, used to describe C/C++ extension +modules in setup scripts.""" + +import os +import warnings + +# This class is really only used by the "build_ext" command, so it might +# make sense to put it in distutils.command.build_ext. However, that +# module is already big enough, and I want to make this class a bit more +# complex to simplify some common cases ("foo" module in "foo.c") and do +# better error-checking ("foo.c" actually exists). +# +# Also, putting this in build_ext.py means every setup script would have to +# import that large-ish module (indirectly, through distutils.core) in +# order to do anything. + +class Extension: + """Just a collection of attributes that describes an extension + module and everything needed to build it (hopefully in a portable + way, but there are hooks that let you be as unportable as you need). + + Instance attributes: + name : string + the full name of the extension, including any packages -- ie. + *not* a filename or pathname, but Python dotted name + sources : [string] + list of source filenames, relative to the distribution root + (where the setup script lives), in Unix form (slash-separated) + for portability. Source files may be C, C++, SWIG (.i), + platform-specific resource files, or whatever else is recognized + by the "build_ext" command as source for a Python extension. + include_dirs : [string] + list of directories to search for C/C++ header files (in Unix + form for portability) + define_macros : [(name : string, value : string|None)] + list of macros to define; each macro is defined using a 2-tuple, + where 'value' is either the string to define it to or None to + define it without a particular value (equivalent of "#define + FOO" in source or -DFOO on Unix C compiler command line) + undef_macros : [string] + list of macros to undefine explicitly + library_dirs : [string] + list of directories to search for C/C++ libraries at link time + libraries : [string] + list of library names (not filenames or paths) to link against + runtime_library_dirs : [string] + list of directories to search for C/C++ libraries at run time + (for shared extensions, this is when the extension is loaded) + extra_objects : [string] + list of extra files to link with (eg. object files not implied + by 'sources', static library that must be explicitly specified, + binary resource files, etc.) + extra_compile_args : [string] + any extra platform- and compiler-specific information to use + when compiling the source files in 'sources'. For platforms and + compilers where "command line" makes sense, this is typically a + list of command-line arguments, but for other platforms it could + be anything. + extra_link_args : [string] + any extra platform- and compiler-specific information to use + when linking object files together to create the extension (or + to create a new static Python interpreter). Similar + interpretation as for 'extra_compile_args'. + export_symbols : [string] + list of symbols to be exported from a shared extension. Not + used on all platforms, and not generally necessary for Python + extensions, which typically export exactly one symbol: "init" + + extension_name. + swig_opts : [string] + any extra options to pass to SWIG if a source file has the .i + extension. + depends : [string] + list of files that the extension depends on + language : string + extension language (i.e. "c", "c++", "objc"). Will be detected + from the source extensions if not provided. + optional : boolean + specifies that a build failure in the extension should not abort the + build process, but simply not install the failing extension. + """ + + # When adding arguments to this constructor, be sure to update + # setup_keywords in core.py. + def __init__(self, name, sources, + include_dirs=None, + define_macros=None, + undef_macros=None, + library_dirs=None, + libraries=None, + runtime_library_dirs=None, + extra_objects=None, + extra_compile_args=None, + extra_link_args=None, + export_symbols=None, + swig_opts = None, + depends=None, + language=None, + optional=None, + **kw # To catch unknown keywords + ): + if not isinstance(name, str): + raise AssertionError("'name' must be a string") + if not (isinstance(sources, list) and + all(isinstance(v, str) for v in sources)): + raise AssertionError("'sources' must be a list of strings") + + self.name = name + self.sources = sources + self.include_dirs = include_dirs or [] + self.define_macros = define_macros or [] + self.undef_macros = undef_macros or [] + self.library_dirs = library_dirs or [] + self.libraries = libraries or [] + self.runtime_library_dirs = runtime_library_dirs or [] + self.extra_objects = extra_objects or [] + self.extra_compile_args = extra_compile_args or [] + self.extra_link_args = extra_link_args or [] + self.export_symbols = export_symbols or [] + self.swig_opts = swig_opts or [] + self.depends = depends or [] + self.language = language + self.optional = optional + + # If there are unknown keyword options, warn about them + if len(kw) > 0: + options = [repr(option) for option in kw] + options = ', '.join(sorted(options)) + msg = "Unknown Extension options: %s" % options + warnings.warn(msg) + + def __repr__(self): + return '<%s.%s(%r) at %#x>' % ( + self.__class__.__module__, + self.__class__.__qualname__, + self.name, + id(self)) + + +def read_setup_file(filename): + """Reads a Setup file and returns Extension instances.""" + from distutils.sysconfig import (parse_makefile, expand_makefile_vars, + _variable_rx) + + from distutils.text_file import TextFile + from distutils.util import split_quoted + + # First pass over the file to gather "VAR = VALUE" assignments. + vars = parse_makefile(filename) + + # Second pass to gobble up the real content: lines of the form + # ... [ ...] [ ...] [ ...] + file = TextFile(filename, + strip_comments=1, skip_blanks=1, join_lines=1, + lstrip_ws=1, rstrip_ws=1) + try: + extensions = [] + + while True: + line = file.readline() + if line is None: # eof + break + if _variable_rx.match(line): # VAR=VALUE, handled in first pass + continue + + if line[0] == line[-1] == "*": + file.warn("'%s' lines not handled yet" % line) + continue + + line = expand_makefile_vars(line, vars) + words = split_quoted(line) + + # NB. this parses a slightly different syntax than the old + # makesetup script: here, there must be exactly one extension per + # line, and it must be the first word of the line. I have no idea + # why the old syntax supported multiple extensions per line, as + # they all wind up being the same. + + module = words[0] + ext = Extension(module, []) + append_next_word = None + + for word in words[1:]: + if append_next_word is not None: + append_next_word.append(word) + append_next_word = None + continue + + suffix = os.path.splitext(word)[1] + switch = word[0:2] ; value = word[2:] + + if suffix in (".c", ".cc", ".cpp", ".cxx", ".c++", ".m", ".mm"): + # hmm, should we do something about C vs. C++ sources? + # or leave it up to the CCompiler implementation to + # worry about? + ext.sources.append(word) + elif switch == "-I": + ext.include_dirs.append(value) + elif switch == "-D": + equals = value.find("=") + if equals == -1: # bare "-DFOO" -- no value + ext.define_macros.append((value, None)) + else: # "-DFOO=blah" + ext.define_macros.append((value[0:equals], + value[equals+2:])) + elif switch == "-U": + ext.undef_macros.append(value) + elif switch == "-C": # only here 'cause makesetup has it! + ext.extra_compile_args.append(word) + elif switch == "-l": + ext.libraries.append(value) + elif switch == "-L": + ext.library_dirs.append(value) + elif switch == "-R": + ext.runtime_library_dirs.append(value) + elif word == "-rpath": + append_next_word = ext.runtime_library_dirs + elif word == "-Xlinker": + append_next_word = ext.extra_link_args + elif word == "-Xcompiler": + append_next_word = ext.extra_compile_args + elif switch == "-u": + ext.extra_link_args.append(word) + if not value: + append_next_word = ext.extra_link_args + elif suffix in (".a", ".so", ".sl", ".o", ".dylib"): + # NB. a really faithful emulation of makesetup would + # append a .o file to extra_objects only if it + # had a slash in it; otherwise, it would s/.o/.c/ + # and append it to sources. Hmmmm. + ext.extra_objects.append(word) + else: + file.warn("unrecognized argument '%s'" % word) + + extensions.append(ext) + finally: + file.close() + + return extensions diff --git a/venv/Lib/site-packages/setuptools/_distutils/fancy_getopt.py b/venv/Lib/site-packages/setuptools/_distutils/fancy_getopt.py new file mode 100644 index 0000000..7d170dd --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_distutils/fancy_getopt.py @@ -0,0 +1,457 @@ +"""distutils.fancy_getopt + +Wrapper around the standard getopt module that provides the following +additional features: + * short and long options are tied together + * options have help strings, so fancy_getopt could potentially + create a complete usage summary + * options set attributes of a passed-in object +""" + +import sys, string, re +import getopt +from distutils.errors import * + +# Much like command_re in distutils.core, this is close to but not quite +# the same as a Python NAME -- except, in the spirit of most GNU +# utilities, we use '-' in place of '_'. (The spirit of LISP lives on!) +# The similarities to NAME are again not a coincidence... +longopt_pat = r'[a-zA-Z](?:[a-zA-Z0-9-]*)' +longopt_re = re.compile(r'^%s$' % longopt_pat) + +# For recognizing "negative alias" options, eg. "quiet=!verbose" +neg_alias_re = re.compile("^(%s)=!(%s)$" % (longopt_pat, longopt_pat)) + +# This is used to translate long options to legitimate Python identifiers +# (for use as attributes of some object). +longopt_xlate = str.maketrans('-', '_') + +class FancyGetopt: + """Wrapper around the standard 'getopt()' module that provides some + handy extra functionality: + * short and long options are tied together + * options have help strings, and help text can be assembled + from them + * options set attributes of a passed-in object + * boolean options can have "negative aliases" -- eg. if + --quiet is the "negative alias" of --verbose, then "--quiet" + on the command line sets 'verbose' to false + """ + + def __init__(self, option_table=None): + # The option table is (currently) a list of tuples. The + # tuples may have 3 or four values: + # (long_option, short_option, help_string [, repeatable]) + # if an option takes an argument, its long_option should have '=' + # appended; short_option should just be a single character, no ':' + # in any case. If a long_option doesn't have a corresponding + # short_option, short_option should be None. All option tuples + # must have long options. + self.option_table = option_table + + # 'option_index' maps long option names to entries in the option + # table (ie. those 3-tuples). + self.option_index = {} + if self.option_table: + self._build_index() + + # 'alias' records (duh) alias options; {'foo': 'bar'} means + # --foo is an alias for --bar + self.alias = {} + + # 'negative_alias' keeps track of options that are the boolean + # opposite of some other option + self.negative_alias = {} + + # These keep track of the information in the option table. We + # don't actually populate these structures until we're ready to + # parse the command-line, since the 'option_table' passed in here + # isn't necessarily the final word. + self.short_opts = [] + self.long_opts = [] + self.short2long = {} + self.attr_name = {} + self.takes_arg = {} + + # And 'option_order' is filled up in 'getopt()'; it records the + # original order of options (and their values) on the command-line, + # but expands short options, converts aliases, etc. + self.option_order = [] + + def _build_index(self): + self.option_index.clear() + for option in self.option_table: + self.option_index[option[0]] = option + + def set_option_table(self, option_table): + self.option_table = option_table + self._build_index() + + def add_option(self, long_option, short_option=None, help_string=None): + if long_option in self.option_index: + raise DistutilsGetoptError( + "option conflict: already an option '%s'" % long_option) + else: + option = (long_option, short_option, help_string) + self.option_table.append(option) + self.option_index[long_option] = option + + def has_option(self, long_option): + """Return true if the option table for this parser has an + option with long name 'long_option'.""" + return long_option in self.option_index + + def get_attr_name(self, long_option): + """Translate long option name 'long_option' to the form it + has as an attribute of some object: ie., translate hyphens + to underscores.""" + return long_option.translate(longopt_xlate) + + def _check_alias_dict(self, aliases, what): + assert isinstance(aliases, dict) + for (alias, opt) in aliases.items(): + if alias not in self.option_index: + raise DistutilsGetoptError(("invalid %s '%s': " + "option '%s' not defined") % (what, alias, alias)) + if opt not in self.option_index: + raise DistutilsGetoptError(("invalid %s '%s': " + "aliased option '%s' not defined") % (what, alias, opt)) + + def set_aliases(self, alias): + """Set the aliases for this option parser.""" + self._check_alias_dict(alias, "alias") + self.alias = alias + + def set_negative_aliases(self, negative_alias): + """Set the negative aliases for this option parser. + 'negative_alias' should be a dictionary mapping option names to + option names, both the key and value must already be defined + in the option table.""" + self._check_alias_dict(negative_alias, "negative alias") + self.negative_alias = negative_alias + + def _grok_option_table(self): + """Populate the various data structures that keep tabs on the + option table. Called by 'getopt()' before it can do anything + worthwhile. + """ + self.long_opts = [] + self.short_opts = [] + self.short2long.clear() + self.repeat = {} + + for option in self.option_table: + if len(option) == 3: + long, short, help = option + repeat = 0 + elif len(option) == 4: + long, short, help, repeat = option + else: + # the option table is part of the code, so simply + # assert that it is correct + raise ValueError("invalid option tuple: %r" % (option,)) + + # Type- and value-check the option names + if not isinstance(long, str) or len(long) < 2: + raise DistutilsGetoptError(("invalid long option '%s': " + "must be a string of length >= 2") % long) + + if (not ((short is None) or + (isinstance(short, str) and len(short) == 1))): + raise DistutilsGetoptError("invalid short option '%s': " + "must a single character or None" % short) + + self.repeat[long] = repeat + self.long_opts.append(long) + + if long[-1] == '=': # option takes an argument? + if short: short = short + ':' + long = long[0:-1] + self.takes_arg[long] = 1 + else: + # Is option is a "negative alias" for some other option (eg. + # "quiet" == "!verbose")? + alias_to = self.negative_alias.get(long) + if alias_to is not None: + if self.takes_arg[alias_to]: + raise DistutilsGetoptError( + "invalid negative alias '%s': " + "aliased option '%s' takes a value" + % (long, alias_to)) + + self.long_opts[-1] = long # XXX redundant?! + self.takes_arg[long] = 0 + + # If this is an alias option, make sure its "takes arg" flag is + # the same as the option it's aliased to. + alias_to = self.alias.get(long) + if alias_to is not None: + if self.takes_arg[long] != self.takes_arg[alias_to]: + raise DistutilsGetoptError( + "invalid alias '%s': inconsistent with " + "aliased option '%s' (one of them takes a value, " + "the other doesn't" + % (long, alias_to)) + + # Now enforce some bondage on the long option name, so we can + # later translate it to an attribute name on some object. Have + # to do this a bit late to make sure we've removed any trailing + # '='. + if not longopt_re.match(long): + raise DistutilsGetoptError( + "invalid long option name '%s' " + "(must be letters, numbers, hyphens only" % long) + + self.attr_name[long] = self.get_attr_name(long) + if short: + self.short_opts.append(short) + self.short2long[short[0]] = long + + def getopt(self, args=None, object=None): + """Parse command-line options in args. Store as attributes on object. + + If 'args' is None or not supplied, uses 'sys.argv[1:]'. If + 'object' is None or not supplied, creates a new OptionDummy + object, stores option values there, and returns a tuple (args, + object). If 'object' is supplied, it is modified in place and + 'getopt()' just returns 'args'; in both cases, the returned + 'args' is a modified copy of the passed-in 'args' list, which + is left untouched. + """ + if args is None: + args = sys.argv[1:] + if object is None: + object = OptionDummy() + created_object = True + else: + created_object = False + + self._grok_option_table() + + short_opts = ' '.join(self.short_opts) + try: + opts, args = getopt.getopt(args, short_opts, self.long_opts) + except getopt.error as msg: + raise DistutilsArgError(msg) + + for opt, val in opts: + if len(opt) == 2 and opt[0] == '-': # it's a short option + opt = self.short2long[opt[1]] + else: + assert len(opt) > 2 and opt[:2] == '--' + opt = opt[2:] + + alias = self.alias.get(opt) + if alias: + opt = alias + + if not self.takes_arg[opt]: # boolean option? + assert val == '', "boolean option can't have value" + alias = self.negative_alias.get(opt) + if alias: + opt = alias + val = 0 + else: + val = 1 + + attr = self.attr_name[opt] + # The only repeating option at the moment is 'verbose'. + # It has a negative option -q quiet, which should set verbose = 0. + if val and self.repeat.get(attr) is not None: + val = getattr(object, attr, 0) + 1 + setattr(object, attr, val) + self.option_order.append((opt, val)) + + # for opts + if created_object: + return args, object + else: + return args + + def get_option_order(self): + """Returns the list of (option, value) tuples processed by the + previous run of 'getopt()'. Raises RuntimeError if + 'getopt()' hasn't been called yet. + """ + if self.option_order is None: + raise RuntimeError("'getopt()' hasn't been called yet") + else: + return self.option_order + + def generate_help(self, header=None): + """Generate help text (a list of strings, one per suggested line of + output) from the option table for this FancyGetopt object. + """ + # Blithely assume the option table is good: probably wouldn't call + # 'generate_help()' unless you've already called 'getopt()'. + + # First pass: determine maximum length of long option names + max_opt = 0 + for option in self.option_table: + long = option[0] + short = option[1] + l = len(long) + if long[-1] == '=': + l = l - 1 + if short is not None: + l = l + 5 # " (-x)" where short == 'x' + if l > max_opt: + max_opt = l + + opt_width = max_opt + 2 + 2 + 2 # room for indent + dashes + gutter + + # Typical help block looks like this: + # --foo controls foonabulation + # Help block for longest option looks like this: + # --flimflam set the flim-flam level + # and with wrapped text: + # --flimflam set the flim-flam level (must be between + # 0 and 100, except on Tuesdays) + # Options with short names will have the short name shown (but + # it doesn't contribute to max_opt): + # --foo (-f) controls foonabulation + # If adding the short option would make the left column too wide, + # we push the explanation off to the next line + # --flimflam (-l) + # set the flim-flam level + # Important parameters: + # - 2 spaces before option block start lines + # - 2 dashes for each long option name + # - min. 2 spaces between option and explanation (gutter) + # - 5 characters (incl. space) for short option name + + # Now generate lines of help text. (If 80 columns were good enough + # for Jesus, then 78 columns are good enough for me!) + line_width = 78 + text_width = line_width - opt_width + big_indent = ' ' * opt_width + if header: + lines = [header] + else: + lines = ['Option summary:'] + + for option in self.option_table: + long, short, help = option[:3] + text = wrap_text(help, text_width) + if long[-1] == '=': + long = long[0:-1] + + # Case 1: no short option at all (makes life easy) + if short is None: + if text: + lines.append(" --%-*s %s" % (max_opt, long, text[0])) + else: + lines.append(" --%-*s " % (max_opt, long)) + + # Case 2: we have a short option, so we have to include it + # just after the long option + else: + opt_names = "%s (-%s)" % (long, short) + if text: + lines.append(" --%-*s %s" % + (max_opt, opt_names, text[0])) + else: + lines.append(" --%-*s" % opt_names) + + for l in text[1:]: + lines.append(big_indent + l) + return lines + + def print_help(self, header=None, file=None): + if file is None: + file = sys.stdout + for line in self.generate_help(header): + file.write(line + "\n") + + +def fancy_getopt(options, negative_opt, object, args): + parser = FancyGetopt(options) + parser.set_negative_aliases(negative_opt) + return parser.getopt(args, object) + + +WS_TRANS = {ord(_wschar) : ' ' for _wschar in string.whitespace} + +def wrap_text(text, width): + """wrap_text(text : string, width : int) -> [string] + + Split 'text' into multiple lines of no more than 'width' characters + each, and return the list of strings that results. + """ + if text is None: + return [] + if len(text) <= width: + return [text] + + text = text.expandtabs() + text = text.translate(WS_TRANS) + chunks = re.split(r'( +|-+)', text) + chunks = [ch for ch in chunks if ch] # ' - ' results in empty strings + lines = [] + + while chunks: + cur_line = [] # list of chunks (to-be-joined) + cur_len = 0 # length of current line + + while chunks: + l = len(chunks[0]) + if cur_len + l <= width: # can squeeze (at least) this chunk in + cur_line.append(chunks[0]) + del chunks[0] + cur_len = cur_len + l + else: # this line is full + # drop last chunk if all space + if cur_line and cur_line[-1][0] == ' ': + del cur_line[-1] + break + + if chunks: # any chunks left to process? + # if the current line is still empty, then we had a single + # chunk that's too big too fit on a line -- so we break + # down and break it up at the line width + if cur_len == 0: + cur_line.append(chunks[0][0:width]) + chunks[0] = chunks[0][width:] + + # all-whitespace chunks at the end of a line can be discarded + # (and we know from the re.split above that if a chunk has + # *any* whitespace, it is *all* whitespace) + if chunks[0][0] == ' ': + del chunks[0] + + # and store this line in the list-of-all-lines -- as a single + # string, of course! + lines.append(''.join(cur_line)) + + return lines + + +def translate_longopt(opt): + """Convert a long option name to a valid Python identifier by + changing "-" to "_". + """ + return opt.translate(longopt_xlate) + + +class OptionDummy: + """Dummy class just used as a place to hold command-line option + values as instance attributes.""" + + def __init__(self, options=[]): + """Create a new OptionDummy instance. The attributes listed in + 'options' will be initialized to None.""" + for opt in options: + setattr(self, opt, None) + + +if __name__ == "__main__": + text = """\ +Tra-la-la, supercalifragilisticexpialidocious. +How *do* you spell that odd word, anyways? +(Someone ask Mary -- she'll know [or she'll +say, "How should I know?"].)""" + + for w in (10, 20, 30, 40): + print("width: %d" % w) + print("\n".join(wrap_text(text, w))) + print() diff --git a/venv/Lib/site-packages/setuptools/_distutils/file_util.py b/venv/Lib/site-packages/setuptools/_distutils/file_util.py new file mode 100644 index 0000000..b3fee35 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_distutils/file_util.py @@ -0,0 +1,238 @@ +"""distutils.file_util + +Utility functions for operating on single files. +""" + +import os +from distutils.errors import DistutilsFileError +from distutils import log + +# for generating verbose output in 'copy_file()' +_copy_action = { None: 'copying', + 'hard': 'hard linking', + 'sym': 'symbolically linking' } + + +def _copy_file_contents(src, dst, buffer_size=16*1024): + """Copy the file 'src' to 'dst'; both must be filenames. Any error + opening either file, reading from 'src', or writing to 'dst', raises + DistutilsFileError. Data is read/written in chunks of 'buffer_size' + bytes (default 16k). No attempt is made to handle anything apart from + regular files. + """ + # Stolen from shutil module in the standard library, but with + # custom error-handling added. + fsrc = None + fdst = None + try: + try: + fsrc = open(src, 'rb') + except OSError as e: + raise DistutilsFileError("could not open '%s': %s" % (src, e.strerror)) + + if os.path.exists(dst): + try: + os.unlink(dst) + except OSError as e: + raise DistutilsFileError( + "could not delete '%s': %s" % (dst, e.strerror)) + + try: + fdst = open(dst, 'wb') + except OSError as e: + raise DistutilsFileError( + "could not create '%s': %s" % (dst, e.strerror)) + + while True: + try: + buf = fsrc.read(buffer_size) + except OSError as e: + raise DistutilsFileError( + "could not read from '%s': %s" % (src, e.strerror)) + + if not buf: + break + + try: + fdst.write(buf) + except OSError as e: + raise DistutilsFileError( + "could not write to '%s': %s" % (dst, e.strerror)) + finally: + if fdst: + fdst.close() + if fsrc: + fsrc.close() + +def copy_file(src, dst, preserve_mode=1, preserve_times=1, update=0, + link=None, verbose=1, dry_run=0): + """Copy a file 'src' to 'dst'. If 'dst' is a directory, then 'src' is + copied there with the same name; otherwise, it must be a filename. (If + the file exists, it will be ruthlessly clobbered.) If 'preserve_mode' + is true (the default), the file's mode (type and permission bits, or + whatever is analogous on the current platform) is copied. If + 'preserve_times' is true (the default), the last-modified and + last-access times are copied as well. If 'update' is true, 'src' will + only be copied if 'dst' does not exist, or if 'dst' does exist but is + older than 'src'. + + 'link' allows you to make hard links (os.link) or symbolic links + (os.symlink) instead of copying: set it to "hard" or "sym"; if it is + None (the default), files are copied. Don't set 'link' on systems that + don't support it: 'copy_file()' doesn't check if hard or symbolic + linking is available. If hardlink fails, falls back to + _copy_file_contents(). + + Under Mac OS, uses the native file copy function in macostools; on + other systems, uses '_copy_file_contents()' to copy file contents. + + Return a tuple (dest_name, copied): 'dest_name' is the actual name of + the output file, and 'copied' is true if the file was copied (or would + have been copied, if 'dry_run' true). + """ + # XXX if the destination file already exists, we clobber it if + # copying, but blow up if linking. Hmmm. And I don't know what + # macostools.copyfile() does. Should definitely be consistent, and + # should probably blow up if destination exists and we would be + # changing it (ie. it's not already a hard/soft link to src OR + # (not update) and (src newer than dst). + + from distutils.dep_util import newer + from stat import ST_ATIME, ST_MTIME, ST_MODE, S_IMODE + + if not os.path.isfile(src): + raise DistutilsFileError( + "can't copy '%s': doesn't exist or not a regular file" % src) + + if os.path.isdir(dst): + dir = dst + dst = os.path.join(dst, os.path.basename(src)) + else: + dir = os.path.dirname(dst) + + if update and not newer(src, dst): + if verbose >= 1: + log.debug("not copying %s (output up-to-date)", src) + return (dst, 0) + + try: + action = _copy_action[link] + except KeyError: + raise ValueError("invalid value '%s' for 'link' argument" % link) + + if verbose >= 1: + if os.path.basename(dst) == os.path.basename(src): + log.info("%s %s -> %s", action, src, dir) + else: + log.info("%s %s -> %s", action, src, dst) + + if dry_run: + return (dst, 1) + + # If linking (hard or symbolic), use the appropriate system call + # (Unix only, of course, but that's the caller's responsibility) + elif link == 'hard': + if not (os.path.exists(dst) and os.path.samefile(src, dst)): + try: + os.link(src, dst) + return (dst, 1) + except OSError: + # If hard linking fails, fall back on copying file + # (some special filesystems don't support hard linking + # even under Unix, see issue #8876). + pass + elif link == 'sym': + if not (os.path.exists(dst) and os.path.samefile(src, dst)): + os.symlink(src, dst) + return (dst, 1) + + # Otherwise (non-Mac, not linking), copy the file contents and + # (optionally) copy the times and mode. + _copy_file_contents(src, dst) + if preserve_mode or preserve_times: + st = os.stat(src) + + # According to David Ascher , utime() should be done + # before chmod() (at least under NT). + if preserve_times: + os.utime(dst, (st[ST_ATIME], st[ST_MTIME])) + if preserve_mode: + os.chmod(dst, S_IMODE(st[ST_MODE])) + + return (dst, 1) + + +# XXX I suspect this is Unix-specific -- need porting help! +def move_file (src, dst, + verbose=1, + dry_run=0): + + """Move a file 'src' to 'dst'. If 'dst' is a directory, the file will + be moved into it with the same name; otherwise, 'src' is just renamed + to 'dst'. Return the new full name of the file. + + Handles cross-device moves on Unix using 'copy_file()'. What about + other systems??? + """ + from os.path import exists, isfile, isdir, basename, dirname + import errno + + if verbose >= 1: + log.info("moving %s -> %s", src, dst) + + if dry_run: + return dst + + if not isfile(src): + raise DistutilsFileError("can't move '%s': not a regular file" % src) + + if isdir(dst): + dst = os.path.join(dst, basename(src)) + elif exists(dst): + raise DistutilsFileError( + "can't move '%s': destination '%s' already exists" % + (src, dst)) + + if not isdir(dirname(dst)): + raise DistutilsFileError( + "can't move '%s': destination '%s' not a valid path" % + (src, dst)) + + copy_it = False + try: + os.rename(src, dst) + except OSError as e: + (num, msg) = e.args + if num == errno.EXDEV: + copy_it = True + else: + raise DistutilsFileError( + "couldn't move '%s' to '%s': %s" % (src, dst, msg)) + + if copy_it: + copy_file(src, dst, verbose=verbose) + try: + os.unlink(src) + except OSError as e: + (num, msg) = e.args + try: + os.unlink(dst) + except OSError: + pass + raise DistutilsFileError( + "couldn't move '%s' to '%s' by copy/delete: " + "delete '%s' failed: %s" + % (src, dst, src, msg)) + return dst + + +def write_file (filename, contents): + """Create a file with the specified name and write 'contents' (a + sequence of strings without line terminators) to it. + """ + f = open(filename, "w") + try: + for line in contents: + f.write(line + "\n") + finally: + f.close() diff --git a/venv/Lib/site-packages/setuptools/_distutils/filelist.py b/venv/Lib/site-packages/setuptools/_distutils/filelist.py new file mode 100644 index 0000000..82a7738 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_distutils/filelist.py @@ -0,0 +1,355 @@ +"""distutils.filelist + +Provides the FileList class, used for poking about the filesystem +and building lists of files. +""" + +import os +import re +import fnmatch +import functools + +from distutils.util import convert_path +from distutils.errors import DistutilsTemplateError, DistutilsInternalError +from distutils import log + + +class FileList: + """A list of files built by on exploring the filesystem and filtered by + applying various patterns to what we find there. + + Instance attributes: + dir + directory from which files will be taken -- only used if + 'allfiles' not supplied to constructor + files + list of filenames currently being built/filtered/manipulated + allfiles + complete list of files under consideration (ie. without any + filtering applied) + """ + + def __init__(self, warn=None, debug_print=None): + # ignore argument to FileList, but keep them for backwards + # compatibility + self.allfiles = None + self.files = [] + + def set_allfiles(self, allfiles): + self.allfiles = allfiles + + def findall(self, dir=os.curdir): + self.allfiles = findall(dir) + + def debug_print(self, msg): + """Print 'msg' to stdout if the global DEBUG (taken from the + DISTUTILS_DEBUG environment variable) flag is true. + """ + from distutils.debug import DEBUG + if DEBUG: + print(msg) + + # Collection methods + + def append(self, item): + self.files.append(item) + + def extend(self, items): + self.files.extend(items) + + def sort(self): + # Not a strict lexical sort! + sortable_files = sorted(map(os.path.split, self.files)) + self.files = [] + for sort_tuple in sortable_files: + self.files.append(os.path.join(*sort_tuple)) + + # Other miscellaneous utility methods + + def remove_duplicates(self): + # Assumes list has been sorted! + for i in range(len(self.files) - 1, 0, -1): + if self.files[i] == self.files[i - 1]: + del self.files[i] + + # "File template" methods + + def _parse_template_line(self, line): + words = line.split() + action = words[0] + + patterns = dir = dir_pattern = None + + if action in ('include', 'exclude', + 'global-include', 'global-exclude'): + if len(words) < 2: + raise DistutilsTemplateError( + "'%s' expects ..." % action) + patterns = [convert_path(w) for w in words[1:]] + elif action in ('recursive-include', 'recursive-exclude'): + if len(words) < 3: + raise DistutilsTemplateError( + "'%s' expects

    ..." % action) + dir = convert_path(words[1]) + patterns = [convert_path(w) for w in words[2:]] + elif action in ('graft', 'prune'): + if len(words) != 2: + raise DistutilsTemplateError( + "'%s' expects a single " % action) + dir_pattern = convert_path(words[1]) + else: + raise DistutilsTemplateError("unknown action '%s'" % action) + + return (action, patterns, dir, dir_pattern) + + def process_template_line(self, line): + # Parse the line: split it up, make sure the right number of words + # is there, and return the relevant words. 'action' is always + # defined: it's the first word of the line. Which of the other + # three are defined depends on the action; it'll be either + # patterns, (dir and patterns), or (dir_pattern). + (action, patterns, dir, dir_pattern) = self._parse_template_line(line) + + # OK, now we know that the action is valid and we have the + # right number of words on the line for that action -- so we + # can proceed with minimal error-checking. + if action == 'include': + self.debug_print("include " + ' '.join(patterns)) + for pattern in patterns: + if not self.include_pattern(pattern, anchor=1): + log.warn("warning: no files found matching '%s'", + pattern) + + elif action == 'exclude': + self.debug_print("exclude " + ' '.join(patterns)) + for pattern in patterns: + if not self.exclude_pattern(pattern, anchor=1): + log.warn(("warning: no previously-included files " + "found matching '%s'"), pattern) + + elif action == 'global-include': + self.debug_print("global-include " + ' '.join(patterns)) + for pattern in patterns: + if not self.include_pattern(pattern, anchor=0): + log.warn(("warning: no files found matching '%s' " + "anywhere in distribution"), pattern) + + elif action == 'global-exclude': + self.debug_print("global-exclude " + ' '.join(patterns)) + for pattern in patterns: + if not self.exclude_pattern(pattern, anchor=0): + log.warn(("warning: no previously-included files matching " + "'%s' found anywhere in distribution"), + pattern) + + elif action == 'recursive-include': + self.debug_print("recursive-include %s %s" % + (dir, ' '.join(patterns))) + for pattern in patterns: + if not self.include_pattern(pattern, prefix=dir): + msg = ( + "warning: no files found matching '%s' " + "under directory '%s'" + ) + log.warn(msg, pattern, dir) + + elif action == 'recursive-exclude': + self.debug_print("recursive-exclude %s %s" % + (dir, ' '.join(patterns))) + for pattern in patterns: + if not self.exclude_pattern(pattern, prefix=dir): + log.warn(("warning: no previously-included files matching " + "'%s' found under directory '%s'"), + pattern, dir) + + elif action == 'graft': + self.debug_print("graft " + dir_pattern) + if not self.include_pattern(None, prefix=dir_pattern): + log.warn("warning: no directories found matching '%s'", + dir_pattern) + + elif action == 'prune': + self.debug_print("prune " + dir_pattern) + if not self.exclude_pattern(None, prefix=dir_pattern): + log.warn(("no previously-included directories found " + "matching '%s'"), dir_pattern) + else: + raise DistutilsInternalError( + "this cannot happen: invalid action '%s'" % action) + + # Filtering/selection methods + + def include_pattern(self, pattern, anchor=1, prefix=None, is_regex=0): + """Select strings (presumably filenames) from 'self.files' that + match 'pattern', a Unix-style wildcard (glob) pattern. Patterns + are not quite the same as implemented by the 'fnmatch' module: '*' + and '?' match non-special characters, where "special" is platform- + dependent: slash on Unix; colon, slash, and backslash on + DOS/Windows; and colon on Mac OS. + + If 'anchor' is true (the default), then the pattern match is more + stringent: "*.py" will match "foo.py" but not "foo/bar.py". If + 'anchor' is false, both of these will match. + + If 'prefix' is supplied, then only filenames starting with 'prefix' + (itself a pattern) and ending with 'pattern', with anything in between + them, will match. 'anchor' is ignored in this case. + + If 'is_regex' is true, 'anchor' and 'prefix' are ignored, and + 'pattern' is assumed to be either a string containing a regex or a + regex object -- no translation is done, the regex is just compiled + and used as-is. + + Selected strings will be added to self.files. + + Return True if files are found, False otherwise. + """ + # XXX docstring lying about what the special chars are? + files_found = False + pattern_re = translate_pattern(pattern, anchor, prefix, is_regex) + self.debug_print("include_pattern: applying regex r'%s'" % + pattern_re.pattern) + + # delayed loading of allfiles list + if self.allfiles is None: + self.findall() + + for name in self.allfiles: + if pattern_re.search(name): + self.debug_print(" adding " + name) + self.files.append(name) + files_found = True + return files_found + + def exclude_pattern( + self, pattern, anchor=1, prefix=None, is_regex=0): + """Remove strings (presumably filenames) from 'files' that match + 'pattern'. Other parameters are the same as for + 'include_pattern()', above. + The list 'self.files' is modified in place. + Return True if files are found, False otherwise. + """ + files_found = False + pattern_re = translate_pattern(pattern, anchor, prefix, is_regex) + self.debug_print("exclude_pattern: applying regex r'%s'" % + pattern_re.pattern) + for i in range(len(self.files)-1, -1, -1): + if pattern_re.search(self.files[i]): + self.debug_print(" removing " + self.files[i]) + del self.files[i] + files_found = True + return files_found + + +# Utility functions + +def _find_all_simple(path): + """ + Find all files under 'path' + """ + all_unique = _UniqueDirs.filter(os.walk(path, followlinks=True)) + results = ( + os.path.join(base, file) + for base, dirs, files in all_unique + for file in files + ) + return filter(os.path.isfile, results) + + +class _UniqueDirs(set): + """ + Exclude previously-seen dirs from walk results, + avoiding infinite recursion. + Ref https://bugs.python.org/issue44497. + """ + def __call__(self, walk_item): + """ + Given an item from an os.walk result, determine + if the item represents a unique dir for this instance + and if not, prevent further traversal. + """ + base, dirs, files = walk_item + stat = os.stat(base) + candidate = stat.st_dev, stat.st_ino + found = candidate in self + if found: + del dirs[:] + self.add(candidate) + return not found + + @classmethod + def filter(cls, items): + return filter(cls(), items) + + +def findall(dir=os.curdir): + """ + Find all files under 'dir' and return the list of full filenames. + Unless dir is '.', return full filenames with dir prepended. + """ + files = _find_all_simple(dir) + if dir == os.curdir: + make_rel = functools.partial(os.path.relpath, start=dir) + files = map(make_rel, files) + return list(files) + + +def glob_to_re(pattern): + """Translate a shell-like glob pattern to a regular expression; return + a string containing the regex. Differs from 'fnmatch.translate()' in + that '*' does not match "special characters" (which are + platform-specific). + """ + pattern_re = fnmatch.translate(pattern) + + # '?' and '*' in the glob pattern become '.' and '.*' in the RE, which + # IMHO is wrong -- '?' and '*' aren't supposed to match slash in Unix, + # and by extension they shouldn't match such "special characters" under + # any OS. So change all non-escaped dots in the RE to match any + # character except the special characters (currently: just os.sep). + sep = os.sep + if os.sep == '\\': + # we're using a regex to manipulate a regex, so we need + # to escape the backslash twice + sep = r'\\\\' + escaped = r'\1[^%s]' % sep + pattern_re = re.sub(r'((?= self.threshold: + if args: + msg = msg % args + if level in (WARN, ERROR, FATAL): + stream = sys.stderr + else: + stream = sys.stdout + try: + stream.write('%s\n' % msg) + except UnicodeEncodeError: + # emulate backslashreplace error handler + encoding = stream.encoding + msg = msg.encode(encoding, "backslashreplace").decode(encoding) + stream.write('%s\n' % msg) + stream.flush() + + def log(self, level, msg, *args): + self._log(level, msg, args) + + def debug(self, msg, *args): + self._log(DEBUG, msg, args) + + def info(self, msg, *args): + self._log(INFO, msg, args) + + def warn(self, msg, *args): + self._log(WARN, msg, args) + + def error(self, msg, *args): + self._log(ERROR, msg, args) + + def fatal(self, msg, *args): + self._log(FATAL, msg, args) + + +_global_log = Log() +log = _global_log.log +debug = _global_log.debug +info = _global_log.info +warn = _global_log.warn +error = _global_log.error +fatal = _global_log.fatal + + +def set_threshold(level): + # return the old threshold for use from tests + old = _global_log.threshold + _global_log.threshold = level + return old + + +def set_verbosity(v): + if v <= 0: + set_threshold(WARN) + elif v == 1: + set_threshold(INFO) + elif v >= 2: + set_threshold(DEBUG) diff --git a/venv/Lib/site-packages/setuptools/_distutils/msvc9compiler.py b/venv/Lib/site-packages/setuptools/_distutils/msvc9compiler.py new file mode 100644 index 0000000..6b62738 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_distutils/msvc9compiler.py @@ -0,0 +1,788 @@ +"""distutils.msvc9compiler + +Contains MSVCCompiler, an implementation of the abstract CCompiler class +for the Microsoft Visual Studio 2008. + +The module is compatible with VS 2005 and VS 2008. You can find legacy support +for older versions of VS in distutils.msvccompiler. +""" + +# Written by Perry Stoll +# hacked by Robin Becker and Thomas Heller to do a better job of +# finding DevStudio (through the registry) +# ported to VS2005 and VS 2008 by Christian Heimes + +import os +import subprocess +import sys +import re + +from distutils.errors import DistutilsExecError, DistutilsPlatformError, \ + CompileError, LibError, LinkError +from distutils.ccompiler import CCompiler, gen_lib_options +from distutils import log +from distutils.util import get_platform + +import winreg + +RegOpenKeyEx = winreg.OpenKeyEx +RegEnumKey = winreg.EnumKey +RegEnumValue = winreg.EnumValue +RegError = winreg.error + +HKEYS = (winreg.HKEY_USERS, + winreg.HKEY_CURRENT_USER, + winreg.HKEY_LOCAL_MACHINE, + winreg.HKEY_CLASSES_ROOT) + +NATIVE_WIN64 = (sys.platform == 'win32' and sys.maxsize > 2**32) +if NATIVE_WIN64: + # Visual C++ is a 32-bit application, so we need to look in + # the corresponding registry branch, if we're running a + # 64-bit Python on Win64 + VS_BASE = r"Software\Wow6432Node\Microsoft\VisualStudio\%0.1f" + WINSDK_BASE = r"Software\Wow6432Node\Microsoft\Microsoft SDKs\Windows" + NET_BASE = r"Software\Wow6432Node\Microsoft\.NETFramework" +else: + VS_BASE = r"Software\Microsoft\VisualStudio\%0.1f" + WINSDK_BASE = r"Software\Microsoft\Microsoft SDKs\Windows" + NET_BASE = r"Software\Microsoft\.NETFramework" + +# A map keyed by get_platform() return values to values accepted by +# 'vcvarsall.bat'. Note a cross-compile may combine these (eg, 'x86_amd64' is +# the param to cross-compile on x86 targeting amd64.) +PLAT_TO_VCVARS = { + 'win32' : 'x86', + 'win-amd64' : 'amd64', +} + +class Reg: + """Helper class to read values from the registry + """ + + def get_value(cls, path, key): + for base in HKEYS: + d = cls.read_values(base, path) + if d and key in d: + return d[key] + raise KeyError(key) + get_value = classmethod(get_value) + + def read_keys(cls, base, key): + """Return list of registry keys.""" + try: + handle = RegOpenKeyEx(base, key) + except RegError: + return None + L = [] + i = 0 + while True: + try: + k = RegEnumKey(handle, i) + except RegError: + break + L.append(k) + i += 1 + return L + read_keys = classmethod(read_keys) + + def read_values(cls, base, key): + """Return dict of registry keys and values. + + All names are converted to lowercase. + """ + try: + handle = RegOpenKeyEx(base, key) + except RegError: + return None + d = {} + i = 0 + while True: + try: + name, value, type = RegEnumValue(handle, i) + except RegError: + break + name = name.lower() + d[cls.convert_mbcs(name)] = cls.convert_mbcs(value) + i += 1 + return d + read_values = classmethod(read_values) + + def convert_mbcs(s): + dec = getattr(s, "decode", None) + if dec is not None: + try: + s = dec("mbcs") + except UnicodeError: + pass + return s + convert_mbcs = staticmethod(convert_mbcs) + +class MacroExpander: + + def __init__(self, version): + self.macros = {} + self.vsbase = VS_BASE % version + self.load_macros(version) + + def set_macro(self, macro, path, key): + self.macros["$(%s)" % macro] = Reg.get_value(path, key) + + def load_macros(self, version): + self.set_macro("VCInstallDir", self.vsbase + r"\Setup\VC", "productdir") + self.set_macro("VSInstallDir", self.vsbase + r"\Setup\VS", "productdir") + self.set_macro("FrameworkDir", NET_BASE, "installroot") + try: + if version >= 8.0: + self.set_macro("FrameworkSDKDir", NET_BASE, + "sdkinstallrootv2.0") + else: + raise KeyError("sdkinstallrootv2.0") + except KeyError: + raise DistutilsPlatformError( + """Python was built with Visual Studio 2008; +extensions must be built with a compiler than can generate compatible binaries. +Visual Studio 2008 was not found on this system. If you have Cygwin installed, +you can try compiling with MingW32, by passing "-c mingw32" to setup.py.""") + + if version >= 9.0: + self.set_macro("FrameworkVersion", self.vsbase, "clr version") + self.set_macro("WindowsSdkDir", WINSDK_BASE, "currentinstallfolder") + else: + p = r"Software\Microsoft\NET Framework Setup\Product" + for base in HKEYS: + try: + h = RegOpenKeyEx(base, p) + except RegError: + continue + key = RegEnumKey(h, 0) + d = Reg.get_value(base, r"%s\%s" % (p, key)) + self.macros["$(FrameworkVersion)"] = d["version"] + + def sub(self, s): + for k, v in self.macros.items(): + s = s.replace(k, v) + return s + +def get_build_version(): + """Return the version of MSVC that was used to build Python. + + For Python 2.3 and up, the version number is included in + sys.version. For earlier versions, assume the compiler is MSVC 6. + """ + prefix = "MSC v." + i = sys.version.find(prefix) + if i == -1: + return 6 + i = i + len(prefix) + s, rest = sys.version[i:].split(" ", 1) + majorVersion = int(s[:-2]) - 6 + if majorVersion >= 13: + # v13 was skipped and should be v14 + majorVersion += 1 + minorVersion = int(s[2:3]) / 10.0 + # I don't think paths are affected by minor version in version 6 + if majorVersion == 6: + minorVersion = 0 + if majorVersion >= 6: + return majorVersion + minorVersion + # else we don't know what version of the compiler this is + return None + +def normalize_and_reduce_paths(paths): + """Return a list of normalized paths with duplicates removed. + + The current order of paths is maintained. + """ + # Paths are normalized so things like: /a and /a/ aren't both preserved. + reduced_paths = [] + for p in paths: + np = os.path.normpath(p) + # XXX(nnorwitz): O(n**2), if reduced_paths gets long perhaps use a set. + if np not in reduced_paths: + reduced_paths.append(np) + return reduced_paths + +def removeDuplicates(variable): + """Remove duplicate values of an environment variable. + """ + oldList = variable.split(os.pathsep) + newList = [] + for i in oldList: + if i not in newList: + newList.append(i) + newVariable = os.pathsep.join(newList) + return newVariable + +def find_vcvarsall(version): + """Find the vcvarsall.bat file + + At first it tries to find the productdir of VS 2008 in the registry. If + that fails it falls back to the VS90COMNTOOLS env var. + """ + vsbase = VS_BASE % version + try: + productdir = Reg.get_value(r"%s\Setup\VC" % vsbase, + "productdir") + except KeyError: + log.debug("Unable to find productdir in registry") + productdir = None + + if not productdir or not os.path.isdir(productdir): + toolskey = "VS%0.f0COMNTOOLS" % version + toolsdir = os.environ.get(toolskey, None) + + if toolsdir and os.path.isdir(toolsdir): + productdir = os.path.join(toolsdir, os.pardir, os.pardir, "VC") + productdir = os.path.abspath(productdir) + if not os.path.isdir(productdir): + log.debug("%s is not a valid directory" % productdir) + return None + else: + log.debug("Env var %s is not set or invalid" % toolskey) + if not productdir: + log.debug("No productdir found") + return None + vcvarsall = os.path.join(productdir, "vcvarsall.bat") + if os.path.isfile(vcvarsall): + return vcvarsall + log.debug("Unable to find vcvarsall.bat") + return None + +def query_vcvarsall(version, arch="x86"): + """Launch vcvarsall.bat and read the settings from its environment + """ + vcvarsall = find_vcvarsall(version) + interesting = {"include", "lib", "libpath", "path"} + result = {} + + if vcvarsall is None: + raise DistutilsPlatformError("Unable to find vcvarsall.bat") + log.debug("Calling 'vcvarsall.bat %s' (version=%s)", arch, version) + popen = subprocess.Popen('"%s" %s & set' % (vcvarsall, arch), + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + try: + stdout, stderr = popen.communicate() + if popen.wait() != 0: + raise DistutilsPlatformError(stderr.decode("mbcs")) + + stdout = stdout.decode("mbcs") + for line in stdout.split("\n"): + line = Reg.convert_mbcs(line) + if '=' not in line: + continue + line = line.strip() + key, value = line.split('=', 1) + key = key.lower() + if key in interesting: + if value.endswith(os.pathsep): + value = value[:-1] + result[key] = removeDuplicates(value) + + finally: + popen.stdout.close() + popen.stderr.close() + + if len(result) != len(interesting): + raise ValueError(str(list(result.keys()))) + + return result + +# More globals +VERSION = get_build_version() +# MACROS = MacroExpander(VERSION) + +class MSVCCompiler(CCompiler) : + """Concrete class that implements an interface to Microsoft Visual C++, + as defined by the CCompiler abstract class.""" + + compiler_type = 'msvc' + + # Just set this so CCompiler's constructor doesn't barf. We currently + # don't use the 'set_executables()' bureaucracy provided by CCompiler, + # as it really isn't necessary for this sort of single-compiler class. + # Would be nice to have a consistent interface with UnixCCompiler, + # though, so it's worth thinking about. + executables = {} + + # Private class data (need to distinguish C from C++ source for compiler) + _c_extensions = ['.c'] + _cpp_extensions = ['.cc', '.cpp', '.cxx'] + _rc_extensions = ['.rc'] + _mc_extensions = ['.mc'] + + # Needed for the filename generation methods provided by the + # base class, CCompiler. + src_extensions = (_c_extensions + _cpp_extensions + + _rc_extensions + _mc_extensions) + res_extension = '.res' + obj_extension = '.obj' + static_lib_extension = '.lib' + shared_lib_extension = '.dll' + static_lib_format = shared_lib_format = '%s%s' + exe_extension = '.exe' + + def __init__(self, verbose=0, dry_run=0, force=0): + super().__init__(verbose, dry_run, force) + self.__version = VERSION + self.__root = r"Software\Microsoft\VisualStudio" + # self.__macros = MACROS + self.__paths = [] + # target platform (.plat_name is consistent with 'bdist') + self.plat_name = None + self.__arch = None # deprecated name + self.initialized = False + + def initialize(self, plat_name=None): + # multi-init means we would need to check platform same each time... + assert not self.initialized, "don't init multiple times" + if self.__version < 8.0: + raise DistutilsPlatformError("VC %0.1f is not supported by this module" % self.__version) + if plat_name is None: + plat_name = get_platform() + # sanity check for platforms to prevent obscure errors later. + ok_plats = 'win32', 'win-amd64' + if plat_name not in ok_plats: + raise DistutilsPlatformError("--plat-name must be one of %s" % + (ok_plats,)) + + if "DISTUTILS_USE_SDK" in os.environ and "MSSdk" in os.environ and self.find_exe("cl.exe"): + # Assume that the SDK set up everything alright; don't try to be + # smarter + self.cc = "cl.exe" + self.linker = "link.exe" + self.lib = "lib.exe" + self.rc = "rc.exe" + self.mc = "mc.exe" + else: + # On x86, 'vcvars32.bat amd64' creates an env that doesn't work; + # to cross compile, you use 'x86_amd64'. + # On AMD64, 'vcvars32.bat amd64' is a native build env; to cross + # compile use 'x86' (ie, it runs the x86 compiler directly) + if plat_name == get_platform() or plat_name == 'win32': + # native build or cross-compile to win32 + plat_spec = PLAT_TO_VCVARS[plat_name] + else: + # cross compile from win32 -> some 64bit + plat_spec = PLAT_TO_VCVARS[get_platform()] + '_' + \ + PLAT_TO_VCVARS[plat_name] + + vc_env = query_vcvarsall(VERSION, plat_spec) + + self.__paths = vc_env['path'].split(os.pathsep) + os.environ['lib'] = vc_env['lib'] + os.environ['include'] = vc_env['include'] + + if len(self.__paths) == 0: + raise DistutilsPlatformError("Python was built with %s, " + "and extensions need to be built with the same " + "version of the compiler, but it isn't installed." + % self.__product) + + self.cc = self.find_exe("cl.exe") + self.linker = self.find_exe("link.exe") + self.lib = self.find_exe("lib.exe") + self.rc = self.find_exe("rc.exe") # resource compiler + self.mc = self.find_exe("mc.exe") # message compiler + #self.set_path_env_var('lib') + #self.set_path_env_var('include') + + # extend the MSVC path with the current path + try: + for p in os.environ['path'].split(';'): + self.__paths.append(p) + except KeyError: + pass + self.__paths = normalize_and_reduce_paths(self.__paths) + os.environ['path'] = ";".join(self.__paths) + + self.preprocess_options = None + if self.__arch == "x86": + self.compile_options = [ '/nologo', '/O2', '/MD', '/W3', + '/DNDEBUG'] + self.compile_options_debug = ['/nologo', '/Od', '/MDd', '/W3', + '/Z7', '/D_DEBUG'] + else: + # Win64 + self.compile_options = [ '/nologo', '/O2', '/MD', '/W3', '/GS-' , + '/DNDEBUG'] + self.compile_options_debug = ['/nologo', '/Od', '/MDd', '/W3', '/GS-', + '/Z7', '/D_DEBUG'] + + self.ldflags_shared = ['/DLL', '/nologo', '/INCREMENTAL:NO'] + if self.__version >= 7: + self.ldflags_shared_debug = [ + '/DLL', '/nologo', '/INCREMENTAL:no', '/DEBUG' + ] + self.ldflags_static = [ '/nologo'] + + self.initialized = True + + # -- Worker methods ------------------------------------------------ + + def object_filenames(self, + source_filenames, + strip_dir=0, + output_dir=''): + # Copied from ccompiler.py, extended to return .res as 'object'-file + # for .rc input file + if output_dir is None: output_dir = '' + obj_names = [] + for src_name in source_filenames: + (base, ext) = os.path.splitext (src_name) + base = os.path.splitdrive(base)[1] # Chop off the drive + base = base[os.path.isabs(base):] # If abs, chop off leading / + if ext not in self.src_extensions: + # Better to raise an exception instead of silently continuing + # and later complain about sources and targets having + # different lengths + raise CompileError ("Don't know how to compile %s" % src_name) + if strip_dir: + base = os.path.basename (base) + if ext in self._rc_extensions: + obj_names.append (os.path.join (output_dir, + base + self.res_extension)) + elif ext in self._mc_extensions: + obj_names.append (os.path.join (output_dir, + base + self.res_extension)) + else: + obj_names.append (os.path.join (output_dir, + base + self.obj_extension)) + return obj_names + + + def compile(self, sources, + output_dir=None, macros=None, include_dirs=None, debug=0, + extra_preargs=None, extra_postargs=None, depends=None): + + if not self.initialized: + self.initialize() + compile_info = self._setup_compile(output_dir, macros, include_dirs, + sources, depends, extra_postargs) + macros, objects, extra_postargs, pp_opts, build = compile_info + + compile_opts = extra_preargs or [] + compile_opts.append ('/c') + if debug: + compile_opts.extend(self.compile_options_debug) + else: + compile_opts.extend(self.compile_options) + + for obj in objects: + try: + src, ext = build[obj] + except KeyError: + continue + if debug: + # pass the full pathname to MSVC in debug mode, + # this allows the debugger to find the source file + # without asking the user to browse for it + src = os.path.abspath(src) + + if ext in self._c_extensions: + input_opt = "/Tc" + src + elif ext in self._cpp_extensions: + input_opt = "/Tp" + src + elif ext in self._rc_extensions: + # compile .RC to .RES file + input_opt = src + output_opt = "/fo" + obj + try: + self.spawn([self.rc] + pp_opts + + [output_opt] + [input_opt]) + except DistutilsExecError as msg: + raise CompileError(msg) + continue + elif ext in self._mc_extensions: + # Compile .MC to .RC file to .RES file. + # * '-h dir' specifies the directory for the + # generated include file + # * '-r dir' specifies the target directory of the + # generated RC file and the binary message resource + # it includes + # + # For now (since there are no options to change this), + # we use the source-directory for the include file and + # the build directory for the RC file and message + # resources. This works at least for win32all. + h_dir = os.path.dirname(src) + rc_dir = os.path.dirname(obj) + try: + # first compile .MC to .RC and .H file + self.spawn([self.mc] + + ['-h', h_dir, '-r', rc_dir] + [src]) + base, _ = os.path.splitext (os.path.basename (src)) + rc_file = os.path.join (rc_dir, base + '.rc') + # then compile .RC to .RES file + self.spawn([self.rc] + + ["/fo" + obj] + [rc_file]) + + except DistutilsExecError as msg: + raise CompileError(msg) + continue + else: + # how to handle this file? + raise CompileError("Don't know how to compile %s to %s" + % (src, obj)) + + output_opt = "/Fo" + obj + try: + self.spawn([self.cc] + compile_opts + pp_opts + + [input_opt, output_opt] + + extra_postargs) + except DistutilsExecError as msg: + raise CompileError(msg) + + return objects + + + def create_static_lib(self, + objects, + output_libname, + output_dir=None, + debug=0, + target_lang=None): + + if not self.initialized: + self.initialize() + (objects, output_dir) = self._fix_object_args(objects, output_dir) + output_filename = self.library_filename(output_libname, + output_dir=output_dir) + + if self._need_link(objects, output_filename): + lib_args = objects + ['/OUT:' + output_filename] + if debug: + pass # XXX what goes here? + try: + self.spawn([self.lib] + lib_args) + except DistutilsExecError as msg: + raise LibError(msg) + else: + log.debug("skipping %s (up-to-date)", output_filename) + + + def link(self, + target_desc, + objects, + output_filename, + output_dir=None, + libraries=None, + library_dirs=None, + runtime_library_dirs=None, + export_symbols=None, + debug=0, + extra_preargs=None, + extra_postargs=None, + build_temp=None, + target_lang=None): + + if not self.initialized: + self.initialize() + (objects, output_dir) = self._fix_object_args(objects, output_dir) + fixed_args = self._fix_lib_args(libraries, library_dirs, + runtime_library_dirs) + (libraries, library_dirs, runtime_library_dirs) = fixed_args + + if runtime_library_dirs: + self.warn ("I don't know what to do with 'runtime_library_dirs': " + + str (runtime_library_dirs)) + + lib_opts = gen_lib_options(self, + library_dirs, runtime_library_dirs, + libraries) + if output_dir is not None: + output_filename = os.path.join(output_dir, output_filename) + + if self._need_link(objects, output_filename): + if target_desc == CCompiler.EXECUTABLE: + if debug: + ldflags = self.ldflags_shared_debug[1:] + else: + ldflags = self.ldflags_shared[1:] + else: + if debug: + ldflags = self.ldflags_shared_debug + else: + ldflags = self.ldflags_shared + + export_opts = [] + for sym in (export_symbols or []): + export_opts.append("/EXPORT:" + sym) + + ld_args = (ldflags + lib_opts + export_opts + + objects + ['/OUT:' + output_filename]) + + # The MSVC linker generates .lib and .exp files, which cannot be + # suppressed by any linker switches. The .lib files may even be + # needed! Make sure they are generated in the temporary build + # directory. Since they have different names for debug and release + # builds, they can go into the same directory. + build_temp = os.path.dirname(objects[0]) + if export_symbols is not None: + (dll_name, dll_ext) = os.path.splitext( + os.path.basename(output_filename)) + implib_file = os.path.join( + build_temp, + self.library_filename(dll_name)) + ld_args.append ('/IMPLIB:' + implib_file) + + self.manifest_setup_ldargs(output_filename, build_temp, ld_args) + + if extra_preargs: + ld_args[:0] = extra_preargs + if extra_postargs: + ld_args.extend(extra_postargs) + + self.mkpath(os.path.dirname(output_filename)) + try: + self.spawn([self.linker] + ld_args) + except DistutilsExecError as msg: + raise LinkError(msg) + + # embed the manifest + # XXX - this is somewhat fragile - if mt.exe fails, distutils + # will still consider the DLL up-to-date, but it will not have a + # manifest. Maybe we should link to a temp file? OTOH, that + # implies a build environment error that shouldn't go undetected. + mfinfo = self.manifest_get_embed_info(target_desc, ld_args) + if mfinfo is not None: + mffilename, mfid = mfinfo + out_arg = '-outputresource:%s;%s' % (output_filename, mfid) + try: + self.spawn(['mt.exe', '-nologo', '-manifest', + mffilename, out_arg]) + except DistutilsExecError as msg: + raise LinkError(msg) + else: + log.debug("skipping %s (up-to-date)", output_filename) + + def manifest_setup_ldargs(self, output_filename, build_temp, ld_args): + # If we need a manifest at all, an embedded manifest is recommended. + # See MSDN article titled + # "How to: Embed a Manifest Inside a C/C++ Application" + # (currently at http://msdn2.microsoft.com/en-us/library/ms235591(VS.80).aspx) + # Ask the linker to generate the manifest in the temp dir, so + # we can check it, and possibly embed it, later. + temp_manifest = os.path.join( + build_temp, + os.path.basename(output_filename) + ".manifest") + ld_args.append('/MANIFESTFILE:' + temp_manifest) + + def manifest_get_embed_info(self, target_desc, ld_args): + # If a manifest should be embedded, return a tuple of + # (manifest_filename, resource_id). Returns None if no manifest + # should be embedded. See http://bugs.python.org/issue7833 for why + # we want to avoid any manifest for extension modules if we can) + for arg in ld_args: + if arg.startswith("/MANIFESTFILE:"): + temp_manifest = arg.split(":", 1)[1] + break + else: + # no /MANIFESTFILE so nothing to do. + return None + if target_desc == CCompiler.EXECUTABLE: + # by default, executables always get the manifest with the + # CRT referenced. + mfid = 1 + else: + # Extension modules try and avoid any manifest if possible. + mfid = 2 + temp_manifest = self._remove_visual_c_ref(temp_manifest) + if temp_manifest is None: + return None + return temp_manifest, mfid + + def _remove_visual_c_ref(self, manifest_file): + try: + # Remove references to the Visual C runtime, so they will + # fall through to the Visual C dependency of Python.exe. + # This way, when installed for a restricted user (e.g. + # runtimes are not in WinSxS folder, but in Python's own + # folder), the runtimes do not need to be in every folder + # with .pyd's. + # Returns either the filename of the modified manifest or + # None if no manifest should be embedded. + manifest_f = open(manifest_file) + try: + manifest_buf = manifest_f.read() + finally: + manifest_f.close() + pattern = re.compile( + r"""|)""", + re.DOTALL) + manifest_buf = re.sub(pattern, "", manifest_buf) + pattern = r"\s*" + manifest_buf = re.sub(pattern, "", manifest_buf) + # Now see if any other assemblies are referenced - if not, we + # don't want a manifest embedded. + pattern = re.compile( + r"""|)""", re.DOTALL) + if re.search(pattern, manifest_buf) is None: + return None + + manifest_f = open(manifest_file, 'w') + try: + manifest_f.write(manifest_buf) + return manifest_file + finally: + manifest_f.close() + except OSError: + pass + + # -- Miscellaneous methods ----------------------------------------- + # These are all used by the 'gen_lib_options() function, in + # ccompiler.py. + + def library_dir_option(self, dir): + return "/LIBPATH:" + dir + + def runtime_library_dir_option(self, dir): + raise DistutilsPlatformError( + "don't know how to set runtime library search path for MSVC++") + + def library_option(self, lib): + return self.library_filename(lib) + + + def find_library_file(self, dirs, lib, debug=0): + # Prefer a debugging library if found (and requested), but deal + # with it if we don't have one. + if debug: + try_names = [lib + "_d", lib] + else: + try_names = [lib] + for dir in dirs: + for name in try_names: + libfile = os.path.join(dir, self.library_filename (name)) + if os.path.exists(libfile): + return libfile + else: + # Oops, didn't find it in *any* of 'dirs' + return None + + # Helper methods for using the MSVC registry settings + + def find_exe(self, exe): + """Return path to an MSVC executable program. + + Tries to find the program in several places: first, one of the + MSVC program search paths from the registry; next, the directories + in the PATH environment variable. If any of those work, return an + absolute path that is known to exist. If none of them work, just + return the original program name, 'exe'. + """ + for p in self.__paths: + fn = os.path.join(os.path.abspath(p), exe) + if os.path.isfile(fn): + return fn + + # didn't find it; try existing path + for p in os.environ['Path'].split(';'): + fn = os.path.join(os.path.abspath(p),exe) + if os.path.isfile(fn): + return fn + + return exe diff --git a/venv/Lib/site-packages/setuptools/_distutils/msvccompiler.py b/venv/Lib/site-packages/setuptools/_distutils/msvccompiler.py new file mode 100644 index 0000000..e1367b8 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_distutils/msvccompiler.py @@ -0,0 +1,643 @@ +"""distutils.msvccompiler + +Contains MSVCCompiler, an implementation of the abstract CCompiler class +for the Microsoft Visual Studio. +""" + +# Written by Perry Stoll +# hacked by Robin Becker and Thomas Heller to do a better job of +# finding DevStudio (through the registry) + +import sys, os +from distutils.errors import \ + DistutilsExecError, DistutilsPlatformError, \ + CompileError, LibError, LinkError +from distutils.ccompiler import \ + CCompiler, gen_lib_options +from distutils import log + +_can_read_reg = False +try: + import winreg + + _can_read_reg = True + hkey_mod = winreg + + RegOpenKeyEx = winreg.OpenKeyEx + RegEnumKey = winreg.EnumKey + RegEnumValue = winreg.EnumValue + RegError = winreg.error + +except ImportError: + try: + import win32api + import win32con + _can_read_reg = True + hkey_mod = win32con + + RegOpenKeyEx = win32api.RegOpenKeyEx + RegEnumKey = win32api.RegEnumKey + RegEnumValue = win32api.RegEnumValue + RegError = win32api.error + except ImportError: + log.info("Warning: Can't read registry to find the " + "necessary compiler setting\n" + "Make sure that Python modules winreg, " + "win32api or win32con are installed.") + pass + +if _can_read_reg: + HKEYS = (hkey_mod.HKEY_USERS, + hkey_mod.HKEY_CURRENT_USER, + hkey_mod.HKEY_LOCAL_MACHINE, + hkey_mod.HKEY_CLASSES_ROOT) + +def read_keys(base, key): + """Return list of registry keys.""" + try: + handle = RegOpenKeyEx(base, key) + except RegError: + return None + L = [] + i = 0 + while True: + try: + k = RegEnumKey(handle, i) + except RegError: + break + L.append(k) + i += 1 + return L + +def read_values(base, key): + """Return dict of registry keys and values. + + All names are converted to lowercase. + """ + try: + handle = RegOpenKeyEx(base, key) + except RegError: + return None + d = {} + i = 0 + while True: + try: + name, value, type = RegEnumValue(handle, i) + except RegError: + break + name = name.lower() + d[convert_mbcs(name)] = convert_mbcs(value) + i += 1 + return d + +def convert_mbcs(s): + dec = getattr(s, "decode", None) + if dec is not None: + try: + s = dec("mbcs") + except UnicodeError: + pass + return s + +class MacroExpander: + def __init__(self, version): + self.macros = {} + self.load_macros(version) + + def set_macro(self, macro, path, key): + for base in HKEYS: + d = read_values(base, path) + if d: + self.macros["$(%s)" % macro] = d[key] + break + + def load_macros(self, version): + vsbase = r"Software\Microsoft\VisualStudio\%0.1f" % version + self.set_macro("VCInstallDir", vsbase + r"\Setup\VC", "productdir") + self.set_macro("VSInstallDir", vsbase + r"\Setup\VS", "productdir") + net = r"Software\Microsoft\.NETFramework" + self.set_macro("FrameworkDir", net, "installroot") + try: + if version > 7.0: + self.set_macro("FrameworkSDKDir", net, "sdkinstallrootv1.1") + else: + self.set_macro("FrameworkSDKDir", net, "sdkinstallroot") + except KeyError as exc: # + raise DistutilsPlatformError( + """Python was built with Visual Studio 2003; +extensions must be built with a compiler than can generate compatible binaries. +Visual Studio 2003 was not found on this system. If you have Cygwin installed, +you can try compiling with MingW32, by passing "-c mingw32" to setup.py.""") + + p = r"Software\Microsoft\NET Framework Setup\Product" + for base in HKEYS: + try: + h = RegOpenKeyEx(base, p) + except RegError: + continue + key = RegEnumKey(h, 0) + d = read_values(base, r"%s\%s" % (p, key)) + self.macros["$(FrameworkVersion)"] = d["version"] + + def sub(self, s): + for k, v in self.macros.items(): + s = s.replace(k, v) + return s + +def get_build_version(): + """Return the version of MSVC that was used to build Python. + + For Python 2.3 and up, the version number is included in + sys.version. For earlier versions, assume the compiler is MSVC 6. + """ + prefix = "MSC v." + i = sys.version.find(prefix) + if i == -1: + return 6 + i = i + len(prefix) + s, rest = sys.version[i:].split(" ", 1) + majorVersion = int(s[:-2]) - 6 + if majorVersion >= 13: + # v13 was skipped and should be v14 + majorVersion += 1 + minorVersion = int(s[2:3]) / 10.0 + # I don't think paths are affected by minor version in version 6 + if majorVersion == 6: + minorVersion = 0 + if majorVersion >= 6: + return majorVersion + minorVersion + # else we don't know what version of the compiler this is + return None + +def get_build_architecture(): + """Return the processor architecture. + + Possible results are "Intel" or "AMD64". + """ + + prefix = " bit (" + i = sys.version.find(prefix) + if i == -1: + return "Intel" + j = sys.version.find(")", i) + return sys.version[i+len(prefix):j] + +def normalize_and_reduce_paths(paths): + """Return a list of normalized paths with duplicates removed. + + The current order of paths is maintained. + """ + # Paths are normalized so things like: /a and /a/ aren't both preserved. + reduced_paths = [] + for p in paths: + np = os.path.normpath(p) + # XXX(nnorwitz): O(n**2), if reduced_paths gets long perhaps use a set. + if np not in reduced_paths: + reduced_paths.append(np) + return reduced_paths + + +class MSVCCompiler(CCompiler) : + """Concrete class that implements an interface to Microsoft Visual C++, + as defined by the CCompiler abstract class.""" + + compiler_type = 'msvc' + + # Just set this so CCompiler's constructor doesn't barf. We currently + # don't use the 'set_executables()' bureaucracy provided by CCompiler, + # as it really isn't necessary for this sort of single-compiler class. + # Would be nice to have a consistent interface with UnixCCompiler, + # though, so it's worth thinking about. + executables = {} + + # Private class data (need to distinguish C from C++ source for compiler) + _c_extensions = ['.c'] + _cpp_extensions = ['.cc', '.cpp', '.cxx'] + _rc_extensions = ['.rc'] + _mc_extensions = ['.mc'] + + # Needed for the filename generation methods provided by the + # base class, CCompiler. + src_extensions = (_c_extensions + _cpp_extensions + + _rc_extensions + _mc_extensions) + res_extension = '.res' + obj_extension = '.obj' + static_lib_extension = '.lib' + shared_lib_extension = '.dll' + static_lib_format = shared_lib_format = '%s%s' + exe_extension = '.exe' + + def __init__(self, verbose=0, dry_run=0, force=0): + super().__init__(verbose, dry_run, force) + self.__version = get_build_version() + self.__arch = get_build_architecture() + if self.__arch == "Intel": + # x86 + if self.__version >= 7: + self.__root = r"Software\Microsoft\VisualStudio" + self.__macros = MacroExpander(self.__version) + else: + self.__root = r"Software\Microsoft\Devstudio" + self.__product = "Visual Studio version %s" % self.__version + else: + # Win64. Assume this was built with the platform SDK + self.__product = "Microsoft SDK compiler %s" % (self.__version + 6) + + self.initialized = False + + def initialize(self): + self.__paths = [] + if "DISTUTILS_USE_SDK" in os.environ and "MSSdk" in os.environ and self.find_exe("cl.exe"): + # Assume that the SDK set up everything alright; don't try to be + # smarter + self.cc = "cl.exe" + self.linker = "link.exe" + self.lib = "lib.exe" + self.rc = "rc.exe" + self.mc = "mc.exe" + else: + self.__paths = self.get_msvc_paths("path") + + if len(self.__paths) == 0: + raise DistutilsPlatformError("Python was built with %s, " + "and extensions need to be built with the same " + "version of the compiler, but it isn't installed." + % self.__product) + + self.cc = self.find_exe("cl.exe") + self.linker = self.find_exe("link.exe") + self.lib = self.find_exe("lib.exe") + self.rc = self.find_exe("rc.exe") # resource compiler + self.mc = self.find_exe("mc.exe") # message compiler + self.set_path_env_var('lib') + self.set_path_env_var('include') + + # extend the MSVC path with the current path + try: + for p in os.environ['path'].split(';'): + self.__paths.append(p) + except KeyError: + pass + self.__paths = normalize_and_reduce_paths(self.__paths) + os.environ['path'] = ";".join(self.__paths) + + self.preprocess_options = None + if self.__arch == "Intel": + self.compile_options = [ '/nologo', '/O2', '/MD', '/W3', '/GX' , + '/DNDEBUG'] + self.compile_options_debug = ['/nologo', '/Od', '/MDd', '/W3', '/GX', + '/Z7', '/D_DEBUG'] + else: + # Win64 + self.compile_options = [ '/nologo', '/O2', '/MD', '/W3', '/GS-' , + '/DNDEBUG'] + self.compile_options_debug = ['/nologo', '/Od', '/MDd', '/W3', '/GS-', + '/Z7', '/D_DEBUG'] + + self.ldflags_shared = ['/DLL', '/nologo', '/INCREMENTAL:NO'] + if self.__version >= 7: + self.ldflags_shared_debug = [ + '/DLL', '/nologo', '/INCREMENTAL:no', '/DEBUG' + ] + else: + self.ldflags_shared_debug = [ + '/DLL', '/nologo', '/INCREMENTAL:no', '/pdb:None', '/DEBUG' + ] + self.ldflags_static = [ '/nologo'] + + self.initialized = True + + # -- Worker methods ------------------------------------------------ + + def object_filenames(self, + source_filenames, + strip_dir=0, + output_dir=''): + # Copied from ccompiler.py, extended to return .res as 'object'-file + # for .rc input file + if output_dir is None: output_dir = '' + obj_names = [] + for src_name in source_filenames: + (base, ext) = os.path.splitext (src_name) + base = os.path.splitdrive(base)[1] # Chop off the drive + base = base[os.path.isabs(base):] # If abs, chop off leading / + if ext not in self.src_extensions: + # Better to raise an exception instead of silently continuing + # and later complain about sources and targets having + # different lengths + raise CompileError ("Don't know how to compile %s" % src_name) + if strip_dir: + base = os.path.basename (base) + if ext in self._rc_extensions: + obj_names.append (os.path.join (output_dir, + base + self.res_extension)) + elif ext in self._mc_extensions: + obj_names.append (os.path.join (output_dir, + base + self.res_extension)) + else: + obj_names.append (os.path.join (output_dir, + base + self.obj_extension)) + return obj_names + + + def compile(self, sources, + output_dir=None, macros=None, include_dirs=None, debug=0, + extra_preargs=None, extra_postargs=None, depends=None): + + if not self.initialized: + self.initialize() + compile_info = self._setup_compile(output_dir, macros, include_dirs, + sources, depends, extra_postargs) + macros, objects, extra_postargs, pp_opts, build = compile_info + + compile_opts = extra_preargs or [] + compile_opts.append ('/c') + if debug: + compile_opts.extend(self.compile_options_debug) + else: + compile_opts.extend(self.compile_options) + + for obj in objects: + try: + src, ext = build[obj] + except KeyError: + continue + if debug: + # pass the full pathname to MSVC in debug mode, + # this allows the debugger to find the source file + # without asking the user to browse for it + src = os.path.abspath(src) + + if ext in self._c_extensions: + input_opt = "/Tc" + src + elif ext in self._cpp_extensions: + input_opt = "/Tp" + src + elif ext in self._rc_extensions: + # compile .RC to .RES file + input_opt = src + output_opt = "/fo" + obj + try: + self.spawn([self.rc] + pp_opts + + [output_opt] + [input_opt]) + except DistutilsExecError as msg: + raise CompileError(msg) + continue + elif ext in self._mc_extensions: + # Compile .MC to .RC file to .RES file. + # * '-h dir' specifies the directory for the + # generated include file + # * '-r dir' specifies the target directory of the + # generated RC file and the binary message resource + # it includes + # + # For now (since there are no options to change this), + # we use the source-directory for the include file and + # the build directory for the RC file and message + # resources. This works at least for win32all. + h_dir = os.path.dirname(src) + rc_dir = os.path.dirname(obj) + try: + # first compile .MC to .RC and .H file + self.spawn([self.mc] + + ['-h', h_dir, '-r', rc_dir] + [src]) + base, _ = os.path.splitext (os.path.basename (src)) + rc_file = os.path.join (rc_dir, base + '.rc') + # then compile .RC to .RES file + self.spawn([self.rc] + + ["/fo" + obj] + [rc_file]) + + except DistutilsExecError as msg: + raise CompileError(msg) + continue + else: + # how to handle this file? + raise CompileError("Don't know how to compile %s to %s" + % (src, obj)) + + output_opt = "/Fo" + obj + try: + self.spawn([self.cc] + compile_opts + pp_opts + + [input_opt, output_opt] + + extra_postargs) + except DistutilsExecError as msg: + raise CompileError(msg) + + return objects + + + def create_static_lib(self, + objects, + output_libname, + output_dir=None, + debug=0, + target_lang=None): + + if not self.initialized: + self.initialize() + (objects, output_dir) = self._fix_object_args(objects, output_dir) + output_filename = self.library_filename(output_libname, + output_dir=output_dir) + + if self._need_link(objects, output_filename): + lib_args = objects + ['/OUT:' + output_filename] + if debug: + pass # XXX what goes here? + try: + self.spawn([self.lib] + lib_args) + except DistutilsExecError as msg: + raise LibError(msg) + else: + log.debug("skipping %s (up-to-date)", output_filename) + + + def link(self, + target_desc, + objects, + output_filename, + output_dir=None, + libraries=None, + library_dirs=None, + runtime_library_dirs=None, + export_symbols=None, + debug=0, + extra_preargs=None, + extra_postargs=None, + build_temp=None, + target_lang=None): + + if not self.initialized: + self.initialize() + (objects, output_dir) = self._fix_object_args(objects, output_dir) + fixed_args = self._fix_lib_args(libraries, library_dirs, + runtime_library_dirs) + (libraries, library_dirs, runtime_library_dirs) = fixed_args + + if runtime_library_dirs: + self.warn ("I don't know what to do with 'runtime_library_dirs': " + + str (runtime_library_dirs)) + + lib_opts = gen_lib_options(self, + library_dirs, runtime_library_dirs, + libraries) + if output_dir is not None: + output_filename = os.path.join(output_dir, output_filename) + + if self._need_link(objects, output_filename): + if target_desc == CCompiler.EXECUTABLE: + if debug: + ldflags = self.ldflags_shared_debug[1:] + else: + ldflags = self.ldflags_shared[1:] + else: + if debug: + ldflags = self.ldflags_shared_debug + else: + ldflags = self.ldflags_shared + + export_opts = [] + for sym in (export_symbols or []): + export_opts.append("/EXPORT:" + sym) + + ld_args = (ldflags + lib_opts + export_opts + + objects + ['/OUT:' + output_filename]) + + # The MSVC linker generates .lib and .exp files, which cannot be + # suppressed by any linker switches. The .lib files may even be + # needed! Make sure they are generated in the temporary build + # directory. Since they have different names for debug and release + # builds, they can go into the same directory. + if export_symbols is not None: + (dll_name, dll_ext) = os.path.splitext( + os.path.basename(output_filename)) + implib_file = os.path.join( + os.path.dirname(objects[0]), + self.library_filename(dll_name)) + ld_args.append ('/IMPLIB:' + implib_file) + + if extra_preargs: + ld_args[:0] = extra_preargs + if extra_postargs: + ld_args.extend(extra_postargs) + + self.mkpath(os.path.dirname(output_filename)) + try: + self.spawn([self.linker] + ld_args) + except DistutilsExecError as msg: + raise LinkError(msg) + + else: + log.debug("skipping %s (up-to-date)", output_filename) + + + # -- Miscellaneous methods ----------------------------------------- + # These are all used by the 'gen_lib_options() function, in + # ccompiler.py. + + def library_dir_option(self, dir): + return "/LIBPATH:" + dir + + def runtime_library_dir_option(self, dir): + raise DistutilsPlatformError( + "don't know how to set runtime library search path for MSVC++") + + def library_option(self, lib): + return self.library_filename(lib) + + + def find_library_file(self, dirs, lib, debug=0): + # Prefer a debugging library if found (and requested), but deal + # with it if we don't have one. + if debug: + try_names = [lib + "_d", lib] + else: + try_names = [lib] + for dir in dirs: + for name in try_names: + libfile = os.path.join(dir, self.library_filename (name)) + if os.path.exists(libfile): + return libfile + else: + # Oops, didn't find it in *any* of 'dirs' + return None + + # Helper methods for using the MSVC registry settings + + def find_exe(self, exe): + """Return path to an MSVC executable program. + + Tries to find the program in several places: first, one of the + MSVC program search paths from the registry; next, the directories + in the PATH environment variable. If any of those work, return an + absolute path that is known to exist. If none of them work, just + return the original program name, 'exe'. + """ + for p in self.__paths: + fn = os.path.join(os.path.abspath(p), exe) + if os.path.isfile(fn): + return fn + + # didn't find it; try existing path + for p in os.environ['Path'].split(';'): + fn = os.path.join(os.path.abspath(p),exe) + if os.path.isfile(fn): + return fn + + return exe + + def get_msvc_paths(self, path, platform='x86'): + """Get a list of devstudio directories (include, lib or path). + + Return a list of strings. The list will be empty if unable to + access the registry or appropriate registry keys not found. + """ + if not _can_read_reg: + return [] + + path = path + " dirs" + if self.__version >= 7: + key = (r"%s\%0.1f\VC\VC_OBJECTS_PLATFORM_INFO\Win32\Directories" + % (self.__root, self.__version)) + else: + key = (r"%s\6.0\Build System\Components\Platforms" + r"\Win32 (%s)\Directories" % (self.__root, platform)) + + for base in HKEYS: + d = read_values(base, key) + if d: + if self.__version >= 7: + return self.__macros.sub(d[path]).split(";") + else: + return d[path].split(";") + # MSVC 6 seems to create the registry entries we need only when + # the GUI is run. + if self.__version == 6: + for base in HKEYS: + if read_values(base, r"%s\6.0" % self.__root) is not None: + self.warn("It seems you have Visual Studio 6 installed, " + "but the expected registry settings are not present.\n" + "You must at least run the Visual Studio GUI once " + "so that these entries are created.") + break + return [] + + def set_path_env_var(self, name): + """Set environment variable 'name' to an MSVC path type value. + + This is equivalent to a SET command prior to execution of spawned + commands. + """ + + if name == "lib": + p = self.get_msvc_paths("library") + else: + p = self.get_msvc_paths(name) + if p: + os.environ[name] = ';'.join(p) + + +if get_build_version() >= 8.0: + log.debug("Importing new compiler from distutils.msvc9compiler") + OldMSVCCompiler = MSVCCompiler + from distutils.msvc9compiler import MSVCCompiler + # get_build_architecture not really relevant now we support cross-compile + from distutils.msvc9compiler import MacroExpander diff --git a/venv/Lib/site-packages/setuptools/_distutils/py35compat.py b/venv/Lib/site-packages/setuptools/_distutils/py35compat.py new file mode 100644 index 0000000..79b2e7f --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_distutils/py35compat.py @@ -0,0 +1,19 @@ +import sys +import subprocess + + +def __optim_args_from_interpreter_flags(): + """Return a list of command-line arguments reproducing the current + optimization settings in sys.flags.""" + args = [] + value = sys.flags.optimize + if value > 0: + args.append("-" + "O" * value) + return args + + +_optim_args_from_interpreter_flags = getattr( + subprocess, + "_optim_args_from_interpreter_flags", + __optim_args_from_interpreter_flags, +) diff --git a/venv/Lib/site-packages/setuptools/_distutils/py38compat.py b/venv/Lib/site-packages/setuptools/_distutils/py38compat.py new file mode 100644 index 0000000..7dbe8ce --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_distutils/py38compat.py @@ -0,0 +1,7 @@ +def aix_platform(osname, version, release): + try: + import _aix_support + return _aix_support.aix_platform() + except ImportError: + pass + return "%s-%s.%s" % (osname, version, release) diff --git a/venv/Lib/site-packages/setuptools/_distutils/spawn.py b/venv/Lib/site-packages/setuptools/_distutils/spawn.py new file mode 100644 index 0000000..b2d10e3 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_distutils/spawn.py @@ -0,0 +1,106 @@ +"""distutils.spawn + +Provides the 'spawn()' function, a front-end to various platform- +specific functions for launching another program in a sub-process. +Also provides the 'find_executable()' to search the path for a given +executable name. +""" + +import sys +import os +import subprocess + +from distutils.errors import DistutilsExecError +from distutils.debug import DEBUG +from distutils import log + + +def spawn(cmd, search_path=1, verbose=0, dry_run=0, env=None): + """Run another program, specified as a command list 'cmd', in a new process. + + 'cmd' is just the argument list for the new process, ie. + cmd[0] is the program to run and cmd[1:] are the rest of its arguments. + There is no way to run a program with a name different from that of its + executable. + + If 'search_path' is true (the default), the system's executable + search path will be used to find the program; otherwise, cmd[0] + must be the exact path to the executable. If 'dry_run' is true, + the command will not actually be run. + + Raise DistutilsExecError if running the program fails in any way; just + return on success. + """ + # cmd is documented as a list, but just in case some code passes a tuple + # in, protect our %-formatting code against horrible death + cmd = list(cmd) + + log.info(subprocess.list2cmdline(cmd)) + if dry_run: + return + + if search_path: + executable = find_executable(cmd[0]) + if executable is not None: + cmd[0] = executable + + env = env if env is not None else dict(os.environ) + + if sys.platform == 'darwin': + from distutils.util import MACOSX_VERSION_VAR, get_macosx_target_ver + macosx_target_ver = get_macosx_target_ver() + if macosx_target_ver: + env[MACOSX_VERSION_VAR] = macosx_target_ver + + try: + proc = subprocess.Popen(cmd, env=env) + proc.wait() + exitcode = proc.returncode + except OSError as exc: + if not DEBUG: + cmd = cmd[0] + raise DistutilsExecError( + "command %r failed: %s" % (cmd, exc.args[-1])) from exc + + if exitcode: + if not DEBUG: + cmd = cmd[0] + raise DistutilsExecError( + "command %r failed with exit code %s" % (cmd, exitcode)) + + +def find_executable(executable, path=None): + """Tries to find 'executable' in the directories listed in 'path'. + + A string listing directories separated by 'os.pathsep'; defaults to + os.environ['PATH']. Returns the complete filename or None if not found. + """ + _, ext = os.path.splitext(executable) + if (sys.platform == 'win32') and (ext != '.exe'): + executable = executable + '.exe' + + if os.path.isfile(executable): + return executable + + 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 + + paths = path.split(os.pathsep) + for p in paths: + f = os.path.join(p, executable) + if os.path.isfile(f): + # the file exists, we have a shot at spawn working + return f + return None diff --git a/venv/Lib/site-packages/setuptools/_distutils/sysconfig.py b/venv/Lib/site-packages/setuptools/_distutils/sysconfig.py new file mode 100644 index 0000000..4a77a43 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_distutils/sysconfig.py @@ -0,0 +1,567 @@ +"""Provide access to Python's configuration information. The specific +configuration variables available depend heavily on the platform and +configuration. The values may be retrieved using +get_config_var(name), and the list of variables is available via +get_config_vars().keys(). Additional convenience functions are also +available. + +Written by: Fred L. Drake, Jr. +Email: +""" + +import _imp +import os +import re +import sys +import sysconfig + +from .errors import DistutilsPlatformError + +IS_PYPY = '__pypy__' in sys.builtin_module_names + +# These are needed in a couple of spots, so just compute them once. +PREFIX = os.path.normpath(sys.prefix) +EXEC_PREFIX = os.path.normpath(sys.exec_prefix) +BASE_PREFIX = os.path.normpath(sys.base_prefix) +BASE_EXEC_PREFIX = os.path.normpath(sys.base_exec_prefix) + +# Path to the base directory of the project. On Windows the binary may +# live in project/PCbuild/win32 or project/PCbuild/amd64. +# set for cross builds +if "_PYTHON_PROJECT_BASE" in os.environ: + project_base = os.path.abspath(os.environ["_PYTHON_PROJECT_BASE"]) +else: + if sys.executable: + project_base = os.path.dirname(os.path.abspath(sys.executable)) + else: + # sys.executable can be empty if argv[0] has been changed and Python is + # unable to retrieve the real program name + project_base = os.getcwd() + + +# python_build: (Boolean) if true, we're either building Python or +# building an extension with an un-installed Python, so we use +# different (hard-wired) directories. +def _is_python_source_dir(d): + for fn in ("Setup", "Setup.local"): + if os.path.isfile(os.path.join(d, "Modules", fn)): + return True + return False + +_sys_home = getattr(sys, '_home', None) + +if os.name == 'nt': + def _fix_pcbuild(d): + if d and os.path.normcase(d).startswith( + os.path.normcase(os.path.join(PREFIX, "PCbuild"))): + return PREFIX + return d + project_base = _fix_pcbuild(project_base) + _sys_home = _fix_pcbuild(_sys_home) + +def _python_build(): + if _sys_home: + return _is_python_source_dir(_sys_home) + return _is_python_source_dir(project_base) + +python_build = _python_build() + + +# Calculate the build qualifier flags if they are defined. Adding the flags +# to the include and lib directories only makes sense for an installation, not +# an in-source build. +build_flags = '' +try: + if not python_build: + build_flags = sys.abiflags +except AttributeError: + # It's not a configure-based build, so the sys module doesn't have + # this attribute, which is fine. + pass + +def get_python_version(): + """Return a string containing the major and minor Python version, + leaving off the patchlevel. Sample return values could be '1.5' + or '2.2'. + """ + return '%d.%d' % sys.version_info[:2] + + +def get_python_inc(plat_specific=0, prefix=None): + """Return the directory containing installed Python header files. + + If 'plat_specific' is false (the default), this is the path to the + non-platform-specific header files, i.e. Python.h and so on; + otherwise, this is the path to platform-specific header files + (namely pyconfig.h). + + If 'prefix' is supplied, use it instead of sys.base_prefix or + sys.base_exec_prefix -- i.e., ignore 'plat_specific'. + """ + if prefix is None: + prefix = plat_specific and BASE_EXEC_PREFIX or BASE_PREFIX + if os.name == "posix": + if IS_PYPY and sys.version_info < (3, 8): + return os.path.join(prefix, 'include') + if python_build: + # Assume the executable is in the build directory. The + # pyconfig.h file should be in the same directory. Since + # the build directory may not be the source directory, we + # must use "srcdir" from the makefile to find the "Include" + # directory. + if plat_specific: + return _sys_home or project_base + else: + incdir = os.path.join(get_config_var('srcdir'), 'Include') + return os.path.normpath(incdir) + implementation = 'pypy' if IS_PYPY else 'python' + python_dir = implementation + get_python_version() + build_flags + return os.path.join(prefix, "include", python_dir) + elif os.name == "nt": + if python_build: + # Include both the include and PC dir to ensure we can find + # pyconfig.h + return (os.path.join(prefix, "include") + os.path.pathsep + + os.path.join(prefix, "PC")) + return os.path.join(prefix, "include") + else: + raise DistutilsPlatformError( + "I don't know where Python installs its C header files " + "on platform '%s'" % os.name) + + +# allow this behavior to be monkey-patched. Ref pypa/distutils#2. +def _posix_lib(standard_lib, libpython, early_prefix, prefix): + if standard_lib: + return libpython + else: + return os.path.join(libpython, "site-packages") + + +def get_python_lib(plat_specific=0, standard_lib=0, prefix=None): + """Return the directory containing the Python library (standard or + site additions). + + If 'plat_specific' is true, return the directory containing + platform-specific modules, i.e. any module from a non-pure-Python + module distribution; otherwise, return the platform-shared library + directory. If 'standard_lib' is true, return the directory + containing standard Python library modules; otherwise, return the + directory for site-specific modules. + + If 'prefix' is supplied, use it instead of sys.base_prefix or + sys.base_exec_prefix -- i.e., ignore 'plat_specific'. + """ + + if IS_PYPY and sys.version_info < (3, 8): + # PyPy-specific schema + if prefix is None: + prefix = PREFIX + if standard_lib: + return os.path.join(prefix, "lib-python", sys.version[0]) + return os.path.join(prefix, 'site-packages') + + early_prefix = prefix + + if prefix is None: + if standard_lib: + prefix = plat_specific and BASE_EXEC_PREFIX or BASE_PREFIX + else: + prefix = plat_specific and EXEC_PREFIX or PREFIX + + if os.name == "posix": + if plat_specific or standard_lib: + # Platform-specific modules (any module from a non-pure-Python + # module distribution) or standard Python library modules. + libdir = getattr(sys, "platlibdir", "lib") + else: + # Pure Python + libdir = "lib" + implementation = 'pypy' if IS_PYPY else 'python' + libpython = os.path.join(prefix, libdir, + implementation + get_python_version()) + return _posix_lib(standard_lib, libpython, early_prefix, prefix) + elif os.name == "nt": + if standard_lib: + return os.path.join(prefix, "Lib") + else: + return os.path.join(prefix, "Lib", "site-packages") + else: + raise DistutilsPlatformError( + "I don't know where Python installs its library " + "on platform '%s'" % os.name) + + + +def customize_compiler(compiler): + """Do any platform-specific customization of a CCompiler instance. + + Mainly needed on Unix, so we can plug in the information that + varies across Unices and is stored in Python's Makefile. + """ + if compiler.compiler_type == "unix": + if sys.platform == "darwin": + # Perform first-time customization of compiler-related + # config vars on OS X now that we know we need a compiler. + # This is primarily to support Pythons from binary + # installers. The kind and paths to build tools on + # the user system may vary significantly from the system + # that Python itself was built on. Also the user OS + # version and build tools may not support the same set + # of CPU architectures for universal builds. + global _config_vars + # Use get_config_var() to ensure _config_vars is initialized. + if not get_config_var('CUSTOMIZED_OSX_COMPILER'): + import _osx_support + _osx_support.customize_compiler(_config_vars) + _config_vars['CUSTOMIZED_OSX_COMPILER'] = 'True' + + (cc, cxx, cflags, ccshared, ldshared, shlib_suffix, ar, ar_flags) = \ + get_config_vars('CC', 'CXX', 'CFLAGS', + 'CCSHARED', 'LDSHARED', 'SHLIB_SUFFIX', 'AR', 'ARFLAGS') + + if 'CC' in os.environ: + newcc = os.environ['CC'] + if('LDSHARED' not in os.environ + and ldshared.startswith(cc)): + # If CC is overridden, use that as the default + # command for LDSHARED as well + ldshared = newcc + ldshared[len(cc):] + cc = newcc + if 'CXX' in os.environ: + cxx = os.environ['CXX'] + if 'LDSHARED' in os.environ: + ldshared = os.environ['LDSHARED'] + if 'CPP' in os.environ: + cpp = os.environ['CPP'] + else: + cpp = cc + " -E" # not always + if 'LDFLAGS' in os.environ: + ldshared = ldshared + ' ' + os.environ['LDFLAGS'] + if 'CFLAGS' in os.environ: + cflags = cflags + ' ' + os.environ['CFLAGS'] + ldshared = ldshared + ' ' + os.environ['CFLAGS'] + if 'CPPFLAGS' in os.environ: + cpp = cpp + ' ' + os.environ['CPPFLAGS'] + cflags = cflags + ' ' + os.environ['CPPFLAGS'] + ldshared = ldshared + ' ' + os.environ['CPPFLAGS'] + if 'AR' in os.environ: + ar = os.environ['AR'] + if 'ARFLAGS' in os.environ: + archiver = ar + ' ' + os.environ['ARFLAGS'] + else: + archiver = ar + ' ' + ar_flags + + cc_cmd = cc + ' ' + cflags + compiler.set_executables( + preprocessor=cpp, + compiler=cc_cmd, + compiler_so=cc_cmd + ' ' + ccshared, + compiler_cxx=cxx, + linker_so=ldshared, + linker_exe=cc, + archiver=archiver) + + if 'RANLIB' in os.environ and compiler.executables.get('ranlib', None): + compiler.set_executables(ranlib=os.environ['RANLIB']) + + compiler.shared_lib_extension = shlib_suffix + + +def get_config_h_filename(): + """Return full pathname of installed pyconfig.h file.""" + if python_build: + if os.name == "nt": + inc_dir = os.path.join(_sys_home or project_base, "PC") + else: + inc_dir = _sys_home or project_base + return os.path.join(inc_dir, 'pyconfig.h') + else: + return sysconfig.get_config_h_filename() + + + +def get_makefile_filename(): + """Return full pathname of installed Makefile from the Python build.""" + return sysconfig.get_makefile_filename() + + +def parse_config_h(fp, g=None): + """Parse a config.h-style file. + + A dictionary containing name/value pairs is returned. If an + optional dictionary is passed in as the second argument, it is + used instead of a new dictionary. + """ + return sysconfig.parse_config_h(fp, vars=g) + + +# Regexes needed for parsing Makefile (and similar syntaxes, +# like old-style Setup files). +_variable_rx = re.compile(r"([a-zA-Z][a-zA-Z0-9_]+)\s*=\s*(.*)") +_findvar1_rx = re.compile(r"\$\(([A-Za-z][A-Za-z0-9_]*)\)") +_findvar2_rx = re.compile(r"\${([A-Za-z][A-Za-z0-9_]*)}") + +def parse_makefile(fn, g=None): + """Parse a Makefile-style file. + + A dictionary containing name/value pairs is returned. If an + optional dictionary is passed in as the second argument, it is + used instead of a new dictionary. + """ + from distutils.text_file import TextFile + fp = TextFile(fn, strip_comments=1, skip_blanks=1, join_lines=1, errors="surrogateescape") + + if g is None: + g = {} + done = {} + notdone = {} + + while True: + line = fp.readline() + if line is None: # eof + break + m = _variable_rx.match(line) + if m: + n, v = m.group(1, 2) + v = v.strip() + # `$$' is a literal `$' in make + tmpv = v.replace('$$', '') + + if "$" in tmpv: + notdone[n] = v + else: + try: + v = int(v) + except ValueError: + # insert literal `$' + done[n] = v.replace('$$', '$') + else: + done[n] = v + + # Variables with a 'PY_' prefix in the makefile. These need to + # be made available without that prefix through sysconfig. + # Special care is needed to ensure that variable expansion works, even + # if the expansion uses the name without a prefix. + renamed_variables = ('CFLAGS', 'LDFLAGS', 'CPPFLAGS') + + # do variable interpolation here + while notdone: + for name in list(notdone): + value = notdone[name] + m = _findvar1_rx.search(value) or _findvar2_rx.search(value) + if m: + n = m.group(1) + found = True + if n in done: + item = str(done[n]) + elif n in notdone: + # get it on a subsequent round + found = False + elif n in os.environ: + # do it like make: fall back to environment + item = os.environ[n] + + elif n in renamed_variables: + if name.startswith('PY_') and name[3:] in renamed_variables: + item = "" + + elif 'PY_' + n in notdone: + found = False + + else: + item = str(done['PY_' + n]) + else: + done[n] = item = "" + if found: + after = value[m.end():] + value = value[:m.start()] + item + after + if "$" in after: + notdone[name] = value + else: + try: value = int(value) + except ValueError: + done[name] = value.strip() + else: + done[name] = value + del notdone[name] + + if name.startswith('PY_') \ + and name[3:] in renamed_variables: + + name = name[3:] + if name not in done: + done[name] = value + else: + # bogus variable reference; just drop it since we can't deal + del notdone[name] + + fp.close() + + # strip spurious spaces + for k, v in done.items(): + if isinstance(v, str): + done[k] = v.strip() + + # save the results in the global dictionary + g.update(done) + return g + + +def expand_makefile_vars(s, vars): + """Expand Makefile-style variables -- "${foo}" or "$(foo)" -- in + 'string' according to 'vars' (a dictionary mapping variable names to + values). Variables not present in 'vars' are silently expanded to the + empty string. The variable values in 'vars' should not contain further + variable expansions; if 'vars' is the output of 'parse_makefile()', + you're fine. Returns a variable-expanded version of 's'. + """ + + # This algorithm does multiple expansion, so if vars['foo'] contains + # "${bar}", it will expand ${foo} to ${bar}, and then expand + # ${bar}... and so forth. This is fine as long as 'vars' comes from + # 'parse_makefile()', which takes care of such expansions eagerly, + # according to make's variable expansion semantics. + + while True: + m = _findvar1_rx.search(s) or _findvar2_rx.search(s) + if m: + (beg, end) = m.span() + s = s[0:beg] + vars.get(m.group(1)) + s[end:] + else: + break + return s + + +_config_vars = None + + +_sysconfig_name_tmpl = '_sysconfigdata_{abi}_{platform}_{multiarch}' + + +def _init_posix(): + """Initialize the module as appropriate for POSIX systems.""" + # _sysconfigdata is generated at build time, see the sysconfig module + name = os.environ.get( + '_PYTHON_SYSCONFIGDATA_NAME', + _sysconfig_name_tmpl.format( + abi=sys.abiflags, + platform=sys.platform, + multiarch=getattr(sys.implementation, '_multiarch', ''), + ), + ) + try: + _temp = __import__(name, globals(), locals(), ['build_time_vars'], 0) + except ImportError: + # Python 3.5 and pypy 7.3.1 + _temp = __import__( + '_sysconfigdata', globals(), locals(), ['build_time_vars'], 0) + build_time_vars = _temp.build_time_vars + global _config_vars + _config_vars = {} + _config_vars.update(build_time_vars) + + +def _init_nt(): + """Initialize the module as appropriate for NT""" + g = {} + # set basic install directories + g['LIBDEST'] = get_python_lib(plat_specific=0, standard_lib=1) + g['BINLIBDEST'] = get_python_lib(plat_specific=1, standard_lib=1) + + # XXX hmmm.. a normal install puts include files here + g['INCLUDEPY'] = get_python_inc(plat_specific=0) + + g['EXT_SUFFIX'] = _imp.extension_suffixes()[0] + g['EXE'] = ".exe" + g['VERSION'] = get_python_version().replace(".", "") + g['BINDIR'] = os.path.dirname(os.path.abspath(sys.executable)) + + global _config_vars + _config_vars = g + + +def get_config_vars(*args): + """With no arguments, return a dictionary of all configuration + variables relevant for the current platform. Generally this includes + everything needed to build extensions and install both pure modules and + extensions. On Unix, this means every variable defined in Python's + installed Makefile; on Windows it's a much smaller set. + + With arguments, return a list of values that result from looking up + each argument in the configuration variable dictionary. + """ + global _config_vars + if _config_vars is None: + func = globals().get("_init_" + os.name) + if func: + func() + else: + _config_vars = {} + + # Normalized versions of prefix and exec_prefix are handy to have; + # in fact, these are the standard versions used most places in the + # Distutils. + _config_vars['prefix'] = PREFIX + _config_vars['exec_prefix'] = EXEC_PREFIX + + if not IS_PYPY: + # For backward compatibility, see issue19555 + SO = _config_vars.get('EXT_SUFFIX') + if SO is not None: + _config_vars['SO'] = SO + + # Always convert srcdir to an absolute path + srcdir = _config_vars.get('srcdir', project_base) + if os.name == 'posix': + if python_build: + # If srcdir is a relative path (typically '.' or '..') + # then it should be interpreted relative to the directory + # containing Makefile. + base = os.path.dirname(get_makefile_filename()) + srcdir = os.path.join(base, srcdir) + else: + # srcdir is not meaningful since the installation is + # spread about the filesystem. We choose the + # directory containing the Makefile since we know it + # exists. + srcdir = os.path.dirname(get_makefile_filename()) + _config_vars['srcdir'] = os.path.abspath(os.path.normpath(srcdir)) + + # Convert srcdir into an absolute path if it appears necessary. + # Normally it is relative to the build directory. However, during + # testing, for example, we might be running a non-installed python + # from a different directory. + if python_build and os.name == "posix": + base = project_base + if (not os.path.isabs(_config_vars['srcdir']) and + base != os.getcwd()): + # srcdir is relative and we are not in the same directory + # as the executable. Assume executable is in the build + # directory and make srcdir absolute. + srcdir = os.path.join(base, _config_vars['srcdir']) + _config_vars['srcdir'] = os.path.normpath(srcdir) + + # OS X platforms require special customization to handle + # multi-architecture, multi-os-version installers + if sys.platform == 'darwin': + import _osx_support + _osx_support.customize_config_vars(_config_vars) + + if args: + vals = [] + for name in args: + vals.append(_config_vars.get(name)) + return vals + else: + return _config_vars + +def get_config_var(name): + """Return the value of a single variable using the dictionary + returned by 'get_config_vars()'. Equivalent to + get_config_vars().get(name) + """ + if name == 'SO': + import warnings + warnings.warn('SO is deprecated, use EXT_SUFFIX', DeprecationWarning, 2) + return get_config_vars().get(name) diff --git a/venv/Lib/site-packages/setuptools/_distutils/text_file.py b/venv/Lib/site-packages/setuptools/_distutils/text_file.py new file mode 100644 index 0000000..93abad3 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_distutils/text_file.py @@ -0,0 +1,286 @@ +"""text_file + +provides the TextFile class, which gives an interface to text files +that (optionally) takes care of stripping comments, ignoring blank +lines, and joining lines with backslashes.""" + +import sys, io + + +class TextFile: + """Provides a file-like object that takes care of all the things you + commonly want to do when processing a text file that has some + line-by-line syntax: strip comments (as long as "#" is your + comment character), skip blank lines, join adjacent lines by + escaping the newline (ie. backslash at end of line), strip + leading and/or trailing whitespace. All of these are optional + and independently controllable. + + Provides a 'warn()' method so you can generate warning messages that + report physical line number, even if the logical line in question + spans multiple physical lines. Also provides 'unreadline()' for + implementing line-at-a-time lookahead. + + Constructor is called as: + + TextFile (filename=None, file=None, **options) + + It bombs (RuntimeError) if both 'filename' and 'file' are None; + 'filename' should be a string, and 'file' a file object (or + something that provides 'readline()' and 'close()' methods). It is + recommended that you supply at least 'filename', so that TextFile + can include it in warning messages. If 'file' is not supplied, + TextFile creates its own using 'io.open()'. + + The options are all boolean, and affect the value returned by + 'readline()': + strip_comments [default: true] + strip from "#" to end-of-line, as well as any whitespace + leading up to the "#" -- unless it is escaped by a backslash + lstrip_ws [default: false] + strip leading whitespace from each line before returning it + rstrip_ws [default: true] + strip trailing whitespace (including line terminator!) from + each line before returning it + skip_blanks [default: true} + skip lines that are empty *after* stripping comments and + whitespace. (If both lstrip_ws and rstrip_ws are false, + then some lines may consist of solely whitespace: these will + *not* be skipped, even if 'skip_blanks' is true.) + join_lines [default: false] + if a backslash is the last non-newline character on a line + after stripping comments and whitespace, join the following line + to it to form one "logical line"; if N consecutive lines end + with a backslash, then N+1 physical lines will be joined to + form one logical line. + collapse_join [default: false] + strip leading whitespace from lines that are joined to their + predecessor; only matters if (join_lines and not lstrip_ws) + errors [default: 'strict'] + error handler used to decode the file content + + Note that since 'rstrip_ws' can strip the trailing newline, the + semantics of 'readline()' must differ from those of the builtin file + object's 'readline()' method! In particular, 'readline()' returns + None for end-of-file: an empty string might just be a blank line (or + an all-whitespace line), if 'rstrip_ws' is true but 'skip_blanks' is + not.""" + + default_options = { 'strip_comments': 1, + 'skip_blanks': 1, + 'lstrip_ws': 0, + 'rstrip_ws': 1, + 'join_lines': 0, + 'collapse_join': 0, + 'errors': 'strict', + } + + def __init__(self, filename=None, file=None, **options): + """Construct a new TextFile object. At least one of 'filename' + (a string) and 'file' (a file-like object) must be supplied. + They keyword argument options are described above and affect + the values returned by 'readline()'.""" + if filename is None and file is None: + raise RuntimeError("you must supply either or both of 'filename' and 'file'") + + # set values for all options -- either from client option hash + # or fallback to default_options + for opt in self.default_options.keys(): + if opt in options: + setattr(self, opt, options[opt]) + else: + setattr(self, opt, self.default_options[opt]) + + # sanity check client option hash + for opt in options.keys(): + if opt not in self.default_options: + raise KeyError("invalid TextFile option '%s'" % opt) + + if file is None: + self.open(filename) + else: + self.filename = filename + self.file = file + self.current_line = 0 # assuming that file is at BOF! + + # 'linebuf' is a stack of lines that will be emptied before we + # actually read from the file; it's only populated by an + # 'unreadline()' operation + self.linebuf = [] + + def open(self, filename): + """Open a new file named 'filename'. This overrides both the + 'filename' and 'file' arguments to the constructor.""" + self.filename = filename + self.file = io.open(self.filename, 'r', errors=self.errors) + self.current_line = 0 + + def close(self): + """Close the current file and forget everything we know about it + (filename, current line number).""" + file = self.file + self.file = None + self.filename = None + self.current_line = None + file.close() + + def gen_error(self, msg, line=None): + outmsg = [] + if line is None: + line = self.current_line + outmsg.append(self.filename + ", ") + if isinstance(line, (list, tuple)): + outmsg.append("lines %d-%d: " % tuple(line)) + else: + outmsg.append("line %d: " % line) + outmsg.append(str(msg)) + return "".join(outmsg) + + def error(self, msg, line=None): + raise ValueError("error: " + self.gen_error(msg, line)) + + def warn(self, msg, line=None): + """Print (to stderr) a warning message tied to the current logical + line in the current file. If the current logical line in the + file spans multiple physical lines, the warning refers to the + whole range, eg. "lines 3-5". If 'line' supplied, it overrides + the current line number; it may be a list or tuple to indicate a + range of physical lines, or an integer for a single physical + line.""" + sys.stderr.write("warning: " + self.gen_error(msg, line) + "\n") + + def readline(self): + """Read and return a single logical line from the current file (or + from an internal buffer if lines have previously been "unread" + with 'unreadline()'). If the 'join_lines' option is true, this + may involve reading multiple physical lines concatenated into a + single string. Updates the current line number, so calling + 'warn()' after 'readline()' emits a warning about the physical + line(s) just read. Returns None on end-of-file, since the empty + string can occur if 'rstrip_ws' is true but 'strip_blanks' is + not.""" + # If any "unread" lines waiting in 'linebuf', return the top + # one. (We don't actually buffer read-ahead data -- lines only + # get put in 'linebuf' if the client explicitly does an + # 'unreadline()'. + if self.linebuf: + line = self.linebuf[-1] + del self.linebuf[-1] + return line + + buildup_line = '' + + while True: + # read the line, make it None if EOF + line = self.file.readline() + if line == '': + line = None + + if self.strip_comments and line: + + # Look for the first "#" in the line. If none, never + # mind. If we find one and it's the first character, or + # is not preceded by "\", then it starts a comment -- + # strip the comment, strip whitespace before it, and + # carry on. Otherwise, it's just an escaped "#", so + # unescape it (and any other escaped "#"'s that might be + # lurking in there) and otherwise leave the line alone. + + pos = line.find("#") + if pos == -1: # no "#" -- no comments + pass + + # It's definitely a comment -- either "#" is the first + # character, or it's elsewhere and unescaped. + elif pos == 0 or line[pos-1] != "\\": + # Have to preserve the trailing newline, because it's + # the job of a later step (rstrip_ws) to remove it -- + # and if rstrip_ws is false, we'd better preserve it! + # (NB. this means that if the final line is all comment + # and has no trailing newline, we will think that it's + # EOF; I think that's OK.) + eol = (line[-1] == '\n') and '\n' or '' + line = line[0:pos] + eol + + # If all that's left is whitespace, then skip line + # *now*, before we try to join it to 'buildup_line' -- + # that way constructs like + # hello \\ + # # comment that should be ignored + # there + # result in "hello there". + if line.strip() == "": + continue + else: # it's an escaped "#" + line = line.replace("\\#", "#") + + # did previous line end with a backslash? then accumulate + if self.join_lines and buildup_line: + # oops: end of file + if line is None: + self.warn("continuation line immediately precedes " + "end-of-file") + return buildup_line + + if self.collapse_join: + line = line.lstrip() + line = buildup_line + line + + # careful: pay attention to line number when incrementing it + if isinstance(self.current_line, list): + self.current_line[1] = self.current_line[1] + 1 + else: + self.current_line = [self.current_line, + self.current_line + 1] + # just an ordinary line, read it as usual + else: + if line is None: # eof + return None + + # still have to be careful about incrementing the line number! + if isinstance(self.current_line, list): + self.current_line = self.current_line[1] + 1 + else: + self.current_line = self.current_line + 1 + + # strip whitespace however the client wants (leading and + # trailing, or one or the other, or neither) + if self.lstrip_ws and self.rstrip_ws: + line = line.strip() + elif self.lstrip_ws: + line = line.lstrip() + elif self.rstrip_ws: + line = line.rstrip() + + # blank line (whether we rstrip'ed or not)? skip to next line + # if appropriate + if (line == '' or line == '\n') and self.skip_blanks: + continue + + if self.join_lines: + if line[-1] == '\\': + buildup_line = line[:-1] + continue + + if line[-2:] == '\\\n': + buildup_line = line[0:-2] + '\n' + continue + + # well, I guess there's some actual content there: return it + return line + + def readlines(self): + """Read and return the list of all logical lines remaining in the + current file.""" + lines = [] + while True: + line = self.readline() + if line is None: + return lines + lines.append(line) + + def unreadline(self, line): + """Push 'line' (a string) onto an internal buffer that will be + checked by future 'readline()' calls. Handy for implementing + a parser with line-at-a-time lookahead.""" + self.linebuf.append(line) diff --git a/venv/Lib/site-packages/setuptools/_distutils/unixccompiler.py b/venv/Lib/site-packages/setuptools/_distutils/unixccompiler.py new file mode 100644 index 0000000..a07e598 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_distutils/unixccompiler.py @@ -0,0 +1,325 @@ +"""distutils.unixccompiler + +Contains the UnixCCompiler class, a subclass of CCompiler that handles +the "typical" Unix-style command-line C compiler: + * macros defined with -Dname[=value] + * macros undefined with -Uname + * include search directories specified with -Idir + * libraries specified with -lllib + * library search directories specified with -Ldir + * compile handled by 'cc' (or similar) executable with -c option: + compiles .c to .o + * link static library handled by 'ar' command (possibly with 'ranlib') + * link shared library handled by 'cc -shared' +""" + +import os, sys, re, shlex + +from distutils import sysconfig +from distutils.dep_util import newer +from distutils.ccompiler import \ + CCompiler, gen_preprocess_options, gen_lib_options +from distutils.errors import \ + DistutilsExecError, CompileError, LibError, LinkError +from distutils import log + +if sys.platform == 'darwin': + import _osx_support + +# XXX Things not currently handled: +# * optimization/debug/warning flags; we just use whatever's in Python's +# Makefile and live with it. Is this adequate? If not, we might +# have to have a bunch of subclasses GNUCCompiler, SGICCompiler, +# SunCCompiler, and I suspect down that road lies madness. +# * even if we don't know a warning flag from an optimization flag, +# we need some way for outsiders to feed preprocessor/compiler/linker +# flags in to us -- eg. a sysadmin might want to mandate certain flags +# via a site config file, or a user might want to set something for +# compiling this module distribution only via the setup.py command +# line, whatever. As long as these options come from something on the +# current system, they can be as system-dependent as they like, and we +# should just happily stuff them into the preprocessor/compiler/linker +# options and carry on. + + +class UnixCCompiler(CCompiler): + + compiler_type = 'unix' + + # These are used by CCompiler in two places: the constructor sets + # instance attributes 'preprocessor', 'compiler', etc. from them, and + # 'set_executable()' allows any of these to be set. The defaults here + # are pretty generic; they will probably have to be set by an outsider + # (eg. using information discovered by the sysconfig about building + # Python extensions). + executables = {'preprocessor' : None, + 'compiler' : ["cc"], + 'compiler_so' : ["cc"], + 'compiler_cxx' : ["cc"], + 'linker_so' : ["cc", "-shared"], + 'linker_exe' : ["cc"], + 'archiver' : ["ar", "-cr"], + 'ranlib' : None, + } + + if sys.platform[:6] == "darwin": + executables['ranlib'] = ["ranlib"] + + # Needed for the filename generation methods provided by the base + # class, CCompiler. NB. whoever instantiates/uses a particular + # UnixCCompiler instance should set 'shared_lib_ext' -- we set a + # reasonable common default here, but it's not necessarily used on all + # Unices! + + src_extensions = [".c",".C",".cc",".cxx",".cpp",".m"] + obj_extension = ".o" + static_lib_extension = ".a" + shared_lib_extension = ".so" + dylib_lib_extension = ".dylib" + xcode_stub_lib_extension = ".tbd" + static_lib_format = shared_lib_format = dylib_lib_format = "lib%s%s" + xcode_stub_lib_format = dylib_lib_format + if sys.platform == "cygwin": + exe_extension = ".exe" + + def preprocess(self, source, output_file=None, macros=None, + include_dirs=None, extra_preargs=None, extra_postargs=None): + fixed_args = self._fix_compile_args(None, macros, include_dirs) + ignore, macros, include_dirs = fixed_args + pp_opts = gen_preprocess_options(macros, include_dirs) + pp_args = self.preprocessor + pp_opts + if output_file: + pp_args.extend(['-o', output_file]) + if extra_preargs: + pp_args[:0] = extra_preargs + if extra_postargs: + pp_args.extend(extra_postargs) + pp_args.append(source) + + # We need to preprocess: either we're being forced to, or we're + # generating output to stdout, or there's a target output file and + # the source file is newer than the target (or the target doesn't + # exist). + if self.force or output_file is None or newer(source, output_file): + if output_file: + self.mkpath(os.path.dirname(output_file)) + try: + self.spawn(pp_args) + except DistutilsExecError as msg: + raise CompileError(msg) + + def _compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts): + compiler_so = self.compiler_so + if sys.platform == 'darwin': + compiler_so = _osx_support.compiler_fixup(compiler_so, + cc_args + extra_postargs) + try: + self.spawn(compiler_so + cc_args + [src, '-o', obj] + + extra_postargs) + except DistutilsExecError as msg: + raise CompileError(msg) + + def create_static_lib(self, objects, output_libname, + output_dir=None, debug=0, target_lang=None): + objects, output_dir = self._fix_object_args(objects, output_dir) + + output_filename = \ + self.library_filename(output_libname, output_dir=output_dir) + + if self._need_link(objects, output_filename): + self.mkpath(os.path.dirname(output_filename)) + self.spawn(self.archiver + + [output_filename] + + objects + self.objects) + + # Not many Unices required ranlib anymore -- SunOS 4.x is, I + # think the only major Unix that does. Maybe we need some + # platform intelligence here to skip ranlib if it's not + # needed -- or maybe Python's configure script took care of + # it for us, hence the check for leading colon. + if self.ranlib: + try: + self.spawn(self.ranlib + [output_filename]) + except DistutilsExecError as msg: + raise LibError(msg) + else: + log.debug("skipping %s (up-to-date)", output_filename) + + def link(self, target_desc, objects, + output_filename, output_dir=None, libraries=None, + library_dirs=None, runtime_library_dirs=None, + export_symbols=None, debug=0, extra_preargs=None, + extra_postargs=None, build_temp=None, target_lang=None): + objects, output_dir = self._fix_object_args(objects, output_dir) + fixed_args = self._fix_lib_args(libraries, library_dirs, + runtime_library_dirs) + libraries, library_dirs, runtime_library_dirs = fixed_args + + lib_opts = gen_lib_options(self, library_dirs, runtime_library_dirs, + libraries) + if not isinstance(output_dir, (str, type(None))): + raise TypeError("'output_dir' must be a string or None") + if output_dir is not None: + output_filename = os.path.join(output_dir, output_filename) + + if self._need_link(objects, output_filename): + ld_args = (objects + self.objects + + lib_opts + ['-o', output_filename]) + if debug: + ld_args[:0] = ['-g'] + if extra_preargs: + ld_args[:0] = extra_preargs + if extra_postargs: + ld_args.extend(extra_postargs) + self.mkpath(os.path.dirname(output_filename)) + try: + if target_desc == CCompiler.EXECUTABLE: + linker = self.linker_exe[:] + else: + linker = self.linker_so[:] + if target_lang == "c++" and self.compiler_cxx: + # skip over environment variable settings if /usr/bin/env + # is used to set up the linker's environment. + # This is needed on OSX. Note: this assumes that the + # normal and C++ compiler have the same environment + # settings. + i = 0 + if os.path.basename(linker[0]) == "env": + i = 1 + while '=' in linker[i]: + i += 1 + + if os.path.basename(linker[i]) == 'ld_so_aix': + # AIX platforms prefix the compiler with the ld_so_aix + # script, so we need to adjust our linker index + offset = 1 + else: + offset = 0 + + linker[i+offset] = self.compiler_cxx[i] + + if sys.platform == 'darwin': + linker = _osx_support.compiler_fixup(linker, ld_args) + + self.spawn(linker + ld_args) + except DistutilsExecError as msg: + raise LinkError(msg) + else: + log.debug("skipping %s (up-to-date)", output_filename) + + # -- Miscellaneous methods ----------------------------------------- + # These are all used by the 'gen_lib_options() function, in + # ccompiler.py. + + def library_dir_option(self, dir): + return "-L" + dir + + def _is_gcc(self, compiler_name): + return "gcc" in compiler_name or "g++" in compiler_name + + def runtime_library_dir_option(self, dir): + # XXX Hackish, at the very least. See Python bug #445902: + # http://sourceforge.net/tracker/index.php + # ?func=detail&aid=445902&group_id=5470&atid=105470 + # Linkers on different platforms need different options to + # specify that directories need to be added to the list of + # directories searched for dependencies when a dynamic library + # is sought. GCC on GNU systems (Linux, FreeBSD, ...) has to + # be told to pass the -R option through to the linker, whereas + # other compilers and gcc on other systems just know this. + # Other compilers may need something slightly different. At + # this time, there's no way to determine this information from + # the configuration data stored in the Python installation, so + # we use this hack. + compiler = os.path.basename(shlex.split(sysconfig.get_config_var("CC"))[0]) + if sys.platform[:6] == "darwin": + from distutils.util import get_macosx_target_ver, split_version + macosx_target_ver = get_macosx_target_ver() + if macosx_target_ver and split_version(macosx_target_ver) >= [10, 5]: + return "-Wl,-rpath," + dir + else: # no support for -rpath on earlier macOS versions + return "-L" + dir + elif sys.platform[:7] == "freebsd": + return "-Wl,-rpath=" + dir + elif sys.platform[:5] == "hp-ux": + if self._is_gcc(compiler): + return ["-Wl,+s", "-L" + dir] + return ["+s", "-L" + dir] + + # For all compilers, `-Wl` is the presumed way to + # pass a compiler option to the linker and `-R` is + # the way to pass an RPATH. + if sysconfig.get_config_var("GNULD") == "yes": + # GNU ld needs an extra option to get a RUNPATH + # instead of just an RPATH. + return "-Wl,--enable-new-dtags,-R" + dir + else: + return "-Wl,-R" + dir + + def library_option(self, lib): + return "-l" + lib + + def find_library_file(self, dirs, lib, debug=0): + shared_f = self.library_filename(lib, lib_type='shared') + dylib_f = self.library_filename(lib, lib_type='dylib') + xcode_stub_f = self.library_filename(lib, lib_type='xcode_stub') + static_f = self.library_filename(lib, lib_type='static') + + if sys.platform == 'darwin': + # On OSX users can specify an alternate SDK using + # '-isysroot', calculate the SDK root if it is specified + # (and use it further on) + # + # Note that, as of Xcode 7, Apple SDKs may contain textual stub + # libraries with .tbd extensions rather than the normal .dylib + # shared libraries installed in /. The Apple compiler tool + # chain handles this transparently but it can cause problems + # for programs that are being built with an SDK and searching + # for specific libraries. Callers of find_library_file need to + # keep in mind that the base filename of the returned SDK library + # file might have a different extension from that of the library + # file installed on the running system, for example: + # /Applications/Xcode.app/Contents/Developer/Platforms/ + # MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/ + # usr/lib/libedit.tbd + # vs + # /usr/lib/libedit.dylib + cflags = sysconfig.get_config_var('CFLAGS') + m = re.search(r'-isysroot\s*(\S+)', cflags) + if m is None: + sysroot = '/' + else: + sysroot = m.group(1) + + + + for dir in dirs: + shared = os.path.join(dir, shared_f) + dylib = os.path.join(dir, dylib_f) + static = os.path.join(dir, static_f) + xcode_stub = os.path.join(dir, xcode_stub_f) + + if sys.platform == 'darwin' and ( + dir.startswith('/System/') or ( + dir.startswith('/usr/') and not dir.startswith('/usr/local/'))): + + shared = os.path.join(sysroot, dir[1:], shared_f) + dylib = os.path.join(sysroot, dir[1:], dylib_f) + static = os.path.join(sysroot, dir[1:], static_f) + xcode_stub = os.path.join(sysroot, dir[1:], xcode_stub_f) + + # We're second-guessing the linker here, with not much hard + # data to go on: GCC seems to prefer the shared library, so I'm + # assuming that *all* Unix C compilers do. And of course I'm + # ignoring even GCC's "-static" option. So sue me. + if os.path.exists(dylib): + return dylib + elif os.path.exists(xcode_stub): + return xcode_stub + elif os.path.exists(shared): + return shared + elif os.path.exists(static): + return static + + # Oops, didn't find it in *any* of 'dirs' + return None diff --git a/venv/Lib/site-packages/setuptools/_distutils/util.py b/venv/Lib/site-packages/setuptools/_distutils/util.py new file mode 100644 index 0000000..6d506d7 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_distutils/util.py @@ -0,0 +1,496 @@ +"""distutils.util + +Miscellaneous utility functions -- anything that doesn't fit into +one of the other *util.py modules. +""" + +import os +import re +import importlib.util +import string +import sys +import sysconfig +from distutils.errors import DistutilsPlatformError +from distutils.dep_util import newer +from distutils.spawn import spawn +from distutils import log +from distutils.errors import DistutilsByteCompileError +from .py35compat import _optim_args_from_interpreter_flags + + +def get_host_platform(): + """Return a string that identifies the current platform. This is used mainly to + distinguish platform-specific build directories and platform-specific built + distributions. + """ + + # We initially exposed platforms as defined in Python 3.9 + # even with older Python versions when distutils was split out. + # Now that we delegate to stdlib sysconfig we need to restore this + # in case anyone has started to depend on it. + + if sys.version_info < (3, 8): + if os.name == 'nt': + if '(arm)' in sys.version.lower(): + return 'win-arm32' + if '(arm64)' in sys.version.lower(): + return 'win-arm64' + + if sys.version_info < (3, 9): + if os.name == "posix" and hasattr(os, 'uname'): + osname, host, release, version, machine = os.uname() + if osname[:3] == "aix": + from .py38compat import aix_platform + return aix_platform(osname, version, release) + + return sysconfig.get_platform() + +def get_platform(): + if os.name == 'nt': + TARGET_TO_PLAT = { + 'x86' : 'win32', + 'x64' : 'win-amd64', + 'arm' : 'win-arm32', + 'arm64': 'win-arm64', + } + return TARGET_TO_PLAT.get(os.environ.get('VSCMD_ARG_TGT_ARCH')) or get_host_platform() + else: + return get_host_platform() + + +if sys.platform == 'darwin': + _syscfg_macosx_ver = None # cache the version pulled from sysconfig +MACOSX_VERSION_VAR = 'MACOSX_DEPLOYMENT_TARGET' + +def _clear_cached_macosx_ver(): + """For testing only. Do not call.""" + global _syscfg_macosx_ver + _syscfg_macosx_ver = None + +def get_macosx_target_ver_from_syscfg(): + """Get the version of macOS latched in the Python interpreter configuration. + Returns the version as a string or None if can't obtain one. Cached.""" + global _syscfg_macosx_ver + if _syscfg_macosx_ver is None: + from distutils import sysconfig + ver = sysconfig.get_config_var(MACOSX_VERSION_VAR) or '' + if ver: + _syscfg_macosx_ver = ver + return _syscfg_macosx_ver + +def get_macosx_target_ver(): + """Return the version of macOS for which we are building. + + The target version defaults to the version in sysconfig latched at time + the Python interpreter was built, unless overridden by an environment + variable. If neither source has a value, then None is returned""" + + syscfg_ver = get_macosx_target_ver_from_syscfg() + env_ver = os.environ.get(MACOSX_VERSION_VAR) + + if env_ver: + # Validate overridden version against sysconfig version, if have both. + # Ensure that the deployment target of the build process is not less + # than 10.3 if the interpreter was built for 10.3 or later. This + # ensures extension modules are built with correct compatibility + # values, specifically LDSHARED which can use + # '-undefined dynamic_lookup' which only works on >= 10.3. + if syscfg_ver and split_version(syscfg_ver) >= [10, 3] and \ + split_version(env_ver) < [10, 3]: + my_msg = ('$' + MACOSX_VERSION_VAR + ' mismatch: ' + 'now "%s" but "%s" during configure; ' + 'must use 10.3 or later' + % (env_ver, syscfg_ver)) + raise DistutilsPlatformError(my_msg) + return env_ver + return syscfg_ver + + +def split_version(s): + """Convert a dot-separated string into a list of numbers for comparisons""" + return [int(n) for n in s.split('.')] + + +def convert_path (pathname): + """Return 'pathname' as a name that will work on the native filesystem, + i.e. split it on '/' and put it back together again using the current + directory separator. Needed because filenames in the setup script are + always supplied in Unix style, and have to be converted to the local + convention before we can actually use them in the filesystem. Raises + ValueError on non-Unix-ish systems if 'pathname' either starts or + ends with a slash. + """ + if os.sep == '/': + return pathname + if not pathname: + return pathname + if pathname[0] == '/': + raise ValueError("path '%s' cannot be absolute" % pathname) + if pathname[-1] == '/': + raise ValueError("path '%s' cannot end with '/'" % pathname) + + paths = pathname.split('/') + while '.' in paths: + paths.remove('.') + if not paths: + return os.curdir + return os.path.join(*paths) + +# convert_path () + + +def change_root (new_root, pathname): + """Return 'pathname' with 'new_root' prepended. If 'pathname' is + relative, this is equivalent to "os.path.join(new_root,pathname)". + Otherwise, it requires making 'pathname' relative and then joining the + two, which is tricky on DOS/Windows and Mac OS. + """ + if os.name == 'posix': + if not os.path.isabs(pathname): + return os.path.join(new_root, pathname) + else: + return os.path.join(new_root, pathname[1:]) + + elif os.name == 'nt': + (drive, path) = os.path.splitdrive(pathname) + if path[0] == '\\': + path = path[1:] + return os.path.join(new_root, path) + + else: + raise DistutilsPlatformError("nothing known about platform '%s'" % os.name) + + +_environ_checked = 0 +def check_environ (): + """Ensure that 'os.environ' has all the environment variables we + guarantee that users can use in config files, command-line options, + etc. Currently this includes: + HOME - user's home directory (Unix only) + PLAT - description of the current platform, including hardware + and OS (see 'get_platform()') + """ + global _environ_checked + if _environ_checked: + return + + if os.name == 'posix' and 'HOME' not in os.environ: + try: + import pwd + os.environ['HOME'] = pwd.getpwuid(os.getuid())[5] + except (ImportError, KeyError): + # bpo-10496: if the current user identifier doesn't exist in the + # password database, do nothing + pass + + if 'PLAT' not in os.environ: + os.environ['PLAT'] = get_platform() + + _environ_checked = 1 + + +def subst_vars (s, local_vars): + """ + Perform variable substitution on 'string'. + Variables are indicated by format-style braces ("{var}"). + Variable is substituted by the value found in the 'local_vars' + dictionary or in 'os.environ' if it's not in 'local_vars'. + 'os.environ' is first checked/augmented to guarantee that it contains + certain values: see 'check_environ()'. Raise ValueError for any + variables not found in either 'local_vars' or 'os.environ'. + """ + check_environ() + lookup = dict(os.environ) + lookup.update((name, str(value)) for name, value in local_vars.items()) + try: + return _subst_compat(s).format_map(lookup) + except KeyError as var: + raise ValueError(f"invalid variable {var}") + +# subst_vars () + + +def _subst_compat(s): + """ + Replace shell/Perl-style variable substitution with + format-style. For compatibility. + """ + def _subst(match): + return f'{{{match.group(1)}}}' + repl = re.sub(r'\$([a-zA-Z_][a-zA-Z_0-9]*)', _subst, s) + if repl != s: + import warnings + warnings.warn( + "shell/Perl-style substitions are deprecated", + DeprecationWarning, + ) + return repl + + +def grok_environment_error (exc, prefix="error: "): + # Function kept for backward compatibility. + # Used to try clever things with EnvironmentErrors, + # but nowadays str(exception) produces good messages. + return prefix + str(exc) + + +# Needed by 'split_quoted()' +_wordchars_re = _squote_re = _dquote_re = None +def _init_regex(): + global _wordchars_re, _squote_re, _dquote_re + _wordchars_re = re.compile(r'[^\\\'\"%s ]*' % string.whitespace) + _squote_re = re.compile(r"'(?:[^'\\]|\\.)*'") + _dquote_re = re.compile(r'"(?:[^"\\]|\\.)*"') + +def split_quoted (s): + """Split a string up according to Unix shell-like rules for quotes and + backslashes. In short: words are delimited by spaces, as long as those + spaces are not escaped by a backslash, or inside a quoted string. + Single and double quotes are equivalent, and the quote characters can + be backslash-escaped. The backslash is stripped from any two-character + escape sequence, leaving only the escaped character. The quote + characters are stripped from any quoted string. Returns a list of + words. + """ + + # This is a nice algorithm for splitting up a single string, since it + # doesn't require character-by-character examination. It was a little + # bit of a brain-bender to get it working right, though... + if _wordchars_re is None: _init_regex() + + s = s.strip() + words = [] + pos = 0 + + while s: + m = _wordchars_re.match(s, pos) + end = m.end() + if end == len(s): + words.append(s[:end]) + break + + if s[end] in string.whitespace: # unescaped, unquoted whitespace: now + words.append(s[:end]) # we definitely have a word delimiter + s = s[end:].lstrip() + pos = 0 + + elif s[end] == '\\': # preserve whatever is being escaped; + # will become part of the current word + s = s[:end] + s[end+1:] + pos = end+1 + + else: + if s[end] == "'": # slurp singly-quoted string + m = _squote_re.match(s, end) + elif s[end] == '"': # slurp doubly-quoted string + m = _dquote_re.match(s, end) + else: + raise RuntimeError("this can't happen (bad char '%c')" % s[end]) + + if m is None: + raise ValueError("bad string (mismatched %s quotes?)" % s[end]) + + (beg, end) = m.span() + s = s[:beg] + s[beg+1:end-1] + s[end:] + pos = m.end() - 2 + + if pos >= len(s): + words.append(s) + break + + return words + +# split_quoted () + + +def execute (func, args, msg=None, verbose=0, dry_run=0): + """Perform some action that affects the outside world (eg. by + writing to the filesystem). Such actions are special because they + are disabled by the 'dry_run' flag. This method takes care of all + that bureaucracy for you; all you have to do is supply the + function to call and an argument tuple for it (to embody the + "external action" being performed), and an optional message to + print. + """ + if msg is None: + msg = "%s%r" % (func.__name__, args) + if msg[-2:] == ',)': # correct for singleton tuple + msg = msg[0:-2] + ')' + + log.info(msg) + if not dry_run: + func(*args) + + +def strtobool (val): + """Convert a string representation of truth to true (1) or false (0). + + True values are 'y', 'yes', 't', 'true', 'on', and '1'; false values + are 'n', 'no', 'f', 'false', 'off', and '0'. Raises ValueError if + 'val' is anything else. + """ + val = val.lower() + if val in ('y', 'yes', 't', 'true', 'on', '1'): + return 1 + elif val in ('n', 'no', 'f', 'false', 'off', '0'): + return 0 + else: + raise ValueError("invalid truth value %r" % (val,)) + + +def byte_compile (py_files, + optimize=0, force=0, + prefix=None, base_dir=None, + verbose=1, dry_run=0, + direct=None): + """Byte-compile a collection of Python source files to .pyc + files in a __pycache__ subdirectory. 'py_files' is a list + of files to compile; any files that don't end in ".py" are silently + skipped. 'optimize' must be one of the following: + 0 - don't optimize + 1 - normal optimization (like "python -O") + 2 - extra optimization (like "python -OO") + If 'force' is true, all files are recompiled regardless of + timestamps. + + The source filename encoded in each bytecode file defaults to the + filenames listed in 'py_files'; you can modify these with 'prefix' and + 'basedir'. 'prefix' is a string that will be stripped off of each + source filename, and 'base_dir' is a directory name that will be + prepended (after 'prefix' is stripped). You can supply either or both + (or neither) of 'prefix' and 'base_dir', as you wish. + + If 'dry_run' is true, doesn't actually do anything that would + affect the filesystem. + + Byte-compilation is either done directly in this interpreter process + with the standard py_compile module, or indirectly by writing a + temporary script and executing it. Normally, you should let + 'byte_compile()' figure out to use direct compilation or not (see + the source for details). The 'direct' flag is used by the script + generated in indirect mode; unless you know what you're doing, leave + it set to None. + """ + + # Late import to fix a bootstrap issue: _posixsubprocess is built by + # setup.py, but setup.py uses distutils. + import subprocess + + # nothing is done if sys.dont_write_bytecode is True + if sys.dont_write_bytecode: + raise DistutilsByteCompileError('byte-compiling is disabled.') + + # First, if the caller didn't force us into direct or indirect mode, + # figure out which mode we should be in. We take a conservative + # approach: choose direct mode *only* if the current interpreter is + # in debug mode and optimize is 0. If we're not in debug mode (-O + # or -OO), we don't know which level of optimization this + # interpreter is running with, so we can't do direct + # byte-compilation and be certain that it's the right thing. Thus, + # always compile indirectly if the current interpreter is in either + # optimize mode, or if either optimization level was requested by + # the caller. + if direct is None: + direct = (__debug__ and optimize == 0) + + # "Indirect" byte-compilation: write a temporary script and then + # run it with the appropriate flags. + if not direct: + try: + from tempfile import mkstemp + (script_fd, script_name) = mkstemp(".py") + except ImportError: + from tempfile import mktemp + (script_fd, script_name) = None, mktemp(".py") + log.info("writing byte-compilation script '%s'", script_name) + if not dry_run: + if script_fd is not None: + script = os.fdopen(script_fd, "w") + else: + script = open(script_name, "w") + + with script: + script.write("""\ +from distutils.util import byte_compile +files = [ +""") + + # XXX would be nice to write absolute filenames, just for + # safety's sake (script should be more robust in the face of + # chdir'ing before running it). But this requires abspath'ing + # 'prefix' as well, and that breaks the hack in build_lib's + # 'byte_compile()' method that carefully tacks on a trailing + # slash (os.sep really) to make sure the prefix here is "just + # right". This whole prefix business is rather delicate -- the + # problem is that it's really a directory, but I'm treating it + # as a dumb string, so trailing slashes and so forth matter. + + #py_files = map(os.path.abspath, py_files) + #if prefix: + # prefix = os.path.abspath(prefix) + + script.write(",\n".join(map(repr, py_files)) + "]\n") + script.write(""" +byte_compile(files, optimize=%r, force=%r, + prefix=%r, base_dir=%r, + verbose=%r, dry_run=0, + direct=1) +""" % (optimize, force, prefix, base_dir, verbose)) + + cmd = [sys.executable] + cmd.extend(_optim_args_from_interpreter_flags()) + cmd.append(script_name) + spawn(cmd, dry_run=dry_run) + execute(os.remove, (script_name,), "removing %s" % script_name, + dry_run=dry_run) + + # "Direct" byte-compilation: use the py_compile module to compile + # right here, right now. Note that the script generated in indirect + # mode simply calls 'byte_compile()' in direct mode, a weird sort of + # cross-process recursion. Hey, it works! + else: + from py_compile import compile + + for file in py_files: + if file[-3:] != ".py": + # This lets us be lazy and not filter filenames in + # the "install_lib" command. + continue + + # Terminology from the py_compile module: + # cfile - byte-compiled file + # dfile - purported source filename (same as 'file' by default) + if optimize >= 0: + opt = '' if optimize == 0 else optimize + cfile = importlib.util.cache_from_source( + file, optimization=opt) + else: + cfile = importlib.util.cache_from_source(file) + dfile = file + if prefix: + if file[:len(prefix)] != prefix: + raise ValueError("invalid prefix: filename %r doesn't start with %r" + % (file, prefix)) + dfile = dfile[len(prefix):] + if base_dir: + dfile = os.path.join(base_dir, dfile) + + cfile_base = os.path.basename(cfile) + if direct: + if force or newer(file, cfile): + log.info("byte-compiling %s to %s", file, cfile_base) + if not dry_run: + compile(file, cfile, dfile) + else: + log.debug("skipping byte-compilation of %s to %s", + file, cfile_base) + +# byte_compile () + +def rfc822_escape (header): + """Return a version of the string escaped for inclusion in an + RFC-822 header, by ensuring there are 8 spaces space after each newline. + """ + lines = header.split('\n') + sep = '\n' + 8 * ' ' + return sep.join(lines) diff --git a/venv/Lib/site-packages/setuptools/_distutils/version.py b/venv/Lib/site-packages/setuptools/_distutils/version.py new file mode 100644 index 0000000..35e181d --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_distutils/version.py @@ -0,0 +1,363 @@ +# +# distutils/version.py +# +# Implements multiple version numbering conventions for the +# Python Module Distribution Utilities. +# +# $Id$ +# + +"""Provides classes to represent module version numbers (one class for +each style of version numbering). There are currently two such classes +implemented: StrictVersion and LooseVersion. + +Every version number class implements the following interface: + * the 'parse' method takes a string and parses it to some internal + representation; if the string is an invalid version number, + 'parse' raises a ValueError exception + * the class constructor takes an optional string argument which, + if supplied, is passed to 'parse' + * __str__ reconstructs the string that was passed to 'parse' (or + an equivalent string -- ie. one that will generate an equivalent + version number instance) + * __repr__ generates Python code to recreate the version number instance + * _cmp compares the current instance with either another instance + of the same class or a string (which will be parsed to an instance + of the same class, thus must follow the same rules) +""" + +import re +import warnings +import contextlib + + +@contextlib.contextmanager +def suppress_known_deprecation(): + with warnings.catch_warnings(record=True) as ctx: + warnings.filterwarnings( + action='default', + category=DeprecationWarning, + message="distutils Version classes are deprecated.", + ) + yield ctx + + +class Version: + """Abstract base class for version numbering classes. Just provides + constructor (__init__) and reproducer (__repr__), because those + seem to be the same for all version numbering classes; and route + rich comparisons to _cmp. + """ + + def __init__ (self, vstring=None): + warnings.warn( + "distutils Version classes are deprecated. " + "Use packaging.version instead.", + DeprecationWarning, + stacklevel=2, + ) + if vstring: + self.parse(vstring) + + def __repr__ (self): + return "%s ('%s')" % (self.__class__.__name__, str(self)) + + def __eq__(self, other): + c = self._cmp(other) + if c is NotImplemented: + return c + return c == 0 + + def __lt__(self, other): + c = self._cmp(other) + if c is NotImplemented: + return c + return c < 0 + + def __le__(self, other): + c = self._cmp(other) + if c is NotImplemented: + return c + return c <= 0 + + def __gt__(self, other): + c = self._cmp(other) + if c is NotImplemented: + return c + return c > 0 + + def __ge__(self, other): + c = self._cmp(other) + if c is NotImplemented: + return c + return c >= 0 + + +# Interface for version-number classes -- must be implemented +# by the following classes (the concrete ones -- Version should +# be treated as an abstract class). +# __init__ (string) - create and take same action as 'parse' +# (string parameter is optional) +# parse (string) - convert a string representation to whatever +# internal representation is appropriate for +# this style of version numbering +# __str__ (self) - convert back to a string; should be very similar +# (if not identical to) the string supplied to parse +# __repr__ (self) - generate Python code to recreate +# the instance +# _cmp (self, other) - compare two version numbers ('other' may +# be an unparsed version string, or another +# instance of your version class) + + +class StrictVersion (Version): + + """Version numbering for anal retentives and software idealists. + Implements the standard interface for version number classes as + described above. A version number consists of two or three + dot-separated numeric components, with an optional "pre-release" tag + on the end. The pre-release tag consists of the letter 'a' or 'b' + followed by a number. If the numeric components of two version + numbers are equal, then one with a pre-release tag will always + be deemed earlier (lesser) than one without. + + The following are valid version numbers (shown in the order that + would be obtained by sorting according to the supplied cmp function): + + 0.4 0.4.0 (these two are equivalent) + 0.4.1 + 0.5a1 + 0.5b3 + 0.5 + 0.9.6 + 1.0 + 1.0.4a3 + 1.0.4b1 + 1.0.4 + + The following are examples of invalid version numbers: + + 1 + 2.7.2.2 + 1.3.a4 + 1.3pl1 + 1.3c4 + + The rationale for this version numbering system will be explained + in the distutils documentation. + """ + + version_re = re.compile(r'^(\d+) \. (\d+) (\. (\d+))? ([ab](\d+))?$', + re.VERBOSE | re.ASCII) + + + def parse (self, vstring): + match = self.version_re.match(vstring) + if not match: + raise ValueError("invalid version number '%s'" % vstring) + + (major, minor, patch, prerelease, prerelease_num) = \ + match.group(1, 2, 4, 5, 6) + + if patch: + self.version = tuple(map(int, [major, minor, patch])) + else: + self.version = tuple(map(int, [major, minor])) + (0,) + + if prerelease: + self.prerelease = (prerelease[0], int(prerelease_num)) + else: + self.prerelease = None + + + def __str__ (self): + + if self.version[2] == 0: + vstring = '.'.join(map(str, self.version[0:2])) + else: + vstring = '.'.join(map(str, self.version)) + + if self.prerelease: + vstring = vstring + self.prerelease[0] + str(self.prerelease[1]) + + return vstring + + + def _cmp (self, other): + if isinstance(other, str): + with suppress_known_deprecation(): + other = StrictVersion(other) + elif not isinstance(other, StrictVersion): + return NotImplemented + + if self.version != other.version: + # numeric versions don't match + # prerelease stuff doesn't matter + if self.version < other.version: + return -1 + else: + return 1 + + # have to compare prerelease + # case 1: neither has prerelease; they're equal + # case 2: self has prerelease, other doesn't; other is greater + # case 3: self doesn't have prerelease, other does: self is greater + # case 4: both have prerelease: must compare them! + + if (not self.prerelease and not other.prerelease): + return 0 + elif (self.prerelease and not other.prerelease): + return -1 + elif (not self.prerelease and other.prerelease): + return 1 + elif (self.prerelease and other.prerelease): + if self.prerelease == other.prerelease: + return 0 + elif self.prerelease < other.prerelease: + return -1 + else: + return 1 + else: + assert False, "never get here" + +# end class StrictVersion + + +# The rules according to Greg Stein: +# 1) a version number has 1 or more numbers separated by a period or by +# sequences of letters. If only periods, then these are compared +# left-to-right to determine an ordering. +# 2) sequences of letters are part of the tuple for comparison and are +# compared lexicographically +# 3) recognize the numeric components may have leading zeroes +# +# The LooseVersion class below implements these rules: a version number +# string is split up into a tuple of integer and string components, and +# comparison is a simple tuple comparison. This means that version +# numbers behave in a predictable and obvious way, but a way that might +# not necessarily be how people *want* version numbers to behave. There +# wouldn't be a problem if people could stick to purely numeric version +# numbers: just split on period and compare the numbers as tuples. +# However, people insist on putting letters into their version numbers; +# the most common purpose seems to be: +# - indicating a "pre-release" version +# ('alpha', 'beta', 'a', 'b', 'pre', 'p') +# - indicating a post-release patch ('p', 'pl', 'patch') +# but of course this can't cover all version number schemes, and there's +# no way to know what a programmer means without asking him. +# +# The problem is what to do with letters (and other non-numeric +# characters) in a version number. The current implementation does the +# obvious and predictable thing: keep them as strings and compare +# lexically within a tuple comparison. This has the desired effect if +# an appended letter sequence implies something "post-release": +# eg. "0.99" < "0.99pl14" < "1.0", and "5.001" < "5.001m" < "5.002". +# +# However, if letters in a version number imply a pre-release version, +# the "obvious" thing isn't correct. Eg. you would expect that +# "1.5.1" < "1.5.2a2" < "1.5.2", but under the tuple/lexical comparison +# implemented here, this just isn't so. +# +# Two possible solutions come to mind. The first is to tie the +# comparison algorithm to a particular set of semantic rules, as has +# been done in the StrictVersion class above. This works great as long +# as everyone can go along with bondage and discipline. Hopefully a +# (large) subset of Python module programmers will agree that the +# particular flavour of bondage and discipline provided by StrictVersion +# provides enough benefit to be worth using, and will submit their +# version numbering scheme to its domination. The free-thinking +# anarchists in the lot will never give in, though, and something needs +# to be done to accommodate them. +# +# Perhaps a "moderately strict" version class could be implemented that +# lets almost anything slide (syntactically), and makes some heuristic +# assumptions about non-digits in version number strings. This could +# sink into special-case-hell, though; if I was as talented and +# idiosyncratic as Larry Wall, I'd go ahead and implement a class that +# somehow knows that "1.2.1" < "1.2.2a2" < "1.2.2" < "1.2.2pl3", and is +# just as happy dealing with things like "2g6" and "1.13++". I don't +# think I'm smart enough to do it right though. +# +# In any case, I've coded the test suite for this module (see +# ../test/test_version.py) specifically to fail on things like comparing +# "1.2a2" and "1.2". That's not because the *code* is doing anything +# wrong, it's because the simple, obvious design doesn't match my +# complicated, hairy expectations for real-world version numbers. It +# would be a snap to fix the test suite to say, "Yep, LooseVersion does +# the Right Thing" (ie. the code matches the conception). But I'd rather +# have a conception that matches common notions about version numbers. + +class LooseVersion (Version): + + """Version numbering for anarchists and software realists. + Implements the standard interface for version number classes as + described above. A version number consists of a series of numbers, + separated by either periods or strings of letters. When comparing + version numbers, the numeric components will be compared + numerically, and the alphabetic components lexically. The following + are all valid version numbers, in no particular order: + + 1.5.1 + 1.5.2b2 + 161 + 3.10a + 8.02 + 3.4j + 1996.07.12 + 3.2.pl0 + 3.1.1.6 + 2g6 + 11g + 0.960923 + 2.2beta29 + 1.13++ + 5.5.kw + 2.0b1pl0 + + In fact, there is no such thing as an invalid version number under + this scheme; the rules for comparison are simple and predictable, + but may not always give the results you want (for some definition + of "want"). + """ + + component_re = re.compile(r'(\d+ | [a-z]+ | \.)', re.VERBOSE) + + def parse (self, vstring): + # I've given up on thinking I can reconstruct the version string + # from the parsed tuple -- so I just store the string here for + # use by __str__ + self.vstring = vstring + components = [x for x in self.component_re.split(vstring) + if x and x != '.'] + for i, obj in enumerate(components): + try: + components[i] = int(obj) + except ValueError: + pass + + self.version = components + + + def __str__ (self): + return self.vstring + + + def __repr__ (self): + return "LooseVersion ('%s')" % str(self) + + + def _cmp (self, other): + if isinstance(other, str): + other = LooseVersion(other) + elif not isinstance(other, LooseVersion): + return NotImplemented + + if self.version == other.version: + return 0 + if self.version < other.version: + return -1 + if self.version > other.version: + return 1 + + +# end class LooseVersion diff --git a/venv/Lib/site-packages/setuptools/_distutils/versionpredicate.py b/venv/Lib/site-packages/setuptools/_distutils/versionpredicate.py new file mode 100644 index 0000000..55f25d9 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_distutils/versionpredicate.py @@ -0,0 +1,169 @@ +"""Module for parsing and testing package version predicate strings. +""" +import re +import distutils.version +import operator + + +re_validPackage = re.compile(r"(?i)^\s*([a-z_]\w*(?:\.[a-z_]\w*)*)(.*)", + re.ASCII) +# (package) (rest) + +re_paren = re.compile(r"^\s*\((.*)\)\s*$") # (list) inside of parentheses +re_splitComparison = re.compile(r"^\s*(<=|>=|<|>|!=|==)\s*([^\s,]+)\s*$") +# (comp) (version) + + +def splitUp(pred): + """Parse a single version comparison. + + Return (comparison string, StrictVersion) + """ + res = re_splitComparison.match(pred) + if not res: + raise ValueError("bad package restriction syntax: %r" % pred) + comp, verStr = res.groups() + with distutils.version.suppress_known_deprecation(): + other = distutils.version.StrictVersion(verStr) + return (comp, other) + +compmap = {"<": operator.lt, "<=": operator.le, "==": operator.eq, + ">": operator.gt, ">=": operator.ge, "!=": operator.ne} + +class VersionPredicate: + """Parse and test package version predicates. + + >>> v = VersionPredicate('pyepat.abc (>1.0, <3333.3a1, !=1555.1b3)') + + The `name` attribute provides the full dotted name that is given:: + + >>> v.name + 'pyepat.abc' + + The str() of a `VersionPredicate` provides a normalized + human-readable version of the expression:: + + >>> print(v) + pyepat.abc (> 1.0, < 3333.3a1, != 1555.1b3) + + The `satisfied_by()` method can be used to determine with a given + version number is included in the set described by the version + restrictions:: + + >>> v.satisfied_by('1.1') + True + >>> v.satisfied_by('1.4') + True + >>> v.satisfied_by('1.0') + False + >>> v.satisfied_by('4444.4') + False + >>> v.satisfied_by('1555.1b3') + False + + `VersionPredicate` is flexible in accepting extra whitespace:: + + >>> v = VersionPredicate(' pat( == 0.1 ) ') + >>> v.name + 'pat' + >>> v.satisfied_by('0.1') + True + >>> v.satisfied_by('0.2') + False + + If any version numbers passed in do not conform to the + restrictions of `StrictVersion`, a `ValueError` is raised:: + + >>> v = VersionPredicate('p1.p2.p3.p4(>=1.0, <=1.3a1, !=1.2zb3)') + Traceback (most recent call last): + ... + ValueError: invalid version number '1.2zb3' + + It the module or package name given does not conform to what's + allowed as a legal module or package name, `ValueError` is + raised:: + + >>> v = VersionPredicate('foo-bar') + Traceback (most recent call last): + ... + ValueError: expected parenthesized list: '-bar' + + >>> v = VersionPredicate('foo bar (12.21)') + Traceback (most recent call last): + ... + ValueError: expected parenthesized list: 'bar (12.21)' + + """ + + def __init__(self, versionPredicateStr): + """Parse a version predicate string. + """ + # Fields: + # name: package name + # pred: list of (comparison string, StrictVersion) + + versionPredicateStr = versionPredicateStr.strip() + if not versionPredicateStr: + raise ValueError("empty package restriction") + match = re_validPackage.match(versionPredicateStr) + if not match: + raise ValueError("bad package name in %r" % versionPredicateStr) + self.name, paren = match.groups() + paren = paren.strip() + if paren: + match = re_paren.match(paren) + if not match: + raise ValueError("expected parenthesized list: %r" % paren) + str = match.groups()[0] + self.pred = [splitUp(aPred) for aPred in str.split(",")] + if not self.pred: + raise ValueError("empty parenthesized list in %r" + % versionPredicateStr) + else: + self.pred = [] + + def __str__(self): + if self.pred: + seq = [cond + " " + str(ver) for cond, ver in self.pred] + return self.name + " (" + ", ".join(seq) + ")" + else: + return self.name + + def satisfied_by(self, version): + """True if version is compatible with all the predicates in self. + The parameter version must be acceptable to the StrictVersion + constructor. It may be either a string or StrictVersion. + """ + for cond, ver in self.pred: + if not compmap[cond](version, ver): + return False + return True + + +_provision_rx = None + +def split_provision(value): + """Return the name and optional version number of a provision. + + The version number, if given, will be returned as a `StrictVersion` + instance, otherwise it will be `None`. + + >>> split_provision('mypkg') + ('mypkg', None) + >>> split_provision(' mypkg( 1.2 ) ') + ('mypkg', StrictVersion ('1.2')) + """ + global _provision_rx + if _provision_rx is None: + _provision_rx = re.compile( + r"([a-zA-Z_]\w*(?:\.[a-zA-Z_]\w*)*)(?:\s*\(\s*([^)\s]+)\s*\))?$", + re.ASCII) + value = value.strip() + m = _provision_rx.match(value) + if not m: + raise ValueError("illegal provides specification: %r" % value) + ver = m.group(2) or None + if ver: + with distutils.version.suppress_known_deprecation(): + ver = distutils.version.StrictVersion(ver) + return m.group(1), ver diff --git a/venv/Lib/site-packages/setuptools/_entry_points.py b/venv/Lib/site-packages/setuptools/_entry_points.py new file mode 100644 index 0000000..f087681 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_entry_points.py @@ -0,0 +1,86 @@ +import functools +import operator +import itertools + +from .extern.jaraco.text import yield_lines +from .extern.jaraco.functools import pass_none +from ._importlib import metadata +from ._itertools import ensure_unique +from .extern.more_itertools import consume + + +def ensure_valid(ep): + """ + Exercise one of the dynamic properties to trigger + the pattern match. + """ + ep.extras + + +def load_group(value, group): + """ + Given a value of an entry point or series of entry points, + return each as an EntryPoint. + """ + # normalize to a single sequence of lines + lines = yield_lines(value) + text = f'[{group}]\n' + '\n'.join(lines) + return metadata.EntryPoints._from_text(text) + + +def by_group_and_name(ep): + return ep.group, ep.name + + +def validate(eps: metadata.EntryPoints): + """ + Ensure entry points are unique by group and name and validate each. + """ + consume(map(ensure_valid, ensure_unique(eps, key=by_group_and_name))) + return eps + + +@functools.singledispatch +def load(eps): + """ + Given a Distribution.entry_points, produce EntryPoints. + """ + groups = itertools.chain.from_iterable( + load_group(value, group) + for group, value in eps.items()) + return validate(metadata.EntryPoints(groups)) + + +@load.register(str) +def _(eps): + r""" + >>> ep, = load('[console_scripts]\nfoo=bar') + >>> ep.group + 'console_scripts' + >>> ep.name + 'foo' + >>> ep.value + 'bar' + """ + return validate(metadata.EntryPoints(metadata.EntryPoints._from_text(eps))) + + +load.register(type(None), lambda x: x) + + +@pass_none +def render(eps: metadata.EntryPoints): + by_group = operator.attrgetter('group') + groups = itertools.groupby(sorted(eps, key=by_group), by_group) + + return '\n'.join( + f'[{group}]\n{render_items(items)}\n' + for group, items in groups + ) + + +def render_items(eps): + return '\n'.join( + f'{ep.name} = {ep.value}' + for ep in sorted(eps) + ) diff --git a/venv/Lib/site-packages/setuptools/_imp.py b/venv/Lib/site-packages/setuptools/_imp.py new file mode 100644 index 0000000..47efd79 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_imp.py @@ -0,0 +1,82 @@ +""" +Re-implementation of find_module and get_frozen_object +from the deprecated imp module. +""" + +import os +import importlib.util +import importlib.machinery + +from .py34compat import module_from_spec + + +PY_SOURCE = 1 +PY_COMPILED = 2 +C_EXTENSION = 3 +C_BUILTIN = 6 +PY_FROZEN = 7 + + +def find_spec(module, paths): + finder = ( + importlib.machinery.PathFinder().find_spec + if isinstance(paths, list) else + importlib.util.find_spec + ) + return finder(module, paths) + + +def find_module(module, paths=None): + """Just like 'imp.find_module()', but with package support""" + spec = find_spec(module, paths) + if spec is None: + raise ImportError("Can't find %s" % module) + if not spec.has_location and hasattr(spec, 'submodule_search_locations'): + spec = importlib.util.spec_from_loader('__init__.py', spec.loader) + + kind = -1 + file = None + static = isinstance(spec.loader, type) + if spec.origin == 'frozen' or static and issubclass( + spec.loader, importlib.machinery.FrozenImporter): + kind = PY_FROZEN + path = None # imp compabilty + suffix = mode = '' # imp compatibility + elif spec.origin == 'built-in' or static and issubclass( + spec.loader, importlib.machinery.BuiltinImporter): + kind = C_BUILTIN + path = None # imp compabilty + suffix = mode = '' # imp compatibility + elif spec.has_location: + path = spec.origin + suffix = os.path.splitext(path)[1] + mode = 'r' if suffix in importlib.machinery.SOURCE_SUFFIXES else 'rb' + + if suffix in importlib.machinery.SOURCE_SUFFIXES: + kind = PY_SOURCE + elif suffix in importlib.machinery.BYTECODE_SUFFIXES: + kind = PY_COMPILED + elif suffix in importlib.machinery.EXTENSION_SUFFIXES: + kind = C_EXTENSION + + if kind in {PY_SOURCE, PY_COMPILED}: + file = open(path, mode) + else: + path = None + suffix = mode = '' + + return file, path, (suffix, mode, kind) + + +def get_frozen_object(module, paths=None): + spec = find_spec(module, paths) + if not spec: + raise ImportError("Can't find %s" % module) + return spec.loader.get_code(module) + + +def get_module(module, paths, info): + spec = find_spec(module, paths) + if not spec: + raise ImportError("Can't find %s" % module) + return module_from_spec(spec) diff --git a/venv/Lib/site-packages/setuptools/_importlib.py b/venv/Lib/site-packages/setuptools/_importlib.py new file mode 100644 index 0000000..c1ac137 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_importlib.py @@ -0,0 +1,36 @@ +import sys + + +def disable_importlib_metadata_finder(metadata): + """ + Ensure importlib_metadata doesn't provide older, incompatible + Distributions. + + Workaround for #3102. + """ + try: + import importlib_metadata + except ImportError: + return + if importlib_metadata is metadata: + return + to_remove = [ + ob + for ob in sys.meta_path + if isinstance(ob, importlib_metadata.MetadataPathFinder) + ] + for item in to_remove: + sys.meta_path.remove(item) + + +if sys.version_info < (3, 10): + from setuptools.extern import importlib_metadata as metadata + disable_importlib_metadata_finder(metadata) +else: + import importlib.metadata as metadata # noqa: F401 + + +if sys.version_info < (3, 9): + from setuptools.extern import importlib_resources as resources +else: + import importlib.resources as resources # noqa: F401 diff --git a/venv/Lib/site-packages/setuptools/_itertools.py b/venv/Lib/site-packages/setuptools/_itertools.py new file mode 100644 index 0000000..b8bf6d2 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_itertools.py @@ -0,0 +1,23 @@ +from setuptools.extern.more_itertools import consume # noqa: F401 + + +# copied from jaraco.itertools 6.1 +def ensure_unique(iterable, key=lambda x: x): + """ + Wrap an iterable to raise a ValueError if non-unique values are encountered. + + >>> list(ensure_unique('abc')) + ['a', 'b', 'c'] + >>> consume(ensure_unique('abca')) + Traceback (most recent call last): + ... + ValueError: Duplicate element 'a' encountered. + """ + seen = set() + seen_add = seen.add + for element in iterable: + k = key(element) + if k in seen: + raise ValueError(f"Duplicate element {element!r} encountered.") + seen_add(k) + yield element diff --git a/venv/Lib/site-packages/setuptools/_path.py b/venv/Lib/site-packages/setuptools/_path.py new file mode 100644 index 0000000..ede9cb0 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_path.py @@ -0,0 +1,7 @@ +import os + + +def ensure_directory(path): + """Ensure that the parent directory of `path` exists""" + dirname = os.path.dirname(path) + os.makedirs(dirname, exist_ok=True) diff --git a/venv/Lib/site-packages/setuptools/_reqs.py b/venv/Lib/site-packages/setuptools/_reqs.py new file mode 100644 index 0000000..ca72417 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_reqs.py @@ -0,0 +1,19 @@ +import setuptools.extern.jaraco.text as text + +from pkg_resources import Requirement + + +def parse_strings(strs): + """ + Yield requirement strings for each specification in `strs`. + + `strs` must be a string, or a (possibly-nested) iterable thereof. + """ + return text.join_continuation(map(text.drop_comment, text.yield_lines(strs))) + + +def parse(strs): + """ + Deprecated drop-in replacement for pkg_resources.parse_requirements. + """ + return map(Requirement, parse_strings(strs)) diff --git a/venv/Lib/site-packages/setuptools/_vendor/__init__.py b/venv/Lib/site-packages/setuptools/_vendor/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/venv/Lib/site-packages/setuptools/_vendor/__pycache__/__init__.cpython-39.pyc b/venv/Lib/site-packages/setuptools/_vendor/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f94715e64facc452874125336abdde90f782607e GIT binary patch literal 183 zcmYe~<>g`kf)07LBoO@=L?8o3AjbiSi&=m~3PUi1CZpdI zlbDy6SRCV6P~ehSk{IKYpPZNz6Ox)+5L1v@pj(<(keHmEnxb2tk(!#LYgn3?Rc>68 z8&jNGQd&@wpPy446JM5^my%x;6Ca2KczG$)edCqXCP((0HbU$ AX8-^I literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/_vendor/__pycache__/ordered_set.cpython-39.pyc b/venv/Lib/site-packages/setuptools/_vendor/__pycache__/ordered_set.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..84799a9755e73c8ea6cefb86f2864b3cb51673a5 GIT binary patch literal 16377 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/_vendor/__pycache__/pyparsing.cpython-39.pyc b/venv/Lib/site-packages/setuptools/_vendor/__pycache__/pyparsing.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..42c9bba48569e6923edbe418525cdb8a3eb928f1 GIT binary patch literal 201336 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�M#Ek$(!) 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/_vendor/__pycache__/typing_extensions.cpython-39.pyc b/venv/Lib/site-packages/setuptools/_vendor/__pycache__/typing_extensions.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f072a2d0f2a53413d395c0cbad874636bf550a33 GIT binary patch literal 68492 zcmeFa3z%HTb>G?V=@|?LPvSvRWD}wZ3<(V16a|qKK@gz$8q(xYqMC#njk$M#9?WzP zZubzta3IkHEs?aSD1OL}CE1{)ID%tKwxVRcNt|Sp?{l1&AK8tQ^tYSXR^miojR{NRbRVyB*W*`Yi~F*Kb6gVOFz<| zGC%I;+wPFh%XrzjOx69(R*csR)_qd z;4!~k9d52CPhqY&KU^K2AE}OHGhWdvy^^V}@rJxIe@BmIyx}ipt801Vlm6OsWBeZZ zQufVkHsi1Ji{6^Ex!}kA;_UkB`ex;!j5q47eI?_qC1ry*=B<09P~GTnw7YC|y)!uuk<4S}78t+>2TuYt^ z{`dIr3E{ue>aSS+pC-pO)oYq%?>etSKV9SP@ZQVcYc0?9mgnclQ>j)4!t?Ke=X<;x zsOyFlJlFZxdDnY84W5d@v&$PN&v*)+9sZ6Go(ie&t-hD*_0{XSeoys#DD_6~Cf>No zA3mF}s_dQBom_WScX1uBs-zpMHyV_?fif3-n3S8UH#K+g?jCP9@9y@qv%5*%<8R)c z@o&&CZ{m$o^(N9LsuT9^&GzmOl5%tP=H?DBYdHQUOtVVg-kwkJPTaE@7;bp^Vxh*ZWgkcrZDC%Ai2}O z!rwBJdo#zIH&D|Z-fh%$n>{JczRx`kp}y0gzSHWwlRERk1JrqU^=^CfF7Hm>ypuQY zCiVUPW`FMt^TXPEx4n6{z4<9WQ^4wFsr+Fi9?)Bc!oA38;R1c9(Px;$o2r{$x*xUE;{)fDW-^la+Ufz6!Hy^G(JpV}b z5#D|@e*3ZTZQ+~VeZ2QwgJ#m8`8z=KX!TL%%oE-ubwBDqT7Ar(KWWc@ljo0DA7`u| zrJV2eo&<&`{RhwH&t|KS8;(51JTC@i@=aDJn^WG?-W26L;XUJhn7>bYAMu~8eJ``) z*)L?hk9yTta@D82=lrK?-%EMVdxt3RkY5JQr~RkBkNHzG*@kd)(tpOEtbN$4as7zF za~ODvfyVsV>a$!wTKy>3YPH&&r6-HQU#GmfcZBkekp5gqO{%0$dxuHo{pz!x=lMYO zy!TD-sCVp@Z1tnf-Co0+CG8M7k9%|Eoa24<+{Z|ncklWivtI9|Voh3JvXmh^^aznxmz-pcY(aq)#;wR zUMlaj%j=!+0${CqZLh=M!`3s4^h_yuoie?u*ZfKkrG3F*{JXT|q<4z8og!C6X?@@K zPJ4^5WEe}YIoI=^sCOy2zYgo?;y{zcZRahQ1%S{c9fKld!HcX6QpeL zk1`f7y-}asUz0Y{B*_$T@^jZ1CG*?{)l6*n1}o&d<@J za_|y)7ORWR&klg_7bxjRy&t2bA4}E$g8zc|7rf6I+=~O&!E*5Xy!Yb+-}{{Rd4qe= z*1<1$U!?3W3QB{lP(A6N3}IX}7=Hp7hXbvHr>dt0)HNJDPhCIhouiy{A#y{hI#rqlS zp(XCmdp~RUFE*bd|JS^)lmF}Fk9zClr2d@u^Q8W~|M9Q~KSA0zyuU))Uy0LR@;?!_ zbjg1yynE5hKAjo=tKSwsI{EE9*YSLi+R?FEi61(@6?}vtTkPqdw$BFUwD3@v9M>cxlo@z?t6Pq9`pUV zJ-05_XHVYVnSZ|RcNP~qt=3%o`PvJ9(`yCK)51pcXw5&>@tf^NtJ$7dINcqqHCrKk zf?=!LX`Fqw%)im>ST-0XZCc$IeG1$R^R-U-7&ptA*-U$LC%c^aJe>X)b7!+JXFGHU z9hKuRPr1u4=a%!w^Fg%(XK(j~;65+k%y|XgD%!iHvNT*HM=YRsRe(!<9ikQf2>wps0a0Vze6|IYTe-}aNs}?w1RGa&Tozvy7}q3 zc6TJn)GgF`&@K2}ZJ69;4Shgq)5rYjG1wm&|2&?ntpf8G8)EP&Q124Iy<1l2$v3jHV zczvNe*7sy+e`}GfLAUsze`3+^u6fX(sV~lT9uzjOc_Q%q!1wHj^`X06`}E?%LM!OB zA8va7DZp+rfHcqR7H6z|rH7jxwSDNZhFUP!9h&q{S`*8y7yMwZRrk8(Cxcd}HQnN2 z00@nFzq=v4as6%mP?(|_Zv6JmHR^45`_N)N@VaZKKKkT=+Wrq6*#GFmlMgZM<)eP5 z29hwcx@!fEqm5>FO!rI?zjmwv?sUtOt*4knL33JTnEq%g+|RdtJr_SCF}9lXvWT%c zMA*DnfcYqfVrj`65&}a6qT=fBgT81?8(^gBt2COBfI7o;v@)~UobG69RyxP(ol4WE z8!CZ;F)>mJKL<|L=NIPuy?aOEq)KHbXw9oQmC~43w^yPX)7d7C{DPOrB?kjAtt*rpRRGikZawjNTX zvC!8@kqA`>0u&RD+~m@YQI(Zx=qLo_h+kQ3GyhLEI>#U?jV4t#r~O^y6X&zRdP+DC zm2PXc7NbhA_4+@pLyJO#~T zaU9Qfho@Vt&W(Dr(=98h*$L_-uXT6fqhLFQep{n4p0gD{$aBB?48EGD$qe>#%-no9 zg9~1fnOmaOMvM=(g83fKKwLtMd1@XU0Snz$7OeB&-9|ST)2ppDPdx^r*6(HjC zsUf#TaZQc&u%jon+Uw-9QP+w%@>U_Yw56wUamLB>#oz#$gM+#}q|39q9M&c2G`lmL zdYT8{&$lhkq%3?=O8p~@&%R1Kp|v88;7hv`EKYYSomND8X}HL3y`s^H2~$LG!@mjr z2>d;)+Kr=4$Os&U)~cX^@Z1yyt5>2)l+dldlE5YS5J$ulirSY+KOf)sZ0+fXs|WU0 z39P4`xAtyJDyF?NO}L@NT|9y#4ZTQ6F>5ts^`KogFMWuSkR zSOM_V!;c?$;+d%s+UHnC4*~M67X{c=aR4 zxr>Tny)dRV1A6!@hzmh$!4EnOzdZrv$wTs1P!`QbecF>;63Pi-hr^DYqkU10L+ zsCyZ>8fAG$$a!gOye#y4+xQli`gRfQZDUkCt63&k3B+2}YLhESJtQsjs1QulPh`G^ zRfQ!dJBhXw=EYIuZmzS?EgV1TwNv!c2r@-CnvG7a_VX%4rNOtXb9iM;i=M5hRdVxw zz3>#5Pz27g#K8J4W`etxk@8qz5PoM1*ljYhaj^L0wD@Q_eS<}(Q|xK4>>flub(IbELD#g-G}?!qNY zEXW{k$rhP!^02MknNV)q_*O2L`%Wppv@!0fc(t02=DhN20V?vf&T{$!R%6y;b~dblE_KrR{G@B=`GNrt_u<1@8#cHmwJ4m2;vW!X=2}N! z!rI-TIcWu&?P{s%pR9Ej`bIryll^b<4VT~b2&0AU(uSxpaUDGzj*vrbQTy7raOq^u z!dtwVIb$ti=(E9Y=|4L8a|N~P&8!W2{(Z`U_Jh`3$Ub)=d+2n!#nYK!h6ivxg=6*hu|OT{(8a*~h<+wKM>L0&wO0FO9y0K`2SU=>YTFpOEtNkOvtwyOA3w%ejOKT%!upHyr$@8QAOxTBb!Lj(Wx;w0k zFw2eVS>3(L1t!sr-n2hA7mc8G;U|S2GJm>pAIh)E?Z16B#O(6N@6 zA~y-2x4Tkrda102t8p>O@)~i1zBf@>edTmZ(gXFjzmnUz-!vt0(GklfG2Ux6{aq4N zLs7mt;C1DnnCN9hU3E_{9@(WT2XI)c6n+`(RRmu8Z-4azTI3*l%&*U^?128)UEU`| z_jl=y@xAW=E)^R0={sMkZFa#4W@q~5nc;3%XsU^y*}MXc^Q0OYYg(AVmU%OxL`be$ zx4J`9tYfIhAcqCXCH-~mA=4l54GB=7-+`7K&7Pi*fViJ;`!dAc(ORgCdpiPeFh%LX zGrA0*mqs4`o9egT$Sz%xu4AxNtDIU(t&^NyN9*Xa$*+zex^4;%kt-y6!6xqeyXi1# zZ}E*P-_}=oypB%>_1@QwWEr*kb3C}9GGh5sDfJdm?sEjiLn#WMrq=_=!o{G8rA3qhjhWLLvv?@uu2v(RErMYS2l8Tt zO4aDsQ8LVsTWsybG;dYsknx>iUaX9Wd*JP&8LFv%T#CzLg+aG#;9~~6Y?;%@aPWg5Am&vQNJ_4Z zpg~$c9Tv-Y9Y_?>;SCXLtuA%O3&111yF%)mkcF|6hlk#=oSnfWi%k(>#0gTJ0@7v? z*)x(w3n^){7z$azalt7C{&>mp{Xe9HSGaVGm`~??GYA+P95yldVdWU0WjAj4dbLlh zm6IDs&~w6BZ%(x|UTu1$MonT~?d5D;_i7P}>R#kNctICin(SihlbG<`slMHm)VR86 zCz)Oqx9{dMK(xEV_2#*Jr_d?RmL%Yvbs}E=i?N6|UYHC{@&1L}?n-c)oAIIGMgBOE zK;79b%(gJE<>%`QP99&@<1@OLIFPhL^4-m9MIzr-B&3E@CSerRRnbTHYQ=uOW^P?o z!W%CHFOw-H;Mr&oVpz_S@6J?zreXL~lI{%afZ6rz{|m z<-1#I2Vy6K&|V-fiyo0!lUrYv+t#cC!LU~>W`i3$*>gD$R6{7v;{aTEAsgJ#L33($ zy^@K`#r8d&655C%I6@d_-YuRh>mDzRTxXb4rk0&xT|}H7!BfMNCD!t-c{78*M&(St zGrFAbti>Vt<0qP(F*Gy~lc0&SAURJoJ!%>+*KeeoOuC$J%r~aRf6ceh6=MnW1H5k% z9}@60;vYgY8%EZ-*3rgvOlWr*OW?J9=gV-c{(>=N*y`uo&LA21(~E(eGsd;#ooofi zac98xF59YX~1zO8WM0F$%CBPDXY2DJvA_o=R&D*yA!-Nz5BW zT*i~9k$IcDD{UWUv(s5<@4flvqZmpTk4#Lr=5JoG$2Yq|Z*H{Pi+=m&J8!u)5ilnm zO+CPPVn@x_k4$%m&8RI;lneXKp+W8zjU`ynqptJXDGn?#%{oC3OG#vJb!%Yz;MDj! zEmzKLk0~BZVcy`@XSIUuN`i7?8vAK1FoGs@H zwm^)cWGt{y6mSz6$>#W$vrD@MPob4aHon4ErmBM1bxBA^GWGug4;~jFId00?K)-_< zxJ>iy`6$EveB0Z&^x87KJeG-qr`cY#m#wNEF*nak>aZtN!d+Z6zdIZK+FZC)FJ#@=6`H9#xn*xzN@2bbvKdd4sR(lJv0M8F5u-%E`=0 zi}^whzpr7mNp(Z%ZqcwY5FVgAh`ffJwyC{h5Y&zL^KIY8WzZntGgmUR5?W36NtB&w ziTh!%%ATFdn#MwBxPE{atxB=HS6lqG|EIBVG!1XYXWA!7LxLGS4 zKn5$5My_UIiYiY5l;Ez~^NOGn7YkX!mX3ZnpUVcjNT9*$DRZg_p5ktrZ_h`M@8^3d znxWEGB4wUb4Z~oX!B8Z0p_892Kr_$@twuA7!Fg3;HT|^iq*V)kMwg$}C7HT5Yc-v} z5|4)?1e;QxZ813rey;cJr1MnOPpAmBpV!?{NqCM|03y&d>kc81)jOTQ&Gw%l3HK_|-2MqJYVgn1Koih&;$%nJuP_ftR?HyctI=4uIzSg+`HbXg#O~M$d>nYqI2(LOxxcK-tS-i{X(DvD)*fFp|7l#E%_Y7zUk{FBofe9W z4lWs~*Wg!`Rygh>b&R0K#=lvvq{up+2V&Z4UsU#Xw;<@c zYf?Q3Gb&U~=AW@InzQ317i zfBpzFq$WSaiF?eEp?%*({2I)2p1Q2jslu%q>%Hx(mUcmXs0L=T!S8T2Be zEqFw^IzuRG%CDNDX1p|MU2$+~bu7G_+QGtGgoUrd^qtMMCOYgVN$_zrvw-&3J(J%= zAAZuszepLuZ|Wla41S9XMnapM?$;L`zclZk}fv-|5kUJyG{?WPj~;9E}w|+j1$#^Q2`^lJCh&Hmhe6r`A!Z_ zoSh{3(x1RuW-nZO3E)=h1+2o?Rab&;R<+gofAU~hwF(pP!O-v3k?lU7_HrKD`cMTE zaAY(*sFwVp*&b=sTpbg4#u1y2^)G|Kazt?Zd2Gv0v@*CPye;Ed7NwvRldA^K5vY;s z?cS{rm9Qwo^<5Fhuj1$+fhh5!K*_e!1wr=19*=>i7pIT)K(Y`tSV0;X^%DKnpq&iP z7>16ob+if75Ub#vL-Hb9VB|dP)N7SpVF}*i^zl6|ZG5-&Pvkq?vjHS(_5PI&kVD61 zw$tr3soc_Q(p3TC+IF4V>xRNyP6l>XSiq?Xt1z`;M7?Nb?B6v$E}xAj5l2ykuIQ(v z>Zj2{K6&8D%AI%IVeR%HT8+6u=#Y5rXf2NW_5Ky=&xy#p7wH(p!S7xEQ+wvwg99c- z4`T#$W_@kzYR83|zdXiBOzAiUvvov@)1wVG*;TZ1H;ycJe6+B*hr^+m8Q5#S!h4C5@#Z$*I#{%X7mzm ztvvd!<7=x=s5Dv620z<_)5$^j@ohnk@>rn=&P0Fml z?SIN8cGg=T8XB{0BpYcgCF5Y3KnpQjbiR*fqsYGo`;?Hv<&gUlQ{O3}R{EQrA=Grm zS75LlU)KH!Z%Df|P{e@|VcJM$eifoi*~BIm?bzTy#ex51R4O$qO4}Wju}-ZQBlU;fm+_JR;a;+BtpU z#yBf38?8uhZ#dnq%rEjX+JOxZj80n9te z(^N^H=B40|bV=4zTS~u0+7l6Yw%ypQB1;eSc4Gv#>vQWy7~QBV@oizZ6Jn$2U9?NJ zvQ&@{$>Je3xcNI%{E-S?aHkoh<*PN4+~;4& zoGCO%!(RpcS}p{4bc*n}+G!l-CoYfiu(QZLl#)49)VoOF_nj$qhL%gbugN*JT$&wL zS)Gv?$>jEXcFmcg<)V4=ewuPA;pHs(M$Z&aOj&v+_|kIzOtCrBS&OkTd#21^%$l!d zm*J0zB9m=nR5>>WH=VT&q~&F5J}a~4u+oWfRDx&}!?Y3VC@&8~5{8$Dj4+IFUGv2u ztG9?|V4Z4tHB%c^Uz}Ud))FQiwcOp=;H_0zq!%0sBG*PES=x3|KC{MKuXkPmrr^WN zYk0be-y3=Nh~z-`-l3^8C3*z;U^b^-;OQ~idxf{*xMCjtF!yUZTU@&Jor{I^Rnk?` zG2q|W*|uCdi{rTS&-iQ>Vz-^zuC#ptnp?Cs*j9o*0a^45Ws1@46#}v-7Cc={ z!a5`j9hIDkVj)?YL?=ET(TN^1W?M8OwSTR4Ib_UMD+)A$6*@a6I;-`dkAwv*1qpEt zscJ7wpNL?(aK+QD`OtkYCP$TB7dDR@KcellS~}pI7zpzNF&_{UcLsK%(OFRx2Ov}y zD@z}M<5^qVskx6V>Bv+DzFUMF5U@wzJo&xMyf?G_t#f_CsLbi+Y2);Lx0kMsM&0}qGWp3QU8 zXlrO*U&(seM(O+eS>yJFd!mUHx-K+Z%{^lJ@tF@*I&x9p*+HbSFaRuE5k~JCzpx|y z3v4>d{=JBks5>Ul)QMB$8=S^1kB-c_#{32?2!2wRbGp2#i!>`v$McHrTDtseUB04= zEqOzsw$CJ6L(%hv;8S{RdaM6kcmIbjeHyGaPBT}N_3d@guDzE`8P+n{>^E~|!)f?; z#LRfwm@;Pe{86qF-pdl+|0Gu^u?jBT9QB(i6fjywy^@~isX9%Cd0}13<~@N9_QIV} zF{XKPyLfxZW4IGP(ogNK9A&zWUuC`NY+=8w){4H$fGXx%npEq_f2SwblZSNo6S^3O zAcd$?!y0q&qxxxFg}jMS)HP2#UB{Ps&@Hin97%kA)8NkWEW@BOggLon$Sylla(iUP-pb__6-5k6 z!R|^7xFUOO0|8)UEVjo8?9E7ieRfNJ^je0We1*K+3d%4(=1Tcf!i zCZ`V|I>Y+=ARsyGjj6On;ao49&|}Cw%%(3?swk!cNC;L2U0zqlgf~reJsQfZ)Y>s_ z&?a47z|uRaR&Iy-{yd3jT}RW(ciTnRLu<9(P{gH_q`|)@Pw;JBepi+Ikm5L%rJ53)raNUK-?ASN}R8TX&s_@mJ->`j1^k1+O3$QSVe+2a~5$}P*??x z7f=brssv+WLLMdMLp42YEp``i;$m)XeLq51Ee~ncXphSBhDitYXK>GQNq^fFv&Na) z7B(?t?Am)D;a;m!^LKD(fZ096TW63bS(Of+8Cf1NNj4K4L25LXm93g1c-Q5E$CgKC zhxD{lHYWG6x^!KnjC$+S zDZKeM1auEZxqk0we*uT7^8nSORFucMV z%fbPIPHtIV$M5aUD;)-qatqA$m86j}dli4L>Ri3N-V@`U3qD58xnQ#Mp5^uDu93MA zaYzsgu4~^^9hK$v@DAHn+K4niFIP$q{u`NtLPUGroR1~rUjc`m;J&M0g>C*;1DM@_ zuFWj%yCjEy5$>MALG6j}4tH-Hv};}|Ze!fM-;SEsLoG>kGg#f2Fu<#G=s`Iy+DK+x z{zsL!ag#jUce#tDol{~BFRX|(10 zy`sf2(p>K#y4uMk@*D`Zxd35JxZ-{RAXKvGZD-YA4YvQ7hHdrQcevWGOloftoz1A; zinuM-(S-TF*%{3O< zjW+B-m>>;dEUeZ07x-^c|NjHv&a%cP`Z0K8JPBcX+h(mFzb-Jflh*lEj~g5MiqZ@X z5)M>K9;cZy=5w1c(AfRY^PoGl?}7b~vwRy<+AS?Eco<=wy-m!LoD-12rKgA0mAOCo zHC?V(DZj2eV~5w8mqXwmmA(Ho(8}q-aaU$od|5fi_0Cz{{jXdQQ=}aWKEtJ3G-kRx ztZkcZ;`8~z)ygcU7N*$ZjRoJ(kCDWQA-G0aObWSHcNJZ(&}jBT%FM&BN1xl-&cPNkW4|o#iQA)VN=D*%G(9TRuai7Of2bdjq=6dn6R@jv{yPY5Rx&-oCPJD1E_eZ?c~fMCt0l@KOwhBX;2T_VeQ{fWOadqRLZ{pr zo;8&n4l()JHC~Ze3=7a|F9b>flEX6kl&f8##kvxWsNdZJ%hF7WIMQ)-Pk$$Z6h6{6b`dm}eY*Bx%UE@l=g zazn+Ml515I9AJ>rBs7TFjFIWqQHa&()(E5_wsi|9md5+X#$=H}nkVPse}&L<3zwc| zs0pzG=BM~U^H(TfP?i)>mRuicUL%izP+2n6rz|WgT&qGD(gzMMdZWWwg!& zct_Gq5I0g~{b8g^kPWFT?&2l`IU!0WlJQ7E4o}>Nij$E)amthOf6Em|{y2w}T6$|F z58=52wB0heTYBtyP{WL1rm9T4%0+G^(2vNqMY4rlTTt`AD$c~YwqysowvacJMncyX zbcDQfj(KiY&bRB{A`NZi-ohOBGIF;H-COLL$qX-?dr=aA9rvYR=(9_L#VBBt|mRdT{T_I zRVDaOhJBMXe<4Or5rq}IDA77K&@Dxb3 z8hnw32Q@@jL3dvc|aE% zie%9B-~kQA4sN7LaT|9X`3$7&YBGzL5Y2O6G_`_vF|&9cMT1i^e6us$XB>Z-vW8G5P&%cR zU1^;)Y~N!#QsWx^#q9mlJ^6-RzGZC*#FE#1mUTdz2J*9OO_}jewdD^rg?qXeSl96^ zg5tkY)<{&RvrRR(bk@hl^whh0)5P(t9H3_;uCGA}k(u4VcO!y*W_HuoOlLEHuRwf9 zDL^Ti*)4pxdZTY>m(JSB;J?td!T+txf92A%szwCtcJ;ny8qC3ZC(Otfua7*S!FyiC z{E;pfbV-opTm1AGL??gm?kAq8*j=c`0W$bNh~Az?z#uYUdLf#LAsXwoYcEwIBONXV z18w6=+g9dqHt(hH3DpIXG%Pw8B?LrMIK3xMk;{)jVbO{i^x#&_PjTnLZJMOpoIq$w zZW9=6690*w+e|g$^#r@Q^SSl7K*{d-tHU)RM@ z!7fJ7tSw@p{ui)5+MZm>yft?J= zJLKFBe}JxfAoeHvZnzyfE1F3-t2-TDwkzKM_Z<#hdsny{UUmxyxf))!qv1u|4FAl@ z@K43b&<*!xxfrfQfq@Q&LUB9`?PFwMrF)^6&?hvtZ{Y&ZA^t*Jh&M-m_*&6fM>#!U zVH{9mbpQ#W460MtU=ET4Usi&O?0=ti;H^C6tD0w zv$^&)9aJcsxj>9gF}9q@kg3s=5XgM}4qkqo9Wj-RZuZ5*yPl_~D^d}FSTdv0%hAwuizY0bIIRML{(HppRE=J_cW{Z|;QloG+13`r6xO+tbV8uzc| z8DcRIneuwpY$@nUNK*WsR$}_2`E)NFv8p;EYIY4xqr53 zJ~_eaZ*bSmdR$B_lh@Ik0?lcM}{R@wzvKaDd8Ii}Cr8|V@c1Q*;GGQ=~ z*h^+L&zyq+9UEhx0%x&`LJTe*?r{oU|uds&xnqozjuP3PF`sLhI+?P z2)1uCTI2Pwg~5HmI!)gALoU;##3Xr{x1tjlmJ#%}Lu8_$OF8VSXCOJtisq1Yksb&a zbYVPhe53*1MG!~%lKIWn;!);Sbbd?XI!i-r9t;5hL-#fQIPZ{b7$DXfXYCqxn+Y)` z{+1dgDk*=CGA^gVK6U=?UDu;f-(9iIU((QXJJayzy!O45%=_Jyn|D`kywPpU8pm<3 z*x}TYxws!F!tC+F59^0#Nm3 z?QoAg!&r3@ZoQK87w0A7NuJHOH3a=2@b?wYG?i$;tCs@d|{?CFE)`GT#!;BCZ0pYb-mq39x;CxZ{tzX>K(@pNJGXxx_W)D{wLvDg`> z?G$BZZzhp*ycm(>GVS4JbLsY^ zr7q<%+R1L~n94W^eD=n0I7_{v?Y26(pueM-6#~MJNx^;0G~q^hwKI1fZ(EFJ#q;W9O^xx*H!1JDttLA90U@do`LH$Q@`d_Y*YJw%3;;@L)HXoF4#Ykvp`BHB>Ehsznr zO4-6&<-CIPC=`!;z((HMn3sQ-WMw_WkBhq!+Gl!U!sTw3g~)4)n2H>pYrd^BU$Jj=sz8Wz1b&BteXBu*p5j!Qeyw6}-sokH*r?Y**oHSw<^zun_0 zRIEvDi8h)$Je-!%Dswl6qdw|JjAGwGU0AHGUl!khZh2h&FCoIFVv4%#+BpdY+_}5* z;><03E1g@|7t8Qg-Ra6==}! z?GwKy-^_^Q*0j-{pTaMtx9mhJOyDkEoTSYr0^V(~IcSS~V)1um#^{Q9to{p?Qlq!}&ZoNK91rbz;Gi4IZr6Nmyg8nTVpc-9t!{ zmiXc&ZW`S#8!ySIEUY+n#5*Cq6HVQ@e>`S~75gnL+kC!MvL zaWS-5>#i~76ooV$x!h|>=BY`LesiW3O!K_&AfMDBY0tDd%x{$)(M00x-1gwE7!L;Q z4rPlknPRX^JHzGl;ACPz_;Y*N#2X~rcJ)e~jl!-n0z|*K^VH706=>7W)BL@SzxEpU zJCC+n-p(`H4*bNUJ#`-GEntbvx2In`Qn&Xa@F?J*1Q|Et)`@)pvDuh2@j{?>ow^rr zPTvbG2FkrVXBxz$-Z@^m_g=%FRWl@|PO$~p@T`Qg{##aY<@SlYZeq$FYiMs5?Y8X@F=$}{)@&DMliTRk+a}&;{eAny zZ8ybl1UEtUrup`K^5HMzC1W0qvmlKx6PH$2oJ6xftT^?_PJDt>i%xtpzHNk+e~i#K z`=Zk_?WDE(qtMo;+yR(6&C9l)I|?HDgt9F}FZw`8nIe%8R;Zog$@`U^ajDNSa_pLC z7I0-6Xy2~|VOLQ)Leoql!b!vNot>R=PdGBDkeX4Y3JxUF=7+By@kK@z(ET_`(6wM* z;oRNnlveugxU^*Nw`48ooa$`D+(?q^eW)iEJ$}x`SEro_EIK|jd0q70 zl#{N=L{&E(4V=bL_bg71`PAYXS+|2LaknDwl3c{)c!kZi01HY;S=<8Tv@NYE;&K!h zr{t7(&oNdyA#onT1^+`u9yR~Pgqsdyz{u3tEl1h zjfA64>#)=)efRSgsp=MEYLM^dh7*P) zp#Y;hVaSvJpZ0ygu)6K5mR|g#)3%{{FicBDy`6|Fer|Oi@HSOl$~T+XVrJaksXj6G z$1ZBP1(A7$COhN$P5q4(Ppi`%2iVqKKEUn0+#VlPI@uEnPXNb6nOQzY`&JjKnt@qzHewOeNnZY;5!uP*)+*LAGP;>z9x~RSHJX0$bJbgTuItm3VA);v`|{ z-74wS+Y`^gf9s&mL#!nT1|}kCeMlW9aqRShm;=roW|8W7TT#9_@775Wo%D&vtdfgi z$zqq2h2?;mmE7J-G5?%I&IzG9K~hT_Eig{eg2Sj>65~dS#Up-QJz>6+muxNU5qww+ zjc1J&k?N$lD^h|#!E-s9*{a^9D(t-FBRY0EUW2u;CK0tM7i~DPhLjxm()(#?juf7( zsc;g#yYrbT0E2vAwSs!pSlbW!N=-D280jf0XWpXThdlPtVn!0tT0$ zkAqzQ-V|>rJ(;xrgzA)9j@+2oLaf(N%&(!JSZO<1VC$`GwS)upurtQsnfkoKmim z+pY1B8E|gp47Rw9S1^KvGR1_+;)MM_4ZSXMI@ntz75LTd4X7ucvw=1%v=x)b*u9MYw) zt1;hZq^$}g#o`o)`|NuDEnO7@MyH!7n#3Affg9?6!wot72{*(Kq}*Z6*<$j-`ovGs z3Aall3A-8@K5c>b2Ee+5v|kdeB`V2avKW1<7s|dp{orjfCXXRT1qypHZSAfJ=ui%)* z!lVKlpF?_JKB>Q^JMnth=)$AUVKR$KSZlE1Y2bn(d{sG3 zi{Qa5#3PJu2ZJQezWxlxRYLZ$05_*O!3ENz2!s}=kI2&qIr0oZMb@^p3nlX0bF3F~ zLW&E+yRE)B*QwZ{1X{?Y+GtheJ0M7dIh5SeM$E9O+&P9z+?{jtaov+vsJpWQjZDd9Db@QdX$Gh%T;j6AfFu+YhJ;B& z&gh$$ih3=O`xojvJ8C^?5KpvXnkwC}#RX&pQzR?En8r1wKrywd))Wg~mo^8eB11h_ z6($unAN6f&g}uE!0$yg zt}i5oM}vF1wdnZMI!r@7TpK;sh?DcNEm+kQR3%7?21 zG6og8*vU>TFz&q>!j=v<341z2r&_nf9qoAf1x4fpP3Sr?%xvscsq=LYNu{L~T}_W` zuSA7A&j#jWWfvXdga%O}wK>E@*!%EI9#boZ2sEB(0kIfJ`Z-2KP3sa<+eJL8igazG z1Atz?9i>Rzr*IOaH&Va>vDtFMdaYH15JHuthS|DDQ(0D|xPR0SQSUhGl))yQ@eyRb zxN$Th1wsgOnhzKBD5HA{@9lgVhg%}u$0?E*Ef;o`&Bd;piJTqR3(K$wQMQBPdX_dV zYogmv^R-}yX7JsZ7<}aols5JrWpQ9F`EBxdv&U^s>0dvdB+DPi>)H;qL#7j~8C6fM zX=<>UgelJ!u)P!-OsRrmaKG+jn7d=WG>>z+nL_;)>-~SJg{#a>=2|&EvREm#r_EH5 zD3B`r5UXKY&_avNI`~_mQ?xt$`fLYZe(83%Jhdxw&=5(Ivym{Mj*#q`M5ZW17M#)c zWuw#kwid{44l8u1H2s(QU1pz#MTZaG;AdYG(2o%Y-Ie#2S|ZjXlM7A&^R#Z$9~G}p z`&BM!O-tI&;Da$&Vk4{hmEE=bA~VI~$n{HGb#+{<=0^N* zApal+q%H4C@y5pT>z?{zLVo{$Lv-{i+E}Uc7fyM?YvZG3Se#__9*Nb@KyLX zWS^BADcLDyTVGe(CB25(;uyAFaZA*|NZ?B0_t7xOeJ~@GE(NyD)})X;2~J!3B26_G zI}$|_SAtuV>G$;9v~dZOEvat=FhcfT+wPaH7zj*HFHoF`ru+G8QVgh`d6RD5E}Y zXxXR@17F005I6MgnRD=r`i*8^hjvP{Ul1j!DOT2%Zb8XTR*fapsys|oQFSctc>U~ma|;$}&nAtV^byWxG|Ilu z&FGLM-ihim~ znQdm3N?w(qQ!TN}kDzGPVg0R(O7+hz6?3)vO7m2ap%Lu)UPh1&4f6P6nTM&(9))+4? z-4%&Uus)8y8Uq58_WT$Z*VZ0c@lYh1IVv(Xzp zG)CyDRX@+yP7c-7Hp&vk=LSjfQr4-VdCaw#glrFYm@Bx4_-2p-Q-B>r-C(2CWY<3` zFnk2vhzwSNnZhA6%T{Cp+Y(KC7Qbgj44I)kDaU3|NqD6emr{)-M(D$O!Hl~$l17wFQ}&V`9MGk2TdF#pNob>+ zsL(_poC@s|x=Yrr!~DEM!@PqV7yMb81qPb9hf<}9U6WV7_NwIAWg7QVxWF>TDgpv z$nb5%M2K9GF7|9zOD8SP6RM4c6nYG5oAwsk>{?WG^HV&ei}audx(0<)^IuVJKlDUJ zqQ6~Kq-WFsQzjCi8*hU_Bja-RtQ(q)Vp45VKEjP#Z`&I=ZHlS(W)`N-x$m-i$akW7 zJ*{I)0YvaFHz8lnHrJzL=1^a?4`C$loRP(^{6k8_o!QzY*4ixuyVW?uY7JR;C=Bgn zqsmk;WL0~+MN`)FF93S|IW<>!s{ka5Mm~~T+2pWX#@N^)<>sS%eQme~>HiaUA*K2^ zx^04fdPkfy0tEL_T;JfBm zxfqO5DItsu>E!sPfwpULyxlU}<8V3XoObRH;%XePYUpg_>b*)kELfIw_o6O_5BroR zfL7mME`m8EaIYpC>wa#u$VAPThsV~G*W#eCwLDxdjg~nDM>(g-)bk-Nb3b2W9MZy= zC)-HgR>JxV%!WTRYCE;gpQcf}&rBVwK_aE7)2^&ER~t8!_R;z?OSSZVkvQ*^^C&(3 z%u+6Qq_nEcR36Hu2tsS%EcDB z4K;EAuvndoBdxTmEI9zZfW6u1uyK=CB)rWjKF8RYLm9iAn@zTqNb!WpevyXILxC6O3 z_W&nT1rD*HhtdkaYDqON3goV^*5~fH?a;VXjN$Jd%t~bk6)l@;T`f-pxcOXI?kHuo zH^Kq6yy5*Nvg%+dfqRME*0s-J-2!g+f~BlhxO3^y!8Cej>d>LE2{_-(;q9^7Yfnx< z>)Qs;lX0F&T;ohdAltvw9T?kShSQgo_I+HsYc1f=)2Pw+QAT%N{PR%^h8!Dj%;hiJ zY;c>M`sUC3dGrO%ANdw!)`cE}gvHdp8@5pEdCwft^b((JOyd$a@f_L4Ovsu4Wqzx4 zEt(V9#5*P22Xny-3RfmIDd#cXty2}rT}G*(FlE^e>fG5;W>4UR*UnmGhCuPHNzRE+OIgP}a=WC!jtlfmET8j1fl2@IE?=b^K} zBs1YR$m!zX3SEPr*5&iM{B17Xauo76_~-m&g)pK2t9sry86=Q@Q!+iS7UC`WLoD@HRR_yFLn;IH-Me!f;t!e7foz?N5GZXw(sY-kYa_q-5#nf@gFYr1pN62frRIhnegJw|6zJ1;xL#uC>~LC04JdI>frhme@}M z&aXvfa@w?huaG12ylvo$j%ezm=gvlIJ3ud5t+_*qb=15-8%^i0dh!_l9wsYurU*Z9O7Krj zhfb&L@{tWVth-V_(s}{U;D}gUxI#;l{03r%K@0w5aIc2wv%TYFLnMs+-=ZPPjJ^|u zbi*pli$1!4=UDh}VsNs-rzmPNc$Mp_2==WgdpTSGIvL*$rbPYN_xIf*P+xJ;&jEN9 zJ?i^=5p?Uz8U1`GSQx$A_xGJ5XN;A7=g#a(d%TT!KTr)rjUFM);S>h8zBE%7@C_h-elE z$|b8(&L05C|Du8gqtrBkQdaLPsZ4wON{155nn(;l+kt>x-0eT$oG$urB;9`!b%NKZ zz*@S3LdR2ipr$YGrgy998$$IOY5FR*VcR-Vz_I$gJ5}GMfQ*!MmsItQTolNtm`EQf zREs{k*S81tf=@@izUrd9HdSM4Q4YH$#IKcMqCP}bft1;)?dz+e+h>5{g3wKCH|RDZ zhgNieN{8+Fc@^`BE@w$t9Sg4~%cZdp>?>meet3RGsDPr?jrMqGes)R`^bb zj!vOxb?86N#yKLQxg#1bKDFf*Yo>u!=dWVB*hakCds3aeDFF?(cNjxY~-T6jv*Y9ul{6;D<41{8=xHrg@-Z6Ri%AXH^1r+r?^+*2mJo^-;jPjeH4e z+nqH{#OS>$oUibEO*#Lr5&IR&tV?DTV!KFa?-sSgQot*ul!3_YG%kbC+dX-A2=40t z|0{|IKP067VOu@#JH_px3D;%8kEqtw_`U}(UUi7r!RLA*Pq0^* zc4sg421*OA1e;gjvG_oJ+H#;u6KI96td@LEkQ1TSK2z>3>H_x)C(ntlUik|yDua9> zN2(*CFXS2yLLP&-uke7>$!(;s^VhdKp$BB*`MA{ptnWnKZ5{68=pFA{HN_YE1DuO! z3Zn;wW_c2^I36>?YwS$z+q+cJSZ7XYU)(~_Kqb&%r@;&&xkTe5D7|O!RK`8sQQDZa z8X1p;E^{b9ZJM~qp@<@EvxJIShz}muYubiE7@9=$EFT6jFIrvduqKKw7p38F&Fi?4 zv(W?3-+2pPGlNUK1?f1}II7I%x*mfT?M)Dk@D!J#Wt+~?q|5EyL21SGs|etm4j};=T(rbO2IHy1}@&8yfcCo=EQ5>@5UJM0!tZ>e3iK)%Cjvl3wT{C+VJq~P( zOaXiD>r2`jLmDpWJ9qBfXPTxx?fMMf_0ixO>ah1aEZlx3n^btKzaT-=Xg2*|*NtMi z2oq$Ba1uyQDUNg*TmwT-N7YTJ$9K)_d~t@AL2ll)+L_8pm=|HO@AY<5#GJS-B$XKl zKvHo}pDJ^h(V$J3DIVOP>dtigqMl}pz%Jr2&CIpxm>vneWOvpayBpZMbfUHvG#BTO zz)R7QXup|b69f7%1ngAhrpoCAuuD^$2*1rfFx@f=*X-D)B&KrQ5_J3ohv|7b&8m+A zDWWk9KT(&N2T>W?n$+`JTv-1kfD*7rgaBMUAwHdz-{^wd1xC|hcI(p}ZO>}6iJjfH z)9tuaReoBA#g@PVoCcf0m|~ioPab%(a@Vc5*|hXfs<2x)94aHVvXAO|pXLa6Mf|*p_Nsx@J ziBvq-t4jqi(f0(n4&JJjeWLgaSDu z2H(pimRj=s;O&fJ1nb^*ZFDkcEsD)ioZ$!^BpHSs4mv?jq1U-1mNa+8669p~ssq~4;7Kuui9 zBH>Y9!Qnbn}F!jL3pt022y*~f#d6)f$KuG{d`S<)iGp~cQl2yJ7=+1+w@72`!CpEQJiK;{2xn}W}jX~6;tP__9O|3s+OKU6AQsSu8C^3$w#IFxV0QFK8%1j=C5;s_z)G>`}y|aFdSbZ?2UD| z)%GXSMaZ_BUjE>81d_ngee|^!hBP0F9Z`G>8JAB+xsW2LrbYTS%7}cIO_gOM(C1#S zvH1JyM!uk}d6-|f8jSD??l8|Dd}o-Fh|9O}L%aB2phK-Mz`&{+9Z&;8x5O6Nq{MhEa|7q4i@^GI;BF`Y%)$UlswBv~Ml#yv+JmtRJH8 z)~DBS13sZD6IKOR+OA6BmxZQGQy4>d0pTWrQRpu*J}C-qNTvtBDLCB@ls)Ut z$_3>sD&K~~{ES|r_UanhGhryr(kg$Y;Fkr|d0j-&Qmc#k^xFbta2v?4D~t82U6MuR zFH+QB7u*_j#p+>G5laY1#1<`notBp(ON#Oh>`&pToeYbUoTARJ2Ul%Zn6};M+~sy< zIXeU2XCaZacP~%cUF5R!U%cXLY%(%RsilP-WDdU-E>v8Rg-j|>8th9q>^FT)MMpAJ z>Xp>GBJCPR6D{WL33K0C+K04Dgkq`q5=~sI=cOd%QrhqoD<79`PSx-n8j~oVlEty+ zcYj!=f%DPmxO$iQxRGXwx6CRweBV3_{!nA|N4i|l#Re*-BSIbl6xfl4d_$?Rg&LXErKdxsClOy=Rkraw$87^P~^B7yb-^H~y3CanpL z6<>;5Ok@uQqEVQKdHkDDzM|R<>dm%vgbGIypszx`YFgQ(JdtAQWK$}OgSsmAlB}J2E`V$i?~~fNsPEW7a~CZ zf9BAEa$gKccYT_U($MdwC*TO${b<46-d_(~Rk-F`D}YoV-LHZ^&I*5iwN5$An`=`Q zUOk|~aH8OU7}Uw0B8Exlat2UlSmlU_gYO)Rt17?BWtxK%0lHTQPZ#axUqG%39I8ZdRVyRs8)9n`=WXe(AG zjgFC_K^{kYQXTbfeU5HVb!87<@?CR1x(sL|uc1piAKi61&_<57(a_oP;o}JjdfhfIiR%>aZRp^C4;M&(amwt6Cu* z{8Z=&1u4;!;4V^EpCR)7PG-mepY4Yh3B~qZrqmB5ofP_P$F-!Wz^Wd!U!z$Eqatw8 z*6*Gn)bL3zvFTXh#&JNAn>K3L94RPkmvb|)-^};iZw(_mN@FYs7)R$sCFf%sNVL_? z?6sjqM!cWf(v-F*#yWI+d{q4xa|+lj4j-Q4HES?@hdXF;TCUO3Y3pO|IE8KG~q z+MD$tXq^O{8x=&YUg@x5x!E|e7+Qt!H@}#rTIFGk@q>A+54>&mQn;yU;>Nkw!98PS z;+z*)tTr1`j48uPk+4SiyB~#VA{d!s|H-I!lJ0w^jfn`;M=y}_fbtXv47loS2s^z5 z%}@agzl-{YF5r;~HMQLd`Ju14~S`!5rTKrQL$pYs|w1 znqQaBqEnF?;T;CJVa1NrkUSl~fg8ZdC@d?0zu-3;b{>rj=~nMGT}z$M*v8lp188+6 zRmoOn2cgC}BQybX(y?0`P1 z!vH;%ngktxPG`X|1OtjB9lN|ZmM|V@+{S1MqzrYpxWm*e zO=wWU09uL3WL698xKeOPXE8y}907cQ<~4m%LN{HGJ~5)l85vP6wggyjOabOTUf9L_ zl*yQbD9uJ*hj1yNqjI{Fk`4V8+mo58c^?-hxc0E|R2~&BE=lMs0||%nvF*MM9TZM! zhC%KO>nV;i8trhFxTK_UhY#B}Oy_od2>5t6Ok<#wV1N=(RA;pcSuMJ{1)!waafvKF zi$|iNP&T#4XO|vR7PnScB&7kJ_Wa;0#lmDXQB7H3n_%MzQ87EG!JW9!lL3)5}v6ZPUjrdPjH4#4{f$u>WM zJKk5>g+?IQ^I&KfpAz=jV%#Q9Yc%Y^983dhebb0N&wXHOv5)C4VZlr!5qtHBm=V*$ z?cSK3CZXpOi*1*dj~y!mI}?9&A4?Xh`fY8FTaLJ-Og8xXMY*IM6diF%vkKvc*KEiq z=?KS|Ph!^zZW@kValA{KX9=nl6AbF6!#wzepovuUBX1RQ94w;#x9(>E=VAU5)_8T9 zS^VBo)a3-E$_GEEwoyaRCm;T5PjZv+xDuC<0@s^;Da%$9XJ0CX_9b^jC+>#WpyH#R zyfJSbvLW`V0(w#S#SLr*h(WjN1CLrJSFoWPyGQw&k+;ti+Fl8c^0XhRW=Z?aWbBqU zC6&=fp?OF}M<2D7{Ep*&iW}#lVKKL}E^5zm&Q#7s>LHE~Y1(JZICG->n^@eu!W)WE zggZme(_*-((K#ZR$HCIo7eRoDso-I159W1g>aw6q-<&y2+PBm^nOPKhNe2FnZ{>2i z@09Z4!H0$vX@r=L##8TTvc(+!1V0RS!)SMJ<}Jb$zfcYnHk5XO!wUH&t(4jsoZyup z(50hGAAGWB{GQ-*$SMZ}Yz|kX2SFi!&5%2-85(^wBmzsIwr}C$EQ*RJht@yGKxBj6 z(pq=p6yosjg!{QHzc#{ZMN6fEg-MwdQAqU72?NB~n9wr$xy?6{O^OA=p)I1lO( zq5~4sJ$2ws@O`RvkP_!C5B^Y98`||(x{Akv`e8rc_HHhqWZz*x)*lKiMK~~y1!7>N zyp6pQA~Vs?)5XE}Q$pbD@=0C#M(kD6E(kiMyQ6><$!lptddzD62_n8`Cxh2|OGr!; zs_7dlMu>^w=cYoAI74Nk3zeWU2FF!AndaN`Q9JMF+ZM|Ak{XQJJzG&M&TC9;`p=Y$ z2o2T&?SwazBV$_&^x-s7|5f^j!xrmkJbCHXb29d+_>=2HzqiuM}5OFOU@A{PiXMw z>}5@#6qJLh*Z{!1EJvS@fg+m4Opz#l8v8l!Q}*B?T?85M7;F{}F5FyF)5AX4UIgBC z32dAVo#P;`UfAfhFld_Uh(5a4NL#5(Z9Zt# z5Rrn0kD>AkL1dL>m#*%ErYB<$y`kV_B&Ggw+`;EF+VXN4o9DNsYV9ANRp^MSv<|=` zUV(x`np8VS4`O$ z_2Q~QzEsu0U!_R{YaGJ(p(3wORk^vZO3Sc%oo)ys4O$A_m#({{KHKf&zi+@G>?3Vw z3aD%PfQoh=MS9^&%*M9^UZir~HSWNBU;uc+^BXS$UR1_v;E7AIxuU75*q2(~q;GUS ze%Zjt>SqVke3-O7am@n>l#91H$vN6amk+8GBZiuo&Ok3x7kpC}F%IrvIWyJ&PfGg* zUH0jLV05z1dzE%rKa=TVcP8t6gQr7+N{a@|V-9;g3uEs;;)W>S+d?I}WITW2KOvc! zqO84uLMYL!Ab;;@`*SlpXL_o89s+-h^~AM}nS$U%CLczc10N}vc{ zr>k73i)gj@PH*p9$BXH>HAaVZ)BNoDXkOgU*G>-Y7b@$D+6TC|<-Uv!!<66pB@8%-boRWp%DV zL;JRL28UBEzjknKjFICGE)wSCZ_?IUR1`)U{q8|Ajbf3njpPn)E=T?FTfa*&`{JF- z;RHubj86oXGPcnWLK0 z&TRg8>xG7&9LJ9CGAVn2LKQa|$P%IF+<041skma5s?TZ8L2-w*_dJ?s1DLC>Cs}V; zvG?wrLTC1P9rp1QhkK(L=UO;8nns2bRFMZgF3UZa-d+Yn(|Ndmt zoRU*}8mWc7H>N_3_QttG?@g~K&3rxXz^FF2jYr#40y>PHI&l*$Oi;qBsSLf2N)o~^ zeTofEN)Pu@@M3kP(%%qH3CFb1W;Sfjeisnz@Y_bP7;cOvaZ5R)ROSyeRn0fBa5ay< zZTwmtrNH*MCJmTA4w2X(6yqBvn3O}1^863RDuJL+aM5Ayu1PiGWIViMo3p{+)_`lQ z)1P?pyR?3loi9=ENLKzXQq9*RQpaA5Ej^XQ#Bv34ic#Co*IZ{E_4BeaOV4t;MyPz1 zM`Bv}`r?^h?OV!V9C=MkU)?Ru&_1YxiNvcauMd;;4MENqwFx_Kq?O&?5C7#TW&aLC z^I9}m=E$U!;1_lITZ4uzuPXVpAK}u&v#c|xu`Ha6ivm;(qX3o6XH)yZ%bb+s&c-Q+ z`@x4zHA^Vc@%8Moc)Wi4h#!sgcU?34*HUA>wYRRpdX4|Lx3h_jn~36gJodV->pHHp zxakLwk~R$?T?DQ8C=~*vBB)3}^aespnt~8gRWT_CC@3mlLIP27J|Sd-R0A6@eX3(WlS>YvREUF2@xga&sHTP!-sqZrFpPdx zm+;I946S%4fzf(X*Yu!VA$h182Fh5gZ&+kx%Q}3^pN@?^q2CA__0q!Zzs-1~F8WpB zP@xAU|3QLZNSgbjemDF7I=QSn^a-}t_a-U+s1*JfN|AkOib&`7LT#7yl5)};Up^}x zeOrIM(pfsS?3Wa+Rw<>u_p-)Bv}U*T=`wu;yU#Qm-vS^}d_`RGS?XAIyS-R$%cXMX zzeDtx;H9E#2BFm_Q;*A5Y#u}QIlw%ee-2mx7J(Oloxm;t=E9#OM4kD0;1Ix5?k@sg z3Pj&(jklM=|7p2|J9Fk8Pows9K>Sz0oxl`uH*gm)16&sL#usWUVkb2+z`v>AkLVsm zg_gwk>#0jUT|ssgxDFfyW(DFAm#_lb%bTk$Xfcxt?GGS~80Gk*6la<<_5t?;M}UWc zZ-L!J`IXRbzyrYVz@NYz(!U7pCq&o69|j&YDR3|FIMOEtaz&6 zUqpHW*h1vvz|+7pzq&8DY6 z!tQ6l7r=+WN5Dk@;>rx;)=CM}9J7V*lL#)cdl~4joU|GF!OV|m2=5tpSYOmewca{9 zJl6KGdD{Q&9?f2ItakKDWsR-e5TfAF{I^P}IK*KQYr1J$a!771Ld}YXRXdG%#bcc} zcX2c&Rfu*_rBUE+CPj5PjWWebb|x)tkt8M=uR3WcZR9A9i#?5Aa!AZdK5nA5IF+`I z_A*x$F~{9Z&<=OkvJ6R%mf~7WSfOFbUd586WmgT8R1Dxmow`2nE{V#ry*jq9P^efP zd#aq}YDp1UK3z~I((-XCVH~@BUge#a!nbobqbal^;}8c!)xrFsB+q7&q&!tlw{_gy z4!J^gkOi*Zx@0n$B#CVWOnXIy_Qnoj$th@kH+0bkMk}P|vRHcgR?7Yf%&h6>x83IZwQHJc>kNZ0J z+;hJ3xNsL1Y8rmO`OaJISGK18JG~Tt7G6HY75@o^(1adpEp^vhI=>q&gYRa`NPxaQkD2eh5tyLElQN?}1pX)5P z&WJft!`sqFnwS^$7n-R1M(6Bvv$c#b3t|yp7X4+spA%=q5?Y?e_p`#nck8*)x*+sN zT4VVYDAzU`#w!!|R}~ZuJ)OTVg)e<^H}I0wdf+BIo=)wuA3c|F-N6+vqe!$PJuybw zb6x1dI5sh`>HZMSYBqi!1$%zacI`gKvG)TMe&~1oUJ~1}-*=^(_`+@y{k`akA=UjaFCM>tdzR;M%`mX|H^K zTDx^LT%WXD|C*-Ma=Xx$rdYGTZt!+K@Tv39w0K3#-DsHUT#)!OiJ~x0%Rw9lo}bP+ zZqM`ML>|1MG|MO>e-rM}U*q8C9+v~aU=Iws}uA8`K|Nq$PUCIMxsGEN_hXZP%oyPcT-e*P5PW5MeExvNB{kN6L~s8>Lydn$kax| zO3M;*6ZF%$T*FcmDwdYwei$STL(XH@QY&$TkVQ%r3-~DKP<$U(Tt%TR)%8Watn*io z<$=E9N6!R^v#6jy*E_V=22epCwpb4zLf~Z2hKP4#JLuWnpf`Zr*}W*C*LcuQq`QMJ zYqs=3Q!nT}wIc#0?#>``fAwa=4x?yy&~NhBh9wEV()sNmgzjv+VeHc)leF$QUeu#; zV#jG1X(gL4txaZ{S#>(^h+umgCvy7VKlBs- zZXn~~E-&-8-3t2mg3u>6d7&G}3J(2VJdl3&5};cESQUZvy(E%>A9H6wD6n+jJs`Gw z;Xt4b7@q9-cF*nlgrSO=Q|e92%K^WMmqhF6M@C{M7C@hroPqy^Hq!56sfR{VO3EWL z2*z`=GUmqAaAUNHiDQ>hjI_^}4)u{v!(L*1_yT70k@ixDWs*y1AqXWzos1#aR2etl4+$6JTg|**qoQP|*r4yT7yzY9#I-oBWM(I=xG_&LOX0#40iS@txJ+ak%h0Cb)zfKx zjd8ROv>&mJA_0&Rmye8Nz$h39MLV)a`Z1L55*R4Ig+`4Mw47*`SMios#~YnmwB2%r zni#1S`{A~{h8Gx@IVcQCmg5v~pno9Egat#Aqm|CH zqGk;~pf3xV@_K$4jun^{isWCiNhcuq2p5xG)vc1D*GhG(YF2B8&TR5fJM}ZOx0psL znm9IVWaO$Xt6<__?qJ5s(4ul$yXVHq&)HNDKjp1_-GoK9GGI0%wHGAZj^Nt%p8=jG zOq3)sl02OB+|=5X6INIp!Pbe3qly=}rWbd7(QLn>}l!F=QK@6s#t zjSFTYbCCG^3>RBi67G7Ld43|l7~9@P>tRiqh9?jQ3ug7;ni2;U*Onm`kF*=WHZ}_Z z3+Fvx6(Psd}Yd zkBs<-xZ;09QPgK)AV+bX9aT83qDfhYKj@roFp;gOsB8lq+A5wo&w%GSJad)-&ow-s z70c|*&g1!D9&`XbMxfyNHf;|K1MgRyWfks3y*Pj&z&4JnRQ@8_36Q%;ZU;g2%FaHt$ZMT^`Q)oslzWVaZ?0cK(qHpw@wD+dktGaO?G1X_f&gXvI zfbt;%2>|;8JBXS;JxKicB8$xx%ZPZ{*B%RF+i&v=w(i!_J#dgho2{#yPU0vaI zP@u~2*Gp`~)b44G+v~iHndaW<&BZ#?KhwdV?vQKK2lh(W@2k<6BH$!1mwb$gW=^sJGD7(IflY&~4!0Ys;vOOa8cOY%^qp&62wZPmZF6OnB~Qk=Fr5xvHVPs$wqk_cG#G-ZHWpnH+6usdp-CVQyF?3BiBq_fmI+4&;h3ea^>prp9dh|fQP;-Y%;>dDVq{s9r~Iv zt0<~oMm&2H6xC1lUXV)&6yc`c3RRO@?`Xi$u~6Zz7END%fz zXV9TA2^^aUW+76MI1No|x3-vvnI}cW7IdX)Z$xme@g+vCVC>T1!6N}y9`S<C%>sTb|v zd-fCL&v;+65DO;D?I~ZH04N`V-Ig`xI&}s_+Q~s5Az8lkhT7$}Z+8a>N02fi*Cy`~ z_kAybKn$q@J)7fL899~^)^k6IAxqRpRS_lgN546ZFj5?tMycuk72hXHSpE)X?p`winoQmdD%ri$+uWyhJMDs+4AD>Q% z2TB$Slqe7w_xlEEv0|K#oK6R2oz52MP%=V&{%16F%wrv?Vy#m;1~RDBM!B#r42HBH zX_eePk{u;8Cv6Y4yHFrTF=Z@QQv^}mNzo~TA;s_@0bw=3O3%Q`Ah7!VW#nc}N)(@v zt9iGWtD%E}hOxmw@zP*@N-c5(0rsq#o0vp?jsiLEM9wN;I+r_*S7-%9pQc~chl?y? zdF9k1C^JfnV9k3M4}|Cf<{V^WA*YbNdIH(0A=`2rBjBKesolZz3`V3irlL(@+_xt* z!UCO{(8#s9*})*3_a?K$M81Is<#Tk5BlsG}?0bx#cX2rP5+J-gcr%xQG5_+a*GMBqGii%>ApSuR$Rz?PN*WE$z%m|>XJ>L| zW-mE7`bm(j$qxo<%oYATwQFcHal+2?tR1bc^_NKmk6?pY6GBvAKAI}6;s`RPK<7kI zdWm)9dm$8>mYN}mkg=Zt z;y)Cj1L2N!R654l)uE2FLakH5@c|tX8ymy(cii4e!hg^K^KC0nu2EHN`2|tW-8)bv_2I%Dbo*7a-4Syyj5gm6|a$z@8}{1rX7XW0DFGRnaK?n8=P9q zJ0uoJ7~-f3tcfH}iB1$L__ox>aeh*uVC>ndnkf=!dO{UGK3Ky89om8n<0(!b`4Gq; z9RD4iv1v!_v>sJPa7iX+rm6rYL1)Dn-cHI=7WVWVyk?GhT8bzJzzG->eP%bMk9O}9 z={ayK;>Sj7ig*&v91<07ceHpB3CH;!a3FiBPxn` z+TXOSqR0Yr5@_;r#5vndfK{ZYV zDbQ$KJuyALhbsAi3i2z{>NugpZk%jWg-3;;f+&{(6}wcB;;0Q^{OQvx!x5d+%K;S> zyfDWhUk(COANe214=tduC|(`~PVC|RGall)pOO0Wvg0UzPWU+I{#nZNqN5j literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/__init__.py b/venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/__init__.py new file mode 100644 index 0000000..292e0c6 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/__init__.py @@ -0,0 +1,1047 @@ +import os +import re +import abc +import csv +import sys +from .. import zipp +import email +import pathlib +import operator +import textwrap +import warnings +import functools +import itertools +import posixpath +import collections + +from . import _adapters, _meta +from ._collections import FreezableDefaultDict, Pair +from ._compat import ( + NullFinder, + install, + pypy_partial, +) +from ._functools import method_cache, pass_none +from ._itertools import always_iterable, unique_everseen +from ._meta import PackageMetadata, SimplePath + +from contextlib import suppress +from importlib import import_module +from importlib.abc import MetaPathFinder +from itertools import starmap +from typing import List, Mapping, Optional, Union + + +__all__ = [ + 'Distribution', + 'DistributionFinder', + 'PackageMetadata', + 'PackageNotFoundError', + 'distribution', + 'distributions', + 'entry_points', + 'files', + 'metadata', + 'packages_distributions', + 'requires', + 'version', +] + + +class PackageNotFoundError(ModuleNotFoundError): + """The package was not found.""" + + def __str__(self): + return f"No package metadata was found for {self.name}" + + @property + def name(self): + (name,) = self.args + return name + + +class Sectioned: + """ + A simple entry point config parser for performance + + >>> for item in Sectioned.read(Sectioned._sample): + ... print(item) + Pair(name='sec1', value='# comments ignored') + Pair(name='sec1', value='a = 1') + Pair(name='sec1', value='b = 2') + Pair(name='sec2', value='a = 2') + + >>> res = Sectioned.section_pairs(Sectioned._sample) + >>> item = next(res) + >>> item.name + 'sec1' + >>> item.value + Pair(name='a', value='1') + >>> item = next(res) + >>> item.value + Pair(name='b', value='2') + >>> item = next(res) + >>> item.name + 'sec2' + >>> item.value + Pair(name='a', value='2') + >>> list(res) + [] + """ + + _sample = textwrap.dedent( + """ + [sec1] + # comments ignored + a = 1 + b = 2 + + [sec2] + a = 2 + """ + ).lstrip() + + @classmethod + def section_pairs(cls, text): + return ( + section._replace(value=Pair.parse(section.value)) + for section in cls.read(text, filter_=cls.valid) + if section.name is not None + ) + + @staticmethod + def read(text, filter_=None): + lines = filter(filter_, map(str.strip, text.splitlines())) + name = None + for value in lines: + section_match = value.startswith('[') and value.endswith(']') + if section_match: + name = value.strip('[]') + continue + yield Pair(name, value) + + @staticmethod + def valid(line): + return line and not line.startswith('#') + + +class DeprecatedTuple: + """ + Provide subscript item access for backward compatibility. + + >>> recwarn = getfixture('recwarn') + >>> ep = EntryPoint(name='name', value='value', group='group') + >>> ep[:] + ('name', 'value', 'group') + >>> ep[0] + 'name' + >>> len(recwarn) + 1 + """ + + _warn = functools.partial( + warnings.warn, + "EntryPoint tuple interface is deprecated. Access members by name.", + DeprecationWarning, + stacklevel=pypy_partial(2), + ) + + def __getitem__(self, item): + self._warn() + return self._key()[item] + + +class EntryPoint(DeprecatedTuple): + """An entry point as defined by Python packaging conventions. + + See `the packaging docs on entry points + `_ + for more information. + """ + + pattern = re.compile( + r'(?P[\w.]+)\s*' + r'(:\s*(?P[\w.]+)\s*)?' + r'((?P\[.*\])\s*)?$' + ) + """ + A regular expression describing the syntax for an entry point, + which might look like: + + - module + - package.module + - package.module:attribute + - package.module:object.attribute + - package.module:attr [extra1, extra2] + + Other combinations are possible as well. + + The expression is lenient about whitespace around the ':', + following the attr, and following any extras. + """ + + dist: Optional['Distribution'] = None + + def __init__(self, name, value, group): + vars(self).update(name=name, value=value, group=group) + + def load(self): + """Load the entry point from its definition. If only a module + is indicated by the value, return that module. Otherwise, + return the named object. + """ + match = self.pattern.match(self.value) + module = import_module(match.group('module')) + attrs = filter(None, (match.group('attr') or '').split('.')) + return functools.reduce(getattr, attrs, module) + + @property + def module(self): + match = self.pattern.match(self.value) + return match.group('module') + + @property + def attr(self): + match = self.pattern.match(self.value) + return match.group('attr') + + @property + def extras(self): + match = self.pattern.match(self.value) + return list(re.finditer(r'\w+', match.group('extras') or '')) + + def _for(self, dist): + vars(self).update(dist=dist) + return self + + def __iter__(self): + """ + Supply iter so one may construct dicts of EntryPoints by name. + """ + msg = ( + "Construction of dict of EntryPoints is deprecated in " + "favor of EntryPoints." + ) + warnings.warn(msg, DeprecationWarning) + return iter((self.name, self)) + + def matches(self, **params): + attrs = (getattr(self, param) for param in params) + return all(map(operator.eq, params.values(), attrs)) + + def _key(self): + return self.name, self.value, self.group + + def __lt__(self, other): + return self._key() < other._key() + + def __eq__(self, other): + return self._key() == other._key() + + def __setattr__(self, name, value): + raise AttributeError("EntryPoint objects are immutable.") + + def __repr__(self): + return ( + f'EntryPoint(name={self.name!r}, value={self.value!r}, ' + f'group={self.group!r})' + ) + + def __hash__(self): + return hash(self._key()) + + +class DeprecatedList(list): + """ + Allow an otherwise immutable object to implement mutability + for compatibility. + + >>> recwarn = getfixture('recwarn') + >>> dl = DeprecatedList(range(3)) + >>> dl[0] = 1 + >>> dl.append(3) + >>> del dl[3] + >>> dl.reverse() + >>> dl.sort() + >>> dl.extend([4]) + >>> dl.pop(-1) + 4 + >>> dl.remove(1) + >>> dl += [5] + >>> dl + [6] + [1, 2, 5, 6] + >>> dl + (6,) + [1, 2, 5, 6] + >>> dl.insert(0, 0) + >>> dl + [0, 1, 2, 5] + >>> dl == [0, 1, 2, 5] + True + >>> dl == (0, 1, 2, 5) + True + >>> len(recwarn) + 1 + """ + + __slots__ = () + + _warn = functools.partial( + warnings.warn, + "EntryPoints list interface is deprecated. Cast to list if needed.", + DeprecationWarning, + stacklevel=pypy_partial(2), + ) + + def _wrap_deprecated_method(method_name: str): # type: ignore + def wrapped(self, *args, **kwargs): + self._warn() + return getattr(super(), method_name)(*args, **kwargs) + + return method_name, wrapped + + locals().update( + map( + _wrap_deprecated_method, + '__setitem__ __delitem__ append reverse extend pop remove ' + '__iadd__ insert sort'.split(), + ) + ) + + def __add__(self, other): + if not isinstance(other, tuple): + self._warn() + other = tuple(other) + return self.__class__(tuple(self) + other) + + def __eq__(self, other): + if not isinstance(other, tuple): + self._warn() + other = tuple(other) + + return tuple(self).__eq__(other) + + +class EntryPoints(DeprecatedList): + """ + An immutable collection of selectable EntryPoint objects. + """ + + __slots__ = () + + def __getitem__(self, name): # -> EntryPoint: + """ + Get the EntryPoint in self matching name. + """ + if isinstance(name, int): + warnings.warn( + "Accessing entry points by index is deprecated. " + "Cast to tuple if needed.", + DeprecationWarning, + stacklevel=2, + ) + return super().__getitem__(name) + try: + return next(iter(self.select(name=name))) + except StopIteration: + raise KeyError(name) + + def select(self, **params): + """ + Select entry points from self that match the + given parameters (typically group and/or name). + """ + return EntryPoints(ep for ep in self if ep.matches(**params)) + + @property + def names(self): + """ + Return the set of all names of all entry points. + """ + return {ep.name for ep in self} + + @property + def groups(self): + """ + Return the set of all groups of all entry points. + + For coverage while SelectableGroups is present. + >>> EntryPoints().groups + set() + """ + return {ep.group for ep in self} + + @classmethod + def _from_text_for(cls, text, dist): + return cls(ep._for(dist) for ep in cls._from_text(text)) + + @staticmethod + def _from_text(text): + return ( + EntryPoint(name=item.value.name, value=item.value.value, group=item.name) + for item in Sectioned.section_pairs(text or '') + ) + + +class Deprecated: + """ + Compatibility add-in for mapping to indicate that + mapping behavior is deprecated. + + >>> recwarn = getfixture('recwarn') + >>> class DeprecatedDict(Deprecated, dict): pass + >>> dd = DeprecatedDict(foo='bar') + >>> dd.get('baz', None) + >>> dd['foo'] + 'bar' + >>> list(dd) + ['foo'] + >>> list(dd.keys()) + ['foo'] + >>> 'foo' in dd + True + >>> list(dd.values()) + ['bar'] + >>> len(recwarn) + 1 + """ + + _warn = functools.partial( + warnings.warn, + "SelectableGroups dict interface is deprecated. Use select.", + DeprecationWarning, + stacklevel=pypy_partial(2), + ) + + def __getitem__(self, name): + self._warn() + return super().__getitem__(name) + + def get(self, name, default=None): + self._warn() + return super().get(name, default) + + def __iter__(self): + self._warn() + return super().__iter__() + + def __contains__(self, *args): + self._warn() + return super().__contains__(*args) + + def keys(self): + self._warn() + return super().keys() + + def values(self): + self._warn() + return super().values() + + +class SelectableGroups(Deprecated, dict): + """ + A backward- and forward-compatible result from + entry_points that fully implements the dict interface. + """ + + @classmethod + def load(cls, eps): + by_group = operator.attrgetter('group') + ordered = sorted(eps, key=by_group) + grouped = itertools.groupby(ordered, by_group) + return cls((group, EntryPoints(eps)) for group, eps in grouped) + + @property + def _all(self): + """ + Reconstruct a list of all entrypoints from the groups. + """ + groups = super(Deprecated, self).values() + return EntryPoints(itertools.chain.from_iterable(groups)) + + @property + def groups(self): + return self._all.groups + + @property + def names(self): + """ + for coverage: + >>> SelectableGroups().names + set() + """ + return self._all.names + + def select(self, **params): + if not params: + return self + return self._all.select(**params) + + +class PackagePath(pathlib.PurePosixPath): + """A reference to a path in a package""" + + def read_text(self, encoding='utf-8'): + with self.locate().open(encoding=encoding) as stream: + return stream.read() + + def read_binary(self): + with self.locate().open('rb') as stream: + return stream.read() + + def locate(self): + """Return a path-like object for this path""" + return self.dist.locate_file(self) + + +class FileHash: + def __init__(self, spec): + self.mode, _, self.value = spec.partition('=') + + def __repr__(self): + return f'' + + +class Distribution: + """A Python distribution package.""" + + @abc.abstractmethod + def read_text(self, filename): + """Attempt to load metadata file given by the name. + + :param filename: The name of the file in the distribution info. + :return: The text if found, otherwise None. + """ + + @abc.abstractmethod + def locate_file(self, path): + """ + Given a path to a file in this distribution, return a path + to it. + """ + + @classmethod + def from_name(cls, name): + """Return the Distribution for the given package name. + + :param name: The name of the distribution package to search for. + :return: The Distribution instance (or subclass thereof) for the named + package, if found. + :raises PackageNotFoundError: When the named package's distribution + metadata cannot be found. + """ + for resolver in cls._discover_resolvers(): + dists = resolver(DistributionFinder.Context(name=name)) + dist = next(iter(dists), None) + if dist is not None: + return dist + else: + raise PackageNotFoundError(name) + + @classmethod + def discover(cls, **kwargs): + """Return an iterable of Distribution objects for all packages. + + Pass a ``context`` or pass keyword arguments for constructing + a context. + + :context: A ``DistributionFinder.Context`` object. + :return: Iterable of Distribution objects for all packages. + """ + context = kwargs.pop('context', None) + if context and kwargs: + raise ValueError("cannot accept context and kwargs") + context = context or DistributionFinder.Context(**kwargs) + return itertools.chain.from_iterable( + resolver(context) for resolver in cls._discover_resolvers() + ) + + @staticmethod + def at(path): + """Return a Distribution for the indicated metadata path + + :param path: a string or path-like object + :return: a concrete Distribution instance for the path + """ + return PathDistribution(pathlib.Path(path)) + + @staticmethod + def _discover_resolvers(): + """Search the meta_path for resolvers.""" + declared = ( + getattr(finder, 'find_distributions', None) for finder in sys.meta_path + ) + return filter(None, declared) + + @property + def metadata(self) -> _meta.PackageMetadata: + """Return the parsed metadata for this Distribution. + + The returned object will have keys that name the various bits of + metadata. See PEP 566 for details. + """ + text = ( + self.read_text('METADATA') + or self.read_text('PKG-INFO') + # This last clause is here to support old egg-info files. Its + # effect is to just end up using the PathDistribution's self._path + # (which points to the egg-info file) attribute unchanged. + or self.read_text('') + ) + return _adapters.Message(email.message_from_string(text)) + + @property + def name(self): + """Return the 'Name' metadata for the distribution package.""" + return self.metadata['Name'] + + @property + def _normalized_name(self): + """Return a normalized version of the name.""" + return Prepared.normalize(self.name) + + @property + def version(self): + """Return the 'Version' metadata for the distribution package.""" + return self.metadata['Version'] + + @property + def entry_points(self): + return EntryPoints._from_text_for(self.read_text('entry_points.txt'), self) + + @property + def files(self): + """Files in this distribution. + + :return: List of PackagePath for this distribution or None + + Result is `None` if the metadata file that enumerates files + (i.e. RECORD for dist-info or SOURCES.txt for egg-info) is + missing. + Result may be empty if the metadata exists but is empty. + """ + + def make_file(name, hash=None, size_str=None): + result = PackagePath(name) + result.hash = FileHash(hash) if hash else None + result.size = int(size_str) if size_str else None + result.dist = self + return result + + @pass_none + def make_files(lines): + return list(starmap(make_file, csv.reader(lines))) + + return make_files(self._read_files_distinfo() or self._read_files_egginfo()) + + def _read_files_distinfo(self): + """ + Read the lines of RECORD + """ + text = self.read_text('RECORD') + return text and text.splitlines() + + def _read_files_egginfo(self): + """ + SOURCES.txt might contain literal commas, so wrap each line + in quotes. + """ + text = self.read_text('SOURCES.txt') + return text and map('"{}"'.format, text.splitlines()) + + @property + def requires(self): + """Generated requirements specified for this Distribution""" + reqs = self._read_dist_info_reqs() or self._read_egg_info_reqs() + return reqs and list(reqs) + + def _read_dist_info_reqs(self): + return self.metadata.get_all('Requires-Dist') + + def _read_egg_info_reqs(self): + source = self.read_text('requires.txt') + return pass_none(self._deps_from_requires_text)(source) + + @classmethod + def _deps_from_requires_text(cls, source): + return cls._convert_egg_info_reqs_to_simple_reqs(Sectioned.read(source)) + + @staticmethod + def _convert_egg_info_reqs_to_simple_reqs(sections): + """ + Historically, setuptools would solicit and store 'extra' + requirements, including those with environment markers, + in separate sections. More modern tools expect each + dependency to be defined separately, with any relevant + extras and environment markers attached directly to that + requirement. This method converts the former to the + latter. See _test_deps_from_requires_text for an example. + """ + + def make_condition(name): + return name and f'extra == "{name}"' + + def quoted_marker(section): + section = section or '' + extra, sep, markers = section.partition(':') + if extra and markers: + markers = f'({markers})' + conditions = list(filter(None, [markers, make_condition(extra)])) + return '; ' + ' and '.join(conditions) if conditions else '' + + def url_req_space(req): + """ + PEP 508 requires a space between the url_spec and the quoted_marker. + Ref python/importlib_metadata#357. + """ + # '@' is uniquely indicative of a url_req. + return ' ' * ('@' in req) + + for section in sections: + space = url_req_space(section.value) + yield section.value + space + quoted_marker(section.name) + + +class DistributionFinder(MetaPathFinder): + """ + A MetaPathFinder capable of discovering installed distributions. + """ + + class Context: + """ + Keyword arguments presented by the caller to + ``distributions()`` or ``Distribution.discover()`` + to narrow the scope of a search for distributions + in all DistributionFinders. + + Each DistributionFinder may expect any parameters + and should attempt to honor the canonical + parameters defined below when appropriate. + """ + + name = None + """ + Specific name for which a distribution finder should match. + A name of ``None`` matches all distributions. + """ + + def __init__(self, **kwargs): + vars(self).update(kwargs) + + @property + def path(self): + """ + The sequence of directory path that a distribution finder + should search. + + Typically refers to Python installed package paths such as + "site-packages" directories and defaults to ``sys.path``. + """ + return vars(self).get('path', sys.path) + + @abc.abstractmethod + def find_distributions(self, context=Context()): + """ + Find distributions. + + Return an iterable of all Distribution instances capable of + loading the metadata for packages matching the ``context``, + a DistributionFinder.Context instance. + """ + + +class FastPath: + """ + Micro-optimized class for searching a path for + children. + + >>> FastPath('').children() + ['...'] + """ + + @functools.lru_cache() # type: ignore + def __new__(cls, root): + return super().__new__(cls) + + def __init__(self, root): + self.root = str(root) + + def joinpath(self, child): + return pathlib.Path(self.root, child) + + def children(self): + with suppress(Exception): + return os.listdir(self.root or '.') + with suppress(Exception): + return self.zip_children() + return [] + + def zip_children(self): + zip_path = zipp.Path(self.root) + names = zip_path.root.namelist() + self.joinpath = zip_path.joinpath + + return dict.fromkeys(child.split(posixpath.sep, 1)[0] for child in names) + + def search(self, name): + return self.lookup(self.mtime).search(name) + + @property + def mtime(self): + with suppress(OSError): + return os.stat(self.root).st_mtime + self.lookup.cache_clear() + + @method_cache + def lookup(self, mtime): + return Lookup(self) + + +class Lookup: + def __init__(self, path: FastPath): + base = os.path.basename(path.root).lower() + base_is_egg = base.endswith(".egg") + self.infos = FreezableDefaultDict(list) + self.eggs = FreezableDefaultDict(list) + + for child in path.children(): + low = child.lower() + if low.endswith((".dist-info", ".egg-info")): + # rpartition is faster than splitext and suitable for this purpose. + name = low.rpartition(".")[0].partition("-")[0] + normalized = Prepared.normalize(name) + self.infos[normalized].append(path.joinpath(child)) + elif base_is_egg and low == "egg-info": + name = base.rpartition(".")[0].partition("-")[0] + legacy_normalized = Prepared.legacy_normalize(name) + self.eggs[legacy_normalized].append(path.joinpath(child)) + + self.infos.freeze() + self.eggs.freeze() + + def search(self, prepared): + infos = ( + self.infos[prepared.normalized] + if prepared + else itertools.chain.from_iterable(self.infos.values()) + ) + eggs = ( + self.eggs[prepared.legacy_normalized] + if prepared + else itertools.chain.from_iterable(self.eggs.values()) + ) + return itertools.chain(infos, eggs) + + +class Prepared: + """ + A prepared search for metadata on a possibly-named package. + """ + + normalized = None + legacy_normalized = None + + def __init__(self, name): + self.name = name + if name is None: + return + self.normalized = self.normalize(name) + self.legacy_normalized = self.legacy_normalize(name) + + @staticmethod + def normalize(name): + """ + PEP 503 normalization plus dashes as underscores. + """ + return re.sub(r"[-_.]+", "-", name).lower().replace('-', '_') + + @staticmethod + def legacy_normalize(name): + """ + Normalize the package name as found in the convention in + older packaging tools versions and specs. + """ + return name.lower().replace('-', '_') + + def __bool__(self): + return bool(self.name) + + +@install +class MetadataPathFinder(NullFinder, DistributionFinder): + """A degenerate finder for distribution packages on the file system. + + This finder supplies only a find_distributions() method for versions + of Python that do not have a PathFinder find_distributions(). + """ + + def find_distributions(self, context=DistributionFinder.Context()): + """ + Find distributions. + + Return an iterable of all Distribution instances capable of + loading the metadata for packages matching ``context.name`` + (or all names if ``None`` indicated) along the paths in the list + of directories ``context.path``. + """ + found = self._search_paths(context.name, context.path) + return map(PathDistribution, found) + + @classmethod + def _search_paths(cls, name, paths): + """Find metadata directories in paths heuristically.""" + prepared = Prepared(name) + return itertools.chain.from_iterable( + path.search(prepared) for path in map(FastPath, paths) + ) + + def invalidate_caches(cls): + FastPath.__new__.cache_clear() + + +class PathDistribution(Distribution): + def __init__(self, path: SimplePath): + """Construct a distribution. + + :param path: SimplePath indicating the metadata directory. + """ + self._path = path + + def read_text(self, filename): + with suppress( + FileNotFoundError, + IsADirectoryError, + KeyError, + NotADirectoryError, + PermissionError, + ): + return self._path.joinpath(filename).read_text(encoding='utf-8') + + read_text.__doc__ = Distribution.read_text.__doc__ + + def locate_file(self, path): + return self._path.parent / path + + @property + def _normalized_name(self): + """ + Performance optimization: where possible, resolve the + normalized name from the file system path. + """ + stem = os.path.basename(str(self._path)) + return self._name_from_stem(stem) or super()._normalized_name + + def _name_from_stem(self, stem): + name, ext = os.path.splitext(stem) + if ext not in ('.dist-info', '.egg-info'): + return + name, sep, rest = stem.partition('-') + return name + + +def distribution(distribution_name): + """Get the ``Distribution`` instance for the named package. + + :param distribution_name: The name of the distribution package as a string. + :return: A ``Distribution`` instance (or subclass thereof). + """ + return Distribution.from_name(distribution_name) + + +def distributions(**kwargs): + """Get all ``Distribution`` instances in the current environment. + + :return: An iterable of ``Distribution`` instances. + """ + return Distribution.discover(**kwargs) + + +def metadata(distribution_name) -> _meta.PackageMetadata: + """Get the metadata for the named package. + + :param distribution_name: The name of the distribution package to query. + :return: A PackageMetadata containing the parsed metadata. + """ + return Distribution.from_name(distribution_name).metadata + + +def version(distribution_name): + """Get the version string for the named package. + + :param distribution_name: The name of the distribution package to query. + :return: The version string for the package as defined in the package's + "Version" metadata key. + """ + return distribution(distribution_name).version + + +def entry_points(**params) -> Union[EntryPoints, SelectableGroups]: + """Return EntryPoint objects for all installed packages. + + Pass selection parameters (group or name) to filter the + result to entry points matching those properties (see + EntryPoints.select()). + + For compatibility, returns ``SelectableGroups`` object unless + selection parameters are supplied. In the future, this function + will return ``EntryPoints`` instead of ``SelectableGroups`` + even when no selection parameters are supplied. + + For maximum future compatibility, pass selection parameters + or invoke ``.select`` with parameters on the result. + + :return: EntryPoints or SelectableGroups for all installed packages. + """ + norm_name = operator.attrgetter('_normalized_name') + unique = functools.partial(unique_everseen, key=norm_name) + eps = itertools.chain.from_iterable( + dist.entry_points for dist in unique(distributions()) + ) + return SelectableGroups.load(eps).select(**params) + + +def files(distribution_name): + """Return a list of files for the named package. + + :param distribution_name: The name of the distribution package to query. + :return: List of files composing the distribution. + """ + return distribution(distribution_name).files + + +def requires(distribution_name): + """ + Return a list of requirements for the named package. + + :return: An iterator of requirements, suitable for + packaging.requirement.Requirement. + """ + return distribution(distribution_name).requires + + +def packages_distributions() -> Mapping[str, List[str]]: + """ + Return a mapping of top-level packages to their + distributions. + + >>> import collections.abc + >>> pkgs = packages_distributions() + >>> all(isinstance(dist, collections.abc.Sequence) for dist in pkgs.values()) + True + """ + pkg_to_dist = collections.defaultdict(list) + for dist in distributions(): + for pkg in _top_level_declared(dist) or _top_level_inferred(dist): + pkg_to_dist[pkg].append(dist.metadata['Name']) + return dict(pkg_to_dist) + + +def _top_level_declared(dist): + return (dist.read_text('top_level.txt') or '').split() + + +def _top_level_inferred(dist): + return { + f.parts[0] if len(f.parts) > 1 else f.with_suffix('').name + for f in always_iterable(dist.files) + if f.suffix == ".py" + } diff --git a/venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/__pycache__/__init__.cpython-39.pyc b/venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c740bf666170a95955b88f07a6837e80b7352540 GIT binary patch literal 37471 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/__pycache__/_adapters.cpython-39.pyc b/venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/__pycache__/_adapters.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..192bec26a01834184a02074304a96b6d460a8af3 GIT binary patch literal 2397 zcmah~%WoS+7@ygfH;$c0X(_F$))a}#6kBbf6)GVDB`pZrG-~K&FOLOJaGq)aq?^{2TAP~En_v3r~e&08&S}ha!j;?*U`LIOD?>IR9 zIWYJViduq-6Ha3ij9MDdVr&IAx40cUT{mzk`I>NtyN86k!tQvT(!dT%oNkc1_Xcht zYi}sjb!y5F)0hjs!jx#^!s*W)57bZ45d;MVmav5*+-*?dH#)EeH1I^J<9BAb^(%cv zwkWr`b65$=+~wXO31*AA688`Npu%T(8Rn{Dj?ePSA%WBLuZTl}1yHPNN{@w7Y+KaJ zro0j}rJ}7!$b9a}rb=U>g=(xuN*jMYW_l}?-F$XkrXA7Njb~3Ekh6NY!FV!c^<4EL&xowH~Ey7Pr0^ z-K>>GS)-R^ti1!q>^&DEZrtv%&fX`w+fqXJGM%QeYK6NZ;i+szU9>xnHp8ya43uE4 z5Sk1eqng>iL~dS1BR!}HtXw-grN~$$!{>r=kY)Ty51imA5pNlX$!&1W&K|aM5zdXObI^nBVU$EV3_pO8DxjhH z!ii#|#WR|rmbkIN4DA|WHayWv&cJMOHJA?$r}6?!$a$;^`6yamg6am8f0J6AJ0le( zVl)*}m!ZQcw+_kAWEwHP2JZ|gcQ27uXb*rz9V+kl>9NH<@SZ&+TUNm$4C2z-nd{Lg zB;p1Xg+TR*tZ=wum&%1cOlzPexBBEFP!o>Z`PG$FN{E~q#8K_(!LT{nh-oeYRK(!5q{dm4*9YB2b=@CTKfNoj8ST7vl)RY^*9jkfE*gIlh zqB8)&YtWp4XUa=4B$9U8&6aP&${$cje)E4-JUJ!L!wECHDpXrW8G5Yl$XT58!;J06 zDdWatSq9-{X19f&OxCS}Or|s@{79$ka8MSkLQ6k_qKemm`rc*gVX$5N58ckV3rU79 zFGyB{PC+gtntwnw(X>xB)z%S#v<;3cc<@7cg7Qk5>yR`c2R|Msf|^citoH53 zleGr=3)rz43uH}~>FHTWX0`PP>$O{V@7-%oXU`~yN+CrHEWd$HpB#}6*(LJ)(Ku%& z9w16C5#&CnJC?kqtz&r9`g910Lku`Wa_r*!0%ORoeZU@!aMuF=JF&l)O0IIdrEb2Z z4MW4aXBNA?SVvhb!k!W#&_S6Jg2Ce0SW-Y5&f-WLH%|938v`?A)`t8m-v|8)>I9bF zk(Y5ajeIi$uSufN17E~fEMWUDQVGr}0M6isX$rJ$A`|>UhtK+ArE#f!~Poi#=APW}b zRhZ!w-sDrO_`N@^znly2y1rAf{fb2kfpuRtVUNV%Hq}C-=0u_UFc-KXW}cDSpX1I# Z&1tBgg2i7N8NZClP@#AqF!8O5{Wo>+Mw9>m literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/__pycache__/_collections.cpython-39.pyc b/venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/__pycache__/_collections.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..30c799f26937da574ecdbb6cce2bbf6ab91d89ab GIT binary patch literal 1572 zcmaJ>&u?IRCKWclR zS>+Zaa_Zjz$NWpaa;P|S(`4BD@Ar)pL@R$3;NEe)<@u3@cFFI4TAJ5a3ZoN#4Rvt}NG1S}0$Oad4afMEc` zva&8+DKsmZ+B(w}7<8A}t~gl6*>&U#RN0xbeg*)_gl)#duzE6?Fe%x6c3B1^U0Ro| zt=s$l=~%R_s^#d;&Yks{@f;aYqjlfj&eIUPxBTE%TGb;dmy347WC1n4XlN(Uu@3eo z42~Q_g&jR1hfuv^dV2{08S$X)Pqnc^3J^Dn0k{ zb9Hn^{T0p&Ev)7IjC`~Yf6D)`%Gg}gwXpfmZM!R+$R9U_(E0DGYV)>ix4XI(#d9UM zUmhr>w|6>m`0@u=xKe(qwwJ*iwYxw&Boh-I5)67Z;<9ixuv=cCv zae$1+Hdk>7xWNkGy`_4-f~j+2Zv78<*7pO>Yf&lA{Se4%WT(;Id%WaRv@P_e{v zkP`|IMGPz_KKV_Q<};Ziy${c$k3r~;9!AF$o+^lkrz-k;SXx;gAO*|ak{e(C3-~32cmMzZ literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/__pycache__/_compat.cpython-39.pyc b/venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/__pycache__/_compat.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0fffec6ba519de943ec0e71c8fde300578af3332 GIT binary patch literal 2061 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 Y@Gd6{I>wS^5#L81TTvCiQm!8T4=J{Hz5oCK literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/__pycache__/_itertools.cpython-39.pyc b/venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/__pycache__/_itertools.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8c99a2c4d307130a88378dcde9bfdcf484aaf60f GIT binary patch literal 2039 zcmbtVUvJ|?5Z|?(T$*cjRYCB`2qaQhX+=4Shls0yJ0wmzMd(`owW*SgcTL>dUUzqs zoDb(IJn&WcN`B>uufP+tPMYSbpabF5Q}6EV%x`9XJIi)|p(I zaqtDc`TzwdoW>-f=adrufVJy)q55p)nLWL~W zq8m7NcKOutzcnA=tA{8InUk4QI9GJ$7L?O5QJ)z*b_+6ho{`JFnOC@lH%Iq{_dTKH z2Gae4;L3-%LhZ_|R@4e-LRAMfYipVvP7#*#`kNP#HZV@3o3Q{9i$tVGw;@wP3pI(- zpFt`v)DgVIrDP}+usB{Rf|%fp79u_B`d;a3VM>>Au54iCcE2CU)UYVk{k~r>8xcm% zhOsE!Ymt|p-FM!wvX6Vp2TS)Qz5bo3hiKuio2Q-LcL+rHSei23`!dU(F~fQ%P8)O=-=@<*X@6=5SKg?j4IQaNp5m*2L{T73 zuy(tKaA%HLuWCtE+t32P=MH|MPDt(A>!$sl(;vtw@rZHqmlW$tkqZlrI{67#K0%9E zJ(s;gbk9RLki)A3h&0?LxD5(JS1GV`F=wO#X=@dkN-NQwPO}Ni=j7xB&;&ez{o^)# z+J?ve8*4FgWS_-Tmg_26wubw-!M{_xSZ=&rSX~E|O0xkN$W$C6-ek1~OR`wfRS|85 zc>Ld?Z2&bGbP>Q{u%0QTlgU?bHs;4}db@wCwVs=$|F3f3B4p#(v|$*fOyyV~4o18( zppC+~H83T>CJb|-BRqJ5-vQc)s1-`tdOM_h)v9)_rDe#p=$kwf6^-!Rv@Ib-fNTko zI@3`Uj9@T`G@fO{(x56oMsd5%9}FrC3)*Q^JyT;$FHB|HGB6aI0y^5nz+YOd)q&&L zzYGcBBY1AxiV+Kfn~?w>1*W9|n~YwWxj?&@tC3~=Ke2i(tS8oz?^`ElN-$Gd#v$baH_ELuWYX74N##4G zi*cN9t#VQAT8M3Ij^(3!edT@IHg{3rrAZsk9`;&?Ht9B1dv=a?@gmu>9;=RBT{Kk> n#>>a3vNp_((3R?%BYT&q%3I^}MDlSgPAE=k+uOI@<~x4_9AGf5 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/__pycache__/_meta.cpython-39.pyc b/venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/__pycache__/_meta.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7fdff50c1eaf3ff8ce47e0afa5474cd52874cc5a GIT binary patch literal 2416 zcmbsq$!;7)wAbmL%{xg<0_jL0FcKbwIDrtd6-xvZ1}kH?=_-5L=`B^&Hsd4l zfiq|SfPbm3obn5tc&~fLp4gTw;cC@Wy`}o?uV}a1GGP7n_}S=B$1wguWPSn7*n};A z2fz$wCPr$8rfD#X*@>0fp`ALRle(dsHo`{gg-o8n|FAZFRUB9y>9`(duFo*ws`7>i+qVMgG2{* z7w;m!lEHs0vE@??%nDlp$Jg}Y4vpT>1O5wFlu<>`P2CV&l_HBUCbNZS+|OZ4ObRo0 zjdOEw4nRASC;MU%s1^7(dH&t-wd6t$X_iqr+$xG~`1SB*9?@jD$J1h1#KlIL6`-55 zjpH%r$;Q_uJv{zKr9%no3zg@I9FilRv0Mz}w8(`@;t@%wb`GmkznEx`kc4N1G|@B* zfMK58zv5MYD$}#H6DyvIE{H{yFkXO#=W7m%1)x?w^(?WB=d~H3c6S9(-615(GezS} z64C+6%!)_Xt+*5fQ|vc<^1m&)cY`HuLJqh>2MNJ+%nW&W-H;2p+tYj*1+jF4QlAje zCx4(kZmaCx@y{9!Iks8#D^rxi@stExf+nk2yy zO-e2UDrFwURB;v@$7&qVpva|+N692e%S6Q+l^hEot4b#B)|t@s$hMJbCa z!5##QfUb{#H*@e>g-vB{31{udw-**{1wZfpI@pNvw4e&C<-vX~(jeat)R+geV!vwf zjd^emWuBq=wTafr+SMGOz@TULd#f6fhDjhqw+KmdRwj6cN`70?WXiGQOo>(ap|+)h zsW*a_6c__>A3+1b0|Yq21-75Sc_(l@h=%~QUx>WmLQRB=v_}XoV_Tgtz@iPnhb^(+ zd~?BGf^WqRT+6I@5s*JvSRtFRxkzsj6i1-Xim;&)Rf+q;RKyXuCKLrL#NbC^bbeshnKY{cCl$!?+2R6RIbn1qh v6mfP?_fOR@Rf|yG{bhp5D>9W$_fdujbY5Bl{a literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/__pycache__/_text.cpython-39.pyc b/venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/__pycache__/_text.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7e9bf607e07caf2414b881b6d3a8cf1ba17d04ef GIT binary patch literal 3105 zcmb7GOK%%D5GHpeTUKPpc{Go};LD^Urrb^tNh*{ELI~ zQ-Q&6@ah&cf(ROt4iS!ULmD|9hmuD`R7CZFh^ln=-A+Z&RnngN2&>7nj}+QA%^Hz3 z{X}>^_xsXEQTag=_-F-JC4UES>I|M0=EIl;v6it8Ot2-HHY$i;Ge6{7-(@}7=UY;v5*`8Ro#G1cb;h$D$HM~#*SuC26v!x}b&se0{_h)H($U|LHr5A%($emX6IiSE0 z{al#Qi#iPhQ^?jV>gED#vTbY;`>WFWL>Vbs5l>r%rweSY`Do?o(-qvn!?e$_b59!H zeAUiPuAP_%dA?()dlh0WV_&jJMm?!?KS(jakU1W_?wj>QZF40`vA$J`-z~^CThp(K z2%(pGMo==bwzSHw|0@}=h`(h<0v*5()6#%GKOAVt@&fA(fDt?vf#60m=r9?|NX8~l zNQ5lvC8iI&g6+u163QY*tqBlqMEp*_KL_!m>4Y=*ud7i_y0Pf2)x#W(wv!-Wp@^s2H8is|GBSNzI zjy((W2Kz3&_uzazyqhwwq*?9MfmVG^>Wmwp7PXR?#wC&#FKo7!q{>c68PzhZg$6R+;()0m0y!#~adDwj+qqLg_>Fq(Ba(`2b+i*(B@b-@bzOnt2iMl}I zL28mD)Lm~&#v)POAWETl!=UHEvCe_byz3dcV;0l5*_7vn#`7#->j~YxRD@zNmwthd zl~tmu;D(yQ1}>=FE9;tSzz{9I28$1&ug|oI(l4;+e2zu=#`7MZYZ0YiVA1^?i?Q^) zC+Av3sgIZK=)wM&IT$B{+@VKgAFgK`(KgVf&vjo-gY=lH8TiY?inPgNTk||z;(5Lr@X~G9qsF@&=|6BZ67+oT)=QN#^7dEJxHapAhHHHk;I0>mFsyn*+A|Y zn8f=QX2!tOSD^I|R6or4^$ARcl2f=QVzP%(q5E_TDydC(zkZOwU5zEgc$!MC@NBiU z^lO_c^yo|ix^N!69Aj~I=So;WbSf>QqSpA~H44o*DGCE-!=Wx??;19RonVBz2}=GR+ou!u?dDIE zDI}kdksdvW0jt>JV9+tZ2Y7)GNASPl9y#ybJ@>G(NA{efQ3bZEnWJPjjh|6LD6=W4 zeV)pUJ_gp{$40wifp%(kWTeV!5#O!@!)X5DDd zXHWz&kD$P^y5~iS7=+jduHr}CP%`a#BJqKuv$$~%n~T`snXRs1gN#)-u))CO3C3V5 z22D0QB)JdYawDSKq}%jk{aXHE_BAT0(aPPLJNh-;TGgR*Ft)4ORrM_@t$XW(*tci5 dH3|teD(A7)T{QL}t^JZaw~Xnt;i)-|%70B7-IxFX literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/_adapters.py b/venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/_adapters.py new file mode 100644 index 0000000..aa460d3 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/_adapters.py @@ -0,0 +1,68 @@ +import re +import textwrap +import email.message + +from ._text import FoldedCase + + +class Message(email.message.Message): + multiple_use_keys = set( + map( + FoldedCase, + [ + 'Classifier', + 'Obsoletes-Dist', + 'Platform', + 'Project-URL', + 'Provides-Dist', + 'Provides-Extra', + 'Requires-Dist', + 'Requires-External', + 'Supported-Platform', + 'Dynamic', + ], + ) + ) + """ + Keys that may be indicated multiple times per PEP 566. + """ + + def __new__(cls, orig: email.message.Message): + res = super().__new__(cls) + vars(res).update(vars(orig)) + return res + + def __init__(self, *args, **kwargs): + self._headers = self._repair_headers() + + # suppress spurious error from mypy + def __iter__(self): + return super().__iter__() + + def _repair_headers(self): + def redent(value): + "Correct for RFC822 indentation" + if not value or '\n' not in value: + return value + return textwrap.dedent(' ' * 8 + value) + + headers = [(key, redent(value)) for key, value in vars(self)['_headers']] + if self._payload: + headers.append(('Description', self.get_payload())) + return headers + + @property + def json(self): + """ + Convert PackageMetadata to a JSON-compatible format + per PEP 0566. + """ + + def transform(key): + value = self.get_all(key) if key in self.multiple_use_keys else self[key] + if key == 'Keywords': + value = re.split(r'\s+', value) + tk = key.lower().replace('-', '_') + return tk, value + + return dict(map(transform, map(FoldedCase, self))) diff --git a/venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/_collections.py b/venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/_collections.py new file mode 100644 index 0000000..cf0954e --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/_collections.py @@ -0,0 +1,30 @@ +import collections + + +# from jaraco.collections 3.3 +class FreezableDefaultDict(collections.defaultdict): + """ + Often it is desirable to prevent the mutation of + a default dict after its initial construction, such + as to prevent mutation during iteration. + + >>> dd = FreezableDefaultDict(list) + >>> dd[0].append('1') + >>> dd.freeze() + >>> dd[1] + [] + >>> len(dd) + 1 + """ + + def __missing__(self, key): + return getattr(self, '_frozen', super().__missing__)(key) + + def freeze(self): + self._frozen = lambda key: self.default_factory() + + +class Pair(collections.namedtuple('Pair', 'name value')): + @classmethod + def parse(cls, text): + return cls(*map(str.strip, text.split("=", 1))) diff --git a/venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/_compat.py b/venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/_compat.py new file mode 100644 index 0000000..ef3136f --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/_compat.py @@ -0,0 +1,71 @@ +import sys +import platform + + +__all__ = ['install', 'NullFinder', 'Protocol'] + + +try: + from typing import Protocol +except ImportError: # pragma: no cover + from ..typing_extensions import Protocol # type: ignore + + +def install(cls): + """ + Class decorator for installation on sys.meta_path. + + Adds the backport DistributionFinder to sys.meta_path and + attempts to disable the finder functionality of the stdlib + DistributionFinder. + """ + sys.meta_path.append(cls()) + disable_stdlib_finder() + return cls + + +def disable_stdlib_finder(): + """ + Give the backport primacy for discovering path-based distributions + by monkey-patching the stdlib O_O. + + See #91 for more background for rationale on this sketchy + behavior. + """ + + def matches(finder): + return getattr( + finder, '__module__', None + ) == '_frozen_importlib_external' and hasattr(finder, 'find_distributions') + + for finder in filter(matches, sys.meta_path): # pragma: nocover + del finder.find_distributions + + +class NullFinder: + """ + A "Finder" (aka "MetaClassFinder") that never finds any modules, + but may find distributions. + """ + + @staticmethod + def find_spec(*args, **kwargs): + return None + + # In Python 2, the import system requires finders + # to have a find_module() method, but this usage + # is deprecated in Python 3 in favor of find_spec(). + # For the purposes of this finder (i.e. being present + # on sys.meta_path but having no other import + # system functionality), the two methods are identical. + find_module = find_spec + + +def pypy_partial(val): + """ + Adjust for variable stacklevel on partial under PyPy. + + Workaround for #327. + """ + is_pypy = platform.python_implementation() == 'PyPy' + return val + is_pypy diff --git a/venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/_functools.py b/venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/_functools.py new file mode 100644 index 0000000..71f66bd --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/_functools.py @@ -0,0 +1,104 @@ +import types +import functools + + +# from jaraco.functools 3.3 +def method_cache(method, cache_wrapper=None): + """ + Wrap lru_cache to support storing the cache data in the object instances. + + Abstracts the common paradigm where the method explicitly saves an + underscore-prefixed protected property on first call and returns that + subsequently. + + >>> class MyClass: + ... calls = 0 + ... + ... @method_cache + ... def method(self, value): + ... self.calls += 1 + ... return value + + >>> a = MyClass() + >>> a.method(3) + 3 + >>> for x in range(75): + ... res = a.method(x) + >>> a.calls + 75 + + Note that the apparent behavior will be exactly like that of lru_cache + except that the cache is stored on each instance, so values in one + instance will not flush values from another, and when an instance is + deleted, so are the cached values for that instance. + + >>> b = MyClass() + >>> for x in range(35): + ... res = b.method(x) + >>> b.calls + 35 + >>> a.method(0) + 0 + >>> a.calls + 75 + + Note that if method had been decorated with ``functools.lru_cache()``, + a.calls would have been 76 (due to the cached value of 0 having been + flushed by the 'b' instance). + + Clear the cache with ``.cache_clear()`` + + >>> a.method.cache_clear() + + Same for a method that hasn't yet been called. + + >>> c = MyClass() + >>> c.method.cache_clear() + + Another cache wrapper may be supplied: + + >>> cache = functools.lru_cache(maxsize=2) + >>> MyClass.method2 = method_cache(lambda self: 3, cache_wrapper=cache) + >>> a = MyClass() + >>> a.method2() + 3 + + Caution - do not subsequently wrap the method with another decorator, such + as ``@property``, which changes the semantics of the function. + + See also + http://code.activestate.com/recipes/577452-a-memoize-decorator-for-instance-methods/ + for another implementation and additional justification. + """ + cache_wrapper = cache_wrapper or functools.lru_cache() + + def wrapper(self, *args, **kwargs): + # it's the first call, replace the method with a cached, bound method + bound_method = types.MethodType(method, self) + cached_method = cache_wrapper(bound_method) + setattr(self, method.__name__, cached_method) + return cached_method(*args, **kwargs) + + # Support cache clear even before cache has been created. + wrapper.cache_clear = lambda: None + + return wrapper + + +# From jaraco.functools 3.3 +def pass_none(func): + """ + Wrap func so it's not called if its first param is None + + >>> print_text = pass_none(print) + >>> print_text('text') + text + >>> print_text(None) + """ + + @functools.wraps(func) + def wrapper(param, *args, **kwargs): + if param is not None: + return func(param, *args, **kwargs) + + return wrapper diff --git a/venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/_itertools.py b/venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/_itertools.py new file mode 100644 index 0000000..d4ca9b9 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/_itertools.py @@ -0,0 +1,73 @@ +from itertools import filterfalse + + +def unique_everseen(iterable, key=None): + "List unique elements, preserving order. Remember all elements ever seen." + # unique_everseen('AAAABBBCCDAABBB') --> A B C D + # unique_everseen('ABBCcAD', str.lower) --> A B C D + seen = set() + seen_add = seen.add + if key is None: + for element in filterfalse(seen.__contains__, iterable): + seen_add(element) + yield element + else: + for element in iterable: + k = key(element) + if k not in seen: + seen_add(k) + yield element + + +# copied from more_itertools 8.8 +def always_iterable(obj, base_type=(str, bytes)): + """If *obj* is iterable, return an iterator over its items:: + + >>> obj = (1, 2, 3) + >>> list(always_iterable(obj)) + [1, 2, 3] + + If *obj* is not iterable, return a one-item iterable containing *obj*:: + + >>> obj = 1 + >>> list(always_iterable(obj)) + [1] + + If *obj* is ``None``, return an empty iterable: + + >>> obj = None + >>> list(always_iterable(None)) + [] + + By default, binary and text strings are not considered iterable:: + + >>> obj = 'foo' + >>> list(always_iterable(obj)) + ['foo'] + + If *base_type* is set, objects for which ``isinstance(obj, base_type)`` + returns ``True`` won't be considered iterable. + + >>> obj = {'a': 1} + >>> list(always_iterable(obj)) # Iterate over the dict's keys + ['a'] + >>> list(always_iterable(obj, base_type=dict)) # Treat dicts as a unit + [{'a': 1}] + + Set *base_type* to ``None`` to avoid any special handling and treat objects + Python considers iterable as iterable: + + >>> obj = 'foo' + >>> list(always_iterable(obj, base_type=None)) + ['f', 'o', 'o'] + """ + if obj is None: + return iter(()) + + if (base_type is not None) and isinstance(obj, base_type): + return iter((obj,)) + + try: + return iter(obj) + except TypeError: + return iter((obj,)) diff --git a/venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/_meta.py b/venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/_meta.py new file mode 100644 index 0000000..37ee43e --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/_meta.py @@ -0,0 +1,48 @@ +from ._compat import Protocol +from typing import Any, Dict, Iterator, List, TypeVar, Union + + +_T = TypeVar("_T") + + +class PackageMetadata(Protocol): + def __len__(self) -> int: + ... # pragma: no cover + + def __contains__(self, item: str) -> bool: + ... # pragma: no cover + + def __getitem__(self, key: str) -> str: + ... # pragma: no cover + + def __iter__(self) -> Iterator[str]: + ... # pragma: no cover + + def get_all(self, name: str, failobj: _T = ...) -> Union[List[Any], _T]: + """ + Return all values associated with a possibly multi-valued key. + """ + + @property + def json(self) -> Dict[str, Union[str, List[str]]]: + """ + A JSON-compatible form of the metadata. + """ + + +class SimplePath(Protocol): + """ + A minimal subset of pathlib.Path required by PathDistribution. + """ + + def joinpath(self) -> 'SimplePath': + ... # pragma: no cover + + def __truediv__(self) -> 'SimplePath': + ... # pragma: no cover + + def parent(self) -> 'SimplePath': + ... # pragma: no cover + + def read_text(self) -> str: + ... # pragma: no cover diff --git a/venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/_text.py b/venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/_text.py new file mode 100644 index 0000000..c88cfbb --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/_text.py @@ -0,0 +1,99 @@ +import re + +from ._functools import method_cache + + +# from jaraco.text 3.5 +class FoldedCase(str): + """ + A case insensitive string class; behaves just like str + except compares equal when the only variation is case. + + >>> s = FoldedCase('hello world') + + >>> s == 'Hello World' + True + + >>> 'Hello World' == s + True + + >>> s != 'Hello World' + False + + >>> s.index('O') + 4 + + >>> s.split('O') + ['hell', ' w', 'rld'] + + >>> sorted(map(FoldedCase, ['GAMMA', 'alpha', 'Beta'])) + ['alpha', 'Beta', 'GAMMA'] + + Sequence membership is straightforward. + + >>> "Hello World" in [s] + True + >>> s in ["Hello World"] + True + + You may test for set inclusion, but candidate and elements + must both be folded. + + >>> FoldedCase("Hello World") in {s} + True + >>> s in {FoldedCase("Hello World")} + True + + String inclusion works as long as the FoldedCase object + is on the right. + + >>> "hello" in FoldedCase("Hello World") + True + + But not if the FoldedCase object is on the left: + + >>> FoldedCase('hello') in 'Hello World' + False + + In that case, use in_: + + >>> FoldedCase('hello').in_('Hello World') + True + + >>> FoldedCase('hello') > FoldedCase('Hello') + False + """ + + def __lt__(self, other): + return self.lower() < other.lower() + + def __gt__(self, other): + return self.lower() > other.lower() + + def __eq__(self, other): + return self.lower() == other.lower() + + def __ne__(self, other): + return self.lower() != other.lower() + + def __hash__(self): + return hash(self.lower()) + + def __contains__(self, other): + return super().lower().__contains__(other.lower()) + + def in_(self, other): + "Does self appear in other?" + return self in FoldedCase(other) + + # cache lower since it's likely to be called frequently. + @method_cache + def lower(self): + return super().lower() + + def index(self, sub): + return self.lower().index(sub.lower()) + + def split(self, splitter=' ', maxsplit=0): + pattern = re.compile(re.escape(splitter), re.I) + return pattern.split(self, maxsplit) diff --git a/venv/Lib/site-packages/setuptools/_vendor/importlib_resources/__init__.py b/venv/Lib/site-packages/setuptools/_vendor/importlib_resources/__init__.py new file mode 100644 index 0000000..34e3a99 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_vendor/importlib_resources/__init__.py @@ -0,0 +1,36 @@ +"""Read resources contained within a package.""" + +from ._common import ( + as_file, + files, + Package, +) + +from ._legacy import ( + contents, + open_binary, + read_binary, + open_text, + read_text, + is_resource, + path, + Resource, +) + +from .abc import ResourceReader + + +__all__ = [ + 'Package', + 'Resource', + 'ResourceReader', + 'as_file', + 'contents', + 'files', + 'is_resource', + 'open_binary', + 'open_text', + 'path', + 'read_binary', + 'read_text', +] diff --git a/venv/Lib/site-packages/setuptools/_vendor/importlib_resources/__pycache__/__init__.cpython-39.pyc b/venv/Lib/site-packages/setuptools/_vendor/importlib_resources/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..92e631f0045c60d005676092435612595795fa99 GIT binary patch literal 638 zcmYk3-HOyO6vx|XrytXHcNOpLl~`dG#5-BUMK48URgh2!nI_Ie^F@+6j!)ooc;_qS z)+=9Ouk7hKVjw@xNzVD_&k1RoRWz;d_aAI-<0$$C$^UCHCC{hrK1`qyifBw1B9;rZ zkO@j;iqaU)60wvS%4CjmS)f9esFW+Tk`=0CjcVDTX0A)cnLJ15akP!-@<)s=X!bVh z@^6oB7@@6YPLFnAt{t@UgeykdJ@-4VTGARad?s6V`FrvibxFvH!yma|VF`30e{(G8 zicmm1Q{IJ28>aAvD`F3!veP4{q?~U&`|3kEpU+{%9X`1TsUdzBikrW#x;UJjVzA3> zSKD+lV{1SIfO**^AOXN|Z3ZX+6(9$c6JB?BLXI)j1IAM@XeqTiD$LCwjdCp5mJElZ z=qxo0%zB`5d}CGy8zCW^VfF&rL&GMcw147d@0cHr*IKw9e_@Jh+jD8O^@4By4Q{%_Tyc-_ Zr8$J+N@_X^_6+{bf$wy2FMC+k$scubt$6?d literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/_vendor/importlib_resources/__pycache__/_adapters.cpython-39.pyc b/venv/Lib/site-packages/setuptools/_vendor/importlib_resources/__pycache__/_adapters.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8804afc43a8d998631985ceb04a0046aaa5c5df4 GIT binary patch literal 7486 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/_vendor/importlib_resources/__pycache__/_compat.cpython-39.pyc b/venv/Lib/site-packages/setuptools/_vendor/importlib_resources/__pycache__/_compat.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b91eed4d27fb2ae9c68487e4d79baeb86d63ca19 GIT binary patch literal 3480 zcmbtWPj3@P6rY)0+v`6u2~bK?1S^$RSONp$(3VD&G?WUdiV&fttSqfII}^NNy}O+m z2W*92f|PJV>bZyH$T#SB=r>rYr=D`|p%PN1zBlVQ4g{paS~H%Rotb^__ulWl7femn z2s~S7K3o13Mt|XC@^N5t9h&+bI!-u^iC6qnkD59282q!?>e-%6iJ+?`Zapl?Iasyh za5|XbdDJ_~RAsJSATJK1tXmV)j;H@02%X z_MS9*e=GJ1vfA{fik;sPUgPzrgx5EicZ4_i6x=e+=@Mx*cR_lx*rK_k`dKE0QZ2S? z!P+jW59{{rKzDapF`1G5L`Oa0hg}gq43=XNQh2lX;27HiG-X4#PL{|Ey7&Swvcg!& zDlD4rWx8;+^Mevnb%G=bRA)ZRZUj2$e4mCv+_@`yStpCK3;iSu!iR!ic+?dlzHqr8 ztUkJ;dmSZoKhtR%tB$`W5}wLV)XP$-<7n9jHPXHe1-uK>UKZ$fHjowg^idQHbs^Nu zQSaL_)oGZO6FUpjE-5)U!C_79eN~upBQvB^%T$^D?i%8dwNWt>&|L zWv~XyAw+lfr1?G#xRAp?YA!tUJjk>gnd!_xQIWGbkM?$)Qq!cb(<|cuT)`U5}CkRj7 zB-QRfXczE|MNcI9P?6e&BnC{t2Ok_`Gv-J4S*Pp72U08%iFA1Z-lQ@Swix`2ctsw8 z#eJ8Mb(rRk??*|beg9LKjchgi9+qAT4G-otIM?J&2MP zmD7hvVuRy!&yA&E!!vJ@0{4cKV4%C92VqmcK*uS>0@9<;XpcQ%lx)%!$}Mg`b)Hye zT;gRI+Xc&?kxc^ctGotlrA@lYRv54I2F%Lqr7gB|E19U& zF`WDel}GP*HEhiI!CDZ-7;i@~e2$V~5;7k0?l8Q1?*SOlt&!n|D`=T5P=A9yp&Ei8 zryES3SO@kY6IyIBFReteP>^*h-9QCEhH)e+yc!~r3ztmzd=t!zL3*UrSMYYEltYI% z-@~>Om%gUa0rn54HQAJoOTWmR) zSCP=ZpVxeU6kzrHA~|9Yp#WaH1z?JWiKT@p%67_kyT|3lR6T?1$P7T&x6x z2g1b~!hIC!uB-Q}EcZZBWX?kEgH;Z0zgVP~iv`U_CDT$L)Pu4~D0iF*+mB?B`Q{5y zll9f%^;l7Qn2)T;wC4uP>6$P#R~kbQ->bY1h~%D|yVAaVsZ|tC@;K-ZbVpBt^w@$w zGxlbdK-}VfQzAl20MnsBU>AfGGx!Jzb7I0Kh8NYb20y{>B3L*LCNJaJncNDN!`xB> zC9%NDYhjvb@fgeIB1bo{Y=vwCRoF_JS0Lje7YuQ|3gqkCz+}&c=MfPbm4p8N|Q)aoRL?V-NzdURKPRSX-C2L#u*hfgNPC*-G7R#$||8x$=OIN?-~ zie{9$vnRaD&-^OLf-20yD$1g&m-VVRi>rRtrvzf|U(sxUdw~0p_aT76CV>ci7@ScU zo_d=E_0U;)^xfw@9)At95f2YZI{1Y-NlNYTv=j!^DH9sfo{e{z5NsmA#_!R*ax%5D z@rTBgwPeEjhhS{)Xwkq4Q#L%7XtrK)gmQe4`Zg~A-}Yy)u#p1ODmnFB*4yRiV_V1+ zMNbe6xgtxi^Umqg?^yeh^^->JHLEk zsvIk68&lUp=fxZ(uT@@FO|6V5Ck2wLTQvprxw%}2Z8r;h@1_rhW94dF$3pZ50*N9T z(U`8G47?c8ed+;vQhJb%ZU63_8|sl+G}t`l2C4!Fp#wK#)pHO#=sR#fg&I0=&s~#W g0hiszud1520$x+p^cup*dpyJv0`k|R8#Ma!4^8agS^xk5 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/_vendor/importlib_resources/__pycache__/_legacy.cpython-39.pyc b/venv/Lib/site-packages/setuptools/_vendor/importlib_resources/__pycache__/_legacy.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3365a5ef22451fad7ff45bb771ea8efcafa0d325 GIT binary patch literal 4198 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/_vendor/importlib_resources/__pycache__/abc.cpython-39.pyc b/venv/Lib/site-packages/setuptools/_vendor/importlib_resources/__pycache__/abc.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7e15f3feb52a144d504829a06256027223621fb0 GIT binary patch literal 5436 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/_vendor/importlib_resources/__pycache__/readers.cpython-39.pyc b/venv/Lib/site-packages/setuptools/_vendor/importlib_resources/__pycache__/readers.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..11edfb4c9bb8ff2fee306df17746631202e0908c GIT binary patch literal 5552 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 Traversable + """ + Get a Traversable resource from a package + """ + return from_package(get_package(package)) + + +def get_resource_reader(package): + # type: (types.ModuleType) -> Optional[ResourceReader] + """ + Return the package's loader if it's a ResourceReader. + """ + # We can't use + # a issubclass() check here because apparently abc.'s __subclasscheck__() + # hook wants to create a weak reference to the object, but + # zipimport.zipimporter does not support weak references, resulting in a + # TypeError. That seems terrible. + spec = package.__spec__ + reader = getattr(spec.loader, 'get_resource_reader', None) # type: ignore + if reader is None: + return None + return reader(spec.name) # type: ignore + + +def resolve(cand): + # type: (Package) -> types.ModuleType + return cand if isinstance(cand, types.ModuleType) else importlib.import_module(cand) + + +def get_package(package): + # type: (Package) -> types.ModuleType + """Take a package name or module object and return the module. + + Raise an exception if the resolved module is not a package. + """ + resolved = resolve(package) + if wrap_spec(resolved).submodule_search_locations is None: + raise TypeError(f'{package!r} is not a package') + return resolved + + +def from_package(package): + """ + Return a Traversable object for the given package. + + """ + spec = wrap_spec(package) + reader = spec.loader.get_resource_reader(spec.name) + return reader.files() + + +@contextlib.contextmanager +def _tempfile(reader, suffix=''): + # Not using tempfile.NamedTemporaryFile as it leads to deeper 'try' + # blocks due to the need to close the temporary file to work on Windows + # properly. + fd, raw_path = tempfile.mkstemp(suffix=suffix) + try: + try: + os.write(fd, reader()) + finally: + os.close(fd) + del reader + yield pathlib.Path(raw_path) + finally: + try: + os.remove(raw_path) + except FileNotFoundError: + pass + + +@functools.singledispatch +def as_file(path): + """ + Given a Traversable object, return that object as a + path on the local file system in a context manager. + """ + return _tempfile(path.read_bytes, suffix=path.name) + + +@as_file.register(pathlib.Path) +@contextlib.contextmanager +def _(path): + """ + Degenerate behavior for pathlib.Path objects. + """ + yield path diff --git a/venv/Lib/site-packages/setuptools/_vendor/importlib_resources/_compat.py b/venv/Lib/site-packages/setuptools/_vendor/importlib_resources/_compat.py new file mode 100644 index 0000000..cb9fc82 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_vendor/importlib_resources/_compat.py @@ -0,0 +1,98 @@ +# flake8: noqa + +import abc +import sys +import pathlib +from contextlib import suppress + +if sys.version_info >= (3, 10): + from zipfile import Path as ZipPath # type: ignore +else: + from ..zipp import Path as ZipPath # type: ignore + + +try: + from typing import runtime_checkable # type: ignore +except ImportError: + + def runtime_checkable(cls): # type: ignore + return cls + + +try: + from typing import Protocol # type: ignore +except ImportError: + Protocol = abc.ABC # type: ignore + + +class TraversableResourcesLoader: + """ + Adapt loaders to provide TraversableResources and other + compatibility. + + Used primarily for Python 3.9 and earlier where the native + loaders do not yet implement TraversableResources. + """ + + def __init__(self, spec): + self.spec = spec + + @property + def path(self): + return self.spec.origin + + def get_resource_reader(self, name): + from . import readers, _adapters + + def _zip_reader(spec): + with suppress(AttributeError): + return readers.ZipReader(spec.loader, spec.name) + + def _namespace_reader(spec): + with suppress(AttributeError, ValueError): + return readers.NamespaceReader(spec.submodule_search_locations) + + def _available_reader(spec): + with suppress(AttributeError): + return spec.loader.get_resource_reader(spec.name) + + def _native_reader(spec): + reader = _available_reader(spec) + return reader if hasattr(reader, 'files') else None + + def _file_reader(spec): + try: + path = pathlib.Path(self.path) + except TypeError: + return None + if path.exists(): + return readers.FileReader(self) + + return ( + # native reader if it supplies 'files' + _native_reader(self.spec) + or + # local ZipReader if a zip module + _zip_reader(self.spec) + or + # local NamespaceReader if a namespace module + _namespace_reader(self.spec) + or + # local FileReader + _file_reader(self.spec) + # fallback - adapt the spec ResourceReader to TraversableReader + or _adapters.CompatibilityFiles(self.spec) + ) + + +def wrap_spec(package): + """ + Construct a package spec with traversable compatibility + on the spec/loader/reader. + + Supersedes _adapters.wrap_spec to use TraversableResourcesLoader + from above for older Python compatibility (<3.10). + """ + from . import _adapters + + return _adapters.SpecLoaderAdapter(package.__spec__, TraversableResourcesLoader) diff --git a/venv/Lib/site-packages/setuptools/_vendor/importlib_resources/_itertools.py b/venv/Lib/site-packages/setuptools/_vendor/importlib_resources/_itertools.py new file mode 100644 index 0000000..cce0558 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_vendor/importlib_resources/_itertools.py @@ -0,0 +1,35 @@ +from itertools import filterfalse + +from typing import ( + Callable, + Iterable, + Iterator, + Optional, + Set, + TypeVar, + Union, +) + +# Type and type variable definitions +_T = TypeVar('_T') +_U = TypeVar('_U') + + +def unique_everseen( + iterable: Iterable[_T], key: Optional[Callable[[_T], _U]] = None +) -> Iterator[_T]: + "List unique elements, preserving order. Remember all elements ever seen." + # unique_everseen('AAAABBBCCDAABBB') --> A B C D + # unique_everseen('ABBCcAD', str.lower) --> A B C D + seen: Set[Union[_T, _U]] = set() + seen_add = seen.add + if key is None: + for element in filterfalse(seen.__contains__, iterable): + seen_add(element) + yield element + else: + for element in iterable: + k = key(element) + if k not in seen: + seen_add(k) + yield element diff --git a/venv/Lib/site-packages/setuptools/_vendor/importlib_resources/_legacy.py b/venv/Lib/site-packages/setuptools/_vendor/importlib_resources/_legacy.py new file mode 100644 index 0000000..1d5d3f1 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_vendor/importlib_resources/_legacy.py @@ -0,0 +1,121 @@ +import functools +import os +import pathlib +import types +import warnings + +from typing import Union, Iterable, ContextManager, BinaryIO, TextIO, Any + +from . import _common + +Package = Union[types.ModuleType, str] +Resource = str + + +def deprecated(func): + @functools.wraps(func) + def wrapper(*args, **kwargs): + warnings.warn( + f"{func.__name__} is deprecated. Use files() instead. " + "Refer to https://importlib-resources.readthedocs.io" + "/en/latest/using.html#migrating-from-legacy for migration advice.", + DeprecationWarning, + stacklevel=2, + ) + return func(*args, **kwargs) + + return wrapper + + +def normalize_path(path): + # type: (Any) -> str + """Normalize a path by ensuring it is a string. + + If the resulting string contains path separators, an exception is raised. + """ + str_path = str(path) + parent, file_name = os.path.split(str_path) + if parent: + raise ValueError(f'{path!r} must be only a file name') + return file_name + + +@deprecated +def open_binary(package: Package, resource: Resource) -> BinaryIO: + """Return a file-like object opened for binary reading of the resource.""" + return (_common.files(package) / normalize_path(resource)).open('rb') + + +@deprecated +def read_binary(package: Package, resource: Resource) -> bytes: + """Return the binary contents of the resource.""" + return (_common.files(package) / normalize_path(resource)).read_bytes() + + +@deprecated +def open_text( + package: Package, + resource: Resource, + encoding: str = 'utf-8', + errors: str = 'strict', +) -> TextIO: + """Return a file-like object opened for text reading of the resource.""" + return (_common.files(package) / normalize_path(resource)).open( + 'r', encoding=encoding, errors=errors + ) + + +@deprecated +def read_text( + package: Package, + resource: Resource, + encoding: str = 'utf-8', + errors: str = 'strict', +) -> str: + """Return the decoded string of the resource. + + The decoding-related arguments have the same semantics as those of + bytes.decode(). + """ + with open_text(package, resource, encoding, errors) as fp: + return fp.read() + + +@deprecated +def contents(package: Package) -> Iterable[str]: + """Return an iterable of entries in `package`. + + Note that not all entries are resources. Specifically, directories are + not considered resources. Use `is_resource()` on each entry returned here + to check if it is a resource or not. + """ + return [path.name for path in _common.files(package).iterdir()] + + +@deprecated +def is_resource(package: Package, name: str) -> bool: + """True if `name` is a resource inside `package`. + + Directories are *not* resources. + """ + resource = normalize_path(name) + return any( + traversable.name == resource and traversable.is_file() + for traversable in _common.files(package).iterdir() + ) + + +@deprecated +def path( + package: Package, + resource: Resource, +) -> ContextManager[pathlib.Path]: + """A context manager providing a file path object to the resource. + + If the resource does not already exist on its own on the file system, + a temporary file will be created. If the file was created, the file + will be deleted upon exiting the context manager (no exception is + raised if the file was deleted prior to the context manager + exiting). + """ + return _common.as_file(_common.files(package) / normalize_path(resource)) diff --git a/venv/Lib/site-packages/setuptools/_vendor/importlib_resources/abc.py b/venv/Lib/site-packages/setuptools/_vendor/importlib_resources/abc.py new file mode 100644 index 0000000..d39dc1a --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_vendor/importlib_resources/abc.py @@ -0,0 +1,137 @@ +import abc +from typing import BinaryIO, Iterable, Text + +from ._compat import runtime_checkable, Protocol + + +class ResourceReader(metaclass=abc.ABCMeta): + """Abstract base class for loaders to provide resource reading support.""" + + @abc.abstractmethod + def open_resource(self, resource: Text) -> BinaryIO: + """Return an opened, file-like object for binary reading. + + The 'resource' argument is expected to represent only a file name. + If the resource cannot be found, FileNotFoundError is raised. + """ + # This deliberately raises FileNotFoundError instead of + # NotImplementedError so that if this method is accidentally called, + # it'll still do the right thing. + raise FileNotFoundError + + @abc.abstractmethod + def resource_path(self, resource: Text) -> Text: + """Return the file system path to the specified resource. + + The 'resource' argument is expected to represent only a file name. + If the resource does not exist on the file system, raise + FileNotFoundError. + """ + # This deliberately raises FileNotFoundError instead of + # NotImplementedError so that if this method is accidentally called, + # it'll still do the right thing. + raise FileNotFoundError + + @abc.abstractmethod + def is_resource(self, path: Text) -> bool: + """Return True if the named 'path' is a resource. + + Files are resources, directories are not. + """ + raise FileNotFoundError + + @abc.abstractmethod + def contents(self) -> Iterable[str]: + """Return an iterable of entries in `package`.""" + raise FileNotFoundError + + +@runtime_checkable +class Traversable(Protocol): + """ + An object with a subset of pathlib.Path methods suitable for + traversing directories and opening files. + """ + + @abc.abstractmethod + def iterdir(self): + """ + Yield Traversable objects in self + """ + + def read_bytes(self): + """ + Read contents of self as bytes + """ + with self.open('rb') as strm: + return strm.read() + + def read_text(self, encoding=None): + """ + Read contents of self as text + """ + with self.open(encoding=encoding) as strm: + return strm.read() + + @abc.abstractmethod + def is_dir(self) -> bool: + """ + Return True if self is a directory + """ + + @abc.abstractmethod + def is_file(self) -> bool: + """ + Return True if self is a file + """ + + @abc.abstractmethod + def joinpath(self, child): + """ + Return Traversable child in self + """ + + def __truediv__(self, child): + """ + Return Traversable child in self + """ + return self.joinpath(child) + + @abc.abstractmethod + def open(self, mode='r', *args, **kwargs): + """ + mode may be 'r' or 'rb' to open as text or binary. Return a handle + suitable for reading (same as pathlib.Path.open). + + When opening as text, accepts encoding parameters such as those + accepted by io.TextIOWrapper. + """ + + @abc.abstractproperty + def name(self) -> str: + """ + The base name of this object without any parent references. + """ + + +class TraversableResources(ResourceReader): + """ + The required interface for providing traversable + resources. + """ + + @abc.abstractmethod + def files(self): + """Return a Traversable object for the loaded package.""" + + def open_resource(self, resource): + return self.files().joinpath(resource).open('rb') + + def resource_path(self, resource): + raise FileNotFoundError(resource) + + def is_resource(self, path): + return self.files().joinpath(path).is_file() + + def contents(self): + return (item.name for item in self.files().iterdir()) diff --git a/venv/Lib/site-packages/setuptools/_vendor/importlib_resources/readers.py b/venv/Lib/site-packages/setuptools/_vendor/importlib_resources/readers.py new file mode 100644 index 0000000..f1190ca --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_vendor/importlib_resources/readers.py @@ -0,0 +1,122 @@ +import collections +import pathlib +import operator + +from . import abc + +from ._itertools import unique_everseen +from ._compat import ZipPath + + +def remove_duplicates(items): + return iter(collections.OrderedDict.fromkeys(items)) + + +class FileReader(abc.TraversableResources): + def __init__(self, loader): + self.path = pathlib.Path(loader.path).parent + + def resource_path(self, resource): + """ + Return the file system path to prevent + `resources.path()` from creating a temporary + copy. + """ + return str(self.path.joinpath(resource)) + + def files(self): + return self.path + + +class ZipReader(abc.TraversableResources): + def __init__(self, loader, module): + _, _, name = module.rpartition('.') + self.prefix = loader.prefix.replace('\\', '/') + name + '/' + self.archive = loader.archive + + def open_resource(self, resource): + try: + return super().open_resource(resource) + except KeyError as exc: + raise FileNotFoundError(exc.args[0]) + + def is_resource(self, path): + # workaround for `zipfile.Path.is_file` returning true + # for non-existent paths. + target = self.files().joinpath(path) + return target.is_file() and target.exists() + + def files(self): + return ZipPath(self.archive, self.prefix) + + +class MultiplexedPath(abc.Traversable): + """ + Given a series of Traversable objects, implement a merged + version of the interface across all objects. Useful for + namespace packages which may be multihomed at a single + name. + """ + + def __init__(self, *paths): + self._paths = list(map(pathlib.Path, remove_duplicates(paths))) + if not self._paths: + message = 'MultiplexedPath must contain at least one path' + raise FileNotFoundError(message) + if not all(path.is_dir() for path in self._paths): + raise NotADirectoryError('MultiplexedPath only supports directories') + + def iterdir(self): + files = (file for path in self._paths for file in path.iterdir()) + return unique_everseen(files, key=operator.attrgetter('name')) + + def read_bytes(self): + raise FileNotFoundError(f'{self} is not a file') + + def read_text(self, *args, **kwargs): + raise FileNotFoundError(f'{self} is not a file') + + def is_dir(self): + return True + + def is_file(self): + return False + + def joinpath(self, child): + # first try to find child in current paths + for file in self.iterdir(): + if file.name == child: + return file + # if it does not exist, construct it with the first path + return self._paths[0] / child + + __truediv__ = joinpath + + def open(self, *args, **kwargs): + raise FileNotFoundError(f'{self} is not a file') + + @property + def name(self): + return self._paths[0].name + + def __repr__(self): + paths = ', '.join(f"'{path}'" for path in self._paths) + return f'MultiplexedPath({paths})' + + +class NamespaceReader(abc.TraversableResources): + def __init__(self, namespace_path): + if 'NamespacePath' not in str(namespace_path): + raise ValueError('Invalid path') + self.path = MultiplexedPath(*list(namespace_path)) + + def resource_path(self, resource): + """ + Return the file system path to prevent + `resources.path()` from creating a temporary + copy. + """ + return str(self.path.joinpath(resource)) + + def files(self): + return self.path diff --git a/venv/Lib/site-packages/setuptools/_vendor/importlib_resources/simple.py b/venv/Lib/site-packages/setuptools/_vendor/importlib_resources/simple.py new file mode 100644 index 0000000..da073cb --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_vendor/importlib_resources/simple.py @@ -0,0 +1,116 @@ +""" +Interface adapters for low-level readers. +""" + +import abc +import io +import itertools +from typing import BinaryIO, List + +from .abc import Traversable, TraversableResources + + +class SimpleReader(abc.ABC): + """ + The minimum, low-level interface required from a resource + provider. + """ + + @abc.abstractproperty + def package(self): + # type: () -> str + """ + The name of the package for which this reader loads resources. + """ + + @abc.abstractmethod + def children(self): + # type: () -> List['SimpleReader'] + """ + Obtain an iterable of SimpleReader for available + child containers (e.g. directories). + """ + + @abc.abstractmethod + def resources(self): + # type: () -> List[str] + """ + Obtain available named resources for this virtual package. + """ + + @abc.abstractmethod + def open_binary(self, resource): + # type: (str) -> BinaryIO + """ + Obtain a File-like for a named resource. + """ + + @property + def name(self): + return self.package.split('.')[-1] + + +class ResourceHandle(Traversable): + """ + Handle to a named resource in a ResourceReader. + """ + + def __init__(self, parent, name): + # type: (ResourceContainer, str) -> None + self.parent = parent + self.name = name # type: ignore + + def is_file(self): + return True + + def is_dir(self): + return False + + def open(self, mode='r', *args, **kwargs): + stream = self.parent.reader.open_binary(self.name) + if 'b' not in mode: + stream = io.TextIOWrapper(*args, **kwargs) + return stream + + def joinpath(self, name): + raise RuntimeError("Cannot traverse into a resource") + + +class ResourceContainer(Traversable): + """ + Traversable container for a package's resources via its reader. + """ + + def __init__(self, reader): + # type: (SimpleReader) -> None + self.reader = reader + + def is_dir(self): + return True + + def is_file(self): + return False + + def iterdir(self): + files = (ResourceHandle(self, name) for name in self.reader.resources) + dirs = map(ResourceContainer, self.reader.children()) + return itertools.chain(files, dirs) + + def open(self, *args, **kwargs): + raise IsADirectoryError() + + def joinpath(self, name): + return next( + traversable for traversable in self.iterdir() if traversable.name == name + ) + + +class TraversableReader(TraversableResources, SimpleReader): + """ + A TraversableResources based on SimpleReader. Resource providers + may derive from this class to provide the TraversableResources + interface by supplying the SimpleReader interface. + """ + + def files(self): + return ResourceContainer(self) diff --git a/venv/Lib/site-packages/setuptools/_vendor/jaraco/__init__.py b/venv/Lib/site-packages/setuptools/_vendor/jaraco/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/venv/Lib/site-packages/setuptools/_vendor/jaraco/__pycache__/__init__.cpython-39.pyc b/venv/Lib/site-packages/setuptools/_vendor/jaraco/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..dfb4dbed907990e8a3b10921b87aaad7c511b6a4 GIT binary patch literal 190 zcmYe~<>g`kf)07LBoO@=L?8o3AjbiSi&=m~3PUi1CZpdI zlbDy6SRCV6P~ehSk{IKYpPZNz6Ox)+5L1v@pj(<(keHmEnxb2tk(!#LYgn3?Rc>68 z8&jNGQd&@wpPy446JM5^my%x;la*MMn4BLIAD@|*SrQ+wS5SG2!zMRBr8Fni4rKXf HAZ7pn83r>t literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/_vendor/jaraco/__pycache__/context.cpython-39.pyc b/venv/Lib/site-packages/setuptools/_vendor/jaraco/__pycache__/context.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4544f5791deddaaec977f8162a8764b9fd60b924 GIT binary patch literal 6275 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 UHd}binYP*d3|b55vFAGf1un!3Z2$lO literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/_vendor/jaraco/__pycache__/functools.cpython-39.pyc b/venv/Lib/site-packages/setuptools/_vendor/jaraco/__pycache__/functools.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f6674394ce6094dc0ce1d7078023f8fff2a6db14 GIT binary patch literal 15646 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 BrriJl literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/_vendor/jaraco/context.py b/venv/Lib/site-packages/setuptools/_vendor/jaraco/context.py new file mode 100644 index 0000000..87a4e3d --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_vendor/jaraco/context.py @@ -0,0 +1,213 @@ +import os +import subprocess +import contextlib +import functools +import tempfile +import shutil +import operator + + +@contextlib.contextmanager +def pushd(dir): + orig = os.getcwd() + os.chdir(dir) + try: + yield dir + finally: + os.chdir(orig) + + +@contextlib.contextmanager +def tarball_context(url, target_dir=None, runner=None, pushd=pushd): + """ + Get a tarball, extract it, change to that directory, yield, then + clean up. + `runner` is the function to invoke commands. + `pushd` is a context manager for changing the directory. + """ + if target_dir is None: + target_dir = os.path.basename(url).replace('.tar.gz', '').replace('.tgz', '') + if runner is None: + runner = functools.partial(subprocess.check_call, shell=True) + # In the tar command, use --strip-components=1 to strip the first path and + # then + # use -C to cause the files to be extracted to {target_dir}. This ensures + # that we always know where the files were extracted. + runner('mkdir {target_dir}'.format(**vars())) + try: + getter = 'wget {url} -O -' + extract = 'tar x{compression} --strip-components=1 -C {target_dir}' + cmd = ' | '.join((getter, extract)) + runner(cmd.format(compression=infer_compression(url), **vars())) + with pushd(target_dir): + yield target_dir + finally: + runner('rm -Rf {target_dir}'.format(**vars())) + + +def infer_compression(url): + """ + Given a URL or filename, infer the compression code for tar. + """ + # cheat and just assume it's the last two characters + compression_indicator = url[-2:] + mapping = dict(gz='z', bz='j', xz='J') + # Assume 'z' (gzip) if no match + return mapping.get(compression_indicator, 'z') + + +@contextlib.contextmanager +def temp_dir(remover=shutil.rmtree): + """ + Create a temporary directory context. Pass a custom remover + to override the removal behavior. + """ + temp_dir = tempfile.mkdtemp() + try: + yield temp_dir + finally: + remover(temp_dir) + + +@contextlib.contextmanager +def repo_context(url, branch=None, quiet=True, dest_ctx=temp_dir): + """ + Check out the repo indicated by url. + + If dest_ctx is supplied, it should be a context manager + to yield the target directory for the check out. + """ + exe = 'git' if 'git' in url else 'hg' + with dest_ctx() as repo_dir: + cmd = [exe, 'clone', url, repo_dir] + if branch: + cmd.extend(['--branch', branch]) + devnull = open(os.path.devnull, 'w') + stdout = devnull if quiet else None + subprocess.check_call(cmd, stdout=stdout) + yield repo_dir + + +@contextlib.contextmanager +def null(): + yield + + +class ExceptionTrap: + """ + A context manager that will catch certain exceptions and provide an + indication they occurred. + + >>> with ExceptionTrap() as trap: + ... raise Exception() + >>> bool(trap) + True + + >>> with ExceptionTrap() as trap: + ... pass + >>> bool(trap) + False + + >>> with ExceptionTrap(ValueError) as trap: + ... raise ValueError("1 + 1 is not 3") + >>> bool(trap) + True + + >>> with ExceptionTrap(ValueError) as trap: + ... raise Exception() + Traceback (most recent call last): + ... + Exception + + >>> bool(trap) + False + """ + + exc_info = None, None, None + + def __init__(self, exceptions=(Exception,)): + self.exceptions = exceptions + + def __enter__(self): + return self + + @property + def type(self): + return self.exc_info[0] + + @property + def value(self): + return self.exc_info[1] + + @property + def tb(self): + return self.exc_info[2] + + def __exit__(self, *exc_info): + type = exc_info[0] + matches = type and issubclass(type, self.exceptions) + if matches: + self.exc_info = exc_info + return matches + + def __bool__(self): + return bool(self.type) + + def raises(self, func, *, _test=bool): + """ + Wrap func and replace the result with the truth + value of the trap (True if an exception occurred). + + First, give the decorator an alias to support Python 3.8 + Syntax. + + >>> raises = ExceptionTrap(ValueError).raises + + Now decorate a function that always fails. + + >>> @raises + ... def fail(): + ... raise ValueError('failed') + >>> fail() + True + """ + + @functools.wraps(func) + def wrapper(*args, **kwargs): + with ExceptionTrap(self.exceptions) as trap: + func(*args, **kwargs) + return _test(trap) + + return wrapper + + def passes(self, func): + """ + Wrap func and replace the result with the truth + value of the trap (True if no exception). + + First, give the decorator an alias to support Python 3.8 + Syntax. + + >>> passes = ExceptionTrap(ValueError).passes + + Now decorate a function that always fails. + + >>> @passes + ... def fail(): + ... raise ValueError('failed') + + >>> fail() + False + """ + return self.raises(func, _test=operator.not_) + + +class suppress(contextlib.suppress, contextlib.ContextDecorator): + """ + A version of contextlib.suppress with decorator support. + + >>> @suppress(KeyError) + ... def key_error(): + ... {}[''] + >>> key_error() + """ diff --git a/venv/Lib/site-packages/setuptools/_vendor/jaraco/functools.py b/venv/Lib/site-packages/setuptools/_vendor/jaraco/functools.py new file mode 100644 index 0000000..bbd8b29 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_vendor/jaraco/functools.py @@ -0,0 +1,525 @@ +import functools +import time +import inspect +import collections +import types +import itertools + +import setuptools.extern.more_itertools + +from typing import Callable, TypeVar + + +CallableT = TypeVar("CallableT", bound=Callable[..., object]) + + +def compose(*funcs): + """ + Compose any number of unary functions into a single unary function. + + >>> import textwrap + >>> expected = str.strip(textwrap.dedent(compose.__doc__)) + >>> strip_and_dedent = compose(str.strip, textwrap.dedent) + >>> strip_and_dedent(compose.__doc__) == expected + True + + Compose also allows the innermost function to take arbitrary arguments. + + >>> round_three = lambda x: round(x, ndigits=3) + >>> f = compose(round_three, int.__truediv__) + >>> [f(3*x, x+1) for x in range(1,10)] + [1.5, 2.0, 2.25, 2.4, 2.5, 2.571, 2.625, 2.667, 2.7] + """ + + def compose_two(f1, f2): + return lambda *args, **kwargs: f1(f2(*args, **kwargs)) + + return functools.reduce(compose_two, funcs) + + +def method_caller(method_name, *args, **kwargs): + """ + Return a function that will call a named method on the + target object with optional positional and keyword + arguments. + + >>> lower = method_caller('lower') + >>> lower('MyString') + 'mystring' + """ + + def call_method(target): + func = getattr(target, method_name) + return func(*args, **kwargs) + + return call_method + + +def once(func): + """ + Decorate func so it's only ever called the first time. + + This decorator can ensure that an expensive or non-idempotent function + will not be expensive on subsequent calls and is idempotent. + + >>> add_three = once(lambda a: a+3) + >>> add_three(3) + 6 + >>> add_three(9) + 6 + >>> add_three('12') + 6 + + To reset the stored value, simply clear the property ``saved_result``. + + >>> del add_three.saved_result + >>> add_three(9) + 12 + >>> add_three(8) + 12 + + Or invoke 'reset()' on it. + + >>> add_three.reset() + >>> add_three(-3) + 0 + >>> add_three(0) + 0 + """ + + @functools.wraps(func) + def wrapper(*args, **kwargs): + if not hasattr(wrapper, 'saved_result'): + wrapper.saved_result = func(*args, **kwargs) + return wrapper.saved_result + + wrapper.reset = lambda: vars(wrapper).__delitem__('saved_result') + return wrapper + + +def method_cache( + method: CallableT, + cache_wrapper: Callable[ + [CallableT], CallableT + ] = functools.lru_cache(), # type: ignore[assignment] +) -> CallableT: + """ + Wrap lru_cache to support storing the cache data in the object instances. + + Abstracts the common paradigm where the method explicitly saves an + underscore-prefixed protected property on first call and returns that + subsequently. + + >>> class MyClass: + ... calls = 0 + ... + ... @method_cache + ... def method(self, value): + ... self.calls += 1 + ... return value + + >>> a = MyClass() + >>> a.method(3) + 3 + >>> for x in range(75): + ... res = a.method(x) + >>> a.calls + 75 + + Note that the apparent behavior will be exactly like that of lru_cache + except that the cache is stored on each instance, so values in one + instance will not flush values from another, and when an instance is + deleted, so are the cached values for that instance. + + >>> b = MyClass() + >>> for x in range(35): + ... res = b.method(x) + >>> b.calls + 35 + >>> a.method(0) + 0 + >>> a.calls + 75 + + Note that if method had been decorated with ``functools.lru_cache()``, + a.calls would have been 76 (due to the cached value of 0 having been + flushed by the 'b' instance). + + Clear the cache with ``.cache_clear()`` + + >>> a.method.cache_clear() + + Same for a method that hasn't yet been called. + + >>> c = MyClass() + >>> c.method.cache_clear() + + Another cache wrapper may be supplied: + + >>> cache = functools.lru_cache(maxsize=2) + >>> MyClass.method2 = method_cache(lambda self: 3, cache_wrapper=cache) + >>> a = MyClass() + >>> a.method2() + 3 + + Caution - do not subsequently wrap the method with another decorator, such + as ``@property``, which changes the semantics of the function. + + See also + http://code.activestate.com/recipes/577452-a-memoize-decorator-for-instance-methods/ + for another implementation and additional justification. + """ + + def wrapper(self: object, *args: object, **kwargs: object) -> object: + # it's the first call, replace the method with a cached, bound method + bound_method: CallableT = types.MethodType( # type: ignore[assignment] + method, self + ) + cached_method = cache_wrapper(bound_method) + setattr(self, method.__name__, cached_method) + return cached_method(*args, **kwargs) + + # Support cache clear even before cache has been created. + wrapper.cache_clear = lambda: None # type: ignore[attr-defined] + + return ( # type: ignore[return-value] + _special_method_cache(method, cache_wrapper) or wrapper + ) + + +def _special_method_cache(method, cache_wrapper): + """ + Because Python treats special methods differently, it's not + possible to use instance attributes to implement the cached + methods. + + Instead, install the wrapper method under a different name + and return a simple proxy to that wrapper. + + https://github.com/jaraco/jaraco.functools/issues/5 + """ + name = method.__name__ + special_names = '__getattr__', '__getitem__' + if name not in special_names: + return + + wrapper_name = '__cached' + name + + def proxy(self, *args, **kwargs): + if wrapper_name not in vars(self): + bound = types.MethodType(method, self) + cache = cache_wrapper(bound) + setattr(self, wrapper_name, cache) + else: + cache = getattr(self, wrapper_name) + return cache(*args, **kwargs) + + return proxy + + +def apply(transform): + """ + Decorate a function with a transform function that is + invoked on results returned from the decorated function. + + >>> @apply(reversed) + ... def get_numbers(start): + ... "doc for get_numbers" + ... return range(start, start+3) + >>> list(get_numbers(4)) + [6, 5, 4] + >>> get_numbers.__doc__ + 'doc for get_numbers' + """ + + def wrap(func): + return functools.wraps(func)(compose(transform, func)) + + return wrap + + +def result_invoke(action): + r""" + Decorate a function with an action function that is + invoked on the results returned from the decorated + function (for its side-effect), then return the original + result. + + >>> @result_invoke(print) + ... def add_two(a, b): + ... return a + b + >>> x = add_two(2, 3) + 5 + >>> x + 5 + """ + + def wrap(func): + @functools.wraps(func) + def wrapper(*args, **kwargs): + result = func(*args, **kwargs) + action(result) + return result + + return wrapper + + return wrap + + +def call_aside(f, *args, **kwargs): + """ + Call a function for its side effect after initialization. + + >>> @call_aside + ... def func(): print("called") + called + >>> func() + called + + Use functools.partial to pass parameters to the initial call + + >>> @functools.partial(call_aside, name='bingo') + ... def func(name): print("called with", name) + called with bingo + """ + f(*args, **kwargs) + return f + + +class Throttler: + """ + Rate-limit a function (or other callable) + """ + + def __init__(self, func, max_rate=float('Inf')): + if isinstance(func, Throttler): + func = func.func + self.func = func + self.max_rate = max_rate + self.reset() + + def reset(self): + self.last_called = 0 + + def __call__(self, *args, **kwargs): + self._wait() + return self.func(*args, **kwargs) + + def _wait(self): + "ensure at least 1/max_rate seconds from last call" + elapsed = time.time() - self.last_called + must_wait = 1 / self.max_rate - elapsed + time.sleep(max(0, must_wait)) + self.last_called = time.time() + + def __get__(self, obj, type=None): + return first_invoke(self._wait, functools.partial(self.func, obj)) + + +def first_invoke(func1, func2): + """ + Return a function that when invoked will invoke func1 without + any parameters (for its side-effect) and then invoke func2 + with whatever parameters were passed, returning its result. + """ + + def wrapper(*args, **kwargs): + func1() + return func2(*args, **kwargs) + + return wrapper + + +def retry_call(func, cleanup=lambda: None, retries=0, trap=()): + """ + Given a callable func, trap the indicated exceptions + for up to 'retries' times, invoking cleanup on the + exception. On the final attempt, allow any exceptions + to propagate. + """ + attempts = itertools.count() if retries == float('inf') else range(retries) + for attempt in attempts: + try: + return func() + except trap: + cleanup() + + return func() + + +def retry(*r_args, **r_kwargs): + """ + Decorator wrapper for retry_call. Accepts arguments to retry_call + except func and then returns a decorator for the decorated function. + + Ex: + + >>> @retry(retries=3) + ... def my_func(a, b): + ... "this is my funk" + ... print(a, b) + >>> my_func.__doc__ + 'this is my funk' + """ + + def decorate(func): + @functools.wraps(func) + def wrapper(*f_args, **f_kwargs): + bound = functools.partial(func, *f_args, **f_kwargs) + return retry_call(bound, *r_args, **r_kwargs) + + return wrapper + + return decorate + + +def print_yielded(func): + """ + Convert a generator into a function that prints all yielded elements + + >>> @print_yielded + ... def x(): + ... yield 3; yield None + >>> x() + 3 + None + """ + print_all = functools.partial(map, print) + print_results = compose(more_itertools.consume, print_all, func) + return functools.wraps(func)(print_results) + + +def pass_none(func): + """ + Wrap func so it's not called if its first param is None + + >>> print_text = pass_none(print) + >>> print_text('text') + text + >>> print_text(None) + """ + + @functools.wraps(func) + def wrapper(param, *args, **kwargs): + if param is not None: + return func(param, *args, **kwargs) + + return wrapper + + +def assign_params(func, namespace): + """ + Assign parameters from namespace where func solicits. + + >>> def func(x, y=3): + ... print(x, y) + >>> assigned = assign_params(func, dict(x=2, z=4)) + >>> assigned() + 2 3 + + The usual errors are raised if a function doesn't receive + its required parameters: + + >>> assigned = assign_params(func, dict(y=3, z=4)) + >>> assigned() + Traceback (most recent call last): + TypeError: func() ...argument... + + It even works on methods: + + >>> class Handler: + ... def meth(self, arg): + ... print(arg) + >>> assign_params(Handler().meth, dict(arg='crystal', foo='clear'))() + crystal + """ + sig = inspect.signature(func) + params = sig.parameters.keys() + call_ns = {k: namespace[k] for k in params if k in namespace} + return functools.partial(func, **call_ns) + + +def save_method_args(method): + """ + Wrap a method such that when it is called, the args and kwargs are + saved on the method. + + >>> class MyClass: + ... @save_method_args + ... def method(self, a, b): + ... print(a, b) + >>> my_ob = MyClass() + >>> my_ob.method(1, 2) + 1 2 + >>> my_ob._saved_method.args + (1, 2) + >>> my_ob._saved_method.kwargs + {} + >>> my_ob.method(a=3, b='foo') + 3 foo + >>> my_ob._saved_method.args + () + >>> my_ob._saved_method.kwargs == dict(a=3, b='foo') + True + + The arguments are stored on the instance, allowing for + different instance to save different args. + + >>> your_ob = MyClass() + >>> your_ob.method({str('x'): 3}, b=[4]) + {'x': 3} [4] + >>> your_ob._saved_method.args + ({'x': 3},) + >>> my_ob._saved_method.args + () + """ + args_and_kwargs = collections.namedtuple('args_and_kwargs', 'args kwargs') + + @functools.wraps(method) + def wrapper(self, *args, **kwargs): + attr_name = '_saved_' + method.__name__ + attr = args_and_kwargs(args, kwargs) + setattr(self, attr_name, attr) + return method(self, *args, **kwargs) + + return wrapper + + +def except_(*exceptions, replace=None, use=None): + """ + Replace the indicated exceptions, if raised, with the indicated + literal replacement or evaluated expression (if present). + + >>> safe_int = except_(ValueError)(int) + >>> safe_int('five') + >>> safe_int('5') + 5 + + Specify a literal replacement with ``replace``. + + >>> safe_int_r = except_(ValueError, replace=0)(int) + >>> safe_int_r('five') + 0 + + Provide an expression to ``use`` to pass through particular parameters. + + >>> safe_int_pt = except_(ValueError, use='args[0]')(int) + >>> safe_int_pt('five') + 'five' + + """ + + def decorate(func): + @functools.wraps(func) + def wrapper(*args, **kwargs): + try: + return func(*args, **kwargs) + except exceptions: + try: + return eval(use) + except TypeError: + return replace + + return wrapper + + return decorate diff --git a/venv/Lib/site-packages/setuptools/_vendor/jaraco/text/__init__.py b/venv/Lib/site-packages/setuptools/_vendor/jaraco/text/__init__.py new file mode 100644 index 0000000..a0306d5 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_vendor/jaraco/text/__init__.py @@ -0,0 +1,599 @@ +import re +import itertools +import textwrap +import functools + +try: + from importlib.resources import files # type: ignore +except ImportError: # pragma: nocover + from setuptools.extern.importlib_resources import files # type: ignore + +from setuptools.extern.jaraco.functools import compose, method_cache +from setuptools.extern.jaraco.context import ExceptionTrap + + +def substitution(old, new): + """ + Return a function that will perform a substitution on a string + """ + return lambda s: s.replace(old, new) + + +def multi_substitution(*substitutions): + """ + Take a sequence of pairs specifying substitutions, and create + a function that performs those substitutions. + + >>> multi_substitution(('foo', 'bar'), ('bar', 'baz'))('foo') + 'baz' + """ + substitutions = itertools.starmap(substitution, substitutions) + # compose function applies last function first, so reverse the + # substitutions to get the expected order. + substitutions = reversed(tuple(substitutions)) + return compose(*substitutions) + + +class FoldedCase(str): + """ + A case insensitive string class; behaves just like str + except compares equal when the only variation is case. + + >>> s = FoldedCase('hello world') + + >>> s == 'Hello World' + True + + >>> 'Hello World' == s + True + + >>> s != 'Hello World' + False + + >>> s.index('O') + 4 + + >>> s.split('O') + ['hell', ' w', 'rld'] + + >>> sorted(map(FoldedCase, ['GAMMA', 'alpha', 'Beta'])) + ['alpha', 'Beta', 'GAMMA'] + + Sequence membership is straightforward. + + >>> "Hello World" in [s] + True + >>> s in ["Hello World"] + True + + You may test for set inclusion, but candidate and elements + must both be folded. + + >>> FoldedCase("Hello World") in {s} + True + >>> s in {FoldedCase("Hello World")} + True + + String inclusion works as long as the FoldedCase object + is on the right. + + >>> "hello" in FoldedCase("Hello World") + True + + But not if the FoldedCase object is on the left: + + >>> FoldedCase('hello') in 'Hello World' + False + + In that case, use ``in_``: + + >>> FoldedCase('hello').in_('Hello World') + True + + >>> FoldedCase('hello') > FoldedCase('Hello') + False + """ + + def __lt__(self, other): + return self.lower() < other.lower() + + def __gt__(self, other): + return self.lower() > other.lower() + + def __eq__(self, other): + return self.lower() == other.lower() + + def __ne__(self, other): + return self.lower() != other.lower() + + def __hash__(self): + return hash(self.lower()) + + def __contains__(self, other): + return super().lower().__contains__(other.lower()) + + def in_(self, other): + "Does self appear in other?" + return self in FoldedCase(other) + + # cache lower since it's likely to be called frequently. + @method_cache + def lower(self): + return super().lower() + + def index(self, sub): + return self.lower().index(sub.lower()) + + def split(self, splitter=' ', maxsplit=0): + pattern = re.compile(re.escape(splitter), re.I) + return pattern.split(self, maxsplit) + + +# Python 3.8 compatibility +_unicode_trap = ExceptionTrap(UnicodeDecodeError) + + +@_unicode_trap.passes +def is_decodable(value): + r""" + Return True if the supplied value is decodable (using the default + encoding). + + >>> is_decodable(b'\xff') + False + >>> is_decodable(b'\x32') + True + """ + value.decode() + + +def is_binary(value): + r""" + Return True if the value appears to be binary (that is, it's a byte + string and isn't decodable). + + >>> is_binary(b'\xff') + True + >>> is_binary('\xff') + False + """ + return isinstance(value, bytes) and not is_decodable(value) + + +def trim(s): + r""" + Trim something like a docstring to remove the whitespace that + is common due to indentation and formatting. + + >>> trim("\n\tfoo = bar\n\t\tbar = baz\n") + 'foo = bar\n\tbar = baz' + """ + return textwrap.dedent(s).strip() + + +def wrap(s): + """ + Wrap lines of text, retaining existing newlines as + paragraph markers. + + >>> print(wrap(lorem_ipsum)) + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do + eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad + minim veniam, quis nostrud exercitation ullamco laboris nisi ut + aliquip ex ea commodo consequat. Duis aute irure dolor in + reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla + pariatur. Excepteur sint occaecat cupidatat non proident, sunt in + culpa qui officia deserunt mollit anim id est laborum. + + Curabitur pretium tincidunt lacus. Nulla gravida orci a odio. Nullam + varius, turpis et commodo pharetra, est eros bibendum elit, nec luctus + magna felis sollicitudin mauris. Integer in mauris eu nibh euismod + gravida. Duis ac tellus et risus vulputate vehicula. Donec lobortis + risus a elit. Etiam tempor. Ut ullamcorper, ligula eu tempor congue, + eros est euismod turpis, id tincidunt sapien risus a quam. Maecenas + fermentum consequat mi. Donec fermentum. Pellentesque malesuada nulla + a mi. Duis sapien sem, aliquet nec, commodo eget, consequat quis, + neque. Aliquam faucibus, elit ut dictum aliquet, felis nisl adipiscing + sapien, sed malesuada diam lacus eget erat. Cras mollis scelerisque + nunc. Nullam arcu. Aliquam consequat. Curabitur augue lorem, dapibus + quis, laoreet et, pretium ac, nisi. Aenean magna nisl, mollis quis, + molestie eu, feugiat in, orci. In hac habitasse platea dictumst. + """ + paragraphs = s.splitlines() + wrapped = ('\n'.join(textwrap.wrap(para)) for para in paragraphs) + return '\n\n'.join(wrapped) + + +def unwrap(s): + r""" + Given a multi-line string, return an unwrapped version. + + >>> wrapped = wrap(lorem_ipsum) + >>> wrapped.count('\n') + 20 + >>> unwrapped = unwrap(wrapped) + >>> unwrapped.count('\n') + 1 + >>> print(unwrapped) + Lorem ipsum dolor sit amet, consectetur adipiscing ... + Curabitur pretium tincidunt lacus. Nulla gravida orci ... + + """ + paragraphs = re.split(r'\n\n+', s) + cleaned = (para.replace('\n', ' ') for para in paragraphs) + return '\n'.join(cleaned) + + + + +class Splitter(object): + """object that will split a string with the given arguments for each call + + >>> s = Splitter(',') + >>> s('hello, world, this is your, master calling') + ['hello', ' world', ' this is your', ' master calling'] + """ + + def __init__(self, *args): + self.args = args + + def __call__(self, s): + return s.split(*self.args) + + +def indent(string, prefix=' ' * 4): + """ + >>> indent('foo') + ' foo' + """ + return prefix + string + + +class WordSet(tuple): + """ + Given an identifier, return the words that identifier represents, + whether in camel case, underscore-separated, etc. + + >>> WordSet.parse("camelCase") + ('camel', 'Case') + + >>> WordSet.parse("under_sep") + ('under', 'sep') + + Acronyms should be retained + + >>> WordSet.parse("firstSNL") + ('first', 'SNL') + + >>> WordSet.parse("you_and_I") + ('you', 'and', 'I') + + >>> WordSet.parse("A simple test") + ('A', 'simple', 'test') + + Multiple caps should not interfere with the first cap of another word. + + >>> WordSet.parse("myABCClass") + ('my', 'ABC', 'Class') + + The result is a WordSet, so you can get the form you need. + + >>> WordSet.parse("myABCClass").underscore_separated() + 'my_ABC_Class' + + >>> WordSet.parse('a-command').camel_case() + 'ACommand' + + >>> WordSet.parse('someIdentifier').lowered().space_separated() + 'some identifier' + + Slices of the result should return another WordSet. + + >>> WordSet.parse('taken-out-of-context')[1:].underscore_separated() + 'out_of_context' + + >>> WordSet.from_class_name(WordSet()).lowered().space_separated() + 'word set' + + >>> example = WordSet.parse('figured it out') + >>> example.headless_camel_case() + 'figuredItOut' + >>> example.dash_separated() + 'figured-it-out' + + """ + + _pattern = re.compile('([A-Z]?[a-z]+)|([A-Z]+(?![a-z]))') + + def capitalized(self): + return WordSet(word.capitalize() for word in self) + + def lowered(self): + return WordSet(word.lower() for word in self) + + def camel_case(self): + return ''.join(self.capitalized()) + + def headless_camel_case(self): + words = iter(self) + first = next(words).lower() + new_words = itertools.chain((first,), WordSet(words).camel_case()) + return ''.join(new_words) + + def underscore_separated(self): + return '_'.join(self) + + def dash_separated(self): + return '-'.join(self) + + def space_separated(self): + return ' '.join(self) + + def trim_right(self, item): + """ + Remove the item from the end of the set. + + >>> WordSet.parse('foo bar').trim_right('foo') + ('foo', 'bar') + >>> WordSet.parse('foo bar').trim_right('bar') + ('foo',) + >>> WordSet.parse('').trim_right('bar') + () + """ + return self[:-1] if self and self[-1] == item else self + + def trim_left(self, item): + """ + Remove the item from the beginning of the set. + + >>> WordSet.parse('foo bar').trim_left('foo') + ('bar',) + >>> WordSet.parse('foo bar').trim_left('bar') + ('foo', 'bar') + >>> WordSet.parse('').trim_left('bar') + () + """ + return self[1:] if self and self[0] == item else self + + def trim(self, item): + """ + >>> WordSet.parse('foo bar').trim('foo') + ('bar',) + """ + return self.trim_left(item).trim_right(item) + + def __getitem__(self, item): + result = super(WordSet, self).__getitem__(item) + if isinstance(item, slice): + result = WordSet(result) + return result + + @classmethod + def parse(cls, identifier): + matches = cls._pattern.finditer(identifier) + return WordSet(match.group(0) for match in matches) + + @classmethod + def from_class_name(cls, subject): + return cls.parse(subject.__class__.__name__) + + +# for backward compatibility +words = WordSet.parse + + +def simple_html_strip(s): + r""" + Remove HTML from the string `s`. + + >>> str(simple_html_strip('')) + '' + + >>> print(simple_html_strip('A stormy day in paradise')) + A stormy day in paradise + + >>> print(simple_html_strip('Somebody tell the truth.')) + Somebody tell the truth. + + >>> print(simple_html_strip('What about
    \nmultiple lines?')) + What about + multiple lines? + """ + html_stripper = re.compile('()|(<[^>]*>)|([^<]+)', re.DOTALL) + texts = (match.group(3) or '' for match in html_stripper.finditer(s)) + return ''.join(texts) + + +class SeparatedValues(str): + """ + A string separated by a separator. Overrides __iter__ for getting + the values. + + >>> list(SeparatedValues('a,b,c')) + ['a', 'b', 'c'] + + Whitespace is stripped and empty values are discarded. + + >>> list(SeparatedValues(' a, b , c, ')) + ['a', 'b', 'c'] + """ + + separator = ',' + + def __iter__(self): + parts = self.split(self.separator) + return filter(None, (part.strip() for part in parts)) + + +class Stripper: + r""" + Given a series of lines, find the common prefix and strip it from them. + + >>> lines = [ + ... 'abcdefg\n', + ... 'abc\n', + ... 'abcde\n', + ... ] + >>> res = Stripper.strip_prefix(lines) + >>> res.prefix + 'abc' + >>> list(res.lines) + ['defg\n', '\n', 'de\n'] + + If no prefix is common, nothing should be stripped. + + >>> lines = [ + ... 'abcd\n', + ... '1234\n', + ... ] + >>> res = Stripper.strip_prefix(lines) + >>> res.prefix = '' + >>> list(res.lines) + ['abcd\n', '1234\n'] + """ + + def __init__(self, prefix, lines): + self.prefix = prefix + self.lines = map(self, lines) + + @classmethod + def strip_prefix(cls, lines): + prefix_lines, lines = itertools.tee(lines) + prefix = functools.reduce(cls.common_prefix, prefix_lines) + return cls(prefix, lines) + + def __call__(self, line): + if not self.prefix: + return line + null, prefix, rest = line.partition(self.prefix) + return rest + + @staticmethod + def common_prefix(s1, s2): + """ + Return the common prefix of two lines. + """ + index = min(len(s1), len(s2)) + while s1[:index] != s2[:index]: + index -= 1 + return s1[:index] + + +def remove_prefix(text, prefix): + """ + Remove the prefix from the text if it exists. + + >>> remove_prefix('underwhelming performance', 'underwhelming ') + 'performance' + + >>> remove_prefix('something special', 'sample') + 'something special' + """ + null, prefix, rest = text.rpartition(prefix) + return rest + + +def remove_suffix(text, suffix): + """ + Remove the suffix from the text if it exists. + + >>> remove_suffix('name.git', '.git') + 'name' + + >>> remove_suffix('something special', 'sample') + 'something special' + """ + rest, suffix, null = text.partition(suffix) + return rest + + +def normalize_newlines(text): + r""" + Replace alternate newlines with the canonical newline. + + >>> normalize_newlines('Lorem Ipsum\u2029') + 'Lorem Ipsum\n' + >>> normalize_newlines('Lorem Ipsum\r\n') + 'Lorem Ipsum\n' + >>> normalize_newlines('Lorem Ipsum\x85') + 'Lorem Ipsum\n' + """ + newlines = ['\r\n', '\r', '\n', '\u0085', '\u2028', '\u2029'] + pattern = '|'.join(newlines) + return re.sub(pattern, '\n', text) + + +def _nonblank(str): + return str and not str.startswith('#') + + +@functools.singledispatch +def yield_lines(iterable): + r""" + Yield valid lines of a string or iterable. + + >>> list(yield_lines('')) + [] + >>> list(yield_lines(['foo', 'bar'])) + ['foo', 'bar'] + >>> list(yield_lines('foo\nbar')) + ['foo', 'bar'] + >>> list(yield_lines('\nfoo\n#bar\nbaz #comment')) + ['foo', 'baz #comment'] + >>> list(yield_lines(['foo\nbar', 'baz', 'bing\n\n\n'])) + ['foo', 'bar', 'baz', 'bing'] + """ + return itertools.chain.from_iterable(map(yield_lines, iterable)) + + +@yield_lines.register(str) +def _(text): + return filter(_nonblank, map(str.strip, text.splitlines())) + + +def drop_comment(line): + """ + Drop comments. + + >>> drop_comment('foo # bar') + 'foo' + + A hash without a space may be in a URL. + + >>> drop_comment('http://example.com/foo#bar') + 'http://example.com/foo#bar' + """ + return line.partition(' #')[0] + + +def join_continuation(lines): + r""" + Join lines continued by a trailing backslash. + + >>> list(join_continuation(['foo \\', 'bar', 'baz'])) + ['foobar', 'baz'] + >>> list(join_continuation(['foo \\', 'bar', 'baz'])) + ['foobar', 'baz'] + >>> list(join_continuation(['foo \\', 'bar \\', 'baz'])) + ['foobarbaz'] + + Not sure why, but... + The character preceeding the backslash is also elided. + + >>> list(join_continuation(['goo\\', 'dly'])) + ['godly'] + + A terrible idea, but... + If no line is available to continue, suppress the lines. + + >>> list(join_continuation(['foo', 'bar\\', 'baz\\'])) + ['foo'] + """ + lines = iter(lines) + for item in lines: + while item.endswith('\\'): + try: + item = item[:-2].strip() + next(lines) + except StopIteration: + return + yield item diff --git a/venv/Lib/site-packages/setuptools/_vendor/jaraco/text/__pycache__/__init__.cpython-39.pyc b/venv/Lib/site-packages/setuptools/_vendor/jaraco/text/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b51b056df15351965a376a979c37a3f7fc6b7436 GIT binary patch literal 19672 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%0D!(V*0?$b0*v>&Yj#>!uBv@~q(Ag{LCETUe z=V_dS4z}gU4&qRjjlX%pSA+QSJB}`oPEJl>#;3s{WS~R> z-J^xTGBB+Z61-MF#4>@eU&qe~zM{GOdY()XH>du16mh64@TH*^zQH;!agG`YJX^T@ z6^U}eP`quZuMLjDWQ3Za@yJ)IkVinc^Jw9Q@pj?8#Zn0o$A14RCjlGw{##h(HQ_`1)v?OpjB3dt#G zp5sE|AAeK^0+eoW3um;5F~-AEtjQU#HjZ}TRfh?Ys!5C9f+Q3iI_=#YWLv&GCp!R> zDv$44Vpv4C@W&kzz_edZSuc}c1tI07OuQnO5Seca^#F39|EfalG<+<2#KcXgJiyHm zfn&*c*H~Zu=)aJ^g$UdLM@JRptwsB3IYU;D<}ZYP?;Q1y_-3Ydf|=49-AjkY5cPR( zC~Dlo(F)R9vxaFLLr@BTvO)!O68ug8Byr~!)_##bZl*i1XF9UpJDL$>f6sS_=KzeZl{U1QRI zWYD;Ed@4;*xyzryk-t`>W%C0BZt3eV@qEWU%lB+u4dZ;XuM3;lvAwma9$yZLU*qJ< znUb@VcO>LodNid^lgrUzIjF0sEcDrx@9@s$g)wJ|y@}5y4uPUkD+ZA0jc9>y__o3E zkiE>-QA6?X_G}^W3)ZA^5J4y8$dOZ&int(^llo=pQ#7Ii#^Omx{4-5s5rkYaaV=J+ yD+d?ftrSbfER#eBDvwo;EFPS#EPlICoGRk}{)Nw07VvMeQbL<0utKSF@P7bTqHFH} literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/_vendor/more_itertools/__init__.py b/venv/Lib/site-packages/setuptools/_vendor/more_itertools/__init__.py new file mode 100644 index 0000000..19a169f --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_vendor/more_itertools/__init__.py @@ -0,0 +1,4 @@ +from .more import * # noqa +from .recipes import * # noqa + +__version__ = '8.8.0' diff --git a/venv/Lib/site-packages/setuptools/_vendor/more_itertools/__pycache__/__init__.cpython-39.pyc b/venv/Lib/site-packages/setuptools/_vendor/more_itertools/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9acca37b43db929f43ca35daf995d45784fb4b92 GIT binary patch literal 264 zcmYjL!Ait15KX!ji?Vlb-h>J*E_+!-MA4&oSl3GlgxCxiH%*2lbISNx@3J^2fs zobGz?!Mw+t$1qP#rw5GiaeVT$B>fuAe`I8?XyOr(W|~{J+9@Z^noLg~Sebuwic3E5 z)Azkay{OOb%Sn@WK0vb{pfw0_IF#}gLNwk<`N={~7hC#S-<*rbNRd#^sVJ@yZ&gy_ z&bP{n6?7=jVAVTR?HY8oc?Pi6tXD6adFn)j)MN7AMnMmp_Cbt~rAZL}*3vkWq^$96 TC@wm$dkdFi<2aTmc#-`ARpLmw literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/_vendor/more_itertools/__pycache__/more.cpython-39.pyc b/venv/Lib/site-packages/setuptools/_vendor/more_itertools/__pycache__/more.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e29ce3113a6f5212ae22ca836f48adab4e713d09 GIT binary patch literal 110012 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 MzW(a^8|vHs4;|y}_5c6? literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/_vendor/more_itertools/__pycache__/recipes.cpython-39.pyc b/venv/Lib/site-packages/setuptools/_vendor/more_itertools/__pycache__/recipes.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0fdc0ba16a55b671f49c150904e6abef5fc92968 GIT binary patch literal 17929 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 list(chunked([1, 2, 3, 4, 5, 6], 3)) + [[1, 2, 3], [4, 5, 6]] + + By the default, the last yielded list will have fewer than *n* elements + if the length of *iterable* is not divisible by *n*: + + >>> list(chunked([1, 2, 3, 4, 5, 6, 7, 8], 3)) + [[1, 2, 3], [4, 5, 6], [7, 8]] + + To use a fill-in value instead, see the :func:`grouper` recipe. + + If the length of *iterable* is not divisible by *n* and *strict* is + ``True``, then ``ValueError`` will be raised before the last + list is yielded. + + """ + iterator = iter(partial(take, n, iter(iterable)), []) + if strict: + + def ret(): + for chunk in iterator: + if len(chunk) != n: + raise ValueError('iterable is not divisible by n.') + yield chunk + + return iter(ret()) + else: + return iterator + + +def first(iterable, default=_marker): + """Return the first item of *iterable*, or *default* if *iterable* is + empty. + + >>> first([0, 1, 2, 3]) + 0 + >>> first([], 'some default') + 'some default' + + If *default* is not provided and there are no items in the iterable, + raise ``ValueError``. + + :func:`first` is useful when you have a generator of expensive-to-retrieve + values and want any arbitrary one. It is marginally shorter than + ``next(iter(iterable), default)``. + + """ + try: + return next(iter(iterable)) + except StopIteration as e: + if default is _marker: + raise ValueError( + 'first() was called on an empty iterable, and no ' + 'default value was provided.' + ) from e + return default + + +def last(iterable, default=_marker): + """Return the last item of *iterable*, or *default* if *iterable* is + empty. + + >>> last([0, 1, 2, 3]) + 3 + >>> last([], 'some default') + 'some default' + + If *default* is not provided and there are no items in the iterable, + raise ``ValueError``. + """ + try: + if isinstance(iterable, Sequence): + return iterable[-1] + # Work around https://bugs.python.org/issue38525 + elif hasattr(iterable, '__reversed__') and (hexversion != 0x030800F0): + return next(reversed(iterable)) + else: + return deque(iterable, maxlen=1)[-1] + except (IndexError, TypeError, StopIteration): + if default is _marker: + raise ValueError( + 'last() was called on an empty iterable, and no default was ' + 'provided.' + ) + return default + + +def nth_or_last(iterable, n, default=_marker): + """Return the nth or the last item of *iterable*, + or *default* if *iterable* is empty. + + >>> nth_or_last([0, 1, 2, 3], 2) + 2 + >>> nth_or_last([0, 1], 2) + 1 + >>> nth_or_last([], 0, 'some default') + 'some default' + + If *default* is not provided and there are no items in the iterable, + raise ``ValueError``. + """ + return last(islice(iterable, n + 1), default=default) + + +class peekable: + """Wrap an iterator to allow lookahead and prepending elements. + + Call :meth:`peek` on the result to get the value that will be returned + by :func:`next`. This won't advance the iterator: + + >>> p = peekable(['a', 'b']) + >>> p.peek() + 'a' + >>> next(p) + 'a' + + Pass :meth:`peek` a default value to return that instead of raising + ``StopIteration`` when the iterator is exhausted. + + >>> p = peekable([]) + >>> p.peek('hi') + 'hi' + + peekables also offer a :meth:`prepend` method, which "inserts" items + at the head of the iterable: + + >>> p = peekable([1, 2, 3]) + >>> p.prepend(10, 11, 12) + >>> next(p) + 10 + >>> p.peek() + 11 + >>> list(p) + [11, 12, 1, 2, 3] + + peekables can be indexed. Index 0 is the item that will be returned by + :func:`next`, index 1 is the item after that, and so on: + The values up to the given index will be cached. + + >>> p = peekable(['a', 'b', 'c', 'd']) + >>> p[0] + 'a' + >>> p[1] + 'b' + >>> next(p) + 'a' + + Negative indexes are supported, but be aware that they will cache the + remaining items in the source iterator, which may require significant + storage. + + To check whether a peekable is exhausted, check its truth value: + + >>> p = peekable(['a', 'b']) + >>> if p: # peekable has items + ... list(p) + ['a', 'b'] + >>> if not p: # peekable is exhausted + ... list(p) + [] + + """ + + def __init__(self, iterable): + self._it = iter(iterable) + self._cache = deque() + + def __iter__(self): + return self + + def __bool__(self): + try: + self.peek() + except StopIteration: + return False + return True + + def peek(self, default=_marker): + """Return the item that will be next returned from ``next()``. + + Return ``default`` if there are no items left. If ``default`` is not + provided, raise ``StopIteration``. + + """ + if not self._cache: + try: + self._cache.append(next(self._it)) + except StopIteration: + if default is _marker: + raise + return default + return self._cache[0] + + def prepend(self, *items): + """Stack up items to be the next ones returned from ``next()`` or + ``self.peek()``. The items will be returned in + first in, first out order:: + + >>> p = peekable([1, 2, 3]) + >>> p.prepend(10, 11, 12) + >>> next(p) + 10 + >>> list(p) + [11, 12, 1, 2, 3] + + It is possible, by prepending items, to "resurrect" a peekable that + previously raised ``StopIteration``. + + >>> p = peekable([]) + >>> next(p) + Traceback (most recent call last): + ... + StopIteration + >>> p.prepend(1) + >>> next(p) + 1 + >>> next(p) + Traceback (most recent call last): + ... + StopIteration + + """ + self._cache.extendleft(reversed(items)) + + def __next__(self): + if self._cache: + return self._cache.popleft() + + return next(self._it) + + def _get_slice(self, index): + # Normalize the slice's arguments + step = 1 if (index.step is None) else index.step + if step > 0: + start = 0 if (index.start is None) else index.start + stop = maxsize if (index.stop is None) else index.stop + elif step < 0: + start = -1 if (index.start is None) else index.start + stop = (-maxsize - 1) if (index.stop is None) else index.stop + else: + raise ValueError('slice step cannot be zero') + + # If either the start or stop index is negative, we'll need to cache + # the rest of the iterable in order to slice from the right side. + if (start < 0) or (stop < 0): + self._cache.extend(self._it) + # Otherwise we'll need to find the rightmost index and cache to that + # point. + else: + n = min(max(start, stop) + 1, maxsize) + cache_len = len(self._cache) + if n >= cache_len: + self._cache.extend(islice(self._it, n - cache_len)) + + return list(self._cache)[index] + + def __getitem__(self, index): + if isinstance(index, slice): + return self._get_slice(index) + + cache_len = len(self._cache) + if index < 0: + self._cache.extend(self._it) + elif index >= cache_len: + self._cache.extend(islice(self._it, index + 1 - cache_len)) + + return self._cache[index] + + +def collate(*iterables, **kwargs): + """Return a sorted merge of the items from each of several already-sorted + *iterables*. + + >>> list(collate('ACDZ', 'AZ', 'JKL')) + ['A', 'A', 'C', 'D', 'J', 'K', 'L', 'Z', 'Z'] + + Works lazily, keeping only the next value from each iterable in memory. Use + :func:`collate` to, for example, perform a n-way mergesort of items that + don't fit in memory. + + If a *key* function is specified, the iterables will be sorted according + to its result: + + >>> key = lambda s: int(s) # Sort by numeric value, not by string + >>> list(collate(['1', '10'], ['2', '11'], key=key)) + ['1', '2', '10', '11'] + + + If the *iterables* are sorted in descending order, set *reverse* to + ``True``: + + >>> list(collate([5, 3, 1], [4, 2, 0], reverse=True)) + [5, 4, 3, 2, 1, 0] + + If the elements of the passed-in iterables are out of order, you might get + unexpected results. + + On Python 3.5+, this function is an alias for :func:`heapq.merge`. + + """ + warnings.warn( + "collate is no longer part of more_itertools, use heapq.merge", + DeprecationWarning, + ) + return merge(*iterables, **kwargs) + + +def consumer(func): + """Decorator that automatically advances a PEP-342-style "reverse iterator" + to its first yield point so you don't have to call ``next()`` on it + manually. + + >>> @consumer + ... def tally(): + ... i = 0 + ... while True: + ... print('Thing number %s is %s.' % (i, (yield))) + ... i += 1 + ... + >>> t = tally() + >>> t.send('red') + Thing number 0 is red. + >>> t.send('fish') + Thing number 1 is fish. + + Without the decorator, you would have to call ``next(t)`` before + ``t.send()`` could be used. + + """ + + @wraps(func) + def wrapper(*args, **kwargs): + gen = func(*args, **kwargs) + next(gen) + return gen + + return wrapper + + +def ilen(iterable): + """Return the number of items in *iterable*. + + >>> ilen(x for x in range(1000000) if x % 3 == 0) + 333334 + + This consumes the iterable, so handle with care. + + """ + # This approach was selected because benchmarks showed it's likely the + # fastest of the known implementations at the time of writing. + # See GitHub tracker: #236, #230. + counter = count() + deque(zip(iterable, counter), maxlen=0) + return next(counter) + + +def iterate(func, start): + """Return ``start``, ``func(start)``, ``func(func(start))``, ... + + >>> from itertools import islice + >>> list(islice(iterate(lambda x: 2*x, 1), 10)) + [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] + + """ + while True: + yield start + start = func(start) + + +def with_iter(context_manager): + """Wrap an iterable in a ``with`` statement, so it closes once exhausted. + + For example, this will close the file when the iterator is exhausted:: + + upper_lines = (line.upper() for line in with_iter(open('foo'))) + + Any context manager which returns an iterable is a candidate for + ``with_iter``. + + """ + with context_manager as iterable: + yield from iterable + + +def one(iterable, too_short=None, too_long=None): + """Return the first item from *iterable*, which is expected to contain only + that item. Raise an exception if *iterable* is empty or has more than one + item. + + :func:`one` is useful for ensuring that an iterable contains only one item. + For example, it can be used to retrieve the result of a database query + that is expected to return a single row. + + If *iterable* is empty, ``ValueError`` will be raised. You may specify a + different exception with the *too_short* keyword: + + >>> it = [] + >>> one(it) # doctest: +IGNORE_EXCEPTION_DETAIL + Traceback (most recent call last): + ... + ValueError: too many items in iterable (expected 1)' + >>> too_short = IndexError('too few items') + >>> one(it, too_short=too_short) # doctest: +IGNORE_EXCEPTION_DETAIL + Traceback (most recent call last): + ... + IndexError: too few items + + Similarly, if *iterable* contains more than one item, ``ValueError`` will + be raised. You may specify a different exception with the *too_long* + keyword: + + >>> it = ['too', 'many'] + >>> one(it) # doctest: +IGNORE_EXCEPTION_DETAIL + Traceback (most recent call last): + ... + ValueError: Expected exactly one item in iterable, but got 'too', + 'many', and perhaps more. + >>> too_long = RuntimeError + >>> one(it, too_long=too_long) # doctest: +IGNORE_EXCEPTION_DETAIL + Traceback (most recent call last): + ... + RuntimeError + + Note that :func:`one` attempts to advance *iterable* twice to ensure there + is only one item. See :func:`spy` or :func:`peekable` to check iterable + contents less destructively. + + """ + it = iter(iterable) + + try: + first_value = next(it) + except StopIteration as e: + raise ( + too_short or ValueError('too few items in iterable (expected 1)') + ) from e + + try: + second_value = next(it) + except StopIteration: + pass + else: + msg = ( + 'Expected exactly one item in iterable, but got {!r}, {!r}, ' + 'and perhaps more.'.format(first_value, second_value) + ) + raise too_long or ValueError(msg) + + return first_value + + +def distinct_permutations(iterable, r=None): + """Yield successive distinct permutations of the elements in *iterable*. + + >>> sorted(distinct_permutations([1, 0, 1])) + [(0, 1, 1), (1, 0, 1), (1, 1, 0)] + + Equivalent to ``set(permutations(iterable))``, except duplicates are not + generated and thrown away. For larger input sequences this is much more + efficient. + + Duplicate permutations arise when there are duplicated elements in the + input iterable. The number of items returned is + `n! / (x_1! * x_2! * ... * x_n!)`, where `n` is the total number of + items input, and each `x_i` is the count of a distinct item in the input + sequence. + + If *r* is given, only the *r*-length permutations are yielded. + + >>> sorted(distinct_permutations([1, 0, 1], r=2)) + [(0, 1), (1, 0), (1, 1)] + >>> sorted(distinct_permutations(range(3), r=2)) + [(0, 1), (0, 2), (1, 0), (1, 2), (2, 0), (2, 1)] + + """ + # Algorithm: https://w.wiki/Qai + def _full(A): + while True: + # Yield the permutation we have + yield tuple(A) + + # Find the largest index i such that A[i] < A[i + 1] + for i in range(size - 2, -1, -1): + if A[i] < A[i + 1]: + break + # If no such index exists, this permutation is the last one + else: + return + + # Find the largest index j greater than j such that A[i] < A[j] + for j in range(size - 1, i, -1): + if A[i] < A[j]: + break + + # Swap the value of A[i] with that of A[j], then reverse the + # sequence from A[i + 1] to form the new permutation + A[i], A[j] = A[j], A[i] + A[i + 1 :] = A[: i - size : -1] # A[i + 1:][::-1] + + # Algorithm: modified from the above + def _partial(A, r): + # Split A into the first r items and the last r items + head, tail = A[:r], A[r:] + right_head_indexes = range(r - 1, -1, -1) + left_tail_indexes = range(len(tail)) + + while True: + # Yield the permutation we have + yield tuple(head) + + # Starting from the right, find the first index of the head with + # value smaller than the maximum value of the tail - call it i. + pivot = tail[-1] + for i in right_head_indexes: + if head[i] < pivot: + break + pivot = head[i] + else: + return + + # Starting from the left, find the first value of the tail + # with a value greater than head[i] and swap. + for j in left_tail_indexes: + if tail[j] > head[i]: + head[i], tail[j] = tail[j], head[i] + break + # If we didn't find one, start from the right and find the first + # index of the head with a value greater than head[i] and swap. + else: + for j in right_head_indexes: + if head[j] > head[i]: + head[i], head[j] = head[j], head[i] + break + + # Reverse head[i + 1:] and swap it with tail[:r - (i + 1)] + tail += head[: i - r : -1] # head[i + 1:][::-1] + i += 1 + head[i:], tail[:] = tail[: r - i], tail[r - i :] + + items = sorted(iterable) + + size = len(items) + if r is None: + r = size + + if 0 < r <= size: + return _full(items) if (r == size) else _partial(items, r) + + return iter(() if r else ((),)) + + +def intersperse(e, iterable, n=1): + """Intersperse filler element *e* among the items in *iterable*, leaving + *n* items between each filler element. + + >>> list(intersperse('!', [1, 2, 3, 4, 5])) + [1, '!', 2, '!', 3, '!', 4, '!', 5] + + >>> list(intersperse(None, [1, 2, 3, 4, 5], n=2)) + [1, 2, None, 3, 4, None, 5] + + """ + if n == 0: + raise ValueError('n must be > 0') + elif n == 1: + # interleave(repeat(e), iterable) -> e, x_0, e, e, x_1, e, x_2... + # islice(..., 1, None) -> x_0, e, e, x_1, e, x_2... + return islice(interleave(repeat(e), iterable), 1, None) + else: + # interleave(filler, chunks) -> [e], [x_0, x_1], [e], [x_2, x_3]... + # islice(..., 1, None) -> [x_0, x_1], [e], [x_2, x_3]... + # flatten(...) -> x_0, x_1, e, x_2, x_3... + filler = repeat([e]) + chunks = chunked(iterable, n) + return flatten(islice(interleave(filler, chunks), 1, None)) + + +def unique_to_each(*iterables): + """Return the elements from each of the input iterables that aren't in the + other input iterables. + + For example, suppose you have a set of packages, each with a set of + dependencies:: + + {'pkg_1': {'A', 'B'}, 'pkg_2': {'B', 'C'}, 'pkg_3': {'B', 'D'}} + + If you remove one package, which dependencies can also be removed? + + If ``pkg_1`` is removed, then ``A`` is no longer necessary - it is not + associated with ``pkg_2`` or ``pkg_3``. Similarly, ``C`` is only needed for + ``pkg_2``, and ``D`` is only needed for ``pkg_3``:: + + >>> unique_to_each({'A', 'B'}, {'B', 'C'}, {'B', 'D'}) + [['A'], ['C'], ['D']] + + If there are duplicates in one input iterable that aren't in the others + they will be duplicated in the output. Input order is preserved:: + + >>> unique_to_each("mississippi", "missouri") + [['p', 'p'], ['o', 'u', 'r']] + + It is assumed that the elements of each iterable are hashable. + + """ + pool = [list(it) for it in iterables] + counts = Counter(chain.from_iterable(map(set, pool))) + uniques = {element for element in counts if counts[element] == 1} + return [list(filter(uniques.__contains__, it)) for it in pool] + + +def windowed(seq, n, fillvalue=None, step=1): + """Return a sliding window of width *n* over the given iterable. + + >>> all_windows = windowed([1, 2, 3, 4, 5], 3) + >>> list(all_windows) + [(1, 2, 3), (2, 3, 4), (3, 4, 5)] + + When the window is larger than the iterable, *fillvalue* is used in place + of missing values: + + >>> list(windowed([1, 2, 3], 4)) + [(1, 2, 3, None)] + + Each window will advance in increments of *step*: + + >>> list(windowed([1, 2, 3, 4, 5, 6], 3, fillvalue='!', step=2)) + [(1, 2, 3), (3, 4, 5), (5, 6, '!')] + + To slide into the iterable's items, use :func:`chain` to add filler items + to the left: + + >>> iterable = [1, 2, 3, 4] + >>> n = 3 + >>> padding = [None] * (n - 1) + >>> list(windowed(chain(padding, iterable), 3)) + [(None, None, 1), (None, 1, 2), (1, 2, 3), (2, 3, 4)] + """ + if n < 0: + raise ValueError('n must be >= 0') + if n == 0: + yield tuple() + return + if step < 1: + raise ValueError('step must be >= 1') + + window = deque(maxlen=n) + i = n + for _ in map(window.append, seq): + i -= 1 + if not i: + i = step + yield tuple(window) + + size = len(window) + if size < n: + yield tuple(chain(window, repeat(fillvalue, n - size))) + elif 0 < i < min(step, n): + window += (fillvalue,) * i + yield tuple(window) + + +def substrings(iterable): + """Yield all of the substrings of *iterable*. + + >>> [''.join(s) for s in substrings('more')] + ['m', 'o', 'r', 'e', 'mo', 'or', 're', 'mor', 'ore', 'more'] + + Note that non-string iterables can also be subdivided. + + >>> list(substrings([0, 1, 2])) + [(0,), (1,), (2,), (0, 1), (1, 2), (0, 1, 2)] + + """ + # The length-1 substrings + seq = [] + for item in iter(iterable): + seq.append(item) + yield (item,) + seq = tuple(seq) + item_count = len(seq) + + # And the rest + for n in range(2, item_count + 1): + for i in range(item_count - n + 1): + yield seq[i : i + n] + + +def substrings_indexes(seq, reverse=False): + """Yield all substrings and their positions in *seq* + + The items yielded will be a tuple of the form ``(substr, i, j)``, where + ``substr == seq[i:j]``. + + This function only works for iterables that support slicing, such as + ``str`` objects. + + >>> for item in substrings_indexes('more'): + ... print(item) + ('m', 0, 1) + ('o', 1, 2) + ('r', 2, 3) + ('e', 3, 4) + ('mo', 0, 2) + ('or', 1, 3) + ('re', 2, 4) + ('mor', 0, 3) + ('ore', 1, 4) + ('more', 0, 4) + + Set *reverse* to ``True`` to yield the same items in the opposite order. + + + """ + r = range(1, len(seq) + 1) + if reverse: + r = reversed(r) + return ( + (seq[i : i + L], i, i + L) for L in r for i in range(len(seq) - L + 1) + ) + + +class bucket: + """Wrap *iterable* and return an object that buckets it iterable into + child iterables based on a *key* function. + + >>> iterable = ['a1', 'b1', 'c1', 'a2', 'b2', 'c2', 'b3'] + >>> s = bucket(iterable, key=lambda x: x[0]) # Bucket by 1st character + >>> sorted(list(s)) # Get the keys + ['a', 'b', 'c'] + >>> a_iterable = s['a'] + >>> next(a_iterable) + 'a1' + >>> next(a_iterable) + 'a2' + >>> list(s['b']) + ['b1', 'b2', 'b3'] + + The original iterable will be advanced and its items will be cached until + they are used by the child iterables. This may require significant storage. + + By default, attempting to select a bucket to which no items belong will + exhaust the iterable and cache all values. + If you specify a *validator* function, selected buckets will instead be + checked against it. + + >>> from itertools import count + >>> it = count(1, 2) # Infinite sequence of odd numbers + >>> key = lambda x: x % 10 # Bucket by last digit + >>> validator = lambda x: x in {1, 3, 5, 7, 9} # Odd digits only + >>> s = bucket(it, key=key, validator=validator) + >>> 2 in s + False + >>> list(s[2]) + [] + + """ + + def __init__(self, iterable, key, validator=None): + self._it = iter(iterable) + self._key = key + self._cache = defaultdict(deque) + self._validator = validator or (lambda x: True) + + def __contains__(self, value): + if not self._validator(value): + return False + + try: + item = next(self[value]) + except StopIteration: + return False + else: + self._cache[value].appendleft(item) + + return True + + def _get_values(self, value): + """ + Helper to yield items from the parent iterator that match *value*. + Items that don't match are stored in the local cache as they + are encountered. + """ + while True: + # If we've cached some items that match the target value, emit + # the first one and evict it from the cache. + if self._cache[value]: + yield self._cache[value].popleft() + # Otherwise we need to advance the parent iterator to search for + # a matching item, caching the rest. + else: + while True: + try: + item = next(self._it) + except StopIteration: + return + item_value = self._key(item) + if item_value == value: + yield item + break + elif self._validator(item_value): + self._cache[item_value].append(item) + + def __iter__(self): + for item in self._it: + item_value = self._key(item) + if self._validator(item_value): + self._cache[item_value].append(item) + + yield from self._cache.keys() + + def __getitem__(self, value): + if not self._validator(value): + return iter(()) + + return self._get_values(value) + + +def spy(iterable, n=1): + """Return a 2-tuple with a list containing the first *n* elements of + *iterable*, and an iterator with the same items as *iterable*. + This allows you to "look ahead" at the items in the iterable without + advancing it. + + There is one item in the list by default: + + >>> iterable = 'abcdefg' + >>> head, iterable = spy(iterable) + >>> head + ['a'] + >>> list(iterable) + ['a', 'b', 'c', 'd', 'e', 'f', 'g'] + + You may use unpacking to retrieve items instead of lists: + + >>> (head,), iterable = spy('abcdefg') + >>> head + 'a' + >>> (first, second), iterable = spy('abcdefg', 2) + >>> first + 'a' + >>> second + 'b' + + The number of items requested can be larger than the number of items in + the iterable: + + >>> iterable = [1, 2, 3, 4, 5] + >>> head, iterable = spy(iterable, 10) + >>> head + [1, 2, 3, 4, 5] + >>> list(iterable) + [1, 2, 3, 4, 5] + + """ + it = iter(iterable) + head = take(n, it) + + return head.copy(), chain(head, it) + + +def interleave(*iterables): + """Return a new iterable yielding from each iterable in turn, + until the shortest is exhausted. + + >>> list(interleave([1, 2, 3], [4, 5], [6, 7, 8])) + [1, 4, 6, 2, 5, 7] + + For a version that doesn't terminate after the shortest iterable is + exhausted, see :func:`interleave_longest`. + + """ + return chain.from_iterable(zip(*iterables)) + + +def interleave_longest(*iterables): + """Return a new iterable yielding from each iterable in turn, + skipping any that are exhausted. + + >>> list(interleave_longest([1, 2, 3], [4, 5], [6, 7, 8])) + [1, 4, 6, 2, 5, 7, 3, 8] + + This function produces the same output as :func:`roundrobin`, but may + perform better for some inputs (in particular when the number of iterables + is large). + + """ + i = chain.from_iterable(zip_longest(*iterables, fillvalue=_marker)) + return (x for x in i if x is not _marker) + + +def collapse(iterable, base_type=None, levels=None): + """Flatten an iterable with multiple levels of nesting (e.g., a list of + lists of tuples) into non-iterable types. + + >>> iterable = [(1, 2), ([3, 4], [[5], [6]])] + >>> list(collapse(iterable)) + [1, 2, 3, 4, 5, 6] + + Binary and text strings are not considered iterable and + will not be collapsed. + + To avoid collapsing other types, specify *base_type*: + + >>> iterable = ['ab', ('cd', 'ef'), ['gh', 'ij']] + >>> list(collapse(iterable, base_type=tuple)) + ['ab', ('cd', 'ef'), 'gh', 'ij'] + + Specify *levels* to stop flattening after a certain level: + + >>> iterable = [('a', ['b']), ('c', ['d'])] + >>> list(collapse(iterable)) # Fully flattened + ['a', 'b', 'c', 'd'] + >>> list(collapse(iterable, levels=1)) # Only one level flattened + ['a', ['b'], 'c', ['d']] + + """ + + def walk(node, level): + if ( + ((levels is not None) and (level > levels)) + or isinstance(node, (str, bytes)) + or ((base_type is not None) and isinstance(node, base_type)) + ): + yield node + return + + try: + tree = iter(node) + except TypeError: + yield node + return + else: + for child in tree: + yield from walk(child, level + 1) + + yield from walk(iterable, 0) + + +def side_effect(func, iterable, chunk_size=None, before=None, after=None): + """Invoke *func* on each item in *iterable* (or on each *chunk_size* group + of items) before yielding the item. + + `func` must be a function that takes a single argument. Its return value + will be discarded. + + *before* and *after* are optional functions that take no arguments. They + will be executed before iteration starts and after it ends, respectively. + + `side_effect` can be used for logging, updating progress bars, or anything + that is not functionally "pure." + + Emitting a status message: + + >>> from more_itertools import consume + >>> func = lambda item: print('Received {}'.format(item)) + >>> consume(side_effect(func, range(2))) + Received 0 + Received 1 + + Operating on chunks of items: + + >>> pair_sums = [] + >>> func = lambda chunk: pair_sums.append(sum(chunk)) + >>> list(side_effect(func, [0, 1, 2, 3, 4, 5], 2)) + [0, 1, 2, 3, 4, 5] + >>> list(pair_sums) + [1, 5, 9] + + Writing to a file-like object: + + >>> from io import StringIO + >>> from more_itertools import consume + >>> f = StringIO() + >>> func = lambda x: print(x, file=f) + >>> before = lambda: print(u'HEADER', file=f) + >>> after = f.close + >>> it = [u'a', u'b', u'c'] + >>> consume(side_effect(func, it, before=before, after=after)) + >>> f.closed + True + + """ + try: + if before is not None: + before() + + if chunk_size is None: + for item in iterable: + func(item) + yield item + else: + for chunk in chunked(iterable, chunk_size): + func(chunk) + yield from chunk + finally: + if after is not None: + after() + + +def sliced(seq, n, strict=False): + """Yield slices of length *n* from the sequence *seq*. + + >>> list(sliced((1, 2, 3, 4, 5, 6), 3)) + [(1, 2, 3), (4, 5, 6)] + + By the default, the last yielded slice will have fewer than *n* elements + if the length of *seq* is not divisible by *n*: + + >>> list(sliced((1, 2, 3, 4, 5, 6, 7, 8), 3)) + [(1, 2, 3), (4, 5, 6), (7, 8)] + + If the length of *seq* is not divisible by *n* and *strict* is + ``True``, then ``ValueError`` will be raised before the last + slice is yielded. + + This function will only work for iterables that support slicing. + For non-sliceable iterables, see :func:`chunked`. + + """ + iterator = takewhile(len, (seq[i : i + n] for i in count(0, n))) + if strict: + + def ret(): + for _slice in iterator: + if len(_slice) != n: + raise ValueError("seq is not divisible by n.") + yield _slice + + return iter(ret()) + else: + return iterator + + +def split_at(iterable, pred, maxsplit=-1, keep_separator=False): + """Yield lists of items from *iterable*, where each list is delimited by + an item where callable *pred* returns ``True``. + + >>> list(split_at('abcdcba', lambda x: x == 'b')) + [['a'], ['c', 'd', 'c'], ['a']] + + >>> list(split_at(range(10), lambda n: n % 2 == 1)) + [[0], [2], [4], [6], [8], []] + + At most *maxsplit* splits are done. If *maxsplit* is not specified or -1, + then there is no limit on the number of splits: + + >>> list(split_at(range(10), lambda n: n % 2 == 1, maxsplit=2)) + [[0], [2], [4, 5, 6, 7, 8, 9]] + + By default, the delimiting items are not included in the output. + The include them, set *keep_separator* to ``True``. + + >>> list(split_at('abcdcba', lambda x: x == 'b', keep_separator=True)) + [['a'], ['b'], ['c', 'd', 'c'], ['b'], ['a']] + + """ + if maxsplit == 0: + yield list(iterable) + return + + buf = [] + it = iter(iterable) + for item in it: + if pred(item): + yield buf + if keep_separator: + yield [item] + if maxsplit == 1: + yield list(it) + return + buf = [] + maxsplit -= 1 + else: + buf.append(item) + yield buf + + +def split_before(iterable, pred, maxsplit=-1): + """Yield lists of items from *iterable*, where each list ends just before + an item for which callable *pred* returns ``True``: + + >>> list(split_before('OneTwo', lambda s: s.isupper())) + [['O', 'n', 'e'], ['T', 'w', 'o']] + + >>> list(split_before(range(10), lambda n: n % 3 == 0)) + [[0, 1, 2], [3, 4, 5], [6, 7, 8], [9]] + + At most *maxsplit* splits are done. If *maxsplit* is not specified or -1, + then there is no limit on the number of splits: + + >>> list(split_before(range(10), lambda n: n % 3 == 0, maxsplit=2)) + [[0, 1, 2], [3, 4, 5], [6, 7, 8, 9]] + """ + if maxsplit == 0: + yield list(iterable) + return + + buf = [] + it = iter(iterable) + for item in it: + if pred(item) and buf: + yield buf + if maxsplit == 1: + yield [item] + list(it) + return + buf = [] + maxsplit -= 1 + buf.append(item) + if buf: + yield buf + + +def split_after(iterable, pred, maxsplit=-1): + """Yield lists of items from *iterable*, where each list ends with an + item where callable *pred* returns ``True``: + + >>> list(split_after('one1two2', lambda s: s.isdigit())) + [['o', 'n', 'e', '1'], ['t', 'w', 'o', '2']] + + >>> list(split_after(range(10), lambda n: n % 3 == 0)) + [[0], [1, 2, 3], [4, 5, 6], [7, 8, 9]] + + At most *maxsplit* splits are done. If *maxsplit* is not specified or -1, + then there is no limit on the number of splits: + + >>> list(split_after(range(10), lambda n: n % 3 == 0, maxsplit=2)) + [[0], [1, 2, 3], [4, 5, 6, 7, 8, 9]] + + """ + if maxsplit == 0: + yield list(iterable) + return + + buf = [] + it = iter(iterable) + for item in it: + buf.append(item) + if pred(item) and buf: + yield buf + if maxsplit == 1: + yield list(it) + return + buf = [] + maxsplit -= 1 + if buf: + yield buf + + +def split_when(iterable, pred, maxsplit=-1): + """Split *iterable* into pieces based on the output of *pred*. + *pred* should be a function that takes successive pairs of items and + returns ``True`` if the iterable should be split in between them. + + For example, to find runs of increasing numbers, split the iterable when + element ``i`` is larger than element ``i + 1``: + + >>> list(split_when([1, 2, 3, 3, 2, 5, 2, 4, 2], lambda x, y: x > y)) + [[1, 2, 3, 3], [2, 5], [2, 4], [2]] + + At most *maxsplit* splits are done. If *maxsplit* is not specified or -1, + then there is no limit on the number of splits: + + >>> list(split_when([1, 2, 3, 3, 2, 5, 2, 4, 2], + ... lambda x, y: x > y, maxsplit=2)) + [[1, 2, 3, 3], [2, 5], [2, 4, 2]] + + """ + if maxsplit == 0: + yield list(iterable) + return + + it = iter(iterable) + try: + cur_item = next(it) + except StopIteration: + return + + buf = [cur_item] + for next_item in it: + if pred(cur_item, next_item): + yield buf + if maxsplit == 1: + yield [next_item] + list(it) + return + buf = [] + maxsplit -= 1 + + buf.append(next_item) + cur_item = next_item + + yield buf + + +def split_into(iterable, sizes): + """Yield a list of sequential items from *iterable* of length 'n' for each + integer 'n' in *sizes*. + + >>> list(split_into([1,2,3,4,5,6], [1,2,3])) + [[1], [2, 3], [4, 5, 6]] + + If the sum of *sizes* is smaller than the length of *iterable*, then the + remaining items of *iterable* will not be returned. + + >>> list(split_into([1,2,3,4,5,6], [2,3])) + [[1, 2], [3, 4, 5]] + + If the sum of *sizes* is larger than the length of *iterable*, fewer items + will be returned in the iteration that overruns *iterable* and further + lists will be empty: + + >>> list(split_into([1,2,3,4], [1,2,3,4])) + [[1], [2, 3], [4], []] + + When a ``None`` object is encountered in *sizes*, the returned list will + contain items up to the end of *iterable* the same way that itertools.slice + does: + + >>> list(split_into([1,2,3,4,5,6,7,8,9,0], [2,3,None])) + [[1, 2], [3, 4, 5], [6, 7, 8, 9, 0]] + + :func:`split_into` can be useful for grouping a series of items where the + sizes of the groups are not uniform. An example would be where in a row + from a table, multiple columns represent elements of the same feature + (e.g. a point represented by x,y,z) but, the format is not the same for + all columns. + """ + # convert the iterable argument into an iterator so its contents can + # be consumed by islice in case it is a generator + it = iter(iterable) + + for size in sizes: + if size is None: + yield list(it) + return + else: + yield list(islice(it, size)) + + +def padded(iterable, fillvalue=None, n=None, next_multiple=False): + """Yield the elements from *iterable*, followed by *fillvalue*, such that + at least *n* items are emitted. + + >>> list(padded([1, 2, 3], '?', 5)) + [1, 2, 3, '?', '?'] + + If *next_multiple* is ``True``, *fillvalue* will be emitted until the + number of items emitted is a multiple of *n*:: + + >>> list(padded([1, 2, 3, 4], n=3, next_multiple=True)) + [1, 2, 3, 4, None, None] + + If *n* is ``None``, *fillvalue* will be emitted indefinitely. + + """ + it = iter(iterable) + if n is None: + yield from chain(it, repeat(fillvalue)) + elif n < 1: + raise ValueError('n must be at least 1') + else: + item_count = 0 + for item in it: + yield item + item_count += 1 + + remaining = (n - item_count) % n if next_multiple else n - item_count + for _ in range(remaining): + yield fillvalue + + +def repeat_last(iterable, default=None): + """After the *iterable* is exhausted, keep yielding its last element. + + >>> list(islice(repeat_last(range(3)), 5)) + [0, 1, 2, 2, 2] + + If the iterable is empty, yield *default* forever:: + + >>> list(islice(repeat_last(range(0), 42), 5)) + [42, 42, 42, 42, 42] + + """ + item = _marker + for item in iterable: + yield item + final = default if item is _marker else item + yield from repeat(final) + + +def distribute(n, iterable): + """Distribute the items from *iterable* among *n* smaller iterables. + + >>> group_1, group_2 = distribute(2, [1, 2, 3, 4, 5, 6]) + >>> list(group_1) + [1, 3, 5] + >>> list(group_2) + [2, 4, 6] + + If the length of *iterable* is not evenly divisible by *n*, then the + length of the returned iterables will not be identical: + + >>> children = distribute(3, [1, 2, 3, 4, 5, 6, 7]) + >>> [list(c) for c in children] + [[1, 4, 7], [2, 5], [3, 6]] + + If the length of *iterable* is smaller than *n*, then the last returned + iterables will be empty: + + >>> children = distribute(5, [1, 2, 3]) + >>> [list(c) for c in children] + [[1], [2], [3], [], []] + + This function uses :func:`itertools.tee` and may require significant + storage. If you need the order items in the smaller iterables to match the + original iterable, see :func:`divide`. + + """ + if n < 1: + raise ValueError('n must be at least 1') + + children = tee(iterable, n) + return [islice(it, index, None, n) for index, it in enumerate(children)] + + +def stagger(iterable, offsets=(-1, 0, 1), longest=False, fillvalue=None): + """Yield tuples whose elements are offset from *iterable*. + The amount by which the `i`-th item in each tuple is offset is given by + the `i`-th item in *offsets*. + + >>> list(stagger([0, 1, 2, 3])) + [(None, 0, 1), (0, 1, 2), (1, 2, 3)] + >>> list(stagger(range(8), offsets=(0, 2, 4))) + [(0, 2, 4), (1, 3, 5), (2, 4, 6), (3, 5, 7)] + + By default, the sequence will end when the final element of a tuple is the + last item in the iterable. To continue until the first element of a tuple + is the last item in the iterable, set *longest* to ``True``:: + + >>> list(stagger([0, 1, 2, 3], longest=True)) + [(None, 0, 1), (0, 1, 2), (1, 2, 3), (2, 3, None), (3, None, None)] + + By default, ``None`` will be used to replace offsets beyond the end of the + sequence. Specify *fillvalue* to use some other value. + + """ + children = tee(iterable, len(offsets)) + + return zip_offset( + *children, offsets=offsets, longest=longest, fillvalue=fillvalue + ) + + +class UnequalIterablesError(ValueError): + def __init__(self, details=None): + msg = 'Iterables have different lengths' + if details is not None: + msg += (': index 0 has length {}; index {} has length {}').format( + *details + ) + + super().__init__(msg) + + +def _zip_equal_generator(iterables): + for combo in zip_longest(*iterables, fillvalue=_marker): + for val in combo: + if val is _marker: + raise UnequalIterablesError() + yield combo + + +def zip_equal(*iterables): + """``zip`` the input *iterables* together, but raise + ``UnequalIterablesError`` if they aren't all the same length. + + >>> it_1 = range(3) + >>> it_2 = iter('abc') + >>> list(zip_equal(it_1, it_2)) + [(0, 'a'), (1, 'b'), (2, 'c')] + + >>> it_1 = range(3) + >>> it_2 = iter('abcd') + >>> list(zip_equal(it_1, it_2)) # doctest: +IGNORE_EXCEPTION_DETAIL + Traceback (most recent call last): + ... + more_itertools.more.UnequalIterablesError: Iterables have different + lengths + + """ + if hexversion >= 0x30A00A6: + warnings.warn( + ( + 'zip_equal will be removed in a future version of ' + 'more-itertools. Use the builtin zip function with ' + 'strict=True instead.' + ), + DeprecationWarning, + ) + # Check whether the iterables are all the same size. + try: + first_size = len(iterables[0]) + for i, it in enumerate(iterables[1:], 1): + size = len(it) + if size != first_size: + break + else: + # If we didn't break out, we can use the built-in zip. + return zip(*iterables) + + # If we did break out, there was a mismatch. + raise UnequalIterablesError(details=(first_size, i, size)) + # If any one of the iterables didn't have a length, start reading + # them until one runs out. + except TypeError: + return _zip_equal_generator(iterables) + + +def zip_offset(*iterables, offsets, longest=False, fillvalue=None): + """``zip`` the input *iterables* together, but offset the `i`-th iterable + by the `i`-th item in *offsets*. + + >>> list(zip_offset('0123', 'abcdef', offsets=(0, 1))) + [('0', 'b'), ('1', 'c'), ('2', 'd'), ('3', 'e')] + + This can be used as a lightweight alternative to SciPy or pandas to analyze + data sets in which some series have a lead or lag relationship. + + By default, the sequence will end when the shortest iterable is exhausted. + To continue until the longest iterable is exhausted, set *longest* to + ``True``. + + >>> list(zip_offset('0123', 'abcdef', offsets=(0, 1), longest=True)) + [('0', 'b'), ('1', 'c'), ('2', 'd'), ('3', 'e'), (None, 'f')] + + By default, ``None`` will be used to replace offsets beyond the end of the + sequence. Specify *fillvalue* to use some other value. + + """ + if len(iterables) != len(offsets): + raise ValueError("Number of iterables and offsets didn't match") + + staggered = [] + for it, n in zip(iterables, offsets): + if n < 0: + staggered.append(chain(repeat(fillvalue, -n), it)) + elif n > 0: + staggered.append(islice(it, n, None)) + else: + staggered.append(it) + + if longest: + return zip_longest(*staggered, fillvalue=fillvalue) + + return zip(*staggered) + + +def sort_together(iterables, key_list=(0,), key=None, reverse=False): + """Return the input iterables sorted together, with *key_list* as the + priority for sorting. All iterables are trimmed to the length of the + shortest one. + + This can be used like the sorting function in a spreadsheet. If each + iterable represents a column of data, the key list determines which + columns are used for sorting. + + By default, all iterables are sorted using the ``0``-th iterable:: + + >>> iterables = [(4, 3, 2, 1), ('a', 'b', 'c', 'd')] + >>> sort_together(iterables) + [(1, 2, 3, 4), ('d', 'c', 'b', 'a')] + + Set a different key list to sort according to another iterable. + Specifying multiple keys dictates how ties are broken:: + + >>> iterables = [(3, 1, 2), (0, 1, 0), ('c', 'b', 'a')] + >>> sort_together(iterables, key_list=(1, 2)) + [(2, 3, 1), (0, 0, 1), ('a', 'c', 'b')] + + To sort by a function of the elements of the iterable, pass a *key* + function. Its arguments are the elements of the iterables corresponding to + the key list:: + + >>> names = ('a', 'b', 'c') + >>> lengths = (1, 2, 3) + >>> widths = (5, 2, 1) + >>> def area(length, width): + ... return length * width + >>> sort_together([names, lengths, widths], key_list=(1, 2), key=area) + [('c', 'b', 'a'), (3, 2, 1), (1, 2, 5)] + + Set *reverse* to ``True`` to sort in descending order. + + >>> sort_together([(1, 2, 3), ('c', 'b', 'a')], reverse=True) + [(3, 2, 1), ('a', 'b', 'c')] + + """ + if key is None: + # if there is no key function, the key argument to sorted is an + # itemgetter + key_argument = itemgetter(*key_list) + else: + # if there is a key function, call it with the items at the offsets + # specified by the key function as arguments + key_list = list(key_list) + if len(key_list) == 1: + # if key_list contains a single item, pass the item at that offset + # as the only argument to the key function + key_offset = key_list[0] + key_argument = lambda zipped_items: key(zipped_items[key_offset]) + else: + # if key_list contains multiple items, use itemgetter to return a + # tuple of items, which we pass as *args to the key function + get_key_items = itemgetter(*key_list) + key_argument = lambda zipped_items: key( + *get_key_items(zipped_items) + ) + + return list( + zip(*sorted(zip(*iterables), key=key_argument, reverse=reverse)) + ) + + +def unzip(iterable): + """The inverse of :func:`zip`, this function disaggregates the elements + of the zipped *iterable*. + + The ``i``-th iterable contains the ``i``-th element from each element + of the zipped iterable. The first element is used to to determine the + length of the remaining elements. + + >>> iterable = [('a', 1), ('b', 2), ('c', 3), ('d', 4)] + >>> letters, numbers = unzip(iterable) + >>> list(letters) + ['a', 'b', 'c', 'd'] + >>> list(numbers) + [1, 2, 3, 4] + + This is similar to using ``zip(*iterable)``, but it avoids reading + *iterable* into memory. Note, however, that this function uses + :func:`itertools.tee` and thus may require significant storage. + + """ + head, iterable = spy(iter(iterable)) + if not head: + # empty iterable, e.g. zip([], [], []) + return () + # spy returns a one-length iterable as head + head = head[0] + iterables = tee(iterable, len(head)) + + def itemgetter(i): + def getter(obj): + try: + return obj[i] + except IndexError: + # basically if we have an iterable like + # iter([(1, 2, 3), (4, 5), (6,)]) + # the second unzipped iterable would fail at the third tuple + # since it would try to access tup[1] + # same with the third unzipped iterable and the second tuple + # to support these "improperly zipped" iterables, + # we create a custom itemgetter + # which just stops the unzipped iterables + # at first length mismatch + raise StopIteration + + return getter + + return tuple(map(itemgetter(i), it) for i, it in enumerate(iterables)) + + +def divide(n, iterable): + """Divide the elements from *iterable* into *n* parts, maintaining + order. + + >>> group_1, group_2 = divide(2, [1, 2, 3, 4, 5, 6]) + >>> list(group_1) + [1, 2, 3] + >>> list(group_2) + [4, 5, 6] + + If the length of *iterable* is not evenly divisible by *n*, then the + length of the returned iterables will not be identical: + + >>> children = divide(3, [1, 2, 3, 4, 5, 6, 7]) + >>> [list(c) for c in children] + [[1, 2, 3], [4, 5], [6, 7]] + + If the length of the iterable is smaller than n, then the last returned + iterables will be empty: + + >>> children = divide(5, [1, 2, 3]) + >>> [list(c) for c in children] + [[1], [2], [3], [], []] + + This function will exhaust the iterable before returning and may require + significant storage. If order is not important, see :func:`distribute`, + which does not first pull the iterable into memory. + + """ + if n < 1: + raise ValueError('n must be at least 1') + + try: + iterable[:0] + except TypeError: + seq = tuple(iterable) + else: + seq = iterable + + q, r = divmod(len(seq), n) + + ret = [] + stop = 0 + for i in range(1, n + 1): + start = stop + stop += q + 1 if i <= r else q + ret.append(iter(seq[start:stop])) + + return ret + + +def always_iterable(obj, base_type=(str, bytes)): + """If *obj* is iterable, return an iterator over its items:: + + >>> obj = (1, 2, 3) + >>> list(always_iterable(obj)) + [1, 2, 3] + + If *obj* is not iterable, return a one-item iterable containing *obj*:: + + >>> obj = 1 + >>> list(always_iterable(obj)) + [1] + + If *obj* is ``None``, return an empty iterable: + + >>> obj = None + >>> list(always_iterable(None)) + [] + + By default, binary and text strings are not considered iterable:: + + >>> obj = 'foo' + >>> list(always_iterable(obj)) + ['foo'] + + If *base_type* is set, objects for which ``isinstance(obj, base_type)`` + returns ``True`` won't be considered iterable. + + >>> obj = {'a': 1} + >>> list(always_iterable(obj)) # Iterate over the dict's keys + ['a'] + >>> list(always_iterable(obj, base_type=dict)) # Treat dicts as a unit + [{'a': 1}] + + Set *base_type* to ``None`` to avoid any special handling and treat objects + Python considers iterable as iterable: + + >>> obj = 'foo' + >>> list(always_iterable(obj, base_type=None)) + ['f', 'o', 'o'] + """ + if obj is None: + return iter(()) + + if (base_type is not None) and isinstance(obj, base_type): + return iter((obj,)) + + try: + return iter(obj) + except TypeError: + return iter((obj,)) + + +def adjacent(predicate, iterable, distance=1): + """Return an iterable over `(bool, item)` tuples where the `item` is + drawn from *iterable* and the `bool` indicates whether + that item satisfies the *predicate* or is adjacent to an item that does. + + For example, to find whether items are adjacent to a ``3``:: + + >>> list(adjacent(lambda x: x == 3, range(6))) + [(False, 0), (False, 1), (True, 2), (True, 3), (True, 4), (False, 5)] + + Set *distance* to change what counts as adjacent. For example, to find + whether items are two places away from a ``3``: + + >>> list(adjacent(lambda x: x == 3, range(6), distance=2)) + [(False, 0), (True, 1), (True, 2), (True, 3), (True, 4), (True, 5)] + + This is useful for contextualizing the results of a search function. + For example, a code comparison tool might want to identify lines that + have changed, but also surrounding lines to give the viewer of the diff + context. + + The predicate function will only be called once for each item in the + iterable. + + See also :func:`groupby_transform`, which can be used with this function + to group ranges of items with the same `bool` value. + + """ + # Allow distance=0 mainly for testing that it reproduces results with map() + if distance < 0: + raise ValueError('distance must be at least 0') + + i1, i2 = tee(iterable) + padding = [False] * distance + selected = chain(padding, map(predicate, i1), padding) + adjacent_to_selected = map(any, windowed(selected, 2 * distance + 1)) + return zip(adjacent_to_selected, i2) + + +def groupby_transform(iterable, keyfunc=None, valuefunc=None, reducefunc=None): + """An extension of :func:`itertools.groupby` that can apply transformations + to the grouped data. + + * *keyfunc* is a function computing a key value for each item in *iterable* + * *valuefunc* is a function that transforms the individual items from + *iterable* after grouping + * *reducefunc* is a function that transforms each group of items + + >>> iterable = 'aAAbBBcCC' + >>> keyfunc = lambda k: k.upper() + >>> valuefunc = lambda v: v.lower() + >>> reducefunc = lambda g: ''.join(g) + >>> list(groupby_transform(iterable, keyfunc, valuefunc, reducefunc)) + [('A', 'aaa'), ('B', 'bbb'), ('C', 'ccc')] + + Each optional argument defaults to an identity function if not specified. + + :func:`groupby_transform` is useful when grouping elements of an iterable + using a separate iterable as the key. To do this, :func:`zip` the iterables + and pass a *keyfunc* that extracts the first element and a *valuefunc* + that extracts the second element:: + + >>> from operator import itemgetter + >>> keys = [0, 0, 1, 1, 1, 2, 2, 2, 3] + >>> values = 'abcdefghi' + >>> iterable = zip(keys, values) + >>> grouper = groupby_transform(iterable, itemgetter(0), itemgetter(1)) + >>> [(k, ''.join(g)) for k, g in grouper] + [(0, 'ab'), (1, 'cde'), (2, 'fgh'), (3, 'i')] + + Note that the order of items in the iterable is significant. + Only adjacent items are grouped together, so if you don't want any + duplicate groups, you should sort the iterable by the key function. + + """ + ret = groupby(iterable, keyfunc) + if valuefunc: + ret = ((k, map(valuefunc, g)) for k, g in ret) + if reducefunc: + ret = ((k, reducefunc(g)) for k, g in ret) + + return ret + + +class numeric_range(abc.Sequence, abc.Hashable): + """An extension of the built-in ``range()`` function whose arguments can + be any orderable numeric type. + + With only *stop* specified, *start* defaults to ``0`` and *step* + defaults to ``1``. The output items will match the type of *stop*: + + >>> list(numeric_range(3.5)) + [0.0, 1.0, 2.0, 3.0] + + With only *start* and *stop* specified, *step* defaults to ``1``. The + output items will match the type of *start*: + + >>> from decimal import Decimal + >>> start = Decimal('2.1') + >>> stop = Decimal('5.1') + >>> list(numeric_range(start, stop)) + [Decimal('2.1'), Decimal('3.1'), Decimal('4.1')] + + With *start*, *stop*, and *step* specified the output items will match + the type of ``start + step``: + + >>> from fractions import Fraction + >>> start = Fraction(1, 2) # Start at 1/2 + >>> stop = Fraction(5, 2) # End at 5/2 + >>> step = Fraction(1, 2) # Count by 1/2 + >>> list(numeric_range(start, stop, step)) + [Fraction(1, 2), Fraction(1, 1), Fraction(3, 2), Fraction(2, 1)] + + If *step* is zero, ``ValueError`` is raised. Negative steps are supported: + + >>> list(numeric_range(3, -1, -1.0)) + [3.0, 2.0, 1.0, 0.0] + + Be aware of the limitations of floating point numbers; the representation + of the yielded numbers may be surprising. + + ``datetime.datetime`` objects can be used for *start* and *stop*, if *step* + is a ``datetime.timedelta`` object: + + >>> import datetime + >>> start = datetime.datetime(2019, 1, 1) + >>> stop = datetime.datetime(2019, 1, 3) + >>> step = datetime.timedelta(days=1) + >>> items = iter(numeric_range(start, stop, step)) + >>> next(items) + datetime.datetime(2019, 1, 1, 0, 0) + >>> next(items) + datetime.datetime(2019, 1, 2, 0, 0) + + """ + + _EMPTY_HASH = hash(range(0, 0)) + + def __init__(self, *args): + argc = len(args) + if argc == 1: + (self._stop,) = args + self._start = type(self._stop)(0) + self._step = type(self._stop - self._start)(1) + elif argc == 2: + self._start, self._stop = args + self._step = type(self._stop - self._start)(1) + elif argc == 3: + self._start, self._stop, self._step = args + elif argc == 0: + raise TypeError( + 'numeric_range expected at least ' + '1 argument, got {}'.format(argc) + ) + else: + raise TypeError( + 'numeric_range expected at most ' + '3 arguments, got {}'.format(argc) + ) + + self._zero = type(self._step)(0) + if self._step == self._zero: + raise ValueError('numeric_range() arg 3 must not be zero') + self._growing = self._step > self._zero + self._init_len() + + def __bool__(self): + if self._growing: + return self._start < self._stop + else: + return self._start > self._stop + + def __contains__(self, elem): + if self._growing: + if self._start <= elem < self._stop: + return (elem - self._start) % self._step == self._zero + else: + if self._start >= elem > self._stop: + return (self._start - elem) % (-self._step) == self._zero + + return False + + def __eq__(self, other): + if isinstance(other, numeric_range): + empty_self = not bool(self) + empty_other = not bool(other) + if empty_self or empty_other: + return empty_self and empty_other # True if both empty + else: + return ( + self._start == other._start + and self._step == other._step + and self._get_by_index(-1) == other._get_by_index(-1) + ) + else: + return False + + def __getitem__(self, key): + if isinstance(key, int): + return self._get_by_index(key) + elif isinstance(key, slice): + step = self._step if key.step is None else key.step * self._step + + if key.start is None or key.start <= -self._len: + start = self._start + elif key.start >= self._len: + start = self._stop + else: # -self._len < key.start < self._len + start = self._get_by_index(key.start) + + if key.stop is None or key.stop >= self._len: + stop = self._stop + elif key.stop <= -self._len: + stop = self._start + else: # -self._len < key.stop < self._len + stop = self._get_by_index(key.stop) + + return numeric_range(start, stop, step) + else: + raise TypeError( + 'numeric range indices must be ' + 'integers or slices, not {}'.format(type(key).__name__) + ) + + def __hash__(self): + if self: + return hash((self._start, self._get_by_index(-1), self._step)) + else: + return self._EMPTY_HASH + + def __iter__(self): + values = (self._start + (n * self._step) for n in count()) + if self._growing: + return takewhile(partial(gt, self._stop), values) + else: + return takewhile(partial(lt, self._stop), values) + + def __len__(self): + return self._len + + def _init_len(self): + if self._growing: + start = self._start + stop = self._stop + step = self._step + else: + start = self._stop + stop = self._start + step = -self._step + distance = stop - start + if distance <= self._zero: + self._len = 0 + else: # distance > 0 and step > 0: regular euclidean division + q, r = divmod(distance, step) + self._len = int(q) + int(r != self._zero) + + def __reduce__(self): + return numeric_range, (self._start, self._stop, self._step) + + def __repr__(self): + if self._step == 1: + return "numeric_range({}, {})".format( + repr(self._start), repr(self._stop) + ) + else: + return "numeric_range({}, {}, {})".format( + repr(self._start), repr(self._stop), repr(self._step) + ) + + def __reversed__(self): + return iter( + numeric_range( + self._get_by_index(-1), self._start - self._step, -self._step + ) + ) + + def count(self, value): + return int(value in self) + + def index(self, value): + if self._growing: + if self._start <= value < self._stop: + q, r = divmod(value - self._start, self._step) + if r == self._zero: + return int(q) + else: + if self._start >= value > self._stop: + q, r = divmod(self._start - value, -self._step) + if r == self._zero: + return int(q) + + raise ValueError("{} is not in numeric range".format(value)) + + def _get_by_index(self, i): + if i < 0: + i += self._len + if i < 0 or i >= self._len: + raise IndexError("numeric range object index out of range") + return self._start + i * self._step + + +def count_cycle(iterable, n=None): + """Cycle through the items from *iterable* up to *n* times, yielding + the number of completed cycles along with each item. If *n* is omitted the + process repeats indefinitely. + + >>> list(count_cycle('AB', 3)) + [(0, 'A'), (0, 'B'), (1, 'A'), (1, 'B'), (2, 'A'), (2, 'B')] + + """ + iterable = tuple(iterable) + if not iterable: + return iter(()) + counter = count() if n is None else range(n) + return ((i, item) for i in counter for item in iterable) + + +def mark_ends(iterable): + """Yield 3-tuples of the form ``(is_first, is_last, item)``. + + >>> list(mark_ends('ABC')) + [(True, False, 'A'), (False, False, 'B'), (False, True, 'C')] + + Use this when looping over an iterable to take special action on its first + and/or last items: + + >>> iterable = ['Header', 100, 200, 'Footer'] + >>> total = 0 + >>> for is_first, is_last, item in mark_ends(iterable): + ... if is_first: + ... continue # Skip the header + ... if is_last: + ... continue # Skip the footer + ... total += item + >>> print(total) + 300 + """ + it = iter(iterable) + + try: + b = next(it) + except StopIteration: + return + + try: + for i in count(): + a = b + b = next(it) + yield i == 0, False, a + + except StopIteration: + yield i == 0, True, a + + +def locate(iterable, pred=bool, window_size=None): + """Yield the index of each item in *iterable* for which *pred* returns + ``True``. + + *pred* defaults to :func:`bool`, which will select truthy items: + + >>> list(locate([0, 1, 1, 0, 1, 0, 0])) + [1, 2, 4] + + Set *pred* to a custom function to, e.g., find the indexes for a particular + item. + + >>> list(locate(['a', 'b', 'c', 'b'], lambda x: x == 'b')) + [1, 3] + + If *window_size* is given, then the *pred* function will be called with + that many items. This enables searching for sub-sequences: + + >>> iterable = [0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3] + >>> pred = lambda *args: args == (1, 2, 3) + >>> list(locate(iterable, pred=pred, window_size=3)) + [1, 5, 9] + + Use with :func:`seekable` to find indexes and then retrieve the associated + items: + + >>> from itertools import count + >>> from more_itertools import seekable + >>> source = (3 * n + 1 if (n % 2) else n // 2 for n in count()) + >>> it = seekable(source) + >>> pred = lambda x: x > 100 + >>> indexes = locate(it, pred=pred) + >>> i = next(indexes) + >>> it.seek(i) + >>> next(it) + 106 + + """ + if window_size is None: + return compress(count(), map(pred, iterable)) + + if window_size < 1: + raise ValueError('window size must be at least 1') + + it = windowed(iterable, window_size, fillvalue=_marker) + return compress(count(), starmap(pred, it)) + + +def lstrip(iterable, pred): + """Yield the items from *iterable*, but strip any from the beginning + for which *pred* returns ``True``. + + For example, to remove a set of items from the start of an iterable: + + >>> iterable = (None, False, None, 1, 2, None, 3, False, None) + >>> pred = lambda x: x in {None, False, ''} + >>> list(lstrip(iterable, pred)) + [1, 2, None, 3, False, None] + + This function is analogous to to :func:`str.lstrip`, and is essentially + an wrapper for :func:`itertools.dropwhile`. + + """ + return dropwhile(pred, iterable) + + +def rstrip(iterable, pred): + """Yield the items from *iterable*, but strip any from the end + for which *pred* returns ``True``. + + For example, to remove a set of items from the end of an iterable: + + >>> iterable = (None, False, None, 1, 2, None, 3, False, None) + >>> pred = lambda x: x in {None, False, ''} + >>> list(rstrip(iterable, pred)) + [None, False, None, 1, 2, None, 3] + + This function is analogous to :func:`str.rstrip`. + + """ + cache = [] + cache_append = cache.append + cache_clear = cache.clear + for x in iterable: + if pred(x): + cache_append(x) + else: + yield from cache + cache_clear() + yield x + + +def strip(iterable, pred): + """Yield the items from *iterable*, but strip any from the + beginning and end for which *pred* returns ``True``. + + For example, to remove a set of items from both ends of an iterable: + + >>> iterable = (None, False, None, 1, 2, None, 3, False, None) + >>> pred = lambda x: x in {None, False, ''} + >>> list(strip(iterable, pred)) + [1, 2, None, 3] + + This function is analogous to :func:`str.strip`. + + """ + return rstrip(lstrip(iterable, pred), pred) + + +class islice_extended: + """An extension of :func:`itertools.islice` that supports negative values + for *stop*, *start*, and *step*. + + >>> iterable = iter('abcdefgh') + >>> list(islice_extended(iterable, -4, -1)) + ['e', 'f', 'g'] + + Slices with negative values require some caching of *iterable*, but this + function takes care to minimize the amount of memory required. + + For example, you can use a negative step with an infinite iterator: + + >>> from itertools import count + >>> list(islice_extended(count(), 110, 99, -2)) + [110, 108, 106, 104, 102, 100] + + You can also use slice notation directly: + + >>> iterable = map(str, count()) + >>> it = islice_extended(iterable)[10:20:2] + >>> list(it) + ['10', '12', '14', '16', '18'] + + """ + + def __init__(self, iterable, *args): + it = iter(iterable) + if args: + self._iterable = _islice_helper(it, slice(*args)) + else: + self._iterable = it + + def __iter__(self): + return self + + def __next__(self): + return next(self._iterable) + + def __getitem__(self, key): + if isinstance(key, slice): + return islice_extended(_islice_helper(self._iterable, key)) + + raise TypeError('islice_extended.__getitem__ argument must be a slice') + + +def _islice_helper(it, s): + start = s.start + stop = s.stop + if s.step == 0: + raise ValueError('step argument must be a non-zero integer or None.') + step = s.step or 1 + + if step > 0: + start = 0 if (start is None) else start + + if start < 0: + # Consume all but the last -start items + cache = deque(enumerate(it, 1), maxlen=-start) + len_iter = cache[-1][0] if cache else 0 + + # Adjust start to be positive + i = max(len_iter + start, 0) + + # Adjust stop to be positive + if stop is None: + j = len_iter + elif stop >= 0: + j = min(stop, len_iter) + else: + j = max(len_iter + stop, 0) + + # Slice the cache + n = j - i + if n <= 0: + return + + for index, item in islice(cache, 0, n, step): + yield item + elif (stop is not None) and (stop < 0): + # Advance to the start position + next(islice(it, start, start), None) + + # When stop is negative, we have to carry -stop items while + # iterating + cache = deque(islice(it, -stop), maxlen=-stop) + + for index, item in enumerate(it): + cached_item = cache.popleft() + if index % step == 0: + yield cached_item + cache.append(item) + else: + # When both start and stop are positive we have the normal case + yield from islice(it, start, stop, step) + else: + start = -1 if (start is None) else start + + if (stop is not None) and (stop < 0): + # Consume all but the last items + n = -stop - 1 + cache = deque(enumerate(it, 1), maxlen=n) + len_iter = cache[-1][0] if cache else 0 + + # If start and stop are both negative they are comparable and + # we can just slice. Otherwise we can adjust start to be negative + # and then slice. + if start < 0: + i, j = start, stop + else: + i, j = min(start - len_iter, -1), None + + for index, item in list(cache)[i:j:step]: + yield item + else: + # Advance to the stop position + if stop is not None: + m = stop + 1 + next(islice(it, m, m), None) + + # stop is positive, so if start is negative they are not comparable + # and we need the rest of the items. + if start < 0: + i = start + n = None + # stop is None and start is positive, so we just need items up to + # the start index. + elif stop is None: + i = None + n = start + 1 + # Both stop and start are positive, so they are comparable. + else: + i = None + n = start - stop + if n <= 0: + return + + cache = list(islice(it, n)) + + yield from cache[i::step] + + +def always_reversible(iterable): + """An extension of :func:`reversed` that supports all iterables, not + just those which implement the ``Reversible`` or ``Sequence`` protocols. + + >>> print(*always_reversible(x for x in range(3))) + 2 1 0 + + If the iterable is already reversible, this function returns the + result of :func:`reversed()`. If the iterable is not reversible, + this function will cache the remaining items in the iterable and + yield them in reverse order, which may require significant storage. + """ + try: + return reversed(iterable) + except TypeError: + return reversed(list(iterable)) + + +def consecutive_groups(iterable, ordering=lambda x: x): + """Yield groups of consecutive items using :func:`itertools.groupby`. + The *ordering* function determines whether two items are adjacent by + returning their position. + + By default, the ordering function is the identity function. This is + suitable for finding runs of numbers: + + >>> iterable = [1, 10, 11, 12, 20, 30, 31, 32, 33, 40] + >>> for group in consecutive_groups(iterable): + ... print(list(group)) + [1] + [10, 11, 12] + [20] + [30, 31, 32, 33] + [40] + + For finding runs of adjacent letters, try using the :meth:`index` method + of a string of letters: + + >>> from string import ascii_lowercase + >>> iterable = 'abcdfgilmnop' + >>> ordering = ascii_lowercase.index + >>> for group in consecutive_groups(iterable, ordering): + ... print(list(group)) + ['a', 'b', 'c', 'd'] + ['f', 'g'] + ['i'] + ['l', 'm', 'n', 'o', 'p'] + + Each group of consecutive items is an iterator that shares it source with + *iterable*. When an an output group is advanced, the previous group is + no longer available unless its elements are copied (e.g., into a ``list``). + + >>> iterable = [1, 2, 11, 12, 21, 22] + >>> saved_groups = [] + >>> for group in consecutive_groups(iterable): + ... saved_groups.append(list(group)) # Copy group elements + >>> saved_groups + [[1, 2], [11, 12], [21, 22]] + + """ + for k, g in groupby( + enumerate(iterable), key=lambda x: x[0] - ordering(x[1]) + ): + yield map(itemgetter(1), g) + + +def difference(iterable, func=sub, *, initial=None): + """This function is the inverse of :func:`itertools.accumulate`. By default + it will compute the first difference of *iterable* using + :func:`operator.sub`: + + >>> from itertools import accumulate + >>> iterable = accumulate([0, 1, 2, 3, 4]) # produces 0, 1, 3, 6, 10 + >>> list(difference(iterable)) + [0, 1, 2, 3, 4] + + *func* defaults to :func:`operator.sub`, but other functions can be + specified. They will be applied as follows:: + + A, B, C, D, ... --> A, func(B, A), func(C, B), func(D, C), ... + + For example, to do progressive division: + + >>> iterable = [1, 2, 6, 24, 120] + >>> func = lambda x, y: x // y + >>> list(difference(iterable, func)) + [1, 2, 3, 4, 5] + + If the *initial* keyword is set, the first element will be skipped when + computing successive differences. + + >>> it = [10, 11, 13, 16] # from accumulate([1, 2, 3], initial=10) + >>> list(difference(it, initial=10)) + [1, 2, 3] + + """ + a, b = tee(iterable) + try: + first = [next(b)] + except StopIteration: + return iter([]) + + if initial is not None: + first = [] + + return chain(first, starmap(func, zip(b, a))) + + +class SequenceView(Sequence): + """Return a read-only view of the sequence object *target*. + + :class:`SequenceView` objects are analogous to Python's built-in + "dictionary view" types. They provide a dynamic view of a sequence's items, + meaning that when the sequence updates, so does the view. + + >>> seq = ['0', '1', '2'] + >>> view = SequenceView(seq) + >>> view + SequenceView(['0', '1', '2']) + >>> seq.append('3') + >>> view + SequenceView(['0', '1', '2', '3']) + + Sequence views support indexing, slicing, and length queries. They act + like the underlying sequence, except they don't allow assignment: + + >>> view[1] + '1' + >>> view[1:-1] + ['1', '2'] + >>> len(view) + 4 + + Sequence views are useful as an alternative to copying, as they don't + require (much) extra storage. + + """ + + def __init__(self, target): + if not isinstance(target, Sequence): + raise TypeError + self._target = target + + def __getitem__(self, index): + return self._target[index] + + def __len__(self): + return len(self._target) + + def __repr__(self): + return '{}({})'.format(self.__class__.__name__, repr(self._target)) + + +class seekable: + """Wrap an iterator to allow for seeking backward and forward. This + progressively caches the items in the source iterable so they can be + re-visited. + + Call :meth:`seek` with an index to seek to that position in the source + iterable. + + To "reset" an iterator, seek to ``0``: + + >>> from itertools import count + >>> it = seekable((str(n) for n in count())) + >>> next(it), next(it), next(it) + ('0', '1', '2') + >>> it.seek(0) + >>> next(it), next(it), next(it) + ('0', '1', '2') + >>> next(it) + '3' + + You can also seek forward: + + >>> it = seekable((str(n) for n in range(20))) + >>> it.seek(10) + >>> next(it) + '10' + >>> it.seek(20) # Seeking past the end of the source isn't a problem + >>> list(it) + [] + >>> it.seek(0) # Resetting works even after hitting the end + >>> next(it), next(it), next(it) + ('0', '1', '2') + + Call :meth:`peek` to look ahead one item without advancing the iterator: + + >>> it = seekable('1234') + >>> it.peek() + '1' + >>> list(it) + ['1', '2', '3', '4'] + >>> it.peek(default='empty') + 'empty' + + Before the iterator is at its end, calling :func:`bool` on it will return + ``True``. After it will return ``False``: + + >>> it = seekable('5678') + >>> bool(it) + True + >>> list(it) + ['5', '6', '7', '8'] + >>> bool(it) + False + + You may view the contents of the cache with the :meth:`elements` method. + That returns a :class:`SequenceView`, a view that updates automatically: + + >>> it = seekable((str(n) for n in range(10))) + >>> next(it), next(it), next(it) + ('0', '1', '2') + >>> elements = it.elements() + >>> elements + SequenceView(['0', '1', '2']) + >>> next(it) + '3' + >>> elements + SequenceView(['0', '1', '2', '3']) + + By default, the cache grows as the source iterable progresses, so beware of + wrapping very large or infinite iterables. Supply *maxlen* to limit the + size of the cache (this of course limits how far back you can seek). + + >>> from itertools import count + >>> it = seekable((str(n) for n in count()), maxlen=2) + >>> next(it), next(it), next(it), next(it) + ('0', '1', '2', '3') + >>> list(it.elements()) + ['2', '3'] + >>> it.seek(0) + >>> next(it), next(it), next(it), next(it) + ('2', '3', '4', '5') + >>> next(it) + '6' + + """ + + def __init__(self, iterable, maxlen=None): + self._source = iter(iterable) + if maxlen is None: + self._cache = [] + else: + self._cache = deque([], maxlen) + self._index = None + + def __iter__(self): + return self + + def __next__(self): + if self._index is not None: + try: + item = self._cache[self._index] + except IndexError: + self._index = None + else: + self._index += 1 + return item + + item = next(self._source) + self._cache.append(item) + return item + + def __bool__(self): + try: + self.peek() + except StopIteration: + return False + return True + + def peek(self, default=_marker): + try: + peeked = next(self) + except StopIteration: + if default is _marker: + raise + return default + if self._index is None: + self._index = len(self._cache) + self._index -= 1 + return peeked + + def elements(self): + return SequenceView(self._cache) + + def seek(self, index): + self._index = index + remainder = index - len(self._cache) + if remainder > 0: + consume(self, remainder) + + +class run_length: + """ + :func:`run_length.encode` compresses an iterable with run-length encoding. + It yields groups of repeated items with the count of how many times they + were repeated: + + >>> uncompressed = 'abbcccdddd' + >>> list(run_length.encode(uncompressed)) + [('a', 1), ('b', 2), ('c', 3), ('d', 4)] + + :func:`run_length.decode` decompresses an iterable that was previously + compressed with run-length encoding. It yields the items of the + decompressed iterable: + + >>> compressed = [('a', 1), ('b', 2), ('c', 3), ('d', 4)] + >>> list(run_length.decode(compressed)) + ['a', 'b', 'b', 'c', 'c', 'c', 'd', 'd', 'd', 'd'] + + """ + + @staticmethod + def encode(iterable): + return ((k, ilen(g)) for k, g in groupby(iterable)) + + @staticmethod + def decode(iterable): + return chain.from_iterable(repeat(k, n) for k, n in iterable) + + +def exactly_n(iterable, n, predicate=bool): + """Return ``True`` if exactly ``n`` items in the iterable are ``True`` + according to the *predicate* function. + + >>> exactly_n([True, True, False], 2) + True + >>> exactly_n([True, True, False], 1) + False + >>> exactly_n([0, 1, 2, 3, 4, 5], 3, lambda x: x < 3) + True + + The iterable will be advanced until ``n + 1`` truthy items are encountered, + so avoid calling it on infinite iterables. + + """ + return len(take(n + 1, filter(predicate, iterable))) == n + + +def circular_shifts(iterable): + """Return a list of circular shifts of *iterable*. + + >>> circular_shifts(range(4)) + [(0, 1, 2, 3), (1, 2, 3, 0), (2, 3, 0, 1), (3, 0, 1, 2)] + """ + lst = list(iterable) + return take(len(lst), windowed(cycle(lst), len(lst))) + + +def make_decorator(wrapping_func, result_index=0): + """Return a decorator version of *wrapping_func*, which is a function that + modifies an iterable. *result_index* is the position in that function's + signature where the iterable goes. + + This lets you use itertools on the "production end," i.e. at function + definition. This can augment what the function returns without changing the + function's code. + + For example, to produce a decorator version of :func:`chunked`: + + >>> from more_itertools import chunked + >>> chunker = make_decorator(chunked, result_index=0) + >>> @chunker(3) + ... def iter_range(n): + ... return iter(range(n)) + ... + >>> list(iter_range(9)) + [[0, 1, 2], [3, 4, 5], [6, 7, 8]] + + To only allow truthy items to be returned: + + >>> truth_serum = make_decorator(filter, result_index=1) + >>> @truth_serum(bool) + ... def boolean_test(): + ... return [0, 1, '', ' ', False, True] + ... + >>> list(boolean_test()) + [1, ' ', True] + + The :func:`peekable` and :func:`seekable` wrappers make for practical + decorators: + + >>> from more_itertools import peekable + >>> peekable_function = make_decorator(peekable) + >>> @peekable_function() + ... def str_range(*args): + ... return (str(x) for x in range(*args)) + ... + >>> it = str_range(1, 20, 2) + >>> next(it), next(it), next(it) + ('1', '3', '5') + >>> it.peek() + '7' + >>> next(it) + '7' + + """ + # See https://sites.google.com/site/bbayles/index/decorator_factory for + # notes on how this works. + def decorator(*wrapping_args, **wrapping_kwargs): + def outer_wrapper(f): + def inner_wrapper(*args, **kwargs): + result = f(*args, **kwargs) + wrapping_args_ = list(wrapping_args) + wrapping_args_.insert(result_index, result) + return wrapping_func(*wrapping_args_, **wrapping_kwargs) + + return inner_wrapper + + return outer_wrapper + + return decorator + + +def map_reduce(iterable, keyfunc, valuefunc=None, reducefunc=None): + """Return a dictionary that maps the items in *iterable* to categories + defined by *keyfunc*, transforms them with *valuefunc*, and + then summarizes them by category with *reducefunc*. + + *valuefunc* defaults to the identity function if it is unspecified. + If *reducefunc* is unspecified, no summarization takes place: + + >>> keyfunc = lambda x: x.upper() + >>> result = map_reduce('abbccc', keyfunc) + >>> sorted(result.items()) + [('A', ['a']), ('B', ['b', 'b']), ('C', ['c', 'c', 'c'])] + + Specifying *valuefunc* transforms the categorized items: + + >>> keyfunc = lambda x: x.upper() + >>> valuefunc = lambda x: 1 + >>> result = map_reduce('abbccc', keyfunc, valuefunc) + >>> sorted(result.items()) + [('A', [1]), ('B', [1, 1]), ('C', [1, 1, 1])] + + Specifying *reducefunc* summarizes the categorized items: + + >>> keyfunc = lambda x: x.upper() + >>> valuefunc = lambda x: 1 + >>> reducefunc = sum + >>> result = map_reduce('abbccc', keyfunc, valuefunc, reducefunc) + >>> sorted(result.items()) + [('A', 1), ('B', 2), ('C', 3)] + + You may want to filter the input iterable before applying the map/reduce + procedure: + + >>> all_items = range(30) + >>> items = [x for x in all_items if 10 <= x <= 20] # Filter + >>> keyfunc = lambda x: x % 2 # Evens map to 0; odds to 1 + >>> categories = map_reduce(items, keyfunc=keyfunc) + >>> sorted(categories.items()) + [(0, [10, 12, 14, 16, 18, 20]), (1, [11, 13, 15, 17, 19])] + >>> summaries = map_reduce(items, keyfunc=keyfunc, reducefunc=sum) + >>> sorted(summaries.items()) + [(0, 90), (1, 75)] + + Note that all items in the iterable are gathered into a list before the + summarization step, which may require significant storage. + + The returned object is a :obj:`collections.defaultdict` with the + ``default_factory`` set to ``None``, such that it behaves like a normal + dictionary. + + """ + valuefunc = (lambda x: x) if (valuefunc is None) else valuefunc + + ret = defaultdict(list) + for item in iterable: + key = keyfunc(item) + value = valuefunc(item) + ret[key].append(value) + + if reducefunc is not None: + for key, value_list in ret.items(): + ret[key] = reducefunc(value_list) + + ret.default_factory = None + return ret + + +def rlocate(iterable, pred=bool, window_size=None): + """Yield the index of each item in *iterable* for which *pred* returns + ``True``, starting from the right and moving left. + + *pred* defaults to :func:`bool`, which will select truthy items: + + >>> list(rlocate([0, 1, 1, 0, 1, 0, 0])) # Truthy at 1, 2, and 4 + [4, 2, 1] + + Set *pred* to a custom function to, e.g., find the indexes for a particular + item: + + >>> iterable = iter('abcb') + >>> pred = lambda x: x == 'b' + >>> list(rlocate(iterable, pred)) + [3, 1] + + If *window_size* is given, then the *pred* function will be called with + that many items. This enables searching for sub-sequences: + + >>> iterable = [0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3] + >>> pred = lambda *args: args == (1, 2, 3) + >>> list(rlocate(iterable, pred=pred, window_size=3)) + [9, 5, 1] + + Beware, this function won't return anything for infinite iterables. + If *iterable* is reversible, ``rlocate`` will reverse it and search from + the right. Otherwise, it will search from the left and return the results + in reverse order. + + See :func:`locate` to for other example applications. + + """ + if window_size is None: + try: + len_iter = len(iterable) + return (len_iter - i - 1 for i in locate(reversed(iterable), pred)) + except TypeError: + pass + + return reversed(list(locate(iterable, pred, window_size))) + + +def replace(iterable, pred, substitutes, count=None, window_size=1): + """Yield the items from *iterable*, replacing the items for which *pred* + returns ``True`` with the items from the iterable *substitutes*. + + >>> iterable = [1, 1, 0, 1, 1, 0, 1, 1] + >>> pred = lambda x: x == 0 + >>> substitutes = (2, 3) + >>> list(replace(iterable, pred, substitutes)) + [1, 1, 2, 3, 1, 1, 2, 3, 1, 1] + + If *count* is given, the number of replacements will be limited: + + >>> iterable = [1, 1, 0, 1, 1, 0, 1, 1, 0] + >>> pred = lambda x: x == 0 + >>> substitutes = [None] + >>> list(replace(iterable, pred, substitutes, count=2)) + [1, 1, None, 1, 1, None, 1, 1, 0] + + Use *window_size* to control the number of items passed as arguments to + *pred*. This allows for locating and replacing subsequences. + + >>> iterable = [0, 1, 2, 5, 0, 1, 2, 5] + >>> window_size = 3 + >>> pred = lambda *args: args == (0, 1, 2) # 3 items passed to pred + >>> substitutes = [3, 4] # Splice in these items + >>> list(replace(iterable, pred, substitutes, window_size=window_size)) + [3, 4, 5, 3, 4, 5] + + """ + if window_size < 1: + raise ValueError('window_size must be at least 1') + + # Save the substitutes iterable, since it's used more than once + substitutes = tuple(substitutes) + + # Add padding such that the number of windows matches the length of the + # iterable + it = chain(iterable, [_marker] * (window_size - 1)) + windows = windowed(it, window_size) + + n = 0 + for w in windows: + # If the current window matches our predicate (and we haven't hit + # our maximum number of replacements), splice in the substitutes + # and then consume the following windows that overlap with this one. + # For example, if the iterable is (0, 1, 2, 3, 4...) + # and the window size is 2, we have (0, 1), (1, 2), (2, 3)... + # If the predicate matches on (0, 1), we need to zap (0, 1) and (1, 2) + if pred(*w): + if (count is None) or (n < count): + n += 1 + yield from substitutes + consume(windows, window_size - 1) + continue + + # If there was no match (or we've reached the replacement limit), + # yield the first item from the window. + if w and (w[0] is not _marker): + yield w[0] + + +def partitions(iterable): + """Yield all possible order-preserving partitions of *iterable*. + + >>> iterable = 'abc' + >>> for part in partitions(iterable): + ... print([''.join(p) for p in part]) + ['abc'] + ['a', 'bc'] + ['ab', 'c'] + ['a', 'b', 'c'] + + This is unrelated to :func:`partition`. + + """ + sequence = list(iterable) + n = len(sequence) + for i in powerset(range(1, n)): + yield [sequence[i:j] for i, j in zip((0,) + i, i + (n,))] + + +def set_partitions(iterable, k=None): + """ + Yield the set partitions of *iterable* into *k* parts. Set partitions are + not order-preserving. + + >>> iterable = 'abc' + >>> for part in set_partitions(iterable, 2): + ... print([''.join(p) for p in part]) + ['a', 'bc'] + ['ab', 'c'] + ['b', 'ac'] + + + If *k* is not given, every set partition is generated. + + >>> iterable = 'abc' + >>> for part in set_partitions(iterable): + ... print([''.join(p) for p in part]) + ['abc'] + ['a', 'bc'] + ['ab', 'c'] + ['b', 'ac'] + ['a', 'b', 'c'] + + """ + L = list(iterable) + n = len(L) + if k is not None: + if k < 1: + raise ValueError( + "Can't partition in a negative or zero number of groups" + ) + elif k > n: + return + + def set_partitions_helper(L, k): + n = len(L) + if k == 1: + yield [L] + elif n == k: + yield [[s] for s in L] + else: + e, *M = L + for p in set_partitions_helper(M, k - 1): + yield [[e], *p] + for p in set_partitions_helper(M, k): + for i in range(len(p)): + yield p[:i] + [[e] + p[i]] + p[i + 1 :] + + if k is None: + for k in range(1, n + 1): + yield from set_partitions_helper(L, k) + else: + yield from set_partitions_helper(L, k) + + +class time_limited: + """ + Yield items from *iterable* until *limit_seconds* have passed. + If the time limit expires before all items have been yielded, the + ``timed_out`` parameter will be set to ``True``. + + >>> from time import sleep + >>> def generator(): + ... yield 1 + ... yield 2 + ... sleep(0.2) + ... yield 3 + >>> iterable = time_limited(0.1, generator()) + >>> list(iterable) + [1, 2] + >>> iterable.timed_out + True + + Note that the time is checked before each item is yielded, and iteration + stops if the time elapsed is greater than *limit_seconds*. If your time + limit is 1 second, but it takes 2 seconds to generate the first item from + the iterable, the function will run for 2 seconds and not yield anything. + + """ + + def __init__(self, limit_seconds, iterable): + if limit_seconds < 0: + raise ValueError('limit_seconds must be positive') + self.limit_seconds = limit_seconds + self._iterable = iter(iterable) + self._start_time = monotonic() + self.timed_out = False + + def __iter__(self): + return self + + def __next__(self): + item = next(self._iterable) + if monotonic() - self._start_time > self.limit_seconds: + self.timed_out = True + raise StopIteration + + return item + + +def only(iterable, default=None, too_long=None): + """If *iterable* has only one item, return it. + If it has zero items, return *default*. + If it has more than one item, raise the exception given by *too_long*, + which is ``ValueError`` by default. + + >>> only([], default='missing') + 'missing' + >>> only([1]) + 1 + >>> only([1, 2]) # doctest: +IGNORE_EXCEPTION_DETAIL + Traceback (most recent call last): + ... + ValueError: Expected exactly one item in iterable, but got 1, 2, + and perhaps more.' + >>> only([1, 2], too_long=TypeError) # doctest: +IGNORE_EXCEPTION_DETAIL + Traceback (most recent call last): + ... + TypeError + + Note that :func:`only` attempts to advance *iterable* twice to ensure there + is only one item. See :func:`spy` or :func:`peekable` to check + iterable contents less destructively. + """ + it = iter(iterable) + first_value = next(it, default) + + try: + second_value = next(it) + except StopIteration: + pass + else: + msg = ( + 'Expected exactly one item in iterable, but got {!r}, {!r}, ' + 'and perhaps more.'.format(first_value, second_value) + ) + raise too_long or ValueError(msg) + + return first_value + + +def ichunked(iterable, n): + """Break *iterable* into sub-iterables with *n* elements each. + :func:`ichunked` is like :func:`chunked`, but it yields iterables + instead of lists. + + If the sub-iterables are read in order, the elements of *iterable* + won't be stored in memory. + If they are read out of order, :func:`itertools.tee` is used to cache + elements as necessary. + + >>> from itertools import count + >>> all_chunks = ichunked(count(), 4) + >>> c_1, c_2, c_3 = next(all_chunks), next(all_chunks), next(all_chunks) + >>> list(c_2) # c_1's elements have been cached; c_3's haven't been + [4, 5, 6, 7] + >>> list(c_1) + [0, 1, 2, 3] + >>> list(c_3) + [8, 9, 10, 11] + + """ + source = iter(iterable) + + while True: + # Check to see whether we're at the end of the source iterable + item = next(source, _marker) + if item is _marker: + return + + # Clone the source and yield an n-length slice + source, it = tee(chain([item], source)) + yield islice(it, n) + + # Advance the source iterable + consume(source, n) + + +def distinct_combinations(iterable, r): + """Yield the distinct combinations of *r* items taken from *iterable*. + + >>> list(distinct_combinations([0, 0, 1], 2)) + [(0, 0), (0, 1)] + + Equivalent to ``set(combinations(iterable))``, except duplicates are not + generated and thrown away. For larger input sequences this is much more + efficient. + + """ + if r < 0: + raise ValueError('r must be non-negative') + elif r == 0: + yield () + return + pool = tuple(iterable) + generators = [unique_everseen(enumerate(pool), key=itemgetter(1))] + current_combo = [None] * r + level = 0 + while generators: + try: + cur_idx, p = next(generators[-1]) + except StopIteration: + generators.pop() + level -= 1 + continue + current_combo[level] = p + if level + 1 == r: + yield tuple(current_combo) + else: + generators.append( + unique_everseen( + enumerate(pool[cur_idx + 1 :], cur_idx + 1), + key=itemgetter(1), + ) + ) + level += 1 + + +def filter_except(validator, iterable, *exceptions): + """Yield the items from *iterable* for which the *validator* function does + not raise one of the specified *exceptions*. + + *validator* is called for each item in *iterable*. + It should be a function that accepts one argument and raises an exception + if that item is not valid. + + >>> iterable = ['1', '2', 'three', '4', None] + >>> list(filter_except(int, iterable, ValueError, TypeError)) + ['1', '2', '4'] + + If an exception other than one given by *exceptions* is raised by + *validator*, it is raised like normal. + """ + for item in iterable: + try: + validator(item) + except exceptions: + pass + else: + yield item + + +def map_except(function, iterable, *exceptions): + """Transform each item from *iterable* with *function* and yield the + result, unless *function* raises one of the specified *exceptions*. + + *function* is called to transform each item in *iterable*. + It should be a accept one argument. + + >>> iterable = ['1', '2', 'three', '4', None] + >>> list(map_except(int, iterable, ValueError, TypeError)) + [1, 2, 4] + + If an exception other than one given by *exceptions* is raised by + *function*, it is raised like normal. + """ + for item in iterable: + try: + yield function(item) + except exceptions: + pass + + +def _sample_unweighted(iterable, k): + # Implementation of "Algorithm L" from the 1994 paper by Kim-Hung Li: + # "Reservoir-Sampling Algorithms of Time Complexity O(n(1+log(N/n)))". + + # Fill up the reservoir (collection of samples) with the first `k` samples + reservoir = take(k, iterable) + + # Generate random number that's the largest in a sample of k U(0,1) numbers + # Largest order statistic: https://en.wikipedia.org/wiki/Order_statistic + W = exp(log(random()) / k) + + # The number of elements to skip before changing the reservoir is a random + # number with a geometric distribution. Sample it using random() and logs. + next_index = k + floor(log(random()) / log(1 - W)) + + for index, element in enumerate(iterable, k): + + if index == next_index: + reservoir[randrange(k)] = element + # The new W is the largest in a sample of k U(0, `old_W`) numbers + W *= exp(log(random()) / k) + next_index += floor(log(random()) / log(1 - W)) + 1 + + return reservoir + + +def _sample_weighted(iterable, k, weights): + # Implementation of "A-ExpJ" from the 2006 paper by Efraimidis et al. : + # "Weighted random sampling with a reservoir". + + # Log-transform for numerical stability for weights that are small/large + weight_keys = (log(random()) / weight for weight in weights) + + # Fill up the reservoir (collection of samples) with the first `k` + # weight-keys and elements, then heapify the list. + reservoir = take(k, zip(weight_keys, iterable)) + heapify(reservoir) + + # The number of jumps before changing the reservoir is a random variable + # with an exponential distribution. Sample it using random() and logs. + smallest_weight_key, _ = reservoir[0] + weights_to_skip = log(random()) / smallest_weight_key + + for weight, element in zip(weights, iterable): + if weight >= weights_to_skip: + # The notation here is consistent with the paper, but we store + # the weight-keys in log-space for better numerical stability. + smallest_weight_key, _ = reservoir[0] + t_w = exp(weight * smallest_weight_key) + r_2 = uniform(t_w, 1) # generate U(t_w, 1) + weight_key = log(r_2) / weight + heapreplace(reservoir, (weight_key, element)) + smallest_weight_key, _ = reservoir[0] + weights_to_skip = log(random()) / smallest_weight_key + else: + weights_to_skip -= weight + + # Equivalent to [element for weight_key, element in sorted(reservoir)] + return [heappop(reservoir)[1] for _ in range(k)] + + +def sample(iterable, k, weights=None): + """Return a *k*-length list of elements chosen (without replacement) + from the *iterable*. Like :func:`random.sample`, but works on iterables + of unknown length. + + >>> iterable = range(100) + >>> sample(iterable, 5) # doctest: +SKIP + [81, 60, 96, 16, 4] + + An iterable with *weights* may also be given: + + >>> iterable = range(100) + >>> weights = (i * i + 1 for i in range(100)) + >>> sampled = sample(iterable, 5, weights=weights) # doctest: +SKIP + [79, 67, 74, 66, 78] + + The algorithm can also be used to generate weighted random permutations. + The relative weight of each item determines the probability that it + appears late in the permutation. + + >>> data = "abcdefgh" + >>> weights = range(1, len(data) + 1) + >>> sample(data, k=len(data), weights=weights) # doctest: +SKIP + ['c', 'a', 'b', 'e', 'g', 'd', 'h', 'f'] + """ + if k == 0: + return [] + + iterable = iter(iterable) + if weights is None: + return _sample_unweighted(iterable, k) + else: + weights = iter(weights) + return _sample_weighted(iterable, k, weights) + + +def is_sorted(iterable, key=None, reverse=False): + """Returns ``True`` if the items of iterable are in sorted order, and + ``False`` otherwise. *key* and *reverse* have the same meaning that they do + in the built-in :func:`sorted` function. + + >>> is_sorted(['1', '2', '3', '4', '5'], key=int) + True + >>> is_sorted([5, 4, 3, 1, 2], reverse=True) + False + + The function returns ``False`` after encountering the first out-of-order + item. If there are no out-of-order items, the iterable is exhausted. + """ + + compare = lt if reverse else gt + it = iterable if (key is None) else map(key, iterable) + return not any(starmap(compare, pairwise(it))) + + +class AbortThread(BaseException): + pass + + +class callback_iter: + """Convert a function that uses callbacks to an iterator. + + Let *func* be a function that takes a `callback` keyword argument. + For example: + + >>> def func(callback=None): + ... for i, c in [(1, 'a'), (2, 'b'), (3, 'c')]: + ... if callback: + ... callback(i, c) + ... return 4 + + + Use ``with callback_iter(func)`` to get an iterator over the parameters + that are delivered to the callback. + + >>> with callback_iter(func) as it: + ... for args, kwargs in it: + ... print(args) + (1, 'a') + (2, 'b') + (3, 'c') + + The function will be called in a background thread. The ``done`` property + indicates whether it has completed execution. + + >>> it.done + True + + If it completes successfully, its return value will be available + in the ``result`` property. + + >>> it.result + 4 + + Notes: + + * If the function uses some keyword argument besides ``callback``, supply + *callback_kwd*. + * If it finished executing, but raised an exception, accessing the + ``result`` property will raise the same exception. + * If it hasn't finished executing, accessing the ``result`` + property from within the ``with`` block will raise ``RuntimeError``. + * If it hasn't finished executing, accessing the ``result`` property from + outside the ``with`` block will raise a + ``more_itertools.AbortThread`` exception. + * Provide *wait_seconds* to adjust how frequently the it is polled for + output. + + """ + + def __init__(self, func, callback_kwd='callback', wait_seconds=0.1): + self._func = func + self._callback_kwd = callback_kwd + self._aborted = False + self._future = None + self._wait_seconds = wait_seconds + self._executor = __import__("concurrent.futures").futures.ThreadPoolExecutor(max_workers=1) + self._iterator = self._reader() + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_value, traceback): + self._aborted = True + self._executor.shutdown() + + def __iter__(self): + return self + + def __next__(self): + return next(self._iterator) + + @property + def done(self): + if self._future is None: + return False + return self._future.done() + + @property + def result(self): + if not self.done: + raise RuntimeError('Function has not yet completed') + + return self._future.result() + + def _reader(self): + q = Queue() + + def callback(*args, **kwargs): + if self._aborted: + raise AbortThread('canceled by user') + + q.put((args, kwargs)) + + self._future = self._executor.submit( + self._func, **{self._callback_kwd: callback} + ) + + while True: + try: + item = q.get(timeout=self._wait_seconds) + except Empty: + pass + else: + q.task_done() + yield item + + if self._future.done(): + break + + remaining = [] + while True: + try: + item = q.get_nowait() + except Empty: + break + else: + q.task_done() + remaining.append(item) + q.join() + yield from remaining + + +def windowed_complete(iterable, n): + """ + Yield ``(beginning, middle, end)`` tuples, where: + + * Each ``middle`` has *n* items from *iterable* + * Each ``beginning`` has the items before the ones in ``middle`` + * Each ``end`` has the items after the ones in ``middle`` + + >>> iterable = range(7) + >>> n = 3 + >>> for beginning, middle, end in windowed_complete(iterable, n): + ... print(beginning, middle, end) + () (0, 1, 2) (3, 4, 5, 6) + (0,) (1, 2, 3) (4, 5, 6) + (0, 1) (2, 3, 4) (5, 6) + (0, 1, 2) (3, 4, 5) (6,) + (0, 1, 2, 3) (4, 5, 6) () + + Note that *n* must be at least 0 and most equal to the length of + *iterable*. + + This function will exhaust the iterable and may require significant + storage. + """ + if n < 0: + raise ValueError('n must be >= 0') + + seq = tuple(iterable) + size = len(seq) + + if n > size: + raise ValueError('n must be <= len(seq)') + + for i in range(size - n + 1): + beginning = seq[:i] + middle = seq[i : i + n] + end = seq[i + n :] + yield beginning, middle, end + + +def all_unique(iterable, key=None): + """ + Returns ``True`` if all the elements of *iterable* are unique (no two + elements are equal). + + >>> all_unique('ABCB') + False + + If a *key* function is specified, it will be used to make comparisons. + + >>> all_unique('ABCb') + True + >>> all_unique('ABCb', str.lower) + False + + The function returns as soon as the first non-unique element is + encountered. Iterables with a mix of hashable and unhashable items can + be used, but the function will be slower for unhashable items. + """ + seenset = set() + seenset_add = seenset.add + seenlist = [] + seenlist_add = seenlist.append + for element in map(key, iterable) if key else iterable: + try: + if element in seenset: + return False + seenset_add(element) + except TypeError: + if element in seenlist: + return False + seenlist_add(element) + return True + + +def nth_product(index, *args): + """Equivalent to ``list(product(*args))[index]``. + + The products of *args* can be ordered lexicographically. + :func:`nth_product` computes the product at sort position *index* without + computing the previous products. + + >>> nth_product(8, range(2), range(2), range(2), range(2)) + (1, 0, 0, 0) + + ``IndexError`` will be raised if the given *index* is invalid. + """ + pools = list(map(tuple, reversed(args))) + ns = list(map(len, pools)) + + c = reduce(mul, ns) + + if index < 0: + index += c + + if not 0 <= index < c: + raise IndexError + + result = [] + for pool, n in zip(pools, ns): + result.append(pool[index % n]) + index //= n + + return tuple(reversed(result)) + + +def nth_permutation(iterable, r, index): + """Equivalent to ``list(permutations(iterable, r))[index]``` + + The subsequences of *iterable* that are of length *r* where order is + important can be ordered lexicographically. :func:`nth_permutation` + computes the subsequence at sort position *index* directly, without + computing the previous subsequences. + + >>> nth_permutation('ghijk', 2, 5) + ('h', 'i') + + ``ValueError`` will be raised If *r* is negative or greater than the length + of *iterable*. + ``IndexError`` will be raised if the given *index* is invalid. + """ + pool = list(iterable) + n = len(pool) + + if r is None or r == n: + r, c = n, factorial(n) + elif not 0 <= r < n: + raise ValueError + else: + c = factorial(n) // factorial(n - r) + + if index < 0: + index += c + + if not 0 <= index < c: + raise IndexError + + if c == 0: + return tuple() + + result = [0] * r + q = index * factorial(n) // c if r < n else index + for d in range(1, n + 1): + q, i = divmod(q, d) + if 0 <= n - d < r: + result[n - d] = i + if q == 0: + break + + return tuple(map(pool.pop, result)) + + +def value_chain(*args): + """Yield all arguments passed to the function in the same order in which + they were passed. If an argument itself is iterable then iterate over its + values. + + >>> list(value_chain(1, 2, 3, [4, 5, 6])) + [1, 2, 3, 4, 5, 6] + + Binary and text strings are not considered iterable and are emitted + as-is: + + >>> list(value_chain('12', '34', ['56', '78'])) + ['12', '34', '56', '78'] + + + Multiple levels of nesting are not flattened. + + """ + for value in args: + if isinstance(value, (str, bytes)): + yield value + continue + try: + yield from value + except TypeError: + yield value + + +def product_index(element, *args): + """Equivalent to ``list(product(*args)).index(element)`` + + The products of *args* can be ordered lexicographically. + :func:`product_index` computes the first index of *element* without + computing the previous products. + + >>> product_index([8, 2], range(10), range(5)) + 42 + + ``ValueError`` will be raised if the given *element* isn't in the product + of *args*. + """ + index = 0 + + for x, pool in zip_longest(element, args, fillvalue=_marker): + if x is _marker or pool is _marker: + raise ValueError('element is not a product of args') + + pool = tuple(pool) + index = index * len(pool) + pool.index(x) + + return index + + +def combination_index(element, iterable): + """Equivalent to ``list(combinations(iterable, r)).index(element)`` + + The subsequences of *iterable* that are of length *r* can be ordered + lexicographically. :func:`combination_index` computes the index of the + first *element*, without computing the previous combinations. + + >>> combination_index('adf', 'abcdefg') + 10 + + ``ValueError`` will be raised if the given *element* isn't one of the + combinations of *iterable*. + """ + element = enumerate(element) + k, y = next(element, (None, None)) + if k is None: + return 0 + + indexes = [] + pool = enumerate(iterable) + for n, x in pool: + if x == y: + indexes.append(n) + tmp, y = next(element, (None, None)) + if tmp is None: + break + else: + k = tmp + else: + raise ValueError('element is not a combination of iterable') + + n, _ = last(pool, default=(n, None)) + + # Python versiosn below 3.8 don't have math.comb + index = 1 + for i, j in enumerate(reversed(indexes), start=1): + j = n - j + if i <= j: + index += factorial(j) // (factorial(i) * factorial(j - i)) + + return factorial(n + 1) // (factorial(k + 1) * factorial(n - k)) - index + + +def permutation_index(element, iterable): + """Equivalent to ``list(permutations(iterable, r)).index(element)``` + + The subsequences of *iterable* that are of length *r* where order is + important can be ordered lexicographically. :func:`permutation_index` + computes the index of the first *element* directly, without computing + the previous permutations. + + >>> permutation_index([1, 3, 2], range(5)) + 19 + + ``ValueError`` will be raised if the given *element* isn't one of the + permutations of *iterable*. + """ + index = 0 + pool = list(iterable) + for i, x in zip(range(len(pool), -1, -1), element): + r = pool.index(x) + index = index * i + r + del pool[r] + + return index + + +class countable: + """Wrap *iterable* and keep a count of how many items have been consumed. + + The ``items_seen`` attribute starts at ``0`` and increments as the iterable + is consumed: + + >>> iterable = map(str, range(10)) + >>> it = countable(iterable) + >>> it.items_seen + 0 + >>> next(it), next(it) + ('0', '1') + >>> list(it) + ['2', '3', '4', '5', '6', '7', '8', '9'] + >>> it.items_seen + 10 + """ + + def __init__(self, iterable): + self._it = iter(iterable) + self.items_seen = 0 + + def __iter__(self): + return self + + def __next__(self): + item = next(self._it) + self.items_seen += 1 + + return item diff --git a/venv/Lib/site-packages/setuptools/_vendor/more_itertools/recipes.py b/venv/Lib/site-packages/setuptools/_vendor/more_itertools/recipes.py new file mode 100644 index 0000000..521abd7 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_vendor/more_itertools/recipes.py @@ -0,0 +1,620 @@ +"""Imported from the recipes section of the itertools documentation. + +All functions taken from the recipes section of the itertools library docs +[1]_. +Some backward-compatible usability improvements have been made. + +.. [1] http://docs.python.org/library/itertools.html#recipes + +""" +import warnings +from collections import deque +from itertools import ( + chain, + combinations, + count, + cycle, + groupby, + islice, + repeat, + starmap, + tee, + zip_longest, +) +import operator +from random import randrange, sample, choice + +__all__ = [ + 'all_equal', + 'consume', + 'convolve', + 'dotproduct', + 'first_true', + 'flatten', + 'grouper', + 'iter_except', + 'ncycles', + 'nth', + 'nth_combination', + 'padnone', + 'pad_none', + 'pairwise', + 'partition', + 'powerset', + 'prepend', + 'quantify', + 'random_combination_with_replacement', + 'random_combination', + 'random_permutation', + 'random_product', + 'repeatfunc', + 'roundrobin', + 'tabulate', + 'tail', + 'take', + 'unique_everseen', + 'unique_justseen', +] + + +def take(n, iterable): + """Return first *n* items of the iterable as a list. + + >>> take(3, range(10)) + [0, 1, 2] + + If there are fewer than *n* items in the iterable, all of them are + returned. + + >>> take(10, range(3)) + [0, 1, 2] + + """ + return list(islice(iterable, n)) + + +def tabulate(function, start=0): + """Return an iterator over the results of ``func(start)``, + ``func(start + 1)``, ``func(start + 2)``... + + *func* should be a function that accepts one integer argument. + + If *start* is not specified it defaults to 0. It will be incremented each + time the iterator is advanced. + + >>> square = lambda x: x ** 2 + >>> iterator = tabulate(square, -3) + >>> take(4, iterator) + [9, 4, 1, 0] + + """ + return map(function, count(start)) + + +def tail(n, iterable): + """Return an iterator over the last *n* items of *iterable*. + + >>> t = tail(3, 'ABCDEFG') + >>> list(t) + ['E', 'F', 'G'] + + """ + return iter(deque(iterable, maxlen=n)) + + +def consume(iterator, n=None): + """Advance *iterable* by *n* steps. If *n* is ``None``, consume it + entirely. + + Efficiently exhausts an iterator without returning values. Defaults to + consuming the whole iterator, but an optional second argument may be + provided to limit consumption. + + >>> i = (x for x in range(10)) + >>> next(i) + 0 + >>> consume(i, 3) + >>> next(i) + 4 + >>> consume(i) + >>> next(i) + Traceback (most recent call last): + File "", line 1, in + StopIteration + + If the iterator has fewer items remaining than the provided limit, the + whole iterator will be consumed. + + >>> i = (x for x in range(3)) + >>> consume(i, 5) + >>> next(i) + Traceback (most recent call last): + File "", line 1, in + StopIteration + + """ + # Use functions that consume iterators at C speed. + if n is None: + # feed the entire iterator into a zero-length deque + deque(iterator, maxlen=0) + else: + # advance to the empty slice starting at position n + next(islice(iterator, n, n), None) + + +def nth(iterable, n, default=None): + """Returns the nth item or a default value. + + >>> l = range(10) + >>> nth(l, 3) + 3 + >>> nth(l, 20, "zebra") + 'zebra' + + """ + return next(islice(iterable, n, None), default) + + +def all_equal(iterable): + """ + Returns ``True`` if all the elements are equal to each other. + + >>> all_equal('aaaa') + True + >>> all_equal('aaab') + False + + """ + g = groupby(iterable) + return next(g, True) and not next(g, False) + + +def quantify(iterable, pred=bool): + """Return the how many times the predicate is true. + + >>> quantify([True, False, True]) + 2 + + """ + return sum(map(pred, iterable)) + + +def pad_none(iterable): + """Returns the sequence of elements and then returns ``None`` indefinitely. + + >>> take(5, pad_none(range(3))) + [0, 1, 2, None, None] + + Useful for emulating the behavior of the built-in :func:`map` function. + + See also :func:`padded`. + + """ + return chain(iterable, repeat(None)) + + +padnone = pad_none + + +def ncycles(iterable, n): + """Returns the sequence elements *n* times + + >>> list(ncycles(["a", "b"], 3)) + ['a', 'b', 'a', 'b', 'a', 'b'] + + """ + return chain.from_iterable(repeat(tuple(iterable), n)) + + +def dotproduct(vec1, vec2): + """Returns the dot product of the two iterables. + + >>> dotproduct([10, 10], [20, 20]) + 400 + + """ + return sum(map(operator.mul, vec1, vec2)) + + +def flatten(listOfLists): + """Return an iterator flattening one level of nesting in a list of lists. + + >>> list(flatten([[0, 1], [2, 3]])) + [0, 1, 2, 3] + + See also :func:`collapse`, which can flatten multiple levels of nesting. + + """ + return chain.from_iterable(listOfLists) + + +def repeatfunc(func, times=None, *args): + """Call *func* with *args* repeatedly, returning an iterable over the + results. + + If *times* is specified, the iterable will terminate after that many + repetitions: + + >>> from operator import add + >>> times = 4 + >>> args = 3, 5 + >>> list(repeatfunc(add, times, *args)) + [8, 8, 8, 8] + + If *times* is ``None`` the iterable will not terminate: + + >>> from random import randrange + >>> times = None + >>> args = 1, 11 + >>> take(6, repeatfunc(randrange, times, *args)) # doctest:+SKIP + [2, 4, 8, 1, 8, 4] + + """ + if times is None: + return starmap(func, repeat(args)) + return starmap(func, repeat(args, times)) + + +def _pairwise(iterable): + """Returns an iterator of paired items, overlapping, from the original + + >>> take(4, pairwise(count())) + [(0, 1), (1, 2), (2, 3), (3, 4)] + + On Python 3.10 and above, this is an alias for :func:`itertools.pairwise`. + + """ + a, b = tee(iterable) + next(b, None) + yield from zip(a, b) + + +try: + from itertools import pairwise as itertools_pairwise +except ImportError: + pairwise = _pairwise +else: + + def pairwise(iterable): + yield from itertools_pairwise(iterable) + + pairwise.__doc__ = _pairwise.__doc__ + + +def grouper(iterable, n, fillvalue=None): + """Collect data into fixed-length chunks or blocks. + + >>> list(grouper('ABCDEFG', 3, 'x')) + [('A', 'B', 'C'), ('D', 'E', 'F'), ('G', 'x', 'x')] + + """ + if isinstance(iterable, int): + warnings.warn( + "grouper expects iterable as first parameter", DeprecationWarning + ) + n, iterable = iterable, n + args = [iter(iterable)] * n + return zip_longest(fillvalue=fillvalue, *args) + + +def roundrobin(*iterables): + """Yields an item from each iterable, alternating between them. + + >>> list(roundrobin('ABC', 'D', 'EF')) + ['A', 'D', 'E', 'B', 'F', 'C'] + + This function produces the same output as :func:`interleave_longest`, but + may perform better for some inputs (in particular when the number of + iterables is small). + + """ + # Recipe credited to George Sakkis + pending = len(iterables) + nexts = cycle(iter(it).__next__ for it in iterables) + while pending: + try: + for next in nexts: + yield next() + except StopIteration: + pending -= 1 + nexts = cycle(islice(nexts, pending)) + + +def partition(pred, iterable): + """ + Returns a 2-tuple of iterables derived from the input iterable. + The first yields the items that have ``pred(item) == False``. + The second yields the items that have ``pred(item) == True``. + + >>> is_odd = lambda x: x % 2 != 0 + >>> iterable = range(10) + >>> even_items, odd_items = partition(is_odd, iterable) + >>> list(even_items), list(odd_items) + ([0, 2, 4, 6, 8], [1, 3, 5, 7, 9]) + + If *pred* is None, :func:`bool` is used. + + >>> iterable = [0, 1, False, True, '', ' '] + >>> false_items, true_items = partition(None, iterable) + >>> list(false_items), list(true_items) + ([0, False, ''], [1, True, ' ']) + + """ + if pred is None: + pred = bool + + evaluations = ((pred(x), x) for x in iterable) + t1, t2 = tee(evaluations) + return ( + (x for (cond, x) in t1 if not cond), + (x for (cond, x) in t2 if cond), + ) + + +def powerset(iterable): + """Yields all possible subsets of the iterable. + + >>> list(powerset([1, 2, 3])) + [(), (1,), (2,), (3,), (1, 2), (1, 3), (2, 3), (1, 2, 3)] + + :func:`powerset` will operate on iterables that aren't :class:`set` + instances, so repeated elements in the input will produce repeated elements + in the output. Use :func:`unique_everseen` on the input to avoid generating + duplicates: + + >>> seq = [1, 1, 0] + >>> list(powerset(seq)) + [(), (1,), (1,), (0,), (1, 1), (1, 0), (1, 0), (1, 1, 0)] + >>> from more_itertools import unique_everseen + >>> list(powerset(unique_everseen(seq))) + [(), (1,), (0,), (1, 0)] + + """ + s = list(iterable) + return chain.from_iterable(combinations(s, r) for r in range(len(s) + 1)) + + +def unique_everseen(iterable, key=None): + """ + Yield unique elements, preserving order. + + >>> list(unique_everseen('AAAABBBCCDAABBB')) + ['A', 'B', 'C', 'D'] + >>> list(unique_everseen('ABBCcAD', str.lower)) + ['A', 'B', 'C', 'D'] + + Sequences with a mix of hashable and unhashable items can be used. + The function will be slower (i.e., `O(n^2)`) for unhashable items. + + Remember that ``list`` objects are unhashable - you can use the *key* + parameter to transform the list to a tuple (which is hashable) to + avoid a slowdown. + + >>> iterable = ([1, 2], [2, 3], [1, 2]) + >>> list(unique_everseen(iterable)) # Slow + [[1, 2], [2, 3]] + >>> list(unique_everseen(iterable, key=tuple)) # Faster + [[1, 2], [2, 3]] + + Similary, you may want to convert unhashable ``set`` objects with + ``key=frozenset``. For ``dict`` objects, + ``key=lambda x: frozenset(x.items())`` can be used. + + """ + seenset = set() + seenset_add = seenset.add + seenlist = [] + seenlist_add = seenlist.append + use_key = key is not None + + for element in iterable: + k = key(element) if use_key else element + try: + if k not in seenset: + seenset_add(k) + yield element + except TypeError: + if k not in seenlist: + seenlist_add(k) + yield element + + +def unique_justseen(iterable, key=None): + """Yields elements in order, ignoring serial duplicates + + >>> list(unique_justseen('AAAABBBCCDAABBB')) + ['A', 'B', 'C', 'D', 'A', 'B'] + >>> list(unique_justseen('ABBCcAD', str.lower)) + ['A', 'B', 'C', 'A', 'D'] + + """ + return map(next, map(operator.itemgetter(1), groupby(iterable, key))) + + +def iter_except(func, exception, first=None): + """Yields results from a function repeatedly until an exception is raised. + + Converts a call-until-exception interface to an iterator interface. + Like ``iter(func, sentinel)``, but uses an exception instead of a sentinel + to end the loop. + + >>> l = [0, 1, 2] + >>> list(iter_except(l.pop, IndexError)) + [2, 1, 0] + + """ + try: + if first is not None: + yield first() + while 1: + yield func() + except exception: + pass + + +def first_true(iterable, default=None, pred=None): + """ + Returns the first true value in the iterable. + + If no true value is found, returns *default* + + If *pred* is not None, returns the first item for which + ``pred(item) == True`` . + + >>> first_true(range(10)) + 1 + >>> first_true(range(10), pred=lambda x: x > 5) + 6 + >>> first_true(range(10), default='missing', pred=lambda x: x > 9) + 'missing' + + """ + return next(filter(pred, iterable), default) + + +def random_product(*args, repeat=1): + """Draw an item at random from each of the input iterables. + + >>> random_product('abc', range(4), 'XYZ') # doctest:+SKIP + ('c', 3, 'Z') + + If *repeat* is provided as a keyword argument, that many items will be + drawn from each iterable. + + >>> random_product('abcd', range(4), repeat=2) # doctest:+SKIP + ('a', 2, 'd', 3) + + This equivalent to taking a random selection from + ``itertools.product(*args, **kwarg)``. + + """ + pools = [tuple(pool) for pool in args] * repeat + return tuple(choice(pool) for pool in pools) + + +def random_permutation(iterable, r=None): + """Return a random *r* length permutation of the elements in *iterable*. + + If *r* is not specified or is ``None``, then *r* defaults to the length of + *iterable*. + + >>> random_permutation(range(5)) # doctest:+SKIP + (3, 4, 0, 1, 2) + + This equivalent to taking a random selection from + ``itertools.permutations(iterable, r)``. + + """ + pool = tuple(iterable) + r = len(pool) if r is None else r + return tuple(sample(pool, r)) + + +def random_combination(iterable, r): + """Return a random *r* length subsequence of the elements in *iterable*. + + >>> random_combination(range(5), 3) # doctest:+SKIP + (2, 3, 4) + + This equivalent to taking a random selection from + ``itertools.combinations(iterable, r)``. + + """ + pool = tuple(iterable) + n = len(pool) + indices = sorted(sample(range(n), r)) + return tuple(pool[i] for i in indices) + + +def random_combination_with_replacement(iterable, r): + """Return a random *r* length subsequence of elements in *iterable*, + allowing individual elements to be repeated. + + >>> random_combination_with_replacement(range(3), 5) # doctest:+SKIP + (0, 0, 1, 2, 2) + + This equivalent to taking a random selection from + ``itertools.combinations_with_replacement(iterable, r)``. + + """ + pool = tuple(iterable) + n = len(pool) + indices = sorted(randrange(n) for i in range(r)) + return tuple(pool[i] for i in indices) + + +def nth_combination(iterable, r, index): + """Equivalent to ``list(combinations(iterable, r))[index]``. + + The subsequences of *iterable* that are of length *r* can be ordered + lexicographically. :func:`nth_combination` computes the subsequence at + sort position *index* directly, without computing the previous + subsequences. + + >>> nth_combination(range(5), 3, 5) + (0, 3, 4) + + ``ValueError`` will be raised If *r* is negative or greater than the length + of *iterable*. + ``IndexError`` will be raised if the given *index* is invalid. + """ + pool = tuple(iterable) + n = len(pool) + if (r < 0) or (r > n): + raise ValueError + + c = 1 + k = min(r, n - r) + for i in range(1, k + 1): + c = c * (n - k + i) // i + + if index < 0: + index += c + + if (index < 0) or (index >= c): + raise IndexError + + result = [] + while r: + c, n, r = c * r // n, n - 1, r - 1 + while index >= c: + index -= c + c, n = c * (n - r) // n, n - 1 + result.append(pool[-1 - n]) + + return tuple(result) + + +def prepend(value, iterator): + """Yield *value*, followed by the elements in *iterator*. + + >>> value = '0' + >>> iterator = ['1', '2', '3'] + >>> list(prepend(value, iterator)) + ['0', '1', '2', '3'] + + To prepend multiple values, see :func:`itertools.chain` + or :func:`value_chain`. + + """ + return chain([value], iterator) + + +def convolve(signal, kernel): + """Convolve the iterable *signal* with the iterable *kernel*. + + >>> signal = (1, 2, 3, 4, 5) + >>> kernel = [3, 2, 1] + >>> list(convolve(signal, kernel)) + [3, 8, 14, 20, 26, 14, 5] + + Note: the input arguments are not interchangeable, as the *kernel* + is immediately consumed and stored. + + """ + kernel = tuple(kernel)[::-1] + n = len(kernel) + window = deque([0], maxlen=n) * n + for x in chain(signal, repeat(0, n - 1)): + window.append(x) + yield sum(map(operator.mul, kernel, window)) diff --git a/venv/Lib/site-packages/setuptools/_vendor/ordered_set.py b/venv/Lib/site-packages/setuptools/_vendor/ordered_set.py new file mode 100644 index 0000000..1487600 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_vendor/ordered_set.py @@ -0,0 +1,488 @@ +""" +An OrderedSet is a custom MutableSet that remembers its order, so that every +entry has an index that can be looked up. + +Based on a recipe originally posted to ActiveState Recipes by Raymond Hettiger, +and released under the MIT license. +""" +import itertools as it +from collections import deque + +try: + # Python 3 + from collections.abc import MutableSet, Sequence +except ImportError: + # Python 2.7 + from collections import MutableSet, Sequence + +SLICE_ALL = slice(None) +__version__ = "3.1" + + +def is_iterable(obj): + """ + Are we being asked to look up a list of things, instead of a single thing? + We check for the `__iter__` attribute so that this can cover types that + don't have to be known by this module, such as NumPy arrays. + + Strings, however, should be considered as atomic values to look up, not + iterables. The same goes for tuples, since they are immutable and therefore + valid entries. + + We don't need to check for the Python 2 `unicode` type, because it doesn't + have an `__iter__` attribute anyway. + """ + return ( + hasattr(obj, "__iter__") + and not isinstance(obj, str) + and not isinstance(obj, tuple) + ) + + +class OrderedSet(MutableSet, Sequence): + """ + An OrderedSet is a custom MutableSet that remembers its order, so that + every entry has an index that can be looked up. + + Example: + >>> OrderedSet([1, 1, 2, 3, 2]) + OrderedSet([1, 2, 3]) + """ + + def __init__(self, iterable=None): + self.items = [] + self.map = {} + if iterable is not None: + self |= iterable + + def __len__(self): + """ + Returns the number of unique elements in the ordered set + + Example: + >>> len(OrderedSet([])) + 0 + >>> len(OrderedSet([1, 2])) + 2 + """ + return len(self.items) + + def __getitem__(self, index): + """ + Get the item at a given index. + + If `index` is a slice, you will get back that slice of items, as a + new OrderedSet. + + If `index` is a list or a similar iterable, you'll get a list of + items corresponding to those indices. This is similar to NumPy's + "fancy indexing". The result is not an OrderedSet because you may ask + for duplicate indices, and the number of elements returned should be + the number of elements asked for. + + Example: + >>> oset = OrderedSet([1, 2, 3]) + >>> oset[1] + 2 + """ + if isinstance(index, slice) and index == SLICE_ALL: + return self.copy() + elif is_iterable(index): + return [self.items[i] for i in index] + elif hasattr(index, "__index__") or isinstance(index, slice): + result = self.items[index] + if isinstance(result, list): + return self.__class__(result) + else: + return result + else: + raise TypeError("Don't know how to index an OrderedSet by %r" % index) + + def copy(self): + """ + Return a shallow copy of this object. + + Example: + >>> this = OrderedSet([1, 2, 3]) + >>> other = this.copy() + >>> this == other + True + >>> this is other + False + """ + return self.__class__(self) + + def __getstate__(self): + if len(self) == 0: + # The state can't be an empty list. + # We need to return a truthy value, or else __setstate__ won't be run. + # + # This could have been done more gracefully by always putting the state + # in a tuple, but this way is backwards- and forwards- compatible with + # previous versions of OrderedSet. + return (None,) + else: + return list(self) + + def __setstate__(self, state): + if state == (None,): + self.__init__([]) + else: + self.__init__(state) + + def __contains__(self, key): + """ + Test if the item is in this ordered set + + Example: + >>> 1 in OrderedSet([1, 3, 2]) + True + >>> 5 in OrderedSet([1, 3, 2]) + False + """ + return key in self.map + + def add(self, key): + """ + Add `key` as an item to this OrderedSet, then return its index. + + If `key` is already in the OrderedSet, return the index it already + had. + + Example: + >>> oset = OrderedSet() + >>> oset.append(3) + 0 + >>> print(oset) + OrderedSet([3]) + """ + if key not in self.map: + self.map[key] = len(self.items) + self.items.append(key) + return self.map[key] + + append = add + + def update(self, sequence): + """ + Update the set with the given iterable sequence, then return the index + of the last element inserted. + + Example: + >>> oset = OrderedSet([1, 2, 3]) + >>> oset.update([3, 1, 5, 1, 4]) + 4 + >>> print(oset) + OrderedSet([1, 2, 3, 5, 4]) + """ + item_index = None + try: + for item in sequence: + item_index = self.add(item) + except TypeError: + raise ValueError( + "Argument needs to be an iterable, got %s" % type(sequence) + ) + return item_index + + def index(self, key): + """ + Get the index of a given entry, raising an IndexError if it's not + present. + + `key` can be an iterable of entries that is not a string, in which case + this returns a list of indices. + + Example: + >>> oset = OrderedSet([1, 2, 3]) + >>> oset.index(2) + 1 + """ + if is_iterable(key): + return [self.index(subkey) for subkey in key] + return self.map[key] + + # Provide some compatibility with pd.Index + get_loc = index + get_indexer = index + + def pop(self): + """ + Remove and return the last element from the set. + + Raises KeyError if the set is empty. + + Example: + >>> oset = OrderedSet([1, 2, 3]) + >>> oset.pop() + 3 + """ + if not self.items: + raise KeyError("Set is empty") + + elem = self.items[-1] + del self.items[-1] + del self.map[elem] + return elem + + def discard(self, key): + """ + Remove an element. Do not raise an exception if absent. + + The MutableSet mixin uses this to implement the .remove() method, which + *does* raise an error when asked to remove a non-existent item. + + Example: + >>> oset = OrderedSet([1, 2, 3]) + >>> oset.discard(2) + >>> print(oset) + OrderedSet([1, 3]) + >>> oset.discard(2) + >>> print(oset) + OrderedSet([1, 3]) + """ + if key in self: + i = self.map[key] + del self.items[i] + del self.map[key] + for k, v in self.map.items(): + if v >= i: + self.map[k] = v - 1 + + def clear(self): + """ + Remove all items from this OrderedSet. + """ + del self.items[:] + self.map.clear() + + def __iter__(self): + """ + Example: + >>> list(iter(OrderedSet([1, 2, 3]))) + [1, 2, 3] + """ + return iter(self.items) + + def __reversed__(self): + """ + Example: + >>> list(reversed(OrderedSet([1, 2, 3]))) + [3, 2, 1] + """ + return reversed(self.items) + + def __repr__(self): + if not self: + return "%s()" % (self.__class__.__name__,) + return "%s(%r)" % (self.__class__.__name__, list(self)) + + def __eq__(self, other): + """ + Returns true if the containers have the same items. If `other` is a + Sequence, then order is checked, otherwise it is ignored. + + Example: + >>> oset = OrderedSet([1, 3, 2]) + >>> oset == [1, 3, 2] + True + >>> oset == [1, 2, 3] + False + >>> oset == [2, 3] + False + >>> oset == OrderedSet([3, 2, 1]) + False + """ + # In Python 2 deque is not a Sequence, so treat it as one for + # consistent behavior with Python 3. + if isinstance(other, (Sequence, deque)): + # Check that this OrderedSet contains the same elements, in the + # same order, as the other object. + return list(self) == list(other) + try: + other_as_set = set(other) + except TypeError: + # If `other` can't be converted into a set, it's not equal. + return False + else: + return set(self) == other_as_set + + def union(self, *sets): + """ + Combines all unique items. + Each items order is defined by its first appearance. + + Example: + >>> oset = OrderedSet.union(OrderedSet([3, 1, 4, 1, 5]), [1, 3], [2, 0]) + >>> print(oset) + OrderedSet([3, 1, 4, 5, 2, 0]) + >>> oset.union([8, 9]) + OrderedSet([3, 1, 4, 5, 2, 0, 8, 9]) + >>> oset | {10} + OrderedSet([3, 1, 4, 5, 2, 0, 10]) + """ + cls = self.__class__ if isinstance(self, OrderedSet) else OrderedSet + containers = map(list, it.chain([self], sets)) + items = it.chain.from_iterable(containers) + return cls(items) + + def __and__(self, other): + # the parent implementation of this is backwards + return self.intersection(other) + + def intersection(self, *sets): + """ + Returns elements in common between all sets. Order is defined only + by the first set. + + Example: + >>> oset = OrderedSet.intersection(OrderedSet([0, 1, 2, 3]), [1, 2, 3]) + >>> print(oset) + OrderedSet([1, 2, 3]) + >>> oset.intersection([2, 4, 5], [1, 2, 3, 4]) + OrderedSet([2]) + >>> oset.intersection() + OrderedSet([1, 2, 3]) + """ + cls = self.__class__ if isinstance(self, OrderedSet) else OrderedSet + if sets: + common = set.intersection(*map(set, sets)) + items = (item for item in self if item in common) + else: + items = self + return cls(items) + + def difference(self, *sets): + """ + Returns all elements that are in this set but not the others. + + Example: + >>> OrderedSet([1, 2, 3]).difference(OrderedSet([2])) + OrderedSet([1, 3]) + >>> OrderedSet([1, 2, 3]).difference(OrderedSet([2]), OrderedSet([3])) + OrderedSet([1]) + >>> OrderedSet([1, 2, 3]) - OrderedSet([2]) + OrderedSet([1, 3]) + >>> OrderedSet([1, 2, 3]).difference() + OrderedSet([1, 2, 3]) + """ + cls = self.__class__ + if sets: + other = set.union(*map(set, sets)) + items = (item for item in self if item not in other) + else: + items = self + return cls(items) + + def issubset(self, other): + """ + Report whether another set contains this set. + + Example: + >>> OrderedSet([1, 2, 3]).issubset({1, 2}) + False + >>> OrderedSet([1, 2, 3]).issubset({1, 2, 3, 4}) + True + >>> OrderedSet([1, 2, 3]).issubset({1, 4, 3, 5}) + False + """ + if len(self) > len(other): # Fast check for obvious cases + return False + return all(item in other for item in self) + + def issuperset(self, other): + """ + Report whether this set contains another set. + + Example: + >>> OrderedSet([1, 2]).issuperset([1, 2, 3]) + False + >>> OrderedSet([1, 2, 3, 4]).issuperset({1, 2, 3}) + True + >>> OrderedSet([1, 4, 3, 5]).issuperset({1, 2, 3}) + False + """ + if len(self) < len(other): # Fast check for obvious cases + return False + return all(item in self for item in other) + + def symmetric_difference(self, other): + """ + Return the symmetric difference of two OrderedSets as a new set. + That is, the new set will contain all elements that are in exactly + one of the sets. + + Their order will be preserved, with elements from `self` preceding + elements from `other`. + + Example: + >>> this = OrderedSet([1, 4, 3, 5, 7]) + >>> other = OrderedSet([9, 7, 1, 3, 2]) + >>> this.symmetric_difference(other) + OrderedSet([4, 5, 9, 2]) + """ + cls = self.__class__ if isinstance(self, OrderedSet) else OrderedSet + diff1 = cls(self).difference(other) + diff2 = cls(other).difference(self) + return diff1.union(diff2) + + def _update_items(self, items): + """ + Replace the 'items' list of this OrderedSet with a new one, updating + self.map accordingly. + """ + self.items = items + self.map = {item: idx for (idx, item) in enumerate(items)} + + def difference_update(self, *sets): + """ + Update this OrderedSet to remove items from one or more other sets. + + Example: + >>> this = OrderedSet([1, 2, 3]) + >>> this.difference_update(OrderedSet([2, 4])) + >>> print(this) + OrderedSet([1, 3]) + + >>> this = OrderedSet([1, 2, 3, 4, 5]) + >>> this.difference_update(OrderedSet([2, 4]), OrderedSet([1, 4, 6])) + >>> print(this) + OrderedSet([3, 5]) + """ + items_to_remove = set() + for other in sets: + items_to_remove |= set(other) + self._update_items([item for item in self.items if item not in items_to_remove]) + + def intersection_update(self, other): + """ + Update this OrderedSet to keep only items in another set, preserving + their order in this set. + + Example: + >>> this = OrderedSet([1, 4, 3, 5, 7]) + >>> other = OrderedSet([9, 7, 1, 3, 2]) + >>> this.intersection_update(other) + >>> print(this) + OrderedSet([1, 3, 7]) + """ + other = set(other) + self._update_items([item for item in self.items if item in other]) + + def symmetric_difference_update(self, other): + """ + Update this OrderedSet to remove items from another set, then + add items from the other set that were not present in this set. + + Example: + >>> this = OrderedSet([1, 4, 3, 5, 7]) + >>> other = OrderedSet([9, 7, 1, 3, 2]) + >>> this.symmetric_difference_update(other) + >>> print(this) + OrderedSet([4, 5, 9, 2]) + """ + items_to_add = [item for item in other if item not in self] + items_to_remove = set(other) + self._update_items( + [item for item in self.items if item not in items_to_remove] + items_to_add + ) diff --git a/venv/Lib/site-packages/setuptools/_vendor/packaging/__about__.py b/venv/Lib/site-packages/setuptools/_vendor/packaging/__about__.py new file mode 100644 index 0000000..3551bc2 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_vendor/packaging/__about__.py @@ -0,0 +1,26 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +__all__ = [ + "__title__", + "__summary__", + "__uri__", + "__version__", + "__author__", + "__email__", + "__license__", + "__copyright__", +] + +__title__ = "packaging" +__summary__ = "Core utilities for Python packages" +__uri__ = "https://github.com/pypa/packaging" + +__version__ = "21.3" + +__author__ = "Donald Stufft and individual contributors" +__email__ = "donald@stufft.io" + +__license__ = "BSD-2-Clause or Apache-2.0" +__copyright__ = "2014-2019 %s" % __author__ diff --git a/venv/Lib/site-packages/setuptools/_vendor/packaging/__init__.py b/venv/Lib/site-packages/setuptools/_vendor/packaging/__init__.py new file mode 100644 index 0000000..3c50c5d --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_vendor/packaging/__init__.py @@ -0,0 +1,25 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +from .__about__ import ( + __author__, + __copyright__, + __email__, + __license__, + __summary__, + __title__, + __uri__, + __version__, +) + +__all__ = [ + "__title__", + "__summary__", + "__uri__", + "__version__", + "__author__", + "__email__", + "__license__", + "__copyright__", +] diff --git a/venv/Lib/site-packages/setuptools/_vendor/packaging/__pycache__/__about__.cpython-39.pyc b/venv/Lib/site-packages/setuptools/_vendor/packaging/__pycache__/__about__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0cff384d6d896a0e7c8eb3d39e14cb4dd280a1c3 GIT binary patch literal 590 zcmYk2&5qMB5XX}?ZPS)Yd*Z+ag9K6!>DO{$h0reT5h0|)C5mLZv6~ni+ww|saM{D6XUG}c;ugEtiMMye=?g*A~@fkzC3*IMbWQN{D0srx`k_3fGVQVk2sHL zoX516_h>)w(Qg%DPy}U`XIfv57Gr!-II6wUAD=#f_TdijBy9;YnE*mtM1We zwSJWWUZWTG!+ad9AOhAjF_>(E<)$By1PlU(0i%Ev@G~;gkO%y(wl~FR3kDWMN@9yU zt#`zc;=L+~C_b@97nu-?0luPR+hF_ z&Lki?Fdy?De$IamoleIn*8Abn{3k=`D~bKeqqvUGokw)2%LI}c&SZ{rS>QsJxRe7t zkV8C_6|Q8B>kRd%%Re$a>WW9yl;3eKYU<4xfCj(N7GN_4Xth~e-Y|P((a5;}l8f zI>hvyBlY)e+acR=|C3TG6>-N;WDk-%;rHeCf;_vp1EES$M{bO{qn?s`-BLlGm^8$2 zGYiVl_KkJ3)q*iGI}P-8b><~;%m?GO7LLG@sZLvxjI`&fCjeaWxZ#OeZ|X~_yCB$A Ky27QSjwgR8sdr@n literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/_vendor/packaging/__pycache__/_manylinux.cpython-39.pyc b/venv/Lib/site-packages/setuptools/_vendor/packaging/__pycache__/_manylinux.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..51942c6bb09f4ff7d458401dac025c04d4d45b3d GIT binary patch literal 7294 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/_vendor/packaging/__pycache__/_musllinux.cpython-39.pyc b/venv/Lib/site-packages/setuptools/_vendor/packaging/__pycache__/_musllinux.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3834478a26b0f8bd5bf8dd35fa0eaf0cd3a5210d GIT binary patch literal 4609 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 aq|eRG|1XB~LwgFQWgO}~I?`_s5Bxtj`ZrDh literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/_vendor/packaging/__pycache__/requirements.cpython-39.pyc b/venv/Lib/site-packages/setuptools/_vendor/packaging/__pycache__/requirements.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0ec0b8b98db5425cb008e65a61012bace7922300 GIT binary patch literal 3980 zcmZ`+-BTOa72mtNS}j5dA;1_ri8qd8TL}=7*ok914l9I-O++{U_aFYo1fk{+?V($XN{LJUYXMNnR|w3gQ0zP;5^gZSAl1G z_*vk?J^VG`*&col_(%_b9eA#Xp9enL!!PjBAP?IY`5B()7xx)IGo{_s+#=5?PH~^9 zwcp@x1Y^*9lfU84@LW*XXTdn=S$=`fPHFBOpTYds`3z};ev7}#E&dka{Opt#Oh9*@ z=lFEvZLT%m!Fczkwy(RFz&rUX-erD?UoL6xd)UK!%IbSvtHDSx8Jzfw5lq3_`>_8S ze;@YGVZ0A(%)P>|9DER*45puI&luDA7{7vjo`U2mzY59e0mrB^ zGl2u2IymjkfURrASAV7mtP~AtF4yBk+Nm@VpZc%@YRv|RPdpRZM=wc?8hTwr&j%Y4VLJzj6~T7A3DVdfak z9--KBjm|Upk=+H1I1j)z$|P407&1x6`3+fEioWri^`OeX-mMEB@+j$il5y~rBB$P! zIpSF8JoIB{yR{nyGtO?zMeM})Tf5BwI@?@0Ny}L)uQ`|JugobUm7*za&x`z!d!EdA zUf2qDn}laQ@9SN^*^{I_FKE>~??+8cW1|WjHWsgLZPFTBeiZrfR;k^-Eg#-fGv|v%68-uRY+w?8EzG(@z^bR|o=|)=n<@H`eR;^fI%F3QS@Dp~9I|VNY@uV!dUMjGeRon{{?_^G zO=;|krnKN-;m5b(#7v`AkJgo+rR@g|zlK|tL!R&-dNEvBqZsOcgp-pNF=DEadwN4_ z+bTTuiqwisTmbh+L$X-1rew+S4T)2bNc(!z5AOy3jRjEu#?Ztp079)FE-x%dhg1vN zK=u$1(;A{duZSGYRvsuGVTz=clv$c4<^ZG>s_=ZlxCx;$PIsDUdvqd(q5n~zMxtXO zhKv&wkaE=PCx{nQ9>|en23#io-!AT8vf4$*c=Y90HBi6!3{VRg@pXW~sOM&&2gdh0 zy#Y^6HwD`Io~c@Ix>k=G3NnzTRfY`9;lb4SyGne=A54k4j0*L>WT%c`8epi)J1?fI(~7X4dw$S- zJiFZzA*WnCN@iuOyMca2>asAPfP1HcBrSn-5mAjoqyN#9Od+|55f>1pom`?Fus!yS zJ<;!K(I=*s=#M{V+7p9mop%x=fNalbm^1=?N+XYdhYJUt`cC`7+-HAaceO9H05g7X zM49gIyf#lUV(n?3h2OOJM`AaI4l;yeC3DYg3uqvBr#5Ax5nNZ&z}LNc0+frsZ6 zcmde>w@ldd8|iB1ctA;$u5|KU*K;9S!toR5?9Y@|9pmg(N1EI9Chv^(+~&ZojtY>@ z$N=lAQ=CAYm4CCjR4uQRD;shcF%t7`4H0QrQw2#H%~nksVZ0;G67MwtX`%Ww>-S_z zO_4UpE@s8G`zYu#0}j2cE{QrafCX$qGf-|q2KNA#bR9?iD{>$4}^L}yb z;Qb?aFmNOcW&s{df%#73o)yFOsz;)RZJp?E{>2tK53|9W@m3IuOsdw+#cy}H^9 zLC{qw+G3InoFFho;3R<+0v{7tC9p=|sCVdM>d|@^g1ZGY<@a7A&6UClsbAe z3#X+DnC&LgoCUFQl5fmbpR)E$siKSgyUi-LI*<6u!yxVRI9)q`hvszmGw7enhY9F(f*GkoL zMOxMFZ)$OMWu=5xv%IpjxVpSrk$MT0X>GHzxUpHGl$}td(0bb4*LK zQd%j?RQdCbYDpTK)g=PUa#%6ez2&9#4QX`=G=_p2Xo^>v{;XWRxw>A4u{)L3YI(5) zJO}1FR`k$aUb-}YOfQ%3lor2`!+rT`r7W|3Vx?610v$!4Twg0M${ZZFMzye1qgMY| zSxNJ~{(HTQJ1A|eQWLH^a#`qGDOGNHJzfq6@&@QJI`S=Vppc6zrmp|TG$vRM XvYeh{CbOQKh6z2)*C+I>kum-Y10DLq literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/_vendor/packaging/__pycache__/specifiers.cpython-39.pyc b/venv/Lib/site-packages/setuptools/_vendor/packaging/__pycache__/specifiers.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fa7fb12d89aa8aa716a262c77787e21acfc7c993 GIT binary patch literal 21521 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/_vendor/packaging/__pycache__/tags.cpython-39.pyc b/venv/Lib/site-packages/setuptools/_vendor/packaging/__pycache__/tags.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ce2ded63be0547c63cfaf0119f4d3afffce222c0 GIT binary patch literal 12252 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 None: + def unpack(fmt: str) -> int: + try: + data = file.read(struct.calcsize(fmt)) + result: Tuple[int, ...] = struct.unpack(fmt, data) + except struct.error: + raise _ELFFileHeader._InvalidELFFileHeader() + return result[0] + + self.e_ident_magic = unpack(">I") + if self.e_ident_magic != self.ELF_MAGIC_NUMBER: + raise _ELFFileHeader._InvalidELFFileHeader() + self.e_ident_class = unpack("B") + if self.e_ident_class not in {self.ELFCLASS32, self.ELFCLASS64}: + raise _ELFFileHeader._InvalidELFFileHeader() + self.e_ident_data = unpack("B") + if self.e_ident_data not in {self.ELFDATA2LSB, self.ELFDATA2MSB}: + raise _ELFFileHeader._InvalidELFFileHeader() + self.e_ident_version = unpack("B") + self.e_ident_osabi = unpack("B") + self.e_ident_abiversion = unpack("B") + self.e_ident_pad = file.read(7) + format_h = "H" + format_i = "I" + format_q = "Q" + format_p = format_i if self.e_ident_class == self.ELFCLASS32 else format_q + self.e_type = unpack(format_h) + self.e_machine = unpack(format_h) + self.e_version = unpack(format_i) + self.e_entry = unpack(format_p) + self.e_phoff = unpack(format_p) + self.e_shoff = unpack(format_p) + self.e_flags = unpack(format_i) + self.e_ehsize = unpack(format_h) + self.e_phentsize = unpack(format_h) + self.e_phnum = unpack(format_h) + self.e_shentsize = unpack(format_h) + self.e_shnum = unpack(format_h) + self.e_shstrndx = unpack(format_h) + + +def _get_elf_header() -> Optional[_ELFFileHeader]: + try: + with open(sys.executable, "rb") as f: + elf_header = _ELFFileHeader(f) + except (OSError, TypeError, _ELFFileHeader._InvalidELFFileHeader): + return None + return elf_header + + +def _is_linux_armhf() -> bool: + # hard-float ABI can be detected from the ELF header of the running + # process + # https://static.docs.arm.com/ihi0044/g/aaelf32.pdf + elf_header = _get_elf_header() + if elf_header is None: + return False + result = elf_header.e_ident_class == elf_header.ELFCLASS32 + result &= elf_header.e_ident_data == elf_header.ELFDATA2LSB + result &= elf_header.e_machine == elf_header.EM_ARM + result &= ( + elf_header.e_flags & elf_header.EF_ARM_ABIMASK + ) == elf_header.EF_ARM_ABI_VER5 + result &= ( + elf_header.e_flags & elf_header.EF_ARM_ABI_FLOAT_HARD + ) == elf_header.EF_ARM_ABI_FLOAT_HARD + return result + + +def _is_linux_i686() -> bool: + elf_header = _get_elf_header() + if elf_header is None: + return False + result = elf_header.e_ident_class == elf_header.ELFCLASS32 + result &= elf_header.e_ident_data == elf_header.ELFDATA2LSB + result &= elf_header.e_machine == elf_header.EM_386 + return result + + +def _have_compatible_abi(arch: str) -> bool: + if arch == "armv7l": + return _is_linux_armhf() + if arch == "i686": + return _is_linux_i686() + return arch in {"x86_64", "aarch64", "ppc64", "ppc64le", "s390x"} + + +# If glibc ever changes its major version, we need to know what the last +# minor version was, so we can build the complete list of all versions. +# For now, guess what the highest minor version might be, assume it will +# be 50 for testing. Once this actually happens, update the dictionary +# with the actual value. +_LAST_GLIBC_MINOR: Dict[int, int] = collections.defaultdict(lambda: 50) + + +class _GLibCVersion(NamedTuple): + major: int + minor: int + + +def _glibc_version_string_confstr() -> Optional[str]: + """ + Primary implementation of glibc_version_string using os.confstr. + """ + # os.confstr is quite a bit faster than ctypes.DLL. It's also less likely + # to be broken or missing. This strategy is used in the standard library + # platform module. + # https://github.com/python/cpython/blob/fcf1d003bf4f0100c/Lib/platform.py#L175-L183 + try: + # os.confstr("CS_GNU_LIBC_VERSION") returns a string like "glibc 2.17". + version_string = os.confstr("CS_GNU_LIBC_VERSION") + assert version_string is not None + _, version = version_string.split() + except (AssertionError, AttributeError, OSError, ValueError): + # os.confstr() or CS_GNU_LIBC_VERSION not available (or a bad value)... + return None + return version + + +def _glibc_version_string_ctypes() -> Optional[str]: + """ + Fallback implementation of glibc_version_string using ctypes. + """ + try: + import ctypes + except ImportError: + return None + + # ctypes.CDLL(None) internally calls dlopen(NULL), and as the dlopen + # manpage says, "If filename is NULL, then the returned handle is for the + # main program". This way we can let the linker do the work to figure out + # which libc our process is actually using. + # + # We must also handle the special case where the executable is not a + # dynamically linked executable. This can occur when using musl libc, + # for example. In this situation, dlopen() will error, leading to an + # OSError. Interestingly, at least in the case of musl, there is no + # errno set on the OSError. The single string argument used to construct + # OSError comes from libc itself and is therefore not portable to + # hard code here. In any case, failure to call dlopen() means we + # can proceed, so we bail on our attempt. + try: + process_namespace = ctypes.CDLL(None) + except OSError: + return None + + try: + gnu_get_libc_version = process_namespace.gnu_get_libc_version + except AttributeError: + # Symbol doesn't exist -> therefore, we are not linked to + # glibc. + return None + + # Call gnu_get_libc_version, which returns a string like "2.5" + gnu_get_libc_version.restype = ctypes.c_char_p + version_str: str = gnu_get_libc_version() + # py2 / py3 compatibility: + if not isinstance(version_str, str): + version_str = version_str.decode("ascii") + + return version_str + + +def _glibc_version_string() -> Optional[str]: + """Returns glibc version string, or None if not using glibc.""" + return _glibc_version_string_confstr() or _glibc_version_string_ctypes() + + +def _parse_glibc_version(version_str: str) -> Tuple[int, int]: + """Parse glibc version. + + We use a regexp instead of str.split because we want to discard any + random junk that might come after the minor version -- this might happen + in patched/forked versions of glibc (e.g. Linaro's version of glibc + uses version strings like "2.20-2014.11"). See gh-3588. + """ + m = re.match(r"(?P[0-9]+)\.(?P[0-9]+)", version_str) + if not m: + warnings.warn( + "Expected glibc version with 2 components major.minor," + " got: %s" % version_str, + RuntimeWarning, + ) + return -1, -1 + return int(m.group("major")), int(m.group("minor")) + + +@functools.lru_cache() +def _get_glibc_version() -> Tuple[int, int]: + version_str = _glibc_version_string() + if version_str is None: + return (-1, -1) + return _parse_glibc_version(version_str) + + +# From PEP 513, PEP 600 +def _is_compatible(name: str, arch: str, version: _GLibCVersion) -> bool: + sys_glibc = _get_glibc_version() + if sys_glibc < version: + return False + # Check for presence of _manylinux module. + try: + import _manylinux # noqa + except ImportError: + return True + if hasattr(_manylinux, "manylinux_compatible"): + result = _manylinux.manylinux_compatible(version[0], version[1], arch) + if result is not None: + return bool(result) + return True + if version == _GLibCVersion(2, 5): + if hasattr(_manylinux, "manylinux1_compatible"): + return bool(_manylinux.manylinux1_compatible) + if version == _GLibCVersion(2, 12): + if hasattr(_manylinux, "manylinux2010_compatible"): + return bool(_manylinux.manylinux2010_compatible) + if version == _GLibCVersion(2, 17): + if hasattr(_manylinux, "manylinux2014_compatible"): + return bool(_manylinux.manylinux2014_compatible) + return True + + +_LEGACY_MANYLINUX_MAP = { + # CentOS 7 w/ glibc 2.17 (PEP 599) + (2, 17): "manylinux2014", + # CentOS 6 w/ glibc 2.12 (PEP 571) + (2, 12): "manylinux2010", + # CentOS 5 w/ glibc 2.5 (PEP 513) + (2, 5): "manylinux1", +} + + +def platform_tags(linux: str, arch: str) -> Iterator[str]: + if not _have_compatible_abi(arch): + return + # Oldest glibc to be supported regardless of architecture is (2, 17). + too_old_glibc2 = _GLibCVersion(2, 16) + if arch in {"x86_64", "i686"}: + # On x86/i686 also oldest glibc to be supported is (2, 5). + too_old_glibc2 = _GLibCVersion(2, 4) + current_glibc = _GLibCVersion(*_get_glibc_version()) + glibc_max_list = [current_glibc] + # We can assume compatibility across glibc major versions. + # https://sourceware.org/bugzilla/show_bug.cgi?id=24636 + # + # Build a list of maximum glibc versions so that we can + # output the canonical list of all glibc from current_glibc + # down to too_old_glibc2, including all intermediary versions. + for glibc_major in range(current_glibc.major - 1, 1, -1): + glibc_minor = _LAST_GLIBC_MINOR[glibc_major] + glibc_max_list.append(_GLibCVersion(glibc_major, glibc_minor)) + for glibc_max in glibc_max_list: + if glibc_max.major == too_old_glibc2.major: + min_minor = too_old_glibc2.minor + else: + # For other glibc major versions oldest supported is (x, 0). + min_minor = -1 + for glibc_minor in range(glibc_max.minor, min_minor, -1): + glibc_version = _GLibCVersion(glibc_max.major, glibc_minor) + tag = "manylinux_{}_{}".format(*glibc_version) + if _is_compatible(tag, arch, glibc_version): + yield linux.replace("linux", tag) + # Handle the legacy manylinux1, manylinux2010, manylinux2014 tags. + if glibc_version in _LEGACY_MANYLINUX_MAP: + legacy_tag = _LEGACY_MANYLINUX_MAP[glibc_version] + if _is_compatible(legacy_tag, arch, glibc_version): + yield linux.replace("linux", legacy_tag) diff --git a/venv/Lib/site-packages/setuptools/_vendor/packaging/_musllinux.py b/venv/Lib/site-packages/setuptools/_vendor/packaging/_musllinux.py new file mode 100644 index 0000000..8ac3059 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_vendor/packaging/_musllinux.py @@ -0,0 +1,136 @@ +"""PEP 656 support. + +This module implements logic to detect if the currently running Python is +linked against musl, and what musl version is used. +""" + +import contextlib +import functools +import operator +import os +import re +import struct +import subprocess +import sys +from typing import IO, Iterator, NamedTuple, Optional, Tuple + + +def _read_unpacked(f: IO[bytes], fmt: str) -> Tuple[int, ...]: + return struct.unpack(fmt, f.read(struct.calcsize(fmt))) + + +def _parse_ld_musl_from_elf(f: IO[bytes]) -> Optional[str]: + """Detect musl libc location by parsing the Python executable. + + Based on: https://gist.github.com/lyssdod/f51579ae8d93c8657a5564aefc2ffbca + ELF header: https://refspecs.linuxfoundation.org/elf/gabi4+/ch4.eheader.html + """ + f.seek(0) + try: + ident = _read_unpacked(f, "16B") + except struct.error: + return None + if ident[:4] != tuple(b"\x7fELF"): # Invalid magic, not ELF. + return None + f.seek(struct.calcsize("HHI"), 1) # Skip file type, machine, and version. + + try: + # e_fmt: Format for program header. + # p_fmt: Format for section header. + # p_idx: Indexes to find p_type, p_offset, and p_filesz. + e_fmt, p_fmt, p_idx = { + 1: ("IIIIHHH", "IIIIIIII", (0, 1, 4)), # 32-bit. + 2: ("QQQIHHH", "IIQQQQQQ", (0, 2, 5)), # 64-bit. + }[ident[4]] + except KeyError: + return None + else: + p_get = operator.itemgetter(*p_idx) + + # Find the interpreter section and return its content. + try: + _, e_phoff, _, _, _, e_phentsize, e_phnum = _read_unpacked(f, e_fmt) + except struct.error: + return None + for i in range(e_phnum + 1): + f.seek(e_phoff + e_phentsize * i) + try: + p_type, p_offset, p_filesz = p_get(_read_unpacked(f, p_fmt)) + except struct.error: + return None + if p_type != 3: # Not PT_INTERP. + continue + f.seek(p_offset) + interpreter = os.fsdecode(f.read(p_filesz)).strip("\0") + if "musl" not in interpreter: + return None + return interpreter + return None + + +class _MuslVersion(NamedTuple): + major: int + minor: int + + +def _parse_musl_version(output: str) -> Optional[_MuslVersion]: + lines = [n for n in (n.strip() for n in output.splitlines()) if n] + if len(lines) < 2 or lines[0][:4] != "musl": + return None + m = re.match(r"Version (\d+)\.(\d+)", lines[1]) + if not m: + return None + return _MuslVersion(major=int(m.group(1)), minor=int(m.group(2))) + + +@functools.lru_cache() +def _get_musl_version(executable: str) -> Optional[_MuslVersion]: + """Detect currently-running musl runtime version. + + This is done by checking the specified executable's dynamic linking + information, and invoking the loader to parse its output for a version + string. If the loader is musl, the output would be something like:: + + musl libc (x86_64) + Version 1.2.2 + Dynamic Program Loader + """ + with contextlib.ExitStack() as stack: + try: + f = stack.enter_context(open(executable, "rb")) + except OSError: + return None + ld = _parse_ld_musl_from_elf(f) + if not ld: + return None + proc = subprocess.run([ld], stderr=subprocess.PIPE, universal_newlines=True) + return _parse_musl_version(proc.stderr) + + +def platform_tags(arch: str) -> Iterator[str]: + """Generate musllinux tags compatible to the current platform. + + :param arch: Should be the part of platform tag after the ``linux_`` + prefix, e.g. ``x86_64``. The ``linux_`` prefix is assumed as a + prerequisite for the current platform to be musllinux-compatible. + + :returns: An iterator of compatible musllinux tags. + """ + sys_musl = _get_musl_version(sys.executable) + if sys_musl is None: # Python not dynamically linked against musl. + return + for minor in range(sys_musl.minor, -1, -1): + yield f"musllinux_{sys_musl.major}_{minor}_{arch}" + + +if __name__ == "__main__": # pragma: no cover + import sysconfig + + plat = sysconfig.get_platform() + assert plat.startswith("linux-"), "not linux" + + print("plat:", plat) + print("musl:", _get_musl_version(sys.executable)) + print("tags:", end=" ") + for t in platform_tags(re.sub(r"[.-]", "_", plat.split("-", 1)[-1])): + print(t, end="\n ") diff --git a/venv/Lib/site-packages/setuptools/_vendor/packaging/_structures.py b/venv/Lib/site-packages/setuptools/_vendor/packaging/_structures.py new file mode 100644 index 0000000..90a6465 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_vendor/packaging/_structures.py @@ -0,0 +1,61 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + + +class InfinityType: + def __repr__(self) -> str: + return "Infinity" + + def __hash__(self) -> int: + return hash(repr(self)) + + def __lt__(self, other: object) -> bool: + return False + + def __le__(self, other: object) -> bool: + return False + + def __eq__(self, other: object) -> bool: + return isinstance(other, self.__class__) + + def __gt__(self, other: object) -> bool: + return True + + def __ge__(self, other: object) -> bool: + return True + + def __neg__(self: object) -> "NegativeInfinityType": + return NegativeInfinity + + +Infinity = InfinityType() + + +class NegativeInfinityType: + def __repr__(self) -> str: + return "-Infinity" + + def __hash__(self) -> int: + return hash(repr(self)) + + def __lt__(self, other: object) -> bool: + return True + + def __le__(self, other: object) -> bool: + return True + + def __eq__(self, other: object) -> bool: + return isinstance(other, self.__class__) + + def __gt__(self, other: object) -> bool: + return False + + def __ge__(self, other: object) -> bool: + return False + + def __neg__(self: object) -> InfinityType: + return Infinity + + +NegativeInfinity = NegativeInfinityType() diff --git a/venv/Lib/site-packages/setuptools/_vendor/packaging/markers.py b/venv/Lib/site-packages/setuptools/_vendor/packaging/markers.py new file mode 100644 index 0000000..eb0541b --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_vendor/packaging/markers.py @@ -0,0 +1,304 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +import operator +import os +import platform +import sys +from typing import Any, Callable, Dict, List, Optional, Tuple, Union + +from setuptools.extern.pyparsing import ( # noqa: N817 + Forward, + Group, + Literal as L, + ParseException, + ParseResults, + QuotedString, + ZeroOrMore, + stringEnd, + stringStart, +) + +from .specifiers import InvalidSpecifier, Specifier + +__all__ = [ + "InvalidMarker", + "UndefinedComparison", + "UndefinedEnvironmentName", + "Marker", + "default_environment", +] + +Operator = Callable[[str, str], bool] + + +class InvalidMarker(ValueError): + """ + An invalid marker was found, users should refer to PEP 508. + """ + + +class UndefinedComparison(ValueError): + """ + An invalid operation was attempted on a value that doesn't support it. + """ + + +class UndefinedEnvironmentName(ValueError): + """ + A name was attempted to be used that does not exist inside of the + environment. + """ + + +class Node: + def __init__(self, value: Any) -> None: + self.value = value + + def __str__(self) -> str: + return str(self.value) + + def __repr__(self) -> str: + return f"<{self.__class__.__name__}('{self}')>" + + def serialize(self) -> str: + raise NotImplementedError + + +class Variable(Node): + def serialize(self) -> str: + return str(self) + + +class Value(Node): + def serialize(self) -> str: + return f'"{self}"' + + +class Op(Node): + def serialize(self) -> str: + return str(self) + + +VARIABLE = ( + L("implementation_version") + | L("platform_python_implementation") + | L("implementation_name") + | L("python_full_version") + | L("platform_release") + | L("platform_version") + | L("platform_machine") + | L("platform_system") + | L("python_version") + | L("sys_platform") + | L("os_name") + | L("os.name") # PEP-345 + | L("sys.platform") # PEP-345 + | L("platform.version") # PEP-345 + | L("platform.machine") # PEP-345 + | L("platform.python_implementation") # PEP-345 + | L("python_implementation") # undocumented setuptools legacy + | L("extra") # PEP-508 +) +ALIASES = { + "os.name": "os_name", + "sys.platform": "sys_platform", + "platform.version": "platform_version", + "platform.machine": "platform_machine", + "platform.python_implementation": "platform_python_implementation", + "python_implementation": "platform_python_implementation", +} +VARIABLE.setParseAction(lambda s, l, t: Variable(ALIASES.get(t[0], t[0]))) + +VERSION_CMP = ( + L("===") | L("==") | L(">=") | L("<=") | L("!=") | L("~=") | L(">") | L("<") +) + +MARKER_OP = VERSION_CMP | L("not in") | L("in") +MARKER_OP.setParseAction(lambda s, l, t: Op(t[0])) + +MARKER_VALUE = QuotedString("'") | QuotedString('"') +MARKER_VALUE.setParseAction(lambda s, l, t: Value(t[0])) + +BOOLOP = L("and") | L("or") + +MARKER_VAR = VARIABLE | MARKER_VALUE + +MARKER_ITEM = Group(MARKER_VAR + MARKER_OP + MARKER_VAR) +MARKER_ITEM.setParseAction(lambda s, l, t: tuple(t[0])) + +LPAREN = L("(").suppress() +RPAREN = L(")").suppress() + +MARKER_EXPR = Forward() +MARKER_ATOM = MARKER_ITEM | Group(LPAREN + MARKER_EXPR + RPAREN) +MARKER_EXPR << MARKER_ATOM + ZeroOrMore(BOOLOP + MARKER_EXPR) + +MARKER = stringStart + MARKER_EXPR + stringEnd + + +def _coerce_parse_result(results: Union[ParseResults, List[Any]]) -> List[Any]: + if isinstance(results, ParseResults): + return [_coerce_parse_result(i) for i in results] + else: + return results + + +def _format_marker( + marker: Union[List[str], Tuple[Node, ...], str], first: Optional[bool] = True +) -> str: + + assert isinstance(marker, (list, tuple, str)) + + # Sometimes we have a structure like [[...]] which is a single item list + # where the single item is itself it's own list. In that case we want skip + # the rest of this function so that we don't get extraneous () on the + # outside. + if ( + isinstance(marker, list) + and len(marker) == 1 + and isinstance(marker[0], (list, tuple)) + ): + return _format_marker(marker[0]) + + if isinstance(marker, list): + inner = (_format_marker(m, first=False) for m in marker) + if first: + return " ".join(inner) + else: + return "(" + " ".join(inner) + ")" + elif isinstance(marker, tuple): + return " ".join([m.serialize() for m in marker]) + else: + return marker + + +_operators: Dict[str, Operator] = { + "in": lambda lhs, rhs: lhs in rhs, + "not in": lambda lhs, rhs: lhs not in rhs, + "<": operator.lt, + "<=": operator.le, + "==": operator.eq, + "!=": operator.ne, + ">=": operator.ge, + ">": operator.gt, +} + + +def _eval_op(lhs: str, op: Op, rhs: str) -> bool: + try: + spec = Specifier("".join([op.serialize(), rhs])) + except InvalidSpecifier: + pass + else: + return spec.contains(lhs) + + oper: Optional[Operator] = _operators.get(op.serialize()) + if oper is None: + raise UndefinedComparison(f"Undefined {op!r} on {lhs!r} and {rhs!r}.") + + return oper(lhs, rhs) + + +class Undefined: + pass + + +_undefined = Undefined() + + +def _get_env(environment: Dict[str, str], name: str) -> str: + value: Union[str, Undefined] = environment.get(name, _undefined) + + if isinstance(value, Undefined): + raise UndefinedEnvironmentName( + f"{name!r} does not exist in evaluation environment." + ) + + return value + + +def _evaluate_markers(markers: List[Any], environment: Dict[str, str]) -> bool: + groups: List[List[bool]] = [[]] + + for marker in markers: + assert isinstance(marker, (list, tuple, str)) + + if isinstance(marker, list): + groups[-1].append(_evaluate_markers(marker, environment)) + elif isinstance(marker, tuple): + lhs, op, rhs = marker + + if isinstance(lhs, Variable): + lhs_value = _get_env(environment, lhs.value) + rhs_value = rhs.value + else: + lhs_value = lhs.value + rhs_value = _get_env(environment, rhs.value) + + groups[-1].append(_eval_op(lhs_value, op, rhs_value)) + else: + assert marker in ["and", "or"] + if marker == "or": + groups.append([]) + + return any(all(item) for item in groups) + + +def format_full_version(info: "sys._version_info") -> str: + version = "{0.major}.{0.minor}.{0.micro}".format(info) + kind = info.releaselevel + if kind != "final": + version += kind[0] + str(info.serial) + return version + + +def default_environment() -> Dict[str, str]: + iver = format_full_version(sys.implementation.version) + implementation_name = sys.implementation.name + return { + "implementation_name": implementation_name, + "implementation_version": iver, + "os_name": os.name, + "platform_machine": platform.machine(), + "platform_release": platform.release(), + "platform_system": platform.system(), + "platform_version": platform.version(), + "python_full_version": platform.python_version(), + "platform_python_implementation": platform.python_implementation(), + "python_version": ".".join(platform.python_version_tuple()[:2]), + "sys_platform": sys.platform, + } + + +class Marker: + def __init__(self, marker: str) -> None: + try: + self._markers = _coerce_parse_result(MARKER.parseString(marker)) + except ParseException as e: + raise InvalidMarker( + f"Invalid marker: {marker!r}, parse error at " + f"{marker[e.loc : e.loc + 8]!r}" + ) + + def __str__(self) -> str: + return _format_marker(self._markers) + + def __repr__(self) -> str: + return f"" + + def evaluate(self, environment: Optional[Dict[str, str]] = None) -> bool: + """Evaluate a marker. + + Return the boolean from evaluating the given marker against the + environment. environment is an optional argument to override all or + part of the determined environment. + + The environment is determined from the current Python process. + """ + current_environment = default_environment() + if environment is not None: + current_environment.update(environment) + + return _evaluate_markers(self._markers, current_environment) diff --git a/venv/Lib/site-packages/setuptools/_vendor/packaging/requirements.py b/venv/Lib/site-packages/setuptools/_vendor/packaging/requirements.py new file mode 100644 index 0000000..0d93231 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_vendor/packaging/requirements.py @@ -0,0 +1,146 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +import re +import string +import urllib.parse +from typing import List, Optional as TOptional, Set + +from setuptools.extern.pyparsing import ( # noqa + Combine, + Literal as L, + Optional, + ParseException, + Regex, + Word, + ZeroOrMore, + originalTextFor, + stringEnd, + stringStart, +) + +from .markers import MARKER_EXPR, Marker +from .specifiers import LegacySpecifier, Specifier, SpecifierSet + + +class InvalidRequirement(ValueError): + """ + An invalid requirement was found, users should refer to PEP 508. + """ + + +ALPHANUM = Word(string.ascii_letters + string.digits) + +LBRACKET = L("[").suppress() +RBRACKET = L("]").suppress() +LPAREN = L("(").suppress() +RPAREN = L(")").suppress() +COMMA = L(",").suppress() +SEMICOLON = L(";").suppress() +AT = L("@").suppress() + +PUNCTUATION = Word("-_.") +IDENTIFIER_END = ALPHANUM | (ZeroOrMore(PUNCTUATION) + ALPHANUM) +IDENTIFIER = Combine(ALPHANUM + ZeroOrMore(IDENTIFIER_END)) + +NAME = IDENTIFIER("name") +EXTRA = IDENTIFIER + +URI = Regex(r"[^ ]+")("url") +URL = AT + URI + +EXTRAS_LIST = EXTRA + ZeroOrMore(COMMA + EXTRA) +EXTRAS = (LBRACKET + Optional(EXTRAS_LIST) + RBRACKET)("extras") + +VERSION_PEP440 = Regex(Specifier._regex_str, re.VERBOSE | re.IGNORECASE) +VERSION_LEGACY = Regex(LegacySpecifier._regex_str, re.VERBOSE | re.IGNORECASE) + +VERSION_ONE = VERSION_PEP440 ^ VERSION_LEGACY +VERSION_MANY = Combine( + VERSION_ONE + ZeroOrMore(COMMA + VERSION_ONE), joinString=",", adjacent=False +)("_raw_spec") +_VERSION_SPEC = Optional((LPAREN + VERSION_MANY + RPAREN) | VERSION_MANY) +_VERSION_SPEC.setParseAction(lambda s, l, t: t._raw_spec or "") + +VERSION_SPEC = originalTextFor(_VERSION_SPEC)("specifier") +VERSION_SPEC.setParseAction(lambda s, l, t: t[1]) + +MARKER_EXPR = originalTextFor(MARKER_EXPR())("marker") +MARKER_EXPR.setParseAction( + lambda s, l, t: Marker(s[t._original_start : t._original_end]) +) +MARKER_SEPARATOR = SEMICOLON +MARKER = MARKER_SEPARATOR + MARKER_EXPR + +VERSION_AND_MARKER = VERSION_SPEC + Optional(MARKER) +URL_AND_MARKER = URL + Optional(MARKER) + +NAMED_REQUIREMENT = NAME + Optional(EXTRAS) + (URL_AND_MARKER | VERSION_AND_MARKER) + +REQUIREMENT = stringStart + NAMED_REQUIREMENT + stringEnd +# setuptools.extern.pyparsing isn't thread safe during initialization, so we do it eagerly, see +# issue #104 +REQUIREMENT.parseString("x[]") + + +class Requirement: + """Parse a requirement. + + Parse a given requirement string into its parts, such as name, specifier, + URL, and extras. Raises InvalidRequirement on a badly-formed requirement + string. + """ + + # TODO: Can we test whether something is contained within a requirement? + # If so how do we do that? Do we need to test against the _name_ of + # the thing as well as the version? What about the markers? + # TODO: Can we normalize the name and extra name? + + def __init__(self, requirement_string: str) -> None: + try: + req = REQUIREMENT.parseString(requirement_string) + except ParseException as e: + raise InvalidRequirement( + f'Parse error at "{ requirement_string[e.loc : e.loc + 8]!r}": {e.msg}' + ) + + self.name: str = req.name + if req.url: + parsed_url = urllib.parse.urlparse(req.url) + if parsed_url.scheme == "file": + if urllib.parse.urlunparse(parsed_url) != req.url: + raise InvalidRequirement("Invalid URL given") + elif not (parsed_url.scheme and parsed_url.netloc) or ( + not parsed_url.scheme and not parsed_url.netloc + ): + raise InvalidRequirement(f"Invalid URL: {req.url}") + self.url: TOptional[str] = req.url + else: + self.url = None + self.extras: Set[str] = set(req.extras.asList() if req.extras else []) + self.specifier: SpecifierSet = SpecifierSet(req.specifier) + self.marker: TOptional[Marker] = req.marker if req.marker else None + + def __str__(self) -> str: + parts: List[str] = [self.name] + + if self.extras: + formatted_extras = ",".join(sorted(self.extras)) + parts.append(f"[{formatted_extras}]") + + if self.specifier: + parts.append(str(self.specifier)) + + if self.url: + parts.append(f"@ {self.url}") + if self.marker: + parts.append(" ") + + if self.marker: + parts.append(f"; {self.marker}") + + return "".join(parts) + + def __repr__(self) -> str: + return f"" diff --git a/venv/Lib/site-packages/setuptools/_vendor/packaging/specifiers.py b/venv/Lib/site-packages/setuptools/_vendor/packaging/specifiers.py new file mode 100644 index 0000000..0e218a6 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_vendor/packaging/specifiers.py @@ -0,0 +1,802 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +import abc +import functools +import itertools +import re +import warnings +from typing import ( + Callable, + Dict, + Iterable, + Iterator, + List, + Optional, + Pattern, + Set, + Tuple, + TypeVar, + Union, +) + +from .utils import canonicalize_version +from .version import LegacyVersion, Version, parse + +ParsedVersion = Union[Version, LegacyVersion] +UnparsedVersion = Union[Version, LegacyVersion, str] +VersionTypeVar = TypeVar("VersionTypeVar", bound=UnparsedVersion) +CallableOperator = Callable[[ParsedVersion, str], bool] + + +class InvalidSpecifier(ValueError): + """ + An invalid specifier was found, users should refer to PEP 440. + """ + + +class BaseSpecifier(metaclass=abc.ABCMeta): + @abc.abstractmethod + def __str__(self) -> str: + """ + Returns the str representation of this Specifier like object. This + should be representative of the Specifier itself. + """ + + @abc.abstractmethod + def __hash__(self) -> int: + """ + Returns a hash value for this Specifier like object. + """ + + @abc.abstractmethod + def __eq__(self, other: object) -> bool: + """ + Returns a boolean representing whether or not the two Specifier like + objects are equal. + """ + + @abc.abstractproperty + def prereleases(self) -> Optional[bool]: + """ + Returns whether or not pre-releases as a whole are allowed by this + specifier. + """ + + @prereleases.setter + def prereleases(self, value: bool) -> None: + """ + Sets whether or not pre-releases as a whole are allowed by this + specifier. + """ + + @abc.abstractmethod + def contains(self, item: str, prereleases: Optional[bool] = None) -> bool: + """ + Determines if the given item is contained within this specifier. + """ + + @abc.abstractmethod + def filter( + self, iterable: Iterable[VersionTypeVar], prereleases: Optional[bool] = None + ) -> Iterable[VersionTypeVar]: + """ + Takes an iterable of items and filters them so that only items which + are contained within this specifier are allowed in it. + """ + + +class _IndividualSpecifier(BaseSpecifier): + + _operators: Dict[str, str] = {} + _regex: Pattern[str] + + def __init__(self, spec: str = "", prereleases: Optional[bool] = None) -> None: + match = self._regex.search(spec) + if not match: + raise InvalidSpecifier(f"Invalid specifier: '{spec}'") + + self._spec: Tuple[str, str] = ( + match.group("operator").strip(), + match.group("version").strip(), + ) + + # Store whether or not this Specifier should accept prereleases + self._prereleases = prereleases + + def __repr__(self) -> str: + pre = ( + f", prereleases={self.prereleases!r}" + if self._prereleases is not None + else "" + ) + + return f"<{self.__class__.__name__}({str(self)!r}{pre})>" + + def __str__(self) -> str: + return "{}{}".format(*self._spec) + + @property + def _canonical_spec(self) -> Tuple[str, str]: + return self._spec[0], canonicalize_version(self._spec[1]) + + def __hash__(self) -> int: + return hash(self._canonical_spec) + + def __eq__(self, other: object) -> bool: + if isinstance(other, str): + try: + other = self.__class__(str(other)) + except InvalidSpecifier: + return NotImplemented + elif not isinstance(other, self.__class__): + return NotImplemented + + return self._canonical_spec == other._canonical_spec + + def _get_operator(self, op: str) -> CallableOperator: + operator_callable: CallableOperator = getattr( + self, f"_compare_{self._operators[op]}" + ) + return operator_callable + + def _coerce_version(self, version: UnparsedVersion) -> ParsedVersion: + if not isinstance(version, (LegacyVersion, Version)): + version = parse(version) + return version + + @property + def operator(self) -> str: + return self._spec[0] + + @property + def version(self) -> str: + return self._spec[1] + + @property + def prereleases(self) -> Optional[bool]: + return self._prereleases + + @prereleases.setter + def prereleases(self, value: bool) -> None: + self._prereleases = value + + def __contains__(self, item: str) -> bool: + return self.contains(item) + + def contains( + self, item: UnparsedVersion, prereleases: Optional[bool] = None + ) -> bool: + + # Determine if prereleases are to be allowed or not. + if prereleases is None: + prereleases = self.prereleases + + # Normalize item to a Version or LegacyVersion, this allows us to have + # a shortcut for ``"2.0" in Specifier(">=2") + normalized_item = self._coerce_version(item) + + # Determine if we should be supporting prereleases in this specifier + # or not, if we do not support prereleases than we can short circuit + # logic if this version is a prereleases. + if normalized_item.is_prerelease and not prereleases: + return False + + # Actually do the comparison to determine if this item is contained + # within this Specifier or not. + operator_callable: CallableOperator = self._get_operator(self.operator) + return operator_callable(normalized_item, self.version) + + def filter( + self, iterable: Iterable[VersionTypeVar], prereleases: Optional[bool] = None + ) -> Iterable[VersionTypeVar]: + + yielded = False + found_prereleases = [] + + kw = {"prereleases": prereleases if prereleases is not None else True} + + # Attempt to iterate over all the values in the iterable and if any of + # them match, yield them. + for version in iterable: + parsed_version = self._coerce_version(version) + + if self.contains(parsed_version, **kw): + # If our version is a prerelease, and we were not set to allow + # prereleases, then we'll store it for later in case nothing + # else matches this specifier. + if parsed_version.is_prerelease and not ( + prereleases or self.prereleases + ): + found_prereleases.append(version) + # Either this is not a prerelease, or we should have been + # accepting prereleases from the beginning. + else: + yielded = True + yield version + + # Now that we've iterated over everything, determine if we've yielded + # any values, and if we have not and we have any prereleases stored up + # then we will go ahead and yield the prereleases. + if not yielded and found_prereleases: + for version in found_prereleases: + yield version + + +class LegacySpecifier(_IndividualSpecifier): + + _regex_str = r""" + (?P(==|!=|<=|>=|<|>)) + \s* + (?P + [^,;\s)]* # Since this is a "legacy" specifier, and the version + # string can be just about anything, we match everything + # except for whitespace, a semi-colon for marker support, + # a closing paren since versions can be enclosed in + # them, and a comma since it's a version separator. + ) + """ + + _regex = re.compile(r"^\s*" + _regex_str + r"\s*$", re.VERBOSE | re.IGNORECASE) + + _operators = { + "==": "equal", + "!=": "not_equal", + "<=": "less_than_equal", + ">=": "greater_than_equal", + "<": "less_than", + ">": "greater_than", + } + + def __init__(self, spec: str = "", prereleases: Optional[bool] = None) -> None: + super().__init__(spec, prereleases) + + warnings.warn( + "Creating a LegacyVersion has been deprecated and will be " + "removed in the next major release", + DeprecationWarning, + ) + + def _coerce_version(self, version: UnparsedVersion) -> LegacyVersion: + if not isinstance(version, LegacyVersion): + version = LegacyVersion(str(version)) + return version + + def _compare_equal(self, prospective: LegacyVersion, spec: str) -> bool: + return prospective == self._coerce_version(spec) + + def _compare_not_equal(self, prospective: LegacyVersion, spec: str) -> bool: + return prospective != self._coerce_version(spec) + + def _compare_less_than_equal(self, prospective: LegacyVersion, spec: str) -> bool: + return prospective <= self._coerce_version(spec) + + def _compare_greater_than_equal( + self, prospective: LegacyVersion, spec: str + ) -> bool: + return prospective >= self._coerce_version(spec) + + def _compare_less_than(self, prospective: LegacyVersion, spec: str) -> bool: + return prospective < self._coerce_version(spec) + + def _compare_greater_than(self, prospective: LegacyVersion, spec: str) -> bool: + return prospective > self._coerce_version(spec) + + +def _require_version_compare( + fn: Callable[["Specifier", ParsedVersion, str], bool] +) -> Callable[["Specifier", ParsedVersion, str], bool]: + @functools.wraps(fn) + def wrapped(self: "Specifier", prospective: ParsedVersion, spec: str) -> bool: + if not isinstance(prospective, Version): + return False + return fn(self, prospective, spec) + + return wrapped + + +class Specifier(_IndividualSpecifier): + + _regex_str = r""" + (?P(~=|==|!=|<=|>=|<|>|===)) + (?P + (?: + # The identity operators allow for an escape hatch that will + # do an exact string match of the version you wish to install. + # This will not be parsed by PEP 440 and we cannot determine + # any semantic meaning from it. This operator is discouraged + # but included entirely as an escape hatch. + (?<====) # Only match for the identity operator + \s* + [^\s]* # We just match everything, except for whitespace + # since we are only testing for strict identity. + ) + | + (?: + # The (non)equality operators allow for wild card and local + # versions to be specified so we have to define these two + # operators separately to enable that. + (?<===|!=) # Only match for equals and not equals + + \s* + v? + (?:[0-9]+!)? # epoch + [0-9]+(?:\.[0-9]+)* # release + (?: # pre release + [-_\.]? + (a|b|c|rc|alpha|beta|pre|preview) + [-_\.]? + [0-9]* + )? + (?: # post release + (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*) + )? + + # You cannot use a wild card and a dev or local version + # together so group them with a | and make them optional. + (?: + (?:[-_\.]?dev[-_\.]?[0-9]*)? # dev release + (?:\+[a-z0-9]+(?:[-_\.][a-z0-9]+)*)? # local + | + \.\* # Wild card syntax of .* + )? + ) + | + (?: + # The compatible operator requires at least two digits in the + # release segment. + (?<=~=) # Only match for the compatible operator + + \s* + v? + (?:[0-9]+!)? # epoch + [0-9]+(?:\.[0-9]+)+ # release (We have a + instead of a *) + (?: # pre release + [-_\.]? + (a|b|c|rc|alpha|beta|pre|preview) + [-_\.]? + [0-9]* + )? + (?: # post release + (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*) + )? + (?:[-_\.]?dev[-_\.]?[0-9]*)? # dev release + ) + | + (?: + # All other operators only allow a sub set of what the + # (non)equality operators do. Specifically they do not allow + # local versions to be specified nor do they allow the prefix + # matching wild cards. + (?=": "greater_than_equal", + "<": "less_than", + ">": "greater_than", + "===": "arbitrary", + } + + @_require_version_compare + def _compare_compatible(self, prospective: ParsedVersion, spec: str) -> bool: + + # Compatible releases have an equivalent combination of >= and ==. That + # is that ~=2.2 is equivalent to >=2.2,==2.*. This allows us to + # implement this in terms of the other specifiers instead of + # implementing it ourselves. The only thing we need to do is construct + # the other specifiers. + + # We want everything but the last item in the version, but we want to + # ignore suffix segments. + prefix = ".".join( + list(itertools.takewhile(_is_not_suffix, _version_split(spec)))[:-1] + ) + + # Add the prefix notation to the end of our string + prefix += ".*" + + return self._get_operator(">=")(prospective, spec) and self._get_operator("==")( + prospective, prefix + ) + + @_require_version_compare + def _compare_equal(self, prospective: ParsedVersion, spec: str) -> bool: + + # We need special logic to handle prefix matching + if spec.endswith(".*"): + # In the case of prefix matching we want to ignore local segment. + prospective = Version(prospective.public) + # Split the spec out by dots, and pretend that there is an implicit + # dot in between a release segment and a pre-release segment. + split_spec = _version_split(spec[:-2]) # Remove the trailing .* + + # Split the prospective version out by dots, and pretend that there + # is an implicit dot in between a release segment and a pre-release + # segment. + split_prospective = _version_split(str(prospective)) + + # Shorten the prospective version to be the same length as the spec + # so that we can determine if the specifier is a prefix of the + # prospective version or not. + shortened_prospective = split_prospective[: len(split_spec)] + + # Pad out our two sides with zeros so that they both equal the same + # length. + padded_spec, padded_prospective = _pad_version( + split_spec, shortened_prospective + ) + + return padded_prospective == padded_spec + else: + # Convert our spec string into a Version + spec_version = Version(spec) + + # If the specifier does not have a local segment, then we want to + # act as if the prospective version also does not have a local + # segment. + if not spec_version.local: + prospective = Version(prospective.public) + + return prospective == spec_version + + @_require_version_compare + def _compare_not_equal(self, prospective: ParsedVersion, spec: str) -> bool: + return not self._compare_equal(prospective, spec) + + @_require_version_compare + def _compare_less_than_equal(self, prospective: ParsedVersion, spec: str) -> bool: + + # NB: Local version identifiers are NOT permitted in the version + # specifier, so local version labels can be universally removed from + # the prospective version. + return Version(prospective.public) <= Version(spec) + + @_require_version_compare + def _compare_greater_than_equal( + self, prospective: ParsedVersion, spec: str + ) -> bool: + + # NB: Local version identifiers are NOT permitted in the version + # specifier, so local version labels can be universally removed from + # the prospective version. + return Version(prospective.public) >= Version(spec) + + @_require_version_compare + def _compare_less_than(self, prospective: ParsedVersion, spec_str: str) -> bool: + + # Convert our spec to a Version instance, since we'll want to work with + # it as a version. + spec = Version(spec_str) + + # Check to see if the prospective version is less than the spec + # version. If it's not we can short circuit and just return False now + # instead of doing extra unneeded work. + if not prospective < spec: + return False + + # This special case is here so that, unless the specifier itself + # includes is a pre-release version, that we do not accept pre-release + # versions for the version mentioned in the specifier (e.g. <3.1 should + # not match 3.1.dev0, but should match 3.0.dev0). + if not spec.is_prerelease and prospective.is_prerelease: + if Version(prospective.base_version) == Version(spec.base_version): + return False + + # If we've gotten to here, it means that prospective version is both + # less than the spec version *and* it's not a pre-release of the same + # version in the spec. + return True + + @_require_version_compare + def _compare_greater_than(self, prospective: ParsedVersion, spec_str: str) -> bool: + + # Convert our spec to a Version instance, since we'll want to work with + # it as a version. + spec = Version(spec_str) + + # Check to see if the prospective version is greater than the spec + # version. If it's not we can short circuit and just return False now + # instead of doing extra unneeded work. + if not prospective > spec: + return False + + # This special case is here so that, unless the specifier itself + # includes is a post-release version, that we do not accept + # post-release versions for the version mentioned in the specifier + # (e.g. >3.1 should not match 3.0.post0, but should match 3.2.post0). + if not spec.is_postrelease and prospective.is_postrelease: + if Version(prospective.base_version) == Version(spec.base_version): + return False + + # Ensure that we do not allow a local version of the version mentioned + # in the specifier, which is technically greater than, to match. + if prospective.local is not None: + if Version(prospective.base_version) == Version(spec.base_version): + return False + + # If we've gotten to here, it means that prospective version is both + # greater than the spec version *and* it's not a pre-release of the + # same version in the spec. + return True + + def _compare_arbitrary(self, prospective: Version, spec: str) -> bool: + return str(prospective).lower() == str(spec).lower() + + @property + def prereleases(self) -> bool: + + # If there is an explicit prereleases set for this, then we'll just + # blindly use that. + if self._prereleases is not None: + return self._prereleases + + # Look at all of our specifiers and determine if they are inclusive + # operators, and if they are if they are including an explicit + # prerelease. + operator, version = self._spec + if operator in ["==", ">=", "<=", "~=", "==="]: + # The == specifier can include a trailing .*, if it does we + # want to remove before parsing. + if operator == "==" and version.endswith(".*"): + version = version[:-2] + + # Parse the version, and if it is a pre-release than this + # specifier allows pre-releases. + if parse(version).is_prerelease: + return True + + return False + + @prereleases.setter + def prereleases(self, value: bool) -> None: + self._prereleases = value + + +_prefix_regex = re.compile(r"^([0-9]+)((?:a|b|c|rc)[0-9]+)$") + + +def _version_split(version: str) -> List[str]: + result: List[str] = [] + for item in version.split("."): + match = _prefix_regex.search(item) + if match: + result.extend(match.groups()) + else: + result.append(item) + return result + + +def _is_not_suffix(segment: str) -> bool: + return not any( + segment.startswith(prefix) for prefix in ("dev", "a", "b", "rc", "post") + ) + + +def _pad_version(left: List[str], right: List[str]) -> Tuple[List[str], List[str]]: + left_split, right_split = [], [] + + # Get the release segment of our versions + left_split.append(list(itertools.takewhile(lambda x: x.isdigit(), left))) + right_split.append(list(itertools.takewhile(lambda x: x.isdigit(), right))) + + # Get the rest of our versions + left_split.append(left[len(left_split[0]) :]) + right_split.append(right[len(right_split[0]) :]) + + # Insert our padding + left_split.insert(1, ["0"] * max(0, len(right_split[0]) - len(left_split[0]))) + right_split.insert(1, ["0"] * max(0, len(left_split[0]) - len(right_split[0]))) + + return (list(itertools.chain(*left_split)), list(itertools.chain(*right_split))) + + +class SpecifierSet(BaseSpecifier): + def __init__( + self, specifiers: str = "", prereleases: Optional[bool] = None + ) -> None: + + # Split on , to break each individual specifier into it's own item, and + # strip each item to remove leading/trailing whitespace. + split_specifiers = [s.strip() for s in specifiers.split(",") if s.strip()] + + # Parsed each individual specifier, attempting first to make it a + # Specifier and falling back to a LegacySpecifier. + parsed: Set[_IndividualSpecifier] = set() + for specifier in split_specifiers: + try: + parsed.add(Specifier(specifier)) + except InvalidSpecifier: + parsed.add(LegacySpecifier(specifier)) + + # Turn our parsed specifiers into a frozen set and save them for later. + self._specs = frozenset(parsed) + + # Store our prereleases value so we can use it later to determine if + # we accept prereleases or not. + self._prereleases = prereleases + + def __repr__(self) -> str: + pre = ( + f", prereleases={self.prereleases!r}" + if self._prereleases is not None + else "" + ) + + return f"" + + def __str__(self) -> str: + return ",".join(sorted(str(s) for s in self._specs)) + + def __hash__(self) -> int: + return hash(self._specs) + + def __and__(self, other: Union["SpecifierSet", str]) -> "SpecifierSet": + if isinstance(other, str): + other = SpecifierSet(other) + elif not isinstance(other, SpecifierSet): + return NotImplemented + + specifier = SpecifierSet() + specifier._specs = frozenset(self._specs | other._specs) + + if self._prereleases is None and other._prereleases is not None: + specifier._prereleases = other._prereleases + elif self._prereleases is not None and other._prereleases is None: + specifier._prereleases = self._prereleases + elif self._prereleases == other._prereleases: + specifier._prereleases = self._prereleases + else: + raise ValueError( + "Cannot combine SpecifierSets with True and False prerelease " + "overrides." + ) + + return specifier + + def __eq__(self, other: object) -> bool: + if isinstance(other, (str, _IndividualSpecifier)): + other = SpecifierSet(str(other)) + elif not isinstance(other, SpecifierSet): + return NotImplemented + + return self._specs == other._specs + + def __len__(self) -> int: + return len(self._specs) + + def __iter__(self) -> Iterator[_IndividualSpecifier]: + return iter(self._specs) + + @property + def prereleases(self) -> Optional[bool]: + + # If we have been given an explicit prerelease modifier, then we'll + # pass that through here. + if self._prereleases is not None: + return self._prereleases + + # If we don't have any specifiers, and we don't have a forced value, + # then we'll just return None since we don't know if this should have + # pre-releases or not. + if not self._specs: + return None + + # Otherwise we'll see if any of the given specifiers accept + # prereleases, if any of them do we'll return True, otherwise False. + return any(s.prereleases for s in self._specs) + + @prereleases.setter + def prereleases(self, value: bool) -> None: + self._prereleases = value + + def __contains__(self, item: UnparsedVersion) -> bool: + return self.contains(item) + + def contains( + self, item: UnparsedVersion, prereleases: Optional[bool] = None + ) -> bool: + + # Ensure that our item is a Version or LegacyVersion instance. + if not isinstance(item, (LegacyVersion, Version)): + item = parse(item) + + # Determine if we're forcing a prerelease or not, if we're not forcing + # one for this particular filter call, then we'll use whatever the + # SpecifierSet thinks for whether or not we should support prereleases. + if prereleases is None: + prereleases = self.prereleases + + # We can determine if we're going to allow pre-releases by looking to + # see if any of the underlying items supports them. If none of them do + # and this item is a pre-release then we do not allow it and we can + # short circuit that here. + # Note: This means that 1.0.dev1 would not be contained in something + # like >=1.0.devabc however it would be in >=1.0.debabc,>0.0.dev0 + if not prereleases and item.is_prerelease: + return False + + # We simply dispatch to the underlying specs here to make sure that the + # given version is contained within all of them. + # Note: This use of all() here means that an empty set of specifiers + # will always return True, this is an explicit design decision. + return all(s.contains(item, prereleases=prereleases) for s in self._specs) + + def filter( + self, iterable: Iterable[VersionTypeVar], prereleases: Optional[bool] = None + ) -> Iterable[VersionTypeVar]: + + # Determine if we're forcing a prerelease or not, if we're not forcing + # one for this particular filter call, then we'll use whatever the + # SpecifierSet thinks for whether or not we should support prereleases. + if prereleases is None: + prereleases = self.prereleases + + # If we have any specifiers, then we want to wrap our iterable in the + # filter method for each one, this will act as a logical AND amongst + # each specifier. + if self._specs: + for spec in self._specs: + iterable = spec.filter(iterable, prereleases=bool(prereleases)) + return iterable + # If we do not have any specifiers, then we need to have a rough filter + # which will filter out any pre-releases, unless there are no final + # releases, and which will filter out LegacyVersion in general. + else: + filtered: List[VersionTypeVar] = [] + found_prereleases: List[VersionTypeVar] = [] + + item: UnparsedVersion + parsed_version: Union[Version, LegacyVersion] + + for item in iterable: + # Ensure that we some kind of Version class for this item. + if not isinstance(item, (LegacyVersion, Version)): + parsed_version = parse(item) + else: + parsed_version = item + + # Filter out any item which is parsed as a LegacyVersion + if isinstance(parsed_version, LegacyVersion): + continue + + # Store any item which is a pre-release for later unless we've + # already found a final version or we are accepting prereleases + if parsed_version.is_prerelease and not prereleases: + if not filtered: + found_prereleases.append(item) + else: + filtered.append(item) + + # If we've found no items except for pre-releases, then we'll go + # ahead and use the pre-releases + if not filtered and found_prereleases and prereleases is None: + return found_prereleases + + return filtered diff --git a/venv/Lib/site-packages/setuptools/_vendor/packaging/tags.py b/venv/Lib/site-packages/setuptools/_vendor/packaging/tags.py new file mode 100644 index 0000000..9a3d25a --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_vendor/packaging/tags.py @@ -0,0 +1,487 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +import logging +import platform +import sys +import sysconfig +from importlib.machinery import EXTENSION_SUFFIXES +from typing import ( + Dict, + FrozenSet, + Iterable, + Iterator, + List, + Optional, + Sequence, + Tuple, + Union, + cast, +) + +from . import _manylinux, _musllinux + +logger = logging.getLogger(__name__) + +PythonVersion = Sequence[int] +MacVersion = Tuple[int, int] + +INTERPRETER_SHORT_NAMES: Dict[str, str] = { + "python": "py", # Generic. + "cpython": "cp", + "pypy": "pp", + "ironpython": "ip", + "jython": "jy", +} + + +_32_BIT_INTERPRETER = sys.maxsize <= 2 ** 32 + + +class Tag: + """ + A representation of the tag triple for a wheel. + + Instances are considered immutable and thus are hashable. Equality checking + is also supported. + """ + + __slots__ = ["_interpreter", "_abi", "_platform", "_hash"] + + def __init__(self, interpreter: str, abi: str, platform: str) -> None: + self._interpreter = interpreter.lower() + self._abi = abi.lower() + self._platform = platform.lower() + # The __hash__ of every single element in a Set[Tag] will be evaluated each time + # that a set calls its `.disjoint()` method, which may be called hundreds of + # times when scanning a page of links for packages with tags matching that + # Set[Tag]. Pre-computing the value here produces significant speedups for + # downstream consumers. + self._hash = hash((self._interpreter, self._abi, self._platform)) + + @property + def interpreter(self) -> str: + return self._interpreter + + @property + def abi(self) -> str: + return self._abi + + @property + def platform(self) -> str: + return self._platform + + def __eq__(self, other: object) -> bool: + if not isinstance(other, Tag): + return NotImplemented + + return ( + (self._hash == other._hash) # Short-circuit ASAP for perf reasons. + and (self._platform == other._platform) + and (self._abi == other._abi) + and (self._interpreter == other._interpreter) + ) + + def __hash__(self) -> int: + return self._hash + + def __str__(self) -> str: + return f"{self._interpreter}-{self._abi}-{self._platform}" + + def __repr__(self) -> str: + return f"<{self} @ {id(self)}>" + + +def parse_tag(tag: str) -> FrozenSet[Tag]: + """ + Parses the provided tag (e.g. `py3-none-any`) into a frozenset of Tag instances. + + Returning a set is required due to the possibility that the tag is a + compressed tag set. + """ + tags = set() + interpreters, abis, platforms = tag.split("-") + for interpreter in interpreters.split("."): + for abi in abis.split("."): + for platform_ in platforms.split("."): + tags.add(Tag(interpreter, abi, platform_)) + return frozenset(tags) + + +def _get_config_var(name: str, warn: bool = False) -> Union[int, str, None]: + value = sysconfig.get_config_var(name) + if value is None and warn: + logger.debug( + "Config variable '%s' is unset, Python ABI tag may be incorrect", name + ) + return value + + +def _normalize_string(string: str) -> str: + return string.replace(".", "_").replace("-", "_") + + +def _abi3_applies(python_version: PythonVersion) -> bool: + """ + Determine if the Python version supports abi3. + + PEP 384 was first implemented in Python 3.2. + """ + return len(python_version) > 1 and tuple(python_version) >= (3, 2) + + +def _cpython_abis(py_version: PythonVersion, warn: bool = False) -> List[str]: + py_version = tuple(py_version) # To allow for version comparison. + abis = [] + version = _version_nodot(py_version[:2]) + debug = pymalloc = ucs4 = "" + with_debug = _get_config_var("Py_DEBUG", warn) + has_refcount = hasattr(sys, "gettotalrefcount") + # Windows doesn't set Py_DEBUG, so checking for support of debug-compiled + # extension modules is the best option. + # https://github.com/pypa/pip/issues/3383#issuecomment-173267692 + has_ext = "_d.pyd" in EXTENSION_SUFFIXES + if with_debug or (with_debug is None and (has_refcount or has_ext)): + debug = "d" + if py_version < (3, 8): + with_pymalloc = _get_config_var("WITH_PYMALLOC", warn) + if with_pymalloc or with_pymalloc is None: + pymalloc = "m" + if py_version < (3, 3): + unicode_size = _get_config_var("Py_UNICODE_SIZE", warn) + if unicode_size == 4 or ( + unicode_size is None and sys.maxunicode == 0x10FFFF + ): + ucs4 = "u" + elif debug: + # Debug builds can also load "normal" extension modules. + # We can also assume no UCS-4 or pymalloc requirement. + abis.append(f"cp{version}") + abis.insert( + 0, + "cp{version}{debug}{pymalloc}{ucs4}".format( + version=version, debug=debug, pymalloc=pymalloc, ucs4=ucs4 + ), + ) + return abis + + +def cpython_tags( + python_version: Optional[PythonVersion] = None, + abis: Optional[Iterable[str]] = None, + platforms: Optional[Iterable[str]] = None, + *, + warn: bool = False, +) -> Iterator[Tag]: + """ + Yields the tags for a CPython interpreter. + + The tags consist of: + - cp-- + - cp-abi3- + - cp-none- + - cp-abi3- # Older Python versions down to 3.2. + + If python_version only specifies a major version then user-provided ABIs and + the 'none' ABItag will be used. + + If 'abi3' or 'none' are specified in 'abis' then they will be yielded at + their normal position and not at the beginning. + """ + if not python_version: + python_version = sys.version_info[:2] + + interpreter = f"cp{_version_nodot(python_version[:2])}" + + if abis is None: + if len(python_version) > 1: + abis = _cpython_abis(python_version, warn) + else: + abis = [] + abis = list(abis) + # 'abi3' and 'none' are explicitly handled later. + for explicit_abi in ("abi3", "none"): + try: + abis.remove(explicit_abi) + except ValueError: + pass + + platforms = list(platforms or platform_tags()) + for abi in abis: + for platform_ in platforms: + yield Tag(interpreter, abi, platform_) + if _abi3_applies(python_version): + yield from (Tag(interpreter, "abi3", platform_) for platform_ in platforms) + yield from (Tag(interpreter, "none", platform_) for platform_ in platforms) + + if _abi3_applies(python_version): + for minor_version in range(python_version[1] - 1, 1, -1): + for platform_ in platforms: + interpreter = "cp{version}".format( + version=_version_nodot((python_version[0], minor_version)) + ) + yield Tag(interpreter, "abi3", platform_) + + +def _generic_abi() -> Iterator[str]: + abi = sysconfig.get_config_var("SOABI") + if abi: + yield _normalize_string(abi) + + +def generic_tags( + interpreter: Optional[str] = None, + abis: Optional[Iterable[str]] = None, + platforms: Optional[Iterable[str]] = None, + *, + warn: bool = False, +) -> Iterator[Tag]: + """ + Yields the tags for a generic interpreter. + + The tags consist of: + - -- + + The "none" ABI will be added if it was not explicitly provided. + """ + if not interpreter: + interp_name = interpreter_name() + interp_version = interpreter_version(warn=warn) + interpreter = "".join([interp_name, interp_version]) + if abis is None: + abis = _generic_abi() + platforms = list(platforms or platform_tags()) + abis = list(abis) + if "none" not in abis: + abis.append("none") + for abi in abis: + for platform_ in platforms: + yield Tag(interpreter, abi, platform_) + + +def _py_interpreter_range(py_version: PythonVersion) -> Iterator[str]: + """ + Yields Python versions in descending order. + + After the latest version, the major-only version will be yielded, and then + all previous versions of that major version. + """ + if len(py_version) > 1: + yield f"py{_version_nodot(py_version[:2])}" + yield f"py{py_version[0]}" + if len(py_version) > 1: + for minor in range(py_version[1] - 1, -1, -1): + yield f"py{_version_nodot((py_version[0], minor))}" + + +def compatible_tags( + python_version: Optional[PythonVersion] = None, + interpreter: Optional[str] = None, + platforms: Optional[Iterable[str]] = None, +) -> Iterator[Tag]: + """ + Yields the sequence of tags that are compatible with a specific version of Python. + + The tags consist of: + - py*-none- + - -none-any # ... if `interpreter` is provided. + - py*-none-any + """ + if not python_version: + python_version = sys.version_info[:2] + platforms = list(platforms or platform_tags()) + for version in _py_interpreter_range(python_version): + for platform_ in platforms: + yield Tag(version, "none", platform_) + if interpreter: + yield Tag(interpreter, "none", "any") + for version in _py_interpreter_range(python_version): + yield Tag(version, "none", "any") + + +def _mac_arch(arch: str, is_32bit: bool = _32_BIT_INTERPRETER) -> str: + if not is_32bit: + return arch + + if arch.startswith("ppc"): + return "ppc" + + return "i386" + + +def _mac_binary_formats(version: MacVersion, cpu_arch: str) -> List[str]: + formats = [cpu_arch] + if cpu_arch == "x86_64": + if version < (10, 4): + return [] + formats.extend(["intel", "fat64", "fat32"]) + + elif cpu_arch == "i386": + if version < (10, 4): + return [] + formats.extend(["intel", "fat32", "fat"]) + + elif cpu_arch == "ppc64": + # TODO: Need to care about 32-bit PPC for ppc64 through 10.2? + if version > (10, 5) or version < (10, 4): + return [] + formats.append("fat64") + + elif cpu_arch == "ppc": + if version > (10, 6): + return [] + formats.extend(["fat32", "fat"]) + + if cpu_arch in {"arm64", "x86_64"}: + formats.append("universal2") + + if cpu_arch in {"x86_64", "i386", "ppc64", "ppc", "intel"}: + formats.append("universal") + + return formats + + +def mac_platforms( + version: Optional[MacVersion] = None, arch: Optional[str] = None +) -> Iterator[str]: + """ + Yields the platform tags for a macOS system. + + The `version` parameter is a two-item tuple specifying the macOS version to + generate platform tags for. The `arch` parameter is the CPU architecture to + generate platform tags for. Both parameters default to the appropriate value + for the current system. + """ + version_str, _, cpu_arch = platform.mac_ver() + if version is None: + version = cast("MacVersion", tuple(map(int, version_str.split(".")[:2]))) + else: + version = version + if arch is None: + arch = _mac_arch(cpu_arch) + else: + arch = arch + + if (10, 0) <= version and version < (11, 0): + # Prior to Mac OS 11, each yearly release of Mac OS bumped the + # "minor" version number. The major version was always 10. + for minor_version in range(version[1], -1, -1): + compat_version = 10, minor_version + binary_formats = _mac_binary_formats(compat_version, arch) + for binary_format in binary_formats: + yield "macosx_{major}_{minor}_{binary_format}".format( + major=10, minor=minor_version, binary_format=binary_format + ) + + if version >= (11, 0): + # Starting with Mac OS 11, each yearly release bumps the major version + # number. The minor versions are now the midyear updates. + for major_version in range(version[0], 10, -1): + compat_version = major_version, 0 + binary_formats = _mac_binary_formats(compat_version, arch) + for binary_format in binary_formats: + yield "macosx_{major}_{minor}_{binary_format}".format( + major=major_version, minor=0, binary_format=binary_format + ) + + if version >= (11, 0): + # Mac OS 11 on x86_64 is compatible with binaries from previous releases. + # Arm64 support was introduced in 11.0, so no Arm binaries from previous + # releases exist. + # + # However, the "universal2" binary format can have a + # macOS version earlier than 11.0 when the x86_64 part of the binary supports + # that version of macOS. + if arch == "x86_64": + for minor_version in range(16, 3, -1): + compat_version = 10, minor_version + binary_formats = _mac_binary_formats(compat_version, arch) + for binary_format in binary_formats: + yield "macosx_{major}_{minor}_{binary_format}".format( + major=compat_version[0], + minor=compat_version[1], + binary_format=binary_format, + ) + else: + for minor_version in range(16, 3, -1): + compat_version = 10, minor_version + binary_format = "universal2" + yield "macosx_{major}_{minor}_{binary_format}".format( + major=compat_version[0], + minor=compat_version[1], + binary_format=binary_format, + ) + + +def _linux_platforms(is_32bit: bool = _32_BIT_INTERPRETER) -> Iterator[str]: + linux = _normalize_string(sysconfig.get_platform()) + if is_32bit: + if linux == "linux_x86_64": + linux = "linux_i686" + elif linux == "linux_aarch64": + linux = "linux_armv7l" + _, arch = linux.split("_", 1) + yield from _manylinux.platform_tags(linux, arch) + yield from _musllinux.platform_tags(arch) + yield linux + + +def _generic_platforms() -> Iterator[str]: + yield _normalize_string(sysconfig.get_platform()) + + +def platform_tags() -> Iterator[str]: + """ + Provides the platform tags for this installation. + """ + if platform.system() == "Darwin": + return mac_platforms() + elif platform.system() == "Linux": + return _linux_platforms() + else: + return _generic_platforms() + + +def interpreter_name() -> str: + """ + Returns the name of the running interpreter. + """ + name = sys.implementation.name + return INTERPRETER_SHORT_NAMES.get(name) or name + + +def interpreter_version(*, warn: bool = False) -> str: + """ + Returns the version of the running interpreter. + """ + version = _get_config_var("py_version_nodot", warn=warn) + if version: + version = str(version) + else: + version = _version_nodot(sys.version_info[:2]) + return version + + +def _version_nodot(version: PythonVersion) -> str: + return "".join(map(str, version)) + + +def sys_tags(*, warn: bool = False) -> Iterator[Tag]: + """ + Returns the sequence of tag triples for the running interpreter. + + The order of the sequence corresponds to priority order for the + interpreter, from most to least important. + """ + + interp_name = interpreter_name() + if interp_name == "cp": + yield from cpython_tags(warn=warn) + else: + yield from generic_tags() + + if interp_name == "pp": + yield from compatible_tags(interpreter="pp3") + else: + yield from compatible_tags() diff --git a/venv/Lib/site-packages/setuptools/_vendor/packaging/utils.py b/venv/Lib/site-packages/setuptools/_vendor/packaging/utils.py new file mode 100644 index 0000000..bab11b8 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_vendor/packaging/utils.py @@ -0,0 +1,136 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +import re +from typing import FrozenSet, NewType, Tuple, Union, cast + +from .tags import Tag, parse_tag +from .version import InvalidVersion, Version + +BuildTag = Union[Tuple[()], Tuple[int, str]] +NormalizedName = NewType("NormalizedName", str) + + +class InvalidWheelFilename(ValueError): + """ + An invalid wheel filename was found, users should refer to PEP 427. + """ + + +class InvalidSdistFilename(ValueError): + """ + An invalid sdist filename was found, users should refer to the packaging user guide. + """ + + +_canonicalize_regex = re.compile(r"[-_.]+") +# PEP 427: The build number must start with a digit. +_build_tag_regex = re.compile(r"(\d+)(.*)") + + +def canonicalize_name(name: str) -> NormalizedName: + # This is taken from PEP 503. + value = _canonicalize_regex.sub("-", name).lower() + return cast(NormalizedName, value) + + +def canonicalize_version(version: Union[Version, str]) -> str: + """ + This is very similar to Version.__str__, but has one subtle difference + with the way it handles the release segment. + """ + if isinstance(version, str): + try: + parsed = Version(version) + except InvalidVersion: + # Legacy versions cannot be normalized + return version + else: + parsed = version + + parts = [] + + # Epoch + if parsed.epoch != 0: + parts.append(f"{parsed.epoch}!") + + # Release segment + # NB: This strips trailing '.0's to normalize + parts.append(re.sub(r"(\.0)+$", "", ".".join(str(x) for x in parsed.release))) + + # Pre-release + if parsed.pre is not None: + parts.append("".join(str(x) for x in parsed.pre)) + + # Post-release + if parsed.post is not None: + parts.append(f".post{parsed.post}") + + # Development release + if parsed.dev is not None: + parts.append(f".dev{parsed.dev}") + + # Local version segment + if parsed.local is not None: + parts.append(f"+{parsed.local}") + + return "".join(parts) + + +def parse_wheel_filename( + filename: str, +) -> Tuple[NormalizedName, Version, BuildTag, FrozenSet[Tag]]: + if not filename.endswith(".whl"): + raise InvalidWheelFilename( + f"Invalid wheel filename (extension must be '.whl'): {filename}" + ) + + filename = filename[:-4] + dashes = filename.count("-") + if dashes not in (4, 5): + raise InvalidWheelFilename( + f"Invalid wheel filename (wrong number of parts): {filename}" + ) + + parts = filename.split("-", dashes - 2) + name_part = parts[0] + # See PEP 427 for the rules on escaping the project name + if "__" in name_part or re.match(r"^[\w\d._]*$", name_part, re.UNICODE) is None: + raise InvalidWheelFilename(f"Invalid project name: {filename}") + name = canonicalize_name(name_part) + version = Version(parts[1]) + if dashes == 5: + build_part = parts[2] + build_match = _build_tag_regex.match(build_part) + if build_match is None: + raise InvalidWheelFilename( + f"Invalid build number: {build_part} in '{filename}'" + ) + build = cast(BuildTag, (int(build_match.group(1)), build_match.group(2))) + else: + build = () + tags = parse_tag(parts[-1]) + return (name, version, build, tags) + + +def parse_sdist_filename(filename: str) -> Tuple[NormalizedName, Version]: + if filename.endswith(".tar.gz"): + file_stem = filename[: -len(".tar.gz")] + elif filename.endswith(".zip"): + file_stem = filename[: -len(".zip")] + else: + raise InvalidSdistFilename( + f"Invalid sdist filename (extension must be '.tar.gz' or '.zip'):" + f" {filename}" + ) + + # We are requiring a PEP 440 version, which cannot contain dashes, + # so we split on the last dash. + name_part, sep, version_part = file_stem.rpartition("-") + if not sep: + raise InvalidSdistFilename(f"Invalid sdist filename: {filename}") + + name = canonicalize_name(name_part) + version = Version(version_part) + return (name, version) diff --git a/venv/Lib/site-packages/setuptools/_vendor/packaging/version.py b/venv/Lib/site-packages/setuptools/_vendor/packaging/version.py new file mode 100644 index 0000000..de9a09a --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_vendor/packaging/version.py @@ -0,0 +1,504 @@ +# This file is dual licensed under the terms of the Apache License, Version +# 2.0, and the BSD License. See the LICENSE file in the root of this repository +# for complete details. + +import collections +import itertools +import re +import warnings +from typing import Callable, Iterator, List, Optional, SupportsInt, Tuple, Union + +from ._structures import Infinity, InfinityType, NegativeInfinity, NegativeInfinityType + +__all__ = ["parse", "Version", "LegacyVersion", "InvalidVersion", "VERSION_PATTERN"] + +InfiniteTypes = Union[InfinityType, NegativeInfinityType] +PrePostDevType = Union[InfiniteTypes, Tuple[str, int]] +SubLocalType = Union[InfiniteTypes, int, str] +LocalType = Union[ + NegativeInfinityType, + Tuple[ + Union[ + SubLocalType, + Tuple[SubLocalType, str], + Tuple[NegativeInfinityType, SubLocalType], + ], + ..., + ], +] +CmpKey = Tuple[ + int, Tuple[int, ...], PrePostDevType, PrePostDevType, PrePostDevType, LocalType +] +LegacyCmpKey = Tuple[int, Tuple[str, ...]] +VersionComparisonMethod = Callable[ + [Union[CmpKey, LegacyCmpKey], Union[CmpKey, LegacyCmpKey]], bool +] + +_Version = collections.namedtuple( + "_Version", ["epoch", "release", "dev", "pre", "post", "local"] +) + + +def parse(version: str) -> Union["LegacyVersion", "Version"]: + """ + Parse the given version string and return either a :class:`Version` object + or a :class:`LegacyVersion` object depending on if the given version is + a valid PEP 440 version or a legacy version. + """ + try: + return Version(version) + except InvalidVersion: + return LegacyVersion(version) + + +class InvalidVersion(ValueError): + """ + An invalid version was found, users should refer to PEP 440. + """ + + +class _BaseVersion: + _key: Union[CmpKey, LegacyCmpKey] + + def __hash__(self) -> int: + return hash(self._key) + + # Please keep the duplicated `isinstance` check + # in the six comparisons hereunder + # unless you find a way to avoid adding overhead function calls. + def __lt__(self, other: "_BaseVersion") -> bool: + if not isinstance(other, _BaseVersion): + return NotImplemented + + return self._key < other._key + + def __le__(self, other: "_BaseVersion") -> bool: + if not isinstance(other, _BaseVersion): + return NotImplemented + + return self._key <= other._key + + def __eq__(self, other: object) -> bool: + if not isinstance(other, _BaseVersion): + return NotImplemented + + return self._key == other._key + + def __ge__(self, other: "_BaseVersion") -> bool: + if not isinstance(other, _BaseVersion): + return NotImplemented + + return self._key >= other._key + + def __gt__(self, other: "_BaseVersion") -> bool: + if not isinstance(other, _BaseVersion): + return NotImplemented + + return self._key > other._key + + def __ne__(self, other: object) -> bool: + if not isinstance(other, _BaseVersion): + return NotImplemented + + return self._key != other._key + + +class LegacyVersion(_BaseVersion): + def __init__(self, version: str) -> None: + self._version = str(version) + self._key = _legacy_cmpkey(self._version) + + warnings.warn( + "Creating a LegacyVersion has been deprecated and will be " + "removed in the next major release", + DeprecationWarning, + ) + + def __str__(self) -> str: + return self._version + + def __repr__(self) -> str: + return f"" + + @property + def public(self) -> str: + return self._version + + @property + def base_version(self) -> str: + return self._version + + @property + def epoch(self) -> int: + return -1 + + @property + def release(self) -> None: + return None + + @property + def pre(self) -> None: + return None + + @property + def post(self) -> None: + return None + + @property + def dev(self) -> None: + return None + + @property + def local(self) -> None: + return None + + @property + def is_prerelease(self) -> bool: + return False + + @property + def is_postrelease(self) -> bool: + return False + + @property + def is_devrelease(self) -> bool: + return False + + +_legacy_version_component_re = re.compile(r"(\d+ | [a-z]+ | \.| -)", re.VERBOSE) + +_legacy_version_replacement_map = { + "pre": "c", + "preview": "c", + "-": "final-", + "rc": "c", + "dev": "@", +} + + +def _parse_version_parts(s: str) -> Iterator[str]: + for part in _legacy_version_component_re.split(s): + part = _legacy_version_replacement_map.get(part, part) + + if not part or part == ".": + continue + + if part[:1] in "0123456789": + # pad for numeric comparison + yield part.zfill(8) + else: + yield "*" + part + + # ensure that alpha/beta/candidate are before final + yield "*final" + + +def _legacy_cmpkey(version: str) -> LegacyCmpKey: + + # We hardcode an epoch of -1 here. A PEP 440 version can only have a epoch + # greater than or equal to 0. This will effectively put the LegacyVersion, + # which uses the defacto standard originally implemented by setuptools, + # as before all PEP 440 versions. + epoch = -1 + + # This scheme is taken from pkg_resources.parse_version setuptools prior to + # it's adoption of the packaging library. + parts: List[str] = [] + for part in _parse_version_parts(version.lower()): + if part.startswith("*"): + # remove "-" before a prerelease tag + if part < "*final": + while parts and parts[-1] == "*final-": + parts.pop() + + # remove trailing zeros from each series of numeric parts + while parts and parts[-1] == "00000000": + parts.pop() + + parts.append(part) + + return epoch, tuple(parts) + + +# Deliberately not anchored to the start and end of the string, to make it +# easier for 3rd party code to reuse +VERSION_PATTERN = r""" + v? + (?: + (?:(?P[0-9]+)!)? # epoch + (?P[0-9]+(?:\.[0-9]+)*) # release segment + (?P
                                              # pre-release
    +            [-_\.]?
    +            (?P(a|b|c|rc|alpha|beta|pre|preview))
    +            [-_\.]?
    +            (?P[0-9]+)?
    +        )?
    +        (?P                                         # post release
    +            (?:-(?P[0-9]+))
    +            |
    +            (?:
    +                [-_\.]?
    +                (?Ppost|rev|r)
    +                [-_\.]?
    +                (?P[0-9]+)?
    +            )
    +        )?
    +        (?P                                          # dev release
    +            [-_\.]?
    +            (?Pdev)
    +            [-_\.]?
    +            (?P[0-9]+)?
    +        )?
    +    )
    +    (?:\+(?P[a-z0-9]+(?:[-_\.][a-z0-9]+)*))?       # local version
    +"""
    +
    +
    +class Version(_BaseVersion):
    +
    +    _regex = re.compile(r"^\s*" + VERSION_PATTERN + r"\s*$", re.VERBOSE | re.IGNORECASE)
    +
    +    def __init__(self, version: str) -> None:
    +
    +        # Validate the version and parse it into pieces
    +        match = self._regex.search(version)
    +        if not match:
    +            raise InvalidVersion(f"Invalid version: '{version}'")
    +
    +        # Store the parsed out pieces of the version
    +        self._version = _Version(
    +            epoch=int(match.group("epoch")) if match.group("epoch") else 0,
    +            release=tuple(int(i) for i in match.group("release").split(".")),
    +            pre=_parse_letter_version(match.group("pre_l"), match.group("pre_n")),
    +            post=_parse_letter_version(
    +                match.group("post_l"), match.group("post_n1") or match.group("post_n2")
    +            ),
    +            dev=_parse_letter_version(match.group("dev_l"), match.group("dev_n")),
    +            local=_parse_local_version(match.group("local")),
    +        )
    +
    +        # Generate a key which will be used for sorting
    +        self._key = _cmpkey(
    +            self._version.epoch,
    +            self._version.release,
    +            self._version.pre,
    +            self._version.post,
    +            self._version.dev,
    +            self._version.local,
    +        )
    +
    +    def __repr__(self) -> str:
    +        return f""
    +
    +    def __str__(self) -> str:
    +        parts = []
    +
    +        # Epoch
    +        if self.epoch != 0:
    +            parts.append(f"{self.epoch}!")
    +
    +        # Release segment
    +        parts.append(".".join(str(x) for x in self.release))
    +
    +        # Pre-release
    +        if self.pre is not None:
    +            parts.append("".join(str(x) for x in self.pre))
    +
    +        # Post-release
    +        if self.post is not None:
    +            parts.append(f".post{self.post}")
    +
    +        # Development release
    +        if self.dev is not None:
    +            parts.append(f".dev{self.dev}")
    +
    +        # Local version segment
    +        if self.local is not None:
    +            parts.append(f"+{self.local}")
    +
    +        return "".join(parts)
    +
    +    @property
    +    def epoch(self) -> int:
    +        _epoch: int = self._version.epoch
    +        return _epoch
    +
    +    @property
    +    def release(self) -> Tuple[int, ...]:
    +        _release: Tuple[int, ...] = self._version.release
    +        return _release
    +
    +    @property
    +    def pre(self) -> Optional[Tuple[str, int]]:
    +        _pre: Optional[Tuple[str, int]] = self._version.pre
    +        return _pre
    +
    +    @property
    +    def post(self) -> Optional[int]:
    +        return self._version.post[1] if self._version.post else None
    +
    +    @property
    +    def dev(self) -> Optional[int]:
    +        return self._version.dev[1] if self._version.dev else None
    +
    +    @property
    +    def local(self) -> Optional[str]:
    +        if self._version.local:
    +            return ".".join(str(x) for x in self._version.local)
    +        else:
    +            return None
    +
    +    @property
    +    def public(self) -> str:
    +        return str(self).split("+", 1)[0]
    +
    +    @property
    +    def base_version(self) -> str:
    +        parts = []
    +
    +        # Epoch
    +        if self.epoch != 0:
    +            parts.append(f"{self.epoch}!")
    +
    +        # Release segment
    +        parts.append(".".join(str(x) for x in self.release))
    +
    +        return "".join(parts)
    +
    +    @property
    +    def is_prerelease(self) -> bool:
    +        return self.dev is not None or self.pre is not None
    +
    +    @property
    +    def is_postrelease(self) -> bool:
    +        return self.post is not None
    +
    +    @property
    +    def is_devrelease(self) -> bool:
    +        return self.dev is not None
    +
    +    @property
    +    def major(self) -> int:
    +        return self.release[0] if len(self.release) >= 1 else 0
    +
    +    @property
    +    def minor(self) -> int:
    +        return self.release[1] if len(self.release) >= 2 else 0
    +
    +    @property
    +    def micro(self) -> int:
    +        return self.release[2] if len(self.release) >= 3 else 0
    +
    +
    +def _parse_letter_version(
    +    letter: str, number: Union[str, bytes, SupportsInt]
    +) -> Optional[Tuple[str, int]]:
    +
    +    if letter:
    +        # We consider there to be an implicit 0 in a pre-release if there is
    +        # not a numeral associated with it.
    +        if number is None:
    +            number = 0
    +
    +        # We normalize any letters to their lower case form
    +        letter = letter.lower()
    +
    +        # We consider some words to be alternate spellings of other words and
    +        # in those cases we want to normalize the spellings to our preferred
    +        # spelling.
    +        if letter == "alpha":
    +            letter = "a"
    +        elif letter == "beta":
    +            letter = "b"
    +        elif letter in ["c", "pre", "preview"]:
    +            letter = "rc"
    +        elif letter in ["rev", "r"]:
    +            letter = "post"
    +
    +        return letter, int(number)
    +    if not letter and number:
    +        # We assume if we are given a number, but we are not given a letter
    +        # then this is using the implicit post release syntax (e.g. 1.0-1)
    +        letter = "post"
    +
    +        return letter, int(number)
    +
    +    return None
    +
    +
    +_local_version_separators = re.compile(r"[\._-]")
    +
    +
    +def _parse_local_version(local: str) -> Optional[LocalType]:
    +    """
    +    Takes a string like abc.1.twelve and turns it into ("abc", 1, "twelve").
    +    """
    +    if local is not None:
    +        return tuple(
    +            part.lower() if not part.isdigit() else int(part)
    +            for part in _local_version_separators.split(local)
    +        )
    +    return None
    +
    +
    +def _cmpkey(
    +    epoch: int,
    +    release: Tuple[int, ...],
    +    pre: Optional[Tuple[str, int]],
    +    post: Optional[Tuple[str, int]],
    +    dev: Optional[Tuple[str, int]],
    +    local: Optional[Tuple[SubLocalType]],
    +) -> CmpKey:
    +
    +    # When we compare a release version, we want to compare it with all of the
    +    # trailing zeros removed. So we'll use a reverse the list, drop all the now
    +    # leading zeros until we come to something non zero, then take the rest
    +    # re-reverse it back into the correct order and make it a tuple and use
    +    # that for our sorting key.
    +    _release = tuple(
    +        reversed(list(itertools.dropwhile(lambda x: x == 0, reversed(release))))
    +    )
    +
    +    # We need to "trick" the sorting algorithm to put 1.0.dev0 before 1.0a0.
    +    # We'll do this by abusing the pre segment, but we _only_ want to do this
    +    # if there is not a pre or a post segment. If we have one of those then
    +    # the normal sorting rules will handle this case correctly.
    +    if pre is None and post is None and dev is not None:
    +        _pre: PrePostDevType = NegativeInfinity
    +    # Versions without a pre-release (except as noted above) should sort after
    +    # those with one.
    +    elif pre is None:
    +        _pre = Infinity
    +    else:
    +        _pre = pre
    +
    +    # Versions without a post segment should sort before those with one.
    +    if post is None:
    +        _post: PrePostDevType = NegativeInfinity
    +
    +    else:
    +        _post = post
    +
    +    # Versions without a development segment should sort after those with one.
    +    if dev is None:
    +        _dev: PrePostDevType = Infinity
    +
    +    else:
    +        _dev = dev
    +
    +    if local is None:
    +        # Versions without a local segment should sort before those with one.
    +        _local: LocalType = NegativeInfinity
    +    else:
    +        # Versions with a local segment need that segment parsed to implement
    +        # the sorting rules in PEP440.
    +        # - Alpha numeric segments sort before numeric segments
    +        # - Alpha numeric segments sort lexicographically
    +        # - Numeric segments sort numerically
    +        # - Shorter versions sort before longer versions when the prefixes
    +        #   match exactly
    +        _local = tuple(
    +            (i, "") if isinstance(i, int) else (NegativeInfinity, i) for i in local
    +        )
    +
    +    return epoch, _release, _pre, _post, _dev, _local
    diff --git a/venv/Lib/site-packages/setuptools/_vendor/pyparsing.py b/venv/Lib/site-packages/setuptools/_vendor/pyparsing.py
    new file mode 100644
    index 0000000..4aa30ee
    --- /dev/null
    +++ b/venv/Lib/site-packages/setuptools/_vendor/pyparsing.py
    @@ -0,0 +1,5742 @@
    +# module pyparsing.py
    +#
    +# Copyright (c) 2003-2018  Paul T. McGuire
    +#
    +# 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.
    +#
    +
    +__doc__ = \
    +"""
    +pyparsing module - Classes and methods to define and execute parsing grammars
    +=============================================================================
    +
    +The pyparsing module is an alternative approach to creating and executing simple grammars,
    +vs. the traditional lex/yacc approach, or the use of regular expressions.  With pyparsing, you
    +don't need to learn a new syntax for defining grammars or matching expressions - the parsing module
    +provides a library of classes that you use to construct the grammar directly in Python.
    +
    +Here is a program to parse "Hello, World!" (or any greeting of the form 
    +C{", !"}), built up using L{Word}, L{Literal}, and L{And} elements 
    +(L{'+'} operator gives L{And} expressions, strings are auto-converted to
    +L{Literal} expressions)::
    +
    +    from pyparsing import Word, alphas
    +
    +    # define grammar of a greeting
    +    greet = Word(alphas) + "," + Word(alphas) + "!"
    +
    +    hello = "Hello, World!"
    +    print (hello, "->", greet.parseString(hello))
    +
    +The program outputs the following::
    +
    +    Hello, World! -> ['Hello', ',', 'World', '!']
    +
    +The Python representation of the grammar is quite readable, owing to the self-explanatory
    +class names, and the use of '+', '|' and '^' operators.
    +
    +The L{ParseResults} object returned from L{ParserElement.parseString} can be accessed as a nested list, a dictionary, or an
    +object with named attributes.
    +
    +The pyparsing module handles some of the problems that are typically vexing when writing text parsers:
    + - extra or missing whitespace (the above program will also handle "Hello,World!", "Hello  ,  World  !", etc.)
    + - quoted strings
    + - embedded comments
    +
    +
    +Getting Started -
    +-----------------
    +Visit the classes L{ParserElement} and L{ParseResults} to see the base classes that most other pyparsing
    +classes inherit from. Use the docstrings for examples of how to:
    + - construct literal match expressions from L{Literal} and L{CaselessLiteral} classes
    + - construct character word-group expressions using the L{Word} class
    + - see how to create repetitive expressions using L{ZeroOrMore} and L{OneOrMore} classes
    + - use L{'+'}, L{'|'}, L{'^'}, and L{'&'} operators to combine simple expressions into more complex ones
    + - associate names with your parsed results using L{ParserElement.setResultsName}
    + - find some helpful expression short-cuts like L{delimitedList} and L{oneOf}
    + - find more useful common expressions in the L{pyparsing_common} namespace class
    +"""
    +
    +__version__ = "2.2.1"
    +__versionTime__ = "18 Sep 2018 00:49 UTC"
    +__author__ = "Paul McGuire "
    +
    +import string
    +from weakref import ref as wkref
    +import copy
    +import sys
    +import warnings
    +import re
    +import sre_constants
    +import collections
    +import pprint
    +import traceback
    +import types
    +from datetime import datetime
    +
    +try:
    +    from _thread import RLock
    +except ImportError:
    +    from threading import RLock
    +
    +try:
    +    # Python 3
    +    from collections.abc import Iterable
    +    from collections.abc import MutableMapping
    +except ImportError:
    +    # Python 2.7
    +    from collections import Iterable
    +    from collections import MutableMapping
    +
    +try:
    +    from collections import OrderedDict as _OrderedDict
    +except ImportError:
    +    try:
    +        from ordereddict import OrderedDict as _OrderedDict
    +    except ImportError:
    +        _OrderedDict = None
    +
    +#~ sys.stderr.write( "testing pyparsing module, version %s, %s\n" % (__version__,__versionTime__ ) )
    +
    +__all__ = [
    +'And', 'CaselessKeyword', 'CaselessLiteral', 'CharsNotIn', 'Combine', 'Dict', 'Each', 'Empty',
    +'FollowedBy', 'Forward', 'GoToColumn', 'Group', 'Keyword', 'LineEnd', 'LineStart', 'Literal',
    +'MatchFirst', 'NoMatch', 'NotAny', 'OneOrMore', 'OnlyOnce', 'Optional', 'Or',
    +'ParseBaseException', 'ParseElementEnhance', 'ParseException', 'ParseExpression', 'ParseFatalException',
    +'ParseResults', 'ParseSyntaxException', 'ParserElement', 'QuotedString', 'RecursiveGrammarException',
    +'Regex', 'SkipTo', 'StringEnd', 'StringStart', 'Suppress', 'Token', 'TokenConverter', 
    +'White', 'Word', 'WordEnd', 'WordStart', 'ZeroOrMore',
    +'alphanums', 'alphas', 'alphas8bit', 'anyCloseTag', 'anyOpenTag', 'cStyleComment', 'col',
    +'commaSeparatedList', 'commonHTMLEntity', 'countedArray', 'cppStyleComment', 'dblQuotedString',
    +'dblSlashComment', 'delimitedList', 'dictOf', 'downcaseTokens', 'empty', 'hexnums',
    +'htmlComment', 'javaStyleComment', 'line', 'lineEnd', 'lineStart', 'lineno',
    +'makeHTMLTags', 'makeXMLTags', 'matchOnlyAtCol', 'matchPreviousExpr', 'matchPreviousLiteral',
    +'nestedExpr', 'nullDebugAction', 'nums', 'oneOf', 'opAssoc', 'operatorPrecedence', 'printables',
    +'punc8bit', 'pythonStyleComment', 'quotedString', 'removeQuotes', 'replaceHTMLEntity', 
    +'replaceWith', 'restOfLine', 'sglQuotedString', 'srange', 'stringEnd',
    +'stringStart', 'traceParseAction', 'unicodeString', 'upcaseTokens', 'withAttribute',
    +'indentedBlock', 'originalTextFor', 'ungroup', 'infixNotation','locatedExpr', 'withClass',
    +'CloseMatch', 'tokenMap', 'pyparsing_common',
    +]
    +
    +system_version = tuple(sys.version_info)[:3]
    +PY_3 = system_version[0] == 3
    +if PY_3:
    +    _MAX_INT = sys.maxsize
    +    basestring = str
    +    unichr = chr
    +    _ustr = str
    +
    +    # build list of single arg builtins, that can be used as parse actions
    +    singleArgBuiltins = [sum, len, sorted, reversed, list, tuple, set, any, all, min, max]
    +
    +else:
    +    _MAX_INT = sys.maxint
    +    range = xrange
    +
    +    def _ustr(obj):
    +        """Drop-in replacement for str(obj) that tries to be Unicode friendly. It first tries
    +           str(obj). If that fails with a UnicodeEncodeError, then it tries unicode(obj). It
    +           then < returns the unicode object | encodes it with the default encoding | ... >.
    +        """
    +        if isinstance(obj,unicode):
    +            return obj
    +
    +        try:
    +            # If this works, then _ustr(obj) has the same behaviour as str(obj), so
    +            # it won't break any existing code.
    +            return str(obj)
    +
    +        except UnicodeEncodeError:
    +            # Else encode it
    +            ret = unicode(obj).encode(sys.getdefaultencoding(), 'xmlcharrefreplace')
    +            xmlcharref = Regex(r'&#\d+;')
    +            xmlcharref.setParseAction(lambda t: '\\u' + hex(int(t[0][2:-1]))[2:])
    +            return xmlcharref.transformString(ret)
    +
    +    # build list of single arg builtins, tolerant of Python version, that can be used as parse actions
    +    singleArgBuiltins = []
    +    import __builtin__
    +    for fname in "sum len sorted reversed list tuple set any all min max".split():
    +        try:
    +            singleArgBuiltins.append(getattr(__builtin__,fname))
    +        except AttributeError:
    +            continue
    +            
    +_generatorType = type((y for y in range(1)))
    + 
    +def _xml_escape(data):
    +    """Escape &, <, >, ", ', etc. in a string of data."""
    +
    +    # ampersand must be replaced first
    +    from_symbols = '&><"\''
    +    to_symbols = ('&'+s+';' for s in "amp gt lt quot apos".split())
    +    for from_,to_ in zip(from_symbols, to_symbols):
    +        data = data.replace(from_, to_)
    +    return data
    +
    +class _Constants(object):
    +    pass
    +
    +alphas     = string.ascii_uppercase + string.ascii_lowercase
    +nums       = "0123456789"
    +hexnums    = nums + "ABCDEFabcdef"
    +alphanums  = alphas + nums
    +_bslash    = chr(92)
    +printables = "".join(c for c in string.printable if c not in string.whitespace)
    +
    +class ParseBaseException(Exception):
    +    """base exception class for all parsing runtime exceptions"""
    +    # Performance tuning: we construct a *lot* of these, so keep this
    +    # constructor as small and fast as possible
    +    def __init__( self, pstr, loc=0, msg=None, elem=None ):
    +        self.loc = loc
    +        if msg is None:
    +            self.msg = pstr
    +            self.pstr = ""
    +        else:
    +            self.msg = msg
    +            self.pstr = pstr
    +        self.parserElement = elem
    +        self.args = (pstr, loc, msg)
    +
    +    @classmethod
    +    def _from_exception(cls, pe):
    +        """
    +        internal factory method to simplify creating one type of ParseException 
    +        from another - avoids having __init__ signature conflicts among subclasses
    +        """
    +        return cls(pe.pstr, pe.loc, pe.msg, pe.parserElement)
    +
    +    def __getattr__( self, aname ):
    +        """supported attributes by name are:
    +            - lineno - returns the line number of the exception text
    +            - col - returns the column number of the exception text
    +            - line - returns the line containing the exception text
    +        """
    +        if( aname == "lineno" ):
    +            return lineno( self.loc, self.pstr )
    +        elif( aname in ("col", "column") ):
    +            return col( self.loc, self.pstr )
    +        elif( aname == "line" ):
    +            return line( self.loc, self.pstr )
    +        else:
    +            raise AttributeError(aname)
    +
    +    def __str__( self ):
    +        return "%s (at char %d), (line:%d, col:%d)" % \
    +                ( self.msg, self.loc, self.lineno, self.column )
    +    def __repr__( self ):
    +        return _ustr(self)
    +    def markInputline( self, markerString = ">!<" ):
    +        """Extracts the exception line from the input string, and marks
    +           the location of the exception with a special symbol.
    +        """
    +        line_str = self.line
    +        line_column = self.column - 1
    +        if markerString:
    +            line_str = "".join((line_str[:line_column],
    +                                markerString, line_str[line_column:]))
    +        return line_str.strip()
    +    def __dir__(self):
    +        return "lineno col line".split() + dir(type(self))
    +
    +class ParseException(ParseBaseException):
    +    """
    +    Exception thrown when parse expressions don't match class;
    +    supported attributes by name are:
    +     - lineno - returns the line number of the exception text
    +     - col - returns the column number of the exception text
    +     - line - returns the line containing the exception text
    +        
    +    Example::
    +        try:
    +            Word(nums).setName("integer").parseString("ABC")
    +        except ParseException as pe:
    +            print(pe)
    +            print("column: {}".format(pe.col))
    +            
    +    prints::
    +       Expected integer (at char 0), (line:1, col:1)
    +        column: 1
    +    """
    +    pass
    +
    +class ParseFatalException(ParseBaseException):
    +    """user-throwable exception thrown when inconsistent parse content
    +       is found; stops all parsing immediately"""
    +    pass
    +
    +class ParseSyntaxException(ParseFatalException):
    +    """just like L{ParseFatalException}, but thrown internally when an
    +       L{ErrorStop} ('-' operator) indicates that parsing is to stop 
    +       immediately because an unbacktrackable syntax error has been found"""
    +    pass
    +
    +#~ class ReparseException(ParseBaseException):
    +    #~ """Experimental class - parse actions can raise this exception to cause
    +       #~ pyparsing to reparse the input string:
    +        #~ - with a modified input string, and/or
    +        #~ - with a modified start location
    +       #~ Set the values of the ReparseException in the constructor, and raise the
    +       #~ exception in a parse action to cause pyparsing to use the new string/location.
    +       #~ Setting the values as None causes no change to be made.
    +       #~ """
    +    #~ def __init_( self, newstring, restartLoc ):
    +        #~ self.newParseText = newstring
    +        #~ self.reparseLoc = restartLoc
    +
    +class RecursiveGrammarException(Exception):
    +    """exception thrown by L{ParserElement.validate} if the grammar could be improperly recursive"""
    +    def __init__( self, parseElementList ):
    +        self.parseElementTrace = parseElementList
    +
    +    def __str__( self ):
    +        return "RecursiveGrammarException: %s" % self.parseElementTrace
    +
    +class _ParseResultsWithOffset(object):
    +    def __init__(self,p1,p2):
    +        self.tup = (p1,p2)
    +    def __getitem__(self,i):
    +        return self.tup[i]
    +    def __repr__(self):
    +        return repr(self.tup[0])
    +    def setOffset(self,i):
    +        self.tup = (self.tup[0],i)
    +
    +class ParseResults(object):
    +    """
    +    Structured parse results, to provide multiple means of access to the parsed data:
    +       - as a list (C{len(results)})
    +       - by list index (C{results[0], results[1]}, etc.)
    +       - by attribute (C{results.} - see L{ParserElement.setResultsName})
    +
    +    Example::
    +        integer = Word(nums)
    +        date_str = (integer.setResultsName("year") + '/' 
    +                        + integer.setResultsName("month") + '/' 
    +                        + integer.setResultsName("day"))
    +        # equivalent form:
    +        # date_str = integer("year") + '/' + integer("month") + '/' + integer("day")
    +
    +        # parseString returns a ParseResults object
    +        result = date_str.parseString("1999/12/31")
    +
    +        def test(s, fn=repr):
    +            print("%s -> %s" % (s, fn(eval(s))))
    +        test("list(result)")
    +        test("result[0]")
    +        test("result['month']")
    +        test("result.day")
    +        test("'month' in result")
    +        test("'minutes' in result")
    +        test("result.dump()", str)
    +    prints::
    +        list(result) -> ['1999', '/', '12', '/', '31']
    +        result[0] -> '1999'
    +        result['month'] -> '12'
    +        result.day -> '31'
    +        'month' in result -> True
    +        'minutes' in result -> False
    +        result.dump() -> ['1999', '/', '12', '/', '31']
    +        - day: 31
    +        - month: 12
    +        - year: 1999
    +    """
    +    def __new__(cls, toklist=None, name=None, asList=True, modal=True ):
    +        if isinstance(toklist, cls):
    +            return toklist
    +        retobj = object.__new__(cls)
    +        retobj.__doinit = True
    +        return retobj
    +
    +    # Performance tuning: we construct a *lot* of these, so keep this
    +    # constructor as small and fast as possible
    +    def __init__( self, toklist=None, name=None, asList=True, modal=True, isinstance=isinstance ):
    +        if self.__doinit:
    +            self.__doinit = False
    +            self.__name = None
    +            self.__parent = None
    +            self.__accumNames = {}
    +            self.__asList = asList
    +            self.__modal = modal
    +            if toklist is None:
    +                toklist = []
    +            if isinstance(toklist, list):
    +                self.__toklist = toklist[:]
    +            elif isinstance(toklist, _generatorType):
    +                self.__toklist = list(toklist)
    +            else:
    +                self.__toklist = [toklist]
    +            self.__tokdict = dict()
    +
    +        if name is not None and name:
    +            if not modal:
    +                self.__accumNames[name] = 0
    +            if isinstance(name,int):
    +                name = _ustr(name) # will always return a str, but use _ustr for consistency
    +            self.__name = name
    +            if not (isinstance(toklist, (type(None), basestring, list)) and toklist in (None,'',[])):
    +                if isinstance(toklist,basestring):
    +                    toklist = [ toklist ]
    +                if asList:
    +                    if isinstance(toklist,ParseResults):
    +                        self[name] = _ParseResultsWithOffset(toklist.copy(),0)
    +                    else:
    +                        self[name] = _ParseResultsWithOffset(ParseResults(toklist[0]),0)
    +                    self[name].__name = name
    +                else:
    +                    try:
    +                        self[name] = toklist[0]
    +                    except (KeyError,TypeError,IndexError):
    +                        self[name] = toklist
    +
    +    def __getitem__( self, i ):
    +        if isinstance( i, (int,slice) ):
    +            return self.__toklist[i]
    +        else:
    +            if i not in self.__accumNames:
    +                return self.__tokdict[i][-1][0]
    +            else:
    +                return ParseResults([ v[0] for v in self.__tokdict[i] ])
    +
    +    def __setitem__( self, k, v, isinstance=isinstance ):
    +        if isinstance(v,_ParseResultsWithOffset):
    +            self.__tokdict[k] = self.__tokdict.get(k,list()) + [v]
    +            sub = v[0]
    +        elif isinstance(k,(int,slice)):
    +            self.__toklist[k] = v
    +            sub = v
    +        else:
    +            self.__tokdict[k] = self.__tokdict.get(k,list()) + [_ParseResultsWithOffset(v,0)]
    +            sub = v
    +        if isinstance(sub,ParseResults):
    +            sub.__parent = wkref(self)
    +
    +    def __delitem__( self, i ):
    +        if isinstance(i,(int,slice)):
    +            mylen = len( self.__toklist )
    +            del self.__toklist[i]
    +
    +            # convert int to slice
    +            if isinstance(i, int):
    +                if i < 0:
    +                    i += mylen
    +                i = slice(i, i+1)
    +            # get removed indices
    +            removed = list(range(*i.indices(mylen)))
    +            removed.reverse()
    +            # fixup indices in token dictionary
    +            for name,occurrences in self.__tokdict.items():
    +                for j in removed:
    +                    for k, (value, position) in enumerate(occurrences):
    +                        occurrences[k] = _ParseResultsWithOffset(value, position - (position > j))
    +        else:
    +            del self.__tokdict[i]
    +
    +    def __contains__( self, k ):
    +        return k in self.__tokdict
    +
    +    def __len__( self ): return len( self.__toklist )
    +    def __bool__(self): return ( not not self.__toklist )
    +    __nonzero__ = __bool__
    +    def __iter__( self ): return iter( self.__toklist )
    +    def __reversed__( self ): return iter( self.__toklist[::-1] )
    +    def _iterkeys( self ):
    +        if hasattr(self.__tokdict, "iterkeys"):
    +            return self.__tokdict.iterkeys()
    +        else:
    +            return iter(self.__tokdict)
    +
    +    def _itervalues( self ):
    +        return (self[k] for k in self._iterkeys())
    +            
    +    def _iteritems( self ):
    +        return ((k, self[k]) for k in self._iterkeys())
    +
    +    if PY_3:
    +        keys = _iterkeys       
    +        """Returns an iterator of all named result keys (Python 3.x only)."""
    +
    +        values = _itervalues
    +        """Returns an iterator of all named result values (Python 3.x only)."""
    +
    +        items = _iteritems
    +        """Returns an iterator of all named result key-value tuples (Python 3.x only)."""
    +
    +    else:
    +        iterkeys = _iterkeys
    +        """Returns an iterator of all named result keys (Python 2.x only)."""
    +
    +        itervalues = _itervalues
    +        """Returns an iterator of all named result values (Python 2.x only)."""
    +
    +        iteritems = _iteritems
    +        """Returns an iterator of all named result key-value tuples (Python 2.x only)."""
    +
    +        def keys( self ):
    +            """Returns all named result keys (as a list in Python 2.x, as an iterator in Python 3.x)."""
    +            return list(self.iterkeys())
    +
    +        def values( self ):
    +            """Returns all named result values (as a list in Python 2.x, as an iterator in Python 3.x)."""
    +            return list(self.itervalues())
    +                
    +        def items( self ):
    +            """Returns all named result key-values (as a list of tuples in Python 2.x, as an iterator in Python 3.x)."""
    +            return list(self.iteritems())
    +
    +    def haskeys( self ):
    +        """Since keys() returns an iterator, this method is helpful in bypassing
    +           code that looks for the existence of any defined results names."""
    +        return bool(self.__tokdict)
    +        
    +    def pop( self, *args, **kwargs):
    +        """
    +        Removes and returns item at specified index (default=C{last}).
    +        Supports both C{list} and C{dict} semantics for C{pop()}. If passed no
    +        argument or an integer argument, it will use C{list} semantics
    +        and pop tokens from the list of parsed tokens. If passed a 
    +        non-integer argument (most likely a string), it will use C{dict}
    +        semantics and pop the corresponding value from any defined 
    +        results names. A second default return value argument is 
    +        supported, just as in C{dict.pop()}.
    +
    +        Example::
    +            def remove_first(tokens):
    +                tokens.pop(0)
    +            print(OneOrMore(Word(nums)).parseString("0 123 321")) # -> ['0', '123', '321']
    +            print(OneOrMore(Word(nums)).addParseAction(remove_first).parseString("0 123 321")) # -> ['123', '321']
    +
    +            label = Word(alphas)
    +            patt = label("LABEL") + OneOrMore(Word(nums))
    +            print(patt.parseString("AAB 123 321").dump())
    +
    +            # Use pop() in a parse action to remove named result (note that corresponding value is not
    +            # removed from list form of results)
    +            def remove_LABEL(tokens):
    +                tokens.pop("LABEL")
    +                return tokens
    +            patt.addParseAction(remove_LABEL)
    +            print(patt.parseString("AAB 123 321").dump())
    +        prints::
    +            ['AAB', '123', '321']
    +            - LABEL: AAB
    +
    +            ['AAB', '123', '321']
    +        """
    +        if not args:
    +            args = [-1]
    +        for k,v in kwargs.items():
    +            if k == 'default':
    +                args = (args[0], v)
    +            else:
    +                raise TypeError("pop() got an unexpected keyword argument '%s'" % k)
    +        if (isinstance(args[0], int) or 
    +                        len(args) == 1 or 
    +                        args[0] in self):
    +            index = args[0]
    +            ret = self[index]
    +            del self[index]
    +            return ret
    +        else:
    +            defaultvalue = args[1]
    +            return defaultvalue
    +
    +    def get(self, key, defaultValue=None):
    +        """
    +        Returns named result matching the given key, or if there is no
    +        such name, then returns the given C{defaultValue} or C{None} if no
    +        C{defaultValue} is specified.
    +
    +        Similar to C{dict.get()}.
    +        
    +        Example::
    +            integer = Word(nums)
    +            date_str = integer("year") + '/' + integer("month") + '/' + integer("day")           
    +
    +            result = date_str.parseString("1999/12/31")
    +            print(result.get("year")) # -> '1999'
    +            print(result.get("hour", "not specified")) # -> 'not specified'
    +            print(result.get("hour")) # -> None
    +        """
    +        if key in self:
    +            return self[key]
    +        else:
    +            return defaultValue
    +
    +    def insert( self, index, insStr ):
    +        """
    +        Inserts new element at location index in the list of parsed tokens.
    +        
    +        Similar to C{list.insert()}.
    +
    +        Example::
    +            print(OneOrMore(Word(nums)).parseString("0 123 321")) # -> ['0', '123', '321']
    +
    +            # use a parse action to insert the parse location in the front of the parsed results
    +            def insert_locn(locn, tokens):
    +                tokens.insert(0, locn)
    +            print(OneOrMore(Word(nums)).addParseAction(insert_locn).parseString("0 123 321")) # -> [0, '0', '123', '321']
    +        """
    +        self.__toklist.insert(index, insStr)
    +        # fixup indices in token dictionary
    +        for name,occurrences in self.__tokdict.items():
    +            for k, (value, position) in enumerate(occurrences):
    +                occurrences[k] = _ParseResultsWithOffset(value, position + (position > index))
    +
    +    def append( self, item ):
    +        """
    +        Add single element to end of ParseResults list of elements.
    +
    +        Example::
    +            print(OneOrMore(Word(nums)).parseString("0 123 321")) # -> ['0', '123', '321']
    +            
    +            # use a parse action to compute the sum of the parsed integers, and add it to the end
    +            def append_sum(tokens):
    +                tokens.append(sum(map(int, tokens)))
    +            print(OneOrMore(Word(nums)).addParseAction(append_sum).parseString("0 123 321")) # -> ['0', '123', '321', 444]
    +        """
    +        self.__toklist.append(item)
    +
    +    def extend( self, itemseq ):
    +        """
    +        Add sequence of elements to end of ParseResults list of elements.
    +
    +        Example::
    +            patt = OneOrMore(Word(alphas))
    +            
    +            # use a parse action to append the reverse of the matched strings, to make a palindrome
    +            def make_palindrome(tokens):
    +                tokens.extend(reversed([t[::-1] for t in tokens]))
    +                return ''.join(tokens)
    +            print(patt.addParseAction(make_palindrome).parseString("lskdj sdlkjf lksd")) # -> 'lskdjsdlkjflksddsklfjkldsjdksl'
    +        """
    +        if isinstance(itemseq, ParseResults):
    +            self += itemseq
    +        else:
    +            self.__toklist.extend(itemseq)
    +
    +    def clear( self ):
    +        """
    +        Clear all elements and results names.
    +        """
    +        del self.__toklist[:]
    +        self.__tokdict.clear()
    +
    +    def __getattr__( self, name ):
    +        try:
    +            return self[name]
    +        except KeyError:
    +            return ""
    +            
    +        if name in self.__tokdict:
    +            if name not in self.__accumNames:
    +                return self.__tokdict[name][-1][0]
    +            else:
    +                return ParseResults([ v[0] for v in self.__tokdict[name] ])
    +        else:
    +            return ""
    +
    +    def __add__( self, other ):
    +        ret = self.copy()
    +        ret += other
    +        return ret
    +
    +    def __iadd__( self, other ):
    +        if other.__tokdict:
    +            offset = len(self.__toklist)
    +            addoffset = lambda a: offset if a<0 else a+offset
    +            otheritems = other.__tokdict.items()
    +            otherdictitems = [(k, _ParseResultsWithOffset(v[0],addoffset(v[1])) )
    +                                for (k,vlist) in otheritems for v in vlist]
    +            for k,v in otherdictitems:
    +                self[k] = v
    +                if isinstance(v[0],ParseResults):
    +                    v[0].__parent = wkref(self)
    +            
    +        self.__toklist += other.__toklist
    +        self.__accumNames.update( other.__accumNames )
    +        return self
    +
    +    def __radd__(self, other):
    +        if isinstance(other,int) and other == 0:
    +            # useful for merging many ParseResults using sum() builtin
    +            return self.copy()
    +        else:
    +            # this may raise a TypeError - so be it
    +            return other + self
    +        
    +    def __repr__( self ):
    +        return "(%s, %s)" % ( repr( self.__toklist ), repr( self.__tokdict ) )
    +
    +    def __str__( self ):
    +        return '[' + ', '.join(_ustr(i) if isinstance(i, ParseResults) else repr(i) for i in self.__toklist) + ']'
    +
    +    def _asStringList( self, sep='' ):
    +        out = []
    +        for item in self.__toklist:
    +            if out and sep:
    +                out.append(sep)
    +            if isinstance( item, ParseResults ):
    +                out += item._asStringList()
    +            else:
    +                out.append( _ustr(item) )
    +        return out
    +
    +    def asList( self ):
    +        """
    +        Returns the parse results as a nested list of matching tokens, all converted to strings.
    +
    +        Example::
    +            patt = OneOrMore(Word(alphas))
    +            result = patt.parseString("sldkj lsdkj sldkj")
    +            # even though the result prints in string-like form, it is actually a pyparsing ParseResults
    +            print(type(result), result) # ->  ['sldkj', 'lsdkj', 'sldkj']
    +            
    +            # Use asList() to create an actual list
    +            result_list = result.asList()
    +            print(type(result_list), result_list) # ->  ['sldkj', 'lsdkj', 'sldkj']
    +        """
    +        return [res.asList() if isinstance(res,ParseResults) else res for res in self.__toklist]
    +
    +    def asDict( self ):
    +        """
    +        Returns the named parse results as a nested dictionary.
    +
    +        Example::
    +            integer = Word(nums)
    +            date_str = integer("year") + '/' + integer("month") + '/' + integer("day")
    +            
    +            result = date_str.parseString('12/31/1999')
    +            print(type(result), repr(result)) # ->  (['12', '/', '31', '/', '1999'], {'day': [('1999', 4)], 'year': [('12', 0)], 'month': [('31', 2)]})
    +            
    +            result_dict = result.asDict()
    +            print(type(result_dict), repr(result_dict)) # ->  {'day': '1999', 'year': '12', 'month': '31'}
    +
    +            # even though a ParseResults supports dict-like access, sometime you just need to have a dict
    +            import json
    +            print(json.dumps(result)) # -> Exception: TypeError: ... is not JSON serializable
    +            print(json.dumps(result.asDict())) # -> {"month": "31", "day": "1999", "year": "12"}
    +        """
    +        if PY_3:
    +            item_fn = self.items
    +        else:
    +            item_fn = self.iteritems
    +            
    +        def toItem(obj):
    +            if isinstance(obj, ParseResults):
    +                if obj.haskeys():
    +                    return obj.asDict()
    +                else:
    +                    return [toItem(v) for v in obj]
    +            else:
    +                return obj
    +                
    +        return dict((k,toItem(v)) for k,v in item_fn())
    +
    +    def copy( self ):
    +        """
    +        Returns a new copy of a C{ParseResults} object.
    +        """
    +        ret = ParseResults( self.__toklist )
    +        ret.__tokdict = self.__tokdict.copy()
    +        ret.__parent = self.__parent
    +        ret.__accumNames.update( self.__accumNames )
    +        ret.__name = self.__name
    +        return ret
    +
    +    def asXML( self, doctag=None, namedItemsOnly=False, indent="", formatted=True ):
    +        """
    +        (Deprecated) Returns the parse results as XML. Tags are created for tokens and lists that have defined results names.
    +        """
    +        nl = "\n"
    +        out = []
    +        namedItems = dict((v[1],k) for (k,vlist) in self.__tokdict.items()
    +                                                            for v in vlist)
    +        nextLevelIndent = indent + "  "
    +
    +        # collapse out indents if formatting is not desired
    +        if not formatted:
    +            indent = ""
    +            nextLevelIndent = ""
    +            nl = ""
    +
    +        selfTag = None
    +        if doctag is not None:
    +            selfTag = doctag
    +        else:
    +            if self.__name:
    +                selfTag = self.__name
    +
    +        if not selfTag:
    +            if namedItemsOnly:
    +                return ""
    +            else:
    +                selfTag = "ITEM"
    +
    +        out += [ nl, indent, "<", selfTag, ">" ]
    +
    +        for i,res in enumerate(self.__toklist):
    +            if isinstance(res,ParseResults):
    +                if i in namedItems:
    +                    out += [ res.asXML(namedItems[i],
    +                                        namedItemsOnly and doctag is None,
    +                                        nextLevelIndent,
    +                                        formatted)]
    +                else:
    +                    out += [ res.asXML(None,
    +                                        namedItemsOnly and doctag is None,
    +                                        nextLevelIndent,
    +                                        formatted)]
    +            else:
    +                # individual token, see if there is a name for it
    +                resTag = None
    +                if i in namedItems:
    +                    resTag = namedItems[i]
    +                if not resTag:
    +                    if namedItemsOnly:
    +                        continue
    +                    else:
    +                        resTag = "ITEM"
    +                xmlBodyText = _xml_escape(_ustr(res))
    +                out += [ nl, nextLevelIndent, "<", resTag, ">",
    +                                                xmlBodyText,
    +                                                "" ]
    +
    +        out += [ nl, indent, "" ]
    +        return "".join(out)
    +
    +    def __lookup(self,sub):
    +        for k,vlist in self.__tokdict.items():
    +            for v,loc in vlist:
    +                if sub is v:
    +                    return k
    +        return None
    +
    +    def getName(self):
    +        r"""
    +        Returns the results name for this token expression. Useful when several 
    +        different expressions might match at a particular location.
    +
    +        Example::
    +            integer = Word(nums)
    +            ssn_expr = Regex(r"\d\d\d-\d\d-\d\d\d\d")
    +            house_number_expr = Suppress('#') + Word(nums, alphanums)
    +            user_data = (Group(house_number_expr)("house_number") 
    +                        | Group(ssn_expr)("ssn")
    +                        | Group(integer)("age"))
    +            user_info = OneOrMore(user_data)
    +            
    +            result = user_info.parseString("22 111-22-3333 #221B")
    +            for item in result:
    +                print(item.getName(), ':', item[0])
    +        prints::
    +            age : 22
    +            ssn : 111-22-3333
    +            house_number : 221B
    +        """
    +        if self.__name:
    +            return self.__name
    +        elif self.__parent:
    +            par = self.__parent()
    +            if par:
    +                return par.__lookup(self)
    +            else:
    +                return None
    +        elif (len(self) == 1 and
    +               len(self.__tokdict) == 1 and
    +               next(iter(self.__tokdict.values()))[0][1] in (0,-1)):
    +            return next(iter(self.__tokdict.keys()))
    +        else:
    +            return None
    +
    +    def dump(self, indent='', depth=0, full=True):
    +        """
    +        Diagnostic method for listing out the contents of a C{ParseResults}.
    +        Accepts an optional C{indent} argument so that this string can be embedded
    +        in a nested display of other data.
    +
    +        Example::
    +            integer = Word(nums)
    +            date_str = integer("year") + '/' + integer("month") + '/' + integer("day")
    +            
    +            result = date_str.parseString('12/31/1999')
    +            print(result.dump())
    +        prints::
    +            ['12', '/', '31', '/', '1999']
    +            - day: 1999
    +            - month: 31
    +            - year: 12
    +        """
    +        out = []
    +        NL = '\n'
    +        out.append( indent+_ustr(self.asList()) )
    +        if full:
    +            if self.haskeys():
    +                items = sorted((str(k), v) for k,v in self.items())
    +                for k,v in items:
    +                    if out:
    +                        out.append(NL)
    +                    out.append( "%s%s- %s: " % (indent,('  '*depth), k) )
    +                    if isinstance(v,ParseResults):
    +                        if v:
    +                            out.append( v.dump(indent,depth+1) )
    +                        else:
    +                            out.append(_ustr(v))
    +                    else:
    +                        out.append(repr(v))
    +            elif any(isinstance(vv,ParseResults) for vv in self):
    +                v = self
    +                for i,vv in enumerate(v):
    +                    if isinstance(vv,ParseResults):
    +                        out.append("\n%s%s[%d]:\n%s%s%s" % (indent,('  '*(depth)),i,indent,('  '*(depth+1)),vv.dump(indent,depth+1) ))
    +                    else:
    +                        out.append("\n%s%s[%d]:\n%s%s%s" % (indent,('  '*(depth)),i,indent,('  '*(depth+1)),_ustr(vv)))
    +            
    +        return "".join(out)
    +
    +    def pprint(self, *args, **kwargs):
    +        """
    +        Pretty-printer for parsed results as a list, using the C{pprint} module.
    +        Accepts additional positional or keyword args as defined for the 
    +        C{pprint.pprint} method. (U{http://docs.python.org/3/library/pprint.html#pprint.pprint})
    +
    +        Example::
    +            ident = Word(alphas, alphanums)
    +            num = Word(nums)
    +            func = Forward()
    +            term = ident | num | Group('(' + func + ')')
    +            func <<= ident + Group(Optional(delimitedList(term)))
    +            result = func.parseString("fna a,b,(fnb c,d,200),100")
    +            result.pprint(width=40)
    +        prints::
    +            ['fna',
    +             ['a',
    +              'b',
    +              ['(', 'fnb', ['c', 'd', '200'], ')'],
    +              '100']]
    +        """
    +        pprint.pprint(self.asList(), *args, **kwargs)
    +
    +    # add support for pickle protocol
    +    def __getstate__(self):
    +        return ( self.__toklist,
    +                 ( self.__tokdict.copy(),
    +                   self.__parent is not None and self.__parent() or None,
    +                   self.__accumNames,
    +                   self.__name ) )
    +
    +    def __setstate__(self,state):
    +        self.__toklist = state[0]
    +        (self.__tokdict,
    +         par,
    +         inAccumNames,
    +         self.__name) = state[1]
    +        self.__accumNames = {}
    +        self.__accumNames.update(inAccumNames)
    +        if par is not None:
    +            self.__parent = wkref(par)
    +        else:
    +            self.__parent = None
    +
    +    def __getnewargs__(self):
    +        return self.__toklist, self.__name, self.__asList, self.__modal
    +
    +    def __dir__(self):
    +        return (dir(type(self)) + list(self.keys()))
    +
    +MutableMapping.register(ParseResults)
    +
    +def col (loc,strg):
    +    """Returns current column within a string, counting newlines as line separators.
    +   The first column is number 1.
    +
    +   Note: the default parsing behavior is to expand tabs in the input string
    +   before starting the parsing process.  See L{I{ParserElement.parseString}} for more information
    +   on parsing strings containing C{}s, and suggested methods to maintain a
    +   consistent view of the parsed string, the parse location, and line and column
    +   positions within the parsed string.
    +   """
    +    s = strg
    +    return 1 if 0} for more information
    +   on parsing strings containing C{}s, and suggested methods to maintain a
    +   consistent view of the parsed string, the parse location, and line and column
    +   positions within the parsed string.
    +   """
    +    return strg.count("\n",0,loc) + 1
    +
    +def line( loc, strg ):
    +    """Returns the line of text containing loc within a string, counting newlines as line separators.
    +       """
    +    lastCR = strg.rfind("\n", 0, loc)
    +    nextCR = strg.find("\n", loc)
    +    if nextCR >= 0:
    +        return strg[lastCR+1:nextCR]
    +    else:
    +        return strg[lastCR+1:]
    +
    +def _defaultStartDebugAction( instring, loc, expr ):
    +    print (("Match " + _ustr(expr) + " at loc " + _ustr(loc) + "(%d,%d)" % ( lineno(loc,instring), col(loc,instring) )))
    +
    +def _defaultSuccessDebugAction( instring, startloc, endloc, expr, toks ):
    +    print ("Matched " + _ustr(expr) + " -> " + str(toks.asList()))
    +
    +def _defaultExceptionDebugAction( instring, loc, expr, exc ):
    +    print ("Exception raised:" + _ustr(exc))
    +
    +def nullDebugAction(*args):
    +    """'Do-nothing' debug action, to suppress debugging output during parsing."""
    +    pass
    +
    +# Only works on Python 3.x - nonlocal is toxic to Python 2 installs
    +#~ 'decorator to trim function calls to match the arity of the target'
    +#~ def _trim_arity(func, maxargs=3):
    +    #~ if func in singleArgBuiltins:
    +        #~ return lambda s,l,t: func(t)
    +    #~ limit = 0
    +    #~ foundArity = False
    +    #~ def wrapper(*args):
    +        #~ nonlocal limit,foundArity
    +        #~ while 1:
    +            #~ try:
    +                #~ ret = func(*args[limit:])
    +                #~ foundArity = True
    +                #~ return ret
    +            #~ except TypeError:
    +                #~ if limit == maxargs or foundArity:
    +                    #~ raise
    +                #~ limit += 1
    +                #~ continue
    +    #~ return wrapper
    +
    +# this version is Python 2.x-3.x cross-compatible
    +'decorator to trim function calls to match the arity of the target'
    +def _trim_arity(func, maxargs=2):
    +    if func in singleArgBuiltins:
    +        return lambda s,l,t: func(t)
    +    limit = [0]
    +    foundArity = [False]
    +    
    +    # traceback return data structure changed in Py3.5 - normalize back to plain tuples
    +    if system_version[:2] >= (3,5):
    +        def extract_stack(limit=0):
    +            # special handling for Python 3.5.0 - extra deep call stack by 1
    +            offset = -3 if system_version == (3,5,0) else -2
    +            frame_summary = traceback.extract_stack(limit=-offset+limit-1)[offset]
    +            return [frame_summary[:2]]
    +        def extract_tb(tb, limit=0):
    +            frames = traceback.extract_tb(tb, limit=limit)
    +            frame_summary = frames[-1]
    +            return [frame_summary[:2]]
    +    else:
    +        extract_stack = traceback.extract_stack
    +        extract_tb = traceback.extract_tb
    +    
    +    # synthesize what would be returned by traceback.extract_stack at the call to 
    +    # user's parse action 'func', so that we don't incur call penalty at parse time
    +    
    +    LINE_DIFF = 6
    +    # IF ANY CODE CHANGES, EVEN JUST COMMENTS OR BLANK LINES, BETWEEN THE NEXT LINE AND 
    +    # THE CALL TO FUNC INSIDE WRAPPER, LINE_DIFF MUST BE MODIFIED!!!!
    +    this_line = extract_stack(limit=2)[-1]
    +    pa_call_line_synth = (this_line[0], this_line[1]+LINE_DIFF)
    +
    +    def wrapper(*args):
    +        while 1:
    +            try:
    +                ret = func(*args[limit[0]:])
    +                foundArity[0] = True
    +                return ret
    +            except TypeError:
    +                # re-raise TypeErrors if they did not come from our arity testing
    +                if foundArity[0]:
    +                    raise
    +                else:
    +                    try:
    +                        tb = sys.exc_info()[-1]
    +                        if not extract_tb(tb, limit=2)[-1][:2] == pa_call_line_synth:
    +                            raise
    +                    finally:
    +                        del tb
    +
    +                if limit[0] <= maxargs:
    +                    limit[0] += 1
    +                    continue
    +                raise
    +
    +    # copy func name to wrapper for sensible debug output
    +    func_name = ""
    +    try:
    +        func_name = getattr(func, '__name__', 
    +                            getattr(func, '__class__').__name__)
    +    except Exception:
    +        func_name = str(func)
    +    wrapper.__name__ = func_name
    +
    +    return wrapper
    +
    +class ParserElement(object):
    +    """Abstract base level parser element class."""
    +    DEFAULT_WHITE_CHARS = " \n\t\r"
    +    verbose_stacktrace = False
    +
    +    @staticmethod
    +    def setDefaultWhitespaceChars( chars ):
    +        r"""
    +        Overrides the default whitespace chars
    +
    +        Example::
    +            # default whitespace chars are space,  and newline
    +            OneOrMore(Word(alphas)).parseString("abc def\nghi jkl")  # -> ['abc', 'def', 'ghi', 'jkl']
    +            
    +            # change to just treat newline as significant
    +            ParserElement.setDefaultWhitespaceChars(" \t")
    +            OneOrMore(Word(alphas)).parseString("abc def\nghi jkl")  # -> ['abc', 'def']
    +        """
    +        ParserElement.DEFAULT_WHITE_CHARS = chars
    +
    +    @staticmethod
    +    def inlineLiteralsUsing(cls):
    +        """
    +        Set class to be used for inclusion of string literals into a parser.
    +        
    +        Example::
    +            # default literal class used is Literal
    +            integer = Word(nums)
    +            date_str = integer("year") + '/' + integer("month") + '/' + integer("day")           
    +
    +            date_str.parseString("1999/12/31")  # -> ['1999', '/', '12', '/', '31']
    +
    +
    +            # change to Suppress
    +            ParserElement.inlineLiteralsUsing(Suppress)
    +            date_str = integer("year") + '/' + integer("month") + '/' + integer("day")           
    +
    +            date_str.parseString("1999/12/31")  # -> ['1999', '12', '31']
    +        """
    +        ParserElement._literalStringClass = cls
    +
    +    def __init__( self, savelist=False ):
    +        self.parseAction = list()
    +        self.failAction = None
    +        #~ self.name = ""  # don't define self.name, let subclasses try/except upcall
    +        self.strRepr = None
    +        self.resultsName = None
    +        self.saveAsList = savelist
    +        self.skipWhitespace = True
    +        self.whiteChars = ParserElement.DEFAULT_WHITE_CHARS
    +        self.copyDefaultWhiteChars = True
    +        self.mayReturnEmpty = False # used when checking for left-recursion
    +        self.keepTabs = False
    +        self.ignoreExprs = list()
    +        self.debug = False
    +        self.streamlined = False
    +        self.mayIndexError = True # used to optimize exception handling for subclasses that don't advance parse index
    +        self.errmsg = ""
    +        self.modalResults = True # used to mark results names as modal (report only last) or cumulative (list all)
    +        self.debugActions = ( None, None, None ) #custom debug actions
    +        self.re = None
    +        self.callPreparse = True # used to avoid redundant calls to preParse
    +        self.callDuringTry = False
    +
    +    def copy( self ):
    +        """
    +        Make a copy of this C{ParserElement}.  Useful for defining different parse actions
    +        for the same parsing pattern, using copies of the original parse element.
    +        
    +        Example::
    +            integer = Word(nums).setParseAction(lambda toks: int(toks[0]))
    +            integerK = integer.copy().addParseAction(lambda toks: toks[0]*1024) + Suppress("K")
    +            integerM = integer.copy().addParseAction(lambda toks: toks[0]*1024*1024) + Suppress("M")
    +            
    +            print(OneOrMore(integerK | integerM | integer).parseString("5K 100 640K 256M"))
    +        prints::
    +            [5120, 100, 655360, 268435456]
    +        Equivalent form of C{expr.copy()} is just C{expr()}::
    +            integerM = integer().addParseAction(lambda toks: toks[0]*1024*1024) + Suppress("M")
    +        """
    +        cpy = copy.copy( self )
    +        cpy.parseAction = self.parseAction[:]
    +        cpy.ignoreExprs = self.ignoreExprs[:]
    +        if self.copyDefaultWhiteChars:
    +            cpy.whiteChars = ParserElement.DEFAULT_WHITE_CHARS
    +        return cpy
    +
    +    def setName( self, name ):
    +        """
    +        Define name for this expression, makes debugging and exception messages clearer.
    +        
    +        Example::
    +            Word(nums).parseString("ABC")  # -> Exception: Expected W:(0123...) (at char 0), (line:1, col:1)
    +            Word(nums).setName("integer").parseString("ABC")  # -> Exception: Expected integer (at char 0), (line:1, col:1)
    +        """
    +        self.name = name
    +        self.errmsg = "Expected " + self.name
    +        if hasattr(self,"exception"):
    +            self.exception.msg = self.errmsg
    +        return self
    +
    +    def setResultsName( self, name, listAllMatches=False ):
    +        """
    +        Define name for referencing matching tokens as a nested attribute
    +        of the returned parse results.
    +        NOTE: this returns a *copy* of the original C{ParserElement} object;
    +        this is so that the client can define a basic element, such as an
    +        integer, and reference it in multiple places with different names.
    +
    +        You can also set results names using the abbreviated syntax,
    +        C{expr("name")} in place of C{expr.setResultsName("name")} - 
    +        see L{I{__call__}<__call__>}.
    +
    +        Example::
    +            date_str = (integer.setResultsName("year") + '/' 
    +                        + integer.setResultsName("month") + '/' 
    +                        + integer.setResultsName("day"))
    +
    +            # equivalent form:
    +            date_str = integer("year") + '/' + integer("month") + '/' + integer("day")
    +        """
    +        newself = self.copy()
    +        if name.endswith("*"):
    +            name = name[:-1]
    +            listAllMatches=True
    +        newself.resultsName = name
    +        newself.modalResults = not listAllMatches
    +        return newself
    +
    +    def setBreak(self,breakFlag = True):
    +        """Method to invoke the Python pdb debugger when this element is
    +           about to be parsed. Set C{breakFlag} to True to enable, False to
    +           disable.
    +        """
    +        if breakFlag:
    +            _parseMethod = self._parse
    +            def breaker(instring, loc, doActions=True, callPreParse=True):
    +                import pdb
    +                pdb.set_trace()
    +                return _parseMethod( instring, loc, doActions, callPreParse )
    +            breaker._originalParseMethod = _parseMethod
    +            self._parse = breaker
    +        else:
    +            if hasattr(self._parse,"_originalParseMethod"):
    +                self._parse = self._parse._originalParseMethod
    +        return self
    +
    +    def setParseAction( self, *fns, **kwargs ):
    +        """
    +        Define one or more actions to perform when successfully matching parse element definition.
    +        Parse action fn is a callable method with 0-3 arguments, called as C{fn(s,loc,toks)},
    +        C{fn(loc,toks)}, C{fn(toks)}, or just C{fn()}, where:
    +         - s   = the original string being parsed (see note below)
    +         - loc = the location of the matching substring
    +         - toks = a list of the matched tokens, packaged as a C{L{ParseResults}} object
    +        If the functions in fns modify the tokens, they can return them as the return
    +        value from fn, and the modified list of tokens will replace the original.
    +        Otherwise, fn does not need to return any value.
    +
    +        Optional keyword arguments:
    +         - callDuringTry = (default=C{False}) indicate if parse action should be run during lookaheads and alternate testing
    +
    +        Note: the default parsing behavior is to expand tabs in the input string
    +        before starting the parsing process.  See L{I{parseString}} for more information
    +        on parsing strings containing C{}s, and suggested methods to maintain a
    +        consistent view of the parsed string, the parse location, and line and column
    +        positions within the parsed string.
    +        
    +        Example::
    +            integer = Word(nums)
    +            date_str = integer + '/' + integer + '/' + integer
    +
    +            date_str.parseString("1999/12/31")  # -> ['1999', '/', '12', '/', '31']
    +
    +            # use parse action to convert to ints at parse time
    +            integer = Word(nums).setParseAction(lambda toks: int(toks[0]))
    +            date_str = integer + '/' + integer + '/' + integer
    +
    +            # note that integer fields are now ints, not strings
    +            date_str.parseString("1999/12/31")  # -> [1999, '/', 12, '/', 31]
    +        """
    +        self.parseAction = list(map(_trim_arity, list(fns)))
    +        self.callDuringTry = kwargs.get("callDuringTry", False)
    +        return self
    +
    +    def addParseAction( self, *fns, **kwargs ):
    +        """
    +        Add one or more parse actions to expression's list of parse actions. See L{I{setParseAction}}.
    +        
    +        See examples in L{I{copy}}.
    +        """
    +        self.parseAction += list(map(_trim_arity, list(fns)))
    +        self.callDuringTry = self.callDuringTry or kwargs.get("callDuringTry", False)
    +        return self
    +
    +    def addCondition(self, *fns, **kwargs):
    +        """Add a boolean predicate function to expression's list of parse actions. See 
    +        L{I{setParseAction}} for function call signatures. Unlike C{setParseAction}, 
    +        functions passed to C{addCondition} need to return boolean success/fail of the condition.
    +
    +        Optional keyword arguments:
    +         - message = define a custom message to be used in the raised exception
    +         - fatal   = if True, will raise ParseFatalException to stop parsing immediately; otherwise will raise ParseException
    +         
    +        Example::
    +            integer = Word(nums).setParseAction(lambda toks: int(toks[0]))
    +            year_int = integer.copy()
    +            year_int.addCondition(lambda toks: toks[0] >= 2000, message="Only support years 2000 and later")
    +            date_str = year_int + '/' + integer + '/' + integer
    +
    +            result = date_str.parseString("1999/12/31")  # -> Exception: Only support years 2000 and later (at char 0), (line:1, col:1)
    +        """
    +        msg = kwargs.get("message", "failed user-defined condition")
    +        exc_type = ParseFatalException if kwargs.get("fatal", False) else ParseException
    +        for fn in fns:
    +            def pa(s,l,t):
    +                if not bool(_trim_arity(fn)(s,l,t)):
    +                    raise exc_type(s,l,msg)
    +            self.parseAction.append(pa)
    +        self.callDuringTry = self.callDuringTry or kwargs.get("callDuringTry", False)
    +        return self
    +
    +    def setFailAction( self, fn ):
    +        """Define action to perform if parsing fails at this expression.
    +           Fail acton fn is a callable function that takes the arguments
    +           C{fn(s,loc,expr,err)} where:
    +            - s = string being parsed
    +            - loc = location where expression match was attempted and failed
    +            - expr = the parse expression that failed
    +            - err = the exception thrown
    +           The function returns no value.  It may throw C{L{ParseFatalException}}
    +           if it is desired to stop parsing immediately."""
    +        self.failAction = fn
    +        return self
    +
    +    def _skipIgnorables( self, instring, loc ):
    +        exprsFound = True
    +        while exprsFound:
    +            exprsFound = False
    +            for e in self.ignoreExprs:
    +                try:
    +                    while 1:
    +                        loc,dummy = e._parse( instring, loc )
    +                        exprsFound = True
    +                except ParseException:
    +                    pass
    +        return loc
    +
    +    def preParse( self, instring, loc ):
    +        if self.ignoreExprs:
    +            loc = self._skipIgnorables( instring, loc )
    +
    +        if self.skipWhitespace:
    +            wt = self.whiteChars
    +            instrlen = len(instring)
    +            while loc < instrlen and instring[loc] in wt:
    +                loc += 1
    +
    +        return loc
    +
    +    def parseImpl( self, instring, loc, doActions=True ):
    +        return loc, []
    +
    +    def postParse( self, instring, loc, tokenlist ):
    +        return tokenlist
    +
    +    #~ @profile
    +    def _parseNoCache( self, instring, loc, doActions=True, callPreParse=True ):
    +        debugging = ( self.debug ) #and doActions )
    +
    +        if debugging or self.failAction:
    +            #~ print ("Match",self,"at loc",loc,"(%d,%d)" % ( lineno(loc,instring), col(loc,instring) ))
    +            if (self.debugActions[0] ):
    +                self.debugActions[0]( instring, loc, self )
    +            if callPreParse and self.callPreparse:
    +                preloc = self.preParse( instring, loc )
    +            else:
    +                preloc = loc
    +            tokensStart = preloc
    +            try:
    +                try:
    +                    loc,tokens = self.parseImpl( instring, preloc, doActions )
    +                except IndexError:
    +                    raise ParseException( instring, len(instring), self.errmsg, self )
    +            except ParseBaseException as err:
    +                #~ print ("Exception raised:", err)
    +                if self.debugActions[2]:
    +                    self.debugActions[2]( instring, tokensStart, self, err )
    +                if self.failAction:
    +                    self.failAction( instring, tokensStart, self, err )
    +                raise
    +        else:
    +            if callPreParse and self.callPreparse:
    +                preloc = self.preParse( instring, loc )
    +            else:
    +                preloc = loc
    +            tokensStart = preloc
    +            if self.mayIndexError or preloc >= len(instring):
    +                try:
    +                    loc,tokens = self.parseImpl( instring, preloc, doActions )
    +                except IndexError:
    +                    raise ParseException( instring, len(instring), self.errmsg, self )
    +            else:
    +                loc,tokens = self.parseImpl( instring, preloc, doActions )
    +
    +        tokens = self.postParse( instring, loc, tokens )
    +
    +        retTokens = ParseResults( tokens, self.resultsName, asList=self.saveAsList, modal=self.modalResults )
    +        if self.parseAction and (doActions or self.callDuringTry):
    +            if debugging:
    +                try:
    +                    for fn in self.parseAction:
    +                        tokens = fn( instring, tokensStart, retTokens )
    +                        if tokens is not None:
    +                            retTokens = ParseResults( tokens,
    +                                                      self.resultsName,
    +                                                      asList=self.saveAsList and isinstance(tokens,(ParseResults,list)),
    +                                                      modal=self.modalResults )
    +                except ParseBaseException as err:
    +                    #~ print "Exception raised in user parse action:", err
    +                    if (self.debugActions[2] ):
    +                        self.debugActions[2]( instring, tokensStart, self, err )
    +                    raise
    +            else:
    +                for fn in self.parseAction:
    +                    tokens = fn( instring, tokensStart, retTokens )
    +                    if tokens is not None:
    +                        retTokens = ParseResults( tokens,
    +                                                  self.resultsName,
    +                                                  asList=self.saveAsList and isinstance(tokens,(ParseResults,list)),
    +                                                  modal=self.modalResults )
    +        if debugging:
    +            #~ print ("Matched",self,"->",retTokens.asList())
    +            if (self.debugActions[1] ):
    +                self.debugActions[1]( instring, tokensStart, loc, self, retTokens )
    +
    +        return loc, retTokens
    +
    +    def tryParse( self, instring, loc ):
    +        try:
    +            return self._parse( instring, loc, doActions=False )[0]
    +        except ParseFatalException:
    +            raise ParseException( instring, loc, self.errmsg, self)
    +    
    +    def canParseNext(self, instring, loc):
    +        try:
    +            self.tryParse(instring, loc)
    +        except (ParseException, IndexError):
    +            return False
    +        else:
    +            return True
    +
    +    class _UnboundedCache(object):
    +        def __init__(self):
    +            cache = {}
    +            self.not_in_cache = not_in_cache = object()
    +
    +            def get(self, key):
    +                return cache.get(key, not_in_cache)
    +
    +            def set(self, key, value):
    +                cache[key] = value
    +
    +            def clear(self):
    +                cache.clear()
    +                
    +            def cache_len(self):
    +                return len(cache)
    +
    +            self.get = types.MethodType(get, self)
    +            self.set = types.MethodType(set, self)
    +            self.clear = types.MethodType(clear, self)
    +            self.__len__ = types.MethodType(cache_len, self)
    +
    +    if _OrderedDict is not None:
    +        class _FifoCache(object):
    +            def __init__(self, size):
    +                self.not_in_cache = not_in_cache = object()
    +
    +                cache = _OrderedDict()
    +
    +                def get(self, key):
    +                    return cache.get(key, not_in_cache)
    +
    +                def set(self, key, value):
    +                    cache[key] = value
    +                    while len(cache) > size:
    +                        try:
    +                            cache.popitem(False)
    +                        except KeyError:
    +                            pass
    +
    +                def clear(self):
    +                    cache.clear()
    +
    +                def cache_len(self):
    +                    return len(cache)
    +
    +                self.get = types.MethodType(get, self)
    +                self.set = types.MethodType(set, self)
    +                self.clear = types.MethodType(clear, self)
    +                self.__len__ = types.MethodType(cache_len, self)
    +
    +    else:
    +        class _FifoCache(object):
    +            def __init__(self, size):
    +                self.not_in_cache = not_in_cache = object()
    +
    +                cache = {}
    +                key_fifo = collections.deque([], size)
    +
    +                def get(self, key):
    +                    return cache.get(key, not_in_cache)
    +
    +                def set(self, key, value):
    +                    cache[key] = value
    +                    while len(key_fifo) > size:
    +                        cache.pop(key_fifo.popleft(), None)
    +                    key_fifo.append(key)
    +
    +                def clear(self):
    +                    cache.clear()
    +                    key_fifo.clear()
    +
    +                def cache_len(self):
    +                    return len(cache)
    +
    +                self.get = types.MethodType(get, self)
    +                self.set = types.MethodType(set, self)
    +                self.clear = types.MethodType(clear, self)
    +                self.__len__ = types.MethodType(cache_len, self)
    +
    +    # argument cache for optimizing repeated calls when backtracking through recursive expressions
    +    packrat_cache = {} # this is set later by enabledPackrat(); this is here so that resetCache() doesn't fail
    +    packrat_cache_lock = RLock()
    +    packrat_cache_stats = [0, 0]
    +
    +    # this method gets repeatedly called during backtracking with the same arguments -
    +    # we can cache these arguments and save ourselves the trouble of re-parsing the contained expression
    +    def _parseCache( self, instring, loc, doActions=True, callPreParse=True ):
    +        HIT, MISS = 0, 1
    +        lookup = (self, instring, loc, callPreParse, doActions)
    +        with ParserElement.packrat_cache_lock:
    +            cache = ParserElement.packrat_cache
    +            value = cache.get(lookup)
    +            if value is cache.not_in_cache:
    +                ParserElement.packrat_cache_stats[MISS] += 1
    +                try:
    +                    value = self._parseNoCache(instring, loc, doActions, callPreParse)
    +                except ParseBaseException as pe:
    +                    # cache a copy of the exception, without the traceback
    +                    cache.set(lookup, pe.__class__(*pe.args))
    +                    raise
    +                else:
    +                    cache.set(lookup, (value[0], value[1].copy()))
    +                    return value
    +            else:
    +                ParserElement.packrat_cache_stats[HIT] += 1
    +                if isinstance(value, Exception):
    +                    raise value
    +                return (value[0], value[1].copy())
    +
    +    _parse = _parseNoCache
    +
    +    @staticmethod
    +    def resetCache():
    +        ParserElement.packrat_cache.clear()
    +        ParserElement.packrat_cache_stats[:] = [0] * len(ParserElement.packrat_cache_stats)
    +
    +    _packratEnabled = False
    +    @staticmethod
    +    def enablePackrat(cache_size_limit=128):
    +        """Enables "packrat" parsing, which adds memoizing to the parsing logic.
    +           Repeated parse attempts at the same string location (which happens
    +           often in many complex grammars) can immediately return a cached value,
    +           instead of re-executing parsing/validating code.  Memoizing is done of
    +           both valid results and parsing exceptions.
    +           
    +           Parameters:
    +            - cache_size_limit - (default=C{128}) - if an integer value is provided
    +              will limit the size of the packrat cache; if None is passed, then
    +              the cache size will be unbounded; if 0 is passed, the cache will
    +              be effectively disabled.
    +            
    +           This speedup may break existing programs that use parse actions that
    +           have side-effects.  For this reason, packrat parsing is disabled when
    +           you first import pyparsing.  To activate the packrat feature, your
    +           program must call the class method C{ParserElement.enablePackrat()}.  If
    +           your program uses C{psyco} to "compile as you go", you must call
    +           C{enablePackrat} before calling C{psyco.full()}.  If you do not do this,
    +           Python will crash.  For best results, call C{enablePackrat()} immediately
    +           after importing pyparsing.
    +           
    +           Example::
    +               import pyparsing
    +               pyparsing.ParserElement.enablePackrat()
    +        """
    +        if not ParserElement._packratEnabled:
    +            ParserElement._packratEnabled = True
    +            if cache_size_limit is None:
    +                ParserElement.packrat_cache = ParserElement._UnboundedCache()
    +            else:
    +                ParserElement.packrat_cache = ParserElement._FifoCache(cache_size_limit)
    +            ParserElement._parse = ParserElement._parseCache
    +
    +    def parseString( self, instring, parseAll=False ):
    +        """
    +        Execute the parse expression with the given string.
    +        This is the main interface to the client code, once the complete
    +        expression has been built.
    +
    +        If you want the grammar to require that the entire input string be
    +        successfully parsed, then set C{parseAll} to True (equivalent to ending
    +        the grammar with C{L{StringEnd()}}).
    +
    +        Note: C{parseString} implicitly calls C{expandtabs()} on the input string,
    +        in order to report proper column numbers in parse actions.
    +        If the input string contains tabs and
    +        the grammar uses parse actions that use the C{loc} argument to index into the
    +        string being parsed, you can ensure you have a consistent view of the input
    +        string by:
    +         - calling C{parseWithTabs} on your grammar before calling C{parseString}
    +           (see L{I{parseWithTabs}})
    +         - define your parse action using the full C{(s,loc,toks)} signature, and
    +           reference the input string using the parse action's C{s} argument
    +         - explictly expand the tabs in your input string before calling
    +           C{parseString}
    +        
    +        Example::
    +            Word('a').parseString('aaaaabaaa')  # -> ['aaaaa']
    +            Word('a').parseString('aaaaabaaa', parseAll=True)  # -> Exception: Expected end of text
    +        """
    +        ParserElement.resetCache()
    +        if not self.streamlined:
    +            self.streamline()
    +            #~ self.saveAsList = True
    +        for e in self.ignoreExprs:
    +            e.streamline()
    +        if not self.keepTabs:
    +            instring = instring.expandtabs()
    +        try:
    +            loc, tokens = self._parse( instring, 0 )
    +            if parseAll:
    +                loc = self.preParse( instring, loc )
    +                se = Empty() + StringEnd()
    +                se._parse( instring, loc )
    +        except ParseBaseException as exc:
    +            if ParserElement.verbose_stacktrace:
    +                raise
    +            else:
    +                # catch and re-raise exception from here, clears out pyparsing internal stack trace
    +                raise exc
    +        else:
    +            return tokens
    +
    +    def scanString( self, instring, maxMatches=_MAX_INT, overlap=False ):
    +        """
    +        Scan the input string for expression matches.  Each match will return the
    +        matching tokens, start location, and end location.  May be called with optional
    +        C{maxMatches} argument, to clip scanning after 'n' matches are found.  If
    +        C{overlap} is specified, then overlapping matches will be reported.
    +
    +        Note that the start and end locations are reported relative to the string
    +        being parsed.  See L{I{parseString}} for more information on parsing
    +        strings with embedded tabs.
    +
    +        Example::
    +            source = "sldjf123lsdjjkf345sldkjf879lkjsfd987"
    +            print(source)
    +            for tokens,start,end in Word(alphas).scanString(source):
    +                print(' '*start + '^'*(end-start))
    +                print(' '*start + tokens[0])
    +        
    +        prints::
    +        
    +            sldjf123lsdjjkf345sldkjf879lkjsfd987
    +            ^^^^^
    +            sldjf
    +                    ^^^^^^^
    +                    lsdjjkf
    +                              ^^^^^^
    +                              sldkjf
    +                                       ^^^^^^
    +                                       lkjsfd
    +        """
    +        if not self.streamlined:
    +            self.streamline()
    +        for e in self.ignoreExprs:
    +            e.streamline()
    +
    +        if not self.keepTabs:
    +            instring = _ustr(instring).expandtabs()
    +        instrlen = len(instring)
    +        loc = 0
    +        preparseFn = self.preParse
    +        parseFn = self._parse
    +        ParserElement.resetCache()
    +        matches = 0
    +        try:
    +            while loc <= instrlen and matches < maxMatches:
    +                try:
    +                    preloc = preparseFn( instring, loc )
    +                    nextLoc,tokens = parseFn( instring, preloc, callPreParse=False )
    +                except ParseException:
    +                    loc = preloc+1
    +                else:
    +                    if nextLoc > loc:
    +                        matches += 1
    +                        yield tokens, preloc, nextLoc
    +                        if overlap:
    +                            nextloc = preparseFn( instring, loc )
    +                            if nextloc > loc:
    +                                loc = nextLoc
    +                            else:
    +                                loc += 1
    +                        else:
    +                            loc = nextLoc
    +                    else:
    +                        loc = preloc+1
    +        except ParseBaseException as exc:
    +            if ParserElement.verbose_stacktrace:
    +                raise
    +            else:
    +                # catch and re-raise exception from here, clears out pyparsing internal stack trace
    +                raise exc
    +
    +    def transformString( self, instring ):
    +        """
    +        Extension to C{L{scanString}}, to modify matching text with modified tokens that may
    +        be returned from a parse action.  To use C{transformString}, define a grammar and
    +        attach a parse action to it that modifies the returned token list.
    +        Invoking C{transformString()} on a target string will then scan for matches,
    +        and replace the matched text patterns according to the logic in the parse
    +        action.  C{transformString()} returns the resulting transformed string.
    +        
    +        Example::
    +            wd = Word(alphas)
    +            wd.setParseAction(lambda toks: toks[0].title())
    +            
    +            print(wd.transformString("now is the winter of our discontent made glorious summer by this sun of york."))
    +        Prints::
    +            Now Is The Winter Of Our Discontent Made Glorious Summer By This Sun Of York.
    +        """
    +        out = []
    +        lastE = 0
    +        # force preservation of s, to minimize unwanted transformation of string, and to
    +        # keep string locs straight between transformString and scanString
    +        self.keepTabs = True
    +        try:
    +            for t,s,e in self.scanString( instring ):
    +                out.append( instring[lastE:s] )
    +                if t:
    +                    if isinstance(t,ParseResults):
    +                        out += t.asList()
    +                    elif isinstance(t,list):
    +                        out += t
    +                    else:
    +                        out.append(t)
    +                lastE = e
    +            out.append(instring[lastE:])
    +            out = [o for o in out if o]
    +            return "".join(map(_ustr,_flatten(out)))
    +        except ParseBaseException as exc:
    +            if ParserElement.verbose_stacktrace:
    +                raise
    +            else:
    +                # catch and re-raise exception from here, clears out pyparsing internal stack trace
    +                raise exc
    +
    +    def searchString( self, instring, maxMatches=_MAX_INT ):
    +        """
    +        Another extension to C{L{scanString}}, simplifying the access to the tokens found
    +        to match the given parse expression.  May be called with optional
    +        C{maxMatches} argument, to clip searching after 'n' matches are found.
    +        
    +        Example::
    +            # a capitalized word starts with an uppercase letter, followed by zero or more lowercase letters
    +            cap_word = Word(alphas.upper(), alphas.lower())
    +            
    +            print(cap_word.searchString("More than Iron, more than Lead, more than Gold I need Electricity"))
    +
    +            # the sum() builtin can be used to merge results into a single ParseResults object
    +            print(sum(cap_word.searchString("More than Iron, more than Lead, more than Gold I need Electricity")))
    +        prints::
    +            [['More'], ['Iron'], ['Lead'], ['Gold'], ['I'], ['Electricity']]
    +            ['More', 'Iron', 'Lead', 'Gold', 'I', 'Electricity']
    +        """
    +        try:
    +            return ParseResults([ t for t,s,e in self.scanString( instring, maxMatches ) ])
    +        except ParseBaseException as exc:
    +            if ParserElement.verbose_stacktrace:
    +                raise
    +            else:
    +                # catch and re-raise exception from here, clears out pyparsing internal stack trace
    +                raise exc
    +
    +    def split(self, instring, maxsplit=_MAX_INT, includeSeparators=False):
    +        """
    +        Generator method to split a string using the given expression as a separator.
    +        May be called with optional C{maxsplit} argument, to limit the number of splits;
    +        and the optional C{includeSeparators} argument (default=C{False}), if the separating
    +        matching text should be included in the split results.
    +        
    +        Example::        
    +            punc = oneOf(list(".,;:/-!?"))
    +            print(list(punc.split("This, this?, this sentence, is badly punctuated!")))
    +        prints::
    +            ['This', ' this', '', ' this sentence', ' is badly punctuated', '']
    +        """
    +        splits = 0
    +        last = 0
    +        for t,s,e in self.scanString(instring, maxMatches=maxsplit):
    +            yield instring[last:s]
    +            if includeSeparators:
    +                yield t[0]
    +            last = e
    +        yield instring[last:]
    +
    +    def __add__(self, other ):
    +        """
    +        Implementation of + operator - returns C{L{And}}. Adding strings to a ParserElement
    +        converts them to L{Literal}s by default.
    +        
    +        Example::
    +            greet = Word(alphas) + "," + Word(alphas) + "!"
    +            hello = "Hello, World!"
    +            print (hello, "->", greet.parseString(hello))
    +        Prints::
    +            Hello, World! -> ['Hello', ',', 'World', '!']
    +        """
    +        if isinstance( other, basestring ):
    +            other = ParserElement._literalStringClass( other )
    +        if not isinstance( other, ParserElement ):
    +            warnings.warn("Cannot combine element of type %s with ParserElement" % type(other),
    +                    SyntaxWarning, stacklevel=2)
    +            return None
    +        return And( [ self, other ] )
    +
    +    def __radd__(self, other ):
    +        """
    +        Implementation of + operator when left operand is not a C{L{ParserElement}}
    +        """
    +        if isinstance( other, basestring ):
    +            other = ParserElement._literalStringClass( other )
    +        if not isinstance( other, ParserElement ):
    +            warnings.warn("Cannot combine element of type %s with ParserElement" % type(other),
    +                    SyntaxWarning, stacklevel=2)
    +            return None
    +        return other + self
    +
    +    def __sub__(self, other):
    +        """
    +        Implementation of - operator, returns C{L{And}} with error stop
    +        """
    +        if isinstance( other, basestring ):
    +            other = ParserElement._literalStringClass( other )
    +        if not isinstance( other, ParserElement ):
    +            warnings.warn("Cannot combine element of type %s with ParserElement" % type(other),
    +                    SyntaxWarning, stacklevel=2)
    +            return None
    +        return self + And._ErrorStop() + other
    +
    +    def __rsub__(self, other ):
    +        """
    +        Implementation of - operator when left operand is not a C{L{ParserElement}}
    +        """
    +        if isinstance( other, basestring ):
    +            other = ParserElement._literalStringClass( other )
    +        if not isinstance( other, ParserElement ):
    +            warnings.warn("Cannot combine element of type %s with ParserElement" % type(other),
    +                    SyntaxWarning, stacklevel=2)
    +            return None
    +        return other - self
    +
    +    def __mul__(self,other):
    +        """
    +        Implementation of * operator, allows use of C{expr * 3} in place of
    +        C{expr + expr + expr}.  Expressions may also me multiplied by a 2-integer
    +        tuple, similar to C{{min,max}} multipliers in regular expressions.  Tuples
    +        may also include C{None} as in:
    +         - C{expr*(n,None)} or C{expr*(n,)} is equivalent
    +              to C{expr*n + L{ZeroOrMore}(expr)}
    +              (read as "at least n instances of C{expr}")
    +         - C{expr*(None,n)} is equivalent to C{expr*(0,n)}
    +              (read as "0 to n instances of C{expr}")
    +         - C{expr*(None,None)} is equivalent to C{L{ZeroOrMore}(expr)}
    +         - C{expr*(1,None)} is equivalent to C{L{OneOrMore}(expr)}
    +
    +        Note that C{expr*(None,n)} does not raise an exception if
    +        more than n exprs exist in the input stream; that is,
    +        C{expr*(None,n)} does not enforce a maximum number of expr
    +        occurrences.  If this behavior is desired, then write
    +        C{expr*(None,n) + ~expr}
    +        """
    +        if isinstance(other,int):
    +            minElements, optElements = other,0
    +        elif isinstance(other,tuple):
    +            other = (other + (None, None))[:2]
    +            if other[0] is None:
    +                other = (0, other[1])
    +            if isinstance(other[0],int) and other[1] is None:
    +                if other[0] == 0:
    +                    return ZeroOrMore(self)
    +                if other[0] == 1:
    +                    return OneOrMore(self)
    +                else:
    +                    return self*other[0] + ZeroOrMore(self)
    +            elif isinstance(other[0],int) and isinstance(other[1],int):
    +                minElements, optElements = other
    +                optElements -= minElements
    +            else:
    +                raise TypeError("cannot multiply 'ParserElement' and ('%s','%s') objects", type(other[0]),type(other[1]))
    +        else:
    +            raise TypeError("cannot multiply 'ParserElement' and '%s' objects", type(other))
    +
    +        if minElements < 0:
    +            raise ValueError("cannot multiply ParserElement by negative value")
    +        if optElements < 0:
    +            raise ValueError("second tuple value must be greater or equal to first tuple value")
    +        if minElements == optElements == 0:
    +            raise ValueError("cannot multiply ParserElement by 0 or (0,0)")
    +
    +        if (optElements):
    +            def makeOptionalList(n):
    +                if n>1:
    +                    return Optional(self + makeOptionalList(n-1))
    +                else:
    +                    return Optional(self)
    +            if minElements:
    +                if minElements == 1:
    +                    ret = self + makeOptionalList(optElements)
    +                else:
    +                    ret = And([self]*minElements) + makeOptionalList(optElements)
    +            else:
    +                ret = makeOptionalList(optElements)
    +        else:
    +            if minElements == 1:
    +                ret = self
    +            else:
    +                ret = And([self]*minElements)
    +        return ret
    +
    +    def __rmul__(self, other):
    +        return self.__mul__(other)
    +
    +    def __or__(self, other ):
    +        """
    +        Implementation of | operator - returns C{L{MatchFirst}}
    +        """
    +        if isinstance( other, basestring ):
    +            other = ParserElement._literalStringClass( other )
    +        if not isinstance( other, ParserElement ):
    +            warnings.warn("Cannot combine element of type %s with ParserElement" % type(other),
    +                    SyntaxWarning, stacklevel=2)
    +            return None
    +        return MatchFirst( [ self, other ] )
    +
    +    def __ror__(self, other ):
    +        """
    +        Implementation of | operator when left operand is not a C{L{ParserElement}}
    +        """
    +        if isinstance( other, basestring ):
    +            other = ParserElement._literalStringClass( other )
    +        if not isinstance( other, ParserElement ):
    +            warnings.warn("Cannot combine element of type %s with ParserElement" % type(other),
    +                    SyntaxWarning, stacklevel=2)
    +            return None
    +        return other | self
    +
    +    def __xor__(self, other ):
    +        """
    +        Implementation of ^ operator - returns C{L{Or}}
    +        """
    +        if isinstance( other, basestring ):
    +            other = ParserElement._literalStringClass( other )
    +        if not isinstance( other, ParserElement ):
    +            warnings.warn("Cannot combine element of type %s with ParserElement" % type(other),
    +                    SyntaxWarning, stacklevel=2)
    +            return None
    +        return Or( [ self, other ] )
    +
    +    def __rxor__(self, other ):
    +        """
    +        Implementation of ^ operator when left operand is not a C{L{ParserElement}}
    +        """
    +        if isinstance( other, basestring ):
    +            other = ParserElement._literalStringClass( other )
    +        if not isinstance( other, ParserElement ):
    +            warnings.warn("Cannot combine element of type %s with ParserElement" % type(other),
    +                    SyntaxWarning, stacklevel=2)
    +            return None
    +        return other ^ self
    +
    +    def __and__(self, other ):
    +        """
    +        Implementation of & operator - returns C{L{Each}}
    +        """
    +        if isinstance( other, basestring ):
    +            other = ParserElement._literalStringClass( other )
    +        if not isinstance( other, ParserElement ):
    +            warnings.warn("Cannot combine element of type %s with ParserElement" % type(other),
    +                    SyntaxWarning, stacklevel=2)
    +            return None
    +        return Each( [ self, other ] )
    +
    +    def __rand__(self, other ):
    +        """
    +        Implementation of & operator when left operand is not a C{L{ParserElement}}
    +        """
    +        if isinstance( other, basestring ):
    +            other = ParserElement._literalStringClass( other )
    +        if not isinstance( other, ParserElement ):
    +            warnings.warn("Cannot combine element of type %s with ParserElement" % type(other),
    +                    SyntaxWarning, stacklevel=2)
    +            return None
    +        return other & self
    +
    +    def __invert__( self ):
    +        """
    +        Implementation of ~ operator - returns C{L{NotAny}}
    +        """
    +        return NotAny( self )
    +
    +    def __call__(self, name=None):
    +        """
    +        Shortcut for C{L{setResultsName}}, with C{listAllMatches=False}.
    +        
    +        If C{name} is given with a trailing C{'*'} character, then C{listAllMatches} will be
    +        passed as C{True}.
    +           
    +        If C{name} is omitted, same as calling C{L{copy}}.
    +
    +        Example::
    +            # these are equivalent
    +            userdata = Word(alphas).setResultsName("name") + Word(nums+"-").setResultsName("socsecno")
    +            userdata = Word(alphas)("name") + Word(nums+"-")("socsecno")             
    +        """
    +        if name is not None:
    +            return self.setResultsName(name)
    +        else:
    +            return self.copy()
    +
    +    def suppress( self ):
    +        """
    +        Suppresses the output of this C{ParserElement}; useful to keep punctuation from
    +        cluttering up returned output.
    +        """
    +        return Suppress( self )
    +
    +    def leaveWhitespace( self ):
    +        """
    +        Disables the skipping of whitespace before matching the characters in the
    +        C{ParserElement}'s defined pattern.  This is normally only used internally by
    +        the pyparsing module, but may be needed in some whitespace-sensitive grammars.
    +        """
    +        self.skipWhitespace = False
    +        return self
    +
    +    def setWhitespaceChars( self, chars ):
    +        """
    +        Overrides the default whitespace chars
    +        """
    +        self.skipWhitespace = True
    +        self.whiteChars = chars
    +        self.copyDefaultWhiteChars = False
    +        return self
    +
    +    def parseWithTabs( self ):
    +        """
    +        Overrides default behavior to expand C{}s to spaces before parsing the input string.
    +        Must be called before C{parseString} when the input grammar contains elements that
    +        match C{} characters.
    +        """
    +        self.keepTabs = True
    +        return self
    +
    +    def ignore( self, other ):
    +        """
    +        Define expression to be ignored (e.g., comments) while doing pattern
    +        matching; may be called repeatedly, to define multiple comment or other
    +        ignorable patterns.
    +        
    +        Example::
    +            patt = OneOrMore(Word(alphas))
    +            patt.parseString('ablaj /* comment */ lskjd') # -> ['ablaj']
    +            
    +            patt.ignore(cStyleComment)
    +            patt.parseString('ablaj /* comment */ lskjd') # -> ['ablaj', 'lskjd']
    +        """
    +        if isinstance(other, basestring):
    +            other = Suppress(other)
    +
    +        if isinstance( other, Suppress ):
    +            if other not in self.ignoreExprs:
    +                self.ignoreExprs.append(other)
    +        else:
    +            self.ignoreExprs.append( Suppress( other.copy() ) )
    +        return self
    +
    +    def setDebugActions( self, startAction, successAction, exceptionAction ):
    +        """
    +        Enable display of debugging messages while doing pattern matching.
    +        """
    +        self.debugActions = (startAction or _defaultStartDebugAction,
    +                             successAction or _defaultSuccessDebugAction,
    +                             exceptionAction or _defaultExceptionDebugAction)
    +        self.debug = True
    +        return self
    +
    +    def setDebug( self, flag=True ):
    +        """
    +        Enable display of debugging messages while doing pattern matching.
    +        Set C{flag} to True to enable, False to disable.
    +
    +        Example::
    +            wd = Word(alphas).setName("alphaword")
    +            integer = Word(nums).setName("numword")
    +            term = wd | integer
    +            
    +            # turn on debugging for wd
    +            wd.setDebug()
    +
    +            OneOrMore(term).parseString("abc 123 xyz 890")
    +        
    +        prints::
    +            Match alphaword at loc 0(1,1)
    +            Matched alphaword -> ['abc']
    +            Match alphaword at loc 3(1,4)
    +            Exception raised:Expected alphaword (at char 4), (line:1, col:5)
    +            Match alphaword at loc 7(1,8)
    +            Matched alphaword -> ['xyz']
    +            Match alphaword at loc 11(1,12)
    +            Exception raised:Expected alphaword (at char 12), (line:1, col:13)
    +            Match alphaword at loc 15(1,16)
    +            Exception raised:Expected alphaword (at char 15), (line:1, col:16)
    +
    +        The output shown is that produced by the default debug actions - custom debug actions can be
    +        specified using L{setDebugActions}. Prior to attempting
    +        to match the C{wd} expression, the debugging message C{"Match  at loc (,)"}
    +        is shown. Then if the parse succeeds, a C{"Matched"} message is shown, or an C{"Exception raised"}
    +        message is shown. Also note the use of L{setName} to assign a human-readable name to the expression,
    +        which makes debugging and exception messages easier to understand - for instance, the default
    +        name created for the C{Word} expression without calling C{setName} is C{"W:(ABCD...)"}.
    +        """
    +        if flag:
    +            self.setDebugActions( _defaultStartDebugAction, _defaultSuccessDebugAction, _defaultExceptionDebugAction )
    +        else:
    +            self.debug = False
    +        return self
    +
    +    def __str__( self ):
    +        return self.name
    +
    +    def __repr__( self ):
    +        return _ustr(self)
    +
    +    def streamline( self ):
    +        self.streamlined = True
    +        self.strRepr = None
    +        return self
    +
    +    def checkRecursion( self, parseElementList ):
    +        pass
    +
    +    def validate( self, validateTrace=[] ):
    +        """
    +        Check defined expressions for valid structure, check for infinite recursive definitions.
    +        """
    +        self.checkRecursion( [] )
    +
    +    def parseFile( self, file_or_filename, parseAll=False ):
    +        """
    +        Execute the parse expression on the given file or filename.
    +        If a filename is specified (instead of a file object),
    +        the entire file is opened, read, and closed before parsing.
    +        """
    +        try:
    +            file_contents = file_or_filename.read()
    +        except AttributeError:
    +            with open(file_or_filename, "r") as f:
    +                file_contents = f.read()
    +        try:
    +            return self.parseString(file_contents, parseAll)
    +        except ParseBaseException as exc:
    +            if ParserElement.verbose_stacktrace:
    +                raise
    +            else:
    +                # catch and re-raise exception from here, clears out pyparsing internal stack trace
    +                raise exc
    +
    +    def __eq__(self,other):
    +        if isinstance(other, ParserElement):
    +            return self is other or vars(self) == vars(other)
    +        elif isinstance(other, basestring):
    +            return self.matches(other)
    +        else:
    +            return super(ParserElement,self)==other
    +
    +    def __ne__(self,other):
    +        return not (self == other)
    +
    +    def __hash__(self):
    +        return hash(id(self))
    +
    +    def __req__(self,other):
    +        return self == other
    +
    +    def __rne__(self,other):
    +        return not (self == other)
    +
    +    def matches(self, testString, parseAll=True):
    +        """
    +        Method for quick testing of a parser against a test string. Good for simple 
    +        inline microtests of sub expressions while building up larger parser.
    +           
    +        Parameters:
    +         - testString - to test against this expression for a match
    +         - parseAll - (default=C{True}) - flag to pass to C{L{parseString}} when running tests
    +            
    +        Example::
    +            expr = Word(nums)
    +            assert expr.matches("100")
    +        """
    +        try:
    +            self.parseString(_ustr(testString), parseAll=parseAll)
    +            return True
    +        except ParseBaseException:
    +            return False
    +                
    +    def runTests(self, tests, parseAll=True, comment='#', fullDump=True, printResults=True, failureTests=False):
    +        """
    +        Execute the parse expression on a series of test strings, showing each
    +        test, the parsed results or where the parse failed. Quick and easy way to
    +        run a parse expression against a list of sample strings.
    +           
    +        Parameters:
    +         - tests - a list of separate test strings, or a multiline string of test strings
    +         - parseAll - (default=C{True}) - flag to pass to C{L{parseString}} when running tests           
    +         - comment - (default=C{'#'}) - expression for indicating embedded comments in the test 
    +              string; pass None to disable comment filtering
    +         - fullDump - (default=C{True}) - dump results as list followed by results names in nested outline;
    +              if False, only dump nested list
    +         - printResults - (default=C{True}) prints test output to stdout
    +         - failureTests - (default=C{False}) indicates if these tests are expected to fail parsing
    +
    +        Returns: a (success, results) tuple, where success indicates that all tests succeeded
    +        (or failed if C{failureTests} is True), and the results contain a list of lines of each 
    +        test's output
    +        
    +        Example::
    +            number_expr = pyparsing_common.number.copy()
    +
    +            result = number_expr.runTests('''
    +                # unsigned integer
    +                100
    +                # negative integer
    +                -100
    +                # float with scientific notation
    +                6.02e23
    +                # integer with scientific notation
    +                1e-12
    +                ''')
    +            print("Success" if result[0] else "Failed!")
    +
    +            result = number_expr.runTests('''
    +                # stray character
    +                100Z
    +                # missing leading digit before '.'
    +                -.100
    +                # too many '.'
    +                3.14.159
    +                ''', failureTests=True)
    +            print("Success" if result[0] else "Failed!")
    +        prints::
    +            # unsigned integer
    +            100
    +            [100]
    +
    +            # negative integer
    +            -100
    +            [-100]
    +
    +            # float with scientific notation
    +            6.02e23
    +            [6.02e+23]
    +
    +            # integer with scientific notation
    +            1e-12
    +            [1e-12]
    +
    +            Success
    +            
    +            # stray character
    +            100Z
    +               ^
    +            FAIL: Expected end of text (at char 3), (line:1, col:4)
    +
    +            # missing leading digit before '.'
    +            -.100
    +            ^
    +            FAIL: Expected {real number with scientific notation | real number | signed integer} (at char 0), (line:1, col:1)
    +
    +            # too many '.'
    +            3.14.159
    +                ^
    +            FAIL: Expected end of text (at char 4), (line:1, col:5)
    +
    +            Success
    +
    +        Each test string must be on a single line. If you want to test a string that spans multiple
    +        lines, create a test like this::
    +
    +            expr.runTest(r"this is a test\\n of strings that spans \\n 3 lines")
    +        
    +        (Note that this is a raw string literal, you must include the leading 'r'.)
    +        """
    +        if isinstance(tests, basestring):
    +            tests = list(map(str.strip, tests.rstrip().splitlines()))
    +        if isinstance(comment, basestring):
    +            comment = Literal(comment)
    +        allResults = []
    +        comments = []
    +        success = True
    +        for t in tests:
    +            if comment is not None and comment.matches(t, False) or comments and not t:
    +                comments.append(t)
    +                continue
    +            if not t:
    +                continue
    +            out = ['\n'.join(comments), t]
    +            comments = []
    +            try:
    +                t = t.replace(r'\n','\n')
    +                result = self.parseString(t, parseAll=parseAll)
    +                out.append(result.dump(full=fullDump))
    +                success = success and not failureTests
    +            except ParseBaseException as pe:
    +                fatal = "(FATAL)" if isinstance(pe, ParseFatalException) else ""
    +                if '\n' in t:
    +                    out.append(line(pe.loc, t))
    +                    out.append(' '*(col(pe.loc,t)-1) + '^' + fatal)
    +                else:
    +                    out.append(' '*pe.loc + '^' + fatal)
    +                out.append("FAIL: " + str(pe))
    +                success = success and failureTests
    +                result = pe
    +            except Exception as exc:
    +                out.append("FAIL-EXCEPTION: " + str(exc))
    +                success = success and failureTests
    +                result = exc
    +
    +            if printResults:
    +                if fullDump:
    +                    out.append('')
    +                print('\n'.join(out))
    +
    +            allResults.append((t, result))
    +        
    +        return success, allResults
    +
    +        
    +class Token(ParserElement):
    +    """
    +    Abstract C{ParserElement} subclass, for defining atomic matching patterns.
    +    """
    +    def __init__( self ):
    +        super(Token,self).__init__( savelist=False )
    +
    +
    +class Empty(Token):
    +    """
    +    An empty token, will always match.
    +    """
    +    def __init__( self ):
    +        super(Empty,self).__init__()
    +        self.name = "Empty"
    +        self.mayReturnEmpty = True
    +        self.mayIndexError = False
    +
    +
    +class NoMatch(Token):
    +    """
    +    A token that will never match.
    +    """
    +    def __init__( self ):
    +        super(NoMatch,self).__init__()
    +        self.name = "NoMatch"
    +        self.mayReturnEmpty = True
    +        self.mayIndexError = False
    +        self.errmsg = "Unmatchable token"
    +
    +    def parseImpl( self, instring, loc, doActions=True ):
    +        raise ParseException(instring, loc, self.errmsg, self)
    +
    +
    +class Literal(Token):
    +    """
    +    Token to exactly match a specified string.
    +    
    +    Example::
    +        Literal('blah').parseString('blah')  # -> ['blah']
    +        Literal('blah').parseString('blahfooblah')  # -> ['blah']
    +        Literal('blah').parseString('bla')  # -> Exception: Expected "blah"
    +    
    +    For case-insensitive matching, use L{CaselessLiteral}.
    +    
    +    For keyword matching (force word break before and after the matched string),
    +    use L{Keyword} or L{CaselessKeyword}.
    +    """
    +    def __init__( self, matchString ):
    +        super(Literal,self).__init__()
    +        self.match = matchString
    +        self.matchLen = len(matchString)
    +        try:
    +            self.firstMatchChar = matchString[0]
    +        except IndexError:
    +            warnings.warn("null string passed to Literal; use Empty() instead",
    +                            SyntaxWarning, stacklevel=2)
    +            self.__class__ = Empty
    +        self.name = '"%s"' % _ustr(self.match)
    +        self.errmsg = "Expected " + self.name
    +        self.mayReturnEmpty = False
    +        self.mayIndexError = False
    +
    +    # Performance tuning: this routine gets called a *lot*
    +    # if this is a single character match string  and the first character matches,
    +    # short-circuit as quickly as possible, and avoid calling startswith
    +    #~ @profile
    +    def parseImpl( self, instring, loc, doActions=True ):
    +        if (instring[loc] == self.firstMatchChar and
    +            (self.matchLen==1 or instring.startswith(self.match,loc)) ):
    +            return loc+self.matchLen, self.match
    +        raise ParseException(instring, loc, self.errmsg, self)
    +_L = Literal
    +ParserElement._literalStringClass = Literal
    +
    +class Keyword(Token):
    +    """
    +    Token to exactly match a specified string as a keyword, that is, it must be
    +    immediately followed by a non-keyword character.  Compare with C{L{Literal}}:
    +     - C{Literal("if")} will match the leading C{'if'} in C{'ifAndOnlyIf'}.
    +     - C{Keyword("if")} will not; it will only match the leading C{'if'} in C{'if x=1'}, or C{'if(y==2)'}
    +    Accepts two optional constructor arguments in addition to the keyword string:
    +     - C{identChars} is a string of characters that would be valid identifier characters,
    +          defaulting to all alphanumerics + "_" and "$"
    +     - C{caseless} allows case-insensitive matching, default is C{False}.
    +       
    +    Example::
    +        Keyword("start").parseString("start")  # -> ['start']
    +        Keyword("start").parseString("starting")  # -> Exception
    +
    +    For case-insensitive matching, use L{CaselessKeyword}.
    +    """
    +    DEFAULT_KEYWORD_CHARS = alphanums+"_$"
    +
    +    def __init__( self, matchString, identChars=None, caseless=False ):
    +        super(Keyword,self).__init__()
    +        if identChars is None:
    +            identChars = Keyword.DEFAULT_KEYWORD_CHARS
    +        self.match = matchString
    +        self.matchLen = len(matchString)
    +        try:
    +            self.firstMatchChar = matchString[0]
    +        except IndexError:
    +            warnings.warn("null string passed to Keyword; use Empty() instead",
    +                            SyntaxWarning, stacklevel=2)
    +        self.name = '"%s"' % self.match
    +        self.errmsg = "Expected " + self.name
    +        self.mayReturnEmpty = False
    +        self.mayIndexError = False
    +        self.caseless = caseless
    +        if caseless:
    +            self.caselessmatch = matchString.upper()
    +            identChars = identChars.upper()
    +        self.identChars = set(identChars)
    +
    +    def parseImpl( self, instring, loc, doActions=True ):
    +        if self.caseless:
    +            if ( (instring[ loc:loc+self.matchLen ].upper() == self.caselessmatch) and
    +                 (loc >= len(instring)-self.matchLen or instring[loc+self.matchLen].upper() not in self.identChars) and
    +                 (loc == 0 or instring[loc-1].upper() not in self.identChars) ):
    +                return loc+self.matchLen, self.match
    +        else:
    +            if (instring[loc] == self.firstMatchChar and
    +                (self.matchLen==1 or instring.startswith(self.match,loc)) and
    +                (loc >= len(instring)-self.matchLen or instring[loc+self.matchLen] not in self.identChars) and
    +                (loc == 0 or instring[loc-1] not in self.identChars) ):
    +                return loc+self.matchLen, self.match
    +        raise ParseException(instring, loc, self.errmsg, self)
    +
    +    def copy(self):
    +        c = super(Keyword,self).copy()
    +        c.identChars = Keyword.DEFAULT_KEYWORD_CHARS
    +        return c
    +
    +    @staticmethod
    +    def setDefaultKeywordChars( chars ):
    +        """Overrides the default Keyword chars
    +        """
    +        Keyword.DEFAULT_KEYWORD_CHARS = chars
    +
    +class CaselessLiteral(Literal):
    +    """
    +    Token to match a specified string, ignoring case of letters.
    +    Note: the matched results will always be in the case of the given
    +    match string, NOT the case of the input text.
    +
    +    Example::
    +        OneOrMore(CaselessLiteral("CMD")).parseString("cmd CMD Cmd10") # -> ['CMD', 'CMD', 'CMD']
    +        
    +    (Contrast with example for L{CaselessKeyword}.)
    +    """
    +    def __init__( self, matchString ):
    +        super(CaselessLiteral,self).__init__( matchString.upper() )
    +        # Preserve the defining literal.
    +        self.returnString = matchString
    +        self.name = "'%s'" % self.returnString
    +        self.errmsg = "Expected " + self.name
    +
    +    def parseImpl( self, instring, loc, doActions=True ):
    +        if instring[ loc:loc+self.matchLen ].upper() == self.match:
    +            return loc+self.matchLen, self.returnString
    +        raise ParseException(instring, loc, self.errmsg, self)
    +
    +class CaselessKeyword(Keyword):
    +    """
    +    Caseless version of L{Keyword}.
    +
    +    Example::
    +        OneOrMore(CaselessKeyword("CMD")).parseString("cmd CMD Cmd10") # -> ['CMD', 'CMD']
    +        
    +    (Contrast with example for L{CaselessLiteral}.)
    +    """
    +    def __init__( self, matchString, identChars=None ):
    +        super(CaselessKeyword,self).__init__( matchString, identChars, caseless=True )
    +
    +    def parseImpl( self, instring, loc, doActions=True ):
    +        if ( (instring[ loc:loc+self.matchLen ].upper() == self.caselessmatch) and
    +             (loc >= len(instring)-self.matchLen or instring[loc+self.matchLen].upper() not in self.identChars) ):
    +            return loc+self.matchLen, self.match
    +        raise ParseException(instring, loc, self.errmsg, self)
    +
    +class CloseMatch(Token):
    +    """
    +    A variation on L{Literal} which matches "close" matches, that is, 
    +    strings with at most 'n' mismatching characters. C{CloseMatch} takes parameters:
    +     - C{match_string} - string to be matched
    +     - C{maxMismatches} - (C{default=1}) maximum number of mismatches allowed to count as a match
    +    
    +    The results from a successful parse will contain the matched text from the input string and the following named results:
    +     - C{mismatches} - a list of the positions within the match_string where mismatches were found
    +     - C{original} - the original match_string used to compare against the input string
    +    
    +    If C{mismatches} is an empty list, then the match was an exact match.
    +    
    +    Example::
    +        patt = CloseMatch("ATCATCGAATGGA")
    +        patt.parseString("ATCATCGAAXGGA") # -> (['ATCATCGAAXGGA'], {'mismatches': [[9]], 'original': ['ATCATCGAATGGA']})
    +        patt.parseString("ATCAXCGAAXGGA") # -> Exception: Expected 'ATCATCGAATGGA' (with up to 1 mismatches) (at char 0), (line:1, col:1)
    +
    +        # exact match
    +        patt.parseString("ATCATCGAATGGA") # -> (['ATCATCGAATGGA'], {'mismatches': [[]], 'original': ['ATCATCGAATGGA']})
    +
    +        # close match allowing up to 2 mismatches
    +        patt = CloseMatch("ATCATCGAATGGA", maxMismatches=2)
    +        patt.parseString("ATCAXCGAAXGGA") # -> (['ATCAXCGAAXGGA'], {'mismatches': [[4, 9]], 'original': ['ATCATCGAATGGA']})
    +    """
    +    def __init__(self, match_string, maxMismatches=1):
    +        super(CloseMatch,self).__init__()
    +        self.name = match_string
    +        self.match_string = match_string
    +        self.maxMismatches = maxMismatches
    +        self.errmsg = "Expected %r (with up to %d mismatches)" % (self.match_string, self.maxMismatches)
    +        self.mayIndexError = False
    +        self.mayReturnEmpty = False
    +
    +    def parseImpl( self, instring, loc, doActions=True ):
    +        start = loc
    +        instrlen = len(instring)
    +        maxloc = start + len(self.match_string)
    +
    +        if maxloc <= instrlen:
    +            match_string = self.match_string
    +            match_stringloc = 0
    +            mismatches = []
    +            maxMismatches = self.maxMismatches
    +
    +            for match_stringloc,s_m in enumerate(zip(instring[loc:maxloc], self.match_string)):
    +                src,mat = s_m
    +                if src != mat:
    +                    mismatches.append(match_stringloc)
    +                    if len(mismatches) > maxMismatches:
    +                        break
    +            else:
    +                loc = match_stringloc + 1
    +                results = ParseResults([instring[start:loc]])
    +                results['original'] = self.match_string
    +                results['mismatches'] = mismatches
    +                return loc, results
    +
    +        raise ParseException(instring, loc, self.errmsg, self)
    +
    +
    +class Word(Token):
    +    """
    +    Token for matching words composed of allowed character sets.
    +    Defined with string containing all allowed initial characters,
    +    an optional string containing allowed body characters (if omitted,
    +    defaults to the initial character set), and an optional minimum,
    +    maximum, and/or exact length.  The default value for C{min} is 1 (a
    +    minimum value < 1 is not valid); the default values for C{max} and C{exact}
    +    are 0, meaning no maximum or exact length restriction. An optional
    +    C{excludeChars} parameter can list characters that might be found in 
    +    the input C{bodyChars} string; useful to define a word of all printables
    +    except for one or two characters, for instance.
    +    
    +    L{srange} is useful for defining custom character set strings for defining 
    +    C{Word} expressions, using range notation from regular expression character sets.
    +    
    +    A common mistake is to use C{Word} to match a specific literal string, as in 
    +    C{Word("Address")}. Remember that C{Word} uses the string argument to define
    +    I{sets} of matchable characters. This expression would match "Add", "AAA",
    +    "dAred", or any other word made up of the characters 'A', 'd', 'r', 'e', and 's'.
    +    To match an exact literal string, use L{Literal} or L{Keyword}.
    +
    +    pyparsing includes helper strings for building Words:
    +     - L{alphas}
    +     - L{nums}
    +     - L{alphanums}
    +     - L{hexnums}
    +     - L{alphas8bit} (alphabetic characters in ASCII range 128-255 - accented, tilded, umlauted, etc.)
    +     - L{punc8bit} (non-alphabetic characters in ASCII range 128-255 - currency, symbols, superscripts, diacriticals, etc.)
    +     - L{printables} (any non-whitespace character)
    +
    +    Example::
    +        # a word composed of digits
    +        integer = Word(nums) # equivalent to Word("0123456789") or Word(srange("0-9"))
    +        
    +        # a word with a leading capital, and zero or more lowercase
    +        capital_word = Word(alphas.upper(), alphas.lower())
    +
    +        # hostnames are alphanumeric, with leading alpha, and '-'
    +        hostname = Word(alphas, alphanums+'-')
    +        
    +        # roman numeral (not a strict parser, accepts invalid mix of characters)
    +        roman = Word("IVXLCDM")
    +        
    +        # any string of non-whitespace characters, except for ','
    +        csv_value = Word(printables, excludeChars=",")
    +    """
    +    def __init__( self, initChars, bodyChars=None, min=1, max=0, exact=0, asKeyword=False, excludeChars=None ):
    +        super(Word,self).__init__()
    +        if excludeChars:
    +            initChars = ''.join(c for c in initChars if c not in excludeChars)
    +            if bodyChars:
    +                bodyChars = ''.join(c for c in bodyChars if c not in excludeChars)
    +        self.initCharsOrig = initChars
    +        self.initChars = set(initChars)
    +        if bodyChars :
    +            self.bodyCharsOrig = bodyChars
    +            self.bodyChars = set(bodyChars)
    +        else:
    +            self.bodyCharsOrig = initChars
    +            self.bodyChars = set(initChars)
    +
    +        self.maxSpecified = max > 0
    +
    +        if min < 1:
    +            raise ValueError("cannot specify a minimum length < 1; use Optional(Word()) if zero-length word is permitted")
    +
    +        self.minLen = min
    +
    +        if max > 0:
    +            self.maxLen = max
    +        else:
    +            self.maxLen = _MAX_INT
    +
    +        if exact > 0:
    +            self.maxLen = exact
    +            self.minLen = exact
    +
    +        self.name = _ustr(self)
    +        self.errmsg = "Expected " + self.name
    +        self.mayIndexError = False
    +        self.asKeyword = asKeyword
    +
    +        if ' ' not in self.initCharsOrig+self.bodyCharsOrig and (min==1 and max==0 and exact==0):
    +            if self.bodyCharsOrig == self.initCharsOrig:
    +                self.reString = "[%s]+" % _escapeRegexRangeChars(self.initCharsOrig)
    +            elif len(self.initCharsOrig) == 1:
    +                self.reString = "%s[%s]*" % \
    +                                      (re.escape(self.initCharsOrig),
    +                                      _escapeRegexRangeChars(self.bodyCharsOrig),)
    +            else:
    +                self.reString = "[%s][%s]*" % \
    +                                      (_escapeRegexRangeChars(self.initCharsOrig),
    +                                      _escapeRegexRangeChars(self.bodyCharsOrig),)
    +            if self.asKeyword:
    +                self.reString = r"\b"+self.reString+r"\b"
    +            try:
    +                self.re = re.compile( self.reString )
    +            except Exception:
    +                self.re = None
    +
    +    def parseImpl( self, instring, loc, doActions=True ):
    +        if self.re:
    +            result = self.re.match(instring,loc)
    +            if not result:
    +                raise ParseException(instring, loc, self.errmsg, self)
    +
    +            loc = result.end()
    +            return loc, result.group()
    +
    +        if not(instring[ loc ] in self.initChars):
    +            raise ParseException(instring, loc, self.errmsg, self)
    +
    +        start = loc
    +        loc += 1
    +        instrlen = len(instring)
    +        bodychars = self.bodyChars
    +        maxloc = start + self.maxLen
    +        maxloc = min( maxloc, instrlen )
    +        while loc < maxloc and instring[loc] in bodychars:
    +            loc += 1
    +
    +        throwException = False
    +        if loc - start < self.minLen:
    +            throwException = True
    +        if self.maxSpecified and loc < instrlen and instring[loc] in bodychars:
    +            throwException = True
    +        if self.asKeyword:
    +            if (start>0 and instring[start-1] in bodychars) or (loc4:
    +                    return s[:4]+"..."
    +                else:
    +                    return s
    +
    +            if ( self.initCharsOrig != self.bodyCharsOrig ):
    +                self.strRepr = "W:(%s,%s)" % ( charsAsStr(self.initCharsOrig), charsAsStr(self.bodyCharsOrig) )
    +            else:
    +                self.strRepr = "W:(%s)" % charsAsStr(self.initCharsOrig)
    +
    +        return self.strRepr
    +
    +
    +class Regex(Token):
    +    r"""
    +    Token for matching strings that match a given regular expression.
    +    Defined with string specifying the regular expression in a form recognized by the inbuilt Python re module.
    +    If the given regex contains named groups (defined using C{(?P...)}), these will be preserved as 
    +    named parse results.
    +
    +    Example::
    +        realnum = Regex(r"[+-]?\d+\.\d*")
    +        date = Regex(r'(?P\d{4})-(?P\d\d?)-(?P\d\d?)')
    +        # ref: http://stackoverflow.com/questions/267399/how-do-you-match-only-valid-roman-numerals-with-a-regular-expression
    +        roman = Regex(r"M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})")
    +    """
    +    compiledREtype = type(re.compile("[A-Z]"))
    +    def __init__( self, pattern, flags=0):
    +        """The parameters C{pattern} and C{flags} are passed to the C{re.compile()} function as-is. See the Python C{re} module for an explanation of the acceptable patterns and flags."""
    +        super(Regex,self).__init__()
    +
    +        if isinstance(pattern, basestring):
    +            if not pattern:
    +                warnings.warn("null string passed to Regex; use Empty() instead",
    +                        SyntaxWarning, stacklevel=2)
    +
    +            self.pattern = pattern
    +            self.flags = flags
    +
    +            try:
    +                self.re = re.compile(self.pattern, self.flags)
    +                self.reString = self.pattern
    +            except sre_constants.error:
    +                warnings.warn("invalid pattern (%s) passed to Regex" % pattern,
    +                    SyntaxWarning, stacklevel=2)
    +                raise
    +
    +        elif isinstance(pattern, Regex.compiledREtype):
    +            self.re = pattern
    +            self.pattern = \
    +            self.reString = str(pattern)
    +            self.flags = flags
    +            
    +        else:
    +            raise ValueError("Regex may only be constructed with a string or a compiled RE object")
    +
    +        self.name = _ustr(self)
    +        self.errmsg = "Expected " + self.name
    +        self.mayIndexError = False
    +        self.mayReturnEmpty = True
    +
    +    def parseImpl( self, instring, loc, doActions=True ):
    +        result = self.re.match(instring,loc)
    +        if not result:
    +            raise ParseException(instring, loc, self.errmsg, self)
    +
    +        loc = result.end()
    +        d = result.groupdict()
    +        ret = ParseResults(result.group())
    +        if d:
    +            for k in d:
    +                ret[k] = d[k]
    +        return loc,ret
    +
    +    def __str__( self ):
    +        try:
    +            return super(Regex,self).__str__()
    +        except Exception:
    +            pass
    +
    +        if self.strRepr is None:
    +            self.strRepr = "Re:(%s)" % repr(self.pattern)
    +
    +        return self.strRepr
    +
    +
    +class QuotedString(Token):
    +    r"""
    +    Token for matching strings that are delimited by quoting characters.
    +    
    +    Defined with the following parameters:
    +        - quoteChar - string of one or more characters defining the quote delimiting string
    +        - escChar - character to escape quotes, typically backslash (default=C{None})
    +        - escQuote - special quote sequence to escape an embedded quote string (such as SQL's "" to escape an embedded ") (default=C{None})
    +        - multiline - boolean indicating whether quotes can span multiple lines (default=C{False})
    +        - unquoteResults - boolean indicating whether the matched text should be unquoted (default=C{True})
    +        - endQuoteChar - string of one or more characters defining the end of the quote delimited string (default=C{None} => same as quoteChar)
    +        - convertWhitespaceEscapes - convert escaped whitespace (C{'\t'}, C{'\n'}, etc.) to actual whitespace (default=C{True})
    +
    +    Example::
    +        qs = QuotedString('"')
    +        print(qs.searchString('lsjdf "This is the quote" sldjf'))
    +        complex_qs = QuotedString('{{', endQuoteChar='}}')
    +        print(complex_qs.searchString('lsjdf {{This is the "quote"}} sldjf'))
    +        sql_qs = QuotedString('"', escQuote='""')
    +        print(sql_qs.searchString('lsjdf "This is the quote with ""embedded"" quotes" sldjf'))
    +    prints::
    +        [['This is the quote']]
    +        [['This is the "quote"']]
    +        [['This is the quote with "embedded" quotes']]
    +    """
    +    def __init__( self, quoteChar, escChar=None, escQuote=None, multiline=False, unquoteResults=True, endQuoteChar=None, convertWhitespaceEscapes=True):
    +        super(QuotedString,self).__init__()
    +
    +        # remove white space from quote chars - wont work anyway
    +        quoteChar = quoteChar.strip()
    +        if not quoteChar:
    +            warnings.warn("quoteChar cannot be the empty string",SyntaxWarning,stacklevel=2)
    +            raise SyntaxError()
    +
    +        if endQuoteChar is None:
    +            endQuoteChar = quoteChar
    +        else:
    +            endQuoteChar = endQuoteChar.strip()
    +            if not endQuoteChar:
    +                warnings.warn("endQuoteChar cannot be the empty string",SyntaxWarning,stacklevel=2)
    +                raise SyntaxError()
    +
    +        self.quoteChar = quoteChar
    +        self.quoteCharLen = len(quoteChar)
    +        self.firstQuoteChar = quoteChar[0]
    +        self.endQuoteChar = endQuoteChar
    +        self.endQuoteCharLen = len(endQuoteChar)
    +        self.escChar = escChar
    +        self.escQuote = escQuote
    +        self.unquoteResults = unquoteResults
    +        self.convertWhitespaceEscapes = convertWhitespaceEscapes
    +
    +        if multiline:
    +            self.flags = re.MULTILINE | re.DOTALL
    +            self.pattern = r'%s(?:[^%s%s]' % \
    +                ( re.escape(self.quoteChar),
    +                  _escapeRegexRangeChars(self.endQuoteChar[0]),
    +                  (escChar is not None and _escapeRegexRangeChars(escChar) or '') )
    +        else:
    +            self.flags = 0
    +            self.pattern = r'%s(?:[^%s\n\r%s]' % \
    +                ( re.escape(self.quoteChar),
    +                  _escapeRegexRangeChars(self.endQuoteChar[0]),
    +                  (escChar is not None and _escapeRegexRangeChars(escChar) or '') )
    +        if len(self.endQuoteChar) > 1:
    +            self.pattern += (
    +                '|(?:' + ')|(?:'.join("%s[^%s]" % (re.escape(self.endQuoteChar[:i]),
    +                                               _escapeRegexRangeChars(self.endQuoteChar[i]))
    +                                    for i in range(len(self.endQuoteChar)-1,0,-1)) + ')'
    +                )
    +        if escQuote:
    +            self.pattern += (r'|(?:%s)' % re.escape(escQuote))
    +        if escChar:
    +            self.pattern += (r'|(?:%s.)' % re.escape(escChar))
    +            self.escCharReplacePattern = re.escape(self.escChar)+"(.)"
    +        self.pattern += (r')*%s' % re.escape(self.endQuoteChar))
    +
    +        try:
    +            self.re = re.compile(self.pattern, self.flags)
    +            self.reString = self.pattern
    +        except sre_constants.error:
    +            warnings.warn("invalid pattern (%s) passed to Regex" % self.pattern,
    +                SyntaxWarning, stacklevel=2)
    +            raise
    +
    +        self.name = _ustr(self)
    +        self.errmsg = "Expected " + self.name
    +        self.mayIndexError = False
    +        self.mayReturnEmpty = True
    +
    +    def parseImpl( self, instring, loc, doActions=True ):
    +        result = instring[loc] == self.firstQuoteChar and self.re.match(instring,loc) or None
    +        if not result:
    +            raise ParseException(instring, loc, self.errmsg, self)
    +
    +        loc = result.end()
    +        ret = result.group()
    +
    +        if self.unquoteResults:
    +
    +            # strip off quotes
    +            ret = ret[self.quoteCharLen:-self.endQuoteCharLen]
    +
    +            if isinstance(ret,basestring):
    +                # replace escaped whitespace
    +                if '\\' in ret and self.convertWhitespaceEscapes:
    +                    ws_map = {
    +                        r'\t' : '\t',
    +                        r'\n' : '\n',
    +                        r'\f' : '\f',
    +                        r'\r' : '\r',
    +                    }
    +                    for wslit,wschar in ws_map.items():
    +                        ret = ret.replace(wslit, wschar)
    +
    +                # replace escaped characters
    +                if self.escChar:
    +                    ret = re.sub(self.escCharReplacePattern, r"\g<1>", ret)
    +
    +                # replace escaped quotes
    +                if self.escQuote:
    +                    ret = ret.replace(self.escQuote, self.endQuoteChar)
    +
    +        return loc, ret
    +
    +    def __str__( self ):
    +        try:
    +            return super(QuotedString,self).__str__()
    +        except Exception:
    +            pass
    +
    +        if self.strRepr is None:
    +            self.strRepr = "quoted string, starting with %s ending with %s" % (self.quoteChar, self.endQuoteChar)
    +
    +        return self.strRepr
    +
    +
    +class CharsNotIn(Token):
    +    """
    +    Token for matching words composed of characters I{not} in a given set (will
    +    include whitespace in matched characters if not listed in the provided exclusion set - see example).
    +    Defined with string containing all disallowed characters, and an optional
    +    minimum, maximum, and/or exact length.  The default value for C{min} is 1 (a
    +    minimum value < 1 is not valid); the default values for C{max} and C{exact}
    +    are 0, meaning no maximum or exact length restriction.
    +
    +    Example::
    +        # define a comma-separated-value as anything that is not a ','
    +        csv_value = CharsNotIn(',')
    +        print(delimitedList(csv_value).parseString("dkls,lsdkjf,s12 34,@!#,213"))
    +    prints::
    +        ['dkls', 'lsdkjf', 's12 34', '@!#', '213']
    +    """
    +    def __init__( self, notChars, min=1, max=0, exact=0 ):
    +        super(CharsNotIn,self).__init__()
    +        self.skipWhitespace = False
    +        self.notChars = notChars
    +
    +        if min < 1:
    +            raise ValueError("cannot specify a minimum length < 1; use Optional(CharsNotIn()) if zero-length char group is permitted")
    +
    +        self.minLen = min
    +
    +        if max > 0:
    +            self.maxLen = max
    +        else:
    +            self.maxLen = _MAX_INT
    +
    +        if exact > 0:
    +            self.maxLen = exact
    +            self.minLen = exact
    +
    +        self.name = _ustr(self)
    +        self.errmsg = "Expected " + self.name
    +        self.mayReturnEmpty = ( self.minLen == 0 )
    +        self.mayIndexError = False
    +
    +    def parseImpl( self, instring, loc, doActions=True ):
    +        if instring[loc] in self.notChars:
    +            raise ParseException(instring, loc, self.errmsg, self)
    +
    +        start = loc
    +        loc += 1
    +        notchars = self.notChars
    +        maxlen = min( start+self.maxLen, len(instring) )
    +        while loc < maxlen and \
    +              (instring[loc] not in notchars):
    +            loc += 1
    +
    +        if loc - start < self.minLen:
    +            raise ParseException(instring, loc, self.errmsg, self)
    +
    +        return loc, instring[start:loc]
    +
    +    def __str__( self ):
    +        try:
    +            return super(CharsNotIn, self).__str__()
    +        except Exception:
    +            pass
    +
    +        if self.strRepr is None:
    +            if len(self.notChars) > 4:
    +                self.strRepr = "!W:(%s...)" % self.notChars[:4]
    +            else:
    +                self.strRepr = "!W:(%s)" % self.notChars
    +
    +        return self.strRepr
    +
    +class White(Token):
    +    """
    +    Special matching class for matching whitespace.  Normally, whitespace is ignored
    +    by pyparsing grammars.  This class is included when some whitespace structures
    +    are significant.  Define with a string containing the whitespace characters to be
    +    matched; default is C{" \\t\\r\\n"}.  Also takes optional C{min}, C{max}, and C{exact} arguments,
    +    as defined for the C{L{Word}} class.
    +    """
    +    whiteStrs = {
    +        " " : "",
    +        "\t": "",
    +        "\n": "",
    +        "\r": "",
    +        "\f": "",
    +        }
    +    def __init__(self, ws=" \t\r\n", min=1, max=0, exact=0):
    +        super(White,self).__init__()
    +        self.matchWhite = ws
    +        self.setWhitespaceChars( "".join(c for c in self.whiteChars if c not in self.matchWhite) )
    +        #~ self.leaveWhitespace()
    +        self.name = ("".join(White.whiteStrs[c] for c in self.matchWhite))
    +        self.mayReturnEmpty = True
    +        self.errmsg = "Expected " + self.name
    +
    +        self.minLen = min
    +
    +        if max > 0:
    +            self.maxLen = max
    +        else:
    +            self.maxLen = _MAX_INT
    +
    +        if exact > 0:
    +            self.maxLen = exact
    +            self.minLen = exact
    +
    +    def parseImpl( self, instring, loc, doActions=True ):
    +        if not(instring[ loc ] in self.matchWhite):
    +            raise ParseException(instring, loc, self.errmsg, self)
    +        start = loc
    +        loc += 1
    +        maxloc = start + self.maxLen
    +        maxloc = min( maxloc, len(instring) )
    +        while loc < maxloc and instring[loc] in self.matchWhite:
    +            loc += 1
    +
    +        if loc - start < self.minLen:
    +            raise ParseException(instring, loc, self.errmsg, self)
    +
    +        return loc, instring[start:loc]
    +
    +
    +class _PositionToken(Token):
    +    def __init__( self ):
    +        super(_PositionToken,self).__init__()
    +        self.name=self.__class__.__name__
    +        self.mayReturnEmpty = True
    +        self.mayIndexError = False
    +
    +class GoToColumn(_PositionToken):
    +    """
    +    Token to advance to a specific column of input text; useful for tabular report scraping.
    +    """
    +    def __init__( self, colno ):
    +        super(GoToColumn,self).__init__()
    +        self.col = colno
    +
    +    def preParse( self, instring, loc ):
    +        if col(loc,instring) != self.col:
    +            instrlen = len(instring)
    +            if self.ignoreExprs:
    +                loc = self._skipIgnorables( instring, loc )
    +            while loc < instrlen and instring[loc].isspace() and col( loc, instring ) != self.col :
    +                loc += 1
    +        return loc
    +
    +    def parseImpl( self, instring, loc, doActions=True ):
    +        thiscol = col( loc, instring )
    +        if thiscol > self.col:
    +            raise ParseException( instring, loc, "Text not in expected column", self )
    +        newloc = loc + self.col - thiscol
    +        ret = instring[ loc: newloc ]
    +        return newloc, ret
    +
    +
    +class LineStart(_PositionToken):
    +    """
    +    Matches if current position is at the beginning of a line within the parse string
    +    
    +    Example::
    +    
    +        test = '''\
    +        AAA this line
    +        AAA and this line
    +          AAA but not this one
    +        B AAA and definitely not this one
    +        '''
    +
    +        for t in (LineStart() + 'AAA' + restOfLine).searchString(test):
    +            print(t)
    +    
    +    Prints::
    +        ['AAA', ' this line']
    +        ['AAA', ' and this line']    
    +
    +    """
    +    def __init__( self ):
    +        super(LineStart,self).__init__()
    +        self.errmsg = "Expected start of line"
    +
    +    def parseImpl( self, instring, loc, doActions=True ):
    +        if col(loc, instring) == 1:
    +            return loc, []
    +        raise ParseException(instring, loc, self.errmsg, self)
    +
    +class LineEnd(_PositionToken):
    +    """
    +    Matches if current position is at the end of a line within the parse string
    +    """
    +    def __init__( self ):
    +        super(LineEnd,self).__init__()
    +        self.setWhitespaceChars( ParserElement.DEFAULT_WHITE_CHARS.replace("\n","") )
    +        self.errmsg = "Expected end of line"
    +
    +    def parseImpl( self, instring, loc, doActions=True ):
    +        if loc len(instring):
    +            return loc, []
    +        else:
    +            raise ParseException(instring, loc, self.errmsg, self)
    +
    +class WordStart(_PositionToken):
    +    """
    +    Matches if the current position is at the beginning of a Word, and
    +    is not preceded by any character in a given set of C{wordChars}
    +    (default=C{printables}). To emulate the C{\b} behavior of regular expressions,
    +    use C{WordStart(alphanums)}. C{WordStart} will also match at the beginning of
    +    the string being parsed, or at the beginning of a line.
    +    """
    +    def __init__(self, wordChars = printables):
    +        super(WordStart,self).__init__()
    +        self.wordChars = set(wordChars)
    +        self.errmsg = "Not at the start of a word"
    +
    +    def parseImpl(self, instring, loc, doActions=True ):
    +        if loc != 0:
    +            if (instring[loc-1] in self.wordChars or
    +                instring[loc] not in self.wordChars):
    +                raise ParseException(instring, loc, self.errmsg, self)
    +        return loc, []
    +
    +class WordEnd(_PositionToken):
    +    """
    +    Matches if the current position is at the end of a Word, and
    +    is not followed by any character in a given set of C{wordChars}
    +    (default=C{printables}). To emulate the C{\b} behavior of regular expressions,
    +    use C{WordEnd(alphanums)}. C{WordEnd} will also match at the end of
    +    the string being parsed, or at the end of a line.
    +    """
    +    def __init__(self, wordChars = printables):
    +        super(WordEnd,self).__init__()
    +        self.wordChars = set(wordChars)
    +        self.skipWhitespace = False
    +        self.errmsg = "Not at the end of a word"
    +
    +    def parseImpl(self, instring, loc, doActions=True ):
    +        instrlen = len(instring)
    +        if instrlen>0 and loc maxExcLoc:
    +                    maxException = err
    +                    maxExcLoc = err.loc
    +            except IndexError:
    +                if len(instring) > maxExcLoc:
    +                    maxException = ParseException(instring,len(instring),e.errmsg,self)
    +                    maxExcLoc = len(instring)
    +            else:
    +                # save match among all matches, to retry longest to shortest
    +                matches.append((loc2, e))
    +
    +        if matches:
    +            matches.sort(key=lambda x: -x[0])
    +            for _,e in matches:
    +                try:
    +                    return e._parse( instring, loc, doActions )
    +                except ParseException as err:
    +                    err.__traceback__ = None
    +                    if err.loc > maxExcLoc:
    +                        maxException = err
    +                        maxExcLoc = err.loc
    +
    +        if maxException is not None:
    +            maxException.msg = self.errmsg
    +            raise maxException
    +        else:
    +            raise ParseException(instring, loc, "no defined alternatives to match", self)
    +
    +
    +    def __ixor__(self, other ):
    +        if isinstance( other, basestring ):
    +            other = ParserElement._literalStringClass( other )
    +        return self.append( other ) #Or( [ self, other ] )
    +
    +    def __str__( self ):
    +        if hasattr(self,"name"):
    +            return self.name
    +
    +        if self.strRepr is None:
    +            self.strRepr = "{" + " ^ ".join(_ustr(e) for e in self.exprs) + "}"
    +
    +        return self.strRepr
    +
    +    def checkRecursion( self, parseElementList ):
    +        subRecCheckList = parseElementList[:] + [ self ]
    +        for e in self.exprs:
    +            e.checkRecursion( subRecCheckList )
    +
    +
    +class MatchFirst(ParseExpression):
    +    """
    +    Requires that at least one C{ParseExpression} is found.
    +    If two expressions match, the first one listed is the one that will match.
    +    May be constructed using the C{'|'} operator.
    +
    +    Example::
    +        # construct MatchFirst using '|' operator
    +        
    +        # watch the order of expressions to match
    +        number = Word(nums) | Combine(Word(nums) + '.' + Word(nums))
    +        print(number.searchString("123 3.1416 789")) #  Fail! -> [['123'], ['3'], ['1416'], ['789']]
    +
    +        # put more selective expression first
    +        number = Combine(Word(nums) + '.' + Word(nums)) | Word(nums)
    +        print(number.searchString("123 3.1416 789")) #  Better -> [['123'], ['3.1416'], ['789']]
    +    """
    +    def __init__( self, exprs, savelist = False ):
    +        super(MatchFirst,self).__init__(exprs, savelist)
    +        if self.exprs:
    +            self.mayReturnEmpty = any(e.mayReturnEmpty for e in self.exprs)
    +        else:
    +            self.mayReturnEmpty = True
    +
    +    def parseImpl( self, instring, loc, doActions=True ):
    +        maxExcLoc = -1
    +        maxException = None
    +        for e in self.exprs:
    +            try:
    +                ret = e._parse( instring, loc, doActions )
    +                return ret
    +            except ParseException as err:
    +                if err.loc > maxExcLoc:
    +                    maxException = err
    +                    maxExcLoc = err.loc
    +            except IndexError:
    +                if len(instring) > maxExcLoc:
    +                    maxException = ParseException(instring,len(instring),e.errmsg,self)
    +                    maxExcLoc = len(instring)
    +
    +        # only got here if no expression matched, raise exception for match that made it the furthest
    +        else:
    +            if maxException is not None:
    +                maxException.msg = self.errmsg
    +                raise maxException
    +            else:
    +                raise ParseException(instring, loc, "no defined alternatives to match", self)
    +
    +    def __ior__(self, other ):
    +        if isinstance( other, basestring ):
    +            other = ParserElement._literalStringClass( other )
    +        return self.append( other ) #MatchFirst( [ self, other ] )
    +
    +    def __str__( self ):
    +        if hasattr(self,"name"):
    +            return self.name
    +
    +        if self.strRepr is None:
    +            self.strRepr = "{" + " | ".join(_ustr(e) for e in self.exprs) + "}"
    +
    +        return self.strRepr
    +
    +    def checkRecursion( self, parseElementList ):
    +        subRecCheckList = parseElementList[:] + [ self ]
    +        for e in self.exprs:
    +            e.checkRecursion( subRecCheckList )
    +
    +
    +class Each(ParseExpression):
    +    """
    +    Requires all given C{ParseExpression}s to be found, but in any order.
    +    Expressions may be separated by whitespace.
    +    May be constructed using the C{'&'} operator.
    +
    +    Example::
    +        color = oneOf("RED ORANGE YELLOW GREEN BLUE PURPLE BLACK WHITE BROWN")
    +        shape_type = oneOf("SQUARE CIRCLE TRIANGLE STAR HEXAGON OCTAGON")
    +        integer = Word(nums)
    +        shape_attr = "shape:" + shape_type("shape")
    +        posn_attr = "posn:" + Group(integer("x") + ',' + integer("y"))("posn")
    +        color_attr = "color:" + color("color")
    +        size_attr = "size:" + integer("size")
    +
    +        # use Each (using operator '&') to accept attributes in any order 
    +        # (shape and posn are required, color and size are optional)
    +        shape_spec = shape_attr & posn_attr & Optional(color_attr) & Optional(size_attr)
    +
    +        shape_spec.runTests('''
    +            shape: SQUARE color: BLACK posn: 100, 120
    +            shape: CIRCLE size: 50 color: BLUE posn: 50,80
    +            color:GREEN size:20 shape:TRIANGLE posn:20,40
    +            '''
    +            )
    +    prints::
    +        shape: SQUARE color: BLACK posn: 100, 120
    +        ['shape:', 'SQUARE', 'color:', 'BLACK', 'posn:', ['100', ',', '120']]
    +        - color: BLACK
    +        - posn: ['100', ',', '120']
    +          - x: 100
    +          - y: 120
    +        - shape: SQUARE
    +
    +
    +        shape: CIRCLE size: 50 color: BLUE posn: 50,80
    +        ['shape:', 'CIRCLE', 'size:', '50', 'color:', 'BLUE', 'posn:', ['50', ',', '80']]
    +        - color: BLUE
    +        - posn: ['50', ',', '80']
    +          - x: 50
    +          - y: 80
    +        - shape: CIRCLE
    +        - size: 50
    +
    +
    +        color: GREEN size: 20 shape: TRIANGLE posn: 20,40
    +        ['color:', 'GREEN', 'size:', '20', 'shape:', 'TRIANGLE', 'posn:', ['20', ',', '40']]
    +        - color: GREEN
    +        - posn: ['20', ',', '40']
    +          - x: 20
    +          - y: 40
    +        - shape: TRIANGLE
    +        - size: 20
    +    """
    +    def __init__( self, exprs, savelist = True ):
    +        super(Each,self).__init__(exprs, savelist)
    +        self.mayReturnEmpty = all(e.mayReturnEmpty for e in self.exprs)
    +        self.skipWhitespace = True
    +        self.initExprGroups = True
    +
    +    def parseImpl( self, instring, loc, doActions=True ):
    +        if self.initExprGroups:
    +            self.opt1map = dict((id(e.expr),e) for e in self.exprs if isinstance(e,Optional))
    +            opt1 = [ e.expr for e in self.exprs if isinstance(e,Optional) ]
    +            opt2 = [ e for e in self.exprs if e.mayReturnEmpty and not isinstance(e,Optional)]
    +            self.optionals = opt1 + opt2
    +            self.multioptionals = [ e.expr for e in self.exprs if isinstance(e,ZeroOrMore) ]
    +            self.multirequired = [ e.expr for e in self.exprs if isinstance(e,OneOrMore) ]
    +            self.required = [ e for e in self.exprs if not isinstance(e,(Optional,ZeroOrMore,OneOrMore)) ]
    +            self.required += self.multirequired
    +            self.initExprGroups = False
    +        tmpLoc = loc
    +        tmpReqd = self.required[:]
    +        tmpOpt  = self.optionals[:]
    +        matchOrder = []
    +
    +        keepMatching = True
    +        while keepMatching:
    +            tmpExprs = tmpReqd + tmpOpt + self.multioptionals + self.multirequired
    +            failed = []
    +            for e in tmpExprs:
    +                try:
    +                    tmpLoc = e.tryParse( instring, tmpLoc )
    +                except ParseException:
    +                    failed.append(e)
    +                else:
    +                    matchOrder.append(self.opt1map.get(id(e),e))
    +                    if e in tmpReqd:
    +                        tmpReqd.remove(e)
    +                    elif e in tmpOpt:
    +                        tmpOpt.remove(e)
    +            if len(failed) == len(tmpExprs):
    +                keepMatching = False
    +
    +        if tmpReqd:
    +            missing = ", ".join(_ustr(e) for e in tmpReqd)
    +            raise ParseException(instring,loc,"Missing one or more required elements (%s)" % missing )
    +
    +        # add any unmatched Optionals, in case they have default values defined
    +        matchOrder += [e for e in self.exprs if isinstance(e,Optional) and e.expr in tmpOpt]
    +
    +        resultlist = []
    +        for e in matchOrder:
    +            loc,results = e._parse(instring,loc,doActions)
    +            resultlist.append(results)
    +
    +        finalResults = sum(resultlist, ParseResults([]))
    +        return loc, finalResults
    +
    +    def __str__( self ):
    +        if hasattr(self,"name"):
    +            return self.name
    +
    +        if self.strRepr is None:
    +            self.strRepr = "{" + " & ".join(_ustr(e) for e in self.exprs) + "}"
    +
    +        return self.strRepr
    +
    +    def checkRecursion( self, parseElementList ):
    +        subRecCheckList = parseElementList[:] + [ self ]
    +        for e in self.exprs:
    +            e.checkRecursion( subRecCheckList )
    +
    +
    +class ParseElementEnhance(ParserElement):
    +    """
    +    Abstract subclass of C{ParserElement}, for combining and post-processing parsed tokens.
    +    """
    +    def __init__( self, expr, savelist=False ):
    +        super(ParseElementEnhance,self).__init__(savelist)
    +        if isinstance( expr, basestring ):
    +            if issubclass(ParserElement._literalStringClass, Token):
    +                expr = ParserElement._literalStringClass(expr)
    +            else:
    +                expr = ParserElement._literalStringClass(Literal(expr))
    +        self.expr = expr
    +        self.strRepr = None
    +        if expr is not None:
    +            self.mayIndexError = expr.mayIndexError
    +            self.mayReturnEmpty = expr.mayReturnEmpty
    +            self.setWhitespaceChars( expr.whiteChars )
    +            self.skipWhitespace = expr.skipWhitespace
    +            self.saveAsList = expr.saveAsList
    +            self.callPreparse = expr.callPreparse
    +            self.ignoreExprs.extend(expr.ignoreExprs)
    +
    +    def parseImpl( self, instring, loc, doActions=True ):
    +        if self.expr is not None:
    +            return self.expr._parse( instring, loc, doActions, callPreParse=False )
    +        else:
    +            raise ParseException("",loc,self.errmsg,self)
    +
    +    def leaveWhitespace( self ):
    +        self.skipWhitespace = False
    +        self.expr = self.expr.copy()
    +        if self.expr is not None:
    +            self.expr.leaveWhitespace()
    +        return self
    +
    +    def ignore( self, other ):
    +        if isinstance( other, Suppress ):
    +            if other not in self.ignoreExprs:
    +                super( ParseElementEnhance, self).ignore( other )
    +                if self.expr is not None:
    +                    self.expr.ignore( self.ignoreExprs[-1] )
    +        else:
    +            super( ParseElementEnhance, self).ignore( other )
    +            if self.expr is not None:
    +                self.expr.ignore( self.ignoreExprs[-1] )
    +        return self
    +
    +    def streamline( self ):
    +        super(ParseElementEnhance,self).streamline()
    +        if self.expr is not None:
    +            self.expr.streamline()
    +        return self
    +
    +    def checkRecursion( self, parseElementList ):
    +        if self in parseElementList:
    +            raise RecursiveGrammarException( parseElementList+[self] )
    +        subRecCheckList = parseElementList[:] + [ self ]
    +        if self.expr is not None:
    +            self.expr.checkRecursion( subRecCheckList )
    +
    +    def validate( self, validateTrace=[] ):
    +        tmp = validateTrace[:]+[self]
    +        if self.expr is not None:
    +            self.expr.validate(tmp)
    +        self.checkRecursion( [] )
    +
    +    def __str__( self ):
    +        try:
    +            return super(ParseElementEnhance,self).__str__()
    +        except Exception:
    +            pass
    +
    +        if self.strRepr is None and self.expr is not None:
    +            self.strRepr = "%s:(%s)" % ( self.__class__.__name__, _ustr(self.expr) )
    +        return self.strRepr
    +
    +
    +class FollowedBy(ParseElementEnhance):
    +    """
    +    Lookahead matching of the given parse expression.  C{FollowedBy}
    +    does I{not} advance the parsing position within the input string, it only
    +    verifies that the specified parse expression matches at the current
    +    position.  C{FollowedBy} always returns a null token list.
    +
    +    Example::
    +        # use FollowedBy to match a label only if it is followed by a ':'
    +        data_word = Word(alphas)
    +        label = data_word + FollowedBy(':')
    +        attr_expr = Group(label + Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join))
    +        
    +        OneOrMore(attr_expr).parseString("shape: SQUARE color: BLACK posn: upper left").pprint()
    +    prints::
    +        [['shape', 'SQUARE'], ['color', 'BLACK'], ['posn', 'upper left']]
    +    """
    +    def __init__( self, expr ):
    +        super(FollowedBy,self).__init__(expr)
    +        self.mayReturnEmpty = True
    +
    +    def parseImpl( self, instring, loc, doActions=True ):
    +        self.expr.tryParse( instring, loc )
    +        return loc, []
    +
    +
    +class NotAny(ParseElementEnhance):
    +    """
    +    Lookahead to disallow matching with the given parse expression.  C{NotAny}
    +    does I{not} advance the parsing position within the input string, it only
    +    verifies that the specified parse expression does I{not} match at the current
    +    position.  Also, C{NotAny} does I{not} skip over leading whitespace. C{NotAny}
    +    always returns a null token list.  May be constructed using the '~' operator.
    +
    +    Example::
    +        
    +    """
    +    def __init__( self, expr ):
    +        super(NotAny,self).__init__(expr)
    +        #~ self.leaveWhitespace()
    +        self.skipWhitespace = False  # do NOT use self.leaveWhitespace(), don't want to propagate to exprs
    +        self.mayReturnEmpty = True
    +        self.errmsg = "Found unwanted token, "+_ustr(self.expr)
    +
    +    def parseImpl( self, instring, loc, doActions=True ):
    +        if self.expr.canParseNext(instring, loc):
    +            raise ParseException(instring, loc, self.errmsg, self)
    +        return loc, []
    +
    +    def __str__( self ):
    +        if hasattr(self,"name"):
    +            return self.name
    +
    +        if self.strRepr is None:
    +            self.strRepr = "~{" + _ustr(self.expr) + "}"
    +
    +        return self.strRepr
    +
    +class _MultipleMatch(ParseElementEnhance):
    +    def __init__( self, expr, stopOn=None):
    +        super(_MultipleMatch, self).__init__(expr)
    +        self.saveAsList = True
    +        ender = stopOn
    +        if isinstance(ender, basestring):
    +            ender = ParserElement._literalStringClass(ender)
    +        self.not_ender = ~ender if ender is not None else None
    +
    +    def parseImpl( self, instring, loc, doActions=True ):
    +        self_expr_parse = self.expr._parse
    +        self_skip_ignorables = self._skipIgnorables
    +        check_ender = self.not_ender is not None
    +        if check_ender:
    +            try_not_ender = self.not_ender.tryParse
    +        
    +        # must be at least one (but first see if we are the stopOn sentinel;
    +        # if so, fail)
    +        if check_ender:
    +            try_not_ender(instring, loc)
    +        loc, tokens = self_expr_parse( instring, loc, doActions, callPreParse=False )
    +        try:
    +            hasIgnoreExprs = (not not self.ignoreExprs)
    +            while 1:
    +                if check_ender:
    +                    try_not_ender(instring, loc)
    +                if hasIgnoreExprs:
    +                    preloc = self_skip_ignorables( instring, loc )
    +                else:
    +                    preloc = loc
    +                loc, tmptokens = self_expr_parse( instring, preloc, doActions )
    +                if tmptokens or tmptokens.haskeys():
    +                    tokens += tmptokens
    +        except (ParseException,IndexError):
    +            pass
    +
    +        return loc, tokens
    +        
    +class OneOrMore(_MultipleMatch):
    +    """
    +    Repetition of one or more of the given expression.
    +    
    +    Parameters:
    +     - expr - expression that must match one or more times
    +     - stopOn - (default=C{None}) - expression for a terminating sentinel
    +          (only required if the sentinel would ordinarily match the repetition 
    +          expression)          
    +
    +    Example::
    +        data_word = Word(alphas)
    +        label = data_word + FollowedBy(':')
    +        attr_expr = Group(label + Suppress(':') + OneOrMore(data_word).setParseAction(' '.join))
    +
    +        text = "shape: SQUARE posn: upper left color: BLACK"
    +        OneOrMore(attr_expr).parseString(text).pprint()  # Fail! read 'color' as data instead of next label -> [['shape', 'SQUARE color']]
    +
    +        # use stopOn attribute for OneOrMore to avoid reading label string as part of the data
    +        attr_expr = Group(label + Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join))
    +        OneOrMore(attr_expr).parseString(text).pprint() # Better -> [['shape', 'SQUARE'], ['posn', 'upper left'], ['color', 'BLACK']]
    +        
    +        # could also be written as
    +        (attr_expr * (1,)).parseString(text).pprint()
    +    """
    +
    +    def __str__( self ):
    +        if hasattr(self,"name"):
    +            return self.name
    +
    +        if self.strRepr is None:
    +            self.strRepr = "{" + _ustr(self.expr) + "}..."
    +
    +        return self.strRepr
    +
    +class ZeroOrMore(_MultipleMatch):
    +    """
    +    Optional repetition of zero or more of the given expression.
    +    
    +    Parameters:
    +     - expr - expression that must match zero or more times
    +     - stopOn - (default=C{None}) - expression for a terminating sentinel
    +          (only required if the sentinel would ordinarily match the repetition 
    +          expression)          
    +
    +    Example: similar to L{OneOrMore}
    +    """
    +    def __init__( self, expr, stopOn=None):
    +        super(ZeroOrMore,self).__init__(expr, stopOn=stopOn)
    +        self.mayReturnEmpty = True
    +        
    +    def parseImpl( self, instring, loc, doActions=True ):
    +        try:
    +            return super(ZeroOrMore, self).parseImpl(instring, loc, doActions)
    +        except (ParseException,IndexError):
    +            return loc, []
    +
    +    def __str__( self ):
    +        if hasattr(self,"name"):
    +            return self.name
    +
    +        if self.strRepr is None:
    +            self.strRepr = "[" + _ustr(self.expr) + "]..."
    +
    +        return self.strRepr
    +
    +class _NullToken(object):
    +    def __bool__(self):
    +        return False
    +    __nonzero__ = __bool__
    +    def __str__(self):
    +        return ""
    +
    +_optionalNotMatched = _NullToken()
    +class Optional(ParseElementEnhance):
    +    """
    +    Optional matching of the given expression.
    +
    +    Parameters:
    +     - expr - expression that must match zero or more times
    +     - default (optional) - value to be returned if the optional expression is not found.
    +
    +    Example::
    +        # US postal code can be a 5-digit zip, plus optional 4-digit qualifier
    +        zip = Combine(Word(nums, exact=5) + Optional('-' + Word(nums, exact=4)))
    +        zip.runTests('''
    +            # traditional ZIP code
    +            12345
    +            
    +            # ZIP+4 form
    +            12101-0001
    +            
    +            # invalid ZIP
    +            98765-
    +            ''')
    +    prints::
    +        # traditional ZIP code
    +        12345
    +        ['12345']
    +
    +        # ZIP+4 form
    +        12101-0001
    +        ['12101-0001']
    +
    +        # invalid ZIP
    +        98765-
    +             ^
    +        FAIL: Expected end of text (at char 5), (line:1, col:6)
    +    """
    +    def __init__( self, expr, default=_optionalNotMatched ):
    +        super(Optional,self).__init__( expr, savelist=False )
    +        self.saveAsList = self.expr.saveAsList
    +        self.defaultValue = default
    +        self.mayReturnEmpty = True
    +
    +    def parseImpl( self, instring, loc, doActions=True ):
    +        try:
    +            loc, tokens = self.expr._parse( instring, loc, doActions, callPreParse=False )
    +        except (ParseException,IndexError):
    +            if self.defaultValue is not _optionalNotMatched:
    +                if self.expr.resultsName:
    +                    tokens = ParseResults([ self.defaultValue ])
    +                    tokens[self.expr.resultsName] = self.defaultValue
    +                else:
    +                    tokens = [ self.defaultValue ]
    +            else:
    +                tokens = []
    +        return loc, tokens
    +
    +    def __str__( self ):
    +        if hasattr(self,"name"):
    +            return self.name
    +
    +        if self.strRepr is None:
    +            self.strRepr = "[" + _ustr(self.expr) + "]"
    +
    +        return self.strRepr
    +
    +class SkipTo(ParseElementEnhance):
    +    """
    +    Token for skipping over all undefined text until the matched expression is found.
    +
    +    Parameters:
    +     - expr - target expression marking the end of the data to be skipped
    +     - include - (default=C{False}) if True, the target expression is also parsed 
    +          (the skipped text and target expression are returned as a 2-element list).
    +     - ignore - (default=C{None}) used to define grammars (typically quoted strings and 
    +          comments) that might contain false matches to the target expression
    +     - failOn - (default=C{None}) define expressions that are not allowed to be 
    +          included in the skipped test; if found before the target expression is found, 
    +          the SkipTo is not a match
    +
    +    Example::
    +        report = '''
    +            Outstanding Issues Report - 1 Jan 2000
    +
    +               # | Severity | Description                               |  Days Open
    +            -----+----------+-------------------------------------------+-----------
    +             101 | Critical | Intermittent system crash                 |          6
    +              94 | Cosmetic | Spelling error on Login ('log|n')         |         14
    +              79 | Minor    | System slow when running too many reports |         47
    +            '''
    +        integer = Word(nums)
    +        SEP = Suppress('|')
    +        # use SkipTo to simply match everything up until the next SEP
    +        # - ignore quoted strings, so that a '|' character inside a quoted string does not match
    +        # - parse action will call token.strip() for each matched token, i.e., the description body
    +        string_data = SkipTo(SEP, ignore=quotedString)
    +        string_data.setParseAction(tokenMap(str.strip))
    +        ticket_expr = (integer("issue_num") + SEP 
    +                      + string_data("sev") + SEP 
    +                      + string_data("desc") + SEP 
    +                      + integer("days_open"))
    +        
    +        for tkt in ticket_expr.searchString(report):
    +            print tkt.dump()
    +    prints::
    +        ['101', 'Critical', 'Intermittent system crash', '6']
    +        - days_open: 6
    +        - desc: Intermittent system crash
    +        - issue_num: 101
    +        - sev: Critical
    +        ['94', 'Cosmetic', "Spelling error on Login ('log|n')", '14']
    +        - days_open: 14
    +        - desc: Spelling error on Login ('log|n')
    +        - issue_num: 94
    +        - sev: Cosmetic
    +        ['79', 'Minor', 'System slow when running too many reports', '47']
    +        - days_open: 47
    +        - desc: System slow when running too many reports
    +        - issue_num: 79
    +        - sev: Minor
    +    """
    +    def __init__( self, other, include=False, ignore=None, failOn=None ):
    +        super( SkipTo, self ).__init__( other )
    +        self.ignoreExpr = ignore
    +        self.mayReturnEmpty = True
    +        self.mayIndexError = False
    +        self.includeMatch = include
    +        self.asList = False
    +        if isinstance(failOn, basestring):
    +            self.failOn = ParserElement._literalStringClass(failOn)
    +        else:
    +            self.failOn = failOn
    +        self.errmsg = "No match found for "+_ustr(self.expr)
    +
    +    def parseImpl( self, instring, loc, doActions=True ):
    +        startloc = loc
    +        instrlen = len(instring)
    +        expr = self.expr
    +        expr_parse = self.expr._parse
    +        self_failOn_canParseNext = self.failOn.canParseNext if self.failOn is not None else None
    +        self_ignoreExpr_tryParse = self.ignoreExpr.tryParse if self.ignoreExpr is not None else None
    +        
    +        tmploc = loc
    +        while tmploc <= instrlen:
    +            if self_failOn_canParseNext is not None:
    +                # break if failOn expression matches
    +                if self_failOn_canParseNext(instring, tmploc):
    +                    break
    +                    
    +            if self_ignoreExpr_tryParse is not None:
    +                # advance past ignore expressions
    +                while 1:
    +                    try:
    +                        tmploc = self_ignoreExpr_tryParse(instring, tmploc)
    +                    except ParseBaseException:
    +                        break
    +            
    +            try:
    +                expr_parse(instring, tmploc, doActions=False, callPreParse=False)
    +            except (ParseException, IndexError):
    +                # no match, advance loc in string
    +                tmploc += 1
    +            else:
    +                # matched skipto expr, done
    +                break
    +
    +        else:
    +            # ran off the end of the input string without matching skipto expr, fail
    +            raise ParseException(instring, loc, self.errmsg, self)
    +
    +        # build up return values
    +        loc = tmploc
    +        skiptext = instring[startloc:loc]
    +        skipresult = ParseResults(skiptext)
    +        
    +        if self.includeMatch:
    +            loc, mat = expr_parse(instring,loc,doActions,callPreParse=False)
    +            skipresult += mat
    +
    +        return loc, skipresult
    +
    +class Forward(ParseElementEnhance):
    +    """
    +    Forward declaration of an expression to be defined later -
    +    used for recursive grammars, such as algebraic infix notation.
    +    When the expression is known, it is assigned to the C{Forward} variable using the '<<' operator.
    +
    +    Note: take care when assigning to C{Forward} not to overlook precedence of operators.
    +    Specifically, '|' has a lower precedence than '<<', so that::
    +        fwdExpr << a | b | c
    +    will actually be evaluated as::
    +        (fwdExpr << a) | b | c
    +    thereby leaving b and c out as parseable alternatives.  It is recommended that you
    +    explicitly group the values inserted into the C{Forward}::
    +        fwdExpr << (a | b | c)
    +    Converting to use the '<<=' operator instead will avoid this problem.
    +
    +    See L{ParseResults.pprint} for an example of a recursive parser created using
    +    C{Forward}.
    +    """
    +    def __init__( self, other=None ):
    +        super(Forward,self).__init__( other, savelist=False )
    +
    +    def __lshift__( self, other ):
    +        if isinstance( other, basestring ):
    +            other = ParserElement._literalStringClass(other)
    +        self.expr = other
    +        self.strRepr = None
    +        self.mayIndexError = self.expr.mayIndexError
    +        self.mayReturnEmpty = self.expr.mayReturnEmpty
    +        self.setWhitespaceChars( self.expr.whiteChars )
    +        self.skipWhitespace = self.expr.skipWhitespace
    +        self.saveAsList = self.expr.saveAsList
    +        self.ignoreExprs.extend(self.expr.ignoreExprs)
    +        return self
    +        
    +    def __ilshift__(self, other):
    +        return self << other
    +    
    +    def leaveWhitespace( self ):
    +        self.skipWhitespace = False
    +        return self
    +
    +    def streamline( self ):
    +        if not self.streamlined:
    +            self.streamlined = True
    +            if self.expr is not None:
    +                self.expr.streamline()
    +        return self
    +
    +    def validate( self, validateTrace=[] ):
    +        if self not in validateTrace:
    +            tmp = validateTrace[:]+[self]
    +            if self.expr is not None:
    +                self.expr.validate(tmp)
    +        self.checkRecursion([])
    +
    +    def __str__( self ):
    +        if hasattr(self,"name"):
    +            return self.name
    +        return self.__class__.__name__ + ": ..."
    +
    +        # stubbed out for now - creates awful memory and perf issues
    +        self._revertClass = self.__class__
    +        self.__class__ = _ForwardNoRecurse
    +        try:
    +            if self.expr is not None:
    +                retString = _ustr(self.expr)
    +            else:
    +                retString = "None"
    +        finally:
    +            self.__class__ = self._revertClass
    +        return self.__class__.__name__ + ": " + retString
    +
    +    def copy(self):
    +        if self.expr is not None:
    +            return super(Forward,self).copy()
    +        else:
    +            ret = Forward()
    +            ret <<= self
    +            return ret
    +
    +class _ForwardNoRecurse(Forward):
    +    def __str__( self ):
    +        return "..."
    +
    +class TokenConverter(ParseElementEnhance):
    +    """
    +    Abstract subclass of C{ParseExpression}, for converting parsed results.
    +    """
    +    def __init__( self, expr, savelist=False ):
    +        super(TokenConverter,self).__init__( expr )#, savelist )
    +        self.saveAsList = False
    +
    +class Combine(TokenConverter):
    +    """
    +    Converter to concatenate all matching tokens to a single string.
    +    By default, the matching patterns must also be contiguous in the input string;
    +    this can be disabled by specifying C{'adjacent=False'} in the constructor.
    +
    +    Example::
    +        real = Word(nums) + '.' + Word(nums)
    +        print(real.parseString('3.1416')) # -> ['3', '.', '1416']
    +        # will also erroneously match the following
    +        print(real.parseString('3. 1416')) # -> ['3', '.', '1416']
    +
    +        real = Combine(Word(nums) + '.' + Word(nums))
    +        print(real.parseString('3.1416')) # -> ['3.1416']
    +        # no match when there are internal spaces
    +        print(real.parseString('3. 1416')) # -> Exception: Expected W:(0123...)
    +    """
    +    def __init__( self, expr, joinString="", adjacent=True ):
    +        super(Combine,self).__init__( expr )
    +        # suppress whitespace-stripping in contained parse expressions, but re-enable it on the Combine itself
    +        if adjacent:
    +            self.leaveWhitespace()
    +        self.adjacent = adjacent
    +        self.skipWhitespace = True
    +        self.joinString = joinString
    +        self.callPreparse = True
    +
    +    def ignore( self, other ):
    +        if self.adjacent:
    +            ParserElement.ignore(self, other)
    +        else:
    +            super( Combine, self).ignore( other )
    +        return self
    +
    +    def postParse( self, instring, loc, tokenlist ):
    +        retToks = tokenlist.copy()
    +        del retToks[:]
    +        retToks += ParseResults([ "".join(tokenlist._asStringList(self.joinString)) ], modal=self.modalResults)
    +
    +        if self.resultsName and retToks.haskeys():
    +            return [ retToks ]
    +        else:
    +            return retToks
    +
    +class Group(TokenConverter):
    +    """
    +    Converter to return the matched tokens as a list - useful for returning tokens of C{L{ZeroOrMore}} and C{L{OneOrMore}} expressions.
    +
    +    Example::
    +        ident = Word(alphas)
    +        num = Word(nums)
    +        term = ident | num
    +        func = ident + Optional(delimitedList(term))
    +        print(func.parseString("fn a,b,100"))  # -> ['fn', 'a', 'b', '100']
    +
    +        func = ident + Group(Optional(delimitedList(term)))
    +        print(func.parseString("fn a,b,100"))  # -> ['fn', ['a', 'b', '100']]
    +    """
    +    def __init__( self, expr ):
    +        super(Group,self).__init__( expr )
    +        self.saveAsList = True
    +
    +    def postParse( self, instring, loc, tokenlist ):
    +        return [ tokenlist ]
    +
    +class Dict(TokenConverter):
    +    """
    +    Converter to return a repetitive expression as a list, but also as a dictionary.
    +    Each element can also be referenced using the first token in the expression as its key.
    +    Useful for tabular report scraping when the first column can be used as a item key.
    +
    +    Example::
    +        data_word = Word(alphas)
    +        label = data_word + FollowedBy(':')
    +        attr_expr = Group(label + Suppress(':') + OneOrMore(data_word).setParseAction(' '.join))
    +
    +        text = "shape: SQUARE posn: upper left color: light blue texture: burlap"
    +        attr_expr = (label + Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join))
    +        
    +        # print attributes as plain groups
    +        print(OneOrMore(attr_expr).parseString(text).dump())
    +        
    +        # instead of OneOrMore(expr), parse using Dict(OneOrMore(Group(expr))) - Dict will auto-assign names
    +        result = Dict(OneOrMore(Group(attr_expr))).parseString(text)
    +        print(result.dump())
    +        
    +        # access named fields as dict entries, or output as dict
    +        print(result['shape'])        
    +        print(result.asDict())
    +    prints::
    +        ['shape', 'SQUARE', 'posn', 'upper left', 'color', 'light blue', 'texture', 'burlap']
    +
    +        [['shape', 'SQUARE'], ['posn', 'upper left'], ['color', 'light blue'], ['texture', 'burlap']]
    +        - color: light blue
    +        - posn: upper left
    +        - shape: SQUARE
    +        - texture: burlap
    +        SQUARE
    +        {'color': 'light blue', 'posn': 'upper left', 'texture': 'burlap', 'shape': 'SQUARE'}
    +    See more examples at L{ParseResults} of accessing fields by results name.
    +    """
    +    def __init__( self, expr ):
    +        super(Dict,self).__init__( expr )
    +        self.saveAsList = True
    +
    +    def postParse( self, instring, loc, tokenlist ):
    +        for i,tok in enumerate(tokenlist):
    +            if len(tok) == 0:
    +                continue
    +            ikey = tok[0]
    +            if isinstance(ikey,int):
    +                ikey = _ustr(tok[0]).strip()
    +            if len(tok)==1:
    +                tokenlist[ikey] = _ParseResultsWithOffset("",i)
    +            elif len(tok)==2 and not isinstance(tok[1],ParseResults):
    +                tokenlist[ikey] = _ParseResultsWithOffset(tok[1],i)
    +            else:
    +                dictvalue = tok.copy() #ParseResults(i)
    +                del dictvalue[0]
    +                if len(dictvalue)!= 1 or (isinstance(dictvalue,ParseResults) and dictvalue.haskeys()):
    +                    tokenlist[ikey] = _ParseResultsWithOffset(dictvalue,i)
    +                else:
    +                    tokenlist[ikey] = _ParseResultsWithOffset(dictvalue[0],i)
    +
    +        if self.resultsName:
    +            return [ tokenlist ]
    +        else:
    +            return tokenlist
    +
    +
    +class Suppress(TokenConverter):
    +    """
    +    Converter for ignoring the results of a parsed expression.
    +
    +    Example::
    +        source = "a, b, c,d"
    +        wd = Word(alphas)
    +        wd_list1 = wd + ZeroOrMore(',' + wd)
    +        print(wd_list1.parseString(source))
    +
    +        # often, delimiters that are useful during parsing are just in the
    +        # way afterward - use Suppress to keep them out of the parsed output
    +        wd_list2 = wd + ZeroOrMore(Suppress(',') + wd)
    +        print(wd_list2.parseString(source))
    +    prints::
    +        ['a', ',', 'b', ',', 'c', ',', 'd']
    +        ['a', 'b', 'c', 'd']
    +    (See also L{delimitedList}.)
    +    """
    +    def postParse( self, instring, loc, tokenlist ):
    +        return []
    +
    +    def suppress( self ):
    +        return self
    +
    +
    +class OnlyOnce(object):
    +    """
    +    Wrapper for parse actions, to ensure they are only called once.
    +    """
    +    def __init__(self, methodCall):
    +        self.callable = _trim_arity(methodCall)
    +        self.called = False
    +    def __call__(self,s,l,t):
    +        if not self.called:
    +            results = self.callable(s,l,t)
    +            self.called = True
    +            return results
    +        raise ParseException(s,l,"")
    +    def reset(self):
    +        self.called = False
    +
    +def traceParseAction(f):
    +    """
    +    Decorator for debugging parse actions. 
    +    
    +    When the parse action is called, this decorator will print C{">> entering I{method-name}(line:I{current_source_line}, I{parse_location}, I{matched_tokens})".}
    +    When the parse action completes, the decorator will print C{"<<"} followed by the returned value, or any exception that the parse action raised.
    +
    +    Example::
    +        wd = Word(alphas)
    +
    +        @traceParseAction
    +        def remove_duplicate_chars(tokens):
    +            return ''.join(sorted(set(''.join(tokens))))
    +
    +        wds = OneOrMore(wd).setParseAction(remove_duplicate_chars)
    +        print(wds.parseString("slkdjs sld sldd sdlf sdljf"))
    +    prints::
    +        >>entering remove_duplicate_chars(line: 'slkdjs sld sldd sdlf sdljf', 0, (['slkdjs', 'sld', 'sldd', 'sdlf', 'sdljf'], {}))
    +        <3:
    +            thisFunc = paArgs[0].__class__.__name__ + '.' + thisFunc
    +        sys.stderr.write( ">>entering %s(line: '%s', %d, %r)\n" % (thisFunc,line(l,s),l,t) )
    +        try:
    +            ret = f(*paArgs)
    +        except Exception as exc:
    +            sys.stderr.write( "< ['aa', 'bb', 'cc']
    +        delimitedList(Word(hexnums), delim=':', combine=True).parseString("AA:BB:CC:DD:EE") # -> ['AA:BB:CC:DD:EE']
    +    """
    +    dlName = _ustr(expr)+" ["+_ustr(delim)+" "+_ustr(expr)+"]..."
    +    if combine:
    +        return Combine( expr + ZeroOrMore( delim + expr ) ).setName(dlName)
    +    else:
    +        return ( expr + ZeroOrMore( Suppress( delim ) + expr ) ).setName(dlName)
    +
    +def countedArray( expr, intExpr=None ):
    +    """
    +    Helper to define a counted list of expressions.
    +    This helper defines a pattern of the form::
    +        integer expr expr expr...
    +    where the leading integer tells how many expr expressions follow.
    +    The matched tokens returns the array of expr tokens as a list - the leading count token is suppressed.
    +    
    +    If C{intExpr} is specified, it should be a pyparsing expression that produces an integer value.
    +
    +    Example::
    +        countedArray(Word(alphas)).parseString('2 ab cd ef')  # -> ['ab', 'cd']
    +
    +        # in this parser, the leading integer value is given in binary,
    +        # '10' indicating that 2 values are in the array
    +        binaryConstant = Word('01').setParseAction(lambda t: int(t[0], 2))
    +        countedArray(Word(alphas), intExpr=binaryConstant).parseString('10 ab cd ef')  # -> ['ab', 'cd']
    +    """
    +    arrayExpr = Forward()
    +    def countFieldParseAction(s,l,t):
    +        n = t[0]
    +        arrayExpr << (n and Group(And([expr]*n)) or Group(empty))
    +        return []
    +    if intExpr is None:
    +        intExpr = Word(nums).setParseAction(lambda t:int(t[0]))
    +    else:
    +        intExpr = intExpr.copy()
    +    intExpr.setName("arrayLen")
    +    intExpr.addParseAction(countFieldParseAction, callDuringTry=True)
    +    return ( intExpr + arrayExpr ).setName('(len) ' + _ustr(expr) + '...')
    +
    +def _flatten(L):
    +    ret = []
    +    for i in L:
    +        if isinstance(i,list):
    +            ret.extend(_flatten(i))
    +        else:
    +            ret.append(i)
    +    return ret
    +
    +def matchPreviousLiteral(expr):
    +    """
    +    Helper to define an expression that is indirectly defined from
    +    the tokens matched in a previous expression, that is, it looks
    +    for a 'repeat' of a previous expression.  For example::
    +        first = Word(nums)
    +        second = matchPreviousLiteral(first)
    +        matchExpr = first + ":" + second
    +    will match C{"1:1"}, but not C{"1:2"}.  Because this matches a
    +    previous literal, will also match the leading C{"1:1"} in C{"1:10"}.
    +    If this is not desired, use C{matchPreviousExpr}.
    +    Do I{not} use with packrat parsing enabled.
    +    """
    +    rep = Forward()
    +    def copyTokenToRepeater(s,l,t):
    +        if t:
    +            if len(t) == 1:
    +                rep << t[0]
    +            else:
    +                # flatten t tokens
    +                tflat = _flatten(t.asList())
    +                rep << And(Literal(tt) for tt in tflat)
    +        else:
    +            rep << Empty()
    +    expr.addParseAction(copyTokenToRepeater, callDuringTry=True)
    +    rep.setName('(prev) ' + _ustr(expr))
    +    return rep
    +
    +def matchPreviousExpr(expr):
    +    """
    +    Helper to define an expression that is indirectly defined from
    +    the tokens matched in a previous expression, that is, it looks
    +    for a 'repeat' of a previous expression.  For example::
    +        first = Word(nums)
    +        second = matchPreviousExpr(first)
    +        matchExpr = first + ":" + second
    +    will match C{"1:1"}, but not C{"1:2"}.  Because this matches by
    +    expressions, will I{not} match the leading C{"1:1"} in C{"1:10"};
    +    the expressions are evaluated first, and then compared, so
    +    C{"1"} is compared with C{"10"}.
    +    Do I{not} use with packrat parsing enabled.
    +    """
    +    rep = Forward()
    +    e2 = expr.copy()
    +    rep <<= e2
    +    def copyTokenToRepeater(s,l,t):
    +        matchTokens = _flatten(t.asList())
    +        def mustMatchTheseTokens(s,l,t):
    +            theseTokens = _flatten(t.asList())
    +            if  theseTokens != matchTokens:
    +                raise ParseException("",0,"")
    +        rep.setParseAction( mustMatchTheseTokens, callDuringTry=True )
    +    expr.addParseAction(copyTokenToRepeater, callDuringTry=True)
    +    rep.setName('(prev) ' + _ustr(expr))
    +    return rep
    +
    +def _escapeRegexRangeChars(s):
    +    #~  escape these chars: ^-]
    +    for c in r"\^-]":
    +        s = s.replace(c,_bslash+c)
    +    s = s.replace("\n",r"\n")
    +    s = s.replace("\t",r"\t")
    +    return _ustr(s)
    +
    +def oneOf( strs, caseless=False, useRegex=True ):
    +    """
    +    Helper to quickly define a set of alternative Literals, and makes sure to do
    +    longest-first testing when there is a conflict, regardless of the input order,
    +    but returns a C{L{MatchFirst}} for best performance.
    +
    +    Parameters:
    +     - strs - a string of space-delimited literals, or a collection of string literals
    +     - caseless - (default=C{False}) - treat all literals as caseless
    +     - useRegex - (default=C{True}) - as an optimization, will generate a Regex
    +          object; otherwise, will generate a C{MatchFirst} object (if C{caseless=True}, or
    +          if creating a C{Regex} raises an exception)
    +
    +    Example::
    +        comp_oper = oneOf("< = > <= >= !=")
    +        var = Word(alphas)
    +        number = Word(nums)
    +        term = var | number
    +        comparison_expr = term + comp_oper + term
    +        print(comparison_expr.searchString("B = 12  AA=23 B<=AA AA>12"))
    +    prints::
    +        [['B', '=', '12'], ['AA', '=', '23'], ['B', '<=', 'AA'], ['AA', '>', '12']]
    +    """
    +    if caseless:
    +        isequal = ( lambda a,b: a.upper() == b.upper() )
    +        masks = ( lambda a,b: b.upper().startswith(a.upper()) )
    +        parseElementClass = CaselessLiteral
    +    else:
    +        isequal = ( lambda a,b: a == b )
    +        masks = ( lambda a,b: b.startswith(a) )
    +        parseElementClass = Literal
    +
    +    symbols = []
    +    if isinstance(strs,basestring):
    +        symbols = strs.split()
    +    elif isinstance(strs, Iterable):
    +        symbols = list(strs)
    +    else:
    +        warnings.warn("Invalid argument to oneOf, expected string or iterable",
    +                SyntaxWarning, stacklevel=2)
    +    if not symbols:
    +        return NoMatch()
    +
    +    i = 0
    +    while i < len(symbols)-1:
    +        cur = symbols[i]
    +        for j,other in enumerate(symbols[i+1:]):
    +            if ( isequal(other, cur) ):
    +                del symbols[i+j+1]
    +                break
    +            elif ( masks(cur, other) ):
    +                del symbols[i+j+1]
    +                symbols.insert(i,other)
    +                cur = other
    +                break
    +        else:
    +            i += 1
    +
    +    if not caseless and useRegex:
    +        #~ print (strs,"->", "|".join( [ _escapeRegexChars(sym) for sym in symbols] ))
    +        try:
    +            if len(symbols)==len("".join(symbols)):
    +                return Regex( "[%s]" % "".join(_escapeRegexRangeChars(sym) for sym in symbols) ).setName(' | '.join(symbols))
    +            else:
    +                return Regex( "|".join(re.escape(sym) for sym in symbols) ).setName(' | '.join(symbols))
    +        except Exception:
    +            warnings.warn("Exception creating Regex for oneOf, building MatchFirst",
    +                    SyntaxWarning, stacklevel=2)
    +
    +
    +    # last resort, just use MatchFirst
    +    return MatchFirst(parseElementClass(sym) for sym in symbols).setName(' | '.join(symbols))
    +
    +def dictOf( key, value ):
    +    """
    +    Helper to easily and clearly define a dictionary by specifying the respective patterns
    +    for the key and value.  Takes care of defining the C{L{Dict}}, C{L{ZeroOrMore}}, and C{L{Group}} tokens
    +    in the proper order.  The key pattern can include delimiting markers or punctuation,
    +    as long as they are suppressed, thereby leaving the significant key text.  The value
    +    pattern can include named results, so that the C{Dict} results can include named token
    +    fields.
    +
    +    Example::
    +        text = "shape: SQUARE posn: upper left color: light blue texture: burlap"
    +        attr_expr = (label + Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join))
    +        print(OneOrMore(attr_expr).parseString(text).dump())
    +        
    +        attr_label = label
    +        attr_value = Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join)
    +
    +        # similar to Dict, but simpler call format
    +        result = dictOf(attr_label, attr_value).parseString(text)
    +        print(result.dump())
    +        print(result['shape'])
    +        print(result.shape)  # object attribute access works too
    +        print(result.asDict())
    +    prints::
    +        [['shape', 'SQUARE'], ['posn', 'upper left'], ['color', 'light blue'], ['texture', 'burlap']]
    +        - color: light blue
    +        - posn: upper left
    +        - shape: SQUARE
    +        - texture: burlap
    +        SQUARE
    +        SQUARE
    +        {'color': 'light blue', 'shape': 'SQUARE', 'posn': 'upper left', 'texture': 'burlap'}
    +    """
    +    return Dict( ZeroOrMore( Group ( key + value ) ) )
    +
    +def originalTextFor(expr, asString=True):
    +    """
    +    Helper to return the original, untokenized text for a given expression.  Useful to
    +    restore the parsed fields of an HTML start tag into the raw tag text itself, or to
    +    revert separate tokens with intervening whitespace back to the original matching
    +    input text. By default, returns astring containing the original parsed text.  
    +       
    +    If the optional C{asString} argument is passed as C{False}, then the return value is a 
    +    C{L{ParseResults}} containing any results names that were originally matched, and a 
    +    single token containing the original matched text from the input string.  So if 
    +    the expression passed to C{L{originalTextFor}} contains expressions with defined
    +    results names, you must set C{asString} to C{False} if you want to preserve those
    +    results name values.
    +
    +    Example::
    +        src = "this is test  bold text  normal text "
    +        for tag in ("b","i"):
    +            opener,closer = makeHTMLTags(tag)
    +            patt = originalTextFor(opener + SkipTo(closer) + closer)
    +            print(patt.searchString(src)[0])
    +    prints::
    +        [' bold text ']
    +        ['text']
    +    """
    +    locMarker = Empty().setParseAction(lambda s,loc,t: loc)
    +    endlocMarker = locMarker.copy()
    +    endlocMarker.callPreparse = False
    +    matchExpr = locMarker("_original_start") + expr + endlocMarker("_original_end")
    +    if asString:
    +        extractText = lambda s,l,t: s[t._original_start:t._original_end]
    +    else:
    +        def extractText(s,l,t):
    +            t[:] = [s[t.pop('_original_start'):t.pop('_original_end')]]
    +    matchExpr.setParseAction(extractText)
    +    matchExpr.ignoreExprs = expr.ignoreExprs
    +    return matchExpr
    +
    +def ungroup(expr): 
    +    """
    +    Helper to undo pyparsing's default grouping of And expressions, even
    +    if all but one are non-empty.
    +    """
    +    return TokenConverter(expr).setParseAction(lambda t:t[0])
    +
    +def locatedExpr(expr):
    +    """
    +    Helper to decorate a returned token with its starting and ending locations in the input string.
    +    This helper adds the following results names:
    +     - locn_start = location where matched expression begins
    +     - locn_end = location where matched expression ends
    +     - value = the actual parsed results
    +
    +    Be careful if the input text contains C{} characters, you may want to call
    +    C{L{ParserElement.parseWithTabs}}
    +
    +    Example::
    +        wd = Word(alphas)
    +        for match in locatedExpr(wd).searchString("ljsdf123lksdjjf123lkkjj1222"):
    +            print(match)
    +    prints::
    +        [[0, 'ljsdf', 5]]
    +        [[8, 'lksdjjf', 15]]
    +        [[18, 'lkkjj', 23]]
    +    """
    +    locator = Empty().setParseAction(lambda s,l,t: l)
    +    return Group(locator("locn_start") + expr("value") + locator.copy().leaveWhitespace()("locn_end"))
    +
    +
    +# convenience constants for positional expressions
    +empty       = Empty().setName("empty")
    +lineStart   = LineStart().setName("lineStart")
    +lineEnd     = LineEnd().setName("lineEnd")
    +stringStart = StringStart().setName("stringStart")
    +stringEnd   = StringEnd().setName("stringEnd")
    +
    +_escapedPunc = Word( _bslash, r"\[]-*.$+^?()~ ", exact=2 ).setParseAction(lambda s,l,t:t[0][1])
    +_escapedHexChar = Regex(r"\\0?[xX][0-9a-fA-F]+").setParseAction(lambda s,l,t:unichr(int(t[0].lstrip(r'\0x'),16)))
    +_escapedOctChar = Regex(r"\\0[0-7]+").setParseAction(lambda s,l,t:unichr(int(t[0][1:],8)))
    +_singleChar = _escapedPunc | _escapedHexChar | _escapedOctChar | CharsNotIn(r'\]', exact=1)
    +_charRange = Group(_singleChar + Suppress("-") + _singleChar)
    +_reBracketExpr = Literal("[") + Optional("^").setResultsName("negate") + Group( OneOrMore( _charRange | _singleChar ) ).setResultsName("body") + "]"
    +
    +def srange(s):
    +    r"""
    +    Helper to easily define string ranges for use in Word construction.  Borrows
    +    syntax from regexp '[]' string range definitions::
    +        srange("[0-9]")   -> "0123456789"
    +        srange("[a-z]")   -> "abcdefghijklmnopqrstuvwxyz"
    +        srange("[a-z$_]") -> "abcdefghijklmnopqrstuvwxyz$_"
    +    The input string must be enclosed in []'s, and the returned string is the expanded
    +    character set joined into a single string.
    +    The values enclosed in the []'s may be:
    +     - a single character
    +     - an escaped character with a leading backslash (such as C{\-} or C{\]})
    +     - an escaped hex character with a leading C{'\x'} (C{\x21}, which is a C{'!'} character) 
    +         (C{\0x##} is also supported for backwards compatibility) 
    +     - an escaped octal character with a leading C{'\0'} (C{\041}, which is a C{'!'} character)
    +     - a range of any of the above, separated by a dash (C{'a-z'}, etc.)
    +     - any combination of the above (C{'aeiouy'}, C{'a-zA-Z0-9_$'}, etc.)
    +    """
    +    _expanded = lambda p: p if not isinstance(p,ParseResults) else ''.join(unichr(c) for c in range(ord(p[0]),ord(p[1])+1))
    +    try:
    +        return "".join(_expanded(part) for part in _reBracketExpr.parseString(s).body)
    +    except Exception:
    +        return ""
    +
    +def matchOnlyAtCol(n):
    +    """
    +    Helper method for defining parse actions that require matching at a specific
    +    column in the input text.
    +    """
    +    def verifyCol(strg,locn,toks):
    +        if col(locn,strg) != n:
    +            raise ParseException(strg,locn,"matched token not at column %d" % n)
    +    return verifyCol
    +
    +def replaceWith(replStr):
    +    """
    +    Helper method for common parse actions that simply return a literal value.  Especially
    +    useful when used with C{L{transformString}()}.
    +
    +    Example::
    +        num = Word(nums).setParseAction(lambda toks: int(toks[0]))
    +        na = oneOf("N/A NA").setParseAction(replaceWith(math.nan))
    +        term = na | num
    +        
    +        OneOrMore(term).parseString("324 234 N/A 234") # -> [324, 234, nan, 234]
    +    """
    +    return lambda s,l,t: [replStr]
    +
    +def removeQuotes(s,l,t):
    +    """
    +    Helper parse action for removing quotation marks from parsed quoted strings.
    +
    +    Example::
    +        # by default, quotation marks are included in parsed results
    +        quotedString.parseString("'Now is the Winter of our Discontent'") # -> ["'Now is the Winter of our Discontent'"]
    +
    +        # use removeQuotes to strip quotation marks from parsed results
    +        quotedString.setParseAction(removeQuotes)
    +        quotedString.parseString("'Now is the Winter of our Discontent'") # -> ["Now is the Winter of our Discontent"]
    +    """
    +    return t[0][1:-1]
    +
    +def tokenMap(func, *args):
    +    """
    +    Helper to define a parse action by mapping a function to all elements of a ParseResults list.If any additional 
    +    args are passed, they are forwarded to the given function as additional arguments after
    +    the token, as in C{hex_integer = Word(hexnums).setParseAction(tokenMap(int, 16))}, which will convert the
    +    parsed data to an integer using base 16.
    +
    +    Example (compare the last to example in L{ParserElement.transformString}::
    +        hex_ints = OneOrMore(Word(hexnums)).setParseAction(tokenMap(int, 16))
    +        hex_ints.runTests('''
    +            00 11 22 aa FF 0a 0d 1a
    +            ''')
    +        
    +        upperword = Word(alphas).setParseAction(tokenMap(str.upper))
    +        OneOrMore(upperword).runTests('''
    +            my kingdom for a horse
    +            ''')
    +
    +        wd = Word(alphas).setParseAction(tokenMap(str.title))
    +        OneOrMore(wd).setParseAction(' '.join).runTests('''
    +            now is the winter of our discontent made glorious summer by this sun of york
    +            ''')
    +    prints::
    +        00 11 22 aa FF 0a 0d 1a
    +        [0, 17, 34, 170, 255, 10, 13, 26]
    +
    +        my kingdom for a horse
    +        ['MY', 'KINGDOM', 'FOR', 'A', 'HORSE']
    +
    +        now is the winter of our discontent made glorious summer by this sun of york
    +        ['Now Is The Winter Of Our Discontent Made Glorious Summer By This Sun Of York']
    +    """
    +    def pa(s,l,t):
    +        return [func(tokn, *args) for tokn in t]
    +
    +    try:
    +        func_name = getattr(func, '__name__', 
    +                            getattr(func, '__class__').__name__)
    +    except Exception:
    +        func_name = str(func)
    +    pa.__name__ = func_name
    +
    +    return pa
    +
    +upcaseTokens = tokenMap(lambda t: _ustr(t).upper())
    +"""(Deprecated) Helper parse action to convert tokens to upper case. Deprecated in favor of L{pyparsing_common.upcaseTokens}"""
    +
    +downcaseTokens = tokenMap(lambda t: _ustr(t).lower())
    +"""(Deprecated) Helper parse action to convert tokens to lower case. Deprecated in favor of L{pyparsing_common.downcaseTokens}"""
    +    
    +def _makeTags(tagStr, xml):
    +    """Internal helper to construct opening and closing tag expressions, given a tag name"""
    +    if isinstance(tagStr,basestring):
    +        resname = tagStr
    +        tagStr = Keyword(tagStr, caseless=not xml)
    +    else:
    +        resname = tagStr.name
    +
    +    tagAttrName = Word(alphas,alphanums+"_-:")
    +    if (xml):
    +        tagAttrValue = dblQuotedString.copy().setParseAction( removeQuotes )
    +        openTag = Suppress("<") + tagStr("tag") + \
    +                Dict(ZeroOrMore(Group( tagAttrName + Suppress("=") + tagAttrValue ))) + \
    +                Optional("/",default=[False]).setResultsName("empty").setParseAction(lambda s,l,t:t[0]=='/') + Suppress(">")
    +    else:
    +        printablesLessRAbrack = "".join(c for c in printables if c not in ">")
    +        tagAttrValue = quotedString.copy().setParseAction( removeQuotes ) | Word(printablesLessRAbrack)
    +        openTag = Suppress("<") + tagStr("tag") + \
    +                Dict(ZeroOrMore(Group( tagAttrName.setParseAction(downcaseTokens) + \
    +                Optional( Suppress("=") + tagAttrValue ) ))) + \
    +                Optional("/",default=[False]).setResultsName("empty").setParseAction(lambda s,l,t:t[0]=='/') + Suppress(">")
    +    closeTag = Combine(_L("")
    +
    +    openTag = openTag.setResultsName("start"+"".join(resname.replace(":"," ").title().split())).setName("<%s>" % resname)
    +    closeTag = closeTag.setResultsName("end"+"".join(resname.replace(":"," ").title().split())).setName("" % resname)
    +    openTag.tag = resname
    +    closeTag.tag = resname
    +    return openTag, closeTag
    +
    +def makeHTMLTags(tagStr):
    +    """
    +    Helper to construct opening and closing tag expressions for HTML, given a tag name. Matches
    +    tags in either upper or lower case, attributes with namespaces and with quoted or unquoted values.
    +
    +    Example::
    +        text = 'More info at the pyparsing wiki page'
    +        # makeHTMLTags returns pyparsing expressions for the opening and closing tags as a 2-tuple
    +        a,a_end = makeHTMLTags("A")
    +        link_expr = a + SkipTo(a_end)("link_text") + a_end
    +        
    +        for link in link_expr.searchString(text):
    +            # attributes in the  tag (like "href" shown here) are also accessible as named results
    +            print(link.link_text, '->', link.href)
    +    prints::
    +        pyparsing -> http://pyparsing.wikispaces.com
    +    """
    +    return _makeTags( tagStr, False )
    +
    +def makeXMLTags(tagStr):
    +    """
    +    Helper to construct opening and closing tag expressions for XML, given a tag name. Matches
    +    tags only in the given upper/lower case.
    +
    +    Example: similar to L{makeHTMLTags}
    +    """
    +    return _makeTags( tagStr, True )
    +
    +def withAttribute(*args,**attrDict):
    +    """
    +    Helper to create a validating parse action to be used with start tags created
    +    with C{L{makeXMLTags}} or C{L{makeHTMLTags}}. Use C{withAttribute} to qualify a starting tag
    +    with a required attribute value, to avoid false matches on common tags such as
    +    C{} or C{
    }. + + Call C{withAttribute} with a series of attribute names and values. Specify the list + of filter attributes names and values as: + - keyword arguments, as in C{(align="right")}, or + - as an explicit dict with C{**} operator, when an attribute name is also a Python + reserved word, as in C{**{"class":"Customer", "align":"right"}} + - a list of name-value tuples, as in ( ("ns1:class", "Customer"), ("ns2:align","right") ) + For attribute names with a namespace prefix, you must use the second form. Attribute + names are matched insensitive to upper/lower case. + + If just testing for C{class} (with or without a namespace), use C{L{withClass}}. + + To verify that the attribute exists, but without specifying a value, pass + C{withAttribute.ANY_VALUE} as the value. + + Example:: + html = ''' +
    + Some text +
    1 4 0 1 0
    +
    1,3 2,3 1,1
    +
    this has no type
    +
    + + ''' + div,div_end = makeHTMLTags("div") + + # only match div tag having a type attribute with value "grid" + div_grid = div().setParseAction(withAttribute(type="grid")) + grid_expr = div_grid + SkipTo(div | div_end)("body") + for grid_header in grid_expr.searchString(html): + print(grid_header.body) + + # construct a match with any div tag having a type attribute, regardless of the value + div_any_type = div().setParseAction(withAttribute(type=withAttribute.ANY_VALUE)) + div_expr = div_any_type + SkipTo(div | div_end)("body") + for div_header in div_expr.searchString(html): + print(div_header.body) + prints:: + 1 4 0 1 0 + + 1 4 0 1 0 + 1,3 2,3 1,1 + """ + if args: + attrs = args[:] + else: + attrs = attrDict.items() + attrs = [(k,v) for k,v in attrs] + def pa(s,l,tokens): + for attrName,attrValue in attrs: + if attrName not in tokens: + raise ParseException(s,l,"no matching attribute " + attrName) + if attrValue != withAttribute.ANY_VALUE and tokens[attrName] != attrValue: + raise ParseException(s,l,"attribute '%s' has value '%s', must be '%s'" % + (attrName, tokens[attrName], attrValue)) + return pa +withAttribute.ANY_VALUE = object() + +def withClass(classname, namespace=''): + """ + Simplified version of C{L{withAttribute}} when matching on a div class - made + difficult because C{class} is a reserved word in Python. + + Example:: + html = ''' +
    + Some text +
    1 4 0 1 0
    +
    1,3 2,3 1,1
    +
    this <div> has no class
    +
    + + ''' + div,div_end = makeHTMLTags("div") + div_grid = div().setParseAction(withClass("grid")) + + grid_expr = div_grid + SkipTo(div | div_end)("body") + for grid_header in grid_expr.searchString(html): + print(grid_header.body) + + div_any_type = div().setParseAction(withClass(withAttribute.ANY_VALUE)) + div_expr = div_any_type + SkipTo(div | div_end)("body") + for div_header in div_expr.searchString(html): + print(div_header.body) + prints:: + 1 4 0 1 0 + + 1 4 0 1 0 + 1,3 2,3 1,1 + """ + classattr = "%s:class" % namespace if namespace else "class" + return withAttribute(**{classattr : classname}) + +opAssoc = _Constants() +opAssoc.LEFT = object() +opAssoc.RIGHT = object() + +def infixNotation( baseExpr, opList, lpar=Suppress('('), rpar=Suppress(')') ): + """ + Helper method for constructing grammars of expressions made up of + operators working in a precedence hierarchy. Operators may be unary or + binary, left- or right-associative. Parse actions can also be attached + to operator expressions. The generated parser will also recognize the use + of parentheses to override operator precedences (see example below). + + Note: if you define a deep operator list, you may see performance issues + when using infixNotation. See L{ParserElement.enablePackrat} for a + mechanism to potentially improve your parser performance. + + Parameters: + - baseExpr - expression representing the most basic element for the nested + - opList - list of tuples, one for each operator precedence level in the + expression grammar; each tuple is of the form + (opExpr, numTerms, rightLeftAssoc, parseAction), where: + - opExpr is the pyparsing expression for the operator; + may also be a string, which will be converted to a Literal; + if numTerms is 3, opExpr is a tuple of two expressions, for the + two operators separating the 3 terms + - numTerms is the number of terms for this operator (must + be 1, 2, or 3) + - rightLeftAssoc is the indicator whether the operator is + right or left associative, using the pyparsing-defined + constants C{opAssoc.RIGHT} and C{opAssoc.LEFT}. + - parseAction is the parse action to be associated with + expressions matching this operator expression (the + parse action tuple member may be omitted); if the parse action + is passed a tuple or list of functions, this is equivalent to + calling C{setParseAction(*fn)} (L{ParserElement.setParseAction}) + - lpar - expression for matching left-parentheses (default=C{Suppress('(')}) + - rpar - expression for matching right-parentheses (default=C{Suppress(')')}) + + Example:: + # simple example of four-function arithmetic with ints and variable names + integer = pyparsing_common.signed_integer + varname = pyparsing_common.identifier + + arith_expr = infixNotation(integer | varname, + [ + ('-', 1, opAssoc.RIGHT), + (oneOf('* /'), 2, opAssoc.LEFT), + (oneOf('+ -'), 2, opAssoc.LEFT), + ]) + + arith_expr.runTests(''' + 5+3*6 + (5+3)*6 + -2--11 + ''', fullDump=False) + prints:: + 5+3*6 + [[5, '+', [3, '*', 6]]] + + (5+3)*6 + [[[5, '+', 3], '*', 6]] + + -2--11 + [[['-', 2], '-', ['-', 11]]] + """ + ret = Forward() + lastExpr = baseExpr | ( lpar + ret + rpar ) + for i,operDef in enumerate(opList): + opExpr,arity,rightLeftAssoc,pa = (operDef + (None,))[:4] + termName = "%s term" % opExpr if arity < 3 else "%s%s term" % opExpr + if arity == 3: + if opExpr is None or len(opExpr) != 2: + raise ValueError("if numterms=3, opExpr must be a tuple or list of two expressions") + opExpr1, opExpr2 = opExpr + thisExpr = Forward().setName(termName) + if rightLeftAssoc == opAssoc.LEFT: + if arity == 1: + matchExpr = FollowedBy(lastExpr + opExpr) + Group( lastExpr + OneOrMore( opExpr ) ) + elif arity == 2: + if opExpr is not None: + matchExpr = FollowedBy(lastExpr + opExpr + lastExpr) + Group( lastExpr + OneOrMore( opExpr + lastExpr ) ) + else: + matchExpr = FollowedBy(lastExpr+lastExpr) + Group( lastExpr + OneOrMore(lastExpr) ) + elif arity == 3: + matchExpr = FollowedBy(lastExpr + opExpr1 + lastExpr + opExpr2 + lastExpr) + \ + Group( lastExpr + opExpr1 + lastExpr + opExpr2 + lastExpr ) + else: + raise ValueError("operator must be unary (1), binary (2), or ternary (3)") + elif rightLeftAssoc == opAssoc.RIGHT: + if arity == 1: + # try to avoid LR with this extra test + if not isinstance(opExpr, Optional): + opExpr = Optional(opExpr) + matchExpr = FollowedBy(opExpr.expr + thisExpr) + Group( opExpr + thisExpr ) + elif arity == 2: + if opExpr is not None: + matchExpr = FollowedBy(lastExpr + opExpr + thisExpr) + Group( lastExpr + OneOrMore( opExpr + thisExpr ) ) + else: + matchExpr = FollowedBy(lastExpr + thisExpr) + Group( lastExpr + OneOrMore( thisExpr ) ) + elif arity == 3: + matchExpr = FollowedBy(lastExpr + opExpr1 + thisExpr + opExpr2 + thisExpr) + \ + Group( lastExpr + opExpr1 + thisExpr + opExpr2 + thisExpr ) + else: + raise ValueError("operator must be unary (1), binary (2), or ternary (3)") + else: + raise ValueError("operator must indicate right or left associativity") + if pa: + if isinstance(pa, (tuple, list)): + matchExpr.setParseAction(*pa) + else: + matchExpr.setParseAction(pa) + thisExpr <<= ( matchExpr.setName(termName) | lastExpr ) + lastExpr = thisExpr + ret <<= lastExpr + return ret + +operatorPrecedence = infixNotation +"""(Deprecated) Former name of C{L{infixNotation}}, will be dropped in a future release.""" + +dblQuotedString = Combine(Regex(r'"(?:[^"\n\r\\]|(?:"")|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*')+'"').setName("string enclosed in double quotes") +sglQuotedString = Combine(Regex(r"'(?:[^'\n\r\\]|(?:'')|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*")+"'").setName("string enclosed in single quotes") +quotedString = Combine(Regex(r'"(?:[^"\n\r\\]|(?:"")|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*')+'"'| + Regex(r"'(?:[^'\n\r\\]|(?:'')|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*")+"'").setName("quotedString using single or double quotes") +unicodeString = Combine(_L('u') + quotedString.copy()).setName("unicode string literal") + +def nestedExpr(opener="(", closer=")", content=None, ignoreExpr=quotedString.copy()): + """ + Helper method for defining nested lists enclosed in opening and closing + delimiters ("(" and ")" are the default). + + Parameters: + - opener - opening character for a nested list (default=C{"("}); can also be a pyparsing expression + - closer - closing character for a nested list (default=C{")"}); can also be a pyparsing expression + - content - expression for items within the nested lists (default=C{None}) + - ignoreExpr - expression for ignoring opening and closing delimiters (default=C{quotedString}) + + If an expression is not provided for the content argument, the nested + expression will capture all whitespace-delimited content between delimiters + as a list of separate values. + + Use the C{ignoreExpr} argument to define expressions that may contain + opening or closing characters that should not be treated as opening + or closing characters for nesting, such as quotedString or a comment + expression. Specify multiple expressions using an C{L{Or}} or C{L{MatchFirst}}. + The default is L{quotedString}, but if no expressions are to be ignored, + then pass C{None} for this argument. + + Example:: + data_type = oneOf("void int short long char float double") + decl_data_type = Combine(data_type + Optional(Word('*'))) + ident = Word(alphas+'_', alphanums+'_') + number = pyparsing_common.number + arg = Group(decl_data_type + ident) + LPAR,RPAR = map(Suppress, "()") + + code_body = nestedExpr('{', '}', ignoreExpr=(quotedString | cStyleComment)) + + c_function = (decl_data_type("type") + + ident("name") + + LPAR + Optional(delimitedList(arg), [])("args") + RPAR + + code_body("body")) + c_function.ignore(cStyleComment) + + source_code = ''' + int is_odd(int x) { + return (x%2); + } + + int dec_to_hex(char hchar) { + if (hchar >= '0' && hchar <= '9') { + return (ord(hchar)-ord('0')); + } else { + return (10+ord(hchar)-ord('A')); + } + } + ''' + for func in c_function.searchString(source_code): + print("%(name)s (%(type)s) args: %(args)s" % func) + + prints:: + is_odd (int) args: [['int', 'x']] + dec_to_hex (int) args: [['char', 'hchar']] + """ + if opener == closer: + raise ValueError("opening and closing strings cannot be the same") + if content is None: + if isinstance(opener,basestring) and isinstance(closer,basestring): + if len(opener) == 1 and len(closer)==1: + if ignoreExpr is not None: + content = (Combine(OneOrMore(~ignoreExpr + + CharsNotIn(opener+closer+ParserElement.DEFAULT_WHITE_CHARS,exact=1)) + ).setParseAction(lambda t:t[0].strip())) + else: + content = (empty.copy()+CharsNotIn(opener+closer+ParserElement.DEFAULT_WHITE_CHARS + ).setParseAction(lambda t:t[0].strip())) + else: + if ignoreExpr is not None: + content = (Combine(OneOrMore(~ignoreExpr + + ~Literal(opener) + ~Literal(closer) + + CharsNotIn(ParserElement.DEFAULT_WHITE_CHARS,exact=1)) + ).setParseAction(lambda t:t[0].strip())) + else: + content = (Combine(OneOrMore(~Literal(opener) + ~Literal(closer) + + CharsNotIn(ParserElement.DEFAULT_WHITE_CHARS,exact=1)) + ).setParseAction(lambda t:t[0].strip())) + else: + raise ValueError("opening and closing arguments must be strings if no content expression is given") + ret = Forward() + if ignoreExpr is not None: + ret <<= Group( Suppress(opener) + ZeroOrMore( ignoreExpr | ret | content ) + Suppress(closer) ) + else: + ret <<= Group( Suppress(opener) + ZeroOrMore( ret | content ) + Suppress(closer) ) + ret.setName('nested %s%s expression' % (opener,closer)) + return ret + +def indentedBlock(blockStatementExpr, indentStack, indent=True): + """ + Helper method for defining space-delimited indentation blocks, such as + those used to define block statements in Python source code. + + Parameters: + - blockStatementExpr - expression defining syntax of statement that + is repeated within the indented block + - indentStack - list created by caller to manage indentation stack + (multiple statementWithIndentedBlock expressions within a single grammar + should share a common indentStack) + - indent - boolean indicating whether block must be indented beyond the + the current level; set to False for block of left-most statements + (default=C{True}) + + A valid block must contain at least one C{blockStatement}. + + Example:: + data = ''' + def A(z): + A1 + B = 100 + G = A2 + A2 + A3 + B + def BB(a,b,c): + BB1 + def BBA(): + bba1 + bba2 + bba3 + C + D + def spam(x,y): + def eggs(z): + pass + ''' + + + indentStack = [1] + stmt = Forward() + + identifier = Word(alphas, alphanums) + funcDecl = ("def" + identifier + Group( "(" + Optional( delimitedList(identifier) ) + ")" ) + ":") + func_body = indentedBlock(stmt, indentStack) + funcDef = Group( funcDecl + func_body ) + + rvalue = Forward() + funcCall = Group(identifier + "(" + Optional(delimitedList(rvalue)) + ")") + rvalue << (funcCall | identifier | Word(nums)) + assignment = Group(identifier + "=" + rvalue) + stmt << ( funcDef | assignment | identifier ) + + module_body = OneOrMore(stmt) + + parseTree = module_body.parseString(data) + parseTree.pprint() + prints:: + [['def', + 'A', + ['(', 'z', ')'], + ':', + [['A1'], [['B', '=', '100']], [['G', '=', 'A2']], ['A2'], ['A3']]], + 'B', + ['def', + 'BB', + ['(', 'a', 'b', 'c', ')'], + ':', + [['BB1'], [['def', 'BBA', ['(', ')'], ':', [['bba1'], ['bba2'], ['bba3']]]]]], + 'C', + 'D', + ['def', + 'spam', + ['(', 'x', 'y', ')'], + ':', + [[['def', 'eggs', ['(', 'z', ')'], ':', [['pass']]]]]]] + """ + def checkPeerIndent(s,l,t): + if l >= len(s): return + curCol = col(l,s) + if curCol != indentStack[-1]: + if curCol > indentStack[-1]: + raise ParseFatalException(s,l,"illegal nesting") + raise ParseException(s,l,"not a peer entry") + + def checkSubIndent(s,l,t): + curCol = col(l,s) + if curCol > indentStack[-1]: + indentStack.append( curCol ) + else: + raise ParseException(s,l,"not a subentry") + + def checkUnindent(s,l,t): + if l >= len(s): return + curCol = col(l,s) + if not(indentStack and curCol < indentStack[-1] and curCol <= indentStack[-2]): + raise ParseException(s,l,"not an unindent") + indentStack.pop() + + NL = OneOrMore(LineEnd().setWhitespaceChars("\t ").suppress()) + INDENT = (Empty() + Empty().setParseAction(checkSubIndent)).setName('INDENT') + PEER = Empty().setParseAction(checkPeerIndent).setName('') + UNDENT = Empty().setParseAction(checkUnindent).setName('UNINDENT') + if indent: + smExpr = Group( Optional(NL) + + #~ FollowedBy(blockStatementExpr) + + INDENT + (OneOrMore( PEER + Group(blockStatementExpr) + Optional(NL) )) + UNDENT) + else: + smExpr = Group( Optional(NL) + + (OneOrMore( PEER + Group(blockStatementExpr) + Optional(NL) )) ) + blockStatementExpr.ignore(_bslash + LineEnd()) + return smExpr.setName('indented block') + +alphas8bit = srange(r"[\0xc0-\0xd6\0xd8-\0xf6\0xf8-\0xff]") +punc8bit = srange(r"[\0xa1-\0xbf\0xd7\0xf7]") + +anyOpenTag,anyCloseTag = makeHTMLTags(Word(alphas,alphanums+"_:").setName('any tag')) +_htmlEntityMap = dict(zip("gt lt amp nbsp quot apos".split(),'><& "\'')) +commonHTMLEntity = Regex('&(?P' + '|'.join(_htmlEntityMap.keys()) +");").setName("common HTML entity") +def replaceHTMLEntity(t): + """Helper parser action to replace common HTML entities with their special characters""" + return _htmlEntityMap.get(t.entity) + +# it's easy to get these comment structures wrong - they're very common, so may as well make them available +cStyleComment = Combine(Regex(r"/\*(?:[^*]|\*(?!/))*") + '*/').setName("C style comment") +"Comment of the form C{/* ... */}" + +htmlComment = Regex(r"").setName("HTML comment") +"Comment of the form C{}" + +restOfLine = Regex(r".*").leaveWhitespace().setName("rest of line") +dblSlashComment = Regex(r"//(?:\\\n|[^\n])*").setName("// comment") +"Comment of the form C{// ... (to end of line)}" + +cppStyleComment = Combine(Regex(r"/\*(?:[^*]|\*(?!/))*") + '*/'| dblSlashComment).setName("C++ style comment") +"Comment of either form C{L{cStyleComment}} or C{L{dblSlashComment}}" + +javaStyleComment = cppStyleComment +"Same as C{L{cppStyleComment}}" + +pythonStyleComment = Regex(r"#.*").setName("Python style comment") +"Comment of the form C{# ... (to end of line)}" + +_commasepitem = Combine(OneOrMore(Word(printables, excludeChars=',') + + Optional( Word(" \t") + + ~Literal(",") + ~LineEnd() ) ) ).streamline().setName("commaItem") +commaSeparatedList = delimitedList( Optional( quotedString.copy() | _commasepitem, default="") ).setName("commaSeparatedList") +"""(Deprecated) Predefined expression of 1 or more printable words or quoted strings, separated by commas. + This expression is deprecated in favor of L{pyparsing_common.comma_separated_list}.""" + +# some other useful expressions - using lower-case class name since we are really using this as a namespace +class pyparsing_common: + """ + Here are some common low-level expressions that may be useful in jump-starting parser development: + - numeric forms (L{integers}, L{reals}, L{scientific notation}) + - common L{programming identifiers} + - network addresses (L{MAC}, L{IPv4}, L{IPv6}) + - ISO8601 L{dates} and L{datetime} + - L{UUID} + - L{comma-separated list} + Parse actions: + - C{L{convertToInteger}} + - C{L{convertToFloat}} + - C{L{convertToDate}} + - C{L{convertToDatetime}} + - C{L{stripHTMLTags}} + - C{L{upcaseTokens}} + - C{L{downcaseTokens}} + + Example:: + pyparsing_common.number.runTests(''' + # any int or real number, returned as the appropriate type + 100 + -100 + +100 + 3.14159 + 6.02e23 + 1e-12 + ''') + + pyparsing_common.fnumber.runTests(''' + # any int or real number, returned as float + 100 + -100 + +100 + 3.14159 + 6.02e23 + 1e-12 + ''') + + pyparsing_common.hex_integer.runTests(''' + # hex numbers + 100 + FF + ''') + + pyparsing_common.fraction.runTests(''' + # fractions + 1/2 + -3/4 + ''') + + pyparsing_common.mixed_integer.runTests(''' + # mixed fractions + 1 + 1/2 + -3/4 + 1-3/4 + ''') + + import uuid + pyparsing_common.uuid.setParseAction(tokenMap(uuid.UUID)) + pyparsing_common.uuid.runTests(''' + # uuid + 12345678-1234-5678-1234-567812345678 + ''') + prints:: + # any int or real number, returned as the appropriate type + 100 + [100] + + -100 + [-100] + + +100 + [100] + + 3.14159 + [3.14159] + + 6.02e23 + [6.02e+23] + + 1e-12 + [1e-12] + + # any int or real number, returned as float + 100 + [100.0] + + -100 + [-100.0] + + +100 + [100.0] + + 3.14159 + [3.14159] + + 6.02e23 + [6.02e+23] + + 1e-12 + [1e-12] + + # hex numbers + 100 + [256] + + FF + [255] + + # fractions + 1/2 + [0.5] + + -3/4 + [-0.75] + + # mixed fractions + 1 + [1] + + 1/2 + [0.5] + + -3/4 + [-0.75] + + 1-3/4 + [1.75] + + # uuid + 12345678-1234-5678-1234-567812345678 + [UUID('12345678-1234-5678-1234-567812345678')] + """ + + convertToInteger = tokenMap(int) + """ + Parse action for converting parsed integers to Python int + """ + + convertToFloat = tokenMap(float) + """ + Parse action for converting parsed numbers to Python float + """ + + integer = Word(nums).setName("integer").setParseAction(convertToInteger) + """expression that parses an unsigned integer, returns an int""" + + hex_integer = Word(hexnums).setName("hex integer").setParseAction(tokenMap(int,16)) + """expression that parses a hexadecimal integer, returns an int""" + + signed_integer = Regex(r'[+-]?\d+').setName("signed integer").setParseAction(convertToInteger) + """expression that parses an integer with optional leading sign, returns an int""" + + fraction = (signed_integer().setParseAction(convertToFloat) + '/' + signed_integer().setParseAction(convertToFloat)).setName("fraction") + """fractional expression of an integer divided by an integer, returns a float""" + fraction.addParseAction(lambda t: t[0]/t[-1]) + + mixed_integer = (fraction | signed_integer + Optional(Optional('-').suppress() + fraction)).setName("fraction or mixed integer-fraction") + """mixed integer of the form 'integer - fraction', with optional leading integer, returns float""" + mixed_integer.addParseAction(sum) + + real = Regex(r'[+-]?\d+\.\d*').setName("real number").setParseAction(convertToFloat) + """expression that parses a floating point number and returns a float""" + + sci_real = Regex(r'[+-]?\d+([eE][+-]?\d+|\.\d*([eE][+-]?\d+)?)').setName("real number with scientific notation").setParseAction(convertToFloat) + """expression that parses a floating point number with optional scientific notation and returns a float""" + + # streamlining this expression makes the docs nicer-looking + number = (sci_real | real | signed_integer).streamline() + """any numeric expression, returns the corresponding Python type""" + + fnumber = Regex(r'[+-]?\d+\.?\d*([eE][+-]?\d+)?').setName("fnumber").setParseAction(convertToFloat) + """any int or real number, returned as float""" + + identifier = Word(alphas+'_', alphanums+'_').setName("identifier") + """typical code identifier (leading alpha or '_', followed by 0 or more alphas, nums, or '_')""" + + ipv4_address = Regex(r'(25[0-5]|2[0-4][0-9]|1?[0-9]{1,2})(\.(25[0-5]|2[0-4][0-9]|1?[0-9]{1,2})){3}').setName("IPv4 address") + "IPv4 address (C{0.0.0.0 - 255.255.255.255})" + + _ipv6_part = Regex(r'[0-9a-fA-F]{1,4}').setName("hex_integer") + _full_ipv6_address = (_ipv6_part + (':' + _ipv6_part)*7).setName("full IPv6 address") + _short_ipv6_address = (Optional(_ipv6_part + (':' + _ipv6_part)*(0,6)) + "::" + Optional(_ipv6_part + (':' + _ipv6_part)*(0,6))).setName("short IPv6 address") + _short_ipv6_address.addCondition(lambda t: sum(1 for tt in t if pyparsing_common._ipv6_part.matches(tt)) < 8) + _mixed_ipv6_address = ("::ffff:" + ipv4_address).setName("mixed IPv6 address") + ipv6_address = Combine((_full_ipv6_address | _mixed_ipv6_address | _short_ipv6_address).setName("IPv6 address")).setName("IPv6 address") + "IPv6 address (long, short, or mixed form)" + + mac_address = Regex(r'[0-9a-fA-F]{2}([:.-])[0-9a-fA-F]{2}(?:\1[0-9a-fA-F]{2}){4}').setName("MAC address") + "MAC address xx:xx:xx:xx:xx (may also have '-' or '.' delimiters)" + + @staticmethod + def convertToDate(fmt="%Y-%m-%d"): + """ + Helper to create a parse action for converting parsed date string to Python datetime.date + + Params - + - fmt - format to be passed to datetime.strptime (default=C{"%Y-%m-%d"}) + + Example:: + date_expr = pyparsing_common.iso8601_date.copy() + date_expr.setParseAction(pyparsing_common.convertToDate()) + print(date_expr.parseString("1999-12-31")) + prints:: + [datetime.date(1999, 12, 31)] + """ + def cvt_fn(s,l,t): + try: + return datetime.strptime(t[0], fmt).date() + except ValueError as ve: + raise ParseException(s, l, str(ve)) + return cvt_fn + + @staticmethod + def convertToDatetime(fmt="%Y-%m-%dT%H:%M:%S.%f"): + """ + Helper to create a parse action for converting parsed datetime string to Python datetime.datetime + + Params - + - fmt - format to be passed to datetime.strptime (default=C{"%Y-%m-%dT%H:%M:%S.%f"}) + + Example:: + dt_expr = pyparsing_common.iso8601_datetime.copy() + dt_expr.setParseAction(pyparsing_common.convertToDatetime()) + print(dt_expr.parseString("1999-12-31T23:59:59.999")) + prints:: + [datetime.datetime(1999, 12, 31, 23, 59, 59, 999000)] + """ + def cvt_fn(s,l,t): + try: + return datetime.strptime(t[0], fmt) + except ValueError as ve: + raise ParseException(s, l, str(ve)) + return cvt_fn + + iso8601_date = Regex(r'(?P\d{4})(?:-(?P\d\d)(?:-(?P\d\d))?)?').setName("ISO8601 date") + "ISO8601 date (C{yyyy-mm-dd})" + + iso8601_datetime = Regex(r'(?P\d{4})-(?P\d\d)-(?P\d\d)[T ](?P\d\d):(?P\d\d)(:(?P\d\d(\.\d*)?)?)?(?PZ|[+-]\d\d:?\d\d)?').setName("ISO8601 datetime") + "ISO8601 datetime (C{yyyy-mm-ddThh:mm:ss.s(Z|+-00:00)}) - trailing seconds, milliseconds, and timezone optional; accepts separating C{'T'} or C{' '}" + + uuid = Regex(r'[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}').setName("UUID") + "UUID (C{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx})" + + _html_stripper = anyOpenTag.suppress() | anyCloseTag.suppress() + @staticmethod + def stripHTMLTags(s, l, tokens): + """ + Parse action to remove HTML tags from web page HTML source + + Example:: + # strip HTML links from normal text + text = 'More info at the
    pyparsing wiki page' + td,td_end = makeHTMLTags("TD") + table_text = td + SkipTo(td_end).setParseAction(pyparsing_common.stripHTMLTags)("body") + td_end + + print(table_text.parseString(text).body) # -> 'More info at the pyparsing wiki page' + """ + return pyparsing_common._html_stripper.transformString(tokens[0]) + + _commasepitem = Combine(OneOrMore(~Literal(",") + ~LineEnd() + Word(printables, excludeChars=',') + + Optional( White(" \t") ) ) ).streamline().setName("commaItem") + comma_separated_list = delimitedList( Optional( quotedString.copy() | _commasepitem, default="") ).setName("comma separated list") + """Predefined expression of 1 or more printable words or quoted strings, separated by commas.""" + + upcaseTokens = staticmethod(tokenMap(lambda t: _ustr(t).upper())) + """Parse action to convert tokens to upper case.""" + + downcaseTokens = staticmethod(tokenMap(lambda t: _ustr(t).lower())) + """Parse action to convert tokens to lower case.""" + + +if __name__ == "__main__": + + selectToken = CaselessLiteral("select") + fromToken = CaselessLiteral("from") + + ident = Word(alphas, alphanums + "_$") + + columnName = delimitedList(ident, ".", combine=True).setParseAction(upcaseTokens) + columnNameList = Group(delimitedList(columnName)).setName("columns") + columnSpec = ('*' | columnNameList) + + tableName = delimitedList(ident, ".", combine=True).setParseAction(upcaseTokens) + tableNameList = Group(delimitedList(tableName)).setName("tables") + + simpleSQL = selectToken("command") + columnSpec("columns") + fromToken + tableNameList("tables") + + # demo runTests method, including embedded comments in test string + simpleSQL.runTests(""" + # '*' as column list and dotted table name + select * from SYS.XYZZY + + # caseless match on "SELECT", and casts back to "select" + SELECT * from XYZZY, ABC + + # list of column names, and mixed case SELECT keyword + Select AA,BB,CC from Sys.dual + + # multiple tables + Select A, B, C from Sys.dual, Table2 + + # invalid SELECT keyword - should fail + Xelect A, B, C from Sys.dual + + # incomplete command - should fail + Select + + # invalid column name - should fail + Select ^^^ frox Sys.dual + + """) + + pyparsing_common.number.runTests(""" + 100 + -100 + +100 + 3.14159 + 6.02e23 + 1e-12 + """) + + # any int or real number, returned as float + pyparsing_common.fnumber.runTests(""" + 100 + -100 + +100 + 3.14159 + 6.02e23 + 1e-12 + """) + + pyparsing_common.hex_integer.runTests(""" + 100 + FF + """) + + import uuid + pyparsing_common.uuid.setParseAction(tokenMap(uuid.UUID)) + pyparsing_common.uuid.runTests(""" + 12345678-1234-5678-1234-567812345678 + """) diff --git a/venv/Lib/site-packages/setuptools/_vendor/typing_extensions.py b/venv/Lib/site-packages/setuptools/_vendor/typing_extensions.py new file mode 100644 index 0000000..9f1c7aa --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_vendor/typing_extensions.py @@ -0,0 +1,2296 @@ +import abc +import collections +import collections.abc +import operator +import sys +import typing + +# After PEP 560, internal typing API was substantially reworked. +# This is especially important for Protocol class which uses internal APIs +# quite extensively. +PEP_560 = sys.version_info[:3] >= (3, 7, 0) + +if PEP_560: + GenericMeta = type +else: + # 3.6 + from typing import GenericMeta, _type_vars # noqa + +# The two functions below are copies of typing internal helpers. +# They are needed by _ProtocolMeta + + +def _no_slots_copy(dct): + dict_copy = dict(dct) + if '__slots__' in dict_copy: + for slot in dict_copy['__slots__']: + dict_copy.pop(slot, None) + return dict_copy + + +def _check_generic(cls, parameters): + if not cls.__parameters__: + raise TypeError(f"{cls} is not a generic class") + alen = len(parameters) + elen = len(cls.__parameters__) + if alen != elen: + raise TypeError(f"Too {'many' if alen > elen else 'few'} arguments for {cls};" + f" actual {alen}, expected {elen}") + + +# Please keep __all__ alphabetized within each category. +__all__ = [ + # Super-special typing primitives. + 'ClassVar', + 'Concatenate', + 'Final', + 'ParamSpec', + 'Self', + 'Type', + + # ABCs (from collections.abc). + 'Awaitable', + 'AsyncIterator', + 'AsyncIterable', + 'Coroutine', + 'AsyncGenerator', + 'AsyncContextManager', + 'ChainMap', + + # Concrete collection types. + 'ContextManager', + 'Counter', + 'Deque', + 'DefaultDict', + 'OrderedDict', + 'TypedDict', + + # Structural checks, a.k.a. protocols. + 'SupportsIndex', + + # One-off things. + 'Annotated', + 'final', + 'IntVar', + 'Literal', + 'NewType', + 'overload', + 'Protocol', + 'runtime', + 'runtime_checkable', + 'Text', + 'TypeAlias', + 'TypeGuard', + 'TYPE_CHECKING', +] + +if PEP_560: + __all__.extend(["get_args", "get_origin", "get_type_hints"]) + +# 3.6.2+ +if hasattr(typing, 'NoReturn'): + NoReturn = typing.NoReturn +# 3.6.0-3.6.1 +else: + class _NoReturn(typing._FinalTypingBase, _root=True): + """Special type indicating functions that never return. + Example:: + + from typing import NoReturn + + def stop() -> NoReturn: + raise Exception('no way') + + This type is invalid in other positions, e.g., ``List[NoReturn]`` + will fail in static type checkers. + """ + __slots__ = () + + def __instancecheck__(self, obj): + raise TypeError("NoReturn cannot be used with isinstance().") + + def __subclasscheck__(self, cls): + raise TypeError("NoReturn cannot be used with issubclass().") + + NoReturn = _NoReturn(_root=True) + +# Some unconstrained type variables. These are used by the container types. +# (These are not for export.) +T = typing.TypeVar('T') # Any type. +KT = typing.TypeVar('KT') # Key type. +VT = typing.TypeVar('VT') # Value type. +T_co = typing.TypeVar('T_co', covariant=True) # Any type covariant containers. +T_contra = typing.TypeVar('T_contra', contravariant=True) # Ditto contravariant. + +ClassVar = typing.ClassVar + +# On older versions of typing there is an internal class named "Final". +# 3.8+ +if hasattr(typing, 'Final') and sys.version_info[:2] >= (3, 7): + Final = typing.Final +# 3.7 +elif sys.version_info[:2] >= (3, 7): + class _FinalForm(typing._SpecialForm, _root=True): + + def __repr__(self): + return 'typing_extensions.' + self._name + + def __getitem__(self, parameters): + item = typing._type_check(parameters, + f'{self._name} accepts only single type') + return typing._GenericAlias(self, (item,)) + + Final = _FinalForm('Final', + doc="""A special typing construct to indicate that a name + cannot be re-assigned or overridden in a subclass. + For example: + + MAX_SIZE: Final = 9000 + MAX_SIZE += 1 # Error reported by type checker + + class Connection: + TIMEOUT: Final[int] = 10 + class FastConnector(Connection): + TIMEOUT = 1 # Error reported by type checker + + There is no runtime checking of these properties.""") +# 3.6 +else: + class _Final(typing._FinalTypingBase, _root=True): + """A special typing construct to indicate that a name + cannot be re-assigned or overridden in a subclass. + For example: + + MAX_SIZE: Final = 9000 + MAX_SIZE += 1 # Error reported by type checker + + class Connection: + TIMEOUT: Final[int] = 10 + class FastConnector(Connection): + TIMEOUT = 1 # Error reported by type checker + + There is no runtime checking of these properties. + """ + + __slots__ = ('__type__',) + + def __init__(self, tp=None, **kwds): + self.__type__ = tp + + def __getitem__(self, item): + cls = type(self) + if self.__type__ is None: + return cls(typing._type_check(item, + f'{cls.__name__[1:]} accepts only single type.'), + _root=True) + raise TypeError(f'{cls.__name__[1:]} cannot be further subscripted') + + def _eval_type(self, globalns, localns): + new_tp = typing._eval_type(self.__type__, globalns, localns) + if new_tp == self.__type__: + return self + return type(self)(new_tp, _root=True) + + def __repr__(self): + r = super().__repr__() + if self.__type__ is not None: + r += f'[{typing._type_repr(self.__type__)}]' + return r + + def __hash__(self): + return hash((type(self).__name__, self.__type__)) + + def __eq__(self, other): + if not isinstance(other, _Final): + return NotImplemented + if self.__type__ is not None: + return self.__type__ == other.__type__ + return self is other + + Final = _Final(_root=True) + + +# 3.8+ +if hasattr(typing, 'final'): + final = typing.final +# 3.6-3.7 +else: + def final(f): + """This decorator can be used to indicate to type checkers that + the decorated method cannot be overridden, and decorated class + cannot be subclassed. For example: + + class Base: + @final + def done(self) -> None: + ... + class Sub(Base): + def done(self) -> None: # Error reported by type checker + ... + @final + class Leaf: + ... + class Other(Leaf): # Error reported by type checker + ... + + There is no runtime checking of these properties. + """ + return f + + +def IntVar(name): + return typing.TypeVar(name) + + +# 3.8+: +if hasattr(typing, 'Literal'): + Literal = typing.Literal +# 3.7: +elif sys.version_info[:2] >= (3, 7): + class _LiteralForm(typing._SpecialForm, _root=True): + + def __repr__(self): + return 'typing_extensions.' + self._name + + def __getitem__(self, parameters): + return typing._GenericAlias(self, parameters) + + Literal = _LiteralForm('Literal', + doc="""A type that can be used to indicate to type checkers + that the corresponding value has a value literally equivalent + to the provided parameter. For example: + + var: Literal[4] = 4 + + The type checker understands that 'var' is literally equal to + the value 4 and no other value. + + Literal[...] cannot be subclassed. There is no runtime + checking verifying that the parameter is actually a value + instead of a type.""") +# 3.6: +else: + class _Literal(typing._FinalTypingBase, _root=True): + """A type that can be used to indicate to type checkers that the + corresponding value has a value literally equivalent to the + provided parameter. For example: + + var: Literal[4] = 4 + + The type checker understands that 'var' is literally equal to the + value 4 and no other value. + + Literal[...] cannot be subclassed. There is no runtime checking + verifying that the parameter is actually a value instead of a type. + """ + + __slots__ = ('__values__',) + + def __init__(self, values=None, **kwds): + self.__values__ = values + + def __getitem__(self, values): + cls = type(self) + if self.__values__ is None: + if not isinstance(values, tuple): + values = (values,) + return cls(values, _root=True) + raise TypeError(f'{cls.__name__[1:]} cannot be further subscripted') + + def _eval_type(self, globalns, localns): + return self + + def __repr__(self): + r = super().__repr__() + if self.__values__ is not None: + r += f'[{", ".join(map(typing._type_repr, self.__values__))}]' + return r + + def __hash__(self): + return hash((type(self).__name__, self.__values__)) + + def __eq__(self, other): + if not isinstance(other, _Literal): + return NotImplemented + if self.__values__ is not None: + return self.__values__ == other.__values__ + return self is other + + Literal = _Literal(_root=True) + + +_overload_dummy = typing._overload_dummy # noqa +overload = typing.overload + + +# This is not a real generic class. Don't use outside annotations. +Type = typing.Type + +# Various ABCs mimicking those in collections.abc. +# A few are simply re-exported for completeness. + + +class _ExtensionsGenericMeta(GenericMeta): + def __subclasscheck__(self, subclass): + """This mimics a more modern GenericMeta.__subclasscheck__() logic + (that does not have problems with recursion) to work around interactions + between collections, typing, and typing_extensions on older + versions of Python, see https://github.com/python/typing/issues/501. + """ + if self.__origin__ is not None: + if sys._getframe(1).f_globals['__name__'] not in ['abc', 'functools']: + raise TypeError("Parameterized generics cannot be used with class " + "or instance checks") + return False + if not self.__extra__: + return super().__subclasscheck__(subclass) + res = self.__extra__.__subclasshook__(subclass) + if res is not NotImplemented: + return res + if self.__extra__ in subclass.__mro__: + return True + for scls in self.__extra__.__subclasses__(): + if isinstance(scls, GenericMeta): + continue + if issubclass(subclass, scls): + return True + return False + + +Awaitable = typing.Awaitable +Coroutine = typing.Coroutine +AsyncIterable = typing.AsyncIterable +AsyncIterator = typing.AsyncIterator + +# 3.6.1+ +if hasattr(typing, 'Deque'): + Deque = typing.Deque +# 3.6.0 +else: + class Deque(collections.deque, typing.MutableSequence[T], + metaclass=_ExtensionsGenericMeta, + extra=collections.deque): + __slots__ = () + + def __new__(cls, *args, **kwds): + if cls._gorg is Deque: + return collections.deque(*args, **kwds) + return typing._generic_new(collections.deque, cls, *args, **kwds) + +ContextManager = typing.ContextManager +# 3.6.2+ +if hasattr(typing, 'AsyncContextManager'): + AsyncContextManager = typing.AsyncContextManager +# 3.6.0-3.6.1 +else: + from _collections_abc import _check_methods as _check_methods_in_mro # noqa + + class AsyncContextManager(typing.Generic[T_co]): + __slots__ = () + + async def __aenter__(self): + return self + + @abc.abstractmethod + async def __aexit__(self, exc_type, exc_value, traceback): + return None + + @classmethod + def __subclasshook__(cls, C): + if cls is AsyncContextManager: + return _check_methods_in_mro(C, "__aenter__", "__aexit__") + return NotImplemented + +DefaultDict = typing.DefaultDict + +# 3.7.2+ +if hasattr(typing, 'OrderedDict'): + OrderedDict = typing.OrderedDict +# 3.7.0-3.7.2 +elif (3, 7, 0) <= sys.version_info[:3] < (3, 7, 2): + OrderedDict = typing._alias(collections.OrderedDict, (KT, VT)) +# 3.6 +else: + class OrderedDict(collections.OrderedDict, typing.MutableMapping[KT, VT], + metaclass=_ExtensionsGenericMeta, + extra=collections.OrderedDict): + + __slots__ = () + + def __new__(cls, *args, **kwds): + if cls._gorg is OrderedDict: + return collections.OrderedDict(*args, **kwds) + return typing._generic_new(collections.OrderedDict, cls, *args, **kwds) + +# 3.6.2+ +if hasattr(typing, 'Counter'): + Counter = typing.Counter +# 3.6.0-3.6.1 +else: + class Counter(collections.Counter, + typing.Dict[T, int], + metaclass=_ExtensionsGenericMeta, extra=collections.Counter): + + __slots__ = () + + def __new__(cls, *args, **kwds): + if cls._gorg is Counter: + return collections.Counter(*args, **kwds) + return typing._generic_new(collections.Counter, cls, *args, **kwds) + +# 3.6.1+ +if hasattr(typing, 'ChainMap'): + ChainMap = typing.ChainMap +elif hasattr(collections, 'ChainMap'): + class ChainMap(collections.ChainMap, typing.MutableMapping[KT, VT], + metaclass=_ExtensionsGenericMeta, + extra=collections.ChainMap): + + __slots__ = () + + def __new__(cls, *args, **kwds): + if cls._gorg is ChainMap: + return collections.ChainMap(*args, **kwds) + return typing._generic_new(collections.ChainMap, cls, *args, **kwds) + +# 3.6.1+ +if hasattr(typing, 'AsyncGenerator'): + AsyncGenerator = typing.AsyncGenerator +# 3.6.0 +else: + class AsyncGenerator(AsyncIterator[T_co], typing.Generic[T_co, T_contra], + metaclass=_ExtensionsGenericMeta, + extra=collections.abc.AsyncGenerator): + __slots__ = () + +NewType = typing.NewType +Text = typing.Text +TYPE_CHECKING = typing.TYPE_CHECKING + + +def _gorg(cls): + """This function exists for compatibility with old typing versions.""" + assert isinstance(cls, GenericMeta) + if hasattr(cls, '_gorg'): + return cls._gorg + while cls.__origin__ is not None: + cls = cls.__origin__ + return cls + + +_PROTO_WHITELIST = ['Callable', 'Awaitable', + 'Iterable', 'Iterator', 'AsyncIterable', 'AsyncIterator', + 'Hashable', 'Sized', 'Container', 'Collection', 'Reversible', + 'ContextManager', 'AsyncContextManager'] + + +def _get_protocol_attrs(cls): + attrs = set() + for base in cls.__mro__[:-1]: # without object + if base.__name__ in ('Protocol', 'Generic'): + continue + annotations = getattr(base, '__annotations__', {}) + for attr in list(base.__dict__.keys()) + list(annotations.keys()): + if (not attr.startswith('_abc_') and attr not in ( + '__abstractmethods__', '__annotations__', '__weakref__', + '_is_protocol', '_is_runtime_protocol', '__dict__', + '__args__', '__slots__', + '__next_in_mro__', '__parameters__', '__origin__', + '__orig_bases__', '__extra__', '__tree_hash__', + '__doc__', '__subclasshook__', '__init__', '__new__', + '__module__', '_MutableMapping__marker', '_gorg')): + attrs.add(attr) + return attrs + + +def _is_callable_members_only(cls): + return all(callable(getattr(cls, attr, None)) for attr in _get_protocol_attrs(cls)) + + +# 3.8+ +if hasattr(typing, 'Protocol'): + Protocol = typing.Protocol +# 3.7 +elif PEP_560: + from typing import _collect_type_vars # noqa + + def _no_init(self, *args, **kwargs): + if type(self)._is_protocol: + raise TypeError('Protocols cannot be instantiated') + + class _ProtocolMeta(abc.ABCMeta): + # This metaclass is a bit unfortunate and exists only because of the lack + # of __instancehook__. + def __instancecheck__(cls, instance): + # We need this method for situations where attributes are + # assigned in __init__. + if ((not getattr(cls, '_is_protocol', False) or + _is_callable_members_only(cls)) and + issubclass(instance.__class__, cls)): + return True + if cls._is_protocol: + if all(hasattr(instance, attr) and + (not callable(getattr(cls, attr, None)) or + getattr(instance, attr) is not None) + for attr in _get_protocol_attrs(cls)): + return True + return super().__instancecheck__(instance) + + class Protocol(metaclass=_ProtocolMeta): + # There is quite a lot of overlapping code with typing.Generic. + # Unfortunately it is hard to avoid this while these live in two different + # modules. The duplicated code will be removed when Protocol is moved to typing. + """Base class for protocol classes. Protocol classes are defined as:: + + class Proto(Protocol): + def meth(self) -> int: + ... + + Such classes are primarily used with static type checkers that recognize + structural subtyping (static duck-typing), for example:: + + class C: + def meth(self) -> int: + return 0 + + def func(x: Proto) -> int: + return x.meth() + + func(C()) # Passes static type check + + See PEP 544 for details. Protocol classes decorated with + @typing_extensions.runtime act as simple-minded runtime protocol that checks + only the presence of given attributes, ignoring their type signatures. + + Protocol classes can be generic, they are defined as:: + + class GenProto(Protocol[T]): + def meth(self) -> T: + ... + """ + __slots__ = () + _is_protocol = True + + def __new__(cls, *args, **kwds): + if cls is Protocol: + raise TypeError("Type Protocol cannot be instantiated; " + "it can only be used as a base class") + return super().__new__(cls) + + @typing._tp_cache + def __class_getitem__(cls, params): + if not isinstance(params, tuple): + params = (params,) + if not params and cls is not typing.Tuple: + raise TypeError( + f"Parameter list to {cls.__qualname__}[...] cannot be empty") + msg = "Parameters to generic types must be types." + params = tuple(typing._type_check(p, msg) for p in params) # noqa + if cls is Protocol: + # Generic can only be subscripted with unique type variables. + if not all(isinstance(p, typing.TypeVar) for p in params): + i = 0 + while isinstance(params[i], typing.TypeVar): + i += 1 + raise TypeError( + "Parameters to Protocol[...] must all be type variables." + f" Parameter {i + 1} is {params[i]}") + if len(set(params)) != len(params): + raise TypeError( + "Parameters to Protocol[...] must all be unique") + else: + # Subscripting a regular Generic subclass. + _check_generic(cls, params) + return typing._GenericAlias(cls, params) + + def __init_subclass__(cls, *args, **kwargs): + tvars = [] + if '__orig_bases__' in cls.__dict__: + error = typing.Generic in cls.__orig_bases__ + else: + error = typing.Generic in cls.__bases__ + if error: + raise TypeError("Cannot inherit from plain Generic") + if '__orig_bases__' in cls.__dict__: + tvars = _collect_type_vars(cls.__orig_bases__) + # Look for Generic[T1, ..., Tn] or Protocol[T1, ..., Tn]. + # If found, tvars must be a subset of it. + # If not found, tvars is it. + # Also check for and reject plain Generic, + # and reject multiple Generic[...] and/or Protocol[...]. + gvars = None + for base in cls.__orig_bases__: + if (isinstance(base, typing._GenericAlias) and + base.__origin__ in (typing.Generic, Protocol)): + # for error messages + the_base = base.__origin__.__name__ + if gvars is not None: + raise TypeError( + "Cannot inherit from Generic[...]" + " and/or Protocol[...] multiple types.") + gvars = base.__parameters__ + if gvars is None: + gvars = tvars + else: + tvarset = set(tvars) + gvarset = set(gvars) + if not tvarset <= gvarset: + s_vars = ', '.join(str(t) for t in tvars if t not in gvarset) + s_args = ', '.join(str(g) for g in gvars) + raise TypeError(f"Some type variables ({s_vars}) are" + f" not listed in {the_base}[{s_args}]") + tvars = gvars + cls.__parameters__ = tuple(tvars) + + # Determine if this is a protocol or a concrete subclass. + if not cls.__dict__.get('_is_protocol', None): + cls._is_protocol = any(b is Protocol for b in cls.__bases__) + + # Set (or override) the protocol subclass hook. + def _proto_hook(other): + if not cls.__dict__.get('_is_protocol', None): + return NotImplemented + if not getattr(cls, '_is_runtime_protocol', False): + if sys._getframe(2).f_globals['__name__'] in ['abc', 'functools']: + return NotImplemented + raise TypeError("Instance and class checks can only be used with" + " @runtime protocols") + if not _is_callable_members_only(cls): + if sys._getframe(2).f_globals['__name__'] in ['abc', 'functools']: + return NotImplemented + raise TypeError("Protocols with non-method members" + " don't support issubclass()") + if not isinstance(other, type): + # Same error as for issubclass(1, int) + raise TypeError('issubclass() arg 1 must be a class') + for attr in _get_protocol_attrs(cls): + for base in other.__mro__: + if attr in base.__dict__: + if base.__dict__[attr] is None: + return NotImplemented + break + annotations = getattr(base, '__annotations__', {}) + if (isinstance(annotations, typing.Mapping) and + attr in annotations and + isinstance(other, _ProtocolMeta) and + other._is_protocol): + break + else: + return NotImplemented + return True + if '__subclasshook__' not in cls.__dict__: + cls.__subclasshook__ = _proto_hook + + # We have nothing more to do for non-protocols. + if not cls._is_protocol: + return + + # Check consistency of bases. + for base in cls.__bases__: + if not (base in (object, typing.Generic) or + base.__module__ == 'collections.abc' and + base.__name__ in _PROTO_WHITELIST or + isinstance(base, _ProtocolMeta) and base._is_protocol): + raise TypeError('Protocols can only inherit from other' + f' protocols, got {repr(base)}') + cls.__init__ = _no_init +# 3.6 +else: + from typing import _next_in_mro, _type_check # noqa + + def _no_init(self, *args, **kwargs): + if type(self)._is_protocol: + raise TypeError('Protocols cannot be instantiated') + + class _ProtocolMeta(GenericMeta): + """Internal metaclass for Protocol. + + This exists so Protocol classes can be generic without deriving + from Generic. + """ + def __new__(cls, name, bases, namespace, + tvars=None, args=None, origin=None, extra=None, orig_bases=None): + # This is just a version copied from GenericMeta.__new__ that + # includes "Protocol" special treatment. (Comments removed for brevity.) + assert extra is None # Protocols should not have extra + if tvars is not None: + assert origin is not None + assert all(isinstance(t, typing.TypeVar) for t in tvars), tvars + else: + tvars = _type_vars(bases) + gvars = None + for base in bases: + if base is typing.Generic: + raise TypeError("Cannot inherit from plain Generic") + if (isinstance(base, GenericMeta) and + base.__origin__ in (typing.Generic, Protocol)): + if gvars is not None: + raise TypeError( + "Cannot inherit from Generic[...] or" + " Protocol[...] multiple times.") + gvars = base.__parameters__ + if gvars is None: + gvars = tvars + else: + tvarset = set(tvars) + gvarset = set(gvars) + if not tvarset <= gvarset: + s_vars = ", ".join(str(t) for t in tvars if t not in gvarset) + s_args = ", ".join(str(g) for g in gvars) + cls_name = "Generic" if any(b.__origin__ is typing.Generic + for b in bases) else "Protocol" + raise TypeError(f"Some type variables ({s_vars}) are" + f" not listed in {cls_name}[{s_args}]") + tvars = gvars + + initial_bases = bases + if (extra is not None and type(extra) is abc.ABCMeta and + extra not in bases): + bases = (extra,) + bases + bases = tuple(_gorg(b) if isinstance(b, GenericMeta) else b + for b in bases) + if any(isinstance(b, GenericMeta) and b is not typing.Generic for b in bases): + bases = tuple(b for b in bases if b is not typing.Generic) + namespace.update({'__origin__': origin, '__extra__': extra}) + self = super(GenericMeta, cls).__new__(cls, name, bases, namespace, + _root=True) + super(GenericMeta, self).__setattr__('_gorg', + self if not origin else + _gorg(origin)) + self.__parameters__ = tvars + self.__args__ = tuple(... if a is typing._TypingEllipsis else + () if a is typing._TypingEmpty else + a for a in args) if args else None + self.__next_in_mro__ = _next_in_mro(self) + if orig_bases is None: + self.__orig_bases__ = initial_bases + elif origin is not None: + self._abc_registry = origin._abc_registry + self._abc_cache = origin._abc_cache + if hasattr(self, '_subs_tree'): + self.__tree_hash__ = (hash(self._subs_tree()) if origin else + super(GenericMeta, self).__hash__()) + return self + + def __init__(cls, *args, **kwargs): + super().__init__(*args, **kwargs) + if not cls.__dict__.get('_is_protocol', None): + cls._is_protocol = any(b is Protocol or + isinstance(b, _ProtocolMeta) and + b.__origin__ is Protocol + for b in cls.__bases__) + if cls._is_protocol: + for base in cls.__mro__[1:]: + if not (base in (object, typing.Generic) or + base.__module__ == 'collections.abc' and + base.__name__ in _PROTO_WHITELIST or + isinstance(base, typing.TypingMeta) and base._is_protocol or + isinstance(base, GenericMeta) and + base.__origin__ is typing.Generic): + raise TypeError(f'Protocols can only inherit from other' + f' protocols, got {repr(base)}') + + cls.__init__ = _no_init + + def _proto_hook(other): + if not cls.__dict__.get('_is_protocol', None): + return NotImplemented + if not isinstance(other, type): + # Same error as for issubclass(1, int) + raise TypeError('issubclass() arg 1 must be a class') + for attr in _get_protocol_attrs(cls): + for base in other.__mro__: + if attr in base.__dict__: + if base.__dict__[attr] is None: + return NotImplemented + break + annotations = getattr(base, '__annotations__', {}) + if (isinstance(annotations, typing.Mapping) and + attr in annotations and + isinstance(other, _ProtocolMeta) and + other._is_protocol): + break + else: + return NotImplemented + return True + if '__subclasshook__' not in cls.__dict__: + cls.__subclasshook__ = _proto_hook + + def __instancecheck__(self, instance): + # We need this method for situations where attributes are + # assigned in __init__. + if ((not getattr(self, '_is_protocol', False) or + _is_callable_members_only(self)) and + issubclass(instance.__class__, self)): + return True + if self._is_protocol: + if all(hasattr(instance, attr) and + (not callable(getattr(self, attr, None)) or + getattr(instance, attr) is not None) + for attr in _get_protocol_attrs(self)): + return True + return super(GenericMeta, self).__instancecheck__(instance) + + def __subclasscheck__(self, cls): + if self.__origin__ is not None: + if sys._getframe(1).f_globals['__name__'] not in ['abc', 'functools']: + raise TypeError("Parameterized generics cannot be used with class " + "or instance checks") + return False + if (self.__dict__.get('_is_protocol', None) and + not self.__dict__.get('_is_runtime_protocol', None)): + if sys._getframe(1).f_globals['__name__'] in ['abc', + 'functools', + 'typing']: + return False + raise TypeError("Instance and class checks can only be used with" + " @runtime protocols") + if (self.__dict__.get('_is_runtime_protocol', None) and + not _is_callable_members_only(self)): + if sys._getframe(1).f_globals['__name__'] in ['abc', + 'functools', + 'typing']: + return super(GenericMeta, self).__subclasscheck__(cls) + raise TypeError("Protocols with non-method members" + " don't support issubclass()") + return super(GenericMeta, self).__subclasscheck__(cls) + + @typing._tp_cache + def __getitem__(self, params): + # We also need to copy this from GenericMeta.__getitem__ to get + # special treatment of "Protocol". (Comments removed for brevity.) + if not isinstance(params, tuple): + params = (params,) + if not params and _gorg(self) is not typing.Tuple: + raise TypeError( + f"Parameter list to {self.__qualname__}[...] cannot be empty") + msg = "Parameters to generic types must be types." + params = tuple(_type_check(p, msg) for p in params) + if self in (typing.Generic, Protocol): + if not all(isinstance(p, typing.TypeVar) for p in params): + raise TypeError( + f"Parameters to {repr(self)}[...] must all be type variables") + if len(set(params)) != len(params): + raise TypeError( + f"Parameters to {repr(self)}[...] must all be unique") + tvars = params + args = params + elif self in (typing.Tuple, typing.Callable): + tvars = _type_vars(params) + args = params + elif self.__origin__ in (typing.Generic, Protocol): + raise TypeError(f"Cannot subscript already-subscripted {repr(self)}") + else: + _check_generic(self, params) + tvars = _type_vars(params) + args = params + + prepend = (self,) if self.__origin__ is None else () + return self.__class__(self.__name__, + prepend + self.__bases__, + _no_slots_copy(self.__dict__), + tvars=tvars, + args=args, + origin=self, + extra=self.__extra__, + orig_bases=self.__orig_bases__) + + class Protocol(metaclass=_ProtocolMeta): + """Base class for protocol classes. Protocol classes are defined as:: + + class Proto(Protocol): + def meth(self) -> int: + ... + + Such classes are primarily used with static type checkers that recognize + structural subtyping (static duck-typing), for example:: + + class C: + def meth(self) -> int: + return 0 + + def func(x: Proto) -> int: + return x.meth() + + func(C()) # Passes static type check + + See PEP 544 for details. Protocol classes decorated with + @typing_extensions.runtime act as simple-minded runtime protocol that checks + only the presence of given attributes, ignoring their type signatures. + + Protocol classes can be generic, they are defined as:: + + class GenProto(Protocol[T]): + def meth(self) -> T: + ... + """ + __slots__ = () + _is_protocol = True + + def __new__(cls, *args, **kwds): + if _gorg(cls) is Protocol: + raise TypeError("Type Protocol cannot be instantiated; " + "it can be used only as a base class") + return typing._generic_new(cls.__next_in_mro__, cls, *args, **kwds) + + +# 3.8+ +if hasattr(typing, 'runtime_checkable'): + runtime_checkable = typing.runtime_checkable +# 3.6-3.7 +else: + def runtime_checkable(cls): + """Mark a protocol class as a runtime protocol, so that it + can be used with isinstance() and issubclass(). Raise TypeError + if applied to a non-protocol class. + + This allows a simple-minded structural check very similar to the + one-offs in collections.abc such as Hashable. + """ + if not isinstance(cls, _ProtocolMeta) or not cls._is_protocol: + raise TypeError('@runtime_checkable can be only applied to protocol classes,' + f' got {cls!r}') + cls._is_runtime_protocol = True + return cls + + +# Exists for backwards compatibility. +runtime = runtime_checkable + + +# 3.8+ +if hasattr(typing, 'SupportsIndex'): + SupportsIndex = typing.SupportsIndex +# 3.6-3.7 +else: + @runtime_checkable + class SupportsIndex(Protocol): + __slots__ = () + + @abc.abstractmethod + def __index__(self) -> int: + pass + + +if sys.version_info >= (3, 9, 2): + # The standard library TypedDict in Python 3.8 does not store runtime information + # about which (if any) keys are optional. See https://bugs.python.org/issue38834 + # The standard library TypedDict in Python 3.9.0/1 does not honour the "total" + # keyword with old-style TypedDict(). See https://bugs.python.org/issue42059 + TypedDict = typing.TypedDict +else: + def _check_fails(cls, other): + try: + if sys._getframe(1).f_globals['__name__'] not in ['abc', + 'functools', + 'typing']: + # Typed dicts are only for static structural subtyping. + raise TypeError('TypedDict does not support instance and class checks') + except (AttributeError, ValueError): + pass + return False + + def _dict_new(*args, **kwargs): + if not args: + raise TypeError('TypedDict.__new__(): not enough arguments') + _, args = args[0], args[1:] # allow the "cls" keyword be passed + return dict(*args, **kwargs) + + _dict_new.__text_signature__ = '($cls, _typename, _fields=None, /, **kwargs)' + + def _typeddict_new(*args, total=True, **kwargs): + if not args: + raise TypeError('TypedDict.__new__(): not enough arguments') + _, args = args[0], args[1:] # allow the "cls" keyword be passed + if args: + typename, args = args[0], args[1:] # allow the "_typename" keyword be passed + elif '_typename' in kwargs: + typename = kwargs.pop('_typename') + import warnings + warnings.warn("Passing '_typename' as keyword argument is deprecated", + DeprecationWarning, stacklevel=2) + else: + raise TypeError("TypedDict.__new__() missing 1 required positional " + "argument: '_typename'") + if args: + try: + fields, = args # allow the "_fields" keyword be passed + except ValueError: + raise TypeError('TypedDict.__new__() takes from 2 to 3 ' + f'positional arguments but {len(args) + 2} ' + 'were given') + elif '_fields' in kwargs and len(kwargs) == 1: + fields = kwargs.pop('_fields') + import warnings + warnings.warn("Passing '_fields' as keyword argument is deprecated", + DeprecationWarning, stacklevel=2) + else: + fields = None + + if fields is None: + fields = kwargs + elif kwargs: + raise TypeError("TypedDict takes either a dict or keyword arguments," + " but not both") + + ns = {'__annotations__': dict(fields)} + try: + # Setting correct module is necessary to make typed dict classes pickleable. + ns['__module__'] = sys._getframe(1).f_globals.get('__name__', '__main__') + except (AttributeError, ValueError): + pass + + return _TypedDictMeta(typename, (), ns, total=total) + + _typeddict_new.__text_signature__ = ('($cls, _typename, _fields=None,' + ' /, *, total=True, **kwargs)') + + class _TypedDictMeta(type): + def __init__(cls, name, bases, ns, total=True): + super().__init__(name, bases, ns) + + def __new__(cls, name, bases, ns, total=True): + # Create new typed dict class object. + # This method is called directly when TypedDict is subclassed, + # or via _typeddict_new when TypedDict is instantiated. This way + # TypedDict supports all three syntaxes described in its docstring. + # Subclasses and instances of TypedDict return actual dictionaries + # via _dict_new. + ns['__new__'] = _typeddict_new if name == 'TypedDict' else _dict_new + tp_dict = super().__new__(cls, name, (dict,), ns) + + annotations = {} + own_annotations = ns.get('__annotations__', {}) + own_annotation_keys = set(own_annotations.keys()) + msg = "TypedDict('Name', {f0: t0, f1: t1, ...}); each t must be a type" + own_annotations = { + n: typing._type_check(tp, msg) for n, tp in own_annotations.items() + } + required_keys = set() + optional_keys = set() + + for base in bases: + annotations.update(base.__dict__.get('__annotations__', {})) + required_keys.update(base.__dict__.get('__required_keys__', ())) + optional_keys.update(base.__dict__.get('__optional_keys__', ())) + + annotations.update(own_annotations) + if total: + required_keys.update(own_annotation_keys) + else: + optional_keys.update(own_annotation_keys) + + tp_dict.__annotations__ = annotations + tp_dict.__required_keys__ = frozenset(required_keys) + tp_dict.__optional_keys__ = frozenset(optional_keys) + if not hasattr(tp_dict, '__total__'): + tp_dict.__total__ = total + return tp_dict + + __instancecheck__ = __subclasscheck__ = _check_fails + + TypedDict = _TypedDictMeta('TypedDict', (dict,), {}) + TypedDict.__module__ = __name__ + TypedDict.__doc__ = \ + """A simple typed name space. At runtime it is equivalent to a plain dict. + + TypedDict creates a dictionary type that expects all of its + instances to have a certain set of keys, with each key + associated with a value of a consistent type. This expectation + is not checked at runtime but is only enforced by type checkers. + Usage:: + + class Point2D(TypedDict): + x: int + y: int + label: str + + a: Point2D = {'x': 1, 'y': 2, 'label': 'good'} # OK + b: Point2D = {'z': 3, 'label': 'bad'} # Fails type check + + assert Point2D(x=1, y=2, label='first') == dict(x=1, y=2, label='first') + + The type info can be accessed via the Point2D.__annotations__ dict, and + the Point2D.__required_keys__ and Point2D.__optional_keys__ frozensets. + TypedDict supports two additional equivalent forms:: + + Point2D = TypedDict('Point2D', x=int, y=int, label=str) + Point2D = TypedDict('Point2D', {'x': int, 'y': int, 'label': str}) + + The class syntax is only supported in Python 3.6+, while two other + syntax forms work for Python 2.7 and 3.2+ + """ + + +# Python 3.9+ has PEP 593 (Annotated and modified get_type_hints) +if hasattr(typing, 'Annotated'): + Annotated = typing.Annotated + get_type_hints = typing.get_type_hints + # Not exported and not a public API, but needed for get_origin() and get_args() + # to work. + _AnnotatedAlias = typing._AnnotatedAlias +# 3.7-3.8 +elif PEP_560: + class _AnnotatedAlias(typing._GenericAlias, _root=True): + """Runtime representation of an annotated type. + + At its core 'Annotated[t, dec1, dec2, ...]' is an alias for the type 't' + with extra annotations. The alias behaves like a normal typing alias, + instantiating is the same as instantiating the underlying type, binding + it to types is also the same. + """ + def __init__(self, origin, metadata): + if isinstance(origin, _AnnotatedAlias): + metadata = origin.__metadata__ + metadata + origin = origin.__origin__ + super().__init__(origin, origin) + self.__metadata__ = metadata + + def copy_with(self, params): + assert len(params) == 1 + new_type = params[0] + return _AnnotatedAlias(new_type, self.__metadata__) + + def __repr__(self): + return (f"typing_extensions.Annotated[{typing._type_repr(self.__origin__)}, " + f"{', '.join(repr(a) for a in self.__metadata__)}]") + + def __reduce__(self): + return operator.getitem, ( + Annotated, (self.__origin__,) + self.__metadata__ + ) + + def __eq__(self, other): + if not isinstance(other, _AnnotatedAlias): + return NotImplemented + if self.__origin__ != other.__origin__: + return False + return self.__metadata__ == other.__metadata__ + + def __hash__(self): + return hash((self.__origin__, self.__metadata__)) + + class Annotated: + """Add context specific metadata to a type. + + Example: Annotated[int, runtime_check.Unsigned] indicates to the + hypothetical runtime_check module that this type is an unsigned int. + Every other consumer of this type can ignore this metadata and treat + this type as int. + + The first argument to Annotated must be a valid type (and will be in + the __origin__ field), the remaining arguments are kept as a tuple in + the __extra__ field. + + Details: + + - It's an error to call `Annotated` with less than two arguments. + - Nested Annotated are flattened:: + + Annotated[Annotated[T, Ann1, Ann2], Ann3] == Annotated[T, Ann1, Ann2, Ann3] + + - Instantiating an annotated type is equivalent to instantiating the + underlying type:: + + Annotated[C, Ann1](5) == C(5) + + - Annotated can be used as a generic type alias:: + + Optimized = Annotated[T, runtime.Optimize()] + Optimized[int] == Annotated[int, runtime.Optimize()] + + OptimizedList = Annotated[List[T], runtime.Optimize()] + OptimizedList[int] == Annotated[List[int], runtime.Optimize()] + """ + + __slots__ = () + + def __new__(cls, *args, **kwargs): + raise TypeError("Type Annotated cannot be instantiated.") + + @typing._tp_cache + def __class_getitem__(cls, params): + if not isinstance(params, tuple) or len(params) < 2: + raise TypeError("Annotated[...] should be used " + "with at least two arguments (a type and an " + "annotation).") + msg = "Annotated[t, ...]: t must be a type." + origin = typing._type_check(params[0], msg) + metadata = tuple(params[1:]) + return _AnnotatedAlias(origin, metadata) + + def __init_subclass__(cls, *args, **kwargs): + raise TypeError( + f"Cannot subclass {cls.__module__}.Annotated" + ) + + def _strip_annotations(t): + """Strips the annotations from a given type. + """ + if isinstance(t, _AnnotatedAlias): + return _strip_annotations(t.__origin__) + if isinstance(t, typing._GenericAlias): + stripped_args = tuple(_strip_annotations(a) for a in t.__args__) + if stripped_args == t.__args__: + return t + res = t.copy_with(stripped_args) + res._special = t._special + return res + return t + + def get_type_hints(obj, globalns=None, localns=None, include_extras=False): + """Return type hints for an object. + + This is often the same as obj.__annotations__, but it handles + forward references encoded as string literals, adds Optional[t] if a + default value equal to None is set and recursively replaces all + 'Annotated[T, ...]' with 'T' (unless 'include_extras=True'). + + The argument may be a module, class, method, or function. The annotations + are returned as a dictionary. For classes, annotations include also + inherited members. + + TypeError is raised if the argument is not of a type that can contain + annotations, and an empty dictionary is returned if no annotations are + present. + + BEWARE -- the behavior of globalns and localns is counterintuitive + (unless you are familiar with how eval() and exec() work). The + search order is locals first, then globals. + + - If no dict arguments are passed, an attempt is made to use the + globals from obj (or the respective module's globals for classes), + and these are also used as the locals. If the object does not appear + to have globals, an empty dictionary is used. + + - If one dict argument is passed, it is used for both globals and + locals. + + - If two dict arguments are passed, they specify globals and + locals, respectively. + """ + hint = typing.get_type_hints(obj, globalns=globalns, localns=localns) + if include_extras: + return hint + return {k: _strip_annotations(t) for k, t in hint.items()} +# 3.6 +else: + + def _is_dunder(name): + """Returns True if name is a __dunder_variable_name__.""" + return len(name) > 4 and name.startswith('__') and name.endswith('__') + + # Prior to Python 3.7 types did not have `copy_with`. A lot of the equality + # checks, argument expansion etc. are done on the _subs_tre. As a result we + # can't provide a get_type_hints function that strips out annotations. + + class AnnotatedMeta(typing.GenericMeta): + """Metaclass for Annotated""" + + def __new__(cls, name, bases, namespace, **kwargs): + if any(b is not object for b in bases): + raise TypeError("Cannot subclass " + str(Annotated)) + return super().__new__(cls, name, bases, namespace, **kwargs) + + @property + def __metadata__(self): + return self._subs_tree()[2] + + def _tree_repr(self, tree): + cls, origin, metadata = tree + if not isinstance(origin, tuple): + tp_repr = typing._type_repr(origin) + else: + tp_repr = origin[0]._tree_repr(origin) + metadata_reprs = ", ".join(repr(arg) for arg in metadata) + return f'{cls}[{tp_repr}, {metadata_reprs}]' + + def _subs_tree(self, tvars=None, args=None): # noqa + if self is Annotated: + return Annotated + res = super()._subs_tree(tvars=tvars, args=args) + # Flatten nested Annotated + if isinstance(res[1], tuple) and res[1][0] is Annotated: + sub_tp = res[1][1] + sub_annot = res[1][2] + return (Annotated, sub_tp, sub_annot + res[2]) + return res + + def _get_cons(self): + """Return the class used to create instance of this type.""" + if self.__origin__ is None: + raise TypeError("Cannot get the underlying type of a " + "non-specialized Annotated type.") + tree = self._subs_tree() + while isinstance(tree, tuple) and tree[0] is Annotated: + tree = tree[1] + if isinstance(tree, tuple): + return tree[0] + else: + return tree + + @typing._tp_cache + def __getitem__(self, params): + if not isinstance(params, tuple): + params = (params,) + if self.__origin__ is not None: # specializing an instantiated type + return super().__getitem__(params) + elif not isinstance(params, tuple) or len(params) < 2: + raise TypeError("Annotated[...] should be instantiated " + "with at least two arguments (a type and an " + "annotation).") + else: + msg = "Annotated[t, ...]: t must be a type." + tp = typing._type_check(params[0], msg) + metadata = tuple(params[1:]) + return self.__class__( + self.__name__, + self.__bases__, + _no_slots_copy(self.__dict__), + tvars=_type_vars((tp,)), + # Metadata is a tuple so it won't be touched by _replace_args et al. + args=(tp, metadata), + origin=self, + ) + + def __call__(self, *args, **kwargs): + cons = self._get_cons() + result = cons(*args, **kwargs) + try: + result.__orig_class__ = self + except AttributeError: + pass + return result + + def __getattr__(self, attr): + # For simplicity we just don't relay all dunder names + if self.__origin__ is not None and not _is_dunder(attr): + return getattr(self._get_cons(), attr) + raise AttributeError(attr) + + def __setattr__(self, attr, value): + if _is_dunder(attr) or attr.startswith('_abc_'): + super().__setattr__(attr, value) + elif self.__origin__ is None: + raise AttributeError(attr) + else: + setattr(self._get_cons(), attr, value) + + def __instancecheck__(self, obj): + raise TypeError("Annotated cannot be used with isinstance().") + + def __subclasscheck__(self, cls): + raise TypeError("Annotated cannot be used with issubclass().") + + class Annotated(metaclass=AnnotatedMeta): + """Add context specific metadata to a type. + + Example: Annotated[int, runtime_check.Unsigned] indicates to the + hypothetical runtime_check module that this type is an unsigned int. + Every other consumer of this type can ignore this metadata and treat + this type as int. + + The first argument to Annotated must be a valid type, the remaining + arguments are kept as a tuple in the __metadata__ field. + + Details: + + - It's an error to call `Annotated` with less than two arguments. + - Nested Annotated are flattened:: + + Annotated[Annotated[T, Ann1, Ann2], Ann3] == Annotated[T, Ann1, Ann2, Ann3] + + - Instantiating an annotated type is equivalent to instantiating the + underlying type:: + + Annotated[C, Ann1](5) == C(5) + + - Annotated can be used as a generic type alias:: + + Optimized = Annotated[T, runtime.Optimize()] + Optimized[int] == Annotated[int, runtime.Optimize()] + + OptimizedList = Annotated[List[T], runtime.Optimize()] + OptimizedList[int] == Annotated[List[int], runtime.Optimize()] + """ + +# Python 3.8 has get_origin() and get_args() but those implementations aren't +# Annotated-aware, so we can't use those. Python 3.9's versions don't support +# ParamSpecArgs and ParamSpecKwargs, so only Python 3.10's versions will do. +if sys.version_info[:2] >= (3, 10): + get_origin = typing.get_origin + get_args = typing.get_args +# 3.7-3.9 +elif PEP_560: + try: + # 3.9+ + from typing import _BaseGenericAlias + except ImportError: + _BaseGenericAlias = typing._GenericAlias + try: + # 3.9+ + from typing import GenericAlias + except ImportError: + GenericAlias = typing._GenericAlias + + def get_origin(tp): + """Get the unsubscripted version of a type. + + This supports generic types, Callable, Tuple, Union, Literal, Final, ClassVar + and Annotated. Return None for unsupported types. Examples:: + + get_origin(Literal[42]) is Literal + get_origin(int) is None + get_origin(ClassVar[int]) is ClassVar + get_origin(Generic) is Generic + get_origin(Generic[T]) is Generic + get_origin(Union[T, int]) is Union + get_origin(List[Tuple[T, T]][int]) == list + get_origin(P.args) is P + """ + if isinstance(tp, _AnnotatedAlias): + return Annotated + if isinstance(tp, (typing._GenericAlias, GenericAlias, _BaseGenericAlias, + ParamSpecArgs, ParamSpecKwargs)): + return tp.__origin__ + if tp is typing.Generic: + return typing.Generic + return None + + def get_args(tp): + """Get type arguments with all substitutions performed. + + For unions, basic simplifications used by Union constructor are performed. + Examples:: + get_args(Dict[str, int]) == (str, int) + get_args(int) == () + get_args(Union[int, Union[T, int], str][int]) == (int, str) + get_args(Union[int, Tuple[T, int]][str]) == (int, Tuple[str, int]) + get_args(Callable[[], T][int]) == ([], int) + """ + if isinstance(tp, _AnnotatedAlias): + return (tp.__origin__,) + tp.__metadata__ + if isinstance(tp, (typing._GenericAlias, GenericAlias)): + if getattr(tp, "_special", False): + return () + res = tp.__args__ + if get_origin(tp) is collections.abc.Callable and res[0] is not Ellipsis: + res = (list(res[:-1]), res[-1]) + return res + return () + + +# 3.10+ +if hasattr(typing, 'TypeAlias'): + TypeAlias = typing.TypeAlias +# 3.9 +elif sys.version_info[:2] >= (3, 9): + class _TypeAliasForm(typing._SpecialForm, _root=True): + def __repr__(self): + return 'typing_extensions.' + self._name + + @_TypeAliasForm + def TypeAlias(self, parameters): + """Special marker indicating that an assignment should + be recognized as a proper type alias definition by type + checkers. + + For example:: + + Predicate: TypeAlias = Callable[..., bool] + + It's invalid when used anywhere except as in the example above. + """ + raise TypeError(f"{self} is not subscriptable") +# 3.7-3.8 +elif sys.version_info[:2] >= (3, 7): + class _TypeAliasForm(typing._SpecialForm, _root=True): + def __repr__(self): + return 'typing_extensions.' + self._name + + TypeAlias = _TypeAliasForm('TypeAlias', + doc="""Special marker indicating that an assignment should + be recognized as a proper type alias definition by type + checkers. + + For example:: + + Predicate: TypeAlias = Callable[..., bool] + + It's invalid when used anywhere except as in the example + above.""") +# 3.6 +else: + class _TypeAliasMeta(typing.TypingMeta): + """Metaclass for TypeAlias""" + + def __repr__(self): + return 'typing_extensions.TypeAlias' + + class _TypeAliasBase(typing._FinalTypingBase, metaclass=_TypeAliasMeta, _root=True): + """Special marker indicating that an assignment should + be recognized as a proper type alias definition by type + checkers. + + For example:: + + Predicate: TypeAlias = Callable[..., bool] + + It's invalid when used anywhere except as in the example above. + """ + __slots__ = () + + def __instancecheck__(self, obj): + raise TypeError("TypeAlias cannot be used with isinstance().") + + def __subclasscheck__(self, cls): + raise TypeError("TypeAlias cannot be used with issubclass().") + + def __repr__(self): + return 'typing_extensions.TypeAlias' + + TypeAlias = _TypeAliasBase(_root=True) + + +# Python 3.10+ has PEP 612 +if hasattr(typing, 'ParamSpecArgs'): + ParamSpecArgs = typing.ParamSpecArgs + ParamSpecKwargs = typing.ParamSpecKwargs +# 3.6-3.9 +else: + class _Immutable: + """Mixin to indicate that object should not be copied.""" + __slots__ = () + + def __copy__(self): + return self + + def __deepcopy__(self, memo): + return self + + class ParamSpecArgs(_Immutable): + """The args for a ParamSpec object. + + Given a ParamSpec object P, P.args is an instance of ParamSpecArgs. + + ParamSpecArgs objects have a reference back to their ParamSpec: + + P.args.__origin__ is P + + This type is meant for runtime introspection and has no special meaning to + static type checkers. + """ + def __init__(self, origin): + self.__origin__ = origin + + def __repr__(self): + return f"{self.__origin__.__name__}.args" + + class ParamSpecKwargs(_Immutable): + """The kwargs for a ParamSpec object. + + Given a ParamSpec object P, P.kwargs is an instance of ParamSpecKwargs. + + ParamSpecKwargs objects have a reference back to their ParamSpec: + + P.kwargs.__origin__ is P + + This type is meant for runtime introspection and has no special meaning to + static type checkers. + """ + def __init__(self, origin): + self.__origin__ = origin + + def __repr__(self): + return f"{self.__origin__.__name__}.kwargs" + +# 3.10+ +if hasattr(typing, 'ParamSpec'): + ParamSpec = typing.ParamSpec +# 3.6-3.9 +else: + + # Inherits from list as a workaround for Callable checks in Python < 3.9.2. + class ParamSpec(list): + """Parameter specification variable. + + Usage:: + + P = ParamSpec('P') + + Parameter specification variables exist primarily for the benefit of static + type checkers. They are used to forward the parameter types of one + callable to another callable, a pattern commonly found in higher order + functions and decorators. They are only valid when used in ``Concatenate``, + or s the first argument to ``Callable``. In Python 3.10 and higher, + they are also supported in user-defined Generics at runtime. + See class Generic for more information on generic types. An + example for annotating a decorator:: + + T = TypeVar('T') + P = ParamSpec('P') + + def add_logging(f: Callable[P, T]) -> Callable[P, T]: + '''A type-safe decorator to add logging to a function.''' + def inner(*args: P.args, **kwargs: P.kwargs) -> T: + logging.info(f'{f.__name__} was called') + return f(*args, **kwargs) + return inner + + @add_logging + def add_two(x: float, y: float) -> float: + '''Add two numbers together.''' + return x + y + + Parameter specification variables defined with covariant=True or + contravariant=True can be used to declare covariant or contravariant + generic types. These keyword arguments are valid, but their actual semantics + are yet to be decided. See PEP 612 for details. + + Parameter specification variables can be introspected. e.g.: + + P.__name__ == 'T' + P.__bound__ == None + P.__covariant__ == False + P.__contravariant__ == False + + Note that only parameter specification variables defined in global scope can + be pickled. + """ + + # Trick Generic __parameters__. + __class__ = typing.TypeVar + + @property + def args(self): + return ParamSpecArgs(self) + + @property + def kwargs(self): + return ParamSpecKwargs(self) + + def __init__(self, name, *, bound=None, covariant=False, contravariant=False): + super().__init__([self]) + self.__name__ = name + self.__covariant__ = bool(covariant) + self.__contravariant__ = bool(contravariant) + if bound: + self.__bound__ = typing._type_check(bound, 'Bound must be a type.') + else: + self.__bound__ = None + + # for pickling: + try: + def_mod = sys._getframe(1).f_globals.get('__name__', '__main__') + except (AttributeError, ValueError): + def_mod = None + if def_mod != 'typing_extensions': + self.__module__ = def_mod + + def __repr__(self): + if self.__covariant__: + prefix = '+' + elif self.__contravariant__: + prefix = '-' + else: + prefix = '~' + return prefix + self.__name__ + + def __hash__(self): + return object.__hash__(self) + + def __eq__(self, other): + return self is other + + def __reduce__(self): + return self.__name__ + + # Hack to get typing._type_check to pass. + def __call__(self, *args, **kwargs): + pass + + if not PEP_560: + # Only needed in 3.6. + def _get_type_vars(self, tvars): + if self not in tvars: + tvars.append(self) + + +# 3.6-3.9 +if not hasattr(typing, 'Concatenate'): + # Inherits from list as a workaround for Callable checks in Python < 3.9.2. + class _ConcatenateGenericAlias(list): + + # Trick Generic into looking into this for __parameters__. + if PEP_560: + __class__ = typing._GenericAlias + else: + __class__ = typing._TypingBase + + # Flag in 3.8. + _special = False + # Attribute in 3.6 and earlier. + _gorg = typing.Generic + + def __init__(self, origin, args): + super().__init__(args) + self.__origin__ = origin + self.__args__ = args + + def __repr__(self): + _type_repr = typing._type_repr + return (f'{_type_repr(self.__origin__)}' + f'[{", ".join(_type_repr(arg) for arg in self.__args__)}]') + + def __hash__(self): + return hash((self.__origin__, self.__args__)) + + # Hack to get typing._type_check to pass in Generic. + def __call__(self, *args, **kwargs): + pass + + @property + def __parameters__(self): + return tuple( + tp for tp in self.__args__ if isinstance(tp, (typing.TypeVar, ParamSpec)) + ) + + if not PEP_560: + # Only required in 3.6. + def _get_type_vars(self, tvars): + if self.__origin__ and self.__parameters__: + typing._get_type_vars(self.__parameters__, tvars) + + +# 3.6-3.9 +@typing._tp_cache +def _concatenate_getitem(self, parameters): + if parameters == (): + raise TypeError("Cannot take a Concatenate of no types.") + if not isinstance(parameters, tuple): + parameters = (parameters,) + if not isinstance(parameters[-1], ParamSpec): + raise TypeError("The last parameter to Concatenate should be a " + "ParamSpec variable.") + msg = "Concatenate[arg, ...]: each arg must be a type." + parameters = tuple(typing._type_check(p, msg) for p in parameters) + return _ConcatenateGenericAlias(self, parameters) + + +# 3.10+ +if hasattr(typing, 'Concatenate'): + Concatenate = typing.Concatenate + _ConcatenateGenericAlias = typing._ConcatenateGenericAlias # noqa +# 3.9 +elif sys.version_info[:2] >= (3, 9): + @_TypeAliasForm + def Concatenate(self, parameters): + """Used in conjunction with ``ParamSpec`` and ``Callable`` to represent a + higher order function which adds, removes or transforms parameters of a + callable. + + For example:: + + Callable[Concatenate[int, P], int] + + See PEP 612 for detailed information. + """ + return _concatenate_getitem(self, parameters) +# 3.7-8 +elif sys.version_info[:2] >= (3, 7): + class _ConcatenateForm(typing._SpecialForm, _root=True): + def __repr__(self): + return 'typing_extensions.' + self._name + + def __getitem__(self, parameters): + return _concatenate_getitem(self, parameters) + + Concatenate = _ConcatenateForm( + 'Concatenate', + doc="""Used in conjunction with ``ParamSpec`` and ``Callable`` to represent a + higher order function which adds, removes or transforms parameters of a + callable. + + For example:: + + Callable[Concatenate[int, P], int] + + See PEP 612 for detailed information. + """) +# 3.6 +else: + class _ConcatenateAliasMeta(typing.TypingMeta): + """Metaclass for Concatenate.""" + + def __repr__(self): + return 'typing_extensions.Concatenate' + + class _ConcatenateAliasBase(typing._FinalTypingBase, + metaclass=_ConcatenateAliasMeta, + _root=True): + """Used in conjunction with ``ParamSpec`` and ``Callable`` to represent a + higher order function which adds, removes or transforms parameters of a + callable. + + For example:: + + Callable[Concatenate[int, P], int] + + See PEP 612 for detailed information. + """ + __slots__ = () + + def __instancecheck__(self, obj): + raise TypeError("Concatenate cannot be used with isinstance().") + + def __subclasscheck__(self, cls): + raise TypeError("Concatenate cannot be used with issubclass().") + + def __repr__(self): + return 'typing_extensions.Concatenate' + + def __getitem__(self, parameters): + return _concatenate_getitem(self, parameters) + + Concatenate = _ConcatenateAliasBase(_root=True) + +# 3.10+ +if hasattr(typing, 'TypeGuard'): + TypeGuard = typing.TypeGuard +# 3.9 +elif sys.version_info[:2] >= (3, 9): + class _TypeGuardForm(typing._SpecialForm, _root=True): + def __repr__(self): + return 'typing_extensions.' + self._name + + @_TypeGuardForm + def TypeGuard(self, parameters): + """Special typing form used to annotate the return type of a user-defined + type guard function. ``TypeGuard`` only accepts a single type argument. + At runtime, functions marked this way should return a boolean. + + ``TypeGuard`` aims to benefit *type narrowing* -- a technique used by static + type checkers to determine a more precise type of an expression within a + program's code flow. Usually type narrowing is done by analyzing + conditional code flow and applying the narrowing to a block of code. The + conditional expression here is sometimes referred to as a "type guard". + + Sometimes it would be convenient to use a user-defined boolean function + as a type guard. Such a function should use ``TypeGuard[...]`` as its + return type to alert static type checkers to this intention. + + Using ``-> TypeGuard`` tells the static type checker that for a given + function: + + 1. The return value is a boolean. + 2. If the return value is ``True``, the type of its argument + is the type inside ``TypeGuard``. + + For example:: + + def is_str(val: Union[str, float]): + # "isinstance" type guard + if isinstance(val, str): + # Type of ``val`` is narrowed to ``str`` + ... + else: + # Else, type of ``val`` is narrowed to ``float``. + ... + + Strict type narrowing is not enforced -- ``TypeB`` need not be a narrower + form of ``TypeA`` (it can even be a wider form) and this may lead to + type-unsafe results. The main reason is to allow for things like + narrowing ``List[object]`` to ``List[str]`` even though the latter is not + a subtype of the former, since ``List`` is invariant. The responsibility of + writing type-safe type guards is left to the user. + + ``TypeGuard`` also works with type variables. For more information, see + PEP 647 (User-Defined Type Guards). + """ + item = typing._type_check(parameters, f'{self} accepts only single type.') + return typing._GenericAlias(self, (item,)) +# 3.7-3.8 +elif sys.version_info[:2] >= (3, 7): + class _TypeGuardForm(typing._SpecialForm, _root=True): + + def __repr__(self): + return 'typing_extensions.' + self._name + + def __getitem__(self, parameters): + item = typing._type_check(parameters, + f'{self._name} accepts only a single type') + return typing._GenericAlias(self, (item,)) + + TypeGuard = _TypeGuardForm( + 'TypeGuard', + doc="""Special typing form used to annotate the return type of a user-defined + type guard function. ``TypeGuard`` only accepts a single type argument. + At runtime, functions marked this way should return a boolean. + + ``TypeGuard`` aims to benefit *type narrowing* -- a technique used by static + type checkers to determine a more precise type of an expression within a + program's code flow. Usually type narrowing is done by analyzing + conditional code flow and applying the narrowing to a block of code. The + conditional expression here is sometimes referred to as a "type guard". + + Sometimes it would be convenient to use a user-defined boolean function + as a type guard. Such a function should use ``TypeGuard[...]`` as its + return type to alert static type checkers to this intention. + + Using ``-> TypeGuard`` tells the static type checker that for a given + function: + + 1. The return value is a boolean. + 2. If the return value is ``True``, the type of its argument + is the type inside ``TypeGuard``. + + For example:: + + def is_str(val: Union[str, float]): + # "isinstance" type guard + if isinstance(val, str): + # Type of ``val`` is narrowed to ``str`` + ... + else: + # Else, type of ``val`` is narrowed to ``float``. + ... + + Strict type narrowing is not enforced -- ``TypeB`` need not be a narrower + form of ``TypeA`` (it can even be a wider form) and this may lead to + type-unsafe results. The main reason is to allow for things like + narrowing ``List[object]`` to ``List[str]`` even though the latter is not + a subtype of the former, since ``List`` is invariant. The responsibility of + writing type-safe type guards is left to the user. + + ``TypeGuard`` also works with type variables. For more information, see + PEP 647 (User-Defined Type Guards). + """) +# 3.6 +else: + class _TypeGuard(typing._FinalTypingBase, _root=True): + """Special typing form used to annotate the return type of a user-defined + type guard function. ``TypeGuard`` only accepts a single type argument. + At runtime, functions marked this way should return a boolean. + + ``TypeGuard`` aims to benefit *type narrowing* -- a technique used by static + type checkers to determine a more precise type of an expression within a + program's code flow. Usually type narrowing is done by analyzing + conditional code flow and applying the narrowing to a block of code. The + conditional expression here is sometimes referred to as a "type guard". + + Sometimes it would be convenient to use a user-defined boolean function + as a type guard. Such a function should use ``TypeGuard[...]`` as its + return type to alert static type checkers to this intention. + + Using ``-> TypeGuard`` tells the static type checker that for a given + function: + + 1. The return value is a boolean. + 2. If the return value is ``True``, the type of its argument + is the type inside ``TypeGuard``. + + For example:: + + def is_str(val: Union[str, float]): + # "isinstance" type guard + if isinstance(val, str): + # Type of ``val`` is narrowed to ``str`` + ... + else: + # Else, type of ``val`` is narrowed to ``float``. + ... + + Strict type narrowing is not enforced -- ``TypeB`` need not be a narrower + form of ``TypeA`` (it can even be a wider form) and this may lead to + type-unsafe results. The main reason is to allow for things like + narrowing ``List[object]`` to ``List[str]`` even though the latter is not + a subtype of the former, since ``List`` is invariant. The responsibility of + writing type-safe type guards is left to the user. + + ``TypeGuard`` also works with type variables. For more information, see + PEP 647 (User-Defined Type Guards). + """ + + __slots__ = ('__type__',) + + def __init__(self, tp=None, **kwds): + self.__type__ = tp + + def __getitem__(self, item): + cls = type(self) + if self.__type__ is None: + return cls(typing._type_check(item, + f'{cls.__name__[1:]} accepts only a single type.'), + _root=True) + raise TypeError(f'{cls.__name__[1:]} cannot be further subscripted') + + def _eval_type(self, globalns, localns): + new_tp = typing._eval_type(self.__type__, globalns, localns) + if new_tp == self.__type__: + return self + return type(self)(new_tp, _root=True) + + def __repr__(self): + r = super().__repr__() + if self.__type__ is not None: + r += f'[{typing._type_repr(self.__type__)}]' + return r + + def __hash__(self): + return hash((type(self).__name__, self.__type__)) + + def __eq__(self, other): + if not isinstance(other, _TypeGuard): + return NotImplemented + if self.__type__ is not None: + return self.__type__ == other.__type__ + return self is other + + TypeGuard = _TypeGuard(_root=True) + +if hasattr(typing, "Self"): + Self = typing.Self +elif sys.version_info[:2] >= (3, 7): + # Vendored from cpython typing._SpecialFrom + class _SpecialForm(typing._Final, _root=True): + __slots__ = ('_name', '__doc__', '_getitem') + + def __init__(self, getitem): + self._getitem = getitem + self._name = getitem.__name__ + self.__doc__ = getitem.__doc__ + + def __getattr__(self, item): + if item in {'__name__', '__qualname__'}: + return self._name + + raise AttributeError(item) + + def __mro_entries__(self, bases): + raise TypeError(f"Cannot subclass {self!r}") + + def __repr__(self): + return f'typing_extensions.{self._name}' + + def __reduce__(self): + return self._name + + def __call__(self, *args, **kwds): + raise TypeError(f"Cannot instantiate {self!r}") + + def __or__(self, other): + return typing.Union[self, other] + + def __ror__(self, other): + return typing.Union[other, self] + + def __instancecheck__(self, obj): + raise TypeError(f"{self} cannot be used with isinstance()") + + def __subclasscheck__(self, cls): + raise TypeError(f"{self} cannot be used with issubclass()") + + @typing._tp_cache + def __getitem__(self, parameters): + return self._getitem(self, parameters) + + @_SpecialForm + def Self(self, params): + """Used to spell the type of "self" in classes. + + Example:: + + from typing import Self + + class ReturnsSelf: + def parse(self, data: bytes) -> Self: + ... + return self + + """ + + raise TypeError(f"{self} is not subscriptable") +else: + class _Self(typing._FinalTypingBase, _root=True): + """Used to spell the type of "self" in classes. + + Example:: + + from typing import Self + + class ReturnsSelf: + def parse(self, data: bytes) -> Self: + ... + return self + + """ + + __slots__ = () + + def __instancecheck__(self, obj): + raise TypeError(f"{self} cannot be used with isinstance().") + + def __subclasscheck__(self, cls): + raise TypeError(f"{self} cannot be used with issubclass().") + + Self = _Self(_root=True) + + +if hasattr(typing, 'Required'): + Required = typing.Required + NotRequired = typing.NotRequired +elif sys.version_info[:2] >= (3, 9): + class _ExtensionsSpecialForm(typing._SpecialForm, _root=True): + def __repr__(self): + return 'typing_extensions.' + self._name + + @_ExtensionsSpecialForm + def Required(self, parameters): + """A special typing construct to mark a key of a total=False TypedDict + as required. For example: + + class Movie(TypedDict, total=False): + title: Required[str] + year: int + + m = Movie( + title='The Matrix', # typechecker error if key is omitted + year=1999, + ) + + There is no runtime checking that a required key is actually provided + when instantiating a related TypedDict. + """ + item = typing._type_check(parameters, f'{self._name} accepts only single type') + return typing._GenericAlias(self, (item,)) + + @_ExtensionsSpecialForm + def NotRequired(self, parameters): + """A special typing construct to mark a key of a TypedDict as + potentially missing. For example: + + class Movie(TypedDict): + title: str + year: NotRequired[int] + + m = Movie( + title='The Matrix', # typechecker error if key is omitted + year=1999, + ) + """ + item = typing._type_check(parameters, f'{self._name} accepts only single type') + return typing._GenericAlias(self, (item,)) + +elif sys.version_info[:2] >= (3, 7): + class _RequiredForm(typing._SpecialForm, _root=True): + def __repr__(self): + return 'typing_extensions.' + self._name + + def __getitem__(self, parameters): + item = typing._type_check(parameters, + '{} accepts only single type'.format(self._name)) + return typing._GenericAlias(self, (item,)) + + Required = _RequiredForm( + 'Required', + doc="""A special typing construct to mark a key of a total=False TypedDict + as required. For example: + + class Movie(TypedDict, total=False): + title: Required[str] + year: int + + m = Movie( + title='The Matrix', # typechecker error if key is omitted + year=1999, + ) + + There is no runtime checking that a required key is actually provided + when instantiating a related TypedDict. + """) + NotRequired = _RequiredForm( + 'NotRequired', + doc="""A special typing construct to mark a key of a TypedDict as + potentially missing. For example: + + class Movie(TypedDict): + title: str + year: NotRequired[int] + + m = Movie( + title='The Matrix', # typechecker error if key is omitted + year=1999, + ) + """) +else: + # NOTE: Modeled after _Final's implementation when _FinalTypingBase available + class _MaybeRequired(typing._FinalTypingBase, _root=True): + __slots__ = ('__type__',) + + def __init__(self, tp=None, **kwds): + self.__type__ = tp + + def __getitem__(self, item): + cls = type(self) + if self.__type__ is None: + return cls(typing._type_check(item, + '{} accepts only single type.'.format(cls.__name__[1:])), + _root=True) + raise TypeError('{} cannot be further subscripted' + .format(cls.__name__[1:])) + + def _eval_type(self, globalns, localns): + new_tp = typing._eval_type(self.__type__, globalns, localns) + if new_tp == self.__type__: + return self + return type(self)(new_tp, _root=True) + + def __repr__(self): + r = super().__repr__() + if self.__type__ is not None: + r += '[{}]'.format(typing._type_repr(self.__type__)) + return r + + def __hash__(self): + return hash((type(self).__name__, self.__type__)) + + def __eq__(self, other): + if not isinstance(other, type(self)): + return NotImplemented + if self.__type__ is not None: + return self.__type__ == other.__type__ + return self is other + + class _Required(_MaybeRequired, _root=True): + """A special typing construct to mark a key of a total=False TypedDict + as required. For example: + + class Movie(TypedDict, total=False): + title: Required[str] + year: int + + m = Movie( + title='The Matrix', # typechecker error if key is omitted + year=1999, + ) + + There is no runtime checking that a required key is actually provided + when instantiating a related TypedDict. + """ + + class _NotRequired(_MaybeRequired, _root=True): + """A special typing construct to mark a key of a TypedDict as + potentially missing. For example: + + class Movie(TypedDict): + title: str + year: NotRequired[int] + + m = Movie( + title='The Matrix', # typechecker error if key is omitted + year=1999, + ) + """ + + Required = _Required(_root=True) + NotRequired = _NotRequired(_root=True) diff --git a/venv/Lib/site-packages/setuptools/_vendor/zipp.py b/venv/Lib/site-packages/setuptools/_vendor/zipp.py new file mode 100644 index 0000000..26b723c --- /dev/null +++ b/venv/Lib/site-packages/setuptools/_vendor/zipp.py @@ -0,0 +1,329 @@ +import io +import posixpath +import zipfile +import itertools +import contextlib +import sys +import pathlib + +if sys.version_info < (3, 7): + from collections import OrderedDict +else: + OrderedDict = dict + + +__all__ = ['Path'] + + +def _parents(path): + """ + Given a path with elements separated by + posixpath.sep, generate all parents of that path. + + >>> list(_parents('b/d')) + ['b'] + >>> list(_parents('/b/d/')) + ['/b'] + >>> list(_parents('b/d/f/')) + ['b/d', 'b'] + >>> list(_parents('b')) + [] + >>> list(_parents('')) + [] + """ + return itertools.islice(_ancestry(path), 1, None) + + +def _ancestry(path): + """ + Given a path with elements separated by + posixpath.sep, generate all elements of that path + + >>> list(_ancestry('b/d')) + ['b/d', 'b'] + >>> list(_ancestry('/b/d/')) + ['/b/d', '/b'] + >>> list(_ancestry('b/d/f/')) + ['b/d/f', 'b/d', 'b'] + >>> list(_ancestry('b')) + ['b'] + >>> list(_ancestry('')) + [] + """ + path = path.rstrip(posixpath.sep) + while path and path != posixpath.sep: + yield path + path, tail = posixpath.split(path) + + +_dedupe = OrderedDict.fromkeys +"""Deduplicate an iterable in original order""" + + +def _difference(minuend, subtrahend): + """ + Return items in minuend not in subtrahend, retaining order + with O(1) lookup. + """ + return itertools.filterfalse(set(subtrahend).__contains__, minuend) + + +class CompleteDirs(zipfile.ZipFile): + """ + A ZipFile subclass that ensures that implied directories + are always included in the namelist. + """ + + @staticmethod + def _implied_dirs(names): + parents = itertools.chain.from_iterable(map(_parents, names)) + as_dirs = (p + posixpath.sep for p in parents) + return _dedupe(_difference(as_dirs, names)) + + def namelist(self): + names = super(CompleteDirs, self).namelist() + return names + list(self._implied_dirs(names)) + + def _name_set(self): + return set(self.namelist()) + + def resolve_dir(self, name): + """ + If the name represents a directory, return that name + as a directory (with the trailing slash). + """ + names = self._name_set() + dirname = name + '/' + dir_match = name not in names and dirname in names + return dirname if dir_match else name + + @classmethod + def make(cls, source): + """ + Given a source (filename or zipfile), return an + appropriate CompleteDirs subclass. + """ + if isinstance(source, CompleteDirs): + return source + + if not isinstance(source, zipfile.ZipFile): + return cls(_pathlib_compat(source)) + + # Only allow for FastLookup when supplied zipfile is read-only + if 'r' not in source.mode: + cls = CompleteDirs + + source.__class__ = cls + return source + + +class FastLookup(CompleteDirs): + """ + ZipFile subclass to ensure implicit + dirs exist and are resolved rapidly. + """ + + def namelist(self): + with contextlib.suppress(AttributeError): + return self.__names + self.__names = super(FastLookup, self).namelist() + return self.__names + + def _name_set(self): + with contextlib.suppress(AttributeError): + return self.__lookup + self.__lookup = super(FastLookup, self)._name_set() + return self.__lookup + + +def _pathlib_compat(path): + """ + For path-like objects, convert to a filename for compatibility + on Python 3.6.1 and earlier. + """ + try: + return path.__fspath__() + except AttributeError: + return str(path) + + +class Path: + """ + A pathlib-compatible interface for zip files. + + Consider a zip file with this structure:: + + . + ├── a.txt + └── b + ├── c.txt + └── d + └── e.txt + + >>> data = io.BytesIO() + >>> zf = zipfile.ZipFile(data, 'w') + >>> zf.writestr('a.txt', 'content of a') + >>> zf.writestr('b/c.txt', 'content of c') + >>> zf.writestr('b/d/e.txt', 'content of e') + >>> zf.filename = 'mem/abcde.zip' + + Path accepts the zipfile object itself or a filename + + >>> root = Path(zf) + + From there, several path operations are available. + + Directory iteration (including the zip file itself): + + >>> a, b = root.iterdir() + >>> a + Path('mem/abcde.zip', 'a.txt') + >>> b + Path('mem/abcde.zip', 'b/') + + name property: + + >>> b.name + 'b' + + join with divide operator: + + >>> c = b / 'c.txt' + >>> c + Path('mem/abcde.zip', 'b/c.txt') + >>> c.name + 'c.txt' + + Read text: + + >>> c.read_text() + 'content of c' + + existence: + + >>> c.exists() + True + >>> (b / 'missing.txt').exists() + False + + Coercion to string: + + >>> import os + >>> str(c).replace(os.sep, posixpath.sep) + 'mem/abcde.zip/b/c.txt' + + At the root, ``name``, ``filename``, and ``parent`` + resolve to the zipfile. Note these attributes are not + valid and will raise a ``ValueError`` if the zipfile + has no filename. + + >>> root.name + 'abcde.zip' + >>> str(root.filename).replace(os.sep, posixpath.sep) + 'mem/abcde.zip' + >>> str(root.parent) + 'mem' + """ + + __repr = "{self.__class__.__name__}({self.root.filename!r}, {self.at!r})" + + def __init__(self, root, at=""): + """ + Construct a Path from a ZipFile or filename. + + Note: When the source is an existing ZipFile object, + its type (__class__) will be mutated to a + specialized type. If the caller wishes to retain the + original type, the caller should either create a + separate ZipFile object or pass a filename. + """ + self.root = FastLookup.make(root) + self.at = at + + def open(self, mode='r', *args, pwd=None, **kwargs): + """ + Open this entry as text or binary following the semantics + of ``pathlib.Path.open()`` by passing arguments through + to io.TextIOWrapper(). + """ + if self.is_dir(): + raise IsADirectoryError(self) + zip_mode = mode[0] + if not self.exists() and zip_mode == 'r': + raise FileNotFoundError(self) + stream = self.root.open(self.at, zip_mode, pwd=pwd) + if 'b' in mode: + if args or kwargs: + raise ValueError("encoding args invalid for binary operation") + return stream + return io.TextIOWrapper(stream, *args, **kwargs) + + @property + def name(self): + return pathlib.Path(self.at).name or self.filename.name + + @property + def suffix(self): + return pathlib.Path(self.at).suffix or self.filename.suffix + + @property + def suffixes(self): + return pathlib.Path(self.at).suffixes or self.filename.suffixes + + @property + def stem(self): + return pathlib.Path(self.at).stem or self.filename.stem + + @property + def filename(self): + return pathlib.Path(self.root.filename).joinpath(self.at) + + def read_text(self, *args, **kwargs): + with self.open('r', *args, **kwargs) as strm: + return strm.read() + + def read_bytes(self): + with self.open('rb') as strm: + return strm.read() + + def _is_child(self, path): + return posixpath.dirname(path.at.rstrip("/")) == self.at.rstrip("/") + + def _next(self, at): + return self.__class__(self.root, at) + + def is_dir(self): + return not self.at or self.at.endswith("/") + + def is_file(self): + return self.exists() and not self.is_dir() + + def exists(self): + return self.at in self.root._name_set() + + def iterdir(self): + if not self.is_dir(): + raise ValueError("Can't listdir a file") + subs = map(self._next, self.root.namelist()) + return filter(self._is_child, subs) + + def __str__(self): + return posixpath.join(self.root.filename, self.at) + + def __repr__(self): + return self.__repr.format(self=self) + + def joinpath(self, *other): + next = posixpath.join(self.at, *map(_pathlib_compat, other)) + return self._next(self.root.resolve_dir(next)) + + __truediv__ = joinpath + + @property + def parent(self): + if not self.at: + return self.filename.parent + parent_at = posixpath.dirname(self.at.rstrip('/')) + if parent_at: + parent_at += '/' + return self._next(parent_at) diff --git a/venv/Lib/site-packages/setuptools/archive_util.py b/venv/Lib/site-packages/setuptools/archive_util.py new file mode 100644 index 0000000..73b2db7 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/archive_util.py @@ -0,0 +1,205 @@ +"""Utilities for extracting common archive formats""" + +import zipfile +import tarfile +import os +import shutil +import posixpath +import contextlib +from distutils.errors import DistutilsError + +from ._path import ensure_directory + +__all__ = [ + "unpack_archive", "unpack_zipfile", "unpack_tarfile", "default_filter", + "UnrecognizedFormat", "extraction_drivers", "unpack_directory", +] + + +class UnrecognizedFormat(DistutilsError): + """Couldn't recognize the archive type""" + + +def default_filter(src, dst): + """The default progress/filter callback; returns True for all files""" + return dst + + +def unpack_archive( + filename, extract_dir, progress_filter=default_filter, + drivers=None): + """Unpack `filename` to `extract_dir`, or raise ``UnrecognizedFormat`` + + `progress_filter` is a function taking two arguments: a source path + internal to the archive ('/'-separated), and a filesystem path where it + will be extracted. The callback must return the desired extract path + (which may be the same as the one passed in), or else ``None`` to skip + that file or directory. The callback can thus be used to report on the + progress of the extraction, as well as to filter the items extracted or + alter their extraction paths. + + `drivers`, if supplied, must be a non-empty sequence of functions with the + same signature as this function (minus the `drivers` argument), that raise + ``UnrecognizedFormat`` if they do not support extracting the designated + archive type. The `drivers` are tried in sequence until one is found that + does not raise an error, or until all are exhausted (in which case + ``UnrecognizedFormat`` is raised). If you do not supply a sequence of + drivers, the module's ``extraction_drivers`` constant will be used, which + means that ``unpack_zipfile`` and ``unpack_tarfile`` will be tried, in that + order. + """ + for driver in drivers or extraction_drivers: + try: + driver(filename, extract_dir, progress_filter) + except UnrecognizedFormat: + continue + else: + return + else: + raise UnrecognizedFormat( + "Not a recognized archive type: %s" % filename + ) + + +def unpack_directory(filename, extract_dir, progress_filter=default_filter): + """"Unpack" a directory, using the same interface as for archives + + Raises ``UnrecognizedFormat`` if `filename` is not a directory + """ + if not os.path.isdir(filename): + raise UnrecognizedFormat("%s is not a directory" % filename) + + paths = { + filename: ('', extract_dir), + } + for base, dirs, files in os.walk(filename): + src, dst = paths[base] + for d in dirs: + paths[os.path.join(base, d)] = src + d + '/', os.path.join(dst, d) + for f in files: + target = os.path.join(dst, f) + target = progress_filter(src + f, target) + if not target: + # skip non-files + continue + ensure_directory(target) + f = os.path.join(base, f) + shutil.copyfile(f, target) + shutil.copystat(f, target) + + +def unpack_zipfile(filename, extract_dir, progress_filter=default_filter): + """Unpack zip `filename` to `extract_dir` + + Raises ``UnrecognizedFormat`` if `filename` is not a zipfile (as determined + by ``zipfile.is_zipfile()``). See ``unpack_archive()`` for an explanation + of the `progress_filter` argument. + """ + + if not zipfile.is_zipfile(filename): + raise UnrecognizedFormat("%s is not a zip file" % (filename,)) + + with zipfile.ZipFile(filename) as z: + for info in z.infolist(): + name = info.filename + + # don't extract absolute paths or ones with .. in them + if name.startswith('/') or '..' in name.split('/'): + continue + + target = os.path.join(extract_dir, *name.split('/')) + target = progress_filter(name, target) + if not target: + continue + if name.endswith('/'): + # directory + ensure_directory(target) + else: + # file + ensure_directory(target) + data = z.read(info.filename) + with open(target, 'wb') as f: + f.write(data) + unix_attributes = info.external_attr >> 16 + if unix_attributes: + os.chmod(target, unix_attributes) + + +def _resolve_tar_file_or_dir(tar_obj, tar_member_obj): + """Resolve any links and extract link targets as normal files.""" + while tar_member_obj is not None and ( + tar_member_obj.islnk() or tar_member_obj.issym()): + linkpath = tar_member_obj.linkname + if tar_member_obj.issym(): + base = posixpath.dirname(tar_member_obj.name) + linkpath = posixpath.join(base, linkpath) + linkpath = posixpath.normpath(linkpath) + tar_member_obj = tar_obj._getmember(linkpath) + + is_file_or_dir = ( + tar_member_obj is not None and + (tar_member_obj.isfile() or tar_member_obj.isdir()) + ) + if is_file_or_dir: + return tar_member_obj + + raise LookupError('Got unknown file type') + + +def _iter_open_tar(tar_obj, extract_dir, progress_filter): + """Emit member-destination pairs from a tar archive.""" + # don't do any chowning! + tar_obj.chown = lambda *args: None + + with contextlib.closing(tar_obj): + for member in tar_obj: + name = member.name + # don't extract absolute paths or ones with .. in them + if name.startswith('/') or '..' in name.split('/'): + continue + + prelim_dst = os.path.join(extract_dir, *name.split('/')) + + try: + member = _resolve_tar_file_or_dir(tar_obj, member) + except LookupError: + continue + + final_dst = progress_filter(name, prelim_dst) + if not final_dst: + continue + + if final_dst.endswith(os.sep): + final_dst = final_dst[:-1] + + yield member, final_dst + + +def unpack_tarfile(filename, extract_dir, progress_filter=default_filter): + """Unpack tar/tar.gz/tar.bz2 `filename` to `extract_dir` + + Raises ``UnrecognizedFormat`` if `filename` is not a tarfile (as determined + by ``tarfile.open()``). See ``unpack_archive()`` for an explanation + of the `progress_filter` argument. + """ + try: + tarobj = tarfile.open(filename) + except tarfile.TarError as e: + raise UnrecognizedFormat( + "%s is not a compressed or uncompressed tar file" % (filename,) + ) from e + + for member, final_dst in _iter_open_tar( + tarobj, extract_dir, progress_filter, + ): + try: + # XXX Ugh + tarobj._extract_member(member, final_dst) + except tarfile.ExtractError: + # chown/chmod/mkfifo/mknode/makedev failed + pass + + return True + + +extraction_drivers = unpack_directory, unpack_zipfile, unpack_tarfile diff --git a/venv/Lib/site-packages/setuptools/build_meta.py b/venv/Lib/site-packages/setuptools/build_meta.py new file mode 100644 index 0000000..5dc65e2 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/build_meta.py @@ -0,0 +1,304 @@ +"""A PEP 517 interface to setuptools + +Previously, when a user or a command line tool (let's call it a "frontend") +needed to make a request of setuptools to take a certain action, for +example, generating a list of installation requirements, the frontend would +would call "setup.py egg_info" or "setup.py bdist_wheel" on the command line. + +PEP 517 defines a different method of interfacing with setuptools. Rather +than calling "setup.py" directly, the frontend should: + + 1. Set the current directory to the directory with a setup.py file + 2. Import this module into a safe python interpreter (one in which + setuptools can potentially set global variables or crash hard). + 3. Call one of the functions defined in PEP 517. + +What each function does is defined in PEP 517. However, here is a "casual" +definition of the functions (this definition should not be relied on for +bug reports or API stability): + + - `build_wheel`: build a wheel in the folder and return the basename + - `get_requires_for_build_wheel`: get the `setup_requires` to build + - `prepare_metadata_for_build_wheel`: get the `install_requires` + - `build_sdist`: build an sdist in the folder and return the basename + - `get_requires_for_build_sdist`: get the `setup_requires` to build + +Again, this is not a formal definition! Just a "taste" of the module. +""" + +import io +import os +import sys +import tokenize +import shutil +import contextlib +import tempfile +import warnings + +import setuptools +import distutils +from ._reqs import parse_strings +from .extern.more_itertools import always_iterable + + +__all__ = ['get_requires_for_build_sdist', + 'get_requires_for_build_wheel', + 'prepare_metadata_for_build_wheel', + 'build_wheel', + 'build_sdist', + '__legacy__', + 'SetupRequirementsError'] + + +class SetupRequirementsError(BaseException): + def __init__(self, specifiers): + self.specifiers = specifiers + + +class Distribution(setuptools.dist.Distribution): + def fetch_build_eggs(self, specifiers): + specifier_list = list(parse_strings(specifiers)) + + raise SetupRequirementsError(specifier_list) + + @classmethod + @contextlib.contextmanager + def patch(cls): + """ + Replace + distutils.dist.Distribution with this class + for the duration of this context. + """ + orig = distutils.core.Distribution + distutils.core.Distribution = cls + try: + yield + finally: + distutils.core.Distribution = orig + + +@contextlib.contextmanager +def no_install_setup_requires(): + """Temporarily disable installing setup_requires + + Under PEP 517, the backend reports build dependencies to the frontend, + and the frontend is responsible for ensuring they're installed. + So setuptools (acting as a backend) should not try to install them. + """ + orig = setuptools._install_setup_requires + setuptools._install_setup_requires = lambda attrs: None + try: + yield + finally: + setuptools._install_setup_requires = orig + + +def _get_immediate_subdirectories(a_dir): + return [name for name in os.listdir(a_dir) + if os.path.isdir(os.path.join(a_dir, name))] + + +def _file_with_extension(directory, extension): + matching = ( + f for f in os.listdir(directory) + if f.endswith(extension) + ) + try: + file, = matching + except ValueError: + raise ValueError( + 'No distribution was found. Ensure that `setup.py` ' + 'is not empty and that it calls `setup()`.') + return file + + +def _open_setup_script(setup_script): + if not os.path.exists(setup_script): + # Supply a default setup.py + return io.StringIO(u"from setuptools import setup; setup()") + + return getattr(tokenize, 'open', open)(setup_script) + + +@contextlib.contextmanager +def suppress_known_deprecation(): + with warnings.catch_warnings(): + warnings.filterwarnings('ignore', 'setup.py install is deprecated') + yield + + +class _BuildMetaBackend: + + @staticmethod + def _fix_config(config_settings): + """ + Ensure config settings meet certain expectations. + + >>> fc = _BuildMetaBackend._fix_config + >>> fc(None) + {'--global-option': []} + >>> fc({}) + {'--global-option': []} + >>> fc({'--global-option': 'foo'}) + {'--global-option': ['foo']} + >>> fc({'--global-option': ['foo']}) + {'--global-option': ['foo']} + """ + config_settings = config_settings or {} + config_settings['--global-option'] = list(always_iterable( + config_settings.get('--global-option'))) + return config_settings + + def _get_build_requires(self, config_settings, requirements): + config_settings = self._fix_config(config_settings) + + sys.argv = sys.argv[:1] + ['egg_info'] + \ + config_settings["--global-option"] + try: + with Distribution.patch(): + self.run_setup() + except SetupRequirementsError as e: + requirements += e.specifiers + + return requirements + + def run_setup(self, setup_script='setup.py'): + # Note that we can reuse our build directory between calls + # Correctness comes first, then optimization later + __file__ = setup_script + __name__ = '__main__' + + with _open_setup_script(__file__) as f: + code = f.read().replace(r'\r\n', r'\n') + + exec(compile(code, __file__, 'exec'), locals()) + + def get_requires_for_build_wheel(self, config_settings=None): + return self._get_build_requires( + config_settings, requirements=['wheel']) + + def get_requires_for_build_sdist(self, config_settings=None): + return self._get_build_requires(config_settings, requirements=[]) + + def prepare_metadata_for_build_wheel(self, metadata_directory, + config_settings=None): + sys.argv = sys.argv[:1] + [ + 'dist_info', '--egg-base', metadata_directory] + with no_install_setup_requires(): + self.run_setup() + + dist_info_directory = metadata_directory + while True: + dist_infos = [f for f in os.listdir(dist_info_directory) + if f.endswith('.dist-info')] + + if ( + len(dist_infos) == 0 and + len(_get_immediate_subdirectories(dist_info_directory)) == 1 + ): + + dist_info_directory = os.path.join( + dist_info_directory, os.listdir(dist_info_directory)[0]) + continue + + assert len(dist_infos) == 1 + break + + # PEP 517 requires that the .dist-info directory be placed in the + # metadata_directory. To comply, we MUST copy the directory to the root + if dist_info_directory != metadata_directory: + shutil.move( + os.path.join(dist_info_directory, dist_infos[0]), + metadata_directory) + shutil.rmtree(dist_info_directory, ignore_errors=True) + + return dist_infos[0] + + def _build_with_temp_dir(self, setup_command, result_extension, + result_directory, config_settings): + config_settings = self._fix_config(config_settings) + result_directory = os.path.abspath(result_directory) + + # Build in a temporary directory, then copy to the target. + os.makedirs(result_directory, exist_ok=True) + with tempfile.TemporaryDirectory(dir=result_directory) as tmp_dist_dir: + sys.argv = (sys.argv[:1] + setup_command + + ['--dist-dir', tmp_dist_dir] + + config_settings["--global-option"]) + with no_install_setup_requires(): + self.run_setup() + + result_basename = _file_with_extension( + tmp_dist_dir, result_extension) + result_path = os.path.join(result_directory, result_basename) + if os.path.exists(result_path): + # os.rename will fail overwriting on non-Unix. + os.remove(result_path) + os.rename(os.path.join(tmp_dist_dir, result_basename), result_path) + + return result_basename + + def build_wheel(self, wheel_directory, config_settings=None, + metadata_directory=None): + with suppress_known_deprecation(): + return self._build_with_temp_dir(['bdist_wheel'], '.whl', + wheel_directory, config_settings) + + def build_sdist(self, sdist_directory, config_settings=None): + return self._build_with_temp_dir(['sdist', '--formats', 'gztar'], + '.tar.gz', sdist_directory, + config_settings) + + +class _BuildMetaLegacyBackend(_BuildMetaBackend): + """Compatibility backend for setuptools + + This is a version of setuptools.build_meta that endeavors + to maintain backwards + compatibility with pre-PEP 517 modes of invocation. It + exists as a temporary + bridge between the old packaging mechanism and the new + packaging mechanism, + and will eventually be removed. + """ + def run_setup(self, setup_script='setup.py'): + # In order to maintain compatibility with scripts assuming that + # the setup.py script is in a directory on the PYTHONPATH, inject + # '' into sys.path. (pypa/setuptools#1642) + sys_path = list(sys.path) # Save the original path + + script_dir = os.path.dirname(os.path.abspath(setup_script)) + if script_dir not in sys.path: + sys.path.insert(0, script_dir) + + # Some setup.py scripts (e.g. in pygame and numpy) use sys.argv[0] to + # get the directory of the source code. They expect it to refer to the + # setup.py script. + sys_argv_0 = sys.argv[0] + sys.argv[0] = setup_script + + try: + super(_BuildMetaLegacyBackend, + self).run_setup(setup_script=setup_script) + finally: + # While PEP 517 frontends should be calling each hook in a fresh + # subprocess according to the standard (and thus it should not be + # strictly necessary to restore the old sys.path), we'll restore + # the original path so that the path manipulation does not persist + # within the hook after run_setup is called. + sys.path[:] = sys_path + sys.argv[0] = sys_argv_0 + + +# The primary backend +_BACKEND = _BuildMetaBackend() + +get_requires_for_build_wheel = _BACKEND.get_requires_for_build_wheel +get_requires_for_build_sdist = _BACKEND.get_requires_for_build_sdist +prepare_metadata_for_build_wheel = _BACKEND.prepare_metadata_for_build_wheel +build_wheel = _BACKEND.build_wheel +build_sdist = _BACKEND.build_sdist + + +# The legacy backend +__legacy__ = _BuildMetaLegacyBackend() diff --git a/venv/Lib/site-packages/setuptools/cli-32.exe b/venv/Lib/site-packages/setuptools/cli-32.exe new file mode 100644 index 0000000000000000000000000000000000000000..b1487b7819e7286577a043c7726fbe0ca1543083 GIT binary patch literal 65536 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

    @|$jDp4t7maBT@by!vG1&J_?=DS4W3Hu6w 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[c}iI#RErv3nvcIClH@!{vM)zJ_weD zu_-L8NU*GlC{d0L!!VW10^+~>qmNB~Y8H+F}!P8_d(PpvjzMJQmr z)FkX;2B~<|3JfJeWv@IXo~nTtp$}Gjie> zs8UDG*kid(%i5QCBp~MA;#I186PI-nZ&k7!k8BiLJSuR>h7ArSYHD~B0I z=T6L{zqglekt0JjG5z&|GWb4?+B5+{p^fgTufl_KesA{@I&g7rNq==^SGc5GcM%$N zDBG2)qExz*Z;jGN_-iD-y8i2BCq)p}2lKcspLg>w-;qwg(()HXrZa3jd!}spuwBVX zwmX!iwU?#7uoQnunw|OlU~+c z^L5Ak3zWhaA4B^FhMMboO0k*O2GL)lD9_<$5b>czbCvKcSt+u*gA*=%dH>Q-Bc11h zzO7jbXN)&5mBf=w2anK6P$YcJZQoWa2#E!v{hFKxxm7Fc)Fc9iC35{|Lp7bIDjrhC zgMiGf4r2yquH{U7WdMio;XS4Y%Ry{q7#kv#gZ07i`7eo#MMh_o68E*Fd_#nrri^4b zX+slbsv>+8pmck%oLDUL()8NRJ#Z z8DReF_eq2zsjEXGs)yS{k}ykS1B!ZrY0f6O65^lslJv3g&wfpDg-&EwF8wrc=hSwm zPlV&n%%yE_@onOwK?)`GNJ6MQ0drMuBYWCH5dkD)uErh@*k}#GcFl<-;;TN+5vb|b zctkCv;*zL7f)A;QuO%(81r0)&aUz4EQu;kA!k@7i8RZ)koMaWW`5cC6n@{w!!J$5d zx}l)4VP4xL=BKi&c^{n_Qi`q@G{vimblcVR53b#*X$FUOQFm!A8JKahNSiBdY+x3bJZfD8n{--FLUM4+Mx@{vM_ep zkk)U=K8R(rhU(X_faI*ZO}cn`5t*O}lx^j8|0rt-)o=Axn^DGcQTi!#7hxLTq?|HQ zB;T6(nrsCeYK0_o%)IO+CP{n#+|;w1ZmvD2c-J{i88bp63RjyKOE!B!D3U{RCs*Zh z&^%65VM(J34230U4bHS}M@SYS9TEK}c%)2<$h1|T;##zRtjRt@#1T%J=kAhOiw+Z% z7DpyWVK@6%9K^uVD9LDKj)dR^aZK6$@Lt)l;sj@`QSzBm{TlLG{JKM_^60Zr2w~nr zr>P-BaV8OjjWm?hQ3$ZCx+lyD%q`~4iNF9xWKi$t&pzBhwN9Dq-o^v9@=abLR#|

    KZqkLal4YCRR9VNhIM|rBqmzzcImvcx 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/cli-64.exe b/venv/Lib/site-packages/setuptools/cli-64.exe new file mode 100644 index 0000000000000000000000000000000000000000..675e6bf3743f3d3011c238657e7128ee9960ef7f GIT binary patch literal 74752 zcmeFad3;nw);Hdr?j}u==7yyqfJg%kqCtqpC80t4LPu^(N8=-ER75n&prFR&UceDB z@phavWskhi=#1m|%%F}lj?UsZGsvQt5JTodne9_xygp zKi+>{KBRBmT2Gxib?VePr|Op8w9@9V*=$byS(eSV22c7I6uw4&mnWJ z$MZk#s+do8oC$GRiOqJ$BTifH-`O?kw07GVTXsfYo9!LM+%035U*jm2#J3_n{DpIsylAeZ?oA}or@^cX*&;p@8Yl5zaYqC zqReLd_+ljZfRn*^ItAvsb0S~E#7db_^bvivWg&Uk_wpg@|NZxW0s~rXw%@JA7W#9w znC{QhVoUu#b(VUadc9_T;ft^jG;@np*brtX*3qDS^H;5NPdwDuuEig)w2D?9%(2-D zI|{#yRD9iR8?D95?Ge^qXDz=|8CgU9QI*v>6KammHk?*-@|>EZqYYnO$MQiT*8IwB zjcsG6_)Vxma~#U=Xm-rjtfpi}VFwC1Cur7YyoLi`)=#&Vu0f#zy$X$$g*3L%uW3y8 zmuYONzr5Kox_P?Yrm@-nV3;*)<|dyyN4-Uz-LyUZkNTT;gI4>+ToAv;T(1p4{=!XK zEb1>4F$Xl(sI2a*v18FK`oNW%)lhSElHqI)TC-QUqg#xxw0P7X1TG@+NBu#}xJW$Y z4{GsQ{sQzzi-r6?etCazhNb=jn^N~z-~hqkY$f^}g8yCNU9xZn3QMGGaTEl`MFX9C zG^k^_1rR8RtYQ(Z&ZG}fxIF8)$B1zR-ss6<%dcHRYkqOqs_HH5(0O@!H7 z(-{Bn=}Th=WLG2XbB!I3m$?Ojp&R@&FvUVkV@K53GMlm?8)Q{d_^}qtLZgkr!HyQY z(XX%piOS;*!3)0(v9>){ouv_)(%i?U zS|zq{MF|F?IUKvFnF@^q@cbE|2r&0wnTB_zh%nk~0w9tZmW7^zXwRVMAE05(%JFqu zi~-E^@F=^jZj0_N+-rF+c@HZ$%}o5%#{9y) zvDf^>h&rSL^*gD7~pzOHv=pn zZpOX|VMKkAilc(3scUTLaN!oqd+b0OM&e5aa-zmVIg^N-3ba7uqC91!t)^(Ao-0Z= zBRe=&VB_K>f*4`+Pn0a&i?Yl$8QqaZV>2w}Ro8`hpBI~vsjPOLi(vhXzC8J=&Bped zU6wJL|AUwqsICB*_!{IcXlEQCj!$@Y{fyvVRn1*ukl8i(qo?7gm{xW32isz5Se(%>1j-a2k4wb|wT)GbP)~3cw z?6fpLj~Sq`9YkM)yDZB*We>-k{xAm5y?nH0Ho2{x^Hypsn|E~r0<*jx=2YhD6NHvl9yo4U5tiyIlU>#Dq@mTY2oce0 zScIx+t*YHbRIT2s&bjqw$p*oU67G{!71sDN2sxTN5)0-oL1Aw=ob$3lFj* ztVs)OQ=VuDG#Tgc$T*v=MF_RTL4A^~749wE!fzjIvze_{!i$bjkvG#thW==gNvR?q zqN9=c9sWvw6oprI%*YEWbx$CY=-}BgsJF|~&ojGDfwn3zlecP(M_rM)Yu~wcoB82L zZNc91uwxJ?*>iE0-InZ+zyt&|243NM1(`ag6+L8(rCNqjEnXsf)~Gdhxy%nxd<%-_ zG<2v%HTr0NH-P%#9@h8)$xbV9#5j)t>pPHUVJX`#82c>$e2P5Fi^z73?Zb3>4H-a4 zyZAo{B_wtgf!oXxBcR1yzjoPeO~Gr4i!#^3fZeu!5V{O<&s;;BtE4N?q(qtks-WJO zD~v3>0nlkN*NA*{4_W;X4Io~{Mogf@=VYQSm6*9^7%EIIDcl0W%13KjY>-_uHx_7S zBM3Ta*CEci_MQineL{VRdq*QvNnCS;!G7c3CFAYj=nW|}g_(0Bp(?@#*~8{BOV7sd zDcx0Cx7X;?l5q+PV%P#V+gK1b6L#Y@;%u9I)LB}a`E+cYYNlR9TO8fRcYr1|=D8ki zBiH!EGQ4k>xDX4mXDLK0EpVV}G7x2RQ+WU4iC8DJH7~s={+*}g@6kFx*BXyG1VJP& zk4O6F@~-nB`>b1#rzEqq_{;*!TY-&T3J_Vpd32D*-d(1cjk$bl@7z}+_r*QACEP&D zVFxw8wdzuUVu0Idf!4+O%DVgW6fJ*iFL*i=X9BYTeFhw6BWnKWO#ufj;l&UybT5BxG@`(Cv-v9sK`sc!KoDR) z67}ijJN2A5PZ=2nO;9zBVYAC!b*-{`Z+NXe^)IaaZ4aV@RcC9R2h0yL^*)jOMlF^L z;kuNyhRwFi!;OhPMzMU!#EV1kKX2Z=l`FMaf1;|ewZ-_h6!2u#_t&h(u+?gGG$|v4 zHp+zm;o76Nvuw8N0?Hq|1`@?JxhMxg>6-ocYeRWFIR4u4*JbQaJ`RvWfLCeik3W>a zk1T?~etHvy@Z|K;PCs47?)I7-zb!EfMA;h!J^hcc1Etvwx*tQ>u`yF0zXD5Ky|cd( z{fLlbZ3N_cCQ^(~lR075)TG6n=-@`+HY03uch$J?TI-bfw>;v2tg<_7eq)su?g_88 zNnF;J*6q=^gv|!G5@o0}RXt%pRsE9a$MydHx{-RlOKar0BA0%9D(ZTf#|5d^vE5aSOvMb88FJ;TQa6RBDfP#(RV&1fQVf4>e zHMI8t#jeT2Ao(bv`ZIKiLhh=*sWGP#4Q@o)t1`u?Cy!7I+f(zogymtrMc5YA{HROq zusI`ak3LXkL3e3InX_|$#IXlFE;43MxT5JwHYitP({q{T)*Lh49jZgobClJp!)$BU zo+LyUZVj_7g1QsGhU6pWQYllhRv}>zkD+^~3H)*$Bbgb}+xSQ<;`f1gBW$Av`I&Dx z2crSD+_YWn2O`LmcO5N%w9$t&Xnp}X^Y{K2FlZ61txwY6v7?X$3-^|?qikzzmcLR9 z9MiKRfo}{Y64I#&Td&*J2qF z@)G(Q#-?r8cnF+(wfKYfq?__O)cV01?J&R5P~i~$PTG?FQe*<`E(kHnAuAkHCh49j zv-Q4HCK^~TjwGF0d;#q(iv}9Iw7}>3qzEuDHUfz%e^;dVQPET7kr#V6y^GJ1O|z5K z@-b?8hz1C*(E^=S5nw_e6=6G56|6$hMfa1OC*a<}hls*Jie9GWzpoWP?I&C;x{7ue z4C^ZOZaY7W!At@e)TQMgqFkb)@gi4uUE7eWa4*&6RO<)%AqM>~)Wx<+)rww`o> zJrWbP>=VHYSyOTVh-4o>jF+`w;M~ZV}s}Q7n`+ zG&RPDMJy0jI=n$ctPg^WYPMm8-O1k-g6C}7ed>^P%uQw8%8YIn+rwYAfad}1kc|FX zV`J{T&PK~JGLAH9jazaPx16@tH>-JA!1gM24+Cy~_#yxwn+_(hvVr;$8>q2*(!Fc3 znc%%1Z#J#Jd-TDqrWLVuu1EW#5jWp_A!Pxau4)n%il@8v;ewIWi)@}dDO+Fu2duNG z9yLwR?GQC&7+zE4$!MOQhiP#{xi900@{qmv8YuFEmE8NS+f&FOMq5I4=Iml~YKA5&&5f2La2_um!c$45?Br(nf%0OEiAmB;b>LDvByYe@O3UNGn zod#vdJ2d7&`Y9mwTn!o!+ZafF&_omg>WA>urXil+l!bx|{Y7@Re@PZ;6$+q0ON#wk zLE#o2xP(X+!#_8*ljt6N1bW7wWB>yqS_FJ~eR@fxg=XXm`?M8<`eM16ywSLUmf5SY zxx7;AY@|(*@xhhxL4D`derPH4YL9g(i}z^Ej#Z&An4Ga$NEldp!t2s&?;(B282#MF-$QpncdwrWX1*xE1cfb#mJHv`n$^}TKeimt>>$O9V=L0p`Js>;A3_ZF zYL@rZ78&Ve+pOK9^l5FqiUB~1_Ykt7&b4l|k(lVC7a1NslEM%|tIrpTLz?@To5x62 zW)5mDgX+aLHE^ivOX3{`)CwkOPj=EJi2|r)2qZ|%tZbr<3~NuiWTJP;6t9s@nNy!S z8wAS^=y~YrV+iwglf`b|O@J?_h{M1bI=x~WJv=w#!Iz_BXzC`s{|2f23Xx^RB#~um z0UpVIKhyzpY9TeJk3_-qsP0nPm;!<=+@i+IGA!=^#8aQn=&Rt3q^im5y^IG-SQ~pc z#EuGl^1WwcXJ$_QD|9?|C3*trZgD+DF9?O|$3BK&-9e>p7hW;=D@Oo=uP0I%QYoog z>Kc^j?_}ZvO57_FyC~5YVI2emmK}((m|U9qH5fMb|61TwRSy3RWi8G$GLoNC1eB=? z|Ai>NpFc#;Sf=$R8XZpc{!}L5)k&`l@EXDP(-jGD9St3!(H)O9nVyhTQVlW*NU{#2 zaTbwd+;b9?#b2ZSe%w1$MrGl_|AeTOqyx^9h*^s@2(QMt7T3?g!3ZBJc$=HALV}8| zYz_+GX?Y7ixXb^I?z(#s8s5J|CuM-187f zke^M}#ax|7@u0bzlJ|swx2E(aDAZEkmVX3Uulr@*Ks@+-tL0L1vsaEnRG^TY84`i(! zPFW@*!Sb%$EPDTU?7jJWK@ol(s~6vYc`7gQ8=gUxY@U*e>Pt~yLn{Y(zeNgIOeVBW z|3*xNxh_NTNX&IP9vbud@L-<7RORzuqC^)>gSvwT75EnP!ZR_l$sw!@TCgBiYeXjy zy`5V`ePlBseK}+u;#Z_AxD*Q!-p41d7epd-ROOgN^YgS=rH}Mgr_JqB_JF&TjS92- zi%Ro9>rkEZN=X#@Ji-!6-FxT=wEHow75c5+#g{3MKsy4$n3Kb%cSQni%ENy|4mSM+ zh0Wg}Y(D6;DN&LN&467W3jT^2P@u85!;ThfH>Q3)4fpbDwRV}UqWYdTW4vZgok_BR zem3Z48bbWPu+jr%{RDZ3*$&H_k7zd2six$2RJM!HKtIFmiXgkzSz1vF3dI%$@8iRc zeL@GmLogJ}yRQj@aV0Wa5M!Hi1D93bowy7mTiB4C7iJIm3cn2JTg4L>%|f?w+01Vv zfe)%KlijPnL<=0P%FzN{)tPEXiPL9HG6OcfFM1W|(#Ir+Xl#~$33~Q-XhHjgfQM2? zi)!tLk&#-OSoN|1n2Z}R9o}3JW()AF*23(g-qSrTmoD|^3f-X(D--9SMU3?mD&azj z{t8&*P7sJ@Hb5`F-*5u{f&7~71TNGL%sfiH{veLS02y*qn00 zX5_CWLp{H80FW1Ro&Ym8uqaIjT|jP(IfTYEHr)>~FG&j76D`yIRG?+Ln;sA(kt@4) zW*!+7MSC!%;4R!M8O7!zS)WxTTzC&G4N@&e$Q3Ky-Fo(X3?kkVBB1gQWZA$s# z0h+R5^E73{qwaQK!u&u{X%<034`? zm1sQ{9TAw64kXh_@1_H*(t%&0S@WnJ>MI0bzus(i-Jv|T9PB}f)&NYiOI4z@qcXdu zE79FFnq4JIbfSovp+v`uz_t24W>>iq{aC!+qz^H>Zd0OUuQ0nRl;|H(ETK7xCBs;4 zZiZQBqdrMv(|)_I}g z{xD0JjTwO4_*%=~rtLYJ90kk}My_ZV7)fSXt)Zg+I(TR!Wjma|4U8g`U;;X@B)HeC z`$Aa*^09$4%vFWJR1*F8fw|6WnnV6bff~Q&oBEKyGXC{>yC$f?dMO;J;F zq8M+gV-RWz>Y1g=8zo)IAs9bAaz$L9(h7u~C9DLhQsnWJ1~x8phdcKZY;IX`mZ-SO zQNkK9Jj>kb1~InTs`+teN#IC{a`llA7P7fyy204J0i;0HGknXKtw55dvYo26Qw?l= z$c4IfXf2R0j5*tRIKmp@(+bS4;^hw2(NgcwtZm8Nsu2jP@)h~!7;X3NNRQzBu)SyMnAZe{KQaGKo+L}RBKN?ht%cgs__lCP^pSt z`~l!kgTK*}NT4lkCZvDXne3x(psX}0u@CzA7=oaFFoBa=1$J6d!L4}NC={YqBE;Y? z1bIzr^O_MHPgdp^s8aT32s<;MwOeH;3L9!at3jkbA{1zc0Kq)Zpla?G^*|)T#Itr6 zHVEj41-c9fv)BEYb*(M z6ogP>Bt$Ym+A82jT|=|o+NGJBGx+L2dPW!*GO7IpSJ%fyptzc!0^w0noc{uCh{?5?@A+w{NAn0l7FoIei)SZXA`DKTwk=AP>5#r9!VYG4; zbc2@CE1AaRVnt#PX5(xux|3Rg46&Zk3W$}i&JX8;P?6NilL+vr6ak)TMa3tfQbq&` zA!IezLo?$pL0ON^YgO{VX=NUswm?5Sm7?KkI6{1U6 zXW}tDr^j)P(bGLiC4!ble!p{BSa1|4KEONrlvBp?Tdp`-$8m=({dq4M#N zwwp2}Cd;BeT}8`d^b7EtuaCy>`T9Wo7ASRjvIciTNmZ5TBLnutNzz^b-I<9a6f(DG zBtA!g&{0W0<@7U)ezX$yA^JeUvP3iT@c(cTnUNP4=`cve<4dVp=VRRu7X4GmlZnNk zQt0ry_pFuJZ7hLb#av&?rd0dIN)Q=MRiEV@u^OB9b>)Z%#cyvVE5;!-6Jh&H3axOU z#c-22`XEta%$2|tloxop{_4BB5ky`=s@Sl_ZOwRw8qtdiJ+Ify92OK}!{ zCR0oqVj^L)sT^YVbG-{!H8Iam5rI{AssDB*8Wuy1xs0}zDA|xA@%c`zq9E+}ZoLh1 zN^zbN$rIcPE+O$a;Eu#EE<+8X4+Q^62|p^(@51)%6mtzlvg+6rbLAosjx!1Pfok=8 zfU7kXMKwPRIlK=}b@#byGjlbOCEjWYG%bySP)7U{ugOdRL-8uJ)WD(T%Qf>dOJ9KB zQ~I6Q{MzjL9D2AhnOHx|`{X}q@oLe-k&4gA9}L1b*3glq3qFR}?gta-LykcZnQSU# z1$P)jmb-2h_7!~Rd9q}tinT5$DMsmSAj4`2)5f{k9XP)9;Sz>g!8#6U3l5fRjuGb) z#Ad*v9bw><-lt}!yC(Ti^K^HuikWB85^Xkqw+8fMl>|OhLeLw3^$(hQ?HYNmTuCS` z5$fbah$g@<)nbLp>ISnb!=T!N$-c1t8BPS4QXix4ovYSDxd5Ow=(5Hr8QCfHTuah$DnJBk{6a2pj<- z{#XVoA$4$Cf0g$47kU)7&?TRNWcK= zF9Gm)Pv0kLaPbBdf5FBcQ0&CK6Hxp%g@7jzkBuUr_*M;kYi#&`fa3djPx}=Yb_hcL zTm}Ad+Cot8+qAwM{5~+gZeV`?S3*e|7HG`jPn2f~h`&iA8FZ|~5 zK}#<{=1G(pxv(vUgV^D}5IuN?$;c153QCT!5m|VjY5G61S!8tZB_CT$EQo&wenlL%fD|7|`4RY-npcQ{Kj3#v$uKVORP(S@+w@CVasC6jIJI&-ua2GZP@nYg0Sb@i4{S2XTe{y(9U57CknKCer!(_6m zggOD^c-Tl5idqJJj*3sBVylG!5*q+HOr*S`x>4j?8ZP3s*rH)=x&uoUjhXNRX%e{; z8K|Lq?qCcF33-x-KwED6faH1zknBD4LATw2(`>VlTdZac;xw4-sdkW1JO|5OHqRI> zOcm!NI`bn$L+uZNAh3UFlTeP!p#wZc1dp6CAfJjB&Cw7x{hLTiIM@x#Y5Y@*k1*P( zq4WRxA(8BHja{nMb?C#*hun5J;S&4szeFiJ`BL&OG0#EsExB6Yf0q1?P`1m{?(qz&$-Hlq6DngjC3`F}b@s)wZ~F)^I1Ir-q)@t`5z1oBLAXN6D1 zON$L>um~$R355`!hqslooH0oZ15x#(KFL=oTtk+(BiOK~igqM(!?D>XZArLWZR58i z6?Ev?ismiv(|<}&XY~KHLAgcFX|Zylb6R|A7oGWV9MsGyhv10AN%IC)22rCw_Z}js za}M=POyH^rbqick9kBH5rHC3VWd(+un2s#LyxN$d%}ElqK(?=r;(^@_K+AQ%0#P;E$;fBfS>f ziS{XvyhefejrMwbvtu$eIgn~f(Q{R;DYij$qzQ3KF@K3%D>C3pNxHG7n#nff6L=%? zND*9{izev#W2TWwHzDFM0BL|wfgv6oA0jZR0SJ*{)C@)dF0ojd=9LRFP3Ok_6 zpE6M&oyt1C*@1&qa1cwq=bc$JKEtjBniu6ZmjL-MW9zUUvl$-n%?_f#G5o(MiUhAS z#|whd-?58NuY;IMrwe#JbB2f^$lirBz1Xv=?5N7x`IL8wfI|N9A!YSJHM-O>!WfCE zjY%CMud#aKXVc&xb>o<3;@HI41wC|oIzdHeN_7hjXBiQ5ImR?dHej}q?NQfa?F4IR zg&-vOSk?RvG4m&!f#9V*-lHQ_Xmxb4t zk=WvT1d)AdGvTU12W_c*?P_tk1xK1#4rVsp`8GA^-JI#lpJ)=YXzHo~x|B!4A@H2*J5_u$sRc zO7bh?5hsoZPP4z_FDT+t zrJhA8+P)J68kRO}sXH8YJ*TE`?uzIjYLDy=jtqT3O8Zu^aWpr}>gOD!uhXU05#8s0U}stj55bRoI0- z>K7vf-Re8=u_5?q4541ggL(lfhL4B`pjX1h)yMyxMFZT$Qm&j&VI73x*Id&83WX1(B;Qn!{4P^$+08Q3J;tU zupNVnE~X_j_A^nKxy})97|(Xo29HowCfgw0HfqCCI@8CuLYzzOu7vNvt@2DyP@X4+ zeTC@e>BluYmEixZX;ov7j@#zMHWE+>|LB%pDB%W+4}(ZSKU((a(Rsg?`d(A<~1o zAPi=TvtC^|;|1@8o!kX+ERhFlfZTJzzaesLgMA>(Hml^=ZYwT=(is8Ou|4egg4{XG zqpqq%t;Hc6DN#BVT?;EZg}ablc@?|We>{UNLz5Ey3=uRf#qRl$RAjS=yy`4c`4Cs( zx9q^~YPmBuCnr>Vhu^0>5*Il_{&7XK{p0lWi^}c#cx82wvRbnTjxP4*??RoIjsQS4 zS9=8xPl-{&eQUAFKZV0Of=gGh9Isjj1?t~4I{GMBsuit_Xe zif**)6O`5carVI;*u9vHB^QoRSHLd!mg=@sY^h^=VD};*zcHg|sIe=Ib*0qtUTOYY z#(E&G_G{`JL8|-Bubq0H`L##SA;rM3^|Ej4W#87zzO5I1n*%T3>vM4u@=K@al=5mO zF}Zo9CfS%lc!O^#WOeKXNjnh%?O+o3-%Aq!lbE^+g6sBH@76K&)`62~2@wL@dhUdM z7TQgoOR_)vEloN|e;e=y2amvXrxJY(w6N9(GUT)2Z38hIA{=R^mm*$czm(IoRb3;p z+=xwSEC3@Pl;oVwHij5S<~qN~{Bz3OZrUwln8w5lc1nXWJYfuaKYrqCxTryYJl26I zEhc~gudsJK(u#5!N*x@?Z5^(&Fk)~+pbdj$1@+&O3)^&O%rz$o@Ta?Dt{X)lC+3<( zfqkTI!!g8{{sMwH=2`}4kFCn9p_#e!)L2xj$7*D4q%6q~W!BnbGy#?kLADj4p=V92 zkJ^3bb!Ym3wvDwGv4myAU^HD39ZG8_xM)cgZqiiZ1gvPa zgaDxxl`CAWL@KnTsdtIOp7%6jWO`gJm*!#kLkan-xU8K{G2~*)MO9?rwCNJSh$RKb zRD0sY0W!ORJ$fzmy4|cHT-ZskjGidbCxI9h$Ku;Vb}a9`fDG9|l)ZqI?>#`u_Z}eW zy*H5a_7OTy12SaC0nIaj6me$)8M4mPwJd=edtV_W%C zSOIW0Rv#J0%UDbT)x?GoXOms+U@?)vZp_AGg7eYcE;J)Z5iRTG3DMI2w9NAdlz``b zTIT7;w}|v78-S=}{#vp1K82aRQj0T+gTg6^uJY^AEV!o3@Nc5?wA3wsVq(! z#9hxn2Vi2gs{m7rdKQ4TwbT+rrBHJ%8A+x$*LKnac&XnlG83bgd?{aaiJ6jh+fv-h zi+;!+WsCIK`UaGMVw%i)t|Nkfn<9z{Wbj-tpOv!20h%2o$ced--roqAEpHp>j(PT? z0@h`Dhy9xHC=T0dam~Jt`~kSi1wv`c6f(~rsV%nK@^+vkrW#@gL*DxqBaeF_D9)Ve zhL$*)$)8RL0SkiAyCQFoHa;aU`uP2Fut*;Q9ZfF3e@Cw&67xcME_VyY#3)&qtZtyB zDX1TMS53Z6lyBwo%_rZ4j={wT$hS(F=9F(sTVxb*^BLCcp=(L#Khd+UGD`ml}u&BsE3CSwb!>H$z z66grjURq$PAB&Mb3>B?^liKdm`d;!bb0?H5Y++h}Jbe*x)X@mXIKEM&jYeAX!$Pa05w7~N z2i+Zwxk{8eN=N+64^F`$JT@~Ab_%4KZC{(M8L(9RNjR2I;)^$6l%+E|M8Lb`+gx%) z&xV-$?*YQdA;h2(Y^33kPF4{mN_!CoBE2>@e?cxZqqrEv!KVAI*1*?rI$u6C1P`p8 z{K8ShN0K*~TYP{ZaXDzkJZ0%)%u}auPJr#ypyrQz2Vp-%cTfn&-z{(x$k~|81c5GW zK|fWuPajgam+i!6JA=oHiO{+%CHgg}7n3~~N{fPedvfsW01NXIr#O+7ZRW4~sOi8- zrEW8FDyxx=m>za|3!%Y+rj4vXr}=}!d=LSZ`c%5!3}*x{es2$|!1W)vYAN8>v*|jM zhFtUbkgCJ@QOvi{;#%x5Y`l63%^o=Pl1wh6<{}DA%wtZCV`GP;+mKXikJU9bj$sJ&78)VR?M*qyTI3Kaj0B9Hc`s=V)f zC}8}Zs5nyezA8G2qm5j@=tp3kgsK6{d=x>S1h0Z&?+3f(q^uRtH&eD!N5j=D)a>Rz z|FP_Ezb~-x>2C-Nxjs0QfDxW3!W<}Bi=7DA(fa>Ixa=a%b)oPZnV?l1gcTsnBJaET zSoA5(X1(v0_$4Ki2DeYtVtH=_7E@Ba5a<`C1o}BbE`tmpN0-i7VZikvsqx1v2781# zb=4*eHUxeeXa0NeMrlKN3L%mb(z1;>3>&{PkAEkOE3II&d^sspVy<&O1q3ly9z7ta zxZ*G>_M!6?JH*s<>4se$i94pW*KV_2R2vFT4&3}OJJj>OxvwFc58v%RsAW? z8-N_DPAE%;L3D%8^Ln2ac&F+LN_&oa6=>3nwMHD|h@aI3r7Hg|)bQxo3;;ss@E;Se zNS*2CrcCmSr1z;h?nXCK8l|9|t+d0UDcf^vAIW4~@BuQ4cJ9ZGQUb>UKa!=!NBrt} zfFGZ_5|1A~XW1hOomTEXS#JLS+j2v8VM_#U9T1q!Uxax9j1l%k5Zl*wBYC>q#TwVj zgLiJ-K__-Av?;h{1YWttbl%R$StrlgU6Y3!=#DgPk5s5r;7=66i3LX^l*_?EaGNgg z1D&ibuLO#{v)MH{kiM(3nCf{6}i_7H17+g-{$4GPq&2G`1)}AEJ z(qTrX#slqup+Grq@h34uK?O0|)zV;XB-vW-fqM%GJ}BhaQGPq{M+$YKS?JAH5Z`3= ztI$rQ!qr!ZReOpj>jTNn+uWF|HMTi%T#;xrK~deW)lTHXjXrONaV1l9I;x4VY3@?0 z^Afz^x(JuyiNtPlLz{adK_?{;WjBOR+Yr&{OD|C8V*j8AyV7YMbt`pTz~MD^Aj(sX zU)8a-lx+yPu zWn?vST19|^oyS;WYcw2WIP1xjBwUd9*E3S^>Cf81m_lkR%;>OiZ zeymsABNR8Fb}~3#gOMfMC7Fr+f*=ql0&oT{Cg6frh>(Nx)iHsH#79_D!H~qr(SA)-bbHc9<%GW@>Q_WNwtkONT*eKo5Wd(;x|I&nIcwPHrHCkPkXI)QML@s`}l1*;yJ;e9EoPjWV7Mk z&GM@c6T9bN=5`|!Cc_T2R$BL^k)_5<9sGeNC_Ui1Oe8ir)n(fNp0J}@-gzr%gRmbP0AF(0)FCuGvc+t$ykn3Ab`%25`sCddqD?5^>jhG$lt);oS0`Wc1m<=R?n2XqaIa<;K8`wp|(hzqRls#(A6J_U5Yv=F}bk z1~v^Bze)J?k9ZZF2pVOG8pDZBw;*xKR9uJv8`U;`jI`5n_-U zu%8GVr|ex9qXz0F*ujXq5XQBo`khqzHI%LiOpRCC_32v0SHk?K!I#cPMPr#%rYb_# zcgTIMJR|={#KTYCLUyyo4G$j8u^+V?&!Q!3J6c5}Gcb)cbL`i61!;zX;6MQO9WGlIT`r1pF8J;UKZSrf4*( z!96Y6-ytjl%YYRL}!S+cQ1nKX^EG5#vl~g40sk5QFO7ElK=GpAJY9G=q?*uHN zps+gR)?!l^fkR<>5N2(LgIw8R;nu{d9CE@SEr`?+yiP)X1y0;(YXK?!8>s~jSI^ce zu))xvHmtq|heF{$w5LiVbg_)GK^WQ?>pCwT1*8$EL2w>{K!24WZbG zmk<`N>4b%{wCjj)OzyTho#9&>WS;xcWw-^xD^88;ew;7dZd_=2e-V4eVC%&sL$XlKkbiNbUYbse(6L}GX?@6Fxi#j*nzPvGx34pfYR&fakf zfpd(`bl@v;R4k&O0xkczwg)R#Q{moF{AxR{z(6c6D7%A>g`7guS_M}FUqH7Et}*9L zLKikAoAe8Ms-SYB0$BSO!YhT?w&mT3vT9(Hkxiz$u`oS{*|!)c_zP2|a9pbn?9}_B z_ex!a2FhD2;>FG=IvEk6A|JT6)qtnbm3p@4H(`5R(N1;l5%#_=07D8_R9u7#5;l~i z%eZhwBN*C_v#Bkloh2#TS_dlbIFx(KFBpF4%!QM9mvTbDY4@s&y_(`F6P=y znm5dmG2~iNAbo;}>{{WTLpPj)Vn2kyD3%r>QwzG6`yb}&{1-~YYofrWy>a2QhtB^s z*evXaP-1mLnsc=wIk|{bUImu73Dppk2)>LUR>5%LLCbqlukcFBg4_@kWa45(knem^ z1akTsLMDAGA~I&bwx%%ETqJNPqJ;KGVk7QGYvIl}5t>h6p;(Y6tXP%BmIOaN_b0)z zWxo^btFWOIDtV#`x&UfC|K(LETf2$UX!)fwint$9AQ4Kvyb$u`hFcnG5ly;Nc~@Wi zEtnk5FBRS}fU(yBDOnwlK=CS8Ye)-1Mo9Zb@MHfVng+>|2U$wrDLlr;+G^515wIm; zaMFHa!kGabI;|e)+h6|wT$993&u=gM(+z3|v_D}Px9Q5fl`CjQ;0mc*U&u6$gx93+ zpX#~W3RW*%EC?-`JA$hfJ8>b^p75AAbq>>47s_3O)eQGHifgEf5uTI^k3x8ejLyO} zRBOQq?NGMi_mucODSl6g-{a!JAJbMDb9_wqEDOLyW?UDHw5 z;wk)Plo9@q-v@T{cAQkC%9N;vuJx`^9H*@B1HWSOFD2%m%J>=fc|@RTZFk}wib$!< zV}BM}b(PI@N+%lN1bS21Q&kuda0nPTy^A#%>*_-g=r`+wi)A^bP9ZSR=6}LG^mEI5 z$8uU`eyY@UQX}8TPvk}5XBT?$BOUyBTXzS4awgn#iw-CNn;Dv-`~#_wD{3;wKCm0z zm9#=|N{1^V5c6o;;-zB02c?FllpF<}6+^p&H{8bkHN@w&;P5v7I?P8>%{NI*LeC&% z5`&8MW*M;!u??J1?8-(0#4AXxdyWX1&y#$Kp90j<>6stt4$>MmfWL%X{Qd4oDbPZV zowj3xfe9M#4L6)rj}nBqwr;Dqi!XUMq*EL*I2&Y~oUNJ1+7?eoPws>EL@pV12Q}i( zM1{EZ(DH8Xf%(2-*A2*rD<=W-2nln(W*%=_L{@d4P4Hdz-@wO5ArVrf<*i=|L86s! z*-9ryl5cZ&I^jN<@UlptZm&P1PX*+%j9wikA^QT%l=uv|VIK(x8mhO^ zxX(B;Ld%rEw-hILA%{4=F@{eTV9Y)pjKM@4WdI|)C3%H7IWd{XFg<}ed@DmakD%Gc zTUs#5TR9(3yPpSKIG&M&JHyQJ1alU@3)GH_b;jGwiaZ;gUXv@P5c32q(49p5!hQt0 zIDpb161WdM(E!DRpFfM%Q`!$f_dQI3zY3chYe|j+U_rf)d0U<>na7tuFOO8N0e+BGORrKMmQjjnpW7XDHx8PzJE75l-~yPbM!9=NjFpWf_ zU=hI*z((qc&-x%AXmcVT1~^9*2|M8TMpK}%FQBFE=|52MPQBe?q%woDmf<77Ab!egg%_X~D?rP>ivU{>kH?!;bLkK`YWvg`p&^m_i2oM( z5rX=Vf3|Agfg}QRb}~%YD{T{f(=UPpqn6(kcHq+wuvqYfEF38n5+;_Ya@xhs3U=Fm>xW_@jPZ)(o&+@*uL}HY_dccmW`6nDp{lVge{)qA@ zZF2?UZ~{q*{*79rRZDXFVEsZm_wV`hRuB(W8;X};JCM`ZUA^UIp>0uk{eM2DSJ<{XPhY zIM};c_Mm#)3Me|P%~P_B?E1kf&RfxcI8Zl2z(BC}s5Q`LtJwD{v9PkMI2j~0M~Z(oe@*U~j;`R!T-9a9K2E02=Nmu+50GbxSM ztH99`(&gcVLH$mwLMCDlN*!c-*|X8;nJD#ReY*hn)PUGGXAlV(%DmWM)og}mDE&2x zzj-lO>+o88^b~b-^AC4(RO|nso7({=O_D1C`j2+?T}U!#boFxT>PEzi(Ygvlu8Kp* zGAiLnEuOtEQ;{-; zw26qdJ-y754hvVf(&w-$4v-W5S^UFB;L(Z|@wEt~oJ6on5pkAT1kL_S{@op zrT(vkn5hqMBE&o^5OYX_gONbYSQF9aM?lQMa@@J`EfA9@5Hprv(_NWdT6&>m-Ww7n zKZQ5KhkiQmh@u@K_{-?|h?2JsmD%!j&q0W@EAzzZO>`ZpFRt zi?i|3q-nsw2q*c>Z^LIMKwVn?0Z~@&XoG3J25L$}Uq*5^^k9i879gcPd@tuQnhcl- zWhJzgr`sCE-Tenj13Qdd#H`(!gfpa)fvcJ^kKQ z^uqgx|MqoIZ4()g%H(Yy3vk;Xbb8`YVZI2sOOu*%V%c6=PdT@dCHui?Cf# z1M+e>nuM_7*7U!hhNI_j4ipzhuAt>mob*yBZ`LP@<6g<+xYMI^C|bvo0`GxO!njeP z55UJ-ijFCDF0l3xKB|Re%Wm8V10g9oBY}^qhAFF|#)mT${|ELLkSpk(xSd+yNcE>G z+mzo7DfqmS`U!qsgWj%#JZFpLN>GKOAw4X(k@yH!NdYgmjwkJluGZpu{wa-}LS58~ zB3mi#X=NAfraooO`7LO~7pkAwT`$C(l+)arGPIa@5>ZTz?~$8h11~62Yh@fYVVB$oZcbI z!|IfVS70Fpz$&a=r=>lHi0#4ada>!bINSo!D0WMk7BkAV*s{6U72UfEG*h@)i7l3I+BVSHp$sHi)JrY=<}-D8HO1 z*rVl*+zTECO>PN$I}|(rl?~A34!68#-$To+_c^>mXCG2R?}TFBC-4?wx8Ul6(#lX^ z*Yb;1wgn$3QS)~Mi;DEDuw!#zmvI>G<|=E88=(Pxx5E<4`40|4iNBC%l0-qU~xX(Pq<~lq7izW(gV#H~b;VDhfQhXTT zL$~U9+ww*MX{4en6o5P56x5-uhZUIqDe8uQ!%C^XZgb*(yqjsyKdmj?*+~Oj6`2{2 zT%L>Bjc*~vRRw1w7Q-ro!EbBlH_b*Z*n{HyVi4vdCHe_wNK58+Y|oOpJnt(SIpG!t zOEKJ^am=1FHPAEyVj`?0SJ=h?Zb<5_0IlVHZz0LIfkq`d6FJ#+HmozyX+f>XO5G(i z*Kv&d4P>J8v=!}Ypk0ZM5_MijmoR>qRUKe;HNb=#fb4@CkZj2D7_{Uzl*cw=yv9nF z$a-)aX-ZnU5A`JuibCzn=Smc4ogD%Nup>n-5hytCdnmZ!<`fE`DF_Gl>myqnqWc5+ z&@aiEra?H<#_7xssS{SBaD**eLc>T0q^97# z@L(ifTFG{^UFeAH4X;Bn(#gR=4R@|16(25P4XCg?i{<^`ZX(TA5Wh1N*oIrYk0)|b z9m0|{m){QOs4!^=ZzTT>Nc%*pi!Z{lU{K_N#aTVHteGESk!s=_Zlrb z)WGEOnk3PsaJ23jl~O0!KkI zhYb9Xfgi^2^rhvuANZzACEZ>i&e~%QKA=Kfwi^|&sDBNJAOzXD0Z&?h%LoDFtX+h} zml26zfrju42t%7m^fw-_tME$Kw!DLPAHN#@6A(h?r<}Ft_Hx#)46~bavEIXBn~vau z50Les7jF*|Z!Z9E2Y)v-@OJdc^`B1x9KqY&A?BH|HsvQ&c(9bUhuAS(!X962CqkNv z!2saiID|lg2QH_-oDY7`q`PBNzeVqomssA}KcPg=CwP?{d}k=;*@w4KV5brtC+Sd$ z(xEr-a;1*^*_bgOA4SNd8$wy7v-6fE7`O6L);t`Z(?lcSxq?O<`z&t`T8vb*g#sT* zZlu0W+;;hVZB2^*J_LeTd?WZQT(eS?eQ}!6WOe6K1k3&GdLrvKV!1d*d|cjn+s$&H zCrdk6E;@)aqvMI?!fOGyiBL|4K`CXMh_=b?moNNJB5whJLq&g(J9H%*su`` zp_|yR!$pvO3=v@tOrwV*@G|5|bz~ntHw=yqAVfZu0D&$Rgk^af=K&h9mg6)ncJUWi z6I;V1aML9C;#Xo41ThITOoB2@g52JdASLUjY!Gw1=Ri(pz1ZfTw z5#b~8N%Wg&p5_28zVg;HT%siieQ?C-Bq{I$80X4V+YwQoLTsejgV$L8Z%%mWQZ_1&dmy)LPw)h_sA%xh;f$UTY8NN zmvM~@ICPxoc4lcJQG7zL9iQ6E#7!kMc1=z6{XDcG8bCv^KOzzz)T4jt@A)B^{=S|M zmRp=zbmGSGSy^tdXrC5S+amN?Jr>Gpr`Rs>ojny=V|**`Ei^VVL8p&;*SAuuJx1=& zRsULp3T;ZBGfT+}Wd*g`#u~f>j4yB?l5(sG;yuE0WP1^%sW1MnapPi)tXyg=53k`| zip!%oAH`udGzKZYjpCsnkE8&zS}C@jV!MnN!?m1RfIX5Pib+7qFZ->9OdIrc$fU0SrVU4#N-2()!Ljwe*Uw0G# z!|@4abrB}o(J&1V&R^iWh8Q3qZjfw7#V1+&8*hu@sg}djGu~o+z_S+1@xfTouyhZT z9G}Ks;}c1>NBHd`{DKl9SwQ`)EE**8VqDaLM8{ujmZB0 z-T17doe7=gY{P^R_o|V>h=tw!KVc!J!z(-{19`kg27G+642;?If__gD?#C5XaKVy4dxhrbasqD%fj58>q50_x%}*N8 z$EYf@DgFSU&%M+GD8A5%uT?wg<$<8ce0%^~zR>T=!rIt2hBt}VBWO|NFHx6s4 zdUykULT@D`l??q-^hXPzhMP4Uu+aiori=)Jn8Ts0Tw^MNn5ChtJOjGCMjw3!cn7Up z>GktB>GH!x-;w+ki8x73!g*ILqDxL>H z21b1IXOeJ!O|!GNq2dUlf5=cVfq(FVFjTC=ys$eRB{)(XM9e3q;2zo^aw z@>5O^p+52TCQzaWCw<+iPc|h7;ss}tr~42AC7DfRqJzD-T~zD7eKoarfUkerF9TX~ zY#bol;2U6v`S>?50&p?x(uzks{vxnkN6Rk^ZHMk5kA%BOIf0D}8Rs6wx&}g6jRZkD zCFKZELNz6TV&2*SP~+Y@kzwcmZtq;+qb{z+Kbr?EAz>3pAd%N1QPC)dhc*zB#K-65zP(C#-7PQ7ojBwH;@&SW8qjf%QVvCajqt%$)`Kka+fLiw; zc=fq_t#YfE`nWA+FUfd2UnW%FeKZD6Vz?grBrS3VspjkKb{XT%XIW5}gvM}K%39MI z!S`|YcXYb!??}>e4<;E5g)goy=Tqgyo_NzZ;q7;Q}mrUtz)}YKhQ(&b4S#dx6gePanZG2 zit_Ks3;(e&Y?^1Slw$~=7;%NoL5^1J3!Y@=YMPX1x)0I))uobsGrix{-cIY0TP86O z_jSyYXZf4CY^!(GSh1Ukj$3}q#SU-u%G_f#-^nc%`n-+#q-IvaMF!?u*XGJMEF-W4 zf_*sq|HBog9n*&Bt749Wx9SSM(O3s z%Q13$gyHl)F0~ZNY0O<@BsJ#F6CbDe9PfQRS)i05IhZb?g99ZLha=_%!Qyge`&(iP z!`F+@JmEz;Uhn?T**p+*IjkCYj(1;c9J)}hC!Y_sXGf0l?r#-!Q{&{8ygS8nO2(D3 z%mqW6o<=#pVQ^@t)63O;#|GnapIJC8v@=dlvmL{!7tg+J&R_;_`L4XTS?avN>$?Bz z*e`4{{D`L1xr{Jz!QuRM1Sf~Lh1y~aCsw0StG*JF1y4ZrcC@*i?Yr$tq#+5%fil$Z zl02)nWyb8=GqiL6JF(yBs?Kk|NCLzdG5g;+!tN#G!iX-G@Z_*HD!ZHA+eg-UG?p^u z@_^`e;?*~X2yg9*7`1c&eQlyGd_e1hOwL6;85 zd_dx|v^Iit)`?pLhLOe5ZR+P|$qJinQ}bPv?h7~rgIK}sZrs~ElHPeX`T4_%&lIv@ zK5d&X!zl`Hi43^&e{SuG%YnCU(Lu&46sS3u!{Vw_s}WLscI<7fhD2g%Y2m#!(P14% z(nr%QVc}+qlRJFtIuRCD;nu>!d->tNA9~muSZLWJlLy zsr+@OWmEYwgJ~vAXzFin(01Tf^3s|1a1mYy76q>f9d{G{_!R1lJMKVi@QzTP~6PxgGUm zJUMj^RRC-<;XfFUns-0H<3VeKG`jkN@K@Rt-i4Pbwrlx+@!ugXNk5H zEgh6v2jOPh4>evF-5L3ij8 z&=s+1&rFT*HxxE8R+MiBo1fg)g>lT0FxJS*cp=R>&3v2Sl*-)D6)kcRsE^A{T6ZU? zpXe`RBQ5Cx+}M=vala-jxtsR+xQ~d{mT+7$w-4NCr&I$xTwD}pG?&Xho)A!vL1D3D z#J*B5+mZ>h!o;ZX-ZJS?4)n%%F%0uk>4zQ#PvQ2mJa9E37TKLeG=NzUde? zU2!+A(ACf<*DCfHNmzRz)<&;1I(L)Cp}&vg)uJ#vCKAi#MplIVcZ%-kzMu}yxtepV zlo3jZ&i*3r5x*`JfzIUiB}YLsrwil5Oh{*Bf#=3wgvUN+t__d%?~gEn%-{4)oal{j zGS4iCHN)FCwZ;2lO&^-f?nnj#A1W@CM-rsqXOT#|o5q-z`>|^UFP244p-Gl}k|Ra> zrmU88c9?sA3O~`eWXqJv@Rz*?7V(6_7QpUM{JV6ONKA>l*>I5?vse;oIA)v2iCqHs zHc!8VP)Q=~rj_hPG=6o{hw-wtjY&{W>P6QuE`M5d_*%DdP|tz<;zxj5(aH@IUt_{k zLR)pW^$zrdD4{hfvo$On6o7*~)&`w5Hwwq!wFE4zF?Ni|=x(nz68l&jVlk$(k7p3v z33Xu(eTN4c`)nVZw;_v3XFNuRs6SmTO-Lq6o;kCllXb6H@s?rL(i{rMdvr#kEyRNB z!w>K!FFZ=Fv)DsN*?bKYKw~KUk&nYZSQpQI232~=q-9Pz=QZ=`m{EYB;i=Fy>2Q=* z{p1_F|D9=R_UA_XbMUI|TnokvLVc%E!o83v#r)tdJcN>6d%{?zaD88d3d+>4YhSqL zX#2vuatJB=!nV4@6kFY4rYJJ3MP00Akt1?*Uidjw6KtiMT|IPesz5S)KqQYkSPAWp z?|`9szMQkMX4M0>E7`S%`;tX86^)8N6qMC5>OAywo;x)83q|bcNAg@R z$Mq$yrl%=WVeWndB^{BIwap9plPzN&>t`Uy+*9->kXW$~;TJ_7;vth`$!K4DGtf8b z8WlXbJ8F+;T9e4un>dNM*biV`VlKRHnc4g7W+@ZrnztL%j+lT&6?m;P?W41G-j;pp z!dpbAdB2{FaU!2x=45tHQQ}xWNhlMHH?s(#Pcao{%l>oCVqRM+{Lww)==JV|JO;XWU+&Y! zv%ajS(I4Bwx@qq@wG61te-2pJQplQklPD?sTl{-OuKH{dm@&1RYIfX+>&QzL@qFr< zd?5!$bqV2*WqQ9~)^eWoFXz2;*_98=1S~tWC{+bVBfr@9NDb$kmBx2_N=K0b*9Otc z5QWJYPF6&XeAtiJmefLXjS` zr{;;Q929e@!4pi!(Th9y$J`etMTrcTy^NRH0M-S2)|^KV8gU|RnK$FI`V!J+z$@pN zH-E;U@J}fyP*M>Ky@Y&>H}nKF6D>H4FU|2Az7GgJ<=69vG05P*)E-zjMd$Pj?&jlO zD+w7+62m%Tzo7d=jC=@*Ju`dEjGmheO+DXQy&XQ1X2GF7>=vWOG=f#f5qMybCyNOr z-Q)QfSooR_PulG{QgL~rMzm@RrTG@cgH72d z+Tx6`iWbX6BgZmKrRSMQbsY8Vu}+PY(slQZ+%uM~rvjoC{b*lkV?M<|bUorfU7tQX zcf477gT3LxVc%X1XUnHj@h$dHKQLjv$q}2wrh|cuNEDSOU)n>OF z=F2@FMWM%J2I5$nE+b))rLwcj9LScI{w&L}*Ln!Sy3ZoahJjczKC*@C+7Or1ZbCoW zkfnvi4b^sg=Dzkn3T0`&MbY)J)5D)i<1E_rjoAKt-rUft%Q@1s^4`ow0*isq;Ay^|{2qvM)gL1KKC`dB*U7gto4143aKLQ_Gi@uWLdOT%q zQMV`=6WD%nhtEruvAxKg{s%$D)ij>QDJSYSSb8@`l54~2Oc^3JwK@B5>MAEU;Y3y5 z!`3lqC>{{2G`1{l+3XO?m&ln{ZXdGx$ow!S&Gwi(P=b&amBAeVhgl+Rzn}bQOu@Qo8GD zB~|8X1a4>-rrILlenU^yN2PPwnP zGwp5z2C=xOBs-6iIhzjcS61&GRTt+ekJX>=B#uuK|C0v}Q z`APO}`}?++7s}#}RyhpE zXVrtgRx_l(equef=0i<)jtZy!22S(-PPkrl4!`g<=b_p87qkz2oABe)+Laq3ZZ)cqfMdHu*4f*KCCiuMj!bm%ByO&v&q!MwIUG zpGCuC-9`tDq>>&gkJoHN{QD)X&zHMx30Ep&!S8-bD)84pZ|=*%w|(K?i0tOejff89 z0AILT^mdJYWae6N4`1?fcgTEgOZ$Z+l$ZO|QayP)SHC>BG(iuS?H*ncp_8?k{O75f zETJAH9UrcZmM!xTDQ8EU4FbF9T`seAPY0PN>XK;P)2@*m7^w6kY!#!gJ!ng|r(~-M97pemeLgAEJ2LC2#+3HMDD)+3j&R9`Kw=@mM!1 z2uFN0#s2wW&Qlbj);<`cm1Hl`s=bFqzHBebZ<={4Cn zR9@_%<7(@9n?w@@@AY6Gw)D33_|m20Dm#C-2t5TS+}Gnq(Ysr@`$Y}*@k3Y{`(vBq0H zY4L=MlF`*klf`&evZ6!o-Jc;eo)PvqH9Z(-A%GrodyltrBRvv!vbm1DEi~Gh`E?$7 z{1y2xAoAZL1|v)NSLl+CkdxfQ#)F8=oVnA=1m5sla?~!|$SV9gOvn zu9{JWxgWTiUc&ttEruEMbLNB00fb{IK>#Demd>~wLTEzKgA;94T+4CV+pK`(ahTV2 zBNq>zwuiSMc>bAHntU#@r4j9oa1wBvv$M5e(%9hM&ekr|glj-c&mx#qZw-!ov>%C@ zC!k;@mNl@;MYk;CbZ9&M^;X8_JnWcl4ZdH{e5#1R0S4wp{^rvzCP#9zwm!VMpBR%0 zCY^Eto<_D=x!*cYcA4p+pjMgnvhwYjjbx^UXnj{H7ALXKlb8FAA?oGtXgiYTjl^LB z_RZCj!B%5iLGu`rKFBMp+D<{X-U<=1L#!hN6nTzUC;(E%4P4$XliGtEZ!ah_Mdmn@ zZECGIfNf?L!{LBq{NcXd#wGD;s;g-&$$E1xj91v8&=^v9eVdA0(R^CHq|C8C%r){aHgQt1?^vS3opUS$l29ru!!1B;QO$J8tf_nq7H z$Dqk7N7N{oSi{@x3h5Oj?5vWbccU)sHxyRruq4s|Dj#0eg-UxpT#KopiY%Y@U-5ouKb9>@#_+>g<`mGBp`25E=CDU}5k$U4#pQgl znI~u%RUfg-^H?5qFBb&HLLmSH6 zs@<*?boNKW3AMQPN3~in~gKe?==2Q_p(YtMj<*39NS?cdh>0 z#9#VNTc>8QFoT|vbd$uUMwSqp{v$F{)MHa5iY++0>uN^3<$-1%V z|0T=T`RqeG=y~49;cpmxlNWmkh%yuD$a4@Lf*IyUve0|#Kg40F%C(PV<%11%+R&#= zU~=P)70k>-@8O1PIOKw1@Grcu8+&qWsLu$m{!1fAjl^8QD&IKgdL-CK2x|>p3x}9< zNSWRBu{r}$erdm(&*4w8L(sGe*Lo~%Tq}v^zGl4WTeW0d4#qbLmKW3M-QDSRJ-JIZ z_tN;o)e~E^rJj32?;T|SAyRI?-}XYpo4d#Bnzjd4C?q2-%xn)1H8(a&u@Xtnd|o@H zYiXY<2&~RrgIh0hI?M-NB~nY$D9VMF*^F?LE)%z*W_zM97%%W{OdyKv`}?i^+EoSF z{k)TRa2p%`QXrPZFs)LkqLI9zXF9#HujjYSad=y*_WM@)vitcacN+7f0Z3sIDH!LW zk5;%cA?i&WIs~E|kSLS9jc9C)jeaD~WQjAJI2qk>tO#EaRpLyJR*c9C>?zY^635vx z?Aq~Q%To0&8F0&3-Q?Wv>dm|miq81^kKkm-WsnC0BOj4#hg7f>yV2FOm~Wti?QNOO zP-g?Yjn}AzVBbc}M8rkn8_TnuU-`>WRC}v1`~fG3WjOZ~loom-?)B}v-5M`3c8}fg7Mp86Cx9AcCxbeQ|snMFC*gFX_3>mGdepBm)xTl z|2v$dO-EFaTb}80T`Lo}2ra3b&>oAPF_C^kD@~qo#GCbrFoJ7^tUTv_>S{89UTuml zKkJ=+v5lOGihZa3x59(r*CNTGFXNV_gKYgEK6_(dqsN<;^SDZ$=upOcbd1wnPc}K^ z4dSGlE!RZH8816_?LQ*z&eq(`K@2Q!#=vsq;-2{Vja;${eHpWo7O*5`Rcw?{_(G&f zp)X^DhxtyHl(P0jQf*@Ge?1RjrR+s>{7Xy`5L*kvk826voAuTUCP&neTST0n@S?UL zV{evJoC=?Edtq>JXIlPP+&j#HpstaAABOU=MK>`Q<&5~*Q#;vTwTS9*-LyUSljbGa z{&pc)?rV=pQ#J-vdMC|MM`7NXEmOu6Lg&!cU5v|`WoBjQ0KA)rUnL`dGFl!iH;awu z80(6Fma`9bv2IM|q-4#yaqXMQk7Kp%Uml5dWwvLrE@bBv-BU3(@9w9BlyyL7+C|LI zX|yZuBY^O)t7#oB*r{epZyr8N7p`*Bjrw4$F{83M3kH@vqSYjfjF+hR^zfP#t>Tr% z*^?u4h0jwDNh%m$**u8ZhShiaw{Mn#g8zjU#EBKKH8X^XU)^L4dG8H8Gq5( zRClJGb~4+WT--3!{2ePP)|h7Q*3NkFYaj8AtjI3l07&@5$bE3n%Y18>OED3}Pc(nU z8^hJIuDIR9vaS;ICMHdms>8hQN$f?UZ^f{B6uoz@1=sd@wC$N;<}?zY@CHXKYk%UlpQ;KP(9Ex9#(Mjkh=S{>Z}1-`56uXvPI@ZHQ*9 zX@VT-ZURIV-&t$zE`s^mB8`3fU8ITu25a-kb#p6I|19%vD|Sf7mZ4gT)HC)^t=N%T zB+<0D*%}f1KG_q(?YzK7( z>z&_;R(>M=Rf(u6TknS$__5Z3%NE>M8he{WT?EGxwoJudJBAzTLAv9iNsu zNAsfFWouxMF5#jF@|vFGob{rO-VMo-zN{$+e5<%qtRS=4yla58IirUJZ}C9&Lab3d z_9s_;+Wu|I(-$SmCrwop#TYSFG4RV9jmS8DssbrvK<;K^X#1)30p9S(k(4K- zeMJ(UARx9QIAj2coZcrIc@?FQqJ|Nx;`=T@fZBa*Q>KaU`bKX{-g4TmRvIayd>&&k zrZGM_hCiPsho0t+bm9qKB$e2ZAm1=W-Z$?jHHt0nC(Iog^T_6 zX(vhuOf-sWt!stMh@~fO^@g{P-h|1E=~~Cn)6`*1Iy_a-+|N}VB(2jWeJjyV#`H)u znCma=kJf6kOnVQpFP$IuZB=sg=3r;qIVb4hZxDqscd`u^&S`%R;xmKmOndcsJ#Z9S z>Fikix6+Bx>9Df(G>ORkX7c{i8NW7z_-$87lrM6tOd9%l8+Upl{Xz#~gK;>S z<74xZOO1}(BXbNv`g>iO=>=3#x$z}@rV;m}cjH@WI1wr^vUxMC=xzGkSQPHh=^PQSe#P<)Rp66K&M-R+HX(CD1UHJnW$%l0>Fo?J z>=<{et$J3X17^O$f*B)fI-5?OW4Lq_`PWC3CusnpD7}dsWU0=~BLnexKo>$|A=YRf zmG-{kFTrHkrFirvIqdQ00g;&g9pP=GH*pgO7@RYe?N5}~c>^5BTZ}TYcmrhe7N_)` z9dRl+X622#7mAF0)IlqgBw(L`zLo1NZ)dcdvKqasNpOKReO{W1YsJ01!E?t^>{ilM z9#@mx=q%1gV~GG1WxkIOLd3kQV0iCdTx`UY!}HF&w6T&?r6B-ik#-Yljw zZXI@qYlR$UWs}p_d61D)PRnZgL!D)EN`tPkHA=2p@sQ@ww4{sfSP!LC%AC*ovi>Ai znq<}5E!=ZCeWvfz-~FDOUwti}gT9qb8j`1;w1T5G3T!!;H&}J(YWjlFJW9lNVWKFO0V_l#H}}(pS3nKdbzg%L6mfn3 zBaJrPMd^ONLzm9g^tR=x8Dh0~QjB1ZUTzVx2=?B`rHn9I*;XRMZgDd;S$7pq# z7k~>|ak(EXd&8a`l=b(lx>uLgY670d50*u5IqYr*9%qd+$6v?yB1gpEQ=I zgwmV(oNb*7CYk|qsiN*+Fz1a_E9uaNb(q1XV>rvc~#ta5mwNSr6f%Zkh6+BND8n49V>sYtIvwlrl*M(n#e zePPc5!e%pmQFtk`hcDa{DuQA@k39|6U%+w=bKpv+H5W8 zaV+a4!X9M_$rK$CNo9_#8olCYD0R!&Gf#9g*w4Vm$_{gv)9UG7#gYMEsD1E$NuLxk zKhz^6D{68gOo{**$PVUDT3+EfqjLRamsKzJ1P0OJE@6d zLAYBc)e3a>l2?w6Z~G9sT3^mMgR9wIHFmP4d&RQLK#S@P6o%t6x$jr5YOEqTnCkFF;u$2Tt@oJcp`A+*x$XGX`7*El*vZsb z7I*^JJRBKeW{^(-@>e5x>Z0xPG4~o`l}?ts8>Kqf*g(qIX*TG(VIk{6y(`r{5nwMx zc#z&#>z((!--h#gT5BJBkP|@4$6Zw%d)-7m${HaZv{8g#jNBw^-h;39;>`A2EL8Ye z(fh$BQ0q)<94Xu-CPP~0g3AuQ;rYgJsVlZkw+F|WGpSm8rExmWFkdc|R#PKFB_^9? z4+(h@-SbQ2SkIQn6on>Jv8L?{x3NH%pZktK{7Rmya68`juhqi`>)^Lom@FL{dBf~S z%AuV2V1M%+XlzMkauS)rk2qN*)tUCn2&r>eafcivI29ZtbFR5aIzuLBJI!s>niSI2 zR1ACL@$@dKd?dyjiMW4{e`u$F|2zK9UD~?iapuCVjLfiR6Rh^XI1DL-RSzaXO#?`U z#AW8U)2!}FT<&T>KSN*HK;K~L*;zHA536&JW$y!F#WYeXyLFAHi7?D{h%95y@ zbp^58C`0&wgmZSLoloAf{Qz6_qeTuOUWBT*kEyrSQYA+?rY^(Cg=hj$6FE`|V$4YT zEN4L(9r^IPh{kz*FURupIloqTdFwpPN4rffOclmqNnDV)v-0gkg zODq6+5cTE(@ioLEkjQ*v1S00S1tQ@2r!^KhoQ>%8Kg+16a+dS1&`8Yg<$taAkBOuc z%HdoVNsfL834C%IxyUovccbJLae4Q@KD6~X)vB0_frOOIDdn;E6izTVR|{RsGu@)& z2_1WEJik_j`lyV7kp%3MF&S%iz!`e~pg;x(y@@b;PL~mX^v~M}J)tw)-g0)FujNwa zoBMsMK4msLi1RkafTbxM$z0l3>(M;yC}f`MG3S#%?Kl_E8v$$nd>&Y|BMysk4{uIR z@PIdGk%Q^nHuU-}pFjPsifmUT^(-%B~2+jJ(l@C6oRrSh&^XsPkxd5 z&^IwbxkmE%^Vk>5{WO>*!a@59 zi#Qs2)hR-qePSyZVXi8#rIIts?Np8Hk@!l!NsE|Q**wj;D*ggqVeXaFxIl$V&Go{- zJ|R@L2mm?anutKgDG5uP;I*5j32t$=Ea{8ZLM-EX&_sbtD2hlZm0%`Av;5}1^66MP zG;a3qDwgTiPN_;+7;Hz-7J&_oKg??)7I;}O7dd2P=)hptid6*bZfBN2vb~H7F(iDI zIYV%PhB@ArDRENGMTlX@m=o}iMcqPs{Mps?UEu=M9vJ;1m|bIC-7Z94OL<(h6d(G- zX}5k)gsWFsFB0c`Y^Zj{LH%+_jRt%Hf^7E%;VmcyE5$^N~|MIafH0?8e10 zlY=MaTo4;P&f9WU9CuCnW1letRto)e3Pzv!d<@3NK9iGSJmVFeqqi_w>x*skvFYjY zPYNpI1dAe*bTqv-z>%I-b1zaZ1IjF^G5@3q!9Vz7KZLDyb(vKa7WwA+IY+@vVg@BN zKcs?S9ZF~xmq)qLtj0;*MNEj@qjgup`UXuD>Dfll z4-cVuGCF3x7Ux=V1GM#*VU*iyAEX+7$=tc& zC`tZDi3qsylXXufIGATXe3YQq5mYxCX)7maqZT^CfTKm2BN1Z1ipWhMBHd$m{7f;+ z{T(iMc4GMJF8D+zUeJ76VVCcZ@fEHuK)mHd*vokYTK?2ZO4!x6T}@*&D?u)E+L)@Re6oiYKZq`A zhmLPHlSo)aPGFcCwccS2-?t^kNH>3s?{-=DRc4iTCJ95osO1Kxe_D>x=O{$JL(u&L zwlU~M@5MO>~{ujc}mmaU5K`s(;hd#=uSQI#K@UzdQG{Ao{sicVZU?d%*<#D$*zS zFMgNrD}pvX9c;~EnOXEsy3>@YJHl0ow52M9Bot4WXE2JkJE5ap?xUS0=NP%RKOB-? z)gs3WrrReI4^h7mi|{DVQ{7sDW&g8CM6##I@#^3dQ$djKE?pGe-S!N5@FhYjW)+93 z$k0h}+(}xFNX{dZJ)b7v&ivkRI# zW8js2E4{HZQX?nI+u-_R1*Bg&R6LJ~q@oR@jrJ!S{ibn-AzjSOx;6}fx$!>6%HmYX z;uXoFZzW{sTV?;!{XM4&*5B z+$PhPb~B?OCPD3Xp3Yz3&pfFS4|dV?Jjgp zd#R!zJnT4TjhrNWsbO%Xclo=jqp;;R)j_XA7m9C?ok8M?3=fATlZQucGGMCm5jwLa z<_(i6Cd(`rZPEU8$RCBCXe332)f_GBxur8_Wb#f z%C?SfPq7e)CNErIeHh*K;V`5RMi%AhzvKTd)5ayuKpr)>DT4LfWY zlWKiG#)jE8^xLq+hK3E7*zgB7yxoTP+3;~2?zG|CHvHIz2W>c5^e6b8WWzIT_+1+= zvf*kQuCd``Hr#2$w{7^54fokFX0Vlhq7Bn+c#;h#+wdG4&a+{q4Ffi8wBgM*Tx-Mo zZ1|)N|71fYqdLEI8;-Z3--h#TxX6ar*>H^wAF$yz8@Ac-&o(@0!(`dteB6f5+3;N(erCg%3@g868y;)Ji8j2@hE+CPWW!Z9)X4sg zKUK%b{;N_`W?QiM5(}=s)PlXEn)g`#1w)VgJsQ5Uw7RCE+-=mkFRd`#6^p73cUfI| zg}bu8Zh<>cUsqPq&@dKNsP1rO^%bQ?MbB^U;~EtI^>2Dzu%_HyTPJB%l*t#{zqD37 zE30eE-9?Lys=8VoAZV1%uc;uIXj{o|^r(RTI+p0xyY^Pot@w3;idr4|l!mhU>VPpe zu-N`ySDy#+MHa?NEl>@rOx3A+Rl&cps$A9ZPpL7gRt2>iwFh~x4c63HPW|3TsXnZI zvN#^wNA-zGj?2r-i+4kC$N-lv)&6#Lr0x zv{0N*fRlgns(;Bj4qcBA*w7IZ8yDZFud`o5|HPyLuH=+~gHqE54@u8BX6UftBSyMM z9XmSnxZ_V4bK*%^C!aF*)a-HNCrmu;^zYKSKxywj%p^3FQjpMTDbg2I{S z7M(Y1b}_qF^Dg-A_b$BX;!8?O=a-dNR9;$Dec9zT3u@~ESJXEc!G%{YT71>jORibE zOmD9XV)emVqk2JwyQ03nuHLOwl3gLi1?SG5ZTV`i+4(ci?(wR8=N5YNXLkF{Iz4;B z#H0jot-CZ3sHrY1HL9uVs?rAcf>PM36o130SP(FTsWWb;U?&Ux(35tQ+;^_ zsY`L{D;k0|hP$rPT~=CCBbh-d!ReH;x&;Bw=e7xf=qdWwdmH*VK{iAq4A5uW`NT)m8Qi ztMXd=J*@9s};_4&kn-JVjCuc~54%AiG8eKh=BqQBlh30Oi)YWD6bq#fu zhWq?#UE1kcSzUA~usTH{Xaa3v?AWnt3S;x7_4IbNrS#gt+RJO}uB<(SdbLTJC;j-S zgaige2{zfSYeP2KRIALTqCa*cTjQcHK$K?=d2iu8I(A90AM|?XtjHnXukZEFG5SNk zv&4DG`;U9Q_i1dru5o!I190qhjn`eM6?2)ts&3J}lEZY*kCshn!e2{}b`8yR02 zgo}z+f|h$s6_b z|C-d{{|*hmTy_6*sBibLXA0MeuVGR_wL(&;EON6 z`uZDmV*k+z(9tJ2-)aK%uP*<;I{$x|{(o-*di3vl0{X8mzu!N3!Gg&R(Pau%&hKP* zAwRb`7W30BrLgeS^72!ym!d*8F?r*nU;#l-BB3@|C<4=}X#* zG$lQrTH-I3v?Luxe2JrGmm0zPaz5}otG?QHDOFq*tZ(RgQ)+HSd2K}xk7C4h`CM36 zt3%BW+OX7+bR@pSQG}B)itifLvn!%&F>{#~*IhZ=(335N|D1-3`g7-B#@r;odxGw@ z3&{6^(gwrJ9Cu+wQC%Pyus+~#`B}-SLe`~9FRhqXx5$b)XLjDK3FF853JR?7-~l>d z1#;jBs!)JW&;pV`83+WOAQx1Fc+e11LQx?szv<`BJa0jjN6Qlan$7DNFV^r#Ile6{vc-~!c$~Cc%a*gjFNEw!(hLyY2 zu!#fIu=@0l!EILAqj|k|f>IxkVL8sut6xH#N|@MBCCus*h=zIOBvPoAllF!#b>*NewuX`>152FXxVd;}csQ=*9FKAD`_=hyLX}#eJ!Z zK2jHfj1&8-Ars44^8T($?ikRPxI3ZM8R%Qmr^u?)9nh+uJ4v~p%1~}2ojiw--(cl- z3{)8%L)y}Ichjz9vQjlXLPzIRV82+^&+)j5fxeoKMn9E7{u$(-LH-%z(^?$~F)Cqv zpX?ODxx61ZJ5}4+U2DSMIiO|H2^tyD2)br~ z3$*Gg!zr_r`j97@R*LX5{2MLfBj+piJWrvWmxWKCE_{U6tL7?o6Hlcb=5E|C@LU&- zGbm0Cn%Gwj8t>9&kT_#6Q0hXSXq+o>ujh%zv1pa7T*WTs`Yp5?;#5Pxe@HQqw1$iy z6wr0}a)0VEfjXovXQj01^7bt2__Ve`yHmRO=rMLvuP#yQP8&D7y%zPe+f%gMAC@Y0 z%zP&NgcI2N`y~9P@;E4qz?2~g;Fk<;E;XcnP)ACeYj;v>|E@Y~W7KS@RO*lK5`mvi zk9g7iKIdEPrI>x>yFkbAL^T}V9u990hlhq!zTx9D+J@|=t@PxhSf{{f1(jJPb zYxpapo^Vcwa!wQpY$ zPtkoD@3^D*?hg`gp;9B?lN6Q8I2BwcUJ*OoQ5k!r{=+>K8VyZQL(2!Kp%atT&{;z| zteUZSLg;w%Ql&29nQ5n)lF~<|OiWZMvxJffCDFXkT*i(#&v)!_R{0WD!VP@_);N=_ z(&3wQ`or`atiCqml%%|oMk@IaqK*ctLDL8PHlf4W)@OHIYfO>V-p~hAR@qZ1JG}Q| z|3JpLq|-(l$!aA1_fXOsGGSo-fR4nrgx${8Xx}L9%!&uE5=QgufEYDke1bI|%!!(h@ITtBcadG~) zy1uP8nxflH5@k+QLuN@!=%#n+$hgp!8?6Vv4MOoPL5n z#O^D)`h>sStJEKUqtqik`KdTXCA~ zsQ8Jjh7Iedh9TeeC_zzw@Xr{{xYxUOiY%FHk<^XuzmlLIG`xZSOVb$I7AHaDM3s6& zav(iLdIak?Q}&%ZqHl-8f9pk9wEDMRghhvcwO+(*$JrIN74>WkO}BQwrW^G&c?;Qd zK`otchV1@NXJ@uc1E4-`ZfUh~R$cvUc3)~LtQjZ!8`HJ^f*s7O)I+heD~PGL(EB8GxoibYGGY@u%_ZHHehG6&qC-oR9-E6RMYF({$+D-HnUhZxRv^IOhHBI!ivNE zzwA!MN*EdL)VSF-70lU>jUfj?#9Lm@1~6+7eH=ZN7_N}G)9V&20HcEHTC%?*c9u~y zr}j#w)Om~4=YqMFDry%(i8Ca{*+#kLNe?V32=>K`0~KnD^|h2e%79G0y{eVgp~J2F|i~zNr9N5BZUNnO+)TT|;<+ol`@7 zC^*Xcf!_X7>Q^y-_CC+5uRu~Tx-3OP1XV0<@AM+2QiVR}<`s(jb?`f% z{rz&yQ>-+o*Qj~f`Y)1wJPP=zto`(O_c+d~X&?b&u@>T$Hwa+8ohfe`jRR6=Jutk# z2UUyp)@yz_^(f&jRMl;9bEzH8gQ_E@fIUNdI}mPsEG9pyhtRtYy|v}D1J$(_V-z?f z^Stg|&Dn-%G&FeCCdvQs532AeG3Kh3adWH7E2dYK))&_m%8v20#YTnNa^!U2_PaIR zDRqz49;Mc4U#l%L`;I*?SW&;YsG?qLY@kA*@rKHmNu3l|mtAgi_`N;oWwRy(o2@xp zFToU}#o}$yJdaD=rSq9pVG(nMj%~MfYWXKU-f8M^$#f_mY^aj>(}I7sNwyWI5bx~rdcYB7S+#aj737w_&5pVjTK7?tP{0p@5h1DR{$HE_ydz8)8 zJr@0{uL3)tnqE`aP+>Rk>n+Z(`!27#tw(9j4H|)5A^}-w*7M z;tF)}NFLHPiC+p2%L@7t|4}^RkGT&W&TGF3~yQG`D72wkE-N7P}%-tWCWAJ$j@qv8Lv@&B{<{Abhe9lrN_ z@BIJ${?DL5@=5Gf%JHZyU`v%pWdZj;3!{H& zy8qi*VvIFkaKyyv;b$EKe95(ouN`F*^;hp$j-UV1g3Ir0`&wL{rHvY{C;X;gy#5Qf z_4%;B%MV&!9veRVEyH{5@EZufYwi1Mk5M12HP>QEqSvo0{iQ$GG0sCEIq&t0Uw5lZ zUcc=1@x4Mbp1-u`?Y1wJ8n@Jn`T0Rhj^dbcrv#qfE5`rSIO93x(0N-gG}OQPyU^ip z(V}Slk@4^N+M;ix!~Py?!QI&wEV9cTO*{IoY`zrXwkIt_wvyjGOgu@PsLV9Reis={ zeh0p=zDLF468qimq|_MuU1T!(9XMcx7nxIjyY2Tu)~i}$zl+Q(zbgAZ!+KR7`yF)< z{d3yyY-#G>?)_H!B5TTTz5PDIdQ~g!ceaD{&uzcE?RRsZ6@Qfd-m%wuKh}OPvfpLz zM1CIoorOjH%eLRIvfthIyKcnzrQ7dOVms~koLjAY{<|Q}SeA$M( zZTOrGci8YL8@Af;aT{*5;R7~YW5XM5xY~x%^qcJWB{no{SY^W!8y4BnW5XO9PPE|| z8z$RO*{~lIxM-Ub!bjWVSgRVk{(9_oT{F$1(?1HA*}rIiAvj2$QCx&SqHSD|Xk>yW z-#Y$c^#et-i^coD{44VPWAWQ;dblT8^yu9`^?sLeMSf8zZfWzmJm2M!_WBc^hk0J+ z`74iXYi9Gz^E|}!63=Hm$%H+Xr;tai2mfFA{XOmSm|nkF z`xh;HP9LkDvTZoVhHe}7bJ-6m2BTBH%kbf^!@2 zO4j>K@dvKr5&T8(<&;y{!^52obkIp=MV90iKWb-I9I| zH4iwIPUAxSJ-}1YwQR(l4Xor5`UHSCodIt6-vS(dCS@UR6>uew;3IIo?H2fF9?7=@ zc%jG2OW->^PZ7QiSmCwYRlp7&%~!xvrYZHN-~epnd0)Zk{A`fR1v;J+St&~KGX<)h!n(<=VJ z$9aSf0{hHhEX3alyp>1Nza6-&P^mq*8-Y`1!t=NVKF1?GBXIh8$WdIIYKuyFg zu$)I|DDZ8DA1R~zeCnM?%D4#l2~RoU6X!BF;gRqYfq&wWtC&n+%{;4I02~2Nx>!wWI?~x`eT!KkXejn@94({(`!hN7B3n__GqF zG6}N=_y~`L*$C|55!z~4YPrV%FSgxnz)|zz3F2k~&*oWz+Yc<~k#wqnr+GG`!6D)47K!jo%&gBKD8|8(HOYoG(}MZmk3Qcm3W z0)M{@y5nvIUe!ohl4$S1tPpjC`($ACN_Y-;4KSt|TH}rb)`n>pxC6j1cy7n-`yuV< zN6-y-HgFM-v`2wSH(373z@PFwM3~!wSNzy=8^8~2_sW~-D{i)Uzzv-H6WS8t=K=5G zk-EDVxaOzS3;qH-c!X90Pruc2`+y(t#KBi4@Uov#*SKqdxARDNf%ERL@)8)hllDaz zfxqUFyw(FBUjtv^FYuJLv{~Ak2ly$EwB-)q?Z2SRgc0aoXQeN28_!DoJAjG5hF5S4 zyoBcf?h@b!cfnUK+V$PYS@&4!7Xk0#5j^h&e#mn&VNBrYdo8}r1a9S#w!Z`T)o-XT z!h8*^xgXxZE%53Gs4v`2z=i(-KDZYFXKkP##9a)0i%06Q4Y>Ca%Y6X2{&(O^7=c3` zxA-j`IN%9uyz>En!XtRz0vxgxJ|=uRaMd=(Al$2gt9HU;;JF&Oco%I1_Yz>rZi@#} zfj7NqkEg)wmuc^W5x9*eLe21O%HjB>5f25z`2}oT4@X66diVP3lzO`aSL2#yRQS@X}bkJXuDg1qPH#K1&WTg;3iP?pT%FG=+TP5K+(+< nw?NT@6}Ldqah31_e`34u06t>71&U6lgcmsMed+*O$?yLG6?YM| literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/cli-arm64.exe b/venv/Lib/site-packages/setuptools/cli-arm64.exe new file mode 100644 index 0000000000000000000000000000000000000000..7a87ce48093d2c984b2ceb7b1f8e1ba6f5fc94f1 GIT binary patch literal 137216 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

    x5%&be+vRm^Y>egOSbwaL4{e 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/cli.exe b/venv/Lib/site-packages/setuptools/cli.exe new file mode 100644 index 0000000000000000000000000000000000000000..b1487b7819e7286577a043c7726fbe0ca1543083 GIT binary patch literal 65536 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

    @|$jDp4t7maBT@by!vG1&J_?=DS4W3Hu6w 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[c}iI#RErv3nvcIClH@!{vM)zJ_weD zu_-L8NU*GlC{d0L!!VW10^+~>qmNB~Y8H+F}!P8_d(PpvjzMJQmr z)FkX;2B~<|3JfJeWv@IXo~nTtp$}Gjie> zs8UDG*kid(%i5QCBp~MA;#I186PI-nZ&k7!k8BiLJSuR>h7ArSYHD~B0I z=T6L{zqglekt0JjG5z&|GWb4?+B5+{p^fgTufl_KesA{@I&g7rNq==^SGc5GcM%$N zDBG2)qExz*Z;jGN_-iD-y8i2BCq)p}2lKcspLg>w-;qwg(()HXrZa3jd!}spuwBVX zwmX!iwU?#7uoQnunw|OlU~+c z^L5Ak3zWhaA4B^FhMMboO0k*O2GL)lD9_<$5b>czbCvKcSt+u*gA*=%dH>Q-Bc11h zzO7jbXN)&5mBf=w2anK6P$YcJZQoWa2#E!v{hFKxxm7Fc)Fc9iC35{|Lp7bIDjrhC zgMiGf4r2yquH{U7WdMio;XS4Y%Ry{q7#kv#gZ07i`7eo#MMh_o68E*Fd_#nrri^4b zX+slbsv>+8pmck%oLDUL()8NRJ#Z z8DReF_eq2zsjEXGs)yS{k}ykS1B!ZrY0f6O65^lslJv3g&wfpDg-&EwF8wrc=hSwm zPlV&n%%yE_@onOwK?)`GNJ6MQ0drMuBYWCH5dkD)uErh@*k}#GcFl<-;;TN+5vb|b zctkCv;*zL7f)A;QuO%(81r0)&aUz4EQu;kA!k@7i8RZ)koMaWW`5cC6n@{w!!J$5d zx}l)4VP4xL=BKi&c^{n_Qi`q@G{vimblcVR53b#*X$FUOQFm!A8JKahNSiBdY+x3bJZfD8n{--FLUM4+Mx@{vM_ep zkk)U=K8R(rhU(X_faI*ZO}cn`5t*O}lx^j8|0rt-)o=Axn^DGcQTi!#7hxLTq?|HQ zB;T6(nrsCeYK0_o%)IO+CP{n#+|;w1ZmvD2c-J{i88bp63RjyKOE!B!D3U{RCs*Zh z&^%65VM(J34230U4bHS}M@SYS9TEK}c%)2<$h1|T;##zRtjRt@#1T%J=kAhOiw+Z% z7DpyWVK@6%9K^uVD9LDKj)dR^aZK6$@Lt)l;sj@`QSzBm{TlLG{JKM_^60Zr2w~nr zr>P-BaV8OjjWm?hQ3$ZCx+lyD%q`~4iNF9xWKi$t&pzBhwN9Dq-o^v9@=abLR#|

    KZqkLal4YCRR9VNhIM|rBqmzzcImvcx z66fD`zj4}M-A;gyA17cSC-oI$`q?*q&8~)Qv|C#(aSFd|hYbf}FFVB?n3Q?Svt+Td z#AW4x=9X}?aizE|`r{}3l-H&b6-{_j#STR!lD001vu;K>KT;*^ChCevBwCMFpg{JI zv``4YsjK1&142Pl%%A#u3rbGso1<_fngd1`+}!pMu@z5Me_5UFxiPYKqFL4_`WXmY zeWJrZUKzrrMuBcHupOq4Wr12sE*T-*CXh;FA=)Q+BMN(?DJ!kq?%Ww`xlG3e;lz2t zY?tl;i?gHO_79VwJ_cThq^>FqRUPlqS?IuI+CfSbNkv_1l~7eGaCwRmuOF|ic1ac2 z9ldo$TN~LhX~J01P75nyi&d8=Y@QNZ5e<=6v_R3rM}nN}5ae`^LV&sAD<=;*z=!~` zvJ0@i!orMuT*5kyXNzJnxfU!+#FTW(syy@yj7XX8#zD_9TWBSg(;KZ25VO;is;-&R zf(29n3U}agkC`j4sjX{=`D1EkCC@enOA~v{GOLYQKAdPN6+?W+QE4fLMhrW4RGbH5^K(rm4T}`=ra<6GP2}cRBE9K8^r(O+ZvKpJDL~qNguPmwQZp-8m7V@ zN^KFU8@Q*E7UJswZD=OYtct4KqA&NDKSOfc-#M>@o#)4;YLqtENdFS^3K9&dFBr|M z*loqE3X2sMmi8hv#7H5rqGc_y=ShEbHT^m7S`?4d%B+(-6dYGI-*t5E+< z^P3gqvBIHjFQNKiDKj-p;Y*MmMAXOK^8{gVhrBn?Un}%9(JqaGPiann?Ll$aX-{n1 z!AnTWyjwZ7y=hrziEYVZVX)-}D^!8a+Bc<5#*3h1xvWqS7I$WL>iwNNvp;P<;TX`| zOF6ZibFB4T(YJC~mj~?Ev*ln|9sgYVFTcLiEi{YE;!ZWj>X*aK9|va;HulW-D`RH9 zw=O#R&of(j+rwMS%oCi;+oFskQ}@q2q4x)O3k5e6yDx`kLvQs@M`+D)vGA+`X6%Dl9YOA?Qrurfg>XqT9E@^ zgWxOT&hX+yo>7=HCb!3BO$p54I3{j@qbN!+nu>Ti*O~vw`5RU!f_JXS+*x#-zFp@m zr}GGVhgT1=p-TFp#dtAVjM3QdpDoi{l*z?1s=d~(E;Fkn=*i8+oBcJ3Ib?Vh+rZWNZ$pO`dl8LcBv_cAA zc18lYB|rc<0u%wEdTGEup|%_S`L>@ui4LTkvnNApm#>+b4WIF<} z^J}=w7L&$J%unXCb|Wy{z3WVlMDNhz3o7S-3)6oqjx)7WX0HTEH{-=9>q+ zXXtoVPHKfVJMk8bt&h;MII}u~0l79^#`5CdW6Ef!eb|E&Q{UJ$n$yP;^Jd)qhw~ej zB?c~nN*%0zm%$}MD%|VZuS8W+Qtf zS+Uu?;oSPLL}G`jMH zn3`(J{6K%B(Gykos(!d}z)Wr!%sjC6=V@s)qG1MJN~uoVlq{jeI#XKPMI;@L^`RBZ z0Fhm zEI{|uQr0z1gk4W{mj*%4Z*00DBL5ko{4X}2{Dl0wAi#aSmq_r~FBHL|;}P&0k>OU! zhx64h5vSKwffV0W4JQs2dFBrfQx(B{AK=BGc`U!}S&BFnE6QSvw?`~m^}8j(4$IzQ z_WzjR?fD!VI8Aa=N;O96$fIWzW@IV2KtfOm4MwFVU~FM5pwL+-yY-+$4mvEEjvjP+5JUm8n(w zTE>U0(q9W!VAi2soP~_07HUw%Pt_tTYxD^79a6Fw-(PjP4xwLxv3Ycv!%RV}m`xvC zX`nx*(H@IF+EJ)392Ul)-t@Oj>L>VGb7%C~V}eWde6yYkCcYR2>L5_BFiz*D#3I_* zY)|v0XvW#xv=Y0=d;t!!=&NUW2H8t2>2H>>rUwQga=@Hd8s$Z+x+rNk0%K7J*cGvn za#2GFTwHgcx}(hY&AoeJJ>OtvvdouZfGLkWz?5@JX6KrhfDJ0`xz(qU+f2hY)2ykx zl5dMrs#`m^OO;aljpVNpXHI7j?NBazjFr-P<5NZ{lysyym6ILI!i}auR#r=s8-sHH zo|F}x&aDr!mLdRfA3dBON<#lrL!uSm7=o9syd*hDuX`F0HkX``(5Ixonj|KOyUg3^ zQc-Q1zi|oXoEJ7t`z@l)r8HbVnV=3@R147(4T%Z?MF>|u+vhb+dmd}f?PMV8SW8Om zNGeF;<~ukE61hiT7Fejt`7XmU^|R{ev+p#`i$*Qly)%e2TjDu=LV)p<*h6u5gyTBv zF2X}pxW+%;eRIVAvq#45Tg=WlQSFR|)0f>5G`p(9xM7}| zFKtPEbWZkN=1qLjD*3c&W=C5QZ78nOyIt7^bEIKqkTQs5B8y0Tx?-c7F3RU`pPOs` z_?hlA-(AYe*|k@#n%-mt4P66m+?M)nmWXqWP-^>As_PEzQPQQFQR8 z8-h3Q39C3Q91oVz2*#A-KL%2bY;8!cmJ9uHA`|C8 z$NX`>3!Xc-34zzMQ(s0p^HbkPL0@}t>MK)QkhQHnsYONA8Y3sjLq95yD8o_vXX;;L z>_rtUVz~Yrx{&>y!BX_$%=h%m(WLsmNbc^@hvIY`rx=`G3p{Y^ZC06YKwy@l-|)Hh zU=6u>PjJFvP!kJ(Tc+sbM_EIjrY|G=W}4NvvWB>k^nM4`K&TNt=8t0byviN1Lph6= zm_yLKL?eam;`vUGWXllNQpvgH+$3sPb_yL=Bg|EjmK*vv&mK-$JqW8%=|ASK>2#&P z_Hr|Y5Dkgu7#^X*C_?v-?p6bh!n7?WmSW!JeSwnSm}M7T5((zV1Sgd@d05#6N@`iq zIof-m%Wyrh&Os_zmvwFpf)UBIy{<8BeDtovo%NaL&_|tBV$bJ-C;E$apFPY)zG1$1 z&owMVml>CDJKAdL5zE6EYkt$pYmLfF?wDG0`I8N*#DQu4-A7E6KcN`U27=18Fz;s6 zgRIKZJ=&bE;>8osoUL9Ryh=TbC>SSDx$a_ae4Sb3Y{(ciQKVJ&x*C=an(TMl4xLH2 zXX$$5{C?<{&`X7#bw|C!?@WU>(wf=M60Egk4C)t`yyBd`(C=(qFld4VoFf6R4+pHN zK8Ll6cJ>?zJRuIOK|)?8A%{uGgm6egv3W?S%i_2=V{%GzdHk`#X)(c}lhxAXtow#+ zFHp)}cHUdTEBD@=-@HTIVx!PQ#~t7^T8*<#^hS~|xc9~6%di^At;m{`IHO;U1JyJ& z?$6LV#Y%45gWjnIu3a5-`VNydN5;meS;L)mKjUK-hMMbbbJA&Cbq9~|S=gw!q$wS} z>!$M`UNJWuIMmgl*gmkLk_ZS(?`c%lMZ(&XFK8NP#)0^vSl6vFEG>}Yt=qY z>WCarV-#iQR(@uObO3d9Zj~Ae<}6f(n;Hky?Oz`=r|lj-I0#^gmZN5;ee)19uN-uf zbLW7xnioz$Qqpv@afoy00q1WU|&pEgH8343To6masFPXZZ+i2fw zw(TOJh6NWV1zH#tgBTU7eP2E-U^0`E%lVvRweM3##v6R|Hc)r2ZWu6UP8uu_SKF^7 z5Ei+b&tX|(bW>KeN_C)b7q?VhC2@*pFT<#gaK20zQb%f_ppm8Xf&=AdHBgp?2g=0N zzUt06{THYVS>0fh!O|&%MP5GTWr9DpB_rmtxWJV%cw()yvDADh1(g)ek#K;gD6diD^_G>B>y~3*2ri=>?y@k#|fr6r^y=jEkKl3E7 z4M}aqf+KgXac<4$1&vT`xA250AV##H0=5ek@I!)vK3Iwme$0oDmHS)WNy*wIdYTYj zZRu7LFxIS58JMfP!&x-K4>+HK()5vW=nSz9Me#w3T`4{giqU44ixKrd!tunBaOeaO;`@Gg0VSi}FyYeUlc*jfuoTFFEd zOR8Z4RTBHrnM_v=qLS_KTIyGvYt1|?i!+C4y??`sV=b9MS0Ju6Q)C6T`W3;Z%o85d ziENh~l0#_RtCgzGELP8JHB9M!#^AHfT3W1T^h?P+q1$V+gEe9y%{FPzuSsRs@Ay-r z&&$%MWa*cg*GZ8R;SHL@d5gHczoSYe+a|;+l&uAZooROH4pP=g`GeNXPLfFzb`#S1 z2_-JE19Kg4B`^wb`OGw9drEbu!t~n%qeIJiU}$Ld55)5#)skz}?aZlPlQ8z#UJ#-| zYO^vmzd2P;V*j5ETWQQ}A;NIjCB|%xCEmF;jXrG6JdLv!xSAK@X@Sdl!B-26nk^;Q zowGGGn&>N2cRRN_tq77S`L(hZ^0u`V19Af$;OpSM*@-NJvG_@@hy5J^vd5CVZ8v5tF zwQ7lkRx1I6-#=R@`m)Md`q#Na+?08k)vz7fn~b?P7;2Kt8t}>IiMVUrKGxYujGZWb zLanz`MzcgG7IDuLahiX|7e$b)I}hh9p%{<(HOiH54&kp~Ytv~>ArTCn#S8~^$oQ)X zh^?`%yGTMs6NUtL_ntBL;MAmDP#8v#36b}%i_U$y`ln#i)B;*>S*Pvjco$ClL? z%=q~elnuXpj0WVh4c6?B5^b?x@W;C;BYJ#|yQV(-^BV8xS@qdyP_7}XGtF%KKWAjn zLectNCDB|O$s?N`pgU^fn(!runKLO{ZL*IDdN#goZ=z)9FDy|a4b+7tIf&rq{hz40 z&UP~#62@?Yv#|LPJJk&HQ3e)?F*x^tH_b5TT8Z=h%QKll3XntrekU{W1ucz%R_!vl zu6JTwtI@B2wku%k4*@aLHLf+aSdHs*_rgZ{Wh2W%`KXEPa`u}qU^8Nd`Gtzm`f-1-zBi0iySJ$H?3COIw5Sts}8 z<+Vm%m)h*yTBpLCW?Q^x1F!Vd+Cd-yYm=~2?%cW>C+BZ7&rJ{WkI2`jH+ zb9w~ZgNut( zRG;4bHiKMr_Jpiv$aIiF9yPwvac%awnv2~cp8C&!2=C}j(2#tMi zjAaHm5bPpSUwa%RYp-#*{ngfz;(tXArj2S*S=&8{L(57D#>Sy>ye}&aBu|6{WXYoR zJy=+9jhe&f&&Pd^I=}K3&D!?hXM~&KKNL|-rI@I}J}9IBm%CT4Pr(h2lA`RU!W}#z zTt1O71J@X3uEEEm16dpYC#BMwiUd{3p3PQWl4fnzvSl_Q9@M}hNeE;-!hE}nWGGc1 zPd%s4GDneKLvjGcS1HB`9XaviNE~IJ5)rQKQ@w;(FbQa{p*Dyv{NvkHXAi;5a-v(C z`r^gH3Wfzd%G^(xROzgOnu~kNc%v|Y{{$u`D4$wu6mDT|WDAsPz{x$PmVRmi?cZF+ z-U3yHJ4XL3ya%Jx{3B1Os@RU`W_KkhwTO`EP<`_mS~KR8U+7dTIE{Ja&Tt#Gon$nl zE(dWJp-%nLFGR6dIAy<_TXIXDnE(n>ay2-K8OIy5nAx_qmLyOgtQ6Fj%*-=qe@HKi z0nCq$syuW4!}7)5RiQ;?m+>J6id0FQbux>KbU4=#b?)3Fg%G{}A@pSk=NYO@J@Gx( z+{gD5$inzGt&2vIBM=9%&Ys$We)D#=;$X>?T(d~*H3&8|nSsg$L4-o()4BCDnT9d8 zE_0`&P_=OS)^ylwt2<5* zvwCk}v{^^0RD(Mo4Ce-R%T811{Z?J%>mVhkZSqsZUab`AH#ms$5NI#mLjx`}sob@d<%w|L( zocFxQ+iwIN$`Lbg(^wA>sk1CDaCHq1dn;88aoAtv)vqavty0V_rw}n1A$&%RTW^fp zY)}2T(vF=bG5SC~B*4=@Q8ksK&3H(1Umvsi=+-mqUO_!8b(bJ>RT_kck`^w4=oz2- zwmQq2dD6)hOs(rtPvK;BG z{Y=ms-NO?H{RWf<@R!l@1ap~PGv8k0k3-q__{PCC@7C5Fh^ikPxV*RPmYM_6 z0kfvSzBw?k$ERj&%~qlI8?ow$vto~Q!31rW=wT=8P}xDGS$oy?u<(xFOYiHeWgsP# zT)aFG=O0)ID^^KfcN36{h|5_lk9ol2Erhw1%VG`GJQ^J0PAl8jr?Yx*E!U4=K2it(Ud zQ6rhrtZtLI1dW*3;fTHQ-7(GY#w6b|7=sK8vsi6UF!k;QP1I`7T{{)D%r}j9f6JY_ z`axh=-H>^}`P?qy;er7j3=la1cXR(2P^}~G5U@)^Y9R^W~(Yf&ei6pNG>XS)n>Z@{y@SU?&+x_PP zwi4TIm{g4?h9h`GI^_uccL{tvDS( zC7i=<#ERSNqK5joFl%3Dof%|KBvEU5qQ@ea%d`kN0xVuIHgfZRyPgfKsk;4%Cssd! zRZy@kcG~O{Xfb=dB)TDUpTCpV$~J|+y5e-hioLf6Tpsho_n_hSP(E;qsV|s#j?^8BAB(5Hf@{N#z(eFM>tMXu;~1uk&K# zE;Rzpm%)M=;(^O${@GT2SY*Q}7pOi8US|%YNHQuI9Dx}gPKACg9BY2xSRbtn$9iuY9oSBsmKgV3c(wEn=%-nK zD|%o2NhvE{vveJc2sn-K3I^M)_Ob0-oNJyT-AUD_7&*4H{_58PGyIvmsB7>#GLE9O zM_%Yt+6~?L-bud7E~=~mV~m!R6?=_4{MCo0O}Rex{k}23X2mR8`5ssCbIoY$sMFI9 zV=R9en4=k(1bGJ`JxbOSr0X_SY1>&{IxnuM;$(R1rZhlZsNjrRzXB)?&li~var z?B}%klDLWDf^4)nO#Q>nX4L#{frSueKHj{6e&Bw?L>`d{`ZHFsWS3ZmQoc`R>p!Zt z)MWNo*@Q0+(@KUAHQ#)n2!1ZmKjktmg>5tXOlEwvo@l;@bE{CFH1qfBRZ%~VD0^FK zYxkW_5R7B$+uR~XI@m1DA|0`t2h;L9#E9HeM)1wN?ybHta2K0&yD%+>v34#tOPGE6 z`4T2CtnhJRUgKcr&fU(Poo6zxgN->hy>T#X%%RSme-YWd)|AY6vM0lNYNQ&yn% zUR-P#5K5nU)Yx-dWQHOQ5Jo1y$g%9Mk}!8IeeMr47nESfX>;2=StXRpPm!JqVOg!O zss1JtXWbeChf1w%MT>HGxYweE6iHzp10k|K23P|lvUm(HB!wrCOfHOAC+sN2t35LB zOh)u5B9syRTR=6tT`Fqj2nANt5guo2m zFRo1DZ{oTuaTy*M?|e>p@X=?|N4fNYq|h*m3`rtjb3S)K(tr~W*Ak!p*pjtM&|QE` z1g;w|3YQ_Trwmq5RfH^6ge+BrELDUoRfH^6gsiVr1gXj)W9({XO@BJWxitVf8QE40 zLOB2Ws z#?1K7`D%?yj@5<1AMJ1LLKc%*@PGU7yMNKNXMh&qIPd`w1JXJYmE39l%IX`-wm@a3j$7_kLoU_KWm1ZQ4y~+M(s#*}g5UJIHUI zPSYM7*7F_qSY1$D>MeBZW$%;b7krZdIkX zK=(%axhGU<{MY7`8>NNrvT{ksyGmSfD<~6()x~9nZqEk2sJu*h8hXL)rCx%Nv^H*R zh4Ps~G%44(vEA{?E4*bY)KyihDvK-hDHR(epUO-M>aj|vX=}79ZIxE8Rcc=TP0ZDN^GT57!tV(H)C zO3L#<8gjb@-_RT@i&pZ}wDlG1`8fyy(bwVN;ozTqYEO+#*R)Fkeo@gjd%u`iNB_71 z@dF1rU4t(gk}&k*OA?0-A2D*&=rQiGmyR1h;j+soUUB85$yZIeI_a8gr%szb28}9zb#_CO*6`47+OuE!lUR3AyZUP zMf}9 zGO)|^f>p#MMnvkDSGlWws z7zSx)=geOaF>~~y;wpDRRh4(m?WG&sg+^s@*&XgOl3FXppd!U(#d>i;Y4P1E`M9ML zo;e~F_7c;5yKx8K?hWNeWn@{WxaaF`g03mA(%q%ScX~-(s#EE$GD>xK`D*v7g3?mS zjFyrzUA3xwO@*4`6R%!XT6u+gwNbW8wW*rn1wDl-tI{itRXUaDzw*o|EzK?{E>m@v zdS5H`R@1wz+_9cwU0rLp)hM0cEx%T zdqSa%f;;<$zi_*RA{7?s1r%YR)#VY>Qce0w?_GwsN(v*Rd`W15p#xdT))X_L7cZUBTaR%G35qstwOO?!9I7T6x(TZ<$UVB&=$~^M);`yu*-yRjR=yteQ`& zS;TaiuobdCcdtZ}ge-4fHG(xQyLeS)c~$vp-JM&kYB^`pr0(`uU@dwqPg)%FVak*# z+AQ|&J1SYt$_iMKjj}t-%GZ@$PalSwFjLm(v2k&1q7rPTTO#x07|yMMVxr?D~p|brlu8 z_G7&NzyG75fN-+k}Y zzx?@qv+Z94r~mDP58FTb_m4Y1Idiu2)4zPy#pTGq`9O5x1J74F5dCM@|35qbzq$SY z+JW@K{^~&bpI!f~teI=p%&Zd9gjUFJvOAlfTV6Ks)3UR#E-bv77k-{>O-lzj6LXGJ zM`vwe`P%OHMVywzImcVUk<<#1Zrov1>6&(ZBmJ+sIZe9;i1gppryTXS_V$nL*F@;USBGfC;q?2K?~0NO$CrF(miG4V8~^$Z zz5OHem-q{7zuf=oExrBw_UHKT_4e3MojVc!>izt0p32|GQ&|!<&s*lL zgt#=vqLj_iD@!xiLc4)ag`Y0mhdDx04|5>O?0E&n`rPu$94I-ZUTbI6zNgJmypm8b zw#R?6K}3&8G^?PjuoMj96G=6@ywE81&V^XJ5Sk64-_kOLVn3%6QZdB99CllX;qZc@ z7kCTSdcWZQm!4Ftg!43Ql0B!?3odbKG&x8?(hCbA7K8uvi;85TR7l)8R(7W^M7e*=UzOp7hJJ^) z(nEEn>)w|f1UFHnFHL(gIt%)yVs2=UsdtN!af>R6N2;LxK6<|NfDkslh4af`eF+6m z)0!jQ!9K$7ITAO0jz`lHq%{_0X3P5tN(1MlxKNE5FdyxD`_j@X0$BW%S@IR)qI^x> zyE!eh_CDPVQi&xzl8mB*r zXq(Ugqj7T7_*7`$Qn*y{aBS?iP!3mTf-#?^-i5iIkYIy zvkydkGkwAIZ-|;(YE%_T+BX=hS9>d&X@8DhFekg9!fHo)VvMc3EtZyt8%Q%FL(vv# z)_jt-m-$7!IlWy7(ZP|O!=%4zS*IFa1D*?m7zHOeWzo6==yb4tsryrBtvuQggi z>ruM)a71ku8G41G%jkWeSExKKMrK~bDzG86%1Nf!ErdI}rlO$I+g;n--Y%5-n3OSM z9OV{N77Jr0UArlB$->M9oCgX^IV_dgmcUk!bT#ddR-D2`tF7dFDt#B-`T)nMV2ubY{4f4woL&rs$D}RvZs(Z@^aBP0$f0Qcfmk3O zaD<-XCf`y7@e`h0*iX`xxbj3Rhsr~yi?|I2E((F41EvhrZ{8zFFW^oFyUm zoY0eHTBV=QQ}SjxR_Uza=>}MEkw-%21CX*xJ)}G}fRwp5^xVQz{C$A<*8x%0>u9fK>QPF6ltGuoAKJcHblus#4r3Eeullm-+iBb z{ri6ZweT1652y2A@9DbW&#J5Yg1`S7ZE<0ygjK%_6UF~))L&|G!66XZ$uBqr-2Zjj zfSUY2J`{?Ef`>)h9gnkNt=zI<%h*uoJo%3Gvi%9`S^L8iUGkQ;sYX4YB7F0Xw|2NK z?=SqVMfO#GX`$z{Uom`oDEv;szw+3r$A)YF@|gM9%~oO&f4kG)v|Ysz-BF9*y7eu$ zcH3JeZ(SP^(t52udhAappr>84$%KX=g3d?)=o1`;TQ*b%AWlwPua^IJY^Ce ze?Lv_#ZU7T9HXA+5T3X26r5%}&tW{f{+y-_=ed{X2%h)y6kMT@=V+c8Jjd`n@h@qb zo99zJ$MSsURGP91=Hj`YZ;j^$9_{a?X?OEH!BYm?ah^e*2YDWXzWY^x;iK>2+=@jadL7(4y z#b1Zbp`VPADB?+6d4_+|PVRo+k#0QiPsT~)ucpF^-~N%s&+_Cfjr9Hxzk4$Nw)lss zmkZ@sGN!|sN4^W6LqL8q7E^(*12QhY4?GLJ27C+*reTtRg@9a?3CEd$=sSM?C)~1m4*&oF literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/command/__init__.py b/venv/Lib/site-packages/setuptools/command/__init__.py new file mode 100644 index 0000000..b966dce --- /dev/null +++ b/venv/Lib/site-packages/setuptools/command/__init__.py @@ -0,0 +1,8 @@ +from distutils.command.bdist import bdist +import sys + +if 'egg' not in bdist.format_commands: + bdist.format_command['egg'] = ('bdist_egg', "Python .egg file") + bdist.format_commands.append('egg') + +del bdist, sys diff --git a/venv/Lib/site-packages/setuptools/command/__pycache__/__init__.cpython-39.pyc b/venv/Lib/site-packages/setuptools/command/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1dc3b2f865c898f2da6da0f1b35395b9c97db4f5 GIT binary patch literal 372 zcmY+AyGjE=6hP;Z4KXBYXK5;7i!6v%5=7BbL{OW_z%t29l8y6XXVwtEz|YXqPjXu; zf5FPTA%$MJk8_`JMZe!gAg_lnO-wXlL{f#9^ck0@ zvIS8~(h+JhZ;7Pu&^N|oBFQ~UlW*97Qd}n!S%i4YsG84H!ge;81HA0tt>ePkK?X3G z6AYBT13Hb+*D}(pp56f@WaY_F?~{UxLPQshsTvzu1=!iLB+~P=XBuP ivpmlWTf{ui{JQRpjFXjC=NJx#=EXhSAzj?XJ@O016lj|O literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/command/__pycache__/alias.cpython-39.pyc b/venv/Lib/site-packages/setuptools/command/__pycache__/alias.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b7129878349045a8ab251947e9d82374abf9259b GIT binary patch literal 2366 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/command/__pycache__/bdist_rpm.cpython-39.pyc b/venv/Lib/site-packages/setuptools/command/__pycache__/bdist_rpm.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..95eb2ef8c1a07f7494bb80662048566e3726018e GIT binary patch literal 1579 zcma)6OK%%D5GJ`RX`{$!lT(TYEiZPe!!D8*y#$7lAO>t9n zt`3l)2QbYpECLCvP>u=0C?}%;w~}xa!VOWKygTY*^caaigy%?vGMJNB!H5Wah=!eC zzydlL;^y|Dv~^|6Qki{OX_<1HmBsg57g;e&oz~Ss;Nt;ILt&9Je(5K&gu^H~{^7;s-*@4BP6&Bc%3xd%pS^={c7$Y0b zJFD&~a%X{n+u&e1za%X)z+{^}K;(j7WJ&>-RLi_P1{uKNbXr@-(mI%gerM#G`Nffx zihkB^6;Gc-Xl4knjFns@P4t#*NNTibtHU&*J84%G&2^xUrDYDRh$bv`Hq(KV2Ox(s z3yoCMpOC%|vfrOQx<3Zj+KhQoa5H{bRr}oX@skp=GyYcQ)ws&4xGo$JDPoT*zE|`4 z;tQLP&8A|9>DrX9$XL(u+PIMaIk2O zSHv-X2Kf-=9G&8Q^a{RCT?YjR?>+Crt3#N+IcAW&XSba4$~Wc(fgPIUg1ja#LNE|6 zZ}>m}v8NeoiY~u=PxOB(aM|7V@0L65PUC`ZzjS?Y7H_|-3&;u7uwd)FpFuu)T2_ju za!4AI+-*XY71AfCT^w^we^){A0>#yyBg8mPyAk;f2*u>DFogAwWqe5~%lUK3OeIq` z&6G@bmCL8ugTq@p!$3!1r7evQ-gz)2+Wr5aR=~tNVDt^Rxee3!UnCx2K=Nz1zx?Pw z{T~dwO~ja^fw88~SYC=+x$}Ur7d2Pwn;v7LOd0ca1K`pe;V_B@ zUN-EFK6XtG9j;8WF34nqs_CsoUb&6F0~VV8Wf}Vp`ZuRdwA+H-bH54i`6iCYAov?o CbF4G~ literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/command/__pycache__/build_clib.cpython-39.pyc b/venv/Lib/site-packages/setuptools/command/__pycache__/build_clib.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..89aab0396d657193e76fb9ea85091cddae35a2d2 GIT binary patch literal 2463 zcma)8PmkO*6nC6VCYzbr-L_B=D&PxDr(#Dc+*Sx$brC|U7NnL-G$r!Hp4n`ZIJKQ_ zXO+3IJ#eYiPk?s0@s)Dm!ild?p_b=l{%ysf9>sZn^Zxw&-t%*4ujeBezkT}o_}eQ8 z{cRST!-2&ec+`EE7-Cj}QVSysr8uxH!@-G@wt`ko+liaDgLX|jiI;8#TNe5ru@-Zm zBj$4Z7@yezX4V5VX#WEi(c!?Vt{ucm7dlSV1FnnwJ1K<(ww;J6yxzhh z88c4w5hsjKXpv~L79?YSM4!f@kVFf@L@hQENg__-Y`X8)Hf|5e4{4t8lxLbyA`2E9 zlFAv;Kq*brd~Zw@XW${{8RJBHdBgi977Km8m*u?A7&_}T%>PQp`gFwO7*Ir3V^Bh71Ou)E;a7q0n)<-pR z1@VnInZV{VnnErFs3lMtL`?o)brnZIJtRLXa1Mb=a}9CT()cx7nI>XPlXtMN61hd9 zNkXRzaIQnN!a^uxaUIr#G-7}>r^=*YW#ZBnOo^?vxHg1yVz8m5#>Rp5QaA_O-)siLawG>sL$T(m4Z3-8y%f zUE&LDp<3V3?K5M#HZ)+;h-3)RR9-bnG8@N(bIu)_#HK9o;M4 zvU7%~Xo@EIvHjAL59_^n5Q}b2f$qFlQ($ktUEA1hY?R%yR~pU^>%4FQow2`Lc1jG? zm73pu;ecm|DKv)OVbyL5P@PWVjP#*DNGhSQ`b6X=+vH}$nvwozsz3OG^cV7dk`_>; zQ2M##sy_W09Lxo8T{dskw>o{lKB}fnjYTMR<8fAb%kz0UdPg8jg*B2(hfqw2p5@RQ z8U*|Gq3Tx%daExAofkS}v8>#bMpCG%8)s2cFm9Nta+{+tXh~C|(p(m@15>cgpJ_?M zTtH`&Q&qJX9~aXBZsd9(GPqjVQ?4sNR&fSWS;Q;H9O$YAT|VK`90F;>R5_+!RgUQ# zl?#TUJytIC4)gYwM<>{A8dA7y5o+1Zp@rts+*DP2DQo})S0c%&<{>!OaTJ;ew}3y` zsT{?VNwu}ga^L|On!Xb(ZU}=&x*#pv##DE+*#w=Ysnl(>a+|mYo{~|`3H&BDrpX4o z{24S^%~{x>SL+zcE?E8($s6!`^~=5e5wtL=Ml{Q)8r{wF1FGrhzKCctdI&ol<#E1O zWI2rU+HwD%+0BVNYn^IkkX8e))&|?pH(}}a<$_Rz^N)>Le{qB zTh}dYVT@nnH;&`sZp-l29LL!PsnxpeSuXs4iRbuM7rP+iymnpq{|#7b`yl0mEO3ps zdB1YIW^Fjmzo#E7tpSmz`RD?bcV!HR?f-3`Mh1x-x0VAT#oCZaHupTJ(~ zSZ+)o8=lFzNun|(;#tm4Qw4r-gDpQihKryL*Ldn$GJ&k6D@Vw9TJ5ei;FCc}RTpu! twPM%x99&zcV+d6cnva{hKsTV7tV@Hh^1g1i_6_uYq&%3eT3z$A{{sW+w;=!k literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/command/__pycache__/build_ext.cpython-39.pyc b/venv/Lib/site-packages/setuptools/command/__pycache__/build_ext.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..956831cfc0c9bd4d95beac54f706780bc466c8e7 GIT binary patch literal 9822 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/command/__pycache__/build_py.cpython-39.pyc b/venv/Lib/site-packages/setuptools/command/__pycache__/build_py.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d749a4d2b393ea0ade4d62c231dcbb8d3c98ee05 GIT binary patch literal 8209 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 bWSVuCgeNBLAY4ds|NOsZ*yie=XutnI{r@Qt literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/command/__pycache__/develop.cpython-39.pyc b/venv/Lib/site-packages/setuptools/command/__pycache__/develop.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4fd1f67c48c4e3599890d09c4ccf33adb57b158c GIT binary patch literal 6132 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 tU3UjHwl*)!Jgc?R=;htNLO|dMnXgmM_ literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/command/__pycache__/easy_install.cpython-39.pyc b/venv/Lib/site-packages/setuptools/command/__pycache__/easy_install.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c1c359bbb19f17ace93581743dd15ee1a4153d73 GIT binary patch literal 64328 zcmce<3!Gfnecw0lnVo%L0W6*b$sq_3SQ5JcA&L+1A%b|2kiaEGfTTF4JRIzuUCd&3 zW^wN*v-gzv**l9oQ0(0)`oO91T=YRg^|31~x(PDzXx9@%6;?JE+CVp2J{eJ~6 zp5+((UOJKR66J)K^iqxFVzQh}>O9>@EvCz9JI`>QDQ6b5<*Z$28@a`NIlova7Z!)g zLyN_7(eCFO!;2&3k;T#Ss9on9V~d;0o9w*M7+>66-fZVXjV+5?%UkWd*qA6!@V;VW zTX~xux0kouaYuQF9e0*@+HqHTmmPPPciZu<@?Cb^Q{H38yUTam@t*QMcD%QIuN_O} zk{$0W-)G0Y<-K;izkI(P_m%hAaesNg9Umw^z;U?oz~X`O0c+z(ys*&>+ZMiS?G5jP-lOX&@3G6NcT)ZrYvuCm-s9dA zl>fMQ%zKjKcY9BHPjjqz&v+l=_@>wNp7oBul`L1i=e!f#x#*qrPH~*|PS++DysHUn z`mNe*xz;Rr&wDTMq~^7}4|^Y>%$#@DdyzZy-i-GW$4lNh@1q>+opHwg<;J$fh4STO z;|V)>==L zm$?7BSLQyA;Qke^zsq}r>o;zu%05>g_r9B}@2>eg4Y;m&Z*u)+E#SIc^B0!O%cNJ! zSG}rtkvCoQW<8JNb+1oEYHc+Sm4aHW)V@?JRcB{gi%Zq!ie9TGMlGCfUvC%ZD0!$vEm!M7 zy>0p5?8{TS)LN{SmU!EnmCAInSgDjQwcAU#f7J=HW)Q zT?^WWz1osro8_FZ;*FKM>y+tB?Zrm1_$^_}$z+(BZ?rCQ9GS1RD@zomdln~C;mB;O zd9~(quiCy87K7!BLA!Fb>IajVaP!HyQ;z%dr+mNVhZEgfFD>cQ-QBV7U3a~`dwni? zlilZa=|*clEO>RlqRys0qjPniH#X|cTE(w%W7Ax{=~ZgiYqQJk>cxg`<)crU;k;n& zr>>Ip6J4@f6=QbkU=qDz$mO zjD!K0Yf*RhwM(^HV{$YcYtq%#M!i#WoxI7f1+8U&wpIz+J}nK$^-Ze7uV18FTFr2a zbwdBGARIo`yju5LO|>E%e!17Aa75kREz1|QFTDt$dewH7QuFiOi{fi7|1xi+-`q&X zg=Sjq)2-#E7jAmB<_EOkM5{U1sL!^k`_!wa&c1Z6a`Mdi3*SmPU>dJAgJr))n}NJ` z%U|Jhhga&ghGzpAgn6$vS6yzXiwgqHdF9E5g`m1v(=-T2`av}uKi9t0{|!O7HJYH6 zYjp;b-kqI``U%LW0Pu75>$PB3z}^1`5s)~+FBl_fC)Sc)avg%;atg$eo(YrZz9oWz zG0V|m%X}WKYs>}=&DRqCqdc4bXug@Qwb@We$ghdQf@vk&E^Aj9RO1 zO(gxtNoVa`*Zk%9W%=1BEpXCKEF{-btBLhwYkPFg2i{1v)4KAKH&d+#R#P|9t7-q3 zJlhH765 zN{m3wuQg{K-qX02G_c?;6*|5=FE9;CEie}Or{jSKHJ7ddgr!!q^coYrbuB2-KUOGM zUSeQ_pca&BLN3`o$D%uJZA2DA10h0~KM|2YbWBd;{;YLek_UzKibSH2!tnK_;XMzAMS$zn2> z97*~waPPL(Ww>dr+s=vRsX%fqwVqf@L%5^_ur^R-<_Q62 zh4GfcykBE6o7F0jQJ#%0D^^-8ELvUsrWzN`w3pNc6qzKyK1?G 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 bUat<wW(R7d3V` literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/command/__pycache__/egg_info.cpython-39.pyc b/venv/Lib/site-packages/setuptools/command/__pycache__/egg_info.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..deac943313b0b0c1794cbbe0761f6d86eb4b97a0 GIT binary patch literal 22519 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/command/__pycache__/install_scripts.cpython-39.pyc b/venv/Lib/site-packages/setuptools/command/__pycache__/install_scripts.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1856c04e05d693046c41346bda79c343dbe76df7 GIT binary patch literal 2441 zcmZuzOK%)S5bo}I?#p&;=Vby}K#8MERd3SkwFx{wU%kHb0gV2{ z$?3<1$!%yVhmI3Yb5hWVQXI3K6%Hem6mH~MiIe+95CzNCFbb_!D{8^p&D%vM>J;6m z3+o>D^IowMtx$5G@PLQU2oHrfb`PD%;GX}WTK{$UrATz(yB0JXiAxX{4*5YOTJ*6Q z#G@f|$Q4GWA!B#!$@jEB4(8z^TBSb%dEA1vw)_mE2KpV;pE2ES*tn-xu!pvK$e>?? zcJ9!fIabdBJy)+chyrrx%)IHAm3tufLGE*(2Otj~lXA-?dP8sSvV-3#a04FrFioFAjpw8al1o#Z`!U8^j=kNgZ|*Ex%wj2+sjmMi$om&iY@w0u#}qaOX3dL zi%*ttyA!4cOTtLZ>;kwBXq&K_=-n(AN@Cj0`H|4^ZdO`2^J7~Qu@u=;?j!(U4{fZX zzLk|pA)*e(;Clc!)`bAfBw9<;`J$*RscrR;NUx~-$TIh_%(Rfv#^bEy)xJ6{G>$q@ z@*J9XcLaoLeR-r<)gq14JW%yRN;2Ap*&6gdb>ZjJw&Sx9B%5@)ah9%_CaP1*XEY5D zk{pw8ADa3JI-n>+iq5=(&3sC!d28No0!v~45Gg>$ z9rYv7GdKiV>s}LZw{b3#Lk4tc&4I91w>4iq0tz%9tOI>6!8(x6hr$?4Z`!0n$?d;@ zeILQq*HvHdiQ~H4Ke-t!ec)E{(!HYMrk75n6s3+QMWUWex4u}w9T?KTrjF}7*t(_+ z-Ov63?mZl=$qhKa#G6FEjUC=X#>ILcb&f*`8yZ$Ai--!;m3>9e}dIn;aR$L9e5Yg5aQc){sj&ao_+uT literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/command/__pycache__/py36compat.cpython-39.pyc b/venv/Lib/site-packages/setuptools/command/__pycache__/py36compat.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..454f3ef5013df41ec6f604ad309ae7d2c93adf4c GIT binary patch literal 4584 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/command/__pycache__/rotate.cpython-39.pyc b/venv/Lib/site-packages/setuptools/command/__pycache__/rotate.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5ec41fd4d449f527babe250b16d1d0ec4b71c12c GIT binary patch literal 2499 zcmZ`*&2Jk;6rb4-d%bbe5JF3#Dl2G647Jq)5(t&5s6kvHfLcIUu2yT$*x6*iGBZn+ zmCd0kQm@=N+T7qz;BVkBm@6mF+`gv*xQva4Deslo0inx@qy@K$w1|S5eHj>AC$4+tOZLOcw(Ey0#>tX z0~kI~xi}2&?{dKdwad@i6hwl0qe*AHz=Lu1fI`5IKjblz zx1q`NKo}X5a84njz*~$!oaj!=)~>Nzd#E-93$=s#AW4qo$?$g~RzShy?(L6z-%2iI zFUqn=_C76&?MOwvFY-Z@^zQPs=oN9%F0&#U>~q!z2YJ%IUPgQO-&bi*a#a>8&lA}j z%v0Z+XQ)#g>a{qFRU9R8#lzeH#TYGXa4?}Y_*EAdtDj$a#&L8SFNJaZS763u58N(^ zSW}eIBl>`X1e^!S6_8jcsaBPZ(j%A)t?xIjCktH6@VTt1@Kyya7iO~vnOg&a--ps;l2BB~4RNs7A0cu^f-**@J9md%i9CU6Z2rzjQnB#qq z=~eCa5w39N66`mm)ex9@fmKg5foL0?(*Ac*QgTyxv>(ejlPbyvT-#tK*jgm9(ystI z!!lzWPUq|xf}ngE)lmMd53A2w`8uqVmw^!KQ;S+p9LJ{~aI18M2DAwX_Mdomb>V-! zJQH?AJvM{kzkmVkK=Gbo;kKBa(3B!B5wY9k-X9YSID6{MplDwpW9tF|303Z1ZCZyJ zZ*0u~*%O<&toD$MZA9e69^2E#jDQw<>SM2#rcG8?%VR{kHM4OBcCRqiw`Y4e5n$g>spy5akk&884w#wbbV1jv}@{trb=w!`B>mjT~Qmd7LG|5)U_sF++`2i4j?dCml4)M$T^N!q(H TkHJlZy2P@Cp=+8zHtqiaIkA)A literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/command/__pycache__/saveopts.cpython-39.pyc b/venv/Lib/site-packages/setuptools/command/__pycache__/saveopts.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9305219dc839df35a1933af5f78eee7f379a2d57 GIT binary patch literal 918 zcmYjPO>Yx15cS6vU| zQ+wddFKCbaC0{x57dSCaw-8G+vd7~$^WK=RulEtG?=M~*{~!qc@`u$Gz~McZ*#;+& zz!}PMjB^qbj6NYj1ieOrN^(VGDuN?4?EHpIG$d|K3T0VZ785mfYh`6sS+HYnWa<-E z7ZkoL@(eZ-#aN)22n>KE4g|nnqqrkF0N!<>;pY;-%>3mM?4q>Hb6$v1rV1I|6)}-5 zBOXmuCg*Q_dSvRV%9IqV2}atw8mE(KRO+a-CsG5J?{)bw#VZZ=VDD`o%$$I0&?#DA zg%+g2r}zMU`?#PD75I$k=d;ZQ-;jph;v0I4;BGr1ivX;%=r$ceAZMrPHsmH~s6w}- z3HH!zXSQiOfC_Q&y(@}AY~V`|wV%Lz(9(=N&0**ULK&;oaqUHQ8|^J?`MZs&wC#Zj zm0H(PR_4a_fwYhlUT0Q&(Ou|8DtInkPv}dg>tfh*fsxt71-=BxEv;3>)Hs^v!cnN; zsL`pT=REs~^dms|lkC4uz8a}b!i$2N^*aLbd=Wy-VUi_EK}Qq`y~DxRK6F}gUB zG8^sI{Pg0r&6DLMY*}U|X^ABFLmpR`jzU)tpp1D44&g2iNS}n5kf%7rTVy`?mkf!A z{);f?DKX~yjOC@MGru1&HmiBo-t-s~WeVXnAx)~)@^|XTP+&=E#clbRAA&d21s6gG t0a?Zlhe7=0fB)mQ|1pF>sinr6-UF+Z(Kn!$+V@Y+_>B6(E}`OODARGa7Bru11=j z8FkNE*08Fg%C3TgdP7)W&+_>|X^p%ruRB_`#_`ROlFDYDDRrmDt^z`(5{oe2W zUdvlpsA~BA=FO{H%dczNKj>!qSHjIlC}N0;X-p5bzTVb#Y8#=^Hw{hK`c}JC^px9W z^`z3SsH@$!)pf2t$4q90)&6{Y9%D+LhF#%wnCLT@iV&{&ntztGsc zKkt`ztmjtSV#b=*Sa^jMXboMOVccuI(({`o!2*%G9%C-^yWSv7#VaF!WcU5lV_xb> ztwWY*_-K8KKdm-lMS#6qm> zo%=z=94`!=ZV>vy8AQzI4)>o1B8VfW6GthJ!|a0a(?OEPaVVNJ(Cy+ip9{!P>hXAx zv>GNaV*#?}<#oSv&-yj zxL#ma*qgXsWDff}uCM=Ev$Xal?Ce{zr1X&8Uh8{2b<~ZMZhI*O<{>0?t3XM)8n1(;Hj_7^tw

    9yQSoKf|Zuz{m7?D2iZrT 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 F{{nbv_C5dr literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/command/__pycache__/setopt.cpython-39.pyc b/venv/Lib/site-packages/setuptools/command/__pycache__/setopt.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a099f50d5473a8bbd2f54ada234d9b517bfa340d GIT binary patch literal 4669 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/command/__pycache__/upload_docs.cpython-39.pyc b/venv/Lib/site-packages/setuptools/command/__pycache__/upload_docs.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d5c7539388ac22925c97392002bdb9462dc14f08 GIT binary patch literal 6167 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 OK_EEw2ZZXTYyB^>LyMmP literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/command/alias.py b/venv/Lib/site-packages/setuptools/command/alias.py new file mode 100644 index 0000000..452a924 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/command/alias.py @@ -0,0 +1,78 @@ +from distutils.errors import DistutilsOptionError + +from setuptools.command.setopt import edit_config, option_base, config_file + + +def shquote(arg): + """Quote an argument for later parsing by shlex.split()""" + for c in '"', "'", "\\", "#": + if c in arg: + return repr(arg) + if arg.split() != [arg]: + return repr(arg) + return arg + + +class alias(option_base): + """Define a shortcut that invokes one or more commands""" + + description = "define a shortcut to invoke one or more commands" + command_consumes_arguments = True + + user_options = [ + ('remove', 'r', 'remove (unset) the alias'), + ] + option_base.user_options + + boolean_options = option_base.boolean_options + ['remove'] + + def initialize_options(self): + option_base.initialize_options(self) + self.args = None + self.remove = None + + def finalize_options(self): + option_base.finalize_options(self) + if self.remove and len(self.args) != 1: + raise DistutilsOptionError( + "Must specify exactly one argument (the alias name) when " + "using --remove" + ) + + def run(self): + aliases = self.distribution.get_option_dict('aliases') + + if not self.args: + print("Command Aliases") + print("---------------") + for alias in aliases: + print("setup.py alias", format_alias(alias, aliases)) + return + + elif len(self.args) == 1: + alias, = self.args + if self.remove: + command = None + elif alias in aliases: + print("setup.py alias", format_alias(alias, aliases)) + return + else: + print("No alias definition found for %r" % alias) + return + else: + alias = self.args[0] + command = ' '.join(map(shquote, self.args[1:])) + + edit_config(self.filename, {'aliases': {alias: command}}, self.dry_run) + + +def format_alias(name, aliases): + source, command = aliases[name] + if source == config_file('global'): + source = '--global-config ' + elif source == config_file('user'): + source = '--user-config ' + elif source == config_file('local'): + source = '' + else: + source = '--filename=%r' % source + return source + name + ' ' + command diff --git a/venv/Lib/site-packages/setuptools/command/bdist_egg.py b/venv/Lib/site-packages/setuptools/command/bdist_egg.py new file mode 100644 index 0000000..11a1c6b --- /dev/null +++ b/venv/Lib/site-packages/setuptools/command/bdist_egg.py @@ -0,0 +1,457 @@ +"""setuptools.command.bdist_egg + +Build .egg distributions""" + +from distutils.dir_util import remove_tree, mkpath +from distutils import log +from types import CodeType +import sys +import os +import re +import textwrap +import marshal + +from pkg_resources import get_build_platform, Distribution +from setuptools.extension import Library +from setuptools import Command +from .._path import ensure_directory + +from sysconfig import get_path, get_python_version + + +def _get_purelib(): + return get_path("purelib") + + +def strip_module(filename): + if '.' in filename: + filename = os.path.splitext(filename)[0] + if filename.endswith('module'): + filename = filename[:-6] + return filename + + +def sorted_walk(dir): + """Do os.walk in a reproducible way, + independent of indeterministic filesystem readdir order + """ + for base, dirs, files in os.walk(dir): + dirs.sort() + files.sort() + yield base, dirs, files + + +def write_stub(resource, pyfile): + _stub_template = textwrap.dedent(""" + def __bootstrap__(): + global __bootstrap__, __loader__, __file__ + import sys, pkg_resources, importlib.util + __file__ = pkg_resources.resource_filename(__name__, %r) + __loader__ = None; del __bootstrap__, __loader__ + spec = importlib.util.spec_from_file_location(__name__,__file__) + mod = importlib.util.module_from_spec(spec) + spec.loader.exec_module(mod) + __bootstrap__() + """).lstrip() + with open(pyfile, 'w') as f: + f.write(_stub_template % resource) + + +class bdist_egg(Command): + description = "create an \"egg\" distribution" + + user_options = [ + ('bdist-dir=', 'b', + "temporary directory for creating the distribution"), + ('plat-name=', 'p', "platform name to embed in generated filenames " + "(default: %s)" % get_build_platform()), + ('exclude-source-files', None, + "remove all .py files from the generated egg"), + ('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)"), + ] + + boolean_options = [ + 'keep-temp', 'skip-build', 'exclude-source-files' + ] + + def initialize_options(self): + self.bdist_dir = None + self.plat_name = None + self.keep_temp = 0 + self.dist_dir = None + self.skip_build = 0 + self.egg_output = None + self.exclude_source_files = None + + def finalize_options(self): + ei_cmd = self.ei_cmd = self.get_finalized_command("egg_info") + self.egg_info = ei_cmd.egg_info + + if self.bdist_dir is None: + bdist_base = self.get_finalized_command('bdist').bdist_base + self.bdist_dir = os.path.join(bdist_base, 'egg') + + if self.plat_name is None: + self.plat_name = get_build_platform() + + self.set_undefined_options('bdist', ('dist_dir', 'dist_dir')) + + if self.egg_output is None: + + # Compute filename of the output egg + basename = Distribution( + None, None, ei_cmd.egg_name, ei_cmd.egg_version, + get_python_version(), + self.distribution.has_ext_modules() and self.plat_name + ).egg_name() + + self.egg_output = os.path.join(self.dist_dir, basename + '.egg') + + def do_install_data(self): + # Hack for packages that install data to install's --install-lib + self.get_finalized_command('install').install_lib = self.bdist_dir + + site_packages = os.path.normcase(os.path.realpath(_get_purelib())) + old, self.distribution.data_files = self.distribution.data_files, [] + + for item in old: + if isinstance(item, tuple) and len(item) == 2: + if os.path.isabs(item[0]): + realpath = os.path.realpath(item[0]) + normalized = os.path.normcase(realpath) + if normalized == site_packages or normalized.startswith( + site_packages + os.sep + ): + item = realpath[len(site_packages) + 1:], item[1] + # XXX else: raise ??? + self.distribution.data_files.append(item) + + try: + log.info("installing package data to %s", self.bdist_dir) + self.call_command('install_data', force=0, root=None) + finally: + self.distribution.data_files = old + + def get_outputs(self): + return [self.egg_output] + + def call_command(self, cmdname, **kw): + """Invoke reinitialized command `cmdname` with keyword args""" + for dirname in INSTALL_DIRECTORY_ATTRS: + kw.setdefault(dirname, self.bdist_dir) + kw.setdefault('skip_build', self.skip_build) + kw.setdefault('dry_run', self.dry_run) + cmd = self.reinitialize_command(cmdname, **kw) + self.run_command(cmdname) + return cmd + + def run(self): # noqa: C901 # is too complex (14) # FIXME + # Generate metadata first + self.run_command("egg_info") + # We run install_lib before install_data, because some data hacks + # pull their data path from the install_lib command. + log.info("installing library code to %s", self.bdist_dir) + instcmd = self.get_finalized_command('install') + old_root = instcmd.root + instcmd.root = None + if self.distribution.has_c_libraries() and not self.skip_build: + self.run_command('build_clib') + cmd = self.call_command('install_lib', warn_dir=0) + instcmd.root = old_root + + all_outputs, ext_outputs = self.get_ext_outputs() + self.stubs = [] + to_compile = [] + for (p, ext_name) in enumerate(ext_outputs): + filename, ext = os.path.splitext(ext_name) + pyfile = os.path.join(self.bdist_dir, strip_module(filename) + + '.py') + self.stubs.append(pyfile) + log.info("creating stub loader for %s", ext_name) + if not self.dry_run: + write_stub(os.path.basename(ext_name), pyfile) + to_compile.append(pyfile) + ext_outputs[p] = ext_name.replace(os.sep, '/') + + if to_compile: + cmd.byte_compile(to_compile) + if self.distribution.data_files: + self.do_install_data() + + # Make the EGG-INFO directory + archive_root = self.bdist_dir + egg_info = os.path.join(archive_root, 'EGG-INFO') + self.mkpath(egg_info) + if self.distribution.scripts: + script_dir = os.path.join(egg_info, 'scripts') + log.info("installing scripts to %s", script_dir) + self.call_command('install_scripts', install_dir=script_dir, + no_ep=1) + + self.copy_metadata_to(egg_info) + native_libs = os.path.join(egg_info, "native_libs.txt") + if all_outputs: + log.info("writing %s", native_libs) + if not self.dry_run: + ensure_directory(native_libs) + libs_file = open(native_libs, 'wt') + libs_file.write('\n'.join(all_outputs)) + libs_file.write('\n') + libs_file.close() + elif os.path.isfile(native_libs): + log.info("removing %s", native_libs) + if not self.dry_run: + os.unlink(native_libs) + + write_safety_flag( + os.path.join(archive_root, 'EGG-INFO'), self.zip_safe() + ) + + if os.path.exists(os.path.join(self.egg_info, 'depends.txt')): + log.warn( + "WARNING: 'depends.txt' will not be used by setuptools 0.6!\n" + "Use the install_requires/extras_require setup() args instead." + ) + + if self.exclude_source_files: + self.zap_pyfiles() + + # Make the archive + make_zipfile(self.egg_output, archive_root, verbose=self.verbose, + dry_run=self.dry_run, mode=self.gen_header()) + if not self.keep_temp: + remove_tree(self.bdist_dir, dry_run=self.dry_run) + + # Add to 'Distribution.dist_files' so that the "upload" command works + getattr(self.distribution, 'dist_files', []).append( + ('bdist_egg', get_python_version(), self.egg_output)) + + def zap_pyfiles(self): + log.info("Removing .py files from temporary directory") + for base, dirs, files in walk_egg(self.bdist_dir): + for name in files: + path = os.path.join(base, name) + + if name.endswith('.py'): + log.debug("Deleting %s", path) + os.unlink(path) + + if base.endswith('__pycache__'): + path_old = path + + pattern = r'(?P.+)\.(?P[^.]+)\.pyc' + m = re.match(pattern, name) + path_new = os.path.join( + base, os.pardir, m.group('name') + '.pyc') + log.info( + "Renaming file from [%s] to [%s]" + % (path_old, path_new)) + try: + os.remove(path_new) + except OSError: + pass + os.rename(path_old, path_new) + + def zip_safe(self): + safe = getattr(self.distribution, 'zip_safe', None) + if safe is not None: + return safe + log.warn("zip_safe flag not set; analyzing archive contents...") + return analyze_egg(self.bdist_dir, self.stubs) + + def gen_header(self): + return 'w' + + def copy_metadata_to(self, target_dir): + "Copy metadata (egg info) to the target_dir" + # normalize the path (so that a forward-slash in egg_info will + # match using startswith below) + norm_egg_info = os.path.normpath(self.egg_info) + prefix = os.path.join(norm_egg_info, '') + for path in self.ei_cmd.filelist.files: + if path.startswith(prefix): + target = os.path.join(target_dir, path[len(prefix):]) + ensure_directory(target) + self.copy_file(path, target) + + def get_ext_outputs(self): + """Get a list of relative paths to C extensions in the output distro""" + + all_outputs = [] + ext_outputs = [] + + paths = {self.bdist_dir: ''} + for base, dirs, files in sorted_walk(self.bdist_dir): + for filename in files: + if os.path.splitext(filename)[1].lower() in NATIVE_EXTENSIONS: + all_outputs.append(paths[base] + filename) + for filename in dirs: + paths[os.path.join(base, filename)] = (paths[base] + + filename + '/') + + if self.distribution.has_ext_modules(): + build_cmd = self.get_finalized_command('build_ext') + for ext in build_cmd.extensions: + if isinstance(ext, Library): + continue + fullname = build_cmd.get_ext_fullname(ext.name) + filename = build_cmd.get_ext_filename(fullname) + if not os.path.basename(filename).startswith('dl-'): + if os.path.exists(os.path.join(self.bdist_dir, filename)): + ext_outputs.append(filename) + + return all_outputs, ext_outputs + + +NATIVE_EXTENSIONS = dict.fromkeys('.dll .so .dylib .pyd'.split()) + + +def walk_egg(egg_dir): + """Walk an unpacked egg's contents, skipping the metadata directory""" + walker = sorted_walk(egg_dir) + base, dirs, files = next(walker) + if 'EGG-INFO' in dirs: + dirs.remove('EGG-INFO') + yield base, dirs, files + for bdf in walker: + yield bdf + + +def analyze_egg(egg_dir, stubs): + # check for existing flag in EGG-INFO + for flag, fn in safety_flags.items(): + if os.path.exists(os.path.join(egg_dir, 'EGG-INFO', fn)): + return flag + if not can_scan(): + return False + safe = True + for base, dirs, files in walk_egg(egg_dir): + for name in files: + if name.endswith('.py') or name.endswith('.pyw'): + continue + elif name.endswith('.pyc') or name.endswith('.pyo'): + # always scan, even if we already know we're not safe + safe = scan_module(egg_dir, base, name, stubs) and safe + return safe + + +def write_safety_flag(egg_dir, safe): + # Write or remove zip safety flag file(s) + for flag, fn in safety_flags.items(): + fn = os.path.join(egg_dir, fn) + if os.path.exists(fn): + if safe is None or bool(safe) != flag: + os.unlink(fn) + elif safe is not None and bool(safe) == flag: + f = open(fn, 'wt') + f.write('\n') + f.close() + + +safety_flags = { + True: 'zip-safe', + False: 'not-zip-safe', +} + + +def scan_module(egg_dir, base, name, stubs): + """Check whether module possibly uses unsafe-for-zipfile stuff""" + + filename = os.path.join(base, name) + if filename[:-1] in stubs: + return True # Extension module + pkg = base[len(egg_dir) + 1:].replace(os.sep, '.') + module = pkg + (pkg and '.' or '') + os.path.splitext(name)[0] + if sys.version_info < (3, 7): + skip = 12 # skip magic & date & file size + else: + skip = 16 # skip magic & reserved? & date & file size + f = open(filename, 'rb') + f.read(skip) + code = marshal.load(f) + f.close() + safe = True + symbols = dict.fromkeys(iter_symbols(code)) + for bad in ['__file__', '__path__']: + if bad in symbols: + log.warn("%s: module references %s", module, bad) + safe = False + if 'inspect' in symbols: + for bad in [ + 'getsource', 'getabsfile', 'getsourcefile', 'getfile' + 'getsourcelines', 'findsource', 'getcomments', 'getframeinfo', + 'getinnerframes', 'getouterframes', 'stack', 'trace' + ]: + if bad in symbols: + log.warn("%s: module MAY be using inspect.%s", module, bad) + safe = False + return safe + + +def iter_symbols(code): + """Yield names and strings used by `code` and its nested code objects""" + for name in code.co_names: + yield name + for const in code.co_consts: + if isinstance(const, str): + yield const + elif isinstance(const, CodeType): + for name in iter_symbols(const): + yield name + + +def can_scan(): + if not sys.platform.startswith('java') and sys.platform != 'cli': + # CPython, PyPy, etc. + return True + log.warn("Unable to analyze compiled code on this platform.") + log.warn("Please ask the author to include a 'zip_safe'" + " setting (either True or False) in the package's setup.py") + + +# Attribute names of options for commands that might need to be convinced to +# install to the egg build directory + +INSTALL_DIRECTORY_ATTRS = [ + 'install_lib', 'install_dir', 'install_data', 'install_base' +] + + +def make_zipfile(zip_filename, base_dir, verbose=0, dry_run=0, compress=True, + mode='w'): + """Create a zip file from all the files under 'base_dir'. The output + zip file will be named 'base_dir' + ".zip". Uses either the "zipfile" + Python module (if available) or the InfoZIP "zip" utility (if installed + and found on the default search path). If neither tool is available, + raises DistutilsExecError. Returns the name of the output zip file. + """ + import zipfile + + mkpath(os.path.dirname(zip_filename), dry_run=dry_run) + log.info("creating '%s' and adding '%s' to it", zip_filename, base_dir) + + def visit(z, dirname, names): + for name in names: + path = os.path.normpath(os.path.join(dirname, name)) + if os.path.isfile(path): + p = path[len(base_dir) + 1:] + if not dry_run: + z.write(path, p) + log.debug("adding '%s'", p) + + compression = zipfile.ZIP_DEFLATED if compress else zipfile.ZIP_STORED + if not dry_run: + z = zipfile.ZipFile(zip_filename, mode, compression=compression) + for dirname, dirs, files in sorted_walk(base_dir): + visit(z, dirname, files) + z.close() + else: + for dirname, dirs, files in sorted_walk(base_dir): + visit(None, dirname, files) + return zip_filename diff --git a/venv/Lib/site-packages/setuptools/command/bdist_rpm.py b/venv/Lib/site-packages/setuptools/command/bdist_rpm.py new file mode 100644 index 0000000..98bf5de --- /dev/null +++ b/venv/Lib/site-packages/setuptools/command/bdist_rpm.py @@ -0,0 +1,40 @@ +import distutils.command.bdist_rpm as orig +import warnings + +from setuptools import SetuptoolsDeprecationWarning + + +class bdist_rpm(orig.bdist_rpm): + """ + Override the default bdist_rpm behavior to do the following: + + 1. Run egg_info to ensure the name and version are properly calculated. + 2. Always run 'install' using --single-version-externally-managed to + disable eggs in RPM distributions. + """ + + def run(self): + warnings.warn( + "bdist_rpm is deprecated and will be removed in a future " + "version. Use bdist_wheel (wheel packages) instead.", + SetuptoolsDeprecationWarning, + ) + + # ensure distro name is up-to-date + self.run_command('egg_info') + + orig.bdist_rpm.run(self) + + def _make_spec_file(self): + spec = orig.bdist_rpm._make_spec_file(self) + spec = [ + line.replace( + "setup.py install ", + "setup.py install --single-version-externally-managed " + ).replace( + "%setup", + "%setup -n %{name}-%{unmangled_version}" + ) + for line in spec + ] + return spec diff --git a/venv/Lib/site-packages/setuptools/command/build_clib.py b/venv/Lib/site-packages/setuptools/command/build_clib.py new file mode 100644 index 0000000..67ce244 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/command/build_clib.py @@ -0,0 +1,101 @@ +import distutils.command.build_clib as orig +from distutils.errors import DistutilsSetupError +from distutils import log +from setuptools.dep_util import newer_pairwise_group + + +class build_clib(orig.build_clib): + """ + Override the default build_clib behaviour to do the following: + + 1. Implement a rudimentary timestamp-based dependency system + so 'compile()' doesn't run every time. + 2. Add more keys to the 'build_info' dictionary: + * obj_deps - specify dependencies for each object compiled. + this should be a dictionary mapping a key + with the source filename to a list of + dependencies. Use an empty string for global + dependencies. + * cflags - specify a list of additional flags to pass to + the compiler. + """ + + def build_libraries(self, libraries): + for (lib_name, build_info) in libraries: + sources = build_info.get('sources') + if sources is None or not isinstance(sources, (list, tuple)): + raise DistutilsSetupError( + "in 'libraries' option (library '%s'), " + "'sources' must be present and must be " + "a list of source filenames" % lib_name) + sources = list(sources) + + log.info("building '%s' library", lib_name) + + # Make sure everything is the correct type. + # obj_deps should be a dictionary of keys as sources + # and a list/tuple of files that are its dependencies. + obj_deps = build_info.get('obj_deps', dict()) + if not isinstance(obj_deps, dict): + raise DistutilsSetupError( + "in 'libraries' option (library '%s'), " + "'obj_deps' must be a dictionary of " + "type 'source: list'" % lib_name) + dependencies = [] + + # Get the global dependencies that are specified by the '' key. + # These will go into every source's dependency list. + global_deps = obj_deps.get('', list()) + if not isinstance(global_deps, (list, tuple)): + raise DistutilsSetupError( + "in 'libraries' option (library '%s'), " + "'obj_deps' must be a dictionary of " + "type 'source: list'" % lib_name) + + # Build the list to be used by newer_pairwise_group + # each source will be auto-added to its dependencies. + for source in sources: + src_deps = [source] + src_deps.extend(global_deps) + extra_deps = obj_deps.get(source, list()) + if not isinstance(extra_deps, (list, tuple)): + raise DistutilsSetupError( + "in 'libraries' option (library '%s'), " + "'obj_deps' must be a dictionary of " + "type 'source: list'" % lib_name) + src_deps.extend(extra_deps) + dependencies.append(src_deps) + + expected_objects = self.compiler.object_filenames( + sources, + output_dir=self.build_temp, + ) + + if ( + newer_pairwise_group(dependencies, expected_objects) + != ([], []) + ): + # First, compile the source code to object files in the library + # directory. (This should probably change to putting object + # files in a temporary build directory.) + macros = build_info.get('macros') + include_dirs = build_info.get('include_dirs') + cflags = build_info.get('cflags') + self.compiler.compile( + sources, + output_dir=self.build_temp, + macros=macros, + include_dirs=include_dirs, + extra_postargs=cflags, + debug=self.debug + ) + + # Now "link" the object files together into a static library. + # (On Unix at least, this isn't really linking -- it just + # builds an archive. Whatever.) + self.compiler.create_static_lib( + expected_objects, + lib_name, + output_dir=self.build_clib, + debug=self.debug + ) diff --git a/venv/Lib/site-packages/setuptools/command/build_ext.py b/venv/Lib/site-packages/setuptools/command/build_ext.py new file mode 100644 index 0000000..c59eff8 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/command/build_ext.py @@ -0,0 +1,328 @@ +import os +import sys +import itertools +from importlib.machinery import EXTENSION_SUFFIXES +from distutils.command.build_ext import build_ext as _du_build_ext +from distutils.file_util import copy_file +from distutils.ccompiler import new_compiler +from distutils.sysconfig import customize_compiler, get_config_var +from distutils.errors import DistutilsError +from distutils import log + +from setuptools.extension import Library + +try: + # Attempt to use Cython for building extensions, if available + from Cython.Distutils.build_ext import build_ext as _build_ext + # Additionally, assert that the compiler module will load + # also. Ref #1229. + __import__('Cython.Compiler.Main') +except ImportError: + _build_ext = _du_build_ext + +# make sure _config_vars is initialized +get_config_var("LDSHARED") +from distutils.sysconfig import _config_vars as _CONFIG_VARS # noqa + + +def _customize_compiler_for_shlib(compiler): + if sys.platform == "darwin": + # building .dylib requires additional compiler flags on OSX; here we + # temporarily substitute the pyconfig.h variables so that distutils' + # 'customize_compiler' uses them before we build the shared libraries. + tmp = _CONFIG_VARS.copy() + try: + # XXX Help! I don't have any idea whether these are right... + _CONFIG_VARS['LDSHARED'] = ( + "gcc -Wl,-x -dynamiclib -undefined dynamic_lookup") + _CONFIG_VARS['CCSHARED'] = " -dynamiclib" + _CONFIG_VARS['SO'] = ".dylib" + customize_compiler(compiler) + finally: + _CONFIG_VARS.clear() + _CONFIG_VARS.update(tmp) + else: + customize_compiler(compiler) + + +have_rtld = False +use_stubs = False +libtype = 'shared' + +if sys.platform == "darwin": + use_stubs = True +elif os.name != 'nt': + try: + import dl + use_stubs = have_rtld = hasattr(dl, 'RTLD_NOW') + except ImportError: + pass + + +def if_dl(s): + return s if have_rtld else '' + + +def get_abi3_suffix(): + """Return the file extension for an abi3-compliant Extension()""" + for suffix in EXTENSION_SUFFIXES: + if '.abi3' in suffix: # Unix + return suffix + elif suffix == '.pyd': # Windows + return suffix + + +class build_ext(_build_ext): + def run(self): + """Build extensions in build directory, then copy if --inplace""" + old_inplace, self.inplace = self.inplace, 0 + _build_ext.run(self) + self.inplace = old_inplace + if old_inplace: + self.copy_extensions_to_source() + + def copy_extensions_to_source(self): + build_py = self.get_finalized_command('build_py') + for ext in self.extensions: + fullname = self.get_ext_fullname(ext.name) + filename = self.get_ext_filename(fullname) + modpath = fullname.split('.') + package = '.'.join(modpath[:-1]) + package_dir = build_py.get_package_dir(package) + dest_filename = os.path.join(package_dir, + os.path.basename(filename)) + src_filename = os.path.join(self.build_lib, filename) + + # Always copy, even if source is older than destination, to ensure + # that the right extensions for the current Python/platform are + # used. + copy_file( + src_filename, dest_filename, verbose=self.verbose, + dry_run=self.dry_run + ) + if ext._needs_stub: + self.write_stub(package_dir or os.curdir, ext, True) + + def get_ext_filename(self, fullname): + so_ext = os.getenv('SETUPTOOLS_EXT_SUFFIX') + if so_ext: + filename = os.path.join(*fullname.split('.')) + so_ext + else: + filename = _build_ext.get_ext_filename(self, fullname) + so_ext = get_config_var('EXT_SUFFIX') + + if fullname in self.ext_map: + ext = self.ext_map[fullname] + use_abi3 = getattr(ext, 'py_limited_api') and get_abi3_suffix() + if use_abi3: + filename = filename[:-len(so_ext)] + so_ext = get_abi3_suffix() + filename = filename + so_ext + if isinstance(ext, Library): + fn, ext = os.path.splitext(filename) + return self.shlib_compiler.library_filename(fn, libtype) + elif use_stubs and ext._links_to_dynamic: + d, fn = os.path.split(filename) + return os.path.join(d, 'dl-' + fn) + return filename + + def initialize_options(self): + _build_ext.initialize_options(self) + self.shlib_compiler = None + self.shlibs = [] + self.ext_map = {} + + def finalize_options(self): + _build_ext.finalize_options(self) + self.extensions = self.extensions or [] + self.check_extensions_list(self.extensions) + self.shlibs = [ext for ext in self.extensions + if isinstance(ext, Library)] + if self.shlibs: + self.setup_shlib_compiler() + for ext in self.extensions: + ext._full_name = self.get_ext_fullname(ext.name) + for ext in self.extensions: + fullname = ext._full_name + self.ext_map[fullname] = ext + + # distutils 3.1 will also ask for module names + # XXX what to do with conflicts? + self.ext_map[fullname.split('.')[-1]] = ext + + ltd = self.shlibs and self.links_to_dynamic(ext) or False + ns = ltd and use_stubs and not isinstance(ext, Library) + ext._links_to_dynamic = ltd + ext._needs_stub = ns + filename = ext._file_name = self.get_ext_filename(fullname) + libdir = os.path.dirname(os.path.join(self.build_lib, filename)) + if ltd and libdir not in ext.library_dirs: + ext.library_dirs.append(libdir) + if ltd and use_stubs and os.curdir not in ext.runtime_library_dirs: + ext.runtime_library_dirs.append(os.curdir) + + def setup_shlib_compiler(self): + compiler = self.shlib_compiler = new_compiler( + compiler=self.compiler, dry_run=self.dry_run, force=self.force + ) + _customize_compiler_for_shlib(compiler) + + if self.include_dirs is not None: + compiler.set_include_dirs(self.include_dirs) + if self.define is not None: + # 'define' option is a list of (name,value) tuples + for (name, value) in self.define: + compiler.define_macro(name, value) + if self.undef is not None: + for macro in self.undef: + compiler.undefine_macro(macro) + if self.libraries is not None: + compiler.set_libraries(self.libraries) + if self.library_dirs is not None: + compiler.set_library_dirs(self.library_dirs) + if self.rpath is not None: + compiler.set_runtime_library_dirs(self.rpath) + if self.link_objects is not None: + compiler.set_link_objects(self.link_objects) + + # hack so distutils' build_extension() builds a library instead + compiler.link_shared_object = link_shared_object.__get__(compiler) + + def get_export_symbols(self, ext): + if isinstance(ext, Library): + return ext.export_symbols + return _build_ext.get_export_symbols(self, ext) + + def build_extension(self, ext): + ext._convert_pyx_sources_to_lang() + _compiler = self.compiler + try: + if isinstance(ext, Library): + self.compiler = self.shlib_compiler + _build_ext.build_extension(self, ext) + if ext._needs_stub: + cmd = self.get_finalized_command('build_py').build_lib + self.write_stub(cmd, ext) + finally: + self.compiler = _compiler + + def links_to_dynamic(self, ext): + """Return true if 'ext' links to a dynamic lib in the same package""" + # XXX this should check to ensure the lib is actually being built + # XXX as dynamic, and not just using a locally-found version or a + # XXX static-compiled version + libnames = dict.fromkeys([lib._full_name for lib in self.shlibs]) + pkg = '.'.join(ext._full_name.split('.')[:-1] + ['']) + return any(pkg + libname in libnames for libname in ext.libraries) + + def get_outputs(self): + return _build_ext.get_outputs(self) + self.__get_stubs_outputs() + + def __get_stubs_outputs(self): + # assemble the base name for each extension that needs a stub + ns_ext_bases = ( + os.path.join(self.build_lib, *ext._full_name.split('.')) + for ext in self.extensions + if ext._needs_stub + ) + # pair each base with the extension + pairs = itertools.product(ns_ext_bases, self.__get_output_extensions()) + return list(base + fnext for base, fnext in pairs) + + def __get_output_extensions(self): + yield '.py' + yield '.pyc' + if self.get_finalized_command('build_py').optimize: + yield '.pyo' + + def write_stub(self, output_dir, ext, compile=False): + log.info("writing stub loader for %s to %s", ext._full_name, + output_dir) + stub_file = (os.path.join(output_dir, *ext._full_name.split('.')) + + '.py') + if compile and os.path.exists(stub_file): + raise DistutilsError(stub_file + " already exists! Please delete.") + if not self.dry_run: + f = open(stub_file, 'w') + f.write( + '\n'.join([ + "def __bootstrap__():", + " global __bootstrap__, __file__, __loader__", + " import sys, os, pkg_resources, importlib.util" + + if_dl(", dl"), + " __file__ = pkg_resources.resource_filename" + "(__name__,%r)" + % os.path.basename(ext._file_name), + " del __bootstrap__", + " if '__loader__' in globals():", + " del __loader__", + if_dl(" old_flags = sys.getdlopenflags()"), + " old_dir = os.getcwd()", + " try:", + " os.chdir(os.path.dirname(__file__))", + if_dl(" sys.setdlopenflags(dl.RTLD_NOW)"), + " spec = importlib.util.spec_from_file_location(", + " __name__, __file__)", + " mod = importlib.util.module_from_spec(spec)", + " spec.loader.exec_module(mod)", + " finally:", + if_dl(" sys.setdlopenflags(old_flags)"), + " os.chdir(old_dir)", + "__bootstrap__()", + "" # terminal \n + ]) + ) + f.close() + if compile: + from distutils.util import byte_compile + + byte_compile([stub_file], optimize=0, + force=True, dry_run=self.dry_run) + optimize = self.get_finalized_command('install_lib').optimize + if optimize > 0: + byte_compile([stub_file], optimize=optimize, + force=True, dry_run=self.dry_run) + if os.path.exists(stub_file) and not self.dry_run: + os.unlink(stub_file) + + +if use_stubs or os.name == 'nt': + # Build shared libraries + # + def link_shared_object( + self, objects, output_libname, output_dir=None, libraries=None, + library_dirs=None, runtime_library_dirs=None, export_symbols=None, + debug=0, extra_preargs=None, extra_postargs=None, build_temp=None, + target_lang=None): + self.link( + self.SHARED_LIBRARY, objects, output_libname, + output_dir, libraries, library_dirs, runtime_library_dirs, + export_symbols, debug, extra_preargs, extra_postargs, + build_temp, target_lang + ) +else: + # Build static libraries everywhere else + libtype = 'static' + + def link_shared_object( + self, objects, output_libname, output_dir=None, libraries=None, + library_dirs=None, runtime_library_dirs=None, export_symbols=None, + debug=0, extra_preargs=None, extra_postargs=None, build_temp=None, + target_lang=None): + # XXX we need to either disallow these attrs on Library instances, + # or warn/abort here if set, or something... + # libraries=None, library_dirs=None, runtime_library_dirs=None, + # export_symbols=None, extra_preargs=None, extra_postargs=None, + # build_temp=None + + assert output_dir is None # distutils build_ext doesn't pass this + output_dir, filename = os.path.split(output_libname) + basename, ext = os.path.splitext(filename) + if self.library_filename("x").startswith('lib'): + # strip 'lib' prefix; this is kludgy if some platform uses + # a different prefix + basename = basename[3:] + + self.create_static_lib( + objects, basename, output_dir, debug, target_lang + ) diff --git a/venv/Lib/site-packages/setuptools/command/build_py.py b/venv/Lib/site-packages/setuptools/command/build_py.py new file mode 100644 index 0000000..c3fdc09 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/command/build_py.py @@ -0,0 +1,242 @@ +from glob import glob +from distutils.util import convert_path +import distutils.command.build_py as orig +import os +import fnmatch +import textwrap +import io +import distutils.errors +import itertools +import stat +from setuptools.extern.more_itertools import unique_everseen + + +def make_writable(target): + os.chmod(target, os.stat(target).st_mode | stat.S_IWRITE) + + +class build_py(orig.build_py): + """Enhanced 'build_py' command that includes data files with packages + + The data files are specified via a 'package_data' argument to 'setup()'. + See 'setuptools.dist.Distribution' for more details. + + Also, this version of the 'build_py' command allows you to specify both + 'py_modules' and 'packages' in the same setup operation. + """ + + def finalize_options(self): + orig.build_py.finalize_options(self) + self.package_data = self.distribution.package_data + self.exclude_package_data = self.distribution.exclude_package_data or {} + if 'data_files' in self.__dict__: + del self.__dict__['data_files'] + self.__updated_files = [] + + def run(self): + """Build modules, packages, and copy data files to build directory""" + if not self.py_modules and not self.packages: + return + + if self.py_modules: + self.build_modules() + + if self.packages: + self.build_packages() + self.build_package_data() + + # Only compile actual .py files, using our base class' idea of what our + # output files are. + self.byte_compile(orig.build_py.get_outputs(self, include_bytecode=0)) + + def __getattr__(self, attr): + "lazily compute data files" + if attr == 'data_files': + self.data_files = self._get_data_files() + return self.data_files + return orig.build_py.__getattr__(self, attr) + + def build_module(self, module, module_file, package): + outfile, copied = orig.build_py.build_module(self, module, module_file, package) + if copied: + self.__updated_files.append(outfile) + return outfile, copied + + def _get_data_files(self): + """Generate list of '(package,src_dir,build_dir,filenames)' tuples""" + self.analyze_manifest() + return list(map(self._get_pkg_data_files, self.packages or ())) + + def get_data_files_without_manifest(self): + """ + Generate list of ``(package,src_dir,build_dir,filenames)`` tuples, + but without triggering any attempt to analyze or build the manifest. + """ + # Prevent eventual errors from unset `manifest_files` + # (that would otherwise be set by `analyze_manifest`) + self.__dict__.setdefault('manifest_files', {}) + return list(map(self._get_pkg_data_files, self.packages or ())) + + def _get_pkg_data_files(self, package): + # Locate package source directory + src_dir = self.get_package_dir(package) + + # Compute package build directory + build_dir = os.path.join(*([self.build_lib] + package.split('.'))) + + # Strip directory from globbed filenames + filenames = [ + os.path.relpath(file, src_dir) + for file in self.find_data_files(package, src_dir) + ] + return package, src_dir, build_dir, filenames + + def find_data_files(self, package, src_dir): + """Return filenames for package's data files in 'src_dir'""" + patterns = self._get_platform_patterns( + self.package_data, + package, + src_dir, + ) + globs_expanded = map(glob, patterns) + # flatten the expanded globs into an iterable of matches + globs_matches = itertools.chain.from_iterable(globs_expanded) + glob_files = filter(os.path.isfile, globs_matches) + files = itertools.chain( + self.manifest_files.get(package, []), + glob_files, + ) + return self.exclude_data_files(package, src_dir, files) + + def build_package_data(self): + """Copy data files into build directory""" + for package, src_dir, build_dir, filenames in self.data_files: + for filename in filenames: + target = os.path.join(build_dir, filename) + self.mkpath(os.path.dirname(target)) + srcfile = os.path.join(src_dir, filename) + outf, copied = self.copy_file(srcfile, target) + make_writable(target) + srcfile = os.path.abspath(srcfile) + + def analyze_manifest(self): + self.manifest_files = mf = {} + if not self.distribution.include_package_data: + return + src_dirs = {} + for package in self.packages or (): + # Locate package source directory + src_dirs[assert_relative(self.get_package_dir(package))] = package + + self.run_command('egg_info') + ei_cmd = self.get_finalized_command('egg_info') + for path in ei_cmd.filelist.files: + d, f = os.path.split(assert_relative(path)) + prev = None + oldf = f + while d and d != prev and d not in src_dirs: + prev = d + d, df = os.path.split(d) + f = os.path.join(df, f) + if d in src_dirs: + if path.endswith('.py') and f == oldf: + continue # it's a module, not data + mf.setdefault(src_dirs[d], []).append(path) + + def get_data_files(self): + pass # Lazily compute data files in _get_data_files() function. + + def check_package(self, package, package_dir): + """Check namespace packages' __init__ for declare_namespace""" + try: + return self.packages_checked[package] + except KeyError: + pass + + init_py = orig.build_py.check_package(self, package, package_dir) + self.packages_checked[package] = init_py + + if not init_py or not self.distribution.namespace_packages: + return init_py + + for pkg in self.distribution.namespace_packages: + if pkg == package or pkg.startswith(package + '.'): + break + else: + return init_py + + with io.open(init_py, 'rb') as f: + contents = f.read() + if b'declare_namespace' not in contents: + raise distutils.errors.DistutilsError( + "Namespace package problem: %s is a namespace package, but " + "its\n__init__.py does not call declare_namespace()! Please " + 'fix it.\n(See the setuptools manual under ' + '"Namespace Packages" for details.)\n"' % (package,) + ) + return init_py + + def initialize_options(self): + self.packages_checked = {} + orig.build_py.initialize_options(self) + + def get_package_dir(self, package): + res = orig.build_py.get_package_dir(self, package) + if self.distribution.src_root is not None: + return os.path.join(self.distribution.src_root, res) + return res + + def exclude_data_files(self, package, src_dir, files): + """Filter filenames for package's data files in 'src_dir'""" + files = list(files) + patterns = self._get_platform_patterns( + self.exclude_package_data, + package, + src_dir, + ) + match_groups = (fnmatch.filter(files, pattern) for pattern in patterns) + # flatten the groups of matches into an iterable of matches + matches = itertools.chain.from_iterable(match_groups) + bad = set(matches) + keepers = (fn for fn in files if fn not in bad) + # ditch dupes + return list(unique_everseen(keepers)) + + @staticmethod + def _get_platform_patterns(spec, package, src_dir): + """ + yield platform-specific path patterns (suitable for glob + or fn_match) from a glob-based spec (such as + self.package_data or self.exclude_package_data) + matching package in src_dir. + """ + raw_patterns = itertools.chain( + spec.get('', []), + spec.get(package, []), + ) + return ( + # Each pattern has to be converted to a platform-specific path + os.path.join(src_dir, convert_path(pattern)) + for pattern in raw_patterns + ) + + +def assert_relative(path): + if not os.path.isabs(path): + return path + from distutils.errors import DistutilsSetupError + + msg = ( + textwrap.dedent( + """ + Error: setup script specifies an absolute path: + + %s + + setup() arguments must *always* be /-separated paths relative to the + setup.py directory, *never* absolute paths. + """ + ).lstrip() + % path + ) + raise DistutilsSetupError(msg) diff --git a/venv/Lib/site-packages/setuptools/command/develop.py b/venv/Lib/site-packages/setuptools/command/develop.py new file mode 100644 index 0000000..24fb0a7 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/command/develop.py @@ -0,0 +1,193 @@ +from distutils.util import convert_path +from distutils import log +from distutils.errors import DistutilsError, DistutilsOptionError +import os +import glob +import io + +import pkg_resources +from setuptools.command.easy_install import easy_install +from setuptools import namespaces +import setuptools + + +class develop(namespaces.DevelopInstaller, easy_install): + """Set up package for development""" + + description = "install package in 'development mode'" + + user_options = easy_install.user_options + [ + ("uninstall", "u", "Uninstall this source package"), + ("egg-path=", None, "Set the path to be used in the .egg-link file"), + ] + + boolean_options = easy_install.boolean_options + ['uninstall'] + + command_consumes_arguments = False # override base + + def run(self): + if self.uninstall: + self.multi_version = True + self.uninstall_link() + self.uninstall_namespaces() + else: + self.install_for_development() + self.warn_deprecated_options() + + def initialize_options(self): + self.uninstall = None + self.egg_path = None + easy_install.initialize_options(self) + self.setup_path = None + self.always_copy_from = '.' # always copy eggs installed in curdir + + def finalize_options(self): + ei = self.get_finalized_command("egg_info") + if ei.broken_egg_info: + template = "Please rename %r to %r before using 'develop'" + args = ei.egg_info, ei.broken_egg_info + raise DistutilsError(template % args) + self.args = [ei.egg_name] + + easy_install.finalize_options(self) + self.expand_basedirs() + self.expand_dirs() + # pick up setup-dir .egg files only: no .egg-info + self.package_index.scan(glob.glob('*.egg')) + + egg_link_fn = ei.egg_name + '.egg-link' + self.egg_link = os.path.join(self.install_dir, egg_link_fn) + self.egg_base = ei.egg_base + if self.egg_path is None: + self.egg_path = os.path.abspath(ei.egg_base) + + target = pkg_resources.normalize_path(self.egg_base) + egg_path = pkg_resources.normalize_path( + os.path.join(self.install_dir, self.egg_path) + ) + if egg_path != target: + raise DistutilsOptionError( + "--egg-path must be a relative path from the install" + " directory to " + target + ) + + # Make a distribution for the package's source + self.dist = pkg_resources.Distribution( + target, + pkg_resources.PathMetadata(target, os.path.abspath(ei.egg_info)), + project_name=ei.egg_name, + ) + + self.setup_path = self._resolve_setup_path( + self.egg_base, + self.install_dir, + self.egg_path, + ) + + @staticmethod + def _resolve_setup_path(egg_base, install_dir, egg_path): + """ + Generate a path from egg_base back to '.' where the + setup script resides and ensure that path points to the + setup path from $install_dir/$egg_path. + """ + path_to_setup = egg_base.replace(os.sep, '/').rstrip('/') + if path_to_setup != os.curdir: + path_to_setup = '../' * (path_to_setup.count('/') + 1) + resolved = pkg_resources.normalize_path( + os.path.join(install_dir, egg_path, path_to_setup) + ) + if resolved != pkg_resources.normalize_path(os.curdir): + raise DistutilsOptionError( + "Can't get a consistent path to setup script from" + " installation directory", + resolved, + pkg_resources.normalize_path(os.curdir), + ) + return path_to_setup + + def install_for_development(self): + self.run_command('egg_info') + + # Build extensions in-place + self.reinitialize_command('build_ext', inplace=1) + self.run_command('build_ext') + + if setuptools.bootstrap_install_from: + self.easy_install(setuptools.bootstrap_install_from) + setuptools.bootstrap_install_from = None + + self.install_namespaces() + + # create an .egg-link in the installation dir, pointing to our egg + log.info("Creating %s (link to %s)", self.egg_link, self.egg_base) + if not self.dry_run: + with open(self.egg_link, "w") as f: + f.write(self.egg_path + "\n" + self.setup_path) + # postprocess the installed distro, fixing up .pth, installing scripts, + # and handling requirements + self.process_distribution(None, self.dist, not self.no_deps) + + def uninstall_link(self): + if os.path.exists(self.egg_link): + log.info("Removing %s (link to %s)", self.egg_link, self.egg_base) + egg_link_file = open(self.egg_link) + contents = [line.rstrip() for line in egg_link_file] + egg_link_file.close() + if contents not in ([self.egg_path], [self.egg_path, self.setup_path]): + log.warn("Link points to %s: uninstall aborted", contents) + return + if not self.dry_run: + os.unlink(self.egg_link) + if not self.dry_run: + self.update_pth(self.dist) # remove any .pth link to us + if self.distribution.scripts: + # XXX should also check for entry point scripts! + log.warn("Note: you must uninstall or replace scripts manually!") + + def install_egg_scripts(self, dist): + if dist is not self.dist: + # Installing a dependency, so fall back to normal behavior + return easy_install.install_egg_scripts(self, dist) + + # create wrapper scripts in the script dir, pointing to dist.scripts + + # new-style... + self.install_wrapper_scripts(dist) + + # ...and old-style + for script_name in self.distribution.scripts or []: + script_path = os.path.abspath(convert_path(script_name)) + script_name = os.path.basename(script_path) + with io.open(script_path) as strm: + script_text = strm.read() + self.install_script(dist, script_name, script_text, script_path) + + def install_wrapper_scripts(self, dist): + dist = VersionlessRequirement(dist) + return easy_install.install_wrapper_scripts(self, dist) + + +class VersionlessRequirement: + """ + Adapt a pkg_resources.Distribution to simply return the project + name as the 'requirement' so that scripts will work across + multiple versions. + + >>> from pkg_resources import Distribution + >>> dist = Distribution(project_name='foo', version='1.0') + >>> str(dist.as_requirement()) + 'foo==1.0' + >>> adapted_dist = VersionlessRequirement(dist) + >>> str(adapted_dist.as_requirement()) + 'foo' + """ + + def __init__(self, dist): + self.__dist = dist + + def __getattr__(self, name): + return getattr(self.__dist, name) + + def as_requirement(self): + return self.project_name diff --git a/venv/Lib/site-packages/setuptools/command/dist_info.py b/venv/Lib/site-packages/setuptools/command/dist_info.py new file mode 100644 index 0000000..c45258f --- /dev/null +++ b/venv/Lib/site-packages/setuptools/command/dist_info.py @@ -0,0 +1,36 @@ +""" +Create a dist_info directory +As defined in the wheel specification +""" + +import os + +from distutils.core import Command +from distutils import log + + +class dist_info(Command): + + description = 'create a .dist-info directory' + + user_options = [ + ('egg-base=', 'e', "directory containing .egg-info directories" + " (default: top of the source tree)"), + ] + + def initialize_options(self): + self.egg_base = None + + def finalize_options(self): + pass + + def run(self): + egg_info = self.get_finalized_command('egg_info') + egg_info.egg_base = self.egg_base + egg_info.finalize_options() + egg_info.run() + dist_info_dir = egg_info.egg_info[:-len('.egg-info')] + '.dist-info' + log.info("creating '{}'".format(os.path.abspath(dist_info_dir))) + + bdist_wheel = self.get_finalized_command('bdist_wheel') + bdist_wheel.egg2dist(egg_info.egg_info, dist_info_dir) diff --git a/venv/Lib/site-packages/setuptools/command/easy_install.py b/venv/Lib/site-packages/setuptools/command/easy_install.py new file mode 100644 index 0000000..5b73e6e --- /dev/null +++ b/venv/Lib/site-packages/setuptools/command/easy_install.py @@ -0,0 +1,2320 @@ +""" +Easy Install +------------ + +A tool for doing automatic download/extract/build of distutils-based Python +packages. For detailed documentation, see the accompanying EasyInstall.txt +file, or visit the `EasyInstall home page`__. + +__ https://setuptools.pypa.io/en/latest/deprecated/easy_install.html + +""" + +from glob import glob +from distutils.util import get_platform +from distutils.util import convert_path, subst_vars +from distutils.errors import ( + DistutilsArgError, DistutilsOptionError, + DistutilsError, DistutilsPlatformError, +) +from distutils import log, dir_util +from distutils.command.build_scripts import first_line_re +from distutils.spawn import find_executable +from distutils.command import install +import sys +import os +import zipimport +import shutil +import tempfile +import zipfile +import re +import stat +import random +import textwrap +import warnings +import site +import struct +import contextlib +import subprocess +import shlex +import io +import configparser +import sysconfig + + +from sysconfig import get_path + +from setuptools import SetuptoolsDeprecationWarning + +from setuptools import Command +from setuptools.sandbox import run_setup +from setuptools.command import setopt +from setuptools.archive_util import unpack_archive +from setuptools.package_index import ( + PackageIndex, parse_requirement_arg, URL_SCHEME, +) +from setuptools.command import bdist_egg, egg_info +from setuptools.wheel import Wheel +from pkg_resources import ( + normalize_path, resource_string, + get_distribution, find_distributions, Environment, Requirement, + Distribution, PathMetadata, EggMetadata, WorkingSet, DistributionNotFound, + VersionConflict, DEVELOP_DIST, +) +import pkg_resources +from .._path import ensure_directory +from ..extern.jaraco.text import yield_lines + + +# Turn on PEP440Warnings +warnings.filterwarnings("default", category=pkg_resources.PEP440Warning) + +__all__ = [ + 'samefile', 'easy_install', 'PthDistributions', 'extract_wininst_cfg', + 'get_exe_prefixes', +] + + +def is_64bit(): + return struct.calcsize("P") == 8 + + +def samefile(p1, p2): + """ + Determine if two paths reference the same file. + + Augments os.path.samefile to work on Windows and + suppresses errors if the path doesn't exist. + """ + both_exist = os.path.exists(p1) and os.path.exists(p2) + use_samefile = hasattr(os.path, 'samefile') and both_exist + if use_samefile: + return os.path.samefile(p1, p2) + norm_p1 = os.path.normpath(os.path.normcase(p1)) + norm_p2 = os.path.normpath(os.path.normcase(p2)) + return norm_p1 == norm_p2 + + +def _to_bytes(s): + return s.encode('utf8') + + +def isascii(s): + try: + s.encode('ascii') + return True + except UnicodeError: + return False + + +def _one_liner(text): + return textwrap.dedent(text).strip().replace('\n', '; ') + + +class easy_install(Command): + """Manage a download/build/install process""" + description = "Find/get/install Python packages" + command_consumes_arguments = True + + user_options = [ + ('prefix=', None, "installation prefix"), + ("zip-ok", "z", "install package as a zipfile"), + ("multi-version", "m", "make apps have to require() a version"), + ("upgrade", "U", "force upgrade (searches PyPI for latest versions)"), + ("install-dir=", "d", "install package to DIR"), + ("script-dir=", "s", "install scripts to DIR"), + ("exclude-scripts", "x", "Don't install scripts"), + ("always-copy", "a", "Copy all needed packages to install dir"), + ("index-url=", "i", "base URL of Python Package Index"), + ("find-links=", "f", "additional URL(s) to search for packages"), + ("build-directory=", "b", + "download/extract/build in DIR; keep the results"), + ('optimize=', 'O', + "also compile with optimization: -O1 for \"python -O\", " + "-O2 for \"python -OO\", and -O0 to disable [default: -O0]"), + ('record=', None, + "filename in which to record list of installed files"), + ('always-unzip', 'Z', "don't install as a zipfile, no matter what"), + ('site-dirs=', 'S', "list of directories where .pth files work"), + ('editable', 'e', "Install specified packages in editable form"), + ('no-deps', 'N', "don't install dependencies"), + ('allow-hosts=', 'H', "pattern(s) that hostnames must match"), + ('local-snapshots-ok', 'l', + "allow building eggs from local checkouts"), + ('version', None, "print version information and exit"), + ('no-find-links', None, + "Don't load find-links defined in packages being installed"), + ('user', None, "install in user site-package '%s'" % site.USER_SITE) + ] + boolean_options = [ + 'zip-ok', 'multi-version', 'exclude-scripts', 'upgrade', 'always-copy', + 'editable', + 'no-deps', 'local-snapshots-ok', 'version', + 'user' + ] + + negative_opt = {'always-unzip': 'zip-ok'} + create_index = PackageIndex + + def initialize_options(self): + warnings.warn( + "easy_install command is deprecated. " + "Use build and pip and other standards-based tools.", + EasyInstallDeprecationWarning, + ) + + # the --user option seems to be an opt-in one, + # so the default should be False. + self.user = 0 + self.zip_ok = self.local_snapshots_ok = None + self.install_dir = self.script_dir = self.exclude_scripts = None + self.index_url = None + self.find_links = None + self.build_directory = None + self.args = None + self.optimize = self.record = None + self.upgrade = self.always_copy = self.multi_version = None + self.editable = self.no_deps = self.allow_hosts = None + self.root = self.prefix = self.no_report = None + self.version = None + self.install_purelib = None # for pure module distributions + self.install_platlib = None # non-pure (dists w/ extensions) + self.install_headers = None # for C/C++ headers + self.install_lib = None # set to either purelib or platlib + self.install_scripts = None + self.install_data = None + self.install_base = None + self.install_platbase = None + if site.ENABLE_USER_SITE: + self.install_userbase = site.USER_BASE + self.install_usersite = site.USER_SITE + else: + self.install_userbase = None + self.install_usersite = None + self.no_find_links = None + + # Options not specifiable via command line + self.package_index = None + self.pth_file = self.always_copy_from = None + self.site_dirs = None + self.installed_projects = {} + # Always read easy_install options, even if we are subclassed, or have + # an independent instance created. This ensures that defaults will + # always come from the standard configuration file(s)' "easy_install" + # section, even if this is a "develop" or "install" command, or some + # other embedding. + self._dry_run = None + self.verbose = self.distribution.verbose + self.distribution._set_command_options( + self, self.distribution.get_option_dict('easy_install') + ) + + def delete_blockers(self, blockers): + extant_blockers = ( + filename for filename in blockers + if os.path.exists(filename) or os.path.islink(filename) + ) + list(map(self._delete_path, extant_blockers)) + + def _delete_path(self, path): + log.info("Deleting %s", path) + if self.dry_run: + return + + is_tree = os.path.isdir(path) and not os.path.islink(path) + remover = rmtree if is_tree else os.unlink + remover(path) + + @staticmethod + def _render_version(): + """ + Render the Setuptools version and installation details, then exit. + """ + ver = '{}.{}'.format(*sys.version_info) + dist = get_distribution('setuptools') + tmpl = 'setuptools {dist.version} from {dist.location} (Python {ver})' + print(tmpl.format(**locals())) + raise SystemExit() + + def finalize_options(self): # noqa: C901 # is too complex (25) # FIXME + self.version and self._render_version() + + py_version = sys.version.split()[0] + + self.config_vars = dict(sysconfig.get_config_vars()) + + self.config_vars.update({ + 'dist_name': self.distribution.get_name(), + 'dist_version': self.distribution.get_version(), + 'dist_fullname': self.distribution.get_fullname(), + 'py_version': py_version, + 'py_version_short': f'{sys.version_info.major}.{sys.version_info.minor}', + 'py_version_nodot': f'{sys.version_info.major}{sys.version_info.minor}', + 'sys_prefix': self.config_vars['prefix'], + 'sys_exec_prefix': self.config_vars['exec_prefix'], + # Only python 3.2+ has abiflags + 'abiflags': getattr(sys, 'abiflags', ''), + 'platlibdir': getattr(sys, 'platlibdir', 'lib'), + }) + with contextlib.suppress(AttributeError): + # only for distutils outside stdlib + self.config_vars.update({ + 'implementation_lower': install._get_implementation().lower(), + 'implementation': install._get_implementation(), + }) + + # pypa/distutils#113 Python 3.9 compat + self.config_vars.setdefault( + 'py_version_nodot_plat', + getattr(sys, 'windir', '').replace('.', ''), + ) + + if site.ENABLE_USER_SITE: + self.config_vars['userbase'] = self.install_userbase + self.config_vars['usersite'] = self.install_usersite + + elif self.user: + log.warn("WARNING: The user site-packages directory is disabled.") + + self._fix_install_dir_for_user_site() + + self.expand_basedirs() + self.expand_dirs() + + self._expand( + 'install_dir', 'script_dir', 'build_directory', + 'site_dirs', + ) + # If a non-default installation directory was specified, default the + # script directory to match it. + if self.script_dir is None: + self.script_dir = self.install_dir + + if self.no_find_links is None: + self.no_find_links = False + + # Let install_dir get set by install_lib command, which in turn + # gets its info from the install command, and takes into account + # --prefix and --home and all that other crud. + self.set_undefined_options( + 'install_lib', ('install_dir', 'install_dir') + ) + # Likewise, set default script_dir from 'install_scripts.install_dir' + self.set_undefined_options( + 'install_scripts', ('install_dir', 'script_dir') + ) + + if self.user and self.install_purelib: + self.install_dir = self.install_purelib + self.script_dir = self.install_scripts + # default --record from the install command + self.set_undefined_options('install', ('record', 'record')) + # Should this be moved to the if statement below? It's not used + # elsewhere + normpath = map(normalize_path, sys.path) + self.all_site_dirs = get_site_dirs() + if self.site_dirs is not None: + site_dirs = [ + os.path.expanduser(s.strip()) for s in + self.site_dirs.split(',') + ] + for d in site_dirs: + if not os.path.isdir(d): + log.warn("%s (in --site-dirs) does not exist", d) + elif normalize_path(d) not in normpath: + raise DistutilsOptionError( + d + " (in --site-dirs) is not on sys.path" + ) + else: + self.all_site_dirs.append(normalize_path(d)) + if not self.editable: + self.check_site_dir() + self.index_url = self.index_url or "https://pypi.org/simple/" + self.shadow_path = self.all_site_dirs[:] + for path_item in self.install_dir, normalize_path(self.script_dir): + if path_item not in self.shadow_path: + self.shadow_path.insert(0, path_item) + + if self.allow_hosts is not None: + hosts = [s.strip() for s in self.allow_hosts.split(',')] + else: + hosts = ['*'] + if self.package_index is None: + self.package_index = self.create_index( + self.index_url, search_path=self.shadow_path, hosts=hosts, + ) + self.local_index = Environment(self.shadow_path + sys.path) + + if self.find_links is not None: + if isinstance(self.find_links, str): + self.find_links = self.find_links.split() + else: + self.find_links = [] + if self.local_snapshots_ok: + self.package_index.scan_egg_links(self.shadow_path + sys.path) + if not self.no_find_links: + self.package_index.add_find_links(self.find_links) + self.set_undefined_options('install_lib', ('optimize', 'optimize')) + if not isinstance(self.optimize, int): + try: + self.optimize = int(self.optimize) + if not (0 <= self.optimize <= 2): + raise ValueError + except ValueError as e: + raise DistutilsOptionError( + "--optimize must be 0, 1, or 2" + ) from e + + if self.editable and not self.build_directory: + raise DistutilsArgError( + "Must specify a build directory (-b) when using --editable" + ) + if not self.args: + raise DistutilsArgError( + "No urls, filenames, or requirements specified (see --help)") + + self.outputs = [] + + def _fix_install_dir_for_user_site(self): + """ + Fix the install_dir if "--user" was used. + """ + if not self.user or not site.ENABLE_USER_SITE: + return + + self.create_home_path() + if self.install_userbase is None: + msg = "User base directory is not specified" + raise DistutilsPlatformError(msg) + self.install_base = self.install_platbase = self.install_userbase + scheme_name = f'{os.name}_user' + self.select_scheme(scheme_name) + + def _expand_attrs(self, attrs): + for attr in attrs: + val = getattr(self, attr) + if val is not None: + if os.name == 'posix' or os.name == 'nt': + val = os.path.expanduser(val) + val = subst_vars(val, self.config_vars) + setattr(self, attr, val) + + def expand_basedirs(self): + """Calls `os.path.expanduser` on install_base, install_platbase and + root.""" + self._expand_attrs(['install_base', 'install_platbase', 'root']) + + def expand_dirs(self): + """Calls `os.path.expanduser` on install dirs.""" + dirs = [ + 'install_purelib', + 'install_platlib', + 'install_lib', + 'install_headers', + 'install_scripts', + 'install_data', + ] + self._expand_attrs(dirs) + + def run(self, show_deprecation=True): + if show_deprecation: + self.announce( + "WARNING: The easy_install command is deprecated " + "and will be removed in a future version.", + log.WARN, + ) + if self.verbose != self.distribution.verbose: + log.set_verbosity(self.verbose) + try: + for spec in self.args: + self.easy_install(spec, not self.no_deps) + if self.record: + outputs = self.outputs + if self.root: # strip any package prefix + root_len = len(self.root) + for counter in range(len(outputs)): + outputs[counter] = outputs[counter][root_len:] + from distutils import file_util + + self.execute( + file_util.write_file, (self.record, outputs), + "writing list of installed files to '%s'" % + self.record + ) + self.warn_deprecated_options() + finally: + log.set_verbosity(self.distribution.verbose) + + def pseudo_tempname(self): + """Return a pseudo-tempname base in the install directory. + This code is intentionally naive; if a malicious party can write to + the target directory you're already in deep doodoo. + """ + try: + pid = os.getpid() + except Exception: + pid = random.randint(0, sys.maxsize) + return os.path.join(self.install_dir, "test-easy-install-%s" % pid) + + def warn_deprecated_options(self): + pass + + def check_site_dir(self): # noqa: C901 # is too complex (12) # FIXME + """Verify that self.install_dir is .pth-capable dir, if needed""" + + instdir = normalize_path(self.install_dir) + pth_file = os.path.join(instdir, 'easy-install.pth') + + if not os.path.exists(instdir): + try: + os.makedirs(instdir) + except (OSError, IOError): + self.cant_write_to_target() + + # Is it a configured, PYTHONPATH, implicit, or explicit site dir? + is_site_dir = instdir in self.all_site_dirs + + if not is_site_dir and not self.multi_version: + # No? Then directly test whether it does .pth file processing + is_site_dir = self.check_pth_processing() + else: + # make sure we can write to target dir + testfile = self.pseudo_tempname() + '.write-test' + test_exists = os.path.exists(testfile) + try: + if test_exists: + os.unlink(testfile) + open(testfile, 'w').close() + os.unlink(testfile) + except (OSError, IOError): + self.cant_write_to_target() + + if not is_site_dir and not self.multi_version: + # Can't install non-multi to non-site dir with easy_install + pythonpath = os.environ.get('PYTHONPATH', '') + log.warn(self.__no_default_msg, self.install_dir, pythonpath) + + if is_site_dir: + if self.pth_file is None: + self.pth_file = PthDistributions(pth_file, self.all_site_dirs) + else: + self.pth_file = None + + if self.multi_version and not os.path.exists(pth_file): + self.pth_file = None # don't create a .pth file + self.install_dir = instdir + + __cant_write_msg = textwrap.dedent(""" + can't create or remove files in install directory + + The following error occurred while trying to add or remove files in the + installation directory: + + %s + + The installation directory you specified (via --install-dir, --prefix, or + the distutils default setting) was: + + %s + """).lstrip() # noqa + + __not_exists_id = textwrap.dedent(""" + This directory does not currently exist. Please create it and try again, or + choose a different installation directory (using the -d or --install-dir + option). + """).lstrip() # noqa + + __access_msg = textwrap.dedent(""" + Perhaps your account does not have write access to this directory? If the + installation directory is a system-owned directory, you may need to sign in + as the administrator or "root" account. If you do not have administrative + access to this machine, you may wish to choose a different installation + directory, preferably one that is listed in your PYTHONPATH environment + variable. + + For information on other options, you may wish to consult the + documentation at: + + https://setuptools.pypa.io/en/latest/deprecated/easy_install.html + + Please make the appropriate changes for your system and try again. + """).lstrip() # noqa + + def cant_write_to_target(self): + msg = self.__cant_write_msg % (sys.exc_info()[1], self.install_dir,) + + if not os.path.exists(self.install_dir): + msg += '\n' + self.__not_exists_id + else: + msg += '\n' + self.__access_msg + raise DistutilsError(msg) + + def check_pth_processing(self): + """Empirically verify whether .pth files are supported in inst. dir""" + instdir = self.install_dir + log.info("Checking .pth file support in %s", instdir) + pth_file = self.pseudo_tempname() + ".pth" + ok_file = pth_file + '.ok' + ok_exists = os.path.exists(ok_file) + tmpl = _one_liner(""" + import os + f = open({ok_file!r}, 'w') + f.write('OK') + f.close() + """) + '\n' + try: + if ok_exists: + os.unlink(ok_file) + dirname = os.path.dirname(ok_file) + os.makedirs(dirname, exist_ok=True) + f = open(pth_file, 'w') + except (OSError, IOError): + self.cant_write_to_target() + else: + try: + f.write(tmpl.format(**locals())) + f.close() + f = None + executable = sys.executable + if os.name == 'nt': + dirname, basename = os.path.split(executable) + alt = os.path.join(dirname, 'pythonw.exe') + use_alt = ( + basename.lower() == 'python.exe' and + os.path.exists(alt) + ) + if use_alt: + # use pythonw.exe to avoid opening a console window + executable = alt + + from distutils.spawn import spawn + + spawn([executable, '-E', '-c', 'pass'], 0) + + if os.path.exists(ok_file): + log.info( + "TEST PASSED: %s appears to support .pth files", + instdir + ) + return True + finally: + if f: + f.close() + if os.path.exists(ok_file): + os.unlink(ok_file) + if os.path.exists(pth_file): + os.unlink(pth_file) + if not self.multi_version: + log.warn("TEST FAILED: %s does NOT support .pth files", instdir) + return False + + def install_egg_scripts(self, dist): + """Write all the scripts for `dist`, unless scripts are excluded""" + if not self.exclude_scripts and dist.metadata_isdir('scripts'): + for script_name in dist.metadata_listdir('scripts'): + if dist.metadata_isdir('scripts/' + script_name): + # The "script" is a directory, likely a Python 3 + # __pycache__ directory, so skip it. + continue + self.install_script( + dist, script_name, + dist.get_metadata('scripts/' + script_name) + ) + self.install_wrapper_scripts(dist) + + def add_output(self, path): + if os.path.isdir(path): + for base, dirs, files in os.walk(path): + for filename in files: + self.outputs.append(os.path.join(base, filename)) + else: + self.outputs.append(path) + + def not_editable(self, spec): + if self.editable: + raise DistutilsArgError( + "Invalid argument %r: you can't use filenames or URLs " + "with --editable (except via the --find-links option)." + % (spec,) + ) + + def check_editable(self, spec): + if not self.editable: + return + + if os.path.exists(os.path.join(self.build_directory, spec.key)): + raise DistutilsArgError( + "%r already exists in %s; can't do a checkout there" % + (spec.key, self.build_directory) + ) + + @contextlib.contextmanager + def _tmpdir(self): + tmpdir = tempfile.mkdtemp(prefix=u"easy_install-") + try: + # cast to str as workaround for #709 and #710 and #712 + yield str(tmpdir) + finally: + os.path.exists(tmpdir) and rmtree(tmpdir) + + def easy_install(self, spec, deps=False): + with self._tmpdir() as tmpdir: + if not isinstance(spec, Requirement): + if URL_SCHEME(spec): + # It's a url, download it to tmpdir and process + self.not_editable(spec) + dl = self.package_index.download(spec, tmpdir) + return self.install_item(None, dl, tmpdir, deps, True) + + elif os.path.exists(spec): + # Existing file or directory, just process it directly + self.not_editable(spec) + return self.install_item(None, spec, tmpdir, deps, True) + else: + spec = parse_requirement_arg(spec) + + self.check_editable(spec) + dist = self.package_index.fetch_distribution( + spec, tmpdir, self.upgrade, self.editable, + not self.always_copy, self.local_index + ) + if dist is None: + msg = "Could not find suitable distribution for %r" % spec + if self.always_copy: + msg += " (--always-copy skips system and development eggs)" + raise DistutilsError(msg) + elif dist.precedence == DEVELOP_DIST: + # .egg-info dists don't need installing, just process deps + self.process_distribution(spec, dist, deps, "Using") + return dist + else: + return self.install_item(spec, dist.location, tmpdir, deps) + + def install_item(self, spec, download, tmpdir, deps, install_needed=False): + + # Installation is also needed if file in tmpdir or is not an egg + install_needed = install_needed or self.always_copy + install_needed = install_needed or os.path.dirname(download) == tmpdir + install_needed = install_needed or not download.endswith('.egg') + install_needed = install_needed or ( + self.always_copy_from is not None and + os.path.dirname(normalize_path(download)) == + normalize_path(self.always_copy_from) + ) + + if spec and not install_needed: + # at this point, we know it's a local .egg, we just don't know if + # it's already installed. + for dist in self.local_index[spec.project_name]: + if dist.location == download: + break + else: + install_needed = True # it's not in the local index + + log.info("Processing %s", os.path.basename(download)) + + if install_needed: + dists = self.install_eggs(spec, download, tmpdir) + for dist in dists: + self.process_distribution(spec, dist, deps) + else: + dists = [self.egg_distribution(download)] + self.process_distribution(spec, dists[0], deps, "Using") + + if spec is not None: + for dist in dists: + if dist in spec: + return dist + + def select_scheme(self, name): + try: + install._select_scheme(self, name) + except AttributeError: + # stdlib distutils + install.install.select_scheme(self, name.replace('posix', 'unix')) + + # FIXME: 'easy_install.process_distribution' is too complex (12) + def process_distribution( # noqa: C901 + self, requirement, dist, deps=True, *info, + ): + self.update_pth(dist) + self.package_index.add(dist) + if dist in self.local_index[dist.key]: + self.local_index.remove(dist) + self.local_index.add(dist) + self.install_egg_scripts(dist) + self.installed_projects[dist.key] = dist + log.info(self.installation_report(requirement, dist, *info)) + if (dist.has_metadata('dependency_links.txt') and + not self.no_find_links): + self.package_index.add_find_links( + dist.get_metadata_lines('dependency_links.txt') + ) + if not deps and not self.always_copy: + return + elif requirement is not None and dist.key != requirement.key: + log.warn("Skipping dependencies for %s", dist) + return # XXX this is not the distribution we were looking for + elif requirement is None or dist not in requirement: + # if we wound up with a different version, resolve what we've got + distreq = dist.as_requirement() + requirement = Requirement(str(distreq)) + log.info("Processing dependencies for %s", requirement) + try: + distros = WorkingSet([]).resolve( + [requirement], self.local_index, self.easy_install + ) + except DistributionNotFound as e: + raise DistutilsError(str(e)) from e + except VersionConflict as e: + raise DistutilsError(e.report()) from e + if self.always_copy or self.always_copy_from: + # Force all the relevant distros to be copied or activated + for dist in distros: + if dist.key not in self.installed_projects: + self.easy_install(dist.as_requirement()) + log.info("Finished processing dependencies for %s", requirement) + + def should_unzip(self, dist): + if self.zip_ok is not None: + return not self.zip_ok + if dist.has_metadata('not-zip-safe'): + return True + if not dist.has_metadata('zip-safe'): + return True + return False + + def maybe_move(self, spec, dist_filename, setup_base): + dst = os.path.join(self.build_directory, spec.key) + if os.path.exists(dst): + msg = ( + "%r already exists in %s; build directory %s will not be kept" + ) + log.warn(msg, spec.key, self.build_directory, setup_base) + return setup_base + if os.path.isdir(dist_filename): + setup_base = dist_filename + else: + if os.path.dirname(dist_filename) == setup_base: + os.unlink(dist_filename) # get it out of the tmp dir + contents = os.listdir(setup_base) + if len(contents) == 1: + dist_filename = os.path.join(setup_base, contents[0]) + if os.path.isdir(dist_filename): + # if the only thing there is a directory, move it instead + setup_base = dist_filename + ensure_directory(dst) + shutil.move(setup_base, dst) + return dst + + def install_wrapper_scripts(self, dist): + if self.exclude_scripts: + return + for args in ScriptWriter.best().get_args(dist): + self.write_script(*args) + + def install_script(self, dist, script_name, script_text, dev_path=None): + """Generate a legacy script wrapper and install it""" + spec = str(dist.as_requirement()) + is_script = is_python_script(script_text, script_name) + + if is_script: + body = self._load_template(dev_path) % locals() + script_text = ScriptWriter.get_header(script_text) + body + self.write_script(script_name, _to_bytes(script_text), 'b') + + @staticmethod + def _load_template(dev_path): + """ + There are a couple of template scripts in the package. This + function loads one of them and prepares it for use. + """ + # See https://github.com/pypa/setuptools/issues/134 for info + # on script file naming and downstream issues with SVR4 + name = 'script.tmpl' + if dev_path: + name = name.replace('.tmpl', ' (dev).tmpl') + + raw_bytes = resource_string('setuptools', name) + return raw_bytes.decode('utf-8') + + def write_script(self, script_name, contents, mode="t", blockers=()): + """Write an executable file to the scripts directory""" + self.delete_blockers( # clean up old .py/.pyw w/o a script + [os.path.join(self.script_dir, x) for x in blockers] + ) + log.info("Installing %s script to %s", script_name, self.script_dir) + target = os.path.join(self.script_dir, script_name) + self.add_output(target) + + if self.dry_run: + return + + mask = current_umask() + ensure_directory(target) + if os.path.exists(target): + os.unlink(target) + with open(target, "w" + mode) as f: + f.write(contents) + chmod(target, 0o777 - mask) + + def install_eggs(self, spec, dist_filename, tmpdir): + # .egg dirs or files are already built, so just return them + installer_map = { + '.egg': self.install_egg, + '.exe': self.install_exe, + '.whl': self.install_wheel, + } + try: + install_dist = installer_map[ + dist_filename.lower()[-4:] + ] + except KeyError: + pass + else: + return [install_dist(dist_filename, tmpdir)] + + # Anything else, try to extract and build + setup_base = tmpdir + if os.path.isfile(dist_filename) and not dist_filename.endswith('.py'): + unpack_archive(dist_filename, tmpdir, self.unpack_progress) + elif os.path.isdir(dist_filename): + setup_base = os.path.abspath(dist_filename) + + if (setup_base.startswith(tmpdir) # something we downloaded + and self.build_directory and spec is not None): + setup_base = self.maybe_move(spec, dist_filename, setup_base) + + # Find the setup.py file + setup_script = os.path.join(setup_base, 'setup.py') + + if not os.path.exists(setup_script): + setups = glob(os.path.join(setup_base, '*', 'setup.py')) + if not setups: + raise DistutilsError( + "Couldn't find a setup script in %s" % + os.path.abspath(dist_filename) + ) + if len(setups) > 1: + raise DistutilsError( + "Multiple setup scripts in %s" % + os.path.abspath(dist_filename) + ) + setup_script = setups[0] + + # Now run it, and return the result + if self.editable: + log.info(self.report_editable(spec, setup_script)) + return [] + else: + return self.build_and_install(setup_script, setup_base) + + def egg_distribution(self, egg_path): + if os.path.isdir(egg_path): + metadata = PathMetadata(egg_path, os.path.join(egg_path, + 'EGG-INFO')) + else: + metadata = EggMetadata(zipimport.zipimporter(egg_path)) + return Distribution.from_filename(egg_path, metadata=metadata) + + # FIXME: 'easy_install.install_egg' is too complex (11) + def install_egg(self, egg_path, tmpdir): # noqa: C901 + destination = os.path.join( + self.install_dir, + os.path.basename(egg_path), + ) + destination = os.path.abspath(destination) + if not self.dry_run: + ensure_directory(destination) + + dist = self.egg_distribution(egg_path) + if not samefile(egg_path, destination): + if os.path.isdir(destination) and not os.path.islink(destination): + dir_util.remove_tree(destination, dry_run=self.dry_run) + elif os.path.exists(destination): + self.execute( + os.unlink, + (destination,), + "Removing " + destination, + ) + try: + new_dist_is_zipped = False + if os.path.isdir(egg_path): + if egg_path.startswith(tmpdir): + f, m = shutil.move, "Moving" + else: + f, m = shutil.copytree, "Copying" + elif self.should_unzip(dist): + self.mkpath(destination) + f, m = self.unpack_and_compile, "Extracting" + else: + new_dist_is_zipped = True + if egg_path.startswith(tmpdir): + f, m = shutil.move, "Moving" + else: + f, m = shutil.copy2, "Copying" + self.execute( + f, + (egg_path, destination), + (m + " %s to %s") % ( + os.path.basename(egg_path), + os.path.dirname(destination) + ), + ) + update_dist_caches( + destination, + fix_zipimporter_caches=new_dist_is_zipped, + ) + except Exception: + update_dist_caches(destination, fix_zipimporter_caches=False) + raise + + self.add_output(destination) + return self.egg_distribution(destination) + + def install_exe(self, dist_filename, tmpdir): + # See if it's valid, get data + cfg = extract_wininst_cfg(dist_filename) + if cfg is None: + raise DistutilsError( + "%s is not a valid distutils Windows .exe" % dist_filename + ) + # Create a dummy distribution object until we build the real distro + dist = Distribution( + None, + project_name=cfg.get('metadata', 'name'), + version=cfg.get('metadata', 'version'), platform=get_platform(), + ) + + # Convert the .exe to an unpacked egg + egg_path = os.path.join(tmpdir, dist.egg_name() + '.egg') + dist.location = egg_path + egg_tmp = egg_path + '.tmp' + _egg_info = os.path.join(egg_tmp, 'EGG-INFO') + pkg_inf = os.path.join(_egg_info, 'PKG-INFO') + ensure_directory(pkg_inf) # make sure EGG-INFO dir exists + dist._provider = PathMetadata(egg_tmp, _egg_info) # XXX + self.exe_to_egg(dist_filename, egg_tmp) + + # Write EGG-INFO/PKG-INFO + if not os.path.exists(pkg_inf): + f = open(pkg_inf, 'w') + f.write('Metadata-Version: 1.0\n') + for k, v in cfg.items('metadata'): + if k != 'target_version': + f.write('%s: %s\n' % (k.replace('_', '-').title(), v)) + f.close() + script_dir = os.path.join(_egg_info, 'scripts') + # delete entry-point scripts to avoid duping + self.delete_blockers([ + os.path.join(script_dir, args[0]) + for args in ScriptWriter.get_args(dist) + ]) + # Build .egg file from tmpdir + bdist_egg.make_zipfile( + egg_path, egg_tmp, verbose=self.verbose, dry_run=self.dry_run, + ) + # install the .egg + return self.install_egg(egg_path, tmpdir) + + # FIXME: 'easy_install.exe_to_egg' is too complex (12) + def exe_to_egg(self, dist_filename, egg_tmp): # noqa: C901 + """Extract a bdist_wininst to the directories an egg would use""" + # Check for .pth file and set up prefix translations + prefixes = get_exe_prefixes(dist_filename) + to_compile = [] + native_libs = [] + top_level = {} + + def process(src, dst): + s = src.lower() + for old, new in prefixes: + if s.startswith(old): + src = new + src[len(old):] + parts = src.split('/') + dst = os.path.join(egg_tmp, *parts) + dl = dst.lower() + if dl.endswith('.pyd') or dl.endswith('.dll'): + parts[-1] = bdist_egg.strip_module(parts[-1]) + top_level[os.path.splitext(parts[0])[0]] = 1 + native_libs.append(src) + elif dl.endswith('.py') and old != 'SCRIPTS/': + top_level[os.path.splitext(parts[0])[0]] = 1 + to_compile.append(dst) + return dst + if not src.endswith('.pth'): + log.warn("WARNING: can't process %s", src) + return None + + # extract, tracking .pyd/.dll->native_libs and .py -> to_compile + unpack_archive(dist_filename, egg_tmp, process) + stubs = [] + for res in native_libs: + if res.lower().endswith('.pyd'): # create stubs for .pyd's + parts = res.split('/') + resource = parts[-1] + parts[-1] = bdist_egg.strip_module(parts[-1]) + '.py' + pyfile = os.path.join(egg_tmp, *parts) + to_compile.append(pyfile) + stubs.append(pyfile) + bdist_egg.write_stub(resource, pyfile) + self.byte_compile(to_compile) # compile .py's + bdist_egg.write_safety_flag( + os.path.join(egg_tmp, 'EGG-INFO'), + bdist_egg.analyze_egg(egg_tmp, stubs)) # write zip-safety flag + + for name in 'top_level', 'native_libs': + if locals()[name]: + txt = os.path.join(egg_tmp, 'EGG-INFO', name + '.txt') + if not os.path.exists(txt): + f = open(txt, 'w') + f.write('\n'.join(locals()[name]) + '\n') + f.close() + + def install_wheel(self, wheel_path, tmpdir): + wheel = Wheel(wheel_path) + assert wheel.is_compatible() + destination = os.path.join(self.install_dir, wheel.egg_name()) + destination = os.path.abspath(destination) + if not self.dry_run: + ensure_directory(destination) + if os.path.isdir(destination) and not os.path.islink(destination): + dir_util.remove_tree(destination, dry_run=self.dry_run) + elif os.path.exists(destination): + self.execute( + os.unlink, + (destination,), + "Removing " + destination, + ) + try: + self.execute( + wheel.install_as_egg, + (destination,), + ("Installing %s to %s") % ( + os.path.basename(wheel_path), + os.path.dirname(destination) + ), + ) + finally: + update_dist_caches(destination, fix_zipimporter_caches=False) + self.add_output(destination) + return self.egg_distribution(destination) + + __mv_warning = textwrap.dedent(""" + Because this distribution was installed --multi-version, before you can + import modules from this package in an application, you will need to + 'import pkg_resources' and then use a 'require()' call similar to one of + these examples, in order to select the desired version: + + pkg_resources.require("%(name)s") # latest installed version + pkg_resources.require("%(name)s==%(version)s") # this exact version + pkg_resources.require("%(name)s>=%(version)s") # this version or higher + """).lstrip() # noqa + + __id_warning = textwrap.dedent(""" + Note also that the installation directory must be on sys.path at runtime for + this to work. (e.g. by being the application's script directory, by being on + PYTHONPATH, or by being added to sys.path by your code.) + """) # noqa + + def installation_report(self, req, dist, what="Installed"): + """Helpful installation message for display to package users""" + msg = "\n%(what)s %(eggloc)s%(extras)s" + if self.multi_version and not self.no_report: + msg += '\n' + self.__mv_warning + if self.install_dir not in map(normalize_path, sys.path): + msg += '\n' + self.__id_warning + + eggloc = dist.location + name = dist.project_name + version = dist.version + extras = '' # TODO: self.report_extras(req, dist) + return msg % locals() + + __editable_msg = textwrap.dedent(""" + Extracted editable version of %(spec)s to %(dirname)s + + If it uses setuptools in its setup script, you can activate it in + "development" mode by going to that directory and running:: + + %(python)s setup.py develop + + See the setuptools documentation for the "develop" command for more info. + """).lstrip() # noqa + + def report_editable(self, spec, setup_script): + dirname = os.path.dirname(setup_script) + python = sys.executable + return '\n' + self.__editable_msg % locals() + + def run_setup(self, setup_script, setup_base, args): + sys.modules.setdefault('distutils.command.bdist_egg', bdist_egg) + sys.modules.setdefault('distutils.command.egg_info', egg_info) + + args = list(args) + if self.verbose > 2: + v = 'v' * (self.verbose - 1) + args.insert(0, '-' + v) + elif self.verbose < 2: + args.insert(0, '-q') + if self.dry_run: + args.insert(0, '-n') + log.info( + "Running %s %s", setup_script[len(setup_base) + 1:], ' '.join(args) + ) + try: + run_setup(setup_script, args) + except SystemExit as v: + raise DistutilsError( + "Setup script exited with %s" % (v.args[0],) + ) from v + + def build_and_install(self, setup_script, setup_base): + args = ['bdist_egg', '--dist-dir'] + + dist_dir = tempfile.mkdtemp( + prefix='egg-dist-tmp-', dir=os.path.dirname(setup_script) + ) + try: + self._set_fetcher_options(os.path.dirname(setup_script)) + args.append(dist_dir) + + self.run_setup(setup_script, setup_base, args) + all_eggs = Environment([dist_dir]) + eggs = [] + for key in all_eggs: + for dist in all_eggs[key]: + eggs.append(self.install_egg(dist.location, setup_base)) + if not eggs and not self.dry_run: + log.warn("No eggs found in %s (setup script problem?)", + dist_dir) + return eggs + finally: + rmtree(dist_dir) + log.set_verbosity(self.verbose) # restore our log verbosity + + def _set_fetcher_options(self, base): + """ + When easy_install is about to run bdist_egg on a source dist, that + source dist might have 'setup_requires' directives, requiring + additional fetching. Ensure the fetcher options given to easy_install + are available to that command as well. + """ + # find the fetch options from easy_install and write them out + # to the setup.cfg file. + ei_opts = self.distribution.get_option_dict('easy_install').copy() + fetch_directives = ( + 'find_links', 'site_dirs', 'index_url', 'optimize', 'allow_hosts', + ) + fetch_options = {} + for key, val in ei_opts.items(): + if key not in fetch_directives: + continue + fetch_options[key] = val[1] + # create a settings dictionary suitable for `edit_config` + settings = dict(easy_install=fetch_options) + cfg_filename = os.path.join(base, 'setup.cfg') + setopt.edit_config(cfg_filename, settings) + + def update_pth(self, dist): # noqa: C901 # is too complex (11) # FIXME + if self.pth_file is None: + return + + for d in self.pth_file[dist.key]: # drop old entries + if not self.multi_version and d.location == dist.location: + continue + + log.info("Removing %s from easy-install.pth file", d) + self.pth_file.remove(d) + if d.location in self.shadow_path: + self.shadow_path.remove(d.location) + + if not self.multi_version: + if dist.location in self.pth_file.paths: + log.info( + "%s is already the active version in easy-install.pth", + dist, + ) + else: + log.info("Adding %s to easy-install.pth file", dist) + self.pth_file.add(dist) # add new entry + if dist.location not in self.shadow_path: + self.shadow_path.append(dist.location) + + if self.dry_run: + return + + self.pth_file.save() + + if dist.key != 'setuptools': + return + + # Ensure that setuptools itself never becomes unavailable! + # XXX should this check for latest version? + filename = os.path.join(self.install_dir, 'setuptools.pth') + if os.path.islink(filename): + os.unlink(filename) + with open(filename, 'wt') as f: + f.write(self.pth_file.make_relative(dist.location) + '\n') + + def unpack_progress(self, src, dst): + # Progress filter for unpacking + log.debug("Unpacking %s to %s", src, dst) + return dst # only unpack-and-compile skips files for dry run + + def unpack_and_compile(self, egg_path, destination): + to_compile = [] + to_chmod = [] + + def pf(src, dst): + if dst.endswith('.py') and not src.startswith('EGG-INFO/'): + to_compile.append(dst) + elif dst.endswith('.dll') or dst.endswith('.so'): + to_chmod.append(dst) + self.unpack_progress(src, dst) + return not self.dry_run and dst or None + + unpack_archive(egg_path, destination, pf) + self.byte_compile(to_compile) + if not self.dry_run: + for f in to_chmod: + mode = ((os.stat(f)[stat.ST_MODE]) | 0o555) & 0o7755 + chmod(f, mode) + + def byte_compile(self, to_compile): + if sys.dont_write_bytecode: + return + + from distutils.util import byte_compile + + try: + # try to make the byte compile messages quieter + log.set_verbosity(self.verbose - 1) + + byte_compile(to_compile, optimize=0, force=1, dry_run=self.dry_run) + if self.optimize: + byte_compile( + to_compile, optimize=self.optimize, force=1, + dry_run=self.dry_run, + ) + finally: + log.set_verbosity(self.verbose) # restore original verbosity + + __no_default_msg = textwrap.dedent(""" + bad install directory or PYTHONPATH + + You are attempting to install a package to a directory that is not + on PYTHONPATH and which Python does not read ".pth" files from. The + installation directory you specified (via --install-dir, --prefix, or + the distutils default setting) was: + + %s + + and your PYTHONPATH environment variable currently contains: + + %r + + Here are some of your options for correcting the problem: + + * You can choose a different installation directory, i.e., one that is + on PYTHONPATH or supports .pth files + + * You can add the installation directory to the PYTHONPATH environment + variable. (It must then also be on PYTHONPATH whenever you run + Python and want to use the package(s) you are installing.) + + * You can set up the installation directory to support ".pth" files by + using one of the approaches described here: + + https://setuptools.pypa.io/en/latest/deprecated/easy_install.html#custom-installation-locations + + + Please make the appropriate changes for your system and try again. + """).strip() + + def create_home_path(self): + """Create directories under ~.""" + if not self.user: + return + home = convert_path(os.path.expanduser("~")) + for path in only_strs(self.config_vars.values()): + if path.startswith(home) and not os.path.isdir(path): + self.debug_print("os.makedirs('%s', 0o700)" % path) + os.makedirs(path, 0o700) + + INSTALL_SCHEMES = dict( + posix=dict( + install_dir='$base/lib/python$py_version_short/site-packages', + script_dir='$base/bin', + ), + ) + + DEFAULT_SCHEME = dict( + install_dir='$base/Lib/site-packages', + script_dir='$base/Scripts', + ) + + def _expand(self, *attrs): + config_vars = self.get_finalized_command('install').config_vars + + if self.prefix: + # Set default install_dir/scripts from --prefix + config_vars = dict(config_vars) + config_vars['base'] = self.prefix + scheme = self.INSTALL_SCHEMES.get(os.name, self.DEFAULT_SCHEME) + for attr, val in scheme.items(): + if getattr(self, attr, None) is None: + setattr(self, attr, val) + + from distutils.util import subst_vars + + for attr in attrs: + val = getattr(self, attr) + if val is not None: + val = subst_vars(val, config_vars) + if os.name == 'posix': + val = os.path.expanduser(val) + setattr(self, attr, val) + + +def _pythonpath(): + items = os.environ.get('PYTHONPATH', '').split(os.pathsep) + return filter(None, items) + + +def get_site_dirs(): + """ + Return a list of 'site' dirs + """ + + sitedirs = [] + + # start with PYTHONPATH + sitedirs.extend(_pythonpath()) + + prefixes = [sys.prefix] + if sys.exec_prefix != sys.prefix: + prefixes.append(sys.exec_prefix) + for prefix in prefixes: + if not prefix: + continue + + if sys.platform in ('os2emx', 'riscos'): + sitedirs.append(os.path.join(prefix, "Lib", "site-packages")) + elif os.sep == '/': + sitedirs.extend([ + os.path.join( + prefix, + "lib", + "python{}.{}".format(*sys.version_info), + "site-packages", + ), + os.path.join(prefix, "lib", "site-python"), + ]) + else: + sitedirs.extend([ + prefix, + os.path.join(prefix, "lib", "site-packages"), + ]) + if sys.platform != 'darwin': + continue + + # 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' not in prefix: + continue + + home = os.environ.get('HOME') + if not home: + continue + + home_sp = os.path.join( + home, + 'Library', + 'Python', + '{}.{}'.format(*sys.version_info), + 'site-packages', + ) + sitedirs.append(home_sp) + lib_paths = get_path('purelib'), get_path('platlib') + + sitedirs.extend(s for s in lib_paths if s not in sitedirs) + + if site.ENABLE_USER_SITE: + sitedirs.append(site.USER_SITE) + + with contextlib.suppress(AttributeError): + sitedirs.extend(site.getsitepackages()) + + sitedirs = list(map(normalize_path, sitedirs)) + + return sitedirs + + +def expand_paths(inputs): # noqa: C901 # is too complex (11) # FIXME + """Yield sys.path directories that might contain "old-style" packages""" + + seen = {} + + for dirname in inputs: + dirname = normalize_path(dirname) + if dirname in seen: + continue + + seen[dirname] = 1 + if not os.path.isdir(dirname): + continue + + files = os.listdir(dirname) + yield dirname, files + + for name in files: + if not name.endswith('.pth'): + # We only care about the .pth files + continue + if name in ('easy-install.pth', 'setuptools.pth'): + # Ignore .pth files that we control + continue + + # Read the .pth file + f = open(os.path.join(dirname, name)) + lines = list(yield_lines(f)) + f.close() + + # Yield existing non-dupe, non-import directory lines from it + for line in lines: + if line.startswith("import"): + continue + + line = normalize_path(line.rstrip()) + if line in seen: + continue + + seen[line] = 1 + if not os.path.isdir(line): + continue + + yield line, os.listdir(line) + + +def extract_wininst_cfg(dist_filename): + """Extract configuration data from a bdist_wininst .exe + + Returns a configparser.RawConfigParser, or None + """ + f = open(dist_filename, 'rb') + try: + endrec = zipfile._EndRecData(f) + if endrec is None: + return None + + prepended = (endrec[9] - endrec[5]) - endrec[6] + if prepended < 12: # no wininst data here + return None + f.seek(prepended - 12) + + tag, cfglen, bmlen = struct.unpack("egg path translations for a given .exe file""" + + prefixes = [ + ('PURELIB/', ''), + ('PLATLIB/pywin32_system32', ''), + ('PLATLIB/', ''), + ('SCRIPTS/', 'EGG-INFO/scripts/'), + ('DATA/lib/site-packages', ''), + ] + z = zipfile.ZipFile(exe_filename) + try: + for info in z.infolist(): + name = info.filename + parts = name.split('/') + if len(parts) == 3 and parts[2] == 'PKG-INFO': + if parts[1].endswith('.egg-info'): + prefixes.insert(0, ('/'.join(parts[:2]), 'EGG-INFO/')) + break + if len(parts) != 2 or not name.endswith('.pth'): + continue + if name.endswith('-nspkg.pth'): + continue + if parts[0].upper() in ('PURELIB', 'PLATLIB'): + contents = z.read(name).decode() + for pth in yield_lines(contents): + pth = pth.strip().replace('\\', '/') + if not pth.startswith('import'): + prefixes.append((('%s/%s/' % (parts[0], pth)), '')) + finally: + z.close() + prefixes = [(x.lower(), y) for x, y in prefixes] + prefixes.sort() + prefixes.reverse() + return prefixes + + +class PthDistributions(Environment): + """A .pth file with Distribution paths in it""" + + dirty = False + + def __init__(self, filename, sitedirs=()): + self.filename = filename + self.sitedirs = list(map(normalize_path, sitedirs)) + self.basedir = normalize_path(os.path.dirname(self.filename)) + self._load() + super().__init__([], None, None) + for path in yield_lines(self.paths): + list(map(self.add, find_distributions(path, True))) + + def _load(self): + self.paths = [] + saw_import = False + seen = dict.fromkeys(self.sitedirs) + if os.path.isfile(self.filename): + f = open(self.filename, 'rt') + for line in f: + if line.startswith('import'): + saw_import = True + continue + path = line.rstrip() + self.paths.append(path) + if not path.strip() or path.strip().startswith('#'): + continue + # skip non-existent paths, in case somebody deleted a package + # manually, and duplicate paths as well + path = self.paths[-1] = normalize_path( + os.path.join(self.basedir, path) + ) + if not os.path.exists(path) or path in seen: + self.paths.pop() # skip it + self.dirty = True # we cleaned up, so we're dirty now :) + continue + seen[path] = 1 + f.close() + + if self.paths and not saw_import: + self.dirty = True # ensure anything we touch has import wrappers + while self.paths and not self.paths[-1].strip(): + self.paths.pop() + + def save(self): + """Write changed .pth file back to disk""" + if not self.dirty: + return + + rel_paths = list(map(self.make_relative, self.paths)) + if rel_paths: + log.debug("Saving %s", self.filename) + lines = self._wrap_lines(rel_paths) + data = '\n'.join(lines) + '\n' + + if os.path.islink(self.filename): + os.unlink(self.filename) + with open(self.filename, 'wt') as f: + f.write(data) + + elif os.path.exists(self.filename): + log.debug("Deleting empty %s", self.filename) + os.unlink(self.filename) + + self.dirty = False + + @staticmethod + def _wrap_lines(lines): + return lines + + def add(self, dist): + """Add `dist` to the distribution map""" + new_path = ( + dist.location not in self.paths and ( + dist.location not in self.sitedirs or + # account for '.' being in PYTHONPATH + dist.location == os.getcwd() + ) + ) + if new_path: + self.paths.append(dist.location) + self.dirty = True + Environment.add(self, dist) + + def remove(self, dist): + """Remove `dist` from the distribution map""" + while dist.location in self.paths: + self.paths.remove(dist.location) + self.dirty = True + Environment.remove(self, dist) + + def make_relative(self, path): + npath, last = os.path.split(normalize_path(path)) + baselen = len(self.basedir) + parts = [last] + sep = os.altsep == '/' and '/' or os.sep + while len(npath) >= baselen: + if npath == self.basedir: + parts.append(os.curdir) + parts.reverse() + return sep.join(parts) + npath, last = os.path.split(npath) + parts.append(last) + else: + return path + + +class RewritePthDistributions(PthDistributions): + @classmethod + def _wrap_lines(cls, lines): + yield cls.prelude + for line in lines: + yield line + yield cls.postlude + + prelude = _one_liner(""" + import sys + sys.__plen = len(sys.path) + """) + postlude = _one_liner(""" + import sys + new = sys.path[sys.__plen:] + del sys.path[sys.__plen:] + p = getattr(sys, '__egginsert', 0) + sys.path[p:p] = new + sys.__egginsert = p + len(new) + """) + + +if os.environ.get('SETUPTOOLS_SYS_PATH_TECHNIQUE', 'raw') == 'rewrite': + PthDistributions = RewritePthDistributions + + +def _first_line_re(): + """ + Return a regular expression based on first_line_re suitable for matching + strings. + """ + if isinstance(first_line_re.pattern, str): + return first_line_re + + # first_line_re in Python >=3.1.4 and >=3.2.1 is a bytes pattern. + return re.compile(first_line_re.pattern.decode()) + + +def auto_chmod(func, arg, exc): + if func in [os.unlink, os.remove] and os.name == 'nt': + chmod(arg, stat.S_IWRITE) + return func(arg) + et, ev, _ = sys.exc_info() + # TODO: This code doesn't make sense. What is it trying to do? + raise (ev[0], ev[1] + (" %s %s" % (func, arg))) + + +def update_dist_caches(dist_path, fix_zipimporter_caches): + """ + Fix any globally cached `dist_path` related data + + `dist_path` should be a path of a newly installed egg distribution (zipped + or unzipped). + + sys.path_importer_cache contains finder objects that have been cached when + importing data from the original distribution. Any such finders need to be + cleared since the replacement distribution might be packaged differently, + e.g. a zipped egg distribution might get replaced with an unzipped egg + folder or vice versa. Having the old finders cached may then cause Python + to attempt loading modules from the replacement distribution using an + incorrect loader. + + zipimport.zipimporter objects are Python loaders charged with importing + data packaged inside zip archives. If stale loaders referencing the + original distribution, are left behind, they can fail to load modules from + the replacement distribution. E.g. if an old zipimport.zipimporter instance + is used to load data from a new zipped egg archive, it may cause the + operation to attempt to locate the requested data in the wrong location - + one indicated by the original distribution's zip archive directory + information. Such an operation may then fail outright, e.g. report having + read a 'bad local file header', or even worse, it may fail silently & + return invalid data. + + zipimport._zip_directory_cache contains cached zip archive directory + information for all existing zipimport.zipimporter instances and all such + instances connected to the same archive share the same cached directory + information. + + If asked, and the underlying Python implementation allows it, we can fix + all existing zipimport.zipimporter instances instead of having to track + them down and remove them one by one, by updating their shared cached zip + archive directory information. This, of course, assumes that the + replacement distribution is packaged as a zipped egg. + + If not asked to fix existing zipimport.zipimporter instances, we still do + our best to clear any remaining zipimport.zipimporter related cached data + that might somehow later get used when attempting to load data from the new + distribution and thus cause such load operations to fail. Note that when + tracking down such remaining stale data, we can not catch every conceivable + usage from here, and we clear only those that we know of and have found to + cause problems if left alive. Any remaining caches should be updated by + whomever is in charge of maintaining them, i.e. they should be ready to + handle us replacing their zip archives with new distributions at runtime. + + """ + # There are several other known sources of stale zipimport.zipimporter + # instances that we do not clear here, but might if ever given a reason to + # do so: + # * Global setuptools pkg_resources.working_set (a.k.a. 'master working + # set') may contain distributions which may in turn contain their + # zipimport.zipimporter loaders. + # * Several zipimport.zipimporter loaders held by local variables further + # up the function call stack when running the setuptools installation. + # * Already loaded modules may have their __loader__ attribute set to the + # exact loader instance used when importing them. Python 3.4 docs state + # that this information is intended mostly for introspection and so is + # not expected to cause us problems. + normalized_path = normalize_path(dist_path) + _uncache(normalized_path, sys.path_importer_cache) + if fix_zipimporter_caches: + _replace_zip_directory_cache_data(normalized_path) + else: + # Here, even though we do not want to fix existing and now stale + # zipimporter cache information, we still want to remove it. Related to + # Python's zip archive directory information cache, we clear each of + # its stale entries in two phases: + # 1. Clear the entry so attempting to access zip archive information + # via any existing stale zipimport.zipimporter instances fails. + # 2. Remove the entry from the cache so any newly constructed + # zipimport.zipimporter instances do not end up using old stale + # zip archive directory information. + # This whole stale data removal step does not seem strictly necessary, + # but has been left in because it was done before we started replacing + # the zip archive directory information cache content if possible, and + # there are no relevant unit tests that we can depend on to tell us if + # this is really needed. + _remove_and_clear_zip_directory_cache_data(normalized_path) + + +def _collect_zipimporter_cache_entries(normalized_path, cache): + """ + Return zipimporter cache entry keys related to a given normalized path. + + Alternative path spellings (e.g. those using different character case or + those using alternative path separators) related to the same path are + included. Any sub-path entries are included as well, i.e. those + corresponding to zip archives embedded in other zip archives. + + """ + result = [] + prefix_len = len(normalized_path) + for p in cache: + np = normalize_path(p) + if (np.startswith(normalized_path) and + np[prefix_len:prefix_len + 1] in (os.sep, '')): + result.append(p) + return result + + +def _update_zipimporter_cache(normalized_path, cache, updater=None): + """ + Update zipimporter cache data for a given normalized path. + + Any sub-path entries are processed as well, i.e. those corresponding to zip + archives embedded in other zip archives. + + Given updater is a callable taking a cache entry key and the original entry + (after already removing the entry from the cache), and expected to update + the entry and possibly return a new one to be inserted in its place. + Returning None indicates that the entry should not be replaced with a new + one. If no updater is given, the cache entries are simply removed without + any additional processing, the same as if the updater simply returned None. + + """ + for p in _collect_zipimporter_cache_entries(normalized_path, cache): + # N.B. pypy's custom zipimport._zip_directory_cache implementation does + # not support the complete dict interface: + # * Does not support item assignment, thus not allowing this function + # to be used only for removing existing cache entries. + # * Does not support the dict.pop() method, forcing us to use the + # get/del patterns instead. For more detailed information see the + # following links: + # https://github.com/pypa/setuptools/issues/202#issuecomment-202913420 + # http://bit.ly/2h9itJX + old_entry = cache[p] + del cache[p] + new_entry = updater and updater(p, old_entry) + if new_entry is not None: + cache[p] = new_entry + + +def _uncache(normalized_path, cache): + _update_zipimporter_cache(normalized_path, cache) + + +def _remove_and_clear_zip_directory_cache_data(normalized_path): + def clear_and_remove_cached_zip_archive_directory_data(path, old_entry): + old_entry.clear() + + _update_zipimporter_cache( + normalized_path, zipimport._zip_directory_cache, + updater=clear_and_remove_cached_zip_archive_directory_data) + + +# PyPy Python implementation does not allow directly writing to the +# zipimport._zip_directory_cache and so prevents us from attempting to correct +# its content. The best we can do there is clear the problematic cache content +# and have PyPy repopulate it as needed. The downside is that if there are any +# stale zipimport.zipimporter instances laying around, attempting to use them +# will fail due to not having its zip archive directory information available +# instead of being automatically corrected to use the new correct zip archive +# directory information. +if '__pypy__' in sys.builtin_module_names: + _replace_zip_directory_cache_data = \ + _remove_and_clear_zip_directory_cache_data +else: + + def _replace_zip_directory_cache_data(normalized_path): + def replace_cached_zip_archive_directory_data(path, old_entry): + # N.B. In theory, we could load the zip directory information just + # once for all updated path spellings, and then copy it locally and + # update its contained path strings to contain the correct + # spelling, but that seems like a way too invasive move (this cache + # structure is not officially documented anywhere and could in + # theory change with new Python releases) for no significant + # benefit. + old_entry.clear() + zipimport.zipimporter(path) + old_entry.update(zipimport._zip_directory_cache[path]) + return old_entry + + _update_zipimporter_cache( + normalized_path, zipimport._zip_directory_cache, + updater=replace_cached_zip_archive_directory_data) + + +def is_python(text, filename=''): + "Is this string a valid Python script?" + try: + compile(text, filename, 'exec') + except (SyntaxError, TypeError): + return False + else: + return True + + +def is_sh(executable): + """Determine if the specified executable is a .sh (contains a #! line)""" + try: + with io.open(executable, encoding='latin-1') as fp: + magic = fp.read(2) + except (OSError, IOError): + return executable + return magic == '#!' + + +def nt_quote_arg(arg): + """Quote a command line argument according to Windows parsing rules""" + return subprocess.list2cmdline([arg]) + + +def is_python_script(script_text, filename): + """Is this text, as a whole, a Python script? (as opposed to shell/bat/etc. + """ + if filename.endswith('.py') or filename.endswith('.pyw'): + return True # extension says it's Python + if is_python(script_text, filename): + return True # it's syntactically valid Python + if script_text.startswith('#!'): + # It begins with a '#!' line, so check if 'python' is in it somewhere + return 'python' in script_text.splitlines()[0].lower() + + return False # Not any Python I can recognize + + +try: + from os import chmod as _chmod +except ImportError: + # Jython compatibility + def _chmod(*args): + pass + + +def chmod(path, mode): + log.debug("changing mode of %s to %o", path, mode) + try: + _chmod(path, mode) + except os.error as e: + log.debug("chmod failed: %s", e) + + +class CommandSpec(list): + """ + A command spec for a #! header, specified as a list of arguments akin to + those passed to Popen. + """ + + options = [] + split_args = dict() + + @classmethod + def best(cls): + """ + Choose the best CommandSpec class based on environmental conditions. + """ + return cls + + @classmethod + def _sys_executable(cls): + _default = os.path.normpath(sys.executable) + return os.environ.get('__PYVENV_LAUNCHER__', _default) + + @classmethod + def from_param(cls, param): + """ + Construct a CommandSpec from a parameter to build_scripts, which may + be None. + """ + if isinstance(param, cls): + return param + if isinstance(param, list): + return cls(param) + if param is None: + return cls.from_environment() + # otherwise, assume it's a string. + return cls.from_string(param) + + @classmethod + def from_environment(cls): + return cls([cls._sys_executable()]) + + @classmethod + def from_string(cls, string): + """ + Construct a command spec from a simple string representing a command + line parseable by shlex.split. + """ + items = shlex.split(string, **cls.split_args) + return cls(items) + + def install_options(self, script_text): + self.options = shlex.split(self._extract_options(script_text)) + cmdline = subprocess.list2cmdline(self) + if not isascii(cmdline): + self.options[:0] = ['-x'] + + @staticmethod + def _extract_options(orig_script): + """ + Extract any options from the first line of the script. + """ + first = (orig_script + '\n').splitlines()[0] + match = _first_line_re().match(first) + options = match.group(1) or '' if match else '' + return options.strip() + + def as_header(self): + return self._render(self + list(self.options)) + + @staticmethod + def _strip_quotes(item): + _QUOTES = '"\'' + for q in _QUOTES: + if item.startswith(q) and item.endswith(q): + return item[1:-1] + return item + + @staticmethod + def _render(items): + cmdline = subprocess.list2cmdline( + CommandSpec._strip_quotes(item.strip()) for item in items) + return '#!' + cmdline + '\n' + + +# For pbr compat; will be removed in a future version. +sys_executable = CommandSpec._sys_executable() + + +class WindowsCommandSpec(CommandSpec): + split_args = dict(posix=False) + + +class ScriptWriter: + """ + Encapsulates behavior around writing entry point scripts for console and + gui apps. + """ + + template = textwrap.dedent(r""" + # EASY-INSTALL-ENTRY-SCRIPT: %(spec)r,%(group)r,%(name)r + import re + import sys + + # for compatibility with easy_install; see #2198 + __requires__ = %(spec)r + + try: + from importlib.metadata import distribution + except ImportError: + try: + from importlib_metadata import distribution + except ImportError: + from pkg_resources import load_entry_point + + + def importlib_load_entry_point(spec, group, name): + dist_name, _, _ = spec.partition('==') + matches = ( + entry_point + for entry_point in distribution(dist_name).entry_points + if entry_point.group == group and entry_point.name == name + ) + return next(matches).load() + + + globals().setdefault('load_entry_point', importlib_load_entry_point) + + + if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0]) + sys.exit(load_entry_point(%(spec)r, %(group)r, %(name)r)()) + """).lstrip() + + command_spec_class = CommandSpec + + @classmethod + def get_script_args(cls, dist, executable=None, wininst=False): + # for backward compatibility + warnings.warn("Use get_args", EasyInstallDeprecationWarning) + writer = (WindowsScriptWriter if wininst else ScriptWriter).best() + header = cls.get_script_header("", executable, wininst) + return writer.get_args(dist, header) + + @classmethod + def get_script_header(cls, script_text, executable=None, wininst=False): + # for backward compatibility + warnings.warn( + "Use get_header", EasyInstallDeprecationWarning, stacklevel=2) + if wininst: + executable = "python.exe" + return cls.get_header(script_text, executable) + + @classmethod + def get_args(cls, dist, header=None): + """ + Yield write_script() argument tuples for a distribution's + console_scripts and gui_scripts entry points. + """ + if header is None: + header = cls.get_header() + spec = str(dist.as_requirement()) + for type_ in 'console', 'gui': + group = type_ + '_scripts' + for name, ep in dist.get_entry_map(group).items(): + cls._ensure_safe_name(name) + script_text = cls.template % locals() + args = cls._get_script_args(type_, name, header, script_text) + for res in args: + yield res + + @staticmethod + def _ensure_safe_name(name): + """ + Prevent paths in *_scripts entry point names. + """ + has_path_sep = re.search(r'[\\/]', name) + if has_path_sep: + raise ValueError("Path separators not allowed in script names") + + @classmethod + def get_writer(cls, force_windows): + # for backward compatibility + warnings.warn("Use best", EasyInstallDeprecationWarning) + return WindowsScriptWriter.best() if force_windows else cls.best() + + @classmethod + def best(cls): + """ + Select the best ScriptWriter for this environment. + """ + if sys.platform == 'win32' or (os.name == 'java' and os._name == 'nt'): + return WindowsScriptWriter.best() + else: + return cls + + @classmethod + def _get_script_args(cls, type_, name, header, script_text): + # Simply write the stub with no extension. + yield (name, header + script_text) + + @classmethod + def get_header(cls, script_text="", executable=None): + """Create a #! line, getting options (if any) from script_text""" + cmd = cls.command_spec_class.best().from_param(executable) + cmd.install_options(script_text) + return cmd.as_header() + + +class WindowsScriptWriter(ScriptWriter): + command_spec_class = WindowsCommandSpec + + @classmethod + def get_writer(cls): + # for backward compatibility + warnings.warn("Use best", EasyInstallDeprecationWarning) + return cls.best() + + @classmethod + def best(cls): + """ + Select the best ScriptWriter suitable for Windows + """ + writer_lookup = dict( + executable=WindowsExecutableLauncherWriter, + natural=cls, + ) + # for compatibility, use the executable launcher by default + launcher = os.environ.get('SETUPTOOLS_LAUNCHER', 'executable') + return writer_lookup[launcher] + + @classmethod + def _get_script_args(cls, type_, name, header, script_text): + "For Windows, add a .py extension" + ext = dict(console='.pya', gui='.pyw')[type_] + if ext not in os.environ['PATHEXT'].lower().split(';'): + msg = ( + "{ext} not listed in PATHEXT; scripts will not be " + "recognized as executables." + ).format(**locals()) + warnings.warn(msg, UserWarning) + old = ['.pya', '.py', '-script.py', '.pyc', '.pyo', '.pyw', '.exe'] + old.remove(ext) + header = cls._adjust_header(type_, header) + blockers = [name + x for x in old] + yield name + ext, header + script_text, 't', blockers + + @classmethod + def _adjust_header(cls, type_, orig_header): + """ + Make sure 'pythonw' is used for gui and 'python' is used for + console (regardless of what sys.executable is). + """ + pattern = 'pythonw.exe' + repl = 'python.exe' + if type_ == 'gui': + pattern, repl = repl, pattern + pattern_ob = re.compile(re.escape(pattern), re.IGNORECASE) + new_header = pattern_ob.sub(string=orig_header, repl=repl) + return new_header if cls._use_header(new_header) else orig_header + + @staticmethod + def _use_header(new_header): + """ + Should _adjust_header use the replaced header? + + On non-windows systems, always use. On + Windows systems, only use the replaced header if it resolves + to an executable on the system. + """ + clean_header = new_header[2:-1].strip('"') + return sys.platform != 'win32' or find_executable(clean_header) + + +class WindowsExecutableLauncherWriter(WindowsScriptWriter): + @classmethod + def _get_script_args(cls, type_, name, header, script_text): + """ + For Windows, add a .py extension and an .exe launcher + """ + if type_ == 'gui': + launcher_type = 'gui' + ext = '-script.pyw' + old = ['.pyw'] + else: + launcher_type = 'cli' + ext = '-script.py' + old = ['.py', '.pyc', '.pyo'] + hdr = cls._adjust_header(type_, header) + blockers = [name + x for x in old] + yield (name + ext, hdr + script_text, 't', blockers) + yield ( + name + '.exe', get_win_launcher(launcher_type), + 'b' # write in binary mode + ) + if not is_64bit(): + # install a manifest for the launcher to prevent Windows + # from detecting it as an installer (which it will for + # launchers like easy_install.exe). Consider only + # adding a manifest for launchers detected as installers. + # See Distribute #143 for details. + m_name = name + '.exe.manifest' + yield (m_name, load_launcher_manifest(name), 't') + + +# for backward-compatibility +get_script_args = ScriptWriter.get_script_args +get_script_header = ScriptWriter.get_script_header + + +def get_win_launcher(type): + """ + Load the Windows launcher (executable) suitable for launching a script. + + `type` should be either 'cli' or 'gui' + + Returns the executable as a byte string. + """ + launcher_fn = '%s.exe' % type + if is_64bit(): + if get_platform() == "win-arm64": + launcher_fn = launcher_fn.replace(".", "-arm64.") + else: + launcher_fn = launcher_fn.replace(".", "-64.") + else: + launcher_fn = launcher_fn.replace(".", "-32.") + return resource_string('setuptools', launcher_fn) + + +def load_launcher_manifest(name): + manifest = pkg_resources.resource_string(__name__, 'launcher manifest.xml') + return manifest.decode('utf-8') % vars() + + +def rmtree(path, ignore_errors=False, onerror=auto_chmod): + return shutil.rmtree(path, ignore_errors, onerror) + + +def current_umask(): + tmp = os.umask(0o022) + os.umask(tmp) + return tmp + + +def only_strs(values): + """ + Exclude non-str values. Ref #3063. + """ + return filter(lambda val: isinstance(val, str), values) + + +class EasyInstallDeprecationWarning(SetuptoolsDeprecationWarning): + """ + Warning for EasyInstall deprecations, bypassing suppression. + """ diff --git a/venv/Lib/site-packages/setuptools/command/egg_info.py b/venv/Lib/site-packages/setuptools/command/egg_info.py new file mode 100644 index 0000000..6338965 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/command/egg_info.py @@ -0,0 +1,743 @@ +"""setuptools.command.egg_info + +Create a distribution's .egg-info directory and contents""" + +from distutils.filelist import FileList as _FileList +from distutils.errors import DistutilsInternalError +from distutils.util import convert_path +from distutils import log +import distutils.errors +import distutils.filelist +import functools +import os +import re +import sys +import io +import warnings +import time +import collections + +from .._importlib import metadata +from .. import _entry_points + +from setuptools import Command +from setuptools.command.sdist import sdist +from setuptools.command.sdist import walk_revctrl +from setuptools.command.setopt import edit_config +from setuptools.command import bdist_egg +from pkg_resources import ( + Requirement, safe_name, parse_version, + safe_version, to_filename) +import setuptools.unicode_utils as unicode_utils +from setuptools.glob import glob + +from setuptools.extern import packaging +from setuptools.extern.jaraco.text import yield_lines +from setuptools import SetuptoolsDeprecationWarning + + +def translate_pattern(glob): # noqa: C901 # is too complex (14) # FIXME + """ + Translate a file path glob like '*.txt' in to a regular expression. + This differs from fnmatch.translate which allows wildcards to match + directory separators. It also knows about '**/' which matches any number of + directories. + """ + pat = '' + + # This will split on '/' within [character classes]. This is deliberate. + chunks = glob.split(os.path.sep) + + sep = re.escape(os.sep) + valid_char = '[^%s]' % (sep,) + + for c, chunk in enumerate(chunks): + last_chunk = c == len(chunks) - 1 + + # Chunks that are a literal ** are globstars. They match anything. + if chunk == '**': + if last_chunk: + # Match anything if this is the last component + pat += '.*' + else: + # Match '(name/)*' + pat += '(?:%s+%s)*' % (valid_char, sep) + continue # Break here as the whole path component has been handled + + # Find any special characters in the remainder + i = 0 + chunk_len = len(chunk) + while i < chunk_len: + char = chunk[i] + if char == '*': + # Match any number of name characters + pat += valid_char + '*' + elif char == '?': + # Match a name character + pat += valid_char + elif char == '[': + # Character class + inner_i = i + 1 + # Skip initial !/] chars + if inner_i < chunk_len and chunk[inner_i] == '!': + inner_i = inner_i + 1 + if inner_i < chunk_len and chunk[inner_i] == ']': + inner_i = inner_i + 1 + + # Loop till the closing ] is found + while inner_i < chunk_len and chunk[inner_i] != ']': + inner_i = inner_i + 1 + + if inner_i >= chunk_len: + # Got to the end of the string without finding a closing ] + # Do not treat this as a matching group, but as a literal [ + pat += re.escape(char) + else: + # Grab the insides of the [brackets] + inner = chunk[i + 1:inner_i] + char_class = '' + + # Class negation + if inner[0] == '!': + char_class = '^' + inner = inner[1:] + + char_class += re.escape(inner) + pat += '[%s]' % (char_class,) + + # Skip to the end ] + i = inner_i + else: + pat += re.escape(char) + i += 1 + + # Join each chunk with the dir separator + if not last_chunk: + pat += sep + + pat += r'\Z' + return re.compile(pat, flags=re.MULTILINE | re.DOTALL) + + +class InfoCommon: + tag_build = None + tag_date = None + + @property + def name(self): + return safe_name(self.distribution.get_name()) + + def tagged_version(self): + return safe_version(self._maybe_tag(self.distribution.get_version())) + + def _maybe_tag(self, version): + """ + egg_info may be called more than once for a distribution, + in which case the version string already contains all tags. + """ + return ( + version if self.vtags and version.endswith(self.vtags) + else version + self.vtags + ) + + def tags(self): + version = '' + if self.tag_build: + version += self.tag_build + if self.tag_date: + version += time.strftime("-%Y%m%d") + return version + vtags = property(tags) + + +class egg_info(InfoCommon, Command): + description = "create a distribution's .egg-info directory" + + user_options = [ + ('egg-base=', 'e', "directory containing .egg-info directories" + " (default: top of the source tree)"), + ('tag-date', 'd', "Add date stamp (e.g. 20050528) to version number"), + ('tag-build=', 'b', "Specify explicit tag to add to version number"), + ('no-date', 'D', "Don't include date stamp [default]"), + ] + + boolean_options = ['tag-date'] + negative_opt = { + 'no-date': 'tag-date', + } + + def initialize_options(self): + self.egg_base = None + self.egg_name = None + self.egg_info = None + self.egg_version = None + self.broken_egg_info = False + + #################################### + # allow the 'tag_svn_revision' to be detected and + # set, supporting sdists built on older Setuptools. + @property + def tag_svn_revision(self): + pass + + @tag_svn_revision.setter + def tag_svn_revision(self, value): + pass + #################################### + + def save_version_info(self, filename): + """ + Materialize the value of date into the + build tag. Install build keys in a deterministic order + to avoid arbitrary reordering on subsequent builds. + """ + egg_info = collections.OrderedDict() + # follow the order these keys would have been added + # when PYTHONHASHSEED=0 + egg_info['tag_build'] = self.tags() + egg_info['tag_date'] = 0 + edit_config(filename, dict(egg_info=egg_info)) + + def finalize_options(self): + # Note: we need to capture the current value returned + # by `self.tagged_version()`, so we can later update + # `self.distribution.metadata.version` without + # repercussions. + self.egg_name = self.name + self.egg_version = self.tagged_version() + parsed_version = parse_version(self.egg_version) + + try: + is_version = isinstance(parsed_version, packaging.version.Version) + spec = "%s==%s" if is_version else "%s===%s" + Requirement(spec % (self.egg_name, self.egg_version)) + except ValueError as e: + raise distutils.errors.DistutilsOptionError( + "Invalid distribution name or version syntax: %s-%s" % + (self.egg_name, self.egg_version) + ) from e + + if self.egg_base is None: + dirs = self.distribution.package_dir + self.egg_base = (dirs or {}).get('', os.curdir) + + self.ensure_dirname('egg_base') + self.egg_info = to_filename(self.egg_name) + '.egg-info' + if self.egg_base != os.curdir: + self.egg_info = os.path.join(self.egg_base, self.egg_info) + if '-' in self.egg_name: + self.check_broken_egg_info() + + # Set package version for the benefit of dumber commands + # (e.g. sdist, bdist_wininst, etc.) + # + self.distribution.metadata.version = self.egg_version + + # If we bootstrapped around the lack of a PKG-INFO, as might be the + # case in a fresh checkout, make sure that any special tags get added + # to the version info + # + pd = self.distribution._patched_dist + if pd is not None and pd.key == self.egg_name.lower(): + pd._version = self.egg_version + pd._parsed_version = parse_version(self.egg_version) + self.distribution._patched_dist = None + + def write_or_delete_file(self, what, filename, data, force=False): + """Write `data` to `filename` or delete if empty + + If `data` is non-empty, this routine is the same as ``write_file()``. + If `data` is empty but not ``None``, this is the same as calling + ``delete_file(filename)`. If `data` is ``None``, then this is a no-op + unless `filename` exists, in which case a warning is issued about the + orphaned file (if `force` is false), or deleted (if `force` is true). + """ + if data: + self.write_file(what, filename, data) + elif os.path.exists(filename): + if data is None and not force: + log.warn( + "%s not set in setup(), but %s exists", what, filename + ) + return + else: + self.delete_file(filename) + + def write_file(self, what, filename, data): + """Write `data` to `filename` (if not a dry run) after announcing it + + `what` is used in a log message to identify what is being written + to the file. + """ + log.info("writing %s to %s", what, filename) + data = data.encode("utf-8") + if not self.dry_run: + f = open(filename, 'wb') + f.write(data) + f.close() + + def delete_file(self, filename): + """Delete `filename` (if not a dry run) after announcing it""" + log.info("deleting %s", filename) + if not self.dry_run: + os.unlink(filename) + + def run(self): + self.mkpath(self.egg_info) + os.utime(self.egg_info, None) + for ep in metadata.entry_points(group='egg_info.writers'): + self.distribution._install_dependencies(ep) + writer = ep.load() + writer(self, ep.name, os.path.join(self.egg_info, ep.name)) + + # Get rid of native_libs.txt if it was put there by older bdist_egg + nl = os.path.join(self.egg_info, "native_libs.txt") + if os.path.exists(nl): + self.delete_file(nl) + + self.find_sources() + + def find_sources(self): + """Generate SOURCES.txt manifest file""" + manifest_filename = os.path.join(self.egg_info, "SOURCES.txt") + mm = manifest_maker(self.distribution) + mm.manifest = manifest_filename + mm.run() + self.filelist = mm.filelist + + def check_broken_egg_info(self): + bei = self.egg_name + '.egg-info' + if self.egg_base != os.curdir: + bei = os.path.join(self.egg_base, bei) + if os.path.exists(bei): + log.warn( + "-" * 78 + '\n' + "Note: Your current .egg-info directory has a '-' in its name;" + '\nthis will not work correctly with "setup.py develop".\n\n' + 'Please rename %s to %s to correct this problem.\n' + '-' * 78, + bei, self.egg_info + ) + self.broken_egg_info = self.egg_info + self.egg_info = bei # make it work for now + + +class FileList(_FileList): + # Implementations of the various MANIFEST.in commands + + def process_template_line(self, line): + # Parse the line: split it up, make sure the right number of words + # is there, and return the relevant words. 'action' is always + # defined: it's the first word of the line. Which of the other + # three are defined depends on the action; it'll be either + # patterns, (dir and patterns), or (dir_pattern). + (action, patterns, dir, dir_pattern) = self._parse_template_line(line) + + action_map = { + 'include': self.include, + 'exclude': self.exclude, + 'global-include': self.global_include, + 'global-exclude': self.global_exclude, + 'recursive-include': functools.partial( + self.recursive_include, dir, + ), + 'recursive-exclude': functools.partial( + self.recursive_exclude, dir, + ), + 'graft': self.graft, + 'prune': self.prune, + } + log_map = { + 'include': "warning: no files found matching '%s'", + 'exclude': ( + "warning: no previously-included files found " + "matching '%s'" + ), + 'global-include': ( + "warning: no files found matching '%s' " + "anywhere in distribution" + ), + 'global-exclude': ( + "warning: no previously-included files matching " + "'%s' found anywhere in distribution" + ), + 'recursive-include': ( + "warning: no files found matching '%s' " + "under directory '%s'" + ), + 'recursive-exclude': ( + "warning: no previously-included files matching " + "'%s' found under directory '%s'" + ), + 'graft': "warning: no directories found matching '%s'", + 'prune': "no previously-included directories found matching '%s'", + } + + try: + process_action = action_map[action] + except KeyError: + raise DistutilsInternalError( + "this cannot happen: invalid action '{action!s}'". + format(action=action), + ) + + # OK, now we know that the action is valid and we have the + # right number of words on the line for that action -- so we + # can proceed with minimal error-checking. + + action_is_recursive = action.startswith('recursive-') + if action in {'graft', 'prune'}: + patterns = [dir_pattern] + extra_log_args = (dir, ) if action_is_recursive else () + log_tmpl = log_map[action] + + self.debug_print( + ' '.join( + [action] + + ([dir] if action_is_recursive else []) + + patterns, + ) + ) + for pattern in patterns: + if not process_action(pattern): + log.warn(log_tmpl, pattern, *extra_log_args) + + def _remove_files(self, predicate): + """ + Remove all files from the file list that match the predicate. + Return True if any matching files were removed + """ + found = False + for i in range(len(self.files) - 1, -1, -1): + if predicate(self.files[i]): + self.debug_print(" removing " + self.files[i]) + del self.files[i] + found = True + return found + + def include(self, pattern): + """Include files that match 'pattern'.""" + found = [f for f in glob(pattern) if not os.path.isdir(f)] + self.extend(found) + return bool(found) + + def exclude(self, pattern): + """Exclude files that match 'pattern'.""" + match = translate_pattern(pattern) + return self._remove_files(match.match) + + def recursive_include(self, dir, pattern): + """ + Include all files anywhere in 'dir/' that match the pattern. + """ + full_pattern = os.path.join(dir, '**', pattern) + found = [f for f in glob(full_pattern, recursive=True) + if not os.path.isdir(f)] + self.extend(found) + return bool(found) + + def recursive_exclude(self, dir, pattern): + """ + Exclude any file anywhere in 'dir/' that match the pattern. + """ + match = translate_pattern(os.path.join(dir, '**', pattern)) + return self._remove_files(match.match) + + def graft(self, dir): + """Include all files from 'dir/'.""" + found = [ + item + for match_dir in glob(dir) + for item in distutils.filelist.findall(match_dir) + ] + self.extend(found) + return bool(found) + + def prune(self, dir): + """Filter out files from 'dir/'.""" + match = translate_pattern(os.path.join(dir, '**')) + return self._remove_files(match.match) + + def global_include(self, pattern): + """ + Include all files anywhere in the current directory that match the + pattern. This is very inefficient on large file trees. + """ + if self.allfiles is None: + self.findall() + match = translate_pattern(os.path.join('**', pattern)) + found = [f for f in self.allfiles if match.match(f)] + self.extend(found) + return bool(found) + + def global_exclude(self, pattern): + """ + Exclude all files anywhere that match the pattern. + """ + match = translate_pattern(os.path.join('**', pattern)) + return self._remove_files(match.match) + + def append(self, item): + if item.endswith('\r'): # Fix older sdists built on Windows + item = item[:-1] + path = convert_path(item) + + if self._safe_path(path): + self.files.append(path) + + def extend(self, paths): + self.files.extend(filter(self._safe_path, paths)) + + def _repair(self): + """ + Replace self.files with only safe paths + + Because some owners of FileList manipulate the underlying + ``files`` attribute directly, this method must be called to + repair those paths. + """ + self.files = list(filter(self._safe_path, self.files)) + + def _safe_path(self, path): + enc_warn = "'%s' not %s encodable -- skipping" + + # To avoid accidental trans-codings errors, first to unicode + u_path = unicode_utils.filesys_decode(path) + if u_path is None: + log.warn("'%s' in unexpected encoding -- skipping" % path) + return False + + # Must ensure utf-8 encodability + utf8_path = unicode_utils.try_encode(u_path, "utf-8") + if utf8_path is None: + log.warn(enc_warn, path, 'utf-8') + return False + + try: + # accept is either way checks out + if os.path.exists(u_path) or os.path.exists(utf8_path): + return True + # this will catch any encode errors decoding u_path + except UnicodeEncodeError: + log.warn(enc_warn, path, sys.getfilesystemencoding()) + + +class manifest_maker(sdist): + template = "MANIFEST.in" + + def initialize_options(self): + self.use_defaults = 1 + self.prune = 1 + self.manifest_only = 1 + self.force_manifest = 1 + + def finalize_options(self): + pass + + def run(self): + self.filelist = FileList() + if not os.path.exists(self.manifest): + self.write_manifest() # it must exist so it'll get in the list + self.add_defaults() + if os.path.exists(self.template): + self.read_template() + self.add_license_files() + self.prune_file_list() + self.filelist.sort() + self.filelist.remove_duplicates() + self.write_manifest() + + def _manifest_normalize(self, path): + path = unicode_utils.filesys_decode(path) + return path.replace(os.sep, '/') + + def write_manifest(self): + """ + Write the file list in 'self.filelist' to the manifest file + named by 'self.manifest'. + """ + self.filelist._repair() + + # Now _repairs should encodability, but not unicode + files = [self._manifest_normalize(f) for f in self.filelist.files] + msg = "writing manifest file '%s'" % self.manifest + self.execute(write_file, (self.manifest, files), msg) + + def warn(self, msg): + if not self._should_suppress_warning(msg): + sdist.warn(self, msg) + + @staticmethod + def _should_suppress_warning(msg): + """ + suppress missing-file warnings from sdist + """ + return re.match(r"standard file .*not found", msg) + + def add_defaults(self): + sdist.add_defaults(self) + self.filelist.append(self.template) + self.filelist.append(self.manifest) + rcfiles = list(walk_revctrl()) + if rcfiles: + self.filelist.extend(rcfiles) + elif os.path.exists(self.manifest): + self.read_manifest() + + if os.path.exists("setup.py"): + # setup.py should be included by default, even if it's not + # the script called to create the sdist + self.filelist.append("setup.py") + + ei_cmd = self.get_finalized_command('egg_info') + self.filelist.graft(ei_cmd.egg_info) + + def add_license_files(self): + license_files = self.distribution.metadata.license_files or [] + for lf in license_files: + log.info("adding license file '%s'", lf) + pass + self.filelist.extend(license_files) + + def prune_file_list(self): + build = self.get_finalized_command('build') + base_dir = self.distribution.get_fullname() + self.filelist.prune(build.build_base) + self.filelist.prune(base_dir) + sep = re.escape(os.sep) + self.filelist.exclude_pattern(r'(^|' + sep + r')(RCS|CVS|\.svn)' + sep, + is_regex=1) + + def _safe_data_files(self, build_py): + """ + The parent class implementation of this method + (``sdist``) will try to include data files, which + might cause recursion problems when + ``include_package_data=True``. + + Therefore, avoid triggering any attempt of + analyzing/building the manifest again. + """ + if hasattr(build_py, 'get_data_files_without_manifest'): + return build_py.get_data_files_without_manifest() + + warnings.warn( + "Custom 'build_py' does not implement " + "'get_data_files_without_manifest'.\nPlease extend command classes" + " from setuptools instead of distutils.", + SetuptoolsDeprecationWarning + ) + return build_py.get_data_files() + + +def write_file(filename, contents): + """Create a file with the specified name and write 'contents' (a + sequence of strings without line terminators) to it. + """ + contents = "\n".join(contents) + + # assuming the contents has been vetted for utf-8 encoding + contents = contents.encode("utf-8") + + with open(filename, "wb") as f: # always write POSIX-style manifest + f.write(contents) + + +def write_pkg_info(cmd, basename, filename): + log.info("writing %s", filename) + if not cmd.dry_run: + metadata = cmd.distribution.metadata + metadata.version, oldver = cmd.egg_version, metadata.version + metadata.name, oldname = cmd.egg_name, metadata.name + + try: + # write unescaped data to PKG-INFO, so older pkg_resources + # can still parse it + metadata.write_pkg_info(cmd.egg_info) + finally: + metadata.name, metadata.version = oldname, oldver + + safe = getattr(cmd.distribution, 'zip_safe', None) + + bdist_egg.write_safety_flag(cmd.egg_info, safe) + + +def warn_depends_obsolete(cmd, basename, filename): + if os.path.exists(filename): + log.warn( + "WARNING: 'depends.txt' is not used by setuptools 0.6!\n" + "Use the install_requires/extras_require setup() args instead." + ) + + +def _write_requirements(stream, reqs): + lines = yield_lines(reqs or ()) + + def append_cr(line): + return line + '\n' + lines = map(append_cr, lines) + stream.writelines(lines) + + +def write_requirements(cmd, basename, filename): + dist = cmd.distribution + data = io.StringIO() + _write_requirements(data, dist.install_requires) + extras_require = dist.extras_require or {} + for extra in sorted(extras_require): + data.write('\n[{extra}]\n'.format(**vars())) + _write_requirements(data, extras_require[extra]) + cmd.write_or_delete_file("requirements", filename, data.getvalue()) + + +def write_setup_requirements(cmd, basename, filename): + data = io.StringIO() + _write_requirements(data, cmd.distribution.setup_requires) + cmd.write_or_delete_file("setup-requirements", filename, data.getvalue()) + + +def write_toplevel_names(cmd, basename, filename): + pkgs = dict.fromkeys( + [ + k.split('.', 1)[0] + for k in cmd.distribution.iter_distribution_names() + ] + ) + cmd.write_file("top-level names", filename, '\n'.join(sorted(pkgs)) + '\n') + + +def overwrite_arg(cmd, basename, filename): + write_arg(cmd, basename, filename, True) + + +def write_arg(cmd, basename, filename, force=False): + argname = os.path.splitext(basename)[0] + value = getattr(cmd.distribution, argname, None) + if value is not None: + value = '\n'.join(value) + '\n' + cmd.write_or_delete_file(argname, filename, value, force) + + +def write_entries(cmd, basename, filename): + eps = _entry_points.load(cmd.distribution.entry_points) + defn = _entry_points.render(eps) + cmd.write_or_delete_file('entry points', filename, defn, True) + + +def get_pkg_info_revision(): + """ + Get a -r### off of PKG-INFO Version in case this is an sdist of + a subversion revision. + """ + warnings.warn( + "get_pkg_info_revision is deprecated.", EggInfoDeprecationWarning) + if os.path.exists('PKG-INFO'): + with io.open('PKG-INFO') as f: + for line in f: + match = re.match(r"Version:.*-r(\d+)\s*$", line) + if match: + return int(match.group(1)) + return 0 + + +class EggInfoDeprecationWarning(SetuptoolsDeprecationWarning): + """Deprecated behavior warning for EggInfo, bypassing suppression.""" diff --git a/venv/Lib/site-packages/setuptools/command/install.py b/venv/Lib/site-packages/setuptools/command/install.py new file mode 100644 index 0000000..35e54d2 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/command/install.py @@ -0,0 +1,132 @@ +from distutils.errors import DistutilsArgError +import inspect +import glob +import warnings +import platform +import distutils.command.install as orig + +import setuptools + +# Prior to numpy 1.9, NumPy relies on the '_install' name, so provide it for +# now. See https://github.com/pypa/setuptools/issues/199/ +_install = orig.install + + +class install(orig.install): + """Use easy_install to install the package, w/dependencies""" + + user_options = orig.install.user_options + [ + ('old-and-unmanageable', None, "Try not to use this!"), + ('single-version-externally-managed', None, + "used by system package builders to create 'flat' eggs"), + ] + boolean_options = orig.install.boolean_options + [ + 'old-and-unmanageable', 'single-version-externally-managed', + ] + new_commands = [ + ('install_egg_info', lambda self: True), + ('install_scripts', lambda self: True), + ] + _nc = dict(new_commands) + + def initialize_options(self): + + warnings.warn( + "setup.py install is deprecated. " + "Use build and pip and other standards-based tools.", + setuptools.SetuptoolsDeprecationWarning, + ) + + orig.install.initialize_options(self) + self.old_and_unmanageable = None + self.single_version_externally_managed = None + + def finalize_options(self): + orig.install.finalize_options(self) + if self.root: + self.single_version_externally_managed = True + elif self.single_version_externally_managed: + if not self.root and not self.record: + raise DistutilsArgError( + "You must specify --record or --root when building system" + " packages" + ) + + def handle_extra_path(self): + if self.root or self.single_version_externally_managed: + # explicit backward-compatibility mode, allow extra_path to work + return orig.install.handle_extra_path(self) + + # Ignore extra_path when installing an egg (or being run by another + # command without --root or --single-version-externally-managed + self.path_file = None + self.extra_dirs = '' + + def run(self): + # Explicit request for old-style install? Just do it + if self.old_and_unmanageable or self.single_version_externally_managed: + return orig.install.run(self) + + if not self._called_from_setup(inspect.currentframe()): + # Run in backward-compatibility mode to support bdist_* commands. + orig.install.run(self) + else: + self.do_egg_install() + + @staticmethod + def _called_from_setup(run_frame): + """ + Attempt to detect whether run() was called from setup() or by another + command. If called by setup(), the parent caller will be the + 'run_command' method in 'distutils.dist', and *its* caller will be + the 'run_commands' method. If called any other way, the + immediate caller *might* be 'run_command', but it won't have been + called by 'run_commands'. Return True in that case or if a call stack + is unavailable. Return False otherwise. + """ + if run_frame is None: + msg = "Call stack not available. bdist_* commands may fail." + warnings.warn(msg) + if platform.python_implementation() == 'IronPython': + msg = "For best results, pass -X:Frames to enable call stack." + warnings.warn(msg) + return True + res = inspect.getouterframes(run_frame)[2] + caller, = res[:1] + info = inspect.getframeinfo(caller) + caller_module = caller.f_globals.get('__name__', '') + return ( + caller_module == 'distutils.dist' + and info.function == 'run_commands' + ) + + def do_egg_install(self): + + easy_install = self.distribution.get_command_class('easy_install') + + cmd = easy_install( + self.distribution, args="x", root=self.root, record=self.record, + ) + cmd.ensure_finalized() # finalize before bdist_egg munges install cmd + cmd.always_copy_from = '.' # make sure local-dir eggs get installed + + # pick up setup-dir .egg files only: no .egg-info + cmd.package_index.scan(glob.glob('*.egg')) + + self.run_command('bdist_egg') + args = [self.distribution.get_command_obj('bdist_egg').egg_output] + + if setuptools.bootstrap_install_from: + # Bootstrap self-installation of setuptools + args.insert(0, setuptools.bootstrap_install_from) + + cmd.args = args + cmd.run(show_deprecation=False) + setuptools.bootstrap_install_from = None + + +# XXX Python 3.1 doesn't see _nc if this is inside the class +install.sub_commands = ( + [cmd for cmd in orig.install.sub_commands if cmd[0] not in install._nc] + + install.new_commands +) diff --git a/venv/Lib/site-packages/setuptools/command/install_egg_info.py b/venv/Lib/site-packages/setuptools/command/install_egg_info.py new file mode 100644 index 0000000..65ede40 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/command/install_egg_info.py @@ -0,0 +1,63 @@ +from distutils import log, dir_util +import os + +from setuptools import Command +from setuptools import namespaces +from setuptools.archive_util import unpack_archive +from .._path import ensure_directory +import pkg_resources + + +class install_egg_info(namespaces.Installer, Command): + """Install an .egg-info directory for the package""" + + description = "Install an .egg-info directory for the package" + + user_options = [ + ('install-dir=', 'd', "directory to install to"), + ] + + def initialize_options(self): + self.install_dir = None + + def finalize_options(self): + self.set_undefined_options('install_lib', + ('install_dir', 'install_dir')) + ei_cmd = self.get_finalized_command("egg_info") + basename = pkg_resources.Distribution( + None, None, ei_cmd.egg_name, ei_cmd.egg_version + ).egg_name() + '.egg-info' + self.source = ei_cmd.egg_info + self.target = os.path.join(self.install_dir, basename) + self.outputs = [] + + def run(self): + self.run_command('egg_info') + if os.path.isdir(self.target) and not os.path.islink(self.target): + dir_util.remove_tree(self.target, dry_run=self.dry_run) + elif os.path.exists(self.target): + self.execute(os.unlink, (self.target,), "Removing " + self.target) + if not self.dry_run: + ensure_directory(self.target) + self.execute( + self.copytree, (), "Copying %s to %s" % (self.source, self.target) + ) + self.install_namespaces() + + def get_outputs(self): + return self.outputs + + def copytree(self): + # Copy the .egg-info tree to site-packages + def skimmer(src, dst): + # filter out source-control directories; note that 'src' is always + # a '/'-separated path, regardless of platform. 'dst' is a + # platform-specific path. + for skip in '.svn/', 'CVS/': + if src.startswith(skip) or '/' + skip in src: + return None + self.outputs.append(dst) + log.debug("Copying %s to %s", src, dst) + return dst + + unpack_archive(self.source, self.target, skimmer) diff --git a/venv/Lib/site-packages/setuptools/command/install_lib.py b/venv/Lib/site-packages/setuptools/command/install_lib.py new file mode 100644 index 0000000..2e9d875 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/command/install_lib.py @@ -0,0 +1,122 @@ +import os +import sys +from itertools import product, starmap +import distutils.command.install_lib as orig + + +class install_lib(orig.install_lib): + """Don't add compiled flags to filenames of non-Python files""" + + def run(self): + self.build() + outfiles = self.install() + if outfiles is not None: + # always compile, in case we have any extension stubs to deal with + self.byte_compile(outfiles) + + def get_exclusions(self): + """ + Return a collections.Sized collections.Container of paths to be + excluded for single_version_externally_managed installations. + """ + all_packages = ( + pkg + for ns_pkg in self._get_SVEM_NSPs() + for pkg in self._all_packages(ns_pkg) + ) + + excl_specs = product(all_packages, self._gen_exclusion_paths()) + return set(starmap(self._exclude_pkg_path, excl_specs)) + + def _exclude_pkg_path(self, pkg, exclusion_path): + """ + Given a package name and exclusion path within that package, + compute the full exclusion path. + """ + parts = pkg.split('.') + [exclusion_path] + return os.path.join(self.install_dir, *parts) + + @staticmethod + def _all_packages(pkg_name): + """ + >>> list(install_lib._all_packages('foo.bar.baz')) + ['foo.bar.baz', 'foo.bar', 'foo'] + """ + while pkg_name: + yield pkg_name + pkg_name, sep, child = pkg_name.rpartition('.') + + def _get_SVEM_NSPs(self): + """ + Get namespace packages (list) but only for + single_version_externally_managed installations and empty otherwise. + """ + # TODO: is it necessary to short-circuit here? i.e. what's the cost + # if get_finalized_command is called even when namespace_packages is + # False? + if not self.distribution.namespace_packages: + return [] + + install_cmd = self.get_finalized_command('install') + svem = install_cmd.single_version_externally_managed + + return self.distribution.namespace_packages if svem else [] + + @staticmethod + def _gen_exclusion_paths(): + """ + Generate file paths to be excluded for namespace packages (bytecode + cache files). + """ + # always exclude the package module itself + yield '__init__.py' + + yield '__init__.pyc' + yield '__init__.pyo' + + if not hasattr(sys, 'implementation'): + return + + base = os.path.join( + '__pycache__', '__init__.' + sys.implementation.cache_tag) + yield base + '.pyc' + yield base + '.pyo' + yield base + '.opt-1.pyc' + yield base + '.opt-2.pyc' + + def copy_tree( + self, infile, outfile, + preserve_mode=1, preserve_times=1, preserve_symlinks=0, level=1 + ): + assert preserve_mode and preserve_times and not preserve_symlinks + exclude = self.get_exclusions() + + if not exclude: + return orig.install_lib.copy_tree(self, infile, outfile) + + # Exclude namespace package __init__.py* files from the output + + from setuptools.archive_util import unpack_directory + from distutils import log + + outfiles = [] + + def pf(src, dst): + if dst in exclude: + log.warn("Skipping installation of %s (namespace package)", + dst) + return False + + log.info("copying %s -> %s", src, os.path.dirname(dst)) + outfiles.append(dst) + return dst + + unpack_directory(infile, outfile, pf) + return outfiles + + def get_outputs(self): + outputs = orig.install_lib.get_outputs(self) + exclude = self.get_exclusions() + if exclude: + return [f for f in outputs if f not in exclude] + return outputs diff --git a/venv/Lib/site-packages/setuptools/command/install_scripts.py b/venv/Lib/site-packages/setuptools/command/install_scripts.py new file mode 100644 index 0000000..aeb0e42 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/command/install_scripts.py @@ -0,0 +1,70 @@ +from distutils import log +import distutils.command.install_scripts as orig +from distutils.errors import DistutilsModuleError +import os +import sys + +from pkg_resources import Distribution, PathMetadata +from .._path import ensure_directory + + +class install_scripts(orig.install_scripts): + """Do normal script install, plus any egg_info wrapper scripts""" + + def initialize_options(self): + orig.install_scripts.initialize_options(self) + self.no_ep = False + + def run(self): + import setuptools.command.easy_install as ei + + self.run_command("egg_info") + if self.distribution.scripts: + orig.install_scripts.run(self) # run first to set up self.outfiles + else: + self.outfiles = [] + if self.no_ep: + # don't install entry point scripts into .egg file! + return + + ei_cmd = self.get_finalized_command("egg_info") + dist = Distribution( + ei_cmd.egg_base, PathMetadata(ei_cmd.egg_base, ei_cmd.egg_info), + ei_cmd.egg_name, ei_cmd.egg_version, + ) + bs_cmd = self.get_finalized_command('build_scripts') + exec_param = getattr(bs_cmd, 'executable', None) + try: + bw_cmd = self.get_finalized_command("bdist_wininst") + is_wininst = getattr(bw_cmd, '_is_running', False) + except (ImportError, DistutilsModuleError): + is_wininst = False + writer = ei.ScriptWriter + if is_wininst: + exec_param = "python.exe" + writer = ei.WindowsScriptWriter + if exec_param == sys.executable: + # In case the path to the Python executable contains a space, wrap + # it so it's not split up. + exec_param = [exec_param] + # resolve the writer to the environment + writer = writer.best() + cmd = writer.command_spec_class.best().from_param(exec_param) + for args in writer.get_args(dist, cmd.as_header()): + self.write_script(*args) + + def write_script(self, script_name, contents, mode="t", *ignored): + """Write an executable file to the scripts directory""" + from setuptools.command.easy_install import chmod, current_umask + + log.info("Installing %s script to %s", script_name, self.install_dir) + target = os.path.join(self.install_dir, script_name) + self.outfiles.append(target) + + mask = current_umask() + if not self.dry_run: + ensure_directory(target) + f = open(target, "w" + mode) + f.write(contents) + f.close() + chmod(target, 0o777 - mask) diff --git a/venv/Lib/site-packages/setuptools/command/launcher manifest.xml b/venv/Lib/site-packages/setuptools/command/launcher manifest.xml new file mode 100644 index 0000000..5972a96 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/command/launcher manifest.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + diff --git a/venv/Lib/site-packages/setuptools/command/py36compat.py b/venv/Lib/site-packages/setuptools/command/py36compat.py new file mode 100644 index 0000000..343547a --- /dev/null +++ b/venv/Lib/site-packages/setuptools/command/py36compat.py @@ -0,0 +1,134 @@ +import os +from glob import glob +from distutils.util import convert_path +from distutils.command import sdist + + +class sdist_add_defaults: + """ + Mix-in providing forward-compatibility for functionality as found in + distutils on Python 3.7. + + Do not edit the code in this class except to update functionality + as implemented in distutils. Instead, override in the subclass. + """ + + def add_defaults(self): + """Add all the default files to self.filelist: + - README or README.txt + - setup.py + - test/test*.py + - all pure Python modules mentioned in setup script + - all files pointed by package_data (build_py) + - all files defined in data_files. + - all files defined as scripts. + - all C sources listed as part of extensions or C libraries + in the setup script (doesn't catch C headers!) + Warns if (README or README.txt) or setup.py are missing; everything + else is optional. + """ + self._add_defaults_standards() + self._add_defaults_optional() + self._add_defaults_python() + self._add_defaults_data_files() + self._add_defaults_ext() + self._add_defaults_c_libs() + self._add_defaults_scripts() + + @staticmethod + def _cs_path_exists(fspath): + """ + Case-sensitive path existence check + + >>> sdist_add_defaults._cs_path_exists(__file__) + True + >>> sdist_add_defaults._cs_path_exists(__file__.upper()) + False + """ + if not os.path.exists(fspath): + return False + # make absolute so we always have a directory + abspath = os.path.abspath(fspath) + directory, filename = os.path.split(abspath) + return filename in os.listdir(directory) + + def _add_defaults_standards(self): + standards = [self.READMES, self.distribution.script_name] + for fn in standards: + if isinstance(fn, tuple): + alts = fn + got_it = False + for fn in alts: + if self._cs_path_exists(fn): + got_it = True + self.filelist.append(fn) + break + + if not got_it: + self.warn("standard file not found: should have one of " + + ', '.join(alts)) + else: + if self._cs_path_exists(fn): + self.filelist.append(fn) + else: + self.warn("standard file '%s' not found" % fn) + + def _add_defaults_optional(self): + optional = ['test/test*.py', 'setup.cfg'] + for pattern in optional: + files = filter(os.path.isfile, glob(pattern)) + self.filelist.extend(files) + + def _add_defaults_python(self): + # build_py is used to get: + # - python modules + # - files defined in package_data + build_py = self.get_finalized_command('build_py') + + # getting python files + if self.distribution.has_pure_modules(): + self.filelist.extend(build_py.get_source_files()) + + # getting package_data files + # (computed in build_py.data_files by build_py.finalize_options) + for pkg, src_dir, build_dir, filenames in build_py.data_files: + for filename in filenames: + self.filelist.append(os.path.join(src_dir, filename)) + + def _add_defaults_data_files(self): + # getting distribution.data_files + if self.distribution.has_data_files(): + for item in self.distribution.data_files: + if isinstance(item, str): + # plain file + item = convert_path(item) + if os.path.isfile(item): + self.filelist.append(item) + else: + # a (dirname, filenames) tuple + dirname, filenames = item + for f in filenames: + f = convert_path(f) + if os.path.isfile(f): + self.filelist.append(f) + + def _add_defaults_ext(self): + if self.distribution.has_ext_modules(): + build_ext = self.get_finalized_command('build_ext') + self.filelist.extend(build_ext.get_source_files()) + + def _add_defaults_c_libs(self): + if self.distribution.has_c_libraries(): + build_clib = self.get_finalized_command('build_clib') + self.filelist.extend(build_clib.get_source_files()) + + def _add_defaults_scripts(self): + if self.distribution.has_scripts(): + build_scripts = self.get_finalized_command('build_scripts') + self.filelist.extend(build_scripts.get_source_files()) + + +if hasattr(sdist.sdist, '_add_defaults_standards'): + # disable the functionality already available upstream + class sdist_add_defaults: # noqa + pass diff --git a/venv/Lib/site-packages/setuptools/command/register.py b/venv/Lib/site-packages/setuptools/command/register.py new file mode 100644 index 0000000..b8266b9 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/command/register.py @@ -0,0 +1,18 @@ +from distutils import log +import distutils.command.register as orig + +from setuptools.errors import RemovedCommandError + + +class register(orig.register): + """Formerly used to register packages on PyPI.""" + + def run(self): + msg = ( + "The register command has been removed, use twine to upload " + + "instead (https://pypi.org/p/twine)" + ) + + self.announce("ERROR: " + msg, log.ERROR) + + raise RemovedCommandError(msg) diff --git a/venv/Lib/site-packages/setuptools/command/rotate.py b/venv/Lib/site-packages/setuptools/command/rotate.py new file mode 100644 index 0000000..74795ba --- /dev/null +++ b/venv/Lib/site-packages/setuptools/command/rotate.py @@ -0,0 +1,64 @@ +from distutils.util import convert_path +from distutils import log +from distutils.errors import DistutilsOptionError +import os +import shutil + +from setuptools import Command + + +class rotate(Command): + """Delete older distributions""" + + description = "delete older distributions, keeping N newest files" + user_options = [ + ('match=', 'm', "patterns to match (required)"), + ('dist-dir=', 'd', "directory where the distributions are"), + ('keep=', 'k', "number of matching distributions to keep"), + ] + + boolean_options = [] + + def initialize_options(self): + self.match = None + self.dist_dir = None + self.keep = None + + def finalize_options(self): + if self.match is None: + raise DistutilsOptionError( + "Must specify one or more (comma-separated) match patterns " + "(e.g. '.zip' or '.egg')" + ) + if self.keep is None: + raise DistutilsOptionError("Must specify number of files to keep") + try: + self.keep = int(self.keep) + except ValueError as e: + raise DistutilsOptionError("--keep must be an integer") from e + if isinstance(self.match, str): + self.match = [ + convert_path(p.strip()) for p in self.match.split(',') + ] + self.set_undefined_options('bdist', ('dist_dir', 'dist_dir')) + + def run(self): + self.run_command("egg_info") + from glob import glob + + for pattern in self.match: + pattern = self.distribution.get_name() + '*' + pattern + files = glob(os.path.join(self.dist_dir, pattern)) + files = [(os.path.getmtime(f), f) for f in files] + files.sort() + files.reverse() + + log.info("%d file(s) matching %s", len(files), pattern) + files = files[self.keep:] + for (t, f) in files: + log.info("Deleting %s", f) + if not self.dry_run: + if os.path.isdir(f): + shutil.rmtree(f) + else: + os.unlink(f) diff --git a/venv/Lib/site-packages/setuptools/command/saveopts.py b/venv/Lib/site-packages/setuptools/command/saveopts.py new file mode 100644 index 0000000..611cec5 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/command/saveopts.py @@ -0,0 +1,22 @@ +from setuptools.command.setopt import edit_config, option_base + + +class saveopts(option_base): + """Save command-line options to a file""" + + description = "save supplied options to setup.cfg or other config file" + + def run(self): + dist = self.distribution + settings = {} + + for cmd in dist.command_options: + + if cmd == 'saveopts': + continue # don't save our own options! + + for opt, (src, val) in dist.get_option_dict(cmd).items(): + if src == "command line": + settings.setdefault(cmd, {})[opt] = val + + edit_config(self.filename, settings, self.dry_run) diff --git a/venv/Lib/site-packages/setuptools/command/sdist.py b/venv/Lib/site-packages/setuptools/command/sdist.py new file mode 100644 index 0000000..0ffeacf --- /dev/null +++ b/venv/Lib/site-packages/setuptools/command/sdist.py @@ -0,0 +1,196 @@ +from distutils import log +import distutils.command.sdist as orig +import os +import sys +import io +import contextlib + +from .py36compat import sdist_add_defaults + +from .._importlib import metadata + +_default_revctrl = list + + +def walk_revctrl(dirname=''): + """Find all files under revision control""" + for ep in metadata.entry_points(group='setuptools.file_finders'): + for item in ep.load()(dirname): + yield item + + +class sdist(sdist_add_defaults, orig.sdist): + """Smart sdist that finds anything supported by revision control""" + + user_options = [ + ('formats=', None, + "formats for source distribution (comma-separated list)"), + ('keep-temp', 'k', + "keep the distribution tree around after creating " + + "archive file(s)"), + ('dist-dir=', 'd', + "directory to put the source distribution archive(s) in " + "[default: dist]"), + ('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]"), + ] + + negative_opt = {} + + README_EXTENSIONS = ['', '.rst', '.txt', '.md'] + READMES = tuple('README{0}'.format(ext) for ext in README_EXTENSIONS) + + def run(self): + self.run_command('egg_info') + ei_cmd = self.get_finalized_command('egg_info') + self.filelist = ei_cmd.filelist + self.filelist.append(os.path.join(ei_cmd.egg_info, 'SOURCES.txt')) + self.check_readme() + + # Run sub commands + for cmd_name in self.get_sub_commands(): + self.run_command(cmd_name) + + self.make_distribution() + + dist_files = getattr(self.distribution, 'dist_files', []) + for file in self.archive_files: + data = ('sdist', '', file) + if data not in dist_files: + dist_files.append(data) + + def initialize_options(self): + orig.sdist.initialize_options(self) + + self._default_to_gztar() + + def _default_to_gztar(self): + # only needed on Python prior to 3.6. + if sys.version_info >= (3, 6, 0, 'beta', 1): + return + self.formats = ['gztar'] + + def make_distribution(self): + """ + Workaround for #516 + """ + with self._remove_os_link(): + orig.sdist.make_distribution(self) + + @staticmethod + @contextlib.contextmanager + def _remove_os_link(): + """ + In a context, remove and restore os.link if it exists + """ + + class NoValue: + pass + + orig_val = getattr(os, 'link', NoValue) + try: + del os.link + except Exception: + pass + try: + yield + finally: + if orig_val is not NoValue: + setattr(os, 'link', orig_val) + + def _add_defaults_optional(self): + super()._add_defaults_optional() + if os.path.isfile('pyproject.toml'): + self.filelist.append('pyproject.toml') + + def _add_defaults_python(self): + """getting python files""" + if self.distribution.has_pure_modules(): + build_py = self.get_finalized_command('build_py') + self.filelist.extend(build_py.get_source_files()) + self._add_data_files(self._safe_data_files(build_py)) + + def _safe_data_files(self, build_py): + """ + Since the ``sdist`` class is also used to compute the MANIFEST + (via :obj:`setuptools.command.egg_info.manifest_maker`), + there might be recursion problems when trying to obtain the list of + data_files and ``include_package_data=True`` (which in turn depends on + the files included in the MANIFEST). + + To avoid that, ``manifest_maker`` should be able to overwrite this + method and avoid recursive attempts to build/analyze the MANIFEST. + """ + return build_py.data_files + + def _add_data_files(self, data_files): + """ + Add data files as found in build_py.data_files. + """ + self.filelist.extend( + os.path.join(src_dir, name) + for _, src_dir, _, filenames in data_files + for name in filenames + ) + + def _add_defaults_data_files(self): + try: + super()._add_defaults_data_files() + except TypeError: + log.warn("data_files contains unexpected objects") + + def check_readme(self): + for f in self.READMES: + if os.path.exists(f): + return + else: + self.warn( + "standard file not found: should have one of " + + ', '.join(self.READMES) + ) + + def make_release_tree(self, base_dir, files): + orig.sdist.make_release_tree(self, base_dir, files) + + # Save any egg_info command line options used to create this sdist + dest = os.path.join(base_dir, 'setup.cfg') + if hasattr(os, 'link') and os.path.exists(dest): + # unlink and re-copy, since it might be hard-linked, and + # we don't want to change the source version + os.unlink(dest) + self.copy_file('setup.cfg', dest) + + self.get_finalized_command('egg_info').save_version_info(dest) + + def _manifest_is_not_generated(self): + # check for special comment used in 2.7.1 and higher + if not os.path.isfile(self.manifest): + return False + + with io.open(self.manifest, 'rb') as fp: + first_line = fp.readline() + return (first_line != + '# file GENERATED by distutils, do NOT edit\n'.encode()) + + def read_manifest(self): + """Read the manifest file (named by 'self.manifest') and use it to + fill in 'self.filelist', the list of files to include in the source + distribution. + """ + log.info("reading manifest file '%s'", self.manifest) + manifest = open(self.manifest, 'rb') + for line in manifest: + # The manifest must contain UTF-8. See #303. + try: + line = line.decode('UTF-8') + except UnicodeDecodeError: + log.warn("%r not UTF-8 decodable -- skipping" % line) + continue + # ignore comments and blank lines + line = line.strip() + if line.startswith('#') or not line: + continue + self.filelist.append(line) + manifest.close() diff --git a/venv/Lib/site-packages/setuptools/command/setopt.py b/venv/Lib/site-packages/setuptools/command/setopt.py new file mode 100644 index 0000000..6358c04 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/command/setopt.py @@ -0,0 +1,149 @@ +from distutils.util import convert_path +from distutils import log +from distutils.errors import DistutilsOptionError +import distutils +import os +import configparser + +from setuptools import Command + +__all__ = ['config_file', 'edit_config', 'option_base', 'setopt'] + + +def config_file(kind="local"): + """Get the filename of the distutils, local, global, or per-user config + + `kind` must be one of "local", "global", or "user" + """ + if kind == 'local': + return 'setup.cfg' + if kind == 'global': + return os.path.join( + os.path.dirname(distutils.__file__), 'distutils.cfg' + ) + if kind == 'user': + dot = os.name == 'posix' and '.' or '' + return os.path.expanduser(convert_path("~/%spydistutils.cfg" % dot)) + raise ValueError( + "config_file() type must be 'local', 'global', or 'user'", kind + ) + + +def edit_config(filename, settings, dry_run=False): + """Edit a configuration file to include `settings` + + `settings` is a dictionary of dictionaries or ``None`` values, keyed by + command/section name. A ``None`` value means to delete the entire section, + while a dictionary lists settings to be changed or deleted in that section. + A setting of ``None`` means to delete that setting. + """ + log.debug("Reading configuration from %s", filename) + opts = configparser.RawConfigParser() + opts.optionxform = lambda x: x + opts.read([filename]) + for section, options in settings.items(): + if options is None: + log.info("Deleting section [%s] from %s", section, filename) + opts.remove_section(section) + else: + if not opts.has_section(section): + log.debug("Adding new section [%s] to %s", section, filename) + opts.add_section(section) + for option, value in options.items(): + if value is None: + log.debug( + "Deleting %s.%s from %s", + section, option, filename + ) + opts.remove_option(section, option) + if not opts.options(section): + log.info("Deleting empty [%s] section from %s", + section, filename) + opts.remove_section(section) + else: + log.debug( + "Setting %s.%s to %r in %s", + section, option, value, filename + ) + opts.set(section, option, value) + + log.info("Writing %s", filename) + if not dry_run: + with open(filename, 'w') as f: + opts.write(f) + + +class option_base(Command): + """Abstract base class for commands that mess with config files""" + + user_options = [ + ('global-config', 'g', + "save options to the site-wide distutils.cfg file"), + ('user-config', 'u', + "save options to the current user's pydistutils.cfg file"), + ('filename=', 'f', + "configuration file to use (default=setup.cfg)"), + ] + + boolean_options = [ + 'global-config', 'user-config', + ] + + def initialize_options(self): + self.global_config = None + self.user_config = None + self.filename = None + + def finalize_options(self): + filenames = [] + if self.global_config: + filenames.append(config_file('global')) + if self.user_config: + filenames.append(config_file('user')) + if self.filename is not None: + filenames.append(self.filename) + if not filenames: + filenames.append(config_file('local')) + if len(filenames) > 1: + raise DistutilsOptionError( + "Must specify only one configuration file option", + filenames + ) + self.filename, = filenames + + +class setopt(option_base): + """Save command-line options to a file""" + + description = "set an option in setup.cfg or another config file" + + user_options = [ + ('command=', 'c', 'command to set an option for'), + ('option=', 'o', 'option to set'), + ('set-value=', 's', 'value of the option'), + ('remove', 'r', 'remove (unset) the value'), + ] + option_base.user_options + + boolean_options = option_base.boolean_options + ['remove'] + + def initialize_options(self): + option_base.initialize_options(self) + self.command = None + self.option = None + self.set_value = None + self.remove = None + + def finalize_options(self): + option_base.finalize_options(self) + if self.command is None or self.option is None: + raise DistutilsOptionError("Must specify --command *and* --option") + if self.set_value is None and not self.remove: + raise DistutilsOptionError("Must specify --set-value or --remove") + + def run(self): + edit_config( + self.filename, { + self.command: {self.option.replace('-', '_'): self.set_value} + }, + self.dry_run + ) diff --git a/venv/Lib/site-packages/setuptools/command/test.py b/venv/Lib/site-packages/setuptools/command/test.py new file mode 100644 index 0000000..652f3e4 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/command/test.py @@ -0,0 +1,251 @@ +import os +import operator +import sys +import contextlib +import itertools +import unittest +from distutils.errors import DistutilsError, DistutilsOptionError +from distutils import log +from unittest import TestLoader + +from pkg_resources import ( + resource_listdir, + resource_exists, + normalize_path, + working_set, + evaluate_marker, + add_activation_listener, + require, +) +from .._importlib import metadata +from setuptools import Command +from setuptools.extern.more_itertools import unique_everseen +from setuptools.extern.jaraco.functools import pass_none + + +class ScanningLoader(TestLoader): + def __init__(self): + TestLoader.__init__(self) + self._visited = set() + + def loadTestsFromModule(self, module, pattern=None): + """Return a suite of all tests cases contained in the given module + + If the module is a package, load tests from all the modules in it. + If the module has an ``additional_tests`` function, call it and add + the return value to the tests. + """ + if module in self._visited: + return None + self._visited.add(module) + + tests = [] + tests.append(TestLoader.loadTestsFromModule(self, module)) + + if hasattr(module, "additional_tests"): + tests.append(module.additional_tests()) + + if hasattr(module, '__path__'): + for file in resource_listdir(module.__name__, ''): + if file.endswith('.py') and file != '__init__.py': + submodule = module.__name__ + '.' + file[:-3] + else: + if resource_exists(module.__name__, file + '/__init__.py'): + submodule = module.__name__ + '.' + file + else: + continue + tests.append(self.loadTestsFromName(submodule)) + + if len(tests) != 1: + return self.suiteClass(tests) + else: + return tests[0] # don't create a nested suite for only one return + + +# adapted from jaraco.classes.properties:NonDataProperty +class NonDataProperty: + def __init__(self, fget): + self.fget = fget + + def __get__(self, obj, objtype=None): + if obj is None: + return self + return self.fget(obj) + + +class test(Command): + """Command to run unit tests after in-place build""" + + description = "run unit tests after in-place build (deprecated)" + + user_options = [ + ('test-module=', 'm', "Run 'test_suite' in specified module"), + ( + 'test-suite=', + 's', + "Run single test, case or suite (e.g. 'module.test_suite')", + ), + ('test-runner=', 'r', "Test runner to use"), + ] + + def initialize_options(self): + self.test_suite = None + self.test_module = None + self.test_loader = None + self.test_runner = None + + def finalize_options(self): + + if self.test_suite and self.test_module: + msg = "You may specify a module or a suite, but not both" + raise DistutilsOptionError(msg) + + if self.test_suite is None: + if self.test_module is None: + self.test_suite = self.distribution.test_suite + else: + self.test_suite = self.test_module + ".test_suite" + + if self.test_loader is None: + self.test_loader = getattr(self.distribution, 'test_loader', None) + if self.test_loader is None: + self.test_loader = "setuptools.command.test:ScanningLoader" + if self.test_runner is None: + self.test_runner = getattr(self.distribution, 'test_runner', None) + + @NonDataProperty + def test_args(self): + return list(self._test_args()) + + def _test_args(self): + if not self.test_suite and sys.version_info >= (2, 7): + yield 'discover' + if self.verbose: + yield '--verbose' + if self.test_suite: + yield self.test_suite + + def with_project_on_sys_path(self, func): + """ + Backward compatibility for project_on_sys_path context. + """ + with self.project_on_sys_path(): + func() + + @contextlib.contextmanager + def project_on_sys_path(self, include_dists=[]): + self.run_command('egg_info') + + # Build extensions in-place + self.reinitialize_command('build_ext', inplace=1) + self.run_command('build_ext') + + ei_cmd = self.get_finalized_command("egg_info") + + old_path = sys.path[:] + old_modules = sys.modules.copy() + + try: + project_path = normalize_path(ei_cmd.egg_base) + sys.path.insert(0, project_path) + working_set.__init__() + add_activation_listener(lambda dist: dist.activate()) + require('%s==%s' % (ei_cmd.egg_name, ei_cmd.egg_version)) + with self.paths_on_pythonpath([project_path]): + yield + finally: + sys.path[:] = old_path + sys.modules.clear() + sys.modules.update(old_modules) + working_set.__init__() + + @staticmethod + @contextlib.contextmanager + def paths_on_pythonpath(paths): + """ + Add the indicated paths to the head of the PYTHONPATH environment + variable so that subprocesses will also see the packages at + these paths. + + Do this in a context that restores the value on exit. + """ + nothing = object() + orig_pythonpath = os.environ.get('PYTHONPATH', nothing) + current_pythonpath = os.environ.get('PYTHONPATH', '') + try: + prefix = os.pathsep.join(unique_everseen(paths)) + to_join = filter(None, [prefix, current_pythonpath]) + new_path = os.pathsep.join(to_join) + if new_path: + os.environ['PYTHONPATH'] = new_path + yield + finally: + if orig_pythonpath is nothing: + os.environ.pop('PYTHONPATH', None) + else: + os.environ['PYTHONPATH'] = orig_pythonpath + + @staticmethod + def install_dists(dist): + """ + Install the requirements indicated by self.distribution and + return an iterable of the dists that were built. + """ + ir_d = dist.fetch_build_eggs(dist.install_requires) + tr_d = dist.fetch_build_eggs(dist.tests_require or []) + er_d = dist.fetch_build_eggs( + v + for k, v in dist.extras_require.items() + if k.startswith(':') and evaluate_marker(k[1:]) + ) + return itertools.chain(ir_d, tr_d, er_d) + + def run(self): + self.announce( + "WARNING: Testing via this command is deprecated and will be " + "removed in a future version. Users looking for a generic test " + "entry point independent of test runner are encouraged to use " + "tox.", + log.WARN, + ) + + installed_dists = self.install_dists(self.distribution) + + cmd = ' '.join(self._argv) + if self.dry_run: + self.announce('skipping "%s" (dry run)' % cmd) + return + + self.announce('running "%s"' % cmd) + + paths = map(operator.attrgetter('location'), installed_dists) + with self.paths_on_pythonpath(paths): + with self.project_on_sys_path(): + self.run_tests() + + def run_tests(self): + test = unittest.main( + None, + None, + self._argv, + testLoader=self._resolve_as_ep(self.test_loader), + testRunner=self._resolve_as_ep(self.test_runner), + exit=False, + ) + if not test.result.wasSuccessful(): + msg = 'Test failed: %s' % test.result + self.announce(msg, log.ERROR) + raise DistutilsError(msg) + + @property + def _argv(self): + return ['unittest'] + self.test_args + + @staticmethod + @pass_none + def _resolve_as_ep(val): + """ + Load the indicated attribute value, called, as a as if it were + specified as an entry point. + """ + return metadata.EntryPoint(value=val, name=None, group=None).load()() diff --git a/venv/Lib/site-packages/setuptools/command/upload.py b/venv/Lib/site-packages/setuptools/command/upload.py new file mode 100644 index 0000000..ec7f81e --- /dev/null +++ b/venv/Lib/site-packages/setuptools/command/upload.py @@ -0,0 +1,17 @@ +from distutils import log +from distutils.command import upload as orig + +from setuptools.errors import RemovedCommandError + + +class upload(orig.upload): + """Formerly used to upload packages to PyPI.""" + + def run(self): + msg = ( + "The upload command has been removed, use twine to upload " + + "instead (https://pypi.org/p/twine)" + ) + + self.announce("ERROR: " + msg, log.ERROR) + raise RemovedCommandError(msg) diff --git a/venv/Lib/site-packages/setuptools/command/upload_docs.py b/venv/Lib/site-packages/setuptools/command/upload_docs.py new file mode 100644 index 0000000..f429f56 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/command/upload_docs.py @@ -0,0 +1,204 @@ +# -*- coding: utf-8 -*- +"""upload_docs + +Implements a Distutils 'upload_docs' subcommand (upload documentation to +sites other than PyPi such as devpi). +""" + +from base64 import standard_b64encode +from distutils import log +from distutils.errors import DistutilsOptionError +import os +import socket +import zipfile +import tempfile +import shutil +import itertools +import functools +import http.client +import urllib.parse + +from .._importlib import metadata + +from .upload import upload + + +def _encode(s): + return s.encode('utf-8', 'surrogateescape') + + +class upload_docs(upload): + # override the default repository as upload_docs isn't + # supported by Warehouse (and won't be). + DEFAULT_REPOSITORY = 'https://pypi.python.org/pypi/' + + description = 'Upload documentation to sites other than PyPi such as devpi' + + user_options = [ + ('repository=', 'r', + "url of repository [default: %s]" % upload.DEFAULT_REPOSITORY), + ('show-response', None, + 'display full response text from server'), + ('upload-dir=', None, 'directory to upload'), + ] + boolean_options = upload.boolean_options + + def has_sphinx(self): + return bool( + self.upload_dir is None + and metadata.entry_points(group='distutils.commands', name='build_sphinx') + ) + + sub_commands = [('build_sphinx', has_sphinx)] + + def initialize_options(self): + upload.initialize_options(self) + self.upload_dir = None + self.target_dir = None + + def finalize_options(self): + upload.finalize_options(self) + if self.upload_dir is None: + if self.has_sphinx(): + build_sphinx = self.get_finalized_command('build_sphinx') + self.target_dir = dict(build_sphinx.builder_target_dirs)['html'] + else: + build = self.get_finalized_command('build') + self.target_dir = os.path.join(build.build_base, 'docs') + else: + self.ensure_dirname('upload_dir') + self.target_dir = self.upload_dir + if 'pypi.python.org' in self.repository: + log.warn("Upload_docs command is deprecated for PyPi. Use RTD instead.") + self.announce('Using upload directory %s' % self.target_dir) + + def create_zipfile(self, filename): + zip_file = zipfile.ZipFile(filename, "w") + try: + self.mkpath(self.target_dir) # just in case + for root, dirs, files in os.walk(self.target_dir): + if root == self.target_dir and not files: + tmpl = "no files found in upload directory '%s'" + raise DistutilsOptionError(tmpl % self.target_dir) + for name in files: + full = os.path.join(root, name) + relative = root[len(self.target_dir):].lstrip(os.path.sep) + dest = os.path.join(relative, name) + zip_file.write(full, dest) + finally: + zip_file.close() + + def run(self): + # Run sub commands + for cmd_name in self.get_sub_commands(): + self.run_command(cmd_name) + + tmp_dir = tempfile.mkdtemp() + name = self.distribution.metadata.get_name() + zip_file = os.path.join(tmp_dir, "%s.zip" % name) + try: + self.create_zipfile(zip_file) + self.upload_file(zip_file) + finally: + shutil.rmtree(tmp_dir) + + @staticmethod + def _build_part(item, sep_boundary): + key, values = item + title = '\nContent-Disposition: form-data; name="%s"' % key + # handle multiple entries for the same name + if not isinstance(values, list): + values = [values] + for value in values: + if isinstance(value, tuple): + title += '; filename="%s"' % value[0] + value = value[1] + else: + value = _encode(value) + yield sep_boundary + yield _encode(title) + yield b"\n\n" + yield value + if value and value[-1:] == b'\r': + yield b'\n' # write an extra newline (lurve Macs) + + @classmethod + def _build_multipart(cls, data): + """ + Build up the MIME payload for the POST data + """ + boundary = '--------------GHSKFJDLGDS7543FJKLFHRE75642756743254' + sep_boundary = b'\n--' + boundary.encode('ascii') + end_boundary = sep_boundary + b'--' + end_items = end_boundary, b"\n", + builder = functools.partial( + cls._build_part, + sep_boundary=sep_boundary, + ) + part_groups = map(builder, data.items()) + parts = itertools.chain.from_iterable(part_groups) + body_items = itertools.chain(parts, end_items) + content_type = 'multipart/form-data; boundary=%s' % boundary + return b''.join(body_items), content_type + + def upload_file(self, filename): + with open(filename, 'rb') as f: + content = f.read() + meta = self.distribution.metadata + data = { + ':action': 'doc_upload', + 'name': meta.get_name(), + 'content': (os.path.basename(filename), content), + } + # set up the authentication + credentials = _encode(self.username + ':' + self.password) + credentials = standard_b64encode(credentials).decode('ascii') + auth = "Basic " + credentials + + body, ct = self._build_multipart(data) + + msg = "Submitting documentation to %s" % (self.repository) + self.announce(msg, log.INFO) + + # build the Request + # We can't use urllib2 since we need to send the Basic + # auth right with the first request + schema, netloc, url, params, query, fragments = \ + urllib.parse.urlparse(self.repository) + assert not params and not query and not fragments + if schema == 'http': + conn = http.client.HTTPConnection(netloc) + elif schema == 'https': + conn = http.client.HTTPSConnection(netloc) + else: + raise AssertionError("unsupported schema " + schema) + + data = '' + try: + conn.connect() + conn.putrequest("POST", url) + content_type = ct + conn.putheader('Content-type', content_type) + conn.putheader('Content-length', str(len(body))) + conn.putheader('Authorization', auth) + conn.endheaders() + conn.send(body) + except socket.error as e: + self.announce(str(e), log.ERROR) + return + + r = conn.getresponse() + if r.status == 200: + msg = 'Server response (%s): %s' % (r.status, r.reason) + self.announce(msg, log.INFO) + elif r.status == 301: + location = r.getheader('Location') + if location is None: + location = 'https://pythonhosted.org/%s/' % meta.get_name() + msg = 'Upload successful. Visit %s' % location + self.announce(msg, log.INFO) + else: + msg = 'Upload failed (%s): %s' % (r.status, r.reason) + self.announce(msg, log.ERROR) + if self.show_response: + print('-' * 75, r.read(), '-' * 75) diff --git a/venv/Lib/site-packages/setuptools/config.py b/venv/Lib/site-packages/setuptools/config.py new file mode 100644 index 0000000..b4e968e --- /dev/null +++ b/venv/Lib/site-packages/setuptools/config.py @@ -0,0 +1,751 @@ +import ast +import io +import os +import sys + +import warnings +import functools +import importlib +from collections import defaultdict +from functools import partial +from functools import wraps +from glob import iglob +import contextlib + +from distutils.errors import DistutilsOptionError, DistutilsFileError +from setuptools.extern.packaging.version import Version, InvalidVersion +from setuptools.extern.packaging.specifiers import SpecifierSet + + +class StaticModule: + """ + Attempt to load the module by the name + """ + + def __init__(self, name): + spec = importlib.util.find_spec(name) + with open(spec.origin) as strm: + src = strm.read() + module = ast.parse(src) + vars(self).update(locals()) + del self.self + + def __getattr__(self, attr): + try: + return next( + ast.literal_eval(statement.value) + for statement in self.module.body + if isinstance(statement, ast.Assign) + for target in statement.targets + if isinstance(target, ast.Name) and target.id == attr + ) + except Exception as e: + raise AttributeError( + "{self.name} has no attribute {attr}".format(**locals()) + ) from e + + +@contextlib.contextmanager +def patch_path(path): + """ + Add path to front of sys.path for the duration of the context. + """ + try: + sys.path.insert(0, path) + yield + finally: + sys.path.remove(path) + + +def read_configuration(filepath, find_others=False, ignore_option_errors=False): + """Read given configuration file and returns options from it as a dict. + + :param str|unicode filepath: Path to configuration file + to get options from. + + :param bool find_others: Whether to search for other configuration files + which could be on in various places. + + :param bool ignore_option_errors: Whether to silently ignore + options, values of which could not be resolved (e.g. due to exceptions + in directives such as file:, attr:, etc.). + If False exceptions are propagated as expected. + + :rtype: dict + """ + from setuptools.dist import Distribution, _Distribution + + filepath = os.path.abspath(filepath) + + if not os.path.isfile(filepath): + raise DistutilsFileError('Configuration file %s does not exist.' % filepath) + + current_directory = os.getcwd() + os.chdir(os.path.dirname(filepath)) + + try: + dist = Distribution() + + filenames = dist.find_config_files() if find_others else [] + if filepath not in filenames: + filenames.append(filepath) + + _Distribution.parse_config_files(dist, filenames=filenames) + + handlers = parse_configuration( + dist, dist.command_options, ignore_option_errors=ignore_option_errors + ) + + finally: + os.chdir(current_directory) + + return configuration_to_dict(handlers) + + +def _get_option(target_obj, key): + """ + Given a target object and option key, get that option from + the target object, either through a get_{key} method or + from an attribute directly. + """ + getter_name = 'get_{key}'.format(**locals()) + by_attribute = functools.partial(getattr, target_obj, key) + getter = getattr(target_obj, getter_name, by_attribute) + return getter() + + +def configuration_to_dict(handlers): + """Returns configuration data gathered by given handlers as a dict. + + :param list[ConfigHandler] handlers: Handlers list, + usually from parse_configuration() + + :rtype: dict + """ + config_dict = defaultdict(dict) + + for handler in handlers: + for option in handler.set_options: + value = _get_option(handler.target_obj, option) + config_dict[handler.section_prefix][option] = value + + return config_dict + + +def parse_configuration(distribution, command_options, ignore_option_errors=False): + """Performs additional parsing of configuration options + for a distribution. + + Returns a list of used option handlers. + + :param Distribution distribution: + :param dict command_options: + :param bool ignore_option_errors: Whether to silently ignore + options, values of which could not be resolved (e.g. due to exceptions + in directives such as file:, attr:, etc.). + If False exceptions are propagated as expected. + :rtype: list + """ + options = ConfigOptionsHandler(distribution, command_options, ignore_option_errors) + options.parse() + + meta = ConfigMetadataHandler( + distribution.metadata, + command_options, + ignore_option_errors, + distribution.package_dir, + ) + meta.parse() + + return meta, options + + +class ConfigHandler: + """Handles metadata supplied in configuration files.""" + + section_prefix = None + """Prefix for config sections handled by this handler. + Must be provided by class heirs. + + """ + + aliases = {} + """Options aliases. + For compatibility with various packages. E.g.: d2to1 and pbr. + Note: `-` in keys is replaced with `_` by config parser. + + """ + + def __init__(self, target_obj, options, ignore_option_errors=False): + sections = {} + + section_prefix = self.section_prefix + for section_name, section_options in options.items(): + if not section_name.startswith(section_prefix): + continue + + section_name = section_name.replace(section_prefix, '').strip('.') + sections[section_name] = section_options + + self.ignore_option_errors = ignore_option_errors + self.target_obj = target_obj + self.sections = sections + self.set_options = [] + + @property + def parsers(self): + """Metadata item name to parser function mapping.""" + raise NotImplementedError( + '%s must provide .parsers property' % self.__class__.__name__ + ) + + def __setitem__(self, option_name, value): + unknown = tuple() + target_obj = self.target_obj + + # Translate alias into real name. + option_name = self.aliases.get(option_name, option_name) + + current_value = getattr(target_obj, option_name, unknown) + + if current_value is unknown: + raise KeyError(option_name) + + if current_value: + # Already inhabited. Skipping. + return + + skip_option = False + parser = self.parsers.get(option_name) + if parser: + try: + value = parser(value) + + except Exception: + skip_option = True + if not self.ignore_option_errors: + raise + + if skip_option: + return + + setter = getattr(target_obj, 'set_%s' % option_name, None) + if setter is None: + setattr(target_obj, option_name, value) + else: + setter(value) + + self.set_options.append(option_name) + + @classmethod + def _parse_list(cls, value, separator=','): + """Represents value as a list. + + Value is split either by separator (defaults to comma) or by lines. + + :param value: + :param separator: List items separator character. + :rtype: list + """ + if isinstance(value, list): # _get_parser_compound case + return value + + if '\n' in value: + value = value.splitlines() + else: + value = value.split(separator) + + return [chunk.strip() for chunk in value if chunk.strip()] + + @classmethod + def _parse_list_glob(cls, value, separator=','): + """Equivalent to _parse_list() but expands any glob patterns using glob(). + + However, unlike with glob() calls, the results remain relative paths. + + :param value: + :param separator: List items separator character. + :rtype: list + """ + glob_characters = ('*', '?', '[', ']', '{', '}') + values = cls._parse_list(value, separator=separator) + expanded_values = [] + for value in values: + + # Has globby characters? + if any(char in value for char in glob_characters): + # then expand the glob pattern while keeping paths *relative*: + expanded_values.extend(sorted( + os.path.relpath(path, os.getcwd()) + for path in iglob(os.path.abspath(value)))) + + else: + # take the value as-is: + expanded_values.append(value) + + return expanded_values + + @classmethod + def _parse_dict(cls, value): + """Represents value as a dict. + + :param value: + :rtype: dict + """ + separator = '=' + result = {} + for line in cls._parse_list(value): + key, sep, val = line.partition(separator) + if sep != separator: + raise DistutilsOptionError( + 'Unable to parse option value to dict: %s' % value + ) + result[key.strip()] = val.strip() + + return result + + @classmethod + def _parse_bool(cls, value): + """Represents value as boolean. + + :param value: + :rtype: bool + """ + value = value.lower() + return value in ('1', 'true', 'yes') + + @classmethod + def _exclude_files_parser(cls, key): + """Returns a parser function to make sure field inputs + are not files. + + Parses a value after getting the key so error messages are + more informative. + + :param key: + :rtype: callable + """ + + def parser(value): + exclude_directive = 'file:' + if value.startswith(exclude_directive): + raise ValueError( + 'Only strings are accepted for the {0} field, ' + 'files are not accepted'.format(key) + ) + return value + + return parser + + @classmethod + def _parse_file(cls, value): + """Represents value as a string, allowing including text + from nearest files using `file:` directive. + + Directive is sandboxed and won't reach anything outside + directory with setup.py. + + Examples: + file: README.rst, CHANGELOG.md, src/file.txt + + :param str value: + :rtype: str + """ + include_directive = 'file:' + + if not isinstance(value, str): + return value + + if not value.startswith(include_directive): + return value + + spec = value[len(include_directive) :] + filepaths = (os.path.abspath(path.strip()) for path in spec.split(',')) + return '\n'.join( + cls._read_file(path) + for path in filepaths + if (cls._assert_local(path) or True) and os.path.isfile(path) + ) + + @staticmethod + def _assert_local(filepath): + if not filepath.startswith(os.getcwd()): + raise DistutilsOptionError('`file:` directive can not access %s' % filepath) + + @staticmethod + def _read_file(filepath): + with io.open(filepath, encoding='utf-8') as f: + return f.read() + + @classmethod + def _parse_attr(cls, value, package_dir=None): + """Represents value as a module attribute. + + Examples: + attr: package.attr + attr: package.module.attr + + :param str value: + :rtype: str + """ + attr_directive = 'attr:' + if not value.startswith(attr_directive): + return value + + attrs_path = value.replace(attr_directive, '').strip().split('.') + attr_name = attrs_path.pop() + + module_name = '.'.join(attrs_path) + module_name = module_name or '__init__' + + parent_path = os.getcwd() + if package_dir: + if attrs_path[0] in package_dir: + # A custom path was specified for the module we want to import + custom_path = package_dir[attrs_path[0]] + parts = custom_path.rsplit('/', 1) + if len(parts) > 1: + parent_path = os.path.join(os.getcwd(), parts[0]) + module_name = parts[1] + else: + module_name = custom_path + elif '' in package_dir: + # A custom parent directory was specified for all root modules + parent_path = os.path.join(os.getcwd(), package_dir['']) + + with patch_path(parent_path): + try: + # attempt to load value statically + return getattr(StaticModule(module_name), attr_name) + except Exception: + # fallback to simple import + module = importlib.import_module(module_name) + + return getattr(module, attr_name) + + @classmethod + def _get_parser_compound(cls, *parse_methods): + """Returns parser function to represents value as a list. + + Parses a value applying given methods one after another. + + :param parse_methods: + :rtype: callable + """ + + def parse(value): + parsed = value + + for method in parse_methods: + parsed = method(parsed) + + return parsed + + return parse + + @classmethod + def _parse_section_to_dict(cls, section_options, values_parser=None): + """Parses section options into a dictionary. + + Optionally applies a given parser to values. + + :param dict section_options: + :param callable values_parser: + :rtype: dict + """ + value = {} + values_parser = values_parser or (lambda val: val) + for key, (_, val) in section_options.items(): + value[key] = values_parser(val) + return value + + def parse_section(self, section_options): + """Parses configuration file section. + + :param dict section_options: + """ + for (name, (_, value)) in section_options.items(): + try: + self[name] = value + + except KeyError: + pass # Keep silent for a new option may appear anytime. + + def parse(self): + """Parses configuration file items from one + or more related sections. + + """ + for section_name, section_options in self.sections.items(): + + method_postfix = '' + if section_name: # [section.option] variant + method_postfix = '_%s' % section_name + + section_parser_method = getattr( + self, + # Dots in section names are translated into dunderscores. + ('parse_section%s' % method_postfix).replace('.', '__'), + None, + ) + + if section_parser_method is None: + raise DistutilsOptionError( + 'Unsupported distribution option section: [%s.%s]' + % (self.section_prefix, section_name) + ) + + section_parser_method(section_options) + + def _deprecated_config_handler(self, func, msg, warning_class): + """this function will wrap around parameters that are deprecated + + :param msg: deprecation message + :param warning_class: class of warning exception to be raised + :param func: function to be wrapped around + """ + + @wraps(func) + def config_handler(*args, **kwargs): + warnings.warn(msg, warning_class) + return func(*args, **kwargs) + + return config_handler + + +class ConfigMetadataHandler(ConfigHandler): + + section_prefix = 'metadata' + + aliases = { + 'home_page': 'url', + 'summary': 'description', + 'classifier': 'classifiers', + 'platform': 'platforms', + } + + strict_mode = False + """We need to keep it loose, to be partially compatible with + `pbr` and `d2to1` packages which also uses `metadata` section. + + """ + + def __init__( + self, target_obj, options, ignore_option_errors=False, package_dir=None + ): + super(ConfigMetadataHandler, self).__init__( + target_obj, options, ignore_option_errors + ) + self.package_dir = package_dir + + @property + def parsers(self): + """Metadata item name to parser function mapping.""" + parse_list = self._parse_list + parse_file = self._parse_file + parse_dict = self._parse_dict + exclude_files_parser = self._exclude_files_parser + + return { + 'platforms': parse_list, + 'keywords': parse_list, + 'provides': parse_list, + 'requires': self._deprecated_config_handler( + parse_list, + "The requires parameter is deprecated, please use " + "install_requires for runtime dependencies.", + DeprecationWarning, + ), + 'obsoletes': parse_list, + 'classifiers': self._get_parser_compound(parse_file, parse_list), + 'license': exclude_files_parser('license'), + 'license_file': self._deprecated_config_handler( + exclude_files_parser('license_file'), + "The license_file parameter is deprecated, " + "use license_files instead.", + DeprecationWarning, + ), + 'license_files': parse_list, + 'description': parse_file, + 'long_description': parse_file, + 'version': self._parse_version, + 'project_urls': parse_dict, + } + + def _parse_version(self, value): + """Parses `version` option value. + + :param value: + :rtype: str + + """ + version = self._parse_file(value) + + if version != value: + version = version.strip() + # Be strict about versions loaded from file because it's easy to + # accidentally include newlines and other unintended content + try: + Version(version) + except InvalidVersion: + tmpl = ( + 'Version loaded from {value} does not ' + 'comply with PEP 440: {version}' + ) + raise DistutilsOptionError(tmpl.format(**locals())) + + return version + + version = self._parse_attr(value, self.package_dir) + + if callable(version): + version = version() + + if not isinstance(version, str): + if hasattr(version, '__iter__'): + version = '.'.join(map(str, version)) + else: + version = '%s' % version + + return version + + +class ConfigOptionsHandler(ConfigHandler): + + section_prefix = 'options' + + @property + def parsers(self): + """Metadata item name to parser function mapping.""" + parse_list = self._parse_list + parse_list_semicolon = partial(self._parse_list, separator=';') + parse_bool = self._parse_bool + parse_dict = self._parse_dict + parse_cmdclass = self._parse_cmdclass + + return { + 'zip_safe': parse_bool, + 'include_package_data': parse_bool, + 'package_dir': parse_dict, + 'scripts': parse_list, + 'eager_resources': parse_list, + 'dependency_links': parse_list, + 'namespace_packages': parse_list, + 'install_requires': parse_list_semicolon, + 'setup_requires': parse_list_semicolon, + 'tests_require': parse_list_semicolon, + 'packages': self._parse_packages, + 'entry_points': self._parse_file, + 'py_modules': parse_list, + 'python_requires': SpecifierSet, + 'cmdclass': parse_cmdclass, + } + + def _parse_cmdclass(self, value): + def resolve_class(qualified_class_name): + idx = qualified_class_name.rfind('.') + class_name = qualified_class_name[idx + 1 :] + pkg_name = qualified_class_name[:idx] + + module = __import__(pkg_name) + + return getattr(module, class_name) + + return {k: resolve_class(v) for k, v in self._parse_dict(value).items()} + + def _parse_packages(self, value): + """Parses `packages` option value. + + :param value: + :rtype: list + """ + find_directives = ['find:', 'find_namespace:'] + trimmed_value = value.strip() + + if trimmed_value not in find_directives: + return self._parse_list(value) + + findns = trimmed_value == find_directives[1] + + # Read function arguments from a dedicated section. + find_kwargs = self.parse_section_packages__find( + self.sections.get('packages.find', {}) + ) + + if findns: + from setuptools import find_namespace_packages as find_packages + else: + from setuptools import find_packages + + return find_packages(**find_kwargs) + + def parse_section_packages__find(self, section_options): + """Parses `packages.find` configuration file section. + + To be used in conjunction with _parse_packages(). + + :param dict section_options: + """ + section_data = self._parse_section_to_dict(section_options, self._parse_list) + + valid_keys = ['where', 'include', 'exclude'] + + find_kwargs = dict( + [(k, v) for k, v in section_data.items() if k in valid_keys and v] + ) + + where = find_kwargs.get('where') + if where is not None: + find_kwargs['where'] = where[0] # cast list to single val + + return find_kwargs + + def parse_section_entry_points(self, section_options): + """Parses `entry_points` configuration file section. + + :param dict section_options: + """ + parsed = self._parse_section_to_dict(section_options, self._parse_list) + self['entry_points'] = parsed + + def _parse_package_data(self, section_options): + parsed = self._parse_section_to_dict(section_options, self._parse_list) + + root = parsed.get('*') + if root: + parsed[''] = root + del parsed['*'] + + return parsed + + def parse_section_package_data(self, section_options): + """Parses `package_data` configuration file section. + + :param dict section_options: + """ + self['package_data'] = self._parse_package_data(section_options) + + def parse_section_exclude_package_data(self, section_options): + """Parses `exclude_package_data` configuration file section. + + :param dict section_options: + """ + self['exclude_package_data'] = self._parse_package_data(section_options) + + def parse_section_extras_require(self, section_options): + """Parses `extras_require` configuration file section. + + :param dict section_options: + """ + parse_list = partial(self._parse_list, separator=';') + self['extras_require'] = self._parse_section_to_dict( + section_options, parse_list + ) + + def parse_section_data_files(self, section_options): + """Parses `data_files` configuration file section. + + :param dict section_options: + """ + parsed = self._parse_section_to_dict(section_options, self._parse_list_glob) + self['data_files'] = [(k, v) for k, v in parsed.items()] diff --git a/venv/Lib/site-packages/setuptools/dep_util.py b/venv/Lib/site-packages/setuptools/dep_util.py new file mode 100644 index 0000000..521eb71 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/dep_util.py @@ -0,0 +1,25 @@ +from distutils.dep_util import newer_group + + +# yes, this is was almost entirely copy-pasted from +# 'newer_pairwise()', this is just another convenience +# function. +def newer_pairwise_group(sources_groups, targets): + """Walk both arguments in parallel, testing if each source group is newer + than its corresponding target. Returns a pair of lists (sources_groups, + targets) where sources is newer than target, according to the semantics + of 'newer_group()'. + """ + if len(sources_groups) != len(targets): + raise ValueError( + "'sources_group' and 'targets' must be the same length") + + # build a pair of lists (sources_groups, targets) where source is newer + n_sources = [] + n_targets = [] + for i in range(len(sources_groups)): + if newer_group(sources_groups[i], targets[i]): + n_sources.append(sources_groups[i]) + n_targets.append(targets[i]) + + return n_sources, n_targets diff --git a/venv/Lib/site-packages/setuptools/depends.py b/venv/Lib/site-packages/setuptools/depends.py new file mode 100644 index 0000000..adffd12 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/depends.py @@ -0,0 +1,176 @@ +import sys +import marshal +import contextlib +import dis + +from setuptools.extern.packaging import version + +from ._imp import find_module, PY_COMPILED, PY_FROZEN, PY_SOURCE +from . import _imp + + +__all__ = [ + 'Require', 'find_module', 'get_module_constant', 'extract_constant' +] + + +class Require: + """A prerequisite to building or installing a distribution""" + + def __init__( + self, name, requested_version, module, homepage='', + attribute=None, format=None): + + if format is None and requested_version is not None: + format = version.Version + + if format is not None: + requested_version = format(requested_version) + if attribute is None: + attribute = '__version__' + + self.__dict__.update(locals()) + del self.self + + def full_name(self): + """Return full package/distribution name, w/version""" + if self.requested_version is not None: + return '%s-%s' % (self.name, self.requested_version) + return self.name + + def version_ok(self, version): + """Is 'version' sufficiently up-to-date?""" + return self.attribute is None or self.format is None or \ + str(version) != "unknown" and self.format(version) >= self.requested_version + + def get_version(self, paths=None, default="unknown"): + """Get version number of installed module, 'None', or 'default' + + Search 'paths' for module. If not found, return 'None'. If found, + return the extracted version attribute, or 'default' if no version + attribute was specified, or the value cannot be determined without + importing the module. The version is formatted according to the + requirement's version format (if any), unless it is 'None' or the + supplied 'default'. + """ + + if self.attribute is None: + try: + f, p, i = find_module(self.module, paths) + if f: + f.close() + return default + except ImportError: + return None + + v = get_module_constant(self.module, self.attribute, default, paths) + + if v is not None and v is not default and self.format is not None: + return self.format(v) + + return v + + def is_present(self, paths=None): + """Return true if dependency is present on 'paths'""" + return self.get_version(paths) is not None + + def is_current(self, paths=None): + """Return true if dependency is present and up-to-date on 'paths'""" + version = self.get_version(paths) + if version is None: + return False + return self.version_ok(str(version)) + + +def maybe_close(f): + @contextlib.contextmanager + def empty(): + yield + return + if not f: + return empty() + + return contextlib.closing(f) + + +def get_module_constant(module, symbol, default=-1, paths=None): + """Find 'module' by searching 'paths', and extract 'symbol' + + Return 'None' if 'module' does not exist on 'paths', or it does not define + 'symbol'. If the module defines 'symbol' as a constant, return the + constant. Otherwise, return 'default'.""" + + try: + f, path, (suffix, mode, kind) = info = find_module(module, paths) + except ImportError: + # Module doesn't exist + return None + + with maybe_close(f): + if kind == PY_COMPILED: + f.read(8) # skip magic & date + code = marshal.load(f) + elif kind == PY_FROZEN: + code = _imp.get_frozen_object(module, paths) + elif kind == PY_SOURCE: + code = compile(f.read(), path, 'exec') + else: + # Not something we can parse; we'll have to import it. :( + imported = _imp.get_module(module, paths, info) + return getattr(imported, symbol, None) + + return extract_constant(code, symbol, default) + + +def extract_constant(code, symbol, default=-1): + """Extract the constant value of 'symbol' from 'code' + + If the name 'symbol' is bound to a constant value by the Python code + object 'code', return that value. If 'symbol' is bound to an expression, + return 'default'. Otherwise, return 'None'. + + Return value is based on the first assignment to 'symbol'. 'symbol' must + be a global, or at least a non-"fast" local in the code block. That is, + only 'STORE_NAME' and 'STORE_GLOBAL' opcodes are checked, and 'symbol' + must be present in 'code.co_names'. + """ + if symbol not in code.co_names: + # name's not there, can't possibly be an assignment + return None + + name_idx = list(code.co_names).index(symbol) + + STORE_NAME = 90 + STORE_GLOBAL = 97 + LOAD_CONST = 100 + + const = default + + for byte_code in dis.Bytecode(code): + op = byte_code.opcode + arg = byte_code.arg + + if op == LOAD_CONST: + const = code.co_consts[arg] + elif arg == name_idx and (op == STORE_NAME or op == STORE_GLOBAL): + return const + else: + const = default + + +def _update_globals(): + """ + Patch the globals to remove the objects not available on some platforms. + + XXX it'd be better to test assertions about bytecode instead. + """ + + if not sys.platform.startswith('java') and sys.platform != 'cli': + return + incompatible = 'extract_constant', 'get_module_constant' + for name in incompatible: + del globals()[name] + __all__.remove(name) + + +_update_globals() diff --git a/venv/Lib/site-packages/setuptools/dist.py b/venv/Lib/site-packages/setuptools/dist.py new file mode 100644 index 0000000..e825785 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/dist.py @@ -0,0 +1,1192 @@ +# -*- coding: utf-8 -*- +__all__ = ['Distribution'] + +import io +import sys +import re +import os +import warnings +import numbers +import distutils.log +import distutils.core +import distutils.cmd +import distutils.dist +import distutils.command +from distutils.util import strtobool +from distutils.debug import DEBUG +from distutils.fancy_getopt import translate_longopt +from glob import iglob +import itertools +import textwrap +from typing import List, Optional, TYPE_CHECKING + +from collections import defaultdict +from email import message_from_file + +from distutils.errors import DistutilsOptionError, DistutilsSetupError +from distutils.util import rfc822_escape + +from setuptools.extern import packaging +from setuptools.extern import ordered_set +from setuptools.extern.more_itertools import unique_everseen, always_iterable + +from ._importlib import metadata + +from . import SetuptoolsDeprecationWarning + +import setuptools +import setuptools.command +from setuptools import windows_support +from setuptools.monkey import get_unpatched +from setuptools.config import parse_configuration +import pkg_resources +from setuptools.extern.packaging import version, requirements +from . import _reqs +from . import _entry_points + +if TYPE_CHECKING: + from email.message import Message + +__import__('setuptools.extern.packaging.specifiers') +__import__('setuptools.extern.packaging.version') + + +def _get_unpatched(cls): + warnings.warn("Do not call this function", DistDeprecationWarning) + return get_unpatched(cls) + + +def get_metadata_version(self): + mv = getattr(self, 'metadata_version', None) + if mv is None: + mv = version.Version('2.1') + self.metadata_version = mv + return mv + + +def rfc822_unescape(content: str) -> str: + """Reverse RFC-822 escaping by removing leading whitespaces from content.""" + lines = content.splitlines() + if len(lines) == 1: + return lines[0].lstrip() + return '\n'.join((lines[0].lstrip(), textwrap.dedent('\n'.join(lines[1:])))) + + +def _read_field_from_msg(msg: "Message", field: str) -> Optional[str]: + """Read Message header field.""" + value = msg[field] + if value == 'UNKNOWN': + return None + return value + + +def _read_field_unescaped_from_msg(msg: "Message", field: str) -> Optional[str]: + """Read Message header field and apply rfc822_unescape.""" + value = _read_field_from_msg(msg, field) + if value is None: + return value + return rfc822_unescape(value) + + +def _read_list_from_msg(msg: "Message", field: str) -> Optional[List[str]]: + """Read Message header field and return all results as list.""" + values = msg.get_all(field, None) + if values == []: + return None + return values + + +def _read_payload_from_msg(msg: "Message") -> Optional[str]: + value = msg.get_payload().strip() + if value == 'UNKNOWN': + return None + return value + + +def read_pkg_file(self, file): + """Reads the metadata values from a file object.""" + msg = message_from_file(file) + + self.metadata_version = version.Version(msg['metadata-version']) + self.name = _read_field_from_msg(msg, 'name') + self.version = _read_field_from_msg(msg, 'version') + self.description = _read_field_from_msg(msg, 'summary') + # we are filling author only. + self.author = _read_field_from_msg(msg, 'author') + self.maintainer = None + self.author_email = _read_field_from_msg(msg, 'author-email') + self.maintainer_email = None + self.url = _read_field_from_msg(msg, 'home-page') + self.download_url = _read_field_from_msg(msg, 'download-url') + self.license = _read_field_unescaped_from_msg(msg, 'license') + + self.long_description = _read_field_unescaped_from_msg(msg, 'description') + if ( + self.long_description is None and + self.metadata_version >= version.Version('2.1') + ): + self.long_description = _read_payload_from_msg(msg) + self.description = _read_field_from_msg(msg, 'summary') + + if 'keywords' in msg: + self.keywords = _read_field_from_msg(msg, 'keywords').split(',') + + self.platforms = _read_list_from_msg(msg, 'platform') + self.classifiers = _read_list_from_msg(msg, 'classifier') + + # PEP 314 - these fields only exist in 1.1 + if self.metadata_version == version.Version('1.1'): + self.requires = _read_list_from_msg(msg, 'requires') + self.provides = _read_list_from_msg(msg, 'provides') + self.obsoletes = _read_list_from_msg(msg, 'obsoletes') + else: + self.requires = None + self.provides = None + self.obsoletes = None + + self.license_files = _read_list_from_msg(msg, 'license-file') + + +def single_line(val): + """ + Quick and dirty validation for Summary pypa/setuptools#1390. + """ + if '\n' in val: + # TODO: Replace with `raise ValueError("newlines not allowed")` + # after reviewing #2893. + warnings.warn("newlines not allowed and will break in the future") + val = val.strip().split('\n')[0] + return val + + +# Based on Python 3.5 version +def write_pkg_file(self, file): # noqa: C901 # is too complex (14) # FIXME + """Write the PKG-INFO format data to a file object.""" + version = self.get_metadata_version() + + def write_field(key, value): + file.write("%s: %s\n" % (key, value)) + + write_field('Metadata-Version', str(version)) + write_field('Name', self.get_name()) + write_field('Version', self.get_version()) + write_field('Summary', single_line(self.get_description())) + + optional_fields = ( + ('Home-page', 'url'), + ('Download-URL', 'download_url'), + ('Author', 'author'), + ('Author-email', 'author_email'), + ('Maintainer', 'maintainer'), + ('Maintainer-email', 'maintainer_email'), + ) + + for field, attr in optional_fields: + attr_val = getattr(self, attr, None) + if attr_val is not None: + write_field(field, attr_val) + + license = rfc822_escape(self.get_license()) + write_field('License', license) + for project_url in self.project_urls.items(): + write_field('Project-URL', '%s, %s' % project_url) + + keywords = ','.join(self.get_keywords()) + if keywords: + write_field('Keywords', keywords) + + for platform in self.get_platforms(): + write_field('Platform', platform) + + self._write_list(file, 'Classifier', self.get_classifiers()) + + # PEP 314 + self._write_list(file, 'Requires', self.get_requires()) + self._write_list(file, 'Provides', self.get_provides()) + self._write_list(file, 'Obsoletes', self.get_obsoletes()) + + # Setuptools specific for PEP 345 + if hasattr(self, 'python_requires'): + write_field('Requires-Python', self.python_requires) + + # PEP 566 + if self.long_description_content_type: + write_field('Description-Content-Type', self.long_description_content_type) + if self.provides_extras: + for extra in self.provides_extras: + write_field('Provides-Extra', extra) + + self._write_list(file, 'License-File', self.license_files or []) + + file.write("\n%s\n\n" % self.get_long_description()) + + +sequence = tuple, list + + +def check_importable(dist, attr, value): + try: + ep = metadata.EntryPoint(value=value, name=None, group=None) + assert not ep.extras + except (TypeError, ValueError, AttributeError, AssertionError) as e: + raise DistutilsSetupError( + "%r must be importable 'module:attrs' string (got %r)" % (attr, value) + ) from e + + +def assert_string_list(dist, attr, value): + """Verify that value is a string list""" + try: + # verify that value is a list or tuple to exclude unordered + # or single-use iterables + assert isinstance(value, (list, tuple)) + # verify that elements of value are strings + assert ''.join(value) != value + except (TypeError, ValueError, AttributeError, AssertionError) as e: + raise DistutilsSetupError( + "%r must be a list of strings (got %r)" % (attr, value) + ) from e + + +def check_nsp(dist, attr, value): + """Verify that namespace packages are valid""" + ns_packages = value + assert_string_list(dist, attr, ns_packages) + for nsp in ns_packages: + if not dist.has_contents_for(nsp): + raise DistutilsSetupError( + "Distribution contains no modules or packages for " + + "namespace package %r" % nsp + ) + parent, sep, child = nsp.rpartition('.') + if parent and parent not in ns_packages: + distutils.log.warn( + "WARNING: %r is declared as a package namespace, but %r" + " is not: please correct this in setup.py", + nsp, + parent, + ) + + +def check_extras(dist, attr, value): + """Verify that extras_require mapping is valid""" + try: + list(itertools.starmap(_check_extra, value.items())) + except (TypeError, ValueError, AttributeError) as e: + raise DistutilsSetupError( + "'extras_require' must be a dictionary whose values are " + "strings or lists of strings containing valid project/version " + "requirement specifiers." + ) from e + + +def _check_extra(extra, reqs): + name, sep, marker = extra.partition(':') + if marker and pkg_resources.invalid_marker(marker): + raise DistutilsSetupError("Invalid environment marker: " + marker) + list(_reqs.parse(reqs)) + + +def assert_bool(dist, attr, value): + """Verify that value is True, False, 0, or 1""" + if bool(value) != value: + tmpl = "{attr!r} must be a boolean value (got {value!r})" + raise DistutilsSetupError(tmpl.format(attr=attr, value=value)) + + +def invalid_unless_false(dist, attr, value): + if not value: + warnings.warn(f"{attr} is ignored.", DistDeprecationWarning) + return + raise DistutilsSetupError(f"{attr} is invalid.") + + +def check_requirements(dist, attr, value): + """Verify that install_requires is a valid requirements list""" + try: + list(_reqs.parse(value)) + if isinstance(value, (dict, set)): + raise TypeError("Unordered types are not allowed") + except (TypeError, ValueError) as error: + tmpl = ( + "{attr!r} must be a string or list of strings " + "containing valid project/version requirement specifiers; {error}" + ) + raise DistutilsSetupError(tmpl.format(attr=attr, error=error)) from error + + +def check_specifier(dist, attr, value): + """Verify that value is a valid version specifier""" + try: + packaging.specifiers.SpecifierSet(value) + except (packaging.specifiers.InvalidSpecifier, AttributeError) as error: + tmpl = ( + "{attr!r} must be a string " "containing valid version specifiers; {error}" + ) + raise DistutilsSetupError(tmpl.format(attr=attr, error=error)) from error + + +def check_entry_points(dist, attr, value): + """Verify that entry_points map is parseable""" + try: + _entry_points.load(value) + except Exception as e: + raise DistutilsSetupError(e) from e + + +def check_test_suite(dist, attr, value): + if not isinstance(value, str): + raise DistutilsSetupError("test_suite must be a string") + + +def check_package_data(dist, attr, value): + """Verify that value is a dictionary of package names to glob lists""" + if not isinstance(value, dict): + raise DistutilsSetupError( + "{!r} must be a dictionary mapping package names to lists of " + "string wildcard patterns".format(attr) + ) + for k, v in value.items(): + if not isinstance(k, str): + raise DistutilsSetupError( + "keys of {!r} dict must be strings (got {!r})".format(attr, k) + ) + assert_string_list(dist, 'values of {!r} dict'.format(attr), v) + + +def check_packages(dist, attr, value): + for pkgname in value: + if not re.match(r'\w+(\.\w+)*', pkgname): + distutils.log.warn( + "WARNING: %r not a valid package name; please use only " + ".-separated package names in setup.py", + pkgname, + ) + + +_Distribution = get_unpatched(distutils.core.Distribution) + + +class Distribution(_Distribution): + """Distribution with support for tests and package data + + This is an enhanced version of 'distutils.dist.Distribution' that + effectively adds the following new optional keyword arguments to 'setup()': + + 'install_requires' -- a string or sequence of strings specifying project + versions that the distribution requires when installed, in the format + used by 'pkg_resources.require()'. They will be installed + automatically when the package is installed. If you wish to use + packages that are not available in PyPI, or want to give your users an + alternate download location, you can add a 'find_links' option to the + '[easy_install]' section of your project's 'setup.cfg' file, and then + setuptools will scan the listed web pages for links that satisfy the + requirements. + + 'extras_require' -- a dictionary mapping names of optional "extras" to the + additional requirement(s) that using those extras incurs. For example, + this:: + + extras_require = dict(reST = ["docutils>=0.3", "reSTedit"]) + + indicates that the distribution can optionally provide an extra + capability called "reST", but it can only be used if docutils and + reSTedit are installed. If the user installs your package using + EasyInstall and requests one of your extras, the corresponding + additional requirements will be installed if needed. + + 'test_suite' -- the name of a test suite to run for the 'test' command. + If the user runs 'python setup.py test', the package will be installed, + and the named test suite will be run. The format is the same as + would be used on a 'unittest.py' command line. That is, it is the + dotted name of an object to import and call to generate a test suite. + + 'package_data' -- a dictionary mapping package names to lists of filenames + or globs to use to find data files contained in the named packages. + If the dictionary has filenames or globs listed under '""' (the empty + string), those names will be searched for in every package, in addition + to any names for the specific package. Data files found using these + names/globs will be installed along with the package, in the same + location as the package. Note that globs are allowed to reference + the contents of non-package subdirectories, as long as you use '/' as + a path separator. (Globs are automatically converted to + platform-specific paths at runtime.) + + In addition to these new keywords, this class also has several new methods + for manipulating the distribution's contents. For example, the 'include()' + and 'exclude()' methods can be thought of as in-place add and subtract + commands that add or remove packages, modules, extensions, and so on from + the distribution. + """ + + _DISTUTILS_UNSUPPORTED_METADATA = { + 'long_description_content_type': lambda: None, + 'project_urls': dict, + 'provides_extras': ordered_set.OrderedSet, + 'license_file': lambda: None, + 'license_files': lambda: None, + } + + _patched_dist = None + + def patch_missing_pkg_info(self, attrs): + # Fake up a replacement for the data that would normally come from + # PKG-INFO, but which might not yet be built if this is a fresh + # checkout. + # + if not attrs or 'name' not in attrs or 'version' not in attrs: + return + key = pkg_resources.safe_name(str(attrs['name'])).lower() + dist = pkg_resources.working_set.by_key.get(key) + if dist is not None and not dist.has_metadata('PKG-INFO'): + dist._version = pkg_resources.safe_version(str(attrs['version'])) + self._patched_dist = dist + + def __init__(self, attrs=None): + have_package_data = hasattr(self, "package_data") + if not have_package_data: + self.package_data = {} + attrs = attrs or {} + self.dist_files = [] + # Filter-out setuptools' specific options. + self.src_root = attrs.pop("src_root", None) + self.patch_missing_pkg_info(attrs) + self.dependency_links = attrs.pop('dependency_links', []) + self.setup_requires = attrs.pop('setup_requires', []) + for ep in metadata.entry_points(group='distutils.setup_keywords'): + vars(self).setdefault(ep.name, None) + _Distribution.__init__( + self, + { + k: v + for k, v in attrs.items() + if k not in self._DISTUTILS_UNSUPPORTED_METADATA + }, + ) + + self._set_metadata_defaults(attrs) + + self.metadata.version = self._normalize_version( + self._validate_version(self.metadata.version) + ) + self._finalize_requires() + + def _validate_metadata(self): + required = {"name"} + provided = { + key + for key in vars(self.metadata) + if getattr(self.metadata, key, None) is not None + } + missing = required - provided + + if missing: + msg = f"Required package metadata is missing: {missing}" + raise DistutilsSetupError(msg) + + def _set_metadata_defaults(self, attrs): + """ + Fill-in missing metadata fields not supported by distutils. + Some fields may have been set by other tools (e.g. pbr). + Those fields (vars(self.metadata)) take precedence to + supplied attrs. + """ + for option, default in self._DISTUTILS_UNSUPPORTED_METADATA.items(): + vars(self.metadata).setdefault(option, attrs.get(option, default())) + + @staticmethod + def _normalize_version(version): + if isinstance(version, setuptools.sic) or version is None: + return version + + normalized = str(packaging.version.Version(version)) + if version != normalized: + tmpl = "Normalizing '{version}' to '{normalized}'" + warnings.warn(tmpl.format(**locals())) + return normalized + return version + + @staticmethod + def _validate_version(version): + if isinstance(version, numbers.Number): + # Some people apparently take "version number" too literally :) + version = str(version) + + if version is not None: + try: + packaging.version.Version(version) + except (packaging.version.InvalidVersion, TypeError): + warnings.warn( + "The version specified (%r) is an invalid version, this " + "may not work as expected with newer versions of " + "setuptools, pip, and PyPI. Please see PEP 440 for more " + "details." % version + ) + return setuptools.sic(version) + return version + + def _finalize_requires(self): + """ + Set `metadata.python_requires` and fix environment markers + in `install_requires` and `extras_require`. + """ + if getattr(self, 'python_requires', None): + self.metadata.python_requires = self.python_requires + + if getattr(self, 'extras_require', None): + for extra in self.extras_require.keys(): + # Since this gets called multiple times at points where the + # keys have become 'converted' extras, ensure that we are only + # truly adding extras we haven't seen before here. + extra = extra.split(':')[0] + if extra: + self.metadata.provides_extras.add(extra) + + self._convert_extras_requirements() + self._move_install_requirements_markers() + + def _convert_extras_requirements(self): + """ + Convert requirements in `extras_require` of the form + `"extra": ["barbazquux; {marker}"]` to + `"extra:{marker}": ["barbazquux"]`. + """ + spec_ext_reqs = getattr(self, 'extras_require', None) or {} + self._tmp_extras_require = defaultdict(list) + for section, v in spec_ext_reqs.items(): + # Do not strip empty sections. + self._tmp_extras_require[section] + for r in _reqs.parse(v): + suffix = self._suffix_for(r) + self._tmp_extras_require[section + suffix].append(r) + + @staticmethod + def _suffix_for(req): + """ + For a requirement, return the 'extras_require' suffix for + that requirement. + """ + return ':' + str(req.marker) if req.marker else '' + + def _move_install_requirements_markers(self): + """ + Move requirements in `install_requires` that are using environment + markers `extras_require`. + """ + + # divide the install_requires into two sets, simple ones still + # handled by install_requires and more complex ones handled + # by extras_require. + + def is_simple_req(req): + return not req.marker + + spec_inst_reqs = getattr(self, 'install_requires', None) or () + inst_reqs = list(_reqs.parse(spec_inst_reqs)) + simple_reqs = filter(is_simple_req, inst_reqs) + complex_reqs = itertools.filterfalse(is_simple_req, inst_reqs) + self.install_requires = list(map(str, simple_reqs)) + + for r in complex_reqs: + self._tmp_extras_require[':' + str(r.marker)].append(r) + self.extras_require = dict( + (k, [str(r) for r in map(self._clean_req, v)]) + for k, v in self._tmp_extras_require.items() + ) + + def _clean_req(self, req): + """ + Given a Requirement, remove environment markers and return it. + """ + req.marker = None + return req + + def _finalize_license_files(self): + """Compute names of all license files which should be included.""" + license_files: Optional[List[str]] = self.metadata.license_files + patterns: List[str] = license_files if license_files else [] + + license_file: Optional[str] = self.metadata.license_file + if license_file and license_file not in patterns: + patterns.append(license_file) + + if license_files is None and license_file is None: + # Default patterns match the ones wheel uses + # See https://wheel.readthedocs.io/en/stable/user_guide.html + # -> 'Including license files in the generated wheel file' + patterns = ('LICEN[CS]E*', 'COPYING*', 'NOTICE*', 'AUTHORS*') + + self.metadata.license_files = list( + unique_everseen(self._expand_patterns(patterns)) + ) + + @staticmethod + def _expand_patterns(patterns): + """ + >>> list(Distribution._expand_patterns(['LICENSE'])) + ['LICENSE'] + >>> list(Distribution._expand_patterns(['setup.cfg', 'LIC*'])) + ['setup.cfg', 'LICENSE'] + """ + return ( + path + for pattern in patterns + for path in sorted(iglob(pattern)) + if not path.endswith('~') and os.path.isfile(path) + ) + + # FIXME: 'Distribution._parse_config_files' is too complex (14) + def _parse_config_files(self, filenames=None): # noqa: C901 + """ + Adapted from distutils.dist.Distribution.parse_config_files, + this method provides the same functionality in subtly-improved + ways. + """ + from configparser import ConfigParser + + # Ignore install directory options if we have a venv + ignore_options = ( + [] + if sys.prefix == sys.base_prefix + else [ + 'install-base', + 'install-platbase', + 'install-lib', + 'install-platlib', + 'install-purelib', + 'install-headers', + 'install-scripts', + 'install-data', + 'prefix', + 'exec-prefix', + 'home', + 'user', + 'root', + ] + ) + + ignore_options = frozenset(ignore_options) + + if filenames is None: + filenames = self.find_config_files() + + if DEBUG: + self.announce("Distribution.parse_config_files():") + + parser = ConfigParser() + parser.optionxform = str + for filename in filenames: + with io.open(filename, encoding='utf-8') as reader: + if DEBUG: + self.announce(" reading {filename}".format(**locals())) + parser.read_file(reader) + for section in parser.sections(): + options = parser.options(section) + opt_dict = self.get_option_dict(section) + + for opt in options: + if opt == '__name__' or opt in ignore_options: + continue + + val = parser.get(section, opt) + opt = self.warn_dash_deprecation(opt, section) + opt = self.make_option_lowercase(opt, section) + opt_dict[opt] = (filename, val) + + # Make the ConfigParser forget everything (so we retain + # the original filenames that options come from) + parser.__init__() + + if 'global' not in self.command_options: + return + + # If there was a "global" section in the config file, use it + # to set Distribution options. + + for (opt, (src, val)) in self.command_options['global'].items(): + alias = self.negative_opt.get(opt) + if alias: + val = not strtobool(val) + elif opt in ('verbose', 'dry_run'): # ugh! + val = strtobool(val) + + try: + setattr(self, alias or opt, val) + except ValueError as e: + raise DistutilsOptionError(e) from e + + def warn_dash_deprecation(self, opt, section): + if section in ( + 'options.extras_require', + 'options.data_files', + ): + return opt + + underscore_opt = opt.replace('-', '_') + commands = list(itertools.chain( + distutils.command.__all__, + self._setuptools_commands(), + )) + if ( + not section.startswith('options') + and section != 'metadata' + and section not in commands + ): + return underscore_opt + + if '-' in opt: + warnings.warn( + "Usage of dash-separated '%s' will not be supported in future " + "versions. Please use the underscore name '%s' instead" + % (opt, underscore_opt) + ) + return underscore_opt + + def _setuptools_commands(self): + try: + return metadata.distribution('setuptools').entry_points.names + except metadata.PackageNotFoundError: + # during bootstrapping, distribution doesn't exist + return [] + + def make_option_lowercase(self, opt, section): + if section != 'metadata' or opt.islower(): + return opt + + lowercase_opt = opt.lower() + warnings.warn( + "Usage of uppercase key '%s' in '%s' will be deprecated in future " + "versions. Please use lowercase '%s' instead" + % (opt, section, lowercase_opt) + ) + return lowercase_opt + + # FIXME: 'Distribution._set_command_options' is too complex (14) + def _set_command_options(self, command_obj, option_dict=None): # noqa: C901 + """ + Set the options for 'command_obj' from 'option_dict'. Basically + this means copying elements of a dictionary ('option_dict') to + attributes of an instance ('command'). + + 'command_obj' must be a Command instance. If 'option_dict' is not + supplied, uses the standard option dictionary for this command + (from 'self.command_options'). + + (Adopted from distutils.dist.Distribution._set_command_options) + """ + command_name = command_obj.get_command_name() + if option_dict is None: + option_dict = self.get_option_dict(command_name) + + if DEBUG: + self.announce(" setting options for '%s' command:" % command_name) + for (option, (source, value)) in option_dict.items(): + if DEBUG: + self.announce(" %s = %s (from %s)" % (option, value, source)) + try: + bool_opts = [translate_longopt(o) for o in command_obj.boolean_options] + except AttributeError: + bool_opts = [] + try: + neg_opt = command_obj.negative_opt + except AttributeError: + neg_opt = {} + + try: + is_string = isinstance(value, str) + if option in neg_opt and is_string: + setattr(command_obj, neg_opt[option], not strtobool(value)) + elif option in bool_opts and is_string: + setattr(command_obj, option, strtobool(value)) + elif hasattr(command_obj, option): + setattr(command_obj, option, value) + else: + raise DistutilsOptionError( + "error in %s: command '%s' has no such option '%s'" + % (source, command_name, option) + ) + except ValueError as e: + raise DistutilsOptionError(e) from e + + def parse_config_files(self, filenames=None, ignore_option_errors=False): + """Parses configuration files from various levels + and loads configuration. + + """ + self._parse_config_files(filenames=filenames) + + parse_configuration( + self, self.command_options, ignore_option_errors=ignore_option_errors + ) + self._finalize_requires() + self._finalize_license_files() + + def fetch_build_eggs(self, requires): + """Resolve pre-setup requirements""" + resolved_dists = pkg_resources.working_set.resolve( + _reqs.parse(requires), + installer=self.fetch_build_egg, + replace_conflicting=True, + ) + for dist in resolved_dists: + pkg_resources.working_set.add(dist, replace=True) + return resolved_dists + + def finalize_options(self): + """ + Allow plugins to apply arbitrary operations to the + distribution. Each hook may optionally define a 'order' + to influence the order of execution. Smaller numbers + go first and the default is 0. + """ + group = 'setuptools.finalize_distribution_options' + + def by_order(hook): + return getattr(hook, 'order', 0) + + defined = metadata.entry_points(group=group) + filtered = itertools.filterfalse(self._removed, defined) + loaded = map(lambda e: e.load(), filtered) + for ep in sorted(loaded, key=by_order): + ep(self) + + @staticmethod + def _removed(ep): + """ + When removing an entry point, if metadata is loaded + from an older version of Setuptools, that removed + entry point will attempt to be loaded and will fail. + See #2765 for more details. + """ + removed = { + # removed 2021-09-05 + '2to3_doctests', + } + return ep.name in removed + + def _finalize_setup_keywords(self): + for ep in metadata.entry_points(group='distutils.setup_keywords'): + value = getattr(self, ep.name, None) + if value is not None: + self._install_dependencies(ep) + ep.load()(self, ep.name, value) + + def _install_dependencies(self, ep): + """ + Given an entry point, ensure that any declared extras for + its distribution are installed. + """ + reqs = { + req + for req in map(requirements.Requirement, always_iterable(ep.dist.requires)) + for extra in ep.extras + if extra in req.extras + } + missing = itertools.filterfalse(self._is_installed, reqs) + for req in missing: + # fetch_build_egg expects pkg_resources.Requirement + self.fetch_build_egg(pkg_resources.Requirement(str(req))) + + def _is_installed(self, req): + try: + dist = metadata.distribution(req.name) + except metadata.PackageNotFoundError: + return False + found_ver = packaging.version.Version(dist.version()) + return found_ver in req.specifier + + def get_egg_cache_dir(self): + egg_cache_dir = os.path.join(os.curdir, '.eggs') + if not os.path.exists(egg_cache_dir): + os.mkdir(egg_cache_dir) + windows_support.hide_file(egg_cache_dir) + readme_txt_filename = os.path.join(egg_cache_dir, 'README.txt') + with open(readme_txt_filename, 'w') as f: + f.write( + 'This directory contains eggs that were downloaded ' + 'by setuptools to build, test, and run plug-ins.\n\n' + ) + f.write( + 'This directory caches those eggs to prevent ' + 'repeated downloads.\n\n' + ) + f.write('However, it is safe to delete this directory.\n\n') + + return egg_cache_dir + + def fetch_build_egg(self, req): + """Fetch an egg needed for building""" + from setuptools.installer import fetch_build_egg + + return fetch_build_egg(self, req) + + def get_command_class(self, command): + """Pluggable version of get_command_class()""" + if command in self.cmdclass: + return self.cmdclass[command] + + eps = metadata.entry_points(group='distutils.commands', name=command) + for ep in eps: + self._install_dependencies(ep) + self.cmdclass[command] = cmdclass = ep.load() + return cmdclass + else: + return _Distribution.get_command_class(self, command) + + def print_commands(self): + for ep in metadata.entry_points(group='distutils.commands'): + if ep.name not in self.cmdclass: + cmdclass = ep.load() + self.cmdclass[ep.name] = cmdclass + return _Distribution.print_commands(self) + + def get_command_list(self): + for ep in metadata.entry_points(group='distutils.commands'): + if ep.name not in self.cmdclass: + cmdclass = ep.load() + self.cmdclass[ep.name] = cmdclass + return _Distribution.get_command_list(self) + + def include(self, **attrs): + """Add items to distribution that are named in keyword arguments + + For example, 'dist.include(py_modules=["x"])' would add 'x' to + the distribution's 'py_modules' attribute, if it was not already + there. + + Currently, this method only supports inclusion for attributes that are + lists or tuples. If you need to add support for adding to other + attributes in this or a subclass, you can add an '_include_X' method, + where 'X' is the name of the attribute. The method will be called with + the value passed to 'include()'. So, 'dist.include(foo={"bar":"baz"})' + will try to call 'dist._include_foo({"bar":"baz"})', which can then + handle whatever special inclusion logic is needed. + """ + for k, v in attrs.items(): + include = getattr(self, '_include_' + k, None) + if include: + include(v) + else: + self._include_misc(k, v) + + def exclude_package(self, package): + """Remove packages, modules, and extensions in named package""" + + pfx = package + '.' + if self.packages: + self.packages = [ + p for p in self.packages if p != package and not p.startswith(pfx) + ] + + if self.py_modules: + self.py_modules = [ + p for p in self.py_modules if p != package and not p.startswith(pfx) + ] + + if self.ext_modules: + self.ext_modules = [ + p + for p in self.ext_modules + if p.name != package and not p.name.startswith(pfx) + ] + + def has_contents_for(self, package): + """Return true if 'exclude_package(package)' would do something""" + + pfx = package + '.' + + for p in self.iter_distribution_names(): + if p == package or p.startswith(pfx): + return True + + def _exclude_misc(self, name, value): + """Handle 'exclude()' for list/tuple attrs without a special handler""" + if not isinstance(value, sequence): + raise DistutilsSetupError( + "%s: setting must be a list or tuple (%r)" % (name, value) + ) + try: + old = getattr(self, name) + except AttributeError as e: + raise DistutilsSetupError("%s: No such distribution setting" % name) from e + if old is not None and not isinstance(old, sequence): + raise DistutilsSetupError( + name + ": this setting cannot be changed via include/exclude" + ) + elif old: + setattr(self, name, [item for item in old if item not in value]) + + def _include_misc(self, name, value): + """Handle 'include()' for list/tuple attrs without a special handler""" + + if not isinstance(value, sequence): + raise DistutilsSetupError("%s: setting must be a list (%r)" % (name, value)) + try: + old = getattr(self, name) + except AttributeError as e: + raise DistutilsSetupError("%s: No such distribution setting" % name) from e + if old is None: + setattr(self, name, value) + elif not isinstance(old, sequence): + raise DistutilsSetupError( + name + ": this setting cannot be changed via include/exclude" + ) + else: + new = [item for item in value if item not in old] + setattr(self, name, old + new) + + def exclude(self, **attrs): + """Remove items from distribution that are named in keyword arguments + + For example, 'dist.exclude(py_modules=["x"])' would remove 'x' from + the distribution's 'py_modules' attribute. Excluding packages uses + the 'exclude_package()' method, so all of the package's contained + packages, modules, and extensions are also excluded. + + Currently, this method only supports exclusion from attributes that are + lists or tuples. If you need to add support for excluding from other + attributes in this or a subclass, you can add an '_exclude_X' method, + where 'X' is the name of the attribute. The method will be called with + the value passed to 'exclude()'. So, 'dist.exclude(foo={"bar":"baz"})' + will try to call 'dist._exclude_foo({"bar":"baz"})', which can then + handle whatever special exclusion logic is needed. + """ + for k, v in attrs.items(): + exclude = getattr(self, '_exclude_' + k, None) + if exclude: + exclude(v) + else: + self._exclude_misc(k, v) + + def _exclude_packages(self, packages): + if not isinstance(packages, sequence): + raise DistutilsSetupError( + "packages: setting must be a list or tuple (%r)" % (packages,) + ) + list(map(self.exclude_package, packages)) + + def _parse_command_opts(self, parser, args): + # Remove --with-X/--without-X options when processing command args + self.global_options = self.__class__.global_options + self.negative_opt = self.__class__.negative_opt + + # First, expand any aliases + command = args[0] + aliases = self.get_option_dict('aliases') + while command in aliases: + src, alias = aliases[command] + del aliases[command] # ensure each alias can expand only once! + import shlex + + args[:1] = shlex.split(alias, True) + command = args[0] + + nargs = _Distribution._parse_command_opts(self, parser, args) + + # Handle commands that want to consume all remaining arguments + cmd_class = self.get_command_class(command) + if getattr(cmd_class, 'command_consumes_arguments', None): + self.get_option_dict(command)['args'] = ("command line", nargs) + if nargs is not None: + return [] + + return nargs + + def get_cmdline_options(self): + """Return a '{cmd: {opt:val}}' map of all command-line options + + Option names are all long, but do not include the leading '--', and + contain dashes rather than underscores. If the option doesn't take + an argument (e.g. '--quiet'), the 'val' is 'None'. + + Note that options provided by config files are intentionally excluded. + """ + + d = {} + + for cmd, opts in self.command_options.items(): + + for opt, (src, val) in opts.items(): + + if src != "command line": + continue + + opt = opt.replace('_', '-') + + if val == 0: + cmdobj = self.get_command_obj(cmd) + neg_opt = self.negative_opt.copy() + neg_opt.update(getattr(cmdobj, 'negative_opt', {})) + for neg, pos in neg_opt.items(): + if pos == opt: + opt = neg + val = None + break + else: + raise AssertionError("Shouldn't be able to get here") + + elif val == 1: + val = None + + d.setdefault(cmd, {})[opt] = val + + return d + + def iter_distribution_names(self): + """Yield all packages, modules, and extension names in distribution""" + + for pkg in self.packages or (): + yield pkg + + for module in self.py_modules or (): + yield module + + for ext in self.ext_modules or (): + if isinstance(ext, tuple): + name, buildinfo = ext + else: + name = ext.name + if name.endswith('module'): + name = name[:-6] + yield name + + def handle_display_options(self, option_order): + """If there were any non-global "display-only" options + (--help-commands or the metadata display options) on the command + line, display the requested info and return true; else return + false. + """ + import sys + + if self.help_commands: + return _Distribution.handle_display_options(self, option_order) + + # Stdout may be StringIO (e.g. in tests) + if not isinstance(sys.stdout, io.TextIOWrapper): + return _Distribution.handle_display_options(self, option_order) + + # Don't wrap stdout if utf-8 is already the encoding. Provides + # workaround for #334. + if sys.stdout.encoding.lower() in ('utf-8', 'utf8'): + return _Distribution.handle_display_options(self, option_order) + + # Print metadata in UTF-8 no matter the platform + encoding = sys.stdout.encoding + errors = sys.stdout.errors + newline = sys.platform != 'win32' and '\n' or None + line_buffering = sys.stdout.line_buffering + + sys.stdout = io.TextIOWrapper( + sys.stdout.detach(), 'utf-8', errors, newline, line_buffering + ) + try: + return _Distribution.handle_display_options(self, option_order) + finally: + sys.stdout = io.TextIOWrapper( + sys.stdout.detach(), encoding, errors, newline, line_buffering + ) + + +class DistDeprecationWarning(SetuptoolsDeprecationWarning): + """Class for warning about deprecations in dist in + setuptools. Not ignored by default, unlike DeprecationWarning.""" diff --git a/venv/Lib/site-packages/setuptools/errors.py b/venv/Lib/site-packages/setuptools/errors.py new file mode 100644 index 0000000..f4d35a6 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/errors.py @@ -0,0 +1,40 @@ +"""setuptools.errors + +Provides exceptions used by setuptools modules. +""" + +from distutils import errors as _distutils_errors +from distutils.errors import DistutilsError + + +class RemovedCommandError(DistutilsError, RuntimeError): + """Error used for commands that have been removed in setuptools. + + Since ``setuptools`` is built on ``distutils``, simply removing a command + from ``setuptools`` will make the behavior fall back to ``distutils``; this + error is raised if a command exists in ``distutils`` but has been actively + removed in ``setuptools``. + """ + + +# Re-export errors from distutils to facilitate the migration to PEP632 + +ByteCompileError = _distutils_errors.DistutilsByteCompileError +CCompilerError = _distutils_errors.CCompilerError +ClassError = _distutils_errors.DistutilsClassError +CompileError = _distutils_errors.CompileError +ExecError = _distutils_errors.DistutilsExecError +FileError = _distutils_errors.DistutilsFileError +InternalError = _distutils_errors.DistutilsInternalError +LibError = _distutils_errors.LibError +LinkError = _distutils_errors.LinkError +ModuleError = _distutils_errors.DistutilsModuleError +OptionError = _distutils_errors.DistutilsOptionError +PlatformError = _distutils_errors.DistutilsPlatformError +PreprocessError = _distutils_errors.PreprocessError +SetupError = _distutils_errors.DistutilsSetupError +TemplateError = _distutils_errors.DistutilsTemplateError +UnknownFileError = _distutils_errors.UnknownFileError + +# The root error class in the hierarchy +BaseError = _distutils_errors.DistutilsError diff --git a/venv/Lib/site-packages/setuptools/extension.py b/venv/Lib/site-packages/setuptools/extension.py new file mode 100644 index 0000000..f696c9c --- /dev/null +++ b/venv/Lib/site-packages/setuptools/extension.py @@ -0,0 +1,55 @@ +import re +import functools +import distutils.core +import distutils.errors +import distutils.extension + +from .monkey import get_unpatched + + +def _have_cython(): + """ + Return True if Cython can be imported. + """ + cython_impl = 'Cython.Distutils.build_ext' + try: + # from (cython_impl) import build_ext + __import__(cython_impl, fromlist=['build_ext']).build_ext + return True + except Exception: + pass + return False + + +# for compatibility +have_pyrex = _have_cython + +_Extension = get_unpatched(distutils.core.Extension) + + +class Extension(_Extension): + """Extension that uses '.c' files in place of '.pyx' files""" + + def __init__(self, name, sources, *args, **kw): + # The *args is needed for compatibility as calls may use positional + # arguments. py_limited_api may be set only via keyword. + self.py_limited_api = kw.pop("py_limited_api", False) + super().__init__(name, sources, *args, **kw) + + def _convert_pyx_sources_to_lang(self): + """ + Replace sources with .pyx extensions to sources with the target + language extension. This mechanism allows language authors to supply + pre-converted sources but to prefer the .pyx sources. + """ + if _have_cython(): + # the build has Cython, so allow it to compile the .pyx files + return + lang = self.language or '' + target_ext = '.cpp' if lang.lower() == 'c++' else '.c' + sub = functools.partial(re.sub, '.pyx$', target_ext) + self.sources = list(map(sub, self.sources)) + + +class Library(Extension): + """Just like a regular Extension, but built as a library instead""" diff --git a/venv/Lib/site-packages/setuptools/extern/__init__.py b/venv/Lib/site-packages/setuptools/extern/__init__.py new file mode 100644 index 0000000..98235a4 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/extern/__init__.py @@ -0,0 +1,76 @@ +import importlib.util +import sys + + +class VendorImporter: + """ + A PEP 302 meta path importer for finding optionally-vendored + or otherwise naturally-installed packages from root_name. + """ + + def __init__(self, root_name, vendored_names=(), vendor_pkg=None): + self.root_name = root_name + self.vendored_names = set(vendored_names) + self.vendor_pkg = vendor_pkg or root_name.replace('extern', '_vendor') + + @property + def search_path(self): + """ + Search first the vendor package then as a natural package. + """ + yield self.vendor_pkg + '.' + yield '' + + def _module_matches_namespace(self, fullname): + """Figure out if the target module is vendored.""" + root, base, target = fullname.partition(self.root_name + '.') + return not root and any(map(target.startswith, self.vendored_names)) + + def load_module(self, fullname): + """ + Iterate over the search path to locate and load fullname. + """ + root, base, target = fullname.partition(self.root_name + '.') + for prefix in self.search_path: + try: + extant = prefix + target + __import__(extant) + mod = sys.modules[extant] + sys.modules[fullname] = mod + return mod + except ImportError: + pass + else: + raise ImportError( + "The '{target}' package is required; " + "normally this is bundled with this package so if you get " + "this warning, consult the packager of your " + "distribution.".format(**locals()) + ) + + def create_module(self, spec): + return self.load_module(spec.name) + + def exec_module(self, module): + pass + + def find_spec(self, fullname, path=None, target=None): + """Return a module spec for vendored names.""" + return ( + importlib.util.spec_from_loader(fullname, self) + if self._module_matches_namespace(fullname) else None + ) + + def install(self): + """ + Install this importer into sys.meta_path if not already present. + """ + if self not in sys.meta_path: + sys.meta_path.append(self) + + +names = ( + 'packaging', 'pyparsing', 'ordered_set', 'more_itertools', 'importlib_metadata', + 'zipp', 'importlib_resources', 'jaraco', 'typing_extensions', +) +VendorImporter(__name__, names, 'setuptools._vendor').install() diff --git a/venv/Lib/site-packages/setuptools/extern/__pycache__/__init__.cpython-39.pyc b/venv/Lib/site-packages/setuptools/extern/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..474cbcd2eabb854a0ec77e4c2fe7384c0ebe69ab GIT binary patch literal 2988 zcmZ`*OK;mo5Z)yzijr){dD%&trbG)Q5fBSW0~BZ*6bbSuf(Am6q-m?FVAtA}O@$(v z-Blc^au1acJ@wYR4fK*<(*Lm6p86LGwCT)J@Y|?~n;?`8?p29nvcEDzCva z;0t^ao)x~tPr$Rv&+=t{5=PbdDSjGy7Pt$mub8FhBITKU*v~Vmg&gfvL%8mQkMBPY zZ(jd6>j-B;{?oen=N0w2D4IAj*9)&OQy2FnsJrTW@)x_y8~s)QsfEi2vaRS zMEQ%2x@SBklCCVl>avUi5J4n{$%=ozzx!GHYbB&=vovL@eJ9WFG0obKvJOky&qP0O z=W)I^NYQe^*S0o=NY-u)Sa0j5?zdqhgIs4>qT0od+ffv!v5ulfJ~YAXr3ULM9|WO3 ztx>Y6ZlY^ZYp%I&hdoQ%p_Sbs|LAGH%a?y|h3_ z7v?NGq}V}YW)}uz9~%vL0UV%#6b;;?ZFk$*cDKE;vp}+I+R^UV>v{0KGy&{@(az}F zgLq>gMVJkA7KMUqAz@sW4vpJqxv2ug zrB++9-n2lem#pO`=nj$uF>X8rpz+q362>oayN1TK83okh< zbaZvjOUDj7;_>A!yhTMDfy1Pym%dM?Q^GB?vj}3U_$<&ztIW(g<2Z&Mqlj% z?;)fs(-4hULfTjqfiE~nXJG>Q1fN;Tp~-kS^XdWaY=}m`KLgNS`KfU4_LUhtF_==k z9K=%a&%-p6eIzDW2>Ri_K1eyz6GpG-oDx;2G6csk8-$1qtG~r$3M6}07LBt@P~ z^@0DawhVc!w2apWh?PdOUXdrk;RTN%;!PED)>3N}0Ur&4e~Qp6Q!7~czLc3XKF}_J z!T9KaMAd^LpU&cBnA36<1){_FxfI>_wdFpRYJg?N=K)qj=S|V_J`7TqKoD;QNX4N6 z{Hpf1Km!NfUGHD-?K>%XXo@57!t_L9wD4Mh#+X1#(jMJ|gnL7qbw_>(y~e|AfEOeN zpx0b<=6AW+kpiMU-RDivQ#SYM=;9pkk0`#g8)QJc8)OPB4e}#s*wtq1`-Ru%cTf|r zMQ6G`migKG^YnB`?fBAl5hf^nu}9@OO?%F+i=}MOd0LzXoYB=MPzWSY>x_KREwAWO_L4vDa?Mi?O>LDOzOX zG!#jKc){Cc>ijo4H|Oqs)prVw3!|*7FF<2VG%)ciDp&Bi3zc~fxWgWNoY9kmoG*?A z(=42wGvXA|9TK8}XAoNozS0dF1so$)-@;zABRQAUhpXE6eNqGYL z=S?n84o z)`=pCSzv-(X1S1hC^7ME^lTzXJkrRkDArJ1M}bQn5?C!IVjt_BIs+o0Ua4AgXtf-a zf|bAx+-lis)GJt>@OTB}1kE9oDh16}Et7x-0WlW3wbaj~h+<${d+KPN+J{kuzTfkKXn4P-HW@&$x2BK8f k(IAYK-LolKRLdLKah&}oxK;T13(RK=P+%%|>8|Jf4>2PP`~Uy| literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/glob.py b/venv/Lib/site-packages/setuptools/glob.py new file mode 100644 index 0000000..87062b8 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/glob.py @@ -0,0 +1,167 @@ +""" +Filename globbing utility. Mostly a copy of `glob` from Python 3.5. + +Changes include: + * `yield from` and PEP3102 `*` removed. + * Hidden files are not ignored. +""" + +import os +import re +import fnmatch + +__all__ = ["glob", "iglob", "escape"] + + +def glob(pathname, recursive=False): + """Return a list of paths matching a pathname pattern. + + The pattern may contain simple shell-style wildcards a la + fnmatch. However, unlike fnmatch, filenames starting with a + dot are special cases that are not matched by '*' and '?' + patterns. + + If recursive is true, the pattern '**' will match any files and + zero or more directories and subdirectories. + """ + return list(iglob(pathname, recursive=recursive)) + + +def iglob(pathname, recursive=False): + """Return an iterator which yields the paths matching a pathname pattern. + + The pattern may contain simple shell-style wildcards a la + fnmatch. However, unlike fnmatch, filenames starting with a + dot are special cases that are not matched by '*' and '?' + patterns. + + If recursive is true, the pattern '**' will match any files and + zero or more directories and subdirectories. + """ + it = _iglob(pathname, recursive) + if recursive and _isrecursive(pathname): + s = next(it) # skip empty string + assert not s + return it + + +def _iglob(pathname, recursive): + dirname, basename = os.path.split(pathname) + glob_in_dir = glob2 if recursive and _isrecursive(basename) else glob1 + + if not has_magic(pathname): + if basename: + if os.path.lexists(pathname): + yield pathname + else: + # Patterns ending with a slash should match only directories + if os.path.isdir(dirname): + yield pathname + return + + if not dirname: + yield from glob_in_dir(dirname, basename) + return + # `os.path.split()` returns the argument itself as a dirname if it is a + # drive or UNC path. Prevent an infinite recursion if a drive or UNC path + # contains magic characters (i.e. r'\\?\C:'). + if dirname != pathname and has_magic(dirname): + dirs = _iglob(dirname, recursive) + else: + dirs = [dirname] + if not has_magic(basename): + glob_in_dir = glob0 + for dirname in dirs: + for name in glob_in_dir(dirname, basename): + yield os.path.join(dirname, name) + + +# These 2 helper functions non-recursively glob inside a literal directory. +# They return a list of basenames. `glob1` accepts a pattern while `glob0` +# takes a literal basename (so it only has to check for its existence). + + +def glob1(dirname, pattern): + if not dirname: + if isinstance(pattern, bytes): + dirname = os.curdir.encode('ASCII') + else: + dirname = os.curdir + try: + names = os.listdir(dirname) + except OSError: + return [] + return fnmatch.filter(names, pattern) + + +def glob0(dirname, basename): + if not basename: + # `os.path.split()` returns an empty basename for paths ending with a + # directory separator. 'q*x/' should match only directories. + if os.path.isdir(dirname): + return [basename] + else: + if os.path.lexists(os.path.join(dirname, basename)): + return [basename] + return [] + + +# This helper function recursively yields relative pathnames inside a literal +# directory. + + +def glob2(dirname, pattern): + assert _isrecursive(pattern) + yield pattern[:0] + for x in _rlistdir(dirname): + yield x + + +# Recursively yields relative pathnames inside a literal directory. +def _rlistdir(dirname): + if not dirname: + if isinstance(dirname, bytes): + dirname = os.curdir.encode('ASCII') + else: + dirname = os.curdir + try: + names = os.listdir(dirname) + except os.error: + return + for x in names: + yield x + path = os.path.join(dirname, x) if dirname else x + for y in _rlistdir(path): + yield os.path.join(x, y) + + +magic_check = re.compile('([*?[])') +magic_check_bytes = re.compile(b'([*?[])') + + +def has_magic(s): + if isinstance(s, bytes): + match = magic_check_bytes.search(s) + else: + match = magic_check.search(s) + return match is not None + + +def _isrecursive(pattern): + if isinstance(pattern, bytes): + return pattern == b'**' + else: + return pattern == '**' + + +def escape(pathname): + """Escape all special characters. + """ + # Escaping is done by wrapping any of "*?[" between square brackets. + # Metacharacters do not work in the drive part and shouldn't be escaped. + drive, pathname = os.path.splitdrive(pathname) + if isinstance(pathname, bytes): + pathname = magic_check_bytes.sub(br'[\1]', pathname) + else: + pathname = magic_check.sub(r'[\1]', pathname) + return drive + pathname diff --git a/venv/Lib/site-packages/setuptools/gui-32.exe b/venv/Lib/site-packages/setuptools/gui-32.exe new file mode 100644 index 0000000000000000000000000000000000000000..f8d3509653ba8f80ca7f3aa7f95616142ba83a94 GIT binary patch literal 65536 zcmeFae|%KMxj%k3yGc&SCTD>S1PQP}R5YmQ5=~qJi^+zl1UE)DtPsG8blp-*!#RLg z0>QIub24npZS_`f-)#|`^OhvIcH|hGc(UT^E}VYJoC(K^_@EDjE;rth;Yer@_4k$X3I);E0Tn+-Zb>&yT9Ew!oxAMfl)C z#Z+d`C?Ev=lGJ)}%Ksnx|0)G)SVf_n2-;d?f9!~MzIJJ-=wKb=iHfW2QCpC29wSNm zA=ztsPZ<@3t`2ENV!bW?>DIbrM&c*bCbqaRzr~R~Z-r)Gl=RG-p}ugUHp=<&@N<(0nQZ)pc;t^f@UfdU)Xs*a2q9hEj|W&QGS`}Q+V zaO>`-aSJ8yAtP2OBNk%M7Utt!$6gfgmQ40WtW_PKSW_r1oOg}p=vZj3XtBjwwJ#E} zLMNCsnAlP1f|%AM?kIHMo~S5v2kZEcbEs|ZrY(iCq{N>@V-R$%P-2fEhzyjmCh@Sy zXyr*PE_By~_)26%86IRFp9Ya zkBHB1hGv2=t60ZM@2flwcy2#L^lN{0=%0Q@MjzL)ErkWFb2Ro*N07ImOt!9YmgwvP zqh2yflmnST)@Q6JEa3kv=;e&Js^gRcx7ile@Me+Xh_`B=wJ3|47Z(=9j;P;M4jj9k ze|zYYnyGIobV=&smWsjxVw3XZ39!ke-gcWd&f8i_T!k-^@^CA0*s%-oQ>v?$_-7%o z(GNN8XT7J;F$I$PlNQv_oLiavAq4>E7I2dQhlE)vSn!y;BSSI+5(`L`#@q*i(+$dj ziMR82oKzstr3NgrEei6^p%m@2rUhVv>rK-H3%XZ<_rUh;c(a2dG)%uOg$_v@w_EZo zlu%GsR0^7TQkP%ahpqsf^)t)7t)|hz?tCY-06G}<$V~#?~heoED!!4L2akG@t z3k(cUbnpdgqwk%>`n0WAC7vv#rU2V~=4eiAwpse1#pRD3*UlGpF7&;UP%~^>-Uq9> zqqY#gDuX1JM-HRLrTl?xL1RW6Nzt8%&-UwXtnfuqbCmh#A4k1U7-%L3c7Zx(d zuhG+B-K2d4zoLVczO#ufnYJw*t5&k#)-NC8`0Z!%(?;tLH)1SS=)o%@p*m1Hza}bC zH<@{EP=$nZv|K=--J~^q2RFJ=UsK7|s*{A7>2riBOI3;B9VN6@g>xk)TvhhOKNMSeI?sb zNT@@qXG7GtAEH*Z*I7+?xX^=^+#cd{e*xu~c+oK%QC`k~8T1Fj`XSd4etuu)23Ly= znHbY_evF#lbUsH*M$@PjpbB6kZlDn4%Pfry7Wc9o2a;HxjOT7A9>$Ks0zkIpxF}-P z4%J+UwB{X!v+x4JvU3b1r4SD4dNJCLBe`P~a!!^eLzUU1z9JMV04G)5v%Ur4xPh4u|g#Tc-(r0PB00 z<2OM*Q-Cajywm3kTRsx?bLZ%s;?w6_FF__SF*1GDPvs6}`fAHZ`iq5gfrnJz3GS7o z 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/setuptools/gui-arm64.exe b/venv/Lib/site-packages/setuptools/gui-arm64.exe new file mode 100644 index 0000000000000000000000000000000000000000..5730f11d5c09df7758cfa1b1dfb5ced4bf2ce55c GIT binary patch literal 137728 zcmeFadwiVLb??2O8A*Od7h~(<8yAgiNJe8I*p@F!NHnq`$TkT@5@{|y$C6E&kqrsL zCc%(IGBoKJH!WkEkeJhB8^Vg^5}KeXZ@u9c5oyW-F7^@H|W-?ApIHvAs_ z-u1@Z+L>!U`h(wZ_R~(9*`^>c`BHO-Gm3}@D|tJ`=7^E%-3N@xGyLPvznb6USxDqB zV461hg)(JH^(yf%%9lyet$FYr$3*O1=HE2|Q&*6c5aT(|n3KP8%q3aL<8P<@)-g*g zpqV%Aj=9?db$nL)eD#LU-o1gl#?Mno0IBbpe)t8##xz}h=dH~fnvMCVuaiohCc$+B z*Q~!7Y;(1j&BSK$VhRoCbA9`~eBD>y;bpXaq_3use0k>rYU{i6v$uU=jj??<;J~=# zD?TsZQd0l#-@gL`Bg@R8sg8MYULck}wPxPIQ@y8Z0EwW;j7^nMEU!4}CW)K_k%4AoMX z@|?Z*Z&PQ3q-Wk+m}YzVY}+?DsgP^78}pH$sviIEM9_4G3!RTUm+bm@fM1Z`s&;eg zukuWzWB%~J!=_V0EvuKfq0koNl)o6AR(#3KvZ+OvS6p`SjM6EEmG2w(=U1G$##(n4 z#wzv|#VSmZ;2eE+!sk5KI;MK;efGPoa#>}@@|!}HtBaXKu9LsTw3-`Z{FF8h6ytWc z*RL|}&EUyT*(+%HGo%xKDdSgu>m0lN2y|q3kb@tv|c*aSt|Gil1 zu20sczSOidwK2Xdb?+V5rJ5tLbj;MiAJ>!jI?61g>{9BeO`UG|`;Pxpb^1698s}h} z2@LJeH;wxpv!}wer&oo|Df-qqJ75}Dn<M?dhe)Iki7%8fyw;uQo%gHm*(3JRClH^;Gr)I+gs{_|8LWGxwb7GIrF06h0^3tV`zweS|k5`yLa$0r11+I(oERH@!PAGtbV(E$%Xh{ zcs-uMukc)P@{wWTHwdn?@!Ji4D~v;Xu^V;0T-TEi4_BPrHoS)Crm(qD*IT&?Uyp*X zi@-JT9}RfI|7M;f#+h5ufhjqG<0NoJpJ2r#CCjIA8TST18NFI8b;>HeTe zpN7|83p$-=f`QK0gTc;Y{PIRd9_|a4boK{Jc`oZb9-P+M!1%p|@%#IX-%l}qKg0O_ zFN|Nq_*ESkm|mHSV(@tT;WO`e&u^{&C~aO(+t&fZGGJMXOsGu(o0S{m$4vHfASZVB z>OxcXGWExD%;MddvGVAZv8}7RYfk+G{IqLB>_(@f_4BjM`!1X9n5yr_O!B+0e0i&6 z-L4HsN8ddRcnB$8JH?u zuigsyr9bE#{BDjzePjJzJv>sC2QTk7W{+TB`ljkPr#dK`4ZnqD(*3s2v#DQsOnRhI z?c7G*U(t61U9-m`^jUIWfkz+FCg%0;Rnevp8Mh0bb~@%++61y_vkQ6Sr~7niwsZ++ z=yHummqJtjUF3$~RJ-5J@o+v$Bl`PjX>7^T5f5I`Xb?Crnp{*^kRNg<<>lrCX;`$V ziJeCW3+HXwbjX7DKGDGhJvva%6?!p&IP4n!uEy z-QXpgZm_5QTSdQan_(K4U1p}lk2}XK4BA54clsmy8=MvMnqNw|q zmHc8(XsB<}&ROR2_D`$c;2*_?Bm9)F4;a=IcK^~PUlaDsIr*-OJrm(Kn$IO)Xo7t7 zKf>?4^8eZGFdicO+61TI&H|L@_s5FGya`?unI&4uus!RH0(^#$n?sc)kLemYv?rv(k}W*2Y_l-9Xu-#?|dFbB|2UhP@y8 zNSc+WVeD$|lWPL!j=c+wu?x}28_C}P#7`dF^W~rK_}dM){lSW_ANx-4E18#?2cEvy zr2c7=*5NF^Stj)r?nZmuszRAeFNFM?*Y^5K*L19+^O`DfN6bW`p#M9 zj%nRnymQv}uR0~KQTAA{G`gvvy}l2->87_w9)59Y)fTn?!rLQNFHAE_UZSq?`L55( zca%J#V5}>WYo=CyCAQ6_Kha#1Ty$@Acp-XJ{W%V<{C@OtuYL$O9qEyUeZiTX>3g&1 zQhzrgKF@%k4vWvSb8xxHDLdGEPkBR#w!=jxSpl6+<(loE%4x5EgEHxWsXm=&lIqh@ zaPVu!!MEtI>MCy?!`Wo)j`Gc>wHci4R6cMvhMSU3mp-r0;O1`n93a2y?0_CG=9!!0 zqF<@wl?-x4g0&fu%1vy|XRPR8Q1r!=L5H?0MSHZ!Y!M=k9vMPh4BFo+CEiGPS!cG^bqOG zL$R*7W72i=x~p44rYk>f5 zKUKaY1Rh)H`%7ykCy%cwrf+%4etb@vkKE1J9#{sC=a_{9YyRHyS`68IUS9BVyYiCf z1m#6H;Z<^CIsLYMg->_WW?lc$CCfwRkoXoE2QBmHZ~o9@89GMJ9$jL28hqq{gX6$4 z3e%ct$*UL_r@3m3w1fBe^L!sy$<^2C^KtO?3CHXeZPfq&4P2IP&6AUoeS4WF>D^z# z`=_VJx+KGf10@A+TWlK>iew4(NsdXDOaYHob4)UfOoQKBi-318ezf(Bm0e$t4ZFP8 zef!tV@HYA?-U*U6LSCgQ|1Fef?ArWq({^@####Ci=+ck;Pn{3f^lMhtub}$MP|DTjO7Lo>67iVvTXp#@3Z&rv;O1wC9!nK ziFM7r>$2iV@4Df&@W*n;Js5SIEwKu7s0kRu;NtAPJ)XY9Zt=?sZ$D)${!hnj|8l9> zp5lr<5&b}!Y$DU8a);p!_Y%|4f$pCd5KP!XyPf2x$-9$ZhxBZ~EZoI?7r%Do3VE=J z7AOCex|ObcTlxKpHgr{eb>wqO%=SOw`4B&J#6rkPcok-ws=JlC`~ z;RB7+w+MMU^7Fe=@N7jzK~g+pn$aJ?-$Xz9%G>Lg!WT++YV(uI7k1DK*iChrvO(Tg zalePQklWFp)82aE_3XD;x&vS9&J0|2$eZ=Z#orYF_+Y zR{36h8Gn{39|xu;%D)VJx00viTIdHX$m!@YWCgr`7`gvEV<-6$_)s*zlYF8Jc2!j) zwD<{S$yYCY{eXG}bBI1Dui91K0qMMDvFbYV|1J5I=j^@DcAP1QrB63JYx%8@^0nmG z6pt+pU}ob$Yq~)e)=yd(-bgO1Hs}>Z1A$33g3lixoy)h>i#M=Eu-{@E%bomn4u0e-KOF0d z_FTE8pfgclhrB6w3f9$PXVlFj&sA+*R9KkLK1Kh;;V^V9wqvF$X7uYP28!E3aWVBBNBe6k!Hwidc|NPbi} z$&rgpI&}7EZy)+PES-xEq%Y4`I!HJNh=LRWL=Y*bfor32=KZJ-^4nu?$6%)jHT58_>rB|XRi)6Q-GgrC+sHdrSf?hduWs27ie=6 zw#;K1ljhDk2iZI|G3)HTy_Vm(ZFc?~ZI)&bY2&Tx)LXk84NwU!%X(rWJl^tV?SQnkwOcY|MG`MEnT;z{7_{wS_z|4p^?n>;)R^(CRfMaGb zzg)KqIK&5boMdF#3dUgxwAz*zOMfhL|82(9n)SE$g>$#fG_h|x-gv|q!G#rt$&w0_borG#WkXA8^J(mz4cN+i(67B8sYNHtMyq+T9sS!DC>vsq*(f-? z^;u8$T(BK%Q`=7Se_lKCWA$Mp$H0ep%=cIM{WI_hw#TSVl*!-Khc6{NKX^FlR$}*v zukmC1e0!dsV2;LvCvV+z9#}Xs%4R(`-yev&G+tS>%KVFHIQqndMCp_*ll6xc03wO&t4YU(jP47l+3$q zc;w-x+~LKNvA3hQT>4)**~}2{^^iaQdTly^4c7GNMah5sJ!HD{FlimME&EHhnCM;s zp8J9`I%R*U-Pt^!M!tn@TP2-uzcKQ#(vOiRNE_&g&X;G$(l1Smr7Or2AMxaDntbZl z5M|Y8`P0A&KA2{_#uC|q~nBMW?o56C6Lwx)N}-Ifd)`kt6CyugW4DRM+3Rv3n$62I#?sShQ|s*V6S~Ob zgcDvABE5=vYZd&NKyH?VM&|~WH^rCuu`ExH*Pp)p3!8Fus6VoH7a;FrT5(_CneU*G5P&(WMW|H_iLuTxjAkkQ+AUjBsJ97xK?*G+!k{*cdXU!HkVWBj2Uv)7i}6iE7cn6qpR zgAZU?SVr9!Q@1k({l~rLeSUt;yZkawfmdsXQLY<$U@sTP?=f9x7`r8ubA9;EZO7_V zwV^RyNPlhJ6<#0YR}>uh&pRj74_S65^*?BON~JTOh}4eZU;td1nWn2e$IR=dzj`i# z4z?X&5l(!#cV)pXp4EIaSG2U_XKYTLZI_;=z9!Lv`um`Tt#|iW`>yaX%ku-M5B|K| z@aNOr!q{`I2fGurFfmW9cV636Z~G5i%&DHQ`_xU=pMZ@wb@`_*>KYH9&rhcte&nrh zlt|BbJ`VBBkx$>$bp)BL_DX3_u$EN>lhc`7$X}Ow=V)(J{q#rFW-obZ=jH>SzNl*f zb3@@n@V|jQ>gnnI)@D*aeh4q?`f@O*^Ck4zabiA>q0hue7!0Ko!DD$aU`|~=BlhMS zlzTmxEBm$ahD+sxYp-{W=?ZY)%{>fW+7WQJ)Z~~aOQ-JKaT0{?TIHo$4} zOTadOFEaw(PXtQPKbiX99BHg;IlV;nFXyWIpQcZ}|{rszmndrrzuX>e7 zb*s+jvg%xltRG+JX!$or8rvxA^YTP=9HkR+c0S*TPKx6>&HBYHQ_Y?#ep}|pQf-bo zHHhuLlj{Ii*_5@|8;SSTrm%lbov>-%yH&hvzDVzuPWW!qWW8H9;k(^MrV$^);n$(L z`ki1bRN`xA9VfXNUxd=i2U!b}o&SNdc%z+I3+TKjF`0GCAUsU0LnXZ7!}bHan)d?WBvJN8Xq@hxw%=G$oN!cICK@aj4M-Tk^csH=TeERC;mPXb$W ze_*<8FZH_eOt-k$NgnAdNvcg>DTj3@@%Fa3k&u5u!y%pl=X2hJ=j3r-pqKO z%)Q35l_R6^m}7Dz#Qafpx;bNYhTKeAVOH9dOd2}fZ##rNV9R0$_-Vd8JbUl=?R>F@ zxqm-%_T<6lRny!3vP9zb5MBG0jM(}0a%?S|VAkKDkO_X8KRHo`md zHz?hvVaM+zZS;ArNq@ll-~QgpMt=--NG~^ga$T}@0QqaulRUe4)424rlhVGd_2IYq zn`=hr!S;F6*z@Uzto3Z-WBqo~O()~ng>m$_8}s};YIZKkfOFP53jYZ*gr= zQu=)wzYWwgE7X3tntZ-~YkJlseP=RT85Wb%z9)lu>kQ9 zb4g@-9ph*tx|B7PUqSfXvqSLfQd-ukrQae+rZnfwCmn2P*Igj?&^ z&a$iSVNLU{%RC!IdQo}5{ev^GAxo;$>Pn;d3UmOyn(1 zFBon+5{JHRfhngLW5g*eO}7QyA<`Pd1=8CB zf%F2>sr&FCX_Ns*=Kai9d|$WVT;-b9Ze;kXLeqNPj2rI>>%PjH@hpSV=M z@cgx!XG>-a4&RsJkDJgnOC=NbhMJrt{C`;Xl6&RSw0pMphvzC7?aB)BL#z>EuT5zc;X?xkU zena>xD=G+GYNpO5&AmL9E8W>tdm_8xb?k+s#8-$P7K3B)ta##M%-ztX#U1cz2p^z)$B}u3^8HuYG}a{! zpaXXEp7@Js*A@75v8{JmzGDu9?YkM7C0c%qYlymPm6lSC zv+Uy6fD;?3Rcq>k^GpWL+u=FsJJw0DBc^p;thfkdspec`ZI!MYA~x$ncJVp$1nO^F zZK|;a_7EGGivNX4X{%rOcOQL)`}r;(4)j8DkGWS<)f>05WFnU(}}L!&cra zNo&DAS;>_-cRI>%a1J_PB#;_eX}U)C=M0Z5%N;&JTO<3;#*y`;9dW8hY69tzWr6g- z4T1E~Q^C~8ww$g6c7xV+`j#zCADyLmi&(YtbZ8zFWZcll(8kM(m(w?`_bR^XVPKRz z0sds)tHgycPdVLCi!L0qFCxfGVvo`;_PgM_k(dD&+iehgZUA3N4SpEW*2UgeS{$3a zAO{~jHeWoG_tzIAA1_4)l{q)pI7MrlH13H3QQj8DXOw)adOVviN{ol@iJ@wY@Q!tx zbyrSJ?1-0jFG*Z#Y%Gq({#C$L2u%NDb1Y4I!+`_wB{dH@t=-i9J>V<^9;LVZB7S#j zWcuRKJpE2m^+(Dc25B(LfFt5-zZ0Ci( z+!@n@o{o_|*aj_M$L`;T3^_);hInEdJa-pkfO$mMQuKuE(Eeq_F`$cxDLM2VbSLts zOExWd+51z4yW3n4wvi8a?(E2XwvTLDs-%hq) zc+3wjxSAF%O^5T$o*ZHgT&*$XK`+`#LHG8 z`!(F}OnI?l&4<0%Cg}Wdl=QXC5e9<9!{o-cMxFdEEAh{-D>mudHm!Q*wne7vAMi8B z=f}G6i>_SDbI7@De#?B*6`^mEQ*9qKU9&Rvi|3nj?ki7^EEIi2oALDQKQ+?W1l^vd&cAx* zZ+m|Bi=p3Suaj6=27knnyQ&L1?!7t-&x12OJl_o*nQsH?#J_p zfk!GyzYs0o3y+95#3Qm9RsX+*M?C&8qx_-$FzV~9EdKaxhCe!9J)b`|zYBlVzUuKu z_BeX{Z+_JM;?DW_c)KjXc=jC$hmYZJ5` zZyzb0@vAlGJS0sob5Iqww3PzHapJIOD%SsV;_Tq8yJti3=DW<)7tg# zr5_p(>IZ(p3Hs4|PCo|F`~KMZ4zYj}!E$*PEJvq%eqiBYJS_fvI|M(~%yeulH##q! zD4el)5d4R(G+jS~&TPVOU|f{eR1?dLK2V-`!HmTrbgA;VS?%r5wAU!Sv%VZbU)Q9Z z)>l}gYUfvT1@-}aSu@XRjp=$b{wC_I+3mDy9WaEyB!ccQ=Xp0Y#r{aTg(h7IJRhdc zwo_X7D6lsm#zxK&KcXkRIx-Pg^$7rk1zhJeYZo5o^!IQW7ypie*5 z`Amp?F~0rf>r|LzyLeSP=g*;YMdm&hG}|xB+_S#DU3QRcq>yuowT)`wL;0~(?n~66 z`C1F_BW1aYZ>x$pGv~*#q41s6zYf1@o!h~_dyRXQQ`}sL=Q!_MW>2ad=2>;UmeF-} zMabGfZFO&cbxQh8+Sw`{ilt) zX_;}?OH8xIU0uQdzsB7XczU97Gz?ze%Q%W;jiWBgyq9rw@p~9Y8{syMBVDukSkLeE zCq5pZSK~-&8b{;b`Oj)k_iCTZdF?CB&+A{a$C01rx36*Jr=35JJiokb^3l0i=-m1G zU7J=7pJBal4>tN9uB$&1>yq8ugb!{$`xG|3&!kfU;)Ss_J0$avO>u1E%C9&LvXwfC zlc;m1C*$N>&NY(Rzoax|@6b#46X9Uy5yvPS`*m`7i74%AM-qcWGj+ z=lL`-rSvPJa`Ww+ey{J>k6-Qi^+R{%-Yg$O3;83tOVi9PPeq86Q-3dn(>pe;db^qW zPL`Onw7oYcvsR!wb66|bOcD=(#*f}SsZp&=)d~SBk`a)kTFkPRe zPk#tL27)I21=d8Y9znNCkH`;_KnFELzoz#QvjqQ-;_6ZlSN-(gFS9u-@AJ@iEoD|> z*S9f0_4BQe?~49~oLSZ`(fjxn8N2%-{0Y=I81U@wxG{^{n1A?X*G+D(U&s6_wDFQ+ z`Fm7W`>0q0AKe4XzMq5f3{OCJ;+>v7C%)K$rz`l4pI2t{<`!rt{9C@npK5(k&bhq3 zX49&>MTbpU_|{xnxDJ5hTZOZwPV#m9H(~0qyp11B>($xxz7l#*RDXQa(Ip9dq28Dn z;}PlcY(6<}zU;@-WW`0;G0NC`Bj`jw2~V!N%Cts^aacYDeYd=G)W^5sS(8lQ(_Dnz z6~bPNg9GtF2>)9P{%XXGw#;9Y<7LqSo;+`w!R5ujBMHL{C?g+!9LE1c-N+#&&dCAe)_6sz6so$fj=T! zm9h_+;ioI%Q?22gA>Ki9;{kk+mL`l_)f0giYw1gZJR0|hi93A=o)8{F8)p@(tmM?u z**a5c2K#ZeMpM!W-w^jv)_FC&Ccfc5Izm}n?$SvOgR&v(z4*#F<48Wn8vHv<0vq+5 zk3EPF`vzot2zk*5Z?A>7#8cp)u_bsePpyr%cRdhbyaSJPtneh*;`QAdx!-8V%%jB0 z5bxuU5%IY4{1%vf_*sw}h2LK%e&yBQzB0()@Zc+hWA>e=m$WYMzyz>wfsYgUH&lkq z6UFQ4!zSckJNig#WeeH+vkiQ1fesq`j6dxk*_%QSMS7+s6TDl%RdDY9Dl~_#qUA?_ zGxD(dH<}myWb<-WKIPd(9%O7ZaRGhh`(@lxZ=KO)ow0*GzTae>;x}4rbJo zSny?h`|!cqvmf2oOU#11aqVzRS!`<|@d{T~6h0z5|F4`-GVwC8V(1^g?1jqA&6N2b zW#VUI)dS4Q9?Zi1$_(yRuV^EgA zzP`3PLY%n9hWxfa#;0=^W2cn59($k8H6msv$eIeWx_^$=AWZTB{90l5XdNS#` zrjO_JyN7jd*-?JKH4j#wRZjh0^Qea}H>)4to}eESt&3|tTx;W}Sr6ZyW2z1?o}-p0 z^M`tnvk~~sRsSTDozepN@#?T2!|>C?jL&js`cT=thj(ZV{aX0vIm(OoLQWZbWK7yV zi#PQQZ`x<-Oc2YnFED+moi=R0kZtl~sGU^6Eok9cV`bv_#fjsf(!`f8VBJ`KLSJ*n zMjm!?yUK90iqkeebTLWcXq(^>CmCNGE?79x%+gDwE#Hrqssc#p! zNC?lF*ayjs9T^xaSS#|MMV&VFMH4d!4 zZkWTpq3@C@OGifb46HH9{z*Bhfw}nU?`Q4rG1m4U%S{a&=el3_d8y+;CwYuB8T;or zN$trx{JQp{dV8x3e`oLgp(j^96X4u7;?#mB`Rfymnf=9wM4L0v2A(6%&aCSL&Vk=2?tqxS!I7NQ$U5k~Kaco?Ny8&SXXD5=o*M$yBR7$!A&`E3 z4(Hh&&rOXymD4qd9)n+^x3J#)&45|7o%p!*jMct|rRhDuYGV~B)5{rNC*XnXScOCQ z_XaLTFFK_|70As6Im3&0KD%Iu{ltwYd8b%m7DV@~#~#{;?w(0M{ruvojzH;_a@Ox9 z-?qOEO)_=in`~73{`;+2aCE>6DgB`}%_prs*A!ia?+muEZ@@k z5A8<})Hs15WG8!OoP%py`j>Rtd4gBo=0(>j5BS#^7O+vf-TPR1a@7*anaaLZOQZ)X zpI@~kj(=3PRAu+7C3V~zC$v&~Y9l6Ay`1MTKFm`*kDvEE3LPssTQ1Vlx5OUP)PjEd(9EL;te*j)(&zwK+P@Kc4Pdhq*&7@eN4a7Osp(l0*a_pK) zFY$@)^4fIh7whj1JC_nOFg8EC7@Z=2sA7i(h|~BL&)T1=veeh;N+wTG&SgK7Y@;G@ ziLd&weAwcH7l>=ju3z{&_nCR1KVLd0&dNj;Ptr{LlDF$Q0emfTZlx1Uu5t>7H0SJ= zUdgR}hVikkop#wrIkX8Hp$85R6q-F{$lASJ_f6ycSn>j&wPBi}QKZ%!vS%sfaeg81 zB)dLC`j@anzL;myrR)>hIh(kg5OXwQHs{uIh6(R$sH3u0JW*iJvjZPp%k#~QFBZ$b z39aje=VJU0guH!j?eN>?%zZa7qPy(=H^Y4>bN^a!TC@V5j!bEOWZRE%K+@%Sw+xcnSAIQsUFLQ6(%iP=cGWTk4H|=*!9+sY5U+r1}Xy7%&vUVslDH0VR${`8*B=yNap&73yP z+Vq2Q&Qyw)nPTmmj$ZZLj#c<~6a%WVwp`Je9h*Jxny3!VXH?Gu>RFGjQ9oouB}Vb$ z?N?L`Toe7Z<1-VBBe+#(K5!Md?e)unsRjAqUU^^#XEHzM!RoHxoc60aUz5=VzKIr#aptCI`K^YGi)V)uEm9Q)o! z90c-Jb+^4*zC<<$`3@1=U7w(Ag#3!7Xwta6!hzq z6A5l?DEu7VTAyM~*W=X$`y}vfO|^R|kOS(w=0htSv-kyMY9f!dXVNs@1+(Ngdb9Nm zcqyQc75F?6uvOG?GxXiV8lA;QcHg6{tGClGHX6POv#`9Kv#Mq+x3Rw~(H-h<6Xldg zxZKNmEI$6!<~cYgkB`IbHk6Ne$?1Xt+wwdZp5Walcy|<93nxB4#BXVI{FrYcbKcrH z``+H(sy&6QnMh7>b&>T0*f@D_&n7Xw(Ysh9=^)-+I${v~|AM-F+mX$e+mEoW*+5-o zVa^z1+-|zhBsssTUUla&|4#6Xt$Q*uI7$AnlMB)}q=lb2IIM#X+j##H_S(pZlRCb} zB&`mjtYEy7c%|3>xHdK0K2PiXAht18OFCy#mc5X6zr4fbkF!E%8@)9!4_D^2Z` zbFa8*>0ZUMX744)mT$sw;+w>i&<3#EIHITVCH)xuTYU>(Fh?&g1TNulDsw`{s!fx< zGawnf+oapSiLRu)`j5S4dEy;#Dw#iC{#`)NcWNA;0Cx4=m0UQ(IWW1KcL3Yyd1-Yz zkB+g2U2!-JKE5~EgYyV`fpx~>X6o3CJ*awGvdcN82d9(2hB~DW#m73Q?-9z|y$9G{ ztR*XMyYs6>^bx|r>pbt#5;c)8}5KM!cjNR zD)+Zsp}}F@|A2eF6E4QjL3QR7=WEsbysG>Szh%BKdVZ4UN9%>wCEsQbvf@*Lp^iTL zXLaeEu1r0}*oU3652>gAD(F~-kLoV$YOl{_o&S|Si|>)`dsb5q=U_$sdR_ttz*6j& zzm)PZXrX8E6$i`NzWp)%iPLA!Otkt>GF0z3d40#0Jb!;iHs7f)?r!>mKS_H+nxIJo zG*G{?aeF)UW#hJm=kxhV_U;&t+&}-__5S|2dK)IHH%nex-0#jIo}O<6Xm1ntVcgUG zhh;0xMIJCNsf4E`Dcym<2&!j20It7zd^=Q=kp=ts+D0Cx!Abol*V=mXU4PyV%0V1Yx>?;iJsd4 zZ`5RT=}vU$Yv|BEV&c>ASPXnf_v!a4<3{BYl#5>$vvKkX@Z^sP-;eCUbN)VLjnRlH zJ4j4eGJ1B|k$nMY==J*_*rD9C1){fhCW zafAJ+JsDjiJfA-=^3PH8;M3RzmXjT;udg1+GYczeSA5{k%ViJv&V=^HB;Y@6UwmI? zA@81-y}1%w)9TKYdpXBuQ=k(KANVO77`oom-HnftVEf{r%L z$xGhBntdYE9`!F&Jx)(Sax>R(Z9(!+;A@-4SuZxNzaaU?N@ENOMwN-shmO^`)d}_h zs6Y6}t1T|kh5jC|9Aa$5AJjDi+hv`929SRag*Tu6q4f_*#~%CRK;>%WxZ3_dc^(fu z99;nY=}?2bSUAniEXb(Vyk~1|JJn9$!z)(qq^W_hVNR=d=+#3~x%0r|k2oW&!fn9D_4@1NjGpIU`(Nul zYmcq=lB#~>)^_`@!h5GQz4PRh$FID9-q}6N?$r?OBAdLt@L=>9{S(itjFE3ed7X=s zvTJO;yT@SAn8N1SW7D(Fbdh}^{!*D;{`=;!a@k{{S3H;+o2OyN5i{oLIp+IboLuJl zD?G!)_WeEFi*G1z$H6~PPl7Sv&%f3&|I&ES{3vwg!5ze_J@-JS9nPIARXx&w@k~9w zuIWSmS7Iyp_UlW9hJ7sF+*z=?FD$qF)LhS|w6a0-O~1T5C3bW9T~qF?fR5$Y#9FD( zjw$!%_a{we91FkFFBfIC^IWDKjSto5qTg$##9A3gC$C}+s*ts)$*e(jY`krF66;V0 zDkeP=?T=N@eYv~(CTC`GH#UDwIMy2G8i@hJ#*6Mmr#04?+SW~^)e(Of>G#$EQ`GU? z6_XyRd)ZX$%sc;`cv^F_x|ya}c?F~Y&M&iyGGAb9V|{fzm6O}BN%t|fgxAvkOOvOOnJ+@mr`VUBKzI5!#DS&x$vCn| zbCzA;vxjH+y7O=5NWPl%dh!yJGkq7b_B+%$-ZnP;sSUR^H)-Wih7KOxyfJZ{u`S-$ zesKA#6X0Sqzk$CDRQ@C5Sv+g|lVv|h9(|OxJGWz5*9!8g?sBL6&gIVLS)4&QPqbLi z7~ zmuarGJn8kv(J$y_#%I^TS-&M` zmu-U&PlaOmWHxQv5pqhtm(Tfjw_rEz3zQ7aVT=WswEWlqcO!P? zUF;9jd*xG}_h;qlBv0uiv*%AImuwM?uQLX|F}Z9DK8wS@4NmUta3+u1M}lhr`v}_Y z;oPX?D_=9i_`R*KQe_9wy_@M*K0c@w$Un&$ba7g~v6b}mpkva?r}xUYoIEGMQ}5LW zb`eDEtdgwlgkuj?r9buR7I7(dkMjv-Zh7`_a>CGs^vq;8C>HxV+H0UH!rpV_No{ ze98Wqa*}I($XjclWMrGxzGTnHev!L(T_IQdWIg#SeM&peyTIj! zO^VnD3!7w*#kHlJVy}Tv+*^<#*2RkLquFdRh7*%CtQlOxx%0FH0x& z{C)fUMANG`q`#r(S10NH6HTw*klw84*T>EpnW%pW@|xOWg*(|3+4X#Ef_k$1^98N(vj6Bbb!6r;54xGNn>8jK>SK?QXHVPn zF#YwhbI!%++K7KnH2i|%!-20Iy|lwin?Nsd&N%+f(eDe+8S~M< zDP;S9hi`mc{weO^gRSp2PUG?mzcW(x`|q%3%lLM=$|v4?cBIPto<~XN zq4{zTFiWnT4sPG^WngP(4)6PzuGOCWT(j_a@M6vbn{L1R))$-=jiKWOSCx3f_M!Bg zK1A^GO)C>@(>m3U@6ZqR`7Zi_|6=Rql=FOi)4)|(=N}1v;<}y*Oxv;;IK^+J&E-iB zEbaPcz1>^Vxtn^-baQAUd1K5aJs8V6OMubf``A9sBzNLl*v)wksD^=eLR)3KBKZX%{_jej05-zLJ&?^}SZ`b@jd|9f&5xVCwF z#^$|!@278ihiy6jU4-^+8nF0hGkz94sm|Y7-vn*pL)%)SK7rq6>>So+p6nC-@gv(l zXTkLvaP7n{=^j^)-)H&bM8grm1Fb~Iw{@T4Ar>|)zq5{@HDX)OMD3`K-(=M>lvT%o zt%Eg_Wr`_3G#XQm%&8Be!+pQ`8_W%TT_d@XK!*MdT_gJmpJqDY`Je3lbEG%i{Ks9$ z={@VP313-Slq_QI96$TfBZ-Z18`D`?QDo=Q4|smfL)g`aO7Qtd{`CICnt$#GCszPl z0^W4tSHbfk`WgQS`{jz<0?DN4R5SIK566yZ?0*@V0v`9y$SMQ=>gQ6XfOr>Z(si3t zvgOy9yQf%Uv*OOY5L>zFM$qlk;!q+XJGyGocyaY`Dyd;t@utv z6J*FKzAM4Gd3+;_vxqr|aEGpn_li@u&WQ+5qCVOqMs?%AAb-wXS1IkRpdR!~bT4}e zw620e*b9t||FN;iIl|i?<7dz#is5JhzI}nv5HX02*?n4+fpOQHZAU(I0T@%9Nk1M& zgHQKXV0@W5zSe4_(|ox847lVE0;avby!s{m5Iu?Au=clXj`P<8J$nfH?%e?Fz7F|- z?T5}28Jm;CQ^g%6rfc7Heiti-yuJQqXqLk~k61q9>P_cv#^x^O6Musp1zn?i$k&0N z^C`aHG9bOluZ4KesN$w&|KYc)gqI88ZN*SWD+(T24o^pBmKWFIUqVMlr(I&UgVd@U zfvJ?Sp?)d-7hJ_>=fq3c^X$AnF~^S%(w5(jVmQ?<>lM{%Q|+nUO#DQ&lD4D$tVI?N zFS@JL%;2o?wH3_WoUF>jTB}TLNYIHB)1)9|Rwt3W5CTX&n>imcFwD+*4$X| zw&hQ`GtBuSz3~1((KU--;9Tx}(?RSG>ofdjUSwu;!zK2 z^NhW(KyUTtLkHI4%R}DT@;Wm)B-vlansxy(hSY^3ty;}hebySb&egh?GY`a%P0!Wd zb2_+fmTZMx^i#Mf=lr!k?#nrU%|UN5S6_@LqN;3z%K&x!(pq zYmMv-c-sAJ)t1$P(v|8bhZ$IVs-1IKOA+hXzUvA{*NUEtp^r#>H=7qHXjqk!S8CCYHFlK=fz$qr;*J{V?D~{Rnft7u+#ux)yWQcn;B* zJ!ZzDo$yx^{dD0K_0NU3te+7++MGY5IG$&^YMd#pjN!(bjb)avYn&X5qZ-GxXQFT( zR_kuw%V)qiE#1tum}?7H#Rb{V`so!Yi(ud{wDi} zx|z4wu}~3fZ3hNhrkVZxlqq#$i;zK2xKmef=6WO=b*AO7HA@z&O~utUI@c_UPm6V} zRo|Vw`7N}I?&zv>rpy=Kqnxd@cCuh;TEu=Z^30geUND~Hwp_@WWXo*l+uo`t;JfPXglVUDuVlR+iXPY0P3 z%;8%c$RQK@^gTV`ITM!?{Q&ba$s~iFGd9LcqD8bP*%CtrV6)&K8`EdUF8UGQ1$Fo? z=-BziC!nX@YsH?m*__w4*!rD%Iyi$a%fCH--+*^stmd2}ZNZfE$w*sHN-}R`F7p}c z99iS=?V$jEfnbz4zGym_%Xc30qCxyYiX*E0(aw4|bLPL~*uZ1n9v;O6WygfiCZBBR zEpBa{{4h66f>ncRn zMslUI3)eZwv(t`Qw_1wUW<)VZo1S?KQ^deuV0^Z?dCwc&VOLW$gPD56i9?OS^Qw zbix_lw+HlHi|L(>*uH{;_1z~Dnf^Z$F!P0j;Weh($Ae^(-fNHE5@30NGAk{f*4g<~ zC42B{Si4-{xQkTxv+y2cI=UA=*Yh6a5A(O^=V<=~e5f?$qScl!?{_R;9$zN^QAxC) zXP-Ym$rwwJS9Rf&V$8Tv&f%TzvS;-LU`{c&D*%psXcgJGZdmXQF6*vd2|OLVYXPS5 zuxgLtX7&k2Y8zHWbuJ4sw*bD3JNYXTXH0c@Ftm0PyuRL&UeF8FAXt?gVq zKMp>6u^&U$R>aQ2j@y=-;l~WUL{IUv&!ghco_kEOc-!Yw@u<(AlDp!~@w~%^2}`ec zg$es#FbT(ZLtkvC=@;sU=o&8b=QzC=T>qF@4taKz{I+#`>+}HhSOSkshaNLEN4WP( zc8(x_TjiXBM?S9Ll+%w?FjDI@@+z5y7Rvo2yBVa2l)xlASbnU zy_)YErYKv}LOdepZgmi&RI?C!2A*f0SbYZH%eCTpXPVuY;^O!9+gZ*SsY4cs|B+FL z%h(I2GKy7IIg967Z|usJ)cT5asHZz~m*)jO$1pK#( z{xxy0u_-%7`IR?1Xt0xs0VR)MYYH^J*$n)3@?E^>4ID20H)6sT-=K*ug;yTv4g-7AH4p}T%RHg}ATl)M$>s|j|dTac7^e)Vz zH+Bc`OAcL--gzFqeOim|_c5nRalVG=-N#;%4t(QT^xi1CT~EKp=snhs=$**WTXfIR zdt){EFGTO9QT8AEi0jo1tH10L`ReZzxz>Jmp z_UX&WfS0g?^ldI=LVXzf^(D?k=mYNYdf~6pug@dr1xL9lS!eDpZ#W1pJCLU>=(?!m z<}(iJ`If>g;uoVW=(%@WM?1$agg^SNa`}b*d9#T=#T;I?`WfcS`1S4DM+z92Uvxdm zH3Clyr&aXvDZXRY3%%W&Z(zT#yKXl6F%Az%Pxv}R`a<;g z*yK^*F8yLA|5vl>sOFw|koD`mRnGUl@VAe}Tx9l(G)%O<>8;sgt4I66<5BQ+3unpq z)2Bbkv~z1#I|P!Kez9TGs- zD?b-!*JbLzk*jcqGqd!T%S_eW%iP5ktZ&t!lbO359(gQ~`V8Z)jc;#vqqo`$ynPyF z*wqU%b$lpOhv@oxfPE*_^%}U8|5d^J{bd%oC{b_uzS8z>a_+-ago76gw>_^4J%BBnhv+dV1e4Ws(2l>=O-pHo0yw;|{?!FKD z_}}2t{MXi*<%iz|UHOK6`VYYW;A2ZGt8(1}&6#DZ+d8q4{Pt~~>+PB^br`~c;FW>$fM1Ph#p#t?sd}{HEpZI~$@S@G|v)~Pbo8ye9@4QocHs&dU@Ht_PY>}M2^0=7wi}~-`*#&~f^_gIY{FXVBzA%C zVipczb2hsAHZVGR6Zb2idjcMmEmg-g#P=!IvUU+C{}4I`U)<3B_<SOFRZISid^9 zR2{Zd+?j6mWEFZ+XEA6VC3v4=uJTi4@OYeZj*W$99k})7;(yKHxdWcic(U?~y2|%B ztYssf~q6sppQ{zrDO1^K#k;;~`ch1UP*1AUPpUge)kyU?pK^xE0mgkNhL;fmqk8nePy1 z`;r8QA5X>k2=a+reNvX`*QHtYz+0szXl3Jr(kF^(zYm%VzFw^+>p63}w6n8T>%W$+brs8WzRcpCtc8n5>zt+fF2bTPd6!dOax%vK zN4du@J=6yuir!0kj%)m9=93z0hVwgYTGsfLZ$bIr1kVY^*F^K<<(jL*$4}Y$bV>BF zOy4vf=p%l<^YWsTc-;He&eqY1aY^E$m-Yn`S9owRweVgl2z%2Z$ zKG_>@0iW>jHrMfXkk6;md2z;u>>s|%)X+=c)&t|uX@3UrUd{bO^qF53^Ol>nch+SM zLuW-R(E z?8-gZms;1pjXc8P&Zk+24V2G+qc|~3_xh#|IB4AYKRh{iC1t88qx{&Jor3Ky;L%z@ zGjW@Io1!zZH0XVI;RN`+`OFjT*h{s zdh3v@vdO+dn_FmG=h!0i(jD@#G<)am^}+M|0^owYw_)4w1$M#rYu17ilq+|N?0E#x zXuI(EPso$oz?0f0e{w^nKQ4VyJu0vEZ^0(kUflf93$s@4F1z?Yt6!`E&5I#l_`dSG z0N0~|{B^STbzkkM4KB>^xG59)AJ3yX)2K6o+tXfzF|nyxi^ibQEvr zKpV+T=5KrTu9SB!GNB3HlWx6~^D+$gszdn`d~-}?3}w2BBa}|N2b?BIbDj~4a zj}!|(c22_B9K_R29mu{A^25%Pe@u)s@znm=3k_#S_D)pSAN8?T%HM?RsPHcEoGj=m zPZCp8f8$qTM-r#LawOEU?wN8ETBk8hyv)>9drhmpFYexmyu03$8@s@jY!&xp;AVZ3 zJ)h?TjNMprv;CIXX6lJ^rcAgc{*2^rc6_RI*)`yWF|t>Ea{FEOrc>90cKsz<;@Efw zdq&Xvvhy9v~avd1|kZG1kLx4e8RuZ$kgs8J+z7tp41^z4Wc{E7}dw??L)~0>96V==L^j zp?=^^vJ0Fz+*CNR`xWZcc%$GDfQ9kb6onm`ZcD4y<>&L*BEdio{S55f0Z^sL(xwfJP6 zeQh)Rj4Y|r+9LA?&g@xxcho7%7w?Jx*FqcNO3z`g?}qO) zf7yJ03^->a19~M(PFO?k3nXXan~-eM{CXH#YTwcxN#y_R{wn6JQ#YAF+)Xmxcm?J_6GV`?K!(YlsuLx6URShh!wTz z{bT8?NsqyQwjSV8J&fJ@@okBw@`oIO{{|+PZVBOcWq)w5U@qX@3DVeK(A#h})O#Sa zw;(}Z;v-tK^v+|KKm=988|Ki4!=&t7K<(|&_#QOw3kTvv5B_2(5S#Ecy4Z{ocK;M;6grs z%ZE13-?Qn3!@!d@qUG~WPmR89-nonz%XZcgZu5Apa{(~(-tK|+_wy*OU>EIc4}tKx zi@nE|7c=`R%EQ4IuE?B6l+E|Hy^3qS_G+(9sx4ry7e9*+P7BZD+Va~7lka!)yVozx zWsm_{^Lak7>00(h+BI~oKf_DcCSON3EDNKPs8ip|=6pQG8?Yx~Qs>pcLZE0T!DU&n z%(Q1Z4SXn;{#Rnxi2>+*nf3pd@CzKrw!s#|o+v|amohhl*1?(=C1*93^*n@4Vf(c^ z&#rxEm-WkuKQ!-BAOB7C>(AiR`LIVn`qf0cZ{u50ztN9b{W$jwCfPd{F2{pQFl5tl zLVl_Jut&e<4-2mrkL~KG=gZN#FEqkX-tQxN1vX{c z+dbCaF53IMe@lB6@7CVA_NQ&L-)l?jTzYn#k0iw}-L(4`w5wQ_h3E8h^vo~pwi0`u zm*z9JueDy=ek_jP-|>25Y@e^k!-`Y0u+)C!T>fqLV2PoZ@6W(;%LK4sN1_ise%uA_ zN8#!B^o;**6rS_WXPC&(J;C_u9|xaPGdjN7fpPr!`UEilXOAy*;dYDb9uL?5vGFwl zKh)M(8Yq6y@14^K zyrlHvLUi;7^nVlQc61|at$xSu>R=wEaoToY`LKU(hw7dP&M`jq){5lE+{apx!S4Sp zXQ`~`c`to=n%`6S`g#L81J+$H-{Qlc`p>e#fbZA9 zC*PTTli9J}V{*=4|2oG{n*Llr=j~Hx96hXgS0ypJ_#eIR?E-g){PVe{SaGDyz+00$ z>&{xPp};2>DQ=!J)q`5oqr9~@{jz*d2xF*9>G)uE)|~A#v}sg(b@IzH?^@0rN9+5F z>4z7JLp--r<_6#z?`IvOj~{oJ=?m*pVPXfr4h}k?O$mDo#d8s-z3YpU-7QbC2H3`$ z@-FBkcsig>Cs*Lx6Y}AuuXXo;PkzysV}7#fE|HrmvfCV@vHkBOb=Rzu#5pL(!9hOw(s*~Gr{LVumP|9HOggb9bXUY= zv|h>c&#=c_0uJyM^#2mwCGV<{?<oM}LHel;p&I z)jnV-u4ULhC&9lInsxFoha@-F+wo-DYinJL{UoraSw0?DGk3`kmZ|w<{6l#b`iQ3F zK+UFKY`}h*;a?b^6S6n#!cSfNDtrH?T$uJu%@O%Lss5b&QN$nBwNJ$6PzMhc|ICx_ z&_iq(eon#q*1RSv;Efi-(ed`#Su$AI5Ib228R0 zLcIrpX-0nXR$%M%V;@^Q$~ZxvD?&%5gTP1os2!(pKi5;xhU^^BL`9`(`=JN8Y7dad zwSYa6))C1^&GZM|>WK}M^~9g6oM>(G)9zl!bP(}v-a zYme|u_xDlWgWscIQeVCBuqxKEf;IQ_=1#=t8(!Zu79AA*>|$RgTD_1gok*{pz{L5q zn;F}3!S@39b)mnH-l#?b34yPFNt#?kv|BgOzpeeC{7x7i>A8U3)3G6Tjy79Z+jiv{ zM&DHGkpCPwYyUZZ{#uL9mq#4^jP1v)ec36mvFl}iVf=N%;Q0yeYw@QlgFY0qtNAN^ zWjAYsAD@^4%lA9ET6!CB{GxlwCGsiOeoOLp^!7={X040hswVI8I#hr70RA(2HgsAm zfHllK3sHX_@Jg2x&2k8c-f{y5)sLwz?NuxgHD)bPO zALBdUId{!Lc&y<5VQ%1k!K<;i_txmhJNmbLCjn0Z@D)22w@aXZNsJHBnx2TSmB6qH zSuTvv2e$QH%rk5|Myu9G<$sjV$(z`d(5Bk{C&s8#Iz;)4lH1qmk8r3l z4r#6?*lm3=^jYusU$7rn(T^{xA8}o0HunMUU!X37Kbz0k@~M;8-^rJkrZ`FDE6Jw* zPjcRg)>6rh2{J+@GSronJ6~R8?YMw{zz5`42~lqb^;Rx`u8{?QOCD3*H$#V>U(M^o zKHmdx(Y$<2c}Mhr9b@DfPfP;y;Nz69T|lfj?Wg{Q_J{ZDHQEm&C#YZ2o8@y2@cU=v zWc8AN-XXtC*K_3I4O~+S zh+|lf+zD(w0clQnp>b6 z@H@-e+hD``2zda!4dEy7ZpB_awr%5FD|RQ3Id~0gxL`wfybC$)@%_jT$bP6C(9u#3 zzV*=cl&Qp5)?7obVBT%x3=Vyx_b;(WpiKL9l!1@6cd(}GEDf!*vw60Uc@eLt{aXGP zFV{H%x_$zD>6>Ty#)389j)#%FB-w1$?Gbd<=0!<;oT9KXQ-SY5nd;w>LAW?HL6 zld>rU*mJ2*Dx*G)1D0*b>Q0}k?Q=ziZxcFK@(dI^1%zParJ<22G3X?z@eqDMBX{M^VL)Z5HB85>*{{VjnHWQ1ed34eyf+ff;?L$*eaQ0$Q$ez2W`db*NF8UoY(i4>iaG6_9NCeqJOY01IsQU zn7hj4S7eY&*C^hL%qrPQIgwrT;BWN4d$fPowx-+z|AkzBm66tuEE%I8<zl#aB3_o|EYFd~X`Sjqf^7Oec3S{H~5v*dvS{B8=|b{*aq@RQ~YA(!el zJKK>JYw)wGQ2k!h+&G>0p=k#iy?<*gn!eviTgH_(neVi$~{oD9J-3=^Z`9MvS4^*l}Z}*?} z6^ZU^$!jN?Y@)rk<3?J5Hp9qfUhq?8+HpG}&hGK>EW~+4g8c=`NLOUiAC1FLUhLnp zV(!d_82hE4fotihg4L52Ri{7F=w&=qk8poC`*+a*G0=xRZqK0-{AB#w!;QLz_^$c! za4vd~;>Fv?o!H7ZJ@||f7gyn3Th|^;J=iFpuH+W)Ru8aw!P5rH)S_$F{8=0^PpIsM zF?QL+a%vy{g^0>t?_Kb|%FQQNqv{-~Trgh0zN-Zu@r?_~?6ytp!ZytT{~L6OjvRZ+ zJ<1~IYSXjlWzwyOD z>+7tq$9TVv_dfhyddQ2Su{r)~Q)9C$8GnqFLqRj8VK3{EK|Y%8t__Vl@h@`bQ8Kjr z=JbF)_oxS3A@Rc5evPZ`-;-hGx0d`mJnr1!Z-`%_mAAv$M-z_$9H9eEx!!5aE&Aho zrm#oriTo7dAO6$sQ5FvgGY+3(jdJ*f$$bERVfkWJ&m%|MTynLQa{iPp=X7EJl#KbK zKlE>z4Sh3zTGe;ugz=l1=*5^<)ER`{b;eK#p5f$5)48@TaNWi80N010S$*Hbn*U4D zEcJ+vl=q^6`K7v2sVg*!x{y^v&_Y3cZu_Z!*(F9%n=8=n-9MwjH`;i72Dskn$^hpR z8ko0_O?liMG2P)t&5xT;lUtA+HRQ30+zU+2$iU(u&DP$5c*6bY1#J66YbtpIzrvYd zZ@W{=?z;&78!>CDfy2Z3Kh0|kwtCN1c7&3N;aWQ?x1d=uU=DL)(KDGR0VLywl45=u9UOYnsk@ADY=K>|}f_jj@u zo1CBZDex8B8Q-_Er%&9sYJO~jmyG1QHTG3IAA#>1Jqy2l*IjoF%m>RK&7m3FFQyB+ zkX`XK^uGmKna(&z$*V8{K65Yni6FQk)~?!A{}RU@-ha^&kbK2o_nu=+x`UfL1PT?tM?7l5r2J+WPXM)XzcUWZQA;n&xxt&bQ>&A-99=lGis*K6B* z{TTDwfPcwfhk0$~wiEyAW}Y5HRwyCwoA{VwuYYIF|Iz-#I+sj*Z0R5$LucaG9F)F7 z^LYmI`3Ss=WKIj)@GINzvggurVx%e=nc7U|%wnx8!}P({xkol#OBQ~czH2>}o~8#po_1fP zGk|tK0zY^3j1}BV&j?@7tiY#|GeveK@!OkZ)@%c&=1g;;YzUHZgZwWV`?Pz)oS&j6 z3diMP`H_X`_Y&R(TQ%p35I5d~QX@aq`fV(f3N?fx_o%J52EM zI~*t;t<3824rZE3s00 zCzv(TEyj=w-gJ-gpFs|np7EG+8^?JZ^Bo;&YV;j!W5n8I?%izG>?5{q@ApkBkI%rj z?h(EnZGZbVb4hyHZSalQdYexuKjcx`vGg0X*~UDNO@&7wlUTA2J>KgfgU zyUeVVF#Mq&{!mSf3N&u*6Edj(4f+9{mrG}5&t+R5znJ!g;{jMdqMr|9ueW8qp*DGE zzIQ?oSqb#;BJ&IyOBbCQ6KwmaGv^Kd3eY=>UloowTIaLQH(soK0O*sDFA8;K?)zC& zm`m0f&CQlx#j=GzR`~cla#9C=QDP?dIOk{#-5=VqJ0<_wzXkcFhxuXA({=IxHAf_m zpr_wbgg+vosnG^2HyV{iR_T{%7^%eKP{WNR(^Jo-V~*6L5x4~MOJEgSK= z_S^f|zq3~c&+X;lUhf2x2YX6rxe)sv5qtBh@FK$@V(vV zM7>tRzF+$&&3{j#eR!JJvJVT7`Rs26bIRv0U>~Mk*@zSIsy%?t+dk(uB84yLJluht zu&hb=VNd0pT<}L9hyhQkX#>A8|XfG1-t1~jdScxv zo=3kQ|$d4<5w)(KtIo<`(%ICDn0~XTJt6BAg}Z6DDdR-O!DuSm3UU_AMoN2ZQx#u)Ft|b?qoTs>BPxSPsq1Q5__+OD9 z^i3yqi*MWU4f4nKMA=tu)*9FaKhpn-n{4A5GKzmCIicG)+bl$U$;q4NwzRMpE8uL0 zOn7Ml=TG%8U%i|`RcmJTyuE%y<3!*Y!|!M4$CrI0(0idhBR&QV-=>a<{F-!b1Ubs4 z@Ld;q5hVA2{}|^J0uTOV*7($^M)pf{2JM-N+hho@jj?u?_+E?zLUEnrAAGJrgw|ZvpX6*HiKl%?JM;@5f(ys( zjwCy7?r`+v!}kfc-dQ+mv-T?4=nx0b{vO)@Z0o$gn0qF1)%X>%emOGpNOE_Kv;8K3 zuTFG^@UHgny=VKro}z!YEHsgQ*#t|6_;>0T=Wdzq%tOR6AF+3U@dl&|8wSN2%s>#7|_i(=YXdk$qnZ(ifwhnmP6 z%l{P*lOtC93>Wn%uXunuH9kKQEX?(tTsOg&^lY2;EW`h6&CM~H4V6>KmpvxCLGQ?) z*!O+4%YJnh_O+1qt@*UgdM2L`*+51bldC(lXL;IMZ%)V0VaF+=PixP{Lt1-M4okl0 zjCAe0qfbmUZjoH%fi^wAG8Uo(TvWoIj4`UHx~#47ATfOQ+(XU;Cq9-T%?B^#OSWk!G1O+E7heOen>TWXv!=*$Q=2Br5mM_c~%N7uV7o4o8yz2IB= zBIz)OdXgSOi)3$ze3cW4eYW%Zeygwn(J*K#)f45P1qr&)Xq-HLS1=k@vp}(WjBI)%VVf?=^~Ue64XEQWCjt z*pKOd?O!~eeZ?_wtv(-xcgkjWn(x)$8LZ*4olZ`|tmuD1TNeKEZTxkCKh1IBZ`;}a zSKg#6g-o6z;z zd{6UBGL7_F@FgqXHGP|zD9aQ9Us$pX>$!Yr!P}5>=S~djNCW6ct#8SDJ)Q63d9RD* zhw8`xBg-n;{v2|fC{IBl^#cR+IhYgh0Bs!OXW-+KrFwxw{IKnV{t7#9wa4$&KUBuZ z_M6I?63<_ajPasmjN>E77-x`KojrG=9Q*n+9c_L&yWDu@HyktaF9wEQJS zufyTqY{6W|*<4mUOZ&-1E{j*3T;y)i843MU&EkogC;tmR(FYCupZEmxwG-IyXI^(g zKlCv&lfEX($%FpTw%$Ry2I7CBPeMa^jKy5?LqQt@zB8pu&||VE%rYlOw(&d<`GtMm zt|{Q@zo@$dU4#c*@PE5xzyQy_0*>^YJ#lLR_lfo0@TH{4qpT+l)bkegY&4T1;c5Gu zL(}S;o7iXKgMmI6df<8O+WO{NXktIlZlNC4m#O+JJu1EqCVZ5=8#2s!XWuww@+cFw zk1u z<=Zya%7f>7X>83ttu@+D@1Gp;{cbEgE8OT+-()kcpNt<>{JwNDsh;BZ;8`|dd!Id^ zul8%7B)+^3ommUtmpn4MRe7lP(?$V!FW~?AnhW)#t$i^$`>p(?L*6a1`J4Ef_@LGt z{E4q&JO}EKyqCcq?Lzum@hItQ2kg%Y@pIxmo9>i+lo1tuh#vm+Amau8Q}7)MK}$_@ zjozkov#*f%O$UtLWc1oi-jhmjGg_mNLAC_c13&ga3YaKTwL zGd;lCy%X8pKG(q73-5&PQs95+vx<9m8pY&rjf7ca-lCj;RG?UVUVG*p;ICnRfn~E) z9`!1|E4VUH6#KA$)|Y5sy13VOj)}PG$5Fn`=YPprDddv7FET5QO33mU$PTsNP#3TP`xThgJ1MiC!Rxq^gpc9}`nR+;WJ zmAi`X)b?1~4!OoOjQvuQ?5b(nAF2JH;b+J=M?PqS$HD6zU4X&gAfL1MkfQga<6JGX z(Xm)QweUT3mYYS-)8Lnii`Kr*!@S3jx)qtadI{qS{*~V()A(dv`)kN?@>4j8EPWdO zrEgrHgwFY<5t@@7bFa(5E}rRsD85fbZ+J~TeJpr)aNo+lDP419FVCF4Pa-e52|Zbe zeV*!17GD~H$AMqv5bra1zrosP5AwGb>eak&1{RgkzBmhixNhz>7v&4$Z<*IBJ=lKM zTj@ka`#MLhneSTo=^VA;eqlApPdB~aFCS0a2a&qw_nCe2$#nE9iE;?>VbKlId96;H ztnbUVfz$8;_$|DD)29M`$``ba_I`*Tf&OoX{}OM|vkhMQ1UM$Ap~c@r9}fB>#=wtN zCp<-EE2&fXtft>j@cpJwp@-u;_(@vThl6n>YUeT9>7Z?u7Y|AFy(+{>FE$a|5g?8|D85)~^Tj&O zq7h%L^Pnq;msz5DdJ+0Xcz10s*N+)%Sbth;;o-`CFMKuu%hwoBt1gGf00 zFDd+*7c47+FDz7E-R1>;trKb0tP$eD1@PcP@F7}gUQkt3g8#I~yo7RvMN8q+mGIv* z;8vMR`sVBhb%p@(Ksmyx=aEmhdeGAuj493;nfF?K$QkH^n?6wP#nEOy_S?Glf26Kw zx&8;^-+b*wTYFMH<8le>dW2N8j(Z18|$uXe<2-M z{A0HYPvYM#YeK6xOfyysPZ9d5@k<2{^syY;iv0LD=xWHjH@N?>eIlB_`F(3G4FhlZ z8{bFv^OX6f*=M$QS0IN>Ys(F>Z}&B`4`U8X21o;Eo{mQAyKQ_|@bXsczKZ+MEB3wm z=83Pc$SKHD0ta9IoTQ6$GxZ%Z5uf zCkLL+1bF5rz{8$p0G@ro;J_nZlfQa`72~76Nna4l_?CQ%YW|q<&BiMBTAzl$^dqaj zi9XGOyK4~c0e=L`KgZs)S!GPmz&Tx7V{XKMtC>Ao4{Hjzp4pA9%7ZUfi24hz+_zeG z<^q#EDCDp8GoIC>k{i&=uW5tcLuS??FTPK6c&8jX&OXZ7r(v72^tBr6pTldi*-MeQ z0G^l~ox)z--a~SBAN*JLFz0*u{M$Ks2EYFS--DBxT4OYKHW$Kqhc#_dgYctU+(CA#Sr|vu^pUO#yTQ7STOy>Ub~|!w-|k!iM#k7 zW&V>fXl`Wv1Sji{puTFTTX`|-SiGlk>x6SCQPchedMA`tMMTacxGE%&l}R*i2EnZG_w!YQ9rVF`*iTBIkn2xnQLE~DSd1`??sC# zoU2iZuG`XI<4>jewAgLbEXKE|%e@hws;p=_cr}o@o}{jz?MGqdu++QH0Gs4z-7ip| znOE8yJW5%IHXWI7F7N3Zd#DS?;yHRfbYI$2w+olQd%@9n6W4C}4cNRxdmQAM-6~_r zGYNSMLZShlA7?&>H3z>F=w%&@v{^X^p-Jvvr|-gX1#v%Blqa@m*Tb@9nDY7X4)OW8 zk-gY9#$Pynh41z)o6)OwQ|Z&bWh;8~`1Vff*iM-zd*~;0SOv|sU?WjEx83)sasZ9g z$0qvN#&?GPD5J}u9B=oRe!QDmKUpz_<=^8zdsJOJxs^MNh1pxBD>P5lm)F31@-$!D z=Uega$SO5n*3g!AZ|hFhmORQSejJ!|*3f2MhvQD|cxXrZt7O{9BPMhKYta1tu1JBE zlg9`95qyc~EZHzV%(or1-2n^^yg|Or%6CU{s0-h)g)PLxR+i^%6(4M)EbuKn2z)c( z>w-`4jKmi&2v^roxE$Zlm^(eHGpfAAjQG>gYY=nSLvC^D6G|Bm_6Opd<;14e1mF>N z+lhWE=bwje5>IM)kT0PD(ccQ_PjfO4oO%N5+E=-;FnXe>VOfs8Joid;u4-b zU>p{Ya>i*iM>6qa z*^F5mW2L!mFjl*#nB{&wFYUi`GH=K6tb`tSs>)PN!{=LLmFQx7ug1Z9n;z3SW z%zYmB+P@BmS-hl^pZvyzDImMQ>Rm3_Po?c+kGo~fqB;$#^E8# z@4IhC?>@$6Gj*$u8lH*w$j%(&TYSOOy30pvjzknYr*lR`?-q@XkXJU3vop%TNmare z7@+@ze1F<&E57n%QtuqAu6Q2wJCW;^2VHxp+0>s!-r5{;dbhF0On|1kr%c%D&kFPr zbNx6v-ipX;*nEgJHIXA{FqdkHwcZAevhS$Tex!1Qm}~m~m}iMCXGrI7%`fT~jjR5d zS%#Hc^ZEq*&*2`Mf+as#^KQToc<}u4zX~r2b8skL?D5wa97o2+Hl5CdX%!FKON^Mt zvzGJ7@V%_aWE>y<{fge%7_$Cuq)ZSzYRu*@9NoI=uG~e?q<=GIn!#x@ zxb*Vvbk6b7ejwC^otx_^+EclaXiGHzDs%M|b8;8<-zHa%mG2^al$c=jM9OWcb=blw zW3KpW;ZyIC0cH=pquAhWSI&NQb*DzWi| z`2k-~fO*_c-IeJ)@z_6eTxbDp*9*<7CSbDq7RXXviN{G4Z!V-y!G zU6=Fh8J-D`L*p8e8RE7(3tz~~;Oj99UoO7q=Y0Q!>b!_&{G4Y$*Ry1v@pGQF=-E{~ zc@{c|6A8+pzo_(t$NmtipbB!#AaFY5Y*(!N`Dy`!}6X08@~67st^a@B3vkmOI~39<)d?VK#z9Xe=(JyD__ z`c7LmFPF|?KEBrI7XJzOJ8+T%LmhKec+5|WbZHzb1qdx`{FLfjPsP_*QOXc{|D|Qe2Pc;Pr5JizlSgW zO62k&_Q_1_Jos(a6e1sp|K^kD$I%hk{^-i{pXpyuTqt{P|2=#sdE`3!@-n=<8GjRR zDSJ3}?8w)DG49;;9reEk&J|Z5g3co=z(e?v zN34C)DC9uVKKqzm%};MF523eSf$mKD1JT?`>fJ$GCT&aRx}5&ne!3axBjh)q6V12Y zW%_Rc)=F?2M3?HRx8(rzvG^2E!UsU{eG@HRBy{ap{p!z2+6}oD?`ffJ{GY3r0CVMB zCG=HaPYh9_&Hh=7XG$JS z4#aaCA;Tv6nI?ZN(DxkekCdYzdG$xUTlo?1>Ms0Fyd|}3TqL>E)(r;D#l7Sp?=cv& z8=&3ifn`J7?zths?isAV!_ouXP`|kMLS+`zOAlo%tVSnkJQ(P^5&T|Yy^eA&XkS&F z*LheQL_?j(KcVHa0U(c)n+Q6XRe7J4KV+8&+cdDxTF#hM^6g#7HI?@aeODcS_o&`c z&zIx>e~D{oot?W&^+KPsLf>Sr_PGz=p?4cKZ(WDKsQZ7k?{Cq!d~=ho4+Z+JWuGYA z<$$|;c91s?zV$M+6LtxIc1&X(ym}w_b71{6-|pktC%J~#-O<~|yE<|m)y2yM>CY#4 z_sSH`WLanBJX-iYa3>ls;<@ZO$zK~4iQ9?zc7vLCTj~@w+&e8C} z!8x(;Bj&`=cSGmI(04=U#L#y`=fseA^z*Ns6AS-}IWeTn@Hz1dWZ2&sf8oUiyUo@3hVXiBZ0!@l<>fQUidjh(0_P&mcu~KJ3 zYuty(WoER4IVOIcX-M~((IcLxZ>6ixFcdeD5$#~?R}xzyIbZt> z5`Bu^U&MR)1tJr+C(0DV^*8FL?1J+DyAj%pS-I_BCbxZd&jDcg?-=dG_r_2QNIMF-BH0PIMCcqdsZe^xVhuJnFT_@qGP{(?|Ks2H1z_EXSLv{~mb3 z8Tu0YL}}lj*mFsru#a4r^82UWnOgHCN9_lvx>mvurAO&xj*~Cza0uSv0cWeINAj0l zkFA#gSLMoUN*#wo@Du4o>ZwQ1g)hN752G5ITzgDx4@$*d})>hY#+vj8YDr_Bw?-u)i;Az)BTX^#9 zzdT~(6LX&U{}Sa}vfmqKf#oNpvIb>Ee~vtA+3M#F=5Pto&nkYh<73BUEwOca1MQeb zi(#5As>2?ap?=i%`FFPe5#z-6wXS^<_08b-#5~TbAqMXX=tDHxgg%D#prR=qzf4_o z=`+_$fxGD{^on}+3H#jA@J+@-=^C4Ddx`%^U^~nB=Tr6s`bg>NXTk5lOS=4wE_Ci( z3v(bSJ~V$GdQDG*^zGOuh_}tG-p1T7ER|fEZ0YHw13!oy{u_9qqmN(5y<+y}fNx6= zL!Z!5wy%KJD(Pb#<9>!Vz}I6FP4r{3Eg%D?KvU1TJkQ<4*b^^$qLTUj3VU4jGe$o> zQ|ik-(_YFAqaWGBK5Y+rioN(v3t#)e)o1DBBx16jMxRl}eK-vrAhB82d%jnnyq}q8 z`9UP7c^fQ!+roK$LGGjIXxK0G?4y6^$odx0N1fdxxMKK=JFwpi?1D`^9X!g$m!tZn zGrNj5HQ&U4Xv>;!;zLW|?FM{T{78Ob!{0L({d%W<67w+7PtUp0^waL&_CFIBVD*oD z8no%avj}*E(`mmK9ojl_@zqNw1m2GUc{H-$`XBbPXL-grtQZ1hmcA0V(N`JY z)9nYw5N9*=KT4d_dgAHEp?4dLp7C4!-(VECq}G);6EEMrh5t7h#T)gGXUD&bo{R6g zn~Y+`l*G0g#jI29_}~6*<73fgHSzc4Lfr0X)-d z*=ej;m6`LgeRX3$;JnL2bFQ)XPxrE~?qRQ2LH$+mL~QQ6MzZY$vF%i0AMy|ftr(W> z5BqoDNNi9idt3FlgE6V2T@OCjnrk88@?31kJL~Gh&S>exp;47N4vp#Ac4$603g2ve z9)e!{wej1RJ~x=kz1~BUWyCLs=!b0Fs@JjM$-d3m$PLL^?45WoTjn-s?m{$Qn{dC1s|N|3h(}e-A$EXnSaU##@orQz*^GJAQvjgTC#Gg)Zdk=YleHD8n z(T;rJR`+sNQbj32ULpl`gM;X9{Tyh+TF3;C;$Was9&?UtLQV@@2S^#X0x``wMRK?CN5{} z7N48KSk6lrPxbRP{zo5>?q^)3!%{4j)|nQ@EEk>;a%CPe&Flu9*{Jbd3(oUK8MC4v zHFnIW+^U&HGl8vzG3>?`+Vq~UNbT*VJ?W5aoKB1$LEdI=&lIlr#9{FOi}Xt9K&-Lw zFeZ=N@33Rrz7{{@fAMFn@qHuYF&SwLu7B3q7mVa*@h?`qsC>-iJMl(FQlZA=k5|Xz zVQR+_8)6b0GQQ<~0hC^5_j=u4xu}nGg4ehsq)&+JU(Nn?qv$TKia2U2@S@Ml@7+03@=AJ zTFXYNLpI2+XWZETCq&;Q??+$^v04^BU6De;^XU=bAzs6(Yu?E4cm)q-4D<^lmP>?Z zSREETJLQisG5QSf)ZuR?znhn_%Uf`*cSYQS>*f*QIu?g((a3NegFa%E8GvhexkR{z zy|dtQ3r|_me->Quoj0okece-UZn1P~oMU=av4-mdeSf@K&yAJ>Y*n7FB+DlBM#lAp zvWJ|SS6Y0Mva*4m-8rxL40TAZb?)^}WyF*3)f`~no@LIiwC*#ar?`(Ty}mf4|7q)8 z{+C@#zG~<0KYYQw#)*F6-M_N+r0j3d0UEoDsRQ|v}?%!h_fiILxr}!+eCi*lF`q$cd?8VD;{=z0(7HNMLem;x#L@WKZ?iShi`-$P| zpUxaxY8J124*an;ofo^cGakDIk4e;TI&-W-v_qKz+8JIhk#>f?v*(x{4=@(mIW?8M zsf-`IAzd;A`*y$h=oVn7KmOQKCnhU1x*EJ_eK~hOIqs=hQtBB78?Hv^J}4`QwuVtl{`&F7=l%x=({Zk?YEUVAP}-g-A@#D~qv>8fiz{fzN!8Dlb+ z{wV&>3(iBFB_HM-`QzVm6^A%KzI(l^7zIRTE%_i+mb`6?yuXXBZZXM~loRN?2Rqmi zbYd>f2(#(|ck0_>;x_5qHFaa93(AgaO`4*1;_q*E-t%4O)Ih7_Z}}to_WDj2d5vV_ zu=6a-)>cXm3ekA>7-VJf+WqcGFT7Vac&+uvl)Dwb%`U!mVhuaJ{omek$mv=4IoVMd5^YGzG){a6+(T~`4ILDHRh=xtuQ|=T zzp$YPT3QAjJ-0TnX|Xw`rw3jfHZxO*Rd1EPK=VX(d<8mm>d+h!eNSiKpt|&ZH2!@G z<)ot&z3QCg?kOqEEu(k=|8D^9ZtCsvr)&*D8}cRBm}{&oJS6aV_C&41V{Bf0-7Oi) zJ3Eo}#oORTk&1u)Xxq?8{{1Cxp&i+K(^2#*+E(1ou_Yv1qEK(9XY>Vj9Ky zNk*E7IqZcW5YN;jpSdhEyR3_L&!dTX@mx0+P2^bqHUZYS*tY_O#GABwI14>C+Gs7| zJlT1)C%ASJb21WMyHb=>Qn3VqKJ}lzHza|Jk^IngF0m6Aan5Z--h0}{S?GM6J^0t+ zY&Q6s#&|opI(#0k0&A3mGXYm?u-T@0@U`~hOYh*S8(aui^c_Fj(oNtD-JTt1YRyk@ zw&OnEB6}WXkBGC9QCZc(n}f5ZgE+(XGbnG2gtMo>#h~B5?Mrg*{tK_0J1PG;@I5gB zchH)Jw~^@Vo;Z!gz&rjQ%bHg>o&%N)E*zLvhrqEYBG6Mll8zIr`vRk?D?y1}{NI|@7<@Cs|} z67cQNr|>SEiAKK&{{E8vcgTJh`NGz(I{IeA{{*};ZWr<6-*!zG?MIH<^64X73*s{3 z70~AswqKof9z49YdP>~aDF^uiS>r*S&oU8tXA(TlbN{`)g;OVO^>+n|kGtfvmEj*v ztdaJ)L*5ayQJc`t@_5^l(XF)v`Cs3%{>jdQ+?L_Lj(W83^ibxmc=@j;)KSPi@+^AX z0~gfeeiU7v`z8F(ZCdi2_#633{V!)5GiM;XFNn8S&ef6KQ{(OZ9C+gL--FkIi(K#` z`7d<;eU_i$*&K4i;|o~v2KvMg-Dy_d33SpyaDL;t(Q|^}s@W)*%^I#4R(#R3{omw# zZs)pUx!D+7~32E8-b*t}mD8v1g1(0Gx^EXg-VQSn$Sq>#+_e@0$E~v8`dh zKCeGBj8>gBP+$i7&{0MTy`0NHeeJf{Tg~P)}Yop`ryk%Ur8VKaJHB;2Os6$ z*}wfAIQuUD-^q1g%%Pu+#^1~iv9|iEY+Fb(Wx|{z>S3R^m3!?wZ{!echpZ=AyG}A6_R`NF zo8|Mpa-DT@W{LEko7q?1FPNd7$>82J9>n)1%m3Av$cuGR;Dqv;Nd}#=eN(RdZ1pac zeVirdg0Bg@UvVJske;gz<)7AfD(l+0Dc2P*tNr!OwBupF>|<|J4;|jl|IKlJ_XX~y z^VUA`B=?g0boToVz@caFSnun~l@kYk{iF*VIPg3|pViL*Z3~W{AvfFf;2rQ+&BLBu zn$TV$YnSp#IP+5b(yOgDjMh2UHPC9eAw6oAzm7KSeJZ{hBlr#fZ}@%&?T9`madl|! z{|&ysf%s*3$wR~WzM0U@DaK!IUx4q^=M4X^s7JVmmNR4V^6zqWV11N(`2Is5#rFsG z8G~z}=vX{{9^<5O+Yc@LKA~RKDO$9~Fy9`-V~oL3_>$x6-8sUX{|R-RV6I88s(SZf zL%{!NQ}_Zhj(lUA+50VH9tYX~$(LGvNz_AZ)ZFC{KSS#}VAt~4`4oPd0CyHJ8@7M0 zwPxdgS-p-q68Fy?QO=SKuQfYh=B8^bzMoLvBJQOpa(og5$4GnuUJ$(z{b3NA&e@-5 z**RBU%%0Yjk>Xt&OxcmFwJj?;d##!AJMiK8)7Lx9s(X9qbCypYyswh{elM{X7k}zt ztw46KzEUz7Yr5iRyp)gOYf!*h_8zl$jxXY_Il!2C*M5D|0&p8FonxJI@9;Ov|6tf0 z8S0l}oq4?bcKYY6=@aa}5`M)RLk>sDE!G);@pJT`$LMRs%Ex7r=oHygcs3K?&CCB= zcE{e?`bO)D{E91O1EEf0ma$`GL_fj#HIiWxeF|)R$}e|-HZ6Yu$sMy3U^{VSP`+{e zZ3fQuyJigj`5BfiY8q{vfleOzcN?~6;C&9fjn=bFzide7w>#wA&DKYdb3@n~43oT; z>%srup`B#py{|D>3$*_z9pri7KsvbcG2p~{H;mt%q+jS?T0h|G z%xUTD>Rf@=e**^kW!V~>J_~N`$FvXYMDCEU`gZ7`C*ga=`5T-YV8KfqgEa@>%YV%r zSb*--I?vMWF6?Bk$FQj%TgqC$o_UY1;|cJoIr1L~?QP`VmObtL&q(=HuKqRngsunj zUZNlMAQ#wqFVoT;y1h^?lp%RgEI*V%dJ&wDGmkjW>jXOA3h73=`^iIse`yQX!uoLT zB51M7Wvmfzas28=&Vy*zdlvq9lJRHV6`!=u$C!=pf#Ns5hhOy?*6>DtA5gz!j}W{N znV{VRZbBE?|055yYwjwiJ91Rb6nA4I`X$>p7MTA*FvBB}xhg90&lKD~b5eB+eZY_5 z#C*mqxiqlQV{9!a7WA;EaDo3gGGds1#K@bTd}H>EjaM0@C0C9qV@;U-@@9S+Mn;3m z-}piQ?o-%56&qsNwAkBuDJy#svhNz55uxX|F@C{#oaMk;GF3jdiFx|%oLJ27_Er2I z=J(h3dxz`cfqqke`={dl4&cMk$+&3TN}*x&Sr+WNVq4GAx`$tSj>GTkkdqc0%AHi# zeii*#0?t`Ki{+P5QaN!s|5uoCABK|8XDzSie?MhYCfITDB_AKZT=J#xS)f?@bH18x zaJ)ce;ME$tl7f`wr96wB+neq)&FW*6U#9ny>&oBae1U>YBi*}X;O9;goI^A0+(p?LSeN};mv_=POQwApKcADM(1b0?UEY52 zku!Lg&77#i59l81SOrcro*w)oLhxXNa}I!*h?h zN1^{s@;}mV=R{_|GP8xbB-|>7dp0^dVp5BIZ-6tt^#Er9&nz7M8XpVb4U^|W@T2E! z72jV5EJ41%(76>$c(3*A^`{19jYPjb2cNPLdyvnAlZ}~|a~;if47PwC`jUbT)1MS* z#aGE1R}c3-aI9RavfCxr_ZGG^y+>}CRcCzSC9n6n+=A`Nlf`zKwi%f;|b?1tWXz@&mv& zAG#G@+klNdbe~{NrOwyUoxMc+-R?kNblNM8KLds%W58wpOO2m1JyAEfX^X><5{Dtx zOtpN}|HL=*;$!rV_nF4ywSix>{mQ-d2>NF)aJ2~j^_9P9Gd&I7Y3{A>@IJ;*aRbfN z`zSHs|3bNCYsYSVTkq<Zf19E2#tD`4s3OW{ygMp6T!1d;Y}uXxxHkYFYKPhDOioEB5r8qpPPfhP9=a_GoRC zP2x>(K)vnFe2eX&L*EDad8uRi>d+p`j>mTerPCXd&2bIM)blyok`7WZz6Gys101keW0}g7>>JB{PeBbMZcjj3vS=)!aaI#+vhyh^XMb~;lz3yGeu`r zRv)VNEMtD@Ikr11&S3aFgnzc5|4j1Th4sf7Ps*--g>t+4@sZd|BltnK>fDYJ&H>wx zEhI!awQJ2Ko_7p8_aIC=+AD-U96a|R#F+-KQjZTlwv91Xjv_->&SkD-3}i#>;(x2n zESG@-BTxZOhL7njWOzZuAf20@Lz`Eb=kDPYy>j%I4GT#O2j9JXh^7q`p z@_yhU*{5RIn+@~JKS(~evZEWBOSaU-g@O0F-A3^kS7*C$@8SH5Zuhr2&&1Q9KHk7D zOnl~oLLc2cauHDgxvjMWk(0uvczjc@sB_lDdi zc*|+#wAu;sn@&AFW%#PLkFQyZoi;XuyoRRHdJFG7u5IPL4WnCQn?|=@kz&lm9#{Sr z@86zbMp|xNwkOO_vTv!Ag9;p$LZjj5#xLB!FLmvxMVCVt9^kmh99>46?FISIHjaXJ zyQw3@wcys!9%LtE9_*s-X?`z!Fqk#JY=h}7OU4$v7y zi9e6=+;gkV6Fus?nUs9c9F?3r?b+Od{NLm*fbaHDX4$P*?9p1I`bC>PWt>6Bc=vq{ zyBOcS&D>PqN^ULKqcz(HZ`lq`^!^NZ*4l3AeYyWW<ly{*q<8yCI4&HHy4kAu)^bDUngJn@`q zaeCbV&1qhFpgYmwaN6@ib0w5LetA>wO>tV=z}P$RNKbhXnk$j40?#ObJ{-Cdy)B5- zmEdvcP_z_^)1l}lxF(!oKP%i*sPC!Ep)cw19r|heCNeED!O90lEn4@$10CX_ollI5 zyt<2hZ@Q7Ld0m)KUMzUaah{)L&6|Jg%srwr*V+dn!yR@aptTmw)53)1{eF`x7Zh2 z*K$2OX)beYZfo#HW5W0Hd*?Ji(7ZL5wfWXs_oCK`#?1MwD{b(olC8+4^^fH0>`3PB z!ovE?BQw071_#G0lLN)8#s-Sloq3=m?8-_JF4xdj6*f=teov`8BAoBwz3KHf1iYCI zUhvx8Gq08LtO;Y&i~Y&UojA+#mt;(S49>L%)#1x?FLI(6oFl`)4?WSh8KdS~tM_=; zj@g=ATG$Z1b^0FG{WQ*7tey}2`S6tuKOemDsQ4S-%!l{rSq^12?%$>j_1|ez zZ9u=7*bZu%f$1#yS5z(o|D7q&hzs9X(S~RwOr4?+(U*sB92{RKdIPsX@W%7jsR?+V z(bsR~_2|Uj^=j&1p9cGral!sP&p4LQzy7C3wZ@oly6>TV^=s)h8yl_vxfh=AjQ@Y> zHCu97vufT*-+)|CZajWJ#6EY|EnnSp5qpp$rl)#8bl!b3JJJSDN^ZSsPmKDnp+Axp z-*%5xKD6>LVXNB<9u3xwz50f}$N0u~>y>+A#@H0rk+g2UyWy5E@9EMgyxA^f)&P4XiH;y0CYd=frqw_LgBPjdpTk`H4~f3np?PklAAsoLor zW4E(Cp`B){+^E*$)E~U{D|=MueA>TSax34fo~yBMSl`3{TiaWUt{_5HDb)@f{MLFSEj)#OF~ z)GwqwdQo!OAHkY^Ci`yuZ;uqC3|4L6y{SeYqm9C@Z}SKw&n}Zta@3O(P3ov zQ-2IveBYf_7OZXFIsyFW(C>R~e(_=(bl=}7ezE0$#4o-A&g1+7{q6bu;vDZs;up?Z z^CM_h{Gt+mano>qL0?AZ7lZxhETh5xi(e%4KO4MCMroi8tv61anp0t(A$MCm>0#4o6eau&ZhL_a)yATFc@7%$MgEE=u4PuO#w{fxZmq6@z_w z!QvI!3A`fP<`sNv^9ugwevnsWS6_O~!xpdjHM~Oo6R-I9A-p2Hx(i;RdH)Ld@WCt2 zFz00>PvjNf7{V*E|3|!{?dv~%=nnh4!ARL;Qj>7A$^|huq`vi+cEl#_#|#!~m~w#*g~GIBfj({-S@& zTbwBsjPv`SaDRq5BRVMnhe7b+@QSneA`;g$%QL_yZb>N{om|#%wEsLlu@T-OKC!K< zzvAJp{=xZ-zDN6vzeLaT#V6wPc?$csk?8ph=PC$R@+ReQ{s(fpk?Gc+nDzT8>xiD! zBRhzG(T8sCTIz{(;&=M-53uRL?|cR5+gK+H(doU#x=N0NV);a_7;QwJCs(1v+qAxY z79M27Ja*U`H)fCr(dP@T*$!_bhIS~7@FNRG+PDuG)rUIv{lKwMKFZo}d-fS=_&F2{ zF8nw9j>{Knl+n72+;G|(O26>nLruBKuH=*$dUw{d!zHEu9_bqjuL(EKG$&a;gtNHf z4^#0DIO7a~37^F`#_8i*;OK>98Ruj`;a-Hxw}+tSH_>bCOp@tqY56F^roiuvg1yZ3RXjr85Je+d+h81JKgn9iAeAGGb>({{kJ#=;_s6+KhZ_-5E_&V_O7SE&~mrngB+^fIZ z`#N@$3hV|8`8hW1LHHdT8u6C%6c3pZ-H(0Ov8(z<I=Z3Bd=!~!OOmwdybXy^8 zMpaXkx811mGfvAmhwn4Y@g?Zqb;fiazH0J~sp9{=*s){t_7xYPBcGzVfDfnEN%(_h zj|^G%($vUs-$(fcXiv`j$2gZD66(T-{M^+8eqtY-wfz>lup#N3KKoq3i?2=0ZIK7e zvcpW_s@SjhZC{6)PUv&EkAXF=33f$KrhUGnC)K?O7-p(23;y_X;iiu9@?08dLD$j~ zKo)Y&gnWk_cd~iZ;saEteW!dM;yx6jtEtp=6nNw}RR^E6-Y>Cj#$C{?#zF74NoO&& z)H=ILFl%mzwi0ca7Tm+~O<1}?>iF!CvGgsk*BC(`1#y3$3*n76(myTSJLfoJUk?Ij zIo}53>&!^s%J0MZrVTr?`tc}s6wbY9Re9xJfPQ9%pbOEEHD+sk>4{@DSg&u$SPnd2 zbMcV!s@rMP%XyQG#j-BOMQ#5L{kPhLAM5|w%mMk*)lD`sO5*mNF#C{!x;Zn!f#u)m z%W#@%_;~Hkh5#rn9CmKZ7cVbi|nNQ zNBN|YgMQbo{7O8=3F)v4h|QM2`UlX>gsSYVr>A-%r~hQMNZ&q3bmz_`FW@VU%+tu? zeB(rr_0s3g?dhIqRCKs<;h_^azdcuZuPf{v7q-u??bihzx=UWcj#RVqz~;sdD}HrC zkMf82UDk;^N-?V4~%HZJzThc^)860Y(W&Bv!5-S=+AqAi`}zSx~?=m+cNp3%t|EW% z4YcLdXV<0k;fB`bz`dBbA;Eov`@(RaUl%zp-=0Fg36&@hO5)g(7d+mVpVG!& z))F_o%I;GZe&bmde(rWzKL@Ojd!18ZhU~xm-1TfpuMxS-A~)%^U(LZ zcCL}c_K9Dh{e2(y&rGF%=<43Jzsa@E20R~LyL>0*)sEMlaj56!KugS(dr18E5bZ2> z=UBeA_c9-#!^r(pjmR&*Y4mD7AfMnnKcPpkB3D|H7hg%#Z~ayw3t->7UM-z=kS0pB27E~^KAFW;y)k8?e-kAKp_r%}UN6IF~~A9gg$4&}bcf7U(PkG{QP34U(!c{7l~d`3of z20EFHZJToMg&&8(RZc28ixq)ZKkHE;@H_eNB*&E!XLbxZM)~t~7VEEw_a#2sznX8g z2Cj!@Jhio(yjJcJJ15=-a@=i0NA^*9@t#JGQk>5z`mquoyaC&mWP}p*Wa`UH_@gK< zUYO^b$q}SAS3WNPtWW z=(SV$6;72eC9yr}{wk^ON$Pupcf`&0iACZSSXFd8l?Z$|=vd<@-;D;WfvaP}^tn(V1k@eUY4v7m^pXB#8 z()p-~{N*a*h9&1{-q^CO?PC;D4BPFctwH7t%5rPpYCacVhj&5zkmDkp!~9d`)tZ7?%8~Vm^{8cwp1|!_I^gb zT*$hcwSOL+#ktfLZjvnA=sedc#=3It*Sd%$-3Po+CDctfZ2v%fAYwa5j-eKw68BWX zkK;FU?*84Dzoh6}=Z(r{-e2ow8D_pN!Z(#Z_wRHS>-#}yAyg6yvP}|tnp>t3MS;W)V@Tqc_Y1J4~lQSVoEcjjn9+&Lg(88Tjw)Ivho5-L%PCdw4FnT~ldk zQ@_Tq86Ci-)Vay}KQsDIw24feS-Z}7JjlM$!sB*tMh{zRX!k@^8| zMyFw)=UmCRTIWvFhZm{K*|#)sFMUKlZJ@{KTLh0l7t@DMZRhZANZvHP| zj{sh+yi(`jwFPG8A@tkUITy-9u^3r|HLPzR?L3(PvvL5@f5t^?4d+a^+cc>5@b~Kz zZ3)Irz-ZIa(Eg32+xhQZ8t;+xIpkr%Us?PDnFXI;tv~YL%N&yLXcn+nA;)whbEsd# z&+t&5Cm&~$Oa88;oF{bJ%H6ab-YL08dz~#G%5UD7sk1wz?+H=PYi2d%ffLCd17ij6 zaPl%Z>!YUnw}Xb`oGQ(#>rYg+L-H|j7NFGxTkV2zO1=|Z;7=oEH*qn zCUv?h^{`CQ2*%;yMFl-RmAJpx}*A?bt#K?&YHCa zJ)L-T@&Ts*SQWpPz9b>;LDkzed7OM9dTk4I;R?I7IPjh{B!2f zMHbDLYwdV|XBxxKsev^bvrc@%rK553{UP_K`@U|pcqX9Z{ycHKBIGkb}5>+_v! z3Mgce_ac}@u%bW~5eN%%UuEgv!YFez3r zlzMTxuik!kH_t3TEzSq=?RVF75nuRip2he{ZugjD$_m(TptoK)-AqY-8{bU)-ZF1U z3lyi~D^x}dMYt~>`-#8Cwns|udj_ANz2=zeb=GxsPj}vT8h>M&hv;MGv*f>c6Tio{ zq+H-~)huD3)P~=6%ET0Zzv1n1V_%n#;Zf#MvsqYHMt^Sb8f)aEIX~4{gWq$Ge7r-9 zyL`N>*zeVrUSBhXt7klLBZqm7dVIjQm6HdqFzhuB?Y${JY`_#zO0fWGrkK zn=6sI*HE{^TW4}FeX(SOO_Z&Sml2KKE;{5pwduq&bpH9>KO6iFZ~rCcpz6kladRcU zb;G~2%R9PY&T(~dPM=j48?$0@>0dv4+~dsa0K7oC211mfAJzN8Rd){g41pzt-?N?t zc$R0uHW+I$2-jdcs#A5pM7`i+7IrG@f4hG2#H1P55`V&$hxg3i+<2eW|B>n+Yuxn% z?}vYCZ!5gvA?XB6#{0+%wy$ERdu;UI@$Y*lwfD(s=rEI5E5tvEjcgC1FEN%}7cpNq zuD* za@zRH$tzQg+b%Bp+T^cs{bzpv#_yr&HIu_`U|d`I(56YtCtrtuVdT2|C$I6Zn0#OI z*C%%*8@CmuteKqkxeDJd?w>5b#h1nZug<;2*L!@GFPHDjQ`SyiQ+B)W)-T`TtK^5S zC)0yJ;t|u+BRiYtzRvdXUgI|4il$NjcR8Q!nvZ>L@>Q<8ejvQbR@(N$S39ot7`LUE zx!0zRzk71q?yq#Ly~w!jZhRIW;JV4YbMnF3y7m}2E4cE8C&p9H!M>Fp)6H>ZRp-Vn z3}crnqD-o39v1FA=Jd#_yA*8in5BAFjsHTmt8iFckxZWTh!O3xBJS~*Rnf& z;*q{Q_sgQCo8C>^r|Y_2m+@}@?QJvbK3?+2iW~XcT{7!?H3f58nm?iUs}H?a(zNiz z=&AGXEP3hKUq154BO73w`g@V3Nq==E|9!_dt>>km{?F^?QtoC|Lp{9goO{(DOFq74 z)}M;s|LP}Tfb`3`eIZ8TwszqK8K*tf z@THG6CZ~_%Ov=&5#l&V#N*C_sqh63?+%nztZ1fnJii>TIAE;|rIqQGEP01U4pJF`NeuQVv`$Ee3%~8>m&Q0w>GvztY z^^>giy1%l-;UuBiu*w`=Fuz5PL3#P(&`<4CuydKK$@i~7mm=;l0yX+zFLd&rOQWvn7 zho)eIp)Si7gDjr7CJ8>)R!ibT>oGwmvgEnh!4!+;@`OL%P;m#*%mT zf1zW&Q}XKwI@Uk3@6}!qd1OQ#YlU~Xjun`IRWSW6Fa_{;7=)QvbaZGA%(HlpZqYv* zpP{z@p-yym9NytN(O&|u=21r+-r+jYC)oE5o{bWRCk}5K@UR}t42+=D9jZ5-lbwAA^D$9Bsr{n#lmE#4b;_Iqrjc}_-=K_iqSCtrs7vJyu8XB3ea471w0yLV zRP*&h`p*H~CoW55wEiGbpCk+c3CqbI=`8EI)PF89OaMHISkT697BI$=Uu^` z2#*kN+C)BK>)V9*aOJb#4{uQ&Bg0biO7MT!ZwEfX(FqQ0UDNsSI69Q!XQHUzp06h@ zN=6`7-W<#PIlxtoU<-`^@U;Mvf&llxrl4b#y#DbMC3tjfc>svtv%_zbVgkEa36&+ z_71Jzd@9#wt-r5ao3#sk<=U*B?y2|&?p`<-T<-2T@2Z!(AMerx7QuQ8A457j z9A?Zu23=A6v})lIHk8YV`3&l(&u2EE-0J?de~3|^8~gVOL zJYg9xFwen@#*o$pJ)Q>NBofC9gZto}y5D&{=sK$QHv-rCPyFSN?~`vGB2JtL5%*l- zrFnzlz#5}Sz`F!bSZ#?H;M#`obv!>WlaW1L>Ofc+y~ZtrL)LcQLm0Cb9F=3-O)bSbS#<*DU!iFPaNz z_YB27c>ON9Ph-V1c)f6Zx5t)2WoRokWHjSCaUAcQYRCH)zUwbeOhy@KKV&!JBw`+d zwbWr3kzaq?3DO&J-0y9oc$5Y<2R1c#ww<8&Aof6=TZh z|6V?SJiCK*oS3hDjr7A$*x&MowZ!%(hs`Q{iIH$AM~pG$##%_Xao3B-6L?niZ!7HOK`uMh;ev{ zmbkJRHoXM*tMqO&y$o2l3l9@x==qajuniiAX9B66t&rKn#8@lV-e_&m7e4QT9#}Kl z`4z$xQ2gFzUH8Ky&+FlY?h7E(!wz7Z7=Yi+BCHd95&A@U#(6!`;74KF47L~IyNefe zxkH9eb8vj(2s?xM69_wZu6TjQAX<~OcI`jbiFBx}NasXUxHzHb%jr-&N|(Yq;ird( zAB9I+Cq@qyC$2_&;Cfk0zX#B-ljzq25uVoUsQ=NmTTc`Aa9M4aB&}Q`8w|cZ0`rAsH1L@(z zmOn}Bx2V@a;?}U`PhsAwzmH-D{ODa7dbl5*db$tbz9xRI?S)!{c!BPH<_@);c*20O z6YJN(@7TgPUXOc_`ulL)gJUC(LLBP4h_OMpAw1)$e|M%8Wt;Yfd}ff+o`Q2LKR>9h zH3CjuZzE8?VSH~({_5I#HtgnD$beyy+SzvuU1xjCNQV}FM-}dc!!drRY2mMhBOa~s z(O5?5Mc^45tP58T4@ghtqsBYqMB7gKO;<#{b;FFIwl#5BFSlwD8-xSTk7Mp0VZn2y z7`raF4gIndb-}$E`egW7#E*jGIiT+JUIO6}_slF7_mpC90`riAD*fR1Eny#{)@=~? zU_!nr5o0>S&ZBE%0sI^W<3C9DA+9lyJxwxNFT(SsJCFU%30o6A)LdSlug>?sN5m*> zYqrkVFpt(=9k2tvUX=y1UMMsD=CPQ{KN{b-M7sSWjVo>7ln0d+zqL4scLrkqiFY)1 zN4>jXt^KQY_bxY>FL7!0lZ;)?pWg+03I&539`63IW%if|%j_93#@Set_yT2JFr$0@ z2Q*i+$Czh_<9sN6H`x$>IgLYB zF2it?VLAK?CJ);nCW`}$ARE_3o81}pY7_O7!cj-q+r5--&yC|UDZOkQBM^TMrJWiV5Amt$5}Xxl+OUXgL~!q^Jfm;hxaXXyCY8PatA$gN$i!by$hA&%-esaYrHUEMOe)WAt|#3%cT-(mLR^hcSj67>2T5iL`FV z+VD_3(|s1oVAr&{*u!D@S-y6q@~M3HAzy0KX5>xvQ2mYUMuYvdn*Qr;CmZ?vKe3$@ z#QU$Zow-QMDf{a|yxXJ~*$(v&vY%ri=1a!Hu2erETcP%#w&=cbY$n+a*%sN+NVG>+ zE#iw2up#OE25xV%i{W^7HWK%O(EojjT?;mhfV?aE)D!4a zR`jVE$T#X?%h@LMC+Z_nU9_{iV2m8SF={08Kb!hW1US9hd(SVwFWAa`jmAk&*E=?t zksj4!1^Szd`i1+HY3TFA(dU+9PkhPx z0V@)<%@5N!Bd-(k`6;WA?^aueXKQFpUtJFzLcFcQVO+yrxNYZa0&_|&VuhOfQ(6=b z{k`75CZJV%@UGb>ZW8xcPHt}S#^QbUc-EY_70*NEDUo>q_2;g z*kdGrJ!~J0nRw3x-Fqv)t)aqf93aEewO9Fv2lzKbr^-Jq#2xsSK+TBtYPhfBP@{^kj2rVZM7wF?Xe>;!rP5MgC$!NBO-PdOTj)6Fo z&b*kv2-Nj3o+CeAXLowwuudRY7P?_ocJcR`*ZZA$OQGssmvzdA!0+;h(B zbOyN>&sk9&PkelOJv8Gw`r{eo9>~8wgWL`Ir)QAUb^4<-$jR0VFpo<_xVO#_&I8-H z>I`;~2wm(sLwwaAE0IrxsLMW8pA`Rb|7$c5g$;6Y(;2U2%w)Wo@lnP)#)FKlj3*h* z2ASSS#yH078TWURayRphjE^%`Gd|1M!1yj>Gh;iW2|rjMH!|^KjSdQ z@r*MWuVzeVT*Y`J<3`3Z#%CGdX8eZH$n9ii9L6}2aRK9U#KAHyc+c;rj#s}{`kPnCa1Al14(H2{Lf?s>PL^m7JQBGZHt{%IYL~zv!+mDE>># zSuFN4$DCDnjm%a0P0W=o9%3$gA07q?;w?epTZ80Z1@X2Z-p*XPef0dt+xhhYW zAh{`s_X-Mc4&wcSxP>|HHFP&9NNx?{BZ7Dob5-7PLGtJz`NSZ(El55!NNx|}aX~yj zDE@*Vo)E;Z4dRJGJSB)bgLpb~r7u?y&kYKnAH>%MaW`|-zY2r6hqWL6wCWY#QZ{zU(dWR^JeB2=EjXOzy8dv z%r9ad&s@cKG4IB5H*=-`o0;Q2P zaTD|IEN^43#?RpK5?}q%^H<@`%vJi)%$0q`Ggta?G4I3q1*dOhdsO3F@c0zmzk|mE zYf$`P`!D4DdvpFvmLxfHQd5-r#F8b+DXGcnK$jyY*@2}O>6R?X$xQ)Q9!r+wI@2fs zdn{S9)RB`L$XBH%=VoOqAEcYE$dVXVT%!^9{c**B6B6OjfzR2c&t0kjSk;;+E# zaje5}5hAU_$uP)=Z zyT+B8wNwQYiRoDoSaNb5xoOFkWqFS56kV1`O3Pg454Vci8(M*X9yJh45@mBqbs<7< zh{TlCrH;IGn%!lpsFvjPtem{;R7xU|Y{8Lz`uLoFVDz+HsdGKPFMnU^fnw-EHz$iM z{^?R7eWhjR=0OuFX*sTRM{;ULYG$q_!{Ji(Om$lRq$pDF{&0R>S^Pyx^vlm!q{QSb z*P7EQjr5k6l55FM&CScs)SD@Bnq4H$Td-h;UJA%%yZWr6BR_S*WdF*pWrL(DDiX6Y zGSe(%Lpf<=6^VW&$(|C}s8qgS`8C&d2$7iK$aE~j9m1a|H8|WUl}h>f_4)_R`L*96 zoYH@go&!T8e9D?kM+Uk^T4q{q8b*$_so9pLS=kn47fOzM9J+}KC|^J*q~ojS8ME_+ z`hqsCiAFJumkThi zSf-}R+ce+sAS_d8*oaMcY5rD z?o@tiE)^VKahlr)#-n>DI%v)njPTO^{|qTlim&pf@Z`wvUvX3>BMx=nLFo`z@d=5O z>ny>?iBfp-SNSWXc;v6r!Kp7kohzsERY?B9`KhqMNa2)j34=L>50n!Rc2q`+r|K5S zm46^oeB$I(oM0}ce!1c*TreuRLM0DQU&;T>UxoV*o?Zi1kty;-I{q;6g0p7krKihN zox^VH)m)xD&IhMHsvMs6=)ms+SM5e&=y{GnPS1J-a(dPyklz!;?+xPgoJe5!9fpn^ z-w^E}@4^LD{V|+*hR6}gB1>e8RQ!z;DY_1@o|ct84cD)Dxk@KQyu0H%Uu_UK)=9aY zv4Phi6`IdLZ=~Fp4xcEw@^^Fk zid&ega7A1%C!_Kod992wGC39EM(2~6 z$1;xxQk;40Kc8_ikkY>j2j!iPgVM>sVZq_T(GN#94l1h~2bFa_#4#(GBan3Tse)-sC6*`LwL=w>WrY+`gkV`;eKqy7~sR^vPqsCrr? z`k6!IqQ~Vzk^zi_#z*77JOrd?j=vP~k`OOjPrqYa($T*XKRqDdG01z2Pq}{{KOJL6 zGIB{rIo9fRNrMm7QI>_$8~tCBUKZ+^gS4r%q_MypqI^00S$$p56qPs?Y2_dtr#|92 z&<@l-e*GyO{8@UGMz-Fn%R0nYCHnLDYoM)UltblC8dI_VT>m*@4N6W{wG{OVOhan@ z&+?ZRnT=YgxMX?%dj9#k7NreS3bMWZDV#cg%Fo{iGQskY4q374BPpoO>Qj{I)ag;& zWTZhYkqeDPA~n(r*+~X8lc(#L`WV?}$Cmcjm5eA=DP?jlEeUTSc-`GNj)O{MrVe7Ehf z*|>qn0>*sYEv983b zC9gqgc+#{WH9I3M6YFSMnX^){2bn@)mGgMy^+aJAbA?{!3b!#=SQ{j-50W>UPaPf=6{RZ1SYImZ zx0kVjaX(`t5=w>WptYxfcY+`I?Y-Ma?Y-bb|vYbXn6Qh~Y!f0iTVvJ_AGbS>+7*+ai z=7o$N##+V(#wNx##?URYTwNH=j8TjUj4sCcd6{BXR;E~hab+>~1{OH;#PsYmF&~qD z$Wk0@1j%)z_CUBCA_$u)&&U`4&b(}0fOEw6g-1Gh+0165|4mO#60;oH7)P>!Ys5_C zKQk{~OwL;-=BK*E9Bf$3&RQj=rph4^aj-VOhT>)GCrBUhlbt}Mkw)`(q@fRrNC%~b zf8MgZ9A2>5D(*U^uGon1;bp4tx5T34zgmhh^ zS+h)6#`klXPL3~xOpmUMem^9`>C>#)AD8@PettihFU>6ceiUvdN|33CPsJR7>ft~b z=oZ&eLgG}ynOsjoYKzIhWx)9;kqbCSB4Lz&^p9+6!S($#Go+_m?9sWs3+3y2S zIGHcaAElG|r|Ef-kIY|Q6BSQq-4U1Np{uzx2w5&UZ<6;F6iSto=HN6-6GE1kW>?Bb z560#1=sy{yBp1&}=dPL z!R>c!xbv=!cNgAs?|qx@f8fEQhaP_9(Z?R&>?tlOEi13s;@w(VwQYNKP3;p;KDFcN zzduvA^V#Q~e__{)^}Ao%v-jm!UTxU-+CTQc{>Gb)2M)gV_B-#s*Yy4eA0GPX1Us}9{b|UufG1~+qUn%|Ka$LKmFYP%Rhhp?ZnC7g=Po|4eQj|7#?v}m#$}b zGj;FLvsdqP&NcVxdtSfuFX(R>Fz~`bgD)Cl9Xf3Ih{%znqDGGyJMQA~mqcHB*#zuC zU2bzE;Q@rD%baP;SEOfTX1P{o=j7(CTAjaU?KRh4cm0yY)64&|?uNhq?SH!d|I_*Z z+xnk8C3fnx=~vii%)Byg*6ca)bLY)puyE1hgsZNW`aiw={|No(i52=7fJZ5Gr!ktI zm-9$kqaN&6i=5!BCu8=vc&5|o(-a}I1VcwIumw7MdwanFX zLUqh(jhI|Lb6O)O*TB4wq@t0zdXB4!xq42jnK`XZlWS#;{Tbc0F~5L$J9G7%oOnUD zr-kK4<^!0Um=9!Lzg>pEkhz)VgP2>G4`yyx4}<~HUw=JCuYGf!k5%iP6$D)R#7)0h`ApU&LN{0ioE%x5rfU_O(16Z0#X zw=$1o-p+hBbK^_0{&Sd{na4A?GM~phn)xE;cIJzjCosR7xs!P+^L*wjm=`clXI{j7 zJ##N}jVB;=%tM(Ma)0j3yn*H6%$t};FmGkvg?T%36LaGpsgIt_&CGi-w=zG6c{Fo; z^j3Fv=I1j{WIlqqi}?iR1shDb35}D%oCVvJVA3Z4`rUuyfgCx=HbkXm`5=8GVj8?j(K0^ z4a_GnZ(^?T1h18ODD!saotYb7mh}&3Ze||A+{(NQ^JwOMncJC9V4lca;|ZgSc{p=7 z^9bgJ%)2o6Fz?H}miYwc4a_y3P&P3SXWq&@f_XdhzRZoU$ofuTZegxjWcx=k4`*&; z9>F|b#b=(V;t!JXT`E3vw~EiaP{n8NQSq%Zeyxhnyk5m;-l)Qlkl~wEc;;;?Jah4? ztgjX&!<(3gGq*60U>>EykCWkTDm?Re6`pyb3Lh=QyOf-{TgfL%d7+Xs_b9nd%4?OJ zdA;IOrMyvbyX4J^$4TC%c)aAILDoNXo#ZCweVJRB%T;25Ra0687J{CgAg9(P?YwfC z%xjvo>P(LIWy#U*tVCLUCN9@L={XQ`OZC-R%=bCGTtyd<%5bzlPL9?^$;P28Y7p=<;mc3IG_P?D>xoK6+zC)@##4naw|Ce3QjKvPaBZS z<8*U5e;22-jPs%0d2+NuPHu(13qa3DDSb$J2Kz7L`jMVjAUr*nKq2WF0;wrVh4$s? z*@yX9kC%?@BT`He>i&o9BvMTCt!tBgM2c9U?nlT@BC-0e?tjQ$h)?76- zsuzWegcT{f%h&bd=WF%&eop->Fg*3MNLZ<=mwXCoy06`+-%&kOxij>7&hpihp4-=7I&2% zL5?q!qO`D;s1Ipo3b%}W3d-NE8G1X-_UT!UM>E7+&R>ovvA+Hy_u2gAqw5gmmcZfV zcrwM;E_B_Y@k;eKIX?L1nR@*L#|H`@A7Ce>zxnX#Xy3A5`^T}seh{mVwds0^q@DTu zzqGR{K79w;O<+8ww`nLlIjNUvKKql`ZM&~ONj**Wm0Rj*vTxjydh(CsQctnI{+FZM ziL7T}Ib`|$^;G4GXAR48#rgV;EZ2NrIc2%x0?I-5=FeA_>k41FRk>7q$?0j;JZ_$a5J1MGnEn;mf7Cm!#szki-D zuk>UWfljR(t8w4O>(V1Qkn3G}pCM=4ct(-;F;p6EmN&6SA@dKIdze4Lyq39#c|G&H znKv?jlX)}qcbK;^Kge9XC(E~$xrzBs<`(9AnMW}{#N5VQ?GwZ^-_Phd= z!1@}>+|BYwm=`f$!Q9N@2QaT?d9sqTel_OxELZcuM&>uLyqWnk%q<*W?Gv`MT=k!5 zmWOh9W0TaMn%|h2-^OwqhYw?JWw{!s?JQUOiqR}D;qZ3m_b^XjuEu32^QTyz&%BDc znb+;re6fJ#8(1FC`FCbs#B#MylfZH#%e^cwWnRbpb>fmS4oYf#pu-PHvwF z=1nY*WA5hoBbm3dJcqf9OP}@>pP0&1uV~H-o)|E%!^oF!`#bU-JiKR zd{>s&v3w5mc+Sttyn*G*nVVSNpLr9@9n1?j{j-_3vRp006|%e=%iCFgKXcWCz9n>maD6F5z9xjJeuYC%+)^hWz6j?zmd7;d0C$B%#A$0Ud}v$ z!{5%_$$Y+w&-ssGp3m|%%%fR8n0W!qmoblG`5@*+ESIZjLU@^PWVw^W4`*J-@(kt; z%x_}e&f(SbGfgbNmF2B0pP)F)Z)RS|@+g%a%O7KI{7C9guHNA}9Oii}w=!SI-21!? z--CHH%O7BFXTE@W0`mu%*K+)x%$+R1i+TMEGX3$)^I85^=5-vu7xMy^FH-SY-kW(5 z%NH~EGB09Y$NWy_4a_$)Z({CMa!&so=B+GGVBW~`bD6iZT&^nMy@D^u`b}iH@ngwv zVQyx=g}IgaD(2D5A7$Rm`SoFLXZbbEEu7y#<_RoMVeVwUi+MitJ~L@Wvcv$MILd9qPkP6TFoyR>GVGFQ*3*qA$6eh2eLjvviDpXF}mO)S5Zc>&AUGjHee_G4be^6Qy< znP)N=oZk7&>sY=-ah6}qyn*HGn5*ZmEX`E=%W%w5do z`YintS2}sW>%e_{AWy<7Zy-5!`wXkRK4 zrB~_8eHgV{NBdT^{y@LCl}@fpB_Rd+4X8gIxnD!81JcR;nq;4zsVtGuveJ{>ze&Mr zw{&v7O#bGDd?fe(&O>tg9~ho~h24>>>!4Z>&fr}qxgWI5xB4L0Z5&u7mQL~{UwI{0 zyOnBPDA`wjDfib$@-$!hBwy}pXUQ{z(s%jnQp(jXoXU@WrxI8`zn#nQYkhVo*Ja4s zRCrp4p6Ke*X5Bd>QO2Fuc=eH&UK~-wp@LGkxtR zF4?ETFO@iq(|%R^zIK8p7uW|lyq`GD$S=) zxqqm3ooU~h_UqJctK5eseXI23I;-D)6j$SrQ zt4{mtwEw7f+iCxr_UZinQSK9}U3HSv{*%g$IE{n!Upl$J6)2be%`YdO;j=%v4@m!| zll#N!=>z#ZLZJP~{UY_00?8@=!0?p5e>{-;dH(Xq{bu!41HH$D?45p5C!OT#X$O1| znD@)nh@rUZ@rtV+Dfg?@Qxfty3Hd8}nZDfb^Or~N=lJ`N&l%Y6iu0w(Ho^&fhh2|d#wC32tR zkJm%#p98(0D!lX$ynf1kJ(WAvm+V!QmN@PE(pwKyd8iB&LXLoPzt*pB`NohyPW%7r zDHVF2gKF=$ANf20{g+PeAFHQd=s6K;5BfExbnv+K>Y;z2i8~a@2^5B zq?7yb{_@Cu0~$}{2;=9n2Pv-NOYZcQM{;_@gLIPT_{ImxbA8uOx$p1KpQ8!Ua@GQa zPE5&>*T0I-bLr0Z#n-vh8y_99xeHOpk2|YgEW38kcSDoqJU`{>6XU}69=vVoy}$IH zkUmw$F}+`yx@p9er1!LG10O#3q9JqWp4Dc!zw_?f7Y*vS<)1Gv%V@|sl(GHGY>gu9 zej{Z_N%CvvvTq0f<-qH%Zx65NAM?dyOXNhmCG+H-*OzyBe(9M0m*P_e)2<%eesJZY znJ?}6pfmPJ?jGqi#y(lOuJ3@2wm0th;jB0I-aO>2FW2qaG?b?9ApCvF->`HKNv?s)FpvW+#1wr;+n)A%Q^ysml4 zA$LUO$u`^j8@-M0zAG-o#VI8^Zp;I(F23oVDKlFf1Gm0E$u#kW>>ob8C%5-i^<68@ z|0@0cVWzh}Lu#g5F1W@qCo^r>U(EeJi4PqQ5yDY4Yf|K-J3ss?Ym za@NsMu|9Ioug4n)&WpEpd*+AldoJ$TYs#S;uDkTzhx%OA-Y@!I@oulDZr!=Me68c; zGd-3&u#(x*{rtO@?O9~$zv;3KW>ACz(KO5?E&%0Ax*H)YN%7KBxJojF;|- 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 z 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 14 and version > best_version: + best_version, best_dir = version, vc_dir + return best_version, best_dir + + +def _msvc14_find_vc2017(): + """Python 3.8 "distutils/_msvccompiler.py" backport + + Returns "15, path" based on the result of invoking vswhere.exe + If no install is found, returns "None, None" + + The version is returned to avoid unnecessarily changing the function + result. It may be ignored when the path is not None. + + If vswhere.exe is not available, by definition, VS 2017 is not + installed. + """ + root = environ.get("ProgramFiles(x86)") or environ.get("ProgramFiles") + if not root: + return None, None + + try: + path = subprocess.check_output([ + join(root, "Microsoft Visual Studio", "Installer", "vswhere.exe"), + "-latest", + "-prerelease", + "-requiresAny", + "-requires", "Microsoft.VisualStudio.Component.VC.Tools.x86.x64", + "-requires", "Microsoft.VisualStudio.Workload.WDExpress", + "-property", "installationPath", + "-products", "*", + ]).decode(encoding="mbcs", errors="strict").strip() + except (subprocess.CalledProcessError, OSError, UnicodeDecodeError): + return None, None + + path = join(path, "VC", "Auxiliary", "Build") + if isdir(path): + return 15, path + + return None, None + + +PLAT_SPEC_TO_RUNTIME = { + 'x86': 'x86', + 'x86_amd64': 'x64', + 'x86_arm': 'arm', + 'x86_arm64': 'arm64' +} + + +def _msvc14_find_vcvarsall(plat_spec): + """Python 3.8 "distutils/_msvccompiler.py" backport""" + _, best_dir = _msvc14_find_vc2017() + vcruntime = None + + if plat_spec in PLAT_SPEC_TO_RUNTIME: + vcruntime_plat = PLAT_SPEC_TO_RUNTIME[plat_spec] + else: + vcruntime_plat = 'x64' if 'amd64' in plat_spec else 'x86' + + if best_dir: + vcredist = join(best_dir, "..", "..", "redist", "MSVC", "**", + vcruntime_plat, "Microsoft.VC14*.CRT", + "vcruntime140.dll") + try: + import glob + vcruntime = glob.glob(vcredist, recursive=True)[-1] + except (ImportError, OSError, LookupError): + vcruntime = None + + if not best_dir: + best_version, best_dir = _msvc14_find_vc2015() + if best_version: + vcruntime = join(best_dir, 'redist', vcruntime_plat, + "Microsoft.VC140.CRT", "vcruntime140.dll") + + if not best_dir: + return None, None + + vcvarsall = join(best_dir, "vcvarsall.bat") + if not isfile(vcvarsall): + return None, None + + if not vcruntime or not isfile(vcruntime): + vcruntime = None + + return vcvarsall, vcruntime + + +def _msvc14_get_vc_env(plat_spec): + """Python 3.8 "distutils/_msvccompiler.py" backport""" + if "DISTUTILS_USE_SDK" in environ: + return { + key.lower(): value + for key, value in environ.items() + } + + vcvarsall, vcruntime = _msvc14_find_vcvarsall(plat_spec) + if not vcvarsall: + raise distutils.errors.DistutilsPlatformError( + "Unable to find vcvarsall.bat" + ) + + try: + out = subprocess.check_output( + 'cmd /u /c "{}" {} && set'.format(vcvarsall, plat_spec), + stderr=subprocess.STDOUT, + ).decode('utf-16le', errors='replace') + except subprocess.CalledProcessError as exc: + raise distutils.errors.DistutilsPlatformError( + "Error executing {}".format(exc.cmd) + ) from exc + + env = { + key.lower(): value + for key, _, value in + (line.partition('=') for line in out.splitlines()) + if key and value + } + + if vcruntime: + env['py_vcruntime_redist'] = vcruntime + return env + + +def msvc14_get_vc_env(plat_spec): + """ + Patched "distutils._msvccompiler._get_vc_env" for support extra + Microsoft Visual C++ 14.X compilers. + + Set environment without use of "vcvarsall.bat". + + Parameters + ---------- + plat_spec: str + Target architecture. + + Return + ------ + dict + environment + """ + + # Always use backport from CPython 3.8 + try: + return _msvc14_get_vc_env(plat_spec) + except distutils.errors.DistutilsPlatformError as exc: + _augment_exception(exc, 14.0) + raise + + +def msvc14_gen_lib_options(*args, **kwargs): + """ + Patched "distutils._msvccompiler.gen_lib_options" for fix + compatibility between "numpy.distutils" and "distutils._msvccompiler" + (for Numpy < 1.11.2) + """ + if "numpy.distutils" in sys.modules: + import numpy as np + if LegacyVersion(np.__version__) < LegacyVersion('1.11.2'): + return np.distutils.ccompiler.gen_lib_options(*args, **kwargs) + return get_unpatched(msvc14_gen_lib_options)(*args, **kwargs) + + +def _augment_exception(exc, version, arch=''): + """ + Add details to the exception message to help guide the user + as to what action will resolve it. + """ + # Error if MSVC++ directory not found or environment not set + message = exc.args[0] + + if "vcvarsall" in message.lower() or "visual c" in message.lower(): + # Special error message if MSVC++ not installed + tmpl = 'Microsoft Visual C++ {version:0.1f} or greater is required.' + message = tmpl.format(**locals()) + msdownload = 'www.microsoft.com/download/details.aspx?id=%d' + if version == 9.0: + if arch.lower().find('ia64') > -1: + # For VC++ 9.0, if IA64 support is needed, redirect user + # to Windows SDK 7.0. + # Note: No download link available from Microsoft. + message += ' Get it with "Microsoft Windows SDK 7.0"' + else: + # For VC++ 9.0 redirect user to Vc++ for Python 2.7 : + # This redirection link is maintained by Microsoft. + # Contact vspython@microsoft.com if it needs updating. + message += ' Get it from http://aka.ms/vcpython27' + elif version == 10.0: + # For VC++ 10.0 Redirect user to Windows SDK 7.1 + message += ' Get it with "Microsoft Windows SDK 7.1": ' + message += msdownload % 8279 + elif version >= 14.0: + # For VC++ 14.X Redirect user to latest Visual C++ Build Tools + message += (' Get it with "Microsoft C++ Build Tools": ' + r'https://visualstudio.microsoft.com' + r'/visual-cpp-build-tools/') + + exc.args = (message, ) + + +class PlatformInfo: + """ + Current and Target Architectures information. + + Parameters + ---------- + arch: str + Target architecture. + """ + current_cpu = environ.get('processor_architecture', '').lower() + + def __init__(self, arch): + self.arch = arch.lower().replace('x64', 'amd64') + + @property + def target_cpu(self): + """ + Return Target CPU architecture. + + Return + ------ + str + Target CPU + """ + return self.arch[self.arch.find('_') + 1:] + + def target_is_x86(self): + """ + Return True if target CPU is x86 32 bits.. + + Return + ------ + bool + CPU is x86 32 bits + """ + return self.target_cpu == 'x86' + + def current_is_x86(self): + """ + Return True if current CPU is x86 32 bits.. + + Return + ------ + bool + CPU is x86 32 bits + """ + return self.current_cpu == 'x86' + + def current_dir(self, hidex86=False, x64=False): + """ + Current platform specific subfolder. + + Parameters + ---------- + hidex86: bool + return '' and not '\x86' if architecture is x86. + x64: bool + return '\x64' and not '\amd64' if architecture is amd64. + + Return + ------ + str + subfolder: '\target', or '' (see hidex86 parameter) + """ + return ( + '' if (self.current_cpu == 'x86' and hidex86) else + r'\x64' if (self.current_cpu == 'amd64' and x64) else + r'\%s' % self.current_cpu + ) + + def target_dir(self, hidex86=False, x64=False): + r""" + Target platform specific subfolder. + + Parameters + ---------- + hidex86: bool + return '' and not '\x86' if architecture is x86. + x64: bool + return '\x64' and not '\amd64' if architecture is amd64. + + Return + ------ + str + subfolder: '\current', or '' (see hidex86 parameter) + """ + return ( + '' if (self.target_cpu == 'x86' and hidex86) else + r'\x64' if (self.target_cpu == 'amd64' and x64) else + r'\%s' % self.target_cpu + ) + + def cross_dir(self, forcex86=False): + r""" + Cross platform specific subfolder. + + Parameters + ---------- + forcex86: bool + Use 'x86' as current architecture even if current architecture is + not x86. + + Return + ------ + str + subfolder: '' if target architecture is current architecture, + '\current_target' if not. + """ + current = 'x86' if forcex86 else self.current_cpu + return ( + '' if self.target_cpu == current else + self.target_dir().replace('\\', '\\%s_' % current) + ) + + +class RegistryInfo: + """ + Microsoft Visual Studio related registry information. + + Parameters + ---------- + platform_info: PlatformInfo + "PlatformInfo" instance. + """ + HKEYS = (winreg.HKEY_USERS, + winreg.HKEY_CURRENT_USER, + winreg.HKEY_LOCAL_MACHINE, + winreg.HKEY_CLASSES_ROOT) + + def __init__(self, platform_info): + self.pi = platform_info + + @property + def visualstudio(self): + """ + Microsoft Visual Studio root registry key. + + Return + ------ + str + Registry key + """ + return 'VisualStudio' + + @property + def sxs(self): + """ + Microsoft Visual Studio SxS registry key. + + Return + ------ + str + Registry key + """ + return join(self.visualstudio, 'SxS') + + @property + def vc(self): + """ + Microsoft Visual C++ VC7 registry key. + + Return + ------ + str + Registry key + """ + return join(self.sxs, 'VC7') + + @property + def vs(self): + """ + Microsoft Visual Studio VS7 registry key. + + Return + ------ + str + Registry key + """ + return join(self.sxs, 'VS7') + + @property + def vc_for_python(self): + """ + Microsoft Visual C++ for Python registry key. + + Return + ------ + str + Registry key + """ + return r'DevDiv\VCForPython' + + @property + def microsoft_sdk(self): + """ + Microsoft SDK registry key. + + Return + ------ + str + Registry key + """ + return 'Microsoft SDKs' + + @property + def windows_sdk(self): + """ + Microsoft Windows/Platform SDK registry key. + + Return + ------ + str + Registry key + """ + return join(self.microsoft_sdk, 'Windows') + + @property + def netfx_sdk(self): + """ + Microsoft .NET Framework SDK registry key. + + Return + ------ + str + Registry key + """ + return join(self.microsoft_sdk, 'NETFXSDK') + + @property + def windows_kits_roots(self): + """ + Microsoft Windows Kits Roots registry key. + + Return + ------ + str + Registry key + """ + return r'Windows Kits\Installed Roots' + + def microsoft(self, key, x86=False): + """ + Return key in Microsoft software registry. + + Parameters + ---------- + key: str + Registry key path where look. + x86: str + Force x86 software registry. + + Return + ------ + str + Registry key + """ + node64 = '' if self.pi.current_is_x86() or x86 else 'Wow6432Node' + return join('Software', node64, 'Microsoft', key) + + def lookup(self, key, name): + """ + Look for values in registry in Microsoft software registry. + + Parameters + ---------- + key: str + Registry key path where look. + name: str + Value name to find. + + Return + ------ + str + value + """ + key_read = winreg.KEY_READ + openkey = winreg.OpenKey + closekey = winreg.CloseKey + ms = self.microsoft + for hkey in self.HKEYS: + bkey = None + try: + bkey = openkey(hkey, ms(key), 0, key_read) + except (OSError, IOError): + if not self.pi.current_is_x86(): + try: + bkey = openkey(hkey, ms(key, True), 0, key_read) + except (OSError, IOError): + continue + else: + continue + try: + return winreg.QueryValueEx(bkey, name)[0] + except (OSError, IOError): + pass + finally: + if bkey: + closekey(bkey) + + +class SystemInfo: + """ + Microsoft Windows and Visual Studio related system information. + + Parameters + ---------- + registry_info: RegistryInfo + "RegistryInfo" instance. + vc_ver: float + Required Microsoft Visual C++ version. + """ + + # Variables and properties in this class use originals CamelCase variables + # names from Microsoft source files for more easy comparison. + WinDir = environ.get('WinDir', '') + ProgramFiles = environ.get('ProgramFiles', '') + ProgramFilesx86 = environ.get('ProgramFiles(x86)', ProgramFiles) + + def __init__(self, registry_info, vc_ver=None): + self.ri = registry_info + self.pi = self.ri.pi + + self.known_vs_paths = self.find_programdata_vs_vers() + + # Except for VS15+, VC version is aligned with VS version + self.vs_ver = self.vc_ver = ( + vc_ver or self._find_latest_available_vs_ver()) + + def _find_latest_available_vs_ver(self): + """ + Find the latest VC version + + Return + ------ + float + version + """ + reg_vc_vers = self.find_reg_vs_vers() + + if not (reg_vc_vers or self.known_vs_paths): + raise distutils.errors.DistutilsPlatformError( + 'No Microsoft Visual C++ version found') + + vc_vers = set(reg_vc_vers) + vc_vers.update(self.known_vs_paths) + return sorted(vc_vers)[-1] + + def find_reg_vs_vers(self): + """ + Find Microsoft Visual Studio versions available in registry. + + Return + ------ + list of float + Versions + """ + ms = self.ri.microsoft + vckeys = (self.ri.vc, self.ri.vc_for_python, self.ri.vs) + vs_vers = [] + for hkey, key in itertools.product(self.ri.HKEYS, vckeys): + try: + bkey = winreg.OpenKey(hkey, ms(key), 0, winreg.KEY_READ) + except (OSError, IOError): + continue + with bkey: + subkeys, values, _ = winreg.QueryInfoKey(bkey) + for i in range(values): + with contextlib.suppress(ValueError): + ver = float(winreg.EnumValue(bkey, i)[0]) + if ver not in vs_vers: + vs_vers.append(ver) + for i in range(subkeys): + with contextlib.suppress(ValueError): + ver = float(winreg.EnumKey(bkey, i)) + if ver not in vs_vers: + vs_vers.append(ver) + return sorted(vs_vers) + + def find_programdata_vs_vers(self): + r""" + Find Visual studio 2017+ versions from information in + "C:\ProgramData\Microsoft\VisualStudio\Packages\_Instances". + + Return + ------ + dict + float version as key, path as value. + """ + vs_versions = {} + instances_dir = \ + r'C:\ProgramData\Microsoft\VisualStudio\Packages\_Instances' + + try: + hashed_names = listdir(instances_dir) + + except (OSError, IOError): + # Directory not exists with all Visual Studio versions + return vs_versions + + for name in hashed_names: + try: + # Get VS installation path from "state.json" file + state_path = join(instances_dir, name, 'state.json') + with open(state_path, 'rt', encoding='utf-8') as state_file: + state = json.load(state_file) + vs_path = state['installationPath'] + + # Raises OSError if this VS installation does not contain VC + listdir(join(vs_path, r'VC\Tools\MSVC')) + + # Store version and path + vs_versions[self._as_float_version( + state['installationVersion'])] = vs_path + + except (OSError, IOError, KeyError): + # Skip if "state.json" file is missing or bad format + continue + + return vs_versions + + @staticmethod + def _as_float_version(version): + """ + Return a string version as a simplified float version (major.minor) + + Parameters + ---------- + version: str + Version. + + Return + ------ + float + version + """ + return float('.'.join(version.split('.')[:2])) + + @property + def VSInstallDir(self): + """ + Microsoft Visual Studio directory. + + Return + ------ + str + path + """ + # Default path + default = join(self.ProgramFilesx86, + 'Microsoft Visual Studio %0.1f' % self.vs_ver) + + # Try to get path from registry, if fail use default path + return self.ri.lookup(self.ri.vs, '%0.1f' % self.vs_ver) or default + + @property + def VCInstallDir(self): + """ + Microsoft Visual C++ directory. + + Return + ------ + str + path + """ + path = self._guess_vc() or self._guess_vc_legacy() + + if not isdir(path): + msg = 'Microsoft Visual C++ directory not found' + raise distutils.errors.DistutilsPlatformError(msg) + + return path + + def _guess_vc(self): + """ + Locate Visual C++ for VS2017+. + + Return + ------ + str + path + """ + if self.vs_ver <= 14.0: + return '' + + try: + # First search in known VS paths + vs_dir = self.known_vs_paths[self.vs_ver] + except KeyError: + # Else, search with path from registry + vs_dir = self.VSInstallDir + + guess_vc = join(vs_dir, r'VC\Tools\MSVC') + + # Subdir with VC exact version as name + try: + # Update the VC version with real one instead of VS version + vc_ver = listdir(guess_vc)[-1] + self.vc_ver = self._as_float_version(vc_ver) + return join(guess_vc, vc_ver) + except (OSError, IOError, IndexError): + return '' + + def _guess_vc_legacy(self): + """ + Locate Visual C++ for versions prior to 2017. + + Return + ------ + str + path + """ + default = join(self.ProgramFilesx86, + r'Microsoft Visual Studio %0.1f\VC' % self.vs_ver) + + # Try to get "VC++ for Python" path from registry as default path + reg_path = join(self.ri.vc_for_python, '%0.1f' % self.vs_ver) + python_vc = self.ri.lookup(reg_path, 'installdir') + default_vc = join(python_vc, 'VC') if python_vc else default + + # Try to get path from registry, if fail use default path + return self.ri.lookup(self.ri.vc, '%0.1f' % self.vs_ver) or default_vc + + @property + def WindowsSdkVersion(self): + """ + Microsoft Windows SDK versions for specified MSVC++ version. + + Return + ------ + tuple of str + versions + """ + if self.vs_ver <= 9.0: + return '7.0', '6.1', '6.0a' + elif self.vs_ver == 10.0: + return '7.1', '7.0a' + elif self.vs_ver == 11.0: + return '8.0', '8.0a' + elif self.vs_ver == 12.0: + return '8.1', '8.1a' + elif self.vs_ver >= 14.0: + return '10.0', '8.1' + + @property + def WindowsSdkLastVersion(self): + """ + Microsoft Windows SDK last version. + + Return + ------ + str + version + """ + return self._use_last_dir_name(join(self.WindowsSdkDir, 'lib')) + + @property # noqa: C901 + def WindowsSdkDir(self): # noqa: C901 # is too complex (12) # FIXME + """ + Microsoft Windows SDK directory. + + Return + ------ + str + path + """ + sdkdir = '' + for ver in self.WindowsSdkVersion: + # Try to get it from registry + loc = join(self.ri.windows_sdk, 'v%s' % ver) + sdkdir = self.ri.lookup(loc, 'installationfolder') + if sdkdir: + break + if not sdkdir or not isdir(sdkdir): + # Try to get "VC++ for Python" version from registry + path = join(self.ri.vc_for_python, '%0.1f' % self.vc_ver) + install_base = self.ri.lookup(path, 'installdir') + if install_base: + sdkdir = join(install_base, 'WinSDK') + if not sdkdir or not isdir(sdkdir): + # If fail, use default new path + for ver in self.WindowsSdkVersion: + intver = ver[:ver.rfind('.')] + path = r'Microsoft SDKs\Windows Kits\%s' % intver + d = join(self.ProgramFiles, path) + if isdir(d): + sdkdir = d + if not sdkdir or not isdir(sdkdir): + # If fail, use default old path + for ver in self.WindowsSdkVersion: + path = r'Microsoft SDKs\Windows\v%s' % ver + d = join(self.ProgramFiles, path) + if isdir(d): + sdkdir = d + if not sdkdir: + # If fail, use Platform SDK + sdkdir = join(self.VCInstallDir, 'PlatformSDK') + return sdkdir + + @property + def WindowsSDKExecutablePath(self): + """ + Microsoft Windows SDK executable directory. + + Return + ------ + str + path + """ + # Find WinSDK NetFx Tools registry dir name + if self.vs_ver <= 11.0: + netfxver = 35 + arch = '' + else: + netfxver = 40 + hidex86 = True if self.vs_ver <= 12.0 else False + arch = self.pi.current_dir(x64=True, hidex86=hidex86) + fx = 'WinSDK-NetFx%dTools%s' % (netfxver, arch.replace('\\', '-')) + + # list all possibles registry paths + regpaths = [] + if self.vs_ver >= 14.0: + for ver in self.NetFxSdkVersion: + regpaths += [join(self.ri.netfx_sdk, ver, fx)] + + for ver in self.WindowsSdkVersion: + regpaths += [join(self.ri.windows_sdk, 'v%sA' % ver, fx)] + + # Return installation folder from the more recent path + for path in regpaths: + execpath = self.ri.lookup(path, 'installationfolder') + if execpath: + return execpath + + @property + def FSharpInstallDir(self): + """ + Microsoft Visual F# directory. + + Return + ------ + str + path + """ + path = join(self.ri.visualstudio, r'%0.1f\Setup\F#' % self.vs_ver) + return self.ri.lookup(path, 'productdir') or '' + + @property + def UniversalCRTSdkDir(self): + """ + Microsoft Universal CRT SDK directory. + + Return + ------ + str + path + """ + # Set Kit Roots versions for specified MSVC++ version + vers = ('10', '81') if self.vs_ver >= 14.0 else () + + # Find path of the more recent Kit + for ver in vers: + sdkdir = self.ri.lookup(self.ri.windows_kits_roots, + 'kitsroot%s' % ver) + if sdkdir: + return sdkdir or '' + + @property + def UniversalCRTSdkLastVersion(self): + """ + Microsoft Universal C Runtime SDK last version. + + Return + ------ + str + version + """ + return self._use_last_dir_name(join(self.UniversalCRTSdkDir, 'lib')) + + @property + def NetFxSdkVersion(self): + """ + Microsoft .NET Framework SDK versions. + + Return + ------ + tuple of str + versions + """ + # Set FxSdk versions for specified VS version + return (('4.7.2', '4.7.1', '4.7', + '4.6.2', '4.6.1', '4.6', + '4.5.2', '4.5.1', '4.5') + if self.vs_ver >= 14.0 else ()) + + @property + def NetFxSdkDir(self): + """ + Microsoft .NET Framework SDK directory. + + Return + ------ + str + path + """ + sdkdir = '' + for ver in self.NetFxSdkVersion: + loc = join(self.ri.netfx_sdk, ver) + sdkdir = self.ri.lookup(loc, 'kitsinstallationfolder') + if sdkdir: + break + return sdkdir + + @property + def FrameworkDir32(self): + """ + Microsoft .NET Framework 32bit directory. + + Return + ------ + str + path + """ + # Default path + guess_fw = join(self.WinDir, r'Microsoft.NET\Framework') + + # Try to get path from registry, if fail use default path + return self.ri.lookup(self.ri.vc, 'frameworkdir32') or guess_fw + + @property + def FrameworkDir64(self): + """ + Microsoft .NET Framework 64bit directory. + + Return + ------ + str + path + """ + # Default path + guess_fw = join(self.WinDir, r'Microsoft.NET\Framework64') + + # Try to get path from registry, if fail use default path + return self.ri.lookup(self.ri.vc, 'frameworkdir64') or guess_fw + + @property + def FrameworkVersion32(self): + """ + Microsoft .NET Framework 32bit versions. + + Return + ------ + tuple of str + versions + """ + return self._find_dot_net_versions(32) + + @property + def FrameworkVersion64(self): + """ + Microsoft .NET Framework 64bit versions. + + Return + ------ + tuple of str + versions + """ + return self._find_dot_net_versions(64) + + def _find_dot_net_versions(self, bits): + """ + Find Microsoft .NET Framework versions. + + Parameters + ---------- + bits: int + Platform number of bits: 32 or 64. + + Return + ------ + tuple of str + versions + """ + # Find actual .NET version in registry + reg_ver = self.ri.lookup(self.ri.vc, 'frameworkver%d' % bits) + dot_net_dir = getattr(self, 'FrameworkDir%d' % bits) + ver = reg_ver or self._use_last_dir_name(dot_net_dir, 'v') or '' + + # Set .NET versions for specified MSVC++ version + if self.vs_ver >= 12.0: + return ver, 'v4.0' + elif self.vs_ver >= 10.0: + return 'v4.0.30319' if ver.lower()[:2] != 'v4' else ver, 'v3.5' + elif self.vs_ver == 9.0: + return 'v3.5', 'v2.0.50727' + elif self.vs_ver == 8.0: + return 'v3.0', 'v2.0.50727' + + @staticmethod + def _use_last_dir_name(path, prefix=''): + """ + Return name of the last dir in path or '' if no dir found. + + Parameters + ---------- + path: str + Use dirs in this path + prefix: str + Use only dirs starting by this prefix + + Return + ------ + str + name + """ + matching_dirs = ( + dir_name + for dir_name in reversed(listdir(path)) + if isdir(join(path, dir_name)) and + dir_name.startswith(prefix) + ) + return next(matching_dirs, None) or '' + + +class EnvironmentInfo: + """ + Return environment variables for specified Microsoft Visual C++ version + and platform : Lib, Include, Path and libpath. + + This function is compatible with Microsoft Visual C++ 9.0 to 14.X. + + Script created by analysing Microsoft environment configuration files like + "vcvars[...].bat", "SetEnv.Cmd", "vcbuildtools.bat", ... + + Parameters + ---------- + arch: str + Target architecture. + vc_ver: float + Required Microsoft Visual C++ version. If not set, autodetect the last + version. + vc_min_ver: float + Minimum Microsoft Visual C++ version. + """ + + # Variables and properties in this class use originals CamelCase variables + # names from Microsoft source files for more easy comparison. + + def __init__(self, arch, vc_ver=None, vc_min_ver=0): + self.pi = PlatformInfo(arch) + self.ri = RegistryInfo(self.pi) + self.si = SystemInfo(self.ri, vc_ver) + + if self.vc_ver < vc_min_ver: + err = 'No suitable Microsoft Visual C++ version found' + raise distutils.errors.DistutilsPlatformError(err) + + @property + def vs_ver(self): + """ + Microsoft Visual Studio. + + Return + ------ + float + version + """ + return self.si.vs_ver + + @property + def vc_ver(self): + """ + Microsoft Visual C++ version. + + Return + ------ + float + version + """ + return self.si.vc_ver + + @property + def VSTools(self): + """ + Microsoft Visual Studio Tools. + + Return + ------ + list of str + paths + """ + paths = [r'Common7\IDE', r'Common7\Tools'] + + if self.vs_ver >= 14.0: + arch_subdir = self.pi.current_dir(hidex86=True, x64=True) + paths += [r'Common7\IDE\CommonExtensions\Microsoft\TestWindow'] + paths += [r'Team Tools\Performance Tools'] + paths += [r'Team Tools\Performance Tools%s' % arch_subdir] + + return [join(self.si.VSInstallDir, path) for path in paths] + + @property + def VCIncludes(self): + """ + Microsoft Visual C++ & Microsoft Foundation Class Includes. + + Return + ------ + list of str + paths + """ + return [join(self.si.VCInstallDir, 'Include'), + join(self.si.VCInstallDir, r'ATLMFC\Include')] + + @property + def VCLibraries(self): + """ + Microsoft Visual C++ & Microsoft Foundation Class Libraries. + + Return + ------ + list of str + paths + """ + if self.vs_ver >= 15.0: + arch_subdir = self.pi.target_dir(x64=True) + else: + arch_subdir = self.pi.target_dir(hidex86=True) + paths = ['Lib%s' % arch_subdir, r'ATLMFC\Lib%s' % arch_subdir] + + if self.vs_ver >= 14.0: + paths += [r'Lib\store%s' % arch_subdir] + + return [join(self.si.VCInstallDir, path) for path in paths] + + @property + def VCStoreRefs(self): + """ + Microsoft Visual C++ store references Libraries. + + Return + ------ + list of str + paths + """ + if self.vs_ver < 14.0: + return [] + return [join(self.si.VCInstallDir, r'Lib\store\references')] + + @property + def VCTools(self): + """ + Microsoft Visual C++ Tools. + + Return + ------ + list of str + paths + """ + si = self.si + tools = [join(si.VCInstallDir, 'VCPackages')] + + forcex86 = True if self.vs_ver <= 10.0 else False + arch_subdir = self.pi.cross_dir(forcex86) + if arch_subdir: + tools += [join(si.VCInstallDir, 'Bin%s' % arch_subdir)] + + if self.vs_ver == 14.0: + path = 'Bin%s' % self.pi.current_dir(hidex86=True) + tools += [join(si.VCInstallDir, path)] + + elif self.vs_ver >= 15.0: + host_dir = (r'bin\HostX86%s' if self.pi.current_is_x86() else + r'bin\HostX64%s') + tools += [join( + si.VCInstallDir, host_dir % self.pi.target_dir(x64=True))] + + if self.pi.current_cpu != self.pi.target_cpu: + tools += [join( + si.VCInstallDir, host_dir % self.pi.current_dir(x64=True))] + + else: + tools += [join(si.VCInstallDir, 'Bin')] + + return tools + + @property + def OSLibraries(self): + """ + Microsoft Windows SDK Libraries. + + Return + ------ + list of str + paths + """ + if self.vs_ver <= 10.0: + arch_subdir = self.pi.target_dir(hidex86=True, x64=True) + return [join(self.si.WindowsSdkDir, 'Lib%s' % arch_subdir)] + + else: + arch_subdir = self.pi.target_dir(x64=True) + lib = join(self.si.WindowsSdkDir, 'lib') + libver = self._sdk_subdir + return [join(lib, '%sum%s' % (libver, arch_subdir))] + + @property + def OSIncludes(self): + """ + Microsoft Windows SDK Include. + + Return + ------ + list of str + paths + """ + include = join(self.si.WindowsSdkDir, 'include') + + if self.vs_ver <= 10.0: + return [include, join(include, 'gl')] + + else: + if self.vs_ver >= 14.0: + sdkver = self._sdk_subdir + else: + sdkver = '' + return [join(include, '%sshared' % sdkver), + join(include, '%sum' % sdkver), + join(include, '%swinrt' % sdkver)] + + @property + def OSLibpath(self): + """ + Microsoft Windows SDK Libraries Paths. + + Return + ------ + list of str + paths + """ + ref = join(self.si.WindowsSdkDir, 'References') + libpath = [] + + if self.vs_ver <= 9.0: + libpath += self.OSLibraries + + if self.vs_ver >= 11.0: + libpath += [join(ref, r'CommonConfiguration\Neutral')] + + if self.vs_ver >= 14.0: + libpath += [ + ref, + join(self.si.WindowsSdkDir, 'UnionMetadata'), + join( + ref, 'Windows.Foundation.UniversalApiContract', '1.0.0.0'), + join(ref, 'Windows.Foundation.FoundationContract', '1.0.0.0'), + join( + ref, 'Windows.Networking.Connectivity.WwanContract', + '1.0.0.0'), + join( + self.si.WindowsSdkDir, 'ExtensionSDKs', 'Microsoft.VCLibs', + '%0.1f' % self.vs_ver, 'References', 'CommonConfiguration', + 'neutral'), + ] + return libpath + + @property + def SdkTools(self): + """ + Microsoft Windows SDK Tools. + + Return + ------ + list of str + paths + """ + return list(self._sdk_tools()) + + def _sdk_tools(self): + """ + Microsoft Windows SDK Tools paths generator. + + Return + ------ + generator of str + paths + """ + if self.vs_ver < 15.0: + bin_dir = 'Bin' if self.vs_ver <= 11.0 else r'Bin\x86' + yield join(self.si.WindowsSdkDir, bin_dir) + + if not self.pi.current_is_x86(): + arch_subdir = self.pi.current_dir(x64=True) + path = 'Bin%s' % arch_subdir + yield join(self.si.WindowsSdkDir, path) + + if self.vs_ver in (10.0, 11.0): + if self.pi.target_is_x86(): + arch_subdir = '' + else: + arch_subdir = self.pi.current_dir(hidex86=True, x64=True) + path = r'Bin\NETFX 4.0 Tools%s' % arch_subdir + yield join(self.si.WindowsSdkDir, path) + + elif self.vs_ver >= 15.0: + path = join(self.si.WindowsSdkDir, 'Bin') + arch_subdir = self.pi.current_dir(x64=True) + sdkver = self.si.WindowsSdkLastVersion + yield join(path, '%s%s' % (sdkver, arch_subdir)) + + if self.si.WindowsSDKExecutablePath: + yield self.si.WindowsSDKExecutablePath + + @property + def _sdk_subdir(self): + """ + Microsoft Windows SDK version subdir. + + Return + ------ + str + subdir + """ + ucrtver = self.si.WindowsSdkLastVersion + return ('%s\\' % ucrtver) if ucrtver else '' + + @property + def SdkSetup(self): + """ + Microsoft Windows SDK Setup. + + Return + ------ + list of str + paths + """ + if self.vs_ver > 9.0: + return [] + + return [join(self.si.WindowsSdkDir, 'Setup')] + + @property + def FxTools(self): + """ + Microsoft .NET Framework Tools. + + Return + ------ + list of str + paths + """ + pi = self.pi + si = self.si + + if self.vs_ver <= 10.0: + include32 = True + include64 = not pi.target_is_x86() and not pi.current_is_x86() + else: + include32 = pi.target_is_x86() or pi.current_is_x86() + include64 = pi.current_cpu == 'amd64' or pi.target_cpu == 'amd64' + + tools = [] + if include32: + tools += [join(si.FrameworkDir32, ver) + for ver in si.FrameworkVersion32] + if include64: + tools += [join(si.FrameworkDir64, ver) + for ver in si.FrameworkVersion64] + return tools + + @property + def NetFxSDKLibraries(self): + """ + Microsoft .Net Framework SDK Libraries. + + Return + ------ + list of str + paths + """ + if self.vs_ver < 14.0 or not self.si.NetFxSdkDir: + return [] + + arch_subdir = self.pi.target_dir(x64=True) + return [join(self.si.NetFxSdkDir, r'lib\um%s' % arch_subdir)] + + @property + def NetFxSDKIncludes(self): + """ + Microsoft .Net Framework SDK Includes. + + Return + ------ + list of str + paths + """ + if self.vs_ver < 14.0 or not self.si.NetFxSdkDir: + return [] + + return [join(self.si.NetFxSdkDir, r'include\um')] + + @property + def VsTDb(self): + """ + Microsoft Visual Studio Team System Database. + + Return + ------ + list of str + paths + """ + return [join(self.si.VSInstallDir, r'VSTSDB\Deploy')] + + @property + def MSBuild(self): + """ + Microsoft Build Engine. + + Return + ------ + list of str + paths + """ + if self.vs_ver < 12.0: + return [] + elif self.vs_ver < 15.0: + base_path = self.si.ProgramFilesx86 + arch_subdir = self.pi.current_dir(hidex86=True) + else: + base_path = self.si.VSInstallDir + arch_subdir = '' + + path = r'MSBuild\%0.1f\bin%s' % (self.vs_ver, arch_subdir) + build = [join(base_path, path)] + + if self.vs_ver >= 15.0: + # Add Roslyn C# & Visual Basic Compiler + build += [join(base_path, path, 'Roslyn')] + + return build + + @property + def HTMLHelpWorkshop(self): + """ + Microsoft HTML Help Workshop. + + Return + ------ + list of str + paths + """ + if self.vs_ver < 11.0: + return [] + + return [join(self.si.ProgramFilesx86, 'HTML Help Workshop')] + + @property + def UCRTLibraries(self): + """ + Microsoft Universal C Runtime SDK Libraries. + + Return + ------ + list of str + paths + """ + if self.vs_ver < 14.0: + return [] + + arch_subdir = self.pi.target_dir(x64=True) + lib = join(self.si.UniversalCRTSdkDir, 'lib') + ucrtver = self._ucrt_subdir + return [join(lib, '%sucrt%s' % (ucrtver, arch_subdir))] + + @property + def UCRTIncludes(self): + """ + Microsoft Universal C Runtime SDK Include. + + Return + ------ + list of str + paths + """ + if self.vs_ver < 14.0: + return [] + + include = join(self.si.UniversalCRTSdkDir, 'include') + return [join(include, '%sucrt' % self._ucrt_subdir)] + + @property + def _ucrt_subdir(self): + """ + Microsoft Universal C Runtime SDK version subdir. + + Return + ------ + str + subdir + """ + ucrtver = self.si.UniversalCRTSdkLastVersion + return ('%s\\' % ucrtver) if ucrtver else '' + + @property + def FSharp(self): + """ + Microsoft Visual F#. + + Return + ------ + list of str + paths + """ + if 11.0 > self.vs_ver > 12.0: + return [] + + return [self.si.FSharpInstallDir] + + @property + def VCRuntimeRedist(self): + """ + Microsoft Visual C++ runtime redistributable dll. + + Return + ------ + str + path + """ + vcruntime = 'vcruntime%d0.dll' % self.vc_ver + arch_subdir = self.pi.target_dir(x64=True).strip('\\') + + # Installation prefixes candidates + prefixes = [] + tools_path = self.si.VCInstallDir + redist_path = dirname(tools_path.replace(r'\Tools', r'\Redist')) + if isdir(redist_path): + # Redist version may not be exactly the same as tools + redist_path = join(redist_path, listdir(redist_path)[-1]) + prefixes += [redist_path, join(redist_path, 'onecore')] + + prefixes += [join(tools_path, 'redist')] # VS14 legacy path + + # CRT directory + crt_dirs = ('Microsoft.VC%d.CRT' % (self.vc_ver * 10), + # Sometime store in directory with VS version instead of VC + 'Microsoft.VC%d.CRT' % (int(self.vs_ver) * 10)) + + # vcruntime path + for prefix, crt_dir in itertools.product(prefixes, crt_dirs): + path = join(prefix, arch_subdir, crt_dir, vcruntime) + if isfile(path): + return path + + def return_env(self, exists=True): + """ + Return environment dict. + + Parameters + ---------- + exists: bool + It True, only return existing paths. + + Return + ------ + dict + environment + """ + env = dict( + include=self._build_paths('include', + [self.VCIncludes, + self.OSIncludes, + self.UCRTIncludes, + self.NetFxSDKIncludes], + exists), + lib=self._build_paths('lib', + [self.VCLibraries, + self.OSLibraries, + self.FxTools, + self.UCRTLibraries, + self.NetFxSDKLibraries], + exists), + libpath=self._build_paths('libpath', + [self.VCLibraries, + self.FxTools, + self.VCStoreRefs, + self.OSLibpath], + exists), + path=self._build_paths('path', + [self.VCTools, + self.VSTools, + self.VsTDb, + self.SdkTools, + self.SdkSetup, + self.FxTools, + self.MSBuild, + self.HTMLHelpWorkshop, + self.FSharp], + exists), + ) + if self.vs_ver >= 14 and isfile(self.VCRuntimeRedist): + env['py_vcruntime_redist'] = self.VCRuntimeRedist + return env + + def _build_paths(self, name, spec_path_lists, exists): + """ + Given an environment variable name and specified paths, + return a pathsep-separated string of paths containing + unique, extant, directories from those paths and from + the environment variable. Raise an error if no paths + are resolved. + + Parameters + ---------- + name: str + Environment variable name + spec_path_lists: list of str + Paths + exists: bool + It True, only return existing paths. + + Return + ------ + str + Pathsep-separated paths + """ + # flatten spec_path_lists + spec_paths = itertools.chain.from_iterable(spec_path_lists) + env_paths = environ.get(name, '').split(pathsep) + paths = itertools.chain(spec_paths, env_paths) + extant_paths = list(filter(isdir, paths)) if exists else paths + if not extant_paths: + msg = "%s environment variable is empty" % name.upper() + raise distutils.errors.DistutilsPlatformError(msg) + unique_paths = unique_everseen(extant_paths) + return pathsep.join(unique_paths) diff --git a/venv/Lib/site-packages/setuptools/namespaces.py b/venv/Lib/site-packages/setuptools/namespaces.py new file mode 100644 index 0000000..44939e1 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/namespaces.py @@ -0,0 +1,107 @@ +import os +from distutils import log +import itertools + + +flatten = itertools.chain.from_iterable + + +class Installer: + + nspkg_ext = '-nspkg.pth' + + def install_namespaces(self): + nsp = self._get_all_ns_packages() + if not nsp: + return + filename, ext = os.path.splitext(self._get_target()) + filename += self.nspkg_ext + self.outputs.append(filename) + log.info("Installing %s", filename) + lines = map(self._gen_nspkg_line, nsp) + + if self.dry_run: + # always generate the lines, even in dry run + list(lines) + return + + with open(filename, 'wt') as f: + f.writelines(lines) + + def uninstall_namespaces(self): + filename, ext = os.path.splitext(self._get_target()) + filename += self.nspkg_ext + if not os.path.exists(filename): + return + log.info("Removing %s", filename) + os.remove(filename) + + def _get_target(self): + return self.target + + _nspkg_tmpl = ( + "import sys, types, os", + "has_mfs = sys.version_info > (3, 5)", + "p = os.path.join(%(root)s, *%(pth)r)", + "importlib = has_mfs and __import__('importlib.util')", + "has_mfs and __import__('importlib.machinery')", + ( + "m = has_mfs and " + "sys.modules.setdefault(%(pkg)r, " + "importlib.util.module_from_spec(" + "importlib.machinery.PathFinder.find_spec(%(pkg)r, " + "[os.path.dirname(p)])))" + ), + ( + "m = m or " + "sys.modules.setdefault(%(pkg)r, types.ModuleType(%(pkg)r))" + ), + "mp = (m or []) and m.__dict__.setdefault('__path__',[])", + "(p not in mp) and mp.append(p)", + ) + "lines for the namespace installer" + + _nspkg_tmpl_multi = ( + 'm and setattr(sys.modules[%(parent)r], %(child)r, m)', + ) + "additional line(s) when a parent package is indicated" + + def _get_root(self): + return "sys._getframe(1).f_locals['sitedir']" + + def _gen_nspkg_line(self, pkg): + pth = tuple(pkg.split('.')) + root = self._get_root() + tmpl_lines = self._nspkg_tmpl + parent, sep, child = pkg.rpartition('.') + if parent: + tmpl_lines += self._nspkg_tmpl_multi + return ';'.join(tmpl_lines) % locals() + '\n' + + def _get_all_ns_packages(self): + """Return sorted list of all package namespaces""" + pkgs = self.distribution.namespace_packages or [] + return sorted(flatten(map(self._pkg_names, pkgs))) + + @staticmethod + def _pkg_names(pkg): + """ + Given a namespace package, yield the components of that + package. + + >>> names = Installer._pkg_names('a.b.c') + >>> set(names) == set(['a', 'a.b', 'a.b.c']) + True + """ + parts = pkg.split('.') + while parts: + yield '.'.join(parts) + parts.pop() + + +class DevelopInstaller(Installer): + def _get_root(self): + return repr(str(self.egg_path)) + + def _get_target(self): + return self.egg_link diff --git a/venv/Lib/site-packages/setuptools/package_index.py b/venv/Lib/site-packages/setuptools/package_index.py new file mode 100644 index 0000000..051e523 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/package_index.py @@ -0,0 +1,1127 @@ +"""PyPI and direct package downloading""" +import sys +import os +import re +import io +import shutil +import socket +import base64 +import hashlib +import itertools +import warnings +import configparser +import html +import http.client +import urllib.parse +import urllib.request +import urllib.error +from functools import wraps + +import setuptools +from pkg_resources import ( + CHECKOUT_DIST, Distribution, BINARY_DIST, normalize_path, SOURCE_DIST, + Environment, find_distributions, safe_name, safe_version, + to_filename, Requirement, DEVELOP_DIST, EGG_DIST, parse_version, +) +from distutils import log +from distutils.errors import DistutilsError +from fnmatch import translate +from setuptools.wheel import Wheel +from setuptools.extern.more_itertools import unique_everseen + + +EGG_FRAGMENT = re.compile(r'^egg=([-A-Za-z0-9_.+!]+)$') +HREF = re.compile(r"""href\s*=\s*['"]?([^'"> ]+)""", re.I) +PYPI_MD5 = re.compile( + r'([^<]+)\n\s+\(md5\)' +) +URL_SCHEME = re.compile('([-+.a-z0-9]{2,}):', re.I).match +EXTENSIONS = ".tar.gz .tar.bz2 .tar .zip .tgz".split() + +__all__ = [ + 'PackageIndex', 'distros_for_url', 'parse_bdist_wininst', + 'interpret_distro_name', +] + +_SOCKET_TIMEOUT = 15 + +_tmpl = "setuptools/{setuptools.__version__} Python-urllib/{py_major}" +user_agent = _tmpl.format( + py_major='{}.{}'.format(*sys.version_info), setuptools=setuptools) + + +def parse_requirement_arg(spec): + try: + return Requirement.parse(spec) + except ValueError as e: + raise DistutilsError( + "Not a URL, existing file, or requirement spec: %r" % (spec,) + ) from e + + +def parse_bdist_wininst(name): + """Return (base,pyversion) or (None,None) for possible .exe name""" + + lower = name.lower() + base, py_ver, plat = None, None, None + + if lower.endswith('.exe'): + if lower.endswith('.win32.exe'): + base = name[:-10] + plat = 'win32' + elif lower.startswith('.win32-py', -16): + py_ver = name[-7:-4] + base = name[:-16] + plat = 'win32' + elif lower.endswith('.win-amd64.exe'): + base = name[:-14] + plat = 'win-amd64' + elif lower.startswith('.win-amd64-py', -20): + py_ver = name[-7:-4] + base = name[:-20] + plat = 'win-amd64' + return base, py_ver, plat + + +def egg_info_for_url(url): + parts = urllib.parse.urlparse(url) + scheme, server, path, parameters, query, fragment = parts + base = urllib.parse.unquote(path.split('/')[-1]) + if server == 'sourceforge.net' and base == 'download': # XXX Yuck + base = urllib.parse.unquote(path.split('/')[-2]) + if '#' in base: + base, fragment = base.split('#', 1) + return base, fragment + + +def distros_for_url(url, metadata=None): + """Yield egg or source distribution objects that might be found at a URL""" + base, fragment = egg_info_for_url(url) + for dist in distros_for_location(url, base, metadata): + yield dist + if fragment: + match = EGG_FRAGMENT.match(fragment) + if match: + for dist in interpret_distro_name( + url, match.group(1), metadata, precedence=CHECKOUT_DIST + ): + yield dist + + +def distros_for_location(location, basename, metadata=None): + """Yield egg or source distribution objects based on basename""" + if basename.endswith('.egg.zip'): + basename = basename[:-4] # strip the .zip + if basename.endswith('.egg') and '-' in basename: + # only one, unambiguous interpretation + return [Distribution.from_location(location, basename, metadata)] + if basename.endswith('.whl') and '-' in basename: + wheel = Wheel(basename) + if not wheel.is_compatible(): + return [] + return [Distribution( + location=location, + project_name=wheel.project_name, + version=wheel.version, + # Increase priority over eggs. + precedence=EGG_DIST + 1, + )] + if basename.endswith('.exe'): + win_base, py_ver, platform = parse_bdist_wininst(basename) + if win_base is not None: + return interpret_distro_name( + location, win_base, metadata, py_ver, BINARY_DIST, platform + ) + # Try source distro extensions (.zip, .tgz, etc.) + # + for ext in EXTENSIONS: + if basename.endswith(ext): + basename = basename[:-len(ext)] + return interpret_distro_name(location, basename, metadata) + return [] # no extension matched + + +def distros_for_filename(filename, metadata=None): + """Yield possible egg or source distribution objects based on a filename""" + return distros_for_location( + normalize_path(filename), os.path.basename(filename), metadata + ) + + +def interpret_distro_name( + location, basename, metadata, py_version=None, precedence=SOURCE_DIST, + platform=None +): + """Generate alternative interpretations of a source distro name + + Note: if `location` is a filesystem filename, you should call + ``pkg_resources.normalize_path()`` on it before passing it to this + routine! + """ + # Generate alternative interpretations of a source distro name + # Because some packages are ambiguous as to name/versions split + # e.g. "adns-python-1.1.0", "egenix-mx-commercial", etc. + # So, we generate each possible interpretation (e.g. "adns, python-1.1.0" + # "adns-python, 1.1.0", and "adns-python-1.1.0, no version"). In practice, + # the spurious interpretations should be ignored, because in the event + # there's also an "adns" package, the spurious "python-1.1.0" version will + # compare lower than any numeric version number, and is therefore unlikely + # to match a request for it. It's still a potential problem, though, and + # in the long run PyPI and the distutils should go for "safe" names and + # versions in distribution archive names (sdist and bdist). + + parts = basename.split('-') + if not py_version and any(re.match(r'py\d\.\d$', p) for p in parts[2:]): + # it is a bdist_dumb, not an sdist -- bail out + return + + for p in range(1, len(parts) + 1): + yield Distribution( + location, metadata, '-'.join(parts[:p]), '-'.join(parts[p:]), + py_version=py_version, precedence=precedence, + platform=platform + ) + + +def unique_values(func): + """ + Wrap a function returning an iterable such that the resulting iterable + only ever yields unique items. + """ + + @wraps(func) + def wrapper(*args, **kwargs): + return unique_everseen(func(*args, **kwargs)) + + return wrapper + + +REL = re.compile(r"""<([^>]*\srel\s*=\s*['"]?([^'">]+)[^>]*)>""", re.I) +# this line is here to fix emacs' cruddy broken syntax highlighting + + +@unique_values +def find_external_links(url, page): + """Find rel="homepage" and rel="download" links in `page`, yielding URLs""" + + for match in REL.finditer(page): + tag, rel = match.groups() + rels = set(map(str.strip, rel.lower().split(','))) + if 'homepage' in rels or 'download' in rels: + for match in HREF.finditer(tag): + yield urllib.parse.urljoin(url, htmldecode(match.group(1))) + + for tag in ("Home Page", "Download URL"): + pos = page.find(tag) + if pos != -1: + match = HREF.search(page, pos) + if match: + yield urllib.parse.urljoin(url, htmldecode(match.group(1))) + + +class ContentChecker: + """ + A null content checker that defines the interface for checking content + """ + + def feed(self, block): + """ + Feed a block of data to the hash. + """ + return + + def is_valid(self): + """ + Check the hash. Return False if validation fails. + """ + return True + + def report(self, reporter, template): + """ + Call reporter with information about the checker (hash name) + substituted into the template. + """ + return + + +class HashChecker(ContentChecker): + pattern = re.compile( + r'(?Psha1|sha224|sha384|sha256|sha512|md5)=' + r'(?P[a-f0-9]+)' + ) + + def __init__(self, hash_name, expected): + self.hash_name = hash_name + self.hash = hashlib.new(hash_name) + self.expected = expected + + @classmethod + def from_url(cls, url): + "Construct a (possibly null) ContentChecker from a URL" + fragment = urllib.parse.urlparse(url)[-1] + if not fragment: + return ContentChecker() + match = cls.pattern.search(fragment) + if not match: + return ContentChecker() + return cls(**match.groupdict()) + + def feed(self, block): + self.hash.update(block) + + def is_valid(self): + return self.hash.hexdigest() == self.expected + + def report(self, reporter, template): + msg = template % self.hash_name + return reporter(msg) + + +class PackageIndex(Environment): + """A distribution index that scans web pages for download URLs""" + + def __init__( + self, index_url="https://pypi.org/simple/", hosts=('*',), + ca_bundle=None, verify_ssl=True, *args, **kw + ): + super().__init__(*args, **kw) + self.index_url = index_url + "/" [:not index_url.endswith('/')] + self.scanned_urls = {} + self.fetched_urls = {} + self.package_pages = {} + self.allows = re.compile('|'.join(map(translate, hosts))).match + self.to_scan = [] + self.opener = urllib.request.urlopen + + def add(self, dist): + # ignore invalid versions + try: + parse_version(dist.version) + except Exception: + return + return super().add(dist) + + # FIXME: 'PackageIndex.process_url' is too complex (14) + def process_url(self, url, retrieve=False): # noqa: C901 + """Evaluate a URL as a possible download, and maybe retrieve it""" + if url in self.scanned_urls and not retrieve: + return + self.scanned_urls[url] = True + if not URL_SCHEME(url): + self.process_filename(url) + return + else: + dists = list(distros_for_url(url)) + if dists: + if not self.url_ok(url): + return + self.debug("Found link: %s", url) + + if dists or not retrieve or url in self.fetched_urls: + list(map(self.add, dists)) + return # don't need the actual page + + if not self.url_ok(url): + self.fetched_urls[url] = True + return + + self.info("Reading %s", url) + self.fetched_urls[url] = True # prevent multiple fetch attempts + tmpl = "Download error on %s: %%s -- Some packages may not be found!" + f = self.open_url(url, tmpl % url) + if f is None: + return + if isinstance(f, urllib.error.HTTPError) and f.code == 401: + self.info("Authentication error: %s" % f.msg) + self.fetched_urls[f.url] = True + if 'html' not in f.headers.get('content-type', '').lower(): + f.close() # not html, we can't process it + return + + base = f.url # handle redirects + page = f.read() + if not isinstance(page, str): + # In Python 3 and got bytes but want str. + if isinstance(f, urllib.error.HTTPError): + # Errors have no charset, assume latin1: + charset = 'latin-1' + else: + charset = f.headers.get_param('charset') or 'latin-1' + page = page.decode(charset, "ignore") + f.close() + for match in HREF.finditer(page): + link = urllib.parse.urljoin(base, htmldecode(match.group(1))) + self.process_url(link) + if url.startswith(self.index_url) and getattr(f, 'code', None) != 404: + page = self.process_index(url, page) + + def process_filename(self, fn, nested=False): + # process filenames or directories + if not os.path.exists(fn): + self.warn("Not found: %s", fn) + return + + if os.path.isdir(fn) and not nested: + path = os.path.realpath(fn) + for item in os.listdir(path): + self.process_filename(os.path.join(path, item), True) + + dists = distros_for_filename(fn) + if dists: + self.debug("Found: %s", fn) + list(map(self.add, dists)) + + def url_ok(self, url, fatal=False): + s = URL_SCHEME(url) + is_file = s and s.group(1).lower() == 'file' + if is_file or self.allows(urllib.parse.urlparse(url)[1]): + return True + msg = ( + "\nNote: Bypassing %s (disallowed host; see " + "http://bit.ly/2hrImnY for details).\n") + if fatal: + raise DistutilsError(msg % url) + else: + self.warn(msg, url) + + def scan_egg_links(self, search_path): + dirs = filter(os.path.isdir, search_path) + egg_links = ( + (path, entry) + for path in dirs + for entry in os.listdir(path) + if entry.endswith('.egg-link') + ) + list(itertools.starmap(self.scan_egg_link, egg_links)) + + def scan_egg_link(self, path, entry): + with open(os.path.join(path, entry)) as raw_lines: + # filter non-empty lines + lines = list(filter(None, map(str.strip, raw_lines))) + + if len(lines) != 2: + # format is not recognized; punt + return + + egg_path, setup_path = lines + + for dist in find_distributions(os.path.join(path, egg_path)): + dist.location = os.path.join(path, *lines) + dist.precedence = SOURCE_DIST + self.add(dist) + + def _scan(self, link): + # Process a URL to see if it's for a package page + NO_MATCH_SENTINEL = None, None + if not link.startswith(self.index_url): + return NO_MATCH_SENTINEL + + parts = list(map( + urllib.parse.unquote, link[len(self.index_url):].split('/') + )) + if len(parts) != 2 or '#' in parts[1]: + return NO_MATCH_SENTINEL + + # it's a package page, sanitize and index it + pkg = safe_name(parts[0]) + ver = safe_version(parts[1]) + self.package_pages.setdefault(pkg.lower(), {})[link] = True + return to_filename(pkg), to_filename(ver) + + def process_index(self, url, page): + """Process the contents of a PyPI page""" + + # process an index page into the package-page index + for match in HREF.finditer(page): + try: + self._scan(urllib.parse.urljoin(url, htmldecode(match.group(1)))) + except ValueError: + pass + + pkg, ver = self._scan(url) # ensure this page is in the page index + if not pkg: + return "" # no sense double-scanning non-package pages + + # process individual package page + for new_url in find_external_links(url, page): + # Process the found URL + base, frag = egg_info_for_url(new_url) + if base.endswith('.py') and not frag: + if ver: + new_url += '#egg=%s-%s' % (pkg, ver) + else: + self.need_version_info(url) + self.scan_url(new_url) + + return PYPI_MD5.sub( + lambda m: '%s' % m.group(1, 3, 2), page + ) + + def need_version_info(self, url): + self.scan_all( + "Page at %s links to .py file(s) without version info; an index " + "scan is required.", url + ) + + def scan_all(self, msg=None, *args): + if self.index_url not in self.fetched_urls: + if msg: + self.warn(msg, *args) + self.info( + "Scanning index of all packages (this may take a while)" + ) + self.scan_url(self.index_url) + + def find_packages(self, requirement): + self.scan_url(self.index_url + requirement.unsafe_name + '/') + + if not self.package_pages.get(requirement.key): + # Fall back to safe version of the name + self.scan_url(self.index_url + requirement.project_name + '/') + + if not self.package_pages.get(requirement.key): + # We couldn't find the target package, so search the index page too + self.not_found_in_index(requirement) + + for url in list(self.package_pages.get(requirement.key, ())): + # scan each page that might be related to the desired package + self.scan_url(url) + + def obtain(self, requirement, installer=None): + self.prescan() + self.find_packages(requirement) + for dist in self[requirement.key]: + if dist in requirement: + return dist + self.debug("%s does not match %s", requirement, dist) + return super(PackageIndex, self).obtain(requirement, installer) + + def check_hash(self, checker, filename, tfp): + """ + checker is a ContentChecker + """ + checker.report( + self.debug, + "Validating %%s checksum for %s" % filename) + if not checker.is_valid(): + tfp.close() + os.unlink(filename) + raise DistutilsError( + "%s validation failed for %s; " + "possible download problem?" + % (checker.hash.name, os.path.basename(filename)) + ) + + def add_find_links(self, urls): + """Add `urls` to the list that will be prescanned for searches""" + for url in urls: + if ( + self.to_scan is None # if we have already "gone online" + or not URL_SCHEME(url) # or it's a local file/directory + or url.startswith('file:') + or list(distros_for_url(url)) # or a direct package link + ): + # then go ahead and process it now + self.scan_url(url) + else: + # otherwise, defer retrieval till later + self.to_scan.append(url) + + def prescan(self): + """Scan urls scheduled for prescanning (e.g. --find-links)""" + if self.to_scan: + list(map(self.scan_url, self.to_scan)) + self.to_scan = None # from now on, go ahead and process immediately + + def not_found_in_index(self, requirement): + if self[requirement.key]: # we've seen at least one distro + meth, msg = self.info, "Couldn't retrieve index page for %r" + else: # no distros seen for this name, might be misspelled + meth, msg = ( + self.warn, + "Couldn't find index page for %r (maybe misspelled?)") + meth(msg, requirement.unsafe_name) + self.scan_all() + + def download(self, spec, tmpdir): + """Locate and/or download `spec` to `tmpdir`, returning a local path + + `spec` may be a ``Requirement`` object, or a string containing a URL, + an existing local filename, or a project/version requirement spec + (i.e. the string form of a ``Requirement`` object). If it is the URL + of a .py file with an unambiguous ``#egg=name-version`` tag (i.e., one + that escapes ``-`` as ``_`` throughout), a trivial ``setup.py`` is + automatically created alongside the downloaded file. + + If `spec` is a ``Requirement`` object or a string containing a + project/version requirement spec, this method returns the location of + a matching distribution (possibly after downloading it to `tmpdir`). + If `spec` is a locally existing file or directory name, it is simply + returned unchanged. If `spec` is a URL, it is downloaded to a subpath + of `tmpdir`, and the local filename is returned. Various errors may be + raised if a problem occurs during downloading. + """ + if not isinstance(spec, Requirement): + scheme = URL_SCHEME(spec) + if scheme: + # It's a url, download it to tmpdir + found = self._download_url(scheme.group(1), spec, tmpdir) + base, fragment = egg_info_for_url(spec) + if base.endswith('.py'): + found = self.gen_setup(found, fragment, tmpdir) + return found + elif os.path.exists(spec): + # Existing file or directory, just return it + return spec + else: + spec = parse_requirement_arg(spec) + return getattr(self.fetch_distribution(spec, tmpdir), 'location', None) + + def fetch_distribution( # noqa: C901 # is too complex (14) # FIXME + self, requirement, tmpdir, force_scan=False, source=False, + develop_ok=False, local_index=None): + """Obtain a distribution suitable for fulfilling `requirement` + + `requirement` must be a ``pkg_resources.Requirement`` instance. + If necessary, or if the `force_scan` flag is set, the requirement is + searched for in the (online) package index as well as the locally + installed packages. If a distribution matching `requirement` is found, + the returned distribution's ``location`` is the value you would have + gotten from calling the ``download()`` method with the matching + distribution's URL or filename. If no matching distribution is found, + ``None`` is returned. + + If the `source` flag is set, only source distributions and source + checkout links will be considered. Unless the `develop_ok` flag is + set, development and system eggs (i.e., those using the ``.egg-info`` + format) will be ignored. + """ + # process a Requirement + self.info("Searching for %s", requirement) + skipped = {} + dist = None + + def find(req, env=None): + if env is None: + env = self + # Find a matching distribution; may be called more than once + + for dist in env[req.key]: + + if dist.precedence == DEVELOP_DIST and not develop_ok: + if dist not in skipped: + self.warn( + "Skipping development or system egg: %s", dist, + ) + skipped[dist] = 1 + continue + + test = ( + dist in req + and (dist.precedence <= SOURCE_DIST or not source) + ) + if test: + loc = self.download(dist.location, tmpdir) + dist.download_location = loc + if os.path.exists(dist.download_location): + return dist + + if force_scan: + self.prescan() + self.find_packages(requirement) + dist = find(requirement) + + if not dist and local_index is not None: + dist = find(requirement, local_index) + + if dist is None: + if self.to_scan is not None: + self.prescan() + dist = find(requirement) + + if dist is None and not force_scan: + self.find_packages(requirement) + dist = find(requirement) + + if dist is None: + self.warn( + "No local packages or working download links found for %s%s", + (source and "a source distribution of " or ""), + requirement, + ) + else: + self.info("Best match: %s", dist) + return dist.clone(location=dist.download_location) + + def fetch(self, requirement, tmpdir, force_scan=False, source=False): + """Obtain a file suitable for fulfilling `requirement` + + DEPRECATED; use the ``fetch_distribution()`` method now instead. For + backward compatibility, this routine is identical but returns the + ``location`` of the downloaded distribution instead of a distribution + object. + """ + dist = self.fetch_distribution(requirement, tmpdir, force_scan, source) + if dist is not None: + return dist.location + return None + + def gen_setup(self, filename, fragment, tmpdir): + match = EGG_FRAGMENT.match(fragment) + dists = match and [ + d for d in + interpret_distro_name(filename, match.group(1), None) if d.version + ] or [] + + if len(dists) == 1: # unambiguous ``#egg`` fragment + basename = os.path.basename(filename) + + # Make sure the file has been downloaded to the temp dir. + if os.path.dirname(filename) != tmpdir: + dst = os.path.join(tmpdir, basename) + from setuptools.command.easy_install import samefile + if not samefile(filename, dst): + shutil.copy2(filename, dst) + filename = dst + + with open(os.path.join(tmpdir, 'setup.py'), 'w') as file: + file.write( + "from setuptools import setup\n" + "setup(name=%r, version=%r, py_modules=[%r])\n" + % ( + dists[0].project_name, dists[0].version, + os.path.splitext(basename)[0] + ) + ) + return filename + + elif match: + raise DistutilsError( + "Can't unambiguously interpret project/version identifier %r; " + "any dashes in the name or version should be escaped using " + "underscores. %r" % (fragment, dists) + ) + else: + raise DistutilsError( + "Can't process plain .py files without an '#egg=name-version'" + " suffix to enable automatic setup script generation." + ) + + dl_blocksize = 8192 + + def _download_to(self, url, filename): + self.info("Downloading %s", url) + # Download the file + fp = None + try: + checker = HashChecker.from_url(url) + fp = self.open_url(url) + if isinstance(fp, urllib.error.HTTPError): + raise DistutilsError( + "Can't download %s: %s %s" % (url, fp.code, fp.msg) + ) + headers = fp.info() + blocknum = 0 + bs = self.dl_blocksize + size = -1 + if "content-length" in headers: + # Some servers return multiple Content-Length headers :( + sizes = headers.get_all('Content-Length') + size = max(map(int, sizes)) + self.reporthook(url, filename, blocknum, bs, size) + with open(filename, 'wb') as tfp: + while True: + block = fp.read(bs) + if block: + checker.feed(block) + tfp.write(block) + blocknum += 1 + self.reporthook(url, filename, blocknum, bs, size) + else: + break + self.check_hash(checker, filename, tfp) + return headers + finally: + if fp: + fp.close() + + def reporthook(self, url, filename, blocknum, blksize, size): + pass # no-op + + # FIXME: + def open_url(self, url, warning=None): # noqa: C901 # is too complex (12) + if url.startswith('file:'): + return local_open(url) + try: + return open_with_auth(url, self.opener) + except (ValueError, http.client.InvalidURL) as v: + msg = ' '.join([str(arg) for arg in v.args]) + if warning: + self.warn(warning, msg) + else: + raise DistutilsError('%s %s' % (url, msg)) from v + except urllib.error.HTTPError as v: + return v + except urllib.error.URLError as v: + if warning: + self.warn(warning, v.reason) + else: + raise DistutilsError("Download error for %s: %s" + % (url, v.reason)) from v + except http.client.BadStatusLine as v: + if warning: + self.warn(warning, v.line) + else: + raise DistutilsError( + '%s returned a bad status line. The server might be ' + 'down, %s' % + (url, v.line) + ) from v + except (http.client.HTTPException, socket.error) as v: + if warning: + self.warn(warning, v) + else: + raise DistutilsError("Download error for %s: %s" + % (url, v)) from v + + def _download_url(self, scheme, url, tmpdir): + # Determine download filename + # + name, fragment = egg_info_for_url(url) + if name: + while '..' in name: + name = name.replace('..', '.').replace('\\', '_') + else: + name = "__downloaded__" # default if URL has no path contents + + if name.endswith('.egg.zip'): + name = name[:-4] # strip the extra .zip before download + + filename = os.path.join(tmpdir, name) + + # Download the file + # + if scheme == 'svn' or scheme.startswith('svn+'): + return self._download_svn(url, filename) + elif scheme == 'git' or scheme.startswith('git+'): + return self._download_git(url, filename) + elif scheme.startswith('hg+'): + return self._download_hg(url, filename) + elif scheme == 'file': + return urllib.request.url2pathname(urllib.parse.urlparse(url)[2]) + else: + self.url_ok(url, True) # raises error if not allowed + return self._attempt_download(url, filename) + + def scan_url(self, url): + self.process_url(url, True) + + def _attempt_download(self, url, filename): + headers = self._download_to(url, filename) + if 'html' in headers.get('content-type', '').lower(): + return self._download_html(url, headers, filename) + else: + return filename + + def _download_html(self, url, headers, filename): + file = open(filename) + for line in file: + if line.strip(): + # Check for a subversion index page + if re.search(r'([^- ]+ - )?Revision \d+:', line): + # it's a subversion index page: + file.close() + os.unlink(filename) + return self._download_svn(url, filename) + break # not an index page + file.close() + os.unlink(filename) + raise DistutilsError("Unexpected HTML page found at " + url) + + def _download_svn(self, url, filename): + warnings.warn("SVN download support is deprecated", UserWarning) + url = url.split('#', 1)[0] # remove any fragment for svn's sake + creds = '' + if url.lower().startswith('svn:') and '@' in url: + scheme, netloc, path, p, q, f = urllib.parse.urlparse(url) + if not netloc and path.startswith('//') and '/' in path[2:]: + netloc, path = path[2:].split('/', 1) + auth, host = _splituser(netloc) + if auth: + if ':' in auth: + user, pw = auth.split(':', 1) + creds = " --username=%s --password=%s" % (user, pw) + else: + creds = " --username=" + auth + netloc = host + parts = scheme, netloc, url, p, q, f + url = urllib.parse.urlunparse(parts) + self.info("Doing subversion checkout from %s to %s", url, filename) + os.system("svn checkout%s -q %s %s" % (creds, url, filename)) + return filename + + @staticmethod + def _vcs_split_rev_from_url(url, pop_prefix=False): + scheme, netloc, path, query, frag = urllib.parse.urlsplit(url) + + scheme = scheme.split('+', 1)[-1] + + # Some fragment identification fails + path = path.split('#', 1)[0] + + rev = None + if '@' in path: + path, rev = path.rsplit('@', 1) + + # Also, discard fragment + url = urllib.parse.urlunsplit((scheme, netloc, path, query, '')) + + return url, rev + + def _download_git(self, url, filename): + filename = filename.split('#', 1)[0] + url, rev = self._vcs_split_rev_from_url(url, pop_prefix=True) + + self.info("Doing git clone from %s to %s", url, filename) + os.system("git clone --quiet %s %s" % (url, filename)) + + if rev is not None: + self.info("Checking out %s", rev) + os.system("git -C %s checkout --quiet %s" % ( + filename, + rev, + )) + + return filename + + def _download_hg(self, url, filename): + filename = filename.split('#', 1)[0] + url, rev = self._vcs_split_rev_from_url(url, pop_prefix=True) + + self.info("Doing hg clone from %s to %s", url, filename) + os.system("hg clone --quiet %s %s" % (url, filename)) + + if rev is not None: + self.info("Updating to %s", rev) + os.system("hg --cwd %s up -C -r %s -q" % ( + filename, + rev, + )) + + return filename + + def debug(self, msg, *args): + log.debug(msg, *args) + + def info(self, msg, *args): + log.info(msg, *args) + + def warn(self, msg, *args): + log.warn(msg, *args) + + +# This pattern matches a character entity reference (a decimal numeric +# references, a hexadecimal numeric reference, or a named reference). +entity_sub = re.compile(r'&(#(\d+|x[\da-fA-F]+)|[\w.:-]+);?').sub + + +def decode_entity(match): + what = match.group(0) + return html.unescape(what) + + +def htmldecode(text): + """ + Decode HTML entities in the given text. + + >>> htmldecode( + ... 'https://../package_name-0.1.2.tar.gz' + ... '?tokena=A&tokenb=B">package_name-0.1.2.tar.gz') + 'https://../package_name-0.1.2.tar.gz?tokena=A&tokenb=B">package_name-0.1.2.tar.gz' + """ + return entity_sub(decode_entity, text) + + +def socket_timeout(timeout=15): + def _socket_timeout(func): + def _socket_timeout(*args, **kwargs): + old_timeout = socket.getdefaulttimeout() + socket.setdefaulttimeout(timeout) + try: + return func(*args, **kwargs) + finally: + socket.setdefaulttimeout(old_timeout) + + return _socket_timeout + + return _socket_timeout + + +def _encode_auth(auth): + """ + Encode auth from a URL suitable for an HTTP header. + >>> str(_encode_auth('username%3Apassword')) + 'dXNlcm5hbWU6cGFzc3dvcmQ=' + + Long auth strings should not cause a newline to be inserted. + >>> long_auth = 'username:' + 'password'*10 + >>> chr(10) in str(_encode_auth(long_auth)) + False + """ + auth_s = urllib.parse.unquote(auth) + # convert to bytes + auth_bytes = auth_s.encode() + encoded_bytes = base64.b64encode(auth_bytes) + # convert back to a string + encoded = encoded_bytes.decode() + # strip the trailing carriage return + return encoded.replace('\n', '') + + +class Credential: + """ + A username/password pair. Use like a namedtuple. + """ + + def __init__(self, username, password): + self.username = username + self.password = password + + def __iter__(self): + yield self.username + yield self.password + + def __str__(self): + return '%(username)s:%(password)s' % vars(self) + + +class PyPIConfig(configparser.RawConfigParser): + def __init__(self): + """ + Load from ~/.pypirc + """ + defaults = dict.fromkeys(['username', 'password', 'repository'], '') + super().__init__(defaults) + + rc = os.path.join(os.path.expanduser('~'), '.pypirc') + if os.path.exists(rc): + self.read(rc) + + @property + def creds_by_repository(self): + sections_with_repositories = [ + section for section in self.sections() + if self.get(section, 'repository').strip() + ] + + return dict(map(self._get_repo_cred, sections_with_repositories)) + + def _get_repo_cred(self, section): + repo = self.get(section, 'repository').strip() + return repo, Credential( + self.get(section, 'username').strip(), + self.get(section, 'password').strip(), + ) + + def find_credential(self, url): + """ + If the URL indicated appears to be a repository defined in this + config, return the credential for that repository. + """ + for repository, cred in self.creds_by_repository.items(): + if url.startswith(repository): + return cred + + +def open_with_auth(url, opener=urllib.request.urlopen): + """Open a urllib2 request, handling HTTP authentication""" + + parsed = urllib.parse.urlparse(url) + scheme, netloc, path, params, query, frag = parsed + + # Double scheme does not raise on macOS as revealed by a + # failing test. We would expect "nonnumeric port". Refs #20. + if netloc.endswith(':'): + raise http.client.InvalidURL("nonnumeric port: ''") + + if scheme in ('http', 'https'): + auth, address = _splituser(netloc) + else: + auth = None + + if not auth: + cred = PyPIConfig().find_credential(url) + if cred: + auth = str(cred) + info = cred.username, url + log.info('Authenticating as %s for %s (from .pypirc)', *info) + + if auth: + auth = "Basic " + _encode_auth(auth) + parts = scheme, address, path, params, query, frag + new_url = urllib.parse.urlunparse(parts) + request = urllib.request.Request(new_url) + request.add_header("Authorization", auth) + else: + request = urllib.request.Request(url) + + request.add_header('User-Agent', user_agent) + fp = opener(request) + + if auth: + # Put authentication info back into request URL if same host, + # so that links found on the page will work + s2, h2, path2, param2, query2, frag2 = urllib.parse.urlparse(fp.url) + if s2 == scheme and h2 == address: + parts = s2, netloc, path2, param2, query2, frag2 + fp.url = urllib.parse.urlunparse(parts) + + return fp + + +# copy of urllib.parse._splituser from Python 3.8 +def _splituser(host): + """splituser('user[:passwd]@host[:port]') + --> 'user[:passwd]', 'host[:port]'.""" + user, delim, host = host.rpartition('@') + return (user if delim else None), host + + +# adding a timeout to avoid freezing package_index +open_with_auth = socket_timeout(_SOCKET_TIMEOUT)(open_with_auth) + + +def fix_sf_url(url): + return url # backward compatibility + + +def local_open(url): + """Read a local path, with special support for directories""" + scheme, server, path, param, query, frag = urllib.parse.urlparse(url) + filename = urllib.request.url2pathname(path) + if os.path.isfile(filename): + return urllib.request.urlopen(url) + elif path.endswith('/') and os.path.isdir(filename): + files = [] + for f in os.listdir(filename): + filepath = os.path.join(filename, f) + if f == 'index.html': + with open(filepath, 'r') as fp: + body = fp.read() + break + elif os.path.isdir(filepath): + f += '/' + files.append('<a href="{name}">{name}</a>'.format(name=f)) + else: + tmpl = ( + "<html><head><title>{url}" + "{files}") + body = tmpl.format(url=url, files='\n'.join(files)) + status, message = 200, "OK" + else: + status, message, body = 404, "Path not found", "Not found" + + headers = {'content-type': 'text/html'} + body_stream = io.StringIO(body) + return urllib.error.HTTPError(url, status, message, headers, body_stream) diff --git a/venv/Lib/site-packages/setuptools/py34compat.py b/venv/Lib/site-packages/setuptools/py34compat.py new file mode 100644 index 0000000..3ad9172 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/py34compat.py @@ -0,0 +1,13 @@ +import importlib + +try: + import importlib.util +except ImportError: + pass + + +try: + module_from_spec = importlib.util.module_from_spec +except AttributeError: + def module_from_spec(spec): + return spec.loader.load_module(spec.name) diff --git a/venv/Lib/site-packages/setuptools/sandbox.py b/venv/Lib/site-packages/setuptools/sandbox.py new file mode 100644 index 0000000..034fc80 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/sandbox.py @@ -0,0 +1,530 @@ +import os +import sys +import tempfile +import operator +import functools +import itertools +import re +import contextlib +import pickle +import textwrap +import builtins + +import pkg_resources +from distutils.errors import DistutilsError +from pkg_resources import working_set + +if sys.platform.startswith('java'): + import org.python.modules.posix.PosixModule as _os +else: + _os = sys.modules[os.name] +try: + _file = file +except NameError: + _file = None +_open = open + + +__all__ = [ + "AbstractSandbox", + "DirectorySandbox", + "SandboxViolation", + "run_setup", +] + + +def _execfile(filename, globals, locals=None): + """ + Python 3 implementation of execfile. + """ + mode = 'rb' + with open(filename, mode) as stream: + script = stream.read() + if locals is None: + locals = globals + code = compile(script, filename, 'exec') + exec(code, globals, locals) + + +@contextlib.contextmanager +def save_argv(repl=None): + saved = sys.argv[:] + if repl is not None: + sys.argv[:] = repl + try: + yield saved + finally: + sys.argv[:] = saved + + +@contextlib.contextmanager +def save_path(): + saved = sys.path[:] + try: + yield saved + finally: + sys.path[:] = saved + + +@contextlib.contextmanager +def override_temp(replacement): + """ + Monkey-patch tempfile.tempdir with replacement, ensuring it exists + """ + os.makedirs(replacement, exist_ok=True) + + saved = tempfile.tempdir + + tempfile.tempdir = replacement + + try: + yield + finally: + tempfile.tempdir = saved + + +@contextlib.contextmanager +def pushd(target): + saved = os.getcwd() + os.chdir(target) + try: + yield saved + finally: + os.chdir(saved) + + +class UnpickleableException(Exception): + """ + An exception representing another Exception that could not be pickled. + """ + + @staticmethod + def dump(type, exc): + """ + Always return a dumped (pickled) type and exc. If exc can't be pickled, + wrap it in UnpickleableException first. + """ + try: + return pickle.dumps(type), pickle.dumps(exc) + except Exception: + # get UnpickleableException inside the sandbox + from setuptools.sandbox import UnpickleableException as cls + + return cls.dump(cls, cls(repr(exc))) + + +class ExceptionSaver: + """ + A Context Manager that will save an exception, serialized, and restore it + later. + """ + + def __enter__(self): + return self + + def __exit__(self, type, exc, tb): + if not exc: + return + + # dump the exception + self._saved = UnpickleableException.dump(type, exc) + self._tb = tb + + # suppress the exception + return True + + def resume(self): + "restore and re-raise any exception" + + if '_saved' not in vars(self): + return + + type, exc = map(pickle.loads, self._saved) + raise exc.with_traceback(self._tb) + + +@contextlib.contextmanager +def save_modules(): + """ + Context in which imported modules are saved. + + Translates exceptions internal to the context into the equivalent exception + outside the context. + """ + saved = sys.modules.copy() + with ExceptionSaver() as saved_exc: + yield saved + + sys.modules.update(saved) + # remove any modules imported since + del_modules = ( + mod_name + for mod_name in sys.modules + if mod_name not in saved + # exclude any encodings modules. See #285 + and not mod_name.startswith('encodings.') + ) + _clear_modules(del_modules) + + saved_exc.resume() + + +def _clear_modules(module_names): + for mod_name in list(module_names): + del sys.modules[mod_name] + + +@contextlib.contextmanager +def save_pkg_resources_state(): + saved = pkg_resources.__getstate__() + try: + yield saved + finally: + pkg_resources.__setstate__(saved) + + +@contextlib.contextmanager +def setup_context(setup_dir): + temp_dir = os.path.join(setup_dir, 'temp') + with save_pkg_resources_state(): + with save_modules(): + with save_path(): + hide_setuptools() + with save_argv(): + with override_temp(temp_dir): + with pushd(setup_dir): + # ensure setuptools commands are available + __import__('setuptools') + yield + + +_MODULES_TO_HIDE = { + 'setuptools', + 'distutils', + 'pkg_resources', + 'Cython', + '_distutils_hack', +} + + +def _needs_hiding(mod_name): + """ + >>> _needs_hiding('setuptools') + True + >>> _needs_hiding('pkg_resources') + True + >>> _needs_hiding('setuptools_plugin') + False + >>> _needs_hiding('setuptools.__init__') + True + >>> _needs_hiding('distutils') + True + >>> _needs_hiding('os') + False + >>> _needs_hiding('Cython') + True + """ + base_module = mod_name.split('.', 1)[0] + return base_module in _MODULES_TO_HIDE + + +def hide_setuptools(): + """ + Remove references to setuptools' modules from sys.modules to allow the + invocation to import the most appropriate setuptools. This technique is + necessary to avoid issues such as #315 where setuptools upgrading itself + would fail to find a function declared in the metadata. + """ + _distutils_hack = sys.modules.get('_distutils_hack', None) + if _distutils_hack is not None: + _distutils_hack.remove_shim() + + modules = filter(_needs_hiding, sys.modules) + _clear_modules(modules) + + +def run_setup(setup_script, args): + """Run a distutils setup script, sandboxed in its directory""" + setup_dir = os.path.abspath(os.path.dirname(setup_script)) + with setup_context(setup_dir): + try: + sys.argv[:] = [setup_script] + list(args) + sys.path.insert(0, setup_dir) + # reset to include setup dir, w/clean callback list + working_set.__init__() + working_set.callbacks.append(lambda dist: dist.activate()) + + with DirectorySandbox(setup_dir): + ns = dict(__file__=setup_script, __name__='__main__') + _execfile(setup_script, ns) + except SystemExit as v: + if v.args and v.args[0]: + raise + # Normal exit, just return + + +class AbstractSandbox: + """Wrap 'os' module and 'open()' builtin for virtualizing setup scripts""" + + _active = False + + def __init__(self): + self._attrs = [ + name + for name in dir(_os) + if not name.startswith('_') and hasattr(self, name) + ] + + def _copy(self, source): + for name in self._attrs: + setattr(os, name, getattr(source, name)) + + def __enter__(self): + self._copy(self) + if _file: + builtins.file = self._file + builtins.open = self._open + self._active = True + + def __exit__(self, exc_type, exc_value, traceback): + self._active = False + if _file: + builtins.file = _file + builtins.open = _open + self._copy(_os) + + def run(self, func): + """Run 'func' under os sandboxing""" + with self: + return func() + + def _mk_dual_path_wrapper(name): + original = getattr(_os, name) + + def wrap(self, src, dst, *args, **kw): + if self._active: + src, dst = self._remap_pair(name, src, dst, *args, **kw) + return original(src, dst, *args, **kw) + + return wrap + + for name in ["rename", "link", "symlink"]: + if hasattr(_os, name): + locals()[name] = _mk_dual_path_wrapper(name) + + def _mk_single_path_wrapper(name, original=None): + original = original or getattr(_os, name) + + def wrap(self, path, *args, **kw): + if self._active: + path = self._remap_input(name, path, *args, **kw) + return original(path, *args, **kw) + + return wrap + + if _file: + _file = _mk_single_path_wrapper('file', _file) + _open = _mk_single_path_wrapper('open', _open) + for name in [ + "stat", + "listdir", + "chdir", + "open", + "chmod", + "chown", + "mkdir", + "remove", + "unlink", + "rmdir", + "utime", + "lchown", + "chroot", + "lstat", + "startfile", + "mkfifo", + "mknod", + "pathconf", + "access", + ]: + if hasattr(_os, name): + locals()[name] = _mk_single_path_wrapper(name) + + def _mk_single_with_return(name): + original = getattr(_os, name) + + def wrap(self, path, *args, **kw): + if self._active: + path = self._remap_input(name, path, *args, **kw) + return self._remap_output(name, original(path, *args, **kw)) + return original(path, *args, **kw) + + return wrap + + for name in ['readlink', 'tempnam']: + if hasattr(_os, name): + locals()[name] = _mk_single_with_return(name) + + def _mk_query(name): + original = getattr(_os, name) + + def wrap(self, *args, **kw): + retval = original(*args, **kw) + if self._active: + return self._remap_output(name, retval) + return retval + + return wrap + + for name in ['getcwd', 'tmpnam']: + if hasattr(_os, name): + locals()[name] = _mk_query(name) + + def _validate_path(self, path): + """Called to remap or validate any path, whether input or output""" + return path + + def _remap_input(self, operation, path, *args, **kw): + """Called for path inputs""" + return self._validate_path(path) + + def _remap_output(self, operation, path): + """Called for path outputs""" + return self._validate_path(path) + + def _remap_pair(self, operation, src, dst, *args, **kw): + """Called for path pairs like rename, link, and symlink operations""" + return ( + self._remap_input(operation + '-from', src, *args, **kw), + self._remap_input(operation + '-to', dst, *args, **kw), + ) + + +if hasattr(os, 'devnull'): + _EXCEPTIONS = [os.devnull] +else: + _EXCEPTIONS = [] + + +class DirectorySandbox(AbstractSandbox): + """Restrict operations to a single subdirectory - pseudo-chroot""" + + write_ops = dict.fromkeys( + [ + "open", + "chmod", + "chown", + "mkdir", + "remove", + "unlink", + "rmdir", + "utime", + "lchown", + "chroot", + "mkfifo", + "mknod", + "tempnam", + ] + ) + + _exception_patterns = [] + "exempt writing to paths that match the pattern" + + def __init__(self, sandbox, exceptions=_EXCEPTIONS): + self._sandbox = os.path.normcase(os.path.realpath(sandbox)) + self._prefix = os.path.join(self._sandbox, '') + self._exceptions = [ + os.path.normcase(os.path.realpath(path)) for path in exceptions + ] + AbstractSandbox.__init__(self) + + def _violation(self, operation, *args, **kw): + from setuptools.sandbox import SandboxViolation + + raise SandboxViolation(operation, args, kw) + + if _file: + + def _file(self, path, mode='r', *args, **kw): + if mode not in ('r', 'rt', 'rb', 'rU', 'U') and not self._ok(path): + self._violation("file", path, mode, *args, **kw) + return _file(path, mode, *args, **kw) + + def _open(self, path, mode='r', *args, **kw): + if mode not in ('r', 'rt', 'rb', 'rU', 'U') and not self._ok(path): + self._violation("open", path, mode, *args, **kw) + return _open(path, mode, *args, **kw) + + def tmpnam(self): + self._violation("tmpnam") + + def _ok(self, path): + active = self._active + try: + self._active = False + realpath = os.path.normcase(os.path.realpath(path)) + return ( + self._exempted(realpath) + or realpath == self._sandbox + or realpath.startswith(self._prefix) + ) + finally: + self._active = active + + def _exempted(self, filepath): + start_matches = ( + filepath.startswith(exception) for exception in self._exceptions + ) + pattern_matches = ( + re.match(pattern, filepath) for pattern in self._exception_patterns + ) + candidates = itertools.chain(start_matches, pattern_matches) + return any(candidates) + + def _remap_input(self, operation, path, *args, **kw): + """Called for path inputs""" + if operation in self.write_ops and not self._ok(path): + self._violation(operation, os.path.realpath(path), *args, **kw) + return path + + def _remap_pair(self, operation, src, dst, *args, **kw): + """Called for path pairs like rename, link, and symlink operations""" + if not self._ok(src) or not self._ok(dst): + self._violation(operation, src, dst, *args, **kw) + return (src, dst) + + def open(self, file, flags, mode=0o777, *args, **kw): + """Called for low-level os.open()""" + if flags & WRITE_FLAGS and not self._ok(file): + self._violation("os.open", file, flags, mode, *args, **kw) + return _os.open(file, flags, mode, *args, **kw) + + +WRITE_FLAGS = functools.reduce( + operator.or_, + [ + getattr(_os, a, 0) + for a in "O_WRONLY O_RDWR O_APPEND O_CREAT O_TRUNC O_TEMPORARY".split() + ], +) + + +class SandboxViolation(DistutilsError): + """A setup script attempted to modify the filesystem outside the sandbox""" + + tmpl = textwrap.dedent( + """ + SandboxViolation: {cmd}{args!r} {kwargs} + + The package setup script has attempted to modify files on your system + that are not within the EasyInstall build area, and has been aborted. + + This package cannot be safely installed by EasyInstall, and may not + support alternate installation locations even if you run its setup + script by hand. Please inform the package's author and the EasyInstall + maintainers to find out if a fix or workaround is available. + """ + ).lstrip() + + def __str__(self): + cmd, args, kwargs = self.args + return self.tmpl.format(**locals()) diff --git a/venv/Lib/site-packages/setuptools/script (dev).tmpl b/venv/Lib/site-packages/setuptools/script (dev).tmpl new file mode 100644 index 0000000..39a24b0 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/script (dev).tmpl @@ -0,0 +1,6 @@ +# EASY-INSTALL-DEV-SCRIPT: %(spec)r,%(script_name)r +__requires__ = %(spec)r +__import__('pkg_resources').require(%(spec)r) +__file__ = %(dev_path)r +with open(__file__) as f: + exec(compile(f.read(), __file__, 'exec')) diff --git a/venv/Lib/site-packages/setuptools/script.tmpl b/venv/Lib/site-packages/setuptools/script.tmpl new file mode 100644 index 0000000..ff5efbc --- /dev/null +++ b/venv/Lib/site-packages/setuptools/script.tmpl @@ -0,0 +1,3 @@ +# EASY-INSTALL-SCRIPT: %(spec)r,%(script_name)r +__requires__ = %(spec)r +__import__('pkg_resources').run_script(%(spec)r, %(script_name)r) diff --git a/venv/Lib/site-packages/setuptools/unicode_utils.py b/venv/Lib/site-packages/setuptools/unicode_utils.py new file mode 100644 index 0000000..e84e65e --- /dev/null +++ b/venv/Lib/site-packages/setuptools/unicode_utils.py @@ -0,0 +1,42 @@ +import unicodedata +import sys + + +# HFS Plus uses decomposed UTF-8 +def decompose(path): + if isinstance(path, str): + return unicodedata.normalize('NFD', path) + try: + path = path.decode('utf-8') + path = unicodedata.normalize('NFD', path) + path = path.encode('utf-8') + except UnicodeError: + pass # Not UTF-8 + return path + + +def filesys_decode(path): + """ + Ensure that the given path is decoded, + NONE when no expected encoding works + """ + + if isinstance(path, str): + return path + + fs_enc = sys.getfilesystemencoding() or 'utf-8' + candidates = fs_enc, 'utf-8' + + for enc in candidates: + try: + return path.decode(enc) + except UnicodeDecodeError: + continue + + +def try_encode(string, enc): + "turn unicode encoding into a functional routine" + try: + return string.encode(enc) + except UnicodeEncodeError: + return None diff --git a/venv/Lib/site-packages/setuptools/version.py b/venv/Lib/site-packages/setuptools/version.py new file mode 100644 index 0000000..95e1869 --- /dev/null +++ b/venv/Lib/site-packages/setuptools/version.py @@ -0,0 +1,6 @@ +import pkg_resources + +try: + __version__ = pkg_resources.get_distribution('setuptools').version +except Exception: + __version__ = 'unknown' diff --git a/venv/Lib/site-packages/setuptools/wheel.py b/venv/Lib/site-packages/setuptools/wheel.py new file mode 100644 index 0000000..9819e8b --- /dev/null +++ b/venv/Lib/site-packages/setuptools/wheel.py @@ -0,0 +1,213 @@ +"""Wheels support.""" + +from distutils.util import get_platform +from distutils import log +import email +import itertools +import os +import posixpath +import re +import zipfile + +import pkg_resources +import setuptools +from pkg_resources import parse_version +from setuptools.extern.packaging.tags import sys_tags +from setuptools.extern.packaging.utils import canonicalize_name +from setuptools.command.egg_info import write_requirements + + +WHEEL_NAME = re.compile( + r"""^(?P.+?)-(?P\d.*?) + ((-(?P\d.*?))?-(?P.+?)-(?P.+?)-(?P.+?) + )\.whl$""", + re.VERBOSE).match + +NAMESPACE_PACKAGE_INIT = \ + "__import__('pkg_resources').declare_namespace(__name__)\n" + + +def unpack(src_dir, dst_dir): + '''Move everything under `src_dir` to `dst_dir`, and delete the former.''' + for dirpath, dirnames, filenames in os.walk(src_dir): + subdir = os.path.relpath(dirpath, src_dir) + for f in filenames: + src = os.path.join(dirpath, f) + dst = os.path.join(dst_dir, subdir, f) + os.renames(src, dst) + for n, d in reversed(list(enumerate(dirnames))): + src = os.path.join(dirpath, d) + dst = os.path.join(dst_dir, subdir, d) + if not os.path.exists(dst): + # Directory does not exist in destination, + # rename it and prune it from os.walk list. + os.renames(src, dst) + del dirnames[n] + # Cleanup. + for dirpath, dirnames, filenames in os.walk(src_dir, topdown=True): + assert not filenames + os.rmdir(dirpath) + + +class Wheel: + + def __init__(self, filename): + match = WHEEL_NAME(os.path.basename(filename)) + if match is None: + raise ValueError('invalid wheel name: %r' % filename) + self.filename = filename + for k, v in match.groupdict().items(): + setattr(self, k, v) + + def tags(self): + '''List tags (py_version, abi, platform) supported by this wheel.''' + return itertools.product( + self.py_version.split('.'), + self.abi.split('.'), + self.platform.split('.'), + ) + + def is_compatible(self): + '''Is the wheel is compatible with the current platform?''' + supported_tags = set( + (t.interpreter, t.abi, t.platform) for t in sys_tags()) + return next((True for t in self.tags() if t in supported_tags), False) + + def egg_name(self): + return pkg_resources.Distribution( + project_name=self.project_name, version=self.version, + platform=(None if self.platform == 'any' else get_platform()), + ).egg_name() + '.egg' + + def get_dist_info(self, zf): + # find the correct name of the .dist-info dir in the wheel file + for member in zf.namelist(): + dirname = posixpath.dirname(member) + if (dirname.endswith('.dist-info') and + canonicalize_name(dirname).startswith( + canonicalize_name(self.project_name))): + return dirname + raise ValueError("unsupported wheel format. .dist-info not found") + + def install_as_egg(self, destination_eggdir): + '''Install wheel as an egg directory.''' + with zipfile.ZipFile(self.filename) as zf: + self._install_as_egg(destination_eggdir, zf) + + def _install_as_egg(self, destination_eggdir, zf): + dist_basename = '%s-%s' % (self.project_name, self.version) + dist_info = self.get_dist_info(zf) + dist_data = '%s.data' % dist_basename + egg_info = os.path.join(destination_eggdir, 'EGG-INFO') + + self._convert_metadata(zf, destination_eggdir, dist_info, egg_info) + self._move_data_entries(destination_eggdir, dist_data) + self._fix_namespace_packages(egg_info, destination_eggdir) + + @staticmethod + def _convert_metadata(zf, destination_eggdir, dist_info, egg_info): + def get_metadata(name): + with zf.open(posixpath.join(dist_info, name)) as fp: + value = fp.read().decode('utf-8') + return email.parser.Parser().parsestr(value) + + wheel_metadata = get_metadata('WHEEL') + # Check wheel format version is supported. + wheel_version = parse_version(wheel_metadata.get('Wheel-Version')) + wheel_v1 = ( + parse_version('1.0') <= wheel_version < parse_version('2.0dev0') + ) + if not wheel_v1: + raise ValueError( + 'unsupported wheel format version: %s' % wheel_version) + # Extract to target directory. + os.mkdir(destination_eggdir) + zf.extractall(destination_eggdir) + # Convert metadata. + dist_info = os.path.join(destination_eggdir, dist_info) + dist = pkg_resources.Distribution.from_location( + destination_eggdir, dist_info, + metadata=pkg_resources.PathMetadata(destination_eggdir, dist_info), + ) + + # Note: Evaluate and strip markers now, + # as it's difficult to convert back from the syntax: + # foobar; "linux" in sys_platform and extra == 'test' + def raw_req(req): + req.marker = None + return str(req) + install_requires = list(map(raw_req, dist.requires())) + extras_require = { + extra: [ + req + for req in map(raw_req, dist.requires((extra,))) + if req not in install_requires + ] + for extra in dist.extras + } + os.rename(dist_info, egg_info) + os.rename( + os.path.join(egg_info, 'METADATA'), + os.path.join(egg_info, 'PKG-INFO'), + ) + setup_dist = setuptools.Distribution( + attrs=dict( + install_requires=install_requires, + extras_require=extras_require, + ), + ) + # Temporarily disable info traces. + log_threshold = log._global_log.threshold + log.set_threshold(log.WARN) + try: + write_requirements( + setup_dist.get_command_obj('egg_info'), + None, + os.path.join(egg_info, 'requires.txt'), + ) + finally: + log.set_threshold(log_threshold) + + @staticmethod + def _move_data_entries(destination_eggdir, dist_data): + """Move data entries to their correct location.""" + dist_data = os.path.join(destination_eggdir, dist_data) + dist_data_scripts = os.path.join(dist_data, 'scripts') + if os.path.exists(dist_data_scripts): + egg_info_scripts = os.path.join( + destination_eggdir, 'EGG-INFO', 'scripts') + os.mkdir(egg_info_scripts) + for entry in os.listdir(dist_data_scripts): + # Remove bytecode, as it's not properly handled + # during easy_install scripts install phase. + if entry.endswith('.pyc'): + os.unlink(os.path.join(dist_data_scripts, entry)) + else: + os.rename( + os.path.join(dist_data_scripts, entry), + os.path.join(egg_info_scripts, entry), + ) + os.rmdir(dist_data_scripts) + for subdir in filter(os.path.exists, ( + os.path.join(dist_data, d) + for d in ('data', 'headers', 'purelib', 'platlib') + )): + unpack(subdir, destination_eggdir) + if os.path.exists(dist_data): + os.rmdir(dist_data) + + @staticmethod + def _fix_namespace_packages(egg_info, destination_eggdir): + namespace_packages = os.path.join( + egg_info, 'namespace_packages.txt') + if os.path.exists(namespace_packages): + with open(namespace_packages) as fp: + namespace_packages = fp.read().split() + for mod in namespace_packages: + mod_dir = os.path.join(destination_eggdir, *mod.split('.')) + mod_init = os.path.join(mod_dir, '__init__.py') + if not os.path.exists(mod_dir): + os.mkdir(mod_dir) + if not os.path.exists(mod_init): + with open(mod_init, 'w') as fp: + fp.write(NAMESPACE_PACKAGE_INIT) diff --git a/venv/Lib/site-packages/setuptools/windows_support.py b/venv/Lib/site-packages/setuptools/windows_support.py new file mode 100644 index 0000000..cb977cf --- /dev/null +++ b/venv/Lib/site-packages/setuptools/windows_support.py @@ -0,0 +1,29 @@ +import platform +import ctypes + + +def windows_only(func): + if platform.system() != 'Windows': + return lambda *args, **kwargs: None + return func + + +@windows_only +def hide_file(path): + """ + Set the hidden attribute on a file or directory. + + From http://stackoverflow.com/questions/19622133/ + + `path` must be text. + """ + __import__('ctypes.wintypes') + SetFileAttributes = ctypes.windll.kernel32.SetFileAttributesW + SetFileAttributes.argtypes = ctypes.wintypes.LPWSTR, ctypes.wintypes.DWORD + SetFileAttributes.restype = ctypes.wintypes.BOOL + + FILE_ATTRIBUTE_HIDDEN = 0x02 + + ret = SetFileAttributes(path, FILE_ATTRIBUTE_HIDDEN) + if not ret: + raise ctypes.WinError() diff --git a/venv/Scripts/Activate.ps1 b/venv/Scripts/Activate.ps1 new file mode 100644 index 0000000..64c5aa3 --- /dev/null +++ b/venv/Scripts/Activate.ps1 @@ -0,0 +1,398 @@ +<# +.Synopsis +Activate a Python virtual environment for the current PowerShell session. + +.Description +Pushes the python executable for a virtual environment to the front of the +$Env:PATH environment variable and sets the prompt to signify that you are +in a Python virtual environment. Makes use of the command line switches as +well as the `pyvenv.cfg` file values present in the virtual environment. + +.Parameter VenvDir +Path to the directory that contains the virtual environment to activate. The +default value for this is the parent of the directory that the Activate.ps1 +script is located within. + +.Parameter Prompt +The prompt prefix to display when this virtual environment is activated. By +default, this prompt is the name of the virtual environment folder (VenvDir) +surrounded by parentheses and followed by a single space (ie. '(.venv) '). + +.Example +Activate.ps1 +Activates the Python virtual environment that contains the Activate.ps1 script. + +.Example +Activate.ps1 -Verbose +Activates the Python virtual environment that contains the Activate.ps1 script, +and shows extra information about the activation as it executes. + +.Example +Activate.ps1 -VenvDir C:\Users\MyUser\Common\.venv +Activates the Python virtual environment located in the specified location. + +.Example +Activate.ps1 -Prompt "MyPython" +Activates the Python virtual environment that contains the Activate.ps1 script, +and prefixes the current prompt with the specified string (surrounded in +parentheses) while the virtual environment is active. + +.Notes +On Windows, it may be required to enable this Activate.ps1 script by setting the +execution policy for the user. You can do this by issuing the following PowerShell +command: + +PS C:\> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser + +For more information on Execution Policies: +https://go.microsoft.com/fwlink/?LinkID=135170 + +#> +Param( + [Parameter(Mandatory = $false)] + [String] + $VenvDir, + [Parameter(Mandatory = $false)] + [String] + $Prompt +) + +<# Function declarations --------------------------------------------------- #> + +<# +.Synopsis +Remove all shell session elements added by the Activate script, including the +addition of the virtual environment's Python executable from the beginning of +the PATH variable. + +.Parameter NonDestructive +If present, do not remove this function from the global namespace for the +session. + +#> +function global:deactivate ([switch]$NonDestructive) { + # Revert to original values + + # The prior prompt: + if (Test-Path -Path Function:_OLD_VIRTUAL_PROMPT) { + Copy-Item -Path Function:_OLD_VIRTUAL_PROMPT -Destination Function:prompt + Remove-Item -Path Function:_OLD_VIRTUAL_PROMPT + } + + # The prior PYTHONHOME: + if (Test-Path -Path Env:_OLD_VIRTUAL_PYTHONHOME) { + Copy-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME -Destination Env:PYTHONHOME + Remove-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME + } + + # The prior PATH: + if (Test-Path -Path Env:_OLD_VIRTUAL_PATH) { + Copy-Item -Path Env:_OLD_VIRTUAL_PATH -Destination Env:PATH + Remove-Item -Path Env:_OLD_VIRTUAL_PATH + } + + # Just remove the VIRTUAL_ENV altogether: + if (Test-Path -Path Env:VIRTUAL_ENV) { + Remove-Item -Path env:VIRTUAL_ENV + } + + # Just remove the _PYTHON_VENV_PROMPT_PREFIX altogether: + if (Get-Variable -Name "_PYTHON_VENV_PROMPT_PREFIX" -ErrorAction SilentlyContinue) { + Remove-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Scope Global -Force + } + + # Leave deactivate function in the global namespace if requested: + if (-not $NonDestructive) { + Remove-Item -Path function:deactivate + } +} + +<# +.Description +Get-PyVenvConfig parses the values from the pyvenv.cfg file located in the +given folder, and returns them in a map. + +For each line in the pyvenv.cfg file, if that line can be parsed into exactly +two strings separated by `=` (with any amount of whitespace surrounding the =) +then it is considered a `key = value` line. The left hand string is the key, +the right hand is the value. + +If the value starts with a `'` or a `"` then the first and last character is +stripped from the value before being captured. + +.Parameter ConfigDir +Path to the directory that contains the `pyvenv.cfg` file. +#> +function Get-PyVenvConfig( + [String] + $ConfigDir +) { + Write-Verbose "Given ConfigDir=$ConfigDir, obtain values in pyvenv.cfg" + + # Ensure the file exists, and issue a warning if it doesn't (but still allow the function to continue). + $pyvenvConfigPath = Join-Path -Resolve -Path $ConfigDir -ChildPath 'pyvenv.cfg' -ErrorAction Continue + + # An empty map will be returned if no config file is found. + $pyvenvConfig = @{ } + + if ($pyvenvConfigPath) { + + Write-Verbose "File exists, parse `key = value` lines" + $pyvenvConfigContent = Get-Content -Path $pyvenvConfigPath + + $pyvenvConfigContent | ForEach-Object { + $keyval = $PSItem -split "\s*=\s*", 2 + if ($keyval[0] -and $keyval[1]) { + $val = $keyval[1] + + # Remove extraneous quotations around a string value. + if ("'""".Contains($val.Substring(0, 1))) { + $val = $val.Substring(1, $val.Length - 2) + } + + $pyvenvConfig[$keyval[0]] = $val + Write-Verbose "Adding Key: '$($keyval[0])'='$val'" + } + } + } + return $pyvenvConfig +} + + +<# Begin Activate script --------------------------------------------------- #> + +# Determine the containing directory of this script +$VenvExecPath = Split-Path -Parent $MyInvocation.MyCommand.Definition +$VenvExecDir = Get-Item -Path $VenvExecPath + +Write-Verbose "Activation script is located in path: '$VenvExecPath'" +Write-Verbose "VenvExecDir Fullname: '$($VenvExecDir.FullName)" +Write-Verbose "VenvExecDir Name: '$($VenvExecDir.Name)" + +# Set values required in priority: CmdLine, ConfigFile, Default +# First, get the location of the virtual environment, it might not be +# VenvExecDir if specified on the command line. +if ($VenvDir) { + Write-Verbose "VenvDir given as parameter, using '$VenvDir' to determine values" +} +else { + Write-Verbose "VenvDir not given as a parameter, using parent directory name as VenvDir." + $VenvDir = $VenvExecDir.Parent.FullName.TrimEnd("\\/") + Write-Verbose "VenvDir=$VenvDir" +} + +# Next, read the `pyvenv.cfg` file to determine any required value such +# as `prompt`. +$pyvenvCfg = Get-PyVenvConfig -ConfigDir $VenvDir + +# Next, set the prompt from the command line, or the config file, or +# just use the name of the virtual environment folder. +if ($Prompt) { + Write-Verbose "Prompt specified as argument, using '$Prompt'" +} +else { + Write-Verbose "Prompt not specified as argument to script, checking pyvenv.cfg value" + if ($pyvenvCfg -and $pyvenvCfg['prompt']) { + Write-Verbose " Setting based on value in pyvenv.cfg='$($pyvenvCfg['prompt'])'" + $Prompt = $pyvenvCfg['prompt']; + } + else { + Write-Verbose " Setting prompt based on parent's directory's name. (Is the directory name passed to venv module when creating the virutal environment)" + Write-Verbose " Got leaf-name of $VenvDir='$(Split-Path -Path $venvDir -Leaf)'" + $Prompt = Split-Path -Path $venvDir -Leaf + } +} + +Write-Verbose "Prompt = '$Prompt'" +Write-Verbose "VenvDir='$VenvDir'" + +# Deactivate any currently active virtual environment, but leave the +# deactivate function in place. +deactivate -nondestructive + +# Now set the environment variable VIRTUAL_ENV, used by many tools to determine +# that there is an activated venv. +$env:VIRTUAL_ENV = $VenvDir + +if (-not $Env:VIRTUAL_ENV_DISABLE_PROMPT) { + + Write-Verbose "Setting prompt to '$Prompt'" + + # Set the prompt to include the env name + # Make sure _OLD_VIRTUAL_PROMPT is global + function global:_OLD_VIRTUAL_PROMPT { "" } + Copy-Item -Path function:prompt -Destination function:_OLD_VIRTUAL_PROMPT + New-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Description "Python virtual environment prompt prefix" -Scope Global -Option ReadOnly -Visibility Public -Value $Prompt + + function global:prompt { + Write-Host -NoNewline -ForegroundColor Green "($_PYTHON_VENV_PROMPT_PREFIX) " + _OLD_VIRTUAL_PROMPT + } +} + +# Clear PYTHONHOME +if (Test-Path -Path Env:PYTHONHOME) { + Copy-Item -Path Env:PYTHONHOME -Destination Env:_OLD_VIRTUAL_PYTHONHOME + Remove-Item -Path Env:PYTHONHOME +} + +# Add the venv to the PATH +Copy-Item -Path Env:PATH -Destination Env:_OLD_VIRTUAL_PATH +$Env:PATH = "$VenvExecDir$([System.IO.Path]::PathSeparator)$Env:PATH" + +# SIG # Begin signature block +# MIIcvwYJKoZIhvcNAQcCoIIcsDCCHKwCAQExDzANBglghkgBZQMEAgEFADB5Bgor +# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG +# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCAwnDYwEHaCQq0n +# 8NAvsN7H7BO7/48rXCNwrg891FS5vaCCC38wggUwMIIEGKADAgECAhAECRgbX9W7 +# ZnVTQ7VvlVAIMA0GCSqGSIb3DQEBCwUAMGUxCzAJBgNVBAYTAlVTMRUwEwYDVQQK +# EwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xJDAiBgNV +# BAMTG0RpZ2lDZXJ0IEFzc3VyZWQgSUQgUm9vdCBDQTAeFw0xMzEwMjIxMjAwMDBa +# Fw0yODEwMjIxMjAwMDBaMHIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2Vy +# dCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xMTAvBgNVBAMTKERpZ2lD +# ZXJ0IFNIQTIgQXNzdXJlZCBJRCBDb2RlIFNpZ25pbmcgQ0EwggEiMA0GCSqGSIb3 +# DQEBAQUAA4IBDwAwggEKAoIBAQD407Mcfw4Rr2d3B9MLMUkZz9D7RZmxOttE9X/l +# qJ3bMtdx6nadBS63j/qSQ8Cl+YnUNxnXtqrwnIal2CWsDnkoOn7p0WfTxvspJ8fT +# eyOU5JEjlpB3gvmhhCNmElQzUHSxKCa7JGnCwlLyFGeKiUXULaGj6YgsIJWuHEqH +# CN8M9eJNYBi+qsSyrnAxZjNxPqxwoqvOf+l8y5Kh5TsxHM/q8grkV7tKtel05iv+ +# bMt+dDk2DZDv5LVOpKnqagqrhPOsZ061xPeM0SAlI+sIZD5SlsHyDxL0xY4PwaLo +# LFH3c7y9hbFig3NBggfkOItqcyDQD2RzPJ6fpjOp/RnfJZPRAgMBAAGjggHNMIIB +# yTASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBhjATBgNVHSUEDDAK +# BggrBgEFBQcDAzB5BggrBgEFBQcBAQRtMGswJAYIKwYBBQUHMAGGGGh0dHA6Ly9v +# Y3NwLmRpZ2ljZXJ0LmNvbTBDBggrBgEFBQcwAoY3aHR0cDovL2NhY2VydHMuZGln +# aWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElEUm9vdENBLmNydDCBgQYDVR0fBHow +# eDA6oDigNoY0aHR0cDovL2NybDQuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJl +# ZElEUm9vdENBLmNybDA6oDigNoY0aHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0Rp +# Z2lDZXJ0QXNzdXJlZElEUm9vdENBLmNybDBPBgNVHSAESDBGMDgGCmCGSAGG/WwA +# AgQwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cuZGlnaWNlcnQuY29tL0NQUzAK +# BghghkgBhv1sAzAdBgNVHQ4EFgQUWsS5eyoKo6XqcQPAYPkt9mV1DlgwHwYDVR0j +# BBgwFoAUReuir/SSy4IxLVGLp6chnfNtyA8wDQYJKoZIhvcNAQELBQADggEBAD7s +# DVoks/Mi0RXILHwlKXaoHV0cLToaxO8wYdd+C2D9wz0PxK+L/e8q3yBVN7Dh9tGS +# dQ9RtG6ljlriXiSBThCk7j9xjmMOE0ut119EefM2FAaK95xGTlz/kLEbBw6RFfu6 +# r7VRwo0kriTGxycqoSkoGjpxKAI8LpGjwCUR4pwUR6F6aGivm6dcIFzZcbEMj7uo +# +MUSaJ/PQMtARKUT8OZkDCUIQjKyNookAv4vcn4c10lFluhZHen6dGRrsutmQ9qz +# sIzV6Q3d9gEgzpkxYz0IGhizgZtPxpMQBvwHgfqL2vmCSfdibqFT+hKUGIUukpHq +# aGxEMrJmoecYpJpkUe8wggZHMIIFL6ADAgECAhADPtXtoGXRuMkd/PkqbJvYMA0G +# CSqGSIb3DQEBCwUAMHIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJ +# bmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xMTAvBgNVBAMTKERpZ2lDZXJ0 +# IFNIQTIgQXNzdXJlZCBJRCBDb2RlIFNpZ25pbmcgQ0EwHhcNMTgxMjE4MDAwMDAw +# WhcNMjExMjIyMTIwMDAwWjCBgzELMAkGA1UEBhMCVVMxFjAUBgNVBAgTDU5ldyBI +# YW1wc2hpcmUxEjAQBgNVBAcTCVdvbGZlYm9ybzEjMCEGA1UEChMaUHl0aG9uIFNv +# ZnR3YXJlIEZvdW5kYXRpb24xIzAhBgNVBAMTGlB5dGhvbiBTb2Z0d2FyZSBGb3Vu +# ZGF0aW9uMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAqr2kS7J1uW7o +# JRxlsdrETAjKarfoH5TI8PWST6Yb2xPooP7vHT4iaVXyL5Lze1f53Jw67Sp+u524 +# fJXf30qHViEWxumy2RWG0nciU2d+mMqzjlaAWSZNF0u4RcvyDJokEV0RUOqI5CG5 +# zPI3W9uQ6LiUk3HCYW6kpH177A5T3pw/Po8O8KErJGn1anaqtIICq99ySxrMad/2 +# hPMBRf6Ndah7f7HPn1gkSSTAoejyuqF5h+B0qI4+JK5+VLvz659VTbAWJsYakkxZ +# xVWYpFv4KeQSSwoo0DzMvmERsTzNvVBMWhu9OriJNg+QfFmf96zVTu93cZ+r7xMp +# bXyfIOGKhHMaRuZ8ihuWIx3gI9WHDFX6fBKR8+HlhdkaiBEWIsXRoy+EQUyK7zUs +# +FqOo2sRYttbs8MTF9YDKFZwyPjn9Wn+gLGd5NUEVyNvD9QVGBEtN7vx87bduJUB +# 8F4DylEsMtZTfjw/au6AmOnmneK5UcqSJuwRyZaGNk7y3qj06utx+HTTqHgi975U +# pxfyrwAqkovoZEWBVSpvku8PVhkBXcLmNe6MEHlFiaMoiADAeKmX5RFRkN+VrmYG +# Tg4zajxfdHeIY8TvLf48tTfmnQJd98geJQv/01NUy/FxuwqAuTkaez5Nl1LxP0Cp +# THhghzO4FRD4itT2wqTh4jpojw9QZnsCAwEAAaOCAcUwggHBMB8GA1UdIwQYMBaA +# FFrEuXsqCqOl6nEDwGD5LfZldQ5YMB0GA1UdDgQWBBT8Kr9+1L6s84KcpM97IgE7 +# uI8H8jAOBgNVHQ8BAf8EBAMCB4AwEwYDVR0lBAwwCgYIKwYBBQUHAwMwdwYDVR0f +# BHAwbjA1oDOgMYYvaHR0cDovL2NybDMuZGlnaWNlcnQuY29tL3NoYTItYXNzdXJl +# ZC1jcy1nMS5jcmwwNaAzoDGGL2h0dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9zaGEy +# LWFzc3VyZWQtY3MtZzEuY3JsMEwGA1UdIARFMEMwNwYJYIZIAYb9bAMBMCowKAYI +# KwYBBQUHAgEWHGh0dHBzOi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMwCAYGZ4EMAQQB +# MIGEBggrBgEFBQcBAQR4MHYwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2lj +# ZXJ0LmNvbTBOBggrBgEFBQcwAoZCaHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29t +# L0RpZ2lDZXJ0U0hBMkFzc3VyZWRJRENvZGVTaWduaW5nQ0EuY3J0MAwGA1UdEwEB +# /wQCMAAwDQYJKoZIhvcNAQELBQADggEBAEt1oS21X0axiafPjyY+vlYqjWKuUu/Y +# FuYWIEq6iRRaFabNDhj9RBFQF/aJiE5msrQEOfAD6/6gVSH91lZWBqg6NEeG9T9S +# XbiAPvJ9CEWFsdkXUrjbWhvCnuZ7kqUuU5BAumI1QRbpYgZL3UA+iZXkmjbGh1ln +# 8rUhWIxbBYL4Sg2nqpB44p7CUFYkPj/MbwU2gvBV2pXjj5WaskoZtsACMv5g42BN +# oVLoRAi+ev6s07POt+JtHRIm87lTyuc8wh0swTPUwksKbLU1Zdj9CpqtzXnuVE0w +# 50exJvRSK3Vt4g+0vigpI3qPmDdpkf9+4Mvy0XMNcqrthw20R+PkIlMxghCWMIIQ +# kgIBATCBhjByMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkw +# FwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMTEwLwYDVQQDEyhEaWdpQ2VydCBTSEEy +# IEFzc3VyZWQgSUQgQ29kZSBTaWduaW5nIENBAhADPtXtoGXRuMkd/PkqbJvYMA0G +# CWCGSAFlAwQCAQUAoIGYMBkGCSqGSIb3DQEJAzEMBgorBgEEAYI3AgEEMBwGCisG +# AQQBgjcCAQsxDjAMBgorBgEEAYI3AgEVMCwGCisGAQQBgjcCAQwxHjAcoBqAGABQ +# AHkAdABoAG8AbgAgADMALgA5AC4ANDAvBgkqhkiG9w0BCQQxIgQgBrni4mcRv7sM +# JHsxpROjRopOz2wuQVrJnn+lD7X7y+gwDQYJKoZIhvcNAQEBBQAEggIAgnraC5Ax +# LdvDJz/AUld/6WGZ21jxAG4ijZvDnAS7Hopm0vclO2+7jtddNTP0w1tbebW2o987 +# AjD16hqG+D96N/sB3vfZ86fVjARf3XuyCWBYuIkLnjir+MfaXNU1n+kJuT7DNpo6 +# H+BIUM8PYqLGo4SwHXC2H2d+VfMLNyZ+91LmqT9qAAC6aT+VuTvlC+BUF/J4N81f +# 3TCa0F7C9KT1cdAmKtt6EMIdAYqWp8r1merIFjD/olBTq9nLcyjTqE9lCb4Nf6J9 +# jyM8/FA8hD41nHZTCKRSPCFKNZRqVYOaiWBHxQxPtYKuLJzMgxK0QHQhjWNpXTLs +# C1G1hQxX0MOWzLmcgtvxh5AhlQS+oHUs4/ebzmaovVzjbQRPqZHLDzYOQeG+79JM +# qi5gQt4L7TksfvmQ/dI4nJtzVDYAjN1v9rJY1snSqBlnSWgOyyZJX7aYBgVM3uJV +# u6j5tKXnPW7/u6USlVjtD4yKxKKoctomYiSIjjJA7DVL9CoCSF2ZyqxtuXDR8VD7 +# fb8gS2XklEJ3wi8MbUg9LJtI5Q3e/Qursr9RpEL5uTjhW9xTV+ubc6SWMWMEj3RT +# +7PUi23Vdh2917qGR+jyrUap+GMCXrUyUsLkMR5UkiltErrubmRnSPTbkFJTfEcf +# aniVMNn3x63CGwXdmSgVJleq1n28KcM/A02hgg1FMIINQQYKKwYBBAGCNwMDATGC +# DTEwgg0tBgkqhkiG9w0BBwKggg0eMIINGgIBAzEPMA0GCWCGSAFlAwQCAQUAMHgG +# CyqGSIb3DQEJEAEEoGkEZzBlAgEBBglghkgBhv1sBwEwMTANBglghkgBZQMEAgEF +# AAQgnJMkz3GdNmSHANJI2WUD6lOcmRKl+QqVqKICyZcEo3wCEQCoQmR+Bv/7IKIC +# +H/HED8fGA8yMDIxMDQwNjE0MDc1MFqgggo3MIIE/jCCA+agAwIBAgIQDUJK4L46 +# iP9gQCHOFADw3TANBgkqhkiG9w0BAQsFADByMQswCQYDVQQGEwJVUzEVMBMGA1UE +# ChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMTEwLwYD +# VQQDEyhEaWdpQ2VydCBTSEEyIEFzc3VyZWQgSUQgVGltZXN0YW1waW5nIENBMB4X +# DTIxMDEwMTAwMDAwMFoXDTMxMDEwNjAwMDAwMFowSDELMAkGA1UEBhMCVVMxFzAV +# BgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMSAwHgYDVQQDExdEaWdpQ2VydCBUaW1lc3Rh +# bXAgMjAyMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMLmYYRnxYr1 +# DQikRcpja1HXOhFCvQp1dU2UtAxQtSYQ/h3Ib5FrDJbnGlxI70Tlv5thzRWRYlq4 +# /2cLnGP9NmqB+in43Stwhd4CGPN4bbx9+cdtCT2+anaH6Yq9+IRdHnbJ5MZ2djpT +# 0dHTWjaPxqPhLxs6t2HWc+xObTOKfF1FLUuxUOZBOjdWhtyTI433UCXoZObd048v +# V7WHIOsOjizVI9r0TXhG4wODMSlKXAwxikqMiMX3MFr5FK8VX2xDSQn9JiNT9o1j +# 6BqrW7EdMMKbaYK02/xWVLwfoYervnpbCiAvSwnJlaeNsvrWY4tOpXIc7p96AXP4 +# Gdb+DUmEvQECAwEAAaOCAbgwggG0MA4GA1UdDwEB/wQEAwIHgDAMBgNVHRMBAf8E +# AjAAMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMIMEEGA1UdIAQ6MDgwNgYJYIZIAYb9 +# bAcBMCkwJwYIKwYBBQUHAgEWG2h0dHA6Ly93d3cuZGlnaWNlcnQuY29tL0NQUzAf +# BgNVHSMEGDAWgBT0tuEgHf4prtLkYaWyoiWyyBc1bjAdBgNVHQ4EFgQUNkSGjqS6 +# sGa+vCgtHUQ23eNqerwwcQYDVR0fBGowaDAyoDCgLoYsaHR0cDovL2NybDMuZGln +# aWNlcnQuY29tL3NoYTItYXNzdXJlZC10cy5jcmwwMqAwoC6GLGh0dHA6Ly9jcmw0 +# LmRpZ2ljZXJ0LmNvbS9zaGEyLWFzc3VyZWQtdHMuY3JsMIGFBggrBgEFBQcBAQR5 +# MHcwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBPBggrBgEF +# BQcwAoZDaHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0U0hBMkFz +# c3VyZWRJRFRpbWVzdGFtcGluZ0NBLmNydDANBgkqhkiG9w0BAQsFAAOCAQEASBzc +# temaI7znGucgDo5nRv1CclF0CiNHo6uS0iXEcFm+FKDlJ4GlTRQVGQd58NEEw4bZ +# O73+RAJmTe1ppA/2uHDPYuj1UUp4eTZ6J7fz51Kfk6ftQ55757TdQSKJ+4eiRgNO +# /PT+t2R3Y18jUmmDgvoaU+2QzI2hF3MN9PNlOXBL85zWenvaDLw9MtAby/Vh/HUI +# AHa8gQ74wOFcz8QRcucbZEnYIpp1FUL1LTI4gdr0YKK6tFL7XOBhJCVPst/JKahz +# Q1HavWPWH1ub9y4bTxMd90oNcX6Xt/Q/hOvB46NJofrOp79Wz7pZdmGJX36ntI5n +# ePk2mOHLKNpbh6aKLzCCBTEwggQZoAMCAQICEAqhJdbWMht+QeQF2jaXwhUwDQYJ +# KoZIhvcNAQELBQAwZTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IElu +# YzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTEkMCIGA1UEAxMbRGlnaUNlcnQg +# QXNzdXJlZCBJRCBSb290IENBMB4XDTE2MDEwNzEyMDAwMFoXDTMxMDEwNzEyMDAw +# MFowcjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UE +# CxMQd3d3LmRpZ2ljZXJ0LmNvbTExMC8GA1UEAxMoRGlnaUNlcnQgU0hBMiBBc3N1 +# cmVkIElEIFRpbWVzdGFtcGluZyBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC +# AQoCggEBAL3QMu5LzY9/3am6gpnFOVQoV7YjSsQOB0UzURB90Pl9TWh+57ag9I2z +# iOSXv2MhkJi/E7xX08PhfgjWahQAOPcuHjvuzKb2Mln+X2U/4Jvr40ZHBhpVfgsn +# fsCi9aDg3iI/Dv9+lfvzo7oiPhisEeTwmQNtO4V8CdPuXciaC1TjqAlxa+DPIhAP +# dc9xck4Krd9AOly3UeGheRTGTSQjMF287DxgaqwvB8z98OpH2YhQXv1mblZhJymJ +# hFHmgudGUP2UKiyn5HU+upgPhH+fMRTWrdXyZMt7HgXQhBlyF/EXBu89zdZN7wZC +# /aJTKk+FHcQdPK/P2qwQ9d2srOlW/5MCAwEAAaOCAc4wggHKMB0GA1UdDgQWBBT0 +# tuEgHf4prtLkYaWyoiWyyBc1bjAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYunpyGd +# 823IDzASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBhjATBgNVHSUE +# DDAKBggrBgEFBQcDCDB5BggrBgEFBQcBAQRtMGswJAYIKwYBBQUHMAGGGGh0dHA6 +# Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBDBggrBgEFBQcwAoY3aHR0cDovL2NhY2VydHMu +# ZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElEUm9vdENBLmNydDCBgQYDVR0f +# BHoweDA6oDigNoY0aHR0cDovL2NybDQuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNz +# dXJlZElEUm9vdENBLmNybDA6oDigNoY0aHR0cDovL2NybDMuZGlnaWNlcnQuY29t +# L0RpZ2lDZXJ0QXNzdXJlZElEUm9vdENBLmNybDBQBgNVHSAESTBHMDgGCmCGSAGG +# /WwAAgQwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cuZGlnaWNlcnQuY29tL0NQ +# UzALBglghkgBhv1sBwEwDQYJKoZIhvcNAQELBQADggEBAHGVEulRh1Zpze/d2nyq +# Y3qzeM8GN0CE70uEv8rPAwL9xafDDiBCLK938ysfDCFaKrcFNB1qrpn4J6Jmvwmq +# YN92pDqTD/iy0dh8GWLoXoIlHsS6HHssIeLWWywUNUMEaLLbdQLgcseY1jxk5R9I +# EBhfiThhTWJGJIdjjJFSLK8pieV4H9YLFKWA1xJHcLN11ZOFk362kmf7U2GJqPVr +# lsD0WGkNfMgBsbkodbeZY4UijGHKeZR+WfyMD+NvtQEmtmyl7odRIeRYYJu6DC0r +# baLEfrvEJStHAgh8Sa4TtuF8QkIoxhhWz0E0tmZdtnR79VYzIi8iNrJLokqV2PWm +# jlIxggJNMIICSQIBATCBhjByMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNl +# cnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMTEwLwYDVQQDEyhEaWdp +# Q2VydCBTSEEyIEFzc3VyZWQgSUQgVGltZXN0YW1waW5nIENBAhANQkrgvjqI/2BA +# Ic4UAPDdMA0GCWCGSAFlAwQCAQUAoIGYMBoGCSqGSIb3DQEJAzENBgsqhkiG9w0B +# CRABBDAcBgkqhkiG9w0BCQUxDxcNMjEwNDA2MTQwNzUwWjArBgsqhkiG9w0BCRAC +# DDEcMBowGDAWBBTh14Ko4ZG+72vKFpG1qrSUpiSb8zAvBgkqhkiG9w0BCQQxIgQg +# 5mFO2l6qrJzEhKgscyI4e20+BlIPLZai0pXpS+XFVIowDQYJKoZIhvcNAQEBBQAE +# ggEApEkQXZn24/PS2O3rXicGnIfxtSxqOLcJFE8C4TcyBsvtgHfiDXPbbctdnpbb +# KZhX60fHqjr98I17Lqg7GHop2SOZHrR3NOEJcbHxHsI74qrCg6b70MHXh2Q1OLzQ +# hCc4JQUv7O/63bzVyJ9H4W1MgHOdmAlNSc3fWGtj4K4jhcM3uHnVl1gF4bJOWhMs +# W5IxHeBmpO4/Xv0upkbQXtmPooNgxwYRTosEyU6tkuDWRvQlddhNndOgX53r6Qsz +# CWdCDv2CiUaUyKOJW8vhO+DKqyK9Cobq537UKIl047zb5yFXfzQ4u/YGeMukkoBt +# 10uT/66Q5dEY8U/Y04CnnzJ83w== +# SIG # End signature block diff --git a/venv/Scripts/activate b/venv/Scripts/activate new file mode 100644 index 0000000..5d8da04 --- /dev/null +++ b/venv/Scripts/activate @@ -0,0 +1,66 @@ +# This file must be used with "source bin/activate" *from bash* +# you cannot run it directly + +deactivate () { + # reset old environment variables + if [ -n "${_OLD_VIRTUAL_PATH:-}" ] ; then + PATH="${_OLD_VIRTUAL_PATH:-}" + export PATH + unset _OLD_VIRTUAL_PATH + fi + if [ -n "${_OLD_VIRTUAL_PYTHONHOME:-}" ] ; then + PYTHONHOME="${_OLD_VIRTUAL_PYTHONHOME:-}" + export PYTHONHOME + unset _OLD_VIRTUAL_PYTHONHOME + fi + + # 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:-}" -o -n "${ZSH_VERSION:-}" ] ; then + hash -r 2> /dev/null + fi + + if [ -n "${_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="C:\Users\annas\Desktop\projekty_studia\AI_wozek_widlowy\venv" +export VIRTUAL_ENV + +_OLD_VIRTUAL_PATH="$PATH" +PATH="$VIRTUAL_ENV/Scripts:$PATH" +export PATH + +# unset PYTHONHOME if set +# this will fail if PYTHONHOME is set to the empty string (which is bad anyway) +# could use `if (set -u; : $PYTHONHOME) ;` in bash +if [ -n "${PYTHONHOME:-}" ] ; then + _OLD_VIRTUAL_PYTHONHOME="${PYTHONHOME:-}" + unset PYTHONHOME +fi + +if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT:-}" ] ; then + _OLD_VIRTUAL_PS1="${PS1:-}" + PS1="(venv) ${PS1:-}" + export PS1 +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:-}" -o -n "${ZSH_VERSION:-}" ] ; then + hash -r 2> /dev/null +fi diff --git a/venv/Scripts/activate.bat b/venv/Scripts/activate.bat new file mode 100644 index 0000000..d2b07a3 --- /dev/null +++ b/venv/Scripts/activate.bat @@ -0,0 +1,33 @@ +@echo off + +rem This file is UTF-8 encoded, so we need to update the current code page while executing it +for /f "tokens=2 delims=:." %%a in ('"%SystemRoot%\System32\chcp.com"') do ( + set _OLD_CODEPAGE=%%a +) +if defined _OLD_CODEPAGE ( + "%SystemRoot%\System32\chcp.com" 65001 > nul +) + +set VIRTUAL_ENV=C:\Users\annas\Desktop\projekty_studia\AI_wozek_widlowy\venv + +if not defined PROMPT set PROMPT=$P$G + +if defined _OLD_VIRTUAL_PROMPT set PROMPT=%_OLD_VIRTUAL_PROMPT% +if defined _OLD_VIRTUAL_PYTHONHOME set PYTHONHOME=%_OLD_VIRTUAL_PYTHONHOME% + +set _OLD_VIRTUAL_PROMPT=%PROMPT% +set PROMPT=(venv) %PROMPT% + +if defined PYTHONHOME set _OLD_VIRTUAL_PYTHONHOME=%PYTHONHOME% +set PYTHONHOME= + +if defined _OLD_VIRTUAL_PATH set PATH=%_OLD_VIRTUAL_PATH% +if not defined _OLD_VIRTUAL_PATH set _OLD_VIRTUAL_PATH=%PATH% + +set PATH=%VIRTUAL_ENV%\Scripts;%PATH% + +:END +if defined _OLD_CODEPAGE ( + "%SystemRoot%\System32\chcp.com" %_OLD_CODEPAGE% > nul + set _OLD_CODEPAGE= +) diff --git a/venv/Scripts/deactivate.bat b/venv/Scripts/deactivate.bat new file mode 100644 index 0000000..1205c61 --- /dev/null +++ b/venv/Scripts/deactivate.bat @@ -0,0 +1,21 @@ +@echo off + +if defined _OLD_VIRTUAL_PROMPT ( + set "PROMPT=%_OLD_VIRTUAL_PROMPT%" +) +set _OLD_VIRTUAL_PROMPT= + +if defined _OLD_VIRTUAL_PYTHONHOME ( + set "PYTHONHOME=%_OLD_VIRTUAL_PYTHONHOME%" + set _OLD_VIRTUAL_PYTHONHOME= +) + +if defined _OLD_VIRTUAL_PATH ( + set "PATH=%_OLD_VIRTUAL_PATH%" +) + +set _OLD_VIRTUAL_PATH= + +set VIRTUAL_ENV= + +:END diff --git a/venv/Scripts/pip.exe b/venv/Scripts/pip.exe new file mode 100644 index 0000000000000000000000000000000000000000..5f7120a4b5ca715389f8808b8a2d0fdf336437de GIT binary patch literal 106390 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 guUrYyo*Vi%RW8RtEa)5gJ&!7~!yR-hj{pDw literal 0 HcmV?d00001 diff --git a/venv/Scripts/pip3.9.exe b/venv/Scripts/pip3.9.exe new file mode 100644 index 0000000000000000000000000000000000000000..5f7120a4b5ca715389f8808b8a2d0fdf336437de GIT binary patch literal 106390 zcmeFadwf*owfH^BWXJ#sdr(FK3XTvIjhE0=O&rh+%*Y;@2r6h)P&62^qEeUtotB*9DH^Zx#M z|9Sc7?EO6ZxvpnD>sf0(YpvAWu-4^vxm*SOZ`&?cD^K}Xt$zRUkHzN^r*9bH`tPCJ z&uGnyZ9ik~;yacHmM**J_GP!+6{x%A?z``a2X4JBuq<(R;EuZk;n~*&?z(5uZRZyk z4=c?!{p(8>-uvE-BPQkkkNbZ(>0Q!CxBPa}7WMqir0=We+DRYs{BYu$SlZ0ZU{1v4TJ-H9t_RLKHb0klz%{`&Jb#$WwV#~-baJ~c z;^|ZG)p_!e_k5SjBR~AhJzYN104>p+5B#bdbCt4nDd{wldq~}Ej=Z`aJ3r4gRlVf7 zelv%cwRx`7hD%27U%qPz11NWspUe7RJ@Z_x&QQO!^!f4IR>t}A;rsl^fMo8n_=Elh zT&{)ZFI#j={1%tXx>!CikV+m0}DYHtETx(sFWQ<}(`v&e7D2l5lFe zt*2t8<$5w)8nAvF097haqD(4GUP@o6r~Lbh@?4f(>~gJ_b+P?xKXSRYb!^-A6@Ah& zeO3(WlbnChXX8Tp+%)pUKK~$n&KT3*=V{qK_2m3gubzyT`mWQB{Q=YSU(=bJd000; zuGkwhyJM;8N42MRMa^!j`DE#~OK)zAk25`{Dz_sP%!_K_m!o!jw2Z>xs-u}*x*0F6 z)XfgvoX?z%O@W&`w)OW@q9<3C2Iht4hUSH?4PB?3`{}njW~O5)&shu-_$<9z9yOJb zinn9Q+bXSv?1_-Mt+|bFMHJC~&~EKIZri#^8Q_{^} zn(dILAB|MBnJ-!C(`61)ZB=RBQw6|3WWE$Nw};IwmZyXzG`H*KF6&*@`W~6;>5OEb z^fF35%=;a!*V)msW4ilD`a3M&laPx7bF1}J&FPm;AqYpB8Qp<_e!rRRH*9u9&6jj@ zhxMb;QhtXtx{}_QAG5o1I5TIS<{s_gc5DAJ=1A|l`CO<~=!f;<?!jGBax;eL5W#I~_?c-=>$4wl3nT4|+}_JK?D@ z-^tWVYpEY8`0ZvM&jUZ}_g`r7*;8^YJ~?dg(5KMom8tnNFoSzu5c> z8EHN-wnFwo=|YzDxuI;lTV=7y-;(jDPE|YBS{XHaWKQqv`l)UD#LeuL@|$lOm}~#O ztk%s}bn}qyPtm?^OmuZZP2@CtN~WL&(iJne>gG%A?r<_D*d8kltQSVc_TNXz7-g7dPhlR|(pk}Mop#8!&9Gqj+|pWBBk37-T^@zQ z(kxiN(Dr{n`&w%}13XU6rDUJXVIGoB`H#{flMhLAG0E?+ILxwpRrVZ66E7{f4tjsB z95A~1KD9oimcr-rKoQ7%=qd1q97S=%+PYcZdeE?}-Z(TNJ}G3rXsze$0h7m2_b*a6 zHOp)J4+!*Coy0c1d2f7p)D3#~rgutPDgTct7-|)MN;h{}bwhKM>X+mqbbIBc-z#ohc-wN4G;S|A#u%u&$Tl#+LkS@ggZc&KaAfo3GV}tImv%(bf%@ ze2{rU(7WQab)m&;W;icz@S+><1J=}1`0Dyl z^6S@b@w8Osx#n0Cff~ng%D-WVTDR=kT@K07Q-(CIo5zLR1@|l;-B48=*BYvZ#fRy3 zyB_RX_F=}&KA=AQLdyR=nvfO$1QJx;aQP^?j-44|%08u$wh)Fh0~m`rdZiPUL^mp|^MY(%X?56z?@a%I66Srb}-TbDtwEL@GWAnVa?IZtdYV7G<>c zt%;m^F8D*2Rmf{aTe^{VRc5y;6MvNigz+3FwZmEqlPvTc%$_6rx!Af$wZT%lGEYCA2!EFg| z2?w-oTlF<^Iz>%z@fqEGnRz7q);eg+JB!NfPpu*&?za|76M$^EbuDkO4b@4n zh>It-!76MCl~8bZVzqVsRH`Ir_;hn^n}9!gvTnAts<&BQJ?K9M2O2-cZ0I7Z+4D5# zNWyDPy+levU_JkNHk+wxhBtnyZqD$TEvi`YBT{Ur6`7*iW(YHUJ*tKL#3)0R$=@=g zB#%SKm;Z^jI&bh8`_Ht+tlv_E+LeLOTu`VQZYFA4&YlRFn`%VZct!>aMvb*@3-mAK zL9o3QE^>AH_v-WR_#48tf`iXmhhZCIAZj2|RW~YenO@ebtvl_~dgDlF*)V=@SW!@K zbOeMP8+|IPPi3_Qgi7o7_IPzY{7|qyxF^0P^L3aNp}zs^BcRABpc2};J=W_2Rbdyh zwT4M8kJQ@6!Ktn5C~FT_!jr~}ge5FDekpJ}rbHGw>a*JjioKY%s}9WvfdIke3O3R1 znE7&*=kiJ*yaE`+zm=Uolg=XYL4+(df9fJ%G&BEL*()=&bwww`_o-POQnP9gaB81a zZyZ*6hgIIjK-AcnAGN#UjJaFJ{7ih4wr-=guDh%Y#FZvttF3v$l&khn)N{xdHxBJv zvC0w0n!9x^atL(4>tdn0-HCwp-gKBihUl^$sOHU-PRvn54`})=o-USNCU%xGEYGr9P1@Dez2r zzBw+>)#1=5)ARO%JlB(=3!ulsR#EU}Ji!hv)}hyRZGg#hB|YsFv5rOBdHMH|<{C-U_c^dS+2L^R5t- zl>f+Sd9FxGcSp^xSjzt~Y!rl3Z}0OMZ=4=A3pVO^cGt$tQF&40unkvk96lcR)Uc0- zbmp@jcGPZ@)}wZJ;%~I4w!Pqu6^y!E4bv80l;?8AJ=XTi6|{H97!XUCz6Gu!OQ&V| zQpL3lLl3^Z>{5XA>gn>nXT{g#IBfm>zpH=e=w;99z3=Poham#b=mS|VD=1^l0=)RPZXqf66S$oI!H z%!+cj1ai|0K%?fi2X7ZifBHVX_ha4Y%U@PI z3j*rX8xOfS30F+fQz)*2?JI`qtp`M0N4(LEeFv<^7@c0WPk7^U81MMmorT-Bu>nrD zUIfM9xa4rsI$eMNyDUqmF9V_(z_STUSHlu*w{909!ej+aR?uVx zO;#{Ls&D_ys-zY=x!dCpKO9fxY)_^Yln&zIwS=K@r%IqQV0lb|<_EySf%&GfC38tHWEp1?}Wraqt z&M-aE-cMt}u6xhcjpKIQhhDQ{x2QGSWIauhq2j+DRIqQw!%;N&+875m7Q2>Euh}v6_ zQ4~aE4=E6kV`XYZY$7`PLwdh|+tTbtT9zdzup0iBit&M7P)`jaSP_ z3rR#oj+u*KXOuvo^q~k@uwpfwZ{|iF{g+iOFm%xWEBJQB{!JFny@%#=ynBhYi~(k` z-S#WqJ^eZZmohmyD3)4;68j7pf6vU4YOVR(6p$6GpX;pHIY!^{_$0k-aK8ub9ZgjJ*tc2a7-yD^hjQOynvV#x|Tvc(<@geCds;wl~(*P3J4(C(^^jI zsJp1GCsf%GKiS&C0JCGgM#j3sX2YH%Bl#1vF!$7$LMXC2!=2VvhL;m5>R6JsQu3gX zFcB#xBU&k;q8?a!l}rJ@CzSt{`e0W=1g1!<92}&U`#70=XCdyd>(0xkwc z;~<+`S{^prZU4*{fLk{R;?dUeL0i|Zt=l?LxIGcK6z>_S*jr=nLWl#85~HopV3o2H zdWctu-1h~vFq>}+n|EQ~S8* z9?>P%gn=pj5e*|`F?|C-v@W@t#Qk15cONJ)>b!_;=nBz+=UKPkBMU&22V~kH>Y<2-KO0uKekpeGzakM8`wHM8}qcLKk`vVm?*6HApI*6 zW%v7P%>6ayr|$c`(e~q>knzsxv&@16HFthc8|n#r=xtSQ7WvjM7r0!(Es2RrgxjgR zyK;l*RD)<=_Hplw5?26nFasntUu5>yUDSahw!8@aQQUH{Z^g)-871EMa48I%VD`n` z=KZDcY-d;Jxvrph)pJ2S-|j5yO@%LHD-EbNMXw3H5K2HM5Q#3-n3t4aV}ouymjtN=LnYX zXv3lq)+qL0zo&GoAUeo+`+@o{0z1A7Arjr4S zxR3vLMH|r+*_Yirv@^1Ym(`iV8L5KOWCUG8jUF>2?8Ta0(AALrf^bPa@%bQC)UMgH z5_vqbtEEJKWi^tKU71mOYThnnu*Mlo8uD|7e3Y^UEhQOW_T!@L#{$T*R<&SH{q*Gg z`s3Q89jO_|<(gy;7lMey%O`Uo$i?7Wxy!&TYzE&isG|fmRMbpIg(}I783&2h^s$<9 zTf#3}eTlD zyXdE&^IY7Bl1bFC*41*@^&L+vwVJ49R8G*Eze_{by`+*Q=>~cK2Jf`>)_h?cxNv4i ztM*vtFSI9O5>#Tz&BvwHvBK}Lnv#CZEp$eM0w>_Ie#9_9#T?HEW$K4FEUq$=D4N5N5S!L82dh|_#jCcqc0CN%Xm@x9)k@6>3?3u_{|$jB29bm8x}I&IvP&i zSdtkV>gmXfkK)%G9}&_vyftiDVdsoe5pt!{^++LMvr}<84_~iv3f1W5R76dzTqed8 z&@Vf?$Kg}ims~#$Y|fCmM+SVNdTr;3eo)QlRYrdvnvh|}k-WIaIFg_EyVdkD`xU*j z@bNpX4`tKtk+*__yuqu^|B}9eSI(}&nD)#xD6MXetK*R4>RM|uKnme*D)g#xmy#Jz zSV!(4E9seY1~U4(#X`C68*06KySyZ@lo)rG)Ma3^Wb0in*GB)rN5$L>2aV$u)}xXR zcHTQiH;307Q}3IW&>ZQ*`lw!-i4Q@-@@97GrkmS^mH9bV2pwFfU~-74S4LT9(_B`OGM-lxgn`S8n$JsBSX+V8DXObj z@+@bB`Dg%9+WHk&h(3sOL9V8)-NO~L^3^P0RtFHNK#$cepdBGR!%$%=#;#vU z@_CeX38k|8x0B%x@624@6Dl#{mskrgl11NY_F20HVb~g%!W07p+rb$R&14|RvnI>P zhgp-~mu*}(*=5v~xSSJ4sV|g%i8JQJvx~}uj;~SHU+6qLj>~w3PM^s*s^de9TS{D+ z1J*Y_%${Tya$-0q*+*n$*eJ3o9F%hI50vFbYt0RE(dPLHx5{YE_hu^fI!`wVh~u~A z;cjoN6tl#{TkD5|2=!HZNn%gMUZb^%H6C&A(5grJc+np2VCdD>Xe3BhWr8s+fMO#b zz0r9WpszcPB38$_InCYBvq>&FD_8V0lw49YUy4FBUDhN0MPHjtvilwo#H!;ndvMr# z^bRiT42szPtNbyR6U3q|I++vxZ96n`9}b)>_D5 zK#M|FY&)4T({t%WG>S>jWju7#AK+mYpTe&-?OlPXoH0-esjx^IUcpahwAp8@Dy>G* zP4@NVY_sm+cdfI)I)E={fuYlrtvi_w>B;GP*>FM^VO6+wZDCjd{re1``+S*~=~*S( zA^NKoJ|D(=p~#B0)(dSiQ@NL+&pEDmNar51lKM0dMuy@O)@`Wwo#P|rnM$Mb9*9vN z@ro8jY*@(VGiWO_K{uO9)c}$nuk@M9CXF`8rsrX)ZhAgct$1!0MIYtYN`FbuLUKDj z7m+!%z}432Dd!F1Diw;6^QGIxybsO3FSY#_b&F#3G0HhBFam(co$o2+1A&{j%F5=E zFs6NrLU6}Uxp!G$+h5Yft)g@Vp|SnDN$HK7WbE*M%0}=;Z!~#lNi?}UAohZT^&-_Z z=6&88bBY-%h?@6R)|BjTs75 zd;pVHQ`Y%-AResPT{Ze%6sEJiW{A19Eh{whc-&iLBX+m@f}@w0WZpppcek0bP9N;s z5OYaqQN|sH#{+JdTm&y(K2Nu~seG$IcfW4VKtpt3S(O8|Myaew& z8lP+gT`+;*;!2piKj(#*jvfZGHSW%ky(>5LW&fjKkTpvao3uNtVM7PoqzUBtY6yBzZj zt*L`tc;2Q@fj`$e#-VFg-xvQzsBEX!^ekCMdU$-M-5tNwNSDOVGSb81V~j%uiSI^) zPyROwM9f{rPG9=BQhmcmg=xXQ>Yh&26oO&K&g%3URccRW71{ZTdyV&w8}A-9cIImv zJ}k^ErJ=;FG!hzaXX=df-1uxGJt97pF3*v^M;nKRXw756k={;M8+-2}dKrNmG_cjm ze@9f(YBh&3jFU1~awl+}D#DgfMP7fqzle__BQs?bnV^akW{dn)715f9Ih~E5nD2z4 zgsUpFX2&uVy<-Fk-|S?kiiubQ3vC(8oq4>B+ROHQb_yFBa+pk%BqOJVlL>B`6O3gu z4*)_JLLfGg$H=vTrH!tX2}TVAm@H7n2h{S;yRY*BItr(Hb*txambjK8iI zvO7Txm5r$fTybnj3l8*Dml%n8z11bI2G%x~nt9CV^R4iuX8WvFYZRl)jA8Bd$y-4J>fJ_DNma z|MW&VrN`+~#60bYuu;N>k89+GS&6a*{>sPCM0tVHnsu7(oFEOb5OQw}n5!LiWA!tS(So1 zE(KxYdNR^r`+wUm2e8>^`~QVE=|H#r4ZN~CK2#S)#t|C^X{)v9c0QXanY>=H&6@Xj z7Ay6$Qh^Sd0nVZ2N-Hq`X1Nc6*Kx?_hS8kXp_HCy{fvFYy0>wHOP*i|j1YHe!|7}= z{dN{Xai|>5AjlPCunsd{jtWbA5dMhrVRLKlE@!)d>x`JNG%@Zt0yby2TH+<5QFhGV z;J^As>VS0<15r9kc;ZE+0nUYfabyLb7?#M{*!A4v#^j<6y<#|3?F|l#m)UJm_b#LF zyk!Sdp%09{kt>F@BLBEL8r#EEY(+E6l_3K2Ghv-iy}TQ?3WQ_)|ByS(Xq;P&@a@&pzIvD6$N3l?NZ zp(JOJqmu>1gZ>S&H)`C!hc&IKXshAcSuBZS!dF=W>} zm2-crw9+SA-*$2qO3n(!2-u!~ADQPuX9!d2O4P+tlfE{ZiP!Z-jj2ani86JcWDPkJ zv`iKp6`+^ssTl!fvyyZx&!gmw(&P+pW=zy9Ix1=nA4mEOuRQeREYNRwx?BYy>`$rH3=qvT)yaqP?+Nim!#{5|BMdq*q@vym%$9yH6 z$dU+wS<3&l*0fh`+gio(gY?X9ZxtoSxz?RzWW~rn`bAG4u3YeVe7J5#9y1>6VjYg5 zcS(;QCZsmfAlE=!QN>RVnFqrxdv(M-9Kxz3Iqy%X<3G@v-W&?t%muBA`g5HJI}}b` z-z7443=)GzqUC9dAdGLW50!P)b8F`3&@bKTA4 zPYLa*QTgqM3+Q)=`Hb*Rr+PU)&=XFiNqO$brqO1rbba}+1VkiU&I81 z?b`Rej8khW1;SYFXiZzdCZlhL)}*VKh}QJq>SdpcRim#~Yr31dT$aNz z_1&U1{ZM_c)0&`DE~R*nnnR+-7EX8}Kfo`jo7^UFP<`#`^JoK&+S|jImuOFm_dqR` zTt6<`_-tR;>`Tiw2y0JQ3Z!e(Nm6K=?kEN!*wMEvg$EQxNMGizQ12%3cuKe^mS zquOS$Zr$DzvOD<=2klj_h#pUkI*iTcQmy%32!5z%Q?=FEmKgBep^p1*cDP8r>_A5osky#Rv&R^)^lcI7O;&Ylp^NG&9;`jnzai( z4OXDH1#anw)mq-BeRni^UDi6elezFTW*Cu2Q8Qn^3pY4k0P-(>VH z*P2#ww5?BMKfNgBRyv914!)#9f6PQ!{M^K46@D>XR9 zw8n9(x4IetV)H(fCwM<(S>eBl$embe?NOe^Y=DWAFfbd&0&kLUG zsb*^YQ3jGjQj}#p*1a~0<5&z8|G3gEMheq zdI-$V-w-AHmn@_`bxg18p;nvipD3)N>=0&JZq~G5lFpm3g>BdeAV~>+!w!YaqmA#e zQm*)^5m4+D8f~Ca+y5py0onVI7JHY%d^Lx$*+SQ-LVp`vNYR1n%3#8)7DuFg$kH?5 zkw6d9BqZ#4aEay3i)*cD!5|CVWu)JBGV|jnw+3>Vsg-XqLOnB-DeEdbOf&Oi=91Et zk+R-!Suf2LB~DUz&t?}YW^v}2I-OCQiPr3mG#JkZx&9Gzr{#R466U4+79{+t(0W<7 zZ0+MAIZ-ixtxa%x*$>{Ln@2(>(o$rtLv3QEi?Y;*J0*LEwSBSLB(XXRE2l|HTOn88 ziyWKU6*L!hA7kdtJ*zjUk!Q|U4{q!kQ8iZ3u+%7@82d{A%Ngc2s!>OP*4(plf{ZnO znln~`PIjzUQz{Erv1FMOdQv_zR0m}uPyo1S>$&I9OoB9WGH@t6rP5`5l_S^ai^k^| zeT(BW)-R!UusvR)4r;U+TJsoHXv6;DX^l6m^1bR?VuT#tvcyH{o;=zyw)xT@@WNS> z-X|GClIlZ7m=in6vCR)-*R$pCnpsOI0?CJ=gq4%&EZXs%q41p)Y>rl?KzTb?YyiXle*=qMEIKn>J4G5)pn zvWHl;iR*=P;ANCT=U}_DQa8}3H-q)xwt`HQ-@MEWS%kvOR1*1_iIj=SDV z%a0y0-;`;{du`?7OtG9c*L5=vc|_kVp77OiZnQL zr;x9om6nU_*|wLczmTEMRbRtfIfu=lMfp}!-;@?03_B3Ih}*?(bRhz{o&(|(Gy;fkZD+-dy| z0gueB!pZ%m(_O@bA43aw{$5LR;y`mW{ z5Y7ul#jAhjj!gE098*(y%5?-5X)SqJ7ufB=j%A;%371~G1(qxzhMd=C&eoo|E-$P- z(H0JFTyaXMj1#Esid3vX+(7gG60m+!N*5TquPJP5OFU;@UW620sg_#AmU8p*0>pdX zILexrLYI_QTx8QQ6u$c#?94@_)h>#e*A|giiF#!zLRGmGm@HHjL%)uSZnCg{g?xXZ zc(X8%C)Nllo0M#&yQsv$xHLxpl+?>!jHMoxk?5%_$HmIFgnHb0@u3YveQUzQ-pY(1 znIHEx3=M?VguQRIGzzdXgYHI$;(PU75=SH?JHA9DWf>RR@f|F)O?@lbRmL z6mdB}X2l3v0eL^y1}b;}{oFE)S5s)2mNo-~3aKJG{_1*Z#| zpL)O^4*!tyw0V7_2wk`3QNFS{Mr-25qH|pM`zL{4R zG^T$8?U!qcg7~RM8gELj5eg7## z)l(1ppmgg+5QEGqOU$Zqt5LFQ&8?i!qJqH4P`2E_#1;kwrgQJ&XWWv{K>YSM3;ssK zuGy*ZIX;{qLX{=)DV5jf#n08A7^yuG$_wsVF$R+GwQ->}?vVTWkT*|qYuwwgECTlJ z`IQ&~!tHo#+^bq2e7L-d(xTOlQOkf z*^7Xi!TM&UR-Ni~_AG0WPc$fQD8d zhHpq0glZ5Xek=L9`9o))c7;eV3CsM?#lg zP@EG@l@$$cll|Y#5Rz&L2W)rGx4S5uuQea$(c^iNqb1L|V0}tx3_$p-L~h4t6eK;r z2HVXU-lXT}>ZK^@`LVpbgc)SPzuPwaNx(Slc>q({XS8+USw0+ooAi~}BfV_Qyh)4& zzBe8goPXeCimVBbIc<7NQ{K{_nZbT zJ79ZdO2t0johdyi3zHmYAC!-7#vB?A8kb=`mpBtRtou+3zKYzA{Bt#BE&uyDty;!Y z0q{N&|4K&@9se@ZW~C!Hrp*(bQDW430B&1D!TV0nWn_^l=d9?557@Z7HTuXA7Rjxs zX=C8TWXXxi^1;bes5aCp=*SJ%*M)9Z%{d^-KA+gp&>RZlm3_(|0mr2NthRvovtWSK zSW9CE?1qIrFfT&m_9NO7SBnGTJdTh4krj{z9Q{MfrE_D;rE`OG(t}6$Lx8PD#|4ub zofP3tR)z;%b%vMCbH;~*s58EBUW*J6J77hx*)=(PFG@^SUohrri{FRh@u%P=2EXyU zbkoRz^%kSjm6)%arUTgS_$fveF1Xf;EwZ^xX~9|!=fS%(pZ*f_29Q9ZCBV)nc@eA}M z8|)eDd=MQ6v^d^r&shIKB4k`5zRoGnB5*Sn+yyzggl!wxneZ`>MY1jI@%oZhy z@(67%zV!eHP)R>8Gs60t`u<285Xh9R7xvs*GfEhmlqq@KYzm)iUCUmh8K=MK7Q%@Qy%T)8X{tVB*)~T_Ky3Qgp*8%$p zHE!GQ{VjC5_!3%>i^0RBfEW8GLENmo4PA1iOoEm>nehs|?G$*o z1FWR&e?{^P;)EpKIA)i2C}s)%WrHfKZe+7kQ+A!d=`4_R=uPQ9YYKSVzbuLdoeiJ{ zm|VFaF{71&ZysyYMp@lix|4dsN!2>3$DPz-C-oC2wbV&{*Ga8(QV*(>*`NR_&EDl? zJSG__&r477P`vLv@}E}c+D>a6KxLIoStX^FleSKi^KvwG42#?x(>%mFjf!hIu`PID zXH8xksjBBzF># zx;dsg3s>16))Gxv$@oGj;h)v=%=ir_zo&){#5P=4%e$VEE-N%#Ml1^-pJEo53DuA_ zKKN_Z!gz!kPQM~Ky8J!lW!Jb>>ax&VVMY3Pu(L0G$^j*3ISM{#`+}W}k&` z2?JlS&$xe-D{+>#ZXUAH)A%Kh5kKpVfrba5O`Kgd2eO<#j>eg#+PWH_5`^(RUOq`l zi`Gd<4WQ2u!fE+3)1(BuM~JKTM1ePRt~m>v_(&k6=BeWJ5FQEnIE=`651R?jhl+8c zn?%0YsX%ryTYip;59PpCoa%a+IywyT5WW2~frbb&kH|>RRi7 zAz%F3FBJ_@y8HAFR%+We=Y8V{dC#unZ6dpKe@;BC5o&8}wJv&HvbI{+szYk4b$Ryr zin_Jms(MU|jq)}eW0#-z1tNvj8bi*Pv320a|N62I22+QD;w-3yqjW_obV6X>Ba?QS_6&6lCtsp2}`t)I_Sxa5_|Uo9EM*8nKuBMH1x#hpB?2LTRU z-9Y-22>3D31pG4m#VLG)Ym?RhcOd9zxeTDmaPO$<0IG_ zI9fe;eA!a#7JSt7s=`Em=3U9SnUmc1`&9isR#-kJ3+?A2M`c7H)F`+^9N3eLr#JqG4h^f)9`Yx*z`Me>zy>!CY^)Pgc1ph?Cz$pFENjcGgfDO{S*herD- zBi5RPoa(9b-a(HL`s*mSh+&>b{wN)8mmora-$fUA;%UvJD2T%0Ln)|YDb*)0Oapmr z(ro{TN6AGy_a6P6Lknlpf)k4HXEeap_YYXX2-*d#%2xrRIQ2ev5uFKC`ljAHQ!+M^ zK@)p{T4+53VtBF0U*Wx@Wt+LYB<3MkC)PHY;V)}<-(K3K`dX?hmx1lp7*#Y8!hb!R zQ|RPy;Q3FJZd!dX=FHf7x1K9@_y(3TXSCxCH!012J~KWz(tv2? z8i(I(6HQ;Zw0h0(P>Z*|svn#)zvNkU0T5sTRZ0nD3oQ^ zT$HWmPKf|0;IsV&KwLM!t588i{ZfuQF_;o$aSW#J#9(T9W!9C-;lbcB6-2F@001}= zAMGS(JMb81O#8!YUPH8@f%1u**F!7H7edk2Iuxq84*ju zQOF_0OQCaA5AfMp+NX5Z1Q>MO%0ck8&LYdSBEW1zE$P%Zx>%3#tUq?O@CCG-@QT*v zPT37f&mu1?=5evv&F#tJOC=TDwLHS+BH+~(y>@-)blWv7oLuJS?E=@ZEz_q+YG$}) z*$g(*B&lF*tR>(=uhWb~>Dp`-e~R9YJM(zytyJeB`T}Y3ohL%0|g9=P5&>**HbMrTIiiNA z%8|k-cG&*w)F^(Q9YwPoHRdOb;?q#@Q&9~3!%<{;!9jOo%8!<%5W{>9jrT>dN#p@# z+KC_dHtWtW4#w9%m}h<@Aju7;4}GvRn9oAN&k|3{U|0>Yz;c$PT9{xb%-8^rCju`a zY*VxItea8eu1($S=8O*n$9b^Ve&9B}?h|Oy%VPSg45?|W=zwzm@>#QRk&;7Wh}{WW zR%#p>wQ355{~(1a8C@ zW71z|uUWUV4cYS^=zS(2{@c|I0)O-F?F9SzW54r)V`kSn4{lBug@Vs zt>ya#^4%=jr81QSixdRd(yA6d?yMCEK@?x{L|-Ti2Hz^4=&Epf7}W-^Uv}O? zdr%?IeG}r-Q?WN{9yL~b^Acz3bz2;oxJAb-08#&IpRkgtqAooNYd`4+>M%Hy`(LBe zXB;VA)vZo%XTj9!F$f38=M#gfLx*oQN;g3vGkXW0>k?EkC z!lMCt0P29u%C^&UgH(2Rvq`#8uYLN@q*!f7XY0U79LNKD-OFN0LYvcW&hSi(wqE5J z;{Mc%6BN?ndo~bH2ooON4R3W`9t}s0RmZ@^0>XOTw|+9!tRo@}IRs6!?%qAf8lYAg zv{|r}qPE%UR85?hJ(>QCfk6aE3s&FrC)D#_8>ripDUK%RA9H1fSabPA?c!28xBX{Q zDPw%uqKL9U%~L_2$#JtkXP-b~FSO-#(b;~+i6>lCN*`%WBgiBWdVOF+0;{&~e*so1 zhU@<(7D1_py66V|);FHbT~%1UyVOlv=HC851Q1^*zyL>~y*d_rgV1@L4BE_gIE!7K zCq^kC9zlNqf(ilQ=Db7l&iEWlxP1c3#nx6D7&{$Iou_=Q*n954Z6mQ3YzOMNB;#RiGK}+KDQ#cyLsK zg>oW__-lzRra1O5vCbEONmK!0D6IggWJ%^hYcwzLXj5ruAfy0|aT|e6g5!ITYfSi> zE#cE`fHDwK;6)5*Xg5(|ZR0IWM1iw0gPgpjP?Z{IJwa}NK!M+>#3?d@i=>_tP@sD7 ziRVPdD2EoYl`8w4A0|5<57sXj1N2J#92_}0BJ;;1uA3MDeW4y#LCkzMPTbyVZ%y4C ztd?T#X9-smoA_+Bt^?xeQ=va}ukN1Z?FqTHcoEmCZbEwLkHp+vv5IGi$>|&y=lvcc z$QUN$aL73L@T`>twH)H5B$mN6Qk@9VI#}90=3(<=oXsBOOxh)T@M7jG5u6q)_f=r4 z^mY>0Dqy}8HoJsBdHQ=SIHU(y3_3!U-T=Xjdxw({9rEyC5_wkQzHD6f;U@s$3;zcB zM;QBY+!<9W&O6>3{uBe(?Z%Dow;W5j#y4FDYEnN%MQ?|; zxFt7nfbe^z5<$`nJbZN3Z;P|IguC4UAx9m8U~-xDigjG%rCB9<-GQF=hoE>*p~viW z4W$cpWFuaQ%+u3e9WSz*oGpgK4xceiQ9w5IR_i~Oai9~fh2FKM z6wPyBz-17o25YN4Ix%OI+FiI+G=K2mm@pQZJFFkpQK~O z<^{{6@|L{JDWcitFe5w>Ma|9DsjBPXF|BzsCAB9++r}DzfJ+8&!@2ixmVVHBqsK7% zyvwf9p4c5-pO^hd@Umygu3k1??|s>LqcA=sR@Sa3eFVQDHdWNvcUiPOJtR@(BnnBm z<0I?q>({Q8i!Y)#N{q!%#SVE`%Sf>a;&!#CLp#0NC58AeO02xoT(0HiQa*VVr{PsT z>Q(dH!~grJ&%@$>l!sUKCH7=~koCvWI!5YR2Q~O{s_?Q$QmPV9OA-gyjreKO#M@qFCSngjtJuhyDH%lUXdhksXq$RcU( z28h;?$E$-{h1RO2atolFArxlZVDGfVVXI*j=QKAe@-v%EN)J-r#deud4^)$$wOf}Z0@J(}?d?`V&4 z0Kq%$tro%_w%Z=#T|zZ|_fX(&RgYS)CPcppc(xP-EeN9bquy`!xk(J~z@RUOE| zk-nMFVe>ul$i0-;$FbMANLq(RJ{w-MWJ)DEM9M|-KM3u@$o{GA;g-7=V&XFjJRWX# z^zM2*FaEgk*72BmFtae5e&pFqD2Uzu^gR%aCWv6n3CMb?)r*NlHeyJT8Ust^O7DXu zf!n}rTw-JGL}XxEMNBJZ?wMsasVPBr%d2w60o|p$24$^K&1mbBWX$N1ZVPb({)^s48_X$t??(<*#Cr2s<}LY4C0T=@4ka z{1#xW*Ufts&!(1Dyi+K+OZ(0@c|}E<_Z?UP_nUOuC#x%yZqS-8u&CU7BwDu#1y7CnVbr}vPev>itbnMfsF3BZQWQl~$7)UQ%ljpp z;>F6a6a`Uw8#(ZAmTq@(Gq8MgG!@B{0AslBY|hU-$i+bV*A!u9YDh9O*t}Yqn&a?E zBiT6yTh!?>%=WKmN#M`ws~&hYehc$D``flXcv5 zEQIQITld`oRz=>9nRm?zmA&??g=uY#xkb3rirwlj8Av31^t#8IgdXe@Hk$kYW-4`A zjSO0b`wWN^?BH4!q4cgM+rAdWY&j*o8nv+yOAgJ1@qFvuYi{eVOEX{VvYqd`J)NG#85sLr2m6% z1vmfBGY73KZtih#6Nn=lZqCml=g*lTa~)y(Ph;Y8eey#JfS?X@0}eGApGVT5nq7U> zygfwq=1*~~i9n^CeITg1Ci3#2WL0iOTjrKul8Ffx`}*rA@Uc2Mb1_S$cW#uk00QW? zcH9nb2>|JR2)(PGPRSJI@(wRHNx9}-_E}7^U##$AmIAe+is{R-g2RS2+O||_OdN=(Yzf-H$GtolyF@@E{f@ND8W z%Q!$boxgrC5N_A;7k9X@jjEE2#+vO^%DBzYX@HY!p3mzAqv9Zc0BtUT_LT4RwN4`s zP%{?>Y$)%HYO1iIC+QfJ6G)a*=|#&sl^NqvFJWEfZ+}Qsv(0+&$nqj~wy}P#ah8Qr zbIaLWtG`W``a@|sxXxA7E+NSL9f1xWa@X421!WNJx$==-D%{s%G!+ewlQeX05r(Wh zYWw}8W2ENu|6FU_FVO1DZ_D{dKPGly=UTJK$TGisp3eD4KO$x)k+p;Tqc_06ilUMj zmesH=^Hw8gH2)SrDOptpoAUd1PzKH8WEj2p#8_P$1<$3RSSlO)ka-SyYVK^St#LPX z%K@K}$hs66N|8`cHPK?vmfGW`_81j&cB2HERX0BpZ1xB3iY=H<#MpDKA28PJu+QMt zaqB*D*dgNox*4{3ipi~+;6Z0(4SUY<>{h-(S>JAaO9@yb93igVp(kB{otsdB-D2_R z{vBWBf@t5=+7%~7wWl_*yT0q)cM_p+zu?NvrymS+AwxKh+zTB??yDGxIBtM+qV!CMM&Basd&^n;oI7?%YpNuvoVZ_L9gIGlxaCgJ=);M7 zoO-z?9#; z55^)RP*6-R@eDifPo5P zozk;8FxVYhK`^~k78C$E?$GAk(pc6J+Da4(eiSY5_lG`TEv>XdEX~dRPSB$rCupC_ z8{`D7(u4h-9Wd`TK^I>a6 zgTFTf&r|Ns9|-?1w0$o~0>rD?Sppvki!fhnzJY10^_wC%;9XuQD0d!i>OGtD;yy`~ zDaUmH63dJvH$Se51Tq%)HnFe@drq@U!)1$TwCp{KDPMjW8ekO9X}9cbB^?XP+nvIA(E`I8W1O&p%z{GmFr#o3t| zh1F5UHeBeOQk_E!FN?1gf(ji`>qP(Aci^S4+N+`D-E!(@m&=L zV}M&-&;fo#O}!}L4>hdJa~!3`xB3GuT?3c*+U1P_R0rJ+Vz4N7nbtV2yeJ8>(9Te;v2zHQTKJnaxbeSsY$7 z0hNW~nbdhN+x*0$YbcssgY>_^)G+sR5-0=uiv*U8$_HaRw+$H$B&$`<(X`??N7ts$b}9zqAx1GVK84@1 z_ym5>|gh3SmgB{bMB&1apxQ|vhsn_L*}%Qa;J)P6*k|@N>?RT1I-%&msQ(8y!7`V!Oh(( zmj|brZ=#OAQ#W6anIA>lk0DZBxRxxmt2)|M#G(%os7jPT6+z_r(|ku*`miU=ErF7i z*v5Pie|u!5Q>=skodbeZ=ydD|OXGnPV#%r2#}ts^bPp7~RvGX$Rur;ucWTLKAgJgjA$;> z6iU>-p-^uEC=8A?wdS9kJne}SB296jT|_*XcCK*HYu!d6eAbKdLhb1SxmjEsG7fpU zX_5xbZZ0CVrYo`{N)34;vh-!szs)|^W}lJl^DIYnX`YiERDbNLlk$btzmNk*#h%&* z*;Qf-+Cp9sTSUdE#Fjs+7h+Gfv-nDM5q4K%Pt8`br+%isBf3oBB@6C ztfXQ!U4Q}y@+YyHdXR4*r%uRpsQKa@C?#9=`k(WT0^Bp67o|NPKui zCumjX`x3DVswvbmEY=U>)@_tU+G_oAlHv-uut?twLJy7yg$1Ynl`*TXVK!h-HfGfw zsx=Ws{%H)Y5VuNe^6`?3UG+P*yCdfiA7RTt?5Y>j@5_PkB|)e{>cUWkrcpCd!9OHo z(bo|W7Qt<(I8?WNE)LZqSS0?Y(}Zkq_YIf2O9p~aMa*OA2k7zh5vWvb0nGg1m=^5f z&wp@aiWD^vg-TC9N?J)(mDJBgq3Z09LM1G>lCCy^2K`Z}ex-0?Y5W!?Vf|iea(t)& zRiX&(k3#hsjY||Ne4_R`GZ(4q)OHbDSw_y5e-w!7_ndw?`6?TT%8{+u^Glx+#Xux= zhcH|Bt&%uYXhxTm&KFrrz1p5|Ju+T$_Dd!Wb?6vVc@4 z2xJ5|_>zEBc&TS2Qaz`F{^iDeRvN*@%B>Vl^ovCIkA zH8>j8!*{V`|L>wv9YmpP`|;|hfv=24wOJLqU~nNtm%b2?0WnJas*qF*PY6kM$#}J0J|B{5q2lkYx8X?#LQ)A!xH5B|dTU3hLs+-A4g#u3Lt4YY9o%oV+P%1N~m5xm2gsM`S6RY$ywFv1QkaH(Y72>oKx737l zVX83Y(~?K&-aO7dimnVWPK;8er?Gp0cTrKQ^z>FW)US+Er6e%Xe*!@#N>y!Iu2=d6 zF`{4P1hEDw_WveI)pa!L&0Hl-XD;VAFHSad=D{?wlr6>HgVQn3MWah*_)hoAz znCt!@_Ra)8>grnjce0Qn3zGoRu*rZRQ3N7H4F+sR5}atFVH32diCG{uBr%y0P|!ev zC5(BcYFlfyrE0D9)s|;n0IP;Yh>8$gQEN%9+Fy)I+#o74|L?i?Hcc+H8b;JN1)p&EvOroS)6(iGf{P9LTQGdQxSN;I@9w)l2xQ z8G0PJFHDaLP)!egz9n)f-So&C{{rnTil>Kr7n?_zdl!3K=rv-y z*iVOwZ6fCMtUa5)#eFr`W5`R%%P=qaKl38a#oe`Fi%0_sJvg7_o}ZRS6rss12DK4x zvTolr^>bAL>r{65C1c#o5zlk=OYS5FlOHO@S25ave9I70(og7E2a(m2%~F3uo|XdL*sL|JSDT9r|fwL_w`FQX+0`G)50)YL;Sg1#rYk#0oF}WZxW# z;C30qP}$#9?eIFBeG7uTq?t6iGjntO4@E#FL z4I~sk!P)AqCdRqo?FY%QUH?7z^TIj_Ca{wJ z{DJFKnmHnwRBA65k$&zX>x2BUL$Rv=8(gR00&co}2G=P=bDhp6?QnMd$2zIr7nZyUpf{#zI*VPcMbnV?Xxk$!s z<8%Hfa~1b0_R~O-4r9sT4Xob)X_330I+c5$O{<&5#CtAsnezRRnO8rfaOZJld11@d zAd8i}fX4|d1})DRkbI5yC*(EeI#FA9Sc@QIDFsux(#*ZwR1teUzW$B^|Z zvBo#n2zoU8=j_z(&Oir9D?HC@_Y zqD_W+N3U+)M}4N%PoKV*c>U4VD=6cq)QncWZY^dwrhy3E>rmmWI&B4bX|`jn%bnsp0~0ks2QSbyNBrO zM(Y9N!q5;Mxu1yqj}hr`B9-{ER}!v%Y&=G)d>lFvF4=RuA==DfdIIepqOB+IGNbcD zjPcgzD|B?f0$1%yuS5En(?V~vit61$l;d-q&{NOYng_Ex@S10rC}*JfFZg2e8WAYl z;hge8UFK+i5{&i_vK}4nx~-Y5b--dh8qC2TFJ7#RTpQyJ?s7dkMO^k+MHfrKIcVtR z0oSaCgT7(x-X6@VJL2~B<8OceFC~)xJI{w54NvO1DF-2wtKqNYqArs&<+{xNejcOS z-tn=vm$kXvz~S|(X=5aNo?t&)p8>OaaC>lTUFJd`ag6q#)$pu;1mZcI+RZ>Rb2QN~ zY{!X`1mrSqYYueoYwt)xSe*3x?TlGS86?ZB9Xq6X_%7ysSm!ji@BC@~eKR1)*{&yB ztcHt(IzdXoBUJ0i@OE8z324)yBMv7BvR&*n4G@OBRI0%4bEVt>AwN9m^)GnSzQ=?1~Rn0x-z(wq5l?Lu!c zvIJgKJJrtO`GJqUnfq#3W<6^?u^sOU zn%&$X9JZ3MP16Sh`qtla^jabu?$Z@I-1~rU6VBXrWW99#U4&z-NmJgZCf|Kv!cRFJ z<%LeRFNYYXqf2n+jZE2j1(SDu7dJ^inEWs(w+eEnyn%j|9{6qI1>YGV$Lq0>y;?>d zi$vMU@WbZh{oYMe?Bwz?59GPBsizSi-pQz_~C>V`qbpCj*X|;+CBKx9R(&q|fjoE6AJk(m>=CE)6im0O5Pvx=A;mVWTj0hb` znu`%=A*R4nf}Tg}c%y->^R65#1)J=qMUKXm`?J=rT;Oe7*_qSuywBOVvdi;WVnv|m{nmMT(l}jfPUW~oi{h;5^d}zLsj^}iMyBTM_eJK!ejV6jbd|^=x!H5_ zGbsFJEcShuD-9mL49mynqcMZCLhAyskjUgKKVdNmMeZEaf`7yV>Hs~(1F{319YeAX z?sWQ`B&kU90}msX%IZK~r!$aW$WvdI$ap=zSE|wNWe+c zRTSX#=_(qKI$iYx3}DMYqJ0cilM{HSW02>MxG4lu{)krwrJTTDHrIhQ=I{2b>GYkj zF8VaqG6!2n=PbUzuF12?mED39CCl=i;M&qY6o$=*iS^G$krnKvRIV-W#@F`q#M%Cs z`tUcbBbG3Uz8LV~c(fLOhcqJPczcwU2sI6j-~F+y{iT+zH$VfbUG|DF5wo%bIXlqs zRj^A6i|9IyXT_K_+77Cn^DSNgkRgrT*y#(XkH(xfeIaa30Kc30nmvJ?CvWA{cZR-T znAOnfn@Sv^NGZg@k$pxe1qvp=I=?$oKO*&U9D4t3yL8a4J?^Nn-`FYV?ni>jf1XDk zTdet%!5Sz9$!Px>^wpcIfkeijd7+7B?l(pA6CI7{^CAvP-xf^16D!txzp)NKK2o!-E_wm_U!m`Soa!|!biW!Sz3fW$yfY?tI(9*@sn zy8;y)#SGbflqsXmvu@WI@7kPJ*P42g%xQql_$!*4r{Qy-KMQCh2OAG#o z&7^Cvr`)h@@`*nokhA~fZT_gZk2@mbI;r$+ zH1`?PWu@sml`R!uG^PmM9kKv&nK4S~?N*fXkH}t|v!LU|&GK%e-C|<7;k2M5N`@QL zlMw=>33_;7F*~rbxp8HSYt1jj0?AFv+I;d>VpLhK1`!_>w9Z$Zxz)8s7{mJRNR1$w z?_8VcsXrWb?F9Ztb0mwU>&g5D+`W<`fqLoXuq>>4Uc<)ui9TC7t=eCP>F^D0#_BOlO?0G&H2nDvp?!Cp zJg3ub4?nwP_;IcI5!v=Mbdp05)1#k7=&i?C6dr~cln(JsNWR4(rwF0Z!d?v~=fRED z^f;4u5+r1c^)d1ldBwwWxxOGQ8M?LbVx&ap)s>_;k5G}Z88o08xDvW#&uVe;FHjVO zxOgCbkGC-@78&pfUuZ^w?rkip8DHI2?t0mDh1O?TdYvR|xfSqmIcoS(GaWa@nnVsl zQ{&@=2yE8^L-j7%-NHH$Z@$-fk7^k@WIczr-be+@M5|bv;PRBdvYjpb&TQm50$XJb zEh{eTb&j3_@-{{~fzz1E@IA^~jJ)4gU2{#zgPB!j3}yuLBKxGr-+;^d3k8;2e>Jo; zve7P!6SLT6$*J|HaR1#C*eVAHg}i;5$MS-?gvQP6fwX9LfGLB6*yprN4eM076A$CV zpTbJW^_WAr=L5?!Bhc(F7sl%~ciI0gF0RL7$Foq9^-=v7NBjxaKnP;^SsmxW%$k^) z;C%vS7K%N1(JWc`i$@Q+QViFV*-oxyXLSs;Ui?8QxK#)WL51C;>x5-f#Td8ENXud^ z`}p3N9@<20@u%2+1>FVV3CeLBkAo>5La zI?4&(93>Z3h3hO)M%q!LL}#yc5C*a2a*P<-g#KRTvG18*k2)6F=Y?399_0T!2F5jRYV_B8cJ;dYGg=5?|oa=3>7&C@TzROPF zvaj3&ro_qn_+!)3}B!pYp+^fu7m_yMDOnt$N&eQ&Ls4TU9QJ=c4T>rFBY-& zBaIh3sq<5ar>yY|-nlP6AM55L`iAo|nsH27W16=<23ES>Exk(itj!)NIn7_hP@`zM z(r~L~>$J>ln1lxz?vt`-y73pty2omQ#j#J6ZM(kVMUMCSJM@l)keYc6d%F=1nlz(l z9Nwu3V_4nM3t7wB{F83I^7Cx{A?!KL9U`sq=LO#&k;NL24U=K4oG?To+A&JT1pQF0 zPfmCk9rBP|mh7SpmDPBgoLW77wVYaA-j*}9c(DIu*_QWnJqiILvolJ&^hKIZ`yfd# z(mEb=J?dhq&}Ow!GT}M?M3*qXEj!Q{PlMx3&v8SVC-dVK3Pv7%VP!zku_EiH7u#;^v5+1A?;iib(H;6ELc z?DdY)e}IYu?{C<3D4(lr{W_HXG&j89yYl`R|EIZ|f=Bf4hFso+(Z5wFYe(w=joq0S z`K^gp1uqAVQ(*nneh`|2r zK0u zxtls^2>e_;BX$M+sHXGUau4yyMps15#TPc^O-S^j0D_&v($l<69v7Mim%@&x@3wVX z*FDb2FuqM5*U1ug+i!Qp?1t;rG057e>s+5l#qLsXzDape4kdng4NmU)Y9=BX6qzjg zh-5E$5Sf!smPfX-1AaA14uJXN_Q+%C9Aoa%>kl8NC8!}0pCVhx=9Apztm*P`ZM9lX z38Zsne(d@ID!1r!Ig6Q1Q^VnjOY_^!i%h}2hhSb&aFjddot2oI*|L;} z=S`twyvfr@9F1s)hWuE^rG3|;BmA_oZOgZlG4G5Kgdm@~NH)PPM?3tVJF?TTe z4hSGBQ+?9{Io0HdjKjp?Kpg%QgE6%hCuPyggN_8dYcJNtft11Ib%cj+)^uU#s;NSA zf3$UR85wE1xZC1fECOg%%XfOGJa46zNIq$t0UBq3#@SSw7-AxX^+E{`R6p8NEouSx z$t+gDtxlxLEuX~JFh*8V*{~v-f!aBn;U))}m3UhlKJ#BfSCMS>`+bOnPT5pc06U#3D zOC&b3{TfE$p7E{cJW?K}t9fJ-5h_@Bf38AHJaww+?z<$oY|l_e=40VKdx zFPSu&dNxy;$Ce+RLF;oPQ9N{X1$l$dgz89Fkhi`)qDLj^3c@ZbTuGq{D(J4D`gW(# zR1?nO4_8o(sUQw|!byC~`pJ&%5=wNEuvAbAb&)6)1mOmoWIQ~ToaBF5S5K{}p6>eA z^~3DB)YK1kA=MJDCR0CKd(=;!ou1IQOXv&1^I{?W+*qlETubcQ#BRUXwURGgLsEUS zsK`8%GgCoMER(*eezs6Q`qcbww(j~ta9KSEa-G&Wh0^;kjR~WoN@M?os3tnRIWr8m-c%9&R245?9mciEx zo^J5l1y42jV!?+S{C>d`4ZczED1&bjyz6pZ_GZD~H+YNSZ3b@@{3U~L5WL0U`vw1_ z!P^AiXmCsLdkx+x`0WPo68vU^%dvu0XK;BU-SQbcQSikEPZ4~f!QFxv7(7+*Y=fr> zo?-9|!B00htXT9W8r&=RV1pM3?lkxU!4EIgWiJ%G)8LB*f7{^Ig6}u@GQoEnyiV|D zgRd3*VS}$1{CaCo~c=jZM0-LE%ns5`yf z6g#9PbW&ZdUF5%8t8|C1V zE&>q9Q#|YcfZ+ZCYm=-iB;aTg?06a_HqV9^MBVER7DIV~XJrjEY@Or0b%Xn#v(0}A z8VHDLzW2~p*(UqnUEjSOzMyGv|FTtY1zlyUzU*=>eU3#i3NvXU+x$=EZV7Fl^CDmH z)_2mN&s7*NDZ*g(^Nw?(V*RHZ9fa8VKeVTQ|43o?xQshHVy&a_V=jzuN9`TC zTF*)@!gn_1@n#akcTw#}GiMt2=V>i}po#wJptR2H*cAUnS&)g^!{=pQ53MhL779O1 zmmTL1WeLcwF-Q^q0`cfHZ1K9DVIyo(57$iZ@=2!srjoiVLCQMPR2K!I#^$q}^j$=q zT@b3Xzx1l8eLX7bX`Q!v%h_FF*P_L-Gf1`B)wQ)FUPu$7`nRvEwGxa%2;bO>U*TBBxLx@&ejb&eao2#n_loX22o?76Wt| zfrNQt6C8VRD#C@Dmzb#aF7?#8loogm^@C`zo^mj-ul_x_yib!K5Z_huCtv<7sDCfg zH>du+DBr~T_xkxx2tMmO(;Bs0*kvc++4|iw*j!ogn&12x=>-yA0kq4}2Uf2es}}(s zD==>}=EuccVKs2-WW-R6IH8=Hb&Dv7k2HXQSxf-RyL>2-mPs>-pFkt!Dt<2 ztc@0L5y+W06*=<*r;q7ylUlY(Z8{)y;jxf+e==kxZ{?!PTkk&)lhu4=xMDp``H|Lb zKjkn4E{YTN#oqhS?_B?t)0b5LRh%!r{;Md2$Y6Y?cATCUcv6-|d9u0n*54;MZ`3;d zgR%pUZUohL)Rk~JF@&!2P(#(rCwXfkxE@g7WW4*C0zAdS)ce?q%wuNb{okO3e&LGl74b^%0o>nbFw zd`OEE^~&JMmJ0QM?8K97EJPcC0&Xf_{g{LhKS6MP9T zF$cM)fkZaiB9b}a2_$%QYI}X@!Q|hin{1zoY_DNFj>JQ%?O{+bxykmx9$H>{!%raL ziysRSYi*ZAu71E~LXn*ILOW@eLm;ml0tGLo9dMQsQgd+mckOq4UGimtcxCGzB2uO${YECR#7oWHuRqt{BAt(QphtbPRQ9naYVi0 zkPb_)&cLiMIGhb-aSeDVi?Etdc$Uk#ntyoy_}9r)MA?kSs6n}$vdX#ZB;f(IcckWx z-#3FZk)gc)8<{KekGKgV3L#V04{vLYceo8BLD!l}209&OTv_A7Sw|39FX&h=xu}&~ zNRit8c+vAOCwA`oFCuP8sQ)6;e?lO7@fw=hs6ccfurc8>F%7aZ31`o8E!S`=sTCTA zY>cQQD7MH*0~E#cM% zlgp>*wo5bhSMm1C4_V;T@1L{IKq!bJkN4Jp)pqR@VlxsO>uz#ml-;Qa02T_8wVXQU2$F&V%_y(fyuO%@V5!bkf ziUc7NcPNh>g&Gx;w@*Cle69?c?F+La4ra9;LDD-y%X@SG2Dvk>6ZsC$ z!E6^=%M-Xq`<&KVerOOC@SOG10jWe+!?SEANhF6vE(k=m;XOu9um6Cxb$Fc~%Q?he z$f~eekK@t9@HzF;!IBeXI9#sVwg;0hrtT!Nm4t$m&F!Cqt_Il>bKZgz6hPkNO_;$8 zbC3#e$j3#ztZAU#twUJ6?u%H?f^p9yD_dA1%4;f~`V}V@D4*N2F8jp1wRvNTJhJgs zYqL?UR9}LVoURvkpzZG&>xRGTCYhc~^^M=28_9~97w!J-K|RC3p*BHj1y&S3wN%nW z;)clka9cu$79zZC>#uLw9)2hu5Io7yf729$;zG^?#}t}Nvic^|lov#LBU&iKVWDul zd7qZ`GD=B=9v4Xzgky>=8RHf@oAqdXi->}A-b4X}h&h2B!Q`t5CxPU6i?@`T%U~)e@?w#b6cosNZH_L?x zbf#tV?)Y`I9EWZ>5&o07T*twCS$$V*8Rg+(>}@+lv|G*}@?_lz=;8ew*JDDoAD;{- zJQMH!MfJNPMBr+at=c)Tn`xm0FSTJWBq<5&qR8py)1J(owWqYd_jNFcuzyqXX4ZGX zT@>am&)RHP9?kMC&#vs40%)MfORB*B_V+Pp+YS&Yd_AFs5W3;hl8<05 z)5JTv#mUtM-3CX%9&MVFAQ}a-y-km}>2W;5$!WUD&N$Dys4=<09n)g{acfU7Iy~6A z@qcYUlzMOq6r>;3?D39TC@S98NO;t-W{+p`%%;A18}z4A_wie`8Y)?#>zbB&_oCrU z{0Eb(CYUOp#0)@fpqqsz^kxzlxXJozVITSVg0WX`pECjQ$$g&xx7U2FD- z3MCvY?eTcUn#`m|x$1XBNCo>54mrU?g^7MOJvB2umo>6D#<=Q>BT~Zc$1h>hw^@Cev>21Q2WtwMB|_^mZHD)BS0Jdv{;MzDU~*l`XkJdSN=*FLG@WFBlI)=ytcn$FFWq21td6G} z?6$;Xbc6BGCz4%*x}b&V276_3n4}$`6wK%bi%5c`q8sdGV{1Lw?eQG3>QgtEluxUc z?!J4f^+_jMmEqu8y8&_xYgy%?MEb5DQKFS{afrvT%)QgQv9e2qjHTQ=HQLTZHS{)D z_}-~#I~$KxCRTbUvV~^A+Jj5A&Es@~U?)i9Nw$(m9A(h&aV%{sgVV~QPl7s>ageny z>|k918ooBfitecUsD0=>8ymd9xh%mOh**m#ScL1*tsPF8rho8LqCuuMs()k;6=!GfUgYF=z|Lf6KHc+&cao?Ht`0{^z$MWKWs3#l!vEv)`K98k$SS83*u&eSm=4=oy#p%`@EbL`r zTdBB-)`z1ND2ou-8*qF*Xri$7K3_hzr{3r9$cnZpImL&c%$>f}9(teC@tFI~dY_Z< z64v{?^IPhDzLUJ#**+DtuWYk6Z68CnrMQ8)@OfCz??U(EQF@eZ^*-B*)tb4bG}HBHL;qG>JzFibs_B(v7fMiMKJ^4z zSfaZcipiOX!ru%lOJKSUKeg@uY{NTk*gzIUWPXff<)5zzIwrS%ms2({lR^s7zP%#o zjeeoybJqR)8RPp>1U-_erl%t4UEin(y4*z9ry}TZNUaF^Vx&@fD1zR|&_v}^h@%ui zpZ|YN5p*H_3VQxC6+wSTs@r<%B|SLkRR_~G`f0heTh@3ss>se};qnhCg4WHaW1_^W zW9e1|eSTMmD1rur6+weX>0XCFH|No!}`pUJ8m&a8Ejl5;T6E$qcg?K#`L8p$Q z9sHLRLEk{M!Q?i##M74|=u5PFb5HkU6hXg0BZ1?RMbBbn`yW*V{e9t12XZ#(3(m4c zFX*9e>?9Udw4mcCg3cqTUVb)DMaTTNQUrZXoIQMe8%59?j1nJLmZg7K6ZBIf5TIK(T5EznlZ7%9 zjxW|z-xY)Ud8qWwilJ-HF^lMLQVcyE#lwqz6Zsob485M~JRih$G}fI{!JU!dHZjJx zFO>-o)zIz2o&<5XGgk-K8AZ@2haOyao#=*^4U`0MwaW~NZfLPbHMDJyYUqh#U&6x% z0?Sca~jn1yezw3~V z!{KGKQGW2!FrBu6LMOZUaM1hKA0>Ckv|PEHd|s28@Q0hoXSsfWc*0ZQ=vvaZ34`SG z4aw)%yfi19+8nZ*67-#0KmBZ--Elp#JFJiFPI)1iyi*tu5{0)uK9W0Z_l>o zqLx9s$HwG=`9iYf8R zpWbwFe{0-LA|Rm6Lz#-FB--ys*QV$v&|f(D%V74Dc=OcsR}E~2d8O{cK>WM-9g-MK ze*Z*v|Lm2+XCO?@S;DIIn)a;aICO~zl8>Wrt4fK9CXp*TV}DCL!uROwTs_OEPJB0K z$_GtXh{~>j5W?-Dxmt5`Jt?-(fcXBJ# z!NB=lrWZCL*{Br$n|R&~y_NOIYME5gl5o^TJeo_EIXBk)JtvG=BuqF(Gq?NThI1;% z&63yTFw9)-lOwx`QD{MG=S-4AvS)me_5Fjk8p>;vt*m+72e-TDGTm?QC_&vomR$6+ z4ooq({5Jm*0@I|{E9ekCzM^PvA!>p?;^T{#*yS|%7bv$@MBOQ{~A+sSp1 zQv-Nz{dPstfO#RZOL5m;d&>#kJ#3H0Twj_BEBr!+{v0lQ$V91cKIb*%WSDDytnEd* zhxH35P3x2Ork#3()!lEtc2c(7+z} zi#(Z)qy)FyTC6Dgo`@iDwy{_wPYSt%1)W=EPPSwSc*EzWB@d_Isrm}Z&cMrDak4Lp zMNry~6UXn@+69`tM_k^mTHhe!KsGFPxsk<`1B=}UL!Q`W0v2tH=KMB=wN7HsGhEb8 zPWd44B_ck7H)(1-GyIp?(h%s*%Bloy{}L=OFbefiMpf39=~##`&a^aXY8JhY^HcGZ z*=982mrY$9;SHR5`_*ztz%#YC?eb=xc?%|g6&KqBAJVZz-&MzDoUk~#)H`*6|MOsT zSchfdbwVGy1%n$`P@25`t*2{sRnQrleZ#!tKazdM8aPs-3XN?jBQCNI&3 z6ndGr@ysD4NIIeC-=e?x9?c}^%au5?t=~ULjE&Jzr4;k(-%5X8zTCQlXVG!3w%(i- zqJf^r!|lFX28;HeLu^q@rUxYHlbgIw>y+g>(jSnLq(YBRg%0br@u1(WHPTrQ;TDA`{vu3#Z^t?dZ1{bVJIOf@tn) zb=AwN6h^^qaE3jbs3~RrNXktquJ5QJC)W$h*yN<0%0&vU6yiQ^BTvrK)x0y(Nfj@ zNilmWx43J*&2?n3ki^`_>e!RB$9-BdFb>wiKxYyv$RW!Nb-ZZ$M6*ohghJO~z zD7g$Smgh5;pXQBxg$(Dqa$XK5{{n^{eg?2awtj}pkQq*;TR%O)5R+Htc3Yb;kR`M< z+|5MNtzu8A+HGBO5nB}T_Cw>X{SG{Z&IW9`mMjqf(RUHup1>Du5iASOlC@O1vFvGB z5jny?lBSd_c5b8=vKVmn4d#<~if9vsjMmaFecfed3}NID?dr^3ECK`jJe#>?3a_%6 z+tSG0pp3Q8F^@fqQ6m<3Z%R_QTavKm)k+Iqt~|o;nFlxs$#LcH!usSlnR3WVy!UpKlN*M0ykUKjk8MV@KhD|< zW_0~{(OD|*=j^d=)mgoZqf)IywndiNzsA%tZ~5gAipcSF%g3gWMprWy4}K=q#Qw1Y zuZQ+~haq2h04)Jt7FYhUR#`Y9>v~WvDKrqDven^0L$eWxTwXifW1Sg}{1EM()q()M z*39Gil%^5OuamJtKWUk3KWT|Tz;oxV%XVaN08`OD9?v(vVp zI+6*hBQ_9ySrzngKyleRg!)Ovn3T{VBa<(pU+f31jCC}XIVoJ9KDcc)8j`w*#y;`8 zFvYz|YoW-XpB&ryN;Gr+NJ~#ZgcpCG+ysKxGmAuuntST4SnkfyU@ltDS;U& zxYf6PRNoTOI3wjZatYf%$+~iaRDUx!JoftrShI|&5EE~;@3Ag@T#qQUaP%j427`xY zu)SlorghT<#(M*E631Vi$dz z9j;rDSH4hVcI1ffB#{F}2&gH!b{Xp*6tuvC&`Me&0k;(?_)BYl2zq?HMDthr2NU+#9 zdqp`+ytP@^WWp=PCP-_PR?solNHW+`Dsx3}ike|)YGS2N=3jF?md!e=UaO@EwK;oi zPSb1oXMA~9+C5B85t2fa*THJW3XT)9>M3TTmzVFg0@oI6BUQ(=fy&Tb9VsT|?n%L# z$x*E+AT}c$auOtqhH=V7aWIsin1??snDvT~s$D-;#_DIbkTQ3Y8UKUHKZ+$6jnN-| zS4zIaYxLtVJ-?|f(4Z181o8C?COnZA!h5>J>0`i z^-t6hExRhS60GmbkGD9Vys?r`?z)z$2n>GKit9m;V=BOuFQd<>0tsU-k!E`e#5<~f zr1Vm8Q|a;{hfvH%mxdMJlxJ3DL@U+ox@~KKf4%FuekGcrrmz96u3wpsMmKLUvbK8b z%s%|HS~L8hA4+!6Mn6=nwe`b3>al)hq0*N-u4X|P%2k+lR%1yYwx}eue0F3<*DWnx zS)=-j$#6jW^>8}6$YwkLE(@JdCZy8-_3KH2+s}{zQK|cExXFe)ZP;eRPi)w4vhhFM zh8Z@TYr`@duCU=PHvF9pci3>h4J{jX*)Va6iGQ>Wcb{#{TWt7%4cFUnh3#*x4R5pI zZ*924hOgMrvf*JHrlgzr&$8hKHoU@y%WQbF4ezkwHXFWR!?$eMWy5}Fns^7>&~3xh zYFiZ1|83ciQj;8@_GBPiz=znE8!`IP-m$;m18Wm{Y5HQ%}^JsY;EgRUUiOI z!oPEfM`AL+5@r6KuH59o{BvtNu~}~all?+l-#*+zzUSbl8k^oRc$8l);;Y3?eiwjOkdx3)%$0-+{XE1{qssAP ze)*~hbFo@%n`h$pDs24PzGpl|#M5nS%A=IYzk;5UU#@xUd`j6RU!nXMSczHElUPkY zj9I8*(iMM_j>J<$e139LVu!$z-%OqRZo9eUTzu8`@;9G+l<1Nl?J^hNr9FJ-L*vRG zVdvm}v{~{IN>|a!Bt4}}{9=~)q#P2D;}AE?sg}X}F`-7m)3KQ=BtVSp6oHqU3?__z-n~|L}^L%ga1sCS!UvzQ7tl4ws!scCY z>1E$tc=;7q78YGqTvA%LXmR=XuC7>8Syg>aO|8#=?b2n-ue*N5${TJ}GpcHGmX-So zYO0D$rFNIlmWrwS8d^cAnn+8k(0xmKP$ey=93Q2O7}Do!v_H2lM}m@dm$aWe`pz8w z_4E^RmG+cNA3Ogzt}?D%OxyElUwy?eoAEDAP2r!!Ie~aQ2ks`x7-h~zV0 zrOWjg0ewBN;)s1~emGZ}AWY?OXjPN^4Rs?`0rT#s!%;}Z9B(k#cl zg1^_<{-pQB>fUAI7k?$V7i)Lvv67~n)MQ+7<5J1r<>XOP6}M{sNsJ~$IWCpdha1XB zDNU?Pu$7V0t$kii{!QL}^lB-+)M70$R%ky}sth}cPwF&OG8vz`=`=ypX$fh|m?~qA zTct816l1DUr(!B2zDmqeX33M-NJ|iUN{No8RHe?Nv>-DFNcp6N^$eM<^CY9Gs`_a(R~K_o{L%PN9w@17)lGxB%c%iDeWUvo)F#A!sQ6%DMY`%N>CD} zyP-yi9+O#zg!-G*ev$4ard-n7`ije~+n}`LP@cN!J6W9_jxUs-Z&#m7NvrP^`>s<% zhslf@q5OaQ^rUA=pZ(9IcV;-fYTBr21J@E)4ROk^JLeP}wj9%?YawRd!_+Z8y8Na0M^fd>B;_7ZsXY^=KlHX(FTLRT(6ckD<*7Z@O z$2K!YTz%YhLizpAw4b9>k~N;tyeGB0>D}E=rB-Cr@Gv!;$To90rGK3Rj5`;i^l!aw9%!4hZ1W)7+?HVcBZZ`Y)wX$vZFbw{p|*Kryz!63 znf_(j=Ha%vGtRi5WSj4|%_D7dTdZ+++vaN9JjyoLIgLA~1o~HKn?noeEZcmY?e4bC zhix-Q7JA*x~fq@K*EH$#o*pPLy{daCqDv!cuclbxEh z5|fKqdrc_`Ow|8)XN|g+*cWM^vgVN4$iyJ=U9DTdQvRN+^VK_*9KxA(>nLK6WpCRv zwsVNj{8EWQMvMyjp!`xR{S_6U{p7zxaYz~2PxXsPjLON$iI(4)X~ZQS-5CW7Vw~#i zw6ysJuwUJ7-Nc-QiwpTFwXAv>KPNtTNyg~}IQb{WfBm3<`JjDzOiv2MrOc&V9h z`q!Y2{dctgRjT`+Lw&n{J!4p{y8lJM^Z7RaLgC&2Y6HjAzs!LD!!5wED*VrARsZ{c zLp3OHwWIrAgyY-&3xz+nMgOBVf3F8fN`v_qN>NPRc%rRG{_mIA_~`Bb+m*K4SEB01 z4d!5U?f%uRT3z3;=BDqjZCn?)x#{12u>Oa)+gzu550yYIR8 zSNHw;{@*CHbMX#2}se|`I%cmHO!zt{2p2Ooaa`SB;8e)jpnLtS5d z`PE@mas8JWG{8D#(4<&Wn471@LEZvX;fG>BueP-2;;X(_TI|cMEUT(nq8;WFMt->G71jDY#lG@uOAD&1 z{ncT6V`rjM`EW6d7L}e?wakQ^2mddJwdNFd6cgbtqC&<5wEy<2tGlUgRUHeu$eZeJ zT3t6dI+_*Tnl)=6d|FyvLET#ARH@@K3g*|bUSm;LP_UMu?$o-qb%atZ>lQCw>~zK~ ztFB&JU46`YPEKYn;*;~6G5DXUcQR%r+>?hY`x)Wl73o#6oL`8mtVhSPb`I@A2w&tY zs&JRq)Kt~D%PZX#MgGd-#icdpxX0FNPc^KeINMOo_*C-xK{t zXvdFxmEU)K54c05(x~t0E)gfNH_?$?*%lJaSNz{KWDNdpuC6!6I$*w%~%UM=U z2Qf8kYL0l9EGeQ6sXd_}WE(e;`W`1(?c&m_imS%luuJKp-O5L=P9?kQ3nVxn`-?);Uz3|h{Rr+w%CeYj-$(Z<;mirbpb8 z)#%j!kz{-HBVAsbp2%7Ct_Mh_%V+v!PrB=z_4Hp-s+&SjKW=}m5N6)onG?*3Z%_X^ z<#8vEa~IjAkXF<)G$|bGf7CcgTTxN9R3etpy_$m|*fHUbuF+np^pQ?c%_6^4c&$6N z^jb!m@-lbnl4{@bQ~!Q?SJBk$L8yp~($7o7jaeG3dr9e%D*H%pwB6H2>k(1s#nMD}7>hi5W-@nU4Ec;!YamRD(+5)u8k^HE6c0HK94KI+bb^Uehg1 z*pKj~cbO=*fbZ#HP8u4ehE6`AI=OIgnuL+~HpA5Ut1x!#Fpk&=6+5|K+K>qeXO7(A zQp0=$)QKetq!+JTQ(|lSwMDf?zW`H&uKWh02@~t5Tq8%G@}WLRnH~4{jaUoLHSSxStwa;-oAwQWi~T37U;t;ahB{y9fNQJF+5%k zFL9~ia|fv5)bsG!DV-;@*)(wVQ!eVt1x;PEyJ)9+Iw9e1juTa#&ntt?Q7OzN*r@;#zXDtTC)l>P^Gl4GMvw9~F8?Ica77){qu z8>*S5)H8g44CQ~MleF2J)^xX5Y2z8>@9(wS{qvM+xTHI-Bxw(mBf@=b#$`%f%J-_B zmdTH)XUUJWjaYZ$B9nH-2Upsxj^dt z#L0uIwY&Hk-d_#BoAR|KwYr)Us^bge(qd`rNs&2ls5%C>Y!SellY)Vo0(~13q$36Frd@{zHoe+UIU<4 z0`!VkgKvRelE&Ov(qQ~x>@f9D9WhQ1p|0)mzd0$XpGusX z{QmJ-rOHEeJ&F0}mbkY5tuf8f)lr3!1rcdNSE0p_v*Og)^lKu=I?5vZnj_r9$e;At z$-DmO80N?FL(R2WQY5%mXAvN7JmHFc7cBS6u`-APj0z9EZsTXat zBbl*}_LTh4fa-+8_yRpHV`e?nIj}9U)wJf=g5#{WI%U1(h>lRv>6~N?lztFPKLAcP zAszi4s{d8A8R>tkfqD$G`)&ahV?g|Dv(|Ksj8`LlNor(CBI}0%YGn8PX3E7F)MLJBll9(^vlG-Q zzQgL2lCRV$>0hc-9G|K1tjHKE`B={}o6i4vj29E7^_ySX6u}*8nJtShw$<3(9?|W` z`0W1sFZp&un}5l-8#?@7k#8UA=qbk8w7`mYte1C2zM_8@!HHBh5ie>!OsP|R2&7&-}gU(hnDynKj zrVDdsUzC$KW%9(53RbrPCG?*STjN??ggG$t=BpgX9A6Fpb1BU^+6Pq!<4sC8$D23b zQ;@5JzZ&5!EvlYbQ%e3`)VN33Ch8NFQwjTNMoqa7W@*J77#qS;SDBG{rA6149%El^ z%34F+&0StCsodPFy?E4~s1PTuoBnS_&8u9j=~I%ktQbLUQlTP9n)yrUb6n?$$lTiO z(yRQ77M0c%)RfjrlQ<=6wy)xn@*1DNsA66vT&fbKMv7ftRn^u0>X|UMB>{>iET9x| znNd`YbhflEU+FTR8Y^}tXwEX#5s_O70g5Whuj^f8Pi4uR>hj7NResX_5NZkkt)Qx0 zsHUD1+4LUfH#B9B?jK4$AT+xK29l=i%i53WDTs7v>J>-}RF#5zW-v3IDw~*Bmvcq7)hXNs)Oo@{6iz(X=p9+a5WaoJxdB`6M+#L*!SB z98%PrZq~60S36(*Me@;?gBsFZCW%W%0{XB!I@HDIR)zb$`i&VM3QBAAX+&i)?T2B%3Mw@`fC?UWas(I%4ljz-6quPF)EcHufL?a zsHQYb+fwn-gGQGW)szcUb-pSxE+rS2NtEogr5tv#WE@fIPo|~QU${4IT7*5qk^STR z>Z*;LSI9YJKI+syG30uDC~IFc!yeyHPZ#ko-@ktUqQJi>@SmqZsLxHl`@n>sj#ujW z%iS-Oy(G#H%un1;;0yIPIlmX2t)EKai{?w<>&M3yk27&|uFqCbpYMxZJYOuIxW(~> z+$3HJE6~L!@ybvkc1e7&+4Lv&qxi%g*1GoRvCT7VGef8jGuyVGV?!CaB>qeJByAR5 zI-Vs!Hy^{Eez1Whi_X84L;TnANuF2Pa5YfMQqL#u4SbTHAM%~b2MbJ_e+iWQ-peQH z!K%{sj{&7jd-%ltRX%Y~fha;B`GhY2++X5xelcpyhF|IsvzSn3y?({(Zgu7B-+O&>FW-#EFYf=doB^D1g9(Ysq2P=jzP$FmgKQgS z*>IW-Gi;b{!!#SF+R$yo6dO8i*wxR_`F$I<+3-&`+;78|Y}jhU-8O8o;SL)%+whMz z++@RtZMe~f_uKGx8{TZg1{;RrUtyblHmtB=p$!+<&}+jC8>ZRtbQ`*D=(J&1v?+Ig zCVWQ^I(ORkmJQo%xZj4YHf*tBvkf=eaDxrk+i;l;3vF0n!wegy*)Y|HZX2f9Fwuri z8!8)iMVb6}+R(CLn+^Bdu*HTOZMeaP>unf{zs@#S+py4vUK?iE&}~Df4G%|}e0*lZ zHXClT;RYM_q;U^&|F@$J7nuAUFXI1gccH^K(V}y9-}x^bY}a>+fz?9|TyK}RAm5l7 zHuM^|8;1J(Rdzp4J!tgs{CB~LBrIQOylJz?on^%)AOBT&qy2l^ zj(3F}?>`EqzeqlN_Z!)3%1_ow@>3T^%NF;)@5ip8Ms^OIvm)A{-sS6@;7}IuVm7=B zPj#pQ;136JR}(+C0ap%I>U8irUafVBZBib0oZH@C@K`KJl{xIKpjk zH}I@caK?F!GXvPlCus@1X|yR9x}p?%pLAG(Kj9NUw*$Yj?GFPdj4^&T0q;3QsTHJq zFYqJ2dnG@>q2rJh10N2Y14CgG_*~#ue68SzfkRG1h2>cM052F1&Bs6!;6r>;mWP40 zr<*+ZfTz(QQt@*-uz@cdT;R_qaZa9!&MDvrX~;Ta-w7OWhKWBBxQ%ZGes%!QWf@+F zpDf^4d{U=}fk&p0XY5rv=Vg3C!wTTLe4W@^z>8qm90o4{?m7#e3;AyWzRoAK`V;V! z4DyD($V`kqhj;`BMo%Yi;7;I`=TZjn#lSy&N2%X}KMZ__PvWtF^Rs9J)Yk&wwR}RW zW?&ni_z}qU1dR)v$tQU(1UB&P$NzfZ{d{fU8-f49_qN0X+{$Nx?*RVjJmfUMZwKz> zI}F|m+>sA&>=gU}hhAjT8V-DvPiV3Un0>LKt-$nI)Div#e#qwq?*!J(CN0V$@bkIw zt+4L`zH$jqK7*s5Oq4X~vZO6g>NhaBq+WgtjJ(X0D+;)rZxjC40w3fPI&1`%vK8Bp z{bJzze3CbTi3?3wfio_LF9m(Fflu=Zty+M0UBUhld;{<`KC%B3@Dm%4zmmSsC-w!v zdcL{f4ZtV(B&}v(RiVMFfx#m7t@z2fN~tUOB<#(=_7dbdz~2W>;#@-Vp8>p@PyEP9 z#<`1?dKf$l_#|H|cr$QDxxur6&)E2G;N0&)Tl@$-!l!8GTohN!`GkfmfGvCyzrcqp z@PeOaU^a}y#oz*;@&>*em{?`XCGa4h^tCQv)-~jZ_yu0UC+)KkxSdbZ z64{l%@JSip26}2ZlOb#!a1UQ6cq{O7AEMyk)xgXAq(__!fxo-fo)s{DGJq%EOuNKS3h-h+$#Vhl zmwXcTUf{V+hPGM2J8n09;ZER=pVDXXBXGeTCJ#Q~)Sn@5jr}y>HFp~N_<&#V32hGp zH{E6EDe(HA6F>e}0RO-zd3YH3IiJuCJ$)+i7X}yDw!y?BF!63a`jo%}_n5J<4fx8v z45irb2k!or8S@23-DlDjIL*cde#Dn2eG}&HR=x$`JAf6x=j<0;;JF)Vx8Pa88a}D( z4Zt9u~B1Mhv3HViKCmTlx4{5GK4Zsrkzu{(@?Ja7r0 z(76tn_B3V0e-= zBXG)o!h)v*<6fgI;PJrOd=md$U^}0T5AOpXf7|qhKLTgHW9n!w@a%VK(}c|c2KXfG z&A_RDGwp2}@Lj%6{8+$+mdU3;M>}O>&2u_1y#tzp3+#HI^#r)U_zz5*5%>_Fj2jOF zt3HP2_^AeV@X6WL9f1s5oC^MVUZ_`={KZ!hxhVlPl+#swF++{Q(2T;#jOUZBW>3NG+P z8y7yJ$OMbMK#_Zuya^PURIlh`>>~Vs=_|(CGawFw11&^#JKi2_O~C${{G|GYaQ`@#NTop|ND<)Z}nj>eAq7R zop&>?K)kn20aWL`teLS7nN#j_sQaDW=H}ng{~&6}J@sMS$99`rU&EZ(ZC>^s{)s!} zzwJZJlqqEPe&j%AsoR{2o0~6-56NNv9{)FS;zV`+`RA+o^XIGb@^a<(`&FHIudCyK zox1(@+tsgs{cE*(^JdlD+^k-G^;LD`$Pp#mSMjAiW9Sr9y!yfJI_|ygTDp{>9^>BN zM~Ca;4=-K1Vug74D7gFZ-r(*-IPb#j#DK2zAm*h@#cb_G>9;mx8&ppId=xxfrrnpW z=ybkM;NVW%ymYU#OTw3x5x@Ly6#u*TmX+-#eQnn9mzD9*K@dMTO8kd$mmhw#e+e(Y zibI$Wlm6bF+Dsx6{{cx~{|=EpZ#(QIf5cW+Ciy$O_lpCV4vGhz|J8@r?LNHwpu{2O zBeNIg;^A-w@nequ<1>R#y>s_oiclu>aqfR`)gU1NKZaE0{Cdsgq`cjG@o_WWiT^iu zoRMKXXmi)|d+#0n+uho)xD)Pu&$M6{!Q-|6y}S3^Gk15_;k|XuVun7!ujf70byz!# zf9TtOXID@=Yx+wRmT?yUTIu?J?%4&lHaUnIDL zPdAO@Kyep;J;O;neSJ4#AFNXjzDT|pJ{RA}ptSQuJ~!XrYv<|d>FB>jbmQ$ z(|HTE@%8K1s|Ox?w8Q zQy)E5c6F7ykt!;CDj2-+sg5gY30L3v;pbOA3UcGm-{D2jugX?F^Ul0^^PVcpOaFJ^ zl~-SI&BejsBUc7*XdL&{cjsNHZVcY@)Fbo$UwdZ)US*N&{YGU3R2I=O;F3ew0ucft zvXg{_C4ne7GYl%;W59@E34ySVvMJ-rAenI#MT8_SNCJWjq9}_i;#EOVaRm_-Q3Mqc z*Sh~-=e*$%BO=cCJ@-D3{iM_9U8=jPx~jUm>OJqFzei`%{}i)bUw^&Cc`3d^zFKUo z)jl@X+|iLL+QqucYj6+uQ)`v+2_7YTKFJUrqBL&Y*d-(+==}<CIcQ<2Ls=Ik)ikmY!*{zt?(Jh*q?rxtp$UQPU&pmrnZ@0d9n2TR&?#w66 zwSLxI($nVJt~1y9C36E`G?%(b;j%Z)_1j`DU-d8B%w6=6xxrh_4f@pFv}x1a_19nT z3JMC`t+(FlZoBO^cgG!fxcT$vySwkc+t2TkB}?4H4?pZ}+2fBt?lwNP#9j5dxrg_d zd*+#E-1E;r?_PZIMYmzY2DfR`Cimu>Z@PEhdB^SkV6)r!g}L|Md(X?o#~**}_U_*4 z-v7qjo;`cq*I$3_Wd*h#m8iW+Up<2(p{X`YzWWjhkCeUU9?7Yl=(<>IcaimT6K#~6 zZ3XUOTk1C1hQOY>lLQ~vSLa*w_%EcnfWe^>DD3;tul?-u;NDEP!Cip!-))-RGj zHAXR|nTo00C*N875PPMLv(2rYz0=Q`HpRBHz}cRq&h~96$3O8T!N&={mEgMyK2z}O zYfp~gC)ROxLu+Sq`#HORl(RJj>T{{H4>lZtm-Es07{UKR@YMxhL-4Xcd*sAe=tO5- zTRR)r&)MHbIlHyM*|Me1Hf=Zn?`rD37pKVIY2aq*U3N?KcF~t5`Fr$kUaNDVv(|ae z`d#Bp8(b@Rz}eEZ&Ngg`f)5G)9KrVy{2;+k5d2KR-zE451;0}8&k0^*7Q8L^4+Oub z9R5tb6{5F#$Wag1s)xJP!_(^FJ@v4sj=3*do7>yZ+`dufzAiBL%~EsUZLo6qQw85b z@JWI{U+{wkKTh!13I4V^rr&lj_fS7`PmVJ8a)G(Gmzw)z!vXkef`eD>Faih4n zCOykc5o}QMLk(!j0k``_e-?VAtMm>8r3`cHAOV?%nrRzglS~#H@H}vcoid@gg zOzobLr0%zURBrN!(6go)F2%lQFZoRVW9>+#; zAt9Mw-hcSylj_#(-Nkp1;Hhk&>%u<`_>>G?KdJ8Ny(75wX$}g44=1H$o|}=;JtJJ7 z4(i36a>^f%KmPdB`hX+Xd1-s5MhVwH=!P(C;CgEJ%=C6SO`H4vyJe~Ti@lOscDgmAO?7JWoN{ipgN0rRC*!ilTP1}v! z%vI!ixI<#?>VK$GrA{wl2#T2*NfM+3*HhZHZPljw(bY~&*TvLslI63{PE9>O^V9CeTsd-*FH8ZJ` zWUc(Nt_P)8?K&MYQ^d#gsLSv_&EKK(?b@VvlBz^s_Wf&qGtwl8>D}9QtZ+H1e@%3H zO2>ntr5^{E%!4|YeYMq7_Sc%4v{lZ3VB6B}ru zYo~=ydO2&b7P^UA=x)+NcaN)M54qO1()F{oZj^0w1@^XEY9DC*KCsTXL@kJYV+60o zcGj7KKS%J%g3l2AMS>qC_-h3}SMU!A{&~S~DPL!P_fy2a-~E*TlYUBlS61rRuP-H1 zT)Q6s>&G-sOiXOfr%?U+G4&fXkF8y^<{9#b>&3-4ZrrqSVx8Kxnw_BI`VAU3ZK`|g z)Q(L|NKA02#WjylJiSI@9oI~vE~W& zV@_$FcwDt=HL6#wdVI55wdx=9hx*M=KdxF0P9)ZjJ^9!w$HwX2#KhC9SEc_y#vD~w zN5?g+QN4PC_5lqVpL+CZx+;*q@<2O%8Xq1r9Ai>jjnhH+> zH)!Aw-IQ9&fgGzFcLQL-Xd%`>WQS6}xxu{_wNUKKn>(&$eB=c733B%ig_vcWYm|{q48k zUi#c~&)ul!d=ff$?kvgoG-=WB{b+aP=k3?rK@m37UKK$@QTfct2DW>4>14cdq=eG-H z-qNK@Cq44WBa`Izb-()RtIx~J%S)R%b7o)p)!^1lHQ|&~PHCgq#)W5{br!sfNlQzM zr(b>kRrr7T<(DR3rl4WNhHb^enLBsxG{tnw`TX+BFWVb$yy5ZG{CM1%o2^^7+FNhE z<&U8$sPcLIXUW{&&p-cszvS*a^||BQZ@;xKzWCzHS6_Yg(f8kfe~ZTY1{l%#FX>xb z;V=`}UyHx|DbrZx75sw=UxUh=1Qq<@6>adDV`@MLE%*dgI9pIP=N8o9T+ki~{!cyi z)C|pIoMd7;v^@Fblb#0TL-8hK4isnd@&b8t!iKh z32V$+t~NV=o!P<<%)Z*UZ=-Yt{Xd-I@n5-eWkI7xjoQkGpDBB3nh#F{HitQYuh7F> zfIFX=|99Vg*H=EnbNCIu$O5#0H~dFNi#|0=d(ABQ6|+tX!M9V+pv_v*@U&TT(a_`x zv$)61X1=Z5!1p{=aahIUFI#Ux1^=K1a}l&hq9^D9^77Yr&3bOucR5}a|Di#1aLx;6 zXNiW~*Ol-1Uh!`IMs%x{UaS;ZJgibraZ+S?Mw>Qm;v@^xp+ocF=?Undg_p#PgF zVrQaD|LxLIXn4mgT{LtT4NG=K-|@4bKi8Gpe} z^tpxP37!5?dA3Su@c3)KXDD_NC%Zl!TCj(-0S&asJ#t-&9n+M zc>Lqy;>zv6)_B(WpUemP%X$#Z2l~KqpeNujyJxF!z0^u3cD8%Qcd;VTFjq8CvSdF8 ziiQEQ@qgZC1`UBeLqnj?*re9aiSJLDHG>B6KlG^Cd9qU~FI9%W?7f$N>Do;EA#^UF zBcO#jU_FSQlYkal@W)O*JT1i*U(v}HiiW#IL*bY*{PTC4UGj-&*kSfp(SSZxUN(vKIj~7hSD7^|!@r_k z^7zZYpV78$+c^0s)1d>qNQ=xs2R;uiv~Z5KHt@^1#(Im-KzVFx2U|9|gDn*ei$uc$ z(eU_fBW>?)3D04ak45JQ%}IOKXVDP&7)@7}0UyMD*?;UsApadZc5K321QmS+Z*T+m zfEH{&_MUwWc9XS=wT-g!s`mD%Xn1&XM_Y1bCo2^V74`YwvPlIaQf$VsZgyQxs$D%K z)uvpUW;c$#(B6H0y+K2?kKy%MHi=Rh{<8O8{)Nv>a0f41Z~|}i0X_$Ff{l;%kMW0~ z5&3`Wx~}$wXjm>99-1T?qzmXXG@#Geq}yaypCELG5!%Wd|gJ}4>M|H03)sJQ`RFHiR>oMnAe+%>+Lq=|H?mBQqAJKuylP7x`qUEb1Efwd4V{8Jt z@Jr?Orx%y|80hmqBKlkb?vVZu_%rvtdi7!+?7sW%^S&28jp73~Zrr$X8V*Irq2>g9 zut^VLlYU8`MFXW0URQRi9(>ZXHfv-%t!dMy77m9^&t@2YU4DMPjTtk>X3Uu3^;#hx zZ+Gy8Dx(G7vo>I>@P+V4*$+_A=a=spYu|sX{YLRPzdlF%7`H|Ad6sm6QW>(rImIe! z$=Cn0jy?V@TC_MvkM`v1C$>M4AMNL%sHn)!JMTQxvqkogfBeIgQ?i?HzS-l${vLiq z18V{61ad`X4+9O@Q{<4f5FR~!W178kFZl1Xb$5+B;A2P^@G;P5Y|`x$GC}_r_g{+r zU9VK=G~`FJUZ8z{TRjI;DjhamGyUeBNhgfs-o1N!zemr*c>4+N;L039Lr^&fzmYxm zIrw(W1^R$adwteCus#R+j7^Hx=l_0W9)94QfY*m=J9Ox9v!3bkaS+Ci=(6bW%_{0N?U zZq!$FI-sF>^X8^!*Ze%NW+3zUJ^>xz3;xJFbh0;~MIX=+^dXoNT4WI4Bv^acd$WI* zy!@*8C%T3FOO^`tyx1o6R2gx*^2#gyJU|0>Rk39oFkpZ`&m2HQP@y5%_p+zN$42hK zlNK3*wm`l(k57fqEnD(W#h%X5bA~suhd2`ak$Wn#M7$ZAz>S!*p1t$>o0^(x$;rv4 zr&Ihqa2=R{2HHTbf;kEF1pNT_phb?@Gay&^fy`YH-w^(!+m2T~oZ{`L=$@ezK%96u z9esY{i6=Y_@Q1je^uyDTm6c_E`tbltCS*c#*;nFD|H0KH^R zkQ3&Bcox@#!e{zrj+hVDbJ2UZ@WyVECp_HZ@ekybHd=+`C(5)1$XG0H*X#>#`*eM{IA6w8a@7j|1W+|hlao|2DAh;(86zQ zlh$s(Pe7(vYoqxKt{j6ua})Rwe*dfWdpfkh zf7*Z!+JFvPc#3^N7pTk)=a>gQ*m z)I-e){yqK=bdi^%B3rc2KKrbJVh%5jh3 z-D|d9v>!&UHx@gsxI&gmzoZwFp~{FN>eTH9k`=Qm%@eC%HCqJUqWZ zj*9#ad4F5W z19@MbfgrX|&Nq-p^1b94JF9*5V3~|%P0{`}OMY&D@Ca~W{_%mqh4p8}Z6kb4o18N- z`Cxo-_%Go=-jn>fmq+11u8kZI@<@(~Tqk+L3#20|Ya??K%Q~*OORm0uH z0Z;I)7f(+0xjynU#1ScsO(pkA{+OI!v^?@G3ppBcedL&s$Al+5=)Pcl{GcGe$hwN3 z7Wi)gE%*MvjDhA$h80x90s~&T!|qW}~+#=P4X`o(G*EXG;m_$FG<;aboV2DN}~x zgHi)Lh?~F*3h{MvP2@Ppm62y6zd@di922<>a%AL}t{hxeZ@DVRz`@I-@~%PdoBpE5 z#|BXGZK%Czqy<#i&E$1dW7 zO8NZbn<)>GrSDz##}=^P$3KT|aDfN3uN3F_ydn82a<}9R$vw}D(eJm=O>he4Cwgv}i)RY@+Mey3Z1?-G9gs)q z1o>;^an9rm7{1c=U$zy0JC^a4i+C?739oLv&rR!{3UIAIsj1Mq+c%n!Wz za>twYQsFRr^y(D;Dw5N)NSK|Gw%P+tD zS#mtY==FtvV=l7Ivzf`>Zp@Z~= zZwJ4LQ_YSm2|xaKbnuIpa^mA}o>_vrdF zHhnVB;Gp*enBFU3=bn46#|<2)+=C8qA991AguURoM8(1j)h~O6!zteWVt@1;{ZRVb zqL@5uJ~oHkg5Fu+bIj-k_)*|P5aY#PCZ~emE*kF8pocp)`1$bzd4{i4@Srjt>yh4( z;B5oXszN(5$9%zS=*A{1_Hxg!9NUl2II=a~{#S-a-~;PB2d3{k`dBf3Au%W9@i&a^ z$A{iv{Y93bmp-Z3Jai7-hE8OR=XZGaLf;GU_TdQWW^76<^jGA2H2;|cDz+Ef$2{wu z5Xj#y#lx;wAH+|NwD4V%+DBN?uV1onKa1D*vHH$#mGbZF#!eM4RI8}E!>HUBz{CoK znxu08ud%Gd`b4AZ;(RZaq@|Zer-n@sDquD1L^_iXv`R6_N+;foK zQ4V0Y`WU%z;X;32_Z(APT%4|W_R2+z7Ww%M)-dK-HvP5e!N{lS`Dfy+->HwSlE1y^ zA$w!wb+Ps!f0AFvbB#&bTg}lvQ00-J5AH>#@!|fa{uvclNz0z&Mi(D&va&Slf8TY=)>E6frQhTsD!kIqUi?jD47Qw!ceP?^^ zJBd-_Q-L>ji^3j;J=BB$9%b|qT|SYCC8k3hfjt}iW1d)p@PjBTuIcXmE%qPmJ=pu; z>$2Y{z2kbL5BA}`ga`AdchC4dH#Q7DY<;@WmQC&A_mlYU`0eZ)*gH+i?&-()(-yM@ z+SlrP-Zo{*6#t9}c{Sz|c?tOMZ`Qx{YnFJwf0Fh-kpi&~!#}MH-foeT z%*r3pa$M`U(1@(uoXfKFgI}TS64$zAtGKQw)Ch$-j~P8S-~XQLVfNOh3{H^w*@MUG zXB;Q`enKjpM`w>3t5LEq?K?VWoPIfQNOpet#pui3CkT{Z=)JW7yzhg7%lnVI<0qqcPCN+L&WYtj3%qk; zz|XFIQ~IW)rKO+SbHISehu@F?bNoQQ`Eu|2qRmBH^$S0)xLR@F;sM33w%!A(^K0jC zp1))M{`u7kV+!L7+ZXmK98h?9;e^8L3TGECC|q8+ws3Rdj>7$g)rw+@cys?I!MORg z=TE(F*238f=Pz8aaLK~u3s)~(yKw!&%?r0K+_7-a!u<`Eg4X9Ny+6Uc_kA{rj}e+GOJ{E$^4Q9B}+<{m#i*XTe7}nbII0{{UxrnT50Xl zn9@*bd}*uF_NB?Cy-NF*4k*2(^zzcY(g~$gORp=PRXV$Le(8eJC8f(tSC_6WU0=Gn zbZhC3(mkd7OWmSsi)t^5Srl3nzo^xs_KT7i^;)!i(dI?_7sV`Yzj(spS&L^cp1*j( z;w6h$FBUC*^^SHmc|{Y7rWRdSG^=QK(fpzXMN5j77p*Q@TLj;B6zwV6?>SeyIHovM z9ADh3xP5Ui&&NxOFE7q3o=`ls7{>fwe&@jdE)FzoFu3EuvHALS+JRZQxmo!GFU`&$ zHfChrz`W5Thh`5OGclY$X6&UoSp&0j!sAE&Eqhpae9ooAM~1zmmyI4dB9xbt*D~yX=Q%fP zc+0`Vb6V0_C<4Ie8abDR!r@%~f^aw->e40DG#IaGN3E=(kh*G_HG0Uni&|YA>Y^c9 z=8qi|Ke}mri!xFM3a#;14uq0sNsXGG8EUE;1=Fm&lWhH*c|0S=H)|%6s~mNbf9r!@ guUrYyo*Vi%RW8RtEa)5gJ&!7~!yR-hj{pDw literal 0 HcmV?d00001 diff --git a/venv/Scripts/pip3.exe b/venv/Scripts/pip3.exe new file mode 100644 index 0000000000000000000000000000000000000000..5f7120a4b5ca715389f8808b8a2d0fdf336437de GIT binary patch literal 106390 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 guUrYyo*Vi%RW8RtEa)5gJ&!7~!yR-hj{pDw literal 0 HcmV?d00001 diff --git a/venv/Scripts/python.exe b/venv/Scripts/python.exe new file mode 100644 index 0000000000000000000000000000000000000000..2b3a9078901499fe99362ddcc843e0534a3f0885 GIT binary patch literal 539312 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 z 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≈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

    <8B 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

    X|sBL- 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 literal 0 HcmV?d00001 diff --git a/venv/pyvenv.cfg b/venv/pyvenv.cfg new file mode 100644 index 0000000..279fcda --- /dev/null +++ b/venv/pyvenv.cfg @@ -0,0 +1,3 @@ +home = C:\Users\annas\AppData\Local\Programs\Python\Python39 +include-system-site-packages = false +version = 3.9.4

    `Dgu$oBCVtEi>Sq^DNT_^T0TxTP$^_gMNa*N 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 z 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

  • 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/examples/data/scarlet.webp b/venv/Lib/site-packages/pygame/examples/data/scarlet.webp new file mode 100644 index 0000000000000000000000000000000000000000..cd0a15cd97d85989b7bc96e5711965a0a0579d1a GIT binary patch literal 82 zcmWIYbaV4!U|i_?HRd$~*exKL>`!rB90{~XY8#(|0 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/examples/data/secosmic_lo.wav b/venv/Lib/site-packages/pygame/examples/data/secosmic_lo.wav new file mode 100644 index 0000000000000000000000000000000000000000..867f802b988a377c0cbeac4dce096d02d6df9ae1 GIT binary patch literal 18700 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/examples/data/static.png b/venv/Lib/site-packages/pygame/examples/data/static.png new file mode 100644 index 0000000000000000000000000000000000000000..fb3b0572ac41b9ad474d0f33efd38c638ef3ee1b GIT binary patch literal 1202 zcmV;j1Wo&iP)6j@JE;pPXVi z5JTnu<9%s`$ti{dF;p%ct@|H8ImK`whRXfN`_c-NQw#@Us9ZW)_dos)IDP+?^QJNc z0Uw{G{e8c#&vjFS?k;S_NfmH-POs&!3e*iaVFC`#sjD-S-^!eD0mtQZ{vs;=nw(4m zlGBJ*a?)56t`?nEEJg z(BKzow9lq%OpzHNb8G9EPk@<|(JrtCXq?8IK{%vK`+A>E9VDsP3WAzw^$9R>@=3)` zp~QT`=hiwliD-PNQ9619rPDKs6`ueDCu1hnjsabaz=`yzt*VTblj`TQiLQ9f3PcY6 z6ahFVZcQ37U|0g31<#3)$TxMQQ)HN!+O2l-+>{8L7_}w=ASb%wkph^o)>4Y+)Xqo3 zUPX%hN|Q~u-n5zcNfSm9!<=P^xp|Egji$1=YxIbyK2_K&@bTv*?ihwbV zH4$Q8E_W{)e|9Uk1Se>17$VXn0Lmw7)qw$kdtPfFLAAobGWbwqvPsA%q%oPlKq8!; zH6yWjh<&+vg9)4-&6yRn&%Z~~T6J&EjNrnqok!TLxq2kha?HxNe=KWpA~M@{CWMqe zjZ+8QgQ^s+KwCK>^^HE4I2xx*ZaU5do?#PIc>DC-u-`K^<#3^!BpHxT_0XmgMD`bk zeBw`H+L1TpWSEiB?aF!o|15e%q82KAR^*dhZ@J+@1Ze%HAQ;Kv7UZ2P*;R5ig%N>K7JZ&GQt!JW& zRI9CLrhAQRL2F*mHGw2lHJZ-D=O|oLUJonvpNvho0PZ#!kE+hC(ZgH^tM7}&X2G|^ zRlYz{?>+BXs6MHE2tZdeb=ay5fOYS(gs8*vYPDoizhiN1ZwEE(EtEQD6n|sC@8?psdo%41KM4CeRKrmQ+;kED6qV>S72$T$>ZQ@Oj!4ufB+w- zt7BYngP}Y=2{dx@9wQ=0_xX(AKyr%VKn#_cYRM^v12I%)J|(9Z4#ZHI`IMYuI1oc+ z=2LQt;Xn+PnNP_nh66EFWn+a07*qoM6N<$f)Q0S)&Kwi literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/examples/data/teal.svg b/venv/Lib/site-packages/pygame/examples/data/teal.svg new file mode 100644 index 0000000..85f4149 --- /dev/null +++ b/venv/Lib/site-packages/pygame/examples/data/teal.svg @@ -0,0 +1,9 @@ + + teal + + + Layer 1 + + + + diff --git a/venv/Lib/site-packages/pygame/examples/data/turquoise.tif b/venv/Lib/site-packages/pygame/examples/data/turquoise.tif new file mode 100644 index 0000000000000000000000000000000000000000..39b3620f895412d0715f57229d4b93bbf2c14dc4 GIT binary patch literal 1186 zcmaizNoW&M7{~uJZH-G8t6j8OoI~7A(6*E!6k=Lhf)>(Es^;KiGHC}glQ=VJFCrca z?V*Q)2NwkE0($VQJqmgi1i=NwQx6_IDSFX5{@-LYIhgt&`F`*JE$_W=-b*Bo;5dM* zP?CM&wuaDrTurWKdOMpI2h*c{56(u~mxi>_)wS9FeT%UeTJa0DkeJ~Qsl*B=QU%LW zjUQ7>y(Zu~@}_`m$PJQ=!?ay2)=1t#PLZ2~I-5Cf4dTUmZ58#~13pN-L#p%FvKX`{ z;8}7fYc|qirea=Y*Za$kD%xgtcw_GRX7VS&Lyy56k*T^!`)>T)}D07B8qYNiTl1S{9@QH>0*i*J` zJbz^CkwQ+jP*4rajas^^^hCR(U8UtV`1iaGoOJ!qFR^btAmo*tW;(SzylJ`i*l=8# zI(J?PtzjGL(Ttrsab+X;1Ya!Lgfx3^L_jNxIx(2K-d)|+`p0|FFFYW{I z%qr*SSAf26)R)Uz_zuuC4?KBM*3#F3rwhQY_XX8f{iS(VA!m7)zdYoNJqPT31#G=g l>KlE+kNadM=JnO%G+b|~R-)|y0u?7GD literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/examples/data/whiff.wav b/venv/Lib/site-packages/pygame/examples/data/whiff.wav new file mode 100644 index 0000000000000000000000000000000000000000..3954efac71fd426ea235cc7414cff7239ad2e34e GIT binary patch literal 5850 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/examples/data/yellow.tga b/venv/Lib/site-packages/pygame/examples/data/yellow.tga new file mode 100644 index 0000000000000000000000000000000000000000..d0124fe5e50615fd76d265d3392104e3f637a16c GIT binary patch literal 3116 zcmZQzU}As)1qKBM2?mD$|3}ei2#kinXb6mkz-S1JhQMeDjE2By2#kinNC^RGcOWDv U)HTdA*wf!nH^R-+$5oF30E^H4uK)l5 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/examples/dropevent.py b/venv/Lib/site-packages/pygame/examples/dropevent.py new file mode 100644 index 0000000..e812558 --- /dev/null +++ b/venv/Lib/site-packages/pygame/examples/dropevent.py @@ -0,0 +1,76 @@ +#!/usr/bin/env python +""" pygame.examples.dropfile + +Drag and drop an image on here. + +Uses these events: + +* DROPBEGIN +* DROPCOMPLETE +* DROPTEXT +* DROPFILE +""" +import pygame as pg + +if pg.get_sdl_version() < (2, 0, 0): + raise Exception("This example requires SDL2.") + +pg.init() + + +def main(): + + Running = True + surf = pg.display.set_mode((640, 480)) + font = pg.font.SysFont("Arial", 24) + clock = pg.time.Clock() + + spr_file_text = font.render("Feed me some file or image!", 1, (255, 255, 255)) + spr_file_text_rect = spr_file_text.get_rect() + spr_file_text_rect.center = surf.get_rect().center + + spr_file_image = None + spr_file_image_rect = None + + while Running: + for ev in pg.event.get(): + if ev.type == pg.QUIT: + Running = False + elif ev.type == pg.DROPBEGIN: + print(ev) + print("File drop begin!") + elif ev.type == pg.DROPCOMPLETE: + print(ev) + print("File drop complete!") + elif ev.type == pg.DROPTEXT: + print(ev) + spr_file_text = font.render(ev.text, 1, (255, 255, 255)) + spr_file_text_rect = spr_file_text.get_rect() + spr_file_text_rect.center = surf.get_rect().center + elif ev.type == pg.DROPFILE: + print(ev) + spr_file_text = font.render(ev.file, 1, (255, 255, 255)) + spr_file_text_rect = spr_file_text.get_rect() + spr_file_text_rect.center = surf.get_rect().center + + # Try to open the file if it's an image + filetype = ev.file[-3:] + if filetype in ["png", "bmp", "jpg"]: + spr_file_image = pg.image.load(ev.file).convert() + spr_file_image.set_alpha(127) + spr_file_image_rect = spr_file_image.get_rect() + spr_file_image_rect.center = surf.get_rect().center + + surf.fill((0, 0, 0)) + surf.blit(spr_file_text, spr_file_text_rect) + if spr_file_image: + surf.blit(spr_file_image, spr_file_image_rect) + + pg.display.flip() + clock.tick(30) + + pg.quit() + + +if __name__ == "__main__": + main() diff --git a/venv/Lib/site-packages/pygame/examples/eventlist.py b/venv/Lib/site-packages/pygame/examples/eventlist.py new file mode 100644 index 0000000..b329586 --- /dev/null +++ b/venv/Lib/site-packages/pygame/examples/eventlist.py @@ -0,0 +1,196 @@ +#!/usr/bin/env python +""" pygame.examples.eventlist + +Learn about pygame events and input. + +At the top of the screen are the state of several device values, +and a scrolling list of events are displayed on the bottom. + +""" + +usage = """ +Mouse Controls +============== + +- 1st button on mouse (left click) to toggle events 'grabed'. +- 3rd button on mouse (right click) to toggle mouse visible. +- The window can be resized. +- Mouse the mouse around to see mouse events. +- If events grabbed and mouse invisible show virtual mouse coords. + + +Keyboard Joystick Controls +========================== + +- press keys up an down to see events. +- you can see joystick events if any are plugged in. +- press "c" to toggle events generated by controllers. +""" + +import pygame as pg + +try: + import pygame._sdl2.controller + + pygame._sdl2.controller.init() + SDL2 = True +except ImportError: + SDL2 = False + +img_on_off = [] +font = None +last_key = None + +# these are a running counter of mouse.get_rel() calls. +virtual_x = 0 +virtual_y = 0 + + +def showtext(win, pos, text, color, bgcolor): + textimg = font.render(text, 1, color, bgcolor) + win.blit(textimg, pos) + return pos[0] + textimg.get_width() + 5, pos[1] + + +def drawstatus(win): + global virtual_x, virtual_y + bgcolor = 50, 50, 50 + win.fill(bgcolor, (0, 0, 640, 120)) + win.blit(font.render("Status Area", 1, (155, 155, 155), bgcolor), (2, 2)) + + pos = showtext(win, (10, 30), "Mouse Focus", (255, 255, 255), bgcolor) + win.blit(img_on_off[pg.mouse.get_focused()], pos) + + pos = showtext( + win, (pos[0] + 50, pos[1]), "Mouse visible", (255, 255, 255), bgcolor + ) + win.blit(img_on_off[pg.mouse.get_visible()], pos) + + pos = showtext(win, (330, 30), "Keyboard Focus", (255, 255, 255), bgcolor) + win.blit(img_on_off[pg.key.get_focused()], pos) + + pos = showtext(win, (10, 60), "Mouse Position(rel)", (255, 255, 255), bgcolor) + rel = pg.mouse.get_rel() + virtual_x += rel[0] + virtual_y += rel[1] + + mouse_data = tuple(list(pg.mouse.get_pos()) + list(rel)) + p = "%s, %s (%s, %s)" % mouse_data + showtext(win, pos, p, bgcolor, (255, 255, 55)) + + pos = showtext(win, (330, 60), "Last Keypress", (255, 255, 255), bgcolor) + if last_key: + p = "%d, %s" % (last_key, pg.key.name(last_key)) + else: + p = "None" + showtext(win, pos, p, bgcolor, (255, 255, 55)) + + pos = showtext(win, (10, 90), "Input Grabbed", (255, 255, 255), bgcolor) + win.blit(img_on_off[pg.event.get_grab()], pos) + + is_virtual_mouse = pg.event.get_grab() and not pg.mouse.get_visible() + pos = showtext(win, (330, 90), "Virtual Mouse", (255, 255, 255), bgcolor) + win.blit(img_on_off[is_virtual_mouse], pos) + if is_virtual_mouse: + p = "%s, %s" % (virtual_x, virtual_y) + showtext(win, (pos[0] + 50, pos[1]), p, bgcolor, (255, 255, 55)) + + +def drawhistory(win, history): + img = font.render("Event History Area", 1, (155, 155, 155), (0, 0, 0)) + win.blit(img, (2, 132)) + ypos = 450 + h = list(history) + h.reverse() + for line in h: + r = win.blit(line, (10, ypos)) + win.fill(0, (r.right, r.top, 620, r.height)) + ypos -= font.get_height() + + +def draw_usage_in_history(history, text): + lines = text.split("\n") + for line in lines: + if line == "" or "===" in line: + continue + img = font.render(line, 1, (50, 200, 50), (0, 0, 0)) + history.append(img) + + +def main(): + pg.init() + print(usage) + + win = pg.display.set_mode((640, 480), pg.RESIZABLE) + pg.display.set_caption("Mouse Focus Workout. h key for help") + + global font + font = pg.font.Font(None, 26) + + global img_on_off + img_on_off.append(font.render("Off", 1, (0, 0, 0), (255, 50, 50))) + img_on_off.append(font.render("On", 1, (0, 0, 0), (50, 255, 50))) + + # stores surfaces of text representing what has gone through the event queue + history = [] + + # let's turn on the joysticks just so we can play with em + for x in range(pg.joystick.get_count()): + if SDL2 and pg._sdl2.controller.is_controller(x): + c = pg._sdl2.controller.Controller(x) + txt = "Enabled controller: " + c.name + else: + j = pg.joystick.Joystick(x) + txt = "Enabled joystick: " + j.get_name() + + img = font.render(txt, 1, (50, 200, 50), (0, 0, 0)) + history.append(img) + if not pg.joystick.get_count(): + img = font.render("No Joysticks to Initialize", 1, (50, 200, 50), (0, 0, 0)) + history.append(img) + + going = True + while going: + for e in pg.event.get(): + if e.type == pg.KEYDOWN: + if e.key == pg.K_ESCAPE: + going = False + else: + global last_key + last_key = e.key + if e.key == pg.K_h: + draw_usage_in_history(history, usage) + if SDL2 and e.key == pg.K_c: + current_state = pg._sdl2.controller.get_eventstate() + pg._sdl2.controller.set_eventstate(not current_state) + + if e.type == pg.MOUSEBUTTONDOWN and e.button == 1: + pg.event.set_grab(not pg.event.get_grab()) + + if e.type == pg.MOUSEBUTTONDOWN and e.button == 3: + pg.mouse.set_visible(not pg.mouse.get_visible()) + + if e.type != pg.MOUSEMOTION: + txt = "%s: %s" % (pg.event.event_name(e.type), e.dict) + img = font.render(txt, 1, (50, 200, 50), (0, 0, 0)) + history.append(img) + history = history[-13:] + + if e.type == pg.VIDEORESIZE: + win = pg.display.set_mode(e.size, pg.RESIZABLE) + + if e.type == pg.QUIT: + going = False + + drawstatus(win) + drawhistory(win, history) + + pg.display.flip() + pg.time.wait(10) + + pg.quit() + raise SystemExit + + +if __name__ == "__main__": + main() diff --git a/venv/Lib/site-packages/pygame/examples/font_viewer.py b/venv/Lib/site-packages/pygame/examples/font_viewer.py new file mode 100644 index 0000000..7170fd4 --- /dev/null +++ b/venv/Lib/site-packages/pygame/examples/font_viewer.py @@ -0,0 +1,279 @@ +#!/usr/bin/env python +""" pygame.examples.font_viewer +Scroll through your system fonts from a list of surfaces or one huge buffer. + +This example exhibits: +* iterate over available fonts using font.get_fonts and font.SysFont() +* click and drag using mouse input +* scrolling with the scroll wheel +* save a surface to disk +* work with a very large surface +* simple mouse and keyboard scroll speed acceleration + +By default this example uses the fonts returned by pygame.font.get_fonts() +and opens them using pygame.font.SysFont(). +Alternatively, you may pass a path to the command line. The TTF files found +in that directory will be used instead. + +Mouse Controls: +* Use the mouse wheel or click and drag to scroll + +Keyboard Controls: +* Press up or down to scroll +* Press escape to exit +""" +import sys +import os + +import pygame as pg + +use_big_surface = False # draw into large buffer and save png file + + +class FontViewer: + """ + This example is encapsulated by the fontviewer class + It initializes the pygame window, handles input, and draws itself + to the screen. + """ + + KEY_SCROLL_SPEED = 10 + MOUSE_SCROLL_SPEED = 50 + + def __init__(self, **dparams): + pg.init() + self.font_dir = dparams.get("folder", None) + + # create a window that uses 80 percent of the screen + info = pg.display.Info() + w = info.current_w + h = info.current_h + pg.display.set_mode((int(w * 0.8), int(h * 0.8))) + self.font_size = h // 20 + + self.clock = pg.time.Clock() + self.y_offset = 0 + self.grabbed = False + self.render_fonts("&N abcDEF789") + + if use_big_surface or "big" in sys.argv: + self.render_surface() + self.display_surface() + self.save_png() + else: + self.display_fonts() + + def get_font_list(self): + """ + Generate a font list using font.get_fonts() for system fonts or + from a path from the command line. + """ + path = "" + if len(sys.argv) > 1 and os.path.exists(sys.argv[1]): + path = os.path.join(sys.argv[1], "") + fonts = [] + if os.path.exists(path): + # this list comprehension could replace the following loop + # fonts = [f in os.listdir(path) if f.endswith('.ttf')] + for font in os.listdir(path): + if font.endswith(".ttf"): + fonts.append(font) + return fonts or pg.font.get_fonts(), path + + def render_fonts(self, text="A display of font &N", **dparams): + """ + Build a list that includes a surface and the running total of their + height for each font in the font list. Store the largest width and + other variables for later use. + """ + font_size = dparams.get("size", 0) or self.font_size + color = dparams.get("color", (255, 255, 255)) + self.back_color = dparams.get("back_color", (0, 0, 0)) + + fonts, path = self.get_font_list() + font_surfaces = [] + total_height = 0 + max_width = 0 + + load_font = pg.font.Font if path else pg.font.SysFont + + # display instructions at the top of the display + font = pg.font.SysFont(pg.font.get_default_font(), font_size) + lines = ( + "Use the scroll wheel or click and drag", + "to scroll up and down", + "Foreign fonts might render incorrectly", + "Here are your {} fonts".format(len(fonts)), + "", + ) + for line in lines: + surf = font.render(line, 1, color, self.back_color) + font_surfaces.append((surf, total_height)) + total_height += surf.get_height() + max_width = max(max_width, surf.get_width()) + + # render all the fonts and store them with the total height + for name in sorted(fonts): + try: + font = load_font(path + name, font_size) + except IOError: + continue + line = text.replace("&N", name) + try: + surf = font.render(line, 1, color, self.back_color) + except pg.error as e: + print(e) + break + + max_width = max(max_width, surf.get_width()) + font_surfaces.append((surf, total_height)) + total_height += surf.get_height() + + # store variables for later usage + self.total_height = total_height + self.max_width = max_width + self.font_surfaces = font_surfaces + self.max_y = total_height - pg.display.get_surface().get_height() + + def display_fonts(self): + """ + Display the visible fonts based on the y_offset value(updated in + handle_events) and the height of the pygame window. + """ + display = pg.display.get_surface() + clock = pg.time.Clock() + center = display.get_width() // 2 + + while True: + # draw visible surfaces + display.fill(self.back_color) + for surface, top in self.font_surfaces: + bottom = top + surface.get_height() + if ( + bottom >= self.y_offset + and top <= self.y_offset + display.get_height() + ): + x = center - surface.get_width() // 2 + display.blit(surface, (x, top - self.y_offset)) + # get input and update the screen + if not self.handle_events(): + break + pg.display.flip() + clock.tick(30) + + def render_surface(self): + """ + Note: this method uses twice the memory and is only called if + big_surface is set to true or big is added to the command line. + + Optionally generates one large buffer to draw all the font surfaces + into. This is necessary to save the display to a png file and may + be useful for testing large surfaces. + """ + + large_surface = pg.surface.Surface( + (self.max_width, self.total_height) + ).convert() + large_surface.fill(self.back_color) + print("scrolling surface created") + + # display the surface size and memory usage + byte_size = large_surface.get_bytesize() + total_size = byte_size * (self.max_width * self.total_height) + print( + "Surface Size = {}x{} @ {}bpp: {:,.3f}mb".format( + self.max_width, self.total_height, byte_size, total_size / 1000000.0 + ) + ) + + y = 0 + center = int(self.max_width / 2) + for surface, top in self.font_surfaces: + w = surface.get_width() + x = center - int(w / 2) + large_surface.blit(surface, (x, y)) + y += surface.get_height() + self.max_y = large_surface.get_height() - pg.display.get_surface().get_height() + self.surface = large_surface + + def display_surface(self, time=10): + """ + Display the large surface created by the render_surface method. Scrolls + based on the y_offset value(set in handle_events) and the height of the + pygame window. + """ + screen = pg.display.get_surface() + + # Create a Rect equal to size of screen. Then we can just change its + # top attribute to draw the desired part of the rendered font surface + # to the display surface + rect = pg.rect.Rect( + 0, + 0, + self.surface.get_width(), + min(self.surface.get_height(), screen.get_height()), + ) + + x = int((screen.get_width() - self.surface.get_width()) / 2) + going = True + while going: + if not self.handle_events(): + going = False + screen.fill(self.back_color) + rect.top = self.y_offset + screen.blit(self.surface, (x, 0), rect) + pg.display.flip() + self.clock.tick(20) + + def save_png(self, name="font_viewer.png"): + pg.image.save(self.surface, name) + file_size = os.path.getsize(name) // 1024 + print("font surface saved to {}\nsize: {:,}Kb".format(name, file_size)) + + def handle_events(self): + """ + This method handles user input. It returns False when it receives + a pygame.QUIT event or the user presses escape. The y_offset is + changed based on mouse and keyboard input. display_fonts() and + display_surface() use the y_offset to scroll display. + """ + events = pg.event.get() + for e in events: + if e.type == pg.QUIT: + return False + elif e.type == pg.KEYDOWN: + if e.key == pg.K_ESCAPE: + return False + elif e.type == pg.MOUSEWHEEL: + self.y_offset += e.y * self.MOUSE_SCROLL_SPEED * -1 + elif e.type == pg.MOUSEBUTTONDOWN: + # enter dragging mode on mouse down + self.grabbed = True + pg.event.set_grab(True) + elif e.type == pg.MOUSEBUTTONUP: + # exit drag mode on mouse up + self.grabbed = False + pg.event.set_grab(False) + + # allow simple accelerated scrolling with the keyboard + keys = pg.key.get_pressed() + if keys[pg.K_UP]: + self.key_held += 1 + self.y_offset -= int(self.KEY_SCROLL_SPEED * (self.key_held // 10)) + elif keys[pg.K_DOWN]: + self.key_held += 1 + self.y_offset += int(self.KEY_SCROLL_SPEED * (self.key_held // 10)) + else: + self.key_held = 20 + + # set the y_offset for scrolling and keep it between 0 and max_y + y = pg.mouse.get_rel()[1] + if y and self.grabbed: + self.y_offset -= y + + self.y_offset = min((max(self.y_offset, 0), self.max_y)) + return True + + +viewer = FontViewer() +pg.quit() diff --git a/venv/Lib/site-packages/pygame/examples/fonty.py b/venv/Lib/site-packages/pygame/examples/fonty.py new file mode 100644 index 0000000..3eed676 --- /dev/null +++ b/venv/Lib/site-packages/pygame/examples/fonty.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python +""" pygame.examples.fonty + +Here we load a .TTF True Type font file, and display it in +a basic pygame window. + +Demonstrating several Font object attributes. + +- basic window, event, and font management. +""" +import pygame as pg + +def main(): + # initialize + pg.init() + resolution = 400, 200 + screen = pg.display.set_mode(resolution) + + ## pg.mouse.set_cursor(*pg.cursors.diamond) + + fg = 250, 240, 230 + bg = 5, 5, 5 + wincolor = 40, 40, 90 + + # fill background + screen.fill(wincolor) + + # load font, prepare values + font = pg.font.Font(None, 80) + text = "Fonty" + size = font.size(text) + + # no AA, no transparancy, normal + ren = font.render(text, 0, fg, bg) + screen.blit(ren, (10, 10)) + + # no AA, transparancy, underline + font.set_underline(1) + ren = font.render(text, 0, fg) + screen.blit(ren, (10, 40 + size[1])) + font.set_underline(0) + + a_sys_font = pg.font.SysFont("Arial", 60) + + # AA, no transparancy, bold + a_sys_font.set_bold(1) + ren = a_sys_font.render(text, 1, fg, bg) + screen.blit(ren, (30 + size[0], 10)) + a_sys_font.set_bold(0) + + # AA, transparancy, italic + a_sys_font.set_italic(1) + ren = a_sys_font.render(text, 1, fg) + screen.blit(ren, (30 + size[0], 40 + size[1])) + a_sys_font.set_italic(0) + + # Get some metrics. + print("Font metrics for 'Fonty': %s" % a_sys_font.metrics(text)) + ch = "\u3060" + msg = "Font metrics for '%s': %s" % (ch, a_sys_font.metrics(ch)) + print(msg) + + ## #some_japanese_unicode = u"\u304b\u3070\u306b" + ##some_japanese_unicode = unicode_('%c%c%c') % (0x304b, 0x3070, 0x306b) + + # AA, transparancy, italic + ##ren = a_sys_font.render(some_japanese_unicode, 1, fg) + ##screen.blit(ren, (30 + size[0], 40 + size[1])) + + # show the surface and await user quit + pg.display.flip() + while True: + # use event.wait to keep from polling 100% cpu + if pg.event.wait().type in (pg.QUIT, pg.KEYDOWN, pg.MOUSEBUTTONDOWN): + break + pg.quit() + + +if __name__ == "__main__": + main() diff --git a/venv/Lib/site-packages/pygame/examples/freetype_misc.py b/venv/Lib/site-packages/pygame/examples/freetype_misc.py new file mode 100644 index 0000000..d07c422 --- /dev/null +++ b/venv/Lib/site-packages/pygame/examples/freetype_misc.py @@ -0,0 +1,157 @@ +#!/usr/bin/env python +""" pygame.examples.freetype_misc + + +Miscellaneous (or misc) means: + "consisting of a mixture of various things that are not + usually connected with each other" + Adjective + + +All those words you read on computers, magazines, books, and such over the years? +Probably a lot of them were constructed with... + +The FreeType Project: a free, high-quality and portable Font engine. +https://freetype.org + +Next time you're reading something. Think of them. + + +Herein lies a *BOLD* demo consisting of a mixture of various things. + + Not only is it a *BOLD* demo, it's an + italics demo, + a rotated demo, + it's a blend, + and is sized to go nicely with a cup of tea*. + + * also goes well with coffee. + +Enjoy! +""" +import os +import pygame as pg +import pygame.freetype as freetype + + +def run(): + pg.init() + + fontdir = os.path.dirname(os.path.abspath(__file__)) + font = freetype.Font(os.path.join(fontdir, "data", "sans.ttf")) + + screen = pg.display.set_mode((800, 600)) + screen.fill("gray") + + font.underline_adjustment = 0.5 + font.pad = True + font.render_to( + screen, + (32, 32), + "Hello World", + "red3", + "dimgray", + size=64, + style=freetype.STYLE_UNDERLINE | freetype.STYLE_OBLIQUE, + ) + font.pad = False + + font.render_to( + screen, + (32, 128), + "abcdefghijklm", + "dimgray", + "green3", + size=64, + ) + + font.vertical = True + font.render_to(screen, (32, 200), "Vertical?", "blue3", None, size=32) + font.vertical = False + + font.render_to(screen, (64, 190), "Let's spin!", "red3", None, size=48, rotation=55) + + font.render_to( + screen, (160, 290), "All around!", "green3", None, size=48, rotation=-55 + ) + + font.render_to(screen, (250, 220), "and BLEND", (255, 0, 0, 128), None, size=64) + + font.render_to(screen, (265, 237), "or BLAND!", (0, 0xCC, 28, 128), None, size=64) + + # Some pinwheels + font.origin = True + for angle in range(0, 360, 45): + font.render_to(screen, (150, 420), ")", "black", size=48, rotation=angle) + font.vertical = True + for angle in range(15, 375, 30): + font.render_to(screen, (600, 400), "|^*", "orange", size=48, rotation=angle) + font.vertical = False + font.origin = False + + utext = "I \u2665 Unicode" + font.render_to(screen, (298, 320), utext, (0, 0xCC, 0xDD), None, size=64) + + utext = "\u2665" + font.render_to(screen, (480, 32), utext, "gray", "red3", size=148) + + font.render_to( + screen, + (380, 380), + "...yes, this is an SDL surface", + "black", + None, + size=24, + style=freetype.STYLE_STRONG, + ) + + font.origin = True + r = font.render_to( + screen, + (100, 530), + "stretch", + "red3", + None, + size=(24, 24), + style=freetype.STYLE_NORMAL, + ) + font.render_to( + screen, + (100 + r.width, 530), + " VERTICAL", + "red3", + None, + size=(24, 48), + style=freetype.STYLE_NORMAL, + ) + + r = font.render_to( + screen, + (100, 580), + "stretch", + "blue3", + None, + size=(24, 24), + style=freetype.STYLE_NORMAL, + ) + font.render_to( + screen, + (100 + r.width, 580), + " HORIZONTAL", + "blue3", + None, + size=(48, 24), + style=freetype.STYLE_NORMAL, + ) + + pg.display.flip() + + while 1: + if pg.event.wait().type in (pg.QUIT, pg.KEYDOWN, pg.MOUSEBUTTONDOWN): + break + + pg.quit() + + +if __name__ == "__main__": + run() diff --git a/venv/Lib/site-packages/pygame/examples/glcube.py b/venv/Lib/site-packages/pygame/examples/glcube.py new file mode 100644 index 0000000..9d85c24 --- /dev/null +++ b/venv/Lib/site-packages/pygame/examples/glcube.py @@ -0,0 +1,591 @@ +#!/usr/bin/env python +""" pygame.examples.glcube + +Draw a cube on the screen. + + + +Amazing. + +Every frame we orbit the camera around a small amount +creating the illusion of a spinning object. + +First we setup some points of a multicolored cube. Then we then go through +a semi-unoptimized loop to draw the cube points onto the screen. + +OpenGL does all the hard work for us. :] + + +Keyboard Controls +----------------- + +* ESCAPE key to quit +* f key to toggle fullscreen. + +""" +import math +import ctypes + +import pygame as pg + +try: + import OpenGL.GL as GL + import OpenGL.GLU as GLU +except ImportError: + print("pyopengl missing. The GLCUBE example requires: pyopengl numpy") + raise SystemExit + +try: + from numpy import array, dot, eye, zeros, float32, uint32 +except ImportError: + print("numpy missing. The GLCUBE example requires: pyopengl numpy") + raise SystemExit + + +# do we want to use the 'modern' OpenGL API or the old one? +# This example shows you how to do both. +USE_MODERN_GL = True + +# Some simple data for a colored cube here we have the 3D point position +# and color for each corner. A list of indices describes each face, and a +# list of indices describes each edge. + +CUBE_POINTS = ( + (0.5, -0.5, -0.5), + (0.5, 0.5, -0.5), + (-0.5, 0.5, -0.5), + (-0.5, -0.5, -0.5), + (0.5, -0.5, 0.5), + (0.5, 0.5, 0.5), + (-0.5, -0.5, 0.5), + (-0.5, 0.5, 0.5), +) + +# colors are 0-1 floating values +CUBE_COLORS = ( + (1, 0, 0), + (1, 1, 0), + (0, 1, 0), + (0, 0, 0), + (1, 0, 1), + (1, 1, 1), + (0, 0, 1), + (0, 1, 1), +) + +CUBE_QUAD_VERTS = ( + (0, 1, 2, 3), + (3, 2, 7, 6), + (6, 7, 5, 4), + (4, 5, 1, 0), + (1, 5, 7, 2), + (4, 0, 3, 6), +) + +CUBE_EDGES = ( + (0, 1), + (0, 3), + (0, 4), + (2, 1), + (2, 3), + (2, 7), + (6, 3), + (6, 4), + (6, 7), + (5, 1), + (5, 4), + (5, 7), +) + + +def translate(matrix, x=0.0, y=0.0, z=0.0): + """ + Translate (move) a matrix in the x, y and z axes. + + :param matrix: Matrix to translate. + :param x: direction and magnitude to translate in x axis. Defaults to 0. + :param y: direction and magnitude to translate in y axis. Defaults to 0. + :param z: direction and magnitude to translate in z axis. Defaults to 0. + :return: The translated matrix. + """ + translation_matrix = array( + [ + [1.0, 0.0, 0.0, x], + [0.0, 1.0, 0.0, y], + [0.0, 0.0, 1.0, z], + [0.0, 0.0, 0.0, 1.0], + ], + dtype=matrix.dtype, + ).T + matrix[...] = dot(matrix, translation_matrix) + return matrix + + +def frustum(left, right, bottom, top, znear, zfar): + """ + Build a perspective matrix from the clipping planes, or camera 'frustrum' + volume. + + :param left: left position of the near clipping plane. + :param right: right position of the near clipping plane. + :param bottom: bottom position of the near clipping plane. + :param top: top position of the near clipping plane. + :param znear: z depth of the near clipping plane. + :param zfar: z depth of the far clipping plane. + + :return: A perspective matrix. + """ + perspective_matrix = zeros((4, 4), dtype=float32) + perspective_matrix[0, 0] = +2.0 * znear / (right - left) + perspective_matrix[2, 0] = (right + left) / (right - left) + perspective_matrix[1, 1] = +2.0 * znear / (top - bottom) + perspective_matrix[3, 1] = (top + bottom) / (top - bottom) + perspective_matrix[2, 2] = -(zfar + znear) / (zfar - znear) + perspective_matrix[3, 2] = -2.0 * znear * zfar / (zfar - znear) + perspective_matrix[2, 3] = -1.0 + return perspective_matrix + + +def perspective(fovy, aspect, znear, zfar): + """ + Build a perspective matrix from field of view, aspect ratio and depth + planes. + + :param fovy: the field of view angle in the y axis. + :param aspect: aspect ratio of our view port. + :param znear: z depth of the near clipping plane. + :param zfar: z depth of the far clipping plane. + + :return: A perspective matrix. + """ + h = math.tan(fovy / 360.0 * math.pi) * znear + w = h * aspect + return frustum(-w, w, -h, h, znear, zfar) + + +def rotate(matrix, angle, x, y, z): + """ + Rotate a matrix around an axis. + + :param matrix: The matrix to rotate. + :param angle: The angle to rotate by. + :param x: x of axis to rotate around. + :param y: y of axis to rotate around. + :param z: z of axis to rotate around. + + :return: The rotated matrix + """ + angle = math.pi * angle / 180 + c, s = math.cos(angle), math.sin(angle) + n = math.sqrt(x * x + y * y + z * z) + x, y, z = x / n, y / n, z / n + cx, cy, cz = (1 - c) * x, (1 - c) * y, (1 - c) * z + rotation_matrix = array( + [ + [cx * x + c, cy * x - z * s, cz * x + y * s, 0], + [cx * y + z * s, cy * y + c, cz * y - x * s, 0], + [cx * z - y * s, cy * z + x * s, cz * z + c, 0], + [0, 0, 0, 1], + ], + dtype=matrix.dtype, + ).T + matrix[...] = dot(matrix, rotation_matrix) + return matrix + + +class Rotation: + """ + Data class that stores rotation angles in three axes. + """ + + def __init__(self): + self.theta = 20 + self.phi = 40 + self.psi = 25 + + +def drawcube_old(): + """ + Draw the cube using the old open GL methods pre 3.2 core context. + """ + allpoints = list(zip(CUBE_POINTS, CUBE_COLORS)) + + GL.glBegin(GL.GL_QUADS) + for face in CUBE_QUAD_VERTS: + for vert in face: + pos, color = allpoints[vert] + GL.glColor3fv(color) + GL.glVertex3fv(pos) + GL.glEnd() + + GL.glColor3f(1.0, 1.0, 1.0) + GL.glBegin(GL.GL_LINES) + for line in CUBE_EDGES: + for vert in line: + pos, color = allpoints[vert] + GL.glVertex3fv(pos) + + GL.glEnd() + + +def init_gl_stuff_old(): + """ + Initialise open GL, prior to core context 3.2 + """ + GL.glEnable(GL.GL_DEPTH_TEST) # use our zbuffer + + # setup the camera + GL.glMatrixMode(GL.GL_PROJECTION) + GL.glLoadIdentity() + GLU.gluPerspective(45.0, 640 / 480.0, 0.1, 100.0) # setup lens + GL.glTranslatef(0.0, 0.0, -3.0) # move back + GL.glRotatef(25, 1, 0, 0) # orbit higher + + +def init_gl_modern(display_size): + """ + Initialise open GL in the 'modern' open GL style for open GL versions + greater than 3.1. + + :param display_size: Size of the window/viewport. + """ + + # Create shaders + # -------------------------------------- + vertex_code = """ + + #version 150 + uniform mat4 model; + uniform mat4 view; + uniform mat4 projection; + + uniform vec4 colour_mul; + uniform vec4 colour_add; + + in vec4 vertex_colour; // vertex colour in + in vec3 vertex_position; + + out vec4 vertex_color_out; // vertex colour out + void main() + { + vertex_color_out = (colour_mul * vertex_colour) + colour_add; + gl_Position = projection * view * model * vec4(vertex_position, 1.0); + } + + """ + + fragment_code = """ + #version 150 + in vec4 vertex_color_out; // vertex colour from vertex shader + out vec4 fragColor; + void main() + { + fragColor = vertex_color_out; + } + """ + + program = GL.glCreateProgram() + vertex = GL.glCreateShader(GL.GL_VERTEX_SHADER) + fragment = GL.glCreateShader(GL.GL_FRAGMENT_SHADER) + GL.glShaderSource(vertex, vertex_code) + GL.glCompileShader(vertex) + + # this logs issues the shader compiler finds. + log = GL.glGetShaderInfoLog(vertex) + if isinstance(log, bytes): + log = log.decode() + for line in log.split("\n"): + print(line) + + GL.glAttachShader(program, vertex) + GL.glShaderSource(fragment, fragment_code) + GL.glCompileShader(fragment) + + # this logs issues the shader compiler finds. + log = GL.glGetShaderInfoLog(fragment) + if isinstance(log, bytes): + log = log.decode() + for line in log.split("\n"): + print(line) + + GL.glAttachShader(program, fragment) + GL.glValidateProgram(program) + GL.glLinkProgram(program) + + GL.glDetachShader(program, vertex) + GL.glDetachShader(program, fragment) + GL.glUseProgram(program) + + # Create vertex buffers and shader constants + # ------------------------------------------ + + # Cube Data + vertices = zeros( + 8, [("vertex_position", float32, 3), ("vertex_colour", float32, 4)] + ) + + vertices["vertex_position"] = [ + [1, 1, 1], + [-1, 1, 1], + [-1, -1, 1], + [1, -1, 1], + [1, -1, -1], + [1, 1, -1], + [-1, 1, -1], + [-1, -1, -1], + ] + + vertices["vertex_colour"] = [ + [0, 1, 1, 1], + [0, 0, 1, 1], + [0, 0, 0, 1], + [0, 1, 0, 1], + [1, 1, 0, 1], + [1, 1, 1, 1], + [1, 0, 1, 1], + [1, 0, 0, 1], + ] + + filled_cube_indices = array( + [ + 0, + 1, + 2, + 0, + 2, + 3, + 0, + 3, + 4, + 0, + 4, + 5, + 0, + 5, + 6, + 0, + 6, + 1, + 1, + 6, + 7, + 1, + 7, + 2, + 7, + 4, + 3, + 7, + 3, + 2, + 4, + 7, + 6, + 4, + 6, + 5, + ], + dtype=uint32, + ) + + outline_cube_indices = array( + [0, 1, 1, 2, 2, 3, 3, 0, 4, 7, 7, 6, 6, 5, 5, 4, 0, 5, 1, 6, 2, 7, 3, 4], + dtype=uint32, + ) + + shader_data = {"buffer": {}, "constants": {}} + + GL.glBindVertexArray(GL.glGenVertexArrays(1)) # Have to do this first + + shader_data["buffer"]["vertices"] = GL.glGenBuffers(1) + GL.glBindBuffer(GL.GL_ARRAY_BUFFER, shader_data["buffer"]["vertices"]) + GL.glBufferData(GL.GL_ARRAY_BUFFER, vertices.nbytes, vertices, GL.GL_DYNAMIC_DRAW) + + stride = vertices.strides[0] + offset = ctypes.c_void_p(0) + + loc = GL.glGetAttribLocation(program, "vertex_position") + GL.glEnableVertexAttribArray(loc) + GL.glVertexAttribPointer(loc, 3, GL.GL_FLOAT, False, stride, offset) + + offset = ctypes.c_void_p(vertices.dtype["vertex_position"].itemsize) + + loc = GL.glGetAttribLocation(program, "vertex_colour") + GL.glEnableVertexAttribArray(loc) + GL.glVertexAttribPointer(loc, 4, GL.GL_FLOAT, False, stride, offset) + + shader_data["buffer"]["filled"] = GL.glGenBuffers(1) + GL.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, shader_data["buffer"]["filled"]) + GL.glBufferData( + GL.GL_ELEMENT_ARRAY_BUFFER, + filled_cube_indices.nbytes, + filled_cube_indices, + GL.GL_STATIC_DRAW, + ) + + shader_data["buffer"]["outline"] = GL.glGenBuffers(1) + GL.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, shader_data["buffer"]["outline"]) + GL.glBufferData( + GL.GL_ELEMENT_ARRAY_BUFFER, + outline_cube_indices.nbytes, + outline_cube_indices, + GL.GL_STATIC_DRAW, + ) + + shader_data["constants"]["model"] = GL.glGetUniformLocation(program, "model") + GL.glUniformMatrix4fv(shader_data["constants"]["model"], 1, False, eye(4)) + + shader_data["constants"]["view"] = GL.glGetUniformLocation(program, "view") + view = translate(eye(4), z=-6) + GL.glUniformMatrix4fv(shader_data["constants"]["view"], 1, False, view) + + shader_data["constants"]["projection"] = GL.glGetUniformLocation( + program, "projection" + ) + GL.glUniformMatrix4fv(shader_data["constants"]["projection"], 1, False, eye(4)) + + # This colour is multiplied with the base vertex colour in producing + # the final output + shader_data["constants"]["colour_mul"] = GL.glGetUniformLocation( + program, "colour_mul" + ) + GL.glUniform4f(shader_data["constants"]["colour_mul"], 1, 1, 1, 1) + + # This colour is added on to the base vertex colour in producing + # the final output + shader_data["constants"]["colour_add"] = GL.glGetUniformLocation( + program, "colour_add" + ) + GL.glUniform4f(shader_data["constants"]["colour_add"], 0, 0, 0, 0) + + # Set GL drawing data + # ------------------- + GL.glClearColor(0, 0, 0, 0) + GL.glPolygonOffset(1, 1) + GL.glEnable(GL.GL_LINE_SMOOTH) + GL.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA) + GL.glDepthFunc(GL.GL_LESS) + GL.glHint(GL.GL_LINE_SMOOTH_HINT, GL.GL_NICEST) + GL.glLineWidth(1.0) + + projection = perspective(45.0, display_size[0] / float(display_size[1]), 2.0, 100.0) + GL.glUniformMatrix4fv(shader_data["constants"]["projection"], 1, False, projection) + + return shader_data, filled_cube_indices, outline_cube_indices + + +def draw_cube_modern(shader_data, filled_cube_indices, outline_cube_indices, rotation): + """ + Draw a cube in the 'modern' Open GL style, for post 3.1 versions of + open GL. + + :param shader_data: compile vertex & pixel shader data for drawing a cube. + :param filled_cube_indices: the indices to draw the 'filled' cube. + :param outline_cube_indices: the indices to draw the 'outline' cube. + :param rotation: the current rotations to apply. + """ + + GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT) + + # Filled cube + GL.glDisable(GL.GL_BLEND) + GL.glEnable(GL.GL_DEPTH_TEST) + GL.glEnable(GL.GL_POLYGON_OFFSET_FILL) + GL.glUniform4f(shader_data["constants"]["colour_mul"], 1, 1, 1, 1) + GL.glUniform4f(shader_data["constants"]["colour_add"], 0, 0, 0, 0.0) + GL.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, shader_data["buffer"]["filled"]) + GL.glDrawElements( + GL.GL_TRIANGLES, len(filled_cube_indices), GL.GL_UNSIGNED_INT, None + ) + + # Outlined cube + GL.glDisable(GL.GL_POLYGON_OFFSET_FILL) + GL.glEnable(GL.GL_BLEND) + GL.glUniform4f(shader_data["constants"]["colour_mul"], 0, 0, 0, 0.0) + GL.glUniform4f(shader_data["constants"]["colour_add"], 1, 1, 1, 1.0) + GL.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, shader_data["buffer"]["outline"]) + GL.glDrawElements(GL.GL_LINES, len(outline_cube_indices), GL.GL_UNSIGNED_INT, None) + + # Rotate cube + # rotation.theta += 1.0 # degrees + rotation.phi += 1.0 # degrees + # rotation.psi += 1.0 # degrees + model = eye(4, dtype=float32) + # rotate(model, rotation.theta, 0, 0, 1) + rotate(model, rotation.phi, 0, 1, 0) + rotate(model, rotation.psi, 1, 0, 0) + GL.glUniformMatrix4fv(shader_data["constants"]["model"], 1, False, model) + + +def main(): + """run the demo""" + + # initialize pygame and setup an opengl display + pg.init() + + gl_version = (3, 0) # GL Version number (Major, Minor) + if USE_MODERN_GL: + gl_version = (3, 2) # GL Version number (Major, Minor) + + # By setting these attributes we can choose which Open GL Profile + # to use, profiles greater than 3.2 use a different rendering path + pg.display.gl_set_attribute(pg.GL_CONTEXT_MAJOR_VERSION, gl_version[0]) + pg.display.gl_set_attribute(pg.GL_CONTEXT_MINOR_VERSION, gl_version[1]) + pg.display.gl_set_attribute( + pg.GL_CONTEXT_PROFILE_MASK, pg.GL_CONTEXT_PROFILE_CORE + ) + + fullscreen = False # start in windowed mode + + display_size = (640, 480) + pg.display.set_mode(display_size, pg.OPENGL | pg.DOUBLEBUF | pg.RESIZABLE) + + if USE_MODERN_GL: + gpu, f_indices, o_indices = init_gl_modern(display_size) + rotation = Rotation() + else: + init_gl_stuff_old() + + going = True + while going: + # check for quit'n events + events = pg.event.get() + for event in events: + if event.type == pg.QUIT or ( + event.type == pg.KEYDOWN and event.key == pg.K_ESCAPE + ): + going = False + + elif event.type == pg.KEYDOWN and event.key == pg.K_f: + if not fullscreen: + print("Changing to FULLSCREEN") + pg.display.set_mode( + (640, 480), pg.OPENGL | pg.DOUBLEBUF | pg.FULLSCREEN + ) + else: + print("Changing to windowed mode") + pg.display.set_mode((640, 480), pg.OPENGL | pg.DOUBLEBUF) + fullscreen = not fullscreen + if gl_version[0] >= 4 or (gl_version[0] == 3 and gl_version[1] >= 2): + gpu, f_indices, o_indices = init_gl_modern(display_size) + rotation = Rotation() + else: + init_gl_stuff_old() + + if USE_MODERN_GL: + draw_cube_modern(gpu, f_indices, o_indices, rotation) + else: + # clear screen and move camera + GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT) + # orbit camera around by 1 degree + GL.glRotatef(1, 0, 1, 0) + drawcube_old() + + pg.display.flip() + pg.time.wait(10) + + pg.quit() + + +if __name__ == "__main__": + main() diff --git a/venv/Lib/site-packages/pygame/examples/headless_no_windows_needed.py b/venv/Lib/site-packages/pygame/examples/headless_no_windows_needed.py new file mode 100644 index 0000000..a74057c --- /dev/null +++ b/venv/Lib/site-packages/pygame/examples/headless_no_windows_needed.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python +""" pygame.examples.headless_no_windows_needed + +How to use pygame with no windowing system, like on headless servers. + +Thumbnail generation with scaling is an example of what you can do with pygame. +NOTE: the pygame scale function uses mmx/sse if available, and can be run + in multiple threads. +""" +useage = """-scale inputimage outputimage new_width new_height +eg. -scale in.png out.png 50 50 + +""" + +import os +import sys + +# set SDL to use the dummy NULL video driver, +# so it doesn't need a windowing system. +os.environ["SDL_VIDEODRIVER"] = "dummy" + +import pygame as pg + +# Some platforms need to init the display for some parts of pg. +pg.display.init() +screen = pg.display.set_mode((1, 1)) + + +def scaleit(fin, fout, w, h): + i = pg.image.load(fin) + + if hasattr(pg.transform, "smoothscale"): + scaled_image = pg.transform.smoothscale(i, (w, h)) + else: + scaled_image = pg.transform.scale(i, (w, h)) + pg.image.save(scaled_image, fout) + + +def main(fin, fout, w, h): + """smoothscale image file named fin as fout with new size (w,h)""" + scaleit(fin, fout, w, h) + + +if __name__ == "__main__": + if "-scale" in sys.argv: + fin, fout, w, h = sys.argv[2:] + w, h = map(int, [w, h]) + main(fin, fout, w, h) + else: + print(useage) diff --git a/venv/Lib/site-packages/pygame/examples/joystick.py b/venv/Lib/site-packages/pygame/examples/joystick.py new file mode 100644 index 0000000..44cc7b8 --- /dev/null +++ b/venv/Lib/site-packages/pygame/examples/joystick.py @@ -0,0 +1,149 @@ +import pygame + +pygame.init() + +# This is a simple class that will help us print to the screen. +# It has nothing to do with the joysticks, just outputting the +# information. +class TextPrint(object): + def __init__(self): + self.reset() + self.font = pygame.font.Font(None, 20) + + def tprint(self, screen, text): + text_bitmap = self.font.render(text, True, "black") + screen.blit(text_bitmap, (self.x, self.y)) + self.y += self.line_height + + def reset(self): + self.x = 10 + self.y = 10 + self.line_height = 15 + + def indent(self): + self.x += 10 + + def unindent(self): + self.x -= 10 + + +def main(): + # Set the width and height of the screen (width, height), and name the window. + screen = pygame.display.set_mode((500, 700)) + pygame.display.set_caption("Joystick example") + + clock = pygame.time.Clock() + + # Get ready to print. + text_print = TextPrint() + + # This dict can be left as-is, since pygame will generate a + # pygame.JOYDEVICEADDED event for every joystick connected + # at the start of the program. + joysticks = {} + + done = False + while not done: + # Event processing step. + # Possible joystick events: JOYAXISMOTION, JOYBALLMOTION, JOYBUTTONDOWN, + # JOYBUTTONUP, JOYHATMOTION, JOYDEVICEADDED, JOYDEVICEREMOVED + for event in pygame.event.get(): + if event.type == pygame.QUIT: + done = True # Flag that we are done so we exit this loop. + + if event.type == pygame.JOYBUTTONDOWN: + print("Joystick button pressed.") + if event.button == 0: + joystick = joysticks[event.instance_id] + if joystick.rumble(0, 0.7, 500): + print( + "Rumble effect played on joystick {}".format( + event.instance_id + ) + ) + + if event.type == pygame.JOYBUTTONUP: + print("Joystick button released.") + + # Handle hotplugging + if event.type == pygame.JOYDEVICEADDED: + # This event will be generated when the program starts for every + # joystick, filling up the list without needing to create them manually. + joy = pygame.joystick.Joystick(event.device_index) + joysticks[joy.get_instance_id()] = joy + print("Joystick {} connencted".format(joy.get_instance_id())) + + if event.type == pygame.JOYDEVICEREMOVED: + del joysticks[event.instance_id] + print("Joystick {} disconnected".format(event.instance_id)) + + # Drawing step + # First, clear the screen to white. Don't put other drawing commands + # above this, or they will be erased with this command. + screen.fill("white") + text_print.reset() + + text_print.tprint(screen, "Number of joysticks: {}".format(len(joysticks))) + text_print.indent() + + # For each joystick: + for joystick in joysticks.values(): + jid = joystick.get_instance_id() + text_print.tprint(screen, "Joystick {}".format(jid)) + text_print.indent() + + # Get the name from the OS for the joystick. + name = joystick.get_name() + text_print.tprint(screen, "Joystick name: {}".format(name)) + + guid = joystick.get_guid() + text_print.tprint(screen, "GUID: {}".format(guid)) + + power_level = joystick.get_power_level() + text_print.tprint(screen, "Joystick's power level: {}".format(power_level)) + + # Usually axis run in pairs, up/down for one, and left/right for + # the other. Triggers count as axes. + axes = joystick.get_numaxes() + text_print.tprint(screen, "Number of axes: {}".format(axes)) + text_print.indent() + + for i in range(axes): + axis = joystick.get_axis(i) + text_print.tprint(screen, "Axis {} value: {:>6.3f}".format(i, axis)) + text_print.unindent() + + buttons = joystick.get_numbuttons() + text_print.tprint(screen, "Number of buttons: {}".format(buttons)) + text_print.indent() + + for i in range(buttons): + button = joystick.get_button(i) + text_print.tprint(screen, "Button {:>2} value: {}".format(i, button)) + text_print.unindent() + + hats = joystick.get_numhats() + text_print.tprint(screen, "Number of hats: {}".format(hats)) + text_print.indent() + + # Hat position. All or nothing for direction, not a float like + # get_axis(). Position is a tuple of int values (x, y). + for i in range(hats): + hat = joystick.get_hat(i) + text_print.tprint(screen, "Hat {} value: {}".format(i, str(hat))) + text_print.unindent() + + text_print.unindent() + + # Go ahead and update the screen with what we've drawn. + pygame.display.flip() + + # Limit to 30 frames per second. + clock.tick(30) + + +if __name__ == "__main__": + main() + # If you forget this line, the program will 'hang' + # on exit if running from IDLE. + pygame.quit() diff --git a/venv/Lib/site-packages/pygame/examples/liquid.py b/venv/Lib/site-packages/pygame/examples/liquid.py new file mode 100644 index 0000000..d55ba9c --- /dev/null +++ b/venv/Lib/site-packages/pygame/examples/liquid.py @@ -0,0 +1,89 @@ +#!/usr/bin/env python +""" pygame.examples.liquid + +This example demonstrates a simplish water effect of an +image. It attempts to create a hardware display surface that +can use pageflipping for faster updates. Note that the colormap +from the loaded GIF image is copied to the colormap for the +display surface. + +This is based on the demo named F2KWarp by Brad Graham of Freedom2000 +done in BlitzBasic. I was just translating the BlitzBasic code to +pygame to compare the results. I didn't bother porting the text and +sound stuff, that's an easy enough challenge for the reader :] +""" + +import pygame as pg +import os +from math import sin +import time + +main_dir = os.path.split(os.path.abspath(__file__))[0] + + +def main(): + # initialize and setup screen + pg.init() + screen = pg.display.set_mode((640, 480), pg.HWSURFACE | pg.DOUBLEBUF) + + # load image and quadruple + imagename = os.path.join(main_dir, "data", "liquid.bmp") + bitmap = pg.image.load(imagename) + bitmap = pg.transform.scale2x(bitmap) + bitmap = pg.transform.scale2x(bitmap) + + # get the image and screen in the same format + if screen.get_bitsize() == 8: + screen.set_palette(bitmap.get_palette()) + else: + bitmap = bitmap.convert() + + # prep some variables + anim = 0.0 + + # mainloop + xblocks = range(0, 640, 20) + yblocks = range(0, 480, 20) + stopevents = pg.QUIT, pg.KEYDOWN, pg.MOUSEBUTTONDOWN + while 1: + for e in pg.event.get(): + if e.type in stopevents: + return + + anim = anim + 0.02 + for x in xblocks: + xpos = (x + (sin(anim + x * 0.01) * 15)) + 20 + for y in yblocks: + ypos = (y + (sin(anim + y * 0.01) * 15)) + 20 + screen.blit(bitmap, (x, y), (xpos, ypos, 20, 20)) + + pg.display.flip() + time.sleep(0.01) + + +if __name__ == "__main__": + main() + pg.quit() + + +"""BTW, here is the code from the BlitzBasic example this was derived +from. i've snipped the sound and text stuff out. +----------------------------------------------------------------- +; Brad@freedom2000.com + +; Load a bmp pic (800x600) and slice it into 1600 squares +Graphics 640,480 +SetBuffer BackBuffer() +bitmap$="f2kwarp.bmp" +pic=LoadAnimImage(bitmap$,20,15,0,1600) + +; use SIN to move all 1600 squares around to give liquid effect +Repeat +f=0:w=w+10:If w=360 Then w=0 +For y=0 To 599 Step 15 +For x = 0 To 799 Step 20 +f=f+1:If f=1600 Then f=0 +DrawBlock pic,(x+(Sin(w+x)*40))/1.7+80,(y+(Sin(w+y)*40))/1.7+60,f +Next:Next:Flip:Cls +Until KeyDown(1) +""" diff --git a/venv/Lib/site-packages/pygame/examples/mask.py b/venv/Lib/site-packages/pygame/examples/mask.py new file mode 100644 index 0000000..dae3b2b --- /dev/null +++ b/venv/Lib/site-packages/pygame/examples/mask.py @@ -0,0 +1,212 @@ +#!/usr/bin/env python +""" pygame.examples.mask + +A pygame.mask collision detection production. + + + + +Brought + + to + you + by + + the + +pixels + 0000000000000 + and + 111111 + + +This is 32 bits: + 11111111111111111111111111111111 + +There are 32 or 64 bits in a computer 'word'. +Rather than using one word for a pixel, +the mask module represents 32 or 64 pixels in one word. +As you can imagine, this makes things fast, and saves memory. + +Compute intensive things like collision detection, +and computer vision benefit greatly from this. + + +This module can also be run as a stand-alone program, excepting +one or more image file names as command line arguments. +""" + +import sys +import os +import random + +import pygame as pg + + +def maskFromSurface(surface, threshold=127): + return pg.mask.from_surface(surface, threshold) + + +def vadd(x, y): + return [x[0] + y[0], x[1] + y[1]] + + +def vsub(x, y): + return [x[0] - y[0], x[1] - y[1]] + + +def vdot(x, y): + return x[0] * y[0] + x[1] * y[1] + + +class Sprite: + def __init__(self, surface, mask=None): + self.surface = surface + if mask: + self.mask = mask + else: + self.mask = maskFromSurface(self.surface) + self.setPos([0, 0]) + self.setVelocity([0, 0]) + + def setPos(self, pos): + self.pos = [pos[0], pos[1]] + + def setVelocity(self, vel): + self.vel = [vel[0], vel[1]] + + def move(self, dr): + self.pos = vadd(self.pos, dr) + + def kick(self, impulse): + self.vel[0] += impulse[0] + self.vel[1] += impulse[1] + + def collide(self, s): + """Test if the sprites are colliding and + resolve the collision in this case.""" + offset = [int(x) for x in vsub(s.pos, self.pos)] + overlap = self.mask.overlap_area(s.mask, offset) + if overlap == 0: + return + """Calculate collision normal""" + nx = self.mask.overlap_area( + s.mask, (offset[0] + 1, offset[1]) + ) - self.mask.overlap_area(s.mask, (offset[0] - 1, offset[1])) + ny = self.mask.overlap_area( + s.mask, (offset[0], offset[1] + 1) + ) - self.mask.overlap_area(s.mask, (offset[0], offset[1] - 1)) + if nx == 0 and ny == 0: + """One sprite is inside another""" + return + n = [nx, ny] + dv = vsub(s.vel, self.vel) + J = vdot(dv, n) / (2 * vdot(n, n)) + if J > 0: + """Can scale up to 2*J here to get bouncy collisions""" + J *= 1.9 + self.kick([nx * J, ny * J]) + s.kick([-J * nx, -J * ny]) + return + + # """Separate the sprites""" + # c1 = -overlap/vdot(n,n) + # c2 = -c1/2 + # self.move([c2*nx,c2*ny]) + # s.move([(c1+c2)*nx,(c1+c2)*ny]) + + def update(self, dt): + self.pos[0] += dt * self.vel[0] + self.pos[1] += dt * self.vel[1] + + +def main(*args): + """Display multiple images bounce off each other using collision detection + + Positional arguments: + one or more image file names. + + This pg.masks demo will display multiple moving sprites bouncing + off each other. More than one sprite image can be provided. + """ + + if len(args) == 0: + raise ValueError("Require at least one image file name: non given") + print("Press any key to quit") + pg.init() + screen = pg.display.set_mode((640, 480)) + images = [] + masks = [] + for impath in args: + images.append(pg.image.load(impath).convert_alpha()) + masks.append(maskFromSurface(images[-1])) + + numtimes = 10 + import time + + t1 = time.time() + for x in range(numtimes): + unused_mask = maskFromSurface(images[-1]) + t2 = time.time() + + print("python maskFromSurface :%s" % (t2 - t1)) + + t1 = time.time() + for x in range(numtimes): + unused_mask = pg.mask.from_surface(images[-1]) + t2 = time.time() + + print("C pg.mask.from_surface :%s" % (t2 - t1)) + + sprites = [] + for i in range(20): + j = i % len(images) + s = Sprite(images[j], masks[j]) + s.setPos( + ( + random.uniform(0, screen.get_width()), + random.uniform(0, screen.get_height()), + ) + ) + s.setVelocity((random.uniform(-5, 5), random.uniform(-5, 5))) + sprites.append(s) + pg.time.set_timer(pg.USEREVENT, 33) + while 1: + event = pg.event.wait() + if event.type == pg.QUIT: + return + elif event.type == pg.USEREVENT: + + # Do both mechanics and screen update + screen.fill((240, 220, 100)) + for i, sprite in enumerate(sprites): + for j in range(i + 1, len(sprites)): + sprite.collide(sprites[j]) + for s in sprites: + s.update(1) + if s.pos[0] < -s.surface.get_width() - 3: + s.pos[0] = screen.get_width() + elif s.pos[0] > screen.get_width() + 3: + s.pos[0] = -s.surface.get_width() + if s.pos[1] < -s.surface.get_height() - 3: + s.pos[1] = screen.get_height() + elif s.pos[1] > screen.get_height() + 3: + s.pos[1] = -s.surface.get_height() + screen.blit(s.surface, s.pos) + pg.display.update() + elif event.type == pg.KEYDOWN: + return + + +if __name__ == "__main__": + if len(sys.argv) < 2: + print("Usage: mask.py [ ...]") + print("Let many copies of IMAGE(s) bounce against each other") + print("Press any key to quit") + main_dir = os.path.split(os.path.abspath(__file__))[0] + imagename = os.path.join(main_dir, "data", "chimp.png") + main(imagename) + + else: + main(*sys.argv[1:]) + pg.quit() diff --git a/venv/Lib/site-packages/pygame/examples/midi.py b/venv/Lib/site-packages/pygame/examples/midi.py new file mode 100644 index 0000000..3e184ef --- /dev/null +++ b/venv/Lib/site-packages/pygame/examples/midi.py @@ -0,0 +1,877 @@ +#!/usr/bin/env python +""" pygame.examples.midi + +midi input, and a separate example of midi output. + +By default it runs the output example. + +python -m pygame.examples.midi --output +python -m pygame.examples.midi --input +python -m pygame.examples.midi --input +""" + +import sys +import os + +import pygame as pg +import pygame.midi + +# black and white piano keys use b/w color values directly +BACKGROUNDCOLOR = "slategray" + + +def print_device_info(): + pygame.midi.init() + _print_device_info() + pygame.midi.quit() + + +def _print_device_info(): + for i in range(pygame.midi.get_count()): + r = pygame.midi.get_device_info(i) + (interf, name, input, output, opened) = r + + in_out = "" + if input: + in_out = "(input)" + if output: + in_out = "(output)" + + print( + "%2i: interface :%s:, name :%s:, opened :%s: %s" + % (i, interf, name, opened, in_out) + ) + + +def input_main(device_id=None): + pg.init() + + pygame.midi.init() + + _print_device_info() + + if device_id is None: + input_id = pygame.midi.get_default_input_id() + else: + input_id = device_id + + print("using input_id :%s:" % input_id) + i = pygame.midi.Input(input_id) + + pg.display.set_mode((1, 1)) + + going = True + while going: + events = pygame.event.get() + for e in events: + if e.type in [pg.QUIT]: + going = False + if e.type in [pg.KEYDOWN]: + going = False + if e.type in [pygame.midi.MIDIIN]: + print(e) + + if i.poll(): + midi_events = i.read(10) + # convert them into pygame events. + midi_evs = pygame.midi.midis2events(midi_events, i.device_id) + + for m_e in midi_evs: + pygame.event.post(m_e) + + del i + pygame.midi.quit() + + +def output_main(device_id=None): + """Execute a musical keyboard example for the Church Organ instrument + + This is a piano keyboard example, with a two octave keyboard, starting at + note F3. Left mouse down over a key starts a note, left up stops it. The + notes are also mapped to the computer keyboard keys, assuming an American + English PC keyboard (sorry everyone else, but I don't know if I can map to + absolute key position instead of value.) The white keys are on the second + row, TAB to BACKSLASH, starting with note F3. The black keys map to the top + row, '1' to BACKSPACE, starting with F#3. 'r' is middle C. Close the + window or press ESCAPE to quit the program. Key velocity (note + amplitude) varies vertically on the keyboard image, with minimum velocity + at the top of a key and maximum velocity at bottom. + + Default Midi output, no device_id given, is to the default output device + for the computer. + + """ + + # A note to new pygamers: + # + # All the midi module stuff is in this function. It is unnecessary to + # understand how the keyboard display works to appreciate how midi + # messages are sent. + + # The keyboard is drawn by a Keyboard instance. This instance maps Midi + # notes to musical keyboard keys. A regions surface maps window position + # to (Midi note, velocity) pairs. A key_mapping dictionary does the same + # for computer keyboard keys. Midi sound is controlled with direct method + # calls to a pygame.midi.Output instance. + # + # Things to consider when using pygame.midi: + # + # 1) Initialize the midi module with a to pygame.midi.init(). + # 2) Create a midi.Output instance for the desired output device port. + # 3) Select instruments with set_instrument() method calls. + # 4) Play notes with note_on() and note_off() method calls. + # 5) Call pygame.midi.Quit() when finished. Though the midi module tries + # to ensure that midi is properly shut down, it is best to do it + # explicitly. A try/finally statement is the safest way to do this. + # + + # GRAND_PIANO = 0 + CHURCH_ORGAN = 19 + + instrument = CHURCH_ORGAN + # instrument = GRAND_PIANO + start_note = 53 # F3 (white key note), start_note != 0 + n_notes = 24 # Two octaves (14 white keys) + + key_mapping = make_key_mapping( + [ + pg.K_TAB, + pg.K_1, + pg.K_q, + pg.K_2, + pg.K_w, + pg.K_3, + pg.K_e, + pg.K_r, + pg.K_5, + pg.K_t, + pg.K_6, + pg.K_y, + pg.K_u, + pg.K_8, + pg.K_i, + pg.K_9, + pg.K_o, + pg.K_0, + pg.K_p, + pg.K_LEFTBRACKET, + pg.K_EQUALS, + pg.K_RIGHTBRACKET, + pg.K_BACKSPACE, + pg.K_BACKSLASH, + ], + start_note, + ) + + pg.init() + pygame.midi.init() + + _print_device_info() + + if device_id is None: + port = pygame.midi.get_default_output_id() + else: + port = device_id + + print("using output_id :%s:" % port) + + midi_out = pygame.midi.Output(port, 0) + try: + midi_out.set_instrument(instrument) + keyboard = Keyboard(start_note, n_notes) + + screen = pg.display.set_mode(keyboard.rect.size) + screen.fill(BACKGROUNDCOLOR) + pg.display.flip() + + background = pg.Surface(screen.get_size()) + background.fill(BACKGROUNDCOLOR) + dirty_rects = [] + keyboard.draw(screen, background, dirty_rects) + pg.display.update(dirty_rects) + + regions = pg.Surface(screen.get_size()) # initial color (0,0,0) + keyboard.map_regions(regions) + + pg.event.set_blocked(pg.MOUSEMOTION) + mouse_note = 0 + on_notes = set() + while 1: + e = pg.event.wait() + if e.type == pg.MOUSEBUTTONDOWN: + mouse_note, velocity, __, __ = regions.get_at(e.pos) + if mouse_note and mouse_note not in on_notes: + keyboard.key_down(mouse_note) + midi_out.note_on(mouse_note, velocity) + on_notes.add(mouse_note) + else: + mouse_note = 0 + elif e.type == pg.MOUSEBUTTONUP: + if mouse_note: + midi_out.note_off(mouse_note) + keyboard.key_up(mouse_note) + on_notes.remove(mouse_note) + mouse_note = 0 + elif e.type == pg.QUIT: + break + elif e.type == pg.KEYDOWN: + if e.key == pg.K_ESCAPE: + break + try: + note, velocity = key_mapping[e.key] + except KeyError: + pass + else: + if note not in on_notes: + keyboard.key_down(note) + midi_out.note_on(note, velocity) + on_notes.add(note) + elif e.type == pg.KEYUP: + try: + note, __ = key_mapping[e.key] + except KeyError: + pass + else: + if note in on_notes and note != mouse_note: + keyboard.key_up(note) + midi_out.note_off(note, 0) + on_notes.remove(note) + + dirty_rects = [] + keyboard.draw(screen, background, dirty_rects) + pg.display.update(dirty_rects) + finally: + del midi_out + pygame.midi.quit() + + +def make_key_mapping(keys, start_note): + """Return a dictionary of (note, velocity) by computer keyboard key code""" + mapping = {} + for i, key in enumerate(keys): + mapping[key] = (start_note + i, 127) + return mapping + + +class NullKey(object): + """A dummy key that ignores events passed to it by other keys + + A NullKey instance is the left key instance used by default + for the left most keyboard key. + + """ + + def _right_white_down(self): + pass + + def _right_white_up(self): + pass + + def _right_black_down(self): + pass + + def _right_black_up(self): + pass + + +null_key = NullKey() + + +def key_class(updates, image_strip, image_rects, is_white_key=True): + """Return a keyboard key widget class + + Arguments: + updates - a set into which a key instance adds itself if it needs + redrawing. + image_strip - The surface containing the images of all key states. + image_rects - A list of Rects giving the regions within image_strip that + are relevant to this key class. + is_white_key (default True) - Set false if this is a black key. + + This function automates the creation of a key widget class for the + three basic key types. A key has two basic states, up or down ( + depressed). Corresponding up and down images are drawn for each + of these two states. But to give the illusion of depth, a key + may have shadows cast upon it by the adjacent keys to its right. + These shadows change depending on the up/down state of the key and + its neighbors. So a key may support multiple images and states + depending on the shadows. A key type is determined by the length + of image_rects and the value of is_white. + + """ + + # Naming convention: Variables used by the Key class as part of a + # closure start with 'c_'. + + # State logic and shadows: + # + # A key may cast a shadow upon the key to its left. A black key casts a + # shadow on an adjacent white key. The shadow changes depending of whether + # the black or white key is depressed. A white key casts a shadow on the + # white key to its left if it is up and the left key is down. Therefore + # a keys state, and image it will draw, is determined entirely by its + # itself and the key immediately adjacent to it on the right. A white key + # is always assumed to have an adjacent white key. + # + # There can be up to eight key states, representing all permutations + # of the three fundamental states of self up/down, adjacent white + # right up/down, adjacent black up/down. + # + down_state_none = 0 + down_state_self = 1 + down_state_white = down_state_self << 1 + down_state_self_white = down_state_self | down_state_white + down_state_black = down_state_white << 1 + down_state_self_black = down_state_self | down_state_black + down_state_white_black = down_state_white | down_state_black + down_state_all = down_state_self | down_state_white_black + + # Some values used in the class. + # + c_down_state_initial = down_state_none + c_down_state_rect_initial = image_rects[0] + c_updates = updates + c_image_strip = image_strip + c_width, c_height = image_rects[0].size + + # A key propagates its up/down state change to the adjacent white key on + # the left by calling the adjacent key's _right_black_down or + # _right_white_down method. + # + if is_white_key: + key_color = "white" + else: + key_color = "black" + c_notify_down_method = "_right_%s_down" % key_color + c_notify_up_method = "_right_%s_up" % key_color + + # Images: + # + # A black key only needs two images, for the up and down states. Its + # appearance is unaffected by the adjacent keys to its right, which cast no + # shadows upon it. + # + # A white key with a no adjacent black to its right only needs three + # images, for self up, self down, and both self and adjacent white down. + # + # A white key with both a black and white key to its right needs six + # images: self up, self up and adjacent black down, self down, self and + # adjacent white down, self and adjacent black down, and all three down. + # + # Each 'c_event' dictionary maps the current key state to a new key state, + # along with corresponding image, for the related event. If no redrawing + # is required for the state change then the image rect is simply None. + # + c_event_down = {down_state_none: (down_state_self, image_rects[1])} + c_event_up = {down_state_self: (down_state_none, image_rects[0])} + c_event_right_white_down = { + down_state_none: (down_state_none, None), + down_state_self: (down_state_self, None), + } + c_event_right_white_up = c_event_right_white_down.copy() + c_event_right_black_down = c_event_right_white_down.copy() + c_event_right_black_up = c_event_right_white_down.copy() + if len(image_rects) > 2: + c_event_down[down_state_white] = (down_state_self_white, image_rects[2]) + c_event_up[down_state_self_white] = (down_state_white, image_rects[0]) + c_event_right_white_down[down_state_none] = (down_state_white, None) + c_event_right_white_down[down_state_self] = ( + down_state_self_white, + image_rects[2], + ) + c_event_right_white_up[down_state_white] = (down_state_none, None) + c_event_right_white_up[down_state_self_white] = ( + down_state_self, + image_rects[1], + ) + c_event_right_black_down[down_state_white] = (down_state_white, None) + c_event_right_black_down[down_state_self_white] = (down_state_self_white, None) + c_event_right_black_up[down_state_white] = (down_state_white, None) + c_event_right_black_up[down_state_self_white] = (down_state_self_white, None) + if len(image_rects) > 3: + c_event_down[down_state_black] = (down_state_self_black, image_rects[4]) + c_event_down[down_state_white_black] = (down_state_all, image_rects[5]) + c_event_up[down_state_self_black] = (down_state_black, image_rects[3]) + c_event_up[down_state_all] = (down_state_white_black, image_rects[3]) + c_event_right_white_down[down_state_black] = (down_state_white_black, None) + c_event_right_white_down[down_state_self_black] = ( + down_state_all, + image_rects[5], + ) + c_event_right_white_up[down_state_white_black] = (down_state_black, None) + c_event_right_white_up[down_state_all] = (down_state_self_black, image_rects[4]) + c_event_right_black_down[down_state_none] = (down_state_black, image_rects[3]) + c_event_right_black_down[down_state_self] = ( + down_state_self_black, + image_rects[4], + ) + c_event_right_black_down[down_state_white] = ( + down_state_white_black, + image_rects[3], + ) + c_event_right_black_down[down_state_self_white] = ( + down_state_all, + image_rects[5], + ) + c_event_right_black_up[down_state_black] = (down_state_none, image_rects[0]) + c_event_right_black_up[down_state_self_black] = ( + down_state_self, + image_rects[1], + ) + c_event_right_black_up[down_state_white_black] = ( + down_state_white, + image_rects[0], + ) + c_event_right_black_up[down_state_all] = (down_state_self_white, image_rects[2]) + + class Key(object): + """A key widget, maintains key state and draws the key's image + + Constructor arguments: + ident - A unique key identifier. Any immutable type suitable as a key. + posn - The location of the key on the display surface. + key_left - Optional, the adjacent white key to the left. Changes in + up and down state are propagated to that key. + + A key has an associated position and state. Related to state is the + image drawn. State changes are managed with method calls, one method + per event type. The up and down event methods are public. Other + internal methods are for passing on state changes to the key_left + key instance. + + """ + + is_white = is_white_key + + def __init__(self, ident, posn, key_left=None): + """Return a new Key instance + + The initial state is up, with all adjacent keys to the right also + up. + + """ + if key_left is None: + key_left = null_key + rect = pg.Rect(posn[0], posn[1], c_width, c_height) + self.rect = rect + self._state = c_down_state_initial + self._source_rect = c_down_state_rect_initial + self._ident = ident + self._hash = hash(ident) + self._notify_down = getattr(key_left, c_notify_down_method) + self._notify_up = getattr(key_left, c_notify_up_method) + self._key_left = key_left + self._background_rect = pg.Rect(rect.left, rect.bottom - 10, c_width, 10) + c_updates.add(self) + + def down(self): + """Signal that this key has been depressed (is down)""" + + self._state, source_rect = c_event_down[self._state] + if source_rect is not None: + self._source_rect = source_rect + c_updates.add(self) + self._notify_down() + + def up(self): + """Signal that this key has been released (is up)""" + + self._state, source_rect = c_event_up[self._state] + if source_rect is not None: + self._source_rect = source_rect + c_updates.add(self) + self._notify_up() + + def _right_white_down(self): + """Signal that the adjacent white key has been depressed + + This method is for internal propagation of events between + key instances. + + """ + + self._state, source_rect = c_event_right_white_down[self._state] + if source_rect is not None: + self._source_rect = source_rect + c_updates.add(self) + + def _right_white_up(self): + """Signal that the adjacent white key has been released + + This method is for internal propagation of events between + key instances. + + """ + + self._state, source_rect = c_event_right_white_up[self._state] + if source_rect is not None: + self._source_rect = source_rect + c_updates.add(self) + + def _right_black_down(self): + """Signal that the adjacent black key has been depressed + + This method is for internal propagation of events between + key instances. + + """ + + self._state, source_rect = c_event_right_black_down[self._state] + if source_rect is not None: + self._source_rect = source_rect + c_updates.add(self) + + def _right_black_up(self): + """Signal that the adjacent black key has been released + + This method is for internal propagation of events between + key instances. + + """ + + self._state, source_rect = c_event_right_black_up[self._state] + if source_rect is not None: + self._source_rect = source_rect + c_updates.add(self) + + def __eq__(self, other): + """True if same identifiers""" + + return self._ident == other._ident + + def __hash__(self): + """Return the immutable hash value""" + + return self._hash + + def __str__(self): + """Return the key's identifier and position as a string""" + + return "" % (self._ident, self.rect.top, self.rect.left) + + def draw(self, surf, background, dirty_rects): + """Redraw the key on the surface surf + + The background is redrawn. The altered region is added to the + dirty_rects list. + + """ + + surf.blit(background, self._background_rect, self._background_rect) + surf.blit(c_image_strip, self.rect, self._source_rect) + dirty_rects.append(self.rect) + + return Key + + +def key_images(): + """Return a keyboard keys image strip and a mapping of image locations + + The return tuple is a surface and a dictionary of rects mapped to key + type. + + This function encapsulates the constants relevant to the keyboard image + file. There are five key types. One is the black key. The other four + white keys are determined by the proximity of the black keys. The plain + white key has no black key adjacent to it. A white-left and white-right + key has a black key to the left or right of it respectively. A white-center + key has a black key on both sides. A key may have up to six related + images depending on the state of adjacent keys to its right. + + """ + + my_dir = os.path.split(os.path.abspath(__file__))[0] + strip_file = os.path.join(my_dir, "data", "midikeys.png") + white_key_width = 42 + white_key_height = 160 + black_key_width = 22 + black_key_height = 94 + strip = pg.image.load(strip_file) + names = [ + "black none", + "black self", + "white none", + "white self", + "white self-white", + "white-left none", + "white-left self", + "white-left black", + "white-left self-black", + "white-left self-white", + "white-left all", + "white-center none", + "white-center self", + "white-center black", + "white-center self-black", + "white-center self-white", + "white-center all", + "white-right none", + "white-right self", + "white-right self-white", + ] + rects = {} + for i in range(2): + rects[names[i]] = pg.Rect( + i * white_key_width, 0, black_key_width, black_key_height + ) + for i in range(2, len(names)): + rects[names[i]] = pg.Rect( + i * white_key_width, 0, white_key_width, white_key_height + ) + return strip, rects + + +class Keyboard(object): + """Musical keyboard widget + + Constructor arguments: + start_note: midi note value of the starting note on the keyboard. + n_notes: number of notes (keys) on the keyboard. + + A Keyboard instance draws the musical keyboard and maintains the state of + all the keyboard keys. Individual keys can be in a down (depressed) or + up (released) state. + + """ + + _image_strip, _rects = key_images() + + white_key_width, white_key_height = _rects["white none"].size + black_key_width, black_key_height = _rects["black none"].size + + _updates = set() + + # There are five key classes, representing key shape: + # black key (BlackKey), plain white key (WhiteKey), white key to the left + # of a black key (WhiteKeyLeft), white key between two black keys + # (WhiteKeyCenter), and white key to the right of a black key + # (WhiteKeyRight). + BlackKey = key_class( + _updates, _image_strip, [_rects["black none"], _rects["black self"]], False + ) + WhiteKey = key_class( + _updates, + _image_strip, + [_rects["white none"], _rects["white self"], _rects["white self-white"]], + ) + WhiteKeyLeft = key_class( + _updates, + _image_strip, + [ + _rects["white-left none"], + _rects["white-left self"], + _rects["white-left self-white"], + _rects["white-left black"], + _rects["white-left self-black"], + _rects["white-left all"], + ], + ) + WhiteKeyCenter = key_class( + _updates, + _image_strip, + [ + _rects["white-center none"], + _rects["white-center self"], + _rects["white-center self-white"], + _rects["white-center black"], + _rects["white-center self-black"], + _rects["white-center all"], + ], + ) + WhiteKeyRight = key_class( + _updates, + _image_strip, + [ + _rects["white-right none"], + _rects["white-right self"], + _rects["white-right self-white"], + ], + ) + + def __init__(self, start_note, n_notes): + """Return a new Keyboard instance with n_note keys""" + + self._start_note = start_note + self._end_note = start_note + n_notes - 1 + self._add_keys() + + def _add_keys(self): + """Populate the keyboard with key instances + + Set the _keys and rect attributes. + + """ + + # Keys are entered in a list, where index is Midi note. Since there are + # only 128 possible Midi notes the list length is managable. Unassigned + # note positions should never be accessed, so are set None to ensure + # the bug is quickly detected. + # + key_map = [None] * 128 + + start_note = self._start_note + end_note = self._end_note + black_offset = self.black_key_width // 2 + prev_white_key = None + x = y = 0 + if is_white_key(start_note): + is_prev_white = True + else: + x += black_offset + is_prev_white = False + for note in range(start_note, end_note + 1): + ident = note # For now notes uniquely identify keyboard keys. + if is_white_key(note): + if is_prev_white: + if note == end_note or is_white_key(note + 1): + key = self.WhiteKey(ident, (x, y), prev_white_key) + else: + key = self.WhiteKeyLeft(ident, (x, y), prev_white_key) + else: + if note == end_note or is_white_key(note + 1): + key = self.WhiteKeyRight(ident, (x, y), prev_white_key) + else: + key = self.WhiteKeyCenter(ident, (x, y), prev_white_key) + is_prev_white = True + x += self.white_key_width + prev_white_key = key + else: + key = self.BlackKey(ident, (x - black_offset, y), prev_white_key) + is_prev_white = False + key_map[note] = key + self._keys = key_map + + kb_width = key_map[self._end_note].rect.right + kb_height = self.white_key_height + self.rect = pg.Rect(0, 0, kb_width, kb_height) + + def map_regions(self, regions): + """Draw the key regions onto surface regions. + + Regions must have at least 3 byte pixels. Each pixel of the keyboard + rectangle is set to the color (note, velocity, 0). The regions surface + must be at least as large as (0, 0, self.rect.left, self.rect.bottom) + + """ + + # First draw the white key regions. Then add the overlapping + # black key regions. + # + cutoff = self.black_key_height + black_keys = [] + for note in range(self._start_note, self._end_note + 1): + key = self._keys[note] + if key.is_white: + fill_region(regions, note, key.rect, cutoff) + else: + black_keys.append((note, key)) + for note, key in black_keys: + fill_region(regions, note, key.rect, cutoff) + + def draw(self, surf, background, dirty_rects): + """Redraw all altered keyboard keys""" + + changed_keys = self._updates + while changed_keys: + changed_keys.pop().draw(surf, background, dirty_rects) + + def key_down(self, note): + """Signal a key down event for note""" + + self._keys[note].down() + + def key_up(self, note): + """Signal a key up event for note""" + + self._keys[note].up() + + +def fill_region(regions, note, rect, cutoff): + """Fill the region defined by rect with a (note, velocity, 0) color + + The velocity varies from a small value at the top of the region to + 127 at the bottom. The vertical region 0 to cutoff is split into + three parts, with velocities 42, 84 and 127. Everything below cutoff + has velocity 127. + + """ + + x, y, width, height = rect + if cutoff is None: + cutoff = height + delta_height = cutoff // 3 + regions.fill((note, 42, 0), (x, y, width, delta_height)) + regions.fill((note, 84, 0), (x, y + delta_height, width, delta_height)) + regions.fill( + (note, 127, 0), (x, y + 2 * delta_height, width, height - 2 * delta_height) + ) + + +def is_white_key(note): + """True if note is represented by a white key""" + + key_pattern = [ + True, + False, + True, + True, + False, + True, + False, + True, + True, + False, + True, + False, + ] + return key_pattern[(note - 21) % len(key_pattern)] + + +def usage(): + print("--input [device_id] : Midi message logger") + print("--output [device_id] : Midi piano keyboard") + print("--list : list available midi devices") + + +def main(mode="output", device_id=None): + """Run a Midi example + + Arguments: + mode - if 'output' run a midi keyboard output example + 'input' run a midi event logger input example + 'list' list available midi devices + (default 'output') + device_id - midi device number; if None then use the default midi input or + output device for the system + + """ + + if mode == "input": + input_main(device_id) + elif mode == "output": + output_main(device_id) + elif mode == "list": + print_device_info() + else: + raise ValueError("Unknown mode option '%s'" % mode) + + +if __name__ == "__main__": + + try: + device_id = int(sys.argv[-1]) + except ValueError: + device_id = None + + if "--input" in sys.argv or "-i" in sys.argv: + + input_main(device_id) + + elif "--output" in sys.argv or "-o" in sys.argv: + output_main(device_id) + elif "--list" in sys.argv or "-l" in sys.argv: + print_device_info() + else: + usage() + + pg.quit() diff --git a/venv/Lib/site-packages/pygame/examples/moveit.py b/venv/Lib/site-packages/pygame/examples/moveit.py new file mode 100644 index 0000000..b902ce5 --- /dev/null +++ b/venv/Lib/site-packages/pygame/examples/moveit.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python +""" pygame.examples.moveit + +This is the full and final example from the Pygame Tutorial, +"How Do I Make It Move". It creates 10 objects and animates +them on the screen. + +Note it's a bit scant on error checking, but it's easy to read. :] +Fortunately, this is python, and we needn't wrestle with a pile of +error codes. +""" +import os +import pygame as pg + +main_dir = os.path.split(os.path.abspath(__file__))[0] + +# our game object class +class GameObject: + def __init__(self, image, height, speed): + self.speed = speed + self.image = image + self.pos = image.get_rect().move(0, height) + + def move(self): + self.pos = self.pos.move(self.speed, 0) + if self.pos.right > 600: + self.pos.left = 0 + + +# quick function to load an image +def load_image(name): + path = os.path.join(main_dir, "data", name) + return pg.image.load(path).convert() + + +# here's the full code +def main(): + pg.init() + screen = pg.display.set_mode((640, 480)) + + player = load_image("player1.gif") + background = load_image("liquid.bmp") + + # scale the background image so that it fills the window and + # successfully overwrites the old sprite position. + background = pg.transform.scale2x(background) + background = pg.transform.scale2x(background) + + screen.blit(background, (0, 0)) + + objects = [] + for x in range(10): + o = GameObject(player, x * 40, x) + objects.append(o) + + while 1: + for event in pg.event.get(): + if event.type in (pg.QUIT, pg.KEYDOWN): + return + + for o in objects: + screen.blit(background, o.pos, o.pos) + for o in objects: + o.move() + screen.blit(o.image, o.pos) + + pg.display.update() + + +if __name__ == "__main__": + main() + pg.quit() diff --git a/venv/Lib/site-packages/pygame/examples/music_drop_fade.py b/venv/Lib/site-packages/pygame/examples/music_drop_fade.py new file mode 100644 index 0000000..9d83546 --- /dev/null +++ b/venv/Lib/site-packages/pygame/examples/music_drop_fade.py @@ -0,0 +1,249 @@ +#!/usr/bin/env python +""" pygame.examples.music_drop_fade +Fade in and play music from a list while observing several events + +Adds music files to a playlist whenever played by one of the following methods +Music files passed from the commandline are played +Music files and filenames are played when drag and dropped onto the pygame window +Polls the clipboard and plays music files if it finds one there + +Keyboard Controls: +* Press space or enter to pause music playback +* Press up or down to change the music volume +* Press left or right to seek 5 seconds into the track +* Press escape to quit +* Press any other button to skip to the next music file in the list +""" + +import pygame as pg +import os, sys + +VOLUME_CHANGE_AMOUNT = 0.02 # how fast should up and down arrows change the volume? + + +def add_file(filename): + """ + This function will check if filename exists and is a music file + If it is the file will be added to a list of music files(even if already there) + Type checking is by the extension of the file, not by its contents + We can only discover if the file is valid when we mixer.music.load() it later + + It looks in the file directory and its data subdirectory + """ + if filename.rpartition(".")[2].lower() not in music_file_types: + print("{} not added to file list".format(filename)) + print("only these files types are allowed: ", music_file_types) + return False + elif os.path.exists(filename): + music_file_list.append(filename) + elif os.path.exists(os.path.join(main_dir, filename)): + music_file_list.append(os.path.join(main_dir, filename)) + elif os.path.exists(os.path.join(data_dir, filename)): + music_file_list.append(os.path.join(data_dir, filename)) + else: + print("file not found") + return False + print("{} added to file list".format(filename)) + return True + + +def play_file(filename): + """ + This function will call add_file and play it if successful + The music will fade in during the first 4 seconds + set_endevent is used to post a MUSIC_DONE event when the song finishes + The main loop will call play_next() when the MUSIC_DONE event is received + """ + global starting_pos + + if add_file(filename): + try: # we must do this in case the file is not a valid audio file + pg.mixer.music.load(music_file_list[-1]) + except pg.error as e: + print(e) # print description such as 'Not an Ogg Vorbis audio stream' + if filename in music_file_list: + music_file_list.remove(filename) + print("{} removed from file list".format(filename)) + return + pg.mixer.music.play(fade_ms=4000) + pg.mixer.music.set_volume(volume) + + if filename.rpartition(".")[2].lower() in music_can_seek: + print("file supports seeking") + starting_pos = 0 + else: + print("file does not support seeking") + starting_pos = -1 + pg.mixer.music.set_endevent(MUSIC_DONE) + + +def play_next(): + """ + This function will play the next song in music_file_list + It uses pop(0) to get the next song and then appends it to the end of the list + The song will fade in during the first 4 seconds + """ + + global starting_pos + if len(music_file_list) > 1: + nxt = music_file_list.pop(0) + + try: + pg.mixer.music.load(nxt) + except pg.error as e: + print(e) + print("{} removed from file list".format(nxt)) + + music_file_list.append(nxt) + print("starting next song: ", nxt) + else: + nxt = music_file_list[0] + pg.mixer.music.play(fade_ms=4000) + pg.mixer.music.set_volume(volume) + pg.mixer.music.set_endevent(MUSIC_DONE) + + if nxt.rpartition(".")[2].lower() in music_can_seek: + starting_pos = 0 + else: + starting_pos = -1 + + +def draw_text_line(text, y=0): + """ + Draws a line of text onto the display surface + The text will be centered horizontally at the given y postition + The text's height is added to y and returned to the caller + """ + screen = pg.display.get_surface() + surf = font.render(text, 1, (255, 255, 255)) + y += surf.get_height() + x = (screen.get_width() - surf.get_width()) / 2 + screen.blit(surf, (x, y)) + return y + + +def change_music_postion(amount): + """ + Changes current playback postition by amount seconds. + This only works with OGG and MP3 files. + music.get_pos() returns how many milliseconds the song has played, not + the current postion in the file. We must track the starting postion + ourselves. music.set_pos() will set the position in seconds. + """ + global starting_pos + + if starting_pos >= 0: # will be -1 unless play_file() was OGG or MP3 + played_for = pg.mixer.music.get_pos() / 1000.0 + old_pos = starting_pos + played_for + starting_pos = old_pos + amount + pg.mixer.music.play(start=starting_pos) + print("jumped from {} to {}".format(old_pos, starting_pos)) + + +MUSIC_DONE = pg.event.custom_type() # event to be set as mixer.music.set_endevent() +main_dir = os.path.split(os.path.abspath(__file__))[0] +data_dir = os.path.join(main_dir, "data") + +starting_pos = 0 # needed to fast forward and rewind +volume = 0.75 +music_file_list = [] +music_file_types = ("mp3", "ogg", "mid", "mod", "it", "xm", "wav") +music_can_seek = ("mp3", "ogg", "mod", "it", "xm") + + +def main(): + global font # this will be used by the draw_text_line function + global volume, starting_pos + running = True + paused = False + + # we will be polling for key up and key down events + # users should be able to change the volume by holding the up and down arrows + # the change_volume variable will be set by key down events and cleared by key up events + change_volume = 0 + + pg.init() + pg.display.set_mode((640, 480)) + font = pg.font.SysFont("Arial", 24) + clock = pg.time.Clock() + + pg.scrap.init() + pg.SCRAP_TEXT = pg.scrap.get_types()[0] # TODO remove when scrap module is fixed + clipped = pg.scrap.get(pg.SCRAP_TEXT).decode("UTF-8") + # store the current text from the clipboard TODO remove decode + + # add the command line arguments to the music_file_list + for arg in sys.argv[1:]: + add_file(arg) + play_file("house_lo.ogg") # play default music included with pygame + + # draw instructions on screen + y = draw_text_line("Drop music files or path names onto this window", 20) + y = draw_text_line("Copy file names into the clipboard", y) + y = draw_text_line("Or feed them from the command line", y) + y = draw_text_line("If it's music it will play!", y) + y = draw_text_line("SPACE to pause or UP/DOWN to change volume", y) + y = draw_text_line("LEFT and RIGHT will skip around the track", y) + draw_text_line("Other keys will start the next track", y) + + """ + This is the main loop + It will respond to drag and drop, clipboard changes, and key presses + """ + while running: + for ev in pg.event.get(): + if ev.type == pg.QUIT: + running = False + elif ev.type == pg.DROPTEXT: + play_file(ev.text) + elif ev.type == pg.DROPFILE: + play_file(ev.file) + elif ev.type == MUSIC_DONE: + play_next() + elif ev.type == pg.KEYDOWN: + if ev.key == pg.K_ESCAPE: + running = False # exit loop + elif ev.key in (pg.K_SPACE, pg.K_RETURN): + if paused: + pg.mixer.music.unpause() + paused = False + else: + pg.mixer.music.pause() + paused = True + elif ev.key == pg.K_UP: + change_volume = VOLUME_CHANGE_AMOUNT + elif ev.key == pg.K_DOWN: + change_volume = -VOLUME_CHANGE_AMOUNT + elif ev.key == pg.K_RIGHT: + change_music_postion(+5) + elif ev.key == pg.K_LEFT: + change_music_postion(-5) + + else: + play_next() + + elif ev.type == pg.KEYUP: + if ev.key in (pg.K_UP, pg.K_DOWN): + change_volume = 0 + + # is the user holding up or down? + if change_volume: + volume += change_volume + volume = min(max(0, volume), 1) # volume should be between 0 and 1 + pg.mixer.music.set_volume(volume) + print("volume:", volume) + + # TODO remove decode when SDL2 scrap is fixed + new_text = pg.scrap.get(pg.SCRAP_TEXT).decode("UTF-8") + if new_text != clipped: # has the clipboard changed? + clipped = new_text + play_file(clipped) # try to play the file if it has + + pg.display.flip() + clock.tick(9) # keep CPU use down by updating screen less often + + pg.quit() + + +if __name__ == "__main__": + main() diff --git a/venv/Lib/site-packages/pygame/examples/pixelarray.py b/venv/Lib/site-packages/pygame/examples/pixelarray.py new file mode 100644 index 0000000..9961091 --- /dev/null +++ b/venv/Lib/site-packages/pygame/examples/pixelarray.py @@ -0,0 +1,142 @@ +#!/usr/bin/env python +""" pygame.examples.pixelarray + +PixelArray does array processing of pixels. +Sort of like another array processor called 'numpy' - But for pixels. + + Flip it, + stripe it, + rotate it. + +Controls +-------- + +To see different effects - press a key or click a mouse. +""" +import os +import pygame as pg + + +main_dir = os.path.split(os.path.abspath(__file__))[0] +data_dir = os.path.join(main_dir, "data") + + +def show(image): + screen = pg.display.get_surface() + screen.fill((255, 255, 255)) + screen.blit(image, (0, 0)) + pg.display.flip() + while 1: + event = pg.event.wait() + if event.type == pg.QUIT: + pg.quit() + raise SystemExit + if event.type in [pg.MOUSEBUTTONDOWN, pg.KEYDOWN]: + break + + +def main(): + pg.init() + + pg.display.set_mode((255, 255)) + surface = pg.Surface((255, 255)) + + pg.display.flip() + + # Create the PixelArray. + ar = pg.PixelArray(surface) + + # Do some easy gradient effect. + for y in range(255): + r, g, b = y, y, y + ar[:, y] = (r, g, b) + del ar + show(surface) + + # We have made some gradient effect, now flip it. + ar = pg.PixelArray(surface) + ar[:] = ar[:, ::-1] + del ar + show(surface) + + # Every second column will be made blue + ar = pg.PixelArray(surface) + ar[::2] = (0, 0, 255) + del ar + show(surface) + + # Every second row will be made green + ar = pg.PixelArray(surface) + ar[:, ::2] = (0, 255, 0) + del ar + show(surface) + + # Manipulate the image. Flip it around the y axis. + surface = pg.image.load(os.path.join(data_dir, "arraydemo.bmp")) + ar = pg.PixelArray(surface) + ar[:] = ar[:, ::-1] + del ar + show(surface) + + # Flip the image around the x axis. + ar = pg.PixelArray(surface) + ar[:] = ar[::-1, :] + del ar + show(surface) + + # Every second column will be made white. + ar = pg.PixelArray(surface) + ar[::2] = (255, 255, 255) + del ar + show(surface) + + # Flip the image around both axes, restoring its original layout. + ar = pg.PixelArray(surface) + ar[:] = ar[::-1, ::-1] + del ar + show(surface) + + # Rotate 90 degrees clockwise. + w, h = surface.get_size() + surface2 = pg.Surface((h, w), surface.get_flags(), surface) + ar = pg.PixelArray(surface) + ar2 = pg.PixelArray(surface2) + ar2[...] = ar.transpose()[::-1, :] + del ar, ar2 + show(surface2) + + # Scale it by throwing each second pixel away. + surface = pg.image.load(os.path.join(data_dir, "arraydemo.bmp")) + ar = pg.PixelArray(surface) + sf2 = ar[::2, ::2].make_surface() + del ar + show(sf2) + + # Replace anything looking like the blue color from the text. + ar = pg.PixelArray(surface) + ar.replace((60, 60, 255), (0, 255, 0), 0.06) + del ar + show(surface) + + # Extract anything which might be somewhat black. + surface = pg.image.load(os.path.join(data_dir, "arraydemo.bmp")) + ar = pg.PixelArray(surface) + ar2 = ar.extract((0, 0, 0), 0.07) + sf2 = ar2.surface + del ar, ar2 + show(sf2) + + # Compare two images. + surface = pg.image.load(os.path.join(data_dir, "alien1.gif")) + surface2 = pg.image.load(os.path.join(data_dir, "alien2.gif")) + ar1 = pg.PixelArray(surface) + ar2 = pg.PixelArray(surface2) + ar3 = ar1.compare(ar2, 0.07) + sf3 = ar3.surface + del ar1, ar2, ar3 + show(sf3) + + +if __name__ == "__main__": + main() + pg.quit() diff --git a/venv/Lib/site-packages/pygame/examples/playmus.py b/venv/Lib/site-packages/pygame/examples/playmus.py new file mode 100644 index 0000000..dac2f64 --- /dev/null +++ b/venv/Lib/site-packages/pygame/examples/playmus.py @@ -0,0 +1,165 @@ +#!/usr/bin/env python +""" pygame.examples.playmus + +A simple music player. + + Use pygame.mixer.music to play an audio file. + +A window is created to handle keyboard events for playback commands. + + +Keyboard Controls +----------------- + +space - play/pause toggle +r - rewind +f - fade out +q - stop + +""" +import sys + +import pygame as pg +import pygame.freetype + + +class Window(object): + """The application's Pygame window + + A Window instance manages the creation of and drawing to a + window. It is a singleton class. Only one instance can exist. + + """ + + instance = None + + def __new__(cls, *args, **kwds): + """Return an open Pygame window""" + + if Window.instance is not None: + return Window.instance + self = object.__new__(cls) + pg.display.init() + self.screen = pg.display.set_mode((600, 400)) + Window.instance = self + return self + + def __init__(self, title): + pg.display.set_caption(title) + self.text_color = (254, 231, 21, 255) + self.background_color = (16, 24, 32, 255) + self.screen.fill(self.background_color) + pg.display.flip() + + pygame.freetype.init() + self.font = pygame.freetype.Font(None, 20) + self.font.origin = True + self.ascender = int(self.font.get_sized_ascender() * 1.5) + self.descender = int(self.font.get_sized_descender() * 1.5) + self.line_height = self.ascender - self.descender + + self.write_lines( + "\nPress 'q' or 'ESCAPE' or close this window to quit\n" + "Press 'SPACE' to play / pause\n" + "Press 'r' to rewind to the beginning (restart)\n" + "Press 'f' to fade music out over 5 seconds\n\n" + "Window will quit automatically when music ends\n", + 0, + ) + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + self.close() + return False + + def close(self): + pg.display.quit() + Window.instance = None + + def write_lines(self, text, line=0): + w, h = self.screen.get_size() + line_height = self.line_height + nlines = h // line_height + if line < 0: + line = nlines + line + for i, text_line in enumerate(text.split("\n"), line): + y = i * line_height + self.ascender + # Clear the line first. + self.screen.fill( + self.background_color, (0, i * line_height, w, line_height) + ) + # Write new text. + self.font.render_to(self.screen, (15, y), text_line, self.text_color) + pg.display.flip() + + +def show_usage_message(): + print("Usage: python playmus.py ") + print(" python -m pygame.examples.playmus ") + + +def main(file_path): + """Play an audio file with pg.mixer.music""" + + with Window(file_path) as win: + win.write_lines("Loading ...", -1) + pg.mixer.init(frequency=44100) + try: + paused = False + pg.mixer.music.load(file_path) + + # Make sure the event loop ticks over at least every 0.5 seconds. + pg.time.set_timer(pg.USEREVENT, 500) + + pg.mixer.music.play() + win.write_lines("Playing ...\n", -1) + + while pg.mixer.music.get_busy() or paused: + e = pg.event.wait() + if e.type == pg.KEYDOWN: + key = e.key + if key == pg.K_SPACE: + if paused: + pg.mixer.music.unpause() + paused = False + win.write_lines("Playing ...\n", -1) + else: + pg.mixer.music.pause() + paused = True + win.write_lines("Paused ...\n", -1) + elif key == pg.K_r: + if file_path[-3:].lower() in ("ogg", "mp3", "mod"): + status = "Rewound." + pg.mixer.music.rewind() + else: + status = "Restarted." + pg.mixer.music.play() + if paused: + pg.mixer.music.pause() + win.write_lines(status, -1) + elif key == pg.K_f: + win.write_lines("Fading out ...\n", -1) + pg.mixer.music.fadeout(5000) + # when finished get_busy() will return False. + elif key in [pg.K_q, pg.K_ESCAPE]: + paused = False + pg.mixer.music.stop() + # get_busy() will now return False. + elif e.type == pg.QUIT: + paused = False + pg.mixer.music.stop() + # get_busy() will now return False. + pg.time.set_timer(pg.USEREVENT, 0) + finally: + pg.mixer.quit() + pg.quit() + + +if __name__ == "__main__": + # Check the only command line argument, a file path + if len(sys.argv) != 2: + show_usage_message() + else: + main(sys.argv[1]) diff --git a/venv/Lib/site-packages/pygame/examples/prevent_display_stretching.py b/venv/Lib/site-packages/pygame/examples/prevent_display_stretching.py new file mode 100644 index 0000000..363df81 --- /dev/null +++ b/venv/Lib/site-packages/pygame/examples/prevent_display_stretching.py @@ -0,0 +1,93 @@ +#!/usr/bin/env python +""" pygame.examples.prevent_display_stretching + +Prevent display stretching on Windows. + +On some computers, the display environment can be configured to stretch +all windows so that they will not appear too small on the screen for +the user. This configuration is especially common on high-DPI displays. +pygame graphics appear distorted when automatically stretched by the +display environment. This script demonstrates a technique for preventing +this stretching and distortion. + +Limitations: +This script makes an API call that is only available on Windows (versions +Vista and newer). + +""" + +# Ensure that the computer is running Windows Vista or newer +import os +import sys + +# game constants +TEXTCOLOR = "green" +BACKGROUNDCOLOR = "black" +AXISCOLOR = "white" + +if os.name != "nt" or sys.getwindowsversion()[0] < 6: + raise NotImplementedError("this script requires Windows Vista or newer") + +import pygame as pg + +import ctypes + +# Determine whether or not the user would like to prevent stretching +if os.path.basename(sys.executable) == "pythonw.exe": + selection = "y" +else: + selection = None + while selection not in ("y", "n"): + selection = input("Prevent stretching? (y/n): ").strip().lower() + +if selection == "y": + msg = "Stretching is prevented." +else: + msg = "Stretching is not prevented." + +# Prevent stretching +if selection == "y": + user32 = ctypes.windll.user32 + user32.SetProcessDPIAware() + +# Show screen +pg.display.init() +RESOLUTION = (350, 350) +screen = pg.display.set_mode(RESOLUTION) + +# Render message onto a surface +pg.font.init() +font = pg.font.Font(None, 36) +msg_surf = font.render(msg, 1, TEXTCOLOR) +res_surf = font.render("Intended resolution: %ix%i" % RESOLUTION, 1, TEXTCOLOR) + +# Control loop +running = True +clock = pg.time.Clock() +counter = 0 +while running: + + for event in pg.event.get(): + if event.type == pg.QUIT: + running = False + + screen.fill(BACKGROUNDCOLOR) + + # Draw lines which will be blurry if the window is stretched + # or clear if the window is not stretched. + pg.draw.line(screen, AXISCOLOR, (0, counter), (RESOLUTION[0] - 1, counter)) + pg.draw.line(screen, AXISCOLOR, (counter, 0), (counter, RESOLUTION[1] - 1)) + + # Blit message onto screen surface + msg_blit_rect = screen.blit(msg_surf, (0, 0)) + screen.blit(res_surf, (0, msg_blit_rect.bottom)) + + clock.tick(10) + + pg.display.flip() + + counter += 1 + if counter == RESOLUTION[0]: + counter = 0 + +pg.quit() diff --git a/venv/Lib/site-packages/pygame/examples/resizing_new.py b/venv/Lib/site-packages/pygame/examples/resizing_new.py new file mode 100644 index 0000000..cda01f2 --- /dev/null +++ b/venv/Lib/site-packages/pygame/examples/resizing_new.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python +import pygame as pg + +pg.init() + +RES = (160, 120) +FPS = 30 +clock = pg.time.Clock() + +screen = pg.display.set_mode(RES, pg.RESIZABLE) +pg.display._set_autoresize(False) + +# MAIN LOOP + +done = False + +i = 0 +j = 0 + +while not done: + for event in pg.event.get(): + if event.type == pg.KEYDOWN and event.key == pg.K_q: + done = True + if event.type == pg.QUIT: + done = True + # if event.type==pg.WINDOWRESIZED: + # screen=pg.display.get_surface() + if event.type == pg.VIDEORESIZE: + screen = pg.display.get_surface() + i += 1 + i = i % screen.get_width() + j += i % 2 + j = j % screen.get_height() + + screen.fill((255, 0, 255)) + pg.draw.circle(screen, (0, 0, 0), (100, 100), 20) + pg.draw.circle(screen, (0, 0, 200), (0, 0), 10) + pg.draw.circle(screen, (200, 0, 0), (160, 120), 30) + pg.draw.line(screen, (250, 250, 0), (0, 120), (160, 0)) + pg.draw.circle(screen, (255, 255, 255), (i, j), 5) + + pg.display.flip() + clock.tick(FPS) +pg.quit() diff --git a/venv/Lib/site-packages/pygame/examples/scaletest.py b/venv/Lib/site-packages/pygame/examples/scaletest.py new file mode 100644 index 0000000..6d7b964 --- /dev/null +++ b/venv/Lib/site-packages/pygame/examples/scaletest.py @@ -0,0 +1,158 @@ +#!/usr/bin/env python +""" pygame.examples.scaletest + +Shows an interactive image scaler. + +""" +import sys +import time +import pygame as pg + + +def main(imagefile, convert_alpha=False, run_speed_test=False): + """show an interactive image scaler + + Args: + imagefile - name of source image (required) + convert_alpha - use convert_alpha() on the surf (default False) + run_speed_test - (default False) + """ + + # initialize display + pg.display.init() + # load background image + background = pg.image.load(imagefile) + + if run_speed_test: + if convert_alpha: + # convert_alpha() requires the display mode to be set + pg.display.set_mode((1, 1)) + background = background.convert_alpha() + + SpeedTest(background) + return + + # start fullscreen mode + screen = pg.display.set_mode((1024, 768), pg.FULLSCREEN) + if convert_alpha: + background = background.convert_alpha() + + # turn off the mouse pointer + pg.mouse.set_visible(0) + # main loop + bRunning = True + bUp = False + bDown = False + bLeft = False + bRight = False + cursize = [background.get_width(), background.get_height()] + while bRunning: + image = pg.transform.smoothscale(background, cursize) + imgpos = image.get_rect(centerx=512, centery=384) + screen.fill((255, 255, 255)) + screen.blit(image, imgpos) + pg.display.flip() + for event in pg.event.get(): + if event.type == pg.QUIT or ( + event.type == pg.KEYDOWN and event.key == pg.K_ESCAPE + ): + bRunning = False + if event.type == pg.KEYDOWN: + if event.key == pg.K_UP: + bUp = True + if event.key == pg.K_DOWN: + bDown = True + if event.key == pg.K_LEFT: + bLeft = True + if event.key == pg.K_RIGHT: + bRight = True + if event.type == pg.KEYUP: + if event.key == pg.K_UP: + bUp = False + if event.key == pg.K_DOWN: + bDown = False + if event.key == pg.K_LEFT: + bLeft = False + if event.key == pg.K_RIGHT: + bRight = False + if bUp: + cursize[1] -= 2 + if cursize[1] < 1: + cursize[1] = 1 + if bDown: + cursize[1] += 2 + if bLeft: + cursize[0] -= 2 + if cursize[0] < 1: + cursize[0] = 1 + if bRight: + cursize[0] += 2 + pg.quit() + + +def SpeedTest(image): + print("\nImage Scaling Speed Test - Image Size %s\n" % str(image.get_size())) + + imgsize = [image.get_width(), image.get_height()] + duration = 0.0 + for i in range(128): + shrinkx = (imgsize[0] * i) // 128 + shrinky = (imgsize[1] * i) // 128 + start = time.time() + tempimg = pg.transform.smoothscale(image, (shrinkx, shrinky)) + duration += time.time() - start + del tempimg + + print( + "Average transform.smoothscale shrink time: %.4f ms." % (duration / 128 * 1000) + ) + + duration = 0.0 + for i in range(128): + expandx = (imgsize[0] * (i + 129)) // 128 + expandy = (imgsize[1] * (i + 129)) // 128 + start = time.time() + tempimg = pg.transform.smoothscale(image, (expandx, expandy)) + duration += time.time() - start + del tempimg + + print( + "Average transform.smoothscale expand time: %.4f ms." % (duration / 128 * 1000) + ) + + duration = 0.0 + for i in range(128): + shrinkx = (imgsize[0] * i) // 128 + shrinky = (imgsize[1] * i) // 128 + start = time.time() + tempimg = pg.transform.scale(image, (shrinkx, shrinky)) + duration += time.time() - start + del tempimg + + print("Average transform.scale shrink time: %.4f ms." % (duration / 128 * 1000)) + + duration = 0.0 + for i in range(128): + expandx = (imgsize[0] * (i + 129)) // 128 + expandy = (imgsize[1] * (i + 129)) // 128 + start = time.time() + tempimg = pg.transform.scale(image, (expandx, expandy)) + duration += time.time() - start + del tempimg + + print("Average transform.scale expand time: %.4f ms." % (duration / 128 * 1000)) + + +if __name__ == "__main__": + # check input parameters + if len(sys.argv) < 2: + print("\nUsage: %s imagefile [-t] [-convert_alpha]" % sys.argv[0]) + print(" imagefile image filename (required)") + print(" -t run speed test") + print(" -convert_alpha use convert_alpha() on the image's " "surface\n") + else: + main( + sys.argv[1], + convert_alpha="-convert_alpha" in sys.argv, + run_speed_test="-t" in sys.argv, + ) diff --git a/venv/Lib/site-packages/pygame/examples/scrap_clipboard.py b/venv/Lib/site-packages/pygame/examples/scrap_clipboard.py new file mode 100644 index 0000000..5978a42 --- /dev/null +++ b/venv/Lib/site-packages/pygame/examples/scrap_clipboard.py @@ -0,0 +1,94 @@ +#!/usr/bin/env python +""" pygame.examples.scrap_clipboard + +Demonstrates the clipboard capabilities of pygame. + +Copy/paste! + + +Keyboard Controls +----------------- + +g - get and print types in clipboard. If, image blit to screen. +p - place some text into clipboard +a - print types available in the clipboard +i - put image into the clipboard +""" +import os + +import pygame as pg +import pygame.scrap as scrap + +from io import BytesIO + + +def usage(): + print("Press the 'g' key to get all of the current clipboard data") + print("Press the 'p' key to put a string into the clipboard") + print("Press the 'a' key to get a list of the currently available types") + print("Press the 'i' key to put an image into the clipboard") + + +main_dir = os.path.split(os.path.abspath(__file__))[0] + +pg.init() +screen = pg.display.set_mode((200, 200)) +c = pg.time.Clock() +going = True + +# Initialize the scrap module and use the clipboard mode. +scrap.init() +scrap.set_mode(pg.SCRAP_CLIPBOARD) + +usage() + +while going: + for e in pg.event.get(): + if e.type == pg.QUIT or (e.type == pg.KEYDOWN and e.key == pg.K_ESCAPE): + going = False + + elif e.type == pg.KEYDOWN and e.key == pg.K_g: + # This means to look for data. + print("Getting the different clipboard data..") + for t in scrap.get_types(): + r = scrap.get(t) + if r and len(r) > 500: + print("Type %s : (large %i byte buffer)" % (t, len(r))) + elif r is None: + print("Type %s : None" % (t,)) + else: + print("Type %s : '%s'" % (t, r.decode("ascii", "ignore"))) + if "image" in t: + namehint = t.split("/")[1] + if namehint in ["bmp", "png", "jpg"]: + f = BytesIO(r) + loaded_surf = pg.image.load(f, "." + namehint) + screen.blit(loaded_surf, (0, 0)) + + elif e.type == pg.KEYDOWN and e.key == pg.K_p: + # Place some text into the selection. + print("Placing clipboard text.") + scrap.put(pg.SCRAP_TEXT, b"Hello. This is a message from scrap.") + + elif e.type == pg.KEYDOWN and e.key == pg.K_a: + # Get all available types. + print("Getting the available types from the clipboard.") + types = scrap.get_types() + print(types) + if len(types) > 0: + print("Contains %s: %s" % (types[0], scrap.contains(types[0]))) + print("Contains _INVALID_: ", scrap.contains("_INVALID_")) + + elif e.type == pg.KEYDOWN and e.key == pg.K_i: + print("Putting image into the clipboard.") + scrap.set_mode(pg.SCRAP_CLIPBOARD) + fp = open(os.path.join(main_dir, "data", "liquid.bmp"), "rb") + buf = fp.read() + scrap.put("image/bmp", buf) + fp.close() + + elif e.type in (pg.KEYDOWN, pg.MOUSEBUTTONDOWN): + usage() + pg.display.flip() + c.tick(40) +pg.quit() diff --git a/venv/Lib/site-packages/pygame/examples/scroll.py b/venv/Lib/site-packages/pygame/examples/scroll.py new file mode 100644 index 0000000..48b7417 --- /dev/null +++ b/venv/Lib/site-packages/pygame/examples/scroll.py @@ -0,0 +1,192 @@ +#!/usr/bin/env python +""" pygame.examples.scroll + +An zoomed image viewer that demonstrates Surface.scroll + +This example shows a scrollable image that has a zoom factor of eight. +It uses the Surface.scroll function to shift the image on the display +surface. A clip rectangle protects a margin area. If called as a function, +the example accepts an optional image file path. If run as a program +it takes an optional file path command line argument. If no file +is provided a default image file is used. + +When running click on a black triangle to move one pixel in the direction +the triangle points. Or use the arrow keys. Close the window or press ESC +to quit. +""" +import sys +import os + +import pygame as pg +from pygame.transform import scale + +main_dir = os.path.dirname(os.path.abspath(__file__)) + +# game constants +DIR_UP = 1 +DIR_DOWN = 2 +DIR_LEFT = 3 +DIR_RIGHT = 4 + +zoom_factor = 8 + + +def draw_arrow(surf, color, posn, direction): + x, y = posn + if direction == DIR_UP: + pointlist = ((x - 29, y + 30), (x + 30, y + 30), (x + 1, y - 29), (x, y - 29)) + elif direction == DIR_DOWN: + pointlist = ((x - 29, y - 29), (x + 30, y - 29), (x + 1, y + 30), (x, y + 30)) + elif direction == DIR_LEFT: + pointlist = ((x + 30, y - 29), (x + 30, y + 30), (x - 29, y + 1), (x - 29, y)) + else: + pointlist = ((x - 29, y - 29), (x - 29, y + 30), (x + 30, y + 1), (x + 30, y)) + pg.draw.polygon(surf, color, pointlist) + + +def add_arrow_button(screen, regions, posn, direction): + draw_arrow(screen, "black", posn, direction) + draw_arrow(regions, (direction, 0, 0), posn, direction) + + +def scroll_view(screen, image, direction, view_rect): + src_rect = None + zoom_view_rect = screen.get_clip() + image_w, image_h = image.get_size() + if direction == DIR_UP: + if view_rect.top > 0: + screen.scroll(dy=zoom_factor) + view_rect.move_ip(0, -1) + src_rect = view_rect.copy() + src_rect.h = 1 + dst_rect = zoom_view_rect.copy() + dst_rect.h = zoom_factor + elif direction == DIR_DOWN: + if view_rect.bottom < image_h: + screen.scroll(dy=-zoom_factor) + view_rect.move_ip(0, 1) + src_rect = view_rect.copy() + src_rect.h = 1 + src_rect.bottom = view_rect.bottom + dst_rect = zoom_view_rect.copy() + dst_rect.h = zoom_factor + dst_rect.bottom = zoom_view_rect.bottom + elif direction == DIR_LEFT: + if view_rect.left > 0: + screen.scroll(dx=zoom_factor) + view_rect.move_ip(-1, 0) + src_rect = view_rect.copy() + src_rect.w = 1 + dst_rect = zoom_view_rect.copy() + dst_rect.w = zoom_factor + elif direction == DIR_RIGHT: + if view_rect.right < image_w: + screen.scroll(dx=-zoom_factor) + view_rect.move_ip(1, 0) + src_rect = view_rect.copy() + src_rect.w = 1 + src_rect.right = view_rect.right + dst_rect = zoom_view_rect.copy() + dst_rect.w = zoom_factor + dst_rect.right = zoom_view_rect.right + if src_rect is not None: + scale(image.subsurface(src_rect), dst_rect.size, screen.subsurface(dst_rect)) + pg.display.update(zoom_view_rect) + + +def main(image_file=None): + if image_file is None: + image_file = os.path.join(main_dir, "data", "arraydemo.bmp") + margin = 80 + view_size = (30, 20) + zoom_view_size = (view_size[0] * zoom_factor, view_size[1] * zoom_factor) + win_size = (zoom_view_size[0] + 2 * margin, zoom_view_size[1] + 2 * margin) + background_color = pg.Color("beige") + + pg.init() + + # set up key repeating so we can hold down the key to scroll. + old_k_delay, old_k_interval = pg.key.get_repeat() + pg.key.set_repeat(500, 30) + + try: + screen = pg.display.set_mode(win_size) + screen.fill(background_color) + pg.display.flip() + + image = pg.image.load(image_file).convert() + image_w, image_h = image.get_size() + + if image_w < view_size[0] or image_h < view_size[1]: + print("The source image is too small for this example.") + print("A %i by %i or larger image is required." % zoom_view_size) + return + + regions = pg.Surface(win_size, 0, 24) + add_arrow_button(screen, regions, (40, win_size[1] // 2), DIR_LEFT) + add_arrow_button( + screen, regions, (win_size[0] - 40, win_size[1] // 2), DIR_RIGHT + ) + add_arrow_button(screen, regions, (win_size[0] // 2, 40), DIR_UP) + add_arrow_button( + screen, regions, (win_size[0] // 2, win_size[1] - 40), DIR_DOWN + ) + pg.display.flip() + + screen.set_clip((margin, margin, zoom_view_size[0], zoom_view_size[1])) + + view_rect = pg.Rect(0, 0, view_size[0], view_size[1]) + + scale( + image.subsurface(view_rect), + zoom_view_size, + screen.subsurface(screen.get_clip()), + ) + pg.display.flip() + + # the direction we will scroll in. + direction = None + + clock = pg.time.Clock() + clock.tick() + + going = True + while going: + # wait for events before doing anything. + # events = [pg.event.wait()] + pg.event.get() + events = pg.event.get() + + for e in events: + if e.type == pg.KEYDOWN: + if e.key == pg.K_ESCAPE: + going = False + elif e.key == pg.K_DOWN: + scroll_view(screen, image, DIR_DOWN, view_rect) + elif e.key == pg.K_UP: + scroll_view(screen, image, DIR_UP, view_rect) + elif e.key == pg.K_LEFT: + scroll_view(screen, image, DIR_LEFT, view_rect) + elif e.key == pg.K_RIGHT: + scroll_view(screen, image, DIR_RIGHT, view_rect) + elif e.type == pg.QUIT: + going = False + elif e.type == pg.MOUSEBUTTONDOWN: + direction = regions.get_at(e.pos)[0] + elif e.type == pg.MOUSEBUTTONUP: + direction = None + + if direction: + scroll_view(screen, image, direction, view_rect) + clock.tick(30) + + finally: + pg.key.set_repeat(old_k_delay, old_k_interval) + pg.quit() + + +if __name__ == "__main__": + if len(sys.argv) > 1: + image_file = sys.argv[1] + else: + image_file = None + main(image_file) diff --git a/venv/Lib/site-packages/pygame/examples/setmodescale.py b/venv/Lib/site-packages/pygame/examples/setmodescale.py new file mode 100644 index 0000000..3f427d2 --- /dev/null +++ b/venv/Lib/site-packages/pygame/examples/setmodescale.py @@ -0,0 +1,67 @@ +#!/usr/bin/env python +""" pygame.examples.setmodescale + +On high resolution displays(4k, 1080p) and tiny graphics games (640x480) +show up very small so that they are unplayable. SCALED scales up the window +for you. The game thinks it's a 640x480 window, but really it can be bigger. +Mouse events are scaled for you, so your game doesn't need to do it. + +Passing SCALED to pygame.display.set_mode means the resolution depends +on desktop size and the graphics are scaled. +""" + +import pygame as pg + +pg.init() + +RES = (160, 120) +FPS = 30 +clock = pg.time.Clock() + +print("desktops", pg.display.get_desktop_sizes()) +screen = pg.display.set_mode(RES, pg.SCALED | pg.RESIZABLE) + +# MAIN LOOP + +done = False + +i = 0 +j = 0 + +r_name, r_flags = pg.display._get_renderer_info() +print("renderer:", r_name, "flags:", bin(r_flags)) +for flag, name in [ + (1, "software"), + (2, "accelerated"), + (4, "VSync"), + (8, "render to texture"), +]: + if flag & r_flags: + print(name) + +while not done: + for event in pg.event.get(): + if event.type == pg.KEYDOWN and event.key == pg.K_q: + done = True + if event.type == pg.QUIT: + done = True + if event.type == pg.KEYDOWN and event.key == pg.K_f: + pg.display.toggle_fullscreen() + if event.type == pg.VIDEORESIZE: + pg.display._resize_event(event) + + i += 1 + i = i % screen.get_width() + j += i % 2 + j = j % screen.get_height() + + screen.fill((255, 0, 255)) + pg.draw.circle(screen, (0, 0, 0), (100, 100), 20) + pg.draw.circle(screen, (0, 0, 200), (0, 0), 10) + pg.draw.circle(screen, (200, 0, 0), (160, 120), 30) + pg.draw.line(screen, (250, 250, 0), (0, 120), (160, 0)) + pg.draw.circle(screen, (255, 255, 255), (i, j), 5) + + pg.display.flip() + clock.tick(FPS) +pg.quit() diff --git a/venv/Lib/site-packages/pygame/examples/sound.py b/venv/Lib/site-packages/pygame/examples/sound.py new file mode 100644 index 0000000..c5a23b9 --- /dev/null +++ b/venv/Lib/site-packages/pygame/examples/sound.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python +""" pygame.examples.sound + +Playing a soundfile and waiting for it to finish. You'll need the +pygame.mixer module for this to work. Note how in this simple example +we don't even bother loading all of the pygame package. +Just pick the mixer for sound and time for the delay function. + +Optional command line argument: audio file name +""" +import os +import sys +import pygame as pg + +main_dir = os.path.split(os.path.abspath(__file__))[0] + + +def main(file_path=None): + """Play an audio file as a buffered sound sample + + :param str file_path: audio file (default data/secosmic_low.wav) + """ + # choose a desired audio format + pg.mixer.init(11025) # raises exception on fail + + # load the sound + sound = pg.mixer.Sound(file_path) + + # start playing + print("Playing Sound...") + channel = sound.play() + + # poll until finished + while channel.get_busy(): # still playing + print(" ...still going...") + pg.time.wait(1000) + print("...Finished") + pg.quit() + + +if __name__ == "__main__": + if len(sys.argv) > 1: + main(sys.argv[1]) + else: + main(os.path.join(main_dir, "data", "secosmic_lo.wav")) diff --git a/venv/Lib/site-packages/pygame/examples/sound_array_demos.py b/venv/Lib/site-packages/pygame/examples/sound_array_demos.py new file mode 100644 index 0000000..1a2b49d --- /dev/null +++ b/venv/Lib/site-packages/pygame/examples/sound_array_demos.py @@ -0,0 +1,217 @@ +#!/usr/bin/env python +""" pygame.examples.sound_array_demos + +Creates an echo effect on any Sound object. + +Uses sndarray and numpy to create offset faded copies of the +original sound. Currently it just uses hardcoded values for the +number of echos and the delay. Easy for you to recreate as +needed. + +version 2. changes: +- Should work with different sample rates now. +- put into a function. +- Uses numpy by default, but falls back on Numeric. +""" +import os +import pygame as pg +from numpy import zeros, int32, int16 +import time + + +# pg.mixer.init(44100, -16, 0) +pg.mixer.init() +# pg.mixer.init(11025, -16, 0) +# pg.mixer.init(11025) + + +def make_echo(sound, samples_per_second, mydebug=True): + """returns a sound which is echoed of the last one.""" + + echo_length = 3.5 + + a1 = pg.sndarray.array(sound) + if mydebug: + print("SHAPE1: %s" % (a1.shape,)) + + length = a1.shape[0] + + # myarr = zeros(length+12000) + myarr = zeros(a1.shape, int32) + + if len(a1.shape) > 1: + # mult = a1.shape[1] + size = (a1.shape[0] + int(echo_length * a1.shape[0]), a1.shape[1]) + # size = (a1.shape[0] + int(a1.shape[0] + (echo_length * 3000)), a1.shape[1]) + else: + # mult = 1 + size = (a1.shape[0] + int(echo_length * a1.shape[0]),) + # size = (a1.shape[0] + int(a1.shape[0] + (echo_length * 3000)),) + + if mydebug: + print(int(echo_length * a1.shape[0])) + myarr = zeros(size, int32) + + if mydebug: + print("size %s" % (size,)) + print(myarr.shape) + myarr[:length] = a1 + # print (myarr[3000:length+3000]) + # print (a1 >> 1) + # print ("a1.shape %s" % (a1.shape,)) + # c = myarr[3000:length+(3000*mult)] + # print ("c.shape %s" % (c.shape,)) + + incr = int(samples_per_second / echo_length) + gap = length + + myarr[incr : gap + incr] += a1 >> 1 + myarr[incr * 2 : gap + (incr * 2)] += a1 >> 2 + myarr[incr * 3 : gap + (incr * 3)] += a1 >> 3 + myarr[incr * 4 : gap + (incr * 4)] += a1 >> 4 + + if mydebug: + print("SHAPE2: %s" % (myarr.shape,)) + + sound2 = pg.sndarray.make_sound(myarr.astype(int16)) + + return sound2 + + +def slow_down_sound(sound, rate): + """returns a sound which is a slowed down version of the original. + rate - at which the sound should be slowed down. eg. 0.5 would be half speed. + """ + + raise NotImplementedError() + # grow_rate = 1 / rate + # make it 1/rate times longer. + # a1 = pg.sndarray.array(sound) + # surf = pg.surfarray.make_surface(a1) + # print (a1.shape[0] * grow_rate) + # scaled_surf = pg.transform.scale(surf, (int(a1.shape[0] * grow_rate), a1.shape[1])) + # print (scaled_surf) + # print (surf) + + # a2 = a1 * rate + # print (a1.shape) + # print (a2.shape) + # print (a2) + # sound2 = pg.sndarray.make_sound(a2.astype(int16)) + # return sound2 + + +def sound_from_pos(sound, start_pos, samples_per_second=None, inplace=1): + """returns a sound which begins at the start_pos. + start_pos - in seconds from the begining. + samples_per_second - + """ + + # see if we want to reuse the sound data or not. + if inplace: + a1 = pg.sndarray.samples(sound) + else: + a1 = pg.sndarray.array(sound) + + # see if samples per second has been given. If not, query the pg.mixer. + # eg. it might be set to 22050 + if samples_per_second is None: + samples_per_second = pg.mixer.get_init()[0] + + # figure out the start position in terms of samples. + start_pos_in_samples = int(start_pos * samples_per_second) + + # cut the beginning off the sound at the start position. + a2 = a1[start_pos_in_samples:] + + # make the Sound instance from the array. + sound2 = pg.sndarray.make_sound(a2) + + return sound2 + + +def main(): + """play various sndarray effects""" + + main_dir = os.path.split(os.path.abspath(__file__))[0] + print("mixer.get_init %s" % (pg.mixer.get_init(),)) + + samples_per_second = pg.mixer.get_init()[0] + + print(("-" * 30) + "\n") + print("loading sound") + sound = pg.mixer.Sound(os.path.join(main_dir, "data", "car_door.wav")) + + print("-" * 30) + print("start positions") + print("-" * 30) + + start_pos = 0.1 + sound2 = sound_from_pos(sound, start_pos, samples_per_second) + + print("sound.get_length %s" % (sound.get_length(),)) + print("sound2.get_length %s" % (sound2.get_length(),)) + sound2.play() + while pg.mixer.get_busy(): + pg.time.wait(200) + + print("waiting 2 seconds") + pg.time.wait(2000) + print("playing original sound") + + sound.play() + while pg.mixer.get_busy(): + pg.time.wait(200) + + print("waiting 2 seconds") + pg.time.wait(2000) + + # if 0: + # #TODO: this is broken. + # print (("-" * 30) + "\n") + # print ("Slow down the original sound.") + # rate = 0.2 + # slowed_sound = slow_down_sound(sound, rate) + # slowed_sound.play() + # while pg.mixer.get_busy(): + # pg.time.wait(200) + + print("-" * 30) + print("echoing") + print("-" * 30) + + t1 = time.time() + sound2 = make_echo(sound, samples_per_second) + print("time to make echo %i" % (time.time() - t1,)) + + print("original sound") + sound.play() + while pg.mixer.get_busy(): + pg.time.wait(200) + + print("echoed sound") + sound2.play() + while pg.mixer.get_busy(): + pg.time.wait(200) + + sound = pg.mixer.Sound(os.path.join(main_dir, "data", "secosmic_lo.wav")) + + t1 = time.time() + sound3 = make_echo(sound, samples_per_second) + print("time to make echo %i" % (time.time() - t1,)) + + print("original sound") + sound.play() + while pg.mixer.get_busy(): + pg.time.wait(200) + + print("echoed sound") + sound3.play() + while pg.mixer.get_busy(): + pg.time.wait(200) + + pg.quit() + + +if __name__ == "__main__": + main() diff --git a/venv/Lib/site-packages/pygame/examples/sprite_texture.py b/venv/Lib/site-packages/pygame/examples/sprite_texture.py new file mode 100644 index 0000000..79d8cf5 --- /dev/null +++ b/venv/Lib/site-packages/pygame/examples/sprite_texture.py @@ -0,0 +1,104 @@ +#!/usr/bin/env python +""" pygame.examples.sprite_texture + +Experimental! Uses APIs which may disapear in the next release (_sdl2 is private). + + +Hardware accelerated Image objects with pygame.sprite. + +_sdl2.video.Image is a backwards compatible way with to use Texture with +pygame.sprite groups. +""" +import os +import pygame as pg + +if pg.get_sdl_version()[0] < 2: + raise SystemExit("This example requires pygame 2 and SDL2.") +from pygame._sdl2 import Window, Texture, Image, Renderer + + +data_dir = os.path.join(os.path.split(os.path.abspath(__file__))[0], "data") + + +def load_img(file): + return pg.image.load(os.path.join(data_dir, file)) + + +pg.display.init() +pg.key.set_repeat(10, 10) + +win = Window("asdf", resizable=True) +renderer = Renderer(win) +tex = Texture.from_surface(renderer, load_img("alien1.gif")) + + +class Something(pg.sprite.Sprite): + def __init__(self, img): + pg.sprite.Sprite.__init__(self) + + self.rect = img.get_rect() + self.image = img + + self.rect.w *= 5 + self.rect.h *= 5 + + img.origin = self.rect.w / 2, self.rect.h / 2 + + +sprite = Something(Image(tex, (0, 0, tex.width / 2, tex.height / 2))) +sprite.rect.x = 250 +sprite.rect.y = 50 + +# sprite2 = Something(Image(sprite.image)) +sprite2 = Something(Image(tex)) +sprite2.rect.x = 250 +sprite2.rect.y = 250 +sprite2.rect.w /= 2 +sprite2.rect.h /= 2 + +group = pg.sprite.Group() +group.add(sprite2) +group.add(sprite) + +import math + +t = 0 +running = True +clock = pg.time.Clock() +renderer.draw_color = (255, 0, 0, 255) + +while running: + for event in pg.event.get(): + if event.type == pg.QUIT: + running = False + elif event.type == pg.KEYDOWN: + if event.key == pg.K_ESCAPE: + running = False + elif event.key == pg.K_LEFT: + sprite.rect.x -= 5 + elif event.key == pg.K_RIGHT: + sprite.rect.x += 5 + elif event.key == pg.K_DOWN: + sprite.rect.y += 5 + elif event.key == pg.K_UP: + sprite.rect.y -= 5 + + renderer.clear() + t += 1 + + img = sprite.image + img.angle += 1 + img.flipX = t % 50 < 25 + img.flipY = t % 100 < 50 + img.color[0] = int(255.0 * (0.5 + math.sin(0.5 * t + 10.0) / 2.0)) + img.alpha = int(255.0 * (0.5 + math.sin(0.1 * t) / 2.0)) + # img.draw(dstrect=(x, y, 5 * img.srcrect['w'], 5 * img.srcrect['h'])) + + group.draw(renderer) + + renderer.present() + + clock.tick(60) + win.title = str("FPS: {}".format(clock.get_fps())) + +pg.quit() diff --git a/venv/Lib/site-packages/pygame/examples/stars.py b/venv/Lib/site-packages/pygame/examples/stars.py new file mode 100644 index 0000000..1bd2ac6 --- /dev/null +++ b/venv/Lib/site-packages/pygame/examples/stars.py @@ -0,0 +1,103 @@ +#!/usr/bin/env python +""" pg.examples.stars + + We are all in the gutter, + but some of us are looking at the stars. + -- Oscar Wilde + +A simple starfield example. Note you can move the 'center' of +the starfield by leftclicking in the window. This example show +the basics of creating a window, simple pixel plotting, and input +event management. +""" +import random +import math +import pygame as pg + +# constants +WINSIZE = [640, 480] +WINCENTER = [320, 240] +NUMSTARS = 150 + + +def init_star(): + "creates new star values" + dir = random.randrange(100000) + velmult = random.random() * 0.6 + 0.4 + vel = [math.sin(dir) * velmult, math.cos(dir) * velmult] + return vel, WINCENTER[:] + + +def initialize_stars(): + "creates a new starfield" + stars = [] + for x in range(NUMSTARS): + star = init_star() + vel, pos = star + steps = random.randint(0, WINCENTER[0]) + pos[0] = pos[0] + (vel[0] * steps) + pos[1] = pos[1] + (vel[1] * steps) + vel[0] = vel[0] * (steps * 0.09) + vel[1] = vel[1] * (steps * 0.09) + stars.append(star) + move_stars(stars) + return stars + + +def draw_stars(surface, stars, color): + "used to draw (and clear) the stars" + for vel, pos in stars: + pos = (int(pos[0]), int(pos[1])) + surface.set_at(pos, color) + + +def move_stars(stars): + "animate the star values" + for vel, pos in stars: + pos[0] = pos[0] + vel[0] + pos[1] = pos[1] + vel[1] + if not 0 <= pos[0] <= WINSIZE[0] or not 0 <= pos[1] <= WINSIZE[1]: + vel[:], pos[:] = init_star() + else: + vel[0] = vel[0] * 1.05 + vel[1] = vel[1] * 1.05 + + +def main(): + "This is the starfield code" + # create our starfield + random.seed() + stars = initialize_stars() + clock = pg.time.Clock() + # initialize and prepare screen + pg.init() + screen = pg.display.set_mode(WINSIZE) + pg.display.set_caption("pygame Stars Example") + white = 255, 240, 200 + black = 20, 20, 40 + screen.fill(black) + + # main game loop + done = 0 + while not done: + draw_stars(screen, stars, black) + move_stars(stars) + draw_stars(screen, stars, white) + pg.display.update() + for e in pg.event.get(): + if e.type == pg.QUIT or (e.type == pg.KEYUP and e.key == pg.K_ESCAPE): + done = 1 + break + elif e.type == pg.MOUSEBUTTONDOWN and e.button == 1: + WINCENTER[:] = list(e.pos) + clock.tick(50) + pg.quit() + + +# if python says run, then we should run +if __name__ == "__main__": + main() + + # I prefer the time of insects to the time of stars. + # + # -- WisÅ‚awa Szymborska diff --git a/venv/Lib/site-packages/pygame/examples/testsprite.py b/venv/Lib/site-packages/pygame/examples/testsprite.py new file mode 100644 index 0000000..825fb9e --- /dev/null +++ b/venv/Lib/site-packages/pygame/examples/testsprite.py @@ -0,0 +1,261 @@ +#!/usr/bin/env python +""" pg.examples.testsprite + +Like the testsprite.c that comes with libsdl, this pygame version shows +lots of sprites moving around. + +It is an abomination of ugly code, and mostly used for testing. + + +See pg.examples.aliens for some prettyier code. +""" +import sys +import os + +from random import randint +from time import time + +import pygame as pg + + +if "-psyco" in sys.argv: + try: + import psyco + + psyco.full() + except Exception: + print("No psyco for you! psyco failed to import and run.") + +main_dir = os.path.split(os.path.abspath(__file__))[0] +data_dir = os.path.join(main_dir, "data") + + +# use this to use update rects or not. +# If the screen is mostly full, then update rects are not useful. +update_rects = True +if "-update_rects" in sys.argv: + update_rects = True +if "-noupdate_rects" in sys.argv: + update_rects = False + +use_static = False +if "-static" in sys.argv: + use_static = True + + +use_layered_dirty = False +if "-layered_dirty" in sys.argv: + update_rects = True + use_layered_dirty = True + + +flags = 0 +if "-flip" in sys.argv: + flags ^= pg.DOUBLEBUF + +if "-fullscreen" in sys.argv: + flags ^= pg.FULLSCREEN + +if "-sw" in sys.argv: + flags ^= pg.SWSURFACE + +use_rle = True + +if "-hw" in sys.argv: + flags ^= pg.HWSURFACE + use_rle = False + +if "-scaled" in sys.argv: + flags ^= pg.SCALED + +screen_dims = [640, 480] + +if "-height" in sys.argv: + i = sys.argv.index("-height") + screen_dims[1] = int(sys.argv[i + 1]) + +if "-width" in sys.argv: + i = sys.argv.index("-width") + screen_dims[0] = int(sys.argv[i + 1]) + +if "-alpha" in sys.argv: + use_alpha = True +else: + use_alpha = False + +print(screen_dims) + + +##class Thingy(pg.sprite.Sprite): +## images = None +## def __init__(self): +## pg.sprite.Sprite.__init__(self) +## self.image = Thingy.images[0] +## self.rect = self.image.get_rect() +## self.rect.x = randint(0, screen_dims[0]) +## self.rect.y = randint(0, screen_dims[1]) +## #self.vel = [randint(-10, 10), randint(-10, 10)] +## self.vel = [randint(-1, 1), randint(-1, 1)] +## +## def move(self): +## for i in [0, 1]: +## nv = self.rect[i] + self.vel[i] +## if nv >= screen_dims[i] or nv < 0: +## self.vel[i] = -self.vel[i] +## nv = self.rect[i] + self.vel[i] +## self.rect[i] = nv + + +class Thingy(pg.sprite.DirtySprite): + images = None + + def __init__(self): + ## pg.sprite.Sprite.__init__(self) + pg.sprite.DirtySprite.__init__(self) + self.image = Thingy.images[0] + self.rect = self.image.get_rect() + self.rect.x = randint(0, screen_dims[0]) + self.rect.y = randint(0, screen_dims[1]) + # self.vel = [randint(-10, 10), randint(-10, 10)] + self.vel = [randint(-1, 1), randint(-1, 1)] + self.dirty = 2 + + def update(self): + for i in [0, 1]: + nv = self.rect[i] + self.vel[i] + if nv >= screen_dims[i] or nv < 0: + self.vel[i] = -self.vel[i] + nv = self.rect[i] + self.vel[i] + self.rect[i] = nv + + +class Static(pg.sprite.DirtySprite): + images = None + + def __init__(self): + pg.sprite.DirtySprite.__init__(self) + self.image = Static.images[0] + self.rect = self.image.get_rect() + self.rect.x = randint(0, 3 * screen_dims[0] / 4) + self.rect.y = randint(0, 3 * screen_dims[1] / 4) + + +def main( + update_rects=True, + use_static=False, + use_layered_dirty=False, + screen_dims=[640, 480], + use_alpha=False, + flags=0, +): + """Show lots of sprites moving around + + Optional keyword arguments: + update_rects - use the RenderUpdate sprite group class (default True) + use_static - include non-moving images (default False) + use_layered_dirty - Use the FastRenderGroup sprite group (default False) + screen_dims - Pygame window dimensions (default [640, 480]) + use_alpha - use alpha blending (default False) + flags - additional display mode flags (default no additional flags) + + """ + + if use_layered_dirty: + update_rects = True + + pg.init() # needed to initialise time module for get_ticks() + pg.display.init() + + # if "-fast" in sys.argv: + + screen = pg.display.set_mode(screen_dims, flags, vsync="-vsync" in sys.argv) + + # this is mainly for GP2X, so it can quit. + pg.joystick.init() + num_joysticks = pg.joystick.get_count() + if num_joysticks > 0: + stick = pg.joystick.Joystick(0) + stick.init() # now we will receive events for the joystick + + screen.fill([0, 0, 0]) + pg.display.flip() + sprite_surface = pg.image.load(os.path.join(data_dir, "asprite.bmp")) + sprite_surface2 = pg.image.load(os.path.join(data_dir, "static.png")) + + if use_rle: + sprite_surface.set_colorkey([0xFF, 0xFF, 0xFF], pg.SRCCOLORKEY | pg.RLEACCEL) + sprite_surface2.set_colorkey([0xFF, 0xFF, 0xFF], pg.SRCCOLORKEY | pg.RLEACCEL) + else: + sprite_surface.set_colorkey([0xFF, 0xFF, 0xFF], pg.SRCCOLORKEY) + sprite_surface2.set_colorkey([0xFF, 0xFF, 0xFF], pg.SRCCOLORKEY) + + if use_alpha: + sprite_surface = sprite_surface.convert_alpha() + sprite_surface2 = sprite_surface2.convert_alpha() + else: + sprite_surface = sprite_surface.convert() + sprite_surface2 = sprite_surface2.convert() + + Thingy.images = [sprite_surface] + if use_static: + Static.images = [sprite_surface2] + + if len(sys.argv) > 1: + try: + numsprites = int(sys.argv[-1]) + except Exception: + numsprites = 100 + else: + numsprites = 100 + sprites = None + if use_layered_dirty: + ## sprites = pg.sprite.FastRenderGroup() + sprites = pg.sprite.LayeredDirty() + else: + if update_rects: + sprites = pg.sprite.RenderUpdates() + else: + sprites = pg.sprite.Group() + + for i in range(0, numsprites): + if use_static and i % 2 == 0: + sprites.add(Static()) + sprites.add(Thingy()) + + frames = 0 + start = time() + + background = pg.Surface(screen.get_size()) + background = background.convert() + background.fill([0, 0, 0]) + + going = True + while going: + if not update_rects: + screen.fill([0, 0, 0]) + + ## for sprite in sprites: + ## sprite.move() + + if update_rects: + sprites.clear(screen, background) + sprites.update() + + rects = sprites.draw(screen) + if update_rects: + pg.display.update(rects) + else: + pg.display.flip() + + for event in pg.event.get(): + if event.type in [pg.QUIT, pg.KEYDOWN, pg.QUIT, pg.JOYBUTTONDOWN]: + going = False + + frames += 1 + end = time() + print("FPS: %f" % (frames / ((end - start)))) + pg.quit() + + +if __name__ == "__main__": + main(update_rects, use_static, use_layered_dirty, screen_dims, use_alpha, flags) diff --git a/venv/Lib/site-packages/pygame/examples/textinput.py b/venv/Lib/site-packages/pygame/examples/textinput.py new file mode 100644 index 0000000..4e241d1 --- /dev/null +++ b/venv/Lib/site-packages/pygame/examples/textinput.py @@ -0,0 +1,174 @@ +#!/usr/bin/env python +""" pg.examples.textinput + +A little "console" where you can write in text. + +Shows how to use the TEXTEDITING and TEXTINPUT events. +""" +import sys +import pygame as pg +import pygame.freetype as freetype + +# Version check +if pg.get_sdl_version() < (2, 0, 0): + raise Exception("This example requires pygame 2.") + +###CONSTS +# Set to true or add 'showevent' in argv to see IME and KEYDOWN events +PRINT_EVENT = False +# frames per second, the general speed of the program +FPS = 50 +# size of window +WINDOWWIDTH, WINDOWHEIGHT = 640, 480 +BGCOLOR = (0, 0, 0) + +# position of chatlist and chatbox +CHATLIST_POS = pg.Rect(0, 20, WINDOWWIDTH, 400) +CHATBOX_POS = pg.Rect(0, 440, WINDOWWIDTH, 40) +CHATLIST_MAXSIZE = 20 + +TEXTCOLOR = (0, 255, 0) + +# Add fontname for each language, otherwise some text can't be correctly displayed. +FONTNAMES = [ + "notosanscjktcregular", + "notosansmonocjktcregular", + "notosansregular,", + "microsoftjhengheimicrosoftjhengheiuilight", + "microsoftyaheimicrosoftyaheiuilight", + "msgothicmsuigothicmspgothic", + "msmincho", + "Arial", +] + +# Initalize +pg.init() +Screen = pg.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT)) +pg.display.set_caption("TextInput example") +FPSClock = pg.time.Clock() + +# Freetype +# "The font name can be a comma separated list of font names to search for." +FONTNAMES = ",".join(str(x) for x in FONTNAMES) +Font = freetype.SysFont(FONTNAMES, 24) +FontSmall = freetype.SysFont(FONTNAMES, 16) +print("Using font: " + Font.name) + +# Main loop process +def main(): + global BGCOLOR, PRINT_EVENT, CHATBOX_POS, CHATLIST_POS, CHATLIST_MAXSIZE + global FPSClock, Font, Screen + + """ + https://wiki.libsdl.org/SDL_HINT_IME_INTERNAL_EDITING + https://wiki.libsdl.org/Tutorials/TextInput + Candidate list not showing due to SDL2 problem ;w; + """ + pg.key.start_text_input() + input_rect = pg.Rect(80, 80, 320, 40) + pg.key.set_text_input_rect(input_rect) + + _IMEEditing = False + _IMEText = "" + _IMETextPos = 0 + _IMEEditingText = "" + _IMEEditingPos = 0 + ChatList = [] + + while True: + for event in pg.event.get(): + if event.type == pg.QUIT: + pg.quit() + return + + elif event.type == pg.KEYDOWN: + if PRINT_EVENT: + print(event) + + if _IMEEditing: + if len(_IMEEditingText) == 0: + _IMEEditing = False + continue + + if event.key == pg.K_BACKSPACE: + if len(_IMEText) > 0 and _IMETextPos > 0: + _IMEText = ( + _IMEText[0 : _IMETextPos - 1] + _IMEText[_IMETextPos:] + ) + _IMETextPos = max(0, _IMETextPos - 1) + + elif event.key == pg.K_DELETE: + _IMEText = _IMEText[0:_IMETextPos] + _IMEText[_IMETextPos + 1 :] + elif event.key == pg.K_LEFT: + _IMETextPos = max(0, _IMETextPos - 1) + elif event.key == pg.K_RIGHT: + _IMETextPos = min(len(_IMEText), _IMETextPos + 1) + # Handle ENTER key + elif event.key in [pg.K_RETURN, pg.K_KP_ENTER]: + # Block if we have no text to append + if len(_IMEText) == 0: + continue + + # Append chat list + ChatList.append(_IMEText) + if len(ChatList) > CHATLIST_MAXSIZE: + ChatList.pop(0) + _IMEText = "" + _IMETextPos = 0 + + elif event.type == pg.TEXTEDITING: + if PRINT_EVENT: + print(event) + _IMEEditing = True + _IMEEditingText = event.text + _IMEEditingPos = event.start + + elif event.type == pg.TEXTINPUT: + if PRINT_EVENT: + print(event) + _IMEEditing = False + _IMEEditingText = "" + _IMEText = _IMEText[0:_IMETextPos] + event.text + _IMEText[_IMETextPos:] + _IMETextPos += len(event.text) + + # Screen updates + Screen.fill(BGCOLOR) + + # Chat List updates + chat_height = CHATLIST_POS.height / CHATLIST_MAXSIZE + for i, chat in enumerate(ChatList): + FontSmall.render_to( + Screen, + (CHATLIST_POS.x, CHATLIST_POS.y + i * chat_height), + chat, + TEXTCOLOR, + ) + + # Chat box updates + start_pos = CHATBOX_POS.copy() + ime_textL = ">" + _IMEText[0:_IMETextPos] + ime_textM = ( + _IMEEditingText[0:_IMEEditingPos] + "|" + _IMEEditingText[_IMEEditingPos:] + ) + ime_textR = _IMEText[_IMETextPos:] + + rect_textL = Font.render_to(Screen, start_pos, ime_textL, TEXTCOLOR) + start_pos.x += rect_textL.width + + # Editing texts should be underlined + rect_textM = Font.render_to( + Screen, start_pos, ime_textM, TEXTCOLOR, None, freetype.STYLE_UNDERLINE + ) + start_pos.x += rect_textM.width + Font.render_to(Screen, start_pos, ime_textR, TEXTCOLOR) + + pg.display.update() + + FPSClock.tick(FPS) + + +if __name__ == "__main__": + if "showevent" in sys.argv: + PRINT_EVENT = True + + main() diff --git a/venv/Lib/site-packages/pygame/examples/vgrade.py b/venv/Lib/site-packages/pygame/examples/vgrade.py new file mode 100644 index 0000000..9618c45 --- /dev/null +++ b/venv/Lib/site-packages/pygame/examples/vgrade.py @@ -0,0 +1,102 @@ +#!/usr/bin/env python +""" pg.examples.vgrade + +This example demonstrates creating an image with numpy +python, and displaying that through SDL. You can look at the +method of importing numpy and pg.surfarray. This method +will fail 'gracefully' if it is not available. +I've tried mixing in a lot of comments where the code might +not be self explanatory, nonetheless it may still seem a bit +strange. Learning to use numpy for images like this takes a +bit of learning, but the payoff is extremely fast image +manipulation in python. + +For Pygame 1.9.2 and up, this example also showcases a new feature +of surfarray.blit_surface: array broadcasting. If a source array +has either a width or height of 1, the array is repeatedly blitted +to the surface along that dimension to fill the surface. In fact, +a (1, 1) or (1, 1, 3) array results in a simple surface color fill. + +Just so you know how this breaks down. For each sampling of +time, 30% goes to each creating the gradient and blitting the +array. The final 40% goes to flipping/updating the display surface + +The window will have no border decorations. + +The code also demonstrates use of the timer events. +""" + + +import os +import pygame as pg + +try: + import numpy as np + import numpy.random as np_random +except ImportError: + raise SystemExit("This example requires numpy and the pygame surfarray module") + +timer = 0 + + +def stopwatch(message=None): + "simple routine to time python code" + global timer + if not message: + timer = pg.time.get_ticks() + return + now = pg.time.get_ticks() + runtime = (now - timer) / 1000.0 + 0.001 + print("%s %s %s" % (message, runtime, ("seconds\t(%.2ffps)" % (1.0 / runtime)))) + timer = now + + +def VertGradientColumn(surf, topcolor, bottomcolor): + "creates a new 3d vertical gradient array" + topcolor = np.array(topcolor, copy=False) + bottomcolor = np.array(bottomcolor, copy=False) + diff = bottomcolor - topcolor + width, height = surf.get_size() + # create array from 0.0 to 1.0 triplets + column = np.arange(height, dtype="float") / height + column = np.repeat(column[:, np.newaxis], [3], 1) + # create a single column of gradient + column = topcolor + (diff * column).astype("int") + # make the column a 3d image column by adding X + column = column.astype("uint8")[np.newaxis, :, :] + # 3d array into 2d array + return pg.surfarray.map_array(surf, column) + + +def DisplayGradient(surf): + "choose random colors and show them" + stopwatch() + colors = np_random.randint(0, 255, (2, 3)) + column = VertGradientColumn(surf, colors[0], colors[1]) + pg.surfarray.blit_array(surf, column) + pg.display.flip() + stopwatch("Gradient:") + + +def main(): + pg.init() + pg.mixer.quit() # remove ALSA underflow messages for Debian squeeze + size = 600, 400 + os.environ["SDL_VIDEO_CENTERED"] = "1" + screen = pg.display.set_mode(size, pg.NOFRAME, 0) + + pg.event.set_blocked(pg.MOUSEMOTION) # keep our queue cleaner + pg.time.set_timer(pg.USEREVENT, 500) + + while 1: + event = pg.event.wait() + if event.type in (pg.QUIT, pg.KEYDOWN, pg.MOUSEBUTTONDOWN): + break + elif event.type == pg.USEREVENT: + DisplayGradient(screen) + + pg.quit() + + +if __name__ == "__main__": + main() diff --git a/venv/Lib/site-packages/pygame/examples/video.py b/venv/Lib/site-packages/pygame/examples/video.py new file mode 100644 index 0000000..3d4b9f1 --- /dev/null +++ b/venv/Lib/site-packages/pygame/examples/video.py @@ -0,0 +1,162 @@ +#!/usr/bin/env python +""" pg.examples.video + +Experimental! + +* dialog message boxes with messagebox. +* multiple windows with Window +* driver selection +* Renderer, Texture, and Image classes +* Drawing lines, rects, and such onto Renderers. +""" +import os +import pygame as pg + +if pg.get_sdl_version()[0] < 2: + raise SystemExit( + "This example requires pygame 2 and SDL2. _sdl2 is experimental and will change." + ) +from pygame._sdl2 import Window, Texture, Image, Renderer, get_drivers, messagebox + +data_dir = os.path.join(os.path.split(os.path.abspath(__file__))[0], "data") + + +def load_img(file): + return pg.image.load(os.path.join(data_dir, file)) + + +pg.display.init() +pg.key.set_repeat(1000, 10) + +for driver in get_drivers(): + print(driver) + +import random + +answer = messagebox( + "I will open two windows! Continue?", + "Hello!", + info=True, + buttons=("Yes", "No", "Chance"), + return_button=0, + escape_button=1, +) +if answer == 1 or (answer == 2 and random.random() < 0.5): + import sys + + sys.exit(0) + +win = Window("asdf", resizable=True) +renderer = Renderer(win) +tex = Texture.from_surface(renderer, load_img("alien1.gif")) + +running = True + +x, y = 250, 50 +clock = pg.time.Clock() + +backgrounds = [(255, 0, 0, 255), (0, 255, 0, 255), (0, 0, 255, 255)] +bg_index = 0 + +renderer.draw_color = backgrounds[bg_index] + +win2 = Window("2nd window", size=(256, 256), always_on_top=True) +win2.opacity = 0.5 +win2.set_icon(load_img("bomb.gif")) +renderer2 = Renderer(win2) +tex2 = Texture.from_surface(renderer2, load_img("asprite.bmp")) +renderer2.clear() +tex2.draw() +renderer2.present() +del tex2 + +full = 0 + +tex = Image(tex) + + +surf = pg.Surface((64, 64)) +streamtex = Texture(renderer, (64, 64), streaming=True) +tex_update_interval = 1000 +next_tex_update = pg.time.get_ticks() + + +while running: + for event in pg.event.get(): + if event.type == pg.QUIT: + running = False + elif getattr(event, "window", None) == win2: + if ( + event.type == pg.KEYDOWN + and event.key == pg.K_ESCAPE + or event.type == pg.WINDOWCLOSE + ): + win2.destroy() + elif event.type == pg.KEYDOWN: + if event.key == pg.K_ESCAPE: + running = False + elif event.key == pg.K_LEFT: + x -= 5 + elif event.key == pg.K_RIGHT: + x += 5 + elif event.key == pg.K_DOWN: + y += 5 + elif event.key == pg.K_UP: + y -= 5 + elif event.key == pg.K_f: + if full == 0: + win.set_fullscreen(True) + full = 1 + else: + win.set_windowed() + full = 0 + elif event.key == pg.K_s: + readsurf = renderer.to_surface() + pg.image.save(readsurf, "test.png") + + elif event.key == pg.K_SPACE: + bg_index = (bg_index + 1) % len(backgrounds) + renderer.draw_color = backgrounds[bg_index] + + renderer.clear() + + # update texture + curtime = pg.time.get_ticks() + if curtime >= next_tex_update: + for x_ in range(streamtex.width // 4): + for y_ in range(streamtex.height // 4): + newcol = ( + random.randint(0, 255), + random.randint(0, 255), + random.randint(0, 255), + 255, + ) + area = (4 * x_, 4 * y_, 4, 4) + surf.fill(newcol, area) + streamtex.update(surf) + next_tex_update = curtime + tex_update_interval + streamtex.draw(dstrect=pg.Rect(64, 128, 64, 64)) + + tex.draw(dstrect=(x, y)) + + # TODO: should these be? + # - line instead of draw_line + # - point instead of draw_point + # - rect(rect, width=1)->draw 1 pixel, instead of draw_rect + # - rect(rect, width=0)->filled ? , instead of fill_rect + # + # TODO: should these work with pg.draw.line(renderer, ...) functions? + renderer.draw_color = (255, 255, 255, 255) + renderer.draw_line((0, 0), (64, 64)) + renderer.draw_line((64, 64), (128, 0)) + renderer.draw_point((72, 32)) + renderer.draw_rect(pg.Rect(0, 64, 64, 64)) + renderer.fill_rect(pg.Rect(0, 128, 64, 64)) + renderer.draw_color = backgrounds[bg_index] + + renderer.present() + + clock.tick(60) + win.title = str("FPS: {}".format(clock.get_fps())) + +pg.quit() diff --git a/venv/Lib/site-packages/pygame/fastevent.py b/venv/Lib/site-packages/pygame/fastevent.py new file mode 100644 index 0000000..e102fc4 --- /dev/null +++ b/venv/Lib/site-packages/pygame/fastevent.py @@ -0,0 +1,88 @@ +""" +A compatibility shim for pygame.fastevent based on pygame.event. +This module was deprecated in pygame 2.2, and is scheduled for removal in a +future pygame version. If you are using pygame.fastevent, please migrate to +using regular pygame.event module +""" + +import pygame.event +import pygame.display +from pygame import error, register_quit +from pygame.event import Event + +_ft_init = False + + +def _ft_init_check(): + """ + Raises error if module is not init + """ + if not _ft_init: + raise error("fastevent system not initialized") + + +def _quit_hook(): + """ + Hook that gets run to quit module + """ + global _ft_init + _ft_init = False + + +def init(): + """init() -> None + initialize pygame.fastevent + """ + global _ft_init + if not pygame.display.get_init(): + raise error("video system not initialized") + + register_quit(_quit_hook) + _ft_init = True + + +def get_init(): + """get_init() -> bool + returns True if the fastevent module is currently initialized + """ + return _ft_init + + +def pump(): + """pump() -> None + internally process pygame event handlers + """ + _ft_init_check() + pygame.event.pump() + + +def wait(): + """wait() -> Event + wait for an event + """ + _ft_init_check() + return pygame.event.wait() + + +def poll(): + """poll() -> Event + get an available event + """ + _ft_init_check() + return pygame.event.poll() + + +def get(): + """get() -> list of Events + get all events from the queue + """ + _ft_init_check() + return pygame.event.get() + + +def post(event: Event): + """post(Event) -> None + place an event on the queue + """ + _ft_init_check() + pygame.event.post(event) diff --git a/venv/Lib/site-packages/pygame/fastevent.pyi b/venv/Lib/site-packages/pygame/fastevent.pyi new file mode 100644 index 0000000..9ef2e26 --- /dev/null +++ b/venv/Lib/site-packages/pygame/fastevent.pyi @@ -0,0 +1,11 @@ +from typing import List + +from pygame.event import Event + +def init() -> None: ... +def get_init() -> bool: ... +def pump() -> None: ... +def wait() -> Event: ... +def pool() -> Event: ... +def get() -> List[Event]: ... +def post(event: Event) -> None: ... diff --git a/venv/Lib/site-packages/pygame/font.cp39-win_amd64.pyd b/venv/Lib/site-packages/pygame/font.cp39-win_amd64.pyd new file mode 100644 index 0000000000000000000000000000000000000000..0a900ac2505abd67335834ce3f4ba229e4d47e03 GIT binary patch literal 24064 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 h?>*dmtT)+vs`p%P_7k~JhFL literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/font.pyi b/venv/Lib/site-packages/pygame/font.pyi new file mode 100644 index 0000000..9002ed7 --- /dev/null +++ b/venv/Lib/site-packages/pygame/font.pyi @@ -0,0 +1,50 @@ +from typing import Hashable, Iterable, List, Optional, Tuple, Union + +from pygame.surface import Surface + +from ._common import _ColorValue, _FileArg + +def init() -> None: ... +def quit() -> None: ... +def get_init() -> bool: ... +def get_default_font() -> str: ... +def get_fonts() -> List[str]: ... +def match_font( + name: Union[str, bytes, Iterable[Union[str, bytes]]], + bold: Hashable = False, + italic: Hashable = False, +) -> str: ... +def SysFont( + name: Union[str, bytes, Iterable[Union[str, bytes]]], + size: int, + bold: Hashable = False, + italic: Hashable = False, +) -> Font: ... + +class Font(object): + + bold: bool + italic: bool + underline: bool + def __init__(self, name: Optional[_FileArg], size: int) -> None: ... + def render( + self, + text: Union[str, bytes], + antialias: bool, + color: _ColorValue, + background: Optional[_ColorValue] = None, + ) -> Surface: ... + def size(self, text: Union[str, bytes]) -> Tuple[int, int]: ... + def set_underline(self, value: bool) -> None: ... + def get_underline(self) -> bool: ... + def set_bold(self, value: bool) -> None: ... + def get_bold(self) -> bool: ... + def set_italic(self, value: bool) -> None: ... + def metrics( + self, text: Union[str, bytes] + ) -> List[Tuple[int, int, int, int, int]]: ... + def get_italic(self) -> bool: ... + def get_linesize(self) -> int: ... + def get_height(self) -> int: ... + def get_ascent(self) -> int: ... + def get_descent(self) -> int: ... diff --git a/venv/Lib/site-packages/pygame/freesansbold.ttf b/venv/Lib/site-packages/pygame/freesansbold.ttf new file mode 100644 index 0000000000000000000000000000000000000000..a98562fc1a89075f2218a2dbf2c08785237fab90 GIT binary patch literal 98600 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 XOU_vD*hn~W&Qgn)LaEoq#MA!+z}l?@ literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/freetype.py b/venv/Lib/site-packages/pygame/freetype.py new file mode 100644 index 0000000..c1b5f59 --- /dev/null +++ b/venv/Lib/site-packages/pygame/freetype.py @@ -0,0 +1,78 @@ +"""Enhanced Pygame module for loading and rendering computer fonts""" + +from pygame._freetype import ( + Font, + STYLE_NORMAL, + STYLE_OBLIQUE, + STYLE_STRONG, + STYLE_UNDERLINE, + STYLE_WIDE, + STYLE_DEFAULT, + init, + quit, + get_init, + was_init, + get_cache_size, + get_default_font, + get_default_resolution, + get_error, + get_version, + set_default_resolution, +) +from pygame.sysfont import match_font, get_fonts, SysFont as _SysFont + +__all__ = [ + "Font", + "STYLE_NORMAL", + "STYLE_OBLIQUE", + "STYLE_STRONG", + "STYLE_UNDERLINE", + "STYLE_WIDE", + "STYLE_DEFAULT", + "init", + "quit", + "get_init", + "was_init", + "get_cache_size", + "get_default_font", + "get_default_resolution", + "get_error", + "get_version", + "set_default_resolution", + "match_font", + "get_fonts", +] + + +def SysFont(name, size, bold=0, italic=0, constructor=None): + """pygame.ftfont.SysFont(name, size, bold=False, italic=False, constructor=None) -> Font + Create a pygame Font from system font resources. + + This will search the system fonts for the given font + name. You can also enable bold or italic styles, and + the appropriate system font will be selected if available. + + This will always return a valid Font object, and will + fallback on the builtin pygame font if the given font + is not found. + + Name can also be an iterable of font names, a string of + comma-separated font names, or a bytes of comma-separated + font names, in which case the set of names will be searched + in order. Pygame uses a small set of common font aliases. If the + specific font you ask for is not available, a reasonable + alternative may be used. + + If optional constructor is provided, it must be a function with + signature constructor(fontpath, size, bold, italic) which returns + a Font instance. If None, a pygame.freetype.Font object is created. + """ + if constructor is None: + + def constructor(fontpath, size, bold, italic): + font = Font(fontpath, size) + font.strong = bold + font.oblique = italic + return font + + return _SysFont(name, size, bold, italic, constructor) diff --git a/venv/Lib/site-packages/pygame/freetype.pyi b/venv/Lib/site-packages/pygame/freetype.pyi new file mode 100644 index 0000000..dd77f55 --- /dev/null +++ b/venv/Lib/site-packages/pygame/freetype.pyi @@ -0,0 +1,122 @@ +from typing import Any, Iterable, List, Optional, Text, Tuple, Union + +from pygame.color import Color +from pygame.font import Font +from pygame.rect import Rect +from pygame.surface import Surface + +from ._common import _ColorValue, _FileArg, _CanBeRect + +def get_error() -> str: ... +def get_version() -> Tuple[int, int, int]: ... +def init(cache_size: int = 64, resolution: int = 72) -> None: ... +def quit() -> None: ... +def get_init() -> bool: ... +def was_init() -> bool: ... +def get_cache_size() -> int: ... +def get_default_resolution() -> int: ... +def set_default_resolution(resolution: int) -> None: ... +def SysFont( + name: Union[str, bytes, Iterable[Union[str, bytes]]], + size: int, + bold: int = False, + italic: int = False, +) -> Font: ... +def get_default_font() -> str: ... + +STYLE_NORMAL: int +STYLE_UNDERLINE: int +STYLE_OBLIQUE: int +STYLE_STRONG: int +STYLE_WIDE: int +STYLE_DEFAULT: int + +class Font: + name: str + path: Text + size: Union[float, Tuple[float, float]] + height: int + ascender: int + descender: int + style: int + underline: bool + strong: bool + oblique: bool + wide: bool + strength: float + underline_adjustment: float + fixed_width: bool + fixed_sizes: int + scalable: bool + use_bitmap_strikes: bool + antialiased: bool + kerning: bool + vertical: bool + rotation: int + fgcolor: Color + bgcolor: Color + origin: bool + pad: bool + ucs4: bool + resolution: int + def __init__( + self, + file: Optional[_FileArg], + size: float = 0, + font_index: int = 0, + resolution: int = 0, + ucs4: int = False, + ) -> None: ... + def get_rect( + self, + text: str, + style: int = STYLE_DEFAULT, + rotation: int = 0, + size: float = 0, + ) -> Rect: ... + def get_metrics( + self, text: str, size: float = 0 + ) -> List[Tuple[int, int, int, int, float, float]]: ... + def get_sized_ascender(self, size: float) -> int: ... + def get_sized_descender(self, size: float) -> int: ... + def get_sized_height(self, size: float) -> int: ... + def get_sized_glyph_height(self, size: float) -> int: ... + def get_sizes(self) -> List[Tuple[int, int, int, float, float]]: ... + def render( + self, + text: str, + fgcolor: Optional[_ColorValue] = None, + bgcolor: Optional[_ColorValue] = None, + style: int = STYLE_DEFAULT, + rotation: int = 0, + size: float = 0, + ) -> Tuple[Surface, Rect]: ... + def render_to( + self, + surf: Surface, + dest: _CanBeRect, + text: str, + fgcolor: Optional[_ColorValue] = None, + bgcolor: Optional[_ColorValue] = None, + style: int = STYLE_DEFAULT, + rotation: int = 0, + size: float = 0, + ) -> Rect: ... + def render_raw( + self, + text: str, + style: int = STYLE_DEFAULT, + rotation: int = 0, + size: float = 0, + invert: bool = False, + ) -> Tuple[bytes, Tuple[int, int]]: ... + def render_raw_to( + self, + array: Any, + text: str, + dest: Optional[_CanBeRect] = None, + style: int = STYLE_DEFAULT, + rotation: int = 0, + size: float = 0, + invert: bool = False, + ) -> Rect: ... diff --git a/venv/Lib/site-packages/pygame/ftfont.py b/venv/Lib/site-packages/pygame/ftfont.py new file mode 100644 index 0000000..e648ede --- /dev/null +++ b/venv/Lib/site-packages/pygame/ftfont.py @@ -0,0 +1,203 @@ +"""pygame module for loading and rendering fonts (freetype alternative)""" + +__all__ = [ + "Font", + "init", + "quit", + "get_default_font", + "get_init", + "SysFont", + "match_font", + "get_fonts", +] + +from pygame._freetype import init, Font as _Font, get_default_resolution +from pygame._freetype import quit, get_default_font, get_init as _get_init +from pygame._freetype import __PYGAMEinit__ +from pygame.sysfont import match_font, get_fonts, SysFont as _SysFont +from pygame import encode_file_path + + +class Font(_Font): + """Font(filename, size) -> Font + Font(object, size) -> Font + create a new Font object from a file (freetype alternative) + + This Font type differs from font.Font in that it can render glyphs + for Unicode code points in the supplementary planes (> 0xFFFF). + """ + + __encode_file_path = staticmethod(encode_file_path) + __get_default_resolution = staticmethod(get_default_resolution) + __default_font = encode_file_path(get_default_font()) + + __unull = "\x00" + __bnull = b"\x00" + + def __init__(self, file, size=-1): + size = max(size, 1) + if isinstance(file, str): + try: + bfile = self.__encode_file_path(file, ValueError) + except ValueError: + bfile = "" + else: + bfile = file + if isinstance(bfile, bytes) and bfile == self.__default_font: + file = None + if file is None: + resolution = int(self.__get_default_resolution() * 0.6875) + if resolution == 0: + resolution = 1 + else: + resolution = 0 + super(Font, self).__init__(file, size=size, resolution=resolution) + self.strength = 1.0 / 12.0 + self.kerning = False + self.origin = True + self.pad = True + self.ucs4 = True + self.underline_adjustment = 1.0 + + def render(self, text, antialias, color, background=None): + """render(text, antialias, color, background=None) -> Surface + draw text on a new Surface""" + + if text is None: + text = "" + if isinstance(text, str) and self.__unull in text: + raise ValueError("A null character was found in the text") + if isinstance(text, bytes) and self.__bnull in text: + raise ValueError("A null character was found in the text") + save_antialiased = ( + self.antialiased # pylint: disable = access-member-before-definition + ) + self.antialiased = bool(antialias) + try: + s, _ = super(Font, self).render(text, color, background) + return s + finally: + self.antialiased = save_antialiased + + def set_bold(self, value): + """set_bold(bool) -> None + enable fake rendering of bold text""" + + self.wide = bool(value) + + def get_bold(self): + """get_bold() -> bool + check if text will be rendered bold""" + + return self.wide + + bold = property(get_bold, set_bold) + + def set_italic(self, value): + """set_italic(bool) -> None + enable fake rendering of italic text""" + + self.oblique = bool(value) + + def get_italic(self): + """get_italic() -> bool + check if the text will be rendered italic""" + + return self.oblique + + italic = property(get_italic, set_italic) + + def set_underline(self, value): + """set_underline(bool) -> None + control if text is rendered with an underline""" + + self.underline = bool(value) + + def get_underline(self): + """set_bold(bool) -> None + enable fake rendering of bold text""" + + return self.underline + + def metrics(self, text): + """metrics(text) -> list + Gets the metrics for each character in the passed string.""" + + return self.get_metrics(text) + + def get_ascent(self): + """get_ascent() -> int + get the ascent of the font""" + + return self.get_sized_ascender() + + def get_descent(self): + """get_descent() -> int + get the descent of the font""" + + return self.get_sized_descender() + + def get_height(self): + """get_height() -> int + get the height of the font""" + + return self.get_sized_ascender() - self.get_sized_descender() + 1 + + def get_linesize(self): + """get_linesize() -> int + get the line space of the font text""" + + return self.get_sized_height() + + def size(self, text): + """size(text) -> (width, height) + determine the amount of space needed to render text""" + + return self.get_rect(text).size + + +FontType = Font + + +def get_init(): + """get_init() -> bool + true if the font module is initialized""" + + return _get_init() + + +def SysFont(name, size, bold=0, italic=0, constructor=None): + """pygame.ftfont.SysFont(name, size, bold=False, italic=False, constructor=None) -> Font + Create a pygame Font from system font resources. + + This will search the system fonts for the given font + name. You can also enable bold or italic styles, and + the appropriate system font will be selected if available. + + This will always return a valid Font object, and will + fallback on the builtin pygame font if the given font + is not found. + + Name can also be an iterable of font names, a string of + comma-separated font names, or a bytes of comma-separated + font names, in which case the set of names will be searched + in order. Pygame uses a small set of common font aliases. If the + specific font you ask for is not available, a reasonable + alternative may be used. + + If optional constructor is provided, it must be a function with + signature constructor(fontpath, size, bold, italic) which returns + a Font instance. If None, a pygame.ftfont.Font object is created. + """ + if constructor is None: + + def constructor(fontpath, size, bold, italic): + font = Font(fontpath, size) + font.set_bold(bold) + font.set_italic(italic) + return font + + return _SysFont(name, size, bold, italic, constructor) + + +del _Font, get_default_resolution, encode_file_path diff --git a/venv/Lib/site-packages/pygame/gfxdraw.cp39-win_amd64.pyd b/venv/Lib/site-packages/pygame/gfxdraw.cp39-win_amd64.pyd new file mode 100644 index 0000000000000000000000000000000000000000..cd47f433b46871c58cf11b9a14a8ea0e8bccdd34 GIT binary patch literal 57856 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 osgtSGsZ44n None: ... +def hline(surface: Surface, x1: int, x2: int, y: int, color: _ColorValue) -> None: ... +def vline(surface: Surface, x: int, y1: int, y2: int, color: _ColorValue) -> None: ... +def line( + surface: Surface, x1: int, y1: int, x2: int, y2: int, color: _ColorValue +) -> None: ... +def rectangle(surface: Surface, rect: _RectValue, color: _ColorValue) -> None: ... +def box(surface: Surface, rect: _RectValue, color: _ColorValue) -> None: ... +def circle(surface: Surface, x: int, y: int, r: int, color: _ColorValue) -> None: ... +def aacircle(surface: Surface, x: int, y: int, r: int, color: _ColorValue) -> None: ... +def filled_circle( + surface: Surface, x: int, y: int, r: int, color: _ColorValue +) -> None: ... +def ellipse( + surface: Surface, x: int, y: int, rx: int, ry: int, color: _ColorValue +) -> None: ... +def aaellipse( + surface: Surface, x: int, y: int, rx: int, ry: int, color: _ColorValue +) -> None: ... +def filled_ellipse( + surface: Surface, x: int, y: int, rx: int, ry: int, color: _ColorValue +) -> None: ... +def arc( + surface: Surface, + x: int, + y: int, + r: int, + start_angle: int, + atp_angle: int, + color: _ColorValue, +) -> None: ... +def pie( + surface: Surface, + x: int, + y: int, + r: int, + start_angle: int, + atp_angle: int, + color: _ColorValue, +) -> None: ... +def trigon( + surface: Surface, + x1: int, + y1: int, + x2: int, + y2: int, + x3: int, + y3: int, + color: _ColorValue, +) -> None: ... +def aatrigon( + surface: Surface, + x1: int, + y1: int, + x2: int, + y2: int, + x3: int, + y3: int, + color: _ColorValue, +) -> None: ... +def filled_trigon( + surface: Surface, + x1: int, + y1: int, + x2: int, + y2: int, + x3: int, + y3: int, + color: _ColorValue, +) -> None: ... +def polygon( + surface: Surface, points: Sequence[_Coordinate], color: _ColorValue +) -> None: ... +def aapolygon( + surface: Surface, points: Sequence[_Coordinate], color: _ColorValue +) -> None: ... +def filled_polygon( + surface: Surface, points: Sequence[_Coordinate], color: _ColorValue +) -> None: ... +def textured_polygon( + surface: Surface, points: Sequence[_Coordinate], texture: Surface, tx: int, ty: int +) -> None: ... +def bezier( + surface: Surface, points: Sequence[_Coordinate], steps: int, color: _ColorValue +) -> None: ... diff --git a/venv/Lib/site-packages/pygame/image.cp39-win_amd64.pyd b/venv/Lib/site-packages/pygame/image.cp39-win_amd64.pyd new file mode 100644 index 0000000000000000000000000000000000000000..c08a92a1d80b3001870053a6e2c7b65402339d42 GIT binary patch literal 28160 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 LtEKzje(?VZT? Surface: ... +def save(surface: Surface, filename: _FileArg, namehint: str = "") -> None: ... +def get_sdl_image_version() -> Union[None, Tuple[int, int, int]]: ... +def get_extended() -> bool: ... +def tostring( + surface: Surface, format: _to_string_format, flipped: bool = False +) -> str: ... +def fromstring( + string: str, + size: Union[List[int], Tuple[int, int]], + format: _from_string_format, + flipped: bool = False, +) -> Surface: ... +def frombuffer( + bytes: _BufferStyle, + size: Union[List[int], Tuple[int, int]], + format: _from_buffer_format, +) -> Surface: ... +def load_basic(filename: _FileArg) -> Surface: ... +def load_extended(filename: _FileArg, namehint: str = "") -> Surface: ... +def save_extended(surface: Surface, filename: _FileArg, namehint: str = "") -> None: ... diff --git a/venv/Lib/site-packages/pygame/imageext.cp39-win_amd64.pyd b/venv/Lib/site-packages/pygame/imageext.cp39-win_amd64.pyd new file mode 100644 index 0000000000000000000000000000000000000000..0c32289be445ff33f83d656faf4eaebcf61eceee GIT binary patch literal 19456 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/joystick.cp39-win_amd64.pyd b/venv/Lib/site-packages/pygame/joystick.cp39-win_amd64.pyd new file mode 100644 index 0000000000000000000000000000000000000000..1b10aa608e6a80682c74a3d287917cfbf836cf27 GIT binary patch literal 20480 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 F_&1Gq69E7K literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pygame/joystick.pyi b/venv/Lib/site-packages/pygame/joystick.pyi new file mode 100644 index 0000000..9ca8532 --- /dev/null +++ b/venv/Lib/site-packages/pygame/joystick.pyi @@ -0,0 +1,29 @@ +from typing import Tuple + +def init() -> None: ... +def quit() -> None: ... +def get_init() -> bool: ... +def get_count() -> int: ... + +class Joystick(object): + def __init__(self, id: int) -> None: ... + def init(self) -> None: ... + def quit(self) -> None: ... + def get_init(self) -> bool: ... + def get_id(self) -> int: ... + def get_instance_id(self) -> int: ... + def get_guid(self) -> str: ... + def get_power_level(self) -> str: ... + def get_name(self) -> str: ... + def get_numaxes(self) -> int: ... + def get_axis(self, axis_number: int) -> float: ... + def get_numballs(self) -> int: ... + def get_ball(self, ball_number: int) -> Tuple[float, float]: ... + def get_numbuttons(self) -> int: ... + def get_button(self, button: int) -> bool: ... + def get_numhats(self) -> int: ... + def get_hat(self, hat_number: int) -> Tuple[float, float]: ... + def rumble( + self, low_frequency: float, high_frequency: float, duration: int + ) -> bool: ... + def stop_rumble(self) -> None: ... diff --git a/venv/Lib/site-packages/pygame/key.cp39-win_amd64.pyd b/venv/Lib/site-packages/pygame/key.cp39-win_amd64.pyd new file mode 100644 index 0000000000000000000000000000000000000000..f234e9e551343651087334f20d0a291c6716d836 GIT binary patch literal 26624 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 bool: ... +def get_pressed() -> Sequence[bool]: ... +def get_mods() -> int: ... +def set_mods(mods: int) -> None: ... +def set_repeat(delay: int = 0, interval: int = 0) -> None: ... +def get_repeat() -> Tuple[int, int]: ... +def name(key: int) -> str: ... +def key_code(name: str) -> int: ... +def start_text_input() -> None: ... +def stop_text_input() -> None: ... +def set_text_input_rect(rect: _RectValue) -> None: ... diff --git a/venv/Lib/site-packages/pygame/libFLAC-8.dll b/venv/Lib/site-packages/pygame/libFLAC-8.dll new file mode 100644 index 0000000000000000000000000000000000000000..71f2e19d9cac86400bcfb3bb68a659b9773925ad GIT binary patch literal 441344 zcmdSCdtg-6wLd%u_*Y2`a-D+Rg?+PLKU2u z!0x%nM(eY^w$=8w+Sk?A3!>F#2oN6fNFoB_BRrjx$Qwe!E8ovrd!LyJ5AXMWf4}b^ zUu-Am?7jBdYwx|*+H0@9_CA$&)_8I~9*+IXlH9emDtIzFH(LPWAOV7>8>E&6H=kc^5>q3vGun2z(3Cw>#{ql2;q?=yz zJb0mh_jKpP9?x~>c6mIdoGi=IBO^)wNvFKo&9mYr%I@x&sz4~uGq#)O^hgu%Wob}MQ^8{0f3`^dHYnj;kEsvQ<=U82@Ye$a0^d` z1AUJ_F!j+%9y!(+a~_L#PK6sVg3$cG{BK-1_EqU(;-=KRMR}gENQOmSs;wB0)&<}1 z-OUqDYzd1TyxdGLA}6W^Ys2--$>G@2(g}6%5GTq0yA5rMzM5+l{5&JnvFjkv9{W!PK<#)(c(t{x40L6Qp*P9uq&kb97xAvl{(YLkH9+e{X zE-`CFZ0%eh%X|2VZXQW3`ZUu7tydf{9(0q_yR)-%vilyfE`I~aDy)LC)PQed)X;lk zS#(syy6ROFJl6?3bqFot;Eq;vO2#{_c3DDVPLc_eCsE{T|?nTArOXW1lk!g}8rQkklYWftI)f zc}!+G9*{44WD*cK$I-1wVSXd>_5`S#oR7G-=b}{*>glkGQzgDb+?`?ay!oP%{WUH-A=7-BtE6c(!!ZCYX&*uk)FDzL`*4XeD+2s9+O z<`{vbj_j2YF|n)<^uf!Uz#;*uMXwrs{U2FxT*|OgcHCwOVW*pu*Pqx;UVVefp90vE^Rf zyW&Q>NY_@I;v!Coa7vD@tuRH7E)D`{wC($)VHN7yDnk^y^wRspMJH z%H?voS(p@VSqzw-3aw4!(&A4Oo#LQj-^#U6>kP{SB!=)9_Q)L6K_qfRL8mCt^dPk{H{E@P4vae{ zhIa|89^Knuh?RP5Yc58|5Mv6(m;x}`kO_CyW#k9^CX=*YbI~pj2G}YuFp+HK>tcUk zU!qahp06Ek7YW^4t0$XtQg6JO2NoMwP+v|qi$@O}FvPe5=Vwp>lWWvmHpJ2k3`;Kz z+fi`0SRED{p%S2AuO2jUB!?e829bQm`BqGGH zDnY_ZL*S1pSu!t!%f+6N0T)+jeHyK95p*fV?YA?|MVjLfhmfQyA~^LNJFjAFQeP+vWGWe^AH#7+N+xVq$WC zFk+qiPAN6?9iZ(r0zlIcYxnC`(HmOz9Li`)>Alx4rnL==7gQ^f4ADJSUhJ1b1f;-K zH7pD@w=nX$v;c(G1t4NwETvOhIQ7rD;_7;o2Ff%7C}u^1VEmW){?__4s@r~?>PLOx z^-`<6Bx2<~dO z%={&W_@Y z5`V34K&6}F8&bI(Rm$a)QrTUSNAkez^BbKq)4k(wj$ZGLB zS+(rY;_qRU^w@EzmgnSCP82M0JU4nDetppj{N_dbrBac+nih0dLzF?c6qK=~ z;t%VR8||`}P0NQw%s%*&)=Q>!nXY|kip$)>S&9jSr>p3qnFt%TAYF+Te}M=l6%!_P z2LcpYYOrD7lY{0$>AfmvKhiCr8ffN86-cO{K75L1!Y@^fuZ(+4QjKEWfS8o0q!~DX zo3spR7fjJWS%Cgf#A=C$vowqvCGTp}+hmH(dTe{H&hzSoLShgn#ySS3KO}j8TuDL0 zc+Aj;(}%*M`yuqpze=fLqrv7cl=$n?DhZ!37oGrWRl&fhCI< zTπ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[^-]+) +-(?P\d+[^-]*) +(-(?P\d+[^-]*))? +-(?P\w+\d+(\.\w+\d+)*) +-(?P\w+) +-(?P\w+(\.\w+)*) +\.whl$ +''', re.IGNORECASE | re.VERBOSE) + +NAME_VERSION_RE = re.compile(r''' +(?P[^-]+) +-(?P\d+[^-]*) +(-(?P\d+[^-]*))?$ +''', re.IGNORECASE | re.VERBOSE) + +SHEBANG_RE = re.compile(br'\s*#![^\r\n]*') +SHEBANG_DETAIL_RE = re.compile(br'^(\s*#!("[^"]+"|\S+))\s+(.*)$') +SHEBANG_PYTHON = b'#!python' +SHEBANG_PYTHONW = b'#!pythonw' + +if os.sep == '/': + to_posix = lambda o: o +else: + to_posix = lambda o: o.replace(os.sep, '/') + + +class Mounter(object): + def __init__(self): + self.impure_wheels = {} + self.libs = {} + + def add(self, pathname, extensions): + self.impure_wheels[pathname] = extensions + self.libs.update(extensions) + + def remove(self, pathname): + extensions = self.impure_wheels.pop(pathname) + for k, v in extensions: + if k in self.libs: + del self.libs[k] + + def find_module(self, fullname, path=None): + if fullname in self.libs: + result = self + else: + result = None + return result + + def load_module(self, fullname): + if fullname in sys.modules: + result = sys.modules[fullname] + else: + if fullname not in self.libs: + raise ImportError('unable to find extension for %s' % fullname) + result = imp.load_dynamic(fullname, self.libs[fullname]) + result.__loader__ = self + parts = fullname.rsplit('.', 1) + if len(parts) > 1: + result.__package__ = parts[0] + return result + +_hook = Mounter() + + +class Wheel(object): + """ + Class to build and install from Wheel files (PEP 427). + """ + + wheel_version = (1, 1) + hash_kind = 'sha256' + + def __init__(self, filename=None, sign=False, verify=False): + """ + Initialise an instance using a (valid) filename. + """ + self.sign = sign + self.should_verify = verify + self.buildver = '' + self.pyver = [PYVER] + self.abi = ['none'] + self.arch = ['any'] + self.dirname = os.getcwd() + if filename is None: + self.name = 'dummy' + self.version = '0.1' + self._filename = self.filename + else: + m = NAME_VERSION_RE.match(filename) + if m: + info = m.groupdict('') + self.name = info['nm'] + # Reinstate the local version separator + self.version = info['vn'].replace('_', '-') + self.buildver = info['bn'] + self._filename = self.filename + else: + dirname, filename = os.path.split(filename) + m = FILENAME_RE.match(filename) + if not m: + raise DistlibException('Invalid name or ' + 'filename: %r' % filename) + if dirname: + self.dirname = os.path.abspath(dirname) + self._filename = filename + info = m.groupdict('') + self.name = info['nm'] + self.version = info['vn'] + self.buildver = info['bn'] + self.pyver = info['py'].split('.') + self.abi = info['bi'].split('.') + self.arch = info['ar'].split('.') + + @property + def filename(self): + """ + Build and return a filename from the various components. + """ + if self.buildver: + buildver = '-' + self.buildver + else: + buildver = '' + pyver = '.'.join(self.pyver) + abi = '.'.join(self.abi) + arch = '.'.join(self.arch) + # replace - with _ as a local version separator + version = self.version.replace('-', '_') + return '%s-%s%s-%s-%s-%s.whl' % (self.name, version, buildver, + pyver, abi, arch) + + @property + def exists(self): + path = os.path.join(self.dirname, self.filename) + return os.path.isfile(path) + + @property + def tags(self): + for pyver in self.pyver: + for abi in self.abi: + for arch in self.arch: + yield pyver, abi, arch + + @cached_property + def metadata(self): + pathname = os.path.join(self.dirname, self.filename) + name_ver = '%s-%s' % (self.name, self.version) + info_dir = '%s.dist-info' % name_ver + wrapper = codecs.getreader('utf-8') + with ZipFile(pathname, 'r') as zf: + wheel_metadata = self.get_wheel_metadata(zf) + wv = wheel_metadata['Wheel-Version'].split('.', 1) + file_version = tuple([int(i) for i in wv]) + # if file_version < (1, 1): + # fns = [WHEEL_METADATA_FILENAME, METADATA_FILENAME, + # LEGACY_METADATA_FILENAME] + # else: + # fns = [WHEEL_METADATA_FILENAME, METADATA_FILENAME] + fns = [WHEEL_METADATA_FILENAME, LEGACY_METADATA_FILENAME] + result = None + for fn in fns: + try: + metadata_filename = posixpath.join(info_dir, fn) + with zf.open(metadata_filename) as bf: + wf = wrapper(bf) + result = Metadata(fileobj=wf) + if result: + break + except KeyError: + pass + if not result: + raise ValueError('Invalid wheel, because metadata is ' + 'missing: looked in %s' % ', '.join(fns)) + return result + + def get_wheel_metadata(self, zf): + name_ver = '%s-%s' % (self.name, self.version) + info_dir = '%s.dist-info' % name_ver + metadata_filename = posixpath.join(info_dir, 'WHEEL') + with zf.open(metadata_filename) as bf: + wf = codecs.getreader('utf-8')(bf) + message = message_from_file(wf) + return dict(message) + + @cached_property + def info(self): + pathname = os.path.join(self.dirname, self.filename) + with ZipFile(pathname, 'r') as zf: + result = self.get_wheel_metadata(zf) + return result + + def process_shebang(self, data): + m = SHEBANG_RE.match(data) + if m: + end = m.end() + shebang, data_after_shebang = data[:end], data[end:] + # Preserve any arguments after the interpreter + if b'pythonw' in shebang.lower(): + shebang_python = SHEBANG_PYTHONW + else: + shebang_python = SHEBANG_PYTHON + m = SHEBANG_DETAIL_RE.match(shebang) + if m: + args = b' ' + m.groups()[-1] + else: + args = b'' + shebang = shebang_python + args + data = shebang + data_after_shebang + else: + cr = data.find(b'\r') + lf = data.find(b'\n') + if cr < 0 or cr > lf: + term = b'\n' + else: + if data[cr:cr + 2] == b'\r\n': + term = b'\r\n' + else: + term = b'\r' + data = SHEBANG_PYTHON + term + data + return data + + def get_hash(self, data, hash_kind=None): + if hash_kind is None: + hash_kind = self.hash_kind + try: + hasher = getattr(hashlib, hash_kind) + except AttributeError: + raise DistlibException('Unsupported hash algorithm: %r' % hash_kind) + result = hasher(data).digest() + result = base64.urlsafe_b64encode(result).rstrip(b'=').decode('ascii') + return hash_kind, result + + def write_record(self, records, record_path, base): + records = list(records) # make a copy, as mutated + p = to_posix(os.path.relpath(record_path, base)) + records.append((p, '', '')) + with CSVWriter(record_path) as writer: + for row in records: + writer.writerow(row) + + def write_records(self, info, libdir, archive_paths): + records = [] + distinfo, info_dir = info + hasher = getattr(hashlib, self.hash_kind) + for ap, p in archive_paths: + with open(p, 'rb') as f: + data = f.read() + digest = '%s=%s' % self.get_hash(data) + size = os.path.getsize(p) + records.append((ap, digest, size)) + + p = os.path.join(distinfo, 'RECORD') + self.write_record(records, p, libdir) + ap = to_posix(os.path.join(info_dir, 'RECORD')) + archive_paths.append((ap, p)) + + def build_zip(self, pathname, archive_paths): + with ZipFile(pathname, 'w', zipfile.ZIP_DEFLATED) as zf: + for ap, p in archive_paths: + logger.debug('Wrote %s to %s in wheel', p, ap) + zf.write(p, ap) + + def build(self, paths, tags=None, wheel_version=None): + """ + Build a wheel from files in specified paths, and use any specified tags + when determining the name of the wheel. + """ + if tags is None: + tags = {} + + libkey = list(filter(lambda o: o in paths, ('purelib', 'platlib')))[0] + if libkey == 'platlib': + is_pure = 'false' + default_pyver = [IMPVER] + default_abi = [ABI] + default_arch = [ARCH] + else: + is_pure = 'true' + default_pyver = [PYVER] + default_abi = ['none'] + default_arch = ['any'] + + self.pyver = tags.get('pyver', default_pyver) + self.abi = tags.get('abi', default_abi) + self.arch = tags.get('arch', default_arch) + + libdir = paths[libkey] + + name_ver = '%s-%s' % (self.name, self.version) + data_dir = '%s.data' % name_ver + info_dir = '%s.dist-info' % name_ver + + archive_paths = [] + + # First, stuff which is not in site-packages + for key in ('data', 'headers', 'scripts'): + if key not in paths: + continue + path = paths[key] + if os.path.isdir(path): + for root, dirs, files in os.walk(path): + for fn in files: + p = fsdecode(os.path.join(root, fn)) + rp = os.path.relpath(p, path) + ap = to_posix(os.path.join(data_dir, key, rp)) + archive_paths.append((ap, p)) + if key == 'scripts' and not p.endswith('.exe'): + with open(p, 'rb') as f: + data = f.read() + data = self.process_shebang(data) + with open(p, 'wb') as f: + f.write(data) + + # Now, stuff which is in site-packages, other than the + # distinfo stuff. + path = libdir + distinfo = None + for root, dirs, files in os.walk(path): + if root == path: + # At the top level only, save distinfo for later + # and skip it for now + for i, dn in enumerate(dirs): + dn = fsdecode(dn) + if dn.endswith('.dist-info'): + distinfo = os.path.join(root, dn) + del dirs[i] + break + assert distinfo, '.dist-info directory expected, not found' + + for fn in files: + # comment out next suite to leave .pyc files in + if fsdecode(fn).endswith(('.pyc', '.pyo')): + continue + p = os.path.join(root, fn) + rp = to_posix(os.path.relpath(p, path)) + archive_paths.append((rp, p)) + + # Now distinfo. Assumed to be flat, i.e. os.listdir is enough. + files = os.listdir(distinfo) + for fn in files: + if fn not in ('RECORD', 'INSTALLER', 'SHARED', 'WHEEL'): + p = fsdecode(os.path.join(distinfo, fn)) + ap = to_posix(os.path.join(info_dir, fn)) + archive_paths.append((ap, p)) + + wheel_metadata = [ + 'Wheel-Version: %d.%d' % (wheel_version or self.wheel_version), + 'Generator: distlib %s' % __version__, + 'Root-Is-Purelib: %s' % is_pure, + ] + for pyver, abi, arch in self.tags: + wheel_metadata.append('Tag: %s-%s-%s' % (pyver, abi, arch)) + p = os.path.join(distinfo, 'WHEEL') + with open(p, 'w') as f: + f.write('\n'.join(wheel_metadata)) + ap = to_posix(os.path.join(info_dir, 'WHEEL')) + archive_paths.append((ap, p)) + + # sort the entries by archive path. Not needed by any spec, but it + # keeps the archive listing and RECORD tidier than they would otherwise + # be. Use the number of path segments to keep directory entries together, + # and keep the dist-info stuff at the end. + def sorter(t): + ap = t[0] + n = ap.count('/') + if '.dist-info' in ap: + n += 10000 + return (n, ap) + archive_paths = sorted(archive_paths, key=sorter) + + # Now, at last, RECORD. + # Paths in here are archive paths - nothing else makes sense. + self.write_records((distinfo, info_dir), libdir, archive_paths) + # Now, ready to build the zip file + pathname = os.path.join(self.dirname, self.filename) + self.build_zip(pathname, archive_paths) + return pathname + + def skip_entry(self, arcname): + """ + Determine whether an archive entry should be skipped when verifying + or installing. + """ + # The signature file won't be in RECORD, + # and we don't currently don't do anything with it + # We also skip directories, as they won't be in RECORD + # either. See: + # + # https://github.com/pypa/wheel/issues/294 + # https://github.com/pypa/wheel/issues/287 + # https://github.com/pypa/wheel/pull/289 + # + return arcname.endswith(('/', '/RECORD.jws')) + + def install(self, paths, maker, **kwargs): + """ + Install a wheel to the specified paths. If kwarg ``warner`` is + specified, it should be a callable, which will be called with two + tuples indicating the wheel version of this software and the wheel + version in the file, if there is a discrepancy in the versions. + This can be used to issue any warnings to raise any exceptions. + If kwarg ``lib_only`` is True, only the purelib/platlib files are + installed, and the headers, scripts, data and dist-info metadata are + not written. If kwarg ``bytecode_hashed_invalidation`` is True, written + bytecode will try to use file-hash based invalidation (PEP-552) on + supported interpreter versions (CPython 2.7+). + + The return value is a :class:`InstalledDistribution` instance unless + ``options.lib_only`` is True, in which case the return value is ``None``. + """ + + dry_run = maker.dry_run + warner = kwargs.get('warner') + lib_only = kwargs.get('lib_only', False) + bc_hashed_invalidation = kwargs.get('bytecode_hashed_invalidation', False) + + pathname = os.path.join(self.dirname, self.filename) + name_ver = '%s-%s' % (self.name, self.version) + data_dir = '%s.data' % name_ver + info_dir = '%s.dist-info' % name_ver + + metadata_name = posixpath.join(info_dir, LEGACY_METADATA_FILENAME) + wheel_metadata_name = posixpath.join(info_dir, 'WHEEL') + record_name = posixpath.join(info_dir, 'RECORD') + + wrapper = codecs.getreader('utf-8') + + with ZipFile(pathname, 'r') as zf: + with zf.open(wheel_metadata_name) as bwf: + wf = wrapper(bwf) + message = message_from_file(wf) + wv = message['Wheel-Version'].split('.', 1) + file_version = tuple([int(i) for i in wv]) + if (file_version != self.wheel_version) and warner: + warner(self.wheel_version, file_version) + + if message['Root-Is-Purelib'] == 'true': + libdir = paths['purelib'] + else: + libdir = paths['platlib'] + + records = {} + with zf.open(record_name) as bf: + with CSVReader(stream=bf) as reader: + for row in reader: + p = row[0] + records[p] = row + + data_pfx = posixpath.join(data_dir, '') + info_pfx = posixpath.join(info_dir, '') + script_pfx = posixpath.join(data_dir, 'scripts', '') + + # make a new instance rather than a copy of maker's, + # as we mutate it + fileop = FileOperator(dry_run=dry_run) + fileop.record = True # so we can rollback if needed + + bc = not sys.dont_write_bytecode # Double negatives. Lovely! + + outfiles = [] # for RECORD writing + + # for script copying/shebang processing + workdir = tempfile.mkdtemp() + # set target dir later + # we default add_launchers to False, as the + # Python Launcher should be used instead + maker.source_dir = workdir + maker.target_dir = None + try: + for zinfo in zf.infolist(): + arcname = zinfo.filename + if isinstance(arcname, text_type): + u_arcname = arcname + else: + u_arcname = arcname.decode('utf-8') + if self.skip_entry(u_arcname): + continue + row = records[u_arcname] + if row[2] and str(zinfo.file_size) != row[2]: + raise DistlibException('size mismatch for ' + '%s' % u_arcname) + if row[1]: + kind, value = row[1].split('=', 1) + with zf.open(arcname) as bf: + data = bf.read() + _, digest = self.get_hash(data, kind) + if digest != value: + raise DistlibException('digest mismatch for ' + '%s' % arcname) + + if lib_only and u_arcname.startswith((info_pfx, data_pfx)): + logger.debug('lib_only: skipping %s', u_arcname) + continue + is_script = (u_arcname.startswith(script_pfx) + and not u_arcname.endswith('.exe')) + + if u_arcname.startswith(data_pfx): + _, where, rp = u_arcname.split('/', 2) + outfile = os.path.join(paths[where], convert_path(rp)) + else: + # meant for site-packages. + if u_arcname in (wheel_metadata_name, record_name): + continue + outfile = os.path.join(libdir, convert_path(u_arcname)) + if not is_script: + with zf.open(arcname) as bf: + fileop.copy_stream(bf, outfile) + # Issue #147: permission bits aren't preserved. Using + # zf.extract(zinfo, libdir) should have worked, but didn't, + # see https://www.thetopsites.net/article/53834422.shtml + # So ... manually preserve permission bits as given in zinfo + if os.name == 'posix': + # just set the normal permission bits + os.chmod(outfile, (zinfo.external_attr >> 16) & 0x1FF) + outfiles.append(outfile) + # Double check the digest of the written file + if not dry_run and row[1]: + with open(outfile, 'rb') as bf: + data = bf.read() + _, newdigest = self.get_hash(data, kind) + if newdigest != digest: + raise DistlibException('digest mismatch ' + 'on write for ' + '%s' % outfile) + if bc and outfile.endswith('.py'): + try: + pyc = fileop.byte_compile(outfile, + hashed_invalidation=bc_hashed_invalidation) + outfiles.append(pyc) + except Exception: + # Don't give up if byte-compilation fails, + # but log it and perhaps warn the user + logger.warning('Byte-compilation failed', + exc_info=True) + else: + fn = os.path.basename(convert_path(arcname)) + workname = os.path.join(workdir, fn) + with zf.open(arcname) as bf: + fileop.copy_stream(bf, workname) + + dn, fn = os.path.split(outfile) + maker.target_dir = dn + filenames = maker.make(fn) + fileop.set_executable_mode(filenames) + outfiles.extend(filenames) + + if lib_only: + logger.debug('lib_only: returning None') + dist = None + else: + # Generate scripts + + # Try to get pydist.json so we can see if there are + # any commands to generate. If this fails (e.g. because + # of a legacy wheel), log a warning but don't give up. + commands = None + file_version = self.info['Wheel-Version'] + if file_version == '1.0': + # Use legacy info + ep = posixpath.join(info_dir, 'entry_points.txt') + try: + with zf.open(ep) as bwf: + epdata = read_exports(bwf) + commands = {} + for key in ('console', 'gui'): + k = '%s_scripts' % key + if k in epdata: + commands['wrap_%s' % key] = d = {} + for v in epdata[k].values(): + s = '%s:%s' % (v.prefix, v.suffix) + if v.flags: + s += ' [%s]' % ','.join(v.flags) + d[v.name] = s + except Exception: + logger.warning('Unable to read legacy script ' + 'metadata, so cannot generate ' + 'scripts') + else: + try: + with zf.open(metadata_name) as bwf: + wf = wrapper(bwf) + commands = json.load(wf).get('extensions') + if commands: + commands = commands.get('python.commands') + except Exception: + logger.warning('Unable to read JSON metadata, so ' + 'cannot generate scripts') + if commands: + console_scripts = commands.get('wrap_console', {}) + gui_scripts = commands.get('wrap_gui', {}) + if console_scripts or gui_scripts: + script_dir = paths.get('scripts', '') + if not os.path.isdir(script_dir): + raise ValueError('Valid script path not ' + 'specified') + maker.target_dir = script_dir + for k, v in console_scripts.items(): + script = '%s = %s' % (k, v) + filenames = maker.make(script) + fileop.set_executable_mode(filenames) + + if gui_scripts: + options = {'gui': True } + for k, v in gui_scripts.items(): + script = '%s = %s' % (k, v) + filenames = maker.make(script, options) + fileop.set_executable_mode(filenames) + + p = os.path.join(libdir, info_dir) + dist = InstalledDistribution(p) + + # Write SHARED + paths = dict(paths) # don't change passed in dict + del paths['purelib'] + del paths['platlib'] + paths['lib'] = libdir + p = dist.write_shared_locations(paths, dry_run) + if p: + outfiles.append(p) + + # Write RECORD + dist.write_installed_files(outfiles, paths['prefix'], + dry_run) + return dist + except Exception: # pragma: no cover + logger.exception('installation failed.') + fileop.rollback() + raise + finally: + shutil.rmtree(workdir) + + def _get_dylib_cache(self): + global cache + if cache is None: + # Use native string to avoid issues on 2.x: see Python #20140. + base = os.path.join(get_cache_base(), str('dylib-cache'), + '%s.%s' % sys.version_info[:2]) + cache = Cache(base) + return cache + + def _get_extensions(self): + pathname = os.path.join(self.dirname, self.filename) + name_ver = '%s-%s' % (self.name, self.version) + info_dir = '%s.dist-info' % name_ver + arcname = posixpath.join(info_dir, 'EXTENSIONS') + wrapper = codecs.getreader('utf-8') + result = [] + with ZipFile(pathname, 'r') as zf: + try: + with zf.open(arcname) as bf: + wf = wrapper(bf) + extensions = json.load(wf) + cache = self._get_dylib_cache() + prefix = cache.prefix_to_dir(pathname) + cache_base = os.path.join(cache.base, prefix) + if not os.path.isdir(cache_base): + os.makedirs(cache_base) + for name, relpath in extensions.items(): + dest = os.path.join(cache_base, convert_path(relpath)) + if not os.path.exists(dest): + extract = True + else: + file_time = os.stat(dest).st_mtime + file_time = datetime.datetime.fromtimestamp(file_time) + info = zf.getinfo(relpath) + wheel_time = datetime.datetime(*info.date_time) + extract = wheel_time > file_time + if extract: + zf.extract(relpath, cache_base) + result.append((name, dest)) + except KeyError: + pass + return result + + def is_compatible(self): + """ + Determine if a wheel is compatible with the running system. + """ + return is_compatible(self) + + def is_mountable(self): + """ + Determine if a wheel is asserted as mountable by its metadata. + """ + return True # for now - metadata details TBD + + def mount(self, append=False): + pathname = os.path.abspath(os.path.join(self.dirname, self.filename)) + if not self.is_compatible(): + msg = 'Wheel %s not compatible with this Python.' % pathname + raise DistlibException(msg) + if not self.is_mountable(): + msg = 'Wheel %s is marked as not mountable.' % pathname + raise DistlibException(msg) + if pathname in sys.path: + logger.debug('%s already in path', pathname) + else: + if append: + sys.path.append(pathname) + else: + sys.path.insert(0, pathname) + extensions = self._get_extensions() + if extensions: + if _hook not in sys.meta_path: + sys.meta_path.append(_hook) + _hook.add(pathname, extensions) + + def unmount(self): + pathname = os.path.abspath(os.path.join(self.dirname, self.filename)) + if pathname not in sys.path: + logger.debug('%s not in path', pathname) + else: + sys.path.remove(pathname) + if pathname in _hook.impure_wheels: + _hook.remove(pathname) + if not _hook.impure_wheels: + if _hook in sys.meta_path: + sys.meta_path.remove(_hook) + + def verify(self): + pathname = os.path.join(self.dirname, self.filename) + name_ver = '%s-%s' % (self.name, self.version) + data_dir = '%s.data' % name_ver + info_dir = '%s.dist-info' % name_ver + + metadata_name = posixpath.join(info_dir, LEGACY_METADATA_FILENAME) + wheel_metadata_name = posixpath.join(info_dir, 'WHEEL') + record_name = posixpath.join(info_dir, 'RECORD') + + wrapper = codecs.getreader('utf-8') + + with ZipFile(pathname, 'r') as zf: + with zf.open(wheel_metadata_name) as bwf: + wf = wrapper(bwf) + message = message_from_file(wf) + wv = message['Wheel-Version'].split('.', 1) + file_version = tuple([int(i) for i in wv]) + # TODO version verification + + records = {} + with zf.open(record_name) as bf: + with CSVReader(stream=bf) as reader: + for row in reader: + p = row[0] + records[p] = row + + for zinfo in zf.infolist(): + arcname = zinfo.filename + if isinstance(arcname, text_type): + u_arcname = arcname + else: + u_arcname = arcname.decode('utf-8') + # See issue #115: some wheels have .. in their entries, but + # in the filename ... e.g. __main__..py ! So the check is + # updated to look for .. in the directory portions + p = u_arcname.split('/') + if '..' in p: + raise DistlibException('invalid entry in ' + 'wheel: %r' % u_arcname) + + if self.skip_entry(u_arcname): + continue + row = records[u_arcname] + if row[2] and str(zinfo.file_size) != row[2]: + raise DistlibException('size mismatch for ' + '%s' % u_arcname) + if row[1]: + kind, value = row[1].split('=', 1) + with zf.open(arcname) as bf: + data = bf.read() + _, digest = self.get_hash(data, kind) + if digest != value: + raise DistlibException('digest mismatch for ' + '%s' % arcname) + + def update(self, modifier, dest_dir=None, **kwargs): + """ + Update the contents of a wheel in a generic way. The modifier should + be a callable which expects a dictionary argument: its keys are + archive-entry paths, and its values are absolute filesystem paths + where the contents the corresponding archive entries can be found. The + modifier is free to change the contents of the files pointed to, add + new entries and remove entries, before returning. This method will + extract the entire contents of the wheel to a temporary location, call + the modifier, and then use the passed (and possibly updated) + dictionary to write a new wheel. If ``dest_dir`` is specified, the new + wheel is written there -- otherwise, the original wheel is overwritten. + + The modifier should return True if it updated the wheel, else False. + This method returns the same value the modifier returns. + """ + + def get_version(path_map, info_dir): + version = path = None + key = '%s/%s' % (info_dir, LEGACY_METADATA_FILENAME) + if key not in path_map: + key = '%s/PKG-INFO' % info_dir + if key in path_map: + path = path_map[key] + version = Metadata(path=path).version + return version, path + + def update_version(version, path): + updated = None + try: + v = NormalizedVersion(version) + i = version.find('-') + if i < 0: + updated = '%s+1' % version + else: + parts = [int(s) for s in version[i + 1:].split('.')] + parts[-1] += 1 + updated = '%s+%s' % (version[:i], + '.'.join(str(i) for i in parts)) + except UnsupportedVersionError: + logger.debug('Cannot update non-compliant (PEP-440) ' + 'version %r', version) + if updated: + md = Metadata(path=path) + md.version = updated + legacy = path.endswith(LEGACY_METADATA_FILENAME) + md.write(path=path, legacy=legacy) + logger.debug('Version updated from %r to %r', version, + updated) + + pathname = os.path.join(self.dirname, self.filename) + name_ver = '%s-%s' % (self.name, self.version) + info_dir = '%s.dist-info' % name_ver + record_name = posixpath.join(info_dir, 'RECORD') + with tempdir() as workdir: + with ZipFile(pathname, 'r') as zf: + path_map = {} + for zinfo in zf.infolist(): + arcname = zinfo.filename + if isinstance(arcname, text_type): + u_arcname = arcname + else: + u_arcname = arcname.decode('utf-8') + if u_arcname == record_name: + continue + if '..' in u_arcname: + raise DistlibException('invalid entry in ' + 'wheel: %r' % u_arcname) + zf.extract(zinfo, workdir) + path = os.path.join(workdir, convert_path(u_arcname)) + path_map[u_arcname] = path + + # Remember the version. + original_version, _ = get_version(path_map, info_dir) + # Files extracted. Call the modifier. + modified = modifier(path_map, **kwargs) + if modified: + # Something changed - need to build a new wheel. + current_version, path = get_version(path_map, info_dir) + if current_version and (current_version == original_version): + # Add or update local version to signify changes. + update_version(current_version, path) + # Decide where the new wheel goes. + if dest_dir is None: + fd, newpath = tempfile.mkstemp(suffix='.whl', + prefix='wheel-update-', + dir=workdir) + os.close(fd) + else: + if not os.path.isdir(dest_dir): + raise DistlibException('Not a directory: %r' % dest_dir) + newpath = os.path.join(dest_dir, self.filename) + archive_paths = list(path_map.items()) + distinfo = os.path.join(workdir, info_dir) + info = distinfo, info_dir + self.write_records(info, workdir, archive_paths) + self.build_zip(newpath, archive_paths) + if dest_dir is None: + shutil.copyfile(newpath, pathname) + return modified + +def _get_glibc_version(): + import platform + ver = platform.libc_ver() + result = [] + if ver[0] == 'glibc': + for s in ver[1].split('.'): + result.append(int(s) if s.isdigit() else 0) + result = tuple(result) + return result + +def compatible_tags(): + """ + Return (pyver, abi, arch) tuples compatible with this Python. + """ + versions = [VER_SUFFIX] + major = VER_SUFFIX[0] + for minor in range(sys.version_info[1] - 1, - 1, -1): + versions.append(''.join([major, str(minor)])) + + abis = [] + for suffix, _, _ in imp.get_suffixes(): + if suffix.startswith('.abi'): + abis.append(suffix.split('.', 2)[1]) + abis.sort() + if ABI != 'none': + abis.insert(0, ABI) + abis.append('none') + result = [] + + arches = [ARCH] + if sys.platform == 'darwin': + m = re.match(r'(\w+)_(\d+)_(\d+)_(\w+)$', ARCH) + if m: + name, major, minor, arch = m.groups() + minor = int(minor) + matches = [arch] + if arch in ('i386', 'ppc'): + matches.append('fat') + if arch in ('i386', 'ppc', 'x86_64'): + matches.append('fat3') + if arch in ('ppc64', 'x86_64'): + matches.append('fat64') + if arch in ('i386', 'x86_64'): + matches.append('intel') + if arch in ('i386', 'x86_64', 'intel', 'ppc', 'ppc64'): + matches.append('universal') + while minor >= 0: + for match in matches: + s = '%s_%s_%s_%s' % (name, major, minor, match) + if s != ARCH: # already there + arches.append(s) + minor -= 1 + + # Most specific - our Python version, ABI and arch + for abi in abis: + for arch in arches: + result.append((''.join((IMP_PREFIX, versions[0])), abi, arch)) + # manylinux + if abi != 'none' and sys.platform.startswith('linux'): + arch = arch.replace('linux_', '') + parts = _get_glibc_version() + if len(parts) == 2: + if parts >= (2, 5): + result.append((''.join((IMP_PREFIX, versions[0])), abi, + 'manylinux1_%s' % arch)) + if parts >= (2, 12): + result.append((''.join((IMP_PREFIX, versions[0])), abi, + 'manylinux2010_%s' % arch)) + if parts >= (2, 17): + result.append((''.join((IMP_PREFIX, versions[0])), abi, + 'manylinux2014_%s' % arch)) + result.append((''.join((IMP_PREFIX, versions[0])), abi, + 'manylinux_%s_%s_%s' % (parts[0], parts[1], + arch))) + + # where no ABI / arch dependency, but IMP_PREFIX dependency + for i, version in enumerate(versions): + result.append((''.join((IMP_PREFIX, version)), 'none', 'any')) + if i == 0: + result.append((''.join((IMP_PREFIX, version[0])), 'none', 'any')) + + # no IMP_PREFIX, ABI or arch dependency + for i, version in enumerate(versions): + result.append((''.join(('py', version)), 'none', 'any')) + if i == 0: + result.append((''.join(('py', version[0])), 'none', 'any')) + + return set(result) + + +COMPATIBLE_TAGS = compatible_tags() + +del compatible_tags + + +def is_compatible(wheel, tags=None): + if not isinstance(wheel, Wheel): + wheel = Wheel(wheel) # assume it's a filename + result = False + if tags is None: + tags = COMPATIBLE_TAGS + for ver, abi, arch in tags: + if ver in wheel.pyver and abi in wheel.abi and arch in wheel.arch: + result = True + break + return result diff --git a/venv/Lib/site-packages/pip/_vendor/distro.py b/venv/Lib/site-packages/pip/_vendor/distro.py new file mode 100644 index 0000000..7892741 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/distro.py @@ -0,0 +1,1386 @@ +# Copyright 2015,2016,2017 Nir Cohen +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +""" +The ``distro`` package (``distro`` stands for Linux Distribution) provides +information about the Linux distribution it runs on, such as a reliable +machine-readable distro ID, or version information. + +It is the recommended replacement for Python's original +:py:func:`platform.linux_distribution` function, but it provides much more +functionality. An alternative implementation became necessary because Python +3.5 deprecated this function, and Python 3.8 removed it altogether. Its +predecessor function :py:func:`platform.dist` was already deprecated since +Python 2.6 and removed in Python 3.8. Still, there are many cases in which +access to OS distribution information is needed. See `Python issue 1322 +`_ for more information. +""" + +import argparse +import json +import logging +import os +import re +import shlex +import subprocess +import sys +import warnings + +__version__ = "1.6.0" + +# Use `if False` to avoid an ImportError on Python 2. After dropping Python 2 +# support, can use typing.TYPE_CHECKING instead. See: +# https://docs.python.org/3/library/typing.html#typing.TYPE_CHECKING +if False: # pragma: nocover + from typing import ( + Any, + Callable, + Dict, + Iterable, + Optional, + Sequence, + TextIO, + Tuple, + Type, + TypedDict, + Union, + ) + + VersionDict = TypedDict( + "VersionDict", {"major": str, "minor": str, "build_number": str} + ) + InfoDict = TypedDict( + "InfoDict", + { + "id": str, + "version": str, + "version_parts": VersionDict, + "like": str, + "codename": str, + }, + ) + + +_UNIXCONFDIR = os.environ.get("UNIXCONFDIR", "/etc") +_UNIXUSRLIBDIR = os.environ.get("UNIXUSRLIBDIR", "/usr/lib") +_OS_RELEASE_BASENAME = "os-release" + +#: Translation table for normalizing the "ID" attribute defined in os-release +#: files, for use by the :func:`distro.id` method. +#: +#: * Key: Value as defined in the os-release file, translated to lower case, +#: with blanks translated to underscores. +#: +#: * Value: Normalized value. +NORMALIZED_OS_ID = { + "ol": "oracle", # Oracle Linux +} + +#: Translation table for normalizing the "Distributor ID" attribute returned by +#: the lsb_release command, for use by the :func:`distro.id` method. +#: +#: * Key: Value as returned by the lsb_release command, translated to lower +#: case, with blanks translated to underscores. +#: +#: * Value: Normalized value. +NORMALIZED_LSB_ID = { + "enterpriseenterpriseas": "oracle", # Oracle Enterprise Linux 4 + "enterpriseenterpriseserver": "oracle", # Oracle Linux 5 + "redhatenterpriseworkstation": "rhel", # RHEL 6, 7 Workstation + "redhatenterpriseserver": "rhel", # RHEL 6, 7 Server + "redhatenterprisecomputenode": "rhel", # RHEL 6 ComputeNode +} + +#: Translation table for normalizing the distro ID derived from the file name +#: of distro release files, for use by the :func:`distro.id` method. +#: +#: * Key: Value as derived from the file name of a distro release file, +#: translated to lower case, with blanks translated to underscores. +#: +#: * Value: Normalized value. +NORMALIZED_DISTRO_ID = { + "redhat": "rhel", # RHEL 6.x, 7.x +} + +# Pattern for content of distro release file (reversed) +_DISTRO_RELEASE_CONTENT_REVERSED_PATTERN = re.compile( + r"(?:[^)]*\)(.*)\()? *(?:STL )?([\d.+\-a-z]*\d) *(?:esaeler *)?(.+)" +) + +# Pattern for base file name of distro release file +_DISTRO_RELEASE_BASENAME_PATTERN = re.compile(r"(\w+)[-_](release|version)$") + +# Base file names to be ignored when searching for distro release file +_DISTRO_RELEASE_IGNORE_BASENAMES = ( + "debian_version", + "lsb-release", + "oem-release", + _OS_RELEASE_BASENAME, + "system-release", + "plesk-release", + "iredmail-release", +) + + +def linux_distribution(full_distribution_name=True): + # type: (bool) -> Tuple[str, str, str] + """ + .. deprecated:: 1.6.0 + + :func:`distro.linux_distribution()` is deprecated. It should only be + used as a compatibility shim with Python's + :py:func:`platform.linux_distribution()`. Please use :func:`distro.id`, + :func:`distro.version` and :func:`distro.name` instead. + + Return information about the current OS distribution as a tuple + ``(id_name, version, codename)`` with items as follows: + + * ``id_name``: If *full_distribution_name* is false, the result of + :func:`distro.id`. Otherwise, the result of :func:`distro.name`. + + * ``version``: The result of :func:`distro.version`. + + * ``codename``: The result of :func:`distro.codename`. + + The interface of this function is compatible with the original + :py:func:`platform.linux_distribution` function, supporting a subset of + its parameters. + + The data it returns may not exactly be the same, because it uses more data + sources than the original function, and that may lead to different data if + the OS distribution is not consistent across multiple data sources it + provides (there are indeed such distributions ...). + + Another reason for differences is the fact that the :func:`distro.id` + method normalizes the distro ID string to a reliable machine-readable value + for a number of popular OS distributions. + """ + warnings.warn( + "distro.linux_distribution() is deprecated. It should only be used as a " + "compatibility shim with Python's platform.linux_distribution(). Please use " + "distro.id(), distro.version() and distro.name() instead.", + DeprecationWarning, + stacklevel=2, + ) + return _distro.linux_distribution(full_distribution_name) + + +def id(): + # type: () -> str + """ + Return the distro ID of the current distribution, as a + machine-readable string. + + For a number of OS distributions, the returned distro ID value is + *reliable*, in the sense that it is documented and that it does not change + across releases of the distribution. + + This package maintains the following reliable distro ID values: + + ============== ========================================= + Distro ID Distribution + ============== ========================================= + "ubuntu" Ubuntu + "debian" Debian + "rhel" RedHat Enterprise Linux + "centos" CentOS + "fedora" Fedora + "sles" SUSE Linux Enterprise Server + "opensuse" openSUSE + "amazon" Amazon Linux + "arch" Arch Linux + "cloudlinux" CloudLinux OS + "exherbo" Exherbo Linux + "gentoo" GenToo Linux + "ibm_powerkvm" IBM PowerKVM + "kvmibm" KVM for IBM z Systems + "linuxmint" Linux Mint + "mageia" Mageia + "mandriva" Mandriva Linux + "parallels" Parallels + "pidora" Pidora + "raspbian" Raspbian + "oracle" Oracle Linux (and Oracle Enterprise Linux) + "scientific" Scientific Linux + "slackware" Slackware + "xenserver" XenServer + "openbsd" OpenBSD + "netbsd" NetBSD + "freebsd" FreeBSD + "midnightbsd" MidnightBSD + ============== ========================================= + + If you have a need to get distros for reliable IDs added into this set, + or if you find that the :func:`distro.id` function returns a different + distro ID for one of the listed distros, please create an issue in the + `distro issue tracker`_. + + **Lookup hierarchy and transformations:** + + First, the ID is obtained from the following sources, in the specified + order. The first available and non-empty value is used: + + * the value of the "ID" attribute of the os-release file, + + * the value of the "Distributor ID" attribute returned by the lsb_release + command, + + * the first part of the file name of the distro release file, + + The so determined ID value then passes the following transformations, + before it is returned by this method: + + * it is translated to lower case, + + * blanks (which should not be there anyway) are translated to underscores, + + * a normalization of the ID is performed, based upon + `normalization tables`_. The purpose of this normalization is to ensure + that the ID is as reliable as possible, even across incompatible changes + in the OS distributions. A common reason for an incompatible change is + the addition of an os-release file, or the addition of the lsb_release + command, with ID values that differ from what was previously determined + from the distro release file name. + """ + return _distro.id() + + +def name(pretty=False): + # type: (bool) -> str + """ + Return the name of the current OS distribution, as a human-readable + string. + + If *pretty* is false, the name is returned without version or codename. + (e.g. "CentOS Linux") + + If *pretty* is true, the version and codename are appended. + (e.g. "CentOS Linux 7.1.1503 (Core)") + + **Lookup hierarchy:** + + The name is obtained from the following sources, in the specified order. + The first available and non-empty value is used: + + * If *pretty* is false: + + - the value of the "NAME" attribute of the os-release file, + + - the value of the "Distributor ID" attribute returned by the lsb_release + command, + + - the value of the "" field of the distro release file. + + * If *pretty* is true: + + - the value of the "PRETTY_NAME" attribute of the os-release file, + + - the value of the "Description" attribute returned by the lsb_release + command, + + - the value of the "" field of the distro release file, appended + with the value of the pretty version ("" and "" + fields) of the distro release file, if available. + """ + return _distro.name(pretty) + + +def version(pretty=False, best=False): + # type: (bool, bool) -> str + """ + Return the version of the current OS distribution, as a human-readable + string. + + If *pretty* is false, the version is returned without codename (e.g. + "7.0"). + + If *pretty* is true, the codename in parenthesis is appended, if the + codename is non-empty (e.g. "7.0 (Maipo)"). + + Some distributions provide version numbers with different precisions in + the different sources of distribution information. Examining the different + sources in a fixed priority order does not always yield the most precise + version (e.g. for Debian 8.2, or CentOS 7.1). + + The *best* parameter can be used to control the approach for the returned + version: + + If *best* is false, the first non-empty version number in priority order of + the examined sources is returned. + + If *best* is true, the most precise version number out of all examined + sources is returned. + + **Lookup hierarchy:** + + In all cases, the version number is obtained from the following sources. + If *best* is false, this order represents the priority order: + + * the value of the "VERSION_ID" attribute of the os-release file, + * the value of the "Release" attribute returned by the lsb_release + command, + * the version number parsed from the "" field of the first line + of the distro release file, + * the version number parsed from the "PRETTY_NAME" attribute of the + os-release file, if it follows the format of the distro release files. + * the version number parsed from the "Description" attribute returned by + the lsb_release command, if it follows the format of the distro release + files. + """ + return _distro.version(pretty, best) + + +def version_parts(best=False): + # type: (bool) -> Tuple[str, str, str] + """ + Return the version of the current OS distribution as a tuple + ``(major, minor, build_number)`` with items as follows: + + * ``major``: The result of :func:`distro.major_version`. + + * ``minor``: The result of :func:`distro.minor_version`. + + * ``build_number``: The result of :func:`distro.build_number`. + + For a description of the *best* parameter, see the :func:`distro.version` + method. + """ + return _distro.version_parts(best) + + +def major_version(best=False): + # type: (bool) -> str + """ + Return the major version of the current OS distribution, as a string, + if provided. + Otherwise, the empty string is returned. The major version is the first + part of the dot-separated version string. + + For a description of the *best* parameter, see the :func:`distro.version` + method. + """ + return _distro.major_version(best) + + +def minor_version(best=False): + # type: (bool) -> str + """ + Return the minor version of the current OS distribution, as a string, + if provided. + Otherwise, the empty string is returned. The minor version is the second + part of the dot-separated version string. + + For a description of the *best* parameter, see the :func:`distro.version` + method. + """ + return _distro.minor_version(best) + + +def build_number(best=False): + # type: (bool) -> str + """ + Return the build number of the current OS distribution, as a string, + if provided. + Otherwise, the empty string is returned. The build number is the third part + of the dot-separated version string. + + For a description of the *best* parameter, see the :func:`distro.version` + method. + """ + return _distro.build_number(best) + + +def like(): + # type: () -> str + """ + Return a space-separated list of distro IDs of distributions that are + closely related to the current OS distribution in regards to packaging + and programming interfaces, for example distributions the current + distribution is a derivative from. + + **Lookup hierarchy:** + + This information item is only provided by the os-release file. + For details, see the description of the "ID_LIKE" attribute in the + `os-release man page + `_. + """ + return _distro.like() + + +def codename(): + # type: () -> str + """ + Return the codename for the release of the current OS distribution, + as a string. + + If the distribution does not have a codename, an empty string is returned. + + Note that the returned codename is not always really a codename. For + example, openSUSE returns "x86_64". This function does not handle such + cases in any special way and just returns the string it finds, if any. + + **Lookup hierarchy:** + + * the codename within the "VERSION" attribute of the os-release file, if + provided, + + * the value of the "Codename" attribute returned by the lsb_release + command, + + * the value of the "" field of the distro release file. + """ + return _distro.codename() + + +def info(pretty=False, best=False): + # type: (bool, bool) -> InfoDict + """ + Return certain machine-readable information items about the current OS + distribution in a dictionary, as shown in the following example: + + .. sourcecode:: python + + { + 'id': 'rhel', + 'version': '7.0', + 'version_parts': { + 'major': '7', + 'minor': '0', + 'build_number': '' + }, + 'like': 'fedora', + 'codename': 'Maipo' + } + + The dictionary structure and keys are always the same, regardless of which + information items are available in the underlying data sources. The values + for the various keys are as follows: + + * ``id``: The result of :func:`distro.id`. + + * ``version``: The result of :func:`distro.version`. + + * ``version_parts -> major``: The result of :func:`distro.major_version`. + + * ``version_parts -> minor``: The result of :func:`distro.minor_version`. + + * ``version_parts -> build_number``: The result of + :func:`distro.build_number`. + + * ``like``: The result of :func:`distro.like`. + + * ``codename``: The result of :func:`distro.codename`. + + For a description of the *pretty* and *best* parameters, see the + :func:`distro.version` method. + """ + return _distro.info(pretty, best) + + +def os_release_info(): + # type: () -> Dict[str, str] + """ + Return a dictionary containing key-value pairs for the information items + from the os-release file data source of the current OS distribution. + + See `os-release file`_ for details about these information items. + """ + return _distro.os_release_info() + + +def lsb_release_info(): + # type: () -> Dict[str, str] + """ + Return a dictionary containing key-value pairs for the information items + from the lsb_release command data source of the current OS distribution. + + See `lsb_release command output`_ for details about these information + items. + """ + return _distro.lsb_release_info() + + +def distro_release_info(): + # type: () -> Dict[str, str] + """ + Return a dictionary containing key-value pairs for the information items + from the distro release file data source of the current OS distribution. + + See `distro release file`_ for details about these information items. + """ + return _distro.distro_release_info() + + +def uname_info(): + # type: () -> Dict[str, str] + """ + Return a dictionary containing key-value pairs for the information items + from the distro release file data source of the current OS distribution. + """ + return _distro.uname_info() + + +def os_release_attr(attribute): + # type: (str) -> str + """ + Return a single named information item from the os-release file data source + of the current OS distribution. + + Parameters: + + * ``attribute`` (string): Key of the information item. + + Returns: + + * (string): Value of the information item, if the item exists. + The empty string, if the item does not exist. + + See `os-release file`_ for details about these information items. + """ + return _distro.os_release_attr(attribute) + + +def lsb_release_attr(attribute): + # type: (str) -> str + """ + Return a single named information item from the lsb_release command output + data source of the current OS distribution. + + Parameters: + + * ``attribute`` (string): Key of the information item. + + Returns: + + * (string): Value of the information item, if the item exists. + The empty string, if the item does not exist. + + See `lsb_release command output`_ for details about these information + items. + """ + return _distro.lsb_release_attr(attribute) + + +def distro_release_attr(attribute): + # type: (str) -> str + """ + Return a single named information item from the distro release file + data source of the current OS distribution. + + Parameters: + + * ``attribute`` (string): Key of the information item. + + Returns: + + * (string): Value of the information item, if the item exists. + The empty string, if the item does not exist. + + See `distro release file`_ for details about these information items. + """ + return _distro.distro_release_attr(attribute) + + +def uname_attr(attribute): + # type: (str) -> str + """ + Return a single named information item from the distro release file + data source of the current OS distribution. + + Parameters: + + * ``attribute`` (string): Key of the information item. + + Returns: + + * (string): Value of the information item, if the item exists. + The empty string, if the item does not exist. + """ + return _distro.uname_attr(attribute) + + +try: + from functools import cached_property +except ImportError: + # Python < 3.8 + class cached_property(object): # type: ignore + """A version of @property which caches the value. On access, it calls the + underlying function and sets the value in `__dict__` so future accesses + will not re-call the property. + """ + + def __init__(self, f): + # type: (Callable[[Any], Any]) -> None + self._fname = f.__name__ + self._f = f + + def __get__(self, obj, owner): + # type: (Any, Type[Any]) -> Any + assert obj is not None, "call {} on an instance".format(self._fname) + ret = obj.__dict__[self._fname] = self._f(obj) + return ret + + +class LinuxDistribution(object): + """ + Provides information about a OS distribution. + + This package creates a private module-global instance of this class with + default initialization arguments, that is used by the + `consolidated accessor functions`_ and `single source accessor functions`_. + By using default initialization arguments, that module-global instance + returns data about the current OS distribution (i.e. the distro this + package runs on). + + Normally, it is not necessary to create additional instances of this class. + However, in situations where control is needed over the exact data sources + that are used, instances of this class can be created with a specific + distro release file, or a specific os-release file, or without invoking the + lsb_release command. + """ + + def __init__( + self, + include_lsb=True, + os_release_file="", + distro_release_file="", + include_uname=True, + root_dir=None, + ): + # type: (bool, str, str, bool, Optional[str]) -> None + """ + The initialization method of this class gathers information from the + available data sources, and stores that in private instance attributes. + Subsequent access to the information items uses these private instance + attributes, so that the data sources are read only once. + + Parameters: + + * ``include_lsb`` (bool): Controls whether the + `lsb_release command output`_ is included as a data source. + + If the lsb_release command is not available in the program execution + path, the data source for the lsb_release command will be empty. + + * ``os_release_file`` (string): The path name of the + `os-release file`_ that is to be used as a data source. + + An empty string (the default) will cause the default path name to + be used (see `os-release file`_ for details). + + If the specified or defaulted os-release file does not exist, the + data source for the os-release file will be empty. + + * ``distro_release_file`` (string): The path name of the + `distro release file`_ that is to be used as a data source. + + An empty string (the default) will cause a default search algorithm + to be used (see `distro release file`_ for details). + + If the specified distro release file does not exist, or if no default + distro release file can be found, the data source for the distro + release file will be empty. + + * ``include_uname`` (bool): Controls whether uname command output is + included as a data source. If the uname command is not available in + the program execution path the data source for the uname command will + be empty. + + * ``root_dir`` (string): The absolute path to the root directory to use + to find distro-related information files. + + Public instance attributes: + + * ``os_release_file`` (string): The path name of the + `os-release file`_ that is actually used as a data source. The + empty string if no distro release file is used as a data source. + + * ``distro_release_file`` (string): The path name of the + `distro release file`_ that is actually used as a data source. The + empty string if no distro release file is used as a data source. + + * ``include_lsb`` (bool): The result of the ``include_lsb`` parameter. + This controls whether the lsb information will be loaded. + + * ``include_uname`` (bool): The result of the ``include_uname`` + parameter. This controls whether the uname information will + be loaded. + + Raises: + + * :py:exc:`IOError`: Some I/O issue with an os-release file or distro + release file. + + * :py:exc:`subprocess.CalledProcessError`: The lsb_release command had + some issue (other than not being available in the program execution + path). + + * :py:exc:`UnicodeError`: A data source has unexpected characters or + uses an unexpected encoding. + """ + self.root_dir = root_dir + self.etc_dir = os.path.join(root_dir, "etc") if root_dir else _UNIXCONFDIR + self.usr_lib_dir = ( + os.path.join(root_dir, "usr/lib") if root_dir else _UNIXUSRLIBDIR + ) + + if os_release_file: + self.os_release_file = os_release_file + else: + etc_dir_os_release_file = os.path.join(self.etc_dir, _OS_RELEASE_BASENAME) + usr_lib_os_release_file = os.path.join( + self.usr_lib_dir, _OS_RELEASE_BASENAME + ) + + # NOTE: The idea is to respect order **and** have it set + # at all times for API backwards compatibility. + if os.path.isfile(etc_dir_os_release_file) or not os.path.isfile( + usr_lib_os_release_file + ): + self.os_release_file = etc_dir_os_release_file + else: + self.os_release_file = usr_lib_os_release_file + + self.distro_release_file = distro_release_file or "" # updated later + self.include_lsb = include_lsb + self.include_uname = include_uname + + def __repr__(self): + # type: () -> str + """Return repr of all info""" + return ( + "LinuxDistribution(" + "os_release_file={self.os_release_file!r}, " + "distro_release_file={self.distro_release_file!r}, " + "include_lsb={self.include_lsb!r}, " + "include_uname={self.include_uname!r}, " + "_os_release_info={self._os_release_info!r}, " + "_lsb_release_info={self._lsb_release_info!r}, " + "_distro_release_info={self._distro_release_info!r}, " + "_uname_info={self._uname_info!r})".format(self=self) + ) + + def linux_distribution(self, full_distribution_name=True): + # type: (bool) -> Tuple[str, str, str] + """ + Return information about the OS distribution that is compatible + with Python's :func:`platform.linux_distribution`, supporting a subset + of its parameters. + + For details, see :func:`distro.linux_distribution`. + """ + return ( + self.name() if full_distribution_name else self.id(), + self.version(), + self.codename(), + ) + + def id(self): + # type: () -> str + """Return the distro ID of the OS distribution, as a string. + + For details, see :func:`distro.id`. + """ + + def normalize(distro_id, table): + # type: (str, Dict[str, str]) -> str + distro_id = distro_id.lower().replace(" ", "_") + return table.get(distro_id, distro_id) + + distro_id = self.os_release_attr("id") + if distro_id: + return normalize(distro_id, NORMALIZED_OS_ID) + + distro_id = self.lsb_release_attr("distributor_id") + if distro_id: + return normalize(distro_id, NORMALIZED_LSB_ID) + + distro_id = self.distro_release_attr("id") + if distro_id: + return normalize(distro_id, NORMALIZED_DISTRO_ID) + + distro_id = self.uname_attr("id") + if distro_id: + return normalize(distro_id, NORMALIZED_DISTRO_ID) + + return "" + + def name(self, pretty=False): + # type: (bool) -> str + """ + Return the name of the OS distribution, as a string. + + For details, see :func:`distro.name`. + """ + name = ( + self.os_release_attr("name") + or self.lsb_release_attr("distributor_id") + or self.distro_release_attr("name") + or self.uname_attr("name") + ) + if pretty: + name = self.os_release_attr("pretty_name") or self.lsb_release_attr( + "description" + ) + if not name: + name = self.distro_release_attr("name") or self.uname_attr("name") + version = self.version(pretty=True) + if version: + name = name + " " + version + return name or "" + + def version(self, pretty=False, best=False): + # type: (bool, bool) -> str + """ + Return the version of the OS distribution, as a string. + + For details, see :func:`distro.version`. + """ + versions = [ + self.os_release_attr("version_id"), + self.lsb_release_attr("release"), + self.distro_release_attr("version_id"), + self._parse_distro_release_content(self.os_release_attr("pretty_name")).get( + "version_id", "" + ), + self._parse_distro_release_content( + self.lsb_release_attr("description") + ).get("version_id", ""), + self.uname_attr("release"), + ] + version = "" + if best: + # This algorithm uses the last version in priority order that has + # the best precision. If the versions are not in conflict, that + # does not matter; otherwise, using the last one instead of the + # first one might be considered a surprise. + for v in versions: + if v.count(".") > version.count(".") or version == "": + version = v + else: + for v in versions: + if v != "": + version = v + break + if pretty and version and self.codename(): + version = "{0} ({1})".format(version, self.codename()) + return version + + def version_parts(self, best=False): + # type: (bool) -> Tuple[str, str, str] + """ + Return the version of the OS distribution, as a tuple of version + numbers. + + For details, see :func:`distro.version_parts`. + """ + version_str = self.version(best=best) + if version_str: + version_regex = re.compile(r"(\d+)\.?(\d+)?\.?(\d+)?") + matches = version_regex.match(version_str) + if matches: + major, minor, build_number = matches.groups() + return major, minor or "", build_number or "" + return "", "", "" + + def major_version(self, best=False): + # type: (bool) -> str + """ + Return the major version number of the current distribution. + + For details, see :func:`distro.major_version`. + """ + return self.version_parts(best)[0] + + def minor_version(self, best=False): + # type: (bool) -> str + """ + Return the minor version number of the current distribution. + + For details, see :func:`distro.minor_version`. + """ + return self.version_parts(best)[1] + + def build_number(self, best=False): + # type: (bool) -> str + """ + Return the build number of the current distribution. + + For details, see :func:`distro.build_number`. + """ + return self.version_parts(best)[2] + + def like(self): + # type: () -> str + """ + Return the IDs of distributions that are like the OS distribution. + + For details, see :func:`distro.like`. + """ + return self.os_release_attr("id_like") or "" + + def codename(self): + # type: () -> str + """ + Return the codename of the OS distribution. + + For details, see :func:`distro.codename`. + """ + try: + # Handle os_release specially since distros might purposefully set + # this to empty string to have no codename + return self._os_release_info["codename"] + except KeyError: + return ( + self.lsb_release_attr("codename") + or self.distro_release_attr("codename") + or "" + ) + + def info(self, pretty=False, best=False): + # type: (bool, bool) -> InfoDict + """ + Return certain machine-readable information about the OS + distribution. + + For details, see :func:`distro.info`. + """ + return dict( + id=self.id(), + version=self.version(pretty, best), + version_parts=dict( + major=self.major_version(best), + minor=self.minor_version(best), + build_number=self.build_number(best), + ), + like=self.like(), + codename=self.codename(), + ) + + def os_release_info(self): + # type: () -> Dict[str, str] + """ + Return a dictionary containing key-value pairs for the information + items from the os-release file data source of the OS distribution. + + For details, see :func:`distro.os_release_info`. + """ + return self._os_release_info + + def lsb_release_info(self): + # type: () -> Dict[str, str] + """ + Return a dictionary containing key-value pairs for the information + items from the lsb_release command data source of the OS + distribution. + + For details, see :func:`distro.lsb_release_info`. + """ + return self._lsb_release_info + + def distro_release_info(self): + # type: () -> Dict[str, str] + """ + Return a dictionary containing key-value pairs for the information + items from the distro release file data source of the OS + distribution. + + For details, see :func:`distro.distro_release_info`. + """ + return self._distro_release_info + + def uname_info(self): + # type: () -> Dict[str, str] + """ + Return a dictionary containing key-value pairs for the information + items from the uname command data source of the OS distribution. + + For details, see :func:`distro.uname_info`. + """ + return self._uname_info + + def os_release_attr(self, attribute): + # type: (str) -> str + """ + Return a single named information item from the os-release file data + source of the OS distribution. + + For details, see :func:`distro.os_release_attr`. + """ + return self._os_release_info.get(attribute, "") + + def lsb_release_attr(self, attribute): + # type: (str) -> str + """ + Return a single named information item from the lsb_release command + output data source of the OS distribution. + + For details, see :func:`distro.lsb_release_attr`. + """ + return self._lsb_release_info.get(attribute, "") + + def distro_release_attr(self, attribute): + # type: (str) -> str + """ + Return a single named information item from the distro release file + data source of the OS distribution. + + For details, see :func:`distro.distro_release_attr`. + """ + return self._distro_release_info.get(attribute, "") + + def uname_attr(self, attribute): + # type: (str) -> str + """ + Return a single named information item from the uname command + output data source of the OS distribution. + + For details, see :func:`distro.uname_attr`. + """ + return self._uname_info.get(attribute, "") + + @cached_property + def _os_release_info(self): + # type: () -> Dict[str, str] + """ + Get the information items from the specified os-release file. + + Returns: + A dictionary containing all information items. + """ + if os.path.isfile(self.os_release_file): + with open(self.os_release_file) as release_file: + return self._parse_os_release_content(release_file) + return {} + + @staticmethod + def _parse_os_release_content(lines): + # type: (TextIO) -> Dict[str, str] + """ + Parse the lines of an os-release file. + + Parameters: + + * lines: Iterable through the lines in the os-release file. + Each line must be a unicode string or a UTF-8 encoded byte + string. + + Returns: + A dictionary containing all information items. + """ + props = {} + lexer = shlex.shlex(lines, posix=True) + lexer.whitespace_split = True + + # The shlex module defines its `wordchars` variable using literals, + # making it dependent on the encoding of the Python source file. + # In Python 2.6 and 2.7, the shlex source file is encoded in + # 'iso-8859-1', and the `wordchars` variable is defined as a byte + # string. This causes a UnicodeDecodeError to be raised when the + # parsed content is a unicode object. The following fix resolves that + # (... but it should be fixed in shlex...): + if sys.version_info[0] == 2 and isinstance(lexer.wordchars, bytes): + lexer.wordchars = lexer.wordchars.decode("iso-8859-1") + + tokens = list(lexer) + for token in tokens: + # At this point, all shell-like parsing has been done (i.e. + # comments processed, quotes and backslash escape sequences + # processed, multi-line values assembled, trailing newlines + # stripped, etc.), so the tokens are now either: + # * variable assignments: var=value + # * commands or their arguments (not allowed in os-release) + if "=" in token: + k, v = token.split("=", 1) + props[k.lower()] = v + else: + # Ignore any tokens that are not variable assignments + pass + + if "version_codename" in props: + # os-release added a version_codename field. Use that in + # preference to anything else Note that some distros purposefully + # do not have code names. They should be setting + # version_codename="" + props["codename"] = props["version_codename"] + elif "ubuntu_codename" in props: + # Same as above but a non-standard field name used on older Ubuntus + props["codename"] = props["ubuntu_codename"] + elif "version" in props: + # If there is no version_codename, parse it from the version + match = re.search(r"(\(\D+\))|,(\s+)?\D+", props["version"]) + if match: + codename = match.group() + codename = codename.strip("()") + codename = codename.strip(",") + codename = codename.strip() + # codename appears within paranthese. + props["codename"] = codename + + return props + + @cached_property + def _lsb_release_info(self): + # type: () -> Dict[str, str] + """ + Get the information items from the lsb_release command output. + + Returns: + A dictionary containing all information items. + """ + if not self.include_lsb: + return {} + with open(os.devnull, "wb") as devnull: + try: + cmd = ("lsb_release", "-a") + stdout = subprocess.check_output(cmd, stderr=devnull) + # Command not found or lsb_release returned error + except (OSError, subprocess.CalledProcessError): + return {} + content = self._to_str(stdout).splitlines() + return self._parse_lsb_release_content(content) + + @staticmethod + def _parse_lsb_release_content(lines): + # type: (Iterable[str]) -> Dict[str, str] + """ + Parse the output of the lsb_release command. + + Parameters: + + * lines: Iterable through the lines of the lsb_release output. + Each line must be a unicode string or a UTF-8 encoded byte + string. + + Returns: + A dictionary containing all information items. + """ + props = {} + for line in lines: + kv = line.strip("\n").split(":", 1) + if len(kv) != 2: + # Ignore lines without colon. + continue + k, v = kv + props.update({k.replace(" ", "_").lower(): v.strip()}) + return props + + @cached_property + def _uname_info(self): + # type: () -> Dict[str, str] + with open(os.devnull, "wb") as devnull: + try: + cmd = ("uname", "-rs") + stdout = subprocess.check_output(cmd, stderr=devnull) + except OSError: + return {} + content = self._to_str(stdout).splitlines() + return self._parse_uname_content(content) + + @staticmethod + def _parse_uname_content(lines): + # type: (Sequence[str]) -> Dict[str, str] + props = {} + match = re.search(r"^([^\s]+)\s+([\d\.]+)", lines[0].strip()) + if match: + name, version = match.groups() + + # This is to prevent the Linux kernel version from + # appearing as the 'best' version on otherwise + # identifiable distributions. + if name == "Linux": + return {} + props["id"] = name.lower() + props["name"] = name + props["release"] = version + return props + + @staticmethod + def _to_str(text): + # type: (Union[bytes, str]) -> str + encoding = sys.getfilesystemencoding() + encoding = "utf-8" if encoding == "ascii" else encoding + + if sys.version_info[0] >= 3: + if isinstance(text, bytes): + return text.decode(encoding) + else: + if isinstance(text, unicode): # noqa + return text.encode(encoding) + + return text + + @cached_property + def _distro_release_info(self): + # type: () -> Dict[str, str] + """ + Get the information items from the specified distro release file. + + Returns: + A dictionary containing all information items. + """ + if self.distro_release_file: + # If it was specified, we use it and parse what we can, even if + # its file name or content does not match the expected pattern. + distro_info = self._parse_distro_release_file(self.distro_release_file) + basename = os.path.basename(self.distro_release_file) + # The file name pattern for user-specified distro release files + # is somewhat more tolerant (compared to when searching for the + # file), because we want to use what was specified as best as + # possible. + match = _DISTRO_RELEASE_BASENAME_PATTERN.match(basename) + if "name" in distro_info and "cloudlinux" in distro_info["name"].lower(): + distro_info["id"] = "cloudlinux" + elif match: + distro_info["id"] = match.group(1) + return distro_info + else: + try: + basenames = os.listdir(self.etc_dir) + # We sort for repeatability in cases where there are multiple + # distro specific files; e.g. CentOS, Oracle, Enterprise all + # containing `redhat-release` on top of their own. + basenames.sort() + except OSError: + # This may occur when /etc is not readable but we can't be + # sure about the *-release files. Check common entries of + # /etc for information. If they turn out to not be there the + # error is handled in `_parse_distro_release_file()`. + basenames = [ + "SuSE-release", + "arch-release", + "base-release", + "centos-release", + "fedora-release", + "gentoo-release", + "mageia-release", + "mandrake-release", + "mandriva-release", + "mandrivalinux-release", + "manjaro-release", + "oracle-release", + "redhat-release", + "sl-release", + "slackware-version", + ] + for basename in basenames: + if basename in _DISTRO_RELEASE_IGNORE_BASENAMES: + continue + match = _DISTRO_RELEASE_BASENAME_PATTERN.match(basename) + if match: + filepath = os.path.join(self.etc_dir, basename) + distro_info = self._parse_distro_release_file(filepath) + if "name" in distro_info: + # The name is always present if the pattern matches + self.distro_release_file = filepath + distro_info["id"] = match.group(1) + if "cloudlinux" in distro_info["name"].lower(): + distro_info["id"] = "cloudlinux" + return distro_info + return {} + + def _parse_distro_release_file(self, filepath): + # type: (str) -> Dict[str, str] + """ + Parse a distro release file. + + Parameters: + + * filepath: Path name of the distro release file. + + Returns: + A dictionary containing all information items. + """ + try: + with open(filepath) as fp: + # Only parse the first line. For instance, on SLES there + # are multiple lines. We don't want them... + return self._parse_distro_release_content(fp.readline()) + except (OSError, IOError): + # Ignore not being able to read a specific, seemingly version + # related file. + # See https://github.com/python-distro/distro/issues/162 + return {} + + @staticmethod + def _parse_distro_release_content(line): + # type: (str) -> Dict[str, str] + """ + Parse a line from a distro release file. + + Parameters: + * line: Line from the distro release file. Must be a unicode string + or a UTF-8 encoded byte string. + + Returns: + A dictionary containing all information items. + """ + matches = _DISTRO_RELEASE_CONTENT_REVERSED_PATTERN.match(line.strip()[::-1]) + distro_info = {} + if matches: + # regexp ensures non-None + distro_info["name"] = matches.group(3)[::-1] + if matches.group(2): + distro_info["version_id"] = matches.group(2)[::-1] + if matches.group(1): + distro_info["codename"] = matches.group(1)[::-1] + elif line: + distro_info["name"] = line.strip() + return distro_info + + +_distro = LinuxDistribution() + + +def main(): + # type: () -> None + logger = logging.getLogger(__name__) + logger.setLevel(logging.DEBUG) + logger.addHandler(logging.StreamHandler(sys.stdout)) + + parser = argparse.ArgumentParser(description="OS distro info tool") + parser.add_argument( + "--json", "-j", help="Output in machine readable format", action="store_true" + ) + + parser.add_argument( + "--root-dir", + "-r", + type=str, + dest="root_dir", + help="Path to the root filesystem directory (defaults to /)", + ) + + args = parser.parse_args() + + if args.root_dir: + dist = LinuxDistribution( + include_lsb=False, include_uname=False, root_dir=args.root_dir + ) + else: + dist = _distro + + if args.json: + logger.info(json.dumps(dist.info(), indent=4, sort_keys=True)) + else: + logger.info("Name: %s", dist.name(pretty=True)) + distribution_version = dist.version(pretty=True) + logger.info("Version: %s", distribution_version) + distribution_codename = dist.codename() + logger.info("Codename: %s", distribution_codename) + + +if __name__ == "__main__": + main() diff --git a/venv/Lib/site-packages/pip/_vendor/html5lib/__init__.py b/venv/Lib/site-packages/pip/_vendor/html5lib/__init__.py new file mode 100644 index 0000000..d1d82f1 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/html5lib/__init__.py @@ -0,0 +1,35 @@ +""" +HTML parsing library based on the `WHATWG HTML specification +`_. The parser is designed to be compatible with +existing HTML found in the wild and implements well-defined error recovery that +is largely compatible with modern desktop web browsers. + +Example usage:: + + from pip._vendor import html5lib + with open("my_document.html", "rb") as f: + tree = html5lib.parse(f) + +For convenience, this module re-exports the following names: + +* :func:`~.html5parser.parse` +* :func:`~.html5parser.parseFragment` +* :class:`~.html5parser.HTMLParser` +* :func:`~.treebuilders.getTreeBuilder` +* :func:`~.treewalkers.getTreeWalker` +* :func:`~.serializer.serialize` +""" + +from __future__ import absolute_import, division, unicode_literals + +from .html5parser import HTMLParser, parse, parseFragment +from .treebuilders import getTreeBuilder +from .treewalkers import getTreeWalker +from .serializer import serialize + +__all__ = ["HTMLParser", "parse", "parseFragment", "getTreeBuilder", + "getTreeWalker", "serialize"] + +# this has to be at the top level, see how setup.py parses this +#: Distribution version number. +__version__ = "1.1" diff --git a/venv/Lib/site-packages/pip/_vendor/html5lib/__pycache__/__init__.cpython-39.pyc b/venv/Lib/site-packages/pip/_vendor/html5lib/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6cc0967b6b60eb8055a981f2d5ffdbe79d0719ec GIT binary patch literal 1295 zcmaJ>O>f&a7?wX`J93XdI-o-_ki&E+N9jn8)A1mpBRUp)a*|HuG@Z&>ItyoeVqeB-9M%&tmj~%V zSWm@59;SzbsEX+9k3sr??xzoF{ByLNlfQs4ezW=EEvkvJTvbT$+z@k#a$*@pS|PV% zXnXqR<>vHz6g+Ls3SRPpIIdOveCJ$k*C!|Kj<~i;w5d*ZPKp;>oS+Td^}x&^ZV_dc zR|-&_Mma-;mNj7Hf}xhXUCb`HbzVYXDRrYL;yr)M1x3W~Wi6Ow%30JhAy$-?+#@n$ zv_Xay`kaAy2U=oa6vR|aT;8WbQd4G>7j))y4Ny7Cjc!4wP2%{w3*u=|V@bu<>o`X6 zltxQb^E$!jOi>^MDcU&XV|@lm3r;=`q-&-gAInQjbG0N-czLeeM*I%!1_4 z(YkC@vEIH5?9cit^zhsNef!#w%Bv1ug&@}62l4g!DOB|ik`E}Tdf79>( zrrylF+4sgz zxS4~w8a+*({u-r8*;`!@ zk!_f)GwAqLqiRx|F}iAZjEU73U;f5zVXyqV?0Ooqk7JNw%oTSSC-r4Fd)~L}3ts_y R2xk20(eP++;6KCJ-oF<{nCk!l literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_vendor/html5lib/__pycache__/_ihatexml.cpython-39.pyc b/venv/Lib/site-packages/pip/_vendor/html5lib/__pycache__/_ihatexml.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a3611165333c9da1d7c295bb41272dad702bc5e0 GIT binary patch literal 13764 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 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_vendor/html5lib/__pycache__/_inputstream.cpython-39.pyc b/venv/Lib/site-packages/pip/_vendor/html5lib/__pycache__/_inputstream.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..026e38797319b79a0f19efd6a44a3cc39db0ab13 GIT binary patch literal 21623 zcmcJ1d5|2}d0$_1?(BiZ0$6|`I0ONLLt&Q?C{Z*6Lm)uHBuy?6VkwDBP{Y~j-o@H1h>d|@2q+}{8xyxg#ad%?bx^A8|77n_* z7Vh@;tsHvOR0qAg-O2riyL;7AKlJY2yvN;r!*nyNmjAz>F~ zUU%xcxeu-P88^&@!_B;|Xa2I`?)i$ja34$Dy(l?SGZv2igyHUUr{6H#Y485)_QElD zzkA>fW8ndm-{l@e`9Uc!;rVX&5S|ZtCA51G&-b`RJQuwW;Q2V7?{yF3`LMK~!Sj9Y z5j-D}=UMltdq2i~$aO9nrDJasmL)qJuPpkldOPsSwZ>XY1!2~$U8(uCRx_MvH*3|F z>y_)Zz*CjFUoyj7;Jp@`ieIhOp7jEG z8k46N*Va5$t@s{>+EsqRTdOGFd-Aoaw-#WoC`^~zL9OmrIdc4GAwxVphs)oKWZCE% zuZ(S&U2_xodBgm?wT|7mX@)6z2{LJ!qj%E^t=SWygOxXK8friK-da5O*rgYJOz={r z*{t}N9$#B~q7qatJ=>~Q>X+ud#@eN|+S*LJiRG+%?#$K8o>!lFX ziU}7ltI){-K5|%TaS)k5r}205MI8TK!sWE2r`lga{$+C}J2EzN&u3u=6{ z=hwgfovpXNv$gfzU)*{N*VcExj{Dbf-@<)sYwLS|b?Yr$Ti-)HuC4E(9@p0QP>*Zt z9n|C6dI$Bmw%$QKuB~@ak8A5))Z^NE7xlQd-bFpGt#?t6YwP={$F=p!+qdy|%Y3CX ze)v-RiAPVIn8EG*`SXWQ7cuYJd$;pU942X_cKddL$rzIfCRrv@Ax&(yGnu5AWSHdG z1dq4*cw0ZB$?e-COh%cEGm*X)dtmtYIP!aJ@}6!Y(?GlTID_}}%Ppfb`EqV%v^ew7 zV>4$iy*%^kr)EC=N)_`?{E;xu;PRhB;u#C3Yb;o4m+jm)p%%zu0QBKdSt8Ls)~nOa@wM)tY=oqtd*_sgMyBuh#1I;-Xjd>#eIrzt*gJ z#ah4@J^w)S!3R&4q-T};75_2MOPC4?scUwPvapu2>6)&!Y~k5*4eW?Lr|v-uCG5@) z(|QBKv|ewRU2FL@;a^th_+EWU9cF8Cn?9X}*)q69Ehv{CL%E+uVwh?CclITBdp2&D zpk*7)9b7WqQ^>d`_@A)?{)ZG3-f!^Sdct^RV#Dg1fz`zc_z`2nT%YE`&;qr5?wa6~ zSP<8uMv#)*-ixYVD`bW{o7wN)u%xQBB|DD}KYhk;@ zwsQ@=b|v)eRo7^|i~!E?B4ZUBWh?0~bjy7qpY{#|R;Q0KeWVA-Pv)(J$%nry7m z?rMP91eiL8fpIR4l{JJsSB^6E0E+vIEjhAIRYGZ)ZY?eOUJ#nKZEN*CZ}mLd_+v;6 za{{Y%%t`#`x38CN6YC|4CD#j>`4d<(R(b=l;3^5dz(x*hg>-UW$^b82=E@%E@_w&P zNB0*5bq3%ms9H+NI>V7N2sk2Rfw1gBI4;HKRjZ-lb<@%yPc8Du-?jrBZnKB@}0^M!nlo6yz-coLzGP+ib z@@dU^K7_$E{L>W(TurwR`iQvI!)OvZE(D(;XsZ*bc^Owk+6A)!R0nAv7+zT)vl7e7 zqA$6d!26rXkfN7CrCc5{eZ!F)@OvZGbu>)_?+x{9T~NZR9o-%OwD1FR0S9f!=<3)bl;UDtJlS2$f8+nPo%=|`R^TWobRR2VeMwt z1zdyNbqjTQ=`DF+!DqDq)iuedfWfx966D=<*WQcg*Uez0Yb=>HVE9+f&jB-nLh@O7 zb7ttTc=9`ygEfmy4BRq(~M; z**Pw)j;hjVn1`a-^n(hdE=9@@3s23@UwFau*IG>|S{W8)RrDBUDz3W-4KTEp*22u? zieCu=rFV#%5$5KhmOiOeONDzm=@+&7IxzQe56jQiniX|zpcn^!+HbX0)eFK^9e)oeT7#)r0M1GDfCAu;TNRd~;`3x8rcJo6@T-Z>y3$1GSAmYPS4Dw_@d zk*S}-<*y-0isTT-ZP$UAopK?N;|`(R&ElSMb8a5@thRVS93OSZ@SKO`V8Y$?hPg1} zPP)5MQgEl-J-Cm$2gTZ8E{sKXhH-Zsoat^ghu7Zv-3zL9rRI7RtYe^QnN^F}v5H;{ zS|Vn11Lj++UbEKm)NCxTLwc^(A%Pcz$|{DcR+N|M-p7wh(=CFj;hhxy74mEKN)-ieuwgWsQczWNdQsTA9HawmaXQY00QE5)3qTy9pPyyrCH=sBHKI5Y?lr)ZVIi^OO*Ig zyP2bCg?t|QksAh>KiPif54J$UPeX>URUjf@0aQ_jkSCfcHJ+iG2Q+RTFTNaO;wz=% z%<1A>OEoZF2bxd>qb0~?McrC9kb_b0YWq;3t`%de!@#R_V}PhhCCCH0dJ3>#s@1)j z*5V5G{&-Qu8z~~sCYUOb`ZO>QwX~KfT$OqszOd4u3(PphMjL7xUJ-W{wG0fwtyL>H zmwMCX&cw@{Ef$|%D*9_)wYF6A+~c}WT-#IKusZj6Zvf>jSCm`#fPT;lsp_45{y9#% zj`ygd>j5=Yg-TcP0l!@ZdxBC4%qe1?mEI_xRx(Q(rMZuDZJr%85Qy?4YS67zJ6M`| zG|Yg11vr^Y1x2e(IPJIBXiW3V^;Xj>`)x3#WiB(^0}Mw+&)6mG%Ga{>?rLlT)1@z- zyZE7Shr*L#w&`7c7HIB=WA#>RwY~OaWLOIe9HaM?Z$XCBY&*Y>HofTOChpIIOCf2!!IJ%v|?yQ3H{35-b!{yH+5h}w$3QB=M zj}&4aQqUYyh+9ZgR8Pz4NQ(|56*{9HME5W!y5&WnemEl8Na9I*;am4AL5NV{y!409HKyn zXE8&SLvmAV@)|V`vvdeQUPakAaQPJ4jZEH5TUo1f?;SR#kA{ie;rY&!TXu(sBE@^| z#U}O$SYY0;MfiuhzK_B`^qO8d#BkxxXM{V$;J%S=7GM%cxz0XgnnJ(R1z!gDP0fX7 zURy2179*yMlt!dfwbgD0Y8meiQ)&t9NL@z0l+lzigS>8-ZfaaA#16=A9JN-n+CLqJMxV9o!b`I;~6AS;szJDno`qPsCC2ervqEe zAT&<#jHZehFB%p((p1Unw2D-DU>L+IV+N}Us=q*<4-hWeF#h4pxKgRrD~ok+7CpIR zy;Fhb06Z2&SoWKefusXvwtCrfXM2tGUV+78(#k~==BV(VqkU2pSV$fgtJ7>1I-J<> z23|$Yf5xRbP^thVaV$!cu$|m>2SVdGa|s%Y6&|564hN(#+J+kAesbSnH-Mr{lpzNe z{!0larTMa?X|%{}W+~fXe~p!#`UKOi1*(Ic6RmU2Y}fK%bpekcPYZ+VtUBszP;)Fd zMME4_AU6${*%#eR*LJ`ZS55T=H;eRZO~*8vdv!~Wg&f?0RIuf31@#tYS%@qe*5)XM z-WyQ4zz;?t_(ploS-%@O%Pj!*qjRc?6$|a3*QYi)z}urtjBmr1fBW|gqhpQcRUJjQ z%+dMM7`#iaw^V7@aYzGVJY+Q56O_U!ghdDtHH<5)5Ph}A93)McLtDyK6f47wmTA4% zXeh%x%9<3p$CY8QUqRK6aQP>Y7yx?OngZDIZxw8UpJ?EKTNKP9o(e<>8&AAjcjO>F z3``&gIY~~96pbA*A;^}P<>Bq1LFpa{5Sop^0MU8y zeQ;kKh<)iPu~?oqykxO|9~r9jL1Z_>Lca_gwbb2!8W@Y z7^W;d5A;}vE~2R|9s?!xDP-r)zfI1lK7(XlT|-*C{qONC2U|h?B@~2N?laxCs>{dJ zvTC*0!W49E6=)fCyyjnw<?Z=H+58Xjo2n&rjD8r%>9@p2F1ejknk z^Z4KtU^@P44exAJg6d_6Z1Hf~Y@Q{nDr2}|fM3FV?<2q|b{Mu+n=N2_*4k^q{)Ai_ zrt~owk;kA^|9_yv$@5hreEgS3hSH1R16YvJnV@vW;}V?5{&84hIl}+0j2tGvoSUmvV_H=-S)^E(t5E{|Oh^vX{6+;(_6CFARnbMvmWd%6Q3W zS|?z<0nXUKFK}60S@5<@H{)i&rN7E&Vg-zw-&+4c^F%kZnFl^*yS>tGdK1PZ-LsqR znI%zQ&aVGpu-47=YQax&esJ=y?p{EKEz_gYW)7h!bZ z>};>m9I)69=+EmNgHYbFFR+`kXpuvgr zFjlZcNI6z(9;5npx#fxlK*AM7!)skZhg#5AFZ*xqAJ}jI6tF-}ii8A08Y6QQBil4G zVq}}x!1+lCUN`p|v5BpdzVzDB6DMDTOM&FpGp$vJk(;Kqr+{kOwD#fm;bbsBA)H}H zW1IcSqkbp#@=^bl56r=cHqJHa<}Y~5Preprf6}`qJWwX1ehlw~sTjPMVFgg^)z6}2 z;QSI9#ip@ejL$rPN_i20!+d|g!fXpVE!>qJU3++=dXob~&ROwkzy1Wj zC;Uk7Lf@iYzz5Ve)df%s=@%wmP&;HFh{%u_x^Stih+EKt9Mn84&(K01h3Zww zkcSj=fs{{f961cNTqhDAg*y@ZV)dGG+z=jwsWwi@pvJABL})<0&Zi47tHWJ#C+$+Y zl+3x3dA>BE&T!PnnVe<9MXFCR5j*-KbFVTHiTwz3G7kb*@k~|Zv+A!i`5R37`kmy& z5KNQc7jXG}g4mG(Sc=&({ExuOKAyin>ty%k9}?4H6-^RMS=tq!Z0B$Yipaj~IMKc}BBEv(Mf-o2|QhJGK*rU-e2j5R* z*z0Cw4A|^f3iPqMPTTYswa;mDRLp)3=9y9-!%J(N!`q}WkwfQ7V*(f`1(mDX93%TD za0?5~c0+tS&%qcKj>k{uKyNO5%)7|X6zsD-i+(r>OJ@`IauxK;?(*q%X{p+BtyzW% z4vJmBa=cz!_3GF91rw3D+b`LLcX_G-ZW~*YRGIT9R>cmf3oQ5wldm%QTTK2olV3s- z=3$eICOv>zf>gxM*NOOKsm5f%8cV^bq9t5PxuE_@yK{)Fahsw3&gP{aoH;z;0*LMh zY&WT{fT(W}rj7`4;ctZiS*&eo!yMDh%J-^p6knS|~`{RdJirAx>v2Oz6B*PhU_iuUqu zSX#aiFYgM5gSU~ysQ3=;W%~efVXhZOC;l?E%IZEp5U9P1G6s5TyG3O0vB0_E7mT!y z?JK;4*@v(1E%QqllyrFm5L*(Zj`1c?Q4x2^iN{{vZMBc}YHf;RLw!HNT8slSJb2tP?9cjQfT{jsjI zIY}`Mf@o@Ux6ZA9ANeWr8|+eQWsjQ{RhvTO=;mHvJzHnEmz*DRSZlPFecRW9HlNdL zbu+qFlnwO>q644=L6zb<#9^fAA4F6nDX11+L^*>Q8`cR0DY5;9~?CLG)8J zA(y7Z92rVAfFWLelB4zbMmVW!Vm?E*C%hzd=xYe`qOgd+Qn*Wa6j7A3Q55AY4}SEY zg?_1Lpa+A`=xdzr$kP(hDxwe~7GMCJ3|`sisCVqaJVFa{iqcIVj6oRbqvu=H)RQjdiaXh0!h zp{})R`;$b)$Wje^wb+mDCkySuaqimCb`)1uT3Trg&=a&1Rf({E*yd9B_3`F zvf-E>KCU(`0GZ6w0GrI>p8zAc#^4VYkeQt$I|C~@P(mxAMncV1gqmMQhJH&Ik}V(s zYX%NG=$DB4agf4YTuX^EJY!!8V67H*-<0(n#m# zLFu8xP3x4fP{da0$odQ~U|$m)h%Sh{mOa#t0Lx)Gq7vh+jH(@%V(RXVO|2=eq_V z)|S9f?h5xrFq9H7X*jkrBMuM7#lQgu9u%&Uiu_+}lh!6i$Tb<*IA}4pAO^h9wO0^m z11|GIkP|M08j9DQAH!z=5PSu~J!onNFNhotZ(;)7y2Z$y+k?G;YEJzl%uWCeeRq?2 z+3Oq3^*4MhCg=vw-~~@ zY1qnI;1pKpft|U6-tPFVJSt1+IsC~fJ6|&AOC#zGh8tE331}^^zRDaAAoWj}5ET@s zGQi1Xq9XD=kBSZts=dfi`x7(Rd-(^U_3h4|&Q4?xiy~Gfe}KZDEv9Fm0Qhryk@cmY`2EV=A_lq&~3Zw!Hy75ES@V82&ublr(MN;Ogv2>>l(n8Eo4G(ML~^M^)tQr|sI(@$j&diCyAb zs2zSMvGp0glVccGXYcSEbu4^><&g36l0D&EyEM)GOJwxukMwdq^p>c4fTUcW>%Gj} z;bqb!@iNYf?~s?BMn+^5I9g%br5QoM(S`Q_mj1(m1vvUJP1mPh$cSt)iYoSqv_7ZD`vh){>uQmH#4_BSs}HGm7A` zePK;$oLCrlkc*RrQ9;vsS+tXY+3%rjC!H62^YxyRgT*~iEm6ItTa?{bR&nn{x5;!_KRgpg`q;WWq4g5G!f z5-6Afvxo33ZoUn*ZS<5KI*1HG-<$Fzr%aKz4E;6QH3U)!rW2s*+ejioQXOHz&>Tk) zlyf2aB4mlvOrsIW&M`atlRG-lGO@9QVQ+>H;$epwQlu8-WF17a=pu2lyZU!bb|M)b zdhz^LIX_ajo*x51hUYlYdfOa(1T=*a07}e+7vmK)S=_{I#Gz&Ct=efmV|c?k9k@Vd z-sY5WVM?8Y$?ZxuOu&>g>CNUTnT-xYiQsCe)0iKOE%Dqam~_o6ruvXr3gIk-B7|Ce zPhzbj)*SGMC{Due9J&Y(SaA(*-s0egO0g$J7B~kK5o8b)A+mr8P^ME~WD+uYlSvX; z)X$)-!xc{=W59j}^D%H)>xK9@Xov*qi~BQKH-x13SvT?i4>;RDV)7rDByual5xoaGZXX$z=$tU>GCqK@o3QHhqbB%kKB6u81dZAG?Pn1< zC&7^w#3Sp#QmP${G==ADNEtyJ5ff$^kjN8Wn)Sp7XTY^~`FjAaX2qlpyRrd;` zo0C!j)XsQ}Vr5Co1zvA3@t4jPpGT8~R&pK@uX@nB$8Y91L{HGDFwhXL^uNa)@1axd zTYs3PbkPh0BQGx#N$B&0Miy-hhYV-Z>`W(N&~KUm0tt@Y&f)S;A?Xwc!JxMu-$R?z z08g22)xBb>d?YqizHVwWWkfSS*8>a}$dh9S_{dzuw^&?;?WfsmLICx460#Y6&y>P6 zbSm!y4F+QfSYzc=`U;88Gq3?}2Kc#pTPtim%zunxlUSI9yQ`DffZN@B9vPavJ{|=Kd`cL;x7-_mS|Z zgXL8P*Ys@vkYyuLfEPg>P7QrO8FZMR7*R zl%cmYHeGG0Reqt$m~1aLKSa}MHRnLC+%EMf6DshLxTgz}d{hwOmk0)OK!g6#9?#T@ z>dwv*iWEdbSpYGL(_S%foJn*E%K2a21UX0Zs_i2!O=Gtqq85|)*--!GYjHoz^P(=skaQ4a4hNM1? z5mGRbgH@pIZ+zTX|Fn$omL35XD*Gj=c?mTqaKT;$pZfYY)}O*CjA6*l`P7h35sb1u zr|zAZ5y{}xL;7~FzI{|tfto)L^`CnljzT>{==ix-gI^ejdHqODJDk#ah(CS}p@B~} z-TBHgegQ!`2(J$JCYxMjtPL7zO8Pd&*MvpD!V|+IJ{-dop*%iO14V*Usp~8pS@pa% z!VoAL+N<8RFs+*nkfTuIZ=vabXp z82fmfb+9gp>lT*jOUTnMjrc@hv#COeb96xA4w8mj_@coNg{3`y_Cx)wZjV?Xe1-_C zH>1LIdpe4f?Xze<9pFn5-G@PSj1b$*Vm=Pyz}RnkXdHZat$s(G&N5av1;KJ!?B2P# z`ST*A%R$1Q-ohooLxrg|4jM&!g*kkSbwO2@8*o|kqfy{(j76ctkF>&F zJ-8;(W{a&XzVBAzJ$Huec2+v4?&ehfCzG9Ui>sUf z95lDY$JIN&Tn?nfYkBSygu=nUkCl;ElG|;9U*c;wa~a5W7SROMn_zc0{F4E`xS%5# z@lGejTLdWpR`}E8hx{xX7g`{q)lwgWALwK2|DXxCJGif*RyZyIYoQF_cGD>PDL11( zgmyD@L!%{2zlg}k3=jhRkiH^`1IOFdSNRrQCw?V-SqIK(t>ecW@J1W_5gsZ*vBao> zv;zW0??-FI;=;B43_ki!=~}L^i&>-eaNNE>H_Q=INPmWCbqdb+fjPqMF3+6T`uCd{ z+0Dsli~Ug&{kzHj&1v+&8Zq)u%PM=L_2(Ci$gKZif5aW;^{qRO`-jPK5kT+-mXz`x z{B)9NsFfmpV#meo3*i_)xI&?{r*e^N%VCiG5TyT^9ln#`7ZtH;b)0dW^qa{q{5%xd zZY)9OIVt;bSiaKaPlDexo|P=AI40>~DaQwNLg+MZ=#wdjXw!~|uYm&zFxJtGyOTc& zrJ2A-*yp#I^pzrp^+vK*pV-4JS2xG_f*f2cs3*8Q=P#qhIPaHSw?wK#3{vdQ}GxQ&adQL5dO%u46IK$p2(6^mA*=5$HRt8 zfF^ec8r>1-a)|QF+M-NVQJMHd5916jp8)M^a{QGJ{FspbY8eiGpk7+tLX*Ui!p_)N z&6B2)NxCw`lnO~KHbC2bH--l0e?ymn#mG9i5fuVUpLG2BiET2>&YBTt(lcaC199Fo zI=A|AE)TU8T9YjP90X!QsVNzhD|HQg?&OrGJ}w5;|7%-v(qCq)6-R4O!y~WIg2gw0 zM?)+6GV_#2(ZiyN^yAnU{jMe>T2Z=Tbq-4pId1i=l0Ddmy40J-wI6D2N{{M_(KT(n zB%_`{Dn^>jo94Ai-R>n>)d@-QMVSdTHTpgL^y$SlHK&_jVW@`UKjF*L$H;;CBOEoQe_D($_wgY}pj;K=``d z`BcQ$#VU9WN@Wuv^ANCw%_ED?`}nI05|9r|#NdxKM4X$SzM;2R&m!xE+w%P8v0$J( ztr(RePK_FVb}+JF%&Og3LvDVF!=(K(D48b z`RGUeG@qyBY%H&}o7JE#od7jA}ljoU;iTIn$@gxwe))7&H z`~8IA2(zd3ueqGYZ1r!*O@aO<|Un9bXc XJ@HI--^6E(Wn52BEF%5!iDUlc3X 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%0DI}o1$O36-78?*k_ARqx_Yl6PO1YGus`Gzy0 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 D8F%5e literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_vendor/html5lib/__pycache__/_utils.cpython-39.pyc b/venv/Lib/site-packages/pip/_vendor/html5lib/__pycache__/_utils.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0709d4aac8b1106649cd2bccc59ba8aedc53677d GIT binary patch literal 4795 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 Ba7+LI literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_vendor/html5lib/__pycache__/serializer.cpython-39.pyc b/venv/Lib/site-packages/pip/_vendor/html5lib/__pycache__/serializer.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..083876b6b606d6ea83dd44b29c17ec59685905e0 GIT binary patch literal 10806 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 item[0] + rv = [] + i = 0 + while i < len(charList): + j = 1 + rv.append(charList[i]) + while i + j < len(charList) and charList[i + j][0] <= rv[-1][1] + 1: + rv[-1][1] = charList[i + j][1] + j += 1 + i += j + return rv + + +# We don't really support characters above the BMP :( +max_unicode = int("FFFF", 16) + + +def missingRanges(charList): + rv = [] + if charList[0] != 0: + rv.append([0, charList[0][0] - 1]) + for i, item in enumerate(charList[:-1]): + rv.append([item[1] + 1, charList[i + 1][0] - 1]) + if charList[-1][1] != max_unicode: + rv.append([charList[-1][1] + 1, max_unicode]) + return rv + + +def listToRegexpStr(charList): + rv = [] + for item in charList: + if item[0] == item[1]: + rv.append(escapeRegexp(chr(item[0]))) + else: + rv.append(escapeRegexp(chr(item[0])) + "-" + + escapeRegexp(chr(item[1]))) + return "[%s]" % "".join(rv) + + +def hexToInt(hex_str): + return int(hex_str, 16) + + +def escapeRegexp(string): + specialCharacters = (".", "^", "$", "*", "+", "?", "{", "}", + "[", "]", "|", "(", ")", "-") + for char in specialCharacters: + string = string.replace(char, "\\" + char) + + return string + +# output from the above +nonXmlNameBMPRegexp = re.compile('[\x00-,/:-@\\[-\\^`\\{-\xb6\xb8-\xbf\xd7\xf7\u0132-\u0133\u013f-\u0140\u0149\u017f\u01c4-\u01cc\u01f1-\u01f3\u01f6-\u01f9\u0218-\u024f\u02a9-\u02ba\u02c2-\u02cf\u02d2-\u02ff\u0346-\u035f\u0362-\u0385\u038b\u038d\u03a2\u03cf\u03d7-\u03d9\u03db\u03dd\u03df\u03e1\u03f4-\u0400\u040d\u0450\u045d\u0482\u0487-\u048f\u04c5-\u04c6\u04c9-\u04ca\u04cd-\u04cf\u04ec-\u04ed\u04f6-\u04f7\u04fa-\u0530\u0557-\u0558\u055a-\u0560\u0587-\u0590\u05a2\u05ba\u05be\u05c0\u05c3\u05c5-\u05cf\u05eb-\u05ef\u05f3-\u0620\u063b-\u063f\u0653-\u065f\u066a-\u066f\u06b8-\u06b9\u06bf\u06cf\u06d4\u06e9\u06ee-\u06ef\u06fa-\u0900\u0904\u093a-\u093b\u094e-\u0950\u0955-\u0957\u0964-\u0965\u0970-\u0980\u0984\u098d-\u098e\u0991-\u0992\u09a9\u09b1\u09b3-\u09b5\u09ba-\u09bb\u09bd\u09c5-\u09c6\u09c9-\u09ca\u09ce-\u09d6\u09d8-\u09db\u09de\u09e4-\u09e5\u09f2-\u0a01\u0a03-\u0a04\u0a0b-\u0a0e\u0a11-\u0a12\u0a29\u0a31\u0a34\u0a37\u0a3a-\u0a3b\u0a3d\u0a43-\u0a46\u0a49-\u0a4a\u0a4e-\u0a58\u0a5d\u0a5f-\u0a65\u0a75-\u0a80\u0a84\u0a8c\u0a8e\u0a92\u0aa9\u0ab1\u0ab4\u0aba-\u0abb\u0ac6\u0aca\u0ace-\u0adf\u0ae1-\u0ae5\u0af0-\u0b00\u0b04\u0b0d-\u0b0e\u0b11-\u0b12\u0b29\u0b31\u0b34-\u0b35\u0b3a-\u0b3b\u0b44-\u0b46\u0b49-\u0b4a\u0b4e-\u0b55\u0b58-\u0b5b\u0b5e\u0b62-\u0b65\u0b70-\u0b81\u0b84\u0b8b-\u0b8d\u0b91\u0b96-\u0b98\u0b9b\u0b9d\u0ba0-\u0ba2\u0ba5-\u0ba7\u0bab-\u0bad\u0bb6\u0bba-\u0bbd\u0bc3-\u0bc5\u0bc9\u0bce-\u0bd6\u0bd8-\u0be6\u0bf0-\u0c00\u0c04\u0c0d\u0c11\u0c29\u0c34\u0c3a-\u0c3d\u0c45\u0c49\u0c4e-\u0c54\u0c57-\u0c5f\u0c62-\u0c65\u0c70-\u0c81\u0c84\u0c8d\u0c91\u0ca9\u0cb4\u0cba-\u0cbd\u0cc5\u0cc9\u0cce-\u0cd4\u0cd7-\u0cdd\u0cdf\u0ce2-\u0ce5\u0cf0-\u0d01\u0d04\u0d0d\u0d11\u0d29\u0d3a-\u0d3d\u0d44-\u0d45\u0d49\u0d4e-\u0d56\u0d58-\u0d5f\u0d62-\u0d65\u0d70-\u0e00\u0e2f\u0e3b-\u0e3f\u0e4f\u0e5a-\u0e80\u0e83\u0e85-\u0e86\u0e89\u0e8b-\u0e8c\u0e8e-\u0e93\u0e98\u0ea0\u0ea4\u0ea6\u0ea8-\u0ea9\u0eac\u0eaf\u0eba\u0ebe-\u0ebf\u0ec5\u0ec7\u0ece-\u0ecf\u0eda-\u0f17\u0f1a-\u0f1f\u0f2a-\u0f34\u0f36\u0f38\u0f3a-\u0f3d\u0f48\u0f6a-\u0f70\u0f85\u0f8c-\u0f8f\u0f96\u0f98\u0fae-\u0fb0\u0fb8\u0fba-\u109f\u10c6-\u10cf\u10f7-\u10ff\u1101\u1104\u1108\u110a\u110d\u1113-\u113b\u113d\u113f\u1141-\u114b\u114d\u114f\u1151-\u1153\u1156-\u1158\u115a-\u115e\u1162\u1164\u1166\u1168\u116a-\u116c\u116f-\u1171\u1174\u1176-\u119d\u119f-\u11a7\u11a9-\u11aa\u11ac-\u11ad\u11b0-\u11b6\u11b9\u11bb\u11c3-\u11ea\u11ec-\u11ef\u11f1-\u11f8\u11fa-\u1dff\u1e9c-\u1e9f\u1efa-\u1eff\u1f16-\u1f17\u1f1e-\u1f1f\u1f46-\u1f47\u1f4e-\u1f4f\u1f58\u1f5a\u1f5c\u1f5e\u1f7e-\u1f7f\u1fb5\u1fbd\u1fbf-\u1fc1\u1fc5\u1fcd-\u1fcf\u1fd4-\u1fd5\u1fdc-\u1fdf\u1fed-\u1ff1\u1ff5\u1ffd-\u20cf\u20dd-\u20e0\u20e2-\u2125\u2127-\u2129\u212c-\u212d\u212f-\u217f\u2183-\u3004\u3006\u3008-\u3020\u3030\u3036-\u3040\u3095-\u3098\u309b-\u309c\u309f-\u30a0\u30fb\u30ff-\u3104\u312d-\u4dff\u9fa6-\uabff\ud7a4-\uffff]') # noqa + +nonXmlNameFirstBMPRegexp = re.compile('[\x00-@\\[-\\^`\\{-\xbf\xd7\xf7\u0132-\u0133\u013f-\u0140\u0149\u017f\u01c4-\u01cc\u01f1-\u01f3\u01f6-\u01f9\u0218-\u024f\u02a9-\u02ba\u02c2-\u0385\u0387\u038b\u038d\u03a2\u03cf\u03d7-\u03d9\u03db\u03dd\u03df\u03e1\u03f4-\u0400\u040d\u0450\u045d\u0482-\u048f\u04c5-\u04c6\u04c9-\u04ca\u04cd-\u04cf\u04ec-\u04ed\u04f6-\u04f7\u04fa-\u0530\u0557-\u0558\u055a-\u0560\u0587-\u05cf\u05eb-\u05ef\u05f3-\u0620\u063b-\u0640\u064b-\u0670\u06b8-\u06b9\u06bf\u06cf\u06d4\u06d6-\u06e4\u06e7-\u0904\u093a-\u093c\u093e-\u0957\u0962-\u0984\u098d-\u098e\u0991-\u0992\u09a9\u09b1\u09b3-\u09b5\u09ba-\u09db\u09de\u09e2-\u09ef\u09f2-\u0a04\u0a0b-\u0a0e\u0a11-\u0a12\u0a29\u0a31\u0a34\u0a37\u0a3a-\u0a58\u0a5d\u0a5f-\u0a71\u0a75-\u0a84\u0a8c\u0a8e\u0a92\u0aa9\u0ab1\u0ab4\u0aba-\u0abc\u0abe-\u0adf\u0ae1-\u0b04\u0b0d-\u0b0e\u0b11-\u0b12\u0b29\u0b31\u0b34-\u0b35\u0b3a-\u0b3c\u0b3e-\u0b5b\u0b5e\u0b62-\u0b84\u0b8b-\u0b8d\u0b91\u0b96-\u0b98\u0b9b\u0b9d\u0ba0-\u0ba2\u0ba5-\u0ba7\u0bab-\u0bad\u0bb6\u0bba-\u0c04\u0c0d\u0c11\u0c29\u0c34\u0c3a-\u0c5f\u0c62-\u0c84\u0c8d\u0c91\u0ca9\u0cb4\u0cba-\u0cdd\u0cdf\u0ce2-\u0d04\u0d0d\u0d11\u0d29\u0d3a-\u0d5f\u0d62-\u0e00\u0e2f\u0e31\u0e34-\u0e3f\u0e46-\u0e80\u0e83\u0e85-\u0e86\u0e89\u0e8b-\u0e8c\u0e8e-\u0e93\u0e98\u0ea0\u0ea4\u0ea6\u0ea8-\u0ea9\u0eac\u0eaf\u0eb1\u0eb4-\u0ebc\u0ebe-\u0ebf\u0ec5-\u0f3f\u0f48\u0f6a-\u109f\u10c6-\u10cf\u10f7-\u10ff\u1101\u1104\u1108\u110a\u110d\u1113-\u113b\u113d\u113f\u1141-\u114b\u114d\u114f\u1151-\u1153\u1156-\u1158\u115a-\u115e\u1162\u1164\u1166\u1168\u116a-\u116c\u116f-\u1171\u1174\u1176-\u119d\u119f-\u11a7\u11a9-\u11aa\u11ac-\u11ad\u11b0-\u11b6\u11b9\u11bb\u11c3-\u11ea\u11ec-\u11ef\u11f1-\u11f8\u11fa-\u1dff\u1e9c-\u1e9f\u1efa-\u1eff\u1f16-\u1f17\u1f1e-\u1f1f\u1f46-\u1f47\u1f4e-\u1f4f\u1f58\u1f5a\u1f5c\u1f5e\u1f7e-\u1f7f\u1fb5\u1fbd\u1fbf-\u1fc1\u1fc5\u1fcd-\u1fcf\u1fd4-\u1fd5\u1fdc-\u1fdf\u1fed-\u1ff1\u1ff5\u1ffd-\u2125\u2127-\u2129\u212c-\u212d\u212f-\u217f\u2183-\u3006\u3008-\u3020\u302a-\u3040\u3095-\u30a0\u30fb-\u3104\u312d-\u4dff\u9fa6-\uabff\ud7a4-\uffff]') # noqa + +# Simpler things +nonPubidCharRegexp = re.compile("[^\x20\x0D\x0Aa-zA-Z0-9\\-'()+,./:=?;!*#@$_%]") + + +class InfosetFilter(object): + replacementRegexp = re.compile(r"U[\dA-F]{5,5}") + + def __init__(self, + dropXmlnsLocalName=False, + dropXmlnsAttrNs=False, + preventDoubleDashComments=False, + preventDashAtCommentEnd=False, + replaceFormFeedCharacters=True, + preventSingleQuotePubid=False): + + self.dropXmlnsLocalName = dropXmlnsLocalName + self.dropXmlnsAttrNs = dropXmlnsAttrNs + + self.preventDoubleDashComments = preventDoubleDashComments + self.preventDashAtCommentEnd = preventDashAtCommentEnd + + self.replaceFormFeedCharacters = replaceFormFeedCharacters + + self.preventSingleQuotePubid = preventSingleQuotePubid + + self.replaceCache = {} + + def coerceAttribute(self, name, namespace=None): + if self.dropXmlnsLocalName and name.startswith("xmlns:"): + warnings.warn("Attributes cannot begin with xmlns", DataLossWarning) + return None + elif (self.dropXmlnsAttrNs and + namespace == "http://www.w3.org/2000/xmlns/"): + warnings.warn("Attributes cannot be in the xml namespace", DataLossWarning) + return None + else: + return self.toXmlName(name) + + def coerceElement(self, name): + return self.toXmlName(name) + + def coerceComment(self, data): + if self.preventDoubleDashComments: + while "--" in data: + warnings.warn("Comments cannot contain adjacent dashes", DataLossWarning) + data = data.replace("--", "- -") + if data.endswith("-"): + warnings.warn("Comments cannot end in a dash", DataLossWarning) + data += " " + return data + + def coerceCharacters(self, data): + if self.replaceFormFeedCharacters: + for _ in range(data.count("\x0C")): + warnings.warn("Text cannot contain U+000C", DataLossWarning) + data = data.replace("\x0C", " ") + # Other non-xml characters + return data + + def coercePubid(self, data): + dataOutput = data + for char in nonPubidCharRegexp.findall(data): + warnings.warn("Coercing non-XML pubid", DataLossWarning) + replacement = self.getReplacementCharacter(char) + dataOutput = dataOutput.replace(char, replacement) + if self.preventSingleQuotePubid and dataOutput.find("'") >= 0: + warnings.warn("Pubid cannot contain single quote", DataLossWarning) + dataOutput = dataOutput.replace("'", self.getReplacementCharacter("'")) + return dataOutput + + def toXmlName(self, name): + nameFirst = name[0] + nameRest = name[1:] + m = nonXmlNameFirstBMPRegexp.match(nameFirst) + if m: + warnings.warn("Coercing non-XML name: %s" % name, DataLossWarning) + nameFirstOutput = self.getReplacementCharacter(nameFirst) + else: + nameFirstOutput = nameFirst + + nameRestOutput = nameRest + replaceChars = set(nonXmlNameBMPRegexp.findall(nameRest)) + for char in replaceChars: + warnings.warn("Coercing non-XML name: %s" % name, DataLossWarning) + replacement = self.getReplacementCharacter(char) + nameRestOutput = nameRestOutput.replace(char, replacement) + return nameFirstOutput + nameRestOutput + + def getReplacementCharacter(self, char): + if char in self.replaceCache: + replacement = self.replaceCache[char] + else: + replacement = self.escapeChar(char) + return replacement + + def fromXmlName(self, name): + for item in set(self.replacementRegexp.findall(name)): + name = name.replace(item, self.unescapeChar(item)) + return name + + def escapeChar(self, char): + replacement = "U%05X" % ord(char) + self.replaceCache[char] = replacement + return replacement + + def unescapeChar(self, charcode): + return chr(int(charcode[1:], 16)) diff --git a/venv/Lib/site-packages/pip/_vendor/html5lib/_inputstream.py b/venv/Lib/site-packages/pip/_vendor/html5lib/_inputstream.py new file mode 100644 index 0000000..e0bb376 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/html5lib/_inputstream.py @@ -0,0 +1,918 @@ +from __future__ import absolute_import, division, unicode_literals + +from pip._vendor.six import text_type +from pip._vendor.six.moves import http_client, urllib + +import codecs +import re +from io import BytesIO, StringIO + +from pip._vendor import webencodings + +from .constants import EOF, spaceCharacters, asciiLetters, asciiUppercase +from .constants import _ReparseException +from . import _utils + +# Non-unicode versions of constants for use in the pre-parser +spaceCharactersBytes = frozenset([item.encode("ascii") for item in spaceCharacters]) +asciiLettersBytes = frozenset([item.encode("ascii") for item in asciiLetters]) +asciiUppercaseBytes = frozenset([item.encode("ascii") for item in asciiUppercase]) +spacesAngleBrackets = spaceCharactersBytes | frozenset([b">", b"<"]) + + +invalid_unicode_no_surrogate = "[\u0001-\u0008\u000B\u000E-\u001F\u007F-\u009F\uFDD0-\uFDEF\uFFFE\uFFFF\U0001FFFE\U0001FFFF\U0002FFFE\U0002FFFF\U0003FFFE\U0003FFFF\U0004FFFE\U0004FFFF\U0005FFFE\U0005FFFF\U0006FFFE\U0006FFFF\U0007FFFE\U0007FFFF\U0008FFFE\U0008FFFF\U0009FFFE\U0009FFFF\U000AFFFE\U000AFFFF\U000BFFFE\U000BFFFF\U000CFFFE\U000CFFFF\U000DFFFE\U000DFFFF\U000EFFFE\U000EFFFF\U000FFFFE\U000FFFFF\U0010FFFE\U0010FFFF]" # noqa + +if _utils.supports_lone_surrogates: + # Use one extra step of indirection and create surrogates with + # eval. Not using this indirection would introduce an illegal + # unicode literal on platforms not supporting such lone + # surrogates. + assert invalid_unicode_no_surrogate[-1] == "]" and invalid_unicode_no_surrogate.count("]") == 1 + invalid_unicode_re = re.compile(invalid_unicode_no_surrogate[:-1] + + eval('"\\uD800-\\uDFFF"') + # pylint:disable=eval-used + "]") +else: + invalid_unicode_re = re.compile(invalid_unicode_no_surrogate) + +non_bmp_invalid_codepoints = {0x1FFFE, 0x1FFFF, 0x2FFFE, 0x2FFFF, 0x3FFFE, + 0x3FFFF, 0x4FFFE, 0x4FFFF, 0x5FFFE, 0x5FFFF, + 0x6FFFE, 0x6FFFF, 0x7FFFE, 0x7FFFF, 0x8FFFE, + 0x8FFFF, 0x9FFFE, 0x9FFFF, 0xAFFFE, 0xAFFFF, + 0xBFFFE, 0xBFFFF, 0xCFFFE, 0xCFFFF, 0xDFFFE, + 0xDFFFF, 0xEFFFE, 0xEFFFF, 0xFFFFE, 0xFFFFF, + 0x10FFFE, 0x10FFFF} + +ascii_punctuation_re = re.compile("[\u0009-\u000D\u0020-\u002F\u003A-\u0040\u005C\u005B-\u0060\u007B-\u007E]") + +# Cache for charsUntil() +charsUntilRegEx = {} + + +class BufferedStream(object): + """Buffering for streams that do not have buffering of their own + + The buffer is implemented as a list of chunks on the assumption that + joining many strings will be slow since it is O(n**2) + """ + + def __init__(self, stream): + self.stream = stream + self.buffer = [] + self.position = [-1, 0] # chunk number, offset + + def tell(self): + pos = 0 + for chunk in self.buffer[:self.position[0]]: + pos += len(chunk) + pos += self.position[1] + return pos + + def seek(self, pos): + assert pos <= self._bufferedBytes() + offset = pos + i = 0 + while len(self.buffer[i]) < offset: + offset -= len(self.buffer[i]) + i += 1 + self.position = [i, offset] + + def read(self, bytes): + if not self.buffer: + return self._readStream(bytes) + elif (self.position[0] == len(self.buffer) and + self.position[1] == len(self.buffer[-1])): + return self._readStream(bytes) + else: + return self._readFromBuffer(bytes) + + def _bufferedBytes(self): + return sum([len(item) for item in self.buffer]) + + def _readStream(self, bytes): + data = self.stream.read(bytes) + self.buffer.append(data) + self.position[0] += 1 + self.position[1] = len(data) + return data + + def _readFromBuffer(self, bytes): + remainingBytes = bytes + rv = [] + bufferIndex = self.position[0] + bufferOffset = self.position[1] + while bufferIndex < len(self.buffer) and remainingBytes != 0: + assert remainingBytes > 0 + bufferedData = self.buffer[bufferIndex] + + if remainingBytes <= len(bufferedData) - bufferOffset: + bytesToRead = remainingBytes + self.position = [bufferIndex, bufferOffset + bytesToRead] + else: + bytesToRead = len(bufferedData) - bufferOffset + self.position = [bufferIndex, len(bufferedData)] + bufferIndex += 1 + rv.append(bufferedData[bufferOffset:bufferOffset + bytesToRead]) + remainingBytes -= bytesToRead + + bufferOffset = 0 + + if remainingBytes: + rv.append(self._readStream(remainingBytes)) + + return b"".join(rv) + + +def HTMLInputStream(source, **kwargs): + # Work around Python bug #20007: read(0) closes the connection. + # http://bugs.python.org/issue20007 + if (isinstance(source, http_client.HTTPResponse) or + # Also check for addinfourl wrapping HTTPResponse + (isinstance(source, urllib.response.addbase) and + isinstance(source.fp, http_client.HTTPResponse))): + isUnicode = False + elif hasattr(source, "read"): + isUnicode = isinstance(source.read(0), text_type) + else: + isUnicode = isinstance(source, text_type) + + if isUnicode: + encodings = [x for x in kwargs if x.endswith("_encoding")] + if encodings: + raise TypeError("Cannot set an encoding with a unicode input, set %r" % encodings) + + return HTMLUnicodeInputStream(source, **kwargs) + else: + return HTMLBinaryInputStream(source, **kwargs) + + +class HTMLUnicodeInputStream(object): + """Provides a unicode stream of characters to the HTMLTokenizer. + + This class takes care of character encoding and removing or replacing + incorrect byte-sequences and also provides column and line tracking. + + """ + + _defaultChunkSize = 10240 + + def __init__(self, source): + """Initialises the HTMLInputStream. + + HTMLInputStream(source, [encoding]) -> Normalized stream from source + for use by html5lib. + + source can be either a file-object, local filename or a string. + + 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) + + """ + + if not _utils.supports_lone_surrogates: + # Such platforms will have already checked for such + # surrogate errors, so no need to do this checking. + self.reportCharacterErrors = None + elif len("\U0010FFFF") == 1: + self.reportCharacterErrors = self.characterErrorsUCS4 + else: + self.reportCharacterErrors = self.characterErrorsUCS2 + + # List of where new lines occur + self.newLines = [0] + + self.charEncoding = (lookupEncoding("utf-8"), "certain") + self.dataStream = self.openStream(source) + + self.reset() + + def reset(self): + self.chunk = "" + self.chunkSize = 0 + self.chunkOffset = 0 + self.errors = [] + + # number of (complete) lines in previous chunks + self.prevNumLines = 0 + # number of columns in the last line of the previous chunk + self.prevNumCols = 0 + + # Deal with CR LF and surrogates split over chunk boundaries + self._bufferedCharacter = None + + def openStream(self, source): + """Produces a file object from source. + + source can be either a file object, local filename or a string. + + """ + # Already a file object + if hasattr(source, 'read'): + stream = source + else: + stream = StringIO(source) + + return stream + + def _position(self, offset): + chunk = self.chunk + nLines = chunk.count('\n', 0, offset) + positionLine = self.prevNumLines + nLines + lastLinePos = chunk.rfind('\n', 0, offset) + if lastLinePos == -1: + positionColumn = self.prevNumCols + offset + else: + positionColumn = offset - (lastLinePos + 1) + return (positionLine, positionColumn) + + def position(self): + """Returns (line, col) of the current position in the stream.""" + line, col = self._position(self.chunkOffset) + return (line + 1, col) + + def char(self): + """ Read one character from the stream or queue if available. Return + EOF when EOF is reached. + """ + # Read a new chunk from the input stream if necessary + if self.chunkOffset >= self.chunkSize: + if not self.readChunk(): + return EOF + + chunkOffset = self.chunkOffset + char = self.chunk[chunkOffset] + self.chunkOffset = chunkOffset + 1 + + return char + + def readChunk(self, chunkSize=None): + if chunkSize is None: + chunkSize = self._defaultChunkSize + + self.prevNumLines, self.prevNumCols = self._position(self.chunkSize) + + self.chunk = "" + self.chunkSize = 0 + self.chunkOffset = 0 + + data = self.dataStream.read(chunkSize) + + # Deal with CR LF and surrogates broken across chunks + if self._bufferedCharacter: + data = self._bufferedCharacter + data + self._bufferedCharacter = None + elif not data: + # We have no more data, bye-bye stream + return False + + if len(data) > 1: + lastv = ord(data[-1]) + if lastv == 0x0D or 0xD800 <= lastv <= 0xDBFF: + self._bufferedCharacter = data[-1] + data = data[:-1] + + if self.reportCharacterErrors: + self.reportCharacterErrors(data) + + # Replace invalid characters + data = data.replace("\r\n", "\n") + data = data.replace("\r", "\n") + + self.chunk = data + self.chunkSize = len(data) + + return True + + def characterErrorsUCS4(self, data): + for _ in range(len(invalid_unicode_re.findall(data))): + self.errors.append("invalid-codepoint") + + def characterErrorsUCS2(self, data): + # Someone picked the wrong compile option + # You lose + skip = False + for match in invalid_unicode_re.finditer(data): + if skip: + continue + codepoint = ord(match.group()) + pos = match.start() + # Pretty sure there should be endianness issues here + if _utils.isSurrogatePair(data[pos:pos + 2]): + # We have a surrogate pair! + char_val = _utils.surrogatePairToCodepoint(data[pos:pos + 2]) + if char_val in non_bmp_invalid_codepoints: + self.errors.append("invalid-codepoint") + skip = True + elif (codepoint >= 0xD800 and codepoint <= 0xDFFF and + pos == len(data) - 1): + self.errors.append("invalid-codepoint") + else: + skip = False + self.errors.append("invalid-codepoint") + + def charsUntil(self, characters, opposite=False): + """ Returns a string of characters from the stream up to but not + including any character in 'characters' or EOF. 'characters' must be + a container that supports the 'in' method and iteration over its + characters. + """ + + # Use a cache of regexps to find the required characters + try: + chars = charsUntilRegEx[(characters, opposite)] + except KeyError: + if __debug__: + for c in characters: + assert(ord(c) < 128) + regex = "".join(["\\x%02x" % ord(c) for c in characters]) + if not opposite: + regex = "^%s" % regex + chars = charsUntilRegEx[(characters, opposite)] = re.compile("[%s]+" % regex) + + rv = [] + + while True: + # Find the longest matching prefix + m = chars.match(self.chunk, self.chunkOffset) + if m is None: + # If nothing matched, and it wasn't because we ran out of chunk, + # then stop + if self.chunkOffset != self.chunkSize: + break + else: + end = m.end() + # If not the whole chunk matched, return everything + # up to the part that didn't match + if end != self.chunkSize: + rv.append(self.chunk[self.chunkOffset:end]) + self.chunkOffset = end + break + # If the whole remainder of the chunk matched, + # use it all and read the next chunk + rv.append(self.chunk[self.chunkOffset:]) + if not self.readChunk(): + # Reached EOF + break + + r = "".join(rv) + return r + + def unget(self, char): + # Only one character is allowed to be ungotten at once - it must + # be consumed again before any further call to unget + if char is not EOF: + if self.chunkOffset == 0: + # unget is called quite rarely, so it's a good idea to do + # more work here if it saves a bit of work in the frequently + # called char and charsUntil. + # So, just prepend the ungotten character onto the current + # chunk: + self.chunk = char + self.chunk + self.chunkSize += 1 + else: + self.chunkOffset -= 1 + assert self.chunk[self.chunkOffset] == char + + +class HTMLBinaryInputStream(HTMLUnicodeInputStream): + """Provides a unicode stream of characters to the HTMLTokenizer. + + This class takes care of character encoding and removing or replacing + incorrect byte-sequences and also provides column and line tracking. + + """ + + def __init__(self, source, override_encoding=None, transport_encoding=None, + same_origin_parent_encoding=None, likely_encoding=None, + default_encoding="windows-1252", useChardet=True): + """Initialises the HTMLInputStream. + + HTMLInputStream(source, [encoding]) -> Normalized stream from source + for use by html5lib. + + source can be either a file-object, local filename or a string. + + 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) + + """ + # Raw Stream - for unicode objects this will encode to utf-8 and set + # self.charEncoding as appropriate + self.rawStream = self.openStream(source) + + HTMLUnicodeInputStream.__init__(self, self.rawStream) + + # Encoding Information + # Number of bytes to use when looking for a meta element with + # encoding information + self.numBytesMeta = 1024 + # Number of bytes to use when using detecting encoding using chardet + self.numBytesChardet = 100 + # Things from args + self.override_encoding = override_encoding + self.transport_encoding = transport_encoding + self.same_origin_parent_encoding = same_origin_parent_encoding + self.likely_encoding = likely_encoding + self.default_encoding = default_encoding + + # Determine encoding + self.charEncoding = self.determineEncoding(useChardet) + assert self.charEncoding[0] is not None + + # Call superclass + self.reset() + + def reset(self): + self.dataStream = self.charEncoding[0].codec_info.streamreader(self.rawStream, 'replace') + HTMLUnicodeInputStream.reset(self) + + def openStream(self, source): + """Produces a file object from source. + + source can be either a file object, local filename or a string. + + """ + # Already a file object + if hasattr(source, 'read'): + stream = source + else: + stream = BytesIO(source) + + try: + stream.seek(stream.tell()) + except Exception: + stream = BufferedStream(stream) + + return stream + + def determineEncoding(self, chardet=True): + # BOMs take precedence over everything + # This will also read past the BOM if present + charEncoding = self.detectBOM(), "certain" + if charEncoding[0] is not None: + return charEncoding + + # If we've been overridden, we've been overridden + charEncoding = lookupEncoding(self.override_encoding), "certain" + if charEncoding[0] is not None: + return charEncoding + + # Now check the transport layer + charEncoding = lookupEncoding(self.transport_encoding), "certain" + if charEncoding[0] is not None: + return charEncoding + + # Look for meta elements with encoding information + charEncoding = self.detectEncodingMeta(), "tentative" + if charEncoding[0] is not None: + return charEncoding + + # Parent document encoding + charEncoding = lookupEncoding(self.same_origin_parent_encoding), "tentative" + if charEncoding[0] is not None and not charEncoding[0].name.startswith("utf-16"): + return charEncoding + + # "likely" encoding + charEncoding = lookupEncoding(self.likely_encoding), "tentative" + if charEncoding[0] is not None: + return charEncoding + + # Guess with chardet, if available + if chardet: + try: + from pip._vendor.chardet.universaldetector import UniversalDetector + except ImportError: + pass + else: + buffers = [] + detector = UniversalDetector() + while not detector.done: + buffer = self.rawStream.read(self.numBytesChardet) + assert isinstance(buffer, bytes) + if not buffer: + break + buffers.append(buffer) + detector.feed(buffer) + detector.close() + encoding = lookupEncoding(detector.result['encoding']) + self.rawStream.seek(0) + if encoding is not None: + return encoding, "tentative" + + # Try the default encoding + charEncoding = lookupEncoding(self.default_encoding), "tentative" + if charEncoding[0] is not None: + return charEncoding + + # Fallback to html5lib's default if even that hasn't worked + return lookupEncoding("windows-1252"), "tentative" + + def changeEncoding(self, newEncoding): + assert self.charEncoding[1] != "certain" + newEncoding = lookupEncoding(newEncoding) + if newEncoding is None: + return + if newEncoding.name in ("utf-16be", "utf-16le"): + newEncoding = lookupEncoding("utf-8") + assert newEncoding is not None + elif newEncoding == self.charEncoding[0]: + self.charEncoding = (self.charEncoding[0], "certain") + else: + self.rawStream.seek(0) + self.charEncoding = (newEncoding, "certain") + self.reset() + raise _ReparseException("Encoding changed from %s to %s" % (self.charEncoding[0], newEncoding)) + + def detectBOM(self): + """Attempts to detect at BOM at the start of the stream. If + an encoding can be determined from the BOM return the name of the + encoding otherwise return None""" + bomDict = { + codecs.BOM_UTF8: 'utf-8', + codecs.BOM_UTF16_LE: 'utf-16le', codecs.BOM_UTF16_BE: 'utf-16be', + codecs.BOM_UTF32_LE: 'utf-32le', codecs.BOM_UTF32_BE: 'utf-32be' + } + + # Go to beginning of file and read in 4 bytes + string = self.rawStream.read(4) + assert isinstance(string, bytes) + + # Try detecting the BOM using bytes from the string + encoding = bomDict.get(string[:3]) # UTF-8 + seek = 3 + if not encoding: + # Need to detect UTF-32 before UTF-16 + encoding = bomDict.get(string) # UTF-32 + seek = 4 + if not encoding: + encoding = bomDict.get(string[:2]) # UTF-16 + seek = 2 + + # Set the read position past the BOM if one was found, otherwise + # set it to the start of the stream + if encoding: + self.rawStream.seek(seek) + return lookupEncoding(encoding) + else: + self.rawStream.seek(0) + return None + + def detectEncodingMeta(self): + """Report the encoding declared by the meta element + """ + buffer = self.rawStream.read(self.numBytesMeta) + assert isinstance(buffer, bytes) + parser = EncodingParser(buffer) + self.rawStream.seek(0) + encoding = parser.getEncoding() + + if encoding is not None and encoding.name in ("utf-16be", "utf-16le"): + encoding = lookupEncoding("utf-8") + + return encoding + + +class EncodingBytes(bytes): + """String-like object with an associated position and various extra methods + If the position is ever greater than the string length then an exception is + raised""" + def __new__(self, value): + assert isinstance(value, bytes) + return bytes.__new__(self, value.lower()) + + def __init__(self, value): + # pylint:disable=unused-argument + self._position = -1 + + def __iter__(self): + return self + + def __next__(self): + p = self._position = self._position + 1 + if p >= len(self): + raise StopIteration + elif p < 0: + raise TypeError + return self[p:p + 1] + + def next(self): + # Py2 compat + return self.__next__() + + def previous(self): + p = self._position + if p >= len(self): + raise StopIteration + elif p < 0: + raise TypeError + self._position = p = p - 1 + return self[p:p + 1] + + def setPosition(self, position): + if self._position >= len(self): + raise StopIteration + self._position = position + + def getPosition(self): + if self._position >= len(self): + raise StopIteration + if self._position >= 0: + return self._position + else: + return None + + position = property(getPosition, setPosition) + + def getCurrentByte(self): + return self[self.position:self.position + 1] + + currentByte = property(getCurrentByte) + + def skip(self, chars=spaceCharactersBytes): + """Skip past a list of characters""" + p = self.position # use property for the error-checking + while p < len(self): + c = self[p:p + 1] + if c not in chars: + self._position = p + return c + p += 1 + self._position = p + return None + + def skipUntil(self, chars): + p = self.position + while p < len(self): + c = self[p:p + 1] + if c in chars: + self._position = p + return c + p += 1 + self._position = p + return None + + def matchBytes(self, bytes): + """Look for a sequence of bytes at the start of a string. If the bytes + are found return True and advance the position to the byte after the + match. Otherwise return False and leave the position alone""" + rv = self.startswith(bytes, self.position) + if rv: + self.position += len(bytes) + return rv + + def jumpTo(self, bytes): + """Look for the next sequence of bytes matching a given sequence. If + a match is found advance the position to the last byte of the match""" + try: + self._position = self.index(bytes, self.position) + len(bytes) - 1 + except ValueError: + raise StopIteration + return True + + +class EncodingParser(object): + """Mini parser for detecting character encoding from meta elements""" + + def __init__(self, data): + """string - the data to work on for encoding detection""" + self.data = EncodingBytes(data) + self.encoding = None + + def getEncoding(self): + if b"") + + def handleMeta(self): + if self.data.currentByte not in spaceCharactersBytes: + # if we have ") + + def getAttribute(self): + """Return a name,value pair for the next attribute in the stream, + if one is found, or None""" + data = self.data + # Step 1 (skip chars) + c = data.skip(spaceCharactersBytes | frozenset([b"/"])) + assert c is None or len(c) == 1 + # Step 2 + if c in (b">", None): + return None + # Step 3 + attrName = [] + attrValue = [] + # Step 4 attribute name + while True: + if c == b"=" and attrName: + break + elif c in spaceCharactersBytes: + # Step 6! + c = data.skip() + break + elif c in (b"/", b">"): + return b"".join(attrName), b"" + elif c in asciiUppercaseBytes: + attrName.append(c.lower()) + elif c is None: + return None + else: + attrName.append(c) + # Step 5 + c = next(data) + # Step 7 + if c != b"=": + data.previous() + return b"".join(attrName), b"" + # Step 8 + next(data) + # Step 9 + c = data.skip() + # Step 10 + if c in (b"'", b'"'): + # 10.1 + quoteChar = c + while True: + # 10.2 + c = next(data) + # 10.3 + if c == quoteChar: + next(data) + return b"".join(attrName), b"".join(attrValue) + # 10.4 + elif c in asciiUppercaseBytes: + attrValue.append(c.lower()) + # 10.5 + else: + attrValue.append(c) + elif c == b">": + return b"".join(attrName), b"" + elif c in asciiUppercaseBytes: + attrValue.append(c.lower()) + elif c is None: + return None + else: + attrValue.append(c) + # Step 11 + while True: + c = next(data) + if c in spacesAngleBrackets: + return b"".join(attrName), b"".join(attrValue) + elif c in asciiUppercaseBytes: + attrValue.append(c.lower()) + elif c is None: + return None + else: + attrValue.append(c) + + +class ContentAttrParser(object): + def __init__(self, data): + assert isinstance(data, bytes) + self.data = data + + def parse(self): + try: + # Check if the attr name is charset + # otherwise return + self.data.jumpTo(b"charset") + self.data.position += 1 + self.data.skip() + if not self.data.currentByte == b"=": + # If there is no = sign keep looking for attrs + return None + self.data.position += 1 + self.data.skip() + # Look for an encoding between matching quote marks + if self.data.currentByte in (b'"', b"'"): + quoteMark = self.data.currentByte + self.data.position += 1 + oldPosition = self.data.position + if self.data.jumpTo(quoteMark): + return self.data[oldPosition:self.data.position] + else: + return None + else: + # Unquoted value + oldPosition = self.data.position + try: + self.data.skipUntil(spaceCharactersBytes) + return self.data[oldPosition:self.data.position] + except StopIteration: + # Return the whole remaining value + return self.data[oldPosition:] + except StopIteration: + return None + + +def lookupEncoding(encoding): + """Return the python codec name corresponding to an encoding or None if the + string doesn't correspond to a valid encoding.""" + if isinstance(encoding, bytes): + try: + encoding = encoding.decode("ascii") + except UnicodeDecodeError: + return None + + if encoding is not None: + try: + return webencodings.lookup(encoding) + except AttributeError: + return None + else: + return None diff --git a/venv/Lib/site-packages/pip/_vendor/html5lib/_tokenizer.py b/venv/Lib/site-packages/pip/_vendor/html5lib/_tokenizer.py new file mode 100644 index 0000000..5f00253 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/html5lib/_tokenizer.py @@ -0,0 +1,1735 @@ +from __future__ import absolute_import, division, unicode_literals + +from pip._vendor.six import unichr as chr + +from collections import deque, OrderedDict +from sys import version_info + +from .constants import spaceCharacters +from .constants import entities +from .constants import asciiLetters, asciiUpper2Lower +from .constants import digits, hexDigits, EOF +from .constants import tokenTypes, tagTokenTypes +from .constants import replacementCharacters + +from ._inputstream import HTMLInputStream + +from ._trie import Trie + +entitiesTrie = Trie(entities) + +if version_info >= (3, 7): + attributeMap = dict +else: + attributeMap = OrderedDict + + +class HTMLTokenizer(object): + """ This class takes care of tokenizing HTML. + + * self.currentToken + Holds the token that is currently being processed. + + * self.state + Holds a reference to the method to be invoked... XXX + + * self.stream + Points to HTMLInputStream object. + """ + + def __init__(self, stream, parser=None, **kwargs): + + self.stream = HTMLInputStream(stream, **kwargs) + self.parser = parser + + # Setup the initial tokenizer state + self.escapeFlag = False + self.lastFourChars = [] + self.state = self.dataState + self.escape = False + + # The current token being created + self.currentToken = None + super(HTMLTokenizer, self).__init__() + + def __iter__(self): + """ This is where the magic happens. + + We do our usually processing through the states and when we have a token + to return we yield the token which pauses processing until the next token + is requested. + """ + self.tokenQueue = deque([]) + # Start processing. When EOF is reached self.state will return False + # instead of True and the loop will terminate. + while self.state(): + while self.stream.errors: + yield {"type": tokenTypes["ParseError"], "data": self.stream.errors.pop(0)} + while self.tokenQueue: + yield self.tokenQueue.popleft() + + def consumeNumberEntity(self, isHex): + """This function returns either U+FFFD or the character based on the + decimal or hexadecimal representation. It also discards ";" if present. + If not present self.tokenQueue.append({"type": tokenTypes["ParseError"]}) is invoked. + """ + + allowed = digits + radix = 10 + if isHex: + allowed = hexDigits + radix = 16 + + charStack = [] + + # Consume all the characters that are in range while making sure we + # don't hit an EOF. + c = self.stream.char() + while c in allowed and c is not EOF: + charStack.append(c) + c = self.stream.char() + + # Convert the set of characters consumed to an int. + charAsInt = int("".join(charStack), radix) + + # Certain characters get replaced with others + if charAsInt in replacementCharacters: + char = replacementCharacters[charAsInt] + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "illegal-codepoint-for-numeric-entity", + "datavars": {"charAsInt": charAsInt}}) + elif ((0xD800 <= charAsInt <= 0xDFFF) or + (charAsInt > 0x10FFFF)): + char = "\uFFFD" + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "illegal-codepoint-for-numeric-entity", + "datavars": {"charAsInt": charAsInt}}) + else: + # Should speed up this check somehow (e.g. move the set to a constant) + if ((0x0001 <= charAsInt <= 0x0008) or + (0x000E <= charAsInt <= 0x001F) or + (0x007F <= charAsInt <= 0x009F) or + (0xFDD0 <= charAsInt <= 0xFDEF) or + charAsInt in frozenset([0x000B, 0xFFFE, 0xFFFF, 0x1FFFE, + 0x1FFFF, 0x2FFFE, 0x2FFFF, 0x3FFFE, + 0x3FFFF, 0x4FFFE, 0x4FFFF, 0x5FFFE, + 0x5FFFF, 0x6FFFE, 0x6FFFF, 0x7FFFE, + 0x7FFFF, 0x8FFFE, 0x8FFFF, 0x9FFFE, + 0x9FFFF, 0xAFFFE, 0xAFFFF, 0xBFFFE, + 0xBFFFF, 0xCFFFE, 0xCFFFF, 0xDFFFE, + 0xDFFFF, 0xEFFFE, 0xEFFFF, 0xFFFFE, + 0xFFFFF, 0x10FFFE, 0x10FFFF])): + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": + "illegal-codepoint-for-numeric-entity", + "datavars": {"charAsInt": charAsInt}}) + try: + # Try/except needed as UCS-2 Python builds' unichar only works + # within the BMP. + char = chr(charAsInt) + except ValueError: + v = charAsInt - 0x10000 + char = chr(0xD800 | (v >> 10)) + chr(0xDC00 | (v & 0x3FF)) + + # Discard the ; if present. Otherwise, put it back on the queue and + # invoke parseError on parser. + if c != ";": + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "numeric-entity-without-semicolon"}) + self.stream.unget(c) + + return char + + def consumeEntity(self, allowedChar=None, fromAttribute=False): + # Initialise to the default output for when no entity is matched + output = "&" + + charStack = [self.stream.char()] + if (charStack[0] in spaceCharacters or charStack[0] in (EOF, "<", "&") or + (allowedChar is not None and allowedChar == charStack[0])): + self.stream.unget(charStack[0]) + + elif charStack[0] == "#": + # Read the next character to see if it's hex or decimal + hex = False + charStack.append(self.stream.char()) + if charStack[-1] in ("x", "X"): + hex = True + charStack.append(self.stream.char()) + + # charStack[-1] should be the first digit + if (hex and charStack[-1] in hexDigits) \ + or (not hex and charStack[-1] in digits): + # At least one digit found, so consume the whole number + self.stream.unget(charStack[-1]) + output = self.consumeNumberEntity(hex) + else: + # No digits found + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "expected-numeric-entity"}) + self.stream.unget(charStack.pop()) + output = "&" + "".join(charStack) + + else: + # At this point in the process might have named entity. Entities + # are stored in the global variable "entities". + # + # Consume characters and compare to these to a substring of the + # entity names in the list until the substring no longer matches. + while (charStack[-1] is not EOF): + if not entitiesTrie.has_keys_with_prefix("".join(charStack)): + break + charStack.append(self.stream.char()) + + # At this point we have a string that starts with some characters + # that may match an entity + # Try to find the longest entity the string will match to take care + # of ¬i for instance. + try: + entityName = entitiesTrie.longest_prefix("".join(charStack[:-1])) + entityLength = len(entityName) + except KeyError: + entityName = None + + if entityName is not None: + if entityName[-1] != ";": + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "named-entity-without-semicolon"}) + if (entityName[-1] != ";" and fromAttribute and + (charStack[entityLength] in asciiLetters or + charStack[entityLength] in digits or + charStack[entityLength] == "=")): + self.stream.unget(charStack.pop()) + output = "&" + "".join(charStack) + else: + output = entities[entityName] + self.stream.unget(charStack.pop()) + output += "".join(charStack[entityLength:]) + else: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "expected-named-entity"}) + self.stream.unget(charStack.pop()) + output = "&" + "".join(charStack) + + if fromAttribute: + self.currentToken["data"][-1][1] += output + else: + if output in spaceCharacters: + tokenType = "SpaceCharacters" + else: + tokenType = "Characters" + self.tokenQueue.append({"type": tokenTypes[tokenType], "data": output}) + + def processEntityInAttribute(self, allowedChar): + """This method replaces the need for "entityInAttributeValueState". + """ + self.consumeEntity(allowedChar=allowedChar, fromAttribute=True) + + def emitCurrentToken(self): + """This method is a generic handler for emitting the tags. It also sets + the state to "data" because that's what's needed after a token has been + emitted. + """ + token = self.currentToken + # Add token to the queue to be yielded + if (token["type"] in tagTokenTypes): + token["name"] = token["name"].translate(asciiUpper2Lower) + if token["type"] == tokenTypes["StartTag"]: + raw = token["data"] + data = attributeMap(raw) + if len(raw) > len(data): + # we had some duplicated attribute, fix so first wins + data.update(raw[::-1]) + token["data"] = data + + if token["type"] == tokenTypes["EndTag"]: + if token["data"]: + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "attributes-in-end-tag"}) + if token["selfClosing"]: + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "self-closing-flag-on-end-tag"}) + self.tokenQueue.append(token) + self.state = self.dataState + + # Below are the various tokenizer states worked out. + def dataState(self): + data = self.stream.char() + if data == "&": + self.state = self.entityDataState + elif data == "<": + self.state = self.tagOpenState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.tokenQueue.append({"type": tokenTypes["Characters"], + "data": "\u0000"}) + elif data is EOF: + # Tokenization ends. + return False + elif data in spaceCharacters: + # Directly after emitting a token you switch back to the "data + # state". At that point spaceCharacters are important so they are + # emitted separately. + self.tokenQueue.append({"type": tokenTypes["SpaceCharacters"], "data": + data + self.stream.charsUntil(spaceCharacters, True)}) + # No need to update lastFourChars here, since the first space will + # have already been appended to lastFourChars and will have broken + # any sequences + else: + chars = self.stream.charsUntil(("&", "<", "\u0000")) + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": + data + chars}) + return True + + def entityDataState(self): + self.consumeEntity() + self.state = self.dataState + return True + + def rcdataState(self): + data = self.stream.char() + if data == "&": + self.state = self.characterReferenceInRcdata + elif data == "<": + self.state = self.rcdataLessThanSignState + elif data == EOF: + # Tokenization ends. + return False + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.tokenQueue.append({"type": tokenTypes["Characters"], + "data": "\uFFFD"}) + elif data in spaceCharacters: + # Directly after emitting a token you switch back to the "data + # state". At that point spaceCharacters are important so they are + # emitted separately. + self.tokenQueue.append({"type": tokenTypes["SpaceCharacters"], "data": + data + self.stream.charsUntil(spaceCharacters, True)}) + # No need to update lastFourChars here, since the first space will + # have already been appended to lastFourChars and will have broken + # any sequences + else: + chars = self.stream.charsUntil(("&", "<", "\u0000")) + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": + data + chars}) + return True + + def characterReferenceInRcdata(self): + self.consumeEntity() + self.state = self.rcdataState + return True + + def rawtextState(self): + data = self.stream.char() + if data == "<": + self.state = self.rawtextLessThanSignState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.tokenQueue.append({"type": tokenTypes["Characters"], + "data": "\uFFFD"}) + elif data == EOF: + # Tokenization ends. + return False + else: + chars = self.stream.charsUntil(("<", "\u0000")) + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": + data + chars}) + return True + + def scriptDataState(self): + data = self.stream.char() + if data == "<": + self.state = self.scriptDataLessThanSignState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.tokenQueue.append({"type": tokenTypes["Characters"], + "data": "\uFFFD"}) + elif data == EOF: + # Tokenization ends. + return False + else: + chars = self.stream.charsUntil(("<", "\u0000")) + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": + data + chars}) + return True + + def plaintextState(self): + data = self.stream.char() + if data == EOF: + # Tokenization ends. + return False + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.tokenQueue.append({"type": tokenTypes["Characters"], + "data": "\uFFFD"}) + else: + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": + data + self.stream.charsUntil("\u0000")}) + return True + + def tagOpenState(self): + data = self.stream.char() + if data == "!": + self.state = self.markupDeclarationOpenState + elif data == "/": + self.state = self.closeTagOpenState + elif data in asciiLetters: + self.currentToken = {"type": tokenTypes["StartTag"], + "name": data, "data": [], + "selfClosing": False, + "selfClosingAcknowledged": False} + self.state = self.tagNameState + elif data == ">": + # XXX In theory it could be something besides a tag name. But + # do we really care? + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "expected-tag-name-but-got-right-bracket"}) + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "<>"}) + self.state = self.dataState + elif data == "?": + # XXX In theory it could be something besides a tag name. But + # do we really care? + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "expected-tag-name-but-got-question-mark"}) + self.stream.unget(data) + self.state = self.bogusCommentState + else: + # XXX + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "expected-tag-name"}) + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "<"}) + self.stream.unget(data) + self.state = self.dataState + return True + + def closeTagOpenState(self): + data = self.stream.char() + if data in asciiLetters: + self.currentToken = {"type": tokenTypes["EndTag"], "name": data, + "data": [], "selfClosing": False} + self.state = self.tagNameState + elif data == ">": + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "expected-closing-tag-but-got-right-bracket"}) + self.state = self.dataState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "expected-closing-tag-but-got-eof"}) + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "": + self.emitCurrentToken() + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-tag-name"}) + self.state = self.dataState + elif data == "/": + self.state = self.selfClosingStartTagState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["name"] += "\uFFFD" + else: + self.currentToken["name"] += data + # (Don't use charsUntil here, because tag names are + # very short and it's faster to not do anything fancy) + return True + + def rcdataLessThanSignState(self): + data = self.stream.char() + if data == "/": + self.temporaryBuffer = "" + self.state = self.rcdataEndTagOpenState + else: + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "<"}) + self.stream.unget(data) + self.state = self.rcdataState + return True + + def rcdataEndTagOpenState(self): + data = self.stream.char() + if data in asciiLetters: + self.temporaryBuffer += data + self.state = self.rcdataEndTagNameState + else: + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "" and appropriate: + self.currentToken = {"type": tokenTypes["EndTag"], + "name": self.temporaryBuffer, + "data": [], "selfClosing": False} + self.emitCurrentToken() + self.state = self.dataState + elif data in asciiLetters: + self.temporaryBuffer += data + else: + self.tokenQueue.append({"type": tokenTypes["Characters"], + "data": "" and appropriate: + self.currentToken = {"type": tokenTypes["EndTag"], + "name": self.temporaryBuffer, + "data": [], "selfClosing": False} + self.emitCurrentToken() + self.state = self.dataState + elif data in asciiLetters: + self.temporaryBuffer += data + else: + self.tokenQueue.append({"type": tokenTypes["Characters"], + "data": "" and appropriate: + self.currentToken = {"type": tokenTypes["EndTag"], + "name": self.temporaryBuffer, + "data": [], "selfClosing": False} + self.emitCurrentToken() + self.state = self.dataState + elif data in asciiLetters: + self.temporaryBuffer += data + else: + self.tokenQueue.append({"type": tokenTypes["Characters"], + "data": "": + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": ">"}) + self.state = self.scriptDataState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.tokenQueue.append({"type": tokenTypes["Characters"], + "data": "\uFFFD"}) + self.state = self.scriptDataEscapedState + elif data == EOF: + self.state = self.dataState + else: + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": data}) + self.state = self.scriptDataEscapedState + return True + + def scriptDataEscapedLessThanSignState(self): + data = self.stream.char() + if data == "/": + self.temporaryBuffer = "" + self.state = self.scriptDataEscapedEndTagOpenState + elif data in asciiLetters: + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "<" + data}) + self.temporaryBuffer = data + self.state = self.scriptDataDoubleEscapeStartState + else: + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "<"}) + self.stream.unget(data) + self.state = self.scriptDataEscapedState + return True + + def scriptDataEscapedEndTagOpenState(self): + data = self.stream.char() + if data in asciiLetters: + self.temporaryBuffer = data + self.state = self.scriptDataEscapedEndTagNameState + else: + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "" and appropriate: + self.currentToken = {"type": tokenTypes["EndTag"], + "name": self.temporaryBuffer, + "data": [], "selfClosing": False} + self.emitCurrentToken() + self.state = self.dataState + elif data in asciiLetters: + self.temporaryBuffer += data + else: + self.tokenQueue.append({"type": tokenTypes["Characters"], + "data": ""))): + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": data}) + if self.temporaryBuffer.lower() == "script": + self.state = self.scriptDataDoubleEscapedState + else: + self.state = self.scriptDataEscapedState + elif data in asciiLetters: + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": data}) + self.temporaryBuffer += data + else: + self.stream.unget(data) + self.state = self.scriptDataEscapedState + return True + + def scriptDataDoubleEscapedState(self): + data = self.stream.char() + if data == "-": + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "-"}) + self.state = self.scriptDataDoubleEscapedDashState + elif data == "<": + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "<"}) + self.state = self.scriptDataDoubleEscapedLessThanSignState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.tokenQueue.append({"type": tokenTypes["Characters"], + "data": "\uFFFD"}) + elif data == EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-script-in-script"}) + self.state = self.dataState + else: + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": data}) + return True + + def scriptDataDoubleEscapedDashState(self): + data = self.stream.char() + if data == "-": + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "-"}) + self.state = self.scriptDataDoubleEscapedDashDashState + elif data == "<": + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "<"}) + self.state = self.scriptDataDoubleEscapedLessThanSignState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.tokenQueue.append({"type": tokenTypes["Characters"], + "data": "\uFFFD"}) + self.state = self.scriptDataDoubleEscapedState + elif data == EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-script-in-script"}) + self.state = self.dataState + else: + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": data}) + self.state = self.scriptDataDoubleEscapedState + return True + + def scriptDataDoubleEscapedDashDashState(self): + data = self.stream.char() + if data == "-": + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "-"}) + elif data == "<": + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "<"}) + self.state = self.scriptDataDoubleEscapedLessThanSignState + elif data == ">": + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": ">"}) + self.state = self.scriptDataState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.tokenQueue.append({"type": tokenTypes["Characters"], + "data": "\uFFFD"}) + self.state = self.scriptDataDoubleEscapedState + elif data == EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-script-in-script"}) + self.state = self.dataState + else: + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": data}) + self.state = self.scriptDataDoubleEscapedState + return True + + def scriptDataDoubleEscapedLessThanSignState(self): + data = self.stream.char() + if data == "/": + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": "/"}) + self.temporaryBuffer = "" + self.state = self.scriptDataDoubleEscapeEndState + else: + self.stream.unget(data) + self.state = self.scriptDataDoubleEscapedState + return True + + def scriptDataDoubleEscapeEndState(self): + data = self.stream.char() + if data in (spaceCharacters | frozenset(("/", ">"))): + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": data}) + if self.temporaryBuffer.lower() == "script": + self.state = self.scriptDataEscapedState + else: + self.state = self.scriptDataDoubleEscapedState + elif data in asciiLetters: + self.tokenQueue.append({"type": tokenTypes["Characters"], "data": data}) + self.temporaryBuffer += data + else: + self.stream.unget(data) + self.state = self.scriptDataDoubleEscapedState + return True + + def beforeAttributeNameState(self): + data = self.stream.char() + if data in spaceCharacters: + self.stream.charsUntil(spaceCharacters, True) + elif data in asciiLetters: + self.currentToken["data"].append([data, ""]) + self.state = self.attributeNameState + elif data == ">": + self.emitCurrentToken() + elif data == "/": + self.state = self.selfClosingStartTagState + elif data in ("'", '"', "=", "<"): + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "invalid-character-in-attribute-name"}) + self.currentToken["data"].append([data, ""]) + self.state = self.attributeNameState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["data"].append(["\uFFFD", ""]) + self.state = self.attributeNameState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "expected-attribute-name-but-got-eof"}) + self.state = self.dataState + else: + self.currentToken["data"].append([data, ""]) + self.state = self.attributeNameState + return True + + def attributeNameState(self): + data = self.stream.char() + leavingThisState = True + emitToken = False + if data == "=": + self.state = self.beforeAttributeValueState + elif data in asciiLetters: + self.currentToken["data"][-1][0] += data +\ + self.stream.charsUntil(asciiLetters, True) + leavingThisState = False + elif data == ">": + # XXX If we emit here the attributes are converted to a dict + # without being checked and when the code below runs we error + # because data is a dict not a list + emitToken = True + elif data in spaceCharacters: + self.state = self.afterAttributeNameState + elif data == "/": + self.state = self.selfClosingStartTagState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["data"][-1][0] += "\uFFFD" + leavingThisState = False + elif data in ("'", '"', "<"): + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": + "invalid-character-in-attribute-name"}) + self.currentToken["data"][-1][0] += data + leavingThisState = False + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "eof-in-attribute-name"}) + self.state = self.dataState + else: + self.currentToken["data"][-1][0] += data + leavingThisState = False + + if leavingThisState: + # Attributes are not dropped at this stage. That happens when the + # start tag token is emitted so values can still be safely appended + # to attributes, but we do want to report the parse error in time. + self.currentToken["data"][-1][0] = ( + self.currentToken["data"][-1][0].translate(asciiUpper2Lower)) + for name, _ in self.currentToken["data"][:-1]: + if self.currentToken["data"][-1][0] == name: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "duplicate-attribute"}) + break + # XXX Fix for above XXX + if emitToken: + self.emitCurrentToken() + return True + + def afterAttributeNameState(self): + data = self.stream.char() + if data in spaceCharacters: + self.stream.charsUntil(spaceCharacters, True) + elif data == "=": + self.state = self.beforeAttributeValueState + elif data == ">": + self.emitCurrentToken() + elif data in asciiLetters: + self.currentToken["data"].append([data, ""]) + self.state = self.attributeNameState + elif data == "/": + self.state = self.selfClosingStartTagState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["data"].append(["\uFFFD", ""]) + self.state = self.attributeNameState + elif data in ("'", '"', "<"): + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "invalid-character-after-attribute-name"}) + self.currentToken["data"].append([data, ""]) + self.state = self.attributeNameState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "expected-end-of-tag-but-got-eof"}) + self.state = self.dataState + else: + self.currentToken["data"].append([data, ""]) + self.state = self.attributeNameState + return True + + def beforeAttributeValueState(self): + data = self.stream.char() + if data in spaceCharacters: + self.stream.charsUntil(spaceCharacters, True) + elif data == "\"": + self.state = self.attributeValueDoubleQuotedState + elif data == "&": + self.state = self.attributeValueUnQuotedState + self.stream.unget(data) + elif data == "'": + self.state = self.attributeValueSingleQuotedState + elif data == ">": + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "expected-attribute-value-but-got-right-bracket"}) + self.emitCurrentToken() + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["data"][-1][1] += "\uFFFD" + self.state = self.attributeValueUnQuotedState + elif data in ("=", "<", "`"): + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "equals-in-unquoted-attribute-value"}) + self.currentToken["data"][-1][1] += data + self.state = self.attributeValueUnQuotedState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "expected-attribute-value-but-got-eof"}) + self.state = self.dataState + else: + self.currentToken["data"][-1][1] += data + self.state = self.attributeValueUnQuotedState + return True + + def attributeValueDoubleQuotedState(self): + data = self.stream.char() + if data == "\"": + self.state = self.afterAttributeValueState + elif data == "&": + self.processEntityInAttribute('"') + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["data"][-1][1] += "\uFFFD" + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-attribute-value-double-quote"}) + self.state = self.dataState + else: + self.currentToken["data"][-1][1] += data +\ + self.stream.charsUntil(("\"", "&", "\u0000")) + return True + + def attributeValueSingleQuotedState(self): + data = self.stream.char() + if data == "'": + self.state = self.afterAttributeValueState + elif data == "&": + self.processEntityInAttribute("'") + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["data"][-1][1] += "\uFFFD" + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-attribute-value-single-quote"}) + self.state = self.dataState + else: + self.currentToken["data"][-1][1] += data +\ + self.stream.charsUntil(("'", "&", "\u0000")) + return True + + def attributeValueUnQuotedState(self): + data = self.stream.char() + if data in spaceCharacters: + self.state = self.beforeAttributeNameState + elif data == "&": + self.processEntityInAttribute(">") + elif data == ">": + self.emitCurrentToken() + elif data in ('"', "'", "=", "<", "`"): + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-character-in-unquoted-attribute-value"}) + self.currentToken["data"][-1][1] += data + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["data"][-1][1] += "\uFFFD" + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-attribute-value-no-quotes"}) + self.state = self.dataState + else: + self.currentToken["data"][-1][1] += data + self.stream.charsUntil( + frozenset(("&", ">", '"', "'", "=", "<", "`", "\u0000")) | spaceCharacters) + return True + + def afterAttributeValueState(self): + data = self.stream.char() + if data in spaceCharacters: + self.state = self.beforeAttributeNameState + elif data == ">": + self.emitCurrentToken() + elif data == "/": + self.state = self.selfClosingStartTagState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-EOF-after-attribute-value"}) + self.stream.unget(data) + self.state = self.dataState + else: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-character-after-attribute-value"}) + self.stream.unget(data) + self.state = self.beforeAttributeNameState + return True + + def selfClosingStartTagState(self): + data = self.stream.char() + if data == ">": + self.currentToken["selfClosing"] = True + self.emitCurrentToken() + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": + "unexpected-EOF-after-solidus-in-tag"}) + self.stream.unget(data) + self.state = self.dataState + else: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-character-after-solidus-in-tag"}) + self.stream.unget(data) + self.state = self.beforeAttributeNameState + return True + + def bogusCommentState(self): + # Make a new comment token and give it as value all the characters + # until the first > or EOF (charsUntil checks for EOF automatically) + # and emit it. + data = self.stream.charsUntil(">") + data = data.replace("\u0000", "\uFFFD") + self.tokenQueue.append( + {"type": tokenTypes["Comment"], "data": data}) + + # Eat the character directly after the bogus comment which is either a + # ">" or an EOF. + self.stream.char() + self.state = self.dataState + return True + + def markupDeclarationOpenState(self): + charStack = [self.stream.char()] + if charStack[-1] == "-": + charStack.append(self.stream.char()) + if charStack[-1] == "-": + self.currentToken = {"type": tokenTypes["Comment"], "data": ""} + self.state = self.commentStartState + return True + elif charStack[-1] in ('d', 'D'): + matched = True + for expected in (('o', 'O'), ('c', 'C'), ('t', 'T'), + ('y', 'Y'), ('p', 'P'), ('e', 'E')): + charStack.append(self.stream.char()) + if charStack[-1] not in expected: + matched = False + break + if matched: + self.currentToken = {"type": tokenTypes["Doctype"], + "name": "", + "publicId": None, "systemId": None, + "correct": True} + self.state = self.doctypeState + return True + elif (charStack[-1] == "[" and + self.parser is not None and + self.parser.tree.openElements and + self.parser.tree.openElements[-1].namespace != self.parser.tree.defaultNamespace): + matched = True + for expected in ["C", "D", "A", "T", "A", "["]: + charStack.append(self.stream.char()) + if charStack[-1] != expected: + matched = False + break + if matched: + self.state = self.cdataSectionState + return True + + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "expected-dashes-or-doctype"}) + + while charStack: + self.stream.unget(charStack.pop()) + self.state = self.bogusCommentState + return True + + def commentStartState(self): + data = self.stream.char() + if data == "-": + self.state = self.commentStartDashState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["data"] += "\uFFFD" + elif data == ">": + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "incorrect-comment"}) + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-comment"}) + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.currentToken["data"] += data + self.state = self.commentState + return True + + def commentStartDashState(self): + data = self.stream.char() + if data == "-": + self.state = self.commentEndState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["data"] += "-\uFFFD" + elif data == ">": + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "incorrect-comment"}) + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-comment"}) + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.currentToken["data"] += "-" + data + self.state = self.commentState + return True + + def commentState(self): + data = self.stream.char() + if data == "-": + self.state = self.commentEndDashState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["data"] += "\uFFFD" + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "eof-in-comment"}) + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.currentToken["data"] += data + \ + self.stream.charsUntil(("-", "\u0000")) + return True + + def commentEndDashState(self): + data = self.stream.char() + if data == "-": + self.state = self.commentEndState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["data"] += "-\uFFFD" + self.state = self.commentState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-comment-end-dash"}) + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.currentToken["data"] += "-" + data + self.state = self.commentState + return True + + def commentEndState(self): + data = self.stream.char() + if data == ">": + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["data"] += "--\uFFFD" + self.state = self.commentState + elif data == "!": + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-bang-after-double-dash-in-comment"}) + self.state = self.commentEndBangState + elif data == "-": + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-dash-after-double-dash-in-comment"}) + self.currentToken["data"] += data + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-comment-double-dash"}) + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + # XXX + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-char-in-comment"}) + self.currentToken["data"] += "--" + data + self.state = self.commentState + return True + + def commentEndBangState(self): + data = self.stream.char() + if data == ">": + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + elif data == "-": + self.currentToken["data"] += "--!" + self.state = self.commentEndDashState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["data"] += "--!\uFFFD" + self.state = self.commentState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-comment-end-bang-state"}) + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.currentToken["data"] += "--!" + data + self.state = self.commentState + return True + + def doctypeState(self): + data = self.stream.char() + if data in spaceCharacters: + self.state = self.beforeDoctypeNameState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "expected-doctype-name-but-got-eof"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "need-space-after-doctype"}) + self.stream.unget(data) + self.state = self.beforeDoctypeNameState + return True + + def beforeDoctypeNameState(self): + data = self.stream.char() + if data in spaceCharacters: + pass + elif data == ">": + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "expected-doctype-name-but-got-right-bracket"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["name"] = "\uFFFD" + self.state = self.doctypeNameState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "expected-doctype-name-but-got-eof"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.currentToken["name"] = data + self.state = self.doctypeNameState + return True + + def doctypeNameState(self): + data = self.stream.char() + if data in spaceCharacters: + self.currentToken["name"] = self.currentToken["name"].translate(asciiUpper2Lower) + self.state = self.afterDoctypeNameState + elif data == ">": + self.currentToken["name"] = self.currentToken["name"].translate(asciiUpper2Lower) + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["name"] += "\uFFFD" + self.state = self.doctypeNameState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-doctype-name"}) + self.currentToken["correct"] = False + self.currentToken["name"] = self.currentToken["name"].translate(asciiUpper2Lower) + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.currentToken["name"] += data + return True + + def afterDoctypeNameState(self): + data = self.stream.char() + if data in spaceCharacters: + pass + elif data == ">": + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + elif data is EOF: + self.currentToken["correct"] = False + self.stream.unget(data) + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-doctype"}) + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + if data in ("p", "P"): + matched = True + for expected in (("u", "U"), ("b", "B"), ("l", "L"), + ("i", "I"), ("c", "C")): + data = self.stream.char() + if data not in expected: + matched = False + break + if matched: + self.state = self.afterDoctypePublicKeywordState + return True + elif data in ("s", "S"): + matched = True + for expected in (("y", "Y"), ("s", "S"), ("t", "T"), + ("e", "E"), ("m", "M")): + data = self.stream.char() + if data not in expected: + matched = False + break + if matched: + self.state = self.afterDoctypeSystemKeywordState + return True + + # All the characters read before the current 'data' will be + # [a-zA-Z], so they're garbage in the bogus doctype and can be + # discarded; only the latest character might be '>' or EOF + # and needs to be ungetted + self.stream.unget(data) + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "expected-space-or-right-bracket-in-doctype", "datavars": + {"data": data}}) + self.currentToken["correct"] = False + self.state = self.bogusDoctypeState + + return True + + def afterDoctypePublicKeywordState(self): + data = self.stream.char() + if data in spaceCharacters: + self.state = self.beforeDoctypePublicIdentifierState + elif data in ("'", '"'): + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-char-in-doctype"}) + self.stream.unget(data) + self.state = self.beforeDoctypePublicIdentifierState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-doctype"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.stream.unget(data) + self.state = self.beforeDoctypePublicIdentifierState + return True + + def beforeDoctypePublicIdentifierState(self): + data = self.stream.char() + if data in spaceCharacters: + pass + elif data == "\"": + self.currentToken["publicId"] = "" + self.state = self.doctypePublicIdentifierDoubleQuotedState + elif data == "'": + self.currentToken["publicId"] = "" + self.state = self.doctypePublicIdentifierSingleQuotedState + elif data == ">": + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-end-of-doctype"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-doctype"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-char-in-doctype"}) + self.currentToken["correct"] = False + self.state = self.bogusDoctypeState + return True + + def doctypePublicIdentifierDoubleQuotedState(self): + data = self.stream.char() + if data == "\"": + self.state = self.afterDoctypePublicIdentifierState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["publicId"] += "\uFFFD" + elif data == ">": + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-end-of-doctype"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-doctype"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.currentToken["publicId"] += data + return True + + def doctypePublicIdentifierSingleQuotedState(self): + data = self.stream.char() + if data == "'": + self.state = self.afterDoctypePublicIdentifierState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["publicId"] += "\uFFFD" + elif data == ">": + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-end-of-doctype"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-doctype"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.currentToken["publicId"] += data + return True + + def afterDoctypePublicIdentifierState(self): + data = self.stream.char() + if data in spaceCharacters: + self.state = self.betweenDoctypePublicAndSystemIdentifiersState + elif data == ">": + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + elif data == '"': + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-char-in-doctype"}) + self.currentToken["systemId"] = "" + self.state = self.doctypeSystemIdentifierDoubleQuotedState + elif data == "'": + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-char-in-doctype"}) + self.currentToken["systemId"] = "" + self.state = self.doctypeSystemIdentifierSingleQuotedState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-doctype"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-char-in-doctype"}) + self.currentToken["correct"] = False + self.state = self.bogusDoctypeState + return True + + def betweenDoctypePublicAndSystemIdentifiersState(self): + data = self.stream.char() + if data in spaceCharacters: + pass + elif data == ">": + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + elif data == '"': + self.currentToken["systemId"] = "" + self.state = self.doctypeSystemIdentifierDoubleQuotedState + elif data == "'": + self.currentToken["systemId"] = "" + self.state = self.doctypeSystemIdentifierSingleQuotedState + elif data == EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-doctype"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-char-in-doctype"}) + self.currentToken["correct"] = False + self.state = self.bogusDoctypeState + return True + + def afterDoctypeSystemKeywordState(self): + data = self.stream.char() + if data in spaceCharacters: + self.state = self.beforeDoctypeSystemIdentifierState + elif data in ("'", '"'): + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-char-in-doctype"}) + self.stream.unget(data) + self.state = self.beforeDoctypeSystemIdentifierState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-doctype"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.stream.unget(data) + self.state = self.beforeDoctypeSystemIdentifierState + return True + + def beforeDoctypeSystemIdentifierState(self): + data = self.stream.char() + if data in spaceCharacters: + pass + elif data == "\"": + self.currentToken["systemId"] = "" + self.state = self.doctypeSystemIdentifierDoubleQuotedState + elif data == "'": + self.currentToken["systemId"] = "" + self.state = self.doctypeSystemIdentifierSingleQuotedState + elif data == ">": + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-char-in-doctype"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-doctype"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-char-in-doctype"}) + self.currentToken["correct"] = False + self.state = self.bogusDoctypeState + return True + + def doctypeSystemIdentifierDoubleQuotedState(self): + data = self.stream.char() + if data == "\"": + self.state = self.afterDoctypeSystemIdentifierState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["systemId"] += "\uFFFD" + elif data == ">": + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-end-of-doctype"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-doctype"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.currentToken["systemId"] += data + return True + + def doctypeSystemIdentifierSingleQuotedState(self): + data = self.stream.char() + if data == "'": + self.state = self.afterDoctypeSystemIdentifierState + elif data == "\u0000": + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + self.currentToken["systemId"] += "\uFFFD" + elif data == ">": + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-end-of-doctype"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-doctype"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.currentToken["systemId"] += data + return True + + def afterDoctypeSystemIdentifierState(self): + data = self.stream.char() + if data in spaceCharacters: + pass + elif data == ">": + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + elif data is EOF: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "eof-in-doctype"}) + self.currentToken["correct"] = False + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + self.tokenQueue.append({"type": tokenTypes["ParseError"], "data": + "unexpected-char-in-doctype"}) + self.state = self.bogusDoctypeState + return True + + def bogusDoctypeState(self): + data = self.stream.char() + if data == ">": + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + elif data is EOF: + # XXX EMIT + self.stream.unget(data) + self.tokenQueue.append(self.currentToken) + self.state = self.dataState + else: + pass + return True + + def cdataSectionState(self): + data = [] + while True: + data.append(self.stream.charsUntil("]")) + data.append(self.stream.charsUntil(">")) + char = self.stream.char() + if char == EOF: + break + else: + assert char == ">" + if data[-1][-2:] == "]]": + data[-1] = data[-1][:-2] + break + else: + data.append(char) + + data = "".join(data) # pylint:disable=redefined-variable-type + # Deal with null here rather than in the parser + nullCount = data.count("\u0000") + if nullCount > 0: + for _ in range(nullCount): + self.tokenQueue.append({"type": tokenTypes["ParseError"], + "data": "invalid-codepoint"}) + data = data.replace("\u0000", "\uFFFD") + if data: + self.tokenQueue.append({"type": tokenTypes["Characters"], + "data": data}) + self.state = self.dataState + return True diff --git a/venv/Lib/site-packages/pip/_vendor/html5lib/_trie/__init__.py b/venv/Lib/site-packages/pip/_vendor/html5lib/_trie/__init__.py new file mode 100644 index 0000000..07bad5d --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/html5lib/_trie/__init__.py @@ -0,0 +1,5 @@ +from __future__ import absolute_import, division, unicode_literals + +from .py import Trie + +__all__ = ["Trie"] diff --git a/venv/Lib/site-packages/pip/_vendor/html5lib/_trie/__pycache__/__init__.cpython-39.pyc b/venv/Lib/site-packages/pip/_vendor/html5lib/_trie/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b48034628c08b81e03a42b82223b38fe7086c616 GIT binary patch literal 345 zcmYjMO-lnY5KXe%Z7CK#c=sk$SZ|7mh@waFV!bSZA>Bk9%@;|wQvZWL#J`lQr~U;` zCO!FJ-ppg(z#BH3O;N_z(eYB}{!_$%kSuO;g_BGiajcNW9oD2Hy6P&7IN_D5^{5-= zxqii6!$(hO-fXiU&8xJ}mcgna3Xs}aAJc@(wG7glbTAm%TP{G!C_GbPi^~m8^}Lh~ zu{IYR)Lyvo7bM62OLOJaGvdOD_r_`E(6ZJ%&yP3rzVE$nCR$wV0DiyUy*K>Z1Nf5$ z^Iw32&#{@G&`6Lhg^YzP;~~$y&|@%J##x^FStD#P_!06AA5`=73kLLaYpvPZ&ye$N z_!^`q{d17MYD~Q_kc|WAHDBTB(DUq#XlRObTq%)cWuYq@$mAq3Ns-&-ah}A5R3c3( zrK8mJm~DL@m1UAYj%oY+=U)xXee5U*nS_u_7J9P#97fDRXotRR$mThO4cU?b{x@Y? zcJROT9DE1^1h!!PL!GF}od-ix=_sx?hmld6aT*!3IV$vKg{x*i=5xU@jqtjeZ5&ik zu^OiQf?vWJe}PFEgWjmTnorpQI6O@9^PuK?Kr=mWKW1|W(%}tktJutkXpW$UM=NKn zW*6`RE}8ag_6I-q58x$WRywANbY-3<)lrXI-ru(D*-K`drB*DH&8{gRm2OlWN&PE;-n zJvgee^pi9h4g@7*ASgrq^3=9>jH==yD|ZR_U)W%Bo3hz|qE1bJC#6tkxBtei=i7!E zmrCm<`dXjdtcQo7FnpuZkzT-g{T>>m(-y*&K?vQY>BZM;ze9Ddc~4uhr`Jx>!mhs=72*rj)7 z2$5Yoii{v8g6bh=HFzIaW)Rr|>k!0s2k~9L{}1^PPpMH^Cm6m)h!p}wrLifK>=x<` ziF}MiQ2RCS!f$*X38L@D{0zrSisUvb^qaC@(HBYb{a2(vOnXB|`D10hROL4KR-JyS zb)m0uX32jUFQo0xV!YzsXkE8lS8>zSlk9VoJBj73U^)s5n#*Dou@y z)?q{iVf#I%@8J41RIPMQ>~qyvy&h5EQeU zvOMsa!JdV<kR98@Bt6drV#NYeVec4p*uNeB+e8s}^o<+|ei3!M3FO#lD@ literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_vendor/html5lib/_trie/__pycache__/py.cpython-39.pyc b/venv/Lib/site-packages/pip/_vendor/html5lib/_trie/__pycache__/py.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..27b4a7db4835930c2083a2aecaa8a4ffe1df5a66 GIT binary patch literal 2250 zcmb7F&2Jk;6rY*>@Y-=wx0JNuqYWS`48(9DAXHTiEk#06E(8viVYK#4>P>dn+nI5j zSnCVUm45*>$6Wby=E|uj4%|5L-mIM_X(hy3e)IKaes6y7W8&rI27&Ll+jshZg@pWx zgY%ycgZuE;+aLrHG$k4B(u{Rk=5;-ab1e0a68T*M)@`T~WQ@Yb;wgHsp+Qj)lssOZMigiA>^zf9ZWf=eS z%Y(0bKWeFTFV6E=_qK}SVQk{w_Gl2Ny1ktb9q>(drJWKH~h(D9evf|JjoNodFO75 zSo&V)Om%W|D^1rAiZ1&!INwsBYnZ0$LxF z*&(X;5gViL63?K(IU2UO<{7(gdZl4AASwIT@LT?1n7f_fDwVhSu+~DVusG zKs^WrR(dnvCsThKQCGoog?DL3>IO8{)6&=mln7BLnzTVzS<9u6&swwv zb0PdEb>{)h*bB@f>u1ah7%UP=t%!t<$b>d%=C z9J9NEIc9^>2WFuGN!2d2*o8{kUU3DJE#)qW1RQ|#iuAbC@uy0^IGGs(GaaGs6CIK@7cjVI$c ztya{#XvljgK0xsyiaRKryFSC-OEb^X#65CYrZgr^M5B7-Rlmj!x3<$>LeRaj87lx) zSZ|bv0$;-J6?hps^OvEclSB9V*syxJU1ULV?#J-*;A?7YTi-muyS~m88{Mt0b`R^C NM*Zuw2^2NGe*ylT=1Kqn literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_vendor/html5lib/_trie/_base.py b/venv/Lib/site-packages/pip/_vendor/html5lib/_trie/_base.py new file mode 100644 index 0000000..6b71975 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/html5lib/_trie/_base.py @@ -0,0 +1,40 @@ +from __future__ import absolute_import, division, unicode_literals + +try: + from collections.abc import Mapping +except ImportError: # Python 2.7 + from collections import Mapping + + +class Trie(Mapping): + """Abstract base class for tries""" + + def keys(self, prefix=None): + # pylint:disable=arguments-differ + keys = super(Trie, self).keys() + + if prefix is None: + return set(keys) + + return {x for x in keys if x.startswith(prefix)} + + def has_keys_with_prefix(self, prefix): + for key in self.keys(): + if key.startswith(prefix): + return True + + return False + + def longest_prefix(self, prefix): + if prefix in self: + return prefix + + for i in range(1, len(prefix) + 1): + if prefix[:-i] in self: + return prefix[:-i] + + raise KeyError(prefix) + + def longest_prefix_item(self, prefix): + lprefix = self.longest_prefix(prefix) + return (lprefix, self[lprefix]) diff --git a/venv/Lib/site-packages/pip/_vendor/html5lib/_trie/py.py b/venv/Lib/site-packages/pip/_vendor/html5lib/_trie/py.py new file mode 100644 index 0000000..c178b21 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/html5lib/_trie/py.py @@ -0,0 +1,67 @@ +from __future__ import absolute_import, division, unicode_literals +from pip._vendor.six import text_type + +from bisect import bisect_left + +from ._base import Trie as ABCTrie + + +class Trie(ABCTrie): + def __init__(self, data): + if not all(isinstance(x, text_type) for x in data.keys()): + raise TypeError("All keys must be strings") + + self._data = data + self._keys = sorted(data.keys()) + self._cachestr = "" + self._cachepoints = (0, len(data)) + + def __contains__(self, key): + return key in self._data + + def __len__(self): + return len(self._data) + + def __iter__(self): + return iter(self._data) + + def __getitem__(self, key): + return self._data[key] + + def keys(self, prefix=None): + if prefix is None or prefix == "" or not self._keys: + return set(self._keys) + + if prefix.startswith(self._cachestr): + lo, hi = self._cachepoints + start = i = bisect_left(self._keys, prefix, lo, hi) + else: + start = i = bisect_left(self._keys, prefix) + + keys = set() + if start == len(self._keys): + return keys + + while self._keys[i].startswith(prefix): + keys.add(self._keys[i]) + i += 1 + + self._cachestr = prefix + self._cachepoints = (start, i) + + return keys + + def has_keys_with_prefix(self, prefix): + if prefix in self._data: + return True + + if prefix.startswith(self._cachestr): + lo, hi = self._cachepoints + i = bisect_left(self._keys, prefix, lo, hi) + else: + i = bisect_left(self._keys, prefix) + + if i == len(self._keys): + return False + + return self._keys[i].startswith(prefix) diff --git a/venv/Lib/site-packages/pip/_vendor/html5lib/_utils.py b/venv/Lib/site-packages/pip/_vendor/html5lib/_utils.py new file mode 100644 index 0000000..d7c4926 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/html5lib/_utils.py @@ -0,0 +1,159 @@ +from __future__ import absolute_import, division, unicode_literals + +from types import ModuleType + +try: + from collections.abc import Mapping +except ImportError: + from collections import Mapping + +from pip._vendor.six import text_type, PY3 + +if PY3: + import xml.etree.ElementTree as default_etree +else: + try: + import xml.etree.cElementTree as default_etree + except ImportError: + import xml.etree.ElementTree as default_etree + + +__all__ = ["default_etree", "MethodDispatcher", "isSurrogatePair", + "surrogatePairToCodepoint", "moduleFactoryFactory", + "supports_lone_surrogates"] + + +# Platforms not supporting lone surrogates (\uD800-\uDFFF) should be +# caught by the below test. In general this would be any platform +# using UTF-16 as its encoding of unicode strings, such as +# Jython. This is because UTF-16 itself is based on the use of such +# surrogates, and there is no mechanism to further escape such +# escapes. +try: + _x = eval('"\\uD800"') # pylint:disable=eval-used + if not isinstance(_x, text_type): + # We need this with u"" because of http://bugs.jython.org/issue2039 + _x = eval('u"\\uD800"') # pylint:disable=eval-used + assert isinstance(_x, text_type) +except Exception: + supports_lone_surrogates = False +else: + supports_lone_surrogates = True + + +class MethodDispatcher(dict): + """Dict with 2 special properties: + + On initiation, keys that are lists, sets or tuples are converted to + multiple keys so accessing any one of the items in the original + list-like object returns the matching value + + md = MethodDispatcher({("foo", "bar"):"baz"}) + md["foo"] == "baz" + + A default value which can be set through the default attribute. + """ + + def __init__(self, items=()): + _dictEntries = [] + for name, value in items: + if isinstance(name, (list, tuple, frozenset, set)): + for item in name: + _dictEntries.append((item, value)) + else: + _dictEntries.append((name, value)) + dict.__init__(self, _dictEntries) + assert len(self) == len(_dictEntries) + self.default = None + + def __getitem__(self, key): + return dict.get(self, key, self.default) + + def __get__(self, instance, owner=None): + return BoundMethodDispatcher(instance, self) + + +class BoundMethodDispatcher(Mapping): + """Wraps a MethodDispatcher, binding its return values to `instance`""" + def __init__(self, instance, dispatcher): + self.instance = instance + self.dispatcher = dispatcher + + def __getitem__(self, key): + # see https://docs.python.org/3/reference/datamodel.html#object.__get__ + # on a function, __get__ is used to bind a function to an instance as a bound method + return self.dispatcher[key].__get__(self.instance) + + def get(self, key, default): + if key in self.dispatcher: + return self[key] + else: + return default + + def __iter__(self): + return iter(self.dispatcher) + + def __len__(self): + return len(self.dispatcher) + + def __contains__(self, key): + return key in self.dispatcher + + +# Some utility functions to deal with weirdness around UCS2 vs UCS4 +# python builds + +def isSurrogatePair(data): + return (len(data) == 2 and + ord(data[0]) >= 0xD800 and ord(data[0]) <= 0xDBFF and + ord(data[1]) >= 0xDC00 and ord(data[1]) <= 0xDFFF) + + +def surrogatePairToCodepoint(data): + char_val = (0x10000 + (ord(data[0]) - 0xD800) * 0x400 + + (ord(data[1]) - 0xDC00)) + return char_val + +# Module Factory Factory (no, this isn't Java, I know) +# Here to stop this being duplicated all over the place. + + +def moduleFactoryFactory(factory): + moduleCache = {} + + def moduleFactory(baseModule, *args, **kwargs): + if isinstance(ModuleType.__name__, type("")): + name = "_%s_factory" % baseModule.__name__ + else: + name = b"_%s_factory" % baseModule.__name__ + + kwargs_tuple = tuple(kwargs.items()) + + try: + return moduleCache[name][args][kwargs_tuple] + except KeyError: + mod = ModuleType(name) + objs = factory(baseModule, *args, **kwargs) + mod.__dict__.update(objs) + if "name" not in moduleCache: + moduleCache[name] = {} + if "args" not in moduleCache[name]: + moduleCache[name][args] = {} + if "kwargs" not in moduleCache[name][args]: + moduleCache[name][args][kwargs_tuple] = {} + moduleCache[name][args][kwargs_tuple] = mod + return mod + + return moduleFactory + + +def memoize(func): + cache = {} + + def wrapped(*args, **kwargs): + key = (tuple(args), tuple(kwargs.items())) + if key not in cache: + cache[key] = func(*args, **kwargs) + return cache[key] + + return wrapped diff --git a/venv/Lib/site-packages/pip/_vendor/html5lib/constants.py b/venv/Lib/site-packages/pip/_vendor/html5lib/constants.py new file mode 100644 index 0000000..fe3e237 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/html5lib/constants.py @@ -0,0 +1,2946 @@ +from __future__ import absolute_import, division, unicode_literals + +import string + +EOF = None + +E = { + "null-character": + "Null character in input stream, replaced with U+FFFD.", + "invalid-codepoint": + "Invalid codepoint in stream.", + "incorrectly-placed-solidus": + "Solidus (/) incorrectly placed in tag.", + "incorrect-cr-newline-entity": + "Incorrect CR newline entity, replaced with LF.", + "illegal-windows-1252-entity": + "Entity used with illegal number (windows-1252 reference).", + "cant-convert-numeric-entity": + "Numeric entity couldn't be converted to character " + "(codepoint U+%(charAsInt)08x).", + "illegal-codepoint-for-numeric-entity": + "Numeric entity represents an illegal codepoint: " + "U+%(charAsInt)08x.", + "numeric-entity-without-semicolon": + "Numeric entity didn't end with ';'.", + "expected-numeric-entity-but-got-eof": + "Numeric entity expected. Got end of file instead.", + "expected-numeric-entity": + "Numeric entity expected but none found.", + "named-entity-without-semicolon": + "Named entity didn't end with ';'.", + "expected-named-entity": + "Named entity expected. Got none.", + "attributes-in-end-tag": + "End tag contains unexpected attributes.", + 'self-closing-flag-on-end-tag': + "End tag contains unexpected self-closing flag.", + "expected-tag-name-but-got-right-bracket": + "Expected tag name. Got '>' instead.", + "expected-tag-name-but-got-question-mark": + "Expected tag name. Got '?' instead. (HTML doesn't " + "support processing instructions.)", + "expected-tag-name": + "Expected tag name. Got something else instead", + "expected-closing-tag-but-got-right-bracket": + "Expected closing tag. Got '>' instead. Ignoring ''.", + "expected-closing-tag-but-got-eof": + "Expected closing tag. Unexpected end of file.", + "expected-closing-tag-but-got-char": + "Expected closing tag. Unexpected character '%(data)s' found.", + "eof-in-tag-name": + "Unexpected end of file in the tag name.", + "expected-attribute-name-but-got-eof": + "Unexpected end of file. Expected attribute name instead.", + "eof-in-attribute-name": + "Unexpected end of file in attribute name.", + "invalid-character-in-attribute-name": + "Invalid character in attribute name", + "duplicate-attribute": + "Dropped duplicate attribute on tag.", + "expected-end-of-tag-name-but-got-eof": + "Unexpected end of file. Expected = or end of tag.", + "expected-attribute-value-but-got-eof": + "Unexpected end of file. Expected attribute value.", + "expected-attribute-value-but-got-right-bracket": + "Expected attribute value. Got '>' instead.", + 'equals-in-unquoted-attribute-value': + "Unexpected = in unquoted attribute", + 'unexpected-character-in-unquoted-attribute-value': + "Unexpected character in unquoted attribute", + "invalid-character-after-attribute-name": + "Unexpected character after attribute name.", + "unexpected-character-after-attribute-value": + "Unexpected character after attribute value.", + "eof-in-attribute-value-double-quote": + "Unexpected end of file in attribute value (\").", + "eof-in-attribute-value-single-quote": + "Unexpected end of file in attribute value (').", + "eof-in-attribute-value-no-quotes": + "Unexpected end of file in attribute value.", + "unexpected-EOF-after-solidus-in-tag": + "Unexpected end of file in tag. Expected >", + "unexpected-character-after-solidus-in-tag": + "Unexpected character after / in tag. Expected >", + "expected-dashes-or-doctype": + "Expected '--' or 'DOCTYPE'. Not found.", + "unexpected-bang-after-double-dash-in-comment": + "Unexpected ! after -- in comment", + "unexpected-space-after-double-dash-in-comment": + "Unexpected space after -- in comment", + "incorrect-comment": + "Incorrect comment.", + "eof-in-comment": + "Unexpected end of file in comment.", + "eof-in-comment-end-dash": + "Unexpected end of file in comment (-)", + "unexpected-dash-after-double-dash-in-comment": + "Unexpected '-' after '--' found in comment.", + "eof-in-comment-double-dash": + "Unexpected end of file in comment (--).", + "eof-in-comment-end-space-state": + "Unexpected end of file in comment.", + "eof-in-comment-end-bang-state": + "Unexpected end of file in comment.", + "unexpected-char-in-comment": + "Unexpected character in comment found.", + "need-space-after-doctype": + "No space after literal string 'DOCTYPE'.", + "expected-doctype-name-but-got-right-bracket": + "Unexpected > character. Expected DOCTYPE name.", + "expected-doctype-name-but-got-eof": + "Unexpected end of file. Expected DOCTYPE name.", + "eof-in-doctype-name": + "Unexpected end of file in DOCTYPE name.", + "eof-in-doctype": + "Unexpected end of file in DOCTYPE.", + "expected-space-or-right-bracket-in-doctype": + "Expected space or '>'. Got '%(data)s'", + "unexpected-end-of-doctype": + "Unexpected end of DOCTYPE.", + "unexpected-char-in-doctype": + "Unexpected character in DOCTYPE.", + "eof-in-innerhtml": + "XXX innerHTML EOF", + "unexpected-doctype": + "Unexpected DOCTYPE. Ignored.", + "non-html-root": + "html needs to be the first start tag.", + "expected-doctype-but-got-eof": + "Unexpected End of file. Expected DOCTYPE.", + "unknown-doctype": + "Erroneous DOCTYPE.", + "expected-doctype-but-got-chars": + "Unexpected non-space characters. Expected DOCTYPE.", + "expected-doctype-but-got-start-tag": + "Unexpected start tag (%(name)s). Expected DOCTYPE.", + "expected-doctype-but-got-end-tag": + "Unexpected end tag (%(name)s). Expected DOCTYPE.", + "end-tag-after-implied-root": + "Unexpected end tag (%(name)s) after the (implied) root element.", + "expected-named-closing-tag-but-got-eof": + "Unexpected end of file. Expected end tag (%(name)s).", + "two-heads-are-not-better-than-one": + "Unexpected start tag head in existing head. Ignored.", + "unexpected-end-tag": + "Unexpected end tag (%(name)s). Ignored.", + "unexpected-start-tag-out-of-my-head": + "Unexpected start tag (%(name)s) that can be in head. Moved.", + "unexpected-start-tag": + "Unexpected start tag (%(name)s).", + "missing-end-tag": + "Missing end tag (%(name)s).", + "missing-end-tags": + "Missing end tags (%(name)s).", + "unexpected-start-tag-implies-end-tag": + "Unexpected start tag (%(startName)s) " + "implies end tag (%(endName)s).", + "unexpected-start-tag-treated-as": + "Unexpected start tag (%(originalName)s). Treated as %(newName)s.", + "deprecated-tag": + "Unexpected start tag %(name)s. Don't use it!", + "unexpected-start-tag-ignored": + "Unexpected start tag %(name)s. Ignored.", + "expected-one-end-tag-but-got-another": + "Unexpected end tag (%(gotName)s). " + "Missing end tag (%(expectedName)s).", + "end-tag-too-early": + "End tag (%(name)s) seen too early. Expected other end tag.", + "end-tag-too-early-named": + "Unexpected end tag (%(gotName)s). Expected end tag (%(expectedName)s).", + "end-tag-too-early-ignored": + "End tag (%(name)s) seen too early. Ignored.", + "adoption-agency-1.1": + "End tag (%(name)s) violates step 1, " + "paragraph 1 of the adoption agency algorithm.", + "adoption-agency-1.2": + "End tag (%(name)s) violates step 1, " + "paragraph 2 of the adoption agency algorithm.", + "adoption-agency-1.3": + "End tag (%(name)s) violates step 1, " + "paragraph 3 of the adoption agency algorithm.", + "adoption-agency-4.4": + "End tag (%(name)s) violates step 4, " + "paragraph 4 of the adoption agency algorithm.", + "unexpected-end-tag-treated-as": + "Unexpected end tag (%(originalName)s). Treated as %(newName)s.", + "no-end-tag": + "This element (%(name)s) has no end tag.", + "unexpected-implied-end-tag-in-table": + "Unexpected implied end tag (%(name)s) in the table phase.", + "unexpected-implied-end-tag-in-table-body": + "Unexpected implied end tag (%(name)s) in the table body phase.", + "unexpected-char-implies-table-voodoo": + "Unexpected non-space characters in " + "table context caused voodoo mode.", + "unexpected-hidden-input-in-table": + "Unexpected input with type hidden in table context.", + "unexpected-form-in-table": + "Unexpected form in table context.", + "unexpected-start-tag-implies-table-voodoo": + "Unexpected start tag (%(name)s) in " + "table context caused voodoo mode.", + "unexpected-end-tag-implies-table-voodoo": + "Unexpected end tag (%(name)s) in " + "table context caused voodoo mode.", + "unexpected-cell-in-table-body": + "Unexpected table cell start tag (%(name)s) " + "in the table body phase.", + "unexpected-cell-end-tag": + "Got table cell end tag (%(name)s) " + "while required end tags are missing.", + "unexpected-end-tag-in-table-body": + "Unexpected end tag (%(name)s) in the table body phase. Ignored.", + "unexpected-implied-end-tag-in-table-row": + "Unexpected implied end tag (%(name)s) in the table row phase.", + "unexpected-end-tag-in-table-row": + "Unexpected end tag (%(name)s) in the table row phase. Ignored.", + "unexpected-select-in-select": + "Unexpected select start tag in the select phase " + "treated as select end tag.", + "unexpected-input-in-select": + "Unexpected input start tag in the select phase.", + "unexpected-start-tag-in-select": + "Unexpected start tag token (%(name)s in the select phase. " + "Ignored.", + "unexpected-end-tag-in-select": + "Unexpected end tag (%(name)s) in the select phase. Ignored.", + "unexpected-table-element-start-tag-in-select-in-table": + "Unexpected table element start tag (%(name)s) in the select in table phase.", + "unexpected-table-element-end-tag-in-select-in-table": + "Unexpected table element end tag (%(name)s) in the select in table phase.", + "unexpected-char-after-body": + "Unexpected non-space characters in the after body phase.", + "unexpected-start-tag-after-body": + "Unexpected start tag token (%(name)s)" + " in the after body phase.", + "unexpected-end-tag-after-body": + "Unexpected end tag token (%(name)s)" + " in the after body phase.", + "unexpected-char-in-frameset": + "Unexpected characters in the frameset phase. Characters ignored.", + "unexpected-start-tag-in-frameset": + "Unexpected start tag token (%(name)s)" + " in the frameset phase. Ignored.", + "unexpected-frameset-in-frameset-innerhtml": + "Unexpected end tag token (frameset) " + "in the frameset phase (innerHTML).", + "unexpected-end-tag-in-frameset": + "Unexpected end tag token (%(name)s)" + " in the frameset phase. Ignored.", + "unexpected-char-after-frameset": + "Unexpected non-space characters in the " + "after frameset phase. Ignored.", + "unexpected-start-tag-after-frameset": + "Unexpected start tag (%(name)s)" + " in the after frameset phase. Ignored.", + "unexpected-end-tag-after-frameset": + "Unexpected end tag (%(name)s)" + " in the after frameset phase. Ignored.", + "unexpected-end-tag-after-body-innerhtml": + "Unexpected end tag after body(innerHtml)", + "expected-eof-but-got-char": + "Unexpected non-space characters. Expected end of file.", + "expected-eof-but-got-start-tag": + "Unexpected start tag (%(name)s)" + ". Expected end of file.", + "expected-eof-but-got-end-tag": + "Unexpected end tag (%(name)s)" + ". Expected end of file.", + "eof-in-table": + "Unexpected end of file. Expected table content.", + "eof-in-select": + "Unexpected end of file. Expected select content.", + "eof-in-frameset": + "Unexpected end of file. Expected frameset content.", + "eof-in-script-in-script": + "Unexpected end of file. Expected script content.", + "eof-in-foreign-lands": + "Unexpected end of file. Expected foreign content", + "non-void-element-with-trailing-solidus": + "Trailing solidus not allowed on element %(name)s", + "unexpected-html-element-in-foreign-content": + "Element %(name)s not allowed in a non-html context", + "unexpected-end-tag-before-html": + "Unexpected end tag (%(name)s) before html.", + "unexpected-inhead-noscript-tag": + "Element %(name)s not allowed in a inhead-noscript context", + "eof-in-head-noscript": + "Unexpected end of file. Expected inhead-noscript content", + "char-in-head-noscript": + "Unexpected non-space character. Expected inhead-noscript content", + "XXX-undefined-error": + "Undefined error (this sucks and should be fixed)", +} + +namespaces = { + "html": "http://www.w3.org/1999/xhtml", + "mathml": "http://www.w3.org/1998/Math/MathML", + "svg": "http://www.w3.org/2000/svg", + "xlink": "http://www.w3.org/1999/xlink", + "xml": "http://www.w3.org/XML/1998/namespace", + "xmlns": "http://www.w3.org/2000/xmlns/" +} + +scopingElements = frozenset([ + (namespaces["html"], "applet"), + (namespaces["html"], "caption"), + (namespaces["html"], "html"), + (namespaces["html"], "marquee"), + (namespaces["html"], "object"), + (namespaces["html"], "table"), + (namespaces["html"], "td"), + (namespaces["html"], "th"), + (namespaces["mathml"], "mi"), + (namespaces["mathml"], "mo"), + (namespaces["mathml"], "mn"), + (namespaces["mathml"], "ms"), + (namespaces["mathml"], "mtext"), + (namespaces["mathml"], "annotation-xml"), + (namespaces["svg"], "foreignObject"), + (namespaces["svg"], "desc"), + (namespaces["svg"], "title"), +]) + +formattingElements = frozenset([ + (namespaces["html"], "a"), + (namespaces["html"], "b"), + (namespaces["html"], "big"), + (namespaces["html"], "code"), + (namespaces["html"], "em"), + (namespaces["html"], "font"), + (namespaces["html"], "i"), + (namespaces["html"], "nobr"), + (namespaces["html"], "s"), + (namespaces["html"], "small"), + (namespaces["html"], "strike"), + (namespaces["html"], "strong"), + (namespaces["html"], "tt"), + (namespaces["html"], "u") +]) + +specialElements = frozenset([ + (namespaces["html"], "address"), + (namespaces["html"], "applet"), + (namespaces["html"], "area"), + (namespaces["html"], "article"), + (namespaces["html"], "aside"), + (namespaces["html"], "base"), + (namespaces["html"], "basefont"), + (namespaces["html"], "bgsound"), + (namespaces["html"], "blockquote"), + (namespaces["html"], "body"), + (namespaces["html"], "br"), + (namespaces["html"], "button"), + (namespaces["html"], "caption"), + (namespaces["html"], "center"), + (namespaces["html"], "col"), + (namespaces["html"], "colgroup"), + (namespaces["html"], "command"), + (namespaces["html"], "dd"), + (namespaces["html"], "details"), + (namespaces["html"], "dir"), + (namespaces["html"], "div"), + (namespaces["html"], "dl"), + (namespaces["html"], "dt"), + (namespaces["html"], "embed"), + (namespaces["html"], "fieldset"), + (namespaces["html"], "figure"), + (namespaces["html"], "footer"), + (namespaces["html"], "form"), + (namespaces["html"], "frame"), + (namespaces["html"], "frameset"), + (namespaces["html"], "h1"), + (namespaces["html"], "h2"), + (namespaces["html"], "h3"), + (namespaces["html"], "h4"), + (namespaces["html"], "h5"), + (namespaces["html"], "h6"), + (namespaces["html"], "head"), + (namespaces["html"], "header"), + (namespaces["html"], "hr"), + (namespaces["html"], "html"), + (namespaces["html"], "iframe"), + # Note that image is commented out in the spec as "this isn't an + # element that can end up on the stack, so it doesn't matter," + (namespaces["html"], "image"), + (namespaces["html"], "img"), + (namespaces["html"], "input"), + (namespaces["html"], "isindex"), + (namespaces["html"], "li"), + (namespaces["html"], "link"), + (namespaces["html"], "listing"), + (namespaces["html"], "marquee"), + (namespaces["html"], "menu"), + (namespaces["html"], "meta"), + (namespaces["html"], "nav"), + (namespaces["html"], "noembed"), + (namespaces["html"], "noframes"), + (namespaces["html"], "noscript"), + (namespaces["html"], "object"), + (namespaces["html"], "ol"), + (namespaces["html"], "p"), + (namespaces["html"], "param"), + (namespaces["html"], "plaintext"), + (namespaces["html"], "pre"), + (namespaces["html"], "script"), + (namespaces["html"], "section"), + (namespaces["html"], "select"), + (namespaces["html"], "style"), + (namespaces["html"], "table"), + (namespaces["html"], "tbody"), + (namespaces["html"], "td"), + (namespaces["html"], "textarea"), + (namespaces["html"], "tfoot"), + (namespaces["html"], "th"), + (namespaces["html"], "thead"), + (namespaces["html"], "title"), + (namespaces["html"], "tr"), + (namespaces["html"], "ul"), + (namespaces["html"], "wbr"), + (namespaces["html"], "xmp"), + (namespaces["svg"], "foreignObject") +]) + +htmlIntegrationPointElements = frozenset([ + (namespaces["mathml"], "annotation-xml"), + (namespaces["svg"], "foreignObject"), + (namespaces["svg"], "desc"), + (namespaces["svg"], "title") +]) + +mathmlTextIntegrationPointElements = frozenset([ + (namespaces["mathml"], "mi"), + (namespaces["mathml"], "mo"), + (namespaces["mathml"], "mn"), + (namespaces["mathml"], "ms"), + (namespaces["mathml"], "mtext") +]) + +adjustSVGAttributes = { + "attributename": "attributeName", + "attributetype": "attributeType", + "basefrequency": "baseFrequency", + "baseprofile": "baseProfile", + "calcmode": "calcMode", + "clippathunits": "clipPathUnits", + "contentscripttype": "contentScriptType", + "contentstyletype": "contentStyleType", + "diffuseconstant": "diffuseConstant", + "edgemode": "edgeMode", + "externalresourcesrequired": "externalResourcesRequired", + "filterres": "filterRes", + "filterunits": "filterUnits", + "glyphref": "glyphRef", + "gradienttransform": "gradientTransform", + "gradientunits": "gradientUnits", + "kernelmatrix": "kernelMatrix", + "kernelunitlength": "kernelUnitLength", + "keypoints": "keyPoints", + "keysplines": "keySplines", + "keytimes": "keyTimes", + "lengthadjust": "lengthAdjust", + "limitingconeangle": "limitingConeAngle", + "markerheight": "markerHeight", + "markerunits": "markerUnits", + "markerwidth": "markerWidth", + "maskcontentunits": "maskContentUnits", + "maskunits": "maskUnits", + "numoctaves": "numOctaves", + "pathlength": "pathLength", + "patterncontentunits": "patternContentUnits", + "patterntransform": "patternTransform", + "patternunits": "patternUnits", + "pointsatx": "pointsAtX", + "pointsaty": "pointsAtY", + "pointsatz": "pointsAtZ", + "preservealpha": "preserveAlpha", + "preserveaspectratio": "preserveAspectRatio", + "primitiveunits": "primitiveUnits", + "refx": "refX", + "refy": "refY", + "repeatcount": "repeatCount", + "repeatdur": "repeatDur", + "requiredextensions": "requiredExtensions", + "requiredfeatures": "requiredFeatures", + "specularconstant": "specularConstant", + "specularexponent": "specularExponent", + "spreadmethod": "spreadMethod", + "startoffset": "startOffset", + "stddeviation": "stdDeviation", + "stitchtiles": "stitchTiles", + "surfacescale": "surfaceScale", + "systemlanguage": "systemLanguage", + "tablevalues": "tableValues", + "targetx": "targetX", + "targety": "targetY", + "textlength": "textLength", + "viewbox": "viewBox", + "viewtarget": "viewTarget", + "xchannelselector": "xChannelSelector", + "ychannelselector": "yChannelSelector", + "zoomandpan": "zoomAndPan" +} + +adjustMathMLAttributes = {"definitionurl": "definitionURL"} + +adjustForeignAttributes = { + "xlink:actuate": ("xlink", "actuate", namespaces["xlink"]), + "xlink:arcrole": ("xlink", "arcrole", namespaces["xlink"]), + "xlink:href": ("xlink", "href", namespaces["xlink"]), + "xlink:role": ("xlink", "role", namespaces["xlink"]), + "xlink:show": ("xlink", "show", namespaces["xlink"]), + "xlink:title": ("xlink", "title", namespaces["xlink"]), + "xlink:type": ("xlink", "type", namespaces["xlink"]), + "xml:base": ("xml", "base", namespaces["xml"]), + "xml:lang": ("xml", "lang", namespaces["xml"]), + "xml:space": ("xml", "space", namespaces["xml"]), + "xmlns": (None, "xmlns", namespaces["xmlns"]), + "xmlns:xlink": ("xmlns", "xlink", namespaces["xmlns"]) +} + +unadjustForeignAttributes = {(ns, local): qname for qname, (prefix, local, ns) in + adjustForeignAttributes.items()} + +spaceCharacters = frozenset([ + "\t", + "\n", + "\u000C", + " ", + "\r" +]) + +tableInsertModeElements = frozenset([ + "table", + "tbody", + "tfoot", + "thead", + "tr" +]) + +asciiLowercase = frozenset(string.ascii_lowercase) +asciiUppercase = frozenset(string.ascii_uppercase) +asciiLetters = frozenset(string.ascii_letters) +digits = frozenset(string.digits) +hexDigits = frozenset(string.hexdigits) + +asciiUpper2Lower = {ord(c): ord(c.lower()) for c in string.ascii_uppercase} + +# Heading elements need to be ordered +headingElements = ( + "h1", + "h2", + "h3", + "h4", + "h5", + "h6" +) + +voidElements = frozenset([ + "base", + "command", + "event-source", + "link", + "meta", + "hr", + "br", + "img", + "embed", + "param", + "area", + "col", + "input", + "source", + "track" +]) + +cdataElements = frozenset(['title', 'textarea']) + +rcdataElements = frozenset([ + 'style', + 'script', + 'xmp', + 'iframe', + 'noembed', + 'noframes', + 'noscript' +]) + +booleanAttributes = { + "": frozenset(["irrelevant", "itemscope"]), + "style": frozenset(["scoped"]), + "img": frozenset(["ismap"]), + "audio": frozenset(["autoplay", "controls"]), + "video": frozenset(["autoplay", "controls"]), + "script": frozenset(["defer", "async"]), + "details": frozenset(["open"]), + "datagrid": frozenset(["multiple", "disabled"]), + "command": frozenset(["hidden", "disabled", "checked", "default"]), + "hr": frozenset(["noshade"]), + "menu": frozenset(["autosubmit"]), + "fieldset": frozenset(["disabled", "readonly"]), + "option": frozenset(["disabled", "readonly", "selected"]), + "optgroup": frozenset(["disabled", "readonly"]), + "button": frozenset(["disabled", "autofocus"]), + "input": frozenset(["disabled", "readonly", "required", "autofocus", "checked", "ismap"]), + "select": frozenset(["disabled", "readonly", "autofocus", "multiple"]), + "output": frozenset(["disabled", "readonly"]), + "iframe": frozenset(["seamless"]), +} + +# entitiesWindows1252 has to be _ordered_ and needs to have an index. It +# therefore can't be a frozenset. +entitiesWindows1252 = ( + 8364, # 0x80 0x20AC EURO SIGN + 65533, # 0x81 UNDEFINED + 8218, # 0x82 0x201A SINGLE LOW-9 QUOTATION MARK + 402, # 0x83 0x0192 LATIN SMALL LETTER F WITH HOOK + 8222, # 0x84 0x201E DOUBLE LOW-9 QUOTATION MARK + 8230, # 0x85 0x2026 HORIZONTAL ELLIPSIS + 8224, # 0x86 0x2020 DAGGER + 8225, # 0x87 0x2021 DOUBLE DAGGER + 710, # 0x88 0x02C6 MODIFIER LETTER CIRCUMFLEX ACCENT + 8240, # 0x89 0x2030 PER MILLE SIGN + 352, # 0x8A 0x0160 LATIN CAPITAL LETTER S WITH CARON + 8249, # 0x8B 0x2039 SINGLE LEFT-POINTING ANGLE QUOTATION MARK + 338, # 0x8C 0x0152 LATIN CAPITAL LIGATURE OE + 65533, # 0x8D UNDEFINED + 381, # 0x8E 0x017D LATIN CAPITAL LETTER Z WITH CARON + 65533, # 0x8F UNDEFINED + 65533, # 0x90 UNDEFINED + 8216, # 0x91 0x2018 LEFT SINGLE QUOTATION MARK + 8217, # 0x92 0x2019 RIGHT SINGLE QUOTATION MARK + 8220, # 0x93 0x201C LEFT DOUBLE QUOTATION MARK + 8221, # 0x94 0x201D RIGHT DOUBLE QUOTATION MARK + 8226, # 0x95 0x2022 BULLET + 8211, # 0x96 0x2013 EN DASH + 8212, # 0x97 0x2014 EM DASH + 732, # 0x98 0x02DC SMALL TILDE + 8482, # 0x99 0x2122 TRADE MARK SIGN + 353, # 0x9A 0x0161 LATIN SMALL LETTER S WITH CARON + 8250, # 0x9B 0x203A SINGLE RIGHT-POINTING ANGLE QUOTATION MARK + 339, # 0x9C 0x0153 LATIN SMALL LIGATURE OE + 65533, # 0x9D UNDEFINED + 382, # 0x9E 0x017E LATIN SMALL LETTER Z WITH CARON + 376 # 0x9F 0x0178 LATIN CAPITAL LETTER Y WITH DIAERESIS +) + +xmlEntities = frozenset(['lt;', 'gt;', 'amp;', 'apos;', 'quot;']) + +entities = { + "AElig": "\xc6", + "AElig;": "\xc6", + "AMP": "&", + "AMP;": "&", + "Aacute": "\xc1", + "Aacute;": "\xc1", + "Abreve;": "\u0102", + "Acirc": "\xc2", + "Acirc;": "\xc2", + "Acy;": "\u0410", + "Afr;": "\U0001d504", + "Agrave": "\xc0", + "Agrave;": "\xc0", + "Alpha;": "\u0391", + "Amacr;": "\u0100", + "And;": "\u2a53", + "Aogon;": "\u0104", + "Aopf;": "\U0001d538", + "ApplyFunction;": "\u2061", + "Aring": "\xc5", + "Aring;": "\xc5", + "Ascr;": "\U0001d49c", + "Assign;": "\u2254", + "Atilde": "\xc3", + "Atilde;": "\xc3", + "Auml": "\xc4", + "Auml;": "\xc4", + "Backslash;": "\u2216", + "Barv;": "\u2ae7", + "Barwed;": "\u2306", + "Bcy;": "\u0411", + "Because;": "\u2235", + "Bernoullis;": "\u212c", + "Beta;": "\u0392", + "Bfr;": "\U0001d505", + "Bopf;": "\U0001d539", + "Breve;": "\u02d8", + "Bscr;": "\u212c", + "Bumpeq;": "\u224e", + "CHcy;": "\u0427", + "COPY": "\xa9", + "COPY;": "\xa9", + "Cacute;": "\u0106", + "Cap;": "\u22d2", + "CapitalDifferentialD;": "\u2145", + "Cayleys;": "\u212d", + "Ccaron;": "\u010c", + "Ccedil": "\xc7", + "Ccedil;": "\xc7", + "Ccirc;": "\u0108", + "Cconint;": "\u2230", + "Cdot;": "\u010a", + "Cedilla;": "\xb8", + "CenterDot;": "\xb7", + "Cfr;": "\u212d", + "Chi;": "\u03a7", + "CircleDot;": "\u2299", + "CircleMinus;": "\u2296", + "CirclePlus;": "\u2295", + "CircleTimes;": "\u2297", + "ClockwiseContourIntegral;": "\u2232", + "CloseCurlyDoubleQuote;": "\u201d", + "CloseCurlyQuote;": "\u2019", + "Colon;": "\u2237", + "Colone;": "\u2a74", + "Congruent;": "\u2261", + "Conint;": "\u222f", + "ContourIntegral;": "\u222e", + "Copf;": "\u2102", + "Coproduct;": "\u2210", + "CounterClockwiseContourIntegral;": "\u2233", + "Cross;": "\u2a2f", + "Cscr;": "\U0001d49e", + "Cup;": "\u22d3", + "CupCap;": "\u224d", + "DD;": "\u2145", + "DDotrahd;": "\u2911", + "DJcy;": "\u0402", + "DScy;": "\u0405", + "DZcy;": "\u040f", + "Dagger;": "\u2021", + "Darr;": "\u21a1", + "Dashv;": "\u2ae4", + "Dcaron;": "\u010e", + "Dcy;": "\u0414", + "Del;": "\u2207", + "Delta;": "\u0394", + "Dfr;": "\U0001d507", + "DiacriticalAcute;": "\xb4", + "DiacriticalDot;": "\u02d9", + "DiacriticalDoubleAcute;": "\u02dd", + "DiacriticalGrave;": "`", + "DiacriticalTilde;": "\u02dc", + "Diamond;": "\u22c4", + "DifferentialD;": "\u2146", + "Dopf;": "\U0001d53b", + "Dot;": "\xa8", + "DotDot;": "\u20dc", + "DotEqual;": "\u2250", + "DoubleContourIntegral;": "\u222f", + "DoubleDot;": "\xa8", + "DoubleDownArrow;": "\u21d3", + "DoubleLeftArrow;": "\u21d0", + "DoubleLeftRightArrow;": "\u21d4", + "DoubleLeftTee;": "\u2ae4", + "DoubleLongLeftArrow;": "\u27f8", + "DoubleLongLeftRightArrow;": "\u27fa", + "DoubleLongRightArrow;": "\u27f9", + "DoubleRightArrow;": "\u21d2", + "DoubleRightTee;": "\u22a8", + "DoubleUpArrow;": "\u21d1", + "DoubleUpDownArrow;": "\u21d5", + "DoubleVerticalBar;": "\u2225", + "DownArrow;": "\u2193", + "DownArrowBar;": "\u2913", + "DownArrowUpArrow;": "\u21f5", + "DownBreve;": "\u0311", + "DownLeftRightVector;": "\u2950", + "DownLeftTeeVector;": "\u295e", + "DownLeftVector;": "\u21bd", + "DownLeftVectorBar;": "\u2956", + "DownRightTeeVector;": "\u295f", + "DownRightVector;": "\u21c1", + "DownRightVectorBar;": "\u2957", + "DownTee;": "\u22a4", + "DownTeeArrow;": "\u21a7", + "Downarrow;": "\u21d3", + "Dscr;": "\U0001d49f", + "Dstrok;": "\u0110", + "ENG;": "\u014a", + "ETH": "\xd0", + "ETH;": "\xd0", + "Eacute": "\xc9", + "Eacute;": "\xc9", + "Ecaron;": "\u011a", + "Ecirc": "\xca", + "Ecirc;": "\xca", + "Ecy;": "\u042d", + "Edot;": "\u0116", + "Efr;": "\U0001d508", + "Egrave": "\xc8", + "Egrave;": "\xc8", + "Element;": "\u2208", + "Emacr;": "\u0112", + "EmptySmallSquare;": "\u25fb", + "EmptyVerySmallSquare;": "\u25ab", + "Eogon;": "\u0118", + "Eopf;": "\U0001d53c", + "Epsilon;": "\u0395", + "Equal;": "\u2a75", + "EqualTilde;": "\u2242", + "Equilibrium;": "\u21cc", + "Escr;": "\u2130", + "Esim;": "\u2a73", + "Eta;": "\u0397", + "Euml": "\xcb", + "Euml;": "\xcb", + "Exists;": "\u2203", + "ExponentialE;": "\u2147", + "Fcy;": "\u0424", + "Ffr;": "\U0001d509", + "FilledSmallSquare;": "\u25fc", + "FilledVerySmallSquare;": "\u25aa", + "Fopf;": "\U0001d53d", + "ForAll;": "\u2200", + "Fouriertrf;": "\u2131", + "Fscr;": "\u2131", + "GJcy;": "\u0403", + "GT": ">", + "GT;": ">", + "Gamma;": "\u0393", + "Gammad;": "\u03dc", + "Gbreve;": "\u011e", + "Gcedil;": "\u0122", + "Gcirc;": "\u011c", + "Gcy;": "\u0413", + "Gdot;": "\u0120", + "Gfr;": "\U0001d50a", + "Gg;": "\u22d9", + "Gopf;": "\U0001d53e", + "GreaterEqual;": "\u2265", + "GreaterEqualLess;": "\u22db", + "GreaterFullEqual;": "\u2267", + "GreaterGreater;": "\u2aa2", + "GreaterLess;": "\u2277", + "GreaterSlantEqual;": "\u2a7e", + "GreaterTilde;": "\u2273", + "Gscr;": "\U0001d4a2", + "Gt;": "\u226b", + "HARDcy;": "\u042a", + "Hacek;": "\u02c7", + "Hat;": "^", + "Hcirc;": "\u0124", + "Hfr;": "\u210c", + "HilbertSpace;": "\u210b", + "Hopf;": "\u210d", + "HorizontalLine;": "\u2500", + "Hscr;": "\u210b", + "Hstrok;": "\u0126", + "HumpDownHump;": "\u224e", + "HumpEqual;": "\u224f", + "IEcy;": "\u0415", + "IJlig;": "\u0132", + "IOcy;": "\u0401", + "Iacute": "\xcd", + "Iacute;": "\xcd", + "Icirc": "\xce", + "Icirc;": "\xce", + "Icy;": "\u0418", + "Idot;": "\u0130", + "Ifr;": "\u2111", + "Igrave": "\xcc", + "Igrave;": "\xcc", + "Im;": "\u2111", + "Imacr;": "\u012a", + "ImaginaryI;": "\u2148", + "Implies;": "\u21d2", + "Int;": "\u222c", + "Integral;": "\u222b", + "Intersection;": "\u22c2", + "InvisibleComma;": "\u2063", + "InvisibleTimes;": "\u2062", + "Iogon;": "\u012e", + "Iopf;": "\U0001d540", + "Iota;": "\u0399", + "Iscr;": "\u2110", + "Itilde;": "\u0128", + "Iukcy;": "\u0406", + "Iuml": "\xcf", + "Iuml;": "\xcf", + "Jcirc;": "\u0134", + "Jcy;": "\u0419", + "Jfr;": "\U0001d50d", + "Jopf;": "\U0001d541", + "Jscr;": "\U0001d4a5", + "Jsercy;": "\u0408", + "Jukcy;": "\u0404", + "KHcy;": "\u0425", + "KJcy;": "\u040c", + "Kappa;": "\u039a", + "Kcedil;": "\u0136", + "Kcy;": "\u041a", + "Kfr;": "\U0001d50e", + "Kopf;": "\U0001d542", + "Kscr;": "\U0001d4a6", + "LJcy;": "\u0409", + "LT": "<", + "LT;": "<", + "Lacute;": "\u0139", + "Lambda;": "\u039b", + "Lang;": "\u27ea", + "Laplacetrf;": "\u2112", + "Larr;": "\u219e", + "Lcaron;": "\u013d", + "Lcedil;": "\u013b", + "Lcy;": "\u041b", + "LeftAngleBracket;": "\u27e8", + "LeftArrow;": "\u2190", + "LeftArrowBar;": "\u21e4", + "LeftArrowRightArrow;": "\u21c6", + "LeftCeiling;": "\u2308", + "LeftDoubleBracket;": "\u27e6", + "LeftDownTeeVector;": "\u2961", + "LeftDownVector;": "\u21c3", + "LeftDownVectorBar;": "\u2959", + "LeftFloor;": "\u230a", + "LeftRightArrow;": "\u2194", + "LeftRightVector;": "\u294e", + "LeftTee;": "\u22a3", + "LeftTeeArrow;": "\u21a4", + "LeftTeeVector;": "\u295a", + "LeftTriangle;": "\u22b2", + "LeftTriangleBar;": "\u29cf", + "LeftTriangleEqual;": "\u22b4", + "LeftUpDownVector;": "\u2951", + "LeftUpTeeVector;": "\u2960", + "LeftUpVector;": "\u21bf", + "LeftUpVectorBar;": "\u2958", + "LeftVector;": "\u21bc", + "LeftVectorBar;": "\u2952", + "Leftarrow;": "\u21d0", + "Leftrightarrow;": "\u21d4", + "LessEqualGreater;": "\u22da", + "LessFullEqual;": "\u2266", + "LessGreater;": "\u2276", + "LessLess;": "\u2aa1", + "LessSlantEqual;": "\u2a7d", + "LessTilde;": "\u2272", + "Lfr;": "\U0001d50f", + "Ll;": "\u22d8", + "Lleftarrow;": "\u21da", + "Lmidot;": "\u013f", + "LongLeftArrow;": "\u27f5", + "LongLeftRightArrow;": "\u27f7", + "LongRightArrow;": "\u27f6", + "Longleftarrow;": "\u27f8", + "Longleftrightarrow;": "\u27fa", + "Longrightarrow;": "\u27f9", + "Lopf;": "\U0001d543", + "LowerLeftArrow;": "\u2199", + "LowerRightArrow;": "\u2198", + "Lscr;": "\u2112", + "Lsh;": "\u21b0", + "Lstrok;": "\u0141", + "Lt;": "\u226a", + "Map;": "\u2905", + "Mcy;": "\u041c", + "MediumSpace;": "\u205f", + "Mellintrf;": "\u2133", + "Mfr;": "\U0001d510", + "MinusPlus;": "\u2213", + "Mopf;": "\U0001d544", + "Mscr;": "\u2133", + "Mu;": "\u039c", + "NJcy;": "\u040a", + "Nacute;": "\u0143", + "Ncaron;": "\u0147", + "Ncedil;": "\u0145", + "Ncy;": "\u041d", + "NegativeMediumSpace;": "\u200b", + "NegativeThickSpace;": "\u200b", + "NegativeThinSpace;": "\u200b", + "NegativeVeryThinSpace;": "\u200b", + "NestedGreaterGreater;": "\u226b", + "NestedLessLess;": "\u226a", + "NewLine;": "\n", + "Nfr;": "\U0001d511", + "NoBreak;": "\u2060", + "NonBreakingSpace;": "\xa0", + "Nopf;": "\u2115", + "Not;": "\u2aec", + "NotCongruent;": "\u2262", + "NotCupCap;": "\u226d", + "NotDoubleVerticalBar;": "\u2226", + "NotElement;": "\u2209", + "NotEqual;": "\u2260", + "NotEqualTilde;": "\u2242\u0338", + "NotExists;": "\u2204", + "NotGreater;": "\u226f", + "NotGreaterEqual;": "\u2271", + "NotGreaterFullEqual;": "\u2267\u0338", + "NotGreaterGreater;": "\u226b\u0338", + "NotGreaterLess;": "\u2279", + "NotGreaterSlantEqual;": "\u2a7e\u0338", + "NotGreaterTilde;": "\u2275", + "NotHumpDownHump;": "\u224e\u0338", + "NotHumpEqual;": "\u224f\u0338", + "NotLeftTriangle;": "\u22ea", + "NotLeftTriangleBar;": "\u29cf\u0338", + "NotLeftTriangleEqual;": "\u22ec", + "NotLess;": "\u226e", + "NotLessEqual;": "\u2270", + "NotLessGreater;": "\u2278", + "NotLessLess;": "\u226a\u0338", + "NotLessSlantEqual;": "\u2a7d\u0338", + "NotLessTilde;": "\u2274", + "NotNestedGreaterGreater;": "\u2aa2\u0338", + "NotNestedLessLess;": "\u2aa1\u0338", + "NotPrecedes;": "\u2280", + "NotPrecedesEqual;": "\u2aaf\u0338", + "NotPrecedesSlantEqual;": "\u22e0", + "NotReverseElement;": "\u220c", + "NotRightTriangle;": "\u22eb", + "NotRightTriangleBar;": "\u29d0\u0338", + "NotRightTriangleEqual;": "\u22ed", + "NotSquareSubset;": "\u228f\u0338", + "NotSquareSubsetEqual;": "\u22e2", + "NotSquareSuperset;": "\u2290\u0338", + "NotSquareSupersetEqual;": "\u22e3", + "NotSubset;": "\u2282\u20d2", + "NotSubsetEqual;": "\u2288", + "NotSucceeds;": "\u2281", + "NotSucceedsEqual;": "\u2ab0\u0338", + "NotSucceedsSlantEqual;": "\u22e1", + "NotSucceedsTilde;": "\u227f\u0338", + "NotSuperset;": "\u2283\u20d2", + "NotSupersetEqual;": "\u2289", + "NotTilde;": "\u2241", + "NotTildeEqual;": "\u2244", + "NotTildeFullEqual;": "\u2247", + "NotTildeTilde;": "\u2249", + "NotVerticalBar;": "\u2224", + "Nscr;": "\U0001d4a9", + "Ntilde": "\xd1", + "Ntilde;": "\xd1", + "Nu;": "\u039d", + "OElig;": "\u0152", + "Oacute": "\xd3", + "Oacute;": "\xd3", + "Ocirc": "\xd4", + "Ocirc;": "\xd4", + "Ocy;": "\u041e", + "Odblac;": "\u0150", + "Ofr;": "\U0001d512", + "Ograve": "\xd2", + "Ograve;": "\xd2", + "Omacr;": "\u014c", + "Omega;": "\u03a9", + "Omicron;": "\u039f", + "Oopf;": "\U0001d546", + "OpenCurlyDoubleQuote;": "\u201c", + "OpenCurlyQuote;": "\u2018", + "Or;": "\u2a54", + "Oscr;": "\U0001d4aa", + "Oslash": "\xd8", + "Oslash;": "\xd8", + "Otilde": "\xd5", + "Otilde;": "\xd5", + "Otimes;": "\u2a37", + "Ouml": "\xd6", + "Ouml;": "\xd6", + "OverBar;": "\u203e", + "OverBrace;": "\u23de", + "OverBracket;": "\u23b4", + "OverParenthesis;": "\u23dc", + "PartialD;": "\u2202", + "Pcy;": "\u041f", + "Pfr;": "\U0001d513", + "Phi;": "\u03a6", + "Pi;": "\u03a0", + "PlusMinus;": "\xb1", + "Poincareplane;": "\u210c", + "Popf;": "\u2119", + "Pr;": "\u2abb", + "Precedes;": "\u227a", + "PrecedesEqual;": "\u2aaf", + "PrecedesSlantEqual;": "\u227c", + "PrecedesTilde;": "\u227e", + "Prime;": "\u2033", + "Product;": "\u220f", + "Proportion;": "\u2237", + "Proportional;": "\u221d", + "Pscr;": "\U0001d4ab", + "Psi;": "\u03a8", + "QUOT": "\"", + "QUOT;": "\"", + "Qfr;": "\U0001d514", + "Qopf;": "\u211a", + "Qscr;": "\U0001d4ac", + "RBarr;": "\u2910", + "REG": "\xae", + "REG;": "\xae", + "Racute;": "\u0154", + "Rang;": "\u27eb", + "Rarr;": "\u21a0", + "Rarrtl;": "\u2916", + "Rcaron;": "\u0158", + "Rcedil;": "\u0156", + "Rcy;": "\u0420", + "Re;": "\u211c", + "ReverseElement;": "\u220b", + "ReverseEquilibrium;": "\u21cb", + "ReverseUpEquilibrium;": "\u296f", + "Rfr;": "\u211c", + "Rho;": "\u03a1", + "RightAngleBracket;": "\u27e9", + "RightArrow;": "\u2192", + "RightArrowBar;": "\u21e5", + "RightArrowLeftArrow;": "\u21c4", + "RightCeiling;": "\u2309", + "RightDoubleBracket;": "\u27e7", + "RightDownTeeVector;": "\u295d", + "RightDownVector;": "\u21c2", + "RightDownVectorBar;": "\u2955", + "RightFloor;": "\u230b", + "RightTee;": "\u22a2", + "RightTeeArrow;": "\u21a6", + "RightTeeVector;": "\u295b", + "RightTriangle;": "\u22b3", + "RightTriangleBar;": "\u29d0", + "RightTriangleEqual;": "\u22b5", + "RightUpDownVector;": "\u294f", + "RightUpTeeVector;": "\u295c", + "RightUpVector;": "\u21be", + "RightUpVectorBar;": "\u2954", + "RightVector;": "\u21c0", + "RightVectorBar;": "\u2953", + "Rightarrow;": "\u21d2", + "Ropf;": "\u211d", + "RoundImplies;": "\u2970", + "Rrightarrow;": "\u21db", + "Rscr;": "\u211b", + "Rsh;": "\u21b1", + "RuleDelayed;": "\u29f4", + "SHCHcy;": "\u0429", + "SHcy;": "\u0428", + "SOFTcy;": "\u042c", + "Sacute;": "\u015a", + "Sc;": "\u2abc", + "Scaron;": "\u0160", + "Scedil;": "\u015e", + "Scirc;": "\u015c", + "Scy;": "\u0421", + "Sfr;": "\U0001d516", + "ShortDownArrow;": "\u2193", + "ShortLeftArrow;": "\u2190", + "ShortRightArrow;": "\u2192", + "ShortUpArrow;": "\u2191", + "Sigma;": "\u03a3", + "SmallCircle;": "\u2218", + "Sopf;": "\U0001d54a", + "Sqrt;": "\u221a", + "Square;": "\u25a1", + "SquareIntersection;": "\u2293", + "SquareSubset;": "\u228f", + "SquareSubsetEqual;": "\u2291", + "SquareSuperset;": "\u2290", + "SquareSupersetEqual;": "\u2292", + "SquareUnion;": "\u2294", + "Sscr;": "\U0001d4ae", + "Star;": "\u22c6", + "Sub;": "\u22d0", + "Subset;": "\u22d0", + "SubsetEqual;": "\u2286", + "Succeeds;": "\u227b", + "SucceedsEqual;": "\u2ab0", + "SucceedsSlantEqual;": "\u227d", + "SucceedsTilde;": "\u227f", + "SuchThat;": "\u220b", + "Sum;": "\u2211", + "Sup;": "\u22d1", + "Superset;": "\u2283", + "SupersetEqual;": "\u2287", + "Supset;": "\u22d1", + "THORN": "\xde", + "THORN;": "\xde", + "TRADE;": "\u2122", + "TSHcy;": "\u040b", + "TScy;": "\u0426", + "Tab;": "\t", + "Tau;": "\u03a4", + "Tcaron;": "\u0164", + "Tcedil;": "\u0162", + "Tcy;": "\u0422", + "Tfr;": "\U0001d517", + "Therefore;": "\u2234", + "Theta;": "\u0398", + "ThickSpace;": "\u205f\u200a", + "ThinSpace;": "\u2009", + "Tilde;": "\u223c", + "TildeEqual;": "\u2243", + "TildeFullEqual;": "\u2245", + "TildeTilde;": "\u2248", + "Topf;": "\U0001d54b", + "TripleDot;": "\u20db", + "Tscr;": "\U0001d4af", + "Tstrok;": "\u0166", + "Uacute": "\xda", + "Uacute;": "\xda", + "Uarr;": "\u219f", + "Uarrocir;": "\u2949", + "Ubrcy;": "\u040e", + "Ubreve;": "\u016c", + "Ucirc": "\xdb", + "Ucirc;": "\xdb", + "Ucy;": "\u0423", + "Udblac;": "\u0170", + "Ufr;": "\U0001d518", + "Ugrave": "\xd9", + "Ugrave;": "\xd9", + "Umacr;": "\u016a", + "UnderBar;": "_", + "UnderBrace;": "\u23df", + "UnderBracket;": "\u23b5", + "UnderParenthesis;": "\u23dd", + "Union;": "\u22c3", + "UnionPlus;": "\u228e", + "Uogon;": "\u0172", + "Uopf;": "\U0001d54c", + "UpArrow;": "\u2191", + "UpArrowBar;": "\u2912", + "UpArrowDownArrow;": "\u21c5", + "UpDownArrow;": "\u2195", + "UpEquilibrium;": "\u296e", + "UpTee;": "\u22a5", + "UpTeeArrow;": "\u21a5", + "Uparrow;": "\u21d1", + "Updownarrow;": "\u21d5", + "UpperLeftArrow;": "\u2196", + "UpperRightArrow;": "\u2197", + "Upsi;": "\u03d2", + "Upsilon;": "\u03a5", + "Uring;": "\u016e", + "Uscr;": "\U0001d4b0", + "Utilde;": "\u0168", + "Uuml": "\xdc", + "Uuml;": "\xdc", + "VDash;": "\u22ab", + "Vbar;": "\u2aeb", + "Vcy;": "\u0412", + "Vdash;": "\u22a9", + "Vdashl;": "\u2ae6", + "Vee;": "\u22c1", + "Verbar;": "\u2016", + "Vert;": "\u2016", + "VerticalBar;": "\u2223", + "VerticalLine;": "|", + "VerticalSeparator;": "\u2758", + "VerticalTilde;": "\u2240", + "VeryThinSpace;": "\u200a", + "Vfr;": "\U0001d519", + "Vopf;": "\U0001d54d", + "Vscr;": "\U0001d4b1", + "Vvdash;": "\u22aa", + "Wcirc;": "\u0174", + "Wedge;": "\u22c0", + "Wfr;": "\U0001d51a", + "Wopf;": "\U0001d54e", + "Wscr;": "\U0001d4b2", + "Xfr;": "\U0001d51b", + "Xi;": "\u039e", + "Xopf;": "\U0001d54f", + "Xscr;": "\U0001d4b3", + "YAcy;": "\u042f", + "YIcy;": "\u0407", + "YUcy;": "\u042e", + "Yacute": "\xdd", + "Yacute;": "\xdd", + "Ycirc;": "\u0176", + "Ycy;": "\u042b", + "Yfr;": "\U0001d51c", + "Yopf;": "\U0001d550", + "Yscr;": "\U0001d4b4", + "Yuml;": "\u0178", + "ZHcy;": "\u0416", + "Zacute;": "\u0179", + "Zcaron;": "\u017d", + "Zcy;": "\u0417", + "Zdot;": "\u017b", + "ZeroWidthSpace;": "\u200b", + "Zeta;": "\u0396", + "Zfr;": "\u2128", + "Zopf;": "\u2124", + "Zscr;": "\U0001d4b5", + "aacute": "\xe1", + "aacute;": "\xe1", + "abreve;": "\u0103", + "ac;": "\u223e", + "acE;": "\u223e\u0333", + "acd;": "\u223f", + "acirc": "\xe2", + "acirc;": "\xe2", + "acute": "\xb4", + "acute;": "\xb4", + "acy;": "\u0430", + "aelig": "\xe6", + "aelig;": "\xe6", + "af;": "\u2061", + "afr;": "\U0001d51e", + "agrave": "\xe0", + "agrave;": "\xe0", + "alefsym;": "\u2135", + "aleph;": "\u2135", + "alpha;": "\u03b1", + "amacr;": "\u0101", + "amalg;": "\u2a3f", + "amp": "&", + "amp;": "&", + "and;": "\u2227", + "andand;": "\u2a55", + "andd;": "\u2a5c", + "andslope;": "\u2a58", + "andv;": "\u2a5a", + "ang;": "\u2220", + "ange;": "\u29a4", + "angle;": "\u2220", + "angmsd;": "\u2221", + "angmsdaa;": "\u29a8", + "angmsdab;": "\u29a9", + "angmsdac;": "\u29aa", + "angmsdad;": "\u29ab", + "angmsdae;": "\u29ac", + "angmsdaf;": "\u29ad", + "angmsdag;": "\u29ae", + "angmsdah;": "\u29af", + "angrt;": "\u221f", + "angrtvb;": "\u22be", + "angrtvbd;": "\u299d", + "angsph;": "\u2222", + "angst;": "\xc5", + "angzarr;": "\u237c", + "aogon;": "\u0105", + "aopf;": "\U0001d552", + "ap;": "\u2248", + "apE;": "\u2a70", + "apacir;": "\u2a6f", + "ape;": "\u224a", + "apid;": "\u224b", + "apos;": "'", + "approx;": "\u2248", + "approxeq;": "\u224a", + "aring": "\xe5", + "aring;": "\xe5", + "ascr;": "\U0001d4b6", + "ast;": "*", + "asymp;": "\u2248", + "asympeq;": "\u224d", + "atilde": "\xe3", + "atilde;": "\xe3", + "auml": "\xe4", + "auml;": "\xe4", + "awconint;": "\u2233", + "awint;": "\u2a11", + "bNot;": "\u2aed", + "backcong;": "\u224c", + "backepsilon;": "\u03f6", + "backprime;": "\u2035", + "backsim;": "\u223d", + "backsimeq;": "\u22cd", + "barvee;": "\u22bd", + "barwed;": "\u2305", + "barwedge;": "\u2305", + "bbrk;": "\u23b5", + "bbrktbrk;": "\u23b6", + "bcong;": "\u224c", + "bcy;": "\u0431", + "bdquo;": "\u201e", + "becaus;": "\u2235", + "because;": "\u2235", + "bemptyv;": "\u29b0", + "bepsi;": "\u03f6", + "bernou;": "\u212c", + "beta;": "\u03b2", + "beth;": "\u2136", + "between;": "\u226c", + "bfr;": "\U0001d51f", + "bigcap;": "\u22c2", + "bigcirc;": "\u25ef", + "bigcup;": "\u22c3", + "bigodot;": "\u2a00", + "bigoplus;": "\u2a01", + "bigotimes;": "\u2a02", + "bigsqcup;": "\u2a06", + "bigstar;": "\u2605", + "bigtriangledown;": "\u25bd", + "bigtriangleup;": "\u25b3", + "biguplus;": "\u2a04", + "bigvee;": "\u22c1", + "bigwedge;": "\u22c0", + "bkarow;": "\u290d", + "blacklozenge;": "\u29eb", + "blacksquare;": "\u25aa", + "blacktriangle;": "\u25b4", + "blacktriangledown;": "\u25be", + "blacktriangleleft;": "\u25c2", + "blacktriangleright;": "\u25b8", + "blank;": "\u2423", + "blk12;": "\u2592", + "blk14;": "\u2591", + "blk34;": "\u2593", + "block;": "\u2588", + "bne;": "=\u20e5", + "bnequiv;": "\u2261\u20e5", + "bnot;": "\u2310", + "bopf;": "\U0001d553", + "bot;": "\u22a5", + "bottom;": "\u22a5", + "bowtie;": "\u22c8", + "boxDL;": "\u2557", + "boxDR;": "\u2554", + "boxDl;": "\u2556", + "boxDr;": "\u2553", + "boxH;": "\u2550", + "boxHD;": "\u2566", + "boxHU;": "\u2569", + "boxHd;": "\u2564", + "boxHu;": "\u2567", + "boxUL;": "\u255d", + "boxUR;": "\u255a", + "boxUl;": "\u255c", + "boxUr;": "\u2559", + "boxV;": "\u2551", + "boxVH;": "\u256c", + "boxVL;": "\u2563", + "boxVR;": "\u2560", + "boxVh;": "\u256b", + "boxVl;": "\u2562", + "boxVr;": "\u255f", + "boxbox;": "\u29c9", + "boxdL;": "\u2555", + "boxdR;": "\u2552", + "boxdl;": "\u2510", + "boxdr;": "\u250c", + "boxh;": "\u2500", + "boxhD;": "\u2565", + "boxhU;": "\u2568", + "boxhd;": "\u252c", + "boxhu;": "\u2534", + "boxminus;": "\u229f", + "boxplus;": "\u229e", + "boxtimes;": "\u22a0", + "boxuL;": "\u255b", + "boxuR;": "\u2558", + "boxul;": "\u2518", + "boxur;": "\u2514", + "boxv;": "\u2502", + "boxvH;": "\u256a", + "boxvL;": "\u2561", + "boxvR;": "\u255e", + "boxvh;": "\u253c", + "boxvl;": "\u2524", + "boxvr;": "\u251c", + "bprime;": "\u2035", + "breve;": "\u02d8", + "brvbar": "\xa6", + "brvbar;": "\xa6", + "bscr;": "\U0001d4b7", + "bsemi;": "\u204f", + "bsim;": "\u223d", + "bsime;": "\u22cd", + "bsol;": "\\", + "bsolb;": "\u29c5", + "bsolhsub;": "\u27c8", + "bull;": "\u2022", + "bullet;": "\u2022", + "bump;": "\u224e", + "bumpE;": "\u2aae", + "bumpe;": "\u224f", + "bumpeq;": "\u224f", + "cacute;": "\u0107", + "cap;": "\u2229", + "capand;": "\u2a44", + "capbrcup;": "\u2a49", + "capcap;": "\u2a4b", + "capcup;": "\u2a47", + "capdot;": "\u2a40", + "caps;": "\u2229\ufe00", + "caret;": "\u2041", + "caron;": "\u02c7", + "ccaps;": "\u2a4d", + "ccaron;": "\u010d", + "ccedil": "\xe7", + "ccedil;": "\xe7", + "ccirc;": "\u0109", + "ccups;": "\u2a4c", + "ccupssm;": "\u2a50", + "cdot;": "\u010b", + "cedil": "\xb8", + "cedil;": "\xb8", + "cemptyv;": "\u29b2", + "cent": "\xa2", + "cent;": "\xa2", + "centerdot;": "\xb7", + "cfr;": "\U0001d520", + "chcy;": "\u0447", + "check;": "\u2713", + "checkmark;": "\u2713", + "chi;": "\u03c7", + "cir;": "\u25cb", + "cirE;": "\u29c3", + "circ;": "\u02c6", + "circeq;": "\u2257", + "circlearrowleft;": "\u21ba", + "circlearrowright;": "\u21bb", + "circledR;": "\xae", + "circledS;": "\u24c8", + "circledast;": "\u229b", + "circledcirc;": "\u229a", + "circleddash;": "\u229d", + "cire;": "\u2257", + "cirfnint;": "\u2a10", + "cirmid;": "\u2aef", + "cirscir;": "\u29c2", + "clubs;": "\u2663", + "clubsuit;": "\u2663", + "colon;": ":", + "colone;": "\u2254", + "coloneq;": "\u2254", + "comma;": ",", + "commat;": "@", + "comp;": "\u2201", + "compfn;": "\u2218", + "complement;": "\u2201", + "complexes;": "\u2102", + "cong;": "\u2245", + "congdot;": "\u2a6d", + "conint;": "\u222e", + "copf;": "\U0001d554", + "coprod;": "\u2210", + "copy": "\xa9", + "copy;": "\xa9", + "copysr;": "\u2117", + "crarr;": "\u21b5", + "cross;": "\u2717", + "cscr;": "\U0001d4b8", + "csub;": "\u2acf", + "csube;": "\u2ad1", + "csup;": "\u2ad0", + "csupe;": "\u2ad2", + "ctdot;": "\u22ef", + "cudarrl;": "\u2938", + "cudarrr;": "\u2935", + "cuepr;": "\u22de", + "cuesc;": "\u22df", + "cularr;": "\u21b6", + "cularrp;": "\u293d", + "cup;": "\u222a", + "cupbrcap;": "\u2a48", + "cupcap;": "\u2a46", + "cupcup;": "\u2a4a", + "cupdot;": "\u228d", + "cupor;": "\u2a45", + "cups;": "\u222a\ufe00", + "curarr;": "\u21b7", + "curarrm;": "\u293c", + "curlyeqprec;": "\u22de", + "curlyeqsucc;": "\u22df", + "curlyvee;": "\u22ce", + "curlywedge;": "\u22cf", + "curren": "\xa4", + "curren;": "\xa4", + "curvearrowleft;": "\u21b6", + "curvearrowright;": "\u21b7", + "cuvee;": "\u22ce", + "cuwed;": "\u22cf", + "cwconint;": "\u2232", + "cwint;": "\u2231", + "cylcty;": "\u232d", + "dArr;": "\u21d3", + "dHar;": "\u2965", + "dagger;": "\u2020", + "daleth;": "\u2138", + "darr;": "\u2193", + "dash;": "\u2010", + "dashv;": "\u22a3", + "dbkarow;": "\u290f", + "dblac;": "\u02dd", + "dcaron;": "\u010f", + "dcy;": "\u0434", + "dd;": "\u2146", + "ddagger;": "\u2021", + "ddarr;": "\u21ca", + "ddotseq;": "\u2a77", + "deg": "\xb0", + "deg;": "\xb0", + "delta;": "\u03b4", + "demptyv;": "\u29b1", + "dfisht;": "\u297f", + "dfr;": "\U0001d521", + "dharl;": "\u21c3", + "dharr;": "\u21c2", + "diam;": "\u22c4", + "diamond;": "\u22c4", + "diamondsuit;": "\u2666", + "diams;": "\u2666", + "die;": "\xa8", + "digamma;": "\u03dd", + "disin;": "\u22f2", + "div;": "\xf7", + "divide": "\xf7", + "divide;": "\xf7", + "divideontimes;": "\u22c7", + "divonx;": "\u22c7", + "djcy;": "\u0452", + "dlcorn;": "\u231e", + "dlcrop;": "\u230d", + "dollar;": "$", + "dopf;": "\U0001d555", + "dot;": "\u02d9", + "doteq;": "\u2250", + "doteqdot;": "\u2251", + "dotminus;": "\u2238", + "dotplus;": "\u2214", + "dotsquare;": "\u22a1", + "doublebarwedge;": "\u2306", + "downarrow;": "\u2193", + "downdownarrows;": "\u21ca", + "downharpoonleft;": "\u21c3", + "downharpoonright;": "\u21c2", + "drbkarow;": "\u2910", + "drcorn;": "\u231f", + "drcrop;": "\u230c", + "dscr;": "\U0001d4b9", + "dscy;": "\u0455", + "dsol;": "\u29f6", + "dstrok;": "\u0111", + "dtdot;": "\u22f1", + "dtri;": "\u25bf", + "dtrif;": "\u25be", + "duarr;": "\u21f5", + "duhar;": "\u296f", + "dwangle;": "\u29a6", + "dzcy;": "\u045f", + "dzigrarr;": "\u27ff", + "eDDot;": "\u2a77", + "eDot;": "\u2251", + "eacute": "\xe9", + "eacute;": "\xe9", + "easter;": "\u2a6e", + "ecaron;": "\u011b", + "ecir;": "\u2256", + "ecirc": "\xea", + "ecirc;": "\xea", + "ecolon;": "\u2255", + "ecy;": "\u044d", + "edot;": "\u0117", + "ee;": "\u2147", + "efDot;": "\u2252", + "efr;": "\U0001d522", + "eg;": "\u2a9a", + "egrave": "\xe8", + "egrave;": "\xe8", + "egs;": "\u2a96", + "egsdot;": "\u2a98", + "el;": "\u2a99", + "elinters;": "\u23e7", + "ell;": "\u2113", + "els;": "\u2a95", + "elsdot;": "\u2a97", + "emacr;": "\u0113", + "empty;": "\u2205", + "emptyset;": "\u2205", + "emptyv;": "\u2205", + "emsp13;": "\u2004", + "emsp14;": "\u2005", + "emsp;": "\u2003", + "eng;": "\u014b", + "ensp;": "\u2002", + "eogon;": "\u0119", + "eopf;": "\U0001d556", + "epar;": "\u22d5", + "eparsl;": "\u29e3", + "eplus;": "\u2a71", + "epsi;": "\u03b5", + "epsilon;": "\u03b5", + "epsiv;": "\u03f5", + "eqcirc;": "\u2256", + "eqcolon;": "\u2255", + "eqsim;": "\u2242", + "eqslantgtr;": "\u2a96", + "eqslantless;": "\u2a95", + "equals;": "=", + "equest;": "\u225f", + "equiv;": "\u2261", + "equivDD;": "\u2a78", + "eqvparsl;": "\u29e5", + "erDot;": "\u2253", + "erarr;": "\u2971", + "escr;": "\u212f", + "esdot;": "\u2250", + "esim;": "\u2242", + "eta;": "\u03b7", + "eth": "\xf0", + "eth;": "\xf0", + "euml": "\xeb", + "euml;": "\xeb", + "euro;": "\u20ac", + "excl;": "!", + "exist;": "\u2203", + "expectation;": "\u2130", + "exponentiale;": "\u2147", + "fallingdotseq;": "\u2252", + "fcy;": "\u0444", + "female;": "\u2640", + "ffilig;": "\ufb03", + "fflig;": "\ufb00", + "ffllig;": "\ufb04", + "ffr;": "\U0001d523", + "filig;": "\ufb01", + "fjlig;": "fj", + "flat;": "\u266d", + "fllig;": "\ufb02", + "fltns;": "\u25b1", + "fnof;": "\u0192", + "fopf;": "\U0001d557", + "forall;": "\u2200", + "fork;": "\u22d4", + "forkv;": "\u2ad9", + "fpartint;": "\u2a0d", + "frac12": "\xbd", + "frac12;": "\xbd", + "frac13;": "\u2153", + "frac14": "\xbc", + "frac14;": "\xbc", + "frac15;": "\u2155", + "frac16;": "\u2159", + "frac18;": "\u215b", + "frac23;": "\u2154", + "frac25;": "\u2156", + "frac34": "\xbe", + "frac34;": "\xbe", + "frac35;": "\u2157", + "frac38;": "\u215c", + "frac45;": "\u2158", + "frac56;": "\u215a", + "frac58;": "\u215d", + "frac78;": "\u215e", + "frasl;": "\u2044", + "frown;": "\u2322", + "fscr;": "\U0001d4bb", + "gE;": "\u2267", + "gEl;": "\u2a8c", + "gacute;": "\u01f5", + "gamma;": "\u03b3", + "gammad;": "\u03dd", + "gap;": "\u2a86", + "gbreve;": "\u011f", + "gcirc;": "\u011d", + "gcy;": "\u0433", + "gdot;": "\u0121", + "ge;": "\u2265", + "gel;": "\u22db", + "geq;": "\u2265", + "geqq;": "\u2267", + "geqslant;": "\u2a7e", + "ges;": "\u2a7e", + "gescc;": "\u2aa9", + "gesdot;": "\u2a80", + "gesdoto;": "\u2a82", + "gesdotol;": "\u2a84", + "gesl;": "\u22db\ufe00", + "gesles;": "\u2a94", + "gfr;": "\U0001d524", + "gg;": "\u226b", + "ggg;": "\u22d9", + "gimel;": "\u2137", + "gjcy;": "\u0453", + "gl;": "\u2277", + "glE;": "\u2a92", + "gla;": "\u2aa5", + "glj;": "\u2aa4", + "gnE;": "\u2269", + "gnap;": "\u2a8a", + "gnapprox;": "\u2a8a", + "gne;": "\u2a88", + "gneq;": "\u2a88", + "gneqq;": "\u2269", + "gnsim;": "\u22e7", + "gopf;": "\U0001d558", + "grave;": "`", + "gscr;": "\u210a", + "gsim;": "\u2273", + "gsime;": "\u2a8e", + "gsiml;": "\u2a90", + "gt": ">", + "gt;": ">", + "gtcc;": "\u2aa7", + "gtcir;": "\u2a7a", + "gtdot;": "\u22d7", + "gtlPar;": "\u2995", + "gtquest;": "\u2a7c", + "gtrapprox;": "\u2a86", + "gtrarr;": "\u2978", + "gtrdot;": "\u22d7", + "gtreqless;": "\u22db", + "gtreqqless;": "\u2a8c", + "gtrless;": "\u2277", + "gtrsim;": "\u2273", + "gvertneqq;": "\u2269\ufe00", + "gvnE;": "\u2269\ufe00", + "hArr;": "\u21d4", + "hairsp;": "\u200a", + "half;": "\xbd", + "hamilt;": "\u210b", + "hardcy;": "\u044a", + "harr;": "\u2194", + "harrcir;": "\u2948", + "harrw;": "\u21ad", + "hbar;": "\u210f", + "hcirc;": "\u0125", + "hearts;": "\u2665", + "heartsuit;": "\u2665", + "hellip;": "\u2026", + "hercon;": "\u22b9", + "hfr;": "\U0001d525", + "hksearow;": "\u2925", + "hkswarow;": "\u2926", + "hoarr;": "\u21ff", + "homtht;": "\u223b", + "hookleftarrow;": "\u21a9", + "hookrightarrow;": "\u21aa", + "hopf;": "\U0001d559", + "horbar;": "\u2015", + "hscr;": "\U0001d4bd", + "hslash;": "\u210f", + "hstrok;": "\u0127", + "hybull;": "\u2043", + "hyphen;": "\u2010", + "iacute": "\xed", + "iacute;": "\xed", + "ic;": "\u2063", + "icirc": "\xee", + "icirc;": "\xee", + "icy;": "\u0438", + "iecy;": "\u0435", + "iexcl": "\xa1", + "iexcl;": "\xa1", + "iff;": "\u21d4", + "ifr;": "\U0001d526", + "igrave": "\xec", + "igrave;": "\xec", + "ii;": "\u2148", + "iiiint;": "\u2a0c", + "iiint;": "\u222d", + "iinfin;": "\u29dc", + "iiota;": "\u2129", + "ijlig;": "\u0133", + "imacr;": "\u012b", + "image;": "\u2111", + "imagline;": "\u2110", + "imagpart;": "\u2111", + "imath;": "\u0131", + "imof;": "\u22b7", + "imped;": "\u01b5", + "in;": "\u2208", + "incare;": "\u2105", + "infin;": "\u221e", + "infintie;": "\u29dd", + "inodot;": "\u0131", + "int;": "\u222b", + "intcal;": "\u22ba", + "integers;": "\u2124", + "intercal;": "\u22ba", + "intlarhk;": "\u2a17", + "intprod;": "\u2a3c", + "iocy;": "\u0451", + "iogon;": "\u012f", + "iopf;": "\U0001d55a", + "iota;": "\u03b9", + "iprod;": "\u2a3c", + "iquest": "\xbf", + "iquest;": "\xbf", + "iscr;": "\U0001d4be", + "isin;": "\u2208", + "isinE;": "\u22f9", + "isindot;": "\u22f5", + "isins;": "\u22f4", + "isinsv;": "\u22f3", + "isinv;": "\u2208", + "it;": "\u2062", + "itilde;": "\u0129", + "iukcy;": "\u0456", + "iuml": "\xef", + "iuml;": "\xef", + "jcirc;": "\u0135", + "jcy;": "\u0439", + "jfr;": "\U0001d527", + "jmath;": "\u0237", + "jopf;": "\U0001d55b", + "jscr;": "\U0001d4bf", + "jsercy;": "\u0458", + "jukcy;": "\u0454", + "kappa;": "\u03ba", + "kappav;": "\u03f0", + "kcedil;": "\u0137", + "kcy;": "\u043a", + "kfr;": "\U0001d528", + "kgreen;": "\u0138", + "khcy;": "\u0445", + "kjcy;": "\u045c", + "kopf;": "\U0001d55c", + "kscr;": "\U0001d4c0", + "lAarr;": "\u21da", + "lArr;": "\u21d0", + "lAtail;": "\u291b", + "lBarr;": "\u290e", + "lE;": "\u2266", + "lEg;": "\u2a8b", + "lHar;": "\u2962", + "lacute;": "\u013a", + "laemptyv;": "\u29b4", + "lagran;": "\u2112", + "lambda;": "\u03bb", + "lang;": "\u27e8", + "langd;": "\u2991", + "langle;": "\u27e8", + "lap;": "\u2a85", + "laquo": "\xab", + "laquo;": "\xab", + "larr;": "\u2190", + "larrb;": "\u21e4", + "larrbfs;": "\u291f", + "larrfs;": "\u291d", + "larrhk;": "\u21a9", + "larrlp;": "\u21ab", + "larrpl;": "\u2939", + "larrsim;": "\u2973", + "larrtl;": "\u21a2", + "lat;": "\u2aab", + "latail;": "\u2919", + "late;": "\u2aad", + "lates;": "\u2aad\ufe00", + "lbarr;": "\u290c", + "lbbrk;": "\u2772", + "lbrace;": "{", + "lbrack;": "[", + "lbrke;": "\u298b", + "lbrksld;": "\u298f", + "lbrkslu;": "\u298d", + "lcaron;": "\u013e", + "lcedil;": "\u013c", + "lceil;": "\u2308", + "lcub;": "{", + "lcy;": "\u043b", + "ldca;": "\u2936", + "ldquo;": "\u201c", + "ldquor;": "\u201e", + "ldrdhar;": "\u2967", + "ldrushar;": "\u294b", + "ldsh;": "\u21b2", + "le;": "\u2264", + "leftarrow;": "\u2190", + "leftarrowtail;": "\u21a2", + "leftharpoondown;": "\u21bd", + "leftharpoonup;": "\u21bc", + "leftleftarrows;": "\u21c7", + "leftrightarrow;": "\u2194", + "leftrightarrows;": "\u21c6", + "leftrightharpoons;": "\u21cb", + "leftrightsquigarrow;": "\u21ad", + "leftthreetimes;": "\u22cb", + "leg;": "\u22da", + "leq;": "\u2264", + "leqq;": "\u2266", + "leqslant;": "\u2a7d", + "les;": "\u2a7d", + "lescc;": "\u2aa8", + "lesdot;": "\u2a7f", + "lesdoto;": "\u2a81", + "lesdotor;": "\u2a83", + "lesg;": "\u22da\ufe00", + "lesges;": "\u2a93", + "lessapprox;": "\u2a85", + "lessdot;": "\u22d6", + "lesseqgtr;": "\u22da", + "lesseqqgtr;": "\u2a8b", + "lessgtr;": "\u2276", + "lesssim;": "\u2272", + "lfisht;": "\u297c", + "lfloor;": "\u230a", + "lfr;": "\U0001d529", + "lg;": "\u2276", + "lgE;": "\u2a91", + "lhard;": "\u21bd", + "lharu;": "\u21bc", + "lharul;": "\u296a", + "lhblk;": "\u2584", + "ljcy;": "\u0459", + "ll;": "\u226a", + "llarr;": "\u21c7", + "llcorner;": "\u231e", + "llhard;": "\u296b", + "lltri;": "\u25fa", + "lmidot;": "\u0140", + "lmoust;": "\u23b0", + "lmoustache;": "\u23b0", + "lnE;": "\u2268", + "lnap;": "\u2a89", + "lnapprox;": "\u2a89", + "lne;": "\u2a87", + "lneq;": "\u2a87", + "lneqq;": "\u2268", + "lnsim;": "\u22e6", + "loang;": "\u27ec", + "loarr;": "\u21fd", + "lobrk;": "\u27e6", + "longleftarrow;": "\u27f5", + "longleftrightarrow;": "\u27f7", + "longmapsto;": "\u27fc", + "longrightarrow;": "\u27f6", + "looparrowleft;": "\u21ab", + "looparrowright;": "\u21ac", + "lopar;": "\u2985", + "lopf;": "\U0001d55d", + "loplus;": "\u2a2d", + "lotimes;": "\u2a34", + "lowast;": "\u2217", + "lowbar;": "_", + "loz;": "\u25ca", + "lozenge;": "\u25ca", + "lozf;": "\u29eb", + "lpar;": "(", + "lparlt;": "\u2993", + "lrarr;": "\u21c6", + "lrcorner;": "\u231f", + "lrhar;": "\u21cb", + "lrhard;": "\u296d", + "lrm;": "\u200e", + "lrtri;": "\u22bf", + "lsaquo;": "\u2039", + "lscr;": "\U0001d4c1", + "lsh;": "\u21b0", + "lsim;": "\u2272", + "lsime;": "\u2a8d", + "lsimg;": "\u2a8f", + "lsqb;": "[", + "lsquo;": "\u2018", + "lsquor;": "\u201a", + "lstrok;": "\u0142", + "lt": "<", + "lt;": "<", + "ltcc;": "\u2aa6", + "ltcir;": "\u2a79", + "ltdot;": "\u22d6", + "lthree;": "\u22cb", + "ltimes;": "\u22c9", + "ltlarr;": "\u2976", + "ltquest;": "\u2a7b", + "ltrPar;": "\u2996", + "ltri;": "\u25c3", + "ltrie;": "\u22b4", + "ltrif;": "\u25c2", + "lurdshar;": "\u294a", + "luruhar;": "\u2966", + "lvertneqq;": "\u2268\ufe00", + "lvnE;": "\u2268\ufe00", + "mDDot;": "\u223a", + "macr": "\xaf", + "macr;": "\xaf", + "male;": "\u2642", + "malt;": "\u2720", + "maltese;": "\u2720", + "map;": "\u21a6", + "mapsto;": "\u21a6", + "mapstodown;": "\u21a7", + "mapstoleft;": "\u21a4", + "mapstoup;": "\u21a5", + "marker;": "\u25ae", + "mcomma;": "\u2a29", + "mcy;": "\u043c", + "mdash;": "\u2014", + "measuredangle;": "\u2221", + "mfr;": "\U0001d52a", + "mho;": "\u2127", + "micro": "\xb5", + "micro;": "\xb5", + "mid;": "\u2223", + "midast;": "*", + "midcir;": "\u2af0", + "middot": "\xb7", + "middot;": "\xb7", + "minus;": "\u2212", + "minusb;": "\u229f", + "minusd;": "\u2238", + "minusdu;": "\u2a2a", + "mlcp;": "\u2adb", + "mldr;": "\u2026", + "mnplus;": "\u2213", + "models;": "\u22a7", + "mopf;": "\U0001d55e", + "mp;": "\u2213", + "mscr;": "\U0001d4c2", + "mstpos;": "\u223e", + "mu;": "\u03bc", + "multimap;": "\u22b8", + "mumap;": "\u22b8", + "nGg;": "\u22d9\u0338", + "nGt;": "\u226b\u20d2", + "nGtv;": "\u226b\u0338", + "nLeftarrow;": "\u21cd", + "nLeftrightarrow;": "\u21ce", + "nLl;": "\u22d8\u0338", + "nLt;": "\u226a\u20d2", + "nLtv;": "\u226a\u0338", + "nRightarrow;": "\u21cf", + "nVDash;": "\u22af", + "nVdash;": "\u22ae", + "nabla;": "\u2207", + "nacute;": "\u0144", + "nang;": "\u2220\u20d2", + "nap;": "\u2249", + "napE;": "\u2a70\u0338", + "napid;": "\u224b\u0338", + "napos;": "\u0149", + "napprox;": "\u2249", + "natur;": "\u266e", + "natural;": "\u266e", + "naturals;": "\u2115", + "nbsp": "\xa0", + "nbsp;": "\xa0", + "nbump;": "\u224e\u0338", + "nbumpe;": "\u224f\u0338", + "ncap;": "\u2a43", + "ncaron;": "\u0148", + "ncedil;": "\u0146", + "ncong;": "\u2247", + "ncongdot;": "\u2a6d\u0338", + "ncup;": "\u2a42", + "ncy;": "\u043d", + "ndash;": "\u2013", + "ne;": "\u2260", + "neArr;": "\u21d7", + "nearhk;": "\u2924", + "nearr;": "\u2197", + "nearrow;": "\u2197", + "nedot;": "\u2250\u0338", + "nequiv;": "\u2262", + "nesear;": "\u2928", + "nesim;": "\u2242\u0338", + "nexist;": "\u2204", + "nexists;": "\u2204", + "nfr;": "\U0001d52b", + "ngE;": "\u2267\u0338", + "nge;": "\u2271", + "ngeq;": "\u2271", + "ngeqq;": "\u2267\u0338", + "ngeqslant;": "\u2a7e\u0338", + "nges;": "\u2a7e\u0338", + "ngsim;": "\u2275", + "ngt;": "\u226f", + "ngtr;": "\u226f", + "nhArr;": "\u21ce", + "nharr;": "\u21ae", + "nhpar;": "\u2af2", + "ni;": "\u220b", + "nis;": "\u22fc", + "nisd;": "\u22fa", + "niv;": "\u220b", + "njcy;": "\u045a", + "nlArr;": "\u21cd", + "nlE;": "\u2266\u0338", + "nlarr;": "\u219a", + "nldr;": "\u2025", + "nle;": "\u2270", + "nleftarrow;": "\u219a", + "nleftrightarrow;": "\u21ae", + "nleq;": "\u2270", + "nleqq;": "\u2266\u0338", + "nleqslant;": "\u2a7d\u0338", + "nles;": "\u2a7d\u0338", + "nless;": "\u226e", + "nlsim;": "\u2274", + "nlt;": "\u226e", + "nltri;": "\u22ea", + "nltrie;": "\u22ec", + "nmid;": "\u2224", + "nopf;": "\U0001d55f", + "not": "\xac", + "not;": "\xac", + "notin;": "\u2209", + "notinE;": "\u22f9\u0338", + "notindot;": "\u22f5\u0338", + "notinva;": "\u2209", + "notinvb;": "\u22f7", + "notinvc;": "\u22f6", + "notni;": "\u220c", + "notniva;": "\u220c", + "notnivb;": "\u22fe", + "notnivc;": "\u22fd", + "npar;": "\u2226", + "nparallel;": "\u2226", + "nparsl;": "\u2afd\u20e5", + "npart;": "\u2202\u0338", + "npolint;": "\u2a14", + "npr;": "\u2280", + "nprcue;": "\u22e0", + "npre;": "\u2aaf\u0338", + "nprec;": "\u2280", + "npreceq;": "\u2aaf\u0338", + "nrArr;": "\u21cf", + "nrarr;": "\u219b", + "nrarrc;": "\u2933\u0338", + "nrarrw;": "\u219d\u0338", + "nrightarrow;": "\u219b", + "nrtri;": "\u22eb", + "nrtrie;": "\u22ed", + "nsc;": "\u2281", + "nsccue;": "\u22e1", + "nsce;": "\u2ab0\u0338", + "nscr;": "\U0001d4c3", + "nshortmid;": "\u2224", + "nshortparallel;": "\u2226", + "nsim;": "\u2241", + "nsime;": "\u2244", + "nsimeq;": "\u2244", + "nsmid;": "\u2224", + "nspar;": "\u2226", + "nsqsube;": "\u22e2", + "nsqsupe;": "\u22e3", + "nsub;": "\u2284", + "nsubE;": "\u2ac5\u0338", + "nsube;": "\u2288", + "nsubset;": "\u2282\u20d2", + "nsubseteq;": "\u2288", + "nsubseteqq;": "\u2ac5\u0338", + "nsucc;": "\u2281", + "nsucceq;": "\u2ab0\u0338", + "nsup;": "\u2285", + "nsupE;": "\u2ac6\u0338", + "nsupe;": "\u2289", + "nsupset;": "\u2283\u20d2", + "nsupseteq;": "\u2289", + "nsupseteqq;": "\u2ac6\u0338", + "ntgl;": "\u2279", + "ntilde": "\xf1", + "ntilde;": "\xf1", + "ntlg;": "\u2278", + "ntriangleleft;": "\u22ea", + "ntrianglelefteq;": "\u22ec", + "ntriangleright;": "\u22eb", + "ntrianglerighteq;": "\u22ed", + "nu;": "\u03bd", + "num;": "#", + "numero;": "\u2116", + "numsp;": "\u2007", + "nvDash;": "\u22ad", + "nvHarr;": "\u2904", + "nvap;": "\u224d\u20d2", + "nvdash;": "\u22ac", + "nvge;": "\u2265\u20d2", + "nvgt;": ">\u20d2", + "nvinfin;": "\u29de", + "nvlArr;": "\u2902", + "nvle;": "\u2264\u20d2", + "nvlt;": "<\u20d2", + "nvltrie;": "\u22b4\u20d2", + "nvrArr;": "\u2903", + "nvrtrie;": "\u22b5\u20d2", + "nvsim;": "\u223c\u20d2", + "nwArr;": "\u21d6", + "nwarhk;": "\u2923", + "nwarr;": "\u2196", + "nwarrow;": "\u2196", + "nwnear;": "\u2927", + "oS;": "\u24c8", + "oacute": "\xf3", + "oacute;": "\xf3", + "oast;": "\u229b", + "ocir;": "\u229a", + "ocirc": "\xf4", + "ocirc;": "\xf4", + "ocy;": "\u043e", + "odash;": "\u229d", + "odblac;": "\u0151", + "odiv;": "\u2a38", + "odot;": "\u2299", + "odsold;": "\u29bc", + "oelig;": "\u0153", + "ofcir;": "\u29bf", + "ofr;": "\U0001d52c", + "ogon;": "\u02db", + "ograve": "\xf2", + "ograve;": "\xf2", + "ogt;": "\u29c1", + "ohbar;": "\u29b5", + "ohm;": "\u03a9", + "oint;": "\u222e", + "olarr;": "\u21ba", + "olcir;": "\u29be", + "olcross;": "\u29bb", + "oline;": "\u203e", + "olt;": "\u29c0", + "omacr;": "\u014d", + "omega;": "\u03c9", + "omicron;": "\u03bf", + "omid;": "\u29b6", + "ominus;": "\u2296", + "oopf;": "\U0001d560", + "opar;": "\u29b7", + "operp;": "\u29b9", + "oplus;": "\u2295", + "or;": "\u2228", + "orarr;": "\u21bb", + "ord;": "\u2a5d", + "order;": "\u2134", + "orderof;": "\u2134", + "ordf": "\xaa", + "ordf;": "\xaa", + "ordm": "\xba", + "ordm;": "\xba", + "origof;": "\u22b6", + "oror;": "\u2a56", + "orslope;": "\u2a57", + "orv;": "\u2a5b", + "oscr;": "\u2134", + "oslash": "\xf8", + "oslash;": "\xf8", + "osol;": "\u2298", + "otilde": "\xf5", + "otilde;": "\xf5", + "otimes;": "\u2297", + "otimesas;": "\u2a36", + "ouml": "\xf6", + "ouml;": "\xf6", + "ovbar;": "\u233d", + "par;": "\u2225", + "para": "\xb6", + "para;": "\xb6", + "parallel;": "\u2225", + "parsim;": "\u2af3", + "parsl;": "\u2afd", + "part;": "\u2202", + "pcy;": "\u043f", + "percnt;": "%", + "period;": ".", + "permil;": "\u2030", + "perp;": "\u22a5", + "pertenk;": "\u2031", + "pfr;": "\U0001d52d", + "phi;": "\u03c6", + "phiv;": "\u03d5", + "phmmat;": "\u2133", + "phone;": "\u260e", + "pi;": "\u03c0", + "pitchfork;": "\u22d4", + "piv;": "\u03d6", + "planck;": "\u210f", + "planckh;": "\u210e", + "plankv;": "\u210f", + "plus;": "+", + "plusacir;": "\u2a23", + "plusb;": "\u229e", + "pluscir;": "\u2a22", + "plusdo;": "\u2214", + "plusdu;": "\u2a25", + "pluse;": "\u2a72", + "plusmn": "\xb1", + "plusmn;": "\xb1", + "plussim;": "\u2a26", + "plustwo;": "\u2a27", + "pm;": "\xb1", + "pointint;": "\u2a15", + "popf;": "\U0001d561", + "pound": "\xa3", + "pound;": "\xa3", + "pr;": "\u227a", + "prE;": "\u2ab3", + "prap;": "\u2ab7", + "prcue;": "\u227c", + "pre;": "\u2aaf", + "prec;": "\u227a", + "precapprox;": "\u2ab7", + "preccurlyeq;": "\u227c", + "preceq;": "\u2aaf", + "precnapprox;": "\u2ab9", + "precneqq;": "\u2ab5", + "precnsim;": "\u22e8", + "precsim;": "\u227e", + "prime;": "\u2032", + "primes;": "\u2119", + "prnE;": "\u2ab5", + "prnap;": "\u2ab9", + "prnsim;": "\u22e8", + "prod;": "\u220f", + "profalar;": "\u232e", + "profline;": "\u2312", + "profsurf;": "\u2313", + "prop;": "\u221d", + "propto;": "\u221d", + "prsim;": "\u227e", + "prurel;": "\u22b0", + "pscr;": "\U0001d4c5", + "psi;": "\u03c8", + "puncsp;": "\u2008", + "qfr;": "\U0001d52e", + "qint;": "\u2a0c", + "qopf;": "\U0001d562", + "qprime;": "\u2057", + "qscr;": "\U0001d4c6", + "quaternions;": "\u210d", + "quatint;": "\u2a16", + "quest;": "?", + "questeq;": "\u225f", + "quot": "\"", + "quot;": "\"", + "rAarr;": "\u21db", + "rArr;": "\u21d2", + "rAtail;": "\u291c", + "rBarr;": "\u290f", + "rHar;": "\u2964", + "race;": "\u223d\u0331", + "racute;": "\u0155", + "radic;": "\u221a", + "raemptyv;": "\u29b3", + "rang;": "\u27e9", + "rangd;": "\u2992", + "range;": "\u29a5", + "rangle;": "\u27e9", + "raquo": "\xbb", + "raquo;": "\xbb", + "rarr;": "\u2192", + "rarrap;": "\u2975", + "rarrb;": "\u21e5", + "rarrbfs;": "\u2920", + "rarrc;": "\u2933", + "rarrfs;": "\u291e", + "rarrhk;": "\u21aa", + "rarrlp;": "\u21ac", + "rarrpl;": "\u2945", + "rarrsim;": "\u2974", + "rarrtl;": "\u21a3", + "rarrw;": "\u219d", + "ratail;": "\u291a", + "ratio;": "\u2236", + "rationals;": "\u211a", + "rbarr;": "\u290d", + "rbbrk;": "\u2773", + "rbrace;": "}", + "rbrack;": "]", + "rbrke;": "\u298c", + "rbrksld;": "\u298e", + "rbrkslu;": "\u2990", + "rcaron;": "\u0159", + "rcedil;": "\u0157", + "rceil;": "\u2309", + "rcub;": "}", + "rcy;": "\u0440", + "rdca;": "\u2937", + "rdldhar;": "\u2969", + "rdquo;": "\u201d", + "rdquor;": "\u201d", + "rdsh;": "\u21b3", + "real;": "\u211c", + "realine;": "\u211b", + "realpart;": "\u211c", + "reals;": "\u211d", + "rect;": "\u25ad", + "reg": "\xae", + "reg;": "\xae", + "rfisht;": "\u297d", + "rfloor;": "\u230b", + "rfr;": "\U0001d52f", + "rhard;": "\u21c1", + "rharu;": "\u21c0", + "rharul;": "\u296c", + "rho;": "\u03c1", + "rhov;": "\u03f1", + "rightarrow;": "\u2192", + "rightarrowtail;": "\u21a3", + "rightharpoondown;": "\u21c1", + "rightharpoonup;": "\u21c0", + "rightleftarrows;": "\u21c4", + "rightleftharpoons;": "\u21cc", + "rightrightarrows;": "\u21c9", + "rightsquigarrow;": "\u219d", + "rightthreetimes;": "\u22cc", + "ring;": "\u02da", + "risingdotseq;": "\u2253", + "rlarr;": "\u21c4", + "rlhar;": "\u21cc", + "rlm;": "\u200f", + "rmoust;": "\u23b1", + "rmoustache;": "\u23b1", + "rnmid;": "\u2aee", + "roang;": "\u27ed", + "roarr;": "\u21fe", + "robrk;": "\u27e7", + "ropar;": "\u2986", + "ropf;": "\U0001d563", + "roplus;": "\u2a2e", + "rotimes;": "\u2a35", + "rpar;": ")", + "rpargt;": "\u2994", + "rppolint;": "\u2a12", + "rrarr;": "\u21c9", + "rsaquo;": "\u203a", + "rscr;": "\U0001d4c7", + "rsh;": "\u21b1", + "rsqb;": "]", + "rsquo;": "\u2019", + "rsquor;": "\u2019", + "rthree;": "\u22cc", + "rtimes;": "\u22ca", + "rtri;": "\u25b9", + "rtrie;": "\u22b5", + "rtrif;": "\u25b8", + "rtriltri;": "\u29ce", + "ruluhar;": "\u2968", + "rx;": "\u211e", + "sacute;": "\u015b", + "sbquo;": "\u201a", + "sc;": "\u227b", + "scE;": "\u2ab4", + "scap;": "\u2ab8", + "scaron;": "\u0161", + "sccue;": "\u227d", + "sce;": "\u2ab0", + "scedil;": "\u015f", + "scirc;": "\u015d", + "scnE;": "\u2ab6", + "scnap;": "\u2aba", + "scnsim;": "\u22e9", + "scpolint;": "\u2a13", + "scsim;": "\u227f", + "scy;": "\u0441", + "sdot;": "\u22c5", + "sdotb;": "\u22a1", + "sdote;": "\u2a66", + "seArr;": "\u21d8", + "searhk;": "\u2925", + "searr;": "\u2198", + "searrow;": "\u2198", + "sect": "\xa7", + "sect;": "\xa7", + "semi;": ";", + "seswar;": "\u2929", + "setminus;": "\u2216", + "setmn;": "\u2216", + "sext;": "\u2736", + "sfr;": "\U0001d530", + "sfrown;": "\u2322", + "sharp;": "\u266f", + "shchcy;": "\u0449", + "shcy;": "\u0448", + "shortmid;": "\u2223", + "shortparallel;": "\u2225", + "shy": "\xad", + "shy;": "\xad", + "sigma;": "\u03c3", + "sigmaf;": "\u03c2", + "sigmav;": "\u03c2", + "sim;": "\u223c", + "simdot;": "\u2a6a", + "sime;": "\u2243", + "simeq;": "\u2243", + "simg;": "\u2a9e", + "simgE;": "\u2aa0", + "siml;": "\u2a9d", + "simlE;": "\u2a9f", + "simne;": "\u2246", + "simplus;": "\u2a24", + "simrarr;": "\u2972", + "slarr;": "\u2190", + "smallsetminus;": "\u2216", + "smashp;": "\u2a33", + "smeparsl;": "\u29e4", + "smid;": "\u2223", + "smile;": "\u2323", + "smt;": "\u2aaa", + "smte;": "\u2aac", + "smtes;": "\u2aac\ufe00", + "softcy;": "\u044c", + "sol;": "/", + "solb;": "\u29c4", + "solbar;": "\u233f", + "sopf;": "\U0001d564", + "spades;": "\u2660", + "spadesuit;": "\u2660", + "spar;": "\u2225", + "sqcap;": "\u2293", + "sqcaps;": "\u2293\ufe00", + "sqcup;": "\u2294", + "sqcups;": "\u2294\ufe00", + "sqsub;": "\u228f", + "sqsube;": "\u2291", + "sqsubset;": "\u228f", + "sqsubseteq;": "\u2291", + "sqsup;": "\u2290", + "sqsupe;": "\u2292", + "sqsupset;": "\u2290", + "sqsupseteq;": "\u2292", + "squ;": "\u25a1", + "square;": "\u25a1", + "squarf;": "\u25aa", + "squf;": "\u25aa", + "srarr;": "\u2192", + "sscr;": "\U0001d4c8", + "ssetmn;": "\u2216", + "ssmile;": "\u2323", + "sstarf;": "\u22c6", + "star;": "\u2606", + "starf;": "\u2605", + "straightepsilon;": "\u03f5", + "straightphi;": "\u03d5", + "strns;": "\xaf", + "sub;": "\u2282", + "subE;": "\u2ac5", + "subdot;": "\u2abd", + "sube;": "\u2286", + "subedot;": "\u2ac3", + "submult;": "\u2ac1", + "subnE;": "\u2acb", + "subne;": "\u228a", + "subplus;": "\u2abf", + "subrarr;": "\u2979", + "subset;": "\u2282", + "subseteq;": "\u2286", + "subseteqq;": "\u2ac5", + "subsetneq;": "\u228a", + "subsetneqq;": "\u2acb", + "subsim;": "\u2ac7", + "subsub;": "\u2ad5", + "subsup;": "\u2ad3", + "succ;": "\u227b", + "succapprox;": "\u2ab8", + "succcurlyeq;": "\u227d", + "succeq;": "\u2ab0", + "succnapprox;": "\u2aba", + "succneqq;": "\u2ab6", + "succnsim;": "\u22e9", + "succsim;": "\u227f", + "sum;": "\u2211", + "sung;": "\u266a", + "sup1": "\xb9", + "sup1;": "\xb9", + "sup2": "\xb2", + "sup2;": "\xb2", + "sup3": "\xb3", + "sup3;": "\xb3", + "sup;": "\u2283", + "supE;": "\u2ac6", + "supdot;": "\u2abe", + "supdsub;": "\u2ad8", + "supe;": "\u2287", + "supedot;": "\u2ac4", + "suphsol;": "\u27c9", + "suphsub;": "\u2ad7", + "suplarr;": "\u297b", + "supmult;": "\u2ac2", + "supnE;": "\u2acc", + "supne;": "\u228b", + "supplus;": "\u2ac0", + "supset;": "\u2283", + "supseteq;": "\u2287", + "supseteqq;": "\u2ac6", + "supsetneq;": "\u228b", + "supsetneqq;": "\u2acc", + "supsim;": "\u2ac8", + "supsub;": "\u2ad4", + "supsup;": "\u2ad6", + "swArr;": "\u21d9", + "swarhk;": "\u2926", + "swarr;": "\u2199", + "swarrow;": "\u2199", + "swnwar;": "\u292a", + "szlig": "\xdf", + "szlig;": "\xdf", + "target;": "\u2316", + "tau;": "\u03c4", + "tbrk;": "\u23b4", + "tcaron;": "\u0165", + "tcedil;": "\u0163", + "tcy;": "\u0442", + "tdot;": "\u20db", + "telrec;": "\u2315", + "tfr;": "\U0001d531", + "there4;": "\u2234", + "therefore;": "\u2234", + "theta;": "\u03b8", + "thetasym;": "\u03d1", + "thetav;": "\u03d1", + "thickapprox;": "\u2248", + "thicksim;": "\u223c", + "thinsp;": "\u2009", + "thkap;": "\u2248", + "thksim;": "\u223c", + "thorn": "\xfe", + "thorn;": "\xfe", + "tilde;": "\u02dc", + "times": "\xd7", + "times;": "\xd7", + "timesb;": "\u22a0", + "timesbar;": "\u2a31", + "timesd;": "\u2a30", + "tint;": "\u222d", + "toea;": "\u2928", + "top;": "\u22a4", + "topbot;": "\u2336", + "topcir;": "\u2af1", + "topf;": "\U0001d565", + "topfork;": "\u2ada", + "tosa;": "\u2929", + "tprime;": "\u2034", + "trade;": "\u2122", + "triangle;": "\u25b5", + "triangledown;": "\u25bf", + "triangleleft;": "\u25c3", + "trianglelefteq;": "\u22b4", + "triangleq;": "\u225c", + "triangleright;": "\u25b9", + "trianglerighteq;": "\u22b5", + "tridot;": "\u25ec", + "trie;": "\u225c", + "triminus;": "\u2a3a", + "triplus;": "\u2a39", + "trisb;": "\u29cd", + "tritime;": "\u2a3b", + "trpezium;": "\u23e2", + "tscr;": "\U0001d4c9", + "tscy;": "\u0446", + "tshcy;": "\u045b", + "tstrok;": "\u0167", + "twixt;": "\u226c", + "twoheadleftarrow;": "\u219e", + "twoheadrightarrow;": "\u21a0", + "uArr;": "\u21d1", + "uHar;": "\u2963", + "uacute": "\xfa", + "uacute;": "\xfa", + "uarr;": "\u2191", + "ubrcy;": "\u045e", + "ubreve;": "\u016d", + "ucirc": "\xfb", + "ucirc;": "\xfb", + "ucy;": "\u0443", + "udarr;": "\u21c5", + "udblac;": "\u0171", + "udhar;": "\u296e", + "ufisht;": "\u297e", + "ufr;": "\U0001d532", + "ugrave": "\xf9", + "ugrave;": "\xf9", + "uharl;": "\u21bf", + "uharr;": "\u21be", + "uhblk;": "\u2580", + "ulcorn;": "\u231c", + "ulcorner;": "\u231c", + "ulcrop;": "\u230f", + "ultri;": "\u25f8", + "umacr;": "\u016b", + "uml": "\xa8", + "uml;": "\xa8", + "uogon;": "\u0173", + "uopf;": "\U0001d566", + "uparrow;": "\u2191", + "updownarrow;": "\u2195", + "upharpoonleft;": "\u21bf", + "upharpoonright;": "\u21be", + "uplus;": "\u228e", + "upsi;": "\u03c5", + "upsih;": "\u03d2", + "upsilon;": "\u03c5", + "upuparrows;": "\u21c8", + "urcorn;": "\u231d", + "urcorner;": "\u231d", + "urcrop;": "\u230e", + "uring;": "\u016f", + "urtri;": "\u25f9", + "uscr;": "\U0001d4ca", + "utdot;": "\u22f0", + "utilde;": "\u0169", + "utri;": "\u25b5", + "utrif;": "\u25b4", + "uuarr;": "\u21c8", + "uuml": "\xfc", + "uuml;": "\xfc", + "uwangle;": "\u29a7", + "vArr;": "\u21d5", + "vBar;": "\u2ae8", + "vBarv;": "\u2ae9", + "vDash;": "\u22a8", + "vangrt;": "\u299c", + "varepsilon;": "\u03f5", + "varkappa;": "\u03f0", + "varnothing;": "\u2205", + "varphi;": "\u03d5", + "varpi;": "\u03d6", + "varpropto;": "\u221d", + "varr;": "\u2195", + "varrho;": "\u03f1", + "varsigma;": "\u03c2", + "varsubsetneq;": "\u228a\ufe00", + "varsubsetneqq;": "\u2acb\ufe00", + "varsupsetneq;": "\u228b\ufe00", + "varsupsetneqq;": "\u2acc\ufe00", + "vartheta;": "\u03d1", + "vartriangleleft;": "\u22b2", + "vartriangleright;": "\u22b3", + "vcy;": "\u0432", + "vdash;": "\u22a2", + "vee;": "\u2228", + "veebar;": "\u22bb", + "veeeq;": "\u225a", + "vellip;": "\u22ee", + "verbar;": "|", + "vert;": "|", + "vfr;": "\U0001d533", + "vltri;": "\u22b2", + "vnsub;": "\u2282\u20d2", + "vnsup;": "\u2283\u20d2", + "vopf;": "\U0001d567", + "vprop;": "\u221d", + "vrtri;": "\u22b3", + "vscr;": "\U0001d4cb", + "vsubnE;": "\u2acb\ufe00", + "vsubne;": "\u228a\ufe00", + "vsupnE;": "\u2acc\ufe00", + "vsupne;": "\u228b\ufe00", + "vzigzag;": "\u299a", + "wcirc;": "\u0175", + "wedbar;": "\u2a5f", + "wedge;": "\u2227", + "wedgeq;": "\u2259", + "weierp;": "\u2118", + "wfr;": "\U0001d534", + "wopf;": "\U0001d568", + "wp;": "\u2118", + "wr;": "\u2240", + "wreath;": "\u2240", + "wscr;": "\U0001d4cc", + "xcap;": "\u22c2", + "xcirc;": "\u25ef", + "xcup;": "\u22c3", + "xdtri;": "\u25bd", + "xfr;": "\U0001d535", + "xhArr;": "\u27fa", + "xharr;": "\u27f7", + "xi;": "\u03be", + "xlArr;": "\u27f8", + "xlarr;": "\u27f5", + "xmap;": "\u27fc", + "xnis;": "\u22fb", + "xodot;": "\u2a00", + "xopf;": "\U0001d569", + "xoplus;": "\u2a01", + "xotime;": "\u2a02", + "xrArr;": "\u27f9", + "xrarr;": "\u27f6", + "xscr;": "\U0001d4cd", + "xsqcup;": "\u2a06", + "xuplus;": "\u2a04", + "xutri;": "\u25b3", + "xvee;": "\u22c1", + "xwedge;": "\u22c0", + "yacute": "\xfd", + "yacute;": "\xfd", + "yacy;": "\u044f", + "ycirc;": "\u0177", + "ycy;": "\u044b", + "yen": "\xa5", + "yen;": "\xa5", + "yfr;": "\U0001d536", + "yicy;": "\u0457", + "yopf;": "\U0001d56a", + "yscr;": "\U0001d4ce", + "yucy;": "\u044e", + "yuml": "\xff", + "yuml;": "\xff", + "zacute;": "\u017a", + "zcaron;": "\u017e", + "zcy;": "\u0437", + "zdot;": "\u017c", + "zeetrf;": "\u2128", + "zeta;": "\u03b6", + "zfr;": "\U0001d537", + "zhcy;": "\u0436", + "zigrarr;": "\u21dd", + "zopf;": "\U0001d56b", + "zscr;": "\U0001d4cf", + "zwj;": "\u200d", + "zwnj;": "\u200c", +} + +replacementCharacters = { + 0x0: "\uFFFD", + 0x0d: "\u000D", + 0x80: "\u20AC", + 0x81: "\u0081", + 0x82: "\u201A", + 0x83: "\u0192", + 0x84: "\u201E", + 0x85: "\u2026", + 0x86: "\u2020", + 0x87: "\u2021", + 0x88: "\u02C6", + 0x89: "\u2030", + 0x8A: "\u0160", + 0x8B: "\u2039", + 0x8C: "\u0152", + 0x8D: "\u008D", + 0x8E: "\u017D", + 0x8F: "\u008F", + 0x90: "\u0090", + 0x91: "\u2018", + 0x92: "\u2019", + 0x93: "\u201C", + 0x94: "\u201D", + 0x95: "\u2022", + 0x96: "\u2013", + 0x97: "\u2014", + 0x98: "\u02DC", + 0x99: "\u2122", + 0x9A: "\u0161", + 0x9B: "\u203A", + 0x9C: "\u0153", + 0x9D: "\u009D", + 0x9E: "\u017E", + 0x9F: "\u0178", +} + +tokenTypes = { + "Doctype": 0, + "Characters": 1, + "SpaceCharacters": 2, + "StartTag": 3, + "EndTag": 4, + "EmptyTag": 5, + "Comment": 6, + "ParseError": 7 +} + +tagTokenTypes = frozenset([tokenTypes["StartTag"], tokenTypes["EndTag"], + tokenTypes["EmptyTag"]]) + + +prefixes = {v: k for k, v in namespaces.items()} +prefixes["http://www.w3.org/1998/Math/MathML"] = "math" + + +class DataLossWarning(UserWarning): + """Raised when the current tree is unable to represent the input data""" + pass + + +class _ReparseException(Exception): + pass diff --git a/venv/Lib/site-packages/pip/_vendor/html5lib/filters/__init__.py b/venv/Lib/site-packages/pip/_vendor/html5lib/filters/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/venv/Lib/site-packages/pip/_vendor/html5lib/filters/__pycache__/__init__.cpython-39.pyc b/venv/Lib/site-packages/pip/_vendor/html5lib/filters/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d1d2e5bca76163065c4aaa3e81557586efcc16af GIT binary patch literal 193 zcmYe~<>g`kf?j#GBoO@=L?8o3AjbiSi&=m~3PUi1CZpdI zlbDy6SRCV6P~ehSk{IKYpPZNz6Ox)+5L1v@pj(<(keHmEnxb2tk(!#LYi5y^S)5#4 z1(J)2FH6l!$uEk@D9Oz+&B;uPNz2SB0ht&dpP83g5+AQuP0WQ!Jr8&H zthKB4DY@p%H97K^`pPLk0WMJ0wuzBwP1SVueh)kxZ zqnB|$5~Js2I(`RuWE%Usd}dqSJ6Wo_YmM`nP)lW1+xVTnQB^Bssg;w4Yx|Dk9qN-A zw-Vl4-y0!~6o;yE74F>(oI^I`DTw_9)CMBIAEdh@qH8O@Pv#NClC1yyQM%qVjKkA) zrtOU4PO>w(V)NF7W#^2VL6~8|LZGTS8IKu^gPSeO7JMlgXAQ5V?RX`bTX4rJfSpMu zm0L)|j*pMpMjjtC1ZEaso0C2EiwszB^Z{IG>y8_|4RX=K<%;(<*sBMyF4TMuc{h%^ zRVVEi%(m=8!nI~8jSE2kdT}j=FYC^&uAQ;DGS=-~1#gflPfQB0-vhTC(lH}2gZj%o z{i^uMN@EM&G~5;kU3bVGFTQIlu8S7{Ty(12?HkDVOp4u$g_L^t(U+&nR(6ehMY)uX zXic$jwSK78te7he1qDRiE%;121yJZV5N!9ll^>O8mr#HVBC!!Dl9>tU3a7UR?mYpq zAA^!4r-I~>pm~g)2_2Y-1Ztf6!8gI{`m=)@uWM=9d$*ymQp*~6wg2fRlmbigPUPo|pr-&}&%Vd*mqD{O{ z&L6=WPVJKo{h3g5J`n^XJ@N^bbsG8Xx#PyY;3q!&8ViWCL;(BH`!R4c9hw1zW41y0 ztSs>}DN8d%bAUZ6g->Czwt+ezA+b`=ed^jX+4vNbw?4sk_34u9UcN89*+S$GKz#&a z?|~w8hfe4KB>MYKG^QC{-@PJr@5c8L_<%qVu`K<#EbCVE8t0R;Jny-_-WisqXe)>n z9o%vn`Yw3JoN&|PA1I><4Ot#d$A~)b;d2F4gT*&7Dm-SeSpp?~t7^5Dm4p9?4TJ;+ a0>=Nj^V$AYq>u4?u!!?vG>Im0w)GFEH&%cE literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_vendor/html5lib/filters/__pycache__/base.cpython-39.pyc b/venv/Lib/site-packages/pip/_vendor/html5lib/filters/__pycache__/base.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..82d1ddb69f1f54c88d27fcdfa6a134387974ba5c GIT binary patch literal 863 zcmZuvO>fjN5VhlMHnd%}LY(1(5IJmbAcPPqDuN5@W#JMe<$*|i7`C$QW@aEjzql01@BMpqVyDc~PNC+S*gLTOEKi>oADptT5KSXo@v7@y z3onXyZ6!?cUe#UE>2BUPov1!3IsbC5l$k$$w$iS0mzXQ~g=%DLi*sL_Cq|dWGR)|T zQaE+oeH~KHb)!A!6Pz%NPA?BfCdaqA3Z7?c82>@ZlQmh<4P6kMKn|&(tbs~KZ3^E4 zpV6TR0ToI($K-!dL+&3T859R04bc t7QP__G+y?;x6s(4ycXG7tR9lKT&c>3(w&w8VU+X5IMYjfn;_>s_6za`y|(}W literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_vendor/html5lib/filters/__pycache__/inject_meta_charset.cpython-39.pyc b/venv/Lib/site-packages/pip/_vendor/html5lib/filters/__pycache__/inject_meta_charset.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d10671dc6a258a6d67bb6632dc3401fa6f585a73 GIT binary patch literal 1869 zcmZt{O>Y}TbY}L`j?Zt%{Pg6jcVP0il)4X0tPn*V!-6%(}!{ z9}vBQqMmz*Zy<5#iJ!m^;J8;#{R0)^0&jMm##9|^-oBal{pP)Ae|foyVEy#|hsQrG zA@r9zEG``mcVUZL04Sn3LNRu6Ok5Icu7(jMREzZ3a1D&^BdSy5DWV25hUSl&Yf|$O z>R2y97In08#XlBlluPD?ah7sf+B6)8B21IAohMzjJitNdLqM6PY>#=2Iu_J2VaQm?bjMz}n?fxXR8RY_SPIq9MK@1uF22 zU{nC+X%s{JWFq%C^Cc6G@6?Voo6dag`255XY0d+-gx@g7F*NEP+gg z$w|$Bc>)OsBDv!2c64rnU)%yv+MX9Cq4d1czLbC$(FKe8rCHnO4Pg8g@fLjk8SU-# zz7~v&o}VPX=zW%D`@Zyh57WSpdWS5|dRdrl=Sk)Vr;Kht888-Y-}+=2ia<;ht>=wd zLQ~!w$T<2q3XgmJ>JdaQtRBHr58%xo;AVElZLq7hP-#W>H9T3Vvvu>*_dpfJE=6c=a+WtyWYIYCoR;vu=v3N*v}=o~-(ZK@YKB{$I2C=9Bd68;d*`VDlU z&!A}G{5dtJ_#7t`=+-GY$NY;04jVZBrj4lycTJEoW@sNh{!>I%R~R9)Du5urLJhM6(%*4eGq5ztRk!W zx>xEH%C@xTb#^#u4y4Ss*(eXklU9%>5*mA3Y3`6Nu+B zj!n`A+$5VoGyk;#+5lTX)j?ttFcWZfXM&dcwnY{@yvjtkW2#Z5{DibLJugma9x1%# zd86Eq<`m2GU@CiFH8d)Z7ot!Dj8~zk(WhpFP(V3sFID5P+p(1LelByUE|07K6RsvY bSF@)?SC8~IwWYmVyLCrBaW$^iNlW_=d&=C_ literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_vendor/html5lib/filters/__pycache__/lint.cpython-39.pyc b/venv/Lib/site-packages/pip/_vendor/html5lib/filters/__pycache__/lint.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e5223ac123ef51b97446e3c129e195704f7fb0dc GIT binary patch literal 2611 zcmZuzOK%)S5bmDG?(ECnIF1vC0HX*<79~C)5k&?eB0E8eB46x8XtdFIJl(d(o|n6O zop`mr;D~TR@&&}vmJm`TegNWx@*6mfI7D#Dl_Lj4RnM-yKw9das;=&;uc~XSHfXi# z1jg5Izqj_$1R;MQGd?U}K7}baVPS;Pm?YGriQyTE>6sMwjMz$S&j#9LR$NJ{UKMDY zRbnTpd9|eO)iqxQzTq{1c8;37aZJ6&XN1*Q{V8E}UfpUPm|lxDmPx1i3apWiSxg3N zGK+hP`%#i-LKO~+b|V>OY0>VbQJ69A$C2V9h-HTsHN~GOU+v}m6-5QKu+{>}Um3_4 zMLi7?F7qJdvS{vR5xX7pgr^FxPU`)I%|HYp=#vEr5ySYvSm2QF!@`M28SxB8J(E?R zk#&mRKdpHddj6Dn_A_D;uL9mUMdeNugVO%S{RphNYLmMv+vce&mEb|*u4lsKLS#bL z>n@DD>u#jn^(bZ14br`#>>6xdiDOp;k>s%NuCCsak_!dlxQ(}0SLe$6E1{{8mJ8CO zDK7$}h@t~>U>q3(dQ2%97z5&)i~?4p|IGqGQXCAsCF)Wo!kQ1nhAXq42>HBrqNM-j z%YRM_zSD~Y_me<{n^C&qt6)RUyN@?H1VOmqcbX|s;0_PEqk}FUJXN;Tu?k!Ea)?q3 zJSZIBkJ3o_esS)#CLnh#$>a5+QeqTsxb++|#P`EEkka>`lfTv$=DQCdfU+B;X&}3| z@_aE+LHB+Z261wuca*Kge1iexDJDC_#WJY|{aZmJ~yFpk!` z>-wc-H-?v<%lE`2*qwqYb@n)I+Mg`LIydql#8e%P8W1+j5T;y&SKA=_RFN$TZ$*yj zA~`f4UE4PXkax3W-yE3C*d>Ql+<_evb}aZ>@U;gPBRwLQlsT}JbzsP)d*llWyY{vz zJ)}WmYssdT*jl275`$G{iL&9|m*qY2E$FGR>MYqd#E)>Zx=Y||GH2V6KjE3Q30!T& zm9+SEK(-uM=}~Q94eWKJ%s142R6iz*5F&|P{8KFkHw2$b3n;zoR z$bo-HOEq@jJ{U?X+OL<$?Yums>7Rh6zHJ;D0wedDIKkcin9aV{s$&I`uZCJjHow!- zkd=tik1_{ot;=9jv(O2&^u?I;#ZY>7Ch>nkhDU)Y{Fa|7v?C(5cg@4kB#Dp^MsCVYzOLY831!DckpYbKYmDV=VJ%V?^)n1zVC zaPr<-9EEpT;mAFycmfpQP?6g6CYQO0f;j4Pp?g68(t~t6%^s)2s*DOW2y|a|CPWoo zIjN!0m7s>!p{1r$1!>3yRv+*^3YEZOB=G-%uAW6D$aAQ6g$)fi0f+J|hnlQJl#2!& z>eR#;_;{@hPWi*Y$imj0PMk+I*nGqruoU)g5cfDIBoT3-#gn{$~P#0ls!<;tCQzQN@km*}`zm(#+I-Suw7wKEn1q!(t zbH*4i&^kOFy3(m)$HCmdX!(AUv0jXH)Ax6JK|GXHeV=8a@9V0sJt$hkh7J;lesjFS~u9BSDU4gEk%oe8wH-cvp3puWI=F#;R8z+U1_LjRc?_MbT!J<%_x yQ&+!nQ42Hurb>=IBtBGOZDmoaO^o5u$PiEAd|bNs2{tB)$fk`Zgt-l~ZvF!*U93a^ literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_vendor/html5lib/filters/__pycache__/optionaltags.cpython-39.pyc b/venv/Lib/site-packages/pip/_vendor/html5lib/filters/__pycache__/optionaltags.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3a22c068a0d1c2d77e7069b566121e4610c6b4d7 GIT binary patch literal 2756 zcmZ`*&x;&I6t1f7>FG>ne_L>U*zVz53p(3Fqco z49^#*&kXuq#(t%b*~i7lB{Y2jon(?HY|MLnEP7(>^c>ElkWS)`8@&c+Z!+o1#w{ir zQDe*d%;|a3TVvhk@6csk$1H>coh6eZ3gU5|slxa&-idXbrDk!G#=}fTK@t~{3KRW1 zCmn9wL8zl48JK+pJ}#l@=g~#1$0h3t$$JjDbBp!d(ve<6da{XcPx|r*-c8wpLr0Bw zEl#k`-m~vT<7_9=oh&clMwoPpa6@-SDjRo-&8Smk+fmxlg^I%QkUXj%iVHRJOuvOr z;&Y$xiz(Y;SJ+3LeP;@%CS0AFiYcEuBj*Fg*_05@KEE+v&0e8d$;w&D;2dAYu05Si z)G+G0#??_W>K(~dv=e6&{lbIcdDF1&-DT=19QbSN@@xI~b)X+& z_v`Rbbk60w@GpsFq-a>10mwR~c&6NQ@SK|H?x(47Lnhjl!!IXW=Zd1?( zeS~ITAapp(6}InAT`9JOLXf1h!t_NTImYe^0y%YVJ9=v>D6BVpAR9nRAVh_5Zi|`u z3TH#?ts1x3%_HNl6`?BD!wus~gvz*SIF5{WHI1AfEied(=RvTHFMR?Xnj{Sq35W%|N@?TA zsZjUJQ?{$qm{wneSNH8&r8i5p1)I0at2UU%C4Sx&rg=FVkE0alu?9{@mp4Nd4iQ!j zL=?)qLM+&CB^ z&j<`YJVBZb6oydZHOjKWh(g(Ottrq%iV%y`BeWEq?86A4j$z_7nysshFLK|(nY%vn z$LI6h_w2}R3uIHnuiwrhZ-E^yZ=>y{Ub50 zN38Av<`F@x_+`B!*-l5WaKa+)A6mFqS%Bt@r$5ws>3QfpYFGXHQ0I?I2l5%6ziJ(u zMkmWO0-sNU8|oBw#6`7&4%f6uV&kLY*$hxm(G2C0%^RCRNEjhOeJRy*n7C$mt{x-Z zQ>Gb07-@}xD&iq>sS#>i6{a;vvf=iPNmd}esMv0(SQ<~pVUleaN5+b}9T-iFKZ>J7 z>ZmXtdVw^ODsVq@v;g)ewmQ53X zBj}Dt;)VnGB_@gS%DUba>TTNKGqeZn4HaIfTs@A@b<90UbCmiR(@UMH1$IOlg+$vd z3xR9z0`)Y3{x|=RWA;Nd-A8wr|1I30;<(NJHr)ht4>TcbRx-@Bnk|cIxh>R+mO~Yy zbrdq(zsofCs(FiB=6fd|QYCO@t#*Cm2LY9;ATX^U7-w>l(6}80Hzr|H%`}5RX2T$` zccFR|&f40gXah618vO%NbhW7_I=bF9U4gcWwfs5%RV!cZHfgERq?jlyrKm0`DprcB blwpb#E%ITejeoIp@^$(rrb*?vXgmJ`m+_c8 literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_vendor/html5lib/filters/__pycache__/sanitizer.cpython-39.pyc b/venv/Lib/site-packages/pip/_vendor/html5lib/filters/__pycache__/sanitizer.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6605f18c49d847134f7db064320ebb0c5177f718 GIT binary patch literal 16879 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 mc0RP{OG~} literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_vendor/html5lib/filters/__pycache__/whitespace.cpython-39.pyc b/venv/Lib/site-packages/pip/_vendor/html5lib/filters/__pycache__/whitespace.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..853cc3809e8d34806384ff2369d906c3dd78c905 GIT binary patch literal 1361 zcmZ8h%WfMt6eT$i&B(GP6mC)jDXK+NK!}}P(;x_n7>b%rVHi~!6jKEQYDh;Ta~>fn zClTb8gYF9C1G;dR{fT}Ew_W)cvPth9#kCs_$Qhn3U z+PX;OC%MV1()AW)o>fAoDz{Q|WezSVDpBW8xsewPH_UD6OmNFbN*1!T#&u22GdY}b z%`?z5jx2*;Z=2_LGBkO8{Fi`TKqX12APEyR@uV-9@Ln(($ncEbBxf{f310-@ek4M0 zzvaRoas{U^_lK2Iyf)JGU(LYJ#&}=8&SY)-dD*YE-0fTW+Hx)VZl9N;Z!(<&DK8!N zK*mLvG8x8rInYC#=(_m>7C}#`C3AYtR*>e$Y{dlIA*bHT6W%e?k5<&&1I*tc zD>C;^2qGf*j-1l+5M)A-dA6cBMQ|U{2cThrX#rzFGuk2AiWt8hlJXX??|^Ls`_B4n z{*12K6?;Y~dD#;Lva)fY(Rt_FH#I~whM4VB{=)esFQg8T3P+_ts5}0oNIur^J?*>p zRpkbO4naw8pk|b&*am6pK5ue-sHKtmL|)ZB`&fyz;myEzzLDz4MUdY{)CIOWmZjc; z^Zp|G7QEiih7Tq`18XL{EV-HN*Y#uYWb$K`aW#1=i+WP$_1>Zce~+cudo`0%?cKXS z&rN2Q$W77{S&B+eX0}k@s(d;*YFfigt{UQQ{YKvab3K@*4-26_?a>Gx_JPsP2gcg0 zL)&b-dH2||yY8>Mmr)-KVoU*M5>n7k)1nd!h2NbteYxQ3BhyM#QDp$fN4i?d(n#xk zl^d%gu&Qt3f}S+dUt7LJ3=`dfX)x^(xVX(4?0-FpCB~i{q996Ja!v(>e#DE-4)iu) za4$RK!~NlCoc=U=GWx}NW--N^i*5d?*)KrhHlBtznoy1VK^KEOTG)k#AT=`D!v#${ zrlrQ8Thkvd&Z^Q_4wru&WQ-#Iyvj@0%BrHymDFFOG{)DQe$4~y0*%qT=;1o2-(!RZ Rn`E0sP?a9kWy||)=U+xKTEqYV literal 0 HcmV?d00001 diff --git a/venv/Lib/site-packages/pip/_vendor/html5lib/filters/alphabeticalattributes.py b/venv/Lib/site-packages/pip/_vendor/html5lib/filters/alphabeticalattributes.py new file mode 100644 index 0000000..5ba926e --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/html5lib/filters/alphabeticalattributes.py @@ -0,0 +1,29 @@ +from __future__ import absolute_import, division, unicode_literals + +from . import base + +from collections import OrderedDict + + +def _attr_key(attr): + """Return an appropriate key for an attribute for sorting + + Attributes have a namespace that can be either ``None`` or a string. We + can't compare the two because they're different types, so we convert + ``None`` to an empty string first. + + """ + return (attr[0][0] or ''), attr[0][1] + + +class Filter(base.Filter): + """Alphabetizes attributes for elements""" + def __iter__(self): + for token in base.Filter.__iter__(self): + if token["type"] in ("StartTag", "EmptyTag"): + attrs = OrderedDict() + for name, value in sorted(token["data"].items(), + key=_attr_key): + attrs[name] = value + token["data"] = attrs + yield token diff --git a/venv/Lib/site-packages/pip/_vendor/html5lib/filters/base.py b/venv/Lib/site-packages/pip/_vendor/html5lib/filters/base.py new file mode 100644 index 0000000..c7dbaed --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/html5lib/filters/base.py @@ -0,0 +1,12 @@ +from __future__ import absolute_import, division, unicode_literals + + +class Filter(object): + def __init__(self, source): + self.source = source + + def __iter__(self): + return iter(self.source) + + def __getattr__(self, name): + return getattr(self.source, name) diff --git a/venv/Lib/site-packages/pip/_vendor/html5lib/filters/inject_meta_charset.py b/venv/Lib/site-packages/pip/_vendor/html5lib/filters/inject_meta_charset.py new file mode 100644 index 0000000..aefb5c8 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/html5lib/filters/inject_meta_charset.py @@ -0,0 +1,73 @@ +from __future__ import absolute_import, division, unicode_literals + +from . import base + + +class Filter(base.Filter): + """Injects ```` tag into head of document""" + def __init__(self, source, encoding): + """Creates a Filter + + :arg source: the source token stream + + :arg encoding: the encoding to set + + """ + base.Filter.__init__(self, source) + self.encoding = encoding + + def __iter__(self): + state = "pre_head" + meta_found = (self.encoding is None) + pending = [] + + for token in base.Filter.__iter__(self): + type = token["type"] + if type == "StartTag": + if token["name"].lower() == "head": + state = "in_head" + + elif type == "EmptyTag": + if token["name"].lower() == "meta": + # replace charset with actual encoding + has_http_equiv_content_type = False + for (namespace, name), value in token["data"].items(): + if namespace is not None: + continue + elif name.lower() == 'charset': + token["data"][(namespace, name)] = self.encoding + meta_found = True + break + elif name == 'http-equiv' and value.lower() == 'content-type': + has_http_equiv_content_type = True + else: + if has_http_equiv_content_type and (None, "content") in token["data"]: + token["data"][(None, "content")] = 'text/html; charset=%s' % self.encoding + meta_found = True + + elif token["name"].lower() == "head" and not meta_found: + # insert meta into empty head + yield {"type": "StartTag", "name": "head", + "data": token["data"]} + yield {"type": "EmptyTag", "name": "meta", + "data": {(None, "charset"): self.encoding}} + yield {"type": "EndTag", "name": "head"} + meta_found = True + continue + + elif type == "EndTag": + if token["name"].lower() == "head" and pending: + # insert meta into head (if necessary) and flush pending queue + yield pending.pop(0) + if not meta_found: + yield {"type": "EmptyTag", "name": "meta", + "data": {(None, "charset"): self.encoding}} + while pending: + yield pending.pop(0) + meta_found = True + state = "post_head" + + if state == "in_head": + pending.append(token) + else: + yield token diff --git a/venv/Lib/site-packages/pip/_vendor/html5lib/filters/lint.py b/venv/Lib/site-packages/pip/_vendor/html5lib/filters/lint.py new file mode 100644 index 0000000..fcc07ee --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/html5lib/filters/lint.py @@ -0,0 +1,93 @@ +from __future__ import absolute_import, division, unicode_literals + +from pip._vendor.six import text_type + +from . import base +from ..constants import namespaces, voidElements + +from ..constants import spaceCharacters +spaceCharacters = "".join(spaceCharacters) + + +class Filter(base.Filter): + """Lints the token stream for errors + + If it finds any errors, it'll raise an ``AssertionError``. + + """ + def __init__(self, source, require_matching_tags=True): + """Creates a Filter + + :arg source: the source token stream + + :arg require_matching_tags: whether or not to require matching tags + + """ + super(Filter, self).__init__(source) + self.require_matching_tags = require_matching_tags + + def __iter__(self): + open_elements = [] + for token in base.Filter.__iter__(self): + type = token["type"] + if type in ("StartTag", "EmptyTag"): + namespace = token["namespace"] + name = token["name"] + assert namespace is None or isinstance(namespace, text_type) + assert namespace != "" + assert isinstance(name, text_type) + assert name != "" + assert isinstance(token["data"], dict) + if (not namespace or namespace == namespaces["html"]) and name in voidElements: + assert type == "EmptyTag" + else: + assert type == "StartTag" + if type == "StartTag" and self.require_matching_tags: + open_elements.append((namespace, name)) + for (namespace, name), value in token["data"].items(): + assert namespace is None or isinstance(namespace, text_type) + assert namespace != "" + assert isinstance(name, text_type) + assert name != "" + assert isinstance(value, text_type) + + elif type == "EndTag": + namespace = token["namespace"] + name = token["name"] + assert namespace is None or isinstance(namespace, text_type) + assert namespace != "" + assert isinstance(name, text_type) + assert name != "" + if (not namespace or namespace == namespaces["html"]) and name in voidElements: + assert False, "Void element reported as EndTag token: %(tag)s" % {"tag": name} + elif self.require_matching_tags: + start = open_elements.pop() + assert start == (namespace, name) + + elif type == "Comment": + data = token["data"] + assert isinstance(data, text_type) + + elif type in ("Characters", "SpaceCharacters"): + data = token["data"] + assert isinstance(data, text_type) + assert data != "" + if type == "SpaceCharacters": + assert data.strip(spaceCharacters) == "" + + elif type == "Doctype": + name = token["name"] + assert name is None or isinstance(name, text_type) + assert token["publicId"] is None or isinstance(name, text_type) + assert token["systemId"] is None or isinstance(name, text_type) + + elif type == "Entity": + assert isinstance(token["name"], text_type) + + elif type == "SerializerError": + assert isinstance(token["data"], text_type) + + else: + assert False, "Unknown token type: %(type)s" % {"type": type} + + yield token diff --git a/venv/Lib/site-packages/pip/_vendor/html5lib/filters/optionaltags.py b/venv/Lib/site-packages/pip/_vendor/html5lib/filters/optionaltags.py new file mode 100644 index 0000000..4a86501 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/html5lib/filters/optionaltags.py @@ -0,0 +1,207 @@ +from __future__ import absolute_import, division, unicode_literals + +from . import base + + +class Filter(base.Filter): + """Removes optional tags from the token stream""" + def slider(self): + previous1 = previous2 = None + for token in self.source: + if previous1 is not None: + yield previous2, previous1, token + previous2 = previous1 + previous1 = token + if previous1 is not None: + yield previous2, previous1, None + + def __iter__(self): + for previous, token, next in self.slider(): + type = token["type"] + if type == "StartTag": + if (token["data"] or + not self.is_optional_start(token["name"], previous, next)): + yield token + elif type == "EndTag": + if not self.is_optional_end(token["name"], next): + yield token + else: + yield token + + def is_optional_start(self, tagname, previous, next): + type = next and next["type"] or None + if tagname in 'html': + # An html element's start tag may be omitted if the first thing + # inside the html element is not a space character or a comment. + return type not in ("Comment", "SpaceCharacters") + elif tagname == 'head': + # A head element's start tag may be omitted if the first thing + # inside the head element is an element. + # XXX: we also omit the start tag if the head element is empty + if type in ("StartTag", "EmptyTag"): + return True + elif type == "EndTag": + return next["name"] == "head" + elif tagname == 'body': + # A body element's start tag may be omitted if the first thing + # inside the body element is not a space character or a comment, + # except if the first thing inside the body element is a script + # or style element and the node immediately preceding the body + # element is a head element whose end tag has been omitted. + if type in ("Comment", "SpaceCharacters"): + return False + elif type == "StartTag": + # XXX: we do not look at the preceding event, so we never omit + # the body element's start tag if it's followed by a script or + # a style element. + return next["name"] not in ('script', 'style') + else: + return True + elif tagname == 'colgroup': + # A colgroup element's start tag may be omitted if the first thing + # inside the colgroup element is a col element, and if the element + # is not immediately preceded by another colgroup element whose + # end tag has been omitted. + if type in ("StartTag", "EmptyTag"): + # XXX: we do not look at the preceding event, so instead we never + # omit the colgroup element's end tag when it is immediately + # followed by another colgroup element. See is_optional_end. + return next["name"] == "col" + else: + return False + elif tagname == 'tbody': + # A tbody element's start tag may be omitted if the first thing + # inside the tbody element is a tr element, and if the element is + # not immediately preceded by a tbody, thead, or tfoot element + # whose end tag has been omitted. + if type == "StartTag": + # omit the thead and tfoot elements' end tag when they are + # immediately followed by a tbody element. See is_optional_end. + if previous and previous['type'] == 'EndTag' and \ + previous['name'] in ('tbody', 'thead', 'tfoot'): + return False + return next["name"] == 'tr' + else: + return False + return False + + def is_optional_end(self, tagname, next): + type = next and next["type"] or None + if tagname in ('html', 'head', 'body'): + # An html element's end tag may be omitted if the html element + # is not immediately followed by a space character or a comment. + return type not in ("Comment", "SpaceCharacters") + elif tagname in ('li', 'optgroup', 'tr'): + # A li element's end tag may be omitted if the li element is + # immediately followed by another li element or if there is + # no more content in the parent element. + # An optgroup element's end tag may be omitted if the optgroup + # element is immediately followed by another optgroup element, + # or if there is no more content in the parent element. + # A tr element's end tag may be omitted if the tr element is + # immediately followed by another tr element, or if there is + # no more content in the parent element. + if type == "StartTag": + return next["name"] == tagname + else: + return type == "EndTag" or type is None + elif tagname in ('dt', 'dd'): + # A dt element's end tag may be omitted if the dt element is + # immediately followed by another dt element or a dd element. + # A dd element's end tag may be omitted if the dd element is + # immediately followed by another dd element or a dt element, + # or if there is no more content in the parent element. + if type == "StartTag": + return next["name"] in ('dt', 'dd') + elif tagname == 'dd': + return type == "EndTag" or type is None + else: + return False + elif tagname == 'p': + # A p element's end tag may be omitted if the p element is + # immediately followed by an address, article, aside, + # blockquote, datagrid, dialog, dir, div, dl, fieldset, + # footer, form, h1, h2, h3, h4, h5, h6, header, hr, menu, + # nav, ol, p, pre, section, table, or ul, element, or if + # there is no more content in the parent element. + if type in ("StartTag", "EmptyTag"): + return next["name"] in ('address', 'article', 'aside', + 'blockquote', 'datagrid', 'dialog', + 'dir', 'div', 'dl', 'fieldset', 'footer', + 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', + 'header', 'hr', 'menu', 'nav', 'ol', + 'p', 'pre', 'section', 'table', 'ul') + else: + return type == "EndTag" or type is None + elif tagname == 'option': + # An option element's end tag may be omitted if the option + # element is immediately followed by another option element, + # or if it is immediately followed by an optgroup + # element, or if there is no more content in the parent + # element. + if type == "StartTag": + return next["name"] in ('option', 'optgroup') + else: + return type == "EndTag" or type is None + elif tagname in ('rt', 'rp'): + # An rt element's end tag may be omitted if the rt element is + # immediately followed by an rt or rp element, or if there is + # no more content in the parent element. + # An rp element's end tag may be omitted if the rp element is + # immediately followed by an rt or rp element, or if there is + # no more content in the parent element. + if type == "StartTag": + return next["name"] in ('rt', 'rp') + else: + return type == "EndTag" or type is None + elif tagname == 'colgroup': + # A colgroup element's end tag may be omitted if the colgroup + # element is not immediately followed by a space character or + # a comment. + if type in ("Comment", "SpaceCharacters"): + return False + elif type == "StartTag": + # XXX: we also look for an immediately following colgroup + # element. See is_optional_start. + return next["name"] != 'colgroup' + else: + return True + elif tagname in ('thead', 'tbody'): + # A thead element's end tag may be omitted if the thead element + # is immediately followed by a tbody or tfoot element. + # A tbody element's end tag may be omitted if the tbody element + # is immediately followed by a tbody or tfoot element, or if + # there is no more content in the parent element. + # A tfoot element's end tag may be omitted if the tfoot element + # is immediately followed by a tbody element, or if there is no + # more content in the parent element. + # XXX: we never omit the end tag when the following element is + # a tbody. See is_optional_start. + if type == "StartTag": + return next["name"] in ['tbody', 'tfoot'] + elif tagname == 'tbody': + return type == "EndTag" or type is None + else: + return False + elif tagname == 'tfoot': + # A tfoot element's end tag may be omitted if the tfoot element + # is immediately followed by a tbody element, or if there is no + # more content in the parent element. + # XXX: we never omit the end tag when the following element is + # a tbody. See is_optional_start. + if type == "StartTag": + return next["name"] == 'tbody' + else: + return type == "EndTag" or type is None + elif tagname in ('td', 'th'): + # A td element's end tag may be omitted if the td element is + # immediately followed by a td or th element, or if there is + # no more content in the parent element. + # A th element's end tag may be omitted if the th element is + # immediately followed by a td or th element, or if there is + # no more content in the parent element. + if type == "StartTag": + return next["name"] in ('td', 'th') + else: + return type == "EndTag" or type is None + return False diff --git a/venv/Lib/site-packages/pip/_vendor/html5lib/filters/sanitizer.py b/venv/Lib/site-packages/pip/_vendor/html5lib/filters/sanitizer.py new file mode 100644 index 0000000..aa7431d --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/html5lib/filters/sanitizer.py @@ -0,0 +1,916 @@ +"""Deprecated from html5lib 1.1. + +See `here `_ for +information about its deprecation; `Bleach `_ +is recommended as a replacement. Please let us know in the aforementioned issue +if Bleach is unsuitable for your needs. + +""" +from __future__ import absolute_import, division, unicode_literals + +import re +import warnings +from xml.sax.saxutils import escape, unescape + +from pip._vendor.six.moves import urllib_parse as urlparse + +from . import base +from ..constants import namespaces, prefixes + +__all__ = ["Filter"] + + +_deprecation_msg = ( + "html5lib's sanitizer is deprecated; see " + + "https://github.com/html5lib/html5lib-python/issues/443 and please let " + + "us know if Bleach is unsuitable for your needs" +) + +warnings.warn(_deprecation_msg, DeprecationWarning) + +allowed_elements = frozenset(( + (namespaces['html'], 'a'), + (namespaces['html'], 'abbr'), + (namespaces['html'], 'acronym'), + (namespaces['html'], 'address'), + (namespaces['html'], 'area'), + (namespaces['html'], 'article'), + (namespaces['html'], 'aside'), + (namespaces['html'], 'audio'), + (namespaces['html'], 'b'), + (namespaces['html'], 'big'), + (namespaces['html'], 'blockquote'), + (namespaces['html'], 'br'), + (namespaces['html'], 'button'), + (namespaces['html'], 'canvas'), + (namespaces['html'], 'caption'), + (namespaces['html'], 'center'), + (namespaces['html'], 'cite'), + (namespaces['html'], 'code'), + (namespaces['html'], 'col'), + (namespaces['html'], 'colgroup'), + (namespaces['html'], 'command'), + (namespaces['html'], 'datagrid'), + (namespaces['html'], 'datalist'), + (namespaces['html'], 'dd'), + (namespaces['html'], 'del'), + (namespaces['html'], 'details'), + (namespaces['html'], 'dfn'), + (namespaces['html'], 'dialog'), + (namespaces['html'], 'dir'), + (namespaces['html'], 'div'), + (namespaces['html'], 'dl'), + (namespaces['html'], 'dt'), + (namespaces['html'], 'em'), + (namespaces['html'], 'event-source'), + (namespaces['html'], 'fieldset'), + (namespaces['html'], 'figcaption'), + (namespaces['html'], 'figure'), + (namespaces['html'], 'footer'), + (namespaces['html'], 'font'), + (namespaces['html'], 'form'), + (namespaces['html'], 'header'), + (namespaces['html'], 'h1'), + (namespaces['html'], 'h2'), + (namespaces['html'], 'h3'), + (namespaces['html'], 'h4'), + (namespaces['html'], 'h5'), + (namespaces['html'], 'h6'), + (namespaces['html'], 'hr'), + (namespaces['html'], 'i'), + (namespaces['html'], 'img'), + (namespaces['html'], 'input'), + (namespaces['html'], 'ins'), + (namespaces['html'], 'keygen'), + (namespaces['html'], 'kbd'), + (namespaces['html'], 'label'), + (namespaces['html'], 'legend'), + (namespaces['html'], 'li'), + (namespaces['html'], 'm'), + (namespaces['html'], 'map'), + (namespaces['html'], 'menu'), + (namespaces['html'], 'meter'), + (namespaces['html'], 'multicol'), + (namespaces['html'], 'nav'), + (namespaces['html'], 'nextid'), + (namespaces['html'], 'ol'), + (namespaces['html'], 'output'), + (namespaces['html'], 'optgroup'), + (namespaces['html'], 'option'), + (namespaces['html'], 'p'), + (namespaces['html'], 'pre'), + (namespaces['html'], 'progress'), + (namespaces['html'], 'q'), + (namespaces['html'], 's'), + (namespaces['html'], 'samp'), + (namespaces['html'], 'section'), + (namespaces['html'], 'select'), + (namespaces['html'], 'small'), + (namespaces['html'], 'sound'), + (namespaces['html'], 'source'), + (namespaces['html'], 'spacer'), + (namespaces['html'], 'span'), + (namespaces['html'], 'strike'), + (namespaces['html'], 'strong'), + (namespaces['html'], 'sub'), + (namespaces['html'], 'sup'), + (namespaces['html'], 'table'), + (namespaces['html'], 'tbody'), + (namespaces['html'], 'td'), + (namespaces['html'], 'textarea'), + (namespaces['html'], 'time'), + (namespaces['html'], 'tfoot'), + (namespaces['html'], 'th'), + (namespaces['html'], 'thead'), + (namespaces['html'], 'tr'), + (namespaces['html'], 'tt'), + (namespaces['html'], 'u'), + (namespaces['html'], 'ul'), + (namespaces['html'], 'var'), + (namespaces['html'], 'video'), + (namespaces['mathml'], 'maction'), + (namespaces['mathml'], 'math'), + (namespaces['mathml'], 'merror'), + (namespaces['mathml'], 'mfrac'), + (namespaces['mathml'], 'mi'), + (namespaces['mathml'], 'mmultiscripts'), + (namespaces['mathml'], 'mn'), + (namespaces['mathml'], 'mo'), + (namespaces['mathml'], 'mover'), + (namespaces['mathml'], 'mpadded'), + (namespaces['mathml'], 'mphantom'), + (namespaces['mathml'], 'mprescripts'), + (namespaces['mathml'], 'mroot'), + (namespaces['mathml'], 'mrow'), + (namespaces['mathml'], 'mspace'), + (namespaces['mathml'], 'msqrt'), + (namespaces['mathml'], 'mstyle'), + (namespaces['mathml'], 'msub'), + (namespaces['mathml'], 'msubsup'), + (namespaces['mathml'], 'msup'), + (namespaces['mathml'], 'mtable'), + (namespaces['mathml'], 'mtd'), + (namespaces['mathml'], 'mtext'), + (namespaces['mathml'], 'mtr'), + (namespaces['mathml'], 'munder'), + (namespaces['mathml'], 'munderover'), + (namespaces['mathml'], 'none'), + (namespaces['svg'], 'a'), + (namespaces['svg'], 'animate'), + (namespaces['svg'], 'animateColor'), + (namespaces['svg'], 'animateMotion'), + (namespaces['svg'], 'animateTransform'), + (namespaces['svg'], 'clipPath'), + (namespaces['svg'], 'circle'), + (namespaces['svg'], 'defs'), + (namespaces['svg'], 'desc'), + (namespaces['svg'], 'ellipse'), + (namespaces['svg'], 'font-face'), + (namespaces['svg'], 'font-face-name'), + (namespaces['svg'], 'font-face-src'), + (namespaces['svg'], 'g'), + (namespaces['svg'], 'glyph'), + (namespaces['svg'], 'hkern'), + (namespaces['svg'], 'linearGradient'), + (namespaces['svg'], 'line'), + (namespaces['svg'], 'marker'), + (namespaces['svg'], 'metadata'), + (namespaces['svg'], 'missing-glyph'), + (namespaces['svg'], 'mpath'), + (namespaces['svg'], 'path'), + (namespaces['svg'], 'polygon'), + (namespaces['svg'], 'polyline'), + (namespaces['svg'], 'radialGradient'), + (namespaces['svg'], 'rect'), + (namespaces['svg'], 'set'), + (namespaces['svg'], 'stop'), + (namespaces['svg'], 'svg'), + (namespaces['svg'], 'switch'), + (namespaces['svg'], 'text'), + (namespaces['svg'], 'title'), + (namespaces['svg'], 'tspan'), + (namespaces['svg'], 'use'), +)) + +allowed_attributes = frozenset(( + # HTML attributes + (None, 'abbr'), + (None, 'accept'), + (None, 'accept-charset'), + (None, 'accesskey'), + (None, 'action'), + (None, 'align'), + (None, 'alt'), + (None, 'autocomplete'), + (None, 'autofocus'), + (None, 'axis'), + (None, 'background'), + (None, 'balance'), + (None, 'bgcolor'), + (None, 'bgproperties'), + (None, 'border'), + (None, 'bordercolor'), + (None, 'bordercolordark'), + (None, 'bordercolorlight'), + (None, 'bottompadding'), + (None, 'cellpadding'), + (None, 'cellspacing'), + (None, 'ch'), + (None, 'challenge'), + (None, 'char'), + (None, 'charoff'), + (None, 'choff'), + (None, 'charset'), + (None, 'checked'), + (None, 'cite'), + (None, 'class'), + (None, 'clear'), + (None, 'color'), + (None, 'cols'), + (None, 'colspan'), + (None, 'compact'), + (None, 'contenteditable'), + (None, 'controls'), + (None, 'coords'), + (None, 'data'), + (None, 'datafld'), + (None, 'datapagesize'), + (None, 'datasrc'), + (None, 'datetime'), + (None, 'default'), + (None, 'delay'), + (None, 'dir'), + (None, 'disabled'), + (None, 'draggable'), + (None, 'dynsrc'), + (None, 'enctype'), + (None, 'end'), + (None, 'face'), + (None, 'for'), + (None, 'form'), + (None, 'frame'), + (None, 'galleryimg'), + (None, 'gutter'), + (None, 'headers'), + (None, 'height'), + (None, 'hidefocus'), + (None, 'hidden'), + (None, 'high'), + (None, 'href'), + (None, 'hreflang'), + (None, 'hspace'), + (None, 'icon'), + (None, 'id'), + (None, 'inputmode'), + (None, 'ismap'), + (None, 'keytype'), + (None, 'label'), + (None, 'leftspacing'), + (None, 'lang'), + (None, 'list'), + (None, 'longdesc'), + (None, 'loop'), + (None, 'loopcount'), + (None, 'loopend'), + (None, 'loopstart'), + (None, 'low'), + (None, 'lowsrc'), + (None, 'max'), + (None, 'maxlength'), + (None, 'media'), + (None, 'method'), + (None, 'min'), + (None, 'multiple'), + (None, 'name'), + (None, 'nohref'), + (None, 'noshade'), + (None, 'nowrap'), + (None, 'open'), + (None, 'optimum'), + (None, 'pattern'), + (None, 'ping'), + (None, 'point-size'), + (None, 'poster'), + (None, 'pqg'), + (None, 'preload'), + (None, 'prompt'), + (None, 'radiogroup'), + (None, 'readonly'), + (None, 'rel'), + (None, 'repeat-max'), + (None, 'repeat-min'), + (None, 'replace'), + (None, 'required'), + (None, 'rev'), + (None, 'rightspacing'), + (None, 'rows'), + (None, 'rowspan'), + (None, 'rules'), + (None, 'scope'), + (None, 'selected'), + (None, 'shape'), + (None, 'size'), + (None, 'span'), + (None, 'src'), + (None, 'start'), + (None, 'step'), + (None, 'style'), + (None, 'summary'), + (None, 'suppress'), + (None, 'tabindex'), + (None, 'target'), + (None, 'template'), + (None, 'title'), + (None, 'toppadding'), + (None, 'type'), + (None, 'unselectable'), + (None, 'usemap'), + (None, 'urn'), + (None, 'valign'), + (None, 'value'), + (None, 'variable'), + (None, 'volume'), + (None, 'vspace'), + (None, 'vrml'), + (None, 'width'), + (None, 'wrap'), + (namespaces['xml'], 'lang'), + # MathML attributes + (None, 'actiontype'), + (None, 'align'), + (None, 'columnalign'), + (None, 'columnalign'), + (None, 'columnalign'), + (None, 'columnlines'), + (None, 'columnspacing'), + (None, 'columnspan'), + (None, 'depth'), + (None, 'display'), + (None, 'displaystyle'), + (None, 'equalcolumns'), + (None, 'equalrows'), + (None, 'fence'), + (None, 'fontstyle'), + (None, 'fontweight'), + (None, 'frame'), + (None, 'height'), + (None, 'linethickness'), + (None, 'lspace'), + (None, 'mathbackground'), + (None, 'mathcolor'), + (None, 'mathvariant'), + (None, 'mathvariant'), + (None, 'maxsize'), + (None, 'minsize'), + (None, 'other'), + (None, 'rowalign'), + (None, 'rowalign'), + (None, 'rowalign'), + (None, 'rowlines'), + (None, 'rowspacing'), + (None, 'rowspan'), + (None, 'rspace'), + (None, 'scriptlevel'), + (None, 'selection'), + (None, 'separator'), + (None, 'stretchy'), + (None, 'width'), + (None, 'width'), + (namespaces['xlink'], 'href'), + (namespaces['xlink'], 'show'), + (namespaces['xlink'], 'type'), + # SVG attributes + (None, 'accent-height'), + (None, 'accumulate'), + (None, 'additive'), + (None, 'alphabetic'), + (None, 'arabic-form'), + (None, 'ascent'), + (None, 'attributeName'), + (None, 'attributeType'), + (None, 'baseProfile'), + (None, 'bbox'), + (None, 'begin'), + (None, 'by'), + (None, 'calcMode'), + (None, 'cap-height'), + (None, 'class'), + (None, 'clip-path'), + (None, 'color'), + (None, 'color-rendering'), + (None, 'content'), + (None, 'cx'), + (None, 'cy'), + (None, 'd'), + (None, 'dx'), + (None, 'dy'), + (None, 'descent'), + (None, 'display'), + (None, 'dur'), + (None, 'end'), + (None, 'fill'), + (None, 'fill-opacity'), + (None, 'fill-rule'), + (None, 'font-family'), + (None, 'font-size'), + (None, 'font-stretch'), + (None, 'font-style'), + (None, 'font-variant'), + (None, 'font-weight'), + (None, 'from'), + (None, 'fx'), + (None, 'fy'), + (None, 'g1'), + (None, 'g2'), + (None, 'glyph-name'), + (None, 'gradientUnits'), + (None, 'hanging'), + (None, 'height'), + (None, 'horiz-adv-x'), + (None, 'horiz-origin-x'), + (None, 'id'), + (None, 'ideographic'), + (None, 'k'), + (None, 'keyPoints'), + (None, 'keySplines'), + (None, 'keyTimes'), + (None, 'lang'), + (None, 'marker-end'), + (None, 'marker-mid'), + (None, 'marker-start'), + (None, 'markerHeight'), + (None, 'markerUnits'), + (None, 'markerWidth'), + (None, 'mathematical'), + (None, 'max'), + (None, 'min'), + (None, 'name'), + (None, 'offset'), + (None, 'opacity'), + (None, 'orient'), + (None, 'origin'), + (None, 'overline-position'), + (None, 'overline-thickness'), + (None, 'panose-1'), + (None, 'path'), + (None, 'pathLength'), + (None, 'points'), + (None, 'preserveAspectRatio'), + (None, 'r'), + (None, 'refX'), + (None, 'refY'), + (None, 'repeatCount'), + (None, 'repeatDur'), + (None, 'requiredExtensions'), + (None, 'requiredFeatures'), + (None, 'restart'), + (None, 'rotate'), + (None, 'rx'), + (None, 'ry'), + (None, 'slope'), + (None, 'stemh'), + (None, 'stemv'), + (None, 'stop-color'), + (None, 'stop-opacity'), + (None, 'strikethrough-position'), + (None, 'strikethrough-thickness'), + (None, 'stroke'), + (None, 'stroke-dasharray'), + (None, 'stroke-dashoffset'), + (None, 'stroke-linecap'), + (None, 'stroke-linejoin'), + (None, 'stroke-miterlimit'), + (None, 'stroke-opacity'), + (None, 'stroke-width'), + (None, 'systemLanguage'), + (None, 'target'), + (None, 'text-anchor'), + (None, 'to'), + (None, 'transform'), + (None, 'type'), + (None, 'u1'), + (None, 'u2'), + (None, 'underline-position'), + (None, 'underline-thickness'), + (None, 'unicode'), + (None, 'unicode-range'), + (None, 'units-per-em'), + (None, 'values'), + (None, 'version'), + (None, 'viewBox'), + (None, 'visibility'), + (None, 'width'), + (None, 'widths'), + (None, 'x'), + (None, 'x-height'), + (None, 'x1'), + (None, 'x2'), + (namespaces['xlink'], 'actuate'), + (namespaces['xlink'], 'arcrole'), + (namespaces['xlink'], 'href'), + (namespaces['xlink'], 'role'), + (namespaces['xlink'], 'show'), + (namespaces['xlink'], 'title'), + (namespaces['xlink'], 'type'), + (namespaces['xml'], 'base'), + (namespaces['xml'], 'lang'), + (namespaces['xml'], 'space'), + (None, 'y'), + (None, 'y1'), + (None, 'y2'), + (None, 'zoomAndPan'), +)) + +attr_val_is_uri = frozenset(( + (None, 'href'), + (None, 'src'), + (None, 'cite'), + (None, 'action'), + (None, 'longdesc'), + (None, 'poster'), + (None, 'background'), + (None, 'datasrc'), + (None, 'dynsrc'), + (None, 'lowsrc'), + (None, 'ping'), + (namespaces['xlink'], 'href'), + (namespaces['xml'], 'base'), +)) + +svg_attr_val_allows_ref = frozenset(( + (None, 'clip-path'), + (None, 'color-profile'), + (None, 'cursor'), + (None, 'fill'), + (None, 'filter'), + (None, 'marker'), + (None, 'marker-start'), + (None, 'marker-mid'), + (None, 'marker-end'), + (None, 'mask'), + (None, 'stroke'), +)) + +svg_allow_local_href = frozenset(( + (None, 'altGlyph'), + (None, 'animate'), + (None, 'animateColor'), + (None, 'animateMotion'), + (None, 'animateTransform'), + (None, 'cursor'), + (None, 'feImage'), + (None, 'filter'), + (None, 'linearGradient'), + (None, 'pattern'), + (None, 'radialGradient'), + (None, 'textpath'), + (None, 'tref'), + (None, 'set'), + (None, 'use') +)) + +allowed_css_properties = frozenset(( + 'azimuth', + 'background-color', + 'border-bottom-color', + 'border-collapse', + 'border-color', + 'border-left-color', + 'border-right-color', + 'border-top-color', + 'clear', + 'color', + 'cursor', + 'direction', + 'display', + 'elevation', + 'float', + 'font', + 'font-family', + 'font-size', + 'font-style', + 'font-variant', + 'font-weight', + 'height', + 'letter-spacing', + 'line-height', + 'overflow', + 'pause', + 'pause-after', + 'pause-before', + 'pitch', + 'pitch-range', + 'richness', + 'speak', + 'speak-header', + 'speak-numeral', + 'speak-punctuation', + 'speech-rate', + 'stress', + 'text-align', + 'text-decoration', + 'text-indent', + 'unicode-bidi', + 'vertical-align', + 'voice-family', + 'volume', + 'white-space', + 'width', +)) + +allowed_css_keywords = frozenset(( + 'auto', + 'aqua', + 'black', + 'block', + 'blue', + 'bold', + 'both', + 'bottom', + 'brown', + 'center', + 'collapse', + 'dashed', + 'dotted', + 'fuchsia', + 'gray', + 'green', + '!important', + 'italic', + 'left', + 'lime', + 'maroon', + 'medium', + 'none', + 'navy', + 'normal', + 'nowrap', + 'olive', + 'pointer', + 'purple', + 'red', + 'right', + 'solid', + 'silver', + 'teal', + 'top', + 'transparent', + 'underline', + 'white', + 'yellow', +)) + +allowed_svg_properties = frozenset(( + 'fill', + 'fill-opacity', + 'fill-rule', + 'stroke', + 'stroke-width', + 'stroke-linecap', + 'stroke-linejoin', + 'stroke-opacity', +)) + +allowed_protocols = frozenset(( + 'ed2k', + 'ftp', + 'http', + 'https', + 'irc', + 'mailto', + 'news', + 'gopher', + 'nntp', + 'telnet', + 'webcal', + 'xmpp', + 'callto', + 'feed', + 'urn', + 'aim', + 'rsync', + 'tag', + 'ssh', + 'sftp', + 'rtsp', + 'afs', + 'data', +)) + +allowed_content_types = frozenset(( + 'image/png', + 'image/jpeg', + 'image/gif', + 'image/webp', + 'image/bmp', + 'text/plain', +)) + + +data_content_type = re.compile(r''' + ^ + # Match a content type / + (?P[-a-zA-Z0-9.]+/[-a-zA-Z0-9.]+) + # Match any character set and encoding + (?:(?:;charset=(?:[-a-zA-Z0-9]+)(?:;(?:base64))?) + |(?:;(?:base64))?(?:;charset=(?:[-a-zA-Z0-9]+))?) + # Assume the rest is data + ,.* + $ + ''', + re.VERBOSE) + + +class Filter(base.Filter): + """Sanitizes token stream of XHTML+MathML+SVG and of inline style attributes""" + def __init__(self, + source, + allowed_elements=allowed_elements, + allowed_attributes=allowed_attributes, + allowed_css_properties=allowed_css_properties, + allowed_css_keywords=allowed_css_keywords, + allowed_svg_properties=allowed_svg_properties, + allowed_protocols=allowed_protocols, + allowed_content_types=allowed_content_types, + attr_val_is_uri=attr_val_is_uri, + svg_attr_val_allows_ref=svg_attr_val_allows_ref, + svg_allow_local_href=svg_allow_local_href): + """Creates a Filter + + :arg allowed_elements: set of elements to allow--everything else will + be escaped + + :arg allowed_attributes: set of attributes to allow in + elements--everything else will be stripped + + :arg allowed_css_properties: set of CSS properties to allow--everything + else will be stripped + + :arg allowed_css_keywords: set of CSS keywords to allow--everything + else will be stripped + + :arg allowed_svg_properties: set of SVG properties to allow--everything + else will be removed + + :arg allowed_protocols: set of allowed protocols for URIs + + :arg allowed_content_types: set of allowed content types for ``data`` URIs. + + :arg attr_val_is_uri: set of attributes that have URI values--values + that have a scheme not listed in ``allowed_protocols`` are removed + + :arg svg_attr_val_allows_ref: set of SVG attributes that can have + references + + :arg svg_allow_local_href: set of SVG elements that can have local + hrefs--these are removed + + """ + super(Filter, self).__init__(source) + + warnings.warn(_deprecation_msg, DeprecationWarning) + + self.allowed_elements = allowed_elements + self.allowed_attributes = allowed_attributes + self.allowed_css_properties = allowed_css_properties + self.allowed_css_keywords = allowed_css_keywords + self.allowed_svg_properties = allowed_svg_properties + self.allowed_protocols = allowed_protocols + self.allowed_content_types = allowed_content_types + self.attr_val_is_uri = attr_val_is_uri + self.svg_attr_val_allows_ref = svg_attr_val_allows_ref + self.svg_allow_local_href = svg_allow_local_href + + def __iter__(self): + for token in base.Filter.__iter__(self): + token = self.sanitize_token(token) + if token: + yield token + + # Sanitize the +html+, escaping all elements not in ALLOWED_ELEMENTS, and + # stripping out all attributes not in ALLOWED_ATTRIBUTES. Style attributes + # are parsed, and a restricted set, specified by ALLOWED_CSS_PROPERTIES and + # ALLOWED_CSS_KEYWORDS, are allowed through. attributes in ATTR_VAL_IS_URI + # are scanned, and only URI schemes specified in ALLOWED_PROTOCOLS are + # allowed. + # + # sanitize_html('') + # => <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/venv/Lib/site-packages/pip/_vendor/html5lib/filters/whitespace.py b/venv/Lib/site-packages/pip/_vendor/html5lib/filters/whitespace.py new file mode 100644 index 0000000..0d12584 --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/html5lib/filters/whitespace.py @@ -0,0 +1,38 @@ +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/venv/Lib/site-packages/pip/_vendor/html5lib/html5parser.py b/venv/Lib/site-packages/pip/_vendor/html5lib/html5parser.py new file mode 100644 index 0000000..d06784f --- /dev/null +++ b/venv/Lib/site-packages/pip/_vendor/html5lib/html5parser.py @@ -0,0 +1,2795 @@ +from __future__ import absolute_import, division, unicode_literals +from pip._vendor.six import with_metaclass, viewkeys + +import types + +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('